agent-board-runner 0.1.5 → 0.1.7

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/dist/cli.js CHANGED
@@ -471,7 +471,7 @@ function stopPtySession(sessionId) {
471
471
  import { randomUUID as randomUUID3 } from "node:crypto";
472
472
  import { spawn } from "node-pty";
473
473
  var SHELL_COMMAND = process.platform === "win32" ? process.env.COMSPEC ?? "cmd.exe" : process.env.SHELL ?? "bash";
474
- function spawnShellPty(repoPath, sessionIdPrefix) {
474
+ function spawnShellPty(repoPath, sessionIdPrefix, initialCommand) {
475
475
  const sessionId = `${sessionIdPrefix}:${randomUUID3()}`;
476
476
  const ticket = randomUUID3();
477
477
  const pty = spawn(SHELL_COMMAND, [], {
@@ -481,14 +481,15 @@ function spawnShellPty(repoPath, sessionIdPrefix) {
481
481
  cwd: repoPath
482
482
  });
483
483
  registerPtySession(sessionId, pty, ticket);
484
+ if (initialCommand) pty.write(`${initialCommand}\r`);
484
485
  pty.onExit(({ exitCode }) => {
485
486
  logger.runner.info("SHELL", `Shell ${sessionId} exited (code ${exitCode}).`);
486
487
  stopPtySession(sessionId);
487
488
  });
488
489
  return { sessionId, ticket };
489
490
  }
490
- function openShellSession(repoPath) {
491
- return spawnShellPty(repoPath, "shell");
491
+ function openShellSession(repoPath, initialCommand) {
492
+ return spawnShellPty(repoPath, "shell", initialCommand);
492
493
  }
493
494
  function closeShellSession(sessionId) {
494
495
  stopPtySession(sessionId);
@@ -497,9 +498,8 @@ var columnShells = /* @__PURE__ */ new Map();
497
498
  function openOrReuseColumnShell(key, repoPath, initialCommand) {
498
499
  const existing = columnShells.get(key);
499
500
  if (existing && getPtySession(existing.sessionId)) return existing;
500
- const shell = spawnShellPty(repoPath, "column-shell");
501
+ const shell = spawnShellPty(repoPath, "column-shell", initialCommand);
501
502
  columnShells.set(key, shell);
502
- if (initialCommand) getPtySession(shell.sessionId)?.pty.write(`${initialCommand}\r`);
503
503
  return shell;
504
504
  }
505
505
  function closeColumnShell(key) {
@@ -2168,7 +2168,9 @@ function handleRequest(req, res) {
2168
2168
  return;
2169
2169
  }
2170
2170
  if (pathname === "/shell/open") {
2171
- sendJson(res, 200, openShellSession(entry.repoRoot));
2171
+ const kind = typeof query.kind === "string" ? query.kind : "shell";
2172
+ if (!COLUMN_SHELL_KINDS.includes(kind)) throw new HttpError(400, "Par\xE2metro kind inv\xE1lido.");
2173
+ sendJson(res, 200, openShellSession(entry.repoRoot, kind === "claude" ? CLAUDE_BYPASS_COMMAND : void 0));
2172
2174
  return;
2173
2175
  }
2174
2176
  if (pathname === "/shell/close") {
@@ -3339,12 +3341,25 @@ async function restartCardSession(supabase, config, card) {
3339
3341
  }
3340
3342
 
3341
3343
  // src/deploy.ts
3344
+ var deploysInFlight = /* @__PURE__ */ new Set();
3342
3345
  async function handleDeployRequested(supabase, config, project) {
3343
3346
  const registered = config.registeredProjects.find((candidate) => candidate.id === project.id);
3344
3347
  if (!registered) {
3345
3348
  logger.runner.warn("DEPLOY", `Ignoring deploy request: project ${project.id} is not registered on this runner.`);
3346
3349
  return;
3347
3350
  }
3351
+ if (deploysInFlight.has(project.id)) {
3352
+ logger.runner.info("DEPLOY", `Deploy already in progress for project ${project.id}, skipping duplicate trigger.`);
3353
+ return;
3354
+ }
3355
+ deploysInFlight.add(project.id);
3356
+ try {
3357
+ await runDeploy(supabase, config, project);
3358
+ } finally {
3359
+ deploysInFlight.delete(project.id);
3360
+ }
3361
+ }
3362
+ async function runDeploy(supabase, config, project) {
3348
3363
  const allCards = await listCardsInColumn(supabase, project.id, "deploy");
3349
3364
  const cards = allCards.filter((card) => card.assigned_user_id === config.ownerUserId);
3350
3365
  if (cards.length === 0) {
package/dist/index.js CHANGED
@@ -309,7 +309,7 @@ function stopPtySession(sessionId) {
309
309
  import { randomUUID as randomUUID2 } from "node:crypto";
310
310
  import { spawn } from "node-pty";
311
311
  var SHELL_COMMAND = process.platform === "win32" ? process.env.COMSPEC ?? "cmd.exe" : process.env.SHELL ?? "bash";
312
- function spawnShellPty(repoPath, sessionIdPrefix) {
312
+ function spawnShellPty(repoPath, sessionIdPrefix, initialCommand) {
313
313
  const sessionId = `${sessionIdPrefix}:${randomUUID2()}`;
314
314
  const ticket = randomUUID2();
315
315
  const pty = spawn(SHELL_COMMAND, [], {
@@ -319,14 +319,15 @@ function spawnShellPty(repoPath, sessionIdPrefix) {
319
319
  cwd: repoPath
320
320
  });
321
321
  registerPtySession(sessionId, pty, ticket);
322
+ if (initialCommand) pty.write(`${initialCommand}\r`);
322
323
  pty.onExit(({ exitCode }) => {
323
324
  logger.runner.info("SHELL", `Shell ${sessionId} exited (code ${exitCode}).`);
324
325
  stopPtySession(sessionId);
325
326
  });
326
327
  return { sessionId, ticket };
327
328
  }
328
- function openShellSession(repoPath) {
329
- return spawnShellPty(repoPath, "shell");
329
+ function openShellSession(repoPath, initialCommand) {
330
+ return spawnShellPty(repoPath, "shell", initialCommand);
330
331
  }
331
332
  function closeShellSession(sessionId) {
332
333
  stopPtySession(sessionId);
@@ -335,9 +336,8 @@ var columnShells = /* @__PURE__ */ new Map();
335
336
  function openOrReuseColumnShell(key, repoPath, initialCommand) {
336
337
  const existing = columnShells.get(key);
337
338
  if (existing && getPtySession(existing.sessionId)) return existing;
338
- const shell = spawnShellPty(repoPath, "column-shell");
339
+ const shell = spawnShellPty(repoPath, "column-shell", initialCommand);
339
340
  columnShells.set(key, shell);
340
- if (initialCommand) getPtySession(shell.sessionId)?.pty.write(`${initialCommand}\r`);
341
341
  return shell;
342
342
  }
343
343
  function closeColumnShell(key) {
@@ -2006,7 +2006,9 @@ function handleRequest(req, res) {
2006
2006
  return;
2007
2007
  }
2008
2008
  if (pathname === "/shell/open") {
2009
- sendJson(res, 200, openShellSession(entry.repoRoot));
2009
+ const kind = typeof query.kind === "string" ? query.kind : "shell";
2010
+ if (!COLUMN_SHELL_KINDS.includes(kind)) throw new HttpError(400, "Par\xE2metro kind inv\xE1lido.");
2011
+ sendJson(res, 200, openShellSession(entry.repoRoot, kind === "claude" ? CLAUDE_BYPASS_COMMAND : void 0));
2010
2012
  return;
2011
2013
  }
2012
2014
  if (pathname === "/shell/close") {
@@ -3278,12 +3280,25 @@ async function restartCardSession(supabase, config, card) {
3278
3280
  }
3279
3281
 
3280
3282
  // src/deploy.ts
3283
+ var deploysInFlight = /* @__PURE__ */ new Set();
3281
3284
  async function handleDeployRequested(supabase, config, project) {
3282
3285
  const registered = config.registeredProjects.find((candidate) => candidate.id === project.id);
3283
3286
  if (!registered) {
3284
3287
  logger.runner.warn("DEPLOY", `Ignoring deploy request: project ${project.id} is not registered on this runner.`);
3285
3288
  return;
3286
3289
  }
3290
+ if (deploysInFlight.has(project.id)) {
3291
+ logger.runner.info("DEPLOY", `Deploy already in progress for project ${project.id}, skipping duplicate trigger.`);
3292
+ return;
3293
+ }
3294
+ deploysInFlight.add(project.id);
3295
+ try {
3296
+ await runDeploy(supabase, config, project);
3297
+ } finally {
3298
+ deploysInFlight.delete(project.id);
3299
+ }
3300
+ }
3301
+ async function runDeploy(supabase, config, project) {
3287
3302
  const allCards = await listCardsInColumn(supabase, project.id, "deploy");
3288
3303
  const cards = allCards.filter((card) => card.assigned_user_id === config.ownerUserId);
3289
3304
  if (cards.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-board-runner",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Local runner for Agent Board — signs in with your own Supabase account (no shared secrets) and drives Claude Code against repos under your local repos root.",
5
5
  "type": "module",
6
6
  "bin": {