feat. rebuild service in Go
Rebuild the Gitea Codex review bot from the product contract with a Go HTTP service, durable SQL queue, typed Gitea client, isolated runner, and deployment updates. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"gitea-codex-bot/internal/domain"
|
||||
)
|
||||
|
||||
var helpAliases = map[string]bool{"-h": true, "--help": true, "help": true}
|
||||
var supported = map[string]bool{"review": true, "rerun": true, "explain": true, "ignore": true}
|
||||
|
||||
func DetectPrefixedCommand(body string, aliases map[string]bool) string {
|
||||
parts, ok := prefixParts(body, aliases)
|
||||
if !ok || len(parts) == 0 {
|
||||
return ""
|
||||
}
|
||||
return strings.ToLower(parts[0])
|
||||
}
|
||||
|
||||
func Parse(body string, aliases map[string]bool) (domain.ParsedCommand, bool) {
|
||||
stripped := strings.TrimSpace(body)
|
||||
parts, ok := prefixParts(stripped, aliases)
|
||||
if !ok || len(parts) == 0 {
|
||||
return domain.ParsedCommand{}, false
|
||||
}
|
||||
name := strings.ToLower(parts[0])
|
||||
rawArgs := append([]string(nil), parts[1:]...)
|
||||
if helpAliases[name] {
|
||||
return domain.ParsedCommand{Name: "help", Alias: aliasOf(stripped), Raw: stripped, Arguments: rawArgs}, true
|
||||
}
|
||||
if !supported[name] {
|
||||
return domain.ParsedCommand{}, false
|
||||
}
|
||||
cmd := domain.ParsedCommand{Name: name, Alias: aliasOf(stripped), Raw: stripped, Mode: "summary", Arguments: rawArgs}
|
||||
if name == "review" {
|
||||
for _, token := range rawArgs {
|
||||
switch strings.ToLower(token) {
|
||||
case "--full":
|
||||
cmd.Full = true
|
||||
cmd.Mode = "full"
|
||||
cmd.ModeExplicit = true
|
||||
case "security", "performance", "tests":
|
||||
if !cmd.ModeExplicit || cmd.Mode == "full" {
|
||||
cmd.Mode = strings.ToLower(token)
|
||||
cmd.ModeExplicit = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cmd, true
|
||||
}
|
||||
|
||||
func prefixParts(body string, aliases map[string]bool) ([]string, bool) {
|
||||
trimmed := strings.TrimSpace(body)
|
||||
if !strings.HasPrefix(trimmed, "@") {
|
||||
return nil, false
|
||||
}
|
||||
space := strings.IndexFunc(trimmed, unicode.IsSpace)
|
||||
if space <= 1 {
|
||||
return nil, false
|
||||
}
|
||||
alias := strings.ToLower(strings.TrimPrefix(trimmed[1:space], "@"))
|
||||
if !aliases[alias] {
|
||||
return nil, false
|
||||
}
|
||||
remainder := strings.TrimSpace(trimmed[space:])
|
||||
tokens, err := lex(remainder)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return tokens, true
|
||||
}
|
||||
|
||||
func aliasOf(body string) string {
|
||||
end := strings.IndexFunc(body[1:], unicode.IsSpace)
|
||||
if end < 0 {
|
||||
return body
|
||||
}
|
||||
return body[:end+1]
|
||||
}
|
||||
|
||||
func lex(input string) ([]string, error) {
|
||||
var out []string
|
||||
var b strings.Builder
|
||||
quoted := rune(0)
|
||||
escaped := false
|
||||
started := false
|
||||
flush := func() {
|
||||
if started {
|
||||
out = append(out, b.String())
|
||||
b.Reset()
|
||||
started = false
|
||||
}
|
||||
}
|
||||
for _, r := range input {
|
||||
if escaped {
|
||||
b.WriteRune(r)
|
||||
started = true
|
||||
escaped = false
|
||||
continue
|
||||
}
|
||||
if r == '\\' {
|
||||
escaped = true
|
||||
started = true
|
||||
continue
|
||||
}
|
||||
if quoted != 0 {
|
||||
if r == quoted {
|
||||
quoted = 0
|
||||
} else {
|
||||
b.WriteRune(r)
|
||||
}
|
||||
started = true
|
||||
continue
|
||||
}
|
||||
if r == '\'' || r == '"' {
|
||||
quoted = r
|
||||
started = true
|
||||
continue
|
||||
}
|
||||
if unicode.IsSpace(r) {
|
||||
flush()
|
||||
continue
|
||||
}
|
||||
b.WriteRune(r)
|
||||
started = true
|
||||
}
|
||||
if escaped || quoted != 0 {
|
||||
return nil, errors.New("unterminated command quote")
|
||||
}
|
||||
flush()
|
||||
return out, nil
|
||||
}
|
||||
Reference in New Issue
Block a user