mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-15 14:16:30 +00:00
feat(desktop): add channel management, paired devices, and multiple fixes
Channel Management:
- Add Channels settings tab with full CRUD for Telegram/Discord (Lite: max 1 each)
- Channel detail panel with tabs: General, Credentials, Managers
- Advanced settings dialog (network, limits, streaming, behavior, access control)
- Schema-driven field renderer with Combobox selects, Switch toggles
- Paired Devices section: approve/deny pending, revoke paired, WS event auto-refresh
- Pairing notification badge in sidebar footer with pending count
- i18n support (en/vi/zh) for all channel strings
Bug Fixes:
- Fix Vietnamese slug generation (NFD normalize + đ/Đ handling) in lib/slug.ts
- Make agent key field editable instead of read-only
- Fix trace detail input/output: use MarkdownRenderer with copy button instead of forced-dark CodePreview
- Fix API error parsing to handle both {error: "string"} and {error: {message}} formats
- Add Accept-Language header to desktop API client for i18n error messages
- Wrap raw err.Error() with i18n messages in HTTP handlers (agents, channel_instances)
- Increase SQLite MaxOpenConns from 2 to 4 to reduce SQLITE_BUSY contention
- Add retryOnBusy wrapper for context file seeding writes
- Update EditionCompareModal: channels moved from "false" to "1 Telegram + 1 Discord"
This commit is contained in:
1 parent
2bc0f5f14a
commit
6ea9b4d762
40 files changed
+2346
-64
No files matched your search
@@ -190,7 +190,8 @@ func (h *AgentsHandler) handleCreate(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.Contains(err.Error(), "duplicate key") || strings.Contains(err.Error(), "23505") {
|
||||
writeJSON(w, http.StatusConflict, map[string]string{"error": i18n.T(locale, i18n.MsgAlreadyExists, "agent", req.AgentKey)})
|
||||
} else {
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
slog.Error("agents.create", "agent_key", req.AgentKey, "error", err)
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": i18n.T(locale, i18n.MsgFailedToCreate, "agent", "internal error")})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ func (h *ChannelInstancesHandler) handleCreate(w http.ResponseWriter, r *http.Re
|
||||
|
||||
if err := h.store.Create(r.Context(), inst); err != nil {
|
||||
slog.Error("channel_instances.create", "error", err)
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": i18n.T(locale, i18n.MsgFailedToCreate, "channel instance", "internal error")})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ func (h *ChannelInstancesHandler) handleUpdate(w http.ResponseWriter, r *http.Re
|
||||
|
||||
if err := h.store.Update(r.Context(), id, updates); err != nil {
|
||||
slog.Error("channel_instances.update", "error", err)
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": i18n.T(locale, i18n.MsgFailedToUpdate, "channel instance", "internal error")})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ func (h *ChannelInstancesHandler) handleDelete(w http.ResponseWriter, r *http.Re
|
||||
|
||||
if err := h.store.Delete(r.Context(), id); err != nil {
|
||||
slog.Error("channel_instances.delete", "error", err)
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": i18n.T(locale, i18n.MsgFailedToDelete, "channel instance", "internal error")})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user