Skip to content

Commit 96c5784

Browse files
authored
Merge pull request #198 from bramses/agents
Add Agents system with AI Wizard, fix streaming markdown corruption
2 parents d679d4d + 9b0a675 commit 96c5784

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+5562
-1222
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ coverage/
2727
# TypeScript
2828
*.tsbuildinfo
2929

30+
# agents
31+
.claude
32+
3033
# obsidian
3134
data.json
3235

CHANGELOG.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,46 @@
11
# ChatGPT MD Changelog
22

3+
## v3.1.0 - Agents System
4+
5+
### 🤖 Major Features
6+
7+
- **Agents System**: Create reusable AI personas with custom system prompts, models, and temperature settings
8+
- Agent files are Markdown notes with frontmatter (model, temperature, stream) and a body that serves as the system prompt
9+
- Agents live in a configurable folder (default: `ChatGPT_MD/agents`)
10+
- **Choose Agent Command**: Select an agent from your agent folder and apply it to the current note
11+
- Sets the `agent` field in the note's frontmatter
12+
- Agent settings (model, temperature) and system prompt are merged into the chat configuration at runtime
13+
- **Create Agent Command**: Two creation modes:
14+
- **Manual**: Configure name, model (with autocomplete), temperature (slider), and system prompt yourself
15+
- **AI Wizard**: Describe what you want the agent to do, and an AI generates the name, temperature, and a comprehensive system prompt
16+
- The wizard pre-fills the manual form so you can review and edit before saving
17+
18+
### 🏗️ Technical Architecture
19+
20+
- **AgentService**: New service for agent file CRUD and resolution (`getAgentFiles`, `readAgent`, `resolveAgentByName`, `createAgentFile`)
21+
- **Agent Resolution in SettingsService**: When a note has `agent: AgentName` in frontmatter, the agent's frontmatter and body are resolved and merged into the configuration
22+
- **Merge Priority**: `defaultConfig < defaultFrontmatter < settings < agentFrontmatter < noteFrontmatter`
23+
- **System Message Injection**: Agent body is prepended as a system message before `system_commands` entries in ChatHandler
24+
25+
### 🎨 User Interface
26+
27+
- **AgentSuggestModal**: Fuzzy-search modal for picking agents from the configured folder
28+
- **CreateAgentModal**: Multi-step wizard modal with mode selection, AI generation, loading state, and manual form
29+
- **Settings**: New "Agent Folder" setting in the Folders section
30+
31+
### 🔧 Streaming Improvements
32+
33+
- **Line-Boundary Flushing**: StreamingHandler now flushes only up to the last newline to prevent cursor offset race conditions during markdown re-rendering
34+
- **Safety Valve**: MAX_BUFFER_SIZE (10KB) forces flush even without newlines to prevent unbounded buffer growth
35+
- **Force Flush on End**: Remaining partial line is written when streaming completes
36+
37+
### 📦 Under the Hood
38+
39+
- **New Files**: `AgentService.ts`, `AgentHandlers.ts`, `AgentSuggestModal.ts`, `CreateAgentModal.ts`
40+
- **Constants**: `AGENT_FOLDER_TYPE`, `CHOOSE_AGENT_COMMAND_ID`, `CREATE_AGENT_COMMAND_ID`, `AGENT_WIZARD_SYSTEM_PROMPT`
41+
- **ServiceContainer**: AgentService wired with late-binding to SettingsService (same pattern as TemplateService)
42+
- **StreamingHandler Tests**: New test suite for line-boundary flushing behavior
43+
344
## v3.0.0 - Privacy-First AI Tool Calling
445

546
### 🎯 Major Features

CLAUDE.md

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
66

77
ChatGPT MD is an Obsidian plugin that integrates multiple AI providers (OpenAI, OpenRouter, Anthropic, Gemini, Ollama, LM Studio) into Obsidian for seamless chat interactions within markdown notes. Users can have AI conversations directly in their notes, with support for note linking, streaming responses, and per-note configuration via frontmatter.
88

9-
## v3.0.0 - Privacy-First AI Tool Calling
9+
## v3.1.0 - Agents System
10+
11+
- **Agent files**: Markdown files in a configurable agent folder with frontmatter (model, temperature, stream) and a body that becomes the system prompt
12+
- **Choose Agent command**: Select an agent to apply to the current note (sets `agent` frontmatter field)
13+
- **Create Agent command**: Create agents manually or via AI Wizard (AI generates name, temperature, system prompt from a description)
14+
- **Agent resolution**: When a note has `agent: AgentName` in frontmatter, the agent's settings (model, temperature) and body (system message) are merged into the chat configuration
15+
- **Merge priority**: defaultConfig < defaultFrontmatter < settings < agentFrontmatter < noteFrontmatter
1016

11-
Major feature: **Privacy-first AI tool calling** with human-in-the-loop approval:
17+
## v3.0.0 - Privacy-First AI Tool Calling
1218

1319
- **Vault Search**: AI can search your notes (you approve which files to share)
1420
- **File Reading**: AI can request access to specific files (you select which ones)
@@ -25,39 +31,42 @@ Major feature: **Privacy-first AI tool calling** with human-in-the-loop approval
2531
```bash
2632
yarn dev # Development with watch mode
2733
yarn build # Production build with TypeScript checks
34+
yarn build:analyze # Build with bundle analysis
35+
yarn analyze # Analyze bundle size without rebuilding
2836
yarn lint # Check code quality
2937
yarn lint:fix # Auto-fix linting issues
30-
yarn analyze # Bundle size analysis
3138
yarn test # Run tests
3239
yarn test:watch # Run tests in watch mode
3340
yarn test:coverage # Run tests with coverage
3441
```
3542

36-
**Test suite**: This project uses Jest with 104 passing tests covering utility functions.
43+
**Run single test file**: `yarn test path/to/test.test.ts`
44+
45+
**Test suite**: Uses Jest with tests in `src/**/*.test.ts`. Tests cover utility functions and pure functions. Tests are NOT used for services or command handlers (those are tested manually).
3746

3847
## Architecture Overview
3948

40-
The plugin uses **constructor injection** via `ServiceContainer`:
49+
The plugin uses **constructor injection** via a centralized `ServiceContainer`:
4150

4251
- `src/core/ServiceContainer.ts` - DI container with readonly service instances
43-
- `src/Commands/` - Command handlers (extracted from old CommandRegistry)
44-
- `src/Services/AiProviderService.ts` - Unified AI service with adapter pattern
52+
- **Only place** where dependencies are defined via `ServiceContainer.create()`
53+
- All services receive dependencies through constructors (no service locator pattern)
4554

4655
**AI SDK**: Uses Vercel AI SDK (`ai` package) with provider-specific adapters (`@ai-sdk/openai`, `@ai-sdk/anthropic`, `@ai-sdk/google`, `@openrouter/ai-sdk-provider`).
4756

48-
**Message flow**: User command → EditorService extracts messages → MessageService parses AiProviderService calls API → Response streamed to editor
57+
**Message flow**: User invokes chat command → EditorService extracts messages → MessageService parses (splits by `<hr class="__chatgpt_plugin">`, extracts `role::assistant` format, resolves wiki links) → FrontmatterManager merges per-note settings → AiProviderService selects adapter → API call → StreamingHandler streams response → EditorService inserts into editor
4958

5059
## Code Organization
5160

5261
Each directory has its own CLAUDE.md with detailed context:
5362

54-
- `src/core/` - ServiceContainer (DI)
55-
- `src/Commands/` - Obsidian command handlers
63+
- `src/core/` - ServiceContainer (DI), plugin initialization
64+
- `src/Commands/` - Obsidian command handlers (ChatHandler, ModelSelectHandler, AgentHandlers, etc.)
5665
- `src/Services/` - Service implementations + `Adapters/` subdirectory
5766
- `src/Views/` - UI components and modals
5867
- `src/Models/` - TypeScript interfaces
5968
- `src/Types/` - AI service type definitions
60-
- `src/Utilities/` - Pure helper functions
69+
- `src/Utilities/` - Pure helper functions (well-tested)
6170

6271
## Cross-cutting Documentation
6372

@@ -66,8 +75,28 @@ Each directory has its own CLAUDE.md with detailed context:
6675

6776
## Key Design Patterns
6877

69-
1. **Constructor Injection** - Dependencies passed via ServiceContainer
70-
2. **Adapter Pattern** - Provider-specific adapters implement common interface
71-
3. **Frontmatter-driven config** - Per-note settings override globals
72-
4. **Streaming responses** - Real-time AI output via Vercel AI SDK
73-
5. **Link context injection** - Auto-include `[[Wiki Links]]` in prompts
78+
1. **Constructor Injection** - Dependencies passed via ServiceContainer; never instantiate services directly outside `ServiceContainer.create()`
79+
2. **Adapter Pattern** - `AiProviderService` uses provider-specific adapters (OpenAI, Anthropic, Gemini, Ollama, OpenRouter, LM Studio) implementing `ProviderAdapter` interface
80+
3. **Frontmatter-driven config** - Per-note settings override globals; merged at runtime by FrontmatterManager
81+
4. **Streaming responses** - Real-time AI output via Vercel AI SDK with platform-specific handling (desktop Node.js vs mobile Web API)
82+
5. **Link context injection** - Wiki links `[[Note Name]]` are resolved and content injected into prompts
83+
6. **Command Handler Interface** - Commands implement `CommandHandler` with metadata; registered via `CommandRegistrar`
84+
7. **Agent system** - Agent files (markdown with frontmatter + body) override model/temperature and provide system prompts; resolved at runtime via `agent` frontmatter field
85+
86+
## Adding a New AI Provider
87+
88+
1. Create adapter in `src/Services/Adapters/` implementing `ProviderAdapter`
89+
2. Add provider-specific configuration to settings
90+
3. Register adapter in `AiProviderService` (provider selection by model prefix: `ollama@`, `openrouter@`, etc.)
91+
4. Add URL configuration parameter (e.g., `providerUrl`)
92+
93+
## Model Selection
94+
95+
Models are specified with provider prefix:
96+
97+
- OpenAI: `gpt-4o` (no prefix, default)
98+
- Ollama: `ollama@llama3.2`
99+
- OpenRouter: `openrouter@anthropic/claude-3-5-sonnet`
100+
- LM Studio: `lmstudio@model-name`
101+
102+
The prefix determines which adapter handles the request in `AiProviderService`.

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@
44

55
![Chatting with links about vacation plans](images/chat-with-link.gif)
66

7-
## 🚀 What's New in v3.0.0: Privacy-First AI Tool Calling (off by default - Settings → ChatGPT MD → Tool Calling)
7+
## 🚀 What's New
8+
9+
### v3.1.0: Agents System
10+
11+
**Create reusable AI personas with custom system prompts, models, and temperature settings.**
12+
13+
Define agents as Markdown files with frontmatter and a system prompt body. Apply an agent to any note with the `Choose Agent` command, or create new agents with the **AI Wizard**—describe what you want, and AI generates the name, temperature, and a comprehensive system prompt for you.
14+
15+
### v3.0.0: Privacy-First AI Tool Calling (off by default - Settings → ChatGPT MD → Tool Calling)
816

917
**Your AI assistant can now actively search your vault, read files, and query the web—with a human-in-the-loop architecture that keeps you in control.**
1018

11-
v3.0.0 introduces a **tool calling system** built on privacy-first principles. When your AI needs information, it requests permission to use tools—you approve execution, review results, and control exactly what gets shared back to the model. Nothing leaves your vault without explicit consent.
19+
Tool calling built on privacy-first principles. When your AI needs information, it requests permission to use tools—you approve execution, review results, and control exactly what gets shared back to the model. Nothing leaves your vault without explicit consent.
1220

1321

1422
## A simple and quick Start 🏁

0 commit comments

Comments
 (0)