Skip to content

feat[ui]: Add pending changes view to raw config mode with lazy JSON …#48621

Closed
JiajunBernoulli wants to merge 3 commits intoopenclaw:mainfrom
JiajunBernoulli:ui/raw-json-diff-test
Closed

feat[ui]: Add pending changes view to raw config mode with lazy JSON …#48621
JiajunBernoulli wants to merge 3 commits intoopenclaw:mainfrom
JiajunBernoulli:ui/raw-json-diff-test

Conversation

@JiajunBernoulli
Copy link
Copy Markdown

…diff comparison

  • Add rawDiffRevealed state to ConfigEphemeralState
  • Create computeRawDiff function using JSON5 parsing
  • Add collapsible diff panel for raw mode (default collapsed)
  • Add json5 dependency to UI package
  • Maintain same UI pattern as form mode

Summary

Describe the problem and fix in 2–5 bullets:

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #

User-visible / Behavior Changes

List user-visible changes (including defaults/config).
If none, write None.

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS:
  • Runtime/container:
  • Model/provider:
  • Integration/channel (if any):
  • Relevant config (redacted):

Steps

Expected

Actual

Evidence

Not View
截屏2026-03-15 08 58 37

View
截屏2026-03-15 08 57 31

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:
  • Edge cases checked:
  • What you did not verify:

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes/No)
  • Config/env changes? (Yes/No)
  • Migration needed? (Yes/No)
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly:
  • Files/config to restore:
  • Known bad symptoms reviewers should watch for:

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk:
    • Mitigation:

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 17, 2026

Greptile Summary

This PR adds a collapsible "pending changes" diff panel to the raw (JSON5) config editor, matching the UX already present in form mode. It introduces json5 as a dependency, a computeRawDiff helper, and a new rawDiffRevealed flag to lazily drive the diff computation.

Key findings:

  • Re-render hack (P1): The @toggle handler on the <details> panel calls props.onRawChange(props.raw) with the unchanged raw string as the only way to force a re-render after mutating the module-level cvs state. If onRawChange de-duplicates identical values (a common and reasonable optimisation), the re-render will silently not fire — meaning the diff will never be populated when the user first opens the panel, and they'll always see the "Changes detected (JSON diff not available)" fallback message.
  • Confusing state naming (P2): rawDiffRevealed tracks panel open/closed state, not value revelation, yet it lives next to rawRevealed which specifically means "show sensitive values." Renaming to rawDiffExpanded or rawDiffOpen would prevent future confusion, especially since renderRawDiffValue reads both flags.
  • The sensitive-value redaction in renderRawDiffValue correctly delegates to cvs.rawRevealed, consistent with the rest of the file.

Confidence Score: 3/5

  • Mostly safe but the re-render mechanism is fragile and may silently produce a broken diff panel in some host implementations.
  • The feature logic and sensitive-value handling are sound, and the new dependency is low-risk. However, the onRawChange(props.raw) re-render hack is a real functional defect — if the parent component deduplicates unchanged values (which is common), the diff content will never be displayed when the panel is first opened, making the entire feature effectively broken in that scenario. This warrants fixing before merge.
  • ui/src/ui/views/config.ts — specifically the @toggle handler at line 989–993 and the rawDiffRevealed naming at line 650.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: ui/src/ui/views/config.ts
Line: 989-993

Comment:
**`onRawChange` misused to force re-render**

The `@toggle` handler calls `props.onRawChange(props.raw)` with the **unchanged** raw string as a hack to trigger a re-render after `cvs.rawDiffRevealed` is mutated. This is fragile in two ways:

1. If `onRawChange` de-duplicates (i.e. bails out early when the new value equals the current value), the re-render never fires. `cvs.rawDiffRevealed` will be `true` in memory, but `rawDiff` (which is only computed when `cvs.rawDiffRevealed` is `true`) will still be `[]` because `renderConfig` wasn't re-invoked. The user will see the fallback "Changes detected (JSON diff not available)" message even though a proper diff could be produced.

2. Even when it does trigger a re-render, calling a "content changed" callback with an identical value is semantically incorrect and may have unintended side effects upstream (e.g. resetting debounce timers, dirtying change-tracking state, etc.).

A cleaner fix is to compute the diff eagerly regardless of `rawDiffRevealed`, or expose a dedicated `onRequestUpdate` / `onStateChange` prop for re-render requests that carry no content semantics:

```
@toggle=${(e: Event) => {
  const details = e.target as HTMLDetailsElement;
  cvs.rawDiffRevealed = details.open;
  props.onRawChange(props.raw); // BUG: unchanged value — replace with a dedicated re-render trigger
}}
```

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

---

This is a comment left during a code review.
Path: ui/src/ui/views/config.ts
Line: 650

Comment:
**Misleading field name: `rawDiffRevealed` vs `rawRevealed`**

In this file, the existing `rawRevealed` flag means "the user has opted-in to showing sensitive/redacted values in the raw editor." The new `rawDiffRevealed` field, however, tracks whether the diff `<details>` panel is expanded — an entirely different concept (panel visibility, not value revelation).

This naming collision makes it easy to confuse the two flags (e.g. `renderRawDiffValue` already references both — `rawRevealed` for redaction logic and `rawDiffRevealed` implicitly through the lazy-diff guard). Consider renaming to `rawDiffExpanded` or `rawDiffOpen` to make the semantics distinct at a glance.

```suggestion
  rawDiffExpanded: boolean;
```

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

Last reviewed commit: ab8ab44

Comment thread ui/src/ui/views/config.ts
Comment thread ui/src/ui/views/config.ts
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: c873bf3d3b

ℹ️ 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".

Comment thread ui/src/ui/views/config.ts
@BunsDev BunsDev self-assigned this Mar 17, 2026
@JiajunBernoulli
Copy link
Copy Markdown
Author

JiajunBernoulli commented Mar 17, 2026

@BunsDev Are you reviewing it?

I have submitted this PR multiple times, but it has not yet received a review.

To keep it up to date, I will periodically rebase it onto main and it troubles me.

If possible, I would greatly appreciate your assistance in reviewing and merging this ready-to-merge PR: #46654

Thanks a lot

@JiajunBernoulli
Copy link
Copy Markdown
Author

@BunsDev Are you reviewing it?

@BunsDev
Copy link
Copy Markdown
Member

BunsDev commented Apr 9, 2026

Please resolve conflicts and then ping me here again and I will work on it ASAP @JiajunBernoulli also resolve convos, where appropriate. Thanks so much for your patience and contribution!

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: 0e77b3b78f

ℹ️ 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".

Comment thread ui/src/ui/views/config.ts
@JiajunBernoulli
Copy link
Copy Markdown
Author

@BunsDev CI Failed because 110782a26a and c6d0baf562

should I fix them in this PR?

@JiajunBernoulli
Copy link
Copy Markdown
Author

Here is new test
QQ_1775782221276

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: 89a83efa37

ℹ️ 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".

Comment thread ui/src/ui/views/config.ts
Comment on lines +794 to +795
const rawDiff =
formMode === "raw" && cvs.rawDiffRevealed ? computeRawDiff(props.originalRaw, props.raw) : [];
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 Avoid parsing raw JSON when no pending raw changes exist

rawDiff is computed whenever formMode === "raw" && cvs.rawDiffRevealed, even if props.raw === props.originalRaw and the raw diff panel is not rendered. Because rawDiffRevealed is sticky after users open the panel once, subsequent renders (including idle host updates after save/apply) still parse both full config strings and run computeDiff, which adds avoidable O(n) work on large configs and can hurt UI responsiveness. Guarding this computation with hasRawChanges (or resetting rawDiffRevealed when changes clear) avoids the unnecessary hot-path parse.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

@BunsDev BunsDev left a comment

Choose a reason for hiding this comment

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

Thanks for the patience here. The feature target is useful: raw config mode should have an actionable pending-changes view like form mode. This implementation needs another pass before it can land.

Blocking changes:

  • Please remove the props.onRawChange(props.raw) render-trigger hack from the <details @toggle> handler. Calling a content-change callback with the unchanged raw value is semantically wrong and can break if the host deduplicates identical values. Use actual component state/update plumbing, compute the diff from existing render state, or add a dedicated non-content update callback.

  • Guard raw diff computation with hasRawChanges and the panel state, or reset the panel state when changes clear. Right now rawDiffRevealed is sticky, so later raw-mode renders can keep parsing both full config strings even when the panel is not rendered or there are no pending raw changes.

  • Please rename rawDiffRevealed to something like rawDiffOpen / rawDiffExpanded. rawRevealed already means sensitive-value reveal in this file, so the new name is easy to confuse with redaction behavior.

Also, the branch is currently dirty and check-additional is failing. Please rebase on current main, resolve the check failure, and keep this PR scoped to the raw pending-changes UI. The existing json5 dependency is acceptable if the final diff path still needs it.

@vincentkoc
Copy link
Copy Markdown
Member

This assigned pull request has been marked as stale after being open for 27 days.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the triage: blank-template Candidate: PR template appears mostly untouched. label Apr 26, 2026
@BunsDev
Copy link
Copy Markdown
Member

BunsDev commented Apr 27, 2026

Thanks again for the contribution and patience here. I’m closing this PR as superseded by the maintainer-owned replacement #72583.

Why: this PR was stale, still conflicting against current main, and still had unresolved requested changes after the latest maintainer review. Since there had not been an author follow-up after that review, I created #72583 to resolve the raw config pending-changes UI directly while preserving the useful feature target.

For transparency, #72583 credits the original contributor in the changelog, references the original feature request #39831, and notes that it supersedes both this PR and the older duplicate #46654.

@BunsDev BunsDev closed this Apr 27, 2026
BunsDev added a commit that referenced this pull request Apr 27, 2026
Adds a raw config pending-changes diff panel in Control UI raw mode, with JSON5 parsing, sensitive-value redaction until explicit reveal, bounded diff work, and tests for redaction/reveal and stale reveal-state reset.

Also aligns provider manifest contract coverage for google-vertex and Qwen aliases to unblock the rebased CI matrix.

Supersedes stale PRs #48621 and #46654. PR #48621 had gone stale without maintainer follow-up, so this maintainer-authored PR carries the implementation forward transparently while preserving changelog credit for the original contributor and @BunsDev.
@BunsDev
Copy link
Copy Markdown
Member

BunsDev commented Apr 27, 2026

Landed in the maintainer-owned replacement #72583 via squash commit 14a27e1.

Keeping this note here for transparency: this stale PR remains closed as superseded, and #72583 preserved changelog credit for the original contribution alongside @BunsDev.

@JiajunBernoulli
Copy link
Copy Markdown
Author

@BunsDev
I was under the impression that this pull request had been abandoned.

It was successfully merged today; however, I was unable to complete the necessary contributions within the timeframe.

Given my involvement in key aspects of the implementation, I would be honored to be acknowledged as a co-author. Thank you for your consideration.

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

Labels

app: web-ui App: web-ui size: M stale Marked as stale due to inactivity triage: blank-template Candidate: PR template appears mostly untouched.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants