diff --git a/internal/api/modules/amp/routes.go b/internal/api/modules/amp/routes.go index 02f518a1..b7105a14 100644 --- a/internal/api/modules/amp/routes.go +++ b/internal/api/modules/amp/routes.go @@ -110,6 +110,8 @@ func (m *AmpModule) registerManagementRoutes(engine *gin.Engine, baseHandler *ha ampAPI.Any("/threads/*path", proxyHandler) ampAPI.Any("/otel", proxyHandler) ampAPI.Any("/otel/*path", proxyHandler) + ampAPI.Any("/tab", proxyHandler) + ampAPI.Any("/tab/*path", proxyHandler) // Root-level routes that AMP CLI expects without /api prefix // These need the same security middleware as the /api/* routes @@ -119,6 +121,12 @@ func (m *AmpModule) registerManagementRoutes(engine *gin.Engine, baseHandler *ha } engine.GET("/threads.rss", append(rootMiddleware, proxyHandler)...) + // Root-level auth routes for CLI login flow + // Amp uses multiple auth routes: /auth/cli-login, /auth/callback, /auth/sign-in, /auth/logout + // We proxy all /auth/* to support the complete OAuth flow + engine.Any("/auth", append(rootMiddleware, proxyHandler)...) + engine.Any("/auth/*path", append(rootMiddleware, proxyHandler)...) + // Google v1beta1 passthrough with OAuth fallback // AMP CLI uses non-standard paths like /publishers/google/models/... // We bridge these to our standard Gemini handler to enable local OAuth. diff --git a/internal/api/modules/amp/routes_test.go b/internal/api/modules/amp/routes_test.go index 51bd7abd..89e43506 100644 --- a/internal/api/modules/amp/routes_test.go +++ b/internal/api/modules/amp/routes_test.go @@ -39,6 +39,11 @@ func TestRegisterManagementRoutes(t *testing.T) { {"/api/threads", http.MethodGet}, {"/threads.rss", http.MethodGet}, // Root-level route (no /api prefix) {"/api/otel", http.MethodGet}, + {"/api/tab", http.MethodGet}, + {"/api/tab/some/path", http.MethodGet}, + {"/auth", http.MethodGet}, // Root-level auth route + {"/auth/cli-login", http.MethodGet}, // CLI login flow + {"/auth/callback", http.MethodGet}, // OAuth callback // Google v1beta1 bridge should still proxy non-model requests (GET) and allow POST {"/api/provider/google/v1beta1/models", http.MethodGet}, {"/api/provider/google/v1beta1/models", http.MethodPost}, diff --git a/internal/logging/global_logger.go b/internal/logging/global_logger.go index 9d4e1fc9..28fde213 100644 --- a/internal/logging/global_logger.go +++ b/internal/logging/global_logger.go @@ -38,7 +38,13 @@ func (m *LogFormatter) Format(entry *log.Entry) ([]byte, error) { timestamp := entry.Time.Format("2006-01-02 15:04:05") message := strings.TrimRight(entry.Message, "\r\n") - formatted := fmt.Sprintf("[%s] [%s] [%s:%d] %s\n", timestamp, entry.Level, filepath.Base(entry.Caller.File), entry.Caller.Line, message) + + var formatted string + if entry.Caller != nil { + formatted = fmt.Sprintf("[%s] [%s] [%s:%d] %s\n", timestamp, entry.Level, filepath.Base(entry.Caller.File), entry.Caller.Line, message) + } else { + formatted = fmt.Sprintf("[%s] [%s] %s\n", timestamp, entry.Level, message) + } buffer.WriteString(formatted) return buffer.Bytes(), nil