groove-dev 0.27.139 → 0.27.141
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@groove-dev/cli/package.json +1 -1
- package/node_modules/@groove-dev/daemon/integrations-registry.json +12 -44
- package/node_modules/@groove-dev/daemon/package.json +1 -1
- package/node_modules/@groove-dev/daemon/src/api.js +225 -16
- package/node_modules/@groove-dev/daemon/src/index.js +2 -0
- package/node_modules/@groove-dev/daemon/src/integrations.js +10 -0
- package/node_modules/@groove-dev/daemon/src/introducer.js +17 -1
- package/node_modules/@groove-dev/daemon/src/journalist.js +169 -0
- package/node_modules/@groove-dev/daemon/src/keeper.js +277 -0
- package/node_modules/@groove-dev/daemon/src/model-lab.js +11 -0
- package/node_modules/@groove-dev/daemon/src/process.js +76 -0
- package/node_modules/@groove-dev/daemon/src/validate.js +9 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-A4e1gIDh.css +1 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-P1hsM27-.js +8696 -0
- package/node_modules/@groove-dev/gui/dist/index.html +2 -2
- package/node_modules/@groove-dev/gui/package.json +1 -1
- package/node_modules/@groove-dev/gui/src/app.jsx +4 -0
- package/node_modules/@groove-dev/gui/src/components/agents/agent-chat.jsx +41 -17
- package/node_modules/@groove-dev/gui/src/components/agents/agent-file-tree.jsx +10 -3
- package/node_modules/@groove-dev/gui/src/components/agents/code-review.jsx +5 -4
- package/node_modules/@groove-dev/gui/src/components/agents/workspace-mode.jsx +160 -12
- package/node_modules/@groove-dev/gui/src/components/editor/ai-panel.jsx +77 -6
- package/node_modules/@groove-dev/gui/src/components/editor/file-tree.jsx +2 -86
- package/node_modules/@groove-dev/gui/src/components/editor/terminal.jsx +15 -4
- package/node_modules/@groove-dev/gui/src/components/keeper/global-modals.jsx +177 -0
- package/node_modules/@groove-dev/gui/src/components/layout/activity-bar.jsx +11 -6
- package/node_modules/@groove-dev/gui/src/components/layout/terminal-panel.jsx +152 -3
- package/node_modules/@groove-dev/gui/src/components/marketplace/integration-wizard.jsx +223 -18
- package/node_modules/@groove-dev/gui/src/stores/groove.js +302 -20
- package/node_modules/@groove-dev/gui/src/views/agents.jsx +118 -60
- package/node_modules/@groove-dev/gui/src/views/editor.jsx +67 -219
- package/node_modules/@groove-dev/gui/src/views/memory.jsx +460 -0
- package/node_modules/@groove-dev/gui/src/views/model-lab.jsx +1 -6
- package/node_modules/@groove-dev/gui/src/views/models.jsx +658 -565
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/daemon/integrations-registry.json +12 -44
- package/packages/daemon/package.json +1 -1
- package/packages/daemon/src/api.js +225 -16
- package/packages/daemon/src/index.js +2 -0
- package/packages/daemon/src/integrations.js +10 -0
- package/packages/daemon/src/introducer.js +17 -1
- package/packages/daemon/src/journalist.js +169 -0
- package/packages/daemon/src/keeper.js +277 -0
- package/packages/daemon/src/model-lab.js +11 -0
- package/packages/daemon/src/process.js +76 -0
- package/packages/daemon/src/validate.js +9 -0
- package/packages/gui/dist/assets/index-A4e1gIDh.css +1 -0
- package/packages/gui/dist/assets/index-P1hsM27-.js +8696 -0
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -1
- package/packages/gui/src/app.jsx +4 -0
- package/packages/gui/src/components/agents/agent-chat.jsx +41 -17
- package/packages/gui/src/components/agents/agent-file-tree.jsx +10 -3
- package/packages/gui/src/components/agents/code-review.jsx +5 -4
- package/packages/gui/src/components/agents/workspace-mode.jsx +160 -12
- package/packages/gui/src/components/editor/ai-panel.jsx +77 -6
- package/packages/gui/src/components/editor/file-tree.jsx +2 -86
- package/packages/gui/src/components/editor/terminal.jsx +15 -4
- package/packages/gui/src/components/keeper/global-modals.jsx +177 -0
- package/packages/gui/src/components/layout/activity-bar.jsx +11 -6
- package/packages/gui/src/components/layout/terminal-panel.jsx +152 -3
- package/packages/gui/src/components/marketplace/integration-wizard.jsx +223 -18
- package/packages/gui/src/stores/groove.js +302 -20
- package/packages/gui/src/views/agents.jsx +118 -60
- package/packages/gui/src/views/editor.jsx +67 -219
- package/packages/gui/src/views/memory.jsx +460 -0
- package/packages/gui/src/views/model-lab.jsx +1 -6
- package/packages/gui/src/views/models.jsx +658 -565
- package/plan_files/keeper-manual.md +295 -0
- package/plan_files/keeper-memory-system.md +223 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-AkOtskHS.css +0 -1
- package/node_modules/@groove-dev/gui/dist/assets/index-B4uYLR57.js +0 -8694
- package/packages/gui/dist/assets/index-AkOtskHS.css +0 -1
- package/packages/gui/dist/assets/index-B4uYLR57.js +0 -8694
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# Keeper — Instruction Manual
|
|
2
|
+
|
|
3
|
+
## What It Is
|
|
4
|
+
|
|
5
|
+
Keeper is your personal tagged notebook inside GROOVE. Save ideas, context, and decisions from agent conversations and pull them into new sessions with a single command. No AI decides what's important — you control every word.
|
|
6
|
+
|
|
7
|
+
Two types of content:
|
|
8
|
+
- **Manual** — you write it via `[save]`, `[append]`, `[update]`
|
|
9
|
+
- **Doc** — AI writes it via `[doc]`, synthesizing your conversation into a structured document
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
All commands work in any agent chat. Brackets are optional — `save #tag` and `[save] #tag` both work. The command and tag are stripped out; your message still gets sent to the agent.
|
|
16
|
+
|
|
17
|
+
### Saving
|
|
18
|
+
|
|
19
|
+
**`save #tag`** — Save the message content under a tag and send the message to the agent. Creates or overwrites.
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
the sky is blue save #thought
|
|
23
|
+
→ Saves "the sky is blue" to #thought
|
|
24
|
+
→ Agent receives "the sky is blue" and responds normally
|
|
25
|
+
|
|
26
|
+
we're going with REST over GraphQL because of team familiarity save #design-decision
|
|
27
|
+
→ Saves to #design-decision AND the agent gets your message
|
|
28
|
+
|
|
29
|
+
this routing approach works well for our use case save #groove/routing
|
|
30
|
+
→ Saves to #groove/routing (nested under groove)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The command can appear anywhere in your message. Everything except the command word and `#tag` becomes the saved content, and the agent gets it too.
|
|
34
|
+
|
|
35
|
+
**`append #tag`** — Add content to an existing memory with a `---` separator. Also sends to the agent. Same syntax as save.
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
actually we should also consider WebSockets append #design-decision
|
|
39
|
+
→ Adds "actually we should also consider WebSockets" to the bottom of #design-decision
|
|
40
|
+
→ Agent receives the message too
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
If the tag doesn't exist yet, `append` creates it (same as `save`).
|
|
44
|
+
|
|
45
|
+
### Editing
|
|
46
|
+
|
|
47
|
+
**`update #tag`** — Opens the editor modal with the current content for in-place editing. Full textarea, Cmd+S to save.
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
update #design-decision
|
|
51
|
+
→ Opens editor with the current content of #design-decision
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
If the tag doesn't exist, opens a blank editor to create it. This command is intercepted — not sent to the agent.
|
|
55
|
+
|
|
56
|
+
### Viewing
|
|
57
|
+
|
|
58
|
+
**`view #tag`** — Opens a read-only modal to review content without risk of editing.
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
view #design-decision
|
|
62
|
+
→ Opens read-only viewer showing the full content
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Intercepted — not sent to the agent.
|
|
66
|
+
|
|
67
|
+
### Reading
|
|
68
|
+
|
|
69
|
+
**`read #tag1 #tag2 ...`** — Sends the memory content to the agent behind the scenes. The agent reads it alongside whatever else you type, but the raw content doesn't flood your chat. You just see a confirmation.
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
read #memory-system
|
|
73
|
+
→ "Sent #memory-system to agent"
|
|
74
|
+
→ Agent has the full content and can work with it
|
|
75
|
+
|
|
76
|
+
read #design-decision #groove/routing
|
|
77
|
+
→ Agent receives both memories
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Reading a parent tag pulls all children automatically. `read #groove` sends `#groove/routing`, `#groove/memory-system`, and anything else under `#groove`.
|
|
81
|
+
|
|
82
|
+
Intercepted — not sent to the agent as your message (the content goes as context).
|
|
83
|
+
|
|
84
|
+
### AI Doc Generation
|
|
85
|
+
|
|
86
|
+
**`doc #tag`** — AI reads the full chat history of the current agent conversation and generates a comprehensive document. The result opens in the editor for your review and editing.
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
doc #memory-system
|
|
90
|
+
→ AI synthesizes the conversation into a structured doc
|
|
91
|
+
→ Opens in editor so you can review/edit before it's final
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The generated doc includes:
|
|
95
|
+
- Core idea and motivation
|
|
96
|
+
- Key decisions from the discussion
|
|
97
|
+
- Architecture / design choices
|
|
98
|
+
- Implementation plan (if discussed)
|
|
99
|
+
- Open questions / next steps
|
|
100
|
+
|
|
101
|
+
If the journalist headless mode isn't available (no API key), falls back to a raw transcript.
|
|
102
|
+
|
|
103
|
+
### Linking
|
|
104
|
+
|
|
105
|
+
**`link #tag path/to/doc`** — Links a memory tag to a NORTHSTAR or external document for cross-referencing.
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
link #design-decision plan_files/NORTHSTAR.md
|
|
109
|
+
→ Links #design-decision to the NORTHSTAR doc
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Links show up as badges on memory cards in the Memory view.
|
|
113
|
+
|
|
114
|
+
### Help
|
|
115
|
+
|
|
116
|
+
**`[instruct]`** — Opens the command reference modal with all commands, tag hierarchy guide, and memory types. (This one needs brackets since it has no `#tag` to disambiguate.)
|
|
117
|
+
|
|
118
|
+
### Deleting
|
|
119
|
+
|
|
120
|
+
**`delete #tag`** — Permanently removes a memory.
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
delete #old-idea
|
|
124
|
+
→ Gone
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Tag Hierarchy
|
|
130
|
+
|
|
131
|
+
Tags use `/` for namespacing. This creates a folder structure:
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
#groove → top-level
|
|
135
|
+
#groove/routing → child of groove
|
|
136
|
+
#groove/memory-system → child of groove
|
|
137
|
+
#design/frontend → child of design
|
|
138
|
+
#design/backend → child of design
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
When you `[pull] #groove`, you get all children too — `#groove/routing` and `#groove/memory-system` are included automatically.
|
|
142
|
+
|
|
143
|
+
In the Memory view, tree mode shows this as collapsible folders.
|
|
144
|
+
|
|
145
|
+
### Tag Rules
|
|
146
|
+
- Lowercase only (auto-converted)
|
|
147
|
+
- Letters, numbers, `/`, `-`, `_` allowed
|
|
148
|
+
- No spaces, no special characters
|
|
149
|
+
- Max 20 tags per agent when spawning with `keeperTags`
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Memory View
|
|
154
|
+
|
|
155
|
+
Access from the activity bar (BookOpen icon, between Dashboard and Teams).
|
|
156
|
+
|
|
157
|
+
### List View
|
|
158
|
+
- Cards with content preview (first 3 lines)
|
|
159
|
+
- Relative timestamps ("5m ago", "2d ago")
|
|
160
|
+
- Size indicator
|
|
161
|
+
- Type badge: purple "AI" sparkle for doc-generated memories
|
|
162
|
+
- Link count badges
|
|
163
|
+
- Hover to reveal edit/delete buttons
|
|
164
|
+
|
|
165
|
+
### Tree View
|
|
166
|
+
- Collapsible folder hierarchy following tag namespacing
|
|
167
|
+
- Click a tag to open the editor
|
|
168
|
+
- Virtual folders appear for parent paths that don't have their own content
|
|
169
|
+
|
|
170
|
+
### Search
|
|
171
|
+
- Filters by tag name in real-time
|
|
172
|
+
|
|
173
|
+
### New Button
|
|
174
|
+
- Opens editor modal with tag input + content textarea
|
|
175
|
+
- Tag input auto-sanitizes (lowercase, valid chars only)
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Syntax Highlighting
|
|
180
|
+
|
|
181
|
+
In agent chat, Keeper syntax highlights in real-time:
|
|
182
|
+
- `[save]`, `[pull]`, etc. — teal accent pills
|
|
183
|
+
- `#tag-name` — accent-colored text
|
|
184
|
+
|
|
185
|
+
This works in both sent messages and the input textarea (via a transparent overlay).
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Spawning Agents with Context
|
|
190
|
+
|
|
191
|
+
When spawning a new agent, you can pre-load memories via `keeperTags` in the agent config:
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
{
|
|
195
|
+
"role": "frontend",
|
|
196
|
+
"keeperTags": ["design-decision", "groove/routing"]
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
The introducer pulls those memories and injects them as a "Keeper Context" section in the agent's intro prompt. Budget: 5KB max.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## How It Works Under the Hood
|
|
205
|
+
|
|
206
|
+
### Storage
|
|
207
|
+
```
|
|
208
|
+
.groove/keeper/
|
|
209
|
+
├── index.json — tag metadata (type, links, timestamps, size)
|
|
210
|
+
├── thought.md — flat tag: #thought
|
|
211
|
+
├── design-decision.md — flat tag: #design-decision
|
|
212
|
+
└── groove/
|
|
213
|
+
├── routing.md — nested: #groove/routing
|
|
214
|
+
└── memory-system.md — nested: #groove/memory-system
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Each tag = one `.md` file. `index.json` stores metadata only.
|
|
218
|
+
|
|
219
|
+
### API Endpoints
|
|
220
|
+
|
|
221
|
+
14 endpoints under `/api/keeper/`:
|
|
222
|
+
|
|
223
|
+
| Method | Path | What It Does |
|
|
224
|
+
|--------|------|--------------|
|
|
225
|
+
| GET | `/api/keeper` | List all memories (metadata only) |
|
|
226
|
+
| GET | `/api/keeper/tree` | Hierarchical tree structure |
|
|
227
|
+
| GET | `/api/keeper/search?q=` | Search tags and content |
|
|
228
|
+
| GET | `/api/keeper/commands` | Command reference data |
|
|
229
|
+
| GET | `/api/keeper/:tag` | Read single memory with content |
|
|
230
|
+
| POST | `/api/keeper` | Save `{ tag, content }` |
|
|
231
|
+
| POST | `/api/keeper/append` | Append `{ tag, content }` |
|
|
232
|
+
| POST | `/api/keeper/pull` | Assemble brief from `{ tags: [...] }` |
|
|
233
|
+
| POST | `/api/keeper/doc` | AI synthesis from `{ tag, chatHistory, agentId }` |
|
|
234
|
+
| POST | `/api/keeper/link` | Link `{ tag, docPath }` |
|
|
235
|
+
| POST | `/api/keeper/parse` | Parse command text |
|
|
236
|
+
| PATCH | `/api/keeper/:tag` | Update content |
|
|
237
|
+
| DELETE | `/api/keeper/link/:tag` | Unlink a document |
|
|
238
|
+
| DELETE | `/api/keeper/:tag` | Delete memory |
|
|
239
|
+
|
|
240
|
+
### Real-Time Sync
|
|
241
|
+
|
|
242
|
+
All mutations broadcast via WebSocket (`keeper:saved`, `keeper:updated`, `keeper:deleted`). Multiple browser tabs stay in sync.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Testing Checklist
|
|
247
|
+
|
|
248
|
+
### Basic Flow
|
|
249
|
+
- [ ] Type `hello world save #test` in agent chat → saves "hello world", agent also receives "hello world"
|
|
250
|
+
- [ ] Type `the sky is blue save #test2` → saves "the sky is blue" to #test2, agent gets the message
|
|
251
|
+
- [ ] `save` and `#test` highlight teal as you type in the input
|
|
252
|
+
- [ ] Navigate to Memory view → both #test and #test2 appear
|
|
253
|
+
- [ ] Click edit icon on #test → editor opens with "hello world"
|
|
254
|
+
- [ ] Modify content, Cmd+S → saves, card updates
|
|
255
|
+
|
|
256
|
+
### All Commands (brackets optional)
|
|
257
|
+
- [ ] `more thoughts append #test` → adds with separator, agent gets "more thoughts"
|
|
258
|
+
- [ ] `update #test` → opens editor modal (intercepted, not sent to agent)
|
|
259
|
+
- [ ] `view #test` → opens read-only modal (intercepted)
|
|
260
|
+
- [ ] `read #test` → "Sent #test to agent", agent receives content, chat stays clean
|
|
261
|
+
- [ ] `doc #test` → "Generating doc..." message, editor opens with result
|
|
262
|
+
- [ ] `link #test plan_files/keeper-manual.md` → links successfully
|
|
263
|
+
- [ ] `[instruct]` → command reference modal opens (brackets required for this one)
|
|
264
|
+
- [ ] `delete #test` → memory removed
|
|
265
|
+
|
|
266
|
+
### Brackets Still Work
|
|
267
|
+
- [ ] `[save] #test hello` → same behavior as `hello save #test`
|
|
268
|
+
- [ ] `[update] #test` → same as `update #test`
|
|
269
|
+
|
|
270
|
+
### Hierarchy
|
|
271
|
+
- [ ] `[save] #project/frontend layout decisions here` → creates nested tag
|
|
272
|
+
- [ ] `[save] #project/backend api design here` → second child
|
|
273
|
+
- [ ] Memory view tree mode shows "project" folder with both children
|
|
274
|
+
- [ ] `[pull] #project` → injects both children
|
|
275
|
+
|
|
276
|
+
### Edge Cases
|
|
277
|
+
- [ ] `save #tag` with no content → shows usage hint
|
|
278
|
+
- [ ] `save` with no tag → not intercepted (no `#tag` to match), sent to agent normally
|
|
279
|
+
- [ ] `view #nonexistent` → "not found" message
|
|
280
|
+
- [ ] `read #nonexistent` → "no memories found" message
|
|
281
|
+
- [ ] Very long content (5KB+) → saves and displays correctly
|
|
282
|
+
|
|
283
|
+
### Memory View
|
|
284
|
+
- [ ] Empty state shows onboarding text + "Create first memory" button
|
|
285
|
+
- [ ] List/Tree toggle works
|
|
286
|
+
- [ ] Search filters by tag name
|
|
287
|
+
- [ ] "New" button opens editor with tag input
|
|
288
|
+
- [ ] Delete from card hover button works
|
|
289
|
+
- [ ] Instruct button (?) opens command reference
|
|
290
|
+
|
|
291
|
+
### Cross-View
|
|
292
|
+
- [ ] Save from agent chat → Memory view updates
|
|
293
|
+
- [ ] Edit in Memory view → reflected when pulled in chat
|
|
294
|
+
- [ ] Global modals work from non-memory views (agents view, dashboard, etc.)
|
|
295
|
+
- [ ] Global modals don't duplicate when ON memory view
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# Keeper — Tagged Memory System
|
|
2
|
+
|
|
3
|
+
## What This Is
|
|
4
|
+
|
|
5
|
+
Keeper is a lightweight tagged memory system for GROOVE that gives users direct, explicit control over saving and retrieving context across agent sessions. It solves the problem of context loss when spawning new agents — instead of manually pointing each agent to scattered docs, users tag ideas inline and pull them into new sessions with a single command.
|
|
6
|
+
|
|
7
|
+
## Why We're Building It
|
|
8
|
+
|
|
9
|
+
When working with multiple agents across sessions, the user repeatedly has to explain the same context: "read NORTHSTAR.md, read this doc, read that doc." This is inefficient for both the user and the agent. The user also loses nuanced ideas — the small decisions, adjustments, and explorations that happen during conversations but never make it into formal docs.
|
|
10
|
+
|
|
11
|
+
Keeper is the user's personal notebook. Not an AI brain that decides what's important — a notebook where the user controls every word. Two types of content:
|
|
12
|
+
|
|
13
|
+
1. **Manual memories** — the user writes exactly what they want saved. No synthesis, no interpretation. "Write that down."
|
|
14
|
+
2. **Doc memories** — for longer explorations, AI reads the full conversation and generates a comprehensive document. The user still reviews and edits.
|
|
15
|
+
|
|
16
|
+
This complements NORTHSTAR (formal strategy docs) rather than replacing it. NORTHSTAR is the plan. Keeper is the working notes, ideas, and context that feed into the plan.
|
|
17
|
+
|
|
18
|
+
## Design Principles
|
|
19
|
+
|
|
20
|
+
- **One tag = one document.** No versioning, no stacking, no timestamps cluttering things up. `#memory-system` is a single block of text.
|
|
21
|
+
- **User owns every word.** `[save]` creates it, `[update]` lets you edit it, `[append]` adds to the bottom. Nothing goes in that the user didn't approve.
|
|
22
|
+
- **Hierarchy is just namespacing.** `#groove/memory-system` and `#groove/routing` live under `#groove`. Not a graph database — just folders.
|
|
23
|
+
- **The modal is the source of truth.** Every mutation goes through an editor modal or explicit chat command. No background magic.
|
|
24
|
+
- **Sidecar pattern.** Commands are intercepted before they reach the agent. The agent never sees `[save]` or `[pull]` — Keeper handles it silently.
|
|
25
|
+
|
|
26
|
+
## Command Grammar
|
|
27
|
+
|
|
28
|
+
All commands are typed in agent chat. Keeper intercepts them before the agent sees the message.
|
|
29
|
+
|
|
30
|
+
| Command | Syntax | Behavior |
|
|
31
|
+
|---------|--------|----------|
|
|
32
|
+
| `[save]` | `[save] #tag content...` | Save the message content under the tag. Creates or overwrites. |
|
|
33
|
+
| `[append]` | `[append] #tag content...` | Add content to an existing memory with a `---` separator. |
|
|
34
|
+
| `[update]` | `[update] #tag` | Opens editor modal with current content for in-place editing. |
|
|
35
|
+
| `[delete]` | `[delete] #tag` | Permanently removes the memory. |
|
|
36
|
+
| `[view]` | `[view] #tag` | Opens read-only modal to review content. |
|
|
37
|
+
| `[pull]` | `[pull] #tag1 #tag2 ...` | Injects memory content into the active agent's context as an instruction. |
|
|
38
|
+
| `[read]` | `[read] #tag` | Alias for `[pull]`. |
|
|
39
|
+
| `[doc]` | `[doc] #tag` | AI reads the full chat history and generates a comprehensive document. Opens result in editor for review. |
|
|
40
|
+
| `[link]` | `[link] #tag path/to/doc` | Links a memory tag to a NORTHSTAR or external document for cross-referencing. |
|
|
41
|
+
| `[instruct]` | `[instruct]` | Opens the command reference modal. |
|
|
42
|
+
|
|
43
|
+
## Architecture
|
|
44
|
+
|
|
45
|
+
### Storage
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
.groove/keeper/
|
|
49
|
+
├── index.json — tag metadata (type, links, timestamps, size)
|
|
50
|
+
├── memory-system.md — flat tag
|
|
51
|
+
├── groove/
|
|
52
|
+
│ ├── routing.md — nested: groove/routing
|
|
53
|
+
│ └── memory-system.md — nested: groove/memory-system
|
|
54
|
+
└── northstar.md
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- Each tag is a single `.md` file. The filename mirrors the tag path.
|
|
58
|
+
- `index.json` stores metadata only — the content lives in the `.md` files.
|
|
59
|
+
- Hierarchy is filesystem directories. `#groove/routing` → `groove/routing.md`.
|
|
60
|
+
|
|
61
|
+
### Daemon Module: `keeper.js`
|
|
62
|
+
|
|
63
|
+
**Location:** `packages/daemon/src/keeper.js`
|
|
64
|
+
|
|
65
|
+
The `Keeper` class handles all file I/O and tag management:
|
|
66
|
+
|
|
67
|
+
- **Constructor** — creates `.groove/keeper/` directory, loads `index.json`
|
|
68
|
+
- **CRUD** — `save()`, `append()`, `update()`, `get()`, `delete()`
|
|
69
|
+
- **Doc** — `saveDoc()` stores content with `type: 'doc'` metadata
|
|
70
|
+
- **Links** — `link()` / `unlink()` associate tags with external doc paths
|
|
71
|
+
- **Query** — `list()`, `tree()`, `children()`, `search()`
|
|
72
|
+
- **Parser** — static `parseCommand(text)` extracts command + tags from chat input
|
|
73
|
+
|
|
74
|
+
Exports `KEEPER_COMMANDS` — a reference object of all 10 commands with syntax and descriptions.
|
|
75
|
+
|
|
76
|
+
### Daemon Wiring
|
|
77
|
+
|
|
78
|
+
**`index.js`** — `this.keeper = new Keeper(this.grooveDir)` instantiated alongside other modules.
|
|
79
|
+
|
|
80
|
+
**`api.js`** — 14 REST endpoints under `/api/keeper/`:
|
|
81
|
+
|
|
82
|
+
| Method | Path | Purpose |
|
|
83
|
+
|--------|------|---------|
|
|
84
|
+
| GET | `/api/keeper` | List all memories |
|
|
85
|
+
| GET | `/api/keeper/tree` | Hierarchical tree structure |
|
|
86
|
+
| GET | `/api/keeper/search?q=` | Search tags and content |
|
|
87
|
+
| GET | `/api/keeper/commands` | Command reference data |
|
|
88
|
+
| GET | `/api/keeper/:tag(*)` | Read single memory (wildcard for nested tags) |
|
|
89
|
+
| POST | `/api/keeper` | Save `{ tag, content }` |
|
|
90
|
+
| POST | `/api/keeper/append` | Append `{ tag, content }` |
|
|
91
|
+
| POST | `/api/keeper/pull` | Assemble brief from `{ tags: [...] }` |
|
|
92
|
+
| POST | `/api/keeper/doc` | AI synthesis — sends chat history to journalist.callHeadless |
|
|
93
|
+
| POST | `/api/keeper/link` | Link `{ tag, docPath }` |
|
|
94
|
+
| POST | `/api/keeper/parse` | Parse command text |
|
|
95
|
+
| PATCH | `/api/keeper/:tag(*)` | Update content |
|
|
96
|
+
| DELETE | `/api/keeper/:tag(*)` | Delete memory |
|
|
97
|
+
| DELETE | `/api/keeper/link/:tag(*)` | Unlink document |
|
|
98
|
+
|
|
99
|
+
All mutations call `daemon.audit.log()` and `daemon.broadcast()` for real-time sync.
|
|
100
|
+
|
|
101
|
+
**Route order matters:** Static paths (`/tree`, `/search`, `/commands`) are registered before the wildcard `/:tag(*)` so Express matches them first.
|
|
102
|
+
|
|
103
|
+
### Context Injection on Spawn
|
|
104
|
+
|
|
105
|
+
**`introducer.js`** — After the existing Layer 7 memory injection, a new "Keeper Context" section is appended if the agent config includes `keeperTags`:
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
if (this.daemon.keeper && newAgent.keeperTags?.length > 0) {
|
|
109
|
+
const brief = this.daemon.keeper.pull(newAgent.keeperTags);
|
|
110
|
+
// Injected as "## Keeper Context (user-tagged memories)" section
|
|
111
|
+
// Hard budget: 5KB
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**`validate.js`** — `keeperTags` added to the validated agent config output. Array of strings, max 20 tags, sanitized.
|
|
116
|
+
|
|
117
|
+
### GUI: Chat Command Interception
|
|
118
|
+
|
|
119
|
+
**`stores/groove.js`** — `instructAgent()` checks every message for bracket commands before sending to the daemon:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
User types: [save] #memory-system This is my idea
|
|
123
|
+
→ Keeper intercepts, saves to .groove/keeper/memory-system.md
|
|
124
|
+
→ System message: "Saved to #memory-system"
|
|
125
|
+
→ Agent never sees the message
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The `_handleKeeperCommand()` method handles all 10 commands:
|
|
129
|
+
- `[save]`, `[append]`, `[delete]` — immediate API call + confirmation
|
|
130
|
+
- `[update]`, `[view]` — opens editor modal via `keeperEditing` store state
|
|
131
|
+
- `[pull]`, `[read]` — fetches brief from API, sends as agent instruction
|
|
132
|
+
- `[doc]` — sends chat history to `/api/keeper/doc`, opens result in editor
|
|
133
|
+
- `[link]` — parses tag + path, calls link API
|
|
134
|
+
- `[instruct]` — sets `keeperInstructOpen: true`
|
|
135
|
+
|
|
136
|
+
### GUI: Syntax Highlighting
|
|
137
|
+
|
|
138
|
+
**`agent-chat.jsx`** — `highlightKeeper()` function splits text on bracket commands and hashtags:
|
|
139
|
+
|
|
140
|
+
- `[save]`, `[pull]`, etc. render as teal accent pills (`bg-accent/15 text-accent font-mono`)
|
|
141
|
+
- `#tag-name` renders in accent color (`text-accent font-medium`)
|
|
142
|
+
- Applied in `FormattedText` (message display) and as a transparent overlay on the textarea input
|
|
143
|
+
|
|
144
|
+
**Input overlay approach:** When the input contains keeper syntax, the textarea text becomes transparent (`text-transparent caret-text-0`) while a mirrored overlay div renders the highlighted version. This lets the cursor and selection work normally while commands light up in real-time.
|
|
145
|
+
|
|
146
|
+
### GUI: Memory View
|
|
147
|
+
|
|
148
|
+
**`views/memory.jsx`** — Full view accessible from the activity bar (BookOpen icon, between Dashboard and Teams).
|
|
149
|
+
|
|
150
|
+
Features:
|
|
151
|
+
- **List view** — cards with content preview, relative timestamps, size, type badge (AI sparkle for docs), link count
|
|
152
|
+
- **Tree view** — collapsible folder hierarchy following tag namespacing
|
|
153
|
+
- **Search** — filters by tag name
|
|
154
|
+
- **Editor modal** — tag input (new only), full-height textarea, Cmd+S save, read-only mode
|
|
155
|
+
- **Instruct modal** — all 10 commands with descriptions, tag hierarchy guide, memory types explanation
|
|
156
|
+
- **Empty state** — onboarding text explaining the system + quick action buttons
|
|
157
|
+
|
|
158
|
+
### GUI: Global Modals
|
|
159
|
+
|
|
160
|
+
**`components/keeper/global-modals.jsx`** — `KeeperGlobalModals` rendered at App.jsx level.
|
|
161
|
+
|
|
162
|
+
Two modals that respond to store state (`keeperEditing`, `keeperInstructOpen`):
|
|
163
|
+
- **KeeperEditorModal** — same editor as the memory view, triggered from chat commands
|
|
164
|
+
- **KeeperInstructModal** — command reference, triggered by `[instruct]`
|
|
165
|
+
|
|
166
|
+
Both skip rendering when `activeView === 'memory'` to avoid duplicate modals (the memory view renders its own copies).
|
|
167
|
+
|
|
168
|
+
### GUI: Store State
|
|
169
|
+
|
|
170
|
+
New state in Zustand store:
|
|
171
|
+
- `keeperItems: []` — list of all memory metadata
|
|
172
|
+
- `keeperTree: []` — hierarchical tree structure
|
|
173
|
+
- `keeperEditing: null` — `{ tag, content, isNew, readOnly }` drives the editor modal
|
|
174
|
+
- `keeperInstructOpen: false` — drives the instruct modal
|
|
175
|
+
|
|
176
|
+
New actions:
|
|
177
|
+
- `fetchKeeperItems()` — loads items + tree from API
|
|
178
|
+
- `saveKeeperItem()`, `appendKeeperItem()`, `updateKeeperItem()`, `deleteKeeperItem()` — CRUD
|
|
179
|
+
- `getKeeperItem()` — fetch single item with content
|
|
180
|
+
- `searchKeeper()` — search API wrapper
|
|
181
|
+
- `setKeeperEditing()` — open/close editor modal
|
|
182
|
+
- `_handleKeeperCommand()` — chat command interception logic
|
|
183
|
+
|
|
184
|
+
WebSocket handlers for `keeper:saved`, `keeper:updated`, `keeper:deleted` — trigger `fetchKeeperItems()` for real-time sync.
|
|
185
|
+
|
|
186
|
+
## Files Changed
|
|
187
|
+
|
|
188
|
+
### New Files
|
|
189
|
+
- `packages/daemon/src/keeper.js` — Keeper module
|
|
190
|
+
- `packages/gui/src/views/memory.jsx` — Memory view
|
|
191
|
+
- `packages/gui/src/components/keeper/global-modals.jsx` — Global editor + instruct modals
|
|
192
|
+
|
|
193
|
+
### Modified Files
|
|
194
|
+
- `packages/daemon/src/index.js` — import + instantiate Keeper
|
|
195
|
+
- `packages/daemon/src/api.js` — 14 Keeper endpoints + import
|
|
196
|
+
- `packages/daemon/src/introducer.js` — Keeper context injection on spawn
|
|
197
|
+
- `packages/daemon/src/validate.js` — `keeperTags` in agent config
|
|
198
|
+
- `packages/gui/src/stores/groove.js` — Keeper state, actions, WebSocket handlers, command interception
|
|
199
|
+
- `packages/gui/src/components/layout/activity-bar.jsx` — BookOpen icon for Memory
|
|
200
|
+
- `packages/gui/src/components/agents/agent-chat.jsx` — syntax highlighting + input overlay
|
|
201
|
+
- `packages/gui/src/App.jsx` — MemoryView route + KeeperGlobalModals
|
|
202
|
+
|
|
203
|
+
## Review Checklist
|
|
204
|
+
|
|
205
|
+
- [ ] Daemon starts without errors after adding keeper.js
|
|
206
|
+
- [ ] All 14 API endpoints respond correctly (save, get, update, delete, append, pull, doc, link, search, tree, list, commands, parse, unlink)
|
|
207
|
+
- [ ] Tag hierarchy works: saving `#groove/routing` creates directory structure
|
|
208
|
+
- [ ] `[save] #test hello world` in agent chat saves without reaching the agent
|
|
209
|
+
- [ ] `[pull] #test` injects the memory into the agent's context
|
|
210
|
+
- [ ] `[update] #test` opens the editor modal with existing content
|
|
211
|
+
- [ ] `[view] #test` opens read-only modal
|
|
212
|
+
- [ ] `[doc] #test` generates a doc from chat history (requires a provider for headless calls)
|
|
213
|
+
- [ ] `[link] #test plan_files/NORTHSTAR.md` links successfully
|
|
214
|
+
- [ ] `[instruct]` opens command reference
|
|
215
|
+
- [ ] `[delete] #test` removes the memory
|
|
216
|
+
- [ ] Syntax highlighting: `[save]` and `#tag` render in teal in both messages and input
|
|
217
|
+
- [ ] Memory view: list/tree toggle, search, new/edit/delete all work
|
|
218
|
+
- [ ] Global modals: editor opens from chat commands when not on memory view
|
|
219
|
+
- [ ] Agent spawn with `keeperTags` gets memory content in intro context
|
|
220
|
+
- [ ] WebSocket: saving from one client updates another
|
|
221
|
+
- [ ] Route order: `GET /api/keeper/commands` doesn't get caught by wildcard
|
|
222
|
+
- [ ] 265 existing tests still pass
|
|
223
|
+
- [ ] GUI build succeeds
|