refactor(ai): split the 1180-line ai.go into focused files #6

Merged
nsatoshi merged 1 commits from devin/1776539460-refactor-ai-package-split into master 2026-04-18 19:36:20 +00:00
Owner

Summary

PR #6 of the 11-PR completion sequence. Decomposes backend/api/rest/ai.go — the review's single largest file at 1,180 lines — into six purpose-built files inside the same package. Pure move: no logic changes, no new public API, no route changes, no caller edits required.

New file layout

file lines role
ai.go 198 HTTP handlers + feature flags + exported AI* DTOs
ai_context.go 381 buildAIContext + indexed-DB queries (stats / tx / address / block) + regex patterns + extractBlockReference
ai_routes.go 139 queryAIRoutes + filterAIRouteMatches + routeMatchesQuery + normalizeHexString
ai_docs.go 136 loadAIDocSnippets + findAIWorkspaceRoot + scanDocForTerms + buildDocSearchTerms
ai_xai.go 267 xAI / OpenAI request+response types + normalizeAIMessages + latestUserMessage + callXAIChatCompletions + parseXAIError + extractOutputText
ai_helpers.go 112 pure utilities: firstRegexMatch, compactStringMap, compactAnyMap, stringValue, stringSliceValue, uniqueStrings, clipString, fileExists

ai_runtime.go (rate limiter + metrics + audit log) is unchanged.

Why same package, not internal/ai/*

The original completion prompt sketched an internal/ai/* split. Keeping the files inside backend/api/rest/ instead:

  • Preserves the *Server method receivers (handleAIChat, buildAIContext, queryAIRoutes, callXAIChatCompletions) without having to export Server.db, Server.chainID, Server.aiRateLimiter, Server.aiMetrics, and the logAIRequest / allowAIRequest helpers.
  • Keeps this PR a diff-only move that any reviewer can verify with diff -q <(cat ai_*.go) <(git show master:backend/api/rest/ai.go).
  • Leaves open a follow-up that does the package extraction with a thin ai.Service interface once the rest of the hardening sequence lands.

Verification

  • go build ./... — clean.
  • go vet ./... — clean.
  • go test ./api/rest/...PASS.
  • staticcheck ./... — clean on the SA* correctness family. The U1000 and S1016 tails are pre-existing and already disabled in the backend/staticcheck.conf introduced in PR #5.

Completion criterion advanced

6. Backend maintainability — "No single Go file exceeds a few hundred lines; AI/LLM plumbing is separated from HTTP handlers; context-building is separated from upstream calls."

## Summary PR #6 of the 11-PR completion sequence. Decomposes `backend/api/rest/ai.go` — the review's single largest file at 1,180 lines — into six purpose-built files inside the same package. Pure move: no logic changes, no new public API, no route changes, no caller edits required. ## New file layout | file | lines | role | | --- | ---:| --- | | `ai.go` | 198 | HTTP handlers + feature flags + exported `AI*` DTOs | | `ai_context.go` | 381 | `buildAIContext` + indexed-DB queries (stats / tx / address / block) + regex patterns + `extractBlockReference` | | `ai_routes.go` | 139 | `queryAIRoutes` + `filterAIRouteMatches` + `routeMatchesQuery` + `normalizeHexString` | | `ai_docs.go` | 136 | `loadAIDocSnippets` + `findAIWorkspaceRoot` + `scanDocForTerms` + `buildDocSearchTerms` | | `ai_xai.go` | 267 | xAI / OpenAI request+response types + `normalizeAIMessages` + `latestUserMessage` + `callXAIChatCompletions` + `parseXAIError` + `extractOutputText` | | `ai_helpers.go` | 112 | pure utilities: `firstRegexMatch`, `compactStringMap`, `compactAnyMap`, `stringValue`, `stringSliceValue`, `uniqueStrings`, `clipString`, `fileExists` | `ai_runtime.go` (rate limiter + metrics + audit log) is unchanged. ## Why same package, not `internal/ai/*` The original completion prompt sketched an `internal/ai/*` split. Keeping the files inside `backend/api/rest/` instead: - Preserves the `*Server` method receivers (`handleAIChat`, `buildAIContext`, `queryAIRoutes`, `callXAIChatCompletions`) without having to export `Server.db`, `Server.chainID`, `Server.aiRateLimiter`, `Server.aiMetrics`, and the `logAIRequest` / `allowAIRequest` helpers. - Keeps this PR a diff-only move that any reviewer can verify with `diff -q <(cat ai_*.go) <(git show master:backend/api/rest/ai.go)`. - Leaves open a follow-up that does the package extraction with a thin `ai.Service` interface once the rest of the hardening sequence lands. ## Verification - `go build ./...` — clean. - `go vet ./...` — clean. - `go test ./api/rest/...` — **PASS**. - `staticcheck ./...` — clean on the SA* correctness family. The U1000 and S1016 tails are pre-existing and already disabled in the `backend/staticcheck.conf` introduced in PR #5. ## Completion criterion advanced > **6. Backend maintainability** — "No single Go file exceeds a few hundred lines; AI/LLM plumbing is separated from HTTP handlers; context-building is separated from upstream calls."
nsatoshi added 1 commit 2026-04-18 19:13:58 +00:00
Decomposes backend/api/rest/ai.go (which the review flagged at 1180 lines
and which was the largest file in the repo by a wide margin) into six
purpose-built files inside the same package, so no import paths change
for any caller and *Server receivers keep working:

  ai.go           198  handlers + feature flags + exported AI* DTOs
  ai_context.go   381  buildAIContext + indexed-DB queries
                       (stats / tx / address / block) + regex patterns +
                       extractBlockReference
  ai_routes.go    139  queryAIRoutes + filterAIRouteMatches +
                       routeMatchesQuery + normalizeHexString
  ai_docs.go      136  loadAIDocSnippets + findAIWorkspaceRoot +
                       scanDocForTerms + buildDocSearchTerms
  ai_xai.go       267  xAI / OpenAI request/response types +
                       normalizeAIMessages + latestUserMessage +
                       callXAIChatCompletions + parseXAIError +
                       extractOutputText
  ai_helpers.go   112  pure-function utilities (firstRegexMatch,
                       compactStringMap, compactAnyMap, stringValue,
                       stringSliceValue, uniqueStrings, clipString,
                       fileExists)

ai_runtime.go (rate limiter + metrics + audit log) is unchanged.

This is a pure move: no logic changes, no new public API, no changes to
HTTP routes. Each file carries only the imports it actually uses so
goimports is clean on every file individually. Every exported symbol
retained its original spelling so callers (routes.go, server.go, and
the AI e2e tests) keep compiling without edits.

Verification:
  go build  ./...  clean
  go vet    ./...  clean
  go test   ./api/rest/...  PASS
  staticcheck ./...  clean on the SA* correctness family

Advances completion criterion 6 (backend maintainability): 'no single
Go file exceeds a few hundred lines; AI/LLM plumbing is separated from
HTTP handlers; context-building is separated from upstream calls.'
nsatoshi merged commit 976f4716d6 into master 2026-04-18 19:36:20 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: d-bis/explorer-monorepo#6