@cliperhq/cliper 1.0.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 (68) hide show
  1. package/README.md +266 -0
  2. package/dist/commands/analyze.d.ts +6 -0
  3. package/dist/commands/analyze.d.ts.map +1 -0
  4. package/dist/commands/analyze.js +216 -0
  5. package/dist/commands/export.d.ts +6 -0
  6. package/dist/commands/export.d.ts.map +1 -0
  7. package/dist/commands/export.js +64 -0
  8. package/dist/commands/init.d.ts +7 -0
  9. package/dist/commands/init.d.ts.map +1 -0
  10. package/dist/commands/init.js +173 -0
  11. package/dist/commands/scope.d.ts +2 -0
  12. package/dist/commands/scope.d.ts.map +1 -0
  13. package/dist/commands/scope.js +124 -0
  14. package/dist/commands/status.d.ts +2 -0
  15. package/dist/commands/status.d.ts.map +1 -0
  16. package/dist/commands/status.js +100 -0
  17. package/dist/commands/sync.d.ts +6 -0
  18. package/dist/commands/sync.d.ts.map +1 -0
  19. package/dist/commands/sync.js +83 -0
  20. package/dist/context/builder.d.ts +19 -0
  21. package/dist/context/builder.d.ts.map +1 -0
  22. package/dist/context/builder.js +143 -0
  23. package/dist/gaps/detector.d.ts +10 -0
  24. package/dist/gaps/detector.d.ts.map +1 -0
  25. package/dist/gaps/detector.js +139 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +48 -0
  29. package/dist/resolver/urlFetcher.d.ts +9 -0
  30. package/dist/resolver/urlFetcher.d.ts.map +1 -0
  31. package/dist/resolver/urlFetcher.js +134 -0
  32. package/dist/scanner/dependencies.d.ts +14 -0
  33. package/dist/scanner/dependencies.d.ts.map +1 -0
  34. package/dist/scanner/dependencies.js +199 -0
  35. package/dist/scanner/fileContent.d.ts +8 -0
  36. package/dist/scanner/fileContent.d.ts.map +1 -0
  37. package/dist/scanner/fileContent.js +133 -0
  38. package/dist/scanner/fileTree.d.ts +2 -0
  39. package/dist/scanner/fileTree.d.ts.map +1 -0
  40. package/dist/scanner/fileTree.js +152 -0
  41. package/dist/scanner/gitContext.d.ts +19 -0
  42. package/dist/scanner/gitContext.d.ts.map +1 -0
  43. package/dist/scanner/gitContext.js +60 -0
  44. package/dist/scope/autoScope.d.ts +2 -0
  45. package/dist/scope/autoScope.d.ts.map +1 -0
  46. package/dist/scope/autoScope.js +226 -0
  47. package/dist/scope/config.d.ts +10 -0
  48. package/dist/scope/config.d.ts.map +1 -0
  49. package/dist/scope/config.js +71 -0
  50. package/index.js +2 -0
  51. package/package.json +37 -0
  52. package/src/commands/analyze.ts +201 -0
  53. package/src/commands/export.ts +33 -0
  54. package/src/commands/init.ts +174 -0
  55. package/src/commands/scope.ts +77 -0
  56. package/src/commands/status.ts +67 -0
  57. package/src/commands/sync.ts +51 -0
  58. package/src/context/builder.ts +178 -0
  59. package/src/gaps/detector.ts +131 -0
  60. package/src/index.ts +54 -0
  61. package/src/resolver/urlFetcher.ts +119 -0
  62. package/src/scanner/dependencies.ts +196 -0
  63. package/src/scanner/fileContent.ts +121 -0
  64. package/src/scanner/fileTree.ts +149 -0
  65. package/src/scanner/gitContext.ts +74 -0
  66. package/src/scope/autoScope.ts +182 -0
  67. package/src/scope/config.ts +39 -0
  68. package/tsconfig.json +19 -0
@@ -0,0 +1,10 @@
1
+ import { FileContent } from "../scanner/fileContent";
2
+ export interface Gap {
3
+ type: "undocumented_function" | "missing_env_var" | "todo_fixme" | "implicit_dependency" | "stale_reference";
4
+ file: string;
5
+ line?: number;
6
+ description: string;
7
+ severity: "high" | "medium" | "low";
8
+ }
9
+ export declare function detectGaps(files: FileContent[], projectRoot: string): Gap[];
10
+ //# sourceMappingURL=detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../src/gaps/detector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,WAAW,GAAG;IAClB,IAAI,EAAE,uBAAuB,GAAG,iBAAiB,GAAG,YAAY,GAAG,qBAAqB,GAAG,iBAAiB,CAAC;IAC7G,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACrC;AAuGD,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,GAAG,EAAE,CAiB3E"}
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.detectGaps = detectGaps;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ // Detect functions/classes with no JSDoc or comments above them
40
+ function detectUndocumentedCode(file) {
41
+ const gaps = [];
42
+ const lines = file.content.split("\n");
43
+ for (let i = 0; i < lines.length; i++) {
44
+ const line = lines[i].trim();
45
+ const prevLine = i > 0 ? lines[i - 1].trim() : "";
46
+ const isFunctionOrClass = /^(export\s+)?(async\s+)?function\s+\w+/.test(line) ||
47
+ /^(export\s+)?(default\s+)?class\s+\w+/.test(line) ||
48
+ /^(export\s+)?const\s+\w+\s*=\s*(async\s+)?\(/.test(line);
49
+ if (isFunctionOrClass) {
50
+ const hasComment = prevLine.startsWith("//") ||
51
+ prevLine.startsWith("*") ||
52
+ prevLine.startsWith("/*") ||
53
+ prevLine.startsWith("/**") ||
54
+ prevLine === "*/";
55
+ if (!hasComment) {
56
+ gaps.push({
57
+ type: "undocumented_function",
58
+ file: file.relativePath,
59
+ line: i + 1,
60
+ description: `Undocumented: "${line.slice(0, 60)}..."`,
61
+ severity: "low",
62
+ });
63
+ }
64
+ }
65
+ }
66
+ return gaps.slice(0, 5); // Cap at 5 per file to avoid noise
67
+ }
68
+ // Detect TODO/FIXME/HACK comments
69
+ function detectTodos(file) {
70
+ const gaps = [];
71
+ const lines = file.content.split("\n");
72
+ for (let i = 0; i < lines.length; i++) {
73
+ const line = lines[i];
74
+ if (/TODO|FIXME|HACK|XXX|TEMP/i.test(line)) {
75
+ gaps.push({
76
+ type: "todo_fixme",
77
+ file: file.relativePath,
78
+ line: i + 1,
79
+ description: line.trim().slice(0, 100),
80
+ severity: /FIXME|HACK/i.test(line) ? "high" : "medium",
81
+ });
82
+ }
83
+ }
84
+ return gaps;
85
+ }
86
+ // Detect env vars referenced in code but not in .env.example
87
+ function detectMissingEnvVars(files, projectRoot) {
88
+ const gaps = [];
89
+ const envExamplePath = path.join(projectRoot, ".env.example");
90
+ let knownEnvVars = new Set();
91
+ if (fs.existsSync(envExamplePath)) {
92
+ const content = fs.readFileSync(envExamplePath, "utf-8");
93
+ for (const line of content.split("\n")) {
94
+ const match = line.match(/^([A-Z_][A-Z0-9_]*)\s*=/);
95
+ if (match)
96
+ knownEnvVars.add(match[1]);
97
+ }
98
+ }
99
+ const ENV_REGEX = /process\.env\.([A-Z_][A-Z0-9_]*)/g;
100
+ for (const file of files) {
101
+ let match;
102
+ while ((match = ENV_REGEX.exec(file.content)) !== null) {
103
+ const varName = match[1];
104
+ if (!knownEnvVars.has(varName)) {
105
+ gaps.push({
106
+ type: "missing_env_var",
107
+ file: file.relativePath,
108
+ description: `process.env.${varName} used but not in .env.example`,
109
+ severity: "high",
110
+ });
111
+ }
112
+ }
113
+ }
114
+ // Deduplicate by description
115
+ const seen = new Set();
116
+ return gaps.filter((g) => {
117
+ if (seen.has(g.description))
118
+ return false;
119
+ seen.add(g.description);
120
+ return true;
121
+ });
122
+ }
123
+ function detectGaps(files, projectRoot) {
124
+ const gaps = [];
125
+ for (const file of files) {
126
+ if (file.truncated)
127
+ continue;
128
+ const ext = path.extname(file.relativePath);
129
+ if ([".ts", ".tsx", ".js", ".jsx"].includes(ext)) {
130
+ gaps.push(...detectUndocumentedCode(file));
131
+ gaps.push(...detectTodos(file));
132
+ }
133
+ }
134
+ gaps.push(...detectMissingEnvVars(files, projectRoot));
135
+ // Sort by severity
136
+ const order = { high: 0, medium: 1, low: 2 };
137
+ return gaps.sort((a, b) => order[a.severity] - order[b.severity]);
138
+ }
139
+ //# sourceMappingURL=detector.js.map
@@ -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,48 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const init_1 = require("./commands/init");
6
+ const sync_1 = require("./commands/sync");
7
+ const scope_1 = require("./commands/scope");
8
+ const status_1 = require("./commands/status");
9
+ const export_1 = require("./commands/export");
10
+ const analyze_1 = require("./commands/analyze");
11
+ const { version } = require("../package.json");
12
+ commander_1.program
13
+ .name("cliper")
14
+ .description("AI context doc generator for developers")
15
+ .version(version);
16
+ commander_1.program
17
+ .command("init")
18
+ .description("Scan project and generate context document")
19
+ .option("-p, --path <path>", "Project root path", process.cwd())
20
+ .option("--max-file-size <kb>", "Max file size to include in KB", (v) => parseInt(v), 50)
21
+ .action(init_1.initCommand);
22
+ commander_1.program
23
+ .command("sync")
24
+ .description("Refresh stale sections of the context document")
25
+ .option("--watch", "Auto-refresh on git events")
26
+ .action(sync_1.syncCommand);
27
+ commander_1.program
28
+ .command("scope")
29
+ .description("Manage active scope")
30
+ .argument("<action>", "add | remove | watch | list")
31
+ .argument("[path]", "File or directory path")
32
+ .action(scope_1.scopeCommand);
33
+ commander_1.program
34
+ .command("status")
35
+ .description("Show what is fresh, stale, and in scope")
36
+ .action(status_1.statusCommand);
37
+ commander_1.program
38
+ .command("export")
39
+ .description("Print context doc to stdout")
40
+ .option("--format <format>", "Output format: md or txt", "md")
41
+ .action(export_1.exportCommand);
42
+ commander_1.program
43
+ .command("analyze")
44
+ .description("Analyze context doc and generate optimized AI prompt")
45
+ .requiredOption("--model <model>", "Target model: claude or chatgpt")
46
+ .action(analyze_1.analyzeCommand);
47
+ commander_1.program.parse(process.argv);
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ export interface ResolvedReference {
2
+ url: string;
3
+ source: string;
4
+ status: "fetched" | "blocked" | "failed" | "skipped";
5
+ content?: string;
6
+ reason?: string;
7
+ }
8
+ export declare function resolveBlockedReferences(projectRoot: string): Promise<ResolvedReference[]>;
9
+ //# sourceMappingURL=urlFetcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urlFetcher.d.ts","sourceRoot":"","sources":["../../src/resolver/urlFetcher.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA+DD,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,EAAE,CAAC,CA2C9B"}
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.resolveBlockedReferences = resolveBlockedReferences;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const glob_1 = require("glob");
40
+ const URL_REGEX = /https?:\/\/[^\s\)\]\>"']+/g;
41
+ const ALWAYS_BLOCKED_PATTERNS = [
42
+ /robots\.txt/i,
43
+ /localhost/i,
44
+ /127\.0\.0\.1/,
45
+ /internal\./,
46
+ /\.local\//,
47
+ ];
48
+ const SKIP_EXTENSIONS = [".png", ".jpg", ".jpeg", ".gif", ".pdf", ".zip"];
49
+ function shouldSkip(url) {
50
+ if (SKIP_EXTENSIONS.some((ext) => url.toLowerCase().includes(ext)))
51
+ return true;
52
+ if (url.includes("shields.io"))
53
+ return true;
54
+ if (url.includes("badge"))
55
+ return true;
56
+ if (url.includes("github.com/") && url.includes("/actions/"))
57
+ return true;
58
+ return false;
59
+ }
60
+ async function fetchUrl(url) {
61
+ try {
62
+ const { default: fetch } = await Promise.resolve().then(() => __importStar(require("node-fetch")));
63
+ const controller = new AbortController();
64
+ const timeout = setTimeout(() => controller.abort(), 8000);
65
+ const res = await fetch(url, {
66
+ signal: controller.signal,
67
+ headers: {
68
+ "User-Agent": "Cliper/1.0 context-doc-generator",
69
+ },
70
+ });
71
+ clearTimeout(timeout);
72
+ if (!res.ok) {
73
+ return { ok: false, reason: `HTTP ${res.status}` };
74
+ }
75
+ const contentType = res.headers.get("content-type") ?? "";
76
+ if (!contentType.includes("text") && !contentType.includes("json")) {
77
+ return { ok: false, reason: "Non-text content" };
78
+ }
79
+ const text = await res.text();
80
+ // Strip HTML tags for cleaner context
81
+ const cleaned = text
82
+ .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "")
83
+ .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "")
84
+ .replace(/<[^>]+>/g, " ")
85
+ .replace(/\s+/g, " ")
86
+ .trim()
87
+ .slice(0, 3000); // Cap at 3000 chars per URL
88
+ return { ok: true, content: cleaned };
89
+ }
90
+ catch (err) {
91
+ return { ok: false, reason: err.message ?? "Network error" };
92
+ }
93
+ }
94
+ async function resolveBlockedReferences(projectRoot) {
95
+ const markdownFiles = await (0, glob_1.glob)("**/*.md", {
96
+ cwd: projectRoot,
97
+ ignore: ["node_modules/**", ".git/**", "dist/**"],
98
+ });
99
+ const urlMap = new Map(); // url -> source file
100
+ for (const mdFile of markdownFiles) {
101
+ const fullPath = path.join(projectRoot, mdFile);
102
+ try {
103
+ const content = fs.readFileSync(fullPath, "utf-8");
104
+ const matches = content.match(URL_REGEX) ?? [];
105
+ for (const url of matches) {
106
+ if (!urlMap.has(url))
107
+ urlMap.set(url, mdFile);
108
+ }
109
+ }
110
+ catch {
111
+ // Skip unreadable files
112
+ }
113
+ }
114
+ const results = [];
115
+ for (const [url, source] of urlMap) {
116
+ if (shouldSkip(url)) {
117
+ results.push({ url, source, status: "skipped", reason: "Badge/asset URL" });
118
+ continue;
119
+ }
120
+ if (ALWAYS_BLOCKED_PATTERNS.some((p) => p.test(url))) {
121
+ results.push({ url, source, status: "blocked", reason: "Internal/local URL" });
122
+ continue;
123
+ }
124
+ const result = await fetchUrl(url);
125
+ if (result.ok && result.content) {
126
+ results.push({ url, source, status: "fetched", content: result.content });
127
+ }
128
+ else {
129
+ results.push({ url, source, status: "failed", reason: result.reason });
130
+ }
131
+ }
132
+ return results;
133
+ }
134
+ //# sourceMappingURL=urlFetcher.js.map
@@ -0,0 +1,14 @@
1
+ import { FileContent } from "./fileContent";
2
+ export interface DependencyEdge {
3
+ from: string;
4
+ to: string;
5
+ type: "import" | "require" | "use" | "mod";
6
+ }
7
+ export interface DependencyMap {
8
+ edges: DependencyEdge[];
9
+ externalPackages: string[];
10
+ entryPoints: string[];
11
+ }
12
+ export declare function buildDependencyMap(files: FileContent[]): DependencyMap;
13
+ export declare function formatDependencyMap(map: DependencyMap): string;
14
+ //# sourceMappingURL=dependencies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/scanner/dependencies.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;CAC9C;AAED,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAkGD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,aAAa,CA2CtE;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAsC9D"}
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.buildDependencyMap = buildDependencyMap;
37
+ exports.formatDependencyMap = formatDependencyMap;
38
+ const path = __importStar(require("path"));
39
+ function extractJSImports(file) {
40
+ const internal = [];
41
+ const external = [];
42
+ const patterns = [
43
+ /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g,
44
+ /require\(['"]([^'"]+)['"]\)/g,
45
+ /import\(['"]([^'"]+)['"]\)/g,
46
+ ];
47
+ for (const pattern of patterns) {
48
+ let match;
49
+ while ((match = pattern.exec(file.content)) !== null) {
50
+ const dep = match[1];
51
+ if (dep.startsWith(".") || dep.startsWith("/")) {
52
+ const dir = path.dirname(file.relativePath);
53
+ const resolved = path.normalize(path.join(dir, dep));
54
+ internal.push(resolved);
55
+ }
56
+ else {
57
+ const pkgName = dep.startsWith("@")
58
+ ? dep.split("/").slice(0, 2).join("/")
59
+ : dep.split("/")[0];
60
+ external.push(pkgName);
61
+ }
62
+ }
63
+ }
64
+ return { internal, external };
65
+ }
66
+ function extractRustImports(file) {
67
+ const internal = [];
68
+ const external = [];
69
+ const usePattern = /^use\s+([\w:]+)/gm;
70
+ const modPattern = /^(?:pub\s+)?mod\s+(\w+)/gm;
71
+ let match;
72
+ while ((match = usePattern.exec(file.content)) !== null) {
73
+ const dep = match[1];
74
+ if (dep.startsWith("crate::") || dep.startsWith("super::") || dep.startsWith("self::")) {
75
+ internal.push(dep.replace(/^(crate|super|self)::/, ""));
76
+ }
77
+ else {
78
+ external.push(dep.split("::")[0]);
79
+ }
80
+ }
81
+ while ((match = modPattern.exec(file.content)) !== null) {
82
+ internal.push(match[1]);
83
+ }
84
+ return { internal, external };
85
+ }
86
+ function extractPythonImports(file) {
87
+ const internal = [];
88
+ const external = [];
89
+ const relPattern = /^from\s+(\.+[\w.]*)\s+import/gm;
90
+ const absPatterns = [
91
+ /^import\s+([\w.]+)/gm,
92
+ /^from\s+([\w.]+)\s+import/gm,
93
+ ];
94
+ let match;
95
+ while ((match = relPattern.exec(file.content)) !== null) {
96
+ internal.push(match[1]);
97
+ }
98
+ for (const pattern of absPatterns) {
99
+ while ((match = pattern.exec(file.content)) !== null) {
100
+ external.push(match[1].split(".")[0]);
101
+ }
102
+ }
103
+ return { internal, external };
104
+ }
105
+ function getExtractor(filePath) {
106
+ const ext = path.extname(filePath).toLowerCase();
107
+ if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext))
108
+ return extractJSImports;
109
+ if (ext === ".rs")
110
+ return extractRustImports;
111
+ if (ext === ".py")
112
+ return extractPythonImports;
113
+ return null;
114
+ }
115
+ function isEntryPoint(filePath) {
116
+ const name = path.basename(filePath);
117
+ return [
118
+ "index.ts", "index.js", "main.ts", "main.js",
119
+ "main.rs", "lib.rs",
120
+ "main.py", "__init__.py",
121
+ "main.go",
122
+ ].includes(name);
123
+ }
124
+ function buildDependencyMap(files) {
125
+ const edges = [];
126
+ const externalSet = new Set();
127
+ const entryPoints = [];
128
+ for (const file of files) {
129
+ if (file.truncated)
130
+ continue;
131
+ const extractor = getExtractor(file.relativePath);
132
+ if (!extractor)
133
+ continue;
134
+ if (isEntryPoint(file.relativePath)) {
135
+ entryPoints.push(file.relativePath);
136
+ }
137
+ const { internal, external } = extractor(file);
138
+ for (const dep of internal) {
139
+ edges.push({
140
+ from: file.relativePath,
141
+ to: dep,
142
+ type: file.relativePath.endsWith(".rs") ? "use" : "import",
143
+ });
144
+ }
145
+ for (const pkg of external) {
146
+ externalSet.add(pkg);
147
+ }
148
+ }
149
+ const seen = new Set();
150
+ const uniqueEdges = edges.filter((e) => {
151
+ const key = `${e.from}→${e.to}`;
152
+ if (seen.has(key))
153
+ return false;
154
+ seen.add(key);
155
+ return true;
156
+ });
157
+ return {
158
+ edges: uniqueEdges,
159
+ externalPackages: Array.from(externalSet).sort(),
160
+ entryPoints,
161
+ };
162
+ }
163
+ function formatDependencyMap(map) {
164
+ if (map.edges.length === 0 && map.externalPackages.length === 0) {
165
+ return "No dependency information available for scoped files.";
166
+ }
167
+ const lines = [];
168
+ if (map.entryPoints.length > 0) {
169
+ lines.push("**Entry points:**");
170
+ for (const ep of map.entryPoints) {
171
+ lines.push(` → ${ep}`);
172
+ }
173
+ lines.push("");
174
+ }
175
+ if (map.edges.length > 0) {
176
+ lines.push("**Internal dependencies:**");
177
+ const byFile = new Map();
178
+ for (const edge of map.edges) {
179
+ if (!byFile.has(edge.from))
180
+ byFile.set(edge.from, []);
181
+ byFile.get(edge.from).push(edge.to);
182
+ }
183
+ for (const [from, deps] of byFile) {
184
+ lines.push(` ${from}`);
185
+ for (const dep of deps.slice(0, 8)) {
186
+ lines.push(` ↳ ${dep}`);
187
+ }
188
+ if (deps.length > 8)
189
+ lines.push(` ↳ ... and ${deps.length - 8} more`);
190
+ }
191
+ lines.push("");
192
+ }
193
+ if (map.externalPackages.length > 0) {
194
+ lines.push("**External packages used:**");
195
+ lines.push(` ${map.externalPackages.join(", ")}`);
196
+ }
197
+ return lines.join("\n");
198
+ }
199
+ //# sourceMappingURL=dependencies.js.map
@@ -0,0 +1,8 @@
1
+ export interface FileContent {
2
+ relativePath: string;
3
+ content: string;
4
+ truncated: boolean;
5
+ size: number;
6
+ }
7
+ export declare function extractFileContents(projectRoot: string, activeScope: string[], watchedScope: string[], maxFileSizeKB?: number): Promise<FileContent[]>;
8
+ //# sourceMappingURL=fileContent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileContent.d.ts","sourceRoot":"","sources":["../../src/scanner/fileContent.ts"],"names":[],"mappings":"AAkCA,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EAAE,EACrB,YAAY,EAAE,MAAM,EAAE,EACtB,aAAa,GAAE,MAAW,GACzB,OAAO,CAAC,WAAW,EAAE,CAAC,CA0ExB"}