feat(codex): optimize for standalone usage with optional workdir and default AI Bridge profile
- Add 'enable_tasks' variable (defaults to true) for better discoverability - Make 'workdir' optional when enable_tasks=false for standalone CLI usage - Keep 'install_agentapi' as deprecated alias for backward compatibility - Prepend 'profile = "aibridge"' to config.toml when AI Bridge is enabled so users can run 'codex' directly without --profile flag - Update README with standalone usage examples and version 4.2.0 - Add tests for aibridge profile at config top and standalone mode
This commit is contained in:
parent
49a7985bc6
commit
e18caa5a46
@ -13,7 +13,7 @@ Run Codex CLI in your workspace to access OpenAI's models through the Codex inte
|
|||||||
```tf
|
```tf
|
||||||
module "codex" {
|
module "codex" {
|
||||||
source = "registry.coder.com/coder-labs/codex/coder"
|
source = "registry.coder.com/coder-labs/codex/coder"
|
||||||
version = "4.1.0"
|
version = "4.2.0"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
openai_api_key = var.openai_api_key
|
openai_api_key = var.openai_api_key
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
@ -32,7 +32,7 @@ module "codex" {
|
|||||||
module "codex" {
|
module "codex" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder-labs/codex/coder"
|
source = "registry.coder.com/coder-labs/codex/coder"
|
||||||
version = "4.1.0"
|
version = "4.2.0"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
openai_api_key = "..."
|
openai_api_key = "..."
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
@ -48,10 +48,27 @@ For tasks integration with AI Bridge, add `enable_aibridge = true` to the [Usage
|
|||||||
|
|
||||||
#### Standalone usage with AI Bridge
|
#### Standalone usage with AI Bridge
|
||||||
|
|
||||||
|
For simple Codex CLI usage without Tasks UI, set `enable_tasks = false`. This is ideal when you just want Codex installed with AI Bridge configuration for manual use.
|
||||||
|
|
||||||
```tf
|
```tf
|
||||||
module "codex" {
|
module "codex" {
|
||||||
source = "registry.coder.com/coder-labs/codex/coder"
|
source = "registry.coder.com/coder-labs/codex/coder"
|
||||||
version = "4.1.0"
|
version = "4.2.0"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
enable_aibridge = true
|
||||||
|
enable_tasks = false # Standalone mode - just CLI, no Tasks UI
|
||||||
|
# workdir not required in standalone mode!
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Users can then run `codex` from any directory and it will automatically use the AI Bridge profile.
|
||||||
|
|
||||||
|
#### Tasks usage with AI Bridge
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "codex" {
|
||||||
|
source = "registry.coder.com/coder-labs/codex/coder"
|
||||||
|
version = "4.2.0"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
enable_aibridge = true
|
enable_aibridge = true
|
||||||
@ -61,8 +78,11 @@ module "codex" {
|
|||||||
When `enable_aibridge = true`, the module:
|
When `enable_aibridge = true`, the module:
|
||||||
|
|
||||||
- Configures Codex to use the AI Bridge profile with `base_url` pointing to `${data.coder_workspace.me.access_url}/api/v2/aibridge/openai/v1` and `env_key` pointing to the workspace owner's session token
|
- Configures Codex to use the AI Bridge profile with `base_url` pointing to `${data.coder_workspace.me.access_url}/api/v2/aibridge/openai/v1` and `env_key` pointing to the workspace owner's session token
|
||||||
|
- Sets `profile = "aibridge"` at the top of `config.toml` so Codex uses AI Bridge by default
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
|
profile = "aibridge"
|
||||||
|
|
||||||
[model_providers.aibridge]
|
[model_providers.aibridge]
|
||||||
name = "AI Bridge"
|
name = "AI Bridge"
|
||||||
base_url = "https://example.coder.com/api/v2/aibridge/openai/v1"
|
base_url = "https://example.coder.com/api/v2/aibridge/openai/v1"
|
||||||
@ -75,7 +95,7 @@ model = "<model>" # as configured in the module input
|
|||||||
model_reasoning_effort = "<model_reasoning_effort>" # as configured in the module input
|
model_reasoning_effort = "<model_reasoning_effort>" # as configured in the module input
|
||||||
```
|
```
|
||||||
|
|
||||||
Codex then runs with `--profile aibridge`
|
When running `codex` manually (without the Tasks UI), it automatically uses the AI Bridge profile.
|
||||||
|
|
||||||
This allows Codex to route API requests through Coder's AI Bridge instead of directly to OpenAI's API.
|
This allows Codex to route API requests through Coder's AI Bridge instead of directly to OpenAI's API.
|
||||||
Template build will fail if `openai_api_key` is provided alongside `enable_aibridge = true`.
|
Template build will fail if `openai_api_key` is provided alongside `enable_aibridge = true`.
|
||||||
@ -94,7 +114,7 @@ data "coder_task" "me" {}
|
|||||||
|
|
||||||
module "codex" {
|
module "codex" {
|
||||||
source = "registry.coder.com/coder-labs/codex/coder"
|
source = "registry.coder.com/coder-labs/codex/coder"
|
||||||
version = "4.1.0"
|
version = "4.2.0"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
openai_api_key = "..."
|
openai_api_key = "..."
|
||||||
ai_prompt = data.coder_task.me.prompt
|
ai_prompt = data.coder_task.me.prompt
|
||||||
@ -112,7 +132,7 @@ This example shows additional configuration options for custom models, MCP serve
|
|||||||
```tf
|
```tf
|
||||||
module "codex" {
|
module "codex" {
|
||||||
source = "registry.coder.com/coder-labs/codex/coder"
|
source = "registry.coder.com/coder-labs/codex/coder"
|
||||||
version = "4.1.0"
|
version = "4.2.0"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
openai_api_key = "..."
|
openai_api_key = "..."
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
@ -174,7 +194,7 @@ network_access = true
|
|||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> To use tasks with Codex CLI, ensure you have the `openai_api_key` variable set. [Tasks Template Example](https://registry.coder.com/templates/coder-labs/tasks-docker).
|
> To use tasks with Codex CLI, ensure you have the `openai_api_key` variable set. [Tasks Template Example](https://registry.coder.com/templates/coder-labs/tasks-docker).
|
||||||
> The module automatically configures Codex with your API key and model preferences.
|
> The module automatically configures Codex with your API key and model preferences.
|
||||||
> workdir is a required variable for the module to function correctly.
|
> `workdir` is required when `enable_tasks = true` (default). For standalone CLI usage, set `enable_tasks = false` and `workdir` becomes optional.
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
|
|||||||
@ -481,5 +481,28 @@ describe("codex", async () => {
|
|||||||
expect(configToml).toContain(
|
expect(configToml).toContain(
|
||||||
"[profiles.aibridge]\n" + 'model_provider = "aibridge"',
|
"[profiles.aibridge]\n" + 'model_provider = "aibridge"',
|
||||||
);
|
);
|
||||||
|
// Verify profile = "aibridge" is set at the top of the config
|
||||||
|
expect(configToml.startsWith('profile = "aibridge"')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("codex-standalone-mode", async () => {
|
||||||
|
// Test standalone mode without tasks (enable_tasks = false)
|
||||||
|
// workdir should default to /home/coder when not explicitly provided
|
||||||
|
const { id } = await setup({
|
||||||
|
moduleVariables: {
|
||||||
|
enable_tasks: "false",
|
||||||
|
enable_aibridge: "true",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await execModuleScript(id);
|
||||||
|
|
||||||
|
const configToml = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.codex/config.toml",
|
||||||
|
);
|
||||||
|
// In standalone mode, config should still have aibridge profile set as default
|
||||||
|
expect(configToml.startsWith('profile = "aibridge"')).toBe(true);
|
||||||
|
expect(configToml).toContain("[profiles.aibridge]");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -38,7 +38,19 @@ variable "icon" {
|
|||||||
|
|
||||||
variable "workdir" {
|
variable "workdir" {
|
||||||
type = string
|
type = string
|
||||||
description = "The folder to run Codex in."
|
description = "The folder to run Codex in. Required when enable_tasks is true."
|
||||||
|
default = null
|
||||||
|
|
||||||
|
validation {
|
||||||
|
condition = var.workdir != null || !local.tasks_enabled
|
||||||
|
error_message = "workdir is required when enable_tasks is true. Set workdir or set enable_tasks = false for standalone CLI usage."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "enable_tasks" {
|
||||||
|
type = bool
|
||||||
|
description = "Enable Tasks UI for Codex (requires workdir). When false, only installs Codex CLI with config for standalone usage."
|
||||||
|
default = true
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "report_tasks" {
|
variable "report_tasks" {
|
||||||
@ -124,8 +136,8 @@ variable "openai_api_key" {
|
|||||||
|
|
||||||
variable "install_agentapi" {
|
variable "install_agentapi" {
|
||||||
type = bool
|
type = bool
|
||||||
description = "Whether to install AgentAPI."
|
description = "DEPRECATED: Use enable_tasks instead. Whether to install AgentAPI."
|
||||||
default = true
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "agentapi_version" {
|
variable "agentapi_version" {
|
||||||
@ -184,7 +196,9 @@ resource "coder_env" "coder_aibridge_session_token" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
workdir = trimsuffix(var.workdir, "/")
|
# Use enable_tasks, but fall back to install_agentapi if explicitly set (for backward compat)
|
||||||
|
tasks_enabled = var.install_agentapi != null ? var.install_agentapi : var.enable_tasks
|
||||||
|
workdir = var.workdir != null ? trimsuffix(var.workdir, "/") : "/home/coder"
|
||||||
app_slug = "codex"
|
app_slug = "codex"
|
||||||
install_script = file("${path.module}/scripts/install.sh")
|
install_script = file("${path.module}/scripts/install.sh")
|
||||||
start_script = file("${path.module}/scripts/start.sh")
|
start_script = file("${path.module}/scripts/start.sh")
|
||||||
@ -218,7 +232,7 @@ module "agentapi" {
|
|||||||
cli_app_slug = var.cli_app ? "${local.app_slug}-cli" : null
|
cli_app_slug = var.cli_app ? "${local.app_slug}-cli" : null
|
||||||
cli_app_display_name = var.cli_app ? var.cli_app_display_name : null
|
cli_app_display_name = var.cli_app ? var.cli_app_display_name : null
|
||||||
module_dir_name = local.module_dir_name
|
module_dir_name = local.module_dir_name
|
||||||
install_agentapi = var.install_agentapi
|
install_agentapi = local.tasks_enabled
|
||||||
agentapi_subdomain = var.subdomain
|
agentapi_subdomain = var.subdomain
|
||||||
agentapi_version = var.agentapi_version
|
agentapi_version = var.agentapi_version
|
||||||
pre_install_script = var.pre_install_script
|
pre_install_script = var.pre_install_script
|
||||||
|
|||||||
@ -151,6 +151,15 @@ function populate_config_toml() {
|
|||||||
write_minimal_default_config "$CONFIG_PATH"
|
write_minimal_default_config "$CONFIG_PATH"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Set aibridge as default profile when AI Bridge is enabled
|
||||||
|
# This allows users to run `codex` without --profile flag
|
||||||
|
if [ "$ARG_ENABLE_AIBRIDGE" = "true" ]; then
|
||||||
|
printf "Setting aibridge as default profile\n"
|
||||||
|
local temp_config
|
||||||
|
temp_config=$(cat "$CONFIG_PATH")
|
||||||
|
echo -e "profile = \"aibridge\"\n\n$temp_config" > "$CONFIG_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
append_mcp_servers_section "$CONFIG_PATH"
|
append_mcp_servers_section "$CONFIG_PATH"
|
||||||
|
|
||||||
if [ "$ARG_ENABLE_AIBRIDGE" = "true" ]; then
|
if [ "$ARG_ENABLE_AIBRIDGE" = "true" ]; then
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user