Skip to content

feat: add AI agent backend - #2947

Open
MohamedBassem wants to merge 1 commit into
karakeep-app:mainfrom
MohamedBassem:feat/ai-chat-backend
Open

feat: add AI agent backend#2947
MohamedBassem wants to merge 1 commit into
karakeep-app:mainfrom
MohamedBassem:feat/ai-chat-backend

Conversation

@MohamedBassem

Copy link
Copy Markdown
Collaborator

No description provided.

@greptile-apps

greptile-apps Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a new AI chat backend. The main changes are:

  • New authenticated chat router and stream endpoint.
  • Chat session and message persistence helpers.
  • Agent model setup and replay conversion.
  • AI tools for bookmarks, lists, tags, and highlights.
  • Event logging and package/build configuration for the AI runtime.

Confidence Score: 4/5

The AI tool mutation paths need ownership fixes before merging.

  • Model-supplied tag IDs can reach a merge path that lacks confirmed ownership checks.
  • Shared-list bookmark removal can mutate list membership without checking bookmark ownership.
  • The rest of the chat router and persistence flow is mostly contained behind authenticated procedures.

packages/trpc/routers/chat/tools.ts

Security Review

The new AI tool surface includes destructive operations. The tag merge and shared-list removal paths need ownership checks before model-supplied IDs can safely reach those mutations.

Important Files Changed

Filename Overview
packages/trpc/routers/chat/tools.ts Adds the AI tool catalog, including destructive bookmark/list/tag/highlight actions and cache invalidation updates.
packages/trpc/routers/chat/stream.ts Adds chat streaming, agent event handling, assistant/tool message persistence, usage logging, and abort cleanup.
packages/trpc/routers/chat.ts Adds the authenticated chat router with list, create, history, clear, clearAll, and message procedures.
packages/trpc/models/chat.repo.ts Adds Drizzle helpers for chat sessions and chat messages.
packages/trpc/routers/chat/messages.ts Adds conversions between stored rows, public messages, and agent messages.
packages/trpc/routers/chat/model.ts Adds chat model construction, API key selection, and usage aggregation.
packages/trpc/routers/chat/contracts.ts Adds public chat schemas, stream event types, metadata validation, and cache invalidation handles.
packages/trpc/routers/chat/asyncQueue.ts Adds a small async iterable queue for bridging agent events into the stream.
packages/trpc/routers/_app.ts Mounts the new chat router under the app router.
apps/web/next.config.mjs Externalizes the new AI packages for the Next.js server build.
packages/trpc/package.json Adds runtime dependencies for the AI agent packages and TypeBox.
packages/shared-server/src/eventLogTypes.ts Adds event log fields for chat messages and chat tool calls.
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
packages/trpc/routers/chat/tools.ts:1024
**Tag Merge Lacks Ownership**

When the agent calls `merge-tags`, model-supplied `intoTagId` and `fromTagIds` are forwarded directly to `tagsApi.merge`. The inspected merge procedure does not enforce ownership for the target or source tags, so a prompt containing another user's tag ID can merge and delete that tag through this new tool path.

### Issue 2 of 3
packages/trpc/routers/chat/tools.ts:664
**List Removal Skips Bookmark Ownership**

When an editor on a shared list asks the agent to remove a bookmark, this tool forwards the model-supplied `bookmarkId` to `listsApi.removeFromList`. The inspected list removal path checks list edit rights but not bookmark ownership, so the agent can remove another user's bookmark from a shared list if that ID is supplied.

### Issue 3 of 3
packages/trpc/routers/chat/tools.ts:180
**Malformed Cursor Aborts Tool**

The `nextCursor` value is generated or replayed by the model, but invalid JSON or a cursor with the wrong shape is parsed with uncaught `JSON.parse`/Zod errors. A hallucinated or stale cursor makes the tool execution fail instead of returning a recoverable invalid-cursor result to the chat turn.

Reviews (1): Last reviewed commit: "feat: add AI chat backend" | Re-trigger Greptile

}),
},
{ additionalProperties: false },
),

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.

P1 security Tag Merge Lacks Ownership

When the agent calls merge-tags, model-supplied intoTagId and fromTagIds are forwarded directly to tagsApi.merge. The inspected merge procedure does not enforce ownership for the target or source tags, so a prompt containing another user's tag ID can merge and delete that tag through this new tool path.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/trpc/routers/chat/tools.ts
Line: 1024

Comment:
**Tag Merge Lacks Ownership**

When the agent calls `merge-tags`, model-supplied `intoTagId` and `fromTagIds` are forwarded directly to `tagsApi.merge`. The inspected merge procedure does not enforce ownership for the target or source tags, so a prompt containing another user's tag ID can merge and delete that tag through this new tool path.

How can I resolve this? If you propose a fix, please make it concise.

},
{ additionalProperties: false },
),
async execute(_toolCallId, params) {

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.

P1 security List Removal Skips Bookmark Ownership

When an editor on a shared list asks the agent to remove a bookmark, this tool forwards the model-supplied bookmarkId to listsApi.removeFromList. The inspected list removal path checks list edit rights but not bookmark ownership, so the agent can remove another user's bookmark from a shared list if that ID is supplied.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/trpc/routers/chat/tools.ts
Line: 664

Comment:
**List Removal Skips Bookmark Ownership**

When an editor on a shared list asks the agent to remove a bookmark, this tool forwards the model-supplied `bookmarkId` to `listsApi.removeFromList`. The inspected list removal path checks list edit rights but not bookmark ownership, so the agent can remove another user's bookmark from a shared list if that ID is supplied.

How can I resolve this? If you propose a fix, please make it concise.

function parseSearchCursor(nextCursor: string | undefined) {
if (!nextCursor) {
return undefined;
}

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.

P2 Malformed Cursor Aborts Tool

The nextCursor value is generated or replayed by the model, but invalid JSON or a cursor with the wrong shape is parsed with uncaught JSON.parse/Zod errors. A hallucinated or stale cursor makes the tool execution fail instead of returning a recoverable invalid-cursor result to the chat turn.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/trpc/routers/chat/tools.ts
Line: 180

Comment:
**Malformed Cursor Aborts Tool**

The `nextCursor` value is generated or replayed by the model, but invalid JSON or a cursor with the wrong shape is parsed with uncaught `JSON.parse`/Zod errors. A hallucinated or stale cursor makes the tool execution fail instead of returning a recoverable invalid-cursor result to the chat turn.

How can I resolve this? If you propose a fix, please make it concise.

@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: a4550040cd

ℹ️ 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".

message: z.string().trim().min(1),
}),
)
.subscription(async function* (opts): AsyncGenerator<ChatStreamEvent> {

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 Route chat streams through a subscription-capable link

This makes chat.message a subscription, but the clients I checked in apps/web/lib/providers.tsx and packages/shared-react/providers/trpc-provider.tsx are still configured with only httpBatchLink. tRPC's HTTP subscription docs require routing op.type === 'subscription' through httpSubscriptionLink (or using wsLink) via splitLink (https://trpc.io/docs/client/links/httpSubscriptionLink), so a web/mobile call to the only message-send endpoint will fail before streamChatMessage runs. Please add the subscription-capable link with this backend change or expose the stream through a transport the existing clients support.

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