skannr 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/.eslintrc.js +22 -0
  2. package/README.md +109 -0
  3. package/dist/agent-cli.d.ts +7 -0
  4. package/dist/agent-cli.d.ts.map +1 -0
  5. package/dist/agent-cli.js +364 -0
  6. package/dist/agent-cli.js.map +1 -0
  7. package/dist/agent.d.ts +115 -0
  8. package/dist/agent.d.ts.map +1 -0
  9. package/dist/agent.js +340 -0
  10. package/dist/agent.js.map +1 -0
  11. package/dist/benchmark.d.ts +53 -0
  12. package/dist/benchmark.d.ts.map +1 -0
  13. package/dist/benchmark.js +307 -0
  14. package/dist/benchmark.js.map +1 -0
  15. package/dist/cache.d.ts +97 -0
  16. package/dist/cache.d.ts.map +1 -0
  17. package/dist/cache.js +284 -0
  18. package/dist/cache.js.map +1 -0
  19. package/dist/cli.d.ts +6 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +238 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/config.d.ts +8 -0
  24. package/dist/config.d.ts.map +1 -0
  25. package/dist/config.js +52 -0
  26. package/dist/config.js.map +1 -0
  27. package/dist/index.d.ts +18 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +176 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/languages/GenericAdapter.d.ts +10 -0
  32. package/dist/languages/GenericAdapter.d.ts.map +1 -0
  33. package/dist/languages/GenericAdapter.js +41 -0
  34. package/dist/languages/GenericAdapter.js.map +1 -0
  35. package/dist/languages/LanguageAdapter.d.ts +14 -0
  36. package/dist/languages/LanguageAdapter.d.ts.map +1 -0
  37. package/dist/languages/LanguageAdapter.js +3 -0
  38. package/dist/languages/LanguageAdapter.js.map +1 -0
  39. package/dist/languages/PythonAdapter.d.ts +10 -0
  40. package/dist/languages/PythonAdapter.d.ts.map +1 -0
  41. package/dist/languages/PythonAdapter.js +98 -0
  42. package/dist/languages/PythonAdapter.js.map +1 -0
  43. package/dist/languages/TypeScriptAdapter.d.ts +17 -0
  44. package/dist/languages/TypeScriptAdapter.d.ts.map +1 -0
  45. package/dist/languages/TypeScriptAdapter.js +321 -0
  46. package/dist/languages/TypeScriptAdapter.js.map +1 -0
  47. package/dist/languages/registry.d.ts +4 -0
  48. package/dist/languages/registry.d.ts.map +1 -0
  49. package/dist/languages/registry.js +86 -0
  50. package/dist/languages/registry.js.map +1 -0
  51. package/dist/mapper.d.ts +49 -0
  52. package/dist/mapper.d.ts.map +1 -0
  53. package/dist/mapper.js +386 -0
  54. package/dist/mapper.js.map +1 -0
  55. package/dist/ranker-enhanced.d.ts +37 -0
  56. package/dist/ranker-enhanced.d.ts.map +1 -0
  57. package/dist/ranker-enhanced.js +395 -0
  58. package/dist/ranker-enhanced.js.map +1 -0
  59. package/dist/ranker.d.ts +14 -0
  60. package/dist/ranker.d.ts.map +1 -0
  61. package/dist/ranker.js +105 -0
  62. package/dist/ranker.js.map +1 -0
  63. package/dist/rocket-chat-scope.d.ts +7 -0
  64. package/dist/rocket-chat-scope.d.ts.map +1 -0
  65. package/dist/rocket-chat-scope.js +95 -0
  66. package/dist/rocket-chat-scope.js.map +1 -0
  67. package/dist/scanner.d.ts +16 -0
  68. package/dist/scanner.d.ts.map +1 -0
  69. package/dist/scanner.js +228 -0
  70. package/dist/scanner.js.map +1 -0
  71. package/dist/skeletonizer.d.ts +5 -0
  72. package/dist/skeletonizer.d.ts.map +1 -0
  73. package/dist/skeletonizer.js +52 -0
  74. package/dist/skeletonizer.js.map +1 -0
  75. package/dist/tokenizer.d.ts +9 -0
  76. package/dist/tokenizer.d.ts.map +1 -0
  77. package/dist/tokenizer.js +21 -0
  78. package/dist/tokenizer.js.map +1 -0
  79. package/dist/types.d.ts +68 -0
  80. package/dist/types.d.ts.map +1 -0
  81. package/dist/types.js +6 -0
  82. package/dist/types.js.map +1 -0
  83. package/gemini-extension/GEMINI.md +26 -0
  84. package/gemini-extension/gemini-extension.json +12 -0
  85. package/gemini-extension/package.json +14 -0
  86. package/gemini-extension/src/server.ts +63 -0
  87. package/gemini-extension/tsconfig.json +14 -0
  88. package/jest.config.js +5 -0
  89. package/package.json +46 -0
  90. package/src/agent-cli.ts +383 -0
  91. package/src/agent.ts +344 -0
  92. package/src/benchmark.ts +389 -0
  93. package/src/cache.ts +317 -0
  94. package/src/cli.ts +223 -0
  95. package/src/config.ts +22 -0
  96. package/src/index.ts +215 -0
  97. package/src/languages/GenericAdapter.ts +44 -0
  98. package/src/languages/LanguageAdapter.ts +14 -0
  99. package/src/languages/PythonAdapter.ts +74 -0
  100. package/src/languages/TypeScriptAdapter.ts +338 -0
  101. package/src/languages/registry.ts +49 -0
  102. package/src/mapper.ts +448 -0
  103. package/src/ranker-enhanced.ts +460 -0
  104. package/src/ranker.ts +92 -0
  105. package/src/scanner.ts +201 -0
  106. package/src/skeletonizer.ts +16 -0
  107. package/src/tokenizer.ts +20 -0
  108. package/src/types.ts +71 -0
  109. package/tests/agent.tools.test.ts +81 -0
  110. package/tests/benchmark.test.ts +31 -0
  111. package/tests/fixtures/sample.py +17 -0
  112. package/tests/fixtures/sample.ts +13 -0
  113. package/tests/fixtures/src/api/routes.ts +1 -0
  114. package/tests/fixtures/src/auth/permission.ts +3 -0
  115. package/tests/ranker-enhanced.test.ts +68 -0
  116. package/tests/ranker.test.ts +75 -0
  117. package/tests/scanner.scope.test.ts +41 -0
  118. package/tests/setup-fixtures.js +29 -0
  119. package/tests/skeletonizer.test.ts +142 -0
  120. package/tsconfig.json +21 -0
  121. package/uca-landing/index.html +17 -0
  122. package/uca-landing/package.json +23 -0
  123. package/uca-landing/postcss.config.js +6 -0
  124. package/uca-landing/src/App.jsx +43 -0
  125. package/uca-landing/src/components/AgentMode.jsx +45 -0
  126. package/uca-landing/src/components/CliReference.jsx +49 -0
  127. package/uca-landing/src/components/Features.jsx +63 -0
  128. package/uca-landing/src/components/Footer.jsx +35 -0
  129. package/uca-landing/src/components/Hero.jsx +124 -0
  130. package/uca-landing/src/components/HowItWorks.jsx +60 -0
  131. package/uca-landing/src/components/Install.jsx +90 -0
  132. package/uca-landing/src/components/LanguageSupport.jsx +63 -0
  133. package/uca-landing/src/components/Navbar.jsx +86 -0
  134. package/uca-landing/src/components/Problem.jsx +51 -0
  135. package/uca-landing/src/components/Reveal.jsx +40 -0
  136. package/uca-landing/src/components/WorksWith.jsx +59 -0
  137. package/uca-landing/src/hooks/useScrollNav.js +13 -0
  138. package/uca-landing/src/hooks/useTypewriter.js +41 -0
  139. package/uca-landing/src/index.css +13 -0
  140. package/uca-landing/src/main.jsx +10 -0
  141. package/uca-landing/tailwind.config.js +68 -0
  142. package/uca-landing/vite.config.js +6 -0
package/src/mapper.ts ADDED
@@ -0,0 +1,448 @@
1
+ /**
2
+ * Symbol mapping system for on-demand code retrieval
3
+ * Tracks locations of all code blocks that were trimmed in skeletons
4
+ */
5
+
6
+ import { Project, SourceFile, SyntaxKind } from 'ts-morph';
7
+ import * as path from 'path';
8
+ import * as fs from 'fs';
9
+
10
+ export interface SymbolLocation {
11
+ symbolId: string;
12
+ symbolName: string;
13
+ symbolType: 'function' | 'method' | 'constructor' | 'arrow-function' | 'variable';
14
+ filePath: string;
15
+ startLine: number;
16
+ endLine: number;
17
+ startPos: number;
18
+ endPos: number;
19
+ parentClass?: string;
20
+ signature?: string;
21
+ }
22
+
23
+ export interface SymbolMapping {
24
+ generatedAt: string;
25
+ rootPath: string;
26
+ files: {
27
+ [filePath: string]: {
28
+ originalPath: string;
29
+ symbols: SymbolLocation[];
30
+ };
31
+ };
32
+ }
33
+
34
+ /**
35
+ * Build skeleton with symbol mapping for on-demand retrieval
36
+ */
37
+ export function buildSkeletonWithMapping(
38
+ filePath: string,
39
+ rootPath: string
40
+ ): { skeleton: string; symbols: SymbolLocation[] } {
41
+ const symbols: SymbolLocation[] = [];
42
+
43
+ try {
44
+ const project = new Project({
45
+ skipAddingFilesFromTsConfig: true,
46
+ compilerOptions: {
47
+ allowJs: true,
48
+ checkJs: false,
49
+ },
50
+ });
51
+
52
+ const sourceFile = project.addSourceFileAtPath(filePath);
53
+ const skeleton = generateSkeletonWithMapping(sourceFile, filePath, symbols, rootPath);
54
+
55
+ return { skeleton, symbols };
56
+ } catch (error) {
57
+ return {
58
+ skeleton: `/* Failed to parse file: ${error instanceof Error ? error.message : 'Unknown error'} */`,
59
+ symbols: [],
60
+ };
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Generate skeleton and populate symbol mapping
66
+ */
67
+ function generateSkeletonWithMapping(
68
+ sourceFile: SourceFile,
69
+ filePath: string,
70
+ symbols: SymbolLocation[],
71
+ rootPath: string
72
+ ): string {
73
+ const lines: string[] = [];
74
+ const fileName = path.basename(filePath);
75
+
76
+ lines.push(`/* Skeleton of ${fileName} - Generated with symbol mapping */\n`);
77
+
78
+ // Imports
79
+ const imports = sourceFile.getImportDeclarations();
80
+ for (const imp of imports) {
81
+ lines.push(imp.getText());
82
+ }
83
+ if (imports.length > 0) lines.push('');
84
+
85
+ // Classes
86
+ const classes = sourceFile.getClasses();
87
+ for (const cls of classes) {
88
+ lines.push(processClassWithMapping(cls, filePath, symbols, rootPath));
89
+ lines.push('');
90
+ }
91
+
92
+ // Interfaces (no mapping needed - no implementation)
93
+ const interfaces = sourceFile.getInterfaces();
94
+ for (const iface of interfaces) {
95
+ lines.push(iface.getText());
96
+ lines.push('');
97
+ }
98
+
99
+ // Type aliases
100
+ const typeAliases = sourceFile.getTypeAliases();
101
+ for (const typeAlias of typeAliases) {
102
+ lines.push(typeAlias.getText());
103
+ lines.push('');
104
+ }
105
+
106
+ // Enums
107
+ const enums = sourceFile.getEnums();
108
+ for (const enumDecl of enums) {
109
+ lines.push(enumDecl.getText());
110
+ lines.push('');
111
+ }
112
+
113
+ // Top-level functions
114
+ const functions = sourceFile.getFunctions();
115
+ for (const func of functions) {
116
+ lines.push(processFunctionWithMapping(func, filePath, symbols, rootPath));
117
+ lines.push('');
118
+ }
119
+
120
+ // Variables (including arrow functions)
121
+ const variables = sourceFile.getVariableStatements();
122
+ for (const varStatement of variables) {
123
+ lines.push(processVariableStatementWithMapping(varStatement, filePath, symbols, rootPath));
124
+ lines.push('');
125
+ }
126
+
127
+ // Export declarations
128
+ const exportDeclarations = sourceFile.getExportDeclarations();
129
+ for (const exportDecl of exportDeclarations) {
130
+ lines.push(exportDecl.getText());
131
+ }
132
+
133
+ const exportAssignments = sourceFile.getExportAssignments();
134
+ for (const exportAssign of exportAssignments) {
135
+ lines.push(exportAssign.getText());
136
+ }
137
+
138
+ return lines.join('\n').trim();
139
+ }
140
+
141
+ /**
142
+ * Process class and map methods
143
+ */
144
+ function processClassWithMapping(
145
+ cls: any,
146
+ filePath: string,
147
+ symbols: SymbolLocation[],
148
+ rootPath: string
149
+ ): string {
150
+ const lines: string[] = [];
151
+ const className = cls.getName() || 'Anonymous';
152
+
153
+ const modifiers = cls.getModifiers().map((m: any) => m.getText()).join(' ');
154
+ let classDecl = modifiers ? `${modifiers} class` : 'class';
155
+ classDecl += ` ${className}`;
156
+
157
+ const typeParams = cls.getTypeParameters();
158
+ if (typeParams.length > 0) {
159
+ classDecl += `<${typeParams.map((tp: any) => tp.getText()).join(', ')}>`;
160
+ }
161
+
162
+ const extendsClause = cls.getExtends();
163
+ if (extendsClause) {
164
+ classDecl += ` extends ${extendsClause.getText()}`;
165
+ }
166
+
167
+ const implementsClauses = cls.getImplements();
168
+ if (implementsClauses.length > 0) {
169
+ classDecl += ` implements ${implementsClauses.map((ic: any) => ic.getText()).join(', ')}`;
170
+ }
171
+
172
+ classDecl += ' {';
173
+ lines.push(classDecl);
174
+
175
+ // Properties
176
+ const properties = cls.getProperties();
177
+ for (const prop of properties) {
178
+ const propModifiers = prop.getModifiers().map((m: any) => m.getText()).join(' ');
179
+ const propName = prop.getName();
180
+ const propType = prop.getType().getText();
181
+ const propLine = propModifiers
182
+ ? ` ${propModifiers} ${propName}: ${propType};`
183
+ : ` ${propName}: ${propType};`;
184
+ lines.push(propLine);
185
+ }
186
+ if (properties.length > 0) lines.push('');
187
+
188
+ // Methods
189
+ const methods = cls.getMethods();
190
+ for (const method of methods) {
191
+ const methodName = method.getName();
192
+ const symbolId = `${className}.${methodName}`;
193
+
194
+ // Record symbol location
195
+ const startLineNum = method.getStartLineNumber();
196
+ const endLineNum = method.getEndLineNumber();
197
+ const startPos = method.getStart();
198
+ const endPos = method.getEnd();
199
+
200
+ symbols.push({
201
+ symbolId,
202
+ symbolName: methodName,
203
+ symbolType: 'method',
204
+ filePath: path.relative(rootPath, filePath),
205
+ startLine: startLineNum,
206
+ endLine: endLineNum,
207
+ startPos,
208
+ endPos,
209
+ parentClass: className,
210
+ signature: method.getText().split('{')[0].trim(),
211
+ });
212
+
213
+ lines.push(processMethodSignature(method, symbolId));
214
+ }
215
+
216
+ // Constructors
217
+ const constructors = cls.getConstructors();
218
+ for (const ctor of constructors) {
219
+ const symbolId = `${className}.constructor`;
220
+
221
+ const startLineNum = ctor.getStartLineNumber();
222
+ const endLineNum = ctor.getEndLineNumber();
223
+
224
+ symbols.push({
225
+ symbolId,
226
+ symbolName: 'constructor',
227
+ symbolType: 'constructor',
228
+ filePath: path.relative(rootPath, filePath),
229
+ startLine: startLineNum,
230
+ endLine: endLineNum,
231
+ startPos: ctor.getStart(),
232
+ endPos: ctor.getEnd(),
233
+ parentClass: className,
234
+ });
235
+
236
+ lines.push(processConstructorSignature(ctor, symbolId));
237
+ }
238
+
239
+ lines.push('}');
240
+ return lines.join('\n');
241
+ }
242
+
243
+ /**
244
+ * Process method signature with symbol placeholder
245
+ */
246
+ function processMethodSignature(method: any, symbolId: string): string {
247
+ const lines: string[] = [];
248
+
249
+ const modifiers = method.getModifiers().map((m: any) => m.getText()).join(' ');
250
+ const name = method.getName();
251
+ const params = method.getParameters()
252
+ .map((p: any) => {
253
+ const pName = p.getName();
254
+ const pType = p.getType().getText();
255
+ const optional = p.isOptional() ? '?' : '';
256
+ return `${pName}${optional}: ${pType}`;
257
+ })
258
+ .join(', ');
259
+ const returnType = method.getReturnType().getText();
260
+
261
+ let signature = modifiers ? ` ${modifiers} ${name}` : ` ${name}`;
262
+ signature += `(${params}): ${returnType} {`;
263
+ lines.push(signature);
264
+ lines.push(` /* [SYMBOL:${symbolId}] - Implementation available via get_symbol_details */`);
265
+ lines.push(' }');
266
+ lines.push('');
267
+
268
+ return lines.join('\n');
269
+ }
270
+
271
+ /**
272
+ * Process constructor signature
273
+ */
274
+ function processConstructorSignature(ctor: any, symbolId: string): string {
275
+ const lines: string[] = [];
276
+
277
+ const params = ctor.getParameters()
278
+ .map((p: any) => {
279
+ const modifiers = p.getModifiers().map((m: any) => m.getText()).join(' ');
280
+ const pName = p.getName();
281
+ const pType = p.getType().getText();
282
+ const optional = p.isOptional() ? '?' : '';
283
+ const paramStr = `${pName}${optional}: ${pType}`;
284
+ return modifiers ? `${modifiers} ${paramStr}` : paramStr;
285
+ })
286
+ .join(', ');
287
+
288
+ lines.push(` constructor(${params}) {`);
289
+ lines.push(` /* [SYMBOL:${symbolId}] - Implementation available via get_symbol_details */`);
290
+ lines.push(' }');
291
+ lines.push('');
292
+
293
+ return lines.join('\n');
294
+ }
295
+
296
+ /**
297
+ * Process function with mapping
298
+ */
299
+ function processFunctionWithMapping(
300
+ func: any,
301
+ filePath: string,
302
+ symbols: SymbolLocation[],
303
+ rootPath: string
304
+ ): string {
305
+ const lines: string[] = [];
306
+ const funcName = func.getName() || 'anonymous';
307
+ const symbolId = funcName;
308
+
309
+ // Record symbol
310
+ symbols.push({
311
+ symbolId,
312
+ symbolName: funcName,
313
+ symbolType: 'function',
314
+ filePath: path.relative(rootPath, filePath),
315
+ startLine: func.getStartLineNumber(),
316
+ endLine: func.getEndLineNumber(),
317
+ startPos: func.getStart(),
318
+ endPos: func.getEnd(),
319
+ signature: func.getText().split('{')[0].trim(),
320
+ });
321
+
322
+ const modifiers = func.getModifiers().map((m: any) => m.getText()).join(' ');
323
+ const params = func.getParameters()
324
+ .map((p: any) => {
325
+ const pName = p.getName();
326
+ const pType = p.getType().getText();
327
+ const optional = p.isOptional() ? '?' : '';
328
+ return `${pName}${optional}: ${pType}`;
329
+ })
330
+ .join(', ');
331
+ const returnType = func.getReturnType().getText();
332
+
333
+ let signature = modifiers ? `${modifiers} function` : 'function';
334
+ signature += ` ${funcName}(${params}): ${returnType} {`;
335
+ lines.push(signature);
336
+ lines.push(` /* [SYMBOL:${symbolId}] - Implementation available via get_symbol_details */`);
337
+ lines.push('}');
338
+
339
+ return lines.join('\n');
340
+ }
341
+
342
+ /**
343
+ * Process variable statements (handles arrow functions)
344
+ */
345
+ function processVariableStatementWithMapping(
346
+ varStatement: any,
347
+ filePath: string,
348
+ symbols: SymbolLocation[],
349
+ rootPath: string
350
+ ): string {
351
+ const lines: string[] = [];
352
+
353
+ const modifiers = varStatement.getModifiers().map((m: any) => m.getText()).join(' ');
354
+ const declarations = varStatement.getDeclarations();
355
+ const declarationKind = varStatement.getDeclarationKind();
356
+
357
+ for (const decl of declarations) {
358
+ const name = decl.getName();
359
+ const type = decl.getType().getText();
360
+ const initializer = decl.getInitializer();
361
+
362
+ if (initializer) {
363
+ const initText = initializer.getText();
364
+
365
+ // Check if it's an arrow function
366
+ if (initText.includes('=>') || initializer.getKind() === SyntaxKind.ArrowFunction) {
367
+ const symbolId = name;
368
+
369
+ symbols.push({
370
+ symbolId,
371
+ symbolName: name,
372
+ symbolType: 'arrow-function',
373
+ filePath: path.relative(rootPath, filePath),
374
+ startLine: decl.getStartLineNumber(),
375
+ endLine: decl.getEndLineNumber(),
376
+ startPos: decl.getStart(),
377
+ endPos: decl.getEnd(),
378
+ signature: `${declarationKind} ${name}: ${type}`,
379
+ });
380
+
381
+ const line = modifiers
382
+ ? `${modifiers} ${declarationKind} ${name}: ${type} = /* [SYMBOL:${symbolId}] */;`
383
+ : `${declarationKind} ${name}: ${type} = /* [SYMBOL:${symbolId}] */;`;
384
+ lines.push(line);
385
+ } else if (initText.length < 50 && !initText.includes('{')) {
386
+ // Simple value - keep it
387
+ const line = modifiers
388
+ ? `${modifiers} ${declarationKind} ${name}: ${type} = ${initText};`
389
+ : `${declarationKind} ${name}: ${type} = ${initText};`;
390
+ lines.push(line);
391
+ } else {
392
+ // Complex value - stub it
393
+ const line = modifiers
394
+ ? `${modifiers} ${declarationKind} ${name}: ${type} = /* trimmed */;`
395
+ : `${declarationKind} ${name}: ${type} = /* trimmed */;`;
396
+ lines.push(line);
397
+ }
398
+ } else {
399
+ const line = modifiers
400
+ ? `${modifiers} ${declarationKind} ${name}: ${type};`
401
+ : `${declarationKind} ${name}: ${type};`;
402
+ lines.push(line);
403
+ }
404
+ }
405
+
406
+ return lines.join('\n');
407
+ }
408
+
409
+ /**
410
+ * Get symbol details by ID from mapping
411
+ */
412
+ export function getSymbolDetails(
413
+ symbolId: string,
414
+ mapping: SymbolMapping
415
+ ): { content: string; location: SymbolLocation } | null {
416
+ for (const fileInfo of Object.values(mapping.files)) {
417
+ const symbol = fileInfo.symbols.find(s => s.symbolId === symbolId);
418
+ if (symbol) {
419
+ const fullPath = path.join(mapping.rootPath, symbol.filePath);
420
+ const fileContent = fs.readFileSync(fullPath, 'utf-8');
421
+ const lines = fileContent.split('\n');
422
+ const symbolContent = lines
423
+ .slice(symbol.startLine - 1, symbol.endLine)
424
+ .join('\n');
425
+
426
+ return {
427
+ content: symbolContent,
428
+ location: symbol,
429
+ };
430
+ }
431
+ }
432
+ return null;
433
+ }
434
+
435
+ /**
436
+ * Save mapping to JSON file
437
+ */
438
+ export function saveMappingToFile(mapping: SymbolMapping, outputPath: string): void {
439
+ fs.writeFileSync(outputPath, JSON.stringify(mapping, null, 2), 'utf-8');
440
+ }
441
+
442
+ /**
443
+ * Load mapping from JSON file
444
+ */
445
+ export function loadMappingFromFile(mappingPath: string): SymbolMapping {
446
+ const content = fs.readFileSync(mappingPath, 'utf-8');
447
+ return JSON.parse(content);
448
+ }