feat(composio): add Linear as a native memory provider#2452
Conversation
Adds LinearProvider under src/openhuman/composio/providers/linear/, joining gmail/notion/slack/clickup as the fifth toolkit with periodic Memory Tree ingest. Syncs issues assigned to the connected user via LINEAR_LIST_LINEAR_ISSUES, with cursor-based incremental updates, daily budget enforcement, and per-item dedup. Migrates LINEAR_CURATED catalog from catalogs_productivity.rs into the provider module (consistent with gmail/notion/clickup), adds LINEAR_LIST_LINEAR_USERS to the curated surface for viewer-id resolution, and registers the provider in init_default_providers. Closes tinyhumansai#2400
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds Linear as a native memory-ingest provider. LinearProvider incrementally syncs issues assigned to the authenticated user via cursored pagination and persists each issue into Memory Tree. Adds JSON extraction helpers, curated tools catalog, module wiring, registry registration, and capability-matrix integration. ChangesLinear memory provider feature
Sequence Diagram (high-level sync flow)sequenceDiagram
participant Client as ProviderContext
participant Provider as LinearProvider::sync
participant State as SyncState
participant LinearAPI as LINEAR_LIST_LINEAR_USERS / LINEAR_LIST_LINEAR_ISSUES
participant Persister as persist_single_item
Client->>Provider: sync(ctx, reason)
Provider->>State: load & check daily budget
Provider->>LinearAPI: LINEAR_LIST_LINEAR_USERS(isMe:true) -> viewer id
Provider->>State: re-check budget
Provider->>LinearAPI: LINEAR_LIST_LINEAR_ISSUES(assignee=viewer, cursor)
loop per page
LinearAPI->>Provider: issues + pageInfo
Provider->>Provider: dedupe by issue_id@updatedAt
Provider->>Persister: persist_single_item(issue)
end
Provider->>State: save cursor & usage
Provider->>Client: SyncOutcome
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/openhuman/composio/providers/linear/provider.rs`:
- Around line 313-319: The cursor is being advanced even when
persist_single_item fails, which can permanently skip items; modify the logic
around persist_single_item so that the cursor update/advance only occurs on
success (i.e., after persist_single_item returns Ok), and do not advance when it
returns Err (log and continue without moving the cursor). Update both
occurrences referenced near the persist_single_item call (the warning block
around tracing::warn! at the first occurrence and the similar block at lines
~346-348) so cursor advancement is gated on successful persistence.
- Around line 209-213: The loop is moving the String viewer_id into the json!
macro (in the args initialization) on the first iteration, causing subsequent
iterations to fail; fix it by passing a non-consuming reference or clone (e.g.,
use &viewer_id or viewer_id.clone()) when building args so viewer_id is not
moved; update the args construction where json!({ "assigneeId": viewer_id,
"first": page_size, "orderBy": "updatedAt" }) to use &viewer_id or
viewer_id.clone() instead.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b0118f1b-7908-4159-ad12-e34f6a1e6ddc
📒 Files selected for processing (10)
src/openhuman/composio/providers/catalogs.rssrc/openhuman/composio/providers/catalogs_productivity.rssrc/openhuman/composio/providers/descriptions.rssrc/openhuman/composio/providers/linear/mod.rssrc/openhuman/composio/providers/linear/provider.rssrc/openhuman/composio/providers/linear/sync.rssrc/openhuman/composio/providers/linear/tests.rssrc/openhuman/composio/providers/linear/tools.rssrc/openhuman/composio/providers/mod.rssrc/openhuman/composio/providers/registry.rs
💤 Files with no reviewable changes (1)
- src/openhuman/composio/providers/catalogs_productivity.rs
- Use &viewer_id in json! macro inside pagination loop to avoid String move on first iteration (CodeRabbit critical, line 213) - Track had_persist_failures and gate cursor advancement on zero failures; emit a warn log when keeping cursor for retry, preventing permanently skipped issues (CodeRabbit major, line 319)
Summary
src/openhuman/composio/providers/linear/— fifth native Composio memory provider joining gmail / notion / slack / clickup.LinearProvidersyncs issues assigned to the connected user viaLINEAR_LIST_LINEAR_ISSUESwith cursor-based incremental updates and per-item dedup (issue_id@updatedAt).LINEAR_LIST_LINEAR_USERS { isMe: true }on each sync pass — validates the OAuth connection is live before paginating.MAX_PAGES_PER_SYNC = 20caps prevent runaway API usage.LINEAR_CURATEDcatalog fromcatalogs_productivity.rsinto the provider module (consistent with gmail / notion / clickup / github pattern). AddsLINEAR_LIST_LINEAR_USERSto the curated surface.capability_matrixtest to assertlinearis a native provider withsync_interval_secs = 30 * 60.Problem
Linear was exposed only via tool-calling (
LINEAR_CURATEDincatalogs_productivity.rs). Connected workspace issues never reached the Memory Tree on the periodic sync path, so the agent had no long-term memory of Linear issues — every conversation started cold.Solution
Mirrors
clickup/as the template (most recent and structurally simplest native provider). Key adaptations for Linear:LINEAR_LIST_LINEAR_ISSUESaccepts a cross-teamassigneeIdfilter directly.updatedAtstring (lexicographically sortable, same as Notion).composio-linear-issue-<issue_uuid>— stable per issue across syncs for upsert semantics.Submission Checklist
sync.rs(18 inline) andtests.rs(18) covering all extraction helpers, provider metadata, and curated catalog surfacecargo testpasses cleancapability_matrix_includes_linear_as_native_memory_providertest added tomod.rsProviderContext::executepathCloses #2400in RelatedImpact
on_connection_createdingests up to 100 assigned issues; subsequent syncs increment from theupdatedAtcursor.Related
src/openhuman/composio/providers/clickup/(PR feat(composio): add ClickUp provider for Memory Tree ingest #2291)AI Authored PR Metadata
Linear Issue
Commit & Branch
Validation Run
pnpm --filter openhuman-app format:check— N/A (Rust-only change)pnpm typecheck— N/A (Rust-only change)cargo test -p openhuman -- composio::providers::linear— 36 tests passcargo fmt --all -- --checkpasses,cargo clippy -p openhumancleanValidation Blocked
command:N/Aerror:N/Aimpact:N/ABehavior Changes
Parity Contract
LINEAR_CURATEDremoved fromcatalogs_productivity.rsand re-pointed incatalog_for_toolkit— tool-calling surface for Linear is identical, just sourced from the provider modulepersist_single_itempath match gmail / clickup patternsDuplicate / Superseded PR Handling
Summary by CodeRabbit