@m0xoo/openboard 1.0.1 → 1.0.3
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/README.md
CHANGED
|
@@ -1,99 +1,100 @@
|
|
|
1
|
-
# Openboard: The AI Agent Orchestration Board
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
- **
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
30
|
-
- **
|
|
31
|
-
- **
|
|
32
|
-
- **
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- **
|
|
37
|
-
- **
|
|
38
|
-
- **
|
|
39
|
-
- **
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- **[
|
|
47
|
-
- **[
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
- The **
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
├──
|
|
93
|
-
|
|
94
|
-
│
|
|
95
|
-
│ │
|
|
96
|
-
│ └──
|
|
97
|
-
│
|
|
98
|
-
│
|
|
99
|
-
|
|
1
|
+
# Openboard: The AI Agent Orchestration Board
|
|
2
|
+
This is a work on progress, contribuations are welcome.
|
|
3
|
+
|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
Openboard is not just another Kanban board—it is an orchestration platform specifically designed to **manage, monitor, and collaborate with autonomous AI coding agents**. While it features a real-time Kanban interface built with React and Node.js, our primary focus is on providing a seamless environment for agents to pick up tasks, execute them in isolation, and submit their work.
|
|
7
|
+
|
|
8
|
+
## Why Openboard? Managing Coding Agents
|
|
9
|
+
|
|
10
|
+
We use a Kanban board as the central nervous system for AI agents for several key reasons:
|
|
11
|
+
|
|
12
|
+
- **Visibility and Tracking**: A board provides a clear, visual representation of what each agent is currently working on, what tasks are queued, and what has been completed.
|
|
13
|
+
- **Task Decomposition**: Complex software engineering tasks can be broken down into smaller, manageable tickets, allowing multiple agents to work in parallel on different components.
|
|
14
|
+
- **State Management**: The board acts as a centralized state machine for the agents' progress. If an agent encounters an error or requires human approval, the ticket status reflects this immediately.
|
|
15
|
+
- **Prioritization**: Easily reorder tickets in the backlog to direct the agents' focus to the most critical tasks first.
|
|
16
|
+
- **Seamless Collaboration**: Facilitates handoffs between specialized agents (e.g., an architecture agent breaking down a task into tickets, which are then picked up by implementation agents).
|
|
17
|
+
|
|
18
|
+
## How Agents Work: Git Worktrees & GitHub CLI
|
|
19
|
+
|
|
20
|
+
To allow multiple agents to work in parallel without tripping over each other, Openboard leverages **Git Worktrees** and the **GitHub CLI (`gh`)**.
|
|
21
|
+
|
|
22
|
+
- **Git Worktrees**: When an agent picks up a ticket, it doesn't just check out a branch in your main project folder. Instead, it creates an isolated feature branch and a dedicated git worktree for it. This provides the agent with its own physical directory and working tree to modify files, run tests, and commit changes comfortably, all while ensuring your main workspace remains untouched.
|
|
23
|
+
- **PR Generation (`gh`)**: Once the agent finishes its implementation, it uses the GitHub CLI to automatically push its branch and open a Pull Request for human review, progressing the ticket to a "Needs Approval" state on the board.
|
|
24
|
+
|
|
25
|
+
## Tech Stack
|
|
26
|
+
|
|
27
|
+
### Frontend (`packages/client`)
|
|
28
|
+
- **Framework:** React with Vite
|
|
29
|
+
- **Language:** TypeScript
|
|
30
|
+
- **Styling:** CSS Modules, Global CSS variables
|
|
31
|
+
- **Routing:** React Router DOM
|
|
32
|
+
- **Interactions:** `@dnd-kit` for drag-and-drop
|
|
33
|
+
- **Icons:** Lucide React
|
|
34
|
+
|
|
35
|
+
### Backend (`packages/server`)
|
|
36
|
+
- **Runtime:** Node.js
|
|
37
|
+
- **Framework:** Express
|
|
38
|
+
- **Language:** TypeScript
|
|
39
|
+
- **Database:** SQLite (via `sql.js`)
|
|
40
|
+
- **Real-time:** Server-Sent Events (SSE)
|
|
41
|
+
|
|
42
|
+
## Prerequisites
|
|
43
|
+
|
|
44
|
+
Before running Openboard, ensure you have the following installed on your system:
|
|
45
|
+
|
|
46
|
+
- **[Node.js](https://nodejs.org/)** (v18 or newer recommended) & npm
|
|
47
|
+
- **[Git](https://git-scm.com/)**: Required for agents to manage versions and worktrees. Ensure `git` is available in your PATH.
|
|
48
|
+
- **[GitHub CLI (`gh`)](https://cli.github.com/)**: Required for agents to authenticate and create Pull Requests. Ensure `gh` is available in your PATH and you are authenticated by running `gh auth login` before starting the agents.
|
|
49
|
+
|
|
50
|
+
## Getting Started
|
|
51
|
+
|
|
52
|
+
1. **Install dependencies**
|
|
53
|
+
|
|
54
|
+
Run this command in the root directory. This will install dependencies for both the client and server workspaces:
|
|
55
|
+
```bash
|
|
56
|
+
npm install
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
2. **Environment Variables**
|
|
60
|
+
|
|
61
|
+
Navigate to the `packages/client` directory and copy the example environment file:
|
|
62
|
+
```bash
|
|
63
|
+
cp packages/client/.env.example packages/client/.env
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
3. **Start the development servers**
|
|
67
|
+
|
|
68
|
+
Start both the frontend and backend simultaneously using concurrently:
|
|
69
|
+
```bash
|
|
70
|
+
npm run dev
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- The **client** will be available at: [http://localhost:5173](http://localhost:5173)
|
|
74
|
+
- The **server** will run on: [http://localhost:3001](http://localhost:3001)
|
|
75
|
+
|
|
76
|
+
4. **Build and Run for Production**
|
|
77
|
+
|
|
78
|
+
To build both the client and server for a production environment:
|
|
79
|
+
```bash
|
|
80
|
+
npm run build
|
|
81
|
+
```
|
|
82
|
+
To start the production servers simultaneously:
|
|
83
|
+
```bash
|
|
84
|
+
npm run start
|
|
85
|
+
```
|
|
86
|
+
Or use `npm run prod` to build and start in one command.
|
|
87
|
+
|
|
88
|
+
## Project Structure
|
|
89
|
+
|
|
90
|
+
```text
|
|
91
|
+
openboard/
|
|
92
|
+
├── package.json # Root workspace configuration
|
|
93
|
+
├── packages/
|
|
94
|
+
│ ├── client/ # React frontend application
|
|
95
|
+
│ │ ├── src/ # Components, Context, Styles
|
|
96
|
+
│ │ └── package.json
|
|
97
|
+
│ └── server/ # Express backend application
|
|
98
|
+
│ ├── src/ # Routes, Database logic, SSE, Agent logic
|
|
99
|
+
│ └── package.json
|
|
100
|
+
```
|
package/package.json
CHANGED
|
@@ -10,11 +10,11 @@ const execFileAsync = promisify(execFile);
|
|
|
10
10
|
async function runCmd(cmd, args, cwd) {
|
|
11
11
|
console.log(`[codereview-agent] Running: ${cmd} ${args.join(' ')} in cwd: ${cwd}`);
|
|
12
12
|
try {
|
|
13
|
-
return await execFileAsync(cmd, args, { cwd
|
|
13
|
+
return await execFileAsync(cmd, args, { cwd });
|
|
14
14
|
}
|
|
15
15
|
catch (e) {
|
|
16
16
|
if (e.code === 'ENOENT') {
|
|
17
|
-
console.log(`[codereview-agent] ENOENT
|
|
17
|
+
console.log(`[codereview-agent] ENOENT finding binary. Trying fallback exec...`);
|
|
18
18
|
return await execAsync(`${cmd} ${args.join(' ')}`, { cwd });
|
|
19
19
|
}
|
|
20
20
|
throw e;
|
|
@@ -63,11 +63,6 @@ export class CodeReviewAgent {
|
|
|
63
63
|
}
|
|
64
64
|
// Resolve workspace path — code review runs in the main workspace (no new worktree needed).
|
|
65
65
|
let workspacePath = process.cwd();
|
|
66
|
-
// Fix WSL path mapping if the Node server is running on Windows
|
|
67
|
-
if (workspacePath.startsWith('/mnt/')) {
|
|
68
|
-
const driveLetter = workspacePath.charAt(5).toUpperCase();
|
|
69
|
-
workspacePath = `${driveLetter}:\\${workspacePath.slice(7).replace(/\//g, '\\')}`;
|
|
70
|
-
}
|
|
71
66
|
try {
|
|
72
67
|
const session = await opencodeClient.session.create({
|
|
73
68
|
body: { title: `Code Review for Ticket: ${ticket.title}` },
|
|
@@ -15,7 +15,7 @@ async function getGhToken(cwd) {
|
|
|
15
15
|
if (cachedGhToken !== null)
|
|
16
16
|
return cachedGhToken;
|
|
17
17
|
try {
|
|
18
|
-
const { stdout } = await execFileAsync('gh', ['auth', 'token'], { cwd
|
|
18
|
+
const { stdout } = await execFileAsync('gh', ['auth', 'token'], { cwd });
|
|
19
19
|
cachedGhToken = stdout.trim() || null;
|
|
20
20
|
}
|
|
21
21
|
catch {
|
|
@@ -35,12 +35,12 @@ async function runCmd(cmd, args, cwd) {
|
|
|
35
35
|
}
|
|
36
36
|
const env = Object.keys(extraEnv).length > 0 ? { ...process.env, ...extraEnv } : undefined;
|
|
37
37
|
try {
|
|
38
|
-
return await execFileAsync(cmd, args, { cwd,
|
|
38
|
+
return await execFileAsync(cmd, args, { cwd, ...(env && { env }) });
|
|
39
39
|
}
|
|
40
40
|
catch (e) {
|
|
41
41
|
if (e.code === 'ENOENT') {
|
|
42
|
-
console.log(`[opencode-agent] ENOENT
|
|
43
|
-
const envPrefix = extraEnv['GH_TOKEN'] ? `GH_TOKEN=${extraEnv['GH_TOKEN']} ` : '';
|
|
42
|
+
console.log(`[opencode-agent] ENOENT finding binary. Trying fallback exec...`);
|
|
43
|
+
const envPrefix = extraEnv['GH_TOKEN'] ? (process.platform === 'win32' ? `set GH_TOKEN=${extraEnv['GH_TOKEN']}&& ` : `GH_TOKEN=${extraEnv['GH_TOKEN']} `) : '';
|
|
44
44
|
return await execAsync(`${envPrefix}${cmd} ${args.join(' ')}`, { cwd });
|
|
45
45
|
}
|
|
46
46
|
throw e;
|
|
@@ -75,12 +75,6 @@ export class OpencodeAgent {
|
|
|
75
75
|
}
|
|
76
76
|
// 1. Find Worktree (Use the directory where openboard was started)
|
|
77
77
|
let originalWorkspacePath = process.cwd();
|
|
78
|
-
// Fix WSL path mapping if the Node server is running on Windows
|
|
79
|
-
if (originalWorkspacePath.startsWith('/mnt/')) {
|
|
80
|
-
const driveLetter = originalWorkspacePath.charAt(5).toUpperCase();
|
|
81
|
-
originalWorkspacePath = `${driveLetter}:\\${originalWorkspacePath.slice(7).replace(/\//g, '\\')}`;
|
|
82
|
-
console.log(`[opencode-agent] Normalized WSL path to Windows path for CWD: ${originalWorkspacePath}`);
|
|
83
|
-
}
|
|
84
78
|
// 2. Set up Worktree
|
|
85
79
|
// If this ticket already has a PR, we reuse the existing branch and worktree.
|
|
86
80
|
// Worktree paths are derived from branch name so they are stable across re-runs.
|