impel-cli 0.15.1 → 0.15.2

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/skills.js +46 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "impel-cli",
3
- "version": "0.15.1",
3
+ "version": "0.15.2",
4
4
  "description": "Configure Claude Code and Codex CLI to talk to Impel's gateway, authenticated by an Impel Personal Access Token",
5
5
  "type": "module",
6
6
  "bin": {
package/src/skills.js CHANGED
@@ -74,6 +74,23 @@ export function resolveMarketplaceName(marketplace) {
74
74
  return typeof name === "string" && name.trim() ? name.trim() : null;
75
75
  }
76
76
 
77
+ /** Resolve a marketplace name from Claude's local `marketplace list --json`. */
78
+ export function resolveConfiguredMarketplaceName(output, sourceUrl) {
79
+ let marketplaces;
80
+ try {
81
+ marketplaces = JSON.parse(String(output || ""));
82
+ } catch {
83
+ return null;
84
+ }
85
+ if (!Array.isArray(marketplaces)) return null;
86
+ const normalizedSource = String(sourceUrl || "").replace(/\/+$/u, "");
87
+ const marketplace = marketplaces.find((candidate) => (
88
+ typeof candidate?.url === "string"
89
+ && candidate.url.replace(/\/+$/u, "") === normalizedSource
90
+ ));
91
+ return resolveMarketplaceName(marketplace);
92
+ }
93
+
77
94
  /**
78
95
  * Resolve the gateway URL for skill serving. Reuses the CLI's configured gateway
79
96
  * (the caller passes `config.gatewayUrl`), then the env/default from config.js,
@@ -317,11 +334,38 @@ export async function syncSkills({
317
334
 
318
335
  const manifestUrl = marketplaceUrl(gatewayUrl, client);
319
336
  const sourceUrl = marketplaceSourceUrl(gatewayUrl, client);
320
- const marketplaceName = await fetchMarketplaceName(manifestUrl, fetchImpl);
321
- const commands = buildSkillCommands({ client, marketplaceSourceUrl: sourceUrl, marketplaceName });
337
+ let marketplaceName = await fetchMarketplaceName(manifestUrl, fetchImpl);
322
338
 
323
339
  logger.log(`Skills: syncing ${SKILL_PLUGIN_NAME} for ${displayLabel}…`);
324
340
  const failures = [];
341
+ const registerCommand = buildSkillCommands({
342
+ client,
343
+ marketplaceSourceUrl: sourceUrl,
344
+ marketplaceName,
345
+ })[0];
346
+ const registerResult = await run(spec.bin, registerCommand.args, env);
347
+ if (registerResult.missing) {
348
+ failures.push({ phase: registerCommand.phase, reason: `\`${spec.bin}\` disappeared mid-sync` });
349
+ } else if (!isBenign(registerResult)) {
350
+ failures.push({
351
+ phase: registerCommand.phase,
352
+ reason: firstLine(registerResult.stderr) || `exit ${registerResult.status}`,
353
+ });
354
+ }
355
+
356
+ // The public manifest fetch is deliberately best-effort and can time out.
357
+ // Once Claude has registered the marketplace, its local JSON index gives us
358
+ // the same dynamic name so refreshes can still use PLUGIN@MARKETPLACE.
359
+ if (!marketplaceName && client === "claude" && !registerResult.missing) {
360
+ const listed = await run(spec.bin, ["plugin", "marketplace", "list", "--json"], env);
361
+ if (listed.ok) marketplaceName = resolveConfiguredMarketplaceName(listed.stdout, sourceUrl);
362
+ }
363
+
364
+ const commands = registerResult.missing ? [] : buildSkillCommands({
365
+ client,
366
+ marketplaceSourceUrl: sourceUrl,
367
+ marketplaceName,
368
+ }).slice(1);
325
369
  for (const command of commands) {
326
370
  const result = await run(spec.bin, command.args, env);
327
371
  if (result.missing) {