@m0xoo/openboard 1.0.8 → 1.0.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m0xoo/openboard",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "openboard": "./bin/openboard.js"
@@ -176,9 +176,11 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
176
176
  // Handle Session Idle (Task Completed)
177
177
  if (event.type === 'session.idle') {
178
178
  console.log(`[opencode-agent] Agent task completed (idle) for ticket ${ticket.id}.`);
179
- // Check if the session failed with a fatal error previously
179
+ // Check if the current session failed with a fatal error previously
180
180
  const currentTicket = ticketRepository.findById(ticket.id);
181
- const hasError = currentTicket?.agent_sessions?.some((s) => s.column_id === ticket.column_id && s.status === 'blocked');
181
+ const sessionsForColumn = currentTicket?.agent_sessions?.filter((s) => s.column_id === ticket.column_id) || [];
182
+ const latestSession = sessionsForColumn[sessionsForColumn.length - 1];
183
+ const hasError = latestSession?.status === 'blocked';
182
184
  if (!hasError) {
183
185
  // Mark the ticket as done now that the agent session finished processing
184
186
  ticketRepository.updateAgentSession(ticket.id, {
@@ -361,6 +363,9 @@ export async function setupOpencodeEventListener(events, opencodeClient, session
361
363
  }
362
364
  } // End of agentType === 'opencode' block
363
365
  }
366
+ // Wait! Since this ticket finished processing, we should re-evaluate the CURRENT column
367
+ // so the next pending ticket can be picked up by an agent.
368
+ agentQueue.evaluateColumnQueue(ticket.column_id);
364
369
  // Clean up the server instance tracking after a brief delay
365
370
  setTimeout(() => {
366
371
  console.log(`[opencode-agent] Cleaning up tracking for ${ticket.id}`);
@@ -3,8 +3,19 @@ import path from 'path';
3
3
  import { fileURLToPath } from 'url';
4
4
  import { createRequire } from 'module';
5
5
  import fs from 'fs';
6
+ import os from 'os';
6
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
- const DB_PATH = path.join(__dirname, '..', '..', '..', 'openboard.db');
8
+ const openboardDir = path.join(os.homedir(), '.openboard');
9
+ if (!fs.existsSync(openboardDir)) {
10
+ fs.mkdirSync(openboardDir, { recursive: true });
11
+ }
12
+ const DB_PATH = path.join(openboardDir, 'openboard.db');
13
+ console.log("[db] DB_PATH", DB_PATH);
14
+ // Migrate old database if it exists
15
+ const oldDbPath = path.join(__dirname, '..', '..', '..', 'openboard.db');
16
+ if (fs.existsSync(oldDbPath) && !fs.existsSync(DB_PATH)) {
17
+ fs.copyFileSync(oldDbPath, DB_PATH);
18
+ }
8
19
  // Resolve sql.js WASM dynamically — handles npm workspace node_modules hoisting
9
20
  const require = createRequire(import.meta.url);
10
21
  const sqlJsDir = path.dirname(require.resolve('sql.js/dist/sql-wasm.wasm'));
@@ -56,8 +56,21 @@ async function start() {
56
56
  app.get('*', (req, res) => {
57
57
  res.sendFile(path.join(clientExtPath, 'index.html'));
58
58
  });
59
- app.listen(PORT, () => {
60
- console.log(`[openboard] Server running at http://localhost:${PORT}`);
59
+ const server = app.listen(PORT);
60
+ server.on('listening', () => {
61
+ const address = server.address();
62
+ const actualPort = typeof address === 'string' ? address : address?.port;
63
+ console.log(`[openboard] Server running at http://localhost:${actualPort}`);
64
+ });
65
+ server.on('error', (err) => {
66
+ if (err.code === 'EADDRINUSE') {
67
+ console.log(`[openboard] Port ${PORT} is in use, trying a random available port...`);
68
+ server.close();
69
+ server.listen(0);
70
+ }
71
+ else {
72
+ console.error('[openboard] Server error:', err);
73
+ }
61
74
  });
62
75
  }
63
76
  start().catch(err => {
@@ -19,7 +19,7 @@ router.get('/:id/config', (req, res) => {
19
19
  });
20
20
  // PUT /api/boards/:boardId/columns/:id/config
21
21
  router.put('/:id/config', (req, res) => {
22
- const { agentType, onFinishColumnId, onRejectColumnId } = req.body;
22
+ const { agentType, agentModel, maxAgents, onFinishColumnId, onRejectColumnId } = req.body;
23
23
  if (!agentType) {
24
24
  res.status(400).json({ error: 'agentType is required' });
25
25
  return;
@@ -27,6 +27,8 @@ router.put('/:id/config', (req, res) => {
27
27
  const config = columnConfigRepository.upsert({
28
28
  columnId: req.params.id,
29
29
  agentType,
30
+ agentModel,
31
+ maxAgents,
30
32
  onFinishColumnId,
31
33
  onRejectColumnId,
32
34
  });