gemini-skill-install 0.1.1__tar.gz
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.
- gemini_skill_install-0.1.1/LICENSE +21 -0
- gemini_skill_install-0.1.1/MANIFEST.in +12 -0
- gemini_skill_install-0.1.1/PKG-INFO +189 -0
- gemini_skill_install-0.1.1/README.md +170 -0
- gemini_skill_install-0.1.1/SKILL.md +37 -0
- gemini_skill_install-0.1.1/VERSION +1 -0
- gemini_skill_install-0.1.1/adapters/__init__.py +0 -0
- gemini_skill_install-0.1.1/adapters/data/__init__.py +0 -0
- gemini_skill_install-0.1.1/adapters/data/batch.py +112 -0
- gemini_skill_install-0.1.1/adapters/data/cache.py +122 -0
- gemini_skill_install-0.1.1/adapters/data/embeddings.py +68 -0
- gemini_skill_install-0.1.1/adapters/data/file_search.py +185 -0
- gemini_skill_install-0.1.1/adapters/data/files.py +185 -0
- gemini_skill_install-0.1.1/adapters/data/token_count.py +52 -0
- gemini_skill_install-0.1.1/adapters/experimental/__init__.py +0 -0
- gemini_skill_install-0.1.1/adapters/experimental/computer_use.py +78 -0
- gemini_skill_install-0.1.1/adapters/experimental/deep_research.py +126 -0
- gemini_skill_install-0.1.1/adapters/generation/__init__.py +0 -0
- gemini_skill_install-0.1.1/adapters/generation/imagen.py +222 -0
- gemini_skill_install-0.1.1/adapters/generation/live.py +193 -0
- gemini_skill_install-0.1.1/adapters/generation/multimodal.py +84 -0
- gemini_skill_install-0.1.1/adapters/generation/streaming.py +54 -0
- gemini_skill_install-0.1.1/adapters/generation/structured.py +67 -0
- gemini_skill_install-0.1.1/adapters/generation/text.py +119 -0
- gemini_skill_install-0.1.1/adapters/media/__init__.py +0 -0
- gemini_skill_install-0.1.1/adapters/media/image_gen.py +158 -0
- gemini_skill_install-0.1.1/adapters/media/music_gen.py +104 -0
- gemini_skill_install-0.1.1/adapters/media/video_gen.py +152 -0
- gemini_skill_install-0.1.1/adapters/tools/__init__.py +0 -0
- gemini_skill_install-0.1.1/adapters/tools/code_exec.py +73 -0
- gemini_skill_install-0.1.1/adapters/tools/function_calling.py +82 -0
- gemini_skill_install-0.1.1/adapters/tools/maps.py +78 -0
- gemini_skill_install-0.1.1/adapters/tools/search.py +90 -0
- gemini_skill_install-0.1.1/core/__init__.py +0 -0
- gemini_skill_install-0.1.1/core/adapter/__init__.py +0 -0
- gemini_skill_install-0.1.1/core/adapter/contract.py +40 -0
- gemini_skill_install-0.1.1/core/adapter/helpers.py +226 -0
- gemini_skill_install-0.1.1/core/auth/__init__.py +0 -0
- gemini_skill_install-0.1.1/core/auth/auth.py +166 -0
- gemini_skill_install-0.1.1/core/cli/__init__.py +0 -0
- gemini_skill_install-0.1.1/core/cli/dispatch.py +256 -0
- gemini_skill_install-0.1.1/core/cli/health_main.py +204 -0
- gemini_skill_install-0.1.1/core/cli/install_main.py +440 -0
- gemini_skill_install-0.1.1/core/cli/installer/__init__.py +19 -0
- gemini_skill_install-0.1.1/core/cli/installer/api_key_prompt.py +177 -0
- gemini_skill_install-0.1.1/core/cli/installer/legacy_migration.py +122 -0
- gemini_skill_install-0.1.1/core/cli/installer/payload.py +63 -0
- gemini_skill_install-0.1.1/core/cli/installer/settings_merge.py +313 -0
- gemini_skill_install-0.1.1/core/cli/installer/venv.py +225 -0
- gemini_skill_install-0.1.1/core/cli/update_main.py +104 -0
- gemini_skill_install-0.1.1/core/infra/__init__.py +0 -0
- gemini_skill_install-0.1.1/core/infra/atomic_write.py +64 -0
- gemini_skill_install-0.1.1/core/infra/checksums.py +233 -0
- gemini_skill_install-0.1.1/core/infra/client.py +103 -0
- gemini_skill_install-0.1.1/core/infra/config.py +259 -0
- gemini_skill_install-0.1.1/core/infra/cost.py +170 -0
- gemini_skill_install-0.1.1/core/infra/errors.py +182 -0
- gemini_skill_install-0.1.1/core/infra/filelock.py +112 -0
- gemini_skill_install-0.1.1/core/infra/mime.py +45 -0
- gemini_skill_install-0.1.1/core/infra/sanitize.py +77 -0
- gemini_skill_install-0.1.1/core/infra/timeouts.py +106 -0
- gemini_skill_install-0.1.1/core/routing/__init__.py +0 -0
- gemini_skill_install-0.1.1/core/routing/registry.py +158 -0
- gemini_skill_install-0.1.1/core/routing/router.py +149 -0
- gemini_skill_install-0.1.1/core/routing/tool_state.py +95 -0
- gemini_skill_install-0.1.1/core/state/__init__.py +0 -0
- gemini_skill_install-0.1.1/core/state/file_state.py +141 -0
- gemini_skill_install-0.1.1/core/state/identity.py +124 -0
- gemini_skill_install-0.1.1/core/state/session_state.py +145 -0
- gemini_skill_install-0.1.1/core/state/store_state.py +160 -0
- gemini_skill_install-0.1.1/core/transport/__init__.py +295 -0
- gemini_skill_install-0.1.1/core/transport/_validation.py +96 -0
- gemini_skill_install-0.1.1/core/transport/base.py +349 -0
- gemini_skill_install-0.1.1/core/transport/coordinator.py +677 -0
- gemini_skill_install-0.1.1/core/transport/normalize.py +310 -0
- gemini_skill_install-0.1.1/core/transport/policy.py +131 -0
- gemini_skill_install-0.1.1/core/transport/raw_http/__init__.py +8 -0
- gemini_skill_install-0.1.1/core/transport/raw_http/client.py +355 -0
- gemini_skill_install-0.1.1/core/transport/raw_http/transport.py +194 -0
- gemini_skill_install-0.1.1/core/transport/sdk/__init__.py +0 -0
- gemini_skill_install-0.1.1/core/transport/sdk/async_transport.py +339 -0
- gemini_skill_install-0.1.1/core/transport/sdk/client_factory.py +243 -0
- gemini_skill_install-0.1.1/core/transport/sdk/transport.py +911 -0
- gemini_skill_install-0.1.1/core/types.py +23 -0
- gemini_skill_install-0.1.1/gemini_skill_install/__init__.py +1 -0
- gemini_skill_install-0.1.1/gemini_skill_install/__main__.py +9 -0
- gemini_skill_install-0.1.1/gemini_skill_install/cli.py +90 -0
- gemini_skill_install-0.1.1/gemini_skill_install.egg-info/PKG-INFO +189 -0
- gemini_skill_install-0.1.1/gemini_skill_install.egg-info/SOURCES.txt +127 -0
- gemini_skill_install-0.1.1/gemini_skill_install.egg-info/dependency_links.txt +1 -0
- gemini_skill_install-0.1.1/gemini_skill_install.egg-info/entry_points.txt +2 -0
- gemini_skill_install-0.1.1/gemini_skill_install.egg-info/requires.txt +3 -0
- gemini_skill_install-0.1.1/gemini_skill_install.egg-info/top_level.txt +2 -0
- gemini_skill_install-0.1.1/pyproject.toml +3 -0
- gemini_skill_install-0.1.1/reference/batch.md +71 -0
- gemini_skill_install-0.1.1/reference/cache.md +61 -0
- gemini_skill_install-0.1.1/reference/code_exec.md +54 -0
- gemini_skill_install-0.1.1/reference/computer_use.md +64 -0
- gemini_skill_install-0.1.1/reference/deep_research.md +75 -0
- gemini_skill_install-0.1.1/reference/embed.md +56 -0
- gemini_skill_install-0.1.1/reference/file_search.md +71 -0
- gemini_skill_install-0.1.1/reference/files.md +81 -0
- gemini_skill_install-0.1.1/reference/function_calling.md +66 -0
- gemini_skill_install-0.1.1/reference/image_gen.md +94 -0
- gemini_skill_install-0.1.1/reference/imagen.md +61 -0
- gemini_skill_install-0.1.1/reference/index.md +54 -0
- gemini_skill_install-0.1.1/reference/live.md +53 -0
- gemini_skill_install-0.1.1/reference/maps.md +72 -0
- gemini_skill_install-0.1.1/reference/multimodal.md +57 -0
- gemini_skill_install-0.1.1/reference/music_gen.md +68 -0
- gemini_skill_install-0.1.1/reference/search.md +66 -0
- gemini_skill_install-0.1.1/reference/streaming.md +51 -0
- gemini_skill_install-0.1.1/reference/structured.md +53 -0
- gemini_skill_install-0.1.1/reference/text.md +51 -0
- gemini_skill_install-0.1.1/reference/token_count.md +54 -0
- gemini_skill_install-0.1.1/reference/video_gen.md +67 -0
- gemini_skill_install-0.1.1/registry/capabilities.json +260 -0
- gemini_skill_install-0.1.1/registry/models.json +148 -0
- gemini_skill_install-0.1.1/scripts/gemini_run.py +108 -0
- gemini_skill_install-0.1.1/scripts/health_check.py +21 -0
- gemini_skill_install-0.1.1/scripts/install_git_hooks.sh +88 -0
- gemini_skill_install-0.1.1/scripts/render_diagrams.sh +45 -0
- gemini_skill_install-0.1.1/scripts/tag_release.sh +100 -0
- gemini_skill_install-0.1.1/setup/install.py +208 -0
- gemini_skill_install-0.1.1/setup/requirements.txt +17 -0
- gemini_skill_install-0.1.1/setup/update.py +21 -0
- gemini_skill_install-0.1.1/setup.cfg +4 -0
- gemini_skill_install-0.1.1/setup.py +86 -0
- gemini_skill_install-0.1.1/tests/test_phase11_branch_fillers.py +1030 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 reshinto
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
include README.md
|
|
2
|
+
include LICENSE
|
|
3
|
+
include VERSION
|
|
4
|
+
include SKILL.md
|
|
5
|
+
recursive-include core *.py
|
|
6
|
+
recursive-include adapters *.py
|
|
7
|
+
recursive-include reference *.md
|
|
8
|
+
recursive-include registry *.json
|
|
9
|
+
recursive-include scripts *.py *.sh
|
|
10
|
+
include setup/install.py
|
|
11
|
+
include setup/update.py
|
|
12
|
+
include setup/requirements.txt
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gemini-skill-install
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Bootstrap installer for the gemini Claude Code skill
|
|
5
|
+
Home-page: https://github.com/reshinto/gemini-skill
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: typing-extensions>=4.0; python_version < "3.10"
|
|
11
|
+
Dynamic: description
|
|
12
|
+
Dynamic: description-content-type
|
|
13
|
+
Dynamic: home-page
|
|
14
|
+
Dynamic: license
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
Dynamic: requires-dist
|
|
17
|
+
Dynamic: requires-python
|
|
18
|
+
Dynamic: summary
|
|
19
|
+
|
|
20
|
+
# gemini-skill
|
|
21
|
+
|
|
22
|
+
A Claude Code skill for broad Gemini REST API access — text generation, multimodal input, image/video/music generation, embeddings, caching, batch processing, search grounding, code execution, file search, and more.
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
1. **Install without cloning**
|
|
27
|
+
```bash
|
|
28
|
+
uvx --from git+https://github.com/reshinto/gemini-skill gemini-skill-install
|
|
29
|
+
```
|
|
30
|
+
Or with `pipx`:
|
|
31
|
+
```bash
|
|
32
|
+
pipx run --spec git+https://github.com/reshinto/gemini-skill.git gemini-skill-install
|
|
33
|
+
```
|
|
34
|
+
Tagged releases build and publish the same bootstrap installer to PyPI. After the
|
|
35
|
+
first PyPI release, these simplify to:
|
|
36
|
+
```bash
|
|
37
|
+
uvx gemini-skill-install
|
|
38
|
+
pipx install gemini-skill-install
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
2. **Fallback: install from a clone or release tarball**
|
|
42
|
+
```bash
|
|
43
|
+
git clone https://github.com/reshinto/gemini-skill.git
|
|
44
|
+
cd gemini-skill
|
|
45
|
+
python3 setup/install.py
|
|
46
|
+
```
|
|
47
|
+
Both installer entry points call the same core installer. They:
|
|
48
|
+
- Copy operational files to `~/.claude/skills/gemini/`
|
|
49
|
+
- Includes the runtime payload: `SKILL.md`, `VERSION`, `core`, `adapters`, `reference`, `registry`, `scripts`, and `setup/{update.py,requirements.txt}`
|
|
50
|
+
- Creates `~/.claude/skills/gemini/.venv` with pinned `google-genai`
|
|
51
|
+
- Verifies install integrity via SHA-256 checksums
|
|
52
|
+
- Prompts for Gemini API key (hidden input)
|
|
53
|
+
- Merges env block into `~/.claude/settings.json` (with conflict resolution)
|
|
54
|
+
- Reuses an existing skill-local `.venv` on overwrite installs
|
|
55
|
+
|
|
56
|
+
3. **Set your Gemini API key** (get one at [aistudio.google.com/apikey](https://aistudio.google.com/apikey))
|
|
57
|
+
|
|
58
|
+
The installer prompts you interactively. If you need to manually edit, add/update the `env` block in `~/.claude/settings.json`:
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"env": {
|
|
62
|
+
"GEMINI_API_KEY": "AIzaSy...",
|
|
63
|
+
"GEMINI_IS_SDK_PRIORITY": "true",
|
|
64
|
+
"GEMINI_IS_RAWHTTP_PRIORITY": "false",
|
|
65
|
+
"GEMINI_LIVE_TESTS": "0"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
Claude Code injects these values into the process env at session start.
|
|
70
|
+
|
|
71
|
+
**Do NOT edit the repo-root `.env`** — that's only for local development from a clone. For the installed skill, use `~/.claude/settings.json` exclusively.
|
|
72
|
+
|
|
73
|
+
4. **Fully restart Claude Code** (⌘Q on macOS, not "Reload Window"). Skill discovery and env injection happen at IDE launch.
|
|
74
|
+
|
|
75
|
+
5. **Use it in Claude Code**
|
|
76
|
+
```
|
|
77
|
+
/gemini text "Explain quantum computing"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Architecture
|
|
81
|
+
|
|
82
|
+

|
|
83
|
+
|
|
84
|
+
## Features
|
|
85
|
+
|
|
86
|
+
- Text generation, multimodal input, structured output, function calling
|
|
87
|
+
- Image generation (Nano Banana, Imagen 3), video generation (Veo), music generation (Lyria 3)
|
|
88
|
+
- Embeddings, context caching, batch processing, token counting
|
|
89
|
+
- Google Search grounding, Google Maps grounding, code execution
|
|
90
|
+
- File API, File Search / hosted RAG
|
|
91
|
+
- Deep Research (Interactions API), Computer Use (preview)
|
|
92
|
+
- Live API realtime sessions (async dispatch)
|
|
93
|
+
- Automatic model routing by task type and complexity
|
|
94
|
+
- Two-phase cost tracking (pre-flight estimate + post-response)
|
|
95
|
+
- Multi-turn conversation sessions with Gemini
|
|
96
|
+
- Dual transport backend — google-genai SDK primary + urllib raw HTTP fallback, user never picks
|
|
97
|
+
|
|
98
|
+
## Prerequisites
|
|
99
|
+
|
|
100
|
+
- Python 3.9+
|
|
101
|
+
- A Gemini API key
|
|
102
|
+
- `google-genai==1.33.0` (installed automatically by the installer into `~/.claude/skills/gemini/.venv`)
|
|
103
|
+
|
|
104
|
+
## Documentation
|
|
105
|
+
|
|
106
|
+
**Start here:** [docs/README.md](docs/README.md) — the single index hub for every doc and reference page.
|
|
107
|
+
|
|
108
|
+
### Most-read pages
|
|
109
|
+
|
|
110
|
+
- **[Design patterns](docs/design-patterns.md)** — what / where / why / how for every architectural decision in the codebase (Adapter, Facade, Capability registry, Coordinator, Anti-corruption layer, Atomic write, SHA-256 integrity, etc.). Read this first if you're touching the code.
|
|
111
|
+
- **[Security & secrets storage](docs/security.md)** — full threat model + the "How the skill stores secrets and why it's safe" section explaining where `GEMINI_API_KEY` lives, why the chosen storage location is safe, alternatives rejected, and rotation procedure.
|
|
112
|
+
- **[Usage tour](docs/usage-tour.md)** — 16 end-to-end examples (text, multimodal, streaming, function calling, search grounding, image gen, batch, caching, sessions, dry-run vs `--execute`, error recovery).
|
|
113
|
+
- **[Per-command reference](reference/index.md)** — detailed docs for all 22 commands. Every page covers what / which model(s) / why (vs alternatives) / how (concrete usage).
|
|
114
|
+
|
|
115
|
+
### Reference catalogs (single-page lookups)
|
|
116
|
+
|
|
117
|
+
- **[Flags reference](docs/flags-reference.md)** — every CLI flag the skill accepts, grouped by category (privacy, cost, execution, I/O), with rationale.
|
|
118
|
+
- **[Models reference](docs/models-reference.md)** — every model in the registry with cost tier, capabilities, and "when to pick this over siblings".
|
|
119
|
+
|
|
120
|
+
### Architecture & internals
|
|
121
|
+
|
|
122
|
+
- [Architecture](docs/architecture.md) — System design, module layout, dual-backend transport diagram, "Why SKILL.md is terse" (token optimization rationale).
|
|
123
|
+
- [How It Works](docs/how-it-works.md) — End-to-end execution trace.
|
|
124
|
+
- [Model Routing](docs/model-routing.md) — Router decision tree.
|
|
125
|
+
- [Capabilities](docs/capabilities.md) — Feature matrix with status and limitations.
|
|
126
|
+
- [Commands](docs/commands.md) — Command index by capability family.
|
|
127
|
+
|
|
128
|
+
### Operating the skill
|
|
129
|
+
|
|
130
|
+
- [Installation](docs/install.md) — Setup, troubleshooting, API key configuration.
|
|
131
|
+
- [Usage](docs/usage.md) — Getting started and common workflows.
|
|
132
|
+
- [Update & Sync](docs/update-sync.md) — Install mechanism, release checking, rollback, and release publishing.
|
|
133
|
+
|
|
134
|
+
### Contributors
|
|
135
|
+
|
|
136
|
+
- [Contributing](docs/contributing.md) — Adding adapters, code style, PRs, strict typing rule.
|
|
137
|
+
- [Testing](docs/testing.md) — Running tests, writing tests, coverage, live API smoke tests.
|
|
138
|
+
- [Python Design](docs/python-guide.md) — Python 3.9+ floor, no `typing.Any`, idiomatic patterns.
|
|
139
|
+
|
|
140
|
+
### Diagrams
|
|
141
|
+
|
|
142
|
+
All diagrams are committed as both Mermaid source (`.mmd`) and rendered SVG with white background under [docs/diagrams/](docs/diagrams/):
|
|
143
|
+
|
|
144
|
+
- `architecture-dual-backend.svg` — high-level dual-backend transport
|
|
145
|
+
- `coordinator-decision-flow.svg` — fallback eligibility + capability gate
|
|
146
|
+
- `backend-priority-matrix.svg` — env flag truth table
|
|
147
|
+
- `auth-resolution.svg` — `GEMINI_API_KEY` precedence
|
|
148
|
+
- `install-flow.svg` — installer pipeline
|
|
149
|
+
- `secrets-flow.svg` — secret storage data flow + threat boundaries
|
|
150
|
+
- `design-patterns-overview.svg` — class-diagram-style pattern map
|
|
151
|
+
- `command-dispatch-flow.svg` — request lifecycle from `/gemini` to stdout
|
|
152
|
+
- `token-optimization-flow.svg` — why SKILL.md stays small
|
|
153
|
+
|
|
154
|
+
Regenerate any diagram with `bash scripts/render_diagrams.sh [name]`.
|
|
155
|
+
|
|
156
|
+
## Releases
|
|
157
|
+
|
|
158
|
+
Tagged releases (`v*`) run [.github/workflows/release.yml](.github/workflows/release.yml). The
|
|
159
|
+
workflow verifies `VERSION`, builds the GitHub release tarball plus Python
|
|
160
|
+
wheel/sdist artifacts, writes `checksums.txt`, creates the GitHub Release, and
|
|
161
|
+
publishes `gemini-skill-install` to PyPI via Trusted Publishing.
|
|
162
|
+
|
|
163
|
+
Maintainers can cut a release tag from the current [VERSION](VERSION) with:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
bash scripts/tag_release.sh
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
See [docs/update-sync.md](docs/update-sync.md) for the full release flow.
|
|
170
|
+
|
|
171
|
+
## Backends
|
|
172
|
+
|
|
173
|
+
By default, the skill uses the **google-genai SDK as the primary backend**, with **urllib raw HTTP as the fallback**. Both backends return identical response shapes via the `normalize` layer — adapters never know which ran.
|
|
174
|
+
|
|
175
|
+
To invert backend priority (raw HTTP primary, SDK fallback), edit `~/.claude/settings.json`:
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"env": {
|
|
179
|
+
"GEMINI_IS_SDK_PRIORITY": "false",
|
|
180
|
+
"GEMINI_IS_RAWHTTP_PRIORITY": "true"
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Restart Claude Code. Both flags cannot be false (ConfigError), and if both are true, SDK wins.
|
|
186
|
+
|
|
187
|
+
## License
|
|
188
|
+
|
|
189
|
+
MIT
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# gemini-skill
|
|
2
|
+
|
|
3
|
+
A Claude Code skill for broad Gemini REST API access — text generation, multimodal input, image/video/music generation, embeddings, caching, batch processing, search grounding, code execution, file search, and more.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
1. **Install without cloning**
|
|
8
|
+
```bash
|
|
9
|
+
uvx --from git+https://github.com/reshinto/gemini-skill gemini-skill-install
|
|
10
|
+
```
|
|
11
|
+
Or with `pipx`:
|
|
12
|
+
```bash
|
|
13
|
+
pipx run --spec git+https://github.com/reshinto/gemini-skill.git gemini-skill-install
|
|
14
|
+
```
|
|
15
|
+
Tagged releases build and publish the same bootstrap installer to PyPI. After the
|
|
16
|
+
first PyPI release, these simplify to:
|
|
17
|
+
```bash
|
|
18
|
+
uvx gemini-skill-install
|
|
19
|
+
pipx install gemini-skill-install
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
2. **Fallback: install from a clone or release tarball**
|
|
23
|
+
```bash
|
|
24
|
+
git clone https://github.com/reshinto/gemini-skill.git
|
|
25
|
+
cd gemini-skill
|
|
26
|
+
python3 setup/install.py
|
|
27
|
+
```
|
|
28
|
+
Both installer entry points call the same core installer. They:
|
|
29
|
+
- Copy operational files to `~/.claude/skills/gemini/`
|
|
30
|
+
- Includes the runtime payload: `SKILL.md`, `VERSION`, `core`, `adapters`, `reference`, `registry`, `scripts`, and `setup/{update.py,requirements.txt}`
|
|
31
|
+
- Creates `~/.claude/skills/gemini/.venv` with pinned `google-genai`
|
|
32
|
+
- Verifies install integrity via SHA-256 checksums
|
|
33
|
+
- Prompts for Gemini API key (hidden input)
|
|
34
|
+
- Merges env block into `~/.claude/settings.json` (with conflict resolution)
|
|
35
|
+
- Reuses an existing skill-local `.venv` on overwrite installs
|
|
36
|
+
|
|
37
|
+
3. **Set your Gemini API key** (get one at [aistudio.google.com/apikey](https://aistudio.google.com/apikey))
|
|
38
|
+
|
|
39
|
+
The installer prompts you interactively. If you need to manually edit, add/update the `env` block in `~/.claude/settings.json`:
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"env": {
|
|
43
|
+
"GEMINI_API_KEY": "AIzaSy...",
|
|
44
|
+
"GEMINI_IS_SDK_PRIORITY": "true",
|
|
45
|
+
"GEMINI_IS_RAWHTTP_PRIORITY": "false",
|
|
46
|
+
"GEMINI_LIVE_TESTS": "0"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
Claude Code injects these values into the process env at session start.
|
|
51
|
+
|
|
52
|
+
**Do NOT edit the repo-root `.env`** — that's only for local development from a clone. For the installed skill, use `~/.claude/settings.json` exclusively.
|
|
53
|
+
|
|
54
|
+
4. **Fully restart Claude Code** (⌘Q on macOS, not "Reload Window"). Skill discovery and env injection happen at IDE launch.
|
|
55
|
+
|
|
56
|
+
5. **Use it in Claude Code**
|
|
57
|
+
```
|
|
58
|
+
/gemini text "Explain quantum computing"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Architecture
|
|
62
|
+
|
|
63
|
+

|
|
64
|
+
|
|
65
|
+
## Features
|
|
66
|
+
|
|
67
|
+
- Text generation, multimodal input, structured output, function calling
|
|
68
|
+
- Image generation (Nano Banana, Imagen 3), video generation (Veo), music generation (Lyria 3)
|
|
69
|
+
- Embeddings, context caching, batch processing, token counting
|
|
70
|
+
- Google Search grounding, Google Maps grounding, code execution
|
|
71
|
+
- File API, File Search / hosted RAG
|
|
72
|
+
- Deep Research (Interactions API), Computer Use (preview)
|
|
73
|
+
- Live API realtime sessions (async dispatch)
|
|
74
|
+
- Automatic model routing by task type and complexity
|
|
75
|
+
- Two-phase cost tracking (pre-flight estimate + post-response)
|
|
76
|
+
- Multi-turn conversation sessions with Gemini
|
|
77
|
+
- Dual transport backend — google-genai SDK primary + urllib raw HTTP fallback, user never picks
|
|
78
|
+
|
|
79
|
+
## Prerequisites
|
|
80
|
+
|
|
81
|
+
- Python 3.9+
|
|
82
|
+
- A Gemini API key
|
|
83
|
+
- `google-genai==1.33.0` (installed automatically by the installer into `~/.claude/skills/gemini/.venv`)
|
|
84
|
+
|
|
85
|
+
## Documentation
|
|
86
|
+
|
|
87
|
+
**Start here:** [docs/README.md](docs/README.md) — the single index hub for every doc and reference page.
|
|
88
|
+
|
|
89
|
+
### Most-read pages
|
|
90
|
+
|
|
91
|
+
- **[Design patterns](docs/design-patterns.md)** — what / where / why / how for every architectural decision in the codebase (Adapter, Facade, Capability registry, Coordinator, Anti-corruption layer, Atomic write, SHA-256 integrity, etc.). Read this first if you're touching the code.
|
|
92
|
+
- **[Security & secrets storage](docs/security.md)** — full threat model + the "How the skill stores secrets and why it's safe" section explaining where `GEMINI_API_KEY` lives, why the chosen storage location is safe, alternatives rejected, and rotation procedure.
|
|
93
|
+
- **[Usage tour](docs/usage-tour.md)** — 16 end-to-end examples (text, multimodal, streaming, function calling, search grounding, image gen, batch, caching, sessions, dry-run vs `--execute`, error recovery).
|
|
94
|
+
- **[Per-command reference](reference/index.md)** — detailed docs for all 22 commands. Every page covers what / which model(s) / why (vs alternatives) / how (concrete usage).
|
|
95
|
+
|
|
96
|
+
### Reference catalogs (single-page lookups)
|
|
97
|
+
|
|
98
|
+
- **[Flags reference](docs/flags-reference.md)** — every CLI flag the skill accepts, grouped by category (privacy, cost, execution, I/O), with rationale.
|
|
99
|
+
- **[Models reference](docs/models-reference.md)** — every model in the registry with cost tier, capabilities, and "when to pick this over siblings".
|
|
100
|
+
|
|
101
|
+
### Architecture & internals
|
|
102
|
+
|
|
103
|
+
- [Architecture](docs/architecture.md) — System design, module layout, dual-backend transport diagram, "Why SKILL.md is terse" (token optimization rationale).
|
|
104
|
+
- [How It Works](docs/how-it-works.md) — End-to-end execution trace.
|
|
105
|
+
- [Model Routing](docs/model-routing.md) — Router decision tree.
|
|
106
|
+
- [Capabilities](docs/capabilities.md) — Feature matrix with status and limitations.
|
|
107
|
+
- [Commands](docs/commands.md) — Command index by capability family.
|
|
108
|
+
|
|
109
|
+
### Operating the skill
|
|
110
|
+
|
|
111
|
+
- [Installation](docs/install.md) — Setup, troubleshooting, API key configuration.
|
|
112
|
+
- [Usage](docs/usage.md) — Getting started and common workflows.
|
|
113
|
+
- [Update & Sync](docs/update-sync.md) — Install mechanism, release checking, rollback, and release publishing.
|
|
114
|
+
|
|
115
|
+
### Contributors
|
|
116
|
+
|
|
117
|
+
- [Contributing](docs/contributing.md) — Adding adapters, code style, PRs, strict typing rule.
|
|
118
|
+
- [Testing](docs/testing.md) — Running tests, writing tests, coverage, live API smoke tests.
|
|
119
|
+
- [Python Design](docs/python-guide.md) — Python 3.9+ floor, no `typing.Any`, idiomatic patterns.
|
|
120
|
+
|
|
121
|
+
### Diagrams
|
|
122
|
+
|
|
123
|
+
All diagrams are committed as both Mermaid source (`.mmd`) and rendered SVG with white background under [docs/diagrams/](docs/diagrams/):
|
|
124
|
+
|
|
125
|
+
- `architecture-dual-backend.svg` — high-level dual-backend transport
|
|
126
|
+
- `coordinator-decision-flow.svg` — fallback eligibility + capability gate
|
|
127
|
+
- `backend-priority-matrix.svg` — env flag truth table
|
|
128
|
+
- `auth-resolution.svg` — `GEMINI_API_KEY` precedence
|
|
129
|
+
- `install-flow.svg` — installer pipeline
|
|
130
|
+
- `secrets-flow.svg` — secret storage data flow + threat boundaries
|
|
131
|
+
- `design-patterns-overview.svg` — class-diagram-style pattern map
|
|
132
|
+
- `command-dispatch-flow.svg` — request lifecycle from `/gemini` to stdout
|
|
133
|
+
- `token-optimization-flow.svg` — why SKILL.md stays small
|
|
134
|
+
|
|
135
|
+
Regenerate any diagram with `bash scripts/render_diagrams.sh [name]`.
|
|
136
|
+
|
|
137
|
+
## Releases
|
|
138
|
+
|
|
139
|
+
Tagged releases (`v*`) run [.github/workflows/release.yml](.github/workflows/release.yml). The
|
|
140
|
+
workflow verifies `VERSION`, builds the GitHub release tarball plus Python
|
|
141
|
+
wheel/sdist artifacts, writes `checksums.txt`, creates the GitHub Release, and
|
|
142
|
+
publishes `gemini-skill-install` to PyPI via Trusted Publishing.
|
|
143
|
+
|
|
144
|
+
Maintainers can cut a release tag from the current [VERSION](VERSION) with:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
bash scripts/tag_release.sh
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
See [docs/update-sync.md](docs/update-sync.md) for the full release flow.
|
|
151
|
+
|
|
152
|
+
## Backends
|
|
153
|
+
|
|
154
|
+
By default, the skill uses the **google-genai SDK as the primary backend**, with **urllib raw HTTP as the fallback**. Both backends return identical response shapes via the `normalize` layer — adapters never know which ran.
|
|
155
|
+
|
|
156
|
+
To invert backend priority (raw HTTP primary, SDK fallback), edit `~/.claude/settings.json`:
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"env": {
|
|
160
|
+
"GEMINI_IS_SDK_PRIORITY": "false",
|
|
161
|
+
"GEMINI_IS_RAWHTTP_PRIORITY": "true"
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Restart Claude Code. Both flags cannot be false (ConfigError), and if both are true, SDK wins.
|
|
167
|
+
|
|
168
|
+
## License
|
|
169
|
+
|
|
170
|
+
MIT
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gemini
|
|
3
|
+
description: Gemini API — text generation, image/video/music generation, embeddings, search grounding, maps grounding, context caching, batch processing, code execution, function calling, file search/RAG, computer use, deep research, and more.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
Run: `python3 "${CLAUDE_SKILL_DIR}/scripts/gemini_run.py" <command> [args]`
|
|
10
|
+
|
|
11
|
+
The launcher self-routes: if the skill-local virtual environment exists at `${CLAUDE_SKILL_DIR}/.venv`, it re-execs into `${CLAUDE_SKILL_DIR}/.venv/bin/python` so the dual-backend SDK is loaded; otherwise it runs under whichever Python invoked it (the raw HTTP backend works without google-genai installed).
|
|
12
|
+
|
|
13
|
+
See `${CLAUDE_SKILL_DIR}/reference/index.md` for the full command map.
|
|
14
|
+
For commands with flags or `--execute`, read `${CLAUDE_SKILL_DIR}/reference/<command>.md` first.
|
|
15
|
+
|
|
16
|
+
## How transport works
|
|
17
|
+
|
|
18
|
+
All commands route through `scripts/gemini_run.py` which dispatches to the right adapter. The adapter calls a single `api_call` / `stream_generate_content` / `upload_file` facade that picks the right backend automatically based on `GEMINI_IS_SDK_PRIORITY` / `GEMINI_IS_RAWHTTP_PRIORITY` environment variables. **You do not need to know which backend is active** — every command has identical CLI surface, identical output shape, and identical error format regardless of whether the SDK or raw HTTP path handled the call.
|
|
19
|
+
|
|
20
|
+
## Rules
|
|
21
|
+
|
|
22
|
+
- Mutating operations and mutating subcommands require `--execute`. Default is dry-run.
|
|
23
|
+
- Privacy-sensitive commands (search grounding, maps grounding, computer use, deep research) are handled internally by dispatch; callers do not pass a separate privacy flag.
|
|
24
|
+
- Pass user input as single opaque argv values (quoted).
|
|
25
|
+
- Use stdin or temp files for complex/multiline content.
|
|
26
|
+
- Never reconstruct shell commands by concatenating user text.
|
|
27
|
+
- Multi-turn sessions: use `--session <id>` to start/continue, `--continue` for most recent.
|
|
28
|
+
- Large responses (>50KB) and all media generation save to a file and return only the path + metadata.
|
|
29
|
+
|
|
30
|
+
## Quick commands
|
|
31
|
+
|
|
32
|
+
- `help` — list all commands
|
|
33
|
+
- `models` — list available models from registry
|
|
34
|
+
- `text "prompt"` — generate text
|
|
35
|
+
- `multimodal "prompt" --file path.pdf` — analyze files
|
|
36
|
+
- `embed "text"` — generate embeddings
|
|
37
|
+
- `image_gen "prompt" --execute` — generate an image
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.1
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""Batch API adapter — submit, list, get, and cancel batch jobs.
|
|
2
|
+
|
|
3
|
+
Submits multiple requests for async processing at reduced cost.
|
|
4
|
+
Mutating operations (create, cancel) require --execute.
|
|
5
|
+
|
|
6
|
+
Dependencies: core/infra/client.py, core/adapter/helpers.py
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
|
|
13
|
+
from core.adapter.helpers import add_execute_flag, build_base_parser, check_dry_run, emit_json
|
|
14
|
+
from core.infra.sanitize import safe_print
|
|
15
|
+
from core.infra.client import api_call
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_parser() -> argparse.ArgumentParser:
|
|
19
|
+
"""Return the argument parser for the batch adapter."""
|
|
20
|
+
parser = build_base_parser("Manage Gemini batch processing jobs")
|
|
21
|
+
sub = parser.add_subparsers(dest="action", help="Batch action")
|
|
22
|
+
|
|
23
|
+
create_p = sub.add_parser("create", help="Create a batch job")
|
|
24
|
+
add_execute_flag(create_p)
|
|
25
|
+
create_p.add_argument("--src", required=True, help="Source file URI (JSONL).")
|
|
26
|
+
create_p.add_argument("--dest", required=True, help="Destination file URI.")
|
|
27
|
+
|
|
28
|
+
sub.add_parser("list", help="List batch jobs")
|
|
29
|
+
|
|
30
|
+
get_p = sub.add_parser("get", help="Get batch job status")
|
|
31
|
+
get_p.add_argument("name", help="Batch job resource name.")
|
|
32
|
+
|
|
33
|
+
cancel_p = sub.add_parser("cancel", help="Cancel a running batch job")
|
|
34
|
+
add_execute_flag(cancel_p)
|
|
35
|
+
cancel_p.add_argument("name", help="Batch job resource name to cancel.")
|
|
36
|
+
|
|
37
|
+
return parser
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def run(
|
|
41
|
+
action: str | None = None,
|
|
42
|
+
name: str | None = None,
|
|
43
|
+
src: str | None = None,
|
|
44
|
+
dest: str | None = None,
|
|
45
|
+
model: str | None = None,
|
|
46
|
+
execute: bool = False,
|
|
47
|
+
**kwargs: object,
|
|
48
|
+
) -> None:
|
|
49
|
+
"""Execute batch management operations."""
|
|
50
|
+
if action == "create":
|
|
51
|
+
_create(src=src, dest=dest, model=model, execute=execute)
|
|
52
|
+
elif action == "list":
|
|
53
|
+
_list_batches()
|
|
54
|
+
elif action == "get":
|
|
55
|
+
_get_batch(name=name)
|
|
56
|
+
elif action == "cancel":
|
|
57
|
+
_cancel_batch(name=name, execute=execute)
|
|
58
|
+
else:
|
|
59
|
+
safe_print("[ERROR] No action specified. Use: create, list, get, cancel")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _create(
|
|
63
|
+
src: str | None,
|
|
64
|
+
dest: str | None,
|
|
65
|
+
model: str | None,
|
|
66
|
+
execute: bool,
|
|
67
|
+
) -> None:
|
|
68
|
+
"""Create a batch processing job."""
|
|
69
|
+
if not src or not dest:
|
|
70
|
+
safe_print("[ERROR] Both --src and --dest are required.")
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
if check_dry_run(execute, f"create batch job from {src}"):
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
body: dict[str, object] = {
|
|
77
|
+
"inputConfig": {"gcsSource": {"inputUri": src}},
|
|
78
|
+
"outputConfig": {"gcsDestination": {"outputUriPrefix": dest}},
|
|
79
|
+
}
|
|
80
|
+
if model:
|
|
81
|
+
body["model"] = f"models/{model}"
|
|
82
|
+
|
|
83
|
+
response = api_call("batchJobs", body=body)
|
|
84
|
+
emit_json(response)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _list_batches() -> None:
|
|
88
|
+
"""List all batch jobs."""
|
|
89
|
+
response = api_call("batchJobs", method="GET")
|
|
90
|
+
jobs_value = response.get("batchJobs")
|
|
91
|
+
jobs = jobs_value if isinstance(jobs_value, list) else []
|
|
92
|
+
emit_json({"count": len(jobs), "jobs": jobs})
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _get_batch(name: str | None) -> None:
|
|
96
|
+
"""Get status of a batch job."""
|
|
97
|
+
if not name:
|
|
98
|
+
safe_print("[ERROR] No batch job name provided.")
|
|
99
|
+
return
|
|
100
|
+
response = api_call(name, method="GET")
|
|
101
|
+
emit_json(response)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _cancel_batch(name: str | None, execute: bool) -> None:
|
|
105
|
+
"""Cancel a running batch job."""
|
|
106
|
+
if not name:
|
|
107
|
+
safe_print("[ERROR] No batch job name provided.")
|
|
108
|
+
return
|
|
109
|
+
if check_dry_run(execute, f"cancel batch {name}"):
|
|
110
|
+
return
|
|
111
|
+
api_call(f"{name}:cancel", body={})
|
|
112
|
+
safe_print(f"Cancelled batch {name}")
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""Context caching adapter — create, list, get, and delete caches.
|
|
2
|
+
|
|
3
|
+
Caches large content (system instructions, files) to reduce cost and
|
|
4
|
+
latency on repeated requests. Mutating operations require --execute.
|
|
5
|
+
|
|
6
|
+
Dependencies: core/infra/client.py, core/adapter/helpers.py
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from core.adapter.helpers import add_execute_flag, build_base_parser, check_dry_run, emit_json
|
|
15
|
+
from core.infra.sanitize import safe_print
|
|
16
|
+
from core.infra.client import api_call
|
|
17
|
+
from core.infra.config import load_config
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_parser() -> argparse.ArgumentParser:
|
|
21
|
+
"""Return the argument parser for the cache adapter."""
|
|
22
|
+
parser = build_base_parser("Manage Gemini context caches")
|
|
23
|
+
sub = parser.add_subparsers(dest="action", help="Cache action")
|
|
24
|
+
|
|
25
|
+
create_p = sub.add_parser("create", help="Create a cache")
|
|
26
|
+
add_execute_flag(create_p)
|
|
27
|
+
create_p.add_argument("content", help="Content to cache (text or file URI).")
|
|
28
|
+
create_p.add_argument("--ttl", default="3600s", help="Time-to-live (e.g., '3600s').")
|
|
29
|
+
|
|
30
|
+
sub.add_parser("list", help="List existing caches")
|
|
31
|
+
|
|
32
|
+
get_p = sub.add_parser("get", help="Get cache metadata")
|
|
33
|
+
get_p.add_argument("name", help="Cache resource name.")
|
|
34
|
+
|
|
35
|
+
delete_p = sub.add_parser("delete", help="Delete a cache")
|
|
36
|
+
add_execute_flag(delete_p)
|
|
37
|
+
delete_p.add_argument("name", help="Cache resource name to delete.")
|
|
38
|
+
|
|
39
|
+
return parser
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def run(
|
|
43
|
+
action: str | None = None,
|
|
44
|
+
content: str | None = None,
|
|
45
|
+
name: str | None = None,
|
|
46
|
+
ttl: str = "3600s",
|
|
47
|
+
model: str | None = None,
|
|
48
|
+
execute: bool = False,
|
|
49
|
+
**kwargs: object,
|
|
50
|
+
) -> None:
|
|
51
|
+
"""Execute cache management operations."""
|
|
52
|
+
if action == "create":
|
|
53
|
+
_create(content=content, ttl=ttl, model=model, execute=execute)
|
|
54
|
+
elif action == "list":
|
|
55
|
+
_list_caches()
|
|
56
|
+
elif action == "get":
|
|
57
|
+
_get_cache(name=name)
|
|
58
|
+
elif action == "delete":
|
|
59
|
+
_delete_cache(name=name, execute=execute)
|
|
60
|
+
else:
|
|
61
|
+
safe_print("[ERROR] No action specified. Use: create, list, get, delete")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _create(
|
|
65
|
+
content: str | None,
|
|
66
|
+
ttl: str,
|
|
67
|
+
model: str | None,
|
|
68
|
+
execute: bool,
|
|
69
|
+
) -> None:
|
|
70
|
+
"""Create a context cache."""
|
|
71
|
+
if not content:
|
|
72
|
+
safe_print("[ERROR] No content provided.")
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
if check_dry_run(execute, f"create cache with TTL {ttl}"):
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
from core.routing.router import Router
|
|
79
|
+
|
|
80
|
+
config = load_config()
|
|
81
|
+
router = Router(
|
|
82
|
+
root_dir=Path(__file__).parent.parent.parent,
|
|
83
|
+
prefer_preview=config.prefer_preview_models,
|
|
84
|
+
)
|
|
85
|
+
resolved_model = model or router.select_model("cache")
|
|
86
|
+
|
|
87
|
+
body: dict[str, object] = {
|
|
88
|
+
"model": f"models/{resolved_model}",
|
|
89
|
+
"contents": [{"role": "user", "parts": [{"text": content}]}],
|
|
90
|
+
"ttl": ttl,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
response = api_call("cachedContents", body=body)
|
|
94
|
+
emit_json(response)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _list_caches() -> None:
|
|
98
|
+
"""List all context caches."""
|
|
99
|
+
response = api_call("cachedContents", method="GET")
|
|
100
|
+
caches_value = response.get("cachedContents")
|
|
101
|
+
caches = caches_value if isinstance(caches_value, list) else []
|
|
102
|
+
emit_json({"count": len(caches), "caches": caches})
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _get_cache(name: str | None) -> None:
|
|
106
|
+
"""Get metadata for a single cache."""
|
|
107
|
+
if not name:
|
|
108
|
+
safe_print("[ERROR] No cache name provided.")
|
|
109
|
+
return
|
|
110
|
+
response = api_call(name, method="GET")
|
|
111
|
+
emit_json(response)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _delete_cache(name: str | None, execute: bool) -> None:
|
|
115
|
+
"""Delete a context cache."""
|
|
116
|
+
if not name:
|
|
117
|
+
safe_print("[ERROR] No cache name provided.")
|
|
118
|
+
return
|
|
119
|
+
if check_dry_run(execute, f"delete cache {name}"):
|
|
120
|
+
return
|
|
121
|
+
api_call(name, method="DELETE")
|
|
122
|
+
safe_print(f"Deleted cache {name}")
|