opencode-cc10x 6.0.21
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 +21 -0
- package/README.md +283 -0
- package/bun.lock +20 -0
- package/dist/agents.d.ts +3 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +483 -0
- package/dist/agents.js.map +1 -0
- package/dist/compatibility-layer.d.ts +18 -0
- package/dist/compatibility-layer.d.ts.map +1 -0
- package/dist/compatibility-layer.js +150 -0
- package/dist/compatibility-layer.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1459 -0
- package/dist/index.js.map +1 -0
- package/dist/intent-detection.d.ts +14 -0
- package/dist/intent-detection.d.ts.map +1 -0
- package/dist/intent-detection.js +121 -0
- package/dist/intent-detection.js.map +1 -0
- package/dist/memory.d.ts +41 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +330 -0
- package/dist/memory.js.map +1 -0
- package/dist/router.d.ts +15 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +208 -0
- package/dist/router.js.map +1 -0
- package/dist/skills.d.ts +3 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +2790 -0
- package/dist/skills.js.map +1 -0
- package/dist/task-orchestrator.d.ts +46 -0
- package/dist/task-orchestrator.d.ts.map +1 -0
- package/dist/task-orchestrator.js +262 -0
- package/dist/task-orchestrator.js.map +1 -0
- package/dist/workflow-executor.d.ts +29 -0
- package/dist/workflow-executor.d.ts.map +1 -0
- package/dist/workflow-executor.js +414 -0
- package/dist/workflow-executor.js.map +1 -0
- package/install-from-github.mjs +152 -0
- package/install-from-github.sh +106 -0
- package/install.sh +295 -0
- package/opencode.json +118 -0
- package/package.json +41 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
import { taskOrchestrator } from './task-orchestrator';
|
|
2
|
+
import { memoryManager } from './memory';
|
|
3
|
+
export class WorkflowExecutor {
|
|
4
|
+
async executeWorkflow(input, options) {
|
|
5
|
+
const { intent, userRequest, memory, workflowTaskId, activeForm } = options;
|
|
6
|
+
console.log(`🚀 Executing ${intent} workflow for: "${userRequest}"`);
|
|
7
|
+
try {
|
|
8
|
+
switch (intent) {
|
|
9
|
+
case 'BUILD':
|
|
10
|
+
await this.executeBuildWorkflow(input, { userRequest, memory, workflowTaskId });
|
|
11
|
+
break;
|
|
12
|
+
case 'DEBUG':
|
|
13
|
+
await this.executeDebugWorkflow(input, { userRequest, memory, workflowTaskId });
|
|
14
|
+
break;
|
|
15
|
+
case 'REVIEW':
|
|
16
|
+
await this.executeReviewWorkflow(input, { userRequest, memory, workflowTaskId });
|
|
17
|
+
break;
|
|
18
|
+
case 'PLAN':
|
|
19
|
+
await this.executePlanWorkflow(input, { userRequest, memory, workflowTaskId });
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
// Final memory update (workflow-final)
|
|
23
|
+
await this.executeMemoryUpdate(input, workflowTaskId);
|
|
24
|
+
// Mark workflow complete
|
|
25
|
+
await taskOrchestrator.completeWorkflow(workflowTaskId);
|
|
26
|
+
console.log(`✅ ${intent} workflow completed successfully`);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
console.error(`❌ ${intent} workflow failed:`, error);
|
|
30
|
+
await this.handleWorkflowFailure(input, workflowTaskId, error);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async executeBuildWorkflow(input, options) {
|
|
34
|
+
const { userRequest, memory, workflowTaskId } = options;
|
|
35
|
+
// Step 1: component-builder (TDD)
|
|
36
|
+
await this.invokeAgent(input, {
|
|
37
|
+
agentName: 'component-builder',
|
|
38
|
+
taskId: `${workflowTaskId}-builder`,
|
|
39
|
+
prompt: this.buildBuilderPrompt(userRequest, memory),
|
|
40
|
+
waitForCompletion: true
|
|
41
|
+
});
|
|
42
|
+
// Step 2: Parallel execution - code-reviewer and silent-failure-hunter
|
|
43
|
+
await this.invokeParallelAgents(input, {
|
|
44
|
+
agentNames: ['code-reviewer', 'silent-failure-hunter'],
|
|
45
|
+
baseTaskId: workflowTaskId,
|
|
46
|
+
sharedPrompt: this.buildReviewAndHuntPrompt(userRequest, memory),
|
|
47
|
+
waitForCompletion: true
|
|
48
|
+
});
|
|
49
|
+
// Step 3: integration-verifier
|
|
50
|
+
await this.invokeAgent(input, {
|
|
51
|
+
agentName: 'integration-verifier',
|
|
52
|
+
taskId: `${workflowTaskId}-verifier`,
|
|
53
|
+
prompt: await this.buildVerifierPrompt(input, workflowTaskId),
|
|
54
|
+
waitForCompletion: true
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async executeDebugWorkflow(input, options) {
|
|
58
|
+
const { userRequest, memory, workflowTaskId } = options;
|
|
59
|
+
// Step 1: bug-investigator (log-first)
|
|
60
|
+
await this.invokeAgent(input, {
|
|
61
|
+
agentName: 'bug-investigator',
|
|
62
|
+
taskId: `${workflowTaskId}-investigator`,
|
|
63
|
+
prompt: this.buildDebugPrompt(userRequest, memory),
|
|
64
|
+
waitForCompletion: true
|
|
65
|
+
});
|
|
66
|
+
// Step 2: code-reviewer (validate fix)
|
|
67
|
+
await this.invokeAgent(input, {
|
|
68
|
+
agentName: 'code-reviewer',
|
|
69
|
+
taskId: `${workflowTaskId}-reviewer`,
|
|
70
|
+
prompt: this.buildReviewFixPrompt(userRequest, memory),
|
|
71
|
+
waitForCompletion: true
|
|
72
|
+
});
|
|
73
|
+
// Step 3: integration-verifier
|
|
74
|
+
await this.invokeAgent(input, {
|
|
75
|
+
agentName: 'integration-verifier',
|
|
76
|
+
taskId: `${workflowTaskId}-verifier`,
|
|
77
|
+
prompt: await this.buildVerifierPrompt(input, workflowTaskId),
|
|
78
|
+
waitForCompletion: true
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
async executeReviewWorkflow(input, options) {
|
|
82
|
+
const { userRequest, memory, workflowTaskId } = options;
|
|
83
|
+
// Single step: code-reviewer
|
|
84
|
+
await this.invokeAgent(input, {
|
|
85
|
+
agentName: 'code-reviewer',
|
|
86
|
+
taskId: `${workflowTaskId}-reviewer`,
|
|
87
|
+
prompt: this.buildReviewPrompt(userRequest, memory),
|
|
88
|
+
waitForCompletion: true
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
async executePlanWorkflow(input, options) {
|
|
92
|
+
const { userRequest, memory, workflowTaskId } = options;
|
|
93
|
+
// Single step: planner
|
|
94
|
+
await this.invokeAgent(input, {
|
|
95
|
+
agentName: 'planner',
|
|
96
|
+
taskId: `${workflowTaskId}-planner`,
|
|
97
|
+
prompt: this.buildPlanPrompt(userRequest, memory),
|
|
98
|
+
waitForCompletion: true
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async executeMemoryUpdate(input, workflowTaskId) {
|
|
102
|
+
// This is the workflow-final memory persistence
|
|
103
|
+
// The main assistant (router) handles this
|
|
104
|
+
console.log('💾 Executing workflow-final memory update');
|
|
105
|
+
// Persist any accumulated memory notes
|
|
106
|
+
await memoryManager.persistAccumulatedNotes(input);
|
|
107
|
+
// Update progress.md with completion
|
|
108
|
+
await memoryManager.updateProgress(input, {
|
|
109
|
+
completed: [`Workflow ${workflowTaskId} completed with verification`]
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
async invokeAgent(input, options) {
|
|
113
|
+
const { agentName, taskId, prompt, waitForCompletion } = options;
|
|
114
|
+
console.log(`🤖 Invoking agent: ${agentName} (task: ${taskId})`);
|
|
115
|
+
try {
|
|
116
|
+
// Update task status to in_progress
|
|
117
|
+
await taskOrchestrator.updateTaskStatus(input, taskId, 'in_progress');
|
|
118
|
+
// Invoke the agent using OpenCode's agent system
|
|
119
|
+
const result = await input.client.app.agent.invoke(agentName, {
|
|
120
|
+
prompt: prompt,
|
|
121
|
+
taskId: taskId
|
|
122
|
+
});
|
|
123
|
+
// Update task status to completed
|
|
124
|
+
await taskOrchestrator.updateTaskStatus(input, taskId, 'completed', result);
|
|
125
|
+
console.log(`✅ Agent ${agentName} completed`);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
console.error(`❌ Agent ${agentName} failed:`, error);
|
|
129
|
+
await taskOrchestrator.updateTaskStatus(input, taskId, 'blocked');
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async invokeParallelAgents(input, options) {
|
|
134
|
+
const { agentNames, baseTaskId, sharedPrompt, waitForCompletion } = options;
|
|
135
|
+
console.log(`⚡ Invoking parallel agents: ${agentNames.join(', ')}`);
|
|
136
|
+
// Create promises for all agents
|
|
137
|
+
const agentPromises = agentNames.map(agentName => this.invokeAgent(input, {
|
|
138
|
+
agentName,
|
|
139
|
+
taskId: `${baseTaskId}-${agentName.split('-').pop()}`,
|
|
140
|
+
prompt: sharedPrompt,
|
|
141
|
+
waitForCompletion: true // Each agent waits for its own completion
|
|
142
|
+
}));
|
|
143
|
+
// Wait for all to complete
|
|
144
|
+
await Promise.all(agentPromises);
|
|
145
|
+
}
|
|
146
|
+
buildBuilderPrompt(userRequest, memory) {
|
|
147
|
+
return `
|
|
148
|
+
# Component Builder (TDD)
|
|
149
|
+
|
|
150
|
+
## User Request
|
|
151
|
+
${userRequest}
|
|
152
|
+
|
|
153
|
+
## Memory Context
|
|
154
|
+
${this.formatMemoryContext(memory)}
|
|
155
|
+
|
|
156
|
+
## Instructions
|
|
157
|
+
Follow the TDD cycle strictly:
|
|
158
|
+
1. RED: Write a failing test first (must exit with code 1)
|
|
159
|
+
2. GREEN: Write minimal code to pass (must exit with code 0)
|
|
160
|
+
3. REFACTOR: Clean up while keeping tests green
|
|
161
|
+
4. VERIFY: All tests must pass
|
|
162
|
+
|
|
163
|
+
## Pre-Implementation Checklist
|
|
164
|
+
- API: CORS? Auth middleware? Input validation? Rate limiting?
|
|
165
|
+
- UI: Loading states? Error boundaries? Accessibility?
|
|
166
|
+
- DB: Migrations? N+1 queries? Transactions?
|
|
167
|
+
- All: Edge cases listed? Error handling planned?
|
|
168
|
+
|
|
169
|
+
## Output Requirements
|
|
170
|
+
- Provide TDD evidence with exact commands and exit codes
|
|
171
|
+
- Include Dev Journal with decisions and assumptions
|
|
172
|
+
- Follow the Router Contract format exactly
|
|
173
|
+
- Update memory via Edit tool (permission-free)
|
|
174
|
+
`.trim();
|
|
175
|
+
}
|
|
176
|
+
buildReviewAndHuntPrompt(userRequest, memory) {
|
|
177
|
+
return `
|
|
178
|
+
# Code Review & Silent Failure Hunt
|
|
179
|
+
|
|
180
|
+
## User Request
|
|
181
|
+
${userRequest}
|
|
182
|
+
|
|
183
|
+
## Memory Context
|
|
184
|
+
${this.formatMemoryContext(memory)}
|
|
185
|
+
|
|
186
|
+
## Instructions
|
|
187
|
+
Analyze the implementation from the component-builder. Focus on:
|
|
188
|
+
|
|
189
|
+
### Code Reviewer Focus
|
|
190
|
+
- Code quality and best practices
|
|
191
|
+
- Security vulnerabilities (OWASP top 10)
|
|
192
|
+
- Performance implications (N+1 queries, etc.)
|
|
193
|
+
- Maintainability and readability
|
|
194
|
+
- API design and contracts
|
|
195
|
+
|
|
196
|
+
### Silent Failure Hunter Focus
|
|
197
|
+
- Empty catch blocks
|
|
198
|
+
- Missing error handling
|
|
199
|
+
- Unvalidated inputs
|
|
200
|
+
- Resource leaks
|
|
201
|
+
- Race conditions
|
|
202
|
+
- Edge cases not covered by tests
|
|
203
|
+
|
|
204
|
+
## Confidence Scoring
|
|
205
|
+
Only report issues with ≥80% confidence. Provide file:line citations.
|
|
206
|
+
|
|
207
|
+
## Output Requirements
|
|
208
|
+
- Critical Issues section with confidence scores
|
|
209
|
+
- Verdict: APPROVED or CHANGES REQUESTED
|
|
210
|
+
- Include "### Memory Notes" section for workflow persistence
|
|
211
|
+
`.trim();
|
|
212
|
+
}
|
|
213
|
+
async buildVerifierPrompt(input, workflowTaskId) {
|
|
214
|
+
// Collect findings from previous agents
|
|
215
|
+
const reviewerTaskId = `${workflowTaskId}-reviewer`;
|
|
216
|
+
const hunterTaskId = `${workflowTaskId}-hunter`;
|
|
217
|
+
// In a full implementation, would fetch task results
|
|
218
|
+
// For now, provide template
|
|
219
|
+
return `
|
|
220
|
+
# Integration Verifier
|
|
221
|
+
|
|
222
|
+
## Task Context
|
|
223
|
+
- Workflow: ${workflowTaskId}
|
|
224
|
+
- Previous agents: code-reviewer, silent-failure-hunter
|
|
225
|
+
|
|
226
|
+
## Instructions
|
|
227
|
+
Verify the implementation considering ALL findings from previous agents.
|
|
228
|
+
|
|
229
|
+
### Verification Checklist
|
|
230
|
+
- [ ] All tests pass (exit code 0)
|
|
231
|
+
- [ ] No critical security issues
|
|
232
|
+
- [ ] No silent failures detected
|
|
233
|
+
- [ ] Error handling is comprehensive
|
|
234
|
+
- [ ] Performance is acceptable
|
|
235
|
+
- [ ] Code follows project patterns
|
|
236
|
+
|
|
237
|
+
### Critical Issues
|
|
238
|
+
Any CRITICAL issues should block PASS verdict.
|
|
239
|
+
|
|
240
|
+
## Output Requirements
|
|
241
|
+
- Verdict: PASS or FAIL with reasoning
|
|
242
|
+
- Include verification evidence (commands + exit codes)
|
|
243
|
+
- Provide "### Memory Notes" section
|
|
244
|
+
`.trim();
|
|
245
|
+
}
|
|
246
|
+
buildDebugPrompt(userRequest, memory) {
|
|
247
|
+
return `
|
|
248
|
+
# Bug Investigator (LOG FIRST)
|
|
249
|
+
|
|
250
|
+
## User Request
|
|
251
|
+
${userRequest}
|
|
252
|
+
|
|
253
|
+
## Memory Context
|
|
254
|
+
${this.formatMemoryContext(memory)}
|
|
255
|
+
|
|
256
|
+
## Iron Law: LOG FIRST
|
|
257
|
+
Never fix without evidence. Follow this process:
|
|
258
|
+
|
|
259
|
+
1. **Reproduce** - Get exact error conditions
|
|
260
|
+
2. **Log** - Gather all relevant logs, stack traces, system state
|
|
261
|
+
3. **Analyze** - Root cause analysis using debugging patterns
|
|
262
|
+
4. **Fix** - Minimal change to resolve
|
|
263
|
+
5. **Verify** - Confirm fix works and doesn't break other things
|
|
264
|
+
|
|
265
|
+
## Common Debugging Patterns
|
|
266
|
+
- Check recent changes (git diff)
|
|
267
|
+
- Examine error logs and stack traces
|
|
268
|
+
- Validate assumptions with print statements
|
|
269
|
+
- Isolate the failing component
|
|
270
|
+
- Check for null/undefined values
|
|
271
|
+
- Verify data types and formats
|
|
272
|
+
|
|
273
|
+
## Output Requirements
|
|
274
|
+
- Evidence before any fix proposal
|
|
275
|
+
- Root cause analysis with confidence
|
|
276
|
+
- Minimal fix with verification
|
|
277
|
+
- Update memory with common gotchas if discovered
|
|
278
|
+
`.trim();
|
|
279
|
+
}
|
|
280
|
+
buildReviewFixPrompt(userRequest, memory) {
|
|
281
|
+
return `
|
|
282
|
+
# Code Reviewer (Fix Validation)
|
|
283
|
+
|
|
284
|
+
## User Request
|
|
285
|
+
${userRequest}
|
|
286
|
+
|
|
287
|
+
## Memory Context
|
|
288
|
+
${this.formatMemoryContext(memory)}
|
|
289
|
+
|
|
290
|
+
## Instructions
|
|
291
|
+
Review the bug fix from bug-investigator. Focus on:
|
|
292
|
+
|
|
293
|
+
- Fix correctness: Does it actually solve the problem?
|
|
294
|
+
- Side effects: Does it introduce new issues?
|
|
295
|
+
- Code quality: Is the fix clean and maintainable?
|
|
296
|
+
- Testing: Are there tests for the fix?
|
|
297
|
+
- Security: Does the fix introduce vulnerabilities?
|
|
298
|
+
|
|
299
|
+
## Confidence Scoring
|
|
300
|
+
Only report issues with ≥80% confidence.
|
|
301
|
+
|
|
302
|
+
## Output Requirements
|
|
303
|
+
- Verdict: APPROVED or CHANGES REQUESTED
|
|
304
|
+
- Critical Issues with file:line citations
|
|
305
|
+
- Include "### Memory Notes" section
|
|
306
|
+
`.trim();
|
|
307
|
+
}
|
|
308
|
+
buildReviewPrompt(userRequest, memory) {
|
|
309
|
+
return `
|
|
310
|
+
# Code Reviewer (Comprehensive Review)
|
|
311
|
+
|
|
312
|
+
## User Request
|
|
313
|
+
${userRequest}
|
|
314
|
+
|
|
315
|
+
## Memory Context
|
|
316
|
+
${this.formatMemoryContext(memory)}
|
|
317
|
+
|
|
318
|
+
## Instructions
|
|
319
|
+
Perform comprehensive code review with 80%+ confidence threshold.
|
|
320
|
+
|
|
321
|
+
### Review Dimensions
|
|
322
|
+
- **Security**: OWASP top 10, input validation, authentication/authorization
|
|
323
|
+
- **Performance**: Algorithm efficiency, database queries, memory usage
|
|
324
|
+
- **Maintainability**: Code structure, naming, documentation
|
|
325
|
+
- **Reliability**: Error handling, edge cases, resource management
|
|
326
|
+
- **Testing**: Test coverage, test quality, edge case coverage
|
|
327
|
+
|
|
328
|
+
## Output Requirements
|
|
329
|
+
- Only report issues with ≥80% confidence
|
|
330
|
+
- File:line citations for every finding
|
|
331
|
+
- Verdict: APPROVED or CHANGES REQUESTED
|
|
332
|
+
- Include "### Memory Notes" section
|
|
333
|
+
`.trim();
|
|
334
|
+
}
|
|
335
|
+
buildPlanPrompt(userRequest, memory) {
|
|
336
|
+
return `
|
|
337
|
+
# Planner (Comprehensive Planning)
|
|
338
|
+
|
|
339
|
+
## User Request
|
|
340
|
+
${userRequest}
|
|
341
|
+
|
|
342
|
+
## Memory Context
|
|
343
|
+
${this.formatMemoryContext(memory)}
|
|
344
|
+
|
|
345
|
+
## Planning Requirements
|
|
346
|
+
Create a comprehensive plan that includes:
|
|
347
|
+
|
|
348
|
+
### 1. Analysis
|
|
349
|
+
- Current state assessment
|
|
350
|
+
- Requirements clarification
|
|
351
|
+
- Constraints and dependencies
|
|
352
|
+
- Risk assessment
|
|
353
|
+
|
|
354
|
+
### 2. Architecture
|
|
355
|
+
- System design decisions
|
|
356
|
+
- Technology choices with rationale
|
|
357
|
+
- API design (if applicable)
|
|
358
|
+
- Data model (if applicable)
|
|
359
|
+
|
|
360
|
+
### 3. Implementation Plan
|
|
361
|
+
- Phased approach with milestones
|
|
362
|
+
- Specific files to create/modify
|
|
363
|
+
- Testing strategy
|
|
364
|
+
- Rollback plan
|
|
365
|
+
|
|
366
|
+
### 4. Research Needs
|
|
367
|
+
- External packages to investigate
|
|
368
|
+
- Best practices to research
|
|
369
|
+
- Alternatives to evaluate
|
|
370
|
+
|
|
371
|
+
## Output Requirements
|
|
372
|
+
- Save plan to docs/plans/YYYY-MM-DD-<topic>-plan.md
|
|
373
|
+
- Update activeContext.md with plan reference
|
|
374
|
+
- Include research phase if needed (github-research skill)
|
|
375
|
+
- Provide clear next steps
|
|
376
|
+
`.trim();
|
|
377
|
+
}
|
|
378
|
+
formatMemoryContext(memory) {
|
|
379
|
+
if (!memory)
|
|
380
|
+
return 'No memory available';
|
|
381
|
+
const parts = [];
|
|
382
|
+
if (memory.activeContext) {
|
|
383
|
+
const focusMatch = memory.activeContext.match(/## Current Focus\n([\s\S]*?)(?=\n##|\n$)/);
|
|
384
|
+
if (focusMatch) {
|
|
385
|
+
parts.push(`Current Focus: ${focusMatch[1].trim()}`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (memory.patterns) {
|
|
389
|
+
const gotchasMatch = memory.patterns.match(/## Common Gotchas\n([\s\S]*?)(?=\n##|\n$)/);
|
|
390
|
+
if (gotchasMatch) {
|
|
391
|
+
parts.push(`Common Gotchas: ${gotchasMatch[1].trim().substring(0, 200)}...`);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (memory.progress) {
|
|
395
|
+
const completedMatch = memory.progress.match(/## Completed\n([\s\S]*?)(?=\n##|\n$)/);
|
|
396
|
+
if (completedMatch) {
|
|
397
|
+
parts.push(`Recent Completions: ${completedMatch[1].trim().substring(0, 200)}...`);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return parts.length > 0 ? parts.join('\n') : 'Memory files empty or not loaded';
|
|
401
|
+
}
|
|
402
|
+
async handleWorkflowFailure(input, workflowTaskId, error) {
|
|
403
|
+
console.error(`Workflow ${workflowTaskId} failed:`, error);
|
|
404
|
+
// Update memory with failure
|
|
405
|
+
await memoryManager.updateActiveContext(input, {
|
|
406
|
+
recentChanges: [`Workflow ${workflowTaskId} failed: ${error.message}`],
|
|
407
|
+
blockers: [`Workflow failure: ${error.message}`]
|
|
408
|
+
});
|
|
409
|
+
// Could create TODO task for remediation
|
|
410
|
+
// This would use OpenCode's task system
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
export const workflowExecutor = new WorkflowExecutor();
|
|
414
|
+
//# sourceMappingURL=workflow-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-executor.js","sourceRoot":"","sources":["../src/workflow-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { mkdtempSync, rmSync, mkdirSync, existsSync, readFileSync, writeFileSync, copyFileSync, readdirSync, statSync } from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { spawnSync } from "node:child_process";
|
|
8
|
+
|
|
9
|
+
const REPO = process.env.CC10X_REPO || "Chaim12345/cc10x";
|
|
10
|
+
const REF = process.env.CC10X_REF || "main";
|
|
11
|
+
const RAW_BASE = `https://raw.githubusercontent.com/${REPO}/${REF}/project/opencode-cc10x-plugin`;
|
|
12
|
+
const TARBALL_URL = `https://codeload.github.com/${REPO}/tar.gz/${REF}`;
|
|
13
|
+
const PLUGIN_NAME = "opencode-cc10x";
|
|
14
|
+
|
|
15
|
+
function log(msg) {
|
|
16
|
+
process.stdout.write(`${msg}\n`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function fail(msg) {
|
|
20
|
+
process.stderr.write(`${msg}\n`);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function run(cmd, args, cwd = process.cwd()) {
|
|
25
|
+
const result = spawnSync(cmd, args, { cwd, stdio: "inherit", shell: process.platform === "win32" });
|
|
26
|
+
if (result.status !== 0) {
|
|
27
|
+
fail(`Command failed: ${cmd} ${args.join(" ")}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function detectConfigBase() {
|
|
32
|
+
if (process.platform === "win32") {
|
|
33
|
+
return process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
|
|
34
|
+
}
|
|
35
|
+
return process.env.XDG_CONFIG_HOME || path.join(os.homedir(), ".config");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isTempHome(home) {
|
|
39
|
+
if (!home) return false;
|
|
40
|
+
if (process.platform === "win32") {
|
|
41
|
+
const normalized = home.toLowerCase();
|
|
42
|
+
return normalized.startsWith(path.join(process.env.TEMP || "", "").toLowerCase());
|
|
43
|
+
}
|
|
44
|
+
return home.startsWith("/tmp/");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function downloadText(url) {
|
|
48
|
+
const res = await fetch(url);
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
throw new Error(`HTTP ${res.status} for ${url}`);
|
|
51
|
+
}
|
|
52
|
+
return await res.text();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function downloadFile(url, targetPath) {
|
|
56
|
+
const res = await fetch(url);
|
|
57
|
+
if (!res.ok) {
|
|
58
|
+
throw new Error(`HTTP ${res.status} for ${url}`);
|
|
59
|
+
}
|
|
60
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
61
|
+
writeFileSync(targetPath, buf);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function findPluginDir(rootDir) {
|
|
65
|
+
const stack = [rootDir];
|
|
66
|
+
while (stack.length > 0) {
|
|
67
|
+
const current = stack.pop();
|
|
68
|
+
if (!current) break;
|
|
69
|
+
if (path.basename(current) === "opencode-cc10x-plugin") return current;
|
|
70
|
+
let entries = [];
|
|
71
|
+
try {
|
|
72
|
+
entries = readdirSync(current);
|
|
73
|
+
} catch {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
for (const entry of entries) {
|
|
77
|
+
const full = path.join(current, entry);
|
|
78
|
+
try {
|
|
79
|
+
if (statSync(full).isDirectory()) {
|
|
80
|
+
stack.push(full);
|
|
81
|
+
}
|
|
82
|
+
} catch {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function upsertConfig(configFile, pluginName) {
|
|
91
|
+
let cfg = {};
|
|
92
|
+
if (existsSync(configFile)) {
|
|
93
|
+
try {
|
|
94
|
+
cfg = JSON.parse(readFileSync(configFile, "utf8"));
|
|
95
|
+
} catch {
|
|
96
|
+
cfg = {};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (!Array.isArray(cfg.plugin)) cfg.plugin = [];
|
|
100
|
+
if (!cfg.plugin.includes(pluginName)) cfg.plugin.push(pluginName);
|
|
101
|
+
if (!cfg.$schema) cfg.$schema = "https://opencode.ai/config.json";
|
|
102
|
+
writeFileSync(configFile, `${JSON.stringify(cfg, null, 2)}\n`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function main() {
|
|
106
|
+
log(`Installing ${PLUGIN_NAME} from GitHub (${REPO}@${REF})...`);
|
|
107
|
+
|
|
108
|
+
if (isTempHome(os.homedir()) && process.env.CC10X_ALLOW_TMP_HOME !== "1") {
|
|
109
|
+
fail(`Refusing to install into temporary HOME (${os.homedir()}). Set CC10X_ALLOW_TMP_HOME=1 for testing.`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const configBase = detectConfigBase();
|
|
113
|
+
const pluginDir = path.join(configBase, "opencode", "plugins");
|
|
114
|
+
const configDir = path.join(configBase, "opencode");
|
|
115
|
+
const configFile = path.join(configDir, "opencode.json");
|
|
116
|
+
const pluginFile = path.join(pluginDir, `${PLUGIN_NAME}.js`);
|
|
117
|
+
|
|
118
|
+
mkdirSync(pluginDir, { recursive: true });
|
|
119
|
+
mkdirSync(configDir, { recursive: true });
|
|
120
|
+
|
|
121
|
+
let installed = false;
|
|
122
|
+
try {
|
|
123
|
+
const source = await downloadText(`${RAW_BASE}/dist/index.js`);
|
|
124
|
+
writeFileSync(pluginFile, source);
|
|
125
|
+
log("Downloaded prebuilt plugin artifact.");
|
|
126
|
+
installed = true;
|
|
127
|
+
} catch {
|
|
128
|
+
log("Prebuilt artifact not found. Building from source...");
|
|
129
|
+
const workdir = mkdtempSync(path.join(tmpdir(), "cc10x-"));
|
|
130
|
+
try {
|
|
131
|
+
const tgzPath = path.join(workdir, "cc10x.tar.gz");
|
|
132
|
+
await downloadFile(TARBALL_URL, tgzPath);
|
|
133
|
+
run("tar", ["-xzf", tgzPath, "-C", workdir]);
|
|
134
|
+
const srcDir = findPluginDir(workdir);
|
|
135
|
+
if (!srcDir) fail("Could not locate plugin source in tarball.");
|
|
136
|
+
run("npm", ["install"], srcDir);
|
|
137
|
+
run("npm", ["run", "build"], srcDir);
|
|
138
|
+
copyFileSync(path.join(srcDir, "dist", "index.js"), pluginFile);
|
|
139
|
+
installed = true;
|
|
140
|
+
} finally {
|
|
141
|
+
rmSync(workdir, { recursive: true, force: true });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!installed) fail("Installation failed.");
|
|
146
|
+
upsertConfig(configFile, PLUGIN_NAME);
|
|
147
|
+
|
|
148
|
+
log(`Installed ${PLUGIN_NAME} to ${pluginFile}`);
|
|
149
|
+
log("Restart OpenCode to load the plugin.");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
main().catch((err) => fail(err instanceof Error ? err.message : String(err)));
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
REPO="${CC10X_REPO:-Chaim12345/cc10x}"
|
|
6
|
+
REF="${CC10X_REF:-main}"
|
|
7
|
+
RAW_BASE="https://raw.githubusercontent.com/${REPO}/${REF}/project/opencode-cc10x-plugin"
|
|
8
|
+
TARBALL_URL="https://codeload.github.com/${REPO}/tar.gz/${REF}"
|
|
9
|
+
OS_NAME="$(uname -s 2>/dev/null || echo unknown)"
|
|
10
|
+
if [[ "${OS_NAME}" == MINGW* || "${OS_NAME}" == MSYS* || "${OS_NAME}" == CYGWIN* ]]; then
|
|
11
|
+
if [[ -n "${APPDATA:-}" ]]; then
|
|
12
|
+
if command -v cygpath >/dev/null 2>&1; then
|
|
13
|
+
CONFIG_BASE="$(cygpath -u "${APPDATA}")"
|
|
14
|
+
else
|
|
15
|
+
CONFIG_BASE="${APPDATA//\\//}"
|
|
16
|
+
fi
|
|
17
|
+
else
|
|
18
|
+
CONFIG_BASE="${HOME}/AppData/Roaming"
|
|
19
|
+
fi
|
|
20
|
+
else
|
|
21
|
+
CONFIG_BASE="${XDG_CONFIG_HOME:-${HOME}/.config}"
|
|
22
|
+
fi
|
|
23
|
+
PLUGIN_DIR="${CONFIG_BASE}/opencode/plugins"
|
|
24
|
+
CONFIG_DIR="${CONFIG_BASE}/opencode"
|
|
25
|
+
CONFIG_FILE="${CONFIG_DIR}/opencode.json"
|
|
26
|
+
PLUGIN_NAME="opencode-cc10x"
|
|
27
|
+
|
|
28
|
+
echo "Installing ${PLUGIN_NAME} from GitHub (${REPO}@${REF})..."
|
|
29
|
+
|
|
30
|
+
if [[ "${HOME}" == /tmp/* ]] && [[ "${CC10X_ALLOW_TMP_HOME:-0}" != "1" ]]; then
|
|
31
|
+
echo "Refusing to install into temporary HOME (${HOME})."
|
|
32
|
+
echo "Run with your real user environment, or set CC10X_ALLOW_TMP_HOME=1 for testing."
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
if ! command -v opencode >/dev/null 2>&1; then
|
|
37
|
+
echo "OpenCode binary not found in PATH; continuing with plugin/config installation."
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
if ! command -v curl >/dev/null 2>&1; then
|
|
41
|
+
echo "curl is required for GitHub installation."
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
mkdir -p "${PLUGIN_DIR}" "${CONFIG_DIR}"
|
|
46
|
+
|
|
47
|
+
if curl -fsSL "${RAW_BASE}/dist/index.js" -o "${PLUGIN_DIR}/${PLUGIN_NAME}.js"; then
|
|
48
|
+
echo "Downloaded prebuilt plugin artifact."
|
|
49
|
+
else
|
|
50
|
+
echo "Prebuilt artifact not found. Building from source..."
|
|
51
|
+
if ! command -v npm >/dev/null 2>&1; then
|
|
52
|
+
echo "npm is required to build from source."
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
WORKDIR="$(mktemp -d)"
|
|
56
|
+
curl -fsSL "${TARBALL_URL}" -o "${WORKDIR}/cc10x.tar.gz"
|
|
57
|
+
tar -xzf "${WORKDIR}/cc10x.tar.gz" -C "${WORKDIR}"
|
|
58
|
+
SRC_DIR="$(find "${WORKDIR}" -maxdepth 5 -type d -name 'opencode-cc10x-plugin' | head -n 1)"
|
|
59
|
+
if [ -z "${SRC_DIR}" ]; then
|
|
60
|
+
echo "Could not locate plugin source in tarball."
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
(cd "${SRC_DIR}" && npm install && npm run build)
|
|
64
|
+
cp "${SRC_DIR}/dist/index.js" "${PLUGIN_DIR}/${PLUGIN_NAME}.js"
|
|
65
|
+
rm -rf "${WORKDIR}"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
if command -v node >/dev/null 2>&1; then
|
|
69
|
+
CONFIG_FILE="${CONFIG_FILE}" PLUGIN_NAME="${PLUGIN_NAME}" node <<'NODE'
|
|
70
|
+
const fs = require('fs');
|
|
71
|
+
const path = require('path');
|
|
72
|
+
|
|
73
|
+
const configFile = process.env.CONFIG_FILE;
|
|
74
|
+
const pluginName = process.env.PLUGIN_NAME;
|
|
75
|
+
|
|
76
|
+
let cfg = {};
|
|
77
|
+
if (fs.existsSync(configFile)) {
|
|
78
|
+
try {
|
|
79
|
+
cfg = JSON.parse(fs.readFileSync(configFile, 'utf8'));
|
|
80
|
+
} catch {
|
|
81
|
+
cfg = {};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!Array.isArray(cfg.plugin)) cfg.plugin = [];
|
|
86
|
+
if (!cfg.plugin.includes(pluginName)) cfg.plugin.push(pluginName);
|
|
87
|
+
if (!cfg.$schema) cfg.$schema = 'https://opencode.ai/config.json';
|
|
88
|
+
|
|
89
|
+
fs.writeFileSync(configFile, JSON.stringify(cfg, null, 2) + '\n');
|
|
90
|
+
NODE
|
|
91
|
+
else
|
|
92
|
+
if [ ! -f "${CONFIG_FILE}" ]; then
|
|
93
|
+
cat > "${CONFIG_FILE}" <<EOF
|
|
94
|
+
{
|
|
95
|
+
"\$schema": "https://opencode.ai/config.json",
|
|
96
|
+
"plugin": ["${PLUGIN_NAME}"]
|
|
97
|
+
}
|
|
98
|
+
EOF
|
|
99
|
+
elif ! grep -q "\"${PLUGIN_NAME}\"" "${CONFIG_FILE}"; then
|
|
100
|
+
echo "Plugin installed, but ${PLUGIN_NAME} was not added to ${CONFIG_FILE} automatically."
|
|
101
|
+
echo "Please add it manually under the \"plugin\" array."
|
|
102
|
+
fi
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
echo "Installed ${PLUGIN_NAME} to ${PLUGIN_DIR}/${PLUGIN_NAME}.js"
|
|
106
|
+
echo "Restart OpenCode to load the plugin."
|