token-pilot 0.1.1

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 (142) hide show
  1. package/.claude-plugin/hooks/hooks.json +15 -0
  2. package/.claude-plugin/marketplace.json +15 -0
  3. package/.claude-plugin/plugin.json +9 -0
  4. package/.mcp.json +8 -0
  5. package/CHANGELOG.md +48 -0
  6. package/README.md +282 -0
  7. package/dist/ast-index/binary-manager.d.ts +15 -0
  8. package/dist/ast-index/binary-manager.d.ts.map +1 -0
  9. package/dist/ast-index/binary-manager.js +222 -0
  10. package/dist/ast-index/binary-manager.js.map +1 -0
  11. package/dist/ast-index/client.d.ts +48 -0
  12. package/dist/ast-index/client.d.ts.map +1 -0
  13. package/dist/ast-index/client.js +371 -0
  14. package/dist/ast-index/client.js.map +1 -0
  15. package/dist/ast-index/tar-extract.d.ts +6 -0
  16. package/dist/ast-index/tar-extract.d.ts.map +1 -0
  17. package/dist/ast-index/tar-extract.js +39 -0
  18. package/dist/ast-index/tar-extract.js.map +1 -0
  19. package/dist/ast-index/types.d.ts +78 -0
  20. package/dist/ast-index/types.d.ts.map +1 -0
  21. package/dist/ast-index/types.js +6 -0
  22. package/dist/ast-index/types.js.map +1 -0
  23. package/dist/config/defaults.d.ts +3 -0
  24. package/dist/config/defaults.d.ts.map +1 -0
  25. package/dist/config/defaults.js +51 -0
  26. package/dist/config/defaults.js.map +1 -0
  27. package/dist/config/loader.d.ts +3 -0
  28. package/dist/config/loader.d.ts.map +1 -0
  29. package/dist/config/loader.js +31 -0
  30. package/dist/config/loader.js.map +1 -0
  31. package/dist/core/context-registry.d.ts +31 -0
  32. package/dist/core/context-registry.d.ts.map +1 -0
  33. package/dist/core/context-registry.js +133 -0
  34. package/dist/core/context-registry.js.map +1 -0
  35. package/dist/core/file-cache.d.ts +34 -0
  36. package/dist/core/file-cache.d.ts.map +1 -0
  37. package/dist/core/file-cache.js +120 -0
  38. package/dist/core/file-cache.js.map +1 -0
  39. package/dist/core/format-duration.d.ts +5 -0
  40. package/dist/core/format-duration.d.ts.map +1 -0
  41. package/dist/core/format-duration.js +13 -0
  42. package/dist/core/format-duration.js.map +1 -0
  43. package/dist/core/session-analytics.d.ts +26 -0
  44. package/dist/core/session-analytics.d.ts.map +1 -0
  45. package/dist/core/session-analytics.js +91 -0
  46. package/dist/core/session-analytics.js.map +1 -0
  47. package/dist/core/symbol-resolver.d.ts +21 -0
  48. package/dist/core/symbol-resolver.d.ts.map +1 -0
  49. package/dist/core/symbol-resolver.js +102 -0
  50. package/dist/core/symbol-resolver.js.map +1 -0
  51. package/dist/core/token-estimator.d.ts +10 -0
  52. package/dist/core/token-estimator.d.ts.map +1 -0
  53. package/dist/core/token-estimator.js +22 -0
  54. package/dist/core/token-estimator.js.map +1 -0
  55. package/dist/core/validation.d.ts +77 -0
  56. package/dist/core/validation.d.ts.map +1 -0
  57. package/dist/core/validation.js +208 -0
  58. package/dist/core/validation.js.map +1 -0
  59. package/dist/formatters/structure.d.ts +13 -0
  60. package/dist/formatters/structure.d.ts.map +1 -0
  61. package/dist/formatters/structure.js +90 -0
  62. package/dist/formatters/structure.js.map +1 -0
  63. package/dist/git/file-watcher.d.ts +17 -0
  64. package/dist/git/file-watcher.d.ts.map +1 -0
  65. package/dist/git/file-watcher.js +54 -0
  66. package/dist/git/file-watcher.js.map +1 -0
  67. package/dist/git/watcher.d.ts +25 -0
  68. package/dist/git/watcher.d.ts.map +1 -0
  69. package/dist/git/watcher.js +95 -0
  70. package/dist/git/watcher.js.map +1 -0
  71. package/dist/handlers/class-hierarchy.d.ts +11 -0
  72. package/dist/handlers/class-hierarchy.d.ts.map +1 -0
  73. package/dist/handlers/class-hierarchy.js +28 -0
  74. package/dist/handlers/class-hierarchy.js.map +1 -0
  75. package/dist/handlers/export-ast-index.d.ts +19 -0
  76. package/dist/handlers/export-ast-index.d.ts.map +1 -0
  77. package/dist/handlers/export-ast-index.js +107 -0
  78. package/dist/handlers/export-ast-index.js.map +1 -0
  79. package/dist/handlers/find-implementations.d.ts +11 -0
  80. package/dist/handlers/find-implementations.d.ts.map +1 -0
  81. package/dist/handlers/find-implementations.js +25 -0
  82. package/dist/handlers/find-implementations.js.map +1 -0
  83. package/dist/handlers/find-usages.d.ts +11 -0
  84. package/dist/handlers/find-usages.d.ts.map +1 -0
  85. package/dist/handlers/find-usages.js +23 -0
  86. package/dist/handlers/find-usages.js.map +1 -0
  87. package/dist/handlers/non-code.d.ts +25 -0
  88. package/dist/handlers/non-code.d.ts.map +1 -0
  89. package/dist/handlers/non-code.js +152 -0
  90. package/dist/handlers/non-code.js.map +1 -0
  91. package/dist/handlers/project-overview.d.ts +8 -0
  92. package/dist/handlers/project-overview.d.ts.map +1 -0
  93. package/dist/handlers/project-overview.js +84 -0
  94. package/dist/handlers/project-overview.js.map +1 -0
  95. package/dist/handlers/read-diff.d.ts +13 -0
  96. package/dist/handlers/read-diff.d.ts.map +1 -0
  97. package/dist/handlers/read-diff.js +174 -0
  98. package/dist/handlers/read-diff.js.map +1 -0
  99. package/dist/handlers/read-range.d.ts +14 -0
  100. package/dist/handlers/read-range.d.ts.map +1 -0
  101. package/dist/handlers/read-range.js +44 -0
  102. package/dist/handlers/read-range.js.map +1 -0
  103. package/dist/handlers/read-symbol.d.ts +16 -0
  104. package/dist/handlers/read-symbol.d.ts.map +1 -0
  105. package/dist/handlers/read-symbol.js +59 -0
  106. package/dist/handlers/read-symbol.js.map +1 -0
  107. package/dist/handlers/search-code.d.ts +14 -0
  108. package/dist/handlers/search-code.d.ts.map +1 -0
  109. package/dist/handlers/search-code.js +27 -0
  110. package/dist/handlers/search-code.js.map +1 -0
  111. package/dist/handlers/smart-read-many.d.ts +14 -0
  112. package/dist/handlers/smart-read-many.d.ts.map +1 -0
  113. package/dist/handlers/smart-read-many.js +32 -0
  114. package/dist/handlers/smart-read-many.js.map +1 -0
  115. package/dist/handlers/smart-read.d.ts +18 -0
  116. package/dist/handlers/smart-read.d.ts.map +1 -0
  117. package/dist/handlers/smart-read.js +86 -0
  118. package/dist/handlers/smart-read.js.map +1 -0
  119. package/dist/hooks/installer.d.ts +16 -0
  120. package/dist/hooks/installer.d.ts.map +1 -0
  121. package/dist/hooks/installer.js +89 -0
  122. package/dist/hooks/installer.js.map +1 -0
  123. package/dist/index.d.ts +3 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +120 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/integration/context-mode-detector.d.ts +16 -0
  128. package/dist/integration/context-mode-detector.d.ts.map +1 -0
  129. package/dist/integration/context-mode-detector.js +53 -0
  130. package/dist/integration/context-mode-detector.js.map +1 -0
  131. package/dist/server.d.ts +36 -0
  132. package/dist/server.d.ts.map +1 -0
  133. package/dist/server.js +375 -0
  134. package/dist/server.js.map +1 -0
  135. package/dist/types.d.ts +122 -0
  136. package/dist/types.d.ts.map +1 -0
  137. package/dist/types.js +5 -0
  138. package/dist/types.js.map +1 -0
  139. package/package.json +67 -0
  140. package/skills/install/SKILL.md +14 -0
  141. package/skills/stats/SKILL.md +8 -0
  142. package/start.sh +27 -0
@@ -0,0 +1,86 @@
1
+ import { readFile, stat } from 'node:fs/promises';
2
+ import { createHash } from 'node:crypto';
3
+ import { formatOutline } from '../formatters/structure.js';
4
+ import { estimateTokens, formatSavings } from '../core/token-estimator.js';
5
+ import { resolveSafePath } from '../core/validation.js';
6
+ export async function handleSmartRead(args, projectRoot, astIndex, fileCache, contextRegistry, config) {
7
+ const absPath = resolveSafePath(projectRoot, args.path);
8
+ // 1. Read file content
9
+ const content = await readFile(absPath, 'utf-8');
10
+ const lines = content.split('\n');
11
+ // 2. Small-file pass-through
12
+ if (lines.length <= config.smartRead.smallFileThreshold) {
13
+ const tokens = estimateTokens(content);
14
+ contextRegistry.trackLoad(absPath, {
15
+ type: 'full',
16
+ startLine: 1,
17
+ endLine: lines.length,
18
+ tokens,
19
+ });
20
+ contextRegistry.setContentHash(absPath, createHash('sha256').update(content).digest('hex'));
21
+ return {
22
+ content: [{
23
+ type: 'text',
24
+ text: `FILE: ${args.path} (${lines.length} lines — returned in full, below threshold)\n\n${content}`,
25
+ }],
26
+ };
27
+ }
28
+ // 3. Check cache
29
+ let cached = fileCache.get(absPath);
30
+ const isStale = cached ? await fileCache.isStale(absPath) : true;
31
+ if (!cached || isStale) {
32
+ // 4. Get structure from ast-index
33
+ const structure = await astIndex.outline(absPath);
34
+ if (!structure) {
35
+ // ast-index doesn't support this — return raw
36
+ return {
37
+ content: [{
38
+ type: 'text',
39
+ text: `FILE: ${args.path} (${lines.length} lines — language not supported, raw content)\n\n${content}`,
40
+ }],
41
+ };
42
+ }
43
+ const fileStat = await stat(absPath);
44
+ const hash = createHash('sha256').update(content).digest('hex');
45
+ cached = {
46
+ structure,
47
+ content,
48
+ lines,
49
+ mtime: fileStat.mtimeMs,
50
+ hash,
51
+ lastAccess: Date.now(),
52
+ };
53
+ fileCache.set(absPath, cached);
54
+ }
55
+ // 5. Advisory context check
56
+ const previouslyLoaded = contextRegistry.getLoaded(absPath);
57
+ if (previouslyLoaded && !contextRegistry.isStale(absPath, cached.hash)) {
58
+ if (config.smartRead.advisoryReminders) {
59
+ const reminder = contextRegistry.compactReminder(absPath, cached.structure.symbols);
60
+ return { content: [{ type: 'text', text: reminder }] };
61
+ }
62
+ }
63
+ // 6. Format output
64
+ const output = formatOutline(cached.structure, {
65
+ showImports: args.show_imports ?? config.display.showImports,
66
+ showDocs: args.show_docs ?? config.display.showDocs,
67
+ showDependencyHints: config.smartRead.showDependencyHints,
68
+ maxDepth: args.depth ?? config.display.maxDepth,
69
+ });
70
+ // 7. Add token savings
71
+ const structureTokens = estimateTokens(output);
72
+ const fullTokens = estimateTokens(content);
73
+ const savings = config.display.showTokenSavings
74
+ ? '\n' + formatSavings(structureTokens, fullTokens)
75
+ : '';
76
+ // 8. Track
77
+ contextRegistry.trackLoad(absPath, {
78
+ type: 'structure',
79
+ startLine: 1,
80
+ endLine: cached.structure.meta.lines,
81
+ tokens: structureTokens,
82
+ });
83
+ contextRegistry.setContentHash(absPath, cached.hash);
84
+ return { content: [{ type: 'text', text: output + savings }] };
85
+ }
86
+ //# sourceMappingURL=smart-read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smart-read.js","sourceRoot":"","sources":["../../src/handlers/smart-read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Install Token Pilot hook into Claude Code settings.
3
+ * Creates or updates .claude/settings.json with PreToolUse hook.
4
+ */
5
+ export declare function installHook(projectRoot: string): Promise<{
6
+ installed: boolean;
7
+ message: string;
8
+ }>;
9
+ /**
10
+ * Remove Token Pilot hook from Claude Code settings.
11
+ */
12
+ export declare function uninstallHook(projectRoot: string): Promise<{
13
+ removed: boolean;
14
+ message: string;
15
+ }>;
16
+ //# sourceMappingURL=installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/hooks/installer.ts"],"names":[],"mappings":"AAmBA;;;GAGG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA+CvG;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA4BvG"}
@@ -0,0 +1,89 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { resolve, dirname } from 'node:path';
3
+ const HOOK_CONFIG = {
4
+ hooks: {
5
+ PreToolUse: [
6
+ {
7
+ matcher: "Read",
8
+ hooks: [
9
+ {
10
+ type: "command",
11
+ command: "token-pilot hook-read $FILE_PATH",
12
+ },
13
+ ],
14
+ },
15
+ ],
16
+ },
17
+ };
18
+ /**
19
+ * Install Token Pilot hook into Claude Code settings.
20
+ * Creates or updates .claude/settings.json with PreToolUse hook.
21
+ */
22
+ export async function installHook(projectRoot) {
23
+ const settingsPath = resolve(projectRoot, '.claude', 'settings.json');
24
+ try {
25
+ // Ensure .claude dir exists
26
+ await mkdir(dirname(settingsPath), { recursive: true });
27
+ let settings = {};
28
+ // Try to read existing settings
29
+ try {
30
+ const raw = await readFile(settingsPath, 'utf-8');
31
+ settings = JSON.parse(raw);
32
+ }
33
+ catch {
34
+ // File doesn't exist or is invalid — start fresh
35
+ }
36
+ // Check if hook already exists
37
+ const existingHooks = settings.hooks?.PreToolUse;
38
+ if (Array.isArray(existingHooks)) {
39
+ const hasTokenPilot = existingHooks.some((h) => h.matcher === 'Read' &&
40
+ h.hooks?.some((hook) => hook.command?.includes('token-pilot')));
41
+ if (hasTokenPilot) {
42
+ return { installed: false, message: 'Token Pilot hook already installed.' };
43
+ }
44
+ // Add to existing PreToolUse hooks
45
+ existingHooks.push(HOOK_CONFIG.hooks.PreToolUse[0]);
46
+ }
47
+ else {
48
+ // Create hooks section
49
+ if (!settings.hooks)
50
+ settings.hooks = {};
51
+ settings.hooks.PreToolUse = HOOK_CONFIG.hooks.PreToolUse;
52
+ }
53
+ await writeFile(settingsPath, JSON.stringify(settings, null, 2) + '\n');
54
+ return {
55
+ installed: true,
56
+ message: `Hook installed at ${settingsPath}. Token Pilot will suggest smart_read for large code files.`,
57
+ };
58
+ }
59
+ catch (err) {
60
+ const msg = err instanceof Error ? err.message : String(err);
61
+ return { installed: false, message: `Failed to install hook: ${msg}` };
62
+ }
63
+ }
64
+ /**
65
+ * Remove Token Pilot hook from Claude Code settings.
66
+ */
67
+ export async function uninstallHook(projectRoot) {
68
+ const settingsPath = resolve(projectRoot, '.claude', 'settings.json');
69
+ try {
70
+ const raw = await readFile(settingsPath, 'utf-8');
71
+ const settings = JSON.parse(raw);
72
+ if (!settings.hooks?.PreToolUse) {
73
+ return { removed: false, message: 'No hooks to remove.' };
74
+ }
75
+ settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter((h) => !(h.matcher === 'Read' && h.hooks?.some((hook) => hook.command?.includes('token-pilot'))));
76
+ if (settings.hooks.PreToolUse.length === 0) {
77
+ delete settings.hooks.PreToolUse;
78
+ }
79
+ if (Object.keys(settings.hooks).length === 0) {
80
+ delete settings.hooks;
81
+ }
82
+ await writeFile(settingsPath, JSON.stringify(settings, null, 2) + '\n');
83
+ return { removed: true, message: 'Token Pilot hook removed.' };
84
+ }
85
+ catch {
86
+ return { removed: false, message: 'Settings file not found or invalid.' };
87
+ }
88
+ }
89
+ //# sourceMappingURL=installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/hooks/installer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { readFileSync } from 'node:fs';
4
+ import { createServer } from './server.js';
5
+ import { installHook, uninstallHook } from './hooks/installer.js';
6
+ import { findBinary, installBinary } from './ast-index/binary-manager.js';
7
+ const SMALL_FILE_THRESHOLD = 80;
8
+ const CODE_EXTENSIONS = new Set([
9
+ 'ts', 'tsx', 'js', 'jsx', 'mjs', 'py', 'go', 'rs', 'java', 'kt', 'kts',
10
+ 'swift', 'cs', 'cpp', 'cc', 'cxx', 'hpp', 'c', 'h', 'php', 'rb', 'scala',
11
+ 'dart', 'lua', 'sh', 'bash', 'sql', 'r', 'vue', 'svelte', 'pl', 'pm',
12
+ 'ex', 'exs', 'groovy', 'm', 'proto', 'bsl',
13
+ ]);
14
+ const args = process.argv.slice(2);
15
+ switch (args[0]) {
16
+ case 'hook-read':
17
+ if (!args[1]) {
18
+ console.error('Usage: token-pilot hook-read <file-path>');
19
+ process.exit(1);
20
+ }
21
+ handleHookRead(args[1]);
22
+ break;
23
+ case 'install-hook':
24
+ handleInstallHook(args[1] || process.cwd());
25
+ break;
26
+ case 'uninstall-hook':
27
+ handleUninstallHook(args[1] || process.cwd());
28
+ break;
29
+ case 'install-ast-index':
30
+ handleInstallAstIndex();
31
+ break;
32
+ case '--help':
33
+ case '-h':
34
+ printHelp();
35
+ break;
36
+ default:
37
+ startServer();
38
+ break;
39
+ }
40
+ async function startServer() {
41
+ const projectRoot = args[0] || process.cwd();
42
+ const server = await createServer(projectRoot);
43
+ const transport = new StdioServerTransport();
44
+ await server.connect(transport);
45
+ process.on('SIGINT', async () => {
46
+ await server.close();
47
+ process.exit(0);
48
+ });
49
+ process.on('SIGTERM', async () => {
50
+ await server.close();
51
+ process.exit(0);
52
+ });
53
+ }
54
+ function handleHookRead(filePath) {
55
+ const ext = filePath.split('.').pop()?.toLowerCase() ?? '';
56
+ if (!CODE_EXTENSIONS.has(ext)) {
57
+ process.exit(0);
58
+ }
59
+ try {
60
+ const content = readFileSync(filePath, 'utf-8');
61
+ const lineCount = content.split('\n').length;
62
+ if (lineCount <= SMALL_FILE_THRESHOLD) {
63
+ process.exit(0);
64
+ }
65
+ }
66
+ catch {
67
+ process.exit(0);
68
+ }
69
+ const suggestion = JSON.stringify({
70
+ decision: "suggest",
71
+ message: `Consider using smart_read instead of Read for "${filePath}" — it returns a structural overview saving 80-95% tokens. Use read_symbol to load specific functions/methods.`,
72
+ });
73
+ process.stdout.write(suggestion);
74
+ process.exit(0);
75
+ }
76
+ async function handleInstallHook(projectRoot) {
77
+ const result = await installHook(projectRoot);
78
+ console.log(result.message);
79
+ process.exit(result.installed ? 0 : 1);
80
+ }
81
+ async function handleUninstallHook(projectRoot) {
82
+ const result = await uninstallHook(projectRoot);
83
+ console.log(result.message);
84
+ process.exit(result.removed ? 0 : 1);
85
+ }
86
+ async function handleInstallAstIndex() {
87
+ const status = await findBinary();
88
+ if (status.available) {
89
+ console.log(`ast-index ${status.version} already available at ${status.path} (${status.source})`);
90
+ process.exit(0);
91
+ }
92
+ try {
93
+ const result = await installBinary((msg) => console.log(msg));
94
+ console.log(`\nast-index ${result.version} installed to ${result.path}`);
95
+ process.exit(0);
96
+ }
97
+ catch (err) {
98
+ console.error(`Failed: ${err instanceof Error ? err.message : err}`);
99
+ process.exit(1);
100
+ }
101
+ }
102
+ function printHelp() {
103
+ console.log(`token-pilot — MCP server for token-efficient code reading
104
+
105
+ Usage:
106
+ token-pilot [project-root] Start MCP server (default: cwd)
107
+ token-pilot hook-read <path> PreToolUse hook for Claude Code
108
+ token-pilot install-hook [root] Install hook into .claude/settings.json
109
+ token-pilot uninstall-hook [root] Remove hook from .claude/settings.json
110
+ token-pilot install-ast-index Download ast-index binary (auto on first run)
111
+ token-pilot --help Show this help
112
+
113
+ MCP Tools (14):
114
+ smart_read, read_symbol, read_range, read_diff, smart_read_many,
115
+ search_code, find_usages, find_implementations, class_hierarchy,
116
+ project_overview, export_ast_index, session_analytics, context_status, forget
117
+ `);
118
+ process.exit(0);
119
+ }
120
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface ContextModeStatus {
2
+ detected: boolean;
3
+ source: 'mcp-json' | 'home-mcp-json' | 'config' | 'none';
4
+ toolPrefix: string;
5
+ }
6
+ /**
7
+ * Detect if context-mode MCP plugin is configured alongside Token Pilot.
8
+ *
9
+ * Checks two locations:
10
+ * 1. Project-level .mcp.json (project root)
11
+ * 2. User-level ~/.mcp.json (home dir)
12
+ *
13
+ * Returns detection result with source info.
14
+ */
15
+ export declare function detectContextMode(projectRoot: string, configOverride?: boolean): Promise<ContextModeStatus>;
16
+ //# sourceMappingURL=context-mode-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-mode-detector.d.ts","sourceRoot":"","sources":["../../src/integration/context-mode-detector.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,UAAU,GAAG,eAAe,GAAG,QAAQ,GAAG,MAAM,CAAC;IACzD,UAAU,EAAE,MAAM,CAAC;CACpB;AAID;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC,iBAAiB,CAAC,CAqB5B"}
@@ -0,0 +1,53 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ const TOOL_PREFIX = 'mcp__plugin_context-mode_context-mode__';
4
+ /**
5
+ * Detect if context-mode MCP plugin is configured alongside Token Pilot.
6
+ *
7
+ * Checks two locations:
8
+ * 1. Project-level .mcp.json (project root)
9
+ * 2. User-level ~/.mcp.json (home dir)
10
+ *
11
+ * Returns detection result with source info.
12
+ */
13
+ export async function detectContextMode(projectRoot, configOverride) {
14
+ // Config override takes priority
15
+ if (configOverride === true) {
16
+ return { detected: true, source: 'config', toolPrefix: TOOL_PREFIX };
17
+ }
18
+ if (configOverride === false) {
19
+ return { detected: false, source: 'none', toolPrefix: TOOL_PREFIX };
20
+ }
21
+ // Check project-level .mcp.json
22
+ if (await checkMcpJson(resolve(projectRoot, '.mcp.json'))) {
23
+ return { detected: true, source: 'mcp-json', toolPrefix: TOOL_PREFIX };
24
+ }
25
+ // Check user-level ~/.mcp.json
26
+ const homeDir = process.env.HOME || process.env.USERPROFILE || '';
27
+ if (homeDir && await checkMcpJson(resolve(homeDir, '.mcp.json'))) {
28
+ return { detected: true, source: 'home-mcp-json', toolPrefix: TOOL_PREFIX };
29
+ }
30
+ return { detected: false, source: 'none', toolPrefix: TOOL_PREFIX };
31
+ }
32
+ async function checkMcpJson(path) {
33
+ try {
34
+ const raw = await readFile(path, 'utf-8');
35
+ const config = JSON.parse(raw);
36
+ const servers = config.mcpServers ?? config.servers ?? {};
37
+ // Look for any server entry containing "context-mode" in name or command
38
+ for (const [name, server] of Object.entries(servers)) {
39
+ if (name.includes('context-mode'))
40
+ return true;
41
+ const s = server;
42
+ if (typeof s.command === 'string' && s.command.includes('context-mode'))
43
+ return true;
44
+ if (Array.isArray(s.args) && s.args.some((a) => String(a).includes('context-mode')))
45
+ return true;
46
+ }
47
+ }
48
+ catch {
49
+ // File doesn't exist or is invalid
50
+ }
51
+ return false;
52
+ }
53
+ //# sourceMappingURL=context-mode-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-mode-detector.js","sourceRoot":"","sources":["../../src/integration/context-mode-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,MAAM,WAAW,GAAG,yCAAyC,CAAC;AAE9D;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAAmB,EACnB,cAAwB;IAExB,iCAAiC;IACjC,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;QAC5B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;IACvE,CAAC;IACD,IAAI,cAAc,KAAK,KAAK,EAAE,CAAC;QAC7B,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;IACtE,CAAC;IAED,gCAAgC;IAChC,IAAI,MAAM,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;QAC1D,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;IACzE,CAAC;IAED,+BAA+B;IAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;IAClE,IAAI,OAAO,IAAI,MAAM,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;QACjE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;IAC9E,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;AACtE,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAAY;IACtC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;QAE1D,yEAAyE;QACzE,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACrD,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC/C,MAAM,CAAC,GAAG,MAA6B,CAAC;YACxC,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;gBAAE,OAAO,IAAI,CAAC;YACrF,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;QAC3G,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;IACrC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ export declare function createServer(projectRoot: string): Promise<Server<{
3
+ method: string;
4
+ params?: {
5
+ [x: string]: unknown;
6
+ _meta?: {
7
+ [x: string]: unknown;
8
+ progressToken?: string | number | undefined;
9
+ "io.modelcontextprotocol/related-task"?: {
10
+ taskId: string;
11
+ } | undefined;
12
+ } | undefined;
13
+ } | undefined;
14
+ }, {
15
+ method: string;
16
+ params?: {
17
+ [x: string]: unknown;
18
+ _meta?: {
19
+ [x: string]: unknown;
20
+ progressToken?: string | number | undefined;
21
+ "io.modelcontextprotocol/related-task"?: {
22
+ taskId: string;
23
+ } | undefined;
24
+ } | undefined;
25
+ } | undefined;
26
+ }, {
27
+ [x: string]: unknown;
28
+ _meta?: {
29
+ [x: string]: unknown;
30
+ progressToken?: string | number | undefined;
31
+ "io.modelcontextprotocol/related-task"?: {
32
+ taskId: string;
33
+ } | undefined;
34
+ } | undefined;
35
+ }>>;
36
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AA2CnE,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAiWrD"}