-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add subscribers to kit #61
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThis pull request introduces several updates across the codebase. New dependencies are added to support AI functionality and rich text editing by integrating the OpenAI SDK and Tiptap libraries. Layout components have been adjusted to improve centering and width, while a new chat API endpoint has been established to process messages via a streaming function. Additional changes include enhancements to error handling, a function to continue AI conversations, updates to the waitlist signup process using webhooks, refined database seeding logic, and the removal of obsolete CSS files and redundant SVG paths. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant API as Chat API (POST)
participant Stream as streamText
participant Model as OpenAI "gpt-4o-mini"
Client->>API: Send POST request with messages
API->>Stream: Convert messages & invoke streamText
Stream->>Model: Request markdown response
Model-->>Stream: Stream response text
Stream-->>API: Pass back processed stream
API-->>Client: Return stream response
sequenceDiagram
participant User
participant Waitlist as Waitlist Function
participant Zapier as Zapier Webhook
participant Discord as Discord Webhook
participant Analytics as Analytics Tracker
User->>Waitlist: Submit email & referrer
Waitlist->>Zapier: POST to Zapier (if URL set)
Waitlist->>Discord: POST to Discord (if URL set)
Waitlist->>Analytics: Log waitlist signup event
Possibly related PRs
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🔭 Outside diff range comments (1)
apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/page.tsx (1)
32-34
: 🛠️ Refactor suggestionAdd content type validation.
Add type validation for the content before rendering to prevent runtime errors.
const content = policy.content as JSONContent; +if (!content || typeof content !== 'object') { + return <div>Invalid policy content</div>; +}
🧹 Nitpick comments (5)
packages/db/prisma/seed.js (1)
12-26
: Add a safety guard to prevent accidental data truncation in non-development environments.While this cleanup is presumably intended for a development environment, a simple code or environment mismatch could lead to erroneous data loss in production. Consider adding guards or explicit confirmations to ensure the cleanup runs only when truly intended.
if (process.env.NODE_ENV === "development") { + // Additional safeguard if needed, e.g.: + if (!process.env.ALLOW_DB_CLEANUP) { + console.log("DB cleanup skipped because ALLOW_DB_CLEANUP is not set."); + return; + } console.log("\n🗑️ Cleaning up existing data..."); ...apps/app/src/components/editor/actions/ai.ts (1)
8-16
: Add error handling for AI call failures.Currently, if the
streamText
call fails or the model name is incorrect, the function will throw an unhandled error. Consider wrapping it in a try-catch block or returning a more descriptive error to provide better resilience and debugging context.export async function continueConversation(messages: CoreMessage[]) { + try { const result = await streamText({ model: openai("gpt-4o-mini"), messages, }); const stream = createStreamableValue(result.textStream); return stream.value; + } catch (err) { + console.error("Error in continueConversation:", err); + throw err; + } }apps/app/src/components/editor/editor.tsx (1)
19-20
: Consider utilizing or exposing the editor's state.Currently,
editorState
is being tracked but not used by the component or returned for external orchestration. If the parent needs the current document state, you might want to expose it via a callback prop or store it for future reference. Otherwise, remove the unused state to prevent confusion.apps/app/src/app/api/chat/route.ts (1)
4-4
: Remove unused constant.The
maxDuration
constant is defined but not used in the code.-export const maxDuration = 30;
apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/page.tsx (1)
50-52
: Consider configuring Tiptap editor options.The Tiptap editor is used with default settings. Consider configuring editor options like placeholder text, autofocus, and available formatting options.
-<Tiptap content={content} /> +<Tiptap + content={content} + placeholder="Start writing your policy..." + autofocus + editorProps={{ + attributes: { + class: 'prose prose-sm sm:prose lg:prose-lg xl:prose-2xl mx-auto focus:outline-none' + } + }} +/>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
bun.lock
is excluded by!**/*.lock
yarn.lock
is excluded by!**/yarn.lock
,!**/*.lock
📒 Files selected for processing (15)
apps/app/package.json
(2 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/layout.tsx
(1 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/page.tsx
(3 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/layout.tsx
(1 hunks)apps/app/src/app/[locale]/(app)/(dashboard)/settings/layout.tsx
(1 hunks)apps/app/src/app/api/chat/route.ts
(1 hunks)apps/app/src/components/editor/actions/ai.ts
(1 hunks)apps/app/src/components/editor/editor.tsx
(1 hunks)apps/app/src/components/google-sign-in.tsx
(1 hunks)apps/web/src/app/actions/waitlist.ts
(1 hunks)packages/db/prisma/seed.js
(3 hunks)packages/ui/src/components/icons.tsx
(1 hunks)packages/ui/src/prosemirror.css
(0 hunks)packages/ui/src/text-editor.css
(0 hunks)turbo.json
(1 hunks)
💤 Files with no reviewable changes (2)
- packages/ui/src/prosemirror.css
- packages/ui/src/text-editor.css
✅ Files skipped from review due to trivial changes (4)
- apps/app/src/app/[locale]/(app)/(dashboard)/settings/layout.tsx
- apps/app/src/app/[locale]/(app)/(dashboard)/policies/all/layout.tsx
- apps/app/src/components/google-sign-in.tsx
- apps/app/src/app/[locale]/(app)/(dashboard)/policies/[id]/layout.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
packages/db/prisma/seed.js
[error] 53-53: The comma operator is disallowed.
Its use is often confusing and obscures side effects.
(lint/style/noCommaOperator)
[error] 53-53: The comma operator is disallowed.
Its use is often confusing and obscures side effects.
(lint/style/noCommaOperator)
🔇 Additional comments (6)
turbo.json (1)
35-36
: LGTM!The addition of
ZAP_WEBHOOK_URL
to the build task's environment variables aligns with the changes inwaitlist.ts
.packages/db/prisma/seed.js (3)
53-53
: Ignore the static analysis warning regarding the comma operator.This snippet,
(0, node_fs_1.readFileSync)((0, node_path_1.join)(...))
, is a TypeScript/ES build artifact and does not actually use the comma operator. Treat it as a false positive from the static analysis tool.🧰 Tools
🪛 Biome (1.9.4)
[error] 53-53: The comma operator is disallowed.
Its use is often confusing and obscures side effects.
(lint/style/noCommaOperator)
[error] 53-53: The comma operator is disallowed.
Its use is often confusing and obscures side effects.
(lint/style/noCommaOperator)
165-165
: Good job filtering by category ID.This change ensures controls are associated with their correct categories based on
data.categoryId
. This makes the seeding process more accurate.
52-99
:❓ Verification inconclusive
Verify concurrency and references when replacing existing policies by slug.
The approach of deleting existing conflicts (same slug, different ID) may invalidate references in other tables. If references exist that rely on the original policy ID, they’ll break after deletion. Confirm that this is acceptable and not used in concurrent seeds.
🏁 Script executed:
#!/bin/bash # Explanation: We'll search references to the policy ID in the codebase to confirm usage. rg -A 4 '\.where:\s*{\s*id:\s*'Length of output: 149
Ensure deletion of policies does not break dependent references
The updated seed code deletes policies that share the same slug but have a different ID. This raises a potential risk: if other parts of the system (or database relations) reference the original policy ID, those references would break when the policy is deleted.
- The automated search using the initial regex did not yield clear evidence of external references to policy IDs. However, the regex error indicates that our search pattern needs adjustment, so we recommend a manual verification.
- Action: Please double-check any code paths or database relations (including the Prisma schema) for dependencies on a policy’s ID. Confirm that deleting a policy record before upserting a new one is acceptable in your context and won’t lead to data integrity issues during concurrent seed operations.
🧰 Tools
🪛 Biome (1.9.4)
[error] 53-53: The comma operator is disallowed.
Its use is often confusing and obscures side effects.
(lint/style/noCommaOperator)
[error] 53-53: The comma operator is disallowed.
Its use is often confusing and obscures side effects.
(lint/style/noCommaOperator)
packages/ui/src/components/icons.tsx (1)
252-257
: LGTM! Improved Google icon implementation.The Google icon implementation has been simplified by:
- Using
currentColor
for better theme support- Consolidating paths under a single group element
apps/app/package.json (1)
13-30
:❓ Verification inconclusive
Verify dependency versions for security and compatibility.
Please verify that the versions of the newly added dependencies are the latest stable versions and don't have any known security vulnerabilities.
🏁 Script executed:
#!/bin/bash # Check for latest versions and known vulnerabilities npm audit npm outdated @ai-sdk/openai @tiptap/pm @tiptap/react @tiptap/starter-kit aiLength of output: 438
Dependency version security check requires additional steps
The automated check was inconclusive due to the missing package-lock file. To reliably verify that the new dependency versions are both secure and up-to-date, please:
- Create the lock file (e.g., by running
npm i --package-lock-only
in the repository root).- Re-run the security and outdated checks with
npm audit
andnpm outdated @ai-sdk/openai @tiptap/pm @tiptap/react @tiptap/starter-kit ai
.- Manually verify that these dependencies are using the latest stable versions and do not have known vulnerabilities.
const kitPayload: ZapSubscriberPayload = { | ||
email_address: parsedInput.email, | ||
referrer: typeof window !== 'undefined' ? window.location.href : 'https://trycomp.ai', | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove duplicated code and fix server-side window check.
The code has the following issues:
- The
window
check is server-side butwindow
is only available client-side. - The payload creation is duplicated.
Apply this diff to fix the issues:
+const getReferrer = () => {
+ return 'https://trycomp.ai';
+};
- const kitPayload: ZapSubscriberPayload = {
- email_address: parsedInput.email,
- referrer: typeof window !== 'undefined' ? window.location.href : 'https://trycomp.ai',
- };
+ const payload: ZapSubscriberPayload = {
+ email_address: parsedInput.email,
+ referrer: getReferrer(),
+ };
- const zapPayload: ZapSubscriberPayload = {
- email_address: parsedInput.email,
- referrer: typeof window !== 'undefined' ? window.location.href : 'https://trycomp.ai',
- };
-
await ky.post(
process.env.ZAP_WEBHOOK_URL as string,
{
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
- json: kitPayload,
+ json: payload,
}
);
Also applies to: 36-39
if (process.env.DISCORD_WEBHOOK_URL) { | ||
await ky.post(process.env.DISCORD_WEBHOOK_URL as string, { | ||
json: { | ||
content: `New waitlist signup: ${parsedInput.email}`, | ||
}, | ||
}); | ||
|
||
await tasks.trigger<typeof introductionEmailTask>( | ||
"introduction-email", | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling and consistent headers.
The webhook calls lack error handling and have inconsistent header usage.
Apply this diff to improve error handling and header consistency:
+ const headers = {
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ };
if (process.env.DISCORD_WEBHOOK_URL) {
- await ky.post(process.env.DISCORD_WEBHOOK_URL as string, {
- json: {
- content: `New waitlist signup: ${parsedInput.email}`,
- },
- });
+ try {
+ await ky.post(process.env.DISCORD_WEBHOOK_URL as string, {
+ headers,
+ json: {
+ content: `New waitlist signup: ${parsedInput.email}`,
+ },
+ });
+ } catch (error) {
+ console.error('Failed to send Discord notification:', error);
+ // Continue execution as this is non-critical
+ }
}
if (process.env.ZAP_WEBHOOK_URL) {
- const zapPayload: ZapSubscriberPayload = {
- email_address: parsedInput.email,
- referrer: typeof window !== 'undefined' ? window.location.href : 'https://trycomp.ai',
- };
-
- await ky.post(
- process.env.ZAP_WEBHOOK_URL as string,
- {
- headers: {
- "Content-Type": "application/json",
- Accept: "application/json",
- },
- json: kitPayload,
- }
- );
+ try {
+ await ky.post(
+ process.env.ZAP_WEBHOOK_URL as string,
+ {
+ headers,
+ json: payload,
+ }
+ );
+ } catch (error) {
+ console.error('Failed to send Zapier notification:', error);
+ throw new Error('Failed to add subscriber');
+ }
}
Also applies to: 35-51
useEffect(() => { | ||
setEditorState(JSON.parse(editor?.getText() || "{}")); | ||
}, [editor]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the built-in method to obtain the editor’s content as JSON.
editor.getText()
returns plain text, which wouldn't be valid JSON to parse. Instead, consider using editor?.getJSON()
to retrieve the editor’s state safely and accurately.
useEffect(() => {
- setEditorState(JSON.parse(editor?.getText() || "{}"));
+ if (editor) {
+ setEditorState(editor.getJSON());
+ }
}, [editor]);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
useEffect(() => { | |
setEditorState(JSON.parse(editor?.getText() || "{}")); | |
}, [editor]); | |
useEffect(() => { | |
if (editor) { | |
setEditorState(editor.getJSON()); | |
} | |
}, [editor]); |
export async function POST(req: Request) { | ||
const { messages } = await req.json(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling for request body parsing.
The current implementation lacks error handling for JSON parsing and message validation.
export async function POST(req: Request) {
+ try {
const { messages } = await req.json();
+ if (!messages || !Array.isArray(messages)) {
+ return new Response(
+ JSON.stringify({ error: "Invalid messages format" }),
+ { status: 400 }
+ );
+ }
+ } catch (error) {
+ return new Response(
+ JSON.stringify({ error: "Invalid JSON payload" }),
+ { status: 400 }
+ );
+ }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
export async function POST(req: Request) { | |
const { messages } = await req.json(); | |
export async function POST(req: Request) { | |
try { | |
const { messages } = await req.json(); | |
if (!messages || !Array.isArray(messages)) { | |
return new Response( | |
JSON.stringify({ error: "Invalid messages format" }), | |
{ status: 400 } | |
); | |
} | |
} catch (error) { | |
return new Response( | |
JSON.stringify({ error: "Invalid JSON payload" }), | |
{ status: 400 } | |
); | |
} | |
} |
const result = await streamText({ | ||
model: openai("gpt-4o-mini"), | ||
system: | ||
"You generate markdown documents for users. Unless specified, this is a draft. Keep things shortish. Do not add any supplementary text, as everything you say will be placed into a document. If you're confused however, it's okay to ask a user for info. Responses must be either a chat response, or a document. Don't add bold styling to headings.", | ||
messages: convertToCoreMessages(messages), | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Extract system prompt to a configuration file.
The system prompt is hardcoded and quite long. Consider extracting it to a separate configuration file for better maintainability.
Additionally, verify if "gpt-4o-mini" is the correct model name as it seems unusual.
🌐 Web query:
What are the available OpenAI GPT-4 model names?
💡 Result:
OpenAI's GPT-4 family includes multiple model variants with distinct capabilities and naming conventions. Here's a breakdown of available models based on current documentation:
Latest GA Models
-
GPT-4o (
gpt-4o
)- Versions:
2024-11-20
,2024-08-06
,2024-05-13
- Multimodal (text + image input)
- 128K token context window
- Enhanced non-English language support
- Structured outputs & parallel function calling[1][4]
- Versions:
-
GPT-4 Turbo with Vision (
gpt-4
, versionturbo-2024-04-09
)- Replaces previous preview models (
vision-preview
,1106-Preview
) - 128K context window
- Image/text input capabilities[1][2][5]
- Replaces previous preview models (
-
GPT-4o mini (
gpt-4o-mini
)- Version:
2024-07-18
- Cost-effective alternative to GPT 3.5 Turbo series
- Supports text/image processing[1][4]
- Version:
Older GA Models
-
Base GPT-4 (
gpt‑4
)- Versions:
0613
(8K context),0314
(legacy) - Core text processing capabilities[1][6]
- Versions:
-
GPT‑4‑32k
- Version:
0613
(32K context) - Extended context variant[1][6]
- Version:
Specialized Variants
-
GPT‑Turbo Realtime Beta
- Models:
gpt‑4o‑realtime‑preview
,gpt‑4o‑mini‑realtime‑preview
- Real-time audio/text interaction via WebRTC/WebSocket[4]
- Models:
-
Vision-Capable Models
- Requires specific deployment configurations in Azure[1]
Key distinctions:
Feature | GPT‑Turbo | Original GPT‑4 |
---|---|---|
Context Window | 128K | 8K/32K |
Training Data | Up to Dec 2023 | Up to Sep 2021 |
Multimodal Input | Yes | Limited[1][2][5] |
Older versions like 0314
are being phased out[1][6], while preview models (0125-Preview
) are being replaced by stable releases[1]. Model names typically follow gpt‑{version}‑{release_date}
patterns[7].
Citations:
- 1: https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models
- 2: https://en.wikipedia.org/wiki/GPT-4
- 3: https://gptforwork.com/guides/openai-gpt3-models
- 4: https://platform.openai.com/docs/models
- 5: https://help.openai.com/en/articles/7127966-what-is-the-difference-between-the-gpt-4-model-versions
- 6: https://community.openai.com/t/gpt-4-32k-0314-model-name-displayed-on-the-playground-screen/588094
- 7: https://community.openai.com/t/what-do-the-numbers-on-gpt-models-actually-mean/623711
- 8: https://openai.com/index/gpt-4/
- 9: https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/chatgpt
- 10: https://help.openai.com/en/articles/7102672-how-can-i-access-gpt-4-gpt-4-turbo-gpt-4o-and-gpt-4o-mini
Action: Extract Hardcoded System Prompt & Confirm "gpt-4o-mini" Is Valid
- The system prompt in
apps/app/src/app/api/chat/route.ts
(lines 9-14) is currently hardcoded. For better maintainability, extract this prompt into a separate configuration file (e.g.,config/prompts.ts
). - The model name
"gpt-4o-mini"
has been verified against current OpenAI GPT-4 model documentation and is valid.
Summary by CodeRabbit
New Features
Refactor / Style
Chores