@hasna/skills 0.1.32 → 0.1.34

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 (95) hide show
  1. package/README.md +1 -16
  2. package/bin/index.js +57 -14
  3. package/bin/mcp.js +57 -13
  4. package/dist/cli/commands/runtime.d.ts +1 -1
  5. package/dist/index.js +51 -5
  6. package/dist/lib/skill-validation.d.ts +2 -0
  7. package/package.json +1 -1
  8. package/skills/ad-creative-pack/package.json +4 -7
  9. package/skills/api-docs-portal/package.json +5 -3
  10. package/skills/audio/package.json +4 -22
  11. package/skills/audio-transcript-pack/package.json +3 -2
  12. package/skills/blog-article/package.json +5 -21
  13. package/skills/brand-kit/package.json +4 -7
  14. package/skills/brand-photo-shoot/package.json +3 -2
  15. package/skills/browse/README.md +13 -256
  16. package/skills/browse/SKILL.md +24 -45
  17. package/skills/browse/package.json +4 -33
  18. package/skills/contract-review-report/package.json +3 -2
  19. package/skills/customer-feedback-report/package.json +3 -2
  20. package/skills/deepresearch/CLAUDE.md +6 -39
  21. package/skills/deepresearch/README.md +15 -150
  22. package/skills/deepresearch/SKILL.md +23 -32
  23. package/skills/deepresearch/package.json +4 -37
  24. package/skills/domainpurchase/SKILL.md +14 -31
  25. package/skills/domainpurchase/package.json +3 -8
  26. package/skills/email-sequence/package.json +4 -7
  27. package/skills/generate-book-cover/package.json +5 -23
  28. package/skills/icon-pack/package.json +4 -22
  29. package/skills/image/README.md +13 -183
  30. package/skills/image/package.json +4 -22
  31. package/skills/invoice-reconciliation/package.json +3 -2
  32. package/skills/landing-page-pack/package.json +4 -7
  33. package/skills/logo-design/package.json +4 -2
  34. package/skills/managemcp/CLAUDE.md +9 -43
  35. package/skills/managemcp/README.md +12 -198
  36. package/skills/managemcp/package.json +2 -10
  37. package/skills/managemcp/tsconfig.json +1 -3
  38. package/skills/market-research-report/package.json +5 -4
  39. package/skills/meeting-pack/package.json +3 -2
  40. package/skills/migration-plan-pack/package.json +3 -2
  41. package/skills/music/package.json +4 -20
  42. package/skills/music-album/package.json +3 -2
  43. package/skills/one-page-website/package.json +3 -2
  44. package/skills/pdf-read/package.json +5 -23
  45. package/skills/pdf-to-dataset/package.json +5 -4
  46. package/skills/pdf-to-markdown/package.json +5 -4
  47. package/skills/performance-audit-report/package.json +3 -2
  48. package/skills/photo-album/package.json +4 -2
  49. package/skills/pitch-deck/package.json +5 -3
  50. package/skills/playlist-maker/package.json +4 -2
  51. package/skills/product-mockup/package.json +3 -2
  52. package/skills/proposal-pack/package.json +5 -4
  53. package/skills/read-pdf/package.json +4 -29
  54. package/skills/remove-background/package.json +5 -21
  55. package/skills/repo-onboarding-report/package.json +3 -2
  56. package/skills/sdk-generator/package.json +3 -2
  57. package/skills/security-audit-report/package.json +5 -4
  58. package/skills/seo-content-pack/package.json +5 -3
  59. package/skills/short-video-pack/package.json +3 -2
  60. package/skills/slide-deck-generator/package.json +3 -2
  61. package/skills/sms/README.md +18 -56
  62. package/skills/sms/package.json +1 -3
  63. package/skills/sms/tsconfig.json +1 -2
  64. package/skills/social-content-calendar/package.json +4 -7
  65. package/skills/test-suite-generator/package.json +5 -4
  66. package/skills/transcript/package.json +4 -23
  67. package/skills/video/package.json +4 -24
  68. package/skills/video-highlight-pack/package.json +3 -2
  69. package/skills/voiceover-jingle-pack/package.json +3 -2
  70. package/skills/webcrawling/CLAUDE.md +6 -17
  71. package/skills/webcrawling/README.md +13 -66
  72. package/skills/webcrawling/package.json +4 -32
  73. package/skills/browse/.env.example +0 -14
  74. package/skills/deepresearch/.env.example +0 -9
  75. package/skills/domainpurchase/.env.example +0 -7
  76. package/skills/domainpurchase/src/lib/api-client.ts +0 -571
  77. package/skills/domainpurchase/src/lib/config.ts +0 -209
  78. package/skills/domainpurchase/src/lib/installer.ts +0 -165
  79. package/skills/image/.env.example +0 -12
  80. package/skills/image/PROJECT_OVERVIEW.md +0 -216
  81. package/skills/image/QUICKSTART.md +0 -111
  82. package/skills/managemcp/.env.example +0 -16
  83. package/skills/managemcp/scripts/migrate.ts +0 -57
  84. package/skills/managemcp/scripts/seed.ts +0 -58
  85. package/skills/managemcp/src/db/index.ts +0 -37
  86. package/skills/managemcp/src/lib/api-client.ts +0 -108
  87. package/skills/managemcp/src/lib/config.ts +0 -34
  88. package/skills/managemcp/src/lib/installer.ts +0 -140
  89. package/skills/managemcp/src/lib/service-dir.ts +0 -119
  90. package/skills/sms/scripts/buy-number.ts +0 -63
  91. package/skills/sms/scripts/test-send.ts +0 -67
  92. package/skills/sms/src/server.ts +0 -351
  93. package/skills/sms/src/sse-server.ts +0 -279
  94. package/skills/transcript/.env.example +0 -10
  95. package/skills/webcrawling/.env.example +0 -2
@@ -1,571 +0,0 @@
1
- import {
2
- getApiKey,
3
- getApiSecret,
4
- getCustomerId,
5
- getApiUrl,
6
- useRemoteServer,
7
- getRemoteServerUrl,
8
- getRemoteApiKeyAsync,
9
- } from "./config";
10
-
11
- export interface Contact {
12
- nameFirst: string;
13
- nameLast: string;
14
- email: string;
15
- phone: string;
16
- addressMailing: {
17
- address1: string;
18
- address2?: string;
19
- city: string;
20
- state: string;
21
- postalCode: string;
22
- country: string;
23
- };
24
- organization?: string;
25
- encoding?: "ASCII" | "UTF-8";
26
- }
27
-
28
- // V2 API consent format
29
- export interface ConsentV2 {
30
- agreedAt: string;
31
- agreedBy: string;
32
- agreementKeys: string[];
33
- price: number; // Price in micro-units (e.g., 1500000 = $1.50)
34
- currency: string; // ISO currency code (e.g., "USD")
35
- registryPremiumPricing?: boolean;
36
- claimToken?: string;
37
- }
38
-
39
- // V2 API contacts format
40
- export interface DomainContactsV2 {
41
- admin?: Contact;
42
- billing?: Contact;
43
- registrant?: Contact;
44
- tech?: Contact;
45
- }
46
-
47
- // V2 API purchase request format
48
- export interface DomainPurchaseRequestV2 {
49
- domain: string;
50
- consent: ConsentV2;
51
- contacts?: DomainContactsV2;
52
- nameServers?: string[];
53
- period?: number;
54
- privacy?: boolean;
55
- renewAuto?: boolean;
56
- }
57
-
58
- // Legacy interface for backwards compatibility
59
- export interface DomainPurchaseRequest {
60
- domain: string;
61
- consent: {
62
- agreedAt: string;
63
- agreedBy: string;
64
- agreementKeys: string[];
65
- price?: number;
66
- currency?: string;
67
- };
68
- contactAdmin?: Contact;
69
- contactBilling?: Contact;
70
- contactRegistrant: Contact;
71
- contactTech?: Contact;
72
- nameServers?: string[];
73
- period?: number;
74
- privacy?: boolean;
75
- renewAuto?: boolean;
76
- }
77
-
78
- // Convert legacy request to V2 format
79
- export function toV2Request(request: DomainPurchaseRequest, price: number, currency: string): DomainPurchaseRequestV2 {
80
- return {
81
- domain: request.domain,
82
- consent: {
83
- agreedAt: request.consent.agreedAt,
84
- agreedBy: request.consent.agreedBy,
85
- agreementKeys: request.consent.agreementKeys,
86
- price: request.consent.price ?? price,
87
- currency: request.consent.currency ?? currency,
88
- },
89
- contacts: {
90
- registrant: request.contactRegistrant,
91
- admin: request.contactAdmin,
92
- billing: request.contactBilling,
93
- tech: request.contactTech,
94
- },
95
- nameServers: request.nameServers,
96
- period: request.period,
97
- privacy: request.privacy,
98
- renewAuto: request.renewAuto,
99
- };
100
- }
101
-
102
- export interface DomainAvailability {
103
- domain: string;
104
- available: boolean;
105
- price?: number;
106
- currency?: string;
107
- period?: number;
108
- definitive?: boolean;
109
- registryPremiumPricing?: boolean;
110
- }
111
-
112
- export interface Agreement {
113
- agreementKey: string;
114
- title: string;
115
- url: string;
116
- content?: string;
117
- }
118
-
119
- export interface DomainDetails {
120
- domain: string;
121
- status: string;
122
- createdAt: string;
123
- expires: string;
124
- renewAuto: boolean;
125
- privacy: boolean;
126
- nameServers?: string[];
127
- contactAdmin?: Contact;
128
- contactBilling?: Contact;
129
- contactRegistrant?: Contact;
130
- contactTech?: Contact;
131
- }
132
-
133
- function getHeaders() {
134
- const apiKey = getApiKey();
135
- const apiSecret = getApiSecret();
136
-
137
- if (!apiKey || !apiSecret) {
138
- throw new Error(
139
- "API credentials not configured. Run: service-domainpurchase config --api-key <key> --api-secret <secret>"
140
- );
141
- }
142
-
143
- return {
144
- Authorization: `sso-key ${apiKey}:${apiSecret}`,
145
- "Content-Type": "application/json",
146
- Accept: "application/json",
147
- };
148
- }
149
-
150
- async function apiRequest<T>(
151
- endpoint: string,
152
- method: string = "GET",
153
- body?: any
154
- ): Promise<{ status: number; data: T; ok: boolean }> {
155
- const baseUrl = getApiUrl();
156
- const url = `${baseUrl}${endpoint}`;
157
-
158
- const options: RequestInit = {
159
- method,
160
- headers: getHeaders(),
161
- };
162
-
163
- if (body) {
164
- options.body = JSON.stringify(body);
165
- }
166
-
167
- const response = await fetch(url, options);
168
- const text = await response.text();
169
-
170
- let data: T;
171
- try {
172
- data = JSON.parse(text);
173
- } catch {
174
- data = { rawResponse: text.substring(0, 500) } as T;
175
- }
176
-
177
- return {
178
- status: response.status,
179
- data,
180
- ok: response.ok || response.status === 203,
181
- };
182
- }
183
-
184
- export const purchaseApi = {
185
- // Check single domain availability with pricing
186
- async checkAvailability(
187
- domain: string,
188
- forTransfer: boolean = false
189
- ): Promise<DomainAvailability> {
190
- const type = forTransfer ? "TRANSFER" : "REGISTRATION";
191
- const result = await apiRequest<DomainAvailability>(
192
- `/v2/domains/available?domain=${encodeURIComponent(domain)}&type=${type}&optimizeFor=ACCURACY`
193
- );
194
-
195
- if (!result.ok) {
196
- throw new Error(`API Error: ${JSON.stringify(result.data)}`);
197
- }
198
-
199
- return result.data;
200
- },
201
-
202
- // Get legal agreements for domain purchase
203
- async getAgreements(tlds: string[], privacy: boolean = false): Promise<Agreement[]> {
204
- const customerId = getCustomerId();
205
- if (!customerId) {
206
- throw new Error("Customer ID not configured");
207
- }
208
-
209
- const result = await apiRequest<Agreement[]>(
210
- `/v2/customers/${customerId}/domains/agreements?tlds=${tlds.join(",")}&privacy=${privacy}`
211
- );
212
-
213
- if (!result.ok) {
214
- throw new Error(`API Error: ${JSON.stringify(result.data)}`);
215
- }
216
-
217
- return result.data;
218
- },
219
-
220
- // Validate domain purchase request (dry run) - V2 API
221
- async validatePurchase(request: DomainPurchaseRequestV2): Promise<any> {
222
- const customerId = getCustomerId();
223
- if (!customerId) {
224
- throw new Error("Customer ID not configured");
225
- }
226
-
227
- const result = await apiRequest<any>(
228
- `/v2/customers/${customerId}/domains/register/validate`,
229
- "POST",
230
- request
231
- );
232
-
233
- return {
234
- valid: result.ok,
235
- status: result.status,
236
- data: result.data,
237
- };
238
- },
239
-
240
- // Purchase domain - V2 API
241
- async purchaseDomain(request: DomainPurchaseRequestV2): Promise<any> {
242
- const customerId = getCustomerId();
243
- if (!customerId) {
244
- throw new Error("Customer ID not configured");
245
- }
246
-
247
- const result = await apiRequest<any>(
248
- `/v2/customers/${customerId}/domains/register`,
249
- "POST",
250
- request
251
- );
252
-
253
- // 202 Accepted is success for registration
254
- if (!result.ok && result.status !== 202) {
255
- throw new Error(`Purchase failed: ${JSON.stringify(result.data)}`);
256
- }
257
-
258
- return result.data;
259
- },
260
-
261
- // Get domain details
262
- async getDomainDetails(domain: string): Promise<DomainDetails> {
263
- const customerId = getCustomerId();
264
- if (!customerId) {
265
- throw new Error("Customer ID not configured");
266
- }
267
-
268
- const result = await apiRequest<DomainDetails>(
269
- `/v2/customers/${customerId}/domains/${encodeURIComponent(domain)}?includes=contacts,nameServers`
270
- );
271
-
272
- if (!result.ok) {
273
- throw new Error(`API Error: ${JSON.stringify(result.data)}`);
274
- }
275
-
276
- return result.data;
277
- },
278
-
279
- // Update domain settings
280
- async updateDomain(
281
- domain: string,
282
- updates: {
283
- renewAuto?: boolean;
284
- privacy?: boolean;
285
- nameServers?: string[];
286
- }
287
- ): Promise<any> {
288
- const customerId = getCustomerId();
289
- if (!customerId) {
290
- throw new Error("Customer ID not configured");
291
- }
292
-
293
- const result = await apiRequest<any>(
294
- `/v2/customers/${customerId}/domains/${encodeURIComponent(domain)}`,
295
- "PATCH",
296
- updates
297
- );
298
-
299
- if (!result.ok) {
300
- throw new Error(`Update failed: ${JSON.stringify(result.data)}`);
301
- }
302
-
303
- return result.data;
304
- },
305
-
306
- // Renew domain
307
- async renewDomain(domain: string, period: number = 1): Promise<any> {
308
- const customerId = getCustomerId();
309
- if (!customerId) {
310
- throw new Error("Customer ID not configured");
311
- }
312
-
313
- const result = await apiRequest<any>(
314
- `/v2/customers/${customerId}/domains/${encodeURIComponent(domain)}/renew`,
315
- "POST",
316
- { period }
317
- );
318
-
319
- if (!result.ok) {
320
- throw new Error(`Renewal failed: ${JSON.stringify(result.data)}`);
321
- }
322
-
323
- return result.data;
324
- },
325
-
326
- // List owned domains
327
- async listOwnedDomains(limit: number = 100): Promise<any[]> {
328
- const customerId = getCustomerId();
329
- if (!customerId) {
330
- throw new Error("Customer ID not configured");
331
- }
332
-
333
- const result = await apiRequest<any[]>(
334
- `/v2/customers/${customerId}/domains?limit=${limit}`
335
- );
336
-
337
- if (!result.ok) {
338
- throw new Error(`API Error: ${JSON.stringify(result.data)}`);
339
- }
340
-
341
- return result.data;
342
- },
343
-
344
- // Delete/cancel domain (if allowed)
345
- async deleteDomain(domain: string): Promise<any> {
346
- const customerId = getCustomerId();
347
- if (!customerId) {
348
- throw new Error("Customer ID not configured");
349
- }
350
-
351
- const result = await apiRequest<any>(
352
- `/v2/customers/${customerId}/domains/${encodeURIComponent(domain)}`,
353
- "DELETE"
354
- );
355
-
356
- if (!result.ok) {
357
- throw new Error(`Delete failed: ${JSON.stringify(result.data)}`);
358
- }
359
-
360
- return result.data;
361
- },
362
-
363
- // Transfer domain in
364
- async initiateTransfer(
365
- domain: string,
366
- authCode: string,
367
- consent: DomainPurchaseRequest["consent"],
368
- contact: Contact
369
- ): Promise<any> {
370
- const customerId = getCustomerId();
371
- if (!customerId) {
372
- throw new Error("Customer ID not configured");
373
- }
374
-
375
- const result = await apiRequest<any>(
376
- `/v2/customers/${customerId}/domains/${encodeURIComponent(domain)}/transfer`,
377
- "POST",
378
- {
379
- authCode,
380
- consent,
381
- contactRegistrant: contact,
382
- }
383
- );
384
-
385
- if (!result.ok) {
386
- throw new Error(`Transfer failed: ${JSON.stringify(result.data)}`);
387
- }
388
-
389
- return result.data;
390
- },
391
- };
392
-
393
- // Format price from micro-units to dollars
394
- export function formatPrice(
395
- microUnits: number,
396
- currency: string = "USD"
397
- ): string {
398
- return `${currency} ${(microUnits / 1000000).toFixed(2)}`;
399
- }
400
-
401
- // ============ REMOTE SERVER API ============
402
- // When useRemoteServer is enabled, calls go through the remote server
403
- // instead of directly to the GoDaddy API. This simplifies credential management.
404
-
405
- async function remoteApiRequest<T>(
406
- endpoint: string,
407
- method: string = "GET",
408
- body?: any
409
- ): Promise<{ status: number; data: T; ok: boolean }> {
410
- const baseUrl = getRemoteServerUrl();
411
- const apiKey = await getRemoteApiKeyAsync();
412
- const url = `${baseUrl}${endpoint}`;
413
-
414
- const headers: Record<string, string> = {
415
- "Content-Type": "application/json",
416
- Accept: "application/json",
417
- };
418
-
419
- if (apiKey) {
420
- headers["Authorization"] = `Bearer ${apiKey}`;
421
- }
422
-
423
- const options: RequestInit = {
424
- method,
425
- headers,
426
- };
427
-
428
- if (body) {
429
- options.body = JSON.stringify(body);
430
- }
431
-
432
- const response = await fetch(url, options);
433
- const text = await response.text();
434
-
435
- let data: T;
436
- try {
437
- data = JSON.parse(text);
438
- } catch {
439
- data = { rawResponse: text.substring(0, 500) } as T;
440
- }
441
-
442
- return {
443
- status: response.status,
444
- data,
445
- ok: response.ok,
446
- };
447
- }
448
-
449
- // Remote server API - proxies requests through the configured remote server
450
- export const remoteApi = {
451
- async checkAvailability(domain: string): Promise<DomainAvailability> {
452
- const result = await remoteApiRequest<DomainAvailability>(
453
- `/check?domain=${encodeURIComponent(domain)}`
454
- );
455
- if (!result.ok) {
456
- throw new Error(`API Error: ${JSON.stringify(result.data)}`);
457
- }
458
- return result.data;
459
- },
460
-
461
- async getAgreements(tlds: string[], privacy: boolean = false): Promise<Agreement[]> {
462
- const result = await remoteApiRequest<Agreement[]>(
463
- `/agreements?tlds=${tlds.join(",")}&privacy=${privacy}`
464
- );
465
- if (!result.ok) {
466
- throw new Error(`API Error: ${JSON.stringify(result.data)}`);
467
- }
468
- return result.data;
469
- },
470
-
471
- async validatePurchase(request: DomainPurchaseRequestV2): Promise<any> {
472
- const result = await remoteApiRequest<any>("/validate", "POST", request);
473
- return {
474
- valid: result.ok,
475
- status: result.status,
476
- data: result.data,
477
- };
478
- },
479
-
480
- async purchaseDomain(request: DomainPurchaseRequestV2): Promise<any> {
481
- const result = await remoteApiRequest<any>("/purchase", "POST", request);
482
- if (!result.ok && result.status !== 202) {
483
- throw new Error(`Purchase failed: ${JSON.stringify(result.data)}`);
484
- }
485
- return result.data;
486
- },
487
-
488
- async listOwnedDomains(limit: number = 100): Promise<any[]> {
489
- const result = await remoteApiRequest<any[]>(`/list?limit=${limit}`);
490
- if (!result.ok) {
491
- throw new Error(`API Error: ${JSON.stringify(result.data)}`);
492
- }
493
- return result.data;
494
- },
495
-
496
- async getDomainDetails(domain: string): Promise<DomainDetails> {
497
- const result = await remoteApiRequest<DomainDetails>(
498
- `/info?domain=${encodeURIComponent(domain)}`
499
- );
500
- if (!result.ok) {
501
- throw new Error(`API Error: ${JSON.stringify(result.data)}`);
502
- }
503
- return result.data;
504
- },
505
-
506
- async updateDomain(
507
- domain: string,
508
- updates: { renewAuto?: boolean; privacy?: boolean; nameServers?: string[] }
509
- ): Promise<any> {
510
- const result = await remoteApiRequest<any>(
511
- `/update?domain=${encodeURIComponent(domain)}`,
512
- "PUT",
513
- updates
514
- );
515
- if (!result.ok) {
516
- throw new Error(`Update failed: ${JSON.stringify(result.data)}`);
517
- }
518
- return result.data;
519
- },
520
-
521
- async renewDomain(domain: string, period: number = 1): Promise<any> {
522
- const result = await remoteApiRequest<any>("/renew", "POST", { domain, period });
523
- if (!result.ok) {
524
- throw new Error(`Renewal failed: ${JSON.stringify(result.data)}`);
525
- }
526
- return result.data;
527
- },
528
- };
529
-
530
- // Smart API that automatically chooses between direct and remote based on config
531
- export const domainApi = {
532
- checkAvailability: (domain: string, forTransfer?: boolean) =>
533
- useRemoteServer()
534
- ? remoteApi.checkAvailability(domain)
535
- : purchaseApi.checkAvailability(domain, forTransfer),
536
-
537
- getAgreements: (tlds: string[], privacy?: boolean) =>
538
- useRemoteServer()
539
- ? remoteApi.getAgreements(tlds, privacy)
540
- : purchaseApi.getAgreements(tlds, privacy),
541
-
542
- validatePurchase: (request: DomainPurchaseRequestV2) =>
543
- useRemoteServer()
544
- ? remoteApi.validatePurchase(request)
545
- : purchaseApi.validatePurchase(request),
546
-
547
- purchaseDomain: (request: DomainPurchaseRequestV2) =>
548
- useRemoteServer()
549
- ? remoteApi.purchaseDomain(request)
550
- : purchaseApi.purchaseDomain(request),
551
-
552
- listOwnedDomains: (limit?: number) =>
553
- useRemoteServer()
554
- ? remoteApi.listOwnedDomains(limit)
555
- : purchaseApi.listOwnedDomains(limit),
556
-
557
- getDomainDetails: (domain: string) =>
558
- useRemoteServer()
559
- ? remoteApi.getDomainDetails(domain)
560
- : purchaseApi.getDomainDetails(domain),
561
-
562
- updateDomain: (domain: string, updates: any) =>
563
- useRemoteServer()
564
- ? remoteApi.updateDomain(domain, updates)
565
- : purchaseApi.updateDomain(domain, updates),
566
-
567
- renewDomain: (domain: string, period?: number) =>
568
- useRemoteServer()
569
- ? remoteApi.renewDomain(domain, period)
570
- : purchaseApi.renewDomain(domain, period),
571
- };