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.
@@ -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)')
@@ -1,5 +1,5 @@
1
1
  {
2
- "frameworkVersion": "1.1.53",
3
- "bundledAt": "2026-05-24T05:20:15.152Z",
4
- "bundledFrom": "156de40"
2
+ "frameworkVersion": "1.1.54",
3
+ "bundledAt": "2026-05-24T14:07:35.874Z",
4
+ "bundledFrom": "4a97a4a"
5
5
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.53",
2
+ "version": "1.1.54",
3
3
  "skills": {
4
4
  "prizm-kit": {
5
5
  "description": "Full-lifecycle dev toolkit. Covers spec-driven development, Prizm context docs, code quality, debugging, deployment, and knowledge management.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prizmkit",
3
- "version": "1.1.53",
3
+ "version": "1.1.54",
4
4
  "description": "Create a new PrizmKit-powered project with clean initialization — no framework dev files, just what you need.",
5
5
  "type": "module",
6
6
  "bin": {
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
- // Note: opencli requires Chrome + Browser Bridge extension for browser-backed commands.
815
- // The extension must be installed manually — see: https://github.com/jackwener/opencli
816
- console.log(chalk.gray(' OpenCLI requires Chrome + Browser Bridge extension for browser commands'));
817
- console.log(chalk.gray(' Run "opencli doctor" to verify connectivity'));
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