skrypt-ai 0.8.0 → 0.8.1
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/dist/auth/index.js +6 -0
- package/dist/binding/binder.d.ts +5 -0
- package/dist/binding/binder.js +63 -0
- package/dist/binding/detector.d.ts +5 -0
- package/dist/binding/detector.js +51 -0
- package/dist/binding/doc-parser.d.ts +9 -0
- package/dist/binding/doc-parser.js +138 -0
- package/dist/binding/extractor.d.ts +14 -0
- package/dist/binding/extractor.js +39 -0
- package/dist/binding/index.d.ts +5 -0
- package/dist/binding/index.js +5 -0
- package/dist/binding/types.d.ts +74 -0
- package/dist/binding/types.js +1 -0
- package/dist/claims/extractor.d.ts +13 -0
- package/dist/claims/extractor.js +138 -0
- package/dist/claims/index.d.ts +4 -0
- package/dist/claims/index.js +4 -0
- package/dist/claims/reporter.d.ts +9 -0
- package/dist/claims/reporter.js +65 -0
- package/dist/claims/store.d.ts +13 -0
- package/dist/claims/store.js +51 -0
- package/dist/claims/types.d.ts +34 -0
- package/dist/claims/types.js +1 -0
- package/dist/cli.js +516 -56
- package/dist/commands/bind.d.ts +2 -0
- package/dist/commands/bind.js +139 -0
- package/dist/commands/claims.d.ts +2 -0
- package/dist/commands/claims.js +84 -0
- package/dist/commands/coverage.d.ts +2 -0
- package/dist/commands/coverage.js +61 -0
- package/dist/commands/generate/index.js +5 -0
- package/dist/commands/generate/scan.js +33 -14
- package/dist/commands/generate/write.d.ts +7 -0
- package/dist/commands/generate/write.js +65 -1
- package/dist/commands/import.js +12 -3
- package/dist/commands/init.js +68 -5
- package/dist/commands/monitor.d.ts +15 -0
- package/dist/commands/monitor.js +2 -2
- package/dist/commands/mutate.d.ts +2 -0
- package/dist/commands/mutate.js +177 -0
- package/dist/config/types.js +2 -2
- package/dist/coverage/calculator.d.ts +7 -0
- package/dist/coverage/calculator.js +86 -0
- package/dist/coverage/index.d.ts +3 -0
- package/dist/coverage/index.js +3 -0
- package/dist/coverage/reporter.d.ts +9 -0
- package/dist/coverage/reporter.js +65 -0
- package/dist/coverage/types.d.ts +36 -0
- package/dist/coverage/types.js +1 -0
- package/dist/generator/generator.d.ts +3 -1
- package/dist/generator/generator.js +137 -23
- package/dist/generator/mdx-serializer.js +3 -2
- package/dist/generator/organizer.d.ts +5 -1
- package/dist/generator/organizer.js +29 -14
- package/dist/generator/types.d.ts +6 -0
- package/dist/generator/writer.js +7 -2
- package/dist/github/org-discovery.js +5 -0
- package/dist/importers/mintlify.js +4 -3
- package/dist/llm/anthropic-client.js +1 -0
- package/dist/llm/index.d.ts +15 -0
- package/dist/llm/index.js +148 -29
- package/dist/llm/openai-client.js +2 -0
- package/dist/mutation/index.d.ts +4 -0
- package/dist/mutation/index.js +4 -0
- package/dist/mutation/mutator.d.ts +5 -0
- package/dist/mutation/mutator.js +101 -0
- package/dist/mutation/reporter.d.ts +14 -0
- package/dist/mutation/reporter.js +66 -0
- package/dist/mutation/runner.d.ts +9 -0
- package/dist/mutation/runner.js +70 -0
- package/dist/mutation/types.d.ts +51 -0
- package/dist/mutation/types.js +1 -0
- package/dist/qa/checks.d.ts +1 -0
- package/dist/qa/checks.js +47 -0
- package/dist/qa/index.js +2 -1
- package/dist/scanner/index.js +78 -11
- package/dist/scanner/typescript.js +42 -31
- package/dist/sentry.d.ts +3 -0
- package/dist/sentry.js +28 -0
- package/dist/template/docs.json +6 -3
- package/dist/template/next.config.mjs +15 -1
- package/dist/template/package.json +4 -3
- package/dist/template/public/docs-schema.json +257 -0
- package/dist/template/sentry.client.config.ts +12 -0
- package/dist/template/sentry.edge.config.ts +7 -0
- package/dist/template/sentry.server.config.ts +7 -0
- package/dist/template/src/app/docs/[...slug]/page.tsx +11 -5
- package/dist/template/src/app/docs/layout.tsx +2 -4
- package/dist/template/src/app/global-error.tsx +60 -0
- package/dist/template/src/app/layout.tsx +7 -16
- package/dist/template/src/app/page.tsx +2 -5
- package/dist/template/src/components/ai-chat-impl.tsx +1 -1
- package/dist/template/src/components/docs-layout.tsx +1 -15
- package/dist/template/src/components/footer.tsx +95 -19
- package/dist/template/src/components/header.tsx +1 -1
- package/dist/template/src/components/search-dialog.tsx +5 -0
- package/dist/template/src/instrumentation.ts +11 -0
- package/dist/template/src/lib/docs-config.ts +235 -0
- package/dist/template/src/lib/fonts.ts +3 -3
- package/dist/testing/runner.js +8 -1
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -1,32 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
-
import { generateCommand } from './commands/generate/index.js';
|
|
4
|
-
import { initCommand } from './commands/init.js';
|
|
5
|
-
import { watchCommand } from './commands/watch.js';
|
|
6
|
-
import { autofixCommand } from './commands/autofix.js';
|
|
7
|
-
import { reviewPRCommand } from './commands/review-pr.js';
|
|
8
|
-
import { lintCommand } from './commands/lint.js';
|
|
9
|
-
import { qaCommand } from './commands/qa.js';
|
|
10
|
-
import { checkLinksCommand } from './commands/check-links.js';
|
|
11
|
-
import { mcpCommand } from './commands/mcp.js';
|
|
12
|
-
import { versionCommand } from './commands/version.js';
|
|
13
|
-
import { i18nCommand } from './commands/i18n.js';
|
|
14
|
-
import { monitorCommand } from './commands/monitor.js';
|
|
15
|
-
import { sdkCommand } from './commands/sdk.js';
|
|
16
|
-
import { ghActionCommand } from './commands/gh-action.js';
|
|
17
|
-
import { llmsTxtCommand } from './commands/llms-txt.js';
|
|
18
|
-
import { loginCommand, logoutCommand, whoamiCommand } from './commands/login.js';
|
|
19
|
-
import { cronCommand } from './commands/cron.js';
|
|
20
|
-
import { deployCommand } from './commands/deploy.js';
|
|
21
|
-
import { testCommand } from './commands/test.js';
|
|
22
|
-
import { securityCommand } from './commands/security.js';
|
|
23
|
-
import { importCommand } from './commands/import.js';
|
|
24
|
-
import { healCommand } from './commands/heal.js';
|
|
25
|
-
import { auditCommand } from './commands/audit.js';
|
|
26
|
-
import { refreshCommand } from './commands/refresh.js';
|
|
27
|
-
import { reviewCommand } from './commands/review.js';
|
|
28
|
-
import { configCommand } from './commands/config.js';
|
|
29
|
-
import { handlePostAction } from './next-actions/index.js';
|
|
30
3
|
import { createRequire } from 'module';
|
|
31
4
|
process.on('uncaughtException', (err) => {
|
|
32
5
|
console.error('\x1b[31mFatal error:\x1b[0m', err.message);
|
|
@@ -42,6 +15,24 @@ process.on('unhandledRejection', (reason) => {
|
|
|
42
15
|
});
|
|
43
16
|
const require = createRequire(import.meta.url);
|
|
44
17
|
const { version: VERSION } = require('../package.json');
|
|
18
|
+
/** Lazily initialize Sentry — called once on first real command invocation */
|
|
19
|
+
let sentryInitialized = false;
|
|
20
|
+
async function ensureSentry() {
|
|
21
|
+
if (sentryInitialized)
|
|
22
|
+
return;
|
|
23
|
+
sentryInitialized = true;
|
|
24
|
+
const { initSentry } = await import('./sentry.js');
|
|
25
|
+
initSentry();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Extract the action handler from a Commander Command instance.
|
|
29
|
+
* Commander stores it as `_actionHandler` (not in public types).
|
|
30
|
+
*/
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
+
function getAction(cmd) {
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
|
+
return cmd._actionHandler;
|
|
35
|
+
}
|
|
45
36
|
function semverNewer(latest, current) {
|
|
46
37
|
const parse = (v) => v.split('.').map(Number);
|
|
47
38
|
const [lMaj, lMin, lPatch] = parse(latest);
|
|
@@ -76,35 +67,504 @@ program
|
|
|
76
67
|
.description('AI-powered documentation generator with code examples')
|
|
77
68
|
.version(VERSION)
|
|
78
69
|
.hook('postAction', async (_thisCommand, actionCommand) => {
|
|
70
|
+
const { handlePostAction } = await import('./next-actions/index.js');
|
|
79
71
|
await handlePostAction(actionCommand.name());
|
|
80
72
|
await checkForUpdates();
|
|
81
73
|
});
|
|
82
|
-
|
|
83
|
-
program
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
program
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
74
|
+
// ── init ──────────────────────────────────────────────────────────────
|
|
75
|
+
program
|
|
76
|
+
.command('init')
|
|
77
|
+
.description('Initialize a new documentation site')
|
|
78
|
+
.argument('[directory]', 'Target directory', '.')
|
|
79
|
+
.option('--name <name>', 'Project name', 'my-docs')
|
|
80
|
+
.option('--color <hex>', 'Primary brand color (hex, e.g. "#FF5733")')
|
|
81
|
+
.option('--logo <url-or-path>', 'Logo URL or local file path')
|
|
82
|
+
.option('--favicon <url-or-path>', 'Favicon URL or local file path')
|
|
83
|
+
.action(async (directory, options) => {
|
|
84
|
+
await ensureSentry();
|
|
85
|
+
const mod = await import('./commands/init.js');
|
|
86
|
+
await getAction(mod.initCommand)(directory, options);
|
|
87
|
+
});
|
|
88
|
+
// ── generate ──────────────────────────────────────────────────────────
|
|
89
|
+
program
|
|
90
|
+
.command('generate')
|
|
91
|
+
.description('Generate documentation with code examples')
|
|
92
|
+
.argument('[sources...]', 'Source directories to scan (use dir:Label for labels)')
|
|
93
|
+
.option('-o, --output <dir>', 'Output directory')
|
|
94
|
+
.option('-c, --config <file>', 'Config file path')
|
|
95
|
+
.option('--provider <name>', 'LLM provider (deepseek, openai, anthropic, google, ollama, openrouter)')
|
|
96
|
+
.option('--model <name>', 'LLM model name')
|
|
97
|
+
.option('--base-url <url>', 'Custom API base URL (for Ollama or proxies)')
|
|
98
|
+
.option('--dry-run', 'Scan only, do not generate docs')
|
|
99
|
+
.option('--multi-lang', 'Generate TypeScript + Python examples')
|
|
100
|
+
.option('--by-topic', 'Organize output by topic instead of file')
|
|
101
|
+
.option('--openapi <file>', 'Include OpenAPI spec file for API Playground')
|
|
102
|
+
.option('--public-only', 'Only document exported/public APIs')
|
|
103
|
+
.option('--exclude <patterns...>', 'Exclude patterns (files, names, or name:pattern)')
|
|
104
|
+
.option('--llms-txt', 'Generate llms.txt for Answer Engine Optimization (AEO)')
|
|
105
|
+
.option('--project-name <name>', 'Project name for llms.txt header')
|
|
106
|
+
.option('--org <name>', 'GitHub organization to discover repos from')
|
|
107
|
+
.option('--repos <list>', 'Comma-separated list of repos to include (with --org)')
|
|
108
|
+
.option('--exclude-repos <list>', 'Comma-separated list of repos to exclude (with --org)')
|
|
109
|
+
.option('--verify', 'Verify generated code examples by running them (Pro)')
|
|
110
|
+
.option('--env-file <file>', 'Load environment variables for code verification')
|
|
111
|
+
.option('--smart-structure', 'Organize docs by user journey instead of file structure (Pro)')
|
|
112
|
+
.option('--max-verify-iterations <n>', 'Max re-generation attempts for failing snippets', '2')
|
|
113
|
+
.option('--no-agents-md', 'Skip AGENTS.md / CLAUDE.md generation')
|
|
114
|
+
.action(async (sources, options) => {
|
|
115
|
+
await ensureSentry();
|
|
116
|
+
const mod = await import('./commands/generate/index.js');
|
|
117
|
+
await getAction(mod.generateCommand)(sources, options);
|
|
118
|
+
});
|
|
119
|
+
// ── watch ─────────────────────────────────────────────────────────────
|
|
120
|
+
program
|
|
121
|
+
.command('watch')
|
|
122
|
+
.description('Watch source files and regenerate docs on changes')
|
|
123
|
+
.argument('[sources...]', 'Source directories to watch')
|
|
124
|
+
.option('-o, --output <dir>', 'Output directory')
|
|
125
|
+
.option('-c, --config <file>', 'Config file path')
|
|
126
|
+
.option('--provider <name>', 'LLM provider')
|
|
127
|
+
.option('--model <name>', 'LLM model name')
|
|
128
|
+
.option('--debounce <ms>', 'Debounce time in milliseconds', '1000')
|
|
129
|
+
.action(async (sources, options) => {
|
|
130
|
+
await ensureSentry();
|
|
131
|
+
const mod = await import('./commands/watch.js');
|
|
132
|
+
await getAction(mod.watchCommand)(sources, options);
|
|
133
|
+
});
|
|
134
|
+
// ── autofix ───────────────────────────────────────────────────────────
|
|
135
|
+
program
|
|
136
|
+
.command('autofix')
|
|
137
|
+
.description('Auto-fix broken code examples in documentation')
|
|
138
|
+
.argument('<file>', 'Documentation file to fix (markdown/mdx)')
|
|
139
|
+
.option('-c, --config <file>', 'Config file path')
|
|
140
|
+
.option('--provider <name>', 'LLM provider')
|
|
141
|
+
.option('--model <name>', 'LLM model')
|
|
142
|
+
.option('--max-iterations <n>', 'Max fix attempts per example', '3')
|
|
143
|
+
.option('--dry-run', 'Show fixes without writing')
|
|
144
|
+
.option('--language <lang>', 'Force language for validation')
|
|
145
|
+
.action(async (file, options) => {
|
|
146
|
+
await ensureSentry();
|
|
147
|
+
const mod = await import('./commands/autofix.js');
|
|
148
|
+
await getAction(mod.autofixCommand)(file, options);
|
|
149
|
+
});
|
|
150
|
+
// ── review-pr ─────────────────────────────────────────────────────────
|
|
151
|
+
program
|
|
152
|
+
.command('review-pr')
|
|
153
|
+
.description('Review a GitHub PR for documentation issues')
|
|
154
|
+
.argument('<pr-url>', 'GitHub PR URL (e.g., https://github.com/owner/repo/pull/123)')
|
|
155
|
+
.option('--inline', 'Post inline comments instead of a single comment')
|
|
156
|
+
.option('--dry-run', 'Show issues without posting comments')
|
|
157
|
+
.option('--token <token>', 'GitHub token (or use GITHUB_TOKEN env var)')
|
|
158
|
+
.action(async (prUrl, options) => {
|
|
159
|
+
await ensureSentry();
|
|
160
|
+
const mod = await import('./commands/review-pr.js');
|
|
161
|
+
await getAction(mod.reviewPRCommand)(prUrl, options);
|
|
162
|
+
});
|
|
163
|
+
// ── lint ──────────────────────────────────────────────────────────────
|
|
164
|
+
program
|
|
165
|
+
.command('lint')
|
|
166
|
+
.description('Lint documentation files for common issues')
|
|
167
|
+
.argument('[path]', 'Directory or file to lint', '.')
|
|
168
|
+
.option('--fix', 'Attempt to fix issues automatically')
|
|
169
|
+
.option('-c, --config <file>', 'Config file with custom rules')
|
|
170
|
+
.action(async (path, options) => {
|
|
171
|
+
await ensureSentry();
|
|
172
|
+
const mod = await import('./commands/lint.js');
|
|
173
|
+
await getAction(mod.lintCommand)(path, options);
|
|
174
|
+
});
|
|
175
|
+
// ── qa ────────────────────────────────────────────────────────────────
|
|
176
|
+
program
|
|
177
|
+
.command('qa')
|
|
178
|
+
.description('Run quality assurance checks on documentation')
|
|
179
|
+
.argument('<dir>', 'Documentation directory to check')
|
|
180
|
+
.option('--strict', 'Fail on warnings (not just errors)')
|
|
181
|
+
.option('--fix', 'Auto-fix safe issues before reporting')
|
|
182
|
+
.action(async (dir, options) => {
|
|
183
|
+
await ensureSentry();
|
|
184
|
+
const mod = await import('./commands/qa.js');
|
|
185
|
+
await getAction(mod.qaCommand)(dir, options);
|
|
186
|
+
});
|
|
187
|
+
// ── check-links ───────────────────────────────────────────────────────
|
|
188
|
+
program
|
|
189
|
+
.command('check-links')
|
|
190
|
+
.description('Check for broken links in documentation')
|
|
191
|
+
.argument('[path]', 'Directory to check', '.')
|
|
192
|
+
.option('--external', 'Also check external links (slower)')
|
|
193
|
+
.option('--timeout <ms>', 'Timeout for external links', '5000')
|
|
194
|
+
.action(async (path, options) => {
|
|
195
|
+
await ensureSentry();
|
|
196
|
+
const mod = await import('./commands/check-links.js');
|
|
197
|
+
await getAction(mod.checkLinksCommand)(path, options);
|
|
198
|
+
});
|
|
199
|
+
// ── mcp ───────────────────────────────────────────────────────────────
|
|
200
|
+
program
|
|
201
|
+
.command('mcp')
|
|
202
|
+
.description('Start MCP server for AI tools or generate MCP manifest')
|
|
203
|
+
.argument('[path]', 'Documentation directory', '.')
|
|
204
|
+
.option('-p, --port <port>', 'Server port', '3100')
|
|
205
|
+
.option('-h, --host <host>', 'Server host', 'localhost')
|
|
206
|
+
.option('-o, --output <file>', 'Output manifest to file instead of starting server')
|
|
207
|
+
.option('-t, --token <token>', 'Bearer token for authenticating MCP requests')
|
|
208
|
+
.action(async (path, options) => {
|
|
209
|
+
await ensureSentry();
|
|
210
|
+
const mod = await import('./commands/mcp.js');
|
|
211
|
+
await getAction(mod.mcpCommand)(path, options);
|
|
212
|
+
});
|
|
213
|
+
// ── version (subcommands) ─────────────────────────────────────────────
|
|
214
|
+
{
|
|
215
|
+
const versionCmd = program
|
|
216
|
+
.command('version')
|
|
217
|
+
.description('Manage documentation versions');
|
|
218
|
+
versionCmd.hook('preAction', async () => {
|
|
219
|
+
await ensureSentry();
|
|
220
|
+
});
|
|
221
|
+
versionCmd.hook('preSubcommand', async () => {
|
|
222
|
+
await ensureSentry();
|
|
223
|
+
});
|
|
224
|
+
versionCmd
|
|
225
|
+
.command('list')
|
|
226
|
+
.description('List all versions')
|
|
227
|
+
.argument('[docs-path]', 'Documentation directory', './docs')
|
|
228
|
+
.action(async (docsPath) => {
|
|
229
|
+
const mod = await import('./commands/version.js');
|
|
230
|
+
const cmd = mod.versionCommand.commands.find(c => c.name() === 'list');
|
|
231
|
+
await getAction(cmd)(docsPath);
|
|
232
|
+
});
|
|
233
|
+
versionCmd
|
|
234
|
+
.command('create')
|
|
235
|
+
.description('Create a new version from current docs')
|
|
236
|
+
.argument('<version>', 'Version name (e.g., v1, v2.0)')
|
|
237
|
+
.argument('[docs-path]', 'Documentation directory', './docs')
|
|
238
|
+
.option('--from <version>', 'Copy from existing version instead of current')
|
|
239
|
+
.action(async (version, docsPath, options) => {
|
|
240
|
+
const mod = await import('./commands/version.js');
|
|
241
|
+
const cmd = mod.versionCommand.commands.find(c => c.name() === 'create');
|
|
242
|
+
await getAction(cmd)(version, docsPath, options);
|
|
243
|
+
});
|
|
244
|
+
versionCmd
|
|
245
|
+
.command('set-current')
|
|
246
|
+
.description('Set the current/default version')
|
|
247
|
+
.argument('<version>', 'Version to set as current')
|
|
248
|
+
.argument('[docs-path]', 'Documentation directory', './docs')
|
|
249
|
+
.action(async (version, docsPath) => {
|
|
250
|
+
const mod = await import('./commands/version.js');
|
|
251
|
+
const cmd = mod.versionCommand.commands.find(c => c.name() === 'set-current');
|
|
252
|
+
await getAction(cmd)(version, docsPath);
|
|
253
|
+
});
|
|
254
|
+
versionCmd
|
|
255
|
+
.command('delete')
|
|
256
|
+
.description('Delete a version')
|
|
257
|
+
.argument('<version>', 'Version to delete')
|
|
258
|
+
.argument('[docs-path]', 'Documentation directory', './docs')
|
|
259
|
+
.option('--force', 'Skip confirmation')
|
|
260
|
+
.action(async (version, docsPath, options) => {
|
|
261
|
+
const mod = await import('./commands/version.js');
|
|
262
|
+
const cmd = mod.versionCommand.commands.find(c => c.name() === 'delete');
|
|
263
|
+
await getAction(cmd)(version, docsPath, options);
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
// ── i18n (subcommands) ────────────────────────────────────────────────
|
|
267
|
+
{
|
|
268
|
+
const i18nCmd = program
|
|
269
|
+
.command('i18n')
|
|
270
|
+
.description('Manage documentation translations');
|
|
271
|
+
i18nCmd.hook('preSubcommand', async () => {
|
|
272
|
+
await ensureSentry();
|
|
273
|
+
});
|
|
274
|
+
i18nCmd
|
|
275
|
+
.command('init')
|
|
276
|
+
.description('Initialize i18n for documentation')
|
|
277
|
+
.argument('[docs-path]', 'Documentation directory', './docs')
|
|
278
|
+
.option('--default <locale>', 'Default locale', 'en')
|
|
279
|
+
.action(async (docsPath, options) => {
|
|
280
|
+
const mod = await import('./commands/i18n.js');
|
|
281
|
+
const cmd = mod.i18nCommand.commands.find(c => c.name() === 'init');
|
|
282
|
+
await getAction(cmd)(docsPath, options);
|
|
283
|
+
});
|
|
284
|
+
i18nCmd
|
|
285
|
+
.command('add')
|
|
286
|
+
.description('Add a new locale')
|
|
287
|
+
.argument('<locale>', 'Locale code (e.g., ja, fr, de)')
|
|
288
|
+
.argument('[docs-path]', 'Documentation directory', './docs')
|
|
289
|
+
.action(async (locale, docsPath) => {
|
|
290
|
+
const mod = await import('./commands/i18n.js');
|
|
291
|
+
const cmd = mod.i18nCommand.commands.find(c => c.name() === 'add');
|
|
292
|
+
await getAction(cmd)(locale, docsPath);
|
|
293
|
+
});
|
|
294
|
+
i18nCmd
|
|
295
|
+
.command('status')
|
|
296
|
+
.description('Show translation status')
|
|
297
|
+
.argument('[docs-path]', 'Documentation directory', './docs')
|
|
298
|
+
.action(async (docsPath) => {
|
|
299
|
+
const mod = await import('./commands/i18n.js');
|
|
300
|
+
const cmd = mod.i18nCommand.commands.find(c => c.name() === 'status');
|
|
301
|
+
await getAction(cmd)(docsPath);
|
|
302
|
+
});
|
|
303
|
+
i18nCmd
|
|
304
|
+
.command('missing')
|
|
305
|
+
.description('List missing translations for a locale')
|
|
306
|
+
.argument('<locale>', 'Locale to check')
|
|
307
|
+
.argument('[docs-path]', 'Documentation directory', './docs')
|
|
308
|
+
.action(async (locale, docsPath) => {
|
|
309
|
+
const mod = await import('./commands/i18n.js');
|
|
310
|
+
const cmd = mod.i18nCommand.commands.find(c => c.name() === 'missing');
|
|
311
|
+
await getAction(cmd)(locale, docsPath);
|
|
312
|
+
});
|
|
313
|
+
i18nCmd
|
|
314
|
+
.command('extract')
|
|
315
|
+
.description('Extract strings for translation')
|
|
316
|
+
.argument('[docs-path]', 'Documentation directory', './docs')
|
|
317
|
+
.option('-o, --output <file>', 'Output file', 'strings.json')
|
|
318
|
+
.action(async (docsPath, options) => {
|
|
319
|
+
const mod = await import('./commands/i18n.js');
|
|
320
|
+
const cmd = mod.i18nCommand.commands.find(c => c.name() === 'extract');
|
|
321
|
+
await getAction(cmd)(docsPath, options);
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
// ── monitor ───────────────────────────────────────────────────────────
|
|
325
|
+
program
|
|
326
|
+
.command('monitor')
|
|
327
|
+
.description('Monitor codebase for changes and suggest documentation updates')
|
|
328
|
+
.argument('[repo-path]', 'Repository path', '.')
|
|
329
|
+
.option('--since <ref>', 'Git ref to compare against', 'HEAD~10')
|
|
330
|
+
.option('-o, --output <file>', 'Output suggestions to JSON file')
|
|
331
|
+
.option('--provider <name>', 'LLM provider')
|
|
332
|
+
.option('--model <name>', 'LLM model')
|
|
333
|
+
.option('--auto-fix', 'Automatically generate documentation for suggestions')
|
|
334
|
+
.option('--create-pr', 'Create a GitHub PR with changes')
|
|
335
|
+
.option('--dry-run', 'Show what would be done without making changes')
|
|
336
|
+
.action(async (repoPath, options) => {
|
|
337
|
+
await ensureSentry();
|
|
338
|
+
const mod = await import('./commands/monitor.js');
|
|
339
|
+
await getAction(mod.monitorCommand)(repoPath, options);
|
|
340
|
+
});
|
|
341
|
+
// ── sdk ───────────────────────────────────────────────────────────────
|
|
342
|
+
program
|
|
343
|
+
.command('sdk')
|
|
344
|
+
.description('Generate SDK code samples from OpenAPI spec')
|
|
345
|
+
.argument('<spec>', 'Path to OpenAPI/Swagger spec file (JSON or YAML)')
|
|
346
|
+
.option('-o, --output <dir>', 'Output directory', './docs/sdk')
|
|
347
|
+
.option('-l, --languages <list>', 'Languages to generate (comma-separated)', 'typescript,python,curl')
|
|
348
|
+
.option('--provider <name>', 'LLM provider for enhanced samples')
|
|
349
|
+
.option('--model <name>', 'LLM model')
|
|
350
|
+
.option('--format <type>', 'Output format (markdown or json)', 'markdown')
|
|
351
|
+
.action(async (specPath, options) => {
|
|
352
|
+
await ensureSentry();
|
|
353
|
+
const mod = await import('./commands/sdk.js');
|
|
354
|
+
await getAction(mod.sdkCommand)(specPath, options);
|
|
355
|
+
});
|
|
356
|
+
// ── gh-action ─────────────────────────────────────────────────────────
|
|
357
|
+
program
|
|
358
|
+
.command('gh-action')
|
|
359
|
+
.description('Generate GitHub Action workflow for documentation CI/CD')
|
|
360
|
+
.argument('[repo-path]', 'Repository path', '.')
|
|
361
|
+
.option('-f, --force', 'Overwrite existing workflow')
|
|
362
|
+
.action(async (repoPath, options) => {
|
|
363
|
+
await ensureSentry();
|
|
364
|
+
const mod = await import('./commands/gh-action.js');
|
|
365
|
+
await getAction(mod.ghActionCommand)(repoPath, options);
|
|
366
|
+
});
|
|
367
|
+
// ── llms-txt ──────────────────────────────────────────────────────────
|
|
368
|
+
program
|
|
369
|
+
.command('llms-txt')
|
|
370
|
+
.description('Generate llms.txt and llms-full.txt for AI discoverability')
|
|
371
|
+
.argument('[docs-path]', 'Path to documentation directory', './docs')
|
|
372
|
+
.option('-o, --output <dir>', 'Output directory', './public')
|
|
373
|
+
.option('--base-url <url>', 'Base URL for documentation', 'https://docs.example.com')
|
|
374
|
+
.option('--title <title>', 'Documentation title', 'Documentation')
|
|
375
|
+
.option('--description <desc>', 'Documentation description', 'API and usage documentation')
|
|
376
|
+
.action(async (docsPath, options) => {
|
|
377
|
+
await ensureSentry();
|
|
378
|
+
const mod = await import('./commands/llms-txt.js');
|
|
379
|
+
await getAction(mod.llmsTxtCommand)(docsPath, options);
|
|
380
|
+
});
|
|
381
|
+
// ── login ─────────────────────────────────────────────────────────────
|
|
382
|
+
program
|
|
383
|
+
.command('login')
|
|
384
|
+
.description('Login to Skrypt Pro')
|
|
385
|
+
.option('--key <api-key>', 'API key (or set SKRYPT_API_KEY env var)')
|
|
386
|
+
.action(async (options) => {
|
|
387
|
+
await ensureSentry();
|
|
388
|
+
const mod = await import('./commands/login.js');
|
|
389
|
+
await getAction(mod.loginCommand)(options);
|
|
390
|
+
});
|
|
391
|
+
// ── logout ────────────────────────────────────────────────────────────
|
|
392
|
+
program
|
|
393
|
+
.command('logout')
|
|
394
|
+
.description('Logout from Skrypt')
|
|
395
|
+
.action(async () => {
|
|
396
|
+
await ensureSentry();
|
|
397
|
+
const mod = await import('./commands/login.js');
|
|
398
|
+
await getAction(mod.logoutCommand)();
|
|
399
|
+
});
|
|
400
|
+
// ── whoami ────────────────────────────────────────────────────────────
|
|
401
|
+
program
|
|
402
|
+
.command('whoami')
|
|
403
|
+
.description('Show current login status')
|
|
404
|
+
.action(async () => {
|
|
405
|
+
await ensureSentry();
|
|
406
|
+
const mod = await import('./commands/login.js');
|
|
407
|
+
await getAction(mod.whoamiCommand)();
|
|
408
|
+
});
|
|
409
|
+
// ── cron ──────────────────────────────────────────────────────────────
|
|
410
|
+
program
|
|
411
|
+
.command('cron')
|
|
412
|
+
.description('Set up automated documentation updates with GitHub Actions')
|
|
413
|
+
.argument('[repo-path]', 'Repository path', '.')
|
|
414
|
+
.option('-s, --schedule <cron>', 'Cron schedule (default: daily at 2am UTC)', '0 2 * * *')
|
|
415
|
+
.option('-f, --force', 'Overwrite existing workflow')
|
|
416
|
+
.action(async (repoPath, options) => {
|
|
417
|
+
await ensureSentry();
|
|
418
|
+
const mod = await import('./commands/cron.js');
|
|
419
|
+
await getAction(mod.cronCommand)(repoPath, options);
|
|
420
|
+
});
|
|
421
|
+
// ── deploy ────────────────────────────────────────────────────────────
|
|
422
|
+
program
|
|
423
|
+
.command('deploy')
|
|
424
|
+
.description('Deploy documentation site to Skrypt hosting')
|
|
425
|
+
.argument('[directory]', 'Documentation site directory', '.')
|
|
426
|
+
.option('--project <slug>', 'Project slug (e.g., my-docs)')
|
|
427
|
+
.option('--token <key>', 'API token (or set SKRYPT_API_KEY env var)')
|
|
428
|
+
.action(async (directory, options) => {
|
|
429
|
+
await ensureSentry();
|
|
430
|
+
const mod = await import('./commands/deploy.js');
|
|
431
|
+
await getAction(mod.deployCommand)(directory, options);
|
|
432
|
+
});
|
|
433
|
+
// ── test ──────────────────────────────────────────────────────────────
|
|
434
|
+
program
|
|
435
|
+
.command('test')
|
|
436
|
+
.description('Test code examples in documentation files')
|
|
437
|
+
.argument('[path]', 'Directory or file to test', '.')
|
|
438
|
+
.option('-f, --file <file>', 'Test a specific file or directory')
|
|
439
|
+
.option('-l, --language <lang>', 'Filter by language (typescript, javascript, python)')
|
|
440
|
+
.option('--fix', 'Auto-fix failing examples using autofix command')
|
|
441
|
+
.option('-t, --timeout <ms>', 'Timeout per code block in milliseconds', '10000')
|
|
442
|
+
.option('-v, --verbose', 'Show detailed output')
|
|
443
|
+
.option('--verify-output', 'Compare stdout against // Output: comments')
|
|
444
|
+
.option('--env-file <file>', 'Load environment variables from file')
|
|
445
|
+
.option('--environments <list>', 'Comma-separated Docker environments (e.g. node-20,python-3.12)')
|
|
446
|
+
.action(async (path, options) => {
|
|
447
|
+
await ensureSentry();
|
|
448
|
+
const mod = await import('./commands/test.js');
|
|
449
|
+
await getAction(mod.testCommand)(path, options);
|
|
450
|
+
});
|
|
451
|
+
// ── security ──────────────────────────────────────────────────────────
|
|
452
|
+
program
|
|
453
|
+
.command('security')
|
|
454
|
+
.description('Show security and key storage details')
|
|
455
|
+
.action(async () => {
|
|
456
|
+
await ensureSentry();
|
|
457
|
+
const mod = await import('./commands/security.js');
|
|
458
|
+
await getAction(mod.securityCommand)();
|
|
459
|
+
});
|
|
460
|
+
// ── import ────────────────────────────────────────────────────────────
|
|
461
|
+
program
|
|
462
|
+
.command('import')
|
|
463
|
+
.description('Import documentation from another platform')
|
|
464
|
+
.argument('<source>', 'Local directory or GitHub URL')
|
|
465
|
+
.option('--from <format>', 'Source format (mintlify, docusaurus, gitbook, readme, notion, confluence, markdown)')
|
|
466
|
+
.option('-o, --output <dir>', 'Output directory')
|
|
467
|
+
.option('--dry-run', 'Show what would be imported without writing files')
|
|
468
|
+
.option('--name <name>', 'Project name')
|
|
469
|
+
.action(async (source, options) => {
|
|
470
|
+
await ensureSentry();
|
|
471
|
+
const mod = await import('./commands/import.js');
|
|
472
|
+
await getAction(mod.importCommand)(source, options);
|
|
473
|
+
});
|
|
474
|
+
// ── heal ──────────────────────────────────────────────────────────────
|
|
475
|
+
program
|
|
476
|
+
.command('heal')
|
|
477
|
+
.description('Self-heal documentation: fix QA issues, broken code, and capture screenshots')
|
|
478
|
+
.argument('[docs-dir]', 'Documentation directory', '.')
|
|
479
|
+
.option('--base-url <url>', 'Base URL for screenshot capture', 'http://localhost:3000')
|
|
480
|
+
.option('--output <dir>', 'Screenshot output directory', 'public/screenshots')
|
|
481
|
+
.option('--viewport <size>', 'Viewport WxH', '1280x720')
|
|
482
|
+
.option('--dark', 'Also capture dark mode variants')
|
|
483
|
+
.option('--diff', 'Only re-capture changed screenshots')
|
|
484
|
+
.option('--screenshots', 'Run screenshot capture phase')
|
|
485
|
+
.option('--qa-only', 'Run only QA fix phase')
|
|
486
|
+
.option('--code-only', 'Run only code fix phase')
|
|
487
|
+
.option('--deep', 'Run all 3 phases')
|
|
488
|
+
.option('--dry-run', 'Show what would change without writing')
|
|
489
|
+
.option('--timeout <ms>', 'Page load timeout', '30000')
|
|
490
|
+
.option('--wait <ms>', 'Wait after page load', '1000')
|
|
491
|
+
.option('--device <name>', 'Emulate device (e.g. "iPhone 14")')
|
|
492
|
+
.option('--concurrency <n>', 'Parallel capture limit', '3')
|
|
493
|
+
.option('--provider <name>', 'LLM provider (for code fix phase)')
|
|
494
|
+
.option('--model <name>', 'LLM model (for code fix phase)')
|
|
495
|
+
.option('--max-iterations <n>', 'Max fix attempts per code example', '3')
|
|
496
|
+
.option('-c, --config <file>', 'Config file path')
|
|
497
|
+
.action(async (docsDir, options) => {
|
|
498
|
+
await ensureSentry();
|
|
499
|
+
const mod = await import('./commands/heal.js');
|
|
500
|
+
await getAction(mod.healCommand)(docsDir, options);
|
|
501
|
+
});
|
|
502
|
+
// ── audit ─────────────────────────────────────────────────────────────
|
|
503
|
+
program
|
|
504
|
+
.command('audit')
|
|
505
|
+
.description('Audit documentation coverage and staleness')
|
|
506
|
+
.argument('[source]', 'Source code directory to audit', '.')
|
|
507
|
+
.option('--docs <dir>', 'Documentation directory to compare against', './docs')
|
|
508
|
+
.option('--format <type>', 'Output format: text or json', 'text')
|
|
509
|
+
.option('--public-only', 'Only audit exported/public APIs')
|
|
510
|
+
.action(async (source, options) => {
|
|
511
|
+
await ensureSentry();
|
|
512
|
+
const mod = await import('./commands/audit.js');
|
|
513
|
+
await getAction(mod.auditCommand)(source, options);
|
|
514
|
+
});
|
|
515
|
+
// ── refresh ───────────────────────────────────────────────────────────
|
|
516
|
+
program
|
|
517
|
+
.command('refresh')
|
|
518
|
+
.description('Refresh stale documentation based on code changes')
|
|
519
|
+
.argument('[source]', 'Source code directory', '.')
|
|
520
|
+
.option('--docs <dir>', 'Documentation directory', './docs')
|
|
521
|
+
.option('--since <ref>', 'Git ref to compare against (e.g. HEAD~3, 2026-03-01)', 'HEAD~1')
|
|
522
|
+
.option('-c, --config <file>', 'Config file path')
|
|
523
|
+
.option('--provider <name>', 'LLM provider')
|
|
524
|
+
.option('--model <name>', 'LLM model name')
|
|
525
|
+
.action(async (source, options) => {
|
|
526
|
+
await ensureSentry();
|
|
527
|
+
const mod = await import('./commands/refresh.js');
|
|
528
|
+
await getAction(mod.refreshCommand)(source, options);
|
|
529
|
+
});
|
|
530
|
+
// ── review ────────────────────────────────────────────────────────────
|
|
531
|
+
program
|
|
532
|
+
.command('review')
|
|
533
|
+
.description('Incorporate feedback into documentation')
|
|
534
|
+
.argument('[docs]', 'Documentation directory', './docs')
|
|
535
|
+
.option('--feedback <file>', 'Feedback file (markdown format)')
|
|
536
|
+
.option('--inline', 'Process <!-- FIXME: --> and <!-- TODO: --> comments in docs')
|
|
537
|
+
.option('-c, --config <file>', 'Config file path')
|
|
538
|
+
.option('--provider <name>', 'LLM provider')
|
|
539
|
+
.option('--model <name>', 'LLM model name')
|
|
540
|
+
.action(async (docs, options) => {
|
|
541
|
+
await ensureSentry();
|
|
542
|
+
const mod = await import('./commands/review.js');
|
|
543
|
+
await getAction(mod.reviewCommand)(docs, options);
|
|
544
|
+
});
|
|
545
|
+
// ── config ────────────────────────────────────────────────────────────
|
|
546
|
+
program
|
|
547
|
+
.command('config')
|
|
548
|
+
.description('Configure Skrypt preferences')
|
|
549
|
+
.option('--suggestions', 'Configure next-step suggestions')
|
|
550
|
+
.option('--suggestions-on', 'Enable next-step suggestions')
|
|
551
|
+
.option('--suggestions-off', 'Disable next-step suggestions')
|
|
552
|
+
.action(async (options) => {
|
|
553
|
+
await ensureSentry();
|
|
554
|
+
const mod = await import('./commands/config.js');
|
|
555
|
+
await getAction(mod.configCommand)(options);
|
|
556
|
+
});
|
|
557
|
+
try {
|
|
558
|
+
await program.parseAsync();
|
|
559
|
+
}
|
|
560
|
+
catch (err) {
|
|
561
|
+
try {
|
|
562
|
+
const { Sentry } = await import('./sentry.js');
|
|
563
|
+
Sentry.captureException(err);
|
|
564
|
+
await Sentry.flush(2000);
|
|
565
|
+
}
|
|
566
|
+
catch {
|
|
567
|
+
// Sentry may not be available
|
|
568
|
+
}
|
|
569
|
+
throw err;
|
|
570
|
+
}
|