feat: KOOK自动获取bot身份 + action/narration剥出气泡 + 渠道配置表单回填
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

agent-116 KOOK token即用+自动获取:
- kook/identity.go: Connect 调 GET /user/me 拿 bot 身份(bot_id/bot_username/bot_nickname), 失败容错
- 渠道列表 enrichAccountsWithBot 附 bot 身份; base_url空用默认/receive_mode默认ws(只填token可跑)

agent-117 action/narration 剥出气泡(主人需求: 动作/旁白不进气泡,按位置上/下):
- parseContent.splitBubble(content)->{body,head,tail}: body=纯文本(去标签), head=开头/中间action/narr(气泡上), tail=结尾(气泡下)
- renderContent 只渲染text(去内联灰斜体); chat.tsx BubbleNotes 泡外 *动作/旁白* 灰斜体小字(气泡外依附), SplitChatBubble 先剥splitBubble再splitParagraphs(body), <p>/\n\n/毛玻璃/SourceLabel不破坏
- 注: 非chat mode renderContent 现在丢弃action/narr(可接受)

Channels 配置表单回填(修save后输入框空):
- openConfig 从 data.accounts[0].config 回填 token(掩码提示)/base_url/平台字段/黑白名单/限流, 不再硬清空
全仓 build/vet/test绿+前端build绿
This commit is contained in:
Aska committed 2026-09-07 15:31:14 +08:00
1 parent bdd9d752e1
commit 65091f6497
15 files changed
+571 -83

No files matched your search

+18 -2
View File
@@ -75,6 +75,11 @@ type Adapter struct {
chatsMu sync.RWMutex
chats map[string]adapter.ChannelInfo
botMu sync.RWMutex
botID string
botUsername string
botNickname string
}
// Compile-time assertion that Adapter satisfies the shared contract.
@@ -117,6 +122,7 @@ func (a *Adapter) Name() string { return platformName }
// this map must treat them as secrets (the admin read path masks these keys via
// the "token"/"key" substring rules).
func (a *Adapter) Config() map[string]any {
id, username, nickname := a.botIdentitySnapshot()
return map[string]any{
"bot_token": a.cfg.BotToken,
"base_url": a.baseURL,
@@ -124,6 +130,9 @@ func (a *Adapter) Config() map[string]any {
"webhook_path": a.cfg.WebhookPath,
"webhook_verify_token": a.cfg.WebhookVerifyToken,
"webhook_encrypt_key": a.cfg.WebhookEncryptKey,
"bot_id": id,
"bot_username": username,
"bot_nickname": nickname,
}
}
@@ -149,9 +158,12 @@ func (a *Adapter) Connect(ctx context.Context) error {
// Webhook mode: the Cyrene gateway mounts InboundHandler to receive KOOK
// callbacks (KOOK posts to the configured route). No gateway WebSocket is
// dialed — webhook and websocket are mutually exclusive. Mark connected so the
// REST reply path and HealthCheck see a live session.
// dialed — webhook and websocket are mutually exclusive. The bot identity
// lookup is best-effort (a bad token or network hiccup logs a warning and
// leaves the identity empty, never aborting the connect), and Mark connected
// so the REST reply path and HealthCheck see a live session.
if mode == modeWebhook {
a.refreshBotIdentity(ctx)
a.mu.Lock()
a.connected = true
a.mu.Unlock()
@@ -163,6 +175,10 @@ func (a *Adapter) Connect(ctx context.Context) error {
return fmt.Errorf("kook: connect: %w", err)
}
// Best-effort bot identity (user/me) so the admin list shows who the bot is.
// Failure here is non-fatal: the gateway URL above already validated the token.
a.refreshBotIdentity(ctx)
lifeCtx, cancel := context.WithCancel(context.Background())
a.mu.Lock()
a.cancel = cancel