Skip to content

fix: ensure assistantTexts populated at message_end for custom providers (#69410)#69724

Closed
EronFan wants to merge 4 commits into
openclaw:mainfrom
EronFan:fix/69410-custom-provider-payloads
Closed

fix: ensure assistantTexts populated at message_end for custom providers (#69410)#69724
EronFan wants to merge 4 commits into
openclaw:mainfrom
EronFan:fix/69410-custom-provider-payloads

Conversation

@EronFan
Copy link
Copy Markdown
Contributor

@EronFan EronFan commented Apr 21, 2026

问题

#69410:Custom provider 返回有效内容但 agent payloads=0。

根因

finalizeAssistantTexts 中当 onBlockReply 存在时(标准 agent 调用),else if (!addedDuringMessage && !chunkerHasBuffered && text) 不满足,因为第一个分支条件不满足。custom provider 场景下流式文本未加入 assistantTexts,message_end 提取的文本两个分支都不满足 → assistantTexts 空 → payloads=0

修复

else if 改为独立 if,确保 message_end 文本无条件加入 assistantTexts

测试覆盖

3 tests passed (21ms).

@EronFan EronFan requested a review from a team as a code owner April 21, 2026 13:42
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: M r: too-many-prs Auto-close: author has more than twenty active PRs. labels Apr 21, 2026
@openclaw-barnacle
Copy link
Copy Markdown

Closing this PR because the author has more than 10 active PRs in this repo. Please reduce the active PR queue and reopen or resubmit once it is back under the limit. You can close your own PRs to get back under the limit.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 21, 2026

Greptile Summary

This PR fixes a bug where custom OpenAI-compatible providers that omit text_end events end up with assistantTexts empty (and thus payloads=0) by changing an else if to a standalone if in finalizeAssistantTexts. The existing pushAssistantText deduplication guard prevents any double-add in the scenarios where both branches would now execute. The PR also includes: startedAt clamping in the task registry to suppress false-positive inconsistent_timestamps audit warnings from clock-skew, bind-mount awareness in the sandbox FS bridge, and a new ariaSnapshotNodes mechanism for resolving ax<number> refs via getByRole.

Confidence Score: 5/5

Safe to merge; all findings are minor style suggestions with no blocking logic issues.

The core fix is correct and well-tested: converting else if to if in finalizeAssistantTexts is safe because pushAssistantText already deduplicates via shouldSkipAssistantText. Supporting changes (task-registry clamping, bind-mount support, aria snapshot node caching) are all independently tested and logically sound. No P0 or P1 issues found.

No files require special attention.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/browser/src/browser/pw-tools-core.snapshot.ts
Line: 65

Comment:
**`nth` field not forwarded when storing aria snapshot nodes**

`AriaSnapshotNode` does not currently include `nth`, so this mapping is complete for the moment. However, `storeAriaSnapshotNodes` and `refLocator` already support `nth` for disambiguation, and if the AX-tree pipeline ever adds it to the type, the field would be silently dropped here. Consider documenting the intentional omission with a comment so reviewers aren't left wondering.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix: ensure assistantTexts populated at ..." | Re-trigger Greptile

page,
cdpUrl: opts.cdpUrl,
targetId: opts.targetId,
nodes: formatted.map((n) => ({ ref: n.ref, role: n.role, name: n.name || undefined })),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 nth field not forwarded when storing aria snapshot nodes

AriaSnapshotNode does not currently include nth, so this mapping is complete for the moment. However, storeAriaSnapshotNodes and refLocator already support nth for disambiguation, and if the AX-tree pipeline ever adds it to the type, the field would be silently dropped here. Consider documenting the intentional omission with a comment so reviewers aren't left wondering.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/browser/src/browser/pw-tools-core.snapshot.ts
Line: 65

Comment:
**`nth` field not forwarded when storing aria snapshot nodes**

`AriaSnapshotNode` does not currently include `nth`, so this mapping is complete for the moment. However, `storeAriaSnapshotNodes` and `refLocator` already support `nth` for disambiguation, and if the AX-tree pipeline ever adds it to the type, the field would be silently dropped here. Consider documenting the intentional omission with a comment so reviewers aren't left wondering.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8979096ea4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

page,
cdpUrl: opts.cdpUrl,
targetId: opts.targetId,
nodes: formatted.map((n) => ({ ref: n.ref, role: n.role, name: n.name || undefined })),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve AX ref uniqueness when caching aria snapshot nodes

snapshotAriaViaPlaywright stores each ax<number> entry with only {ref, role, name}, but refLocator can only disambiguate duplicate role/name matches when nth is present. In pages with repeated accessible names (e.g. two "Submit" buttons), both refs resolve to the same getByRole(...) locator set, which can produce strict-mode failures or target the wrong element. This breaks the new ax-ref resolution path for common UIs with duplicate names.

Useful? React with 👍 / 👎.

Comment on lines +334 to +337
roleRefsByTarget.set(roleRefsKey(opts.cdpUrl, targetId), {
refs: {},
ariaSnapshotNodes: opts.nodes,
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Enforce cache cap when creating aria-only target entries

storeAriaSnapshotNodes inserts a new roleRefsByTarget entry when none exists, but unlike rememberRoleRefsForTarget it never applies the MAX_ROLE_REFS_CACHE eviction loop. Repeated aria snapshots across many targets can therefore grow this map unbounded (bypassing the intended size limit of 50), which is a memory regression introduced by the new cache write path.

Useful? React with 👍 / 👎.

Comment on lines +266 to +270
mounts.push({
containerRoot: parsed.containerRoot,
hostRoot: parsed.hostRoot,
writable: parsed.writable,
source: "bind",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve bind-mount precedence for equal container roots

This adds bind mounts to getMounts, but resolveMountByContainerPath still chooses mounts only by containerRoot length; equal-length roots keep insertion order, so the default workspace mount wins over a custom bind mounted at the same path (e.g. /workspace). That causes path resolution and writable checks to ignore the override mount, which can route operations against the wrong effective mount configuration.

Useful? React with 👍 / 👎.

@lmcpixs
Copy link
Copy Markdown

lmcpixs commented Apr 22, 2026

The core fix for #69410 looks correct: making the message_end text append unconditional in finalizeAssistantTexts() should prevent the payloads=0 regression for custom OpenAI-compatible providers.

That said, this PR is broader than the bug fix and includes unrelated browser/sandbox changes. I’d recommend splitting those out into follow-up PRs, since they introduce separate risks:

  • aria snapshot cache eviction / AX ref uniqueness
  • bind-mount precedence in remote-fs resolution

Suggestion: land the minimal pi-embedded-subscribe.ts fix + regression test first, then revisit the unrelated changes separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling r: too-many-prs Auto-close: author has more than twenty active PRs. size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants