token-pilot 0.14.2 → 0.16.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 (39) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +25 -8
  3. package/dist/ast-index/client.d.ts +2 -89
  4. package/dist/ast-index/client.js +49 -742
  5. package/dist/ast-index/enricher.d.ts +10 -0
  6. package/dist/ast-index/enricher.js +202 -0
  7. package/dist/ast-index/parser.d.ts +31 -0
  8. package/dist/ast-index/parser.js +340 -0
  9. package/dist/ast-index/regex-parser-python.d.ts +8 -0
  10. package/dist/ast-index/regex-parser-python.js +132 -0
  11. package/dist/ast-index/regex-parser.d.ts +8 -0
  12. package/dist/ast-index/regex-parser.js +118 -0
  13. package/dist/config/defaults.js +1 -0
  14. package/dist/core/session-analytics.d.ts +2 -2
  15. package/dist/core/session-analytics.js +78 -61
  16. package/dist/core/symbol-resolver.d.ts +0 -1
  17. package/dist/core/symbol-resolver.js +3 -12
  18. package/dist/core/validation.d.ts +12 -0
  19. package/dist/core/validation.js +62 -2
  20. package/dist/handlers/code-audit.js +2 -2
  21. package/dist/handlers/find-unused.js +1 -1
  22. package/dist/handlers/find-usages.d.ts +1 -1
  23. package/dist/handlers/find-usages.js +93 -25
  24. package/dist/handlers/read-for-edit.d.ts +1 -0
  25. package/dist/handlers/read-for-edit.js +65 -0
  26. package/dist/handlers/read-symbols.d.ts +18 -0
  27. package/dist/handlers/read-symbols.js +142 -0
  28. package/dist/handlers/smart-diff.js +23 -0
  29. package/dist/handlers/smart-read.js +14 -1
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.js +6 -5
  32. package/dist/server/token-estimates.d.ts +31 -0
  33. package/dist/server/token-estimates.js +204 -0
  34. package/dist/server/tool-definitions.d.ts +1070 -0
  35. package/dist/server/tool-definitions.js +316 -0
  36. package/dist/server.js +23 -480
  37. package/dist/types.d.ts +1 -0
  38. package/package.json +1 -1
  39. package/skills/guide/SKILL.md +64 -0
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Token estimation functions for analytics.
3
+ * Used to calculate "tokens would be" for honest savings reporting.
4
+ */
5
+ import type { FileCache } from '../core/file-cache.js';
6
+ import type { SavingsCategory } from '../core/session-analytics.js';
7
+ /**
8
+ * Creates token estimation functions bound to a project context.
9
+ * Uses getter for projectRoot since it may change on auto-detect.
10
+ */
11
+ export declare function createTokenEstimates(getProjectRoot: () => string, fileCache: FileCache): {
12
+ fullFileTokens: (relativePath: string) => Promise<number>;
13
+ estimateProjectOverviewWorkflowTokens: (includeSections: Array<"stack" | "ci" | "quality" | "architecture">) => Promise<number>;
14
+ estimateOutlineWorkflowTokens: (relativePath: string, recursive: boolean, maxDepth: number) => Promise<number>;
15
+ estimateRelatedFilesWorkflowTokens: (targetPath: string, meta?: {
16
+ imports?: string[];
17
+ importedBy?: string[];
18
+ tests?: string[];
19
+ }) => Promise<number>;
20
+ estimateFindUsagesWorkflowTokens: (files: string[]) => Promise<number>;
21
+ estimateExploreAreaWorkflowTokens: (meta: {
22
+ codeFiles?: string[];
23
+ testFiles?: string[];
24
+ internalDeps?: string[];
25
+ importedBy?: string[];
26
+ externalDeps?: string[];
27
+ changeCount?: number;
28
+ }) => Promise<number>;
29
+ detectSavingsCategory: (text: string) => SavingsCategory;
30
+ };
31
+ //# sourceMappingURL=token-estimates.d.ts.map
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Token estimation functions for analytics.
3
+ * Used to calculate "tokens would be" for honest savings reporting.
4
+ */
5
+ import { estimateTokens } from '../core/token-estimator.js';
6
+ import { resolveSafePath } from '../core/validation.js';
7
+ import { CODE_EXTENSIONS } from '../handlers/outline.js';
8
+ /**
9
+ * Creates token estimation functions bound to a project context.
10
+ * Uses getter for projectRoot since it may change on auto-detect.
11
+ */
12
+ export function createTokenEstimates(getProjectRoot, fileCache) {
13
+ async function fullFileTokens(relativePath) {
14
+ try {
15
+ const absPath = resolveSafePath(getProjectRoot(), relativePath);
16
+ const cached = fileCache.get(absPath);
17
+ if (cached)
18
+ return estimateTokens(cached.content);
19
+ const { readFile: readFileAsync } = await import('node:fs/promises');
20
+ const content = await readFileAsync(absPath, 'utf-8');
21
+ return estimateTokens(content);
22
+ }
23
+ catch {
24
+ return 0;
25
+ }
26
+ }
27
+ async function estimateProjectOverviewWorkflowTokens(includeSections) {
28
+ const sectionFiles = {
29
+ stack: ['package.json', 'composer.json', 'Cargo.toml', 'pyproject.toml', 'go.mod'],
30
+ ci: ['.gitlab-ci.yml', 'Jenkinsfile', '.circleci/config.yml', 'bitbucket-pipelines.yml', '.travis.yml'],
31
+ quality: [
32
+ 'tsconfig.json',
33
+ 'vitest.config.ts',
34
+ 'vitest.config.js',
35
+ 'vitest.config.mts',
36
+ 'jest.config.js',
37
+ 'jest.config.ts',
38
+ 'jest.config.mjs',
39
+ 'eslint.config.js',
40
+ 'eslint.config.mjs',
41
+ '.eslintrc',
42
+ '.eslintrc.js',
43
+ '.eslintrc.json',
44
+ '.eslintrc.yml',
45
+ 'biome.json',
46
+ 'biome.jsonc',
47
+ '.prettierrc',
48
+ '.prettierrc.js',
49
+ '.prettierrc.json',
50
+ 'prettier.config.js',
51
+ 'phpunit.xml',
52
+ 'phpunit.xml.dist',
53
+ 'phpstan.neon',
54
+ 'phpstan.neon.dist',
55
+ ],
56
+ architecture: ['README.md'],
57
+ };
58
+ let total = 0;
59
+ const seen = new Set();
60
+ for (const section of includeSections) {
61
+ for (const file of sectionFiles[section]) {
62
+ if (seen.has(file))
63
+ continue;
64
+ seen.add(file);
65
+ total += await fullFileTokens(file);
66
+ }
67
+ }
68
+ if (includeSections.includes('ci')) {
69
+ try {
70
+ const { readdir: readDirAsync } = await import('node:fs/promises');
71
+ const workflowDir = resolveSafePath(getProjectRoot(), '.github/workflows');
72
+ const workflowFiles = await readDirAsync(workflowDir, { withFileTypes: true });
73
+ for (const file of workflowFiles) {
74
+ if (!file.isFile())
75
+ continue;
76
+ if (!file.name.endsWith('.yml') && !file.name.endsWith('.yaml'))
77
+ continue;
78
+ total += await fullFileTokens(`.github/workflows/${file.name}`);
79
+ }
80
+ }
81
+ catch {
82
+ // ignore missing workflows dir
83
+ }
84
+ }
85
+ if (includeSections.includes('architecture')) {
86
+ total += 200;
87
+ }
88
+ return total;
89
+ }
90
+ async function estimateOutlineWorkflowTokens(relativePath, recursive, maxDepth) {
91
+ const SAMPLE_LIMIT = 30;
92
+ try {
93
+ const { readdir: readDirAsync } = await import('node:fs/promises');
94
+ const { resolve: resolvePath } = await import('node:path');
95
+ const absDir = resolveSafePath(getProjectRoot(), relativePath);
96
+ const sampledFiles = [];
97
+ let totalFiles = 0;
98
+ async function walk(dirPath, depth) {
99
+ const entries = await readDirAsync(dirPath, { withFileTypes: true });
100
+ for (const entry of entries) {
101
+ if (entry.isFile()) {
102
+ const ext = entry.name.split('.').pop()?.toLowerCase() ?? '';
103
+ if (!CODE_EXTENSIONS.has(ext))
104
+ continue;
105
+ totalFiles++;
106
+ if (sampledFiles.length < SAMPLE_LIMIT) {
107
+ sampledFiles.push(resolvePath(dirPath, entry.name));
108
+ }
109
+ continue;
110
+ }
111
+ if (entry.isDirectory() && recursive && depth < maxDepth) {
112
+ await walk(resolvePath(dirPath, entry.name), depth + 1);
113
+ }
114
+ }
115
+ }
116
+ await walk(absDir, 0);
117
+ if (totalFiles === 0)
118
+ return 0;
119
+ let sampledTokens = 0;
120
+ const projectRoot = getProjectRoot();
121
+ for (const filePath of sampledFiles) {
122
+ const relPath = filePath.startsWith(projectRoot)
123
+ ? filePath.slice(projectRoot.length + 1)
124
+ : filePath;
125
+ sampledTokens += await fullFileTokens(relPath);
126
+ }
127
+ if (sampledFiles.length === 0 || sampledTokens === 0)
128
+ return 0;
129
+ if (sampledFiles.length === totalFiles)
130
+ return sampledTokens;
131
+ const averageTokens = sampledTokens / sampledFiles.length;
132
+ return Math.round(averageTokens * totalFiles);
133
+ }
134
+ catch {
135
+ return 0;
136
+ }
137
+ }
138
+ async function estimateRelatedFilesWorkflowTokens(targetPath, meta) {
139
+ const related = new Set([targetPath]);
140
+ for (const path of meta?.imports ?? [])
141
+ related.add(path);
142
+ for (const path of meta?.importedBy ?? [])
143
+ related.add(path);
144
+ for (const path of meta?.tests ?? [])
145
+ related.add(path);
146
+ let total = 0;
147
+ let counted = 0;
148
+ for (const path of related) {
149
+ total += await fullFileTokens(path);
150
+ counted++;
151
+ if (counted >= 12)
152
+ break;
153
+ }
154
+ return total;
155
+ }
156
+ async function estimateFindUsagesWorkflowTokens(files) {
157
+ let total = 0;
158
+ let counted = 0;
159
+ for (const file of files) {
160
+ total += await fullFileTokens(file);
161
+ counted++;
162
+ if (counted >= 20)
163
+ break;
164
+ }
165
+ return total;
166
+ }
167
+ async function estimateExploreAreaWorkflowTokens(meta) {
168
+ const localFiles = new Set();
169
+ for (const file of meta.codeFiles ?? [])
170
+ localFiles.add(file);
171
+ for (const file of meta.testFiles ?? [])
172
+ localFiles.add(file);
173
+ for (const file of meta.internalDeps ?? [])
174
+ localFiles.add(file);
175
+ for (const file of meta.importedBy ?? [])
176
+ localFiles.add(file);
177
+ let total = 0;
178
+ let counted = 0;
179
+ for (const file of localFiles) {
180
+ total += await fullFileTokens(file);
181
+ counted++;
182
+ if (counted >= 24)
183
+ break;
184
+ }
185
+ total += (meta.externalDeps?.length ?? 0) * 30;
186
+ total += (meta.changeCount ?? 0) * 40;
187
+ return total;
188
+ }
189
+ function detectSavingsCategory(text) {
190
+ if (text.startsWith('REMINDER:') || text.startsWith('DEDUP:'))
191
+ return 'dedup';
192
+ return 'compression';
193
+ }
194
+ return {
195
+ fullFileTokens,
196
+ estimateProjectOverviewWorkflowTokens,
197
+ estimateOutlineWorkflowTokens,
198
+ estimateRelatedFilesWorkflowTokens,
199
+ estimateFindUsagesWorkflowTokens,
200
+ estimateExploreAreaWorkflowTokens,
201
+ detectSavingsCategory,
202
+ };
203
+ }
204
+ //# sourceMappingURL=token-estimates.js.map