@botdocs/cli 0.10.3 → 0.12.0
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 +7 -5
- package/bin/botdocs.cjs +78 -0
- package/dist/commands/check-updates.d.ts +22 -0
- package/dist/commands/check-updates.js +73 -18
- package/dist/commands/edit.js +10 -2
- package/dist/commands/ingest.d.ts +25 -0
- package/dist/commands/ingest.js +303 -12
- package/dist/commands/init.d.ts +24 -0
- package/dist/commands/init.js +43 -6
- package/dist/commands/install.js +146 -5
- package/dist/commands/list.js +62 -0
- package/dist/commands/login.js +56 -2
- package/dist/commands/publish.d.ts +30 -3
- package/dist/commands/publish.js +353 -40
- package/dist/commands/sync.js +252 -40
- package/dist/commands/uninstall.js +12 -0
- package/dist/commands/validate.js +82 -8
- package/dist/commands/views/login-app.js +6 -5
- package/dist/commands/views/theme.d.ts +3 -4
- package/dist/commands/views/theme.js +3 -4
- package/dist/index.js +162 -30
- package/dist/lib/api.d.ts +55 -2
- package/dist/lib/api.js +168 -11
- package/dist/lib/auto-detect.js +70 -30
- package/dist/lib/config.d.ts +15 -0
- package/dist/lib/config.js +83 -2
- package/dist/lib/ingest-session-client.d.ts +93 -0
- package/dist/lib/ingest-session-client.js +217 -0
- package/dist/lib/lockfile.d.ts +13 -0
- package/dist/lib/manifest.d.ts +12 -0
- package/dist/lib/manifest.js +29 -2
- package/dist/lib/node-preflight.d.ts +20 -0
- package/dist/lib/node-preflight.js +11 -0
- package/dist/lib/skill-caps.d.ts +17 -0
- package/dist/lib/skill-caps.js +19 -0
- package/package.json +3 -3
package/dist/lib/manifest.js
CHANGED
|
@@ -4,6 +4,18 @@ export class ManifestError extends Error {
|
|
|
4
4
|
this.name = 'ManifestError';
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* The placeholder description `botdocs init` writes into a fresh manifest.
|
|
9
|
+
* Duplicated here (kept in sync with the constant in `commands/init.ts`) so
|
|
10
|
+
* the validator can reject the exact string without commands/init.ts and
|
|
11
|
+
* lib/manifest.ts having a circular dependency (init imports validate
|
|
12
|
+
* indirectly through the publish flow; manifest is upstream of both).
|
|
13
|
+
*
|
|
14
|
+
* If you change this, change `INIT_PLACEHOLDER_DESCRIPTION` in
|
|
15
|
+
* `commands/init.ts` to match — a string-literal diff in either file
|
|
16
|
+
* silently breaks the "you left the placeholder" detection.
|
|
17
|
+
*/
|
|
18
|
+
export const INIT_PLACEHOLDER_DESCRIPTION = 'TODO: describe your skill in one sentence.';
|
|
7
19
|
const SEMVER = /^\d+\.\d+\.\d+(-[\w.-]+)?(\+[\w.-]+)?$/;
|
|
8
20
|
function parseSkillRef(raw) {
|
|
9
21
|
const cleaned = raw.startsWith('@') ? raw.slice(1) : raw;
|
|
@@ -38,8 +50,23 @@ export function parseManifest(input) {
|
|
|
38
50
|
if (type !== 'SPEC' && !SEMVER.test(version)) {
|
|
39
51
|
throw new ManifestError(`Version must be semver (e.g. 1.0.0), got: "${version}"`);
|
|
40
52
|
}
|
|
41
|
-
|
|
42
|
-
|
|
53
|
+
// Split title and description validation into separate errors so the
|
|
54
|
+
// author sees exactly which field is missing. The old combined check
|
|
55
|
+
// ("title and description are required") was generic — a friend who'd
|
|
56
|
+
// filled in the title still saw the same line and had to guess.
|
|
57
|
+
if (typeof data.title !== 'string' || !data.title.trim()) {
|
|
58
|
+
throw new ManifestError('title is required in botdocs.json');
|
|
59
|
+
}
|
|
60
|
+
if (typeof data.description !== 'string' || !data.description.trim()) {
|
|
61
|
+
throw new ManifestError('description is required in botdocs.json');
|
|
62
|
+
}
|
|
63
|
+
// Reject the unchanged placeholder that `botdocs init` writes. Without
|
|
64
|
+
// this, an author who scaffolded but never edited the manifest would
|
|
65
|
+
// publish a skill called "TODO: describe your skill in one sentence." —
|
|
66
|
+
// a recurring source of registry noise. The message names the file so
|
|
67
|
+
// the fix is obvious.
|
|
68
|
+
if (data.description.trim() === INIT_PLACEHOLDER_DESCRIPTION) {
|
|
69
|
+
throw new ManifestError(`Description still says "${INIT_PLACEHOLDER_DESCRIPTION}" — edit botdocs.json before publishing.`);
|
|
43
70
|
}
|
|
44
71
|
const title = data.title;
|
|
45
72
|
const description = data.description;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure Node-version check. Lives in its own module so the inline preflight at
|
|
3
|
+
* the top of `src/index.ts` can be unit-tested without having to spawn a
|
|
4
|
+
* subprocess with a doctored `process.versions.node`.
|
|
5
|
+
*
|
|
6
|
+
* Returns `{ ok: true }` when the version satisfies the floor; otherwise
|
|
7
|
+
* `{ ok: false, message }` where `message` is the exact stderr line we want
|
|
8
|
+
* the CLI to print. Keeping the wording in one place means tests pin the
|
|
9
|
+
* message and we can't accidentally diverge between runtime and docs.
|
|
10
|
+
*
|
|
11
|
+
* Safe to import before any Node-20-only globals are touched — this file
|
|
12
|
+
* uses only `Number.parseInt` and string ops that exist on every supported
|
|
13
|
+
* Node version, including the legacy runtimes we're trying to reject.
|
|
14
|
+
*/
|
|
15
|
+
export interface NodePreflightResult {
|
|
16
|
+
ok: boolean;
|
|
17
|
+
message?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const MIN_NODE_MAJOR = 20;
|
|
20
|
+
export declare function checkNodeVersion(nodeVersion: string): NodePreflightResult;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const MIN_NODE_MAJOR = 20;
|
|
2
|
+
export function checkNodeVersion(nodeVersion) {
|
|
3
|
+
const major = Number.parseInt(nodeVersion.split('.')[0] ?? '0', 10);
|
|
4
|
+
if (!Number.isFinite(major) || major < MIN_NODE_MAJOR) {
|
|
5
|
+
return {
|
|
6
|
+
ok: false,
|
|
7
|
+
message: `BotDocs CLI requires Node.js ${MIN_NODE_MAJOR} or newer. You're on Node ${nodeVersion}. Install from https://nodejs.org`,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
return { ok: true };
|
|
11
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side mirror of the server's per-skill size and count caps. The server
|
|
3
|
+
* enforces these on every ingest + publish-from-source request — duplicating
|
|
4
|
+
* the constants here lets `validate` flag violations locally so authors don't
|
|
5
|
+
* blow through the publish flow only to get a 413 back from the API.
|
|
6
|
+
*
|
|
7
|
+
* MUST stay in sync with apps/web/src/lib/skill-caps.ts. A shared package
|
|
8
|
+
* would eliminate the duplication long-term; for now the constants are tiny
|
|
9
|
+
* enough that mirroring is the simplest path. If you change one, change the
|
|
10
|
+
* other.
|
|
11
|
+
*/
|
|
12
|
+
export declare const PER_FILE_BYTE_CAP: number;
|
|
13
|
+
export declare const PER_SKILL_BYTE_CAP: number;
|
|
14
|
+
export declare const PER_SKILL_FILE_CAP = 25;
|
|
15
|
+
/** Pretty-print a byte count as KB with one decimal. Used in validate error
|
|
16
|
+
* messages so authors see "71.3 KB" instead of "73012 bytes". */
|
|
17
|
+
export declare function formatKB(bytes: number): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side mirror of the server's per-skill size and count caps. The server
|
|
3
|
+
* enforces these on every ingest + publish-from-source request — duplicating
|
|
4
|
+
* the constants here lets `validate` flag violations locally so authors don't
|
|
5
|
+
* blow through the publish flow only to get a 413 back from the API.
|
|
6
|
+
*
|
|
7
|
+
* MUST stay in sync with apps/web/src/lib/skill-caps.ts. A shared package
|
|
8
|
+
* would eliminate the duplication long-term; for now the constants are tiny
|
|
9
|
+
* enough that mirroring is the simplest path. If you change one, change the
|
|
10
|
+
* other.
|
|
11
|
+
*/
|
|
12
|
+
export const PER_FILE_BYTE_CAP = 64 * 1024;
|
|
13
|
+
export const PER_SKILL_BYTE_CAP = 512 * 1024;
|
|
14
|
+
export const PER_SKILL_FILE_CAP = 25;
|
|
15
|
+
/** Pretty-print a byte count as KB with one decimal. Used in validate error
|
|
16
|
+
* messages so authors see "71.3 KB" instead of "73012 bytes". */
|
|
17
|
+
export function formatKB(bytes) {
|
|
18
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botdocs/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "CLI for BotDocs — author, publish, install, and sync agent skills across Claude, Claude Code, Cursor, Codex, ChatGPT, Windsurf, Copilot, Gemini, Antigravity, and OpenCode.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"botdocs",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"author": "BotDocs contributors",
|
|
35
35
|
"bin": {
|
|
36
|
-
"botdocs": "./
|
|
36
|
+
"botdocs": "./bin/botdocs.cjs"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@eslint/js": "^10.0.1",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"vitest": "^3.1.0"
|
|
50
50
|
},
|
|
51
51
|
"files": [
|
|
52
|
+
"bin",
|
|
52
53
|
"dist",
|
|
53
54
|
"templates",
|
|
54
55
|
"README.md"
|
|
@@ -67,7 +68,6 @@
|
|
|
67
68
|
"commander": "^14.0.3",
|
|
68
69
|
"diff": "^9.0.0",
|
|
69
70
|
"ink": "^5.2.1",
|
|
70
|
-
"ink-big-text": "^2.0.0",
|
|
71
71
|
"ink-gradient": "^3.0.0",
|
|
72
72
|
"ink-select-input": "^6.2.0",
|
|
73
73
|
"ink-spinner": "^5.0.0",
|