Repository navigation
feat(runtime): type Linear agent session events - #180
Conversation
|
CodeAnt AI is reviewing your PR. |
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
Warning Review limit reached
More reviews will be available in 51 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (10)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
| } | ||
|
|
||
| export type WorkforceEvent = WorkforceCronEvent | WorkforceProviderEvent; | ||
| export function unwrapResourceRecord<T = unknown>(payload: unknown): T | unknown { |
There was a problem hiding this comment.
Suggestion: The generic return type is effectively lost because T | unknown always collapses to unknown, so callers never get the typed result they requested from unwrapResourceRecord<T>(...). Change the signature to return T (or T | undefined if needed) so the helper preserves the generic contract. [api mismatch]
Severity Level: Major ⚠️
- ⚠️ Linear handlers lose static typing for unwrapped payloads.
- ⚠️ Agent authors require extra guards or type assertions.Steps of Reproduction ✅
1. In `packages/runtime/src/types.ts:59-62`, `unwrapResourceRecord` is declared as `export
function unwrapResourceRecord<T = unknown>(payload: unknown): T | unknown { … }`.
2. Because `T` is unconstrained, the return type `T | unknown` is equivalent to `unknown`
in TypeScript, so any call like `unwrapResourceRecord<Foo>(...)` is statically typed as
`unknown`, ignoring `Foo`.
3. The helper is re‑exported from `packages/runtime/src/index.ts:8-11` (`export {
unwrapResourceRecord } from './types.js';`), and used in
`packages/runtime/src/define-agent.test.ts:70-38` where it is called as
`unwrapResourceRecord<LinearAgentSessionPayload>(event.payload)` and
`unwrapResourceRecord<{ body?: string; issue_id?: string; issue_identifier?: string }>({
resource: { … }})`.
4. In both usages, the generic argument (`LinearAgentSessionPayload` or the inline object
type) does not affect the inferred return type, which remains `unknown`, forcing callers
to rely on separate type guards or assertions instead of getting the requested generic
shape from `unwrapResourceRecord<T>(...)`.Fix in Cursor | Fix in VSCode Claude
(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** packages/runtime/src/types.ts
**Line:** 59:59
**Comment:**
*Api Mismatch: The generic return type is effectively lost because `T | unknown` always collapses to `unknown`, so callers never get the typed result they requested from `unwrapResourceRecord<T>(...)`. Change the signature to return `T` (or `T | undefined` if needed) so the helper preserves the generic contract.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| payload: LinearAppUserNotificationEventPayload; | ||
| }); | ||
|
|
||
| export type WorkforceEvent = WorkforceCronEvent | LinearAgentSessionEvent | WorkforceProviderEvent; |
There was a problem hiding this comment.
Suggestion: This union includes both a specialized Linear event type and the broad WorkforceProviderEvent that still allows source: 'linear', so the broad member swallows the specialized one during narrowing and payload falls back to unknown in common event.source/event.type checks. Exclude Linear from the generic provider branch (or split provider variants by source) so Linear payload typing is actually preserved. [api mismatch]
Severity Level: Major ⚠️
- ⚠️ Linear events via handler() keep payload as unknown.
- ⚠️ Event narrowing by source and type loses specificity.
- ⚠️ Encourages unsafe `any` casts in Linear handlers.Steps of Reproduction ✅
1. In `packages/runtime/src/types.ts:44-49`, `WorkforceProviderEvent` is defined with
`source: Exclude<WorkforceEventSource, 'cron'>;`, which includes `'linear'`, and `payload:
unknown`.
2. In `packages/runtime/src/types.ts:148-158`, `LinearAgentSessionEvent` is defined as a
union of two specialized Linear variants with `source: 'linear'`, specific `type` literals
(`'AgentSessionEvent.created' | 'AgentSessionEvent.prompted' |
'AppUserNotification.issueCommentMention'`), and strongly typed `payload` fields
(`LinearAgentSessionEventPayload` / `LinearAppUserNotificationEventPayload`).
3. In `packages/runtime/src/types.ts:160`, `WorkforceEvent` is declared as
`WorkforceCronEvent | LinearAgentSessionEvent | WorkforceProviderEvent`, so a Linear event
with `source: 'linear'` and `type: 'AgentSessionEvent.created'` satisfies both
`LinearAgentSessionEvent` and the generic `WorkforceProviderEvent` branch.
4. The public handler signature in `packages/runtime/src/types.ts:370` and
`packages/runtime/src/handler.ts:27` uses `event: WorkforceEvent`, so in a typical handler
following the documented pattern in `handler.ts:14-24` but checking `event.source ===
'linear'` and `event.type === 'AgentSessionEvent.created'`, TypeScript narrows `event` to
`LinearAgentSessionEvent | (WorkforceProviderEvent & { source: 'linear'; type:
'AgentSessionEvent.created' })`, making `event.payload` effectively
`LinearAgentSessionEventPayload | unknown` which collapses to `unknown` and prevents the
Linear specialization from surfacing under normal `source`/`type` narrowing.Fix in Cursor | Fix in VSCode Claude
(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** packages/runtime/src/types.ts
**Line:** 160:160
**Comment:**
*Api Mismatch: This union includes both a specialized Linear event type and the broad `WorkforceProviderEvent` that still allows `source: 'linear'`, so the broad member swallows the specialized one during narrowing and `payload` falls back to `unknown` in common `event.source/event.type` checks. Exclude Linear from the generic provider branch (or split provider variants by source) so Linear payload typing is actually preserved.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix|
CodeAnt AI finished reviewing your PR. |
1f49e7f to
54ff48d
Compare
|
Reviewed PR #180 and fixed the runtime payload typing issue I found. Changed:
Verification:
|
|
Reviewed PR #180 against the provided diff and traced the Linear trigger/runtime type changes through No source fixes were needed. I ran:
The workspace check completed successfully after the required build step that the workflow also runs before lint/typecheck/test. |
|
Reviewed PR #180 against the provided diff and traced the Linear trigger/type changes through persona-kit, runtime exports, narrowing, shim behavior, and tests. I did not find breakage requiring code edits. Local verification passed:
|
|
Reviewed PR #180 and fixed one runtime typing issue: Local verification completed:
|
|
Reviewed PR #180 and made one fix. Changed packages/runtime/src/types.ts: Updated packages/runtime/src/define-agent.test.ts so the test exercises the typed return directly. Validation run locally:
|
|
Reviewed PR #180 and fixed type issues in the Linear runtime surface. Key fixes:
Verification run:
|
Summary
@relayfile/adapter-linearsoTriggerNameFor<'linear'>acceptsAgentSessionEvent.created,AgentSessionEvent.prompted, andAppUserNotification.issueCommentMention.payloadcontainerunwrapResourceRecord(payload)from@agentworkforce/runtimepublic entry so agents do not hand-copy theresource -> payloadunwrap{ resource: { payload: { body, issue_id, issue_identifier }}}container@agentworkforce/persona-kitand@agentworkforce/runtimeto3.0.41for publish after mergeVerification
corepack pnpm --filter @agentworkforce/persona-kit test(246/246)corepack pnpm --filter @agentworkforce/runtime test(59/59)Notes
The AgentSessionEvent leg is intentionally defensive because no live AgentSessionEvent record exists yet. The fallback issue-comment container is covered by the AR-70-style fixture. The workforce union narrows via
unwrapResourceRecord(event.payload)output, not raw idealized payload fields;unwrapResourceRecordis exported from@agentworkforce/runtime.Blocker
blocked-pending-npm-publish: @agentworkforce/persona-kit@3.0.41, @agentworkforce/runtime@3.0.41blocked-pending-npm-publish: @relayfile/adapter-core@0.3.31, @relayfile/adapter-linear@0.3.10, @relayfile/relay-helpers@0.3.31Runtime tests are green with the current installed adapter-linear for event names. This marker tracks the cross-repo Lane A package publish dependency before cloud can consume the new Linear agent activity writeback route.