推进 INI 面板 shell handoff summary browser API

This commit is contained in:
2026-06-15 08:12:33 +08:00
parent b31b9a2f8a
commit 01817f6493
9 changed files with 133 additions and 9 deletions

View File

@@ -132,7 +132,9 @@ control-page API methods, readiness gate, and readonly status handoff fields
before opening a browser frame.
Use `createIniPanelShellSessionHandoffSummary()` when the outer shell needs one
read-only display summary of readiness, target page, persistence capabilities,
readonly status fields, handoff methods, and blocking reasons.
readonly status fields, handoff methods, and blocking reasons. Browser shells
can read the same summary through
`linuxCncIniPanelLaunchApi.getShellSessionHandoffSummary()`.
The browser workflow smoke
`tests/browser/ini_panel_shell_integration_workflow_smoke.html` verifies the
same external shell handoff: read integration manifest, pass readiness gate,

View File

@@ -97,6 +97,7 @@
getShellIntegrationSchema: () => shellViewModel.shellIntegrationSchema,
getShellIntegrationManifest: () => shellViewModel.shellIntegrationManifest,
getShellIntegrationReadiness: () => shellViewModel.shellIntegrationReadiness,
getShellSessionHandoffSummary: () => shellViewModel.shellSessionHandoffSummary,
getLauncherLinks: () => shellViewModel.launcherLinks,
getControlPageApiMethods: () => shellViewModel.controlPage.browserApiMethods,
};

View File

@@ -126,6 +126,7 @@ export function createIniPanelLaunchApiManifest(entries = getVisibleIniPanelEntr
"getShellIntegrationSchema",
"getShellIntegrationManifest",
"getShellIntegrationReadiness",
"getShellSessionHandoffSummary",
"getLauncherLinks",
"getControlPageApiMethods",
],

View File

@@ -73,6 +73,7 @@
!launchApi?.getShellIntegrationSchema ||
!launchApi?.getShellIntegrationManifest ||
!launchApi?.getShellIntegrationReadiness ||
!launchApi?.getShellSessionHandoffSummary ||
!launchApi?.getLauncherLinks ||
!launchApi?.getControlPageApiMethods
) {
@@ -112,12 +113,13 @@
);
assertEqual(
launchApiManifest.methods.join(","),
"isSupportedLaunchApiManifest,getLaunchApiSchema,getLaunchApiManifest,getShellIntegrationSchema,getShellIntegrationManifest,getShellIntegrationReadiness,getLauncherLinks,getControlPageApiMethods",
"isSupportedLaunchApiManifest,getLaunchApiSchema,getLaunchApiManifest,getShellIntegrationSchema,getShellIntegrationManifest,getShellIntegrationReadiness,getShellSessionHandoffSummary,getLauncherLinks,getControlPageApiMethods",
"launch API manifest methods",
);
const shellIntegrationSchema = launchApi.getShellIntegrationSchema();
const shellIntegrationManifest = launchApi.getShellIntegrationManifest();
const shellIntegrationReadiness = launchApi.getShellIntegrationReadiness();
const shellSessionHandoffSummary = launchApi.getShellSessionHandoffSummary();
assertEqual(
shellIntegrationSchema.manifestVersion,
1,
@@ -158,6 +160,26 @@
"",
"shell integration readiness missing checks",
);
assertEqual(
shellSessionHandoffSummary.ready,
true,
"shell session handoff summary readiness",
);
assertEqual(
shellSessionHandoffSummary.targetPage.href,
"./control-page.html",
"shell session handoff summary target",
);
assertEqual(
shellSessionHandoffSummary.readonlyStatusFields.includes("session"),
true,
"shell session handoff summary readonly fields",
);
assertEqual(
shellSessionHandoffSummary.persistenceCapabilities.length,
3,
"shell session handoff summary persistence capabilities",
);
assertEqual(
JSON.stringify(shellIntegrationManifest),
JSON.stringify(createIniPanelShellIntegrationManifest()),

View File

@@ -63,16 +63,24 @@ TOOL_TABLE = browser-shell-tool.tbl
const launchApi = launchDoc.defaultView.linuxCncIniPanelLaunchApi;
if (
!launchApi?.getShellIntegrationManifest ||
!launchApi?.getShellIntegrationReadiness
!launchApi?.getShellIntegrationReadiness ||
!launchApi?.getShellSessionHandoffSummary
) {
throw new Error("launch API namespace did not expose shell integration helpers");
}
const integrationManifest = launchApi.getShellIntegrationManifest();
const readiness = launchApi.getShellIntegrationReadiness();
const handoffSummary = launchApi.getShellSessionHandoffSummary();
assertEqual(readiness.phase, "ready", "shell integration readiness phase");
assertEqual(readiness.ready, true, "shell integration readiness");
assertEqual(readiness.missing.join(","), "", "shell integration readiness missing checks");
assertEqual(handoffSummary.ready, true, "shell handoff summary readiness");
assertEqual(handoffSummary.blockingReasons.join(","), "", "shell handoff summary blocking reasons");
assertEqual(handoffSummary.handoffMethods.loadSessionState, "loadControlPageSessionState", "shell handoff load method");
assertEqual(handoffSummary.handoffMethods.readStatus, "readControlPageStatus", "shell handoff status method");
assertEqual(handoffSummary.readonlyStatusFields.includes("session"), true, "shell handoff readonly session field");
assertEqual(handoffSummary.persistenceCapabilities.length, 3, "shell handoff persistence capabilities");
assertEqual(readiness.apiNames.launch, "ini-panel-launch", "shell integration launch API name");
assertEqual(
readiness.apiNames.controlPage,
@@ -94,6 +102,7 @@ TOOL_TABLE = browser-shell-tool.tbl
(page) => page.entryId === "control-view",
);
assertEqual(controlTarget.href, "./control-page.html", "shell integration control target");
assertEqual(handoffSummary.targetPage.href, controlTarget.href, "shell handoff summary target");
const controlDoc = await loadFrame(`../../runtime/ui/ini-panel/${controlTarget.href.slice(2)}`);
const controlPageApi = controlDoc.defaultView.linuxCncIniPanelControlPageApi;
@@ -120,12 +129,12 @@ TOOL_TABLE = browser-shell-tool.tbl
"embedded INI panel API",
);
assertEqual(
controlPageApi.loadControlPageSessionState().phase,
controlPageApi[handoffSummary.handoffMethods.loadSessionState]().phase,
"ready",
"shell integration control-page session readiness",
);
assertEqual(
controlPageApi.readControlPageStatus().status.lastAction,
controlPageApi[handoffSummary.handoffMethods.readStatus]().status.lastAction,
null,
"shell integration initial readonly status",
);
@@ -147,7 +156,7 @@ TOOL_TABLE = browser-shell-tool.tbl
"shell integration load session",
);
const readonlyStatus = controlPageApi.readControlPageStatus();
const readonlyStatus = controlPageApi[handoffSummary.handoffMethods.readStatus]();
assertEqual(
readonlyStatus.workflowStatus.lastAction,
"load-session",
@@ -163,6 +172,11 @@ TOOL_TABLE = browser-shell-tool.tbl
"browser-shell-tool.tbl",
"shell integration readonly state bundle tool table",
);
assertEqual(
handoffSummary.readonlyStatusFields.every((fieldName) => Object.hasOwn(readonlyStatus, fieldName)),
true,
"shell handoff readonly status fields",
);
assertEqual(
controlDoc.getElementById("control-page-status").textContent,
"load-session | not-run | -",

View File

@@ -221,6 +221,7 @@ assert.match(launchText, /\bgetLaunchApiManifest\b/);
assert.match(launchText, /\bgetShellIntegrationSchema\b/);
assert.match(launchText, /\bgetShellIntegrationManifest\b/);
assert.match(launchText, /\bgetShellIntegrationReadiness\b/);
assert.match(launchText, /\bgetShellSessionHandoffSummary\b/);
assert.match(launchText, /\bgetControlPageApiMethods\b/);
assert.match(controlPageText, /\bgetControlPageContract\b/);
assert.match(controlPageText, /\breadControlPageStatus\b/);
@@ -249,10 +250,13 @@ assert.match(docText, /\blinuxCncIniPanelLaunchApi\.getLaunchApiManifest\b/);
assert.match(docText, /\blinuxCncIniPanelLaunchApi\.getShellIntegrationSchema\b/);
assert.match(docText, /\blinuxCncIniPanelLaunchApi\.getShellIntegrationManifest\b/);
assert.match(docText, /\blinuxCncIniPanelLaunchApi\.getShellIntegrationReadiness\b/);
assert.match(docText, /\blinuxCncIniPanelLaunchApi\.getShellSessionHandoffSummary\b/);
assert.match(docText, /\blinuxCncIniPanelLaunchApi\.getControlPageApiMethods\b/);
assert.match(docText, /\bini_panel_shell_integration_workflow_smoke\.html\b/);
assert.match(browserIniPanelText, /\bini_panel_shell_integration_workflow_smoke\.html\b/);
assert.match(shellIntegrationWorkflowSmokeText, /\bgetShellIntegrationReadiness\b/);
assert.match(shellIntegrationWorkflowSmokeText, /\bgetShellSessionHandoffSummary\b/);
assert.match(shellIntegrationWorkflowSmokeText, /\bhandoffSummary\.handoffMethods\.readStatus\b/);
assert.match(shellIntegrationWorkflowSmokeText, /\breadControlPageStatus\b/);
assert.match(shellIntegrationWorkflowSmokeText, /\bbrowser_ini_shell_integration_workflow_smoke=ok\b/);
assert.match(docText, /\bOPFS\/session persistence capabilities\b/);

View File

@@ -46,6 +46,7 @@ assert.deepEqual(manifest, {
"getShellIntegrationSchema",
"getShellIntegrationManifest",
"getShellIntegrationReadiness",
"getShellSessionHandoffSummary",
"getLauncherLinks",
"getControlPageApiMethods",
],
@@ -146,6 +147,7 @@ assert.match(launchText, /\bgetLaunchApiManifest\b/);
assert.match(launchText, /\bgetShellIntegrationSchema\b/);
assert.match(launchText, /\bgetShellIntegrationManifest\b/);
assert.match(launchText, /\bgetShellIntegrationReadiness\b/);
assert.match(launchText, /\bgetShellSessionHandoffSummary\b/);
assert.match(launchText, /\blinuxCncIniPanelLaunchApi\b/);
console.log("ini_panel_launch_api_manifest_node_smoke=ok");

View File

@@ -85,7 +85,7 @@ assert.deepEqual(readiness, {
counts: {
pages: 2,
launcherLinks: 2,
launchMethods: 8,
launchMethods: 9,
controlPageMethods: 11,
persistenceCapabilities: 3,
},
@@ -145,7 +145,7 @@ assert.deepEqual(handoffSummary, {
counts: {
pages: 2,
launcherLinks: 2,
launchMethods: 8,
launchMethods: 9,
controlPageMethods: 11,
persistenceCapabilities: 3,
},
@@ -210,7 +210,7 @@ assert.deepEqual(createIniPanelShellIntegrationReadiness(blockedManifest), {
counts: {
pages: 2,
launcherLinks: 2,
launchMethods: 8,
launchMethods: 9,
controlPageMethods: 11,
persistenceCapabilities: 3,
},