Changeset 0.32.0 (#206)
This commit is contained in:
@@ -5,8 +5,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
type Mode string
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
const bcryptCost = 12
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// MTLSConfig holds mTLS-specific configuration.
|
||||
|
||||
@@ -3,7 +3,7 @@ package auth
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
func TestParseDN(t *testing.T) {
|
||||
|
||||
@@ -18,8 +18,8 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// OIDCConfig holds OIDC-specific configuration from env vars.
|
||||
|
||||
@@ -3,7 +3,7 @@ package auth_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/auth"
|
||||
"chat-switchboard/auth"
|
||||
)
|
||||
|
||||
func TestOIDCProvider_Discovery(t *testing.T) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// EveryoneGroupID is the stable ID of the implicit "Everyone" group seeded in
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/config"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
const sessionCookieName = "sb_session"
|
||||
|
||||
@@ -3,7 +3,7 @@ package capabilities
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"chat-switchboard/models"
|
||||
)
|
||||
|
||||
func TestLookupKnownModel_AlwaysFalse(t *testing.T) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"chat-switchboard/models"
|
||||
)
|
||||
|
||||
// ── Known Model Defaults ────────────────────
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ModelsForUser returns all models and Personas visible to a user.
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/roles"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/treepath"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/roles"
|
||||
"chat-switchboard/store"
|
||||
"chat-switchboard/treepath"
|
||||
)
|
||||
|
||||
// ── Request / Result ────────────────────────
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
postgres "git.gobha.me/xcaliber/chat-switchboard/store/postgres"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/models"
|
||||
postgres "chat-switchboard/store/postgres"
|
||||
)
|
||||
|
||||
// ── Helpers ─────────────────────────────────
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package compaction
|
||||
|
||||
import (
|
||||
"git.gobha.me/xcaliber/chat-switchboard/treepath"
|
||||
"chat-switchboard/treepath"
|
||||
)
|
||||
|
||||
// ── Token Estimation ────────────────────────
|
||||
|
||||
@@ -3,7 +3,7 @@ package compaction
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/treepath"
|
||||
"chat-switchboard/treepath"
|
||||
)
|
||||
|
||||
func TestEstimateTokens(t *testing.T) {
|
||||
|
||||
@@ -6,10 +6,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/roles"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/treepath"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/roles"
|
||||
"chat-switchboard/store"
|
||||
"chat-switchboard/treepath"
|
||||
)
|
||||
|
||||
// ── Defaults ────────────────────────────────
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"chat-switchboard/database"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
_ "github.com/lib/pq"
|
||||
_ "modernc.org/sqlite"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
"chat-switchboard/config"
|
||||
)
|
||||
|
||||
// DB is the application-wide database connection pool.
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
CREATE TABLE IF NOT EXISTS teams (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(200) NOT NULL UNIQUE,
|
||||
slug VARCHAR(200) NOT NULL DEFAULT '' UNIQUE,
|
||||
description TEXT DEFAULT '',
|
||||
created_by UUID NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
|
||||
37
server/database/migrations/020_ha.sql
Normal file
37
server/database/migrations/020_ha.sql
Normal file
@@ -0,0 +1,37 @@
|
||||
-- ==========================================
|
||||
-- Chat Switchboard — 020 Multi-Replica HA
|
||||
-- ==========================================
|
||||
-- Shared state tables for multi-replica operation.
|
||||
-- v0.32.0: ws_tickets, rate_limit_counters.
|
||||
-- ==========================================
|
||||
|
||||
-- =========================================
|
||||
-- WEBSOCKET TICKETS (replaces in-memory sync.Map)
|
||||
-- =========================================
|
||||
-- Short-lived, single-use tokens for WebSocket authentication.
|
||||
-- Ticket issued on pod-1 must validate on pod-2.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ws_tickets (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
expires_at TIMESTAMPTZ NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ws_tickets_expires
|
||||
ON ws_tickets (expires_at);
|
||||
|
||||
-- =========================================
|
||||
-- RATE LIMIT COUNTERS (replaces in-memory token bucket)
|
||||
-- =========================================
|
||||
-- Fixed-window counters keyed by scope:identifier and time bucket.
|
||||
-- Key format: "{scope}:{identifier}" e.g. "auth:192.168.1.1"
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rate_limit_counters (
|
||||
key TEXT NOT NULL,
|
||||
window_start TIMESTAMPTZ NOT NULL,
|
||||
tokens REAL NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (key, window_start)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_rate_limit_counters_window
|
||||
ON rate_limit_counters (window_start);
|
||||
@@ -4,7 +4,6 @@
|
||||
CREATE TABLE IF NOT EXISTS teams (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
slug TEXT NOT NULL DEFAULT '' UNIQUE,
|
||||
description TEXT DEFAULT '',
|
||||
created_by TEXT NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
|
||||
is_active INTEGER DEFAULT 1,
|
||||
|
||||
34
server/database/migrations/sqlite/020_ha.sql
Normal file
34
server/database/migrations/sqlite/020_ha.sql
Normal file
@@ -0,0 +1,34 @@
|
||||
-- ==========================================
|
||||
-- Chat Switchboard — 020 Multi-Replica HA
|
||||
-- ==========================================
|
||||
-- Shared state tables for multi-replica operation.
|
||||
-- v0.32.0: ws_tickets, rate_limit_counters.
|
||||
-- SQLite parity — functional for single-process test coverage.
|
||||
-- ==========================================
|
||||
|
||||
-- =========================================
|
||||
-- WEBSOCKET TICKETS
|
||||
-- =========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ws_tickets (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
expires_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_ws_tickets_expires
|
||||
ON ws_tickets (expires_at);
|
||||
|
||||
-- =========================================
|
||||
-- RATE LIMIT COUNTERS
|
||||
-- =========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rate_limit_counters (
|
||||
key TEXT NOT NULL,
|
||||
window_start TEXT NOT NULL,
|
||||
tokens REAL NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (key, window_start)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_rate_limit_counters_window
|
||||
ON rate_limit_counters (window_start);
|
||||
@@ -115,7 +115,7 @@ func TestRouteFor(t *testing.T) {
|
||||
{"pong", DirToClient},
|
||||
// Tool bridge routes
|
||||
{"tool.call.abc123", DirToClient},
|
||||
{"tool.result.abc123", DirFromClient},
|
||||
{"tool.result.abc123", DirBoth}, // v0.32.0: DirBoth for cross-pod WaitFor
|
||||
// Extension lifecycle
|
||||
{"extension.loaded", DirLocal},
|
||||
{"extension.error", DirLocal},
|
||||
@@ -201,11 +201,14 @@ func TestToolCallRouteToClient(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolResultRouteFromClient(t *testing.T) {
|
||||
func TestToolResultRouteBoth(t *testing.T) {
|
||||
// v0.32.0: tool.result is DirBoth so results cross pods for WaitFor.
|
||||
// The WS subscriber explicitly filters out tool.result events to
|
||||
// prevent re-sending to clients (see subscribeToBus in ws.go).
|
||||
if !ShouldAcceptFromClient("tool.result.abc123") {
|
||||
t.Error("tool.result.* should be accepted from client")
|
||||
}
|
||||
if ShouldSendToClient("tool.result.abc123") {
|
||||
t.Error("tool.result.* should NOT be sent to client")
|
||||
if !ShouldSendToClient("tool.result.abc123") {
|
||||
t.Error("tool.result.* should route DirBoth (filtered by WS subscriber, not routing table)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
"github.com/lib/pq"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"chat-switchboard/database"
|
||||
)
|
||||
|
||||
const pgNotifyChannel = "switchboard_events"
|
||||
|
||||
25
server/events/ticket_adapter.go
Normal file
25
server/events/ticket_adapter.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package events
|
||||
|
||||
// v0.32.0: TicketValidatorAdapter bridges the context-aware store.TicketStore
|
||||
// to the middleware.TicketValidator interface (which has no context parameter).
|
||||
// Replaces the in-memory TicketStore that lived in this file previously.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// TicketValidatorAdapter satisfies middleware.TicketValidator using a
|
||||
// store.TicketStore backend (PG or SQLite).
|
||||
type TicketValidatorAdapter struct {
|
||||
Store store.TicketStore
|
||||
}
|
||||
|
||||
// Validate atomically consumes a ticket. Satisfies middleware.TicketValidator.
|
||||
func (a *TicketValidatorAdapter) Validate(ticketID string) (string, bool) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
return a.Store.Validate(ctx, ticketID)
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// ticketTTL is how long a ticket remains valid after issuance.
|
||||
ticketTTL = 30 * time.Second
|
||||
|
||||
// ticketReapInterval is how often the background reaper runs.
|
||||
ticketReapInterval = 15 * time.Second
|
||||
)
|
||||
|
||||
// ticket is a single-use opaque token that maps to a user ID.
|
||||
type ticket struct {
|
||||
userID string
|
||||
expiresAt time.Time
|
||||
}
|
||||
|
||||
// TicketStore manages short-lived, single-use WebSocket authentication tickets.
|
||||
//
|
||||
// Flow:
|
||||
// 1. Client POSTs to /api/v1/ws/ticket (authenticated via JWT).
|
||||
// 2. Server returns {"ticket": "<opaque>"}.
|
||||
// 3. Client connects WebSocket with ?ticket=<opaque>.
|
||||
// 4. Server validates and deletes the ticket atomically (single-use).
|
||||
//
|
||||
// This replaces passing the JWT as ?token= in the WebSocket URL, which
|
||||
// exposed the token in server logs, proxy logs, and browser history.
|
||||
type TicketStore struct {
|
||||
mu sync.Mutex
|
||||
tickets map[string]ticket
|
||||
stopCh chan struct{}
|
||||
}
|
||||
|
||||
// NewTicketStore creates a store and starts the background reaper.
|
||||
func NewTicketStore() *TicketStore {
|
||||
ts := &TicketStore{
|
||||
tickets: make(map[string]ticket),
|
||||
stopCh: make(chan struct{}),
|
||||
}
|
||||
go ts.reaper()
|
||||
return ts
|
||||
}
|
||||
|
||||
// Issue creates a new single-use ticket for the given user.
|
||||
// Returns the opaque ticket string.
|
||||
func (ts *TicketStore) Issue(userID string) (string, error) {
|
||||
b := make([]byte, 16) // 128-bit random
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
return "", err
|
||||
}
|
||||
id := hex.EncodeToString(b)
|
||||
|
||||
ts.mu.Lock()
|
||||
ts.tickets[id] = ticket{
|
||||
userID: userID,
|
||||
expiresAt: time.Now().Add(ticketTTL),
|
||||
}
|
||||
ts.mu.Unlock()
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// Validate checks a ticket, deletes it (single-use), and returns the user ID.
|
||||
// Returns ("", false) if the ticket is invalid, expired, or already consumed.
|
||||
func (ts *TicketStore) Validate(ticketID string) (string, bool) {
|
||||
ts.mu.Lock()
|
||||
defer ts.mu.Unlock()
|
||||
|
||||
t, ok := ts.tickets[ticketID]
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
delete(ts.tickets, ticketID) // single-use: delete immediately
|
||||
|
||||
if time.Now().After(t.expiresAt) {
|
||||
return "", false
|
||||
}
|
||||
return t.userID, true
|
||||
}
|
||||
|
||||
// Stop shuts down the background reaper.
|
||||
func (ts *TicketStore) Stop() {
|
||||
close(ts.stopCh)
|
||||
}
|
||||
|
||||
// reaper periodically removes expired tickets that were never validated.
|
||||
func (ts *TicketStore) reaper() {
|
||||
ticker := time.NewTicker(ticketReapInterval)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
ts.mu.Lock()
|
||||
now := time.Now()
|
||||
reaped := 0
|
||||
for id, t := range ts.tickets {
|
||||
if now.After(t.expiresAt) {
|
||||
delete(ts.tickets, id)
|
||||
reaped++
|
||||
}
|
||||
}
|
||||
ts.mu.Unlock()
|
||||
if reaped > 0 {
|
||||
log.Printf("[ws-tickets] reaped %d expired tickets", reaped)
|
||||
}
|
||||
case <-ts.stopCh:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,11 @@ type Event struct {
|
||||
Payload json.RawMessage `json:"payload"`
|
||||
Ts int64 `json:"ts"`
|
||||
|
||||
// v0.32.0: Cross-pod targeted delivery. When set, only connections
|
||||
// belonging to this user receive the event. Serialized for pg_broadcast
|
||||
// (harmless if clients see it — they ignore unknown fields).
|
||||
TargetUserID string `json:"target_user_id,omitempty"`
|
||||
|
||||
// Server-side metadata (not serialized to clients)
|
||||
SenderID string `json:"-"` // user ID of sender, empty for system events
|
||||
ConnID string `json:"-"` // WebSocket connection ID, empty for server-origin
|
||||
@@ -60,7 +65,7 @@ var routeTable = map[string]Direction{
|
||||
"role.fallback": DirToClient,
|
||||
|
||||
// Notifications (v0.20.0)
|
||||
"notification.new": DirToClient, // targeted via Hub.SendToUser, not room-based
|
||||
"notification.new": DirToClient, // targeted via Hub.PublishToUser, not room-based
|
||||
"notification.read": DirToClient, // badge sync across tabs
|
||||
|
||||
// Workspace (v0.21.5)
|
||||
@@ -79,7 +84,7 @@ var routeTable = map[string]Direction{
|
||||
|
||||
// Tool execution (browser tools bridge)
|
||||
"tool.call.": DirToClient, // Server → specific client (browser tool invocation)
|
||||
"tool.result.": DirFromClient, // Client → server (browser tool result)
|
||||
"tool.result.": DirBoth, // v0.32.0: DirBoth — result must cross pods for WaitFor
|
||||
|
||||
// Extension lifecycle
|
||||
"extension.loaded": DirLocal, // Client-only
|
||||
|
||||
@@ -170,9 +170,17 @@ func (h *Hub) IsConnected(userID string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// SendToUser sends an event directly to all WebSocket connections for a user,
|
||||
// bypassing room filtering. Used for targeted tool.call delivery.
|
||||
func (h *Hub) SendToUser(userID string, event Event) {
|
||||
// PublishToUser sends an event to a specific user via the bus.
|
||||
// v0.32.0: Cross-pod safe — the bus broadcast hook fans out via pg_notify.
|
||||
// All replicas receive the event; only the one with the user's connection delivers it.
|
||||
func (h *Hub) PublishToUser(userID string, event Event) {
|
||||
event.TargetUserID = userID
|
||||
h.bus.Publish(event)
|
||||
}
|
||||
|
||||
// sendToUserLocal sends an event directly to local WebSocket connections for a user.
|
||||
// Unexported — callers should use PublishToUser for cross-pod delivery.
|
||||
func (h *Hub) sendToUserLocal(userID string, event Event) {
|
||||
data, err := json.Marshal(event)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -226,6 +234,18 @@ func (c *Conn) subscribeToBus() {
|
||||
return
|
||||
}
|
||||
|
||||
// v0.32.0: Targeted delivery — only deliver to the intended user.
|
||||
// Targeted events skip room filtering (user-scoped, not room-scoped).
|
||||
if e.TargetUserID != "" && e.TargetUserID != c.userID {
|
||||
return
|
||||
}
|
||||
|
||||
// v0.32.0: tool.result travels cross-pod for WaitFor (DirBoth) but
|
||||
// must not be forwarded to WebSocket clients — they sent it.
|
||||
if strings.HasPrefix(e.Label, "tool.result.") {
|
||||
return
|
||||
}
|
||||
|
||||
// Don't echo typing events back to the sender
|
||||
if e.Label == "chat.typing" || e.ConnID == c.id {
|
||||
if e.SenderID == c.userID && e.ConnID == c.id {
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/sandbox"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/sandbox"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// DiscoverStarlarkFilters scans the package registry for active starlark
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// KBInjectFilter injects a system prompt listing active knowledge bases
|
||||
|
||||
@@ -24,8 +24,8 @@ import (
|
||||
|
||||
"go.starlark.net/starlark"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/sandbox"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/sandbox"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// StarlarkFilter runs a Starlark package's on_pre_completion entry point.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module git.gobha.me/xcaliber/chat-switchboard
|
||||
module chat-switchboard
|
||||
|
||||
go 1.22
|
||||
|
||||
|
||||
@@ -12,14 +12,14 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/auth"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/storage"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/tools/search"
|
||||
"chat-switchboard/auth"
|
||||
"chat-switchboard/crypto"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/storage"
|
||||
"chat-switchboard/store"
|
||||
"chat-switchboard/tools/search"
|
||||
)
|
||||
|
||||
type AdminHandler struct {
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/notifications"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/notifications"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// AdminEmailHandler handles admin SMTP configuration and test endpoints.
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/crypto"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ProviderConfigHandler handles user-facing provider config endpoints.
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// AuditLog writes an audit entry via the store interface.
|
||||
|
||||
@@ -17,11 +17,11 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/auth"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/auth"
|
||||
"chat-switchboard/config"
|
||||
"chat-switchboard/crypto"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// Claims represents the JWT payload.
|
||||
|
||||
@@ -14,9 +14,9 @@ import (
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/auth"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/auth"
|
||||
"chat-switchboard/config"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
func testConfig() *config.Config {
|
||||
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
const avatarSize = 128
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
capspkg "git.gobha.me/xcaliber/chat-switchboard/capabilities"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/auth"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/health"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
capspkg "chat-switchboard/capabilities"
|
||||
"chat-switchboard/auth"
|
||||
"chat-switchboard/health"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ModelHandler provides the unified models endpoint.
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Channel Models Handler ──────────────────
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Request / Response types ────────────────
|
||||
|
||||
@@ -13,22 +13,22 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/auth"
|
||||
capspkg "git.gobha.me/xcaliber/chat-switchboard/capabilities"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/events"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/filters"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/health"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/knowledge"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/notifications"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/routing"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/sandbox"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/storage"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/tools"
|
||||
"chat-switchboard/auth"
|
||||
capspkg "chat-switchboard/capabilities"
|
||||
"chat-switchboard/crypto"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/events"
|
||||
"chat-switchboard/filters"
|
||||
"chat-switchboard/health"
|
||||
"chat-switchboard/knowledge"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/notifications"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/routing"
|
||||
"chat-switchboard/sandbox"
|
||||
"chat-switchboard/storage"
|
||||
"chat-switchboard/store"
|
||||
"chat-switchboard/tools"
|
||||
)
|
||||
|
||||
// ── Request Types ───────────────────────────
|
||||
@@ -280,7 +280,7 @@ func (h *CompletionHandler) Complete(c *gin.Context) {
|
||||
Ts: time.Now().UnixMilli(),
|
||||
}
|
||||
// Send to sender
|
||||
h.hub.SendToUser(userID, evt)
|
||||
h.hub.PublishToUser(userID, evt)
|
||||
// Send to other user participants in the channel
|
||||
pRows, pErr := database.DB.QueryContext(c.Request.Context(), database.Q(`
|
||||
SELECT participant_id FROM channel_participants
|
||||
@@ -291,7 +291,7 @@ func (h *CompletionHandler) Complete(c *gin.Context) {
|
||||
for pRows.Next() {
|
||||
var pid string
|
||||
if pRows.Scan(&pid) == nil {
|
||||
h.hub.SendToUser(pid, evt)
|
||||
h.hub.PublishToUser(pid, evt)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -598,7 +598,7 @@ func (h *CompletionHandler) Complete(c *gin.Context) {
|
||||
"from_user": userID,
|
||||
"content": truncateContent(req.Content, 120),
|
||||
})
|
||||
h.hub.SendToUser(mentionedUserID, events.Event{
|
||||
h.hub.PublishToUser(mentionedUserID, events.Event{
|
||||
Label: "user.mentioned",
|
||||
Payload: payload,
|
||||
Ts: time.Now().UnixMilli(),
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/events"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"chat-switchboard/events"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/providers"
|
||||
|
||||
capspkg "git.gobha.me/xcaliber/chat-switchboard/capabilities"
|
||||
capspkg "chat-switchboard/capabilities"
|
||||
)
|
||||
|
||||
// maxChainDepth limits AI-to-AI chaining to prevent runaway loops.
|
||||
@@ -175,7 +175,7 @@ func (h *CompletionHandler) chainIfMentioned(
|
||||
"tokens_used": resp.InputTokens + resp.OutputTokens,
|
||||
"chain_depth": depth + 1,
|
||||
})
|
||||
h.hub.SendToUser(userID, events.Event{
|
||||
h.hub.PublishToUser(userID, events.Event{
|
||||
Label: "message.created",
|
||||
Payload: payload,
|
||||
Ts: time.Now().UnixMilli(),
|
||||
@@ -314,7 +314,7 @@ func (h *CompletionHandler) chainToPersona(channelID, userID, personaID, trigger
|
||||
"tokens_used": resp.InputTokens + resp.OutputTokens,
|
||||
"chain_depth": depth,
|
||||
})
|
||||
h.hub.SendToUser(userID, events.Event{
|
||||
h.hub.PublishToUser(userID, events.Event{
|
||||
Label: "message.created",
|
||||
Payload: payload,
|
||||
Ts: time.Now().UnixMilli(),
|
||||
@@ -350,7 +350,7 @@ func (h *CompletionHandler) emitTyping(userID, channelID, participantID, display
|
||||
"participant_type": "persona",
|
||||
"display_name": displayName,
|
||||
})
|
||||
h.hub.SendToUser(userID, events.Event{
|
||||
h.hub.PublishToUser(userID, events.Event{
|
||||
Label: eventType,
|
||||
Payload: payload,
|
||||
Ts: time.Now().UnixMilli(),
|
||||
|
||||
@@ -42,9 +42,9 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.starlark.net/starlark"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/sandbox"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/sandbox"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ExtAPIHandler serves extension API routes via Starlark.
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// validSchemaIdentifier matches safe SQL identifiers for table and column names.
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── mock ExtDataStore ────────────────────────────────────────────────────────
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ExtPermHandler serves extension permission management endpoints.
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ExtSecretsHandler serves extension secret management endpoints.
|
||||
|
||||
@@ -11,13 +11,13 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
authpkg "git.gobha.me/xcaliber/chat-switchboard/auth"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/middleware"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
postgres "git.gobha.me/xcaliber/chat-switchboard/store/postgres"
|
||||
sqlite "git.gobha.me/xcaliber/chat-switchboard/store/sqlite"
|
||||
authpkg "chat-switchboard/auth"
|
||||
"chat-switchboard/config"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/middleware"
|
||||
"chat-switchboard/store"
|
||||
postgres "chat-switchboard/store/postgres"
|
||||
sqlite "chat-switchboard/store/sqlite"
|
||||
)
|
||||
|
||||
// ── Extension Test Harness ──────────────────
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ExtensionHandler serves extension management endpoints.
|
||||
|
||||
@@ -12,10 +12,10 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/extraction"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/storage"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/extraction"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/storage"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Default Limits ─────────────────────────
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
type FolderHandler struct {
|
||||
|
||||
@@ -11,10 +11,10 @@ import (
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/workspace"
|
||||
"chat-switchboard/crypto"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
"chat-switchboard/workspace"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -7,13 +7,13 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/middleware"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
postgres "git.gobha.me/xcaliber/chat-switchboard/store/postgres"
|
||||
sqlite "git.gobha.me/xcaliber/chat-switchboard/store/sqlite"
|
||||
"chat-switchboard/config"
|
||||
"chat-switchboard/crypto"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/middleware"
|
||||
"chat-switchboard/store"
|
||||
postgres "chat-switchboard/store/postgres"
|
||||
sqlite "chat-switchboard/store/sqlite"
|
||||
)
|
||||
|
||||
// ── Git Credentials Test Harness ──────────
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/auth"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/notifications"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/auth"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/notifications"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Request types ───────────────────────────
|
||||
|
||||
@@ -6,11 +6,11 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
capspkg "git.gobha.me/xcaliber/chat-switchboard/capabilities"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/health"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
capspkg "chat-switchboard/capabilities"
|
||||
"chat-switchboard/health"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Health Admin Handler ────────────────────
|
||||
|
||||
@@ -15,16 +15,16 @@ import (
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
authpkg "git.gobha.me/xcaliber/chat-switchboard/auth"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/middleware"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/roles"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
postgres "git.gobha.me/xcaliber/chat-switchboard/store/postgres"
|
||||
sqlite "git.gobha.me/xcaliber/chat-switchboard/store/sqlite"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/treepath"
|
||||
"chat-switchboard/config"
|
||||
authpkg "chat-switchboard/auth"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/middleware"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/roles"
|
||||
"chat-switchboard/store"
|
||||
postgres "chat-switchboard/store/postgres"
|
||||
sqlite "chat-switchboard/store/sqlite"
|
||||
"chat-switchboard/treepath"
|
||||
)
|
||||
|
||||
// ── Test Harness ────────────────────────────
|
||||
|
||||
@@ -11,10 +11,10 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/knowledge"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/storage"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/knowledge"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/storage"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Limits ───────────────────────────────────
|
||||
|
||||
@@ -7,14 +7,14 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/compaction"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/roles"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
postgres "git.gobha.me/xcaliber/chat-switchboard/store/postgres"
|
||||
sqlite "git.gobha.me/xcaliber/chat-switchboard/store/sqlite"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/treepath"
|
||||
"chat-switchboard/compaction"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/roles"
|
||||
"chat-switchboard/store"
|
||||
postgres "chat-switchboard/store/postgres"
|
||||
sqlite "chat-switchboard/store/sqlite"
|
||||
"chat-switchboard/treepath"
|
||||
)
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/providers"
|
||||
)
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/memory"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/memory"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// MemoryHandler provides REST endpoints for memory management.
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/knowledge"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/knowledge"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// maxMemoryChars is the approximate character budget for injected memories.
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/models"
|
||||
)
|
||||
|
||||
// seedMemory inserts a memory directly into the DB for testing.
|
||||
|
||||
@@ -10,15 +10,15 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
capspkg "git.gobha.me/xcaliber/chat-switchboard/capabilities"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/events"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/storage"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/tools"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/treepath"
|
||||
capspkg "chat-switchboard/capabilities"
|
||||
"chat-switchboard/crypto"
|
||||
"chat-switchboard/events"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/storage"
|
||||
"chat-switchboard/store"
|
||||
"chat-switchboard/tools"
|
||||
"chat-switchboard/treepath"
|
||||
)
|
||||
|
||||
// ── Request / Response types ────────────────
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ModelPrefsHandler handles user model preference endpoints.
|
||||
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/middleware"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
postgres "git.gobha.me/xcaliber/chat-switchboard/store/postgres"
|
||||
sqlite "git.gobha.me/xcaliber/chat-switchboard/store/sqlite"
|
||||
"chat-switchboard/config"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/middleware"
|
||||
"chat-switchboard/store"
|
||||
postgres "chat-switchboard/store/postgres"
|
||||
sqlite "chat-switchboard/store/sqlite"
|
||||
)
|
||||
|
||||
// ── Model Prefs Test Harness ──────────────
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// providerSyncTimeout is the maximum time allowed for an outbound provider
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/notelinks"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/notelinks"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Request / Response Types ────────────────
|
||||
|
||||
@@ -8,14 +8,14 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/middleware"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/notifications"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
postgres "git.gobha.me/xcaliber/chat-switchboard/store/postgres"
|
||||
sqlite "git.gobha.me/xcaliber/chat-switchboard/store/sqlite"
|
||||
"chat-switchboard/config"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/middleware"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/notifications"
|
||||
"chat-switchboard/store"
|
||||
postgres "chat-switchboard/store/postgres"
|
||||
sqlite "chat-switchboard/store/sqlite"
|
||||
)
|
||||
|
||||
// ── Notification Test Harness ──────────────
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/events"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/notifications"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/events"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/notifications"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Handler ─────────────────────────────────
|
||||
@@ -111,7 +111,7 @@ func (h *NotificationHandler) MarkRead(c *gin.Context) {
|
||||
// Sync badge across tabs
|
||||
if h.hub != nil {
|
||||
payload, _ := json.Marshal(map[string]string{"id": id})
|
||||
h.hub.SendToUser(userID, events.Event{
|
||||
h.hub.PublishToUser(userID, events.Event{
|
||||
Label: "notification.read",
|
||||
Payload: payload,
|
||||
Ts: time.Now().UnixMilli(),
|
||||
@@ -138,7 +138,7 @@ func (h *NotificationHandler) MarkAllRead(c *gin.Context) {
|
||||
// Sync badge across tabs
|
||||
if h.hub != nil {
|
||||
payload, _ := json.Marshal(map[string]string{"action": "mark_all_read"})
|
||||
h.hub.SendToUser(userID, events.Event{
|
||||
h.hub.PublishToUser(userID, events.Event{
|
||||
Label: "notification.read",
|
||||
Payload: payload,
|
||||
Ts: time.Now().UnixMilli(),
|
||||
@@ -341,7 +341,7 @@ func (h *NotificationHandler) Broadcast(c *gin.Context) {
|
||||
"level": level,
|
||||
})
|
||||
for _, uid := range userIDs {
|
||||
h.hub.SendToUser(uid, events.Event{
|
||||
h.hub.PublishToUser(uid, events.Event{
|
||||
Label: "system.broadcast",
|
||||
Payload: payload,
|
||||
Ts: time.Now().UnixMilli(),
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// PackageExportHandler handles package export operations.
|
||||
|
||||
@@ -28,8 +28,8 @@ import (
|
||||
|
||||
"go.starlark.net/starlark"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/sandbox"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/sandbox"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ParseSchemaVersion extracts the "schema_version" integer from a manifest.
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// RegistryEntry represents a single package in the registry.
|
||||
|
||||
@@ -14,9 +14,9 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/sandbox"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/sandbox"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// validPackageID matches lowercase alphanumeric slugs with optional hyphens.
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Channel Participants Handler ──────────────
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
type PersonaGroupHandler struct {
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// PersonaHandler handles persona endpoints.
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
const presenceOnlineThreshold = 90 * time.Second
|
||||
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/middleware"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
postgres "git.gobha.me/xcaliber/chat-switchboard/store/postgres"
|
||||
sqlite "git.gobha.me/xcaliber/chat-switchboard/store/sqlite"
|
||||
"chat-switchboard/config"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/middleware"
|
||||
"chat-switchboard/store"
|
||||
postgres "chat-switchboard/store/postgres"
|
||||
sqlite "chat-switchboard/store/sqlite"
|
||||
)
|
||||
|
||||
// ── Profile Test Harness ──────────────────
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Request / Response Types ────────────────
|
||||
|
||||
@@ -8,13 +8,13 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/middleware"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
postgres "git.gobha.me/xcaliber/chat-switchboard/store/postgres"
|
||||
sqlite "git.gobha.me/xcaliber/chat-switchboard/store/sqlite"
|
||||
"chat-switchboard/config"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/middleware"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
postgres "chat-switchboard/store/postgres"
|
||||
sqlite "chat-switchboard/store/sqlite"
|
||||
)
|
||||
|
||||
// ── Project Test Harness ──────────────────
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/sandbox"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/crypto"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/sandbox"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ProviderResolverAdapter implements sandbox.ProviderResolver using
|
||||
|
||||
@@ -17,10 +17,10 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/tools"
|
||||
"chat-switchboard/crypto"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/store"
|
||||
"chat-switchboard/tools"
|
||||
)
|
||||
|
||||
// ── Provider Resolution ────────────────────────
|
||||
|
||||
@@ -5,10 +5,10 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/roles"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/roles"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// RolesHandler manages model role configuration.
|
||||
|
||||
@@ -7,14 +7,14 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
authpkg "git.gobha.me/xcaliber/chat-switchboard/auth"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/middleware"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/pages"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
postgres "git.gobha.me/xcaliber/chat-switchboard/store/postgres"
|
||||
sqlite "git.gobha.me/xcaliber/chat-switchboard/store/sqlite"
|
||||
"chat-switchboard/config"
|
||||
authpkg "chat-switchboard/auth"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/middleware"
|
||||
"chat-switchboard/pages"
|
||||
"chat-switchboard/store"
|
||||
postgres "chat-switchboard/store/postgres"
|
||||
sqlite "chat-switchboard/store/sqlite"
|
||||
)
|
||||
|
||||
// TestRouteRegistration verifies that ALL production routes can be
|
||||
|
||||
@@ -6,10 +6,10 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/health"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/routing"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/health"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/routing"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Routing Admin Handler ───────────────────
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/lib/pq"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"chat-switchboard/database"
|
||||
)
|
||||
|
||||
// ── SafeJSON ────────────────────────────────
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// builtinManifest is the on-disk manifest.json shape.
|
||||
|
||||
@@ -5,10 +5,10 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/config"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/config"
|
||||
"chat-switchboard/crypto"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// Known provider default endpoints for seeding.
|
||||
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/crypto"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Request Types ───────────────────────────
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/storage"
|
||||
"chat-switchboard/storage"
|
||||
)
|
||||
|
||||
// storageConfigured is a package-level flag set during init.
|
||||
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/events"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/sandbox"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/tools"
|
||||
"chat-switchboard/events"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/sandbox"
|
||||
"chat-switchboard/store"
|
||||
"chat-switchboard/tools"
|
||||
)
|
||||
|
||||
// recordHealthFn records provider health from standalone streaming functions.
|
||||
@@ -141,7 +141,7 @@ func executeBrowserTool(hub *events.Hub, userID string, call tools.ToolCall) too
|
||||
"arguments": json.RawMessage(call.Arguments),
|
||||
})
|
||||
|
||||
hub.SendToUser(userID, events.Event{
|
||||
hub.PublishToUser(userID, events.Event{
|
||||
Label: "tool.call." + callID,
|
||||
Payload: payload,
|
||||
Ts: time.Now().UnixMilli(),
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/compaction"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/roles"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/compaction"
|
||||
"chat-switchboard/roles"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// SummarizeHandler handles manual conversation summarization via HTTP.
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"chat-switchboard/database"
|
||||
)
|
||||
|
||||
// ═══════════════════════════════════════════════
|
||||
|
||||
@@ -7,12 +7,12 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/auth"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/middleware"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/taskutil"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/webhook"
|
||||
"chat-switchboard/auth"
|
||||
"chat-switchboard/middleware"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/store"
|
||||
"chat-switchboard/taskutil"
|
||||
"chat-switchboard/webhook"
|
||||
)
|
||||
|
||||
// TaskHandler manages task CRUD and manual execution.
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
capspkg "git.gobha.me/xcaliber/chat-switchboard/capabilities"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
capspkg "chat-switchboard/capabilities"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Team Provider Handlers ──────────────────
|
||||
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/crypto"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/crypto"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/models"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ── Request types ───────────────────────────
|
||||
@@ -105,7 +105,6 @@ func (h *TeamHandler) CreateTeam(c *gin.Context) {
|
||||
|
||||
team := &models.Team{
|
||||
Name: req.Name,
|
||||
Slug: slugify(req.Name),
|
||||
Description: req.Description,
|
||||
CreatedBy: adminID,
|
||||
IsActive: true,
|
||||
@@ -119,7 +118,7 @@ func (h *TeamHandler) CreateTeam(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, gin.H{"id": team.ID, "name": team.Name, "slug": team.Slug})
|
||||
c.JSON(http.StatusCreated, gin.H{"id": team.ID, "name": team.Name})
|
||||
AuditLog(h.stores.Audit, c, "team.create", "team", team.ID, map[string]interface{}{"name": team.Name})
|
||||
}
|
||||
|
||||
@@ -156,7 +155,6 @@ func (h *TeamHandler) UpdateTeam(c *gin.Context) {
|
||||
fields := map[string]interface{}{}
|
||||
if req.Name != nil {
|
||||
fields["name"] = *req.Name
|
||||
fields["slug"] = slugify(*req.Name)
|
||||
}
|
||||
if req.Description != nil {
|
||||
fields["description"] = *req.Description
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/database"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"chat-switchboard/database"
|
||||
"chat-switchboard/providers"
|
||||
|
||||
_ "modernc.org/sqlite" // register sqlite driver for DB_DRIVER=sqlite
|
||||
)
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/providers"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/roles"
|
||||
"git.gobha.me/xcaliber/chat-switchboard/store"
|
||||
"chat-switchboard/providers"
|
||||
"chat-switchboard/roles"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// TitleHandler generates chat titles using the utility role.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user