@kb-labs/marketplace-core 2.31.0 → 2.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,54 +1,142 @@
1
1
  import { EntityKind, MarketplaceEntry } from '@kb-labs/core-discovery';
2
- import { MarketplaceServiceAPI, PackageSource, EntityKindStrategy, InstallResult, InstallResultEntry, MarketplaceEntryWithId, SyncResult, DoctorReport, ManifestCache, ManifestCacheEntry } from '@kb-labs/marketplace-contracts';
2
+ import { MarketplaceServiceAPI, PackageSource, EntityKindStrategy, ScopeContext, InstallResult, InstallResultEntry, QueryScopeContext, ScopedMarketplaceEntry, SyncResult, DoctorReport, MarketplaceScope, MarketplaceEntryWithId, MarketplaceDiagnostic, ManifestCache, ManifestCacheEntry } from '@kb-labs/marketplace-contracts';
3
3
 
4
4
  /**
5
5
  * @module @kb-labs/marketplace-core/marketplace-service
6
6
  * Unified marketplace service — install/uninstall/enable/disable for all entity types.
7
+ *
8
+ * Every mutating method is explicitly scope-bound (`platform` or `project`).
9
+ * There is no implicit default: callers pass a `ScopeContext` per call so
10
+ * the service can target the right `.kb/marketplace.lock`.
11
+ *
7
12
  * Works through PackageSource abstraction — never calls pnpm directly.
8
13
  */
9
14
 
10
15
  interface MarketplaceServiceOptions {
11
- /** Workspace root directory */
12
- root: string;
16
+ /** Platform workspace root always required. Used for `scope: 'platform'`. */
17
+ platformRoot: string;
18
+ /**
19
+ * Default project root. Optional — a daemon serving multiple projects can
20
+ * leave this unset and pass `ctx.projectRoot` per call. When both are
21
+ * provided, per-call `ctx.projectRoot` wins.
22
+ */
23
+ projectRoot?: string;
13
24
  /** Package source (npm, registry, etc.) */
14
25
  source: PackageSource;
15
26
  /** Additional strategies beyond built-in plugin/adapter */
16
27
  strategies?: EntityKindStrategy[];
17
28
  }
18
29
  declare class MarketplaceService implements MarketplaceServiceAPI {
19
- private readonly root;
30
+ private readonly roots;
20
31
  private readonly source;
21
32
  private readonly strategies;
22
33
  constructor(opts: MarketplaceServiceOptions);
23
34
  registerStrategy(strategy: EntityKindStrategy): void;
24
- install(specs: string[], opts?: {
35
+ install(ctx: ScopeContext, specs: string[], opts?: {
25
36
  dev?: boolean;
26
37
  }): Promise<InstallResult>;
27
- uninstall(packageIds: string[]): Promise<void>;
28
- link(packagePath: string): Promise<InstallResultEntry>;
29
- unlink(packageId: string): Promise<void>;
30
- update(packageIds?: string[]): Promise<InstallResult>;
31
- enable(packageId: string): Promise<void>;
32
- disable(packageId: string): Promise<void>;
33
- list(filter?: {
38
+ uninstall(ctx: ScopeContext, packageIds: string[]): Promise<void>;
39
+ link(ctx: ScopeContext, packagePath: string): Promise<InstallResultEntry>;
40
+ unlink(ctx: ScopeContext, packageId: string): Promise<void>;
41
+ update(ctx: ScopeContext, packageIds?: string[]): Promise<InstallResult>;
42
+ enable(ctx: ScopeContext, packageId: string): Promise<void>;
43
+ disable(ctx: ScopeContext, packageId: string): Promise<void>;
44
+ list(ctx: QueryScopeContext, filter?: {
34
45
  kind?: EntityKind;
35
- }): Promise<MarketplaceEntryWithId[]>;
36
- getEntry(packageId: string): Promise<MarketplaceEntry | null>;
46
+ }): Promise<ScopedMarketplaceEntry[]>;
47
+ getEntry(ctx: ScopeContext, packageId: string): Promise<MarketplaceEntry | null>;
37
48
  /**
38
49
  * Scan workspace for plugins and adapters using glob patterns.
39
50
  * Existing entries are preserved (not overwritten).
40
51
  * Patterns come from kb.config.json marketplace.sync.include.
52
+ *
53
+ * Sync is scope-bound: globs resolve against the scope root and results go
54
+ * into that scope's lock. Adapter discovery in `project` scope is refused
55
+ * with a clear error to preserve the adapters-are-platform-only invariant.
41
56
  */
42
- sync(opts: {
57
+ sync(ctx: ScopeContext, opts: {
43
58
  include: string[];
44
59
  exclude?: string[];
45
60
  autoEnable?: boolean;
46
61
  }): Promise<SyncResult>;
47
62
  private _syncPackage;
48
- doctor(): Promise<DoctorReport>;
63
+ doctor(ctx: ScopeContext): Promise<DoctorReport>;
49
64
  private detectKind;
65
+ /**
66
+ * Hard guard: adapters may only be installed/linked in platform scope.
67
+ * Lives in one place so adapter-scope policy is not duplicated across
68
+ * `link`, `install`, and `sync`.
69
+ */
70
+ private assertScopeAllowsKind;
50
71
  private cacheManifest;
51
72
  }
73
+ declare class AdapterScopeError extends Error {
74
+ readonly code = "MARKETPLACE_ADAPTER_PROJECT_SCOPE";
75
+ constructor(message: string);
76
+ }
77
+ /**
78
+ * Merge per-scope entries with platform-wins precedence.
79
+ *
80
+ * For a given package id present in both platform and project, the platform
81
+ * entry is kept and a diagnostic is emitted so the caller can surface the
82
+ * conflict.
83
+ */
84
+ declare function mergeScopedEntries(perScope: Array<{
85
+ scope: MarketplaceScope;
86
+ entries: MarketplaceEntryWithId[];
87
+ }>): {
88
+ entries: ScopedMarketplaceEntry[];
89
+ diagnostics: MarketplaceDiagnostic[];
90
+ };
91
+
92
+ /**
93
+ * @module @kb-labs/marketplace-core/scope
94
+ * Scope resolution helpers for the platform/project marketplace split.
95
+ *
96
+ * Every mutating service method is explicitly scope-bound — there is no
97
+ * implicit default. The helpers below compute the absolute root directory
98
+ * for a given ScopeContext and enforce the invariants that the rest of the
99
+ * service relies on (distinct platform/project roots, project has a `.kb/`).
100
+ */
101
+
102
+ /**
103
+ * Roots known to the MarketplaceService at construction time.
104
+ * `platformRoot` is always known. `projectRoot` is optional at construction
105
+ * (daemon may serve multiple projects); per-call `ctx.projectRoot` can
106
+ * override it.
107
+ */
108
+ interface ServiceRoots {
109
+ platformRoot: string;
110
+ projectRoot?: string;
111
+ }
112
+ /**
113
+ * Resolve the absolute scope root for a single mutating call.
114
+ *
115
+ * - `scope: 'platform'` — returns `roots.platformRoot`. `projectRoot` in
116
+ * the context is ignored.
117
+ * - `scope: 'project'` — prefers `ctx.projectRoot`, falls back to
118
+ * `roots.projectRoot` from construction. Throws if neither is set,
119
+ * if the path isn't absolute, doesn't exist, lacks a `.kb/kb.config.*`,
120
+ * or equals `roots.platformRoot`.
121
+ */
122
+ declare function resolveScopeRoot(roots: ServiceRoots, ctx: ScopeContext): string;
123
+ /**
124
+ * Resolve the set of roots to read from for a query context (`list`,
125
+ * `getEntry`). `'all'` returns both; the caller is responsible for merging
126
+ * with a platform-wins precedence.
127
+ */
128
+ declare function resolveQueryRoots(roots: ServiceRoots, ctx: QueryScopeContext): Array<{
129
+ scope: MarketplaceScope;
130
+ root: string;
131
+ }>;
132
+ /**
133
+ * Thrown when a scope context cannot be resolved to a concrete root.
134
+ * Uses a stable `code` so API/CLI can surface actionable errors.
135
+ */
136
+ declare class ScopeResolutionError extends Error {
137
+ readonly code: string;
138
+ constructor(code: string, message: string);
139
+ }
52
140
 
53
141
  /**
54
142
  * @module @kb-labs/marketplace-core/manifest-cache
@@ -97,8 +185,8 @@ declare class AdapterStrategy implements EntityKindStrategy {
97
185
  kind: EntityKind;
98
186
  detectKind(packageRoot: string): Promise<EntityKind | null>;
99
187
  extractProvides(_packageRoot: string): Promise<EntityKind[]>;
100
- afterInstall(packageId: string, packageRoot: string, service: MarketplaceServiceAPI): Promise<void>;
101
- beforeUninstall(packageId: string, service: MarketplaceServiceAPI): Promise<void>;
188
+ afterInstall(packageId: string, packageRoot: string, service: MarketplaceServiceAPI, ctx: ScopeContext): Promise<void>;
189
+ beforeUninstall(packageId: string, service: MarketplaceServiceAPI, ctx: ScopeContext): Promise<void>;
102
190
  }
103
191
 
104
- export { AdapterStrategy, MarketplaceService, type MarketplaceServiceOptions, PluginStrategy, createEmptyManifestCache, readManifestCache, removeCacheEntry, setCacheEntry, writeManifestCache };
192
+ export { AdapterScopeError, AdapterStrategy, MarketplaceService, type MarketplaceServiceOptions, PluginStrategy, ScopeResolutionError, type ServiceRoots, createEmptyManifestCache, mergeScopedEntries, readManifestCache, removeCacheEntry, resolveQueryRoots, resolveScopeRoot, setCacheEntry, writeManifestCache };
package/dist/index.js CHANGED
@@ -1,16 +1,17 @@
1
1
  import * as fs from 'fs/promises';
2
- import * as path3 from 'path';
2
+ import * as path4 from 'path';
3
3
  import * as crypto from 'crypto';
4
4
  import { randomUUID } from 'crypto';
5
5
  import { pathToFileURL } from 'url';
6
6
  import { glob } from 'glob';
7
7
  import { DiagnosticCollector, loadManifest, extractEntityKinds, createMarketplaceEntry, addToMarketplaceLock, removeFromMarketplaceLock, readMarketplaceLock, enablePlugin, disablePlugin, createEmptyLock, writeMarketplaceLock } from '@kb-labs/core-discovery';
8
+ import { accessSync, constants } from 'fs';
8
9
 
9
10
  // src/marketplace-service.ts
10
11
  var CACHE_FILE = ".kb/marketplace.manifests.json";
11
12
  var SCHEMA_VERSION = "kb.marketplace.manifests/1";
12
13
  async function readManifestCache(root) {
13
- const cachePath = path3.join(root, CACHE_FILE);
14
+ const cachePath = path4.join(root, CACHE_FILE);
14
15
  try {
15
16
  const raw = await fs.readFile(cachePath, "utf-8");
16
17
  const parsed = JSON.parse(raw);
@@ -23,8 +24,8 @@ async function readManifestCache(root) {
23
24
  }
24
25
  }
25
26
  async function writeManifestCache(root, cache) {
26
- const cachePath = path3.join(root, CACHE_FILE);
27
- const dir = path3.dirname(cachePath);
27
+ const cachePath = path4.join(root, CACHE_FILE);
28
+ const dir = path4.dirname(cachePath);
28
29
  await fs.mkdir(dir, { recursive: true });
29
30
  const tmpPath = `${cachePath}.tmp.${randomUUID()}`;
30
31
  await fs.writeFile(tmpPath, JSON.stringify(cache, null, 2) + "\n", "utf-8");
@@ -76,16 +77,16 @@ var AdapterStrategy = class {
76
77
  async extractProvides(_packageRoot) {
77
78
  return ["adapter"];
78
79
  }
79
- async afterInstall(packageId, packageRoot, service) {
80
+ async afterInstall(packageId, packageRoot, service, ctx) {
80
81
  const manifest = await loadAdapterManifest(packageRoot);
81
82
  if (!manifest?.requires?.adapters) {
82
83
  return;
83
84
  }
84
- const installed = await service.list({ kind: "adapter" });
85
+ const installed = await service.list(ctx, { kind: "adapter" });
85
86
  const installedIds = new Set(installed.map((e) => e.id));
86
87
  for (const dep of manifest.requires.adapters) {
87
88
  const depId = typeof dep === "string" ? dep : dep.id;
88
- const found = installedIds.has(depId) || installed.some((e) => e.id?.includes(`adapters-${depId}`));
89
+ const found = installedIds.has(depId) || installed.some((e) => e.id.includes(`adapters-${depId}`));
89
90
  if (!found) {
90
91
  console.warn(
91
92
  `[marketplace] Adapter "${packageId}" requires adapter "${depId}" which is not installed. Run: kb marketplace link <adapter-package-that-provides-${depId}>`
@@ -93,8 +94,8 @@ var AdapterStrategy = class {
93
94
  }
94
95
  }
95
96
  }
96
- async beforeUninstall(packageId, service) {
97
- const installed = await service.list({ kind: "adapter" });
97
+ async beforeUninstall(packageId, service, ctx) {
98
+ const installed = await service.list(ctx, { kind: "adapter" });
98
99
  if (installed.length > 1) {
99
100
  console.warn(
100
101
  `[marketplace] Removing adapter "${packageId}" \u2014 verify no other adapters depend on it`
@@ -104,7 +105,7 @@ var AdapterStrategy = class {
104
105
  };
105
106
  async function loadAdapterManifest(packageRoot) {
106
107
  try {
107
- const distPath = path3.join(packageRoot, "dist", "index.js");
108
+ const distPath = path4.join(packageRoot, "dist", "index.js");
108
109
  await fs.access(distPath);
109
110
  const mod = await import(pathToFileURL(distPath).href);
110
111
  if (mod.manifest && typeof mod.manifest === "object" && mod.manifest.implements) {
@@ -115,14 +116,95 @@ async function loadAdapterManifest(packageRoot) {
115
116
  return null;
116
117
  }
117
118
  }
119
+ var CONFIG_FILE_CANDIDATES = ["kb.config.jsonc", "kb.config.json"];
120
+ function resolveScopeRoot(roots, ctx) {
121
+ if (ctx.scope === "platform") {
122
+ return roots.platformRoot;
123
+ }
124
+ const candidate = ctx.projectRoot ?? roots.projectRoot;
125
+ if (!candidate) {
126
+ throw new ScopeResolutionError(
127
+ "SCOPE_PROJECT_ROOT_MISSING",
128
+ 'scope="project" requires a projectRoot (pass ctx.projectRoot or configure the service with projectRoot).'
129
+ );
130
+ }
131
+ if (!path4.isAbsolute(candidate)) {
132
+ throw new ScopeResolutionError(
133
+ "SCOPE_PROJECT_ROOT_NOT_ABSOLUTE",
134
+ `projectRoot must be absolute, got "${candidate}".`
135
+ );
136
+ }
137
+ try {
138
+ accessSync(candidate, constants.F_OK);
139
+ } catch {
140
+ throw new ScopeResolutionError(
141
+ "SCOPE_PROJECT_ROOT_NOT_FOUND",
142
+ `projectRoot does not exist: "${candidate}".`
143
+ );
144
+ }
145
+ const hasConfig = CONFIG_FILE_CANDIDATES.some((name) => {
146
+ try {
147
+ accessSync(path4.join(candidate, ".kb", name), constants.F_OK);
148
+ return true;
149
+ } catch {
150
+ return false;
151
+ }
152
+ });
153
+ if (!hasConfig) {
154
+ throw new ScopeResolutionError(
155
+ "SCOPE_PROJECT_ROOT_NO_KB_DIR",
156
+ `projectRoot "${candidate}" does not contain .kb/kb.config.{json,jsonc} \u2014 refusing to treat it as a project.`
157
+ );
158
+ }
159
+ if (path4.resolve(candidate) === path4.resolve(roots.platformRoot)) {
160
+ throw new ScopeResolutionError(
161
+ "SCOPE_PROJECT_EQUALS_PLATFORM",
162
+ 'projectRoot must not equal platformRoot; use scope="platform" for platform-level operations.'
163
+ );
164
+ }
165
+ return path4.resolve(candidate);
166
+ }
167
+ function resolveQueryRoots(roots, ctx) {
168
+ if (ctx.scope === "platform") {
169
+ return [{ scope: "platform", root: roots.platformRoot }];
170
+ }
171
+ if (ctx.scope === "project") {
172
+ return [
173
+ {
174
+ scope: "project",
175
+ root: resolveScopeRoot(roots, { scope: "project", projectRoot: ctx.projectRoot })
176
+ }
177
+ ];
178
+ }
179
+ const out = [
180
+ { scope: "platform", root: roots.platformRoot }
181
+ ];
182
+ const projectCandidate = ctx.projectRoot ?? roots.projectRoot;
183
+ if (projectCandidate) {
184
+ try {
185
+ const projectRoot = resolveScopeRoot(roots, { scope: "project", projectRoot: projectCandidate });
186
+ out.push({ scope: "project", root: projectRoot });
187
+ } catch {
188
+ }
189
+ }
190
+ return out;
191
+ }
192
+ var ScopeResolutionError = class extends Error {
193
+ code;
194
+ constructor(code, message) {
195
+ super(message);
196
+ this.code = code;
197
+ this.name = "ScopeResolutionError";
198
+ }
199
+ };
118
200
 
119
201
  // src/marketplace-service.ts
120
202
  var MarketplaceService = class {
121
- root;
203
+ roots;
122
204
  source;
123
205
  strategies = /* @__PURE__ */ new Map();
124
206
  constructor(opts) {
125
- this.root = opts.root;
207
+ this.roots = { platformRoot: opts.platformRoot, projectRoot: opts.projectRoot };
126
208
  this.source = opts.source;
127
209
  this.registerStrategy(new PluginStrategy());
128
210
  this.registerStrategy(new AdapterStrategy());
@@ -138,28 +220,31 @@ var MarketplaceService = class {
138
220
  // -------------------------------------------------------------------------
139
221
  // Install
140
222
  // -------------------------------------------------------------------------
141
- async install(specs, opts) {
223
+ async install(ctx, specs, opts) {
224
+ const scopeRoot = resolveScopeRoot(this.roots, ctx);
142
225
  const installed = [];
143
226
  const warnings = [];
227
+ const diagnostics = [];
144
228
  for (const spec of specs) {
145
229
  const resolved = await this.source.resolve(spec);
146
- const result = await this.source.install(resolved, this.root, opts);
230
+ const result = await this.source.install(resolved, scopeRoot, opts);
147
231
  const primaryKind = await this.detectKind(result.packageRoot);
232
+ this.assertScopeAllowsKind(ctx.scope, primaryKind);
148
233
  const strategy = this.strategies.get(primaryKind);
149
234
  const provides = strategy ? await strategy.extractProvides(result.packageRoot) : [primaryKind];
150
235
  const entry = createMarketplaceEntry({
151
236
  version: result.version,
152
237
  integrity: result.integrity,
153
- resolvedPath: relativeToRoot(this.root, result.packageRoot),
238
+ resolvedPath: relativeToRoot(scopeRoot, result.packageRoot),
154
239
  source: resolved.source,
155
240
  primaryKind,
156
241
  provides
157
242
  });
158
- await addToMarketplaceLock(this.root, result.id, entry);
159
- await this.cacheManifest(result.id, result.packageRoot, primaryKind, result.integrity);
243
+ await addToMarketplaceLock(scopeRoot, result.id, entry);
244
+ await this.cacheManifest(scopeRoot, result.id, result.packageRoot, primaryKind, result.integrity);
160
245
  if (strategy?.afterInstall) {
161
246
  try {
162
- await strategy.afterInstall(result.id, result.packageRoot, this);
247
+ await strategy.afterInstall(result.id, result.packageRoot, this, ctx);
163
248
  } catch (err) {
164
249
  warnings.push(`afterInstall for ${result.id}: ${err.message}`);
165
250
  }
@@ -169,113 +254,126 @@ var MarketplaceService = class {
169
254
  version: result.version,
170
255
  primaryKind,
171
256
  provides,
172
- packageRoot: result.packageRoot
257
+ packageRoot: result.packageRoot,
258
+ scope: ctx.scope
173
259
  });
174
260
  }
175
- return { installed, warnings };
261
+ return { installed, warnings, scope: ctx.scope, diagnostics: diagnostics.length ? diagnostics : void 0 };
176
262
  }
177
263
  // -------------------------------------------------------------------------
178
264
  // Uninstall
179
265
  // -------------------------------------------------------------------------
180
- async uninstall(packageIds) {
266
+ async uninstall(ctx, packageIds) {
267
+ const scopeRoot = resolveScopeRoot(this.roots, ctx);
181
268
  for (const id of packageIds) {
182
- const entry = await this.getEntry(id);
269
+ const entry = await this.getEntry(ctx, id);
183
270
  if (entry) {
184
271
  const strategy = this.strategies.get(entry.primaryKind);
185
272
  if (strategy?.beforeUninstall) {
186
- await strategy.beforeUninstall(id, this);
273
+ await strategy.beforeUninstall(id, this, ctx);
187
274
  }
188
275
  }
189
- await removeFromMarketplaceLock(this.root, id);
190
- await removeCacheEntry(this.root, id);
191
- await this.source.remove(id, this.root);
276
+ await removeFromMarketplaceLock(scopeRoot, id);
277
+ await removeCacheEntry(scopeRoot, id);
278
+ await this.source.remove(id, scopeRoot);
192
279
  }
193
280
  }
194
281
  // -------------------------------------------------------------------------
195
282
  // Link / Unlink
196
283
  // -------------------------------------------------------------------------
197
- async link(packagePath) {
198
- const absPath = path3.resolve(this.root, packagePath);
199
- if (!absPath.startsWith(this.root)) {
200
- throw new Error(`Path "${packagePath}" is outside workspace root \u2014 refusing to link`);
284
+ async link(ctx, packagePath) {
285
+ const scopeRoot = resolveScopeRoot(this.roots, ctx);
286
+ const absPath = path4.resolve(scopeRoot, packagePath);
287
+ if (!isPathInside(scopeRoot, absPath)) {
288
+ throw new Error(
289
+ `Path "${packagePath}" is outside ${ctx.scope} root "${scopeRoot}" \u2014 refusing to link`
290
+ );
201
291
  }
202
292
  const pkgJson = JSON.parse(
203
- await fs.readFile(
204
- path3.join(absPath, "package.json"),
205
- "utf-8"
206
- )
293
+ await fs.readFile(path4.join(absPath, "package.json"), "utf-8")
207
294
  );
208
295
  const id = pkgJson.name;
209
296
  const version = pkgJson.version ?? "0.0.0";
210
297
  const primaryKind = await this.detectKind(absPath);
298
+ this.assertScopeAllowsKind(ctx.scope, primaryKind);
211
299
  const strategy = this.strategies.get(primaryKind);
212
300
  const provides = strategy ? await strategy.extractProvides(absPath) : [primaryKind];
213
301
  const integrity = await computeIntegrity(absPath);
214
302
  const entry = createMarketplaceEntry({
215
303
  version,
216
304
  integrity,
217
- resolvedPath: relativeToRoot(this.root, absPath),
305
+ resolvedPath: relativeToRoot(scopeRoot, absPath),
218
306
  source: "local",
219
307
  primaryKind,
220
308
  provides
221
309
  });
222
- await addToMarketplaceLock(this.root, id, entry);
223
- await this.cacheManifest(id, absPath, primaryKind, integrity);
310
+ await addToMarketplaceLock(scopeRoot, id, entry);
311
+ await this.cacheManifest(scopeRoot, id, absPath, primaryKind, integrity);
224
312
  if (strategy?.afterInstall) {
225
- await strategy.afterInstall(id, absPath, this);
313
+ await strategy.afterInstall(id, absPath, this, ctx);
226
314
  }
227
- return { id, version, primaryKind, provides, packageRoot: absPath };
315
+ return { id, version, primaryKind, provides, packageRoot: absPath, scope: ctx.scope };
228
316
  }
229
- async unlink(packageId) {
230
- await removeFromMarketplaceLock(this.root, packageId);
231
- await removeCacheEntry(this.root, packageId);
317
+ async unlink(ctx, packageId) {
318
+ const scopeRoot = resolveScopeRoot(this.roots, ctx);
319
+ await removeFromMarketplaceLock(scopeRoot, packageId);
320
+ await removeCacheEntry(scopeRoot, packageId);
232
321
  }
233
322
  // -------------------------------------------------------------------------
234
323
  // Update
235
324
  // -------------------------------------------------------------------------
236
- async update(packageIds) {
325
+ async update(ctx, packageIds) {
326
+ const scopeRoot = resolveScopeRoot(this.roots, ctx);
237
327
  const diag = new DiagnosticCollector();
238
- const lock = await readMarketplaceLock(this.root, diag);
328
+ const lock = await readMarketplaceLock(scopeRoot, diag);
239
329
  if (!lock) {
240
- return { installed: [], warnings: ["No marketplace.lock found"] };
330
+ return { installed: [], warnings: ["No marketplace.lock found"], scope: ctx.scope };
241
331
  }
242
332
  const ids = packageIds ?? Object.keys(lock.installed);
243
333
  const specs = ids.filter((id) => id in lock.installed);
244
- return this.install(specs);
334
+ return this.install(ctx, specs);
245
335
  }
246
336
  // -------------------------------------------------------------------------
247
337
  // Enable / Disable
248
338
  // -------------------------------------------------------------------------
249
- async enable(packageId) {
250
- const ok = await enablePlugin(this.root, packageId);
339
+ async enable(ctx, packageId) {
340
+ const scopeRoot = resolveScopeRoot(this.roots, ctx);
341
+ const ok = await enablePlugin(scopeRoot, packageId);
251
342
  if (!ok) {
252
- throw new Error(`Package "${packageId}" not found in marketplace.lock`);
343
+ throw new Error(`Package "${packageId}" not found in ${ctx.scope} marketplace.lock`);
253
344
  }
254
345
  }
255
- async disable(packageId) {
256
- const ok = await disablePlugin(this.root, packageId);
346
+ async disable(ctx, packageId) {
347
+ const scopeRoot = resolveScopeRoot(this.roots, ctx);
348
+ const ok = await disablePlugin(scopeRoot, packageId);
257
349
  if (!ok) {
258
- throw new Error(`Package "${packageId}" not found in marketplace.lock`);
350
+ throw new Error(`Package "${packageId}" not found in ${ctx.scope} marketplace.lock`);
259
351
  }
260
352
  }
261
353
  // -------------------------------------------------------------------------
262
354
  // List / GetEntry (MarketplaceServiceAPI)
263
355
  // -------------------------------------------------------------------------
264
- async list(filter) {
265
- const diag = new DiagnosticCollector();
266
- const lock = await readMarketplaceLock(this.root, diag);
267
- if (!lock) {
268
- return [];
269
- }
270
- let entries = Object.entries(lock.installed).map(([id, entry]) => ({ ...entry, id }));
271
- if (filter?.kind) {
272
- entries = entries.filter((e) => e.primaryKind === filter.kind);
356
+ async list(ctx, filter) {
357
+ const targets = resolveQueryRoots(this.roots, ctx);
358
+ const perScope = [];
359
+ for (const { scope, root } of targets) {
360
+ const diag = new DiagnosticCollector();
361
+ const lock = await readMarketplaceLock(root, diag);
362
+ if (!lock) {
363
+ perScope.push({ scope, entries: [] });
364
+ continue;
365
+ }
366
+ const entries = Object.entries(lock.installed).map(([id, entry]) => ({ ...entry, id }));
367
+ perScope.push({ scope, entries });
273
368
  }
274
- return entries;
369
+ const merged = mergeScopedEntries(perScope);
370
+ const filtered = filter?.kind ? merged.entries.filter((e) => e.primaryKind === filter.kind) : merged.entries;
371
+ return filtered;
275
372
  }
276
- async getEntry(packageId) {
373
+ async getEntry(ctx, packageId) {
374
+ const scopeRoot = resolveScopeRoot(this.roots, ctx);
277
375
  const diag = new DiagnosticCollector();
278
- const lock = await readMarketplaceLock(this.root, diag);
376
+ const lock = await readMarketplaceLock(scopeRoot, diag);
279
377
  return lock?.installed[packageId] ?? null;
280
378
  }
281
379
  // -------------------------------------------------------------------------
@@ -285,33 +383,38 @@ var MarketplaceService = class {
285
383
  * Scan workspace for plugins and adapters using glob patterns.
286
384
  * Existing entries are preserved (not overwritten).
287
385
  * Patterns come from kb.config.json marketplace.sync.include.
386
+ *
387
+ * Sync is scope-bound: globs resolve against the scope root and results go
388
+ * into that scope's lock. Adapter discovery in `project` scope is refused
389
+ * with a clear error to preserve the adapters-are-platform-only invariant.
288
390
  */
289
- async sync(opts) {
391
+ async sync(ctx, opts) {
392
+ const scopeRoot = resolveScopeRoot(this.roots, ctx);
290
393
  const autoEnable = opts.autoEnable ?? false;
291
394
  const diag = new DiagnosticCollector();
292
- const lock = await readMarketplaceLock(this.root, diag) ?? createEmptyLock();
395
+ const lock = await readMarketplaceLock(scopeRoot, diag) ?? createEmptyLock();
293
396
  const existingIds = new Set(Object.keys(lock.installed));
294
397
  const added = [];
295
398
  const skipped = [];
296
- const includePatterns = opts.include.map((p) => path3.join(p, "package.json"));
399
+ const includePatterns = opts.include.map((p) => path4.join(p, "package.json"));
297
400
  const excludePatterns = opts.exclude ?? [];
298
401
  const packageJsonPaths = await glob(includePatterns, {
299
- cwd: this.root,
402
+ cwd: scopeRoot,
300
403
  ignore: excludePatterns,
301
404
  absolute: false
302
405
  });
303
406
  for (const relPkgJson of packageJsonPaths) {
304
- const pkgDir = path3.resolve(this.root, path3.dirname(relPkgJson));
305
- await this._syncPackage(pkgDir, relPkgJson, existingIds, autoEnable, lock, added, skipped);
407
+ const pkgDir = path4.resolve(scopeRoot, path4.dirname(relPkgJson));
408
+ await this._syncPackage(ctx.scope, scopeRoot, pkgDir, relPkgJson, existingIds, autoEnable, lock, added, skipped);
306
409
  }
307
- await writeMarketplaceLock(this.root, lock);
410
+ await writeMarketplaceLock(scopeRoot, lock);
308
411
  return { added, skipped, total: Object.keys(lock.installed).length };
309
412
  }
310
- async _syncPackage(pkgDir, _relPkgJson, existingIds, autoEnable, lock, added, skipped) {
413
+ async _syncPackage(scope, scopeRoot, pkgDir, _relPkgJson, existingIds, autoEnable, lock, added, skipped) {
311
414
  let pkgName;
312
415
  let pkgVersion;
313
416
  try {
314
- const pkgJson = JSON.parse(await fs.readFile(path3.join(pkgDir, "package.json"), "utf-8"));
417
+ const pkgJson = JSON.parse(await fs.readFile(path4.join(pkgDir, "package.json"), "utf-8"));
315
418
  pkgName = pkgJson.name;
316
419
  pkgVersion = pkgJson.version ?? "0.0.0";
317
420
  if (!pkgName) {
@@ -336,6 +439,10 @@ var MarketplaceService = class {
336
439
  return;
337
440
  }
338
441
  const primaryKind = await this.detectKind(pkgDir);
442
+ if (scope === "project" && primaryKind === "adapter") {
443
+ skipped.push({ id: pkgName, reason: "adapter not allowed in project scope" });
444
+ return;
445
+ }
339
446
  const strategy = this.strategies.get(primaryKind);
340
447
  const provides = strategy ? await strategy.extractProvides(pkgDir) : [primaryKind];
341
448
  const integrity = await computeIntegrity(pkgDir);
@@ -347,7 +454,7 @@ var MarketplaceService = class {
347
454
  const entry = createMarketplaceEntry({
348
455
  version: pkgVersion,
349
456
  integrity,
350
- resolvedPath: relativeToRoot(this.root, pkgDir),
457
+ resolvedPath: relativeToRoot(scopeRoot, pkgDir),
351
458
  source: "local",
352
459
  primaryKind,
353
460
  provides
@@ -361,16 +468,17 @@ var MarketplaceService = class {
361
468
  // -------------------------------------------------------------------------
362
469
  // Doctor
363
470
  // -------------------------------------------------------------------------
364
- async doctor() {
471
+ async doctor(ctx) {
472
+ const scopeRoot = resolveScopeRoot(this.roots, ctx);
365
473
  const diag = new DiagnosticCollector();
366
- const lock = await readMarketplaceLock(this.root, diag);
474
+ const lock = await readMarketplaceLock(scopeRoot, diag);
367
475
  const issues = [];
368
476
  if (!lock) {
369
477
  return { ok: true, total: 0, issues: [{ severity: "info", packageId: "", message: "No marketplace.lock found" }] };
370
478
  }
371
479
  const entries = Object.entries(lock.installed);
372
480
  for (const [id, entry] of entries) {
373
- const pkgRoot = path3.resolve(this.root, entry.resolvedPath);
481
+ const pkgRoot = path4.resolve(scopeRoot, entry.resolvedPath);
374
482
  try {
375
483
  await fs.access(pkgRoot);
376
484
  } catch {
@@ -420,13 +528,25 @@ var MarketplaceService = class {
420
528
  }
421
529
  return "plugin";
422
530
  }
423
- async cacheManifest(packageId, packageRoot, primaryKind, integrity) {
531
+ /**
532
+ * Hard guard: adapters may only be installed/linked in platform scope.
533
+ * Lives in one place so adapter-scope policy is not duplicated across
534
+ * `link`, `install`, and `sync`.
535
+ */
536
+ assertScopeAllowsKind(scope, kind) {
537
+ if (scope === "project" && kind === "adapter") {
538
+ throw new AdapterScopeError(
539
+ "Adapters can only be installed in platform scope. Use --scope platform or install globally via the platform marketplace."
540
+ );
541
+ }
542
+ }
543
+ async cacheManifest(scopeRoot, packageId, packageRoot, primaryKind, integrity) {
424
544
  try {
425
545
  if (primaryKind === "plugin") {
426
546
  const diag = new DiagnosticCollector();
427
547
  const manifest = await loadManifest(packageRoot, diag);
428
548
  if (manifest) {
429
- await setCacheEntry(this.root, packageId, {
549
+ await setCacheEntry(scopeRoot, packageId, {
430
550
  manifestType: "plugin",
431
551
  manifest,
432
552
  cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -434,10 +554,10 @@ var MarketplaceService = class {
434
554
  });
435
555
  }
436
556
  } else if (primaryKind === "adapter") {
437
- const distPath = path3.join(packageRoot, "dist", "index.js");
557
+ const distPath = path4.join(packageRoot, "dist", "index.js");
438
558
  const mod = await import(pathToFileURL(distPath).href);
439
559
  if (mod.manifest) {
440
- await setCacheEntry(this.root, packageId, {
560
+ await setCacheEntry(scopeRoot, packageId, {
441
561
  manifestType: "adapter",
442
562
  manifest: mod.manifest,
443
563
  cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -450,19 +570,56 @@ var MarketplaceService = class {
450
570
  }
451
571
  }
452
572
  };
573
+ var AdapterScopeError = class extends Error {
574
+ code = "MARKETPLACE_ADAPTER_PROJECT_SCOPE";
575
+ constructor(message) {
576
+ super(message);
577
+ this.name = "AdapterScopeError";
578
+ }
579
+ };
453
580
  function relativeToRoot(root, absPath) {
454
- const rel = path3.relative(root, absPath);
581
+ const rel = path4.relative(root, absPath);
455
582
  return rel.startsWith(".") ? rel : `./${rel}`;
456
583
  }
584
+ function isPathInside(parent, child) {
585
+ const rel = path4.relative(path4.resolve(parent), path4.resolve(child));
586
+ return !rel.startsWith("..") && !path4.isAbsolute(rel);
587
+ }
457
588
  async function computeIntegrity(packageRoot) {
458
589
  try {
459
- const content = await fs.readFile(path3.join(packageRoot, "package.json"));
590
+ const content = await fs.readFile(path4.join(packageRoot, "package.json"));
460
591
  return `sha256-${crypto.createHash("sha256").update(content).digest("base64")}`;
461
592
  } catch {
462
593
  return "";
463
594
  }
464
595
  }
596
+ function mergeScopedEntries(perScope) {
597
+ const out = /* @__PURE__ */ new Map();
598
+ const diagnostics = [];
599
+ const ordered = [...perScope].sort((a, b) => {
600
+ if (a.scope === b.scope) {
601
+ return 0;
602
+ }
603
+ return a.scope === "platform" ? -1 : 1;
604
+ });
605
+ for (const { scope, entries } of ordered) {
606
+ for (const e of entries) {
607
+ const existing = out.get(e.id);
608
+ if (existing) {
609
+ diagnostics.push({
610
+ code: "MARKETPLACE_SCOPE_COLLISION",
611
+ message: `Package "${e.id}" exists in both platform and ${scope} scopes \u2014 platform wins.`,
612
+ packageId: e.id,
613
+ scope
614
+ });
615
+ continue;
616
+ }
617
+ out.set(e.id, { ...e, scope });
618
+ }
619
+ }
620
+ return { entries: Array.from(out.values()), diagnostics };
621
+ }
465
622
 
466
- export { AdapterStrategy, MarketplaceService, PluginStrategy, createEmptyManifestCache, readManifestCache, removeCacheEntry, setCacheEntry, writeManifestCache };
623
+ export { AdapterScopeError, AdapterStrategy, MarketplaceService, PluginStrategy, ScopeResolutionError, createEmptyManifestCache, mergeScopedEntries, readManifestCache, removeCacheEntry, resolveQueryRoots, resolveScopeRoot, setCacheEntry, writeManifestCache };
467
624
  //# sourceMappingURL=index.js.map
468
625
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/manifest-cache.ts","../src/strategies/plugin-strategy.ts","../src/strategies/adapter-strategy.ts","../src/marketplace-service.ts"],"names":["path","path2","fs2","fs3","DiagnosticCollector","strategy","loadManifest","pathToFileURL"],"mappings":";;;;;;;;;AAUA,IAAM,UAAA,GAAa,gCAAA;AACnB,IAAM,cAAA,GAAiB,4BAAA;AAKvB,eAAsB,kBAAkB,IAAA,EAA6C;AACnF,EAAA,MAAM,SAAA,GAAiBA,KAAA,CAAA,IAAA,CAAK,IAAA,EAAM,UAAU,CAAA;AAC5C,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAS,EAAA,CAAA,QAAA,CAAS,SAAA,EAAW,OAAO,CAAA;AAChD,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,IAAI,MAAA,EAAQ,WAAW,cAAA,EAAgB;AAAC,MAAA,OAAO,IAAA;AAAA,IAAK;AACpD,IAAA,OAAO,MAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAKA,eAAsB,kBAAA,CAAmB,MAAc,KAAA,EAAqC;AAC1F,EAAA,MAAM,SAAA,GAAiBA,KAAA,CAAA,IAAA,CAAK,IAAA,EAAM,UAAU,CAAA;AAC5C,EAAA,MAAM,GAAA,GAAWA,cAAQ,SAAS,CAAA;AAClC,EAAA,MAAS,EAAA,CAAA,KAAA,CAAM,GAAA,EAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AAEvC,EAAA,MAAM,OAAA,GAAU,CAAA,EAAG,SAAS,CAAA,KAAA,EAAQ,YAAY,CAAA,CAAA;AAChD,EAAA,MAAS,EAAA,CAAA,SAAA,CAAU,SAAS,IAAA,CAAK,SAAA,CAAU,OAAO,IAAA,EAAM,CAAC,CAAA,GAAI,IAAA,EAAM,OAAO,CAAA;AAC1E,EAAA,MAAS,EAAA,CAAA,MAAA,CAAO,SAAS,SAAS,CAAA;AACpC;AAKO,SAAS,wBAAA,GAA0C;AACxD,EAAA,OAAO,EAAE,MAAA,EAAQ,cAAA,EAAgB,OAAA,EAAS,EAAC,EAAE;AAC/C;AAKA,eAAsB,aAAA,CACpB,IAAA,EACA,SAAA,EACA,KAAA,EACe;AACf,EAAA,MAAM,QAAA,GAAW,MAAM,iBAAA,CAAkB,IAAI,KAAK,wBAAA,EAAyB;AAC3E,EAAA,QAAA,CAAS,OAAA,CAAQ,SAAS,CAAA,GAAI,KAAA;AAC9B,EAAA,MAAM,kBAAA,CAAmB,MAAM,QAAQ,CAAA;AACzC;AAKA,eAAsB,gBAAA,CACpB,MACA,SAAA,EACe;AACf,EAAA,MAAM,QAAA,GAAW,MAAM,iBAAA,CAAkB,IAAI,CAAA;AAC7C,EAAA,IAAI,CAAC,QAAA,IAAY,EAAE,SAAA,IAAa,SAAS,OAAA,CAAA,EAAU;AAAC,IAAA;AAAA,EAAO;AAC3D,EAAA,OAAO,QAAA,CAAS,QAAQ,SAAS,CAAA;AACjC,EAAA,MAAM,kBAAA,CAAmB,MAAM,QAAQ,CAAA;AACzC;AC/DO,IAAM,iBAAN,MAAmD;AAAA,EACxD,IAAA,GAAmB,QAAA;AAAA,EAEnB,MAAM,WAAW,WAAA,EAAiD;AAChE,IAAA,MAAM,IAAA,GAAO,IAAI,mBAAA,EAAoB;AACrC,IAAA,MAAM,QAAA,GAAW,MAAM,YAAA,CAAa,WAAA,EAAa,IAAI,CAAA;AACrD,IAAA,OAAO,WAAW,QAAA,GAAW,IAAA;AAAA,EAC/B;AAAA,EAEA,MAAM,gBAAgB,WAAA,EAA4C;AAChE,IAAA,MAAM,IAAA,GAAO,IAAI,mBAAA,EAAoB;AACrC,IAAA,MAAM,QAAA,GAAW,MAAM,YAAA,CAAa,WAAA,EAAa,IAAI,CAAA;AACrD,IAAA,IAAI,CAAC,QAAA,EAAU;AAAC,MAAA,OAAO,CAAC,QAAQ,CAAA;AAAA,IAAE;AAClC,IAAA,OAAO,mBAAmB,QAAQ,CAAA;AAAA,EACpC;AAAA,EAEA,MAAM,UAAU,WAAA,EAA6C;AAC3D,IAAA,MAAM,IAAA,GAAO,IAAI,mBAAA,EAAoB;AACrC,IAAA,MAAM,QAAA,GAAW,MAAM,YAAA,CAAa,WAAA,EAAa,IAAI,CAAA;AACrD,IAAA,OAAO,UAAU,EAAA,IAAM,IAAA;AAAA,EACzB;AACF;ACnBO,IAAM,kBAAN,MAAoD;AAAA,EACzD,IAAA,GAAmB,SAAA;AAAA,EAEnB,MAAM,WAAW,WAAA,EAAiD;AAChE,IAAA,MAAM,QAAA,GAAW,MAAM,mBAAA,CAAoB,WAAW,CAAA;AACtD,IAAA,OAAO,WAAW,SAAA,GAAY,IAAA;AAAA,EAChC;AAAA,EAEA,MAAM,gBAAgB,YAAA,EAA6C;AACjE,IAAA,OAAO,CAAC,SAAS,CAAA;AAAA,EACnB;AAAA,EAEA,MAAM,YAAA,CACJ,SAAA,EACA,WAAA,EACA,OAAA,EACe;AACf,IAAA,MAAM,QAAA,GAAW,MAAM,mBAAA,CAAoB,WAAW,CAAA;AACtD,IAAA,IAAI,CAAC,QAAA,EAAU,QAAA,EAAU,QAAA,EAAU;AAAC,MAAA;AAAA,IAAO;AAE3C,IAAA,MAAM,YAAY,MAAM,OAAA,CAAQ,KAAK,EAAE,IAAA,EAAM,WAAW,CAAA;AACxD,IAAA,MAAM,YAAA,GAAe,IAAI,GAAA,CAAI,SAAA,CAAU,IAAI,CAAA,CAAA,KAAM,CAAA,CAAU,EAAY,CAAC,CAAA;AAExE,IAAA,KAAA,MAAW,GAAA,IAAO,QAAA,CAAS,QAAA,CAAS,QAAA,EAAU;AAC5C,MAAA,MAAM,KAAA,GAAQ,OAAO,GAAA,KAAQ,QAAA,GAAW,MAAM,GAAA,CAAI,EAAA;AAElD,MAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,GAAA,CAAI,KAAK,KAClC,SAAA,CAAU,IAAA,CAAK,CAAA,CAAA,KAAM,CAAA,CAAU,EAAA,EAAI,QAAA,CAAS,CAAA,SAAA,EAAY,KAAK,EAAE,CAAC,CAAA;AAElE,MAAA,IAAI,CAAC,KAAA,EAAO;AACV,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN,CAAA,uBAAA,EAA0B,SAAS,CAAA,oBAAA,EAAuB,KAAK,qFACJ,KAAK,CAAA,CAAA;AAAA,SAClE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,eAAA,CACJ,SAAA,EACA,OAAA,EACe;AAGf,IAAA,MAAM,YAAY,MAAM,OAAA,CAAQ,KAAK,EAAE,IAAA,EAAM,WAAW,CAAA;AACxD,IAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG;AACxB,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN,mCAAmC,SAAS,CAAA,8CAAA;AAAA,OAC9C;AAAA,IACF;AAAA,EACF;AACF;AAeA,eAAe,oBAAoB,WAAA,EAA0D;AAC3F,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAgBC,KAAA,CAAA,IAAA,CAAK,WAAA,EAAa,MAAA,EAAQ,UAAU,CAAA;AAC1D,IAAA,MAASC,UAAO,QAAQ,CAAA;AACxB,IAAA,MAAM,GAAA,GAAM,MAAM,OAAO,aAAA,CAAc,QAAQ,CAAA,CAAE,IAAA,CAAA;AACjD,IAAA,IAAI,GAAA,CAAI,YAAY,OAAO,GAAA,CAAI,aAAa,QAAA,IAAY,GAAA,CAAI,SAAS,UAAA,EAAY;AAC/E,MAAA,OAAO,GAAA,CAAI,QAAA;AAAA,IACb;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;ACjCO,IAAM,qBAAN,MAA0D;AAAA,EAC9C,IAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA,uBAAiB,GAAA,EAAoC;AAAA,EAEtE,YAAY,IAAA,EAAiC;AAC3C,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,IAAA;AACjB,IAAA,IAAA,CAAK,SAAS,IAAA,CAAK,MAAA;AAGnB,IAAA,IAAA,CAAK,gBAAA,CAAiB,IAAI,cAAA,EAAgB,CAAA;AAC1C,IAAA,IAAA,CAAK,gBAAA,CAAiB,IAAI,eAAA,EAAiB,CAAA;AAG3C,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,KAAA,MAAW,CAAA,IAAK,KAAK,UAAA,EAAY;AAC/B,QAAA,IAAA,CAAK,iBAAiB,CAAC,CAAA;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,iBAAiB,QAAA,EAAoC;AACnD,IAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,QAAA,CAAS,IAAA,EAAM,QAAQ,CAAA;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAA,CAAQ,KAAA,EAAiB,IAAA,EAAkD;AAC/E,IAAA,MAAM,YAAkC,EAAC;AACzC,IAAA,MAAM,WAAqB,EAAC;AAE5B,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,QAAQ,IAAI,CAAA;AAC/C,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,CAAO,QAAQ,QAAA,EAAU,IAAA,CAAK,MAAM,IAAI,CAAA;AAGlE,MAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,UAAA,CAAW,OAAO,WAAW,CAAA;AAC5D,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,WAAW,CAAA;AAChD,MAAA,MAAM,QAAA,GAAW,WACb,MAAM,QAAA,CAAS,gBAAgB,MAAA,CAAO,WAAW,CAAA,GACjD,CAAC,WAAW,CAAA;AAGhB,MAAA,MAAM,QAAQ,sBAAA,CAAuB;AAAA,QACnC,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,YAAA,EAAc,cAAA,CAAe,IAAA,CAAK,IAAA,EAAM,OAAO,WAAW,CAAA;AAAA,QAC1D,QAAQ,QAAA,CAAS,MAAA;AAAA,QACjB,WAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,MAAM,oBAAA,CAAqB,IAAA,CAAK,IAAA,EAAM,MAAA,CAAO,IAAI,KAAK,CAAA;AAGtD,MAAA,MAAM,IAAA,CAAK,cAAc,MAAA,CAAO,EAAA,EAAI,OAAO,WAAA,EAAa,WAAA,EAAa,OAAO,SAAS,CAAA;AAGrF,MAAA,IAAI,UAAU,YAAA,EAAc;AAC1B,QAAA,IAAI;AACF,UAAA,MAAM,SAAS,YAAA,CAAa,MAAA,CAAO,EAAA,EAAI,MAAA,CAAO,aAAa,IAAI,CAAA;AAAA,QACjE,SAAS,GAAA,EAAK;AACZ,UAAA,QAAA,CAAS,KAAK,CAAA,iBAAA,EAAoB,MAAA,CAAO,EAAE,CAAA,EAAA,EAAM,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AAAA,QAC1E;AAAA,MACF;AAEA,MAAA,SAAA,CAAU,IAAA,CAAK;AAAA,QACb,IAAI,MAAA,CAAO,EAAA;AAAA,QACX,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,WAAA;AAAA,QACA,QAAA;AAAA,QACA,aAAa,MAAA,CAAO;AAAA,OACrB,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,EAAE,WAAW,QAAA,EAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAU,UAAA,EAAqC;AACnD,IAAA,KAAA,MAAW,MAAM,UAAA,EAAY;AAE3B,MAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,QAAA,CAAS,EAAE,CAAA;AACpC,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,MAAM,QAAA,GAAW,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,MAAM,WAAW,CAAA;AACtD,QAAA,IAAI,UAAU,eAAA,EAAiB;AAC7B,UAAA,MAAM,QAAA,CAAS,eAAA,CAAgB,EAAA,EAAI,IAAI,CAAA;AAAA,QACzC;AAAA,MACF;AAGA,MAAA,MAAM,yBAAA,CAA0B,IAAA,CAAK,IAAA,EAAM,EAAE,CAAA;AAG7C,MAAA,MAAM,gBAAA,CAAiB,IAAA,CAAK,IAAA,EAAM,EAAE,CAAA;AAGpC,MAAA,MAAM,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,EAAA,EAAI,KAAK,IAAI,CAAA;AAAA,IACxC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAK,WAAA,EAAkD;AAC3D,IAAA,MAAM,OAAA,GAAe,KAAA,CAAA,OAAA,CAAQ,IAAA,CAAK,IAAA,EAAM,WAAW,CAAA;AAGnD,IAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,CAAW,IAAA,CAAK,IAAI,CAAA,EAAG;AAClC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,MAAA,EAAS,WAAW,CAAA,mDAAA,CAAgD,CAAA;AAAA,IACtF;AAEA,IAAA,MAAM,UAAU,IAAA,CAAK,KAAA;AAAA,MACnB,MAASC,EAAA,CAAA,QAAA;AAAA,QACF,KAAA,CAAA,IAAA,CAAK,SAAS,cAAc,CAAA;AAAA,QAAG;AAAA;AACtC,KACF;AACA,IAAA,MAAM,KAAa,OAAA,CAAQ,IAAA;AAC3B,IAAA,MAAM,OAAA,GAAkB,QAAQ,OAAA,IAAW,OAAA;AAE3C,IAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,UAAA,CAAW,OAAO,CAAA;AACjD,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,WAAW,CAAA;AAChD,IAAA,MAAM,QAAA,GAAW,WACb,MAAM,QAAA,CAAS,gBAAgB,OAAO,CAAA,GACtC,CAAC,WAAW,CAAA;AAEhB,IAAA,MAAM,SAAA,GAAY,MAAM,gBAAA,CAAiB,OAAO,CAAA;AAEhD,IAAA,MAAM,QAAQ,sBAAA,CAAuB;AAAA,MACnC,OAAA;AAAA,MACA,SAAA;AAAA,MACA,YAAA,EAAc,cAAA,CAAe,IAAA,CAAK,IAAA,EAAM,OAAO,CAAA;AAAA,MAC/C,MAAA,EAAQ,OAAA;AAAA,MACR,WAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,MAAM,oBAAA,CAAqB,IAAA,CAAK,IAAA,EAAM,EAAA,EAAI,KAAK,CAAA;AAC/C,IAAA,MAAM,IAAA,CAAK,aAAA,CAAc,EAAA,EAAI,OAAA,EAAS,aAAa,SAAS,CAAA;AAE5D,IAAA,IAAI,UAAU,YAAA,EAAc;AAC1B,MAAA,MAAM,QAAA,CAAS,YAAA,CAAa,EAAA,EAAI,OAAA,EAAS,IAAI,CAAA;AAAA,IAC/C;AAEA,IAAA,OAAO,EAAE,EAAA,EAAI,OAAA,EAAS,WAAA,EAAa,QAAA,EAAU,aAAa,OAAA,EAAQ;AAAA,EACpE;AAAA,EAEA,MAAM,OAAO,SAAA,EAAkC;AAC7C,IAAA,MAAM,yBAAA,CAA0B,IAAA,CAAK,IAAA,EAAM,SAAS,CAAA;AACpD,IAAA,MAAM,gBAAA,CAAiB,IAAA,CAAK,IAAA,EAAM,SAAS,CAAA;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAO,UAAA,EAA+C;AAC1D,IAAA,MAAM,IAAA,GAAO,IAAIC,mBAAAA,EAAoB;AACrC,IAAA,MAAM,IAAA,GAAO,MAAM,mBAAA,CAAoB,IAAA,CAAK,MAAM,IAAI,CAAA;AACtD,IAAA,IAAI,CAAC,IAAA,EAAM;AAAC,MAAA,OAAO,EAAE,SAAA,EAAW,IAAI,QAAA,EAAU,CAAC,2BAA2B,CAAA,EAAE;AAAA,IAAE;AAE9E,IAAA,MAAM,GAAA,GAAM,UAAA,IAAc,MAAA,CAAO,IAAA,CAAK,KAAK,SAAS,CAAA;AACpD,IAAA,MAAM,QAAQ,GAAA,CAAI,MAAA,CAAO,CAAA,EAAA,KAAM,EAAA,IAAM,KAAK,SAAS,CAAA;AAGnD,IAAA,OAAO,IAAA,CAAK,QAAQ,KAAK,CAAA;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAO,SAAA,EAAkC;AAC7C,IAAA,MAAM,EAAA,GAAK,MAAM,YAAA,CAAa,IAAA,CAAK,MAAM,SAAS,CAAA;AAClD,IAAA,IAAI,CAAC,EAAA,EAAI;AACP,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,SAAA,EAAY,SAAS,CAAA,+BAAA,CAAiC,CAAA;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,SAAA,EAAkC;AAC9C,IAAA,MAAM,EAAA,GAAK,MAAM,aAAA,CAAc,IAAA,CAAK,MAAM,SAAS,CAAA;AACnD,IAAA,IAAI,CAAC,EAAA,EAAI;AACP,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,SAAA,EAAY,SAAS,CAAA,+BAAA,CAAiC,CAAA;AAAA,IACxE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAK,MAAA,EAAmE;AAC5E,IAAA,MAAM,IAAA,GAAO,IAAIA,mBAAAA,EAAoB;AACrC,IAAA,MAAM,IAAA,GAAO,MAAM,mBAAA,CAAoB,IAAA,CAAK,MAAM,IAAI,CAAA;AACtD,IAAA,IAAI,CAAC,IAAA,EAAM;AAAC,MAAA,OAAO,EAAC;AAAA,IAAE;AAEtB,IAAA,IAAI,UAAU,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,SAAS,EAAE,GAAA,CAAI,CAAC,CAAC,EAAA,EAAI,KAAK,CAAA,MAAO,EAAE,GAAG,KAAA,EAAO,IAAG,CAAE,CAAA;AACpF,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,OAAA,GAAU,QAAQ,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,WAAA,KAAgB,OAAO,IAAI,CAAA;AAAA,IAC7D;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,SAAA,EAAqD;AAClE,IAAA,MAAM,IAAA,GAAO,IAAIA,mBAAAA,EAAoB;AACrC,IAAA,MAAM,IAAA,GAAO,MAAM,mBAAA,CAAoB,IAAA,CAAK,MAAM,IAAI,CAAA;AACtD,IAAA,OAAO,IAAA,EAAM,SAAA,CAAU,SAAS,CAAA,IAAK,IAAA;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,KAAK,IAAA,EAIa;AACtB,IAAA,MAAM,UAAA,GAAa,KAAK,UAAA,IAAc,KAAA;AACtC,IAAA,MAAM,IAAA,GAAO,IAAIA,mBAAAA,EAAoB;AACrC,IAAA,MAAM,OAAO,MAAM,mBAAA,CAAoB,KAAK,IAAA,EAAM,IAAI,KAAK,eAAA,EAAgB;AAC3E,IAAA,MAAM,cAAc,IAAI,GAAA,CAAI,OAAO,IAAA,CAAK,IAAA,CAAK,SAAS,CAAC,CAAA;AAEvD,IAAA,MAAM,QAA6B,EAAC;AACpC,IAAA,MAAM,UAAiC,EAAC;AAGxC,IAAA,MAAM,eAAA,GAAkB,KAAK,OAAA,CAAQ,GAAA,CAAI,OAAU,KAAA,CAAA,IAAA,CAAK,CAAA,EAAG,cAAc,CAAC,CAAA;AAC1E,IAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,OAAA,IAAW,EAAC;AAEzC,IAAA,MAAM,gBAAA,GAAmB,MAAM,IAAA,CAAK,eAAA,EAAiB;AAAA,MACnD,KAAK,IAAA,CAAK,IAAA;AAAA,MACV,MAAA,EAAQ,eAAA;AAAA,MACR,QAAA,EAAU;AAAA,KACX,CAAA;AAED,IAAA,KAAA,MAAW,cAAc,gBAAA,EAAkB;AACzC,MAAA,MAAM,SAAc,KAAA,CAAA,OAAA,CAAQ,IAAA,CAAK,IAAA,EAAW,KAAA,CAAA,OAAA,CAAQ,UAAU,CAAC,CAAA;AAC/D,MAAA,MAAM,IAAA,CAAK,aAAa,MAAA,EAAQ,UAAA,EAAY,aAAa,UAAA,EAAY,IAAA,EAAM,OAAO,OAAO,CAAA;AAAA,IAC3F;AAEA,IAAA,MAAM,oBAAA,CAAqB,IAAA,CAAK,IAAA,EAAM,IAAI,CAAA;AAE1C,IAAA,OAAO,EAAE,OAAO,OAAA,EAAS,KAAA,EAAO,OAAO,IAAA,CAAK,IAAA,CAAK,SAAS,CAAA,CAAE,MAAA,EAAO;AAAA,EACrE;AAAA,EAEA,MAAc,aACZ,MAAA,EACA,WAAA,EACA,aACA,UAAA,EACA,IAAA,EACA,OACA,OAAA,EACe;AACf,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI,UAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,MAASD,EAAA,CAAA,QAAA,CAAc,WAAK,MAAA,EAAQ,cAAc,CAAA,EAAG,OAAO,CAAC,CAAA;AACxF,MAAA,OAAA,GAAU,OAAA,CAAQ,IAAA;AAClB,MAAA,UAAA,GAAa,QAAQ,OAAA,IAAW,OAAA;AAChC,MAAA,IAAI,CAAC,OAAA,EAAS;AAAE,QAAA;AAAA,MAAQ;AAAA,IAC1B,CAAA,CAAA,MAAQ;AACN,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,OAAO,CAAA,EAAG;AAC5B,MAAA,OAAA,CAAQ,KAAK,EAAE,EAAA,EAAI,OAAA,EAAS,MAAA,EAAQ,mBAAmB,CAAA;AACvD,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,QAAA,GAAW,KAAA;AACf,IAAA,KAAA,MAAWE,SAAAA,IAAY,IAAA,CAAK,UAAA,CAAW,MAAA,EAAO,EAAG;AAC/C,MAAA,MAAM,IAAA,GAAO,MAAMA,SAAAA,CAAS,UAAA,CAAW,MAAM,CAAA;AAC7C,MAAA,IAAI,IAAA,EAAM;AAAE,QAAA,QAAA,GAAW,IAAA;AAAM,QAAA;AAAA,MAAO;AAAA,IACtC;AACA,IAAA,IAAI,CAAC,QAAA,EAAU;AAAE,MAAA;AAAA,IAAQ;AAEzB,IAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,UAAA,CAAW,MAAM,CAAA;AAChD,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,WAAW,CAAA;AAChD,IAAA,MAAM,QAAA,GAAW,WAAW,MAAM,QAAA,CAAS,gBAAgB,MAAM,CAAA,GAAI,CAAC,WAAW,CAAA;AACjF,IAAA,MAAM,SAAA,GAAY,MAAM,gBAAA,CAAiB,MAAM,CAAA;AAK/C,IAAA,MAAM,UAAA,GAAA,CAAc,UAAU,SAAA,GAAY,MAAM,SAAS,SAAA,CAAU,MAAM,IAAI,IAAA,KAAS,OAAA;AAEtF,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,UAAU,CAAA,IAAK,eAAe,OAAA,EAAS;AACzD,MAAA,OAAA,CAAQ,KAAK,EAAE,EAAA,EAAI,UAAA,EAAY,MAAA,EAAQ,mBAAmB,CAAA;AAC1D,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAQ,sBAAA,CAAuB;AAAA,MACnC,OAAA,EAAS,UAAA;AAAA,MACT,SAAA;AAAA,MACA,YAAA,EAAc,cAAA,CAAe,IAAA,CAAK,IAAA,EAAM,MAAM,CAAA;AAAA,MAC9C,MAAA,EAAQ,OAAA;AAAA,MACR,WAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,IAAI,CAAC,UAAA,EAAY;AAAE,MAAA,KAAA,CAAM,OAAA,GAAU,KAAA;AAAA,IAAO;AAE1C,IAAA,IAAA,CAAK,SAAA,CAAU,UAAU,CAAA,GAAI,KAAA;AAC7B,IAAA,KAAA,CAAM,KAAK,EAAE,EAAA,EAAI,YAAY,WAAA,EAAa,OAAA,EAAS,YAAY,CAAA;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAA,GAAgC;AACpC,IAAA,MAAM,IAAA,GAAO,IAAID,mBAAAA,EAAoB;AACrC,IAAA,MAAM,IAAA,GAAO,MAAM,mBAAA,CAAoB,IAAA,CAAK,MAAM,IAAI,CAAA;AACtD,IAAA,MAAM,SAAwB,EAAC;AAE/B,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,KAAA,EAAO,GAAG,MAAA,EAAQ,CAAC,EAAE,QAAA,EAAU,QAAQ,SAAA,EAAW,EAAA,EAAI,OAAA,EAAS,2BAAA,EAA6B,CAAA,EAAE;AAAA,IACnH;AAEA,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,SAAS,CAAA;AAE7C,IAAA,KAAA,MAAW,CAAC,EAAA,EAAI,KAAK,CAAA,IAAK,OAAA,EAAS;AACjC,MAAA,MAAM,OAAA,GAAe,KAAA,CAAA,OAAA,CAAQ,IAAA,CAAK,IAAA,EAAM,MAAM,YAAY,CAAA;AAG1D,MAAA,IAAI;AACF,QAAA,MAASD,UAAO,OAAO,CAAA;AAAA,MACzB,CAAA,CAAA,MAAQ;AACN,QAAA,MAAA,CAAO,IAAA,CAAK;AAAA,UACV,QAAA,EAAU,OAAA;AAAA,UACV,SAAA,EAAW,EAAA;AAAA,UACX,OAAA,EAAS,gCAAgC,OAAO,CAAA,CAAA;AAAA,UAChD,WAAA,EAAa,+BAA+B,EAAE,CAAA,YAAA;AAAA,SAC/C,CAAA;AACD,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,MAAM,SAAA,EAAW;AACnB,QAAA,MAAM,QAAA,GAAW,MAAM,gBAAA,CAAiB,OAAO,CAAA;AAC/C,QAAA,IAAI,QAAA,IAAY,QAAA,KAAa,KAAA,CAAM,SAAA,EAAW;AAC5C,UAAA,MAAA,CAAO,IAAA,CAAK;AAAA,YACV,QAAA,EAAU,SAAA;AAAA,YACV,SAAA,EAAW,EAAA;AAAA,YACX,OAAA,EAAS,CAAA,6BAAA,EAAgC,KAAA,CAAM,SAAS,SAAS,QAAQ,CAAA,CAAA;AAAA,YACzE,WAAA,EAAa,sCAAsC,EAAE,CAAA;AAAA,WACtD,CAAA;AAAA,QACH;AAAA,MACF;AAGA,MAAA,IAAI,CAAC,MAAM,SAAA,EAAW;AACpB,QAAA,MAAA,CAAO,IAAA,CAAK;AAAA,UACV,QAAA,EAAU,MAAA;AAAA,UACV,SAAA,EAAW,EAAA;AAAA,UACX,OAAA,EAAS,uBAAA;AAAA,UACT,WAAA,EAAa;AAAA,SACd,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,EAAA,EAAI,OAAO,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,QAAA,KAAa,OAAO,EAAE,MAAA,KAAW,CAAA;AAAA,MAC1D,OAAO,OAAA,CAAQ,MAAA;AAAA,MACf;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,WAAW,WAAA,EAA0C;AAEjE,IAAA,KAAA,MAAW,QAAA,IAAY,IAAA,CAAK,UAAA,CAAW,MAAA,EAAO,EAAG;AAC/C,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,UAAA,CAAW,WAAW,CAAA;AAClD,MAAA,IAAI,IAAA,EAAM;AAAC,QAAA,OAAO,IAAA;AAAA,MAAK;AAAA,IACzB;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,MAAc,aAAA,CACZ,SAAA,EACA,WAAA,EACA,aACA,SAAA,EACe;AACf,IAAA,IAAI;AACF,MAAA,IAAI,gBAAgB,QAAA,EAAU;AAC5B,QAAA,MAAM,IAAA,GAAO,IAAIC,mBAAAA,EAAoB;AACrC,QAAA,MAAM,QAAA,GAAW,MAAME,YAAAA,CAAa,WAAA,EAAa,IAAI,CAAA;AACrD,QAAA,IAAI,QAAA,EAAU;AACZ,UAAA,MAAM,aAAA,CAAc,IAAA,CAAK,IAAA,EAAM,SAAA,EAAW;AAAA,YACxC,YAAA,EAAc,QAAA;AAAA,YACd,QAAA;AAAA,YACA,QAAA,EAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,YACjC;AAAA,WACD,CAAA;AAAA,QACH;AAAA,MACF,CAAA,MAAA,IAAW,gBAAgB,SAAA,EAAW;AACpC,QAAA,MAAM,QAAA,GAAgB,KAAA,CAAA,IAAA,CAAK,WAAA,EAAa,MAAA,EAAQ,UAAU,CAAA;AAC1D,QAAA,MAAM,GAAA,GAAM,MAAM,OAAOC,aAAAA,CAAc,QAAQ,CAAA,CAAE,IAAA,CAAA;AACjD,QAAA,IAAI,IAAI,QAAA,EAAU;AAChB,UAAA,MAAM,aAAA,CAAc,IAAA,CAAK,IAAA,EAAM,SAAA,EAAW;AAAA,YACxC,YAAA,EAAc,SAAA;AAAA,YACd,UAAU,GAAA,CAAI,QAAA;AAAA,YACd,QAAA,EAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,YACjC;AAAA,WACD,CAAA;AAAA,QACH;AAAA,MACF;AAAA,IACF,SAAS,GAAA,EAAK;AAEZ,MAAA,OAAA,CAAQ,KAAK,CAAA,4CAAA,EAA+C,SAAS,CAAA,GAAA,EAAO,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AAAA,IACrG;AAAA,EACF;AACF;AAMA,SAAS,cAAA,CAAe,MAAc,OAAA,EAAyB;AAC7D,EAAA,MAAM,GAAA,GAAW,KAAA,CAAA,QAAA,CAAS,IAAA,EAAM,OAAO,CAAA;AACvC,EAAA,OAAO,IAAI,UAAA,CAAW,GAAG,CAAA,GAAI,GAAA,GAAM,KAAK,GAAG,CAAA,CAAA;AAC7C;AAEA,eAAe,iBAAiB,WAAA,EAAsC;AACpE,EAAA,IAAI;AACF,IAAA,MAAM,UAAU,MAASJ,EAAA,CAAA,QAAA,CAAc,KAAA,CAAA,IAAA,CAAK,WAAA,EAAa,cAAc,CAAC,CAAA;AACxE,IAAA,OAAO,CAAA,OAAA,EAAiB,kBAAW,QAAQ,CAAA,CAAE,OAAO,OAAO,CAAA,CAAE,MAAA,CAAO,QAAQ,CAAC,CAAA,CAAA;AAAA,EAC/E,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAA;AAAA,EACT;AACF","file":"index.js","sourcesContent":["/**\n * @module @kb-labs/marketplace-core/manifest-cache\n * Read/write .kb/marketplace.manifests.json — cached manifests for fast discovery.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport type { ManifestCache, ManifestCacheEntry } from '@kb-labs/marketplace-contracts';\n\nconst CACHE_FILE = '.kb/marketplace.manifests.json';\nconst SCHEMA_VERSION = 'kb.marketplace.manifests/1' as const;\n\n/**\n * Read the manifest cache from disk. Returns null if missing or invalid.\n */\nexport async function readManifestCache(root: string): Promise<ManifestCache | null> {\n const cachePath = path.join(root, CACHE_FILE);\n try {\n const raw = await fs.readFile(cachePath, 'utf-8');\n const parsed = JSON.parse(raw);\n if (parsed?.schema !== SCHEMA_VERSION) {return null;}\n return parsed as ManifestCache;\n } catch {\n return null;\n }\n}\n\n/**\n * Write the manifest cache atomically (tmp → rename).\n */\nexport async function writeManifestCache(root: string, cache: ManifestCache): Promise<void> {\n const cachePath = path.join(root, CACHE_FILE);\n const dir = path.dirname(cachePath);\n await fs.mkdir(dir, { recursive: true });\n\n const tmpPath = `${cachePath}.tmp.${randomUUID()}`;\n await fs.writeFile(tmpPath, JSON.stringify(cache, null, 2) + '\\n', 'utf-8');\n await fs.rename(tmpPath, cachePath);\n}\n\n/**\n * Create an empty manifest cache.\n */\nexport function createEmptyManifestCache(): ManifestCache {\n return { schema: SCHEMA_VERSION, entries: {} };\n}\n\n/**\n * Set a single entry in the manifest cache and persist.\n */\nexport async function setCacheEntry(\n root: string,\n packageId: string,\n entry: ManifestCacheEntry,\n): Promise<void> {\n const existing = await readManifestCache(root) ?? createEmptyManifestCache();\n existing.entries[packageId] = entry;\n await writeManifestCache(root, existing);\n}\n\n/**\n * Remove a single entry from the manifest cache and persist.\n */\nexport async function removeCacheEntry(\n root: string,\n packageId: string,\n): Promise<void> {\n const existing = await readManifestCache(root);\n if (!existing || !(packageId in existing.entries)) {return;}\n delete existing.entries[packageId];\n await writeManifestCache(root, existing);\n}\n","/**\n * @module @kb-labs/marketplace-core/strategies/plugin-strategy\n * Strategy for plugins — detects ManifestV3 and extracts entity kinds.\n */\n\nimport type { EntityKind } from '@kb-labs/core-discovery';\nimport type { EntityKindStrategy } from '@kb-labs/marketplace-contracts';\nimport { loadManifest, DiagnosticCollector, extractEntityKinds } from '@kb-labs/core-discovery';\n\nexport class PluginStrategy implements EntityKindStrategy {\n kind: EntityKind = 'plugin';\n\n async detectKind(packageRoot: string): Promise<EntityKind | null> {\n const diag = new DiagnosticCollector();\n const manifest = await loadManifest(packageRoot, diag);\n return manifest ? 'plugin' : null;\n }\n\n async extractProvides(packageRoot: string): Promise<EntityKind[]> {\n const diag = new DiagnosticCollector();\n const manifest = await loadManifest(packageRoot, diag);\n if (!manifest) {return ['plugin'];}\n return extractEntityKinds(manifest);\n }\n\n async resolveId(packageRoot: string): Promise<string | null> {\n const diag = new DiagnosticCollector();\n const manifest = await loadManifest(packageRoot, diag);\n return manifest?.id ?? null;\n }\n}\n","/**\n * @module @kb-labs/marketplace-core/strategies/adapter-strategy\n * Strategy for adapters — detects AdapterManifest, validates dependencies.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { EntityKind } from '@kb-labs/core-discovery';\nimport type { EntityKindStrategy, MarketplaceServiceAPI } from '@kb-labs/marketplace-contracts';\n\nexport class AdapterStrategy implements EntityKindStrategy {\n kind: EntityKind = 'adapter';\n\n async detectKind(packageRoot: string): Promise<EntityKind | null> {\n const manifest = await loadAdapterManifest(packageRoot);\n return manifest ? 'adapter' : null;\n }\n\n async extractProvides(_packageRoot: string): Promise<EntityKind[]> {\n return ['adapter'];\n }\n\n async afterInstall(\n packageId: string,\n packageRoot: string,\n service: MarketplaceServiceAPI,\n ): Promise<void> {\n const manifest = await loadAdapterManifest(packageRoot);\n if (!manifest?.requires?.adapters) {return;}\n\n const installed = await service.list({ kind: 'adapter' });\n const installedIds = new Set(installed.map(e => (e as any).id as string));\n\n for (const dep of manifest.requires.adapters) {\n const depId = typeof dep === 'string' ? dep : dep.id;\n // Check by package ID (exact match), not by path substring\n const found = installedIds.has(depId) ||\n installed.some(e => (e as any).id?.includes(`adapters-${depId}`));\n\n if (!found) {\n console.warn(\n `[marketplace] Adapter \"${packageId}\" requires adapter \"${depId}\" which is not installed. ` +\n `Run: kb marketplace link <adapter-package-that-provides-${depId}>`\n );\n }\n }\n }\n\n async beforeUninstall(\n packageId: string,\n service: MarketplaceServiceAPI,\n ): Promise<void> {\n // Check if any other installed adapter depends on this one\n // This requires loading manifests — for now, warn about potential breakage\n const installed = await service.list({ kind: 'adapter' });\n if (installed.length > 1) {\n console.warn(\n `[marketplace] Removing adapter \"${packageId}\" — verify no other adapters depend on it`\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\ninterface AdapterManifestLike {\n id?: string;\n type?: 'core' | 'extension' | 'proxy';\n implements?: string;\n requires?: {\n adapters?: Array<string | { id: string; alias?: string }>;\n };\n}\n\nasync function loadAdapterManifest(packageRoot: string): Promise<AdapterManifestLike | null> {\n try {\n const distPath = path.join(packageRoot, 'dist', 'index.js');\n await fs.access(distPath);\n const mod = await import(pathToFileURL(distPath).href);\n if (mod.manifest && typeof mod.manifest === 'object' && mod.manifest.implements) {\n return mod.manifest as AdapterManifestLike;\n }\n return null;\n } catch {\n return null;\n }\n}\n","/**\n * @module @kb-labs/marketplace-core/marketplace-service\n * Unified marketplace service — install/uninstall/enable/disable for all entity types.\n * Works through PackageSource abstraction — never calls pnpm directly.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport * as crypto from 'node:crypto';\nimport { pathToFileURL } from 'node:url';\nimport { glob } from 'glob';\nimport type { EntityKind, MarketplaceEntry, MarketplaceLock } from '@kb-labs/core-discovery';\nimport {\n readMarketplaceLock,\n writeMarketplaceLock,\n createEmptyLock,\n createMarketplaceEntry,\n addToMarketplaceLock,\n removeFromMarketplaceLock,\n enablePlugin,\n disablePlugin,\n DiagnosticCollector,\n loadManifest,\n} from '@kb-labs/core-discovery';\nimport type {\n PackageSource,\n EntityKindStrategy,\n MarketplaceServiceAPI,\n MarketplaceEntryWithId,\n InstallResult,\n InstallResultEntry,\n SyncResult,\n DoctorReport,\n DoctorIssue,\n} from '@kb-labs/marketplace-contracts';\nimport { setCacheEntry, removeCacheEntry } from './manifest-cache.js';\nimport { PluginStrategy } from './strategies/plugin-strategy.js';\nimport { AdapterStrategy } from './strategies/adapter-strategy.js';\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface MarketplaceServiceOptions {\n /** Workspace root directory */\n root: string;\n /** Package source (npm, registry, etc.) */\n source: PackageSource;\n /** Additional strategies beyond built-in plugin/adapter */\n strategies?: EntityKindStrategy[];\n}\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class MarketplaceService implements MarketplaceServiceAPI {\n private readonly root: string;\n private readonly source: PackageSource;\n private readonly strategies = new Map<EntityKind, EntityKindStrategy>();\n\n constructor(opts: MarketplaceServiceOptions) {\n this.root = opts.root;\n this.source = opts.source;\n\n // Built-in strategies\n this.registerStrategy(new PluginStrategy());\n this.registerStrategy(new AdapterStrategy());\n\n // User-supplied strategies\n if (opts.strategies) {\n for (const s of opts.strategies) {\n this.registerStrategy(s);\n }\n }\n }\n\n registerStrategy(strategy: EntityKindStrategy): void {\n this.strategies.set(strategy.kind, strategy);\n }\n\n // -------------------------------------------------------------------------\n // Install\n // -------------------------------------------------------------------------\n\n async install(specs: string[], opts?: { dev?: boolean }): Promise<InstallResult> {\n const installed: InstallResultEntry[] = [];\n const warnings: string[] = [];\n\n for (const spec of specs) {\n const resolved = await this.source.resolve(spec);\n const result = await this.source.install(resolved, this.root, opts);\n\n // Detect primary kind via strategies\n const primaryKind = await this.detectKind(result.packageRoot);\n const strategy = this.strategies.get(primaryKind);\n const provides = strategy\n ? await strategy.extractProvides(result.packageRoot)\n : [primaryKind];\n\n // Write to marketplace.lock\n const entry = createMarketplaceEntry({\n version: result.version,\n integrity: result.integrity,\n resolvedPath: relativeToRoot(this.root, result.packageRoot),\n source: resolved.source,\n primaryKind,\n provides,\n });\n\n await addToMarketplaceLock(this.root, result.id, entry);\n\n // Cache manifest\n await this.cacheManifest(result.id, result.packageRoot, primaryKind, result.integrity);\n\n // Run post-install hook\n if (strategy?.afterInstall) {\n try {\n await strategy.afterInstall(result.id, result.packageRoot, this);\n } catch (err) {\n warnings.push(`afterInstall for ${result.id}: ${(err as Error).message}`);\n }\n }\n\n installed.push({\n id: result.id,\n version: result.version,\n primaryKind,\n provides,\n packageRoot: result.packageRoot,\n });\n }\n\n return { installed, warnings };\n }\n\n // -------------------------------------------------------------------------\n // Uninstall\n // -------------------------------------------------------------------------\n\n async uninstall(packageIds: string[]): Promise<void> {\n for (const id of packageIds) {\n // Run pre-uninstall hook\n const entry = await this.getEntry(id);\n if (entry) {\n const strategy = this.strategies.get(entry.primaryKind);\n if (strategy?.beforeUninstall) {\n await strategy.beforeUninstall(id, this);\n }\n }\n\n // Remove from lock\n await removeFromMarketplaceLock(this.root, id);\n\n // Remove from manifest cache\n await removeCacheEntry(this.root, id);\n\n // Remove from disk\n await this.source.remove(id, this.root);\n }\n }\n\n // -------------------------------------------------------------------------\n // Link / Unlink\n // -------------------------------------------------------------------------\n\n async link(packagePath: string): Promise<InstallResultEntry> {\n const absPath = path.resolve(this.root, packagePath);\n\n // Path traversal guard — linked path must be within workspace root\n if (!absPath.startsWith(this.root)) {\n throw new Error(`Path \"${packagePath}\" is outside workspace root — refusing to link`);\n }\n\n const pkgJson = JSON.parse(\n await fs.readFile(\n path.join(absPath, 'package.json'), 'utf-8',\n ),\n );\n const id: string = pkgJson.name;\n const version: string = pkgJson.version ?? '0.0.0';\n\n const primaryKind = await this.detectKind(absPath);\n const strategy = this.strategies.get(primaryKind);\n const provides = strategy\n ? await strategy.extractProvides(absPath)\n : [primaryKind];\n\n const integrity = await computeIntegrity(absPath);\n\n const entry = createMarketplaceEntry({\n version,\n integrity,\n resolvedPath: relativeToRoot(this.root, absPath),\n source: 'local',\n primaryKind,\n provides,\n });\n\n await addToMarketplaceLock(this.root, id, entry);\n await this.cacheManifest(id, absPath, primaryKind, integrity);\n\n if (strategy?.afterInstall) {\n await strategy.afterInstall(id, absPath, this);\n }\n\n return { id, version, primaryKind, provides, packageRoot: absPath };\n }\n\n async unlink(packageId: string): Promise<void> {\n await removeFromMarketplaceLock(this.root, packageId);\n await removeCacheEntry(this.root, packageId);\n }\n\n // -------------------------------------------------------------------------\n // Update\n // -------------------------------------------------------------------------\n\n async update(packageIds?: string[]): Promise<InstallResult> {\n const diag = new DiagnosticCollector();\n const lock = await readMarketplaceLock(this.root, diag);\n if (!lock) {return { installed: [], warnings: ['No marketplace.lock found'] };}\n\n const ids = packageIds ?? Object.keys(lock.installed);\n const specs = ids.filter(id => id in lock.installed);\n\n // Re-install at latest\n return this.install(specs);\n }\n\n // -------------------------------------------------------------------------\n // Enable / Disable\n // -------------------------------------------------------------------------\n\n async enable(packageId: string): Promise<void> {\n const ok = await enablePlugin(this.root, packageId);\n if (!ok) {\n throw new Error(`Package \"${packageId}\" not found in marketplace.lock`);\n }\n }\n\n async disable(packageId: string): Promise<void> {\n const ok = await disablePlugin(this.root, packageId);\n if (!ok) {\n throw new Error(`Package \"${packageId}\" not found in marketplace.lock`);\n }\n }\n\n // -------------------------------------------------------------------------\n // List / GetEntry (MarketplaceServiceAPI)\n // -------------------------------------------------------------------------\n\n async list(filter?: { kind?: EntityKind }): Promise<MarketplaceEntryWithId[]> {\n const diag = new DiagnosticCollector();\n const lock = await readMarketplaceLock(this.root, diag);\n if (!lock) {return [];}\n\n let entries = Object.entries(lock.installed).map(([id, entry]) => ({ ...entry, id }));\n if (filter?.kind) {\n entries = entries.filter(e => e.primaryKind === filter.kind);\n }\n return entries;\n }\n\n async getEntry(packageId: string): Promise<MarketplaceEntry | null> {\n const diag = new DiagnosticCollector();\n const lock = await readMarketplaceLock(this.root, diag);\n return lock?.installed[packageId] ?? null;\n }\n\n // -------------------------------------------------------------------------\n // Sync (scan workspace → populate lock from config-driven globs)\n // -------------------------------------------------------------------------\n\n /**\n * Scan workspace for plugins and adapters using glob patterns.\n * Existing entries are preserved (not overwritten).\n * Patterns come from kb.config.json marketplace.sync.include.\n */\n async sync(opts: {\n include: string[];\n exclude?: string[];\n autoEnable?: boolean;\n }): Promise<SyncResult> {\n const autoEnable = opts.autoEnable ?? false;\n const diag = new DiagnosticCollector();\n const lock = await readMarketplaceLock(this.root, diag) ?? createEmptyLock();\n const existingIds = new Set(Object.keys(lock.installed));\n\n const added: SyncResult['added'] = [];\n const skipped: SyncResult['skipped'] = [];\n\n // Resolve glob patterns to package directories\n const includePatterns = opts.include.map(p => path.join(p, 'package.json'));\n const excludePatterns = opts.exclude ?? [];\n\n const packageJsonPaths = await glob(includePatterns, {\n cwd: this.root,\n ignore: excludePatterns,\n absolute: false,\n });\n\n for (const relPkgJson of packageJsonPaths) {\n const pkgDir = path.resolve(this.root, path.dirname(relPkgJson));\n await this._syncPackage(pkgDir, relPkgJson, existingIds, autoEnable, lock, added, skipped);\n }\n\n await writeMarketplaceLock(this.root, lock);\n\n return { added, skipped, total: Object.keys(lock.installed).length };\n }\n\n private async _syncPackage(\n pkgDir: string,\n _relPkgJson: string,\n existingIds: Set<string>,\n autoEnable: boolean,\n lock: MarketplaceLock,\n added: SyncResult['added'],\n skipped: SyncResult['skipped'],\n ): Promise<void> {\n let pkgName: string;\n let pkgVersion: string;\n try {\n const pkgJson = JSON.parse(await fs.readFile(path.join(pkgDir, 'package.json'), 'utf-8'));\n pkgName = pkgJson.name;\n pkgVersion = pkgJson.version ?? '0.0.0';\n if (!pkgName) { return; }\n } catch {\n return;\n }\n\n if (existingIds.has(pkgName)) {\n skipped.push({ id: pkgName, reason: 'already in lock' });\n return;\n }\n\n let detected = false;\n for (const strategy of this.strategies.values()) {\n const kind = await strategy.detectKind(pkgDir);\n if (kind) { detected = true; break; }\n }\n if (!detected) { return; }\n\n const primaryKind = await this.detectKind(pkgDir);\n const strategy = this.strategies.get(primaryKind);\n const provides = strategy ? await strategy.extractProvides(pkgDir) : [primaryKind];\n const integrity = await computeIntegrity(pkgDir);\n\n // Use manifest ID as lock key if the strategy can resolve it.\n // This keeps discovery working even when package.json name differs from manifest.id\n // (e.g. after folder renames like cli/ → entry/).\n const resolvedId = (strategy?.resolveId ? await strategy.resolveId(pkgDir) : null) ?? pkgName;\n\n if (existingIds.has(resolvedId) && resolvedId !== pkgName) {\n skipped.push({ id: resolvedId, reason: 'already in lock' });\n return;\n }\n\n const entry = createMarketplaceEntry({\n version: pkgVersion,\n integrity,\n resolvedPath: relativeToRoot(this.root, pkgDir),\n source: 'local',\n primaryKind,\n provides,\n });\n\n if (!autoEnable) { entry.enabled = false; }\n\n lock.installed[resolvedId] = entry;\n added.push({ id: resolvedId, primaryKind, version: pkgVersion });\n }\n\n // -------------------------------------------------------------------------\n // Doctor\n // -------------------------------------------------------------------------\n\n async doctor(): Promise<DoctorReport> {\n const diag = new DiagnosticCollector();\n const lock = await readMarketplaceLock(this.root, diag);\n const issues: DoctorIssue[] = [];\n\n if (!lock) {\n return { ok: true, total: 0, issues: [{ severity: 'info', packageId: '', message: 'No marketplace.lock found' }] };\n }\n\n const entries = Object.entries(lock.installed);\n\n for (const [id, entry] of entries) {\n const pkgRoot = path.resolve(this.root, entry.resolvedPath);\n\n // Check package exists\n try {\n await fs.access(pkgRoot);\n } catch {\n issues.push({\n severity: 'error',\n packageId: id,\n message: `Package directory not found: ${pkgRoot}`,\n remediation: `Run \"kb marketplace install ${id}\" to restore`,\n });\n continue;\n }\n\n // Check integrity\n if (entry.integrity) {\n const computed = await computeIntegrity(pkgRoot);\n if (computed && computed !== entry.integrity) {\n issues.push({\n severity: 'warning',\n packageId: id,\n message: `Integrity mismatch: expected ${entry.integrity}, got ${computed}`,\n remediation: `Re-install: kb marketplace install ${id}`,\n });\n }\n }\n\n // Check signature\n if (!entry.signature) {\n issues.push({\n severity: 'info',\n packageId: id,\n message: 'Package is not signed',\n remediation: 'Publish through the official marketplace to get a platform signature',\n });\n }\n }\n\n return {\n ok: issues.filter(i => i.severity === 'error').length === 0,\n total: entries.length,\n issues,\n };\n }\n\n // -------------------------------------------------------------------------\n // Private\n // -------------------------------------------------------------------------\n\n private async detectKind(packageRoot: string): Promise<EntityKind> {\n // Try each strategy in registration order\n for (const strategy of this.strategies.values()) {\n const kind = await strategy.detectKind(packageRoot);\n if (kind) {return kind;}\n }\n // Default: plugin\n return 'plugin';\n }\n\n private async cacheManifest(\n packageId: string,\n packageRoot: string,\n primaryKind: EntityKind,\n integrity: string,\n ): Promise<void> {\n try {\n if (primaryKind === 'plugin') {\n const diag = new DiagnosticCollector();\n const manifest = await loadManifest(packageRoot, diag);\n if (manifest) {\n await setCacheEntry(this.root, packageId, {\n manifestType: 'plugin',\n manifest,\n cachedAt: new Date().toISOString(),\n integrity,\n });\n }\n } else if (primaryKind === 'adapter') {\n const distPath = path.join(packageRoot, 'dist', 'index.js');\n const mod = await import(pathToFileURL(distPath).href);\n if (mod.manifest) {\n await setCacheEntry(this.root, packageId, {\n manifestType: 'adapter',\n manifest: mod.manifest,\n cachedAt: new Date().toISOString(),\n integrity,\n });\n }\n }\n } catch (err) {\n // Non-fatal — cache miss means slower next discovery, but log for diagnostics\n console.warn(`[marketplace] Failed to cache manifest for \"${packageId}\": ${(err as Error).message}`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction relativeToRoot(root: string, absPath: string): string {\n const rel = path.relative(root, absPath);\n return rel.startsWith('.') ? rel : `./${rel}`;\n}\n\nasync function computeIntegrity(packageRoot: string): Promise<string> {\n try {\n const content = await fs.readFile(path.join(packageRoot, 'package.json'));\n return `sha256-${crypto.createHash('sha256').update(content).digest('base64')}`;\n } catch {\n return '';\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/manifest-cache.ts","../src/strategies/plugin-strategy.ts","../src/strategies/adapter-strategy.ts","../src/scope.ts","../src/marketplace-service.ts"],"names":["path","path2","fs2","path3","fs3","DiagnosticCollector","strategy","loadManifest","pathToFileURL"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @module @kb-labs/marketplace-core/manifest-cache\n * Read/write .kb/marketplace.manifests.json — cached manifests for fast discovery.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport type { ManifestCache, ManifestCacheEntry } from '@kb-labs/marketplace-contracts';\n\nconst CACHE_FILE = '.kb/marketplace.manifests.json';\nconst SCHEMA_VERSION = 'kb.marketplace.manifests/1' as const;\n\n/**\n * Read the manifest cache from disk. Returns null if missing or invalid.\n */\nexport async function readManifestCache(root: string): Promise<ManifestCache | null> {\n const cachePath = path.join(root, CACHE_FILE);\n try {\n const raw = await fs.readFile(cachePath, 'utf-8');\n const parsed = JSON.parse(raw);\n if (parsed?.schema !== SCHEMA_VERSION) {return null;}\n return parsed as ManifestCache;\n } catch {\n return null;\n }\n}\n\n/**\n * Write the manifest cache atomically (tmp → rename).\n */\nexport async function writeManifestCache(root: string, cache: ManifestCache): Promise<void> {\n const cachePath = path.join(root, CACHE_FILE);\n const dir = path.dirname(cachePath);\n await fs.mkdir(dir, { recursive: true });\n\n const tmpPath = `${cachePath}.tmp.${randomUUID()}`;\n await fs.writeFile(tmpPath, JSON.stringify(cache, null, 2) + '\\n', 'utf-8');\n await fs.rename(tmpPath, cachePath);\n}\n\n/**\n * Create an empty manifest cache.\n */\nexport function createEmptyManifestCache(): ManifestCache {\n return { schema: SCHEMA_VERSION, entries: {} };\n}\n\n/**\n * Set a single entry in the manifest cache and persist.\n */\nexport async function setCacheEntry(\n root: string,\n packageId: string,\n entry: ManifestCacheEntry,\n): Promise<void> {\n const existing = await readManifestCache(root) ?? createEmptyManifestCache();\n existing.entries[packageId] = entry;\n await writeManifestCache(root, existing);\n}\n\n/**\n * Remove a single entry from the manifest cache and persist.\n */\nexport async function removeCacheEntry(\n root: string,\n packageId: string,\n): Promise<void> {\n const existing = await readManifestCache(root);\n if (!existing || !(packageId in existing.entries)) {return;}\n delete existing.entries[packageId];\n await writeManifestCache(root, existing);\n}\n","/**\n * @module @kb-labs/marketplace-core/strategies/plugin-strategy\n * Strategy for plugins — detects ManifestV3 and extracts entity kinds.\n */\n\nimport type { EntityKind } from '@kb-labs/core-discovery';\nimport type { EntityKindStrategy } from '@kb-labs/marketplace-contracts';\nimport { loadManifest, DiagnosticCollector, extractEntityKinds } from '@kb-labs/core-discovery';\n\nexport class PluginStrategy implements EntityKindStrategy {\n kind: EntityKind = 'plugin';\n\n async detectKind(packageRoot: string): Promise<EntityKind | null> {\n const diag = new DiagnosticCollector();\n const manifest = await loadManifest(packageRoot, diag);\n return manifest ? 'plugin' : null;\n }\n\n async extractProvides(packageRoot: string): Promise<EntityKind[]> {\n const diag = new DiagnosticCollector();\n const manifest = await loadManifest(packageRoot, diag);\n if (!manifest) {return ['plugin'];}\n return extractEntityKinds(manifest);\n }\n\n async resolveId(packageRoot: string): Promise<string | null> {\n const diag = new DiagnosticCollector();\n const manifest = await loadManifest(packageRoot, diag);\n return manifest?.id ?? null;\n }\n}\n","/**\n * @module @kb-labs/marketplace-core/strategies/adapter-strategy\n * Strategy for adapters — detects AdapterManifest, validates dependencies.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { EntityKind } from '@kb-labs/core-discovery';\nimport type {\n EntityKindStrategy,\n MarketplaceServiceAPI,\n ScopeContext,\n} from '@kb-labs/marketplace-contracts';\n\nexport class AdapterStrategy implements EntityKindStrategy {\n kind: EntityKind = 'adapter';\n\n async detectKind(packageRoot: string): Promise<EntityKind | null> {\n const manifest = await loadAdapterManifest(packageRoot);\n return manifest ? 'adapter' : null;\n }\n\n async extractProvides(_packageRoot: string): Promise<EntityKind[]> {\n return ['adapter'];\n }\n\n async afterInstall(\n packageId: string,\n packageRoot: string,\n service: MarketplaceServiceAPI,\n ctx: ScopeContext,\n ): Promise<void> {\n const manifest = await loadAdapterManifest(packageRoot);\n if (!manifest?.requires?.adapters) {return;}\n\n // Adapters only live in platform scope (guarded in MarketplaceService),\n // so we query the same scope we were invoked with.\n const installed = await service.list(ctx, { kind: 'adapter' });\n const installedIds = new Set(installed.map(e => e.id));\n\n for (const dep of manifest.requires.adapters) {\n const depId = typeof dep === 'string' ? dep : dep.id;\n const found = installedIds.has(depId) ||\n installed.some(e => e.id.includes(`adapters-${depId}`));\n\n if (!found) {\n console.warn(\n `[marketplace] Adapter \"${packageId}\" requires adapter \"${depId}\" which is not installed. ` +\n `Run: kb marketplace link <adapter-package-that-provides-${depId}>`,\n );\n }\n }\n }\n\n async beforeUninstall(\n packageId: string,\n service: MarketplaceServiceAPI,\n ctx: ScopeContext,\n ): Promise<void> {\n const installed = await service.list(ctx, { kind: 'adapter' });\n if (installed.length > 1) {\n console.warn(\n `[marketplace] Removing adapter \"${packageId}\" — verify no other adapters depend on it`,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\ninterface AdapterManifestLike {\n id?: string;\n type?: 'core' | 'extension' | 'proxy';\n implements?: string;\n requires?: {\n adapters?: Array<string | { id: string; alias?: string }>;\n };\n}\n\nasync function loadAdapterManifest(packageRoot: string): Promise<AdapterManifestLike | null> {\n try {\n const distPath = path.join(packageRoot, 'dist', 'index.js');\n await fs.access(distPath);\n const mod = await import(pathToFileURL(distPath).href);\n if (mod.manifest && typeof mod.manifest === 'object' && mod.manifest.implements) {\n return mod.manifest as AdapterManifestLike;\n }\n return null;\n } catch {\n return null;\n }\n}\n","/**\n * @module @kb-labs/marketplace-core/scope\n * Scope resolution helpers for the platform/project marketplace split.\n *\n * Every mutating service method is explicitly scope-bound — there is no\n * implicit default. The helpers below compute the absolute root directory\n * for a given ScopeContext and enforce the invariants that the rest of the\n * service relies on (distinct platform/project roots, project has a `.kb/`).\n */\n\nimport * as path from 'node:path';\nimport { accessSync, constants } from 'node:fs';\nimport type {\n MarketplaceScope,\n MarketplaceQueryScope,\n ScopeContext,\n QueryScopeContext,\n} from '@kb-labs/marketplace-contracts';\n\nconst CONFIG_FILE_CANDIDATES = ['kb.config.jsonc', 'kb.config.json'] as const;\n\n/**\n * Roots known to the MarketplaceService at construction time.\n * `platformRoot` is always known. `projectRoot` is optional at construction\n * (daemon may serve multiple projects); per-call `ctx.projectRoot` can\n * override it.\n */\nexport interface ServiceRoots {\n platformRoot: string;\n projectRoot?: string;\n}\n\n/**\n * Resolve the absolute scope root for a single mutating call.\n *\n * - `scope: 'platform'` — returns `roots.platformRoot`. `projectRoot` in\n * the context is ignored.\n * - `scope: 'project'` — prefers `ctx.projectRoot`, falls back to\n * `roots.projectRoot` from construction. Throws if neither is set,\n * if the path isn't absolute, doesn't exist, lacks a `.kb/kb.config.*`,\n * or equals `roots.platformRoot`.\n */\nexport function resolveScopeRoot(roots: ServiceRoots, ctx: ScopeContext): string {\n if (ctx.scope === 'platform') {\n return roots.platformRoot;\n }\n\n const candidate = ctx.projectRoot ?? roots.projectRoot;\n if (!candidate) {\n throw new ScopeResolutionError(\n 'SCOPE_PROJECT_ROOT_MISSING',\n 'scope=\"project\" requires a projectRoot (pass ctx.projectRoot or configure the service with projectRoot).',\n );\n }\n\n if (!path.isAbsolute(candidate)) {\n throw new ScopeResolutionError(\n 'SCOPE_PROJECT_ROOT_NOT_ABSOLUTE',\n `projectRoot must be absolute, got \"${candidate}\".`,\n );\n }\n\n try {\n accessSync(candidate, constants.F_OK);\n } catch {\n throw new ScopeResolutionError(\n 'SCOPE_PROJECT_ROOT_NOT_FOUND',\n `projectRoot does not exist: \"${candidate}\".`,\n );\n }\n\n const hasConfig = CONFIG_FILE_CANDIDATES.some((name) => {\n try {\n accessSync(path.join(candidate, '.kb', name), constants.F_OK);\n return true;\n } catch {\n return false;\n }\n });\n if (!hasConfig) {\n throw new ScopeResolutionError(\n 'SCOPE_PROJECT_ROOT_NO_KB_DIR',\n `projectRoot \"${candidate}\" does not contain .kb/kb.config.{json,jsonc} — refusing to treat it as a project.`,\n );\n }\n\n if (path.resolve(candidate) === path.resolve(roots.platformRoot)) {\n throw new ScopeResolutionError(\n 'SCOPE_PROJECT_EQUALS_PLATFORM',\n 'projectRoot must not equal platformRoot; use scope=\"platform\" for platform-level operations.',\n );\n }\n\n return path.resolve(candidate);\n}\n\n/**\n * Resolve the set of roots to read from for a query context (`list`,\n * `getEntry`). `'all'` returns both; the caller is responsible for merging\n * with a platform-wins precedence.\n */\nexport function resolveQueryRoots(\n roots: ServiceRoots,\n ctx: QueryScopeContext,\n): Array<{ scope: MarketplaceScope; root: string }> {\n if (ctx.scope === 'platform') {\n return [{ scope: 'platform', root: roots.platformRoot }];\n }\n if (ctx.scope === 'project') {\n return [\n {\n scope: 'project',\n root: resolveScopeRoot(roots, { scope: 'project', projectRoot: ctx.projectRoot }),\n },\n ];\n }\n // 'all' — platform is always included. Project is included only when a\n // project root is available (explicitly via ctx or implicitly from the\n // service). If no project context is known, 'all' degrades to platform-only.\n const out: Array<{ scope: MarketplaceScope; root: string }> = [\n { scope: 'platform', root: roots.platformRoot },\n ];\n const projectCandidate = ctx.projectRoot ?? roots.projectRoot;\n if (projectCandidate) {\n try {\n const projectRoot = resolveScopeRoot(roots, { scope: 'project', projectRoot: projectCandidate });\n out.push({ scope: 'project', root: projectRoot });\n } catch {\n // For 'all' we swallow resolution errors — a missing or invalid project\n // context should not block a platform-only listing.\n }\n }\n return out;\n}\n\n/**\n * Thrown when a scope context cannot be resolved to a concrete root.\n * Uses a stable `code` so API/CLI can surface actionable errors.\n */\nexport class ScopeResolutionError extends Error {\n readonly code: string;\n constructor(code: string, message: string) {\n super(message);\n this.code = code;\n this.name = 'ScopeResolutionError';\n }\n}\n","/**\n * @module @kb-labs/marketplace-core/marketplace-service\n * Unified marketplace service — install/uninstall/enable/disable for all entity types.\n *\n * Every mutating method is explicitly scope-bound (`platform` or `project`).\n * There is no implicit default: callers pass a `ScopeContext` per call so\n * the service can target the right `.kb/marketplace.lock`.\n *\n * Works through PackageSource abstraction — never calls pnpm directly.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport * as crypto from 'node:crypto';\nimport { pathToFileURL } from 'node:url';\nimport { glob } from 'glob';\nimport type { EntityKind, MarketplaceEntry, MarketplaceLock } from '@kb-labs/core-discovery';\nimport {\n readMarketplaceLock,\n writeMarketplaceLock,\n createEmptyLock,\n createMarketplaceEntry,\n addToMarketplaceLock,\n removeFromMarketplaceLock,\n enablePlugin,\n disablePlugin,\n DiagnosticCollector,\n loadManifest,\n} from '@kb-labs/core-discovery';\nimport type {\n PackageSource,\n EntityKindStrategy,\n MarketplaceServiceAPI,\n MarketplaceEntryWithId,\n ScopedMarketplaceEntry,\n ScopeContext,\n QueryScopeContext,\n MarketplaceScope,\n MarketplaceDiagnostic,\n InstallResult,\n InstallResultEntry,\n SyncResult,\n DoctorReport,\n DoctorIssue,\n} from '@kb-labs/marketplace-contracts';\nimport { setCacheEntry, removeCacheEntry } from './manifest-cache.js';\nimport { PluginStrategy } from './strategies/plugin-strategy.js';\nimport { AdapterStrategy } from './strategies/adapter-strategy.js';\nimport { resolveScopeRoot, resolveQueryRoots, type ServiceRoots } from './scope.js';\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface MarketplaceServiceOptions {\n /** Platform workspace root — always required. Used for `scope: 'platform'`. */\n platformRoot: string;\n /**\n * Default project root. Optional — a daemon serving multiple projects can\n * leave this unset and pass `ctx.projectRoot` per call. When both are\n * provided, per-call `ctx.projectRoot` wins.\n */\n projectRoot?: string;\n /** Package source (npm, registry, etc.) */\n source: PackageSource;\n /** Additional strategies beyond built-in plugin/adapter */\n strategies?: EntityKindStrategy[];\n}\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class MarketplaceService implements MarketplaceServiceAPI {\n private readonly roots: ServiceRoots;\n private readonly source: PackageSource;\n private readonly strategies = new Map<EntityKind, EntityKindStrategy>();\n\n constructor(opts: MarketplaceServiceOptions) {\n this.roots = { platformRoot: opts.platformRoot, projectRoot: opts.projectRoot };\n this.source = opts.source;\n\n // Built-in strategies\n this.registerStrategy(new PluginStrategy());\n this.registerStrategy(new AdapterStrategy());\n\n // User-supplied strategies\n if (opts.strategies) {\n for (const s of opts.strategies) {\n this.registerStrategy(s);\n }\n }\n }\n\n registerStrategy(strategy: EntityKindStrategy): void {\n this.strategies.set(strategy.kind, strategy);\n }\n\n // -------------------------------------------------------------------------\n // Install\n // -------------------------------------------------------------------------\n\n async install(\n ctx: ScopeContext,\n specs: string[],\n opts?: { dev?: boolean },\n ): Promise<InstallResult> {\n const scopeRoot = resolveScopeRoot(this.roots, ctx);\n const installed: InstallResultEntry[] = [];\n const warnings: string[] = [];\n const diagnostics: MarketplaceDiagnostic[] = [];\n\n for (const spec of specs) {\n const resolved = await this.source.resolve(spec);\n const result = await this.source.install(resolved, scopeRoot, opts);\n\n // Detect primary kind via strategies\n const primaryKind = await this.detectKind(result.packageRoot);\n this.assertScopeAllowsKind(ctx.scope, primaryKind);\n\n const strategy = this.strategies.get(primaryKind);\n const provides = strategy\n ? await strategy.extractProvides(result.packageRoot)\n : [primaryKind];\n\n // Write to marketplace.lock\n const entry = createMarketplaceEntry({\n version: result.version,\n integrity: result.integrity,\n resolvedPath: relativeToRoot(scopeRoot, result.packageRoot),\n source: resolved.source,\n primaryKind,\n provides,\n });\n\n await addToMarketplaceLock(scopeRoot, result.id, entry);\n\n // Cache manifest\n await this.cacheManifest(scopeRoot, result.id, result.packageRoot, primaryKind, result.integrity);\n\n // Run post-install hook\n if (strategy?.afterInstall) {\n try {\n await strategy.afterInstall(result.id, result.packageRoot, this, ctx);\n } catch (err) {\n warnings.push(`afterInstall for ${result.id}: ${(err as Error).message}`);\n }\n }\n\n installed.push({\n id: result.id,\n version: result.version,\n primaryKind,\n provides,\n packageRoot: result.packageRoot,\n scope: ctx.scope,\n });\n }\n\n return { installed, warnings, scope: ctx.scope, diagnostics: diagnostics.length ? diagnostics : undefined };\n }\n\n // -------------------------------------------------------------------------\n // Uninstall\n // -------------------------------------------------------------------------\n\n async uninstall(ctx: ScopeContext, packageIds: string[]): Promise<void> {\n const scopeRoot = resolveScopeRoot(this.roots, ctx);\n for (const id of packageIds) {\n // Run pre-uninstall hook\n const entry = await this.getEntry(ctx, id);\n if (entry) {\n const strategy = this.strategies.get(entry.primaryKind);\n if (strategy?.beforeUninstall) {\n await strategy.beforeUninstall(id, this, ctx);\n }\n }\n\n await removeFromMarketplaceLock(scopeRoot, id);\n await removeCacheEntry(scopeRoot, id);\n await this.source.remove(id, scopeRoot);\n }\n }\n\n // -------------------------------------------------------------------------\n // Link / Unlink\n // -------------------------------------------------------------------------\n\n async link(ctx: ScopeContext, packagePath: string): Promise<InstallResultEntry> {\n const scopeRoot = resolveScopeRoot(this.roots, ctx);\n const absPath = path.resolve(scopeRoot, packagePath);\n\n // Path traversal guard — linked path must be within the scope root.\n if (!isPathInside(scopeRoot, absPath)) {\n throw new Error(\n `Path \"${packagePath}\" is outside ${ctx.scope} root \"${scopeRoot}\" — refusing to link`,\n );\n }\n\n const pkgJson = JSON.parse(\n await fs.readFile(path.join(absPath, 'package.json'), 'utf-8'),\n );\n const id: string = pkgJson.name;\n const version: string = pkgJson.version ?? '0.0.0';\n\n const primaryKind = await this.detectKind(absPath);\n this.assertScopeAllowsKind(ctx.scope, primaryKind);\n\n const strategy = this.strategies.get(primaryKind);\n const provides = strategy\n ? await strategy.extractProvides(absPath)\n : [primaryKind];\n\n const integrity = await computeIntegrity(absPath);\n\n const entry = createMarketplaceEntry({\n version,\n integrity,\n resolvedPath: relativeToRoot(scopeRoot, absPath),\n source: 'local',\n primaryKind,\n provides,\n });\n\n await addToMarketplaceLock(scopeRoot, id, entry);\n await this.cacheManifest(scopeRoot, id, absPath, primaryKind, integrity);\n\n if (strategy?.afterInstall) {\n await strategy.afterInstall(id, absPath, this, ctx);\n }\n\n return { id, version, primaryKind, provides, packageRoot: absPath, scope: ctx.scope };\n }\n\n async unlink(ctx: ScopeContext, packageId: string): Promise<void> {\n const scopeRoot = resolveScopeRoot(this.roots, ctx);\n await removeFromMarketplaceLock(scopeRoot, packageId);\n await removeCacheEntry(scopeRoot, packageId);\n }\n\n // -------------------------------------------------------------------------\n // Update\n // -------------------------------------------------------------------------\n\n async update(ctx: ScopeContext, packageIds?: string[]): Promise<InstallResult> {\n const scopeRoot = resolveScopeRoot(this.roots, ctx);\n const diag = new DiagnosticCollector();\n const lock = await readMarketplaceLock(scopeRoot, diag);\n if (!lock) {\n return { installed: [], warnings: ['No marketplace.lock found'], scope: ctx.scope };\n }\n\n const ids = packageIds ?? Object.keys(lock.installed);\n const specs = ids.filter(id => id in lock.installed);\n\n return this.install(ctx, specs);\n }\n\n // -------------------------------------------------------------------------\n // Enable / Disable\n // -------------------------------------------------------------------------\n\n async enable(ctx: ScopeContext, packageId: string): Promise<void> {\n const scopeRoot = resolveScopeRoot(this.roots, ctx);\n const ok = await enablePlugin(scopeRoot, packageId);\n if (!ok) {\n throw new Error(`Package \"${packageId}\" not found in ${ctx.scope} marketplace.lock`);\n }\n }\n\n async disable(ctx: ScopeContext, packageId: string): Promise<void> {\n const scopeRoot = resolveScopeRoot(this.roots, ctx);\n const ok = await disablePlugin(scopeRoot, packageId);\n if (!ok) {\n throw new Error(`Package \"${packageId}\" not found in ${ctx.scope} marketplace.lock`);\n }\n }\n\n // -------------------------------------------------------------------------\n // List / GetEntry (MarketplaceServiceAPI)\n // -------------------------------------------------------------------------\n\n async list(\n ctx: QueryScopeContext,\n filter?: { kind?: EntityKind },\n ): Promise<ScopedMarketplaceEntry[]> {\n const targets = resolveQueryRoots(this.roots, ctx);\n\n // Collect per-scope entries. For 'all' we later apply platform-wins.\n const perScope: Array<{ scope: MarketplaceScope; entries: MarketplaceEntryWithId[] }> = [];\n for (const { scope, root } of targets) {\n const diag = new DiagnosticCollector();\n const lock = await readMarketplaceLock(root, diag);\n if (!lock) {\n perScope.push({ scope, entries: [] });\n continue;\n }\n const entries = Object.entries(lock.installed).map(([id, entry]) => ({ ...entry, id }));\n perScope.push({ scope, entries });\n }\n\n const merged = mergeScopedEntries(perScope);\n const filtered = filter?.kind\n ? merged.entries.filter(e => e.primaryKind === filter.kind)\n : merged.entries;\n return filtered;\n }\n\n async getEntry(ctx: ScopeContext, packageId: string): Promise<MarketplaceEntry | null> {\n const scopeRoot = resolveScopeRoot(this.roots, ctx);\n const diag = new DiagnosticCollector();\n const lock = await readMarketplaceLock(scopeRoot, diag);\n return lock?.installed[packageId] ?? null;\n }\n\n // -------------------------------------------------------------------------\n // Sync (scan workspace → populate lock from config-driven globs)\n // -------------------------------------------------------------------------\n\n /**\n * Scan workspace for plugins and adapters using glob patterns.\n * Existing entries are preserved (not overwritten).\n * Patterns come from kb.config.json marketplace.sync.include.\n *\n * Sync is scope-bound: globs resolve against the scope root and results go\n * into that scope's lock. Adapter discovery in `project` scope is refused\n * with a clear error to preserve the adapters-are-platform-only invariant.\n */\n async sync(\n ctx: ScopeContext,\n opts: {\n include: string[];\n exclude?: string[];\n autoEnable?: boolean;\n },\n ): Promise<SyncResult> {\n const scopeRoot = resolveScopeRoot(this.roots, ctx);\n const autoEnable = opts.autoEnable ?? false;\n const diag = new DiagnosticCollector();\n const lock = await readMarketplaceLock(scopeRoot, diag) ?? createEmptyLock();\n const existingIds = new Set(Object.keys(lock.installed));\n\n const added: SyncResult['added'] = [];\n const skipped: SyncResult['skipped'] = [];\n\n const includePatterns = opts.include.map(p => path.join(p, 'package.json'));\n const excludePatterns = opts.exclude ?? [];\n\n const packageJsonPaths = await glob(includePatterns, {\n cwd: scopeRoot,\n ignore: excludePatterns,\n absolute: false,\n });\n\n for (const relPkgJson of packageJsonPaths) {\n const pkgDir = path.resolve(scopeRoot, path.dirname(relPkgJson));\n await this._syncPackage(ctx.scope, scopeRoot, pkgDir, relPkgJson, existingIds, autoEnable, lock, added, skipped);\n }\n\n await writeMarketplaceLock(scopeRoot, lock);\n\n return { added, skipped, total: Object.keys(lock.installed).length };\n }\n\n private async _syncPackage(\n scope: MarketplaceScope,\n scopeRoot: string,\n pkgDir: string,\n _relPkgJson: string,\n existingIds: Set<string>,\n autoEnable: boolean,\n lock: MarketplaceLock,\n added: SyncResult['added'],\n skipped: SyncResult['skipped'],\n ): Promise<void> {\n let pkgName: string;\n let pkgVersion: string;\n try {\n const pkgJson = JSON.parse(await fs.readFile(path.join(pkgDir, 'package.json'), 'utf-8'));\n pkgName = pkgJson.name;\n pkgVersion = pkgJson.version ?? '0.0.0';\n if (!pkgName) { return; }\n } catch {\n return;\n }\n\n if (existingIds.has(pkgName)) {\n skipped.push({ id: pkgName, reason: 'already in lock' });\n return;\n }\n\n let detected = false;\n for (const strategy of this.strategies.values()) {\n const kind = await strategy.detectKind(pkgDir);\n if (kind) { detected = true; break; }\n }\n if (!detected) { return; }\n\n const primaryKind = await this.detectKind(pkgDir);\n\n // Adapters can only live in platform scope.\n if (scope === 'project' && primaryKind === 'adapter') {\n skipped.push({ id: pkgName, reason: 'adapter not allowed in project scope' });\n return;\n }\n\n const strategy = this.strategies.get(primaryKind);\n const provides = strategy ? await strategy.extractProvides(pkgDir) : [primaryKind];\n const integrity = await computeIntegrity(pkgDir);\n\n // Use manifest ID as lock key if the strategy can resolve it.\n // This keeps discovery working even when package.json name differs from manifest.id\n // (e.g. after folder renames like cli/ → entry/).\n const resolvedId = (strategy?.resolveId ? await strategy.resolveId(pkgDir) : null) ?? pkgName;\n\n if (existingIds.has(resolvedId) && resolvedId !== pkgName) {\n skipped.push({ id: resolvedId, reason: 'already in lock' });\n return;\n }\n\n const entry = createMarketplaceEntry({\n version: pkgVersion,\n integrity,\n resolvedPath: relativeToRoot(scopeRoot, pkgDir),\n source: 'local',\n primaryKind,\n provides,\n });\n\n if (!autoEnable) { entry.enabled = false; }\n\n lock.installed[resolvedId] = entry;\n added.push({ id: resolvedId, primaryKind, version: pkgVersion });\n }\n\n // -------------------------------------------------------------------------\n // Doctor\n // -------------------------------------------------------------------------\n\n async doctor(ctx: ScopeContext): Promise<DoctorReport> {\n const scopeRoot = resolveScopeRoot(this.roots, ctx);\n const diag = new DiagnosticCollector();\n const lock = await readMarketplaceLock(scopeRoot, diag);\n const issues: DoctorIssue[] = [];\n\n if (!lock) {\n return { ok: true, total: 0, issues: [{ severity: 'info', packageId: '', message: 'No marketplace.lock found' }] };\n }\n\n const entries = Object.entries(lock.installed);\n\n for (const [id, entry] of entries) {\n const pkgRoot = path.resolve(scopeRoot, entry.resolvedPath);\n\n try {\n await fs.access(pkgRoot);\n } catch {\n issues.push({\n severity: 'error',\n packageId: id,\n message: `Package directory not found: ${pkgRoot}`,\n remediation: `Run \"kb marketplace install ${id}\" to restore`,\n });\n continue;\n }\n\n if (entry.integrity) {\n const computed = await computeIntegrity(pkgRoot);\n if (computed && computed !== entry.integrity) {\n issues.push({\n severity: 'warning',\n packageId: id,\n message: `Integrity mismatch: expected ${entry.integrity}, got ${computed}`,\n remediation: `Re-install: kb marketplace install ${id}`,\n });\n }\n }\n\n if (!entry.signature) {\n issues.push({\n severity: 'info',\n packageId: id,\n message: 'Package is not signed',\n remediation: 'Publish through the official marketplace to get a platform signature',\n });\n }\n }\n\n return {\n ok: issues.filter(i => i.severity === 'error').length === 0,\n total: entries.length,\n issues,\n };\n }\n\n // -------------------------------------------------------------------------\n // Private\n // -------------------------------------------------------------------------\n\n private async detectKind(packageRoot: string): Promise<EntityKind> {\n for (const strategy of this.strategies.values()) {\n const kind = await strategy.detectKind(packageRoot);\n if (kind) { return kind; }\n }\n return 'plugin';\n }\n\n /**\n * Hard guard: adapters may only be installed/linked in platform scope.\n * Lives in one place so adapter-scope policy is not duplicated across\n * `link`, `install`, and `sync`.\n */\n private assertScopeAllowsKind(scope: MarketplaceScope, kind: EntityKind): void {\n if (scope === 'project' && kind === 'adapter') {\n throw new AdapterScopeError(\n 'Adapters can only be installed in platform scope. ' +\n 'Use --scope platform or install globally via the platform marketplace.',\n );\n }\n }\n\n private async cacheManifest(\n scopeRoot: string,\n packageId: string,\n packageRoot: string,\n primaryKind: EntityKind,\n integrity: string,\n ): Promise<void> {\n try {\n if (primaryKind === 'plugin') {\n const diag = new DiagnosticCollector();\n const manifest = await loadManifest(packageRoot, diag);\n if (manifest) {\n await setCacheEntry(scopeRoot, packageId, {\n manifestType: 'plugin',\n manifest,\n cachedAt: new Date().toISOString(),\n integrity,\n });\n }\n } else if (primaryKind === 'adapter') {\n const distPath = path.join(packageRoot, 'dist', 'index.js');\n const mod = await import(pathToFileURL(distPath).href);\n if (mod.manifest) {\n await setCacheEntry(scopeRoot, packageId, {\n manifestType: 'adapter',\n manifest: mod.manifest,\n cachedAt: new Date().toISOString(),\n integrity,\n });\n }\n }\n } catch (err) {\n console.warn(`[marketplace] Failed to cache manifest for \"${packageId}\": ${(err as Error).message}`);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport class AdapterScopeError extends Error {\n readonly code = 'MARKETPLACE_ADAPTER_PROJECT_SCOPE';\n constructor(message: string) {\n super(message);\n this.name = 'AdapterScopeError';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction relativeToRoot(root: string, absPath: string): string {\n const rel = path.relative(root, absPath);\n return rel.startsWith('.') ? rel : `./${rel}`;\n}\n\nfunction isPathInside(parent: string, child: string): boolean {\n const rel = path.relative(path.resolve(parent), path.resolve(child));\n return !rel.startsWith('..') && !path.isAbsolute(rel);\n}\n\nasync function computeIntegrity(packageRoot: string): Promise<string> {\n try {\n const content = await fs.readFile(path.join(packageRoot, 'package.json'));\n return `sha256-${crypto.createHash('sha256').update(content).digest('base64')}`;\n } catch {\n return '';\n }\n}\n\n/**\n * Merge per-scope entries with platform-wins precedence.\n *\n * For a given package id present in both platform and project, the platform\n * entry is kept and a diagnostic is emitted so the caller can surface the\n * conflict.\n */\nexport function mergeScopedEntries(\n perScope: Array<{ scope: MarketplaceScope; entries: MarketplaceEntryWithId[] }>,\n): { entries: ScopedMarketplaceEntry[]; diagnostics: MarketplaceDiagnostic[] } {\n const out = new Map<string, ScopedMarketplaceEntry>();\n const diagnostics: MarketplaceDiagnostic[] = [];\n\n // Process platform first so platform entries land first and project\n // duplicates are rejected with a diagnostic.\n const ordered = [...perScope].sort((a, b) => {\n if (a.scope === b.scope) { return 0; }\n return a.scope === 'platform' ? -1 : 1;\n });\n\n for (const { scope, entries } of ordered) {\n for (const e of entries) {\n const existing = out.get(e.id);\n if (existing) {\n // platform-wins: ignore subsequent duplicates, emit a diagnostic.\n diagnostics.push({\n code: 'MARKETPLACE_SCOPE_COLLISION',\n message: `Package \"${e.id}\" exists in both platform and ${scope} scopes — platform wins.`,\n packageId: e.id,\n scope,\n });\n continue;\n }\n out.set(e.id, { ...e, scope });\n }\n }\n\n return { entries: Array.from(out.values()), diagnostics };\n}\n"]}
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "dependencies": {
3
3
  "glob": "^11.0.0",
4
- "@kb-labs/plugin-contracts": "2.31.0",
5
- "@kb-labs/core-discovery": "2.31.0",
6
- "@kb-labs/core-platform": "2.31.0",
7
- "@kb-labs/marketplace-contracts": "2.31.0"
4
+ "@kb-labs/core-discovery": "2.32.0",
5
+ "@kb-labs/marketplace-contracts": "2.32.0",
6
+ "@kb-labs/core-platform": "2.32.0",
7
+ "@kb-labs/plugin-contracts": "2.32.0"
8
8
  },
9
9
  "description": "Marketplace service — unified install/uninstall/enable/disable for all entity types",
10
10
  "devDependencies": {
11
11
  "tsup": "^8.5.0",
12
12
  "typescript": "^5",
13
13
  "vitest": "^3.2.4",
14
- "@kb-labs/devkit": "2.31.0"
14
+ "@kb-labs/devkit": "2.32.0"
15
15
  },
16
16
  "engines": {
17
17
  "node": ">=20.0.0",
@@ -33,7 +33,7 @@
33
33
  "sideEffects": false,
34
34
  "type": "module",
35
35
  "types": "./dist/index.d.ts",
36
- "version": "2.31.0",
36
+ "version": "2.32.0",
37
37
  "scripts": {
38
38
  "build": "tsup",
39
39
  "clean": "rimraf dist",