Skip to content

feat: Add outreach-personalizer kit#191

Open
dhruvil-codes wants to merge 4 commits into
Lamatic:mainfrom
dhruvil-codes:feat/outreach-personalizer-kit
Open

feat: Add outreach-personalizer kit#191
dhruvil-codes wants to merge 4 commits into
Lamatic:mainfrom
dhruvil-codes:feat/outreach-personalizer-kit

Conversation

@dhruvil-codes

@dhruvil-codes dhruvil-codes commented Jul 7, 2026

Copy link
Copy Markdown

Adds a new AgentKit kit that generates personalized cold outreach pitches from a company website URL, founder LinkedIn URL, and candidate background context.

  • Firecrawl-based company research node
  • LLM pitch generation with custom constitution (tone, identity, data-handling rules)
  • Next.js reference app (apps/) demonstrating end-to-end usage via the Lamatic SDK

Verified via end-to-end test through the live reference app UI with real company/LinkedIn/candidate inputs; output confirmed clean with no console/terminal errors.

PR Checklist

1. Select Contribution Type

  • Kit (kits/<category>/<kit-name>/)
  • Bundle (bundles/<bundle-name>/)
  • Template (templates/<template-name>/)

2. General Requirements

  • PR is for one project only (no unrelated changes)
  • No secrets, API keys, or real credentials are committed
  • Folder name uses kebab-case and matches the flow ID
  • All changes are documented in README.md (purpose, setup, usage)

3. File Structure (Check what applies)

  • config.json present with valid metadata (name, description, tags, steps, author, env keys)
  • All flows in flows/<flow-name>/ (where applicable) include:
    • config.json (Lamatic flow export)
    • inputs.json
    • meta.json
    • README.md
  • .env.example with placeholder values only (kits only)
  • No hand‑edited flow config.json node graphs (changes via Lamatic Studio export)

4. Validation

  • npm install && npm run dev works locally (kits: UI runs; bundles/templates: flows are valid)
  • PR title is clear (e.g., [kit] Add <name> for <use case>)
  • GitHub Actions workflows pass (all checks are green)
  • All CodeRabbit or other PR review comments are addressed and resolved
  • No unrelated files or projects are modified
  • Added kits/outreach-personalizer/.gitignore (ignores .lamatic/, node_modules/, .next/, and local env files).

  • Added kits/outreach-personalizer/README.md (what the kit/app does, required env vars, and architecture: Next.js route → Lamatic flow via LamaticClient, with friendly handling for non-JSON/HTML gateway errors).

  • Added kits/outreach-personalizer/agent.md (agent objective and workflow: Firecrawl company/founder crawl → extract 3–5 “noticed things” → propose a buildable value-add asset → draft final personalized cold email; includes tone/format rules, banned phrases, and no em-dashes).

  • Added kits/outreach-personalizer/.env.example (example FIRECRAWL_API_KEY and GROQ_API_KEY).

  • Added kits/outreach-personalizer/constitutions/default.md (Default Constitution: identity/tone rules, jailbreak/prompt-injection refusal, and strict PII/data-handling + exact 80–120 word plain-text email + exact closing sentence).

  • Added kits/outreach-personalizer/lamatic.config.ts (kit metadata; single step average-teenager with envKey: "FLOW_ID").

  • Added kits/outreach-personalizer/flows/average-teenager.ts (full flow graph + references to prompts/constitutions/model configs).

  • Added model-config files:

    • kits/outreach-personalizer/model-configs/average-teenager_llmnode-276_generative-model-name.ts
    • kits/outreach-personalizer/model-configs/average-teenager_llmnode-696_generative-model-name.ts
    • kits/outreach-personalizer/model-configs/average-teenager_llmnode-996_generative-model-name.ts
  • Added prompt files:

    • kits/outreach-personalizer/prompts/average-teenager_llmnode-276_system_0.md
    • kits/outreach-personalizer/prompts/average-teenager_llmnode-276_user_1.md
    • kits/outreach-personalizer/prompts/average-teenager_llmnode-996_system_0.md
    • kits/outreach-personalizer/prompts/average-teenager_llmnode-996_user_1.md
    • kits/outreach-personalizer/prompts/average-teenager_llmnode-696_system_0.md
    • kits/outreach-personalizer/prompts/average-teenager_llmnode-696_user_1.md
  • Added Next.js reference app under kits/outreach-personalizer/apps/:

    • kits/outreach-personalizer/apps/.env.example
    • kits/outreach-personalizer/apps/.gitignore
    • kits/outreach-personalizer/apps/AGENTS.md
    • kits/outreach-personalizer/apps/CLAUDE.md
    • kits/outreach-personalizer/apps/README.md
    • kits/outreach-personalizer/apps/actions/orchestrate.ts (server action: PitchInput + generatePersonalizedPitch; trims inputs, derives FLOW_ID from lamatic.config, calls getLamaticClient().executeFlow(...) with a 5-minute timeout, returns {success, data|error}).
    • kits/outreach-personalizer/apps/lib/lamatic-client.ts (lazy singleton Lamatic client with runtime env validation).
    • kits/outreach-personalizer/apps/app/globals.css
    • kits/outreach-personalizer/apps/app/layout.tsx
    • kits/outreach-personalizer/apps/app/page.tsx (UI form + step/progress state; renders generated pitch and optional intermediate node output; copy-to-clipboard).
    • kits/outreach-personalizer/apps/app/favicon.ico
    • kits/outreach-personalizer/apps/app/eslint.config.mjs
    • kits/outreach-personalizer/apps/next.config.ts (sets turbopack.root to parent directory).
    • kits/outreach-personalizer/apps/package.json
    • kits/outreach-personalizer/apps/package-lock.json
    • kits/outreach-personalizer/apps/postcss.config.mjs
    • kits/outreach-personalizer/apps/tsconfig.json
    • kits/outreach-personalizer/apps/public/file.svg, globe.svg, next.svg, vercel.svg, window.svg

Flow behavior (from kits/outreach-personalizer/flows/average-teenager.ts)

  • Node types
    • triggerNode (triggerNode_1 / graphqlNode): realtime API trigger that accepts company_url, founder_linkedin_url, candidate_context and advances via to-response.
    • dynamicNode:
      • firecrawlNode_692: syncBatchScrape over company_url + founder_linkedin_url using provided Firecrawl credentials.
      • LLMNode_276: extracts 3–5 “noticed things” with specificity_score (prompt average-teenager_llmnode-276_*).
      • LLMNode_996: proposes one buildable value-add asset under 2 hours (prompt average-teenager_llmnode-996_*).
      • LLMNode_696: drafts the final cold email/pitch in 80–120 words with the required structure/constraints (prompt average-teenager_llmnode-696_*).
    • responseNode (responseNode_triggerNode_1): returns the final flow output as JSON to the caller.
  • Edges / wiring
    • triggerNode_1 → firecrawlNode_692 (default edge)
    • firecrawlNode_692 → LLMNode_276 → LLMNode_996 → LLMNode_696 (default edges in sequence)
    • LLMNode_696 → responseNode_triggerNode_1 (default edge)
    • triggerNode_1 → responseNode_triggerNode_1 (a responseEdge using sourceHandle: "to-response" / targetHandle: "from-trigger"), ensuring the API trigger’s response is populated from the flow result.

Adds a new AgentKit kit that generates personalized cold outreach pitches from a company website URL, founder LinkedIn URL, and candidate background context.

- Firecrawl-based company research node
- LLM pitch generation with custom constitution (tone, identity, data-handling rules)
- Next.js reference app (apps/) demonstrating end-to-end usage via the Lamatic SDK

Verified via end-to-end test through the live reference app UI with real company/LinkedIn/candidate inputs; output confirmed clean with no console/terminal errors.
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

This PR adds the outreach-personalizer kit: a Lamatic flow and prompt stack, a Next.js app that executes it through a server action, and the supporting app shell, configuration, and documentation.

Changes

Outreach Personalizer kit

Layer / File(s) Summary
Flow definition and prompt chain
kits/outreach-personalizer/flows/average-teenager.ts, kits/outreach-personalizer/prompts/*, kits/outreach-personalizer/model-configs/*, kits/outreach-personalizer/constitutions/default.md, kits/outreach-personalizer/lamatic.config.ts, kits/outreach-personalizer/agent.md, kits/outreach-personalizer/.gitignore, kits/outreach-personalizer/.env.example, kits/outreach-personalizer/README.md
Defines the flow graph, prompt templates, model wiring, constitution rules, kit metadata, and kit-level documentation and ignore/env scaffolding.
Lamatic client and server action
kits/outreach-personalizer/apps/lib/lamatic-client.ts, kits/outreach-personalizer/apps/actions/orchestrate.ts, kits/outreach-personalizer/apps/.env.example, kits/outreach-personalizer/apps/.gitignore, kits/outreach-personalizer/apps/eslint.config.mjs, kits/outreach-personalizer/apps/next.config.ts, kits/outreach-personalizer/apps/tsconfig.json, kits/outreach-personalizer/apps/package.json, kits/outreach-personalizer/apps/postcss.config.mjs, kits/outreach-personalizer/apps/AGENTS.md, kits/outreach-personalizer/apps/CLAUDE.md, kits/outreach-personalizer/apps/README.md
Validates Lamatic environment variables, executes the flow with timeout/error normalization, and adds app setup, linting, type, and usage documentation.
Next.js shell and page
kits/outreach-personalizer/apps/app/layout.tsx, kits/outreach-personalizer/apps/app/globals.css, kits/outreach-personalizer/apps/app/page.tsx
Adds the root layout, global Tailwind/theme styling, and the client page that submits inputs, tracks progress, renders generated outreach, and supports copy-to-clipboard.

Suggested reviewers: amanintech, d-pamneja

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly names the new outreach-personalizer kit and matches the main change.
Description check ✅ Passed The description covers the kit purpose, key components, and validation, and includes the required checklist template.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

:robot_face: AgentKit Structural Validation

New Contributions Detected

  • Kit: kits/outreach-personalizer

Check Results

Check Status
No edits to existing kits ✅ Pass
Required root files present ✅ Pass
Flow .ts files present ✅ Pass
lamatic.config.ts valid ✅ Pass
No changes outside kits/ ✅ Pass

🎉 All checks passed! This contribution follows the AgentKit structure.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 11

🤖 Prompt for all review comments with 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.

Inline comments:
In `@kits/outreach-personalizer/agent.md`:
- Around line 21-24: The agent doc is overstating what the flow actually crawls:
`firecrawlNode_692` in the outreach-personalizer flow only receives
`company_url`, not a founder LinkedIn URL or other dynamically constructed URLs.
Update the description in the agent doc to match the real wiring, or extend the
flow so `firecrawlNode_692` also accepts and crawls the founder URL before
keeping the broader wording.

In `@kits/outreach-personalizer/apps/actions/orchestrate.ts`:
- Line 17: Remove the scaffold debug logging that leaks sensitive data from
orchestrate; the `console.log` in `orchestrate` should not print `input`, and
the raw SDK response dump should also be removed or replaced with a minimal,
non-PII status message. Keep only safe metadata in logs by updating the
`orchestrate` flow’s logging around the `[v0]` statements and any response
handling so user-submitted `candidate_context` and raw payload contents are
never written to server logs.
- Line 30: Wrap the lamaticClient.executeFlow call in orchestrate with a local
timeout so the server action cannot hang indefinitely if the flow stalls. Use a
timeout helper around executeFlow in orchestrate.ts, and on timeout return or
throw a clear error that the flow timed out; keep the existing trimmedInput and
flowId usage unchanged.

In `@kits/outreach-personalizer/apps/app/page.tsx`:
- Around line 178-238: The form fields in this section are missing programmatic
label associations because the labels are separate from the inputs in the page
component. Update the Company Website URL, Founder LinkedIn URL, and Candidate
Background & Context fields in app/page.tsx so each <label> uses a matching
htmlFor and each input/textarea has the corresponding id, or wrap the control
inside the label. Use the existing field blocks and related state handlers
(companyUrl, founderLinkedinUrl, candidateContext) to keep the structure aligned
while making the labels accessible.

In `@kits/outreach-personalizer/apps/lib/lamatic-client.ts`:
- Around line 4-8: The FLOW_ID validation in lamatic-client.ts is in the wrong
module and duplicates the real guard already performed in orchestrate.ts. Remove
the process.env.FLOW_ID check from the client initialization path and keep
lamatic-client focused on client setup only; leave FLOW_ID validation in
orchestrate.ts where the flow invocation actually happens. Use the lamatic
client setup code and the orchestrate.ts flow entrypoint as the symbols to
locate the affected logic.
- Around line 10-20: The module-scope environment guard in lamaticClient is
throwing during import, which can break page build/static generation before
runtime. Move the validation out of the top-level of lamatic-client.ts and into
a lazy initializer or the first place Lamatic is actually used (for example
inside orchestrate or a createLamaticClient helper), so page.tsx can import the
module without immediately requiring LAMATIC_API_URL, LAMATIC_PROJECT_ID, and
LAMATIC_API_KEY. Keep the existing Lamatic constructor setup, but only run the
env check when the client is actually needed.

In `@kits/outreach-personalizer/apps/README.md`:
- Around line 1-36: The README is still the default create-next-app template and
does not document the outreach-personalizer kit workflow. Replace the generic
content with kit-specific setup instructions that explain how to configure the
Lamatic environment variables, run the reference app end to end, and any
required prerequisites. Update the README content in place so it reflects the
shipped kit rather than the starter Next.js app, and make sure the guidance is
tailored to this app’s setup and usage.

In `@kits/outreach-personalizer/constitutions/default.md`:
- Around line 3-31: The Markdown in the default constitution is missing blank
lines around the `##` headings, causing MD022 failures. Update the `##
Identity`, `## Safety`, `## Data Handling`, `## Tone & Style Guidelines`, `##
Banned Words & Symbols`, and `## Structural Rules` sections so each heading has
a blank line before and after it, while keeping the existing content and
structure intact.

In `@kits/outreach-personalizer/flows/average-teenager.ts`:
- Around line 20-31: The Firecrawl input mapping is dropping
founder_linkedin_url, so the founder-provided URL never reaches downstream
research or prompt steps. Update firecrawlNode_692 in average-teenager.ts to
pass through founder_linkedin_url alongside company_url, and make sure the input
schema/field wiring matches the downstream contract used by orchestrate so both
sources are preserved end-to-end.

In `@kits/outreach-personalizer/prompts/average-teenager_llmnode-276_system_0.md`:
- Around line 1-5: The extraction prompt is vulnerable to prompt injection
because it treats scraped page text as instruction-bearing content. Update the
prompt around the main extraction flow to explicitly tell the model to ignore
any commands, directives, or role instructions found in the crawl output and to
treat the text only as untrusted data. Keep the task focused on extracting 3-5
specific noticed things with source and specificity_score, and reinforce this
guardrail in the prompt text used by the LLM node.

In `@kits/outreach-personalizer/README.md`:
- Around line 22-23: The README setup and architecture instructions reference
the wrong app structure and execution flow, so update them to match the actual
kit implementation. Replace mentions of apps/web with the real apps directory,
and describe the invocation path through the generatePersonalizedPitch Server
Action in apps/actions/orchestrate.ts using the lamaticClient wrapper in
apps/lib/lamatic-client.ts instead of an API route or lib/lamatic.ts. Keep the
environment/setup steps aligned with the real directory layout so readers are
not sent to nonexistent paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: d963c140-3478-42ec-8f6b-6c37abf396c4

📥 Commits

Reviewing files that changed from the base of the PR and between dafde4c and 0c783f0.

⛔ Files ignored due to path filters (7)
  • kits/outreach-personalizer/apps/app/favicon.ico is excluded by !**/*.ico
  • kits/outreach-personalizer/apps/package-lock.json is excluded by !**/package-lock.json
  • kits/outreach-personalizer/apps/public/file.svg is excluded by !**/*.svg
  • kits/outreach-personalizer/apps/public/globe.svg is excluded by !**/*.svg
  • kits/outreach-personalizer/apps/public/next.svg is excluded by !**/*.svg
  • kits/outreach-personalizer/apps/public/vercel.svg is excluded by !**/*.svg
  • kits/outreach-personalizer/apps/public/window.svg is excluded by !**/*.svg
📒 Files selected for processing (30)
  • kits/outreach-personalizer/.gitignore
  • kits/outreach-personalizer/README.md
  • kits/outreach-personalizer/agent.md
  • kits/outreach-personalizer/apps/.env.example
  • kits/outreach-personalizer/apps/.gitignore
  • kits/outreach-personalizer/apps/AGENTS.md
  • kits/outreach-personalizer/apps/CLAUDE.md
  • kits/outreach-personalizer/apps/README.md
  • kits/outreach-personalizer/apps/actions/orchestrate.ts
  • kits/outreach-personalizer/apps/app/globals.css
  • kits/outreach-personalizer/apps/app/layout.tsx
  • kits/outreach-personalizer/apps/app/page.tsx
  • kits/outreach-personalizer/apps/eslint.config.mjs
  • kits/outreach-personalizer/apps/lib/lamatic-client.ts
  • kits/outreach-personalizer/apps/next.config.ts
  • kits/outreach-personalizer/apps/package.json
  • kits/outreach-personalizer/apps/postcss.config.mjs
  • kits/outreach-personalizer/apps/tsconfig.json
  • kits/outreach-personalizer/constitutions/default.md
  • kits/outreach-personalizer/flows/average-teenager.ts
  • kits/outreach-personalizer/lamatic.config.ts
  • kits/outreach-personalizer/model-configs/average-teenager_llmnode-276_generative-model-name.ts
  • kits/outreach-personalizer/model-configs/average-teenager_llmnode-696_generative-model-name.ts
  • kits/outreach-personalizer/model-configs/average-teenager_llmnode-996_generative-model-name.ts
  • kits/outreach-personalizer/prompts/average-teenager_llmnode-276_system_0.md
  • kits/outreach-personalizer/prompts/average-teenager_llmnode-276_user_1.md
  • kits/outreach-personalizer/prompts/average-teenager_llmnode-696_system_0.md
  • kits/outreach-personalizer/prompts/average-teenager_llmnode-696_user_1.md
  • kits/outreach-personalizer/prompts/average-teenager_llmnode-996_system_0.md
  • kits/outreach-personalizer/prompts/average-teenager_llmnode-996_user_1.md

Comment thread kits/outreach-personalizer/agent.md Outdated
Comment thread kits/outreach-personalizer/apps/actions/orchestrate.ts Outdated
Comment thread kits/outreach-personalizer/apps/actions/orchestrate.ts Outdated
Comment thread kits/outreach-personalizer/apps/app/page.tsx
Comment thread kits/outreach-personalizer/apps/lib/lamatic-client.ts Outdated
Comment thread kits/outreach-personalizer/apps/README.md Outdated
Comment thread kits/outreach-personalizer/constitutions/default.md
Comment thread kits/outreach-personalizer/flows/average-teenager.ts
Comment thread kits/outreach-personalizer/prompts/average-teenager_llmnode-276_system_0.md Outdated
Comment on lines +22 to +23
### 1. Configure Environment Variables
Create a file named `.env.local` in the `apps/web/` directory (or copy it from the workspace root) and define the following variables:

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Setup guide describes an architecture that doesn't exist — self-destruct these instructions before someone follows them.

This document sends the reader to apps/web/ (lines 23, 45) and describes execution via apps/web/app/api/generate/route.ts calling a lib/lamatic.ts wrapper (lines 60, 73-74, 84) using a GraphQL POST diagram. The actual kit implementation uses:

  • Directory apps/ (not apps/web/)
  • A Server Action generatePersonalizedPitch in apps/actions/orchestrate.ts, not an API route handler
  • The client wrapper at apps/lib/lamatic-client.ts, not lib/lamatic.ts

Following these instructions verbatim (cd apps/web) will fail immediately, and the architecture section misrepresents how the flow is actually invoked.

📝 Proposed fix (representative excerpt)
-Create a file named `.env.local` in the `apps/web/` directory (or copy it from the workspace root) and define the following variables:
+Create a file named `.env.local` in the `apps/` directory (or copy it from the workspace root) and define the following variables:
-Change into the `apps/web` directory and install the required modules:
+Change into the `apps/` directory and install the required modules:
```diff
-The app initiates execution of the Lamatic flow using a Next.js Server Handler at `apps/web/app/api/generate/route.ts`. 
+The app initiates execution of the Lamatic flow using a Next.js Server Action (`generatePersonalizedPitch`) defined in `apps/actions/orchestrate.ts`, which calls the `lamaticClient` in `apps/lib/lamatic-client.ts`.

Also applies to: 45-46, 60-86

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 22-22: 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/outreach-personalizer/README.md` around lines 22 - 23, The README setup
and architecture instructions reference the wrong app structure and execution
flow, so update them to match the actual kit implementation. Replace mentions of
apps/web with the real apps directory, and describe the invocation path through
the generatePersonalizedPitch Server Action in apps/actions/orchestrate.ts using
the lamaticClient wrapper in apps/lib/lamatic-client.ts instead of an API route
or lib/lamatic.ts. Keep the environment/setup steps aligned with the real
directory layout so readers are not sent to nonexistent paths.

…ning

- Wire founder_linkedin_url into Firecrawl node
- Remove debug logs leaking candidate_context and raw SDK responses
- Add timeout wrapper around executeFlow
- Harden signal-extraction prompt against prompt injection
- Fix agent.md to match actual flow behavior
- Add htmlFor/id pairs to form labels for accessibility
- Add blank lines around headings in constitution (MD022)
- Remove redundant FLOW_ID check in lamatic-client.ts
- Rewrite apps/README.md with kit-specific setup docs
- Add kit-level .env.example for flow-level API keys

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with 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.

Inline comments:
In `@kits/outreach-personalizer/apps/actions/orchestrate.ts`:
- Line 33: The remaining debug-style logging in orchestrate() still leaks
implementation noise, so clean up the console.log calls tied to the flow
execution and error handling by removing the “[v0]” prefix and avoiding logging
sensitive inputs like company_url or raw error objects. Update the affected log
statements in orchestrate() to use neutral, non-debug messages and keep only the
minimal context needed for normal operation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0d813d41-4a46-4aa9-947f-41179902708d

📥 Commits

Reviewing files that changed from the base of the PR and between 0c783f0 and 60cb10f.

📒 Files selected for processing (10)
  • kits/outreach-personalizer/.env.example
  • kits/outreach-personalizer/agent.md
  • kits/outreach-personalizer/apps/README.md
  • kits/outreach-personalizer/apps/actions/orchestrate.ts
  • kits/outreach-personalizer/apps/app/page.tsx
  • kits/outreach-personalizer/apps/lib/lamatic-client.ts
  • kits/outreach-personalizer/constitutions/default.md
  • kits/outreach-personalizer/flows/average-teenager.ts
  • kits/outreach-personalizer/prompts/average-teenager_llmnode-276_system_0.md
  • kits/outreach-personalizer/prompts/average-teenager_llmnode-276_user_1.md
💤 Files with no reviewable changes (1)
  • kits/outreach-personalizer/apps/lib/lamatic-client.ts

error?: string;
}> {
try {
console.log("[v0] Executing Average Teenager flow for company URL:", input.company_url);

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.

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Debug tags survived the mission, but the sensitive payloads didn't.

candidate_context and the raw SDK dump are gone — good. The [v0] log prefixes and the company_url/error-object logging are cosmetic remnants; not a blocker, low priority.

Also applies to: 61-61

🤖 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/outreach-personalizer/apps/actions/orchestrate.ts` at line 33, The
remaining debug-style logging in orchestrate() still leaks implementation noise,
so clean up the console.log calls tied to the flow execution and error handling
by removing the “[v0]” prefix and avoiding logging sensitive inputs like
company_url or raw error objects. Update the affected log statements in
orchestrate() to use neutral, non-debug messages and keep only the minimal
context needed for normal operation.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
kits/outreach-personalizer/apps/actions/orchestrate.ts (1)

16-25: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

withTimeout leaks an unhandled rejection when the main promise resolves first.

When executeFlow resolves before the 5-minute timeout, Promise.race settles but the setTimeout timer is still pending. When it eventually fires, it rejects the timeoutPromise with no consumer — an unhandled promise rejection. On Node.js 15+ (where --unhandled-rejections=throw is the default), this can crash the server process.

Clear the timer once the race settles.

🔒 Proposed fix
 async function withTimeout<T>(promise: Promise<T>, timeoutMs: number, errorMessage: string): Promise<T> {
+  let timer: ReturnType<typeof setTimeout>;
   const timeoutPromise = new Promise<never>((_, reject) => {
-    const timer = setTimeout(() => reject(new Error(errorMessage)), timeoutMs);
+    timer = setTimeout(() => reject(new Error(errorMessage)), timeoutMs);
     // Ensure node can exit if the timer is the only thing keeping it alive
     if (timer.unref) {
       timer.unref();
     }
   });
-  return Promise.race([promise, timeoutPromise]);
+  try {
+    return await Promise.race([promise, timeoutPromise]);
+  } finally {
+    clearTimeout(timer);
+  }
 }
🤖 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/outreach-personalizer/apps/actions/orchestrate.ts` around lines 16 - 25,
The withTimeout helper in orchestrate.ts leaves the timeout pending after
Promise.race settles, so a later timeout can reject without a consumer and
trigger an unhandled rejection. Update withTimeout to keep the timeout handle,
clear it as soon as the wrapped promise resolves or rejects, and still preserve
the timeout error path; use the withTimeout function and its internal
setTimeout/Promise.race logic as the place to fix this.
🤖 Prompt for all review comments with 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.

Inline comments:
In `@kits/outreach-personalizer/apps/actions/orchestrate.ts`:
- Around line 1-2: The orchestrate.ts action is missing the parent kit
configuration import, so the step-definition source is not being registered.
Update the module that contains getLamaticClient() and FLOW_ID usage to also
import ../../lamatic.config, ensuring the orchestration flow loads the required
kit config before execution. Keep the fix localized to orchestrate.ts and
preserve the existing server action setup.

---

Outside diff comments:
In `@kits/outreach-personalizer/apps/actions/orchestrate.ts`:
- Around line 16-25: The withTimeout helper in orchestrate.ts leaves the timeout
pending after Promise.race settles, so a later timeout can reject without a
consumer and trigger an unhandled rejection. Update withTimeout to keep the
timeout handle, clear it as soon as the wrapped promise resolves or rejects, and
still preserve the timeout error path; use the withTimeout function and its
internal setTimeout/Promise.race logic as the place to fix this.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: a4fe28f4-5463-47f0-83f6-edb8312a238c

📥 Commits

Reviewing files that changed from the base of the PR and between 60cb10f and d915073.

📒 Files selected for processing (2)
  • kits/outreach-personalizer/apps/actions/orchestrate.ts
  • kits/outreach-personalizer/apps/lib/lamatic-client.ts

Comment thread kits/outreach-personalizer/apps/actions/orchestrate.ts
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant