@kb-labs/cli-commands 2.5.0 → 2.9.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.
@@ -208,6 +208,12 @@ declare const __test: {
208
208
  ensureManifestLoader: typeof ensureManifestLoader;
209
209
  createManifestV3Loader: typeof createManifestV3Loader;
210
210
  };
211
+ /**
212
+ * Reset the in-process discovery cache.
213
+ * Call this after clearing the disk cache so the next discoverManifests() call
214
+ * in the same process performs a fresh scan rather than serving stale results.
215
+ */
216
+ declare function resetInProcCache(): void;
211
217
  /**
212
218
  * Main discovery function — discovers command manifests from workspace,
213
219
  * current package, and `node_modules`.
@@ -231,4 +237,4 @@ declare function discoverManifests(cwd: string, noCache?: boolean, options?: {
231
237
  */
232
238
  declare function discoverManifestsByNamespace(cwd: string, namespace: string, noCache?: boolean): Promise<DiscoveryResult[]>;
233
239
 
234
- export { type AvailabilityCheck as A, type CommandGroup as C, type DiscoveryResult as D, type FlagDefinition as F, type GlobalFlags as G, type ProductGroup as P, type RegisteredCommand as R, __test as _, type Command as a, findCommandWithType as b, type CommandType as c, type CommandLookupResult as d, discoverManifestsByNamespace as e, findCommand as f, discoverManifests as g, type CommandManifest as h, type CommandModule as i, type PackageCacheEntry as j, type CacheFile as k, registry as r };
240
+ export { type AvailabilityCheck as A, type CommandGroup as C, type DiscoveryResult as D, type FlagDefinition as F, type GlobalFlags as G, type ProductGroup as P, type RegisteredCommand as R, __test as _, type Command as a, type CacheFile as b, type CommandLookupResult as c, type CommandManifest as d, type CommandModule as e, type CommandType as f, type PackageCacheEntry as g, discoverManifests as h, discoverManifestsByNamespace as i, findCommand as j, findCommandWithType as k, resetInProcCache as l, registry as r };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CommandGroup, P as ProductGroup, a as Command, R as RegisteredCommand } from './discover-8_R7njIS.js';
2
- export { A as AvailabilityCheck, k as CacheFile, d as CommandLookupResult, h as CommandManifest, i as CommandModule, c as CommandType, D as DiscoveryResult, F as FlagDefinition, G as GlobalFlags, j as PackageCacheEntry, g as discoverManifests, e as discoverManifestsByNamespace, f as findCommand, b as findCommandWithType, r as registry } from './discover-8_R7njIS.js';
1
+ import { C as CommandGroup, P as ProductGroup, a as Command, R as RegisteredCommand } from './discover-BY7VE2Hf.js';
2
+ export { A as AvailabilityCheck, b as CacheFile, c as CommandLookupResult, d as CommandManifest, e as CommandModule, f as CommandType, D as DiscoveryResult, F as FlagDefinition, G as GlobalFlags, g as PackageCacheEntry, h as discoverManifests, i as discoverManifestsByNamespace, j as findCommand, k as findCommandWithType, r as registry } from './discover-BY7VE2Hf.js';
3
3
  import { ILogger } from '@kb-labs/core-platform';
4
4
  export { TimingTracker } from '@kb-labs/shared-cli-ui';
5
5
  import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import { glob } from 'glob';
10
10
  import { defineSystemCommand, defineSystemCommandGroup } from '@kb-labs/shared-command-kit';
11
11
  import { createRegistry, formatDiagnosticReport } from '@kb-labs/core-registry';
12
12
  import { readMarketplaceLock, DiagnosticCollector } from '@kb-labs/core-discovery';
13
- import { platform } from '@kb-labs/core-runtime';
13
+ import { platform, platformSync } from '@kb-labs/core-runtime';
14
14
  import { CredentialsManager } from '@kb-labs/cli-runtime/gateway';
15
15
  import Ajv from 'ajv';
16
16
  import { createRequire } from 'module';
@@ -167,7 +167,8 @@ var discover_exports = {};
167
167
  __export(discover_exports, {
168
168
  __test: () => __test,
169
169
  discoverManifests: () => discoverManifests,
170
- discoverManifestsByNamespace: () => discoverManifestsByNamespace
170
+ discoverManifestsByNamespace: () => discoverManifestsByNamespace,
171
+ resetInProcCache: () => resetInProcCache
171
172
  });
172
173
  function createManifestV3Loader(commandId) {
173
174
  return async () => {
@@ -207,8 +208,12 @@ function createUnavailableManifest(pkgName, error) {
207
208
  throw new Error(`Cannot load ${pkgName} CLI manifest. ${rawMsg}`);
208
209
  }
209
210
  };
211
+ manifest._synthetic = true;
210
212
  return manifest;
211
213
  }
214
+ function resetInProcCache() {
215
+ inProcDiscoveryCache = null;
216
+ }
212
217
  async function computeManifestHash(manifestPath) {
213
218
  try {
214
219
  const content = await promises.readFile(manifestPath, "utf8");
@@ -551,7 +556,7 @@ async function discoverNodeModules(cwd) {
551
556
  const packageInfos = [];
552
557
  const scanPromises = [];
553
558
  for (const entry of entries) {
554
- if (!entry.isDirectory()) {
559
+ if (!entry.isDirectory() && !entry.isSymbolicLink()) {
555
560
  continue;
556
561
  }
557
562
  const scanEntry = async () => {
@@ -561,7 +566,7 @@ async function discoverNodeModules(cwd) {
561
566
  const scopeDir = path.join(nmDir, entry.name);
562
567
  try {
563
568
  const scopedDirs = await promises.readdir(scopeDir, { withFileTypes: true });
564
- for (const scopedEntry of scopedDirs.filter((d) => d.isDirectory())) {
569
+ for (const scopedEntry of scopedDirs.filter((d) => d.isDirectory() || d.isSymbolicLink())) {
565
570
  pkgRoot = path.join(scopeDir, scopedEntry.name);
566
571
  pkg = await readPackageJson(path.join(pkgRoot, PACKAGE_JSON));
567
572
  if (!pkg) {
@@ -791,6 +796,11 @@ async function saveCache(cwd, results) {
791
796
  const now = Date.now();
792
797
  const stateHasher = createHash("sha256");
793
798
  for (const result of results) {
799
+ const allSynthetic = result.manifests.length > 0 && result.manifests.every((m) => m._synthetic === true);
800
+ if (allSynthetic) {
801
+ log("debug", `[plugins][cache] Skipping synthetic unavailable manifest for ${result.packageName}`);
802
+ continue;
803
+ }
794
804
  try {
795
805
  const manifestHash = await computeManifestHash(result.manifestPath);
796
806
  const pkgJsonPath = path.join(result.pkgRoot.split("/").join(path.sep), PACKAGE_JSON);
@@ -982,6 +992,7 @@ var init_discover = __esm({
982
992
  __test = {
983
993
  ensureManifestLoader,
984
994
  createManifestV3Loader
995
+ // resetInProcCache is exported directly (not via __test) since it's part of the public API
985
996
  };
986
997
  PACKAGE_JSON = "package.json";
987
998
  MANIFEST_LOAD_TIMEOUT = 1500;
@@ -1766,6 +1777,9 @@ var registryDiagnostics = defineSystemCommand({
1766
1777
  }
1767
1778
  }
1768
1779
  });
1780
+
1781
+ // src/registry/plugins-state.ts
1782
+ init_discover();
1769
1783
  async function clearCache(cwd, options) {
1770
1784
  const cleared = [];
1771
1785
  const cacheDir = path.join(cwd, ".kb", "cache");
@@ -1794,6 +1808,7 @@ async function clearCache(cwd, options) {
1794
1808
  }
1795
1809
  } catch {
1796
1810
  }
1811
+ resetInProcCache();
1797
1812
  const modulesCleared = [];
1798
1813
  if (options?.deep) {
1799
1814
  try {
@@ -3142,6 +3157,146 @@ var authCreateServiceAccount = defineSystemCommand({
3142
3157
  return { ok: true, clientId: data.clientId, clientSecret: data.clientSecret, hostId: data.hostId };
3143
3158
  }
3144
3159
  });
3160
+ function isMode(value) {
3161
+ return value === "validate" || value === "reconcile" || value === "auto";
3162
+ }
3163
+ var platformSyncCommand = defineSystemCommand({
3164
+ name: "provision",
3165
+ description: "Reconcile .kb/marketplace.lock with installed adapters & plugins",
3166
+ longDescription: "Reads .kb/marketplace.lock as the declarative source of truth for which adapters and plugins this installation needs, and makes the filesystem match. In monorepo/dev mode it only validates. In prod/Docker build mode it installs missing marketplace packages via pnpm.",
3167
+ category: "platform",
3168
+ examples: generateExamples("platform provision", "kb", [
3169
+ { flags: {} },
3170
+ { flags: { mode: "validate" } },
3171
+ { flags: { mode: "reconcile", json: true } },
3172
+ { flags: { "dry-run": true } }
3173
+ ]),
3174
+ flags: {
3175
+ json: { type: "boolean", description: "Output machine-readable JSON" },
3176
+ mode: {
3177
+ type: "string",
3178
+ description: "Sync mode: validate | reconcile | auto (default: auto)"
3179
+ },
3180
+ "dry-run": {
3181
+ type: "boolean",
3182
+ description: "Never install, fail on drift"
3183
+ },
3184
+ root: {
3185
+ type: "string",
3186
+ description: "Workspace root (default: current working directory)"
3187
+ }
3188
+ },
3189
+ analytics: {
3190
+ command: "platform.sync",
3191
+ startEvent: "PLATFORM_SYNC_STARTED",
3192
+ finishEvent: "PLATFORM_SYNC_FINISHED"
3193
+ },
3194
+ async handler(ctx, _argv, flags) {
3195
+ const cwd = getContextCwd(ctx);
3196
+ const root = flags.root ?? cwd;
3197
+ const modeFlag = flags.mode;
3198
+ const mode = isMode(modeFlag) ? modeFlag : "auto";
3199
+ const dryRun = Boolean(flags["dry-run"]);
3200
+ const logger = ctx.platform?.logger;
3201
+ logger?.info("platform sync started", { root, mode, dryRun });
3202
+ const result = await platformSync({
3203
+ root,
3204
+ mode,
3205
+ dryRun,
3206
+ logger
3207
+ });
3208
+ logger?.info("platform sync finished", {
3209
+ ok: result.ok,
3210
+ mode: result.mode,
3211
+ checked: result.checked,
3212
+ missing: result.missing.length,
3213
+ mismatched: result.mismatched.length,
3214
+ installed: result.installed.length,
3215
+ errors: result.errors.length
3216
+ });
3217
+ return {
3218
+ ok: result.ok,
3219
+ status: result.ok ? "success" : "error",
3220
+ sync: result
3221
+ };
3222
+ },
3223
+ formatter(result, ctx, flags) {
3224
+ if (flags.json) {
3225
+ console.log(JSON.stringify(result.sync ?? result, null, 2));
3226
+ return;
3227
+ }
3228
+ const sync = result.sync;
3229
+ if (!sync) {
3230
+ ctx.ui.error("Platform Sync", {
3231
+ sections: [{ header: "Error", items: [result.error ?? "Unknown error"] }]
3232
+ });
3233
+ return;
3234
+ }
3235
+ const summary = [
3236
+ `Mode: ${sync.mode}${sync.mode !== flags.mode && flags.mode !== "auto" ? " (auto-detected)" : ""}`,
3237
+ `Checked: ${sync.checked}`
3238
+ ];
3239
+ if (sync.lockMissing) {
3240
+ summary.push("Lock: not found (nothing to reconcile)");
3241
+ }
3242
+ if (sync.installed.length) {
3243
+ summary.push(`Installed: ${sync.installed.length}`);
3244
+ }
3245
+ if (sync.missing.length) {
3246
+ summary.push(`Missing: ${sync.missing.length}`);
3247
+ }
3248
+ if (sync.mismatched.length) {
3249
+ summary.push(`Integrity mismatch: ${sync.mismatched.length}`);
3250
+ }
3251
+ if (sync.errors.length) {
3252
+ summary.push(`Errors: ${sync.errors.length}`);
3253
+ }
3254
+ const sections = [
3255
+ { header: "Summary", items: summary }
3256
+ ];
3257
+ if (sync.installed.length) {
3258
+ sections.push({
3259
+ header: "Installed",
3260
+ items: sync.installed.map((id) => `\u2022 ${id}`)
3261
+ });
3262
+ }
3263
+ if (sync.missing.length) {
3264
+ sections.push({
3265
+ header: "Missing",
3266
+ items: sync.missing.map((id) => `\u2022 ${id}`)
3267
+ });
3268
+ }
3269
+ if (sync.mismatched.length) {
3270
+ sections.push({
3271
+ header: "Integrity mismatch",
3272
+ items: sync.mismatched.map((id) => `\u2022 ${id}`)
3273
+ });
3274
+ }
3275
+ if (sync.errors.length) {
3276
+ sections.push({
3277
+ header: "Errors",
3278
+ items: sync.errors.map((e) => `\u2022 ${e.packageId}: ${e.message}`)
3279
+ });
3280
+ }
3281
+ const nextSteps = [];
3282
+ if (!sync.ok) {
3283
+ if (sync.missing.length && sync.mode === "validate") {
3284
+ nextSteps.push("kb platform provision --mode reconcile Install missing packages");
3285
+ }
3286
+ if (sync.mismatched.length) {
3287
+ nextSteps.push("kb marketplace install <pkg> Re-install mismatched packages");
3288
+ }
3289
+ }
3290
+ if (nextSteps.length) {
3291
+ sections.push({ header: "Next Steps", items: nextSteps });
3292
+ }
3293
+ if (sync.ok) {
3294
+ ctx.ui.success("Platform Sync", { sections });
3295
+ } else {
3296
+ ctx.ui.error("Platform Sync", { sections });
3297
+ }
3298
+ }
3299
+ });
3145
3300
 
3146
3301
  // src/commands/system/groups.ts
3147
3302
  var infoGroup = defineSystemCommandGroup("info", "System information commands", [
@@ -3174,6 +3329,9 @@ var authGroup = defineSystemCommandGroup("auth", "Gateway authentication command
3174
3329
  authStatus,
3175
3330
  authCreateServiceAccount
3176
3331
  ]);
3332
+ var platformGroup = defineSystemCommandGroup("platform", "Platform lifecycle commands", [
3333
+ platformSyncCommand
3334
+ ]);
3177
3335
  var req = createRequire(import.meta.url);
3178
3336
  var __filename$1 = fileURLToPath(import.meta.url);
3179
3337
  var __dirname$1 = path.dirname(__filename$1);
@@ -3657,6 +3815,7 @@ async function registerBuiltinCommands(input = {}) {
3657
3815
  registry.registerGroup(docsGroup);
3658
3816
  registry.registerGroup(logsGroup);
3659
3817
  registry.registerGroup(authGroup);
3818
+ registry.registerGroup(platformGroup);
3660
3819
  try {
3661
3820
  const cwd = getContextCwd({ cwd: input.cwd });
3662
3821
  const env = input.env ?? process.env;