@skillrecordings/cli 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -300
- package/dist/{chunk-F3WI3BN5.js → chunk-4VWYLYQ6.js} +176 -117
- package/dist/chunk-4VWYLYQ6.js.map +1 -0
- package/dist/{chunk-V34YUISF.js → chunk-SCSLY3L5.js} +63 -1
- package/dist/{chunk-V34YUISF.js.map → chunk-SCSLY3L5.js.map} +1 -1
- package/dist/{chunk-GNPR4OKX.js → chunk-UTPBU2WN.js} +3 -3
- package/dist/{chunk-H3D6VCME.js → chunk-ZZGGSV6N.js} +7 -5
- package/dist/chunk-ZZGGSV6N.js.map +1 -0
- package/dist/{config-HHQF5U6R.js → config-3GIHLVO4.js} +4 -4
- package/dist/index.js +2727 -2632
- package/dist/index.js.map +1 -1
- package/dist/{pipeline-L72KB4SP.js → pipeline-BX3TO5EY.js} +3 -3
- package/dist/{routing-BAEPFB7V.js → routing-W3Y5PNH6.js} +2 -2
- package/dist/{src-6OB6UR3N.js → src-IJEFQUUU.js} +6 -2
- package/package.json +1 -1
- package/dist/chunk-F3WI3BN5.js.map +0 -1
- package/dist/chunk-H3D6VCME.js.map +0 -1
- /package/dist/{chunk-GNPR4OKX.js.map → chunk-UTPBU2WN.js.map} +0 -0
- /package/dist/{config-HHQF5U6R.js.map → config-3GIHLVO4.js.map} +0 -0
- /package/dist/{pipeline-L72KB4SP.js.map → pipeline-BX3TO5EY.js.map} +0 -0
- /package/dist/{routing-BAEPFB7V.js.map → routing-W3Y5PNH6.js.map} +0 -0
- /package/dist/{src-6OB6UR3N.js.map → src-IJEFQUUU.js.map} +0 -0
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from "./chunk-HKRLO2GE.js";
|
|
15
15
|
import {
|
|
16
16
|
queryVectors
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-ZZGGSV6N.js";
|
|
18
18
|
import {
|
|
19
19
|
Index2
|
|
20
20
|
} from "./chunk-MG37YDAK.js";
|
|
@@ -81,7 +81,9 @@ function computeMessageSignals(body, subject = "") {
|
|
|
81
81
|
isPersonalToInstructor: PERSONAL_MESSAGE_PATTERN.test(text) || INSTRUCTOR_MENTION_PATTERN.test(text) && /(?:thank|love|amazing|big fan)/i.test(text),
|
|
82
82
|
// Presales signals (set by LLM classifier, defaulted here)
|
|
83
83
|
isPresalesFaq: false,
|
|
84
|
-
isPresalesTeam: false
|
|
84
|
+
isPresalesTeam: false,
|
|
85
|
+
isThirdPartyReceipt: false,
|
|
86
|
+
isKnownVendorDomain: false
|
|
85
87
|
};
|
|
86
88
|
}
|
|
87
89
|
function computeThreadSignals(input) {
|
|
@@ -165,6 +167,8 @@ function computeThreadSignals(input) {
|
|
|
165
167
|
// Presales signals (merged from base)
|
|
166
168
|
isPresalesFaq: baseSignals.isPresalesFaq || threadWideSignals.isPresalesFaq,
|
|
167
169
|
isPresalesTeam: baseSignals.isPresalesTeam || threadWideSignals.isPresalesTeam,
|
|
170
|
+
isThirdPartyReceipt: false,
|
|
171
|
+
isKnownVendorDomain: false,
|
|
168
172
|
// Thread structure
|
|
169
173
|
threadLength: sorted.length,
|
|
170
174
|
threadDurationHours,
|
|
@@ -283,6 +287,24 @@ var VENDOR_PATTERNS = [
|
|
|
283
287
|
/\bproduction[- ]ready\s+(?:saas|app|template|boilerplate|platform|starter)/i
|
|
284
288
|
// cold SaaS pitch
|
|
285
289
|
];
|
|
290
|
+
var THIRD_PARTY_RECEIPT_PATTERNS = [
|
|
291
|
+
/\b(?:invoice|receipt|payment)\b.*\b(?:fly\.io|upstash|dmarc|mux|inngest|vercel|github|heroku|aws|digitalocean|cloudflare|netlify|render)\b/i,
|
|
292
|
+
/\b(?:fly\.io|upstash|dmarc|mux|inngest)\b.*\b(?:invoice|receipt|payment|billing|subscription|charge)\b/i,
|
|
293
|
+
/your\s+(?:monthly|annual|weekly)\s+(?:invoice|receipt|statement)\s+(?:from|for)\b/i
|
|
294
|
+
];
|
|
295
|
+
var KNOWN_VENDOR_DOMAINS = [
|
|
296
|
+
"fly.io",
|
|
297
|
+
"upstash.com",
|
|
298
|
+
"dmarcdigests.com",
|
|
299
|
+
"dmarc.postmarkapp.com",
|
|
300
|
+
"mux.com",
|
|
301
|
+
"inngest.com",
|
|
302
|
+
"gaming1.com",
|
|
303
|
+
"guestposting",
|
|
304
|
+
"meecocreative.com",
|
|
305
|
+
"getrecall.ai",
|
|
306
|
+
"seaverse.ai"
|
|
307
|
+
];
|
|
286
308
|
var LEGAL_THREAT_PATTERNS = [
|
|
287
309
|
/\b(?:my\s+)?lawyer/i,
|
|
288
310
|
/\blegal\s+action/i,
|
|
@@ -404,6 +426,9 @@ function extractSignals(input) {
|
|
|
404
426
|
hasAngrySentiment: ANGRY_PATTERNS.some((p) => p.test(text)),
|
|
405
427
|
isAutomated: AUTOMATED_PATTERNS.some((p) => p.test(text)) || (input.from ? /noreply|no-reply|mailer-daemon/i.test(input.from) : false),
|
|
406
428
|
isVendorOutreach: VENDOR_PATTERNS.some((p) => p.test(text)),
|
|
429
|
+
// ADR-0003 D2: Third-party receipts and known vendor domains
|
|
430
|
+
isThirdPartyReceipt: THIRD_PARTY_RECEIPT_PATTERNS.some((p) => p.test(text)),
|
|
431
|
+
isKnownVendorDomain: input.from ? KNOWN_VENDOR_DOMAINS.some((d) => input.from.toLowerCase().includes(d)) : false,
|
|
407
432
|
// Escalation signals
|
|
408
433
|
hasLegalThreat: LEGAL_THREAT_PATTERNS.some((p) => p.test(fullText)),
|
|
409
434
|
hasOutsidePolicyTimeframe: OUTSIDE_POLICY_PATTERNS.some(
|
|
@@ -429,6 +454,15 @@ function fastClassify(input, signals) {
|
|
|
429
454
|
_fastPathRule: "automated_system"
|
|
430
455
|
};
|
|
431
456
|
}
|
|
457
|
+
if (signals.isThirdPartyReceipt || signals.isKnownVendorDomain) {
|
|
458
|
+
return {
|
|
459
|
+
category: "system",
|
|
460
|
+
confidence: 0.95,
|
|
461
|
+
signals,
|
|
462
|
+
reasoning: signals.isKnownVendorDomain ? `Sender domain matches known vendor/service (${input.from})` : "Third-party receipt/notification \u2014 not a customer support request",
|
|
463
|
+
_fastPathRule: signals.isKnownVendorDomain ? "known_vendor_domain" : "third_party_receipt"
|
|
464
|
+
};
|
|
465
|
+
}
|
|
432
466
|
if (signals.isVendorOutreach && !signals.hasEmailInBody) {
|
|
433
467
|
return {
|
|
434
468
|
category: "spam",
|
|
@@ -1467,8 +1501,10 @@ var EditDraftSchema = z2.object({
|
|
|
1467
1501
|
cc: z2.array(z2.string()).optional(),
|
|
1468
1502
|
bcc: z2.array(z2.string()).optional(),
|
|
1469
1503
|
subject: z2.string().optional(),
|
|
1470
|
-
version: z2.string()
|
|
1504
|
+
version: z2.string(),
|
|
1471
1505
|
// Required for optimistic locking
|
|
1506
|
+
channel_id: z2.string().optional()
|
|
1507
|
+
// Required by Front API for PATCH
|
|
1472
1508
|
});
|
|
1473
1509
|
var MessageTemplateFolderSchema = z2.object({
|
|
1474
1510
|
_links: z2.object({
|
|
@@ -2318,6 +2354,12 @@ function createInstrumentedFrontClient(config) {
|
|
|
2318
2354
|
}
|
|
2319
2355
|
|
|
2320
2356
|
// ../core/src/pipeline/steps/comment.ts
|
|
2357
|
+
var REASONING_MAX_LENGTH = 150;
|
|
2358
|
+
function truncateReasoning(text, maxLength = REASONING_MAX_LENGTH) {
|
|
2359
|
+
if (!text) return text;
|
|
2360
|
+
if (text.length <= maxLength) return text;
|
|
2361
|
+
return text.slice(0, maxLength).trimEnd() + "\u2026";
|
|
2362
|
+
}
|
|
2321
2363
|
function formatSupportComment(context) {
|
|
2322
2364
|
const parts = ["\u{1F916} **Agent Research Context**\n"];
|
|
2323
2365
|
if (context.user) {
|
|
@@ -2406,121 +2448,47 @@ function formatEscalationType(type) {
|
|
|
2406
2448
|
return "Escalated";
|
|
2407
2449
|
}
|
|
2408
2450
|
}
|
|
2409
|
-
function formatPurchase(purchase, adminBaseUrl) {
|
|
2410
|
-
const status = purchase.status !== "active" ? ` (${purchase.status})` : "";
|
|
2411
|
-
const amount = purchase.amount ? ` - $${(purchase.amount / 100).toFixed(2)}` : "";
|
|
2412
|
-
if (adminBaseUrl && purchase.productId) {
|
|
2413
|
-
const adminLink = `${adminBaseUrl}/purchases/${purchase.productId}`;
|
|
2414
|
-
return `- [${purchase.productName}](${adminLink})${amount}${status}`;
|
|
2415
|
-
}
|
|
2416
|
-
return `- ${purchase.productName}${amount}${status}`;
|
|
2417
|
-
}
|
|
2418
2451
|
function formatEscalationComment(context) {
|
|
2419
|
-
const parts = [];
|
|
2420
2452
|
const emoji = getEscalationEmoji(context.type);
|
|
2421
2453
|
const typeLabel = formatEscalationType(context.type);
|
|
2422
|
-
parts
|
|
2423
|
-
`);
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
);
|
|
2430
|
-
if (context.classification.reasoning) {
|
|
2431
|
-
parts.push(`**Agent reasoning:** ${context.classification.reasoning}`);
|
|
2432
|
-
}
|
|
2433
|
-
}
|
|
2434
|
-
parts.push("\n---");
|
|
2435
|
-
parts.push("**Customer Info**");
|
|
2436
|
-
parts.push(`- **Email:** ${context.customer.email}`);
|
|
2437
|
-
if (context.customer.name) {
|
|
2438
|
-
parts.push(`- **Name:** ${context.customer.name}`);
|
|
2439
|
-
}
|
|
2440
|
-
if (context.customer.id) {
|
|
2441
|
-
parts.push(`- **ID:** ${context.customer.id}`);
|
|
2442
|
-
}
|
|
2443
|
-
parts.push("\n**Purchases:**");
|
|
2444
|
-
if (context.purchases && context.purchases.length > 0) {
|
|
2445
|
-
const adminBaseUrl = context.links?.admin?.replace(/\/users\/.*$/, "");
|
|
2446
|
-
for (const p of context.purchases) {
|
|
2447
|
-
parts.push(formatPurchase(p, adminBaseUrl));
|
|
2448
|
-
}
|
|
2449
|
-
} else {
|
|
2450
|
-
parts.push("_No purchases found for this email_");
|
|
2451
|
-
}
|
|
2452
|
-
if (context.agentFindings && context.agentFindings.length > 0) {
|
|
2453
|
-
parts.push("\n**What Agent Found/Tried:**");
|
|
2454
|
-
for (const finding of context.agentFindings) {
|
|
2455
|
-
parts.push(`- ${finding}`);
|
|
2456
|
-
}
|
|
2457
|
-
}
|
|
2458
|
-
if (context.links) {
|
|
2459
|
-
const hasLinks = context.links.admin || context.links.magicLogin || context.links.frontConversation;
|
|
2460
|
-
if (hasLinks) {
|
|
2461
|
-
parts.push("\n---");
|
|
2462
|
-
parts.push("**Quick Links**");
|
|
2463
|
-
if (context.links.admin) {
|
|
2464
|
-
parts.push(`- [Admin Profile](${context.links.admin})`);
|
|
2465
|
-
}
|
|
2466
|
-
if (context.links.magicLogin) {
|
|
2467
|
-
parts.push(`- [Magic Login](${context.links.magicLogin})`);
|
|
2468
|
-
}
|
|
2469
|
-
if (context.links.frontConversation) {
|
|
2470
|
-
parts.push(`- [Front Conversation](${context.links.frontConversation})`);
|
|
2471
|
-
}
|
|
2472
|
-
}
|
|
2454
|
+
const parts = [];
|
|
2455
|
+
parts.push(`${emoji} **${typeLabel}:** ${context.reason}`);
|
|
2456
|
+
const purchaseCount = context.purchases?.length ?? 0;
|
|
2457
|
+
const purchaseSummary = purchaseCount > 0 ? `${purchaseCount} purchase${purchaseCount > 1 ? "s" : ""}` : "no purchases";
|
|
2458
|
+
parts.push(`${context.customer.email} (${purchaseSummary})`);
|
|
2459
|
+
if (context.links?.magicLogin) {
|
|
2460
|
+
parts.push(`[Magic Login](${context.links.magicLogin})`);
|
|
2473
2461
|
}
|
|
2474
2462
|
return parts.join("\n");
|
|
2475
2463
|
}
|
|
2476
2464
|
function formatApprovalComment(context) {
|
|
2477
|
-
const parts = [];
|
|
2478
|
-
parts.push("\u{1F50D} **Draft Pending Review**\n");
|
|
2479
|
-
parts.push(`**Review Reason:** ${context.reviewReason}`);
|
|
2480
2465
|
const confidencePercent = Math.round(context.confidence * 100);
|
|
2481
|
-
const
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2466
|
+
const parts = [];
|
|
2467
|
+
const cat = context.category ? `${context.category} ` : "";
|
|
2468
|
+
parts.push(
|
|
2469
|
+
`\u{1F50D} **Review:** ${cat}(${confidencePercent}%) \u2014 ${context.reviewReason}`
|
|
2470
|
+
);
|
|
2486
2471
|
if (context.customerEmail) {
|
|
2487
|
-
parts.push(
|
|
2488
|
-
}
|
|
2489
|
-
parts.push("\n---");
|
|
2490
|
-
parts.push("**Draft Preview:**");
|
|
2491
|
-
parts.push("");
|
|
2492
|
-
const draftLines = context.draft.split("\n");
|
|
2493
|
-
for (const line of draftLines) {
|
|
2494
|
-
parts.push(`> ${line}`);
|
|
2472
|
+
parts.push(context.customerEmail);
|
|
2495
2473
|
}
|
|
2496
2474
|
if (context.actionLinks) {
|
|
2497
|
-
|
|
2498
|
-
parts.push("**Actions:**");
|
|
2475
|
+
const links = [];
|
|
2499
2476
|
if (context.actionLinks.approve) {
|
|
2500
|
-
|
|
2477
|
+
links.push(`[Approve](${context.actionLinks.approve})`);
|
|
2501
2478
|
}
|
|
2502
2479
|
if (context.actionLinks.edit) {
|
|
2503
|
-
|
|
2480
|
+
links.push(`[Edit](${context.actionLinks.edit})`);
|
|
2481
|
+
}
|
|
2482
|
+
if (links.length > 0) {
|
|
2483
|
+
parts.push(links.join(" \xB7 "));
|
|
2504
2484
|
}
|
|
2505
2485
|
}
|
|
2506
2486
|
return parts.join("\n");
|
|
2507
2487
|
}
|
|
2508
2488
|
function formatAuditComment(context) {
|
|
2509
|
-
const parts = [];
|
|
2510
2489
|
const actionEmoji = context.action === "auto_sent" ? "\u2705" : context.action === "draft_created" ? "\u{1F4DD}" : context.action === "silenced" ? "\u{1F507}" : context.action === "escalated" ? "\u26A0\uFE0F" : "\u{1F916}";
|
|
2511
|
-
parts.push(
|
|
2512
|
-
`${actionEmoji} **Agent Action: ${formatActionLabel(context.action)}**`
|
|
2513
|
-
);
|
|
2514
2490
|
const confidencePercent = Math.round(context.confidence * 100);
|
|
2515
|
-
|
|
2516
|
-
`Category: ${context.category} | Confidence: ${confidencePercent}%`
|
|
2517
|
-
);
|
|
2518
|
-
const timestamp = context.timestamp ?? /* @__PURE__ */ new Date();
|
|
2519
|
-
parts.push(`Timestamp: ${timestamp.toISOString()}`);
|
|
2520
|
-
if (context.messageId) {
|
|
2521
|
-
parts.push(`Message ID: ${context.messageId}`);
|
|
2522
|
-
}
|
|
2523
|
-
return parts.join("\n");
|
|
2491
|
+
return `${actionEmoji} ${formatActionLabel(context.action)} \u2014 ${context.category} (${confidencePercent}%)`;
|
|
2524
2492
|
}
|
|
2525
2493
|
function formatActionLabel(action) {
|
|
2526
2494
|
switch (action) {
|
|
@@ -2573,7 +2541,7 @@ function formatDecisionComment(context) {
|
|
|
2573
2541
|
const confidencePercent = Math.round(context.confidence * 100);
|
|
2574
2542
|
parts.push(`**Category:** ${context.category} (${confidencePercent}%)`);
|
|
2575
2543
|
if (context.reasoning) {
|
|
2576
|
-
parts.push(`**Reasoning:** ${context.reasoning}`);
|
|
2544
|
+
parts.push(`**Reasoning:** ${truncateReasoning(context.reasoning)}`);
|
|
2577
2545
|
}
|
|
2578
2546
|
if (context.customerEmail) {
|
|
2579
2547
|
const customerLine = context.customerName ? `${context.customerName} (${context.customerEmail})` : context.customerEmail;
|
|
@@ -2760,12 +2728,13 @@ init_esm_shims();
|
|
|
2760
2728
|
var BASE_DRAFT_PROMPT = `You are a support agent. Write a helpful response to the customer.
|
|
2761
2729
|
|
|
2762
2730
|
## Style Guide
|
|
2763
|
-
- Be direct and concise
|
|
2764
|
-
-
|
|
2765
|
-
- No
|
|
2731
|
+
- Be direct and concise \u2014 1-3 sentences is ideal, not paragraphs
|
|
2732
|
+
- Give the answer or link first, explain only if needed
|
|
2733
|
+
- No corporate speak, no enthusiasm performance
|
|
2766
2734
|
- Get to the point immediately
|
|
2767
|
-
- If you need info, just ask
|
|
2768
|
-
-
|
|
2735
|
+
- If you need info, just ask \u2014 no softening
|
|
2736
|
+
- NEVER use numbered step-by-step lists for simple questions. A direct link + 1 sentence beats a 5-step guide every time.
|
|
2737
|
+
- NEVER say "I've escalated this" or "someone will reach out" \u2014 if you have a URL or answer, give it directly
|
|
2769
2738
|
|
|
2770
2739
|
## NEVER Use These Phrases
|
|
2771
2740
|
- "Great!" or exclamatory openers
|
|
@@ -2776,6 +2745,14 @@ var BASE_DRAFT_PROMPT = `You are a support agent. Write a helpful response to th
|
|
|
2776
2745
|
- "I understand" or "I hear you"
|
|
2777
2746
|
- "Thanks for reaching out"
|
|
2778
2747
|
- Em dashes (\u2014)
|
|
2748
|
+
- "Someone will reach out" / "I've escalated this"
|
|
2749
|
+
- "Pricing varies" (give the link instead)
|
|
2750
|
+
|
|
2751
|
+
## Prices and Numbers
|
|
2752
|
+
- NEVER cite specific dollar amounts, percentages, or discount numbers unless they appear in the gathered context below
|
|
2753
|
+
- If you don't have pricing data, link to the pricing/buy page instead
|
|
2754
|
+
- Wrong: "The course is $495 with a 45% discount"
|
|
2755
|
+
- Right: "You can see current pricing at [URL]"
|
|
2779
2756
|
|
|
2780
2757
|
## If You Don't Have Info
|
|
2781
2758
|
Don't make things up. If knowledge base has no answer:
|
|
@@ -2812,9 +2789,10 @@ function buildBillingPrompt(context) {
|
|
|
2812
2789
|
return `${BASE_DRAFT_PROMPT}
|
|
2813
2790
|
|
|
2814
2791
|
## Billing/Invoice
|
|
2815
|
-
-
|
|
2816
|
-
- Invoices are customizable
|
|
2817
|
-
-
|
|
2792
|
+
- Give them the direct link: ${invoicesUrl}
|
|
2793
|
+
- That's it. Invoices are customizable (company name, tax ID, address) and PDFs are editable.
|
|
2794
|
+
- Don't write a numbered step-by-step guide \u2014 just the link + one sentence.
|
|
2795
|
+
- NEVER fabricate dollar amounts or discount percentages.`;
|
|
2818
2796
|
}
|
|
2819
2797
|
function buildPresalesFaqPrompt(context) {
|
|
2820
2798
|
let promotionsSection = "";
|
|
@@ -2839,7 +2817,8 @@ Use this data to answer pricing, discount, and coupon questions. If a customer a
|
|
|
2839
2817
|
## Presales FAQ
|
|
2840
2818
|
- Answer pricing, curriculum, requirements, and discount questions
|
|
2841
2819
|
- Only reference information from the knowledge base or gathered context
|
|
2842
|
-
-
|
|
2820
|
+
- NEVER fabricate specific dollar amounts or discount percentages
|
|
2821
|
+
- For pricing questions: link to the buy/pricing page, explain that PPP/regional pricing adjusts automatically at checkout
|
|
2843
2822
|
- If unsure, offer to connect them with the team${promotionsSection}`;
|
|
2844
2823
|
}
|
|
2845
2824
|
function buildPresalesTeamPrompt(context) {
|
|
@@ -2870,17 +2849,16 @@ Use this data to answer team seat questions. If a customer needs more seats or w
|
|
|
2870
2849
|
## Team/Enterprise Inquiries
|
|
2871
2850
|
- Answer questions about team licensing, seat management, enterprise pricing
|
|
2872
2851
|
- If license data is available above, reference it directly
|
|
2873
|
-
-
|
|
2874
|
-
-
|
|
2852
|
+
- Link to the buy/pricing page for pricing questions \u2014 don't say "someone will reach out" or "pricing varies"
|
|
2853
|
+
- NEVER fabricate seat counts, pricing tiers, or discount numbers${licenseSection}`;
|
|
2875
2854
|
}
|
|
2876
2855
|
var STATIC_CATEGORY_PROMPTS = {
|
|
2877
2856
|
support_access: `${BASE_DRAFT_PROMPT}
|
|
2878
2857
|
|
|
2879
2858
|
## Access Issues
|
|
2880
|
-
-
|
|
2881
|
-
- If no purchase found: ask which email they used to buy
|
|
2882
|
-
-
|
|
2883
|
-
- GitHub login issues: they may have multiple GitHub accounts`,
|
|
2859
|
+
- If purchase found: send the magic login link directly
|
|
2860
|
+
- If no purchase found: ask which email they used to buy (1 sentence)
|
|
2861
|
+
- Don't write a multi-step troubleshooting guide unless they've already tried the basics`,
|
|
2884
2862
|
support_transfer: `${BASE_DRAFT_PROMPT}
|
|
2885
2863
|
|
|
2886
2864
|
## Transfer Requests
|
|
@@ -3148,6 +3126,34 @@ async function gather(input, options = {}) {
|
|
|
3148
3126
|
})
|
|
3149
3127
|
);
|
|
3150
3128
|
}
|
|
3129
|
+
if (tools.searchResolvedThreads) {
|
|
3130
|
+
const query = `${message.subject} ${message.body}`.slice(0, 500);
|
|
3131
|
+
gatherPromises.push(
|
|
3132
|
+
withTimeout(
|
|
3133
|
+
(async () => {
|
|
3134
|
+
try {
|
|
3135
|
+
const resolvedThreads = await tools.searchResolvedThreads(
|
|
3136
|
+
query,
|
|
3137
|
+
appId
|
|
3138
|
+
);
|
|
3139
|
+
result.knowledge = [...result.knowledge, ...resolvedThreads];
|
|
3140
|
+
} catch (error) {
|
|
3141
|
+
result.gatherErrors.push({
|
|
3142
|
+
step: "resolved_threads",
|
|
3143
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
3144
|
+
});
|
|
3145
|
+
}
|
|
3146
|
+
})(),
|
|
3147
|
+
timeout,
|
|
3148
|
+
"resolved threads search"
|
|
3149
|
+
).catch((err) => {
|
|
3150
|
+
result.gatherErrors.push({
|
|
3151
|
+
step: "resolved_threads",
|
|
3152
|
+
error: err.message
|
|
3153
|
+
});
|
|
3154
|
+
})
|
|
3155
|
+
);
|
|
3156
|
+
}
|
|
3151
3157
|
if (tools.getHistory && message.conversationId) {
|
|
3152
3158
|
gatherPromises.push(
|
|
3153
3159
|
withTimeout(
|
|
@@ -3560,7 +3566,7 @@ ${message.body}
|
|
|
3560
3566
|
---
|
|
3561
3567
|
Write your response:`;
|
|
3562
3568
|
if (useAgentMode && appId) {
|
|
3563
|
-
const { runSupportAgent } = await import("./config-
|
|
3569
|
+
const { runSupportAgent } = await import("./config-3GIHLVO4.js");
|
|
3564
3570
|
await log("debug", "draft using agent mode", {
|
|
3565
3571
|
workflow: "pipeline",
|
|
3566
3572
|
step: "draft",
|
|
@@ -3670,6 +3676,25 @@ Write your response:`;
|
|
|
3670
3676
|
});
|
|
3671
3677
|
const toolsUsed = memories.length > 0 ? ["memory_query"] : [];
|
|
3672
3678
|
const durationMs = Date.now() - startTime;
|
|
3679
|
+
if (!result.text?.trim()) {
|
|
3680
|
+
await log("warn", "draft:empty-response", {
|
|
3681
|
+
workflow: "pipeline",
|
|
3682
|
+
step: "draft",
|
|
3683
|
+
appId,
|
|
3684
|
+
conversationId,
|
|
3685
|
+
category: classification.category,
|
|
3686
|
+
model,
|
|
3687
|
+
durationMs
|
|
3688
|
+
});
|
|
3689
|
+
return {
|
|
3690
|
+
draft: "",
|
|
3691
|
+
reasoning: "LLM returned empty response",
|
|
3692
|
+
toolsUsed,
|
|
3693
|
+
durationMs,
|
|
3694
|
+
templateUsed: void 0,
|
|
3695
|
+
memoriesCited: void 0
|
|
3696
|
+
};
|
|
3697
|
+
}
|
|
3673
3698
|
await log("info", "draft:decision", {
|
|
3674
3699
|
workflow: "pipeline",
|
|
3675
3700
|
step: "draft",
|
|
@@ -3841,7 +3866,8 @@ var ROUTING_RULES = [
|
|
|
3841
3866
|
// NOTE: Must be BEFORE unknown_escalate so isPersonalToInstructor signal is honored
|
|
3842
3867
|
{
|
|
3843
3868
|
name: "personal_to_instructor",
|
|
3844
|
-
condition: ({ classification }) => classification.signals.isPersonalToInstructor,
|
|
3869
|
+
condition: ({ classification }) => classification.signals.isPersonalToInstructor && // ADR-0003 D4: presales_faq should respond, not escalate to instructor
|
|
3870
|
+
classification.category !== "presales_faq",
|
|
3845
3871
|
action: "escalate_instructor",
|
|
3846
3872
|
reason: "Personal message addressed to instructor"
|
|
3847
3873
|
},
|
|
@@ -4055,7 +4081,8 @@ var THREAD_ROUTING_RULES = [
|
|
|
4055
4081
|
// NOTE: Must be BEFORE unknown_escalate so isPersonalToInstructor signal is honored
|
|
4056
4082
|
{
|
|
4057
4083
|
name: "personal_to_instructor",
|
|
4058
|
-
condition: ({ classification }) => classification.signals.isPersonalToInstructor,
|
|
4084
|
+
condition: ({ classification }) => classification.signals.isPersonalToInstructor && // ADR-0003 D4: presales_faq should respond, not escalate to instructor
|
|
4085
|
+
classification.category !== "presales_faq",
|
|
4059
4086
|
action: "escalate_instructor",
|
|
4060
4087
|
reason: "Personal message addressed to instructor"
|
|
4061
4088
|
},
|
|
@@ -4700,6 +4727,19 @@ var FABRICATION_PATTERNS = {
|
|
|
4700
4727
|
percentage: /\d+%/g,
|
|
4701
4728
|
guarantee: /guarantee|always|never|definitely|certainly/gi
|
|
4702
4729
|
};
|
|
4730
|
+
var SIGNATURE_PATTERNS = [
|
|
4731
|
+
/\n\s*Best,?\s*$/im,
|
|
4732
|
+
/\n\s*Thanks,?\s*$/im,
|
|
4733
|
+
/\n\s*Cheers,?\s*$/im,
|
|
4734
|
+
/\n\s*Sincerely,?\s*$/im,
|
|
4735
|
+
/\n\s*Kind regards,?\s*$/im,
|
|
4736
|
+
/\n\s*Best regards,?\s*$/im,
|
|
4737
|
+
/\n\s*Warm regards,?\s*$/im,
|
|
4738
|
+
/\bTeam AI Hero\b/i,
|
|
4739
|
+
/\bTeam Total TypeScript\b/i,
|
|
4740
|
+
/\bTeam Epic Web\b/i,
|
|
4741
|
+
/\bTeam egghead\b/i
|
|
4742
|
+
];
|
|
4703
4743
|
var MIN_RESPONSE_LENGTH = 10;
|
|
4704
4744
|
var MAX_RESPONSE_LENGTH = 2e3;
|
|
4705
4745
|
function calculateConfidenceScore(issues) {
|
|
@@ -4767,6 +4807,23 @@ function checkBannedPhrases(draft2) {
|
|
|
4767
4807
|
}
|
|
4768
4808
|
return issues;
|
|
4769
4809
|
}
|
|
4810
|
+
function checkSignatures(draft2) {
|
|
4811
|
+
const issues = [];
|
|
4812
|
+
for (const pattern of SIGNATURE_PATTERNS) {
|
|
4813
|
+
const match = draft2.match(pattern);
|
|
4814
|
+
if (match) {
|
|
4815
|
+
issues.push({
|
|
4816
|
+
type: "banned_phrase",
|
|
4817
|
+
severity: "error",
|
|
4818
|
+
message: "Response contains a signature (Front adds signatures automatically)",
|
|
4819
|
+
match: match[0].trim(),
|
|
4820
|
+
position: match.index
|
|
4821
|
+
});
|
|
4822
|
+
break;
|
|
4823
|
+
}
|
|
4824
|
+
}
|
|
4825
|
+
return issues;
|
|
4826
|
+
}
|
|
4770
4827
|
function checkFabrication(draft2, context) {
|
|
4771
4828
|
const issues = [];
|
|
4772
4829
|
const hasKnowledge = (context.knowledge?.length ?? 0) > 0;
|
|
@@ -5059,6 +5116,7 @@ function validateSync(input) {
|
|
|
5059
5116
|
...checkInternalLeaks(draft2),
|
|
5060
5117
|
...checkMetaCommentary(draft2),
|
|
5061
5118
|
...checkBannedPhrases(draft2),
|
|
5119
|
+
...checkSignatures(draft2),
|
|
5062
5120
|
...checkFabrication(draft2, context),
|
|
5063
5121
|
...checkLength(draft2)
|
|
5064
5122
|
];
|
|
@@ -5096,6 +5154,7 @@ async function validate(input, options = {}) {
|
|
|
5096
5154
|
...checkInternalLeaks(draft2),
|
|
5097
5155
|
...checkMetaCommentary(draft2),
|
|
5098
5156
|
...checkBannedPhrases(draft2),
|
|
5157
|
+
...checkSignatures(draft2),
|
|
5099
5158
|
...checkFabrication(draft2, context),
|
|
5100
5159
|
...checkLength(draft2)
|
|
5101
5160
|
];
|
|
@@ -7096,4 +7155,4 @@ export {
|
|
|
7096
7155
|
runPipeline,
|
|
7097
7156
|
runThreadPipeline
|
|
7098
7157
|
};
|
|
7099
|
-
//# sourceMappingURL=chunk-
|
|
7158
|
+
//# sourceMappingURL=chunk-4VWYLYQ6.js.map
|