wave-agent-sdk 0.17.3 → 0.17.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"skillManager.d.ts","sourceRoot":"","sources":["../../src/managers/skillManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,KAAK,EAGL,aAAa,EACb,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAU3B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD;;GAEG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAc1C,OAAO,CAAC,SAAS;IAbnB,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,YAAY,CAAU;gBAGpB,SAAS,EAAE,SAAS,EAC5B,OAAO,GAAE,mBAAwB;IAUnC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBjC;;OAEG;YACW,aAAa;IAqC3B;;OAEG;YACW,YAAY;IAkC1B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,kBAAkB,IAAI,aAAa,EAAE;IAQrC;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAQzD;;;OAGG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAgBzD;;OAEG;YACW,cAAc;IA4B5B;;OAEG;YACW,uBAAuB;IAoFrC;;OAEG;YACW,oBAAoB;IA4BlC;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC;QAC/C,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,sBAAsB,CAAC;QACjC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;IA8BF;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAC5C;QACE,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,KAAK,CAAC;KACd,GACD;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,CAAA;KAAE,CACzC;IA6BD;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;OAEG;YACW,yBAAyB;IASvC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;CA8BhE"}
1
+ {"version":3,"file":"skillManager.d.ts","sourceRoot":"","sources":["../../src/managers/skillManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,KAAK,EAGL,aAAa,EACb,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAU3B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD;;GAEG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAc1C,OAAO,CAAC,SAAS;IAbnB,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,kBAAkB,CAA4B;IACtD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,YAAY,CAAU;gBAGpB,SAAS,EAAE,SAAS,EAC5B,OAAO,GAAE,mBAAwB;IAUnC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBjC;;OAEG;YACW,aAAa;IAqC3B;;OAEG;YACW,YAAY;IAkC1B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,kBAAkB,IAAI,aAAa,EAAE;IAQrC;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAQzD;;;OAGG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAgBzD;;OAEG;YACW,cAAc;IA4B5B;;OAEG;YACW,uBAAuB;IAoFrC;;OAEG;YACW,oBAAoB;IA4BlC;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC;QAC/C,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,sBAAsB,CAAC;QACjC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;IA8BF;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAC5C;QACE,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,KAAK,CAAC;KACd,GACD;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,CAAA;KAAE,CACzC;IA6BD;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA0B3B;;OAEG;YACW,yBAAyB;IASvC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI;CA8BhE"}
@@ -343,7 +343,7 @@ export class SkillManager extends EventEmitter {
343
343
  prepareSkillContent(skill, argsString) {
344
344
  const skillPath = `Base directory for this skill: ${skill.skillPath}\n\n`;
345
345
  // Extract content after frontmatter
346
- const contentMatch = skill.content.match(/^---\n[\s\S]*?\n---\n([\s\S]*)$/);
346
+ const contentMatch = skill.content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n([\s\S]*)$/);
347
347
  let mainContent = contentMatch ? contentMatch[1].trim() : skill.content;
348
348
  // 1. Substitute parameters ($1, $ARGUMENTS, etc.)
349
349
  mainContent = substituteCommandParameters(mainContent, argsString);
@@ -33,6 +33,15 @@ export declare class MarketplaceService {
33
33
  * to user-level settings if they aren't already declared there.
34
34
  */
35
35
  private runMigration;
36
+ /**
37
+ * Seeds the builtin marketplace on first startup.
38
+ * Adds it to user-scope settings and marks the cache as seeded.
39
+ */
40
+ private seedBuiltinMarketplace;
41
+ /**
42
+ * Sets the builtinSeeded flag in the cache registry, preserving all other fields.
43
+ */
44
+ private setBuiltinSeeded;
36
45
  /**
37
46
  * Check if a lock file is stale by reading its PID and checking if the process is alive.
38
47
  * Returns true if the lock is stale and safe to remove.
@@ -97,6 +106,12 @@ export declare class MarketplaceService {
97
106
  * Removes a marketplace by name from the specified scope
98
107
  */
99
108
  removeMarketplace(name: string, scope?: Scope): Promise<void>;
109
+ /**
110
+ * Uninstalls all plugins belonging to a given marketplace.
111
+ * Removes them from installed_plugins.json, deletes cache files,
112
+ * and cleans up enabledPlugins entries from all scopes.
113
+ */
114
+ private uninstallPluginsByMarketplace;
100
115
  /**
101
116
  * Updates a specific marketplace or all marketplaces
102
117
  */
@@ -1 +1 @@
1
- {"version":3,"file":"MarketplaceService.d.ts","sourceRoot":"","sources":["../../src/services/MarketplaceService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MarketplaceService.d.ts","sourceRoot":"","sources":["../../src/services/MarketplaceService.ts"],"names":[],"mappings":"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"}
@@ -28,6 +28,9 @@ export class MarketplaceService {
28
28
  this.gitService = new GitService();
29
29
  this.ensureDirectoryStructure();
30
30
  this.runMigration();
31
+ // Stored dynamically to avoid widening keyof MarketplaceService
32
+ this._seedComplete =
33
+ this.seedBuiltinMarketplace();
31
34
  }
32
35
  /**
33
36
  * Ensures the required directory structure exists in ~/.wave/plugins
@@ -65,6 +68,46 @@ export class MarketplaceService {
65
68
  // Migration failure should not block startup
66
69
  }
67
70
  }
71
+ /**
72
+ * Seeds the builtin marketplace on first startup.
73
+ * Adds it to user-scope settings and marks the cache as seeded.
74
+ */
75
+ async seedBuiltinMarketplace() {
76
+ try {
77
+ const cache = await this.getCacheRegistry();
78
+ if (cache?.builtinSeeded)
79
+ return;
80
+ const builtin = MarketplaceService.BUILTIN_MARKETPLACE;
81
+ // Add to user-scope settings if not already in any scope
82
+ const scoped = this.configurationService.getMergedMarketplaces(this.workdir);
83
+ if (!scoped[builtin.name]) {
84
+ await this.configurationService.addMarketplaceToScope(this.workdir, "user", builtin.name, { source: builtin.source, autoUpdate: builtin.autoUpdate });
85
+ }
86
+ // Update cache: add entry + set builtinSeeded flag
87
+ await this.updateCacheMarketplace(builtin.name, {
88
+ source: builtin.source,
89
+ autoUpdate: builtin.autoUpdate,
90
+ isBuiltin: true,
91
+ declaredScope: "builtin",
92
+ });
93
+ await this.setBuiltinSeeded(true);
94
+ }
95
+ catch {
96
+ // Seeding failure should not block startup
97
+ }
98
+ }
99
+ /**
100
+ * Sets the builtinSeeded flag in the cache registry, preserving all other fields.
101
+ */
102
+ async setBuiltinSeeded(value) {
103
+ const registry = await this.getCacheRegistry();
104
+ const tmpPath = `${this.knownMarketplacesPath}.tmp`;
105
+ await fs.writeFile(tmpPath, JSON.stringify({
106
+ builtinSeeded: value,
107
+ marketplaces: registry?.marketplaces ?? [],
108
+ }, null, 2));
109
+ await fs.rename(tmpPath, this.knownMarketplacesPath);
110
+ }
68
111
  /**
69
112
  * Check if a lock file is stale by reading its PID and checking if the process is alive.
70
113
  * Returns true if the lock is stale and safe to remove.
@@ -192,7 +235,10 @@ export class MarketplaceService {
192
235
  });
193
236
  }
194
237
  const tmpPath = `${this.knownMarketplacesPath}.tmp`;
195
- await fs.writeFile(tmpPath, JSON.stringify({ marketplaces }, null, 2));
238
+ await fs.writeFile(tmpPath, JSON.stringify({
239
+ builtinSeeded: registry?.builtinSeeded ?? false,
240
+ marketplaces,
241
+ }, null, 2));
196
242
  await fs.rename(tmpPath, this.knownMarketplacesPath);
197
243
  }
198
244
  /**
@@ -203,7 +249,10 @@ export class MarketplaceService {
203
249
  const marketplaces = registry?.marketplaces ?? [];
204
250
  const filtered = marketplaces.filter((m) => m.name !== name);
205
251
  const tmpPath = `${this.knownMarketplacesPath}.tmp`;
206
- await fs.writeFile(tmpPath, JSON.stringify({ marketplaces: filtered }, null, 2));
252
+ await fs.writeFile(tmpPath, JSON.stringify({
253
+ builtinSeeded: registry?.builtinSeeded ?? false,
254
+ marketplaces: filtered,
255
+ }, null, 2));
207
256
  await fs.rename(tmpPath, this.knownMarketplacesPath);
208
257
  }
209
258
  /**
@@ -402,6 +451,8 @@ export class MarketplaceService {
402
451
  async removeMarketplace(name, scope) {
403
452
  return this.withLock(async () => {
404
453
  const targetScope = scope || this.getMarketplaceDeclaringSource(name) || "user";
454
+ // Uninstall all plugins from this marketplace
455
+ await this.uninstallPluginsByMarketplace(name);
405
456
  if (targetScope !== "builtin") {
406
457
  await this.configurationService.removeMarketplaceFromScope(this.workdir, targetScope, name);
407
458
  }
@@ -409,6 +460,36 @@ export class MarketplaceService {
409
460
  await this.removeFromCache(name);
410
461
  });
411
462
  }
463
+ /**
464
+ * Uninstalls all plugins belonging to a given marketplace.
465
+ * Removes them from installed_plugins.json, deletes cache files,
466
+ * and cleans up enabledPlugins entries from all scopes.
467
+ */
468
+ async uninstallPluginsByMarketplace(marketplaceName) {
469
+ const installedRegistry = await this.getInstalledPlugins();
470
+ const pluginsFromMarketplace = installedRegistry.plugins.filter((p) => p.marketplace === marketplaceName);
471
+ if (pluginsFromMarketplace.length === 0)
472
+ return;
473
+ // Remove all plugins from this marketplace from the registry
474
+ installedRegistry.plugins = installedRegistry.plugins.filter((p) => p.marketplace !== marketplaceName);
475
+ await this.saveInstalledPlugins(installedRegistry);
476
+ // Delete cache files that are no longer referenced
477
+ const remainingCachePaths = new Set(installedRegistry.plugins.map((p) => p.cachePath));
478
+ for (const plugin of pluginsFromMarketplace) {
479
+ if (!remainingCachePaths.has(plugin.cachePath) &&
480
+ existsSync(plugin.cachePath)) {
481
+ await fs.rm(plugin.cachePath, { recursive: true, force: true });
482
+ }
483
+ }
484
+ // Remove enabledPlugins entries from all scopes
485
+ const scopes = ["user", "project", "local"];
486
+ for (const plugin of pluginsFromMarketplace) {
487
+ const pluginId = `${plugin.name}@${plugin.marketplace}`;
488
+ for (const s of scopes) {
489
+ await this.configurationService.removeEnabledPlugin(this.workdir, s, pluginId);
490
+ }
491
+ }
492
+ }
412
493
  /**
413
494
  * Updates a specific marketplace or all marketplaces
414
495
  */
@@ -1 +1 @@
1
- {"version":3,"file":"fileWatcher.d.ts","sourceRoot":"","sources":["../../src/services/fileWatcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AAaD,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,OAAO,CAAC,QAAQ,CAA4C;IAC5D,OAAO,CAAC,aAAa,CAAmC;IACxD,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,MAAM,CAAC,CAAS;gBAEZ,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC;IAahE;;;OAGG;IACG,SAAS,CACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GACxC,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;OAGG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB9C;;;OAGG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI;IA0BxD;;;OAGG;IACH,qBAAqB,IAAI,iBAAiB,EAAE;IAM5C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAahB,iBAAiB;IAqD/B,OAAO,CAAC,wBAAwB;IAoChC,OAAO,CAAC,eAAe;CAoCxB"}
1
+ {"version":3,"file":"fileWatcher.d.ts","sourceRoot":"","sources":["../../src/services/fileWatcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AAaD,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,OAAO,CAAC,QAAQ,CAA4C;IAC5D,OAAO,CAAC,aAAa,CAAmC;IACxD,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,MAAM,CAAC,CAAS;gBAEZ,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC;IAahE;;;OAGG;IACG,SAAS,CACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GACxC,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;OAGG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB9C;;;OAGG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI;IA0BxD;;;OAGG;IACH,qBAAqB,IAAI,iBAAiB,EAAE;IAM5C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAahB,iBAAiB;IAqD/B,OAAO,CAAC,wBAAwB;IAoChC,OAAO,CAAC,eAAe;CAmCxB"}
@@ -198,11 +198,10 @@ export class FileWatcherService extends EventEmitter {
198
198
  };
199
199
  // Notify all watchers that match the path or are parents of the path
200
200
  for (const [watchedPath, entry] of this.watchers.entries()) {
201
- if (filePath === watchedPath ||
202
- filePath.startsWith(watchedPath + "/") ||
203
- // Handle cases where the watched path might be a file and we get an event for it
204
- // (already covered by filePath === watchedPath)
205
- false) {
201
+ const normalizedFilePath = filePath.replace(/\\/g, "/");
202
+ const normalizedWatchedPath = watchedPath.replace(/\\/g, "/");
203
+ if (normalizedFilePath === normalizedWatchedPath ||
204
+ normalizedFilePath.startsWith(normalizedWatchedPath + "/")) {
206
205
  entry.lastEvent = event.timestamp;
207
206
  // Notify all callbacks for this watcher
208
207
  for (const callback of entry.callbacks) {
@@ -43,6 +43,7 @@ export interface KnownMarketplace {
43
43
  declaredScope?: "user" | "project" | "local" | "builtin";
44
44
  }
45
45
  export interface KnownMarketplacesRegistry {
46
+ builtinSeeded?: boolean;
46
47
  marketplaces: KnownMarketplace[];
47
48
  }
48
49
  export interface InstalledPlugin {
@@ -1 +1 @@
1
- {"version":3,"file":"marketplace.d.ts","sourceRoot":"","sources":["../../src/types/marketplace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAwB,SAAQ,sBAAsB;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,EAAE,sBAAsB,EAAE,CAAC;CACnC;AAED,MAAM,MAAM,iBAAiB,GACzB;IACE,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd,GACD;IACE,MAAM,EAAE,QAAQ,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GACD;IACE,MAAM,EAAE,KAAK,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEN,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uFAAuF;IACvF,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;CAC1D;AAED,MAAM,WAAW,yBAAyB;IACxC,YAAY,EAAE,gBAAgB,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B"}
1
+ {"version":3,"file":"marketplace.d.ts","sourceRoot":"","sources":["../../src/types/marketplace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAwB,SAAQ,sBAAsB;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,EAAE,sBAAsB,EAAE,CAAC;CACnC;AAED,MAAM,MAAM,iBAAiB,GACzB;IACE,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd,GACD;IACE,MAAM,EAAE,QAAQ,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GACD;IACE,MAAM,EAAE,KAAK,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEN,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uFAAuF;IACvF,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;CAC1D;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,EAAE,gBAAgB,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"commandPathResolver.d.ts","sourceRoot":"","sources":["../../src/utils/commandPathResolver.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CA4C3E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAS5D"}
1
+ {"version":3,"file":"commandPathResolver.d.ts","sourceRoot":"","sources":["../../src/utils/commandPathResolver.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CA8C3E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAS5D"}
@@ -21,7 +21,9 @@ export function generateCommandId(filePath, rootDir) {
21
21
  if (!relativePath || relativePath === ".") {
22
22
  throw new Error("Command filename cannot be empty");
23
23
  }
24
- const segments = relativePath.split("/").filter((segment) => segment !== "");
24
+ const segments = relativePath
25
+ .split(/[\\/]/)
26
+ .filter((segment) => segment !== "");
25
27
  // Remove .md extension from the last segment
26
28
  const lastSegment = segments[segments.length - 1];
27
29
  if (!lastSegment.endsWith(".md")) {
@@ -1 +1 @@
1
- {"version":3,"file":"skillParser.d.ts","sourceRoot":"","sources":["../../src/utils/skillParser.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EAEjB,aAAa,EACd,MAAM,mBAAmB,CAAC;AAE3B;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,iBAAsB,GAC9B,eAAe,CA8FjB;AAyDD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,EAAE,CAwCvE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOtD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAa5E"}
1
+ {"version":3,"file":"skillParser.d.ts","sourceRoot":"","sources":["../../src/utils/skillParser.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EAEjB,aAAa,EACd,MAAM,mBAAmB,CAAC;AAE3B;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,iBAAsB,GAC9B,eAAe,CAgGjB;AAyDD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,EAAE,CAwCvE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOtD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAa5E"}
@@ -22,7 +22,7 @@ export function parseSkillFile(filePath, options = {}) {
22
22
  const content = readFileSync(filePath, "utf-8");
23
23
  result.content = content;
24
24
  // Parse YAML frontmatter
25
- const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
25
+ const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
26
26
  if (!frontmatterMatch) {
27
27
  result.validationErrors.push("Missing YAML frontmatter");
28
28
  return result;
@@ -35,7 +35,8 @@ export function parseSkillFile(filePath, options = {}) {
35
35
  }
36
36
  // Determine skill type and path
37
37
  const skillPath = basePath || dirname(filePath);
38
- const skillType = skillPath.includes("/.wave/skills")
38
+ const skillType = skillPath.includes("/.wave/skills") ||
39
+ skillPath.includes("\\.wave\\skills")
39
40
  ? "project"
40
41
  : "personal";
41
42
  // Extract allowed tools
@@ -1 +1 @@
1
- {"version":3,"file":"subagentParser.d.ts","sourceRoot":"","sources":["../../src/utils/subagentParser.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAkKD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,QAAQ,EACf,UAAU,EAAE,MAAM,GACjB,qBAAqB,CAEvB;AAqCD;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAsBlC;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAGvC"}
1
+ {"version":3,"file":"subagentParser.d.ts","sourceRoot":"","sources":["../../src/utils/subagentParser.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAmKD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,QAAQ,EACf,UAAU,EAAE,MAAM,GACjB,qBAAqB,CAEvB;AAqCD;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAsBlC;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAGvC"}
@@ -6,7 +6,7 @@ import { getBuiltinSubagentsDir } from "./configPaths.js";
6
6
  * Parse YAML frontmatter from markdown file content
7
7
  */
8
8
  function parseFrontmatter(content) {
9
- const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
9
+ const frontmatterRegex = /^---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*\r?\n([\s\S]*)$/;
10
10
  const match = content.match(frontmatterRegex);
11
11
  if (!match) {
12
12
  return { frontmatter: {}, body: content.trim() };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "0.17.3",
3
+ "version": "0.17.5",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",
@@ -442,7 +442,9 @@ export class SkillManager extends EventEmitter {
442
442
  const skillPath = `Base directory for this skill: ${skill.skillPath}\n\n`;
443
443
 
444
444
  // Extract content after frontmatter
445
- const contentMatch = skill.content.match(/^---\n[\s\S]*?\n---\n([\s\S]*)$/);
445
+ const contentMatch = skill.content.match(
446
+ /^---\r?\n[\s\S]*?\r?\n---\r?\n([\s\S]*)$/,
447
+ );
446
448
  let mainContent = contentMatch ? contentMatch[1].trim() : skill.content;
447
449
 
448
450
  // 1. Substitute parameters ($1, $ARGUMENTS, etc.)
@@ -68,6 +68,9 @@ export class MarketplaceService {
68
68
 
69
69
  this.ensureDirectoryStructure();
70
70
  this.runMigration();
71
+ // Stored dynamically to avoid widening keyof MarketplaceService
72
+ (this as Record<string, unknown>)._seedComplete =
73
+ this.seedBuiltinMarketplace();
71
74
  }
72
75
 
73
76
  /**
@@ -121,6 +124,63 @@ export class MarketplaceService {
121
124
  }
122
125
  }
123
126
 
127
+ /**
128
+ * Seeds the builtin marketplace on first startup.
129
+ * Adds it to user-scope settings and marks the cache as seeded.
130
+ */
131
+ private async seedBuiltinMarketplace(): Promise<void> {
132
+ try {
133
+ const cache = await this.getCacheRegistry();
134
+ if (cache?.builtinSeeded) return;
135
+
136
+ const builtin = MarketplaceService.BUILTIN_MARKETPLACE;
137
+
138
+ // Add to user-scope settings if not already in any scope
139
+ const scoped = this.configurationService.getMergedMarketplaces(
140
+ this.workdir,
141
+ );
142
+ if (!scoped[builtin.name]) {
143
+ await this.configurationService.addMarketplaceToScope(
144
+ this.workdir,
145
+ "user",
146
+ builtin.name,
147
+ { source: builtin.source, autoUpdate: builtin.autoUpdate },
148
+ );
149
+ }
150
+
151
+ // Update cache: add entry + set builtinSeeded flag
152
+ await this.updateCacheMarketplace(builtin.name, {
153
+ source: builtin.source,
154
+ autoUpdate: builtin.autoUpdate,
155
+ isBuiltin: true,
156
+ declaredScope: "builtin",
157
+ });
158
+ await this.setBuiltinSeeded(true);
159
+ } catch {
160
+ // Seeding failure should not block startup
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Sets the builtinSeeded flag in the cache registry, preserving all other fields.
166
+ */
167
+ private async setBuiltinSeeded(value: boolean): Promise<void> {
168
+ const registry = await this.getCacheRegistry();
169
+ const tmpPath = `${this.knownMarketplacesPath}.tmp`;
170
+ await fs.writeFile(
171
+ tmpPath,
172
+ JSON.stringify(
173
+ {
174
+ builtinSeeded: value,
175
+ marketplaces: registry?.marketplaces ?? [],
176
+ },
177
+ null,
178
+ 2,
179
+ ),
180
+ );
181
+ await fs.rename(tmpPath, this.knownMarketplacesPath);
182
+ }
183
+
124
184
  /**
125
185
  * Check if a lock file is stale by reading its PID and checking if the process is alive.
126
186
  * Returns true if the lock is stale and safe to remove.
@@ -258,7 +318,17 @@ export class MarketplaceService {
258
318
  });
259
319
  }
260
320
  const tmpPath = `${this.knownMarketplacesPath}.tmp`;
261
- await fs.writeFile(tmpPath, JSON.stringify({ marketplaces }, null, 2));
321
+ await fs.writeFile(
322
+ tmpPath,
323
+ JSON.stringify(
324
+ {
325
+ builtinSeeded: registry?.builtinSeeded ?? false,
326
+ marketplaces,
327
+ },
328
+ null,
329
+ 2,
330
+ ),
331
+ );
262
332
  await fs.rename(tmpPath, this.knownMarketplacesPath);
263
333
  }
264
334
 
@@ -272,7 +342,14 @@ export class MarketplaceService {
272
342
  const tmpPath = `${this.knownMarketplacesPath}.tmp`;
273
343
  await fs.writeFile(
274
344
  tmpPath,
275
- JSON.stringify({ marketplaces: filtered }, null, 2),
345
+ JSON.stringify(
346
+ {
347
+ builtinSeeded: registry?.builtinSeeded ?? false,
348
+ marketplaces: filtered,
349
+ },
350
+ null,
351
+ 2,
352
+ ),
276
353
  );
277
354
  await fs.rename(tmpPath, this.knownMarketplacesPath);
278
355
  }
@@ -536,6 +613,9 @@ export class MarketplaceService {
536
613
  const targetScope =
537
614
  scope || this.getMarketplaceDeclaringSource(name) || "user";
538
615
 
616
+ // Uninstall all plugins from this marketplace
617
+ await this.uninstallPluginsByMarketplace(name);
618
+
539
619
  if (targetScope !== "builtin") {
540
620
  await this.configurationService.removeMarketplaceFromScope(
541
621
  this.workdir,
@@ -549,6 +629,54 @@ export class MarketplaceService {
549
629
  });
550
630
  }
551
631
 
632
+ /**
633
+ * Uninstalls all plugins belonging to a given marketplace.
634
+ * Removes them from installed_plugins.json, deletes cache files,
635
+ * and cleans up enabledPlugins entries from all scopes.
636
+ */
637
+ private async uninstallPluginsByMarketplace(
638
+ marketplaceName: string,
639
+ ): Promise<void> {
640
+ const installedRegistry = await this.getInstalledPlugins();
641
+ const pluginsFromMarketplace = installedRegistry.plugins.filter(
642
+ (p) => p.marketplace === marketplaceName,
643
+ );
644
+
645
+ if (pluginsFromMarketplace.length === 0) return;
646
+
647
+ // Remove all plugins from this marketplace from the registry
648
+ installedRegistry.plugins = installedRegistry.plugins.filter(
649
+ (p) => p.marketplace !== marketplaceName,
650
+ );
651
+ await this.saveInstalledPlugins(installedRegistry);
652
+
653
+ // Delete cache files that are no longer referenced
654
+ const remainingCachePaths = new Set(
655
+ installedRegistry.plugins.map((p) => p.cachePath),
656
+ );
657
+ for (const plugin of pluginsFromMarketplace) {
658
+ if (
659
+ !remainingCachePaths.has(plugin.cachePath) &&
660
+ existsSync(plugin.cachePath)
661
+ ) {
662
+ await fs.rm(plugin.cachePath, { recursive: true, force: true });
663
+ }
664
+ }
665
+
666
+ // Remove enabledPlugins entries from all scopes
667
+ const scopes: Scope[] = ["user", "project", "local"];
668
+ for (const plugin of pluginsFromMarketplace) {
669
+ const pluginId = `${plugin.name}@${plugin.marketplace}`;
670
+ for (const s of scopes) {
671
+ await this.configurationService.removeEnabledPlugin(
672
+ this.workdir,
673
+ s,
674
+ pluginId,
675
+ );
676
+ }
677
+ }
678
+ }
679
+
552
680
  /**
553
681
  * Updates a specific marketplace or all marketplaces
554
682
  */
@@ -281,12 +281,11 @@ export class FileWatcherService extends EventEmitter {
281
281
 
282
282
  // Notify all watchers that match the path or are parents of the path
283
283
  for (const [watchedPath, entry] of this.watchers.entries()) {
284
+ const normalizedFilePath = filePath.replace(/\\/g, "/");
285
+ const normalizedWatchedPath = watchedPath.replace(/\\/g, "/");
284
286
  if (
285
- filePath === watchedPath ||
286
- filePath.startsWith(watchedPath + "/") ||
287
- // Handle cases where the watched path might be a file and we get an event for it
288
- // (already covered by filePath === watchedPath)
289
- false
287
+ normalizedFilePath === normalizedWatchedPath ||
288
+ normalizedFilePath.startsWith(normalizedWatchedPath + "/")
290
289
  ) {
291
290
  entry.lastEvent = event.timestamp;
292
291
 
@@ -53,6 +53,7 @@ export interface KnownMarketplace {
53
53
  }
54
54
 
55
55
  export interface KnownMarketplacesRegistry {
56
+ builtinSeeded?: boolean;
56
57
  marketplaces: KnownMarketplace[];
57
58
  }
58
59
 
@@ -26,7 +26,9 @@ export function generateCommandId(filePath: string, rootDir: string): string {
26
26
  throw new Error("Command filename cannot be empty");
27
27
  }
28
28
 
29
- const segments = relativePath.split("/").filter((segment) => segment !== "");
29
+ const segments = relativePath
30
+ .split(/[\\/]/)
31
+ .filter((segment) => segment !== "");
30
32
 
31
33
  // Remove .md extension from the last segment
32
34
  const lastSegment = segments[segments.length - 1];
@@ -35,7 +35,7 @@ export function parseSkillFile(
35
35
  result.content = content;
36
36
 
37
37
  // Parse YAML frontmatter
38
- const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
38
+ const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
39
39
  if (!frontmatterMatch) {
40
40
  result.validationErrors.push("Missing YAML frontmatter");
41
41
  return result;
@@ -53,9 +53,11 @@ export function parseSkillFile(
53
53
 
54
54
  // Determine skill type and path
55
55
  const skillPath = basePath || dirname(filePath);
56
- const skillType = skillPath.includes("/.wave/skills")
57
- ? "project"
58
- : "personal";
56
+ const skillType =
57
+ skillPath.includes("/.wave/skills") ||
58
+ skillPath.includes("\\.wave\\skills")
59
+ ? "project"
60
+ : "personal";
59
61
 
60
62
  // Extract allowed tools
61
63
  let allowedTools: string[] | undefined;
@@ -30,7 +30,8 @@ function parseFrontmatter(content: string): {
30
30
  frontmatter: SubagentFrontmatter;
31
31
  body: string;
32
32
  } {
33
- const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
33
+ const frontmatterRegex =
34
+ /^---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*\r?\n([\s\S]*)$/;
34
35
  const match = content.match(frontmatterRegex);
35
36
 
36
37
  if (!match) {