skillfish 1.0.2 → 1.0.3

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.
@@ -151,6 +151,7 @@ Examples:
151
151
  // Install each selected skill
152
152
  let totalInstalled = 0;
153
153
  let totalSkipped = 0;
154
+ const telemetryPromises = [];
154
155
  // SECURITY: Ask for confirmation before installation (unless --yes is used)
155
156
  // Single confirmation for all selected skills
156
157
  if (!trustSource && !jsonMode && isInputTTY()) {
@@ -221,14 +222,18 @@ Examples:
221
222
  }
222
223
  totalInstalled += result.installed.length;
223
224
  totalSkipped += result.skipped.length;
224
- // Track successful installs (fire-and-forget telemetry)
225
+ // Track successful installs (telemetry with timeout)
225
226
  if (result.installed.length > 0) {
226
227
  // Construct github value to match skills.github column format: owner/repo/path/to/skill
227
228
  const skillDir = skillPath.replace(/\/?SKILL\.md$/i, '').replace(/^\.?\/?/, '');
228
229
  const github = skillDir ? `${owner}/${repo}/${skillDir}` : `${owner}/${repo}`;
229
- trackInstall(github);
230
+ telemetryPromises.push(trackInstall(github));
230
231
  }
231
232
  }
233
+ // Wait for telemetry to complete (with timeout built into trackInstall)
234
+ if (telemetryPromises.length > 0) {
235
+ await Promise.all(telemetryPromises);
236
+ }
232
237
  // Summary
233
238
  if (jsonMode) {
234
239
  outputJsonAndExit(EXIT_CODES.SUCCESS);
package/dist/index.js CHANGED
File without changes
@@ -1,10 +1,8 @@
1
1
  /**
2
- * Track a skill install. Fire-and-forget - never blocks or throws.
3
- *
4
- * NOTE: Due to Node.js event loop behavior, this request may not complete
5
- * if the CLI process exits immediately after calling. This is acceptable
6
- * for directional metrics (like npm download counts).
2
+ * Track a skill install. Returns a promise that resolves when the request
3
+ * completes (or times out). Never rejects.
7
4
  *
8
5
  * @param github Full GitHub path (e.g., owner/repo/path/to/skill)
6
+ * @returns Promise that resolves when telemetry is sent (or times out)
9
7
  */
10
- export declare function trackInstall(github: string): void;
8
+ export declare function trackInstall(github: string): Promise<void>;
package/dist/telemetry.js CHANGED
@@ -1,27 +1,34 @@
1
1
  const TELEMETRY_URL = 'https://mcpmarket.com/api/telemetry';
2
+ /** Timeout for telemetry requests (ms) */
3
+ const TELEMETRY_TIMEOUT = 2000;
2
4
  /**
3
- * Track a skill install. Fire-and-forget - never blocks or throws.
4
- *
5
- * NOTE: Due to Node.js event loop behavior, this request may not complete
6
- * if the CLI process exits immediately after calling. This is acceptable
7
- * for directional metrics (like npm download counts).
5
+ * Track a skill install. Returns a promise that resolves when the request
6
+ * completes (or times out). Never rejects.
8
7
  *
9
8
  * @param github Full GitHub path (e.g., owner/repo/path/to/skill)
9
+ * @returns Promise that resolves when telemetry is sent (or times out)
10
10
  */
11
11
  export function trackInstall(github) {
12
12
  try {
13
- if (process.env.DO_NOT_TRACK === '1' || process.env.CI === 'true')
14
- return;
15
- if (!github || github.length > 500)
16
- return;
17
- // POST with JSON body - fire and forget
18
- fetch(TELEMETRY_URL, {
13
+ if (process.env.DO_NOT_TRACK === '1' || process.env.CI === 'true') {
14
+ return Promise.resolve();
15
+ }
16
+ if (!github || github.length > 500) {
17
+ return Promise.resolve();
18
+ }
19
+ // Race between the fetch and a timeout to ensure we don't block the CLI
20
+ const fetchPromise = fetch(TELEMETRY_URL, {
19
21
  method: 'POST',
20
22
  headers: { 'Content-Type': 'application/json' },
21
23
  body: JSON.stringify({ github }),
22
- }).catch(() => { });
24
+ }).then(() => { }).catch(() => { });
25
+ const timeoutPromise = new Promise((resolve) => {
26
+ setTimeout(resolve, TELEMETRY_TIMEOUT);
27
+ });
28
+ return Promise.race([fetchPromise, timeoutPromise]);
23
29
  }
24
30
  catch {
25
31
  // Telemetry should never throw
32
+ return Promise.resolve();
26
33
  }
27
34
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillfish",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Install AI agent skills from GitHub with a single command",
5
5
  "type": "module",
6
6
  "bin": {