-
Notifications
You must be signed in to change notification settings - Fork 131
Gemini session resume #810
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
45d2390
64fa3e8
886f556
5a7cfaf
4994200
753e417
610c67a
5d0b10b
531940d
c961ee0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,9 +13,9 @@ Run [Gemini CLI](https://github.com/google-gemini/gemini-cli) in your workspace | |
| ```tf | ||
| module "gemini" { | ||
| source = "registry.coder.com/coder-labs/gemini/coder" | ||
| version = "3.0.0" | ||
| version = "3.0.1" | ||
| agent_id = coder_agent.main.id | ||
| folder = "/home/coder/project" | ||
| folder = "/home/coder" | ||
| } | ||
| ``` | ||
|
|
||
|
|
@@ -46,18 +46,18 @@ variable "gemini_api_key" { | |
|
|
||
| module "gemini" { | ||
| source = "registry.coder.com/coder-labs/gemini/coder" | ||
| version = "3.0.0" | ||
| version = "3.0.1" | ||
| agent_id = coder_agent.main.id | ||
| gemini_api_key = var.gemini_api_key | ||
| folder = "/home/coder/project" | ||
| folder = "/home/coder" | ||
| } | ||
| ``` | ||
|
|
||
| This basic setup will: | ||
|
|
||
| - Install Gemini CLI in the workspace | ||
| - Configure authentication with your API key | ||
| - Set Gemini to run in `/home/coder/project` directory | ||
| - Set Gemini to run in `/home/coder` directory | ||
| - Enable interactive use from the terminal | ||
| - Set up MCP server integration for task reporting | ||
|
|
||
|
|
@@ -94,11 +94,11 @@ data "coder_parameter" "ai_prompt" { | |
| module "gemini" { | ||
| count = data.coder_workspace.me.start_count | ||
| source = "registry.coder.com/coder-labs/gemini/coder" | ||
| version = "3.0.0" | ||
| version = "3.0.1" | ||
| agent_id = coder_agent.main.id | ||
| gemini_api_key = var.gemini_api_key | ||
| gemini_model = "gemini-2.5-flash" | ||
| folder = "/home/coder/project" | ||
| folder = "/home/coder" | ||
| task_prompt = data.coder_parameter.ai_prompt.value | ||
| enable_yolo_mode = true # Auto-approve all tool calls for automation | ||
| gemini_system_prompt = <<-EOT | ||
|
|
@@ -111,17 +111,34 @@ module "gemini" { | |
| > [!WARNING] | ||
| > YOLO mode automatically approves all tool calls without user confirmation. The agent has access to your machine's file system and terminal. Only enable in trusted, isolated environments. | ||
|
|
||
| ### Session Resumption Behavior | ||
|
|
||
| By default, Gemini CLI automatically resumes existing conversations when your workspace restarts. Sessions are tracked per workspace directory, so conversations continue where you left off. If no session exists (first start), your `ai_prompt` will run normally. To disable this behavior and always start fresh, set `continue = false` | ||
|
|
||
| ## State Persistence | ||
|
|
||
| AgentAPI can save and restore its conversation state to disk across workspace restarts. This complements `continue` (which resumes the Gemini CLI session) by also preserving the AgentAPI-level context. Enabled by default, requires agentapi >= v0.12.0 (older versions skip it with a warning). | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2
If this refers to the Nit The
|
||
| To disable: | ||
|
|
||
| ```tf | ||
| module "gemini" { | ||
| # ... other config | ||
| enable_state_persistence = false | ||
| } | ||
| ``` | ||
|
|
||
| ### Using Vertex AI (Enterprise) | ||
|
|
||
| For enterprise users who prefer Google's Vertex AI platform: | ||
|
|
||
| ```tf | ||
| module "gemini" { | ||
| source = "registry.coder.com/coder-labs/gemini/coder" | ||
| version = "3.0.0" | ||
| version = "3.0.1" | ||
| agent_id = coder_agent.main.id | ||
| gemini_api_key = var.gemini_api_key | ||
| folder = "/home/coder/project" | ||
| folder = "/home/coder" | ||
| use_vertexai = true | ||
| } | ||
| ``` | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -78,10 +78,16 @@ variable "install_agentapi" { | |
| default = true | ||
| } | ||
|
|
||
| variable "continue" { | ||
| type = bool | ||
| description = "Automatically continue existing sessions on workspace restart. When true, resumes existing conversation if found, otherwise runs prompt or starts new session. When false, always starts fresh (ignores existing sessions)." | ||
| default = true | ||
| } | ||
|
|
||
| variable "agentapi_version" { | ||
| type = string | ||
| description = "The version of AgentAPI to install." | ||
| default = "v0.10.0" | ||
| default = "v0.12.0" | ||
| } | ||
|
|
||
| variable "gemini_model" { | ||
|
|
@@ -126,6 +132,12 @@ variable "enable_yolo_mode" { | |
| default = false | ||
| } | ||
|
|
||
| variable "enable_state_persistence" { | ||
| type = bool | ||
| description = "Enable AgentAPI conversation state persistence across restarts." | ||
| default = true | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1
Either bump the default
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1
Either bump the default
|
||
| } | ||
|
|
||
| resource "coder_env" "gemini_api_key" { | ||
| agent_id = var.agent_id | ||
| name = "GEMINI_API_KEY" | ||
|
|
@@ -177,23 +189,24 @@ EOT | |
|
|
||
| module "agentapi" { | ||
| source = "registry.coder.com/coder/agentapi/coder" | ||
| version = "2.0.0" | ||
|
|
||
| agent_id = var.agent_id | ||
| folder = local.folder | ||
| web_app_slug = local.app_slug | ||
| web_app_order = var.order | ||
| web_app_group = var.group | ||
| web_app_icon = var.icon | ||
| web_app_display_name = "Gemini" | ||
| cli_app_slug = "${local.app_slug}-cli" | ||
| cli_app_display_name = "Gemini CLI" | ||
| module_dir_name = local.module_dir_name | ||
| install_agentapi = var.install_agentapi | ||
| agentapi_version = var.agentapi_version | ||
| pre_install_script = var.pre_install_script | ||
| post_install_script = var.post_install_script | ||
| install_script = <<-EOT | ||
| version = "2.2.0" | ||
|
|
||
| agent_id = var.agent_id | ||
| folder = local.folder | ||
| web_app_slug = local.app_slug | ||
| web_app_order = var.order | ||
| web_app_group = var.group | ||
| web_app_icon = var.icon | ||
| web_app_display_name = "Gemini" | ||
| cli_app_slug = "${local.app_slug}-cli" | ||
| cli_app_display_name = "Gemini CLI" | ||
| module_dir_name = local.module_dir_name | ||
| install_agentapi = var.install_agentapi | ||
| agentapi_version = var.agentapi_version | ||
| enable_state_persistence = var.enable_state_persistence | ||
| pre_install_script = var.pre_install_script | ||
| post_install_script = var.post_install_script | ||
| install_script = <<-EOT | ||
| #!/bin/bash | ||
| set -o errexit | ||
| set -o pipefail | ||
|
|
@@ -209,20 +222,21 @@ module "agentapi" { | |
| GEMINI_SYSTEM_PROMPT='${base64encode(var.gemini_system_prompt)}' \ | ||
| /tmp/install.sh | ||
| EOT | ||
| start_script = <<-EOT | ||
| start_script = <<-EOT | ||
| #!/bin/bash | ||
| set -o errexit | ||
| set -o pipefail | ||
|
|
||
| echo -n '${base64encode(local.start_script)}' | base64 -d > /tmp/start.sh | ||
| chmod +x /tmp/start.sh | ||
| GEMINI_API_KEY='${var.gemini_api_key}' \ | ||
| GOOGLE_API_KEY='${var.gemini_api_key}' \ | ||
| GOOGLE_GENAI_USE_VERTEXAI='${var.use_vertexai}' \ | ||
| GEMINI_YOLO_MODE='${var.enable_yolo_mode}' \ | ||
| GEMINI_MODEL='${var.gemini_model}' \ | ||
| GEMINI_START_DIRECTORY='${var.folder}' \ | ||
| GEMINI_TASK_PROMPT='${var.task_prompt}' \ | ||
| GEMINI_API_KEY='${base64encode(var.gemini_api_key)}' \ | ||
| GOOGLE_API_KEY='${base64encode(var.gemini_api_key)}' \ | ||
| GOOGLE_GENAI_USE_VERTEXAI='${base64encode(var.use_vertexai)}' \ | ||
| GEMINI_YOLO_MODE='${base64encode(var.enable_yolo_mode)}' \ | ||
| GEMINI_MODEL='${base64encode(var.gemini_model)}' \ | ||
| GEMINI_START_DIRECTORY='${base64encode(var.folder)}' \ | ||
| GEMINI_TASK_PROMPT='${base64encode(var.task_prompt)}' \ | ||
| ARG_CONTINUE='${base64encode(var.continue)}' \ | ||
| /tmp/start.sh | ||
| EOT | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,202 @@ | ||
| run "test_gemini_basic" { | ||
| command = plan | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3 Every test assertion checks that a variable equals what it was just set to, or that a default equals its declared default. This proves Terraform can assign variables, not that the module works. (Bisky P1, Meruem P3, Hisoka Obs)
Plan-level assertions on module outputs or resource attributes would catch wiring errors. Having a test file is better than not, but these particular tests create a false sense of coverage. PS. Missing newline at end of file (line 82).
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3 Every test assertion checks that a variable equals what it was just set to, or that a default equals its declared default. This proves Terraform can assign variables, not that the module works. (Bisky P1, Meruem P3, Hisoka Obs)
Plan-level assertions on module outputs or resource attributes would catch wiring errors. Having a test file is better than not, but these particular tests create a false sense of coverage. PS. Missing newline at end of file (line 82).
|
||
|
|
||
| variables { | ||
| agent_id = "test-agent-123" | ||
| folder = "/home/coder" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.agent_id == "test-agent-123" | ||
| error_message = "Agent ID variable should be set correctly" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.folder == "/home/coder" | ||
| error_message = "Folder variable should be set correctly" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.install_gemini == true | ||
| error_message = "install_gemini should default to true" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.install_agentapi == true | ||
| error_message = "install_agentapi should default to true" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.use_vertexai == false | ||
| error_message = "use_vertexai should default to false" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.enable_yolo_mode == false | ||
| error_message = "enable_yolo_mode should default to false" | ||
| } | ||
| } | ||
|
|
||
| run "test_gemini_with_api_key" { | ||
| command = plan | ||
|
|
||
| variables { | ||
| agent_id = "test-agent-456" | ||
| folder = "/home/coder" | ||
| gemini_api_key = "test-api-key-123" | ||
| } | ||
|
|
||
| assert { | ||
| condition = coder_env.gemini_api_key[0].value == "test-api-key-123" | ||
| error_message = "Gemini API key value should match the input" | ||
| } | ||
| } | ||
|
|
||
| run "test_gemini_with_custom_options" { | ||
| command = plan | ||
|
|
||
| variables { | ||
| agent_id = "test-agent-789" | ||
| folder = "/home/coder/custom" | ||
| order = 5 | ||
| group = "development" | ||
| icon = "/icon/custom.svg" | ||
| gemini_version = "1.0.0" | ||
| gemini_model = "gemini-pro" | ||
| agentapi_version = "v0.13.0" | ||
| continue = false | ||
| pre_install_script = "echo 'Pre-install script'" | ||
| post_install_script = "echo 'Post-install script'" | ||
| task_prompt = "Automate this task" | ||
| additional_extensions = "{ \"my-extension\": {} }" | ||
| gemini_system_prompt = "Custom system prompt" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.order == 5 | ||
| error_message = "Order variable should be set to 5" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.group == "development" | ||
| error_message = "Group variable should be set to 'development'" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.icon == "/icon/custom.svg" | ||
| error_message = "Icon variable should be set to custom icon" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.gemini_version == "1.0.0" | ||
| error_message = "Gemini version should be set to '1.0.0'" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.gemini_model == "gemini-pro" | ||
| error_message = "Gemini model variable should be set to 'gemini-pro'" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.agentapi_version == "v0.13.0" | ||
| error_message = "AgentAPI version should be set to 'v0.13.0'" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.continue == false | ||
| error_message = "Continue should be set to false" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.pre_install_script == "echo 'Pre-install script'" | ||
| error_message = "Pre-install script should be set correctly" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.post_install_script == "echo 'Post-install script'" | ||
| error_message = "Post-install script should be set correctly" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.task_prompt == "Automate this task" | ||
| error_message = "Task prompt should be set correctly" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.additional_extensions == "{ \"my-extension\": {} }" | ||
| error_message = "Additional extensions should be set correctly" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.gemini_system_prompt == "Custom system prompt" | ||
| error_message = "Gemini system prompt should be set correctly" | ||
| } | ||
| } | ||
|
|
||
| run "test_gemini_system_prompt" { | ||
| command = plan | ||
|
|
||
| variables { | ||
| agent_id = "test-agent-system-prompt" | ||
| folder = "/home/coder/test" | ||
| gemini_system_prompt = "Custom addition" | ||
| } | ||
|
|
||
| assert { | ||
| condition = trimspace(coder_env.gemini_system_prompt.value) != "" | ||
| error_message = "System prompt should not be empty" | ||
| } | ||
|
|
||
| assert { | ||
| condition = length(regexall("Custom addition", coder_env.gemini_system_prompt.value)) > 0 | ||
| error_message = "System prompt should have system_prompt variable value" | ||
| } | ||
| } | ||
|
|
||
| run "test_no_api_key_no_env" { | ||
| command = plan | ||
|
|
||
| variables { | ||
| agent_id = "test-agent-no-key" | ||
| folder = "/home/coder/test" | ||
| } | ||
|
|
||
| assert { | ||
| condition = length(coder_env.gemini_api_key) == 0 | ||
| error_message = "GEMINI_API_KEY should not be created when no API key is provided" | ||
| } | ||
|
|
||
| assert { | ||
| condition = length(coder_env.google_api_key) == 0 | ||
| error_message = "GOOGLE_API_KEY should not be created when no API key is provided" | ||
| } | ||
| } | ||
|
|
||
| run "test_enable_state_persistence_default" { | ||
| command = plan | ||
|
|
||
| variables { | ||
| agent_id = "test-agent" | ||
| workdir = "/home/coder" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.enable_state_persistence == true | ||
| error_message = "enable_state_persistence should default to true" | ||
| } | ||
| } | ||
|
|
||
| run "test_disable_state_persistence" { | ||
| command = plan | ||
|
|
||
| variables { | ||
| agent_id = "test-agent" | ||
| workdir = "/home/coder" | ||
| enable_state_persistence = false | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.enable_state_persistence == false | ||
| error_message = "enable_state_persistence should be false when explicitly disabled" | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2
continuein backticks implies a command or flag, but it doesn't exist in this module. The script uses--resume. (Hisoka P2, Leorio Nit, Pen Botter Nit)If this refers to the
--resumeflag, call it--resume. If it's a Gemini CLI concept, link or explain it.Nit The
## State Persistenceheading breaks the heading hierarchy.### Using Vertex AI (Enterprise)was previously a child of## Examples. Now it appears to be a child of## State Persistence, which has nothing to do with Vertex AI. Move this section after the Vertex AI subsection, or place it before## Troubleshooting. (Leorio Nit, Pen Botter Nit)