Changeset 0.19.1 (#83)
This commit is contained in:
194
docs/DESIGN-0.19.1.md
Normal file
194
docs/DESIGN-0.19.1.md
Normal file
@@ -0,0 +1,194 @@
|
||||
# v0.19.1 — Active Projects, Project System Prompt, Project Detail Panel
|
||||
|
||||
**Status:** Implementation
|
||||
**Depends on:** v0.19.0 Projects/Workspaces
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Three tightly-scoped improvements that make projects genuinely usable
|
||||
for daily workflow rather than just organizational containers:
|
||||
|
||||
1. **Active Project** — one-click project activation so new chats
|
||||
auto-assign without drag-drop.
|
||||
2. **Project System Prompt** — per-project instructions injected into
|
||||
every chat within the project at completion time.
|
||||
3. **Project Detail Panel** — side panel UI for managing a project's
|
||||
system prompt, KB bindings, and notes.
|
||||
|
||||
---
|
||||
|
||||
## 1. Active Project
|
||||
|
||||
### State
|
||||
|
||||
| Location | Key | Type |
|
||||
|----------|-----|------|
|
||||
| `App.activeProjectId` | runtime | `string \| null` |
|
||||
| `localStorage` | `cs-active-project` | `string \| null` |
|
||||
|
||||
### Behavior
|
||||
|
||||
- Click project header's **pin icon** (or "Set as active" in ⋯ menu)
|
||||
to activate.
|
||||
- Active project gets a visual indicator: left accent border + subtle
|
||||
background tint using the project's color.
|
||||
- Creating a new chat (via `sendMessage` when `!App.currentChatId`)
|
||||
auto-calls `addChannelToProject(activeProjectId, newChannelId)` and
|
||||
sets `chat.projectId` client-side.
|
||||
- Only one project can be active at a time. Clicking the pin on an
|
||||
already-active project deactivates it.
|
||||
- Active state persists across page reloads via `localStorage`.
|
||||
- If the active project is deleted, `activeProjectId` is cleared.
|
||||
|
||||
### Files Changed
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `src/js/app.js` | Add `activeProjectId: null` to App, restore from localStorage on init |
|
||||
| `src/js/projects-ui.js` | `setActiveProject(id)`, `clearActiveProject()`, menu items, pin icon |
|
||||
| `src/js/chat.js` | Auto-assign in `sendMessage` after channel creation |
|
||||
| `src/js/ui-core.js` | `.active` class on project group in `renderChatList` |
|
||||
| `src/css/styles.css` | `.project-group.active` styling |
|
||||
|
||||
---
|
||||
|
||||
## 2. Project System Prompt
|
||||
|
||||
### Injection Order
|
||||
|
||||
```
|
||||
1. Admin system prompt (global policy — no opt-out)
|
||||
2. Persona OR channel prompt (role/character definition)
|
||||
3. ▸ PROJECT system prompt (project-specific context) ← NEW
|
||||
4. KB hint (available knowledge bases)
|
||||
5. Memory hint (user facts from v0.18.0)
|
||||
6. Summary / conversation (message history)
|
||||
```
|
||||
|
||||
The project prompt sits between the role definition and the KB hint.
|
||||
This lets a persona define "you are a coding assistant" while the
|
||||
project adds "this project is the React dashboard for client X."
|
||||
|
||||
### Backend Flow (completion.go)
|
||||
|
||||
In `loadConversation`, after the persona/channel system prompt block:
|
||||
|
||||
```go
|
||||
// ── Project system prompt (v0.19.1) ──
|
||||
if h.stores.Projects != nil {
|
||||
projID, _ := h.stores.Projects.GetProjectIDForChannel(ctx, channelID)
|
||||
if projID != "" {
|
||||
proj, err := h.stores.Projects.GetByID(ctx, projID)
|
||||
if err == nil {
|
||||
if sp, ok := proj.Settings["system_prompt"].(string); ok && sp != "" {
|
||||
messages = append(messages, providers.Message{
|
||||
Role: "system",
|
||||
Content: sp,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Storage
|
||||
|
||||
Uses existing `projects.settings` JSONB column. No migration needed.
|
||||
|
||||
```json
|
||||
{
|
||||
"system_prompt": "You are helping build the Chat Switchboard project..."
|
||||
}
|
||||
```
|
||||
|
||||
### Files Changed
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `server/handlers/completion.go` | Inject project system prompt in `loadConversation` |
|
||||
|
||||
---
|
||||
|
||||
## 3. Project Detail Panel
|
||||
|
||||
### Registration
|
||||
|
||||
Follows the same `PanelRegistry.register()` pattern as notes and
|
||||
preview panels. Registered during app init via `_registerProjectPanel()`.
|
||||
|
||||
### Panel Layout
|
||||
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ Project: <name> [✕] │ ← header (editable name)
|
||||
├─────────────────────────────┤
|
||||
│ System Prompt │
|
||||
│ ┌─────────────────────────┐ │
|
||||
│ │ textarea (auto-resize) │ │
|
||||
│ └─────────────────────────┘ │
|
||||
│ [Save] │
|
||||
├─────────────────────────────┤
|
||||
│ Knowledge Bases [+] │
|
||||
│ ┌─────────────────────────┐ │
|
||||
│ │ • KB Alpha [✕] │ │
|
||||
│ │ • KB Beta [✕] │ │
|
||||
│ └─────────────────────────┘ │
|
||||
│ (empty: "No KBs bound") │
|
||||
├─────────────────────────────┤
|
||||
│ Notes │
|
||||
│ ┌─────────────────────────┐ │
|
||||
│ │ • Meeting notes [✕] │ │
|
||||
│ │ • Design spec [✕] │ │
|
||||
│ └─────────────────────────┘ │
|
||||
│ (empty: "No notes") │
|
||||
├─────────────────────────────┤
|
||||
│ Color [●] │
|
||||
│ Archived [ ] │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
### Interactions
|
||||
|
||||
- **System prompt:** Textarea with debounced save (1s) or explicit Save
|
||||
button. Writes to `PUT /projects/:id` with
|
||||
`settings: { system_prompt: "..." }`.
|
||||
- **KB add:** [+] opens a dropdown of available KBs (from
|
||||
`GET /knowledge-bases`), filtered to exclude already-bound ones.
|
||||
Calls `POST /projects/:id/knowledge-bases`.
|
||||
- **KB remove:** [✕] calls `DELETE /projects/:id/knowledge-bases/:kbId`.
|
||||
- **Notes:** Read-only list with [✕] to unbind. Notes are auto-associated
|
||||
from channel creation (v0.19.0).
|
||||
- **Color:** Reuses the invisible color picker pattern from
|
||||
`setProjectColor()`.
|
||||
- **Open trigger:** Click project name in sidebar header, or
|
||||
"Project details" in ⋯ menu.
|
||||
|
||||
### Files Changed
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `src/index.html` | Add `#sidePanelProject` div inside `#sidePanelBody` |
|
||||
| `src/js/projects-ui.js` | `openProjectPanel(id)`, `_registerProjectPanel()`, panel rendering, KB/note management |
|
||||
| `src/js/app.js` | Call `_registerProjectPanel()` in init |
|
||||
| `src/css/styles.css` | `.project-panel-*` styles |
|
||||
|
||||
---
|
||||
|
||||
## Files Summary
|
||||
|
||||
| File | Phase | Type |
|
||||
|------|-------|------|
|
||||
| `server/handlers/completion.go` | 2 | Modified |
|
||||
| `src/js/app.js` | 1,3 | Modified |
|
||||
| `src/js/projects-ui.js` | 1,3 | Modified |
|
||||
| `src/js/chat.js` | 1 | Modified |
|
||||
| `src/js/ui-core.js` | 1 | Modified |
|
||||
| `src/css/styles.css` | 1,3 | Modified |
|
||||
| `src/index.html` | 3 | Modified |
|
||||
| `VERSION` | — | Modified (0.19.0 → 0.19.1) |
|
||||
| `CHANGELOG.md` | — | Modified |
|
||||
|
||||
No new files. No migrations. Backend change is a single injection
|
||||
point in completion.go.
|
||||
Reference in New Issue
Block a user