Skip to content

Releases: Chinchill-AI/chat-sdk-python

v0.4.31.1

Choose a tag to compare

@patrick-chinchill patrick-chinchill released this 21 Jun 20:03
Immutable release. Only release title and notes can be modified.
68a77dc

Python-only fixes on top of 4.31.0 (UPSTREAM_PARITY unchanged at 4.31.0). Two Slack adapter bug fixes, both divergences ahead of upstream, documented in docs/UPSTREAM_SYNC.md.

  • Slack #138 — empty-DM thread_ts fetch now routes to conversations.history instead of conversations.replies(ts='') (in fetch_messages/fetch_message), so DM-root context isn't lost. Non-empty (real thread) path is byte-identical.
  • Slack #95chat.startStream threads a workspace team_id (= the plumbed recipient_team_id) for Enterprise Grid orgs, where the per-workspace token alone returns team_not_found. Verified end-to-end against slack_sdk that the value reaches the API call.
  • Docs — Linear "agent-sessions" mode marked experimental (schema-hardened but unverified vs a live tenant, #151).

See CHANGELOG.md.

v0.4.31

Choose a tag to compare

@patrick-chinchill patrick-chinchill released this 20 Jun 10:17
Immutable release. Only release title and notes can be modified.
3d753c0

Synced to upstream vercel/chat@4.31.0 (UPSTREAM_PARITY = "4.31.0").

Highlights:

  • Linear agent-sessions mode (#151, L1–L5): raw-GraphQL, schema-hardened against Linear's published schema (webhook parse/routing, agent-activity emit, fetch, append-only guards)
  • Teams SDK-free primitive subpaths: teams/api, graph, format, webhook, cards/cards_input, modals (each with SSRF/token-leak host gates)
  • Slack 4.31 (#155): @mention-inside-URL fix, web_client_options, stable link-button action_id
  • Telegram rich messages + slash-command router
  • LinkButton(id=…) stable id, and an opt-in Python-only ThinkingChunk stream-input type (default-off; StreamChunk unchanged)

The mapped-core test files are byte-identical 4.30→4.31, so the fidelity re-pin to chat@4.31.0 is string-only (732/732, 0 missing). See CHANGELOG.md.

v0.4.30 — Teams SDK migration + 4.30.0 parity

Choose a tag to compare

@patrick-chinchill patrick-chinchill released this 19 Jun 05:36
Immutable release. Only release title and notes can be modified.
34314dd

Synced to upstream vercel/chat@4.30.0 (UPSTREAM_PARITY = "4.30.0").

Headline: the Teams adapter is migrated to the official microsoft-teams-apps Python SDK (issue #93 — inbound+auth, outbound, native streaming via the SDK IStreamer, each independently reviewed).

Also in this release:

  • New Twilio adapter (10th platform), Telegram native DM draft streaming, Slack webhook/primitives subpaths, and WhatsApp / Slack / Google Chat fixes.
  • 7 pre-existing parity gaps closed from a pre-ship parity audit (Google Chat cardsV2/Select·RadioSelect, Teams ChoiceSet fan-out + list_threads/post_channel_message + api_url, api_url across Slack/Discord/GitHub/Linear + get_installation_id, core AiMessage re-exports).
  • Documentation accuracy pass correcting earlier phantom-feature / parity-label errors.

CI fidelity re-pinned to chat@4.30.0 (732/732 mapped-core tests). Matches chat@4.30.0 with documented exceptions (Linear agent sessions deferred to 4.31, tracked in #152). See CHANGELOG.md for the full entry.

v0.4.29

Choose a tag to compare

@patrick-chinchill patrick-chinchill released this 18 Jun 18:44
Immutable release. Only release title and notes can be modified.
209601d

Synced to upstream Vercel Chat v4.29.0 (release commit 6581d31; UPSTREAM_PARITY = "4.29.0"). Upstream never tagged chat@4.27.0/chat@4.28.0.

Highlights

  • Meta Messenger adapter — the 9th platform
  • chat/ai tool factories (create_chat_tools)
  • callback_url on buttons and modals (vercel/chat#454)
  • Transcripts API + per-thread cache rename message_historythread_history (vercel/chat#448), with back-compat shims at the old import path and config names
  • message.subject + fetch_subject adapter hook (#131)
  • Slack feature wave — verifier precedence flip, external installation providers, native markdown_text, web_client property (#127), and a DM block-action threading fix (#137)
  • Teams outbound files via data-URI activity attachments (#125)
  • Upstream adapter-hardening security pass (SSRF/URL-allowlist, fail-closed verification)
  • burst concurrency strategy

⚠️ Breaking changes

  • Python floor raised to 3.12 (was 3.10) — required for the Teams SDK migration line.
  • Google Chat fail-closed JWT verification at construction (#130, port of upstream 9824d33): GoogleChatAdapter.__init__ now raises ValidationError unless one of google_chat_project_number, pubsub_audience, or disable_signature_verification is set (config or GOOGLE_CHAT_* env). Existing gchat deployments must set one of these.

Deferred to 0.4.29.1

  • Google Chat multipart file upload (#112) — pending the /attachments:upload endpoint + media-scope fixes.
  • Teams content.downloadUrl surfacing (#136) — pending a one-line is not None guideline fix.

See CHANGELOG.md for the complete list of ports and Python-only divergences (docs/UPSTREAM_SYNC.md).

v0.4.27.1 — Slack files_upload_v2 confirmation via SentMessage.raw

Choose a tag to compare

@patrick-chinchill patrick-chinchill released this 29 May 18:21
Immutable release. Only release title and notes can be modified.

Python-only patch on the 0.4.27 line. Does not include the 0.4.29 alpha sync work in flight on main (no upstream 4.29 sync, no Python-floor bump, no auth-precedence change). Branched off the v0.4.27 tag and cherry-picked.

Cut so chinchill-api can gate UX on actual Slack file-delivery confirmation ahead of the 0.4.29 release.

Fixes

  • Slack surfaces files_upload_v2 confirmation through post(). SlackAdapter._upload_files already computed the list of Slack-confirmed file IDs, but post_message discarded the return and ThreadImpl._create_sent_message hardcoded raw=None, so the confirmation never reached SentMessage.raw. Slack was the only file-capable adapter to drop this (discord/telegram upload inline and expose the platform response naturally). post_message now augments RawMessage.raw with "uploaded_file_ids" on every return path that can carry files (file-only, card, table, text); ThreadImpl._create_sent_message accepts and propagates the adapter's raw into SentMessage.raw. None = no upload occurred; an empty list = Slack confirmed zero attachments. raw is augmented, not replaced, so existing consumers are unaffected. (Backported from #117; upstream convergence tracked in vercel/chat#564.)
  • chat._MessageHistoryCache.append nulls raw before persisting to history — mirror of the existing null-out in message_history.MessageHistoryCache.append. Without it, the platform payload the above fix now populates on SentMessage.raw (Slack team_id/user_id, etc.) would persist on every reply to Redis/Postgres-backed state, inflating storage and PII surface.

Tests

4 added: three in tests/test_slack_api.py (file-only, text+files, text-only-no-augment paths) and one end-to-end in tests/test_thread_faithful.py verifying post() propagates RawMessage.rawSentMessage.raw. Full suite green.

Diff vs v0.4.27: +139/-9 across 7 files — strictly additive over the 0.4.27 release.

v0.4.27

Choose a tag to compare

@patrick-chinchill patrick-chinchill released this 28 May 22:15
Immutable release. Only release title and notes can be modified.
c43ea05

Synced to upstream vercel/chat@4.27.0 (release commit f55378a).

Highlights

Upstream parity ports

  • Chat.get_user(adapter, user_id) across all 8 adapters (#90)
  • Slack Socket Mode transport (#86) — closes #68
  • Slack dynamic bot_token resolver + custom webhook_verifier (#87)
  • Teams native DM streaming via emit (#88)
  • Telegram MarkdownV2 rendering (#89)
  • Discord card-text dedup (#89)
  • Slack streaming team_id fix + Teams DM Graph conversation IDs (#85)
  • ExternalSelect.initial_option + option_groups (#84)

Python-only improvements

  • Markdown parser: GFM task lists, escaped chars, inline math (#101)
  • Streaming markdown: list-marker awareness + table chunk-boundary (#99, issue #69)
  • Slack files_upload_v2 kwarg fix (#103, issue #102)
  • Dict-shaped StreamChunk support in slack/github/gchat (#105)
  • Google Chat card-text markdown rendering (#92)
  • Adapter init logs + registered-adapter list in not-found errors (#104)

Sync-process docs

  • New "Review-Loop Discipline" section in docs/UPSTREAM_SYNC.md
  • docs/SELF_REVIEW.md rewritten with explicit timing + economics

Validation

4,036 tests pass, 3 skipped, 0 failed. ruff/format/audit clean.

Upstream tagging note

Upstream did not publish a chat@4.27.0 tag (only @chat-adapter/shared@4.27.0 got one). The fidelity workflow stays pinned to chat@4.26.0 for this release; will move to a 4.27 SHA pin in the next sync.

See CHANGELOG.md for the full release notes.

v0.4.26.3 — Slack render_postable AST fix

Choose a tag to compare

@patrick-chinchill patrick-chinchill released this 07 May 04:27
Immutable release. Only release title and notes can be modified.
04c0658

Python-only patch on top of vercel/chat@4.26.0. No upstream version change.

Fixes

  • SlackFormatConverter.render_postable now uses the AST path for all markdown inputs (#81). Previously, PostableMarkdown and {"markdown": ...} dict inputs were routed through a private regex helper (_markdown_to_mrkdwn) that truncated URLs containing parentheses and diverged silently from the TS SDK's fromAst(parseMarkdown(text)) behavior. Both branches now call from_markdown, which goes through the AST. str and raw branches are unchanged.

Structural parity

  • Deleted _markdown_to_mrkdwn — a regex-based private method with no call sites after the fix above. The TS SDK has no equivalent; its presence was an undocumented divergence.

Additions

  • render_postable now handles card and object-with-ast inputs — added {"card": ...} dict, {"type": "card", ...} CardElement dict, {"ast": ...} dict, and .card / .ast attribute branches, plus str(message) fallback for unrecognized types. Matches the full union of AdapterPostableMessage variants.

Test quality

19 new tests in tests/test_slack_format.py (47 → 66) covering all render_postable branches, every _node_to_mrkdwn node type (heading, blockquote, thematic break, image with/without alt), the remaining extract_plain_text paths (strikethrough, bare URL, channel mentions), and to_blocks_with_table edge cases (non-dict AST, standalone table, column alignment).

Closes: #81 · PR: #82

v0.4.26.2 — upstream parity catch-up

Choose a tag to compare

@patrick-chinchill patrick-chinchill released this 24 Apr 20:05
Immutable release. Only release title and notes can be modified.
c36c8aa

Parity catch-up release with upstream vercel/chat@4.26.0.

Highlights

  • Thread.get_participants() (#54) — upstream-parity port
  • onOptionsLoad + Slack block_suggestion (#50) — external-select dispatch with 2.5s timeout
  • rehydrateAttachment hook + SSRF guards (#52) — 5-adapter implementations with per-adapter URL allowlists
  • StreamingPlan + StreamingPlanOptions (#56) — adds kind=='stream' branch in Thread.post() (options were previously silently dropped)
  • IoRedisStateAdapter (#71) — cross-runtime Redis interop with TS deployments
  • Teams cert config shape (#58) — parity with upstream's deprecated-throws stub
  • 20 [post with Plan] + 6 [Streaming] test ports (#55, #56) + 3 Plan divergence fixes (UpdateTaskInput.id, error propagation, FIFO edit queue)
  • Strict fidelity CI (#53) — verify_test_fidelity.py wired into lint workflow, fails on any missing test or missing upstream checkout

Fidelity

588/588 matched (mapped core files) against chat@4.26.0. Closed [getParticipants], [thread], [Options Load], [post with Plan], [Streaming], and [concurrency: queue attachment rehydration] gaps.

Test coverage

3640 passed, 2 skipped (up from 3545 in 0.4.26.1).

Python-first divergences (documented in docs/UPSTREAM_SYNC.md)

  • StreamingPlan.is_supported() / get_fallback_text() raise on misroute (upstream silently posts blank)
  • rehydrate_attachment URL allowlists on Slack / Teams / Google Chat (SSRF defense — upstream doesn't validate)
  • Redis token format uses CSPRNG hex (upstream uses Math.random() base36; interop preserved via full-string equality)

Follow-ups tracked

  • #78 — extend fidelity MAPPING to all 17 packages/chat/src/*.test.ts files
  • #79 — pin upstream clone SHA in CI
  • #80 — tighten fuzzy matcher against hyphen-stripped accidental matches

Full changelog: CHANGELOG.md

v0.4.26.1 — Python-only follow-up on 4.26

Choose a tag to compare

@patrick-chinchill patrick-chinchill released this 23 Apr 23:03
Immutable release. Only release title and notes can be modified.
d23b6d9

0.4.26.1 (2026-04-23)

Python-only follow-up on 0.4.26. Still alpha — APIs may change.

Fixes

  • Slack native streaming: SlackAdapter.stream() no longer calls
    AsyncWebClient.chat_stream(...) without await. The unawaited coroutine
    returned a truthy object, and the first streamer.append(...) raised
    AttributeError, breaking native Slack streaming for any consumer using
    the default adapter. Issue #44.
  • Teams divider renders at non-zero height: empty Container with
    separator: True rendered as zero-height in the Teams UI. Dividers
    between siblings now hoist separator: True onto the following element;
    a trailing divider emits a minimal non-empty Container. Issue #45.
  • ConcurrencyConfig.max_concurrent is now enforced: consumers setting
    concurrency=ConcurrencyConfig(strategy="concurrent", max_concurrent=N)
    now actually get an asyncio.Semaphore(N) cap on in-flight handlers.
    Previously the field was accepted and ignored (upstream TS has the same
    gap). None / unset keeps the unbounded default. Issue #51.

Python-specific (divergence from upstream 4.26)

  • Fallback streaming runtime robustness (cluster of fixes): framework-
    agnostic request.text() handling now tolerates sync Flask-style
    requests (was raising TypeError: object is not awaitable). Handlers
    typed Callable[..., Awaitable[None] | None] may return sync (None) —
    the dispatcher now awaits only when inspect.isawaitable() confirms,
    preventing runtime crashes on sync handlers.
  • max_concurrent enforcement (see above) — upstream accepts the
    config field but never enforces it; we do.

New public APIs

  • Chat.thread(thread_id, *, current_message=None): new worker-
    reconstruction factory mirroring TS chat.thread(threadId). Adapter is
    inferred from the thread-ID prefix; state and message history come from
    the Chat instance. current_message is preserved so Slack native
    streaming still works post-reconstruction. Issue #46.
  • SlackAdapter.current_token / current_client: public @property
    accessors for the request-context-bound bot token and a preconfigured
    AsyncWebClient. Replaces underscore access from consumer code making
    direct Slack Web API calls inside a handler (email resolution, user
    profile fetches, etc.). Issue #47.

Internals

  • Pyrefly: 213 → 0 type errors; baseline file removed. CI now enforces
    zero errors. Root causes fixed: 8-adapter lock_scope: LockScope | None
    protocol conformance; _ChatSingleton as Protocol; submodule-aware
    replace-imports-with-any; NoReturn on error re-raisers;
    inspect.isawaitable guards for duck-typed request handling and
    sync-or-async handler dispatch. No Any widening, no new # type: ignore lines beyond 10 at adapter event-construction sites where
    thread=None/channel=None get re-wrapped by Chat before handler
    dispatch (matches upstream TS's Omit<> partial-event pattern).
  • Test count: 3545 passed, 2 skipped.

Known gaps (not fixed in this release)

  • onOptionsLoad handler for dynamic select dropdowns — issue #50
  • Thread.getParticipants() method — issue #54
  • rehydrate_attachment adapter hook for queue/debounce + attachments —
    issue #52
  • 40 upstream tests without Python equivalents (Options Load, Plan variants,
    StreamingPlan options, getParticipants) — issue #53
  • Discord native Gateway WebSocket (HTTP-only today) — issue #57
  • Teams certificate-based mTLS auth — issue #58
  • Google Chat file uploads (TODO upstream too) — issue #59
  • Global handler-dispatch bound across reactions/actions/slash/modals — issue #61

v0.4.25 — Synced to Vercel Chat 4.25.0

Choose a tag to compare

@patrick-chinchill patrick-chinchill released this 11 Apr 05:24
Immutable release. Only release title and notes can be modified.
68520d6

Synced to Vercel Chat 4.25.0. New versioning: 0.{upstream_major}.{upstream_minor} embeds the upstream version directly.

Upgrading

pip install chat-sdk==0.4.25

Version scheme changed from 0.0.1aX to 0.{upstream_major}.{upstream_minor}[.patch]. Check chat_sdk.UPSTREAM_PARITY programmatically.

New features (from upstream 4.25.0)

  • Plan blocks: Post structured task lists with live updates.
    plan = Plan(title="Deploy steps")
    posted = await thread.post(plan)
    await plan.add_task("Build image")
    await plan.update_task(0, status="completed")
    await plan.complete()
  • Streaming table option: StreamingMarkdownRenderer(wrap_tables_for_append=False) for platforms with native table support. Slack uses this by default.
  • Teams Select/RadioSelect: Card elements render as Adaptive Card Input.ChoiceSet with auto-submit.
  • GitHub issue threads: issue_comment webhooks on plain issues create threads with github:owner/repo:issue:42.
  • Slack OAuth redirect fix: handle_oauth_callback correctly forwards redirect_uri.

Python-only improvements (not in upstream)

  • PostableObjects cached in message history with real message ID (upstream skips this)
  • Teams msteams transport key stripped from action values (upstream leaks it)
  • End-to-end integration tests for Teams card inputs
  • GitHub fetch_thread round-trip test with channel APIs

Internals

  • 3,421 tests, 0 warnings, 0 lint errors
  • 535/535 TS fidelity (100%)
  • Version mapping and sync procedure in UPSTREAM_SYNC.md