From ec6bd3155c09d9e35f5ee4d21c02de0c82eaf8b4 Mon Sep 17 00:00:00 2001 From: Aadi <123532141+golok727@users.noreply.github.com> Date: Wed, 23 Jul 2025 21:15:17 +0530 Subject: [PATCH 1/4] fix(server): handle missing Gmail permissions properly (#1804) --- apps/server/src/trpc/trpc.ts | 58 +++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/apps/server/src/trpc/trpc.ts b/apps/server/src/trpc/trpc.ts index 5f60481bef..9732bf9948 100644 --- a/apps/server/src/trpc/trpc.ts +++ b/apps/server/src/trpc/trpc.ts @@ -40,37 +40,47 @@ export const activeConnectionProcedure = privateProcedure.use(async ({ ctx, next } }); +const permissionErrors = ['precondition check', 'insufficient permission', 'invalid credentials']; + export const activeDriverProcedure = activeConnectionProcedure.use(async ({ ctx, next }) => { const { activeConnection, sessionUser } = ctx; const res = await next({ ctx: { ...ctx } }); - // This is for when the user has not granted the required scopes for GMail - if (!res.ok && res.error.message === 'Precondition check failed.') { - throw new TRPCError({ - code: 'BAD_REQUEST', - message: 'Required scopes missing', - cause: res.error, - }); - } - - if (!res.ok && res.error.message === 'invalid_grant') { - // Remove the access token and refresh token - const db = await getZeroDB(sessionUser.id); - await db.updateConnection(activeConnection.id, { - accessToken: null, - refreshToken: null, - }); + if (!res.ok) { + const errorMessage = res.error.message.toLowerCase(); - ctx.c.header( - 'X-Zero-Redirect', - `/settings/connections?disconnectedConnectionId=${activeConnection.id}`, + const isPermissionError = permissionErrors.some((errorType) => + errorMessage.includes(errorType), ); - throw new TRPCError({ - code: 'UNAUTHORIZED', - message: 'Connection expired. Please reconnect.', - cause: res.error, - }); + if (isPermissionError) { + throw new TRPCError({ + code: 'BAD_REQUEST', + message: 'Required scopes missing', + cause: res.error, + }); + } + + // Handle token expiration/refresh issues + if (errorMessage.includes('invalid_grant')) { + // Remove the access token and refresh token + const db = await getZeroDB(sessionUser.id); + await db.updateConnection(activeConnection.id, { + accessToken: null, + refreshToken: null, + }); + + ctx.c.header( + 'X-Zero-Redirect', + `/settings/connections?disconnectedConnectionId=${activeConnection.id}`, + ); + + throw new TRPCError({ + code: 'UNAUTHORIZED', + message: 'Connection expired. Please reconnect.', + cause: res.error, + }); + } } return res; From f31f93cd27b39d71923fcdc26b8d4240a57674f8 Mon Sep 17 00:00:00 2001 From: Nizzy Date: Wed, 23 Jul 2025 11:48:50 -0400 Subject: [PATCH 2/4] corners --- apps/mail/components/create/email-composer.tsx | 2 +- apps/mail/components/mail/reply-composer.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/mail/components/create/email-composer.tsx b/apps/mail/components/create/email-composer.tsx index 75b37c99c8..54b1d98ff6 100644 --- a/apps/mail/components/create/email-composer.tsx +++ b/apps/mail/components/create/email-composer.tsx @@ -709,7 +709,7 @@ export function EmailComposer({ className, )} > -
+
{/* To, Cc, Bcc */}
diff --git a/apps/mail/components/mail/reply-composer.tsx b/apps/mail/components/mail/reply-composer.tsx index 8c9245fbbd..ea35fb4427 100644 --- a/apps/mail/components/mail/reply-composer.tsx +++ b/apps/mail/components/mail/reply-composer.tsx @@ -242,10 +242,10 @@ export default function ReplyCompose({ messageId }: ReplyComposeProps) { if (!mode || !emailData) return null; return ( -
+
{ setMode(null); From a8e5c82fb62d73d759e9548e4af14e4897ca312f Mon Sep 17 00:00:00 2001 From: Adam <13007539+MrgSub@users.noreply.github.com> Date: Wed, 23 Jul 2025 11:30:27 -0700 Subject: [PATCH 3/4] Add sequential thinking processor and switch to OpenAI model (#1808) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # READ CAREFULLY THEN REMOVE Remove bullet points that are not relevant. PLEASE REFRAIN FROM USING AI TO WRITE YOUR CODE AND PR DESCRIPTION. IF YOU DO USE AI TO WRITE YOUR CODE PLEASE PROVIDE A DESCRIPTION AND REVIEW IT CAREFULLY. MAKE SURE YOU UNDERSTAND THE CODE YOU ARE SUBMITTING USING AI. - Pull requests that do not follow these guidelines will be closed without review or comment. - If you use AI to write your PR description your pr will be close without review or comment. - If you are unsure about anything, feel free to ask for clarification. ## Description Please provide a clear description of your changes. --- ## Type of Change Please delete options that are not relevant. - [ ] 🐛 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (non-breaking change which adds functionality) - [ ] 💥 Breaking change (fix or feature with breaking changes) - [ ] 📝 Documentation update - [ ] 🎨 UI/UX improvement - [ ] 🔒 Security enhancement - [ ] ⚡ Performance improvement ## Areas Affected Please check all that apply: - [ ] Email Integration (Gmail, IMAP, etc.) - [ ] User Interface/Experience - [ ] Authentication/Authorization - [ ] Data Storage/Management - [ ] API Endpoints - [ ] Documentation - [ ] Testing Infrastructure - [ ] Development Workflow - [ ] Deployment/Infrastructure ## Testing Done Describe the tests you've done: - [ ] Unit tests added/updated - [ ] Integration tests added/updated - [ ] Manual testing performed - [ ] Cross-browser testing (if UI changes) - [ ] Mobile responsiveness verified (if UI changes) ## Security Considerations For changes involving data or authentication: - [ ] No sensitive data is exposed - [ ] Authentication checks are in place - [ ] Input validation is implemented - [ ] Rate limiting is considered (if applicable) ## Checklist - [ ] I have read the [CONTRIBUTING](https://github.com/Mail-0/Zero/blob/staging/.github/CONTRIBUTING.md) document - [ ] My code follows the project's style guidelines - [ ] I have performed a self-review of my code - [ ] I have commented my code, particularly in complex areas - [ ] I have updated the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix/feature works - [ ] All tests pass locally - [ ] Any dependent changes are merged and published ## Additional Notes Add any other context about the pull request here. ## Screenshots/Recordings Add screenshots or recordings here if applicable. --- _By submitting this pull request, I confirm that my contribution is made under the terms of the project's license._ --- ## Summary by cubic Added a sequential thinking processor for dynamic problem-solving and switched the default model to OpenAI for agent responses. - **New Features** - Introduced a SequentialThinkingProcessor to support step-by-step and branching thought processes. - Added ThinkingMCP agent for advanced reasoning workflows. - **Dependencies** - Updated environment to use OpenAI models by default. --- apps/mail/components/party.tsx | 1 - apps/server/src/lib/sequential-thinking.ts | 303 +++++++++++++++++++++ apps/server/src/routes/agent/index.ts | 29 +- apps/server/wrangler.jsonc | 1 + 4 files changed, 329 insertions(+), 5 deletions(-) create mode 100644 apps/server/src/lib/sequential-thinking.ts diff --git a/apps/mail/components/party.tsx b/apps/mail/components/party.tsx index bd8e0c92a8..a297cf8b5f 100644 --- a/apps/mail/components/party.tsx +++ b/apps/mail/components/party.tsx @@ -45,7 +45,6 @@ export const NotificationProvider = () => { queryClient.invalidateQueries({ queryKey: trpc.mail.get.queryKey({ id: threadId }), }); - console.log('invalidated mail get', threadId); } else if (type === IncomingMessageType.Mail_List) { const { folder } = JSON.parse(message.data); queryClient.invalidateQueries({ diff --git a/apps/server/src/lib/sequential-thinking.ts b/apps/server/src/lib/sequential-thinking.ts new file mode 100644 index 0000000000..1aac210de1 --- /dev/null +++ b/apps/server/src/lib/sequential-thinking.ts @@ -0,0 +1,303 @@ +/* + * Licensed to Zero Email Inc. under one or more contributor license agreements. + * You may not use this file except in compliance with the Apache License, Version 2.0 (the "License"). + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Reuse or distribution of this file requires a license from Zero Email Inc. + */ + +import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; +import type { env } from 'cloudflare:workers'; +import { McpAgent } from 'agents/mcp'; +import { z } from 'zod'; + +interface ThoughtData { + thought: string; + thoughtNumber: number; + totalThoughts: number; + isRevision?: boolean; + revisesThought?: number; + branchFromThought?: number; + branchId?: string; + needsMoreThoughts?: boolean; + nextThoughtNeeded: boolean; +} + +interface SequentialThinkingParams { + thought: string; + nextThoughtNeeded: boolean; + thoughtNumber: number; + totalThoughts: number; + isRevision?: boolean; + revisesThought?: number; + branchFromThought?: number; + branchId?: string; + needsMoreThoughts?: boolean; +} + +export class SequentialThinkingProcessor { + private thoughtHistory: ThoughtData[] = []; + private branches: Record = {}; + private disableThoughtLogging: boolean; + + constructor() { + this.disableThoughtLogging = false; // Enable logging by default in Zero + } + + private validateThoughtData(input: SequentialThinkingParams): ThoughtData { + if (!input.thought || typeof input.thought !== 'string') { + throw new Error('Invalid thought: must be a string'); + } + if (!input.thoughtNumber || typeof input.thoughtNumber !== 'number') { + throw new Error('Invalid thoughtNumber: must be a number'); + } + if (!input.totalThoughts || typeof input.totalThoughts !== 'number') { + throw new Error('Invalid totalThoughts: must be a number'); + } + if (typeof input.nextThoughtNeeded !== 'boolean') { + throw new Error('Invalid nextThoughtNeeded: must be a boolean'); + } + + return { + thought: input.thought, + thoughtNumber: input.thoughtNumber, + totalThoughts: input.totalThoughts, + nextThoughtNeeded: input.nextThoughtNeeded, + isRevision: input.isRevision, + revisesThought: input.revisesThought, + branchFromThought: input.branchFromThought, + branchId: input.branchId, + needsMoreThoughts: input.needsMoreThoughts, + }; + } + + private formatThought(thoughtData: ThoughtData): string { + const { + thoughtNumber, + totalThoughts, + thought, + isRevision, + revisesThought, + branchFromThought, + branchId, + } = thoughtData; + + let prefix = ''; + let context = ''; + + if (isRevision) { + prefix = '🔄 Revision'; + context = ` (revising thought ${revisesThought})`; + } else if (branchFromThought) { + prefix = '🌿 Branch'; + context = ` (from thought ${branchFromThought}, ID: ${branchId})`; + } else { + prefix = '💭 Thought'; + context = ''; + } + + const header = `${prefix} ${thoughtNumber}/${totalThoughts}${context}`; + const border = '─'.repeat(Math.max(header.length, thought.length) + 4); + + return ` +┌${border}┐ +│ ${header} │ +├${border}┤ +│ ${thought.padEnd(border.length - 2)} │ +└${border}┘`; + } + + public processThought(input: SequentialThinkingParams) { + try { + const validatedInput = this.validateThoughtData(input); + + if (validatedInput.thoughtNumber > validatedInput.totalThoughts) { + validatedInput.totalThoughts = validatedInput.thoughtNumber; + } + + this.thoughtHistory.push(validatedInput); + + if (validatedInput.branchFromThought && validatedInput.branchId) { + if (!this.branches[validatedInput.branchId]) { + this.branches[validatedInput.branchId] = []; + } + this.branches[validatedInput.branchId].push(validatedInput); + } + + if (!this.disableThoughtLogging) { + const formattedThought = this.formatThought(validatedInput); + console.log(formattedThought); // Use console.log instead of console.error + } + + return { + content: [ + { + type: 'text' as const, + text: JSON.stringify( + { + thoughtNumber: validatedInput.thoughtNumber, + totalThoughts: validatedInput.totalThoughts, + nextThoughtNeeded: validatedInput.nextThoughtNeeded, + branches: Object.keys(this.branches), + thoughtHistoryLength: this.thoughtHistory.length, + }, + null, + 2, + ), + }, + ], + }; + } catch (error) { + return { + content: [ + { + type: 'text' as const, + text: JSON.stringify( + { + error: error instanceof Error ? error.message : String(error), + status: 'failed', + }, + null, + 2, + ), + }, + ], + isError: true, + }; + } + } + + public getThoughtHistory(): ThoughtData[] { + return this.thoughtHistory; + } + + public getBranches(): Record { + return this.branches; + } + + public reset(): void { + this.thoughtHistory = []; + this.branches = {}; + } +} + +export class ThinkingMCP extends McpAgent, { userId: string }> { + thinkingServer = new SequentialThinkingProcessor(); + server = new McpServer({ + name: 'thinking-mcp', + version: '1.0.0', + description: 'Thinking MCP', + }); + + async init(): Promise { + this.server.tool('Test', () => { + return { + content: [{ type: 'text' as const, text: 'Hello World' }], + }; + }); + + console.log('Here!'); + + // this.server.registerTool( + // 'sequentialthinking', + // { + // description: `A detailed tool for dynamic and reflective problem-solving through thoughts. + // This tool helps analyze problems through a flexible thinking process that can adapt and evolve. + // Each thought can build on, question, or revise previous insights as understanding deepens. + + // When to use this tool: + // - Breaking down complex problems into steps + // - Planning and design with room for revision + // - Analysis that might need course correction + // - Problems where the full scope might not be clear initially + // - Problems that require a multi-step solution + // - Tasks that need to maintain context over multiple steps + // - Situations where irrelevant information needs to be filtered out + + // Key features: + // - You can adjust total_thoughts up or down as you progress + // - You can question or revise previous thoughts + // - You can add more thoughts even after reaching what seemed like the end + // - You can express uncertainty and explore alternative approaches + // - Not every thought needs to build linearly - you can branch or backtrack + // - Generates a solution hypothesis + // - Verifies the hypothesis based on the Chain of Thought steps + // - Repeats the process until satisfied + // - Provides a correct answer + + // Parameters explained: + // - thought: Your current thinking step, which can include: + // * Regular analytical steps + // * Revisions of previous thoughts + // * Questions about previous decisions + // * Realizations about needing more analysis + // * Changes in approach + // * Hypothesis generation + // * Hypothesis verification + // - next_thought_needed: True if you need more thinking, even if at what seemed like the end + // - thought_number: Current number in sequence (can go beyond initial total if needed) + // - total_thoughts: Current estimate of thoughts needed (can be adjusted up/down) + // - is_revision: A boolean indicating if this thought revises previous thinking + // - revises_thought: If is_revision is true, which thought number is being reconsidered + // - branch_from_thought: If branching, which thought number is the branching point + // - branch_id: Identifier for the current branch (if any) + // - needs_more_thoughts: If reaching end but realizing more thoughts needed + + // You should: + // 1. Start with an initial estimate of needed thoughts, but be ready to adjust + // 2. Feel free to question or revise previous thoughts + // 3. Don't hesitate to add more thoughts if needed, even at the "end" + // 4. Express uncertainty when present + // 5. Mark thoughts that revise previous thinking or branch into new paths + // 6. Ignore information that is irrelevant to the current step + // 7. Generate a solution hypothesis when appropriate + // 8. Verify the hypothesis based on the Chain of Thought steps + // 9. Repeat the process until satisfied with the solution + // 10. Provide a single, ideally correct answer as the final output + // 11. Only set next_thought_needed to false when truly done and a satisfactory answer is reached`, + // inputSchema: { + // thought: z.string().describe('Your current thinking step'), + // nextThoughtNeeded: z.boolean().describe('Whether another thought step is needed'), + // thoughtNumber: z.number().int().min(1).describe('Current thought number'), + // totalThoughts: z.number().int().min(1).describe('Estimated total thoughts needed'), + // isRevision: z.boolean().optional().describe('Whether this revises previous thinking'), + // revisesThought: z + // .number() + // .int() + // .min(1) + // .optional() + // .describe('Which thought is being reconsidered'), + // branchFromThought: z + // .number() + // .int() + // .min(1) + // .optional() + // .describe('Branching point thought number'), + // branchId: z.string().optional().describe('Branch identifier'), + // needsMoreThoughts: z.boolean().optional().describe('If more thoughts are needed'), + // }, + // }, + // (params) => { + // return this.thinkingServer.processThought({ + // thought: params.thought, + // nextThoughtNeeded: params.nextThoughtNeeded, + // thoughtNumber: params.thoughtNumber, + // totalThoughts: params.totalThoughts, + // isRevision: params.isRevision, + // revisesThought: params.revisesThought, + // branchFromThought: params.branchFromThought, + // branchId: params.branchId, + // needsMoreThoughts: params.needsMoreThoughts, + // }); + // }, + // ); + } +} diff --git a/apps/server/src/routes/agent/index.ts b/apps/server/src/routes/agent/index.ts index 6ed51c800a..a34504b6ef 100644 --- a/apps/server/src/routes/agent/index.ts +++ b/apps/server/src/routes/agent/index.ts @@ -51,6 +51,7 @@ import { processToolCalls } from './utils'; import { env } from 'cloudflare:workers'; import type { Connection } from 'agents'; import { openai } from '@ai-sdk/openai'; +import { openai } from '@ai-sdk/openai'; import { createDb } from '../../db'; import { DriverRpcDO } from './rpc'; import { eq } from 'drizzle-orm'; @@ -1065,7 +1066,7 @@ export class ZeroAgent extends AIChatAgent { private chatMessageAbortControllers: Map = new Map(); async registerZeroMCP() { - await this.mcp.connect(env.VITE_PUBLIC_BACKEND_URL + '/sse', { + await this.mcp.connect(env.VITE_PUBLIC_BACKEND_URL + '/sse?mcpId=zero-mcp', { transport: { authProvider: new DurableObjectOAuthClientProvider( this.ctx.storage, @@ -1076,8 +1077,20 @@ export class ZeroAgent extends AIChatAgent { }); } + async registerThinkingMCP() { + await this.mcp.connect(env.VITE_PUBLIC_BACKEND_URL + '/sse?mcpId=thinking-mcp', { + transport: { + authProvider: new DurableObjectOAuthClientProvider( + this.ctx.storage, + 'thinking-mcp', + env.VITE_PUBLIC_BACKEND_URL, + ), + }, + }); + } + onStart(): void | Promise { - // this.registerZeroMCP(); + // this.registerThinkingMCP(); } private getDataStreamResponse( @@ -1091,11 +1104,14 @@ export class ZeroAgent extends AIChatAgent { if (this.name === 'general') return; const connectionId = this.name; const orchestrator = new ToolOrchestrator(dataStream, connectionId); - // const mcpTools = await this.mcp.unstable_getAITools(); + + // const mcpTools = this.mcp.unstable_getAITools(); const rawTools = { ...(await authTools(connectionId)), + // ...mcpTools, }; + const tools = orchestrator.processTools(rawTools); const processedMessages = await processToolCalls( { @@ -1106,8 +1122,13 @@ export class ZeroAgent extends AIChatAgent { {}, ); + const model = + env.USE_OPENAI === 'true' + ? openai(env.OPENAI_MODEL || 'gpt-4o') + : anthropic(env.OPENAI_MODEL || 'claude-3-7-sonnet-20250219'); + const result = streamText({ - model: anthropic(env.OPENAI_MODEL || 'claude-3-5-haiku-latest'), + model, maxSteps: 10, messages: processedMessages, tools, diff --git a/apps/server/wrangler.jsonc b/apps/server/wrangler.jsonc index 6ae420f957..46d73b88d5 100644 --- a/apps/server/wrangler.jsonc +++ b/apps/server/wrangler.jsonc @@ -116,6 +116,7 @@ "THREAD_SYNC_LOOP": "false", "DISABLE_WORKFLOWS": "false", "AUTORAG_ID": "", + "USE_OPENAI": "true", }, "kv_namespaces": [ { From d4953f19dfa41813001e73444b051a2fcac6d414 Mon Sep 17 00:00:00 2001 From: Adam <13007539+MrgSub@users.noreply.github.com> Date: Wed, 23 Jul 2025 11:34:59 -0700 Subject: [PATCH 4/4] Remove license header and zod import (#1809) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # READ CAREFULLY THEN REMOVE Remove bullet points that are not relevant. PLEASE REFRAIN FROM USING AI TO WRITE YOUR CODE AND PR DESCRIPTION. IF YOU DO USE AI TO WRITE YOUR CODE PLEASE PROVIDE A DESCRIPTION AND REVIEW IT CAREFULLY. MAKE SURE YOU UNDERSTAND THE CODE YOU ARE SUBMITTING USING AI. - Pull requests that do not follow these guidelines will be closed without review or comment. - If you use AI to write your PR description your pr will be close without review or comment. - If you are unsure about anything, feel free to ask for clarification. ## Description Please provide a clear description of your changes. --- ## Type of Change Please delete options that are not relevant. - [ ] 🐛 Bug fix (non-breaking change which fixes an issue) - [ ] ✨ New feature (non-breaking change which adds functionality) - [ ] 💥 Breaking change (fix or feature with breaking changes) - [ ] 📝 Documentation update - [ ] 🎨 UI/UX improvement - [ ] 🔒 Security enhancement - [ ] ⚡ Performance improvement ## Areas Affected Please check all that apply: - [ ] Email Integration (Gmail, IMAP, etc.) - [ ] User Interface/Experience - [ ] Authentication/Authorization - [ ] Data Storage/Management - [ ] API Endpoints - [ ] Documentation - [ ] Testing Infrastructure - [ ] Development Workflow - [ ] Deployment/Infrastructure ## Testing Done Describe the tests you've done: - [ ] Unit tests added/updated - [ ] Integration tests added/updated - [ ] Manual testing performed - [ ] Cross-browser testing (if UI changes) - [ ] Mobile responsiveness verified (if UI changes) ## Security Considerations For changes involving data or authentication: - [ ] No sensitive data is exposed - [ ] Authentication checks are in place - [ ] Input validation is implemented - [ ] Rate limiting is considered (if applicable) ## Checklist - [ ] I have read the [CONTRIBUTING](https://github.com/Mail-0/Zero/blob/staging/.github/CONTRIBUTING.md) document - [ ] My code follows the project's style guidelines - [ ] I have performed a self-review of my code - [ ] I have commented my code, particularly in complex areas - [ ] I have updated the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix/feature works - [ ] All tests pass locally - [ ] Any dependent changes are merged and published ## Additional Notes Add any other context about the pull request here. ## Screenshots/Recordings Add screenshots or recordings here if applicable. --- _By submitting this pull request, I confirm that my contribution is made under the terms of the project's license._ --- ## Summary by cubic Removed the license header and unused zod import from sequential-thinking.ts to clean up the file. ## Summary by CodeRabbit * **Chores** * Removed the license header comment and an unused import from internal files. No changes to features or functionality. --- apps/server/src/lib/sequential-thinking.ts | 17 ----------------- apps/server/src/routes/agent/index.ts | 1 - 2 files changed, 18 deletions(-) diff --git a/apps/server/src/lib/sequential-thinking.ts b/apps/server/src/lib/sequential-thinking.ts index 1aac210de1..0c68fe91c2 100644 --- a/apps/server/src/lib/sequential-thinking.ts +++ b/apps/server/src/lib/sequential-thinking.ts @@ -1,23 +1,6 @@ -/* - * Licensed to Zero Email Inc. under one or more contributor license agreements. - * You may not use this file except in compliance with the Apache License, Version 2.0 (the "License"). - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Reuse or distribution of this file requires a license from Zero Email Inc. - */ - import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { env } from 'cloudflare:workers'; import { McpAgent } from 'agents/mcp'; -import { z } from 'zod'; interface ThoughtData { thought: string; diff --git a/apps/server/src/routes/agent/index.ts b/apps/server/src/routes/agent/index.ts index a34504b6ef..da0156728e 100644 --- a/apps/server/src/routes/agent/index.ts +++ b/apps/server/src/routes/agent/index.ts @@ -51,7 +51,6 @@ import { processToolCalls } from './utils'; import { env } from 'cloudflare:workers'; import type { Connection } from 'agents'; import { openai } from '@ai-sdk/openai'; -import { openai } from '@ai-sdk/openai'; import { createDb } from '../../db'; import { DriverRpcDO } from './rpc'; import { eq } from 'drizzle-orm';