2026-02-11 17:42:51 -08:00
|
|
|
{
|
|
|
|
|
"name": "beadboard",
|
|
|
|
|
"version": "0.1.0",
|
|
|
|
|
"private": true,
|
|
|
|
|
"license": "MIT",
|
2026-03-02 20:44:07 -08:00
|
|
|
"bin": {
|
|
|
|
|
"beadboard": "bin/beadboard.js",
|
|
|
|
|
"bb": "bin/beadboard.js"
|
|
|
|
|
},
|
2026-02-11 17:42:51 -08:00
|
|
|
"scripts": {
|
|
|
|
|
"dev": "next dev",
|
|
|
|
|
"build": "next build",
|
|
|
|
|
"start": "next start",
|
2026-02-13 12:27:09 -08:00
|
|
|
"lint": "eslint .",
|
2026-02-11 17:42:51 -08:00
|
|
|
"typecheck": "tsc --noEmit",
|
[beadboard] Add Dispatch-to-Agent button and prompt template
## Context
We want a one-click path from the right-panel task detail into the
claude-agent-service runner, without the user copy-pasting the bead id
into a CLI or another tab. The runner expects a self-contained prompt
that restates the bead id, title, description, acceptance criteria, and
the guard rails the agent must operate under (no push, no file edits,
no terraform/kubectl/helm). The prompt template lives in `src/lib/` so
it can be tested and reused from the server-side dispatch route.
The right-panel button needs to:
- Only appear when the bead is actionable (`open` or `in_progress`).
- Disable itself while the claude-agent-service is already busy (the
service has a global `asyncio.Lock` — parallel dispatches 409).
- Disable itself when the bead lacks acceptance criteria. An agent that
doesn't know what "done" looks like burns budget and closes nothing.
- Surface the resulting `job_id` or any 409/error back to the user.
The project has no toast library (no `sonner`, no `react-hot-toast`), so
we render status inline under the button rather than pulling in a new
dependency for this single surface.
## This change
- `src/lib/dispatch-prompt.ts` exports `buildDispatchPrompt(bead)` which
produces the exact prompt the agent runner expects. Bead id, priority
(`P<n>`), issue type, description, and acceptance criteria are
interpolated; `<job_id>` stays a literal placeholder because the agent
only learns its own id at runtime (env var).
- `src/components/shared/dispatch-button.tsx` is a focused client
component with three responsibilities:
1. Poll `GET /api/agent-status` every 5 s while the panel is open
(plus an initial fetch on mount), mirror `busy` into local state.
2. On click, `POST /api/agent-dispatch` with `{taskId}`; branch on
200 / 409 / other.
3. Render an inline status line under the button (`text-xs`, tone
driven by `ok | info | error`) — no toast dep required.
The poll interval self-clears on unmount so closing the panel stops
network traffic.
- `src/components/shared/thread-drawer.tsx` renders `<DispatchButton>`
alongside the existing "Edit task" button in the summary section,
wrapped in a `flex-wrap` so the two controls reflow on narrow panes.
- Registers two new tests in `package.json`'s enumerated test script.
## What is NOT in this change
- The `/api/agent-dispatch` and `/api/agent-status` routes themselves —
those land in the next commit. The button calls them but the server
side is intentionally a separate step so each commit can be reviewed
in isolation.
- No real toast system is introduced; inline status is sufficient.
- No change to how task state transitions on dispatch. The agent itself
is expected to run `bd update --claim` / `bd close` via the prompt's
operating rules.
## Test Plan
### Automated
```
$ node --import tsx --test tests/lib/dispatch-prompt.test.ts \
tests/components/shared/dispatch-button.test.tsx
# tests 7 pass 7 fail 0
```
Covers:
- Bead id appears in opening paragraph and in both `bd note` / `bd close`
commands.
- Priority rendered as `P<n>`, issue type echoed.
- Description and acceptance criteria quoted verbatim when present.
- `(no description)` / `(no acceptance criteria)` fallbacks when null.
- Guard rails block present (no terraform/kubectl/helm, workspace bd
path, `bd update … --status blocked` fallback).
- DispatchButton module loads and exports both named and default.
`npm run typecheck` shows only the pre-existing `OrchestratorChatMessage`
type gap in `left-panel.tsx` that reproduces on untouched `main`.
### Manual Verification
1. `npm install`
2. `npm run dev`
3. Open `http://localhost:3000/?task=<some-open-bead-id>`
4. Expected: "Dispatch to Agent" button next to "Edit task" in the
right-panel summary section.
5. Button disabled on beads with `status in {closed, blocked, deferred}`
(they don't render the button at all).
6. Button disabled on beads missing acceptance criteria, with tooltip
"Task is missing acceptance criteria — cannot dispatch.".
7. Click: UI flips to "Dispatching…"; once the next commit is merged,
the agent-dispatch route will surface a `job_id` (today it returns
404 which renders as "Dispatch failed (HTTP 404)").
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 14:04:34 +00:00
|
|
|
"test": "node --test tests/bootstrap.test.mjs && node --import tsx --test tests/pr14-critical-bugs.test.ts && node --import tsx --test tests/components/shared/base-card.test.tsx && node --import tsx --test tests/components/shared/agent-avatar.test.tsx && node --import tsx --test tests/components/sessions/sessions-header.test.ts && node --import tsx --test tests/components/sessions/agent-station-logic.test.ts && node --import tsx --test tests/lib/parser.test.ts && node --import tsx --test tests/lib/pathing.test.ts && node --import tsx --test tests/components/shared/left-panel.test.tsx && node --import tsx --test tests/components/shared/top-bar.test.tsx && node --import tsx --test tests/components/shared/mobile-nav.test.tsx && node --import tsx --test tests/components/swarm/swarm-card.test.tsx && node --import tsx --test tests/hooks/url-state-integration.test.ts && node --import tsx --test tests/hooks/use-graph-analysis.test.ts && node --import tsx --test tests/components/graph/smart-dag.test.tsx && node --import tsx --test tests/components/unified-shell.test.tsx && node --import tsx --test tests/components/blocked-triage-modal.test.tsx && node --import tsx --test tests/components/graph/graph-node-labels.test.tsx && node --import tsx --test tests/components/graph/graph-node-assign.test.tsx && node --import tsx --test tests/components/graph/graph-node-conversation.test.tsx && node --import tsx --test tests/lib/coord-schema.test.ts && node --import tsx --test tests/lib/install-manifest.test.ts && node --import tsx --test tests/lib/runtime-manager.test.ts && node --import tsx --test tests/lib/coord-events.test.ts && node --import tsx --test tests/api/coord-events-route.test.ts && node --import tsx --test tests/lib/coord-projections-inbox.test.ts && node --import tsx --test tests/lib/coord-projections-reservations.test.ts && node --import tsx --test tests/components/sessions/conversation-drawer-coord.test.tsx && node --import tsx --test tests/scripts/beadboard-launcher.test.ts && node --import tsx --test tests/scripts/beadboard-launcher-runtime.test.ts && node --import tsx --test tests/scripts/beadboard-launcher-status-text.test.ts && node --import tsx --test tests/scripts/install-wrappers-contract.test.ts && node --import tsx --test tests/scripts/install-sh-smoke.test.ts && node --import tsx --test tests/scripts/install-legacy-migration.test.ts && node --import tsx --test tests/scripts/installer-ci-contract.test.ts && node --import tsx --test tests/docs/installer-quickstart-contract.test.ts && node --import tsx --test tests/docs/runtime-manager-adr-contract.test.ts && node --import tsx --test tests/cli/beadboard-cli.test.ts && node --import tsx --test tests/cli/beadboard-bin-routing.test.ts && node --import tsx --test tests/cli/beadboard-help-output.test.ts && node --import tsx --test tests/skills/beadboard-driver/resolve-bb.test.ts && node --import tsx --test tests/skills/beadboard-driver/session-preflight.test.ts && node --import tsx --test tests/skills/beadboard-driver/generate-agent-name.test.ts && node --import tsx --test tests/skills/beadboard-driver/readiness-report.test.ts && node --import tsx --test tests/skills/beadboard-driver/skill-local-runner.test.ts && node --import tsx --test tests/skills/beadboard-driver/diagnose-env.test.ts && node --import tsx --test tests/skills/beadboard-driver/heal-common-issues.test.ts && node --import tsx --test tests/lib/epic-graph.test.ts && node --import tsx --test tests/components/shared/left-panel-filtering.test.ts && node --import tsx --test tests/hooks/use-beads-subscription-contract.test.ts && node --import tsx --test tests/components/graph/dependency-graph-hide-closed-contract.test.ts && node --import tsx --test tests/components/shared/unified-shell-hide-closed-contract.test.ts && node --import tsx --test tests/lib/agent-registry.test.ts && node --import tsx --test tests/api/agents-mail.test.ts && node --import tsx --test tests/skills/beadboard-driver/bb-mail-shim.test.ts && node --import tsx --test tests/skills/beadboard-driver/ensure-bb-mail-configured.test.ts && node -
|
2026-02-16 10:10:50 -08:00
|
|
|
"video": "remotion preview src/video/index.ts",
|
|
|
|
|
"video:render": "remotion render src/video/index.ts Main out/video.mp4",
|
|
|
|
|
"video:thumbnail": "remotion still src/video/index.ts Main out/thumbnail.png --frame=60"
|
2026-02-11 17:42:51 -08:00
|
|
|
},
|
|
|
|
|
"dependencies": {
|
2026-03-24 15:39:19 -07:00
|
|
|
"@mariozechner/pi-agent-core": "^0.57.1",
|
|
|
|
|
"@mariozechner/pi-ai": "^0.57.1",
|
|
|
|
|
"@mariozechner/pi-coding-agent": "^0.57.1",
|
2026-02-15 21:19:58 -08:00
|
|
|
"@radix-ui/react-avatar": "^1.1.11",
|
2026-02-20 22:19:38 -08:00
|
|
|
"@radix-ui/react-dialog": "^1.1.15",
|
2026-02-15 21:19:58 -08:00
|
|
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
2026-02-20 22:19:38 -08:00
|
|
|
"@radix-ui/react-label": "^2.1.8",
|
2026-02-15 21:19:58 -08:00
|
|
|
"@radix-ui/react-scroll-area": "^1.2.10",
|
2026-02-20 22:19:38 -08:00
|
|
|
"@radix-ui/react-select": "^2.2.6",
|
2026-02-15 21:19:58 -08:00
|
|
|
"@radix-ui/react-separator": "^1.1.8",
|
|
|
|
|
"@radix-ui/react-slot": "^1.2.4",
|
2026-02-20 22:19:38 -08:00
|
|
|
"@radix-ui/react-tabs": "^1.1.13",
|
2026-02-15 21:19:58 -08:00
|
|
|
"@radix-ui/react-tooltip": "^1.2.8",
|
2026-02-16 10:10:50 -08:00
|
|
|
"@remotion/google-fonts": "^4.0.422",
|
|
|
|
|
"@remotion/tailwind": "^4.0.422",
|
|
|
|
|
"@remotion/zod-types": "^4.0.422",
|
2026-03-24 15:39:19 -07:00
|
|
|
"@sinclair/typebox": "^0.34.48",
|
2026-02-12 23:37:27 -08:00
|
|
|
"@xyflow/react": "^12.10.0",
|
2026-02-11 21:05:27 -08:00
|
|
|
"chokidar": "^5.0.0",
|
2026-02-15 21:19:58 -08:00
|
|
|
"class-variance-authority": "^0.7.1",
|
|
|
|
|
"clsx": "^2.1.1",
|
2026-02-12 23:37:27 -08:00
|
|
|
"dagre": "^0.8.5",
|
2026-02-11 18:38:51 -08:00
|
|
|
"framer-motion": "^11.18.2",
|
2026-02-15 21:19:58 -08:00
|
|
|
"lucide-react": "^0.564.0",
|
2026-02-28 17:08:38 -08:00
|
|
|
"mysql2": "^3.18.2",
|
2026-02-11 17:42:51 -08:00
|
|
|
"next": "15.5.7",
|
|
|
|
|
"react": "19.2.1",
|
2026-02-15 21:19:58 -08:00
|
|
|
"react-dom": "19.2.1",
|
2026-02-16 10:10:50 -08:00
|
|
|
"remotion": "^4.0.422",
|
2026-02-15 21:19:58 -08:00
|
|
|
"tailwind-merge": "^3.4.1",
|
2026-02-16 10:10:50 -08:00
|
|
|
"tailwindcss-animate": "^1.0.7",
|
2026-03-05 15:57:33 -08:00
|
|
|
"tsx": "^4.21.0",
|
2026-02-16 10:10:50 -08:00
|
|
|
"zod": "3.22.3"
|
2026-02-11 17:42:51 -08:00
|
|
|
},
|
|
|
|
|
"devDependencies": {
|
2026-02-11 19:01:34 -08:00
|
|
|
"@playwright/test": "^1.58.2",
|
2026-02-16 10:10:50 -08:00
|
|
|
"@remotion/cli": "^4.0.422",
|
2026-02-12 23:37:27 -08:00
|
|
|
"@types/dagre": "^0.7.53",
|
2026-02-11 17:42:51 -08:00
|
|
|
"@types/node": "^22.10.0",
|
|
|
|
|
"@types/react": "^19.0.0",
|
|
|
|
|
"@types/react-dom": "^19.0.0",
|
2026-02-11 18:38:51 -08:00
|
|
|
"autoprefixer": "^10.4.24",
|
2026-02-12 23:37:27 -08:00
|
|
|
"eslint": "9.39.2",
|
2026-02-20 22:19:38 -08:00
|
|
|
"eslint-config-next": "^15.5.7",
|
2026-02-11 19:01:34 -08:00
|
|
|
"playwright": "^1.58.2",
|
2026-02-11 18:38:51 -08:00
|
|
|
"postcss": "^8.5.6",
|
|
|
|
|
"tailwindcss": "^3.4.17",
|
2026-02-11 17:42:51 -08:00
|
|
|
"typescript": "^5.7.2"
|
|
|
|
|
}
|
2026-02-15 21:19:58 -08:00
|
|
|
}
|