-
Notifications
You must be signed in to change notification settings - Fork 119
feat: Add mock-ai interviewer Agentkit #101
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
base: old-main
Are you sure you want to change the base?
Changes from all commits
5b4a53e
63e4993
0241491
a92235c
7aca27f
ef6622f
be6edc8
cdb13df
4ef625e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # AGENTIC_GENERATE_CONTENT = "AGENTIC_GENERATE_CONTENT Flow ID" | ||
| LAMATIC_API_URL = "LAMATIC_API_URL" | ||
| LAMATIC_PROJECT_ID = "LAMATIC_PROJECT_ID" | ||
| LAMATIC_API_KEY = "LAMATIC_API_KEY" | ||
| AGENTIC_FEEDBACK_FLOW_ID="Feedback agent Flow ID" | ||
| AGENTIC_QUESTION_FLOW_ID="Question agent Flow ID" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
|
||
| # dependencies | ||
| /node_modules | ||
|
|
||
| # next.js | ||
| /.next/ | ||
| /out/ | ||
|
|
||
| # production | ||
| /build | ||
|
|
||
| # debug | ||
| npm-debug.log* | ||
| yarn-debug.log* | ||
| yarn-error.log* | ||
| .pnpm-debug.log* | ||
|
|
||
| # env files | ||
| .env | ||
| .env.local | ||
|
|
||
| # vercel | ||
| .vercel | ||
|
|
||
| # typescript | ||
| *.tsbuildinfo | ||
| next-env.d.ts |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| ## Title: feat(mockai): transform generic app into Mockai Interview prep platform | ||
|
|
||
| ### 📖 Description | ||
| This PR significantly transforms the initial `agentic/mockai` app into **Mockai**, a powerful 3-step AI mock interview application tailored for an engaging user assessment journey. It introduces a modern, dynamic UI, reliable real-time microphone dictation, intelligent audio visualizations, and robust Vercel deployment configurations. | ||
|
|
||
| ### 🧪 How to Test | ||
| 1. Pull the branch and run `npm install`. | ||
| 2. Ensure your `.env` contains the keys `AGENTIC_QUESTION_FLOW_ID`, `AGENTIC_FEEDBACK_FLOW_ID` mapping to your Lamatic workflows. | ||
| 3. Start the server with `npm run dev` and navigate to `http://localhost:3200` (ensure you use `localhost` instead of a network IP, otherwise browsers block mic permissions). | ||
| 4. Run through the interview, utilizing the real-time "Record Voice" functionality, and verify the feedback metrics at the end. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| # Agent Kit Generation by Lamatic.ai | ||
| <p align="center"> | ||
| <img src="https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExYnl0MGoxN203ZDczams4NzN6MGkxaXRham95N2NrejluZnU1N2NhMCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/TcZYytytvZBLODohJb/giphy.gif"/> | ||
| </p> | ||
|
|
||
| <p align="center"> | ||
| <a href="https://agent-kit-generation.vercel.app" target="_blank"> | ||
| <img src="https://img.shields.io/badge/Live%20Demo-black?style=for-the-badge" alt="Live Demo" /> | ||
| </a> | ||
| </p> | ||
|
|
||
|
|
||
| **Agent Kit Generation** is an AI-powered content generation system built with [Lamatic.ai](https://lamatic.ai). It uses intelligent workflows to generate text, images, and JSON content through a modern Next.js interface with markdown rendering support. | ||
|
|
||
| [](https://vercel.com/new/clone?repository-url=https://github.com/Lamatic/AgentKit&root-directory=kits/agentic/generation&env=AGENTIC_GENERATE_CONTENT,LAMATIC_API_URL,LAMATIC_PROJECT_ID,LAMATIC_API_KEY&envDescription=Your%20Lamatic%20Generation%20keys%20are%20required.&envLink=https://lamatic.ai/templates/agentkits/agentic/agent-kit-generation) | ||
|
amanintech marked this conversation as resolved.
|
||
|
|
||
| --- | ||
|
|
||
| ## Lamatic Setup (Pre and Post) | ||
|
|
||
| Before running this project, you must build and deploy the flow in Lamatic, then wire its config into this codebase. | ||
|
|
||
| Pre: Build in Lamatic | ||
| 1. Sign in or sign up at https://lamatic.ai | ||
| 2. Create a project (if you don’t have one yet) | ||
| 3. Click “+ New Flow” and select "Templates" | ||
| 4. Select the 'Generation' agent kit | ||
| 5. Configure providers/tools/inputs as prompted | ||
| 6. Deploy the kit in Lamatic and obtain your .env keys | ||
| 7. Copy the keys from your studio | ||
|
|
||
| Post: Wire into this repo | ||
| 1. Create a .env file and set the keys | ||
| 2. Install and run locally: | ||
| - npm install | ||
| - npm run dev | ||
| 3. Deploy (Vercel recommended): | ||
| - Import your repo, set the project's Root Directory (if applicable) | ||
| - Add env vars in Vercel (same as your .env) | ||
| - Deploy and test your live URL | ||
|
|
||
| Notes | ||
| - Coming soon: single-click export and "Connect Git" in Lamatic to push config directly to your repo. | ||
|
|
||
| --- | ||
|
|
||
| ## 🔑 Setup | ||
| ## Required Keys and Config | ||
|
|
||
| You’ll need these things to run this project locally: | ||
|
|
||
| 1. **.env Keys** → get it from your [Lamatic account](https://lamatic.ai) post kit deployment. | ||
|
|
||
|
|
||
| | Item | Purpose | Where to Get It | | ||
| | ----------------- | -------------------------------------------- | ----------------------------------------------- | | ||
| | .env Key | Authentication for Lamatic AI APIs and Orchestration | [lamatic.ai](https://lamatic.ai) | | ||
|
|
||
| ### 1. Environment Variables | ||
|
|
||
| Create `.env.local` with: | ||
|
|
||
| ```bash | ||
| # Lamatic | ||
| AGENTIC_GENERATE_CONTENT = "AGENTIC_GENERATE_CONTENT Flow ID" | ||
| LAMATIC_API_URL = "LAMATIC_API_URL" | ||
| LAMATIC_PROJECT_ID = "LAMATIC_PROJECT_ID" | ||
| LAMATIC_API_KEY = "LAMATIC_API_KEY" | ||
| ``` | ||
|
amanintech marked this conversation as resolved.
|
||
|
|
||
| ### 2. Install & Run | ||
|
|
||
| ```bash | ||
| npm install | ||
| npm run dev | ||
| # Open http://localhost:3000 | ||
| ``` | ||
| --- | ||
|
|
||
| ## 📂 Repo Structure | ||
|
|
||
| ``` | ||
| /actions | ||
| └── orchestrate.ts # Lamatic workflow orchestration | ||
| /app | ||
| └── page.tsx # Main generation form UI | ||
| /components | ||
| ├── header.tsx # Header component with navigation | ||
| └── ui # shadcn/ui components | ||
| /lib | ||
| └── lamatic-client.ts # Lamatic SDK client | ||
| /public | ||
| └── lamatic-logo.png # Lamatic branding | ||
| /flows | ||
| └── ... # Lamatic Flows | ||
| /package.json # Dependencies & scripts | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## 🤝 Contributing | ||
|
|
||
| We welcome contributions! Open an issue or PR in this repo. | ||
|
|
||
| --- | ||
|
|
||
| ## 📜 License | ||
|
|
||
| MIT License – see [LICENSE](./LICENSE). | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,157 @@ | ||||||||||||||
| "use server" | ||||||||||||||
|
|
||||||||||||||
| import { lamaticClient } from "@/lib/lamatic-client" | ||||||||||||||
| import { config } from "../orchestrate.js" | ||||||||||||||
| import { z } from "zod" | ||||||||||||||
|
|
||||||||||||||
| export async function generateQuestions( | ||||||||||||||
| jobTitle: string, | ||||||||||||||
| yearsOfExp: number, | ||||||||||||||
| jobDesc: string, | ||||||||||||||
| ): Promise<{ | ||||||||||||||
| success: boolean | ||||||||||||||
| questions?: string[] | ||||||||||||||
| error?: string | ||||||||||||||
| }> { | ||||||||||||||
| try { | ||||||||||||||
| // console.log("[v0] Generating questions - Flow started") | ||||||||||||||
|
|
||||||||||||||
| const flow = config.flows.question | ||||||||||||||
|
|
||||||||||||||
| if (!flow.workflowId) { | ||||||||||||||
| throw new Error("Workflow ID not found in config for question flow.") | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| const inputs = { | ||||||||||||||
| jobTitle, | ||||||||||||||
| yearsOfExp: parseInt(yearsOfExp.toString()), | ||||||||||||||
| jobDesc | ||||||||||||||
| } | ||||||||||||||
|
sreecharan1306 marked this conversation as resolved.
|
||||||||||||||
|
|
||||||||||||||
| const inputSchema = z.object({ | ||||||||||||||
| jobTitle: z.string().min(1, "Job title is required"), | ||||||||||||||
| yearsOfExp: z.number().min(0, "Years of experience must be a valid number"), | ||||||||||||||
| jobDesc: z.string().optional() | ||||||||||||||
| }) | ||||||||||||||
|
|
||||||||||||||
| inputSchema.parse(inputs) | ||||||||||||||
|
|
||||||||||||||
| // console.log(`[v0] Executing flow: ${flow.workflowId}`) | ||||||||||||||
|
|
||||||||||||||
| const resData = await lamaticClient.executeFlow(flow.workflowId, inputs) | ||||||||||||||
| // console.log("[v0] Flow execution completed") | ||||||||||||||
|
|
||||||||||||||
| const responseSchema = z.object({ | ||||||||||||||
| result: z.object({ | ||||||||||||||
| data: z.array(z.string()).min(1, "No questions found in response") | ||||||||||||||
| }) | ||||||||||||||
| }) | ||||||||||||||
|
|
||||||||||||||
| const validatedResponse = responseSchema.parse(resData) | ||||||||||||||
| const questions = validatedResponse.result.data | ||||||||||||||
|
|
||||||||||||||
| return { | ||||||||||||||
| success: true, | ||||||||||||||
| questions, | ||||||||||||||
| } | ||||||||||||||
| } catch (error) { | ||||||||||||||
| console.error("[v0] Generation error:", error) | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sanitize error logs to prevent intelligence leakage. This error log writes the full error object to the server, which may contain sensitive interview content (job descriptions, candidate answers, API tokens in stack traces, or full Lamatic payloads). You're already sanitizing the error message before sending it to the client—apply the same discipline to server-side logging. Log only the sanitized message, flow name, and error type. 🔒 Proposed sanitized logging- console.error("[v0] Generation error:", error)
+ console.error("[v0] Generation error:", {
+ flow: "question",
+ errorType: error instanceof z.ZodError ? "validation" : error instanceof Error ? "execution" : "unknown",
+ message: error instanceof Error ? error.message : "Unknown error"
+ })📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
| let errorMessage = "Unknown error occurred" | ||||||||||||||
| if (error instanceof z.ZodError) { | ||||||||||||||
| errorMessage = "Validation error: Invalid data format." | ||||||||||||||
| } else if (error instanceof Error) { | ||||||||||||||
| errorMessage = error.message | ||||||||||||||
| if (error.message.includes("fetch failed")) { | ||||||||||||||
| errorMessage = | ||||||||||||||
| "Network error: Unable to connect to the service. Please check your internet connection and try again." | ||||||||||||||
| } else if (error.message.includes("API key")) { | ||||||||||||||
| errorMessage = "Authentication error: Please check your API configuration." | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| return { | ||||||||||||||
| success: false, | ||||||||||||||
| error: errorMessage, | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| export async function evaluateAnswers( | ||||||||||||||
| candidateResponses: { question: string, answers: string }[] | ||||||||||||||
| ): Promise<{ | ||||||||||||||
| success: boolean | ||||||||||||||
| feedback?: { positives: string[], negatives: string[], rating: number } | ||||||||||||||
| error?: string | ||||||||||||||
| }> { | ||||||||||||||
| try { | ||||||||||||||
| // console.log("[v0] Evaluating answers - Flow started", { count: candidateResponses.length }) | ||||||||||||||
|
|
||||||||||||||
| const flow = config.flows.feedback | ||||||||||||||
|
|
||||||||||||||
| if (!flow.workflowId) { | ||||||||||||||
| throw new Error("Workflow ID not found in config for feedback flow.") | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // We can just format the string or array to be safe. We pass what's expected. | ||||||||||||||
| const inputs = { | ||||||||||||||
| candidateResponses | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| const inputSchema = z.object({ | ||||||||||||||
| candidateResponses: z.array( | ||||||||||||||
| z.object({ | ||||||||||||||
| question: z.string(), | ||||||||||||||
| answers: z.string() | ||||||||||||||
| }) | ||||||||||||||
| ).min(1, "At least one candidate response is required") | ||||||||||||||
| }) | ||||||||||||||
|
|
||||||||||||||
| inputSchema.parse(inputs) | ||||||||||||||
|
|
||||||||||||||
| // console.log(`[v0] Executing flow: ${flow.workflowId}`) | ||||||||||||||
|
|
||||||||||||||
| const resData = await lamaticClient.executeFlow(flow.workflowId, inputs) | ||||||||||||||
| console.log("[v0] Flow execution completed") | ||||||||||||||
|
|
||||||||||||||
| const responseSchema = z.object({ | ||||||||||||||
| result: z.object({ | ||||||||||||||
| positives: z.array(z.string()).optional().default([]), | ||||||||||||||
| negatives: z.array(z.string()).optional().default([]), | ||||||||||||||
| rating: z.number() | ||||||||||||||
| }) | ||||||||||||||
| }) | ||||||||||||||
|
|
||||||||||||||
| const validatedResponse = responseSchema.parse(resData) | ||||||||||||||
| const result = validatedResponse.result | ||||||||||||||
|
|
||||||||||||||
| return { | ||||||||||||||
| success: true, | ||||||||||||||
| feedback: { | ||||||||||||||
| positives: result.positives, | ||||||||||||||
| negatives: result.negatives, | ||||||||||||||
| rating: result.rating | ||||||||||||||
| }, | ||||||||||||||
| } | ||||||||||||||
| } catch (error) { | ||||||||||||||
| console.error("[v0] Evaluation error:", error) | ||||||||||||||
|
|
||||||||||||||
| let errorMessage = "Unknown error occurred" | ||||||||||||||
| if (error instanceof z.ZodError) { | ||||||||||||||
| errorMessage = "Validation error: Invalid data format." | ||||||||||||||
| } else if (error instanceof Error) { | ||||||||||||||
| errorMessage = error.message | ||||||||||||||
| if (error.message.includes("fetch failed")) { | ||||||||||||||
| errorMessage = | ||||||||||||||
| "Network error: Unable to connect to the service. Please check your internet connection and try again." | ||||||||||||||
| } else if (error.message.includes("API key")) { | ||||||||||||||
| errorMessage = "Authentication error: Please check your API configuration." | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| return { | ||||||||||||||
| success: false, | ||||||||||||||
| error: errorMessage, | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
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.
🧹 Nitpick | 🔵 Trivial | 💤 Low value
Documentation formatting requires adjustment for field manual standards.
Your markdown structure violates standard heading hierarchy and spacing conventions. The first line should be a level-1 heading (single
#), and all headings need blank lines above and below for proper document parsing and readability in mission briefs.📝 Proposed formatting corrections
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 1-1: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
[warning] 3-3: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 6-6: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
🤖 Prompt for AI Agents