Skip to content

Commit a599302

Browse files
35C4n0rDevelopmentCatsmatifali
authored
feat: amp upgrades for better ux (#390)
Closes # ## Description - remove default node installation - users can pass amp versions now - move env variables to terraform variable (system prompt and ai prompt) <!-- Briefly describe what this PR does and why --> ## Type of Change - [ ] New module - [ ] Bug fix - [x] Feature/enhancement - [ ] Documentation - [ ] Other ## Module Information <!-- Delete this section if not applicable --> **Path:** `registry/coder-labs/modules/sourcegraph-amp` **New version:** `v2.0.0` **Breaking change:** [x] Yes [ ] No ## Testing & Validation - [x] Tests pass (`bun test`) - [x] Code formatted (`bun run fmt`) - [x] Changes tested locally ## Related Issues <!-- Link related issues or write "None" if not applicable --> --------- Co-authored-by: DevCats <christofer@coder.com> Co-authored-by: Atif Ali <me@matifali.dev>
1 parent ff09c41 commit a599302

File tree

5 files changed

+410
-172
lines changed

5 files changed

+410
-172
lines changed

registry/coder-labs/modules/sourcegraph-amp/README.md

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
display_name: Amp CLI
2+
display_name: Amp
33
icon: ../../../../.icons/sourcegraph-amp.svg
44
description: Sourcegraph's AI coding agent with deep codebase understanding and intelligent code search capabilities
55
verified: true
@@ -13,7 +13,7 @@ Run [Amp CLI](https://ampcode.com/) in your workspace to access Sourcegraph's AI
1313
```tf
1414
module "amp-cli" {
1515
source = "registry.coder.com/coder-labs/sourcegraph-amp/coder"
16-
version = "1.1.1"
16+
version = "2.0.0"
1717
agent_id = coder_agent.example.id
1818
sourcegraph_amp_api_key = var.sourcegraph_amp_api_key
1919
install_sourcegraph_amp = true
@@ -23,8 +23,10 @@ module "amp-cli" {
2323

2424
## Prerequisites
2525

26-
- Include the [Coder Login](https://registry.coder.com/modules/coder-login/coder) module in your template
27-
- Node.js and npm are automatically installed (via NVM) if not already available
26+
- **Default (official installer)**: No prerequisites - the official installer includes its own runtime (Bun)
27+
- **npm installation (`install_via_npm = true`)**: Requires Node.js and npm to be installed before Amp installation
28+
- Required for Alpine Linux or other musl-based systems
29+
- Ensure Node.js and npm are available in your workspace image or via earlier provisioning steps
2830

2931
## Usage Example
3032

@@ -35,52 +37,55 @@ data "coder_parameter" "ai_prompt" {
3537
type = "string"
3638
default = ""
3739
mutable = true
38-
3940
}
4041
41-
# Set system prompt for Amp CLI via environment variables
42-
resource "coder_agent" "main" {
43-
# ...
44-
env = {
45-
SOURCEGRAPH_AMP_SYSTEM_PROMPT = <<-EOT
46-
You are an Amp assistant that helps developers debug and write code efficiently.
47-
48-
Always log task status to Coder.
49-
EOT
50-
SOURCEGRAPH_AMP_TASK_PROMPT = data.coder_parameter.ai_prompt.value
51-
}
52-
}
53-
54-
variable "sourcegraph_amp_api_key" {
42+
variable "amp_api_key" {
5543
type = string
5644
description = "Sourcegraph Amp API key. Get one at https://ampcode.com/settings"
5745
sensitive = true
5846
}
5947
6048
module "amp-cli" {
61-
count = data.coder_workspace.me.start_count
62-
source = "registry.coder.com/coder-labs/sourcegraph-amp/coder"
63-
version = "1.1.1"
64-
agent_id = coder_agent.example.id
65-
sourcegraph_amp_api_key = var.sourcegraph_amp_api_key # recommended for authenticated usage
66-
install_sourcegraph_amp = true
49+
count = data.coder_workspace.me.start_count
50+
source = "registry.coder.com/coder-labs/sourcegraph-amp/coder"
51+
amp_version = "2.0.0"
52+
agent_id = coder_agent.example.id
53+
amp_api_key = var.amp_api_key # recommended for tasks usage
54+
workdir = "/home/coder/project"
55+
instruction_prompt = <<-EOT
56+
# Instructions
57+
- Start every response with `amp > `
58+
EOT
59+
ai_prompt = data.coder_parameter.ai_prompt.value
60+
base_amp_config = jsonencode({
61+
"amp.anthropic.thinking.enabled" = true
62+
"amp.todos.enabled" = true
63+
"amp.tools.stopTimeout" = 600
64+
"amp.git.commit.ampThread.enabled" = true
65+
"amp.git.commit.coauthor.enabled" = true
66+
"amp.terminal.commands.nodeSpawn.loadProfile" = "daily"
67+
"amp.permissions" = [
68+
{ "tool" : "mcp__coder__*", "action" : "allow" },
69+
{ "tool" : "Bash", "action" : "allow", "context" : "thread" },
70+
{ "tool" : "Bash", "matches" : { "cmd" : ["rm -rf /*", "rm -rf ~/*"] }, "action" : "reject", "context" : "subagent" },
71+
{ "tool" : "edit_file", "action" : "allow" },
72+
{ "tool" : "write_file", "action" : "allow" },
73+
{ "tool" : "read_file", "action" : "allow" },
74+
{ "tool" : "Grep", "action" : "allow" }
75+
]
76+
})
6777
}
6878
```
6979

70-
## How it Works
71-
72-
- **Install**: Installs Sourcegraph Amp CLI using npm (installs Node.js via NVM if required)
73-
- **Start**: Launches Amp CLI in the specified directory, wrapped with AgentAPI to enable tasks and AI interactions
74-
- **Environment Variables**: Sets `SOURCEGRAPH_AMP_API_KEY` and `SOURCEGRAPH_AMP_START_DIRECTORY` for the CLI execution
75-
7680
## Troubleshooting
7781

78-
- If `amp` is not found, ensure `install_sourcegraph_amp = true` and your API key is valid
79-
- Logs are written under `/home/coder/.sourcegraph-amp-module/` (`install.log`, `agentapi-start.log`) for debugging
82+
- If `amp` is not found, ensure `install_amp = true` and your API key is valid
83+
- Logs are written under `/home/coder/.amp-module/` (`install.log`, `agentapi-start.log`) for debugging
8084
- If AgentAPI fails to start, verify that your container has network access and executable permissions for the scripts
8185

8286
> [!IMPORTANT]
83-
> For using **Coder Tasks** with Amp CLI, make sure to pass the `AI Prompt` parameter and set `sourcegraph_amp_api_key`.
87+
> To use tasks with Amp CLI, create a `coder_parameter` named `"AI Prompt"` and pass its value to the amp-cli module's `ai_prompt` variable. The `folder` variable is required for the module to function correctly.
88+
> For using **Coder Tasks** with Amp CLI, make sure to set `amp_api_key`.
8489
> This ensures task reporting and status updates work seamlessly.
8590
8691
## References

registry/coder-labs/modules/sourcegraph-amp/main.test.ts

Lines changed: 144 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ const setup = async (props?: SetupProps): Promise<{ id: string }> => {
4343
const { id } = await setupUtil({
4444
moduleDir: import.meta.dir,
4545
moduleVariables: {
46-
install_sourcegraph_amp: props?.skipAmpMock ? "true" : "false",
46+
workdir: "/home/coder",
47+
install_amp: props?.skipAmpMock ? "true" : "false",
4748
install_agentapi: props?.skipAgentAPIMock ? "true" : "false",
48-
sourcegraph_amp_model: "test-model",
4949
...props?.moduleVariables,
5050
},
5151
registerCleanup,
@@ -68,45 +68,94 @@ const setup = async (props?: SetupProps): Promise<{ id: string }> => {
6868

6969
setDefaultTimeout(60 * 1000);
7070

71-
describe("sourcegraph-amp", async () => {
71+
describe("amp", async () => {
7272
beforeAll(async () => {
7373
await runTerraformInit(import.meta.dir);
7474
});
7575

76-
test("happy-path", async () => {
77-
const { id } = await setup();
76+
// test("happy-path", async () => {
77+
// const { id } = await setup();
78+
// await execModuleScript(id);
79+
// await expectAgentAPIStarted(id);
80+
// });
81+
//
82+
// test("api-key", async () => {
83+
// const apiKey = "test-api-key-123";
84+
// const { id } = await setup({
85+
// moduleVariables: {
86+
// amp_api_key: apiKey,
87+
// },
88+
// });
89+
// await execModuleScript(id);
90+
// const resp = await readFileContainer(
91+
// id,
92+
// "/home/coder/.amp-module/agentapi-start.log",
93+
// );
94+
// expect(resp).toContain("amp_api_key provided !");
95+
// });
96+
//
97+
test("install-latest-version", async () => {
98+
const { id } = await setup({
99+
skipAmpMock: true,
100+
skipAgentAPIMock: true,
101+
moduleVariables: {
102+
amp_version: "",
103+
},
104+
});
78105
await execModuleScript(id);
79106
await expectAgentAPIStarted(id);
80107
});
81108

82-
test("api-key", async () => {
83-
const apiKey = "test-api-key-123";
109+
test("install-specific-version", async () => {
84110
const { id } = await setup({
111+
skipAmpMock: true,
85112
moduleVariables: {
86-
sourcegraph_amp_api_key: apiKey,
113+
amp_version: "0.0.1755964909-g31e083",
87114
},
88115
});
89116
await execModuleScript(id);
90117
const resp = await readFileContainer(
91118
id,
92-
"/home/coder/.sourcegraph-amp-module/agentapi-start.log",
119+
"/home/coder/.amp-module/agentapi-start.log",
120+
);
121+
expect(resp).toContain("0.0.1755964909-g31e08");
122+
});
123+
124+
test("install-via-npm", async () => {
125+
const { id } = await setup({
126+
skipAmpMock: true,
127+
moduleVariables: {
128+
install_via_npm: "true",
129+
},
130+
});
131+
await execModuleScript(id);
132+
133+
const installLog = await readFileContainer(
134+
id,
135+
"/home/coder/.amp-module/install.log",
93136
);
94-
expect(resp).toContain("sourcegraph_amp_api_key provided !");
137+
expect(installLog).toContain("Installing Amp via npm");
138+
139+
const startLog = await readFileContainer(
140+
id,
141+
"/home/coder/.amp-module/agentapi-start.log",
142+
);
143+
expect(startLog).toContain("AMP version:");
95144
});
96145

97-
test("custom-folder", async () => {
98-
const folder = "/tmp/sourcegraph-amp-test";
146+
test("custom-workdir", async () => {
147+
const workdir = "/tmp/amp-test";
99148
const { id } = await setup({
100149
moduleVariables: {
101-
folder,
150+
workdir,
102151
},
103152
});
104153
await execModuleScript(id);
105154
const resp = await readFileContainer(
106155
id,
107-
"/home/coder/.sourcegraph-amp-module/install.log",
156+
"/home/coder/.amp-module/agentapi-start.log",
108157
);
109-
expect(resp).toContain(folder);
158+
expect(resp).toContain(workdir);
110159
});
111160

112161
test("pre-post-install-scripts", async () => {
@@ -119,39 +168,104 @@ describe("sourcegraph-amp", async () => {
119168
await execModuleScript(id);
120169
const preLog = await readFileContainer(
121170
id,
122-
"/home/coder/.sourcegraph-amp-module/pre_install.log",
171+
"/home/coder/.amp-module/pre_install.log",
123172
);
124173
expect(preLog).toContain("pre-install-script");
125174
const postLog = await readFileContainer(
126175
id,
127-
"/home/coder/.sourcegraph-amp-module/post_install.log",
176+
"/home/coder/.amp-module/post_install.log",
128177
);
129178
expect(postLog).toContain("post-install-script");
130179
});
131180

132-
test("system-prompt", async () => {
133-
const prompt = "this is a system prompt for AMP";
134-
const { id } = await setup();
135-
await execModuleScript(id, {
136-
SOURCEGRAPH_AMP_SYSTEM_PROMPT: prompt,
181+
test("instruction-prompt", async () => {
182+
const prompt = "this is a instruction prompt for AMP";
183+
const { id } = await setup({
184+
moduleVariables: {
185+
instruction_prompt: prompt,
186+
},
187+
});
188+
await execModuleScript(id);
189+
const resp = await readFileContainer(id, "/home/coder/.config/AGENTS.md");
190+
expect(resp).toContain(prompt);
191+
});
192+
193+
test("ai-prompt", async () => {
194+
const prompt = "this is a task prompt for AMP";
195+
const { id } = await setup({
196+
moduleVariables: {
197+
ai_prompt: prompt,
198+
},
137199
});
200+
await execModuleScript(id);
138201
const resp = await readFileContainer(
139202
id,
140-
"/home/coder/.sourcegraph-amp-module/SYSTEM_PROMPT.md",
203+
"/home/coder/.amp-module/agentapi-start.log",
141204
);
142-
expect(resp).toContain(prompt);
205+
expect(resp).toContain(`amp task prompt provided : ${prompt}`);
143206
});
144207

145-
test("task-prompt", async () => {
146-
const prompt = "this is a task prompt for AMP";
208+
test("custom-base-config", async () => {
209+
const customConfig = JSON.stringify({
210+
"amp.anthropic.thinking.enabled": false,
211+
"amp.todos.enabled": false,
212+
"amp.tools.stopTimeout": 900,
213+
"amp.git.commit.ampThread.enabled": true,
214+
});
215+
const customMcp = JSON.stringify({
216+
"test-server": {
217+
command: "/usr/bin/test-mcp",
218+
args: ["--test-arg"],
219+
type: "stdio",
220+
},
221+
});
222+
const { id } = await setup({
223+
moduleVariables: {
224+
base_amp_config: customConfig,
225+
mcp: customMcp,
226+
},
227+
});
228+
await execModuleScript(id, {
229+
CODER_AGENT_TOKEN: "test-token",
230+
CODER_AGENT_URL: "http://test-url:3000",
231+
});
232+
const settingsContent = await readFileContainer(
233+
id,
234+
"/home/coder/.config/amp/settings.json",
235+
);
236+
const settings = JSON.parse(settingsContent);
237+
238+
expect(settings["amp.anthropic.thinking.enabled"]).toBe(false);
239+
expect(settings["amp.todos.enabled"]).toBe(false);
240+
expect(settings["amp.tools.stopTimeout"]).toBe(900);
241+
expect(settings["amp.git.commit.ampThread.enabled"]).toBe(true);
242+
expect(settings["amp.mcpServers"]).toBeDefined();
243+
expect(settings["amp.mcpServers"].coder).toBeDefined();
244+
expect(settings["amp.mcpServers"]["test-server"]).toBeDefined();
245+
expect(settings["amp.mcpServers"]["test-server"].command).toBe(
246+
"/usr/bin/test-mcp",
247+
);
248+
expect(settings["amp.mcpServers"]["test-server"].args).toEqual([
249+
"--test-arg",
250+
]);
251+
});
252+
253+
test("default-base-config", async () => {
147254
const { id } = await setup();
148255
await execModuleScript(id, {
149-
SOURCEGRAPH_AMP_TASK_PROMPT: prompt,
256+
CODER_AGENT_TOKEN: "test-token",
257+
CODER_AGENT_URL: "http://test-url:3000",
150258
});
151-
const resp = await readFileContainer(
259+
const settingsContent = await readFileContainer(
152260
id,
153-
"/home/coder/.sourcegraph-amp-module/agentapi-start.log",
261+
"/home/coder/.config/amp/settings.json",
154262
);
155-
expect(resp).toContain(`sourcegraph amp task prompt provided : ${prompt}`);
263+
const settings = JSON.parse(settingsContent);
264+
265+
expect(settings["amp.anthropic.thinking.enabled"]).toBe(true);
266+
expect(settings["amp.todos.enabled"]).toBe(true);
267+
expect(settings["amp.mcpServers"]).toBeDefined();
268+
expect(settings["amp.mcpServers"].coder).toBeDefined();
269+
expect(settings["amp.mcpServers"].coder.command).toBe("coder");
156270
});
157271
});

0 commit comments

Comments
 (0)