untrap-mcp 0.2.5 → 0.2.7
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/dist/index.js +0 -0
- package/dist/middleware/logging.js +1 -1
- package/dist/tools/ai/explain-budget.d.ts.map +1 -1
- package/dist/tools/ai/explain-budget.js +7 -4
- package/dist/tools/ai/explain-budget.js.map +1 -1
- package/dist/tools/ai/explain-experience.d.ts.map +1 -1
- package/dist/tools/ai/explain-experience.js +8 -5
- package/dist/tools/ai/explain-experience.js.map +1 -1
- package/dist/tools/ai/explain-sla.d.ts.map +1 -1
- package/dist/tools/ai/explain-sla.js +8 -5
- package/dist/tools/ai/explain-sla.js.map +1 -1
- package/dist/tools/ai/root-causes.d.ts.map +1 -1
- package/dist/tools/ai/root-causes.js +4 -1
- package/dist/tools/ai/root-causes.js.map +1 -1
- package/dist/tools/ai/similar-tickets.d.ts.map +1 -1
- package/dist/tools/ai/similar-tickets.js +4 -0
- package/dist/tools/ai/similar-tickets.js.map +1 -1
- package/dist/tools/ai/suggest-improvement.d.ts.map +1 -1
- package/dist/tools/ai/suggest-improvement.js +4 -1
- package/dist/tools/ai/suggest-improvement.js.map +1 -1
- package/dist/tools/cfo/agreement-analysis.d.ts.map +1 -1
- package/dist/tools/cfo/agreement-analysis.js +4 -1
- package/dist/tools/cfo/agreement-analysis.js.map +1 -1
- package/dist/tools/composite/ticket-deep-dive.d.ts.map +1 -1
- package/dist/tools/composite/ticket-deep-dive.js +15 -11
- package/dist/tools/composite/ticket-deep-dive.js.map +1 -1
- package/dist/tools/qbr/recommendations.d.ts.map +1 -1
- package/dist/tools/qbr/recommendations.js +7 -4
- package/dist/tools/qbr/recommendations.js.map +1 -1
- package/dist/tools/qbr/top-issues.d.ts.map +1 -1
- package/dist/tools/qbr/top-issues.js +8 -5
- package/dist/tools/qbr/top-issues.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
File without changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { queryWrite } from "../db/gateway-client.js";
|
|
2
2
|
export async function logToolCall(log) {
|
|
3
3
|
try {
|
|
4
|
-
await queryWrite(`INSERT INTO
|
|
4
|
+
await queryWrite(`INSERT INTO mcp_tool_call_log (msp_id, tool_name, parameters, response_summary, duration_ms, status, error_message)
|
|
5
5
|
VALUES ($1, $2, $3, $4, $5, $6, $7)`, [
|
|
6
6
|
log.mspId,
|
|
7
7
|
log.toolName,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explain-budget.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/explain-budget.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"explain-budget.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/explain-budget.ts"],"names":[],"mappings":"AAIA,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,mBAAmB;;;GAwF5B"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { queryRLS } from "../../db/gateway-client.js";
|
|
2
2
|
import { chatCompletion } from "../../db/azure-openai.js";
|
|
3
|
+
import { getFilters, buildTicketFilter } from "../../db/filters.js";
|
|
3
4
|
export async function explainBudgetOverage(mspId, params) {
|
|
4
5
|
// Check cache first
|
|
5
6
|
const cached = await queryRLS(`SELECT explanation FROM ticket_budget_overage_explanation
|
|
@@ -8,11 +9,13 @@ export async function explainBudgetOverage(mspId, params) {
|
|
|
8
9
|
return { explanation: cached[0].explanation, cached: true };
|
|
9
10
|
}
|
|
10
11
|
// Gather context
|
|
12
|
+
const filters = await getFilters(mspId);
|
|
13
|
+
const tf = buildTicketFilter(filters, { tableAlias: "tl", includeTechnicianFilter: false });
|
|
11
14
|
const [ticket, budget, notes] = await Promise.all([
|
|
12
|
-
queryRLS(`SELECT ticket_id, summary, priority_name, owner_name, company_name,
|
|
13
|
-
resolution_minutes
|
|
14
|
-
FROM ticket_lifecycle
|
|
15
|
-
WHERE msp_id = $1 AND ticket_id = $2`, [mspId, params.ticketId], mspId),
|
|
15
|
+
queryRLS(`SELECT tl.ticket_id, tl.summary, tl.priority_name, tl.owner_name, tl.company_name,
|
|
16
|
+
tl.resolution_minutes
|
|
17
|
+
FROM ticket_lifecycle tl
|
|
18
|
+
WHERE tl.msp_id = $1 AND tl.ticket_id = $2 ${tf}`, [mspId, params.ticketId], mspId),
|
|
16
19
|
queryRLS(`SELECT budget_hours, actual_hours, hours_over_budget, pct_over_budget,
|
|
17
20
|
member_name
|
|
18
21
|
FROM analytics.technician_ticket_budget_mv
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explain-budget.js","sourceRoot":"","sources":["../../../src/tools/ai/explain-budget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"explain-budget.js","sourceRoot":"","sources":["../../../src/tools/ai/explain-budget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAOpE,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAAa,EACb,MAA2B;IAE3B,oBAAoB;IACpB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAC3B;qEACiE,EACjE,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC,EACjD,KAAK,CACN,CAAC;IAEF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC9D,CAAC;IAED,iBAAiB;IACjB,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,iBAAiB,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,CAAC;IAE5F,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAChD,QAAQ,CACN;;;oDAG8C,EAAE,EAAE,EAClD,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,KAAK,CACN;QACD,QAAQ,CACN;;;uEAGiE,EACjE,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,gBAAgB,CAAC,EACjD,KAAK,CACN;QACD,QAAQ,CACN;;;;gBAIU,EACV,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,KAAK,CACN;KACF,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/C,OAAO,EAAE,WAAW,EAAE,4CAA4C,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACtF,CAAC;IAED,MAAM,YAAY,GAAG,KAAK;SACvB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAAC,CAAC,IAAe,EAAE,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SACjD,IAAI,CAAC,SAAS,CAAC,CAAC;IAEnB,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,4TAA4T;aACtU;YACD;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,WAAW,MAAM,CAAC,QAAQ,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO;YACtD,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa;UACzB,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY;cAClB,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW;UACzB,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,cAAc,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC,eAAe;;;EAGjG,YAAY,IAAI,oBAAoB;;wCAEE;aACjC;SACF;QACD,SAAS,EAAE,GAAG;QACd,WAAW,EAAE,GAAG;KACjB,CAAC,CAAC;IAEH,qCAAqC;IACrC,QAAQ,CACN;;uFAEmF,EACnF,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,OAAO,CAAC,EACjE,KAAK,CACN,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAElB,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACxD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explain-experience.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/explain-experience.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"explain-experience.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/explain-experience.ts"],"names":[],"mappings":"AAIA,UAAU,gBAAgB;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,gBA6EzB"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { queryRLS } from "../../db/gateway-client.js";
|
|
2
2
|
import { chatCompletion } from "../../db/azure-openai.js";
|
|
3
|
+
import { getFilters, buildTicketFilter } from "../../db/filters.js";
|
|
3
4
|
export async function explainExperienceScore(mspId, params) {
|
|
5
|
+
const filters = await getFilters(mspId);
|
|
6
|
+
const tf = buildTicketFilter(filters, { tableAlias: "tl", includeTechnicianFilter: false });
|
|
4
7
|
const [metrics, sentiment, slaBreaches] = await Promise.all([
|
|
5
8
|
queryRLS(`SELECT company_name, ticket_count, avg_response_minutes, avg_resolution_minutes,
|
|
6
9
|
avg_sentiment_score, health_score, total_cost, sla_breach_count
|
|
@@ -15,13 +18,13 @@ export async function explainExperienceScore(mspId, params) {
|
|
|
15
18
|
FROM ticket_notes_sentiment tns
|
|
16
19
|
JOIN ticket_lifecycle tl ON tl.msp_id = tns.msp_id AND tl.ticket_id = tns.ticket_id
|
|
17
20
|
WHERE tns.msp_id = $1 AND LOWER(tl.company_name) = LOWER($2)
|
|
18
|
-
AND tl.responded_date >= CURRENT_DATE - INTERVAL '90 days'`, [mspId, params.clientName], mspId),
|
|
21
|
+
AND tl.responded_date >= CURRENT_DATE - INTERVAL '90 days' ${tf}`, [mspId, params.clientName], mspId),
|
|
19
22
|
queryRLS(`SELECT COUNT(*)::int as breach_count,
|
|
20
23
|
AVG(resolution_minutes)::numeric as avg_breach_resolution_min
|
|
21
|
-
FROM ticket_lifecycle
|
|
22
|
-
WHERE msp_id = $1 AND LOWER(company_name) = LOWER($2)
|
|
23
|
-
AND sla_status = 'breached'
|
|
24
|
-
AND responded_date >= CURRENT_DATE - INTERVAL '90 days'`, [mspId, params.clientName], mspId),
|
|
24
|
+
FROM ticket_lifecycle tl
|
|
25
|
+
WHERE tl.msp_id = $1 AND LOWER(tl.company_name) = LOWER($2)
|
|
26
|
+
AND tl.sla_status = 'breached'
|
|
27
|
+
AND tl.responded_date >= CURRENT_DATE - INTERVAL '90 days' ${tf}`, [mspId, params.clientName], mspId),
|
|
25
28
|
]);
|
|
26
29
|
if (metrics.length === 0) {
|
|
27
30
|
return { found: false, message: `No data found for client "${params.clientName}"` };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explain-experience.js","sourceRoot":"","sources":["../../../src/tools/ai/explain-experience.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"explain-experience.js","sourceRoot":"","sources":["../../../src/tools/ai/explain-experience.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAMpE,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,KAAa,EACb,MAAwB;IAExB,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,iBAAiB,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,CAAC;IAE5F,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1D,QAAQ,CACN;;;;;;eAMS,EACT,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,EAC1B,KAAK,CACN;QACD,QAAQ,CACN;;;;;;sEAMgE,EAAE,EAAE,EACpE,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,EAC1B,KAAK,CACN;QACD,QAAQ,CACN;;;;;sEAKgE,EAAE,EAAE,EACpE,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,EAC1B,KAAK,CACN;KACF,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,6BAA6B,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;IACtF,CAAC;IAED,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACrB,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7B,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAE/B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,sTAAsT;aAChU;YACD;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,WAAW,MAAM,CAAC,UAAU;gBAC7B,CAAC,CAAC,YAAY;iBACb,CAAC,CAAC,YAAY;gBACf,CAAC,CAAC,oBAAoB;kBACpB,CAAC,CAAC,sBAAsB;iBACzB,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,cAAc,oBAAoB,CAAC,CAAC,WAAW;gBACtE,CAAC,CAAC,YAAY,SAAS,CAAC,CAAC,yBAAyB;eACnD,CAAC,CAAC,UAAU;;8DAEmC;aACvD;SACF;QACD,SAAS,EAAE,GAAG;QACd,WAAW,EAAE,GAAG;KACjB,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,YAAY,EAAE,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAC7E,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explain-sla.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/explain-sla.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"explain-sla.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/explain-sla.ts"],"names":[],"mappings":"AAIA,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB;;;GAoEzB"}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { queryRLS } from "../../db/gateway-client.js";
|
|
2
2
|
import { chatCompletion } from "../../db/azure-openai.js";
|
|
3
|
+
import { getFilters, buildTicketFilter } from "../../db/filters.js";
|
|
3
4
|
export async function explainSlaVariance(mspId, params) {
|
|
5
|
+
const filters = await getFilters(mspId);
|
|
6
|
+
const tf = buildTicketFilter(filters, { tableAlias: "tl", includeTechnicianFilter: false });
|
|
4
7
|
const [ticket, timeEntries] = await Promise.all([
|
|
5
|
-
queryRLS(`SELECT ticket_id, summary, priority_name, owner_name, company_name,
|
|
6
|
-
board_name, status, response_minutes, resolution_minutes,
|
|
7
|
-
sla_status, entered_date::text, responded_date::text, closed_date::text
|
|
8
|
-
FROM ticket_lifecycle
|
|
9
|
-
WHERE msp_id = $1 AND ticket_id = $2`, [mspId, params.ticketId], mspId),
|
|
8
|
+
queryRLS(`SELECT tl.ticket_id, tl.summary, tl.priority_name, tl.owner_name, tl.company_name,
|
|
9
|
+
tl.board_name, tl.status, tl.response_minutes, tl.resolution_minutes,
|
|
10
|
+
tl.sla_status, tl.entered_date::text, tl.responded_date::text, tl.closed_date::text
|
|
11
|
+
FROM ticket_lifecycle tl
|
|
12
|
+
WHERE tl.msp_id = $1 AND tl.ticket_id = $2 ${tf}`, [mspId, params.ticketId], mspId),
|
|
10
13
|
queryRLS(`SELECT member_name, actual_hours, date_worked::text, notes_text
|
|
11
14
|
FROM time_entries
|
|
12
15
|
WHERE msp_id = $1 AND ticket_id = $2
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explain-sla.js","sourceRoot":"","sources":["../../../src/tools/ai/explain-sla.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"explain-sla.js","sourceRoot":"","sources":["../../../src/tools/ai/explain-sla.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAMpE,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAa,EACb,MAAwB;IAExB,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,iBAAiB,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,CAAC;IAE5F,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC9C,QAAQ,CACN;;;;oDAI8C,EAAE,EAAE,EAClD,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,KAAK,CACN;QACD,QAAQ,CACN;;;gCAG0B,EAC1B,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,KAAK,CACN;KACF,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC3D,CAAC;IAED,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,OAAO,GAAG,WAAW;SACxB,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,KAAK,EAAE,CAAC,WAAW,KAAK,EAAE,CAAC,YAAY,QAAS,EAAE,CAAC,UAAqB,EAAE,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,UAAU,EAAE,CAAC;SACzI,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,wNAAwN;aAClO;YACD;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,OAAO;YAC1C,CAAC,CAAC,aAAa,aAAa,CAAC,CAAC,MAAM,UAAU,CAAC,CAAC,UAAU;UAC5D,CAAC,CAAC,YAAY,YAAY,CAAC,CAAC,UAAU;WACrC,CAAC,CAAC,YAAY,gBAAgB,CAAC,CAAC,cAAc,aAAa,CAAC,CAAC,WAAW;iBAClE,CAAC,CAAC,gBAAgB,0BAA0B,CAAC,CAAC,kBAAkB;cACnE,CAAC,CAAC,UAAU;;;EAGxB,OAAO,IAAI,iBAAiB;;8BAEA;aACvB;SACF;QACD,SAAS,EAAE,GAAG;QACd,WAAW,EAAE,GAAG;KACjB,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1C,OAAO;YACL,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,OAAO;YACjD,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;SAC9B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACtD,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-causes.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/root-causes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"root-causes.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/root-causes.ts"],"names":[],"mappings":"AAIA,UAAU,eAAe;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,eAAe;;;;;;;;;;;;;GAiExB"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { queryRLS } from "../../db/gateway-client.js";
|
|
2
2
|
import { chatCompletion } from "../../db/azure-openai.js";
|
|
3
|
+
import { getFilters, buildCompanyExclusionFilter } from "../../db/filters.js";
|
|
3
4
|
export async function analyzeRootCauses(mspId, params) {
|
|
4
5
|
const fromDate = params.fromDate ?? new Date(Date.now() - 90 * 86400000).toISOString().split("T")[0];
|
|
5
6
|
const toDate = params.toDate ?? new Date().toISOString().split("T")[0];
|
|
7
|
+
const filters = await getFilters(mspId);
|
|
8
|
+
const cf = buildCompanyExclusionFilter(filters, { tableAlias: "rc" });
|
|
6
9
|
let categoryFilter = "";
|
|
7
10
|
const queryParams = [mspId];
|
|
8
11
|
if (params.category) {
|
|
@@ -14,7 +17,7 @@ export async function analyzeRootCauses(mspId, params) {
|
|
|
14
17
|
FROM root_cause_ticket_classifier rc
|
|
15
18
|
WHERE rc.msp_id = $1
|
|
16
19
|
AND rc.root_cause_category IS NOT NULL
|
|
17
|
-
${categoryFilter}
|
|
20
|
+
${categoryFilter} ${cf}
|
|
18
21
|
GROUP BY rc.root_cause_category
|
|
19
22
|
ORDER BY count DESC
|
|
20
23
|
LIMIT 15`, queryParams, mspId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root-causes.js","sourceRoot":"","sources":["../../../src/tools/ai/root-causes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"root-causes.js","sourceRoot":"","sources":["../../../src/tools/ai/root-causes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"similar-tickets.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/similar-tickets.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"similar-tickets.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/similar-tickets.ts"],"names":[],"mappings":"AAGA,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,aAAa;;;;;;;;;;;;;;GA6DtB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { queryRLS } from "../../db/gateway-client.js";
|
|
2
|
+
import { getFilters, buildTicketFilter } from "../../db/filters.js";
|
|
2
3
|
export async function findSimilarTickets(mspId, params) {
|
|
3
4
|
const limit = params.limit ?? 5;
|
|
4
5
|
// Get the source ticket's embedding
|
|
@@ -12,6 +13,8 @@ export async function findSimilarTickets(mspId, params) {
|
|
|
12
13
|
};
|
|
13
14
|
}
|
|
14
15
|
// Find similar tickets using cosine similarity on problem_embedding
|
|
16
|
+
const filters = await getFilters(mspId);
|
|
17
|
+
const tf = buildTicketFilter(filters, { tableAlias: "tl" });
|
|
15
18
|
const similar = await queryRLS(`SELECT te.ticket_id,
|
|
16
19
|
1 - (te.problem_embedding <=> (
|
|
17
20
|
SELECT problem_embedding FROM ticket_embeddings
|
|
@@ -29,6 +32,7 @@ export async function findSimilarTickets(mspId, params) {
|
|
|
29
32
|
WHERE te.msp_id = $1
|
|
30
33
|
AND te.ticket_id != $2
|
|
31
34
|
AND te.problem_embedding IS NOT NULL
|
|
35
|
+
${tf}
|
|
32
36
|
ORDER BY te.problem_embedding <=> (
|
|
33
37
|
SELECT problem_embedding FROM ticket_embeddings
|
|
34
38
|
WHERE msp_id = $1 AND ticket_id = $2
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"similar-tickets.js","sourceRoot":"","sources":["../../../src/tools/ai/similar-tickets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"similar-tickets.js","sourceRoot":"","sources":["../../../src/tools/ai/similar-tickets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAOpE,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAa,EACb,MAAqB;IAErB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;IAEhC,oCAAoC;IACpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAC3B;;0CAEsC,EACtC,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,KAAK,CACN,CAAC;IAEF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;QACxD,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,kCAAkC,MAAM,CAAC,QAAQ,kEAAkE;SAC7H,CAAC;IACJ,CAAC;IAED,oEAAoE;IACpE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,iBAAiB,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5D,MAAM,OAAO,GAAG,MAAM,QAAQ,CAC5B;;;;;;;;;;;;;;;;;SAiBK,EAAE;;;;;cAKG,EACV,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,EAC/B,KAAK,CACN,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,IAAI;QACX,aAAa,EAAE,MAAM,CAAC,QAAQ;QAC9B,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU;QACpC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,GAAG,CAAC;YACJ,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI;SACvE,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggest-improvement.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/suggest-improvement.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"suggest-improvement.d.ts","sourceRoot":"","sources":["../../../src/tools/ai/suggest-improvement.ts"],"names":[],"mappings":"AAIA,UAAU,aAAa;IACrB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,aAAa,gBA0FtB"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { queryRLS } from "../../db/gateway-client.js";
|
|
2
2
|
import { chatCompletion } from "../../db/azure-openai.js";
|
|
3
|
+
import { getFilters, buildTicketFilter } from "../../db/filters.js";
|
|
3
4
|
export async function suggestTechnicianImprovement(mspId, params) {
|
|
5
|
+
const filters = await getFilters(mspId);
|
|
6
|
+
const tf = buildTicketFilter(filters, { tableAlias: "tl", includeTechnicianFilter: false });
|
|
4
7
|
const [dqScore, recentNotes, profile] = await Promise.all([
|
|
5
8
|
queryRLS(`SELECT technician_name, quality_points, completeness_points,
|
|
6
9
|
accuracy_points, timeliness_points, detail_quality_points,
|
|
@@ -13,7 +16,7 @@ export async function suggestTechnicianImprovement(mspId, params) {
|
|
|
13
16
|
FROM ticket_notes_sentiment tns
|
|
14
17
|
JOIN ticket_lifecycle tl ON tl.msp_id = tns.msp_id AND tl.ticket_id = tns.ticket_id
|
|
15
18
|
WHERE tns.msp_id = $1 AND LOWER(tl.owner_name) = LOWER($2)
|
|
16
|
-
AND tl.responded_date >= CURRENT_DATE - INTERVAL '30 days'
|
|
19
|
+
AND tl.responded_date >= CURRENT_DATE - INTERVAL '30 days' ${tf}
|
|
17
20
|
ORDER BY tns.created_at DESC
|
|
18
21
|
LIMIT 5`, [mspId, params.technicianName], mspId),
|
|
19
22
|
queryRLS(`SELECT technician_name, level, hourly_rate
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggest-improvement.js","sourceRoot":"","sources":["../../../src/tools/ai/suggest-improvement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"suggest-improvement.js","sourceRoot":"","sources":["../../../src/tools/ai/suggest-improvement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAMpE,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,KAAa,EACb,MAAqB;IAErB,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,iBAAiB,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,CAAC;IAE5F,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACxD,QAAQ,CACN;;;;;;eAMS,EACT,CAAC,KAAK,EAAE,MAAM,CAAC,cAAc,CAAC,EAC9B,KAAK,CACN;QACD,QAAQ,CACN;;;;sEAIgE,EAAE;;eAEzD,EACT,CAAC,KAAK,EAAE,MAAM,CAAC,cAAc,CAAC,EAC9B,KAAK,CACN;QACD,QAAQ,CACN;;;eAGS,EACT,CAAC,KAAK,EAAE,MAAM,CAAC,cAAc,CAAC,EAC9B,KAAK,CACN;KACF,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,4BAA4B,MAAM,CAAC,cAAc,GAAG,EAAE,CAAC;IACzF,CAAC;IAED,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,WAAW,GAAG,WAAW;SAC5B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAO,CAAC,CAAC,IAAe,EAAE,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAC,eAAe,GAAG,CAAC;SAC/F,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;QAClC,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,kYAAkY;aAC5Y;YACD;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,eAAe,EAAE,CAAC,eAAe,YAAY,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,SAAS;YAChF,EAAE,CAAC,cAAc;kBACX,EAAE,CAAC,mBAAmB;cAC1B,EAAE,CAAC,eAAe;gBAChB,EAAE,CAAC,iBAAiB;oBAChB,EAAE,CAAC,qBAAqB;WACjC,EAAE,CAAC,cAAc,YAAY,EAAE,CAAC,WAAW,iBAAiB,EAAE,CAAC,eAAe;;;EAGvF,WAAW,IAAI,2BAA2B;;4CAEA;aACrC;SACF;QACD,SAAS,EAAE,GAAG;QACd,WAAW,EAAE,GAAG;KACjB,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1C,OAAO;YACL,KAAK,EAAE,IAAI;YACX,aAAa,EAAE,EAAE,CAAC,cAAc;YAChC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,IAAI;YAChC,GAAG,MAAM;SACV,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,KAAK,EAAE,IAAI;YACX,aAAa,EAAE,EAAE,CAAC,cAAc;YAChC,WAAW,EAAE,MAAM,CAAC,OAAO;YAC3B,SAAS,EAAE,EAAE;YACb,iBAAiB,EAAE,EAAE;SACtB,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agreement-analysis.d.ts","sourceRoot":"","sources":["../../../src/tools/cfo/agreement-analysis.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agreement-analysis.d.ts","sourceRoot":"","sources":["../../../src/tools/cfo/agreement-analysis.ts"],"names":[],"mappings":"AAGA,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM;;;;;;;;;;GAyEvD"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { queryRLS } from "../../db/gateway-client.js";
|
|
2
|
+
import { getFilters, buildTimeEntriesFilter } from "../../db/filters.js";
|
|
2
3
|
export async function cfoAgreementAnalysis(mspId) {
|
|
4
|
+
const filters = await getFilters(mspId);
|
|
5
|
+
const tef = buildTimeEntriesFilter(filters);
|
|
3
6
|
// Agreement type breakdown
|
|
4
7
|
const byType = await queryRLS(`SELECT type_name,
|
|
5
8
|
COUNT(*)::int as total,
|
|
@@ -20,7 +23,7 @@ export async function cfoAgreementAnalysis(mspId) {
|
|
|
20
23
|
WHERE te.msp_id = $1
|
|
21
24
|
AND te.time_start >= CURRENT_DATE - INTERVAL '90 days'
|
|
22
25
|
AND ca.id IS NULL
|
|
23
|
-
AND te.company IS NOT NULL
|
|
26
|
+
AND te.company IS NOT NULL ${tef}
|
|
24
27
|
GROUP BY te.company
|
|
25
28
|
HAVING SUM(te.actual_hours) > 1
|
|
26
29
|
ORDER BY cost_last_90d DESC
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agreement-analysis.js","sourceRoot":"","sources":["../../../src/tools/cfo/agreement-analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"agreement-analysis.js","sourceRoot":"","sources":["../../../src/tools/cfo/agreement-analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAEzE,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAAa;IACtD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAC5C,2BAA2B;IAC3B,MAAM,MAAM,GAAG,MAAM,QAAQ,CAC3B;;;;;;;0BAOsB,EACtB,CAAC,KAAK,CAAC,EACP,KAAK,CACN,CAAC;IAEF,6DAA6D;IAC7D,MAAM,kBAAkB,GAAG,MAAM,QAAQ,CACvC;;;;;;;;;;oCAUgC,GAAG;;;;cAIzB,EACV,CAAC,KAAK,CAAC,EACP,KAAK,CACN,CAAC;IAEF,6CAA6C;IAC7C,IAAI,aAAa,GAA8B,EAAE,CAAC;IAClD,IAAI,CAAC;QACH,aAAa,GAAG,MAAM,QAAQ,CAC5B;;;;;;;;;wDASkD,EAClD,CAAC,KAAK,CAAC,EACP,KAAK,CACN,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACrE,MAAM,aAAa,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;IAE1F,OAAO;QACL,eAAe,EAAE,MAAM;QACvB,OAAO,EAAE;YACP,uBAAuB,EAAE,WAAW;YACpC,oBAAoB,EAAE,MAAM,CAAC,MAAM;YACnC,yBAAyB,EAAE,kBAAkB,CAAC,MAAM;YACpD,kBAAkB,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,GAAG,GAAG;SAC1D;QACD,yBAAyB,EAAE,kBAAkB;QAC7C,cAAc,EAAE,aAAa;KAC9B,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ticket-deep-dive.d.ts","sourceRoot":"","sources":["../../../src/tools/composite/ticket-deep-dive.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ticket-deep-dive.d.ts","sourceRoot":"","sources":["../../../src/tools/composite/ticket-deep-dive.ts"],"names":[],"mappings":"AAGA,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,oBAAoB;;;;;;;;;;;;;;;;;;GAiF7B"}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { queryRLS } from "../../db/gateway-client.js";
|
|
2
|
+
import { getFilters, buildTicketFilter, buildTimeEntriesFilter } from "../../db/filters.js";
|
|
2
3
|
export async function getTicketDeepDive(mspId, params) {
|
|
4
|
+
const filters = await getFilters(mspId);
|
|
5
|
+
const tf = buildTicketFilter(filters, { tableAlias: "tl", includeTechnicianFilter: false });
|
|
6
|
+
const tef = buildTimeEntriesFilter(filters);
|
|
3
7
|
const [ticket, aiSummary, timeEntries, sentiment, budget] = await Promise.all([
|
|
4
|
-
// Core ticket data
|
|
5
|
-
queryRLS(`SELECT ticket_id, company_name, summary, status, priority_name,
|
|
6
|
-
owner_name, board_name, agreement_type,
|
|
7
|
-
entered_date::text, responded_date::text, closed_date::text,
|
|
8
|
-
resolution_minutes, response_minutes, is_closed, is_resolved,
|
|
9
|
-
sla_status
|
|
10
|
-
FROM ticket_lifecycle
|
|
11
|
-
WHERE msp_id = $1 AND ticket_id = $2`, [mspId, params.ticketId], mspId),
|
|
8
|
+
// Core ticket data — validate ticket belongs to allowed board
|
|
9
|
+
queryRLS(`SELECT tl.ticket_id, tl.company_name, tl.summary, tl.status, tl.priority_name,
|
|
10
|
+
tl.owner_name, tl.board_name, tl.agreement_type,
|
|
11
|
+
tl.entered_date::text, tl.responded_date::text, tl.closed_date::text,
|
|
12
|
+
tl.resolution_minutes, tl.response_minutes, tl.is_closed, tl.is_resolved,
|
|
13
|
+
tl.sla_status
|
|
14
|
+
FROM ticket_lifecycle tl
|
|
15
|
+
WHERE tl.msp_id = $1 AND tl.ticket_id = $2 ${tf}`, [mspId, params.ticketId], mspId),
|
|
12
16
|
// AI analysis
|
|
13
17
|
queryRLS(`SELECT problem_statement as problem_summary, ai_summary,
|
|
14
18
|
ticket_classification, root_cause as root_cause_analysis,
|
|
@@ -19,9 +23,9 @@ export async function getTicketDeepDive(mspId, params) {
|
|
|
19
23
|
queryRLS(`SELECT member_name as technician, actual_hours, billable_hours,
|
|
20
24
|
hourly_rate, (actual_hours * COALESCE(hourly_rate, 0))::numeric as cost,
|
|
21
25
|
notes_text as description
|
|
22
|
-
FROM time_entries
|
|
23
|
-
WHERE msp_id = $1 AND ticket_id = $2
|
|
24
|
-
ORDER BY date_worked DESC`, [mspId, params.ticketId], mspId),
|
|
26
|
+
FROM time_entries te
|
|
27
|
+
WHERE te.msp_id = $1 AND te.ticket_id = $2 ${tef}
|
|
28
|
+
ORDER BY te.date_worked DESC`, [mspId, params.ticketId], mspId),
|
|
25
29
|
// Sentiment
|
|
26
30
|
queryRLS(`SELECT AVG(sentiment_score)::numeric as avg_sentiment,
|
|
27
31
|
COUNT(*)::int as note_count
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ticket-deep-dive.js","sourceRoot":"","sources":["../../../src/tools/composite/ticket-deep-dive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"ticket-deep-dive.js","sourceRoot":"","sources":["../../../src/tools/composite/ticket-deep-dive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAM5F,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAa,EACb,MAA4B;IAE5B,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,iBAAiB,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5F,MAAM,GAAG,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAE5C,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,GACvD,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,8DAA8D;QAC9D,QAAQ,CACN;;;;;;sDAM8C,EAAE,EAAE,EAClD,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,KAAK,CACN;QAED,cAAc;QACd,QAAQ,CACN;;;;8CAIsC,EACtC,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,KAAK,CACN;QAED,eAAe;QACf,QAAQ,CACN;;;;sDAI8C,GAAG;sCACnB,EAC9B,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,KAAK,CACN;QAED,YAAY;QACZ,QAAQ,CACN;;;8CAGsC,EACtC,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,KAAK,CACN;QAED,gBAAgB;QAChB,QAAQ,CACN;;;iBAGS,EACT,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,KAAK,CACN;KACF,CAAC,CAAC;IAEL,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,MAAM,CAAC,QAAQ,YAAY,EAAE,CAAC;IAC3E,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QACjB,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI;QACjC,YAAY,EAAE,WAAW;QACzB,WAAW,EAAE,WAAW,CAAC,MAAM,CAC7B,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAE,CAAC,CAAC,YAAuB,IAAI,CAAC,CAAC,EACnD,CAAC,CACF;QACD,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI;QAC/B,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI;KAC1B,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recommendations.d.ts","sourceRoot":"","sources":["../../../src/tools/qbr/recommendations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"recommendations.d.ts","sourceRoot":"","sources":["../../../src/tools/qbr/recommendations.ts"],"names":[],"mappings":"AAIA,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,gBAqGpF"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { queryRLS } from "../../db/gateway-client.js";
|
|
2
2
|
import { chatCompletion } from "../../db/azure-openai.js";
|
|
3
|
+
import { getFilters, buildCompanyExclusionFilter } from "../../db/filters.js";
|
|
3
4
|
export async function qbrRecommendations(mspId, params) {
|
|
5
|
+
const filters = await getFilters(mspId);
|
|
6
|
+
const cf = buildCompanyExclusionFilter(filters, { tableAlias: "bc" });
|
|
4
7
|
// Gather key signals across all areas
|
|
5
8
|
const [health, sla, patterns, billing, techPerf] = await Promise.all([
|
|
6
9
|
queryRLS(`SELECT COUNT(*)::int as total,
|
|
@@ -23,10 +26,10 @@ export async function qbrRecommendations(mspId, params) {
|
|
|
23
26
|
LIMIT 3`, [mspId], mspId),
|
|
24
27
|
queryRLS(`SELECT COUNT(DISTINCT ticket_id)::int as tickets,
|
|
25
28
|
COALESCE(SUM(billable_amount), 0)::numeric as dollars
|
|
26
|
-
FROM agents.billing_classifications
|
|
27
|
-
WHERE msp_id::uuid = $1::uuid
|
|
28
|
-
AND classification = 'out_of_scope' AND billable_amount > 0
|
|
29
|
-
AND resolved_date >= $2::date AND resolved_date <= $3::date`, [mspId, params.fromDate, params.toDate], mspId),
|
|
29
|
+
FROM agents.billing_classifications bc
|
|
30
|
+
WHERE bc.msp_id::uuid = $1::uuid
|
|
31
|
+
AND bc.classification = 'out_of_scope' AND bc.billable_amount > 0
|
|
32
|
+
AND bc.resolved_date >= $2::date AND bc.resolved_date <= $3::date ${cf}`, [mspId, params.fromDate, params.toDate], mspId),
|
|
30
33
|
queryRLS(`SELECT technician_name, AVG(quality_points)::numeric as avg_dq
|
|
31
34
|
FROM analytics.technician_dq_leaderboard_daily
|
|
32
35
|
WHERE msp_id = $1 AND calculation_date >= $2::date AND calculation_date <= $3::date
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recommendations.js","sourceRoot":"","sources":["../../../src/tools/qbr/recommendations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"recommendations.js","sourceRoot":"","sources":["../../../src/tools/qbr/recommendations.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"top-issues.d.ts","sourceRoot":"","sources":["../../../src/tools/qbr/top-issues.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"top-issues.d.ts","sourceRoot":"","sources":["../../../src/tools/qbr/top-issues.ts"],"names":[],"mappings":"AAGA,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe;;;;;GA+CxE"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { queryRLS } from "../../db/gateway-client.js";
|
|
2
|
+
import { getFilters, buildCompanyExclusionFilter } from "../../db/filters.js";
|
|
2
3
|
export async function qbrTopIssues(mspId, params) {
|
|
4
|
+
const filters = await getFilters(mspId);
|
|
5
|
+
const cf = buildCompanyExclusionFilter(filters, { tableAlias: "rc" });
|
|
3
6
|
let patterns = [];
|
|
4
7
|
try {
|
|
5
8
|
patterns = await queryRLS(`SELECT pattern_name, ticket_count, affected_clients, root_cause_category
|
|
@@ -14,12 +17,12 @@ export async function qbrTopIssues(mspId, params) {
|
|
|
14
17
|
}
|
|
15
18
|
let rootCauses = [];
|
|
16
19
|
try {
|
|
17
|
-
rootCauses = await queryRLS(`SELECT root_cause_category as category,
|
|
20
|
+
rootCauses = await queryRLS(`SELECT rc.root_cause_category as category,
|
|
18
21
|
COUNT(*)::int as count
|
|
19
|
-
FROM root_cause_ticket_classifier
|
|
20
|
-
WHERE msp_id = $1
|
|
21
|
-
AND root_cause_category IS NOT NULL
|
|
22
|
-
GROUP BY root_cause_category
|
|
22
|
+
FROM root_cause_ticket_classifier rc
|
|
23
|
+
WHERE rc.msp_id = $1
|
|
24
|
+
AND rc.root_cause_category IS NOT NULL ${cf}
|
|
25
|
+
GROUP BY rc.root_cause_category
|
|
23
26
|
ORDER BY count DESC
|
|
24
27
|
LIMIT 10`, [mspId], mspId);
|
|
25
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"top-issues.js","sourceRoot":"","sources":["../../../src/tools/qbr/top-issues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"top-issues.js","sourceRoot":"","sources":["../../../src/tools/qbr/top-issues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAO9E,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa,EAAE,MAAuB;IACvE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,2BAA2B,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,IAAI,QAAQ,GAA8B,EAAE,CAAC;IAC7C,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,QAAQ,CACvB;;;;;gBAKU,EACV,CAAC,KAAK,CAAC,EACP,KAAK,CACN,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,wEAAwE;IAC1E,CAAC;IAED,IAAI,UAAU,GAA8B,EAAE,CAAC;IAC/C,IAAI,CAAC;QACH,UAAU,GAAG,MAAM,QAAQ,CACzB;;;;kDAI4C,EAAE;;;gBAGpC,EACV,CAAC,KAAK,CAAC,EACP,KAAK,CACN,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;IACtB,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACtE,MAAM,iBAAiB,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/C,GAAG,CAAC;QACJ,UAAU,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;KAC9E,CAAC,CAAC,CAAC;IAEJ,OAAO;QACL,QAAQ;QACR,WAAW,EAAE,iBAAiB;KAC/B,CAAC;AACJ,CAAC"}
|