Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions kits/agentic/mockai/.env.example
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"
28 changes: 28 additions & 0 deletions kits/agentic/mockai/.gitignore
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
10 changes: 10 additions & 0 deletions kits/agentic/mockai/PR_DESCRIPTION.md
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.
Comment on lines +1 to +10
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.

🧹 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
-## Title: feat(mockai): transform generic app into Mockai Interview prep platform
+# feat(mockai): transform generic app into Mockai Interview prep platform

-### 📖 Description
+
+## 📖 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
+
+## 🧪 How to Test
+
 1. Pull the branch and run `npm install`.
🧰 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
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/agentic/mockai/PR_DESCRIPTION.md` around lines 1 - 10, The
PR_DESCRIPTION.md headings violate markdown conventions: change the first line
to a level-1 heading (replace "## Title: feat(mockai): ..." with "#
feat(mockai): transform generic app into Mockai Interview prep platform") and
ensure there is a blank line before and after each heading (for "📖 Description"
and "🧪 How to Test") so the renderer parses them correctly; keep the existing
heading text but adjust them to use consistent heading levels (e.g., "## 📖
Description" and "## 🧪 How to Test" or lower as appropriate) and add a blank
line between paragraphs and each heading to meet field manual standards.

109 changes: 109 additions & 0 deletions kits/agentic/mockai/README.md
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.

[![Deploy with Vercel](https://vercel.com/button)](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)
Comment thread
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"
```
Comment thread
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).
157 changes: 157 additions & 0 deletions kits/agentic/mockai/actions/orchestrate.ts
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
}
Comment thread
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)
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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

‼️ 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.

Suggested change
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"
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/agentic/mockai/actions/orchestrate.ts` at line 58, The current
console.error call in orchestrate.ts logs the full error object
(console.error("[v0] Generation error:", error)) which may contain sensitive
data; replace it with a sanitized server-side log that prints only the sanitized
error message, the flow name/ID, and the error type/name. Use the same sanitizer
function you call when sending errors to the client (e.g., sanitizeErrorMessage
or the existing sanitization utility used elsewhere in this file) to produce the
message, then log exactly: flow identifier, error.name (or error.type), and the
sanitized message instead of the full error object.


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,
}
}
}
Loading
Loading