@girardmedia/bootspring 1.2.0 → 2.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.
- package/README.md +107 -14
- package/bin/bootspring.js +166 -27
- package/cli/agent.js +189 -17
- package/cli/analyze.js +499 -0
- package/cli/audit.js +557 -0
- package/cli/auth.js +495 -38
- package/cli/billing.js +302 -0
- package/cli/build.js +695 -0
- package/cli/business.js +109 -26
- package/cli/checkpoint-utils.js +168 -0
- package/cli/checkpoint.js +639 -0
- package/cli/cloud-sync.js +447 -0
- package/cli/content.js +198 -0
- package/cli/context.js +1 -1
- package/cli/deploy.js +543 -0
- package/cli/fundraise.js +112 -50
- package/cli/github-cmd.js +435 -0
- package/cli/health.js +477 -0
- package/cli/init.js +84 -13
- package/cli/legal.js +107 -95
- package/cli/log.js +2 -2
- package/cli/loop.js +976 -73
- package/cli/manager.js +711 -0
- package/cli/metrics.js +480 -0
- package/cli/monitor.js +812 -0
- package/cli/onboard.js +521 -0
- package/cli/orchestrator.js +12 -24
- package/cli/prd.js +594 -0
- package/cli/preseed-start.js +1483 -0
- package/cli/preseed.js +2302 -0
- package/cli/project.js +436 -0
- package/cli/quality.js +233 -0
- package/cli/security.js +913 -0
- package/cli/seed.js +1441 -5
- package/cli/skill.js +273 -211
- package/cli/suggest.js +989 -0
- package/cli/switch.js +453 -0
- package/cli/visualize.js +527 -0
- package/cli/watch.js +769 -0
- package/cli/workspace.js +607 -0
- package/core/analyze-workflow.js +1134 -0
- package/core/api-client.js +535 -22
- package/core/audit-workflow.js +1350 -0
- package/core/build-orchestrator.js +480 -0
- package/core/build-state.js +577 -0
- package/core/checkpoint-engine.js +408 -0
- package/core/config.js +1109 -26
- package/core/context-loader.js +21 -1
- package/core/deploy-workflow.js +836 -0
- package/core/entitlements.js +93 -22
- package/core/github-sync.js +610 -0
- package/core/index.js +8 -1
- package/core/ingest.js +1111 -0
- package/core/metrics-engine.js +768 -0
- package/core/onboard-workflow.js +1007 -0
- package/core/preseed-workflow.js +934 -0
- package/core/preseed.js +1617 -0
- package/core/project-context.js +325 -0
- package/core/project-state.js +694 -0
- package/core/r2-sync.js +583 -0
- package/core/scaffold.js +525 -7
- package/core/session.js +258 -0
- package/core/task-extractor.js +758 -0
- package/core/telemetry.js +28 -6
- package/core/tier-enforcement.js +737 -0
- package/core/utils.js +38 -14
- package/generators/questionnaire.js +15 -12
- package/generators/sections/ai.js +7 -7
- package/generators/sections/content.js +300 -0
- package/generators/sections/index.js +3 -0
- package/generators/sections/plugins.js +7 -6
- package/generators/templates/build-planning.template.js +596 -0
- package/generators/templates/content.template.js +819 -0
- package/generators/templates/index.js +2 -1
- package/hooks/git-autopilot.js +1250 -0
- package/hooks/index.js +9 -0
- package/intelligence/agent-collab.js +2057 -0
- package/intelligence/auto-suggest.js +634 -0
- package/intelligence/content-gen.js +1589 -0
- package/intelligence/cross-project.js +1647 -0
- package/intelligence/index.js +184 -0
- package/intelligence/learning/insights.json +517 -7
- package/intelligence/learning/pattern-learner.js +1008 -14
- package/intelligence/memory/decision-tracker.js +1431 -31
- package/intelligence/memory/decisions.jsonl +0 -0
- package/intelligence/orchestrator.js +2896 -1
- package/intelligence/prd.js +92 -1
- package/intelligence/recommendation-weights.json +14 -2
- package/intelligence/recommendations.js +463 -9
- package/intelligence/workflow-composer.js +1451 -0
- package/marketplace/index.d.ts +324 -0
- package/marketplace/index.js +1921 -0
- package/mcp/contracts/mcp-contract.v1.json +342 -4
- package/mcp/registry.js +680 -3
- package/mcp/response-formatter.js +23 -0
- package/mcp/tools/assist-tool.js +78 -4
- package/mcp/tools/autopilot-tool.js +408 -0
- package/mcp/tools/content-tool.js +571 -0
- package/mcp/tools/dashboard-tool.js +251 -5
- package/mcp/tools/mvp-tool.js +344 -0
- package/mcp/tools/plugin-tool.js +23 -1
- package/mcp/tools/prd-tool.js +579 -0
- package/mcp/tools/seed-tool.js +447 -0
- package/mcp/tools/skill-tool.js +43 -14
- package/mcp/tools/suggest-tool.js +147 -0
- package/package.json +15 -6
- package/agents/README.md +0 -93
- package/agents/ai-integration-expert/context.md +0 -386
- package/agents/api-expert/context.md +0 -416
- package/agents/architecture-expert/context.md +0 -454
- package/agents/auth-expert/context.md +0 -399
- package/agents/backend-expert/context.md +0 -483
- package/agents/business-strategy-expert/context.md +0 -180
- package/agents/code-review-expert/context.md +0 -365
- package/agents/competitive-analysis-expert/context.md +0 -239
- package/agents/data-modeling-expert/context.md +0 -352
- package/agents/database-expert/context.md +0 -250
- package/agents/devops-expert/context.md +0 -446
- package/agents/email-expert/context.md +0 -379
- package/agents/financial-expert/context.md +0 -213
- package/agents/frontend-expert/context.md +0 -364
- package/agents/fundraising-expert/context.md +0 -257
- package/agents/growth-expert/context.md +0 -249
- package/agents/index.js +0 -140
- package/agents/investor-relations-expert/context.md +0 -266
- package/agents/legal-expert/context.md +0 -284
- package/agents/marketing-expert/context.md +0 -236
- package/agents/monitoring-expert/context.md +0 -362
- package/agents/operations-expert/context.md +0 -279
- package/agents/partnerships-expert/context.md +0 -286
- package/agents/payment-expert/context.md +0 -340
- package/agents/performance-expert/context.md +0 -377
- package/agents/private-equity-expert/context.md +0 -246
- package/agents/railway-expert/context.md +0 -284
- package/agents/research-expert/context.md +0 -245
- package/agents/sales-expert/context.md +0 -241
- package/agents/security-expert/context.md +0 -343
- package/agents/testing-expert/context.md +0 -414
- package/agents/ui-ux-expert/context.md +0 -448
- package/agents/vercel-expert/context.md +0 -426
- package/skills/index.js +0 -787
- package/skills/patterns/README.md +0 -163
- package/skills/patterns/ai/agents.md +0 -281
- package/skills/patterns/ai/claude.md +0 -138
- package/skills/patterns/ai/embeddings.md +0 -150
- package/skills/patterns/ai/rag.md +0 -266
- package/skills/patterns/ai/streaming.md +0 -170
- package/skills/patterns/ai/structured-output.md +0 -162
- package/skills/patterns/ai/tools.md +0 -154
- package/skills/patterns/analytics/tracking.md +0 -220
- package/skills/patterns/api/errors.md +0 -296
- package/skills/patterns/api/graphql.md +0 -440
- package/skills/patterns/api/middleware.md +0 -279
- package/skills/patterns/api/openapi.md +0 -285
- package/skills/patterns/api/rate-limiting.md +0 -231
- package/skills/patterns/api/route-handler.md +0 -217
- package/skills/patterns/api/server-action.md +0 -249
- package/skills/patterns/api/versioning.md +0 -443
- package/skills/patterns/api/webhooks.md +0 -247
- package/skills/patterns/auth/clerk.md +0 -132
- package/skills/patterns/auth/mfa.md +0 -313
- package/skills/patterns/auth/nextauth.md +0 -140
- package/skills/patterns/auth/oauth.md +0 -237
- package/skills/patterns/auth/rbac.md +0 -152
- package/skills/patterns/auth/session-management.md +0 -367
- package/skills/patterns/auth/session.md +0 -120
- package/skills/patterns/database/audit.md +0 -177
- package/skills/patterns/database/migrations.md +0 -177
- package/skills/patterns/database/pagination.md +0 -230
- package/skills/patterns/database/pooling.md +0 -357
- package/skills/patterns/database/prisma.md +0 -180
- package/skills/patterns/database/relations.md +0 -187
- package/skills/patterns/database/seeding.md +0 -246
- package/skills/patterns/database/soft-delete.md +0 -153
- package/skills/patterns/database/transactions.md +0 -162
- package/skills/patterns/deployment/ci-cd.md +0 -231
- package/skills/patterns/deployment/docker.md +0 -188
- package/skills/patterns/deployment/monitoring.md +0 -387
- package/skills/patterns/deployment/vercel.md +0 -160
- package/skills/patterns/email/resend.md +0 -143
- package/skills/patterns/email/templates.md +0 -245
- package/skills/patterns/email/transactional.md +0 -503
- package/skills/patterns/email/verification.md +0 -176
- package/skills/patterns/files/download.md +0 -243
- package/skills/patterns/files/upload.md +0 -239
- package/skills/patterns/i18n/nextintl.md +0 -188
- package/skills/patterns/logging/structured.md +0 -292
- package/skills/patterns/notifications/email-queue.md +0 -248
- package/skills/patterns/notifications/push.md +0 -279
- package/skills/patterns/payments/checkout.md +0 -303
- package/skills/patterns/payments/invoices.md +0 -287
- package/skills/patterns/payments/portal.md +0 -245
- package/skills/patterns/payments/stripe.md +0 -272
- package/skills/patterns/payments/subscriptions.md +0 -300
- package/skills/patterns/payments/usage.md +0 -279
- package/skills/patterns/performance/caching.md +0 -276
- package/skills/patterns/performance/code-splitting.md +0 -233
- package/skills/patterns/performance/edge.md +0 -254
- package/skills/patterns/performance/isr.md +0 -266
- package/skills/patterns/performance/lazy-loading.md +0 -281
- package/skills/patterns/realtime/sse.md +0 -327
- package/skills/patterns/realtime/websockets.md +0 -336
- package/skills/patterns/search/filtering.md +0 -329
- package/skills/patterns/search/fulltext.md +0 -260
- package/skills/patterns/security/audit-logging.md +0 -444
- package/skills/patterns/security/csrf.md +0 -234
- package/skills/patterns/security/headers.md +0 -252
- package/skills/patterns/security/sanitization.md +0 -258
- package/skills/patterns/security/secrets.md +0 -261
- package/skills/patterns/security/validation.md +0 -268
- package/skills/patterns/security/xss.md +0 -229
- package/skills/patterns/seo/metadata.md +0 -252
- package/skills/patterns/state/context.md +0 -349
- package/skills/patterns/state/react-query.md +0 -313
- package/skills/patterns/state/url-state.md +0 -482
- package/skills/patterns/state/zustand.md +0 -262
- package/skills/patterns/testing/api.md +0 -259
- package/skills/patterns/testing/component.md +0 -233
- package/skills/patterns/testing/coverage.md +0 -207
- package/skills/patterns/testing/fixtures.md +0 -225
- package/skills/patterns/testing/integration.md +0 -436
- package/skills/patterns/testing/mocking.md +0 -177
- package/skills/patterns/testing/playwright.md +0 -162
- package/skills/patterns/testing/snapshot.md +0 -175
- package/skills/patterns/testing/vitest.md +0 -307
- package/skills/patterns/ui/accordions.md +0 -395
- package/skills/patterns/ui/cards.md +0 -299
- package/skills/patterns/ui/dropdowns.md +0 -476
- package/skills/patterns/ui/empty-states.md +0 -320
- package/skills/patterns/ui/forms.md +0 -405
- package/skills/patterns/ui/inputs.md +0 -319
- package/skills/patterns/ui/layouts.md +0 -282
- package/skills/patterns/ui/loading.md +0 -291
- package/skills/patterns/ui/modals.md +0 -338
- package/skills/patterns/ui/navigation.md +0 -374
- package/skills/patterns/ui/tables.md +0 -407
- package/skills/patterns/ui/toasts.md +0 -300
- package/skills/patterns/ui/tooltips.md +0 -396
- package/skills/patterns/utils/dates.md +0 -435
- package/skills/patterns/utils/errors.md +0 -451
- package/skills/patterns/utils/formatting.md +0 -345
- package/skills/patterns/utils/validation.md +0 -434
- package/templates/bootspring.config.js +0 -83
- package/templates/business/business-model-canvas.md +0 -246
- package/templates/business/business-plan.md +0 -266
- package/templates/business/competitive-analysis.md +0 -312
- package/templates/fundraising/data-room-checklist.md +0 -300
- package/templates/fundraising/investor-research.md +0 -243
- package/templates/fundraising/pitch-deck-outline.md +0 -253
- package/templates/legal/gdpr-checklist.md +0 -339
- package/templates/legal/privacy-policy.md +0 -285
- package/templates/legal/terms-of-service.md +0 -222
- package/templates/mcp.json +0 -9
package/cli/skill.js
CHANGED
|
@@ -5,8 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
const utils = require('../core/utils');
|
|
7
7
|
const entitlements = require('../core/entitlements');
|
|
8
|
+
const tierEnforcement = require('../core/tier-enforcement');
|
|
8
9
|
const telemetry = require('../core/telemetry');
|
|
9
|
-
const
|
|
10
|
+
const api = require('../core/api-client');
|
|
11
|
+
const auth = require('../core/auth');
|
|
12
|
+
|
|
13
|
+
// Note: skills module removed - all content fetched from API (thin client)
|
|
10
14
|
|
|
11
15
|
function trackTelemetry(event, payload) {
|
|
12
16
|
try {
|
|
@@ -16,234 +20,302 @@ function trackTelemetry(event, payload) {
|
|
|
16
20
|
}
|
|
17
21
|
}
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
// Use centralized tier badge formatting
|
|
24
|
+
const { formatTierBadge } = tierEnforcement;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Fetch skills list from API (thin client)
|
|
28
|
+
*/
|
|
29
|
+
async function fetchSkillsList(options = {}) {
|
|
30
|
+
if (!auth.isAuthenticated()) {
|
|
31
|
+
return { error: 'auth_required' };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const response = await api.listSkills(options);
|
|
36
|
+
return response;
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error.status === 401) {
|
|
39
|
+
return { error: 'auth_required' };
|
|
31
40
|
}
|
|
32
|
-
|
|
41
|
+
return { error: 'network_error', message: error.message };
|
|
33
42
|
}
|
|
34
43
|
}
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Fetch skill content from API (thin client)
|
|
47
|
+
*/
|
|
48
|
+
async function fetchSkillContent(skillId) {
|
|
49
|
+
if (!auth.isAuthenticated()) {
|
|
50
|
+
return { error: 'auth_required' };
|
|
51
|
+
}
|
|
41
52
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return;
|
|
53
|
+
try {
|
|
54
|
+
const response = await api.getSkillContent(skillId);
|
|
55
|
+
return response;
|
|
56
|
+
} catch (error) {
|
|
57
|
+
if (error.status === 403) {
|
|
58
|
+
return { error: 'upgrade_required', requiredTier: 'pro' };
|
|
59
|
+
}
|
|
60
|
+
if (error.status === 401) {
|
|
61
|
+
return { error: 'auth_required' };
|
|
62
|
+
}
|
|
63
|
+
if (error.status === 404) {
|
|
64
|
+
return { error: 'not_found' };
|
|
65
|
+
}
|
|
66
|
+
return { error: 'network_error', message: error.message };
|
|
45
67
|
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* List skills from API (thin client)
|
|
72
|
+
*/
|
|
73
|
+
async function listSkills(options = {}) {
|
|
74
|
+
const { tierFilter, category } = options;
|
|
46
75
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
76
|
+
// Check authentication
|
|
77
|
+
if (!auth.isAuthenticated()) {
|
|
78
|
+
console.log(`
|
|
79
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Skills${utils.COLORS.reset}
|
|
80
|
+
${utils.COLORS.red}Authentication required${utils.COLORS.reset}
|
|
50
81
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (denied.length > 0) {
|
|
55
|
-
utils.print.dim(denied[0].reason);
|
|
56
|
-
}
|
|
82
|
+
${utils.COLORS.dim}Skills are served from the API. Please log in:${utils.COLORS.reset}
|
|
83
|
+
${utils.COLORS.cyan}bootspring auth login${utils.COLORS.reset}
|
|
84
|
+
`);
|
|
57
85
|
return;
|
|
58
86
|
}
|
|
59
87
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
88
|
+
const tierLabel = tierFilter ? ` (${tierFilter} tier)` : '';
|
|
89
|
+
console.log(`
|
|
90
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Skills${utils.COLORS.reset}${tierLabel}
|
|
91
|
+
${utils.COLORS.dim}Code patterns served from API${utils.COLORS.reset}
|
|
92
|
+
`);
|
|
93
|
+
|
|
94
|
+
const spinner = utils.createSpinner('Loading skills...');
|
|
95
|
+
spinner.start();
|
|
96
|
+
|
|
97
|
+
const result = await fetchSkillsList({ category });
|
|
66
98
|
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
console.log(
|
|
70
|
-
|
|
99
|
+
if (result.error === 'auth_required') {
|
|
100
|
+
spinner.fail('Authentication required');
|
|
101
|
+
console.log(`${utils.COLORS.dim}Run: bootspring auth login${utils.COLORS.reset}`);
|
|
102
|
+
return;
|
|
71
103
|
}
|
|
72
|
-
|
|
73
|
-
|
|
104
|
+
|
|
105
|
+
if (result.error === 'network_error') {
|
|
106
|
+
spinner.fail('Failed to load skills');
|
|
107
|
+
console.log(`${utils.COLORS.dim}Check your internet connection.${utils.COLORS.reset}`);
|
|
108
|
+
return;
|
|
74
109
|
}
|
|
75
|
-
console.log('');
|
|
76
|
-
}
|
|
77
110
|
|
|
78
|
-
|
|
79
|
-
const {
|
|
80
|
-
includeExternal = false,
|
|
81
|
-
externalOnly = false,
|
|
82
|
-
limit = 20,
|
|
83
|
-
accessOptions = {}
|
|
84
|
-
} = options;
|
|
111
|
+
spinner.succeed(`Loaded ${result.skills?.length || 0} skills`);
|
|
85
112
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
113
|
+
// Group skills by category
|
|
114
|
+
const categories = {};
|
|
115
|
+
for (const skill of result.skills || []) {
|
|
116
|
+
// Apply tier filter if specified
|
|
117
|
+
if (tierFilter && skill.tier !== tierFilter) continue;
|
|
90
118
|
|
|
91
|
-
|
|
92
|
-
|
|
119
|
+
if (!categories[skill.category]) {
|
|
120
|
+
categories[skill.category] = [];
|
|
121
|
+
}
|
|
122
|
+
categories[skill.category].push(skill);
|
|
93
123
|
}
|
|
94
124
|
|
|
95
|
-
|
|
96
|
-
|
|
125
|
+
// Display by category
|
|
126
|
+
for (const [cat, catSkills] of Object.entries(categories).sort()) {
|
|
127
|
+
console.log(`\n${utils.COLORS.bold}${cat}${utils.COLORS.reset}`);
|
|
128
|
+
for (const skill of catSkills) {
|
|
129
|
+
const tierBadge = formatTierBadge(skill.tier);
|
|
130
|
+
const lockIcon = skill.accessible ? '' : ` ${utils.COLORS.red}🔒${utils.COLORS.reset}`;
|
|
131
|
+
const description = skill.description ? ` - ${skill.description}` : '';
|
|
132
|
+
console.log(` ${utils.COLORS.cyan}${skill.id}${utils.COLORS.reset} ${tierBadge}${lockIcon}${description}`);
|
|
133
|
+
}
|
|
97
134
|
}
|
|
98
135
|
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
136
|
+
const accessibleCount = (result.skills || []).filter(s => s.accessible).length;
|
|
137
|
+
const lockedCount = (result.skills || []).length - accessibleCount;
|
|
138
|
+
|
|
139
|
+
console.log(`\n${utils.COLORS.dim}${accessibleCount} skills available, ${lockedCount} locked${utils.COLORS.reset}`);
|
|
140
|
+
console.log(`${utils.COLORS.dim}Your tier: ${result.userTier || 'free'}${utils.COLORS.reset}`);
|
|
105
141
|
console.log(`${utils.COLORS.dim}Use "bootspring skill show <id>" to view a skill${utils.COLORS.reset}`);
|
|
106
142
|
}
|
|
107
143
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
144
|
+
/**
|
|
145
|
+
* Show skill content from API (thin client)
|
|
146
|
+
*/
|
|
147
|
+
async function showSkill(skillId, _options = {}) {
|
|
148
|
+
// Check authentication first
|
|
149
|
+
if (!auth.isAuthenticated()) {
|
|
150
|
+
console.log(`
|
|
151
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Skill: ${skillId}${utils.COLORS.reset}
|
|
152
|
+
${utils.COLORS.red}Authentication required${utils.COLORS.reset}
|
|
153
|
+
|
|
154
|
+
${utils.COLORS.dim}Skill content is served from the API. Please log in:${utils.COLORS.reset}
|
|
155
|
+
${utils.COLORS.cyan}bootspring auth login${utils.COLORS.reset}
|
|
156
|
+
`);
|
|
111
157
|
return;
|
|
112
158
|
}
|
|
113
159
|
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
maxChars,
|
|
119
|
-
accessOptions = {}
|
|
120
|
-
} = options;
|
|
160
|
+
const isMCP = utils.isMCPContext();
|
|
161
|
+
|
|
162
|
+
const spinner = utils.createSpinner('Loading skill...');
|
|
163
|
+
spinner.start();
|
|
121
164
|
|
|
122
|
-
const
|
|
123
|
-
const resolvedSkillId = metadata?.id || skillId;
|
|
124
|
-
const access = entitlements.checkSkillAccess(resolvedSkillId, accessOptions);
|
|
165
|
+
const result = await fetchSkillContent(skillId);
|
|
125
166
|
|
|
126
|
-
if (
|
|
167
|
+
if (result.error === 'auth_required') {
|
|
168
|
+
spinner.fail('Authentication required');
|
|
169
|
+
console.log(`${utils.COLORS.dim}Run: bootspring auth login${utils.COLORS.reset}`);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (result.error === 'upgrade_required') {
|
|
174
|
+
spinner.fail('Upgrade required');
|
|
127
175
|
trackTelemetry('premium_prompted', {
|
|
128
|
-
capability: '
|
|
129
|
-
skillId
|
|
130
|
-
|
|
131
|
-
tier: access.context?.tier,
|
|
132
|
-
reason: access.code
|
|
176
|
+
capability: 'premium_pattern',
|
|
177
|
+
skillId,
|
|
178
|
+
reason: 'upgrade_required'
|
|
133
179
|
});
|
|
134
|
-
|
|
180
|
+
console.log(tierEnforcement.getUpgradePrompt(`skill: ${skillId}`, result.requiredTier || 'pro'));
|
|
135
181
|
return;
|
|
136
182
|
}
|
|
137
183
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (!rawContent) {
|
|
141
|
-
utils.print.error(`Skill not found: ${skillId}`);
|
|
184
|
+
if (result.error === 'not_found') {
|
|
185
|
+
spinner.fail('Skill not found');
|
|
142
186
|
utils.print.dim('Try: bootspring skill list');
|
|
143
|
-
utils.print.dim('Or: bootspring skill search <query> --external');
|
|
144
187
|
return;
|
|
145
188
|
}
|
|
146
189
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
190
|
+
if (result.error === 'network_error') {
|
|
191
|
+
spinner.fail('Failed to load skill');
|
|
192
|
+
console.log(`${utils.COLORS.dim}Check your internet connection.${utils.COLORS.reset}`);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
spinner.succeed('Skill loaded');
|
|
197
|
+
|
|
198
|
+
const tierBadge = formatTierBadge(result.tier || 'free');
|
|
199
|
+
|
|
200
|
+
console.log(`
|
|
201
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}${result.name || skillId}${utils.COLORS.reset} ${tierBadge}
|
|
202
|
+
${utils.COLORS.dim}ID: ${result.id || skillId} | Tier: ${result.tier || 'free'}${utils.COLORS.reset}
|
|
203
|
+
`);
|
|
204
|
+
|
|
205
|
+
// Track successful access
|
|
206
|
+
trackTelemetry('skill_accessed', {
|
|
207
|
+
skillId: result.id || skillId,
|
|
208
|
+
tier: result.tier
|
|
151
209
|
});
|
|
152
210
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
211
|
+
// In MCP mode, output full content
|
|
212
|
+
if (isMCP) {
|
|
213
|
+
console.log(result.content);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// CLI mode - show content with truncation notice
|
|
218
|
+
const contentLines = result.content.split('\n');
|
|
219
|
+
const previewLines = contentLines.slice(0, 40);
|
|
220
|
+
const hasMore = contentLines.length > 40;
|
|
221
|
+
|
|
222
|
+
console.log(previewLines.join('\n'));
|
|
223
|
+
|
|
224
|
+
if (hasMore) {
|
|
225
|
+
console.log(`\n${utils.COLORS.dim}... (${contentLines.length - 40} more lines)${utils.COLORS.reset}`);
|
|
163
226
|
}
|
|
164
227
|
|
|
165
228
|
console.log(`
|
|
166
|
-
${utils.COLORS.
|
|
167
|
-
|
|
168
|
-
`);
|
|
229
|
+
${utils.COLORS.bold}Usage:${utils.COLORS.reset}
|
|
230
|
+
Copy the pattern above and adapt it to your project.
|
|
169
231
|
|
|
170
|
-
|
|
232
|
+
${utils.COLORS.yellow}${utils.COLORS.bold}Full Content in MCP Mode${utils.COLORS.reset}
|
|
233
|
+
${utils.COLORS.dim}With MCP integration, skills are available directly in your AI assistant.${utils.COLORS.reset}
|
|
234
|
+
${utils.COLORS.cyan}bootspring mcp start${utils.COLORS.reset}
|
|
235
|
+
`);
|
|
171
236
|
}
|
|
172
237
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
238
|
+
/**
|
|
239
|
+
* Search skills via API (thin client)
|
|
240
|
+
*/
|
|
241
|
+
async function searchSkills(query, options = {}) {
|
|
242
|
+
const { tierFilter } = options;
|
|
243
|
+
|
|
244
|
+
// Check authentication
|
|
245
|
+
if (!auth.isAuthenticated()) {
|
|
246
|
+
console.log(`
|
|
247
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}Search: "${query}"${utils.COLORS.reset}
|
|
248
|
+
${utils.COLORS.red}Authentication required${utils.COLORS.reset}
|
|
249
|
+
|
|
250
|
+
${utils.COLORS.dim}Skills are served from the API. Please log in:${utils.COLORS.reset}
|
|
251
|
+
${utils.COLORS.cyan}bootspring auth login${utils.COLORS.reset}
|
|
252
|
+
`);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const spinner = utils.createSpinner('Searching...');
|
|
257
|
+
spinner.start();
|
|
258
|
+
|
|
259
|
+
const result = await fetchSkillsList({ search: query });
|
|
260
|
+
|
|
261
|
+
if (result.error) {
|
|
262
|
+
spinner.fail('Search failed');
|
|
263
|
+
console.log(`${utils.COLORS.dim}${result.message || 'Check your internet connection.'}${utils.COLORS.reset}`);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
spinner.succeed('Search complete');
|
|
268
|
+
|
|
269
|
+
let skills = result.skills || [];
|
|
185
270
|
|
|
186
|
-
if
|
|
187
|
-
|
|
271
|
+
// Apply tier filter if specified
|
|
272
|
+
if (tierFilter) {
|
|
273
|
+
skills = skills.filter(s => s.tier === tierFilter);
|
|
188
274
|
}
|
|
189
|
-
const filtered = entitlements.filterAccessibleSkills(results, accessOptions);
|
|
190
|
-
results = filtered.allowed;
|
|
191
275
|
|
|
276
|
+
const tierLabel = tierFilter ? ` (${tierFilter} tier)` : '';
|
|
192
277
|
console.log(`
|
|
193
|
-
${utils.COLORS.cyan}${utils.COLORS.bold}Search Results${utils.COLORS.reset}
|
|
278
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}Search Results${utils.COLORS.reset}${tierLabel}
|
|
194
279
|
${utils.COLORS.dim}Query: "${query}"${utils.COLORS.reset}
|
|
195
280
|
`);
|
|
196
281
|
|
|
197
|
-
if (
|
|
282
|
+
if (skills.length === 0) {
|
|
198
283
|
utils.print.warning('No matching skills found');
|
|
199
284
|
utils.print.dim('Try: bootspring skill list');
|
|
200
285
|
return;
|
|
201
286
|
}
|
|
202
287
|
|
|
203
|
-
for (const
|
|
204
|
-
const
|
|
205
|
-
const
|
|
206
|
-
const description =
|
|
207
|
-
|
|
208
|
-
console.log(` ${color}${id}${utils.COLORS.reset} ${utils.COLORS.dim}[${source}]${utils.COLORS.reset}${description}`);
|
|
288
|
+
for (const skill of skills) {
|
|
289
|
+
const tierBadge = formatTierBadge(skill.tier);
|
|
290
|
+
const lockIcon = skill.accessible ? '' : ` ${utils.COLORS.red}🔒${utils.COLORS.reset}`;
|
|
291
|
+
const description = skill.description ? ` - ${skill.description}` : '';
|
|
292
|
+
console.log(` ${utils.COLORS.cyan}${skill.id}${utils.COLORS.reset} ${tierBadge}${lockIcon}${description}`);
|
|
209
293
|
}
|
|
210
294
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
295
|
+
const accessibleCount = skills.filter(s => s.accessible).length;
|
|
296
|
+
const lockedCount = skills.length - accessibleCount;
|
|
297
|
+
|
|
298
|
+
console.log(`\n${utils.COLORS.dim}${skills.length} match(es)${utils.COLORS.reset}`);
|
|
299
|
+
if (lockedCount > 0) {
|
|
300
|
+
console.log(`${utils.COLORS.dim}${lockedCount} result(s) require upgrade${utils.COLORS.reset}`);
|
|
301
|
+
console.log(`${utils.COLORS.dim}Run: bootspring billing upgrade${utils.COLORS.reset}`);
|
|
214
302
|
}
|
|
215
303
|
}
|
|
216
304
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
manifestUrl,
|
|
232
|
-
contentBaseUrl,
|
|
233
|
-
token,
|
|
234
|
-
timeoutMs,
|
|
235
|
-
cacheDir,
|
|
236
|
-
manifestPublicKey,
|
|
237
|
-
requireManifestSignature
|
|
238
|
-
});
|
|
239
|
-
spinner.succeed(`Synced ${result.fetched} external skills`);
|
|
240
|
-
if (result.skipped.length > 0) {
|
|
241
|
-
utils.print.warning(`Skipped ${result.skipped.length} skill(s): ${result.skipped.join(', ')}`);
|
|
242
|
-
}
|
|
243
|
-
utils.print.dim(`Cache: ${result.manifestPath}`);
|
|
244
|
-
} catch (error) {
|
|
245
|
-
spinner.fail(`Sync failed: ${error.message}`);
|
|
246
|
-
}
|
|
305
|
+
/**
|
|
306
|
+
* Sync is no longer needed - thin client fetches from API
|
|
307
|
+
* @deprecated
|
|
308
|
+
*/
|
|
309
|
+
async function syncCatalog() {
|
|
310
|
+
console.log(`
|
|
311
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}Sync Not Required${utils.COLORS.reset}
|
|
312
|
+
|
|
313
|
+
${utils.COLORS.dim}Skills are now served directly from the API.${utils.COLORS.reset}
|
|
314
|
+
${utils.COLORS.dim}No local sync needed - content is always up to date.${utils.COLORS.reset}
|
|
315
|
+
|
|
316
|
+
${utils.COLORS.bold}To view available skills:${utils.COLORS.reset}
|
|
317
|
+
${utils.COLORS.cyan}bootspring skill list${utils.COLORS.reset}
|
|
318
|
+
`);
|
|
247
319
|
}
|
|
248
320
|
|
|
249
321
|
function showHelp() {
|
|
@@ -257,36 +329,42 @@ ${utils.COLORS.cyan}Commands:${utils.COLORS.reset}
|
|
|
257
329
|
${utils.COLORS.cyan}list${utils.COLORS.reset} List built-in skills
|
|
258
330
|
${utils.COLORS.cyan}show${utils.COLORS.reset} <id> Show skill content
|
|
259
331
|
${utils.COLORS.cyan}search${utils.COLORS.reset} <query> Search skills
|
|
260
|
-
${utils.COLORS.cyan}sync${utils.COLORS.reset} Sync external catalog from remote manifest
|
|
261
332
|
|
|
262
333
|
${utils.COLORS.cyan}Options:${utils.COLORS.reset}
|
|
263
|
-
${utils.COLORS.cyan}--
|
|
264
|
-
${utils.COLORS.cyan}--
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
${utils.COLORS.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
${utils.COLORS.cyan}
|
|
274
|
-
${utils.COLORS.cyan}--token <value>${utils.COLORS.reset} Bearer token for remote catalog APIs
|
|
275
|
-
${utils.COLORS.cyan}--cache-dir <path>${utils.COLORS.reset} Override local skill cache directory
|
|
276
|
-
${utils.COLORS.cyan}--manifest-public-key <pem>${utils.COLORS.reset} Public key for manifest signature verification
|
|
277
|
-
${utils.COLORS.cyan}--require-signature <bool>${utils.COLORS.reset} Require remote manifest signature validation
|
|
334
|
+
${utils.COLORS.cyan}--tier-filter <tier>${utils.COLORS.reset} Filter by tier: free or pro
|
|
335
|
+
${utils.COLORS.cyan}--category <cat>${utils.COLORS.reset} Filter by category
|
|
336
|
+
|
|
337
|
+
${utils.COLORS.cyan}Tier Information:${utils.COLORS.reset}
|
|
338
|
+
Skills are labeled with their tier: ${utils.COLORS.green}[FREE]${utils.COLORS.reset} or ${utils.COLORS.yellow}[PRO]${utils.COLORS.reset}
|
|
339
|
+
- FREE tier patterns are available to all authenticated users
|
|
340
|
+
- PRO tier patterns require a Pro subscription
|
|
341
|
+
|
|
342
|
+
${utils.COLORS.cyan}Authentication:${utils.COLORS.reset}
|
|
343
|
+
All skill commands require authentication.
|
|
344
|
+
Run: ${utils.COLORS.cyan}bootspring auth login${utils.COLORS.reset}
|
|
278
345
|
|
|
279
346
|
${utils.COLORS.cyan}Examples:${utils.COLORS.reset}
|
|
280
347
|
bootspring skill list
|
|
281
|
-
bootspring skill list --
|
|
348
|
+
bootspring skill list --tier-filter=free
|
|
282
349
|
bootspring skill search auth
|
|
283
|
-
bootspring skill search vercel --external
|
|
284
350
|
bootspring skill show auth/clerk
|
|
285
|
-
bootspring skill show
|
|
286
|
-
bootspring skill sync --manifest-url https://api.bootspring.com/skills/manifest.json
|
|
351
|
+
bootspring skill show api/route-handler
|
|
287
352
|
`);
|
|
288
353
|
}
|
|
289
354
|
|
|
355
|
+
/**
|
|
356
|
+
* Normalize tier filter value
|
|
357
|
+
*/
|
|
358
|
+
function normalizeTierFilter(value) {
|
|
359
|
+
if (!value) return undefined;
|
|
360
|
+
const normalized = String(value).trim().toLowerCase();
|
|
361
|
+
if (normalized === 'free' || normalized === 'pro' || normalized === 'premium') {
|
|
362
|
+
// Treat 'premium' as 'pro' for filtering purposes
|
|
363
|
+
return normalized === 'premium' ? 'pro' : normalized;
|
|
364
|
+
}
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
|
|
290
368
|
/**
|
|
291
369
|
* Run skill command
|
|
292
370
|
*/
|
|
@@ -300,6 +378,10 @@ async function run(args) {
|
|
|
300
378
|
const parsedLimit = parsedArgs.limit ? Number(parsedArgs.limit) : 20;
|
|
301
379
|
const limit = Number.isFinite(parsedLimit) && parsedLimit > 0 ? parsedLimit : 20;
|
|
302
380
|
const maxChars = parsedArgs['max-chars'] ? Number(parsedArgs['max-chars']) : undefined;
|
|
381
|
+
|
|
382
|
+
// Parse tier filter (for list/search filtering) separately from access tier
|
|
383
|
+
const tierFilter = normalizeTierFilter(parsedArgs['tier-filter'] || parsedArgs['filter-tier']);
|
|
384
|
+
|
|
303
385
|
const accessOptions = {
|
|
304
386
|
mode: parsedArgs['access-mode'],
|
|
305
387
|
entitled: parsedArgs.entitled,
|
|
@@ -308,7 +390,7 @@ async function run(args) {
|
|
|
308
390
|
|
|
309
391
|
switch (subcommand) {
|
|
310
392
|
case 'list':
|
|
311
|
-
listSkills({
|
|
393
|
+
await listSkills({ tierFilter, category: parsedArgs.category });
|
|
312
394
|
break;
|
|
313
395
|
|
|
314
396
|
case 'show':
|
|
@@ -317,13 +399,7 @@ async function run(args) {
|
|
|
317
399
|
utils.print.dim('Usage: bootspring skill show <id>');
|
|
318
400
|
return;
|
|
319
401
|
}
|
|
320
|
-
showSkill(subargs[0], {
|
|
321
|
-
includeExternal: true,
|
|
322
|
-
summary: Boolean(parsedArgs.summary),
|
|
323
|
-
sections: parsedArgs.sections,
|
|
324
|
-
maxChars,
|
|
325
|
-
accessOptions
|
|
326
|
-
});
|
|
402
|
+
await showSkill(subargs[0], {});
|
|
327
403
|
break;
|
|
328
404
|
|
|
329
405
|
case 'search':
|
|
@@ -332,19 +408,11 @@ async function run(args) {
|
|
|
332
408
|
utils.print.dim('Usage: bootspring skill search <query>');
|
|
333
409
|
return;
|
|
334
410
|
}
|
|
335
|
-
searchSkills(subargs.join(' '), {
|
|
411
|
+
await searchSkills(subargs.join(' '), { tierFilter });
|
|
336
412
|
break;
|
|
337
413
|
|
|
338
414
|
case 'sync':
|
|
339
|
-
await syncCatalog(
|
|
340
|
-
manifestUrl: parsedArgs['manifest-url'],
|
|
341
|
-
contentBaseUrl: parsedArgs['content-base-url'],
|
|
342
|
-
token: parsedArgs.token,
|
|
343
|
-
timeoutMs: parsedArgs.timeout,
|
|
344
|
-
cacheDir: parsedArgs['cache-dir'],
|
|
345
|
-
manifestPublicKey: parsedArgs['manifest-public-key'],
|
|
346
|
-
requireManifestSignature: parsedArgs['require-signature']
|
|
347
|
-
});
|
|
415
|
+
await syncCatalog();
|
|
348
416
|
break;
|
|
349
417
|
|
|
350
418
|
case 'help':
|
|
@@ -355,13 +423,7 @@ async function run(args) {
|
|
|
355
423
|
|
|
356
424
|
default:
|
|
357
425
|
// Shortcut: `bootspring skill auth/clerk`
|
|
358
|
-
showSkill(subcommand, {
|
|
359
|
-
includeExternal: true,
|
|
360
|
-
summary: Boolean(parsedArgs.summary),
|
|
361
|
-
sections: parsedArgs.sections,
|
|
362
|
-
maxChars,
|
|
363
|
-
accessOptions
|
|
364
|
-
});
|
|
426
|
+
await showSkill(subcommand, {});
|
|
365
427
|
}
|
|
366
428
|
}
|
|
367
429
|
|