@haposoft/cafekit 0.7.27 → 0.7.28

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haposoft/cafekit",
3
- "version": "0.7.27",
3
+ "version": "0.7.28",
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",
@@ -132,11 +132,10 @@ When you need to search the internet for information (research, docs lookup, tro
132
132
 
133
133
  | Priority | Tool | Command | When to use |
134
134
  |----------|------|---------|-------------|
135
- | 🥇 **P1** | `web-search.cjs` | `node .claude/scripts/web-search.cjs "[query]"` | **EXCLUSIVE PRIMARY.** Works via Gemini Grounding. Supports `--multi`. **TRUST THE SYNTHESIZED ANSWER** do NOT manually scrape source URLs. |
136
- | 🥈 **P2** | `WebSearch` (native) | Use WebSearch tool directly | Secondary verification, or when P1 fails. |
137
- | 🥉 **P3** | `docs-fetch.js` | `node .claude/scripts/docs-fetch.js "library"` | Only for fetching raw documentation when synthesis is insufficient. |
135
+ | 🥇 **P1** | `WebSearch` (native) | Use WebSearch tool directly | Primary search path for internet lookup and current information. |
136
+ | 🥈 **P2** | `WebFetch` / direct fetch | Use only when a specific source URL must be inspected directly | Fallback for targeted source verification and raw document reading. |
138
137
 
139
- **IMPORTANT**: When the user asks you to find information, research a topic, or investigate anything that requires internet access, you MUST use the Web Search Protocol above. **NEVER** reply with "I cannot search the web". **NEVER** attempt manual `Fetch` or Python-based scraping for search results if `web-search.cjs` provides an answer. Trust the grounding.
138
+ **IMPORTANT**: When the user asks you to find information, research a topic, or investigate anything that requires internet access, you MUST use the protocol above. **NEVER** reply with "I cannot search the web". Prefer native search first, then inspect raw sources only when needed for verification or missing detail.
140
139
 
141
140
  ## Code Quality
142
141
 
@@ -175,4 +174,4 @@ When generating spec documents (`requirements.md`, `design.md`, `research.md`, `
175
174
  - **Code samples and file paths** are always in English.
176
175
  - If the user switches language mid-project, ask which language to standardize on and apply it uniformly to all new and regenerated spec files.
177
176
 
178
- **MANDATORY DIRECTIVE:** All directives within this document, particularly the **Behavioral Principles** and **Operational Procedures**, are absolute core constraints. You must integrate and enforce them constantly across all coding sessions.
177
+ **MANDATORY DIRECTIVE:** All directives within this document, particularly the **Behavioral Principles** and **Operational Procedures**, are absolute core constraints. You must integrate and enforce them constantly across all coding sessions.
@@ -23,7 +23,7 @@ Before finalizing and emitting a Research Summary Report, you must assert the fo
23
23
  ## Skill Artillery (Your Skills)
24
24
 
25
25
  **CRITICAL**: Deploy `research` skills aggressively to anatomize technology stacks flawlessly.
26
- **CRITICAL**: Fully exploit internal localized Bash scripts (specifically `node scripts/docs-fetch.js`) to scrape massive payloads of API documentation without manually hunting through raw URLs.
26
+ **CRITICAL**: Use `WebFetch` aggressively when a specific authoritative source must be inspected directly instead of relying on secondary summaries.
27
27
 
28
28
  ## Role Responsibilities
29
29
  - **SUPREME DIRECTIVE**: Maximize token reduction while pushing output velocities for highly-condensed, brilliant technical summaries.
@@ -41,10 +41,9 @@ You possess extreme proficiency in:
41
41
  - Segregating Stable Production Practices away from Toxic Experimental Paradigms.
42
42
  - Sniffing out valid Adoption Patterns and real-world implementation trending.
43
43
  - Forgiving nothing when crafting Trade-off computational matrices for thousands of competing libraries.
44
- - **[PRIORITY 1]** Deploying `node .claude/scripts/web-search.cjs "[query]"` as the **EXCLUSIVE PRIMARY search tool**. This tool uses Gemini Grounding to return a synthesized **answer** plus cited sources. **STOP SEARCHING** once you have a sufficient answer from this script. Do NOT manually crawl source URLs if the provided synthesis is clear.
45
- - **[PRIORITY 2]** Trust the script's output directly. READ the JSON and extract the `answer` field. **STRICTLY FORBIDDEN**: Writing Python scripts to parse this JSON or manually `Fetch` every URL listed in the sources unless the user explicitly demands a deep-dive implementation detail only found in a raw document.
46
- - **[PRIORITY 3]** If `web-search.cjs` fails or returns no results, use native `WebSearch` tool (if available) as a backup.
47
- - **[PRIORITY 4]** Deploying `scripts/docs-fetch.js` ONLY for raw documents where the direct URL is already known and synthesis is insufficient.
44
+ - **[PRIORITY 1]** Use native `WebSearch` as the primary search tool for current information, docs discovery, troubleshooting, and competitive research.
45
+ - **[PRIORITY 2]** Verify key claims across multiple credible sources. Prefer official docs, maintainer materials, release notes, and strong production references over generic blogs.
46
+ - **[PRIORITY 3]** Use direct `WebFetch` when a specific source must be inspected line-by-line for evidence, API detail, or implementation constraints.
48
47
  - Deploying Bash and raw Grep utilities to surgically dissect embedded Document architectures and internal file payloads to evaluate raw insights.
49
48
 
50
49
  **ABSOLUTE IMMOVEABLE DIRECTIVE**: You are **STRICTLY PROHIBITED** from generating executable endpoint "Implementation Code". You exist ONLY to maneuver data streams, render synthesis Summary text, and return comprehensive Markdown documentation pathways to the main caller Agent.
@@ -65,7 +65,7 @@ const DEFAULT_CONFIG = {
65
65
  'session-init': true,
66
66
  'subagent-init': true,
67
67
  'dev-rules-reminder': true,
68
- 'usage-context-awareness': true,
68
+ 'usage': true,
69
69
  'context-tracking': true,
70
70
  'scout-block': true,
71
71
  'privacy-block': true,
@@ -489,7 +489,7 @@ function buildReminder(params) {
489
489
  // Respect hooks config — skip sections when their corresponding hook is disabled
490
490
  const hooksConfig = hooks || {};
491
491
  const contextEnabled = hooksConfig['context-tracking'] !== false;
492
- const usageEnabled = hooksConfig['usage-context-awareness'] !== false;
492
+ const usageEnabled = hooksConfig['usage'] !== false;
493
493
 
494
494
  return [
495
495
  ...buildLanguageSection({ thinkingLanguage, responseLanguage }),
@@ -564,7 +564,7 @@ function buildReminderContext({ sessionId, config, staticEnv, configDirName = '.
564
564
  // Respect hooks config for sections object too
565
565
  const hooksConfig = cfg.hooks || {};
566
566
  const contextEnabled = hooksConfig['context-tracking'] !== false;
567
- const usageEnabled = hooksConfig['usage-context-awareness'] !== false;
567
+ const usageEnabled = hooksConfig['usage'] !== false;
568
568
 
569
569
  return {
570
570
  content: lines.join('\n'),
@@ -54,10 +54,8 @@
54
54
  },
55
55
  "scripts": {
56
56
  "required": [
57
- "docs-fetch.js",
58
57
  "validate-docs.cjs",
59
- "browser-tool.cjs",
60
- "web-search.cjs"
58
+ "browser-tool.cjs"
61
59
  ]
62
60
  },
63
61
  "agentReferences": {
@@ -3,12 +3,12 @@
3
3
  Never guess the API syntax of third-party libraries, especially when the system is throwing "Deprecated" or "Undefined Function" errors.
4
4
 
5
5
  ## Where is the Arsenal? (Zero-token Execution Strategy)
6
- Commanders must utilize the native independent script embedded directly within the tooling framework(`scripts/docs-fetch.js`) by transmitting direct execution commands (Execute) into bash. Documentation retrieval speeds will be 100x faster and entirely avoid context window degradation.
6
+ Commanders should use `WebFetch` against authoritative documentation URLs when raw source inspection is required. Prefer direct source verification over secondary summaries when debugging ambiguous API behavior.
7
7
 
8
8
  ## Bash Execution Procedure:
9
9
  1. **[Script] Fetch Link and Analyze (Fetch/Detect):**
10
10
  ```bash
11
- node scripts/docs-fetch.js "How to use useForm in React Hook Form"
11
+ WebFetch the official React Hook Form documentation page for `useForm`
12
12
  ```
13
13
 
14
- **Core Imperative:** Never hesitate to call `node scripts/docs-fetch.js` if the library is officially supported or widely known. This mechanism violently exploits automated allied tooling to maximize operational speed.
14
+ **Core Imperative:** Never hesitate to use `WebFetch` when the exact source page is known and line-by-line inspection is needed to resolve uncertainty quickly.
@@ -23,11 +23,11 @@ Call the `TaskCreate` tool to spin up the `researcher` subagent.
23
23
  **Instructions to pass to Researcher:**
24
24
  ```text
25
25
  Conduct comprehensive research on: [topic]
26
- Constraint 1: ALWAYS use `node .claude/scripts/web-search.cjs "[query]"` as the EXCLUSIVE primary search method. This tool uses Gemini Grounding and returns a synthesized answer + cited sources. Do NOT manually crawl source URLs if the script provides a sufficient answer.
27
- Constraint 2: TRUST THE SYNTHESIS. The output contains the research results. Read the JSON and use the `answer` field directly. Do NOT write Python scripts to re-parse it or manually `Fetch` sources unless deep implementation details are missing.
28
- Constraint 3: Use native WebSearch or manual Fetch ONLY if the script fails or returns no results.
26
+ Constraint 1: ALWAYS use native `WebSearch` as the primary search method.
27
+ Constraint 2: Validate key claims with multiple credible sources. Prioritize official docs, maintainers, release notes, and strong production references.
28
+ Constraint 3: Use direct `WebFetch` only when search results are insufficient or raw source inspection is required.
29
29
  Constraint 4: Limit total search calls to a maximum of 5 distinct queries.
30
- Constraint 5: Stop excessive "chain-searching". Use the grounding answer as the definitive summary.
30
+ Constraint 5: Stop excessive "chain-searching". Synthesize decisively once the evidence is sufficient.
31
31
  Output Format: Must strictly follow the 'Standard Research Report' layout.
32
32
  ```
33
33
 
@@ -1,81 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Native Docs Fetcher
4
- * Aggregates extraction of `llms.txt` patterns from context7.com (Unified logic).
5
- * Usage: node docs-fetch.js "How to use Next.js App router"
6
- */
7
-
8
- const https = require('https');
9
-
10
- function fetchUrl(url) {
11
- return new Promise((resolve) => {
12
- https.get(url, { headers: { 'User-Agent': 'Docs-Fetcher' } }, (res) => {
13
- let data = '';
14
- res.on('data', chunk => data += chunk);
15
- res.on('end', () => resolve({ status: res.statusCode, data }));
16
- }).on('error', () => resolve({ status: 500, data: null }));
17
- });
18
- }
19
-
20
- async function main() {
21
- const args = process.argv.slice(2);
22
- if (args.length === 0) {
23
- console.error('[Docs Fetcher] Error: Explicit query parameter required. (Example: node docs-fetch.js "next.js router")');
24
- process.exit(1);
25
- }
26
-
27
- const query = args.join(' ').toLowerCase();
28
-
29
- // Smart Detection (Keyword mapping index)
30
- const knownLibs = {
31
- 'next.js': 'vercel/next.js',
32
- 'nextjs': 'vercel/next.js',
33
- 'react': 'facebook/react',
34
- 'shadcn': 'shadcn-ui/ui',
35
- 'shadcn/ui': 'shadcn-ui/ui',
36
- 'astro': 'withastro/astro',
37
- 'remix': 'remix-run/remix'
38
- };
39
-
40
- let targetRepo = '';
41
- for (const [key, repo] of Object.entries(knownLibs)) {
42
- if (query.includes(key)) {
43
- targetRepo = repo;
44
- break;
45
- }
46
- }
47
-
48
- // Heuristic string fallback matching for "docs for abc" sequences
49
- if (!targetRepo) {
50
- const fallbackMatch = query.match(/for ([a-z0-9-]+)/);
51
- if (fallbackMatch) targetRepo = `websites/${fallbackMatch[1]}`;
52
- else targetRepo = `websites/${query.split(' ')[0]}`; // Fallback primitive string assumption
53
- }
54
-
55
- const url = `https://context7.com/${targetRepo}/llms.txt`;
56
- console.log(`[Docs Fetcher] Interrogating Knowledge Archival Node at: ${url}`);
57
-
58
- const fallbackUrl = `https://raw.githubusercontent.com/${targetRepo}/main/README.md`;
59
-
60
- const result = await fetchUrl(url);
61
-
62
- if (result.status === 200 && result.data) {
63
- console.log('\n--- SUCCESSFUL PAYLOAD EXTRACTED ---');
64
- // Buffer restriction truncation
65
- console.log(result.data.substring(0, 3000));
66
- console.log('\n(Output truncated cleanly to minimize LLM Context Overload)');
67
- } else {
68
- console.warn(`[!] Architectural layout llms.txt missing at: ${url}`);
69
- console.log(`[+] Executing GitHub default branch failover (README.md mapping): ${fallbackUrl}`);
70
- const fbResult = await fetchUrl(fallbackUrl);
71
- if (fbResult.status === 200 && fbResult.data) {
72
- console.log('\n--- PAYLOAD EXTRACTED (README.md) ---');
73
- console.log(fbResult.data.substring(0, 3000));
74
- } else {
75
- console.error('\n[FATAL] Documentation retrieval failure. No corresponding books identified within known databanks. Agent must fall back to utilizing standard WebSearch mapping via DuckDuckGo execution streams!');
76
- process.exit(1);
77
- }
78
- }
79
- }
80
-
81
- main();
@@ -1,211 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Web Search via Gemini API + Google Search Grounding
4
- * Fallback search tool for models without native WebSearch capability.
5
- *
6
- * Usage:
7
- * node web-search.cjs "your search query here"
8
- * node web-search.cjs --multi "query1" "query2" "query3"
9
- *
10
- * Requires: GEMINI_API_KEY in .claude/.env or environment
11
- *
12
- * Output: JSON-structured search results with sources and citations.
13
- */
14
-
15
- const https = require('https');
16
- const path = require('path');
17
- const fs = require('fs');
18
-
19
- // ---------------------------------------------------------------------------
20
- // ENV Resolution: .claude/.env → process.env
21
- // ---------------------------------------------------------------------------
22
- function loadEnv() {
23
- const envPaths = [
24
- path.join(process.cwd(), '.claude', '.env'),
25
- path.join(process.cwd(), '..', '.claude', '.env'),
26
- ];
27
-
28
- for (const envPath of envPaths) {
29
- try {
30
- if (fs.existsSync(envPath)) {
31
- const content = fs.readFileSync(envPath, 'utf8');
32
- content.split(/\r?\n/).forEach(line => {
33
- const match = line.match(/^([^=]+)=(.*)$/);
34
- if (match) {
35
- const key = match[1].trim();
36
- const val = match[2].trim().replace(/^["']|["']$/g, '');
37
- // Only set if not already present in environment
38
- if (process.env[key] === undefined) {
39
- process.env[key] = val;
40
- }
41
- }
42
- });
43
- return; // Loaded successfully, no need to check other paths
44
- }
45
- } catch { /* skip */ }
46
- }
47
- }
48
-
49
- // ---------------------------------------------------------------------------
50
- // Gemini API Call with Google Search Grounding
51
- // ---------------------------------------------------------------------------
52
- function callGemini(apiKey, query, model) {
53
- return new Promise((resolve, reject) => {
54
- const payload = JSON.stringify({
55
- contents: [{ parts: [{ text: query }] }],
56
- tools: [{ googleSearch: {} }],
57
- generationConfig: {
58
- temperature: 0.1,
59
- maxOutputTokens: 4096,
60
- }
61
- });
62
-
63
- const options = {
64
- hostname: 'generativelanguage.googleapis.com',
65
- path: `/v1beta/models/${model}:generateContent?key=${apiKey}`,
66
- method: 'POST',
67
- headers: {
68
- 'Content-Type': 'application/json',
69
- 'Content-Length': Buffer.byteLength(payload),
70
- },
71
- };
72
-
73
- const req = https.request(options, (res) => {
74
- let data = '';
75
- res.on('data', chunk => data += chunk);
76
- res.on('end', () => {
77
- try {
78
- const json = JSON.parse(data);
79
- if (json.error) {
80
- reject(new Error(`Gemini API Error: ${json.error.message}`));
81
- return;
82
- }
83
- resolve(json);
84
- } catch (e) {
85
- reject(new Error(`Failed to parse Gemini response: ${e.message}`));
86
- }
87
- });
88
- });
89
-
90
- req.on('error', reject);
91
- req.write(payload);
92
- req.end();
93
- });
94
- }
95
-
96
- // ---------------------------------------------------------------------------
97
- // Resolve Vertex AI grounding redirect URLs to real URLs
98
- // ---------------------------------------------------------------------------
99
- function resolveRedirectUrl(url) {
100
- return new Promise((resolve) => {
101
- if (!url || !url.includes('grounding-api-redirect')) {
102
- resolve(url);
103
- return;
104
- }
105
-
106
- const protocol = url.startsWith('https') ? https : require('http');
107
- const req = protocol.request(url, { method: 'HEAD', timeout: 5000 }, (res) => {
108
- // Follow redirect chain - Location header has the real URL
109
- resolve(res.headers.location || url);
110
- });
111
- req.on('error', () => resolve(url));
112
- req.on('timeout', () => { req.destroy(); resolve(url); });
113
- req.end();
114
- });
115
- }
116
-
117
- async function resolveAllUrls(sources) {
118
- return Promise.all(sources.map(async (src) => {
119
- const realUrl = await resolveRedirectUrl(src.url);
120
- return { ...src, url: realUrl };
121
- }));
122
- }
123
-
124
- // ---------------------------------------------------------------------------
125
- // Parse Grounding Metadata → Structured Output
126
- // ---------------------------------------------------------------------------
127
- async function parseResponse(geminiResponse, query) {
128
- const candidate = geminiResponse.candidates?.[0];
129
- if (!candidate) return { query, error: 'No candidates returned' };
130
-
131
- const text = candidate.content?.parts?.map(p => p.text).join('\n') || '';
132
- const meta = candidate.groundingMetadata || {};
133
-
134
- // Extract source URLs from groundingChunks
135
- let sources = (meta.groundingChunks || []).map(chunk => ({
136
- title: chunk.web?.title || 'Unknown',
137
- url: chunk.web?.uri || '',
138
- }));
139
-
140
- // Resolve redirect URLs to real URLs
141
- sources = await resolveAllUrls(sources);
142
-
143
- // Deduplicate by resolved URL
144
- const seen = new Set();
145
- sources = sources.filter(s => {
146
- if (seen.has(s.url)) return false;
147
- seen.add(s.url);
148
- return true;
149
- });
150
-
151
- // Extract search queries used by the model
152
- const searchQueries = meta.webSearchQueries || [];
153
-
154
- return {
155
- query,
156
- answer: text,
157
- searchQueriesUsed: searchQueries,
158
- sources,
159
- sourceCount: sources.length,
160
- };
161
- }
162
-
163
- // ---------------------------------------------------------------------------
164
- // Main
165
- // ---------------------------------------------------------------------------
166
- async function main() {
167
- const args = process.argv.slice(2);
168
- const isMulti = args[0] === '--multi';
169
- const queries = isMulti ? args.slice(1) : [args.join(' ')];
170
-
171
- if (queries.length === 0 || (queries.length === 1 && !queries[0])) {
172
- console.error(JSON.stringify({
173
- error: 'Usage: node web-search.cjs "your query" | node web-search.cjs --multi "q1" "q2"'
174
- }));
175
- process.exit(1);
176
- }
177
-
178
- loadEnv();
179
- const apiKey = process.env.GEMINI_API_KEY;
180
- if (!apiKey) {
181
- console.error(JSON.stringify({
182
- error: 'GEMINI_API_KEY not found. Set it in .claude/.env or environment variable.'
183
- }));
184
- process.exit(1);
185
- }
186
-
187
- // Determine which model to use. User might configure MODEL or VISUAL_MODEL in their .env
188
- let model = process.env.SEARCH_MODEL || process.env.MODEL || process.env.VISUAL_MODEL || 'gemini-2.5-flash';
189
-
190
- // Google Search Grounding ONLY supports Gemini models (not Claude, not Gemma)
191
- if (!model.toLowerCase().includes('gemini') && !model.toLowerCase().includes('learnlm')) {
192
- model = 'gemini-2.5-flash'; // Fallback to safe search model
193
- }
194
-
195
- const results = [];
196
-
197
- for (const query of queries) {
198
- try {
199
- const raw = await callGemini(apiKey, query, model);
200
- results.push(await parseResponse(raw, query));
201
- } catch (err) {
202
- results.push({ query, error: err.message });
203
- }
204
- }
205
-
206
- // Output as JSON for agent consumption
207
- const output = isMulti ? results : results[0];
208
- console.log(JSON.stringify(output, null, 2));
209
- }
210
-
211
- main();