Skip to content

Commit 3d753c0

Browse files
chore(release): cut 0.4.31 — sync to chat@4.31.0 (#174)
* chore(release): cut 0.4.31 — sync to chat@4.31.0 Bumps version 0.4.30 → 0.4.31 and UPSTREAM_PARITY → 4.31.0; re-pins the fidelity check + CI clone to chat@4.31.0 (string-only — the mapped-core test files are byte-identical 4.30→4.31, 732/732 still pass). Wave content (already merged): Linear agent-sessions L1–L5 (#151), Teams SDK-free primitive subpaths, Slack 4.31 (#155), Telegram rich messages, LinkButton stable id, and the opt-in ThinkingChunk stream type (#169). Documents the new chat/adapters static catalog as an intentional non-port (npm-addressed + vendor adapters not shipped here; no consumer need). * docs(upstream-sync): correct adapters-catalog counts (19 tests, ~25 adapters)
1 parent c2eac43 commit 3d753c0

8 files changed

Lines changed: 51 additions & 10 deletions

File tree

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
- name: Clone upstream vercel/chat at pinned parity tag
6161
id: clone_upstream
6262
run: |
63-
git clone --depth 1 --branch chat@4.30.0 \
63+
git clone --depth 1 --branch chat@4.31.0 \
6464
https://github.com/vercel/chat.git /tmp/vercel-chat
6565
6666
- name: Test fidelity check (strict — zero missing in mapped core files)

CHANGELOG.md

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

3+
## 0.4.31
4+
5+
Synced to upstream `vercel/chat@4.31.0`. The mapped-core **test** files (`packages/chat/src/*.test.ts`) are byte-identical between the `chat@4.30.0` and `chat@4.31.0` tags, so the fidelity re-pin to `chat@4.31.0` is string-only (732/732 mapped-core tests still pass, 0 missing); the core **source** delta is the `LinkButton` stable-id field (below). The headline is the **Linear agent-sessions** mode, plus the **Teams SDK-free primitive subpaths**, the **Slack 4.31** changes, **Telegram rich messages**, and a Python-only opt-in **`ThinkingChunk`** stream type. Sets `UPSTREAM_PARITY = "4.31.0"`.
6+
7+
### Headline: Linear agent-sessions mode (issue #151)
8+
9+
Full port of upstream's Linear agent-sessions interaction model, delivered across five PRs (L1–L5). Because no official Linear Python SDK exists, every `@linear/sdk` call is reproduced as **raw GraphQL** over the existing `_graphql_query` helper and **schema-hardened field-by-field against Linear's published GraphQL schema** (`linear/packages/sdk/src/schema.graphql`).
10+
11+
- **L1 — types** (#168). `LinearAgentSessionThreadId`, the `mode: "agent-sessions" | "comments"` config (default `"comments"`), the `kind`-discriminated raw-message variants (`comment` / `agent_session_comment`), and the `AgentSessionEvent` webhook payload types.
12+
- **L2 — thread-id** (#170). Anchored `linear:{issue}:c:{comment}:s:{session}` / `linear:{issue}:s:{session}` encode/decode with a strict decode order; existing thread-id forms stay byte-identical so cross-SDK state is preserved.
13+
- **L3 — webhook parse + routing** (#171). The `AgentSessionEvent` branch with mutually-exclusive mode gating (agent-session events flow only in `agent-sessions` mode, comment events only in `comments` mode), `_parse_message_from_agent_session_event` (created/prompted actions + null-return/warn paths), app-ownership guard, and `get_user_name_from_profile_url`.
14+
- **L4 — emit** (#172). `post_message` / `start_typing` / `stream` route through raw `agentActivityCreate` / `agentSessionUpdate` mutations (lowercase `AgentActivityType` enum, `content: JSONObject!`, `ephemeral` included only when set); streaming flushes markdown deltas as `response`/`thought` activities and maps `task_update`/`plan_update` chunks to `action`/`error` activities and session-plan updates.
15+
- **L5 — fetch** (#173). `fetch_messages` dispatches agent-session threads to `_fetch_agent_session_messages` (raw `agentSession(id:)` + `comments(filter:{parent})` with forward/backward pagination); `edit_message`/`delete_message` raise append-only errors for session threads.
16+
17+
The schema-hardening caught two live-tenant-breaking selection bugs before they shipped (`AgentActivity` exposes the `agentSession` relation, not a scalar `agentSessionId`; `AgentSession` likewise has no scalar `issueId`). The mutations/queries are confirmed against the published schema but **not yet exercised against a live Linear agent-session tenant** — documented in `docs/UPSTREAM_SYNC.md`.
18+
19+
### Teams: SDK-free primitive subpaths (chat@4.31, commit `8c71411`)
20+
21+
New runtime-free Teams subpaths mirroring upstream's `@chat-adapter/teams/*` exports: `teams/api` (Bot Connector — token grant, post/update/delete message, typing, create conversation), `teams/graph` (Microsoft Graph — channels, messages, pagination), `teams/format` (Teams text/mention/HTML↔Markdown), `teams/webhook` (read/parse, continuation/user/attachment extraction, mention detection), `teams/cards` + `cards_input` (card → Adaptive Card + input parsing), and `teams/modals` (modal → Adaptive Card + dialog-submit parsing). Each network-facing primitive carries an SSRF/token-leak host gate: `call_teams_connector_api` (serviceUrl Bot Framework allowlist) and `call_teams_graph_api` (host pinned to `graph.microsoft.com`, also guarding followed `@odata.nextLink` cursors).
22+
23+
### Slack 4.31 (commit `f801985`, PR #155)
24+
25+
- **`@mention`-inside-URL fix.** Bare `@handle`s inside `http(s)` URLs (paths, query strings, fragments) are no longer rewritten into `<@handle>` mentions (which corrupted the link), via a URL-span exclusion pass.
26+
- **`web_client_options`** config — forwarded to both the default and per-token `slack_sdk` `WebClient`s to tune the underlying HTTP client (timeout, `retry_handlers`, headers), with per-client header isolation. (Maps to slack_sdk kwargs rather than `@slack/web-api`'s axios options — documented divergence.)
27+
- **Stable link-button `action_id`**`LinkButton(id=…)` now flows to the Slack block `action_id` instead of always deriving it from the URL.
28+
29+
### Telegram: rich messages (commit `4662309`)
30+
31+
Character-for-character port of the new `rich.ts` (Telegram rich-message wire types → Markdown + plain text) as `telegram/rich.py`, plus the rich-message/media type family (`TelegramRichText`/`RichBlock`/`RichMessage`, animation/audio/location/video/voice), native `sendRichMessage`/`sendRichMessageDraft` threading through post/edit/stream with a rich→regular fallback, and a `/slash`-command router.
32+
33+
### Core: `LinkButton` stable id + opt-in `ThinkingChunk`
34+
35+
- **`LinkButton(id=…)`** (chat@4.31, commit `171657a`). Optional action identifier for platforms that report link clicks (matches the `Button`/`Select` `id` convention). The JSX-runtime half of the same commit has no Python equivalent (no JSX runtime) and is documented as such.
36+
- **`ThinkingChunk`** (Python-only, opt-in, default-off; supersedes PR #39, landed in #169). A **separate** `ThinkingChunk(type="thinking", content=str)` stream-input type surfaces AI-SDK `reasoning`/`reasoning-delta` parts. **`StreamChunk` is not widened** — it stays byte-identical to upstream's three variants, so consumers referencing it are unaffected; `ThinkingChunk` is accepted only at the stream boundaries via the `StreamInput = str | StreamChunk | ThinkingChunk` alias. Emitted only when a caller opts in (`emit_thinking=True`); the default stream and persisted `Message` are byte-identical to upstream, so cross-SDK state stays compatible. Gives chinchill a first-class path to stream agent thinking to Slack/Teams without intercepting the model stream out-of-band.
37+
38+
### Not ported (documented)
39+
40+
- **`chat/adapters` static catalog** (new `./adapters` subpath). Upstream's SDK-free adapter/env-var metadata registry is addressed by npm package names and includes ~13 vendor-official adapters this SDK doesn't ship, so it isn't meaningfully portable verbatim; a Python-native equivalent would be a new feature with no current consumer need. Documented in `docs/UPSTREAM_SYNC.md`; deferred demand-driven.
41+
342
## 0.4.30
443

544
Synced to upstream `vercel/chat@4.30.0`. The mapped core (`packages/chat/src`) is content-identical between the `chat@4.29.0` and `chat@4.30.0` upstream tags, so this wave is all adapter work: a **new Twilio adapter**, a **Telegram native-streaming** port, a **Slack primitives-subpath** wave, a batch of **WhatsApp / Slack / Google Chat** fixes, and the headline — the **Teams adapter migration to the official `microsoft-teams-apps` SDK** (issue #93, delivered across four PRs). Sets `UPSTREAM_PARITY = "4.30.0"`; CI fidelity re-pinned to `chat@4.30.0` (732/732 mapped-core tests still pass, 0 missing).

CLAUDE.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Claude Code Quick Reference -- chat-sdk-python
22

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

66
## Key Commands
77
```bash
@@ -28,6 +28,7 @@ Our version embeds the upstream Vercel Chat version: `0.{upstream_major}.{upstre
2828
- `0.4.27.1` = Python-only fix on top of `4.27.0`
2929
- `0.4.29` = synced to upstream `4.29.0` (upstream never tagged 4.27/4.28 as `chat@*`)
3030
- `0.4.30` = synced to upstream `4.30.0`
31+
- `0.4.31` = synced to upstream `4.31.0`
3132
- `UPSTREAM_PARITY` constant in `__init__.py` = programmatic access
3233

3334
## Architecture
@@ -110,7 +111,7 @@ will not pass CI.
110111

111112
**Fidelity check** (`scripts/verify_test_fidelity.py`) verifies every TS
112113
`it("...")` in the mapped core files has a matching Python `def test_*()`,
113-
pinned to `chat@4.30.0` (matches `UPSTREAM_PARITY`; upstream never tagged
114+
pinned to `chat@4.31.0` (matches `UPSTREAM_PARITY`; upstream never tagged
114115
`chat@4.27.0`/`chat@4.28.0`). The `MAPPING` dict in that script is the
115116
authoritative scope list — extending it to the remaining unmapped
116117
`packages/chat/src/*.test.ts` files is tracked as issue #78.
@@ -125,7 +126,7 @@ divergence in `docs/UPSTREAM_SYNC.md`.
125126
Before the fidelity check can run locally, clone the pinned upstream
126127
checkout (same command CI uses in `lint.yml`):
127128
```bash
128-
git clone --depth 1 --branch chat@4.30.0 \
129+
git clone --depth 1 --branch chat@4.31.0 \
129130
https://github.com/vercel/chat.git /tmp/vercel-chat
130131
```
131132
Then `TS_ROOT=/tmp/vercel-chat uv run python scripts/verify_test_fidelity.py --strict`.

README.md

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

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

10-
> **Status: 0.4.30 — synced to [Vercel Chat 4.30.0](https://github.com/vercel/chat)** (`UPSTREAM_PARITY = "4.30.0"`). See [CHANGELOG.md](CHANGELOG.md).
10+
> **Status: 0.4.31 — synced to [Vercel Chat 4.31.0](https://github.com/vercel/chat)** (`UPSTREAM_PARITY = "4.31.0"`). See [CHANGELOG.md](CHANGELOG.md).
1111
1212
## Why chat-sdk?
1313

0 commit comments

Comments
 (0)