2242 lines
80 KiB
JavaScript
2242 lines
80 KiB
JavaScript
import {
|
|
INI_PANEL_ENTRIES,
|
|
getIniPanelEntryByHref,
|
|
getIniPanelEntryManifest,
|
|
} from "./entry-manifest.js";
|
|
import {
|
|
createMachineSessionControlPageController,
|
|
} from "./control-page-controller.js";
|
|
import {
|
|
renderMachineSessionControlView,
|
|
} from "./control-view-renderer.js";
|
|
import {
|
|
controlPageStatusText,
|
|
createControlPageRefreshState,
|
|
refreshMachineSessionControlPage,
|
|
} from "./control-page-refresh-workflow.js";
|
|
import {
|
|
createControlPageSessionLoadState,
|
|
loadMachineSessionForControlPageWorkflow,
|
|
} from "./control-page-session-workflow.js";
|
|
import {
|
|
createMachineSessionReadonlyStatus,
|
|
createMachineSessionReadonlyStatusApiManifest,
|
|
readMachineSessionReadonlyStatus,
|
|
} from "./readonly-status-api.js";
|
|
export {
|
|
controlPageStatusText,
|
|
createControlPageRefreshState,
|
|
refreshMachineSessionControlPage,
|
|
} from "./control-page-refresh-workflow.js";
|
|
export {
|
|
createControlPageSessionLoadState,
|
|
loadMachineSessionForControlPageWorkflow,
|
|
} from "./control-page-session-workflow.js";
|
|
export {
|
|
createMachineSessionReadonlyStatus,
|
|
createMachineSessionReadonlyStatusApiManifest,
|
|
readMachineSessionReadonlyStatus,
|
|
} from "./readonly-status-api.js";
|
|
export {
|
|
INI_PANEL_ENTRIES,
|
|
getIniPanelEntryByHref,
|
|
getIniPanelEntryManifest,
|
|
} from "./entry-manifest.js";
|
|
export {
|
|
createMachineSessionControlPageController,
|
|
} from "./control-page-controller.js";
|
|
export {
|
|
renderMachineSessionControlView,
|
|
} from "./control-view-renderer.js";
|
|
|
|
export function getVisibleIniPanelEntries() {
|
|
return getIniPanelEntryManifest();
|
|
}
|
|
|
|
export function createIniPanelLauncherLinkViewModel(entries = getVisibleIniPanelEntries()) {
|
|
return entries.map(({ id, href, title }) => ({
|
|
entryId: id,
|
|
href,
|
|
label: title,
|
|
}));
|
|
}
|
|
|
|
export function createIniPanelLaunchApiSchema() {
|
|
return {
|
|
apiName: "ini-panel-launch",
|
|
manifestVersion: 1,
|
|
fields: [
|
|
"apiName",
|
|
"manifestVersion",
|
|
"methods",
|
|
"visibleEntries",
|
|
"targetPages",
|
|
"controlPageApiMethods",
|
|
"persistenceCapabilities",
|
|
],
|
|
};
|
|
}
|
|
|
|
export function isSupportedIniPanelLaunchApiManifest(manifest, schema = createIniPanelLaunchApiSchema()) {
|
|
if (!manifest || typeof manifest !== "object") {
|
|
return false;
|
|
}
|
|
if (manifest.apiName !== schema.apiName || manifest.manifestVersion !== schema.manifestVersion) {
|
|
return false;
|
|
}
|
|
return schema.fields.every((fieldName) => Object.hasOwn(manifest, fieldName));
|
|
}
|
|
|
|
export function createControlPageBrowserApiSchema() {
|
|
return {
|
|
apiName: "ini-panel-control-page",
|
|
manifestVersion: 1,
|
|
fields: [
|
|
"apiName",
|
|
"manifestVersion",
|
|
"methods",
|
|
"contract",
|
|
"readonlyStatusApiManifest",
|
|
],
|
|
};
|
|
}
|
|
|
|
export function isSupportedIniPanelControlPageApiManifest(
|
|
manifest,
|
|
schema = createControlPageBrowserApiSchema(),
|
|
) {
|
|
if (!manifest || typeof manifest !== "object") {
|
|
return false;
|
|
}
|
|
if (manifest.apiName !== schema.apiName || manifest.manifestVersion !== schema.manifestVersion) {
|
|
return false;
|
|
}
|
|
return schema.fields.every((fieldName) => Object.hasOwn(manifest, fieldName));
|
|
}
|
|
|
|
export function createIniPanelLaunchApiManifest(entries = getVisibleIniPanelEntries()) {
|
|
const schema = createIniPanelLaunchApiSchema();
|
|
return {
|
|
apiName: schema.apiName,
|
|
manifestVersion: schema.manifestVersion,
|
|
methods: [
|
|
"isSupportedLaunchApiManifest",
|
|
"getLaunchApiSchema",
|
|
"getLaunchApiManifest",
|
|
"getShellIntegrationSchema",
|
|
"getShellIntegrationManifest",
|
|
"getShellIntegrationReadiness",
|
|
"getShellSessionHandoffSummarySchema",
|
|
"getShellSessionHandoffSummary",
|
|
"isSupportedShellSessionHandoffSummary",
|
|
"getShellSessionHandoffCompatibilityReport",
|
|
"getShellSessionHandoffDisplayViewModel",
|
|
"getShellSessionHandoffSnapshot",
|
|
"getShellSessionHandoffRenderState",
|
|
"getShellSessionHandoffActionPlan",
|
|
"getShellSessionHandoffChecklist",
|
|
"getShellSessionHandoffPackageSchema",
|
|
"getShellSessionHandoffPackage",
|
|
"getShellSessionHandoffPackageReport",
|
|
"getShellSessionHandoffPackageDisplayViewModel",
|
|
"getShellSessionHandoffPackageRenderState",
|
|
"getShellSessionHandoffPackageMountState",
|
|
"getShellSessionHandoffPackageMountDisplayViewModel",
|
|
"getShellSessionHandoffPackageMountRenderState",
|
|
"getShellSessionHandoffMountDomContract",
|
|
"getShellSessionHandoffMountDomReadiness",
|
|
"renderShellSessionHandoffMountState",
|
|
"mountShellSessionHandoff",
|
|
"mountShellSessionHandoffFromControlPage",
|
|
"readShellSessionHandoffStatusFromControlPage",
|
|
"getShellSessionHandoffWorkflowSummary",
|
|
"getShellSessionHandoffWorkflowDisplayViewModel",
|
|
"getShellSessionHandoffWorkflowRenderState",
|
|
"getShellSessionHandoffWorkflowDomContract",
|
|
"getShellSessionHandoffWorkflowDomReadiness",
|
|
"renderShellSessionHandoffWorkflowState",
|
|
"mountShellSessionHandoffWorkflow",
|
|
"getWorkflowOverviewContract",
|
|
"getWorkflowOverviewReadiness",
|
|
"mountWorkflowOverviewEmbedding",
|
|
"getWorkflowOverviewEmbeddingReport",
|
|
"getWorkflowOverviewEmbeddingDisplayViewModel",
|
|
"getWorkflowOverviewEmbeddingRenderState",
|
|
"getWorkflowOverviewEmbeddingDomContract",
|
|
"getWorkflowOverviewEmbeddingDomReadiness",
|
|
"renderWorkflowOverviewEmbeddingState",
|
|
"isSupportedShellSessionHandoffPackage",
|
|
"getLauncherLinks",
|
|
"getControlPageApiMethods",
|
|
],
|
|
visibleEntries: entries.map(({ id, href, title }) => ({
|
|
id,
|
|
href,
|
|
title,
|
|
})),
|
|
targetPages: entries.map(({ id, href }) => ({
|
|
entryId: id,
|
|
href,
|
|
})),
|
|
controlPageApiMethods: createControlPageBrowserApiMethods(),
|
|
persistenceCapabilities: [
|
|
{
|
|
id: "machine-files",
|
|
label: "Machine text files",
|
|
scope: "opfs",
|
|
},
|
|
{
|
|
id: "session-snapshot",
|
|
label: "Machine session snapshot",
|
|
scope: "opfs",
|
|
},
|
|
{
|
|
id: "readonly-status",
|
|
label: "Read-only machine session status",
|
|
scope: "control-page",
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellControlPageContract() {
|
|
const readonlyStatusApiManifest = createMachineSessionReadonlyStatusApiManifest();
|
|
return {
|
|
methodNames: [
|
|
"createController",
|
|
"loadSessionState",
|
|
"readStatus",
|
|
"refresh",
|
|
"renderView",
|
|
],
|
|
readonlyStatusApiManifest,
|
|
readonlyStatusApiMethodNames: Object.keys(readonlyStatusApiManifest.methods),
|
|
readonlyStatusApiStatusFields: readonlyStatusApiManifest.statusFields,
|
|
relatedControlPageMethods: readonlyStatusApiManifest.relatedControlPageMethods,
|
|
};
|
|
}
|
|
|
|
export function createControlPageBrowserApiMethods() {
|
|
return [
|
|
"isSupportedControlPageApiManifest",
|
|
"getControlPageApiSchema",
|
|
"getControlPageApiManifest",
|
|
"getControlPageApiMethods",
|
|
"getControlPageContract",
|
|
"getControlView",
|
|
"getPanelApi",
|
|
"loadControlPageSessionState",
|
|
"readControlPageStatus",
|
|
"refreshControlPage",
|
|
"renderControlPage",
|
|
];
|
|
}
|
|
|
|
export function createControlPageBrowserApiManifest() {
|
|
const schema = createControlPageBrowserApiSchema();
|
|
const contract = createIniPanelShellControlPageContract();
|
|
return {
|
|
apiName: schema.apiName,
|
|
manifestVersion: schema.manifestVersion,
|
|
methods: createControlPageBrowserApiMethods(),
|
|
contract,
|
|
readonlyStatusApiManifest: contract.readonlyStatusApiManifest,
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellIntegrationSchema() {
|
|
return {
|
|
apiName: "ini-panel-shell-integration",
|
|
manifestVersion: 1,
|
|
fields: [
|
|
"apiName",
|
|
"manifestVersion",
|
|
"pages",
|
|
"launcherLinks",
|
|
"launchApiSchema",
|
|
"launchApiManifest",
|
|
"controlPageApiSchema",
|
|
"controlPageApiManifest",
|
|
"compatibility",
|
|
"persistenceCapabilities",
|
|
],
|
|
};
|
|
}
|
|
|
|
export function isSupportedIniPanelShellIntegrationManifest(
|
|
manifest,
|
|
schema = createIniPanelShellIntegrationSchema(),
|
|
) {
|
|
if (!manifest || typeof manifest !== "object") {
|
|
return false;
|
|
}
|
|
if (manifest.apiName !== schema.apiName || manifest.manifestVersion !== schema.manifestVersion) {
|
|
return false;
|
|
}
|
|
return schema.fields.every((fieldName) => Object.hasOwn(manifest, fieldName));
|
|
}
|
|
|
|
export function createIniPanelShellIntegrationManifest(entries = getVisibleIniPanelEntries()) {
|
|
const schema = createIniPanelShellIntegrationSchema();
|
|
const launchApiSchema = createIniPanelLaunchApiSchema();
|
|
const launchApiManifest = createIniPanelLaunchApiManifest(entries);
|
|
const controlPageApiSchema = createControlPageBrowserApiSchema();
|
|
const controlPageApiManifest = createControlPageBrowserApiManifest();
|
|
return {
|
|
apiName: schema.apiName,
|
|
manifestVersion: schema.manifestVersion,
|
|
pages: entries.map(({ id, href, title }) => ({
|
|
id,
|
|
href,
|
|
title,
|
|
})),
|
|
launcherLinks: createIniPanelLauncherLinkViewModel(entries),
|
|
launchApiSchema,
|
|
launchApiManifest,
|
|
controlPageApiSchema,
|
|
controlPageApiManifest,
|
|
compatibility: {
|
|
launchApiManifest: isSupportedIniPanelLaunchApiManifest(launchApiManifest, launchApiSchema),
|
|
controlPageApiManifest: isSupportedIniPanelControlPageApiManifest(
|
|
controlPageApiManifest,
|
|
controlPageApiSchema,
|
|
),
|
|
},
|
|
persistenceCapabilities: launchApiManifest.persistenceCapabilities,
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellIntegrationReadiness(
|
|
manifest = createIniPanelShellIntegrationManifest(),
|
|
) {
|
|
const integrationManifestSupported = isSupportedIniPanelShellIntegrationManifest(manifest);
|
|
const launchApiManifestSupported = integrationManifestSupported
|
|
&& isSupportedIniPanelLaunchApiManifest(manifest.launchApiManifest, manifest.launchApiSchema);
|
|
const controlPageApiManifestSupported = integrationManifestSupported
|
|
&& isSupportedIniPanelControlPageApiManifest(
|
|
manifest.controlPageApiManifest,
|
|
manifest.controlPageApiSchema,
|
|
);
|
|
const compatibility = integrationManifestSupported && manifest.compatibility
|
|
? {
|
|
launchApiManifest: Boolean(manifest.compatibility.launchApiManifest),
|
|
controlPageApiManifest: Boolean(manifest.compatibility.controlPageApiManifest),
|
|
}
|
|
: {
|
|
launchApiManifest: false,
|
|
controlPageApiManifest: false,
|
|
};
|
|
const checks = {
|
|
integrationManifestSupported,
|
|
launchApiManifestSupported,
|
|
controlPageApiManifestSupported,
|
|
launchCompatibility: compatibility.launchApiManifest,
|
|
controlPageCompatibility: compatibility.controlPageApiManifest,
|
|
};
|
|
const missing = Object.entries(checks)
|
|
.filter(([, passed]) => !passed)
|
|
.map(([name]) => name);
|
|
const ready = missing.length === 0;
|
|
|
|
return {
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
checks,
|
|
missing,
|
|
counts: {
|
|
pages: Array.isArray(manifest?.pages) ? manifest.pages.length : 0,
|
|
launcherLinks: Array.isArray(manifest?.launcherLinks) ? manifest.launcherLinks.length : 0,
|
|
launchMethods: Array.isArray(manifest?.launchApiManifest?.methods)
|
|
? manifest.launchApiManifest.methods.length
|
|
: 0,
|
|
controlPageMethods: Array.isArray(manifest?.controlPageApiManifest?.methods)
|
|
? manifest.controlPageApiManifest.methods.length
|
|
: 0,
|
|
persistenceCapabilities: Array.isArray(manifest?.persistenceCapabilities)
|
|
? manifest.persistenceCapabilities.length
|
|
: 0,
|
|
},
|
|
apiNames: {
|
|
integration: manifest?.apiName ?? null,
|
|
launch: manifest?.launchApiManifest?.apiName ?? null,
|
|
controlPage: manifest?.controlPageApiManifest?.apiName ?? null,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellIntegrationWorkflowPlan({
|
|
manifest = createIniPanelShellIntegrationManifest(),
|
|
readiness = createIniPanelShellIntegrationReadiness(manifest),
|
|
controlEntryId = "control-view",
|
|
} = {}) {
|
|
const targetPage = manifest?.launchApiManifest?.targetPages?.find(
|
|
(page) => page.entryId === controlEntryId,
|
|
) ?? null;
|
|
const requiredLaunchApiMethods = [
|
|
"getShellIntegrationManifest",
|
|
"getShellIntegrationReadiness",
|
|
];
|
|
const requiredControlPageApiMethods = [
|
|
"getControlPageApiManifest",
|
|
"loadControlPageSessionState",
|
|
"readControlPageStatus",
|
|
];
|
|
const launchMethods = Array.isArray(manifest?.launchApiManifest?.methods)
|
|
? manifest.launchApiManifest.methods
|
|
: [];
|
|
const controlPageMethods = Array.isArray(manifest?.controlPageApiManifest?.methods)
|
|
? manifest.controlPageApiManifest.methods
|
|
: [];
|
|
const missingLaunchApiMethods = requiredLaunchApiMethods.filter(
|
|
(methodName) => !launchMethods.includes(methodName),
|
|
);
|
|
const missingControlPageApiMethods = requiredControlPageApiMethods.filter(
|
|
(methodName) => !controlPageMethods.includes(methodName),
|
|
);
|
|
const missing = [
|
|
...readiness.missing,
|
|
...(targetPage ? [] : ["controlTargetPage"]),
|
|
...missingLaunchApiMethods.map((methodName) => `launchApi.${methodName}`),
|
|
...missingControlPageApiMethods.map((methodName) => `controlPageApi.${methodName}`),
|
|
];
|
|
const ready = readiness.ready && missing.length === 0;
|
|
|
|
return {
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
controlEntryId,
|
|
targetPage,
|
|
readiness,
|
|
requiredLaunchApiMethods,
|
|
requiredControlPageApiMethods,
|
|
missingLaunchApiMethods,
|
|
missingControlPageApiMethods,
|
|
missing,
|
|
readonlyStatusHandoff: {
|
|
loadSessionStateMethod: "loadControlPageSessionState",
|
|
readStatusMethod: "readControlPageStatus",
|
|
expectedStatusFields: manifest?.controlPageApiManifest?.readonlyStatusApiManifest?.statusFields ?? [],
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffSummarySchema() {
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-summary",
|
|
summaryVersion: 1,
|
|
fields: [
|
|
"apiName",
|
|
"summaryVersion",
|
|
"phase",
|
|
"ready",
|
|
"targetPage",
|
|
"readiness",
|
|
"persistenceCapabilities",
|
|
"readonlyStatusFields",
|
|
"handoffMethods",
|
|
"blockingReasons",
|
|
],
|
|
};
|
|
}
|
|
|
|
export function isSupportedIniPanelShellSessionHandoffSummary(
|
|
summary,
|
|
schema = createIniPanelShellSessionHandoffSummarySchema(),
|
|
) {
|
|
if (!summary || typeof summary !== "object") {
|
|
return false;
|
|
}
|
|
if (summary.apiName !== schema.apiName || summary.summaryVersion !== schema.summaryVersion) {
|
|
return false;
|
|
}
|
|
return schema.fields.every((fieldName) => Object.hasOwn(summary, fieldName));
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffSummary({
|
|
manifest = createIniPanelShellIntegrationManifest(),
|
|
readiness = createIniPanelShellIntegrationReadiness(manifest),
|
|
workflowPlan = createIniPanelShellIntegrationWorkflowPlan({ manifest, readiness }),
|
|
} = {}) {
|
|
const schema = createIniPanelShellSessionHandoffSummarySchema();
|
|
const persistenceCapabilities = Array.isArray(manifest?.persistenceCapabilities)
|
|
? manifest.persistenceCapabilities.map(({ id, label, scope }) => ({ id, label, scope }))
|
|
: [];
|
|
const readonlyStatusFields = Array.isArray(workflowPlan?.readonlyStatusHandoff?.expectedStatusFields)
|
|
? [...workflowPlan.readonlyStatusHandoff.expectedStatusFields]
|
|
: [];
|
|
return {
|
|
apiName: schema.apiName,
|
|
summaryVersion: schema.summaryVersion,
|
|
phase: workflowPlan.ready ? "ready" : "blocked",
|
|
ready: Boolean(workflowPlan.ready),
|
|
targetPage: workflowPlan.targetPage,
|
|
readiness: {
|
|
phase: readiness.phase,
|
|
missing: [...readiness.missing],
|
|
counts: { ...readiness.counts },
|
|
apiNames: { ...readiness.apiNames },
|
|
},
|
|
persistenceCapabilities,
|
|
readonlyStatusFields,
|
|
handoffMethods: {
|
|
loadSessionState: workflowPlan.readonlyStatusHandoff.loadSessionStateMethod,
|
|
readStatus: workflowPlan.readonlyStatusHandoff.readStatusMethod,
|
|
},
|
|
blockingReasons: [...workflowPlan.missing],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffCompatibilityReport(
|
|
summary = createIniPanelShellSessionHandoffSummary(),
|
|
schema = createIniPanelShellSessionHandoffSummarySchema(),
|
|
) {
|
|
const summaryObject = summary && typeof summary === "object" ? summary : {};
|
|
const missingFields = schema.fields.filter((fieldName) => !Object.hasOwn(summaryObject, fieldName));
|
|
const mismatchFields = [
|
|
...(summaryObject.apiName === schema.apiName ? [] : ["apiName"]),
|
|
...(summaryObject.summaryVersion === schema.summaryVersion ? [] : ["summaryVersion"]),
|
|
];
|
|
const summarySupported = missingFields.length === 0 && mismatchFields.length === 0;
|
|
const blockingReasons = Array.isArray(summaryObject.blockingReasons)
|
|
? [...summaryObject.blockingReasons]
|
|
: [];
|
|
const handoffReady = summarySupported && summaryObject.ready === true && blockingReasons.length === 0;
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-compatibility-report",
|
|
reportVersion: 1,
|
|
phase: handoffReady ? "ready" : "blocked",
|
|
compatible: handoffReady,
|
|
summarySupported,
|
|
handoffReady,
|
|
schema: {
|
|
apiName: schema.apiName,
|
|
summaryVersion: schema.summaryVersion,
|
|
fields: [...schema.fields],
|
|
},
|
|
summary: {
|
|
apiName: summaryObject.apiName ?? null,
|
|
summaryVersion: summaryObject.summaryVersion ?? null,
|
|
phase: summaryObject.phase ?? null,
|
|
ready: summaryObject.ready ?? false,
|
|
},
|
|
missingFields,
|
|
mismatchFields,
|
|
blockingReasons,
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffDisplayViewModel(
|
|
report = createIniPanelShellSessionHandoffCompatibilityReport(),
|
|
) {
|
|
const missingFields = Array.isArray(report?.missingFields) ? report.missingFields : [];
|
|
const mismatchFields = Array.isArray(report?.mismatchFields) ? report.mismatchFields : [];
|
|
const blockingReasons = Array.isArray(report?.blockingReasons) ? report.blockingReasons : [];
|
|
const problems = [...missingFields, ...mismatchFields, ...blockingReasons];
|
|
|
|
return {
|
|
phase: report?.phase === "ready" ? "ready" : "blocked",
|
|
title: "Shell handoff compatibility",
|
|
statusText: report?.compatible ? "Ready" : "Blocked",
|
|
detailText: problems.length === 0 ? "No blocking reasons" : problems.join(", "),
|
|
rows: [
|
|
{
|
|
id: "summary-supported",
|
|
label: "Summary schema",
|
|
value: report?.summarySupported ? "supported" : "blocked",
|
|
},
|
|
{
|
|
id: "handoff-ready",
|
|
label: "Handoff readiness",
|
|
value: report?.handoffReady ? "ready" : "blocked",
|
|
},
|
|
{
|
|
id: "missing-fields",
|
|
label: "Missing fields",
|
|
value: missingFields.length === 0 ? "none" : missingFields.join(", "),
|
|
},
|
|
{
|
|
id: "mismatch-fields",
|
|
label: "Mismatched fields",
|
|
value: mismatchFields.length === 0 ? "none" : mismatchFields.join(", "),
|
|
},
|
|
{
|
|
id: "blocking-reasons",
|
|
label: "Blocking reasons",
|
|
value: blockingReasons.length === 0 ? "none" : blockingReasons.join(", "),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffSnapshot({
|
|
readiness = createIniPanelShellIntegrationReadiness(),
|
|
summary = createIniPanelShellSessionHandoffSummary(),
|
|
compatibilityReport = createIniPanelShellSessionHandoffCompatibilityReport(summary),
|
|
displayViewModel = createIniPanelShellSessionHandoffDisplayViewModel(compatibilityReport),
|
|
} = {}) {
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-snapshot",
|
|
snapshotVersion: 1,
|
|
phase: compatibilityReport.phase,
|
|
ready: Boolean(compatibilityReport.compatible),
|
|
readiness,
|
|
summary,
|
|
compatibilityReport,
|
|
displayViewModel,
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffRenderState(
|
|
snapshot = createIniPanelShellSessionHandoffSnapshot(),
|
|
) {
|
|
const displayViewModel = snapshot?.displayViewModel && typeof snapshot.displayViewModel === "object"
|
|
? snapshot.displayViewModel
|
|
: createIniPanelShellSessionHandoffDisplayViewModel(snapshot?.compatibilityReport);
|
|
const rows = Array.isArray(displayViewModel.rows)
|
|
? displayViewModel.rows.map(({ id, label, value }) => ({
|
|
id,
|
|
label,
|
|
value: value == null ? "" : String(value),
|
|
}))
|
|
: [];
|
|
const ready = snapshot?.ready === true && displayViewModel.phase === "ready";
|
|
const statusText = displayViewModel.statusText ?? (ready ? "Ready" : "Blocked");
|
|
const detailText = displayViewModel.detailText ?? "No blocking reasons";
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-render-state",
|
|
renderStateVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
title: displayViewModel.title ?? "Shell handoff compatibility",
|
|
statusText,
|
|
detailText,
|
|
statusLine: `${statusText}: ${detailText}`,
|
|
rows,
|
|
dataset: {
|
|
handoffPhase: ready ? "ready" : "blocked",
|
|
handoffReady: ready ? "true" : "false",
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffActionPlan({
|
|
snapshot = createIniPanelShellSessionHandoffSnapshot(),
|
|
renderState = createIniPanelShellSessionHandoffRenderState(snapshot),
|
|
} = {}) {
|
|
const summary = snapshot?.summary && typeof snapshot.summary === "object" ? snapshot.summary : {};
|
|
const handoffMethods = summary.handoffMethods && typeof summary.handoffMethods === "object"
|
|
? summary.handoffMethods
|
|
: {};
|
|
const blockingReasons = Array.isArray(summary.blockingReasons)
|
|
? [...summary.blockingReasons]
|
|
: [];
|
|
const displayRows = Array.isArray(renderState?.rows) ? renderState.rows.map(({ id, label, value }) => ({
|
|
id,
|
|
label,
|
|
value,
|
|
})) : [];
|
|
const ready = snapshot?.ready === true && renderState?.ready === true && blockingReasons.length === 0;
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-action-plan",
|
|
planVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
statusLine: renderState?.statusLine ?? "Blocked: No handoff render state",
|
|
targetPage: summary.targetPage ?? null,
|
|
requiredMethods: {
|
|
loadSessionState: handoffMethods.loadSessionState ?? null,
|
|
readStatus: handoffMethods.readStatus ?? null,
|
|
},
|
|
blockingReasons,
|
|
displayRows,
|
|
nextSteps: ready
|
|
? [
|
|
{
|
|
id: "open-control-page",
|
|
label: "Open control page target",
|
|
targetPage: summary.targetPage ?? null,
|
|
},
|
|
{
|
|
id: "read-readonly-status",
|
|
label: "Read readonly status",
|
|
methods: {
|
|
loadSessionState: handoffMethods.loadSessionState ?? null,
|
|
readStatus: handoffMethods.readStatus ?? null,
|
|
},
|
|
},
|
|
]
|
|
: [
|
|
{
|
|
id: "resolve-blockers",
|
|
label: "Resolve handoff blockers",
|
|
blockingReasons,
|
|
displayRows,
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffChecklist({
|
|
actionPlan = createIniPanelShellSessionHandoffActionPlan(),
|
|
renderState = createIniPanelShellSessionHandoffRenderState(),
|
|
} = {}) {
|
|
const displayRows = Array.isArray(actionPlan?.displayRows)
|
|
? actionPlan.displayRows.map(({ id, label, value }) => ({ id, label, value }))
|
|
: [];
|
|
const blockingReasons = Array.isArray(actionPlan?.blockingReasons)
|
|
? [...actionPlan.blockingReasons]
|
|
: [];
|
|
const targetPageReady = Boolean(actionPlan?.targetPage?.href);
|
|
const loadMethodReady = Boolean(actionPlan?.requiredMethods?.loadSessionState);
|
|
const readMethodReady = Boolean(actionPlan?.requiredMethods?.readStatus);
|
|
const ready = actionPlan?.ready === true
|
|
&& renderState?.ready === true
|
|
&& targetPageReady
|
|
&& loadMethodReady
|
|
&& readMethodReady
|
|
&& blockingReasons.length === 0;
|
|
const checks = [
|
|
{
|
|
id: "render-state",
|
|
label: "Render state",
|
|
status: renderState?.ready ? "pass" : "blocked",
|
|
value: renderState?.statusLine ?? "missing",
|
|
},
|
|
{
|
|
id: "target-page",
|
|
label: "Control target",
|
|
status: targetPageReady ? "pass" : "blocked",
|
|
value: actionPlan?.targetPage?.href ?? "missing",
|
|
},
|
|
{
|
|
id: "load-session-method",
|
|
label: "Load session method",
|
|
status: loadMethodReady ? "pass" : "blocked",
|
|
value: actionPlan?.requiredMethods?.loadSessionState ?? "missing",
|
|
},
|
|
{
|
|
id: "read-status-method",
|
|
label: "Read status method",
|
|
status: readMethodReady ? "pass" : "blocked",
|
|
value: actionPlan?.requiredMethods?.readStatus ?? "missing",
|
|
},
|
|
{
|
|
id: "blocking-reasons",
|
|
label: "Blocking reasons",
|
|
status: blockingReasons.length === 0 ? "pass" : "blocked",
|
|
value: blockingReasons.length === 0 ? "none" : blockingReasons.join(", "),
|
|
},
|
|
];
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-checklist",
|
|
checklistVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
statusLine: actionPlan?.statusLine ?? renderState?.statusLine ?? "Blocked: No handoff action plan",
|
|
checks,
|
|
displayRows,
|
|
nextStepIds: Array.isArray(actionPlan?.nextSteps)
|
|
? actionPlan.nextSteps.map(({ id }) => id)
|
|
: [],
|
|
blockingReasons,
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffPackage({
|
|
shellIntegrationManifest = createIniPanelShellIntegrationManifest(),
|
|
launchApiManifest = shellIntegrationManifest.launchApiManifest ?? createIniPanelLaunchApiManifest(),
|
|
controlPageApiManifest = shellIntegrationManifest.controlPageApiManifest ?? createControlPageBrowserApiManifest(),
|
|
snapshot = createIniPanelShellSessionHandoffSnapshot(),
|
|
renderState = createIniPanelShellSessionHandoffRenderState(snapshot),
|
|
actionPlan = createIniPanelShellSessionHandoffActionPlan({ snapshot, renderState }),
|
|
checklist = createIniPanelShellSessionHandoffChecklist({ actionPlan, renderState }),
|
|
} = {}) {
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-package",
|
|
packageVersion: 1,
|
|
phase: checklist.phase,
|
|
ready: Boolean(checklist.ready),
|
|
statusLine: checklist.statusLine,
|
|
manifests: {
|
|
shellIntegration: shellIntegrationManifest,
|
|
launchApi: launchApiManifest,
|
|
controlPageApi: controlPageApiManifest,
|
|
launchMethods: Array.isArray(launchApiManifest?.methods) ? [...launchApiManifest.methods] : [],
|
|
controlPageMethods: Array.isArray(controlPageApiManifest?.methods) ? [...controlPageApiManifest.methods] : [],
|
|
},
|
|
snapshot,
|
|
renderState,
|
|
actionPlan,
|
|
checklist,
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffPackageSchema() {
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-package",
|
|
packageVersion: 1,
|
|
fields: [
|
|
"apiName",
|
|
"packageVersion",
|
|
"phase",
|
|
"ready",
|
|
"statusLine",
|
|
"manifests",
|
|
"snapshot",
|
|
"renderState",
|
|
"actionPlan",
|
|
"checklist",
|
|
],
|
|
manifestFields: [
|
|
"shellIntegration",
|
|
"launchApi",
|
|
"controlPageApi",
|
|
"launchMethods",
|
|
"controlPageMethods",
|
|
],
|
|
};
|
|
}
|
|
|
|
export function isSupportedIniPanelShellSessionHandoffPackage(
|
|
handoffPackage,
|
|
schema = createIniPanelShellSessionHandoffPackageSchema(),
|
|
) {
|
|
if (!handoffPackage || typeof handoffPackage !== "object") {
|
|
return false;
|
|
}
|
|
if (handoffPackage.apiName !== schema.apiName || handoffPackage.packageVersion !== schema.packageVersion) {
|
|
return false;
|
|
}
|
|
if (!schema.fields.every((fieldName) => Object.hasOwn(handoffPackage, fieldName))) {
|
|
return false;
|
|
}
|
|
const manifests = handoffPackage.manifests;
|
|
if (!manifests || typeof manifests !== "object") {
|
|
return false;
|
|
}
|
|
return schema.manifestFields.every((fieldName) => Object.hasOwn(manifests, fieldName));
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffPackageReport(
|
|
handoffPackage = createIniPanelShellSessionHandoffPackage(),
|
|
schema = createIniPanelShellSessionHandoffPackageSchema(),
|
|
) {
|
|
const packageObject = handoffPackage && typeof handoffPackage === "object" ? handoffPackage : {};
|
|
const manifests = packageObject.manifests && typeof packageObject.manifests === "object"
|
|
? packageObject.manifests
|
|
: {};
|
|
const missingPackageFields = schema.fields.filter((fieldName) => !Object.hasOwn(packageObject, fieldName));
|
|
const missingManifestFields = schema.manifestFields.filter((fieldName) => !Object.hasOwn(manifests, fieldName));
|
|
const mismatchFields = [
|
|
...(packageObject.apiName === schema.apiName ? [] : ["apiName"]),
|
|
...(packageObject.packageVersion === schema.packageVersion ? [] : ["packageVersion"]),
|
|
];
|
|
const blockingReasons = Array.isArray(packageObject?.checklist?.blockingReasons)
|
|
? [...packageObject.checklist.blockingReasons]
|
|
: [];
|
|
const packageSupported = missingPackageFields.length === 0
|
|
&& missingManifestFields.length === 0
|
|
&& mismatchFields.length === 0;
|
|
const ready = packageSupported && packageObject.ready === true && blockingReasons.length === 0;
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-package-report",
|
|
reportVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
packageSupported,
|
|
packageReady: ready,
|
|
statusLine: packageObject.statusLine ?? (ready ? "Ready: No blocking reasons" : "Blocked: Package unsupported"),
|
|
schema: {
|
|
apiName: schema.apiName,
|
|
packageVersion: schema.packageVersion,
|
|
fields: [...schema.fields],
|
|
manifestFields: [...schema.manifestFields],
|
|
},
|
|
package: {
|
|
apiName: packageObject.apiName ?? null,
|
|
packageVersion: packageObject.packageVersion ?? null,
|
|
phase: packageObject.phase ?? null,
|
|
ready: packageObject.ready ?? false,
|
|
},
|
|
missingPackageFields,
|
|
missingManifestFields,
|
|
mismatchFields,
|
|
blockingReasons,
|
|
rows: [
|
|
{
|
|
id: "package-supported",
|
|
label: "Package schema",
|
|
value: packageSupported ? "supported" : "blocked",
|
|
},
|
|
{
|
|
id: "package-ready",
|
|
label: "Package readiness",
|
|
value: ready ? "ready" : "blocked",
|
|
},
|
|
{
|
|
id: "missing-package-fields",
|
|
label: "Missing package fields",
|
|
value: missingPackageFields.length === 0 ? "none" : missingPackageFields.join(", "),
|
|
},
|
|
{
|
|
id: "missing-manifest-fields",
|
|
label: "Missing manifest fields",
|
|
value: missingManifestFields.length === 0 ? "none" : missingManifestFields.join(", "),
|
|
},
|
|
{
|
|
id: "mismatch-fields",
|
|
label: "Mismatched fields",
|
|
value: mismatchFields.length === 0 ? "none" : mismatchFields.join(", "),
|
|
},
|
|
{
|
|
id: "blocking-reasons",
|
|
label: "Blocking reasons",
|
|
value: blockingReasons.length === 0 ? "none" : blockingReasons.join(", "),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffPackageDisplayViewModel(
|
|
report = createIniPanelShellSessionHandoffPackageReport(),
|
|
) {
|
|
const missingPackageFields = Array.isArray(report?.missingPackageFields) ? report.missingPackageFields : [];
|
|
const missingManifestFields = Array.isArray(report?.missingManifestFields) ? report.missingManifestFields : [];
|
|
const mismatchFields = Array.isArray(report?.mismatchFields) ? report.mismatchFields : [];
|
|
const blockingReasons = Array.isArray(report?.blockingReasons) ? report.blockingReasons : [];
|
|
const problems = [
|
|
...missingPackageFields,
|
|
...missingManifestFields,
|
|
...mismatchFields,
|
|
...blockingReasons,
|
|
];
|
|
|
|
return {
|
|
phase: report?.phase === "ready" ? "ready" : "blocked",
|
|
title: "Shell handoff package",
|
|
statusText: report?.ready ? "Ready" : "Blocked",
|
|
detailText: problems.length === 0 ? "No blocking reasons" : problems.join(", "),
|
|
rows: Array.isArray(report?.rows)
|
|
? report.rows.map(({ id, label, value }) => ({
|
|
id,
|
|
label,
|
|
value,
|
|
}))
|
|
: [],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffPackageRenderState(
|
|
displayViewModel = createIniPanelShellSessionHandoffPackageDisplayViewModel(),
|
|
) {
|
|
const rows = Array.isArray(displayViewModel?.rows)
|
|
? displayViewModel.rows.map(({ id, label, value }) => ({
|
|
id,
|
|
label,
|
|
value: value == null ? "" : String(value),
|
|
}))
|
|
: [];
|
|
const ready = displayViewModel?.phase === "ready" && displayViewModel?.statusText === "Ready";
|
|
const statusText = displayViewModel?.statusText ?? (ready ? "Ready" : "Blocked");
|
|
const detailText = displayViewModel?.detailText ?? "No blocking reasons";
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-package-render-state",
|
|
renderStateVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
title: displayViewModel?.title ?? "Shell handoff package",
|
|
statusText,
|
|
detailText,
|
|
statusLine: `${statusText}: ${detailText}`,
|
|
rows,
|
|
dataset: {
|
|
handoffPhase: ready ? "ready" : "blocked",
|
|
handoffReady: ready ? "true" : "false",
|
|
handoffScope: "package",
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffPackageMountState({
|
|
handoffPackage = createIniPanelShellSessionHandoffPackage(),
|
|
packageRenderState = createIniPanelShellSessionHandoffPackageRenderState(),
|
|
sessionLoadState = createControlPageSessionLoadState({ phase: "waiting-panel" }),
|
|
} = {}) {
|
|
const actionPlan = handoffPackage?.actionPlan && typeof handoffPackage.actionPlan === "object"
|
|
? handoffPackage.actionPlan
|
|
: {};
|
|
const requiredMethods = actionPlan.requiredMethods && typeof actionPlan.requiredMethods === "object"
|
|
? actionPlan.requiredMethods
|
|
: {};
|
|
const targetPage = actionPlan.targetPage ?? null;
|
|
const blockingReasons = [
|
|
...(Array.isArray(actionPlan.blockingReasons) ? actionPlan.blockingReasons : []),
|
|
...(sessionLoadState?.phase === "error" ? ["controlPageSessionError"] : []),
|
|
];
|
|
const packageReady = handoffPackage?.ready === true && packageRenderState?.ready === true;
|
|
const targetReady = Boolean(targetPage?.href);
|
|
const methodsReady = Boolean(requiredMethods.loadSessionState && requiredMethods.readStatus);
|
|
const sessionReady = sessionLoadState?.phase === "ready";
|
|
const ready = packageReady && targetReady && methodsReady && sessionReady && blockingReasons.length === 0;
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-package-mount-state",
|
|
mountStateVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
packageReady,
|
|
targetReady,
|
|
methodsReady,
|
|
sessionReady,
|
|
statusLine: ready
|
|
? "Ready: Control page session mounted"
|
|
: `Blocked: ${blockingReasons.length === 0 ? sessionLoadState?.phase ?? "waiting-panel" : blockingReasons.join(", ")}`,
|
|
packageRenderState,
|
|
targetPage,
|
|
requiredMethods: {
|
|
loadSessionState: requiredMethods.loadSessionState ?? null,
|
|
readStatus: requiredMethods.readStatus ?? null,
|
|
},
|
|
sessionLoadState,
|
|
blockingReasons,
|
|
checks: [
|
|
{
|
|
id: "package-render-state",
|
|
label: "Package render state",
|
|
status: packageReady ? "pass" : "blocked",
|
|
value: packageRenderState?.statusLine ?? "missing",
|
|
},
|
|
{
|
|
id: "target-page",
|
|
label: "Control target",
|
|
status: targetReady ? "pass" : "blocked",
|
|
value: targetPage?.href ?? "missing",
|
|
},
|
|
{
|
|
id: "required-methods",
|
|
label: "Readonly methods",
|
|
status: methodsReady ? "pass" : "blocked",
|
|
value: methodsReady
|
|
? `${requiredMethods.loadSessionState}, ${requiredMethods.readStatus}`
|
|
: "missing",
|
|
},
|
|
{
|
|
id: "session-load-state",
|
|
label: "Session load state",
|
|
status: sessionReady ? "pass" : "blocked",
|
|
value: sessionLoadState?.phase ?? "missing",
|
|
},
|
|
{
|
|
id: "blocking-reasons",
|
|
label: "Blocking reasons",
|
|
status: blockingReasons.length === 0 ? "pass" : "blocked",
|
|
value: blockingReasons.length === 0 ? "none" : blockingReasons.join(", "),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffPackageMountDisplayViewModel(
|
|
mountState = createIniPanelShellSessionHandoffPackageMountState(),
|
|
) {
|
|
const checks = Array.isArray(mountState?.checks) ? mountState.checks : [];
|
|
const blockingChecks = checks.filter(({ status }) => status !== "pass");
|
|
const blockingReasons = Array.isArray(mountState?.blockingReasons) ? mountState.blockingReasons : [];
|
|
const problems = [
|
|
...blockingReasons,
|
|
...blockingChecks.map(({ id }) => id),
|
|
];
|
|
|
|
return {
|
|
phase: mountState?.phase === "ready" ? "ready" : "blocked",
|
|
title: "Shell handoff mount",
|
|
statusText: mountState?.ready ? "Ready" : "Blocked",
|
|
detailText: problems.length === 0 ? "No blocking reasons" : problems.join(", "),
|
|
rows: checks.map(({ id, label, status, value }) => ({
|
|
id,
|
|
label,
|
|
value,
|
|
status,
|
|
})),
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffPackageMountRenderState(
|
|
displayViewModel = createIniPanelShellSessionHandoffPackageMountDisplayViewModel(),
|
|
) {
|
|
const rows = Array.isArray(displayViewModel?.rows)
|
|
? displayViewModel.rows.map(({ id, label, value, status }) => ({
|
|
id,
|
|
label,
|
|
value: value == null ? "" : String(value),
|
|
status: status ?? "blocked",
|
|
}))
|
|
: [];
|
|
const ready = displayViewModel?.phase === "ready" && displayViewModel?.statusText === "Ready";
|
|
const statusText = displayViewModel?.statusText ?? (ready ? "Ready" : "Blocked");
|
|
const detailText = displayViewModel?.detailText ?? "No blocking reasons";
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-package-mount-render-state",
|
|
renderStateVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
title: displayViewModel?.title ?? "Shell handoff mount",
|
|
statusText,
|
|
detailText,
|
|
statusLine: `${statusText}: ${detailText}`,
|
|
rows,
|
|
dataset: {
|
|
handoffPhase: ready ? "ready" : "blocked",
|
|
handoffReady: ready ? "true" : "false",
|
|
handoffScope: "mount",
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffMountDomContract({
|
|
rowDatasetPrefix = "handoffMount",
|
|
selectors = {},
|
|
} = {}) {
|
|
const mountSelector = selectors.mount ?? "[data-handoff-mount]";
|
|
const statusSelector = selectors.status ?? "[data-handoff-mount-status]";
|
|
const rowsSelector = selectors.rows ?? "[data-handoff-mount-rows]";
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-mount-dom-contract",
|
|
contractVersion: 1,
|
|
requiredNodeIds: ["mount", "status", "rows"],
|
|
selectors: {
|
|
mount: mountSelector,
|
|
status: statusSelector,
|
|
rows: rowsSelector,
|
|
},
|
|
mountDatasetKeys: ["handoffPhase", "handoffReady", "handoffScope"],
|
|
rowDatasetPrefix,
|
|
rowDatasetKeys: {
|
|
term: [`${rowDatasetPrefix}Row`, `${rowDatasetPrefix}Status`],
|
|
detail: [`${rowDatasetPrefix}Value`, `${rowDatasetPrefix}Status`],
|
|
},
|
|
renderResultFields: ["rendered", "statusLine", "rowCount", "rowIds", "dataset"],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffMountDomReadiness({
|
|
rowDatasetPrefix = "handoffMount",
|
|
contract = createIniPanelShellSessionHandoffMountDomContract({ rowDatasetPrefix }),
|
|
documentRef = globalThis.document,
|
|
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
|
|
statusNode = documentRef?.querySelector?.(contract.selectors.status),
|
|
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
|
|
} = {}) {
|
|
const checks = {
|
|
document: Boolean(documentRef?.createElement),
|
|
mount: Boolean(mountNode),
|
|
status: Boolean(statusNode),
|
|
rows: Boolean(rowsNode),
|
|
rowDatasetPrefix: Boolean(contract.rowDatasetPrefix),
|
|
};
|
|
const missing = Object.entries(checks)
|
|
.filter(([, passed]) => !passed)
|
|
.map(([name]) => name);
|
|
const ready = missing.length === 0;
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-mount-dom-readiness",
|
|
readinessVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
missing,
|
|
checks,
|
|
contract,
|
|
};
|
|
}
|
|
|
|
export function renderIniPanelShellSessionHandoffMountState(
|
|
renderState = createIniPanelShellSessionHandoffPackageMountRenderState(),
|
|
{
|
|
rowDatasetPrefix = "handoffMount",
|
|
contract = createIniPanelShellSessionHandoffMountDomContract({ rowDatasetPrefix }),
|
|
documentRef = globalThis.document,
|
|
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
|
|
statusNode = documentRef?.querySelector?.(contract.selectors.status),
|
|
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
|
|
} = {},
|
|
) {
|
|
const readiness = createIniPanelShellSessionHandoffMountDomReadiness({
|
|
contract,
|
|
documentRef,
|
|
mountNode,
|
|
statusNode,
|
|
rowsNode,
|
|
});
|
|
if (!readiness.ready) {
|
|
throw new Error(
|
|
`Shell handoff mount DOM is not ready: ${readiness.missing.join(", ")}`,
|
|
);
|
|
}
|
|
|
|
mountNode.dataset.handoffPhase = renderState?.dataset?.handoffPhase ?? "blocked";
|
|
mountNode.dataset.handoffReady = renderState?.dataset?.handoffReady ?? "false";
|
|
mountNode.dataset.handoffScope = renderState?.dataset?.handoffScope ?? "mount";
|
|
statusNode.textContent = renderState?.statusLine ?? "Blocked: No mount render state";
|
|
rowsNode.replaceChildren();
|
|
|
|
const rows = Array.isArray(renderState?.rows) ? renderState.rows : [];
|
|
const effectiveRowDatasetPrefix = contract.rowDatasetPrefix;
|
|
for (const row of rows) {
|
|
const term = documentRef.createElement("dt");
|
|
term.dataset[`${effectiveRowDatasetPrefix}Row`] = row.id;
|
|
term.dataset[`${effectiveRowDatasetPrefix}Status`] = row.status;
|
|
term.textContent = row.label;
|
|
const detail = documentRef.createElement("dd");
|
|
detail.dataset[`${effectiveRowDatasetPrefix}Value`] = row.id;
|
|
detail.dataset[`${effectiveRowDatasetPrefix}Status`] = row.status;
|
|
detail.textContent = row.value;
|
|
rowsNode.append(term, detail);
|
|
}
|
|
|
|
return {
|
|
rendered: true,
|
|
statusLine: statusNode.textContent,
|
|
rowCount: rows.length,
|
|
rowIds: rows.map(({ id }) => id),
|
|
dataset: {
|
|
handoffPhase: mountNode.dataset.handoffPhase,
|
|
handoffReady: mountNode.dataset.handoffReady,
|
|
handoffScope: mountNode.dataset.handoffScope,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function mountIniPanelShellSessionHandoff({
|
|
renderState = createIniPanelShellSessionHandoffPackageMountRenderState(),
|
|
rowDatasetPrefix = "handoffMount",
|
|
contract = createIniPanelShellSessionHandoffMountDomContract({ rowDatasetPrefix }),
|
|
documentRef = globalThis.document,
|
|
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
|
|
statusNode = documentRef?.querySelector?.(contract.selectors.status),
|
|
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
|
|
} = {}) {
|
|
const domReadiness = createIniPanelShellSessionHandoffMountDomReadiness({
|
|
contract,
|
|
documentRef,
|
|
mountNode,
|
|
statusNode,
|
|
rowsNode,
|
|
});
|
|
if (!domReadiness.ready) {
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-mount-workflow",
|
|
workflowVersion: 1,
|
|
phase: "blocked",
|
|
ready: false,
|
|
statusLine: `Blocked: ${domReadiness.missing.join(", ")}`,
|
|
contract,
|
|
domReadiness,
|
|
renderState,
|
|
renderResult: null,
|
|
error: null,
|
|
};
|
|
}
|
|
|
|
try {
|
|
const renderResult = renderIniPanelShellSessionHandoffMountState(renderState, {
|
|
contract,
|
|
documentRef,
|
|
mountNode,
|
|
statusNode,
|
|
rowsNode,
|
|
});
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-mount-workflow",
|
|
workflowVersion: 1,
|
|
phase: renderState?.ready ? "ready" : "blocked",
|
|
ready: renderState?.ready === true,
|
|
statusLine: renderResult.statusLine,
|
|
contract,
|
|
domReadiness,
|
|
renderState,
|
|
renderResult,
|
|
error: null,
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-mount-workflow",
|
|
workflowVersion: 1,
|
|
phase: "blocked",
|
|
ready: false,
|
|
statusLine: `Blocked: ${error?.message ?? "mount workflow error"}`,
|
|
contract,
|
|
domReadiness,
|
|
renderState,
|
|
renderResult: null,
|
|
error: error?.message ?? String(error),
|
|
};
|
|
}
|
|
}
|
|
|
|
export function mountIniPanelShellSessionHandoffFromControlPage({
|
|
controlPageApi = null,
|
|
sessionLoadState = null,
|
|
loadSessionStateMethod = "loadControlPageSessionState",
|
|
handoffPackage = createIniPanelShellSessionHandoffPackage(),
|
|
packageRenderState = createIniPanelShellSessionHandoffPackageRenderState(),
|
|
rowDatasetPrefix = "handoffMount",
|
|
contract = createIniPanelShellSessionHandoffMountDomContract({ rowDatasetPrefix }),
|
|
documentRef = globalThis.document,
|
|
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
|
|
statusNode = documentRef?.querySelector?.(contract.selectors.status),
|
|
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
|
|
} = {}) {
|
|
let observedSessionLoadState = sessionLoadState;
|
|
let sessionLoadError = null;
|
|
if (!observedSessionLoadState) {
|
|
const loadSessionState = controlPageApi?.[loadSessionStateMethod];
|
|
if (typeof loadSessionState === "function") {
|
|
try {
|
|
observedSessionLoadState = loadSessionState.call(controlPageApi);
|
|
} catch (error) {
|
|
sessionLoadError = error?.message ?? String(error);
|
|
observedSessionLoadState = createControlPageSessionLoadState({
|
|
phase: "error",
|
|
error: sessionLoadError,
|
|
});
|
|
}
|
|
} else {
|
|
observedSessionLoadState = createControlPageSessionLoadState({ phase: "waiting-api" });
|
|
}
|
|
}
|
|
|
|
const mountState = createIniPanelShellSessionHandoffPackageMountState({
|
|
handoffPackage,
|
|
packageRenderState,
|
|
sessionLoadState: observedSessionLoadState,
|
|
});
|
|
const mountDisplayViewModel = createIniPanelShellSessionHandoffPackageMountDisplayViewModel(mountState);
|
|
const mountRenderState = createIniPanelShellSessionHandoffPackageMountRenderState(mountDisplayViewModel);
|
|
const mountWorkflow = mountIniPanelShellSessionHandoff({
|
|
renderState: mountRenderState,
|
|
contract,
|
|
documentRef,
|
|
mountNode,
|
|
statusNode,
|
|
rowsNode,
|
|
});
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-control-page-mount-workflow",
|
|
workflowVersion: 1,
|
|
phase: mountWorkflow.phase,
|
|
ready: mountWorkflow.ready,
|
|
statusLine: mountWorkflow.statusLine,
|
|
loadSessionStateMethod,
|
|
sessionLoadState: observedSessionLoadState,
|
|
sessionLoadError,
|
|
mountState,
|
|
mountDisplayViewModel,
|
|
mountRenderState,
|
|
mountWorkflow,
|
|
};
|
|
}
|
|
|
|
export function readIniPanelShellSessionHandoffStatusFromControlPage({
|
|
controlPageApi = null,
|
|
readonlyStatus = null,
|
|
readStatusMethod = "readControlPageStatus",
|
|
handoffSummary = createIniPanelShellSessionHandoffSummary(),
|
|
expectedStatusFields = handoffSummary?.readonlyStatusFields ?? [],
|
|
} = {}) {
|
|
let observedStatus = readonlyStatus;
|
|
let readError = null;
|
|
if (!observedStatus) {
|
|
const readStatus = controlPageApi?.[readStatusMethod];
|
|
if (typeof readStatus === "function") {
|
|
try {
|
|
observedStatus = readStatus.call(controlPageApi);
|
|
} catch (error) {
|
|
readError = error?.message ?? String(error);
|
|
observedStatus = null;
|
|
}
|
|
} else {
|
|
readError = `Missing ${readStatusMethod}`;
|
|
observedStatus = null;
|
|
}
|
|
}
|
|
|
|
const statusObject = observedStatus && typeof observedStatus === "object" ? observedStatus : {};
|
|
const expectedFields = Array.isArray(expectedStatusFields) ? [...expectedStatusFields] : [];
|
|
const presentStatusFields = expectedFields.filter((fieldName) => Object.hasOwn(statusObject, fieldName));
|
|
const missingStatusFields = expectedFields.filter((fieldName) => !Object.hasOwn(statusObject, fieldName));
|
|
const ready = !readError && missingStatusFields.length === 0;
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-readonly-status-result",
|
|
resultVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
statusLine: ready
|
|
? "Ready: readonly status fields available"
|
|
: `Blocked: ${readError ?? missingStatusFields.join(", ")}`,
|
|
readStatusMethod,
|
|
expectedStatusFields: expectedFields,
|
|
presentStatusFields,
|
|
missingStatusFields,
|
|
readonlyStatus: observedStatus,
|
|
readError,
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffWorkflowSummary({
|
|
mountWorkflow = {
|
|
phase: "blocked",
|
|
ready: false,
|
|
statusLine: "Blocked: mount workflow unavailable",
|
|
},
|
|
controlPageMountWorkflow = {
|
|
phase: "blocked",
|
|
ready: false,
|
|
statusLine: "Blocked: control-page mount workflow unavailable",
|
|
},
|
|
readonlyStatusResult = {
|
|
phase: "blocked",
|
|
ready: false,
|
|
statusLine: "Blocked: readonly status unavailable",
|
|
missingStatusFields: [],
|
|
},
|
|
} = {}) {
|
|
const blockingReasons = [];
|
|
if (mountWorkflow?.ready !== true) {
|
|
blockingReasons.push(`mount:${mountWorkflow?.phase ?? "blocked"}`);
|
|
}
|
|
if (controlPageMountWorkflow?.ready !== true) {
|
|
blockingReasons.push(`control-page-mount:${controlPageMountWorkflow?.phase ?? "blocked"}`);
|
|
}
|
|
if (readonlyStatusResult?.ready !== true) {
|
|
const readonlyDetail = readonlyStatusResult?.readError
|
|
?? (
|
|
Array.isArray(readonlyStatusResult?.missingStatusFields)
|
|
&& readonlyStatusResult.missingStatusFields.length > 0
|
|
? readonlyStatusResult.missingStatusFields.join(", ")
|
|
: readonlyStatusResult?.phase ?? "blocked"
|
|
);
|
|
blockingReasons.push(`readonly-status:${readonlyDetail}`);
|
|
}
|
|
const ready = blockingReasons.length === 0;
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-workflow-summary",
|
|
summaryVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
statusLine: ready
|
|
? "Ready: shell handoff end-to-end workflow available"
|
|
: `Blocked: ${blockingReasons.join("; ")}`,
|
|
mountWorkflow: {
|
|
phase: mountWorkflow?.phase ?? "blocked",
|
|
ready: mountWorkflow?.ready === true,
|
|
statusLine: mountWorkflow?.statusLine ?? null,
|
|
},
|
|
controlPageMountWorkflow: {
|
|
phase: controlPageMountWorkflow?.phase ?? "blocked",
|
|
ready: controlPageMountWorkflow?.ready === true,
|
|
statusLine: controlPageMountWorkflow?.statusLine ?? null,
|
|
},
|
|
readonlyStatusResult: {
|
|
phase: readonlyStatusResult?.phase ?? "blocked",
|
|
ready: readonlyStatusResult?.ready === true,
|
|
statusLine: readonlyStatusResult?.statusLine ?? null,
|
|
missingStatusFields: Array.isArray(readonlyStatusResult?.missingStatusFields)
|
|
? [...readonlyStatusResult.missingStatusFields]
|
|
: [],
|
|
},
|
|
blockingReasons,
|
|
rows: [
|
|
{
|
|
id: "mount-workflow",
|
|
label: "Mount workflow",
|
|
value: mountWorkflow?.statusLine ?? "missing",
|
|
},
|
|
{
|
|
id: "control-page-mount-workflow",
|
|
label: "Control-page mount workflow",
|
|
value: controlPageMountWorkflow?.statusLine ?? "missing",
|
|
},
|
|
{
|
|
id: "readonly-status-workflow",
|
|
label: "Readonly status workflow",
|
|
value: readonlyStatusResult?.statusLine ?? "missing",
|
|
},
|
|
{
|
|
id: "readonly-status-missing-fields",
|
|
label: "Readonly missing fields",
|
|
value: Array.isArray(readonlyStatusResult?.missingStatusFields)
|
|
&& readonlyStatusResult.missingStatusFields.length > 0
|
|
? readonlyStatusResult.missingStatusFields.join(", ")
|
|
: "none",
|
|
},
|
|
{
|
|
id: "blocking-reasons",
|
|
label: "Blocking reasons",
|
|
value: blockingReasons.length > 0 ? blockingReasons.join("; ") : "none",
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffWorkflowDisplayViewModel(
|
|
workflowSummary = createIniPanelShellSessionHandoffWorkflowSummary(),
|
|
) {
|
|
const blockingReasons = Array.isArray(workflowSummary?.blockingReasons)
|
|
? workflowSummary.blockingReasons
|
|
: [];
|
|
return {
|
|
phase: workflowSummary?.phase === "ready" ? "ready" : "blocked",
|
|
title: "Shell handoff workflow",
|
|
statusText: workflowSummary?.ready ? "Ready" : "Blocked",
|
|
detailText: blockingReasons.length > 0 ? blockingReasons.join(", ") : "No blocking reasons",
|
|
rows: Array.isArray(workflowSummary?.rows)
|
|
? workflowSummary.rows.map(({ id, label, value }) => ({
|
|
id,
|
|
label,
|
|
value,
|
|
}))
|
|
: [],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffWorkflowRenderState(
|
|
displayViewModel = createIniPanelShellSessionHandoffWorkflowDisplayViewModel(),
|
|
) {
|
|
const rows = Array.isArray(displayViewModel?.rows)
|
|
? displayViewModel.rows.map(({ id, label, value }) => ({
|
|
id,
|
|
label,
|
|
value: value == null ? "" : String(value),
|
|
}))
|
|
: [];
|
|
const ready = displayViewModel?.phase === "ready" && displayViewModel?.statusText === "Ready";
|
|
const statusText = displayViewModel?.statusText ?? (ready ? "Ready" : "Blocked");
|
|
const detailText = displayViewModel?.detailText ?? "No blocking reasons";
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-workflow-render-state",
|
|
renderStateVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
title: displayViewModel?.title ?? "Shell handoff workflow",
|
|
statusText,
|
|
detailText,
|
|
statusLine: `${statusText}: ${detailText}`,
|
|
rows,
|
|
dataset: {
|
|
handoffPhase: ready ? "ready" : "blocked",
|
|
handoffReady: ready ? "true" : "false",
|
|
handoffScope: "workflow",
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffWorkflowDomContract({
|
|
rowDatasetPrefix = "handoffWorkflow",
|
|
selectors = {},
|
|
} = {}) {
|
|
const mountSelector = selectors.mount ?? "[data-handoff-workflow]";
|
|
const statusSelector = selectors.status ?? "[data-handoff-workflow-status]";
|
|
const rowsSelector = selectors.rows ?? "[data-handoff-workflow-rows]";
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-workflow-dom-contract",
|
|
contractVersion: 1,
|
|
requiredNodeIds: ["mount", "status", "rows"],
|
|
selectors: {
|
|
mount: mountSelector,
|
|
status: statusSelector,
|
|
rows: rowsSelector,
|
|
},
|
|
mountDatasetKeys: ["handoffPhase", "handoffReady", "handoffScope"],
|
|
rowDatasetPrefix,
|
|
rowDatasetKeys: {
|
|
term: [`${rowDatasetPrefix}Row`, `${rowDatasetPrefix}Status`],
|
|
detail: [`${rowDatasetPrefix}Value`, `${rowDatasetPrefix}Status`],
|
|
},
|
|
renderResultFields: ["rendered", "statusLine", "rowCount", "rowIds", "dataset"],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellWorkflowOverviewContract() {
|
|
return {
|
|
pageHref: "./workflow-overview.html",
|
|
entryId: "workflow-overview",
|
|
apiName: "linuxCncIniPanelWorkflowOverviewApi",
|
|
methodNames: [
|
|
"getWorkflowOverviewRenderState",
|
|
"getWorkflowOverviewDisplayViewModel",
|
|
"getWorkflowOverviewSummary",
|
|
"getWorkflowOverviewDomContract",
|
|
"getWorkflowOverviewDomReadiness",
|
|
"renderWorkflowOverview",
|
|
"mountWorkflowOverview",
|
|
"createWorkflowOverviewRenderState",
|
|
],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellWorkflowOverviewReadiness({
|
|
overviewApi = null,
|
|
contract = createIniPanelShellWorkflowOverviewContract(),
|
|
} = {}) {
|
|
const methodNames = Array.isArray(contract?.methodNames) ? contract.methodNames : [];
|
|
const missing = methodNames.filter((methodName) => typeof overviewApi?.[methodName] !== "function");
|
|
const ready = missing.length === 0;
|
|
return {
|
|
apiName: "ini-panel-shell-workflow-overview-readiness",
|
|
readinessVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
missing,
|
|
contract,
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellSessionHandoffWorkflowDomReadiness({
|
|
rowDatasetPrefix = "handoffWorkflow",
|
|
contract = createIniPanelShellSessionHandoffWorkflowDomContract({ rowDatasetPrefix }),
|
|
documentRef = globalThis.document,
|
|
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
|
|
statusNode = documentRef?.querySelector?.(contract.selectors.status),
|
|
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
|
|
} = {}) {
|
|
const checks = {
|
|
document: Boolean(documentRef?.createElement),
|
|
mount: Boolean(mountNode),
|
|
status: Boolean(statusNode),
|
|
rows: Boolean(rowsNode),
|
|
rowDatasetPrefix: Boolean(contract.rowDatasetPrefix),
|
|
};
|
|
const missing = Object.entries(checks)
|
|
.filter(([, passed]) => !passed)
|
|
.map(([name]) => name);
|
|
const ready = missing.length === 0;
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-workflow-dom-readiness",
|
|
readinessVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
missing,
|
|
checks,
|
|
contract,
|
|
};
|
|
}
|
|
|
|
export function renderIniPanelShellSessionHandoffWorkflowState(
|
|
renderState = createIniPanelShellSessionHandoffWorkflowRenderState(),
|
|
{
|
|
rowDatasetPrefix = "handoffWorkflow",
|
|
contract = createIniPanelShellSessionHandoffWorkflowDomContract({ rowDatasetPrefix }),
|
|
documentRef = globalThis.document,
|
|
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
|
|
statusNode = documentRef?.querySelector?.(contract.selectors.status),
|
|
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
|
|
} = {},
|
|
) {
|
|
const readiness = createIniPanelShellSessionHandoffWorkflowDomReadiness({
|
|
contract,
|
|
documentRef,
|
|
mountNode,
|
|
statusNode,
|
|
rowsNode,
|
|
});
|
|
if (!readiness.ready) {
|
|
throw new Error(
|
|
`Shell handoff workflow DOM is not ready: ${readiness.missing.join(", ")}`,
|
|
);
|
|
}
|
|
|
|
mountNode.dataset.handoffPhase = renderState?.dataset?.handoffPhase ?? "blocked";
|
|
mountNode.dataset.handoffReady = renderState?.dataset?.handoffReady ?? "false";
|
|
mountNode.dataset.handoffScope = renderState?.dataset?.handoffScope ?? "workflow";
|
|
statusNode.textContent = renderState?.statusLine ?? "Blocked: No workflow render state";
|
|
rowsNode.replaceChildren();
|
|
|
|
const rows = Array.isArray(renderState?.rows) ? renderState.rows : [];
|
|
const effectiveRowDatasetPrefix = contract.rowDatasetPrefix;
|
|
for (const row of rows) {
|
|
const term = documentRef.createElement("dt");
|
|
term.dataset[`${effectiveRowDatasetPrefix}Row`] = row.id;
|
|
term.dataset[`${effectiveRowDatasetPrefix}Status`] = renderState?.ready ? "pass" : "blocked";
|
|
term.textContent = row.label;
|
|
const detail = documentRef.createElement("dd");
|
|
detail.dataset[`${effectiveRowDatasetPrefix}Value`] = row.id;
|
|
detail.dataset[`${effectiveRowDatasetPrefix}Status`] = renderState?.ready ? "pass" : "blocked";
|
|
detail.textContent = row.value;
|
|
rowsNode.append(term, detail);
|
|
}
|
|
|
|
return {
|
|
rendered: true,
|
|
statusLine: statusNode.textContent,
|
|
rowCount: rows.length,
|
|
rowIds: rows.map(({ id }) => id),
|
|
dataset: {
|
|
handoffPhase: mountNode.dataset.handoffPhase,
|
|
handoffReady: mountNode.dataset.handoffReady,
|
|
handoffScope: mountNode.dataset.handoffScope,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function mountIniPanelShellSessionHandoffWorkflow({
|
|
renderState = createIniPanelShellSessionHandoffWorkflowRenderState(),
|
|
rowDatasetPrefix = "handoffWorkflow",
|
|
contract = createIniPanelShellSessionHandoffWorkflowDomContract({ rowDatasetPrefix }),
|
|
documentRef = globalThis.document,
|
|
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
|
|
statusNode = documentRef?.querySelector?.(contract.selectors.status),
|
|
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
|
|
} = {}) {
|
|
const domReadiness = createIniPanelShellSessionHandoffWorkflowDomReadiness({
|
|
contract,
|
|
documentRef,
|
|
mountNode,
|
|
statusNode,
|
|
rowsNode,
|
|
});
|
|
if (!domReadiness.ready) {
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-workflow-dom-mount",
|
|
workflowVersion: 1,
|
|
phase: "blocked",
|
|
ready: false,
|
|
statusLine: `Blocked: ${domReadiness.missing.join(", ")}`,
|
|
contract,
|
|
domReadiness,
|
|
renderState,
|
|
renderResult: null,
|
|
error: null,
|
|
};
|
|
}
|
|
|
|
try {
|
|
const renderResult = renderIniPanelShellSessionHandoffWorkflowState(renderState, {
|
|
contract,
|
|
documentRef,
|
|
mountNode,
|
|
statusNode,
|
|
rowsNode,
|
|
});
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-workflow-dom-mount",
|
|
workflowVersion: 1,
|
|
phase: renderState?.phase === "ready" ? "ready" : "blocked",
|
|
ready: renderState?.ready === true,
|
|
statusLine: renderResult.statusLine,
|
|
contract,
|
|
domReadiness,
|
|
renderState,
|
|
renderResult,
|
|
error: null,
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
apiName: "ini-panel-shell-session-handoff-workflow-dom-mount",
|
|
workflowVersion: 1,
|
|
phase: "blocked",
|
|
ready: false,
|
|
statusLine: `Blocked: ${error?.message ?? "workflow DOM mount error"}`,
|
|
contract,
|
|
domReadiness,
|
|
renderState,
|
|
renderResult: null,
|
|
error: error?.message ?? String(error),
|
|
};
|
|
}
|
|
}
|
|
|
|
export function mountIniPanelShellWorkflowOverviewEmbedding({
|
|
overviewApi = null,
|
|
contract = createIniPanelShellWorkflowOverviewContract(),
|
|
mountOptions = {},
|
|
} = {}) {
|
|
const readiness = createIniPanelShellWorkflowOverviewReadiness({
|
|
overviewApi,
|
|
contract,
|
|
});
|
|
if (!readiness.ready) {
|
|
return {
|
|
apiName: "ini-panel-shell-workflow-overview-embedding",
|
|
embeddingVersion: 1,
|
|
phase: "blocked",
|
|
ready: false,
|
|
pageHref: contract.pageHref,
|
|
contract,
|
|
readiness,
|
|
renderState: null,
|
|
mountResult: null,
|
|
error: null,
|
|
};
|
|
}
|
|
|
|
try {
|
|
const renderState = overviewApi.getWorkflowOverviewRenderState();
|
|
const mountResult = overviewApi.mountWorkflowOverview(mountOptions);
|
|
return {
|
|
apiName: "ini-panel-shell-workflow-overview-embedding",
|
|
embeddingVersion: 1,
|
|
phase: mountResult?.phase ?? "blocked",
|
|
ready: mountResult?.ready === true,
|
|
pageHref: contract.pageHref,
|
|
contract,
|
|
readiness,
|
|
renderState,
|
|
mountResult,
|
|
error: null,
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
apiName: "ini-panel-shell-workflow-overview-embedding",
|
|
embeddingVersion: 1,
|
|
phase: "blocked",
|
|
ready: false,
|
|
pageHref: contract.pageHref,
|
|
contract,
|
|
readiness,
|
|
renderState: null,
|
|
mountResult: null,
|
|
error: error?.message ?? String(error),
|
|
};
|
|
}
|
|
}
|
|
|
|
export function createIniPanelShellWorkflowOverviewEmbeddingReport(
|
|
embeddingResult = mountIniPanelShellWorkflowOverviewEmbedding(),
|
|
contract = createIniPanelShellWorkflowOverviewContract(),
|
|
) {
|
|
const result = embeddingResult && typeof embeddingResult === "object" ? embeddingResult : {};
|
|
const readiness = result.readiness && typeof result.readiness === "object" ? result.readiness : {};
|
|
const resultContract = result.contract && typeof result.contract === "object" ? result.contract : contract;
|
|
const mountResult = result.mountResult && typeof result.mountResult === "object" ? result.mountResult : {};
|
|
const renderResult = mountResult.renderResult && typeof mountResult.renderResult === "object"
|
|
? mountResult.renderResult
|
|
: {};
|
|
const missingMethods = Array.isArray(readiness.missing) ? [...readiness.missing] : [];
|
|
const error = result.error ?? mountResult.error ?? null;
|
|
const overviewReady = readiness.ready === true;
|
|
const embeddingReady = result.ready === true;
|
|
const mountPhase = mountResult.phase ?? null;
|
|
const mountReady = mountResult.ready === true;
|
|
const renderRowCount = Number.isFinite(renderResult.rowCount) ? renderResult.rowCount : 0;
|
|
const blockingReasons = [
|
|
...missingMethods.map((methodName) => `missing:${methodName}`),
|
|
...(embeddingReady ? [] : [`embedding:${result.phase ?? "blocked"}`]),
|
|
...(mountPhase && !mountReady ? [`mount:${mountPhase}`] : []),
|
|
...(error ? [`error:${error}`] : []),
|
|
];
|
|
const ready = overviewReady && embeddingReady && mountReady && !error && blockingReasons.length === 0;
|
|
const statusLine = ready
|
|
? "Ready: No blocking reasons"
|
|
: `Blocked: ${blockingReasons.length > 0 ? blockingReasons.join(", ") : "workflow overview embedding unavailable"}`;
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-workflow-overview-embedding-report",
|
|
reportVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
overviewReady,
|
|
embeddingReady,
|
|
mountReady,
|
|
statusLine,
|
|
pageHref: result.pageHref ?? resultContract.pageHref ?? null,
|
|
contract: resultContract,
|
|
missingMethods,
|
|
mountPhase,
|
|
renderRowCount,
|
|
error,
|
|
blockingReasons,
|
|
rows: [
|
|
{
|
|
id: "overview-api",
|
|
label: "Overview API",
|
|
value: overviewReady ? "ready" : "blocked",
|
|
},
|
|
{
|
|
id: "missing-methods",
|
|
label: "Missing methods",
|
|
value: missingMethods.length === 0 ? "none" : missingMethods.join(", "),
|
|
},
|
|
{
|
|
id: "embedding-ready",
|
|
label: "Embedding readiness",
|
|
value: embeddingReady ? "ready" : "blocked",
|
|
},
|
|
{
|
|
id: "mount-phase",
|
|
label: "Mount phase",
|
|
value: mountPhase ?? "missing",
|
|
},
|
|
{
|
|
id: "render-row-count",
|
|
label: "Render row count",
|
|
value: String(renderRowCount),
|
|
},
|
|
{
|
|
id: "error",
|
|
label: "Error",
|
|
value: error ?? "none",
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellWorkflowOverviewEmbeddingDisplayViewModel(
|
|
report = createIniPanelShellWorkflowOverviewEmbeddingReport(),
|
|
) {
|
|
const blockingReasons = Array.isArray(report?.blockingReasons) ? report.blockingReasons : [];
|
|
const rows = Array.isArray(report?.rows)
|
|
? report.rows.map(({ id, label, value }) => ({
|
|
id,
|
|
label,
|
|
value: value == null ? "" : String(value),
|
|
}))
|
|
: [];
|
|
return {
|
|
phase: report?.phase === "ready" ? "ready" : "blocked",
|
|
title: "Workflow overview embedding",
|
|
statusText: report?.ready ? "Ready" : "Blocked",
|
|
detailText: blockingReasons.length === 0 ? "No blocking reasons" : blockingReasons.join(", "),
|
|
rows,
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellWorkflowOverviewEmbeddingRenderState(
|
|
displayViewModel = createIniPanelShellWorkflowOverviewEmbeddingDisplayViewModel(),
|
|
) {
|
|
const rows = Array.isArray(displayViewModel?.rows)
|
|
? displayViewModel.rows.map(({ id, label, value }) => ({
|
|
id,
|
|
label,
|
|
value: value == null ? "" : String(value),
|
|
}))
|
|
: [];
|
|
const ready = displayViewModel?.phase === "ready" && displayViewModel?.statusText === "Ready";
|
|
const statusText = displayViewModel?.statusText ?? (ready ? "Ready" : "Blocked");
|
|
const detailText = displayViewModel?.detailText ?? "No blocking reasons";
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-workflow-overview-embedding-render-state",
|
|
renderStateVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
title: displayViewModel?.title ?? "Workflow overview embedding",
|
|
statusText,
|
|
detailText,
|
|
statusLine: `${statusText}: ${detailText}`,
|
|
rows,
|
|
dataset: {
|
|
handoffPhase: ready ? "ready" : "blocked",
|
|
handoffReady: ready ? "true" : "false",
|
|
handoffScope: "workflow-overview-embedding",
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellWorkflowOverviewEmbeddingDomContract({
|
|
rowDatasetPrefix = "workflowOverviewEmbedding",
|
|
selectors = {},
|
|
} = {}) {
|
|
const mountSelector = selectors.mount ?? "[data-workflow-overview-embedding]";
|
|
const statusSelector = selectors.status ?? "[data-workflow-overview-embedding-status]";
|
|
const rowsSelector = selectors.rows ?? "[data-workflow-overview-embedding-rows]";
|
|
return {
|
|
apiName: "ini-panel-shell-workflow-overview-embedding-dom-contract",
|
|
contractVersion: 1,
|
|
requiredNodeIds: ["mount", "status", "rows"],
|
|
selectors: {
|
|
mount: mountSelector,
|
|
status: statusSelector,
|
|
rows: rowsSelector,
|
|
},
|
|
mountDatasetKeys: ["handoffPhase", "handoffReady", "handoffScope"],
|
|
rowDatasetPrefix,
|
|
rowDatasetKeys: {
|
|
term: [`${rowDatasetPrefix}Row`, `${rowDatasetPrefix}Status`],
|
|
detail: [`${rowDatasetPrefix}Value`, `${rowDatasetPrefix}Status`],
|
|
},
|
|
renderResultFields: ["rendered", "statusLine", "rowCount", "rowIds", "dataset"],
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellWorkflowOverviewEmbeddingDomReadiness({
|
|
rowDatasetPrefix = "workflowOverviewEmbedding",
|
|
contract = createIniPanelShellWorkflowOverviewEmbeddingDomContract({ rowDatasetPrefix }),
|
|
documentRef = globalThis.document,
|
|
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
|
|
statusNode = documentRef?.querySelector?.(contract.selectors.status),
|
|
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
|
|
} = {}) {
|
|
const checks = {
|
|
document: Boolean(documentRef?.createElement),
|
|
mount: Boolean(mountNode),
|
|
status: Boolean(statusNode),
|
|
rows: Boolean(rowsNode),
|
|
rowDatasetPrefix: Boolean(contract.rowDatasetPrefix),
|
|
};
|
|
const missing = Object.entries(checks)
|
|
.filter(([, passed]) => !passed)
|
|
.map(([name]) => name);
|
|
const ready = missing.length === 0;
|
|
|
|
return {
|
|
apiName: "ini-panel-shell-workflow-overview-embedding-dom-readiness",
|
|
readinessVersion: 1,
|
|
phase: ready ? "ready" : "blocked",
|
|
ready,
|
|
missing,
|
|
checks,
|
|
contract,
|
|
};
|
|
}
|
|
|
|
export function renderIniPanelShellWorkflowOverviewEmbeddingState(
|
|
renderState = createIniPanelShellWorkflowOverviewEmbeddingRenderState(),
|
|
{
|
|
rowDatasetPrefix = "workflowOverviewEmbedding",
|
|
contract = createIniPanelShellWorkflowOverviewEmbeddingDomContract({ rowDatasetPrefix }),
|
|
documentRef = globalThis.document,
|
|
mountNode = documentRef?.querySelector?.(contract.selectors.mount),
|
|
statusNode = documentRef?.querySelector?.(contract.selectors.status),
|
|
rowsNode = documentRef?.querySelector?.(contract.selectors.rows),
|
|
} = {},
|
|
) {
|
|
const readiness = createIniPanelShellWorkflowOverviewEmbeddingDomReadiness({
|
|
contract,
|
|
documentRef,
|
|
mountNode,
|
|
statusNode,
|
|
rowsNode,
|
|
});
|
|
if (!readiness.ready) {
|
|
throw new Error(
|
|
`Workflow overview embedding DOM is not ready: ${readiness.missing.join(", ")}`,
|
|
);
|
|
}
|
|
|
|
mountNode.dataset.handoffPhase = renderState?.dataset?.handoffPhase ?? "blocked";
|
|
mountNode.dataset.handoffReady = renderState?.dataset?.handoffReady ?? "false";
|
|
mountNode.dataset.handoffScope = renderState?.dataset?.handoffScope ?? "workflow-overview-embedding";
|
|
statusNode.textContent = renderState?.statusLine ?? "Blocked: No workflow overview embedding render state";
|
|
rowsNode.replaceChildren();
|
|
|
|
const rows = Array.isArray(renderState?.rows) ? renderState.rows : [];
|
|
const effectiveRowDatasetPrefix = contract.rowDatasetPrefix;
|
|
for (const row of rows) {
|
|
const term = documentRef.createElement("dt");
|
|
term.dataset[`${effectiveRowDatasetPrefix}Row`] = row.id;
|
|
term.dataset[`${effectiveRowDatasetPrefix}Status`] = renderState?.ready ? "pass" : "blocked";
|
|
term.textContent = row.label;
|
|
const detail = documentRef.createElement("dd");
|
|
detail.dataset[`${effectiveRowDatasetPrefix}Value`] = row.id;
|
|
detail.dataset[`${effectiveRowDatasetPrefix}Status`] = renderState?.ready ? "pass" : "blocked";
|
|
detail.textContent = row.value;
|
|
rowsNode.append(term, detail);
|
|
}
|
|
|
|
return {
|
|
rendered: true,
|
|
statusLine: statusNode.textContent,
|
|
rowCount: rows.length,
|
|
rowIds: rows.map(({ id }) => id),
|
|
dataset: {
|
|
handoffPhase: mountNode.dataset.handoffPhase,
|
|
handoffReady: mountNode.dataset.handoffReady,
|
|
handoffScope: mountNode.dataset.handoffScope,
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createIniPanelShellViewModel(entries = getVisibleIniPanelEntries()) {
|
|
const shellIntegrationManifest = createIniPanelShellIntegrationManifest(entries);
|
|
const shellIntegrationReadiness = createIniPanelShellIntegrationReadiness(shellIntegrationManifest);
|
|
const shellIntegrationWorkflowPlan = createIniPanelShellIntegrationWorkflowPlan({
|
|
manifest: shellIntegrationManifest,
|
|
readiness: shellIntegrationReadiness,
|
|
});
|
|
const shellSessionHandoffSummary = createIniPanelShellSessionHandoffSummary({
|
|
manifest: shellIntegrationManifest,
|
|
readiness: shellIntegrationReadiness,
|
|
workflowPlan: shellIntegrationWorkflowPlan,
|
|
});
|
|
const shellSessionHandoffCompatibilityReport = createIniPanelShellSessionHandoffCompatibilityReport(
|
|
shellSessionHandoffSummary,
|
|
);
|
|
const shellSessionHandoffDisplayViewModel = createIniPanelShellSessionHandoffDisplayViewModel(
|
|
shellSessionHandoffCompatibilityReport,
|
|
);
|
|
const shellSessionHandoffSnapshot = createIniPanelShellSessionHandoffSnapshot({
|
|
readiness: shellIntegrationReadiness,
|
|
summary: shellSessionHandoffSummary,
|
|
compatibilityReport: shellSessionHandoffCompatibilityReport,
|
|
displayViewModel: shellSessionHandoffDisplayViewModel,
|
|
});
|
|
const shellSessionHandoffRenderState = createIniPanelShellSessionHandoffRenderState(
|
|
shellSessionHandoffSnapshot,
|
|
);
|
|
const shellSessionHandoffActionPlan = createIniPanelShellSessionHandoffActionPlan({
|
|
snapshot: shellSessionHandoffSnapshot,
|
|
renderState: shellSessionHandoffRenderState,
|
|
});
|
|
const shellSessionHandoffChecklist = createIniPanelShellSessionHandoffChecklist({
|
|
actionPlan: shellSessionHandoffActionPlan,
|
|
renderState: shellSessionHandoffRenderState,
|
|
});
|
|
const shellSessionHandoffPackage = createIniPanelShellSessionHandoffPackage({
|
|
shellIntegrationManifest,
|
|
launchApiManifest: shellIntegrationManifest.launchApiManifest,
|
|
controlPageApiManifest: shellIntegrationManifest.controlPageApiManifest,
|
|
snapshot: shellSessionHandoffSnapshot,
|
|
renderState: shellSessionHandoffRenderState,
|
|
actionPlan: shellSessionHandoffActionPlan,
|
|
checklist: shellSessionHandoffChecklist,
|
|
});
|
|
const shellSessionHandoffPackageReport = createIniPanelShellSessionHandoffPackageReport(
|
|
shellSessionHandoffPackage,
|
|
);
|
|
const shellSessionHandoffPackageDisplayViewModel = createIniPanelShellSessionHandoffPackageDisplayViewModel(
|
|
shellSessionHandoffPackageReport,
|
|
);
|
|
const shellSessionHandoffPackageRenderState = createIniPanelShellSessionHandoffPackageRenderState(
|
|
shellSessionHandoffPackageDisplayViewModel,
|
|
);
|
|
const shellSessionHandoffPackageMountState = createIniPanelShellSessionHandoffPackageMountState({
|
|
handoffPackage: shellSessionHandoffPackage,
|
|
packageRenderState: shellSessionHandoffPackageRenderState,
|
|
});
|
|
const shellSessionHandoffPackageMountDisplayViewModel = createIniPanelShellSessionHandoffPackageMountDisplayViewModel(
|
|
shellSessionHandoffPackageMountState,
|
|
);
|
|
const shellSessionHandoffPackageMountRenderState = createIniPanelShellSessionHandoffPackageMountRenderState(
|
|
shellSessionHandoffPackageMountDisplayViewModel,
|
|
);
|
|
const shellSessionHandoffMountDomContract = createIniPanelShellSessionHandoffMountDomContract();
|
|
const shellSessionHandoffWorkflowSummary = createIniPanelShellSessionHandoffWorkflowSummary({
|
|
mountWorkflow: {
|
|
phase: shellSessionHandoffPackageMountRenderState.phase,
|
|
ready: shellSessionHandoffPackageMountRenderState.ready,
|
|
statusLine: shellSessionHandoffPackageMountRenderState.statusLine,
|
|
},
|
|
controlPageMountWorkflow: {
|
|
phase: shellSessionHandoffPackageMountState.phase,
|
|
ready: shellSessionHandoffPackageMountState.ready,
|
|
statusLine: shellSessionHandoffPackageMountState.statusLine,
|
|
},
|
|
readonlyStatusResult: readIniPanelShellSessionHandoffStatusFromControlPage({
|
|
handoffSummary: shellSessionHandoffSummary,
|
|
}),
|
|
});
|
|
const shellSessionHandoffWorkflowDisplayViewModel = createIniPanelShellSessionHandoffWorkflowDisplayViewModel(
|
|
shellSessionHandoffWorkflowSummary,
|
|
);
|
|
const shellSessionHandoffWorkflowRenderState = createIniPanelShellSessionHandoffWorkflowRenderState(
|
|
shellSessionHandoffWorkflowDisplayViewModel,
|
|
);
|
|
const shellSessionHandoffWorkflowDomContract = createIniPanelShellSessionHandoffWorkflowDomContract();
|
|
const shellWorkflowOverviewContract = createIniPanelShellWorkflowOverviewContract();
|
|
return {
|
|
pages: entries.map(({ id, href, title }) => ({
|
|
id,
|
|
href,
|
|
title,
|
|
})),
|
|
launcherLinks: createIniPanelLauncherLinkViewModel(entries),
|
|
shellIntegrationSchema: createIniPanelShellIntegrationSchema(),
|
|
shellIntegrationManifest,
|
|
shellIntegrationReadiness,
|
|
shellIntegrationWorkflowPlan,
|
|
shellSessionHandoffSummarySchema: createIniPanelShellSessionHandoffSummarySchema(),
|
|
shellSessionHandoffSummary,
|
|
shellSessionHandoffCompatibilityReport,
|
|
shellSessionHandoffDisplayViewModel,
|
|
shellSessionHandoffSnapshot,
|
|
shellSessionHandoffRenderState,
|
|
shellSessionHandoffActionPlan,
|
|
shellSessionHandoffChecklist,
|
|
shellSessionHandoffPackage,
|
|
shellSessionHandoffPackageSchema: createIniPanelShellSessionHandoffPackageSchema(),
|
|
shellSessionHandoffPackageReport,
|
|
shellSessionHandoffPackageDisplayViewModel,
|
|
shellSessionHandoffPackageRenderState,
|
|
shellSessionHandoffPackageMountState,
|
|
shellSessionHandoffPackageMountDisplayViewModel,
|
|
shellSessionHandoffPackageMountRenderState,
|
|
shellSessionHandoffMountDomContract,
|
|
shellSessionHandoffWorkflowSummary,
|
|
shellSessionHandoffWorkflowDisplayViewModel,
|
|
shellSessionHandoffWorkflowRenderState,
|
|
shellSessionHandoffWorkflowDomContract,
|
|
shellWorkflowOverviewContract,
|
|
launchApiSchema: createIniPanelLaunchApiSchema(),
|
|
launchApiManifest: createIniPanelLaunchApiManifest(entries),
|
|
isSupportedShellIntegrationManifest: isSupportedIniPanelShellIntegrationManifest,
|
|
createShellIntegrationReadiness: createIniPanelShellIntegrationReadiness,
|
|
createShellIntegrationWorkflowPlan: createIniPanelShellIntegrationWorkflowPlan,
|
|
isSupportedShellSessionHandoffSummary: isSupportedIniPanelShellSessionHandoffSummary,
|
|
createShellSessionHandoffSummarySchema: createIniPanelShellSessionHandoffSummarySchema,
|
|
createShellSessionHandoffSummary: createIniPanelShellSessionHandoffSummary,
|
|
createShellSessionHandoffCompatibilityReport: createIniPanelShellSessionHandoffCompatibilityReport,
|
|
createShellSessionHandoffDisplayViewModel: createIniPanelShellSessionHandoffDisplayViewModel,
|
|
createShellSessionHandoffSnapshot: createIniPanelShellSessionHandoffSnapshot,
|
|
createShellSessionHandoffRenderState: createIniPanelShellSessionHandoffRenderState,
|
|
createShellSessionHandoffActionPlan: createIniPanelShellSessionHandoffActionPlan,
|
|
createShellSessionHandoffChecklist: createIniPanelShellSessionHandoffChecklist,
|
|
createShellSessionHandoffPackage: createIniPanelShellSessionHandoffPackage,
|
|
createShellSessionHandoffPackageSchema: createIniPanelShellSessionHandoffPackageSchema,
|
|
createShellSessionHandoffPackageReport: createIniPanelShellSessionHandoffPackageReport,
|
|
createShellSessionHandoffPackageDisplayViewModel: createIniPanelShellSessionHandoffPackageDisplayViewModel,
|
|
createShellSessionHandoffPackageRenderState: createIniPanelShellSessionHandoffPackageRenderState,
|
|
createShellSessionHandoffPackageMountState: createIniPanelShellSessionHandoffPackageMountState,
|
|
createShellSessionHandoffPackageMountDisplayViewModel: createIniPanelShellSessionHandoffPackageMountDisplayViewModel,
|
|
createShellSessionHandoffPackageMountRenderState: createIniPanelShellSessionHandoffPackageMountRenderState,
|
|
createShellSessionHandoffMountDomContract: createIniPanelShellSessionHandoffMountDomContract,
|
|
createShellSessionHandoffMountDomReadiness: createIniPanelShellSessionHandoffMountDomReadiness,
|
|
renderShellSessionHandoffMountState: renderIniPanelShellSessionHandoffMountState,
|
|
mountShellSessionHandoff: mountIniPanelShellSessionHandoff,
|
|
mountShellSessionHandoffFromControlPage: mountIniPanelShellSessionHandoffFromControlPage,
|
|
readShellSessionHandoffStatusFromControlPage: readIniPanelShellSessionHandoffStatusFromControlPage,
|
|
createShellSessionHandoffWorkflowSummary: createIniPanelShellSessionHandoffWorkflowSummary,
|
|
createShellSessionHandoffWorkflowDisplayViewModel: createIniPanelShellSessionHandoffWorkflowDisplayViewModel,
|
|
createShellSessionHandoffWorkflowRenderState: createIniPanelShellSessionHandoffWorkflowRenderState,
|
|
createShellSessionHandoffWorkflowDomContract: createIniPanelShellSessionHandoffWorkflowDomContract,
|
|
createShellSessionHandoffWorkflowDomReadiness: createIniPanelShellSessionHandoffWorkflowDomReadiness,
|
|
renderShellSessionHandoffWorkflowState: renderIniPanelShellSessionHandoffWorkflowState,
|
|
mountShellSessionHandoffWorkflow: mountIniPanelShellSessionHandoffWorkflow,
|
|
createWorkflowOverviewContract: createIniPanelShellWorkflowOverviewContract,
|
|
createWorkflowOverviewReadiness: createIniPanelShellWorkflowOverviewReadiness,
|
|
mountWorkflowOverviewEmbedding: mountIniPanelShellWorkflowOverviewEmbedding,
|
|
createWorkflowOverviewEmbeddingReport: createIniPanelShellWorkflowOverviewEmbeddingReport,
|
|
createWorkflowOverviewEmbeddingDisplayViewModel: createIniPanelShellWorkflowOverviewEmbeddingDisplayViewModel,
|
|
createWorkflowOverviewEmbeddingRenderState: createIniPanelShellWorkflowOverviewEmbeddingRenderState,
|
|
createWorkflowOverviewEmbeddingDomContract: createIniPanelShellWorkflowOverviewEmbeddingDomContract,
|
|
createWorkflowOverviewEmbeddingDomReadiness: createIniPanelShellWorkflowOverviewEmbeddingDomReadiness,
|
|
renderWorkflowOverviewEmbeddingState: renderIniPanelShellWorkflowOverviewEmbeddingState,
|
|
isSupportedShellSessionHandoffPackage: isSupportedIniPanelShellSessionHandoffPackage,
|
|
controlPage: {
|
|
browserApiSchema: createControlPageBrowserApiSchema(),
|
|
browserApiManifest: createControlPageBrowserApiManifest(),
|
|
browserApiMethods: createControlPageBrowserApiMethods(),
|
|
contract: createIniPanelShellControlPageContract(),
|
|
createController: createMachineSessionControlPageController,
|
|
isSupportedBrowserApiManifest: isSupportedIniPanelControlPageApiManifest,
|
|
loadSessionState: loadMachineSessionForControlPageWorkflow,
|
|
readonlyStatusApiManifest: createMachineSessionReadonlyStatusApiManifest(),
|
|
readStatus: readMachineSessionReadonlyStatus,
|
|
refresh: refreshMachineSessionControlPage,
|
|
renderView: renderMachineSessionControlView,
|
|
},
|
|
};
|
|
}
|