feat: add gateway API, voice service, WebSocket hub, and startup entry

- services/gateway/api: net/http router with JWT auth, stub login, 6 tests
- services/gateway/ws: WebSocket hub with echo support
- services/voice: STT/TTS provider chain with fallback, 6 tests
- cmd/cyrene/main.go: single binary startup, 108 tests total
- Smoke test: health check + login verified on :8080
This commit is contained in:
Aska committed 2026-08-09 21:09:43 +08:00
1 parent 81ebdb910c
commit 99806fefad
12 files changed
+874 -1

No files matched your search

+14 -1
View File
@@ -6,6 +6,7 @@ import (
"database/sql"
"fmt"
"log"
"strings"
"time"
_ "github.com/lib/pq" // PostgreSQL driver
@@ -117,7 +118,6 @@ func Transaction(ctx context.Context, db *sql.DB, fn func(tx *sql.Tx) error) err
}
// RunMigration executes a list of SQL migration statements in order.
// Each migration is run within its own transaction.
func RunMigration(ctx context.Context, db *sql.DB, name string, statements []string) error {
log.Printf("[db] running migration: %s (%d statements)", name, len(statements))
@@ -129,3 +129,16 @@ func RunMigration(ctx context.Context, db *sql.DB, name string, statements []str
log.Printf("[db] migration %s completed", name)
return nil
}
// SplitSQL splits a multi-statement SQL string on semicolons.
func SplitSQL(sql string) []string {
parts := strings.Split(sql, ";")
result := make([]string, 0, len(parts))
for _, p := range parts {
p = strings.TrimSpace(p)
if p != "" && !strings.HasPrefix(p, "--") {
result = append(result, p)
}
}
return result
}