skillfish 1.0.29 → 1.0.31

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/LICENSE CHANGED
@@ -633,8 +633,8 @@ the "copyright" line and a pointer to where the full notice is found.
633
633
  Copyright (C) <year> <name of author>
634
634
 
635
635
  This program is free software: you can redistribute it and/or modify
636
- it under the terms of the GNU Affero General Public License as published by
637
- the Free Software Foundation, either version 3 of the License, or
636
+ it under the terms of the GNU Affero General Public License as published
637
+ by the Free Software Foundation, either version 3 of the License, or
638
638
  (at your option) any later version.
639
639
 
640
640
  This program is distributed in the hope that it will be useful,
@@ -658,4 +658,4 @@ specific requirements.
658
658
  You should also get your employer (if you work as a programmer) or school,
659
659
  if any, to sign a "copyright disclaimer" for the program, if necessary.
660
660
  For more information on this, and how to apply and follow the GNU AGPL, see
661
- <https://www.gnu.org/licenses/>.
661
+ <https://www.gnu.org/licenses/>.
@@ -42,7 +42,16 @@ export async function submitSkillsToRegistry(skills) {
42
42
  // Validate Content-Type before parsing JSON
43
43
  const contentType = res.headers.get('content-type');
44
44
  if (!contentType?.includes('application/json')) {
45
- throw new Error('Unexpected response type from registry');
45
+ let body = '';
46
+ try {
47
+ body = (await res.text()).trim();
48
+ }
49
+ catch {
50
+ // ignore read errors
51
+ }
52
+ const statusInfo = !res.ok ? ` (HTTP ${res.status})` : '';
53
+ const bodyHint = body ? `: ${body.slice(0, 200)}` : '';
54
+ throw new Error(`Registry returned non-JSON response${statusInfo}${bodyHint}`);
46
55
  }
47
56
  const data = (await res.json());
48
57
  if (res.ok && data.success) {
@@ -118,12 +127,23 @@ export async function searchSkillsInRegistry(query, limit = 5) {
118
127
  }, MAX_RETRIES);
119
128
  // Validate Content-Type before parsing JSON
120
129
  const contentType = res.headers.get('content-type');
121
- if (!contentType?.includes('application/json')) {
130
+ const isJson = contentType?.includes('application/json');
131
+ // Handle non-JSON responses (e.g. 403 plain text from CDN/WAF)
132
+ if (!isJson) {
133
+ let body = '';
134
+ try {
135
+ body = (await res.text()).trim();
136
+ }
137
+ catch {
138
+ // ignore read errors
139
+ }
140
+ const statusInfo = !res.ok ? ` (HTTP ${res.status})` : '';
141
+ const bodyHint = body ? `: ${body.slice(0, 200)}` : '';
122
142
  return {
123
143
  success: false,
124
144
  results: [],
125
145
  totalCount: 0,
126
- error: 'Unexpected response type from registry',
146
+ error: `Registry returned non-JSON response${statusInfo}${bodyHint}`,
127
147
  };
128
148
  }
129
149
  const data = (await res.json());
@@ -145,16 +165,14 @@ export async function searchSkillsInRegistry(query, limit = 5) {
145
165
  // Validate and transform API response to our SearchResult format
146
166
  // Filter out malformed items that are missing required string fields
147
167
  const results = data.skills
148
- .filter((item) => typeof item.name === 'string' &&
149
- typeof item.slug === 'string' &&
150
- typeof item.github === 'string')
168
+ .filter((item) => typeof item.name === 'string' && typeof item.slug === 'string')
151
169
  .map((item) => ({
152
170
  name: item.name,
153
171
  slug: item.slug,
154
172
  type: 'skill',
155
173
  owner: item.owner?.name ?? '',
156
174
  ownerUrl: item.owner?.url ?? '',
157
- github: item.github,
175
+ github: item.github ?? '',
158
176
  description: item.description ?? '',
159
177
  stars: item.github_stars ?? 0,
160
178
  relevanceScore: item.relevance_score ?? 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillfish",
3
- "version": "1.0.29",
3
+ "version": "1.0.31",
4
4
  "description": "All in one Skill manager for AI coding agents. Install, update, and sync Skills across Claude Code, Cursor, Copilot + more.",
5
5
  "type": "module",
6
6
  "bin": {