-
Notifications
You must be signed in to change notification settings - Fork 92
Feat: Support Triage [agentkit-challenge] #80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
940d0c4
5e70655
69d4027
cbb842d
04f3aad
afe8151
51d3b9f
d696140
3f9c961
5c592b7
17a3de1
2fc331d
00fe5b3
8c6539c
689aa8a
b1e4705
053de0e
07516c3
2ae78f9
688183a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| LAMATIC_PROJECT_ENDPOINT= | ||
| LAMATIC_PROJECT_ID= | ||
| LAMATIC_PROJECT_API_KEY= | ||
| LAMATIC_FLOW_ID= |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
|
||
| # dependencies | ||
| /node_modules | ||
| /.pnp | ||
| .pnp.* | ||
| .yarn/* | ||
| !.yarn/patches | ||
| !.yarn/plugins | ||
| !.yarn/releases | ||
| !.yarn/versions | ||
|
|
||
| # testing | ||
| /coverage | ||
|
|
||
| # next.js | ||
| /.next/ | ||
| /out/ | ||
|
|
||
| # production | ||
| /build | ||
|
|
||
| # misc | ||
| .DS_Store | ||
| *.pem | ||
|
|
||
| # debug | ||
| npm-debug.log* | ||
| yarn-debug.log* | ||
| yarn-error.log* | ||
| .pnpm-debug.log* | ||
|
|
||
| # env files (can opt-in for committing if needed) | ||
| .env* | ||
|
|
||
| # vercel | ||
| .vercel | ||
|
|
||
| # typescript | ||
| *.tsbuildinfo | ||
| next-env.d.ts | ||
| !.env.example | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a live demo link to this file? would allow us to view the functionality better, and allow users to see the kit before forking it. otherwise, LGTM. Thanks! Will check once that is fixed and github action will be handled
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @d-pamneja I already have added the live demo link to the README! You can also test the deployment here: https://agent-kit-ten.vercel.app/ Thanks for the review. Let me know if you need anything else to unblock the merge.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @d-pamneja Sorry for that! I had hardcoded the text colors for a dark theme and missed the light mode toggle. I've updated the Tailwind classes to properly support both light and dark system preferences. The Vercel deployment has been automatically updated with the fix. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # AI Support Triage Engine | ||
|
|
||
| ## What This Kit Does | ||
| Automates customer support by taking inbound tickets and instantly generating a category, sentiment analysis, urgency level, and a draft email response. This saves time, reduces manual routing work, and improves response clarity. | ||
|
|
||
| ## Providers & Prerequisites | ||
| - Lamatic Studio Flow | ||
| - Gemini Free Tier (Note: Requires a 60-second cooldown between requests to prevent 429 Rate Limit errors). | ||
|
|
||
| ## How to Run Locally | ||
| 1. `cd kits/automation/support-triage` | ||
| 2. `npm install` | ||
| 3. `cp .env.example .env.local` and fill in your Lamatic API values. | ||
| 4. `npm run dev` | ||
amanintech marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ## Lamatic Flow | ||
| Flow ID: `your-flow-id` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import { Lamatic } from 'lamatic'; | ||
| import { NextRequest, NextResponse } from 'next/server'; | ||
|
|
||
| export async function POST(request: NextRequest) { | ||
| try { | ||
| const endpoint = process.env.LAMATIC_PROJECT_ENDPOINT; | ||
| const projectId = process.env.LAMATIC_PROJECT_ID; | ||
| const apiKey = process.env.LAMATIC_PROJECT_API_KEY; | ||
| const flowId = process.env.LAMATIC_FLOW_ID; | ||
|
|
||
| // Fails fast and safely if env vars are missing | ||
| if (!endpoint || !projectId || !apiKey || !flowId) { | ||
| return NextResponse.json( | ||
| { error: "Missing required Lamatic environment variables on the server." }, | ||
| { status: 500 } | ||
| ); | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| const lamaticClient = new Lamatic({ endpoint, projectId, apiKey }); | ||
| const { ticket_text } = await request.json(); | ||
|
|
||
| const response = await lamaticClient.executeFlow(flowId, { ticket_text }); | ||
| return NextResponse.json(response); | ||
amanintech marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+4
to
+23
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== Verify /api/token route exists =="
fd -i 'route\.ts$' kits/automation/support-triage/app/api/token
echo
echo "== Verify JWT issuance/verification usage in support-triage API routes =="
rg -nP --type=ts -C2 'SignJWT|jwtVerify|HS256|JWT_SECRET|authorization' kits/automation/support-triage/app/apiRepository: Lamatic/AgentKit Length of output: 245 🏁 Script executed: # Search entire support-triage codebase for JWT/token references
find kits/automation/support-triage -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name ".env*" -o -name "*.json" \) | head -20Repository: Lamatic/AgentKit Length of output: 475 🏁 Script executed: # Look for jose library usage or JWT references across entire triage kit
rg -i 'jose|jwtverify|signjwt|jwt_secret|authorization.*bearer' kits/automation/support-triage --type=ts --type=tsx --type=json -lRepository: Lamatic/AgentKit Length of output: 87 🏁 Script executed: # Check the actual triage route file to see complete implementation including error handling
cat kits/automation/support-triage/app/api/triage/route.tsRepository: Lamatic/AgentKit Length of output: 1186 🏁 Script executed: # Check config.json and .env files for environment variable naming
find kits/automation/support-triage -name "config.json" -o -name ".env*" | xargs cat 2>/dev/nullRepository: Lamatic/AgentKit Length of output: 1237 This mission cannot be accepted in its current state: Your route processes API requests on line 4 without verifying bearer tokens. This exposes the Lamatic flow to unauthorized abuse and quota exhaustion. Additionally, your Critical blockers:
🔐 JWT verification patch (before line 20) import { Lamatic } from 'lamatic';
+import { jwtVerify } from 'jose';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
try {
+ const authHeader = request.headers.get("authorization");
+ if (!authHeader?.startsWith("Bearer ")) {
+ return NextResponse.json({ error: "Missing bearer token." }, { status: 401 });
+ }
+
+ const jwtSecret = process.env.JWT_SECRET;
+ if (!jwtSecret) {
+ return NextResponse.json({ error: "Missing JWT_SECRET on server." }, { status: 500 });
+ }
+
+ try {
+ const token = authHeader.slice("Bearer ".length);
+ await jwtVerify(token, new TextEncoder().encode(jwtSecret), {
+ algorithms: ["HS256"],
+ });
+ } catch {
+ return NextResponse.json({ error: "Invalid or expired token." }, { status: 401 });
+ }
+
const endpoint = process.env.LAMATIC_PROJECT_ENDPOINT;Outstanding issues from prior review:
🤖 Prompt for AI Agents |
||
|
|
||
| } catch (error: unknown) { | ||
| // Safely narrows the 'unknown' error type | ||
| const errorMessage = error instanceof Error ? error.message : "API execution failed"; | ||
| return NextResponse.json({ error: errorMessage }, { status: 500 }); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| @import "tailwindcss"; | ||
|
|
||
| :root { | ||
| --background: #ffffff; | ||
| --foreground: #171717; | ||
| } | ||
|
|
||
| @theme inline { | ||
amanintech marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| --color-background: var(--background); | ||
| --color-foreground: var(--foreground); | ||
| --font-sans: var(--font-geist-sans); | ||
| --font-mono: var(--font-geist-mono); | ||
| } | ||
|
|
||
| @media (prefers-color-scheme: dark) { | ||
| :root { | ||
| --background: #0a0a0a; | ||
| --foreground: #ededed; | ||
| } | ||
| } | ||
|
|
||
| body { | ||
| background: var(--background); | ||
| color: var(--foreground); | ||
| font-family: var(--font-sans), Arial, Helvetica, sans-serif; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import type { Metadata } from "next"; | ||
| import { Geist, Geist_Mono } from "next/font/google"; | ||
| import "./globals.css"; | ||
|
|
||
| const geistSans = Geist({ | ||
| variable: "--font-geist-sans", | ||
| subsets: ["latin"], | ||
| }); | ||
|
|
||
| const geistMono = Geist_Mono({ | ||
| variable: "--font-geist-mono", | ||
| subsets: ["latin"], | ||
| }); | ||
|
|
||
| export const metadata = { | ||
| title: "AI Support Triage Engine", | ||
| description: "Automated customer support ticket categorization, sentiment analysis, and draft response generation", | ||
| }; | ||
|
|
||
| export default function RootLayout({ | ||
| children, | ||
| }: Readonly<{ | ||
| children: React.ReactNode; | ||
| }>) { | ||
| return ( | ||
| <html | ||
| lang="en" | ||
| className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`} | ||
| suppressHydrationWarning | ||
| > | ||
| <body className="min-h-full flex flex-col">{children}</body> | ||
| </html> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,169 @@ | ||
| 'use client'; | ||
| import React, { useState } from 'react'; | ||
|
|
||
| export default function Page() { | ||
| const [ticketText, setTicketText] = useState(''); | ||
| const [loading, setLoading] = useState(false); | ||
| const [triageData, setTriageData] = useState<any>(null); | ||
|
|
||
| const executeFlow = async () => { | ||
| const normalizedTicket = ticketText.trim(); | ||
| if (!normalizedTicket) { | ||
| setTriageData({ error: "Please enter a ticket before processing." }); | ||
| return; | ||
| } | ||
|
|
||
| setLoading(true); | ||
| setTriageData(null); | ||
|
|
||
| try { | ||
| const res = await fetch('/api/triage', { | ||
| method: 'POST', | ||
| headers: { 'Content-Type': 'application/json' }, | ||
| body: JSON.stringify({ ticket_text: normalizedTicket }) | ||
| }); | ||
amanintech marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| const response = await res.json(); | ||
| const data = response.result || response; | ||
|
|
||
| // Improved Rate Limit Detection | ||
| const message = typeof data?.message === 'string' ? data.message.toLowerCase() : ''; | ||
| const isRateLimited = message.includes('quota') || message.includes('rate limit') || data?.status === 429; | ||
|
|
||
| if (isRateLimited) { | ||
| setTriageData({ error: "API Rate Limit: Free tier restricted. Please wait 60 seconds before testing the next ticket." }); | ||
| } else if (data.error) { | ||
amanintech marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| setTriageData({ error: data.error }); | ||
| } else { | ||
| setTriageData(data); | ||
| } | ||
|
|
||
| } catch (error) { | ||
| console.error("Execution error:", error); | ||
| setTriageData({ error: "Failed to connect to AI triage." }); | ||
| } finally { | ||
| setLoading(false); | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="min-h-screen bg-gradient-to-br from-indigo-50 via-white to-cyan-100 dark:from-gray-950 dark:via-gray-900 dark:to-black text-gray-900 dark:text-gray-100 p-4 md:p-8 font-sans selection:bg-blue-500/30"> | ||
| <div className="max-w-3xl mx-auto space-y-8 mt-10 md:mt-20"> | ||
|
|
||
| {/* Header */} | ||
| <div className="text-center space-y-4"> | ||
| <div className="inline-flex items-center justify-center p-2 bg-blue-100 dark:bg-blue-500/10 rounded-full mb-4 border border-blue-200 dark:border-blue-500/20"> | ||
| <span className="text-blue-600 dark:text-blue-400 text-xs font-bold tracking-widest uppercase px-3">AgentKit Challenge</span> | ||
| </div> | ||
| <h1 className="text-4xl md:text-5xl font-extrabold tracking-tight text-gray-900 dark:text-transparent dark:bg-clip-text dark:bg-gradient-to-r dark:from-blue-400 dark:via-indigo-400 dark:to-purple-400 pb-2"> | ||
| AI Support Triage Engine | ||
| </h1> | ||
| <p className="text-gray-600 dark:text-gray-400 text-lg max-w-xl mx-auto"> | ||
| Instantly categorize issues, analyze customer sentiment, and draft responses using Lamatic flows. | ||
| </p> | ||
| </div> | ||
|
|
||
| {/* Input Card */} | ||
| <div className="bg-white dark:bg-white/[0.02] backdrop-blur-xl border border-gray-200 dark:border-white/10 rounded-2xl p-6 md:p-8 shadow-xl dark:shadow-2xl"> | ||
| <label htmlFor="ticketText" className="block text-sm font-semibold text-gray-700 dark:text-gray-300 mb-3 uppercase tracking-wider"> | ||
| Inbound Customer Ticket | ||
| </label> | ||
| <textarea | ||
| id="ticketText" | ||
| className="w-full p-5 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl focus:ring-2 focus:ring-blue-500/50 outline-none resize-none text-gray-900 dark:text-gray-100 placeholder-gray-400 shadow-sm transition-all duration-300" | ||
| value={ticketText} | ||
| onChange={(e) => setTicketText(e.target.value)} | ||
| placeholder="I was overcharged by $50 on my invoice today and I am furious!" | ||
| spellCheck="false" | ||
| /> | ||
|
|
||
| <button | ||
| onClick={executeFlow} | ||
| disabled={loading} | ||
| className="mt-6 w-full group relative overflow-hidden bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-500 hover:to-indigo-500 disabled:from-gray-300 disabled:to-gray-400 dark:disabled:from-gray-800 dark:disabled:to-gray-900 disabled:text-gray-500 text-white font-bold py-4 px-6 rounded-xl transition-all duration-300 shadow-md dark:shadow-[0_0_20px_rgba(79,70,229,0.2)] hover:shadow-lg dark:hover:shadow-[0_0_30px_rgba(79,70,229,0.4)] disabled:shadow-none flex justify-center items-center" | ||
| > | ||
| {loading ? ( | ||
| <span className="flex items-center gap-2"> | ||
| <svg className="animate-spin h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> | ||
| <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle> | ||
| <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> | ||
| </svg> | ||
| Processing Ticket... | ||
| </span> | ||
| ) : 'Process Ticket'} | ||
| </button> | ||
| </div> | ||
|
|
||
| {/* Error State */} | ||
| {triageData?.error && ( | ||
| <div className="bg-red-50 dark:bg-red-500/10 border border-red-200 dark:border-red-500/20 rounded-xl p-5 flex items-start gap-4"> | ||
| <div className="bg-red-100 dark:bg-red-500/20 p-2 rounded-full mt-0.5"> | ||
| <svg className="w-5 h-5 text-red-600 dark:text-red-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /> | ||
| </svg> | ||
| </div> | ||
| <div> | ||
| <h3 className="text-red-800 dark:text-red-400 font-bold">Execution Error</h3> | ||
| <p className="text-red-600 dark:text-red-300/80 text-sm mt-1">{triageData.error}</p> | ||
| </div> | ||
| </div> | ||
| )} | ||
|
|
||
| {/* Results Area */} | ||
| {triageData && !triageData.error && ( | ||
| <div className="space-y-6 animate-in fade-in slide-in-from-bottom-4 duration-700"> | ||
| {/* Metrics Grid */} | ||
| <div className="grid grid-cols-1 md:grid-cols-3 gap-4"> | ||
| <div className="bg-white dark:bg-white/[0.02] border border-gray-200 dark:border-white/10 rounded-xl p-6 shadow-md dark:shadow-lg backdrop-blur-md"> | ||
| <div className="flex items-center gap-3 mb-2"> | ||
| <div className="w-2 h-2 rounded-full bg-blue-500 dark:bg-blue-400 shadow-[0_0_10px_rgba(59,130,246,0.5)] dark:shadow-[0_0_10px_rgba(96,165,250,0.8)]"></div> | ||
| <p className="text-xs text-gray-500 dark:text-gray-400 uppercase tracking-widest font-semibold">Category</p> | ||
| </div> | ||
| <p className="text-2xl font-bold text-gray-900 dark:text-gray-100">{triageData.category || 'N/A'}</p> | ||
| </div> | ||
|
|
||
| <div className="bg-white dark:bg-white/[0.02] border border-gray-200 dark:border-white/10 rounded-xl p-6 shadow-md dark:shadow-lg backdrop-blur-md"> | ||
| <div className="flex items-center gap-3 mb-2"> | ||
| <div className="w-2 h-2 rounded-full bg-emerald-500 dark:bg-emerald-400 shadow-[0_0_10px_rgba(16,185,129,0.5)] dark:shadow-[0_0_10px_rgba(52,211,153,0.8)]"></div> | ||
| <p className="text-xs text-gray-500 dark:text-gray-400 uppercase tracking-widest font-semibold">Sentiment</p> | ||
| </div> | ||
| <p className="text-2xl font-bold text-gray-900 dark:text-gray-100">{triageData.sentiment || 'N/A'}</p> | ||
| </div> | ||
|
|
||
| <div className="bg-white dark:bg-white/[0.02] border border-gray-200 dark:border-white/10 rounded-xl p-6 shadow-md dark:shadow-lg backdrop-blur-md"> | ||
| <div className="flex items-center gap-3 mb-2"> | ||
| <div className="w-2 h-2 rounded-full bg-rose-500 dark:bg-rose-400 shadow-[0_0_10px_rgba(244,63,94,0.5)] dark:shadow-[0_0_10px_rgba(251,113,133,0.8)]"></div> | ||
| <p className="text-xs text-gray-500 dark:text-gray-400 uppercase tracking-widest font-semibold">Urgency</p> | ||
| </div> | ||
| <p className="text-2xl font-bold text-gray-900 dark:text-gray-100">{triageData.urgency || 'N/A'}</p> | ||
| </div> | ||
| </div> | ||
|
|
||
| {/* AI Draft Response */} | ||
| <div className="bg-white dark:bg-white/[0.02] border border-gray-200 dark:border-white/10 rounded-xl overflow-hidden shadow-md dark:shadow-lg backdrop-blur-md"> | ||
| <div className="bg-gray-50 dark:bg-white/[0.02] border-b border-gray-200 dark:border-white/10 px-6 py-4 flex items-center justify-between"> | ||
| <p className="text-sm font-semibold text-indigo-600 dark:text-indigo-400 flex items-center gap-2"> | ||
| <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 10V3L4 14h7v7l9-11h-7z" /> | ||
| </svg> | ||
| Generated AI Draft | ||
| </p> | ||
| </div> | ||
| <div className="p-6 bg-white dark:bg-black/20"> | ||
| <p className="text-sm md:text-base leading-relaxed whitespace-pre-wrap text-gray-800 dark:text-gray-300 font-medium"> | ||
| {triageData.draft || JSON.stringify(triageData, null, 2)} | ||
| </p> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| )} | ||
| {/* Subtle Credit Footer */} | ||
| <div className="text-center pt-8 pb-4"> | ||
| <p className="text-gray-400 dark:text-gray-500 text-sm"> | ||
| Built for the AgentKit Challenge by Yash Singhal | ||
| </p> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| { | ||
| "name": "AI Support Triage Engine", | ||
| "description": "Automated triage system that categorizes, analyzes sentiment, and drafts responses for customer support tickets.", | ||
| "tags": ["🤖 Automation", "💬 Assistant"], | ||
| "author": { | ||
| "name": "Yash Singhal", | ||
| "email": "yashjee979@gmail.com", | ||
| "url": "https://github.com/VITianYash42" | ||
| }, | ||
| "steps": [ | ||
| { | ||
| "id": "your-flow-id", | ||
| "type": "mandatory", | ||
| "envKey": "NEXT_PUBLIC_LAMATIC_FLOW_ID" | ||
| } | ||
| ], | ||
| "integrations": [ | ||
| { | ||
| "name": "Lamatic Studio Flow", | ||
| "type": "AI Framework" | ||
| }, | ||
| { | ||
| "name": "Gemini Free Tier", | ||
| "type": "LLM" | ||
| } | ||
| ], | ||
| "features": ["Sentiment Analysis", "Auto-Drafting", "Urgency Detection"], | ||
| "demoUrl": "https://agent-kit-git-feat-suppo-3f22fd-yash-singhals-projects-d43367ba.vercel.app/", | ||
| "githubUrl": "https://github.com/VITianYash42/AgentKit/tree/feat/support-triage/kits/automation/support-triage", | ||
| "deployUrl": "", | ||
| "documentationUrl": "" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import { defineConfig, globalIgnores } from "eslint/config"; | ||
| import nextVitals from "eslint-config-next/core-web-vitals"; | ||
| import nextTs from "eslint-config-next/typescript"; | ||
|
|
||
| const eslintConfig = defineConfig([ | ||
| ...nextVitals, | ||
| ...nextTs, | ||
| // Override default ignores of eslint-config-next. | ||
| globalIgnores([ | ||
| // Default ignores of eslint-config-next: | ||
| ".next/**", | ||
| "out/**", | ||
| "build/**", | ||
| "next-env.d.ts", | ||
| ]), | ||
| ]); | ||
|
|
||
| export default eslintConfig; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # Support Triage Flow | ||
| This flow takes an inbound customer ticket and automatically routes it based on category and sentiment. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "name": "Support Triage Flow", | ||
| "type": "flow" | ||
| } |

Uh oh!
There was an error while loading. Please reload this page.