@haposoft/cafekit 0.10.2 → 0.10.3

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.
@@ -81,9 +81,20 @@ function npmInstall(dir) {
81
81
  return run('npm', ['install', '--no-audit', '--no-fund'], { cwd: dir }).ok;
82
82
  }
83
83
 
84
- /** Download the Puppeteer Chromium browser for chrome-devtools. */
84
+ /**
85
+ * Download the Puppeteer Chromium browser for chrome-devtools.
86
+ * Prefer puppeteer's own install script (cache-aware, same as its postinstall);
87
+ * fall back to the bundled @puppeteer/browsers CLI. `npx puppeteer ...` is
88
+ * avoided — puppeteer ships no `puppeteer` bin under that invocation and `--yes`
89
+ * would refetch from the registry.
90
+ */
85
91
  function installChromium(scriptsDir) {
86
- return run('npx', ['--yes', 'puppeteer', 'browsers', 'install', 'chrome'], { cwd: scriptsDir }).ok;
92
+ // Absolute path so it resolves regardless of the child process cwd.
93
+ const installMjs = path.resolve(scriptsDir, 'node_modules', 'puppeteer', 'install.mjs');
94
+ if (fs.existsSync(installMjs)) {
95
+ return run('node', [installMjs], { cwd: scriptsDir }).ok;
96
+ }
97
+ return run('npx', ['--yes', '@puppeteer/browsers', 'install', 'chrome'], { cwd: scriptsDir }).ok;
87
98
  }
88
99
 
89
100
  /** Does a skill scripts dir declare a given npm dependency? */
@@ -1,19 +1,18 @@
1
1
  /**
2
2
  * Phase: post-install runtime configuration.
3
3
  *
4
- * OpenCode model, optional Gemini API key, and addressing config. Interactive
5
- * prompts use ctx.ui (clack); in non-interactive/dry-run they are skipped via
6
- * fallbacks so spawned/CI runs never hang. Writes (.env, CLAUDE.md,
7
- * opencode.json) happen only when a value is actually provided.
4
+ * OpenCode model + addressing config. Interactive prompts use ctx.ui (clack);
5
+ * in non-interactive/dry-run they are skipped via fallbacks so spawned/CI runs
6
+ * never hang.
8
7
  *
9
- * Note: CafeKit no longer installs the `gemini-cli` (the upstream package was
10
- * removed). We only configure GEMINI_API_KEY, which the SDK-based skills
11
- * (e.g. hapo:ai-multimodal) read directly.
8
+ * Note: CafeKit no longer prompts for a Gemini API key. The upstream gemini-cli
9
+ * was removed, and the key now serves only the ai-multimodal skill — which
10
+ * documents it in its own `.env.example`. Users set GEMINI_API_KEY there when
11
+ * (and only if) they use that skill.
12
12
  */
13
13
 
14
14
  const fs = require('fs');
15
15
  const path = require('path');
16
- const { PLATFORMS } = require('../lib/context');
17
16
  const { setupOpenCodeModel } = require('../lib/opencode-install');
18
17
 
19
18
  /** Human assistant name for the active platform(s). */
@@ -21,33 +20,6 @@ function assistantName(ctx) {
21
20
  return ctx.platforms.includes('claude') ? 'Claude Code' : 'OpenCode';
22
21
  }
23
22
 
24
- function configureGeminiKey(ctx, apiKey, platforms) {
25
- const envBody = `GEMINI_API_KEY=${apiKey}\nVISUAL_MODEL=gemma-4-31b-it\nSEARCH_MODEL=gemini-2.5-pro\n`;
26
- const targets = platforms.filter((key) => PLATFORMS[key]).map((key) => PLATFORMS[key].folder);
27
- if (targets.length === 0) targets.push('.claude');
28
-
29
- for (const folder of targets) {
30
- try {
31
- const targetDir = path.join(process.cwd(), folder);
32
- if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true });
33
- fs.writeFileSync(path.join(targetDir, '.env'), envBody, { mode: 0o600 });
34
- ctx.ui.success(`Gemini API key stored in ${folder}/.env (0600)`);
35
- } catch (error) {
36
- ctx.ui.error(`Failed to configure Gemini API key: ${error.message}`);
37
- }
38
- }
39
- }
40
-
41
- async function setupGeminiKey(ctx) {
42
- const apiKey = await ctx.ui.text(
43
- { message: 'Gemini API key for AI skills (Enter to skip)', placeholder: 'aistudio.google.com/apikey' },
44
- ''
45
- );
46
- if (apiKey && typeof apiKey === 'string' && apiKey.trim()) {
47
- configureGeminiKey(ctx, apiKey.trim(), ctx.platforms);
48
- }
49
- }
50
-
51
23
  function configureAddressing(ctx, userAddress) {
52
24
  const claudeMdFile = path.join(process.cwd(), 'CLAUDE.md');
53
25
  if (!fs.existsSync(claudeMdFile)) {
@@ -92,7 +64,7 @@ async function setupAddressing(ctx) {
92
64
  /** Run the post-install configuration sequence. */
93
65
  async function runPostInstall(ctx) {
94
66
  if (ctx.dryRun) {
95
- ctx.ui.info('[dry-run] Skipping OpenCode model / Gemini / addressing setup');
67
+ ctx.ui.info('[dry-run] Skipping OpenCode model / addressing setup');
96
68
  return ctx;
97
69
  }
98
70
 
@@ -103,7 +75,6 @@ async function runPostInstall(ctx) {
103
75
  await setupOpenCodeModel(ctx.platforms, ctx.results);
104
76
  }
105
77
 
106
- await setupGeminiKey(ctx);
107
78
  await setupAddressing(ctx);
108
79
 
109
80
  // Re-record CLAUDE.md baseline so the installer-managed file (template +
@@ -115,4 +86,4 @@ async function runPostInstall(ctx) {
115
86
  return ctx;
116
87
  }
117
88
 
118
- module.exports = { configureGeminiKey, configureAddressing, runPostInstall };
89
+ module.exports = { configureAddressing, runPostInstall };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haposoft/cafekit",
3
- "version": "0.10.2",
3
+ "version": "0.10.3",
4
4
  "description": "Claude Code-first spec-driven workflow for AI coding assistants. Bundles CafeKit hapo: skills, runtime hooks, agents, and installer scaffolding.",
5
5
  "author": "Haposoft <nghialt@haposoft.com>",
6
6
  "license": "MIT",