@lssm/example.ai-support-bot 0.0.0-canary-20251217083314 → 1.41.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.
Files changed (58) hide show
  1. package/.turbo/turbo-build.log +16 -18
  2. package/dist/docs/ai-support-bot.docblock.js +12 -27
  3. package/dist/docs/index.js +1 -1
  4. package/dist/example.js +1 -38
  5. package/dist/index.js +1 -5
  6. package/dist/setup.js +1 -47
  7. package/package.json +12 -15
  8. package/tsconfig.tsbuildinfo +1 -1
  9. package/.turbo/turbo-build$colon$bundle.log +0 -74
  10. package/CHANGELOG.md +0 -16
  11. package/dist/docs/ai-support-bot.docblock.d.ts +0 -1
  12. package/dist/docs/index.d.ts +0 -1
  13. package/dist/example.d.ts +0 -33
  14. package/dist/index.d.ts +0 -3
  15. package/dist/libs/contracts/dist/docs/PUBLISHING.docblock.js +0 -16
  16. package/dist/libs/contracts/dist/docs/accessibility_wcag_compliance_specs.docblock.js +0 -16
  17. package/dist/libs/contracts/dist/docs/index.js +0 -29
  18. package/dist/libs/contracts/dist/docs/presentations.js +0 -71
  19. package/dist/libs/contracts/dist/docs/registry.js +0 -44
  20. package/dist/libs/contracts/dist/docs/tech/PHASE_1_QUICKSTART.docblock.js +0 -16
  21. package/dist/libs/contracts/dist/docs/tech/PHASE_2_AI_NATIVE_OPERATIONS.docblock.js +0 -16
  22. package/dist/libs/contracts/dist/docs/tech/PHASE_3_AUTO_EVOLUTION.docblock.js +0 -16
  23. package/dist/libs/contracts/dist/docs/tech/PHASE_4_PERSONALIZATION_ENGINE.docblock.js +0 -16
  24. package/dist/libs/contracts/dist/docs/tech/PHASE_5_ZERO_TOUCH_OPERATIONS.docblock.js +0 -16
  25. package/dist/libs/contracts/dist/docs/tech/auth/better-auth-nextjs.docblock.js +0 -80
  26. package/dist/libs/contracts/dist/docs/tech/contracts/openapi-export.docblock.js +0 -57
  27. package/dist/libs/contracts/dist/docs/tech/lifecycle-stage-system.docblock.js +0 -16
  28. package/dist/libs/contracts/dist/docs/tech/llm/llm-integration.docblock.js +0 -357
  29. package/dist/libs/contracts/dist/docs/tech/mcp-endpoints.docblock.js +0 -37
  30. package/dist/libs/contracts/dist/docs/tech/presentation-runtime.docblock.js +0 -16
  31. package/dist/libs/contracts/dist/docs/tech/schema/README.docblock.js +0 -20
  32. package/dist/libs/contracts/dist/docs/tech/studio/learning-events.docblock.js +0 -48
  33. package/dist/libs/contracts/dist/docs/tech/studio/learning-journeys.docblock.js +0 -79
  34. package/dist/libs/contracts/dist/docs/tech/studio/platform-admin-panel.docblock.js +0 -84
  35. package/dist/libs/contracts/dist/docs/tech/studio/project-access-teams.docblock.js +0 -45
  36. package/dist/libs/contracts/dist/docs/tech/studio/project-routing.docblock.js +0 -67
  37. package/dist/libs/contracts/dist/docs/tech/studio/sandbox-unlogged.docblock.js +0 -40
  38. package/dist/libs/contracts/dist/docs/tech/studio/team-invitations.docblock.js +0 -69
  39. package/dist/libs/contracts/dist/docs/tech/studio/workspace-ops.docblock.js +0 -47
  40. package/dist/libs/contracts/dist/docs/tech/studio/workspaces.docblock.js +0 -62
  41. package/dist/libs/contracts/dist/docs/tech/telemetry-ingest.docblock.js +0 -155
  42. package/dist/libs/contracts/dist/docs/tech/templates/runtime.docblock.js +0 -20
  43. package/dist/libs/contracts/dist/docs/tech/vscode-extension.docblock.js +0 -101
  44. package/dist/libs/contracts/dist/docs/tech/workflows/overview.docblock.js +0 -20
  45. package/dist/libs/logger/dist/context.node.js +0 -78
  46. package/dist/libs/logger/dist/elysia-plugin.js +0 -3
  47. package/dist/libs/logger/dist/formatters.js +0 -163
  48. package/dist/libs/logger/dist/index.js +0 -7
  49. package/dist/libs/logger/dist/logger.node.js +0 -189
  50. package/dist/libs/logger/dist/timer.js +0 -126
  51. package/dist/libs/logger/dist/tracer.node.js +0 -115
  52. package/dist/libs/logger/dist/types.js +0 -13
  53. package/dist/libs/support-bot/dist/bot/auto-responder.js +0 -83
  54. package/dist/libs/support-bot/dist/bot/index.js +0 -2
  55. package/dist/libs/support-bot/dist/bot/tools.js +0 -71
  56. package/dist/libs/support-bot/dist/rag/ticket-resolver.js +0 -63
  57. package/dist/libs/support-bot/dist/tickets/classifier.js +0 -198
  58. package/dist/setup.d.ts +0 -4
@@ -1,126 +0,0 @@
1
- //#region ../../libs/logger/dist/timer.mjs
2
- var Timer = class {
3
- id;
4
- startTime;
5
- laps = [];
6
- stopped = false;
7
- stopTime;
8
- constructor(id) {
9
- this.id = id || crypto.randomUUID();
10
- this.startTime = performance.now();
11
- }
12
- /**
13
- * Stop the timer and return elapsed time in milliseconds
14
- */
15
- stop() {
16
- if (this.stopped) return this.getElapsed();
17
- this.stopTime = performance.now();
18
- this.stopped = true;
19
- const elapsed = this.stopTime - this.startTime;
20
- this.laps.push({
21
- label: "stop",
22
- time: this.stopTime,
23
- elapsed
24
- });
25
- return elapsed;
26
- }
27
- /**
28
- * Record a lap time and return elapsed time since start
29
- */
30
- lap(label) {
31
- if (this.stopped) return this.getElapsed();
32
- const now = performance.now();
33
- const elapsed = now - this.startTime;
34
- this.laps.push({
35
- label: label || `lap-${this.laps.length + 1}`,
36
- time: now,
37
- elapsed
38
- });
39
- return elapsed;
40
- }
41
- /**
42
- * Get elapsed time without stopping the timer
43
- */
44
- getElapsed() {
45
- if (this.stopped && this.stopTime) return this.stopTime - this.startTime;
46
- return performance.now() - this.startTime;
47
- }
48
- /**
49
- * Get all recorded laps
50
- */
51
- getLaps() {
52
- return [...this.laps];
53
- }
54
- /**
55
- * Get timer summary with total time and laps
56
- */
57
- getSummary() {
58
- return {
59
- id: this.id,
60
- totalTime: this.getElapsed(),
61
- isRunning: !this.stopped,
62
- laps: this.getLaps()
63
- };
64
- }
65
- /**
66
- * Reset the timer (starts a new timing session)
67
- */
68
- reset() {
69
- this.startTime = performance.now();
70
- this.laps = [];
71
- this.stopped = false;
72
- this.stopTime = void 0;
73
- }
74
- };
75
- /**
76
- * Utility class for managing multiple timers
77
- */
78
- var TimerManager = class {
79
- timers = /* @__PURE__ */ new Map();
80
- /**
81
- * Start a new timer
82
- */
83
- start(id) {
84
- const timer = new Timer(id);
85
- this.timers.set(timer.id, timer);
86
- return timer;
87
- }
88
- /**
89
- * Get an existing timer
90
- */
91
- get(id) {
92
- return this.timers.get(id);
93
- }
94
- /**
95
- * Stop and remove a timer
96
- */
97
- stop(id) {
98
- const timer = this.timers.get(id);
99
- if (timer) {
100
- const elapsed = timer.stop();
101
- this.timers.delete(id);
102
- return elapsed;
103
- }
104
- }
105
- /**
106
- * Get all active timers
107
- */
108
- getActive() {
109
- return Array.from(this.timers.values()).filter((timer) => !timer.getSummary().isRunning === false);
110
- }
111
- /**
112
- * Clear all timers
113
- */
114
- clear() {
115
- this.timers.clear();
116
- }
117
- /**
118
- * Get summary of all timers
119
- */
120
- getSummary() {
121
- return Array.from(this.timers.values()).map((timer) => timer.getSummary());
122
- }
123
- };
124
-
125
- //#endregion
126
- export { Timer, TimerManager };
@@ -1,115 +0,0 @@
1
- import { LogContext } from "./context.node.js";
2
- import { Timer } from "./timer.js";
3
-
4
- //#region ../../libs/logger/dist/tracer.node.mjs
5
- var Tracer = class {
6
- context;
7
- activeSpans = /* @__PURE__ */ new Map();
8
- constructor() {
9
- this.context = LogContext.getInstance();
10
- }
11
- /**
12
- * Start a new trace span
13
- */
14
- startSpan(options) {
15
- const parentTrace = this.context.getCurrentTrace();
16
- const span = {
17
- traceId: parentTrace?.traceId || this.generateTraceId(),
18
- parentId: parentTrace?.spanId,
19
- spanId: this.generateSpanId(),
20
- operationType: options.operationType,
21
- operationName: options.operationName,
22
- startTime: performance.now(),
23
- metadata: { ...options.metadata },
24
- tags: [...options.tags || []]
25
- };
26
- this.activeSpans.set(span.spanId, span);
27
- this.context.setTrace(span);
28
- return span;
29
- }
30
- /**
31
- * Finish a trace span
32
- */
33
- finishSpan(spanId) {
34
- const span = this.activeSpans.get(spanId);
35
- if (!span) return;
36
- const duration = performance.now() - span.startTime;
37
- this.activeSpans.delete(spanId);
38
- if (this.context.getCurrentTrace()?.spanId === spanId && span.parentId) {
39
- const parentSpan = this.findSpanById(span.parentId);
40
- if (parentSpan) this.context.setTrace(parentSpan);
41
- }
42
- return duration;
43
- }
44
- /**
45
- * Execute a function within a trace span
46
- */
47
- async trace(options, fn) {
48
- const span = this.startSpan(options);
49
- const timer = options.autoTiming !== false ? new Timer(`trace-${span.spanId}`) : void 0;
50
- try {
51
- const result = await fn();
52
- const duration = this.finishSpan(span.spanId);
53
- if (timer) timer.stop();
54
- if (duration !== void 0) span.metadata.duration = duration;
55
- return result;
56
- } catch (error) {
57
- span.metadata.error = {
58
- name: error.name || "Unknown",
59
- message: error.message || "Unknown error",
60
- stack: error.stack
61
- };
62
- const duration = this.finishSpan(span.spanId);
63
- span.metadata.duration = duration;
64
- if (timer) timer.stop();
65
- throw error;
66
- }
67
- }
68
- /**
69
- * Add metadata to current span
70
- */
71
- addMetadata(key, value) {
72
- const currentTrace = this.context.getCurrentTrace();
73
- if (currentTrace) currentTrace.metadata[key] = value;
74
- }
75
- /**
76
- * Add tags to current span
77
- */
78
- addTags(...tags) {
79
- const currentTrace = this.context.getCurrentTrace();
80
- if (currentTrace) currentTrace.tags.push(...tags);
81
- }
82
- /**
83
- * Get current trace context
84
- */
85
- getCurrentTrace() {
86
- return this.context.getCurrentTrace();
87
- }
88
- /**
89
- * Get all active spans
90
- */
91
- getActiveSpans() {
92
- return Array.from(this.activeSpans.values());
93
- }
94
- /**
95
- * Find a span by ID
96
- */
97
- findSpanById(spanId) {
98
- return this.activeSpans.get(spanId);
99
- }
100
- /**
101
- * Generate a unique trace ID
102
- */
103
- generateTraceId() {
104
- return crypto.randomUUID().replace(/-/g, "");
105
- }
106
- /**
107
- * Generate a unique span ID
108
- */
109
- generateSpanId() {
110
- return crypto.randomUUID().replace(/-/g, "").substring(0, 16);
111
- }
112
- };
113
-
114
- //#endregion
115
- export { Tracer };
@@ -1,13 +0,0 @@
1
- //#region ../../libs/logger/dist/types.mjs
2
- let LogLevel = /* @__PURE__ */ function(LogLevel$1) {
3
- LogLevel$1[LogLevel$1["TRACE"] = 0] = "TRACE";
4
- LogLevel$1[LogLevel$1["DEBUG"] = 1] = "DEBUG";
5
- LogLevel$1[LogLevel$1["INFO"] = 2] = "INFO";
6
- LogLevel$1[LogLevel$1["WARN"] = 3] = "WARN";
7
- LogLevel$1[LogLevel$1["ERROR"] = 4] = "ERROR";
8
- LogLevel$1[LogLevel$1["FATAL"] = 5] = "FATAL";
9
- return LogLevel$1;
10
- }({});
11
-
12
- //#endregion
13
- export { LogLevel };
@@ -1,83 +0,0 @@
1
- //#region ../../libs/support-bot/dist/bot/auto-responder.js
2
- var AutoResponder = class {
3
- llm;
4
- model;
5
- tone;
6
- closing;
7
- constructor(options) {
8
- this.llm = options?.llm;
9
- this.model = options?.model;
10
- this.tone = options?.tone ?? "friendly";
11
- this.closing = options?.closing ?? (this.tone === "friendly" ? "We remain available if you need anything else." : "Please let us know if you require additional assistance.");
12
- }
13
- async draft(ticket, resolution, classification) {
14
- if (this.llm) return this.generateWithLLM(ticket, resolution, classification);
15
- return this.generateTemplate(ticket, resolution, classification);
16
- }
17
- async generateWithLLM(ticket, resolution, classification) {
18
- const prompt = `You are a ${this.tone} support agent. Draft an email response.
19
- Ticket Subject: ${ticket.subject}
20
- Ticket Body: ${ticket.body}
21
- Detected Category: ${classification.category}
22
- Detected Priority: ${classification.priority}
23
- Resolution:
24
- ${resolution.answer}
25
- Citations: ${resolution.citations.map((c) => c.label).join(", ")}`;
26
- const body = (await this.llm.chat([{
27
- role: "system",
28
- content: [{
29
- type: "text",
30
- text: "Write empathetic, accurate support replies that cite sources when relevant."
31
- }]
32
- }, {
33
- role: "user",
34
- content: [{
35
- type: "text",
36
- text: prompt
37
- }]
38
- }], { model: this.model })).message.content.map((part) => "text" in part ? part.text : "").join("").trim();
39
- return this.buildDraft(ticket, resolution, classification, body);
40
- }
41
- generateTemplate(ticket, resolution, classification) {
42
- const body = `${ticket.customerName ? `Hi ${ticket.customerName},` : "Hi there,"}
43
-
44
- Thanks for contacting us about "${ticket.subject}". ${this.renderCategoryIntro(classification)}
45
-
46
- ${resolution.answer}
47
-
48
- ${this.renderCitations(resolution)}
49
- ${this.closing}
50
-
51
- — ContractSpec Support`;
52
- return this.buildDraft(ticket, resolution, classification, body);
53
- }
54
- buildDraft(ticket, resolution, classification, body) {
55
- return {
56
- ticketId: ticket.id,
57
- subject: ticket.subject.startsWith("Re:") ? ticket.subject : `Re: ${ticket.subject}`,
58
- body,
59
- confidence: Math.min(resolution.confidence, classification.confidence),
60
- requiresEscalation: resolution.actions.some((action) => action.type === "escalate") || Boolean(classification.escalationRequired),
61
- citations: resolution.citations
62
- };
63
- }
64
- renderCategoryIntro(classification) {
65
- switch (classification.category) {
66
- case "billing": return "I understand billing issues can be stressful, so let me clarify the situation.";
67
- case "technical": return "I see you encountered a technical issue. Here is what happened and how to fix it.";
68
- case "product": return "Thanks for sharing feedback about the product. Here are the next steps.";
69
- case "account": return "Account access is critical, so let me walk you through the resolution.";
70
- case "compliance": return "Compliance questions require precision. See the policy-aligned answer below.";
71
- default: return "Here is what we found after reviewing your request.";
72
- }
73
- }
74
- renderCitations(resolution) {
75
- if (!resolution.citations.length) return "";
76
- return `References:\n${resolution.citations.map((citation, index) => {
77
- return `- ${citation.label || `Source ${index + 1}`}${citation.url ? ` (${citation.url})` : ""}`;
78
- }).join("\n")}`;
79
- }
80
- };
81
-
82
- //#endregion
83
- export { AutoResponder };
@@ -1,2 +0,0 @@
1
- import { AutoResponder } from "./auto-responder.js";
2
- import "./tools.js";
@@ -1,71 +0,0 @@
1
- import * as z from "zod";
2
-
3
- //#region ../../libs/support-bot/dist/bot/tools.js
4
- const ticketSchema = z.object({
5
- id: z.string(),
6
- subject: z.string(),
7
- body: z.string(),
8
- channel: z.enum([
9
- "email",
10
- "chat",
11
- "phone",
12
- "portal"
13
- ]),
14
- customerName: z.string().optional(),
15
- customerEmail: z.string().optional(),
16
- metadata: z.object().optional()
17
- });
18
- const supportCitationSchema = z.object({
19
- label: z.string(),
20
- url: z.string().optional(),
21
- snippet: z.string().optional(),
22
- score: z.number().optional()
23
- });
24
- const supportActionSchema = z.object({
25
- type: z.enum([
26
- "respond",
27
- "escalate",
28
- "refund",
29
- "manual"
30
- ]),
31
- label: z.string(),
32
- payload: z.record(z.string(), z.string())
33
- });
34
- const supportResolutionSchema = z.object({
35
- ticketId: z.string(),
36
- answer: z.string(),
37
- confidence: z.number(),
38
- citations: supportCitationSchema.array(),
39
- actions: supportActionSchema.array(),
40
- escalationReason: z.string().optional(),
41
- knowledgeUpdates: z.array(z.string()).optional()
42
- });
43
- const ticketClassificationSchema = z.object({
44
- ticketId: z.string(),
45
- category: z.enum([
46
- "billing",
47
- "technical",
48
- "product",
49
- "account",
50
- "compliance",
51
- "other"
52
- ]),
53
- priority: z.enum([
54
- "urgent",
55
- "high",
56
- "medium",
57
- "low"
58
- ]),
59
- sentiment: z.enum([
60
- "positive",
61
- "neutral",
62
- "negative",
63
- "frustrated"
64
- ]),
65
- intents: z.array(z.string()),
66
- tags: z.array(z.string()),
67
- confidence: z.number(),
68
- escalationRequired: z.boolean().optional()
69
- });
70
-
71
- //#endregion
@@ -1,63 +0,0 @@
1
- //#region ../../libs/support-bot/dist/rag/ticket-resolver.js
2
- var TicketResolver = class {
3
- knowledge;
4
- minConfidence;
5
- prependPrompt;
6
- constructor(options) {
7
- this.knowledge = options.knowledge;
8
- this.minConfidence = options.minConfidence ?? .65;
9
- this.prependPrompt = options.prependPrompt;
10
- }
11
- async resolve(ticket) {
12
- const question = this.buildQuestion(ticket);
13
- const answer = await this.knowledge.query(question);
14
- return this.toResolution(ticket, answer);
15
- }
16
- buildQuestion(ticket) {
17
- const header = [`Subject: ${ticket.subject}`, `Channel: ${ticket.channel}`];
18
- if (ticket.customerName) header.push(`Customer: ${ticket.customerName}`);
19
- return [
20
- this.prependPrompt,
21
- header.join("\n"),
22
- "---",
23
- ticket.body
24
- ].filter(Boolean).join("\n");
25
- }
26
- toResolution(ticket, answer) {
27
- const citations = answer.references.map((ref) => {
28
- return {
29
- label: typeof ref.payload?.title === "string" ? ref.payload.title : typeof ref.payload?.documentId === "string" ? ref.payload.documentId : ref.id,
30
- url: typeof ref.payload?.url === "string" ? ref.payload.url : void 0,
31
- snippet: typeof ref.payload?.text === "string" ? ref.payload.text.slice(0, 280) : void 0,
32
- score: ref.score
33
- };
34
- });
35
- const confidence = this.deriveConfidence(answer);
36
- const escalate = confidence < this.minConfidence || citations.length === 0;
37
- return {
38
- ticketId: ticket.id,
39
- answer: answer.answer,
40
- confidence,
41
- citations,
42
- actions: [escalate ? {
43
- type: "escalate",
44
- label: "Escalate for human review"
45
- } : {
46
- type: "respond",
47
- label: "Send automated response"
48
- }],
49
- escalationReason: escalate ? "Insufficient confidence or missing knowledge references" : void 0,
50
- knowledgeUpdates: escalate ? [ticket.body.slice(0, 200)] : void 0
51
- };
52
- }
53
- deriveConfidence(answer) {
54
- if (!answer.references.length) return .3;
55
- const topScore = answer.references[0]?.score ?? .4;
56
- const normalized = Math.min(1, Math.max(0, topScore));
57
- const tokenPenalty = answer.usage?.completionTokens ? Math.min(answer.usage.completionTokens / 1e3, .2) : 0;
58
- return Number((normalized - tokenPenalty).toFixed(2));
59
- }
60
- };
61
-
62
- //#endregion
63
- export { TicketResolver };
@@ -1,198 +0,0 @@
1
- //#region ../../libs/support-bot/dist/tickets/classifier.js
2
- const CATEGORY_KEYWORDS = {
3
- billing: [
4
- "invoice",
5
- "payout",
6
- "refund",
7
- "charge",
8
- "billing",
9
- "payment"
10
- ],
11
- technical: [
12
- "bug",
13
- "error",
14
- "crash",
15
- "issue",
16
- "failed",
17
- "timeout"
18
- ],
19
- product: [
20
- "feature",
21
- "roadmap",
22
- "idea",
23
- "request",
24
- "feedback"
25
- ],
26
- account: [
27
- "login",
28
- "password",
29
- "2fa",
30
- "account",
31
- "profile",
32
- "email change"
33
- ],
34
- compliance: [
35
- "kyc",
36
- "aml",
37
- "compliance",
38
- "regulation",
39
- "gdpr"
40
- ],
41
- other: []
42
- };
43
- const PRIORITY_HINTS = {
44
- urgent: [
45
- "urgent",
46
- "asap",
47
- "immediately",
48
- "today",
49
- "right away"
50
- ],
51
- high: [
52
- "high priority",
53
- "blocking",
54
- "major",
55
- "critical"
56
- ],
57
- medium: ["soon", "next few days"],
58
- low: [
59
- "nice to have",
60
- "when possible",
61
- "later"
62
- ]
63
- };
64
- const SENTIMENT_HINTS = {
65
- positive: [
66
- "love",
67
- "great",
68
- "awesome",
69
- "thank you"
70
- ],
71
- neutral: [
72
- "question",
73
- "wonder",
74
- "curious"
75
- ],
76
- negative: [
77
- "unhappy",
78
- "bad",
79
- "terrible",
80
- "awful",
81
- "angry"
82
- ],
83
- frustrated: [
84
- "furious",
85
- "frustrated",
86
- "fed up",
87
- "ridiculous"
88
- ]
89
- };
90
- var TicketClassifier = class {
91
- keywords;
92
- llm;
93
- llmModel;
94
- constructor(options) {
95
- this.keywords = {
96
- ...CATEGORY_KEYWORDS,
97
- ...options?.keywords ?? {}
98
- };
99
- this.llm = options?.llm;
100
- this.llmModel = options?.llmModel;
101
- }
102
- async classify(ticket) {
103
- const heuristics = this.heuristicClassification(ticket);
104
- if (!this.llm) return heuristics;
105
- try {
106
- const content = (await this.llm.chat([{
107
- role: "system",
108
- content: [{
109
- type: "text",
110
- text: "Classify the support ticket."
111
- }]
112
- }, {
113
- role: "user",
114
- content: [{
115
- type: "text",
116
- text: JSON.stringify({
117
- subject: ticket.subject,
118
- body: ticket.body,
119
- channel: ticket.channel
120
- })
121
- }]
122
- }], {
123
- responseFormat: "json",
124
- model: this.llmModel
125
- })).message.content.find((part) => "text" in part);
126
- if (content && "text" in content) {
127
- const parsed = JSON.parse(content.text);
128
- return {
129
- ...heuristics,
130
- ...parsed,
131
- intents: parsed.intents ?? heuristics.intents,
132
- tags: parsed.tags ?? heuristics.tags
133
- };
134
- }
135
- } catch {}
136
- return heuristics;
137
- }
138
- heuristicClassification(ticket) {
139
- const text = `${ticket.subject}\n${ticket.body}`.toLowerCase();
140
- const category = this.detectCategory(text);
141
- const priority = this.detectPriority(text);
142
- const sentiment = this.detectSentiment(text);
143
- const intents = this.extractIntents(text);
144
- const tags = intents.slice(0, 3);
145
- const confidence = this.estimateConfidence(category, priority, sentiment);
146
- return {
147
- ticketId: ticket.id,
148
- category,
149
- priority,
150
- sentiment,
151
- intents,
152
- tags,
153
- confidence,
154
- escalationRequired: priority === "urgent" || category === "compliance"
155
- };
156
- }
157
- detectCategory(text) {
158
- for (const [category, keywords] of Object.entries(this.keywords)) if (keywords.some((keyword) => text.includes(keyword))) return category;
159
- return "other";
160
- }
161
- detectPriority(text) {
162
- for (const priority of [
163
- "urgent",
164
- "high",
165
- "medium",
166
- "low"
167
- ]) if (PRIORITY_HINTS[priority].some((word) => text.includes(word))) return priority;
168
- return "medium";
169
- }
170
- detectSentiment(text) {
171
- for (const sentiment of [
172
- "frustrated",
173
- "negative",
174
- "neutral",
175
- "positive"
176
- ]) if (SENTIMENT_HINTS[sentiment].some((word) => text.includes(word))) return sentiment;
177
- return "neutral";
178
- }
179
- extractIntents(text) {
180
- const intents = [];
181
- if (text.includes("refund") || text.includes("chargeback")) intents.push("refund");
182
- if (text.includes("payout")) intents.push("payout");
183
- if (text.includes("login")) intents.push("login-help");
184
- if (text.includes("feature")) intents.push("feature-request");
185
- if (text.includes("bug") || text.includes("error")) intents.push("bug-report");
186
- return intents.length ? intents : ["general"];
187
- }
188
- estimateConfidence(category, priority, sentiment) {
189
- let base = .6;
190
- if (category !== "other") base += .1;
191
- if (priority === "urgent" || priority === "low") base += .05;
192
- if (sentiment === "frustrated") base -= .05;
193
- return Math.min(.95, Math.max(.4, Number(base.toFixed(2))));
194
- }
195
- };
196
-
197
- //#endregion
198
- export { TicketClassifier };
package/dist/setup.d.ts DELETED
@@ -1,4 +0,0 @@
1
- //#region src/setup.d.ts
2
- declare function runAiSupportBotExample(): Promise<void>;
3
- //#endregion
4
- export { runAiSupportBotExample };