Skip to content

Commit 5dab59a

Browse files
sync: upstream Vercel Chat v4.25.0
Port all 5 changes from upstream v4.25.0: - feat: Plan/PostableObject blocks for threads (new plan.py module) - feat: StreamingMarkdownRenderer wrap_tables_for_append option (Slack disables code-fencing since it now supports native markdown tables) - feat: Teams Select/RadioSelect card rendering (Adaptive Card ChoiceSet) - feat: GitHub issue comment threads (github:owner/repo:issue:42 format) - fix: Slack OAuth redirect_uri handling New versioning scheme: - 0.{upstream_minor}.{patch} — our 0.25.0 = synced to upstream 4.25.0 - UPSTREAM_PARITY constant in __init__.py for programmatic access - Sync procedure documented in UPSTREAM_SYNC.md Updated docs: - CLAUDE.md: version mapping, thread ID formats, message handling flow, full validation command - UPSTREAM_SYNC.md: step-by-step sync procedure with checklist - CHANGELOG.md: public-facing release notes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent bf1d78b commit 5dab59a

21 files changed

Lines changed: 1870 additions & 108 deletions

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# Changelog
22

3+
## 0.25.0 (2026-04-10)
4+
5+
Synced to [Vercel Chat 4.25.0](https://github.com/vercel/chat). New versioning: our minor version matches the upstream minor version.
6+
7+
### New features (from upstream 4.25.0)
8+
- **Plan blocks**: `Plan` PostableObject for structured task lists with live updates. Post a plan to a thread, then `add_task()`, `update_task()`, and `complete()` with automatic card rendering.
9+
- **Streaming table option**: `StreamingMarkdownRenderer(wrap_tables_for_append=False)` disables code-fence wrapping for platforms with native table support. Slack adapter now uses this by default.
10+
- **Teams Select/RadioSelect**: `Select` and `RadioSelect` card elements now render as Adaptive Card `Input.ChoiceSet` with auto-injected submit button.
11+
- **GitHub issue threads**: `issue_comment` webhooks on plain issues (not just PRs) now create threads with format `github:owner/repo:issue:42`.
12+
- **Slack OAuth redirect fix**: `handle_oauth_callback` correctly forwards `redirect_uri` option.
13+
14+
### Versioning
15+
- Version scheme changed from `0.0.1aX` to `0.{upstream_minor}.{patch}`
16+
- `UPSTREAM_PARITY` constant in `chat_sdk.__init__` for programmatic access
17+
- Sync procedure documented in [UPSTREAM_SYNC.md](docs/UPSTREAM_SYNC.md)
18+
319
## 0.0.1a12 (2026-04-10)
420

521
Python 3.10 support, async-safe Chat resolver, and a large correctness audit.

CLAUDE.md

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,57 @@
11
# Claude Code Quick Reference -- chat-sdk-python
22

33
## What is this?
4-
Python port of Vercel Chat SDK. Multi-platform async chat framework.
4+
Python port of [Vercel Chat SDK](https://github.com/vercel/chat) (v4.25.0). Multi-platform async chat framework.
55

66
## Key Commands
7-
- `uv sync --group dev` -- install dependencies
8-
- `uv run pytest tests/ -q` -- run tests
9-
- `uv run ruff check src/` -- lint
10-
- `uv run ruff format src/` -- format
7+
```bash
8+
uv sync --group dev # install dependencies
9+
uv run pytest tests/ -q # run tests
10+
uv run ruff check src/ tests/ scripts/ # lint
11+
uv run ruff format src/ tests/ scripts/ # format
12+
13+
# Full validation — run before declaring any task done
14+
uv run ruff check src/ tests/ scripts/ && \
15+
uv run ruff format --check src/ tests/ scripts/ && \
16+
uv run python scripts/audit_test_quality.py && \
17+
uv run python scripts/verify_test_fidelity.py && \
18+
uv run pytest tests/ --tb=short -q
19+
```
20+
21+
## Version Mapping
22+
Our version tracks the upstream Vercel Chat minor version:
23+
- `0.25.0` = synced to upstream `4.25.0`
24+
- `0.25.1` = Python-only fixes on top of `4.25.0`
25+
- `0.26.0` = synced to upstream `4.26.0`
26+
- `UPSTREAM_PARITY` constant in `__init__.py` = programmatic access
1127

1228
## Architecture
13-
- `src/chat_sdk/chat.py` -- Main Chat orchestrator (handlers, routing, concurrency)
29+
- `src/chat_sdk/chat.py` -- Chat orchestrator (handlers, routing, concurrency)
1430
- `src/chat_sdk/thread.py` -- Thread (streaming, pagination, subscriptions)
1531
- `src/chat_sdk/channel.py` -- Channel (thread listing, metadata)
32+
- `src/chat_sdk/plan.py` -- Plan (PostableObject for structured task lists)
1633
- `src/chat_sdk/types.py` -- All types (Message, Author, Adapter protocol)
1734
- `src/chat_sdk/adapters/` -- 8 platform adapters
1835
- `src/chat_sdk/shared/` -- Markdown parser, format converter, streaming renderer
1936
- `src/chat_sdk/state/` -- Memory, Redis, Postgres backends
20-
- `tests/` -- 3,267 tests
37+
- `tests/` -- 3,400+ tests
38+
39+
### Thread ID Format
40+
All thread IDs follow: `{adapter}:{channel}:{thread}`
41+
- Slack: `slack:C123ABC:1234567890.123456`
42+
- Teams: `teams:{base64(conversationId)}:{base64(serviceUrl)}`
43+
- Google Chat: `gchat:spaces/ABC123:{base64(threadName)}`
44+
- Discord: `discord:{guildId}:{channelId}[:{threadId}]`
45+
- GitHub: `github:owner/repo:42` (PR) or `github:owner/repo:issue:42`
46+
47+
### Message Handling Flow
48+
1. Platform sends webhook → adapter verifies + parses
49+
2. Adapter calls `chat.process_message()` (or `process_action`, etc.)
50+
3. Chat acquires lock, deduplicates, then routes:
51+
- Subscribed thread → `on_subscribed_message` handlers
52+
- @mention`on_mention` handlers
53+
- DM → `on_direct_message` handlers
54+
- Pattern match → `on_message` handlers
2155

2256
## Principles
2357

@@ -31,25 +65,22 @@ Python port of Vercel Chat SDK. Multi-platform async chat framework.
3165

3266
## Port Rules (TS → Python)
3367

34-
These are specific patterns that broke during the port. The principles above
35-
explain *why*; these explain *what to watch for*.
68+
See docs/UPSTREAM_SYNC.md for the full 15-hazard guide. Key patterns:
3669

37-
- `datetime.utcnow()``datetime.now(tz=UTC)` (deprecated, naive)
38-
- `asyncio.ensure_future``loop.create_task()` (deprecated)
70+
- `x or default``x if x is not None else default` (truthiness trap)
71+
- `datetime.utcnow()``datetime.now(tz=timezone.utc)` (deprecated, naive)
3972
- Raw dicts to `process_*` → typed dataclasses (ActionEvent, etc.)
40-
- camelCase dispatch keys → snake_case
73+
- camelCase dispatch keys → snake_case internally, camelCase at serialization boundary
4174
- `random.choices` for tokens → `secrets.token_hex`
42-
- Optional deps at module level → lazy import
75+
- Optional deps at module level → lazy import inside methods
4376
- `==` for signatures → `hmac.compare_digest`
44-
- `or` for empty-string-valid fields → `is not None`
4577
- Validate external URLs before requests (SSRF)
46-
- Check `extend_lock` return value in loops
47-
48-
## Adding a New Adapter
49-
See docs/ARCHITECTURE.md and CONTRIBUTING.md.
78+
- `chat.activate()` > `register_singleton()` > error (3-level resolver)
5079

5180
## Upstream Sync
52-
See docs/UPSTREAM_SYNC.md for TS->Python translation patterns.
81+
82+
See docs/UPSTREAM_SYNC.md for the full sync procedure, porting hazards, review
83+
checklist, and known non-parity list.
5384

5485
## Known Limitations
5586
- Markdown parser handles common cases but is not full CommonMark
@@ -63,5 +94,5 @@ async mock bugs, and cross-file duplicates. PRs that introduce hard failures
6394
will not pass CI.
6495

6596
**Fidelity check** (`scripts/verify_test_fidelity.py`) verifies every TS
66-
`it("...")` has a matching Python `def test_*()`. Name match ≠ faithful port —
67-
the audit script catches the quality side.
97+
`it("...")` has a matching Python `def test_*()`. Must show 0 missing before
98+
committing test changes.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Multi-platform async chat SDK for Python. Port of [Vercel Chat](https://github.com/vercel/chat).
44

5-
> **Status: Alpha (0.0.1a12)** — API may change. Not yet tested in production.
5+
> **Status: Alpha (0.25.0 — synced to [Vercel Chat 4.25.0](https://github.com/vercel/chat))** — API may change.
66
77
## Why chat-sdk?
88

docs/UPSTREAM_SYNC.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,66 @@
22

33
How to keep `chat-sdk-python` in sync with the [Vercel Chat TS SDK](https://github.com/vercel/chat).
44

5+
## Version Mapping
6+
7+
Our version number tracks the upstream Vercel Chat minor version:
8+
9+
| Python version | Upstream version | Meaning |
10+
|---|---|---|
11+
| `0.25.0` | `4.25.0` | Synced to upstream 4.25.0 |
12+
| `0.25.1` | `4.25.0` | Python-only fix on top of 4.25.0 |
13+
| `0.26.0` | `4.26.0` | Synced to upstream 4.26.0 |
14+
15+
The `UPSTREAM_PARITY` constant in `chat_sdk/__init__.py` provides programmatic access
16+
to the upstream version this release is synced to.
17+
18+
## How to Sync an Upstream Release
19+
20+
Step-by-step procedure for porting a new upstream release (e.g., `4.26.0`):
21+
22+
```bash
23+
# 1. Update the TS repo and check what changed
24+
cd /tmp/vercel-chat && git fetch origin
25+
git log --oneline chat@4.25.0..chat@4.26.0 -- packages/
26+
27+
# 2. For each commit, read the diff
28+
git diff chat@4.25.0..chat@4.26.0 -- packages/chat/src/
29+
git diff chat@4.25.0..chat@4.26.0 -- packages/adapter-slack/src/
30+
# ... repeat for each changed package
31+
32+
# 3. Create a sync branch
33+
cd /tmp/chat-sdk-python
34+
git checkout -b sync/upstream-v4.26.0
35+
36+
# 4. Port each change following the TS → Python Porting Hazards below
37+
38+
# 5. Run full validation
39+
uv run ruff check src/ tests/ scripts/
40+
uv run ruff format --check src/ tests/ scripts/
41+
uv run python scripts/audit_test_quality.py
42+
uv run python scripts/verify_test_fidelity.py
43+
uv run pytest tests/ --tb=short -q
44+
45+
# 6. Update version
46+
# - pyproject.toml: version = "0.26.0"
47+
# - README.md: status line
48+
# - __init__.py: UPSTREAM_PARITY = "4.26.0"
49+
# - CLAUDE.md: version reference
50+
# - CHANGELOG.md: new entry
51+
52+
# 7. PR, merge, publish
53+
gh pr create --title "sync: upstream v4.26.0"
54+
```
55+
56+
### What to check for each upstream commit
57+
58+
- [ ] New types or fields → add to `types.py`
59+
- [ ] New methods on Thread/Channel → add to `thread.py`/`channel.py`
60+
- [ ] New adapter features → update the adapter + tests
61+
- [ ] New TS tests → run fidelity script, port missing tests
62+
- [ ] Changed behavior → verify Python matches with regression tests
63+
- [ ] Review the porting hazards below for each change
64+
565
## How to Diff Upstream Changes
666

767
```bash

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "chat-sdk"
3-
version = "0.0.1a12"
3+
version = "0.25.0"
44
description = "Multi-platform async chat SDK for Python — port of Vercel Chat"
55
readme = "README.md"
66
license = {text = "MIT"}

src/chat_sdk/__init__.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,21 @@
8686
select_option,
8787
text_input,
8888
)
89+
from chat_sdk.plan import (
90+
AddTaskOptions,
91+
CompletePlanOptions,
92+
Plan,
93+
PlanContent,
94+
PlanModel,
95+
PlanModelTask,
96+
PlanTask,
97+
PlanTaskStatus,
98+
PostableObjectContext,
99+
StartPlanOptions,
100+
UpdateTaskInput,
101+
is_postable_object,
102+
post_postable_object,
103+
)
89104
from chat_sdk.shared.base_format_converter import BaseFormatConverter
90105
from chat_sdk.shared.errors import (
91106
AdapterError,
@@ -165,11 +180,29 @@
165180
WellKnownEmoji,
166181
)
167182

183+
# The upstream Vercel Chat version this release is synced to.
184+
UPSTREAM_PARITY = "4.25.0"
185+
168186
__all__ = [
187+
"UPSTREAM_PARITY",
169188
# Core classes
170189
"Chat",
171190
"ThreadImpl",
172191
"ChannelImpl",
192+
# Plan / PostableObject
193+
"Plan",
194+
"PlanTask",
195+
"PlanTaskStatus",
196+
"PlanModel",
197+
"PlanModelTask",
198+
"PlanContent",
199+
"StartPlanOptions",
200+
"AddTaskOptions",
201+
"UpdateTaskInput",
202+
"CompletePlanOptions",
203+
"PostableObjectContext",
204+
"is_postable_object",
205+
"post_postable_object",
173206
# AI
174207
"to_ai_messages",
175208
# Card builders (PascalCase primary — matches source TS SDK)

0 commit comments

Comments
 (0)