yams-blackboard 0.1.1

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.
Files changed (4) hide show
  1. package/DESIGN.md +344 -0
  2. package/README.md +268 -0
  3. package/index.js +1082 -0
  4. package/package.json +34 -0
package/DESIGN.md ADDED
@@ -0,0 +1,344 @@
1
+ # YAMS Blackboard Plugin - Schema Design
2
+
3
+ ## Overview
4
+
5
+ This plugin implements a **blackboard architecture** for agent-to-agent communication using YAMS as the shared memory store. Agents post findings, claim tasks, and discover each other's work through structured queries.
6
+
7
+ ## Core Entities
8
+
9
+ ### 1. Agent Card
10
+
11
+ Agents self-register their identity and capabilities. This enables:
12
+ - Capability-based task routing
13
+ - Agent discovery for collaboration
14
+ - Audit trail of who contributed what
15
+
16
+ ```typescript
17
+ interface AgentCard {
18
+ id: string // Unique identifier, e.g., "security-scanner"
19
+ name: string // Human-readable name
20
+ capabilities: string[] // What this agent can do
21
+ version?: string // Agent version
22
+ registered_at: string // ISO timestamp
23
+ status: "active" | "idle" | "offline"
24
+ }
25
+ ```
26
+
27
+ **Storage**: `agents/{agent_id}.json`
28
+ **Tags**: `agent, capability:{cap1}, capability:{cap2}`
29
+
30
+ ---
31
+
32
+ ### 2. Finding
33
+
34
+ The core unit of agent communication. Findings are discoveries, observations, or outputs that other agents may want to know about.
35
+
36
+ ```typescript
37
+ interface Finding {
38
+ // Identity
39
+ id: string // Auto-generated: f-{timestamp}-{random}
40
+ agent_id: string // Who produced this
41
+
42
+ // Classification
43
+ topic: string // Category: security, performance, bug, architecture, refactor, test, doc
44
+ title: string // Brief summary (< 100 chars)
45
+
46
+ // Content
47
+ content: string // Full details (markdown)
48
+
49
+ // Confidence & Priority
50
+ confidence: number // 0.0 - 1.0, how certain the agent is
51
+ severity?: "info" | "low" | "medium" | "high" | "critical"
52
+
53
+ // Context & Relationships
54
+ context_id?: string // Groups related findings (e.g., a task ID)
55
+ references?: Reference[] // Links to code, docs, other findings
56
+ parent_id?: string // For threaded/reply findings
57
+
58
+ // Lifecycle
59
+ status: "draft" | "published" | "acknowledged" | "resolved" | "rejected"
60
+ created_at: string // ISO timestamp
61
+ updated_at?: string
62
+ resolved_by?: string // Agent that resolved this
63
+ resolution?: string // How it was resolved
64
+
65
+ // Persistence
66
+ scope: "session" | "persistent" // Default: persistent
67
+ ttl?: number // Optional TTL in seconds (for session-scoped)
68
+
69
+ // Arbitrary metadata
70
+ metadata?: Record<string, string>
71
+ }
72
+
73
+ interface Reference {
74
+ type: "file" | "url" | "finding" | "task" | "symbol"
75
+ target: string // Path, URL, ID, or symbol name
76
+ label?: string // Human-readable label
77
+ line_start?: number // For file references
78
+ line_end?: number
79
+ }
80
+ ```
81
+
82
+ **Storage**: `findings/{topic}/{id}.md` (with YAML frontmatter)
83
+ **Tags**: `finding, agent:{id}, topic:{topic}, severity:{sev}, scope:{scope}, status:{status}`
84
+
85
+ ---
86
+
87
+ ### 3. Task
88
+
89
+ For coordinated workflows where agents need to claim work, track progress, and hand off results.
90
+
91
+ ```typescript
92
+ interface Task {
93
+ // Identity
94
+ id: string // Auto-generated: t-{timestamp}-{random}
95
+
96
+ // Description
97
+ title: string // What needs to be done
98
+ description?: string // Detailed requirements
99
+
100
+ // Classification
101
+ type: "analysis" | "fix" | "review" | "test" | "research" | "synthesis"
102
+ priority: 0 | 1 | 2 | 3 | 4 // 0 = critical, 4 = backlog
103
+
104
+ // Lifecycle
105
+ status: "pending" | "claimed" | "working" | "blocked" | "review" | "completed" | "failed" | "cancelled"
106
+
107
+ // Assignment
108
+ created_by: string // Agent that created the task
109
+ assigned_to?: string // Agent currently working on it
110
+ claimed_at?: string
111
+
112
+ // Dependencies
113
+ depends_on?: string[] // Task IDs that must complete first
114
+ blocks?: string[] // Task IDs waiting on this
115
+
116
+ // Results
117
+ findings?: string[] // Finding IDs produced by this task
118
+ artifacts?: Artifact[] // Output files/data
119
+
120
+ // Context
121
+ context_id?: string // Groups related tasks
122
+ parent_task?: string // For subtasks
123
+
124
+ // Timestamps
125
+ created_at: string
126
+ updated_at?: string
127
+ completed_at?: string
128
+
129
+ // Failure handling
130
+ error?: string // Error message if failed
131
+ retry_count?: number
132
+ max_retries?: number
133
+ }
134
+
135
+ interface Artifact {
136
+ name: string
137
+ type: "file" | "data" | "report"
138
+ path?: string // YAMS path or local path
139
+ hash?: string // YAMS content hash
140
+ mime_type?: string
141
+ }
142
+ ```
143
+
144
+ **Storage**: `tasks/{id}.json`
145
+ **Tags**: `task, type:{type}, status:{status}, priority:{p}, creator:{id}, assignee:{id}`
146
+
147
+ **State Machine**:
148
+ ```
149
+ ┌──────────────────────────────────────┐
150
+ │ │
151
+ ▼ │
152
+ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
153
+ │ pending │───▶│ claimed │───▶│ working │───▶│ review │──┤
154
+ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
155
+ │ │ │ │ │
156
+ │ │ ▼ │ │
157
+ │ │ ┌─────────┐ │ │
158
+ │ └────────▶│ blocked │────────┘ │
159
+ │ └─────────┘ │
160
+ │ │
161
+ │ ┌───────────┐ ┌─────────┐ │
162
+ └────────▶│ cancelled │ │completed│◀─────────────┘
163
+ └───────────┘ └─────────┘
164
+
165
+
166
+ ┌─────────┐
167
+ │ failed │
168
+ └─────────┘
169
+ ```
170
+
171
+ ---
172
+
173
+ ### 4. Context
174
+
175
+ Groups related findings and tasks into a coherent unit of work.
176
+
177
+ ```typescript
178
+ interface Context {
179
+ id: string // Auto-generated or user-provided
180
+ name: string // Human-readable name
181
+ description?: string
182
+
183
+ // Aggregates
184
+ findings: string[] // Finding IDs in this context
185
+ tasks: string[] // Task IDs in this context
186
+ agents: string[] // Agents that contributed
187
+
188
+ // Lifecycle
189
+ status: "active" | "completed" | "archived"
190
+ created_at: string
191
+ updated_at?: string
192
+
193
+ // Summary (for compaction)
194
+ summary?: string // AI-generated summary
195
+ key_findings?: string[] // Most important finding IDs
196
+ }
197
+ ```
198
+
199
+ **Storage**: `contexts/{id}.json`
200
+ **Tags**: `context, status:{status}`
201
+
202
+ ---
203
+
204
+ ## Naming Conventions
205
+
206
+ ### Tags
207
+
208
+ All entities use hierarchical tags for efficient filtering:
209
+
210
+ | Prefix | Purpose | Examples |
211
+ |--------|---------|----------|
212
+ | `agent:` | Source agent | `agent:security-scanner` |
213
+ | `topic:` | Finding category | `topic:security`, `topic:performance` |
214
+ | `severity:` | Finding severity | `severity:high`, `severity:critical` |
215
+ | `status:` | Lifecycle state | `status:published`, `status:completed` |
216
+ | `scope:` | Persistence | `scope:session`, `scope:persistent` |
217
+ | `type:` | Task type | `type:fix`, `type:review` |
218
+ | `priority:` | Task priority | `priority:0`, `priority:2` |
219
+ | `ctx:` | Context grouping | `ctx:audit-2025-01` |
220
+ | `capability:` | Agent capability | `capability:code-review` |
221
+
222
+ ### Paths
223
+
224
+ ```
225
+ agents/{agent_id}.json
226
+ findings/{topic}/{finding_id}.md
227
+ tasks/{task_id}.json
228
+ contexts/{context_id}.json
229
+ ```
230
+
231
+ ---
232
+
233
+ ## Compaction Behavior
234
+
235
+ When OpenCode compacts a session, the plugin:
236
+
237
+ 1. **Queries active context** - Gets all findings/tasks in current context
238
+ 2. **Generates summary** - Uses structured template:
239
+
240
+ ```markdown
241
+ ## Blackboard Summary
242
+
243
+ ### Agents Active
244
+ - security-scanner: code-review, vuln-detection
245
+ - performance-analyzer: profiling, optimization
246
+
247
+ ### Key Findings ({count} total)
248
+ - [HIGH] SQL injection in auth module (security-scanner, 0.95 confidence)
249
+ - [MEDIUM] N+1 query in user list (performance-analyzer, 0.87 confidence)
250
+ - ...
251
+
252
+ ### Tasks
253
+ - [COMPLETED] Audit authentication flow (2 findings)
254
+ - [WORKING] Fix SQL injection vulnerability (assigned: code-fixer)
255
+ - [PENDING] Review performance optimizations (blocked by: t-xxx)
256
+
257
+ ### Unresolved Issues
258
+ - Finding f-xxx still unacknowledged
259
+ - Task t-yyy blocked for >1 hour
260
+ ```
261
+
262
+ 3. **Injects into context** - Adds summary to `output.context`
263
+
264
+ ---
265
+
266
+ ## Session vs Persistent Scope
267
+
268
+ | Aspect | Session-Scoped | Persistent |
269
+ |--------|----------------|------------|
270
+ | **Default** | No | Yes |
271
+ | **Survives restart** | No | Yes |
272
+ | **Use case** | Temporary scratch work | Long-term knowledge |
273
+ | **Cleanup** | Auto on session end | Manual or TTL |
274
+ | **Example** | Draft findings, WIP | Confirmed bugs, decisions |
275
+
276
+ To make a finding session-scoped:
277
+ ```typescript
278
+ bb_post_finding({
279
+ // ...
280
+ scope: "session",
281
+ ttl: 3600 // Optional: auto-delete after 1 hour
282
+ })
283
+ ```
284
+
285
+ ---
286
+
287
+ ## Tool Summary
288
+
289
+ | Tool | Purpose |
290
+ |------|---------|
291
+ | `bb_register_agent` | Register agent identity and capabilities |
292
+ | `bb_post_finding` | Publish a finding to the blackboard |
293
+ | `bb_query_findings` | Filter findings by topic, agent, severity, etc. |
294
+ | `bb_search_findings` | Semantic search across findings |
295
+ | `bb_acknowledge_finding` | Mark a finding as seen/acknowledged |
296
+ | `bb_resolve_finding` | Mark a finding as resolved |
297
+ | `bb_create_task` | Create a new task |
298
+ | `bb_claim_task` | Claim a pending task |
299
+ | `bb_update_task` | Update task status/progress |
300
+ | `bb_complete_task` | Mark task completed with results |
301
+ | `bb_fail_task` | Mark task as failed |
302
+ | `bb_get_ready_tasks` | Get tasks ready to work (no blockers) |
303
+ | `bb_list_agents` | List registered agents |
304
+ | `bb_create_context` | Create a new context grouping |
305
+ | `bb_get_context_summary` | Get summary of a context |
306
+ | `bb_recent_activity` | Get recent findings and task updates |
307
+
308
+ ---
309
+
310
+ ## Example Workflow
311
+
312
+ ```
313
+ 1. Agents register on session start
314
+ bb_register_agent({ id: "scanner", capabilities: ["security", "lint"] })
315
+ bb_register_agent({ id: "fixer", capabilities: ["code-fix", "refactor"] })
316
+
317
+ 2. Scanner posts findings
318
+ bb_post_finding({
319
+ agent_id: "scanner",
320
+ topic: "security",
321
+ title: "XSS in user profile",
322
+ severity: "high",
323
+ confidence: 0.91
324
+ })
325
+
326
+ 3. Coordinator creates task
327
+ bb_create_task({
328
+ title: "Fix XSS vulnerability",
329
+ type: "fix",
330
+ priority: 1,
331
+ context_id: "security-audit"
332
+ })
333
+
334
+ 4. Fixer claims and works
335
+ bb_claim_task({ task_id: "t-xxx", agent_id: "fixer" })
336
+ bb_update_task({ task_id: "t-xxx", status: "working" })
337
+
338
+ 5. Fixer completes with finding
339
+ bb_post_finding({ ..., context_id: "security-audit", parent_id: "f-original" })
340
+ bb_complete_task({ task_id: "t-xxx", findings: ["f-fix"] })
341
+
342
+ 6. Original finding resolved
343
+ bb_resolve_finding({ finding_id: "f-original", resolved_by: "fixer", resolution: "Fixed in PR #123" })
344
+ ```
package/README.md ADDED
@@ -0,0 +1,268 @@
1
+ # YAMS Blackboard Plugin for OpenCode
2
+
3
+ A **blackboard architecture** plugin enabling agent-to-agent communication through [YAMS](https://github.com/yams-project/yams) as shared memory.
4
+
5
+ ## Overview
6
+
7
+ This plugin implements the classic [blackboard pattern](https://en.wikipedia.org/wiki/Blackboard_system) for multi-agent AI systems. Agents post findings, claim tasks, and discover each other's work through a shared knowledge store.
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────┐
11
+ │ YAMS BLACKBOARD │
12
+ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
13
+ │ │ Findings │ │ Tasks │ │ Context │ │
14
+ │ │ (tagged) │ │ (status) │ │ (graph) │ │
15
+ │ └─────────────┘ └─────────────┘ └─────────────┘ │
16
+ └─────────────────────────────────────────────────────┘
17
+ ▲ write ▲ write │ read
18
+ │ │ ▼
19
+ ┌────┴────┐ ┌────┴────┐ ┌────────┐
20
+ │ Agent A │ │ Agent B │ │ Agent C │
21
+ │ (scan) │ │ (review)│ │(synthesize)│
22
+ └─────────┘ └─────────┘ └────────┘
23
+ ```
24
+
25
+ ## Prerequisites
26
+
27
+ - **YAMS daemon** must be installed and running
28
+ - **bun** (for local development/building)
29
+ - **OpenCode** v1.1.0+ (for plugin support)
30
+
31
+ ## Installation
32
+
33
+ ### Option 1: npm (Recommended)
34
+
35
+ Add to your `opencode.json`:
36
+
37
+ ```json
38
+ {
39
+ "plugins": ["yams-blackboard"]
40
+ }
41
+ ```
42
+
43
+ OpenCode automatically installs npm plugins at startup.
44
+
45
+ ### Option 2: Local Plugin
46
+
47
+ Copy to your project's `.opencode/plugin/` directory:
48
+
49
+ ```bash
50
+ mkdir -p .opencode/plugin/yams-blackboard
51
+ cp -r * .opencode/plugin/yams-blackboard/
52
+ ```
53
+
54
+ ### Verify YAMS is Running
55
+
56
+ The plugin communicates with YAMS via CLI. Ensure the daemon is running:
57
+
58
+ ```bash
59
+ yams daemon start
60
+ yams status
61
+ ```
62
+
63
+ ## Tools
64
+
65
+ ### Agent Management
66
+
67
+ | Tool | Description |
68
+ |------|-------------|
69
+ | `bb_register_agent` | Register agent identity and capabilities |
70
+ | `bb_list_agents` | List all registered agents |
71
+
72
+ ### Findings
73
+
74
+ | Tool | Description |
75
+ |------|-------------|
76
+ | `bb_post_finding` | Post a finding to the blackboard |
77
+ | `bb_query_findings` | Query findings by topic, agent, severity |
78
+ | `bb_search_findings` | Semantic search across findings |
79
+ | `bb_get_finding` | Get full details of a finding |
80
+ | `bb_acknowledge_finding` | Mark a finding as acknowledged |
81
+ | `bb_resolve_finding` | Mark a finding as resolved |
82
+
83
+ ### Tasks
84
+
85
+ | Tool | Description |
86
+ |------|-------------|
87
+ | `bb_create_task` | Create a new task |
88
+ | `bb_get_ready_tasks` | Get tasks ready to work (no blockers) |
89
+ | `bb_claim_task` | Claim a pending task |
90
+ | `bb_update_task` | Update task status |
91
+ | `bb_complete_task` | Mark task completed |
92
+ | `bb_fail_task` | Mark task as failed |
93
+ | `bb_query_tasks` | Query tasks by type, status, assignee |
94
+
95
+ ### Context & Utility
96
+
97
+ | Tool | Description |
98
+ |------|-------------|
99
+ | `bb_create_context` | Create a context to group findings/tasks |
100
+ | `bb_get_context_summary` | Get summary of a context |
101
+ | `bb_set_context` | Set current working context |
102
+ | `bb_recent_activity` | Get recent findings and tasks |
103
+ | `bb_stats` | Get blackboard statistics |
104
+ | `bb_connections` | Explore graph connections |
105
+
106
+ ## Example Workflow
107
+
108
+ ```typescript
109
+ // Agent 1: Security scanner registers and posts finding
110
+ bb_register_agent({
111
+ id: "scanner",
112
+ name: "Security Scanner",
113
+ capabilities: ["security", "code-review"]
114
+ })
115
+
116
+ bb_post_finding({
117
+ agent_id: "scanner",
118
+ topic: "security",
119
+ title: "SQL Injection in auth.ts:42",
120
+ severity: "high",
121
+ confidence: 0.92,
122
+ content: "Found unsanitized user input passed directly to SQL query...",
123
+ references: [{ type: "file", target: "src/auth.ts", line_start: 42 }]
124
+ })
125
+
126
+ // Agent 2: Fixer discovers the finding
127
+ bb_search_findings({ query: "SQL injection" })
128
+
129
+ // Coordinator creates a task
130
+ bb_create_task({
131
+ title: "Fix SQL injection vulnerability",
132
+ type: "fix",
133
+ created_by: "coordinator",
134
+ priority: 1
135
+ })
136
+
137
+ // Fixer claims and works
138
+ bb_claim_task({ task_id: "t-xxx", agent_id: "fixer" })
139
+ bb_update_task({ task_id: "t-xxx", status: "working" })
140
+
141
+ // Fixer completes and resolves
142
+ bb_complete_task({ task_id: "t-xxx", findings: ["f-fix-001"] })
143
+ bb_resolve_finding({
144
+ finding_id: "f-original",
145
+ agent_id: "fixer",
146
+ resolution: "Parameterized queries added in PR #123"
147
+ })
148
+ ```
149
+
150
+ ## Schemas
151
+
152
+ ### Finding
153
+
154
+ ```typescript
155
+ interface Finding {
156
+ id: string
157
+ agent_id: string
158
+ topic: "security" | "performance" | "bug" | "architecture" | ...
159
+ title: string
160
+ content: string
161
+ confidence: number // 0.0 - 1.0
162
+ severity?: "info" | "low" | "medium" | "high" | "critical"
163
+ status: "draft" | "published" | "acknowledged" | "resolved" | "rejected"
164
+ scope: "session" | "persistent" // Default: persistent
165
+ context_id?: string
166
+ references?: Reference[]
167
+ }
168
+ ```
169
+
170
+ ### Task
171
+
172
+ ```typescript
173
+ interface Task {
174
+ id: string
175
+ title: string
176
+ type: "analysis" | "fix" | "review" | "test" | "research" | "synthesis"
177
+ priority: 0 | 1 | 2 | 3 | 4 // 0=critical, 4=backlog
178
+ status: "pending" | "claimed" | "working" | "blocked" | "review" | "completed" | "failed"
179
+ created_by: string
180
+ assigned_to?: string
181
+ depends_on?: string[]
182
+ findings?: string[]
183
+ }
184
+ ```
185
+
186
+ See [DESIGN.md](./DESIGN.md) for complete schema documentation.
187
+
188
+ ## Lifecycle Hooks
189
+
190
+ The plugin integrates with OpenCode's lifecycle:
191
+
192
+ - **`session.created`**: Starts a YAMS session for the conversation
193
+ - **`session.compacted`**: Injects blackboard summary into compaction context
194
+
195
+ ## Persistence
196
+
197
+ By default, findings are **persistent** (survive across sessions). Use `scope: "session"` for temporary scratch work:
198
+
199
+ ```typescript
200
+ bb_post_finding({
201
+ // ...
202
+ scope: "session",
203
+ ttl: 3600 // Optional: auto-delete after 1 hour
204
+ })
205
+ ```
206
+
207
+ ## Architecture
208
+
209
+ Based on research into multi-agent communication patterns:
210
+
211
+ - **Blackboard Pattern**: Shared memory over direct messaging for loose coupling
212
+ - **A2A Protocol Concepts**: Structured findings with lifecycle states
213
+ - **Task Coordination**: Claim-based work distribution with dependencies
214
+
215
+ ## Development
216
+
217
+ ### Building
218
+
219
+ Build with external dependencies (do not bundle zod or plugin SDK):
220
+
221
+ ```bash
222
+ bun install
223
+ bun run build
224
+ ```
225
+
226
+ This compiles `index.ts` to `index.js` for distribution.
227
+
228
+ ### Type Checking
229
+
230
+ ```bash
231
+ bun run typecheck
232
+ ```
233
+
234
+ ### Local Testing
235
+
236
+ 1. Build the plugin: `bun run build`
237
+ 2. Copy to your project: `cp index.js ~/.opencode/plugin/yams-blackboard.js`
238
+ 3. Restart OpenCode
239
+ 4. Test with: `bb_list_agents`
240
+
241
+ ## Troubleshooting
242
+
243
+ ### "YAMS daemon not running"
244
+
245
+ Ensure the YAMS daemon is started:
246
+
247
+ ```bash
248
+ yams daemon start
249
+ yams status # Should show "running"
250
+ ```
251
+
252
+ ### "Command 'yams' not found"
253
+
254
+ YAMS must be installed and in your PATH. Check your installation.
255
+
256
+ ### Plugin not loading
257
+
258
+ 1. Verify `opencode.json` has `"plugins": ["yams-blackboard"]`
259
+ 2. Check OpenCode logs for plugin load errors
260
+ 3. Try clearing npm cache: `npm cache clean --force`
261
+
262
+ ### Tools not appearing
263
+
264
+ The plugin registers tools on `session.created`. Start a new session if tools don't appear.
265
+
266
+ ## License
267
+
268
+ MIT