Skip to content

Releases: Chinchill-AI/chat-sdk-python

v0.4.26.3 — Slack render_postable AST fix

07 May 04:27
Immutable release. Only release title and notes can be modified.
04c0658

Choose a tag to compare

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

24 Apr 20:05
Immutable release. Only release title and notes can be modified.
c36c8aa

Choose a tag to compare

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

23 Apr 23:03
Immutable release. Only release title and notes can be modified.
d23b6d9

Choose a tag to compare

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

11 Apr 05:24
Immutable release. Only release title and notes can be modified.
68520d6

Choose a tag to compare

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

v0.0.1a12

10 Apr 23:39
Immutable release. Only release title and notes can be modified.
bf1d78b

Choose a tag to compare

v0.0.1a12 Pre-release
Pre-release

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

Upgrading

Python 3.10 is now supported. CI tests 3.10 through 3.13.

Breaking changes (all alpha — no stable API guarantees yet):

  • Serialization keys are now camelCase (threadId, channelId, adapterName) to match the TS SDK. from_json() accepts both camelCase and snake_case, so existing stored data still loads.
  • PermissionErrorAdapterPermissionError: the old name shadowed Python's builtin.
  • StateNotConnectedError replaces bare RuntimeError when calling state methods before connect().
  • OnLockConflict callbacks should return "force" or "drop" (strings). Returning True still works but is deprecated.
  • reviver() no longer registers a global singleton. Each reviver is bound to the Chat that created it.

New: async-safe Chat resolver

Thread and Channel deserialization now supports three resolution levels:

# 1. Explicit (best for library code, multi-tenant)
thread = ThreadImpl.from_json(data, chat=my_chat)

# 2. Context-local (best for tests, request scoping)
with chat.activate():
    thread = ThreadImpl.from_json(data)

# 3. Global (existing pattern, unchanged)
chat.register_singleton()

Bug fixes

  • Fixed streaming: intermediate edits now use the markdown renderer, paragraph separators between agent steps, 500ms latency on stream end eliminated
  • Fixed all adapters: token refresh race conditions, HTTP session reuse, limit=0 no longer silently replaced by defaults
  • Fixed serialization: Slack installations interoperate with TS SDK, card fallback text extracted properly, AI SDK field names corrected
  • Fixed Teams: status code comparison, modal dialog buttons, table cell escaping
  • Fixed shutdown: in-flight handler tasks cancelled, fire-and-forget tasks tracked for GC safety
  • 30+ additional production bug fixes (see CHANGELOG)

Internals

  • 3,360 tests, 0 warnings, 0 lint errors, 535/535 TS fidelity
  • Automated test quality gate in CI
  • Porting guide with 15 hazards and merge checklist

v0.0.1a11 — 100% Test Fidelity

08 Apr 01:46
Immutable release. Only release title and notes can be modified.
88a5144

Choose a tag to compare

Pre-release

529/529 TS tests matched (100%). 3,427 tests. verify_test_fidelity.py enforces 1:1 name correspondence going forward.

v0.0.1a8 — Full Test Parity

07 Apr 08:00
Immutable release. Only release title and notes can be modified.
e98d994

Choose a tag to compare

Pre-release

3,106 tests. All components at 94%+ of TypeScript test count. See CHANGELOG.md.

v0.0.1a7 — Coverage & Fixtures

07 Apr 06:56
Immutable release. Only release title and notes can be modified.
7981d3c

Choose a tag to compare

Pre-release

82% coverage (up from 79%). 2,767 tests. All 46 fixture replay tests pass. Postgres atomic lock. Core SDK test gaps documented.

v0.0.1a6 — Systematic Port Fidelity

07 Apr 03:23
Immutable release. Only release title and notes can be modified.
2d655bb

Choose a tag to compare

Pre-release

10 more port bugs fixed from systematic TS comparison. See CHANGELOG.md.

v0.0.1a5 — Port Fidelity Release

07 Apr 02:58
Immutable release. Only release title and notes can be modified.
c393499

Choose a tag to compare

Pre-release

10 critical/high port bugs fixed from systematic comparison against TS originals. See CHANGELOG.md for details.