bobs-workshop 0.3.3 â 3.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/LICENSE +2 -2
- package/README.md +199 -210
- package/bin/bobs-workshop.js +109 -0
- package/config/agents.json +27 -0
- package/dist/plugins/bobs-workshop.js +34 -0
- package/dist/tools/background-agent/cancel.d.ts +3 -0
- package/dist/tools/background-agent/cancel.d.ts.map +1 -0
- package/dist/tools/background-agent/cancel.js +52 -0
- package/dist/tools/background-agent/concurrency.d.ts +15 -0
- package/dist/tools/background-agent/concurrency.d.ts.map +1 -0
- package/dist/tools/background-agent/concurrency.js +61 -0
- package/dist/tools/background-agent/index.d.ts +8 -0
- package/dist/tools/background-agent/index.d.ts.map +1 -0
- package/dist/tools/background-agent/index.js +7 -0
- package/dist/tools/background-agent/launch.d.ts +6 -0
- package/dist/tools/background-agent/launch.d.ts.map +1 -0
- package/dist/tools/background-agent/launch.js +33 -0
- package/dist/tools/background-agent/list.d.ts +7 -0
- package/dist/tools/background-agent/list.d.ts.map +1 -0
- package/dist/tools/background-agent/list.js +40 -0
- package/dist/tools/background-agent/manager.d.ts +29 -0
- package/dist/tools/background-agent/manager.d.ts.map +1 -0
- package/dist/tools/background-agent/manager.js +388 -0
- package/dist/tools/background-agent/output.d.ts +3 -0
- package/dist/tools/background-agent/output.d.ts.map +1 -0
- package/dist/tools/background-agent/output.js +41 -0
- package/dist/tools/background-agent/types.d.ts +46 -0
- package/dist/tools/background-agent/types.d.ts.map +1 -0
- package/dist/tools/background-agent/types.js +1 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +8 -0
- package/dist/tools/manual/index.d.ts +3 -0
- package/dist/tools/manual/index.d.ts.map +1 -0
- package/dist/tools/manual/index.js +2 -0
- package/dist/tools/manual/manual-update.d.ts +4 -0
- package/dist/tools/manual/manual-update.d.ts.map +1 -0
- package/dist/tools/manual/manual-update.js +190 -0
- package/dist/tools/manual/verify-manual.d.ts +4 -0
- package/dist/tools/manual/verify-manual.d.ts.map +1 -0
- package/dist/tools/manual/verify-manual.js +51 -0
- package/package.json +34 -66
- package/postinstall.js +193 -0
- package/src/agents/alice.md +466 -0
- package/src/agents/bob-rev.md +493 -0
- package/src/agents/bob-send.md +277 -0
- package/src/agents/bob.md +442 -0
- package/src/agents/trace.md +451 -0
- package/src/plugins/bobs-workshop.ts +45 -0
- package/src/skills/api-patterns/SKILL.md +376 -0
- package/src/skills/architecture/SKILL.md +271 -0
- package/src/skills/bobs-workshop/performance/icon.svg +3 -0
- package/src/skills/brainstorming/SKILL.md +210 -0
- package/src/skills/clean-code/SKILL.md +151 -0
- package/src/skills/code-review-checklist/SKILL.md +220 -0
- package/src/skills/database-design/SKILL.md +271 -0
- package/src/skills/exploration/SKILL.md +257 -0
- package/src/skills/frontend-ui-ux/SKILL.md +78 -0
- package/src/skills/git-master/SKILL.md +1105 -0
- package/src/skills/performance/SKILL.md +144 -0
- package/src/skills/performance/icon.svg +3 -0
- package/src/skills/plan-writing/SKILL.md +225 -0
- package/src/skills/security/SKILL.md +410 -0
- package/src/skills/simplification/SKILL.md +238 -0
- package/src/skills/systematic-debugging/SKILL.md +175 -0
- package/src/skills/testing-patterns/SKILL.md +305 -0
- package/src/skills/verification/SKILL.md +286 -0
- package/src/tools/background-agent/cancel.ts +67 -0
- package/src/tools/background-agent/concurrency.ts +71 -0
- package/src/tools/background-agent/index.ts +7 -0
- package/src/tools/background-agent/launch.ts +39 -0
- package/src/tools/background-agent/list.ts +50 -0
- package/src/tools/background-agent/manager.ts +466 -0
- package/src/tools/background-agent/output.ts +57 -0
- package/src/tools/background-agent/types.ts +55 -0
- package/src/tools/index.ts +8 -0
- package/src/tools/manual/index.ts +2 -0
- package/src/tools/manual/manual-update.ts +197 -0
- package/src/tools/manual/verify-manual.ts +60 -0
- package/uninstall.js +64 -0
- package/Claude.md +0 -162
- package/bin/bobs-mcp-server.js +0 -11
- package/bin/bobs-mcp.js +0 -130
- package/dist/api/taskLogger.js +0 -106
- package/dist/api/taskLogger.js.map +0 -1
- package/dist/cli/checker.js +0 -401
- package/dist/cli/checker.js.map +0 -1
- package/dist/cli/cleanup.js +0 -131
- package/dist/cli/cleanup.js.map +0 -1
- package/dist/cli/debug.js +0 -157
- package/dist/cli/debug.js.map +0 -1
- package/dist/cli/health.js +0 -97
- package/dist/cli/health.js.map +0 -1
- package/dist/cli/setup.js +0 -81
- package/dist/cli/setup.js.map +0 -1
- package/dist/cli/workshop.js +0 -42
- package/dist/cli/workshop.js.map +0 -1
- package/dist/dashboard/server.js +0 -1203
- package/dist/dashboard/server.js.map +0 -1
- package/dist/index.js +0 -960
- package/dist/index.js.map +0 -1
- package/dist/prompts/architect.js +0 -221
- package/dist/prompts/architect.js.map +0 -1
- package/dist/prompts/debugger.js +0 -257
- package/dist/prompts/debugger.js.map +0 -1
- package/dist/prompts/engineer.js +0 -249
- package/dist/prompts/engineer.js.map +0 -1
- package/dist/prompts/orchestrator.js +0 -304
- package/dist/prompts/orchestrator.js.map +0 -1
- package/dist/prompts/reviewer.js +0 -289
- package/dist/prompts/reviewer.js.map +0 -1
- package/dist/services/activitySummarizer.js +0 -388
- package/dist/services/activitySummarizer.js.map +0 -1
- package/dist/services/changeValidator.js +0 -396
- package/dist/services/changeValidator.js.map +0 -1
- package/dist/services/claudeOrchestrator.js +0 -343
- package/dist/services/claudeOrchestrator.js.map +0 -1
- package/dist/services/fileMonitor.js +0 -250
- package/dist/services/fileMonitor.js.map +0 -1
- package/dist/services/implementationSummarizer.js +0 -306
- package/dist/services/implementationSummarizer.js.map +0 -1
- package/dist/services/liveMonitor.js +0 -315
- package/dist/services/liveMonitor.js.map +0 -1
- package/dist/services/mcpAuditLogger.js +0 -104
- package/dist/services/mcpAuditLogger.js.map +0 -1
- package/dist/services/mcpLogger.js +0 -223
- package/dist/services/mcpLogger.js.map +0 -1
- package/dist/services/tmuxManager.js +0 -541
- package/dist/services/tmuxManager.js.map +0 -1
- package/dist/tools/approvalTools.js +0 -244
- package/dist/tools/approvalTools.js.map +0 -1
- package/dist/tools/autoDebugger.js +0 -147
- package/dist/tools/autoDebugger.js.map +0 -1
- package/dist/tools/cleanupService.js +0 -221
- package/dist/tools/cleanupService.js.map +0 -1
- package/dist/tools/dashboardTools.js +0 -342
- package/dist/tools/dashboardTools.js.map +0 -1
- package/dist/tools/developmentNudges.js +0 -336
- package/dist/tools/developmentNudges.js.map +0 -1
- package/dist/tools/gitTools.js +0 -741
- package/dist/tools/gitTools.js.map +0 -1
- package/dist/tools/orchestratorTools.js +0 -832
- package/dist/tools/orchestratorTools.js.map +0 -1
- package/dist/tools/searchCache.js +0 -64
- package/dist/tools/searchCache.js.map +0 -1
- package/dist/tools/searchTools.js +0 -1107
- package/dist/tools/searchTools.js.map +0 -1
- package/dist/tools/semgrep-patterns.js +0 -296
- package/dist/tools/semgrep-patterns.js.map +0 -1
- package/dist/tools/specTools.js +0 -332
- package/dist/tools/specTools.js.map +0 -1
- package/dist/tools/structural/__tests__/orchestrator.test.js +0 -61
- package/dist/tools/structural/__tests__/orchestrator.test.js.map +0 -1
- package/dist/tools/structural/cache.js +0 -226
- package/dist/tools/structural/cache.js.map +0 -1
- package/dist/tools/structural/engines/python/index.js +0 -118
- package/dist/tools/structural/engines/python/index.js.map +0 -1
- package/dist/tools/structural/engines/typescript/__tests__/typescript-engine.test.js +0 -97
- package/dist/tools/structural/engines/typescript/__tests__/typescript-engine.test.js.map +0 -1
- package/dist/tools/structural/engines/typescript/analyzer.js +0 -433
- package/dist/tools/structural/engines/typescript/analyzer.js.map +0 -1
- package/dist/tools/structural/engines/typescript/index.js +0 -381
- package/dist/tools/structural/engines/typescript/index.js.map +0 -1
- package/dist/tools/structural/engines/typescript/utils.js +0 -279
- package/dist/tools/structural/engines/typescript/utils.js.map +0 -1
- package/dist/tools/structural/index.js +0 -248
- package/dist/tools/structural/index.js.map +0 -1
- package/dist/tools/structural/types.js +0 -18
- package/dist/tools/structural/types.js.map +0 -1
- package/dist/tools/tmuxTools.js +0 -100
- package/dist/tools/tmuxTools.js.map +0 -1
- package/dist/tools/workRecorder.js +0 -215
- package/dist/tools/workRecorder.js.map +0 -1
- package/dist/tools/worktreeTools.js +0 -705
- package/dist/tools/worktreeTools.js.map +0 -1
- package/dist/utils/__tests__/integration.test.js +0 -57
- package/dist/utils/__tests__/integration.test.js.map +0 -1
- package/dist/utils/__tests__/serverDetection.test.js +0 -151
- package/dist/utils/__tests__/serverDetection.test.js.map +0 -1
- package/dist/utils/errorHandling.js +0 -336
- package/dist/utils/errorHandling.js.map +0 -1
- package/dist/utils/processManager.js +0 -172
- package/dist/utils/processManager.js.map +0 -1
- package/dist/utils/reliability.js +0 -263
- package/dist/utils/reliability.js.map +0 -1
- package/dist/utils/responseFormatter.js +0 -250
- package/dist/utils/responseFormatter.js.map +0 -1
- package/dist/utils/serverDetection.js +0 -133
- package/dist/utils/serverDetection.js.map +0 -1
- package/dist/utils/specMigration.js +0 -105
- package/dist/utils/specMigration.js.map +0 -1
- package/dist/validation/schemas.js +0 -299
- package/dist/validation/schemas.js.map +0 -1
- package/public/.well-known/mcp/manifest.json +0 -473
- package/public/index.html +0 -3157
- package/public/index.html.backup +0 -2805
- package/public/index.html.backup2 +0 -1292
- package/scripts/cleanup-system-logs.ts +0 -121
- package/scripts/init-workspace.js +0 -63
- package/scripts/install-search-tools.js +0 -116
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
const MANUAL_TEMPLATE = `# đ MANUAL: [Feature Name]
|
|
3
|
+
|
|
4
|
+
> Created: MAN-YYMMDD-[feature-name].md
|
|
5
|
+
|
|
6
|
+
## đ Executive Summary
|
|
7
|
+
|
|
8
|
+
High-level overview of what we're building and why.
|
|
9
|
+
|
|
10
|
+
**Example:**
|
|
11
|
+
- What problem does this solve?
|
|
12
|
+
- Who are the users?
|
|
13
|
+
- What's the success criteria?
|
|
14
|
+
- What are the core features?
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## đ Product Specifications
|
|
19
|
+
|
|
20
|
+
Detailed requirements and acceptance criteria.
|
|
21
|
+
|
|
22
|
+
**Example:**
|
|
23
|
+
- User stories / Use cases
|
|
24
|
+
- Functional requirements
|
|
25
|
+
- Non-functional requirements (performance, security, etc.)
|
|
26
|
+
- Edge cases and error handling
|
|
27
|
+
- Success metrics
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## đī¸ Architecture Analysis
|
|
32
|
+
|
|
33
|
+
Technical design decisions and system architecture.
|
|
34
|
+
|
|
35
|
+
**Example:**
|
|
36
|
+
- System diagram / architecture overview
|
|
37
|
+
- Data models and schemas
|
|
38
|
+
- API endpoints and contracts
|
|
39
|
+
- Database design (indexes, relationships)
|
|
40
|
+
- Authentication/authorization approach
|
|
41
|
+
- Technology choices and trade-offs
|
|
42
|
+
- Security considerations
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## đ Implementation Plan
|
|
47
|
+
|
|
48
|
+
Breakdown of tasks with dependencies.
|
|
49
|
+
|
|
50
|
+
**Example:**
|
|
51
|
+
1. Setup and scaffolding
|
|
52
|
+
2. Database schema migrations
|
|
53
|
+
3. Core business logic
|
|
54
|
+
4. API endpoint implementation
|
|
55
|
+
5. Frontend components
|
|
56
|
+
6. Integration testing
|
|
57
|
+
7. Documentation
|
|
58
|
+
|
|
59
|
+
Mark completed tasks with â
, in-progress with đ, blocked with đĢ
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## đ Execution Logs
|
|
64
|
+
|
|
65
|
+
Chronological progress as tasks are completed.
|
|
66
|
+
|
|
67
|
+
**Format:**
|
|
68
|
+
\`\`\`
|
|
69
|
+
[YYYY-MM-DD HH:MM] - Agent: task description
|
|
70
|
+
- Output: results / artifacts
|
|
71
|
+
- Files modified: list of files
|
|
72
|
+
- Dependencies: what blocked this or what it enables
|
|
73
|
+
\`\`\`
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## đ Review Notes
|
|
78
|
+
|
|
79
|
+
Findings from code reviews, architectural reviews, or peer reviews.
|
|
80
|
+
|
|
81
|
+
**Example:**
|
|
82
|
+
- Code quality observations
|
|
83
|
+
- Performance concerns
|
|
84
|
+
- Security vulnerabilities
|
|
85
|
+
- Suggestions for improvements
|
|
86
|
+
- Action items from reviews
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## đ Debug Logs
|
|
91
|
+
|
|
92
|
+
Troubleshooting sessions and root cause analysis.
|
|
93
|
+
|
|
94
|
+
**Format:**
|
|
95
|
+
\`\`\`
|
|
96
|
+
[YYYY-MM-DD HH:MM] - Issue description
|
|
97
|
+
- Symptoms: what went wrong
|
|
98
|
+
- Investigation: steps taken
|
|
99
|
+
- Root cause: underlying problem
|
|
100
|
+
- Resolution: fix applied
|
|
101
|
+
- Prevention: how to avoid recurrence
|
|
102
|
+
\`\`\`
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## â
Verification Logs
|
|
107
|
+
|
|
108
|
+
Test results and quality assurance checks.
|
|
109
|
+
|
|
110
|
+
**Example:**
|
|
111
|
+
- Unit test results
|
|
112
|
+
- Integration test results
|
|
113
|
+
- E2E test results
|
|
114
|
+
- Performance benchmarks
|
|
115
|
+
- Security scan results
|
|
116
|
+
- Manual QA checklists
|
|
117
|
+
|
|
118
|
+
Each verification should include:
|
|
119
|
+
- PASS/FAIL status
|
|
120
|
+
- Evidence (screenshots, logs, metrics)
|
|
121
|
+
- Coverage percentage
|
|
122
|
+
- Blockers for release
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## đ¤ Agent Handoffs
|
|
127
|
+
|
|
128
|
+
Context transfers between different agents.
|
|
129
|
+
|
|
130
|
+
**Format:**
|
|
131
|
+
\`\`\`
|
|
132
|
+
[YYYY-MM-DD HH:MM] - alice â bob
|
|
133
|
+
- Context: architectural decisions, design docs
|
|
134
|
+
- Artifacts: MAN-xxx.md, schema.sql
|
|
135
|
+
- Next steps: implement authentication flow
|
|
136
|
+
\`\`\`
|
|
137
|
+
|
|
138
|
+
This ensures smooth handoffs between agents and maintains continuity across sessions.
|
|
139
|
+
`;
|
|
140
|
+
const ManualUpdateTool = tool({
|
|
141
|
+
description: "Update a specific section in a MANUAL file. Creates file/section if missing.",
|
|
142
|
+
args: {
|
|
143
|
+
manual_path: tool.schema.string().describe("Path to MANUAL file (e.g., manuals/MAN-260127-auth.md)"),
|
|
144
|
+
section: tool.schema.string().describe("Section header to update (e.g., 'đ Executive Summary', 'đ Execution Logs')"),
|
|
145
|
+
content: tool.schema.string().describe("Content to append to the section"),
|
|
146
|
+
create_if_missing: tool.schema.boolean().default(true)
|
|
147
|
+
.describe("Create section if it doesn't exist (default: true)"),
|
|
148
|
+
},
|
|
149
|
+
async execute(args) {
|
|
150
|
+
const { readFileSync, writeFileSync, existsSync, mkdirSync } = await import("node:fs");
|
|
151
|
+
const { dirname } = await import("node:path");
|
|
152
|
+
const manualPath = args.manual_path;
|
|
153
|
+
if (!manualPath.match(/^manuals\/MAN-\d{6}-.+\.md$/)) {
|
|
154
|
+
return `â Invalid path. Expected format: manuals/MAN-YYMMDD-<feature>.md`;
|
|
155
|
+
}
|
|
156
|
+
const manualsDir = dirname(manualPath);
|
|
157
|
+
if (!existsSync(manualsDir)) {
|
|
158
|
+
mkdirSync(manualsDir, { recursive: true });
|
|
159
|
+
}
|
|
160
|
+
let content = "";
|
|
161
|
+
if (existsSync(manualPath)) {
|
|
162
|
+
content = readFileSync(manualPath, "utf8");
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
content = MANUAL_TEMPLATE;
|
|
166
|
+
writeFileSync(manualPath, content, "utf8");
|
|
167
|
+
}
|
|
168
|
+
const lines = content.split('\n');
|
|
169
|
+
let sectionIndex = lines.findIndex(l => l.trim() === args.section);
|
|
170
|
+
if (sectionIndex === -1) {
|
|
171
|
+
if (!args.create_if_missing) {
|
|
172
|
+
return `â Section '${args.section}' not found in ${manualPath}`;
|
|
173
|
+
}
|
|
174
|
+
content = `${content}\n${args.section}\n${args.content}\n`;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
const insertPosition = sectionIndex + 1;
|
|
178
|
+
if (lines[insertPosition] && !lines[insertPosition].startsWith('##')) {
|
|
179
|
+
lines[insertPosition] = `${lines[insertPosition]}\n${args.content}`;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
lines.splice(insertPosition, 0, args.content);
|
|
183
|
+
}
|
|
184
|
+
content = lines.join('\n');
|
|
185
|
+
}
|
|
186
|
+
writeFileSync(manualPath, content, "utf8");
|
|
187
|
+
return `â
Updated section '${args.section}' in ${manualPath}`;
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
export default ManualUpdateTool;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-manual.d.ts","sourceRoot":"","sources":["../../../src/tools/manual/verify-manual.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAErE,QAAA,MAAM,gBAAgB,EAAE,cAuDtB,CAAC;AAEH,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
const VerifyManualTool = tool({
|
|
3
|
+
description: "Run bob-rev verification in background for a MANUAL",
|
|
4
|
+
args: {
|
|
5
|
+
manual_path: tool.schema.string().describe("Path to MANUAL file (e.g., manuals/MAN-260127-auth.md)"),
|
|
6
|
+
},
|
|
7
|
+
async execute(args, context) {
|
|
8
|
+
const { client, directory, sessionID } = context;
|
|
9
|
+
const createResult = await client.session.create({
|
|
10
|
+
body: {
|
|
11
|
+
parentID: sessionID,
|
|
12
|
+
title: `Verification: ${args.manual_path.split('/').pop()}`,
|
|
13
|
+
},
|
|
14
|
+
query: { directory },
|
|
15
|
+
});
|
|
16
|
+
const createData = createResult;
|
|
17
|
+
if (createData.error) {
|
|
18
|
+
throw new Error(`Failed to create verification session: ${createData.error}`);
|
|
19
|
+
}
|
|
20
|
+
const { readFileSync, existsSync } = await import("node:fs");
|
|
21
|
+
const { join } = await import("node:path");
|
|
22
|
+
let manualContent = "";
|
|
23
|
+
if (existsSync(args.manual_path)) {
|
|
24
|
+
manualContent = readFileSync(args.manual_path, "utf8");
|
|
25
|
+
// Sanitize content to prevent JSON parsing issues with kimi model
|
|
26
|
+
manualContent = manualContent
|
|
27
|
+
.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F]/g, '') // Remove control chars except \n, \r, \t
|
|
28
|
+
.replace(/\u2028/g, '\n') // Replace line separator with newline
|
|
29
|
+
.replace(/\u2029/g, '\n'); // Replace paragraph separator with newline
|
|
30
|
+
}
|
|
31
|
+
const skillPath = join(directory, ".opencode", "agent", "bobs-workshop", "bob-rev.md");
|
|
32
|
+
let agentPrompt = "You are bob-rev, a reviewer agent that verifies implementation against MANUAL requirements.";
|
|
33
|
+
if (existsSync(skillPath)) {
|
|
34
|
+
agentPrompt = readFileSync(skillPath, "utf8");
|
|
35
|
+
}
|
|
36
|
+
await client.session.prompt({
|
|
37
|
+
path: { id: createData.data.id },
|
|
38
|
+
body: {
|
|
39
|
+
agent: "bob-rev",
|
|
40
|
+
system: `${agentPrompt}\n\n## MANUAL to Verify:\n${manualContent}`,
|
|
41
|
+
tools: {
|
|
42
|
+
task: false,
|
|
43
|
+
delegate_task: false,
|
|
44
|
+
},
|
|
45
|
+
parts: [{ type: "text", text: "Verify this MANUAL and provide PASS/FAIL decision with reasoning." }],
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
return `â
Started verification for ${args.manual_path} in session ${createData.data.id}`;
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
export default VerifyManualTool;
|
package/package.json
CHANGED
|
@@ -1,86 +1,54 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bobs-workshop",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.1.1",
|
|
4
|
+
"description": "MANUAL-driven development with background agents for OpenCode",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "dist/
|
|
6
|
+
"main": "./dist/plugins/bobs-workshop.js",
|
|
7
|
+
"types": "./dist/plugins/bobs-workshop.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"src/agents",
|
|
10
|
+
"src/skills",
|
|
11
|
+
"src/tools",
|
|
12
|
+
"src/plugins",
|
|
13
|
+
"dist/tools",
|
|
14
|
+
"dist/plugins",
|
|
15
|
+
"config",
|
|
16
|
+
"postinstall.js",
|
|
17
|
+
"uninstall.js"
|
|
18
|
+
],
|
|
7
19
|
"bin": {
|
|
8
|
-
"bobs-
|
|
9
|
-
"bobs": "bin/bobs-mcp.js"
|
|
20
|
+
"bobs-workshop": "bin/bobs-workshop.js"
|
|
10
21
|
},
|
|
11
22
|
"scripts": {
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"test": "
|
|
16
|
-
"
|
|
17
|
-
"dashboard": "node dist/dashboard/server.js",
|
|
18
|
-
"postinstall": "node scripts/install-search-tools.js && node scripts/init-workspace.js",
|
|
19
|
-
"install-search-tools": "node scripts/install-search-tools.js",
|
|
20
|
-
"cleanup:system-logs": "tsx scripts/cleanup-system-logs.ts"
|
|
23
|
+
"build": "tsc && node scripts/copy-plugin.js",
|
|
24
|
+
"prepublishOnly": "node scripts/prepublish.js",
|
|
25
|
+
"postinstall": "node postinstall.js",
|
|
26
|
+
"test": "bun test",
|
|
27
|
+
"test:watch": "bun test --watch"
|
|
21
28
|
},
|
|
22
29
|
"dependencies": {
|
|
23
|
-
"@
|
|
24
|
-
"
|
|
25
|
-
"bobs-workshop": "^0.2.0",
|
|
26
|
-
"chokidar": "^4.0.3",
|
|
27
|
-
"express": "^4.x",
|
|
28
|
-
"fs-extra": "^11.x",
|
|
29
|
-
"glob": "^10.3.10",
|
|
30
|
-
"lru-cache": "^10.1.0",
|
|
31
|
-
"minimatch": "^9.0.3",
|
|
32
|
-
"multer": "^2.0.2",
|
|
33
|
-
"simple-git": "^3.x",
|
|
34
|
-
"ts-morph": "^23.0.0",
|
|
35
|
-
"uuid": "^9.x",
|
|
36
|
-
"zod": "^3.x",
|
|
37
|
-
"@vscode/ripgrep": "^1.15.14"
|
|
30
|
+
"@opencode-ai/plugin": "^1.1.36",
|
|
31
|
+
"jsonc-parser": "^3.2.1"
|
|
38
32
|
},
|
|
39
33
|
"devDependencies": {
|
|
40
|
-
"@types/
|
|
41
|
-
"
|
|
42
|
-
"@types/fs-extra": "^11.0.4",
|
|
43
|
-
"@types/jest": "^29.x",
|
|
44
|
-
"@types/node": "^20.x",
|
|
45
|
-
"@types/uuid": "^10.0.0",
|
|
46
|
-
"eslint": "^8.x",
|
|
47
|
-
"jest": "^29.x",
|
|
48
|
-
"ts-jest": "^29.x",
|
|
49
|
-
"tsx": "^4.x",
|
|
50
|
-
"typescript": "^5.x"
|
|
34
|
+
"@types/node": "^20.0.0",
|
|
35
|
+
"typescript": "^5.7.2"
|
|
51
36
|
},
|
|
52
37
|
"keywords": [
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"dashboard",
|
|
59
|
-
"spec-driven",
|
|
60
|
-
"development",
|
|
61
|
-
"typescript",
|
|
62
|
-
"developer-experience"
|
|
38
|
+
"opencode",
|
|
39
|
+
"plugin",
|
|
40
|
+
"agents",
|
|
41
|
+
"manual-driven",
|
|
42
|
+
"background-tasks"
|
|
63
43
|
],
|
|
64
|
-
"author": "
|
|
44
|
+
"author": "pwnk77",
|
|
65
45
|
"license": "MIT",
|
|
66
46
|
"repository": {
|
|
67
47
|
"type": "git",
|
|
68
|
-
"url": "git+https://github.com/
|
|
48
|
+
"url": "git+https://github.com/pwnk77/bobs-workshop.git"
|
|
69
49
|
},
|
|
70
|
-
"homepage": "https://github.com/your-org/bobs-workshop#readme",
|
|
71
50
|
"bugs": {
|
|
72
|
-
"url": "https://github.com/
|
|
51
|
+
"url": "https://github.com/pwnk77/bobs-workshop/issues"
|
|
73
52
|
},
|
|
74
|
-
"
|
|
75
|
-
"node": ">=18.0.0"
|
|
76
|
-
},
|
|
77
|
-
"files": [
|
|
78
|
-
"dist/**/*",
|
|
79
|
-
"bin/**/*",
|
|
80
|
-
"scripts/**/*",
|
|
81
|
-
"public/**/*",
|
|
82
|
-
"README.md",
|
|
83
|
-
"LICENSE",
|
|
84
|
-
"Claude.md"
|
|
85
|
-
]
|
|
53
|
+
"homepage": "https://github.com/pwnk77/bobs-workshop#readme"
|
|
86
54
|
}
|
package/postinstall.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* postinstall.js â runs only when this package is installed as a dependency in a repo.
|
|
3
|
+
* Skips when: npm install inside bobs-workshop itself, or global npm update (e.g. npm update -g @opencode/cli).
|
|
4
|
+
*/
|
|
5
|
+
import jsonc, { parse } from 'jsonc-parser';
|
|
6
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, cpSync, readdirSync } from 'fs';
|
|
7
|
+
import { dirname, join } from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
|
|
12
|
+
const PACKAGE_NAME = 'bobs-workshop';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Only run when bobs-workshop is installed as a dependency in this repo (npm install at repo level).
|
|
16
|
+
* Skip when: global npm update, or running from within bobs-workshop repo itself.
|
|
17
|
+
*/
|
|
18
|
+
function isInstalledAsDependencyInThisRepo() {
|
|
19
|
+
// Use INIT_CWD which npm sets to the directory where 'npm install' was invoked
|
|
20
|
+
// process.cwd() returns the package directory (node_modules/bobs-workshop/) during postinstall
|
|
21
|
+
const projectRoot = process.env.INIT_CWD || process.cwd();
|
|
22
|
+
const pkgPath = join(projectRoot, 'package.json');
|
|
23
|
+
if (!existsSync(pkgPath)) return false;
|
|
24
|
+
let pkg;
|
|
25
|
+
try {
|
|
26
|
+
pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
31
|
+
return typeof deps[PACKAGE_NAME] === 'string';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function checkConflicts(opencodeDir) {
|
|
35
|
+
const conflicts = [];
|
|
36
|
+
|
|
37
|
+
const agentsDir = join(opencodeDir, 'agents');
|
|
38
|
+
if (existsSync(agentsDir)) {
|
|
39
|
+
const ourAgents = ['alice.md', 'bob.md', 'bob-rev.md', 'trace.md', 'bob-send.md'];
|
|
40
|
+
const existingAgents = readdirSync(agentsDir).filter(f => f.endsWith('.md'));
|
|
41
|
+
|
|
42
|
+
existingAgents.forEach(agent => {
|
|
43
|
+
if (ourAgents.includes(agent)) {
|
|
44
|
+
conflicts.push({ path: join(agentsDir, agent), type: 'agent' });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const skillsDir = join(opencodeDir, 'skills');
|
|
50
|
+
if (existsSync(skillsDir)) {
|
|
51
|
+
const skillNames = ['architecture', 'exploration', 'api-patterns',
|
|
52
|
+
'brainstorming', 'clean-code', 'code-review-checklist',
|
|
53
|
+
'database-design', 'frontend-ui-ux', 'git-master',
|
|
54
|
+
'performance', 'plan-writing', 'security', 'simplification',
|
|
55
|
+
'systematic-debugging', 'testing-patterns', 'verification'];
|
|
56
|
+
|
|
57
|
+
skillNames.forEach(skill => {
|
|
58
|
+
const skillPath = join(skillsDir, skill);
|
|
59
|
+
if (existsSync(skillPath)) {
|
|
60
|
+
conflicts.push({ path: skillPath, type: 'skill' });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return conflicts;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function postinstall() {
|
|
69
|
+
if (!isInstalledAsDependencyInThisRepo()) {
|
|
70
|
+
return; // Not a repo that depends on bobs-workshop (e.g. global update or bobs-workshop repo itself)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Use INIT_CWD to get the actual project directory where npm install was run
|
|
74
|
+
const projectRoot = process.env.INIT_CWD || process.cwd();
|
|
75
|
+
const opencodeDir = join(projectRoot, '.opencode');
|
|
76
|
+
|
|
77
|
+
console.log('đ§ Installing bobs-workshop...');
|
|
78
|
+
|
|
79
|
+
const conflicts = checkConflicts(opencodeDir);
|
|
80
|
+
if (conflicts.length > 0) {
|
|
81
|
+
console.error('â Installation aborted: Conflicts detected');
|
|
82
|
+
console.error('');
|
|
83
|
+
console.error('The following items already exist and would be overwritten:');
|
|
84
|
+
conflicts.forEach(c => console.error(` - ${c.path} (${c.type})`));
|
|
85
|
+
console.error('');
|
|
86
|
+
console.error('Please rename these items to resolve conflicts:');
|
|
87
|
+
console.error(' Agents: Rename .opencode/agents/<name>.md files');
|
|
88
|
+
console.error(' Skills: Rename .opencode/skills/<name>/SKILL.md directories');
|
|
89
|
+
console.error('');
|
|
90
|
+
console.error('Run npm install again after resolving conflicts.');
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const dirsToCreate = [
|
|
95
|
+
join(opencodeDir, 'plugins/bobs-workshop'),
|
|
96
|
+
join(opencodeDir, 'agents'),
|
|
97
|
+
join(opencodeDir, 'tools/bobs-workshop'),
|
|
98
|
+
join(projectRoot, 'manuals')
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
dirsToCreate.forEach(dir => {
|
|
102
|
+
if (!existsSync(dir)) {
|
|
103
|
+
mkdirSync(dir, { recursive: true });
|
|
104
|
+
console.log(`â
Created: ${dir}`);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const pluginSrc = join(__dirname, 'dist/plugins/bobs-workshop.js');
|
|
109
|
+
const pluginDest = join(opencodeDir, 'plugins/bobs-workshop/plugin.js');
|
|
110
|
+
|
|
111
|
+
if (existsSync(pluginSrc)) {
|
|
112
|
+
copyFileSync(pluginSrc, pluginDest);
|
|
113
|
+
console.log(`â
Copied plugin to: ${pluginDest}`);
|
|
114
|
+
} else {
|
|
115
|
+
console.warn('â ī¸ Plugin file not found. Did you run npm run build?');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const agentSrcDir = join(__dirname, 'src/agents');
|
|
119
|
+
const agentDestDir = join(opencodeDir, 'agents');
|
|
120
|
+
|
|
121
|
+
if (existsSync(agentSrcDir)) {
|
|
122
|
+
cpSync(agentSrcDir, agentDestDir, { recursive: true });
|
|
123
|
+
console.log('â
Copied agent definitions');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const skillSrcDir = join(__dirname, 'src/skills');
|
|
127
|
+
const skillDestDir = join(opencodeDir, 'skills');
|
|
128
|
+
|
|
129
|
+
if (existsSync(skillSrcDir)) {
|
|
130
|
+
cpSync(skillSrcDir, skillDestDir, { recursive: true });
|
|
131
|
+
console.log('â
Copied skill definitions');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const toolsSrcDir = join(__dirname, 'dist/tools');
|
|
135
|
+
const toolsDestDir = join(opencodeDir, 'tools/bobs-workshop');
|
|
136
|
+
|
|
137
|
+
if (existsSync(toolsSrcDir)) {
|
|
138
|
+
cpSync(toolsSrcDir, toolsDestDir, { recursive: true });
|
|
139
|
+
console.log('â
Copied tool definitions');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const configPath = join(opencodeDir, 'opencode.jsonc');
|
|
143
|
+
const configContent = existsSync(configPath)
|
|
144
|
+
? readFileSync(configPath, 'utf8')
|
|
145
|
+
: '{}';
|
|
146
|
+
|
|
147
|
+
let config;
|
|
148
|
+
try {
|
|
149
|
+
config = parse(configContent, { allowTrailingComma: true });
|
|
150
|
+
} catch (err) {
|
|
151
|
+
console.warn(`â ī¸ Could not parse opencode.jsonc: ${err.message}`);
|
|
152
|
+
config = {};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const agentsConfig = JSON.parse(readFileSync(
|
|
156
|
+
join(__dirname, 'config/agents.json'), 'utf8'
|
|
157
|
+
));
|
|
158
|
+
|
|
159
|
+
if (!config.agent) config.agent = {};
|
|
160
|
+
let agentsAdded = 0;
|
|
161
|
+
|
|
162
|
+
Object.entries(agentsConfig).forEach(([name, agentDef]) => {
|
|
163
|
+
if (!config.agent[name]) {
|
|
164
|
+
config.agent[name] = agentDef;
|
|
165
|
+
console.log(`â
Added agent: ${name}`);
|
|
166
|
+
agentsAdded++;
|
|
167
|
+
} else {
|
|
168
|
+
console.log(`âī¸ Agent ${name} already exists, skipping`);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
if (agentsAdded === 0) {
|
|
173
|
+
console.log('âšī¸ All agents already configured');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const newConfig = JSON.stringify(config, null, 2);
|
|
177
|
+
writeFileSync(configPath, newConfig);
|
|
178
|
+
|
|
179
|
+
console.log('â
bobs-workshop installed successfully!');
|
|
180
|
+
console.log('');
|
|
181
|
+
console.log('Next steps:');
|
|
182
|
+
console.log(' 1. Review your agents in .opencode/opencode.jsonc');
|
|
183
|
+
console.log(' 2. Create your first MANUAL: manuals/MAN-260128-feature.md');
|
|
184
|
+
console.log(' 3. Start using background_agent, manual_update, verify_manual tools');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
postinstall();
|
|
189
|
+
} catch (error) {
|
|
190
|
+
console.error('â Installation failed:', error.message);
|
|
191
|
+
console.error(error.stack);
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|