Compare commits
1 Commits
35C4n0r/fe
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1601ab3e8b |
4
.icons/coder-modules.svg
Normal file
4
.icons/coder-modules.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect width="7" height="7" x="14" y="3" rx="1"/>
|
||||
<path d="M10 21V8a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 339 B |
5
.icons/coder-templates.svg
Normal file
5
.icons/coder-templates.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect width="18" height="7" x="3" y="3" rx="1"/>
|
||||
<rect width="9" height="7" x="3" y="14" rx="1"/>
|
||||
<rect width="5" height="7" x="16" y="14" rx="1"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 336 B |
@ -13,7 +13,7 @@ Install and configure the [Codex CLI](https://github.com/openai/codex) in your w
|
||||
```tf
|
||||
module "codex" {
|
||||
source = "registry.coder.com/coder-labs/codex/coder"
|
||||
version = "5.1.0"
|
||||
version = "5.0.0"
|
||||
agent_id = coder_agent.main.id
|
||||
openai_api_key = var.openai_api_key
|
||||
}
|
||||
@ -33,7 +33,7 @@ locals {
|
||||
|
||||
module "codex" {
|
||||
source = "registry.coder.com/coder-labs/codex/coder"
|
||||
version = "5.1.0"
|
||||
version = "5.0.0"
|
||||
agent_id = coder_agent.main.id
|
||||
workdir = local.codex_workdir
|
||||
openai_api_key = var.openai_api_key
|
||||
@ -64,7 +64,7 @@ resource "coder_app" "codex" {
|
||||
```tf
|
||||
module "codex" {
|
||||
source = "registry.coder.com/coder-labs/codex/coder"
|
||||
version = "5.1.0"
|
||||
version = "5.0.0"
|
||||
agent_id = coder_agent.main.id
|
||||
workdir = "/home/coder/project"
|
||||
enable_ai_gateway = true
|
||||
@ -88,7 +88,7 @@ When `enable_ai_gateway = true`, the module configures Codex to use the `aigatew
|
||||
```tf
|
||||
module "codex" {
|
||||
source = "registry.coder.com/coder-labs/codex/coder"
|
||||
version = "5.1.0"
|
||||
version = "5.0.0"
|
||||
agent_id = coder_agent.main.id
|
||||
workdir = "/home/coder/project"
|
||||
openai_api_key = var.openai_api_key
|
||||
@ -107,26 +107,9 @@ module "codex" {
|
||||
args = ["-y", "@modelcontextprotocol/server-github"]
|
||||
type = "stdio"
|
||||
EOT
|
||||
|
||||
mcp_config_remote_path = [
|
||||
"https://example.com/team-mcp-servers.toml",
|
||||
"https://raw.githubusercontent.com/your-org/your-repo/main/.codex/mcp.toml",
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Servers configured through `mcp` or `mcp_config_remote_path` are appended to `~/.codex/config.toml`, so they apply to every Codex session in the workspace. Each remote URL should return a body in Codex's native TOML format, e.g.:
|
||||
>
|
||||
> ```toml
|
||||
> [mcp_servers.my-tool]
|
||||
> command = "my-tool-server"
|
||||
> args = ["--port", "8080"]
|
||||
> type = "stdio"
|
||||
> ```
|
||||
>
|
||||
> Fetch failures (network errors or non-2xx responses) log a warning and the install continues with the remaining URLs. Bodies are appended verbatim without further validation, so make sure the URL returns valid Codex TOML.
|
||||
|
||||
### Serialize a downstream `coder_script` after the install pipeline
|
||||
|
||||
The module exposes the `scripts` output: an ordered list of `coder exp sync` names for the scripts this module creates (pre_install, install, post_install). Scripts that were not configured are absent.
|
||||
@ -134,7 +117,7 @@ The module exposes the `scripts` output: an ordered list of `coder exp sync` nam
|
||||
```tf
|
||||
module "codex" {
|
||||
source = "registry.coder.com/coder-labs/codex/coder"
|
||||
version = "5.1.0"
|
||||
version = "5.0.0"
|
||||
agent_id = coder_agent.main.id
|
||||
openai_api_key = var.openai_api_key
|
||||
}
|
||||
|
||||
@ -425,86 +425,6 @@ describe("codex", async () => {
|
||||
expect(installLog).toContain("Installed Codex CLI");
|
||||
});
|
||||
|
||||
test("mcp-config-remote-path", async () => {
|
||||
const remoteToml = [
|
||||
"[mcp_servers.remote-fetched]",
|
||||
'command = "remote-mcp-cmd"',
|
||||
'args = ["--from-url"]',
|
||||
'type = "stdio"',
|
||||
].join("\n");
|
||||
const projectDir = "/home/coder/project";
|
||||
const moduleDir = path.resolve(import.meta.dir);
|
||||
const state = await runTerraformApply(moduleDir, {
|
||||
agent_id: "foo",
|
||||
workdir: projectDir,
|
||||
install_codex: "false",
|
||||
mcp_config_remote_path: JSON.stringify([
|
||||
"http://localhost:19999/mcp.toml",
|
||||
"file:///tmp/remote-mcp.toml",
|
||||
]),
|
||||
});
|
||||
const scripts = collectScripts(state);
|
||||
const coderEnvVars = extractCoderEnvVars(state);
|
||||
|
||||
const id = await runContainer("codercom/enterprise-node:latest");
|
||||
registerCleanup(async () => {
|
||||
if (process.env["DEBUG"] === "true" || process.env["DEBUG"] === "1") {
|
||||
console.log(`Not removing container ${id} in debug mode`);
|
||||
return;
|
||||
}
|
||||
await removeContainer(id);
|
||||
});
|
||||
|
||||
await execContainer(id, ["bash", "-c", `mkdir -p '${projectDir}'`]);
|
||||
await writeExecutable({
|
||||
containerId: id,
|
||||
filePath: "/usr/bin/coder",
|
||||
content: "#!/bin/bash\nexit 0\n",
|
||||
});
|
||||
await writeExecutable({
|
||||
containerId: id,
|
||||
filePath: "/usr/bin/codex",
|
||||
content: await Bun.file(
|
||||
path.join(moduleDir, "testdata", "codex-mock.sh"),
|
||||
).text(),
|
||||
});
|
||||
// Drop the remote TOML payload at a path the install script will fetch
|
||||
// via file://. Keeps the test self-contained (no external network).
|
||||
await execContainer(id, [
|
||||
"bash",
|
||||
"-c",
|
||||
`cat > /tmp/remote-mcp.toml <<'EOF'\n${remoteToml}\nEOF`,
|
||||
]);
|
||||
|
||||
await runScripts(id, scripts, coderEnvVars);
|
||||
|
||||
const installLog = await readFileContainer(
|
||||
id,
|
||||
"/home/coder/.coder-modules/coder-labs/codex/logs/install.log",
|
||||
);
|
||||
// Both URLs were attempted.
|
||||
expect(installLog).toContain("http://localhost:19999/mcp.toml");
|
||||
expect(installLog).toContain("file:///tmp/remote-mcp.toml");
|
||||
// First URL fails gracefully.
|
||||
expect(installLog).toContain(
|
||||
"Warning: Failed to fetch MCP configuration from 'http://localhost:19999/mcp.toml'",
|
||||
);
|
||||
// Second URL succeeds.
|
||||
expect(installLog).not.toContain(
|
||||
"Warning: Failed to fetch MCP configuration from 'file:///tmp/remote-mcp.toml'",
|
||||
);
|
||||
expect(installLog).toContain(
|
||||
"Appending MCP servers from file:///tmp/remote-mcp.toml",
|
||||
);
|
||||
|
||||
const configToml = await readFileContainer(
|
||||
id,
|
||||
"/home/coder/.codex/config.toml",
|
||||
);
|
||||
expect(configToml).toContain("[mcp_servers.remote-fetched]");
|
||||
expect(configToml).toContain('command = "remote-mcp-cmd"');
|
||||
});
|
||||
|
||||
test("custom-config-drops-reasoning-effort", async () => {
|
||||
const baseConfig = [
|
||||
'sandbox_mode = "danger-full-access"',
|
||||
|
||||
@ -88,12 +88,6 @@ variable "mcp" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "mcp_config_remote_path" {
|
||||
type = list(string)
|
||||
description = "List of URLs that return MCP server configurations in TOML format (matching Codex's native config format). Fetched at install time and appended to config.toml."
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "model_reasoning_effort" {
|
||||
type = string
|
||||
description = "The reasoning effort for the model. One of: none, minimal, low, medium, high, xhigh. See https://platform.openai.com/docs/guides/latest-model#lower-reasoning-effort"
|
||||
@ -147,7 +141,6 @@ locals {
|
||||
ARG_WORKDIR = local.workdir != "" ? base64encode(local.workdir) : ""
|
||||
ARG_BASE_CONFIG_TOML = var.base_config_toml != "" ? base64encode(var.base_config_toml) : ""
|
||||
ARG_MCP = var.mcp != "" ? base64encode(var.mcp) : ""
|
||||
ARG_MCP_CONFIG_REMOTE_PATH = base64encode(jsonencode(var.mcp_config_remote_path))
|
||||
ARG_ENABLE_AI_GATEWAY = tostring(var.enable_ai_gateway)
|
||||
ARG_AIBRIDGE_CONFIG = var.enable_ai_gateway ? base64encode(local.aibridge_config) : ""
|
||||
ARG_MODEL_REASONING_EFFORT = var.model_reasoning_effort
|
||||
|
||||
@ -183,34 +183,3 @@ run "test_workdir_optional" {
|
||||
error_message = "scripts output should have install script even without workdir"
|
||||
}
|
||||
}
|
||||
|
||||
run "test_mcp_config_remote_path" {
|
||||
command = plan
|
||||
|
||||
variables {
|
||||
agent_id = "test-agent"
|
||||
workdir = "/home/coder"
|
||||
mcp_config_remote_path = [
|
||||
"https://example.com/mcp-one.toml",
|
||||
"https://example.com/mcp-two.toml",
|
||||
]
|
||||
}
|
||||
|
||||
assert {
|
||||
condition = strcontains(local.install_script, base64encode(jsonencode(var.mcp_config_remote_path)))
|
||||
error_message = "install script should embed the base64-encoded mcp_config_remote_path JSON"
|
||||
}
|
||||
}
|
||||
|
||||
run "test_mcp_config_remote_path_default" {
|
||||
command = plan
|
||||
|
||||
variables {
|
||||
agent_id = "test-agent"
|
||||
}
|
||||
|
||||
assert {
|
||||
condition = length(var.mcp_config_remote_path) == 0
|
||||
error_message = "mcp_config_remote_path should default to an empty list"
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,6 @@ ARG_CODEX_VERSION=$(echo -n '${ARG_CODEX_VERSION}' | base64 -d)
|
||||
ARG_WORKDIR=$(echo -n '${ARG_WORKDIR}' | base64 -d)
|
||||
ARG_BASE_CONFIG_TOML=$(echo -n '${ARG_BASE_CONFIG_TOML}' | base64 -d)
|
||||
ARG_MCP=$(echo -n '${ARG_MCP}' | base64 -d)
|
||||
ARG_MCP_CONFIG_REMOTE_PATH=$(echo -n '${ARG_MCP_CONFIG_REMOTE_PATH}' | base64 -d)
|
||||
ARG_ENABLE_AI_GATEWAY='${ARG_ENABLE_AI_GATEWAY}'
|
||||
ARG_AIBRIDGE_CONFIG=$(echo -n '${ARG_AIBRIDGE_CONFIG}' | base64 -d)
|
||||
ARG_MODEL_REASONING_EFFORT='${ARG_MODEL_REASONING_EFFORT}'
|
||||
@ -25,7 +24,6 @@ printf "workdir: %s\n" "$${ARG_WORKDIR}"
|
||||
printf "enable_ai_gateway: %s\n" "$${ARG_ENABLE_AI_GATEWAY}"
|
||||
printf "install_codex: %s\n" "$${ARG_INSTALL}"
|
||||
printf "model_reasoning_effort: %s\n" "$${ARG_MODEL_REASONING_EFFORT}"
|
||||
printf "mcp_config_remote_path: %s\n" "$${ARG_MCP_CONFIG_REMOTE_PATH}"
|
||||
echo "--------------------------------"
|
||||
|
||||
function add_path_to_shell_profiles() {
|
||||
@ -157,22 +155,6 @@ function populate_config_toml() {
|
||||
echo "$${ARG_MCP}" >> "$${config_path}"
|
||||
fi
|
||||
|
||||
if [ -n "$${ARG_MCP_CONFIG_REMOTE_PATH}" ] && [ "$${ARG_MCP_CONFIG_REMOTE_PATH}" != "[]" ]; then
|
||||
if ! command -v jq > /dev/null 2>&1; then
|
||||
printf "Error: 'jq' is required to process mcp_config_remote_path but was not found. Skipping remote MCP config fetch.\n" >&2
|
||||
else
|
||||
for url in $(echo "$${ARG_MCP_CONFIG_REMOTE_PATH}" | jq -r '.[]'); do
|
||||
echo "Fetching MCP configuration from: $${url}"
|
||||
mcp_toml=$(curl -fsSL "$${url}") || {
|
||||
echo "Warning: Failed to fetch MCP configuration from '$${url}', continuing..."
|
||||
continue
|
||||
}
|
||||
printf "Appending MCP servers from %s\n" "$${url}"
|
||||
printf '\n%s\n' "$${mcp_toml}" >> "$${config_path}"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$${ARG_ENABLE_AI_GATEWAY}" = "true" ] && [ -n "$${ARG_AIBRIDGE_CONFIG}" ]; then
|
||||
if ! grep -q '\[model_providers\.aigateway\]' "$${config_path}" 2>/dev/null; then
|
||||
printf "Adding AI Gateway configuration\n"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user