Add OpenSpec foudnation
This commit is contained in:
134
openspec/project.md
Normal file
134
openspec/project.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# Project Context
|
||||
|
||||
## Purpose
|
||||
Obsidian plugin that embeds the OpenCode AI assistant via an iframe. The plugin spawns a local OpenCode server process and displays its web UI in the Obsidian sidebar, enabling AI-assisted coding and note-taking within Obsidian.
|
||||
|
||||
## Tech Stack
|
||||
- **TypeScript** - Primary language with strict null checks
|
||||
- **Obsidian Plugin API** - For UI integration, views, settings, and commands
|
||||
- **esbuild** - Bundler (ES2018 target, CommonJS output)
|
||||
- **Node.js child_process** - For spawning the OpenCode server process
|
||||
- **Bun** - Package manager and runtime
|
||||
|
||||
## Project Conventions
|
||||
|
||||
### Code Style
|
||||
|
||||
**Imports:**
|
||||
- ES modules with named imports
|
||||
- Order: Obsidian API → Node.js builtins → local modules
|
||||
- Use `type` keyword for type-only imports
|
||||
- Relative paths with `./` prefix
|
||||
|
||||
```typescript
|
||||
import { Plugin, WorkspaceLeaf, Notice } from "obsidian";
|
||||
import { spawn, ChildProcess } from "child_process";
|
||||
import type OpenCodePlugin from "./main";
|
||||
import { OpenCodeSettings, DEFAULT_SETTINGS } from "./types";
|
||||
```
|
||||
|
||||
**Naming Conventions:**
|
||||
| Type | Convention | Example |
|
||||
|------|------------|---------|
|
||||
| Classes | PascalCase | `OpenCodePlugin`, `ProcessManager` |
|
||||
| Interfaces/Types | PascalCase | `OpenCodeSettings`, `ProcessState` |
|
||||
| Constants | UPPER_CASE or camelCase | `DEFAULT_SETTINGS`, `OPENCODE_VIEW_TYPE` |
|
||||
| Variables/functions | camelCase | `getVaultPath`, `startServer` |
|
||||
| Private members | camelCase (no prefix) | `private processManager` |
|
||||
| Files | PascalCase for classes | `ProcessManager.ts`, `OpenCodeView.ts` |
|
||||
|
||||
**TypeScript Patterns:**
|
||||
- `strictNullChecks` enabled - always handle null/undefined
|
||||
- Union types for state: `"stopped" | "starting" | "running" | "error"`
|
||||
- `async/await` over raw Promises
|
||||
- Explicit return types on public methods
|
||||
|
||||
### Architecture Patterns
|
||||
|
||||
**Project Structure:**
|
||||
```
|
||||
src/
|
||||
├── main.ts # Plugin entry, extends Plugin
|
||||
├── types.ts # Types and constants
|
||||
├── OpenCodeView.ts # Sidebar view (ItemView) with iframe
|
||||
├── ProcessManager.ts # Server process lifecycle
|
||||
├── SettingsTab.ts # Settings UI (PluginSettingTab)
|
||||
└── icons.ts # Custom icon registration
|
||||
```
|
||||
|
||||
**Obsidian Patterns:**
|
||||
- Extend `Plugin` with `onload()`/`onunload()` lifecycle
|
||||
- Extend `ItemView` for views: `getViewType()`, `onOpen()`, `onClose()`
|
||||
- Extend `PluginSettingTab` for settings: `display()`
|
||||
- DOM helpers: `createEl()`, `createDiv()`, `setIcon()`
|
||||
- Register in `onload()`, clean up in `onunload()`
|
||||
|
||||
**State Management:**
|
||||
- Callback-based subscriptions for state changes
|
||||
- Centralized state in manager classes (ProcessManager)
|
||||
- Immediate notification on state change via callbacks
|
||||
|
||||
**Error Handling:**
|
||||
- try/catch for async operations
|
||||
- `console.error()` for debugging
|
||||
- `new Notice()` for user-facing errors
|
||||
- Boolean returns for success/failure
|
||||
- Silent catch for non-critical ops (health checks)
|
||||
|
||||
### Testing Strategy
|
||||
Not currently configured. If adding tests:
|
||||
- Use Vitest for test runner
|
||||
- Place tests in `src/__tests__/` or `*.test.ts` files
|
||||
- Add ESLint with `@typescript-eslint/parser` for linting
|
||||
|
||||
### Git Workflow
|
||||
Standard feature branch workflow. Commit messages should be concise and describe the change.
|
||||
|
||||
## Domain Context
|
||||
|
||||
**OpenCode Server:**
|
||||
- OpenCode is an AI assistant CLI that can run as a web server
|
||||
- The plugin spawns `opencode serve` with port/hostname/CORS flags
|
||||
- Server health is checked via `/global/health` endpoint
|
||||
- Project directory is encoded as base64 in the URL path
|
||||
|
||||
**Obsidian Integration:**
|
||||
- View is registered with `OPENCODE_VIEW_TYPE` constant
|
||||
- Opens in right sidebar by default
|
||||
- Supports lazy start (starts server when view opens)
|
||||
- Auto-start option available in settings
|
||||
|
||||
**Process States:**
|
||||
- `stopped` - Server not running
|
||||
- `starting` - Server spawn initiated, waiting for health check
|
||||
- `running` - Server healthy and responding
|
||||
- `error` - Server failed to start or crashed
|
||||
|
||||
## Important Constraints
|
||||
|
||||
**Desktop Only:**
|
||||
- Uses Node.js APIs (`child_process.spawn()`) unavailable on mobile
|
||||
- File system access via vault adapter requires desktop
|
||||
- Check for desktop environment before adding mobile-incompatible features
|
||||
|
||||
**Build Output:**
|
||||
- Must produce single `main.js` file (CommonJS format)
|
||||
- External: `obsidian`, `electron`, CodeMirror modules, Node.js builtins
|
||||
|
||||
**TypeScript Config:**
|
||||
- Target: ES6
|
||||
- Module: ESNext (bundled to CJS)
|
||||
- Strict null checks enabled
|
||||
- No implicit any
|
||||
|
||||
## External Dependencies
|
||||
|
||||
**Runtime:**
|
||||
- OpenCode CLI must be installed on user's system (configurable path)
|
||||
- Default port: 14096, hostname: 127.0.0.1
|
||||
|
||||
**Development:**
|
||||
- `obsidian` - Obsidian API types and runtime
|
||||
- `@types/node` - Node.js type definitions
|
||||
- `esbuild` - Build bundler
|
||||
- `typescript` - Type checking
|
||||
Reference in New Issue
Block a user