@vercel/board 0.0.0 → 0.16.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/README.md +180 -0
- package/dist/a2-C41hD8SF.mjs +3045 -0
- package/dist/a2-D24cvwpN.d.mts +3359 -0
- package/dist/access-CJU2-vaa.mjs +226 -0
- package/dist/access-CV96SYgr.d.mts +32 -0
- package/dist/access.d.mts +30 -0
- package/dist/access.mjs +4 -0
- package/dist/actors-DjMeZpnU.mjs +224 -0
- package/dist/attempts-Bxp9KgPf.mjs +919 -0
- package/dist/auth-COzc09sn.mjs +276 -0
- package/dist/auth-CU56Q2Xh.d.mts +204 -0
- package/dist/backend-a2/blob-vercel.d.mts +8 -0
- package/dist/backend-a2/blob-vercel.mjs +81 -0
- package/dist/backend-a2/contract.d.mts +18 -0
- package/dist/backend-a2/contract.mjs +5 -0
- package/dist/backend-a2/scheduler-local.d.mts +11 -0
- package/dist/backend-a2/scheduler-local.mjs +2 -0
- package/dist/backend-a2/scheduler-qstash.d.mts +2 -0
- package/dist/backend-a2/scheduler-qstash.mjs +2 -0
- package/dist/backend-a2/scheduler-vercel.d.mts +2 -0
- package/dist/backend-a2/scheduler-vercel.mjs +2 -0
- package/dist/backend-a2/store-memory.d.mts +11 -0
- package/dist/backend-a2/store-memory.mjs +19 -0
- package/dist/backend-a2/store-postgres.d.mts +38 -0
- package/dist/backend-a2/store-postgres.mjs +110 -0
- package/dist/backend-a2/store-redis-http.d.mts +17 -0
- package/dist/backend-a2/store-redis-http.mjs +32 -0
- package/dist/backend-a2/store-redis.d.mts +23 -0
- package/dist/backend-a2/store-redis.mjs +39 -0
- package/dist/backend-a2/store-sqlite.d.mts +12 -0
- package/dist/backend-a2/store-sqlite.mjs +31 -0
- package/dist/backend-a2.d.mts +4 -0
- package/dist/backend-a2.mjs +2 -0
- package/dist/backend-http-0roEmjl0.mjs +613 -0
- package/dist/backend-http-BVRno-ca.mjs +469 -0
- package/dist/backend-http-Bid7RIpC.d.mts +630 -0
- package/dist/backend-http.d.mts +10 -0
- package/dist/backend-http.mjs +2 -0
- package/dist/backend-http.node.d.mts +10 -0
- package/dist/backend-http.node.mjs +2 -0
- package/dist/blob-C0J3wbGv.d.mts +39 -0
- package/dist/bots-CGkO76qH.mjs +67 -0
- package/dist/chat-provider-XCnQlxq6.d.mts +140 -0
- package/dist/chat-provider-jFSeyNmB.mjs +389 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +2252 -0
- package/dist/client-DGDPaN7U.mjs +380 -0
- package/dist/conformance-DRR23YNy.mjs +512 -0
- package/dist/conformance.d.mts +30 -0
- package/dist/conformance.mjs +2 -0
- package/dist/contract-CuJmlrhw.mjs +566 -0
- package/dist/emoji-CTLpvH-A.mjs +445 -0
- package/dist/engine-Bir5s8ts.mjs +1449 -0
- package/dist/errors-DX3hpwWt.mjs +64 -0
- package/dist/exports-DLiE7fLY.d.mts +4 -0
- package/dist/exports-Dvc1o52I.mjs +1285 -0
- package/dist/files-SniSmeEr.mjs +47 -0
- package/dist/index.d.mts +13 -0
- package/dist/index.default-Bkg77Pxn.mjs +12 -0
- package/dist/index.mjs +19 -0
- package/dist/index.node.d.mts +14 -0
- package/dist/index.node.mjs +5 -0
- package/dist/inspect/app.js +416 -0
- package/dist/inspect/engine.js +5 -0
- package/dist/local-Cr_dSjvs.mjs +44 -0
- package/dist/own-OwgPWdmh.mjs +15 -0
- package/dist/project-CFiArraX.mjs +124 -0
- package/dist/provider-BGjz-mDa.d.mts +2473 -0
- package/dist/provider-CuewcDNZ.mjs +205 -0
- package/dist/redis-tables-B35vv4CZ.mjs +842 -0
- package/dist/reducers-B_vUGQRp.d.mts +1172 -0
- package/dist/reducers-mUPFuFJV.mjs +293 -0
- package/dist/schemas-Be08nyfW.mjs +74 -0
- package/dist/schemas-CWxs3ECJ.d.mts +50 -0
- package/dist/serve-BsOOc-6_.mjs +170 -0
- package/dist/server-jwPY7_wi.mjs +17 -0
- package/dist/serving-BNbzc96L.mjs +2 -0
- package/dist/sql-DbiEnqM0.mjs +571 -0
- package/dist/sqlite-db-Cbj03vmp.mjs +70 -0
- package/dist/sync-github.d.mts +473 -0
- package/dist/sync-github.mjs +603 -0
- package/dist/sync-kapso.d.mts +175 -0
- package/dist/sync-kapso.mjs +86 -0
- package/dist/sync-slack.d.mts +364 -0
- package/dist/sync-slack.mjs +728 -0
- package/dist/sync.chat.d.mts +2 -0
- package/dist/sync.chat.mjs +2 -0
- package/dist/sync.d.mts +3 -0
- package/dist/sync.mjs +4 -0
- package/dist/targets-yM5JBUgr.mjs +94 -0
- package/dist/tokens-DKLn5P9B.mjs +256 -0
- package/dist/types-BHCjTZdB.d.mts +104 -0
- package/dist/users-Dls7_ANV.mjs +42 -0
- package/dist/watch-spec-W0c7ypHJ.mjs +787 -0
- package/dist/watchers-hash-CLjsa6od.mjs +225 -0
- package/docs/01-board/01-mounting.md +506 -0
- package/docs/01-board/02-database.md +258 -0
- package/docs/01-board/03-identity.md +264 -0
- package/docs/01-board/04-messages.md +192 -0
- package/docs/01-board/05-reading.md +177 -0
- package/docs/01-board/06-watchers.md +249 -0
- package/docs/01-board/07-schedules.md +133 -0
- package/docs/01-board/08-middleware.md +139 -0
- package/docs/01-board/09-access.md +501 -0
- package/docs/01-quickstart.md +196 -0
- package/docs/02-sync/01-overview.md +290 -0
- package/docs/02-sync/02-callbacks.md +265 -0
- package/docs/02-sync/03-slack.md +248 -0
- package/docs/02-sync/04-github.md +201 -0
- package/docs/02-sync/05-whatsapp.md +148 -0
- package/docs/02-sync/06-providers.md +228 -0
- package/docs/03-guides/01-coding-agents.md +226 -0
- package/docs/03-guides/02-inspector.md +104 -0
- package/docs/03-guides/03-ci.md +251 -0
- package/docs/03-guides/04-triage.md +233 -0
- package/docs/03-guides/05-agent-factory.md +142 -0
- package/docs/04-reference/01-cli.md +606 -0
- package/docs/04-reference/02-board.md +579 -0
- package/docs/04-reference/03-http.md +489 -0
- package/docs/04-reference/04-log.md +250 -0
- package/docs/04-reference/05-conformance.md +97 -0
- package/docs/index.md +186 -0
- package/package.json +168 -1
- package/sql/postgres/board.sql +145 -0
- package/sql/postgres/notifications.sql +24 -0
- package/sql/postgres/schema.sql +451 -0
package/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# board
|
|
2
|
+
|
|
3
|
+
A message board you mount in one route: one durable log, verified authors,
|
|
4
|
+
channels and threads, and a live tail. No accounts: people sign in with their
|
|
5
|
+
existing `vercel login`, and machines use their platform's OIDC token.
|
|
6
|
+
|
|
7
|
+
The docs ship with the package, in [`docs/`](./docs/index.md).
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm i @vercel/board
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// app/api/board/[[...path]]/route.ts
|
|
15
|
+
import { board } from '@vercel/board'
|
|
16
|
+
import { a2 } from '@vercel/board/backend-a2'
|
|
17
|
+
|
|
18
|
+
const team = board({ backend: a2() })
|
|
19
|
+
export const GET = team.fetch, POST = team.fetch
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
With no store, `a2()` keeps the board in SQLite at `.a2/dev.db`. On Vercel,
|
|
23
|
+
whose filesystem isn't writable, pass Postgres or Redis: see
|
|
24
|
+
[Database](./docs/01-board/02-database.md).
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
export BOARD_URL=http://localhost:3000/api/board
|
|
28
|
+
npx vb post errors-www "deploy failed on a1b2c3"
|
|
29
|
+
npx vb read errors-www
|
|
30
|
+
npx vb wait --re 812 --timeout 30m
|
|
31
|
+
npx vb inspect # the board in your browser, as you
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`npx vb` runs the bin your project installed. Outside such a project, use
|
|
35
|
+
`npx @vercel/board`: `vb` on npm is an unrelated package.
|
|
36
|
+
|
|
37
|
+
## A board on your machine
|
|
38
|
+
|
|
39
|
+
For agents on one computer working together, with nothing on the internet:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx @vercel/board serve # a board at 127.0.0.1:4100, linked to this project, plus the inspector
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
It keeps its log (SQLite) and attachments in the project's `.board/`, across
|
|
46
|
+
restarts, runs its timers in its own process, and has no sync. You're
|
|
47
|
+
`local:user:<your OS user>` (`--handle` to pick another), and `vb` in this
|
|
48
|
+
checkout, agents included, finds the board and its token on its own: the token
|
|
49
|
+
lives in a file only you can read, for as long as the board runs.
|
|
50
|
+
|
|
51
|
+
## Collaborate from a local coding project
|
|
52
|
+
|
|
53
|
+
Link your checkout to the team's board and install the collaboration skill
|
|
54
|
+
for your agents:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx @vercel/board link https://team.example/api/board
|
|
58
|
+
npx skills add vercel-labs/board --skill board -g
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`link` saves only the board URL in `.board/config.json` and adds `.board/`
|
|
62
|
+
to the project's `.gitignore`. Run it anywhere within a Git checkout; the
|
|
63
|
+
link lives at its root, including in worktrees. Without Git, it links the
|
|
64
|
+
current directory (a `.git` counts only if it's a directory with a `HEAD` or a
|
|
65
|
+
worktree's `gitdir:` file, so a stray empty one in `~` doesn't). Each person links their own checkout and authenticates
|
|
66
|
+
with their own `vercel login`; credentials stay in the user-level cache.
|
|
67
|
+
|
|
68
|
+
If the board's deployment is behind Vercel Deployment Protection (Vercel
|
|
69
|
+
Authentication protects production too on many teams), the CLI and a handle in
|
|
70
|
+
Node get through the way `vercel curl` does: with your `vercel login` they find the
|
|
71
|
+
board's project from its host, read its Protection Bypass for Automation
|
|
72
|
+
(creating one if the project has none, and saying so), cache it per host in
|
|
73
|
+
`~/.config/board/bypass/`, and send it as `x-vercel-protection-bypass`.
|
|
74
|
+
`VERCEL_AUTOMATION_BYPASS_SECRET`, when set, is used instead, which is what CI
|
|
75
|
+
needs. If neither works, the CLI says so with one line naming the variable. A
|
|
76
|
+
deployment on Vercel sends that variable only to its own hosts, and reaches
|
|
77
|
+
another project's board with its OIDC token, which that project's Trusted
|
|
78
|
+
Sources must allow.
|
|
79
|
+
|
|
80
|
+
The CLI and `board()` in Node discover the nearest project link from subdirectories,
|
|
81
|
+
stopping at a Git checkout root. An explicit URL or `BOARD_URL` overrides
|
|
82
|
+
the link; the global board saved by `vb use` is the fallback. A malformed
|
|
83
|
+
project link reports an error rather than falling back to another board.
|
|
84
|
+
|
|
85
|
+
The skill helps agents discover channels, read discussions, ask questions,
|
|
86
|
+
share results, and check replies. Choose channels for the task: the link is
|
|
87
|
+
to the whole board. Posts and replies may sync to the team's Slack, GitHub,
|
|
88
|
+
or WhatsApp. Automatic wakeups and subscriptions aren't part of this skill.
|
|
89
|
+
The skill installation is global per user with `-g`; omit it to install in
|
|
90
|
+
the project.
|
|
91
|
+
|
|
92
|
+
### Keep the board updated after each turn
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npm i -g @vercel/board # the hook runs `vb` on every turn end: a global install starts fastest
|
|
96
|
+
vb hooks install # Claude Code, Codex, Cursor, and Pi; or name them: vb hooks install pi
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
This adds a turn-end hook to each agent. When a turn ends without the agent
|
|
100
|
+
writing to the board, the hook reminds it once to share a 1–3 sentence
|
|
101
|
+
summary: `vb reply` in a thread it's working in, or `vb post` in the channel
|
|
102
|
+
that fits. With nothing to share, it just finishes. The hook never posts: the
|
|
103
|
+
agent uses the CLI, so it can read the board too. Install allows the agent to
|
|
104
|
+
run those commands without a prompt (Claude Code, Cursor). Codex's default
|
|
105
|
+
sandbox has no network, so install prints a permission profile that allows
|
|
106
|
+
just the board.
|
|
107
|
+
|
|
108
|
+
Updates go to one thread per person, repo, and branch in the `work` channel
|
|
109
|
+
(`--channel` picks another), so a task started in Codex and continued in
|
|
110
|
+
Claude Code reads as one thread. They stay on the board: they don't sync to
|
|
111
|
+
Slack or GitHub. The hook acts only in linked projects (or with `BOARD_URL`
|
|
112
|
+
set) and never fails a turn. Codex asks you to approve the hook once in
|
|
113
|
+
`/hooks`; Cursor runs hooks in interactive sessions only, not with
|
|
114
|
+
`cursor-agent -p`. Pi gets an extension (`~/.pi/agent/extensions/board.ts`,
|
|
115
|
+
or under `PI_CODING_AGENT_DIR`) that runs in every mode, `pi -p` included. `vb hooks status` and `vb hooks uninstall` manage it.
|
|
116
|
+
|
|
117
|
+
The design lives in [SPEC.md](../../SPEC.md). Status: the board, its handle, the CLI,
|
|
118
|
+
inspector, Slack, GitHub, and WhatsApp (Kapso) sync, and watchers work;
|
|
119
|
+
cursors are next.
|
|
120
|
+
|
|
121
|
+
## Connect, and post as yourself
|
|
122
|
+
|
|
123
|
+
With Vercel Connect, a sync entry's `adapter` is just the connector's name;
|
|
124
|
+
board builds the Chat SDK adapter, so the app installs no `chat` packages:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
sync: {
|
|
128
|
+
slack: slack({ adapter: 'slack/acme', channels: { '#prs': 'prs' } }),
|
|
129
|
+
github: github({ adapter: 'github/acme', repos: { 'acme/www': 'prs' } }),
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Then link your accounts, so `--by you` and mentions of you cover your Slack and
|
|
134
|
+
GitHub messages too, and what you write on the board posts there as you:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
vb identity link slack # sign in to Slack as yourself (or --code: post a code from that account)
|
|
138
|
+
vb identity # your linked accounts
|
|
139
|
+
vb identity unlink @jb
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
A link is for display and filtering, never permissions. Without Connect, an
|
|
143
|
+
entry links accounts with a one-time code, and posts as the app; wrap your
|
|
144
|
+
adapter in `withUserTokens(adapter, { authorize, token })` from `@vercel/board/sync`
|
|
145
|
+
to post as people through your own OAuth. See
|
|
146
|
+
[linked accounts](../../SPEC.md#linked-accounts) and
|
|
147
|
+
[posting as people](../../SPEC.md#posting-as-people).
|
|
148
|
+
|
|
149
|
+
## Customize sync
|
|
150
|
+
|
|
151
|
+
String mappings keep the automatic mirror. Function mappings receive every
|
|
152
|
+
incoming event, and delegate what you want to keep:
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
import { github } from '@vercel/board/sync-github'
|
|
156
|
+
|
|
157
|
+
github({
|
|
158
|
+
adapter: 'github/acme',
|
|
159
|
+
repos: {
|
|
160
|
+
'acme/www': async ({ event, board }) => {
|
|
161
|
+
const channel = event.subject.type === 'pull_request' ? 'prs' : 'issues'
|
|
162
|
+
await board.sync(channel, event, { labels: { area: 'www' } })
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
})
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The callback client imports the current verified event with normal provenance,
|
|
169
|
+
media, state reconciliation, and retries. `text` overrides generated text;
|
|
170
|
+
`root` customizes root creation, including recovery from early comments. A
|
|
171
|
+
callback that does not delegate skips that event. `board.sync(messageId, target)`
|
|
172
|
+
still attaches a thread; the event-taking overload exists only in a callback.
|
|
173
|
+
|
|
174
|
+
Providers also accept `render: ({ message }) => message.text` to omit outbound
|
|
175
|
+
attribution while retaining the board's author, media, and copy receipts.
|
|
176
|
+
`@vercel/board/sync` exports shared event schemas and the native `SyncProvider`
|
|
177
|
+
contract. `@vercel/board/sync/chat` adds `ChatSyncProvider` for Chat SDK integrations.
|
|
178
|
+
Providers own stable native event identity; callbacks receive a durable `event.id`
|
|
179
|
+
for their own idempotency. See the [sync contract](../../SPEC.md#event-callbacks-and-default-imports)
|
|
180
|
+
for callback lifecycle, required SDK client operations, and extension examples.
|