prizmkit 1.1.53 → 1.1.54
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/bin/create-prizmkit.js +2 -0
- package/bundled/VERSION.json +3 -3
- package/bundled/skills/_metadata.json +1 -1
- package/package.json +1 -1
- package/src/index.js +10 -0
- package/src/scaffold.js +124 -7
package/bin/create-prizmkit.js
CHANGED
|
@@ -41,6 +41,8 @@ program
|
|
|
41
41
|
.option('--no-playwright-cli', 'Disable playwright-cli installation')
|
|
42
42
|
.option('--open-cli', 'Install opencli browser tool (default: true)')
|
|
43
43
|
.option('--no-open-cli', 'Disable opencli installation')
|
|
44
|
+
.option('--open-cli-auto-download', 'Auto-download opencli extension if missing (default: true)')
|
|
45
|
+
.option('--no-open-cli-auto-download', 'Skip auto-download, show manual steps only')
|
|
44
46
|
.option('--rules <preset>', 'Rules preset: recommended, minimal, or none', 'recommended')
|
|
45
47
|
.option('--ai-cli <command>', 'AI CLI executable command (e.g. cbc, claude, claude-internal)')
|
|
46
48
|
.option('--external-skills <names>', 'Comma-separated external skill names to install (e.g. find-skills,impeccable)')
|
package/bundled/VERSION.json
CHANGED
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -69,6 +69,7 @@ export async function runScaffold(directory, options) {
|
|
|
69
69
|
pipeline: options.pipeline !== false,
|
|
70
70
|
playwrightCli: options.playwrightCli !== false,
|
|
71
71
|
openCli: options.openCli !== false,
|
|
72
|
+
openCliAutoDownload: options.openCliAutoDownload !== false,
|
|
72
73
|
rules: options.rules || 'recommended',
|
|
73
74
|
aiCli: options.aiCli || '',
|
|
74
75
|
externalSkills: options.externalSkills ? options.externalSkills.split(',').map(s => s.trim()).filter(Boolean) : [],
|
|
@@ -198,6 +199,14 @@ export async function runScaffold(directory, options) {
|
|
|
198
199
|
default: true,
|
|
199
200
|
});
|
|
200
201
|
|
|
202
|
+
let openCliAutoDownload = true;
|
|
203
|
+
if (openCli) {
|
|
204
|
+
openCliAutoDownload = await confirm({
|
|
205
|
+
message: '检测到 Chrome Browser Bridge 扩展缺失时,自动下载扩展包?\n (仍需手动在 Chrome 中加载,但可省去下载解压步骤)',
|
|
206
|
+
default: true,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
201
210
|
// 5. Rules 预设
|
|
202
211
|
const rulesPreset = await select({
|
|
203
212
|
message: '安装 AI 行为规则 (rules):',
|
|
@@ -248,6 +257,7 @@ export async function runScaffold(directory, options) {
|
|
|
248
257
|
pipeline,
|
|
249
258
|
playwrightCli,
|
|
250
259
|
openCli,
|
|
260
|
+
openCliAutoDownload,
|
|
251
261
|
rules: rulesPreset,
|
|
252
262
|
aiCli: aiCli || '',
|
|
253
263
|
externalSkills: selectedExternalSkills,
|
package/src/scaffold.js
CHANGED
|
@@ -778,6 +778,27 @@ export async function installPlaywrightCli(projectRoot, dryRun) {
|
|
|
778
778
|
console.log(chalk.yellow(` ⚠ Skills install skipped: ${e.message}`));
|
|
779
779
|
console.log(chalk.yellow(' ⚠ Run manually: playwright-cli install --skills'));
|
|
780
780
|
}
|
|
781
|
+
|
|
782
|
+
// Install Playwright browser binary (needed for E2E testing via prizmkit-test)
|
|
783
|
+
try {
|
|
784
|
+
const cacheDir = process.env.PLAYWRIGHT_BROWSERS_PATH
|
|
785
|
+
|| path.join(process.env.HOME || process.env.USERPROFILE || '.',
|
|
786
|
+
process.platform === 'darwin' ? 'Library/Caches/ms-playwright'
|
|
787
|
+
: process.platform === 'win32' ? 'AppData/Local/ms-playwright'
|
|
788
|
+
: '.cache/ms-playwright');
|
|
789
|
+
const hasChromium = fs.pathExistsSync(cacheDir)
|
|
790
|
+
&& fs.readdirSync(cacheDir).some(d => d.startsWith('chromium-'));
|
|
791
|
+
if (hasChromium) {
|
|
792
|
+
console.log(chalk.green(' ✓ Playwright Chromium (already installed)'));
|
|
793
|
+
} else {
|
|
794
|
+
console.log(chalk.blue(' ⏳ Installing Playwright Chromium (needed for E2E testing)...'));
|
|
795
|
+
execSync('npx --yes playwright install chromium', { stdio: 'pipe', timeout: 180000 });
|
|
796
|
+
console.log(chalk.green(' ✓ Playwright Chromium installed'));
|
|
797
|
+
}
|
|
798
|
+
} catch (e) {
|
|
799
|
+
console.log(chalk.yellow(` ⚠ Playwright browser install skipped: ${e.message}`));
|
|
800
|
+
console.log(chalk.yellow(' ⚠ Run manually: npx playwright install chromium'));
|
|
801
|
+
}
|
|
781
802
|
}
|
|
782
803
|
|
|
783
804
|
// ============================================================
|
|
@@ -788,7 +809,7 @@ export async function installPlaywrightCli(projectRoot, dryRun) {
|
|
|
788
809
|
* 安装 opencli(全局 npm 包)
|
|
789
810
|
* 用于浏览器交互验证,复用 Chrome 已登录会话(OAuth/SSO/第三方集成)
|
|
790
811
|
*/
|
|
791
|
-
export async function installOpenCli(projectRoot, dryRun) {
|
|
812
|
+
export async function installOpenCli(projectRoot, dryRun, autoDownload = true) {
|
|
792
813
|
if (dryRun) {
|
|
793
814
|
console.log(chalk.gray(' [dry-run] @jackwener/opencli (global install)'));
|
|
794
815
|
return;
|
|
@@ -811,10 +832,105 @@ export async function installOpenCli(projectRoot, dryRun) {
|
|
|
811
832
|
}
|
|
812
833
|
}
|
|
813
834
|
|
|
814
|
-
//
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
835
|
+
// Verify opencli connectivity — Chrome Browser Bridge extension is a manual install
|
|
836
|
+
try {
|
|
837
|
+
const doctorOutput = execSync('opencli doctor 2>&1', { stdio: 'pipe', timeout: 15000 }).toString();
|
|
838
|
+
if (doctorOutput.includes('[MISSING] Extension') || doctorOutput.includes('[FAIL] Connectivity')) {
|
|
839
|
+
console.log(chalk.yellow(' ⚠ Chrome Browser Bridge extension is NOT connected'));
|
|
840
|
+
|
|
841
|
+
if (autoDownload) {
|
|
842
|
+
await downloadOpenCliExtension(projectRoot);
|
|
843
|
+
} else {
|
|
844
|
+
printOpenCliManualSteps();
|
|
845
|
+
}
|
|
846
|
+
} else {
|
|
847
|
+
console.log(chalk.green(' ✓ opencli connectivity verified'));
|
|
848
|
+
}
|
|
849
|
+
} catch {
|
|
850
|
+
// doctor command itself failed — already warned about install issues
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// ============================================================
|
|
855
|
+
// OpenCLI Extension 下载/指引
|
|
856
|
+
// ============================================================
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* 从 GitHub releases 下载并解压 opencli Chrome 扩展。
|
|
860
|
+
* 省去用户手动下载解压步骤,但仍需在 Chrome 中手动加载。
|
|
861
|
+
*/
|
|
862
|
+
async function downloadOpenCliExtension(projectRoot) {
|
|
863
|
+
const extDir = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.opencli', 'extension');
|
|
864
|
+
|
|
865
|
+
// Check if already downloaded
|
|
866
|
+
const manifestPath = path.join(extDir, 'manifest.json');
|
|
867
|
+
if (fs.pathExistsSync(manifestPath)) {
|
|
868
|
+
console.log(chalk.green(` ✓ Extension already downloaded at ${extDir}`));
|
|
869
|
+
printOpenCliLoadSteps(extDir);
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
try {
|
|
874
|
+
console.log(chalk.blue(' ⏳ Fetching latest extension release info...'));
|
|
875
|
+
const releaseJson = execSync(
|
|
876
|
+
'curl -sL https://api.github.com/repos/jackwener/OpenCLI/releases/latest',
|
|
877
|
+
{ stdio: 'pipe', timeout: 30000 }
|
|
878
|
+
).toString();
|
|
879
|
+
const release = JSON.parse(releaseJson);
|
|
880
|
+
const extAsset = release.assets?.find(a => a.name?.startsWith('opencli-extension-') && a.name?.endsWith('.zip'));
|
|
881
|
+
|
|
882
|
+
if (!extAsset) {
|
|
883
|
+
console.log(chalk.yellow(' ⚠ Could not find extension asset in latest release'));
|
|
884
|
+
printOpenCliManualSteps();
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
console.log(chalk.blue(` ⏳ Downloading ${extAsset.name}...`));
|
|
889
|
+
const tmpZip = path.join(extDir, '..', '.opencli-ext-tmp.zip');
|
|
890
|
+
await fs.ensureDir(path.dirname(tmpZip));
|
|
891
|
+
execSync(`curl -sL "${extAsset.browser_download_url}" -o "${tmpZip}"`, { stdio: 'pipe', timeout: 60000 });
|
|
892
|
+
|
|
893
|
+
// Extract (use unzip on macOS/Linux, tar on Windows fallback)
|
|
894
|
+
console.log(chalk.blue(` ⏳ Extracting to ${extDir}...`));
|
|
895
|
+
await fs.ensureDir(extDir);
|
|
896
|
+
execSync(`unzip -o "${tmpZip}" -d "${extDir}"`, { stdio: 'pipe', timeout: 30000 });
|
|
897
|
+
await fs.remove(tmpZip);
|
|
898
|
+
|
|
899
|
+
console.log(chalk.green(` ✓ Extension extracted to ${extDir}`));
|
|
900
|
+
printOpenCliLoadSteps(extDir);
|
|
901
|
+
} catch (e) {
|
|
902
|
+
console.log(chalk.yellow(` ⚠ Extension download failed: ${e.message}`));
|
|
903
|
+
printOpenCliManualSteps();
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* 显示手动安装步骤(兜底路径)。
|
|
909
|
+
*/
|
|
910
|
+
function printOpenCliManualSteps() {
|
|
911
|
+
console.log(chalk.cyan(' ┌─────────────────────────────────────────────────────────────┐'));
|
|
912
|
+
console.log(chalk.cyan(' │ To enable opencli browser control: │'));
|
|
913
|
+
console.log(chalk.cyan(' │ 1. Download extension from: │'));
|
|
914
|
+
console.log(chalk.cyan(' │ https://github.com/jackwener/opencli/releases │'));
|
|
915
|
+
console.log(chalk.cyan(' │ 2. Unzip the extension file │'));
|
|
916
|
+
console.log(chalk.cyan(' │ 3. Open chrome://extensions/ → Enable Developer Mode │'));
|
|
917
|
+
console.log(chalk.cyan(' │ 4. Click "Load unpacked" → select the extension folder │'));
|
|
918
|
+
console.log(chalk.cyan(' │ 5. Run "opencli doctor" to verify connectivity │'));
|
|
919
|
+
console.log(chalk.cyan(' └─────────────────────────────────────────────────────────────┘'));
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/**
|
|
923
|
+
* 显示加载已解压扩展的指引(已自动下载解压后)。
|
|
924
|
+
*/
|
|
925
|
+
function printOpenCliLoadSteps(extDir) {
|
|
926
|
+
console.log(chalk.yellow(' ⚠ Browser commands will NOT work until the extension is loaded in Chrome'));
|
|
927
|
+
console.log(chalk.cyan(' ┌─────────────────────────────────────────────────────────────┐'));
|
|
928
|
+
console.log(chalk.cyan(' │ To complete setup: │'));
|
|
929
|
+
console.log(chalk.cyan(` │ 1. Open chrome://extensions/ → Enable Developer Mode │`));
|
|
930
|
+
console.log(chalk.cyan(` │ 2. Click "Load unpacked" → select: │`));
|
|
931
|
+
console.log(chalk.cyan(` │ ${extDir}`));
|
|
932
|
+
console.log(chalk.cyan(' │ 3. Run "opencli doctor" to verify connectivity │'));
|
|
933
|
+
console.log(chalk.cyan(' └─────────────────────────────────────────────────────────────┘'));
|
|
818
934
|
}
|
|
819
935
|
|
|
820
936
|
// ============================================================
|
|
@@ -852,11 +968,12 @@ export const EXTRAS_REGISTRY = {
|
|
|
852
968
|
* @param {string[]} [config.externalSkills] - 要安装的外部 skill 名称列表
|
|
853
969
|
* @param {boolean} [config.playwrightCli] - 是否安装 playwright-cli
|
|
854
970
|
* @param {boolean} [config.openCli] - 是否安装 opencli
|
|
971
|
+
* @param {boolean} [config.openCliAutoDownload] - opencli 扩展缺失时是否自动下载
|
|
855
972
|
* @param {string} config.projectRoot - 目标项目根目录
|
|
856
973
|
* @param {boolean} config.dryRun - 是否为预览模式
|
|
857
974
|
*/
|
|
858
975
|
export async function scaffold(config) {
|
|
859
|
-
const { platform, skills, team, pipeline, rules, aiCli, externalSkills, playwrightCli, openCli, projectRoot, dryRun } = config;
|
|
976
|
+
const { platform, skills, team, pipeline, rules, aiCli, externalSkills, playwrightCli, openCli, openCliAutoDownload, projectRoot, dryRun } = config;
|
|
860
977
|
const platforms = platform === 'both' ? ['codebuddy', 'claude'] : [platform];
|
|
861
978
|
|
|
862
979
|
if (dryRun) {
|
|
@@ -961,7 +1078,7 @@ export async function scaffold(config) {
|
|
|
961
1078
|
if (openCli) {
|
|
962
1079
|
activeExtras.push('opencli');
|
|
963
1080
|
console.log(chalk.blue(` ${EXTRAS_REGISTRY['opencli'].label}:`));
|
|
964
|
-
await installOpenCli(projectRoot, dryRun);
|
|
1081
|
+
await installOpenCli(projectRoot, dryRun, openCliAutoDownload);
|
|
965
1082
|
console.log('');
|
|
966
1083
|
}
|
|
967
1084
|
|