@cliwant/practiq-mcp 0.1.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 (79) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +238 -0
  3. package/dist/bin/practiq-mcp.d.ts +11 -0
  4. package/dist/bin/practiq-mcp.d.ts.map +1 -0
  5. package/dist/bin/practiq-mcp.js +59 -0
  6. package/dist/bin/practiq-mcp.js.map +1 -0
  7. package/dist/index.d.ts +28 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +40 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/server.d.ts +10 -0
  12. package/dist/server.d.ts.map +1 -0
  13. package/dist/server.js +348 -0
  14. package/dist/server.js.map +1 -0
  15. package/dist/store/client-store.d.ts +29 -0
  16. package/dist/store/client-store.d.ts.map +1 -0
  17. package/dist/store/client-store.js +146 -0
  18. package/dist/store/client-store.js.map +1 -0
  19. package/dist/store/deadline-store.d.ts +22 -0
  20. package/dist/store/deadline-store.d.ts.map +1 -0
  21. package/dist/store/deadline-store.js +92 -0
  22. package/dist/store/deadline-store.js.map +1 -0
  23. package/dist/store/interaction-store.d.ts +22 -0
  24. package/dist/store/interaction-store.d.ts.map +1 -0
  25. package/dist/store/interaction-store.js +111 -0
  26. package/dist/store/interaction-store.js.map +1 -0
  27. package/dist/store/types.d.ts +83 -0
  28. package/dist/store/types.d.ts.map +1 -0
  29. package/dist/store/types.js +8 -0
  30. package/dist/store/types.js.map +1 -0
  31. package/dist/tools/add-client.d.ts +24 -0
  32. package/dist/tools/add-client.d.ts.map +1 -0
  33. package/dist/tools/add-client.js +88 -0
  34. package/dist/tools/add-client.js.map +1 -0
  35. package/dist/tools/client-context.d.ts +8 -0
  36. package/dist/tools/client-context.d.ts.map +1 -0
  37. package/dist/tools/client-context.js +104 -0
  38. package/dist/tools/client-context.js.map +1 -0
  39. package/dist/tools/client-health.d.ts +8 -0
  40. package/dist/tools/client-health.d.ts.map +1 -0
  41. package/dist/tools/client-health.js +104 -0
  42. package/dist/tools/client-health.js.map +1 -0
  43. package/dist/tools/deadline-tracker.d.ts +13 -0
  44. package/dist/tools/deadline-tracker.d.ts.map +1 -0
  45. package/dist/tools/deadline-tracker.js +145 -0
  46. package/dist/tools/deadline-tracker.js.map +1 -0
  47. package/dist/tools/handoff-brief.d.ts +10 -0
  48. package/dist/tools/handoff-brief.d.ts.map +1 -0
  49. package/dist/tools/handoff-brief.js +116 -0
  50. package/dist/tools/handoff-brief.js.map +1 -0
  51. package/dist/tools/log-interaction.d.ts +12 -0
  52. package/dist/tools/log-interaction.d.ts.map +1 -0
  53. package/dist/tools/log-interaction.js +48 -0
  54. package/dist/tools/log-interaction.js.map +1 -0
  55. package/dist/tools/morning-briefing.d.ts +8 -0
  56. package/dist/tools/morning-briefing.d.ts.map +1 -0
  57. package/dist/tools/morning-briefing.js +103 -0
  58. package/dist/tools/morning-briefing.js.map +1 -0
  59. package/dist/tools/prepare-meeting.d.ts +9 -0
  60. package/dist/tools/prepare-meeting.d.ts.map +1 -0
  61. package/dist/tools/prepare-meeting.js +121 -0
  62. package/dist/tools/prepare-meeting.js.map +1 -0
  63. package/dist/tools/search-clients.d.ts +8 -0
  64. package/dist/tools/search-clients.d.ts.map +1 -0
  65. package/dist/tools/search-clients.js +45 -0
  66. package/dist/tools/search-clients.js.map +1 -0
  67. package/dist/tools/week-priorities.d.ts +5 -0
  68. package/dist/tools/week-priorities.d.ts.map +1 -0
  69. package/dist/tools/week-priorities.js +98 -0
  70. package/dist/tools/week-priorities.js.map +1 -0
  71. package/dist/utils/date-utils.d.ts +18 -0
  72. package/dist/utils/date-utils.d.ts.map +1 -0
  73. package/dist/utils/date-utils.js +75 -0
  74. package/dist/utils/date-utils.js.map +1 -0
  75. package/dist/utils/scoring.d.ts +18 -0
  76. package/dist/utils/scoring.d.ts.map +1 -0
  77. package/dist/utils/scoring.js +155 -0
  78. package/dist/utils/scoring.js.map +1 -0
  79. package/package.json +58 -0
@@ -0,0 +1,104 @@
1
+ /**
2
+ * client_health — Health score for a specific client or all clients.
3
+ */
4
+ import { getAllClients, getClient } from "../store/client-store.js";
5
+ import { getInteractions, getAllInteractions } from "../store/interaction-store.js";
6
+ import { getDeadlinesForClient, getAllDeadlines } from "../store/deadline-store.js";
7
+ import { computeHealth } from "../utils/scoring.js";
8
+ export async function clientHealthTool(input) {
9
+ // Single client mode
10
+ if (input.client_name) {
11
+ const client = await getClient(input.client_name);
12
+ if (!client) {
13
+ return `Client not found: "${input.client_name}". Use search_clients to find the correct name.`;
14
+ }
15
+ const interactions = await getInteractions(client.slug);
16
+ const deadlines = await getDeadlinesForClient(client.slug);
17
+ const health = computeHealth(client, interactions, deadlines);
18
+ const sections = [];
19
+ sections.push(`HEALTH REPORT: ${client.name}`);
20
+ sections.push("=".repeat(50));
21
+ sections.push("");
22
+ sections.push(`Overall Score: ${health.score}/100 (${health.band})`);
23
+ sections.push("");
24
+ sections.push("DIMENSIONS:");
25
+ sections.push(` Interaction Recency: ${health.dimensions.interactionRecency}/100`);
26
+ sections.push(` How recently was the last interaction?`);
27
+ sections.push(` Deadline Status: ${health.dimensions.deadlineStatus}/100`);
28
+ sections.push(` Are deadlines on track?`);
29
+ sections.push(` Engagement Depth: ${health.dimensions.engagementDepth}/100`);
30
+ sections.push(` How many interactions total?`);
31
+ sections.push(` Risk Signals: ${health.dimensions.riskSignals}/100`);
32
+ sections.push(` Any negative indicators in notes?`);
33
+ sections.push("");
34
+ sections.push(`ASSESSMENT: ${health.summary}`);
35
+ sections.push("");
36
+ sections.push("SCORING WEIGHTS: Recency 30%, Deadlines 30%, Risk 25%, Depth 15%");
37
+ return sections.join("\n");
38
+ }
39
+ // All clients mode
40
+ const clients = await getAllClients();
41
+ if (clients.length === 0) {
42
+ return "No clients found. Use the add_client tool to add your first client.";
43
+ }
44
+ const allInteractions = await getAllInteractions();
45
+ const allDeadlines = await getAllDeadlines();
46
+ const results = clients.map((client) => {
47
+ const cInteractions = allInteractions.filter((i) => i.clientSlug === client.slug);
48
+ const cDeadlines = allDeadlines.filter((d) => d.clientSlug === client.slug);
49
+ return computeHealth(client, cInteractions, cDeadlines);
50
+ });
51
+ // Sort: worst health first
52
+ results.sort((a, b) => a.score - b.score);
53
+ const byBand = {
54
+ Critical: results.filter((r) => r.band === "Critical"),
55
+ "At Risk": results.filter((r) => r.band === "At Risk"),
56
+ Watch: results.filter((r) => r.band === "Watch"),
57
+ Healthy: results.filter((r) => r.band === "Healthy"),
58
+ };
59
+ const sections = [];
60
+ sections.push("PRACTICE HEALTH DASHBOARD");
61
+ sections.push("=".repeat(50));
62
+ sections.push("");
63
+ sections.push(`${clients.length} clients | ` +
64
+ `${byBand.Healthy.length} Healthy | ` +
65
+ `${byBand.Watch.length} Watch | ` +
66
+ `${byBand["At Risk"].length} At Risk | ` +
67
+ `${byBand.Critical.length} Critical`);
68
+ sections.push("");
69
+ if (byBand.Critical.length > 0) {
70
+ sections.push("CRITICAL:");
71
+ for (const r of byBand.Critical) {
72
+ sections.push(` ${r.clientName}: ${r.score}/100 — ${r.summary}`);
73
+ }
74
+ sections.push("");
75
+ }
76
+ if (byBand["At Risk"].length > 0) {
77
+ sections.push("AT RISK:");
78
+ for (const r of byBand["At Risk"]) {
79
+ sections.push(` ${r.clientName}: ${r.score}/100 — ${r.summary}`);
80
+ }
81
+ sections.push("");
82
+ }
83
+ if (byBand.Watch.length > 0) {
84
+ sections.push("WATCH:");
85
+ for (const r of byBand.Watch) {
86
+ sections.push(` ${r.clientName}: ${r.score}/100`);
87
+ }
88
+ sections.push("");
89
+ }
90
+ if (byBand.Healthy.length > 0) {
91
+ sections.push(`HEALTHY (${byBand.Healthy.length} clients):`);
92
+ for (const r of byBand.Healthy.slice(0, 10)) {
93
+ sections.push(` ${r.clientName}: ${r.score}/100`);
94
+ }
95
+ if (byBand.Healthy.length > 10) {
96
+ sections.push(` ... and ${byBand.Healthy.length - 10} more`);
97
+ }
98
+ sections.push("");
99
+ }
100
+ const avgScore = Math.round(results.reduce((sum, r) => sum + r.score, 0) / results.length);
101
+ sections.push(`Practice average health: ${avgScore}/100`);
102
+ return sections.join("\n");
103
+ }
104
+ //# sourceMappingURL=client-health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-health.js","sourceRoot":"","sources":["../../src/tools/client-health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * deadline_tracker — Track and manage deadlines across clients.
3
+ */
4
+ export interface DeadlineTrackerInput {
5
+ action: string;
6
+ client_name?: string;
7
+ description?: string;
8
+ due_date?: string;
9
+ priority?: string;
10
+ deadline_id?: string;
11
+ }
12
+ export declare function deadlineTracker(input: DeadlineTrackerInput): Promise<string>;
13
+ //# sourceMappingURL=deadline-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deadline-tracker.d.ts","sourceRoot":"","sources":["../../src/tools/deadline-tracker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAalF"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * deadline_tracker — Track and manage deadlines across clients.
3
+ */
4
+ import { getClient } from "../store/client-store.js";
5
+ import { getDeadlinesForClient, getActiveDeadlines, getOverdueDeadlines, getUpcomingDeadlines, addDeadline, completeDeadline, } from "../store/deadline-store.js";
6
+ import { formatDueRelative } from "../utils/date-utils.js";
7
+ export async function deadlineTracker(input) {
8
+ const action = input.action.toLowerCase();
9
+ switch (action) {
10
+ case "list":
11
+ return listDeadlines(input.client_name);
12
+ case "add":
13
+ return addDeadlineAction(input);
14
+ case "complete":
15
+ return completeDeadlineAction(input);
16
+ default:
17
+ return `Unknown action: "${input.action}". Must be one of: list, add, complete`;
18
+ }
19
+ }
20
+ async function listDeadlines(clientName) {
21
+ const sections = [];
22
+ if (clientName) {
23
+ const client = await getClient(clientName);
24
+ if (!client) {
25
+ return `Client not found: "${clientName}".`;
26
+ }
27
+ const deadlines = await getDeadlinesForClient(client.slug);
28
+ sections.push(`DEADLINES: ${client.name}`);
29
+ sections.push("=".repeat(50));
30
+ const active = deadlines.filter((d) => !d.completed);
31
+ const completed = deadlines.filter((d) => d.completed);
32
+ if (active.length > 0) {
33
+ sections.push("");
34
+ sections.push("ACTIVE:");
35
+ for (const d of active) {
36
+ const overdue = new Date(d.dueDate).getTime() < Date.now() ? " [OVERDUE]" : "";
37
+ sections.push(` [${d.priority.toUpperCase()}] ${d.description} — ${formatDueRelative(d.dueDate)}${overdue}`);
38
+ sections.push(` ID: ${d.id}`);
39
+ }
40
+ }
41
+ if (completed.length > 0) {
42
+ sections.push("");
43
+ sections.push(`COMPLETED (${completed.length}):`);
44
+ for (const d of completed.slice(0, 5)) {
45
+ sections.push(` ${d.description} — completed ${d.completedAt?.slice(0, 10) ?? "unknown"}`);
46
+ }
47
+ }
48
+ if (active.length === 0 && completed.length === 0) {
49
+ sections.push("");
50
+ sections.push("No deadlines found for this client.");
51
+ }
52
+ return sections.join("\n");
53
+ }
54
+ // All clients overview
55
+ const overdue = await getOverdueDeadlines();
56
+ const upcoming = await getUpcomingDeadlines(14);
57
+ const active = await getActiveDeadlines();
58
+ sections.push("DEADLINE TRACKER — ALL CLIENTS");
59
+ sections.push("=".repeat(50));
60
+ sections.push("");
61
+ if (overdue.length > 0) {
62
+ sections.push(`OVERDUE (${overdue.length}):`);
63
+ for (const d of overdue) {
64
+ sections.push(` [${d.priority.toUpperCase()}] ${d.clientName}: ${d.description} — ${formatDueRelative(d.dueDate)}`);
65
+ sections.push(` ID: ${d.id}`);
66
+ }
67
+ sections.push("");
68
+ }
69
+ if (upcoming.length > 0) {
70
+ sections.push(`UPCOMING (next 14 days, ${upcoming.length}):`);
71
+ for (const d of upcoming) {
72
+ sections.push(` [${d.priority.toUpperCase()}] ${d.clientName}: ${d.description} — ${formatDueRelative(d.dueDate)}`);
73
+ sections.push(` ID: ${d.id}`);
74
+ }
75
+ sections.push("");
76
+ }
77
+ const futureCount = active.length - overdue.length - upcoming.length;
78
+ if (futureCount > 0) {
79
+ sections.push(`FUTURE (beyond 14 days): ${futureCount} deadline${futureCount !== 1 ? "s" : ""}`);
80
+ sections.push("");
81
+ }
82
+ sections.push(`Summary: ${active.length} active, ${overdue.length} overdue, ${upcoming.length} due within 14 days`);
83
+ return sections.join("\n");
84
+ }
85
+ async function addDeadlineAction(input) {
86
+ if (!input.client_name) {
87
+ return 'Missing required field: "client_name"';
88
+ }
89
+ if (!input.description) {
90
+ return 'Missing required field: "description"';
91
+ }
92
+ if (!input.due_date) {
93
+ return 'Missing required field: "due_date" (format: YYYY-MM-DD)';
94
+ }
95
+ const client = await getClient(input.client_name);
96
+ if (!client) {
97
+ return `Client not found: "${input.client_name}".`;
98
+ }
99
+ const validPriorities = ["low", "medium", "high", "critical"];
100
+ const priority = (input.priority?.toLowerCase() ?? "medium");
101
+ if (!validPriorities.includes(priority)) {
102
+ return `Invalid priority: "${input.priority}". Must be one of: ${validPriorities.join(", ")}`;
103
+ }
104
+ try {
105
+ const deadline = await addDeadline({
106
+ clientSlug: client.slug,
107
+ clientName: client.name,
108
+ description: input.description,
109
+ dueDate: input.due_date,
110
+ priority,
111
+ });
112
+ return [
113
+ "Deadline added successfully.",
114
+ "",
115
+ ` Client: ${client.name}`,
116
+ ` Description: ${deadline.description}`,
117
+ ` Due: ${deadline.dueDate} (${formatDueRelative(deadline.dueDate)})`,
118
+ ` Priority: ${deadline.priority}`,
119
+ ` ID: ${deadline.id}`,
120
+ ].join("\n");
121
+ }
122
+ catch (err) {
123
+ return `Error adding deadline: ${err instanceof Error ? err.message : String(err)}`;
124
+ }
125
+ }
126
+ async function completeDeadlineAction(input) {
127
+ if (!input.deadline_id) {
128
+ return 'Missing required field: "deadline_id". Use action "list" to find deadline IDs.';
129
+ }
130
+ try {
131
+ const deadline = await completeDeadline(input.deadline_id);
132
+ return [
133
+ "Deadline marked as complete.",
134
+ "",
135
+ ` Client: ${deadline.clientName}`,
136
+ ` Description: ${deadline.description}`,
137
+ ` Was due: ${deadline.dueDate}`,
138
+ ` Completed: ${deadline.completedAt?.slice(0, 10) ?? "now"}`,
139
+ ].join("\n");
140
+ }
141
+ catch (err) {
142
+ return `Error: ${err instanceof Error ? err.message : String(err)}`;
143
+ }
144
+ }
145
+ //# sourceMappingURL=deadline-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deadline-tracker.js","sourceRoot":"","sources":["../../src/tools/deadline-tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * handoff_brief — Generate a handoff document for transitioning a client.
3
+ */
4
+ export interface HandoffBriefInput {
5
+ client_name: string;
6
+ outgoing_person: string;
7
+ incoming_person: string;
8
+ }
9
+ export declare function handoffBrief(input: HandoffBriefInput): Promise<string>;
10
+ //# sourceMappingURL=handoff-brief.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoff-brief.d.ts","sourceRoot":"","sources":["../../src/tools/handoff-brief.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6G5E"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * handoff_brief — Generate a handoff document for transitioning a client.
3
+ */
4
+ import { getClient } from "../store/client-store.js";
5
+ import { getInteractions } from "../store/interaction-store.js";
6
+ import { getDeadlinesForClient } from "../store/deadline-store.js";
7
+ import { computeHealth } from "../utils/scoring.js";
8
+ import { today } from "../utils/date-utils.js";
9
+ export async function handoffBrief(input) {
10
+ const client = await getClient(input.client_name);
11
+ if (!client) {
12
+ return `Client not found: "${input.client_name}". Use search_clients to find the correct name.`;
13
+ }
14
+ const interactions = await getInteractions(client.slug);
15
+ const deadlines = await getDeadlinesForClient(client.slug);
16
+ const health = computeHealth(client, interactions, deadlines);
17
+ const activeDeadlines = deadlines.filter((d) => !d.completed);
18
+ const sections = [];
19
+ sections.push("CLIENT HANDOFF BRIEF");
20
+ sections.push("=".repeat(50));
21
+ sections.push(`Client: ${client.name}`);
22
+ sections.push(`Date: ${today()}`);
23
+ sections.push(`Outgoing: ${input.outgoing_person}`);
24
+ sections.push(`Incoming: ${input.incoming_person}`);
25
+ sections.push("");
26
+ // 1. Client overview
27
+ sections.push("1. CLIENT OVERVIEW");
28
+ sections.push("-".repeat(30));
29
+ sections.push(` Name: ${client.name}`);
30
+ sections.push(` Vertical: ${client.vertical}`);
31
+ sections.push(` Status: ${client.status}`);
32
+ sections.push(` Engagement: ${client.engagement.type} since ${client.engagement.startDate}`);
33
+ if (client.engagement.value) {
34
+ sections.push(` Monthly value: $${client.engagement.value.toLocaleString()}`);
35
+ }
36
+ if (client.engagement.scope) {
37
+ sections.push(` Scope: ${client.engagement.scope}`);
38
+ }
39
+ sections.push(` Health: ${health.score}/100 (${health.band})`);
40
+ sections.push(` Tags: ${client.tags.length > 0 ? client.tags.join(", ") : "none"}`);
41
+ sections.push("");
42
+ // 2. Key contacts
43
+ sections.push("2. KEY CONTACTS");
44
+ sections.push("-".repeat(30));
45
+ if (client.contacts.length > 0) {
46
+ for (const c of client.contacts) {
47
+ const primary = c.isPrimary ? " [PRIMARY]" : "";
48
+ sections.push(` ${c.name} — ${c.role}${primary}`);
49
+ if (c.email)
50
+ sections.push(` Email: ${c.email}`);
51
+ if (c.phone)
52
+ sections.push(` Phone: ${c.phone}`);
53
+ if (c.notes)
54
+ sections.push(` Relationship notes: ${c.notes}`);
55
+ }
56
+ }
57
+ else {
58
+ sections.push(" No contacts recorded.");
59
+ }
60
+ sections.push("");
61
+ // 3. Active deadlines & open items
62
+ sections.push("3. ACTIVE DEADLINES & OPEN ITEMS");
63
+ sections.push("-".repeat(30));
64
+ if (activeDeadlines.length > 0) {
65
+ for (const d of activeDeadlines) {
66
+ const overdue = new Date(d.dueDate).getTime() < Date.now() ? " [OVERDUE]" : "";
67
+ sections.push(` [${d.priority.toUpperCase()}] ${d.description} — due ${d.dueDate}${overdue}`);
68
+ }
69
+ }
70
+ else {
71
+ sections.push(" No active deadlines.");
72
+ }
73
+ sections.push("");
74
+ // 4. Full interaction history
75
+ sections.push(`4. INTERACTION HISTORY (${interactions.length} total)`);
76
+ sections.push("-".repeat(30));
77
+ if (interactions.length > 0) {
78
+ for (const i of interactions) {
79
+ sections.push(` [${i.date}] ${i.type.toUpperCase()}`);
80
+ sections.push(` ${i.summary}`);
81
+ if (i.actionItems.length > 0) {
82
+ for (const item of i.actionItems) {
83
+ sections.push(` -> ${item}`);
84
+ }
85
+ }
86
+ }
87
+ }
88
+ else {
89
+ sections.push(" No interactions recorded.");
90
+ }
91
+ sections.push("");
92
+ // 5. Client notes
93
+ sections.push("5. CLIENT NOTES");
94
+ sections.push("-".repeat(30));
95
+ if (client.notes) {
96
+ sections.push(client.notes);
97
+ }
98
+ else {
99
+ sections.push(" No notes recorded.");
100
+ }
101
+ sections.push("");
102
+ // 6. Handoff checklist
103
+ sections.push("6. HANDOFF CHECKLIST");
104
+ sections.push("-".repeat(30));
105
+ sections.push(` [ ] ${input.incoming_person} has reviewed this brief`);
106
+ sections.push(` [ ] Introduction email sent to client contacts`);
107
+ sections.push(` [ ] Access to client files/systems transferred`);
108
+ sections.push(` [ ] Active deadlines confirmed and assigned`);
109
+ sections.push(` [ ] Open action items reviewed`);
110
+ sections.push(` [ ] First touch scheduled with client`);
111
+ if (health.band === "At Risk" || health.band === "Critical") {
112
+ sections.push(` [ ] PRIORITY: Address health concerns (currently ${health.band})`);
113
+ }
114
+ return sections.join("\n");
115
+ }
116
+ //# sourceMappingURL=handoff-brief.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoff-brief.js","sourceRoot":"","sources":["../../src/tools/handoff-brief.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * log_interaction — Log an interaction (meeting, email, call, note) with a client.
3
+ */
4
+ export interface LogInteractionToolInput {
5
+ client_name: string;
6
+ type: string;
7
+ summary: string;
8
+ action_items?: string[];
9
+ date?: string;
10
+ }
11
+ export declare function logInteractionTool(input: LogInteractionToolInput): Promise<string>;
12
+ //# sourceMappingURL=log-interaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-interaction.d.ts","sourceRoot":"","sources":["../../src/tools/log-interaction.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0CxF"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * log_interaction — Log an interaction (meeting, email, call, note) with a client.
3
+ */
4
+ import { getClient } from "../store/client-store.js";
5
+ import { logInteraction } from "../store/interaction-store.js";
6
+ const VALID_TYPES = ["meeting", "email", "call", "note"];
7
+ export async function logInteractionTool(input) {
8
+ // Validate type
9
+ const interactionType = input.type.toLowerCase();
10
+ if (!VALID_TYPES.includes(interactionType)) {
11
+ return `Invalid interaction type: "${input.type}". Must be one of: ${VALID_TYPES.join(", ")}`;
12
+ }
13
+ // Find client
14
+ const client = await getClient(input.client_name);
15
+ if (!client) {
16
+ return `Client not found: "${input.client_name}". Use search_clients to find the correct name.`;
17
+ }
18
+ const logInput = {
19
+ clientSlug: client.slug,
20
+ type: interactionType,
21
+ summary: input.summary,
22
+ actionItems: input.action_items,
23
+ date: input.date,
24
+ };
25
+ try {
26
+ const interaction = await logInteraction(logInput);
27
+ const lines = [
28
+ `Interaction logged for ${client.name}.`,
29
+ "",
30
+ ` Type: ${interaction.type}`,
31
+ ` Date: ${interaction.date}`,
32
+ ` Summary: ${interaction.summary}`,
33
+ ];
34
+ if (interaction.actionItems.length > 0) {
35
+ lines.push(" Action items:");
36
+ for (const item of interaction.actionItems) {
37
+ lines.push(` - ${item}`);
38
+ }
39
+ }
40
+ lines.push("");
41
+ lines.push(`Logged to: ~/.practiq/interactions/${client.slug}.jsonl`);
42
+ return lines.join("\n");
43
+ }
44
+ catch (err) {
45
+ return `Error logging interaction: ${err instanceof Error ? err.message : String(err)}`;
46
+ }
47
+ }
48
+ //# sourceMappingURL=log-interaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-interaction.js","sourceRoot":"","sources":["../../src/tools/log-interaction.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAW,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAA4B,MAAM,+BAA+B,CAAC;AAWzF,MAAM,WAAW,GAAsB,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE5E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAA8B;IACrE,gBAAgB;IAChB,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,EAAqB,CAAC;IACpE,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QAC3C,OAAO,8BAA8B,KAAK,CAAC,IAAI,sBAAsB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAChG,CAAC;IAED,cAAc;IACd,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAClD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,sBAAsB,KAAK,CAAC,WAAW,iDAAiD,CAAC;IAClG,CAAC;IAED,MAAM,QAAQ,GAAwB;QACpC,UAAU,EAAE,MAAM,CAAC,IAAI;QACvB,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,WAAW,EAAE,KAAK,CAAC,YAAY;QAC/B,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG;YACZ,0BAA0B,MAAM,CAAC,IAAI,GAAG;YACxC,EAAE;YACF,WAAW,WAAW,CAAC,IAAI,EAAE;YAC7B,WAAW,WAAW,CAAC,IAAI,EAAE;YAC7B,cAAc,WAAW,CAAC,OAAO,EAAE;SACpC,CAAC;QACF,IAAI,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC9B,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC;gBAC3C,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,sCAAsC,MAAM,CAAC,IAAI,QAAQ,CAAC,CAAC;QACtE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,8BAA8B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IAC1F,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * morning_briefing — Generate a prioritized daily briefing across all clients.
3
+ */
4
+ export interface MorningBriefingInput {
5
+ vertical?: string;
6
+ }
7
+ export declare function morningBriefing(input: MorningBriefingInput): Promise<string>;
8
+ //# sourceMappingURL=morning-briefing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"morning-briefing.d.ts","sourceRoot":"","sources":["../../src/tools/morning-briefing.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiHlF"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * morning_briefing — Generate a prioritized daily briefing across all clients.
3
+ */
4
+ import { getAllClients } from "../store/client-store.js";
5
+ import { getAllInteractions } from "../store/interaction-store.js";
6
+ import { getOverdueDeadlines, getUpcomingDeadlines, getAllDeadlines, } from "../store/deadline-store.js";
7
+ import { computeHealth } from "../utils/scoring.js";
8
+ import { today, formatRelative, formatDueRelative } from "../utils/date-utils.js";
9
+ export async function morningBriefing(input) {
10
+ let clients = await getAllClients();
11
+ const verticalFilter = input.vertical;
12
+ if (verticalFilter) {
13
+ clients = clients.filter((c) => c.vertical === verticalFilter);
14
+ }
15
+ if (clients.length === 0) {
16
+ return "No clients found" + (verticalFilter ? ` for vertical "${verticalFilter}"` : "") +
17
+ ". Use the add_client tool to add your first client.";
18
+ }
19
+ const allInteractions = await getAllInteractions();
20
+ const allDeadlines = await getAllDeadlines();
21
+ const overdue = await getOverdueDeadlines();
22
+ const upcoming = await getUpcomingDeadlines(7);
23
+ const sections = [];
24
+ sections.push(`PRACTIQ MORNING BRIEFING — ${today()}`);
25
+ sections.push(`${"=".repeat(50)}`);
26
+ sections.push(`Practice: ${clients.length} client${clients.length === 1 ? "" : "s"}` +
27
+ (verticalFilter ? ` (${verticalFilter})` : ""));
28
+ sections.push("");
29
+ // OVERDUE DEADLINES
30
+ if (overdue.length > 0) {
31
+ sections.push("OVERDUE (requires immediate attention):");
32
+ for (const d of overdue) {
33
+ sections.push(` - ${d.clientName}: ${d.description} (${formatDueRelative(d.dueDate)})`);
34
+ }
35
+ sections.push("");
36
+ }
37
+ // UPCOMING DEADLINES (next 7 days)
38
+ if (upcoming.length > 0) {
39
+ sections.push("THIS WEEK:");
40
+ for (const d of upcoming) {
41
+ sections.push(` - ${d.clientName}: ${d.description} (${formatDueRelative(d.dueDate)})`);
42
+ }
43
+ sections.push("");
44
+ }
45
+ // STALE CLIENTS (no interaction in 30+ days)
46
+ const staleClients = clients.filter((c) => {
47
+ if (!c.lastInteraction)
48
+ return true;
49
+ const days = Math.floor((Date.now() - new Date(c.lastInteraction).getTime()) / (1000 * 60 * 60 * 24));
50
+ return days > 30;
51
+ });
52
+ if (staleClients.length > 0) {
53
+ sections.push("NEEDS ATTENTION (no contact in 30+ days):");
54
+ for (const c of staleClients.slice(0, 10)) {
55
+ const lastTouch = c.lastInteraction
56
+ ? formatRelative(c.lastInteraction)
57
+ : "never contacted";
58
+ sections.push(` - ${c.name} (${c.vertical}): last touch ${lastTouch}`);
59
+ }
60
+ if (staleClients.length > 10) {
61
+ sections.push(` ... and ${staleClients.length - 10} more`);
62
+ }
63
+ sections.push("");
64
+ }
65
+ // RECENT INTERACTIONS (last 3 days)
66
+ const recentInteractions = allInteractions.filter((i) => {
67
+ const days = Math.floor((Date.now() - new Date(i.date).getTime()) / (1000 * 60 * 60 * 24));
68
+ return days <= 3;
69
+ });
70
+ if (recentInteractions.length > 0) {
71
+ sections.push("RECENT ACTIVITY (last 3 days):");
72
+ for (const i of recentInteractions.slice(0, 8)) {
73
+ sections.push(` - [${i.type}] ${i.clientSlug}: ${i.summary.slice(0, 80)}`);
74
+ }
75
+ sections.push("");
76
+ }
77
+ // AT-RISK CLIENTS
78
+ const healthResults = [];
79
+ for (const client of clients) {
80
+ const cInteractions = allInteractions.filter((i) => i.clientSlug === client.slug);
81
+ const cDeadlines = allDeadlines.filter((d) => d.clientSlug === client.slug);
82
+ healthResults.push(computeHealth(client, cInteractions, cDeadlines));
83
+ }
84
+ const atRisk = healthResults.filter((h) => h.band === "Critical" || h.band === "At Risk");
85
+ if (atRisk.length > 0) {
86
+ sections.push("AT-RISK CLIENTS:");
87
+ for (const h of atRisk) {
88
+ sections.push(` - ${h.clientName}: score ${h.score}/100 (${h.band}) — ${h.summary}`);
89
+ }
90
+ sections.push("");
91
+ }
92
+ // SUMMARY STATS
93
+ const activeClients = clients.filter((c) => c.status === "active").length;
94
+ const totalDeadlines = allDeadlines.filter((d) => !d.completed).length;
95
+ sections.push("QUICK STATS:");
96
+ sections.push(` Active clients: ${activeClients}`);
97
+ sections.push(` Open deadlines: ${totalDeadlines}`);
98
+ sections.push(` Overdue: ${overdue.length}`);
99
+ sections.push(` Due this week: ${upcoming.length}`);
100
+ sections.push(` At risk: ${atRisk.length}`);
101
+ return sections.join("\n");
102
+ }
103
+ //# sourceMappingURL=morning-briefing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"morning-briefing.js","sourceRoot":"","sources":["../../src/tools/morning-briefing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * prepare_meeting — Pre-meeting context bundle for a client.
3
+ */
4
+ export interface PrepareMeetingInput {
5
+ client_name: string;
6
+ meeting_purpose?: string;
7
+ }
8
+ export declare function prepareMeeting(input: PrepareMeetingInput): Promise<string>;
9
+ //# sourceMappingURL=prepare-meeting.d.ts.map