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,114 @@
1
+ import { readFileSync, writeFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ import { homedir } from "os";
4
+ const SETTINGS_PATH = join(homedir(), ".claude", "settings.json");
5
+ const MYPLAYER_HOOK_COMMAND = "npx buildpartner log-session";
6
+ /**
7
+ * Merge the MyPlayer Stop hook into ~/.claude/settings.json.
8
+ * Uses the correct Claude Code hook schema:
9
+ * hooks.Stop[].hooks[].{type, command, timeout}
10
+ * Preserves all existing hooks and settings.
11
+ */
12
+ export function installHook() {
13
+ let settings = {};
14
+ if (existsSync(SETTINGS_PATH)) {
15
+ try {
16
+ settings = JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
17
+ }
18
+ catch {
19
+ settings = {};
20
+ }
21
+ }
22
+ // Ensure hooks object exists
23
+ if (!settings.hooks || typeof settings.hooks !== "object") {
24
+ settings.hooks = {};
25
+ }
26
+ const hooks = settings.hooks;
27
+ // Ensure Stop array exists
28
+ if (!Array.isArray(hooks.Stop)) {
29
+ hooks.Stop = [];
30
+ }
31
+ // Check if our hook already exists anywhere in the Stop array
32
+ const exists = hooks.Stop.some((entry) => {
33
+ if (typeof entry !== "object" || entry === null)
34
+ return false;
35
+ const innerHooks = entry.hooks;
36
+ if (!Array.isArray(innerHooks))
37
+ return false;
38
+ return innerHooks.some((h) => typeof h === "object" &&
39
+ h !== null &&
40
+ h.command === MYPLAYER_HOOK_COMMAND);
41
+ });
42
+ if (exists) {
43
+ return { installed: false, alreadyExists: true };
44
+ }
45
+ // Also clean up any old-format "stop" (lowercase) entries we may have written
46
+ if (hooks.stop) {
47
+ delete hooks.stop;
48
+ }
49
+ hooks.Stop.push({
50
+ hooks: [
51
+ {
52
+ type: "command",
53
+ command: MYPLAYER_HOOK_COMMAND,
54
+ timeout: 5,
55
+ },
56
+ ],
57
+ });
58
+ writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + "\n");
59
+ return { installed: true, alreadyExists: false };
60
+ }
61
+ /**
62
+ * Add mcp__myplayer__* to the allow list in ~/.claude/settings.json
63
+ * so users don't get prompted for every MCP tool call.
64
+ */
65
+ export function installPermissions() {
66
+ let settings = {};
67
+ if (existsSync(SETTINGS_PATH)) {
68
+ try {
69
+ settings = JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
70
+ }
71
+ catch {
72
+ settings = {};
73
+ }
74
+ }
75
+ if (!settings.permissions || typeof settings.permissions !== "object") {
76
+ settings.permissions = {};
77
+ }
78
+ const permissions = settings.permissions;
79
+ if (!Array.isArray(permissions.allow)) {
80
+ permissions.allow = [];
81
+ }
82
+ const allowList = permissions.allow;
83
+ const myplayerPermission = "mcp__myplayer__*";
84
+ if (allowList.includes(myplayerPermission)) {
85
+ return { installed: false, alreadyExists: true };
86
+ }
87
+ allowList.push(myplayerPermission);
88
+ writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + "\n");
89
+ return { installed: true, alreadyExists: false };
90
+ }
91
+ export function isHookInstalled() {
92
+ if (!existsSync(SETTINGS_PATH))
93
+ return false;
94
+ try {
95
+ const settings = JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
96
+ const stopEntries = settings?.hooks?.Stop;
97
+ if (!Array.isArray(stopEntries))
98
+ return false;
99
+ return stopEntries.some((entry) => {
100
+ if (typeof entry !== "object" || entry === null)
101
+ return false;
102
+ const innerHooks = entry.hooks;
103
+ if (!Array.isArray(innerHooks))
104
+ return false;
105
+ return innerHooks.some((h) => typeof h === "object" &&
106
+ h !== null &&
107
+ h.command === MYPLAYER_HOOK_COMMAND);
108
+ });
109
+ }
110
+ catch {
111
+ return false;
112
+ }
113
+ }
114
+ //# sourceMappingURL=hook-installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-installer.js","sourceRoot":"","sources":["../../../src/installer/hook-installer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Add MyPlayer MCP server to Claude Code config.
3
+ * Writes to ~/.claude.json (primary) and ~/.claude/mcp_servers.json (fallback).
4
+ */
5
+ export declare function installMcp(): {
6
+ installed: boolean;
7
+ alreadyExists: boolean;
8
+ };
9
+ export declare function isMcpInstalled(): boolean;
@@ -0,0 +1,80 @@
1
+ import { readFileSync, writeFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ import { homedir } from "os";
4
+ // Claude Code stores user MCP servers in ~/.claude.json (not ~/.claude/mcp_servers.json)
5
+ const CLAUDE_JSON_PATH = join(homedir(), ".claude.json");
6
+ const LEGACY_MCP_PATH = join(homedir(), ".claude", "mcp_servers.json");
7
+ const MYPLAYER_MCP_ENTRY = {
8
+ command: "npx",
9
+ args: ["-y", "buildpartner", "serve"],
10
+ };
11
+ /**
12
+ * Add MyPlayer MCP server to Claude Code config.
13
+ * Writes to ~/.claude.json (primary) and ~/.claude/mcp_servers.json (fallback).
14
+ */
15
+ export function installMcp() {
16
+ // Try ~/.claude.json first (this is where Claude Code reads user MCPs)
17
+ if (existsSync(CLAUDE_JSON_PATH)) {
18
+ try {
19
+ const config = JSON.parse(readFileSync(CLAUDE_JSON_PATH, "utf-8"));
20
+ if (!config.mcpServers)
21
+ config.mcpServers = {};
22
+ if (config.mcpServers.myplayer) {
23
+ return { installed: false, alreadyExists: true };
24
+ }
25
+ config.mcpServers.myplayer = MYPLAYER_MCP_ENTRY;
26
+ writeFileSync(CLAUDE_JSON_PATH, JSON.stringify(config, null, 2) + "\n");
27
+ return { installed: true, alreadyExists: false };
28
+ }
29
+ catch {
30
+ // Fall through to legacy path
31
+ }
32
+ }
33
+ // Fallback: ~/.claude/mcp_servers.json
34
+ let config = {};
35
+ if (existsSync(LEGACY_MCP_PATH)) {
36
+ try {
37
+ config = JSON.parse(readFileSync(LEGACY_MCP_PATH, "utf-8"));
38
+ }
39
+ catch {
40
+ config = {};
41
+ }
42
+ }
43
+ const hasNested = config.mcpServers && typeof config.mcpServers === "object";
44
+ const target = hasNested
45
+ ? config.mcpServers
46
+ : config;
47
+ if (target["myplayer"]) {
48
+ return { installed: false, alreadyExists: true };
49
+ }
50
+ if (!hasNested) {
51
+ config.mcpServers = config.mcpServers || {};
52
+ }
53
+ config.mcpServers["myplayer"] = MYPLAYER_MCP_ENTRY;
54
+ writeFileSync(LEGACY_MCP_PATH, JSON.stringify(config, null, 2) + "\n");
55
+ return { installed: true, alreadyExists: false };
56
+ }
57
+ export function isMcpInstalled() {
58
+ // Check ~/.claude.json
59
+ if (existsSync(CLAUDE_JSON_PATH)) {
60
+ try {
61
+ const config = JSON.parse(readFileSync(CLAUDE_JSON_PATH, "utf-8"));
62
+ if (config.mcpServers?.myplayer)
63
+ return true;
64
+ }
65
+ catch { }
66
+ }
67
+ // Check legacy path
68
+ if (existsSync(LEGACY_MCP_PATH)) {
69
+ try {
70
+ const config = JSON.parse(readFileSync(LEGACY_MCP_PATH, "utf-8"));
71
+ if (config.mcpServers?.myplayer)
72
+ return true;
73
+ if (config.myplayer)
74
+ return true;
75
+ }
76
+ catch { }
77
+ }
78
+ return false;
79
+ }
80
+ //# sourceMappingURL=mcp-installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-installer.js","sourceRoot":"","sources":["../../../src/installer/mcp-installer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Copy SKILL.md files to ~/.claude/skills/ (global only).
3
+ * Global install makes skills accessible in every project.
4
+ */
5
+ export declare function installSkills(): string[];
@@ -0,0 +1,55 @@
1
+ import { copyFileSync, mkdirSync, existsSync } from "fs";
2
+ import { join, dirname } from "path";
3
+ import { homedir } from "os";
4
+ import { fileURLToPath } from "url";
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+ // When compiled: __dirname = .../dist/src/installer
8
+ // Package root = 3 levels up from there
9
+ const PACKAGE_ROOT = join(__dirname, "..", "..", "..");
10
+ const GLOBAL_SKILLS_DIR = join(homedir(), ".claude", "skills");
11
+ const SKILLS = ["he-consult", "he-coach", "he-recap-week", "he-flex-socials", "he-interview", "he-life-story", "he-quest-status", "he-enhance-claude-md", "he-open-dashboard", "he-log-experience", "he-improve-skill", "he-full-audit"];
12
+ /**
13
+ * Find the source skills directory from the package.
14
+ */
15
+ function findSkillsSource() {
16
+ const searchPaths = [
17
+ join(PACKAGE_ROOT, "skills"),
18
+ join(PACKAGE_ROOT, "..", "skills"),
19
+ join(__dirname, "..", "..", "..", "..", "skills"),
20
+ ];
21
+ for (const p of searchPaths) {
22
+ if (existsSync(join(p, SKILLS[0], "SKILL.md"))) {
23
+ return p;
24
+ }
25
+ }
26
+ return null;
27
+ }
28
+ /**
29
+ * Install skills to a target directory.
30
+ */
31
+ function installToDir(skillsDir, targetDir) {
32
+ const installed = [];
33
+ for (const skill of SKILLS) {
34
+ const source = join(skillsDir, skill, "SKILL.md");
35
+ if (!existsSync(source))
36
+ continue;
37
+ const destDir = join(targetDir, skill);
38
+ const dest = join(destDir, "SKILL.md");
39
+ mkdirSync(destDir, { recursive: true });
40
+ copyFileSync(source, dest);
41
+ installed.push(skill);
42
+ }
43
+ return installed;
44
+ }
45
+ /**
46
+ * Copy SKILL.md files to ~/.claude/skills/ (global only).
47
+ * Global install makes skills accessible in every project.
48
+ */
49
+ export function installSkills() {
50
+ const skillsDir = findSkillsSource();
51
+ if (!skillsDir)
52
+ return [];
53
+ return installToDir(skillsDir, GLOBAL_SKILLS_DIR);
54
+ }
55
+ //# sourceMappingURL=skill-installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-installer.js","sourceRoot":"","sources":["../../../src/installer/skill-installer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,oDAAoD;AACpD,wCAAwC;AACxC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACvD,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAE/D,MAAM,MAAM,GAAG,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,eAAe,CAAC,CAAC;AAEzO;;GAEG;AACH,SAAS,gBAAgB;IACvB,MAAM,WAAW,GAAG;QAClB,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC;QAC5B,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,QAAQ,CAAC;QAClC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC;KAClD,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;YAC/C,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,SAAiB,EAAE,SAAiB;IACxD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QAClD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,SAAS;QAElC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAEvC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3B,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;IACrC,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,CAAC;IAE1B,OAAO,YAAY,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Skill sync: pulls latest skill definitions from the API.
3
+ * Called on MCP server startup. Writes to ~/.claude/skills/he-*.
4
+ * Falls back to bundled skills if offline.
5
+ */
6
+ /**
7
+ * Sync skills from API if stale. Non-blocking, best-effort.
8
+ * Returns true if sync happened, false if skipped or failed.
9
+ */
10
+ export declare function syncSkills(): Promise<boolean>;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Skill sync: pulls latest skill definitions from the API.
3
+ * Called on MCP server startup. Writes to ~/.claude/skills/he-*.
4
+ * Falls back to bundled skills if offline.
5
+ */
6
+ import { writeFileSync, readFileSync, mkdirSync } from "fs";
7
+ import { join } from "path";
8
+ import { homedir } from "os";
9
+ import { apiFetch } from "../api-client.js";
10
+ const SKILLS_DIR = join(homedir(), ".claude", "skills");
11
+ const SYNC_STATE_PATH = join(homedir(), ".myplayer", "skill-sync.json");
12
+ const SYNC_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours
13
+ function readSyncState() {
14
+ try {
15
+ return JSON.parse(readFileSync(SYNC_STATE_PATH, "utf-8"));
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ function writeSyncState(state) {
22
+ try {
23
+ const dir = join(homedir(), ".myplayer");
24
+ mkdirSync(dir, { recursive: true });
25
+ writeFileSync(SYNC_STATE_PATH, JSON.stringify(state));
26
+ }
27
+ catch {
28
+ // Non-fatal
29
+ }
30
+ }
31
+ /**
32
+ * Sync skills from API if stale. Non-blocking, best-effort.
33
+ * Returns true if sync happened, false if skipped or failed.
34
+ */
35
+ export async function syncSkills() {
36
+ const state = readSyncState();
37
+ const now = Date.now();
38
+ // Skip if synced recently
39
+ if (state?.last_sync) {
40
+ const age = now - new Date(state.last_sync).getTime();
41
+ if (age < SYNC_INTERVAL_MS) {
42
+ return false;
43
+ }
44
+ }
45
+ try {
46
+ const since = state?.last_sync || undefined;
47
+ const qs = since ? `?since=${encodeURIComponent(since)}` : "";
48
+ const res = await apiFetch(`/api/myplayer/skills${qs}`);
49
+ if (!res || !res.ok) {
50
+ return false;
51
+ }
52
+ const data = await res.json();
53
+ if (!data.skills || data.skills.length === 0) {
54
+ // No updates, but mark sync as done
55
+ writeSyncState({ last_sync: new Date().toISOString(), sync_version: data.sync_version });
56
+ return false;
57
+ }
58
+ // Write updated skills to disk
59
+ for (const skill of data.skills) {
60
+ const skillDir = join(SKILLS_DIR, skill.name);
61
+ const skillPath = join(skillDir, "SKILL.md");
62
+ mkdirSync(skillDir, { recursive: true });
63
+ writeFileSync(skillPath, skill.content);
64
+ }
65
+ writeSyncState({
66
+ last_sync: new Date().toISOString(),
67
+ sync_version: data.sync_version,
68
+ });
69
+ return true;
70
+ }
71
+ catch {
72
+ // Sync failures are non-fatal, skills fall back to bundled versions
73
+ return false;
74
+ }
75
+ }
76
+ //# sourceMappingURL=skill-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-sync.js","sourceRoot":"","sources":["../../../src/installer/skill-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createServer(): McpServer;
3
+ export declare function startServer(): Promise<void>;
@@ -0,0 +1,106 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ import { apiGet, apiPost, track } from "../api-client.js";
5
+ import { checkStatus } from "../store/status-store.js";
6
+ import { getQuestStatus, getQuestSchema } from "./tools/quest.js";
7
+ import { checkAccess } from "./subscription-gate.js";
8
+ // Tools that work even when trial is expired
9
+ const UNGATED_TOOLS = new Set(["check_status", "get_quest_progress"]);
10
+ function gated(toolName, handler) {
11
+ if (UNGATED_TOOLS.has(toolName))
12
+ return handler;
13
+ return async (args) => {
14
+ const blocked = await checkAccess();
15
+ if (blocked) {
16
+ return { content: [{ type: "text", text: blocked }] };
17
+ }
18
+ return handler(args);
19
+ };
20
+ }
21
+ export function createServer() {
22
+ const server = new McpServer({
23
+ name: "myplayer",
24
+ version: "0.2.0",
25
+ });
26
+ track("mcp.server.start");
27
+ // ─── GET PERSONAL CONTEXT ───────────────────────────────────
28
+ // Returns: stats, AI profile, workspace, subscription, daily activity.
29
+ // Optionally includes session history for skills that need it.
30
+ server.tool("get_personal_context", "Get your personal context: stats, AI profile, workspace, subscription status, and optionally recent session history. This is the main data source for most skills.", {
31
+ include_sessions: z.boolean().optional().describe("Include last 30 session summaries. Use for skills that need session history (coach, recap, interview, enhance-claude-md). Omit for lighter payload."),
32
+ }, gated("get_personal_context", async ({ include_sessions }) => {
33
+ track("mcp.tool.get_personal_context", { include_sessions });
34
+ const qs = include_sessions ? "?include_sessions=true" : "";
35
+ const result = await apiGet(`/api/myplayer/context${qs}`);
36
+ if (!result) {
37
+ return { content: [{ type: "text", text: JSON.stringify({ error: "Could not fetch personal context. Check your connection." }) }] };
38
+ }
39
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
40
+ }));
41
+ // ─── GET EXPERT KNOWLEDGE ──────────────────────────────────
42
+ // Searches/fetches expert frameworks. Also returns personal context
43
+ // so consultant skills only need one call.
44
+ server.tool("get_expert_knowledge", "Search or fetch expert frameworks (pricing, content, launch, AI automation, etc). Also returns your personal context for personalized advice. Use query to search, or topic to fetch a specific framework.", {
45
+ query: z.string().optional().describe("Search query to find relevant frameworks (e.g. 'pricing strategy', 'YouTube titles', 'launch plan')"),
46
+ topic: z.string().optional().describe("Specific topic key to fetch full content (e.g. 'sales-value-equation', 'content-hooks')"),
47
+ }, gated("get_expert_knowledge", async ({ query, topic }) => {
48
+ track("mcp.tool.get_expert_knowledge", { query, topic });
49
+ const params = new URLSearchParams();
50
+ if (query)
51
+ params.set("query", query);
52
+ if (topic)
53
+ params.set("topic", topic);
54
+ const qs = params.toString();
55
+ const path = qs ? `/api/myplayer/expert-knowledge?${qs}` : "/api/myplayer/expert-knowledge";
56
+ const result = await apiGet(path);
57
+ if (!result) {
58
+ return { content: [{ type: "text", text: JSON.stringify({ error: "Could not fetch expert knowledge. Check your connection." }) }] };
59
+ }
60
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
61
+ }));
62
+ // ─── SAVE PROFILE ──────────────────────────────────────────
63
+ // Batch update AI profile sections. Used by /interview and /life-story.
64
+ server.tool("save_profile", "Save your AI profile. Updates multiple sections at once: writing_style, preferences, tech_identity, work_patterns, personality. Used after interviews or profile building.", {
65
+ updates: z.record(z.string(), z.any()).describe("Object with section names as keys and section data as values. Sections: writing_style, preferences, tech_identity, work_patterns, personality."),
66
+ signals: z.array(z.string()).optional().describe("Summary of what was learned, stored as raw signals for future reference."),
67
+ }, gated("save_profile", async ({ updates, signals }) => {
68
+ track("mcp.tool.save_profile", { sections: Object.keys(updates) });
69
+ const payload = { ...updates };
70
+ if (signals)
71
+ payload.raw_signals = signals;
72
+ const result = await apiPost("/api/myplayer/profile", payload);
73
+ if (!result) {
74
+ return { content: [{ type: "text", text: JSON.stringify({ error: "Could not save profile. Check your connection." }) }] };
75
+ }
76
+ return { content: [{ type: "text", text: JSON.stringify({ saved: true, sections: Object.keys(updates) }) }] };
77
+ }));
78
+ // ─── GET QUEST PROGRESS ────────────────────────────────────
79
+ // Returns quest state from local store.
80
+ server.tool("get_quest_progress", "Check your quest progress: which quests are completed, active, or locked. Shows your path through BuildPartner.", getQuestSchema, gated("get_quest_progress", async () => {
81
+ track("mcp.tool.get_quest_progress");
82
+ const result = await getQuestStatus();
83
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
84
+ }));
85
+ // ─── CHECK STATUS ──────────────────────────────────────────
86
+ // Internal bookkeeping. Every skill calls this as its final step.
87
+ server.tool("check_status", "Check system status and get reminders. Every skill should call this as its final step.", {
88
+ skill_name: z.string().describe("The skill that just ran (e.g., 'coach', 'recap-week')"),
89
+ session_context: z.string().optional().describe("Brief description of what the session involved"),
90
+ }, gated("check_status", async ({ skill_name, session_context }) => {
91
+ track("mcp.tool.check_status", { skill_name });
92
+ const result = checkStatus(skill_name, session_context);
93
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
94
+ }));
95
+ return server;
96
+ }
97
+ export async function startServer() {
98
+ const server = createServer();
99
+ const transport = new StdioServerTransport();
100
+ // Sync skills from API in background (non-blocking)
101
+ import("../installer/skill-sync.js")
102
+ .then(({ syncSkills }) => syncSkills())
103
+ .catch(() => { }); // Never block startup
104
+ await server.connect(transport);
105
+ }
106
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,6CAA6C;AAC7C,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAEtE,SAAS,KAAK,CAAO,QAAgB,EAAE,OAAgC;IACrE,IAAI,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,OAAO,CAAC;IAChD,OAAO,KAAK,EAAE,IAAO,EAAE,EAAE;QACvB,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;QACpC,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAkB,CAAC;QACjF,CAAC;QACD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAE1B,+DAA+D;IAC/D,uEAAuE;IACvE,+DAA+D;IAC/D,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,oKAAoK,EACpK;QACE,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qJAAqJ,CAAC;KACzM,EACD,KAAK,CAAC,sBAAsB,EAAE,KAAK,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE;QAC3D,KAAK,CAAC,+BAA+B,EAAE,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAC7D,MAAM,EAAE,GAAG,gBAAgB,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,0DAA0D,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAC/I,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC,CAAC,CACH,CAAC;IAEF,8DAA8D;IAC9D,oEAAoE;IACpE,2CAA2C;IAC3C,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,4MAA4M,EAC5M;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qGAAqG,CAAC;QAC5I,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yFAAyF,CAAC;KACjI,EACD,KAAK,CAAC,sBAAsB,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;QACvD,KAAK,CAAC,+BAA+B,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,KAAK;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACtC,IAAI,KAAK;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACtC,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,kCAAkC,EAAE,EAAE,CAAC,CAAC,CAAC,gCAAgC,CAAC;QAC5F,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,0DAA0D,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAC/I,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC,CAAC,CACH,CAAC;IAEF,8DAA8D;IAC9D,wEAAwE;IACxE,MAAM,CAAC,IAAI,CACT,cAAc,EACd,4KAA4K,EAC5K;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,gJAAgJ,CAAC;QACjM,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0EAA0E,CAAC;KAC7H,EACD,KAAK,CAAC,cAAc,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE;QACnD,KAAK,CAAC,uBAAuB,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACnE,MAAM,OAAO,GAA4B,EAAE,GAAG,OAAO,EAAE,CAAC;QACxD,IAAI,OAAO;YAAE,OAAO,CAAC,WAAW,GAAG,OAAO,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,gDAAgD,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACrI,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IACzH,CAAC,CAAC,CACH,CAAC;IAEF,8DAA8D;IAC9D,wCAAwC;IACxC,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,iHAAiH,EACjH,cAAc,EACd,KAAK,CAAC,oBAAoB,EAAE,KAAK,IAAI,EAAE;QACrC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;QACtC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC,CAAC,CACH,CAAC;IAEF,8DAA8D;IAC9D,kEAAkE;IAClE,MAAM,CAAC,IAAI,CACT,cAAc,EACd,wFAAwF,EACxF;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;QACxF,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gDAAgD,CAAC;KAClG,EACD,KAAK,CAAC,cAAc,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,eAAe,EAAE,EAAE,EAAE;QAC9D,KAAK,CAAC,uBAAuB,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,WAAW,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;QACxD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IACzF,CAAC,CAAC,CACH,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,oDAAoD;IACpD,MAAM,CAAC,4BAA4B,CAAC;SACjC,IAAI,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC;SACtC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,sBAAsB;IAE1C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Subscription gate for MCP tool calls.
3
+ *
4
+ * Checks if the user has an active trial or has paid.
5
+ * Caches the result for 5 minutes to avoid hitting the API on every call.
6
+ */
7
+ /**
8
+ * Check if the user can use tools. Returns null if access is granted,
9
+ * or an error message string if access is denied.
10
+ */
11
+ export declare function checkAccess(): Promise<string | null>;
12
+ /**
13
+ * Get trial status for informational purposes (used by check_status).
14
+ */
15
+ export declare function getTrialInfo(): Promise<{
16
+ status: "active" | "trial" | "expired";
17
+ trial_days_left: number;
18
+ upgrade_url: string;
19
+ } | null>;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Subscription gate for MCP tool calls.
3
+ *
4
+ * Checks if the user has an active trial or has paid.
5
+ * Caches the result for 5 minutes to avoid hitting the API on every call.
6
+ */
7
+ import { apiGet } from "../api-client.js";
8
+ import { readAuth } from "../store/local-store.js";
9
+ let cachedStatus = null;
10
+ let cacheTimestamp = 0;
11
+ const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
12
+ async function getSubscriptionStatus() {
13
+ const now = Date.now();
14
+ if (cachedStatus && now - cacheTimestamp < CACHE_TTL_MS) {
15
+ return cachedStatus;
16
+ }
17
+ const result = await apiGet("/api/myplayer/subscription");
18
+ if (result) {
19
+ cachedStatus = result;
20
+ cacheTimestamp = now;
21
+ }
22
+ return result;
23
+ }
24
+ /**
25
+ * Check if the user can use tools. Returns null if access is granted,
26
+ * or an error message string if access is denied.
27
+ */
28
+ export async function checkAccess() {
29
+ const auth = readAuth();
30
+ if (!auth?.token) {
31
+ // No auth = not set up yet. Allow access (setup flow needs tools).
32
+ return null;
33
+ }
34
+ const status = await getSubscriptionStatus();
35
+ // If we can't reach the API, allow access (offline-friendly)
36
+ if (!status) {
37
+ return null;
38
+ }
39
+ if (status.status === "active") {
40
+ return null;
41
+ }
42
+ if (status.status === "trial") {
43
+ // Trial active, but remind them on last 2 days
44
+ if (status.trial_days_left <= 2) {
45
+ // Don't block, just return null. The check_status tool can remind them.
46
+ return null;
47
+ }
48
+ return null;
49
+ }
50
+ // Trial expired and hasn't paid
51
+ return [
52
+ "Your 7-day free trial has ended.",
53
+ "",
54
+ "Upgrade to keep using BuildPartner ($8.99, one-time):",
55
+ status.upgrade_url,
56
+ "",
57
+ "Run this to open your dashboard:",
58
+ `open "${status.upgrade_url}"`,
59
+ ].join("\n");
60
+ }
61
+ /**
62
+ * Get trial status for informational purposes (used by check_status).
63
+ */
64
+ export async function getTrialInfo() {
65
+ const status = await getSubscriptionStatus();
66
+ if (!status)
67
+ return null;
68
+ return {
69
+ status: status.status,
70
+ trial_days_left: status.trial_days_left,
71
+ upgrade_url: status.upgrade_url,
72
+ };
73
+ }
74
+ //# sourceMappingURL=subscription-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription-gate.js","sourceRoot":"","sources":["../../../src/mcp/subscription-gate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAUnD,IAAI,YAAY,GAA8B,IAAI,CAAC;AACnD,IAAI,cAAc,GAAG,CAAC,CAAC;AACvB,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,YAAY;AAEhD,KAAK,UAAU,qBAAqB;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,YAAY,IAAI,GAAG,GAAG,cAAc,GAAG,YAAY,EAAE,CAAC;QACxD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAqB,4BAA4B,CAAC,CAAC;IAC9E,IAAI,MAAM,EAAE,CAAC;QACX,YAAY,GAAG,MAAM,CAAC;QACtB,cAAc,GAAG,GAAG,CAAC;IACvB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;QACjB,mEAAmE;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,qBAAqB,EAAE,CAAC;IAE7C,6DAA6D;IAC7D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC9B,+CAA+C;QAC/C,IAAI,MAAM,CAAC,eAAe,IAAI,CAAC,EAAE,CAAC;YAChC,wEAAwE;YACxE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gCAAgC;IAChC,OAAO;QACL,kCAAkC;QAClC,EAAE;QACF,uDAAuD;QACvD,MAAM,CAAC,WAAW;QAClB,EAAE;QACF,kCAAkC;QAClC,SAAS,MAAM,CAAC,WAAW,GAAG;KAC/B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAKhC,MAAM,MAAM,GAAG,MAAM,qBAAqB,EAAE,CAAC;IAC7C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC;AACJ,CAAC"}