feat: remove the responsibility of running install and start script from agentapi module

This commit is contained in:
35C4n0r 2026-02-05 16:17:12 +00:00
parent 80f47d09dd
commit 4459d39529
6 changed files with 30 additions and 144 deletions

View File

@ -16,41 +16,21 @@ The AgentAPI module is a building block for modules that need to run an AgentAPI
```tf
module "agentapi" {
source = "registry.coder.com/coder/agentapi/coder"
version = "3.0.0"
version = "4.0.0"
agent_id = var.agent_id
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 = "Goose"
cli_app_slug = "goose-cli"
cli_app_display_name = "Goose CLI"
web_app_display_name = "ClaudeCode"
cli_app_slug = "claude-cli"
cli_app_display_name = "Claude CLI"
module_dir_name = local.module_dir_name
agentapi_server_type = "claude"
install_agentapi = var.install_agentapi
pre_install_script = var.pre_install_script
post_install_script = var.post_install_script
start_script = local.start_script
agentapi_server_type = "claude" # required
agentapi_term_width = 67 # default: 67
agentapi_term_height = 1190 # default: 1190
agentapi_initial_prompt = "You are a helpful assistant." # optional
install_script = <<-EOT
#!/bin/bash
set -o errexit
set -o pipefail
echo -n '${base64encode(local.install_script)}' | base64 -d > /tmp/install.sh
chmod +x /tmp/install.sh
ARG_PROVIDER='${var.goose_provider}' \
ARG_MODEL='${var.goose_model}' \
ARG_GOOSE_CONFIG="$(echo -n '${base64encode(local.combined_extensions)}' | base64 -d)" \
ARG_INSTALL='${var.install_goose}' \
ARG_GOOSE_VERSION='${var.goose_version}' \
/tmp/install.sh
EOT
agentapi_server_type = "claude"
agentapi_term_width = 67
agentapi_term_height = 1190
}
```
@ -71,11 +51,11 @@ module "agentapi" {
For a complete example of how to use this module, see the [Goose module](https://github.com/coder/registry/blob/main/registry/coder/modules/goose/main.tf).
### Start script behavior
### agent-command.sh
The `start_script` should write the agent command to `$module_path/agent-command.sh` instead of starting the AgentAPI server directly.
The calling module must create an executable script at `$HOME/{module_dir_name}/agent-command.sh` before this module's script runs. This script should contain the command to start your AI agent.
Example start script:
Example:
```bash
#!/bin/bash
@ -85,6 +65,6 @@ cat > "$module_path/agent-command.sh" << EOF
#!/bin/bash
my-agent-command --my-agent-flags
EOF
chmod +x "$module_path/agent-command.sh"
```
The AgentAPI module will run this script with the agentapi server.

View File

@ -60,7 +60,6 @@ const setup = async (props?: SetupProps): Promise<{ id: string }> => {
agentapi_version: "latest",
agentapi_server_type: "claude",
module_dir_name: moduleDirName,
start_script: await loadTestFile(import.meta.dir, "agentapi-start.sh"),
folder: projectDir,
...props?.moduleVariables,
},
@ -69,11 +68,23 @@ const setup = async (props?: SetupProps): Promise<{ id: string }> => {
skipAgentAPIMock: props?.skipAgentAPIMock,
moduleDir: import.meta.dir,
});
// Create the ai agent mock binary
await writeExecutable({
containerId: id,
filePath: "/usr/bin/aiagent",
content: await loadTestFile(import.meta.dir, "ai-agent-mock.js"),
});
// Create the agent-command.sh script that the module expects
await execContainer(id, [
"bash",
"-c",
`mkdir -p /home/coder/${moduleDirName}`,
]);
await writeExecutable({
containerId: id,
filePath: `/home/coder/${moduleDirName}/agent-command.sh`,
content: "#!/bin/bash\nexec aiagent",
});
return { id };
};
@ -105,36 +116,6 @@ describe("agentapi", async () => {
await expectAgentAPIStarted(id, 3827);
});
test("pre-post-install-scripts", async () => {
const { id } = await setup({
moduleVariables: {
pre_install_script: `#!/bin/bash\necho "pre-install"`,
install_script: `#!/bin/bash\necho "install"`,
post_install_script: `#!/bin/bash\necho "post-install"`,
},
});
await execModuleScript(id);
await expectAgentAPIStarted(id);
const preInstallLog = await readFileContainer(
id,
`/home/coder/${moduleDirName}/pre_install.log`,
);
const installLog = await readFileContainer(
id,
`/home/coder/${moduleDirName}/install.log`,
);
const postInstallLog = await readFileContainer(
id,
`/home/coder/${moduleDirName}/post_install.log`,
);
expect(preInstallLog).toContain("pre-install");
expect(installLog).toContain("install");
expect(postInstallLog).toContain("post-install");
});
test("install-agentapi", async () => {
const { id } = await setup({ skipAgentAPIMock: true });
@ -161,12 +142,12 @@ describe("agentapi", async () => {
expect(respModuleScript.exitCode).toBe(0);
await expectAgentAPIStarted(id);
const agentApiStartLog = await readFileContainer(
const agentApiMockLog = await readFileContainer(
id,
"/home/coder/test-agentapi-start.log",
"/home/coder/agentapi-mock.log",
);
expect(agentApiStartLog).toContain(
"Using AGENTAPI_CHAT_BASE_PATH: /@default/default.foo/apps/agentapi-web/chat",
expect(agentApiMockLog).toContain(
"AGENTAPI_CHAT_BASE_PATH: /@default/default.foo/apps/agentapi-web/chat",
);
});

View File

@ -87,29 +87,6 @@ variable "cli_app_slug" {
description = "The slug of the CLI workspace app."
}
variable "pre_install_script" {
type = string
description = "Custom script to run before installing the agent used by AgentAPI."
default = null
}
variable "install_script" {
type = string
description = "Script to install the agent used by AgentAPI."
default = ""
}
variable "post_install_script" {
type = string
description = "Custom script to run after installing the agent used by AgentAPI."
default = null
}
variable "start_script" {
type = string
description = "Script that starts AgentAPI."
}
variable "install_agentapi" {
type = bool
description = "Whether to install AgentAPI."
@ -191,11 +168,7 @@ variable "module_dir_name" {
locals {
# we always trim the slash for consistency
workdir = trimsuffix(var.folder, "/")
encoded_pre_install_script = var.pre_install_script != null ? base64encode(var.pre_install_script) : ""
encoded_install_script = var.install_script != null ? base64encode(var.install_script) : ""
encoded_post_install_script = var.post_install_script != null ? base64encode(var.post_install_script) : ""
encoded_initial_prompt = var.agentapi_initial_prompt != null ? base64encode(var.agentapi_initial_prompt) : ""
agentapi_start_script_b64 = base64encode(var.start_script)
agentapi_wait_for_start_script_b64 = base64encode(file("${path.module}/scripts/agentapi-wait-for-start.sh"))
// Chat base path is only set if not using a subdomain.
// NOTE:
@ -210,7 +183,7 @@ locals {
resource "coder_script" "agentapi" {
agent_id = var.agent_id
display_name = "Install and start AgentAPI"
display_name = "Start AgentAPI"
icon = var.web_app_icon
script = <<-EOT
#!/bin/bash
@ -222,13 +195,9 @@ resource "coder_script" "agentapi" {
ARG_MODULE_DIR_NAME='${var.module_dir_name}' \
ARG_WORKDIR="$(echo -n '${base64encode(local.workdir)}' | base64 -d)" \
ARG_PRE_INSTALL_SCRIPT="$(echo -n '${local.encoded_pre_install_script}' | base64 -d)" \
ARG_INSTALL_SCRIPT="$(echo -n '${local.encoded_install_script}' | base64 -d)" \
ARG_INSTALL_AGENTAPI='${var.install_agentapi}' \
ARG_AGENTAPI_VERSION='${var.agentapi_version}' \
ARG_START_SCRIPT="$(echo -n '${local.agentapi_start_script_b64}' | base64 -d)" \
ARG_WAIT_FOR_START_SCRIPT="$(echo -n '${local.agentapi_wait_for_start_script_b64}' | base64 -d)" \
ARG_POST_INSTALL_SCRIPT="$(echo -n '${local.encoded_post_install_script}' | base64 -d)" \
ARG_AGENTAPI_PORT='${var.agentapi_port}' \
ARG_AGENTAPI_SERVER_TYPE='${var.agentapi_server_type}' \
ARG_AGENTAPI_TERM_WIDTH='${var.agentapi_term_width}' \

View File

@ -5,13 +5,9 @@ set -x
set -o nounset
MODULE_DIR_NAME="$ARG_MODULE_DIR_NAME"
WORKDIR="$ARG_WORKDIR"
PRE_INSTALL_SCRIPT="$ARG_PRE_INSTALL_SCRIPT"
INSTALL_SCRIPT="$ARG_INSTALL_SCRIPT"
INSTALL_AGENTAPI="$ARG_INSTALL_AGENTAPI"
AGENTAPI_VERSION="$ARG_AGENTAPI_VERSION"
START_SCRIPT="$ARG_START_SCRIPT"
WAIT_FOR_START_SCRIPT="$ARG_WAIT_FOR_START_SCRIPT"
POST_INSTALL_SCRIPT="$ARG_POST_INSTALL_SCRIPT"
AGENTAPI_PORT="$ARG_AGENTAPI_PORT"
AGENTAPI_SERVER_TYPE="$ARG_AGENTAPI_SERVER_TYPE"
AGENTAPI_TERM_WIDTH="$ARG_AGENTAPI_TERM_WIDTH"
@ -42,17 +38,6 @@ if [ ! -d "${WORKDIR}" ]; then
mkdir -p "${WORKDIR}"
echo "Folder created successfully."
fi
if [ -n "${PRE_INSTALL_SCRIPT}" ]; then
echo "Running pre-install script..."
echo -n "${PRE_INSTALL_SCRIPT}" > "$module_path/pre_install.sh"
chmod +x "$module_path/pre_install.sh"
"$module_path/pre_install.sh" 2>&1 | tee "$module_path/pre_install.log"
fi
echo "Running install script..."
echo -n "${INSTALL_SCRIPT}" > "$module_path/install.sh"
chmod +x "$module_path/install.sh"
"$module_path/install.sh" 2>&1 | tee "$module_path/install.log"
# Install AgentAPI if enabled
if [ "${INSTALL_AGENTAPI}" = "true" ]; then
@ -90,18 +75,9 @@ if ! command_exists agentapi; then
exit 1
fi
echo -n "${START_SCRIPT}" > "$module_path/scripts/agentapi-start.sh"
echo -n "${WAIT_FOR_START_SCRIPT}" > "$module_path/scripts/agentapi-wait-for-start.sh"
chmod +x "$module_path/scripts/agentapi-start.sh"
chmod +x "$module_path/scripts/agentapi-wait-for-start.sh"
if [ -n "${POST_INSTALL_SCRIPT}" ]; then
echo "Running post-install script..."
echo -n "${POST_INSTALL_SCRIPT}" > "$module_path/post_install.sh"
chmod +x "$module_path/post_install.sh"
"$module_path/post_install.sh" 2>&1 | tee "$module_path/post_install.log"
fi
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
@ -111,9 +87,6 @@ export AGENTAPI_CHAT_BASE_PATH="${AGENTAPI_CHAT_BASE_PATH:-}"
# Disable host header check since AgentAPI is proxied by Coder (which does its own validation)
export AGENTAPI_ALLOWED_HOSTS="*"
# Call agentapi-start.sh to write agent-command.sh
"$module_path/scripts/agentapi-start.sh" &> "$module_path/agentapi-start.log"
# Build agentapi server command arguments
ARGS=(
"server"

View File

@ -9,7 +9,7 @@ const port = portIdx ? args[portIdx] : 3284;
console.log(`starting server on port ${port}`);
fs.writeFileSync(
"/home/coder/agentapi-mock.log",
`AGENTAPI_ALLOWED_HOSTS: ${process.env.AGENTAPI_ALLOWED_HOSTS}`,
`AGENTAPI_ALLOWED_HOSTS: ${process.env.AGENTAPI_ALLOWED_HOSTS}\nAGENTAPI_CHAT_BASE_PATH: ${process.env.AGENTAPI_CHAT_BASE_PATH || "not set"}`,
);
http

View File

@ -1,17 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
module_path="$HOME/.agentapi-module"
# Write the agent command to agent-command.sh
cat > "$module_path/agent-command.sh" << 'EOF'
#!/bin/bash
exec bash -c aiagent
EOF
chmod +x "$module_path/agent-command.sh"
echo "Agent command written to $module_path/agent-command.sh"
echo "Using AGENTAPI_CHAT_BASE_PATH: ${AGENTAPI_CHAT_BASE_PATH:-not set}" >> /home/coder/test-agentapi-start.log