Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,54 @@ bun run watch # Watch mode

---

## AI Chat (Desktop App)

Built-in Claude integration for document analysis and Q&A.

### Commands

Type `/` in the input field to show command menu. Navigate with arrow keys, select with Enter.

| Command | Description |
|---------|-------------|
| `/clear` | Reset conversation history |
| `/summarise` | Generate comprehensive document summary |
| `/model` | Select AI model (opens submenu) |
| `/export` | Export chat as markdown in new tab |

### Command Menu Pattern

Commands are defined in `ai-chat-panel.tsx`:

```typescript
interface Command {
name: string; // Command name (without /)
description: string; // Shown in menu
hasSubmenu?: boolean; // Opens nested selection
action?: () => void; // Direct execution
}
```

**Menu behavior:**
- Shows when input starts with `/`
- Filters as user types more characters
- Arrow keys navigate, Tab autocompletes, Enter executes, Escape closes
- Commands with `hasSubmenu: true` open a nested selection (e.g., model picker)

### Models

Available via `/model` command:

| Short Name | Full Name | API ID |
|------------|-----------|--------|
| haiku-4.5 | Claude Haiku 4.5 | `claude-haiku-4-5` |
| sonnet-4.5 | Claude Sonnet 4.5 | `claude-sonnet-4-5` |
| opus-4.5 | Claude Opus 4.5 | `claude-opus-4-5` |

**State:** Model selection persisted in localStorage (`md-ai-model`).

---

## Versioning

When creating a new version:
Expand Down
13 changes: 11 additions & 2 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/api/go.mod
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
module github.com/dnl-fm/md/packages/api

go 1.24
go 1.26.0

require (
github.com/chromedp/chromedp v0.14.2
github.com/go-chi/chi/v5 v5.1.0
github.com/go-chi/cors v1.2.1
)

require (
github.com/chromedp/cdproto v0.0.0-20250724212937-08a3db8b4327 // indirect
github.com/chromedp/chromedp v0.14.2 // indirect
github.com/chromedp/sysutil v1.1.0 // indirect
github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions packages/api/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs=
github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
11 changes: 8 additions & 3 deletions packages/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,14 @@
</style>
<script>
// Apply saved theme immediately to prevent flash
if (localStorage.getItem('theme') === 'light') {
document.documentElement.classList.add('light');
}
(function() {
var theme = localStorage.getItem('theme');
var isLight = theme === 'light' ||
(theme === 'system' && window.matchMedia('(prefers-color-scheme: light)').matches);
if (isLight) {
document.documentElement.classList.add('light');
}
})();
</script>
</head>
<body>
Expand Down
1 change: 1 addition & 0 deletions packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
},
"license": "MIT",
"dependencies": {
"@anthropic-ai/sdk": "^0.71.2",
"@md/shared": "workspace:*",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-dialog": "^2.4.2",
Expand Down
2,811 changes: 0 additions & 2,811 deletions packages/app/public/vendor/mermaid.min.js

This file was deleted.

29 changes: 29 additions & 0 deletions packages/app/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions packages/app/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ crate-type = ["staticlib", "cdylib", "rlib"]
tauri-build = { version = "2", features = [] }

[dependencies]
tauri = { version = "2", features = [] }
tauri = { version = "2", features = ["devtools"] }
tauri-plugin-opener = "2"
tauri-plugin-dialog = "2"
tauri-plugin-fs = "2"
Expand All @@ -31,4 +31,6 @@ parking_lot = "0.12"
chrono = "0.4"
base64 = "0.22"
tauri-plugin-single-instance = "2.3.6"
reqwest = { version = "0.12", features = ["blocking"] }
reqwest = { version = "0.12", features = ["blocking", "stream", "json"] }
futures = "0.3"
tokio-stream = "0.1"
1 change: 1 addition & 0 deletions packages/app/src-tauri/capabilities/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"windows": ["main"],
"permissions": [
"core:default",
"core:window:default",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find files related to AI chat feature
fd -type f -name "*.ts" -o -name "*.tsx" | xargs grep -l "chat\|claude\|ai" | head -20

Repository: dnl-fm/md

Length of output: 223


🏁 Script executed:

# Search for Tauri window API imports in TypeScript/TSX files
rg -n "@tauri-apps/api/window|getCurrentWindow|appWindow|getAll|create|physicalSize|Monitor" packages/app/src --type ts --type tsx -A 2 -B 2

Repository: dnl-fm/md

Length of output: 80


🏁 Script executed:

# Search for window-related operations in Rust backend
rg -n "WindowBuilder|create_window|show_window|focus_window|resize|Window" packages/app/src-tauri/src --type rust -A 1 -B 1 | head -50

Repository: dnl-fm/md

Length of output: 270


🏁 Script executed:

# Check the actual changes in the PR - list all modified files
git diff --name-only HEAD^ HEAD 2>/dev/null || echo "Git not available, checking file structure"

Repository: dnl-fm/md

Length of output: 95


🏁 Script executed:

# Look for any window-specific code in new or modified files related to streaming/AI
find packages/app/src -type f \( -name "*stream*" -o -name "*chat*" -o -name "*claude*" -o -name "*panel*" \) 2>/dev/null | xargs wc -l 2>/dev/null

Repository: dnl-fm/md

Length of output: 254


🏁 Script executed:

# Search for window API imports and usage
rg "@tauri-apps/api/window|getCurrentWindow|appWindow|createTauriWindow" packages/app/src

Repository: dnl-fm/md

Length of output: 403


🏁 Script executed:

# Check the ai-chat-panel component for window operations
cat -n packages/app/src/components/ai-chat-panel.tsx | head -80

Repository: dnl-fm/md

Length of output: 3240


🏁 Script executed:

# Search for any Tauri command invocations in AI chat files
rg "invoke|tauri|window" packages/app/src/components/ai-chat-panel.tsx -i

Repository: dnl-fm/md

Length of output: 35


🏁 Script executed:

# Check the claude client for Tauri API usage
cat -n packages/app/src/services/claude-client.ts

Repository: dnl-fm/md

Length of output: 6718


🏁 Script executed:

# Search for Tauri imports across the entire src directory
rg "@tauri-apps" packages/app/src

Repository: dnl-fm/md

Length of output: 1010


Remove the unnecessary core:window:default permission.

The AI chat feature does not use any window management APIs. The panel is implemented as a resizable UI component using CSS and state management. The only window API usage in the codebase is in app-store.ts for theme detection, which is unrelated to the new AI chat feature. The new code uses only invoke() for Tauri commands and listen() for event streaming.

🤖 Prompt for AI Agents
In `@packages/app/src-tauri/capabilities/default.json` at line 8, Remove the
unnecessary "core:window:default" permission from the capabilities list in
default.json: locate the entry "core:window:default" and delete it so the AI
chat feature no longer requests window-management permission (leave the rest of
the JSON array intact and ensure valid JSON punctuation after removal).

"opener:default",
"dialog:default",
"fs:default",
Expand Down
Loading