@agiflowai/aicode-utils 1.0.15 → 1.0.17

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.
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
- import * as path$1 from "node:path";
3
- import path from "node:path";
2
+ import * as path from "node:path";
3
+ import nodePath from "node:path";
4
4
  import * as fs from "node:fs/promises";
5
5
  import { accessSync, mkdirSync, readFileSync, readFileSync as readFileSync$1, statSync, writeFileSync } from "node:fs";
6
6
  import * as os from "node:os";
@@ -84,7 +84,7 @@ async function copy(src, dest) {
84
84
  * Move a file or directory
85
85
  */
86
86
  async function move(src, dest) {
87
- await ensureDir(path.dirname(dest));
87
+ await ensureDir(nodePath.dirname(dest));
88
88
  await fs.rename(src, dest);
89
89
  }
90
90
  /**
@@ -120,12 +120,12 @@ const cp = fs.cp;
120
120
 
121
121
  //#endregion
122
122
  //#region src/utils/logger.ts
123
- const logsDir = path$1.join(os.tmpdir(), "scaffold-mcp-logs");
123
+ const logsDir = path.join(os.tmpdir(), "scaffold-mcp-logs");
124
124
  const logger = pino({
125
125
  level: process.env.LOG_LEVEL || "debug",
126
126
  timestamp: pino.stdTimeFunctions.isoTime
127
127
  }, pino.destination({
128
- dest: path$1.join(logsDir, "scaffold-mcp.log"),
128
+ dest: path.join(logsDir, "scaffold-mcp.log"),
129
129
  mkdir: true,
130
130
  sync: true
131
131
  }));
@@ -164,16 +164,41 @@ const log = {
164
164
  var TemplatesManagerService = class TemplatesManagerService {
165
165
  static SCAFFOLD_CONFIG_FILE = "scaffold.yaml";
166
166
  static TEMPLATES_FOLDER = "templates";
167
+ static TOOLKIT_FOLDER = ".toolkit";
168
+ static SETTINGS_FILE = "settings.yaml";
169
+ static SETTINGS_LOCAL_FILE = "settings.local.yaml";
167
170
  static TOOLKIT_CONFIG_FILE = "toolkit.yaml";
168
171
  /**
172
+ * Recursively merge two plain objects. Primitive and array values in `local`
173
+ * replace those in `base`; plain-object values are merged recursively.
174
+ */
175
+ static deepMerge(base, local) {
176
+ const result = { ...base };
177
+ for (const [key, localValue] of Object.entries(local)) {
178
+ const baseValue = result[key];
179
+ if (localValue !== null && typeof localValue === "object" && !Array.isArray(localValue) && baseValue !== null && typeof baseValue === "object" && !Array.isArray(baseValue)) result[key] = TemplatesManagerService.deepMerge(baseValue, localValue);
180
+ else result[key] = localValue;
181
+ }
182
+ return result;
183
+ }
184
+ /**
185
+ * Deep-merge two ToolkitConfig objects. Plain-object values are merged
186
+ * recursively; primitives and arrays in `local` replace those in `base`.
187
+ * This allows settings.local.yaml to override a single leaf key (e.g.
188
+ * scaffold-mcp.mcp-serve.fallbackTool) without wiping sibling keys.
189
+ */
190
+ static mergeToolkitConfigs(base, local) {
191
+ return TemplatesManagerService.deepMerge(base, local);
192
+ }
193
+ /**
169
194
  * Find the templates directory by searching upwards from the starting path.
170
195
  *
171
196
  * Algorithm:
172
197
  * 1. Start from the provided path (default: current working directory)
173
198
  * 2. Search upwards to find the workspace root (where .git exists or filesystem root)
174
- * 3. Check if toolkit.yaml exists at workspace root
175
- * - If yes, read templatesPath from toolkit.yaml
176
- * - If no, default to 'templates' folder in workspace root
199
+ * 3. Read toolkit config (checks .toolkit/settings.yaml, then toolkit.yaml)
200
+ * - If config has templatesPath, use it
201
+ * - If no config, default to 'templates' folder in workspace root
177
202
  * 4. Verify the templates directory exists
178
203
  *
179
204
  * @param startPath - The path to start searching from (defaults to process.cwd())
@@ -181,18 +206,13 @@ var TemplatesManagerService = class TemplatesManagerService {
181
206
  */
182
207
  static async findTemplatesPath(startPath = process.cwd()) {
183
208
  const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
184
- const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
185
- if (await pathExists(toolkitConfigPath)) {
186
- const yaml$1 = await import("js-yaml");
187
- const content = await fs.readFile(toolkitConfigPath, "utf-8");
188
- const config = yaml$1.load(content);
189
- if (config?.templatesPath) {
190
- const templatesPath$1 = path.isAbsolute(config.templatesPath) ? config.templatesPath : path.join(workspaceRoot, config.templatesPath);
191
- if (await pathExists(templatesPath$1)) return templatesPath$1;
192
- else return null;
193
- }
209
+ const config = await TemplatesManagerService.readToolkitConfig(startPath);
210
+ if (config?.templatesPath) {
211
+ const templatesPath$1 = nodePath.isAbsolute(config.templatesPath) ? config.templatesPath : nodePath.join(workspaceRoot, config.templatesPath);
212
+ if (await pathExists(templatesPath$1)) return templatesPath$1;
213
+ return null;
194
214
  }
195
- const templatesPath = path.join(workspaceRoot, TemplatesManagerService.TEMPLATES_FOLDER);
215
+ const templatesPath = nodePath.join(workspaceRoot, TemplatesManagerService.TEMPLATES_FOLDER);
196
216
  if (await pathExists(templatesPath)) return templatesPath;
197
217
  return null;
198
218
  }
@@ -200,12 +220,12 @@ var TemplatesManagerService = class TemplatesManagerService {
200
220
  * Find the workspace root by searching upwards for .git folder
201
221
  */
202
222
  static async findWorkspaceRoot(startPath) {
203
- let currentPath = path.resolve(startPath);
204
- const rootPath = path.parse(currentPath).root;
223
+ let currentPath = nodePath.resolve(startPath);
224
+ const rootPath = nodePath.parse(currentPath).root;
205
225
  while (true) {
206
- if (await pathExists(path.join(currentPath, ".git"))) return currentPath;
226
+ if (await pathExists(nodePath.join(currentPath, ".git"))) return currentPath;
207
227
  if (currentPath === rootPath) return process.cwd();
208
- currentPath = path.dirname(currentPath);
228
+ currentPath = nodePath.dirname(currentPath);
209
229
  }
210
230
  }
211
231
  /**
@@ -217,18 +237,13 @@ var TemplatesManagerService = class TemplatesManagerService {
217
237
  */
218
238
  static findTemplatesPathSync(startPath = process.cwd()) {
219
239
  const workspaceRoot = TemplatesManagerService.findWorkspaceRootSync(startPath);
220
- const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
221
- if (pathExistsSync(toolkitConfigPath)) {
222
- const yaml$1 = __require("js-yaml");
223
- const content = readFileSync$1(toolkitConfigPath, "utf-8");
224
- const config = yaml$1.load(content);
225
- if (config?.templatesPath) {
226
- const templatesPath$1 = path.isAbsolute(config.templatesPath) ? config.templatesPath : path.join(workspaceRoot, config.templatesPath);
227
- if (pathExistsSync(templatesPath$1)) return templatesPath$1;
228
- else return null;
229
- }
240
+ const config = TemplatesManagerService.readToolkitConfigSync(startPath);
241
+ if (config?.templatesPath) {
242
+ const templatesPath$1 = nodePath.isAbsolute(config.templatesPath) ? config.templatesPath : nodePath.join(workspaceRoot, config.templatesPath);
243
+ if (pathExistsSync(templatesPath$1)) return templatesPath$1;
244
+ return null;
230
245
  }
231
- const templatesPath = path.join(workspaceRoot, TemplatesManagerService.TEMPLATES_FOLDER);
246
+ const templatesPath = nodePath.join(workspaceRoot, TemplatesManagerService.TEMPLATES_FOLDER);
232
247
  if (pathExistsSync(templatesPath)) return templatesPath;
233
248
  return null;
234
249
  }
@@ -236,12 +251,12 @@ var TemplatesManagerService = class TemplatesManagerService {
236
251
  * Find the workspace root synchronously by searching upwards for .git folder
237
252
  */
238
253
  static findWorkspaceRootSync(startPath) {
239
- let currentPath = path.resolve(startPath);
240
- const rootPath = path.parse(currentPath).root;
254
+ let currentPath = nodePath.resolve(startPath);
255
+ const rootPath = nodePath.parse(currentPath).root;
241
256
  while (true) {
242
- if (pathExistsSync(path.join(currentPath, ".git"))) return currentPath;
257
+ if (pathExistsSync(nodePath.join(currentPath, ".git"))) return currentPath;
243
258
  if (currentPath === rootPath) return process.cwd();
244
- currentPath = path.dirname(currentPath);
259
+ currentPath = nodePath.dirname(currentPath);
245
260
  }
246
261
  }
247
262
  /**
@@ -267,44 +282,80 @@ var TemplatesManagerService = class TemplatesManagerService {
267
282
  return TemplatesManagerService.TEMPLATES_FOLDER;
268
283
  }
269
284
  /**
270
- * Read toolkit.yaml configuration from workspace root
285
+ * Read toolkit configuration from workspace root.
286
+ *
287
+ * Priority order:
288
+ * 1. .toolkit/settings.yaml (new location)
289
+ * 2. Shallow-merge .toolkit/settings.local.yaml over settings.yaml if present
290
+ * 3. Fallback to root toolkit.yaml (deprecated, backward-compat)
271
291
  *
272
292
  * @param startPath - The path to start searching from (defaults to process.cwd())
273
293
  * @returns The toolkit configuration object or null if not found
274
294
  */
275
295
  static async readToolkitConfig(startPath = process.cwd()) {
276
296
  const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
277
- const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
278
- if (!await pathExists(toolkitConfigPath)) return null;
279
297
  const yaml$1 = await import("js-yaml");
280
- const content = await fs.readFile(toolkitConfigPath, "utf-8");
298
+ const toolkitFolder = nodePath.join(workspaceRoot, TemplatesManagerService.TOOLKIT_FOLDER);
299
+ const settingsPath = nodePath.join(toolkitFolder, TemplatesManagerService.SETTINGS_FILE);
300
+ const settingsLocalPath = nodePath.join(toolkitFolder, TemplatesManagerService.SETTINGS_LOCAL_FILE);
301
+ if (await pathExists(settingsPath)) {
302
+ const baseContent = await fs.readFile(settingsPath, "utf-8");
303
+ const base = yaml$1.load(baseContent);
304
+ if (await pathExists(settingsLocalPath)) {
305
+ const localContent = await fs.readFile(settingsLocalPath, "utf-8");
306
+ const local = yaml$1.load(localContent);
307
+ return TemplatesManagerService.mergeToolkitConfigs(base, local);
308
+ }
309
+ return base;
310
+ }
311
+ const legacyConfigPath = nodePath.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
312
+ if (!await pathExists(legacyConfigPath)) return null;
313
+ const content = await fs.readFile(legacyConfigPath, "utf-8");
281
314
  return yaml$1.load(content);
282
315
  }
283
316
  /**
284
- * Read toolkit.yaml configuration from workspace root (sync)
317
+ * Read toolkit configuration from workspace root (sync).
318
+ *
319
+ * Priority order:
320
+ * 1. .toolkit/settings.yaml (new location)
321
+ * 2. Shallow-merge .toolkit/settings.local.yaml over settings.yaml if present
322
+ * 3. Fallback to root toolkit.yaml (deprecated, backward-compat)
285
323
  *
286
324
  * @param startPath - The path to start searching from (defaults to process.cwd())
287
325
  * @returns The toolkit configuration object or null if not found
288
326
  */
289
327
  static readToolkitConfigSync(startPath = process.cwd()) {
290
328
  const workspaceRoot = TemplatesManagerService.findWorkspaceRootSync(startPath);
291
- const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
292
- if (!pathExistsSync(toolkitConfigPath)) return null;
293
329
  const yaml$1 = __require("js-yaml");
294
- const content = readFileSync$1(toolkitConfigPath, "utf-8");
295
- return yaml$1.load(content);
330
+ const toolkitFolder = nodePath.join(workspaceRoot, TemplatesManagerService.TOOLKIT_FOLDER);
331
+ const settingsPath = nodePath.join(toolkitFolder, TemplatesManagerService.SETTINGS_FILE);
332
+ const settingsLocalPath = nodePath.join(toolkitFolder, TemplatesManagerService.SETTINGS_LOCAL_FILE);
333
+ if (pathExistsSync(settingsPath)) {
334
+ const base = yaml$1.load(readFileSync$1(settingsPath, "utf-8"));
335
+ if (pathExistsSync(settingsLocalPath)) {
336
+ const local = yaml$1.load(readFileSync$1(settingsLocalPath, "utf-8"));
337
+ return TemplatesManagerService.mergeToolkitConfigs(base, local);
338
+ }
339
+ return base;
340
+ }
341
+ const legacyConfigPath = nodePath.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
342
+ if (!pathExistsSync(legacyConfigPath)) return null;
343
+ return yaml$1.load(readFileSync$1(legacyConfigPath, "utf-8"));
296
344
  }
297
345
  /**
298
- * Write toolkit.yaml configuration to workspace root
346
+ * Write toolkit configuration to .toolkit/settings.yaml.
347
+ * Creates the .toolkit directory if it does not exist.
299
348
  *
300
349
  * @param config - The toolkit configuration to write
301
350
  * @param startPath - The path to start searching from (defaults to process.cwd())
302
351
  */
303
352
  static async writeToolkitConfig(config, startPath = process.cwd()) {
304
353
  const workspaceRoot = await TemplatesManagerService.findWorkspaceRoot(startPath);
305
- const toolkitConfigPath = path.join(workspaceRoot, TemplatesManagerService.TOOLKIT_CONFIG_FILE);
354
+ const toolkitFolder = nodePath.join(workspaceRoot, TemplatesManagerService.TOOLKIT_FOLDER);
355
+ const settingsPath = nodePath.join(toolkitFolder, TemplatesManagerService.SETTINGS_FILE);
356
+ await fs.mkdir(toolkitFolder, { recursive: true });
306
357
  const content = (await import("js-yaml")).dump(config, { indent: 2 });
307
- await fs.writeFile(toolkitConfigPath, content, "utf-8");
358
+ await fs.writeFile(settingsPath, content, "utf-8");
308
359
  }
309
360
  /**
310
361
  * Get the workspace root directory
@@ -373,13 +424,13 @@ var ProjectConfigResolver = class ProjectConfigResolver {
373
424
  */
374
425
  static async resolveProjectConfig(projectPath, explicitTemplate) {
375
426
  try {
376
- const absolutePath = path.resolve(projectPath);
427
+ const absolutePath = nodePath.resolve(projectPath);
377
428
  if (explicitTemplate) return {
378
429
  type: ProjectType.MONOLITH,
379
430
  sourceTemplate: explicitTemplate,
380
431
  configSource: ConfigSource.TOOLKIT_YAML
381
432
  };
382
- const projectJsonPath = path.join(absolutePath, "project.json");
433
+ const projectJsonPath = nodePath.join(absolutePath, "project.json");
383
434
  if (await pathExists(projectJsonPath)) {
384
435
  const projectJson = await readJson(projectJsonPath);
385
436
  if (projectJson.sourceTemplate && typeof projectJson.sourceTemplate === "string" && projectJson.sourceTemplate.trim()) return {
@@ -470,12 +521,12 @@ Run 'scaffold-mcp scaffold list --help' for more info.`;
470
521
  * @param sourceTemplate - The template identifier
471
522
  */
472
523
  static async createProjectJson(projectPath, projectName, sourceTemplate) {
473
- const projectJsonPath = path.join(projectPath, "project.json");
524
+ const projectJsonPath = nodePath.join(projectPath, "project.json");
474
525
  try {
475
526
  let projectJson;
476
527
  if (await pathExists(projectJsonPath)) projectJson = await readJson(projectJsonPath);
477
528
  else {
478
- const relativePath = path.relative(projectPath, process.cwd());
529
+ const relativePath = nodePath.relative(projectPath, process.cwd());
479
530
  projectJson = {
480
531
  name: projectName,
481
532
  $schema: relativePath ? `${relativePath}/node_modules/nx/schemas/project-schema.json` : "node_modules/nx/schemas/project-schema.json",
@@ -527,15 +578,15 @@ var ProjectFinderService = class {
527
578
  * @returns Project configuration or null if not found
528
579
  */
529
580
  async findProjectForFile(filePath) {
530
- const normalizedPath = path.isAbsolute(filePath) ? filePath : path.join(this.workspaceRoot, filePath);
531
- let currentDir = path.dirname(normalizedPath);
581
+ const normalizedPath = nodePath.isAbsolute(filePath) ? filePath : nodePath.join(this.workspaceRoot, filePath);
582
+ let currentDir = nodePath.dirname(normalizedPath);
532
583
  while (currentDir !== "/" && currentDir.startsWith(this.workspaceRoot)) {
533
- const projectJsonPath = path.join(currentDir, "project.json");
584
+ const projectJsonPath = nodePath.join(currentDir, "project.json");
534
585
  try {
535
586
  const project = await this.loadProjectConfig(projectJsonPath);
536
587
  if (project) return project;
537
588
  } catch {}
538
- currentDir = path.dirname(currentDir);
589
+ currentDir = nodePath.dirname(currentDir);
539
590
  }
540
591
  return null;
541
592
  }
@@ -546,15 +597,15 @@ var ProjectFinderService = class {
546
597
  * @returns Project configuration or null if not found
547
598
  */
548
599
  findProjectForFileSync(filePath) {
549
- const normalizedPath = path.isAbsolute(filePath) ? filePath : path.join(this.workspaceRoot, filePath);
550
- let currentDir = path.dirname(normalizedPath);
600
+ const normalizedPath = nodePath.isAbsolute(filePath) ? filePath : nodePath.join(this.workspaceRoot, filePath);
601
+ let currentDir = nodePath.dirname(normalizedPath);
551
602
  while (currentDir !== "/" && currentDir.startsWith(this.workspaceRoot)) {
552
- const projectJsonPath = path.join(currentDir, "project.json");
603
+ const projectJsonPath = nodePath.join(currentDir, "project.json");
553
604
  try {
554
605
  const project = this.loadProjectConfigSync(projectJsonPath);
555
606
  if (project) return project;
556
607
  } catch {}
557
- currentDir = path.dirname(currentDir);
608
+ currentDir = nodePath.dirname(currentDir);
558
609
  }
559
610
  return null;
560
611
  }
@@ -567,8 +618,8 @@ var ProjectFinderService = class {
567
618
  const content = await fs.readFile(projectJsonPath, "utf-8");
568
619
  const config = JSON.parse(content);
569
620
  const projectConfig = {
570
- name: config.name || path.basename(path.dirname(projectJsonPath)),
571
- root: path.dirname(projectJsonPath),
621
+ name: config.name || nodePath.basename(nodePath.dirname(projectJsonPath)),
622
+ root: nodePath.dirname(projectJsonPath),
572
623
  sourceTemplate: config.sourceTemplate,
573
624
  projectType: config.projectType
574
625
  };
@@ -587,8 +638,8 @@ var ProjectFinderService = class {
587
638
  const content = readFileSync$1(projectJsonPath, "utf-8");
588
639
  const config = JSON.parse(content);
589
640
  const projectConfig = {
590
- name: config.name || path.basename(path.dirname(projectJsonPath)),
591
- root: path.dirname(projectJsonPath),
641
+ name: config.name || nodePath.basename(nodePath.dirname(projectJsonPath)),
642
+ root: nodePath.dirname(projectJsonPath),
592
643
  sourceTemplate: config.sourceTemplate,
593
644
  projectType: config.projectType
594
645
  };
@@ -648,7 +699,7 @@ var ScaffoldProcessingService = class {
648
699
  * Now supports tracking existing files separately from created files
649
700
  */
650
701
  async copyAndProcess(sourcePath, targetPath, variables, createdFiles, existingFiles) {
651
- await this.fileSystem.ensureDir(path.dirname(targetPath));
702
+ await this.fileSystem.ensureDir(nodePath.dirname(targetPath));
652
703
  if (await this.fileSystem.pathExists(targetPath) && existingFiles) {
653
704
  await this.trackExistingFiles(targetPath, existingFiles);
654
705
  return;
@@ -670,7 +721,7 @@ var ScaffoldProcessingService = class {
670
721
  }
671
722
  for (const item of items) {
672
723
  if (!item) continue;
673
- const itemPath = path.join(dirPath, item);
724
+ const itemPath = nodePath.join(dirPath, item);
674
725
  try {
675
726
  const stat$1 = await this.fileSystem.stat(itemPath);
676
727
  if (stat$1.isDirectory()) await this.trackCreatedFilesRecursive(itemPath, createdFiles);
@@ -693,7 +744,7 @@ var ScaffoldProcessingService = class {
693
744
  }
694
745
  for (const item of items) {
695
746
  if (!item) continue;
696
- const itemPath = path.join(dirPath, item);
747
+ const itemPath = nodePath.join(dirPath, item);
697
748
  try {
698
749
  const stat$1 = await this.fileSystem.stat(itemPath);
699
750
  if (stat$1.isDirectory()) await this.trackExistingFilesRecursive(itemPath, existingFiles);
@@ -820,12 +871,12 @@ async function gitInit(projectPath) {
820
871
  * }
821
872
  */
822
873
  async function findWorkspaceRoot(startPath = process.cwd()) {
823
- let currentPath = path.resolve(startPath);
824
- const rootPath = path.parse(currentPath).root;
874
+ let currentPath = nodePath.resolve(startPath);
875
+ const rootPath = nodePath.parse(currentPath).root;
825
876
  while (true) {
826
- if (await pathExists(path.join(currentPath, ".git"))) return currentPath;
877
+ if (await pathExists(nodePath.join(currentPath, ".git"))) return currentPath;
827
878
  if (currentPath === rootPath) return null;
828
- currentPath = path.dirname(currentPath);
879
+ currentPath = nodePath.dirname(currentPath);
829
880
  }
830
881
  }
831
882
  /**
@@ -907,7 +958,7 @@ async function cloneSubdirectory(repoUrl, branch, subdirectory, targetFolder) {
907
958
  "core.sparseCheckout",
908
959
  "true"
909
960
  ], tempFolder);
910
- await writeFile(path.join(tempFolder, ".git", "info", "sparse-checkout"), `${subdirectory}\n`);
961
+ await writeFile(nodePath.join(tempFolder, ".git", "info", "sparse-checkout"), `${subdirectory}\n`);
911
962
  await execGit([
912
963
  "pull",
913
964
  "--depth=1",
@@ -915,7 +966,7 @@ async function cloneSubdirectory(repoUrl, branch, subdirectory, targetFolder) {
915
966
  "--",
916
967
  branch
917
968
  ], tempFolder);
918
- const sourceDir = path.join(tempFolder, subdirectory);
969
+ const sourceDir = nodePath.join(tempFolder, subdirectory);
919
970
  if (!await pathExists(sourceDir)) throw new Error(`Subdirectory '${subdirectory}' not found in repository at branch '${branch}'`);
920
971
  if (await pathExists(targetFolder)) throw new Error(`Target folder already exists: ${targetFolder}`);
921
972
  await move(sourceDir, targetFolder);
@@ -942,7 +993,7 @@ async function cloneRepository(repoUrl, targetFolder) {
942
993
  repoUrl,
943
994
  targetFolder
944
995
  ]);
945
- const gitFolder = path.join(targetFolder, ".git");
996
+ const gitFolder = nodePath.join(targetFolder, ".git");
946
997
  if (await pathExists(gitFolder)) await remove(gitFolder);
947
998
  }
948
999
  /**
@@ -1159,7 +1210,7 @@ const MONOREPO_INDICATOR_FILES = [
1159
1210
  */
1160
1211
  async function detectProjectType(workspaceRoot) {
1161
1212
  const indicators = [];
1162
- const toolkitYamlPath = path.join(workspaceRoot, "toolkit.yaml");
1213
+ const toolkitYamlPath = nodePath.join(workspaceRoot, "toolkit.yaml");
1163
1214
  if (await pathExists(toolkitYamlPath)) try {
1164
1215
  const content = await fs.readFile(toolkitYamlPath, "utf-8");
1165
1216
  const config = yaml.load(content);
@@ -1171,14 +1222,14 @@ async function detectProjectType(workspaceRoot) {
1171
1222
  };
1172
1223
  }
1173
1224
  } catch {}
1174
- for (const filename of MONOREPO_INDICATOR_FILES) if (await pathExists(path.join(workspaceRoot, filename))) {
1225
+ for (const filename of MONOREPO_INDICATOR_FILES) if (await pathExists(nodePath.join(workspaceRoot, filename))) {
1175
1226
  indicators.push(`${filename} found`);
1176
1227
  return {
1177
1228
  projectType: ProjectType.MONOREPO,
1178
1229
  indicators
1179
1230
  };
1180
1231
  }
1181
- const packageJsonPath = path.join(workspaceRoot, "package.json");
1232
+ const packageJsonPath = nodePath.join(workspaceRoot, "package.json");
1182
1233
  if (await pathExists(packageJsonPath)) try {
1183
1234
  if ((await readJson(packageJsonPath)).workspaces) {
1184
1235
  indicators.push("package.json with workspaces found");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agiflowai/aicode-utils",
3
3
  "description": "Shared utilities and types for AI-powered code generation, scaffolding, and analysis",
4
- "version": "1.0.15",
4
+ "version": "1.0.17",
5
5
  "license": "AGPL-3.0",
6
6
  "author": "AgiflowIO",
7
7
  "repository": {