Skip to content

Conversation

@hkfires
Copy link
Collaborator

@hkfires hkfires commented Dec 8, 2025

No description provided.

Add new REST API endpoints under /v0/management/ampcode for managing
ampcode configuration including upstream URL, API key, localhost
restriction, model mappings, and force model mappings settings.

- Move force-model-mappings from config_basic to config_lists
- Add GET/PUT/PATCH/DELETE endpoints for all ampcode settings
- Support model mapping CRUD with upsert (PATCH) capability
- Add comprehensive test coverage for all ampcode endpoints
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @hkfires, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the 'ampcode' configuration management capabilities by introducing a dedicated and comprehensive set of API endpoints. These new routes allow for programmatic control over 'ampcode' settings such as upstream URLs, API keys, localhost access restrictions, and detailed model mappings, including the ability to get, set, update, and delete individual or collections of mappings. The changes streamline configuration management and are thoroughly tested to ensure reliability.

Highlights

  • New AmpCode Management API: Introduced a comprehensive set of API endpoints under '/v0/management/ampcode' for managing various 'ampcode' configuration settings.
  • Centralized Configuration: Consolidated 'ampcode' related configuration management into a dedicated API, including upstream URL, API key, localhost restriction, and model mappings.
  • Model Mapping Operations: Provided granular control over model mappings with GET, PUT (replace all), PATCH (add/update), and DELETE (remove specific or all) operations.
  • Refactored Boolean Update Logic: Simplified the 'updateBoolField' helper function by removing redundant JSON unmarshalling.
  • Extensive Test Coverage: Added a new test file ('test/amp_management_test.go') with detailed unit tests for all new 'ampcode' management API endpoints, ensuring functionality and state persistence.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a comprehensive management API for ampcode configuration, which is a great addition. The changes are well-structured, with new handlers neatly organized and existing code refactored for clarity. The inclusion of a thorough test suite is particularly commendable, covering a wide range of scenarios for the new endpoints.

My review includes a couple of suggestions for improving the test suite's maintainability and consistency. Overall, this is a solid contribution.

Comment on lines +21 to +45
// newAmpTestHandler creates a test handler with default ampcode configuration.
func newAmpTestHandler(t *testing.T) (*management.Handler, string) {
t.Helper()
tmpDir := t.TempDir()
configPath := filepath.Join(tmpDir, "config.yaml")

cfg := &config.Config{
AmpCode: config.AmpCode{
UpstreamURL: "https://example.com",
UpstreamAPIKey: "test-api-key-12345",
RestrictManagementToLocalhost: true,
ForceModelMappings: false,
ModelMappings: []config.AmpModelMapping{
{From: "gpt-4", To: "gemini-pro"},
},
},
}

if err := os.WriteFile(configPath, []byte("port: 8080\n"), 0644); err != nil {
t.Fatalf("failed to write config file: %v", err)
}

h := management.NewHandler(cfg, configPath, nil)
return h, configPath
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test suite has a number of redundant tests. For many endpoints, there is one test that only checks for a 200 OK status (e.g., TestPutAmpUpstreamURL), and another test with a _VerifyState suffix that performs the same action and also verifies the state change (e.g., TestPutAmpUpstreamURL_VerifyState).

This pattern leads to code duplication and makes the test suite harder to maintain. It would be better to have a single, comprehensive test for each action that includes state verification.

For example, TestPutAmpUpstreamURL could be removed, and TestPutAmpUpstreamURL_VerifyState could be renamed to TestPutAmpUpstreamURL and become the sole test for that endpoint action. This principle can be applied to other similar pairs of tests in this file.

Comment on lines +164 to +172
var resp map[string]any
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
t.Fatalf("failed to unmarshal response: %v", err)
}

key := resp["upstream-api-key"].(string)
if key != "test-api-key-12345" {
t.Errorf("expected key %q, got %q", "test-api-key-12345", key)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test TestGetAmpUpstreamAPIKey uses map[string]any to unmarshal the JSON response, which is inconsistent with other tests that use more specific types like map[string]string or map[string]bool. Using any (or interface{}) requires a type assertion, which can panic if the response format is not as expected. Using a specific type like map[string]string is safer and more consistent.

var resp map[string]string
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
    t.Fatalf("failed to unmarshal response: %v", err)
}

if resp["upstream-api-key"] != "test-api-key-12345" {
    t.Errorf("expected key %q, got %q", "test-api-key-12345", resp["upstream-api-key"])
}

Comment on lines +320 to +331
func TestDeleteAmpModelMappings_All(t *testing.T) {
h, _ := newAmpTestHandler(t)
r := setupAmpRouter(h)

req := httptest.NewRequest(http.MethodDelete, "/v0/management/ampcode/model-mappings", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)

if w.Code != http.StatusOK {
t.Fatalf("expected status %d, got %d", http.StatusOK, w.Code)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This test verifies that a DELETE request with an empty body to the model mappings endpoint returns a 200 OK status. However, it doesn't verify that all model mappings were actually deleted. To make the test more robust, it should be extended to make a subsequent GET request and assert that the list of model mappings is empty.

func TestDeleteAmpModelMappings_All(t *testing.T) {
	h, _ := newAmpTestHandler(t)
	r := setupAmpRouter(h)

	req := httptest.NewRequest(http.MethodDelete, "/v0/management/ampcode/model-mappings", nil)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)

	if w.Code != http.StatusOK {
		t.Fatalf("expected status %d, got %d", http.StatusOK, w.Code)
	}

	req = httptest.NewRequest(http.MethodGet, "/v0/management/ampcode/model-mappings", nil)
	w = httptest.NewRecorder()
	r.ServeHTTP(w, req)

	if w.Code != http.StatusOK {
		t.Fatalf("GET after DELETE failed: status %d", w.Code)
	}

	var resp map[string][]config.AmpModelMapping
	if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
		t.Fatalf("failed to unmarshal: %v", err)
	}

	if len(resp["model-mappings"]) != 0 {
		t.Errorf("expected 0 mappings after DELETE all, got %d", len(resp["model-mappings"]))
	}
}

@luispater luispater merged commit 5aa386d into dev Dec 8, 2025
1 check passed
@hkfires hkfires deleted the amp branch December 8, 2025 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants