@bike4mind/cli 0.2.28-feat-questmaster-progress-indicators.18753 → 0.2.28-feat-get-file-structure-tool.18750

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.
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  BadRequestError,
4
4
  secureParameters
5
- } from "./chunk-UNOJBVD2.js";
5
+ } from "./chunk-NTNJJRSU.js";
6
6
  import {
7
7
  CompletionApiUsageTransaction,
8
8
  GenericCreditDeductTransaction,
@@ -6,7 +6,7 @@ import {
6
6
  getSettingsByNames,
7
7
  obfuscateApiKey,
8
8
  secureParameters
9
- } from "./chunk-UNOJBVD2.js";
9
+ } from "./chunk-NTNJJRSU.js";
10
10
  import {
11
11
  ApiKeyType,
12
12
  MementoTier,
@@ -9181,7 +9181,7 @@ var QuestMaster = class {
9181
9181
  if (!this.quest) {
9182
9182
  throw new Error("No quest context available");
9183
9183
  }
9184
- await this.onStatusUpdate(this.quest, "Step 2/4: Organizing quests and sub-tasks...");
9184
+ await this.onStatusUpdate(this.quest, "Processing quest plan...");
9185
9185
  const defaultResponse = {
9186
9186
  type: "narrative",
9187
9187
  meta: {
@@ -9263,7 +9263,7 @@ var QuestMaster = class {
9263
9263
  }
9264
9264
  if (extracted.length > 0) {
9265
9265
  this.logger.log("Successfully extracted QuestMaster data:", extracted);
9266
- await this.onStatusUpdate(this.quest, "Step 3/4: Validating quest structure...");
9266
+ await this.onStatusUpdate(this.quest, "Extracted QuestMaster data");
9267
9267
  const validQuests = extracted.filter((quest) => quest !== null && typeof quest === "object" && quest.id && quest.title && quest.description);
9268
9268
  if (validQuests.length === 0) {
9269
9269
  throw new Error("No valid quests found after filtering");
@@ -9356,7 +9356,7 @@ var QuestMaster = class {
9356
9356
  questResponse = defaultResponse;
9357
9357
  this.logger.error("Invalid quest response structure, using default");
9358
9358
  }
9359
- await this.onStatusUpdate(this.quest, "Step 4/4: Saving quest plan...");
9359
+ await this.onStatusUpdate(this.quest, "Saving quest plan...");
9360
9360
  console.log("\u{1F3AF} Creating QuestMasterPlan with userId:", this.userId);
9361
9361
  const questMasterPlan = await this.db.questMasterPlans.create({
9362
9362
  notebookId: this.quest.sessionId,
@@ -9678,7 +9678,7 @@ HANDLING VERBOSE INPUT:
9678
9678
  }
9679
9679
  const { history = [] } = options;
9680
9680
  this.logger.log(`Creating quest plan with ${history.length} history messages for context`);
9681
- await this.onStatusUpdate(this.quest, "Step 1/4: Analyzing your request...");
9681
+ await this.onStatusUpdate(this.quest, "Creating quest plan...");
9682
9682
  if (isGPT5ModelWithToolSupport(model)) {
9683
9683
  this.logger.log(`Using function calling approach for GPT-5 model: ${model}`);
9684
9684
  try {
@@ -7,7 +7,7 @@ import {
7
7
  getSettingsMap,
8
8
  getSettingsValue,
9
9
  secureParameters
10
- } from "./chunk-UNOJBVD2.js";
10
+ } from "./chunk-NTNJJRSU.js";
11
11
  import {
12
12
  KnowledgeType,
13
13
  SupportedFabFileMimeTypes
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  createFabFile,
4
4
  createFabFileSchema
5
- } from "./chunk-ZEMWV6IR.js";
6
- import "./chunk-UNOJBVD2.js";
5
+ } from "./chunk-WXWRI3H7.js";
6
+ import "./chunk-NTNJJRSU.js";
7
7
  import "./chunk-XJRPAAUS.js";
8
8
  import "./chunk-OCYRD7D6.js";
9
9
  export {
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  getEffectiveApiKey,
6
6
  getOpenWeatherKey,
7
7
  getSerperKey
8
- } from "./chunk-VGYTNJXN.js";
8
+ } from "./chunk-AXOBK7TG.js";
9
9
  import {
10
10
  ConfigStore
11
11
  } from "./chunk-23T2XGSZ.js";
@@ -13,8 +13,8 @@ import {
13
13
  selectActiveBackgroundAgents,
14
14
  useCliStore
15
15
  } from "./chunk-TVW4ZESU.js";
16
- import "./chunk-JJBDHUGY.js";
17
- import "./chunk-ZEMWV6IR.js";
16
+ import "./chunk-6QZAOJPA.js";
17
+ import "./chunk-WXWRI3H7.js";
18
18
  import {
19
19
  BFLImageService,
20
20
  BaseStorage,
@@ -26,7 +26,7 @@ import {
26
26
  OpenAIBackend,
27
27
  OpenAIImageService,
28
28
  XAIImageService
29
- } from "./chunk-UNOJBVD2.js";
29
+ } from "./chunk-NTNJJRSU.js";
30
30
  import {
31
31
  AiEvents,
32
32
  ApiKeyEvents,
@@ -3806,6 +3806,7 @@ var DEFAULT_TOOL_CATEGORIES = {
3806
3806
  grep_search: "prompt_default",
3807
3807
  glob_files: "prompt_default",
3808
3808
  get_file_tree: "prompt_default",
3809
+ get_file_structure: "prompt_default",
3809
3810
  git_status: "prompt_default",
3810
3811
  git_diff: "prompt_default",
3811
3812
  git_log: "prompt_default",
@@ -6059,8 +6060,8 @@ async function processAndStoreImages(images, context) {
6059
6060
  const buffer = await downloadImage(image);
6060
6061
  const fileType = await fileTypeFromBuffer2(buffer);
6061
6062
  const filename = `${uuidv45()}.${fileType?.ext}`;
6062
- const path18 = await context.imageGenerateStorage.upload(buffer, filename, {});
6063
- return path18;
6063
+ const path19 = await context.imageGenerateStorage.upload(buffer, filename, {});
6064
+ return path19;
6064
6065
  }));
6065
6066
  }
6066
6067
  async function updateQuestAndReturnMarkdown(storedImageUrls, context) {
@@ -7386,8 +7387,8 @@ async function processAndStoreImage(imageUrl, context) {
7386
7387
  const buffer = await downloadImage2(imageUrl);
7387
7388
  const fileType = await fileTypeFromBuffer3(buffer);
7388
7389
  const filename = `${uuidv46()}.${fileType?.ext}`;
7389
- const path18 = await context.imageGenerateStorage.upload(buffer, filename, {});
7390
- return path18;
7390
+ const path19 = await context.imageGenerateStorage.upload(buffer, filename, {});
7391
+ return path19;
7391
7392
  }
7392
7393
  async function generateFullMask(imageBuffer) {
7393
7394
  const sharp = (await import("sharp")).default;
@@ -11624,7 +11625,7 @@ async function generateFileDeletePreview(args) {
11624
11625
  if (!existsSync7(args.path)) {
11625
11626
  return `[File does not exist: ${args.path}]`;
11626
11627
  }
11627
- const stats = await import("fs/promises").then((fs14) => fs14.stat(args.path));
11628
+ const stats = await import("fs/promises").then((fs15) => fs15.stat(args.path));
11628
11629
  return `[File will be deleted]
11629
11630
 
11630
11631
  Path: ${args.path}
@@ -11915,21 +11916,21 @@ var NoOpStorage = class extends BaseStorage {
11915
11916
  async upload(input, destination, options) {
11916
11917
  return `/tmp/${destination}`;
11917
11918
  }
11918
- async download(path18) {
11919
+ async download(path19) {
11919
11920
  throw new Error("Download not supported in CLI");
11920
11921
  }
11921
- async delete(path18) {
11922
+ async delete(path19) {
11922
11923
  }
11923
- async getSignedUrl(path18) {
11924
- return `/tmp/${path18}`;
11924
+ async getSignedUrl(path19) {
11925
+ return `/tmp/${path19}`;
11925
11926
  }
11926
- getPublicUrl(path18) {
11927
- return `/tmp/${path18}`;
11927
+ getPublicUrl(path19) {
11928
+ return `/tmp/${path19}`;
11928
11929
  }
11929
- async getPreview(path18) {
11930
- return `/tmp/${path18}`;
11930
+ async getPreview(path19) {
11931
+ return `/tmp/${path19}`;
11931
11932
  }
11932
- async getMetadata(path18) {
11933
+ async getMetadata(path19) {
11933
11934
  return { size: 0, contentType: "application/octet-stream" };
11934
11935
  }
11935
11936
  };
@@ -13801,7 +13802,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
13801
13802
  // package.json
13802
13803
  var package_default = {
13803
13804
  name: "@bike4mind/cli",
13804
- version: "0.2.28-feat-questmaster-progress-indicators.18753+454386ccc",
13805
+ version: "0.2.28-feat-get-file-structure-tool.18750+9a81a7d11",
13805
13806
  type: "module",
13806
13807
  description: "Interactive CLI tool for Bike4Mind with ReAct agents",
13807
13808
  license: "UNLICENSED",
@@ -13896,10 +13897,12 @@ var package_default = {
13896
13897
  sharp: "^0.34.5",
13897
13898
  speakeasy: "^2.0.0",
13898
13899
  tiktoken: "^1.0.16",
13900
+ "tree-sitter-wasms": "^0.1.13",
13899
13901
  turndown: "^7.2.0",
13900
13902
  unpdf: "^0.10.0",
13901
13903
  uuid: "^9.0.1",
13902
13904
  voyageai: "^0.0.4",
13905
+ "web-tree-sitter": "0.25.10",
13903
13906
  xlsx: "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
13904
13907
  yargs: "^17.7.2",
13905
13908
  yauzl: "^3.1.3",
@@ -13909,10 +13912,10 @@ var package_default = {
13909
13912
  },
13910
13913
  devDependencies: {
13911
13914
  "@bike4mind/agents": "0.1.0",
13912
- "@bike4mind/common": "2.49.1-feat-questmaster-progress-indicators.18753+454386ccc",
13913
- "@bike4mind/mcp": "1.28.3-feat-questmaster-progress-indicators.18753+454386ccc",
13914
- "@bike4mind/services": "2.47.2-feat-questmaster-progress-indicators.18753+454386ccc",
13915
- "@bike4mind/utils": "2.4.2-feat-questmaster-progress-indicators.18753+454386ccc",
13915
+ "@bike4mind/common": "2.49.1-feat-get-file-structure-tool.18750+9a81a7d11",
13916
+ "@bike4mind/mcp": "1.28.3-feat-get-file-structure-tool.18750+9a81a7d11",
13917
+ "@bike4mind/services": "2.47.2-feat-get-file-structure-tool.18750+9a81a7d11",
13918
+ "@bike4mind/utils": "2.4.2-feat-get-file-structure-tool.18750+9a81a7d11",
13916
13919
  "@types/better-sqlite3": "^7.6.13",
13917
13920
  "@types/diff": "^5.0.9",
13918
13921
  "@types/jsonwebtoken": "^9.0.4",
@@ -13929,7 +13932,7 @@ var package_default = {
13929
13932
  optionalDependencies: {
13930
13933
  "@vscode/ripgrep": "^1.17.0"
13931
13934
  },
13932
- gitHead: "454386ccc6289192423295966887b31dd897b32c"
13935
+ gitHead: "9a81a7d11946ea54b9a47fe35897e36fc7541c65"
13933
13936
  };
13934
13937
 
13935
13938
  // src/config/constants.ts
@@ -15609,6 +15612,99 @@ function createFindDefinitionTool() {
15609
15612
  };
15610
15613
  }
15611
15614
 
15615
+ // src/tools/getFileStructure/index.ts
15616
+ import { existsSync as existsSync9, promises as fs14, statSync as statSync6 } from "fs";
15617
+ import path18 from "path";
15618
+
15619
+ // src/tools/getFileStructure/formatter.ts
15620
+ var SECTIONS = [
15621
+ { title: "IMPORTS", kind: "import", exportable: false },
15622
+ { title: "EXPORTS", kind: "export", exportable: false },
15623
+ { title: "FUNCTIONS", kind: "function", exportable: true },
15624
+ { title: "CLASSES", kind: "class", exportable: true },
15625
+ { title: "INTERFACES", kind: "interface", exportable: true },
15626
+ { title: "TYPES", kind: "type", exportable: true },
15627
+ { title: "ENUMS", kind: "enum", exportable: true }
15628
+ ];
15629
+ function formatStructureOutput(filePath, items, fileSize, lineCount) {
15630
+ const sizeStr = fileSize < 1024 ? `${fileSize} B` : `${(fileSize / 1024).toFixed(1)} KB`;
15631
+ const lines = [`File: ${filePath} (${sizeStr}, ${lineCount} lines)`, ""];
15632
+ for (const section of SECTIONS) {
15633
+ const sectionItems = items.filter((i) => i.kind === section.kind);
15634
+ formatSection(lines, section.title, sectionItems, (item) => {
15635
+ const prefix = section.exportable && item.exported ? "export " : "";
15636
+ return `L${item.line}: ${prefix}${item.name}`;
15637
+ });
15638
+ }
15639
+ return lines.join("\n").trimEnd();
15640
+ }
15641
+ function formatSection(lines, title, items, format) {
15642
+ lines.push(`${title} (${items.length}):`);
15643
+ if (items.length === 0) {
15644
+ lines.push(" (none)");
15645
+ } else {
15646
+ for (const item of items) {
15647
+ lines.push(` ${format(item)}`);
15648
+ }
15649
+ }
15650
+ lines.push("");
15651
+ }
15652
+
15653
+ // src/tools/getFileStructure/index.ts
15654
+ var MAX_FILE_SIZE3 = 10 * 1024 * 1024;
15655
+ function createGetFileStructureTool() {
15656
+ return {
15657
+ toolFn: async (value) => {
15658
+ const params = value;
15659
+ try {
15660
+ const cwd = process.cwd();
15661
+ const resolvedPath = path18.resolve(cwd, params.path);
15662
+ if (!resolvedPath.startsWith(cwd)) {
15663
+ return "Error: Access denied - cannot read files outside of current working directory";
15664
+ }
15665
+ if (!existsSync9(resolvedPath)) {
15666
+ return `Error: File not found: ${params.path}`;
15667
+ }
15668
+ const stats = statSync6(resolvedPath);
15669
+ if (stats.isDirectory()) {
15670
+ return `Error: Path is a directory, not a file: ${params.path}`;
15671
+ }
15672
+ if (stats.size > MAX_FILE_SIZE3) {
15673
+ return `Error: File too large (${(stats.size / 1024 / 1024).toFixed(2)}MB). Max: ${MAX_FILE_SIZE3 / 1024 / 1024}MB`;
15674
+ }
15675
+ const ext = path18.extname(resolvedPath).toLowerCase();
15676
+ const { getLanguageForExtension, parseFileStructure, getSupportedLanguages } = await import("./treeSitterEngine-4SGFQDY3.js");
15677
+ const languageId = getLanguageForExtension(ext);
15678
+ if (!languageId) {
15679
+ const supported = getSupportedLanguages();
15680
+ return `Error: Unsupported file type "${ext}". Supported languages: ${supported.join(", ")}`;
15681
+ }
15682
+ const sourceCode = await fs14.readFile(resolvedPath, "utf-8");
15683
+ const lineCount = sourceCode.split("\n").length;
15684
+ const items = await parseFileStructure(sourceCode, languageId);
15685
+ return formatStructureOutput(params.path, items, stats.size, lineCount);
15686
+ } catch (error) {
15687
+ const errorMessage = error instanceof Error ? error.message : String(error);
15688
+ return `Error analyzing file structure: ${errorMessage}`;
15689
+ }
15690
+ },
15691
+ toolSchema: {
15692
+ name: "get_file_structure",
15693
+ description: "Extract the high-level structure of a source file (imports, exports, functions, classes, interfaces, types) using AST parsing. Returns a concise outline with line numbers. Much more efficient than file_read when you only need to understand what a file contains or exports. Use this before file_read to decide which parts of a large file to read.",
15694
+ parameters: {
15695
+ type: "object",
15696
+ properties: {
15697
+ path: {
15698
+ type: "string",
15699
+ description: "Path to the source file (relative to cwd or absolute within cwd). Supported: .ts, .tsx, .js, .jsx, .mjs, .cjs, .py"
15700
+ }
15701
+ },
15702
+ required: ["path"]
15703
+ }
15704
+ }
15705
+ };
15706
+ }
15707
+
15612
15708
  // src/index.tsx
15613
15709
  process.removeAllListeners("warning");
15614
15710
  process.on("warning", (warning) => {
@@ -15917,7 +16013,14 @@ function CliApp() {
15917
16013
  sessionId: newSession.id
15918
16014
  }) : null;
15919
16015
  const findDefinitionTool = createFindDefinitionTool();
15920
- const cliTools = [agentDelegateTool, ...backgroundTools, writeTodosTool, findDefinitionTool];
16016
+ const getFileStructureTool = createGetFileStructureTool();
16017
+ const cliTools = [
16018
+ agentDelegateTool,
16019
+ ...backgroundTools,
16020
+ writeTodosTool,
16021
+ findDefinitionTool,
16022
+ getFileStructureTool
16023
+ ];
15921
16024
  if (skillTool) {
15922
16025
  cliTools.push(skillTool);
15923
16026
  }
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  findMostSimilarMemento,
4
4
  getRelevantMementos
5
- } from "./chunk-VGYTNJXN.js";
6
- import "./chunk-UNOJBVD2.js";
5
+ } from "./chunk-AXOBK7TG.js";
6
+ import "./chunk-NTNJJRSU.js";
7
7
  import "./chunk-XJRPAAUS.js";
8
8
  import "./chunk-OCYRD7D6.js";
9
9
  export {
@@ -133,7 +133,7 @@ import {
133
133
  validateMermaidSyntax,
134
134
  warmUpSettingsCache,
135
135
  withRetry
136
- } from "./chunk-UNOJBVD2.js";
136
+ } from "./chunk-NTNJJRSU.js";
137
137
  import "./chunk-XJRPAAUS.js";
138
138
  import {
139
139
  Logger,
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  SubtractCreditsSchema,
4
4
  subtractCredits
5
- } from "./chunk-JJBDHUGY.js";
6
- import "./chunk-UNOJBVD2.js";
5
+ } from "./chunk-6QZAOJPA.js";
6
+ import "./chunk-NTNJJRSU.js";
7
7
  import "./chunk-XJRPAAUS.js";
8
8
  import "./chunk-OCYRD7D6.js";
9
9
  export {
@@ -0,0 +1,330 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/tools/getFileStructure/treeSitterEngine.ts
4
+ import { createRequire } from "module";
5
+ import { readFileSync } from "fs";
6
+
7
+ // src/tools/getFileStructure/types.ts
8
+ var EXTENSION_TO_LANGUAGE = {
9
+ ".ts": "typescript",
10
+ ".tsx": "tsx",
11
+ ".js": "javascript",
12
+ ".jsx": "javascript",
13
+ ".mjs": "javascript",
14
+ ".cjs": "javascript",
15
+ ".py": "python"
16
+ };
17
+
18
+ // src/tools/getFileStructure/queries/typescript.ts
19
+ var typescriptQueries = {
20
+ imports: `
21
+ (import_statement
22
+ source: (string) @source
23
+ ) @import
24
+ `,
25
+ exports: `
26
+ (export_statement
27
+ declaration: (function_declaration
28
+ name: (identifier) @name)
29
+ ) @export
30
+
31
+ (export_statement
32
+ declaration: (class_declaration
33
+ name: (type_identifier) @name)
34
+ ) @export
35
+
36
+ (export_statement
37
+ declaration: (interface_declaration
38
+ name: (type_identifier) @name)
39
+ ) @export
40
+
41
+ (export_statement
42
+ declaration: (type_alias_declaration
43
+ name: (type_identifier) @name)
44
+ ) @export
45
+
46
+ (export_statement
47
+ declaration: (enum_declaration
48
+ name: (identifier) @name)
49
+ ) @export
50
+
51
+ (export_statement
52
+ declaration: (lexical_declaration
53
+ (variable_declarator
54
+ name: (identifier) @name))
55
+ ) @export
56
+
57
+ (export_statement
58
+ (export_clause
59
+ (export_specifier
60
+ name: (identifier) @name))
61
+ ) @export
62
+ `,
63
+ functions: `
64
+ (function_declaration
65
+ name: (identifier) @name
66
+ ) @function
67
+
68
+ (lexical_declaration
69
+ (variable_declarator
70
+ name: (identifier) @name
71
+ value: (arrow_function)
72
+ )
73
+ ) @function
74
+ `,
75
+ classes: `
76
+ (class_declaration
77
+ name: (type_identifier) @name
78
+ ) @class
79
+ `,
80
+ interfaces: `
81
+ (interface_declaration
82
+ name: (type_identifier) @name
83
+ ) @interface
84
+ `,
85
+ types: `
86
+ (type_alias_declaration
87
+ name: (type_identifier) @name
88
+ ) @type
89
+
90
+ (enum_declaration
91
+ name: (identifier) @name
92
+ ) @enum
93
+ `
94
+ };
95
+
96
+ // src/tools/getFileStructure/queries/javascript.ts
97
+ var javascriptQueries = {
98
+ imports: `
99
+ (import_statement
100
+ source: (string) @source
101
+ ) @import
102
+ `,
103
+ exports: `
104
+ (export_statement
105
+ declaration: (function_declaration
106
+ name: (identifier) @name)
107
+ ) @export
108
+
109
+ (export_statement
110
+ declaration: (class_declaration
111
+ name: (identifier) @name)
112
+ ) @export
113
+
114
+ (export_statement
115
+ declaration: (lexical_declaration
116
+ (variable_declarator
117
+ name: (identifier) @name))
118
+ ) @export
119
+
120
+ (export_statement
121
+ (export_clause
122
+ (export_specifier
123
+ name: (identifier) @name))
124
+ ) @export
125
+ `,
126
+ functions: `
127
+ (function_declaration
128
+ name: (identifier) @name
129
+ ) @function
130
+
131
+ (lexical_declaration
132
+ (variable_declarator
133
+ name: (identifier) @name
134
+ value: (arrow_function)
135
+ )
136
+ ) @function
137
+ `,
138
+ classes: `
139
+ (class_declaration
140
+ name: (identifier) @name
141
+ ) @class
142
+ `,
143
+ // JavaScript has no interface keyword
144
+ interfaces: "",
145
+ // JavaScript has no type aliases or enums
146
+ types: ""
147
+ };
148
+
149
+ // src/tools/getFileStructure/queries/python.ts
150
+ var pythonQueries = {
151
+ imports: `
152
+ (import_statement
153
+ name: (dotted_name) @source
154
+ ) @import
155
+
156
+ (import_from_statement
157
+ module_name: (dotted_name) @source
158
+ ) @import_from
159
+ `,
160
+ // Python uses __all__ convention, not language-level exports
161
+ exports: "",
162
+ functions: `
163
+ (function_definition
164
+ name: (identifier) @name
165
+ ) @function
166
+ `,
167
+ classes: `
168
+ (class_definition
169
+ name: (identifier) @name
170
+ ) @class
171
+ `,
172
+ // Python has no interface keyword (Protocol is a runtime construct)
173
+ interfaces: "",
174
+ // Python has no type alias syntax at the grammar level
175
+ types: ""
176
+ };
177
+
178
+ // src/tools/getFileStructure/queries/index.ts
179
+ var LANGUAGE_QUERIES = {
180
+ typescript: typescriptQueries,
181
+ tsx: typescriptQueries,
182
+ javascript: javascriptQueries,
183
+ python: pythonQueries
184
+ };
185
+
186
+ // src/tools/getFileStructure/treeSitterEngine.ts
187
+ var require2 = createRequire(import.meta.url);
188
+ var TreeSitter;
189
+ var parserInitialized = false;
190
+ var languageCache = /* @__PURE__ */ new Map();
191
+ function locateTreeSitterWasm() {
192
+ return require2.resolve("web-tree-sitter/tree-sitter.wasm");
193
+ }
194
+ function locateLanguageWasm(language) {
195
+ return require2.resolve(`tree-sitter-wasms/out/tree-sitter-${language}.wasm`);
196
+ }
197
+ async function ensureInitialized() {
198
+ if (parserInitialized) return;
199
+ try {
200
+ const moduleName = "web-tree-sitter";
201
+ TreeSitter = await import(
202
+ /* webpackIgnore: true */
203
+ moduleName
204
+ );
205
+ } catch {
206
+ throw new Error(
207
+ "web-tree-sitter is not available. Install it with: pnpm add web-tree-sitter tree-sitter-wasms --filter @bike4mind/cli"
208
+ );
209
+ }
210
+ const wasmPath = locateTreeSitterWasm();
211
+ const wasmBinary = readFileSync(wasmPath);
212
+ await TreeSitter.Parser.init({
213
+ locateFile: (scriptName) => {
214
+ if (scriptName === "tree-sitter.wasm") {
215
+ return wasmPath;
216
+ }
217
+ return scriptName;
218
+ },
219
+ wasmBinary
220
+ });
221
+ parserInitialized = true;
222
+ }
223
+ async function loadLanguage(languageId) {
224
+ const cached = languageCache.get(languageId);
225
+ if (cached) return cached;
226
+ const wasmPath = locateLanguageWasm(languageId);
227
+ const language = await TreeSitter.Language.load(wasmPath);
228
+ languageCache.set(languageId, language);
229
+ return language;
230
+ }
231
+ function runQuery(language, rootNode, querySource, kind) {
232
+ if (!querySource.trim()) return [];
233
+ const items = [];
234
+ const query = new TreeSitter.Query(language, querySource);
235
+ try {
236
+ const matches = query.matches(rootNode);
237
+ for (const match of matches) {
238
+ const nameCapture = match.captures.find((c) => c.name === "name");
239
+ const sourceCapture = match.captures.find((c) => c.name === "source");
240
+ if (kind === "import") {
241
+ const importCapture = match.captures.find((c) => c.name === "import" || c.name === "import_from");
242
+ const node = importCapture?.node || sourceCapture?.node;
243
+ if (node) {
244
+ items.push({
245
+ kind: "import",
246
+ name: sourceCapture?.node.text.replace(/['"]/g, "") || "",
247
+ line: node.startPosition.row + 1,
248
+ details: node.text
249
+ });
250
+ }
251
+ } else if (nameCapture) {
252
+ items.push({
253
+ kind,
254
+ name: nameCapture.node.text,
255
+ line: nameCapture.node.startPosition.row + 1,
256
+ ...kind === "export" && { exported: true }
257
+ });
258
+ }
259
+ }
260
+ } finally {
261
+ query.delete();
262
+ }
263
+ return items;
264
+ }
265
+ var QUERY_CATEGORIES = [
266
+ ["imports", "import"],
267
+ ["exports", "export"],
268
+ ["functions", "function"],
269
+ ["classes", "class"],
270
+ ["interfaces", "interface"],
271
+ ["types", "type"]
272
+ ];
273
+ async function parseFileStructure(sourceCode, languageId) {
274
+ await ensureInitialized();
275
+ const queries = LANGUAGE_QUERIES[languageId];
276
+ if (!queries) {
277
+ throw new Error(
278
+ `No query definitions for language: ${languageId}. Supported: ${getSupportedLanguages().join(", ")}`
279
+ );
280
+ }
281
+ const language = await loadLanguage(languageId);
282
+ const parser = new TreeSitter.Parser();
283
+ let tree = null;
284
+ try {
285
+ parser.setLanguage(language);
286
+ tree = parser.parse(sourceCode);
287
+ if (!tree) {
288
+ throw new Error("Failed to parse source code");
289
+ }
290
+ const allItems = [];
291
+ for (const [queryKey, kind] of QUERY_CATEGORIES) {
292
+ allItems.push(...runQuery(language, tree.rootNode, queries[queryKey], kind));
293
+ }
294
+ return deduplicateItems(allItems);
295
+ } finally {
296
+ tree?.delete();
297
+ parser.delete();
298
+ }
299
+ }
300
+ function deduplicateItems(items) {
301
+ const exportNames = /* @__PURE__ */ new Set();
302
+ const definitionNames = /* @__PURE__ */ new Set();
303
+ for (const item of items) {
304
+ if (item.kind === "export") {
305
+ exportNames.add(item.name);
306
+ } else if (item.kind !== "import") {
307
+ definitionNames.add(item.name);
308
+ }
309
+ }
310
+ const result = [];
311
+ for (const item of items) {
312
+ if (item.kind === "export" && definitionNames.has(item.name)) continue;
313
+ if (item.kind !== "export" && item.kind !== "import" && exportNames.has(item.name)) {
314
+ item.exported = true;
315
+ }
316
+ result.push(item);
317
+ }
318
+ return result;
319
+ }
320
+ function getSupportedLanguages() {
321
+ return Object.keys(LANGUAGE_QUERIES);
322
+ }
323
+ function getLanguageForExtension(ext) {
324
+ return EXTENSION_TO_LANGUAGE[ext] || null;
325
+ }
326
+ export {
327
+ getLanguageForExtension,
328
+ getSupportedLanguages,
329
+ parseFileStructure
330
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bike4mind/cli",
3
- "version": "0.2.28-feat-questmaster-progress-indicators.18753+454386ccc",
3
+ "version": "0.2.28-feat-get-file-structure-tool.18750+9a81a7d11",
4
4
  "type": "module",
5
5
  "description": "Interactive CLI tool for Bike4Mind with ReAct agents",
6
6
  "license": "UNLICENSED",
@@ -95,10 +95,12 @@
95
95
  "sharp": "^0.34.5",
96
96
  "speakeasy": "^2.0.0",
97
97
  "tiktoken": "^1.0.16",
98
+ "tree-sitter-wasms": "^0.1.13",
98
99
  "turndown": "^7.2.0",
99
100
  "unpdf": "^0.10.0",
100
101
  "uuid": "^9.0.1",
101
102
  "voyageai": "^0.0.4",
103
+ "web-tree-sitter": "0.25.10",
102
104
  "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
103
105
  "yargs": "^17.7.2",
104
106
  "yauzl": "^3.1.3",
@@ -108,10 +110,10 @@
108
110
  },
109
111
  "devDependencies": {
110
112
  "@bike4mind/agents": "0.1.0",
111
- "@bike4mind/common": "2.49.1-feat-questmaster-progress-indicators.18753+454386ccc",
112
- "@bike4mind/mcp": "1.28.3-feat-questmaster-progress-indicators.18753+454386ccc",
113
- "@bike4mind/services": "2.47.2-feat-questmaster-progress-indicators.18753+454386ccc",
114
- "@bike4mind/utils": "2.4.2-feat-questmaster-progress-indicators.18753+454386ccc",
113
+ "@bike4mind/common": "2.49.1-feat-get-file-structure-tool.18750+9a81a7d11",
114
+ "@bike4mind/mcp": "1.28.3-feat-get-file-structure-tool.18750+9a81a7d11",
115
+ "@bike4mind/services": "2.47.2-feat-get-file-structure-tool.18750+9a81a7d11",
116
+ "@bike4mind/utils": "2.4.2-feat-get-file-structure-tool.18750+9a81a7d11",
115
117
  "@types/better-sqlite3": "^7.6.13",
116
118
  "@types/diff": "^5.0.9",
117
119
  "@types/jsonwebtoken": "^9.0.4",
@@ -128,5 +130,5 @@
128
130
  "optionalDependencies": {
129
131
  "@vscode/ripgrep": "^1.17.0"
130
132
  },
131
- "gitHead": "454386ccc6289192423295966887b31dd897b32c"
133
+ "gitHead": "9a81a7d11946ea54b9a47fe35897e36fc7541c65"
132
134
  }