fix(doctor): migrate legacy bundled plugin load paths#55054
Conversation
|
@codex review |
Greptile SummaryThis PR adds targeted detection and auto-repair of legacy bundled plugin load paths that still point at Confidence Score: 5/5Safe to merge; targeted fix with solid test coverage and no changes to startup-time behaviour. Core detection and repair logic is correct: buildLegacyBundledPath correctly inverts the dist/extensions/ suffix, the seen-set deduplication handles the edge case where both the legacy and new paths are already present, and the repair is correctly ordered before maybeRepairStalePluginConfig. The only identified gap (non-string path entries silently dropped during repair) is a defensive-coding concern rather than a correctness bug under realistic configs. Test coverage is thorough. No files require special attention; the P2 comment on bundled-plugin-load-paths.ts is optional hardening.
|
| Filename | Overview |
|---|---|
| src/commands/doctor/shared/bundled-plugin-load-paths.ts | New module implementing legacy bundled plugin path detection and repair. Logic is correct and well-structured; one minor issue: non-string path entries are silently dropped when the repair rewrites the paths array. |
| src/commands/doctor/shared/bundled-plugin-load-paths.test.ts | Good test coverage for detection, repair, warning formatting, and the no-op case. All three exported functions are exercised. |
| src/commands/doctor/shared/preview-warnings.ts | Correctly integrates the new bundled plugin load path scan into the preview warnings pipeline, consistent with existing warning patterns. |
| src/commands/doctor/shared/preview-warnings.test.ts | New integration test correctly mocks both manifest registry and bundled sources to verify the end-to-end warning surfaced to the user. |
| src/commands/doctor/repair-sequencing.ts | New repair is correctly inserted before maybeRepairStalePluginConfig, which is the right order since stale-plugin cleanup should operate on already-migrated paths. |
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/commands/doctor/shared/bundled-plugin-load-paths.ts
Line: 120-132
Comment:
**Non-string path entries silently dropped during repair**
When a legacy hit is detected, `maybeRepairBundledPluginLoadPaths` rebuilds the `paths` array but silently omits any non-string entries via the `continue` branch. The scan phase correctly skips non-strings without affecting them, but the repair phase drops them entirely — so a config with `paths: ["/legacy/feishu", 42, "/other/path"]` would be written back as `["/new/feishu", "/other/path"]` with no corresponding entry in `changes`.
In practice `paths` entries should always be strings, so this is unlikely to matter today, but making the repair preserve unrecognised entries would make the behaviour consistent with the scan:
```suggestion
for (const entry of paths) {
if (typeof entry !== "string") {
// Preserve non-string entries as-is; only rewrite known legacy paths.
rewritten.push(entry as string);
continue;
}
const resolved = path.normalize(resolveUserPath(entry, env));
const replacement = replacements.get(resolved)?.toPath ?? entry;
const replacementResolved = path.normalize(resolveUserPath(replacement, env));
if (seen.has(replacementResolved)) {
continue;
}
seen.add(replacementResolved);
rewritten.push(replacement);
}
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(doctor): migrate legacy bundled plug..." | Re-trigger Greptile
|
Codex Review: Didn't find any major issues. What shall we delve into next? ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
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". |
|
Follow-up:
Local verification still passes:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0f6f55efec
ℹ️ 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".
| const suffix = path.join("dist", "extensions", pluginId); | ||
| if (!normalized.endsWith(suffix)) { |
There was a problem hiding this comment.
Derive legacy bundled path from directory name
buildLegacyBundledPath assumes every bundled path ends in dist/extensions/<pluginId>, but this is not always true for bundled plugins (for example, extensions/kimi-coding/openclaw.plugin.json declares id: "kimi"). In that case the suffix check fails, the plugin is skipped from legacyPathMap, and openclaw doctor --fix will not migrate stale .../extensions/kimi-coding entries, so affected upgrades can still hit plugin path not found. Please derive the legacy path from the bundled directory segment in source.localPath (or equivalent manifest/package metadata) rather than pluginId alone.
Useful? React with 👍 / 👎.
|
@obviyus when you have a moment, could you take a quick look? This branch is now fully green again after the follow-up. The latest update only preserves mixed Thanks! |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f37cccb269
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const normalized = path.normalize(resolveUserPath(rawPath, env)); | ||
| const match = legacyPathMap.get(normalized); |
There was a problem hiding this comment.
Canonicalize load-path slashes before migration lookup
scanBundledPluginLoadPathMigrations compares plugins.load.paths entries with a plain path.normalize(resolveUserPath(...)) key lookup, but path.normalize preserves trailing separators (for example .../extensions/feishu/), while buildLegacyBundledPath stores keys without that trailing slash. In configs that contain a legacy bundled path with a trailing / or \, the lookup misses and openclaw doctor --fix will not rewrite the stale path, so the original plugin path not found failure can persist after repair. This only triggers for those slash-suffixed path variants, but it breaks the migration in that common manual-edit case.
Useful? React with 👍 / 👎.
f37cccb to
ba35989
Compare
…nowSky1) * fix(doctor): migrate legacy bundled plugin load paths * fix(doctor): preserve unknown plugin path entries * fix: derive bundled plugin legacy paths from actual directory names * fix: land bundled plugin doctor migration (openclaw#55054) (thanks @SnowSky1) --------- Co-authored-by: Ayaan Zaidi <hi@obviy.us>
…nowSky1) * fix(doctor): migrate legacy bundled plugin load paths * fix(doctor): preserve unknown plugin path entries * fix: derive bundled plugin legacy paths from actual directory names * fix: land bundled plugin doctor migration (openclaw#55054) (thanks @SnowSky1) --------- Co-authored-by: Ayaan Zaidi <hi@obviy.us>
…nowSky1) * fix(doctor): migrate legacy bundled plugin load paths * fix(doctor): preserve unknown plugin path entries * fix: derive bundled plugin legacy paths from actual directory names * fix: land bundled plugin doctor migration (openclaw#55054) (thanks @SnowSky1) --------- Co-authored-by: Ayaan Zaidi <hi@obviy.us>
…nowSky1) * fix(doctor): migrate legacy bundled plugin load paths * fix(doctor): preserve unknown plugin path entries * fix: derive bundled plugin legacy paths from actual directory names * fix: land bundled plugin doctor migration (openclaw#55054) (thanks @SnowSky1) --------- Co-authored-by: Ayaan Zaidi <hi@obviy.us>
…nowSky1) * fix(doctor): migrate legacy bundled plugin load paths * fix(doctor): preserve unknown plugin path entries * fix: derive bundled plugin legacy paths from actual directory names * fix: land bundled plugin doctor migration (openclaw#55054) (thanks @SnowSky1) --------- Co-authored-by: Ayaan Zaidi <hi@obviy.us>
…nowSky1) * fix(doctor): migrate legacy bundled plugin load paths * fix(doctor): preserve unknown plugin path entries * fix: derive bundled plugin legacy paths from actual directory names * fix: land bundled plugin doctor migration (openclaw#55054) (thanks @SnowSky1) --------- Co-authored-by: Ayaan Zaidi <hi@obviy.us>
…nowSky1) * fix(doctor): migrate legacy bundled plugin load paths * fix(doctor): preserve unknown plugin path entries * fix: derive bundled plugin legacy paths from actual directory names * fix: land bundled plugin doctor migration (openclaw#55054) (thanks @SnowSky1) --------- Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Summary
extensions/<id>after packaged builds moved todist/extensions/<id>openclaw doctor --fixto rewrite those stale bundled paths automaticallyWhy
Users upgrading from older installs can be left with bundled plugin load paths like
.../openclaw/extensions/feishu, which no longer exist in packaged builds. That currently blocks startup withplugin path not found, even though the matching bundled plugin now lives underdist/extensions/<id>.Scope
Verification
pnpm test -- src/commands/doctor/shared/bundled-plugin-load-paths.test.ts src/commands/doctor/shared/preview-warnings.test.tspnpm exec oxfmt --check src/commands/doctor/shared/bundled-plugin-load-paths.ts src/commands/doctor/shared/bundled-plugin-load-paths.test.ts src/commands/doctor/shared/preview-warnings.ts src/commands/doctor/shared/preview-warnings.test.ts src/commands/doctor/repair-sequencing.tsCloses #54963