feat: add AI Career Copilot AgentKit#102
feat: add AI Career Copilot AgentKit#102Durvankur-Joshi wants to merge 3 commits intoLamatic:mainfrom
Conversation
📝 WalkthroughWalkthroughAdds a new "AI Career Copilot" Next.js kit: UI components, server action, Lamatic client, workflow files, types, and configuration to analyze resume text and produce skills, gaps, roles, readiness score, roadmap, projects, and interview questions. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User (Browser)
participant Form as CareerAnalysisForm
participant Page as Home Page
participant Action as analyzeCareer (Server)
participant Client as Lamatic Client
participant API as Lamatic API
User->>Form: enter resume & domain
Form->>Page: onSubmit(resume, domain)
Page->>Action: analyzeCareer({resume_text, domain})
Action->>Action: validate input
Action->>Client: executeCareerAnalysis({resume_text, domain})
Client->>API: POST executeWorkflow (GraphQL)
alt API success
API-->>Client: workflow result
Client-->>Action: return result
Action-->>Page: { success: true, data }
else API error
API-->>Client: error
Client-->>Action: throw / return error
Action-->>Page: { success: false, error }
end
Page->>Page: render AnalysisResult or ErrorMessage
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Ready for Review
Looking forward to feedback 🚀 |
There was a problem hiding this comment.
Actionable comments posted: 14
🧹 Nitpick comments (9)
kits/assistant/ai-career-copilot/components/ErrorMessage.tsx (1)
19-25: Add explicittype="button"to prevent unintended form submission.The button lacks an explicit
typeattribute. If this component is ever rendered inside a form, the default type ("submit") could cause unintended form submissions.Proposed fix
<button + type="button" onClick={onRetry} className="mt-3 inline-flex items-center gap-2 text-sm text-red-700 hover:text-red-800 font-medium" >kits/assistant/ai-career-copilot/app/globals.css (1)
1-3: Stylelint configuration needs Tailwind support.The Stylelint errors flagging
@tailwindas unknown are false positives. Configure Stylelint withstylelint-config-tailwindcssor add@tailwindto theignoreAtRulesoption forscss/at-rule-no-unknown.Note: These
@tailwinddirectives follow Tailwind v3 syntax. If migrating to Tailwind v4+ per guidelines, the syntax would change to@import "tailwindcss";.kits/assistant/ai-career-copilot/components/SkillsDisplay.tsx (1)
15-15: Consider usinglucide-reacticons instead of emoji for consistency.Other components in this kit (e.g.,
ErrorMessage,RoadmapDisplay) uselucide-reacticons. For visual consistency across the kit, consider replacing the emoji with icons.Proposed changes
'use client'; +import { CheckCircle2, AlertTriangle } from 'lucide-react'; + interface SkillsDisplayProps {- <p className="text-sm font-medium text-gray-700 mb-2">✓ Your Current Skills</p> + <p className="text-sm font-medium text-gray-700 mb-2 flex items-center gap-1"> + <CheckCircle2 className="w-4 h-4 text-green-600" /> + Your Current Skills + </p>- <p className="text-sm font-medium text-gray-700 mb-2">⚠️ Skills to Develop</p> + <p className="text-sm font-medium text-gray-700 mb-2 flex items-center gap-1"> + <AlertTriangle className="w-4 h-4 text-yellow-600" /> + Skills to Develop + </p>Based on learnings: "Use lucide-react for icons throughout kits"
kits/assistant/ai-career-copilot/components/InterviewQuestions.tsx (1)
16-28: Minor: Empty state renders both container and message.When
questions.length === 0, the component renders an empty<div className="space-y-3">followed by the fallback message. Consider conditionally rendering either the list or the fallback.♻️ Suggested improvement
- <div className="space-y-3"> - {questions.map((question, idx) => ( - <div key={idx} className="flex items-start gap-3"> - <span className="flex-shrink-0 w-6 h-6 bg-gray-100 text-gray-600 rounded-full flex items-center justify-center text-xs font-semibold"> - {idx + 1} - </span> - <p className="text-gray-700">{question}</p> - </div> - ))} - </div> - {questions.length === 0 && ( - <p className="text-gray-500 text-center py-4">No interview questions available</p> - )} + {questions.length > 0 ? ( + <div className="space-y-3"> + {questions.map((question, idx) => ( + <div key={idx} className="flex items-start gap-3"> + <span className="flex-shrink-0 w-6 h-6 bg-gray-100 text-gray-600 rounded-full flex items-center justify-center text-xs font-semibold"> + {idx + 1} + </span> + <p className="text-gray-700">{question}</p> + </div> + ))} + </div> + ) : ( + <p className="text-gray-500 text-center py-4">No interview questions available</p> + )}kits/assistant/ai-career-copilot/components/CareerAnalysisForm.tsx (1)
24-51: Form handling should use react-hook-form with zod validation.The current implementation uses manual
useStateand custom validation logic. As per coding guidelines, kit forms should usereact-hook-formwithzodfor validation.♻️ Example refactor structure
import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; const formSchema = z.object({ resumeText: z.string() .min(1, 'Please paste your resume text') .min(50, 'Please provide at least 50 characters of resume text for accurate analysis'), domain: z.string().min(1, 'Please select your target domain'), }); type FormData = z.infer<typeof formSchema>; export default function CareerAnalysisForm({ onSubmit }: CareerAnalysisFormProps) { const { register, handleSubmit, formState: { errors } } = useForm<FormData>({ resolver: zodResolver(formSchema), }); const onFormSubmit = (data: FormData) => { onSubmit(data.resumeText, data.domain); }; return ( <form onSubmit={handleSubmit(onFormSubmit)}> {/* ... */} </form> ); }As per coding guidelines: "Use react-hook-form with zod validation for form handling in kits"
kits/assistant/ai-career-copilot/components/AnalysisResult.tsx (1)
8-8: Remove unusedLightbulbimport.The
Lightbulbicon is imported but not used in this component.RoadmapDisplayimports it separately.♻️ Suggested fix
-import { TrendingUp, Briefcase, Lightbulb } from 'lucide-react'; +import { TrendingUp, Briefcase } from 'lucide-react';kits/assistant/ai-career-copilot/components/ProjectsDisplay.tsx (1)
16-26: Minor: Same empty state pattern issue as InterviewQuestions.The empty container is rendered alongside the fallback message when
projects.length === 0. Consider the same conditional rendering pattern suggested forInterviewQuestions.tsx.kits/assistant/ai-career-copilot/app/page.tsx (1)
69-71: Consider usinghandleResetinstead of page reload for retry.Using
window.location.reload()discards all client state and triggers a full page reload. The existinghandleResetfunction could provide a smoother UX.♻️ Suggested change
- <ErrorMessage message={error} onRetry={() => window.location.reload()} /> + <ErrorMessage message={error} onRetry={handleReset} />kits/assistant/ai-career-copilot/lib/lamatic-client.ts (1)
3-6: Add runtime validation for required environment variables.Non-null assertions (
!) will throw unclear errors if environment variables are missing. Consider adding explicit validation with meaningful error messages.♻️ Suggested improvement
-const endpoint = process.env.LAMATIC_API_URL!; -const apiKey = process.env.LAMATIC_API_KEY!; -const projectId = process.env.LAMATIC_PROJECT_ID!; -const flowId = process.env.AGENTIC_GENERATE_CONTENT!; +const endpoint = process.env.LAMATIC_API_URL; +const apiKey = process.env.LAMATIC_API_KEY; +const projectId = process.env.LAMATIC_PROJECT_ID; +const flowId = process.env.AGENTIC_GENERATE_CONTENT; + +function assertEnvVar(name: string, value: string | undefined): asserts value is string { + if (!value) { + throw new Error(`Missing required environment variable: ${name}`); + } +}Then validate before use:
async executeCareerAnalysis(input: { ... }) { assertEnvVar('LAMATIC_API_URL', endpoint); assertEnvVar('LAMATIC_API_KEY', apiKey); assertEnvVar('LAMATIC_PROJECT_ID', projectId); assertEnvVar('AGENTIC_GENERATE_CONTENT', flowId); // ... }
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 847c6d93-1353-430e-85a7-4cf4415a242e
⛔ Files ignored due to path filters (1)
kits/assistant/ai-career-copilot/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (28)
kits/assistant/ai-career-copilot/.env.examplekits/assistant/ai-career-copilot/.gitignorekits/assistant/ai-career-copilot/README.mdkits/assistant/ai-career-copilot/actions/orchestrate.tskits/assistant/ai-career-copilot/app/globals.csskits/assistant/ai-career-copilot/app/layout.tsxkits/assistant/ai-career-copilot/app/page.tsxkits/assistant/ai-career-copilot/components/AnalysisResult.tsxkits/assistant/ai-career-copilot/components/CareerAnalysisForm.tsxkits/assistant/ai-career-copilot/components/ErrorMessage.tsxkits/assistant/ai-career-copilot/components/InterviewQuestions.tsxkits/assistant/ai-career-copilot/components/LoadingSpinner.tsxkits/assistant/ai-career-copilot/components/ProjectsDisplay.tsxkits/assistant/ai-career-copilot/components/RoadmapDisplay.tsxkits/assistant/ai-career-copilot/components/SkillsDisplay.tsxkits/assistant/ai-career-copilot/config.jsonkits/assistant/ai-career-copilot/flows/ai-career-copilot/README.mdkits/assistant/ai-career-copilot/flows/ai-career-copilot/config.jsonkits/assistant/ai-career-copilot/flows/ai-career-copilot/inputs.jsonkits/assistant/ai-career-copilot/flows/ai-career-copilot/meta.jsonkits/assistant/ai-career-copilot/gitkits/assistant/ai-career-copilot/lib/lamatic-client.tskits/assistant/ai-career-copilot/next.config.jskits/assistant/ai-career-copilot/package.jsonkits/assistant/ai-career-copilot/postcss.config.jskits/assistant/ai-career-copilot/tailwind.config.tskits/assistant/ai-career-copilot/tsconfig.jsonkits/assistant/ai-career-copilot/types/index.ts
| AGENTIC_GENERATE_CONTENT=your-flow-id | ||
| LAMATIC_API_URL=https://your-project.lamatic.dev/graphql | ||
| LAMATIC_PROJECT_ID=your-project-id | ||
| LAMATIC_API_KEY=your-api-key No newline at end of file |
There was a problem hiding this comment.
Add trailing newline to satisfy dotenv linting.
Static analysis flagged missing ending blank line at Line 4; please append a newline at EOF.
🧰 Tools
🪛 dotenv-linter (4.0.0)
[warning] 4-4: [EndingBlankLine] No blank line at the end of the file
(EndingBlankLine)
[warning] 4-4: [UnorderedKey] The LAMATIC_API_KEY key should go before the LAMATIC_API_URL key
(UnorderedKey)
| "eslint": "^8.0.0", | ||
| "eslint-config-next": "^14.0.0", | ||
| "postcss": "^8.4.0", | ||
| "tailwindcss": "^3.3.0", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify current Tailwind major version declared for the kit
python - <<'PY'
import json, re
p = "kits/assistant/ai-career-copilot/package.json"
deps = json.load(open(p)).get("devDependencies", {})
v = deps.get("tailwindcss")
print("tailwindcss version:", v)
m = re.search(r'(\d+)', v or "")
print("major:", m.group(1) if m else "unknown")
PYRepository: Lamatic/AgentKit
Length of output: 96
Update tailwindcss to v4 or later.
The kit requires Tailwind CSS v4+, but package.json declares ^3.3.0 at line 33. Update the dependency version to meet the kit baseline.
| import type { Config } from 'tailwindcss' | ||
|
|
||
| const config: Config = { | ||
| content: [ | ||
| './pages/**/*.{js,ts,jsx,tsx,mdx}', | ||
| './components/**/*.{js,ts,jsx,tsx,mdx}', | ||
| './app/**/*.{js,ts,jsx,tsx,mdx}', | ||
| ], | ||
| theme: { | ||
| extend: { | ||
| colors: { | ||
| primary: { | ||
| 50: '#eff6ff', | ||
| 100: '#dbeafe', | ||
| 200: '#bfdbfe', | ||
| 300: '#93c5fd', | ||
| 400: '#60a5fa', | ||
| 500: '#3b82f6', | ||
| 600: '#2563eb', | ||
| 700: '#1d4ed8', | ||
| 800: '#1e40af', | ||
| 900: '#1e3a8a', | ||
| }, | ||
| }, | ||
| animation: { | ||
| 'fade-in': 'fadeIn 0.5s ease-in-out', | ||
| 'slide-up': 'slideUp 0.3s ease-out', | ||
| }, | ||
| keyframes: { | ||
| fadeIn: { | ||
| '0%': { opacity: '0' }, | ||
| '100%': { opacity: '1' }, | ||
| }, | ||
| slideUp: { | ||
| '0%': { transform: 'translateY(10px)', opacity: '0' }, | ||
| '100%': { transform: 'translateY(0)', opacity: '1' }, | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| plugins: [], | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check the Tailwind CSS version in package.json
fd -t f "package.json" kits/assistant/ai-career-copilot --exec cat {} | jq '.dependencies.tailwindcss // .devDependencies.tailwindcss'Repository: Lamatic/AgentKit
Length of output: 68
Upgrade Tailwind CSS to v4+ and migrate to CSS-first configuration.
The kit currently uses Tailwind CSS v3.3.0, but the coding guidelines require v4+. The tailwind.config.ts file uses the v3 configuration pattern, which is no longer the recommended approach in v4.
Update package.json to Tailwind v4+ and migrate the configuration to Tailwind v4's CSS-first approach using @theme and @config directives in a CSS file instead of this TypeScript config file.
| "compilerOptions": { | ||
| "target": "es5", | ||
| "lib": ["dom", "dom.iterable", "esnext"], | ||
| "allowJs": true, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify whether JS/JSX files exist in TS-only kit code paths.
fd -t f -e js -e jsx kits/assistant/ai-career-copilot | rg -n 'kits/assistant/ai-career-copilot/(app|components|actions|lib|types)/'Repository: Lamatic/AgentKit
Length of output: 493
🏁 Script executed:
#!/bin/bash
# First, check the actual tsconfig.json content
echo "=== tsconfig.json content ==="
cat kits/assistant/ai-career-copilot/tsconfig.json
echo -e "\n=== Searching for JS/JSX files in kit directories ==="
# Proper syntax: search for .js/.jsx files in the kit directory
fd --full-path --type f -e js -e jsx kits/assistant/ai-career-copilot
echo -e "\n=== File structure of the kit ==="
# Show the directory structure to understand what's in the kit
fd --type f --type d . kits/assistant/ai-career-copilot | head -30Repository: Lamatic/AgentKit
Length of output: 2487
Remove unnecessary allowJs setting to enforce TS-only intent.
The "allowJs": true setting at line 5 is unnecessary—all application code (components, actions, app, lib) is already TypeScript, and the tsconfig include array explicitly lists only **/*.ts and **/*.tsx, meaning JavaScript files are not compiled by TypeScript anyway. The presence of next.config.js and postcss.config.js are configuration files outside the application code scope.
Removing this setting (set to false) will align the configuration with the guideline: "Use TypeScript for all kit components and server actions."
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
kits/assistant/ai-career-copilot/.env.example (1)
1-4: Consider reordering keys to satisfy dotenv lint.
dotenv-linterflagged key ordering (LAMATIC_API_KEYbeforeLAMATIC_API_URL). Not functionally required, but aligning avoids CI/lint noise.kits/assistant/ai-career-copilot/README.md (1)
82-92: Add language identifiers to fenced code blocks (MD040).These fences should declare languages (
text,bash, etc.) to satisfy markdownlint and improve rendering consistency.Also applies to: 109-111, 121-123, 127-129
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: fb395155-da54-4434-9636-cb8d36f4e7fa
📒 Files selected for processing (8)
kits/assistant/ai-career-copilot/.env.examplekits/assistant/ai-career-copilot/.gitignorekits/assistant/ai-career-copilot/README.mdkits/assistant/ai-career-copilot/actions/orchestrate.tskits/assistant/ai-career-copilot/app/layout.tsxkits/assistant/ai-career-copilot/config.jsonkits/assistant/ai-career-copilot/package.jsonkits/assistant/ai-career-copilot/tsconfig.json
✅ Files skipped from review due to trivial changes (5)
- kits/assistant/ai-career-copilot/tsconfig.json
- kits/assistant/ai-career-copilot/.gitignore
- kits/assistant/ai-career-copilot/config.json
- kits/assistant/ai-career-copilot/package.json
- kits/assistant/ai-career-copilot/app/layout.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- kits/assistant/ai-career-copilot/actions/orchestrate.ts
| AGENTIC_GENERATE_CONTENT=your-flow-id | ||
| LAMATIC_API_URL=https://your-project.lamatic.dev/graphql | ||
| LAMATIC_PROJECT_ID=your-project-id | ||
| LAMATIC_API_KEY=your-api- |
There was a problem hiding this comment.
Use a complete placeholder for LAMATIC_API_KEY.
LAMATIC_API_KEY=your-api- looks truncated and can confuse setup; use a clear placeholder like your-api-key (or YOUR_API_KEY) for consistency with the README.
As per coding guidelines: "Never commit real API keys, secrets, or credentials; use .env.example with placeholders only".
🧰 Tools
🪛 dotenv-linter (4.0.0)
[warning] 4-4: [UnorderedKey] The LAMATIC_API_KEY key should go before the LAMATIC_API_URL key
(UnorderedKey)
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5b1508b1-baef-4875-a28f-a9d2f0a82fbc
📒 Files selected for processing (1)
kits/assistant/ai-career-copilot/README.md
| ``` | ||
| ai-career-copilot/ | ||
| ├── app/ # Next.js pages | ||
| ├── components/ # UI components | ||
| ├── actions/ # Server actions | ||
| ├── lib/ # Lamatic API client | ||
| ├── flows/ # Exported Lamatic flow | ||
| ├── .env.example # Environment template | ||
| ├── config.json # Kit configuration | ||
| └── README.md | ||
| ``` |
There was a problem hiding this comment.
Add language identifiers to fenced code blocks (MD040).
Line 91, Line 118, Line 130, and Line 136 use unlabeled fenced blocks, which triggers markdownlint warnings.
Proposed README fix
-```
+```text
ai-career-copilot/
├── app/ # Next.js pages
├── components/ # UI components
├── actions/ # Server actions
├── lib/ # Lamatic API client
├── flows/ # Exported Lamatic flow
├── .env.example # Environment template
├── config.json # Kit configuration
└── README.md- +text
kits/assistant/ai-career-copilot
-```
+```text
I know JavaScript, React, and basic Node.js
- +text
Web Development
Also applies to: 118-120, 130-132, 136-138
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)
[warning] 91-91: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🚀 AI Career Copilot
What This Kit Does
AI-powered career assistant that analyzes resumes and provides:
Providers & Prerequisites
How to Run Locally
Navigate to the project:
cd kits/assistant/ai-career-copilot
Install dependencies:
npm install
Set up environment variables:
cp .env.example .env
Add your Lamatic credentials in
.envRun the project:
npm run dev
Live Preview
https://your-vercel-link.vercel.app/
Lamatic Flow
Flow ID:
66c98d92-70da-4eec-82b0-af4f01be9cd5