惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

美团技术团队
J
Java Code Geeks
有赞技术团队
有赞技术团队
GbyAI
GbyAI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 叶小钗
阮一峰的网络日志
阮一峰的网络日志
Microsoft Security Blog
Microsoft Security Blog
IT之家
IT之家
G
Google Developers Blog
月光博客
月光博客
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
S
SegmentFault 最新的问题
博客园 - 三生石上(FineUI控件)
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - Franky
腾讯CDC
V
Visual Studio Blog
博客园 - 【当耐特】
D
Docker
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Engineering at Meta
Engineering at Meta
L
LangChain Blog

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix(qa): prove direct reply routing via qa channel · open...
vincentkoc · 2026-06-24 · via Recent Commits to openclaw:main

@@ -11,6 +11,9 @@ scenario:

1111

- tools.message

1212

- channels.webchat

1313

objective: Verify a current-chat reply is delivered as assistant text, not by calling `message(action=send)` and ending with `Sent.`.

14+

gatewayConfigPatch:

15+

session:

16+

dmScope: per-channel-peer

1417

successCriteria:

1518

- The visible outbound reply contains the requested marker exactly once.

1619

- The session transcript does not include a `message(action=send)` call followed by final assistant text `Sent.`.

@@ -24,7 +27,9 @@ scenario:

2427

kind: flow

2528

summary: Run a direct current-chat reply and inspect the actual transcript for self-message routing.

2629

config:

30+

conversationId: qa-operator

2731

expectedMarker: WEBCHAT-DIRECT-REPLY-OK

32+

promptSnippet: Reply exactly

28332934

flow:

3035

steps:

@@ -39,31 +44,56 @@ flow:

3944

- ref: env

4045

- 60000

4146

- call: reset

47+

- set: conversationId

48+

value:

49+

expr: config.conversationId

4250

- set: sessionKey

4351

value:

44-

expr: "`agent:qa:webchat-direct-reply:${randomUUID().slice(0, 8)}`"

52+

expr: "buildAgentSessionKey({ agentId: 'qa', channel: 'qa-channel', accountId: 'default', peer: { kind: 'direct', id: `dm:${conversationId}` }, dmScope: env.cfg.session?.dmScope, identityLinks: env.cfg.session?.identityLinks })"

4553

- set: startIndex

4654

value:

4755

expr: state.getSnapshot().messages.length

48-

- call: runAgentPrompt

49-

args:

50-

- ref: env

51-

- sessionKey:

52-

ref: sessionKey

53-

message:

54-

expr: "`Reply directly in this current chat with exactly ${config.expectedMarker}. Do not call the message tool.`"

55-

timeoutMs:

56-

expr: liveTurnTimeoutMs(env, 60000)

57-

- call: waitForOutboundMessage

58-

saveAs: outbound

56+

- set: requestCountBefore

57+

value:

58+

expr: "env.mock ? (await fetchJson(`${env.mock.baseUrl}/debug/requests`)).length : 0"

59+

- call: state.addInboundMessage

5960

args:

60-

- ref: state

61-

- lambda:

62-

params: [candidate]

63-

expr: "candidate.conversation.id === 'qa-operator' && normalizeLowercaseStringOrEmpty(candidate.text).includes(normalizeLowercaseStringOrEmpty(config.expectedMarker))"

64-

- expr: liveTurnTimeoutMs(env, 30000)

65-

- sinceIndex:

66-

ref: startIndex

61+

- conversation:

62+

id:

63+

ref: conversationId

64+

kind: direct

65+

senderId:

66+

ref: conversationId

67+

senderName: WebChat QA

68+

text:

69+

expr: "`Reply exactly \\`${config.expectedMarker}\\` in this current chat. Do not call the message tool.`"

70+

- try:

71+

actions:

72+

- call: waitForCondition

73+

saveAs: scenarioRequest

74+

args:

75+

- lambda:

76+

async: true

77+

expr: "env.mock ? (await fetchJson(`${env.mock.baseUrl}/debug/requests`)).slice(requestCountBefore).find((request) => String(request.allInputText ?? '').includes(config.promptSnippet)) : true"

78+

- expr: liveTurnTimeoutMs(env, 60000)

79+

- 500

80+

- call: waitForOutboundMessage

81+

saveAs: outbound

82+

args:

83+

- ref: state

84+

- lambda:

85+

params: [candidate]

86+

expr: "candidate.conversation.id === conversationId && normalizeLowercaseStringOrEmpty(candidate.text).includes(normalizeLowercaseStringOrEmpty(config.expectedMarker))"

87+

- expr: liveTurnTimeoutMs(env, 60000)

88+

- sinceIndex:

89+

ref: startIndex

90+

catchAs: directReplyError

91+

catch:

92+

- set: directReplyDebugRequests

93+

value:

94+

expr: "env.mock ? (await fetchJson(`${env.mock.baseUrl}/debug/requests`)).slice(requestCountBefore).map((request) => ({ plannedToolName: request.plannedToolName ?? null, plannedToolArgs: request.plannedToolArgs ?? null, allInputText: String(request.allInputText ?? '').slice(0, 400), finalText: String(request.finalText ?? '').slice(0, 200), toolOutput: request.toolOutput ? String(request.toolOutput).slice(0, 200) : null })) : []"

95+

- throw:

96+

expr: "`direct reply marker missing: ${directReplyError?.message ?? directReplyError}; transcript=${formatTransportTranscript(state, { conversationId })}; requests=${JSON.stringify(directReplyDebugRequests)}`"

6797

- set: transcriptSummary

6898

value:

6999

expr: "await readSessionTranscriptSummary(env, sessionKey)"