Skip to content

improvement(copilot): trim copilot_chats reads to lean projections#4629

Merged
waleedlatif1 merged 2 commits into
stagingfrom
waleedlatif1/copilot-chat-query
May 16, 2026
Merged

improvement(copilot): trim copilot_chats reads to lean projections#4629
waleedlatif1 merged 2 commits into
stagingfrom
waleedlatif1/copilot-chat-query

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Split getAccessibleCopilotChat into a lean getAccessibleCopilotChatAuth (auth-only projection) and the existing full-row helper; identical authorization logic shared via a generic
  • Migrate rename/delete/update-messages/checkpoints/checkpoints-revert/mothership-delete to the lean helper — no more TOAST detoast of messages/planArtifact/config/resources on the hot auth path
  • Trim list-mode SELECT in /api/copilot/chat (and matching contract copilotChatGetListItemSchema) to drop messages/planArtifact/config; verified zero client consumers of those fields
  • Derive CopilotChatAuthRow / CopilotChatListRow from $inferSelect so types stay in sync with the schema

Type of Change

  • Improvement

Testing

Tested manually. bun run type-check, bun run check:api-validation:strict, and 179/179 tests across copilot + mothership suites all green.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel Bot commented May 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 16, 2026 1:49am

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 16, 2026

PR Summary

Medium Risk
Moderate risk because it changes shared authorization helpers and trims fields returned by the copilot chat list API/contract, which could break any undiscovered consumers despite being a performance-focused refactor.

Overview
Reduces database load on common copilot chat paths by splitting chat access into getAccessibleCopilotChatAuth (lean, auth-only projection) vs getAccessibleCopilotChat (full row), with shared authorization logic.

Updates multiple mutation/authorization routes (chat delete, rename, update-messages, checkpoints create/list/revert, and mothership chat DELETE) to use the new lean helper so they no longer read heavy TOAST columns just to verify access.

Slims the /api/copilot/chat list response to only return chat metadata (drops messages/planArtifact/config) and updates the corresponding Zod contract schema and server-side list transformation accordingly.

Reviewed by Cursor Bugbot for commit 59d25fe. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 16, 2026

Greptile Summary

This PR splits getAccessibleCopilotChat into a lean getAccessibleCopilotChatAuth (selecting only id, userId, workflowId, workspaceId, type) and preserves the full-select variant for paths that actually consume heavy TOAST columns. Authorization logic is deduplicated into a shared authorizeCopilotChatRow<T> generic.

  • lifecycle.ts: New getAccessibleCopilotChatAuth + shared authorizeCopilotChatRow<T extends CopilotChatAuthRow> generic; type is included in the auth projection so chat.type !== 'mothership' guards remain valid.
  • queries.ts + copilot.ts: List SELECT drops messages, planArtifact, and config; copilotChatGetListItemSchema updated to match; single-chat GET path is untouched and continues to use the full row.
  • Route migrations: rename, delete, update-messages, checkpoints, checkpoints-revert, and mothership-delete all migrated to the lean helper; tests updated with correct per-mock aliases.

Confidence Score: 5/5

Safe to merge — auth logic is shared through a well-typed generic, all migrated routes only needed ownership verification, and the full-select path is preserved for callers that consume message content.

The refactoring is narrow and mechanical: the authorization logic is unchanged, the type column is retained in the lean projection so chat.type guards remain valid, and the previously-flagged test gap in the idempotent-delete path was correctly fixed in this PR.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/lib/copilot/chat/lifecycle.ts Refactors shared auth logic into a generic authorizeCopilotChatRow<T>, adds lean getAccessibleCopilotChatAuth selecting only 5 columns, preserves full-select getAccessibleCopilotChat — logic is correct and types are inferred from the schema.
apps/sim/app/api/copilot/chat/queries.ts Adds CopilotChatListRow type and transformChatListItem for the list path; the list SELECT now omits messages, planArtifact, and config; single-chat GET continues to use the full transformChat — consistent with the slimmed contract.
apps/sim/lib/api/contracts/copilot.ts Removes messages, messageCount, planArtifact, and config from copilotChatGetListItemSchema to match the trimmed list response; .passthrough() ensures forward compatibility.
apps/sim/app/api/copilot/chat/delete/route.test.ts Adds mockGetAccessibleCopilotChatAuth mock; the previously-flagged idempotent-delete test gap is now correctly addressed with mockGetAccessibleCopilotChatAuth.mockResolvedValueOnce(null).
apps/sim/app/api/mothership/chats/[chatId]/route.ts DELETE handler migrated to getAccessibleCopilotChatAuth; chat.type !== 'mothership' check is safe because type is in copilotChatAuthColumns. GET handler correctly retains getAccessibleCopilotChat for full-row access.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Mutation Route
rename / delete / update-messages
checkpoints / mothership-delete] -->|chatId, userId| B[getAccessibleCopilotChatAuth]
    C[Read Route
chat GET by chatId
resolveOrCreateChat] -->|chatId, userId| D[getAccessibleCopilotChat]
    B --> E[db.select id, userId,
workflowId, workspaceId, type]
    D --> F[db.select *]
    E --> G[authorizeCopilotChatRow T]
    F --> G
    G --> H{chat exists?}
    H -- No --> I[return null]
    H -- Yes --> J{workflowId?}
    J -- Yes --> K[authorizeWorkflowByWorkspacePermission]
    J -- No --> L{workspaceId?}
    L -- Yes --> M[checkWorkspaceAccess]
    L -- No --> N[return chat]
    K --> O{allowed?}
    O -- No --> I
    O -- Yes --> N
    M --> P{hasAccess?}
    P -- No --> I
    P -- Yes --> N
Loading

Reviews (2): Last reviewed commit: "fix(copilot): exercise idempotent-delete..." | Re-trigger Greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

Fixed in 59d25fe — the idempotent-delete test now overrides mockGetAccessibleCopilotChatAuth (matching the route's actual call) so the if (!chat) return { success: true } early-return guard is genuinely exercised. Confirmed the test still passes.

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 59d25fe. Configure here.

@waleedlatif1 waleedlatif1 merged commit f76e8e6 into staging May 16, 2026
14 checks passed
@waleedlatif1 waleedlatif1 deleted the waleedlatif1/copilot-chat-query branch May 16, 2026 01:54
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