feat(gateway): 消息mode落库(A3) — 持久化真实写入渲染模式
- POST /api/v1/chat 与 ws.chat 上行新增可选 mode(行为模式 design/01 §3/design/16 §5.1) - Web路径经ctx透传本轮mode到编排器持久化(persistUserMessages/persistAssistantReply),缺省回落chat - pendingMsg记录mode,恢复/续接路径沿用发起轮次mode - IM路径(persistToMain/persistIsolated)恒为chat - 新增/扩充测试:REST/WS/orchestrator/channelbridge 覆盖mode写入 - Docs/api-client.md v0.20 同步mode字段
This commit is contained in:
1 parent
fe5dbcddba
commit
b686d5fec8
9 files changed
+199
-41
No files matched your search
@@ -315,14 +315,17 @@ func TestOwnerPrivatePersistsToMainSessionWithPlatform(t *testing.T) {
|
||||
if len(recs) != 2 {
|
||||
t.Fatalf("appends = %d, want 2 (user + assistant)", len(recs))
|
||||
}
|
||||
// Both land on the main web session and carry the channel platform + adapter.
|
||||
// Both land on the main web session and carry the channel platform + adapter,
|
||||
// and IM messages are always persisted in chat mode (design/16 §5.1).
|
||||
if recs[0].SessionID != history.MainSessionID || recs[0].Role != history.RoleUser ||
|
||||
recs[0].Content != "hello" || recs[0].Platform != "telegram" || recs[0].AdapterID != "telegram" {
|
||||
t.Fatalf("user record = %+v, want web/telegram/hello/telegram", recs[0])
|
||||
recs[0].Content != "hello" || recs[0].Platform != "telegram" || recs[0].AdapterID != "telegram" ||
|
||||
recs[0].Mode != "chat" {
|
||||
t.Fatalf("user record = %+v, want web/telegram/hello/telegram/chat", recs[0])
|
||||
}
|
||||
if recs[1].SessionID != history.MainSessionID || recs[1].Role != history.RoleAssistant ||
|
||||
recs[1].Content != "微信回复" || recs[1].Platform != "telegram" || recs[1].AdapterID != "telegram" {
|
||||
t.Fatalf("assistant record = %+v, want web/telegram/微信回复/telegram", recs[1])
|
||||
recs[1].Content != "微信回复" || recs[1].Platform != "telegram" || recs[1].AdapterID != "telegram" ||
|
||||
recs[1].Mode != "chat" {
|
||||
t.Fatalf("assistant record = %+v, want web/telegram/微信回复/telegram/chat", recs[1])
|
||||
}
|
||||
// Every persisted message was handed to the broadcast hook.
|
||||
if len(persisted) != 2 {
|
||||
@@ -414,6 +417,10 @@ func TestGroupMessageNotPersistedToMainSession(t *testing.T) {
|
||||
if rec.Platform != "telegram" {
|
||||
t.Fatalf("record[%d] Platform = %q, want telegram", i, rec.Platform)
|
||||
}
|
||||
// Isolated IM messages are still chat-mode (design/16 §5.1).
|
||||
if rec.Mode != "chat" {
|
||||
t.Fatalf("record[%d] Mode = %q, want chat", i, rec.Mode)
|
||||
}
|
||||
}
|
||||
if chat.sessionID != "sess-g" {
|
||||
t.Fatalf("group loop session id = %q, want sess-g", chat.sessionID)
|
||||
|
||||
@@ -14,6 +14,10 @@ import (
|
||||
// without a refresh. Kept separate from channelbridge.go so the bridge's inbound
|
||||
// pipeline file stays under the module size bound.
|
||||
|
||||
// modeChat is the behavior mode written for every IM-persisted message: IM carries
|
||||
// chat text alone (design/02 §1 单向回流), so no other mode ever applies there.
|
||||
const modeChat = "chat"
|
||||
|
||||
// SetOnPersisted wires (or replaces) the transport hook called after an
|
||||
// owner-private message is persisted into the main web session. The gateway is
|
||||
// built after the bridge in the composition root, so the hook is attached post-New
|
||||
@@ -60,7 +64,7 @@ func (b *Bridge) persistToMain(ctx context.Context, role, content, platform, dev
|
||||
return
|
||||
}
|
||||
full, err := b.history.AppendFull(ctx, history.Message{
|
||||
SessionID: history.MainSessionID, Role: role, Content: content, Platform: platform, DeviceID: deviceID, AdapterID: adapterID,
|
||||
SessionID: history.MainSessionID, Role: role, Content: content, Platform: platform, DeviceID: deviceID, AdapterID: adapterID, Mode: modeChat,
|
||||
})
|
||||
if err != nil {
|
||||
b.log.Warn("persist main session", "err", err, "role", role, "platform", platform, "device_id", deviceID, "adapter", adapterID)
|
||||
@@ -85,7 +89,7 @@ func (b *Bridge) persistIsolated(ctx context.Context, role, content, deviceID st
|
||||
}
|
||||
full, err := b.history.AppendFull(ctx, history.Message{
|
||||
SessionID: sess.SessionID, Role: role, Content: content, Platform: platform,
|
||||
DeviceID: deviceID, SenderName: senderName, AdapterID: adapterID,
|
||||
DeviceID: deviceID, SenderName: senderName, AdapterID: adapterID, Mode: modeChat,
|
||||
})
|
||||
if err != nil {
|
||||
b.log.Warn("persist isolated session", "err", err, "role", role,
|
||||
|
||||
Reference in new issue
Block a user