@kodax-ai/kodax 0.7.95 → 0.7.96-alpha.2
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/CHANGELOG.md +178 -1
- package/LICENSE +158 -158
- package/README.md +149 -24
- package/README_CN.md +117 -24
- package/config-templates/config.example.jsonc +2 -1
- package/config-templates/integrations/a2a.example.jsonc +91 -91
- package/config-templates/integrations/extensions.example.jsonc +7 -7
- package/config-templates/integrations/mcp.example.jsonc +16 -16
- package/dist/builtin/code-review/SKILL.md +82 -82
- package/dist/builtin/git-workflow/SKILL.md +84 -84
- package/dist/builtin/skill-creator/SKILL.md +127 -127
- package/dist/builtin/skill-creator/agents/analyzer.md +12 -12
- package/dist/builtin/skill-creator/agents/comparator.md +13 -13
- package/dist/builtin/skill-creator/agents/grader.md +13 -13
- package/dist/builtin/skill-creator/references/schemas.md +227 -227
- package/dist/builtin/skill-creator/scripts/aggregate-benchmark.d.ts +46 -46
- package/dist/builtin/skill-creator/scripts/aggregate-benchmark.js +208 -208
- package/dist/builtin/skill-creator/scripts/analyze-benchmark.d.ts +46 -46
- package/dist/builtin/skill-creator/scripts/analyze-benchmark.js +286 -286
- package/dist/builtin/skill-creator/scripts/compare-runs.d.ts +62 -62
- package/dist/builtin/skill-creator/scripts/compare-runs.js +330 -330
- package/dist/builtin/skill-creator/scripts/generate-review.d.ts +33 -33
- package/dist/builtin/skill-creator/scripts/generate-review.js +414 -414
- package/dist/builtin/skill-creator/scripts/grade-evals.d.ts +73 -73
- package/dist/builtin/skill-creator/scripts/grade-evals.js +402 -402
- package/dist/builtin/skill-creator/scripts/improve-description.d.ts +23 -23
- package/dist/builtin/skill-creator/scripts/improve-description.js +160 -160
- package/dist/builtin/skill-creator/scripts/init-skill.d.ts +14 -14
- package/dist/builtin/skill-creator/scripts/init-skill.js +155 -155
- package/dist/builtin/skill-creator/scripts/install-skill.d.ts +29 -29
- package/dist/builtin/skill-creator/scripts/install-skill.js +173 -173
- package/dist/builtin/skill-creator/scripts/package-skill.d.ts +38 -38
- package/dist/builtin/skill-creator/scripts/package-skill.js +121 -121
- package/dist/builtin/skill-creator/scripts/quick-validate.d.ts +8 -8
- package/dist/builtin/skill-creator/scripts/quick-validate.js +163 -163
- package/dist/builtin/skill-creator/scripts/run-eval.d.ts +66 -66
- package/dist/builtin/skill-creator/scripts/run-eval.js +353 -353
- package/dist/builtin/skill-creator/scripts/run-loop.d.ts +49 -49
- package/dist/builtin/skill-creator/scripts/run-loop.js +242 -242
- package/dist/builtin/skill-creator/scripts/run-trigger-eval.d.ts +58 -58
- package/dist/builtin/skill-creator/scripts/run-trigger-eval.js +224 -224
- package/dist/builtin/tdd/SKILL.md +56 -56
- package/dist/chunks/agent-4FABF6WK.js +2 -0
- package/dist/chunks/argument-completer-72VHB2VL.js +2 -0
- package/dist/chunks/{chunk-7JXA3533.js → chunk-4OIQZWA5.js} +223 -226
- package/dist/chunks/{chunk-BNVSKIAB.js → chunk-6BVF3HZ7.js} +136 -136
- package/dist/chunks/chunk-7JZZIFZH.js +501 -0
- package/dist/chunks/chunk-AC7Z2OIY.js +2 -0
- package/dist/chunks/{chunk-JS452J2F.js → chunk-C4KYZAFU.js} +2 -2
- package/dist/chunks/chunk-CHUPIWIF.js +251 -0
- package/dist/chunks/{chunk-C4DTUKTR.js → chunk-GYUU7XLH.js} +5 -4
- package/dist/chunks/{chunk-OK4AXDC5.js → chunk-HAX55GOQ.js} +1 -1
- package/dist/chunks/chunk-JKTJCGO2.js +418 -0
- package/dist/chunks/{chunk-O743AJ5V.js → chunk-LQYETRFK.js} +171 -175
- package/dist/chunks/{chunk-2PEDBGKN.js → chunk-LTUZTQ6W.js} +1 -1
- package/dist/chunks/chunk-LYWDUSKO.js +2 -0
- package/dist/chunks/chunk-NGH6T4FD.js +92 -0
- package/dist/chunks/{chunk-SRIJX5ZP.js → chunk-NVRWCSA5.js} +1 -1
- package/dist/chunks/chunk-O4DS7RIQ.js +384 -0
- package/dist/chunks/chunk-ORXU6OWZ.js +2 -0
- package/dist/chunks/chunk-POTW3O65.js +124 -0
- package/dist/chunks/{chunk-2TM3W3GK.js → chunk-RIQSS56Y.js} +1 -1
- package/dist/chunks/chunk-U27XKEN5.js +407 -0
- package/dist/chunks/{chunk-6ABQJUK6.js → chunk-XUX6OUCA.js} +2 -2
- package/dist/chunks/{client-JDOS3YJR.js → client-4C456K4O.js} +1 -1
- package/dist/chunks/compaction-config-3VQRDFF4.js +2 -0
- package/dist/chunks/{construction-bootstrap-YCWHHUYO.js → construction-bootstrap-AHN7EDGG.js} +1 -1
- package/dist/chunks/dist-BCBQXAGI.js +2 -0
- package/dist/chunks/dist-QK2YDWU6.js +2 -0
- package/dist/chunks/host-VIHV7ADG.js +2 -0
- package/dist/chunks/run-manager-NBVMU3KV.js +2 -0
- package/dist/chunks/utils-MEJZ2IGI.js +2 -0
- package/dist/index.d.ts +22 -21
- package/dist/index.js +7 -7
- package/dist/kodax_bootstrap.js +26 -26
- package/dist/kodax_cli.js +1905 -1882
- package/dist/native/darwin-arm64/LICENSE-APACHE.txt +13 -0
- package/dist/native/darwin-arm64/kodax-text-transaction.node +0 -0
- package/dist/native/darwin-arm64/manifest.json +16 -0
- package/dist/native/darwin-x64/LICENSE-APACHE.txt +13 -0
- package/dist/native/darwin-x64/kodax-text-transaction.node +0 -0
- package/dist/native/darwin-x64/manifest.json +16 -0
- package/dist/native/linux-arm64/LICENSE-APACHE.txt +13 -0
- package/dist/native/linux-arm64/kodax-text-transaction.node +0 -0
- package/dist/native/linux-arm64/manifest.json +16 -0
- package/dist/native/linux-x64/LICENSE-APACHE.txt +13 -0
- package/dist/native/linux-x64/kodax-text-transaction.node +0 -0
- package/dist/native/linux-x64/manifest.json +16 -0
- package/dist/native/win32-x64/LICENSE-APACHE.txt +13 -0
- package/dist/native/win32-x64/NOTICE-windows-sandbox.txt +8 -0
- package/dist/native/win32-x64/kodax-windows-sandbox.exe +0 -0
- package/dist/native/win32-x64/kodax-windows-text-transaction.node +0 -0
- package/dist/native/win32-x64/manifest.json +30 -0
- package/dist/provider-capabilities.json +108 -2
- package/dist/runtime-worker.js +1745 -1727
- package/dist/sandbox-network-broker.js +1715 -0
- package/dist/sdk-a2a.d.ts +13 -12
- package/dist/sdk-a2a.js +1 -1
- package/dist/sdk-agent.d.ts +27 -18
- package/dist/sdk-agent.js +1 -1
- package/dist/sdk-coding.d.ts +107 -58
- package/dist/sdk-coding.js +1 -1
- package/dist/sdk-experimental-memory.d.ts +4 -4
- package/dist/sdk-experimental-memory.js +1 -1
- package/dist/sdk-llm.d.ts +9 -10
- package/dist/sdk-llm.js +1 -1
- package/dist/sdk-mcp.js +1 -1
- package/dist/sdk-media.d.ts +1 -1
- package/dist/sdk-media.js +1 -1
- package/dist/sdk-repl.d.ts +25 -17
- package/dist/sdk-repl.js +1 -1
- package/dist/sdk-runtime.d.ts +41 -17
- package/dist/sdk-runtime.js +1 -1
- package/dist/sdk-sandbox.d.ts +17 -3
- package/dist/sdk-sandbox.js +1 -1
- package/dist/sdk-session.d.ts +8 -7
- package/dist/sdk-session.js +1 -1
- package/dist/sdk-skills.js +1 -1
- package/dist/semantic-worker.js +61 -61
- package/dist/types-chunks/{base.d-vopO1rml.d.ts → base.d-COo8E2dk.d.ts} +18 -27
- package/dist/types-chunks/{bash-prefix-extractor.d-B2rxNI4L.d.ts → bash-prefix-extractor.d-DQOlA8cy.d.ts} +72 -52
- package/dist/types-chunks/{capability-learning.d-CE1tm29C.d.ts → capability-learning.d-lRPgA3Or.d.ts} +1 -1
- package/dist/types-chunks/{capsule.d-Y7QRS4J2.d.ts → capsule.d-0zxsgXg_.d.ts} +3 -3
- package/dist/types-chunks/{controller.d-BR-UVeUR.d.ts → controller.d-BTtyIIC1.d.ts} +1 -1
- package/dist/types-chunks/{controller.d-C5noq5-w.d.ts → controller.d-C7tXUcXo.d.ts} +2 -2
- package/dist/types-chunks/{guardrail.d-DqHD-61O.d.ts → guardrail.d-DKTyEHJa.d.ts} +5 -5
- package/dist/types-chunks/{history-retrieval.d-CKU8zmt_.d.ts → history-retrieval.d-CHnL99S7.d.ts} +2 -2
- package/dist/types-chunks/{public-api.d-D7fXaWW8.d.ts → public-api.d-Dx3L3W4Z.d.ts} +7 -4
- package/dist/types-chunks/{repl.d-BYDb14s6.d.ts → repl.d-mO01olIa.d.ts} +5 -5
- package/dist/types-chunks/{resolver.d-CwHUwbdE.d.ts → resolver.d-DlXPjeyx.d.ts} +38 -6
- package/dist/types-chunks/{review-inbox.d-BSgFewyj.d.ts → review-inbox.d-WDSe1nze.d.ts} +1 -1
- package/dist/types-chunks/{run-manager.d-BVJSntpS.d.ts → run-manager.d-DENbbzgR.d.ts} +1 -1
- package/dist/types-chunks/{sdk-session-CqEG84oP.d.ts → sdk-session-DYHGXXH4.d.ts} +3 -3
- package/dist/types-chunks/{shell-command-sets.d-DqaaBwhU.d.ts → shell-command-sets.d-CjFqS4dp.d.ts} +1 -1
- package/dist/types-chunks/{side-query.d-iH0P9ASy.d.ts → side-query.d-j8A3sFv_.d.ts} +2 -2
- package/dist/types-chunks/{types.d-rUOjXych.d.ts → types.d-BbZjR0Wr.d.ts} +1 -1
- package/dist/types-chunks/{types.d-CaTXAW_Q.d.ts → types.d-BkTIKdH6.d.ts} +2 -2
- package/dist/types-chunks/{types.d-C5xQEFcj.d.ts → types.d-DncLrpu_.d.ts} +4 -4
- package/dist/types-chunks/{types.d-CK9A9rpP.d.ts → types.d-Xy0f3x4i.d.ts} +9 -0
- package/dist/types-chunks/{utils.d-CWUyLiXo.d.ts → utils.d-CnxefMos.d.ts} +6 -6
- package/package.json +10 -3
- package/public_docs/README.md +130 -0
- package/public_docs/configuration/sandbox.md +289 -0
- package/public_docs/sdk/embedder-guide.md +6674 -0
- package/scripts/kodax-bin.cjs +28 -28
- package/scripts/production-env.cjs +25 -25
- package/dist/chunks/agent-XXZMXKKA.js +0 -2
- package/dist/chunks/argument-completer-KCYDGTQW.js +0 -2
- package/dist/chunks/chunk-77PNP27P.js +0 -92
- package/dist/chunks/chunk-7QBWHCIZ.js +0 -2
- package/dist/chunks/chunk-BHE66SP3.js +0 -123
- package/dist/chunks/chunk-BR2OSB2I.js +0 -722
- package/dist/chunks/chunk-DSMONSVB.js +0 -407
- package/dist/chunks/chunk-Q5VRWSKG.js +0 -418
- package/dist/chunks/chunk-XWRPOGJN.js +0 -4
- package/dist/chunks/chunk-Y5VIQBT6.js +0 -383
- package/dist/chunks/compaction-config-EGS4577X.js +0 -2
- package/dist/chunks/dist-ITTXQHRJ.js +0 -2
- package/dist/chunks/dist-KFYN3OKD.js +0 -2
- package/dist/chunks/host-VAYADIPW.js +0 -2
- package/dist/chunks/run-manager-52IJZMZJ.js +0 -2
- package/dist/chunks/utils-P7PBSL3R.js +0 -2
- package/dist/sandbox-workspace-session.js +0 -1705
|
@@ -1,177 +1,177 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { cp, mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import { strFromU8, unzipSync } from 'fflate';
|
|
7
|
-
import { validateSkillDirectory } from './quick-validate.js';
|
|
8
|
-
import { getDefaultSkillsDir, parseSkillMarkdown, pathExists } from './utils.js';
|
|
9
|
-
|
|
10
|
-
const PACKAGE_MANIFEST_PATH = '.kodax-package.json';
|
|
11
|
-
|
|
12
|
-
function normalizeArchivePath(relativePath) {
|
|
13
|
-
return relativePath.replace(/\\/g, '/').replace(/^\.?\//, '');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function assertSafeArchivePath(relativePath) {
|
|
17
|
-
const normalized = normalizeArchivePath(relativePath);
|
|
18
|
-
if (!normalized || normalized.startsWith('/') || normalized.includes('../')) {
|
|
19
|
-
throw new Error(`Unsafe archive entry path: ${relativePath}`);
|
|
20
|
-
}
|
|
21
|
-
return normalized;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function isZipLike(filePath) {
|
|
25
|
-
return /\.(skill|zip)$/i.test(filePath);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function readSkillPackageBuffer(buffer) {
|
|
29
|
-
const archive = unzipSync(buffer);
|
|
30
|
-
const entries = Object.entries(archive).map(([relativePath, bytes]) => ({
|
|
31
|
-
relativePath: assertSafeArchivePath(relativePath),
|
|
32
|
-
bytes,
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
|
-
const skillEntry = entries.find((entry) => entry.relativePath === 'SKILL.md');
|
|
36
|
-
if (!skillEntry) {
|
|
37
|
-
throw new Error('Archive is missing SKILL.md');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const parsedSkill = parseSkillMarkdown(strFromU8(skillEntry.bytes));
|
|
41
|
-
const skillName = typeof parsedSkill.frontmatter.name === 'string'
|
|
42
|
-
? parsedSkill.frontmatter.name.trim()
|
|
43
|
-
: '';
|
|
44
|
-
const description = typeof parsedSkill.frontmatter.description === 'string'
|
|
45
|
-
? parsedSkill.frontmatter.description.trim()
|
|
46
|
-
: '';
|
|
47
|
-
if (!skillName || !description) {
|
|
48
|
-
throw new Error('Archive SKILL.md is missing required frontmatter fields.');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const manifestEntry = entries.find((entry) => entry.relativePath === PACKAGE_MANIFEST_PATH);
|
|
52
|
-
const manifest = manifestEntry
|
|
53
|
-
? JSON.parse(strFromU8(manifestEntry.bytes))
|
|
54
|
-
: null;
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
skillName,
|
|
58
|
-
manifest,
|
|
59
|
-
entries: entries.filter((entry) => entry.relativePath !== PACKAGE_MANIFEST_PATH),
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async function ensureInstallTarget(targetDir, force) {
|
|
64
|
-
if (await pathExists(targetDir)) {
|
|
65
|
-
if (!force) {
|
|
66
|
-
throw new Error(`Target skill already exists: ${targetDir}`);
|
|
67
|
-
}
|
|
68
|
-
await rm(targetDir, { recursive: true, force: true });
|
|
69
|
-
}
|
|
70
|
-
await mkdir(targetDir, { recursive: true });
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export async function installSkillArchive(archivePath, options = {}) {
|
|
74
|
-
const skillsDir = path.resolve(options.skillsDir ?? getDefaultSkillsDir());
|
|
75
|
-
const archive = readSkillPackageBuffer(await readFile(archivePath));
|
|
76
|
-
const targetDir = path.join(skillsDir, archive.skillName);
|
|
77
|
-
await ensureInstallTarget(targetDir, options.force === true);
|
|
78
|
-
|
|
79
|
-
for (const entry of archive.entries) {
|
|
80
|
-
const destination = path.join(targetDir, entry.relativePath);
|
|
81
|
-
await mkdir(path.dirname(destination), { recursive: true });
|
|
82
|
-
await writeFile(destination, entry.bytes);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return {
|
|
86
|
-
skillName: archive.skillName,
|
|
87
|
-
installedTo: targetDir,
|
|
88
|
-
source: path.resolve(archivePath),
|
|
89
|
-
manifest: archive.manifest,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export async function installSkillDirectory(skillDir, options = {}) {
|
|
94
|
-
const validation = await validateSkillDirectory(skillDir);
|
|
95
|
-
if (!validation.valid) {
|
|
96
|
-
throw new Error(`Cannot install invalid skill:\n- ${validation.errors.join('\n- ')}`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const skillFilePath = path.join(skillDir, 'SKILL.md');
|
|
100
|
-
const skill = parseSkillMarkdown(await readFile(skillFilePath, 'utf8'));
|
|
101
|
-
const skillsDir = path.resolve(options.skillsDir ?? getDefaultSkillsDir());
|
|
102
|
-
const targetDir = path.join(skillsDir, skill.frontmatter.name);
|
|
103
|
-
if (await pathExists(targetDir)) {
|
|
104
|
-
if (!options.force) {
|
|
105
|
-
throw new Error(`Target skill already exists: ${targetDir}`);
|
|
106
|
-
}
|
|
107
|
-
await rm(targetDir, { recursive: true, force: true });
|
|
108
|
-
}
|
|
109
|
-
await mkdir(skillsDir, { recursive: true });
|
|
110
|
-
await cp(skillDir, targetDir, { recursive: true });
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
skillName: skill.frontmatter.name,
|
|
114
|
-
installedTo: targetDir,
|
|
115
|
-
source: path.resolve(skillDir),
|
|
116
|
-
manifest: null,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export async function installSkill(inputPath, options = {}) {
|
|
121
|
-
const resolvedInput = path.resolve(inputPath);
|
|
122
|
-
const inputStat = await stat(resolvedInput).catch(() => null);
|
|
123
|
-
if (!inputStat) {
|
|
124
|
-
throw new Error(`Input not found: ${resolvedInput}`);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (inputStat.isDirectory()) {
|
|
128
|
-
return installSkillDirectory(resolvedInput, options);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (inputStat.isFile() && isZipLike(resolvedInput)) {
|
|
132
|
-
return installSkillArchive(resolvedInput, options);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
throw new Error('Input must be a skill directory or a .skill/.zip archive.');
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function parseArgs(argv) {
|
|
139
|
-
const args = {
|
|
140
|
-
input: argv[2],
|
|
141
|
-
skillsDir: undefined,
|
|
142
|
-
force: false,
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
for (let index = 3; index < argv.length; index += 1) {
|
|
146
|
-
const token = argv[index];
|
|
147
|
-
if (token === '--dest' && argv[index + 1]) {
|
|
148
|
-
args.skillsDir = argv[++index];
|
|
149
|
-
} else if (token === '--force') {
|
|
150
|
-
args.force = true;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return args;
|
|
155
|
-
}
|
|
156
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { cp, mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { strFromU8, unzipSync } from 'fflate';
|
|
7
|
+
import { validateSkillDirectory } from './quick-validate.js';
|
|
8
|
+
import { getDefaultSkillsDir, parseSkillMarkdown, pathExists } from './utils.js';
|
|
9
|
+
|
|
10
|
+
const PACKAGE_MANIFEST_PATH = '.kodax-package.json';
|
|
11
|
+
|
|
12
|
+
function normalizeArchivePath(relativePath) {
|
|
13
|
+
return relativePath.replace(/\\/g, '/').replace(/^\.?\//, '');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function assertSafeArchivePath(relativePath) {
|
|
17
|
+
const normalized = normalizeArchivePath(relativePath);
|
|
18
|
+
if (!normalized || normalized.startsWith('/') || normalized.includes('../')) {
|
|
19
|
+
throw new Error(`Unsafe archive entry path: ${relativePath}`);
|
|
20
|
+
}
|
|
21
|
+
return normalized;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function isZipLike(filePath) {
|
|
25
|
+
return /\.(skill|zip)$/i.test(filePath);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function readSkillPackageBuffer(buffer) {
|
|
29
|
+
const archive = unzipSync(buffer);
|
|
30
|
+
const entries = Object.entries(archive).map(([relativePath, bytes]) => ({
|
|
31
|
+
relativePath: assertSafeArchivePath(relativePath),
|
|
32
|
+
bytes,
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
const skillEntry = entries.find((entry) => entry.relativePath === 'SKILL.md');
|
|
36
|
+
if (!skillEntry) {
|
|
37
|
+
throw new Error('Archive is missing SKILL.md');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const parsedSkill = parseSkillMarkdown(strFromU8(skillEntry.bytes));
|
|
41
|
+
const skillName = typeof parsedSkill.frontmatter.name === 'string'
|
|
42
|
+
? parsedSkill.frontmatter.name.trim()
|
|
43
|
+
: '';
|
|
44
|
+
const description = typeof parsedSkill.frontmatter.description === 'string'
|
|
45
|
+
? parsedSkill.frontmatter.description.trim()
|
|
46
|
+
: '';
|
|
47
|
+
if (!skillName || !description) {
|
|
48
|
+
throw new Error('Archive SKILL.md is missing required frontmatter fields.');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const manifestEntry = entries.find((entry) => entry.relativePath === PACKAGE_MANIFEST_PATH);
|
|
52
|
+
const manifest = manifestEntry
|
|
53
|
+
? JSON.parse(strFromU8(manifestEntry.bytes))
|
|
54
|
+
: null;
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
skillName,
|
|
58
|
+
manifest,
|
|
59
|
+
entries: entries.filter((entry) => entry.relativePath !== PACKAGE_MANIFEST_PATH),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function ensureInstallTarget(targetDir, force) {
|
|
64
|
+
if (await pathExists(targetDir)) {
|
|
65
|
+
if (!force) {
|
|
66
|
+
throw new Error(`Target skill already exists: ${targetDir}`);
|
|
67
|
+
}
|
|
68
|
+
await rm(targetDir, { recursive: true, force: true });
|
|
69
|
+
}
|
|
70
|
+
await mkdir(targetDir, { recursive: true });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function installSkillArchive(archivePath, options = {}) {
|
|
74
|
+
const skillsDir = path.resolve(options.skillsDir ?? getDefaultSkillsDir());
|
|
75
|
+
const archive = readSkillPackageBuffer(await readFile(archivePath));
|
|
76
|
+
const targetDir = path.join(skillsDir, archive.skillName);
|
|
77
|
+
await ensureInstallTarget(targetDir, options.force === true);
|
|
78
|
+
|
|
79
|
+
for (const entry of archive.entries) {
|
|
80
|
+
const destination = path.join(targetDir, entry.relativePath);
|
|
81
|
+
await mkdir(path.dirname(destination), { recursive: true });
|
|
82
|
+
await writeFile(destination, entry.bytes);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
skillName: archive.skillName,
|
|
87
|
+
installedTo: targetDir,
|
|
88
|
+
source: path.resolve(archivePath),
|
|
89
|
+
manifest: archive.manifest,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export async function installSkillDirectory(skillDir, options = {}) {
|
|
94
|
+
const validation = await validateSkillDirectory(skillDir);
|
|
95
|
+
if (!validation.valid) {
|
|
96
|
+
throw new Error(`Cannot install invalid skill:\n- ${validation.errors.join('\n- ')}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const skillFilePath = path.join(skillDir, 'SKILL.md');
|
|
100
|
+
const skill = parseSkillMarkdown(await readFile(skillFilePath, 'utf8'));
|
|
101
|
+
const skillsDir = path.resolve(options.skillsDir ?? getDefaultSkillsDir());
|
|
102
|
+
const targetDir = path.join(skillsDir, skill.frontmatter.name);
|
|
103
|
+
if (await pathExists(targetDir)) {
|
|
104
|
+
if (!options.force) {
|
|
105
|
+
throw new Error(`Target skill already exists: ${targetDir}`);
|
|
106
|
+
}
|
|
107
|
+
await rm(targetDir, { recursive: true, force: true });
|
|
108
|
+
}
|
|
109
|
+
await mkdir(skillsDir, { recursive: true });
|
|
110
|
+
await cp(skillDir, targetDir, { recursive: true });
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
skillName: skill.frontmatter.name,
|
|
114
|
+
installedTo: targetDir,
|
|
115
|
+
source: path.resolve(skillDir),
|
|
116
|
+
manifest: null,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export async function installSkill(inputPath, options = {}) {
|
|
121
|
+
const resolvedInput = path.resolve(inputPath);
|
|
122
|
+
const inputStat = await stat(resolvedInput).catch(() => null);
|
|
123
|
+
if (!inputStat) {
|
|
124
|
+
throw new Error(`Input not found: ${resolvedInput}`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (inputStat.isDirectory()) {
|
|
128
|
+
return installSkillDirectory(resolvedInput, options);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (inputStat.isFile() && isZipLike(resolvedInput)) {
|
|
132
|
+
return installSkillArchive(resolvedInput, options);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
throw new Error('Input must be a skill directory or a .skill/.zip archive.');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function parseArgs(argv) {
|
|
139
|
+
const args = {
|
|
140
|
+
input: argv[2],
|
|
141
|
+
skillsDir: undefined,
|
|
142
|
+
force: false,
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
for (let index = 3; index < argv.length; index += 1) {
|
|
146
|
+
const token = argv[index];
|
|
147
|
+
if (token === '--dest' && argv[index + 1]) {
|
|
148
|
+
args.skillsDir = argv[++index];
|
|
149
|
+
} else if (token === '--force') {
|
|
150
|
+
args.force = true;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return args;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
157
|
export async function main(argv = process.argv) {
|
|
158
158
|
const args = parseArgs(argv);
|
|
159
|
-
if (!args.input) {
|
|
160
|
-
console.error('Usage: node scripts/install-skill.js <skill-dir-or-archive> [--dest <skills-dir>] [--force]');
|
|
161
|
-
process.exit(1);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const result = await installSkill(args.input, args);
|
|
165
|
-
console.log(`Installed ${result.skillName} to ${result.installedTo}`);
|
|
166
|
-
}
|
|
167
|
-
|
|
159
|
+
if (!args.input) {
|
|
160
|
+
console.error('Usage: node scripts/install-skill.js <skill-dir-or-archive> [--dest <skills-dir>] [--force]');
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const result = await installSkill(args.input, args);
|
|
165
|
+
console.log(`Installed ${result.skillName} to ${result.installedTo}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
168
|
const isDirectRun = process.env.KODAX_MODULE_BUNDLE !== 'true'
|
|
169
169
|
&& process.argv[1]
|
|
170
|
-
&& fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
171
|
-
|
|
172
|
-
if (isDirectRun) {
|
|
173
|
-
main().catch((error) => {
|
|
174
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
175
|
-
process.exit(1);
|
|
176
|
-
});
|
|
177
|
-
}
|
|
170
|
+
&& fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
171
|
+
|
|
172
|
+
if (isDirectRun) {
|
|
173
|
+
main().catch((error) => {
|
|
174
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
175
|
+
process.exit(1);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
export interface PackagedSkillFile {
|
|
2
|
-
path: string;
|
|
3
|
-
size: number;
|
|
4
|
-
sha256: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface SkillPackageManifest {
|
|
8
|
-
format: 'kodax-skill-package';
|
|
9
|
-
version: 1;
|
|
10
|
-
created_at: string;
|
|
11
|
-
entrypoint: 'SKILL.md';
|
|
12
|
-
skill: {
|
|
13
|
-
name: string;
|
|
14
|
-
description: string;
|
|
15
|
-
compatibility: string | null;
|
|
16
|
-
user_invocable: boolean;
|
|
17
|
-
disable_model_invocation: boolean;
|
|
18
|
-
};
|
|
19
|
-
files: PackagedSkillFile[];
|
|
20
|
-
note: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function createPackageManifest(
|
|
24
|
-
skill: { frontmatter: Record<string, unknown> },
|
|
25
|
-
files: Array<{ relativePath: string; bytes: Uint8Array; sha256: string }>,
|
|
26
|
-
options?: { createdAt?: string }
|
|
27
|
-
): SkillPackageManifest;
|
|
28
|
-
|
|
29
|
-
export function buildSkillPackage(
|
|
30
|
-
skillDir: string,
|
|
31
|
-
options?: { createdAt?: string }
|
|
32
|
-
): Promise<{ manifest: SkillPackageManifest; bytes: Uint8Array }>;
|
|
33
|
-
|
|
34
|
-
export function writeSkillPackage(
|
|
35
|
-
skillDir: string,
|
|
36
|
-
outputPath: string,
|
|
37
|
-
options?: { createdAt?: string }
|
|
38
|
-
): Promise<{ manifest: SkillPackageManifest; bytes: Uint8Array; outputPath: string }>;
|
|
1
|
+
export interface PackagedSkillFile {
|
|
2
|
+
path: string;
|
|
3
|
+
size: number;
|
|
4
|
+
sha256: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface SkillPackageManifest {
|
|
8
|
+
format: 'kodax-skill-package';
|
|
9
|
+
version: 1;
|
|
10
|
+
created_at: string;
|
|
11
|
+
entrypoint: 'SKILL.md';
|
|
12
|
+
skill: {
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
compatibility: string | null;
|
|
16
|
+
user_invocable: boolean;
|
|
17
|
+
disable_model_invocation: boolean;
|
|
18
|
+
};
|
|
19
|
+
files: PackagedSkillFile[];
|
|
20
|
+
note: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function createPackageManifest(
|
|
24
|
+
skill: { frontmatter: Record<string, unknown> },
|
|
25
|
+
files: Array<{ relativePath: string; bytes: Uint8Array; sha256: string }>,
|
|
26
|
+
options?: { createdAt?: string }
|
|
27
|
+
): SkillPackageManifest;
|
|
28
|
+
|
|
29
|
+
export function buildSkillPackage(
|
|
30
|
+
skillDir: string,
|
|
31
|
+
options?: { createdAt?: string }
|
|
32
|
+
): Promise<{ manifest: SkillPackageManifest; bytes: Uint8Array }>;
|
|
33
|
+
|
|
34
|
+
export function writeSkillPackage(
|
|
35
|
+
skillDir: string,
|
|
36
|
+
outputPath: string,
|
|
37
|
+
options?: { createdAt?: string }
|
|
38
|
+
): Promise<{ manifest: SkillPackageManifest; bytes: Uint8Array; outputPath: string }>;
|
|
39
39
|
export declare function main(argv?: string[]): Promise<void>;
|
|
@@ -1,125 +1,125 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { readFile, writeFile } from 'node:fs/promises';
|
|
4
|
-
import { createHash } from 'node:crypto';
|
|
5
|
-
import path from 'node:path';
|
|
6
|
-
import { fileURLToPath } from 'node:url';
|
|
7
|
-
import { zipSync, strToU8 } from 'fflate';
|
|
8
|
-
import { validateSkillDirectory } from './quick-validate.js';
|
|
9
|
-
import { collectFiles, loadSkill } from './utils.js';
|
|
10
|
-
|
|
11
|
-
const PACKAGE_MANIFEST_PATH = '.kodax-package.json';
|
|
12
|
-
|
|
13
|
-
function toUint8Array(value) {
|
|
14
|
-
return value instanceof Uint8Array ? value : new Uint8Array(value);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function sha256(buffer) {
|
|
18
|
-
return createHash('sha256').update(buffer).digest('hex');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function createPackageManifest(skill, files, options = {}) {
|
|
22
|
-
return {
|
|
23
|
-
format: 'kodax-skill-package',
|
|
24
|
-
version: 1,
|
|
25
|
-
created_at: options.createdAt ?? new Date().toISOString(),
|
|
26
|
-
entrypoint: 'SKILL.md',
|
|
27
|
-
skill: {
|
|
28
|
-
name: skill.frontmatter.name,
|
|
29
|
-
description: skill.frontmatter.description,
|
|
30
|
-
compatibility: skill.frontmatter.compatibility ?? null,
|
|
31
|
-
user_invocable: skill.frontmatter['user-invocable'] ?? true,
|
|
32
|
-
disable_model_invocation: skill.frontmatter['disable-model-invocation'] ?? false,
|
|
33
|
-
},
|
|
34
|
-
files: files.map((file) => ({
|
|
35
|
-
path: file.relativePath,
|
|
36
|
-
size: file.bytes.length,
|
|
37
|
-
sha256: file.sha256,
|
|
38
|
-
})),
|
|
39
|
-
note: 'This archive is a zip file with a .skill extension. Compatible agents can extract and install the included skill directory.',
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export async function buildSkillPackage(skillDir, options = {}) {
|
|
44
|
-
const validation = await validateSkillDirectory(skillDir);
|
|
45
|
-
if (!validation.valid) {
|
|
46
|
-
throw new Error(`Cannot package invalid skill:\n- ${validation.errors.join('\n- ')}`);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const skill = await loadSkill(skillDir);
|
|
50
|
-
const discoveredFiles = await collectFiles(skillDir);
|
|
51
|
-
const files = [];
|
|
52
|
-
for (const file of discoveredFiles) {
|
|
53
|
-
if (file.relativePath.endsWith('.skill')) {
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
const bytes = toUint8Array(await readFile(file.absolutePath));
|
|
57
|
-
files.push({
|
|
58
|
-
...file,
|
|
59
|
-
bytes,
|
|
60
|
-
sha256: sha256(bytes),
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const manifest = createPackageManifest(skill, files, options);
|
|
65
|
-
const archiveEntries = {
|
|
66
|
-
[PACKAGE_MANIFEST_PATH]: strToU8(JSON.stringify(manifest, null, 2)),
|
|
67
|
-
};
|
|
68
|
-
for (const file of files) {
|
|
69
|
-
archiveEntries[file.relativePath] = file.bytes;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
manifest,
|
|
74
|
-
bytes: zipSync(archiveEntries, { level: 6 }),
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export async function writeSkillPackage(skillDir, outputPath, options = {}) {
|
|
79
|
-
const result = await buildSkillPackage(skillDir, options);
|
|
80
|
-
await writeFile(outputPath, result.bytes);
|
|
81
|
-
return {
|
|
82
|
-
...result,
|
|
83
|
-
outputPath: path.resolve(outputPath),
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function parseArgs(argv) {
|
|
88
|
-
const args = {
|
|
89
|
-
skillDir: argv[2],
|
|
90
|
-
output: undefined,
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
for (let index = 3; index < argv.length; index += 1) {
|
|
94
|
-
const token = argv[index];
|
|
95
|
-
if (token === '--output' && argv[index + 1]) {
|
|
96
|
-
args.output = argv[++index];
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return args;
|
|
101
|
-
}
|
|
102
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { zipSync, strToU8 } from 'fflate';
|
|
8
|
+
import { validateSkillDirectory } from './quick-validate.js';
|
|
9
|
+
import { collectFiles, loadSkill } from './utils.js';
|
|
10
|
+
|
|
11
|
+
const PACKAGE_MANIFEST_PATH = '.kodax-package.json';
|
|
12
|
+
|
|
13
|
+
function toUint8Array(value) {
|
|
14
|
+
return value instanceof Uint8Array ? value : new Uint8Array(value);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function sha256(buffer) {
|
|
18
|
+
return createHash('sha256').update(buffer).digest('hex');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function createPackageManifest(skill, files, options = {}) {
|
|
22
|
+
return {
|
|
23
|
+
format: 'kodax-skill-package',
|
|
24
|
+
version: 1,
|
|
25
|
+
created_at: options.createdAt ?? new Date().toISOString(),
|
|
26
|
+
entrypoint: 'SKILL.md',
|
|
27
|
+
skill: {
|
|
28
|
+
name: skill.frontmatter.name,
|
|
29
|
+
description: skill.frontmatter.description,
|
|
30
|
+
compatibility: skill.frontmatter.compatibility ?? null,
|
|
31
|
+
user_invocable: skill.frontmatter['user-invocable'] ?? true,
|
|
32
|
+
disable_model_invocation: skill.frontmatter['disable-model-invocation'] ?? false,
|
|
33
|
+
},
|
|
34
|
+
files: files.map((file) => ({
|
|
35
|
+
path: file.relativePath,
|
|
36
|
+
size: file.bytes.length,
|
|
37
|
+
sha256: file.sha256,
|
|
38
|
+
})),
|
|
39
|
+
note: 'This archive is a zip file with a .skill extension. Compatible agents can extract and install the included skill directory.',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function buildSkillPackage(skillDir, options = {}) {
|
|
44
|
+
const validation = await validateSkillDirectory(skillDir);
|
|
45
|
+
if (!validation.valid) {
|
|
46
|
+
throw new Error(`Cannot package invalid skill:\n- ${validation.errors.join('\n- ')}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const skill = await loadSkill(skillDir);
|
|
50
|
+
const discoveredFiles = await collectFiles(skillDir);
|
|
51
|
+
const files = [];
|
|
52
|
+
for (const file of discoveredFiles) {
|
|
53
|
+
if (file.relativePath.endsWith('.skill')) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const bytes = toUint8Array(await readFile(file.absolutePath));
|
|
57
|
+
files.push({
|
|
58
|
+
...file,
|
|
59
|
+
bytes,
|
|
60
|
+
sha256: sha256(bytes),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const manifest = createPackageManifest(skill, files, options);
|
|
65
|
+
const archiveEntries = {
|
|
66
|
+
[PACKAGE_MANIFEST_PATH]: strToU8(JSON.stringify(manifest, null, 2)),
|
|
67
|
+
};
|
|
68
|
+
for (const file of files) {
|
|
69
|
+
archiveEntries[file.relativePath] = file.bytes;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
manifest,
|
|
74
|
+
bytes: zipSync(archiveEntries, { level: 6 }),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function writeSkillPackage(skillDir, outputPath, options = {}) {
|
|
79
|
+
const result = await buildSkillPackage(skillDir, options);
|
|
80
|
+
await writeFile(outputPath, result.bytes);
|
|
81
|
+
return {
|
|
82
|
+
...result,
|
|
83
|
+
outputPath: path.resolve(outputPath),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function parseArgs(argv) {
|
|
88
|
+
const args = {
|
|
89
|
+
skillDir: argv[2],
|
|
90
|
+
output: undefined,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
for (let index = 3; index < argv.length; index += 1) {
|
|
94
|
+
const token = argv[index];
|
|
95
|
+
if (token === '--output' && argv[index + 1]) {
|
|
96
|
+
args.output = argv[++index];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return args;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
103
|
export async function main(argv = process.argv) {
|
|
104
104
|
const args = parseArgs(argv);
|
|
105
|
-
if (!args.skillDir) {
|
|
106
|
-
console.error('Usage: node scripts/package-skill.js <skill-dir> [--output <file.skill>]');
|
|
107
|
-
process.exit(1);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const skill = await loadSkill(args.skillDir);
|
|
111
|
-
const outputPath = args.output ?? path.join(path.dirname(args.skillDir), `${skill.frontmatter.name}.skill`);
|
|
112
|
-
const result = await writeSkillPackage(args.skillDir, outputPath);
|
|
113
|
-
console.log(`Wrote ${result.outputPath}`);
|
|
114
|
-
}
|
|
115
|
-
|
|
105
|
+
if (!args.skillDir) {
|
|
106
|
+
console.error('Usage: node scripts/package-skill.js <skill-dir> [--output <file.skill>]');
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const skill = await loadSkill(args.skillDir);
|
|
111
|
+
const outputPath = args.output ?? path.join(path.dirname(args.skillDir), `${skill.frontmatter.name}.skill`);
|
|
112
|
+
const result = await writeSkillPackage(args.skillDir, outputPath);
|
|
113
|
+
console.log(`Wrote ${result.outputPath}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
116
|
const isDirectRun = process.env.KODAX_MODULE_BUNDLE !== 'true'
|
|
117
117
|
&& process.argv[1]
|
|
118
|
-
&& fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
119
|
-
|
|
120
|
-
if (isDirectRun) {
|
|
121
|
-
main().catch((error) => {
|
|
122
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
123
|
-
process.exit(1);
|
|
124
|
-
});
|
|
125
|
-
}
|
|
118
|
+
&& fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
119
|
+
|
|
120
|
+
if (isDirectRun) {
|
|
121
|
+
main().catch((error) => {
|
|
122
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
123
|
+
process.exit(1);
|
|
124
|
+
});
|
|
125
|
+
}
|