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.
- package/DESIGN.md +344 -0
- package/README.md +268 -0
- package/index.js +1082 -0
- 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
|