wave-agent-sdk 0.17.4 → 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.
@@ -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
  */
@@ -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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-agent-sdk",
3
- "version": "0.17.4",
3
+ "version": "0.17.5",
4
4
  "description": "SDK for building AI-powered development tools and agents",
5
5
  "keywords": [
6
6
  "ai",
@@ -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
  */
@@ -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