summaryrefslogtreecommitdiffhomepage
path: root/.rules
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-03-29 13:25:18 +0900
committerAdam Malczewski <[email protected]>2026-03-29 13:25:18 +0900
commit90346a91a81c317b90f4ca9a64cbaaf0ade7868b (patch)
tree0be851269904a3ef76f16cff9d384914face8927 /.rules
parentbffeac84cb7b3094f7a4b879b6bab6ceaec561ac (diff)
downloadai-pulse-obsidian-plugin-90346a91a81c317b90f4ca9a64cbaaf0ade7868b.tar.gz
ai-pulse-obsidian-plugin-90346a91a81c317b90f4ca9a64cbaaf0ade7868b.zip
add persistent chat history with cross-device sync
Diffstat (limited to '.rules')
-rw-r--r--.rules/changelog/2026-03/28/10.md15
-rw-r--r--.rules/changelog/2026-03/29/01.md24
2 files changed, 39 insertions, 0 deletions
diff --git a/.rules/changelog/2026-03/28/10.md b/.rules/changelog/2026-03/28/10.md
new file mode 100644
index 0000000..a5f6de0
--- /dev/null
+++ b/.rules/changelog/2026-03/28/10.md
@@ -0,0 +1,15 @@
+# Phase 2: Calendar State
+
+## Added
+- `src/calendar/calendar-state.ts` — observable state container for the calendar view
+
+## Details
+- `CalendarState` class with private fields: `displayedMonth`, `today`, `activeFileDate`, `noteIndex`
+- Read-only getters for all state fields
+- `subscribe(cb)` / unsubscribe pattern using a `Set<() => void>`
+- `setDisplayedMonth(m)` — clones and normalizes to start-of-month
+- `setActiveFile(file, rootFolder)` — delegates to `getDateFromDailyNote()` from Phase 1
+- `reindex(app, rootFolder)` — delegates to `indexDailyNotes()` from Phase 1
+- `tick()` — heartbeat that notifies only on day rollover
+- `rootFolder` passed as parameter (not stored) for consistency across methods
+- No framework dependencies; strict TypeScript, no `any`
diff --git a/.rules/changelog/2026-03/29/01.md b/.rules/changelog/2026-03/29/01.md
new file mode 100644
index 0000000..117efc2
--- /dev/null
+++ b/.rules/changelog/2026-03/29/01.md
@@ -0,0 +1,24 @@
+# Chat History Persistence & Cross-Device Sync
+
+## New File: `src/chat-history.ts`
+- Added `PersistedMessage` and `ChatHistoryData` interfaces for typed storage
+- `loadChatHistory()` — reads from `chat-history.json` in the plugin folder via `vault.adapter`
+- `saveChatHistory()` — writes user/assistant messages to disk (strips system/tool messages)
+- `clearChatHistory()` — writes an empty history file (not deletion) for reliable Obsidian Sync propagation
+- `toPersistableMessages()` / `toRuntimeMessages()` — conversion between runtime `ChatMessage[]` and storage format
+- `isValidChatHistory()` — strict type guard for safe JSON parsing with version check
+
+## Modified: `src/chat-view.ts`
+- On **open**: restores persisted chat history, renders user messages as plain text and assistant messages as markdown (with wiki-link navigation)
+- On **message send**: debounced save (500ms) after user message and after assistant response completes
+- On **close**: flushes pending save and cleans up debounce timer
+- On **clear chat**: writes empty history file and updates sync snapshot
+- Added `reloadChatHistory()` public method for external sync triggers; skips reload if streaming is active to avoid UI disruption
+- Added `saveChatHistoryDebounced()` with snapshot update to prevent false sync reloads from local writes
+
+## Modified: `src/main.ts`
+- Added `onExternalSettingsChange()` — reloads settings and checks for chat history changes when Obsidian Sync updates `data.json`
+- Added `visibilitychange` DOM event listener — checks for synced changes when the app regains focus (covers device switching)
+- Added `checkChatHistorySync()` — snapshot-based change detection that reloads the chat view only when the persisted file differs from the known state
+- Added `updateChatSnapshot()` — called after local saves and restores to prevent false sync triggers
+- Added `buildChatSnapshot()` helper — lightweight string comparison using message count and last message content