agents-inc 0.172.0 → 0.173.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/{chunk-MBIOZ5LW.js → chunk-2RTBSLSR.js} +2 -2
  3. package/dist/{chunk-255DGUCH.js → chunk-3N4FSTVX.js} +12 -6
  4. package/dist/{chunk-255DGUCH.js.map → chunk-3N4FSTVX.js.map} +1 -1
  5. package/dist/{chunk-5MGRHS2G.js → chunk-AARQBW5L.js} +22 -12
  6. package/dist/chunk-AARQBW5L.js.map +1 -0
  7. package/dist/{chunk-NISWBQNS.js → chunk-BRZA7ZCX.js} +3 -3
  8. package/dist/{chunk-LUKDDHSI.js → chunk-EHJIQDXR.js} +2 -2
  9. package/dist/{chunk-MOL2J5HS.js → chunk-F437ICEG.js} +2 -2
  10. package/dist/{chunk-KCLBLK3F.js → chunk-ITQF35UQ.js} +3 -3
  11. package/dist/{chunk-7ZOWSCAO.js → chunk-LJQXQTFC.js} +2 -2
  12. package/dist/{chunk-6LUTY35Q.js → chunk-Q4UNHVPX.js} +4 -4
  13. package/dist/{chunk-33JICQD5.js → chunk-Q6WRR4BN.js} +4 -5
  14. package/dist/{chunk-33JICQD5.js.map → chunk-Q6WRR4BN.js.map} +1 -1
  15. package/dist/{chunk-5PPB6HT6.js → chunk-SPQSNZMM.js} +2 -2
  16. package/dist/{chunk-Y23MP2OC.js → chunk-VR6QTK5Z.js} +3 -3
  17. package/dist/{chunk-6CRA46YO.js → chunk-VSPC74SS.js} +41 -19
  18. package/dist/chunk-VSPC74SS.js.map +1 -0
  19. package/dist/{chunk-VILFCMRN.js → chunk-WVFBBZEP.js} +252 -102
  20. package/dist/chunk-WVFBBZEP.js.map +1 -0
  21. package/dist/commands/build/marketplace.js +2 -2
  22. package/dist/commands/build/plugins.js +4 -4
  23. package/dist/commands/compile.js +10 -10
  24. package/dist/commands/doctor.js +31 -13
  25. package/dist/commands/doctor.js.map +1 -1
  26. package/dist/commands/edit.js +13 -13
  27. package/dist/commands/eject.js +23 -28
  28. package/dist/commands/eject.js.map +1 -1
  29. package/dist/commands/init.js +12 -12
  30. package/dist/commands/list.js +3 -3
  31. package/dist/commands/new/marketplace.js +2 -2
  32. package/dist/commands/search.js +7 -7
  33. package/dist/commands/share.js +6 -6
  34. package/dist/commands/uninstall.js +45 -41
  35. package/dist/commands/uninstall.js.map +1 -1
  36. package/dist/commands/update.js +4 -4
  37. package/dist/components/common/summary-panel.js +1 -1
  38. package/dist/hooks/init.js +29 -20
  39. package/dist/hooks/init.js.map +1 -1
  40. package/dist/load-agent-defs-E67DSYTN.js +14 -0
  41. package/dist/{recompile-project-agents-5A44NJRD.js → recompile-project-agents-6G6M2RS6.js} +6 -6
  42. package/dist/{source-loader-LQNRI5UZ.js → source-loader-W7XCNKNA.js} +2 -2
  43. package/package.json +1 -1
  44. package/dist/chunk-5MGRHS2G.js.map +0 -1
  45. package/dist/chunk-6CRA46YO.js.map +0 -1
  46. package/dist/chunk-VILFCMRN.js.map +0 -1
  47. package/dist/load-agent-defs-54VIKN4T.js +0 -14
  48. /package/dist/{chunk-MBIOZ5LW.js.map → chunk-2RTBSLSR.js.map} +0 -0
  49. /package/dist/{chunk-NISWBQNS.js.map → chunk-BRZA7ZCX.js.map} +0 -0
  50. /package/dist/{chunk-LUKDDHSI.js.map → chunk-EHJIQDXR.js.map} +0 -0
  51. /package/dist/{chunk-MOL2J5HS.js.map → chunk-F437ICEG.js.map} +0 -0
  52. /package/dist/{chunk-KCLBLK3F.js.map → chunk-ITQF35UQ.js.map} +0 -0
  53. /package/dist/{chunk-7ZOWSCAO.js.map → chunk-LJQXQTFC.js.map} +0 -0
  54. /package/dist/{chunk-6LUTY35Q.js.map → chunk-Q4UNHVPX.js.map} +0 -0
  55. /package/dist/{chunk-5PPB6HT6.js.map → chunk-SPQSNZMM.js.map} +0 -0
  56. /package/dist/{chunk-Y23MP2OC.js.map → chunk-VR6QTK5Z.js.map} +0 -0
  57. /package/dist/{load-agent-defs-54VIKN4T.js.map → load-agent-defs-E67DSYTN.js.map} +0 -0
  58. /package/dist/{recompile-project-agents-5A44NJRD.js.map → recompile-project-agents-6G6M2RS6.js.map} +0 -0
  59. /package/dist/{source-loader-LQNRI5UZ.js.map → source-loader-W7XCNKNA.js.map} +0 -0
@@ -744,8 +744,8 @@ async function fileExists(filePath) {
744
744
  }
745
745
  async function directoryExists2(dirPath) {
746
746
  try {
747
- const stat = await fs3.stat(dirPath);
748
- return stat.isDirectory();
747
+ const stat2 = await fs3.stat(dirPath);
748
+ return stat2.isDirectory();
749
749
  } catch {
750
750
  return false;
751
751
  }
@@ -953,6 +953,8 @@ var INFO_MESSAGES = {
953
953
  CONFIG_TYPES_REFRESHED: `Refreshed ${STANDARD_FILES.CONFIG_TYPES_TS}`,
954
954
  EJECTED_SKILLS_USER_OWNED: `Ejected skills are yours to own \u2014 '${CLI_INVOKE_COMMAND} update' does not change them.`,
955
955
  NO_PLUGIN_MARKETPLACES: "No plugin marketplaces are configured \u2014 nothing to refresh.",
956
+ /** Under doctor's marketplace row, when its download replaced a saved copy whose files differed. */
957
+ SAVED_COPY_REPLACED: "The saved copy differed from the marketplace and has been replaced",
956
958
  /** Printed under the destination already named, so it names files only. */
957
959
  AGENT_PARTIALS_CUSTOMIZABLE: `Each sub-agent directory there holds ${AGENT_PARTIAL_FILES.join(", ")} \u2014 edit those to customize that sub-agent.`
958
960
  };
@@ -2549,14 +2551,12 @@ async function loadConfig(configPath, schema) {
2549
2551
  if (declaresNoDefaultExport(namespace)) {
2550
2552
  throw new ConfigDefaultExportError(configPath);
2551
2553
  }
2552
- if (schema) {
2553
- const result = schema.safeParse(raw);
2554
- if (!result.success) {
2555
- throw new ConfigSchemaError(configPath, formatZodIssues(result.error.issues));
2556
- }
2557
- return result.data;
2554
+ if (!schema) return raw;
2555
+ const result = schema.safeParse(raw);
2556
+ if (!result.success) {
2557
+ throw new ConfigSchemaError(configPath, formatZodIssues(result.error.issues));
2558
2558
  }
2559
- return raw;
2559
+ return result.data;
2560
2560
  }
2561
2561
  async function importConfigModule(configPath) {
2562
2562
  try {
@@ -3177,7 +3177,16 @@ function brokenUnionLayout(members, bodyIndent) {
3177
3177
  }
3178
3178
  function renderUnionBody(members, layout, bodyIndent) {
3179
3179
  const padding = spaces(bodyIndent);
3180
- return layout === "indented" ? `${padding}${flatUnion(members)}` : members.map((member) => `${padding}| ${member}`).join("\n");
3180
+ switch (layout) {
3181
+ case "indented":
3182
+ return `${padding}${flatUnion(members)}`;
3183
+ case "stacked":
3184
+ return members.map((member) => `${padding}| ${member}`).join("\n");
3185
+ default: {
3186
+ const _exhaustive = layout;
3187
+ return _exhaustive;
3188
+ }
3189
+ }
3181
3190
  }
3182
3191
  function flatUnion(members) {
3183
3192
  return members.join(" | ");
@@ -3225,9 +3234,18 @@ function renderArray(entries, position) {
3225
3234
  return ["[", ...lines, `${spaces(position.indent)}]`].join("\n");
3226
3235
  }
3227
3236
  function renderEntryLine(entry, indent) {
3228
- if (entry.kind === "comment") return `${spaces(indent)}// ${entry.text}`;
3229
- if (entry.kind === "source") return `${spaces(indent)}${entry.source},`;
3230
- return renderValueLine(entry.value, { indent, prefix: "", suffix: "," });
3237
+ switch (entry.kind) {
3238
+ case "comment":
3239
+ return `${spaces(indent)}// ${entry.text}`;
3240
+ case "source":
3241
+ return `${spaces(indent)}${entry.source},`;
3242
+ case "value":
3243
+ return renderValueLine(entry.value, { indent, prefix: "", suffix: "," });
3244
+ default: {
3245
+ const _exhaustive = entry;
3246
+ return _exhaustive;
3247
+ }
3248
+ }
3231
3249
  }
3232
3250
  function renderRecord(record, position) {
3233
3251
  const properties = Object.entries(record);
@@ -3247,11 +3265,27 @@ function propertyPosition(key, indent) {
3247
3265
  function flatArray(entries) {
3248
3266
  const items = [];
3249
3267
  for (const entry of entries) {
3250
- if (entry.kind === "comment") return void 0;
3251
- items.push(entry.kind === "source" ? entry.source : flatValue(entry.value));
3268
+ const item = flatEntry(entry);
3269
+ if (item === void 0) return void 0;
3270
+ items.push(item);
3252
3271
  }
3253
3272
  return flatList(items);
3254
3273
  }
3274
+ function flatEntry(entry) {
3275
+ switch (entry.kind) {
3276
+ // A `//` line cannot fold onto one line.
3277
+ case "comment":
3278
+ return void 0;
3279
+ case "source":
3280
+ return entry.source;
3281
+ case "value":
3282
+ return flatValue(entry.value);
3283
+ default: {
3284
+ const _exhaustive = entry;
3285
+ return _exhaustive;
3286
+ }
3287
+ }
3288
+ }
3255
3289
  function flatValue(value) {
3256
3290
  if (Array.isArray(value)) return flatList(value.map(flatValue));
3257
3291
  if (isKeyedRecord(value)) return flatRecord(value);
@@ -3297,12 +3331,16 @@ var GLOBAL_IDENTITY_FIELDS = [
3297
3331
  ...HAND_WRITTEN_FIELDS,
3298
3332
  "description"
3299
3333
  ];
3300
- var EXTRACTED_FIELDS = /* @__PURE__ */ new Set([
3334
+ var EXTRACTED_FIELDS = [
3301
3335
  "skills",
3302
3336
  "agents",
3303
3337
  "stack",
3304
3338
  "selectedDomains"
3305
- ]);
3339
+ ];
3340
+ var extractedFields = new Set(EXTRACTED_FIELDS);
3341
+ function isExtractedField(key) {
3342
+ return extractedFields.has(key);
3343
+ }
3306
3344
  var CANONICAL_FIELD_ORDER = [
3307
3345
  "name",
3308
3346
  "description",
@@ -3503,11 +3541,21 @@ function generateStandaloneConfig(cleaned) {
3503
3541
  });
3504
3542
  }
3505
3543
  function standaloneExportField(key, value, emitted) {
3506
- if (!EXTRACTED_FIELDS.has(key)) return [renderScalarField(key, value)];
3507
- if (key === "skills") return [` skills${emitted.hasSkills ? "" : ": []"},`];
3508
- if (key === "agents") return [` agents${emitted.hasAgents ? "" : ": []"},`];
3509
- if (key === "stack") return emitted.hasStack ? [` stack,`] : [];
3510
- return [` selectedDomains${emitted.hasSelectedDomains ? "" : ": []"},`];
3544
+ if (!isExtractedField(key)) return [renderScalarField(key, value)];
3545
+ switch (key) {
3546
+ case "skills":
3547
+ return [` skills${emitted.hasSkills ? "" : ": []"},`];
3548
+ case "agents":
3549
+ return [` agents${emitted.hasAgents ? "" : ": []"},`];
3550
+ case "stack":
3551
+ return emitted.hasStack ? [` stack,`] : [];
3552
+ case "selectedDomains":
3553
+ return [` selectedDomains${emitted.hasSelectedDomains ? "" : ": []"},`];
3554
+ default: {
3555
+ const _exhaustive = key;
3556
+ return _exhaustive;
3557
+ }
3558
+ }
3511
3559
  }
3512
3560
  function assembleConfigSource({
3513
3561
  imports,
@@ -3538,7 +3586,7 @@ function buildTypeImports(flags) {
3538
3586
  ].filter((t) => Boolean(t));
3539
3587
  }
3540
3588
  function isCopiedScalarField(key) {
3541
- return !EXTRACTED_FIELDS.has(key) && key !== "name";
3589
+ return !isExtractedField(key) && key !== "name";
3542
3590
  }
3543
3591
  function resolveProjectName(cleaned) {
3544
3592
  return cleaned.name && cleaned.name !== GLOBAL_CONFIG_NAME ? cleaned.name : DEFAULT_PLUGIN_NAME;
@@ -4310,12 +4358,12 @@ async function loadStackById(stackId, configDir, source) {
4310
4358
  );
4311
4359
  return null;
4312
4360
  }
4313
- const defaultStack = defaultStacks.find((s) => s.id === stackId) ?? null;
4314
- if (defaultStack) {
4315
- verbose(`Found default stack: ${defaultStack.name} (${stackId})`);
4316
- } else {
4361
+ const defaultStack = defaultStacks.find((s) => s.id === stackId);
4362
+ if (!defaultStack) {
4317
4363
  verbose(`Stack '${stackId}' not found in the default marketplace or the built-ins`);
4364
+ return null;
4318
4365
  }
4366
+ verbose(`Found default stack: ${defaultStack.name} (${stackId})`);
4319
4367
  return defaultStack;
4320
4368
  }
4321
4369
  function stackNotOfferedMessage(stackId, source) {
@@ -4446,10 +4494,8 @@ async function loadProjectConfig(projectDir) {
4446
4494
  const provider = providerInUse(projectDir);
4447
4495
  const projectResult = await loadProjectConfigFromDir(projectDir, provider);
4448
4496
  if (projectResult) return projectResult;
4449
- if (!isHomeDirectory(projectDir)) {
4450
- return loadProjectConfigFromDir(os5.homedir(), provider);
4451
- }
4452
- return null;
4497
+ if (isHomeDirectory(projectDir)) return null;
4498
+ return loadProjectConfigFromDir(os5.homedir(), provider);
4453
4499
  }
4454
4500
  function validateProjectConfig(config) {
4455
4501
  const result = projectConfigLoaderSchema.safeParse(config);
@@ -5236,10 +5282,13 @@ async function loadPluginSkills(pluginDir) {
5236
5282
  // src/cli/lib/loading/source-fetcher.ts
5237
5283
  import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
5238
5284
  import { createHash as createHash2 } from "crypto";
5239
- import { rename } from "fs/promises";
5285
+ import { readFileSync } from "fs";
5286
+ import { rename, stat } from "fs/promises";
5240
5287
  import { downloadTemplate } from "giget";
5241
5288
  import os8 from "os";
5242
5289
  import path17 from "path";
5290
+ import { isDeepEqual } from "remeda";
5291
+ import { z as z4 } from "zod";
5243
5292
 
5244
5293
  // src/cli/lib/marketplace-generator.ts
5245
5294
  import path16 from "path";
@@ -5375,10 +5424,11 @@ var TarballWithheldError = class extends Error {
5375
5424
  };
5376
5425
  var marketplaceMustAnswer = new AsyncLocalStorage3();
5377
5426
  function askingEachMarketplaceItself(body) {
5378
- return marketplaceMustAnswer.run(true, body);
5427
+ const differingCopiesReplaced = /* @__PURE__ */ new Set();
5428
+ return marketplaceMustAnswer.run(differingCopiesReplaced, () => body(differingCopiesReplaced));
5379
5429
  }
5380
5430
  function mustAnswer() {
5381
- return marketplaceMustAnswer.getStore() === true;
5431
+ return marketplaceMustAnswer.getStore() !== void 0;
5382
5432
  }
5383
5433
  function sanitizeSourceForCache(source) {
5384
5434
  const hash = createHash2("sha256").update(source).digest("hex").slice(0, CACHE_HASH_LENGTH);
@@ -5430,8 +5480,10 @@ function getGigetCacheDir(source) {
5430
5480
  return void 0;
5431
5481
  }
5432
5482
  const templateName = uriMatch.groups.repo.replace("/", "-").replace(/[^\da-z-]/gi, "-");
5433
- const gigetCacheRoot = process.env.XDG_CACHE_HOME ? path17.resolve(process.env.XDG_CACHE_HOME, "giget") : path17.resolve(os8.homedir(), ".cache", "giget");
5434
- return path17.join(gigetCacheRoot, providerName, templateName);
5483
+ return path17.join(gigetCacheRoot(), providerName, templateName);
5484
+ }
5485
+ function gigetCacheRoot() {
5486
+ return process.env.XDG_CACHE_HOME ? path17.resolve(process.env.XDG_CACHE_HOME, "giget") : path17.resolve(os8.homedir(), ".cache", "giget");
5435
5487
  }
5436
5488
  async function clearGigetCache(source) {
5437
5489
  const gigetDir = getGigetCacheDir(source);
@@ -5460,7 +5512,8 @@ async function fetchFromRemoteSource(source, subdir) {
5460
5512
  announceRefetch(verdict);
5461
5513
  if (!mustAnswer()) await discardCachedCopy(cacheDir, source);
5462
5514
  }
5463
- return mustAnswer() ? downloadAnsweredFor(cacheDir, source, fullSource) : downloadFreshCopy(cacheDir, source, fullSource);
5515
+ const differingCopiesReplaced = marketplaceMustAnswer.getStore();
5516
+ return differingCopiesReplaced ? downloadAnsweredFor(cacheDir, source, fullSource, differingCopiesReplaced) : downloadFreshCopy(cacheDir, source, fullSource);
5464
5517
  }
5465
5518
  async function discardCachedCopy(cacheDir, source) {
5466
5519
  await clearGigetCache(source);
@@ -5469,14 +5522,14 @@ async function discardCachedCopy(cacheDir, source) {
5469
5522
  async function downloadFreshCopy(cacheDir, source, fullSource) {
5470
5523
  await ensureDir(path17.dirname(cacheDir));
5471
5524
  try {
5472
- const result = await downloadTemplate(fullSource, {
5525
+ const { result, savedTarball } = await gigetDownload(source, fullSource, {
5473
5526
  dir: cacheDir,
5474
5527
  force: true,
5475
5528
  // Always force when downloading to avoid "already exists" error
5476
5529
  offline: false
5477
5530
  });
5478
5531
  verbose(`Downloaded to: ${result.dir}`);
5479
- await recordFetchedCopy(cacheDir, result);
5532
+ await recordFetchedCopy(cacheDir, result, savedTarball);
5480
5533
  markCopyCurrentForThisRun(cacheDir);
5481
5534
  return {
5482
5535
  path: result.dir,
@@ -5489,18 +5542,24 @@ async function downloadFreshCopy(cacheDir, source, fullSource) {
5489
5542
  }
5490
5543
  }
5491
5544
  var STAGED_DOWNLOAD_SUFFIX = ".download";
5492
- async function downloadAnsweredFor(cacheDir, source, fullSource) {
5545
+ var ONLY_A_SAVED_COPY_CAME_BACK = "the download failed and only a saved copy came back";
5546
+ var SET_ASIDE_SUFFIX = ".set-aside";
5547
+ async function downloadAnsweredFor(cacheDir, source, fullSource, differingCopiesReplaced) {
5493
5548
  const staged = `${cacheDir}${STAGED_DOWNLOAD_SUFFIX}`;
5549
+ const downloadStaged = () => gigetDownload(source, fullSource, {
5550
+ dir: staged,
5551
+ force: true,
5552
+ forceClean: true,
5553
+ offline: false
5554
+ });
5494
5555
  await ensureDir(path17.dirname(cacheDir));
5495
5556
  try {
5496
- const result = await downloadTemplate(fullSource, {
5497
- dir: staged,
5498
- force: true,
5499
- forceClean: true,
5500
- offline: false
5501
- });
5557
+ const { result, savedTarball } = await downloadStaged();
5502
5558
  const record = await askAfterTheDownload(result, source);
5559
+ if (savedTarball) await downloadPast(savedTarball, record, downloadStaged, source);
5560
+ const differed = await savedCopyDiffers(cacheDir, staged);
5503
5561
  await replaceCopy(cacheDir, staged, record);
5562
+ if (differed) differingCopiesReplaced.add(source);
5504
5563
  markCopyCurrentForThisRun(cacheDir);
5505
5564
  return { path: cacheDir, fromCache: false, unreachable: false, source: fullSource };
5506
5565
  } catch (error) {
@@ -5510,11 +5569,96 @@ async function downloadAnsweredFor(cacheDir, source, fullSource) {
5510
5569
  await remove(staged);
5511
5570
  }
5512
5571
  }
5572
+ async function downloadPast(savedTarball, record, download, source) {
5573
+ if (!savedUnder(savedTarball, record)) {
5574
+ throw new MarketplaceUnreachableError(source, ONLY_A_SAVED_COPY_CAME_BACK);
5575
+ }
5576
+ await withTarballSetAside(savedTarball.path, download);
5577
+ }
5578
+ async function withTarballSetAside(tarball, download) {
5579
+ const record = gigetRecordOf(tarball);
5580
+ await rename(record, setAsideOf(record));
5581
+ await rename(tarball, setAsideOf(tarball));
5582
+ try {
5583
+ await download();
5584
+ } catch (error) {
5585
+ await rename(setAsideOf(tarball), tarball);
5586
+ await rename(setAsideOf(record), record);
5587
+ throw error;
5588
+ }
5589
+ await Promise.all([remove(setAsideOf(tarball)), remove(setAsideOf(record))]);
5590
+ }
5591
+ function setAsideOf(file) {
5592
+ return `${file}${SET_ASIDE_SUFFIX}`;
5593
+ }
5594
+ async function savedCopyDiffers(cacheDir, downloaded) {
5595
+ if (!await directoryExists2(cacheDir)) return false;
5596
+ try {
5597
+ return !await holdSameFiles(cacheDir, downloaded);
5598
+ } catch (error) {
5599
+ verbose(`Could not read the saved copy at ${cacheDir}: ${getErrorMessage(error)}`);
5600
+ return true;
5601
+ }
5602
+ }
5603
+ async function holdSameFiles(left, right) {
5604
+ const [leftFiles, rightFiles] = await Promise.all([everyFileIn(left), everyFileIn(right)]);
5605
+ return isDeepEqual(leftFiles, rightFiles) && leftFiles.every((file) => sameBytesAt(file, left, right));
5606
+ }
5607
+ var EVERY_FILE = "**/*";
5608
+ function everyFileIn(dir) {
5609
+ return glob(EVERY_FILE, dir, { dot: true });
5610
+ }
5611
+ function sameBytesAt(file, left, right) {
5612
+ return readFileSync(path17.join(left, file)).equals(readFileSync(path17.join(right, file)));
5613
+ }
5513
5614
  async function replaceCopy(cacheDir, staged, record) {
5514
5615
  await remove(cacheDir);
5515
5616
  await rename(staged, cacheDir);
5516
5617
  await writeFile(fetchRecordPath(cacheDir), JSON.stringify(record));
5517
5618
  }
5619
+ var GIGET_TARBALLS = "**/*.tar.gz";
5620
+ var gigetTarballRecordSchema = z4.object({ etag: z4.string().min(1).optional() });
5621
+ async function gigetDownload(source, fullSource, options) {
5622
+ const providerDir = gigetProviderDir(source);
5623
+ const timesBefore = await tarballTimes(providerDir);
5624
+ const result = await downloadTemplate(fullSource, options);
5625
+ const tarball = path17.join(providerDir, gigetTarballOf(result));
5626
+ const writtenByThisDownload = timesBefore.get(tarball) !== await modifiedAt(tarball);
5627
+ if (writtenByThisDownload) return { result };
5628
+ verbose(`giget extracted the tarball it saved earlier, not a download: ${tarball}`);
5629
+ return { result, savedTarball: { path: tarball, etag: await etagSavedWith(tarball) } };
5630
+ }
5631
+ function gigetProviderDir(source) {
5632
+ const provider = SOURCE_PROTO_RE.exec(source)?.[1];
5633
+ if (provider === void 0) throw new Error(`No provider named in '${source}'`);
5634
+ return path17.join(gigetCacheRoot(), provider);
5635
+ }
5636
+ async function tarballTimes(providerDir) {
5637
+ const tarballs = await glob(GIGET_TARBALLS, providerDir);
5638
+ const paths = tarballs.map((tarball) => path17.join(providerDir, tarball));
5639
+ return new Map(await Promise.all(paths.map(async (at) => [at, await modifiedAt(at)])));
5640
+ }
5641
+ async function modifiedAt(file) {
5642
+ return await fileExists(file) ? (await stat(file)).mtimeMs : void 0;
5643
+ }
5644
+ function gigetTarballOf(result) {
5645
+ const name = result.name;
5646
+ const version = result.version;
5647
+ if (typeof name !== "string") throw new Error("the download named no template");
5648
+ const stem = typeof version === "string" && version !== "" ? version : name;
5649
+ return path17.join(name, `${stem}.tar.gz`);
5650
+ }
5651
+ function gigetRecordOf(tarball) {
5652
+ return `${tarball}.json`;
5653
+ }
5654
+ async function etagSavedWith(tarballPath) {
5655
+ const raw = await readFileOptional(gigetRecordOf(tarballPath));
5656
+ const parsed = gigetTarballRecordSchema.safeParse(parseJsonOrUndefined(raw));
5657
+ return parsed.success ? parsed.data.etag : void 0;
5658
+ }
5659
+ function savedUnder(savedTarball, record) {
5660
+ return savedTarball.etag !== void 0 && savedTarball.etag === record.etag;
5661
+ }
5518
5662
  var REVALIDATION_TIMEOUT_MS = 5e3;
5519
5663
  var FETCH_RECORD_SUFFIX = ".etag.json";
5520
5664
  var askedThisRun = /* @__PURE__ */ new Map();
@@ -5546,13 +5690,7 @@ async function classifyCachedCopy(cacheDir, source) {
5546
5690
  return "current";
5547
5691
  }
5548
5692
  try {
5549
- const live = await fetchEtag(record.tar);
5550
- if (live !== void 0 && record.etag !== void 0) {
5551
- return live === record.etag ? "current" : "superseded";
5552
- }
5553
- if (mustAnswer()) return "unconfirmed";
5554
- verbose(`${record.tar} answered without an ETag \u2014 keeping the cached copy`);
5555
- return "current";
5693
+ return judgeAnswer(record, await fetchEtag(record.tar));
5556
5694
  } catch (error) {
5557
5695
  if (error instanceof TarballWithheldError) throw createDetailedFetchError(error, source);
5558
5696
  verbose(`Could not revalidate ${record.tar}: ${getErrorMessage(error)}`);
@@ -5561,6 +5699,17 @@ async function classifyCachedCopy(cacheDir, source) {
5561
5699
  return "unreachable";
5562
5700
  }
5563
5701
  }
5702
+ function judgeAnswer(record, live) {
5703
+ if (movedOn(record, live)) return "superseded";
5704
+ if (mustAnswer()) return "answered";
5705
+ if (live === void 0) {
5706
+ verbose(`${record.tar} answered without an ETag \u2014 keeping the cached copy`);
5707
+ }
5708
+ return "current";
5709
+ }
5710
+ function movedOn(record, live) {
5711
+ return live !== void 0 && record.etag !== void 0 && live !== record.etag;
5712
+ }
5564
5713
  async function fetchEtag(tar) {
5565
5714
  const auth = process.env.GIGET_AUTH;
5566
5715
  const response = await fetch(tar, {
@@ -5585,13 +5734,13 @@ async function readFetchRecord(cacheDir) {
5585
5734
  }
5586
5735
  return parsed.data;
5587
5736
  }
5588
- async function recordFetchedCopy(cacheDir, result) {
5737
+ async function recordFetchedCopy(cacheDir, result, savedTarball) {
5589
5738
  const tar = tarballOf(result);
5590
5739
  if (tar === void 0) {
5591
5740
  verbose("No tarball URL came back from the download \u2014 the copy cannot be revalidated");
5592
5741
  return;
5593
5742
  }
5594
- const etag = await etagIfAnswered(tar);
5743
+ const etag = savedTarball ? savedTarball.etag : await etagIfAnswered(tar);
5595
5744
  await writeFile(fetchRecordPath(cacheDir), JSON.stringify(fetchRecord(tar, etag)));
5596
5745
  }
5597
5746
  async function etagIfAnswered(tar) {
@@ -6140,7 +6289,7 @@ async function installationIfPresent(candidate) {
6140
6289
  // src/cli/lib/hosts/claude-host.ts
6141
6290
  import os12 from "os";
6142
6291
  import path21 from "path";
6143
- import { z as z5 } from "zod";
6292
+ import { z as z6 } from "zod";
6144
6293
 
6145
6294
  // src/cli/utils/exec.ts
6146
6295
  import { spawn } from "child_process";
@@ -6243,24 +6392,24 @@ async function execCommand(command, args, options) {
6243
6392
 
6244
6393
  // src/cli/lib/plugins/plugin-settings.ts
6245
6394
  import path20 from "path";
6246
- import { z as z4 } from "zod";
6247
- var pluginSettingsSchema = z4.object({
6395
+ import { z as z5 } from "zod";
6396
+ var pluginSettingsSchema = z5.object({
6248
6397
  // Absent when no plugin is enabled.
6249
- enabledPlugins: z4.record(z4.string(), z4.unknown()).exactOptional()
6398
+ enabledPlugins: z5.record(z5.string(), z5.unknown()).exactOptional()
6250
6399
  }).passthrough();
6251
6400
  var installationFields = {
6252
- installPath: z4.string(),
6253
- version: z4.string(),
6254
- installedAt: z4.string()
6401
+ installPath: z5.string(),
6402
+ version: z5.string(),
6403
+ installedAt: z5.string()
6255
6404
  };
6256
- var pluginInstallationSchema = z4.discriminatedUnion("scope", [
6257
- z4.object({ scope: z4.literal("project"), projectPath: z4.string(), ...installationFields }),
6258
- z4.object({ scope: z4.literal("user"), ...installationFields }),
6259
- z4.object({ scope: z4.literal("local"), ...installationFields })
6405
+ var pluginInstallationSchema = z5.discriminatedUnion("scope", [
6406
+ z5.object({ scope: z5.literal("project"), projectPath: z5.string(), ...installationFields }),
6407
+ z5.object({ scope: z5.literal("user"), ...installationFields }),
6408
+ z5.object({ scope: z5.literal("local"), ...installationFields })
6260
6409
  ]);
6261
- var installedPluginsSchema = z4.object({
6262
- version: z4.number(),
6263
- plugins: z4.record(z4.string(), z4.array(pluginInstallationSchema))
6410
+ var installedPluginsSchema = z5.object({
6411
+ version: z5.number(),
6412
+ plugins: z5.record(z5.string(), z5.array(pluginInstallationSchema))
6264
6413
  }).passthrough();
6265
6414
  function getInstalledPluginsRegistryPath(pluginsDir2) {
6266
6415
  return path20.join(pluginsDir2, INSTALLED_PLUGINS_FILE);
@@ -6364,12 +6513,12 @@ async function isClaudeCLIAvailable(options) {
6364
6513
  return false;
6365
6514
  }
6366
6515
  }
6367
- var marketplaceInfoListSchema = z5.array(
6368
- z5.object({
6369
- name: z5.string(),
6370
- source: z5.string(),
6371
- repo: z5.string().exactOptional(),
6372
- path: z5.string().exactOptional()
6516
+ var marketplaceInfoListSchema = z6.array(
6517
+ z6.object({
6518
+ name: z6.string(),
6519
+ source: z6.string(),
6520
+ repo: z6.string().exactOptional(),
6521
+ path: z6.string().exactOptional()
6373
6522
  })
6374
6523
  );
6375
6524
  async function claudePluginMarketplaceList(options) {
@@ -6480,7 +6629,7 @@ function claudeHost() {
6480
6629
  // src/cli/lib/hosts/codex-host.ts
6481
6630
  import os13 from "os";
6482
6631
  import path22 from "path";
6483
- import { z as z6 } from "zod";
6632
+ import { z as z7 } from "zod";
6484
6633
  var CODEX = "codex";
6485
6634
  var PLUGIN_CACHE_SUBDIR = "cache";
6486
6635
  var STANDING_WARNING = /could not create PATH aliases/;
@@ -6543,22 +6692,22 @@ async function readJsonFromCodex(schema, args, options, attempt, askedFrom) {
6543
6692
  }
6544
6693
  return validated.data;
6545
6694
  }
6546
- var marketplaceRegistrySchema = z6.object({
6547
- marketplaces: z6.array(
6548
- z6.object({
6549
- name: z6.string(),
6550
- marketplaceSource: z6.object({ sourceType: z6.string(), source: z6.string() })
6695
+ var marketplaceRegistrySchema = z7.object({
6696
+ marketplaces: z7.array(
6697
+ z7.object({
6698
+ name: z7.string(),
6699
+ marketplaceSource: z7.object({ sourceType: z7.string(), source: z7.string() })
6551
6700
  })
6552
6701
  )
6553
6702
  });
6554
- var pluginListingSchema = z6.object({
6555
- installed: z6.array(
6556
- z6.object({
6557
- pluginId: z6.string(),
6558
- name: z6.string(),
6559
- marketplaceName: z6.string(),
6560
- version: z6.string(),
6561
- enabled: z6.boolean()
6703
+ var pluginListingSchema = z7.object({
6704
+ installed: z7.array(
6705
+ z7.object({
6706
+ pluginId: z7.string(),
6707
+ name: z7.string(),
6708
+ marketplaceName: z7.string(),
6709
+ version: z7.string(),
6710
+ enabled: z7.boolean()
6562
6711
  })
6563
6712
  )
6564
6713
  });
@@ -7529,16 +7678,15 @@ Compiled ${plural(results.length, "skill plugin")}:`);
7529
7678
 
7530
7679
  // src/cli/lib/skills/local-skill-loader.ts
7531
7680
  import path25 from "path";
7532
- function copiedInSkillsAt(root) {
7681
+ function copiedInSkillsAt(root, provider) {
7533
7682
  const scope = isHomeDirectory(root) ? "global" : "project";
7534
- const provider = providerInUse(root);
7535
7683
  return {
7536
7684
  dir: skillsDir(provider, scope, root),
7537
7685
  pathPrefix: skillsPathPrefix(provider, scope, root)
7538
7686
  };
7539
7687
  }
7540
- async function discoverLocalSkills(root) {
7541
- const { dir: localSkillsPath, pathPrefix } = copiedInSkillsAt(root);
7688
+ async function discoverLocalSkills(root, provider = providerInUse(root)) {
7689
+ const { dir: localSkillsPath, pathPrefix } = copiedInSkillsAt(root, provider);
7542
7690
  if (!await directoryExists2(localSkillsPath)) {
7543
7691
  verbose(`Local skills directory not found: ${localSkillsPath}`);
7544
7692
  return null;
@@ -7739,9 +7887,10 @@ async function extractSkill(skillsDir2, metadataFile) {
7739
7887
  const frontmatter = parseFrontmatterOrWarn(skillDir, skillMdPath, await readFile(skillMdPath));
7740
7888
  if (!frontmatter) return null;
7741
7889
  if (!metadata.displayName) {
7742
- throw new Error(
7743
- `Skill at ${metadataFile} is missing required '${METADATA_KEYS.DISPLAY_NAME}' field in metadata.yaml`
7890
+ warn(
7891
+ `Skipping '${metadataFile}': invalid ${STANDARD_FILES.METADATA_YAML} \u2014 missing required field: ${METADATA_KEYS.DISPLAY_NAME}`
7744
7892
  );
7893
+ return null;
7745
7894
  }
7746
7895
  const skillId = frontmatter.name;
7747
7896
  const extracted = {
@@ -9678,7 +9827,7 @@ async function loadCatalogue(options) {
9678
9827
  ...catalogue,
9679
9828
  marketplaceSkillIds: new Set(typedKeys(catalogue.matrix.skills))
9680
9829
  };
9681
- result.matrix = await mergeLocalSkills(result.matrix, resolvedProjectDir);
9830
+ result.matrix = await mergeLocalSkills(result.matrix, resolvedProjectDir, provider);
9682
9831
  await seatGlobalInstallationSkills(result.matrix, source, purpose);
9683
9832
  if (!options.skipExtraSources) {
9684
9833
  await loadSkillsFromAllSources(
@@ -9840,12 +9989,12 @@ function goesOnWithoutManifest(source, purpose) {
9840
9989
  function configuredLabel(sourceConfig) {
9841
9990
  return sourceConfig.marketplace === void 0 ? {} : { marketplace: sourceConfig.marketplace };
9842
9991
  }
9843
- async function mergeLocalSkills(matrix2, projectDir) {
9844
- const withGlobal = isHomeDirectory(projectDir) ? matrix2 : await mergeDiscoveredLocalSkills(matrix2, os14.homedir(), "global");
9845
- return mergeDiscoveredLocalSkills(withGlobal, projectDir, "project");
9992
+ async function mergeLocalSkills(matrix2, projectDir, provider) {
9993
+ const withGlobal = isHomeDirectory(projectDir) ? matrix2 : await mergeDiscoveredLocalSkills(matrix2, os14.homedir(), "global", provider);
9994
+ return mergeDiscoveredLocalSkills(withGlobal, projectDir, "project", provider);
9846
9995
  }
9847
- async function mergeDiscoveredLocalSkills(matrix2, dir, label) {
9848
- const discovered = await discoverLocalSkills(dir);
9996
+ async function mergeDiscoveredLocalSkills(matrix2, dir, label, provider) {
9997
+ const discovered = await discoverLocalSkills(dir, provider);
9849
9998
  if (!discovered || discovered.skills.length === 0) return matrix2;
9850
9999
  verbose(
9851
10000
  `Found ${discovered.skills.length} ${label} local skill(s) in ${discovered.localSkillsPath}`
@@ -10280,6 +10429,7 @@ export {
10280
10429
  flatUnion,
10281
10430
  renderTypeImportLine,
10282
10431
  spaces,
10432
+ EXTRACTED_FIELDS,
10283
10433
  generateConfigSource,
10284
10434
  refuseUnwritableStack,
10285
10435
  generateBlankGlobalConfigSource,
@@ -10375,4 +10525,4 @@ export {
10375
10525
  executeMigration,
10376
10526
  keepsGlobalInstall
10377
10527
  };
10378
- //# sourceMappingURL=chunk-VILFCMRN.js.map
10528
+ //# sourceMappingURL=chunk-WVFBBZEP.js.map