Skip to content

feat: Add Intelligent Watchdog automation kit for competitor intelligence#109

Open
HarshM1010 wants to merge 36 commits intoLamatic:mainfrom
HarshM1010:feat/Add-Intelligent-Watchdog-automation-kit-for-competitor-intelligence
Open

feat: Add Intelligent Watchdog automation kit for competitor intelligence#109
HarshM1010 wants to merge 36 commits intoLamatic:mainfrom
HarshM1010:feat/Add-Intelligent-Watchdog-automation-kit-for-competitor-intelligence

Conversation

@HarshM1010
Copy link
Copy Markdown

@HarshM1010 HarshM1010 commented Mar 27, 2026

What This Kit Does

Intelligent Watchdog is an AI-powered competitor intelligence agent. It automates the tedious task of monitoring rival websites by scraping landing pages, detecting changes in pricing, features or updates, and generating tactical "battle cards" for sales teams to win more deals.

Providers & Prerequisites

  • External Providers: Google Gemini (via Lamatic), Firecrawl (for web scraping)
  • Prerequisites: Lamatic.ai account, Firecrawl API Key (configured in Lamatic Studio)

How to Run Locally

Bash

cd kits/automation/Watchdog
npm install
# Create .env.local and add your Lamatic keys
npm run dev

Live Preview

Vercel URL: https://intelligent-watchdog.vercel.app/

Lamatic Flow

  • Watchdog Flow ID: 811a44e5-a5ab-471e-9b1e-9e994b49554f
  • Project ID: be77e472-8fda-41f1-a52d-575cf5b1bb3f

Intelligent Watchdog: AI-Powered Competitor Monitor

Overview

Adds a production-ready automation kit (kits/automation/Watchdog/) that transforms raw competitor URLs into actionable sales intelligence. Built with Next.js 15 and integrated with Lamatic.ai GraphQL endpoints.

Core Features

  • Multi-Competitor Watchlist: Track up to 10 competitors simultaneously through a centralized dashboard.
  • Automated Web Scraping: Uses the Firecrawl node to bypass bot detection and extract clean content from landing pages.
  • AI Change Analysis: Compares scraped data against previous states to identify pricing hikes, discounts, or new feature rollouts.
  • Sales Counter-Strategies: Automatically generates objection-handling points based on competitor updates.

Technical Implementation

  • Dynamic Dashboard (app/page.tsx): A responsive, dark-mode UI built with Shadcn UI and Lucide React for managing the watchlist and viewing reports.
  • API Orchestration (app/api/analyse/route.ts): A robust POST handler that validates input, handles batching, and communicates with Lamatic’s GraphQL API.
  • State Management: Local React state for real-time UI updates during long-running scraping operations.
  • Schema Validation: Implements strict checking for competitor object structures to prevent runtime failures.

Configuration

  • Environment Variables: LAMATIC_API_URL, LAMATIC_PROJECT_ID, LAMATIC_API_KEY, WATCHDOG_FLOW_ID.
  • Framework: Next.js with TypeScript and Tailwind CSS.
  • Styling: Custom global CSS for glassmorphism effects and modern dashboard aesthetic.

File Structure

  • app/: Contains the core UI and the /analyse API route.
  • config.json: Metadata for the Lamatic marketplace including environment variable mappings.
  • components.json: UI primitive configurations for Shadcn/Tailwind consistency.
  • README.md: Detailed setup instructions and deployment guide.

Files Added (concise)

  • kits/automation/Watchdog/app/page.tsx — Next.js 15 client dashboard: manage up to 10 competitors, run analysis, render markdown intelligence reports, modal UI, local state for long-running ops.
  • kits/automation/Watchdog/app/layout.tsx — Root layout with metadata and global CSS import.
  • kits/automation/Watchdog/app/actions.ts — Server Action analyzeCompetitorsAction: input validation (1–10 competitors), optional Upstash rate limiting, GraphQL executeWorkflow call to Lamatic with 80s timeout, error handling.
  • kits/automation/Watchdog/package.json — Next.js app manifest and dependencies (Next 15, React, Tailwind, shadcn tooling, lamatic, react-markdown, remark-gfm, lucide-react, Upstash).
  • kits/automation/Watchdog/tsconfig.json — TypeScript config (strict, path alias, Next plugin).
  • kits/automation/Watchdog/tailwind.config.ts — Tailwind config (content globs, custom pulse-slow animation, typography plugin).
  • kits/automation/Watchdog/postcss.config.mjs — PostCSS config enabling Tailwind plugin.
  • kits/automation/Watchdog/next.config.mjs — Next config (ignore TypeScript build errors, images.unoptimized).
  • kits/automation/Watchdog/global.css — Tailwind import.
  • kits/automation/Watchdog/components.json — shadcn UI generation config (new-york style, RSC/TSX, lucide).
  • kits/automation/Watchdog/config.json — Kit metadata: name, description, tags, author, integrations (Firecrawl, Postgres), required env key WATCHDOG_FLOW_ID, demo/docs URLs.
  • kits/automation/Watchdog/README.md — Kit README with setup, env vars, local run and deploy instructions, features and usage.
  • kits/automation/Watchdog/.gitignore — Node/Next artifacts and env exclusions for the kit.
  • kits/automation/Watchdog/flows/watchdog-flow/config.json — Flow config (webhook node + output mapping).
  • kits/automation/Watchdog/flows/watchdog-flow/inputs.json — JSON Schema for flow input: competitors array (min 1, max 10), each item { org_name: string, url: uri }.
  • kits/automation/Watchdog/flows/watchdog-flow/meta.json — Flow metadata (name, description, icon, category, complexity).
  • kits/automation/Watchdog/flows/watchdog-flow/README.md — Flow README describing Webhook Trigger, Firecrawl Scraper, and LLM Analyzer.
  • kits/automation/Watchdog/components.json, tailwind/postcss, and other build files as above support UI generation and styling.

Other repository changes:

  • Removed kits/agentic/stock-analysis git submodule pointer.
  • Root .gitignore: removed .env entry.
  • Updated CONTRIBUTING.md and root README.md (hero text and badges).
  • Modified .github/workflows/validate-pr.yml (validation step output/permissions changes).

Flow node types and high-level behavior

  • Observed nodes/types:

    • webhook (configured as node id "trigger", method POST, path /execute)
    • Documentation and outputMapping reference indicate additional logical nodes used by the flow at runtime: a Firecrawl Scraper node (for fetching landing-page content) and an LLM Analyzer node (LLM / Google Gemini via Lamatic) — these are described in the flow README and referenced in outputMapping placeholders (forLoopNode_304, LLMNode_331) though only the webhook node appears in the checked config.json file.
  • High-level flow operation:

    1. The Next.js app sends a POST to the flow webhook with payload { competitors: [{ org_name, url }, ...] } (1–10 items validated by inputs.json).
    2. The flow (as documented) uses Firecrawl to scrape each competitor landing page and bypass bot detection.
    3. An LLM Analyzer (Google Gemini via Lamatic) compares the latest scrape to historical baseline data to detect meaningful changes (pricing, features, discounts) and generates a tactical sales "Battle Card" / counter-strategy.
    4. The flow returns mapped output: { org_name, response } where response is the generated analysis (or "NO_CHANGE").
    5. The Next.js app's server action calls Lamatic's executeWorkflow GraphQL endpoint and the UI renders the returned analysis as markdown for sales teams.

Validation / notes

  • inputs.json enforces competitors array size (1–10) and strict item schema.
  • config.json's outputMapping references a loop node and an LLM node by placeholder IDs — ensure the deployed Lamatic flow includes the Firecrawl and LLM nodes matching those runtime IDs or update mapping accordingly.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a new "Intelligent Watchdog" automation kit (Next.js app, workflow, configs, docs), implements server action with validation and optional rate limiting, updates CI validation workflow, removes a submodule pointer, and refines contribution and README text.

Changes

Cohort / File(s) Summary
Watchdog — Next.js app
kits/automation/Watchdog/app/page.tsx, kits/automation/Watchdog/app/layout.tsx, kits/automation/Watchdog/app/actions.ts
New dashboard UI, root layout, and server action to validate input, enforce optional Upstash rate limits, call Lamatic executeWorkflow, and normalize analysis responses.
Watchdog — Build & tooling
kits/automation/Watchdog/package.json, kits/automation/Watchdog/tsconfig.json, kits/automation/Watchdog/next.config.mjs, kits/automation/Watchdog/postcss.config.mjs, kits/automation/Watchdog/tailwind.config.ts
Project manifest, TypeScript config, Next.js config (ignore TS build errors, unoptimized images), PostCSS/Tailwind setup and custom animation.
Watchdog — UI config & styles
kits/automation/Watchdog/components.json, kits/automation/Watchdog/global.css, kits/automation/Watchdog/.gitignore
Shadcn components config, Tailwind import, and .gitignore entries for node/Next.js artifacts and env files.
Watchdog — Workflow & schema
kits/automation/Watchdog/flows/watchdog-flow/config.json, kits/automation/Watchdog/flows/watchdog-flow/inputs.json, kits/automation/Watchdog/flows/watchdog-flow/meta.json, kits/automation/Watchdog/flows/watchdog-flow/README.md
Flow metadata, webhook trigger config, strict inputs JSON Schema (1–10 competitors with org_name and url), and flow README describing nodes and setup.
Watchdog — Metadata & docs
kits/automation/Watchdog/config.json, kits/automation/Watchdog/README.md
Automation manifest, required env keys, features, setup steps, example .env.local, and user-facing README with demo/deploy instructions.
Repository & CI updates
.github/workflows/validate-pr.yml, .gitignore, kits/agentic/stock-analysis
Simplified PR validation workflow (removed temp file, comment posting, label logic), adjusted top-level .gitignore, and removed a git submodule reference.
Contributor & repo README
CONTRIBUTING.md, README.md
Refocused CONTRIBUTING on Kit creation/export/run/deploy workflow and updated README hero text and badges.

Suggested reviewers

  • amanintech
  • d-pamneja

Mission handler: file secured.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely describes the main contribution: adding the Intelligent Watchdog automation kit for competitor intelligence monitoring.
Description check ✅ Passed The PR description comprehensively covers purpose, setup instructions, technical implementation, and file structure, addressing all major template sections despite not explicitly checking every checkbox.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 and usage tips.

Copy link
Copy Markdown
Author

@HarshM1010 HarshM1010 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have resolved the issues

@HarshM1010
Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

✅ Actions performed

Review triggered.

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.

@coderabbitai coderabbitai bot requested a review from amanintech March 27, 2026 08:52
@HarshM1010
Copy link
Copy Markdown
Author

Hi @maintainers! All validation checks are now passing, and I've added the required flow directory and metadata. I don't have permissions to add labels myself—could you please add the agentkit-challenge label to this PR so it can be officially tracked? Thank you!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 18

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@kits/automation/Watchdog/app/api/analyse/route.ts`:
- Around line 39-41: The handler currently calls req.json() directly and any
malformed JSON bubbles to the outer try/catch producing a generic 500; wrap the
JSON parse in its own try/catch (around the req.json() that assigns body and the
subsequent competitors extraction) and when parsing fails return a 400 Bad
Request Response with a clear message (e.g., "Malformed JSON" or similar)
instead of letting the outer catch handle it; ensure you reference and adjust
the code around the existing req.json() call and the competitors variable so
only the parse error is handled locally.
- Around line 61-76: The fetch to LAMATIC_API_URL in route.ts (the POST using
EXECUTE_WORKFLOW / WATCHDOG_FLOW_ID and payload { competitors }) lacks an
AbortController timeout; create an AbortController, set a setTimeout to call
controller.abort() after a reasonable delay (e.g., 5–10s), pass
controller.signal into the fetch options, and clear the timeout after the
response arrives; also update the catch in the surrounding try/catch to detect
err.name === 'AbortError' and return a 504 NextResponse JSON indicating a
request timeout, otherwise continue returning a 500 for other errors.

In `@kits/automation/Watchdog/app/page.tsx`:
- Around line 149-153: The icon-only remove button (using the Trash2 icon and
calling removeCompetitor(i)) and the icon-only dialog-close control must have
accessible names; add an aria-label (e.g., aria-label="Remove competitor" for
the Trash2 button) and also include a title attribute for hover tooltips, and do
the same for the dialog close control (the close button rendered around lines
274-278—add aria-label="Close dialog" and title="Close dialog" or similar).
Ensure the attributes are added to the actual <button> elements that invoke
removeCompetitor and the dialog close handler so assistive tech and sighted
users both receive a descriptive label.
- Around line 55-63: The parser in page.tsx incorrectly assumes data.result is
raw JSON and references flow internals (raw = data.result; JSON.parse(raw);
codeNode_584), causing failures—update the client to consume the stable API
contract returned by the analyse route ({ status, result }) and the typed result
shape instead of flow-node keys: change code that reads data.result/rawResults
to expect the API's typed result (e.g., the LLMNode_331.output.generatedResponse
mapping) and normalize that single stable field into your Result[] shape before
mapping to cleanResults; remove any hard-coded node ids like codeNode_584 and
JSON.parse calls, validate the result type at runtime, and coerce/convert the
API's result into the Result[] shape used by cleanResults.
- Around line 19-22: Create a shared close handler that not only sets modalOpen
false but also resets newName, newUrl, and error, then replace inline close
logic in the Escape key listener (handleKey in useEffect) and the other close
paths (the handlers around lines 263–267, 275, and 321) to call this single
function; ensure the new function (e.g., closeModal or handleCloseModal) is
referenced wherever modalOpen is currently toggled to false so reopening the
modal never resurrects stale values or validation errors.
- Around line 25-34: When editing the watchlist in addCompetitor or
removeCompetitor (and other edit helpers around those lines), clear the current
reports and protect against stale in-flight responses by adding a request
version/token: 1) call setResults([]) (or setReports([])) immediately after
setCompetitors to clear the UI; 2) increment a requestVersionRef
(useRef<number>) or setRequestVersion(state) whenever the watchlist changes; 3)
in the async runner that commits server responses (the function that currently
writes the response at "line 82" — e.g.,
runWatchlist/fetchReports/handleResponse), capture the current requestVersion
when the request starts and ignore the response unless it matches the latest
requestVersionRef; reference addCompetitor, removeCompetitor, setCompetitors,
setResults (or setReports), and the async response handler to implement this.
- Around line 284-311: Add proper associations between each label and its input
by giving the Organisation Name input (the one bound to newName and using
setNewName/onKeyDown -> addCompetitor) a unique id and set the corresponding
label's htmlFor to that id, and do the same for the Pricing / features / updates
/ Landing URL input (the one bound to newUrl and using setNewUrl/onKeyDown ->
addCompetitor). Ensure ids are unique and stable (e.g., orgNameId and orgUrlId
or generated constants) and keep existing props like autoFocus and onKeyDown
unchanged so clicking the label or using assistive tech focuses and describes
the correct input.

In `@kits/automation/Watchdog/components.json`:
- Around line 6-8: The Tailwind config path under the "tailwind" object is
incorrect (currently set to ".js"); update the "config" value to the actual file
name "tailwind.config.ts" so the shadcn configuration points to the existing
Tailwind config file (edit the "tailwind" -> "config" entry in components.json).

In `@kits/automation/Watchdog/config.json`:
- Around line 22-25: Update the incorrect URLs in config.json: change the
deployUrl's root-directory and repository URL to point to the actual kit path
(use root-directory=kits/automation/Watchdog and repository-url pointing at the
main AgentKit repo), replace githubUrl with the main AgentKit repository URL
(and optionally include a tree path to kits/automation/Watchdog), and update
documentationUrl to the correct docs for this kit (use intelligent-watchdog or
Watchdog path). Edit the keys deployUrl, githubUrl, and documentationUrl to
reflect these corrected coordinates (leave demoUrl as-is if it is correct).
- Around line 9-15: Update the step ID in kits/automation/Watchdog/config.json
from "pricing-watchdog-flow" to match the actual flow folder name
"watchdog-flow" so the step ID aligns with the flow folder; also verify the
envKey "WATCHDOG_FLOW_ID" corresponds to the same flow and adjust it if your
environment variable naming convention requires the folder name (e.g.,
WATCHDOG_FLOW_ID) to match the step ID change.

In `@kits/automation/Watchdog/flows/watchdog-flow/config.json`:
- Around line 12-14: The outputMapping currently points to a non-existent node
id LLMNode_331 (result: "{{LLMNode_331.output.generatedResponse}}"), so update
the mapping to reference a real node or regenerate the flow from Lamatic Studio;
specifically, either replace LLMNode_331 with the actual node id that produces
generatedResponse (or change the property name to match the existing trigger
node's output) in the outputMapping entry, or open Lamatic Studio and re-export
the flow so the config contains the correct node IDs and mappings.

In `@kits/automation/Watchdog/flows/watchdog-flow/inputs.json`:
- Around line 4-13: The "competitors" JSON schema currently allows an unbounded
array; add a maxItems constraint to enforce the "up to 10" contract by setting
"maxItems": 10 on the "competitors" array definition (update the competitors
schema object where "type": "array" is declared) so flow invocations cannot pass
more than 10 entries; optionally add "minItems": 0 if an explicit lower bound is
desired.

In `@kits/automation/Watchdog/flows/watchdog-flow/README.md`:
- Around line 5-11: The README has markdown-structure issues: change the
top-level heading hierarchy so you add or convert an h2 before the existing h3
sections (e.g., introduce a "## Overview" or convert "### Nodes:" and "###
Setup:" to "## Nodes:" and "## Setup:"), ensure there is a blank line above and
below each heading (so add an empty line before each "## Nodes:" and "## Setup:"
and after their titles), and ensure the file ends with exactly one newline; also
keep the referenced environment variable WATCHDOG_FLOW_ID text unchanged while
applying these formatting fixes.

In `@kits/automation/Watchdog/package.json`:
- Line 2: The package.json "name" field currently has an invalid value with a
space ("Intelligent Watchdog"); update the "name" value to a valid npm package
identifier (e.g., lowercase, hyphenated like "intelligent-watchdog") while
leaving "private": true as-is; if you need a human-friendly title, add a
separate "displayName" or document it elsewhere rather than using the "name"
field.
- Around line 18-36: The dependencies in package.json use caret ranges (e.g.,
"@tailwindcss/postcss", "@tailwindcss/typography", "next", "react", "react-dom",
"typescript", etc.), which violates the pinned-version policy; update both
"dependencies" and "devDependencies" entries to use exact (pinned) versions
instead of caret ranges by removing the leading "^" and locking each package to
the current intended version string (for all listed packages such as
"@tailwindcss/postcss", "lamatic", "lucide-react", "react-markdown",
"@types/node", "@types/react", "autoprefixer", "postcss", "tailwindcss",
"typescript"), ensuring no range specifiers remain so installs are reproducible.

In `@kits/automation/Watchdog/README.md`:
- Around line 60-66: The README's environment variable entry uses the wrong key
AGENTIC_GENERATE_CONTENT; update the README environment variables section to
match the actual key validated in app/api/analyse/route.ts by replacing
AGENTIC_GENERATE_CONTENT with WATCHDOG_FLOW_ID and provide realistic example
values for WATCHDOG_FLOW_ID, LAMATIC_API_URL, LAMATIC_PROJECT_ID, and
LAMATIC_API_KEY so the documented names match the route's validation and usage
of WATCHDOG_FLOW_ID.
- Around line 77-94: README's "Repo Structure" block is out of sync with the
actual Watchdog kit; update the documented tree to reflect real assets by
replacing references to non-existent paths (/actions, /lib, /components/ui) and
showing actual files and folders such as /app (including page.tsx, layout.tsx,
api/analyse/route.ts), /flows/watchdog-flow, /public, global.css, config.json
and package.json; ensure the README's code block lists these exact symbols
(page.tsx, layout.tsx, api/analyse/route.ts, watchdog-flow, global.css,
config.json, package.json) and remove the outdated entries so the displayed
structure matches the repo.
- Around line 1-12: The README header is copy-pasted from the wrong kit; update
the top metadata so it correctly represents the Watchdog kit: change the title
string "Agent Kit Generation" to "Intelligent Watchdog", update the Live Demo
badge URL to the Watchdog demo, and fix the Deploy with Vercel link query param
repository-root to point to kits/automation/Watchdog (replace
kits/agentic/generation). Edit the visible header lines and the hrefs in the
README to reflect these new values so the title, demo badge, and Deploy button
all reference the Watchdog kit.
🪄 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: 32cab4bc-7e2a-471b-8f9d-1e5049f98933

📥 Commits

Reviewing files that changed from the base of the PR and between 5b8dea8 and f6a21b1.

⛔ Files ignored due to path filters (1)
  • kits/automation/Watchdog/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • CHALLENGE.md
  • CLAUDE.md
  • kits/automation/Watchdog/.gitignore
  • kits/automation/Watchdog/README.md
  • kits/automation/Watchdog/app/api/analyse/route.ts
  • kits/automation/Watchdog/app/layout.tsx
  • kits/automation/Watchdog/app/page.tsx
  • kits/automation/Watchdog/components.json
  • kits/automation/Watchdog/config.json
  • kits/automation/Watchdog/flows/watchdog-flow/README.md
  • kits/automation/Watchdog/flows/watchdog-flow/config.json
  • kits/automation/Watchdog/flows/watchdog-flow/inputs.json
  • kits/automation/Watchdog/flows/watchdog-flow/meta.json
  • kits/automation/Watchdog/global.css
  • kits/automation/Watchdog/next.config.mjs
  • kits/automation/Watchdog/package.json
  • kits/automation/Watchdog/postcss.config.mjs
  • kits/automation/Watchdog/tailwind.config.ts
  • kits/automation/Watchdog/tsconfig.json
💤 Files with no reviewable changes (2)
  • CHALLENGE.md
  • CLAUDE.md

Comment on lines +19 to +22
useEffect(() => {
const handleKey = (e: KeyboardEvent) => { if (e.key === "Escape") setModalOpen(false); };
window.addEventListener("keydown", handleKey);
return () => window.removeEventListener("keydown", handleKey);
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 | 🟡 Minor

Mission note: reset modal state on every close path.

Escape and backdrop close only flip modalOpen, unlike Line 275 and Line 321. Reopening the modal can resurrect stale values and validation errors. Extract a shared close handler that also clears newName, newUrl, and error.

Also applies to: 263-267

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/app/page.tsx` around lines 19 - 22, Create a shared
close handler that not only sets modalOpen false but also resets newName,
newUrl, and error, then replace inline close logic in the Escape key listener
(handleKey in useEffect) and the other close paths (the handlers around lines
263–267, 275, and 321) to call this single function; ensure the new function
(e.g., closeModal or handleCloseModal) is referenced wherever modalOpen is
currently toggled to false so reopening the modal never resurrects stale values
or validation errors.

@HarshM1010
Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

✅ Actions performed

Review triggered.

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (4)
kits/automation/Watchdog/config.json (2)

23-25: ⚠️ Potential issue | 🟠 Major

Deploy coordinates still point to wrong extraction zone, Agent.

The deployUrl references root-directory=kits/automation/intelligent-watchdog but the actual kit path is kits/automation/Watchdog. This mismatch will cause Vercel deployments to fail when attempting to locate the project root.

🔧 Proposed URL fix
     "demoUrl": "https://intelligent-watchdog.vercel.app/",
     "githubUrl": "https://github.com/HarshM1010/AgentKit/tree/feat/Add-Intelligent-Watchdog-automation-kit-for-competitor-intelligence/kits/automation/Watchdog",
-    "deployUrl": "https://vercel.com/new/clone?repository-url=https://github.com/HarshM1010/AgentKit_Watchdog&root-directory=kits/automation/intelligent-watchdog&env=WATCHDOG_FLOW_ID,LAMATIC_API_URL,LAMATIC_PROJECT_ID,LAMATIC_API_KEY&envDescription=Your%20Intelligent%20Watchdog%20flow%20ID%20and%20Lamatic%20API%20keys%20are%20required.&envLink=https://lamatic.ai/templates/agentkits/automation/intelligent-watchdog",
+    "deployUrl": "https://vercel.com/new/clone?repository-url=https://github.com/Lamatic/AgentKit&root-directory=kits/automation/Watchdog&env=WATCHDOG_FLOW_ID,LAMATIC_API_URL,LAMATIC_PROJECT_ID,LAMATIC_API_KEY&envDescription=Your%20Intelligent%20Watchdog%20flow%20ID%20and%20Lamatic%20API%20keys%20are%20required.&envLink=https://lamatic.ai/templates/agentkits/automation/intelligent-watchdog",
     "documentationUrl": "https://lamatic.ai/templates/agentkits/automation/intelligent-watchdog"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/config.json` around lines 23 - 25, The deployUrl in
config.json has an incorrect root-directory; update the deployUrl string so the
query param root-directory is kits/automation/Watchdog (instead of
kits/automation/intelligent-watchdog) so Vercel can locate the project
root—modify the "deployUrl" value to reference the correct path while keeping
the rest of the URL intact (key: deployUrl, param: root-directory, correct path:
kits/automation/Watchdog).

9-15: ⚠️ Potential issue | 🟠 Major

Agent, your step ID still doesn't match the flow folder — mission coordination compromised.

Per directive, step IDs must align with flow folder names. The step ID remains pricing-watchdog-flow but the actual flow folder is watchdog-flow. This discrepancy could cause deployment failures when the system attempts to locate the flow.

🔧 Proposed fix — align step ID with flow folder
     "steps": [
         {
-            "id": "pricing-watchdog-flow",
+            "id": "watchdog-flow",
             "type": "mandatory",
             "envKey": "WATCHDOG_FLOW_ID"
         }
     ],

As per coding guidelines: "Kit step IDs in config.json must align with flow folder names and corresponding environment variable keys"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/config.json` around lines 9 - 15, The step id
"pricing-watchdog-flow" in the steps array does not match the actual flow folder
name "watchdog-flow"; update the step object's "id" value to "watchdog-flow" so
the Kit step ID aligns with the flow folder name (leave the envKey
"WATCHDOG_FLOW_ID" as-is unless your environment variable also needs renaming).
Ensure the change is applied to the steps entry that currently contains "id":
"pricing-watchdog-flow".
kits/automation/Watchdog/app/page.tsx (2)

27-31: ⚠️ Potential issue | 🟡 Minor

Escape route doesn't follow protocol, Agent.

The closeModal helper (lines 20-25) properly resets all modal state, but the Escape key handler (line 28) still calls setModalOpen(false) directly. This can leave stale newName, newUrl, and error values when reopening the modal.

🔧 Proposed fix
   useEffect(() => {
-    const handleKey = (e: KeyboardEvent) => { if (e.key === "Escape") setModalOpen(false); };
+    const handleKey = (e: KeyboardEvent) => { if (e.key === "Escape") closeModal(); };
     window.addEventListener("keydown", handleKey);
     return () => window.removeEventListener("keydown", handleKey);
-  }, []);
+  }, [closeModal]);

Note: You may need to wrap closeModal in useCallback to avoid re-registering the listener on every render.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/app/page.tsx` around lines 27 - 31, The Escape key
handler directly calls setModalOpen(false) which skips the cleanup logic in
closeModal and can leave stale newName/newUrl/error state; update the useEffect
to call closeModal from the handleKey instead of setModalOpen, and if closeModal
is defined inline, wrap closeModal with useCallback so the effect doesn't
re-register the listener on every render; ensure handleKey references closeModal
(not setModalOpen) to fully reset modal state when Escape is pressed.

77-95: ⚠️ Potential issue | 🟠 Major

Response parser still references flow internals — fragile mission intel, Agent.

The parser hard-codes codeNode_584 (line 78), which is a flow-specific node ID. If the Lamatic flow is modified or re-exported, this ID will change and break the UI without any compile-time warning.

Consider either:

  1. Updating the flow's outputMapping to expose a stable, documented structure
  2. Having the API route normalize the response before returning it
🛡️ Suggested defensive parsing
       const cleanResults: Result[] = rawResults.map((item: any) => {
-        const formatted = item.codeNode_584?.output?.formatted;
+        // Try multiple known structures to be resilient to flow changes
+        const formatted = 
+          item.formatted ||
+          item.codeNode_584?.output?.formatted ||
+          item.output?.formatted;

         if (formatted && typeof formatted === "object") {

Better yet, normalize the response shape in route.ts so the client receives a stable contract.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/app/page.tsx` around lines 77 - 95, The parser in
the cleanResults mapping depends on a hard-coded flow node ID (codeNode_584)
which is brittle; update the implementation so the UI does not reference flow
internals: either adjust the server-side normalization in route.ts to return a
stable shape (e.g., { org_name, response }) and have cleanResults/rawResults
expect that, or change the client parsing in page.tsx (the cleanResults mapping
that produces Result) to defensively locate output (search known keys, prefer an
exported "output" property, or fallback to item.response/item) instead of using
codeNode_584; update types (Result) and any callers accordingly so the client
uses a documented, stable contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@kits/automation/Watchdog/app/api/analyse/route.ts`:
- Around line 70-71: The hardcoded 400000ms timeout in the AbortController setup
(const controller = new AbortController(); const timeoutId = setTimeout(() =>
controller.abort(), 400000);) is too long for serverless environments; change
this to a safer default (e.g., 60000–120000ms) or make the timeout configurable
via an environment variable, and ensure the timeoutId is cleared when the
operation completes; update any callers in route.ts that rely on controller to
use the new configurable value.

In `@kits/automation/Watchdog/app/page.tsx`:
- Around line 289-293: The backdrop click handler currently calls
setModalOpen(false) directly (in the modal rendering block checking modalOpen),
which bypasses the cleanup in closeModal; change the onClick handler on the
backdrop div to invoke closeModal() when e.target === e.currentTarget so the
modal closes and form/state cleanup runs (refer to closeModal, setModalOpen,
modalOpen, and the backdrop div's onClick).

In `@kits/automation/Watchdog/README.md`:
- Around line 11-14: The README exposes real Lamatic credentials
(WATCHDOG_FLOW_ID, LAMATIC_API_URL, LAMATIC_PROJECT_ID, LAMATIC_API_KEY);
immediately revoke/rotate the exposed LAMATIC_API_KEY in Lamatic, then edit the
README to replace those four symbols with clearly labeled placeholder values
(e.g., "<WATCHDOG_FLOW_ID_PLACEHOLDER>") and add a short note instructing users
to set real credentials via environment variables or a secrets manager;
additionally, add or update project safeguards (a .gitignore entry and/or a
pre-commit hook) to prevent committing real secrets in the future.
- Around line 1-43: Update the README.md markdown structure: change the
top-level heading from "## Intelligent Watchdog by Lamatic.ai" to "# Intelligent
Watchdog by Lamatic.ai", split the long compressed intro paragraphs (the live
demo and overview text around the top) into distinct sections (e.g., "##
Overview", "## Prerequisites", "## Setup", "## Environment Variables", "##
Running Locally", "## Deployment"), and fix the broken ordered list under
"Environment Variables" so list items use proper Markdown numbering or fenced
code blocks for the .env example (ensure a blank line before lists/code blocks);
reference the existing headings and section names in README.md to locate and
adjust the content.

---

Duplicate comments:
In `@kits/automation/Watchdog/app/page.tsx`:
- Around line 27-31: The Escape key handler directly calls setModalOpen(false)
which skips the cleanup logic in closeModal and can leave stale
newName/newUrl/error state; update the useEffect to call closeModal from the
handleKey instead of setModalOpen, and if closeModal is defined inline, wrap
closeModal with useCallback so the effect doesn't re-register the listener on
every render; ensure handleKey references closeModal (not setModalOpen) to fully
reset modal state when Escape is pressed.
- Around line 77-95: The parser in the cleanResults mapping depends on a
hard-coded flow node ID (codeNode_584) which is brittle; update the
implementation so the UI does not reference flow internals: either adjust the
server-side normalization in route.ts to return a stable shape (e.g., {
org_name, response }) and have cleanResults/rawResults expect that, or change
the client parsing in page.tsx (the cleanResults mapping that produces Result)
to defensively locate output (search known keys, prefer an exported "output"
property, or fallback to item.response/item) instead of using codeNode_584;
update types (Result) and any callers accordingly so the client uses a
documented, stable contract.

In `@kits/automation/Watchdog/config.json`:
- Around line 23-25: The deployUrl in config.json has an incorrect
root-directory; update the deployUrl string so the query param root-directory is
kits/automation/Watchdog (instead of kits/automation/intelligent-watchdog) so
Vercel can locate the project root—modify the "deployUrl" value to reference the
correct path while keeping the rest of the URL intact (key: deployUrl, param:
root-directory, correct path: kits/automation/Watchdog).
- Around line 9-15: The step id "pricing-watchdog-flow" in the steps array does
not match the actual flow folder name "watchdog-flow"; update the step object's
"id" value to "watchdog-flow" so the Kit step ID aligns with the flow folder
name (leave the envKey "WATCHDOG_FLOW_ID" as-is unless your environment variable
also needs renaming). Ensure the change is applied to the steps entry that
currently contains "id": "pricing-watchdog-flow".
🪄 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: 8b63f828-ea06-44c6-aa12-e3c34e5bb438

📥 Commits

Reviewing files that changed from the base of the PR and between f6a21b1 and 0ab3d9a.

📒 Files selected for processing (5)
  • kits/automation/Watchdog/README.md
  • kits/automation/Watchdog/app/api/analyse/route.ts
  • kits/automation/Watchdog/app/page.tsx
  • kits/automation/Watchdog/config.json
  • kits/automation/Watchdog/package.json

Comment on lines +11 to +14
WATCHDOG_FLOW_ID = "811a44e5-a5ab-471e-9b1e-9e994b49554f"
LAMATIC_API_URL = "https://harshsorganization186-watchdog623.lamatic.dev/graphql"
LAMATIC_PROJECT_ID = "be77e472-8fda-41f1-a52d-575cf5b1bb3f"
LAMATIC_API_KEY = "36dfd9791177adaee07cb4976a9e40f4"
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 | 🔴 Critical

🚨 ABORT MISSION — Actual API credentials exposed in documentation, Agent!

This is a critical security breach. Lines 11-14 contain what appear to be real Lamatic API credentials:

  • WATCHDOG_FLOW_ID with actual UUID
  • LAMATIC_API_URL with real endpoint
  • LAMATIC_PROJECT_ID with actual UUID
  • LAMATIC_API_KEY with actual API key value

These credentials must be revoked immediately and replaced with placeholder examples. Once committed to version control, secrets are considered compromised even if later removed.

🔐 Proposed fix — use placeholder values
-WATCHDOG_FLOW_ID = "811a44e5-a5ab-471e-9b1e-9e994b49554f"
-LAMATIC_API_URL = "https://harshsorganization186-watchdog623.lamatic.dev/graphql"
-LAMATIC_PROJECT_ID = "be77e472-8fda-41f1-a52d-575cf5b1bb3f"
-LAMATIC_API_KEY = "36dfd9791177adaee07cb4976a9e40f4"
+WATCHDOG_FLOW_ID=your-watchdog-flow-id
+LAMATIC_API_URL=https://your-org.lamatic.dev/graphql
+LAMATIC_PROJECT_ID=your-project-id
+LAMATIC_API_KEY=your-api-key

Immediate action required:

  1. Rotate/revoke the exposed LAMATIC_API_KEY in your Lamatic dashboard
  2. Replace with placeholder values in this file
  3. Consider adding a .gitignore rule or pre-commit hook to prevent future credential leaks
📝 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
WATCHDOG_FLOW_ID = "811a44e5-a5ab-471e-9b1e-9e994b49554f"
LAMATIC_API_URL = "https://harshsorganization186-watchdog623.lamatic.dev/graphql"
LAMATIC_PROJECT_ID = "be77e472-8fda-41f1-a52d-575cf5b1bb3f"
LAMATIC_API_KEY = "36dfd9791177adaee07cb4976a9e40f4"
WATCHDOG_FLOW_ID=your-watchdog-flow-id
LAMATIC_API_URL=https://your-org.lamatic.dev/graphql
LAMATIC_PROJECT_ID=your-project-id
LAMATIC_API_KEY=your-api-key
🧰 Tools
🪛 Betterleaks (1.1.1)

[high] 14-14: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/README.md` around lines 11 - 14, The README exposes
real Lamatic credentials (WATCHDOG_FLOW_ID, LAMATIC_API_URL, LAMATIC_PROJECT_ID,
LAMATIC_API_KEY); immediately revoke/rotate the exposed LAMATIC_API_KEY in
Lamatic, then edit the README to replace those four symbols with clearly labeled
placeholder values (e.g., "<WATCHDOG_FLOW_ID_PLACEHOLDER>") and add a short note
instructing users to set real credentials via environment variables or a secrets
manager; additionally, add or update project safeguards (a .gitignore entry
and/or a pre-commit hook) to prevent committing real secrets in the future.

@HarshM1010
Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

✅ Actions performed

Review triggered.

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (4)
kits/automation/Watchdog/app/page.tsx (2)

27-31: ⚠️ Potential issue | 🟡 Minor

Escape route still bypasses decontamination protocol, Agent.

The Escape key handler (line 28) calls setModalOpen(false) directly instead of using the closeModal() function, which means stale form values (newName, newUrl, error) will persist if the user reopens the modal.

🔧 Proposed extraction fix
   useEffect(() => {
-    const handleKey = (e: KeyboardEvent) => { if (e.key === "Escape") setModalOpen(false); };
+    const handleKey = (e: KeyboardEvent) => { if (e.key === "Escape") closeModal(); };
     window.addEventListener("keydown", handleKey);
     return () => window.removeEventListener("keydown", handleKey);
-  }, []);
+  }, [closeModal]);

Note: You'll need to wrap closeModal in useCallback or move it inside the effect to satisfy the dependency array.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/app/page.tsx` around lines 27 - 31, The Escape key
handler currently calls setModalOpen(false) directly which bypasses the cleanup
logic in closeModal and leaves stale state (newName, newUrl, error); update the
useEffect handler (handleKey) to call closeModal instead of setModalOpen, and
ensure closeModal is stable by wrapping it in useCallback or by defining
closeModal inside the same useEffect so it can be referenced in the dependency
array—this ensures modal state and form fields are reset when Escape is pressed.

77-95: ⚠️ Potential issue | 🟠 Major

Mission-critical: Response parser references a phantom node, Agent.

Line 78 extracts data from item.codeNode_584?.output?.formatted, but according to the flow configuration at kits/automation/Watchdog/flows/watchdog-flow/config.json, the outputMapping maps result to LLMNode_331.output.generatedResponse — not codeNode_584.

This means the parser may fail to extract valid responses when the LLM node returns data under the correct key, causing fallback to JSON.stringify(item) which produces unreadable reports.

Verify the actual response structure from the Lamatic workflow:

#!/bin/bash
# Check the config.json outputMapping to confirm the expected response structure
cat kits/automation/Watchdog/flows/watchdog-flow/config.json | jq '.outputMapping // .output // .'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/app/page.tsx` around lines 77 - 95, The parser
currently reads item.codeNode_584?.output?.formatted (codeNode_584) but the flow
maps outputs to LLMNode_331.output.generatedResponse; update the cleanResults
mapping to first check item.LLMNode_331?.output?.generatedResponse (and its
formatted/response fields if present), then fall back to item.codeNode_584 for
backward compatibility, and finally to item.org_name/item.response before
JSON-stringifying; ensure you reference the symbols codeNode_584 and LLMNode_331
in the conditional checks so the correct node payload is extracted and readable
responses are returned.
kits/automation/Watchdog/README.md (2)

6-6: 🧹 Nitpick | 🔵 Trivial

Intel formatting needs cleanup for field operatives, Agent.

The documentation is compressed into wall-of-text paragraphs (line 6) making it difficult for operatives to quickly extract mission-critical setup steps. Static analysis also flagged spelling/grammar issues from concatenated text.

Consider breaking into proper markdown sections:

  • ## Overview
  • ## Prerequisites
  • ## Lamatic Setup
  • ## Environment Variables
  • ## Running Locally
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/README.md` at line 6, The README text is a single
compressed paragraph with concatenated sentences and grammar issues; split and
reformat it into clear Markdown sections (for example: "## Overview", "##
Prerequisites", "## Lamatic Setup", "## Environment Variables", "## Running
Locally", and "## Deploy to Vercel") and move the existing content into those
sections, preserving the Lamatic Setup steps (Webhook Trigger, Firecrawl
Scraper, LLM Node), the .env.local instructions (add LAMATIC_API_KEY,
WATCHDOG_FLOW_ID, LAMATIC_PROJECT_ID), and the npm/Vercel commands; also fix
punctuation and spacing errors, use bullet or numbered lists for step sequences,
and ensure each credential entry in the "Environment Variables" section includes
the purpose and where to get it.

11-14: ⚠️ Potential issue | 🔴 Critical

🚨 ABORT MISSION — Your cover is blown, Agent! Real credentials are still exposed!

Despite prior intelligence indicating this was addressed, lines 11-14 still contain what appear to be actual Lamatic API credentials:

  • WATCHDOG_FLOW_ID with real UUID
  • LAMATIC_API_URL with actual endpoint
  • LAMATIC_PROJECT_ID with real UUID
  • LAMATIC_API_KEY with actual key value

Static analysis confirms: "Detected a Generic API Key, potentially exposing access to various services and sensitive operations."

Immediate action required:

  1. Rotate/revoke the exposed LAMATIC_API_KEY in your Lamatic dashboard — consider it compromised
  2. Replace all four values with clearly labeled placeholders
🔐 Proposed fix — sanitize the credentials
-WATCHDOG_FLOW_ID = "811a44e5-a5ab-471e-9b1e-9e994b49554f"
-LAMATIC_API_URL = "https://harshsorganization186-watchdog623.lamatic.dev/graphql"
-LAMATIC_PROJECT_ID = "be77e472-8fda-41f1-a52d-575cf5b1bb3f"
-LAMATIC_API_KEY = "36dfd9791177adaee07cb4976a9e40f4"
+WATCHDOG_FLOW_ID=your-watchdog-flow-id
+LAMATIC_API_URL=https://your-org.lamatic.dev/graphql
+LAMATIC_PROJECT_ID=your-project-id
+LAMATIC_API_KEY=your-api-key

Based on learnings: "Never commit real API keys, secrets, or credentials; use .env.example with placeholders only"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/README.md` around lines 11 - 14, Replace the exposed
secrets by revoking/rotating the compromised LAMATIC_API_KEY immediately, then
sanitize the README entries by replacing WATCHDOG_FLOW_ID, LAMATIC_API_URL,
LAMATIC_PROJECT_ID, and LAMATIC_API_KEY with descriptive placeholders (e.g.,
WATCHDOG_FLOW_ID="<YOUR_FLOW_ID>", LAMATIC_API_URL="<YOUR_API_URL>", etc.) and
add a note directing developers to use environment variables or a .env.example
for real credentials; ensure no real keys remain in the file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@kits/automation/Watchdog/app/api/analyse/route.ts`:
- Around line 50-68: The API validation allows any number of competitors,
bypassing the inputs.json maxItems:10 limit; update the validation around the
competitors variable and isValid check to also enforce competitors.length <= 10
(or a constant MAX_COMPETITORS) and return the 400 NextResponse.json error when
exceeded; reference the competitors array and isValid logic in route.ts to add
the length check and a clear error message about the maximum allowed.

In `@kits/automation/Watchdog/app/page.tsx`:
- Around line 348-354: The Cancel button is duplicating cleanup by calling
setModalOpen(false); setNewName(""); setNewUrl(""); setError("") inline instead
of using the shared closeModal() handler; replace the inline reset with a call
to closeModal() so the modal teardown logic is centralized (locate the Cancel
button's onClick and swap the current inline calls to invoke closeModal(),
ensuring closeModal handles all state resets performed previously).

In `@kits/automation/Watchdog/flows/watchdog-flow/inputs.json`:
- Around line 11-12: The JSON schema mistakenly applies "format": "uri" to the
org_name property; remove the format key from org_name (leave it as type:
"string" for plain company names) and add "format": "uri" to the url property so
url is validated as a URI; specifically update the org_name and url entries in
the inputs.json schema (properties "org_name" and "url") to swap the format
constraint.

---

Duplicate comments:
In `@kits/automation/Watchdog/app/page.tsx`:
- Around line 27-31: The Escape key handler currently calls setModalOpen(false)
directly which bypasses the cleanup logic in closeModal and leaves stale state
(newName, newUrl, error); update the useEffect handler (handleKey) to call
closeModal instead of setModalOpen, and ensure closeModal is stable by wrapping
it in useCallback or by defining closeModal inside the same useEffect so it can
be referenced in the dependency array—this ensures modal state and form fields
are reset when Escape is pressed.
- Around line 77-95: The parser currently reads
item.codeNode_584?.output?.formatted (codeNode_584) but the flow maps outputs to
LLMNode_331.output.generatedResponse; update the cleanResults mapping to first
check item.LLMNode_331?.output?.generatedResponse (and its formatted/response
fields if present), then fall back to item.codeNode_584 for backward
compatibility, and finally to item.org_name/item.response before
JSON-stringifying; ensure you reference the symbols codeNode_584 and LLMNode_331
in the conditional checks so the correct node payload is extracted and readable
responses are returned.

In `@kits/automation/Watchdog/README.md`:
- Line 6: The README text is a single compressed paragraph with concatenated
sentences and grammar issues; split and reformat it into clear Markdown sections
(for example: "## Overview", "## Prerequisites", "## Lamatic Setup", "##
Environment Variables", "## Running Locally", and "## Deploy to Vercel") and
move the existing content into those sections, preserving the Lamatic Setup
steps (Webhook Trigger, Firecrawl Scraper, LLM Node), the .env.local
instructions (add LAMATIC_API_KEY, WATCHDOG_FLOW_ID, LAMATIC_PROJECT_ID), and
the npm/Vercel commands; also fix punctuation and spacing errors, use bullet or
numbered lists for step sequences, and ensure each credential entry in the
"Environment Variables" section includes the purpose and where to get it.
- Around line 11-14: Replace the exposed secrets by revoking/rotating the
compromised LAMATIC_API_KEY immediately, then sanitize the README entries by
replacing WATCHDOG_FLOW_ID, LAMATIC_API_URL, LAMATIC_PROJECT_ID, and
LAMATIC_API_KEY with descriptive placeholders (e.g.,
WATCHDOG_FLOW_ID="<YOUR_FLOW_ID>", LAMATIC_API_URL="<YOUR_API_URL>", etc.) and
add a note directing developers to use environment variables or a .env.example
for real credentials; ensure no real keys remain in the file.
🪄 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: ea10a562-e136-466b-bffc-e0bd6a7458a8

📥 Commits

Reviewing files that changed from the base of the PR and between 0ab3d9a and 3095fd2.

📒 Files selected for processing (5)
  • kits/automation/Watchdog/README.md
  • kits/automation/Watchdog/app/api/analyse/route.ts
  • kits/automation/Watchdog/app/page.tsx
  • kits/automation/Watchdog/flows/watchdog-flow/README.md
  • kits/automation/Watchdog/flows/watchdog-flow/inputs.json

@HarshM1010
Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

✅ Actions performed

Review triggered.

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (1)
kits/automation/Watchdog/app/page.tsx (1)

58-68: ⚠️ Potential issue | 🟡 Minor

Intel parsing could detonate on malformed payloads, Agent.

If raw is a malformed JSON string, JSON.parse(raw) at line 60 will throw an unhandled exception, crashing the analysis flow and leaving the UI in an error state without a clear message.

🛡️ Proposed defensive protocol
 const normalizeWatchdogData = (raw: any): { results: any[] } => {
   // Handle stringified JSON from GraphQL
-  const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
+  let parsed: any;
+  try {
+    parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
+  } catch {
+    console.warn("Failed to parse watchdog response:", raw);
+    return { results: [] };
+  }

   // Detect and convert to Canonical Form: { results: [...] }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/app/page.tsx` around lines 58 - 68, The
normalizeWatchdogData function currently calls JSON.parse(raw) directly which
will throw on malformed JSON; wrap the string parsing in a try/catch (or
implement a small safeParse helper) inside normalizeWatchdogData so that if
JSON.parse fails you catch the error, optionally log or surface a concise error
message, and return the safe fallback { results: [] } instead of letting the
exception propagate; keep the existing detection for parsed?.results,
parsed?.Result, and Array.isArray(parsed) after successful parse.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@kits/automation/Watchdog/app/actions.ts`:
- Line 16: The analyzeCompetitorsAction function accepts competitors: any[] with
no validation; add input validation at the start of analyzeCompetitorsAction to
enforce 1–10 items and that each item has a non-empty string org_name and a
valid URL string for url (matching the flow inputs.json schema),
returning/rejecting early with an error if validation fails; use the function
name analyzeCompetitorsAction to locate the entry point and perform checks
(length, types, string emptiness, and URL format via a simple URL parse or
regex) before sending the payload to the Lamatic API so malformed payloads are
blocked.
- Around line 48-62: Add an AbortController-based timeout around the fetch to
LAMATIC_API_URL (the block that posts query EXECUTE_WORKFLOW with variables
including WATCHDOG_FLOW_ID and competitors): create an AbortController, set a
timer (e.g. setTimeout) to call controller.abort() after a chosen timeout, pass
controller.signal into fetch options, and clear the timer when the response
arrives; also update the surrounding catch to detect error.name === 'AbortError'
and throw a clear timeout Error (e.g. "Request timeout - Lamatic API did not
respond in time") while rethrowing other errors with their messages.
- Around line 47-62: Replace the raw GraphQL fetch in app/actions.ts that posts
to LAMATIC_API_URL (using LAMATIC_API_KEY, LAMATIC_PROJECT_ID, EXECUTE_WORKFLOW,
WATCHDOG_FLOW_ID and competitors) with the Lamatic SDK client: create
lib/lamatic-client.ts exporting lamaticClient (per the provided pattern that
validates env vars and instantiates Lamatic with endpoint/projectId/apiKey) and
then call the flow execution via lamaticClient (instead of fetch) in the action
that currently references EXECUTE_WORKFLOW and WATCHDOG_FLOW_ID; ensure you
propagate the same payload ({ competitors }), handle SDK errors, and remove the
direct fetch usage so the file matches embed/search and embed/chat patterns.

In `@kits/automation/Watchdog/app/api/analyse/route.ts`:
- Around line 1-206: The file contains a fully commented-out POST handler and
related symbols (EXECUTE_WORKFLOW, localRateLimitMap, POST) and should not
remain as dead code; either delete this route.ts file entirely, or convert it
into a short reference file by removing the commented implementation and
replacing it with a clear top-of-file comment that states the file is
decommissioned, points to kits/automation/Watchdog/app/actions.ts for the active
logic, and documents when/why it can be restored (keep git history for full code
recovery); ensure no exports or build artifacts remain that could confuse the
runtime.

In `@kits/automation/Watchdog/package.json`:
- Around line 21-22: The package.json currently uses caret ranges for
`@upstash/ratelimit` and `@upstash/redis` which violates the pinned-version policy;
update the dependencies entry for "@upstash/ratelimit" and "@upstash/redis" to
use exact version strings (no ^ or ~) matching the tested versions (e.g.,
replace "^2.0.8" and "^1.37.0" with the equivalent exact versions "2.0.8" and
"1.37.0"); ensure you save package.json and run a quick install to verify there
are no resolution issues.
- Line 26: The package.json in this kit pins "next": "16.2.1" while the sibling
kit kits/automation/blog-automation pins "next": "15.5.9", so confirm whether
the major-version divergence is intentional; if not, align versions by updating
one of the package.json files so both kits use the same Next.js major (either
both 16.x or both 15.x) and run npm/yarn install + test to ensure compatibility;
if the divergence is intentional, add a short comment in each package.json (or
in the repo README) documenting why the kits target different Next versions to
avoid future confusion.

---

Duplicate comments:
In `@kits/automation/Watchdog/app/page.tsx`:
- Around line 58-68: The normalizeWatchdogData function currently calls
JSON.parse(raw) directly which will throw on malformed JSON; wrap the string
parsing in a try/catch (or implement a small safeParse helper) inside
normalizeWatchdogData so that if JSON.parse fails you catch the error,
optionally log or surface a concise error message, and return the safe fallback
{ results: [] } instead of letting the exception propagate; keep the existing
detection for parsed?.results, parsed?.Result, and Array.isArray(parsed) after
successful parse.
🪄 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: b0ca74fb-6486-457e-badb-e1225575593c

📥 Commits

Reviewing files that changed from the base of the PR and between ead9c79 and b7edf0b.

⛔ Files ignored due to path filters (1)
  • kits/automation/Watchdog/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • kits/agentic/stock-analysis
  • kits/automation/Watchdog/app/actions.ts
  • kits/automation/Watchdog/app/api/analyse/route.ts
  • kits/automation/Watchdog/app/page.tsx
  • kits/automation/Watchdog/package.json
💤 Files with no reviewable changes (1)
  • kits/agentic/stock-analysis

Comment on lines +47 to +62
// 3. 🚀 Secure Fetch: Performed entirely on the server
const res = await fetch(LAMATIC_API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${LAMATIC_API_KEY}`,
'x-project-id': LAMATIC_PROJECT_ID,
},
body: JSON.stringify({
query: EXECUTE_WORKFLOW,
variables: {
workflowId: WATCHDOG_FLOW_ID,
payload: { competitors },
},
}),
});
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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how other kits in this repo call Lamatic flows
echo "=== Searching for Lamatic SDK usage ==="
rg -n "from ['\"]lamatic['\"]" --type=ts -C2

echo ""
echo "=== Searching for executeWorkflow GraphQL pattern ==="
rg -n "executeWorkflow" --type=ts -C2

Repository: Lamatic/AgentKit

Length of output: 13413


🏁 Script executed:

# Check if Watchdog has a lamatic-client.ts file
echo "=== Checking Watchdog kit structure ==="
find kits/automation/Watchdog -type f -name "*.ts" -o -name "*.tsx" -o -name "*.json" | head -20

echo ""
echo "=== Checking if app/actions.ts is a server action file ==="
head -20 kits/automation/Watchdog/app/actions.ts

echo ""
echo "=== Checking Watchdog orchestrate or related config files ==="
find kits/automation/Watchdog -name "config.json" -o -name "orchestrate.*" | xargs ls -la 2>/dev/null

Repository: Lamatic/AgentKit

Length of output: 1631


🏁 Script executed:

# Check for CLAUDE.md or README in Watchdog kit
echo "=== Checking for design docs in Watchdog ==="
find kits/automation/Watchdog -name "CLAUDE.md" -o -name "README.md" | xargs cat 2>/dev/null

echo ""
echo "=== Checking full app/actions.ts file ==="
wc -l kits/automation/Watchdog/app/actions.ts
cat -n kits/automation/Watchdog/app/actions.ts

echo ""
echo "=== Comparing with standard lamatic-client.ts pattern (from hiring kit) ==="
head -60 kits/automation/hiring/lib/lamatic-client.ts

Repository: Lamatic/AgentKit

Length of output: 7545


Mission briefing: Migrate to SDK client for server action.

Your server action file (app/actions.ts) must use the Lamatic SDK via lamatic-client.ts pattern, not raw GraphQL fetch. This is the established requirement across the codebase—other server action files in embed/search and embed/chat implement this correctly.

Create lib/lamatic-client.ts following the standard pattern:

import { Lamatic } from "lamatic";

if (!process.env.LAMATIC_API_URL || !process.env.LAMATIC_PROJECT_ID || !process.env.LAMATIC_API_KEY) {
  throw new Error("Missing Lamatic credentials in environment variables");
}

export const lamaticClient = new Lamatic({
  endpoint: process.env.LAMATIC_API_URL,
  projectId: process.env.LAMATIC_PROJECT_ID,
  apiKey: process.env.LAMATIC_API_KEY,
});

Then call the flow via SDK in app/actions.ts rather than direct fetch. The SDK provides type safety, error handling, and consistency with the rest of the kit ecosystem.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/app/actions.ts` around lines 47 - 62, Replace the
raw GraphQL fetch in app/actions.ts that posts to LAMATIC_API_URL (using
LAMATIC_API_KEY, LAMATIC_PROJECT_ID, EXECUTE_WORKFLOW, WATCHDOG_FLOW_ID and
competitors) with the Lamatic SDK client: create lib/lamatic-client.ts exporting
lamaticClient (per the provided pattern that validates env vars and instantiates
Lamatic with endpoint/projectId/apiKey) and then call the flow execution via
lamaticClient (instead of fetch) in the action that currently references
EXECUTE_WORKFLOW and WATCHDOG_FLOW_ID; ensure you propagate the same payload ({
competitors }), handle SDK errors, and remove the direct fetch usage so the file
matches embed/search and embed/chat patterns.

@HarshM1010 HarshM1010 force-pushed the feat/Add-Intelligent-Watchdog-automation-kit-for-competitor-intelligence branch from b657c8f to b745f04 Compare March 31, 2026 20:03
@HarshM1010
Copy link
Copy Markdown
Author

Screenshot 2026-03-31 at 1 31 24 PM Here, you could fix the UI to render the markdown of the final answer. Rest LGTM!

Screenshot 2026-03-31 at 1 31 24 PM Here, you could fix the UI to render the markdown of the final answer. Rest LGTM!

Done! I've updated the UI to properly render the Markdown for the final response. It’s much more readable now—thanks for the catch!

HarshM1010 and others added 4 commits April 1, 2026 12:42
Copy link
Copy Markdown
Contributor

@d-pamneja d-pamneja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kindly do not edit the files not pertaining to your kit, only makes changes to your kit. Otherwise LGTM, we could merge post this fix. Thanks!

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 1, 2026

✅ Actions performed

Review triggered.

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a 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

♻️ Duplicate comments (3)
kits/automation/Watchdog/app/page.tsx (1)

59-69: ⚠️ Potential issue | 🟠 Major

Intel parsing could detonate on malformed payloads, Agent.

The JSON.parse(raw) at line 61 operates without extraction cover. If the GraphQL response contains malformed JSON, this will throw an unhandled exception and crash the analysis flow. Previous surveillance flagged this vulnerability.

🛡️ Proposed defensive protocol
 const normalizeWatchdogData = (raw: any): { results: any[] } => {
   // Handle stringified JSON from GraphQL
-  const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
+  let parsed: any;
+  try {
+    parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
+  } catch {
+    console.warn("Failed to parse watchdog response:", raw);
+    return { results: [] };
+  }

   // Detect and convert to Canonical Form: { results: [...] }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/app/page.tsx` around lines 59 - 69, The
normalizeWatchdogData function currently calls JSON.parse(raw) directly which
can throw on malformed input; wrap the parse in a try/catch and fall back to
treating raw as-is (or returning { results: [] }) on parse error or when raw is
null/undefined, so the function never throws; update the parsing logic inside
normalizeWatchdogData to safely attempt JSON.parse in a try block, catch and log
or ignore the error, then continue the existing detection/conversion steps
(checking parsed?.results, parsed?.Result, Array.isArray(parsed)) using the safe
fallback when parsing fails.
kits/automation/Watchdog/app/actions.ts (1)

95-97: ⚠️ Potential issue | 🟡 Minor

Abort signal deployed — but extraction protocol incomplete, Agent.

The timeout mechanism at lines 62-63 is in place, but the catch block doesn't distinguish AbortError from other failures. When the 80-second timeout fires, operatives receive a generic error message instead of clear timeout intel.

⏱️ Proposed extraction protocol
   } catch (error: any) {
+    if (error.name === 'AbortError') {
+      throw new Error("Request timeout - Lamatic API did not respond within 80 seconds.");
+    }
     throw new Error(error.message || "An unexpected error occurred");
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/app/actions.ts` around lines 95 - 97, The catch
block in actions.ts currently throws a generic Error for all failures; update it
to detect AbortError and rethrow a clear timeout error message: inside the
existing catch (error: any) { ... } check if error.name === 'AbortError' (or
error instanceof DOMException if appropriate) and throw a new Error like
"Operation timed out after 80 seconds"; otherwise preserve the current behavior
(throw new Error(error.message || "An unexpected error occurred")). This change
should be applied where the timeout/AbortController logic lives so timeout cases
are distinguishable from other failures.
kits/automation/Watchdog/package.json (1)

30-30: ⚠️ Potential issue | 🟡 Minor

One asset remains unpinned — mission not yet complete, Agent.

The remark-gfm dependency still uses a caret range (^4.0.1), which violates operational protocols. All other dependencies were correctly pinned in previous operations, but this one slipped through surveillance.

As per coding guidelines: "Each kit must have its own package.json with pinned dependency versions; do not rely on workspace-level hoisting or a root package.json"

📌 Proposed fix — pin the version
-    "remark-gfm": "^4.0.1"
+    "remark-gfm": "4.0.1"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/package.json` at line 30, The remark-gfm dependency
in this kit's package.json is using a caret range ("remark-gfm": "^4.0.1");
update the package.json entry for remark-gfm to a pinned exact version (e.g.,
"remark-gfm": "4.0.1") so it no longer uses ^ or ~, and verify the file contains
only explicitly pinned versions for all dependencies in this kit (not relying on
root/workspace hoisting).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.gitignore:
- Line 1: Restore the sensitive entries back into .gitignore by adding back the
lines excluding `.env` and `.env.local` (and any related variants like `.env.*`
if desired) so that local credential files are not tracked; locate the
repository .gitignore and re-add `.env` and `.env.local` entries (or a single
pattern such as `.env*`) ensuring they are not commented out, then verify by
running git status to confirm no .env files are staged and update
CONTRIBUTING.md guidance if needed.

In `@CONTRIBUTING.md`:
- Around line 193-214: The fenced code block showing the folder tree for
kits/<category>/<kit-name>/ in CONTRIBUTING.md is missing a language identifier;
update the opening ``` fence to include a hint like ```text or ```plaintext so
Markdown renderers consistently preserve formatting (modify the code block that
begins with the kits/<category>/<kit-name>/ tree).
- Line 507: The file CONTRIBUTING.md is missing a terminal newline character;
update the file so it ends with exactly one newline (no extra blank lines) to
satisfy POSIX and MD047—open CONTRIBUTING.md, add a single '\n' at the end,
remove any trailing blank lines if present, and re-run your markdown linting to
confirm the file now passes MD047.

In `@kits/automation/Watchdog/app/actions.ts`:
- Line 16: The analyzeCompetitorsAction function uses a broad any[]; replace it
with a concrete interface (e.g., Competitor) that mirrors the flow's inputs.json
schema and use Competitor[] as the parameter type for analyzeCompetitorsAction;
add the Competitor interface (or export it from a nearby types module) with the
exact fields from inputs.json, update any internal uses/calls to satisfy the new
type, and adjust imports/exports so analyzeCompetitorsAction and the new type
are correctly referenced across the codebase.

In `@kits/automation/Watchdog/app/page.tsx`:
- Around line 237-239: The current JSX uses array index as the React key in the
results rendering (results.map(...) key={index}), which can be acceptable now
but is fragible; update the rendering to use a stable ID on each result instead
of index: ensure the data normalization that produces the results array attaches
a stable identifier (e.g., a result.id generated in the normalization step) and
change the map key to use that property (key={item.id}) so the component uses
stable keys (refer to results.map, key={index} and the result objects).

---

Duplicate comments:
In `@kits/automation/Watchdog/app/actions.ts`:
- Around line 95-97: The catch block in actions.ts currently throws a generic
Error for all failures; update it to detect AbortError and rethrow a clear
timeout error message: inside the existing catch (error: any) { ... } check if
error.name === 'AbortError' (or error instanceof DOMException if appropriate)
and throw a new Error like "Operation timed out after 80 seconds"; otherwise
preserve the current behavior (throw new Error(error.message || "An unexpected
error occurred")). This change should be applied where the
timeout/AbortController logic lives so timeout cases are distinguishable from
other failures.

In `@kits/automation/Watchdog/app/page.tsx`:
- Around line 59-69: The normalizeWatchdogData function currently calls
JSON.parse(raw) directly which can throw on malformed input; wrap the parse in a
try/catch and fall back to treating raw as-is (or returning { results: [] }) on
parse error or when raw is null/undefined, so the function never throws; update
the parsing logic inside normalizeWatchdogData to safely attempt JSON.parse in a
try block, catch and log or ignore the error, then continue the existing
detection/conversion steps (checking parsed?.results, parsed?.Result,
Array.isArray(parsed)) using the safe fallback when parsing fails.

In `@kits/automation/Watchdog/package.json`:
- Line 30: The remark-gfm dependency in this kit's package.json is using a caret
range ("remark-gfm": "^4.0.1"); update the package.json entry for remark-gfm to
a pinned exact version (e.g., "remark-gfm": "4.0.1") so it no longer uses ^ or
~, and verify the file contains only explicitly pinned versions for all
dependencies in this kit (not relying on root/workspace hoisting).
🪄 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: b3544644-52fd-4b8c-8898-9f20fe6645c2

📥 Commits

Reviewing files that changed from the base of the PR and between b7edf0b and e00692f.

⛔ Files ignored due to path filters (2)
  • .DS_Store is excluded by !**/.DS_Store
  • kits/automation/Watchdog/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (7)
  • .github/workflows/validate-pr.yml
  • .gitignore
  • CONTRIBUTING.md
  • README.md
  • kits/automation/Watchdog/app/actions.ts
  • kits/automation/Watchdog/app/page.tsx
  • kits/automation/Watchdog/package.json

Comment on lines +237 to +239
{results.map((item, index) => (
<div
key={index}
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

Results rendered with index keys — acceptable given operational parameters.

While array indices as React keys are generally discouraged, the results array is replaced wholesale (never mutated in place), so React reconciliation risks are minimal here. The competitor list correctly uses stable UUIDs. Low-priority optimization if desired.

🔧 Optional: Add stable IDs to results

If results ever need to persist across partial updates, consider generating IDs during normalization:

const cleanResults: Result[] = rawResults.map((item: any, idx: number) => ({
  id: `result-${idx}-${Date.now()}`,
  org_name: item.org_name || "Unknown",
  response: item.response || (typeof item === "string" ? item : JSON.stringify(item)),
}));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/app/page.tsx` around lines 237 - 239, The current
JSX uses array index as the React key in the results rendering (results.map(...)
key={index}), which can be acceptable now but is fragible; update the rendering
to use a stable ID on each result instead of index: ensure the data
normalization that produces the results array attaches a stable identifier
(e.g., a result.id generated in the normalization step) and change the map key
to use that property (key={item.id}) so the component uses stable keys (refer to
results.map, key={index} and the result objects).

@HarshM1010
Copy link
Copy Markdown
Author

Hello @d-pamneja Thank you for the feedback. I've reverted all changes to the existing kits. Sorry for the inconvenience :)

@HarshM1010 HarshM1010 requested a review from d-pamneja April 2, 2026 17:22
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

PR Validation Results

New Contributions Detected

  • Kit: kits/automation/Watchdog

Check Results

Check Status
No edits to existing projects ✅ Pass
Required root files present ✅ Pass
Flow folder structure valid ✅ Pass
No changes outside contribution dirs ⚠️ Warning

Warnings

  • ⚠️ File outside kits/bundles/templates modified: .DS_Store
  • ⚠️ File outside kits/bundles/templates modified: .github/workflows/validate-pr.yml
  • ⚠️ File outside kits/bundles/templates modified: .gitignore
  • ⚠️ File outside kits/bundles/templates modified: CONTRIBUTING.md
  • ⚠️ File outside kits/bundles/templates modified: README.md

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

@HarshM1010 HarshM1010 force-pushed the feat/Add-Intelligent-Watchdog-automation-kit-for-competitor-intelligence branch from a96f40d to 1d78d46 Compare April 3, 2026 03:31
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 3, 2026

✅ Actions performed

Review triggered.

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
kits/automation/Watchdog/app/actions.ts (1)

59-88: 🛠️ Refactor suggestion | 🟠 Major

Mission directive: route Lamatic flow execution through the SDK client, not raw GraphQL fetch.

This action still performs direct fetch + inline executeWorkflow GraphQL. For kit server actions, align to the shared lib/lamatic-client.ts pattern and call the flow via SDK for consistency and centralized transport/error handling.

#!/bin/bash
# Verify current Watchdog action path and compare with SDK usage patterns.

echo "=== Watchdog action: raw fetch vs SDK import ==="
rg -n -C2 --type=ts "fetch\\(LAMATIC_API_URL|executeWorkflow|lamatic-client" kits/automation/Watchdog/app/actions.ts

echo ""
echo "=== Repo-wide Lamatic SDK patterns in kits ==="
rg -n -C2 --type=ts "from [\"']lamatic[\"']|lamaticClient" kits

Based on learnings: "Kit server action files (e.g., actions/orchestrate.ts) must call Lamatic flows via the SDK and read flow IDs from environment variables."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/app/actions.ts` around lines 59 - 88, Replace the
raw GraphQL fetch+AbortController logic (EXECUTE_WORKFLOW, AbortController,
fetch to LAMATIC_API_URL) with the shared SDK client: import the lamatic client
from lib/lamatic-client (e.g., lamaticClient or lamaticClient() used elsewhere)
and call its executeWorkflow method using WATCHDOG_FLOW_ID and payload: {
competitors }; remove the inline EXECUTE_WORKFLOW string and the manual
signal/timeout handling (or delegate timeout/error handling to the SDK), and
preserve/error-handle the response using the same pattern as other kit actions
(check success status/result and propagate/log errors consistently).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@kits/automation/Watchdog/app/actions.ts`:
- Around line 40-45: The rate-limit currently uses the raw header value from
headerList.get("x-forwarded-for") as the identity key which can be a
comma-separated, user-controlled chain; update the logic before calling
ratelimit.limit(ip) to extract and sanitize a single client IP (e.g., take the
first non-empty token from x-forwarded-for after splitting on commas, trim it,
validate it as an IP or fall back to headers.get("x-real-ip") or "127.0.0.1"),
then pass that canonicalized IP to ratelimit.limit; locate the ip variable
assignment and the call to ratelimit.limit in actions.ts and replace the naive
usage with this sanitized/validated value.

---

Duplicate comments:
In `@kits/automation/Watchdog/app/actions.ts`:
- Around line 59-88: Replace the raw GraphQL fetch+AbortController logic
(EXECUTE_WORKFLOW, AbortController, fetch to LAMATIC_API_URL) with the shared
SDK client: import the lamatic client from lib/lamatic-client (e.g.,
lamaticClient or lamaticClient() used elsewhere) and call its executeWorkflow
method using WATCHDOG_FLOW_ID and payload: { competitors }; remove the inline
EXECUTE_WORKFLOW string and the manual signal/timeout handling (or delegate
timeout/error handling to the SDK), and preserve/error-handle the response using
the same pattern as other kit actions (check success status/result and
propagate/log errors consistently).
🪄 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: 374b1f19-216c-494c-849d-d7f8fbc84811

📥 Commits

Reviewing files that changed from the base of the PR and between e00692f and b1c28ff.

📒 Files selected for processing (2)
  • .github/workflows/validate-pr.yml
  • kits/automation/Watchdog/app/actions.ts

Comment on lines +40 to +45
const headerList = await headers();
const ip = headerList.get("x-forwarded-for") || "127.0.0.1";

if (ratelimit) {
const { success } = await ratelimit.limit(ip);
if (!success) throw new Error("Too many requests. Please wait 60 seconds.");
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

Harden the rate-limit identity source before deployment.

Line 41 uses the raw x-forwarded-for header value as a key. That header can contain a comma-separated chain and can be user-influenced, which weakens effective limiting.

🛠️ Proposed hardening patch
-    const ip = headerList.get("x-forwarded-for") || "127.0.0.1";
+    const forwardedFor = headerList.get("x-forwarded-for");
+    const ip =
+      forwardedFor?.split(",")[0]?.trim() ||
+      headerList.get("x-real-ip") ||
+      "127.0.0.1";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/Watchdog/app/actions.ts` around lines 40 - 45, The rate-limit
currently uses the raw header value from headerList.get("x-forwarded-for") as
the identity key which can be a comma-separated, user-controlled chain; update
the logic before calling ratelimit.limit(ip) to extract and sanitize a single
client IP (e.g., take the first non-empty token from x-forwarded-for after
splitting on commas, trim it, validate it as an IP or fall back to
headers.get("x-real-ip") or "127.0.0.1"), then pass that canonicalized IP to
ratelimit.limit; locate the ip variable assignment and the call to
ratelimit.limit in actions.ts and replace the naive usage with this
sanitized/validated value.

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.

3 participants