diff --git a/registry/coder-labs/modules/gemini/README.md b/registry/coder-labs/modules/gemini/README.md index 37fdca120..e661093ea 100644 --- a/registry/coder-labs/modules/gemini/README.md +++ b/registry/coder-labs/modules/gemini/README.md @@ -13,7 +13,7 @@ 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 = "1.1.0" + version = "2.0.0" agent_id = coder_agent.example.id folder = "/home/coder/project" } @@ -30,7 +30,7 @@ module "gemini" { ## Prerequisites -- Node.js and npm will be installed automatically if not present +- **Node.js and npm must be sourced/available before the gemini module installs** - ensure they are installed in your workspace image or via earlier provisioning steps - The [Coder Login](https://registry.coder.com/modules/coder/coder-login) module is required ## Examples @@ -46,7 +46,7 @@ variable "gemini_api_key" { module "gemini" { source = "registry.coder.com/coder-labs/gemini/coder" - version = "1.1.0" + version = "2.0.0" agent_id = coder_agent.example.id gemini_api_key = var.gemini_api_key folder = "/home/coder/project" @@ -94,7 +94,7 @@ data "coder_parameter" "ai_prompt" { module "gemini" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder-labs/gemini/coder" - version = "1.1.0" + version = "2.0.0" agent_id = coder_agent.example.id gemini_api_key = var.gemini_api_key gemini_model = "gemini-2.5-flash" @@ -118,7 +118,7 @@ For enterprise users who prefer Google's Vertex AI platform: ```tf module "gemini" { source = "registry.coder.com/coder-labs/gemini/coder" - version = "1.1.0" + version = "2.0.0" agent_id = coder_agent.example.id gemini_api_key = var.gemini_api_key folder = "/home/coder/project" diff --git a/registry/coder-labs/modules/gemini/main.test.ts b/registry/coder-labs/modules/gemini/main.test.ts index 33de80a98..2dfd75bc5 100644 --- a/registry/coder-labs/modules/gemini/main.test.ts +++ b/registry/coder-labs/modules/gemini/main.test.ts @@ -153,7 +153,7 @@ describe("gemini", async () => { }, }); await execModuleScript(id); - const resp = await readFileContainer(id, "/home/coder/.gemini-module/install.log"); + const resp = await readFileContainer(id, "/home/coder/.gemini-module/agentapi-start.log"); expect(resp).toContain('GOOGLE_GENAI_USE_VERTEXAI=\'true\''); }); @@ -166,7 +166,7 @@ describe("gemini", async () => { }, }); await execModuleScript(id); - const resp = await readFileContainer(id, "/home/coder/.gemini-module/install.log"); + const resp = await readFileContainer(id, "/home/coder/.gemini-module/agentapi-start.log"); expect(resp).toContain(model); }); @@ -193,7 +193,7 @@ describe("gemini", async () => { }, }); await execModuleScript(id); - const resp = await readFileContainer(id, "/home/coder/.gemini-module/install.log"); + const resp = await readFileContainer(id, "/home/coder/.gemini-module/agentapi-start.log"); expect(resp).toContain(folder); }); diff --git a/registry/coder-labs/modules/gemini/scripts/install.sh b/registry/coder-labs/modules/gemini/scripts/install.sh index 89ea07a0b..7b70a6af4 100644 --- a/registry/coder-labs/modules/gemini/scripts/install.sh +++ b/registry/coder-labs/modules/gemini/scripts/install.sh @@ -1,9 +1,9 @@ #!/bin/bash BOLD='\033[0;1m' - +source "$HOME"/.bashrc command_exists() { - command -v "$1" >/dev/null 2>&1 + command -v "$1" > /dev/null 2>&1 } set -o nounset @@ -21,144 +21,132 @@ echo "--------------------------------" set +o nounset -function install_node() { - if ! command_exists npm; then - printf "npm not found, checking for Node.js installation...\n" - if ! command_exists node; then - printf "Node.js not found, installing Node.js via NVM...\n" - export NVM_DIR="$HOME/.nvm" - if [ ! -d "$NVM_DIR" ]; then - mkdir -p "$NVM_DIR" - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - else - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - fi - - nvm install --lts - nvm use --lts - nvm alias default node - - printf "Node.js installed: %s\n" "$(node --version)" - printf "npm installed: %s\n" "$(npm --version)" - else - printf "Node.js is installed but npm is not available. Please install npm manually.\n" - exit 1 - fi - fi +function check_dependencies() { + if ! command_exists node; then + printf "Error: Node.js is not installed. Please install Node.js manually or use the pre_install_script to install it.\n" + exit 1 + fi + + if ! command_exists npm; then + printf "Error: npm is not installed. Please install npm manually or use the pre_install_script to install it.\n" + exit 1 + fi + + printf "Node.js version: %s\n" "$(node --version)" + printf "npm version: %s\n" "$(npm --version)" } function install_gemini() { if [ "${ARG_INSTALL}" = "true" ]; then - install_node - - if ! command_exists nvm; then - printf "which node: %s\n" "$(which node)" - printf "which npm: %s\n" "$(which npm)" - - mkdir -p "$HOME"/.npm-global - npm config set prefix "$HOME/.npm-global" - export PATH="$HOME/.npm-global/bin:$PATH" - if ! grep -q "export PATH=$HOME/.npm-global/bin:\$PATH" ~/.bashrc; then - echo "export PATH=$HOME/.npm-global/bin:\$PATH" >> ~/.bashrc - fi - fi + check_dependencies printf "%s Installing Gemini CLI\n" "${BOLD}" + NPM_GLOBAL_PREFIX="${HOME}/.npm-global" + if [ ! -d "$NPM_GLOBAL_PREFIX" ]; then + mkdir -p "$NPM_GLOBAL_PREFIX" + fi + + npm config set prefix "$NPM_GLOBAL_PREFIX" + + export PATH="$NPM_GLOBAL_PREFIX/bin:$PATH" + if [ -n "$ARG_GEMINI_VERSION" ]; then npm install -g "@google/gemini-cli@$ARG_GEMINI_VERSION" else npm install -g "@google/gemini-cli" fi + + if ! grep -q "export PATH=\"\$HOME/.npm-global/bin:\$PATH\"" "$HOME/.bashrc"; then + echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> "$HOME/.bashrc" + fi + printf "%s Successfully installed Gemini CLI. Version: %s\n" "${BOLD}" "$(gemini --version)" fi } function populate_settings_json() { - if [ "${ARG_GEMINI_CONFIG}" != "" ]; then - SETTINGS_PATH="$HOME/.gemini/settings.json" - mkdir -p "$(dirname "$SETTINGS_PATH")" - printf "Custom gemini_config is provided !\n" - echo "${ARG_GEMINI_CONFIG}" > "$HOME/.gemini/settings.json" - else - printf "No custom gemini_config provided, using default settings.json.\n" - append_extensions_to_settings_json - fi -} - -function append_extensions_to_settings_json() { + if [ "${ARG_GEMINI_CONFIG}" != "" ]; then SETTINGS_PATH="$HOME/.gemini/settings.json" mkdir -p "$(dirname "$SETTINGS_PATH")" - printf "[append_extensions_to_settings_json] Starting extension merge process...\n" - if [ -z "${BASE_EXTENSIONS:-}" ]; then - printf "[append_extensions_to_settings_json] BASE_EXTENSIONS is empty, skipping merge.\n" - return - fi - if [ ! -f "$SETTINGS_PATH" ]; then - printf "%s does not exist. Creating with merged mcpServers structure.\n" "$SETTINGS_PATH" - ADD_EXT_JSON='{}' - if [ -n "${ADDITIONAL_EXTENSIONS:-}" ]; then - ADD_EXT_JSON="$ADDITIONAL_EXTENSIONS" - fi - printf '{"mcpServers":%s}\n' "$(jq -s 'add' <(echo "$BASE_EXTENSIONS") <(echo "$ADD_EXT_JSON"))" > "$SETTINGS_PATH" - fi + printf "Custom gemini_config is provided !\n" + echo "${ARG_GEMINI_CONFIG}" > "$HOME/.gemini/settings.json" + else + printf "No custom gemini_config provided, using default settings.json.\n" + append_extensions_to_settings_json + fi +} - TMP_SETTINGS=$(mktemp) +function append_extensions_to_settings_json() { + SETTINGS_PATH="$HOME/.gemini/settings.json" + mkdir -p "$(dirname "$SETTINGS_PATH")" + printf "[append_extensions_to_settings_json] Starting extension merge process...\n" + if [ -z "${BASE_EXTENSIONS:-}" ]; then + printf "[append_extensions_to_settings_json] BASE_EXTENSIONS is empty, skipping merge.\n" + return + fi + if [ ! -f "$SETTINGS_PATH" ]; then + printf "%s does not exist. Creating with merged mcpServers structure.\n" "$SETTINGS_PATH" ADD_EXT_JSON='{}' if [ -n "${ADDITIONAL_EXTENSIONS:-}" ]; then - printf "[append_extensions_to_settings_json] ADDITIONAL_EXTENSIONS is set.\n" ADD_EXT_JSON="$ADDITIONAL_EXTENSIONS" - else - printf "[append_extensions_to_settings_json] ADDITIONAL_EXTENSIONS is empty or not set.\n" fi + printf '{"mcpServers":%s}\n' "$(jq -s 'add' <(echo "$BASE_EXTENSIONS") <(echo "$ADD_EXT_JSON"))" > "$SETTINGS_PATH" + fi + + TMP_SETTINGS=$(mktemp) + ADD_EXT_JSON='{}' + if [ -n "${ADDITIONAL_EXTENSIONS:-}" ]; then + printf "[append_extensions_to_settings_json] ADDITIONAL_EXTENSIONS is set.\n" + ADD_EXT_JSON="$ADDITIONAL_EXTENSIONS" + else + printf "[append_extensions_to_settings_json] ADDITIONAL_EXTENSIONS is empty or not set.\n" + fi - printf "[append_extensions_to_settings_json] Merging BASE_EXTENSIONS and ADDITIONAL_EXTENSIONS into mcpServers...\n" - jq --argjson base "$BASE_EXTENSIONS" --argjson add "$ADD_EXT_JSON" \ - '.mcpServers = (.mcpServers // {} + $base + $add)' \ - "$SETTINGS_PATH" > "$TMP_SETTINGS" && mv "$TMP_SETTINGS" "$SETTINGS_PATH" + printf "[append_extensions_to_settings_json] Merging BASE_EXTENSIONS and ADDITIONAL_EXTENSIONS into mcpServers...\n" + jq --argjson base "$BASE_EXTENSIONS" --argjson add "$ADD_EXT_JSON" \ + '.mcpServers = (.mcpServers // {} + $base + $add)' \ + "$SETTINGS_PATH" > "$TMP_SETTINGS" && mv "$TMP_SETTINGS" "$SETTINGS_PATH" - jq '.theme = "Default" | .selectedAuthType = "gemini-api-key"' "$SETTINGS_PATH" > "$TMP_SETTINGS" && mv "$TMP_SETTINGS" "$SETTINGS_PATH" + jq '.theme = "Default" | .selectedAuthType = "gemini-api-key"' "$SETTINGS_PATH" > "$TMP_SETTINGS" && mv "$TMP_SETTINGS" "$SETTINGS_PATH" - printf "[append_extensions_to_settings_json] Merge complete.\n" + printf "[append_extensions_to_settings_json] Merge complete.\n" } function add_system_prompt_if_exists() { - if [ -n "${GEMINI_SYSTEM_PROMPT:-}" ]; then - if [ -d "${GEMINI_START_DIRECTORY}" ]; then - printf "Directory '%s' exists. Changing to it.\\n" "${GEMINI_START_DIRECTORY}" - cd "${GEMINI_START_DIRECTORY}" || { - printf "Error: Could not change to directory '%s'.\\n" "${GEMINI_START_DIRECTORY}" - exit 1 - } - else - printf "Directory '%s' does not exist. Creating and changing to it.\\n" "${GEMINI_START_DIRECTORY}" - mkdir -p "${GEMINI_START_DIRECTORY}" || { - printf "Error: Could not create directory '%s'.\\n" "${GEMINI_START_DIRECTORY}" - exit 1 - } - cd "${GEMINI_START_DIRECTORY}" || { - printf "Error: Could not change to directory '%s'.\\n" "${GEMINI_START_DIRECTORY}" - exit 1 - } - fi - touch GEMINI.md - printf "Setting GEMINI.md\n" - echo "${GEMINI_SYSTEM_PROMPT}" > GEMINI.md + if [ -n "${GEMINI_SYSTEM_PROMPT:-}" ]; then + if [ -d "${GEMINI_START_DIRECTORY}" ]; then + printf "Directory '%s' exists. Changing to it.\\n" "${GEMINI_START_DIRECTORY}" + cd "${GEMINI_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${GEMINI_START_DIRECTORY}" + exit 1 + } else - printf "GEMINI.md is not set.\n" + printf "Directory '%s' does not exist. Creating and changing to it.\\n" "${GEMINI_START_DIRECTORY}" + mkdir -p "${GEMINI_START_DIRECTORY}" || { + printf "Error: Could not create directory '%s'.\\n" "${GEMINI_START_DIRECTORY}" + exit 1 + } + cd "${GEMINI_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${GEMINI_START_DIRECTORY}" + exit 1 + } fi + touch GEMINI.md + printf "Setting GEMINI.md\n" + echo "${GEMINI_SYSTEM_PROMPT}" > GEMINI.md + else + printf "GEMINI.md is not set.\n" + fi } function configure_mcp() { - export CODER_MCP_APP_STATUS_SLUG="gemini" - export CODER_MCP_AI_AGENTAPI_URL="http://localhost:3284" - coder exp mcp configure gemini "${GEMINI_START_DIRECTORY}" + export CODER_MCP_APP_STATUS_SLUG="gemini" + export CODER_MCP_AI_AGENTAPI_URL="http://localhost:3284" + coder exp mcp configure gemini "${GEMINI_START_DIRECTORY}" } install_gemini -gemini --version populate_settings_json add_system_prompt_if_exists configure_mcp - diff --git a/registry/coder-labs/modules/gemini/scripts/start.sh b/registry/coder-labs/modules/gemini/scripts/start.sh index aa09c165f..eed550907 100644 --- a/registry/coder-labs/modules/gemini/scripts/start.sh +++ b/registry/coder-labs/modules/gemini/scripts/start.sh @@ -5,7 +5,7 @@ set -o pipefail source "$HOME"/.bashrc command_exists() { - command -v "$1" >/dev/null 2>&1 + command -v "$1" > /dev/null 2>&1 } if [ -f "$HOME/.nvm/nvm.sh" ]; then @@ -20,55 +20,55 @@ MODULE_DIR="$HOME/.gemini-module" mkdir -p "$MODULE_DIR" if command_exists gemini; then - printf "Gemini is installed\n" + printf "Gemini is installed\n" else - printf "Error: Gemini is not installed. Please enable install_gemini or install it manually :)\n" - exit 1 + printf "Error: Gemini is not installed. Please enable install_gemini or install it manually :)\n" + exit 1 fi if [ -d "${GEMINI_START_DIRECTORY}" ]; then - printf "Directory '%s' exists. Changing to it.\\n" "${GEMINI_START_DIRECTORY}" - cd "${GEMINI_START_DIRECTORY}" || { - printf "Error: Could not change to directory '%s'.\\n" "${GEMINI_START_DIRECTORY}" - exit 1 - } + printf "Directory '%s' exists. Changing to it.\\n" "${GEMINI_START_DIRECTORY}" + cd "${GEMINI_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${GEMINI_START_DIRECTORY}" + exit 1 + } else - printf "Directory '%s' does not exist. Creating and changing to it.\\n" "${GEMINI_START_DIRECTORY}" - mkdir -p "${GEMINI_START_DIRECTORY}" || { - printf "Error: Could not create directory '%s'.\\n" "${GEMINI_START_DIRECTORY}" - exit 1 - } - cd "${GEMINI_START_DIRECTORY}" || { - printf "Error: Could not change to directory '%s'.\\n" "${GEMINI_START_DIRECTORY}" - exit 1 - } + printf "Directory '%s' does not exist. Creating and changing to it.\\n" "${GEMINI_START_DIRECTORY}" + mkdir -p "${GEMINI_START_DIRECTORY}" || { + printf "Error: Could not create directory '%s'.\\n" "${GEMINI_START_DIRECTORY}" + exit 1 + } + cd "${GEMINI_START_DIRECTORY}" || { + printf "Error: Could not change to directory '%s'.\\n" "${GEMINI_START_DIRECTORY}" + exit 1 + } 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") + 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=() + 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) + 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" - else - printf "Using direct Gemini API with API key\n" - fi + if [ -n "$GOOGLE_GENAI_USE_VERTEXAI" ] && [ "$GOOGLE_GENAI_USE_VERTEXAI" = "true" ]; then + printf "Using Vertex AI with API key\n" + else + printf "Using direct Gemini API with API key\n" + fi else - printf "No API key provided (neither GEMINI_API_KEY nor GOOGLE_API_KEY)\n" + printf "No API key provided (neither GEMINI_API_KEY nor GOOGLE_API_KEY)\n" fi agentapi server --term-width 67 --term-height 1190 -- \ - bash -c "$(printf '%q ' gemini "${GEMINI_ARGS[@]}")" \ No newline at end of file + bash -c "$(printf '%q ' gemini "${GEMINI_ARGS[@]}")"