loopwork 0.3.0
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/CHANGELOG.md +52 -0
- package/README.md +528 -0
- package/bin/loopwork +0 -0
- package/examples/README.md +70 -0
- package/examples/basic-json-backend/.specs/tasks/TASK-001.md +22 -0
- package/examples/basic-json-backend/.specs/tasks/TASK-002.md +23 -0
- package/examples/basic-json-backend/.specs/tasks/TASK-003.md +37 -0
- package/examples/basic-json-backend/.specs/tasks/tasks.json +19 -0
- package/examples/basic-json-backend/README.md +32 -0
- package/examples/basic-json-backend/TESTING.md +184 -0
- package/examples/basic-json-backend/hello.test.ts +9 -0
- package/examples/basic-json-backend/hello.ts +3 -0
- package/examples/basic-json-backend/loopwork.config.js +35 -0
- package/examples/basic-json-backend/math.test.ts +29 -0
- package/examples/basic-json-backend/math.ts +3 -0
- package/examples/basic-json-backend/package.json +15 -0
- package/examples/basic-json-backend/quick-start.sh +80 -0
- package/loopwork.config.ts +164 -0
- package/package.json +26 -0
- package/src/backends/github.ts +426 -0
- package/src/backends/index.ts +86 -0
- package/src/backends/json.ts +598 -0
- package/src/backends/plugin.ts +317 -0
- package/src/backends/types.ts +19 -0
- package/src/commands/init.ts +100 -0
- package/src/commands/run.ts +365 -0
- package/src/contracts/backend.ts +127 -0
- package/src/contracts/config.ts +129 -0
- package/src/contracts/index.ts +43 -0
- package/src/contracts/plugin.ts +82 -0
- package/src/contracts/task.ts +78 -0
- package/src/core/cli.ts +275 -0
- package/src/core/config.ts +165 -0
- package/src/core/state.ts +154 -0
- package/src/core/utils.ts +125 -0
- package/src/dashboard/cli.ts +449 -0
- package/src/dashboard/index.ts +6 -0
- package/src/dashboard/kanban.tsx +226 -0
- package/src/dashboard/tui.tsx +372 -0
- package/src/index.ts +19 -0
- package/src/mcp/server.ts +451 -0
- package/src/monitor/index.ts +420 -0
- package/src/plugins/asana.ts +192 -0
- package/src/plugins/cost-tracking.ts +402 -0
- package/src/plugins/discord.ts +269 -0
- package/src/plugins/everhour.ts +335 -0
- package/src/plugins/index.ts +253 -0
- package/src/plugins/telegram/bot.ts +517 -0
- package/src/plugins/telegram/index.ts +6 -0
- package/src/plugins/telegram/notifications.ts +198 -0
- package/src/plugins/todoist.ts +261 -0
- package/test/backends.test.ts +929 -0
- package/test/cli.test.ts +145 -0
- package/test/config.test.ts +90 -0
- package/test/e2e.test.ts +458 -0
- package/test/github-tasks.test.ts +191 -0
- package/test/loopwork-config-types.test.ts +288 -0
- package/test/monitor.test.ts +123 -0
- package/test/plugins.test.ts +1175 -0
- package/test/state.test.ts +295 -0
- package/test/utils.test.ts +60 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# TASK-003: Create README Documentation
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
Write a simple README.md file for the project
|
|
5
|
+
|
|
6
|
+
## Requirements
|
|
7
|
+
- Create a `README.md` file in the project root
|
|
8
|
+
- Include a project title
|
|
9
|
+
- Add a brief description
|
|
10
|
+
- List the functions available
|
|
11
|
+
- Show usage examples
|
|
12
|
+
|
|
13
|
+
## Example Structure
|
|
14
|
+
```markdown
|
|
15
|
+
# My Project
|
|
16
|
+
|
|
17
|
+
A simple TypeScript project with basic utility functions.
|
|
18
|
+
|
|
19
|
+
## Functions
|
|
20
|
+
|
|
21
|
+
### sayHello()
|
|
22
|
+
Returns a greeting message.
|
|
23
|
+
|
|
24
|
+
### sum(a, b)
|
|
25
|
+
Adds two numbers together.
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
`npm install`
|
|
30
|
+
`npm test`
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Success Criteria
|
|
34
|
+
- README.md exists
|
|
35
|
+
- Contains all required sections
|
|
36
|
+
- Examples are clear and accurate
|
|
37
|
+
- Proper markdown formatting
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tasks": [
|
|
3
|
+
{
|
|
4
|
+
"id": "TASK-001",
|
|
5
|
+
"status": "completed",
|
|
6
|
+
"priority": "high"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"id": "TASK-002",
|
|
10
|
+
"status": "completed",
|
|
11
|
+
"priority": "medium"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"id": "TASK-003",
|
|
15
|
+
"status": "completed",
|
|
16
|
+
"priority": "low"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Basic JSON Backend
|
|
2
|
+
|
|
3
|
+
A simple TypeScript project with basic utility functions.
|
|
4
|
+
|
|
5
|
+
## Functions
|
|
6
|
+
|
|
7
|
+
### sayHello()
|
|
8
|
+
Returns a greeting message.
|
|
9
|
+
|
|
10
|
+
### sum(a, b)
|
|
11
|
+
Adds two numbers together.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Install dependencies
|
|
16
|
+
```bash
|
|
17
|
+
bun install
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Run tests
|
|
21
|
+
```bash
|
|
22
|
+
bun test
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Example
|
|
26
|
+
```typescript
|
|
27
|
+
import { sayHello } from './hello'
|
|
28
|
+
import { sum } from './math'
|
|
29
|
+
|
|
30
|
+
console.log(sayHello()) // 'Hello, World!'
|
|
31
|
+
console.log(sum(2, 3)) // 5
|
|
32
|
+
```
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Testing Guide
|
|
2
|
+
|
|
3
|
+
This document explains how to test the loopwork example.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### Option 1: Interactive Menu
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
./quick-start.sh
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Choose from:
|
|
14
|
+
1. **Dry Run** - Preview tasks without executing
|
|
15
|
+
2. **Run Loopwork** - Execute tasks with AI
|
|
16
|
+
3. **Reset tasks** - Reset all tasks to pending status
|
|
17
|
+
4. **View task details** - See task descriptions
|
|
18
|
+
|
|
19
|
+
### Option 2: Direct Commands
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Dry run (preview)
|
|
23
|
+
bun run dry-run
|
|
24
|
+
|
|
25
|
+
# Actually execute
|
|
26
|
+
bun run start
|
|
27
|
+
|
|
28
|
+
# With explicit flags
|
|
29
|
+
bun ../../src/index.ts --dry-run
|
|
30
|
+
bun ../../src/index.ts --cli claude --timeout 600
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Testing Checklist
|
|
34
|
+
|
|
35
|
+
### 1. Config Loading
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
bun ../../src/index.ts --dry-run 2>&1 | grep "CLI:"
|
|
39
|
+
# Should show: CLI: claude (from config)
|
|
40
|
+
|
|
41
|
+
bun ../../src/index.ts --dry-run 2>&1 | grep "Max Iterations:"
|
|
42
|
+
# Should show: Max Iterations: 10 (from config)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 2. Dry Run Mode
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
bun ../../src/index.ts --dry-run 2>&1 | grep "Dry Run:"
|
|
49
|
+
# Should show: Dry Run: true
|
|
50
|
+
|
|
51
|
+
bun ../../src/index.ts 2>&1 | grep "Dry Run:"
|
|
52
|
+
# Should show: Dry Run: false
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 3. Task Priority
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
bun ../../src/index.ts --dry-run 2>&1 | grep "Task:" | head -1
|
|
59
|
+
# Should show: Task: TASK-001 (high priority first)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 4. Config Override
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
bun ../../src/index.ts --cli opencode --dry-run 2>&1 | grep "CLI:"
|
|
66
|
+
# Should show: CLI: opencode (CLI arg overrides config)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Manual Testing
|
|
70
|
+
|
|
71
|
+
### Test 1: Complete Workflow
|
|
72
|
+
|
|
73
|
+
1. Reset tasks: `echo "3" | ./quick-start.sh`
|
|
74
|
+
2. Check status: `cat .specs/tasks/tasks.json`
|
|
75
|
+
3. Run dry-run: `bun run dry-run`
|
|
76
|
+
4. Verify output shows all 3 tasks
|
|
77
|
+
|
|
78
|
+
### Test 2: Task Execution
|
|
79
|
+
|
|
80
|
+
ā ļø **Warning**: This will actually execute AI commands!
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Make sure you want to run this
|
|
84
|
+
bun run start
|
|
85
|
+
|
|
86
|
+
# Monitor in another terminal
|
|
87
|
+
tail -f loopwork-runs/basic-example/*/logs/iteration-*.txt
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Test 3: State Management
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Start execution
|
|
94
|
+
bun run start
|
|
95
|
+
|
|
96
|
+
# In another terminal, send SIGINT
|
|
97
|
+
kill -INT <pid>
|
|
98
|
+
|
|
99
|
+
# Should save state and show:
|
|
100
|
+
# "State saved. Resume with: --resume"
|
|
101
|
+
|
|
102
|
+
# Resume
|
|
103
|
+
bun ../../src/index.ts --resume
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Debugging
|
|
107
|
+
|
|
108
|
+
### Enable Debug Mode
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# Method 1: Environment variable
|
|
112
|
+
LOOPWORK_DEBUG=true bun ../../src/index.ts --dry-run
|
|
113
|
+
|
|
114
|
+
# Method 2: CLI flag
|
|
115
|
+
bun ../../src/index.ts --debug --dry-run
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Check Command Being Executed
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
bun ../../src/index.ts --debug --dry-run 2>&1 | grep "Executing:"
|
|
122
|
+
# Shows: [model-name] Executing: <command>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Verify Config File Loading
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# Should NOT show warning about failed config load
|
|
129
|
+
bun ../../src/index.ts --dry-run 2>&1 | head -5
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Common Issues
|
|
133
|
+
|
|
134
|
+
### "No pending tasks found"
|
|
135
|
+
|
|
136
|
+
Tasks have been completed. Reset them:
|
|
137
|
+
```bash
|
|
138
|
+
echo "3" | ./quick-start.sh
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### "Another loopwork is running"
|
|
142
|
+
|
|
143
|
+
Remove the lock file:
|
|
144
|
+
```bash
|
|
145
|
+
rm -rf .loopwork-*.lock
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Config not loading
|
|
149
|
+
|
|
150
|
+
Make sure you're in the correct directory:
|
|
151
|
+
```bash
|
|
152
|
+
pwd
|
|
153
|
+
# Should be: .../examples/basic-json-backend
|
|
154
|
+
|
|
155
|
+
ls loopwork.config.js
|
|
156
|
+
# Should exist
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### --dry-run not working
|
|
160
|
+
|
|
161
|
+
This was a known issue that's now fixed. Update to latest code:
|
|
162
|
+
```bash
|
|
163
|
+
git pull origin main
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Success Criteria
|
|
167
|
+
|
|
168
|
+
All of these should pass:
|
|
169
|
+
|
|
170
|
+
- ā
`./quick-start.sh` shows interactive menu
|
|
171
|
+
- ā
`bun run dry-run` shows 3 pending tasks
|
|
172
|
+
- ā
Config values are loaded (claude CLI, 10 max iterations, 300s timeout)
|
|
173
|
+
- ā
`--dry-run` flag shows "Dry Run: true"
|
|
174
|
+
- ā
Tasks are shown in priority order (TASK-001 first)
|
|
175
|
+
- ā
Command being executed is displayed
|
|
176
|
+
|
|
177
|
+
## Next Steps
|
|
178
|
+
|
|
179
|
+
After testing the basic example:
|
|
180
|
+
|
|
181
|
+
1. Try modifying the config (change CLI, timeouts, etc.)
|
|
182
|
+
2. Create your own tasks in `.specs/tasks/`
|
|
183
|
+
3. Experiment with task dependencies
|
|
184
|
+
4. Add plugins (Telegram, cost tracking, etc.)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic Loopwork Configuration Example
|
|
3
|
+
*
|
|
4
|
+
* This is a minimal configuration for testing loopwork with JSON backend.
|
|
5
|
+
* Tasks are stored in .specs/tasks/tasks.json
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
// Backend configuration
|
|
10
|
+
backend: {
|
|
11
|
+
type: 'json',
|
|
12
|
+
tasksFile: '.specs/tasks/tasks.json',
|
|
13
|
+
tasksDir: '.specs/tasks',
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
// CLI tool to use: 'opencode' or 'claude'
|
|
17
|
+
cli: 'claude',
|
|
18
|
+
|
|
19
|
+
// Loop settings
|
|
20
|
+
maxIterations: 10,
|
|
21
|
+
timeout: 300, // 5 minutes per task
|
|
22
|
+
|
|
23
|
+
// Optional settings
|
|
24
|
+
// dryRun: false, // Set to true to test without executing (use --dry-run flag instead)
|
|
25
|
+
debug: true, // Enable debug logging
|
|
26
|
+
// autoConfirm: false, // Set to true to skip confirmations (use -y flag instead)
|
|
27
|
+
|
|
28
|
+
// Retry settings
|
|
29
|
+
maxRetries: 2,
|
|
30
|
+
retryDelay: 3000, // Wait 3 seconds before retry
|
|
31
|
+
taskDelay: 2000, // Wait 2 seconds between tasks
|
|
32
|
+
|
|
33
|
+
// Namespace for concurrent runs
|
|
34
|
+
namespace: 'basic-example',
|
|
35
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, it, expect } from 'bun:test'
|
|
2
|
+
import { sum } from './math'
|
|
3
|
+
|
|
4
|
+
describe('sum', () => {
|
|
5
|
+
it('should add two positive integers', () => {
|
|
6
|
+
const result = sum(2, 3)
|
|
7
|
+
expect(result).toBe(5)
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
it('should add two negative integers', () => {
|
|
11
|
+
const result = sum(-2, -3)
|
|
12
|
+
expect(result).toBe(-5)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('should add positive and negative integers', () => {
|
|
16
|
+
const result = sum(5, -3)
|
|
17
|
+
expect(result).toBe(2)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should handle decimal numbers', () => {
|
|
21
|
+
const result = sum(2.5, 3.7)
|
|
22
|
+
expect(result).toBe(6.2)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('should handle zero', () => {
|
|
26
|
+
const result = sum(0, 5)
|
|
27
|
+
expect(result).toBe(5)
|
|
28
|
+
})
|
|
29
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "loopwork-example-basic",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Basic example of using Loopwork with JSON backend",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "bun run ../../src/index.ts",
|
|
9
|
+
"dry-run": "bun run ../../src/index.ts --dry-run",
|
|
10
|
+
"build": "echo 'No build needed for example'"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@types/bun": "latest"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Quick Start Script for Basic JSON Backend Example
|
|
3
|
+
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
echo "š Loopwork Basic Example - Quick Start"
|
|
7
|
+
echo "========================================"
|
|
8
|
+
echo ""
|
|
9
|
+
|
|
10
|
+
# Check if we're in the right directory
|
|
11
|
+
if [ ! -f "loopwork.config.js" ] && [ ! -f "loopwork.config.ts" ]; then
|
|
12
|
+
echo "ā Error: Please run this script from the examples/basic-json-backend directory"
|
|
13
|
+
exit 1
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
echo "š Current Tasks:"
|
|
17
|
+
cat .specs/tasks/tasks.json | grep -A 2 '"id"'
|
|
18
|
+
echo ""
|
|
19
|
+
|
|
20
|
+
echo "Choose an option:"
|
|
21
|
+
echo "1) Dry Run (preview without executing)"
|
|
22
|
+
echo "2) Run Loopwork (execute tasks)"
|
|
23
|
+
echo "3) Reset tasks to pending"
|
|
24
|
+
echo "4) View task details"
|
|
25
|
+
echo ""
|
|
26
|
+
|
|
27
|
+
read -p "Enter your choice (1-4): " choice
|
|
28
|
+
|
|
29
|
+
case $choice in
|
|
30
|
+
1)
|
|
31
|
+
echo ""
|
|
32
|
+
echo "š Running dry-run..."
|
|
33
|
+
bun run ../../src/index.ts --dry-run
|
|
34
|
+
;;
|
|
35
|
+
2)
|
|
36
|
+
echo ""
|
|
37
|
+
echo "ā” Running Loopwork..."
|
|
38
|
+
bun run ../../src/index.ts
|
|
39
|
+
;;
|
|
40
|
+
3)
|
|
41
|
+
echo ""
|
|
42
|
+
echo "š Resetting all tasks to pending..."
|
|
43
|
+
cat > .specs/tasks/tasks.json << 'EOF'
|
|
44
|
+
{
|
|
45
|
+
"tasks": [
|
|
46
|
+
{
|
|
47
|
+
"id": "TASK-001",
|
|
48
|
+
"status": "pending",
|
|
49
|
+
"priority": "high"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"id": "TASK-002",
|
|
53
|
+
"status": "pending",
|
|
54
|
+
"priority": "medium"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "TASK-003",
|
|
58
|
+
"status": "pending",
|
|
59
|
+
"priority": "low"
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
EOF
|
|
64
|
+
echo "ā
Tasks reset!"
|
|
65
|
+
;;
|
|
66
|
+
4)
|
|
67
|
+
echo ""
|
|
68
|
+
echo "š Task Details:"
|
|
69
|
+
echo ""
|
|
70
|
+
for task in .specs/tasks/TASK-*.md; do
|
|
71
|
+
echo "----------------------------------------"
|
|
72
|
+
head -5 "$task"
|
|
73
|
+
echo ""
|
|
74
|
+
done
|
|
75
|
+
;;
|
|
76
|
+
*)
|
|
77
|
+
echo "ā Invalid choice"
|
|
78
|
+
exit 1
|
|
79
|
+
;;
|
|
80
|
+
esac
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineConfig,
|
|
3
|
+
withTelegram,
|
|
4
|
+
withCostTracking,
|
|
5
|
+
withJSON,
|
|
6
|
+
withGitHub,
|
|
7
|
+
withPlugin,
|
|
8
|
+
withAsana,
|
|
9
|
+
withEverhour,
|
|
10
|
+
withTodoist,
|
|
11
|
+
withDiscord,
|
|
12
|
+
compose,
|
|
13
|
+
} from './src/loopwork-config-types'
|
|
14
|
+
import { withJSONBackend, withGitHubBackend } from './src/backend-plugin'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Loopwork Configuration
|
|
18
|
+
*
|
|
19
|
+
* This file configures the Loopwork task runner.
|
|
20
|
+
* Similar to next.config.js, you can use plugin wrappers to add functionality.
|
|
21
|
+
*
|
|
22
|
+
* Backends are now plugins:
|
|
23
|
+
* - withJSONBackend({ tasksFile: 'tasks.json' })
|
|
24
|
+
* - withGitHubBackend({ repo: 'owner/repo' })
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// Full Example with All Plugins
|
|
29
|
+
// =============================================================================
|
|
30
|
+
|
|
31
|
+
export default compose(
|
|
32
|
+
// Backend plugins (choose one)
|
|
33
|
+
withJSONBackend({ tasksFile: '.specs/tasks/tasks.json' }),
|
|
34
|
+
// withGitHubBackend({ repo: 'owner/repo' }),
|
|
35
|
+
|
|
36
|
+
// Legacy backend config (still supported)
|
|
37
|
+
// withJSON({ tasksFile: '.specs/tasks/tasks.json' }),
|
|
38
|
+
// withGitHub({ repo: 'owner/repo' }),
|
|
39
|
+
|
|
40
|
+
// Telegram notifications on task events
|
|
41
|
+
withTelegram({
|
|
42
|
+
botToken: process.env.TELEGRAM_BOT_TOKEN,
|
|
43
|
+
chatId: process.env.TELEGRAM_CHAT_ID,
|
|
44
|
+
silent: false,
|
|
45
|
+
}),
|
|
46
|
+
|
|
47
|
+
// Asana integration: sync task status to Asana project
|
|
48
|
+
// Tasks should have metadata.asanaGid set in the tasks file
|
|
49
|
+
// withAsana({
|
|
50
|
+
// projectId: process.env.ASANA_PROJECT_ID,
|
|
51
|
+
// syncStatus: true,
|
|
52
|
+
// }),
|
|
53
|
+
|
|
54
|
+
// Everhour time tracking: auto-track time spent on tasks
|
|
55
|
+
// Uses metadata.everhourId or metadata.asanaGid (auto-prefixed with 'as:')
|
|
56
|
+
// withEverhour({
|
|
57
|
+
// autoStartTimer: true,
|
|
58
|
+
// autoStopTimer: true,
|
|
59
|
+
// }),
|
|
60
|
+
|
|
61
|
+
// Todoist integration: sync task status to Todoist
|
|
62
|
+
// Tasks should have metadata.todoistId set
|
|
63
|
+
// withTodoist({
|
|
64
|
+
// projectId: process.env.TODOIST_PROJECT_ID,
|
|
65
|
+
// syncStatus: true,
|
|
66
|
+
// addComments: true,
|
|
67
|
+
// }),
|
|
68
|
+
|
|
69
|
+
// Discord notifications via webhook
|
|
70
|
+
// withDiscord({
|
|
71
|
+
// webhookUrl: process.env.DISCORD_WEBHOOK_URL,
|
|
72
|
+
// username: 'Loopwork',
|
|
73
|
+
// notifyOnComplete: true,
|
|
74
|
+
// notifyOnFail: true,
|
|
75
|
+
// mentionOnFail: '<@&123456>', // mention role on failures
|
|
76
|
+
// }),
|
|
77
|
+
|
|
78
|
+
// Cost tracking for token usage
|
|
79
|
+
withCostTracking({
|
|
80
|
+
enabled: true,
|
|
81
|
+
defaultModel: 'claude-3.5-sonnet',
|
|
82
|
+
}),
|
|
83
|
+
|
|
84
|
+
// Dashboard TUI: live progress display
|
|
85
|
+
// Requires: bun add ink react @types/react
|
|
86
|
+
// withPlugin(createDashboardPlugin({ totalTasks: 10 })),
|
|
87
|
+
|
|
88
|
+
// Custom plugin: Log to console
|
|
89
|
+
withPlugin({
|
|
90
|
+
name: 'console-logger',
|
|
91
|
+
onLoopStart: (namespace) => {
|
|
92
|
+
console.log(`\nš Loop starting in namespace: ${namespace}\n`)
|
|
93
|
+
},
|
|
94
|
+
onTaskStart: (task) => {
|
|
95
|
+
console.log(`š Starting: ${task.id} - ${task.title}`)
|
|
96
|
+
},
|
|
97
|
+
onTaskComplete: (task, result) => {
|
|
98
|
+
console.log(`ā
Completed: ${task.id} in ${result.duration}s`)
|
|
99
|
+
},
|
|
100
|
+
onTaskFailed: (task, error) => {
|
|
101
|
+
console.log(`ā Failed: ${task.id} - ${error}`)
|
|
102
|
+
},
|
|
103
|
+
onLoopEnd: (stats) => {
|
|
104
|
+
console.log(`\nš Loop finished: ${stats.completed} completed, ${stats.failed} failed\n`)
|
|
105
|
+
},
|
|
106
|
+
}),
|
|
107
|
+
|
|
108
|
+
// Custom plugin: Slack webhook (example)
|
|
109
|
+
// withPlugin({
|
|
110
|
+
// name: 'slack-notify',
|
|
111
|
+
// onTaskComplete: async (task) => {
|
|
112
|
+
// await fetch(process.env.SLACK_WEBHOOK_URL, {
|
|
113
|
+
// method: 'POST',
|
|
114
|
+
// headers: { 'Content-Type': 'application/json' },
|
|
115
|
+
// body: JSON.stringify({
|
|
116
|
+
// text: `ā
Task completed: ${task.id} - ${task.title}`,
|
|
117
|
+
// }),
|
|
118
|
+
// })
|
|
119
|
+
// },
|
|
120
|
+
// }),
|
|
121
|
+
)(defineConfig({
|
|
122
|
+
// AI CLI tool: 'opencode', 'claude', or 'gemini'
|
|
123
|
+
cli: 'opencode',
|
|
124
|
+
|
|
125
|
+
// Loop settings
|
|
126
|
+
maxIterations: 50,
|
|
127
|
+
timeout: 600, // seconds per task
|
|
128
|
+
namespace: 'default', // for concurrent loops
|
|
129
|
+
|
|
130
|
+
// Behavior
|
|
131
|
+
autoConfirm: false, // -y flag
|
|
132
|
+
dryRun: false,
|
|
133
|
+
debug: false,
|
|
134
|
+
|
|
135
|
+
// Retry settings
|
|
136
|
+
maxRetries: 3,
|
|
137
|
+
circuitBreakerThreshold: 5,
|
|
138
|
+
taskDelay: 2000, // ms between tasks
|
|
139
|
+
retryDelay: 3000, // ms before retry
|
|
140
|
+
}))
|
|
141
|
+
|
|
142
|
+
// =============================================================================
|
|
143
|
+
// Alternative: Backend Plugins Pattern (recommended)
|
|
144
|
+
// =============================================================================
|
|
145
|
+
|
|
146
|
+
// export default compose(
|
|
147
|
+
// withJSONBackend({ tasksFile: 'tasks.json' }),
|
|
148
|
+
// withTelegram(),
|
|
149
|
+
// withAsana(),
|
|
150
|
+
// withEverhour(),
|
|
151
|
+
// )(defineConfig({ cli: 'opencode' }))
|
|
152
|
+
|
|
153
|
+
// =============================================================================
|
|
154
|
+
// Alternative: GitHub Backend Plugin
|
|
155
|
+
// =============================================================================
|
|
156
|
+
|
|
157
|
+
// export default compose(
|
|
158
|
+
// withGitHubBackend({ repo: 'myorg/myrepo' }),
|
|
159
|
+
// withTelegram(),
|
|
160
|
+
// withDiscord({ webhookUrl: process.env.DISCORD_WEBHOOK_URL }),
|
|
161
|
+
// )(defineConfig({
|
|
162
|
+
// cli: 'claude',
|
|
163
|
+
// feature: 'auth', // filter by feature label
|
|
164
|
+
// }))
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "loopwork",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Loopwork - AI task runner with pluggable backends",
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"bin": {
|
|
7
|
+
"loopwork": "bin/loopwork"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "bun run src/index.ts",
|
|
11
|
+
"build": "bun build ./src/index.ts --compile --outfile bin/loopwork",
|
|
12
|
+
"test": "bun test",
|
|
13
|
+
"setup-labels": "bun run src/setup-labels.ts"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"chalk": "^5.3.0",
|
|
17
|
+
"commander": "^12.0.0",
|
|
18
|
+
"ink": "^4.4.1",
|
|
19
|
+
"react": "^18.2.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/bun": "latest",
|
|
23
|
+
"@types/node": "^20.0.0",
|
|
24
|
+
"@types/react": "^18.2.0"
|
|
25
|
+
}
|
|
26
|
+
}
|