@haposoft/cafekit 0.13.4 → 0.14.0

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.
Files changed (119) hide show
  1. package/README.md +2 -23
  2. package/bin/lib/i18n.js +2 -2
  3. package/bin/lib/manifest.js +15 -0
  4. package/bin/lib/opencode-install.js +0 -14
  5. package/bin/phases/claude-runtime.js +4 -1
  6. package/bin/phases/claude-settings.js +38 -7
  7. package/bin/phases/root-config.js +5 -24
  8. package/package.json +1 -1
  9. package/src/claude/agents/ui-ux-designer.md +4 -4
  10. package/src/claude/gitignore +4 -11
  11. package/src/claude/hooks/__tests__/privacy-block.test.js +79 -0
  12. package/src/claude/hooks/__tests__/session-writeenv.test.js +68 -0
  13. package/src/claude/hooks/__tests__/spec-gate.test.js +270 -0
  14. package/src/claude/hooks/privacy-block.cjs +22 -2
  15. package/src/claude/hooks/session.cjs +5 -1
  16. package/src/claude/hooks/spec-gate.cjs +173 -0
  17. package/src/claude/hooks/spec-state.cjs +10 -17
  18. package/src/claude/hooks/task-scaffold-guard.cjs +4 -2
  19. package/src/claude/migration-manifest.json +5 -5
  20. package/src/claude/rules/skill-domain-routing.md +2 -3
  21. package/src/claude/rules/skill-workflow-routing.md +2 -11
  22. package/src/claude/rules/state-sync.md +4 -0
  23. package/src/claude/runtime.json +4 -0
  24. package/src/claude/scripts/validate-docs.cjs +4 -7
  25. package/src/claude/scripts/validate-spec-output.cjs +29 -9
  26. package/src/claude/settings/settings.json +4 -0
  27. package/src/claude/skills/ai-multimodal/.env.example +11 -13
  28. package/src/claude/skills/ai-multimodal/SKILL.md +1 -1
  29. package/src/claude/skills/ai-multimodal/references/audio-processing.md +25 -27
  30. package/src/claude/skills/ai-multimodal/references/video-analysis.md +23 -27
  31. package/src/claude/skills/ai-multimodal/references/vision-understanding.md +26 -26
  32. package/src/claude/skills/ai-multimodal/scripts/check_setup.py +1 -1
  33. package/src/claude/skills/ai-multimodal/scripts/gemini_batch_process.py +7 -9
  34. package/src/claude/skills/brainstorm/SKILL.md +1 -2
  35. package/src/claude/skills/docx/SKILL.md +1 -1
  36. package/src/claude/skills/frontend-design/SKILL.md +1 -1
  37. package/src/claude/skills/frontend-design/references/ai-multimodal-overview.md +4 -4
  38. package/src/claude/skills/frontend-design/references/analysis-techniques.md +3 -3
  39. package/src/claude/skills/frontend-design/references/asset-generation.md +2 -2
  40. package/src/claude/skills/frontend-design/references/design-extraction-overview.md +4 -4
  41. package/src/claude/skills/frontend-design/references/extraction-best-practices.md +3 -3
  42. package/src/claude/skills/frontend-design/references/technical-accessibility.md +1 -1
  43. package/src/claude/skills/frontend-design/references/technical-optimization.md +1 -1
  44. package/src/claude/skills/frontend-design/references/technical-overview.md +2 -2
  45. package/src/claude/skills/frontend-design/references/technical-workflows.md +6 -6
  46. package/src/claude/skills/frontend-design/references/visual-analysis-overview.md +3 -3
  47. package/src/claude/skills/inspect/SKILL.md +3 -3
  48. package/src/claude/skills/inspect/references/external-gemini-inspection.md +9 -9
  49. package/src/claude/skills/pdf/SKILL.md +1 -1
  50. package/src/claude/skills/pptx/SKILL.md +1 -1
  51. package/src/claude/skills/specs/SKILL.md +1 -1
  52. package/src/claude/skills/xlsx/SKILL.md +1 -1
  53. package/src/opencode/AGENTS.md +1 -2
  54. package/src/opencode/plugins/session.ts +2 -2
  55. package/src/opencode/plugins/spec-state.ts +244 -0
  56. package/src/opencode/plugins/task-scaffold-guard.ts +161 -0
  57. package/src/claude/scripts/browser-tool.cjs +0 -138
  58. package/src/claude/skills/delegate/SKILL.md +0 -124
  59. package/src/claude/skills/delegate/references/codex-delegation.md +0 -71
  60. package/src/claude/skills/delegate/references/grok-delegation.md +0 -84
  61. package/src/claude/skills/generate-graph/LICENSE +0 -21
  62. package/src/claude/skills/generate-graph/README.md +0 -523
  63. package/src/claude/skills/generate-graph/SKILL.md +0 -429
  64. package/src/claude/skills/generate-graph/agentloop-core.svg +0 -101
  65. package/src/claude/skills/generate-graph/agents/openai.yaml +0 -4
  66. package/src/claude/skills/generate-graph/assets/samples/sample-style1-flat.png +0 -0
  67. package/src/claude/skills/generate-graph/assets/samples/sample-style2-dark.png +0 -0
  68. package/src/claude/skills/generate-graph/assets/samples/sample-style3-blueprint.png +0 -0
  69. package/src/claude/skills/generate-graph/assets/samples/sample-style4-notion.png +0 -0
  70. package/src/claude/skills/generate-graph/assets/samples/sample-style5-glass.png +0 -0
  71. package/src/claude/skills/generate-graph/assets/samples/sample-style6-claude.png +0 -0
  72. package/src/claude/skills/generate-graph/assets/samples/sample-style7-openai.png +0 -0
  73. package/src/claude/skills/generate-graph/fixtures/agent-memory-types-style4.json +0 -181
  74. package/src/claude/skills/generate-graph/fixtures/api-flow-style7.json +0 -40
  75. package/src/claude/skills/generate-graph/fixtures/mem0-style1.json +0 -297
  76. package/src/claude/skills/generate-graph/fixtures/microservices-style3.json +0 -64
  77. package/src/claude/skills/generate-graph/fixtures/multi-agent-style5.json +0 -45
  78. package/src/claude/skills/generate-graph/fixtures/system-architecture-style6.json +0 -48
  79. package/src/claude/skills/generate-graph/fixtures/tool-call-style2.json +0 -182
  80. package/src/claude/skills/generate-graph/package.json +0 -42
  81. package/src/claude/skills/generate-graph/references/icons.md +0 -281
  82. package/src/claude/skills/generate-graph/references/style-1-flat-icon.md +0 -108
  83. package/src/claude/skills/generate-graph/references/style-2-dark-terminal.md +0 -107
  84. package/src/claude/skills/generate-graph/references/style-3-blueprint.md +0 -113
  85. package/src/claude/skills/generate-graph/references/style-4-notion-clean.md +0 -94
  86. package/src/claude/skills/generate-graph/references/style-5-glassmorphism.md +0 -125
  87. package/src/claude/skills/generate-graph/references/style-6-claude-official.md +0 -209
  88. package/src/claude/skills/generate-graph/references/style-7-openai.md +0 -215
  89. package/src/claude/skills/generate-graph/references/style-diagram-matrix.md +0 -135
  90. package/src/claude/skills/generate-graph/references/svg-layout-best-practices.md +0 -100
  91. package/src/claude/skills/generate-graph/scripts/generate-diagram.sh +0 -157
  92. package/src/claude/skills/generate-graph/scripts/generate-from-template.py +0 -1556
  93. package/src/claude/skills/generate-graph/scripts/test-all-styles.sh +0 -135
  94. package/src/claude/skills/generate-graph/scripts/validate-svg.sh +0 -292
  95. package/src/claude/skills/generate-graph/templates/agent-architecture.svg +0 -28
  96. package/src/claude/skills/generate-graph/templates/architecture.svg +0 -23
  97. package/src/claude/skills/generate-graph/templates/comparison-matrix.svg +0 -14
  98. package/src/claude/skills/generate-graph/templates/data-flow.svg +0 -28
  99. package/src/claude/skills/generate-graph/templates/er-diagram.svg +0 -21
  100. package/src/claude/skills/generate-graph/templates/flowchart.svg +0 -21
  101. package/src/claude/skills/generate-graph/templates/sequence.svg +0 -20
  102. package/src/claude/skills/generate-graph/templates/state-machine.svg +0 -20
  103. package/src/claude/skills/generate-graph/templates/timeline.svg +0 -19
  104. package/src/claude/skills/generate-graph/templates/use-case.svg +0 -21
  105. package/src/claude/skills/impact-analysis/SKILL.md +0 -276
  106. package/src/claude/skills/impact-analysis/references/change-detection.md +0 -270
  107. package/src/claude/skills/impact-analysis/references/dependency-scouting.md +0 -338
  108. package/src/claude/skills/impact-analysis/references/edge-case-identification.md +0 -439
  109. package/src/claude/skills/impact-analysis/references/industry-techniques.md +0 -695
  110. package/src/claude/skills/impact-analysis/references/practical-techniques-guide.md +0 -753
  111. package/src/claude/skills/impact-analysis/references/project-detection.md +0 -704
  112. package/src/claude/skills/impact-analysis/references/react-native-customization.md +0 -508
  113. package/src/claude/skills/impact-analysis/references/report-template.md +0 -604
  114. package/src/claude/skills/impact-analysis/references/test-scenario-generation.md +0 -459
  115. package/src/claude/skills/impact-analysis/scripts/README.md +0 -476
  116. package/src/claude/skills/impact-analysis/scripts/ast-analyze.js +0 -403
  117. package/src/claude/skills/impact-analysis/scripts/calculate-risk.js +0 -475
  118. package/src/claude/skills/impact-analysis/scripts/find-dependencies.sh +0 -202
  119. package/src/claude/skills/impact-analysis/scripts/run-analysis.sh +0 -312
@@ -53,17 +53,14 @@ function main() {
53
53
 
54
54
  const linkIssues = checkBrokenLinks(docsDir);
55
55
  if (linkIssues.length > 0) {
56
- console.warn('\n⚠️ WARNING: CRITICAL HYPERLINK CORRUPTION DETECTED IN DOCUMENTATION MATRIX!');
56
+ console.error(`\n❌ FAIL: ${linkIssues.length} broken relative link(s) found:`);
57
57
  linkIssues.forEach(issue => {
58
- console.warn(`- Compromised File: ${path.relative(process.cwd(), issue.file)} -> Links externally to Missing Null Pointer: ./${issue.brokenLink}`);
58
+ console.error(`- ${path.relative(process.cwd(), issue.file)} -> ./${issue.brokenLink} (target missing)`);
59
59
  });
60
- } else {
61
- console.log('✅ Validation verified! Zero broken integrity links detected across the system.');
60
+ process.exit(1);
62
61
  }
63
62
 
64
- // Structural Note: To honor Execution Velocity patterns inherent to Architecture,
65
- // aggressive deep-code grepping functions (function tracing) have been stripped.
66
- // This ensures document validation pipeline triggers definitively under < 1s (Zero-latency verification).
63
+ console.log('✅ PASS: no broken relative links detected.');
67
64
  }
68
65
 
69
66
  main();
@@ -203,11 +203,13 @@ function extractContractDefs(designText) {
203
203
  }
204
204
 
205
205
  /**
206
- * From a task body, return the contracts it claims plus the first fenced block
207
- * it carries (the task's local copy of the contract). Shape:
208
- * { names: string[], block: string|null }
209
- * `names` come from a `Contracts: A, B` line; `block` is the first fenced code
210
- * block in the task (normalized) used to compare against the canonical defs.
206
+ * From a task body, return the contracts it claims plus its local contract
207
+ * copies. Shape: { names: string[], blocks: Map<name, string>, firstBlock: string|null }
208
+ * `names` come from a `Contracts: A, B` line. `blocks` maps every
209
+ * `<!-- contract:NAME -->` marker in the task to its fenced block, so a task
210
+ * carrying multiple contracts has EACH copy verified (not just the first).
211
+ * `firstBlock` keeps the legacy fallback for single-contract tasks that copy
212
+ * the block without repeating the marker.
211
213
  */
212
214
  function extractTaskContracts(taskText) {
213
215
  const names = [];
@@ -218,9 +220,10 @@ function extractTaskContracts(taskText) {
218
220
  if (name) names.push(name);
219
221
  }
220
222
  }
223
+ const blocks = extractContractDefs(taskText); // same marker+fence grammar as design.md
221
224
  const blockMatch = taskText.match(/```[^\n]*\n([\s\S]*?)\n```/);
222
- const block = blockMatch ? normalizeBlock(blockMatch[1]) : null;
223
- return { names, block };
225
+ const firstBlock = blockMatch ? normalizeBlock(blockMatch[1]) : null;
226
+ return { names, blocks, firstBlock };
224
227
  }
225
228
 
226
229
  function validateSpec(specDir) {
@@ -393,16 +396,33 @@ function validateSpec(specDir) {
393
396
  // (after whitespace normalization). This catches BE/FE drift like
394
397
  // user_name vs userName before integration.
395
398
  if (contractDefs.size > 0) {
396
- const { names, block } = extractTaskContracts(content);
399
+ const { names, blocks, firstBlock } = extractTaskContracts(content);
397
400
  for (const name of names) {
398
401
  if (!contractDefs.has(name)) {
399
402
  errors.push(`${taskFile}: declares unknown contract "${name}" (not defined in design.md)`);
400
403
  continue;
401
404
  }
402
- if (block !== null && block !== contractDefs.get(name)) {
405
+ // Prefer the task's marker-tagged copy for this contract; fall back to
406
+ // the first fenced block only for single-contract tasks (legacy format).
407
+ const localCopy = blocks.has(name)
408
+ ? blocks.get(name)
409
+ : (names.length === 1 ? firstBlock : null);
410
+ if (localCopy === null) {
411
+ if (names.length > 1) {
412
+ errors.push(`${taskFile}: contract "${name}" has no <!-- contract:${name} --> tagged block (multi-contract tasks must tag each copy)`);
413
+ }
414
+ continue;
415
+ }
416
+ if (localCopy !== contractDefs.get(name)) {
403
417
  errors.push(`${taskFile}: contract "${name}" body diverges from the canonical definition in design.md`);
404
418
  }
405
419
  }
420
+ // Marker-tagged blocks not declared on the Contracts: line are drift risks.
421
+ for (const taggedName of blocks.keys()) {
422
+ if (!names.includes(taggedName)) {
423
+ warnings.push(`${taskFile}: carries <!-- contract:${taggedName} --> block but does not declare it on the Contracts: line`);
424
+ }
425
+ }
406
426
  }
407
427
  }
408
428
 
@@ -102,6 +102,10 @@
102
102
  "Stop": [
103
103
  {
104
104
  "hooks": [
105
+ {
106
+ "type": "command",
107
+ "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/spec-gate.cjs\""
108
+ },
105
109
  {
106
110
  "type": "command",
107
111
  "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/state.cjs\""
@@ -41,16 +41,16 @@ GEMINI_API_KEY=your_api_key_here
41
41
 
42
42
  # --- Image Generation ---
43
43
  # Used by: --task generate (image)
44
- # Default: gemini-2.5-flash-image (Nano Banana Flash - fast, cost-effective)
44
+ # Default: gemma-4-31b-it-image (Nano Banana Flash - fast, cost-effective)
45
45
  # Alternative: imagen-4.0-generate-001 (production quality)
46
46
  # NOTE: All image generation requires billing - no free tier available (limit: 0)
47
47
  # Options:
48
- # gemini-2.5-flash-image - Nano Banana Flash: fast, ~$1/1M tokens (DEFAULT)
49
- # gemini-3-pro-image-preview - Nano Banana Pro: 4K text, reasoning (requires billing)
48
+ # gemma-4-31b-it-image - Nano Banana Flash: fast, ~$1/1M tokens (DEFAULT)
49
+ # gemma-4-31b-it-image-preview - Nano Banana Pro: 4K text, reasoning (requires billing)
50
50
  # imagen-4.0-generate-001 - Imagen 4 Standard: production quality (~$0.02/image)
51
51
  # imagen-4.0-ultra-generate-001 - Imagen 4 Ultra: maximum quality (~$0.04/image)
52
52
  # imagen-4.0-fast-generate-001 - Imagen 4 Fast: speed-optimized (~$0.01/image)
53
- # IMAGE_GEN_MODEL=gemini-2.5-flash-image
53
+ # IMAGE_GEN_MODEL=gemma-4-31b-it-image
54
54
 
55
55
  # --- Video Generation ---
56
56
  # Used by: --task generate-video (new capability)
@@ -65,17 +65,15 @@ GEMINI_API_KEY=your_api_key_here
65
65
 
66
66
  # --- Multimodal Analysis ---
67
67
  # Used by: --task analyze, transcribe, extract
68
- # Default: gemini-2.5-flash
68
+ # Default: gemma-4-31b-it
69
69
  # Options:
70
- # gemini-3-pro-preview - Latest, agentic workflows, 1M context
71
- # gemini-2.5-flash - Best price/performance (recommended)
72
- # gemini-2.5-pro - Highest quality
73
- # MULTIMODAL_MODEL=gemini-2.5-flash
70
+ # gemma-4-31b-it - Best price/performance (recommended)
71
+ # MULTIMODAL_MODEL=gemma-4-31b-it
74
72
 
75
73
  # --- Legacy Compatibility ---
76
74
  # Generic model override (use specific variables above instead)
77
- # GEMINI_MODEL=gemini-2.5-flash
78
- # GEMINI_IMAGE_GEN_MODEL=gemini-2.5-flash-image
75
+ # GEMINI_MODEL=gemma-4-31b-it
76
+ # GEMINI_IMAGE_GEN_MODEL=gemma-4-31b-it-image
79
77
 
80
78
  # ============================================================================
81
79
  # MiniMax API Configuration (Optional - for image/video/speech/music generation)
@@ -223,8 +221,8 @@ GEMINI_API_KEY=your_api_key_here
223
221
  # 5. Free tier limits: 15 RPM, 1M-4M TPM, 1,500 RPD
224
222
  # 6. Vertex AI requires GCP authentication via gcloud CLI
225
223
  # 7. Model defaults (Dec 2025):
226
- # - Image gen: gemini-2.5-flash-image (Nano Banana Flash - default)
224
+ # - Image gen: gemma-4-31b-it-image (Nano Banana Flash - default)
227
225
  # - Image gen: imagen-4.0-generate-001 (alternative for production)
228
226
  # - Video gen: veo-3.1-generate-preview
229
- # - Analysis: gemini-2.5-flash
227
+ # - Analysis: gemma-4-31b-it
230
228
  # 8. Preview models (veo-3.1, gemini-3) may have API changes
@@ -43,7 +43,7 @@ export GEMINI_API_KEY_2="key2" # auto-rotates on rate limit
43
43
  ## Models
44
44
 
45
45
  ### Google Gemini
46
- - **Analysis**: `gemma-4-31b-it` (recommended), `gemini-2.5-pro` (advanced)
46
+ - **Analysis**: `gemma-4-31b-it` (recommended), `gemma-4-31b-it` (advanced)
47
47
 
48
48
  ## Scripts
49
49
 
@@ -42,7 +42,7 @@ myfile = client.files.upload(file='meeting.mp3')
42
42
 
43
43
  # Transcribe
44
44
  response = client.models.generate_content(
45
- model='gemini-2.5-flash',
45
+ model='gemma-4-31b-it',
46
46
  contents=['Generate a transcript of the speech.', myfile]
47
47
  )
48
48
  print(response.text)
@@ -52,7 +52,7 @@ print(response.text)
52
52
 
53
53
  ```python
54
54
  response = client.models.generate_content(
55
- model='gemini-2.5-flash',
55
+ model='gemma-4-31b-it',
56
56
  contents=['Generate transcript with timestamps in MM:SS format.', myfile]
57
57
  )
58
58
  ```
@@ -61,7 +61,7 @@ response = client.models.generate_content(
61
61
 
62
62
  ```python
63
63
  response = client.models.generate_content(
64
- model='gemini-2.5-flash',
64
+ model='gemma-4-31b-it',
65
65
  contents=['Transcribe with speaker labels. Format: [Speaker 1], [Speaker 2], etc.', myfile]
66
66
  )
67
67
  ```
@@ -70,7 +70,7 @@ response = client.models.generate_content(
70
70
 
71
71
  ```python
72
72
  response = client.models.generate_content(
73
- model='gemini-2.5-flash',
73
+ model='gemma-4-31b-it',
74
74
  contents=['Transcribe only the segment from 02:30 to 05:15.', myfile]
75
75
  )
76
76
  ```
@@ -81,7 +81,7 @@ response = client.models.generate_content(
81
81
 
82
82
  ```python
83
83
  response = client.models.generate_content(
84
- model='gemini-2.5-flash',
84
+ model='gemma-4-31b-it',
85
85
  contents=['Summarize key points in 5 bullets with timestamps.', myfile]
86
86
  )
87
87
  ```
@@ -91,19 +91,19 @@ response = client.models.generate_content(
91
91
  ```python
92
92
  # Music analysis
93
93
  response = client.models.generate_content(
94
- model='gemini-2.5-flash',
94
+ model='gemma-4-31b-it',
95
95
  contents=['Identify the musical instruments and genre.', myfile]
96
96
  )
97
97
 
98
98
  # Environmental sounds
99
99
  response = client.models.generate_content(
100
- model='gemini-2.5-flash',
100
+ model='gemma-4-31b-it',
101
101
  contents=['Identify all sounds: voices, music, ambient noise.', myfile]
102
102
  )
103
103
 
104
104
  # Birdsong identification
105
105
  response = client.models.generate_content(
106
- model='gemini-2.5-flash',
106
+ model='gemma-4-31b-it',
107
107
  contents=['Identify bird species based on their calls.', myfile]
108
108
  )
109
109
  ```
@@ -112,7 +112,7 @@ response = client.models.generate_content(
112
112
 
113
113
  ```python
114
114
  response = client.models.generate_content(
115
- model='gemini-2.5-flash',
115
+ model='gemma-4-31b-it',
116
116
  contents=['What is discussed from 10:30 to 15:45? Provide key points.', myfile]
117
117
  )
118
118
  ```
@@ -127,13 +127,13 @@ myfile = client.files.upload(file='large-audio.mp3')
127
127
 
128
128
  # First query
129
129
  response1 = client.models.generate_content(
130
- model='gemini-2.5-flash',
130
+ model='gemma-4-31b-it',
131
131
  contents=['Transcribe this', myfile]
132
132
  )
133
133
 
134
134
  # Second query (reuses same file)
135
135
  response2 = client.models.generate_content(
136
- model='gemini-2.5-flash',
136
+ model='gemma-4-31b-it',
137
137
  contents=['Summarize this', myfile]
138
138
  )
139
139
  ```
@@ -147,7 +147,7 @@ with open('small-audio.mp3', 'rb') as f:
147
147
  audio_bytes = f.read()
148
148
 
149
149
  response = client.models.generate_content(
150
- model='gemini-2.5-flash',
150
+ model='gemma-4-31b-it',
151
151
  contents=[
152
152
  'Describe this audio',
153
153
  types.Part.from_bytes(data=audio_bytes, mime_type='audio/mp3')
@@ -161,14 +161,14 @@ response = client.models.generate_content(
161
161
 
162
162
  | Model | Quality | Speed | Cost/1M tokens |
163
163
  |-------|---------|-------|----------------|
164
- | `gemini-2.5-flash-native-audio-preview-09-2025` | High | Fast | $10 |
165
- | `gemini-2.5-pro` TTS mode | Premium | Slower | $20 |
164
+ | `gemma-4-31b-it-native-audio-preview-09-2025` | High | Fast | $10 |
165
+ | `gemma-4-31b-it` TTS mode | Premium | Slower | $20 |
166
166
 
167
167
  ### Basic TTS
168
168
 
169
169
  ```python
170
170
  response = client.models.generate_content(
171
- model='gemini-2.5-flash-native-audio-preview-09-2025',
171
+ model='gemma-4-31b-it-native-audio-preview-09-2025',
172
172
  contents='Generate audio: Welcome to today\'s episode.'
173
173
  )
174
174
 
@@ -182,19 +182,19 @@ with open('output.wav', 'wb') as f:
182
182
  ```python
183
183
  # Professional tone
184
184
  response = client.models.generate_content(
185
- model='gemini-2.5-flash-native-audio-preview-09-2025',
185
+ model='gemma-4-31b-it-native-audio-preview-09-2025',
186
186
  contents='Generate audio in a professional, clear tone: Welcome to our quarterly earnings call.'
187
187
  )
188
188
 
189
189
  # Casual and friendly
190
190
  response = client.models.generate_content(
191
- model='gemini-2.5-flash-native-audio-preview-09-2025',
191
+ model='gemma-4-31b-it-native-audio-preview-09-2025',
192
192
  contents='Generate audio in a friendly, conversational tone: Hey there! Let\'s dive into today\'s topic.'
193
193
  )
194
194
 
195
195
  # Narrative style
196
196
  response = client.models.generate_content(
197
- model='gemini-2.5-flash-native-audio-preview-09-2025',
197
+ model='gemma-4-31b-it-native-audio-preview-09-2025',
198
198
  contents='Generate audio in a narrative, storytelling tone: Once upon a time, in a land far away...'
199
199
  )
200
200
  ```
@@ -244,9 +244,7 @@ response = client.models.generate_content(
244
244
  - 9.5 hours = 1,094,400 tokens
245
245
 
246
246
  **Model selection**:
247
- - Use `gemini-2.5-flash` ($1/1M tokens) for most tasks
248
- - Upgrade to `gemini-2.5-pro` ($3/1M tokens) for complex analysis
249
- - For high-volume: `gemini-1.5-flash` ($0.70/1M tokens)
247
+ - Use `gemma-4-31b-it` for transcription and analysis (read model from `.claude/runtime.json`: `gemini.model`)
250
248
 
251
249
  **Reduce costs**:
252
250
  - Process only relevant segments using timestamps
@@ -265,7 +263,7 @@ def transcribe_with_retry(file_path, max_retries=3):
265
263
  try:
266
264
  myfile = client.files.upload(file=file_path)
267
265
  response = client.models.generate_content(
268
- model='gemini-2.5-flash',
266
+ model='gemma-4-31b-it',
269
267
  contents=['Transcribe with timestamps', myfile]
270
268
  )
271
269
  return response.text
@@ -283,7 +281,7 @@ def transcribe_with_retry(file_path, max_retries=3):
283
281
 
284
282
  ```python
285
283
  response = client.models.generate_content(
286
- model='gemini-2.5-flash',
284
+ model='gemma-4-31b-it',
287
285
  contents=[
288
286
  '''Transcribe this meeting with:
289
287
  1. Speaker labels
@@ -299,7 +297,7 @@ response = client.models.generate_content(
299
297
 
300
298
  ```python
301
299
  response = client.models.generate_content(
302
- model='gemini-2.5-flash',
300
+ model='gemma-4-31b-it',
303
301
  contents=[
304
302
  '''Create podcast summary with:
305
303
  1. Main topics with timestamps
@@ -315,7 +313,7 @@ response = client.models.generate_content(
315
313
 
316
314
  ```python
317
315
  response = client.models.generate_content(
318
- model='gemini-2.5-flash',
316
+ model='gemma-4-31b-it',
319
317
  contents=[
320
318
  '''Analyze interview:
321
319
  1. Questions asked with timestamps
@@ -331,7 +329,7 @@ response = client.models.generate_content(
331
329
 
332
330
  ```python
333
331
  response = client.models.generate_content(
334
- model='gemini-2.5-flash',
332
+ model='gemma-4-31b-it',
335
333
  contents=[
336
334
  '''Verify audio content:
337
335
  1. Check for specific keywords or phrases
@@ -348,7 +346,7 @@ response = client.models.generate_content(
348
346
  ```python
349
347
  # Gemini auto-detects language
350
348
  response = client.models.generate_content(
351
- model='gemini-2.5-flash',
349
+ model='gemma-4-31b-it',
352
350
  contents=['Transcribe this audio and translate to English if needed.', myfile]
353
351
  )
354
352
  ```
@@ -22,12 +22,8 @@ Comprehensive guide for video understanding, temporal analysis, and YouTube proc
22
22
 
23
23
  ## Model Selection
24
24
 
25
- ### Gemini 3 Series (Latest)
26
- - **gemini-3-pro-preview**: Latest, agentic workflows, 1M context, dynamic thinking
27
-
28
- ### Gemini 2.5 Series (Recommended)
29
- - **gemini-2.5-pro**: Best quality, 1M-2M context
30
- - **gemini-2.5-flash**: Balanced, 1M-2M context (recommended)
25
+ ### Recommended
26
+ - **gemma-4-31b-it**: 1M-2M context, balanced quality/speed (read model from `.claude/runtime.json`: `gemini.model`)
31
27
 
32
28
  ### Context Windows
33
29
  - **2M token models**: ~2 hours (default) or ~6 hours (low-res)
@@ -57,7 +53,7 @@ if myfile.state.name == 'FAILED':
57
53
 
58
54
  # Analyze
59
55
  response = client.models.generate_content(
60
- model='gemini-2.5-flash',
56
+ model='gemma-4-31b-it',
61
57
  contents=['Summarize this video in 3 key points', myfile]
62
58
  )
63
59
  print(response.text)
@@ -69,7 +65,7 @@ print(response.text)
69
65
  from google.genai import types
70
66
 
71
67
  response = client.models.generate_content(
72
- model='gemini-2.5-flash',
68
+ model='gemma-4-31b-it',
73
69
  contents=[
74
70
  'Summarize the main topics discussed',
75
71
  types.Part.from_uri(
@@ -87,7 +83,7 @@ with open('short-clip.mp4', 'rb') as f:
87
83
  video_bytes = f.read()
88
84
 
89
85
  response = client.models.generate_content(
90
- model='gemini-2.5-flash',
86
+ model='gemma-4-31b-it',
91
87
  contents=[
92
88
  'What happens in this video?',
93
89
  types.Part.from_bytes(data=video_bytes, mime_type='video/mp4')
@@ -102,7 +98,7 @@ response = client.models.generate_content(
102
98
  ```python
103
99
  # Analyze specific time range
104
100
  response = client.models.generate_content(
105
- model='gemini-2.5-flash',
101
+ model='gemma-4-31b-it',
106
102
  contents=[
107
103
  'Summarize this segment',
108
104
  types.Part.from_video_metadata(
@@ -119,7 +115,7 @@ response = client.models.generate_content(
119
115
  ```python
120
116
  # Lower FPS for static content (saves tokens)
121
117
  response = client.models.generate_content(
122
- model='gemini-2.5-flash',
118
+ model='gemma-4-31b-it',
123
119
  contents=[
124
120
  'Analyze this presentation',
125
121
  types.Part.from_video_metadata(
@@ -131,7 +127,7 @@ response = client.models.generate_content(
131
127
 
132
128
  # Higher FPS for fast-moving content
133
129
  response = client.models.generate_content(
134
- model='gemini-2.5-flash',
130
+ model='gemma-4-31b-it',
135
131
  contents=[
136
132
  'Analyze rapid movements in this sports video',
137
133
  types.Part.from_video_metadata(
@@ -155,7 +151,7 @@ for video in [video1, video2]:
155
151
  video = client.files.get(name=video.name)
156
152
 
157
153
  response = client.models.generate_content(
158
- model='gemini-2.5-pro',
154
+ model='gemma-4-31b-it',
159
155
  contents=[
160
156
  'Compare these two product demos. Which explains features better?',
161
157
  video1,
@@ -170,7 +166,7 @@ response = client.models.generate_content(
170
166
 
171
167
  ```python
172
168
  response = client.models.generate_content(
173
- model='gemini-2.5-flash',
169
+ model='gemma-4-31b-it',
174
170
  contents=[
175
171
  'What happens at 01:15 and how does it relate to 02:30?',
176
172
  myfile
@@ -182,7 +178,7 @@ response = client.models.generate_content(
182
178
 
183
179
  ```python
184
180
  response = client.models.generate_content(
185
- model='gemini-2.5-flash',
181
+ model='gemma-4-31b-it',
186
182
  contents=[
187
183
  '''Create a timeline with timestamps:
188
184
  - Key events
@@ -199,7 +195,7 @@ response = client.models.generate_content(
199
195
 
200
196
  ```python
201
197
  response = client.models.generate_content(
202
- model='gemini-2.5-flash',
198
+ model='gemma-4-31b-it',
203
199
  contents=[
204
200
  'Identify all scene changes with timestamps and describe each scene',
205
201
  myfile
@@ -213,7 +209,7 @@ response = client.models.generate_content(
213
209
 
214
210
  ```python
215
211
  response = client.models.generate_content(
216
- model='gemini-2.5-flash',
212
+ model='gemma-4-31b-it',
217
213
  contents=[
218
214
  'Transcribe the audio from this video',
219
215
  myfile
@@ -225,7 +221,7 @@ response = client.models.generate_content(
225
221
 
226
222
  ```python
227
223
  response = client.models.generate_content(
228
- model='gemini-2.5-flash',
224
+ model='gemma-4-31b-it',
229
225
  contents=[
230
226
  '''Transcribe with visual context:
231
227
  - Audio transcription
@@ -241,7 +237,7 @@ response = client.models.generate_content(
241
237
 
242
238
  ```python
243
239
  response = client.models.generate_content(
244
- model='gemini-2.5-flash',
240
+ model='gemma-4-31b-it',
245
241
  contents=[
246
242
  'Transcribe with speaker labels and timestamps',
247
243
  myfile
@@ -255,7 +251,7 @@ response = client.models.generate_content(
255
251
 
256
252
  ```python
257
253
  response = client.models.generate_content(
258
- model='gemini-2.5-flash',
254
+ model='gemma-4-31b-it',
259
255
  contents=[
260
256
  '''Summarize this video:
261
257
  1. Main topic and purpose
@@ -271,7 +267,7 @@ response = client.models.generate_content(
271
267
 
272
268
  ```python
273
269
  response = client.models.generate_content(
274
- model='gemini-2.5-flash',
270
+ model='gemma-4-31b-it',
275
271
  contents=[
276
272
  '''Create educational materials:
277
273
  1. List key concepts taught
@@ -287,7 +283,7 @@ response = client.models.generate_content(
287
283
 
288
284
  ```python
289
285
  response = client.models.generate_content(
290
- model='gemini-2.5-flash',
286
+ model='gemma-4-31b-it',
291
287
  contents=[
292
288
  'List all actions performed in this tutorial with timestamps',
293
289
  myfile
@@ -299,7 +295,7 @@ response = client.models.generate_content(
299
295
 
300
296
  ```python
301
297
  response = client.models.generate_content(
302
- model='gemini-2.5-flash',
298
+ model='gemma-4-31b-it',
303
299
  contents=[
304
300
  '''Review video content:
305
301
  1. Identify any problematic content
@@ -315,7 +311,7 @@ response = client.models.generate_content(
315
311
 
316
312
  ```python
317
313
  response = client.models.generate_content(
318
- model='gemini-2.5-flash',
314
+ model='gemma-4-31b-it',
319
315
  contents=[
320
316
  '''Analyze interview:
321
317
  1. Questions asked (timestamps)
@@ -332,7 +328,7 @@ response = client.models.generate_content(
332
328
 
333
329
  ```python
334
330
  response = client.models.generate_content(
335
- model='gemini-2.5-flash',
331
+ model='gemma-4-31b-it',
336
332
  contents=[
337
333
  '''Analyze sports video:
338
334
  1. Key plays with timestamps
@@ -362,7 +358,7 @@ response = client.models.generate_content(
362
358
  youtube_uri = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
363
359
 
364
360
  response = client.models.generate_content(
365
- model='gemini-2.5-flash',
361
+ model='gemma-4-31b-it',
366
362
  contents=[
367
363
  'Create chapter markers with timestamps',
368
364
  types.Part.from_uri(uri=youtube_uri, mime_type='video/mp4')
@@ -444,7 +440,7 @@ class VideoAnalysis(BaseModel):
444
440
  duration: str
445
441
 
446
442
  response = client.models.generate_content(
447
- model='gemini-2.5-flash',
443
+ model='gemma-4-31b-it',
448
444
  contents=['Analyze this video', myfile],
449
445
  config=genai.types.GenerateContentConfig(
450
446
  response_mime_type='application/json',