Better RSS Fulltext Content Support
 
Telegram Integration?
 
Flexible Spaces for AI Chat Toolbar
 
Save to Planet from Codex
 
Link between Articles
 
2026-04-05 Session: Add Planet AI Chat with sessions and sparkles button

What was done

  • Added a sparkles button to the main sidebar toolbar that opens a global Planet AI Chat window
  • Parameterized ArticleAIChatView to support both per-article and planet-wide modes
  • Created PlanetAIChatWindowController with NSSplitViewController for session sidebar
  • Refactored ArticleAIChatWindowManager to use NSWindowController + NSToolbar
  • Added AIChatToolbarState for AppKit/SwiftUI toolbar state synchronization
  • Implemented session management with persistence, migration from legacy chat file, and session title auto-naming
  • Fixed chat windows staying open when clicking article links (previously closed unexpectedly)
  • Iterated on window chrome: transparent titlebar, fullSizeContentView, unified compact toolbar style

Key decisions

  • Parameterized existing ArticleAIChatView instead of duplicating 5000+ lines — all tools (search_articles, list_planet_articles, read_article) already work cross-planet
  • Used NSSplitViewController for sessions sidebar rather than SwiftUI tabs — matches the app's existing window controller patterns
  • Planet-wide system prompt emphasizes using search_articles and list_planet_articles to discover content across all planets
  • Session titles auto-generate from first user message (truncated to 40 chars)

Files changed

  • Planet/Views/Articles/ArticleAIChatView.swift — replaced @ObservedObject article with optional articleRef, added planet-wide mode, session ID, toolbar state sync, planet summary context, sending animation
  • Planet/Views/Articles/PlanetAIChatWindowController.swift — new: NSWindowController with NSSplitViewController, NSToolbar, AIChatToolbarState, AIChatProviderToolbarItem
  • Planet/Views/Articles/PlanetAIChatSessionsView.swift — new: session model, PlanetAIChatSessionStore, sidebar/content views, environment key
  • Planet/Views/Articles/ArticleAIChatWindowManager.swift — refactored to use NSWindowController + NSToolbar pattern
  • Planet/Views/Articles/ArticleAIOnDeviceTools.swift — made articleID optional in OnDeviceToolContext and factory
  • Planet/Views/Articles/ChatInputField.swift — added configurable placeholder parameter
  • Planet/Views/Sidebar/PlanetSidebarView.swift — added sparkles toolbar button with AI readiness checks
  • Planet/PlanetAppDelegate.swift — added openPlanetAIChatWindow() and planetAIChatWindowController
  • Planet/Helper/Extensions.swift — added settingsAILastChatSessionID key
 
2026-04-05 Session: Detect Ollama and improve AI settings UX

What was done

  • Added Ollama auto-detection in AI settings — pings localhost:11434/api/tags on view appear
  • Added "Use Ollama" button when Ollama is detected but not yet configured
  • Shows "Using Ollama" status when API base already points to Ollama (localhost, 127.x, LAN IPs on port 11434)
  • Changed HTTP security warning to only display when the URL actually violates the policy (was previously always visible), styled in red

Key decisions

  • Ollama detection covers localhost, 127.x, 0.0.0.0, and LAN IPs (10.x, 100.x, 192.168.x) on port 11434
  • Detection uses a 2-second timeout to avoid blocking the UI
  • HTTP warning changed from always-on informational to conditional error styling

Files changed

  • Planet/Settings/PlanetSettingsAIView.swift — Added ollamaDetected state, checkOllama() function, isUsingOllama and hasInsecureHTTPError computed properties, and conditional UI for Ollama row and HTTP warning
 
2026-04-05 Session: Convert AI chat from sheet to dedicated window per article

What was done

  • Converted AI chat from a modal sheet to a dedicated macOS window per article, allowing multiple chats open simultaneously and free repositioning
  • Created ArticleAIChatWindowManager following the existing AppLogWindowManager pattern, tracking one window per article UUID
  • Added 20px bottom padding to chat messages for visual comfort
  • Auto-focus the input field when the chat window opens, using @FocusState on macOS 13+ with graceful fallback
  • Updated CLAUDE.md with guideline to use #available/@available for newer APIs while maintaining macOS 12 compatibility

Key decisions

  • Used the direct NSWindow + NSHostingView pattern (like AppLogWindowManager) rather than the heavier WindowManager/WindowController/Window/ViewController hierarchy — simplest approach that supports multiple instances
  • Replaced @Environment(\.dismiss) with NSApp.keyWindow?.close() since dismiss doesn't work outside sheet context
  • For auto-focus, extracted a FocusableChatInput struct gated behind @available(macOS 13.0, *) rather than using fragile NSView hierarchy traversal

Files changed

  • Planet/Views/Articles/ArticleAIChatWindowManager.swift — New file: window manager tracking one NSWindow per article UUID
  • Planet/Views/Articles/ArticleView.swift — Removed sheet presentation, toolbar button now opens dedicated window
  • Planet/Views/Articles/ArticleAIChatView.swift — Removed dismiss environment, replaced with window close, flexible frame, bottom padding, focusOnAppear
  • Planet/Views/Articles/ChatInputField.swift — Added focusOnAppear support with @FocusState on macOS 13+
  • Planet.xcodeproj/project.pbxproj — Added new file to Planet target
  • CLAUDE.md — Added #available API adoption guideline
 
Global Chat or Planet-level Chat
 
2026-04-05 Session: Fix 6 Xcode warnings and remove legacy CoreData

What was done

  • Fixed 6 Xcode compiler warnings identified in the build
  • Removed the entire legacy CoreData migration subsystem after confirming it was dead code

Warning fixes

  • FollowingPlanetModel — suppressed unused result from MainActor.run returning a Task value
  • Template (2 warnings) — removed redundant ?? nil on getNextPage/getPreviousPage which already return String?
  • VideoInfoRow — added nonisolated to makeCompressionBackup(for:) since it only does file I/O but was MainActor-isolated and called from a detached task
  • Planet+CoreDataProperties / PlanetArticle+CoreDataProperties — initially fixed by switching codegen to Manual/None, then removed entirely with the CoreData cleanup

CoreData removal

  • Confirmed CoreData was only used by Saver.swift for a one-time migration from old CoreData persistence to current JSON format
  • The migration path: PlanetAppDelegate.applicationDidFinishLaunchingSaver.isMigrationNeeded()savePlanets() / migratePublic()
  • No other code paths referenced CoreData classes

Files changed

  • Planet/Entities/FollowingPlanetModel.swift_ = Task { to suppress unused result
  • Planet/TemplateBrowser/Template.swift — removed ?? nil wrapping
  • Planet/Writer/VideoInfoRow.swift — added nonisolated to static method
  • Planet/PlanetAppDelegate.swift — removed migration block
  • Planet/Entities/PlanetStore.swift — removed isMigrating property
  • Planet/Views/PlanetMainView.swift — removed migration progress sheet
  • Planet.xcodeproj/project.pbxproj — removed all CoreData file references
  • Planet/LegacyCoreData/ — deleted (Planet.swift, PlanetArticle.swift, CoreDataPersistence.swift)
  • Planet/Planet.xcdatamodeld/ — deleted (7 model versions)
  • Planet/Helper/Saver.swift — deleted
  • Planet/Views/Saver/MigrationProgressView.swift — deleted
 
AI Setting: Detect Ollama
 
Guide to Use Ollama + Gemma4 + Planet
 
Pull Remote Template via Git or Download
 
AI Chat Window per Article