ag-cortex 0.1.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 (162) hide show
  1. package/.agent/commands/test-browser.md +339 -0
  2. package/.agent/rules/00-constitution.md +46 -0
  3. package/.agent/rules/project-rules.md +49 -0
  4. package/.agent/skills/agent-browser/SKILL.md +223 -0
  5. package/.agent/skills/agent-native-architecture/SKILL.md +435 -0
  6. package/.agent/skills/agent-native-architecture/references/action-parity-discipline.md +409 -0
  7. package/.agent/skills/agent-native-architecture/references/agent-execution-patterns.md +467 -0
  8. package/.agent/skills/agent-native-architecture/references/agent-native-testing.md +582 -0
  9. package/.agent/skills/agent-native-architecture/references/architecture-patterns.md +478 -0
  10. package/.agent/skills/agent-native-architecture/references/dynamic-context-injection.md +338 -0
  11. package/.agent/skills/agent-native-architecture/references/files-universal-interface.md +301 -0
  12. package/.agent/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +359 -0
  13. package/.agent/skills/agent-native-architecture/references/mcp-tool-design.md +506 -0
  14. package/.agent/skills/agent-native-architecture/references/mobile-patterns.md +871 -0
  15. package/.agent/skills/agent-native-architecture/references/product-implications.md +443 -0
  16. package/.agent/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +317 -0
  17. package/.agent/skills/agent-native-architecture/references/self-modification.md +269 -0
  18. package/.agent/skills/agent-native-architecture/references/shared-workspace-architecture.md +680 -0
  19. package/.agent/skills/agent-native-architecture/references/system-prompt-design.md +250 -0
  20. package/.agent/skills/agent-native-reviewer/SKILL.md +246 -0
  21. package/.agent/skills/andrew-kane-gem-writer/SKILL.md +184 -0
  22. package/.agent/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
  23. package/.agent/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
  24. package/.agent/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
  25. package/.agent/skills/andrew-kane-gem-writer/references/resources.md +119 -0
  26. package/.agent/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
  27. package/.agent/skills/ankane-readme-writer/SKILL.md +50 -0
  28. package/.agent/skills/architecture-strategist/SKILL.md +52 -0
  29. package/.agent/skills/best-practices-researcher/SKILL.md +100 -0
  30. package/.agent/skills/bug-reproduction-validator/SKILL.md +67 -0
  31. package/.agent/skills/code-simplicity-reviewer/SKILL.md +85 -0
  32. package/.agent/skills/coding-tutor/.claude-plugin/plugin.json +9 -0
  33. package/.agent/skills/coding-tutor/README.md +37 -0
  34. package/.agent/skills/coding-tutor/commands/quiz-me.md +1 -0
  35. package/.agent/skills/coding-tutor/commands/sync-tutorials.md +25 -0
  36. package/.agent/skills/coding-tutor/commands/teach-me.md +1 -0
  37. package/.agent/skills/coding-tutor/skills/coding-tutor/SKILL.md +214 -0
  38. package/.agent/skills/coding-tutor/skills/coding-tutor/scripts/create_tutorial.py +202 -0
  39. package/.agent/skills/coding-tutor/skills/coding-tutor/scripts/index_tutorials.py +203 -0
  40. package/.agent/skills/coding-tutor/skills/coding-tutor/scripts/quiz_priority.py +190 -0
  41. package/.agent/skills/coding-tutor/skills/coding-tutor/scripts/setup_tutorials.py +132 -0
  42. package/.agent/skills/compound-docs/SKILL.md +510 -0
  43. package/.agent/skills/compound-docs/assets/critical-pattern-template.md +34 -0
  44. package/.agent/skills/compound-docs/assets/resolution-template.md +93 -0
  45. package/.agent/skills/compound-docs/references/yaml-schema.md +65 -0
  46. package/.agent/skills/compound-docs/schema.yaml +176 -0
  47. package/.agent/skills/create-agent-skills/SKILL.md +299 -0
  48. package/.agent/skills/create-agent-skills/references/api-security.md +226 -0
  49. package/.agent/skills/create-agent-skills/references/be-clear-and-direct.md +531 -0
  50. package/.agent/skills/create-agent-skills/references/best-practices.md +404 -0
  51. package/.agent/skills/create-agent-skills/references/common-patterns.md +595 -0
  52. package/.agent/skills/create-agent-skills/references/core-principles.md +437 -0
  53. package/.agent/skills/create-agent-skills/references/executable-code.md +175 -0
  54. package/.agent/skills/create-agent-skills/references/iteration-and-testing.md +474 -0
  55. package/.agent/skills/create-agent-skills/references/official-spec.md +185 -0
  56. package/.agent/skills/create-agent-skills/references/recommended-structure.md +168 -0
  57. package/.agent/skills/create-agent-skills/references/skill-structure.md +372 -0
  58. package/.agent/skills/create-agent-skills/references/using-scripts.md +113 -0
  59. package/.agent/skills/create-agent-skills/references/using-templates.md +112 -0
  60. package/.agent/skills/create-agent-skills/references/workflows-and-validation.md +510 -0
  61. package/.agent/skills/create-agent-skills/templates/router-skill.md +73 -0
  62. package/.agent/skills/create-agent-skills/templates/simple-skill.md +33 -0
  63. package/.agent/skills/create-agent-skills/workflows/add-reference.md +96 -0
  64. package/.agent/skills/create-agent-skills/workflows/add-script.md +93 -0
  65. package/.agent/skills/create-agent-skills/workflows/add-template.md +74 -0
  66. package/.agent/skills/create-agent-skills/workflows/add-workflow.md +120 -0
  67. package/.agent/skills/create-agent-skills/workflows/audit-skill.md +138 -0
  68. package/.agent/skills/create-agent-skills/workflows/create-domain-expertise-skill.md +605 -0
  69. package/.agent/skills/create-agent-skills/workflows/create-new-skill.md +191 -0
  70. package/.agent/skills/create-agent-skills/workflows/get-guidance.md +121 -0
  71. package/.agent/skills/create-agent-skills/workflows/upgrade-to-router.md +161 -0
  72. package/.agent/skills/create-agent-skills/workflows/verify-skill.md +204 -0
  73. package/.agent/skills/data-integrity-guardian/SKILL.md +70 -0
  74. package/.agent/skills/data-migration-expert/SKILL.md +97 -0
  75. package/.agent/skills/deployment-verification-agent/SKILL.md +159 -0
  76. package/.agent/skills/design-implementation-reviewer/SKILL.md +85 -0
  77. package/.agent/skills/design-iterator/SKILL.md +197 -0
  78. package/.agent/skills/dhh-rails-reviewer/SKILL.md +45 -0
  79. package/.agent/skills/dhh-rails-style/SKILL.md +184 -0
  80. package/.agent/skills/dhh-rails-style/references/architecture.md +653 -0
  81. package/.agent/skills/dhh-rails-style/references/controllers.md +303 -0
  82. package/.agent/skills/dhh-rails-style/references/frontend.md +510 -0
  83. package/.agent/skills/dhh-rails-style/references/gems.md +266 -0
  84. package/.agent/skills/dhh-rails-style/references/models.md +359 -0
  85. package/.agent/skills/dhh-rails-style/references/testing.md +338 -0
  86. package/.agent/skills/dspy-ruby/SKILL.md +594 -0
  87. package/.agent/skills/dspy-ruby/assets/config-template.rb +359 -0
  88. package/.agent/skills/dspy-ruby/assets/module-template.rb +326 -0
  89. package/.agent/skills/dspy-ruby/assets/signature-template.rb +143 -0
  90. package/.agent/skills/dspy-ruby/references/core-concepts.md +265 -0
  91. package/.agent/skills/dspy-ruby/references/optimization.md +623 -0
  92. package/.agent/skills/dspy-ruby/references/providers.md +305 -0
  93. package/.agent/skills/every-style-editor/SKILL.md +134 -0
  94. package/.agent/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
  95. package/.agent/skills/figma-design-sync/SKILL.md +166 -0
  96. package/.agent/skills/file-todos/SKILL.md +251 -0
  97. package/.agent/skills/file-todos/assets/todo-template.md +155 -0
  98. package/.agent/skills/framework-docs-researcher/SKILL.md +83 -0
  99. package/.agent/skills/frontend-design/SKILL.md +42 -0
  100. package/.agent/skills/gemini-imagegen/SKILL.md +237 -0
  101. package/.agent/skills/gemini-imagegen/requirements.txt +2 -0
  102. package/.agent/skills/gemini-imagegen/scripts/compose_images.py +168 -0
  103. package/.agent/skills/gemini-imagegen/scripts/edit_image.py +157 -0
  104. package/.agent/skills/gemini-imagegen/scripts/gemini_images.py +265 -0
  105. package/.agent/skills/gemini-imagegen/scripts/generate_image.py +147 -0
  106. package/.agent/skills/gemini-imagegen/scripts/multi_turn_chat.py +215 -0
  107. package/.agent/skills/git-history-analyzer/SKILL.md +42 -0
  108. package/.agent/skills/git-worktree/SKILL.md +302 -0
  109. package/.agent/skills/git-worktree/scripts/worktree-manager.sh +345 -0
  110. package/.agent/skills/julik-frontend-races-reviewer/SKILL.md +222 -0
  111. package/.agent/skills/kieran-python-reviewer/SKILL.md +104 -0
  112. package/.agent/skills/kieran-rails-reviewer/SKILL.md +86 -0
  113. package/.agent/skills/kieran-typescript-reviewer/SKILL.md +95 -0
  114. package/.agent/skills/lint/SKILL.md +16 -0
  115. package/.agent/skills/pattern-recognition-specialist/SKILL.md +57 -0
  116. package/.agent/skills/performance-oracle/SKILL.md +110 -0
  117. package/.agent/skills/pr-comment-resolver/SKILL.md +69 -0
  118. package/.agent/skills/rclone/SKILL.md +150 -0
  119. package/.agent/skills/rclone/scripts/check_setup.sh +60 -0
  120. package/.agent/skills/repo-research-analyst/SKILL.md +113 -0
  121. package/.agent/skills/security-sentinel/SKILL.md +93 -0
  122. package/.agent/skills/skill-creator/SKILL.md +209 -0
  123. package/.agent/skills/skill-creator/scripts/init_skill.py +304 -0
  124. package/.agent/skills/skill-creator/scripts/package_skill.py +112 -0
  125. package/.agent/skills/skill-creator/scripts/quick_validate.py +72 -0
  126. package/.agent/skills/spec-flow-analyzer/SKILL.md +113 -0
  127. package/.agent/skills/test-agent/SKILL.md +4 -0
  128. package/.agent/workflows/agent-native-audit.md +277 -0
  129. package/.agent/workflows/ask-user-question.md +21 -0
  130. package/.agent/workflows/changelog.md +137 -0
  131. package/.agent/workflows/compound.md +202 -0
  132. package/.agent/workflows/create-agent-skill.md +8 -0
  133. package/.agent/workflows/deepen-plan-research.md +334 -0
  134. package/.agent/workflows/deepen-plan-synthesis.md +182 -0
  135. package/.agent/workflows/deepen-plan.md +79 -0
  136. package/.agent/workflows/feature-video.md +342 -0
  137. package/.agent/workflows/generate-command.md +162 -0
  138. package/.agent/workflows/heal-skill.md +142 -0
  139. package/.agent/workflows/lfg.md +20 -0
  140. package/.agent/workflows/plan-analysis.md +67 -0
  141. package/.agent/workflows/plan-next-steps.md +63 -0
  142. package/.agent/workflows/plan-review.md +33 -0
  143. package/.agent/workflows/plan-synthesis.md +106 -0
  144. package/.agent/workflows/plan.md +49 -0
  145. package/.agent/workflows/report-bug.md +150 -0
  146. package/.agent/workflows/reproduce-bug.md +99 -0
  147. package/.agent/workflows/resolve-parallel.md +34 -0
  148. package/.agent/workflows/resolve-pr-parallel.md +49 -0
  149. package/.agent/workflows/resolve-todo-parallel.md +35 -0
  150. package/.agent/workflows/review-analysis.md +145 -0
  151. package/.agent/workflows/review-synthesis.md +262 -0
  152. package/.agent/workflows/review.md +64 -0
  153. package/.agent/workflows/ship.md +90 -0
  154. package/.agent/workflows/test-command.md +3 -0
  155. package/.agent/workflows/triage.md +310 -0
  156. package/.agent/workflows/work.md +157 -0
  157. package/.agent/workflows/xcode-test.md +332 -0
  158. package/LICENSE +22 -0
  159. package/README.md +49 -0
  160. package/bin/ag-cortex.js +54 -0
  161. package/lib/core.js +165 -0
  162. package/package.json +31 -0
@@ -0,0 +1,265 @@
1
+ """
2
+ Gemini Image Generation Library
3
+
4
+ A simple Python library for generating and editing images with the Gemini API.
5
+
6
+ Usage:
7
+ from gemini_images import GeminiImageGenerator
8
+
9
+ gen = GeminiImageGenerator()
10
+ gen.generate("A sunset over mountains", "sunset.png")
11
+ gen.edit("input.png", "Add clouds", "output.png")
12
+
13
+ Environment:
14
+ GEMINI_API_KEY - Required API key
15
+ """
16
+
17
+ import os
18
+ from pathlib import Path
19
+ from typing import Literal
20
+
21
+ from PIL import Image
22
+ from google import genai
23
+ from google.genai import types
24
+
25
+
26
+ AspectRatio = Literal[
27
+ "1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"
28
+ ]
29
+ ImageSize = Literal["1K", "2K", "4K"]
30
+ Model = Literal["gemini-2.5-flash-image", "gemini-3-pro-image-preview"]
31
+
32
+
33
+ class GeminiImageGenerator:
34
+ """High-level interface for Gemini image generation."""
35
+
36
+ FLASH = "gemini-2.5-flash-image"
37
+ PRO = "gemini-3-pro-image-preview"
38
+
39
+ def __init__(self, api_key: str | None = None, model: Model = FLASH):
40
+ """Initialize the generator.
41
+
42
+ Args:
43
+ api_key: Gemini API key (defaults to GEMINI_API_KEY env var)
44
+ model: Default model to use
45
+ """
46
+ self.api_key = api_key or os.environ.get("GEMINI_API_KEY")
47
+ if not self.api_key:
48
+ raise EnvironmentError("GEMINI_API_KEY not set")
49
+
50
+ self.client = genai.Client(api_key=self.api_key)
51
+ self.model = model
52
+
53
+ def _build_config(
54
+ self,
55
+ aspect_ratio: AspectRatio | None = None,
56
+ image_size: ImageSize | None = None,
57
+ google_search: bool = False,
58
+ ) -> types.GenerateContentConfig:
59
+ """Build generation config."""
60
+ kwargs = {"response_modalities": ["TEXT", "IMAGE"]}
61
+
62
+ img_config = {}
63
+ if aspect_ratio:
64
+ img_config["aspect_ratio"] = aspect_ratio
65
+ if image_size:
66
+ img_config["image_size"] = image_size
67
+
68
+ if img_config:
69
+ kwargs["image_config"] = types.ImageConfig(**img_config)
70
+
71
+ if google_search:
72
+ kwargs["tools"] = [{"google_search": {}}]
73
+
74
+ return types.GenerateContentConfig(**kwargs)
75
+
76
+ def generate(
77
+ self,
78
+ prompt: str,
79
+ output: str | Path,
80
+ *,
81
+ model: Model | None = None,
82
+ aspect_ratio: AspectRatio | None = None,
83
+ image_size: ImageSize | None = None,
84
+ google_search: bool = False,
85
+ ) -> tuple[Path, str | None]:
86
+ """Generate an image from a text prompt.
87
+
88
+ Args:
89
+ prompt: Text description
90
+ output: Output file path
91
+ model: Override default model
92
+ aspect_ratio: Output aspect ratio
93
+ image_size: Output resolution
94
+ google_search: Enable Google Search grounding (Pro only)
95
+
96
+ Returns:
97
+ Tuple of (output path, optional text response)
98
+ """
99
+ output = Path(output)
100
+ config = self._build_config(aspect_ratio, image_size, google_search)
101
+
102
+ response = self.client.models.generate_content(
103
+ model=model or self.model,
104
+ contents=[prompt],
105
+ config=config,
106
+ )
107
+
108
+ text = None
109
+ for part in response.parts:
110
+ if part.text:
111
+ text = part.text
112
+ elif part.inline_data:
113
+ part.as_image().save(output)
114
+
115
+ return output, text
116
+
117
+ def edit(
118
+ self,
119
+ input_image: str | Path | Image.Image,
120
+ instruction: str,
121
+ output: str | Path,
122
+ *,
123
+ model: Model | None = None,
124
+ aspect_ratio: AspectRatio | None = None,
125
+ image_size: ImageSize | None = None,
126
+ ) -> tuple[Path, str | None]:
127
+ """Edit an existing image.
128
+
129
+ Args:
130
+ input_image: Input image (path or PIL Image)
131
+ instruction: Edit instruction
132
+ output: Output file path
133
+ model: Override default model
134
+ aspect_ratio: Output aspect ratio
135
+ image_size: Output resolution
136
+
137
+ Returns:
138
+ Tuple of (output path, optional text response)
139
+ """
140
+ output = Path(output)
141
+
142
+ if isinstance(input_image, (str, Path)):
143
+ input_image = Image.open(input_image)
144
+
145
+ config = self._build_config(aspect_ratio, image_size)
146
+
147
+ response = self.client.models.generate_content(
148
+ model=model or self.model,
149
+ contents=[instruction, input_image],
150
+ config=config,
151
+ )
152
+
153
+ text = None
154
+ for part in response.parts:
155
+ if part.text:
156
+ text = part.text
157
+ elif part.inline_data:
158
+ part.as_image().save(output)
159
+
160
+ return output, text
161
+
162
+ def compose(
163
+ self,
164
+ instruction: str,
165
+ images: list[str | Path | Image.Image],
166
+ output: str | Path,
167
+ *,
168
+ model: Model | None = None,
169
+ aspect_ratio: AspectRatio | None = None,
170
+ image_size: ImageSize | None = None,
171
+ ) -> tuple[Path, str | None]:
172
+ """Compose multiple images into one.
173
+
174
+ Args:
175
+ instruction: Composition instruction
176
+ images: List of input images (up to 14)
177
+ output: Output file path
178
+ model: Override default model (Pro recommended)
179
+ aspect_ratio: Output aspect ratio
180
+ image_size: Output resolution
181
+
182
+ Returns:
183
+ Tuple of (output path, optional text response)
184
+ """
185
+ output = Path(output)
186
+
187
+ # Load images
188
+ loaded = []
189
+ for img in images:
190
+ if isinstance(img, (str, Path)):
191
+ loaded.append(Image.open(img))
192
+ else:
193
+ loaded.append(img)
194
+
195
+ config = self._build_config(aspect_ratio, image_size)
196
+ contents = [instruction] + loaded
197
+
198
+ response = self.client.models.generate_content(
199
+ model=model or self.PRO, # Pro recommended for composition
200
+ contents=contents,
201
+ config=config,
202
+ )
203
+
204
+ text = None
205
+ for part in response.parts:
206
+ if part.text:
207
+ text = part.text
208
+ elif part.inline_data:
209
+ part.as_image().save(output)
210
+
211
+ return output, text
212
+
213
+ def chat(self) -> "ImageChat":
214
+ """Start an interactive chat session for iterative refinement."""
215
+ return ImageChat(self.client, self.model)
216
+
217
+
218
+ class ImageChat:
219
+ """Multi-turn chat session for iterative image generation."""
220
+
221
+ def __init__(self, client: genai.Client, model: Model):
222
+ self.client = client
223
+ self.model = model
224
+ self._chat = client.chats.create(
225
+ model=model,
226
+ config=types.GenerateContentConfig(response_modalities=["TEXT", "IMAGE"]),
227
+ )
228
+ self.current_image: Image.Image | None = None
229
+
230
+ def send(
231
+ self,
232
+ message: str,
233
+ image: Image.Image | str | Path | None = None,
234
+ ) -> tuple[Image.Image | None, str | None]:
235
+ """Send a message and optionally an image.
236
+
237
+ Returns:
238
+ Tuple of (generated image or None, text response or None)
239
+ """
240
+ contents = [message]
241
+ if image:
242
+ if isinstance(image, (str, Path)):
243
+ image = Image.open(image)
244
+ contents.append(image)
245
+
246
+ response = self._chat.send_message(contents)
247
+
248
+ text = None
249
+ img = None
250
+ for part in response.parts:
251
+ if part.text:
252
+ text = part.text
253
+ elif part.inline_data:
254
+ img = part.as_image()
255
+ self.current_image = img
256
+
257
+ return img, text
258
+
259
+ def reset(self):
260
+ """Reset the chat session."""
261
+ self._chat = self.client.chats.create(
262
+ model=self.model,
263
+ config=types.GenerateContentConfig(response_modalities=["TEXT", "IMAGE"]),
264
+ )
265
+ self.current_image = None
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Generate images from text prompts using Gemini API.
4
+
5
+ Usage:
6
+ python generate_image.py "prompt" output.png [--model MODEL] [--aspect RATIO] [--size SIZE]
7
+
8
+ Examples:
9
+ python generate_image.py "A cat in space" cat.png
10
+ python generate_image.py "A logo for Acme Corp" logo.png --model gemini-3-pro-image-preview --aspect 1:1
11
+ python generate_image.py "Epic landscape" landscape.png --aspect 16:9 --size 2K
12
+
13
+ Environment:
14
+ GEMINI_API_KEY - Required API key
15
+ """
16
+
17
+ import argparse
18
+ import os
19
+ import sys
20
+
21
+ from google import genai
22
+ from google.genai import types
23
+
24
+
25
+ def generate_image(
26
+ prompt: str,
27
+ output_path: str,
28
+ model: str = "gemini-2.5-flash-image",
29
+ aspect_ratio: str | None = None,
30
+ image_size: str | None = None,
31
+ ) -> str | None:
32
+ """Generate an image from a text prompt.
33
+
34
+ Args:
35
+ prompt: Text description of the image to generate
36
+ output_path: Path to save the generated image
37
+ model: Gemini model to use
38
+ aspect_ratio: Aspect ratio (1:1, 16:9, 9:16, etc.)
39
+ image_size: Resolution (1K, 2K, 4K - 4K only for pro model)
40
+
41
+ Returns:
42
+ Any text response from the model, or None
43
+ """
44
+ api_key = os.environ.get("GEMINI_API_KEY")
45
+ if not api_key:
46
+ raise EnvironmentError("GEMINI_API_KEY environment variable not set")
47
+
48
+ client = genai.Client(api_key=api_key)
49
+
50
+ # Build config
51
+ config_kwargs = {"response_modalities": ["TEXT", "IMAGE"]}
52
+
53
+ image_config_kwargs = {}
54
+ if aspect_ratio:
55
+ image_config_kwargs["aspect_ratio"] = aspect_ratio
56
+ if image_size:
57
+ image_config_kwargs["image_size"] = image_size
58
+
59
+ if image_config_kwargs:
60
+ config_kwargs["image_config"] = types.ImageConfig(**image_config_kwargs)
61
+
62
+ config = types.GenerateContentConfig(**config_kwargs)
63
+
64
+ response = client.models.generate_content(
65
+ model=model,
66
+ contents=[prompt],
67
+ config=config,
68
+ )
69
+
70
+ text_response = None
71
+ image_saved = False
72
+
73
+ for part in response.parts:
74
+ if part.text is not None:
75
+ text_response = part.text
76
+ elif part.inline_data is not None:
77
+ image = part.as_image()
78
+ image.save(output_path)
79
+ image_saved = True
80
+
81
+ if not image_saved:
82
+ raise RuntimeError("No image was generated. Check your prompt and try again.")
83
+
84
+ return text_response
85
+
86
+
87
+ def main():
88
+ parser = argparse.ArgumentParser(
89
+ description="Generate images from text prompts using Gemini API",
90
+ formatter_class=argparse.RawDescriptionHelpFormatter,
91
+ epilog=__doc__,
92
+ )
93
+ parser.add_argument("prompt", help="Text prompt describing the image")
94
+ parser.add_argument("output", help="Output file path (e.g., output.png)")
95
+ parser.add_argument(
96
+ "--model",
97
+ "-m",
98
+ default="gemini-2.5-flash-image",
99
+ choices=["gemini-2.5-flash-image", "gemini-3-pro-image-preview"],
100
+ help="Model to use (default: gemini-2.5-flash-image)",
101
+ )
102
+ parser.add_argument(
103
+ "--aspect",
104
+ "-a",
105
+ choices=[
106
+ "1:1",
107
+ "2:3",
108
+ "3:2",
109
+ "3:4",
110
+ "4:3",
111
+ "4:5",
112
+ "5:4",
113
+ "9:16",
114
+ "16:9",
115
+ "21:9",
116
+ ],
117
+ help="Aspect ratio",
118
+ )
119
+ parser.add_argument(
120
+ "--size",
121
+ "-s",
122
+ choices=["1K", "2K", "4K"],
123
+ help="Image resolution (4K only available with pro model)",
124
+ )
125
+
126
+ args = parser.parse_args()
127
+
128
+ try:
129
+ text = generate_image(
130
+ prompt=args.prompt,
131
+ output_path=args.output,
132
+ model=args.model,
133
+ aspect_ratio=args.aspect,
134
+ image_size=args.size,
135
+ )
136
+
137
+ print(f"Image saved to: {args.output}")
138
+ if text:
139
+ print(f"Model response: {text}")
140
+
141
+ except Exception as e:
142
+ print(f"Error: {e}", file=sys.stderr)
143
+ sys.exit(1)
144
+
145
+
146
+ if __name__ == "__main__":
147
+ main()
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Interactive multi-turn image generation and refinement using Gemini API.
4
+
5
+ Usage:
6
+ python multi_turn_chat.py [--model MODEL] [--output-dir DIR]
7
+
8
+ This starts an interactive session where you can:
9
+ - Generate images from prompts
10
+ - Iteratively refine images through conversation
11
+ - Load existing images for editing
12
+ - Save images at any point
13
+
14
+ Commands:
15
+ /save [filename] - Save current image
16
+ /load <path> - Load an image into the conversation
17
+ /clear - Start fresh conversation
18
+ /quit - Exit
19
+
20
+ Environment:
21
+ GEMINI_API_KEY - Required API key
22
+ """
23
+
24
+ import argparse
25
+ import os
26
+ import sys
27
+ from datetime import datetime
28
+ from pathlib import Path
29
+
30
+ from PIL import Image
31
+ from google import genai
32
+ from google.genai import types
33
+
34
+
35
+ class ImageChat:
36
+ """Interactive chat session for image generation and refinement."""
37
+
38
+ def __init__(
39
+ self,
40
+ model: str = "gemini-2.5-flash-image",
41
+ output_dir: str = ".",
42
+ ):
43
+ api_key = os.environ.get("GEMINI_API_KEY")
44
+ if not api_key:
45
+ raise EnvironmentError("GEMINI_API_KEY environment variable not set")
46
+
47
+ self.client = genai.Client(api_key=api_key)
48
+ self.model = model
49
+ self.output_dir = Path(output_dir)
50
+ self.output_dir.mkdir(parents=True, exist_ok=True)
51
+
52
+ self.chat = None
53
+ self.current_image = None
54
+ self.image_count = 0
55
+
56
+ self._init_chat()
57
+
58
+ def _init_chat(self):
59
+ """Initialize or reset the chat session."""
60
+ config = types.GenerateContentConfig(response_modalities=["TEXT", "IMAGE"])
61
+ self.chat = self.client.chats.create(
62
+ model=self.model,
63
+ config=config,
64
+ )
65
+ self.current_image = None
66
+
67
+ def send_message(
68
+ self, message: str, image: Image.Image | None = None
69
+ ) -> tuple[str | None, Image.Image | None]:
70
+ """Send a message and optionally an image, return response text and image."""
71
+ contents = []
72
+ if message:
73
+ contents.append(message)
74
+ if image:
75
+ contents.append(image)
76
+
77
+ if not contents:
78
+ return None, None
79
+
80
+ response = self.chat.send_message(contents)
81
+
82
+ text_response = None
83
+ image_response = None
84
+
85
+ for part in response.parts:
86
+ if part.text is not None:
87
+ text_response = part.text
88
+ elif part.inline_data is not None:
89
+ image_response = part.as_image()
90
+ self.current_image = image_response
91
+
92
+ return text_response, image_response
93
+
94
+ def save_image(self, filename: str | None = None) -> str | None:
95
+ """Save the current image to a file."""
96
+ if self.current_image is None:
97
+ return None
98
+
99
+ if filename is None:
100
+ self.image_count += 1
101
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
102
+ filename = f"image_{timestamp}_{self.image_count}.png"
103
+
104
+ filepath = self.output_dir / filename
105
+ self.current_image.save(filepath)
106
+ return str(filepath)
107
+
108
+ def load_image(self, path: str) -> Image.Image:
109
+ """Load an image from disk."""
110
+ img = Image.open(path)
111
+ self.current_image = img
112
+ return img
113
+
114
+
115
+ def main():
116
+ parser = argparse.ArgumentParser(
117
+ description="Interactive multi-turn image generation",
118
+ formatter_class=argparse.RawDescriptionHelpFormatter,
119
+ epilog=__doc__,
120
+ )
121
+ parser.add_argument(
122
+ "--model",
123
+ "-m",
124
+ default="gemini-2.5-flash-image",
125
+ choices=["gemini-2.5-flash-image", "gemini-3-pro-image-preview"],
126
+ help="Model to use",
127
+ )
128
+ parser.add_argument(
129
+ "--output-dir", "-o", default=".", help="Directory to save images"
130
+ )
131
+
132
+ args = parser.parse_args()
133
+
134
+ try:
135
+ chat = ImageChat(model=args.model, output_dir=args.output_dir)
136
+ except Exception as e:
137
+ print(f"Error initializing: {e}", file=sys.stderr)
138
+ sys.exit(1)
139
+
140
+ print(f"Gemini Image Chat ({args.model})")
141
+ print("Commands: /save [name], /load <path>, /clear, /quit")
142
+ print("-" * 50)
143
+
144
+ while True:
145
+ try:
146
+ user_input = input("\nYou: ").strip()
147
+ except (EOFError, KeyboardInterrupt):
148
+ print("\nGoodbye!")
149
+ break
150
+
151
+ if not user_input:
152
+ continue
153
+
154
+ # Handle commands
155
+ if user_input.startswith("/"):
156
+ parts = user_input.split(maxsplit=1)
157
+ cmd = parts[0].lower()
158
+ arg = parts[1] if len(parts) > 1 else None
159
+
160
+ if cmd == "/quit":
161
+ print("Goodbye!")
162
+ break
163
+
164
+ elif cmd == "/clear":
165
+ chat._init_chat()
166
+ print("Conversation cleared.")
167
+ continue
168
+
169
+ elif cmd == "/save":
170
+ path = chat.save_image(arg)
171
+ if path:
172
+ print(f"Image saved to: {path}")
173
+ else:
174
+ print("No image to save.")
175
+ continue
176
+
177
+ elif cmd == "/load":
178
+ if not arg:
179
+ print("Usage: /load <path>")
180
+ continue
181
+ try:
182
+ chat.load_image(arg)
183
+ print(f"Loaded: {arg}")
184
+ print("You can now describe edits to make.")
185
+ except Exception as e:
186
+ print(f"Error loading image: {e}")
187
+ continue
188
+
189
+ else:
190
+ print(f"Unknown command: {cmd}")
191
+ continue
192
+
193
+ # Send message to model
194
+ try:
195
+ # If we have a loaded image and this is first message, include it
196
+ image_to_send = None
197
+ if chat.current_image and not chat.chat.history:
198
+ image_to_send = chat.current_image
199
+
200
+ text, image = chat.send_message(user_input, image_to_send)
201
+
202
+ if text:
203
+ print(f"\nGemini: {text}")
204
+
205
+ if image:
206
+ # Auto-save
207
+ path = chat.save_image()
208
+ print(f"\n[Image generated: {path}]")
209
+
210
+ except Exception as e:
211
+ print(f"\nError: {e}")
212
+
213
+
214
+ if __name__ == "__main__":
215
+ main()
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: git-history-analyzer
3
+ description: "Use this agent when you need to understand the historical context and evolution of code changes, trace the origins of specific code patterns, identify key contributors and their expertise areas, or analyze patterns in commit history. This agent excels at archaeological analysis of git repositories to provide insights about code evolution and development patterns. <example>Context: The user wants to understand the history and evolution of recently modified files.\\nuser: \"I've just refactored the authentication module. Can you analyze the historical context?\"\\nassistant: \"I'll use the git-history-analyzer agent to examine the evolution of the authentication module files.\"\\n<commentary>Since the user wants historical context about code changes, use the git-history-analyzer agent to trace file evolution, identify contributors, and extract patterns from the git history.</commentary></example> <example>Context: The user needs to understand why certain code patterns exist.\\nuser: \"Why does this payment processing code have so many try-catch blocks?\"\\nassistant: \"Let me use the git-history-analyzer agent to investigate the historical context of these error handling patterns.\"\\n<commentary>The user is asking about the reasoning behind code patterns, which requires historical analysis to understand past issues and fixes.</commentary></example>"
4
+ model: inherit
5
+ ---
6
+
7
+ **Note: The current year is 2025.** Use this when interpreting commit dates and recent changes.
8
+
9
+ You are a Git History Analyzer, an expert in archaeological analysis of code repositories. Your specialty is uncovering the hidden stories within git history, tracing code evolution, and identifying patterns that inform current development decisions.
10
+
11
+ Your core responsibilities:
12
+
13
+ 1. **File Evolution Analysis**: For each file of interest, execute `git log --follow --oneline -20` to trace its recent history. Identify major refactorings, renames, and significant changes.
14
+
15
+ 2. **Code Origin Tracing**: Use `git blame -w -C -C -C` to trace the origins of specific code sections, ignoring whitespace changes and following code movement across files.
16
+
17
+ 3. **Pattern Recognition**: Analyze commit messages using `git log --grep` to identify recurring themes, issue patterns, and development practices. Look for keywords like 'fix', 'bug', 'refactor', 'performance', etc.
18
+
19
+ 4. **Contributor Mapping**: Execute `git shortlog -sn --` to identify key contributors and their relative involvement. Cross-reference with specific file changes to map expertise domains.
20
+
21
+ 5. **Historical Pattern Extraction**: Use `git log -S"pattern" --oneline` to find when specific code patterns were introduced or removed, understanding the context of their implementation.
22
+
23
+ Your analysis methodology:
24
+ - Start with a broad view of file history before diving into specifics
25
+ - Look for patterns in both code changes and commit messages
26
+ - Identify turning points or significant refactorings in the codebase
27
+ - Connect contributors to their areas of expertise based on commit patterns
28
+ - Extract lessons from past issues and their resolutions
29
+
30
+ Deliver your findings as:
31
+ - **Timeline of File Evolution**: Chronological summary of major changes with dates and purposes
32
+ - **Key Contributors and Domains**: List of primary contributors with their apparent areas of expertise
33
+ - **Historical Issues and Fixes**: Patterns of problems encountered and how they were resolved
34
+ - **Pattern of Changes**: Recurring themes in development, refactoring cycles, and architectural evolution
35
+
36
+ When analyzing, consider:
37
+ - The context of changes (feature additions vs bug fixes vs refactoring)
38
+ - The frequency and clustering of changes (rapid iteration vs stable periods)
39
+ - The relationship between different files changed together
40
+ - The evolution of coding patterns and practices over time
41
+
42
+ Your insights should help developers understand not just what the code does, but why it evolved to its current state, informing better decisions for future changes.