compound-engineering-pi 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +124 -0
- package/bin/compound-engineering-pi +12 -0
- package/bin/compound-plugin +12 -0
- package/compound-engineering-pi +12 -0
- package/compound-plugin +5 -0
- package/docs/pi.md +152 -0
- package/extensions/compound-engineering-compat.ts +452 -0
- package/package.json +84 -0
- package/pi-resources/compound-engineering/mcporter.json +7 -0
- package/plugins/coding-tutor/.claude-plugin/plugin.json +9 -0
- package/plugins/coding-tutor/README.md +37 -0
- package/plugins/coding-tutor/commands/quiz-me.md +1 -0
- package/plugins/coding-tutor/commands/sync-tutorials.md +25 -0
- package/plugins/coding-tutor/commands/teach-me.md +1 -0
- package/plugins/coding-tutor/skills/coding-tutor/SKILL.md +214 -0
- package/plugins/coding-tutor/skills/coding-tutor/scripts/create_tutorial.py +207 -0
- package/plugins/coding-tutor/skills/coding-tutor/scripts/index_tutorials.py +193 -0
- package/plugins/coding-tutor/skills/coding-tutor/scripts/quiz_priority.py +190 -0
- package/plugins/coding-tutor/skills/coding-tutor/scripts/setup_tutorials.py +118 -0
- package/plugins/compound-engineering/.claude-plugin/plugin.json +33 -0
- package/plugins/compound-engineering/CHANGELOG.md +457 -0
- package/plugins/compound-engineering/CLAUDE.md +89 -0
- package/plugins/compound-engineering/LICENSE +21 -0
- package/plugins/compound-engineering/README.md +232 -0
- package/plugins/compound-engineering/agents/design/design-implementation-reviewer.md +109 -0
- package/plugins/compound-engineering/agents/design/design-iterator.md +224 -0
- package/plugins/compound-engineering/agents/design/figma-design-sync.md +190 -0
- package/plugins/compound-engineering/agents/docs/ankane-readme-writer.md +65 -0
- package/plugins/compound-engineering/agents/research/best-practices-researcher.md +126 -0
- package/plugins/compound-engineering/agents/research/framework-docs-researcher.md +106 -0
- package/plugins/compound-engineering/agents/research/git-history-analyzer.md +59 -0
- package/plugins/compound-engineering/agents/research/learnings-researcher.md +264 -0
- package/plugins/compound-engineering/agents/research/repo-research-analyst.md +135 -0
- package/plugins/compound-engineering/agents/review/agent-native-reviewer.md +261 -0
- package/plugins/compound-engineering/agents/review/architecture-strategist.md +67 -0
- package/plugins/compound-engineering/agents/review/code-simplicity-reviewer.md +101 -0
- package/plugins/compound-engineering/agents/review/data-integrity-guardian.md +85 -0
- package/plugins/compound-engineering/agents/review/data-migration-expert.md +112 -0
- package/plugins/compound-engineering/agents/review/deployment-verification-agent.md +174 -0
- package/plugins/compound-engineering/agents/review/dhh-rails-reviewer.md +66 -0
- package/plugins/compound-engineering/agents/review/julik-frontend-races-reviewer.md +221 -0
- package/plugins/compound-engineering/agents/review/kieran-python-reviewer.md +133 -0
- package/plugins/compound-engineering/agents/review/kieran-rails-reviewer.md +115 -0
- package/plugins/compound-engineering/agents/review/kieran-typescript-reviewer.md +124 -0
- package/plugins/compound-engineering/agents/review/pattern-recognition-specialist.md +72 -0
- package/plugins/compound-engineering/agents/review/performance-oracle.md +137 -0
- package/plugins/compound-engineering/agents/review/schema-drift-detector.md +154 -0
- package/plugins/compound-engineering/agents/review/security-sentinel.md +114 -0
- package/plugins/compound-engineering/agents/workflow/bug-reproduction-validator.md +82 -0
- package/plugins/compound-engineering/agents/workflow/every-style-editor.md +64 -0
- package/plugins/compound-engineering/agents/workflow/lint.md +16 -0
- package/plugins/compound-engineering/agents/workflow/pr-comment-resolver.md +84 -0
- package/plugins/compound-engineering/agents/workflow/spec-flow-analyzer.md +134 -0
- package/plugins/compound-engineering/commands/agent-native-audit.md +278 -0
- package/plugins/compound-engineering/commands/changelog.md +138 -0
- package/plugins/compound-engineering/commands/create-agent-skill.md +9 -0
- package/plugins/compound-engineering/commands/deepen-plan.md +546 -0
- package/plugins/compound-engineering/commands/deploy-docs.md +113 -0
- package/plugins/compound-engineering/commands/feature-video.md +342 -0
- package/plugins/compound-engineering/commands/generate_command.md +163 -0
- package/plugins/compound-engineering/commands/heal-skill.md +143 -0
- package/plugins/compound-engineering/commands/lfg.md +20 -0
- package/plugins/compound-engineering/commands/release-docs.md +212 -0
- package/plugins/compound-engineering/commands/report-bug.md +151 -0
- package/plugins/compound-engineering/commands/reproduce-bug.md +100 -0
- package/plugins/compound-engineering/commands/resolve_parallel.md +35 -0
- package/plugins/compound-engineering/commands/resolve_todo_parallel.md +37 -0
- package/plugins/compound-engineering/commands/slfg.md +32 -0
- package/plugins/compound-engineering/commands/technical_review.md +8 -0
- package/plugins/compound-engineering/commands/test-browser.md +339 -0
- package/plugins/compound-engineering/commands/test-xcode.md +332 -0
- package/plugins/compound-engineering/commands/triage.md +311 -0
- package/plugins/compound-engineering/commands/workflows/brainstorm.md +124 -0
- package/plugins/compound-engineering/commands/workflows/compound.md +239 -0
- package/plugins/compound-engineering/commands/workflows/plan.md +551 -0
- package/plugins/compound-engineering/commands/workflows/review.md +526 -0
- package/plugins/compound-engineering/commands/workflows/work.md +433 -0
- package/plugins/compound-engineering/skills/agent-browser/SKILL.md +223 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/SKILL.md +435 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/action-parity-discipline.md +409 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/agent-execution-patterns.md +467 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/agent-native-testing.md +582 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/architecture-patterns.md +478 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/dynamic-context-injection.md +338 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/files-universal-interface.md +301 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +359 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/mcp-tool-design.md +506 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/mobile-patterns.md +871 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/product-implications.md +443 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +317 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/self-modification.md +269 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/shared-workspace-architecture.md +680 -0
- package/plugins/compound-engineering/skills/agent-native-architecture/references/system-prompt-design.md +250 -0
- package/plugins/compound-engineering/skills/andrew-kane-gem-writer/SKILL.md +184 -0
- package/plugins/compound-engineering/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
- package/plugins/compound-engineering/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
- package/plugins/compound-engineering/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
- package/plugins/compound-engineering/skills/andrew-kane-gem-writer/references/resources.md +119 -0
- package/plugins/compound-engineering/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
- package/plugins/compound-engineering/skills/brainstorming/SKILL.md +190 -0
- package/plugins/compound-engineering/skills/compound-docs/SKILL.md +511 -0
- package/plugins/compound-engineering/skills/compound-docs/assets/critical-pattern-template.md +34 -0
- package/plugins/compound-engineering/skills/compound-docs/assets/resolution-template.md +93 -0
- package/plugins/compound-engineering/skills/compound-docs/references/yaml-schema.md +65 -0
- package/plugins/compound-engineering/skills/compound-docs/schema.yaml +176 -0
- package/plugins/compound-engineering/skills/create-agent-skills/SKILL.md +275 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/api-security.md +226 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/be-clear-and-direct.md +531 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/best-practices.md +404 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/common-patterns.md +595 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/core-principles.md +437 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/executable-code.md +175 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/iteration-and-testing.md +474 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/official-spec.md +134 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/recommended-structure.md +168 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/skill-structure.md +152 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/using-scripts.md +113 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/using-templates.md +112 -0
- package/plugins/compound-engineering/skills/create-agent-skills/references/workflows-and-validation.md +510 -0
- package/plugins/compound-engineering/skills/create-agent-skills/templates/router-skill.md +73 -0
- package/plugins/compound-engineering/skills/create-agent-skills/templates/simple-skill.md +33 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/add-reference.md +96 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/add-script.md +93 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/add-template.md +74 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/add-workflow.md +120 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/audit-skill.md +138 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/create-domain-expertise-skill.md +605 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/create-new-skill.md +191 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/get-guidance.md +121 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/upgrade-to-router.md +161 -0
- package/plugins/compound-engineering/skills/create-agent-skills/workflows/verify-skill.md +204 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/SKILL.md +185 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/references/architecture.md +653 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/references/controllers.md +303 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/references/frontend.md +510 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/references/gems.md +266 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/references/models.md +359 -0
- package/plugins/compound-engineering/skills/dhh-rails-style/references/testing.md +338 -0
- package/plugins/compound-engineering/skills/document-review/SKILL.md +87 -0
- package/plugins/compound-engineering/skills/dspy-ruby/SKILL.md +737 -0
- package/plugins/compound-engineering/skills/dspy-ruby/assets/config-template.rb +187 -0
- package/plugins/compound-engineering/skills/dspy-ruby/assets/module-template.rb +300 -0
- package/plugins/compound-engineering/skills/dspy-ruby/assets/signature-template.rb +221 -0
- package/plugins/compound-engineering/skills/dspy-ruby/references/core-concepts.md +674 -0
- package/plugins/compound-engineering/skills/dspy-ruby/references/observability.md +366 -0
- package/plugins/compound-engineering/skills/dspy-ruby/references/optimization.md +603 -0
- package/plugins/compound-engineering/skills/dspy-ruby/references/providers.md +418 -0
- package/plugins/compound-engineering/skills/dspy-ruby/references/toolsets.md +502 -0
- package/plugins/compound-engineering/skills/every-style-editor/SKILL.md +134 -0
- package/plugins/compound-engineering/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
- package/plugins/compound-engineering/skills/file-todos/SKILL.md +252 -0
- package/plugins/compound-engineering/skills/file-todos/assets/todo-template.md +155 -0
- package/plugins/compound-engineering/skills/frontend-design/SKILL.md +42 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/SKILL.md +237 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/requirements.txt +2 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/scripts/compose_images.py +157 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/scripts/edit_image.py +144 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/scripts/gemini_images.py +263 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/scripts/generate_image.py +133 -0
- package/plugins/compound-engineering/skills/gemini-imagegen/scripts/multi_turn_chat.py +216 -0
- package/plugins/compound-engineering/skills/git-worktree/SKILL.md +302 -0
- package/plugins/compound-engineering/skills/git-worktree/scripts/worktree-manager.sh +337 -0
- package/plugins/compound-engineering/skills/orchestrating-swarms/SKILL.md +1718 -0
- package/plugins/compound-engineering/skills/rclone/SKILL.md +150 -0
- package/plugins/compound-engineering/skills/rclone/scripts/check_setup.sh +60 -0
- package/plugins/compound-engineering/skills/resolve-pr-parallel/SKILL.md +89 -0
- package/plugins/compound-engineering/skills/resolve-pr-parallel/scripts/get-pr-comments +68 -0
- package/plugins/compound-engineering/skills/resolve-pr-parallel/scripts/resolve-pr-thread +23 -0
- package/plugins/compound-engineering/skills/skill-creator/SKILL.md +210 -0
- package/plugins/compound-engineering/skills/skill-creator/scripts/init_skill.py +303 -0
- package/plugins/compound-engineering/skills/skill-creator/scripts/package_skill.py +110 -0
- package/plugins/compound-engineering/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/prompts/deepen-plan.md +549 -0
- package/prompts/feature-video.md +341 -0
- package/prompts/resolve_todo_parallel.md +36 -0
- package/prompts/test-browser.md +342 -0
- package/prompts/workflows-brainstorm.md +123 -0
- package/prompts/workflows-compound.md +238 -0
- package/prompts/workflows-plan.md +550 -0
- package/prompts/workflows-review.md +529 -0
- package/prompts/workflows-work.md +432 -0
- package/skills/agent-browser/SKILL.md +223 -0
- package/skills/agent-native-architecture/SKILL.md +435 -0
- package/skills/agent-native-architecture/references/action-parity-discipline.md +409 -0
- package/skills/agent-native-architecture/references/agent-execution-patterns.md +467 -0
- package/skills/agent-native-architecture/references/agent-native-testing.md +582 -0
- package/skills/agent-native-architecture/references/architecture-patterns.md +478 -0
- package/skills/agent-native-architecture/references/dynamic-context-injection.md +338 -0
- package/skills/agent-native-architecture/references/files-universal-interface.md +301 -0
- package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +359 -0
- package/skills/agent-native-architecture/references/mcp-tool-design.md +506 -0
- package/skills/agent-native-architecture/references/mobile-patterns.md +871 -0
- package/skills/agent-native-architecture/references/product-implications.md +443 -0
- package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +317 -0
- package/skills/agent-native-architecture/references/self-modification.md +269 -0
- package/skills/agent-native-architecture/references/shared-workspace-architecture.md +680 -0
- package/skills/agent-native-architecture/references/system-prompt-design.md +250 -0
- package/skills/agent-native-reviewer/SKILL.md +260 -0
- package/skills/andrew-kane-gem-writer/SKILL.md +184 -0
- package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
- package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
- package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
- package/skills/andrew-kane-gem-writer/references/resources.md +119 -0
- package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
- package/skills/ankane-readme-writer/SKILL.md +63 -0
- package/skills/architecture-strategist/SKILL.md +66 -0
- package/skills/best-practices-researcher/SKILL.md +125 -0
- package/skills/brainstorming/SKILL.md +190 -0
- package/skills/bug-reproduction-validator/SKILL.md +81 -0
- package/skills/code-simplicity-reviewer/SKILL.md +100 -0
- package/skills/compound-docs/SKILL.md +511 -0
- package/skills/compound-docs/assets/critical-pattern-template.md +34 -0
- package/skills/compound-docs/assets/resolution-template.md +93 -0
- package/skills/compound-docs/references/yaml-schema.md +65 -0
- package/skills/compound-docs/schema.yaml +176 -0
- package/skills/create-agent-skills/SKILL.md +275 -0
- package/skills/create-agent-skills/references/api-security.md +226 -0
- package/skills/create-agent-skills/references/be-clear-and-direct.md +531 -0
- package/skills/create-agent-skills/references/best-practices.md +404 -0
- package/skills/create-agent-skills/references/common-patterns.md +595 -0
- package/skills/create-agent-skills/references/core-principles.md +437 -0
- package/skills/create-agent-skills/references/executable-code.md +175 -0
- package/skills/create-agent-skills/references/iteration-and-testing.md +474 -0
- package/skills/create-agent-skills/references/official-spec.md +134 -0
- package/skills/create-agent-skills/references/recommended-structure.md +168 -0
- package/skills/create-agent-skills/references/skill-structure.md +152 -0
- package/skills/create-agent-skills/references/using-scripts.md +113 -0
- package/skills/create-agent-skills/references/using-templates.md +112 -0
- package/skills/create-agent-skills/references/workflows-and-validation.md +510 -0
- package/skills/create-agent-skills/templates/router-skill.md +73 -0
- package/skills/create-agent-skills/templates/simple-skill.md +33 -0
- package/skills/create-agent-skills/workflows/add-reference.md +96 -0
- package/skills/create-agent-skills/workflows/add-script.md +93 -0
- package/skills/create-agent-skills/workflows/add-template.md +74 -0
- package/skills/create-agent-skills/workflows/add-workflow.md +120 -0
- package/skills/create-agent-skills/workflows/audit-skill.md +138 -0
- package/skills/create-agent-skills/workflows/create-domain-expertise-skill.md +605 -0
- package/skills/create-agent-skills/workflows/create-new-skill.md +191 -0
- package/skills/create-agent-skills/workflows/get-guidance.md +121 -0
- package/skills/create-agent-skills/workflows/upgrade-to-router.md +161 -0
- package/skills/create-agent-skills/workflows/verify-skill.md +204 -0
- package/skills/data-integrity-guardian/SKILL.md +84 -0
- package/skills/data-migration-expert/SKILL.md +111 -0
- package/skills/deployment-verification-agent/SKILL.md +173 -0
- package/skills/design-implementation-reviewer/SKILL.md +107 -0
- package/skills/design-iterator/SKILL.md +222 -0
- package/skills/dhh-rails-reviewer/SKILL.md +65 -0
- package/skills/dhh-rails-style/SKILL.md +185 -0
- package/skills/dhh-rails-style/references/architecture.md +653 -0
- package/skills/dhh-rails-style/references/controllers.md +303 -0
- package/skills/dhh-rails-style/references/frontend.md +510 -0
- package/skills/dhh-rails-style/references/gems.md +266 -0
- package/skills/dhh-rails-style/references/models.md +359 -0
- package/skills/dhh-rails-style/references/testing.md +338 -0
- package/skills/document-review/SKILL.md +87 -0
- package/skills/dspy-ruby/SKILL.md +737 -0
- package/skills/dspy-ruby/assets/config-template.rb +187 -0
- package/skills/dspy-ruby/assets/module-template.rb +300 -0
- package/skills/dspy-ruby/assets/signature-template.rb +221 -0
- package/skills/dspy-ruby/references/core-concepts.md +674 -0
- package/skills/dspy-ruby/references/observability.md +366 -0
- package/skills/dspy-ruby/references/optimization.md +603 -0
- package/skills/dspy-ruby/references/providers.md +418 -0
- package/skills/dspy-ruby/references/toolsets.md +502 -0
- package/skills/every-style-editor/SKILL.md +134 -0
- package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
- package/skills/every-style-editor-2/SKILL.md +62 -0
- package/skills/figma-design-sync/SKILL.md +188 -0
- package/skills/file-todos/SKILL.md +252 -0
- package/skills/file-todos/assets/todo-template.md +155 -0
- package/skills/framework-docs-researcher/SKILL.md +105 -0
- package/skills/frontend-design/SKILL.md +42 -0
- package/skills/gemini-imagegen/SKILL.md +237 -0
- package/skills/gemini-imagegen/requirements.txt +2 -0
- package/skills/gemini-imagegen/scripts/compose_images.py +157 -0
- package/skills/gemini-imagegen/scripts/edit_image.py +144 -0
- package/skills/gemini-imagegen/scripts/gemini_images.py +263 -0
- package/skills/gemini-imagegen/scripts/generate_image.py +133 -0
- package/skills/gemini-imagegen/scripts/multi_turn_chat.py +216 -0
- package/skills/git-history-analyzer/SKILL.md +58 -0
- package/skills/git-worktree/SKILL.md +302 -0
- package/skills/git-worktree/scripts/worktree-manager.sh +337 -0
- package/skills/julik-frontend-races-reviewer/SKILL.md +220 -0
- package/skills/kieran-python-reviewer/SKILL.md +132 -0
- package/skills/kieran-rails-reviewer/SKILL.md +114 -0
- package/skills/kieran-typescript-reviewer/SKILL.md +123 -0
- package/skills/learnings-researcher/SKILL.md +263 -0
- package/skills/lint/SKILL.md +14 -0
- package/skills/orchestrating-swarms/SKILL.md +1718 -0
- package/skills/pattern-recognition-specialist/SKILL.md +71 -0
- package/skills/performance-oracle/SKILL.md +136 -0
- package/skills/pr-comment-resolver/SKILL.md +82 -0
- package/skills/rclone/SKILL.md +150 -0
- package/skills/rclone/scripts/check_setup.sh +60 -0
- package/skills/repo-research-analyst/SKILL.md +134 -0
- package/skills/resolve_pr_parallel/SKILL.md +89 -0
- package/skills/resolve_pr_parallel/scripts/get-pr-comments +68 -0
- package/skills/resolve_pr_parallel/scripts/resolve-pr-thread +23 -0
- package/skills/schema-drift-detector/SKILL.md +153 -0
- package/skills/security-sentinel/SKILL.md +113 -0
- package/skills/skill-creator/SKILL.md +210 -0
- package/skills/skill-creator/scripts/init_skill.py +303 -0
- package/skills/skill-creator/scripts/package_skill.py +110 -0
- package/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/skills/spec-flow-analyzer/SKILL.md +133 -0
- package/src/commands/convert.ts +183 -0
- package/src/commands/install.ts +273 -0
- package/src/commands/list.ts +37 -0
- package/src/commands/sync.ts +89 -0
- package/src/converters/claude-to-codex.ts +182 -0
- package/src/converters/claude-to-opencode.ts +395 -0
- package/src/converters/claude-to-pi.ts +205 -0
- package/src/index.ts +22 -0
- package/src/parsers/claude-home.ts +65 -0
- package/src/parsers/claude.ts +252 -0
- package/src/sync/codex.ts +92 -0
- package/src/sync/opencode.ts +75 -0
- package/src/sync/pi.ts +88 -0
- package/src/targets/codex.ts +96 -0
- package/src/targets/index.ts +38 -0
- package/src/targets/opencode.ts +57 -0
- package/src/targets/pi.ts +131 -0
- package/src/templates/pi/compat-extension.ts +452 -0
- package/src/types/claude.ts +90 -0
- package/src/types/codex.ts +23 -0
- package/src/types/opencode.ts +54 -0
- package/src/types/pi.ts +40 -0
- package/src/utils/codex-agents.ts +64 -0
- package/src/utils/files.ts +77 -0
- package/src/utils/frontmatter.ts +65 -0
- package/src/utils/symlink.ts +43 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Compose multiple images into a new image using Gemini API.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python compose_images.py "instruction" output.png image1.png [image2.png ...]
|
|
7
|
+
|
|
8
|
+
Examples:
|
|
9
|
+
python compose_images.py "Create a group photo of these people" group.png person1.png person2.png
|
|
10
|
+
python compose_images.py "Put the cat from the first image on the couch from the second" result.png cat.png couch.png
|
|
11
|
+
python compose_images.py "Apply the art style from the first image to the scene in the second" styled.png style.png photo.png
|
|
12
|
+
|
|
13
|
+
Note: Supports up to 14 reference images (Gemini 3 Pro only).
|
|
14
|
+
|
|
15
|
+
Environment:
|
|
16
|
+
GEMINI_API_KEY - Required API key
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import os
|
|
21
|
+
import sys
|
|
22
|
+
|
|
23
|
+
from PIL import Image
|
|
24
|
+
from google import genai
|
|
25
|
+
from google.genai import types
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def compose_images(
|
|
29
|
+
instruction: str,
|
|
30
|
+
output_path: str,
|
|
31
|
+
image_paths: list[str],
|
|
32
|
+
model: str = "gemini-3-pro-image-preview",
|
|
33
|
+
aspect_ratio: str | None = None,
|
|
34
|
+
image_size: str | None = None,
|
|
35
|
+
) -> str | None:
|
|
36
|
+
"""Compose multiple images based on instructions.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
instruction: Text description of how to combine images
|
|
40
|
+
output_path: Path to save the result
|
|
41
|
+
image_paths: List of input image paths (up to 14)
|
|
42
|
+
model: Gemini model to use (pro recommended)
|
|
43
|
+
aspect_ratio: Output aspect ratio
|
|
44
|
+
image_size: Output resolution
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Any text response from the model, or None
|
|
48
|
+
"""
|
|
49
|
+
api_key = os.environ.get("GEMINI_API_KEY")
|
|
50
|
+
if not api_key:
|
|
51
|
+
raise EnvironmentError("GEMINI_API_KEY environment variable not set")
|
|
52
|
+
|
|
53
|
+
if len(image_paths) > 14:
|
|
54
|
+
raise ValueError("Maximum 14 reference images supported")
|
|
55
|
+
|
|
56
|
+
if len(image_paths) < 1:
|
|
57
|
+
raise ValueError("At least one image is required")
|
|
58
|
+
|
|
59
|
+
# Verify all images exist
|
|
60
|
+
for path in image_paths:
|
|
61
|
+
if not os.path.exists(path):
|
|
62
|
+
raise FileNotFoundError(f"Image not found: {path}")
|
|
63
|
+
|
|
64
|
+
client = genai.Client(api_key=api_key)
|
|
65
|
+
|
|
66
|
+
# Load images
|
|
67
|
+
images = [Image.open(path) for path in image_paths]
|
|
68
|
+
|
|
69
|
+
# Build contents: instruction first, then images
|
|
70
|
+
contents = [instruction] + images
|
|
71
|
+
|
|
72
|
+
# Build config
|
|
73
|
+
config_kwargs = {"response_modalities": ["TEXT", "IMAGE"]}
|
|
74
|
+
|
|
75
|
+
image_config_kwargs = {}
|
|
76
|
+
if aspect_ratio:
|
|
77
|
+
image_config_kwargs["aspect_ratio"] = aspect_ratio
|
|
78
|
+
if image_size:
|
|
79
|
+
image_config_kwargs["image_size"] = image_size
|
|
80
|
+
|
|
81
|
+
if image_config_kwargs:
|
|
82
|
+
config_kwargs["image_config"] = types.ImageConfig(**image_config_kwargs)
|
|
83
|
+
|
|
84
|
+
config = types.GenerateContentConfig(**config_kwargs)
|
|
85
|
+
|
|
86
|
+
response = client.models.generate_content(
|
|
87
|
+
model=model,
|
|
88
|
+
contents=contents,
|
|
89
|
+
config=config,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
text_response = None
|
|
93
|
+
image_saved = False
|
|
94
|
+
|
|
95
|
+
for part in response.parts:
|
|
96
|
+
if part.text is not None:
|
|
97
|
+
text_response = part.text
|
|
98
|
+
elif part.inline_data is not None:
|
|
99
|
+
image = part.as_image()
|
|
100
|
+
image.save(output_path)
|
|
101
|
+
image_saved = True
|
|
102
|
+
|
|
103
|
+
if not image_saved:
|
|
104
|
+
raise RuntimeError("No image was generated.")
|
|
105
|
+
|
|
106
|
+
return text_response
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def main():
|
|
110
|
+
parser = argparse.ArgumentParser(
|
|
111
|
+
description="Compose multiple images using Gemini API",
|
|
112
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
113
|
+
epilog=__doc__
|
|
114
|
+
)
|
|
115
|
+
parser.add_argument("instruction", help="Composition instruction")
|
|
116
|
+
parser.add_argument("output", help="Output file path")
|
|
117
|
+
parser.add_argument("images", nargs="+", help="Input images (up to 14)")
|
|
118
|
+
parser.add_argument(
|
|
119
|
+
"--model", "-m",
|
|
120
|
+
default="gemini-3-pro-image-preview",
|
|
121
|
+
choices=["gemini-2.5-flash-image", "gemini-3-pro-image-preview"],
|
|
122
|
+
help="Model to use (pro recommended for composition)"
|
|
123
|
+
)
|
|
124
|
+
parser.add_argument(
|
|
125
|
+
"--aspect", "-a",
|
|
126
|
+
choices=["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"],
|
|
127
|
+
help="Output aspect ratio"
|
|
128
|
+
)
|
|
129
|
+
parser.add_argument(
|
|
130
|
+
"--size", "-s",
|
|
131
|
+
choices=["1K", "2K", "4K"],
|
|
132
|
+
help="Output resolution"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
args = parser.parse_args()
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
text = compose_images(
|
|
139
|
+
instruction=args.instruction,
|
|
140
|
+
output_path=args.output,
|
|
141
|
+
image_paths=args.images,
|
|
142
|
+
model=args.model,
|
|
143
|
+
aspect_ratio=args.aspect,
|
|
144
|
+
image_size=args.size,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
print(f"Composed image saved to: {args.output}")
|
|
148
|
+
if text:
|
|
149
|
+
print(f"Model response: {text}")
|
|
150
|
+
|
|
151
|
+
except Exception as e:
|
|
152
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
153
|
+
sys.exit(1)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
if __name__ == "__main__":
|
|
157
|
+
main()
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Edit existing images using Gemini API.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python edit_image.py input.png "edit instruction" output.png [options]
|
|
7
|
+
|
|
8
|
+
Examples:
|
|
9
|
+
python edit_image.py photo.png "Add a rainbow in the sky" edited.png
|
|
10
|
+
python edit_image.py room.jpg "Change the sofa to red leather" room_edited.jpg
|
|
11
|
+
python edit_image.py portrait.png "Make it look like a Van Gogh painting" artistic.png --model gemini-3-pro-image-preview
|
|
12
|
+
|
|
13
|
+
Environment:
|
|
14
|
+
GEMINI_API_KEY - Required API key
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import argparse
|
|
18
|
+
import os
|
|
19
|
+
import sys
|
|
20
|
+
|
|
21
|
+
from PIL import Image
|
|
22
|
+
from google import genai
|
|
23
|
+
from google.genai import types
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def edit_image(
|
|
27
|
+
input_path: str,
|
|
28
|
+
instruction: str,
|
|
29
|
+
output_path: str,
|
|
30
|
+
model: str = "gemini-2.5-flash-image",
|
|
31
|
+
aspect_ratio: str | None = None,
|
|
32
|
+
image_size: str | None = None,
|
|
33
|
+
) -> str | None:
|
|
34
|
+
"""Edit an existing image based on text instructions.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
input_path: Path to the input image
|
|
38
|
+
instruction: Text description of edits to make
|
|
39
|
+
output_path: Path to save the edited image
|
|
40
|
+
model: Gemini model to use
|
|
41
|
+
aspect_ratio: Output aspect ratio
|
|
42
|
+
image_size: Output resolution
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Any text response from the model, or None
|
|
46
|
+
"""
|
|
47
|
+
api_key = os.environ.get("GEMINI_API_KEY")
|
|
48
|
+
if not api_key:
|
|
49
|
+
raise EnvironmentError("GEMINI_API_KEY environment variable not set")
|
|
50
|
+
|
|
51
|
+
if not os.path.exists(input_path):
|
|
52
|
+
raise FileNotFoundError(f"Input image not found: {input_path}")
|
|
53
|
+
|
|
54
|
+
client = genai.Client(api_key=api_key)
|
|
55
|
+
|
|
56
|
+
# Load input image
|
|
57
|
+
input_image = Image.open(input_path)
|
|
58
|
+
|
|
59
|
+
# Build config
|
|
60
|
+
config_kwargs = {"response_modalities": ["TEXT", "IMAGE"]}
|
|
61
|
+
|
|
62
|
+
image_config_kwargs = {}
|
|
63
|
+
if aspect_ratio:
|
|
64
|
+
image_config_kwargs["aspect_ratio"] = aspect_ratio
|
|
65
|
+
if image_size:
|
|
66
|
+
image_config_kwargs["image_size"] = image_size
|
|
67
|
+
|
|
68
|
+
if image_config_kwargs:
|
|
69
|
+
config_kwargs["image_config"] = types.ImageConfig(**image_config_kwargs)
|
|
70
|
+
|
|
71
|
+
config = types.GenerateContentConfig(**config_kwargs)
|
|
72
|
+
|
|
73
|
+
response = client.models.generate_content(
|
|
74
|
+
model=model,
|
|
75
|
+
contents=[instruction, input_image],
|
|
76
|
+
config=config,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
text_response = None
|
|
80
|
+
image_saved = False
|
|
81
|
+
|
|
82
|
+
for part in response.parts:
|
|
83
|
+
if part.text is not None:
|
|
84
|
+
text_response = part.text
|
|
85
|
+
elif part.inline_data is not None:
|
|
86
|
+
image = part.as_image()
|
|
87
|
+
image.save(output_path)
|
|
88
|
+
image_saved = True
|
|
89
|
+
|
|
90
|
+
if not image_saved:
|
|
91
|
+
raise RuntimeError("No image was generated. Check your instruction and try again.")
|
|
92
|
+
|
|
93
|
+
return text_response
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def main():
|
|
97
|
+
parser = argparse.ArgumentParser(
|
|
98
|
+
description="Edit images using Gemini API",
|
|
99
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
100
|
+
epilog=__doc__
|
|
101
|
+
)
|
|
102
|
+
parser.add_argument("input", help="Input image path")
|
|
103
|
+
parser.add_argument("instruction", help="Edit instruction")
|
|
104
|
+
parser.add_argument("output", help="Output file path")
|
|
105
|
+
parser.add_argument(
|
|
106
|
+
"--model", "-m",
|
|
107
|
+
default="gemini-2.5-flash-image",
|
|
108
|
+
choices=["gemini-2.5-flash-image", "gemini-3-pro-image-preview"],
|
|
109
|
+
help="Model to use (default: gemini-2.5-flash-image)"
|
|
110
|
+
)
|
|
111
|
+
parser.add_argument(
|
|
112
|
+
"--aspect", "-a",
|
|
113
|
+
choices=["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"],
|
|
114
|
+
help="Output aspect ratio"
|
|
115
|
+
)
|
|
116
|
+
parser.add_argument(
|
|
117
|
+
"--size", "-s",
|
|
118
|
+
choices=["1K", "2K", "4K"],
|
|
119
|
+
help="Output resolution"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
args = parser.parse_args()
|
|
123
|
+
|
|
124
|
+
try:
|
|
125
|
+
text = edit_image(
|
|
126
|
+
input_path=args.input,
|
|
127
|
+
instruction=args.instruction,
|
|
128
|
+
output_path=args.output,
|
|
129
|
+
model=args.model,
|
|
130
|
+
aspect_ratio=args.aspect,
|
|
131
|
+
image_size=args.size,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
print(f"Edited image saved to: {args.output}")
|
|
135
|
+
if text:
|
|
136
|
+
print(f"Model response: {text}")
|
|
137
|
+
|
|
138
|
+
except Exception as e:
|
|
139
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
140
|
+
sys.exit(1)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if __name__ == "__main__":
|
|
144
|
+
main()
|
|
@@ -0,0 +1,263 @@
|
|
|
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["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"]
|
|
27
|
+
ImageSize = Literal["1K", "2K", "4K"]
|
|
28
|
+
Model = Literal["gemini-2.5-flash-image", "gemini-3-pro-image-preview"]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class GeminiImageGenerator:
|
|
32
|
+
"""High-level interface for Gemini image generation."""
|
|
33
|
+
|
|
34
|
+
FLASH = "gemini-2.5-flash-image"
|
|
35
|
+
PRO = "gemini-3-pro-image-preview"
|
|
36
|
+
|
|
37
|
+
def __init__(self, api_key: str | None = None, model: Model = FLASH):
|
|
38
|
+
"""Initialize the generator.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
api_key: Gemini API key (defaults to GEMINI_API_KEY env var)
|
|
42
|
+
model: Default model to use
|
|
43
|
+
"""
|
|
44
|
+
self.api_key = api_key or os.environ.get("GEMINI_API_KEY")
|
|
45
|
+
if not self.api_key:
|
|
46
|
+
raise EnvironmentError("GEMINI_API_KEY not set")
|
|
47
|
+
|
|
48
|
+
self.client = genai.Client(api_key=self.api_key)
|
|
49
|
+
self.model = model
|
|
50
|
+
|
|
51
|
+
def _build_config(
|
|
52
|
+
self,
|
|
53
|
+
aspect_ratio: AspectRatio | None = None,
|
|
54
|
+
image_size: ImageSize | None = None,
|
|
55
|
+
google_search: bool = False,
|
|
56
|
+
) -> types.GenerateContentConfig:
|
|
57
|
+
"""Build generation config."""
|
|
58
|
+
kwargs = {"response_modalities": ["TEXT", "IMAGE"]}
|
|
59
|
+
|
|
60
|
+
img_config = {}
|
|
61
|
+
if aspect_ratio:
|
|
62
|
+
img_config["aspect_ratio"] = aspect_ratio
|
|
63
|
+
if image_size:
|
|
64
|
+
img_config["image_size"] = image_size
|
|
65
|
+
|
|
66
|
+
if img_config:
|
|
67
|
+
kwargs["image_config"] = types.ImageConfig(**img_config)
|
|
68
|
+
|
|
69
|
+
if google_search:
|
|
70
|
+
kwargs["tools"] = [{"google_search": {}}]
|
|
71
|
+
|
|
72
|
+
return types.GenerateContentConfig(**kwargs)
|
|
73
|
+
|
|
74
|
+
def generate(
|
|
75
|
+
self,
|
|
76
|
+
prompt: str,
|
|
77
|
+
output: str | Path,
|
|
78
|
+
*,
|
|
79
|
+
model: Model | None = None,
|
|
80
|
+
aspect_ratio: AspectRatio | None = None,
|
|
81
|
+
image_size: ImageSize | None = None,
|
|
82
|
+
google_search: bool = False,
|
|
83
|
+
) -> tuple[Path, str | None]:
|
|
84
|
+
"""Generate an image from a text prompt.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
prompt: Text description
|
|
88
|
+
output: Output file path
|
|
89
|
+
model: Override default model
|
|
90
|
+
aspect_ratio: Output aspect ratio
|
|
91
|
+
image_size: Output resolution
|
|
92
|
+
google_search: Enable Google Search grounding (Pro only)
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Tuple of (output path, optional text response)
|
|
96
|
+
"""
|
|
97
|
+
output = Path(output)
|
|
98
|
+
config = self._build_config(aspect_ratio, image_size, google_search)
|
|
99
|
+
|
|
100
|
+
response = self.client.models.generate_content(
|
|
101
|
+
model=model or self.model,
|
|
102
|
+
contents=[prompt],
|
|
103
|
+
config=config,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
text = None
|
|
107
|
+
for part in response.parts:
|
|
108
|
+
if part.text:
|
|
109
|
+
text = part.text
|
|
110
|
+
elif part.inline_data:
|
|
111
|
+
part.as_image().save(output)
|
|
112
|
+
|
|
113
|
+
return output, text
|
|
114
|
+
|
|
115
|
+
def edit(
|
|
116
|
+
self,
|
|
117
|
+
input_image: str | Path | Image.Image,
|
|
118
|
+
instruction: str,
|
|
119
|
+
output: str | Path,
|
|
120
|
+
*,
|
|
121
|
+
model: Model | None = None,
|
|
122
|
+
aspect_ratio: AspectRatio | None = None,
|
|
123
|
+
image_size: ImageSize | None = None,
|
|
124
|
+
) -> tuple[Path, str | None]:
|
|
125
|
+
"""Edit an existing image.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
input_image: Input image (path or PIL Image)
|
|
129
|
+
instruction: Edit instruction
|
|
130
|
+
output: Output file path
|
|
131
|
+
model: Override default model
|
|
132
|
+
aspect_ratio: Output aspect ratio
|
|
133
|
+
image_size: Output resolution
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Tuple of (output path, optional text response)
|
|
137
|
+
"""
|
|
138
|
+
output = Path(output)
|
|
139
|
+
|
|
140
|
+
if isinstance(input_image, (str, Path)):
|
|
141
|
+
input_image = Image.open(input_image)
|
|
142
|
+
|
|
143
|
+
config = self._build_config(aspect_ratio, image_size)
|
|
144
|
+
|
|
145
|
+
response = self.client.models.generate_content(
|
|
146
|
+
model=model or self.model,
|
|
147
|
+
contents=[instruction, input_image],
|
|
148
|
+
config=config,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
text = None
|
|
152
|
+
for part in response.parts:
|
|
153
|
+
if part.text:
|
|
154
|
+
text = part.text
|
|
155
|
+
elif part.inline_data:
|
|
156
|
+
part.as_image().save(output)
|
|
157
|
+
|
|
158
|
+
return output, text
|
|
159
|
+
|
|
160
|
+
def compose(
|
|
161
|
+
self,
|
|
162
|
+
instruction: str,
|
|
163
|
+
images: list[str | Path | Image.Image],
|
|
164
|
+
output: str | Path,
|
|
165
|
+
*,
|
|
166
|
+
model: Model | None = None,
|
|
167
|
+
aspect_ratio: AspectRatio | None = None,
|
|
168
|
+
image_size: ImageSize | None = None,
|
|
169
|
+
) -> tuple[Path, str | None]:
|
|
170
|
+
"""Compose multiple images into one.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
instruction: Composition instruction
|
|
174
|
+
images: List of input images (up to 14)
|
|
175
|
+
output: Output file path
|
|
176
|
+
model: Override default model (Pro recommended)
|
|
177
|
+
aspect_ratio: Output aspect ratio
|
|
178
|
+
image_size: Output resolution
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
Tuple of (output path, optional text response)
|
|
182
|
+
"""
|
|
183
|
+
output = Path(output)
|
|
184
|
+
|
|
185
|
+
# Load images
|
|
186
|
+
loaded = []
|
|
187
|
+
for img in images:
|
|
188
|
+
if isinstance(img, (str, Path)):
|
|
189
|
+
loaded.append(Image.open(img))
|
|
190
|
+
else:
|
|
191
|
+
loaded.append(img)
|
|
192
|
+
|
|
193
|
+
config = self._build_config(aspect_ratio, image_size)
|
|
194
|
+
contents = [instruction] + loaded
|
|
195
|
+
|
|
196
|
+
response = self.client.models.generate_content(
|
|
197
|
+
model=model or self.PRO, # Pro recommended for composition
|
|
198
|
+
contents=contents,
|
|
199
|
+
config=config,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
text = None
|
|
203
|
+
for part in response.parts:
|
|
204
|
+
if part.text:
|
|
205
|
+
text = part.text
|
|
206
|
+
elif part.inline_data:
|
|
207
|
+
part.as_image().save(output)
|
|
208
|
+
|
|
209
|
+
return output, text
|
|
210
|
+
|
|
211
|
+
def chat(self) -> "ImageChat":
|
|
212
|
+
"""Start an interactive chat session for iterative refinement."""
|
|
213
|
+
return ImageChat(self.client, self.model)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class ImageChat:
|
|
217
|
+
"""Multi-turn chat session for iterative image generation."""
|
|
218
|
+
|
|
219
|
+
def __init__(self, client: genai.Client, model: Model):
|
|
220
|
+
self.client = client
|
|
221
|
+
self.model = model
|
|
222
|
+
self._chat = client.chats.create(
|
|
223
|
+
model=model,
|
|
224
|
+
config=types.GenerateContentConfig(response_modalities=["TEXT", "IMAGE"]),
|
|
225
|
+
)
|
|
226
|
+
self.current_image: Image.Image | None = None
|
|
227
|
+
|
|
228
|
+
def send(
|
|
229
|
+
self,
|
|
230
|
+
message: str,
|
|
231
|
+
image: Image.Image | str | Path | None = None,
|
|
232
|
+
) -> tuple[Image.Image | None, str | None]:
|
|
233
|
+
"""Send a message and optionally an image.
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
Tuple of (generated image or None, text response or None)
|
|
237
|
+
"""
|
|
238
|
+
contents = [message]
|
|
239
|
+
if image:
|
|
240
|
+
if isinstance(image, (str, Path)):
|
|
241
|
+
image = Image.open(image)
|
|
242
|
+
contents.append(image)
|
|
243
|
+
|
|
244
|
+
response = self._chat.send_message(contents)
|
|
245
|
+
|
|
246
|
+
text = None
|
|
247
|
+
img = None
|
|
248
|
+
for part in response.parts:
|
|
249
|
+
if part.text:
|
|
250
|
+
text = part.text
|
|
251
|
+
elif part.inline_data:
|
|
252
|
+
img = part.as_image()
|
|
253
|
+
self.current_image = img
|
|
254
|
+
|
|
255
|
+
return img, text
|
|
256
|
+
|
|
257
|
+
def reset(self):
|
|
258
|
+
"""Reset the chat session."""
|
|
259
|
+
self._chat = self.client.chats.create(
|
|
260
|
+
model=self.model,
|
|
261
|
+
config=types.GenerateContentConfig(response_modalities=["TEXT", "IMAGE"]),
|
|
262
|
+
)
|
|
263
|
+
self.current_image = None
|
|
@@ -0,0 +1,133 @@
|
|
|
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", "-m",
|
|
97
|
+
default="gemini-2.5-flash-image",
|
|
98
|
+
choices=["gemini-2.5-flash-image", "gemini-3-pro-image-preview"],
|
|
99
|
+
help="Model to use (default: gemini-2.5-flash-image)"
|
|
100
|
+
)
|
|
101
|
+
parser.add_argument(
|
|
102
|
+
"--aspect", "-a",
|
|
103
|
+
choices=["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"],
|
|
104
|
+
help="Aspect ratio"
|
|
105
|
+
)
|
|
106
|
+
parser.add_argument(
|
|
107
|
+
"--size", "-s",
|
|
108
|
+
choices=["1K", "2K", "4K"],
|
|
109
|
+
help="Image resolution (4K only available with pro model)"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
args = parser.parse_args()
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
text = generate_image(
|
|
116
|
+
prompt=args.prompt,
|
|
117
|
+
output_path=args.output,
|
|
118
|
+
model=args.model,
|
|
119
|
+
aspect_ratio=args.aspect,
|
|
120
|
+
image_size=args.size,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
print(f"Image saved to: {args.output}")
|
|
124
|
+
if text:
|
|
125
|
+
print(f"Model response: {text}")
|
|
126
|
+
|
|
127
|
+
except Exception as e:
|
|
128
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
129
|
+
sys.exit(1)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
if __name__ == "__main__":
|
|
133
|
+
main()
|