-
Notifications
You must be signed in to change notification settings - Fork 146
feat(gemini-module): 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 7 commits
45d2390
64fa3e8
886f556
5a7cfaf
4994200
753e417
610c67a
5d0b10b
531940d
c961ee0
ec7fdb6
79377fe
a7f7992
39e5ef2
f824fcf
8ee19cd
17ade9f
060e75e
b16b17d
dfea777
574e3f9
180ed2c
01091d9
c6605b0
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 |
|---|---|---|
|
|
@@ -111,6 +111,19 @@ 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. | ||
|
|
||
| ## 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: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,7 +39,7 @@ variable "icon" { | |
| variable "folder" { | ||
| type = string | ||
| description = "The folder to run Gemini in." | ||
| default = "/home/coder" | ||
| default = "/home/coder/project" | ||
| } | ||
|
Harsh9485 marked this conversation as resolved.
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 Default
The PR description marks "Breaking change: No" and uses a minor version bump (3.1.0). Per registry conventions, breaking changes require a major bump. If this change is intentional, it needs a major version bump and a migration note. If accidental, revert it.
|
||
|
|
||
| variable "install_gemini" { | ||
|
|
@@ -126,6 +126,12 @@ variable "enable_yolo_mode" { | |
| default = false | ||
| } | ||
|
|
||
| variable "enable_state_persistence" { | ||
| type = bool | ||
| description = "Enable AgentAPI conversation state persistence across restarts." | ||
| default = true | ||
|
Harsh9485 marked this conversation as resolved.
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 +183,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 +216,20 @@ 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)}' \ | ||
| /tmp/start.sh | ||
| EOT | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| run "test_gemini_basic" { | ||
| command = plan | ||
|
Harsh9485 marked this conversation as resolved.
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/projects" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.agent_id == "test-agent-123" | ||
| error_message = "Agent ID variable should be set correctly" | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.folder == "/home/coder/projects" | ||
| 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_enable_state_persistence_default" { | ||
| command = plan | ||
|
|
||
| variables { | ||
| agent_id = "test-agent" | ||
| folder = "/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" | ||
| folder = "/home/coder" | ||
| enable_state_persistence = false | ||
| } | ||
|
|
||
| assert { | ||
| condition = var.enable_state_persistence == false | ||
| error_message = "enable_state_persistence should be false when explicitly disabled" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,18 @@ set -o pipefail | |
|
|
||
| source "$HOME"/.bashrc | ||
|
|
||
| set -o nounset | ||
|
|
||
| GEMINI_API_KEY=$(echo -n "$GEMINI_API_KEY" | base64 -d) | ||
| GOOGLE_API_KEY=$(echo -n "$GOOGLE_API_KEY" | base64 -d) | ||
| GOOGLE_GENAI_USE_VERTEXAI=$(echo -n "$GOOGLE_GENAI_USE_VERTEXAI" | base64 -d) | ||
| GEMINI_YOLO_MODE=$(echo -n "$GEMINI_YOLO_MODE" | base64 -d) | ||
| GEMINI_MODEL=$(echo -n "$GEMINI_MODEL" | base64 -d) | ||
| GEMINI_START_DIRECTORY=$(echo -n "$GEMINI_START_DIRECTORY" | base64 -d) | ||
| GEMINI_TASK_PROMPT=$(echo -n "$GEMINI_TASK_PROMPT" | base64 -d) | ||
|
|
||
| set +o nounset | ||
|
|
||
| command_exists() { | ||
| command -v "$1" > /dev/null 2>&1 | ||
| } | ||
|
|
@@ -44,22 +56,6 @@ else | |
| } | ||
| fi | ||
|
|
||
| if [ -n "$GEMINI_TASK_PROMPT" ]; then | ||
| printf "Running automated task: %s\n" "$GEMINI_TASK_PROMPT" | ||
| PROMPT="Every step of the way, report tasks to Coder with proper descriptions and statuses. Your task at hand: $GEMINI_TASK_PROMPT" | ||
| PROMPT_FILE="$MODULE_DIR/prompt.txt" | ||
| echo -n "$PROMPT" > "$PROMPT_FILE" | ||
| GEMINI_ARGS=(--prompt-interactive "$PROMPT") | ||
| else | ||
| printf "Starting Gemini CLI in interactive mode.\n" | ||
| GEMINI_ARGS=() | ||
| fi | ||
|
|
||
| if [ -n "$GEMINI_YOLO_MODE" ] && [ "$GEMINI_YOLO_MODE" = "true" ]; then | ||
| printf "YOLO mode enabled - will auto-approve all tool calls\n" | ||
| GEMINI_ARGS+=(--yolo) | ||
| fi | ||
|
|
||
| if [ -n "$GEMINI_API_KEY" ] || [ -n "$GOOGLE_API_KEY" ]; then | ||
| if [ -n "$GOOGLE_GENAI_USE_VERTEXAI" ] && [ "$GOOGLE_GENAI_USE_VERTEXAI" = "true" ]; then | ||
| printf "Using Vertex AI with API key\n" | ||
|
|
@@ -68,7 +64,32 @@ if [ -n "$GEMINI_API_KEY" ] || [ -n "$GOOGLE_API_KEY" ]; then | |
| fi | ||
| else | ||
| printf "No API key provided (neither GEMINI_API_KEY nor GOOGLE_API_KEY)\n" | ||
| exit 1 | ||
| fi | ||
|
Harsh9485 marked this conversation as resolved.
Harsh9485 marked this conversation as resolved.
|
||
|
|
||
| if [ -n "$GEMINI_YOLO_MODE" ] && [ "$GEMINI_YOLO_MODE" = "true" ]; then | ||
| printf "YOLO mode enabled - will auto-approve all tool calls\n" | ||
| GEMINI_ARGS=(--yolo) | ||
| fi | ||
|
Harsh9485 marked this conversation as resolved.
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
Add PS. Line 91 (
|
||
|
|
||
| agentapi server --term-width 67 --term-height 1190 -- \ | ||
| bash -c "$(printf '%q ' gemini "${GEMINI_ARGS[@]}")" | ||
| SESSION_FOLDER_NAME=$(basename "${GEMINI_START_DIRECTORY}") | ||
| if [ -d "$GEMINI_START_DIRECTORY/.gemini/tmp/$SESSION_FOLDER_NAME/chats/" ]; then | ||
| printf "Existing Gemini chats detected. Starting Gemini CLI in interactive mode with existing chats.\n" | ||
|
Harsh9485 marked this conversation as resolved.
Outdated
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
Either add a separate variable to control Gemini CLI resume behavior, or document clearly that Obs The session detection path (
|
||
| GEMINI_ARGS+=(--resume) | ||
| agentapi server --type gemini --term-width 67 --term-height 1190 -- \ | ||
|
Harsh9485 marked this conversation as resolved.
Outdated
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 Task prompt is silently dropped when resuming an existing session. (Bisky P1, Hisoka P1, Mafuuu P1, Mafu-san P1, Meruem P1, Kurapika P1, Luffy P1)
This means the "Automated task execution" example from the README stops working after the first workspace restart. At minimum, log a warning when task_prompt is set but resume takes precedence. The codex module handles this correctly with a separate
|
||
| bash -c "$(printf '%q ' gemini "${GEMINI_ARGS[@]}")" | ||
| else | ||
| printf "No existing Gemini chats found. Starting Gemini CLI in interactive mode.\n" | ||
| if [ -n "$GEMINI_TASK_PROMPT" ]; then | ||
| printf "Running automated task: %s\n" "$GEMINI_TASK_PROMPT" | ||
| PROMPT="Every step of the way, report tasks to Coder with proper descriptions and statuses. Your task at hand: $GEMINI_TASK_PROMPT" | ||
| PROMPT_FILE="$MODULE_DIR/prompt.txt" | ||
| echo -n "$PROMPT" > "$PROMPT_FILE" | ||
| GEMINI_ARGS+=(--prompt-interactive "$PROMPT") | ||
| else | ||
| printf "Starting Gemini CLI in interactive mode.\n" | ||
| GEMINI_ARGS+=() | ||
|
Harsh9485 marked this conversation as resolved.
Outdated
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. Nit Duplicate log message. Line 82 already prints "Starting Gemini CLI in interactive mode." This line prints it again. (Gon, Leorio)
|
||
| fi | ||
| agentapi server --type gemini --term-width 67 --term-height 1190 -- \ | ||
| bash -c "$(printf '%q ' gemini "${GEMINI_ARGS[@]}")" | ||
| fi | ||
Uh oh!
There was an error while loading. Please reload this page.