diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index 8cf0305f..00000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "permissions": { - "allow": [ - "Skill(lua-agent-builder:lua-architect)", - "Bash(lua agents *)", - "Bash(echo \"EXIT:$?\")", - "Bash(lua --version)", - "Bash(lua init *)", - "Bash(lua compile *)", - "Bash(lua test *)", - "PowerShell(Start-Process \"C:\\\\Users\\\\Elitebook\\\\OneDrive\\\\Documents\\\\PROJECTS\\\\TechSafari x Lua\\\\TechSafari x Lua\\\\index.html\")", - "Bash(lua push *)", - "Bash(git init *)", - "Bash(git add *)", - "Bash(git commit *)", - "Bash(lua sync *)", - "Bash(lua status *)", - "Read(//c/Users/Elitebook/.claude/**)", - "Bash(find /usr -name \"confirm-deploy.mjs\")", - "Bash(LUA_DEPLOY_CONFIRMED=1 lua deploy *)", - "Bash(lua logs *)", - "Bash(lua chat *)", - "Bash(lua whoami *)", - "Bash(curl -s -X POST https://api.heylua.ai/v1/skills/score-role/invoke -H 'Authorization: Bearer api_403f64cd0f8b4e3b97c2c98443508e84' -H 'Content-Type: application/json' -d '{\"agentId\":\"baseAgent_agent_1779215133611_x0svb7j5d\",\"input\":{\"jdText\":\"Head of Sales. Lead a 10-person sales team, own enterprise pipeline from prospecting to close, negotiate seven-figure contracts, represent the company at industry events. 10 plus years B2B sales leadership required.\",\"volume\":\"low\",\"stakes\":\"high\",\"exposure\":\"executive\"}}')", - "Bash(curl -s -X POST https://api.heylua.ai/v1/agents/baseAgent_agent_1779215133611_x0svb7j5d/chat -H 'Authorization: Bearer api_403f64cd0f8b4e3b97c2c98443508e84' -H 'Content-Type: application/json' -d '{\"message\":\"Score this JD: Head of Sales. Lead a 10-person sales team, own enterprise pipeline from prospecting to close, negotiate seven-figure contracts. 10 plus years B2B sales leadership required.\"}')", - "Bash(curl -s \"https://api.heylua.ai/\")", - "Bash(curl -s \"https://api.heylua.ai/v1/\")", - "Bash(node -e ' *)", - "Bash(curl *)", - "Bash(lua env *)", - "Bash(npx --yes serve . -p 3000)", - "PowerShell(Start-Process \"http://localhost:3000\")", - "PowerShell(Start-Process powershell -ArgumentList \"-NoExit\", \"-Command\", \"cd 'C:\\\\Users\\\\Elitebook\\\\OneDrive\\\\Documents\\\\PROJECTS\\\\TechSafari x Lua\\\\TechSafari x Lua'; npx serve . -p 3000\" -WindowStyle Minimized)", - "PowerShell(node -e \"const lua = require\\('lua-cli'\\); console.log\\(Object.keys\\(lua\\).filter\\(k => k.toLowerCase\\(\\).includes\\('data'\\) || k.toLowerCase\\(\\).includes\\('store'\\) || k.toLowerCase\\(\\).includes\\('db'\\)\\)\\)\" 2>&1)", - "PowerShell(node -e \"const { Data } = require\\('lua-cli'\\); console.log\\(Object.getOwnPropertyNames\\(Data\\).join\\('\\\\n'\\)\\); console.log\\('prototype:', Object.getOwnPropertyNames\\(Data.prototype||{}\\).join\\('\\\\n'\\)\\)\" 2>&1)", - "Skill(lua-agent-builder:lua-deploy)", - "Bash(python3 -c ' *)", - "Bash(git push *)", - "Bash(git *)", - "Bash(node *)" - ] - } -} diff --git a/.gitignore b/.gitignore index 1d06ba0d..6928aab6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,12 @@ dist-v2/ -node_modules +node_modules/ + +.env + +# Claude Code local settings — contains approved bash commands with secrets +.claude/settings.local.json + +# Local mock server (confirm frontend render without the slow upstream) — not for commit +mock-server.mjs +mock-check.mjs diff --git a/.lua/backup-manifest.json b/.lua/backup-manifest.json index bbf502d5..5bfd8e90 100644 --- a/.lua/backup-manifest.json +++ b/.lua/backup-manifest.json @@ -1,10 +1,66 @@ { - "lastHash": "e47bdc60bc8cef6a77170bcaa08d07ce2bfd430242df2b8b69fc8f194418ffcc", - "lastPushedAt": "2026-05-25T13:28:49.508Z", + "lastHash": "3593183c55e79306bbd8b16cdc95c92f38b8c24e1e828788525fccb0abe986f8", + "lastPushedAt": "2026-06-05T14:45:32.947Z", "files": [ + { + "relativePath": "api/_lib/origin.js", + "hash": "abc2037d9a2ad20e" + }, + { + "relativePath": "api/_lib/rate-limit.js", + "hash": "086e410e25685975" + }, + { + "relativePath": "api/_lib/stream-aggregate.js", + "hash": "252e08e4d10c2705" + }, + { + "relativePath": "api/fetch-jd.js", + "hash": "1c548362212ba216" + }, + { + "relativePath": "api/lua-chat.js", + "hash": "169fcb41a92086b0" + }, + { + "relativePath": "api/slack-notify.js", + "hash": "77352a502849a493" + }, { "relativePath": "build.md", - "hash": "4b80192c6471a386" + "hash": "4722e1e36284660f" + }, + { + "relativePath": "changes.md", + "hash": "001ebaabc0f049c9" + }, + { + "relativePath": "dev-server.mjs", + "hash": "7ae969c564777cae" + }, + { + "relativePath": "docs/fixes/ada_persona.md", + "hash": "68c8cab666ced769" + }, + { + "relativePath": "docs/fixes/bug_fix.md", + "hash": "07df360e65a9a31a" + }, + { + "relativePath": "docs/fixes/fix_ada_flow.md", + "hash": "c6f46dc6c54420db" + }, + { + "relativePath": "docs/fixes/UI_change.md", + "hash": "1511b4efa823e5cf" + }, + { + "relativePath": "docs/llm.md/llm.md", + "hash": "fcd49fb3510ebb68" + }, + { + "relativePath": "email-preview.html", + "hash": "3d541bd6f57a64fa" }, { "relativePath": "env.example", @@ -12,19 +68,75 @@ }, { "relativePath": "index.html", - "hash": "c6e24e63fa8aa6d2" + "hash": "c27047560bef8dbb" }, { "relativePath": "lua.skill.yaml", - "hash": "cd09d861d731c2f3" + "hash": "603f990682f37e06" }, { "relativePath": "netlify.toml", - "hash": "2bc5bc6e341c5e81" + "hash": "7bcd116156bdee81" + }, + { + "relativePath": "netlify/functions/fetch-jd.js", + "hash": "99372ecf4067d76b" + }, + { + "relativePath": "netlify/functions/lua-chat.js", + "hash": "b8a3883e4b99c1a9" + }, + { + "relativePath": "netlify/functions/score-jd.js", + "hash": "83da42d230e001ba" + }, + { + "relativePath": "netlify/functions/slack-notify.js", + "hash": "eb8d2040c636852a" }, { "relativePath": "package.json", - "hash": "110536777933a2d1" + "hash": "d56bbe348b9f62fd" + }, + { + "relativePath": "plan.md", + "hash": "e2ed46d402b4ed4b" + }, + { + "relativePath": "public/lua-logo-full.png", + "hash": "eed9c85376590bff" + }, + { + "relativePath": "public/lua-logo.png", + "hash": "0af27ad79ca12ed3" + }, + { + "relativePath": "public/lua-logo.svg", + "hash": "74f974fe0c331daf" + }, + { + "relativePath": "public/social-facebook.png", + "hash": "9070f98432588ddd" + }, + { + "relativePath": "public/social-instagram.png", + "hash": "d83c19d486196643" + }, + { + "relativePath": "public/social-linkedin.png", + "hash": "c3c32e06e79f35ac" + }, + { + "relativePath": "public/talent-safari-logo.jpg", + "hash": "1802a5db225825a5" + }, + { + "relativePath": "public/talent-safari-logo.png", + "hash": "bd44edad815d44bf" + }, + { + "relativePath": "public/talent-safari-logo1.jpg", + "hash": "b2f21158b02085a1" }, { "relativePath": "public/talentsafari_logo.jpg", @@ -38,9 +150,13 @@ "relativePath": "README.md", "hash": "2ca2d2b3168e75e5" }, + { + "relativePath": "sheets-apps-script.gs", + "hash": "634b71f65a75a8e5" + }, { "relativePath": "src/index.ts", - "hash": "2444f8afe5be524f" + "hash": "e96c585c90fbeb4d" }, { "relativePath": "src/skills/ada-chat.skill.ts", @@ -52,19 +168,23 @@ }, { "relativePath": "src/skills/capture-lead.skill.ts", - "hash": "07abb33d708827c9" + "hash": "fea1652d9b341d83" + }, + { + "relativePath": "src/skills/email-assets.ts", + "hash": "fe0b285247485488" }, { "relativePath": "src/skills/score-role.skill.ts", - "hash": "6c1eeb871d522684" + "hash": "336d837f8454e942" }, { "relativePath": "src/skills/scrape-jd.skill.ts", - "hash": "ae4336460784add0" + "hash": "35d0e547fcbce515" }, { "relativePath": "src/skills/submit-cta.skill.ts", - "hash": "959e71e2d4166df1" + "hash": "dc40341bc7b3999e" }, { "relativePath": "src/skills/tools/CaptureLead.ts", @@ -85,6 +205,10 @@ { "relativePath": "tsconfig.json", "hash": "748d6fffca1cc9ce" + }, + { + "relativePath": "vercel.json", + "hash": "74835210ba9078b4" } ] } \ No newline at end of file diff --git a/api/_lib/origin.js b/api/_lib/origin.js new file mode 100644 index 00000000..f465a0d8 --- /dev/null +++ b/api/_lib/origin.js @@ -0,0 +1,43 @@ +// Shared origin allowlist for all /api/* functions. +// +// Allowed origins come from three sources: +// 1. ALLOWED_ORIGINS env var (comma-separated, set per environment in Vercel) +// 2. Vercel's auto-injected URLs: VERCEL_URL, VERCEL_BRANCH_URL, VERCEL_PROJECT_PRODUCTION_URL +// (these are hostnames without protocol — we prepend https:// before comparing) +// 3. Common local dev origins (vercel dev, vite, plain http servers) +// +// Defeats casual browser-based abuse from other sites. Curl/server-to-server requests +// with forged Origin headers can still hit the endpoint — for production-scale abuse +// protection, add a rate limiter (Upstash Redis / Vercel KV) keyed on req.headers +// ['x-forwarded-for']. + +const DEFAULT_DEV_ORIGINS = [ + 'http://localhost:3000', + 'http://localhost:5173', + 'http://localhost:8000', + 'http://localhost:8080', + 'http://127.0.0.1:3000', + 'http://127.0.0.1:5173', +]; + +function buildAllowedOrigins() { + const fromEnv = (process.env.ALLOWED_ORIGINS || '') + .split(',').map((o) => o.trim()).filter(Boolean); + + const vercelHosts = [ + process.env.VERCEL_URL, + process.env.VERCEL_BRANCH_URL, + process.env.VERCEL_PROJECT_PRODUCTION_URL, + ].filter(Boolean); + const vercelOrigins = vercelHosts.map((h) => `https://${h}`); + + return new Set([...fromEnv, ...vercelOrigins, ...DEFAULT_DEV_ORIGINS]); +} + +export function isOriginAllowed(origin, host) { + if (!origin) return false; + const allowed = buildAllowedOrigins(); + if (allowed.has(origin)) return true; + // Same-origin fallback: Origin host matches the request host (e.g. preview deploys). + try { return new URL(origin).host === host; } catch { return false; } +} diff --git a/api/_lib/rate-limit.js b/api/_lib/rate-limit.js new file mode 100644 index 00000000..a3802c85 --- /dev/null +++ b/api/_lib/rate-limit.js @@ -0,0 +1,113 @@ +// Per-IP sliding-window rate limiter backed by Vercel KV (Upstash Redis). +// +// Each (route, ip) pair gets its own ZSET keyed `rl::s:`. +// Members are unique timestamp-suffixed tokens; scores are millisecond timestamps. +// On every call we atomically (MULTI/EXEC): +// 1. Drop members older than `now - windowMs` (ZREMRANGEBYSCORE) +// 2. Insert the current request (ZADD) +// 3. Count remaining members (ZCARD) +// 4. Refresh the key TTL (PEXPIRE) +// 5. Read the oldest remaining score (ZRANGE 0 0 WITHSCORES) — for resetAt +// +// If KV env vars are missing (local dev, preview without KV) we no-op with allowed:true. +// If a KV call throws (transient network) we also fail open — we'd rather serve a real +// user than 500 the whole site over a rate-limiter outage. + +import { kv } from '@vercel/kv'; + +let kvMissingWarned = false; + +function isKvConfigured() { + return Boolean(process.env.KV_REST_API_URL && process.env.KV_REST_API_TOKEN); +} + +function clientIp(req) { + const xff = req.headers['x-forwarded-for']; + if (typeof xff === 'string' && xff.length > 0) { + const first = xff.split(',')[0].trim(); + if (first) return first; + } + const xri = req.headers['x-real-ip']; + if (typeof xri === 'string' && xri.trim()) return xri.trim(); + // Shared bucket for unknown IPs — intentionally the *most* rate-limited path, + // not an unlimited bypass. + return 'unknown'; +} + +export async function checkRateLimit(req, { route, limit, windowSeconds }) { + if (!isKvConfigured()) { + if (!kvMissingWarned) { + kvMissingWarned = true; + console.warn('[rate-limit] KV_REST_API_URL / KV_REST_API_TOKEN not set — rate limiting disabled'); + } + return { allowed: true, remaining: limit, resetAt: 0 }; + } + + const ip = clientIp(req); + const now = Date.now(); + const windowMs = windowSeconds * 1000; + const cutoff = now - windowMs; + const key = `rl:${route}:${windowSeconds}s:${ip}`; + const member = `${now}-${Math.random().toString(36).slice(2, 10)}`; + + try { + const tx = kv.multi(); + tx.zremrangebyscore(key, 0, cutoff); + tx.zadd(key, { score: now, member }); + tx.zcard(key); + tx.pexpire(key, windowMs + 1000); + tx.zrange(key, 0, 0, { withScores: true }); + const results = await tx.exec(); + + // results: [removed, added, count, expireOk, oldestEntry] + const count = Number(results[2] ?? 0); + const oldestScore = parseOldestScore(results[4], now); + const resetAt = oldestScore + windowMs; + const allowed = count <= limit; + const remaining = Math.max(0, limit - count); + return { allowed, remaining, resetAt }; + } catch (err) { + console.error('[rate-limit] KV error, failing open:', err?.message || err); + return { allowed: true, remaining: limit, resetAt: 0 }; + } +} + +// @upstash/redis has shipped ZRANGE WITHSCORES in two shapes across versions: +// flat [member, score, ...] and [{ member, score }, ...]. Tolerate both, fall +// back to `now` (gives resetAt = now + windowMs, a safe worst-case upper bound). +function parseOldestScore(entry, fallbackNow) { + if (!Array.isArray(entry) || entry.length === 0) return fallbackNow; + if (entry.length >= 2 && (typeof entry[1] === 'number' || typeof entry[1] === 'string')) { + const n = Number(entry[1]); + if (Number.isFinite(n)) return n; + } + const first = entry[0]; + if (first && typeof first === 'object') { + const n = Number(first.score); + if (Number.isFinite(n)) return n; + } + return fallbackNow; +} + +// Pick the stricter of two checkRateLimit results: any block wins; among blocks, +// the one with the latest resetAt; among allows, the one with the lowest remaining. +export function pickStricter(a, b) { + if (!a.allowed && !b.allowed) return a.resetAt >= b.resetAt ? a : b; + if (!a.allowed) return a; + if (!b.allowed) return b; + return a.remaining <= b.remaining ? a : b; +} + +// Send a 429 with standard rate-limit headers and a JSON body the FE can read. +export function send429(res, { route, result }) { + const retryAfterSec = Math.max(1, Math.ceil((result.resetAt - Date.now()) / 1000)); + res.setHeader('Retry-After', String(retryAfterSec)); + res.setHeader('X-RateLimit-Remaining', String(result.remaining)); + res.setHeader('X-RateLimit-Reset', String(Math.ceil(result.resetAt / 1000))); + return res.status(429).json({ + error: 'Too Many Requests', + route, + retryAfterSeconds: retryAfterSec, + resetAt: new Date(result.resetAt).toISOString(), + }); +} diff --git a/api/_lib/stream-aggregate.js b/api/_lib/stream-aggregate.js new file mode 100644 index 00000000..10844b6a --- /dev/null +++ b/api/_lib/stream-aggregate.js @@ -0,0 +1,88 @@ +// Aggregates a Lua `/chat/stream/:agentId` SSE response into the SAME +// `{ text, steps: [{ toolResults }] }` shape that `/chat/generate` returns — +// so every existing caller of the /api/lua-chat proxy keeps working unchanged. +// +// Why we stream instead of calling /generate: a synchronous /generate call holds +// the connection open with zero bytes until the (sometimes >60s) agent run finishes, +// which trips an upstream ~60s gateway timeout and returns an HTML error page. +// /stream emits events continuously (heartbeats, text-deltas, tool events), keeping +// the connection alive, so the run completes (~45-50s observed) without timing out. +// +// Observed stream event shapes (newline-delimited JSON, occasionally `data:`-prefixed): +// { "type": "text-delta", "textDelta": "..." } -> agent reply text +// { "type": "tool-result", "toolResult": "" } -> tool output +// where JSON.parse(toolResult) = { args, toolCallId, toolName, result } +// { "type": "tool" | "system" | "heartbeat", ... } -> ignored here +// +// The frontend reads result.steps[].toolResults[].{toolName,result} and data.text, +// so we emit exactly those. + +export function makeStreamAggregator() { + let buffer = ''; + let text = ''; + const toolResults = []; + + function handleLine(line) { + const trimmed = line.trim(); + if (!trimmed) return; + const payload = trimmed.startsWith('data:') ? trimmed.slice(5).trim() : trimmed; + if (!payload || payload === '[DONE]') return; + + let evt; + try { evt = JSON.parse(payload); } catch { return; } + + if (evt.type === 'text-delta') { + text += evt.textDelta ?? evt.delta ?? ''; + return; + } + + if (evt.type === 'tool-result' && typeof evt.toolResult === 'string') { + try { + const tr = JSON.parse(evt.toolResult); + toolResults.push({ + toolName: tr.toolName, + result: tr.result, + args: tr.args, + toolCallId: tr.toolCallId, + }); + } catch { /* skip malformed tool-result payload */ } + } + } + + return { + /** Feed a decoded text chunk; splits on newlines and processes complete lines. */ + push(textChunk) { + buffer += textChunk; + let idx; + while ((idx = buffer.indexOf('\n')) !== -1) { + handleLine(buffer.slice(0, idx)); + buffer = buffer.slice(idx + 1); + } + }, + /** Flush any trailing partial line and return the aggregated response object. */ + finish() { + if (buffer.trim()) handleLine(buffer); + buffer = ''; + return { text, steps: [{ toolResults }] }; + }, + }; +} + +/** + * Consume a whole `fetch` Response body (web ReadableStream) and return the + * aggregated `{ text, steps: [{ toolResults }] }` object. Uses getReader() for + * broad runtime compatibility (Node/undici on Vercel + local dev server). + */ +export async function aggregateStreamResponse(response) { + if (!response.body) throw new Error('stream response has no body'); + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + const agg = makeStreamAggregator(); + // eslint-disable-next-line no-constant-condition + while (true) { + const { done, value } = await reader.read(); + if (done) break; + agg.push(decoder.decode(value, { stream: true })); + } + return agg.finish(); +} diff --git a/api/fetch-jd.js b/api/fetch-jd.js new file mode 100644 index 00000000..64ed80d1 --- /dev/null +++ b/api/fetch-jd.js @@ -0,0 +1,76 @@ +// Fetch a job posting URL server-side (CORS workaround) and return plain text. +// Includes SSRF protection: blocks loopback, private IP ranges, and AWS metadata. + +import { isOriginAllowed } from './_lib/origin.js'; +import { checkRateLimit, pickStricter, send429 } from './_lib/rate-limit.js'; + +function isSafeUrl(url) { + let parsed; + try { parsed = new URL(url); } catch { return false; } + if (!['http:', 'https:'].includes(parsed.protocol)) return false; + + const host = parsed.hostname.toLowerCase(); + if (host === 'localhost' || host === '0.0.0.0' || host.endsWith('.localhost')) return false; + if (/^127\./.test(host)) return false; // loopback + if (/^10\./.test(host)) return false; // RFC1918 + if (/^192\.168\./.test(host)) return false; // RFC1918 + if (/^172\.(1[6-9]|2\d|3[01])\./.test(host)) return false; // RFC1918 + if (/^169\.254\./.test(host)) return false; // link-local / AWS metadata + if (host === '::1' || host === '[::1]') return false; // IPv6 loopback + if (/^fe80:/i.test(host)) return false; // IPv6 link-local + if (/^fc00:|^fd00:/i.test(host)) return false; // IPv6 unique local + return true; +} + +export default async function handler(req, res) { + if (req.method !== 'POST') return res.status(405).send('Method not allowed'); + + if (!isOriginAllowed(req.headers.origin, req.headers.host)) { + return res.status(403).json({ error: 'Origin not allowed' }); + } + + const [rlMin, rlHr] = await Promise.all([ + checkRateLimit(req, { route: 'fetch-jd', limit: 5, windowSeconds: 60 }), + checkRateLimit(req, { route: 'fetch-jd', limit: 30, windowSeconds: 3600 }), + ]); + const rl = pickStricter(rlMin, rlHr); + if (!rl.allowed) return send429(res, { route: 'fetch-jd', result: rl }); + + const body = typeof req.body === 'string' ? safeParse(req.body) : req.body; + if (!body) return res.status(400).json({ error: 'Invalid JSON body' }); + + const { url } = body; + if (!url || typeof url !== 'string') return res.status(400).json({ error: 'Valid URL required' }); + if (!isSafeUrl(url)) return res.status(400).json({ error: 'URL blocked (must be public https/http)' }); + + try { + const response = await fetch(url, { + headers: { + 'User-Agent': 'Mozilla/5.0 (compatible; TalentSafariBot/1.0)', + 'Accept': 'text/html,application/xhtml+xml,*/*', + }, + redirect: 'follow', + }); + + if (!response.ok) { + return res.status(502).json({ error: `Upstream ${response.status}` }); + } + + const html = await response.text(); + const text = html + .replace(//gi, ' ') + .replace(//gi, ' ') + .replace(/<[^>]+>/g, ' ') + .replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>') + .replace(/ /g, ' ').replace(/&#\d+;/g, ' ') + .replace(/\s{3,}/g, '\n\n') + .trim(); + + const trimmed = text.length > 8000 ? text.slice(0, 8000) + '\n[truncated]' : text; + return res.status(200).json({ text: trimmed }); + } catch (err) { + return res.status(502).json({ error: err.message }); + } +} + +function safeParse(s) { try { return JSON.parse(s); } catch { return null; } } diff --git a/api/lua-chat.js b/api/lua-chat.js new file mode 100644 index 00000000..294d8ee8 --- /dev/null +++ b/api/lua-chat.js @@ -0,0 +1,104 @@ +// Proxy for Ada chat calls (scoring + enrichment + capture_lead + submit_cta). +// Forwards the ?channel= query param so the frontend's per-call session pattern +// (eval-, enrich-, lead-, cta-) reaches Lua intact. +// Keeps LUA_API_KEY in process.env, never on the wire to the browser. +// +// PRIMARY PATH: /chat/stream (SSE). A synchronous /chat/generate call holds the +// connection open with no bytes until the agent run finishes; long runs (>60s) +// trip an upstream gateway timeout that returns an HTML error page, which the +// browser then fails to JSON.parse. Streaming emits events continuously, so the +// connection stays alive and the run completes (~45-50s). We aggregate the stream +// server-side back into the exact { text, steps:[{toolResults}] } shape /generate +// returned — so the frontend is unchanged. +// +// FALLBACK PATH: if the stream endpoint can't be reached (non-2xx / throws before +// data), we fall back to the original /chat/generate call. This guarantees the +// proxy is never worse than before this change. + +import { isOriginAllowed } from './_lib/origin.js'; +import { checkRateLimit, pickStricter, send429 } from './_lib/rate-limit.js'; +import { aggregateStreamResponse } from './_lib/stream-aggregate.js'; + +const UPSTREAM = 'https://api.heylua.ai'; + +export default async function handler(req, res) { + if (req.method !== 'POST') return res.status(405).send('Method not allowed'); + + if (!isOriginAllowed(req.headers.origin, req.headers.host)) { + return res.status(403).json({ error: 'Origin not allowed' }); + } + + const [rlMin, rlHr] = await Promise.all([ + checkRateLimit(req, { route: 'lua-chat', limit: 10, windowSeconds: 60 }), + checkRateLimit(req, { route: 'lua-chat', limit: 60, windowSeconds: 3600 }), + ]); + const rl = pickStricter(rlMin, rlHr); + if (!rl.allowed) return send429(res, { route: 'lua-chat', result: rl }); + + const agentId = process.env.LUA_AGENT_ID; + const apiKey = process.env.LUA_API_KEY; + if (!agentId || !apiKey) { + return res.status(500).json({ error: 'Server configuration error' }); + } + + const body = typeof req.body === 'string' ? safeParse(req.body) : req.body; + if (!body) return res.status(400).json({ error: 'Invalid JSON body' }); + + // Sanity-limit so a client can't smuggle path traversal or huge headers via the channel. + const rawChannel = (req.query?.channel || 'production').toString(); + const safeChannel = rawChannel.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 64) || 'production'; + const channelQs = `?channel=${encodeURIComponent(safeChannel)}`; + + const authHeaders = { + 'Content-Type': 'application/json', + Authorization: `Bearer ${apiKey}`, + }; + const payload = JSON.stringify(body); + + const controller = new AbortController(); + const fetchTimeout = setTimeout(() => controller.abort(), 115_000); + + try { + // ── Primary: streaming, aggregated server-side ────────────────────────── + try { + const streamRes = await fetch(`${UPSTREAM}/chat/stream/${agentId}${channelQs}`, { + method: 'POST', + headers: { ...authHeaders, Accept: 'text/event-stream' }, + body: payload, + signal: controller.signal, + }); + + if (streamRes.ok && streamRes.body) { + const data = await aggregateStreamResponse(streamRes); + clearTimeout(fetchTimeout); + return res.status(200).json(data); + } + // Non-2xx from the stream endpoint → fall through to /generate. + } catch (streamErr) { + // Abort means we're out of time — don't burn the rest on a fallback. + if (streamErr?.name === 'AbortError') throw streamErr; + // Otherwise fall through to the non-streaming path. + } + + // ── Fallback: original non-streaming /generate ────────────────────────── + const genRes = await fetch(`${UPSTREAM}/chat/generate/${agentId}${channelQs}`, { + method: 'POST', + headers: authHeaders, + body: payload, + signal: controller.signal, + }); + const data = await genRes.json(); + clearTimeout(fetchTimeout); + return res.status(genRes.status).json(data); + } catch (err) { + clearTimeout(fetchTimeout); + if (err.name === 'AbortError') { + return res.status(504).json({ error: 'scoring_timeout', detail: 'Evaluation took too long. Please try again.' }); + } + return res.status(500).json({ error: err.message }); + } +} + +function safeParse(s) { try { return JSON.parse(s); } catch { return null; } } + +export const config = { maxDuration: 120 }; diff --git a/api/slack-notify.js b/api/slack-notify.js new file mode 100644 index 00000000..bcff9c8d --- /dev/null +++ b/api/slack-notify.js @@ -0,0 +1,40 @@ +// Proxy for frontend Slack pings — keeps webhook URL server-side. + +import { isOriginAllowed } from './_lib/origin.js'; +import { checkRateLimit, pickStricter, send429 } from './_lib/rate-limit.js'; + +export default async function handler(req, res) { + if (req.method !== 'POST') return res.status(405).send('Method not allowed'); + + if (!isOriginAllowed(req.headers.origin, req.headers.host)) { + return res.status(403).json({ error: 'Origin not allowed' }); + } + + const [rlMin, rlHr] = await Promise.all([ + checkRateLimit(req, { route: 'slack-notify', limit: 10, windowSeconds: 60 }), + checkRateLimit(req, { route: 'slack-notify', limit: 60, windowSeconds: 3600 }), + ]); + const rl = pickStricter(rlMin, rlHr); + if (!rl.allowed) return send429(res, { route: 'slack-notify', result: rl }); + + const webhookUrl = process.env.SLACK_LEADS_WEBHOOK_URL; + if (!webhookUrl) { + return res.status(200).send(''); // non-fatal if not configured + } + + const payload = typeof req.body === 'string' ? safeParse(req.body) : req.body; + if (!payload) return res.status(400).json({ error: 'Invalid JSON body' }); + + try { + const response = await fetch(webhookUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + return res.status(response.ok ? 200 : response.status).send(''); + } catch (err) { + return res.status(500).json({ error: err.message }); + } +} + +function safeParse(s) { try { return JSON.parse(s); } catch { return null; } } diff --git a/build.md b/build.md index e83eee22..0b82c172 100644 --- a/build.md +++ b/build.md @@ -1,8 +1,44 @@ -# Human or Agent? — Full Build Spec -### Frontend Replica + Lua Agent (Ada) -> **Launch target:** Mon 25 May 2026 -> **Stack:** Next.js 14 · Tailwind CSS · Claude API (structured output) · Lua agent platform · Slack webhook · Resend email -> **Reference site:** https://human-or-agent.vercel.app/ +# Human or Agent? — Build Spec (Updated to match shipped architecture) +### Static HTML Frontend + Netlify Functions + Lua Agent (Ada) +> **Launched:** 25 May 2026 +> **Stack (shipped):** Static `index.html` · Netlify Functions (API proxy) · Lua agent platform · Claude Sonnet 4.6 (via AI.generate in score_jd tool) · Slack webhook · Resend email +> **Original spec stack:** Next.js 14 + Vercel — not built; static HTML + Netlify chosen for speed of launch + +--- + +## Architecture (as shipped) + +``` +Browser (index.html) + └─► /.netlify/functions/lua-chat ← proxies all Lua agent API calls + └─► /.netlify/functions/slack-notify ← proxies frontend Slack pings + +Netlify Functions (server-side, secrets never reach browser) + └─► Lua agent API (Ada) + └─► score_jd tool → AI.generate({ temperature: 0.2, tool_choice: forced }) + └─► capture_lead tool → Slack Block Kit + Resend email + └─► submit_cta tool → Slack + Resend confirmation + +Environment variables (set in Netlify dashboard): + LUA_AGENT_ID — Lua agent ID + LUA_API_KEY — Lua API key (rotate from git history exposure) + SLACK_LEADS_WEBHOOK_URL — Slack incoming webhook (recreate from git history exposure) + RESEND_API_KEY — Resend transactional email key + FROM_EMAIL — Sender address for Resend +``` + +## URL routing +- `/` → hero/JD input +- `/score` → analysis screen (history.pushState) +- `/results` → results screen (history.pushState, tracked for LinkedIn conversion) +All routes served by `index.html` via Netlify redirects. + +## What was NOT built from original spec +- PDF generation (called out in spec — not implemented) +- Email gate before showing monthly_cost (spec called this out — tool returns value, frontend hides it behind lead form instead) +- Next.js / Vercel stack + +--- --- diff --git a/changes.md b/changes.md new file mode 100644 index 00000000..d7071db4 --- /dev/null +++ b/changes.md @@ -0,0 +1,714 @@ +# Change Log — `analysis` field in evaluations + +**Date:** 2026-06-02 +**Branch:** `review/latest-updates` +**Status:** APPLIED — `src/skills/capture-lead.skill.ts` edited. Stores BOTH a readable +`analysis` string AND the raw `dimensions[]` array. Pending: `lua compile --ci` + live eval. + +--- + +## Goal +Record the agent's analysis in the `evaluations` data primitive. Each evaluation +should persist the per-dimension reasoning Ada produces during `score_jd`, not just +the final score/verdict. + +## Decision +Store **structured analysis** (agent's verdict + rationale + all 7 dimension +rationales), composed into a readable string. Chosen over capturing the freeform +chat narrative because the frontend wizard flow never generates that narrative — +it renders structured cards from `dimensions[]`. The dimension rationales ARE the +agent's analysis. + +## Root finding +- Frontend `submitLead()` (`index.html:1246`) already sends the **full** + `state.result` JSON (including `dimensions[]`) to Ada → `capture_lead`. +- `capture-lead.skill.ts` schema does NOT declare `dimensions`, so Zod **strips it** + before the tool runs. The analysis data arrives at the proxy and is discarded. +- Write point: `Data.create('evaluations', {...})` (`capture-lead.skill.ts:264–279`). + No `analysis` field today. + +--- + +## Files changed +**Only:** `src/skills/capture-lead.skill.ts` (1 file). No frontend change. No other skill. + +### Change 1 — accept `dimensions` in input schema +Stop Zod from stripping the dimension data the frontend already sends. Optional so +existing/older callers never break. +```ts +// inside captureLeadInputSchema.scoringResult, after `rationale`: +dimensions: z.array(z.object({ + key: z.string(), + label: z.string(), + score: z.number(), + weight: z.number(), + rationale: z.string(), +})).optional(), +``` + +### Change 2 — compose analysis string (new helper) +```ts +function buildAnalysis(s: ScoringResult): string { + const lines: string[] = []; + lines.push(`Score: ${s.score}/100 — ${s.verdict_line} (${s.verdict})`); + if (s.rationale) lines.push('', s.rationale); + if (s.dimensions?.length) { + lines.push('', 'Dimension breakdown:'); + for (const d of [...s.dimensions].sort((a, b) => b.weight - a.weight)) { + lines.push(`- ${d.label}: ${d.score}/10 (weight ${d.weight}×) — ${d.rationale}`); + } + } + return lines.join('\n'); +} +``` + +### Change 3 — store it in the evaluations record (string + raw array) +```ts +jd_text: jdText ?? '', +analysis: buildAnalysis(scoringResult), // ← NEW: readable string +dimensions: scoringResult.dimensions ?? [], // ← NEW: raw array (lossless insurance) +timestamp: new Date().toISOString(), +``` + +--- + +## Risk / non-breaking check +- `dimensions` is **optional** → if absent, analysis still builds from + `verdict_line` + `rationale`. Graceful degradation. +- `Data.create` is schemaless → adding a key is safe. Old records simply lack + `analysis` (null on read). Backward compatible. +- **Frontend untouched** — already sends full `state.result`. Persona / invocation + contract unchanged. +- No impact on latency, `maxDuration`, Slack, email, or Sheets paths. + +## Verification (before push) +- `lua compile --ci` → must exit 0 (zero-error standard). +- No `lua deploy` (Ada agent unchanged; `api/` deploys via git push to Vercel branch). +- Confirm a fresh evaluation writes the `analysis` field. + +## Decided +Store BOTH the readable `analysis` string and the raw `dimensions[]` array. +Rationale: the `scoringResult` is relayed THROUGH the LLM (Ada) as prompt text +(`index.html:1252`), so faithful reproduction of the 7-item `dimensions[]` is not +guaranteed. Storing both = lossless when relayed, graceful fallback when not. + +## Residual risk (accepted) +LLM relay may occasionally drop/abbreviate `dimensions[]` → `analysis` degrades to +verdict + rationale only, `dimensions` stores `[]`. True fix = bypass the LLM relay +(frontend → tool directly), which is an architecture change, out of scope here. + +--- + +# Phase 2 — CTA-clicked label + Google Sheets lead logging + +**Date:** 2026-06-02 +**Status:** APPLIED — Parts A/B/C done. `submit-cta.skill.ts` (+`cta_clicked`, contract +key `ctaClicked`), `capture-lead.skill.ts` (append payload: `date`/`roleEvaluated`/ +`ctaClicked:'No'`), new `sheets-apps-script.gs`. Pending: deploy Apps Script + set +`SHEETS_WEBHOOK_URL` on Lua + `lua push`/deploy + live test (Part D). + +## Goals +1. Record the specific CTA clicked as a clean label (`Lua` / `Talent Safari`) in the + `cta-submissions` data primitive. +2. On lead submit, append a row to a Google Sheet with columns: + `Name · Title · Company · Email · Date · Role Evaluated · Score · CTA Clicked`. + The **CTA Clicked** column starts `No` and flips to `Lua` / `Talent Safari` when + the user clicks a CTA — matched by email. + +## Root finding (most plumbing already exists) +- `capture-lead.skill.ts:56` `appendToSheets()` already POSTs `{action:'append', …}` + when `SHEETS_WEBHOOK_URL` is set. +- `submit-cta.skill.ts:43` `updateSheetsRow()` already POSTs + `{action:'updateCta', email, ctaPath}` to flip the CTA cell by email. +- The append → update-by-email design is already in code. Phase 2 only closes gaps + (Date column, initial `No`, clean label field) + adds the Google-side Apps Script. + +## Decisions (confirmed with user) +- **Q1** Add a clean `cta_clicked` label field to `cta-submissions` (keep existing `path` too). +- **Q2** CTA Clicked semantics: row born `No` at lead submit → `Lua`/`Talent Safari` on click, matched by email. ✔ +- **Q3** Date source = **agent-sent ISO timestamp** (recommended — single source, consistent + with the existing `timestamp` field; no dependency on when the Apps Script runs). +- **Q4** Provide the full Google Apps Script (below). +- **Q7** `SHEETS_WEBHOOK_URL` set on the **Lua platform** (skills side), NOT Vercel — + no Vercel access required (verified: only read via `env()` in skills). + +--- + +## Files changed + +### Part A — `src/skills/submit-cta.skill.ts` +Add the clean label to the `cta-submissions` record (inside `Data.create`): +```ts +recommended_cta: scoringResult.recommended_cta, +cta_clicked: path === 'lua' ? 'Lua' : 'Talent Safari', // ← NEW clean label +jd_text: jdText ?? '', +``` +(Optional consistency rename — align the update contract key with the script below: +`ctaPath` → `ctaClicked` in `updateSheetsRow()`. Low priority.) + +### Part B — `src/skills/capture-lead.skill.ts` → `appendToSheets()` +Send the columns the sheet needs, with `CTA Clicked` defaulted to `No` and an +agent-sent `date`: +```ts +body: JSON.stringify({ + action: 'append', + name, + title, + company, + email, + date: new Date().toISOString(), // ← NEW: Date (agent-sent ISO) + roleEvaluated: scoringResult.role_title, // Role Evaluated + score: scoringResult.score, + ctaClicked: 'No', // ← NEW: initial CTA Clicked +}), +``` +> ⚠️ This changes the `append` payload key names. Safe ONLY because the receiving +> Apps Script is new / under our control (Part C). If a DIFFERENT Apps Script already +> consumes the old keys (`path`, `jobTitle`), it must be updated in lockstep — FLAG +> before applying. + +### Part C — NEW file `sheets-apps-script.gs` (deploy in Google, not bundled) +Reference copy kept in repo. User pastes into Google Sheet → Extensions → Apps Script, +deploys as Web App (Execute as: Me; Access: Anyone), copies the `/exec` URL. +```javascript +// TalentSafari — leads logger. Bound to the target Google Sheet. +const HEADERS = ['Name','Title','Company','Email','Date','Role Evaluated','Score','CTA Clicked']; +const EMAIL_COL = 4; // 1-based column index of "Email" +const CTA_COL = 8; // 1-based column index of "CTA Clicked" + +function doPost(e) { + const lock = LockService.getScriptLock(); + lock.waitLock(30000); + try { + const body = JSON.parse(e.postData.contents); + const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; + ensureHeaders_(sheet); + + if (body.action === 'append') { + sheet.appendRow([ + body.name || '', + body.title || '', + body.company || '', + body.email || '', + body.date ? new Date(body.date) : new Date(), + body.roleEvaluated || '', + body.score != null ? body.score : '', + body.ctaClicked || 'No', + ]); + return json_({ ok: true, action: 'append' }); + } + + if (body.action === 'updateCta') { + const row = findLastRowByEmail_(sheet, body.email); + if (row > 0) { + sheet.getRange(row, CTA_COL).setValue(body.ctaClicked || body.ctaPath || 'No'); + return json_({ ok: true, action: 'updateCta', row: row }); + } + return json_({ ok: false, reason: 'email_not_found' }); + } + + return json_({ ok: false, reason: 'unknown_action' }); + } catch (err) { + return json_({ ok: false, error: String(err) }); + } finally { + lock.releaseLock(); + } +} + +function ensureHeaders_(sheet) { + if (sheet.getLastRow() === 0) sheet.appendRow(HEADERS); +} + +function findLastRowByEmail_(sheet, email) { + if (!email) return -1; + const last = sheet.getLastRow(); + if (last < 2) return -1; + const values = sheet.getRange(2, EMAIL_COL, last - 1, 1).getValues(); + for (let i = values.length - 1; i >= 0; i--) { // last match wins + if (String(values[i][0]).trim().toLowerCase() === email.trim().toLowerCase()) { + return i + 2; // back to sheet row index + } + } + return -1; +} + +function json_(obj) { + return ContentService + .createTextOutput(JSON.stringify(obj)) + .setMimeType(ContentService.MimeType.JSON); +} +``` + +### Part D — env `SHEETS_WEBHOOK_URL` (Lua platform, no Vercel) +1. Deploy the Apps Script Web App → copy the `…/exec` URL. +2. Set `SHEETS_WEBHOOK_URL` on the **Lua agent** (via lua-cli or Lua dashboard — confirm + exact command via `/lua-docs`). NOT Vercel. +3. Redeploy skills so the env is picked up. +4. (Local/sandbox dev) set the same var in the Lua sandbox env. + +--- + +## Risk / non-breaking check +- `cta_clicked` — additive field, schemaless Data primitive. Safe. +- `appendToSheets` payload rename — safe IFF the new Apps Script is the only consumer + (Part C). FLAG if a prior script exists. +- **email match edge cases:** duplicate emails → `updateCta` updates the LAST matching + row (intended). CTA clicked before lead appended (race) → `email_not_found`, no-op + (acceptable; append fires at results render, click is later). +- LLM relay: `title`, `score`, `role_title` are small scalars → reliably relayed + (same path as today's working fields). +- If `SHEETS_WEBHOOK_URL` unset → both Sheets calls silently skip (existing behavior, + non-fatal). No regression. + +## Verification (before ship) +- `npx tsc --noEmit` → zero errors (lua-cli not yet installed). +- `/lua-doctor` → install lua-cli → `lua compile --ci`. +- Set env, deploy skills (`lua push` + deploy — these are SKILLS, not Vercel `api/`). +- Live test: run one eval → confirm a Sheet row appends with `CTA Clicked = No`; click a + CTA → confirm same row flips to `Lua`/`Talent Safari`; confirm `cta_clicked` in the + `cta-submissions` primitive. + +## Open / to confirm before applying +- Does a Google Apps Script ALREADY exist behind the current `SHEETS_WEBHOOK_URL` + (old `append`/`updateCta` shape)? If yes, Part B payload rename must match it. + → RESOLVED: building a fresh script. Part B rename safe. +- Sheet target: first tab of the bound spreadsheet (script assumes `getSheets()[0]`). + +--- + +# Phase 3 — confirmation email delivers the full report + +**Date:** 2026-06-02 +**Status:** PROPOSED — not yet applied (awaiting approval) + +## Goal +When the lead submits their email after results render, the confirmation email should +contain the actual evaluation report/analysis — not just a verdict line. + +## Root finding +- `capture-lead.skill.ts` `sendEmail1()` sends a THIN email: verdict_line + score, plus + the line *"The full seven-dimension breakdown is attached"* — but nothing is attached + or included. It promises a report it never delivers. +- `sendEmail1` only receives `roleTitle, verdictLine, score` (3 scalars). It has no + dimensions or candidate cards to render. +- The full analysis data already exists on `scoringResult` (dimensions added in Phase 1; + human_candidate / agent_candidate already in the capture_lead schema). +- Fires only when `RESEND_API_KEY` + `FROM_EMAIL` are set; otherwise skips silently + (non-fatal — same class as the Slack open item). + +## Decisions (confirmed with user) +- Format = **inline HTML** in the email body (no attachment). Renders in all clients, + no PDF dependency, lowest risk. +- Detail = **full report**: verdict + score + rationale + all 7 dimension rationales + + human vs agent candidate cards + CTA nudge. + +## Files changed +**Only:** `src/skills/capture-lead.skill.ts` (1 file). No frontend / persona change. + +### Change 1 — new `esc()` + `renderReportHtml()` helpers +HTML-escape all model/user text (prevents broken markup), then render a table-based, +inline-styled report (email-client safe): +```ts +function esc(v: unknown): string { + return String(v ?? '') + .replace(/&/g, '&').replace(//g, '>') + .replace(/"/g, '"'); +} + +function renderReportHtml(s: ScoringResult): string { + const dims = (s.dimensions ?? []) + .slice() + .sort((a, b) => b.weight - a.weight) + .map( + (d) => + ` + ${esc(d.label)} + ${esc(d.score)}/10 + ${esc(d.weight)}× + ${esc(d.rationale)} + `, + ) + .join(''); + + const dimsBlock = dims + ? `

Seven-dimension breakdown

+ + + + + ${dims} +
DimensionScoreWeightWhy
` + : ''; + + const h = s.human_candidate; + const a = s.agent_candidate; + const cards = + `

Human vs Agent

+ + + + + +
+ Human hire
+ ${h.salary_range ? `Salary: ${esc(h.salary_range)}
` : ''} + Time to productive: ${esc(h.time_to_productive)} +
+ ${esc(a.name)} (Lua agent)
+ Monthly cost: ${esc(a.monthly_cost)}
+ Live: ${esc(a.start_date)}${a.throughput ? ` · ${esc(a.throughput)}` : ''} +
`; + + const ctaLine = + s.recommended_cta === 'lua' + ? 'Recommended next step: talk to Lua about building this agent.' + : 'Recommended next step: brief Talent Safari to source the human hire.'; + + return ` +
+

${esc(s.role_title)}

+

${esc(s.verdict_line)} · Score ${esc(s.score)}/100

+

${esc(s.rationale)}

+ ${dimsBlock} + ${cards} +

${esc(ctaLine)}

+

— Ada · Built by Lua

+
`; +} +``` + +### Change 2 — `sendEmail1` takes the full `scoringResult` +```ts +// signature: (resendApiKey, fromEmail, toEmail, scoringResult: ScoringResult) +subject: `Your Human or Agent? report — ${scoringResult.role_title}`, +html: renderReportHtml(scoringResult), +``` +Removes the false "attached" line. + +### Change 3 — update the call site in `execute()` +```ts +await sendEmail1(resendKey, fromEmail, email, scoringResult); +``` + +## Risk / non-breaking check +- All model text passes through `esc()` → no broken HTML / injection. +- `dimensions` optional → if absent, the breakdown block is omitted; email still sends + with verdict + rationale + cards. Graceful. +- `sendEmail1` stays wrapped in the existing non-fatal `try/catch` in `execute()`. +- Flag short-circuit unchanged — flagged evaluations still send no email. +- Frontend / persona / Slack / Sheets paths untouched. +- 2h follow-up email (`scheduleFollowupEmail`) left as-is (separate, already has rationale). + +## Verification (before ship) +- `npx tsc --noEmit` → zero errors. +- `/lua-doctor` → `lua compile --ci`. +- Ensure `RESEND_API_KEY` + `FROM_EMAIL` set on the Lua agent (else email skips silently). +- Live test: run one eval, submit email → confirm the inbox email contains verdict, + score, 7 dimensions, and the candidate cards. + +## Open / to confirm before applying +- Are `RESEND_API_KEY` + `FROM_EMAIL` set on the Lua agent? (If not, email never sends — + must set before this is testable / live.) + +--- + +# Phase 4 — extra Google Sheet columns (Verdict, Recommended CTA, JD, Analysis) + +**Date:** 2026-06-02 +**Status:** APPLIED — `capture-lead.skill.ts` `appendToSheets()` + `sheets-apps-script.gs`. + +## Goal +Log 4 more fields per lead row: Verdict, Recommended CTA, JD, Analysis (raw values). + +## Decisions (confirmed) +- Raw values: `verdict` (enum), `recommended_cta` (`lua`/`tech_safari`), `jdText`, `buildAnalysis()`. +- New columns APPENDED at END (positions 9-12) — protects existing rows, keeps `EMAIL_COL=4`/`CTA_COL=8` unchanged. User already added the 4 headers to the live sheet. + +## Layout +`Name . Title . Company . Email . Date . Role Evaluated . Score . CTA Clicked . Verdict . Recommended CTA . JD . Analysis` + +## Changes +- `appendToSheets()` — new `jdText` param; payload += `verdict`, `recommendedCta`, `jd`, `analysis`. Call site passes `jdText ?? .`. +- `sheets-apps-script.gs` — `HEADERS` += 4 cols; `append` row += 4 values (same order). + +## Risk / non-breaking +- Append-at-end → existing rows keep alignment (blank trailing cells only). +- `updateCta` unaffected (CTA_COL=8 unchanged). +- `analysis`/`jd` are large text — within Sheets ~50k char/cell limit. +- `appendToSheets` stays in non-fatal try/catch. No frontend/persona/Slack/email impact. + +## Verification +- `npx tsc --noEmit` PASS (clean). +- Pending: redeploy Apps Script (new HEADERS) + `lua push`/deploy skills + live eval -> confirm all 12 columns populate. + +--- + +# Phase 5 — DIAGNOSIS: flagged (short_jd) eval recorded nothing + +**Date:** 2026-06-03 +**Status:** DIAGNOSIS ONLY — no code changes made. + +## Symptom +A short JD evaluation: NOT in `evaluations` data primitive, NOT in Google Sheets, NOT +posted to Slack. Agent (Ada) replied in chat on channel `lead-969116e8...`: +"The short_jd flag is set ... the tool will skip silently per policy. No Slack post or +email ... If Robert submits a fuller job description, I can re-score and capture cleanly." + +## Root cause +Ada did NOT call `capture_lead` — it produced a TEXT explanation instead. + +Why this explains all three misses (verified `capture-lead.skill.ts` execute order): +1. `Data.create('evaluations', ...)` runs FIRST, ALWAYS, regardless of flags (before the short-circuit). +2. THEN the flag short-circuit returns (skips Slack/Sheets/email). + +- evaluations empty => capture_lead was NEVER invoked. If it had run, the always-on + Data.create would have recorded even a flagged lead. => tool not called. +- no Slack / no Sheets => (a) tool not called, AND (b) by design short_jd short-circuits + BEFORE postToSlack/appendToSheets. + +Design intent: ALWAYS call capture_lead; the TOOL decides to skip Slack/email while still +recording to Data. Ada pre-empted the tool based on the flag => always-record never ran. +This is a persona / invocation-contract gap, not a tool-logic bug. + +## Candidate fixes (NOT applied — for next phase) +1. Persona/contract: on "Call the capture_lead tool", ALWAYS call it with the exact + values even if a flag is believed set. Tool handles skipping. Never reply text / refuse. +2. Verify frontend fires capture_lead even for flagged evals (does the wizard render + results + call submitLead when score_jd returns short_jd=true?). +3. POLICY (confirm with user): should flagged leads still be written to Sheets? (move + appendToSheets before the short-circuit) and/or pinged to Slack as a flagged notice? + +## Note +Google Sheets webhook QA (Phase 4): live endpoint returns bare {"ok":true} for append + +updateCta, NOT the {ok,action,row} our repo sheets-apps-script.gs returns => the DEPLOYED +Apps Script is not our repo version. 200 ok confirms reachable, NOT that cols 9-12 fill. +Verify by inspecting the sheet row, or deploy our .gs. + +--- + +# Phase 6 — FIX: persona/contract + Zod schema (resolve F1 + F2 from QA) + +**Date:** 2026-06-03 +**Status:** TO BE DONE — plan only, awaiting approval. No code changes yet. +**Branch target:** `review/latest-updates` +**Source of findings:** `/lua-qa` run 2026-06-03T13:07:00Z (thread IDs `qa-leadcols-happy-20260603`, +`qa-leadcols-short-20260603`). + +## Goal +Close the two high-severity QA findings so that: +1. Every `score_jd` call is followed by a `capture_lead` call — including flagged + evals (short_jd / non_english / suspected_fake). Phase 5 root cause closed. +2. The raw `score_jd` output passes `captureLeadInputSchema` on the first relay + attempt (no validation warn, no retry, no dropped `dimensions[]`). Restores the + 7-dimension breakdown in Sheets col 12 (Analysis) and in the `evaluations` + primitive's `dimensions` field. + +## Files changed +**Only:** `src/skills/capture-lead.skill.ts` (1 file). No frontend / no other skill. +No persona file edit (skill `context` is the persona contract for this tool). +No Apps Script change. No env change. + +--- + +## Part A — F1 fix: persona/contract rewrites (two strings) + +### A1 — Tool `description` (line 374-375) +Replace the misleading "Skips silently if any quality flag is set." which Ada read +as "don't call when flagged." + +```ts +description = + "ALWAYS call this tool immediately after score_jd, even when quality flags are set. The tool always records the evaluation to Data; it decides internally whether to also post Slack / send email / append Sheets. Never refuse, explain, or withhold the call."; +``` + +### A2 — Skill `context` (line 460-468) +Flip the contract from "skip on flag" to "always call; the tool handles skipping." + +```ts +context: `Use the capture_lead tool immediately after every successful score_jd call — pass the full scoringResult along with the lead's email and company name. ALWAYS call it, even if you believe a flag (short_jd, non_english, suspected_fake) is set. Never reply with text in place of the call; never explain the flag instead of calling the tool. The tool itself handles flag-based skipping. + +The tool will: +1. ALWAYS record the evaluation to the evaluations Data primitive (regardless of flags). +2. If any flag is set → return { skipped: true, reason } and skip Slack/Sheets/email. This is internal; you still MUST call it. +3. Otherwise → post Slack Block Kit, append Google Sheets row, send Resend report email, schedule 2h follow-up. + +Returns: { posted, email1Sent, email2ScheduledAt } on success, or { skipped: true, reason } when flagged.`, +``` + +### A3 — Why this resolves F1 +QA log thread `qa-leadcols-short-20260603` shows Ada returned text only, no +`capture_lead` tool entry in logs. Skill `context` line 463 ("Skip silently … do +not retry or explain") was being read as "don't call." A1+A2 invert the +instruction. Tool `execute()` order is already correct: `Data.create` runs +unconditionally (line 383-401) BEFORE the flag short-circuit (line 405). No logic +change needed. + +--- + +## Part B — F2 fix: Zod `.passthrough()` on score_jd-shaped objects + +### B1 — Drift between `score_jd` output and `captureLeadInputSchema` +`score_jd` emits these keys NOT declared in `captureLeadInputSchema.scoringResult`: + +| Object | Extra keys (rejected by Zod strict default) | +|---|---| +| `human_candidate` | `scale_ceiling`, `coverage`, `great_at`, `hard_at` | +| `agent_candidate` | `avatar_seed`, `coverage`, `great_at`, `cant_do` | +| top-level `scoringResult` | `adjacent_agents` | + +Live evidence: log `_id 6a2026a47e566f2327bd0d64` at `2026-06-03T13:05:40.302Z` +— `subType: warn`, message `"Tool input validation failed"`, fired between the +`score_jd` result and the eventual retry. Retry payload at `13:05:51` had +`dimensions` absent → `buildAnalysis()` fell back to verdict+rationale only. + +### B2 — Edit (`capture-lead.skill.ts:33-43, 50`) +Add `.passthrough()` to the two nested objects and the outer `scoringResult`: + +```ts +human_candidate: z.object({ + salary_range: z.string(), + time_to_productive: z.string(), +}).passthrough(), +agent_candidate: z.object({ + name: z.string(), + role_title: z.string(), + monthly_cost: z.string(), + start_date: z.string(), + throughput: z.string().optional(), +}).passthrough(), +``` + +And on the outer `scoringResult` `.object({...})`: +```ts +}).passthrough().describe('The full scoring result from score_jd'), +``` + +### B3 — Why this resolves F2 + F3 +- First relay passes Zod (no warn, no retry). +- `dimensions[]` survives the relay because no strip step runs. +- `buildAnalysis()` (line 159-170) receives the full `dimensions[]` → composes the + 9-line breakdown. +- `appendToSheets()` writes the full breakdown into Sheets col 12. +- `Data.create('evaluations', ...)` `dimensions` field stops being `[]`. +- F3 is downstream of F2 → resolves with same edit. + +--- + +## Risk / non-breaking check +- A1/A2: prose-only contract rewrite. Tool `execute()` unchanged. No fields renamed, + no return shape changed. Frontend untouched. Slack/Sheets/email paths unchanged. +- B2: `.passthrough()` is additive — accepts extra keys, still validates declared + keys. Older `score_jd` payloads without the extra keys remain valid. +- No env change. No Vercel deploy. Apps Script untouched. +- `cta-submissions` primitive untouched. + +## Out of scope (deliberately not in Phase 6) +- F4: deployed Apps Script ≠ repo. Manual Google Apps Script re-deploy required + (paste `sheets-apps-script.gs` into Extensions → Apps Script → re-deploy Web App). + Operational task, not a code change. +- Frontend behavior on flagged evals: confirm wizard still calls `submitLead()` + when `score_jd` returns `short_jd=true` (Phase 5 candidate fix #2). Deferred. +- Policy: should flagged leads also appear in Sheets/Slack as a flagged notice? + (Phase 5 candidate fix #3.) Requires product decision. + +## Verification (before push) +1. `npx tsc --noEmit` → zero errors. +2. `lua compile --ci` → exit 0. +3. `lua push` + deploy skills. +4. Live test — normal JD: + - Submit a realistic JD via chat. + - Confirm no `"Tool input validation failed"` warn in logs. + - Inspect `capture_lead` tool input log → `scoringResult.dimensions` is + a 7-element array, not absent. + - Inspect `evaluations` primitive → `dimensions` is non-empty. + - Inspect Sheets row → col 12 (Analysis) contains the 9-line breakdown. +5. Live test — flagged JD (short_jd): + - Submit "hire a dev" or similar. + - Confirm Ada DOES call `capture_lead` (tool entry appears in logs for the thread). + - Confirm `evaluations` primitive has a row for the flagged eval. + - Confirm Slack / Sheets / email are correctly skipped (this is the intended + design for flagged leads). + +## Rollback +Revert the single file `src/skills/capture-lead.skill.ts` to pre-Phase-6 state +and re-deploy. No data migration; no env to unset. + +## Open / to confirm before applying +- Approval to edit `capture-lead.skill.ts` (4 edit points: 1 description string, + 1 context string, 2 nested `.passthrough()` calls + 1 outer `.passthrough()`). +- Order of application: A then B (A is independent of B; B independent of A). + Can ship both in one push. + +--- + +# Phase 7 — branded email footer (Lua logo) + wider margins + +**Date:** 2026-06-03 +**Status:** PROPOSED — not applied. Blocked on assets (logo + icon PNGs, social URLs). + +## Goal +Replace the plain `— Ada · Built by Lua` email footer with a branded Lua footer: centered +Lua logo, tagline, social icons (Facebook / LinkedIn / Instagram). Also widen the email +margins for more breathing room. + +## Constraint (why this needs hosted images) +Email clients strip SVG, external CSS, and most ` diff --git a/lua.skill.yaml b/lua.skill.yaml index d2698dba..27b4cfd0 100644 --- a/lua.skill.yaml +++ b/lua.skill.yaml @@ -2,30 +2,30 @@ agent: agentId: baseAgent_agent_1779215133611_x0svb7j5d orgId: e2fa42a6-4fd8-4963-9c46-aaa60ca61d91 skills: - - name: score-role - skillId: bf212f12-d2fd-417a-bb30-a9fa71ad1afc - version: 1.0.14 - name: capture-lead skillId: 86c230de-eb61-4b97-8111-70602454c2bc - version: 1.0.15 + version: 1.0.37 - name: submit-cta skillId: 278ee16a-780a-464f-8022-c04a88b9e1fc - version: 1.0.13 + version: 1.0.33 - name: ada-chat skillId: c489ffca-735c-46fc-abfc-68644f269f18 - version: 1.0.10 + version: 1.0.29 - name: brief-wizard skillId: 624cdb64-6a55-4745-8469-c6770d10c490 - version: 1.0.10 + version: 1.0.29 - name: scrape-jd skillId: 3ed62a95-73fe-41d8-a4d9-910221226965 - version: 1.0.10 + version: 1.0.30 + - name: score-role + skillId: bf212f12-d2fd-417a-bb30-a9fa71ad1afc + version: 1.0.35 webhooks: [] jobs: [] preprocessors: [] postprocessors: [] mcpServers: [] backup: - activeVersion: 21 - lastHash: e47bdc60bc8cef6a77170bcaa08d07ce2bfd430242df2b8b69fc8f194418ffcc - lastPushedAt: '2026-05-25T13:28:49.507Z' + activeVersion: 48 + lastHash: 3593183c55e79306bbd8b16cdc95c92f38b8c24e1e828788525fccb0abe986f8 + lastPushedAt: '2026-06-05T14:45:32.946Z' diff --git a/netlify.toml b/netlify.toml index da44d968..7abc344e 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,9 +1,30 @@ [build] - command = "" - publish = "." + command = "echo 'static site — no build step'" + publish = "." + +[functions] + directory = "netlify/functions" + +[context.production] + environment = { NODE_VERSION = "20" } + +# Rewrite /api/* to /.netlify/functions/* so index.html's /api/ calls +# work on Netlify (Vercel uses api/ natively; this shim bridges the gap +# until DNS is flipped to Vercel). +[[redirects]] + from = "/api/:name" + to = "/.netlify/functions/:name" + status = 200 + +# SPA-style: keep unknown paths on the same HTML file +[[redirects]] + from = "/*" + to = "/index.html" + status = 200 [[headers]] for = "/*" [headers.values] X-Frame-Options = "DENY" X-Content-Type-Options = "nosniff" + Referrer-Policy = "strict-origin-when-cross-origin" diff --git a/netlify/functions/fetch-jd.js b/netlify/functions/fetch-jd.js new file mode 100644 index 00000000..9a44cf8b --- /dev/null +++ b/netlify/functions/fetch-jd.js @@ -0,0 +1,64 @@ +// Fetch a job posting URL server-side (browser CORS) → return plain text. + +exports.handler = async (event) => { + if (event.httpMethod !== 'POST') { + return { statusCode: 405, body: 'Method not allowed' }; + } + + let url; + try { ({ url } = JSON.parse(event.body || '{}')); } + catch { return { statusCode: 400, body: JSON.stringify({ error: 'Invalid JSON' }) }; } + + if (!url || !/^https?:\/\//i.test(url)) { + return { statusCode: 400, body: JSON.stringify({ error: 'Valid URL required' }) }; + } + + // SSRF guard — block RFC1918, loopback, link-local, metadata + try { assertSafeUrl(url); } + catch { return { statusCode: 400, body: JSON.stringify({ error: 'URL not allowed' }) }; } + + try { + const res = await fetch(url, { + headers: { + 'User-Agent': 'Mozilla/5.0 (compatible; TalentSafariBot/1.0)', + 'Accept': 'text/html,application/xhtml+xml,*/*', + }, + redirect: 'follow', + }); + + if (!res.ok) { + return { statusCode: 502, body: JSON.stringify({ error: `Upstream ${res.status}` }) }; + } + + const html = await res.text(); + const text = html + .replace(//gi, ' ') + .replace(//gi, ' ') + .replace(/<[^>]+>/g, ' ') + .replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>') + .replace(/ /g, ' ').replace(/&#\d+;/g, ' ') + .replace(/\s{3,}/g, '\n\n') + .trim(); + + const trimmed = text.length > 8000 ? text.slice(0, 8000) + '\n[truncated]' : text; + return { + statusCode: 200, + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ text: trimmed }), + }; + } catch (err) { + return { statusCode: 502, body: JSON.stringify({ error: err.message }) }; + } +}; + +const BLOCKED = [ + /^localhost$/i, /^127\./, /^10\./, /^172\.(1[6-9]|2\d|3[01])\./, /^192\.168\./, + /^169\.254\./, /^::1$/, /^fc00:/i, /^fe80:/i, /^0\./, /^100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\./, +]; + +function assertSafeUrl(raw) { + const p = new URL(raw); + if (p.protocol !== 'https:') throw new Error('https only'); + const h = p.hostname.toLowerCase(); + for (const pat of BLOCKED) if (pat.test(h)) throw new Error('blocked'); +} diff --git a/netlify/functions/lua-chat.js b/netlify/functions/lua-chat.js new file mode 100644 index 00000000..9988361d --- /dev/null +++ b/netlify/functions/lua-chat.js @@ -0,0 +1,41 @@ +// Proxy for Ada chat calls. Channel comes from the query string (?channel=...) +// to match the frontend's adaSessionUrl() pattern and the Vercel api/lua-chat.js contract. + +exports.handler = async (event) => { + if (event.httpMethod !== 'POST') { + return { statusCode: 405, body: 'Method not allowed' }; + } + + const agentId = process.env.LUA_AGENT_ID; + const apiKey = process.env.LUA_API_KEY; + if (!agentId || !apiKey) { + return { statusCode: 500, body: JSON.stringify({ error: 'Server configuration error' }) }; + } + + let body; + try { body = JSON.parse(event.body || '{}'); } + catch { return { statusCode: 400, body: JSON.stringify({ error: 'Invalid JSON' }) }; } + + const rawChannel = (event.queryStringParameters?.channel || 'production').toString(); + const safeChannel = rawChannel.replace(/[^a-zA-Z0-9_-]/g, '').slice(0, 64) || 'production'; + + try { + const response = await fetch( + `https://api.heylua.ai/chat/generate/${agentId}?channel=${encodeURIComponent(safeChannel)}`, + { + method: 'POST', + headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` }, + body: JSON.stringify(body), + }, + ); + + const data = await response.json(); + return { + statusCode: response.status, + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data), + }; + } catch (err) { + return { statusCode: 500, body: JSON.stringify({ error: err.message }) }; + } +}; diff --git a/netlify/functions/score-jd.js b/netlify/functions/score-jd.js new file mode 100644 index 00000000..7371cd39 --- /dev/null +++ b/netlify/functions/score-jd.js @@ -0,0 +1,102 @@ +// JD scoring via Ada's chat API. +// Ada's persona has the full scoring rubric; she outputs JSON directly. +// Single LLM call fits within Netlify's 26s timeout for the free tier. + +exports.handler = async (event) => { + if (event.httpMethod !== 'POST') { + return { statusCode: 405, body: 'Method not allowed' }; + } + + const agentId = process.env.LUA_AGENT_ID; + const apiKey = process.env.LUA_API_KEY; + if (!agentId || !apiKey) { + return { statusCode: 500, body: JSON.stringify({ error: 'Server configuration error' }) }; + } + + let body; + try { body = JSON.parse(event.body || '{}'); } + catch { return { statusCode: 400, body: JSON.stringify({ error: 'Invalid JSON' }) }; } + + const { jdText, volume, taskFreq, stakes, exposure } = body; + if (!jdText) { + return { statusCode: 400, body: JSON.stringify({ error: 'jdText is required' }) }; + } + + const contextLines = [ + volume && `Task structure: ${volume}`, + taskFreq && `Task frequency: ${taskFreq} volume per day`, + stakes && `Decision stakes: ${stakes}`, + exposure && `Exposure type: ${exposure}`, + ].filter(Boolean); + + const fullJd = contextLines.length + ? `${jdText}\n\nAdditional context:\n${contextLines.join('\n')}` + : jdText; + + const channelId = `eval-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`; + + try { + const response = await fetch( + `https://api.heylua.ai/chat/generate/${agentId}?channel=${encodeURIComponent(channelId)}`, + { + method: 'POST', + headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` }, + body: JSON.stringify({ + messages: [{ type: 'text', text: `Score this job description:\n\n${fullJd}` }], + navigate: false, + }), + }, + ); + + const data = await response.json(); + console.log('[score-jd] status:', response.status, 'channel:', channelId); + + if (!response.ok) { + return { statusCode: response.status, body: JSON.stringify({ error: data }) }; + } + + const rawText = extractText(data); + const jsonMatch = rawText.match(/```(?:json)?\s*([\s\S]*?)```/) || rawText.match(/(\{[\s\S]*\})/); + if (!jsonMatch) { + console.error('[score-jd] no JSON:', rawText.slice(0, 300)); + return { statusCode: 500, body: JSON.stringify({ error: 'No JSON in Ada response', raw: rawText.slice(0, 300) }) }; + } + + let result; + try { result = JSON.parse(jsonMatch[1].trim()); } + catch (e) { + return { statusCode: 500, body: JSON.stringify({ error: 'JSON parse failed', raw: jsonMatch[1].slice(0, 300) }) }; + } + + if (!result.role_title || !Array.isArray(result.dimensions) || result.dimensions.length !== 7) { + return { statusCode: 500, body: JSON.stringify({ error: 'Invalid result shape', raw: result }) }; + } + + const computed = Math.round(result.dimensions.reduce((s, d) => s + d.score * d.weight, 0)); + if (Math.abs(computed - result.score) > 1) { + result.score = computed; + result.verdict = computed < 40 ? 'needs_human' : computed < 65 ? 'human_led_agent_assist' : 'strong_agent'; + result.recommended_cta = computed >= 65 ? 'lua' : 'tech_safari'; + } + + return { + statusCode: 200, + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ result }), + }; + } catch (err) { + console.error('[score-jd] error:', err.message); + return { statusCode: 500, body: JSON.stringify({ error: err.message }) }; + } +}; + +function extractText(data) { + if (typeof data?.text === 'string' && data.text.trim()) return data.text; + if (Array.isArray(data?.steps)) { + for (const step of data.steps) { + const t = step?.output || step?.result || ''; + if (typeof t === 'string' && t.includes('"score"')) return t; + } + } + return ''; +} diff --git a/netlify/functions/slack-notify.js b/netlify/functions/slack-notify.js new file mode 100644 index 00000000..743d4bae --- /dev/null +++ b/netlify/functions/slack-notify.js @@ -0,0 +1,27 @@ +// Proxy for frontend Slack pings — keeps webhook URL server-side. + +exports.handler = async (event) => { + if (event.httpMethod !== 'POST') { + return { statusCode: 405, body: 'Method not allowed' }; + } + + const webhookUrl = process.env.SLACK_LEADS_WEBHOOK_URL; + if (!webhookUrl) { + return { statusCode: 200, body: '' }; + } + + let payload; + try { payload = JSON.parse(event.body || '{}'); } + catch { return { statusCode: 400, body: JSON.stringify({ error: 'Invalid JSON' }) }; } + + try { + const response = await fetch(webhookUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + return { statusCode: response.ok ? 200 : response.status, body: '' }; + } catch (err) { + return { statusCode: 500, body: JSON.stringify({ error: err.message }) }; + } +}; diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json deleted file mode 100644 index f1eb944c..00000000 --- a/node_modules/.package-lock.json +++ /dev/null @@ -1,4917 +0,0 @@ -{ - "name": "lua-skill", - "version": "1.0.1-beta.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "node_modules/@ai-sdk/gateway": { - "version": "2.0.89", - "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-2.0.89.tgz", - "integrity": "sha512-oIIsLOTgfuFIg6HGQ3d5gXjUvgx2YKav10T4t+sexnQj1anw6WoMDdSAT24igbfgWrC+Cf2tmlLeRhBUxdsZ9g==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "2.0.3", - "@ai-sdk/provider-utils": "3.0.25", - "@vercel/oidc": "3.1.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.3.tgz", - "integrity": "sha512-h88OPkavHTiN9tMn2l5awAznGB0lXzjcLhgR1/rvjB2zlLprsNxbM2tt6OJsHUxduLC3klq0/eqaSf6fX5XVww==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@ai-sdk/provider-utils": { - "version": "3.0.25", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.25.tgz", - "integrity": "sha512-CvsRu+32Y8a167s+lrIBtsybvgTHp8j9y+6BeTvLeoW3Q+okw/b4CnNUFOLIXsRaKHQKAH+IHNJPYWywfpw0LA==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "2.0.3", - "@standard-schema/spec": "^1.0.0", - "eventsource-parser": "^3.0.6" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@bufbuild/protobuf": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.10.1.tgz", - "integrity": "sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ==", - "license": "(Apache-2.0 AND BSD-3-Clause)" - }, - "node_modules/@datastructures-js/deque": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@datastructures-js/deque/-/deque-1.0.8.tgz", - "integrity": "sha512-PSBhJ2/SmeRPRHuBv7i/fHWIdSC3JTyq56qb+Rq0wjOagi0/fdV5/B/3Md5zFZus/W6OkSPMaxMKKMNMrSmubg==", - "license": "MIT" - }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@ffmpeg-installer/ffmpeg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@ffmpeg-installer/ffmpeg/-/ffmpeg-1.1.0.tgz", - "integrity": "sha512-Uq4rmwkdGxIa9A6Bd/VqqYbT7zqh1GrT5/rFwCwKM70b42W5gIjWeVETq6SdcL0zXqDtY081Ws/iJWhr1+xvQg==", - "license": "LGPL-2.1", - "optionalDependencies": { - "@ffmpeg-installer/darwin-arm64": "4.1.5", - "@ffmpeg-installer/darwin-x64": "4.1.0", - "@ffmpeg-installer/linux-arm": "4.1.3", - "@ffmpeg-installer/linux-arm64": "4.1.4", - "@ffmpeg-installer/linux-ia32": "4.1.0", - "@ffmpeg-installer/linux-x64": "4.1.0", - "@ffmpeg-installer/win32-ia32": "4.1.0", - "@ffmpeg-installer/win32-x64": "4.1.0" - } - }, - "node_modules/@ffmpeg-installer/win32-x64": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@ffmpeg-installer/win32-x64/-/win32-x64-4.1.0.tgz", - "integrity": "sha512-Drt5u2vzDnIONf4ZEkKtFlbvwj6rI3kxw1Ck9fpudmtgaZIHD4ucsWB2lCZBXRxJgXR+2IMSti+4rtM4C4rXgg==", - "cpu": [ - "x64" - ], - "license": "GPLv3", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@google/genai": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.52.0.tgz", - "integrity": "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "google-auth-library": "^10.3.0", - "p-retry": "^4.6.2", - "protobufjs": "^7.5.4", - "ws": "^8.18.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@modelcontextprotocol/sdk": "^1.25.2" - }, - "peerDependenciesMeta": { - "@modelcontextprotocol/sdk": { - "optional": true - } - } - }, - "node_modules/@img/colour": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", - "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@inquirer/ansi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", - "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/checkbox": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", - "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/confirm": { - "version": "5.1.21", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", - "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/core": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", - "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/editor": { - "version": "4.2.23", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", - "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/external-editor": "^1.0.3", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/expand": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", - "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/external-editor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", - "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", - "license": "MIT", - "dependencies": { - "chardet": "^2.1.1", - "iconv-lite": "^0.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/figures": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", - "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/input": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", - "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/number": { - "version": "3.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", - "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/password": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", - "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/prompts": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", - "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", - "license": "MIT", - "dependencies": { - "@inquirer/checkbox": "^4.3.2", - "@inquirer/confirm": "^5.1.21", - "@inquirer/editor": "^4.2.23", - "@inquirer/expand": "^4.0.23", - "@inquirer/input": "^4.3.1", - "@inquirer/number": "^3.0.23", - "@inquirer/password": "^4.0.23", - "@inquirer/rawlist": "^4.1.11", - "@inquirer/search": "^3.2.2", - "@inquirer/select": "^4.4.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/rawlist": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", - "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/search": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", - "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/select": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", - "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/type": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", - "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@livekit/agents": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@livekit/agents/-/agents-1.4.3.tgz", - "integrity": "sha512-yYJMW6DRzJVd0TD9RyLjPmls8U1PIp70MwGn2NGsVdvjrlGFIdngvVTTriY5GsCiTLRbFrjhL/B0h59F7Hd7aQ==", - "license": "Apache-2.0", - "dependencies": { - "@bufbuild/protobuf": "^1.10.0", - "@ffmpeg-installer/ffmpeg": "^1.1.0", - "@livekit/mutex": "^1.1.1", - "@livekit/protocol": "^1.45.7", - "@livekit/throws-transformer": "0.1.8", - "@livekit/typed-emitter": "^3.0.0", - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/api-logs": "^0.54.0", - "@opentelemetry/core": "^2.2.0", - "@opentelemetry/exporter-logs-otlp-proto": "^0.54.0", - "@opentelemetry/exporter-trace-otlp-proto": "^0.54.0", - "@opentelemetry/instrumentation-pino": "^0.43.0", - "@opentelemetry/otlp-exporter-base": "^0.208.0", - "@opentelemetry/resources": "^1.28.0", - "@opentelemetry/sdk-logs": "^0.54.0", - "@opentelemetry/sdk-trace-base": "^1.28.0", - "@opentelemetry/sdk-trace-node": "^1.28.0", - "@opentelemetry/semantic-conventions": "^1.28.0", - "@types/pidusage": "^2.0.5", - "commander": "^12.0.0", - "fluent-ffmpeg": "^2.1.3", - "form-data": "^4.0.5", - "heap-js": "^2.6.0", - "json-schema": "^0.4.0", - "livekit-server-sdk": "^2.14.1", - "ofetch": "^1.5.1", - "openai": "^6.8.1", - "pidusage": "^4.0.1", - "pino": "^8.19.0", - "pino-pretty": "^11.0.0", - "sharp": "0.34.5", - "ws": "^8.18.0", - "zod-to-json-schema": "^3.24.6" - }, - "bin": { - "livekit-agents": "dist/bin/livekit-agents.js" - }, - "peerDependencies": { - "@livekit/rtc-node": "^0.13.27", - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@livekit/agents-plugin-deepgram": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@livekit/agents-plugin-deepgram/-/agents-plugin-deepgram-1.4.3.tgz", - "integrity": "sha512-S5qXRJDnf9Mgp/ELlZsMZFbXz0CRZkOl2X6iwpE6PL6MAIqaen5dSG0iJhQTucd/GrWEMvyt19X1ilMyvJGlRw==", - "license": "Apache-2.0", - "dependencies": { - "ws": "^8.18.0" - }, - "peerDependencies": { - "@livekit/agents": "1.4.3", - "@livekit/rtc-node": "^0.13.27" - } - }, - "node_modules/@livekit/agents-plugin-elevenlabs": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@livekit/agents-plugin-elevenlabs/-/agents-plugin-elevenlabs-1.4.3.tgz", - "integrity": "sha512-hqpiLTWmTv280ZGNYimbMaRvkhDsU6kNNtH/eG6z/IBq+A+bdpdnGKqnE1+QtqEXI+RRRSGUr6iSoN9r1/5LnQ==", - "license": "Apache-2.0", - "dependencies": { - "@livekit/mutex": "^1.1.1", - "ws": "^8.18.0" - }, - "peerDependencies": { - "@livekit/agents": "1.4.3", - "@livekit/rtc-node": "^0.13.27" - } - }, - "node_modules/@livekit/agents-plugin-google": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@livekit/agents-plugin-google/-/agents-plugin-google-1.4.3.tgz", - "integrity": "sha512-Bayxm8UxOqNevdzq8djrMy/bvB0Wlbm8FX9d3P5S5HH1o0GDo/8KXbYlTTn53DFL82jXDxpstO77Mwf9jn095w==", - "license": "Apache-2.0", - "dependencies": { - "@google/genai": "^1.44.0", - "@livekit/mutex": "^1.1.1", - "@types/json-schema": "^7.0.15", - "json-schema": "^0.4.0" - }, - "peerDependencies": { - "@livekit/agents": "1.4.3", - "@livekit/rtc-node": "^0.13.27" - } - }, - "node_modules/@livekit/agents-plugin-openai": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@livekit/agents-plugin-openai/-/agents-plugin-openai-1.4.3.tgz", - "integrity": "sha512-fm5xc+TKPkBEUITbw7gs7kVXxYTq1oSRCbLHUK68E+ptok+msb6JT4K6BjPK+Upkw72DJmXaqDqtwubnRy+bew==", - "license": "Apache-2.0", - "dependencies": { - "@livekit/mutex": "^1.1.1", - "openai": "^6.8.1", - "ws": "^8.18.0" - }, - "peerDependencies": { - "@livekit/agents": "1.4.3", - "@livekit/rtc-node": "^0.13.27", - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@livekit/agents-plugin-openai/node_modules/openai": { - "version": "6.38.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-6.38.0.tgz", - "integrity": "sha512-AoMplt2UalrpgUDMh3L09QWjNRlgJPipclQvA6sYAaeF6nHNBMgmikAZGmcYLn8on4d9sQY9Q8bOLfrBS7Lc8g==", - "license": "Apache-2.0", - "bin": { - "openai": "bin/cli" - }, - "peerDependencies": { - "ws": "^8.18.0", - "zod": "^3.25 || ^4.0" - }, - "peerDependenciesMeta": { - "ws": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/@livekit/agents-plugin-xai": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@livekit/agents-plugin-xai/-/agents-plugin-xai-1.4.3.tgz", - "integrity": "sha512-zcsF9FBO3j6hWtz2TFV3TqhkNcSYAc4jOo6/ISoGERWNeOsSFPGd0NyvP/tZsT8BSqZjri13s6/LL6006udOyQ==", - "license": "Apache-2.0", - "dependencies": { - "openai": "^6.8.1", - "ws": "^8.18.0" - }, - "peerDependencies": { - "@livekit/agents": "1.4.3", - "@livekit/agents-plugin-openai": "1.4.3", - "@livekit/rtc-node": "^0.13.27" - } - }, - "node_modules/@livekit/agents-plugin-xai/node_modules/openai": { - "version": "6.38.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-6.38.0.tgz", - "integrity": "sha512-AoMplt2UalrpgUDMh3L09QWjNRlgJPipclQvA6sYAaeF6nHNBMgmikAZGmcYLn8on4d9sQY9Q8bOLfrBS7Lc8g==", - "license": "Apache-2.0", - "bin": { - "openai": "bin/cli" - }, - "peerDependencies": { - "ws": "^8.18.0", - "zod": "^3.25 || ^4.0" - }, - "peerDependenciesMeta": { - "ws": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/@livekit/agents/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@livekit/agents/node_modules/openai": { - "version": "6.38.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-6.38.0.tgz", - "integrity": "sha512-AoMplt2UalrpgUDMh3L09QWjNRlgJPipclQvA6sYAaeF6nHNBMgmikAZGmcYLn8on4d9sQY9Q8bOLfrBS7Lc8g==", - "license": "Apache-2.0", - "bin": { - "openai": "bin/cli" - }, - "peerDependencies": { - "ws": "^8.18.0", - "zod": "^3.25 || ^4.0" - }, - "peerDependenciesMeta": { - "ws": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/@livekit/mutex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@livekit/mutex/-/mutex-1.1.1.tgz", - "integrity": "sha512-EsshAucklmpuUAfkABPxJNhzj9v2sG7JuzFDL4ML1oJQSV14sqrpTYnsaOudMAw9yOaW53NU3QQTlUQoRs4czw==", - "license": "Apache-2.0" - }, - "node_modules/@livekit/protocol": { - "version": "1.45.8", - "resolved": "https://registry.npmjs.org/@livekit/protocol/-/protocol-1.45.8.tgz", - "integrity": "sha512-Q+l57E7w/xxOBFVWzdX5rkAZO7ffyF+rlDzNUYq2SU114+5aTyCq+PK4unaEVDNd4952Af7wteKr3sOgasGuaA==", - "license": "Apache-2.0", - "dependencies": { - "@bufbuild/protobuf": "^1.10.0" - } - }, - "node_modules/@livekit/rtc-ffi-bindings": { - "version": "0.12.56", - "resolved": "https://registry.npmjs.org/@livekit/rtc-ffi-bindings/-/rtc-ffi-bindings-0.12.56.tgz", - "integrity": "sha512-BCirumGTO7iQYk2KidsqraSNqCbveYGBEQGJS/9lMSeJOFXwwlWHWL9N9ZThBNjAdCQdcvSthWB33FApob8H1w==", - "license": "Apache-2.0", - "dependencies": { - "@bufbuild/protobuf": "^1.10.1" - }, - "engines": { - "node": ">= 18" - }, - "optionalDependencies": { - "@livekit/rtc-ffi-bindings-darwin-arm64": "0.12.56", - "@livekit/rtc-ffi-bindings-darwin-x64": "0.12.56", - "@livekit/rtc-ffi-bindings-linux-arm64-gnu": "0.12.56", - "@livekit/rtc-ffi-bindings-linux-x64-gnu": "0.12.56", - "@livekit/rtc-ffi-bindings-win32-x64-msvc": "0.12.56" - } - }, - "node_modules/@livekit/rtc-ffi-bindings-win32-x64-msvc": { - "version": "0.12.56", - "resolved": "https://registry.npmjs.org/@livekit/rtc-ffi-bindings-win32-x64-msvc/-/rtc-ffi-bindings-win32-x64-msvc-0.12.56.tgz", - "integrity": "sha512-uPK1k43h7HHt2rhRObVNLhhH+x3YvA8DPcTMP8OpRwMeq16TdD/44BdgFKvmlHQoJJfzMFty74MyEkr4nTdqAw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 18" - } - }, - "node_modules/@livekit/rtc-node": { - "version": "0.13.28", - "resolved": "https://registry.npmjs.org/@livekit/rtc-node/-/rtc-node-0.13.28.tgz", - "integrity": "sha512-qUYgU7zE4i8UeS6OwWSqQ0BNSMPTrsXtzfkAqeegsiUgJbyiIizIhrwsLpKJmyxtTFVC5o1X4sTXLomrYy+Inw==", - "license": "Apache-2.0", - "dependencies": { - "@datastructures-js/deque": "1.0.8", - "@livekit/mutex": "^1.0.0", - "@livekit/rtc-ffi-bindings": "0.12.56", - "@livekit/typed-emitter": "^3.0.0", - "pino": "^9.0.0", - "pino-pretty": "^13.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@livekit/rtc-node/node_modules/fast-copy": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-4.0.3.tgz", - "integrity": "sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw==", - "license": "MIT" - }, - "node_modules/@livekit/rtc-node/node_modules/pino": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", - "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", - "license": "MIT", - "dependencies": { - "@pinojs/redact": "^0.4.0", - "atomic-sleep": "^1.0.0", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^2.0.0", - "pino-std-serializers": "^7.0.0", - "process-warning": "^5.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^4.0.1", - "thread-stream": "^3.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/@livekit/rtc-node/node_modules/pino-abstract-transport": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", - "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", - "license": "MIT", - "dependencies": { - "split2": "^4.0.0" - } - }, - "node_modules/@livekit/rtc-node/node_modules/pino-pretty": { - "version": "13.1.3", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.1.3.tgz", - "integrity": "sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==", - "license": "MIT", - "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^4.0.0", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^3.0.0", - "pump": "^3.0.0", - "secure-json-parse": "^4.0.0", - "sonic-boom": "^4.0.1", - "strip-json-comments": "^5.0.2" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/@livekit/rtc-node/node_modules/pino-pretty/node_modules/pino-abstract-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", - "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", - "license": "MIT", - "dependencies": { - "split2": "^4.0.0" - } - }, - "node_modules/@livekit/rtc-node/node_modules/pino-std-serializers": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", - "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", - "license": "MIT" - }, - "node_modules/@livekit/rtc-node/node_modules/process-warning": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", - "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/@livekit/rtc-node/node_modules/secure-json-parse": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.0.tgz", - "integrity": "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/@livekit/rtc-node/node_modules/sonic-boom": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", - "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/@livekit/rtc-node/node_modules/strip-json-comments": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz", - "integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@livekit/rtc-node/node_modules/thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", - "license": "MIT", - "dependencies": { - "real-require": "^0.2.0" - } - }, - "node_modules/@livekit/throws-transformer": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@livekit/throws-transformer/-/throws-transformer-0.1.8.tgz", - "integrity": "sha512-AaSwQfIaG6YArKOCO+5/DgI8HfL19oHdrkyI0LJJVCqGeZXzPsZIO/Nm/SKUHbT1ERGhF5c34X8CcVWeOePpIQ==", - "license": "Apache-2.0", - "dependencies": { - "glob": "^13.0.0" - }, - "bin": { - "throws-check": "dist/cli.js" - }, - "peerDependencies": { - "typescript": ">=4.7.0" - } - }, - "node_modules/@livekit/typed-emitter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@livekit/typed-emitter/-/typed-emitter-3.0.0.tgz", - "integrity": "sha512-9bl0k4MgBPZu3Qu3R3xy12rmbW17e3bE9yf4YY85gJIQ3ezLEj/uzpKHWBsLaDoL5Mozz8QCgggwIBudYQWeQg==", - "license": "MIT" - }, - "node_modules/@opentelemetry/api": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", - "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@opentelemetry/api-logs": { - "version": "0.54.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.54.2.tgz", - "integrity": "sha512-4MTVwwmLgUh5QrJnZpYo6YRO5IBLAggf2h8gWDblwRagDStY13aEvt7gGk3jewrMaPlHiF83fENhIx0HO97/cQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.3.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/context-async-hooks": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz", - "integrity": "sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/core": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.7.1.tgz", - "integrity": "sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto": { - "version": "0.54.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.54.2.tgz", - "integrity": "sha512-agrzFbSNmIy6dhkyg41ERlEDUDqkaUJj2n/tVRFp9Tl+6wyNVPsqmwU5RWJOXpyK+lYH/znv6A47VpTeJF0lrw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.54.2", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-exporter-base": "0.54.2", - "@opentelemetry/otlp-transformer": "0.54.2", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-logs": "0.54.2", - "@opentelemetry/sdk-trace-base": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", - "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.54.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.54.2.tgz", - "integrity": "sha512-NrNyxu6R/bGAwanhz1HI0aJWKR6xUED4TjCH4iWMlAfyRukGbI9Kt/Akd2sYLwRKNhfS+sKetKGCUQPMDyYYMA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-transformer": "0.54.2" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/resources": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.27.0.tgz", - "integrity": "sha512-jOwt2VJ/lUD5BLc+PMNymDrUCpm5PKi1E9oSVYAvz01U/VdndGmrtV3DU1pG4AwlYhJRHbHfOUIlpBeXCPw6QQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.27.0.tgz", - "integrity": "sha512-btz6XTQzwsyJjombpeqCX6LhiMQYpzt2pIYNPnw0IPO/3AhT6yjnf8Mnv3ZC2A4eRYOjqrg+bfaXg9XHDRJDWQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", - "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto": { - "version": "0.54.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.54.2.tgz", - "integrity": "sha512-XSmm1N2wAhoWDXP1q/N6kpLebWaxl6VIADv4WA5QWKHLRpF3gLz5NAWNJBR8ygsvv8jQcrwnXgwfnJ18H3v1fg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-exporter-base": "0.54.2", - "@opentelemetry/otlp-transformer": "0.54.2", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", - "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.54.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.54.2.tgz", - "integrity": "sha512-NrNyxu6R/bGAwanhz1HI0aJWKR6xUED4TjCH4iWMlAfyRukGbI9Kt/Akd2sYLwRKNhfS+sKetKGCUQPMDyYYMA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/otlp-transformer": "0.54.2" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.27.0.tgz", - "integrity": "sha512-jOwt2VJ/lUD5BLc+PMNymDrUCpm5PKi1E9oSVYAvz01U/VdndGmrtV3DU1pG4AwlYhJRHbHfOUIlpBeXCPw6QQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.27.0.tgz", - "integrity": "sha512-btz6XTQzwsyJjombpeqCX6LhiMQYpzt2pIYNPnw0IPO/3AhT6yjnf8Mnv3ZC2A4eRYOjqrg+bfaXg9XHDRJDWQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", - "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/instrumentation": { - "version": "0.54.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.54.2.tgz", - "integrity": "sha512-go6zpOVoZVztT9r1aPd79Fr3OWiD4N24bCPJsIKkBses8oyFo12F/Ew3UBTdIu6hsW4HC4MVEJygG6TEyJI/lg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.54.2", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pino": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.43.0.tgz", - "integrity": "sha512-jlOOgbODWRRNknWXY1VLgmqgG0SO4kLgU3XnejjO/3De4OisroAsMGk+1cRB5AQ6WZ8WLAMkMyTShaOe6j2Asw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "^0.54.0", - "@opentelemetry/core": "^1.25.0", - "@opentelemetry/instrumentation": "^0.54.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pino/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/instrumentation-pino/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.208.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.208.0.tgz", - "integrity": "sha512-gMd39gIfVb2OgxldxUtOwGJYSH8P1kVFFlJLuut32L6KgUC4gl1dMhn+YC2mGn0bDOiQYSk/uHOdSjuKp58vvA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/otlp-transformer": "0.208.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/api-logs": { - "version": "0.208.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.208.0.tgz", - "integrity": "sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.3.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/core": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz", - "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/otlp-transformer": { - "version": "0.208.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.208.0.tgz", - "integrity": "sha512-DCFPY8C6lAQHUNkzcNT9R+qYExvsk6C5Bto2pbNxgicpcSWbe2WHShLxkOxIdNcBiYPdVHv/e7vH7K6TI+C+fQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.208.0", - "@opentelemetry/core": "2.2.0", - "@opentelemetry/resources": "2.2.0", - "@opentelemetry/sdk-logs": "0.208.0", - "@opentelemetry/sdk-metrics": "2.2.0", - "@opentelemetry/sdk-trace-base": "2.2.0", - "protobufjs": "^7.3.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/resources": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", - "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/sdk-logs": { - "version": "0.208.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.208.0.tgz", - "integrity": "sha512-QlAyL1jRpOeaqx7/leG1vJMp84g0xKP6gJmfELBpnI4O/9xPX+Hu5m1POk9Kl+veNkyth5t19hRlN6tNY1sjbA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.208.0", - "@opentelemetry/core": "2.2.0", - "@opentelemetry/resources": "2.2.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/sdk-metrics": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.2.0.tgz", - "integrity": "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/resources": "2.2.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.9.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.2.0.tgz", - "integrity": "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.2.0", - "@opentelemetry/resources": "2.2.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer": { - "version": "0.54.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.54.2.tgz", - "integrity": "sha512-2tIjahJlMRRUz0A2SeE+qBkeBXBFkSjR0wqJ08kuOqaL8HNGan5iZf+A8cfrfmZzPUuMKCyY9I+okzFuFs6gKQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.54.2", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/sdk-logs": "0.54.2", - "@opentelemetry/sdk-metrics": "1.27.0", - "@opentelemetry/sdk-trace-base": "1.27.0", - "protobufjs": "^7.3.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", - "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.27.0.tgz", - "integrity": "sha512-jOwt2VJ/lUD5BLc+PMNymDrUCpm5PKi1E9oSVYAvz01U/VdndGmrtV3DU1pG4AwlYhJRHbHfOUIlpBeXCPw6QQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.27.0.tgz", - "integrity": "sha512-btz6XTQzwsyJjombpeqCX6LhiMQYpzt2pIYNPnw0IPO/3AhT6yjnf8Mnv3ZC2A4eRYOjqrg+bfaXg9XHDRJDWQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", - "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/propagator-b3": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.30.1.tgz", - "integrity": "sha512-oATwWWDIJzybAZ4pO76ATN5N6FFbOA1otibAVlS8v90B4S1wClnhRUk7K+2CHAwN1JKYuj4jh/lpCEG5BAqFuQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/propagator-b3/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/propagator-b3/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/propagator-jaeger": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.30.1.tgz", - "integrity": "sha512-Pj/BfnYEKIOImirH76M4hDaBSx6HyZ2CXUqk+Kj02m6BB80c/yo4BdWkn/1gDFfU+YPY+bPR2U0DKBfdxCKwmg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/propagator-jaeger/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/propagator-jaeger/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/resources": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", - "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/sdk-logs": { - "version": "0.54.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.54.2.tgz", - "integrity": "sha512-yIbYqDLS/AtBbPjCjh6eSToGNRMqW2VR8RrKEy+G+J7dFG7pKoptTH5T+XlKPleP9NY8JZYIpgJBlI+Osi0rFw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.54.2", - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", - "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.27.0.tgz", - "integrity": "sha512-jOwt2VJ/lUD5BLc+PMNymDrUCpm5PKi1E9oSVYAvz01U/VdndGmrtV3DU1pG4AwlYhJRHbHfOUIlpBeXCPw6QQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", - "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/sdk-metrics": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.27.0.tgz", - "integrity": "sha512-JzWgzlutoXCydhHWIbLg+r76m+m3ncqvkCcsswXAQ4gqKS+LOHKhq+t6fx1zNytvLuaOUBur7EvWxECc4jPQKg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/resources": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/core": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.27.0.tgz", - "integrity": "sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/resources": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.27.0.tgz", - "integrity": "sha512-jOwt2VJ/lUD5BLc+PMNymDrUCpm5PKi1E9oSVYAvz01U/VdndGmrtV3DU1pG4AwlYhJRHbHfOUIlpBeXCPw6QQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.27.0", - "@opentelemetry/semantic-conventions": "1.27.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz", - "integrity": "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz", - "integrity": "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/sdk-trace-node": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.30.1.tgz", - "integrity": "sha512-cBjYOINt1JxXdpw1e5MlHmFRc5fgj4GW/86vsKFxJCJ8AL4PdVtYH41gWwl4qd4uQjqEL1oJVrXkSy5cnduAnQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/context-async-hooks": "1.30.1", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/propagator-b3": "1.30.1", - "@opentelemetry/propagator-jaeger": "1.30.1", - "@opentelemetry/sdk-trace-base": "1.30.1", - "semver": "^7.5.2" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.41.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.41.1.tgz", - "integrity": "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@pinecone-database/pinecone": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@pinecone-database/pinecone/-/pinecone-6.1.4.tgz", - "integrity": "sha512-wkipvpkBYNGYDeYj4azVVyCzSrekJE3Pgo0HImkbw80SGnTo9gz5kSbDCXCfVvFnhqC2q4nGikdTUvFCDiuruA==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@pinojs/redact": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", - "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", - "license": "MIT" - }, - "node_modules/@posthog/core": { - "version": "1.29.5", - "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.29.5.tgz", - "integrity": "sha512-Jm5AE95EwBRqO6J8+skDufyf5rnEcmOvjYArCKCOzD4mWdH1xGpfcRXj5TEyZII3mD04Kr7pw9aP2ZbAHQGu2A==", - "license": "MIT", - "dependencies": { - "@posthog/types": "1.374.2" - } - }, - "node_modules/@posthog/types": { - "version": "1.374.2", - "resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.374.2.tgz", - "integrity": "sha512-ZghQSFMi+HFJNPvPjBoyY/jWQ+q6mSQVtWQxOHMSbBidUZjsyYbxYxBFbHy2qWLNe4mEpX+Wqir2Q4I/4AVvJQ==", - "license": "MIT" - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", - "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", - "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz", - "integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", - "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", - "license": "BSD-3-Clause" - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "license": "MIT" - }, - "node_modules/@tailwindcss/node": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.0.tgz", - "integrity": "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==", - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "^5.21.0", - "jiti": "^2.6.1", - "lightningcss": "1.32.0", - "magic-string": "^0.30.21", - "source-map-js": "^1.2.1", - "tailwindcss": "4.3.0" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.0.tgz", - "integrity": "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==", - "license": "MIT", - "engines": { - "node": ">= 20" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.3.0", - "@tailwindcss/oxide-darwin-arm64": "4.3.0", - "@tailwindcss/oxide-darwin-x64": "4.3.0", - "@tailwindcss/oxide-freebsd-x64": "4.3.0", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0", - "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0", - "@tailwindcss/oxide-linux-arm64-musl": "4.3.0", - "@tailwindcss/oxide-linux-x64-gnu": "4.3.0", - "@tailwindcss/oxide-linux-x64-musl": "4.3.0", - "@tailwindcss/oxide-wasm32-wasi": "4.3.0", - "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0", - "@tailwindcss/oxide-win32-x64-msvc": "4.3.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.0.tgz", - "integrity": "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/postcss": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.0.tgz", - "integrity": "sha512-Jm05Tjx+9yCLGv5qw1c+84Psds8MnyrEQYCB+FFk2lgGiUjlRqdxke4mVTuYrj2xnVZqKim2Apr5ySuQRYAw/w==", - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.3.0", - "@tailwindcss/oxide": "4.3.0", - "postcss": "^8.5.10", - "tailwindcss": "4.3.0" - } - }, - "node_modules/@tanstack/query-core": { - "version": "5.100.11", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.100.11.tgz", - "integrity": "sha512-lmE0994apShXPj8CUxgx4ch5yUJhE9k/+tVwihBvPOyerACWdBocfFg24t8+0RhtlTd7tEgchDkhlCxNssvDxw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/react-query": { - "version": "5.100.11", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.100.11.tgz", - "integrity": "sha512-J0f9s5x3LE1450nNNfYx+e/n0DMa0uOBdFJUy5r0RvmsXd4nB/n0rbHtHI1vYXhikNFan+wf51p6Tmp4c8ucrg==", - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "5.100.11" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^18 || ^19" - } - }, - "node_modules/@truestamp/canonify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@truestamp/canonify/-/canonify-2.1.0.tgz", - "integrity": "sha512-j9GsioYlfLrZmPfkhLCsPMdhsa6CaXHOkERwEU+Ax2o7JL3ZvtD5PfPj1sDsacvDoG2W/Sx99wkIWPLa0gNN5w==", - "license": "MIT License" - }, - "node_modules/@ts-morph/common": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.28.1.tgz", - "integrity": "sha512-W74iWf7ILp1ZKNYXY5qbddNaml7e9Sedv5lvU1V8lftlitkc9Pq1A+jlH23ltDgWYeZFFEqGCD1Ies9hqu3O+g==", - "license": "MIT", - "dependencies": { - "minimatch": "^10.0.1", - "path-browserify": "^1.0.1", - "tinyglobby": "^0.2.14" - } - }, - "node_modules/@types/inquirer": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.9.tgz", - "integrity": "sha512-/mWx5136gts2Z2e5izdoRCo46lPp5TMs9R15GTSsgg/XnZyxDWVqoVU3R9lWnccKpqwsJLvRoxbCjoJtZB7DSw==", - "license": "MIT", - "dependencies": { - "@types/through": "*", - "rxjs": "^7.2.0" - } - }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.19.41", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.41.tgz", - "integrity": "sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/pidusage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/pidusage/-/pidusage-2.0.5.tgz", - "integrity": "sha512-MIiyZI4/MK9UGUXWt0jJcCZhVw7YdhBuTOuqP/BjuLDLZ2PmmViMIQgZiWxtaMicQfAz/kMrZ5T7PKxFSkTeUA==", - "license": "MIT" - }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "license": "MIT" - }, - "node_modules/@types/shimmer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", - "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", - "license": "MIT" - }, - "node_modules/@types/through": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz", - "integrity": "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@vercel/oidc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.1.0.tgz", - "integrity": "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==", - "license": "Apache-2.0", - "engines": { - "node": ">= 20" - } - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ai": { - "version": "5.0.188", - "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.188.tgz", - "integrity": "sha512-ABV+wRB1hz3UTZJTTqFIDi85tzUyr9o1ZKO5ZYZluFYlhZgKGOaInWaYv+OnBAb+qLpXWsrTWemd9/XShZJN0g==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/gateway": "2.0.89", - "@ai-sdk/provider": "2.0.3", - "@ai-sdk/provider-utils": "3.0.25", - "@opentelemetry/api": "1.9.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/ai/node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/autoprefixer": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", - "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.28.2", - "caniuse-lite": "^1.0.30001787", - "fraction.js": "^5.3.4", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/axios": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.1.tgz", - "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.16.0", - "form-data": "^4.0.5", - "https-proxy-agent": "^5.0.1", - "proxy-from-env": "^2.1.0" - } - }, - "node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.31", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.31.tgz", - "integrity": "sha512-MujYO3eP72uvmSE0i4wltsodRfIpZATP3jvzRNRGGxgzId7aVocVJJV3nf01qnzzKFGxQVC9bpWxl5cjxTr/7Q==", - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bignumber.js": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", - "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", - "update-browserslist-db": "^1.2.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", - "license": "BSD-3-Clause" - }, - "node_modules/bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "license": "MIT", - "dependencies": { - "run-applescript": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-9.1.3.tgz", - "integrity": "sha512-Rircqi9ch8AnZscQcsA1C47NFdaO3wukpmIRzYcDOrmvgt78hM/sj5pZhZNec2NM12uk5vTwRHZ4anGcrC4ZTg==", - "license": "MIT", - "dependencies": { - "camelcase": "^8.0.0", - "map-obj": "5.0.0", - "quick-lru": "^6.1.1", - "type-fest": "^4.3.2" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001793", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", - "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chardet": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", - "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", - "license": "MIT" - }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", - "license": "MIT" - }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "license": "ISC", - "engines": { - "node": ">= 12" - } - }, - "node_modules/code-block-writer": { - "version": "13.0.3", - "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", - "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", - "license": "MIT" - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "license": "MIT" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", - "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", - "license": "MIT", - "engines": { - "node": ">=20" - } - }, - "node_modules/crosspath": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crosspath/-/crosspath-2.0.0.tgz", - "integrity": "sha512-ju88BYCQ2uvjO2bR+SsgLSTwTSctU+6Vp2ePbKPgSCZyy4MWZxYsT738DlKVRE5utUjobjPRm1MkTYKJxCmpTA==", - "license": "MIT", - "dependencies": { - "@types/node": "^17.0.36" - }, - "engines": { - "node": ">=14.9.0" - } - }, - "node_modules/crosspath/node_modules/@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", - "license": "MIT" - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/default-browser": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", - "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", - "license": "MIT", - "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", - "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/destr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", - "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/diff": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", - "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dotenv": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", - "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.359", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.359.tgz", - "integrity": "sha512-8lPELWuYZIWk7NDvCNthtmMw/7Q5Wu25NpM4djFMHBmk8DubPAtL4YTOp7ou0e7HyJtwkVlWv8XMLURnrtgJQw==", - "license": "ISC" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.21.5", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.5.tgz", - "integrity": "sha512-mLCNbrQli11K1ySUmuNt4ZUB3OpGIDq4q2vTBTf5cL2lpsRjI9QKqSD0ndjW8FyvcW/Jj46gMe9syyHAsvMa/A==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/eventsource-parser": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.8.tgz", - "integrity": "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, - "node_modules/fast-copy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", - "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", - "license": "MIT" - }, - "node_modules/fast-redact": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", - "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "license": "MIT" - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/fluent-ffmpeg": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.3.tgz", - "integrity": "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "license": "MIT", - "dependencies": { - "async": "^0.2.9", - "which": "^1.1.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/follow-redirects": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", - "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "license": "MIT", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/fraction.js": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", - "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gaxios": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz", - "integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==", - "license": "Apache-2.0", - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "node-fetch": "^3.3.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/gaxios/node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/gaxios/node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/gcp-metadata": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", - "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", - "license": "Apache-2.0", - "dependencies": { - "gaxios": "^7.0.0", - "google-logging-utils": "^1.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/google-auth-library": { - "version": "10.6.2", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz", - "integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==", - "license": "Apache-2.0", - "dependencies": { - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "gaxios": "^7.1.4", - "gcp-metadata": "8.1.2", - "google-logging-utils": "1.1.3", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/google-logging-utils": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", - "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", - "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/heap-js": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/heap-js/-/heap-js-2.7.1.tgz", - "integrity": "sha512-EQfezRg0NCZGNlhlDR3Evrw1FVL2G3LhU7EgPoxufQKruNBSYA8MiRPHeWbU+36o+Fhel0wMwM+sLEiBAlNLJA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", - "license": "MIT" - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/import-in-the-middle": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", - "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", - "license": "Apache-2.0", - "dependencies": { - "acorn": "^8.14.0", - "acorn-import-attributes": "^1.9.5", - "cjs-module-lexer": "^1.2.2", - "module-details-from-path": "^1.0.3" - } - }, - "node_modules/inquirer": { - "version": "12.11.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.11.1.tgz", - "integrity": "sha512-9VF7mrY+3OmsAfjH3yKz/pLbJ5z22E23hENKw3/LNSaA/sAt3v49bDRY+Ygct1xwuKT+U+cBfTzjCPySna69Qw==", - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/prompts": "^7.10.1", - "@inquirer/type": "^3.0.10", - "mute-stream": "^2.0.0", - "run-async": "^4.0.6", - "rxjs": "^7.8.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/is-core-module": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", - "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", - "license": "MIT", - "dependencies": { - "hasown": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "license": "MIT", - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-wsl": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", - "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", - "license": "MIT", - "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, - "node_modules/jiti": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", - "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/jose": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz", - "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "license": "MIT", - "dependencies": { - "bignumber.js": "^9.0.0" - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "node_modules/jwa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", - "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", - "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", - "license": "MIT", - "dependencies": { - "jwa": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/livekit-server-sdk": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/livekit-server-sdk/-/livekit-server-sdk-2.15.3.tgz", - "integrity": "sha512-CU+CaOsyiKR/8BW7myJ2LGNg7T66MV/HZx+AMeAiiGu8PQnVDwqJ42HEH61o20fH68e4cI+hYQcPA5Fs2aKv1g==", - "license": "Apache-2.0", - "dependencies": { - "@bufbuild/protobuf": "^1.10.1", - "@livekit/protocol": "^1.45.6", - "camelcase-keys": "^9.0.0", - "jose": "^5.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, - "node_modules/lru-cache": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.4.0.tgz", - "integrity": "sha512-W+R+kFL4HgVxONq2bhXPi3bGpzGe/yEhVOp233qw9wCRtgncJ15P3bC+e4zZMu4Cq7d+WAJjXGW0uUkifhcatA==", - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/lua-cli": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/lua-cli/-/lua-cli-3.16.0.tgz", - "integrity": "sha512-3P6bjXpT9L2TDp2rCIaz2tb2QI3xk5nMHr/PwiwGQWlgxQik94tGZDDLLyTrQQoVNJuKdp0x5MhTYwUeFC9pCg==", - "license": "MIT", - "dependencies": { - "@livekit/agents": "^1.4.2", - "@livekit/agents-plugin-deepgram": "^1.4.2", - "@livekit/agents-plugin-elevenlabs": "^1.4.2", - "@livekit/agents-plugin-google": "^1.4.2", - "@livekit/agents-plugin-openai": "^1.4.2", - "@livekit/agents-plugin-xai": "^1.4.2", - "@livekit/rtc-node": "^0.13.27", - "@tailwindcss/postcss": "^4.1.14", - "@tanstack/react-query": "^5.90.11", - "@truestamp/canonify": "^2.1.0", - "ai": "^5.0.76", - "autoprefixer": "^10.4.21", - "chalk": "^5.3.0", - "commander": "^14.0.1", - "diff": "^8.0.2", - "dotenv": "^17.2.3", - "esbuild": "^0.25.10", - "inquirer": "^12.9.6", - "js-yaml": "^4.1.0", - "open": "^10.1.0", - "posthog-node": "^5.26.0", - "ts-evaluator": "^2.0.0", - "ts-morph": "^27.0.0", - "typescript": "^5.9.2", - "undici": "^6.21.0", - "zod": "^3.25.76", - "zod-to-json-schema": "^3.24.6" - }, - "bin": { - "heylua": "dist/index.js", - "lua": "dist/index.js", - "lua-ai": "dist/index.js" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/map-obj": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-5.0.0.tgz", - "integrity": "sha512-2L3MIgJynYrZ3TYMriLDLWocz15okFakV6J12HXvMXDHui2x/zgChzg1u9mFFGbbGWE+GsLpQByt4POb9Or+uA==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/module-details-from-path": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", - "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "deprecated": "Use your platform's native DOMException instead", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "license": "MIT", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/node-fetch-native": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", - "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.44", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", - "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==", - "license": "MIT" - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-path": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.8.tgz", - "integrity": "sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==", - "license": "MIT", - "engines": { - "node": ">= 10.12.0" - } - }, - "node_modules/ofetch": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", - "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", - "license": "MIT", - "dependencies": { - "destr": "^2.0.5", - "node-fetch-native": "^1.6.7", - "ufo": "^1.6.1" - } - }, - "node_modules/on-exit-leak-free": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", - "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/open": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", - "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", - "license": "MIT", - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "wsl-utils": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/openai": { - "version": "5.23.2", - "resolved": "https://registry.npmjs.org/openai/-/openai-5.23.2.tgz", - "integrity": "sha512-MQBzmTulj+MM5O8SKEk/gL8a7s5mktS9zUtAkU257WjvobGc9nKcBuVwjyEEcb9SI8a8Y2G/mzn3vm9n1Jlleg==", - "license": "Apache-2.0", - "bin": { - "openai": "bin/cli" - }, - "peerDependencies": { - "ws": "^8.18.0", - "zod": "^3.23.8" - }, - "peerDependenciesMeta": { - "ws": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "license": "MIT", - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "license": "MIT" - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", - "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidusage": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-4.0.1.tgz", - "integrity": "sha512-yCH2dtLHfEBnzlHUJymR/Z1nN2ePG3m392Mv8TFlTP1B0xkpMQNHAnfkY0n2tAi6ceKO6YWhxYfZ96V4vVkh/g==", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/pino": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.21.0.tgz", - "integrity": "sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==", - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.2.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^3.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^3.7.0", - "thread-stream": "^2.6.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-abstract-transport": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", - "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", - "license": "MIT", - "dependencies": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - } - }, - "node_modules/pino-pretty": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.3.0.tgz", - "integrity": "sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA==", - "license": "MIT", - "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.2", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^2.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^4.0.1", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/pino-pretty/node_modules/pino-abstract-transport": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", - "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", - "license": "MIT", - "dependencies": { - "split2": "^4.0.0" - } - }, - "node_modules/pino-pretty/node_modules/sonic-boom": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", - "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/pino-std-serializers": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", - "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==", - "license": "MIT" - }, - "node_modules/postcss": { - "version": "8.5.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", - "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.12", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "license": "MIT" - }, - "node_modules/posthog-node": { - "version": "5.34.6", - "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-5.34.6.tgz", - "integrity": "sha512-oDjagFRkmCbWJBxG1FVU3kOGC6dxNpR849q8ARrZSBK3zWz4zJox6V5EjrATKM9RXKvAmbCSFoxYaOYTzp3phA==", - "license": "MIT", - "dependencies": { - "@posthog/core": "1.29.5" - }, - "engines": { - "node": "^20.20.0 || >=22.22.0" - }, - "peerDependencies": { - "rxjs": "^7.0.0" - }, - "peerDependenciesMeta": { - "rxjs": { - "optional": true - } - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", - "license": "MIT" - }, - "node_modules/protobufjs": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.0.tgz", - "integrity": "sha512-LtESOsMPTZgyYtwxhvdgdjGL0HmXEaRA/hVD6sol4zA60hVXXXP/SGmxnqDbgGE8gy7pYex7cym+5vYPcmaXBQ==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.5", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.1", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.2", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.1", - "@types/node": ">=13.7.0", - "long": "^5.3.2" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/proxy-from-env": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", - "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/pump": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", - "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/qs": { - "version": "6.15.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", - "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/quick-format-unescaped": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", - "license": "MIT" - }, - "node_modules/quick-lru": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.2.tgz", - "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react": { - "version": "19.2.6", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", - "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/real-require": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", - "license": "MIT", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/require-in-the-middle": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", - "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/resolve": { - "version": "1.22.12", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", - "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/run-applescript": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", - "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-async": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-4.0.6.tgz", - "integrity": "sha512-IoDlSLTs3Yq593mb3ZoKWKXMNu3UpObxhgA/Xuid5p4bbfi2jdY1Hj0m1K+0/tEuQTxIGMhQDqGjKb7RuxGpAQ==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safe-stable-stringify": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", - "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/secure-json-parse": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", - "license": "BSD-3-Clause" - }, - "node_modules/semver": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", - "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sharp": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@img/colour": "^1.0.0", - "detect-libc": "^2.1.2", - "semver": "^7.7.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.5", - "@img/sharp-darwin-x64": "0.34.5", - "@img/sharp-libvips-darwin-arm64": "1.2.4", - "@img/sharp-libvips-darwin-x64": "1.2.4", - "@img/sharp-libvips-linux-arm": "1.2.4", - "@img/sharp-libvips-linux-arm64": "1.2.4", - "@img/sharp-libvips-linux-ppc64": "1.2.4", - "@img/sharp-libvips-linux-riscv64": "1.2.4", - "@img/sharp-libvips-linux-s390x": "1.2.4", - "@img/sharp-libvips-linux-x64": "1.2.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", - "@img/sharp-libvips-linuxmusl-x64": "1.2.4", - "@img/sharp-linux-arm": "0.34.5", - "@img/sharp-linux-arm64": "0.34.5", - "@img/sharp-linux-ppc64": "0.34.5", - "@img/sharp-linux-riscv64": "0.34.5", - "@img/sharp-linux-s390x": "0.34.5", - "@img/sharp-linux-x64": "0.34.5", - "@img/sharp-linuxmusl-arm64": "0.34.5", - "@img/sharp-linuxmusl-x64": "0.34.5", - "@img/sharp-wasm32": "0.34.5", - "@img/sharp-win32-arm64": "0.34.5", - "@img/sharp-win32-ia32": "0.34.5", - "@img/sharp-win32-x64": "0.34.5" - } - }, - "node_modules/shimmer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", - "license": "BSD-2-Clause" - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", - "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sonic-boom": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", - "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stripe": { - "version": "17.7.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-17.7.0.tgz", - "integrity": "sha512-aT2BU9KkizY9SATf14WhhYVv2uOapBWX0OFWF4xvcj1mPaNotlSc2CsxpS4DS46ZueSppmCF5BX1sNYBtwBvfw==", - "license": "MIT", - "dependencies": { - "@types/node": ">=8.1.0", - "qs": "^6.11.0" - }, - "engines": { - "node": ">=12.*" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tailwindcss": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz", - "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==", - "license": "MIT" - }, - "node_modules/tapable": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", - "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/thread-stream": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", - "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==", - "license": "MIT", - "dependencies": { - "real-require": "^0.2.0" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/ts-evaluator": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-evaluator/-/ts-evaluator-2.0.0.tgz", - "integrity": "sha512-NcvI1QzdutjcDTHRcUdH+hM6I4dPrreDlDHdLoxQ3uj7icoJtSrX2mJYjmazW8QW2XSaZRiru4VcrSHysvRFAQ==", - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.3", - "crosspath": "^2.0.0", - "object-path": "^0.11.8" - }, - "engines": { - "node": ">=18.20.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/wessberg/ts-evaluator?sponsor=1" - }, - "peerDependencies": { - "jsdom": ">=14.x || >=15.x || >=16.x || >=17.x || >=18.x || >=19.x || >=20.x || >=21.x || >=22.x", - "typescript": ">=3.2.x || >= 4.x || >= 5.x" - }, - "peerDependenciesMeta": { - "jsdom": { - "optional": true - } - } - }, - "node_modules/ts-morph": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-27.0.2.tgz", - "integrity": "sha512-fhUhgeljcrdZ+9DZND1De1029PrE+cMkIP7ooqkLRTrRLTqcki2AstsyJm0vRNbTbVCNJ0idGlbBrfqc7/nA8w==", - "license": "MIT", - "dependencies": { - "@ts-morph/common": "~0.28.1", - "code-block-writer": "^13.0.3" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tsx": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.3.tgz", - "integrity": "sha512-mdoNxBC/cSQObGGVQ5Bpn5i+yv7j68gk3Nfm3wFjcJg3Z0Mix9jzAFfP12prmm5eVGmDKtp0yyArrs0Q+8gZHg==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.28.0" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", - "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/esbuild": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", - "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.0", - "@esbuild/android-arm": "0.28.0", - "@esbuild/android-arm64": "0.28.0", - "@esbuild/android-x64": "0.28.0", - "@esbuild/darwin-arm64": "0.28.0", - "@esbuild/darwin-x64": "0.28.0", - "@esbuild/freebsd-arm64": "0.28.0", - "@esbuild/freebsd-x64": "0.28.0", - "@esbuild/linux-arm": "0.28.0", - "@esbuild/linux-arm64": "0.28.0", - "@esbuild/linux-ia32": "0.28.0", - "@esbuild/linux-loong64": "0.28.0", - "@esbuild/linux-mips64el": "0.28.0", - "@esbuild/linux-ppc64": "0.28.0", - "@esbuild/linux-riscv64": "0.28.0", - "@esbuild/linux-s390x": "0.28.0", - "@esbuild/linux-x64": "0.28.0", - "@esbuild/netbsd-arm64": "0.28.0", - "@esbuild/netbsd-x64": "0.28.0", - "@esbuild/openbsd-arm64": "0.28.0", - "@esbuild/openbsd-x64": "0.28.0", - "@esbuild/openharmony-arm64": "0.28.0", - "@esbuild/sunos-x64": "0.28.0", - "@esbuild/win32-arm64": "0.28.0", - "@esbuild/win32-ia32": "0.28.0", - "@esbuild/win32-x64": "0.28.0" - } - }, - "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/ufo": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", - "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", - "license": "MIT" - }, - "node_modules/undici": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.25.0.tgz", - "integrity": "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==", - "license": "MIT", - "engines": { - "node": ">=18.17" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "license": "MIT" - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uuid": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.2.tgz", - "integrity": "sha512-vzi9uRZ926x4XV73S/4qQaTwPXM2JBj6/6lI/byHH1jOpCzb0zDbfytgA9LcN/hzb2l7WQSQnxITOVx5un/wGw==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist-node/bin/uuid" - } - }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, - "node_modules/ws": { - "version": "8.20.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", - "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/wsl-utils": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", - "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", - "license": "MIT", - "dependencies": { - "is-wsl": "^3.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yoctocolors-cjs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", - "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.2", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", - "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25.28 || ^4" - } - } - } -} diff --git a/package-lock.json b/package-lock.json index 49621894..7ff95a55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@pinecone-database/pinecone": "^6.1.2", "@types/inquirer": "^9.0.9", "@types/js-yaml": "^4.0.9", + "@vercel/kv": "^3.0.0", "axios": "^1.6.0", "inquirer": "^12.9.6", "js-yaml": "^4.1.0", @@ -23,6 +24,7 @@ }, "devDependencies": { "@types/node": "^20.10.0", + "express": "^4.18.2", "tsx": "^4.7.0", "typescript": "^5.9.2" } @@ -3285,6 +3287,28 @@ "@types/node": "*" } }, + "node_modules/@upstash/redis": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/@upstash/redis/-/redis-1.38.0.tgz", + "integrity": "sha512-wu+dZBptlLy0+MCUEoHmzrY/TnmgDey3+c7EbIGwrLqAvkP8yi5MWZHYGIFtAygmL4Bkz2TdFu+eU0vFPncIcg==", + "license": "MIT", + "dependencies": { + "uncrypto": "^0.1.3" + } + }, + "node_modules/@vercel/kv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@vercel/kv/-/kv-3.0.0.tgz", + "integrity": "sha512-pKT8fRnfyYk2MgvyB6fn6ipJPCdfZwiKDdw7vB+HL50rjboEBHDVBEcnwfkEpVSp2AjNtoaOUH7zG+bVC/rvSg==", + "deprecated": "Vercel KV is deprecated. If you had an existing KV store, it should have moved to Upstash Redis which you will see under Vercel Integrations. For new projects, install a Redis integration from Vercel Marketplace: https://vercel.com/marketplace?category=storage&search=redis", + "license": "Apache-2.0", + "dependencies": { + "@upstash/redis": "^1.34.0" + }, + "engines": { + "node": ">=14.6" + } + }, "node_modules/@vercel/oidc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.1.0.tgz", @@ -3306,6 +3330,20 @@ "node": ">=6.5" } }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", @@ -3405,6 +3443,13 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "license": "Python-2.0" }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true, + "license": "MIT" + }, "node_modules/async": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", @@ -3523,6 +3568,61 @@ "node": "*" } }, + "node_modules/body-parser": { + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, "node_modules/brace-expansion": { "version": "5.0.6", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", @@ -3613,6 +3713,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -3776,6 +3886,46 @@ "node": ">=20" } }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "dev": true, + "license": "MIT" + }, "node_modules/crosspath": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crosspath/-/crosspath-2.0.0.tgz", @@ -3878,12 +4028,33 @@ "node": ">=0.4.0" } }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/destr": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", "license": "MIT" }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -3937,6 +4108,13 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, "node_modules/electron-to-chromium": { "version": "1.5.359", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.359.tgz", @@ -3949,6 +4127,16 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", @@ -4066,6 +4254,23 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -4093,6 +4298,70 @@ "node": ">=18.0.0" } }, + "node_modules/express": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.15.1", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -4160,6 +4429,42 @@ "node": "^12.20 || >= 14.13" } }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, "node_modules/fluent-ffmpeg": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.3.tgz", @@ -4222,6 +4527,16 @@ "node": ">=12.20.0" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fraction.js": { "version": "5.3.4", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", @@ -4235,6 +4550,16 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -4461,6 +4786,27 @@ "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", "license": "MIT" }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -4522,6 +4868,13 @@ "module-details-from-path": "^1.0.3" } }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, "node_modules/inquirer": { "version": "12.11.1", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.11.1.tgz", @@ -4548,6 +4901,16 @@ } } }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/is-core-module": { "version": "2.16.2", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", @@ -5053,6 +5416,49 @@ "node": ">= 0.4" } }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -5146,6 +5552,16 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -5237,6 +5653,19 @@ "node": ">=14.0.0" } }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5298,6 +5727,16 @@ "node": ">=8" } }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -5326,6 +5765,13 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -5530,6 +5976,20 @@ "node": ">=12.0.0" } }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/proxy-from-env": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", @@ -5582,6 +6042,45 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react": { "version": "19.2.6", "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", @@ -5744,6 +6243,71 @@ "node": ">=10" } }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, "node_modules/sharp": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", @@ -5905,6 +6469,16 @@ "node": ">= 10.x" } }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -6021,6 +6595,16 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, "node_modules/ts-evaluator": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ts-evaluator/-/ts-evaluator-2.0.0.tgz", @@ -6579,6 +7163,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -6598,6 +7196,12 @@ "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", "license": "MIT" }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", + "license": "MIT" + }, "node_modules/undici": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/undici/-/undici-6.25.0.tgz", @@ -6613,6 +7217,16 @@ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "license": "MIT" }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -6643,6 +7257,16 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/uuid": { "version": "13.0.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.2.tgz", @@ -6656,6 +7280,16 @@ "uuid": "dist-node/bin/uuid" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/web-streams-polyfill": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", diff --git a/package.json b/package.json index 79021de0..8377c849 100644 --- a/package.json +++ b/package.json @@ -8,12 +8,14 @@ "main": "src/index.ts", "scripts": { "start": "tsx src/index.ts", - "dev": "tsx watch src/index.ts", + "dev": "node dev-server.mjs", + "dev:agent": "tsx watch src/index.ts", "build": "tsc", "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { "@pinecone-database/pinecone": "^6.1.2", + "@vercel/kv": "^3.0.0", "@types/inquirer": "^9.0.9", "@types/js-yaml": "^4.0.9", "axios": "^1.6.0", @@ -27,6 +29,7 @@ }, "devDependencies": { "@types/node": "^20.10.0", + "express": "^4.18.2", "tsx": "^4.7.0", "typescript": "^5.9.2" } diff --git a/plan.md b/plan.md new file mode 100644 index 00000000..25b5cd74 --- /dev/null +++ b/plan.md @@ -0,0 +1,148 @@ +# Plan — Email + CTA Landing Implementation + +**Owner branch:** `review/latest-updates` +**Scope locked:** 4 features listed in §2. Anything outside is OUT-OF-SCOPE. +**Working principle:** Audit existing code first, refactor where needed, rebuild nothing that already works. + +--- + +## 1. Roles + +| Role | Owner | Files in their lane | +|---|---|---| +| Backend | **User (you)** | `src/skills/capture-lead.skill.ts`, `src/skills/submit-cta.skill.ts`, `sheets-apps-script.gs`, `lua.skill.yaml`, env config | +| Frontend | **Collaborator** | `index.html` (CTA deep-link handler + landing screens), any frontend glue | + +Neither side edits files in the other lane without a heads-up in chat / commit. + +--- + +## 2. In-Scope Features (4) + +### F1. Email with full rendered analysis report +- Confirmation email to the lead must contain the **rendered evaluation report** (verdict, score band, 7-dimension breakdown, human vs agent compare cards, CTAs, footer). +- Trigger point: when `capture_lead` runs for a genuine lead-form submission (after `score_jd`), email1 sends. + +### F2. Email primary CTA = `recommended_cta` from the scoring primitive +- Primary CTA in the email body must match `scoringResult.recommended_cta` (`lua` or `tech_safari`). +- Alternative CTA = the other path, styled smaller. + +### F3. CTA click updates Google Sheets — Lua column or Talent Safari column +- When lead clicks the email CTA and submits the landing form, Sheets row for that email gets its `CTA Clicked` cell updated to `Lua` or `Talent Safari` depending on which path was taken. + +### F4. CTA URL lands on the existing landing screens inside `index.html` +- Lua path → renders the existing **Lua landing screen** (purple "Sent. Lua will be in touch within 24 hours." after form submit). +- Talent Safari path → renders the existing **Talent Safari brief screen** (green "Brief Talent Safari on this role." → "Brief sent. Talent Safari will reply within 1 business day."). +- Mechanism: `index.html` reads `?cta=lua|tech_safari` from `location.search` on page load → auto-jumps to that screen → prefills `name`, `email`, `company` from query params. + +--- + +## 3. Out-Of-Scope (do NOT touch) + +- Score-JD logic, Ada chat, brief-wizard, scrape-jd skills. +- Slack post format (existing). +- Follow-up email (`scheduleFollowupEmail`). +- Data primitive schemas already in production. +- Score-time auto-call gating. +- `changes.md` content — leave intact. +- Any styling/layout changes outside the CTA landing screens. +- Adding new env vars beyond what's already in `env.example`. + +If a touched file needs a change that drifts into out-of-scope behavior, STOP and ask before proceeding. + +--- + +## 4. Current-State Audit + +| Feature | File | Status | Action | +|---|---|---|---| +| F1 | `capture-lead.skill.ts` `renderReportHtml()` L137-225 | Built; QA never confirmed firing in prod | Audit + QA | +| F1 | `capture-lead.skill.ts` `sendEmail1()` L348-373 | Calls `renderReportHtml`, gated on `RESEND_API_KEY` + `FROM_EMAIL` | Confirm env vars set in prod | +| F2 | `capture-lead.skill.ts` L149 `primaryTs = s.recommended_cta !== 'lua'` | Built | Audit | +| F3 | `submit-cta.skill.ts` `updateSheetsRow()` L43-54 | Built; posts `action:'updateCta'` w/ `ctaClicked:'Lua'\|'Talent Safari'` | Audit + verify Apps Script side | +| F3 | `sheets-apps-script.gs` `updateCta` handler L46-54 | Built — finds row by email, writes to CTA Clicked column | Audit | +| F4 | `capture-lead.skill.ts` `ctaUrl()` L101-112 | Emits `?cta=lua\|tech_safari&rec=&role=&score=&email=&name=&company=` | Keep as-is | +| F4 | `index.html` query-param handler | **MISSING** — no code reads `?cta=` on load to auto-jump | **Build** | + +--- + +## 5. Task Allocation + +### Backend (User) — Lua skills + Apps Script + +**B1.** Audit `renderReportHtml()` against the production-deployed version. +- Diff `src/skills/capture-lead.skill.ts` ↔ `dist-v2/artifacts/tool/capture_lead.js` to confirm local edits match what's deployed (or stage a push). +- Verify all asset URLs in the email body resolve under `ASSET_BASE = https://agent.talentsafari.io` (the 8 PNG/SVG files in `public/` are now tracked under that path). + +**B2.** Verify `recommended_cta` → primary CTA mapping is correct for all 3 verdicts. +- `needs_human` → recommended should typically be `tech_safari` (primary = TS, alt = Lua). +- `strong_agent` → recommended should be `lua` (primary = Lua, alt = TS). +- `human_led_agent_assist` → check what `score_jd` sets; primary must follow whatever `recommended_cta` is, not the verdict. + +**B3.** Run sandbox QA via `/lua-qa` on the email-send path. +- Trigger: `lua chat --ci -e sandbox -m "" -t qa-email-report-`. +- Verify in logs: `Resend API` HTTP 200, no `Resend API error` thrown, `email1Sent: true` in tool result. +- If env vars missing in sandbox, document required keys for the collaborator's local test setup. + +**B4.** Confirm Apps Script `updateCta` action is wired to the same spreadsheet/webhook that `append` writes to. +- Read `sheets-apps-script.gs` — confirm `getSheets()[0]` matches the sheet where leads are appended. +- Confirm column index for `CTA Clicked` matches the position in `HEADERS`. + +**B5.** Verify CTA URL query-param contract is stable so the frontend can rely on it. +- Document exact keys emitted by `ctaUrl()`: `cta`, `rec`, `role`, `score`, `email`, `name`, `company`. +- Send the contract to Frontend so they read the same keys. + +**B6.** Push + deploy via `/lua-deploy` once F1-F3 audited and B3 QA passes. + +### Frontend (Collaborator) — index.html CTA landing + +**F1.** Add a `?cta=` reader on page load (or on `DOMContentLoaded`). +- Parse `URLSearchParams(location.search)`. +- If `cta=lua` → auto-show the Lua confirm/landing screen (the one ending with `#luaSuccess` per `index.html:830`). +- If `cta=tech_safari` → auto-show the Talent Safari brief screen (the one with `#tsBriefBody` → `#tsSuccess` per `index.html:793-795`). +- If `cta` absent → keep current default behavior; don't break the existing entry flow. + +**F2.** Prefill the landing form using `state.leadName`, `state.leadEmail`, `state.leadCompany` from query params. +- Hydrate `state` from `?name`, `?email`, `?company` before `prefillCtaForms()` runs (see existing `prefillCtaForms()` at `index.html:1412`). +- If a value is missing, leave the field empty — do not fabricate. + +**F3.** Sanity-check the existing `submitCta(path)` flow (`index.html:1387`). +- After deep-link land + prefill + user clicks submit, confirm it still fires `adaSessionUrl('cta')` POST so the backend `submit_cta` tool runs. +- Don't change the success-message strings (they match the screenshots). + +**F4.** Verify behavior on both desktop and mobile widths for the two landing variants — no layout regression vs the existing screens shown in the screenshots. + +**F5.** Update CTA contract doc (or inline comment) once F1/F2 land so Backend can confirm shared keys match. + +--- + +## 6. Definition of Done + +A test run satisfies every box below before this slice ships: + +- [ ] Submitting the lead form in production triggers an email to the lead's address within ~10s. +- [ ] Email body renders the full report (header logos, verdict chip, score bar, dimensions, candidate cards, CTAs, footer) in Gmail + Outlook web. +- [ ] Email primary CTA label + destination match `scoringResult.recommended_cta`. +- [ ] Clicking the primary CTA opens `index.html` and auto-lands on the matching screen (Lua confirm OR TS brief), prefilled. +- [ ] Submitting the landing form fires `submit_cta` → posts Slack + updates Sheets `CTA Clicked` cell for that email to `Lua` or `Talent Safari`. +- [ ] No regression to score_jd flow, Ada chat, or any out-of-scope behavior. +- [ ] No new env vars introduced beyond existing. + +--- + +## 7. Open Questions / Risks + +- **Email asset hosting:** `ASSET_BASE = https://agent.talentsafari.io` — confirm `public/*.png` files are actually served at that origin in production (Vercel `public/` is served at root, so this should work, but verify after deploy). +- **`talent-safari-logo.png` vs `talent-safari-logo.jpg`:** both exist in `public/`. `renderReportHtml` references `.png`. Confirm the `.png` is the canonical one. +- **Apps Script idempotency:** if `updateCta` runs twice for the same email, behavior = overwrite (acceptable). Confirm with collaborator that double-submit on the landing page is prevented client-side. +- **Query param max length:** if `role` title is very long, the URL could approach mail-client limits. `ctaUrl` truncation not currently in place — flag if QA shows broken links. +- **Sandbox vs production parity:** `lua sync --check` must be clean before deploy; B3 QA targets whichever env is in sync. + +--- + +## 8. Working Agreement + +- One PR (or one commit batch) per feature slice. Don't bundle F1+F4 into a single change. +- Backend pushes go through `/lua-deploy`. Frontend goes through the existing Vercel build. +- If either side hits a question that affects the other lane, ping in chat **before** editing. +- `changes.md` is read-only for this slice — historical record, do not append. diff --git a/public/lua-logo-full.png b/public/lua-logo-full.png new file mode 100644 index 00000000..613b6968 Binary files /dev/null and b/public/lua-logo-full.png differ diff --git a/public/lua-logo.png b/public/lua-logo.png new file mode 100644 index 00000000..8328550a Binary files /dev/null and b/public/lua-logo.png differ diff --git a/public/lua-logo.svg b/public/lua-logo.svg new file mode 100644 index 00000000..f5475563 --- /dev/null +++ b/public/lua-logo.svg @@ -0,0 +1,29 @@ + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + + +
diff --git a/public/social-facebook.png b/public/social-facebook.png new file mode 100644 index 00000000..bb93d9ee Binary files /dev/null and b/public/social-facebook.png differ diff --git a/public/social-instagram.png b/public/social-instagram.png new file mode 100644 index 00000000..c0850744 Binary files /dev/null and b/public/social-instagram.png differ diff --git a/public/social-linkedin.png b/public/social-linkedin.png new file mode 100644 index 00000000..411f3886 Binary files /dev/null and b/public/social-linkedin.png differ diff --git a/public/talent-safari-logo.jpg b/public/talent-safari-logo.jpg new file mode 100644 index 00000000..a78d18da Binary files /dev/null and b/public/talent-safari-logo.jpg differ diff --git a/public/talent-safari-logo.png b/public/talent-safari-logo.png new file mode 100644 index 00000000..2bac5559 Binary files /dev/null and b/public/talent-safari-logo.png differ diff --git a/public/talent-safari-logo1.jpg b/public/talent-safari-logo1.jpg new file mode 100644 index 00000000..f8953065 Binary files /dev/null and b/public/talent-safari-logo1.jpg differ diff --git a/sheets-apps-script.gs b/sheets-apps-script.gs new file mode 100644 index 00000000..ac1f9f33 --- /dev/null +++ b/sheets-apps-script.gs @@ -0,0 +1,84 @@ +// TalentSafari — leads logger (Google Apps Script). +// Bind to the target Google Sheet: Extensions → Apps Script → paste → Deploy as +// Web App (Execute as: Me; Who has access: Anyone). Copy the /exec URL and set it +// as the Lua agent env var SHEETS_WEBHOOK_URL. +// +// Contract (POST JSON): +// { action:'append', name, title, company, email, date, roleEvaluated, score, +// ctaClicked, verdict, recommendedCta, jd, analysis } +// { action:'updateCta', email, ctaClicked } // ctaClicked: 'Lua' | 'Talent Safari' +// +// Columns: Name · Title · Company · Email · Date · Role Evaluated · Score · CTA Clicked +// · Verdict · Recommended CTA · JD · Analysis +// CTA Clicked starts 'No' on append, flips to 'Lua'/'Talent Safari' on updateCta +// (matched by email, last matching row wins). + +const HEADERS = ['Name', 'Title', 'Company', 'Email', 'Date', 'Role Evaluated', 'Score', 'CTA Clicked', 'Verdict', 'Recommended CTA', 'JD', 'Analysis']; +const EMAIL_COL = 4; // 1-based column index of "Email" +const CTA_COL = 8; // 1-based column index of "CTA Clicked" + +function doPost(e) { + const lock = LockService.getScriptLock(); + lock.waitLock(30000); + try { + const body = JSON.parse(e.postData.contents); + const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; + ensureHeaders_(sheet); + + if (body.action === 'append') { + sheet.appendRow([ + body.name || '', + body.title || '', + body.company || '', + body.email || '', + body.date ? new Date(body.date) : new Date(), + body.roleEvaluated || '', + body.score != null ? body.score : '', + body.ctaClicked || 'No', + body.verdict || '', + body.recommendedCta || '', + body.jd || '', + body.analysis || '', + ]); + return json_({ ok: true, action: 'append' }); + } + + if (body.action === 'updateCta') { + const row = findLastRowByEmail_(sheet, body.email); + if (row > 0) { + sheet.getRange(row, CTA_COL).setValue(body.ctaClicked || body.ctaPath || 'No'); + return json_({ ok: true, action: 'updateCta', row: row }); + } + return json_({ ok: false, reason: 'email_not_found' }); + } + + return json_({ ok: false, reason: 'unknown_action' }); + } catch (err) { + return json_({ ok: false, error: String(err) }); + } finally { + lock.releaseLock(); + } +} + +function ensureHeaders_(sheet) { + if (sheet.getLastRow() === 0) sheet.appendRow(HEADERS); +} + +function findLastRowByEmail_(sheet, email) { + if (!email) return -1; + const last = sheet.getLastRow(); + if (last < 2) return -1; + const values = sheet.getRange(2, EMAIL_COL, last - 1, 1).getValues(); + for (let i = values.length - 1; i >= 0; i--) { // last match wins + if (String(values[i][0]).trim().toLowerCase() === email.trim().toLowerCase()) { + return i + 2; // back to sheet row index + } + } + return -1; +} + +function json_(obj) { + return ContentService + .createTextOutput(JSON.stringify(obj)) + .setMimeType(ContentService.MimeType.JSON); +} diff --git a/src/index.ts b/src/index.ts index 80c80e2e..b63af09c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,39 +1,22 @@ -import { LuaAgent } from 'lua-cli'; -import { scoreRoleSkill } from './skills/score-role.skill.js'; -import { captureLeadSkill } from './skills/capture-lead.skill.js'; -import { submitCtaSkill } from './skills/submit-cta.skill.js'; -import { adaChatSkill } from './skills/ada-chat.skill.js'; -import { briefWizardSkill } from './skills/brief-wizard.skill.js'; -import { scrapeJdSkill } from './skills/scrape-jd.skill.js'; +import { LuaAgent } from "lua-cli"; +import { scoreRoleSkill } from "./skills/score-role.skill.js"; +import { captureLeadSkill } from "./skills/capture-lead.skill.js"; +import { submitCtaSkill } from "./skills/submit-cta.skill.js"; +import { adaChatSkill } from "./skills/ada-chat.skill.js"; +import { briefWizardSkill } from "./skills/brief-wizard.skill.js"; +import { scrapeJdSkill } from "./skills/scrape-jd.skill.js"; -/** - * Your Lua AI Agent - * - * This is a minimal agent ready for you to customize. - * Add skills, webhooks, jobs, and processors as needed. - * - * Quick start: - * 1. Create a tool in src/skills/tools/MyTool.ts - * 2. Create a skill in src/skills/my.skill.ts - * 3. Import and add it to the skills array below - * 4. Run `lua test` to test your tool - * 5. Run `lua chat` to chat with your agent - * - * Need examples? Run `lua init --with-examples` in a new project - * or see: https://docs.heylua.ai/examples - */ const agent = new LuaAgent({ - name: 'Ada', + name: "Ada", persona: `## Identity & Role You are Ada — an AI agent built by Lua that evaluates job descriptions for automation fit. -You score roles honestly across 7 dimensions and return a verdict: should this seat be filled by a human (sourced by Talent Safari) or an AI agent (built by Lua)? +You score roles honestly across 7 dimensions and return a structured verdict. You sign every communication as: Ada · Built by Lua ## Business Context You are the AI-side of a joint lead magnet built by Talent Safari × Lua called "Human or Agent?". The tool is honest by design — roughly 40% of evaluations recommend hiring a human, which is the trust mechanism. Talent Safari handles human recruiting. Lua builds and deploys AI agents. -You route warm leads to the right partner based on the evaluation verdict. ## Tone & Communication Style - First-person, warm, direct — a capable colleague, not a chatbot @@ -42,48 +25,43 @@ You route warm leads to the right partner based on the evaluation verdict. - Never sound like a template or a generic AI response - No filler phrases ("Absolutely!", "Great question!") — they undermine the premium tone -## Capabilities (v1) +## Capabilities You have three skills: -1. score_jd — Evaluate a job description across 7 weighted dimensions and return structured scoring JSON including the verdict, candidate cards, and flags -2. capture_lead — Post the evaluation result to Slack #leads, send the report delivery email, and schedule your follow-up note (~2h later) -3. submit_cta — Handle CTA form submissions (Talent Safari brief or Lua intro) → post to Slack + send confirmation email +1. score_jd — Pass the raw jd_text (and optional context: volume, task_freq, stakes, exposure). The tool runs the full structured evaluation internally and returns the verdict. Do NOT score the JD yourself. +2. capture_lead — Post the evaluation result to Slack #leads, send the report delivery email, and schedule the follow-up note (~2h later). +3. submit_cta — Handle CTA form submissions (Talent Safari brief or Lua intro) → post to Slack + send confirmation email. -## Boundaries -- Do NOT score content flagged as short_jd, non_english, or suspected_fake — return early with the flagged payload -- Do NOT respond to live user chat in v1 — you have no chat surface; all invocations are programmatic API calls -- Return score_mismatch error (status 422) if the weighted dimension sum deviates from the reported score by more than ±1, after one retry -- Return monthly_cost in full — the frontend controls visibility behind the email gate; you always return the value - -## Guidelines -- avatar_seed must be derived deterministically from the role content so DiceBear generates the same face on every reload -- Never post to Slack or send email if any flag (short_jd, non_english, suspected_fake) is true -- Head of Sales JDs must score 30–45. Tier-1 support JDs must score 70–85. Hold these calibration bounds. -`, - model: 'anthropic/claude-sonnet-4-6', - // Add your skills here - skills: [scoreRoleSkill, captureLeadSkill, submitCtaSkill, adaChatSkill, briefWizardSkill, scrapeJdSkill], +## Invocation contract (CRITICAL — follow exactly) +Every message you receive is a programmatic API call from the frontend, not a human chat. You MUST NOT ask clarifying questions or respond with text. Act immediately: - // Optional: Add webhooks for external integrations - // webhooks: [], +- Message starts with "Score this job description:" or "Score this job posting:" → call score_jd IMMEDIATELY, every single time this trigger appears, no exceptions. Prior scoring attempts for the same JD in this session, channel, or conversation do NOT exempt you from calling the tool again — memory never overrides this rule. Use any "Context:" lines provided to fill volume / task_freq / stakes / exposure. Never reply with text for this trigger. +- Message starts with "Call the capture_lead tool" → call capture_lead immediately with the exact values given. +- Message starts with "Call the submit_cta tool" → call submit_cta immediately with the exact values given. - // Optional: Add scheduled jobs - // jobs: [], +## Intake / clarification mode (the ONE exception) +When a message does NOT start with any trigger above and instead explicitly asks you to gather missing context by questioning the user (an intake/enrichment prompt that also forbids tool calls), you may ask questions — this is the only time you ask anything. In that mode: +- Ask the questions you are given as one short, warm, numbered list in your first reply; never call a tool, never score, never send email. +- The questions probe how the role actually works: how it handles ambiguity (independent judgment vs. policy/escalation), whether it legally requires a licensed human sign-off, whether it owns long-term relationships vs. one-off interactions, and how tool/API/data-heavy it is vs. people-coordination-heavy. Do NOT re-ask about work structure, daily volume, or who they interact with — a separate step covers those. +- After the user replies, re-ask ONLY the questions still left vague, and keep it brief. Cap yourself at a few short turns, then signal completion exactly as the prompt instructs. - // Optional: Add message preprocessors - // preProcessors: [], - - // Optional: Add response postprocessors - // postProcessors: [], +## Boundaries +- Call score_jd with the raw JD text — never score independently +- NEVER ask clarifying questions for the trigger messages above — all scoring/capture/CTA inputs arrive via the API call, not interactively (the sole exception is intake/clarification mode) +- NEVER reply with text when a tool call is required — just call the tool +- Never post to Slack or send email if a spam flag (non_english, suspected_fake) is true; short_jd does NOT block capture (the tool handles this internally) +- Return monthly_cost in full — the frontend controls visibility; always return the value +`, + model: "anthropic/claude-sonnet-4-6", + skills: [ + scoreRoleSkill, + captureLeadSkill, + submitCtaSkill, + adaChatSkill, + briefWizardSkill, + scrapeJdSkill, + ], }); -async function main() { - // Your agent is ready! - // - // Next steps: - // 1. Create your first skill with tools - // 2. Run `lua test` to test tools interactively - // 3. Run `lua chat` to chat with your agent - // 4. Run `lua push` to deploy -} +async function main() {} main().catch(console.error); diff --git a/src/skills/capture-lead.skill.ts b/src/skills/capture-lead.skill.ts index fbe4c557..be2616d7 100644 --- a/src/skills/capture-lead.skill.ts +++ b/src/skills/capture-lead.skill.ts @@ -1,5 +1,6 @@ import { LuaSkill, LuaTool, Jobs, Data, env } from 'lua-cli'; import { z } from 'zod'; +import { TS_LOGO_B64, LUA_LOGO_B64, SOCIAL_FB_B64, SOCIAL_LI_B64, SOCIAL_IG_B64 } from './email-assets'; // --------------------------------------------------------------------------- // Input schema @@ -18,17 +19,29 @@ const captureLeadInputSchema = z.object({ verdict: z.enum(['needs_human', 'human_led_agent_assist', 'strong_agent']), verdict_line: z.string(), rationale: z.string(), + dimensions: z + .array( + z.object({ + key: z.string(), + label: z.string(), + score: z.number(), + weight: z.number(), + rationale: z.string(), + }), + ) + .optional() + .describe('The 7 scored dimensions from score_jd — the agent\'s per-dimension analysis'), human_candidate: z.object({ salary_range: z.string(), time_to_productive: z.string(), - }), + }).passthrough(), agent_candidate: z.object({ name: z.string(), role_title: z.string(), monthly_cost: z.string(), start_date: z.string(), throughput: z.string().optional(), - }), + }).passthrough(), recommended_cta: z.enum(['lua', 'tech_safari']), flags: z.object({ short_jd: z.boolean(), @@ -36,6 +49,7 @@ const captureLeadInputSchema = z.object({ suspected_fake: z.boolean(), }), }) + .passthrough() .describe('The full scoring result from score_jd'), }); @@ -53,6 +67,211 @@ function slugify(text: string): string { .replace(/^-+|-+$/g, ''); } +// HTML-escape model/user text before injection into email markup. +function esc(v: unknown): string { + return String(v ?? '') + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +} + +// Hosted assets (public/ served by Vercel) + site origin for CTA deep-links. +const ASSET_BASE = 'https://agent.talentsafari.io'; +const SITE_BASE = 'https://agent.talentsafari.io'; + +type EmailCtx = { email?: string; name?: string; company?: string }; + +// Verdict → single functional accent (AA-safe text + graphic) + band label. +function verdictTheme(verdict: string): { text: string; chipBg: string; label: string } { + switch (verdict) { + case 'needs_human': return { text: '#1F7A45', chipBg: '#e9f5ee', label: 'Needs human' }; + case 'strong_agent': return { text: '#1E6FB0', chipBg: '#e7f2fc', label: 'Strong agent fit' }; + default: return { text: '#8a5616', chipBg: '#fbf1df', label: 'Human-led, agent-assisted' }; + } +} + +// Dimension bar color along the human↔agent spectrum. +function dimBarColor(score: number): string { + if (score <= 4) return '#2E9E5B'; + if (score <= 6) return '#E8A33D'; + return '#2C8FE0'; +} + +// CTA url that opens the matching in-app screen, carrying context for prefill. +function ctaUrl(path: 'tech_safari' | 'lua', s: ScoringResult, ctx: EmailCtx): string { + const q = new URLSearchParams({ + cta: path, + rec: s.recommended_cta, + role: s.role_title ?? '', + score: String(s.score ?? ''), + }); + if (ctx.email) q.set('email', ctx.email); + if (ctx.name) q.set('name', ctx.name); + if (ctx.company) q.set('company', ctx.company); + return `${SITE_BASE}/?${q.toString()}`; +} + +// 7-dimension breakdown — label + bar + score on one line, rationale below. +function renderDimensions(dims: ScoringResult['dimensions']): string { + if (!dims || dims.length === 0) return ''; + const rows = dims.map((d, i) => { + const last = i === dims.length - 1; + const w = Math.max(0, Math.min(100, Math.round(d.score * 10))); + const border = last ? '' : 'border-bottom:1px solid #eceae5;'; + return ` + + + +
${esc(d.label)} + + +
${esc(d.score)}/10
+
${esc(d.rationale)}
+ `; + }).join(''); + return `

Seven-dimension breakdown

+ ${rows}
`; +} + +// Render the full co-branded evaluation report as inline-styled HTML (email-safe). +function renderReportHtml(s: ScoringResult, ctx: EmailCtx = {}): string { + const theme = verdictTheme(s.verdict); + const markerPct = Math.round(Math.min(100, Math.max(0, ((s.score - 10) / 90) * 100))); + const h = s.human_candidate; + const a = s.agent_candidate; + + // Quick personal intro line. "Hey [name], here's your evaluation for the [role] role at [company]." + const hey = ctx.name && ctx.name.trim() ? `Hey ${esc(ctx.name.trim())},` : 'Hey,'; + const atCompany = ctx.company && ctx.company.trim() ? ` at ${esc(ctx.company.trim())}` : ''; + const intro = `${hey} here’s your evaluation for the ${esc(s.role_title)} role${atCompany}.`; + + // Primary CTA = recommended action (bigger); alternative = the other path (smaller). + const primaryTs = s.recommended_cta !== 'lua'; + // Primary = brand-colored solid (TS forest-green gradient + lime arrow; Lua brand gradient + glow). + const primary = primaryTs + ? { href: ctaUrl('tech_safari', s, ctx), label: 'Brief Talent Safari for this role', arrow: '#C7F04A', style: 'background:#15241B;background:linear-gradient(135deg,#1f4231 0%,#15241B 100%);color:#ffffff;box-shadow:0 8px 22px rgba(21,36,27,.28)' } + : { href: ctaUrl('lua', s, ctx), label: 'Brief Lua for this role', arrow: '#ffffff', style: 'background:#9B4DFF;background:linear-gradient(135deg,#FF2D78 0%,#9B4DFF 50%,#3BA5FF 100%);color:#ffffff;box-shadow:0 8px 22px rgba(155,77,255,.30)' }; + // Alternative = tinted to its destination brand (Lua purple / TS green), never neutral gray. + const alt = primaryTs + ? { href: ctaUrl('lua', s, ctx), label: 'Prefer an AI agent? Talk to Lua', style: 'border:1.5px solid #d9c7ff;background:#f7f3ff;color:#6b3fd4' } + : { href: ctaUrl('tech_safari', s, ctx), label: 'Prefer a human hire? Brief Talent Safari', style: 'border:1.5px solid #cbe0d2;background:#f2f9f5;color:#1f7a45' }; + + return ` +Talent Safari × Lua — evaluation + +
${esc(s.role_title)} scored ${esc(s.score)}/100 — ${esc(s.verdict_line)}. Your full 7-dimension breakdown inside.
+
+ + + + + + + + +
+ + + +
Talent SafariLua
+
+
Human or Agent? · Evaluation
+

${intro}

+

${esc(s.role_title)}

+ + + + +
${esc(s.score)}/100 + ${esc(s.verdict_line || theme.label)} +
+
+
Needs humanAgent-assistedStrong agent
+
+ +

${esc(s.rationale)}

+ + ${renderDimensions(s.dimensions)} + +

Human vs Agent

+ + + +
+
Human hire
+ ${h.salary_range ? `Salary ${esc(h.salary_range)}
` : ''}Productive in ${esc(h.time_to_productive)} +
+
${esc(a.name)} (AI agent)
+ Cost ${esc(a.monthly_cost)}
Live ${esc(a.start_date)}${a.throughput ? ` · ${esc(a.throughput)}` : ''} +
+ + +
+ + + +
Talent SafariLua
+

Human or Agent? — a Talent Safari × Lua collaboration.

+

Talent Safari sources the humans · Lua builds the agents.

+

talentsafari.io · heylua.ai

+

Facebook  LinkedIn  Instagram

+

3 Germany Drive, Unit 4 #1816 · Wilmington, Delaware 19804, USA

+
+
+`; +} + +// Compose the agent's analysis into a readable string for the evaluations record. +// Falls back gracefully to verdict + rationale when dimensions weren't relayed. +function buildAnalysis(s: ScoringResult): string { + const lines: string[] = []; + lines.push(`Score: ${s.score}/100 — ${s.verdict_line} (${s.verdict})`); + if (s.rationale) lines.push('', s.rationale); + if (s.dimensions?.length) { + lines.push('', 'Dimension breakdown:'); + for (const d of [...s.dimensions].sort((a, b) => b.weight - a.weight)) { + lines.push(`- ${d.label}: ${d.score}/10 (weight ${d.weight}×) — ${d.rationale}`); + } + } + return lines.join('\n'); +} + +async function appendToSheets( + webhookUrl: string, + name: string, + title: string, + company: string, + email: string, + scoringResult: ScoringResult, + jdText: string, +): Promise { + const response = await fetch(webhookUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + action: 'append', + name, + title, + company, + email, + date: new Date().toISOString(), // Date (agent-sent ISO) + roleEvaluated: scoringResult.role_title, // Role Evaluated + score: scoringResult.score, + ctaClicked: 'No', // initial CTA Clicked — flips on submit_cta + verdict: scoringResult.verdict, // raw enum + recommendedCta: scoringResult.recommended_cta, // raw: 'lua' | 'tech_safari' + jd: jdText, // full JD text + analysis: buildAnalysis(scoringResult), // composed analysis + shortJd: scoringResult.flags?.short_jd ? 'Yes' : 'No', // thin-JD tag (ignored unless sheet maps a column) + }), + }); + if (!response.ok) throw new Error(`Sheets webhook error ${response.status}`); +} + async function postToSlack( webhookUrl: string, scoringResult: ScoringResult, @@ -62,10 +281,12 @@ async function postToSlack( ): Promise { const { role_title, verdict_line, score, human_candidate, agent_candidate } = scoringResult; const roleSlug = slugify(role_title); + // Short JDs are captured (no longer blocked) but flagged for a quick eyeball. + const shortTag = scoringResult.flags?.short_jd ? ' ⚠️ short JD' : ''; const jdSnippet = jdText - ? jdText.length > 600 - ? jdText.slice(0, 600) + '…' + ? jdText.length > 2800 + ? jdText.slice(0, 2800) + '…' : jdText : null; @@ -75,7 +296,7 @@ async function postToSlack( type: 'section', text: { type: 'mrkdwn', - text: `*New evaluation — ${role_title}*\nVerdict: ${verdict_line} · Score ${score} · ${company}\n${email}`, + text: `*New evaluation — ${role_title}*${shortTag}\nVerdict: ${verdict_line} · Score ${score} · ${company}\n${email}`, }, }, { @@ -132,9 +353,8 @@ async function sendEmail1( resendApiKey: string, fromEmail: string, toEmail: string, - roleTitle: string, - verdictLine: string, - score: number, + scoringResult: ScoringResult, + ctx: EmailCtx = {}, ): Promise { const response = await fetch('https://api.resend.com/emails', { method: 'POST', @@ -145,8 +365,40 @@ async function sendEmail1( body: JSON.stringify({ from: fromEmail, to: [toEmail], - subject: `Your Human or Agent? report — ${roleTitle}`, - html: `

Here's your full evaluation for ${roleTitle}.

Verdict: ${verdictLine} (Score: ${score}/100)

The full seven-dimension breakdown is attached. Use it to brief Talent Safari or Lua.

— Ada · Built by Lua

`, + subject: `Your Human or Agent? report — ${scoringResult.role_title}`, + html: renderReportHtml(scoringResult, { email: toEmail, ...ctx }), + attachments: [ + { + filename: 'talent-safari-logo.png', + content: TS_LOGO_B64, + content_id: 'ts-logo', + disposition: 'inline', + }, + { + filename: 'lua-logo.png', + content: LUA_LOGO_B64, + content_id: 'lua-logo', + disposition: 'inline', + }, + { + filename: 'social-facebook.png', + content: SOCIAL_FB_B64, + content_id: 'social-fb', + disposition: 'inline', + }, + { + filename: 'social-linkedin.png', + content: SOCIAL_LI_B64, + content_id: 'social-li', + disposition: 'inline', + }, + { + filename: 'social-instagram.png', + content: SOCIAL_IG_B64, + content_id: 'social-ig', + disposition: 'inline', + }, + ], }), }); @@ -227,18 +479,55 @@ Ada · Built by Lua`; export class captureLeadTool implements LuaTool { name = 'capture_lead'; description = - "Post an evaluation result to Slack #leads, send the report delivery email to the lead, and schedule Ada's follow-up note (~2h later). Skips silently if any quality flag is set."; + "ALWAYS call this tool immediately after score_jd, even when quality flags are set. The tool decides internally what to do: for the score-time call (no real lead yet) or a spam-flagged evaluation (non_english / suspected_fake) it records nothing and returns { skipped }. A genuine lead-form submission (real name + title present) is recorded to the evaluations Data primitive and triggers Slack / Sheets / report email — short JDs are NOT blocked, they are captured and tagged as short. Pass whatever fields you have and never fabricate contact details. Never refuse, explain, or withhold the call."; inputSchema = captureLeadInputSchema; async execute(input: CaptureLeadInput): Promise { const { email, name, title, company, jdText, scoringResult } = input; const { flags } = scoringResult; - // Always store to Data regardless of flags + // Spam short-circuit — no Slack, no email. NOTE: short_jd is intentionally + // NOT a blocker here. It's LLM-judged and misfires on borderline JDs, which + // silently dropped genuine leads (no Slack body, no Sheets row, no email). + // Short but real JDs now flow through; short_jd is surfaced as a tag on the + // Slack post / Sheets row instead (see postToSlack / appendToSheets). + if (flags.non_english || flags.suspected_fake) { + const reason = Object.keys(flags).find( + (k) => k !== 'short_jd' && flags[k as keyof typeof flags], + ); + return { + posted: false, + email1Sent: false, + email2ScheduledAt: '', + skipped: true, + reason, + }; + } + + // Real-lead gate. This tool is called twice per evaluation: once right + // after score_jd (the score-time auto-call) and once when the visitor + // submits the lead form. Only the form submission carries real contact + // details (name + title are required form fields). The score-time call has + // no genuine lead, so skip everything below — including the Data write — to + // avoid phantom evaluation records, Sheets rows, Slack posts, and report + // emails with placeholder contact info. + if (!name?.trim() || !title?.trim()) { + return { + posted: false, + email1Sent: false, + email2ScheduledAt: '', + skipped: true, + reason: 'no_lead_details', + }; + } + + // Record the evaluation to Data — genuine leads only (this runs after the + // real-lead gate, so score-time auto-calls no longer create placeholder + // records). try { - await Data.create({ - name: `eval_${Date.now()}`, - metadata: { + await Data.create( + 'evaluations', + { email, name: name ?? '', title: title ?? '', @@ -248,23 +537,14 @@ export class captureLeadTool implements LuaTool { verdict: scoringResult.verdict, recommended_cta: scoringResult.recommended_cta, jd_text: jdText ?? '', + analysis: buildAnalysis(scoringResult), + dimensions: scoringResult.dimensions ?? [], timestamp: new Date().toISOString(), }, - }); + `${scoringResult.role_title} ${scoringResult.verdict} ${company} ${jdText ?? ''}`.slice(0, 2000), + ); } catch { /* non-fatal */ } - // Flag short-circuit — no Slack, no email - if (flags.short_jd || flags.non_english || flags.suspected_fake) { - const reason = Object.keys(flags).find((k) => flags[k as keyof typeof flags]); - return { - posted: false, - email1Sent: false, - email2ScheduledAt: '', - skipped: true, - reason, - }; - } - const slackUrl = env('SLACK_LEADS_WEBHOOK_URL') ?? ''; const resendKey = env('RESEND_API_KEY') ?? ''; const fromEmail = env('FROM_EMAIL') ?? ''; @@ -272,12 +552,20 @@ export class captureLeadTool implements LuaTool { // Slack — primary signal, must succeed await postToSlack(slackUrl, scoringResult, email, company, jdText); + // Sheets — non-fatal + const sheetsUrl = env('SHEETS_WEBHOOK_URL') ?? ''; + if (sheetsUrl) { + try { + await appendToSheets(sheetsUrl, name ?? '', title ?? '', company, email, scoringResult, jdText ?? ''); + } catch { /* non-fatal */ } + } + // Email — non-fatal if Resend key not configured let email1Sent = false; let email2ScheduledAt = ''; if (resendKey && fromEmail) { try { - await sendEmail1(resendKey, fromEmail, email, scoringResult.role_title, scoringResult.verdict_line, scoringResult.score); + await sendEmail1(resendKey, fromEmail, email, scoringResult, { name: name ?? '', company }); email1Sent = true; } catch { /* non-fatal */ } try { @@ -301,14 +589,13 @@ export const captureLeadSkill = new LuaSkill({ name: 'capture-lead', description: 'Captures a qualified lead by posting the evaluation result to Slack and delivering the report and follow-up emails.', - context: `Use the capture_lead tool immediately after a successful score_jd call — pass the full scoringResult along with the lead's email and company name. + context: `Use the capture_lead tool immediately after every successful score_jd call — pass the full scoringResult along with the lead's email and company name. ALWAYS call it, even if you believe a flag (non_english, suspected_fake) is set. Never reply with text in place of the call; never explain the flag instead of calling the tool. The tool itself handles flag-based skipping. The tool will: -1. Skip silently (skipped: true) if any flag is set (short_jd, non_english, suspected_fake) — do not retry or explain. -2. Post a rich Block Kit notification to Slack #leads with human vs Ada comparison and routing buttons. -3. Send the evaluation report to the lead's email via Resend. -4. Schedule Ada's personalised follow-up email to fire ~2 hours later. +1. If a spam flag (non_english or suspected_fake) is set → return { skipped: true, reason } and do nothing else. This is internal; you still MUST call it. (short_jd is NOT a blocker — short but genuine leads are captured and the JD is tagged as short on the Slack post / Sheets row.) +2. If there is no genuine lead yet (missing name or title — e.g. the score-time call) → return { skipped: true, reason: 'no_lead_details' } and do nothing else. +3. Otherwise (a real lead-form submission) → record the evaluation to the evaluations Data primitive, post Slack Block Kit, append the Google Sheets row, send the Resend report email, and schedule the 2h follow-up. -Returns: { posted, email1Sent, email2ScheduledAt } on success, or { skipped: true, reason } when flagged.`, +Returns: { posted, email1Sent, email2ScheduledAt } on success, or { skipped: true, reason } when skipped.`, tools: [new captureLeadTool()], }); diff --git a/src/skills/email-assets.ts b/src/skills/email-assets.ts new file mode 100644 index 00000000..f463cdc8 --- /dev/null +++ b/src/skills/email-assets.ts @@ -0,0 +1,8 @@ +// Inline base64 PNG payloads for email logos + social icons. +// Sent as MIME CID attachments so Gmail/Outlook render without external-image blocking. + +export const TS_LOGO_B64 = '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'; +export const LUA_LOGO_B64 = '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'; +export const SOCIAL_FB_B64 = 'iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAACXBIWXMAAC4jAAAuIwF4pT92AAADYUlEQVR4nNWZS2gUQRCGRxNERXxBTHb+6pmt6tXDqhcfFwVjUHwmoB4MinhRAiIiJgfBW/AUwVtEPQiCqAhqvAQUUQ9q8IGCIGIUEfEgRHPwAauGJNK7G3ajm8nMzuzDgjrNdM3X1X9XP8aywlmNUrKCiDsAOUfED4ikn4g/ZlxeA3LfPFOK2x1HLzdtrHIbEa8E5BQgg0QyGsz5CyDdpqMlBwX0WiK+GxxSJoK/QxRfEzmo4zgxgC9HByrjHJCLrus2RAJr27IOkE+lgqVctgcA2RwKFuAjRDJSelgZ82FADhcLe7yMoKPjJcKdgWCJ9KFKwVJOIh2+YG2bW6KRgSlf3APIUaV0K1F8I1G80ba5GdB7AT4G8CWAv04QYwSQLZPAalVcbc0fTnlPxPtd153uJ0GAPPHo9GeihfBozDdCwt4kovm+htIXcNqvWoXMpD+kBJ75zWpA4FGl4hsKNXwcAnbItnmRVYTBBzAR9/3VSDeFnGSFhy0yYON5SziRXAip3a1+4CyrsbahIe7GYnqZ2bkRyRIieeFzFM+nQ8RisZlE8iME8MhkE42IZgBy0pS6ELL7lp4jts3rw2WX302WVyI+G1Jy2W/ppiiW4EdesK7rzgUkFQ0wd0ZSe72AYzFZHQVsVhbXzCx9FbLXPd5y0NuiAgb4pRVuIqSDXPcCtu34zggzPGAk8fN/AQYkZTI8FKSROTw6jjNvzOvqkrO8gJPJ5LT89/OdSG8KmJzflsf2rqAXuwQXMqXkQMAMD5oMv6kUMBGfDiiLflMlblUQuC/gpOs1kjhRIeCpRPw9oIa7TIZ3VAKYSCcCysF8u9kSkTkA/wrQcLvZaY25UgntBeakK0Lu/Vw7bg844VKJRGJ2trfcG7S35a7DyF9RTdaqHdi2uSUvbGMtwG+rGLjfTNJxgc1dQbUCK6VbC8Wekrn+rDZgfmjYCgY35y1zFKkWYEBSSunFXvGNNNqqB1i3ecLmoLmr0sCAnLICmNHzmQoCXynm502N6WW5gQHpDvWnCeA9XvcWUQEjfbLmg1YUlrmh4eelAgb4KZEstSK2mmwF+RAVMDJ3yfv+WcWiNHNGy8iE72V+ogQGHiaS20Syy2wJSgZayOrrZYFt61Ve75g9bOZkkb6u2s3M9WE++gdouxgAeHD1IwAAAABJRU5ErkJggg=='; +export const SOCIAL_LI_B64 = 'iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAACXBIWXMAAC4jAAAuIwF4pT92AAACEElEQVR4nO2ZvWsVQRTFhxi0CVgtSfacXbl39zXbqSA2YrD0T7CwtpBoCBb2YiCNjaB/gCAiCHYqWNlJmpDOLwhY+4ViimRXRqPv5TGzee8hmRH3wunODr8dztyZ3THGmClAlgB5TWpNahOZalJeAXrVshpSr0UA1YwmWTaAvgsPoiMJkDcm0hg0vniYCCCacdQBM4IZXid1BdBFUu4A+inaSAB625iz02agsixLd3t2dMCbVVUdNo4C9HyMwA+Np5KkmgnVDk1LHJ75gIGSMc7wtzzvqRtYrscI3ACykabl8QHWQ7ZbALIVJTD72gRkjdSvoUA5JnA0Mu2R0A8u2XwPReez2ydfhsZcJ+UuqTdJuQXIo3E3ojbgHV+XSFO9NOgdyvmfIuXU7gttAMdOuzy215NyGdCPUQAD+kJVj5p9Ks/LCpD3QYGzrCxEZHY/2L5fzpC6HQx4kiL1QRTAed5TQM+RPbT5gGIhKHCSVDOAPh7w14De8PnLsjwC6PdgwIDec43f/szPTerggefmysR3qgNkteUlnwQBnp8vTkxyfG1beAeycdApee6fYbnfAbOb4X51kUi7Rbe3ukikXST+UiTyvDjp0q9vsj3eCy4fUFz0jQ/oS9/4gD6dBDhKmdAA/B+A69AQHF21XZFvIwBpRpH9kW7PrMv/EPCSbXtT9lrUXo9GGo/fV7dX7NXtDwwO2nfZYPxkAAAAAElFTkSuQmCC'; +export const SOCIAL_IG_B64 = 'iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAACXBIWXMAAC4jAAAuIwF4pT92AAAFSElEQVR4nM1ZSW8dRRAemx2xyhi/11U9M1UzLzZGkIMPKCgkCAICsVxYj5AgxHIC/gKXwAUfwDIc+AMkbCIJhMABLlgsQljCIUKJFClxlAQikiAnGIPqLUlPze6YZ0qqS0919zfV1VXVVZ5XQr7vNxFpCyJNAtAHiPQdAP16nvk4AP/WY0ReROR/zjOddL93eb47fxaRdiDy29by80EQhN5yCYDvB+CvEHkpCeC/ZQCesTZ82PO8gUpAG414GJH29BMkZjJ9KVgKwVob3QzA+1cfLPf4gGDKBDsywjeKQMaf/gXAnyHSK8bQQwDhWt9vsTFjQ77vX99jz9t4ccnhDbrywo1GcJO1dA8ivYDIHwPQ2QwT2d9srrlBLzYgR5AWlksWxV6fyPd9AqD3MzS9OyEoRp4B9rXKhr+yNADAr6dBR/edk5CbqcxgW7/AWmsNIj9pLa9PgpbTTWD6uv1FfJ/S7NkL8oe1wPJ6RPrD2fvd3jcxRbk/DrYliQle1+BdI//Q6xNBx88njt73ownn+6dKy5s9iTLuoESc5QKI4/iyZjMYQww3CBsTjspYnjwi/ZLhFR7ofbeWXlaA3/AAaKc7aAxtqolzUGxQTgaA/8y44afFHo0JHxdZd6JcbAV2PgiC6/KcAQBtl0mzScDhaD0b5B9qRK/vjYlud08EgF9F5B/FDyPyLckfCtcqwN/KsRxMAh4bqgIWIHo2y9GXMQCdQaRnquyB2AI1d58Y9iF30D2SIrAFoOYQ6ZNuFjZXoO0tZfsQ0YiOeqLhI+7g8PD4VWVmkNZsO3y/JZFKy/t+ixFpSrmotqaNidYV7SWnrfY5KICPJQfxipILlrBZAP4dgO8q05YxtElkUzZZEKDiOL5G7XVYTOKEOzg+Pn5p3gLWRk9kaLYUbI+M4bszNP2ol0PNZvNKtd9R8cOn3EHtelxC5I/UH7+ZJ5u/Bk2lXFUOifL0aXrKdy7lTQ6C4HLxqe4CYp91AVsbR9pPFwSXQSV7SvzwGfeI8zYyhtaoyT97yyRE3ptcKz+Fdd+IALSQHsidGG5UR7lzuYBBRVdZu0B2wZFdrAwYILpz5QDzLgV4Q2XAqYHqJjHXH5Ogc15FzLeylxD/rJMbuUD1wUaxclUni1ypW2aQ/VN+eGJi4pK8yZKRqc2m6gIG4HfUSb1XIH6R/jlR+VF3UJx1ncBRJx217RdysjIEQI/U8MMn5I8Pu4MSDgv2HJQUUTtzAVIFLKRCM88UhWYxQ6WgY7XTS8lnk767c1kRaTrLprHzNpvO0OwCQHhb0V6SiCnARzxd6ZGUrkxbks8qwC7vldSy42sp9QRy+OmyfZj5WnUih8St7Usu1IKyhXqgMzRdygC0YC0/VWWPzPRSUjy14K1VFussGK3T84vB8kyZGSTXD0cVtp88XRoyhh706pEUPR6TrEsnR9jh01KY6XqDWsUZa8N7lYZ3yNFOqr94yVsmiRsC4Ja1dIeEWwBuFQWFMkKkFxXgaRncrI5tl/c/IVCByhh+TvLchqqyL0resNpgG40w0JdaxjJLRmLXq1S5dO/F9owg0yEpZWa4n62rV26lrRqPFNMTUoj0efqG07Z+VTJ7UTFdZm3j2JNSnjRAsvobUoMQ45cioSQ64hvdsr+89bwKNDQ0erU7DyBGKU2J5qTo16lUJl/UXT6Q25yRBkh2n6M2/53u13FtFgXmNmVcTSPSFysA+kJ5d1YzJo8GOh0j/qbPIJekNZDoZ9Ql8X3isDspYjsLm+22bOd1S1ZeBArAopI57rZ9u21gaQdPSnGw3RIooX8Btm2E7PRRLFoAAAAASUVORK5CYII='; diff --git a/src/skills/score-role.skill.ts b/src/skills/score-role.skill.ts index 682b04fb..02e4d913 100644 --- a/src/skills/score-role.skill.ts +++ b/src/skills/score-role.skill.ts @@ -1,63 +1,167 @@ -import { LuaSkill, LuaTool } from 'lua-cli'; +import { LuaSkill, LuaTool, AI } from 'lua-cli'; import { z } from 'zod'; // --------------------------------------------------------------------------- -// Input schema — Ada passes the full scored result; tool validates & returns +// Scoring rubric — single source of truth, used as the AI.generate system prompt // --------------------------------------------------------------------------- -const dimensionSchema = z.object({ - key: z.enum([ - 'task_structure', - 'judgment_complexity', - 'volume_scale', - 'regulatory_burden', - 'relationship_depth', - 'system_integration', - 'data_sensitivity', - ]), - label: z.string(), - score: z.number().int().min(1).max(10), - weight: z.number(), - rationale: z.string().max(120), -}); +const SCORING_SYSTEM = `You are an honest expert evaluator scoring job descriptions for automation fit. +Score each role across 7 dimensions (1–10, where 1 = strongly human-suited, 10 = strongly agent-suited). + +Modern AI agents reason, handle nuance, manage emotional conversations well, and operate autonomously +in complex environments. Score based on whether the STRUCTURE of the role suits an agent — not +outdated assumptions about AI limits. + +DIMENSIONS & WEIGHTS: + task_structure (weight 1.8) — highly novel/ambiguous ↔ structured/repeatable + judgment_complexity (weight 2.0) — requires genuine human expertise & judgment ↔ rule-based/learnable + volume_scale (weight 1.5) — one-off strategic ↔ high-throughput repeated + regulatory_burden (weight 1.5) — legally requires human sign-off ↔ agent can act autonomously + relationship_depth (weight 1.3) — long-term strategic relationship ownership ↔ episodic/transactional + system_integration (weight 1.0) — heavy cross-functional human coordination ↔ tool/API-heavy + data_sensitivity (weight 0.9) — highly regulated PII/constrained ↔ open/standard business data + +NOTE on relationship_depth: score LOW (human) only for SUSTAINED RELATIONSHIP OWNERSHIP (e.g. managing +a key account for 12 months). Emotional + episodic = agent-suited. + +NOTE on regulatory_burden: high stakes alone does NOT mean human-required. Score based on REGULATORY +SIGN-OFF requirements only. A $10M contract agent assistant is fine; a licensed financial advisor +signing off on advice is not. + +FINAL SCORE = Σ(dimension.score × dimension.weight), range 10–100. Round to nearest integer. + +VERDICT BANDS: + 10–39 → needs_human recommended_cta: tech_safari + 40–64 → human_led_agent_assist recommended_cta: tech_safari + 65–100 → strong_agent recommended_cta: lua + +CALIBRATION (non-negotiable): + - Head of Sales JDs MUST score 30–45 (needs_human) + - Tier-1 support / triage JDs MUST score 82–92 (strong_agent) + - ~40% of real JDs should score human — be honest, not optimistic + +CANDIDATE CARDS: + human_candidate: salary_range = exact salary/budget text from JD if explicitly stated, "" if not mentioned + agent_candidate: name always "Lua", role_title adapts to role, monthly_cost $800–$3,000/mo, + avatar_seed short slug from role (e.g. "lua-support", "lua-ops"), + start_date "Today", throughput and coverage reflect agent advantages + +FLAGS (check before scoring — set flag but still return full result): + short_jd: fewer than 80 words + non_english: not written in English + suspected_fake: test/lorem ipsum/placeholder content + +ADJACENT AGENTS: always include 2–3 distinct Lua agent suggestions for OTHER roles/tasks at this company. +Base on company type, industry, and function visible in the JD. +Format: icon (single emoji), name ("Lua [Role]"), value_prop (one sentence, specific to this context).`; + +// --------------------------------------------------------------------------- +// JSON Schema 7 — drives AI.generate's structuredOutput. The platform converts +// this to AI SDK's `experimental_output: Output.object({ schema })`, and the +// response surfaces the parsed object on `response.output`. +// --------------------------------------------------------------------------- + +const dimensionSchema = { + type: 'object', + required: ['key', 'label', 'score', 'weight', 'rationale'], + properties: { + key: { type: 'string' }, + label: { type: 'string' }, + score: { type: 'integer', minimum: 1, maximum: 10 }, + weight: { type: 'number' }, + rationale: { type: 'string' }, + }, + additionalProperties: false, +}; + +const SCORE_ROLE_SCHEMA: Record = { + type: 'object', + required: [ + 'role_title', 'score', 'verdict', 'verdict_line', 'rationale', + 'dimensions', 'human_candidate', 'agent_candidate', + 'recommended_cta', 'flags', 'adjacent_agents', + ], + properties: { + role_title: { type: 'string' }, + score: { type: 'integer', minimum: 10, maximum: 100 }, + verdict: { type: 'string', enum: ['needs_human', 'human_led_agent_assist', 'strong_agent'] }, + verdict_line: { type: 'string' }, + rationale: { type: 'string' }, + dimensions: { + type: 'array', + minItems: 7, + maxItems: 7, + items: dimensionSchema, + }, + human_candidate: { + type: 'object', + required: ['salary_range', 'time_to_productive', 'scale_ceiling', 'coverage', 'great_at', 'hard_at'], + properties: { + salary_range: { type: 'string' }, + time_to_productive: { type: 'string' }, + scale_ceiling: { type: 'string' }, + coverage: { type: 'string' }, + great_at: { type: 'array', items: { type: 'string' }, minItems: 3, maxItems: 3 }, + hard_at: { type: 'array', items: { type: 'string' }, minItems: 3, maxItems: 3 }, + }, + additionalProperties: false, + }, + agent_candidate: { + type: 'object', + required: ['name', 'role_title', 'avatar_seed', 'monthly_cost', 'start_date', 'throughput', 'coverage', 'great_at', 'cant_do'], + properties: { + name: { type: 'string' }, + role_title: { type: 'string' }, + avatar_seed: { type: 'string' }, + monthly_cost: { type: 'string' }, + start_date: { type: 'string' }, + throughput: { type: 'string' }, + coverage: { type: 'string' }, + great_at: { type: 'array', items: { type: 'string' }, minItems: 3, maxItems: 3 }, + cant_do: { type: 'array', items: { type: 'string' }, minItems: 3, maxItems: 3 }, + }, + additionalProperties: false, + }, + recommended_cta: { type: 'string', enum: ['lua', 'tech_safari'] }, + flags: { + type: 'object', + required: ['short_jd', 'non_english', 'suspected_fake'], + properties: { + short_jd: { type: 'boolean' }, + non_english: { type: 'boolean' }, + suspected_fake: { type: 'boolean' }, + }, + additionalProperties: false, + }, + adjacent_agents: { + type: 'array', + minItems: 2, + maxItems: 3, + items: { + type: 'object', + required: ['icon', 'name', 'value_prop'], + properties: { + icon: { type: 'string' }, + name: { type: 'string' }, + value_prop: { type: 'string' }, + }, + additionalProperties: false, + }, + }, + }, + additionalProperties: false, +}; + +// --------------------------------------------------------------------------- +// Input +// --------------------------------------------------------------------------- const scoreJdInputSchema = z.object({ - role_title: z.string(), - score: z.number().int().min(10).max(100), - verdict: z.enum(['needs_human', 'human_led_agent_assist', 'strong_agent']), - verdict_line: z.string().max(60), - rationale: z.string().max(240), - dimensions: z.array(dimensionSchema).length(7), - human_candidate: z.object({ - salary_range: z.string(), - time_to_productive: z.string(), - scale_ceiling: z.string(), - coverage: z.string(), - great_at: z.array(z.string()).max(3), - hard_at: z.array(z.string()).max(3), - }), - agent_candidate: z.object({ - name: z.string(), - role_title: z.string(), - avatar_seed: z.string(), - monthly_cost: z.string(), - start_date: z.string(), - throughput: z.string(), - coverage: z.string(), - great_at: z.array(z.string()).max(3), - cant_do: z.array(z.string()).max(3), - }), - recommended_cta: z.enum(['lua', 'tech_safari']), - flags: z.object({ - short_jd: z.boolean(), - non_english: z.boolean(), - suspected_fake: z.boolean(), - }), - adjacent_agents: z.array(z.object({ - icon: z.string().describe('Single emoji for this agent type'), - name: z.string().describe('Short agent name e.g. "Lua Scheduler"'), - value_prop: z.string().max(120).describe('One sentence on what this agent does for this specific company/role context'), - })).min(2).max(3).describe('2–3 complementary Lua agents that could help this company regardless of the main verdict'), + jd_text: z.string().describe('The full job description text to evaluate'), + volume: z.string().optional().describe('Task structure context'), + task_freq: z.string().optional().describe('Task frequency (low/medium/high volume per day)'), + stakes: z.string().optional().describe('Decision stakes context'), + exposure: z.string().optional().describe('Exposure type (e.g. customer_unregulated, regulated)'), }); type ScoreJdInput = z.infer; @@ -70,36 +174,87 @@ function computeScore(dimensions: Array<{ score: number; weight: number }>): num return Math.round(dimensions.reduce((sum, d) => sum + d.score * d.weight, 0)); } +function verdictForScore(score: number): { verdict: string; recommended_cta: string } { + if (score < 40) return { verdict: 'needs_human', recommended_cta: 'tech_safari' }; + if (score < 65) return { verdict: 'human_led_agent_assist', recommended_cta: 'tech_safari' }; + return { verdict: 'strong_agent', recommended_cta: 'lua' }; +} + // --------------------------------------------------------------------------- -// Tool — Ada scores the JD herself; this tool validates the weighted sum +// Tool — runs the structured scoring call via AI.generate({ structuredOutput }) // --------------------------------------------------------------------------- export class scoreJdTool implements LuaTool { name = 'score_jd'; description = - 'Validate and record a completed JD scoring. Call this after you have scored the role across all 7 dimensions. The tool checks your weighted sum is internally consistent and returns the structured result.'; + 'Score a job description for automation fit. Returns a structured verdict (score, dimensions, candidate cards) via a temperature-0.2 LLM call constrained by JSON Schema.'; inputSchema = scoreJdInputSchema; async execute(input: ScoreJdInput): Promise { - const { dimensions, score, flags } = input; + const { jd_text, volume, task_freq, stakes, exposure } = input; + + const contextLines = [ + volume && `Task structure: ${volume}`, + task_freq && `Task frequency: ${task_freq} volume per day`, + stakes && `Decision stakes: ${stakes}`, + exposure && `Exposure type: ${exposure}`, + ].filter(Boolean); + + const userContent = contextLines.length + ? `${jd_text}\n\nAdditional context:\n${contextLines.join('\n')}` + : jd_text; - // Validate weighted sum (±1 tolerance) - const computed = computeScore(dimensions); - if (Math.abs(computed - score) > 1) { + let response: { output?: unknown; finishReason?: string }; + try { + response = (await AI.generate({ + system: SCORING_SYSTEM, + messages: [{ role: 'user', content: userContent }], + temperature: 0.2, + structuredOutput: { schema: SCORE_ROLE_SCHEMA }, + // Two narrow casts drop on the next lua-cli release that widens + // AiGenerateInput with structuredOutput and AiGenerateOutput with output. + } as any)) as { output?: unknown; finishReason?: string }; + } catch (err) { + return { error: 'generation_failed', detail: (err as Error)?.message ?? String(err) }; + } + + const raw = response.output as Record | undefined; + if (!raw || typeof raw !== 'object') { return { - error: 'score_mismatch', - status: 422, - detail: `Reported score ${score} does not match computed weighted sum ${computed}. Recompute: Σ(dimension.score × dimension.weight) = ${computed}.`, + error: 'parse_failed', + detail: 'AI.generate returned no structured output', + finishReason: response.finishReason, }; } - // Flag check — return early; no Slack/email side effects here - if (flags.short_jd || flags.non_english || flags.suspected_fake) { - const reason = Object.keys(flags).find((k) => flags[k as keyof typeof flags]); - return { ...input, flagged: true, flagReason: reason }; + const dims = raw.dimensions as Array<{ score: number; weight: number }> | undefined; + if (!Array.isArray(dims) || dims.length !== 7) { + return { error: 'invalid_dimensions', detail: 'Expected exactly 7 dimensions' }; } - return input; + // Deterministic short_jd. The LLM-judged flag misfires on borderline JDs + // (e.g. a 105-word JD getting short_jd:true), which silently blocked real + // leads downstream. Recompute it from an actual word count and overwrite the + // model's value. Threshold matches the prompt rubric (fewer than 80 words). + // Mutating raw.flags here covers every return path below (all return raw). + const flags = raw.flags as Record | undefined; + if (flags && typeof flags === 'object') { + const wordCount = jd_text.trim() ? jd_text.trim().split(/\s+/).length : 0; + flags.short_jd = wordCount < 80; + } + + // Sanity-correct score + verdict band so the two stay in sync + const reported = raw.score as number; + const computed = computeScore(dims); + if (Math.abs(computed - reported) > 1) { + const v = verdictForScore(computed); + return { ...raw, score: computed, verdict: v.verdict, recommended_cta: v.recommended_cta }; + } + const expected = verdictForScore(reported); + if (raw.verdict !== expected.verdict) { + return { ...raw, verdict: expected.verdict, recommended_cta: expected.recommended_cta }; + } + return raw; } } @@ -110,63 +265,9 @@ export class scoreJdTool implements LuaTool { export const scoreRoleSkill = new LuaSkill({ name: 'score-role', description: - 'Evaluates a job description for automation fit across 7 weighted dimensions and returns a structured verdict with candidate cards.', - context: `When the user provides a job description (or text scraped from a URL), score it yourself using this rubric, then call score_jd to validate and record the result. - -SCORING RUBRIC — evaluate across 7 dimensions, each scored 1–10: - 1 = strongly human-suited - 10 = strongly agent-suited - -Modern AI agents (built on models like Claude) are NOT simple if/then workflow tools. They reason, -handle nuance, manage emotional conversations well, and operate autonomously in complex environments. -Score based on whether the STRUCTURE of the role suits an agent — not outdated assumptions about AI limits. - -DIMENSIONS & WEIGHTS: - task_structure (weight 1.8) — highly novel/ambiguous ↔ structured/repeatable - judgment_complexity (weight 2.0) — requires genuine human expertise & judgment ↔ rule-based/learnable pattern - volume_scale (weight 1.5) — one-off strategic ↔ high-throughput repeated - regulatory_burden (weight 1.5) — legally requires human sign-off (healthcare, legal, finance) ↔ unregulated / agent can act autonomously - relationship_depth (weight 1.3) — long-term strategic relationship ownership (C-suite, key accounts) ↔ episodic or transactional interactions - system_integration (weight 1.0) — heavy cross-functional human coordination ↔ tool/API-heavy, automatable - data_sensitivity (weight 0.9) — highly regulated PII / constrained ↔ open / standard business data - -NOTE on relationship_depth: modern agents handle emotional, frustrated, and distressed customers extremely well. -Score LOW (human) only when the role requires SUSTAINED RELATIONSHIP OWNERSHIP — e.g. managing a key account for 12 months, -not just handling an emotional support ticket. Emotional + episodic = agent-suited. + 'Evaluates a job description for automation fit via a temperature-0.2 structured-output LLM call.', + context: `When the user asks to score a job description, call score_jd with the raw jd_text and any context (volume, task_freq, stakes, exposure). Pass the returned object straight on — no transformation needed. -NOTE on regulatory_burden: high stakes alone does NOT mean human-required. Score based on REGULATORY SIGN-OFF requirements, -not perceived risk. A $10M contract agent assistant is fine; a licensed financial advisor signing off on advice is not. - -FINAL SCORE = Σ(score × weight), range 10–100. Round to nearest integer. - -VERDICT BANDS: - 10–39 → needs_human recommended_cta: tech_safari - 40–64 → human_led_agent_assist recommended_cta: tech_safari - 65–100 → strong_agent recommended_cta: lua - -CALIBRATION (non-negotiable): - - Head of Sales JDs MUST score 30–45 (needs_human) — strategic relationship ownership - - Tier-1 support / triage JDs MUST score 82–92 (strong_agent) — high volume, episodic, no regulatory burden - - Roughly 40% of real JDs should score human — be honest, not optimistic - -CANDIDATE CARDS: - human_candidate: salary_range = exact salary/budget from JD if explicitly stated (keep original wording); set to "" if JD does not mention salary or budget. scale ceiling, coverage. - agent_candidate: name is always "Lua", role_title adapts to role, monthly_cost $800–$3,000/mo, - avatar_seed is a short slug derived from role_title (e.g. "lua-support", "lua-ops"), - start_date is "Today", throughput and coverage reflect agent advantages - -FLAGS (check before scoring): - short_jd: fewer than 80 words → call score_jd with flagged:true, skip deep scoring - non_english: not in English → flag and return - suspected_fake: test/lorem ipsum content → flag and return - -If score_jd returns a score_mismatch error (status 422), recompute your dimension scores and retry once. - -ADJACENT AGENTS (always include — ignore verdict, every company benefits from more automation): - Generate 2–3 Lua agent suggestions for OTHER roles/tasks at this company beyond the evaluated role. - Base suggestions on the company type, industry, and function visible in the JD. - Each should be distinct and realistic. Format: icon (emoji), name ("Lua [Role]"), value_prop (one sentence, specific to context). - Examples: Lua Scheduler (calendar/coordination), Lua Prospector (lead research), Lua Onboarder (HR/new hire), - Lua Analyst (reporting/metrics), Lua QA Agent (quality auditing), Lua Invoice Agent (finance ops).`, +If the tool returns { error: ... }, tell the user something went wrong and ask them to try again.`, tools: [new scoreJdTool()], }); diff --git a/src/skills/scrape-jd.skill.ts b/src/skills/scrape-jd.skill.ts index 3d5e64f9..1517233b 100644 --- a/src/skills/scrape-jd.skill.ts +++ b/src/skills/scrape-jd.skill.ts @@ -11,6 +11,42 @@ const scrapeJdInputSchema = z.object({ type ScrapeJdInput = z.infer; +// --------------------------------------------------------------------------- +// SSRF guard — block RFC1918, loopback, link-local, and metadata endpoints +// --------------------------------------------------------------------------- + +const BLOCKED_PATTERNS = [ + /^localhost$/i, + /^127\./, + /^10\./, + /^172\.(1[6-9]|2\d|3[01])\./, + /^192\.168\./, + /^169\.254\./, // link-local / AWS metadata + /^::1$/, // IPv6 loopback + /^fc00:/i, // IPv6 ULA + /^fe80:/i, // IPv6 link-local + /^0\./, // 0.x.x.x + /^100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\./, // RFC6598 shared +]; + +function assertSafeUrl(rawUrl: string): void { + let parsed: URL; + try { + parsed = new URL(rawUrl); + } catch { + throw new Error('Invalid URL'); + } + if (parsed.protocol !== 'https:') { + throw new Error('Only HTTPS URLs are allowed'); + } + const host = parsed.hostname.toLowerCase(); + for (const pat of BLOCKED_PATTERNS) { + if (pat.test(host)) { + throw new Error(`Blocked host: ${host}`); + } + } +} + // --------------------------------------------------------------------------- // Helpers // --------------------------------------------------------------------------- @@ -53,6 +89,13 @@ export class scrapeJdTool implements LuaTool { async execute(input: ScrapeJdInput): Promise { const { url } = input; + // Guard against SSRF — block private/internal/metadata hosts + try { + assertSafeUrl(url); + } catch { + return { error: 'Could not fetch that URL. Try pasting the JD text directly.' }; + } + // Step 1: Fetch the job posting page let html: string; try { @@ -91,6 +134,7 @@ export class scrapeJdTool implements LuaTool { try { const parsed = new URL(url); const careersUrl = `${parsed.origin}/careers`; + assertSafeUrl(careersUrl); // same host — already passed, but keep guard consistent const careersResponse = await fetch(careersUrl, { headers: { diff --git a/src/skills/submit-cta.skill.ts b/src/skills/submit-cta.skill.ts index 13e4a734..d38bc6ee 100644 --- a/src/skills/submit-cta.skill.ts +++ b/src/skills/submit-cta.skill.ts @@ -1,4 +1,4 @@ -import { LuaSkill, LuaTool, env } from 'lua-cli'; +import { LuaSkill, LuaTool, Data, env } from 'lua-cli'; import { z } from 'zod'; // --------------------------------------------------------------------------- @@ -40,6 +40,19 @@ type SubmitCtaInput = z.infer; // Helpers // --------------------------------------------------------------------------- +async function updateSheetsRow(webhookUrl: string, email: string, path: string): Promise { + const response = await fetch(webhookUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + action: 'updateCta', + email, + ctaClicked: path === 'lua' ? 'Lua' : 'Talent Safari', + }), + }); + if (!response.ok) throw new Error(`Sheets webhook error ${response.status}`); +} + async function postCtaToSlack(webhookUrl: string, input: SubmitCtaInput): Promise { const { path, name, email, company, extraField, jdText, scoringResult } = input; const { role_title, score, verdict_line, agent_candidate, human_candidate } = scoringResult; @@ -52,7 +65,7 @@ async function postCtaToSlack(webhookUrl: string, input: SubmitCtaInput): Promis : ''; const jdSnippet = jdText - ? jdText.length > 600 ? jdText.slice(0, 600) + '…' : jdText + ? jdText.length > 2800 ? jdText.slice(0, 2800) + '…' : jdText : null; const text = [ @@ -61,7 +74,7 @@ async function postCtaToSlack(webhookUrl: string, input: SubmitCtaInput): Promis `Contact: ${name} · ${email} · ${company}`, extraField ? `${extraLabel}: ${extraField}` : '', financialLine, - jdSnippet ? `\n*Job description:*\n${jdSnippet}` : '', + path === 'tech_safari' && jdSnippet ? `\n*Job description:*\n${jdSnippet}` : '', ] .filter(Boolean) .join('\n'); @@ -128,15 +141,65 @@ async function sendConfirmationEmail( export class submitCtaTool implements LuaTool { name = 'submit_cta'; description = - 'Handle a CTA form submission for either the Talent Safari (human recruiting) or Lua (AI agent) path. Posts to Slack and sends a confirmation email to the contact.'; + 'Handle a CTA form submission for either the Talent Safari (human recruiting) or Lua (AI agent) path. Posts to Slack and sends a confirmation email to the contact. ONLY call this after a real score_jd evaluation has been produced in the conversation — never fabricate scoringResult fields. If no evaluation has run, ask the user to paste a JD first instead of calling this tool.'; inputSchema = submitCtaInputSchema; async execute(input: SubmitCtaInput): Promise { + const { path, name, email, company, extraField, jdText, scoringResult } = input; + + // Real-evaluation gate — short-circuit if the agent invoked submit_cta without + // a genuine score_jd result in context (LLM fabrication sentinel pattern: + // role_title='Unknown' + score=0). Prevents garbage Slack posts, Sheets + // updates, and confirmation emails for non-existent evaluations. + if ( + !scoringResult?.role_title || + scoringResult.role_title.trim().toLowerCase() === 'unknown' || + !scoringResult.score + ) { + return { + posted: false, + confirmationSent: false, + skipped: true, + reason: 'no_evaluation_context', + }; + } + const slackUrl = env('SLACK_LEADS_WEBHOOK_URL') ?? ''; const resendKey = env('RESEND_API_KEY') ?? ''; const fromEmail = env('FROM_EMAIL') ?? ''; + // Store CTA submission to Data + try { + await Data.create( + 'cta-submissions', + { + path, + name, + email, + company, + extra_field: extraField ?? '', + role_title: scoringResult.role_title, + score: scoringResult.score, + verdict_line: scoringResult.verdict_line, + recommended_cta: scoringResult.recommended_cta, + cta_clicked: path === 'lua' ? 'Lua' : 'Talent Safari', + jd_text: jdText ?? '', + timestamp: new Date().toISOString(), + }, + `${scoringResult.role_title} ${path} ${company} ${jdText ?? ''}`.slice(0, 2000), + ); + } catch { /* non-fatal */ } + await postCtaToSlack(slackUrl, input); + + // Sheets — update CTA Clicked + Path for this email, non-fatal + const sheetsUrl = env('SHEETS_WEBHOOK_URL') ?? ''; + if (sheetsUrl) { + try { + await updateSheetsRow(sheetsUrl, input.email, input.path); + } catch { /* non-fatal */ } + } + await sendConfirmationEmail(resendKey, fromEmail, input); return { @@ -154,14 +217,16 @@ export const submitCtaSkill = new LuaSkill({ name: 'submit-cta', description: 'Handles CTA form submissions — routes the contact to Talent Safari (human recruiting) or Lua (AI agent build), posts to Slack, and sends a confirmation email.', - context: `Use the submit_cta tool when a user completes a CTA form after reviewing their evaluation results. + context: `Use the submit_cta tool when a user completes a CTA form AFTER reviewing their evaluation results. + +PRECONDITION: A score_jd call must have produced a real scoringResult earlier in this conversation. If no evaluation has run yet, do NOT call submit_cta — instead tell the user to paste a job description so Ada can evaluate it first. Never fabricate scoringResult fields (no placeholder role_title='Unknown', score=0, verdict_line='No evaluation completed yet'). If the tool is called without a real evaluation, it returns { skipped: true, reason: 'no_evaluation_context' }. Two paths are supported: - tech_safari: The user wants a human hire sourced by Talent Safari. Collect name, email, company, and optionally "When do you need this seat filled?". - lua: The user wants an AI agent built by Lua. Collect name, email, company, and optionally "What should this agent own first?". -Always pass the scoringResult from the earlier score_jd call so Slack gets the full role context. +Always pass the actual scoringResult from the earlier score_jd call so Slack gets the full role context. -The tool posts a plain-text Slack notification and sends a path-appropriate confirmation email. Returns { posted: true, confirmationSent: true } on success.`, +The tool posts a plain-text Slack notification and sends a path-appropriate confirmation email. Returns { posted: true, confirmationSent: true } on success, or { skipped: true, reason } when the real-evaluation gate trips.`, tools: [new submitCtaTool()], }); diff --git a/vercel.json b/vercel.json new file mode 100644 index 00000000..2e7bea24 --- /dev/null +++ b/vercel.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://openapi.vercel.sh/vercel.json", + "buildCommand": "echo 'Static HTML + api/ serverless — no build step needed.'", + "outputDirectory": ".", + "functions": { + "api/lua-chat.js": { "maxDuration": 120 } + }, + "rewrites": [ + { "source": "/results", "destination": "/index.html" }, + { "source": "/score", "destination": "/index.html" } + ], + "headers": [ + { + "source": "/(.*)", + "headers": [ + { "key": "X-Frame-Options", "value": "DENY" }, + { "key": "X-Content-Type-Options", "value": "nosniff" }, + { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" } + ] + } + ] +}