fix(plugins): retain Host progress fallback after master merge

This commit is contained in:
RockChinQ
2026-09-21 17:04:57 +00:00
parent 5d9684731e
commit a8d291e581
4 changed files with 71 additions and 2 deletions
@@ -159,6 +159,7 @@ export function asyncTaskToPluginInstallTask(
stage,
downloadCurrent: num(md.download_current),
downloadTotal: num(md.download_total),
reportedProgress: num(md.progress_percent),
stageElapsedSeconds: 0,
}),
);
@@ -326,6 +327,7 @@ export function PluginInstallTaskProvider({
stage,
downloadCurrent,
downloadTotal,
reportedProgress: num(md.progress_percent),
stageElapsedSeconds: (Date.now() - stageStartedAt) / 1000,
});
const progress = Math.min(
@@ -106,6 +106,8 @@ export interface StageProgressInput {
stage: InstallStage;
downloadCurrent?: number;
downloadTotal?: number;
/** Host coarse stage progress, used only when measured bytes are absent. */
reportedProgress?: number;
/** Seconds spent in the current stage, used to bound fallback drift. */
stageElapsedSeconds: number;
}
@@ -136,6 +138,13 @@ export function computeStageProgress(input: StageProgressInput): number {
return clampToRange(Math.round(start + (end - start) * ratio), start, end);
}
if (
input.reportedProgress != null &&
Number.isFinite(input.reportedProgress)
) {
return clampToRange(input.reportedProgress, start, end);
}
// Nothing measurable to show yet: drift slowly, but never past this stage's
// own ceiling (hence `end - start - 1`, leaving the final point to the real
// stage transition).
+57
View File
@@ -116,6 +116,63 @@ test('fallback drift never spills into the next stage range', () => {
}
});
test('preserves Host stage progress when byte counts are unavailable', () => {
assert.equal(
computeStageProgress({
stage: InstallStage.DOWNLOADING,
reportedProgress: 23,
stageElapsedSeconds: 0,
}),
23,
);
assert.equal(
computeStageProgress({
stage: InstallStage.INSTALLING_DEPS,
reportedProgress: 64,
stageElapsedSeconds: 0,
}),
64,
);
assert.equal(
mapActionToStage('checking plugin update'),
InstallStage.CHECKING,
);
assert.equal(
mapActionToStage('validating plugin package'),
InstallStage.VALIDATING,
);
assert.equal(
mapActionToStage('applying plugin update'),
InstallStage.INSTALLING_DEPS,
);
assert.equal(
mapActionToStage('refreshing plugin components'),
InstallStage.LAUNCHING,
);
assert.equal(mapActionToStage('plugin updated'), InstallStage.DONE);
});
test('measured bytes override Host coarse progress and fallback stays bounded', () => {
assert.equal(
computeStageProgress({
stage: InstallStage.DOWNLOADING,
downloadCurrent: 90,
downloadTotal: 100,
reportedProgress: 15,
stageElapsedSeconds: 40,
}),
41,
);
for (const reportedProgress of [-5, 100]) {
const progress = computeStageProgress({
stage: InstallStage.DOWNLOADING,
reportedProgress,
stageElapsedSeconds: 0,
});
assert.ok(progress >= 5 && progress <= 45);
}
});
test('a missing or zero download total falls back to bounded drift', () => {
const [start, end] = STAGE_PROGRESS_RANGE[InstallStage.DOWNLOADING];
@@ -71,10 +71,11 @@ test('offers KnowledgeEngine marketplace plugins inside the selector', () => {
test('tracks plugin upgrades as recoverable multistep async tasks', () => {
assert.match(taskContextSource, /name\.startsWith\('plugin-upgrade-'\)/);
assert.match(taskContextSource, /operation: PluginTaskOperation/);
assert.match(taskContextSource, /progress_percent/);
assert.match(taskContextSource, /computeStageProgress/);
assert.match(taskContextSource, /INSTALL_PROGRESS_CAP/);
assert.match(progressDialogSource, /InstallStage\.CHECKING/);
assert.match(progressDialogSource, /InstallStage\.VALIDATING/);
assert.match(progressDialogSource, /InstallStage\.ACTIVATING/);
assert.match(progressDialogSource, /InstallStage\.LAUNCHING/);
assert.match(progressDialogSource, /plugins\.installProgress\.updateTitle/);
for (const source of [installedPluginsSource, homeSidebarSource]) {
assert.match(