Skip to content

Stores

All renderer state lives in Zustand v5 stores in @openconduit/core/src/stores/.

conversationStore

Manages conversations and open tabs.

ts
import { useConversationStore } from '@openconduit/core';
ActionSignatureDescription
addConversation(opts: { providerId, model }) => ConversationCreates and returns a new conversation
updateConversation(id, patch) => voidPartial update a conversation
deleteConversation(id) => voidDeletes a conversation
openTab(id) => voidAdds id to openTabs
closeTab(id) => voidRemoves id from openTabs
StateTypeDescription
conversationsConversation[]All conversations
openTabsstring[]Currently open tab ids

uiStore

UI state — active conversation, panels, modals, notifications.

ts
import { useUiStore } from '@openconduit/core';
ActionSignatureDescription
setActiveConversation(id: string | null) => voidSets the active conversation
setShowSettings(v: boolean) => voidOpens/closes the settings panel
setCommandPaletteOpen(v: boolean) => voidOpens/closes the command palette
addNotification(payload: Omit<AppNotification, 'id' | 'timestamp' | 'read'>) => voidFires an in-app notification
markRead(id: string) => voidMarks a single notification as read
markAllRead() => voidMarks all notifications as read
clearNotifications() => voidClears all notifications

addNotification payload

ts
addNotification({
  title: 'Export complete',
  message: 'Conversation saved to file', // optional
  variant: 'success',                    // 'info' | 'success' | 'warning' | 'error'
  source: 'app',                         // optional, defaults to 'app'
});

Payloads are intentionally serializable (no React nodes) so that future extension callers (#38) can fire them over IPC.

settingsStore

Wraps electron-store settings via IPC.

ts
import { useSettingsStore } from '@openconduit/core';
StateTypeDescription
settingsAppSettings | nullCurrent settings
modelsstring[]Loaded model list
ActionSignatureDescription
saveSettings(patch: Partial<AppSettings>) => voidPersists settings via IPC
loadModels() => voidFetches available models from the active provider

analyticsStore

Tracks token usage and cost per conversation. Persisted to localStorage under openconduit-analytics.

ts
import { useAnalyticsStore } from '@openconduit/core';
StateTypeDescription
recordsUsageRecord[]All usage records, newest first
ActionSignatureDescription
addRecord(params, pricing?) => voidAppends a UsageRecord; computes USD cost if pricing data is available
clearRecords() => voidWipes all records

addRecord params

ts
addRecord(
  {
    conversationId: string;
    providerId: string;
    model: string;
    usage: TokenUsage; // { inputTokens, outputTokens }
  },
  pricing?: ModelPricing, // optional — from provider registry
)

tasksStore

Holds the AI-generated task list for the active conversation. The task list is extracted from <ai-tasks> XML blocks in AI responses by useChat and replaced in full on every update.

ts
import { useTasksStore } from '@openconduit/core';
StateTypeDescription
tasksAiTask[]Current task list
conversationIdstring | nullConversation the tasks belong to
ActionSignatureDescription
setTasks(tasks: AiTask[], conversationId: string) => voidReplace the full task list
clearTasks() => voidClear tasks and conversationId

AiTask

ts
interface AiTask {
  id: string;
  text: string;
  status: 'pending' | 'in-progress' | 'done' | 'cancelled';
}

personasStore

Manages personas (named system-prompt presets). Persisted to localStorage under openconduit-personas. The default persona always exists and cannot be deleted.

ts
import { usePersonasStore } from '@openconduit/core';
StateTypeDescription
personasPersona[]All personas including defaults
ActionSignatureDescription
addPersona(partial: Omit<Persona, 'id' | 'isDefault'>) => PersonaCreates and returns a new persona
updatePersona(id, updates) => voidUpdate name, color, or systemPrompt (blocked on isDefault personas)
deletePersona(id) => voidDelete a non-default persona
duplicatePersona(id) => Persona | nullClone a persona with a new id
importPersonas(personas: Persona[]) => voidBulk-import personas (merges by id)
getPersona(id) => Persona | undefinedLook up a persona by id

Persona

ts
interface Persona {
  id: string;
  name: string;
  systemPrompt: string;
  color: string;   // hex color for the avatar badge
  isDefault: boolean;
}

useSavedFilesStore

Stores files that were saved from conversations (e.g. AI-generated artifacts). Persisted to localStorage under openconduit-files.

Note

The export name is useSavedFilesStore, not useFilesStore.

ts
import { useSavedFilesStore } from '@openconduit/core';
StateTypeDescription
filesSavedFile[]All saved files, newest first
ActionSignatureDescription
saveFile(file: Omit<SavedFile, 'id' | 'savedAt'>) => stringSaves and returns the new file id
renameFile(id, name) => voidRename a file
deleteFile(id) => voidDelete a file

SavedFile

ts
interface SavedFile {
  id: string;
  name: string;
  content: string;
  mimeType: string;
  size: number;
  conversationId?: string;
  savedAt: number;
}

Released under the AGPLv3 License.