Extracts the extractText helper + ActivityEntry type into their own
module so unit tests can import them without dragging server.ts's
top-level boot side-effects (cursor load, MCP transport connect, poll
loop) into the test runner. server.ts re-imports both — the wire
behavior is unchanged.
Tests cover the v0/v1 part-discriminator regression that landed on
2026-04-30 (every canvas peer message returning act.summary because
parts had `kind` instead of `type`):
- v1 `kind: text` parts (current production shape)
- v0 `type: text` back-compat
- multi-part text join, ignore non-text parts
- body-shape priority: params.message.parts > params.parts > body.parts
- empty-text-part recovery: skips empty candidate, tries next
- summary fallback when no shape matches
- `(empty A2A message)` fallback when summary is null
Adds:
- extract-text.ts (helper + type, no side-effects)
- extract-text.test.ts (9 tests)
- .github/workflows/test.yml (bun test on push/PR)
- "test": "bun test" script in package.json
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>