steps 5-8: deep gut — purge chat/notes/projects/providers from code
main.go: remove ~300 lines of stale routes referencing deleted handlers (channels, messages, folders, personas, notes, projects, memories, models, providers, tasks, roles, usage, routing, capabilities, etc.) Fix branding: "Chat Switchboard" → "Switchboard Core" pages: remove chat/notes/projects surface manifests and templates Keep: admin, settings, team-admin, workflow, workflow-landing frontend: delete chat/, notes/, projects/ surface directories (19 files) Delete 5 CSS files (4,144 lines): sw-chat-*, sw-notes-*, sw-projects-* SDK: strip gutted API domains (594→287 lines), remove chatPane/notesPane tests: remove integration_test.go (5,194 lines, broken imports to deleted packages) and perm_enforcement_test.go (551 lines, depended on deleted test helpers). Fix testmain_test.go (remove providers import). openapi.yaml: replace 12,491-line stale spec with kernel auth stub. Full ICD rebuild is Step 8 proper. Auth (builtin, mTLS, OIDC) untouched throughout. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
309
server/main.go
309
server/main.go
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
@@ -107,12 +106,6 @@ func main() {
|
||||
stores = postgres.NewStores(database.DB)
|
||||
}
|
||||
|
||||
|
||||
// Provider health accumulator (v0.22.0)
|
||||
if database.IsSQLite() {
|
||||
} else {
|
||||
}
|
||||
|
||||
// v0.33.0: Start Prometheus DB pool collector
|
||||
metrics.StartDBCollector(database.DB, 15*time.Second)
|
||||
|
||||
@@ -131,25 +124,15 @@ func main() {
|
||||
}
|
||||
}()
|
||||
|
||||
retScanner.Start()
|
||||
defer retScanner.Stop()
|
||||
|
||||
// v0.27.2: Task scheduler startup deferred to after hub/notification init — see below.
|
||||
|
||||
// Bootstrap admin from env (K8s secret) — upserts on every restart
|
||||
handlers.BootstrapAdmin(cfg, stores, uekCache)
|
||||
|
||||
// Seed additional users from env (dev/test only, skipped in production)
|
||||
handlers.SeedUsers(cfg, stores, uekCache)
|
||||
|
||||
// Seed providers from env (dev/test only, skipped in production)
|
||||
handlers.SeedProviders(cfg, stores, keyResolver)
|
||||
|
||||
// Seed builtin extensions from disk (idempotent, version-aware)
|
||||
handlers.SeedBuiltinPackages(stores, "extensions/builtin")
|
||||
|
||||
// Load search provider config from DB (defaults to DuckDuckGo if not set)
|
||||
loadSearchConfig(stores)
|
||||
}
|
||||
defer database.Close()
|
||||
|
||||
@@ -178,15 +161,6 @@ func main() {
|
||||
}
|
||||
handlers.SetStorageConfigured(objStore != nil)
|
||||
|
||||
// Filesystem-based queue for document text extraction (PDF, DOCX, etc.)
|
||||
// Nil if storage is disabled.
|
||||
if objStore != nil && cfg.StoragePath != "" {
|
||||
if err != nil {
|
||||
log.Printf("⚠ Extraction queue init failed: %v", err)
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
// ── EventBus (created early — needed by role resolver) ──
|
||||
bus := events.NewBus()
|
||||
|
||||
@@ -194,15 +168,6 @@ func main() {
|
||||
// No-op when running SQLite — in-process Bus is sufficient for single-pod.
|
||||
events.StartPGBroadcast(bus)
|
||||
|
||||
if cfg.StoragePath != "" {
|
||||
if err := wfs.Init(); err != nil {
|
||||
log.Printf("⚠ Workspace FS init failed: %v", err)
|
||||
} else {
|
||||
log.Printf(" 📁 Workspace FS initialized at %s/workspaces", cfg.StoragePath)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Sandboxed interpreter for extension scripts. Runner assembles
|
||||
// modules based on granted permissions. Notifier attached below
|
||||
// after notification service init.
|
||||
@@ -253,7 +218,7 @@ func main() {
|
||||
if stores.GlobalConfig != nil {
|
||||
if smtpCfg, err := notifications.LoadSMTPConfig(stores.GlobalConfig, keyResolver); err == nil && smtpCfg != nil {
|
||||
transport := notifications.NewEmailTransport(*smtpCfg)
|
||||
instanceName := "Chat Switchboard"
|
||||
instanceName := "Switchboard Core"
|
||||
if brandCfg, err := stores.GlobalConfig.Get(context.Background(), "branding"); err == nil {
|
||||
if name, ok := brandCfg["instance_name"].(string); ok && name != "" {
|
||||
instanceName = name
|
||||
@@ -272,8 +237,6 @@ func main() {
|
||||
defer notifSvc.StopCleanup()
|
||||
}
|
||||
|
||||
// v0.27.2: Task scheduler with executor — needs hub + notification service
|
||||
|
||||
// Health check (k8s probes hit this directly)
|
||||
base.GET("/health", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
@@ -419,48 +382,6 @@ func main() {
|
||||
c.JSON(http.StatusOK, gin.H{"ticket": ticket})
|
||||
})
|
||||
|
||||
// Channels
|
||||
|
||||
// Typing indicator broadcast (v0.23.2)
|
||||
protected.POST("/channels/:id/typing", func(c *gin.Context) {
|
||||
userID := c.GetString("user_id")
|
||||
channelID := c.Param("id")
|
||||
// Resolve display name
|
||||
var displayName string
|
||||
user, err := stores.Users.GetByID(c.Request.Context(), userID)
|
||||
if err == nil && user != nil {
|
||||
displayName = user.DisplayName
|
||||
if displayName == "" {
|
||||
displayName = user.Username
|
||||
}
|
||||
}
|
||||
if displayName == "" {
|
||||
displayName = userID[:8]
|
||||
}
|
||||
if err == nil {
|
||||
payload, _ := json.Marshal(map[string]any{
|
||||
"channel_id": channelID,
|
||||
"user_id": userID,
|
||||
"display_name": displayName,
|
||||
})
|
||||
evt := events.Event{
|
||||
Label: "typing.user",
|
||||
Payload: payload,
|
||||
Ts: time.Now().UnixMilli(),
|
||||
}
|
||||
for _, pid := range pids {
|
||||
hub.PublishToUser(pid, evt)
|
||||
}
|
||||
}
|
||||
c.JSON(200, gin.H{"ok": true})
|
||||
})
|
||||
|
||||
// Chat Folders (v0.23.1)
|
||||
protected.GET("/folders", folders.List)
|
||||
protected.POST("/folders", folders.Create)
|
||||
protected.PUT("/folders/:id", folders.Update)
|
||||
protected.DELETE("/folders/:id", folders.Delete)
|
||||
|
||||
// Presence (v0.23.1)
|
||||
presence := handlers.NewPresenceHandler(stores)
|
||||
protected.POST("/presence/heartbeat", presence.Heartbeat)
|
||||
@@ -469,15 +390,6 @@ func main() {
|
||||
// User search (v0.23.2 — DM user picker)
|
||||
protected.GET("/users/search", presence.SearchUsers)
|
||||
|
||||
// Persona groups (v0.23.2 — roster templates for group chats)
|
||||
protected.GET("/persona-groups", pgH.List)
|
||||
protected.POST("/persona-groups", pgH.Create)
|
||||
protected.GET("/persona-groups/:id", pgH.Get)
|
||||
protected.PUT("/persona-groups/:id", pgH.Update)
|
||||
protected.DELETE("/persona-groups/:id", pgH.Delete)
|
||||
protected.POST("/persona-groups/:id/members", pgH.AddMember)
|
||||
protected.DELETE("/persona-groups/:id/members/:memberId", pgH.RemoveMember)
|
||||
|
||||
// Workflows (v0.26.1 — team-owned staged processes)
|
||||
wfH := handlers.NewWorkflowHandler(stores)
|
||||
protected.GET("/workflows", wfH.List)
|
||||
@@ -494,30 +406,6 @@ func main() {
|
||||
protected.GET("/workflows/:id/versions/:version", wfH.GetVersion)
|
||||
|
||||
|
||||
// Workflow assignments (v0.26.4 — team assignment queue)
|
||||
|
||||
// Tasks (v0.27.1, permissions v0.27.2)
|
||||
|
||||
// Channel models (v0.20.0 — multi-model @mention routing)
|
||||
protected.GET("/channels/:id/models", chModelH.List)
|
||||
protected.POST("/channels/:id/models", chModelH.Add)
|
||||
protected.PATCH("/channels/:id/models/:modelId", chModelH.Update)
|
||||
protected.DELETE("/channels/:id/models/:modelId", chModelH.Delete)
|
||||
|
||||
// Channel participants (v0.23.0 — ICD §3.7)
|
||||
|
||||
// Messages
|
||||
protected.GET("/channels/:id/messages", msgs.ListMessages)
|
||||
protected.POST("/channels/:id/messages", msgs.CreateMessage)
|
||||
|
||||
// Message tree (forking)
|
||||
protected.GET("/channels/:id/path", msgs.GetActivePath)
|
||||
protected.PUT("/channels/:id/cursor", msgs.UpdateCursor)
|
||||
protected.POST("/channels/:id/messages/:msgId/edit", msgs.EditMessage)
|
||||
protected.POST("/channels/:id/messages/:msgId/regenerate", msgs.Regenerate)
|
||||
protected.GET("/channels/:id/messages/:msgId/siblings", msgs.ListSiblings)
|
||||
protected.DELETE("/channels/:id/messages/:msgId", msgs.DeleteMessage)
|
||||
|
||||
// Surface discovery (v0.25.0, v0.28.7: unified packages)
|
||||
pkgH := handlers.NewPackageHandler(stores)
|
||||
protected.GET("/surfaces", pkgH.ListEnabledSurfaces)
|
||||
@@ -532,10 +420,6 @@ func main() {
|
||||
protected.POST("/packages/install", userPkgH.InstallPersonalPackage)
|
||||
protected.DELETE("/packages/:id", userPkgH.DeletePersonalPackage)
|
||||
|
||||
|
||||
|
||||
// Provider Configs (user-facing — replaces /api-configs)
|
||||
|
||||
// Connection Type Discovery (v0.38.4)
|
||||
connTypeH := handlers.NewConnectionTypeHandler(stores)
|
||||
protected.GET("/connection-types", connTypeH.ListConnectionTypes)
|
||||
@@ -549,13 +433,6 @@ func main() {
|
||||
protected.PUT("/connections/:id", connH.UpdateConnection)
|
||||
protected.DELETE("/connections/:id", connH.DeleteConnection)
|
||||
|
||||
// Models (unified resolver — replaces scattered endpoints)
|
||||
|
||||
// Model Preferences
|
||||
protected.GET("/models/preferences", modelPrefs.GetPreferences)
|
||||
protected.PUT("/models/preferences", modelPrefs.SetPreference)
|
||||
protected.POST("/models/preferences/bulk", modelPrefs.BulkSetPreferences)
|
||||
|
||||
// User Settings & Profile
|
||||
settings := handlers.NewSettingsHandler(stores, uekCache)
|
||||
protected.GET("/profile", settings.GetProfile)
|
||||
@@ -572,33 +449,6 @@ func main() {
|
||||
bootH := handlers.NewProfileBootstrapHandler(stores)
|
||||
protected.GET("/profile/bootstrap", bootH.GetBootstrap)
|
||||
|
||||
// Usage (personal)
|
||||
protected.GET("/usage", usage.PersonalUsage)
|
||||
|
||||
// Personas
|
||||
|
||||
// Notes
|
||||
protected.GET("/notes", notes.List)
|
||||
protected.POST("/notes", notes.Create)
|
||||
protected.GET("/notes/search", notes.Search)
|
||||
protected.GET("/notes/search-titles", notes.SearchTitles)
|
||||
protected.GET("/notes/folders", notes.ListFolders)
|
||||
protected.GET("/notes/graph", notes.Graph)
|
||||
protected.POST("/notes/bulk-delete", notes.BulkDelete)
|
||||
protected.GET("/notes/:id", notes.Get)
|
||||
protected.PUT("/notes/:id", notes.Update)
|
||||
protected.DELETE("/notes/:id", notes.Delete)
|
||||
protected.GET("/notes/:id/backlinks", notes.Backlinks)
|
||||
|
||||
// Projects (v0.19.0)
|
||||
protected.POST("/projects/:id/files", projFileH.UploadToProject)
|
||||
protected.GET("/projects/:id/files", projFileH.ListByProject)
|
||||
protected.GET("/projects/:id/files/download", projFileH.DownloadProjectFile)
|
||||
protected.DELETE("/projects/:id/files", projFileH.DeleteProjectFile)
|
||||
protected.POST("/projects/:id/files/mkdir", projFileH.MkdirProject)
|
||||
protected.POST("/projects/:id/archive/upload", projFileH.UploadProjectArchive)
|
||||
protected.GET("/projects/:id/archive/download", projFileH.DownloadProjectArchive)
|
||||
|
||||
// Notifications (v0.20.0)
|
||||
notifH := handlers.NewNotificationHandler(stores, hub)
|
||||
protected.GET("/notifications", notifH.List)
|
||||
@@ -612,28 +462,6 @@ func main() {
|
||||
protected.PUT("/notifications/preferences/:type", notifH.SetPreference)
|
||||
protected.DELETE("/notifications/preferences/:type", notifH.DeletePreference)
|
||||
|
||||
// Git credentials (v0.21.4) — user-scoped, independent of workspace
|
||||
|
||||
|
||||
// Export (v0.22.4) — pandoc-based markdown → PDF/DOCX conversion
|
||||
|
||||
// Data portability (v0.34.0) — user data export/import
|
||||
protected.GET("/export/me", dataExport.ExportMyData)
|
||||
protected.POST("/import/me", dataImport.ImportMyData)
|
||||
protected.POST("/import/chatgpt", dataImport.ImportChatGPT)
|
||||
|
||||
// Hook: clean up storage files when channels are deleted
|
||||
|
||||
|
||||
// Memory management (v0.18.0)
|
||||
protected.GET("/memories", memH.ListMyMemories)
|
||||
protected.PUT("/memories/:id", memH.UpdateMemory)
|
||||
protected.DELETE("/memories/:id", memH.DeleteMemory)
|
||||
protected.POST("/memories/:id/approve", memH.ApproveMemory)
|
||||
protected.POST("/memories/:id/reject", memH.RejectMemory)
|
||||
protected.GET("/memories/count", memH.MemoryCount)
|
||||
protected.POST("/memories/compact", memH.CompactMemories)
|
||||
|
||||
// Teams (user: my teams)
|
||||
teams := handlers.NewTeamHandler(stores, keyResolver)
|
||||
protected.GET("/teams/mine", teams.MyTeams)
|
||||
@@ -654,8 +482,6 @@ func main() {
|
||||
// Team groups (team admins manage team-scoped groups)
|
||||
teamScoped.GET("/groups", groupH.ListTeamGroups)
|
||||
|
||||
// Team providers
|
||||
|
||||
// Team connections (v0.38.1)
|
||||
teamScoped.GET("/connections", teams.ListTeamConnections)
|
||||
teamScoped.POST("/connections", teams.CreateTeamConnection)
|
||||
@@ -671,25 +497,6 @@ func main() {
|
||||
teamScoped.GET("/audit", teams.ListTeamAuditLog)
|
||||
teamScoped.GET("/audit/actions", teams.ListTeamAuditActions)
|
||||
|
||||
// Team usage (team admins only — usage against team-owned providers)
|
||||
teamScoped.GET("/usage", teamUsage.TeamUsage)
|
||||
|
||||
// Team personas
|
||||
teamScoped.GET("/personas", teamPersonas.ListTeamPersonas)
|
||||
teamScoped.POST("/personas", teamPersonas.CreateTeamPersona)
|
||||
teamScoped.PUT("/personas/:id", teamPersonas.UpdateTeamPersona)
|
||||
teamScoped.DELETE("/personas/:id", teamPersonas.DeleteTeamPersona)
|
||||
teamScoped.GET("/personas/:id/knowledge-bases", teamPersonas.GetTeamPersonaKBs) // v0.17.0
|
||||
teamScoped.PUT("/personas/:id/knowledge-bases", teamPersonas.SetTeamPersonaKBs) // v0.17.0
|
||||
teamScoped.GET("/personas/:id/tool-grants", teamPersonas.GetTeamPersonaToolGrants) // v0.28.0
|
||||
teamScoped.PUT("/personas/:id/tool-grants", teamPersonas.SetTeamPersonaToolGrants) // v0.28.0
|
||||
|
||||
teamScoped.GET("/roles", teamRoles.ListTeamRoles)
|
||||
teamScoped.PUT("/roles/:role", teamRoles.UpdateTeamRole)
|
||||
teamScoped.DELETE("/roles/:role", teamRoles.DeleteTeamRole)
|
||||
|
||||
// Team workflow assignments (v0.26.4)
|
||||
|
||||
// Team workflows — self-service (v0.31.2)
|
||||
teamWfH := handlers.NewWorkflowHandler(stores)
|
||||
teamScoped.GET("/workflows", teamWfH.ListTeamWorkflows)
|
||||
@@ -705,18 +512,6 @@ func main() {
|
||||
teamScoped.POST("/workflows/:id/publish", teamWfH.PublishTeamWorkflow)
|
||||
teamScoped.GET("/workflows/:id/versions/:version", teamWfH.GetTeamWorkflowVersion)
|
||||
|
||||
// Team workflow monitoring (v0.35.0)
|
||||
|
||||
|
||||
// Team tasks — admin CRUD (v0.27.5)
|
||||
}
|
||||
|
||||
// Team task viewing for all members (v0.27.5)
|
||||
teamMemberRoutes := protected.Group("/teams/:teamId")
|
||||
teamMemberRoutes.Use(middleware.RequireTeamMember(stores.Teams))
|
||||
{
|
||||
teamMemberRoutes.GET("/tasks", teamMemberTaskH.ListTeamTasks)
|
||||
teamMemberRoutes.GET("/tasks/:id/runs", teamMemberTaskH.ListRuns)
|
||||
}
|
||||
|
||||
// Public global settings (non-admin users can read safe subset)
|
||||
@@ -756,30 +551,12 @@ func main() {
|
||||
// Stats
|
||||
admin.GET("/stats", adm.GetStats)
|
||||
|
||||
// Global Provider Configs
|
||||
|
||||
// Global Connections (v0.38.1)
|
||||
admin.GET("/connections", adm.ListGlobalConnections)
|
||||
admin.POST("/connections", adm.CreateGlobalConnection)
|
||||
admin.PUT("/connections/:id", adm.UpdateGlobalConnection)
|
||||
admin.DELETE("/connections/:id", adm.DeleteGlobalConnection)
|
||||
|
||||
// Model Catalog
|
||||
|
||||
// Personas (admin global)
|
||||
admin.GET("/personas", personaAdm.ListAdminPersonas)
|
||||
admin.POST("/personas", personaAdm.CreateAdminPersona)
|
||||
admin.PUT("/personas/:id", personaAdm.UpdateAdminPersona)
|
||||
admin.DELETE("/personas/:id", personaAdm.DeleteAdminPersona)
|
||||
admin.GET("/personas/:id/knowledge-bases", personaAdm.GetPersonaKBs) // v0.17.0
|
||||
admin.PUT("/personas/:id/knowledge-bases", personaAdm.SetPersonaKBs) // v0.17.0
|
||||
admin.GET("/personas/:id/tool-grants", personaAdm.GetPersonaToolGrants) // v0.25.0
|
||||
admin.PUT("/personas/:id/tool-grants", personaAdm.SetPersonaToolGrants) // v0.25.0
|
||||
|
||||
// Admin memory review (v0.18.0)
|
||||
admin.GET("/memories/pending", adminMemH.ListPendingReview)
|
||||
admin.POST("/memories/bulk-approve", adminMemH.BulkApprove)
|
||||
|
||||
// Teams (admin)
|
||||
teamAdm := handlers.NewTeamHandler(stores, keyResolver)
|
||||
admin.GET("/teams", teamAdm.ListTeams)
|
||||
@@ -792,10 +569,6 @@ func main() {
|
||||
admin.PUT("/teams/:id/members/:memberId", teamAdm.UpdateMember)
|
||||
admin.DELETE("/teams/:id/members/:memberId", teamAdm.RemoveMember)
|
||||
|
||||
// Team data export/import (v0.34.0)
|
||||
admin.GET("/teams/:id/export", teamExport.ExportTeam)
|
||||
admin.POST("/teams/:id/import", teamImport.ImportTeam)
|
||||
|
||||
// Admin broadcast (v0.28.6)
|
||||
adminNotifH := handlers.NewNotificationHandler(stores, hub)
|
||||
admin.POST("/notifications/broadcast", adminNotifH.Broadcast)
|
||||
@@ -823,18 +596,8 @@ func main() {
|
||||
admin.GET("/grants/:type/:id", groupAdm.GetResourceGrant)
|
||||
admin.PUT("/grants/:type/:id", groupAdm.SetResourceGrant)
|
||||
|
||||
// Projects (admin — v0.19.0)
|
||||
admin.GET("/projects", adminProjH.AdminList)
|
||||
admin.DELETE("/projects/:id", adminProjH.Delete)
|
||||
admin.DELETE("/grants/:type/:id", groupAdm.DeleteResourceGrant)
|
||||
|
||||
admin.GET("/roles", rolesH.ListRoles)
|
||||
admin.GET("/roles/:role", rolesH.GetRole)
|
||||
admin.PUT("/roles/:role", rolesH.UpdateRole)
|
||||
admin.POST("/roles/:role/test", rolesH.TestRole)
|
||||
|
||||
// Usage & Pricing
|
||||
|
||||
// Storage status
|
||||
storageH := handlers.NewStorageHandler(objStore)
|
||||
admin.GET("/storage/status", storageH.Status)
|
||||
@@ -846,12 +609,6 @@ func main() {
|
||||
emailAdm := handlers.NewAdminEmailHandler(stores)
|
||||
admin.POST("/notifications/test-email", emailAdm.TestEmail)
|
||||
|
||||
admin.GET("/storage/orphans", fileAdm.OrphanCount)
|
||||
admin.POST("/storage/cleanup", fileAdm.CleanupOrphans)
|
||||
admin.GET("/storage/extraction", fileAdm.ExtractionStatus)
|
||||
|
||||
// Archived channels (admin — v0.23.2)
|
||||
|
||||
// Extensions (admin)
|
||||
extAdm := handlers.NewExtensionHandler(stores)
|
||||
admin.GET("/extensions", extAdm.AdminListExtensions)
|
||||
@@ -873,27 +630,6 @@ func main() {
|
||||
admin.PUT("/extensions/:id/secrets", extSecH.SetSecrets)
|
||||
admin.DELETE("/extensions/:id/secrets", extSecH.DeleteSecrets)
|
||||
|
||||
admin.GET("/dashboard", dashAdm.GetDashboard)
|
||||
|
||||
admin.GET("/providers/health", healthAdm.GetAllProviderHealth)
|
||||
admin.GET("/providers/:id/health", healthAdm.GetProviderHealth)
|
||||
|
||||
// Capability Overrides (admin — v0.22.0)
|
||||
admin.GET("/models/:id/capabilities", capAdm.GetModelCapabilities)
|
||||
admin.PUT("/models/:id/capabilities", capAdm.SetModelCapability)
|
||||
admin.DELETE("/models/:id/capabilities/:overrideId", capAdm.DeleteModelCapability)
|
||||
admin.GET("/capability-overrides", capAdm.ListAllOverrides)
|
||||
|
||||
// Provider Types (admin — v0.22.1)
|
||||
admin.GET("/provider-types", handlers.GetProviderTypes)
|
||||
|
||||
admin.GET("/routing/policies", routingAdm.ListPolicies)
|
||||
admin.GET("/routing/policies/:id", routingAdm.GetPolicy)
|
||||
admin.POST("/routing/policies", routingAdm.CreatePolicy)
|
||||
admin.PUT("/routing/policies/:id", routingAdm.UpdatePolicy)
|
||||
admin.DELETE("/routing/policies/:id", routingAdm.DeletePolicy)
|
||||
admin.POST("/routing/test", routingAdm.TestRouting)
|
||||
|
||||
// Package lifecycle management (v0.28.7 — replaces surfaces + extensions admin)
|
||||
packagesDir := ""
|
||||
if cfg.StoragePath != "" {
|
||||
@@ -920,15 +656,10 @@ func main() {
|
||||
admin.POST("/packages/:id/test-tool", pkgAdm.TestTool) // v0.38.2
|
||||
admin.GET("/dependencies", pkgAdm.ListAllDependencies) // v0.38.2
|
||||
|
||||
// Package export (v0.30.0)
|
||||
admin.GET("/packages/:id/export", pkgExport.ExportPackage)
|
||||
|
||||
// Workflow package export (v0.30.2)
|
||||
wfPkgH := handlers.NewWorkflowPackageHandler(stores)
|
||||
admin.GET("/workflows/:id/export", wfPkgH.ExportWorkflowPackage)
|
||||
|
||||
// Workflow monitoring (v0.35.0)
|
||||
|
||||
// Surface aliases (backward compat — same handlers)
|
||||
admin.GET("/surfaces", pkgAdm.ListPackages)
|
||||
admin.GET("/surfaces/:id", pkgAdm.GetPackage)
|
||||
@@ -937,20 +668,10 @@ func main() {
|
||||
admin.PUT("/surfaces/:id/disable", pkgAdm.DisablePackage)
|
||||
admin.DELETE("/surfaces/:id", pkgAdm.DeletePackage)
|
||||
|
||||
// Task management — admin (v0.27.1, extended v0.27.2)
|
||||
admin.GET("/tasks", taskAdm.ListAll)
|
||||
admin.POST("/tasks/:id/run", taskAdm.RunNow)
|
||||
admin.POST("/tasks/:id/kill", taskAdm.KillRun)
|
||||
admin.DELETE("/tasks/:id", taskAdm.Delete)
|
||||
admin.GET("/system-functions", taskAdm.ListSystemFunctions)
|
||||
}
|
||||
}
|
||||
|
||||
// ── Page Routes (v0.22.5) ────────────────
|
||||
// Server-rendered pages via Go templates. Runs alongside the SPA.
|
||||
// The chat surface is a bridge: Go renders the shell, existing JS
|
||||
// builds the DOM inside it — identical behavior to index.html.
|
||||
|
||||
// ── Page Routes ──────────────────────────
|
||||
// v0.27.0: Extension surface static assets (JS, CSS, images).
|
||||
// Served without auth — same rationale as extension assets (script tags can't send headers).
|
||||
// v0.28.7: on-disk path moved to /data/packages/, URL stays /surfaces/:id/ for stability.
|
||||
@@ -996,32 +717,11 @@ func main() {
|
||||
extAPI.Any("/*path", extAPIH.Handle)
|
||||
}
|
||||
|
||||
// Workflow API — session participants can send messages + trigger completions
|
||||
wfAPI := base.Group("/api/v1/w")
|
||||
wfAPI.Use(middleware.AuthOrSession(cfg, stores, userCache))
|
||||
{
|
||||
wfAPI.POST("/:id/messages", wfMsgs.CreateMessage)
|
||||
wfAPI.GET("/:id/messages", wfMsgs.ListMessages)
|
||||
|
||||
wfAPI.POST("/:id/completions", wfComp.Complete)
|
||||
|
||||
wfAPI.GET("/:id/form", wfForms.GetFormTemplate)
|
||||
wfAPI.POST("/:id/form-submit", wfForms.SubmitForm)
|
||||
}
|
||||
|
||||
// Workflow visitor entry (v0.26.3) — public start endpoint
|
||||
// NOTE: Cannot use /api/v1/w/:scope/:slug/start — Gin's radix trie
|
||||
// conflicts with /api/v1/w/:id/messages (different wildcard names at
|
||||
// same path position). Separate namespace avoids the collision.
|
||||
base.POST("/api/v1/workflow-entry/:scope/:slug", wfEntry.StartVisitor)
|
||||
|
||||
// v0.28.0: Webhook trigger endpoint (token-based auth, no JWT)
|
||||
|
||||
bp := cfg.BasePath
|
||||
if bp == "" {
|
||||
bp = "/"
|
||||
}
|
||||
log.Printf("🔀 Chat Switchboard API v%s starting on port %s", Version, cfg.Port)
|
||||
log.Printf("🔀 Switchboard Core v%s starting on port %s", Version, cfg.Port)
|
||||
log.Printf(" Base path: %s", bp)
|
||||
log.Printf(" Schema: %s", database.SchemaVersion())
|
||||
if objStore != nil {
|
||||
@@ -1038,9 +738,6 @@ func main() {
|
||||
|
||||
// ── Vault CLI Commands ──────────────────────
|
||||
|
||||
// loadSearchConfig reads search provider config from global_config and applies it.
|
||||
// Falls back to DuckDuckGo (the default set in search package init) if not configured.
|
||||
|
||||
func runVaultCommand(subcmd string) {
|
||||
cfg := config.Load()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user