buildpartner 0.3.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 (109) hide show
  1. package/dist/bin/cli.d.ts +2 -0
  2. package/dist/bin/cli.js +44 -0
  3. package/dist/bin/cli.js.map +1 -0
  4. package/dist/src/api-client.d.ts +18 -0
  5. package/dist/src/api-client.js +74 -0
  6. package/dist/src/api-client.js.map +1 -0
  7. package/dist/src/classifiers/activity-classifier.d.ts +12 -0
  8. package/dist/src/classifiers/activity-classifier.js +300 -0
  9. package/dist/src/classifiers/activity-classifier.js.map +1 -0
  10. package/dist/src/classifiers/path-detector.d.ts +33 -0
  11. package/dist/src/classifiers/path-detector.js +98 -0
  12. package/dist/src/classifiers/path-detector.js.map +1 -0
  13. package/dist/src/commands/log-session.d.ts +10 -0
  14. package/dist/src/commands/log-session.js +162 -0
  15. package/dist/src/commands/log-session.js.map +1 -0
  16. package/dist/src/commands/serve.d.ts +1 -0
  17. package/dist/src/commands/serve.js +5 -0
  18. package/dist/src/commands/serve.js.map +1 -0
  19. package/dist/src/commands/setup.d.ts +1 -0
  20. package/dist/src/commands/setup.js +578 -0
  21. package/dist/src/commands/setup.js.map +1 -0
  22. package/dist/src/constants.d.ts +9 -0
  23. package/dist/src/constants.js +12 -0
  24. package/dist/src/constants.js.map +1 -0
  25. package/dist/src/installer/hook-installer.d.ts +19 -0
  26. package/dist/src/installer/hook-installer.js +114 -0
  27. package/dist/src/installer/hook-installer.js.map +1 -0
  28. package/dist/src/installer/mcp-installer.d.ts +9 -0
  29. package/dist/src/installer/mcp-installer.js +80 -0
  30. package/dist/src/installer/mcp-installer.js.map +1 -0
  31. package/dist/src/installer/skill-installer.d.ts +5 -0
  32. package/dist/src/installer/skill-installer.js +55 -0
  33. package/dist/src/installer/skill-installer.js.map +1 -0
  34. package/dist/src/installer/skill-sync.d.ts +10 -0
  35. package/dist/src/installer/skill-sync.js +76 -0
  36. package/dist/src/installer/skill-sync.js.map +1 -0
  37. package/dist/src/mcp/server.d.ts +3 -0
  38. package/dist/src/mcp/server.js +106 -0
  39. package/dist/src/mcp/server.js.map +1 -0
  40. package/dist/src/mcp/subscription-gate.d.ts +19 -0
  41. package/dist/src/mcp/subscription-gate.js +74 -0
  42. package/dist/src/mcp/subscription-gate.js.map +1 -0
  43. package/dist/src/mcp/tools/ai-profile.d.ts +88 -0
  44. package/dist/src/mcp/tools/ai-profile.js +123 -0
  45. package/dist/src/mcp/tools/ai-profile.js.map +1 -0
  46. package/dist/src/mcp/tools/classify-session.d.ts +31 -0
  47. package/dist/src/mcp/tools/classify-session.js +34 -0
  48. package/dist/src/mcp/tools/classify-session.js.map +1 -0
  49. package/dist/src/mcp/tools/get-knowledge.d.ts +25 -0
  50. package/dist/src/mcp/tools/get-knowledge.js +31 -0
  51. package/dist/src/mcp/tools/get-knowledge.js.map +1 -0
  52. package/dist/src/mcp/tools/get-profile.d.ts +1 -0
  53. package/dist/src/mcp/tools/get-profile.js +77 -0
  54. package/dist/src/mcp/tools/get-profile.js.map +1 -0
  55. package/dist/src/mcp/tools/get-stats.d.ts +58 -0
  56. package/dist/src/mcp/tools/get-stats.js +135 -0
  57. package/dist/src/mcp/tools/get-stats.js.map +1 -0
  58. package/dist/src/mcp/tools/get-suggestions.d.ts +7 -0
  59. package/dist/src/mcp/tools/get-suggestions.js +176 -0
  60. package/dist/src/mcp/tools/get-suggestions.js.map +1 -0
  61. package/dist/src/mcp/tools/get-training.d.ts +48 -0
  62. package/dist/src/mcp/tools/get-training.js +102 -0
  63. package/dist/src/mcp/tools/get-training.js.map +1 -0
  64. package/dist/src/mcp/tools/log-highlight.d.ts +32 -0
  65. package/dist/src/mcp/tools/log-highlight.js +39 -0
  66. package/dist/src/mcp/tools/log-highlight.js.map +1 -0
  67. package/dist/src/mcp/tools/quest.d.ts +78 -0
  68. package/dist/src/mcp/tools/quest.js +72 -0
  69. package/dist/src/mcp/tools/quest.js.map +1 -0
  70. package/dist/src/mcp/tools/web-search.d.ts +15 -0
  71. package/dist/src/mcp/tools/web-search.js +17 -0
  72. package/dist/src/mcp/tools/web-search.js.map +1 -0
  73. package/dist/src/readers/history-reader.d.ts +28 -0
  74. package/dist/src/readers/history-reader.js +83 -0
  75. package/dist/src/readers/history-reader.js.map +1 -0
  76. package/dist/src/readers/session-reader.d.ts +89 -0
  77. package/dist/src/readers/session-reader.js +310 -0
  78. package/dist/src/readers/session-reader.js.map +1 -0
  79. package/dist/src/readers/stats-reader.d.ts +38 -0
  80. package/dist/src/readers/stats-reader.js +125 -0
  81. package/dist/src/readers/stats-reader.js.map +1 -0
  82. package/dist/src/store/local-store.d.ts +72 -0
  83. package/dist/src/store/local-store.js +145 -0
  84. package/dist/src/store/local-store.js.map +1 -0
  85. package/dist/src/store/quest-store.d.ts +77 -0
  86. package/dist/src/store/quest-store.js +309 -0
  87. package/dist/src/store/quest-store.js.map +1 -0
  88. package/dist/src/store/status-store.d.ts +73 -0
  89. package/dist/src/store/status-store.js +372 -0
  90. package/dist/src/store/status-store.js.map +1 -0
  91. package/dist/src/suggestions/rules.d.ts +1 -0
  92. package/dist/src/suggestions/rules.js +2 -0
  93. package/dist/src/suggestions/rules.js.map +1 -0
  94. package/dist/src/suggestions/video-links.d.ts +1 -0
  95. package/dist/src/suggestions/video-links.js +2 -0
  96. package/dist/src/suggestions/video-links.js.map +1 -0
  97. package/package.json +35 -0
  98. package/skills/he-coach/SKILL.md +56 -0
  99. package/skills/he-consult/SKILL.md +43 -0
  100. package/skills/he-enhance-claude-md/SKILL.md +58 -0
  101. package/skills/he-flex-socials/SKILL.md +50 -0
  102. package/skills/he-full-audit/SKILL.md +119 -0
  103. package/skills/he-improve-skill/SKILL.md +111 -0
  104. package/skills/he-interview/SKILL.md +54 -0
  105. package/skills/he-life-story/SKILL.md +64 -0
  106. package/skills/he-log-experience/SKILL.md +68 -0
  107. package/skills/he-open-dashboard/SKILL.md +27 -0
  108. package/skills/he-quest-status/SKILL.md +48 -0
  109. package/skills/he-recap-week/SKILL.md +49 -0
@@ -0,0 +1,88 @@
1
+ import { z } from "zod";
2
+ export declare const getAiProfileSchema: {};
3
+ export declare const updateAiProfileSchema: {
4
+ section: z.ZodEnum<{
5
+ writing_style: "writing_style";
6
+ preferences: "preferences";
7
+ tech_identity: "tech_identity";
8
+ work_patterns: "work_patterns";
9
+ personality: "personality";
10
+ }>;
11
+ data: z.ZodRecord<z.ZodString, z.ZodUnknown>;
12
+ signal: z.ZodOptional<z.ZodString>;
13
+ };
14
+ export declare const batchUpdateAiProfileSchema: {
15
+ updates: z.ZodRecord<z.ZodEnum<{
16
+ writing_style: "writing_style";
17
+ preferences: "preferences";
18
+ tech_identity: "tech_identity";
19
+ work_patterns: "work_patterns";
20
+ personality: "personality";
21
+ }>, z.ZodRecord<z.ZodString, z.ZodUnknown>>;
22
+ signals: z.ZodOptional<z.ZodArray<z.ZodString>>;
23
+ };
24
+ export declare function batchUpdateAiProfile({ updates, signals, }: {
25
+ updates: Record<string, Record<string, unknown>>;
26
+ signals?: string[];
27
+ }): Promise<{
28
+ updated: boolean;
29
+ sections: string[];
30
+ error?: undefined;
31
+ } | {
32
+ error: string;
33
+ updated?: undefined;
34
+ sections?: undefined;
35
+ }>;
36
+ export declare const analyzeHistorySchema: {
37
+ session_count: z.ZodOptional<z.ZodNumber>;
38
+ };
39
+ export declare function getAiProfile(): Promise<{}>;
40
+ export declare function updateAiProfile({ section, data, signal, }: {
41
+ section: string;
42
+ data: Record<string, unknown>;
43
+ signal?: string;
44
+ }): Promise<{
45
+ updated: boolean;
46
+ section: string;
47
+ keys: string[];
48
+ error?: undefined;
49
+ } | {
50
+ error: string;
51
+ updated?: undefined;
52
+ section?: undefined;
53
+ keys?: undefined;
54
+ }>;
55
+ /**
56
+ * Analyze session history to extract profile signals.
57
+ * This is called by the /mp-profile-build skill.
58
+ * Returns structured observations that Claude then saves to the profile.
59
+ */
60
+ export declare function analyzeHistory({ session_count }: {
61
+ session_count?: number;
62
+ }): Promise<{
63
+ error: string;
64
+ analysis?: undefined;
65
+ instructions?: undefined;
66
+ } | {
67
+ analysis: {
68
+ tech_identity: {
69
+ primary_languages: string[];
70
+ frameworks: string[];
71
+ mcp_servers: string[];
72
+ top_tools: {
73
+ name: string;
74
+ count: number;
75
+ }[];
76
+ };
77
+ work_patterns: {
78
+ peak_hour: string;
79
+ peak_day: string;
80
+ avg_session_minutes: number;
81
+ activity_distribution: Record<string, number>;
82
+ total_sessions_analyzed: number;
83
+ };
84
+ session_summaries: string[];
85
+ };
86
+ instructions: string;
87
+ error?: undefined;
88
+ }>;
@@ -0,0 +1,123 @@
1
+ import { z } from "zod";
2
+ import { apiGet, apiPost } from "../../api-client.js";
3
+ import { readAuth } from "../../store/local-store.js";
4
+ export const getAiProfileSchema = {};
5
+ export const updateAiProfileSchema = {
6
+ section: z.enum(["writing_style", "preferences", "tech_identity", "work_patterns", "personality"]).describe("Which section of the profile to update"),
7
+ data: z.record(z.string(), z.unknown()).describe("Key-value pairs to merge into the section"),
8
+ signal: z.string().optional().describe("A raw signal/observation to add to the profile log"),
9
+ };
10
+ export const batchUpdateAiProfileSchema = {
11
+ updates: z.record(z.enum(["writing_style", "preferences", "tech_identity", "work_patterns", "personality"]), z.record(z.string(), z.unknown())).describe("Object with section names as keys and key-value data as values. Updates all sections in one call."),
12
+ signals: z.array(z.string()).optional().describe("Array of raw signal strings to append to the profile log"),
13
+ };
14
+ export async function batchUpdateAiProfile({ updates, signals, }) {
15
+ const payload = { ...updates };
16
+ if (signals && signals.length > 0) {
17
+ payload.raw_signals = signals.map(s => `[${new Date().toISOString().slice(0, 10)}] ${s}`);
18
+ }
19
+ const result = await apiPost("/api/myplayer/profile", payload);
20
+ if (result)
21
+ return { updated: true, sections: Object.keys(updates) };
22
+ return { error: "Could not update profile." };
23
+ }
24
+ export const analyzeHistorySchema = {
25
+ session_count: z.number().optional().describe("Number of recent sessions to analyze (default 20)"),
26
+ };
27
+ export async function getAiProfile() {
28
+ const data = await apiGet("/api/myplayer/profile");
29
+ if (data)
30
+ return data;
31
+ return { error: "Could not fetch profile. Check your connection." };
32
+ }
33
+ export async function updateAiProfile({ section, data, signal, }) {
34
+ const payload = {
35
+ [section]: data,
36
+ };
37
+ if (signal) {
38
+ payload.raw_signals = [`[${new Date().toISOString().slice(0, 10)}] ${signal}`];
39
+ }
40
+ const result = await apiPost("/api/myplayer/profile", payload);
41
+ if (result)
42
+ return { updated: true, section, keys: Object.keys(data) };
43
+ return { error: "Could not update profile." };
44
+ }
45
+ /**
46
+ * Analyze session history to extract profile signals.
47
+ * This is called by the /mp-profile-build skill.
48
+ * Returns structured observations that Claude then saves to the profile.
49
+ */
50
+ export async function analyzeHistory({ session_count }) {
51
+ const limit = session_count || 20;
52
+ // Fetch recent sessions from API
53
+ const dashData = await apiGet(`/api/myplayer/dashboard?username=${readAuth()?.username || ""}`);
54
+ if (!dashData) {
55
+ return { error: "Could not fetch session history." };
56
+ }
57
+ const sessions = dashData.sessions.slice(0, limit);
58
+ // Extract tech identity
59
+ const frameworks = new Set();
60
+ const languages = new Set();
61
+ const tools = Object.entries(dashData.workspace.tools).sort((a, b) => b[1] - a[1]).slice(0, 10);
62
+ const mcpServers = Object.keys(dashData.workspace.mcp_servers);
63
+ for (const s of sessions) {
64
+ const summary = (s.summary || "").toLowerCase();
65
+ if (summary.includes("next.js") || summary.includes("next js"))
66
+ frameworks.add("Next.js");
67
+ if (summary.includes("react"))
68
+ frameworks.add("React");
69
+ if (summary.includes("supabase"))
70
+ frameworks.add("Supabase");
71
+ if (summary.includes("typescript") || summary.includes(".ts"))
72
+ languages.add("TypeScript");
73
+ if (summary.includes("python") || summary.includes(".py"))
74
+ languages.add("Python");
75
+ if (summary.includes("tailwind"))
76
+ frameworks.add("Tailwind CSS");
77
+ if (summary.includes("vercel"))
78
+ frameworks.add("Vercel");
79
+ if (summary.includes("mcp"))
80
+ frameworks.add("MCP SDK");
81
+ }
82
+ // Extract work patterns
83
+ const hourCounts = {};
84
+ const dayCounts = {};
85
+ const dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
86
+ let totalDuration = 0;
87
+ for (const s of sessions) {
88
+ const d = new Date(s.timestamp);
89
+ const hour = d.getHours();
90
+ hourCounts[hour] = (hourCounts[hour] || 0) + 1;
91
+ const day = dayNames[d.getDay()];
92
+ dayCounts[day] = (dayCounts[day] || 0) + 1;
93
+ totalDuration += s.duration_minutes || 0;
94
+ }
95
+ const peakHour = Object.entries(hourCounts).sort((a, b) => b[1] - a[1])[0];
96
+ const peakDay = Object.entries(dayCounts).sort((a, b) => b[1] - a[1])[0];
97
+ const avgDuration = sessions.length > 0 ? Math.round(totalDuration / sessions.length) : 0;
98
+ // Extract session summaries for Claude to analyze writing style and preferences
99
+ const summaries = sessions
100
+ .filter((s) => s.summary && s.summary.length > 10)
101
+ .map((s) => s.summary)
102
+ .slice(0, 15);
103
+ return {
104
+ analysis: {
105
+ tech_identity: {
106
+ primary_languages: [...languages],
107
+ frameworks: [...frameworks],
108
+ mcp_servers: mcpServers,
109
+ top_tools: tools.map(([name, count]) => ({ name, count })),
110
+ },
111
+ work_patterns: {
112
+ peak_hour: peakHour ? `${peakHour[0]}:00` : "unknown",
113
+ peak_day: peakDay ? peakDay[0] : "unknown",
114
+ avg_session_minutes: avgDuration,
115
+ activity_distribution: dashData.distribution,
116
+ total_sessions_analyzed: sessions.length,
117
+ },
118
+ session_summaries: summaries,
119
+ },
120
+ instructions: "Use the session_summaries to infer writing style, communication preferences, and personality traits. Then call update_ai_profile for each section with your observations. Add a raw signal summarizing what you learned.",
121
+ };
122
+ }
123
+ //# sourceMappingURL=ai-profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-profile.js","sourceRoot":"","sources":["../../../../src/mcp/tools/ai-profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ export declare const classifySessionSchema: {
3
+ session_path: z.ZodString;
4
+ };
5
+ export declare function classifySessionTool({ session_path }: {
6
+ session_path: string;
7
+ }): Promise<{
8
+ error: string;
9
+ activity_type?: undefined;
10
+ confidence?: undefined;
11
+ signals?: undefined;
12
+ scores?: undefined;
13
+ tokens?: undefined;
14
+ duration_minutes?: undefined;
15
+ prompts?: undefined;
16
+ summary?: undefined;
17
+ files_touched?: undefined;
18
+ project?: undefined;
19
+ } | {
20
+ activity_type: import("../../classifiers/activity-classifier.js").ActivityType;
21
+ confidence: number;
22
+ signals: string[];
23
+ scores: Record<import("../../classifiers/activity-classifier.js").ActivityType, number>;
24
+ tokens: number;
25
+ duration_minutes: number;
26
+ prompts: number;
27
+ summary: string | null;
28
+ files_touched: string[];
29
+ project: string;
30
+ error?: undefined;
31
+ }>;
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ import { parseSession } from "../../readers/session-reader.js";
3
+ import { classifySession } from "../../classifiers/activity-classifier.js";
4
+ export const classifySessionSchema = {
5
+ session_path: z.string().describe("Absolute path to a session JSONL file"),
6
+ };
7
+ export async function classifySessionTool({ session_path }) {
8
+ const session = parseSession(session_path);
9
+ if (!session) {
10
+ return { error: "Could not parse session file" };
11
+ }
12
+ const result = classifySession(session);
13
+ // Compute duration in minutes
14
+ let durationMinutes = 0;
15
+ if (session.startTime && session.endTime) {
16
+ const ms = new Date(session.endTime).getTime() - new Date(session.startTime).getTime();
17
+ durationMinutes = Math.round(ms / 60000);
18
+ }
19
+ // Estimate tokens from tool call count (rough heuristic: ~1500 tokens per tool call + prompts)
20
+ const estimatedTokens = session.toolCalls.length * 1500 + session.userPromptCount * 2000;
21
+ return {
22
+ activity_type: result.activityType,
23
+ confidence: Math.round(result.confidence * 100),
24
+ signals: result.signals,
25
+ scores: result.scores,
26
+ tokens: estimatedTokens,
27
+ duration_minutes: durationMinutes,
28
+ prompts: session.userPromptCount,
29
+ summary: session.summary,
30
+ files_touched: session.filesTouched,
31
+ project: session.projectPath,
32
+ };
33
+ }
34
+ //# sourceMappingURL=classify-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify-session.js","sourceRoot":"","sources":["../../../../src/mcp/tools/classify-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,0CAA0C,CAAC;AAE3E,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;CAC3E,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,EAAE,YAAY,EAA4B;IAClF,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAC;IACnD,CAAC;IAED,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAExC,8BAA8B;IAC9B,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACzC,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;QACvF,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,+FAA+F;IAC/F,MAAM,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAEzF,OAAO;QACL,aAAa,EAAE,MAAM,CAAC,YAAY;QAClC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,GAAG,GAAG,CAAC;QAC/C,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,eAAe;QACvB,gBAAgB,EAAE,eAAe;QACjC,OAAO,EAAE,OAAO,CAAC,eAAe;QAChC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,aAAa,EAAE,OAAO,CAAC,YAAY;QACnC,OAAO,EAAE,OAAO,CAAC,WAAW;KAC7B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { z } from "zod";
2
+ export declare const getKnowledgeSchema: {
3
+ topic: z.ZodOptional<z.ZodString>;
4
+ query: z.ZodOptional<z.ZodString>;
5
+ };
6
+ export declare function getKnowledge({ topic, query }: {
7
+ topic?: string;
8
+ query?: string;
9
+ }): Promise<{
10
+ topics: {
11
+ key: string;
12
+ title: string;
13
+ }[];
14
+ } | {
15
+ title: string;
16
+ content: string;
17
+ } | {
18
+ results: {
19
+ key: string;
20
+ title: string;
21
+ excerpt: string;
22
+ }[];
23
+ } | {
24
+ error: string;
25
+ }>;
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ import { apiGet } from "../../api-client.js";
3
+ export const getKnowledgeSchema = {
4
+ topic: z.string().optional().describe("Specific topic key (e.g. 'augment-vs-automate', 'mcp-architecture'). Omit to list all topics."),
5
+ query: z.string().optional().describe("Search query to find relevant knowledge across all topics."),
6
+ };
7
+ export async function getKnowledge({ topic, query }) {
8
+ // List topics
9
+ if (!topic && !query) {
10
+ const data = await apiGet("/api/myplayer/knowledge");
11
+ if (data)
12
+ return data;
13
+ return { error: "Could not fetch knowledge base. Check your connection." };
14
+ }
15
+ // Get specific topic
16
+ if (topic) {
17
+ const data = await apiGet(`/api/myplayer/knowledge?topic=${encodeURIComponent(topic)}`);
18
+ if (data)
19
+ return data;
20
+ return { error: `Topic '${topic}' not found.` };
21
+ }
22
+ // Search
23
+ if (query) {
24
+ const data = await apiGet(`/api/myplayer/knowledge?q=${encodeURIComponent(query)}`);
25
+ if (data)
26
+ return data;
27
+ return { error: "Search failed. Check your connection." };
28
+ }
29
+ return { error: "Provide a topic or query." };
30
+ }
31
+ //# sourceMappingURL=get-knowledge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-knowledge.js","sourceRoot":"","sources":["../../../../src/mcp/tools/get-knowledge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+FAA+F,CAAC;IACtI,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4DAA4D,CAAC;CACpG,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EAAE,KAAK,EAAE,KAAK,EAAsC;IACrF,cAAc;IACd,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,MAAM,MAAM,CAA+C,yBAAyB,CAAC,CAAC;QACnG,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO,EAAE,KAAK,EAAE,wDAAwD,EAAE,CAAC;IAC7E,CAAC;IAED,qBAAqB;IACrB,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,IAAI,GAAG,MAAM,MAAM,CAAqC,iCAAiC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5H,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO,EAAE,KAAK,EAAE,UAAU,KAAK,cAAc,EAAE,CAAC;IAClD,CAAC;IAED,SAAS;IACT,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,IAAI,GAAG,MAAM,MAAM,CAAiE,6BAA6B,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACpJ,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO,EAAE,KAAK,EAAE,uCAAuC,EAAE,CAAC;IAC5D,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,2BAA2B,EAAE,CAAC;AAChD,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function getProfile(): Promise<{}>;
@@ -0,0 +1,77 @@
1
+ import { readProfile, readSessions, readHighlights, readAuth } from "../../store/local-store.js";
2
+ import { getStatsSummary } from "../../readers/stats-reader.js";
3
+ import { apiGet } from "../../api-client.js";
4
+ export async function getProfile() {
5
+ const auth = readAuth();
6
+ // Try API first
7
+ if (auth?.username) {
8
+ const apiData = await apiGet(`/api/myplayer/dashboard?username=${auth.username}`);
9
+ if (apiData)
10
+ return apiData;
11
+ }
12
+ // Fallback to local
13
+ const profile = readProfile();
14
+ const sessions = readSessions();
15
+ const highlights = readHighlights();
16
+ const stats = getStatsSummary();
17
+ const recentSessions = sessions.slice(-10).reverse();
18
+ const mcpServerCounts = {};
19
+ const skillCounts = {};
20
+ const topTools = {};
21
+ for (const s of sessions) {
22
+ if (s.mcp_servers_used) {
23
+ for (const server of s.mcp_servers_used) {
24
+ mcpServerCounts[server] = (mcpServerCounts[server] || 0) + 1;
25
+ }
26
+ }
27
+ if (s.skills_invoked) {
28
+ for (const skill of s.skills_invoked) {
29
+ skillCounts[skill] = (skillCounts[skill] || 0) + 1;
30
+ }
31
+ }
32
+ if (s.tool_counts) {
33
+ for (const [tool, count] of Object.entries(s.tool_counts)) {
34
+ topTools[tool] = (topTools[tool] || 0) + count;
35
+ }
36
+ }
37
+ }
38
+ return {
39
+ username: auth?.username ?? null,
40
+ email: auth?.email ?? null,
41
+ profile_url: auth?.profile_url ?? null,
42
+ path: profile?.path ?? "unknown",
43
+ path_scores: profile?.path_scores ?? {},
44
+ streak: {
45
+ current: profile?.streak_current ?? stats?.currentStreak ?? 0,
46
+ best: profile?.streak_best ?? stats?.bestStreak ?? 0,
47
+ },
48
+ totals: {
49
+ sessions: profile?.total_sessions ?? sessions.length,
50
+ tokens: profile?.total_tokens ?? 0,
51
+ highlights: highlights.length,
52
+ active_since: profile?.active_since ?? stats?.firstDate ?? null,
53
+ },
54
+ workspace: profile?.workspace ?? null,
55
+ tooling: {
56
+ mcp_servers: mcpServerCounts,
57
+ skills: skillCounts,
58
+ top_tools: Object.fromEntries(Object.entries(topTools).sort((a, b) => b[1] - a[1]).slice(0, 15)),
59
+ },
60
+ recent_sessions: recentSessions.map((s) => ({
61
+ timestamp: s.timestamp,
62
+ project: s.project,
63
+ activity_type: s.activity_type,
64
+ summary: s.summary,
65
+ tokens: s.tokens,
66
+ duration_minutes: s.duration_minutes,
67
+ })),
68
+ highlights: highlights.slice(-5).reverse().map((h) => ({
69
+ title: h.title,
70
+ description: h.description,
71
+ activity_type: h.activity_type,
72
+ tech_stack: h.tech_stack,
73
+ created_at: h.created_at,
74
+ })),
75
+ };
76
+ }
77
+ //# sourceMappingURL=get-profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-profile.js","sourceRoot":"","sources":["../../../../src/mcp/tools/get-profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import { z } from "zod";
2
+ export declare const getStatsSchema: {
3
+ period: z.ZodEnum<{
4
+ week: "week";
5
+ month: "month";
6
+ all: "all";
7
+ }>;
8
+ };
9
+ export declare function getStats({ period }: {
10
+ period: "week" | "month" | "all";
11
+ }): Promise<{
12
+ period: string;
13
+ sessionCount: number;
14
+ totalTokens: number;
15
+ highlights: {
16
+ title: string;
17
+ created_at: string;
18
+ }[];
19
+ distribution: Record<string, number>;
20
+ dailyBreakdown: Record<string, {
21
+ sessions: number;
22
+ types: string[];
23
+ tokens: number;
24
+ }>;
25
+ streak: {
26
+ current: number;
27
+ best: number;
28
+ };
29
+ fingerprint: string;
30
+ pathScores: {};
31
+ allTime: {
32
+ totalSessions: number;
33
+ totalTokens: number;
34
+ activeSince: null;
35
+ };
36
+ } | {
37
+ period: "week" | "month" | "all";
38
+ sessionCount: number;
39
+ totalTokens: number;
40
+ highlights: import("../../store/local-store.js").HighlightEntry[];
41
+ distribution: Record<string, number>;
42
+ dailyBreakdown: Record<string, {
43
+ sessions: number;
44
+ types: string[];
45
+ tokens: number;
46
+ }>;
47
+ streak: {
48
+ current: number;
49
+ best: number;
50
+ };
51
+ fingerprint: string;
52
+ pathScores: Record<string, number>;
53
+ allTime: {
54
+ totalSessions: number;
55
+ totalTokens: number;
56
+ activeSince: string | null;
57
+ };
58
+ }>;
@@ -0,0 +1,135 @@
1
+ import { z } from "zod";
2
+ import { readAuth } from "../../store/local-store.js";
3
+ import { apiGet } from "../../api-client.js";
4
+ import { readSessions, readHighlights, readProfile } from "../../store/local-store.js";
5
+ import { getStatsSummary, getThisWeekActivity, getActivityInRange } from "../../readers/stats-reader.js";
6
+ function toLocalDate(isoTimestamp) {
7
+ const d = new Date(isoTimestamp);
8
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
9
+ }
10
+ function todayLocal() {
11
+ return toLocalDate(new Date().toISOString());
12
+ }
13
+ export const getStatsSchema = {
14
+ period: z.enum(["week", "month", "all"]).describe("Time period for stats"),
15
+ };
16
+ export async function getStats({ period }) {
17
+ const auth = readAuth();
18
+ // Try API first
19
+ if (auth?.username) {
20
+ const apiData = await apiGet(`/api/myplayer/dashboard?username=${auth.username}`);
21
+ if (apiData) {
22
+ return formatApiStats(apiData, period);
23
+ }
24
+ }
25
+ // Fallback to local
26
+ return getLocalStats(period);
27
+ }
28
+ function formatApiStats(data, period) {
29
+ const now = new Date();
30
+ let sessions = data.sessions;
31
+ if (period === "week") {
32
+ const weekAgo = new Date(now);
33
+ weekAgo.setDate(weekAgo.getDate() - 7);
34
+ sessions = sessions.filter((s) => new Date(s.timestamp) >= weekAgo);
35
+ }
36
+ else if (period === "month") {
37
+ const monthAgo = new Date(now);
38
+ monthAgo.setMonth(monthAgo.getMonth() - 1);
39
+ sessions = sessions.filter((s) => new Date(s.timestamp) >= monthAgo);
40
+ }
41
+ const totalTokens = sessions.reduce((sum, s) => sum + (s.tokens || 0), 0);
42
+ const distribution = {};
43
+ const dailyBreakdown = {};
44
+ for (const s of sessions) {
45
+ distribution[s.activity_type] = (distribution[s.activity_type] || 0) + 1;
46
+ const date = toLocalDate(s.timestamp);
47
+ if (!dailyBreakdown[date])
48
+ dailyBreakdown[date] = { sessions: 0, types: [], tokens: 0 };
49
+ dailyBreakdown[date].sessions++;
50
+ dailyBreakdown[date].types.push(s.activity_type);
51
+ dailyBreakdown[date].tokens += s.tokens || 0;
52
+ }
53
+ return {
54
+ period,
55
+ sessionCount: sessions.length,
56
+ totalTokens,
57
+ highlights: data.highlights || [],
58
+ distribution,
59
+ dailyBreakdown,
60
+ streak: {
61
+ current: data.stats.current_streak,
62
+ best: data.stats.current_streak, // API doesn't track best yet
63
+ },
64
+ fingerprint: "unknown",
65
+ pathScores: {},
66
+ allTime: {
67
+ totalSessions: data.stats.total_sessions,
68
+ totalTokens: data.stats.total_tokens,
69
+ activeSince: null,
70
+ },
71
+ };
72
+ }
73
+ function getLocalStats(period) {
74
+ const statsSummary = getStatsSummary();
75
+ const sessions = readSessions();
76
+ const highlights = readHighlights();
77
+ const profile = readProfile();
78
+ const now = new Date();
79
+ let periodSessions = sessions;
80
+ let periodActivity = statsSummary?.dailyActivity || [];
81
+ if (period === "week") {
82
+ const weekAgo = new Date(now);
83
+ weekAgo.setDate(weekAgo.getDate() - 7);
84
+ const startDateLocal = toLocalDate(weekAgo.toISOString());
85
+ periodSessions = sessions.filter((s) => toLocalDate(s.timestamp) >= startDateLocal);
86
+ periodActivity = getThisWeekActivity();
87
+ }
88
+ else if (period === "month") {
89
+ const monthAgo = new Date(now);
90
+ monthAgo.setMonth(monthAgo.getMonth() - 1);
91
+ const startDateLocal = toLocalDate(monthAgo.toISOString());
92
+ periodSessions = sessions.filter((s) => toLocalDate(s.timestamp) >= startDateLocal);
93
+ periodActivity = getActivityInRange(startDateLocal, todayLocal());
94
+ }
95
+ const totalTokens = periodSessions.reduce((sum, s) => sum + s.tokens, 0);
96
+ const distribution = {};
97
+ const dailyBreakdown = {};
98
+ for (const s of periodSessions) {
99
+ distribution[s.activity_type] = (distribution[s.activity_type] || 0) + 1;
100
+ const date = toLocalDate(s.timestamp);
101
+ if (!dailyBreakdown[date])
102
+ dailyBreakdown[date] = { sessions: 0, types: [], tokens: 0 };
103
+ dailyBreakdown[date].sessions++;
104
+ dailyBreakdown[date].types.push(s.activity_type);
105
+ dailyBreakdown[date].tokens += s.tokens;
106
+ }
107
+ const periodHighlights = period === "all" ? highlights : highlights.filter((h) => {
108
+ const cutoff = new Date(now);
109
+ if (period === "week")
110
+ cutoff.setDate(cutoff.getDate() - 7);
111
+ else
112
+ cutoff.setMonth(cutoff.getMonth() - 1);
113
+ return h.created_at >= cutoff.toISOString();
114
+ });
115
+ return {
116
+ period,
117
+ sessionCount: periodSessions.length,
118
+ totalTokens,
119
+ highlights: periodHighlights,
120
+ distribution,
121
+ dailyBreakdown,
122
+ streak: {
123
+ current: profile?.streak_current ?? statsSummary?.currentStreak ?? 0,
124
+ best: profile?.streak_best ?? statsSummary?.bestStreak ?? 0,
125
+ },
126
+ fingerprint: profile?.path ?? "unknown",
127
+ pathScores: profile?.path_scores ?? {},
128
+ allTime: {
129
+ totalSessions: profile?.total_sessions ?? statsSummary?.totalSessions ?? 0,
130
+ totalTokens: profile?.total_tokens ?? 0,
131
+ activeSince: profile?.active_since ?? statsSummary?.firstDate ?? null,
132
+ },
133
+ };
134
+ }
135
+ //# sourceMappingURL=get-stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-stats.js","sourceRoot":"","sources":["../../../../src/mcp/tools/get-stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ interface Suggestion {
2
+ message: string;
3
+ category: string;
4
+ video?: string;
5
+ }
6
+ export declare function getSuggestions(): Promise<Suggestion[]>;
7
+ export {};