Skip to content

feat(linear): agent-session types + kind discriminator (chat@4.31/#151 — L1/5)#168

Merged
patrick-chinchill merged 1 commit into
mainfrom
feat/4.31-linear-agent-sessions-l1-types
Jun 20, 2026
Merged

feat(linear): agent-session types + kind discriminator (chat@4.31/#151 — L1/5)#168
patrick-chinchill merged 1 commit into
mainfrom
feat/4.31-linear-agent-sessions-l1-types

Conversation

@patrick-chinchill

Copy link
Copy Markdown
Collaborator

First of the 5-PR Wave D (issue #151): the foundational TYPES layer for Linear agent sessions. Faithful port of the agent-session type surface from upstream packages/adapter-linear/src/types.ts (vercel/chat, adapter-linear 4.27.0 / chat@4.31.0).

Scope (STRICT): TYPES + the kind discriminator plumbing only. No agent-session webhook routing / emit / fetch logic — those land in L3/L4/L5. CHANGELOG untouched.

Types added (vs upstream types.ts)

  • LinearAdapterMode = Literal["agent-sessions", "comments"] (LinearAdapterMode, types.ts:44).
  • LinearAdapterBaseConfig.mode field; default resolved to "comments" in LinearAdapter.__init__ (config.mode ?? "comments", index.ts:236), exposed via a new LinearAdapter.mode property (mirrors protected readonly mode, index.ts:201).
  • LinearThreadId.agent_session_id: str | None = None (optional; LinearThreadId.agentSessionId, types.ts:189).
  • LinearAgentSessionThreadId — subclass narrowing agent_session_id to required str (LinearThreadId & { agentSessionId: string }, types.ts:203).
  • LinearRawMessage is now a discriminated union on kind: LinearCommentRawMessage (kind="comment") + LinearAgentSessionCommentRawMessage (kind="agent_session_comment", agentSessionId, optional agentSessionPromptContext). Faithful to types.ts:258–281.
  • AgentSessionEventWebhookPayload (+ nested SDK-mirror TypedDicts: AgentSessionWebhookPayload, AgentActivityWebhookPayload, child comment/issue/user payloads, guidance). Hand-authored to match the @linear/sdk/webhooks shape that upstream index.ts consumes; raw Linear camelCase wire keys kept verbatim (external JSON). Added to the LinearWebhookPayload union.
  • New public types re-exported from the linear package __init__ for L2–L5.

kind-discriminator audit (every producer set)

All four LinearRawMessage construction sites in adapter.py are comment-based and now set kind="comment" via LinearCommentRawMessage:

  1. _webhook_comment_to_message (was line 647)
  2. post_message (was 705)
  3. edit_message (was 758)
  4. _comment_node_to_message (was 965)

A test exercises each producer path and asserts raw["kind"] == "comment", so a future producer that forgets the discriminator regresses.

Config mode default

"comments" (faithful to upstream; there is no env var for mode upstream — only config.mode ?? "comments").

Gauntlet

  • ruff check: pass; ruff format --check: pass
  • audit_test_quality.py: 0 hard failures (no warnings reference the new file)
  • pyrefly: src 0 errors; new test file 0 errors (1 justified # type: ignore[misc] on the frozen-mutation test)
  • pytest: full suite 5107 passed, 4 skipped; Linear subset 194 passed (incl. 22 new)

What L2–L5 consume from these types

  • L2/L3 (webhook routing): AgentSessionEventWebhookPayload, the LinearWebhookPayload union, and LinearAdapter.mode to gate AgentSessionEvent handling.
  • L3 (parse): LinearAgentSessionCommentRawMessage (kind="agent_session_comment", agentSessionId, agentSessionPromptContext) emitted from the agent-session parse path.
  • L4 (emit/agent-activity + thread IDs): LinearAgentSessionThreadId (required agent_session_id) and LinearThreadId.agent_session_id for encode/decode + agent-activity creation.
  • L5 (fetch): the agent-session raw-message variant for fetched agent-session comments.

🤖 Generated with Claude Code

…— L1/5)

Port the Linear agent-session type surface from upstream
packages/adapter-linear/src/types.ts (vercel/chat, adapter-linear 4.27.0 /
chat@4.31.0). TYPES + kind-discriminator plumbing only; agent-session
webhook routing / emit / fetch logic lands in L3/L4/L5.

- LinearThreadId gains optional agent_session_id; add
  LinearAgentSessionThreadId (required agent_session_id).
- LinearAdapterConfig gains mode: Literal["agent-sessions", "comments"],
  default "comments" (config.mode ?? "comments", index.ts:236); exposed via
  the LinearAdapter.mode property.
- LinearRawMessage becomes a discriminated union on kind: the existing
  comment variant (LinearCommentRawMessage, kind="comment") plus the new
  LinearAgentSessionCommentRawMessage (kind="agent_session_comment",
  agentSessionId, optional agentSessionPromptContext). All four existing
  comment producers in adapter.py now set kind="comment" (emit/parse
  symmetry — a raw message without kind would break the union).
- Hand-author AgentSessionEventWebhookPayload (+ nested SDK-mirror
  TypedDicts) to match the @linear/sdk/webhooks shape upstream index.ts
  consumes; raw Linear camelCase wire keys kept verbatim. Extend the
  LinearWebhookPayload union to include it.

Re-export the new public types from the linear package __init__ for L2–L5.

Tests: structural/typing coverage (mode default, thread-id fields, kind
discriminator on every existing producer, agent-session variant + webhook
payload shape). pyrefly-clean (src 0, test file 0 / 1 justified ignore).
@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@patrick-chinchill, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 40 minutes and 29 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 04fa0403-2acd-4e25-99ce-4aa50edc1d22

📥 Commits

Reviewing files that changed from the base of the PR and between bf2963a and c0b7cf1.

📒 Files selected for processing (4)
  • src/chat_sdk/adapters/linear/__init__.py
  • src/chat_sdk/adapters/linear/adapter.py
  • src/chat_sdk/adapters/linear/types.py
  • tests/test_linear_agent_session_types.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for Linear agent-session types and configuration modes ('comments' or 'agent-sessions') in the Linear adapter. It adds new type definitions, updates the adapter configuration to support the mode parameter, refactors the raw message types into a discriminated union, and includes comprehensive unit tests to verify the structural correctness of these new types. I have no feedback to provide as there are no review comments.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@patrick-chinchill patrick-chinchill marked this pull request as ready for review June 20, 2026 05:57
@patrick-chinchill patrick-chinchill merged commit 8185f57 into main Jun 20, 2026
9 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c0b7cf1bcb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

# handling. Defaults to "comments". Use "agent-sessions" for app-actor
# installs. Faithful port of upstream ``config.mode ?? "comments"``
# (types.ts:67, index.ts:236).
mode: LinearAdapterMode | None = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve existing config positional arguments

Adding mode here changes the generated positional __init__ for all LinearAdapter*Config dataclasses. Existing callers that pass positional args after logger now have their user_name bound to mode, their webhook_secret bound to user_name, and so on, which can make LinearAdapter fail authentication/webhook-secret setup or silently use the wrong bot name. Make this new option keyword-only (or otherwise avoid shifting the public positional signature).

Useful? React with 👍 / 👎.

"""

# Required for agent-session threads (narrows the optional base field).
agent_session_id: str = ""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require the agent session id

This subclass is documented and exported as the required-session form, but the default allows LinearAgentSessionThreadId(issue_id="...") to construct a value with agent_session_id == "". Code that accepts this type can therefore proceed with an empty Linear agent-session id instead of failing at the call site, so please validate it (or make the field truly required/keyword-only required).

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant