@tutti-os/workspace-app-center 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  workspaceAppManifestSchemaVersion
3
- } from "./chunk-QSAEUGFC.js";
3
+ } from "./chunk-UBERYRMA.js";
4
4
 
5
5
  // src/core/appCenterControllerHelpers.ts
6
6
  function resolveAppRunDurationMs(startedAtUnixMs, now) {
@@ -24,6 +24,7 @@ function mergeWorkspaceAppCatalogFields(currentApp, snapshotApp) {
24
24
  localizations: snapshotApp.localizations,
25
25
  minimizeBehavior: snapshotApp.minimizeBehavior,
26
26
  name: snapshotApp.name,
27
+ references: snapshotApp.references,
27
28
  source: snapshotApp.source,
28
29
  tags: snapshotApp.tags,
29
30
  updateAvailable: snapshotApp.updateAvailable
@@ -35,10 +36,10 @@ function areWorkspaceAppCenterAppsEqual(left, right) {
35
36
  }
36
37
  return left.every((leftApp, index) => {
37
38
  const rightApp = right[index];
38
- return rightApp !== void 0 && leftApp.appId === rightApp.appId && leftApp.availableIconUrl === rightApp.availableIconUrl && leftApp.availableVersion === rightApp.availableVersion && leftApp.createdAtUnixMs === rightApp.createdAtUnixMs && leftApp.description === rightApp.description && leftApp.enabled === rightApp.enabled && leftApp.exportable === rightApp.exportable && leftApp.iconUrl === rightApp.iconUrl && leftApp.installed === rightApp.installed && areWorkspaceAppCenterLocalizationsEqual(
39
+ return rightApp !== void 0 && leftApp.appId === rightApp.appId && leftApp.availableIconUrl === rightApp.availableIconUrl && leftApp.availableVersion === rightApp.availableVersion && leftApp.createdAtUnixMs === rightApp.createdAtUnixMs && leftApp.description === rightApp.description && leftApp.enabled === rightApp.enabled && leftApp.exportable === rightApp.exportable && leftApp.iconUrl === rightApp.iconUrl && leftApp.installed === rightApp.installed && leftApp.installationId === rightApp.installationId && areWorkspaceAppCenterLocalizationsEqual(
39
40
  leftApp.localizations ?? [],
40
41
  rightApp.localizations ?? []
41
- ) && leftApp.minimizeBehavior === rightApp.minimizeBehavior && leftApp.name === rightApp.name && leftApp.runtimeStatus === rightApp.runtimeStatus && leftApp.source === rightApp.source && leftApp.stateRevision === rightApp.stateRevision && areStringArraysEqual(leftApp.tags ?? [], rightApp.tags ?? []) && (leftApp.updateAvailable ?? false) === (rightApp.updateAvailable ?? false) && leftApp.url === rightApp.url && leftApp.version === rightApp.version;
42
+ ) && leftApp.minimizeBehavior === rightApp.minimizeBehavior && leftApp.name === rightApp.name && leftApp.references.searchSupported === rightApp.references.searchSupported && leftApp.runtimeId === rightApp.runtimeId && leftApp.runtimeStatus === rightApp.runtimeStatus && leftApp.source === rightApp.source && leftApp.stateRevision === rightApp.stateRevision && areStringArraysEqual(leftApp.tags ?? [], rightApp.tags ?? []) && (leftApp.updateAvailable ?? false) === (rightApp.updateAvailable ?? false) && leftApp.launchUrl === rightApp.launchUrl && leftApp.version === rightApp.version && leftApp.windowMinHeight === rightApp.windowMinHeight && leftApp.windowMinWidth === rightApp.windowMinWidth;
42
43
  });
43
44
  }
44
45
  function normalizeWorkspaceAppCenterViewState(value) {
@@ -463,7 +464,7 @@ var WorkspaceAppCenterControllerState = class extends WorkspaceAppCenterControll
463
464
  const app = this.store.apps.find(
464
465
  (candidate) => candidate.appId === input.appId
465
466
  );
466
- return app?.installed && app.runtimeStatus === "running" && app.url ? app : null;
467
+ return app?.installed && app.runtimeStatus === "running" && app.launchUrl ? app : null;
467
468
  }
468
469
  markAppInstalling(appId, options = {}) {
469
470
  this.store.apps = this.store.apps.map(
@@ -481,7 +482,7 @@ var WorkspaceAppCenterControllerState = class extends WorkspaceAppCenterControll
481
482
  markEnabledAppsStarting() {
482
483
  let changed = false;
483
484
  this.store.apps = this.store.apps.map((app) => {
484
- if (!app.enabled || !app.installed || app.runtimeStatus === "running" || app.runtimeStatus === "preparing" || app.runtimeStatus === "starting") {
485
+ if (!app.enabled || !app.installed || app.runtimeStatus !== "idle") {
485
486
  return app;
486
487
  }
487
488
  changed = true;
@@ -655,14 +656,18 @@ var WorkspaceAppCenterController = class extends WorkspaceAppCenterControllerSta
655
656
  if (currentLaunchableApp) {
656
657
  return currentLaunchableApp;
657
658
  }
659
+ const previousApps = this.store.apps;
658
660
  this.markAppStarting(input.appId);
659
661
  try {
660
- const snapshot = await this.dependencies.gateway.retryWorkspaceApp(
662
+ const snapshot = await this.dependencies.gateway.launchWorkspaceApp(
661
663
  input.workspaceId,
662
664
  input.appId
663
665
  );
664
666
  this.applySnapshot(input.workspaceId, snapshot);
665
667
  } catch (error) {
668
+ if (this.store.workspaceId === input.workspaceId) {
669
+ this.store.apps = previousApps;
670
+ }
666
671
  this.setOperationError(error, {
667
672
  appId: input.appId,
668
673
  operation: "workspace_app.prepare_launch",
@@ -974,12 +979,31 @@ var WorkspaceAppCenterController = class extends WorkspaceAppCenterControllerSta
974
979
  }
975
980
  }
976
981
  async retryApp(input) {
977
- this.markAppStarting(input.appId);
978
- const snapshot = await this.dependencies.gateway.retryWorkspaceApp(
979
- input.workspaceId,
980
- input.appId
982
+ const app = this.store.apps.find(
983
+ (candidate) => candidate.appId === input.appId
981
984
  );
982
- this.applySnapshot(input.workspaceId, snapshot);
985
+ if (this.store.workspaceId !== input.workspaceId || !app?.installed || app.runtimeStatus !== "failed") {
986
+ return;
987
+ }
988
+ const previousApps = this.store.apps;
989
+ this.markAppStarting(input.appId);
990
+ try {
991
+ const snapshot = await this.dependencies.gateway.retryWorkspaceApp(
992
+ input.workspaceId,
993
+ input.appId
994
+ );
995
+ this.applySnapshot(input.workspaceId, snapshot);
996
+ } catch (error) {
997
+ if (this.store.workspaceId === input.workspaceId) {
998
+ this.store.apps = previousApps;
999
+ }
1000
+ this.setOperationError(error, {
1001
+ appId: input.appId,
1002
+ operation: "workspace_app.retry",
1003
+ uiAction: "retry_app",
1004
+ workspaceId: input.workspaceId
1005
+ });
1006
+ }
983
1007
  }
984
1008
  waitForLaunchableApp(input) {
985
1009
  const current = this.resolveLaunchableApp(input);
@@ -1124,6 +1148,7 @@ function validateWorkspaceAppManifest(value) {
1124
1148
  const runtime = validateRuntime(value.runtime, issues);
1125
1149
  const window = validateWindow(value.window, issues);
1126
1150
  const author = validateAuthor(value.author, issues);
1151
+ const references = validateReferences(value.references, issues);
1127
1152
  const tags = validateTags(value.tags, issues);
1128
1153
  const localizationInfo = validateLocalizationInfo(
1129
1154
  value.localizationInfo,
@@ -1147,6 +1172,7 @@ function validateWorkspaceAppManifest(value) {
1147
1172
  runtime,
1148
1173
  ...window ? { window } : {},
1149
1174
  ...author ? { author } : {},
1175
+ ...references ? { references } : {},
1150
1176
  ...tags ? { tags } : {},
1151
1177
  ...localizationInfo ? { localizationInfo } : {}
1152
1178
  },
@@ -1298,6 +1324,29 @@ function validateAuthor(value, issues) {
1298
1324
  ...url ? { url } : {}
1299
1325
  };
1300
1326
  }
1327
+ function validateReferences(value, issues) {
1328
+ if (value === void 0) {
1329
+ return void 0;
1330
+ }
1331
+ if (!isRecord(value)) {
1332
+ issues.push({
1333
+ code: "manifest.references",
1334
+ message: "references must be an object when provided.",
1335
+ path: "$.references"
1336
+ });
1337
+ return void 0;
1338
+ }
1339
+ const searchEndpoint = readOptionalString(value.searchEndpoint);
1340
+ if (!searchEndpoint || !isRelativeUrlPath(searchEndpoint)) {
1341
+ issues.push({
1342
+ code: "manifest.references",
1343
+ message: "references.searchEndpoint must be a relative URL path without query or hash.",
1344
+ path: "$.references.searchEndpoint"
1345
+ });
1346
+ return void 0;
1347
+ }
1348
+ return { searchEndpoint };
1349
+ }
1301
1350
  function validateTags(value, issues) {
1302
1351
  if (value === void 0) {
1303
1352
  return void 0;
@@ -1402,6 +1451,13 @@ function readOptionalString(value) {
1402
1451
  function isRelativePackagePath(value) {
1403
1452
  return !value.startsWith("/") && !value.split(/[\\/]/u).includes("..");
1404
1453
  }
1454
+ function isRelativeUrlPath(value) {
1455
+ const trimmed = value.trim();
1456
+ if (!trimmed || !trimmed.startsWith("/") || trimmed.startsWith("//") || trimmed.includes("\0") || trimmed.includes("?") || trimmed.includes("#") || trimmed.includes("%")) {
1457
+ return false;
1458
+ }
1459
+ return true;
1460
+ }
1405
1461
  function isRecord(value) {
1406
1462
  return typeof value === "object" && value !== null && !Array.isArray(value);
1407
1463
  }
@@ -1422,12 +1478,18 @@ var statusAliases = /* @__PURE__ */ new Map([
1422
1478
  ["preparing", "preparing"],
1423
1479
  ["ready", "idle"],
1424
1480
  ["running", "running"],
1481
+ ["runner_unavailable", "unavailable"],
1482
+ ["runtime_unavailable", "unavailable"],
1483
+ ["sandbox_unavailable", "unavailable"],
1425
1484
  ["started", "running"],
1426
1485
  ["starting", "starting"],
1486
+ ["stale", "unavailable"],
1427
1487
  ["stopped", "idle"],
1428
1488
  ["stopping", "stopping"],
1429
1489
  ["terminated", "idle"],
1430
- ["terminating", "stopping"]
1490
+ ["terminating", "stopping"],
1491
+ ["unavailable", "unavailable"],
1492
+ ["unreachable", "unavailable"]
1431
1493
  ]);
1432
1494
  function mapWorkspaceAppRuntimeStatus(value) {
1433
1495
  if (typeof value !== "string") {
@@ -1479,6 +1541,12 @@ function resolveWorkspaceAppStatusPresentation(status) {
1479
1541
  pulse: true,
1480
1542
  tone: "amber"
1481
1543
  };
1544
+ case "unavailable":
1545
+ return {
1546
+ labelKey: "status.unavailable",
1547
+ pulse: false,
1548
+ tone: "amber"
1549
+ };
1482
1550
  case "idle":
1483
1551
  return {
1484
1552
  labelKey: "actions.openApp",
@@ -1496,21 +1564,20 @@ function createAppCenterViewModel({
1496
1564
  replaceableIconAppIds = [],
1497
1565
  runtimeStates = []
1498
1566
  }) {
1499
- const runtimeByAppId = new Map(
1500
- runtimeStates.map((state) => [
1501
- state.appId,
1502
- {
1503
- ...state,
1504
- status: mapWorkspaceAppRuntimeStatus(state.status)
1505
- }
1506
- ])
1507
- );
1567
+ const runtimeStateMaps = createRuntimeStateMaps(runtimeStates);
1508
1568
  const appFactoryJobByAppId = createAppFactoryJobByAppId(factoryJobs);
1509
1569
  const replaceableIconAppIdSet = new Set(
1510
1570
  replaceableIconAppIds.map((appId) => appId.trim()).filter(Boolean)
1511
1571
  );
1512
1572
  const appCards = apps.map((app) => {
1513
- const runtime = runtimeByAppId.get(app.manifest.appId);
1573
+ const installationId = normalizeOptionalString(
1574
+ app.install?.installationId
1575
+ );
1576
+ const runtime = findRuntimeStateForApp(
1577
+ runtimeStateMaps,
1578
+ app.manifest.appId,
1579
+ installationId
1580
+ );
1514
1581
  const factoryJob = appFactoryJobByAppId.get(app.manifest.appId);
1515
1582
  const metadata = resolveWorkspaceAppCatalogMetadata({
1516
1583
  catalog: app.catalog,
@@ -1523,9 +1590,15 @@ function createAppCenterViewModel({
1523
1590
  const installed = Boolean(app.install);
1524
1591
  const sourceKind = resolveCatalogSourceKind(app.catalog);
1525
1592
  const localApp = sourceKind === "local";
1593
+ const runtimeId = normalizeOptionalString(runtime?.runtimeId);
1594
+ const launchUrl = normalizeOptionalString(runtime?.launchUrl);
1595
+ const installedVersion = normalizeOptionalString(app.install?.version);
1596
+ const manifestVersion = normalizeOptionalString(app.manifest.version);
1597
+ const displayVersion = installedVersion ?? manifestVersion;
1526
1598
  const comingSoon = isComingSoonApp(metadata.tags) || isComingSoonApp(app.manifest.tags ?? []);
1527
1599
  const busy = isBusyRuntimeStatus(status);
1528
- const canUpdate = !comingSoon && !busy && installed && (app.updateAvailable ?? false);
1600
+ const unavailable = status === "unavailable";
1601
+ const canUpdate = !comingSoon && !busy && !unavailable && installed && (app.updateAvailable ?? false);
1529
1602
  const canOpen = !comingSoon && installed && canOpenInstalledApp(status);
1530
1603
  const canRetry = installed && status === "failed";
1531
1604
  const primaryAction = resolvePrimaryAction({
@@ -1538,10 +1611,13 @@ function createAppCenterViewModel({
1538
1611
  });
1539
1612
  return {
1540
1613
  id: app.manifest.appId,
1614
+ installationId,
1615
+ runtimeId,
1616
+ launchUrl,
1541
1617
  name: metadata.name,
1542
1618
  createdAtUnixMs: app.createdAtUnixMs ?? null,
1543
1619
  ...metadata.description ? { description: metadata.description } : {},
1544
- ...app.manifest.version && !comingSoon ? { version: app.manifest.version } : {},
1620
+ ...displayVersion && !comingSoon ? { version: displayVersion } : {},
1545
1621
  ...app.availableVersion && !comingSoon ? { availableVersion: app.availableVersion } : {},
1546
1622
  ...app.category?.trim() ? { category: app.category.trim() } : {},
1547
1623
  updateAvailable: app.updateAvailable ?? false,
@@ -1559,7 +1635,7 @@ function createAppCenterViewModel({
1559
1635
  canDelete: localApp,
1560
1636
  canReplaceIcon: replaceableIconAppIdSet.has(app.manifest.appId),
1561
1637
  canOpenFolder: installed,
1562
- canOpenPackageFolder: installed && localApp && Boolean(app.manifest.version?.trim()),
1638
+ canOpenPackageFolder: installed && localApp && Boolean(displayVersion),
1563
1639
  canOpenFactorySession: Boolean(factoryAgentSessionId),
1564
1640
  canPublishFactoryUpdate: installed && factoryJob?.status === "ready" && Boolean(factoryJob.publishedVersion?.trim()),
1565
1641
  canUninstall: installed,
@@ -1580,6 +1656,38 @@ function createAppCenterViewModel({
1580
1656
  runningCount: appCards.filter((app) => app.status === "running").length
1581
1657
  };
1582
1658
  }
1659
+ function createRuntimeStateMaps(runtimeStates) {
1660
+ const fallbackByAppId = /* @__PURE__ */ new Map();
1661
+ const byInstallationId = /* @__PURE__ */ new Map();
1662
+ for (const state of runtimeStates) {
1663
+ const runtime = {
1664
+ ...state,
1665
+ status: mapWorkspaceAppRuntimeStatus(state.status)
1666
+ };
1667
+ const installationId = normalizeOptionalString(runtime.installationId);
1668
+ if (installationId) {
1669
+ byInstallationId.set(installationId, runtime);
1670
+ continue;
1671
+ }
1672
+ const appId = normalizeOptionalString(runtime.appId);
1673
+ if (appId) {
1674
+ fallbackByAppId.set(appId, runtime);
1675
+ }
1676
+ }
1677
+ return {
1678
+ fallbackByAppId,
1679
+ byInstallationId
1680
+ };
1681
+ }
1682
+ function findRuntimeStateForApp(maps, appId, installationId) {
1683
+ if (installationId) {
1684
+ const runtime = maps.byInstallationId.get(installationId);
1685
+ if (runtime) {
1686
+ return runtime;
1687
+ }
1688
+ }
1689
+ return maps.fallbackByAppId.get(appId);
1690
+ }
1583
1691
  function resolveCatalogSourceKind(catalog) {
1584
1692
  return catalog?.source?.kind ?? "bundled";
1585
1693
  }
@@ -1622,6 +1730,10 @@ function normalizeLocale(value) {
1622
1730
  const normalized = value?.trim().replace(/_/gu, "-").toLowerCase() ?? "";
1623
1731
  return normalized.length > 0 ? normalized : null;
1624
1732
  }
1733
+ function normalizeOptionalString(value) {
1734
+ const normalized = value?.trim() ?? "";
1735
+ return normalized.length > 0 ? normalized : null;
1736
+ }
1625
1737
  function resolvePrimaryAction(input) {
1626
1738
  if (input.comingSoon) {
1627
1739
  return "none";
@@ -1629,6 +1741,9 @@ function resolvePrimaryAction(input) {
1629
1741
  if (isBusyRuntimeStatus(input.status)) {
1630
1742
  return "none";
1631
1743
  }
1744
+ if (input.status === "unavailable") {
1745
+ return "none";
1746
+ }
1632
1747
  if (!input.installed) {
1633
1748
  return "install";
1634
1749
  }
@@ -1739,4 +1854,4 @@ export {
1739
1854
  resolveWorkspaceAppCatalogMetadata,
1740
1855
  createWorkspaceAppRecord
1741
1856
  };
1742
- //# sourceMappingURL=chunk-INI5PAWK.js.map
1857
+ //# sourceMappingURL=chunk-5SANC3S6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/appCenterControllerHelpers.ts","../src/core/appCenterControllerTypes.ts","../src/core/appCenterControllerBase.ts","../src/core/appCenterControllerState.ts","../src/core/appCenterController.ts","../src/core/appIdentity.ts","../src/core/manifestValidation.ts","../src/core/statusMapping.ts","../src/core/appCenterViewModel.ts"],"sourcesContent":["import type {\n WorkspaceAppCenterApp,\n WorkspaceAppCenterViewState,\n WorkspaceAppFactoryJob\n} from \"../contracts/host.ts\";\n\nexport function resolveAppRunDurationMs(\n startedAtUnixMs: number | null | undefined,\n now: number\n) {\n if (\n typeof startedAtUnixMs !== \"number\" ||\n !Number.isFinite(startedAtUnixMs) ||\n startedAtUnixMs <= 0\n ) {\n return null;\n }\n\n return Math.max(0, now - startedAtUnixMs);\n}\n\nexport function sortWorkspaceAppCenterApps(\n apps: readonly WorkspaceAppCenterApp[]\n): WorkspaceAppCenterApp[] {\n return [...apps].sort((left, right) =>\n left.name.localeCompare(right.name, undefined, { sensitivity: \"base\" })\n );\n}\n\nexport function mergeWorkspaceAppCatalogFields(\n currentApp: WorkspaceAppCenterApp,\n snapshotApp: WorkspaceAppCenterApp\n): WorkspaceAppCenterApp {\n return {\n ...currentApp,\n availableIconUrl: snapshotApp.availableIconUrl,\n availableVersion: snapshotApp.availableVersion,\n description: snapshotApp.description,\n iconUrl: snapshotApp.iconUrl,\n localizations: snapshotApp.localizations,\n minimizeBehavior: snapshotApp.minimizeBehavior,\n name: snapshotApp.name,\n references: snapshotApp.references,\n source: snapshotApp.source,\n tags: snapshotApp.tags,\n updateAvailable: snapshotApp.updateAvailable\n };\n}\n\nexport function areWorkspaceAppCenterAppsEqual(\n left: readonly WorkspaceAppCenterApp[],\n right: readonly WorkspaceAppCenterApp[]\n): boolean {\n if (left.length !== right.length) {\n return false;\n }\n return left.every((leftApp, index) => {\n const rightApp = right[index];\n return (\n rightApp !== undefined &&\n leftApp.appId === rightApp.appId &&\n leftApp.availableIconUrl === rightApp.availableIconUrl &&\n leftApp.availableVersion === rightApp.availableVersion &&\n leftApp.createdAtUnixMs === rightApp.createdAtUnixMs &&\n leftApp.description === rightApp.description &&\n leftApp.enabled === rightApp.enabled &&\n leftApp.exportable === rightApp.exportable &&\n leftApp.iconUrl === rightApp.iconUrl &&\n leftApp.installed === rightApp.installed &&\n leftApp.installationId === rightApp.installationId &&\n areWorkspaceAppCenterLocalizationsEqual(\n leftApp.localizations ?? [],\n rightApp.localizations ?? []\n ) &&\n leftApp.minimizeBehavior === rightApp.minimizeBehavior &&\n leftApp.name === rightApp.name &&\n leftApp.references.searchSupported ===\n rightApp.references.searchSupported &&\n leftApp.runtimeId === rightApp.runtimeId &&\n leftApp.runtimeStatus === rightApp.runtimeStatus &&\n leftApp.source === rightApp.source &&\n leftApp.stateRevision === rightApp.stateRevision &&\n areStringArraysEqual(leftApp.tags ?? [], rightApp.tags ?? []) &&\n (leftApp.updateAvailable ?? false) ===\n (rightApp.updateAvailable ?? false) &&\n leftApp.launchUrl === rightApp.launchUrl &&\n leftApp.version === rightApp.version &&\n leftApp.windowMinHeight === rightApp.windowMinHeight &&\n leftApp.windowMinWidth === rightApp.windowMinWidth\n );\n });\n}\n\nexport function normalizeWorkspaceAppCenterViewState(\n value: Partial<WorkspaceAppCenterViewState> | null | undefined\n): WorkspaceAppCenterViewState {\n return {\n activeAppTab: value?.activeAppTab === \"my\" ? \"my\" : \"recommended\"\n };\n}\n\nexport function areWorkspaceAppCenterViewStatesEqual(\n left: WorkspaceAppCenterViewState,\n right: WorkspaceAppCenterViewState\n): boolean {\n return left.activeAppTab === right.activeAppTab;\n}\n\nfunction areWorkspaceAppCenterLocalizationsEqual(\n left: NonNullable<WorkspaceAppCenterApp[\"localizations\"]>,\n right: NonNullable<WorkspaceAppCenterApp[\"localizations\"]>\n): boolean {\n if (left.length !== right.length) {\n return false;\n }\n return left.every((leftLocalization, index) => {\n const rightLocalization = right[index];\n return (\n rightLocalization !== undefined &&\n leftLocalization.locale === rightLocalization.locale &&\n leftLocalization.name === rightLocalization.name &&\n leftLocalization.description === rightLocalization.description &&\n areStringArraysEqual(leftLocalization.tags, rightLocalization.tags)\n );\n });\n}\n\nfunction areStringArraysEqual(\n left: readonly string[],\n right: readonly string[]\n): boolean {\n if (left.length !== right.length) {\n return false;\n }\n return left.every((value, index) => value === right[index]);\n}\n\nexport function appRuntimeKey(workspaceId: string, appId: string): string {\n return `${workspaceId}\\u0000${appId}`;\n}\n\nexport function factoryJobKey(workspaceId: string, jobId: string): string {\n return `${workspaceId}\\u0000${jobId}`;\n}\n\nexport function removedOrUninstalledAppIds(\n previousApps: readonly WorkspaceAppCenterApp[],\n nextApps: readonly WorkspaceAppCenterApp[]\n): string[] {\n const nextAppsById = new Map(nextApps.map((app) => [app.appId, app]));\n const appIds: string[] = [];\n for (const previousApp of previousApps) {\n if (!previousApp.installed) {\n continue;\n }\n const nextApp = nextAppsById.get(previousApp.appId);\n if (!nextApp?.installed) {\n appIds.push(previousApp.appId);\n }\n }\n return appIds;\n}\n\nexport function sortWorkspaceAppFactoryJobs(\n jobs: readonly WorkspaceAppFactoryJob[]\n): WorkspaceAppFactoryJob[] {\n return [...jobs].sort(\n (left, right) => right.updatedAtUnixMs - left.updatedAtUnixMs\n );\n}\n\nexport function areWorkspaceAppFactoryJobsEqual(\n left: readonly WorkspaceAppFactoryJob[],\n right: readonly WorkspaceAppFactoryJob[]\n): boolean {\n if (left.length !== right.length) {\n return false;\n }\n return left.every((leftJob, index) => {\n const rightJob = right[index];\n return (\n rightJob !== undefined &&\n leftJob.agentSessionId === rightJob.agentSessionId &&\n leftJob.appId === rightJob.appId &&\n leftJob.createdAtUnixMs === rightJob.createdAtUnixMs &&\n leftJob.description === rightJob.description &&\n leftJob.displayName === rightJob.displayName &&\n leftJob.failureReason === rightJob.failureReason &&\n leftJob.jobId === rightJob.jobId &&\n leftJob.model === rightJob.model &&\n leftJob.prompt === rightJob.prompt &&\n leftJob.provider === rightJob.provider &&\n leftJob.publishedVersion === rightJob.publishedVersion &&\n leftJob.reasoningEffort === rightJob.reasoningEffort &&\n leftJob.status === rightJob.status &&\n leftJob.updatedAtUnixMs === rightJob.updatedAtUnixMs &&\n leftJob.workspaceId === rightJob.workspaceId\n );\n });\n}\n\nexport function noop(): void {}\n","import type {\n WorkspaceAppCenterApp,\n WorkspaceAppCenterGateway,\n WorkspaceAppCenterStoreState,\n WorkspaceAppFactoryJob\n} from \"../contracts/host.ts\";\n\nexport const defaultCatalogLoadingRefreshDelayMs = 750;\nexport const defaultAppOpenLaunchWaitTimeoutMs = 35_000;\nexport const defaultInstallRefreshDelayMs = 750;\n\nexport type WorkspaceAppCenterOperation =\n | \"app_center.refresh\"\n | \"app_center.refresh_catalog\"\n | \"app_center.start_workspace_updates\"\n | \"app_factory.prepare_modification\"\n | \"app_factory.publish\"\n | \"workspace_app.delete\"\n | \"workspace_app.export\"\n | \"workspace_app.import\"\n | \"workspace_app.install\"\n | \"workspace_app.prepare_launch\"\n | \"workspace_app.refresh_install_state\"\n | \"workspace_app.refresh_launch_wait_state\"\n | \"workspace_app.replace_icon\"\n | \"workspace_app.retry\"\n | \"workspace_app.start_enabled\"\n | \"workspace_app.update\";\n\nexport type WorkspaceAppCenterUiAction =\n | \"delete_app\"\n | \"export_app\"\n | \"import_app\"\n | \"install_app\"\n | \"open_app\"\n | \"prepare_factory_job_modification\"\n | \"publish_factory_job\"\n | \"refresh_install_state\"\n | \"refresh_launch_wait_state\"\n | \"replace_app_icon\"\n | \"retry_app\"\n | \"update_app\";\n\nexport interface WorkspaceAppCenterOperationDetails {\n appId?: string;\n jobId?: string;\n operation: WorkspaceAppCenterOperation;\n uiAction?: WorkspaceAppCenterUiAction;\n workspaceId: string;\n}\n\nexport interface WorkspaceAppCenterRefreshDiscard {\n currentSequence: number;\n itemCount?: number;\n operation: \"app_center.refresh\" | \"app_center.refresh_catalog\";\n sequence: number;\n snapshotKind: \"apps\" | \"catalog_apps\" | \"factory_jobs\";\n workspaceId: string;\n}\n\nexport interface WorkspaceAppCenterControllerHooks {\n onAppDeleted?: (app: WorkspaceAppCenterApp | null) => void;\n onAppInstallFailed?: (input: {\n app: WorkspaceAppCenterApp | null;\n appId: string;\n failureReason: string | null;\n }) => void;\n onAppInstalled?: (app: WorkspaceAppCenterApp) => void;\n onAppRuntimeFailed?: (input: {\n app: WorkspaceAppCenterApp;\n failureReason: string | null;\n }) => void;\n onAppStopped?: (input: {\n app: WorkspaceAppCenterApp;\n runDurationMs: number | null;\n }) => void;\n onAppUninstalled?: (app: WorkspaceAppCenterApp | null) => void;\n onAppUpdated?: (input: {\n app: WorkspaceAppCenterApp | undefined;\n trigger: \"badge_button\" | \"primary_action\";\n }) => void;\n onCatalogRefreshed?: (input: {\n appCount: number | null;\n errorReason: string | null;\n success: boolean;\n }) => void;\n onCloseWorkspaceAppViews?: (input: {\n appIds: readonly string[];\n workspaceId: string;\n }) => void;\n onFactoryJobCreated?: (job: WorkspaceAppFactoryJob | null) => void;\n onFactorySnapshotApplied?: (input: {\n nextJobs: readonly WorkspaceAppFactoryJob[];\n previousJobs: readonly WorkspaceAppFactoryJob[];\n workspaceId: string;\n }) => void;\n onOperationFailure?: (input: {\n details: WorkspaceAppCenterOperationDetails;\n error: unknown;\n toastMessage: string;\n }) => void;\n onRefreshDiscard?: (input: WorkspaceAppCenterRefreshDiscard) => void;\n}\n\nexport interface WorkspaceAppCenterControllerDependencies {\n appOpenLaunchWaitTimeoutMs?: number;\n catalogLoadingRefreshDelayMs?: number;\n formatError: (\n error: unknown,\n details?: WorkspaceAppCenterOperationDetails\n ) => string;\n gateway: WorkspaceAppCenterGateway;\n getErrorReason?: (error: unknown) => string | null;\n hooks?: WorkspaceAppCenterControllerHooks;\n installRefreshDelayMs?: number;\n now?: () => number;\n store?: WorkspaceAppCenterStoreState;\n}\n\nexport function createWorkspaceAppCenterStoreState(): WorkspaceAppCenterStoreState {\n return {\n apps: [],\n catalogLastError: null,\n catalogStatus: \"disabled\",\n catalogUpdatedAtUnixMs: null,\n error: null,\n factoryJobs: [],\n loadStatus: \"idle\",\n openingFolderAppId: null,\n revision: 0,\n viewStateByWorkspaceId: {},\n workspaceId: null\n };\n}\n","import type {\n WorkspaceAppCenterReadableStoreState,\n WorkspaceAppCenterStoreState,\n WorkspaceAppCenterViewState\n} from \"../contracts/host.ts\";\nimport {\n areWorkspaceAppCenterViewStatesEqual,\n appRuntimeKey,\n normalizeWorkspaceAppCenterViewState\n} from \"./appCenterControllerHelpers.ts\";\nimport {\n createWorkspaceAppCenterStoreState,\n type WorkspaceAppCenterControllerDependencies,\n type WorkspaceAppCenterOperationDetails\n} from \"./appCenterControllerTypes.ts\";\n\nexport abstract class WorkspaceAppCenterControllerBase {\n readonly store: WorkspaceAppCenterStoreState;\n\n protected readonly dependencies: WorkspaceAppCenterControllerDependencies;\n protected readonly listeners = new Set<() => void>();\n protected catalogRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n protected installRefreshTimers = new Map<\n string,\n ReturnType<typeof setTimeout>\n >();\n protected pendingFactoryPublishKeys = new Set<string>();\n protected pendingInstallKeys = new Set<string>();\n protected pendingInstallReportKeys = new Set<string>();\n protected appLoadSequence = 0;\n protected factoryLoadSequence = 0;\n protected pollingWorkspaceId: string | null = null;\n\n constructor(dependencies: WorkspaceAppCenterControllerDependencies) {\n this.dependencies = dependencies;\n this.store = dependencies.store ?? createWorkspaceAppCenterStoreState();\n }\n\n get readableStore(): WorkspaceAppCenterReadableStoreState {\n return this.store;\n }\n\n consumeError(): string | null {\n const error = this.store.error;\n if (error === null) {\n return null;\n }\n this.store.error = null;\n this.bumpRevision();\n return error;\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n beginWorkspacePolling(workspaceId: string): void {\n const normalizedWorkspaceId = workspaceId.trim();\n if (!normalizedWorkspaceId) {\n return;\n }\n if (this.pollingWorkspaceId === normalizedWorkspaceId) {\n return;\n }\n this.clearCatalogRefreshTimer();\n this.clearInstallRefreshTimers();\n this.pollingWorkspaceId = normalizedWorkspaceId;\n }\n\n endWorkspacePolling(workspaceId: string): void {\n if (this.pollingWorkspaceId !== workspaceId.trim()) {\n return;\n }\n this.pollingWorkspaceId = null;\n this.clearCatalogRefreshTimer();\n this.clearInstallRefreshTimers();\n }\n\n getViewState(\n workspaceId: string,\n restoredState?: WorkspaceAppCenterViewState | null\n ): WorkspaceAppCenterViewState {\n const normalizedWorkspaceId = workspaceId.trim();\n if (!normalizedWorkspaceId) {\n return normalizeWorkspaceAppCenterViewState(restoredState);\n }\n const existing = this.store.viewStateByWorkspaceId[normalizedWorkspaceId];\n if (existing) {\n return existing;\n }\n const nextState = normalizeWorkspaceAppCenterViewState(restoredState);\n this.store.viewStateByWorkspaceId = {\n ...this.store.viewStateByWorkspaceId,\n [normalizedWorkspaceId]: nextState\n };\n return nextState;\n }\n\n setViewState(input: {\n state: Partial<WorkspaceAppCenterViewState>;\n workspaceId: string;\n }): void {\n const normalizedWorkspaceId = input.workspaceId.trim();\n if (!normalizedWorkspaceId) {\n return;\n }\n const previous = this.getViewState(normalizedWorkspaceId);\n const nextState = normalizeWorkspaceAppCenterViewState({\n ...previous,\n ...input.state\n });\n if (areWorkspaceAppCenterViewStatesEqual(previous, nextState)) {\n return;\n }\n this.store.viewStateByWorkspaceId = {\n ...this.store.viewStateByWorkspaceId,\n [normalizedWorkspaceId]: nextState\n };\n this.bumpRevision();\n }\n\n setOperationError(\n error: unknown,\n details: WorkspaceAppCenterOperationDetails\n ): void {\n const message = this.dependencies.formatError(error, details);\n this.recordOperationFailure(error, message, details);\n this.store.error = message;\n this.bumpRevision();\n }\n\n setUnavailableError(\n error: unknown,\n details: WorkspaceAppCenterOperationDetails\n ): void {\n const message = this.dependencies.formatError(error, details);\n this.recordOperationFailure(error, message, details);\n this.store.error = message;\n this.store.loadStatus = \"unavailable\";\n this.bumpRevision();\n }\n\n protected clearCatalogRefreshTimer(): void {\n if (!this.catalogRefreshTimer) {\n return;\n }\n clearTimeout(this.catalogRefreshTimer);\n this.catalogRefreshTimer = null;\n }\n\n protected clearInstallRefreshTimer(workspaceId: string, appId: string): void {\n const key = appRuntimeKey(workspaceId, appId);\n const timer = this.installRefreshTimers.get(key);\n if (!timer) {\n return;\n }\n clearTimeout(timer);\n this.installRefreshTimers.delete(key);\n }\n\n protected clearInstallRefreshTimers(): void {\n for (const timer of this.installRefreshTimers.values()) {\n clearTimeout(timer);\n }\n this.installRefreshTimers.clear();\n this.pendingInstallKeys.clear();\n this.pendingInstallReportKeys.clear();\n }\n\n protected recordOperationFailure(\n error: unknown,\n toastMessage: string,\n details: WorkspaceAppCenterOperationDetails\n ): void {\n this.dependencies.hooks?.onOperationFailure?.({\n details,\n error,\n toastMessage\n });\n }\n\n protected bumpRevision(): void {\n this.store.revision += 1;\n for (const listener of this.listeners) {\n listener();\n }\n }\n\n protected closeWorkspaceAppViews(\n workspaceId: string,\n appIds: readonly string[]\n ): void {\n if (appIds.length === 0) {\n return;\n }\n this.dependencies.hooks?.onCloseWorkspaceAppViews?.({\n appIds,\n workspaceId\n });\n }\n\n protected getErrorReason(error: unknown): string | null {\n return this.dependencies.getErrorReason?.(error) ?? null;\n }\n}\n","import type {\n WorkspaceAppCenterApp,\n WorkspaceAppCenterSnapshot,\n WorkspaceAppFactoryJob,\n WorkspaceAppFactorySnapshot\n} from \"../contracts/host.ts\";\nimport { WorkspaceAppCenterControllerBase } from \"./appCenterControllerBase.ts\";\nimport {\n areWorkspaceAppCenterAppsEqual,\n areWorkspaceAppFactoryJobsEqual,\n appRuntimeKey,\n mergeWorkspaceAppCatalogFields,\n removedOrUninstalledAppIds,\n resolveAppRunDurationMs,\n sortWorkspaceAppCenterApps,\n sortWorkspaceAppFactoryJobs\n} from \"./appCenterControllerHelpers.ts\";\nimport {\n defaultCatalogLoadingRefreshDelayMs,\n defaultInstallRefreshDelayMs\n} from \"./appCenterControllerTypes.ts\";\n\nexport abstract class WorkspaceAppCenterControllerState extends WorkspaceAppCenterControllerBase {\n abstract refresh(workspaceId: string): Promise<void>;\n\n applySnapshot(\n workspaceId: string,\n snapshot: WorkspaceAppCenterSnapshot\n ): void {\n const nextApps = sortWorkspaceAppCenterApps(\n this.mergeSnapshotAppsByStateRevision(\n workspaceId,\n this.withPendingInstallState(workspaceId, snapshot.apps)\n )\n );\n for (const app of nextApps) {\n this.settlePendingInstallReport({\n app,\n failureReason: app.failureReason ?? app.lastError ?? null,\n workspaceId\n });\n }\n const appIdsToClose =\n this.store.workspaceId === workspaceId\n ? removedOrUninstalledAppIds(this.store.apps, nextApps)\n : [];\n this.scheduleCatalogLoadingRefresh(workspaceId, snapshot);\n const changed =\n this.store.workspaceId !== workspaceId ||\n this.store.catalogLastError !== (snapshot.catalogLastError ?? null) ||\n this.store.catalogStatus !== snapshot.catalogStatus ||\n this.store.catalogUpdatedAtUnixMs !==\n (snapshot.catalogUpdatedAtUnixMs ?? null) ||\n this.store.error !== null ||\n this.store.loadStatus !== \"ready\" ||\n !areWorkspaceAppCenterAppsEqual(this.store.apps, nextApps);\n if (!changed) {\n return;\n }\n this.store.apps = nextApps;\n this.store.catalogLastError = snapshot.catalogLastError ?? null;\n this.store.catalogStatus = snapshot.catalogStatus;\n this.store.catalogUpdatedAtUnixMs = snapshot.catalogUpdatedAtUnixMs ?? null;\n this.store.error = null;\n this.store.loadStatus = \"ready\";\n this.store.workspaceId = workspaceId;\n this.bumpRevision();\n this.closeWorkspaceAppViews(workspaceId, appIdsToClose);\n }\n\n applyFactorySnapshot(\n workspaceId: string,\n snapshot: WorkspaceAppFactorySnapshot\n ): void {\n if (this.store.workspaceId !== workspaceId) {\n this.store.workspaceId = workspaceId;\n }\n const nextJobs = sortWorkspaceAppFactoryJobs(snapshot.jobs);\n if (areWorkspaceAppFactoryJobsEqual(this.store.factoryJobs, nextJobs)) {\n return;\n }\n const previousJobs = this.store.factoryJobs;\n this.store.factoryJobs = nextJobs;\n this.dependencies.hooks?.onFactorySnapshotApplied?.({\n nextJobs,\n previousJobs,\n workspaceId\n });\n this.bumpRevision();\n }\n\n applyAppUpdate(input: {\n app: WorkspaceAppCenterApp;\n failureReason?: string | null;\n startedAtUnixMs?: number | null;\n workspaceId: string;\n }): void {\n if (this.store.workspaceId !== input.workspaceId) {\n return;\n }\n const currentApp = this.store.apps.find(\n (candidate) => candidate.appId === input.app.appId\n );\n if (!currentApp) {\n return;\n }\n const acceptedRuntimeTransition =\n input.app.stateRevision > currentApp.stateRevision;\n if (\n acceptedRuntimeTransition &&\n input.app.runtimeStatus === \"failed\" &&\n currentApp.runtimeStatus !== \"failed\"\n ) {\n this.dependencies.hooks?.onAppRuntimeFailed?.({\n app: input.app,\n failureReason: input.failureReason ?? null\n });\n }\n if (\n acceptedRuntimeTransition &&\n currentApp.runtimeStatus === \"running\" &&\n input.app.runtimeStatus !== \"running\"\n ) {\n this.dependencies.hooks?.onAppStopped?.({\n app: currentApp,\n runDurationMs: resolveAppRunDurationMs(\n input.startedAtUnixMs,\n this.dependencies.now?.() ?? Date.now()\n )\n });\n }\n this.applyAppSnapshot(input.workspaceId, input.app, {\n installFailureReason: input.failureReason ?? null\n });\n }\n\n applyAppSnapshot(\n workspaceId: string,\n nextApp: WorkspaceAppCenterApp,\n options: { installFailureReason?: string | null } = {}\n ): void {\n if (this.store.workspaceId !== workspaceId) {\n return;\n }\n const currentApp = this.store.apps.find(\n (candidate) => candidate.appId === nextApp.appId\n );\n if (currentApp && nextApp.stateRevision <= currentApp.stateRevision) {\n this.settlePendingInstallReport({\n app: currentApp,\n failureReason:\n options.installFailureReason ??\n currentApp.failureReason ??\n currentApp.lastError ??\n null,\n workspaceId\n });\n return;\n }\n const appIdsToClose =\n currentApp?.installed === true && !nextApp.installed\n ? [nextApp.appId]\n : [];\n\n const nextApps = sortWorkspaceAppCenterApps([\n ...this.store.apps.filter(\n (candidate) => candidate.appId !== nextApp.appId\n ),\n nextApp\n ]);\n if (areWorkspaceAppCenterAppsEqual(this.store.apps, nextApps)) {\n return;\n }\n this.store.apps = nextApps;\n this.store.error = null;\n this.store.loadStatus = \"ready\";\n this.bumpRevision();\n this.settlePendingInstallReport({\n app: nextApp,\n failureReason:\n options.installFailureReason ??\n nextApp.failureReason ??\n nextApp.lastError ??\n null,\n workspaceId\n });\n this.closeWorkspaceAppViews(workspaceId, appIdsToClose);\n }\n\n applyFactoryJobUpdate(\n workspaceId: string,\n job: WorkspaceAppFactoryJob\n ): void {\n if (this.store.workspaceId !== workspaceId) {\n return;\n }\n const currentJob = this.store.factoryJobs.find(\n (candidate) => candidate.jobId === job.jobId\n );\n if (currentJob && job.updatedAtUnixMs < currentJob.updatedAtUnixMs) {\n return;\n }\n const nextJobs = sortWorkspaceAppFactoryJobs([\n ...this.store.factoryJobs.filter(\n (candidate) => candidate.jobId !== job.jobId\n ),\n job\n ]);\n if (areWorkspaceAppFactoryJobsEqual(this.store.factoryJobs, nextJobs)) {\n return;\n }\n this.store.factoryJobs = nextJobs;\n this.bumpRevision();\n }\n\n protected scheduleInstallRefresh(workspaceId: string, appId: string): void {\n const key = appRuntimeKey(workspaceId, appId);\n if (this.installRefreshTimers.has(key)) {\n return;\n }\n const timer = setTimeout(() => {\n this.installRefreshTimers.delete(key);\n if (!this.pendingInstallKeys.has(key)) {\n return;\n }\n void this.refreshInstallState(workspaceId, appId);\n }, this.dependencies.installRefreshDelayMs ?? defaultInstallRefreshDelayMs);\n this.installRefreshTimers.set(key, timer);\n }\n\n protected markAppStarting(appId: string): void {\n this.store.apps = this.store.apps.map((app) =>\n app.appId === appId\n ? {\n ...app,\n enabled: true,\n installed: true,\n runtimeStatus: \"preparing\"\n }\n : app\n );\n this.bumpRevision();\n }\n\n protected markLaunchWaitTimedOut(input: {\n appId: string;\n workspaceId: string;\n }): void {\n if (this.store.workspaceId !== input.workspaceId) {\n return;\n }\n let changed = false;\n this.store.apps = this.store.apps.map((app) => {\n if (\n app.appId !== input.appId ||\n !app.installed ||\n (app.runtimeStatus !== \"preparing\" && app.runtimeStatus !== \"starting\")\n ) {\n return app;\n }\n changed = true;\n return {\n ...app,\n runtimeStatus: \"failed\"\n };\n });\n if (changed) {\n this.bumpRevision();\n }\n }\n\n protected resolveLaunchableApp(input: {\n appId: string;\n workspaceId: string;\n }): WorkspaceAppCenterApp | null {\n if (this.store.workspaceId !== input.workspaceId) {\n return null;\n }\n const app = this.store.apps.find(\n (candidate) => candidate.appId === input.appId\n );\n return app?.installed && app.runtimeStatus === \"running\" && app.launchUrl\n ? app\n : null;\n }\n\n protected markAppInstalling(\n appId: string,\n options: { preserveInstalled?: boolean } = {}\n ): void {\n this.store.apps = this.store.apps.map((app) =>\n app.appId === appId\n ? {\n ...app,\n availableVersion: null,\n enabled: true,\n installed:\n options.preserveInstalled === true ? app.installed : false,\n runtimeStatus: \"installing\",\n updateAvailable: false\n }\n : app\n );\n this.bumpRevision();\n }\n\n protected markEnabledAppsStarting(): void {\n let changed = false;\n this.store.apps = this.store.apps.map((app) => {\n if (!app.enabled || !app.installed || app.runtimeStatus !== \"idle\") {\n return app;\n }\n changed = true;\n return {\n ...app,\n runtimeStatus: \"preparing\"\n };\n });\n if (changed) {\n this.bumpRevision();\n }\n }\n\n protected isPendingInstallSettled(\n installKey: string,\n app: WorkspaceAppCenterApp\n ): boolean {\n if (app.runtimeStatus === \"failed\") {\n return true;\n }\n if (this.pendingInstallReportKeys.has(installKey)) {\n return app.installed;\n }\n return app.installed && !app.updateAvailable && !app.availableVersion;\n }\n\n private mergeSnapshotAppsByStateRevision(\n workspaceId: string,\n snapshotApps: readonly WorkspaceAppCenterApp[]\n ): WorkspaceAppCenterApp[] {\n if (this.store.workspaceId !== workspaceId) {\n return [...snapshotApps];\n }\n const currentAppsById = new Map(\n this.store.apps.map((app) => [app.appId, app])\n );\n return snapshotApps.map((snapshotApp) => {\n const currentApp = currentAppsById.get(snapshotApp.appId);\n if (!currentApp || currentApp.stateRevision < snapshotApp.stateRevision) {\n return snapshotApp;\n }\n const installKey = appRuntimeKey(workspaceId, snapshotApp.appId);\n if (this.pendingInstallKeys.has(installKey)) {\n const pendingSettled = this.isPendingInstallSettled(\n installKey,\n snapshotApp\n );\n if (\n pendingSettled &&\n currentApp.stateRevision <= snapshotApp.stateRevision\n ) {\n return snapshotApp;\n }\n }\n return mergeWorkspaceAppCatalogFields(currentApp, snapshotApp);\n });\n }\n\n private scheduleCatalogLoadingRefresh(\n workspaceId: string,\n snapshot: WorkspaceAppCenterSnapshot\n ): void {\n if (snapshot.catalogStatus !== \"loading\") {\n this.clearCatalogRefreshTimer();\n return;\n }\n if (\n this.pollingWorkspaceId !== workspaceId ||\n this.catalogRefreshTimer !== null\n ) {\n return;\n }\n this.catalogRefreshTimer = setTimeout(() => {\n this.catalogRefreshTimer = null;\n if (this.pollingWorkspaceId !== workspaceId) {\n return;\n }\n void this.refresh(workspaceId);\n }, this.dependencies.catalogLoadingRefreshDelayMs ?? defaultCatalogLoadingRefreshDelayMs);\n }\n\n private withPendingInstallState(\n workspaceId: string,\n apps: readonly WorkspaceAppCenterApp[]\n ): WorkspaceAppCenterApp[] {\n return apps.map((app) => {\n const installKey = appRuntimeKey(workspaceId, app.appId);\n if (!this.pendingInstallKeys.has(installKey)) {\n return app;\n }\n if (this.isPendingInstallSettled(installKey, app)) {\n return app;\n }\n return {\n ...app,\n enabled: true,\n installed: this.pendingInstallReportKeys.has(installKey)\n ? false\n : app.installed,\n runtimeStatus: \"installing\"\n };\n });\n }\n\n private async refreshInstallState(\n workspaceId: string,\n appId: string\n ): Promise<void> {\n try {\n const snapshot =\n await this.dependencies.gateway.listWorkspaceApps(workspaceId);\n this.applySnapshot(workspaceId, snapshot);\n } catch (error) {\n this.setOperationError(error, {\n appId,\n operation: \"workspace_app.refresh_install_state\",\n uiAction: \"refresh_install_state\",\n workspaceId\n });\n }\n if (this.pendingInstallKeys.has(appRuntimeKey(workspaceId, appId))) {\n this.scheduleInstallRefresh(workspaceId, appId);\n }\n }\n\n private settlePendingInstallReport(input: {\n app: WorkspaceAppCenterApp;\n failureReason: string | null;\n workspaceId: string;\n }): void {\n const installKey = appRuntimeKey(input.workspaceId, input.app.appId);\n if (!this.pendingInstallKeys.has(installKey)) {\n return;\n }\n if (!this.isPendingInstallSettled(installKey, input.app)) {\n return;\n }\n\n this.pendingInstallKeys.delete(installKey);\n this.clearInstallRefreshTimer(input.workspaceId, input.app.appId);\n if (!this.pendingInstallReportKeys.delete(installKey)) {\n return;\n }\n if (input.app.installed) {\n this.dependencies.hooks?.onAppInstalled?.(input.app);\n return;\n }\n this.dependencies.hooks?.onAppInstallFailed?.({\n app: input.app,\n appId: input.app.appId,\n failureReason:\n input.failureReason ??\n input.app.failureReason ??\n input.app.lastError ??\n null\n });\n }\n}\n","import type {\n WorkspaceAppCenterApp,\n WorkspaceAppCenterGateway,\n WorkspaceAppFactoryJob\n} from \"../contracts/host.ts\";\nimport {\n appRuntimeKey,\n factoryJobKey,\n noop\n} from \"./appCenterControllerHelpers.ts\";\nimport { WorkspaceAppCenterControllerState } from \"./appCenterControllerState.ts\";\nimport {\n defaultAppOpenLaunchWaitTimeoutMs,\n type WorkspaceAppCenterControllerDependencies\n} from \"./appCenterControllerTypes.ts\";\n\nexport {\n createWorkspaceAppCenterStoreState,\n type WorkspaceAppCenterControllerDependencies,\n type WorkspaceAppCenterControllerHooks,\n type WorkspaceAppCenterOperation,\n type WorkspaceAppCenterOperationDetails,\n type WorkspaceAppCenterRefreshDiscard,\n type WorkspaceAppCenterUiAction\n} from \"./appCenterControllerTypes.ts\";\n\nexport function createWorkspaceAppCenterController(\n dependencies: WorkspaceAppCenterControllerDependencies\n): WorkspaceAppCenterController {\n return new WorkspaceAppCenterController(dependencies);\n}\n\nexport class WorkspaceAppCenterController extends WorkspaceAppCenterControllerState {\n async installApp(input: {\n appId: string;\n workspaceId: string;\n }): Promise<void> {\n const installKey = appRuntimeKey(input.workspaceId, input.appId);\n if (this.pendingInstallKeys.has(installKey)) {\n return;\n }\n const previousApps = this.store.apps;\n const appBeforeInstall =\n previousApps.find((app) => app.appId === input.appId) ?? null;\n this.pendingInstallKeys.add(installKey);\n this.pendingInstallReportKeys.add(installKey);\n this.markAppInstalling(input.appId);\n try {\n const snapshot = await this.dependencies.gateway.installWorkspaceApp(\n input.workspaceId,\n input.appId\n );\n this.applySnapshot(input.workspaceId, snapshot);\n if (this.pendingInstallKeys.has(installKey)) {\n this.scheduleInstallRefresh(input.workspaceId, input.appId);\n }\n } catch (error) {\n this.pendingInstallKeys.delete(installKey);\n this.pendingInstallReportKeys.delete(installKey);\n this.clearInstallRefreshTimer(input.workspaceId, input.appId);\n this.store.apps = previousApps;\n this.dependencies.hooks?.onAppInstallFailed?.({\n app: appBeforeInstall,\n appId: input.appId,\n failureReason: this.getErrorReason(error)\n });\n this.setOperationError(error, {\n appId: input.appId,\n operation: \"workspace_app.install\",\n uiAction: \"install_app\",\n workspaceId: input.workspaceId\n });\n }\n }\n\n async prepareAppLaunch(input: {\n appId: string;\n workspaceId: string;\n }): Promise<WorkspaceAppCenterApp | null> {\n const app = this.store.apps.find(\n (candidate) => candidate.appId === input.appId\n );\n if (this.store.workspaceId !== input.workspaceId || !app?.installed) {\n return null;\n }\n const currentLaunchableApp = this.resolveLaunchableApp(input);\n if (currentLaunchableApp) {\n return currentLaunchableApp;\n }\n const previousApps = this.store.apps;\n this.markAppStarting(input.appId);\n try {\n const snapshot = await this.dependencies.gateway.launchWorkspaceApp(\n input.workspaceId,\n input.appId\n );\n this.applySnapshot(input.workspaceId, snapshot);\n } catch (error) {\n if (this.store.workspaceId === input.workspaceId) {\n this.store.apps = previousApps;\n }\n this.setOperationError(error, {\n appId: input.appId,\n operation: \"workspace_app.prepare_launch\",\n uiAction: \"open_app\",\n workspaceId: input.workspaceId\n });\n return null;\n }\n\n return await this.waitForLaunchableApp(input);\n }\n\n async createFactoryJob(input: {\n displayName: string;\n model?: string;\n permissionModeId?: string;\n provider?: string;\n prompt: string;\n reasoningEffort?: string;\n workspaceId: string;\n }): Promise<void> {\n const previousJobIds = new Set(\n this.store.factoryJobs.map((job) => job.jobId)\n );\n const snapshot =\n await this.dependencies.gateway.createWorkspaceAppFactoryJob(\n input.workspaceId,\n {\n displayName: input.displayName,\n ...(input.model?.trim() ? { model: input.model.trim() } : {}),\n ...(input.permissionModeId?.trim()\n ? { permissionModeId: input.permissionModeId.trim() }\n : {}),\n ...(input.provider?.trim()\n ? { provider: input.provider.trim() }\n : {}),\n prompt: input.prompt,\n ...(input.reasoningEffort?.trim()\n ? { reasoningEffort: input.reasoningEffort.trim() }\n : {})\n }\n );\n this.applyFactorySnapshot(input.workspaceId, snapshot);\n this.dependencies.hooks?.onFactoryJobCreated?.(\n snapshot.jobs.find((job) => !previousJobIds.has(job.jobId)) ?? null\n );\n }\n\n async cancelFactoryJob(input: {\n jobId: string;\n workspaceId: string;\n }): Promise<void> {\n const snapshot =\n await this.dependencies.gateway.cancelWorkspaceAppFactoryJob(\n input.workspaceId,\n input.jobId\n );\n this.applyFactorySnapshot(input.workspaceId, snapshot);\n }\n\n async deleteFactoryJob(input: {\n jobId: string;\n workspaceId: string;\n }): Promise<void> {\n const snapshot =\n await this.dependencies.gateway.deleteWorkspaceAppFactoryJob(\n input.workspaceId,\n input.jobId\n );\n this.applyFactorySnapshot(input.workspaceId, snapshot);\n }\n\n async deleteApp(input: {\n appId: string;\n workspaceId: string;\n }): Promise<void> {\n const app = this.store.apps.find(\n (candidate) => candidate.appId === input.appId\n );\n try {\n const snapshot = await this.dependencies.gateway.deleteWorkspaceApp(\n input.workspaceId,\n input.appId\n );\n this.pendingInstallKeys.delete(\n appRuntimeKey(input.workspaceId, input.appId)\n );\n this.pendingInstallReportKeys.delete(\n appRuntimeKey(input.workspaceId, input.appId)\n );\n this.clearInstallRefreshTimer(input.workspaceId, input.appId);\n this.applySnapshot(input.workspaceId, snapshot);\n this.dependencies.hooks?.onAppDeleted?.(app ?? null);\n } catch (error) {\n this.setOperationError(error, {\n appId: input.appId,\n operation: \"workspace_app.delete\",\n uiAction: \"delete_app\",\n workspaceId: input.workspaceId\n });\n }\n }\n\n async retryFactoryValidation(input: {\n jobId: string;\n workspaceId: string;\n }): Promise<void> {\n const snapshot =\n await this.dependencies.gateway.retryWorkspaceAppFactoryJobValidation(\n input.workspaceId,\n input.jobId\n );\n this.applyFactorySnapshot(input.workspaceId, snapshot);\n }\n\n async fixFactoryJob(input: {\n jobId: string;\n prompt: string;\n workspaceId: string;\n }): Promise<void> {\n const snapshot = await this.dependencies.gateway.fixWorkspaceAppFactoryJob(\n input.workspaceId,\n input.jobId,\n { prompt: input.prompt }\n );\n this.applyFactorySnapshot(input.workspaceId, snapshot);\n }\n\n async prepareFactoryJobModification(input: {\n jobId: string;\n workspaceId: string;\n }): Promise<WorkspaceAppFactoryJob | null> {\n try {\n const snapshot =\n await this.dependencies.gateway.prepareWorkspaceAppFactoryJobModification(\n input.workspaceId,\n input.jobId\n );\n this.applyFactorySnapshot(input.workspaceId, snapshot);\n return (\n snapshot.jobs.find((candidate) => candidate.jobId === input.jobId) ??\n null\n );\n } catch (error) {\n this.setOperationError(error, {\n jobId: input.jobId,\n operation: \"app_factory.prepare_modification\",\n uiAction: \"prepare_factory_job_modification\",\n workspaceId: input.workspaceId\n });\n return null;\n }\n }\n\n async publishFactoryJob(input: {\n jobId: string;\n workspaceId: string;\n }): Promise<WorkspaceAppFactoryJob | null> {\n const publishKey = factoryJobKey(input.workspaceId, input.jobId);\n if (this.pendingFactoryPublishKeys.has(publishKey)) {\n return null;\n }\n this.pendingFactoryPublishKeys.add(publishKey);\n let result: Awaited<\n ReturnType<WorkspaceAppCenterGateway[\"publishWorkspaceAppFactoryJob\"]>\n >;\n try {\n result = await this.dependencies.gateway.publishWorkspaceAppFactoryJob(\n input.workspaceId,\n input.jobId\n );\n } catch (error) {\n if (this.pendingFactoryPublishKeys.delete(publishKey)) {\n this.setOperationError(error, {\n jobId: input.jobId,\n operation: \"app_factory.publish\",\n uiAction: \"publish_factory_job\",\n workspaceId: input.workspaceId\n });\n }\n return null;\n }\n this.pendingFactoryPublishKeys.delete(publishKey);\n this.applyFactorySnapshot(input.workspaceId, result.factorySnapshot);\n this.applySnapshot(input.workspaceId, result.appSnapshot);\n return (\n result.factorySnapshot.jobs.find(\n (candidate) => candidate.jobId === input.jobId\n ) ?? null\n );\n }\n\n async refresh(workspaceId: string): Promise<void> {\n const normalizedWorkspaceId = workspaceId.trim();\n if (!normalizedWorkspaceId) {\n return;\n }\n\n const appSequence = ++this.appLoadSequence;\n const factorySequence = ++this.factoryLoadSequence;\n const wasIdle = this.store.loadStatus === \"idle\";\n this.store.workspaceId = normalizedWorkspaceId;\n this.store.error = null;\n if (wasIdle) {\n this.store.loadStatus = \"loading\";\n }\n\n try {\n const [appResult, factoryResult] = await Promise.allSettled([\n this.dependencies.gateway.listWorkspaceApps(normalizedWorkspaceId),\n this.dependencies.gateway.listWorkspaceAppFactoryJobs(\n normalizedWorkspaceId\n )\n ]);\n\n if (\n appResult.status === \"fulfilled\" &&\n appSequence !== this.appLoadSequence\n ) {\n this.dependencies.hooks?.onRefreshDiscard?.({\n currentSequence: this.appLoadSequence,\n itemCount: appResult.value.apps.length,\n operation: \"app_center.refresh\",\n sequence: appSequence,\n snapshotKind: \"apps\",\n workspaceId: normalizedWorkspaceId\n });\n }\n if (\n factoryResult.status === \"fulfilled\" &&\n factorySequence !== this.factoryLoadSequence\n ) {\n this.dependencies.hooks?.onRefreshDiscard?.({\n currentSequence: this.factoryLoadSequence,\n itemCount: factoryResult.value.jobs.length,\n operation: \"app_center.refresh\",\n sequence: factorySequence,\n snapshotKind: \"factory_jobs\",\n workspaceId: normalizedWorkspaceId\n });\n }\n\n let error: unknown = null;\n if (\n appResult.status === \"rejected\" &&\n appSequence === this.appLoadSequence\n ) {\n error = appResult.reason;\n } else if (\n factoryResult.status === \"rejected\" &&\n factorySequence === this.factoryLoadSequence\n ) {\n error = factoryResult.reason;\n }\n if (error) {\n this.setUnavailableError(error, {\n operation: \"app_center.refresh\",\n workspaceId: normalizedWorkspaceId\n });\n return;\n }\n\n if (\n appResult.status === \"fulfilled\" &&\n appSequence === this.appLoadSequence\n ) {\n this.applySnapshot(normalizedWorkspaceId, appResult.value);\n }\n if (\n factoryResult.status === \"fulfilled\" &&\n factorySequence === this.factoryLoadSequence\n ) {\n this.applyFactorySnapshot(normalizedWorkspaceId, factoryResult.value);\n }\n } catch (error) {\n this.setUnavailableError(error, {\n operation: \"app_center.refresh\",\n workspaceId: normalizedWorkspaceId\n });\n }\n }\n\n async refreshCatalog(workspaceId: string): Promise<void> {\n const normalizedWorkspaceId = workspaceId.trim();\n if (!normalizedWorkspaceId) {\n return;\n }\n\n const sequence = ++this.appLoadSequence;\n this.store.workspaceId = normalizedWorkspaceId;\n this.store.error = null;\n try {\n const snapshot =\n await this.dependencies.gateway.refreshWorkspaceAppCatalog(\n normalizedWorkspaceId\n );\n if (sequence !== this.appLoadSequence) {\n this.dependencies.hooks?.onRefreshDiscard?.({\n currentSequence: this.appLoadSequence,\n itemCount: snapshot.apps.length,\n operation: \"app_center.refresh_catalog\",\n sequence,\n snapshotKind: \"catalog_apps\",\n workspaceId: normalizedWorkspaceId\n });\n return;\n }\n this.applySnapshot(normalizedWorkspaceId, snapshot);\n this.dependencies.hooks?.onCatalogRefreshed?.({\n appCount: snapshot.apps.length,\n errorReason: null,\n success: true\n });\n } catch (error) {\n if (sequence !== this.appLoadSequence) {\n this.dependencies.hooks?.onRefreshDiscard?.({\n currentSequence: this.appLoadSequence,\n operation: \"app_center.refresh_catalog\",\n sequence,\n snapshotKind: \"catalog_apps\",\n workspaceId: normalizedWorkspaceId\n });\n return;\n }\n this.setUnavailableError(error, {\n operation: \"app_center.refresh_catalog\",\n workspaceId: normalizedWorkspaceId\n });\n this.dependencies.hooks?.onCatalogRefreshed?.({\n appCount: null,\n errorReason: this.getErrorReason(error),\n success: false\n });\n }\n }\n\n async startEnabledApps(workspaceId: string): Promise<void> {\n this.markEnabledAppsStarting();\n try {\n const snapshot =\n await this.dependencies.gateway.startEnabledWorkspaceApps(workspaceId);\n this.applySnapshot(workspaceId, snapshot);\n } catch (error) {\n this.setUnavailableError(error, {\n operation: \"workspace_app.start_enabled\",\n workspaceId\n });\n }\n }\n\n async uninstallApp(input: {\n appId: string;\n workspaceId: string;\n }): Promise<void> {\n const app = this.store.apps.find(\n (candidate) => candidate.appId === input.appId\n );\n const snapshot = await this.dependencies.gateway.uninstallWorkspaceApp(\n input.workspaceId,\n input.appId\n );\n this.applySnapshot(input.workspaceId, snapshot);\n this.dependencies.hooks?.onAppUninstalled?.(app ?? null);\n }\n\n async updateApp(input: {\n appId: string;\n trigger: \"badge_button\" | \"primary_action\";\n workspaceId: string;\n }): Promise<void> {\n const installKey = appRuntimeKey(input.workspaceId, input.appId);\n if (this.pendingInstallKeys.has(installKey)) {\n return;\n }\n const app = this.store.apps.find(\n (candidate) => candidate.appId === input.appId\n );\n const previousApps = this.store.apps;\n this.pendingInstallKeys.add(installKey);\n this.markAppInstalling(input.appId, { preserveInstalled: true });\n try {\n const snapshot = await this.dependencies.gateway.installWorkspaceApp(\n input.workspaceId,\n input.appId\n );\n this.applySnapshot(input.workspaceId, snapshot);\n this.dependencies.hooks?.onAppUpdated?.({\n app,\n trigger: input.trigger\n });\n if (this.pendingInstallKeys.has(installKey)) {\n this.scheduleInstallRefresh(input.workspaceId, input.appId);\n }\n } catch (error) {\n this.pendingInstallKeys.delete(installKey);\n this.clearInstallRefreshTimer(input.workspaceId, input.appId);\n this.store.apps = previousApps;\n this.setOperationError(error, {\n appId: input.appId,\n operation: \"workspace_app.update\",\n uiAction: \"update_app\",\n workspaceId: input.workspaceId\n });\n }\n }\n\n async retryApp(input: { appId: string; workspaceId: string }): Promise<void> {\n const app = this.store.apps.find(\n (candidate) => candidate.appId === input.appId\n );\n if (\n this.store.workspaceId !== input.workspaceId ||\n !app?.installed ||\n app.runtimeStatus !== \"failed\"\n ) {\n return;\n }\n const previousApps = this.store.apps;\n this.markAppStarting(input.appId);\n try {\n const snapshot = await this.dependencies.gateway.retryWorkspaceApp(\n input.workspaceId,\n input.appId\n );\n this.applySnapshot(input.workspaceId, snapshot);\n } catch (error) {\n if (this.store.workspaceId === input.workspaceId) {\n this.store.apps = previousApps;\n }\n this.setOperationError(error, {\n appId: input.appId,\n operation: \"workspace_app.retry\",\n uiAction: \"retry_app\",\n workspaceId: input.workspaceId\n });\n }\n }\n\n private waitForLaunchableApp(input: {\n appId: string;\n workspaceId: string;\n }): Promise<WorkspaceAppCenterApp | null> {\n const current = this.resolveLaunchableApp(input);\n if (current) {\n return Promise.resolve(current);\n }\n if (this.shouldAbortLaunchWait(input)) {\n return Promise.resolve(null);\n }\n\n const launchWaitTimeoutMs =\n this.dependencies.appOpenLaunchWaitTimeoutMs ??\n defaultAppOpenLaunchWaitTimeoutMs;\n return new Promise((resolve) => {\n let settled = false;\n let unsubscribe = noop;\n let timeout: ReturnType<typeof setTimeout> | null = null;\n const settle = (app: WorkspaceAppCenterApp | null) => {\n if (settled) {\n return;\n }\n settled = true;\n if (timeout) {\n clearTimeout(timeout);\n }\n unsubscribe();\n resolve(app);\n };\n timeout = setTimeout(() => {\n void this.refreshLaunchWaitState(input).then((app) => {\n if (!app) {\n this.markLaunchWaitTimedOut(input);\n }\n settle(app);\n });\n }, launchWaitTimeoutMs);\n unsubscribe = this.subscribe(() => {\n const app = this.store.apps.find(\n (candidate) => candidate.appId === input.appId\n );\n if (this.shouldAbortLaunchWait(input, app)) {\n settle(null);\n return;\n }\n const launchable = this.resolveLaunchableApp(input);\n if (launchable) {\n settle(launchable);\n }\n });\n });\n }\n\n private async refreshLaunchWaitState(input: {\n appId: string;\n workspaceId: string;\n }): Promise<WorkspaceAppCenterApp | null> {\n try {\n const snapshot = await this.dependencies.gateway.listWorkspaceApps(\n input.workspaceId\n );\n this.applySnapshot(input.workspaceId, snapshot);\n } catch (error) {\n this.setOperationError(error, {\n appId: input.appId,\n operation: \"workspace_app.refresh_launch_wait_state\",\n uiAction: \"refresh_launch_wait_state\",\n workspaceId: input.workspaceId\n });\n return null;\n }\n return this.resolveLaunchableApp(input);\n }\n\n private shouldAbortLaunchWait(\n input: { appId: string; workspaceId: string },\n app = this.store.apps.find((candidate) => candidate.appId === input.appId)\n ): boolean {\n return (\n this.store.workspaceId !== input.workspaceId ||\n !app?.installed ||\n app.runtimeStatus === \"failed\"\n );\n }\n}\n","export const workspaceAppIdPattern = /^[a-z0-9]+(?:[._-][a-z0-9]+)*$/;\n\nexport function isWorkspaceAppId(value: string): boolean {\n return workspaceAppIdPattern.test(value);\n}\n\nexport function normalizeWorkspaceAppId(value: string): string {\n return value.trim().toLowerCase();\n}\n\nexport function createWorkspaceAppIdentity(input: {\n readonly id: string;\n}): string {\n return normalizeWorkspaceAppId(input.id);\n}\n","import {\n workspaceAppManifestSchemaVersion,\n type WorkspaceAppManifest\n} from \"../contracts/manifest.ts\";\nimport { isWorkspaceAppId, normalizeWorkspaceAppId } from \"./appIdentity.ts\";\n\nconst appWindowMinWidth = 280;\nconst appWindowMinHeight = 160;\nconst appWindowMaxWidth = 1600;\nconst appWindowMaxHeight = 1200;\n\nexport type WorkspaceAppManifestValidationIssueCode =\n | \"manifest.notObject\"\n | \"manifest.schemaVersion\"\n | \"manifest.appId\"\n | \"manifest.name\"\n | \"manifest.version\"\n | \"manifest.description\"\n | \"manifest.icon\"\n | \"manifest.runtime\"\n | \"manifest.window\"\n | \"manifest.author\"\n | \"manifest.references\"\n | \"manifest.tags\"\n | \"manifest.localizationInfo\";\n\nexport interface WorkspaceAppManifestValidationIssue {\n readonly code: WorkspaceAppManifestValidationIssueCode;\n readonly path: string;\n readonly message: string;\n}\n\nexport interface WorkspaceAppManifestValidationResult {\n readonly manifest?: WorkspaceAppManifest;\n readonly issues: readonly WorkspaceAppManifestValidationIssue[];\n readonly valid: boolean;\n}\n\nexport function validateWorkspaceAppManifest(\n value: unknown\n): WorkspaceAppManifestValidationResult {\n const issues: WorkspaceAppManifestValidationIssue[] = [];\n\n if (!isRecord(value)) {\n return {\n issues: [\n {\n code: \"manifest.notObject\",\n message: \"Manifest must be an object.\",\n path: \"$\"\n }\n ],\n valid: false\n };\n }\n\n if (value.schemaVersion !== workspaceAppManifestSchemaVersion) {\n issues.push({\n code: \"manifest.schemaVersion\",\n message: `schemaVersion must be ${workspaceAppManifestSchemaVersion}.`,\n path: \"$.schemaVersion\"\n });\n }\n\n const appId = readOptionalString(value.appId);\n if (!appId || !isWorkspaceAppId(normalizeWorkspaceAppId(appId))) {\n issues.push({\n code: \"manifest.appId\",\n message:\n \"appId must contain lowercase letters, numbers, dots, hyphens, or underscores.\",\n path: \"$.appId\"\n });\n }\n\n const name = readOptionalString(value.name);\n if (!name) {\n issues.push({\n code: \"manifest.name\",\n message: \"name is required.\",\n path: \"$.name\"\n });\n }\n\n const version = readOptionalString(value.version);\n if (!version) {\n issues.push({\n code: \"manifest.version\",\n message: \"version is required.\",\n path: \"$.version\"\n });\n }\n\n const description = readOptionalString(value.description);\n if (!description) {\n issues.push({\n code: \"manifest.description\",\n message: \"description is required.\",\n path: \"$.description\"\n });\n }\n\n const icon = validateIcon(value.icon, issues);\n const runtime = validateRuntime(value.runtime, issues);\n const window = validateWindow(value.window, issues);\n const author = validateAuthor(value.author, issues);\n const references = validateReferences(value.references, issues);\n const tags = validateTags(value.tags, issues);\n const localizationInfo = validateLocalizationInfo(\n value.localizationInfo,\n issues\n );\n\n if (\n issues.length > 0 ||\n !appId ||\n !name ||\n !version ||\n !description ||\n !runtime\n ) {\n return {\n issues,\n valid: false\n };\n }\n\n return {\n issues,\n manifest: {\n schemaVersion: workspaceAppManifestSchemaVersion,\n appId: normalizeWorkspaceAppId(appId),\n name,\n version,\n description,\n ...(icon ? { icon } : {}),\n runtime,\n ...(window ? { window } : {}),\n ...(author ? { author } : {}),\n ...(references ? { references } : {}),\n ...(tags ? { tags } : {}),\n ...(localizationInfo ? { localizationInfo } : {})\n },\n valid: true\n };\n}\n\nfunction validateIcon(\n value: unknown,\n issues: WorkspaceAppManifestValidationIssue[]\n): WorkspaceAppManifest[\"icon\"] | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n if (!isRecord(value)) {\n issues.push({\n code: \"manifest.icon\",\n message: \"icon must be an object when provided.\",\n path: \"$.icon\"\n });\n return undefined;\n }\n\n const type = value.type;\n const src = readOptionalString(value.src);\n if (type !== \"asset\" || !src || !isRelativePackagePath(src)) {\n issues.push({\n code: \"manifest.icon\",\n message: \"icon must include type=asset and a relative src.\",\n path: \"$.icon\"\n });\n return undefined;\n }\n\n return {\n type,\n src\n };\n}\n\nfunction validateRuntime(\n value: unknown,\n issues: WorkspaceAppManifestValidationIssue[]\n): WorkspaceAppManifest[\"runtime\"] | undefined {\n if (!isRecord(value)) {\n issues.push({\n code: \"manifest.runtime\",\n message: \"runtime is required.\",\n path: \"$.runtime\"\n });\n return undefined;\n }\n\n const bootstrap = readOptionalString(value.bootstrap);\n const healthcheckPath = readOptionalString(value.healthcheckPath);\n if (!bootstrap || !isRelativePackagePath(bootstrap)) {\n issues.push({\n code: \"manifest.runtime\",\n message: \"runtime.bootstrap must be a relative package path.\",\n path: \"$.runtime.bootstrap\"\n });\n }\n if (!healthcheckPath || !healthcheckPath.startsWith(\"/\")) {\n issues.push({\n code: \"manifest.runtime\",\n message: \"runtime.healthcheckPath must start with /.\",\n path: \"$.runtime.healthcheckPath\"\n });\n }\n if (\n !bootstrap ||\n !healthcheckPath ||\n !isRelativePackagePath(bootstrap) ||\n !healthcheckPath.startsWith(\"/\")\n ) {\n return undefined;\n }\n\n return {\n bootstrap,\n healthcheckPath\n };\n}\n\nfunction validateWindow(\n value: unknown,\n issues: WorkspaceAppManifestValidationIssue[]\n): WorkspaceAppManifest[\"window\"] | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n if (!isRecord(value)) {\n issues.push({\n code: \"manifest.window\",\n message: \"window must be an object when provided.\",\n path: \"$.window\"\n });\n return undefined;\n }\n\n const minimizeBehavior = value.minimizeBehavior;\n if (\n minimizeBehavior !== undefined &&\n minimizeBehavior !== \"keep-mounted\" &&\n minimizeBehavior !== \"hibernate\"\n ) {\n issues.push({\n code: \"manifest.window\",\n message:\n \"window.minimizeBehavior must be keep-mounted or hibernate when provided.\",\n path: \"$.window.minimizeBehavior\"\n });\n return undefined;\n }\n const minWidth = validateWindowSize(\n value.minWidth,\n \"minWidth\",\n appWindowMinWidth,\n appWindowMaxWidth,\n issues\n );\n const minHeight = validateWindowSize(\n value.minHeight,\n \"minHeight\",\n appWindowMinHeight,\n appWindowMaxHeight,\n issues\n );\n if (minWidth === null || minHeight === null) {\n return undefined;\n }\n\n return {\n ...(minimizeBehavior ? { minimizeBehavior } : {}),\n ...(minHeight === undefined ? {} : { minHeight }),\n ...(minWidth === undefined ? {} : { minWidth })\n };\n}\n\nfunction validateWindowSize(\n value: unknown,\n field: \"minHeight\" | \"minWidth\",\n minimum: number,\n maximum: number,\n issues: WorkspaceAppManifestValidationIssue[]\n): number | null | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (\n typeof value !== \"number\" ||\n !Number.isInteger(value) ||\n value < minimum ||\n value > maximum\n ) {\n issues.push({\n code: \"manifest.window\",\n message: `window.${field} must be an integer between ${minimum} and ${maximum} when provided.`,\n path: `$.window.${field}`\n });\n return null;\n }\n return value;\n}\n\nfunction validateAuthor(\n value: unknown,\n issues: WorkspaceAppManifestValidationIssue[]\n): WorkspaceAppManifest[\"author\"] | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n if (!isRecord(value)) {\n issues.push({\n code: \"manifest.author\",\n message: \"author must be an object when provided.\",\n path: \"$.author\"\n });\n return undefined;\n }\n\n const name = readOptionalString(value.name);\n const url = readOptionalString(value.url);\n if (!name || (value.url !== undefined && !url)) {\n issues.push({\n code: \"manifest.author\",\n message: \"author must include name and an optional non-empty url.\",\n path: \"$.author\"\n });\n return undefined;\n }\n\n return {\n name,\n ...(url ? { url } : {})\n };\n}\n\nfunction validateReferences(\n value: unknown,\n issues: WorkspaceAppManifestValidationIssue[]\n): WorkspaceAppManifest[\"references\"] | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n if (!isRecord(value)) {\n issues.push({\n code: \"manifest.references\",\n message: \"references must be an object when provided.\",\n path: \"$.references\"\n });\n return undefined;\n }\n\n const searchEndpoint = readOptionalString(value.searchEndpoint);\n if (!searchEndpoint || !isRelativeUrlPath(searchEndpoint)) {\n issues.push({\n code: \"manifest.references\",\n message:\n \"references.searchEndpoint must be a relative URL path without query or hash.\",\n path: \"$.references.searchEndpoint\"\n });\n return undefined;\n }\n\n return { searchEndpoint };\n}\n\nfunction validateTags(\n value: unknown,\n issues: WorkspaceAppManifestValidationIssue[]\n): readonly string[] | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n if (!Array.isArray(value)) {\n issues.push({\n code: \"manifest.tags\",\n message: \"tags must be an array when provided.\",\n path: \"$.tags\"\n });\n return undefined;\n }\n\n const tags = value\n .map((tag) => readOptionalString(tag))\n .filter((tag): tag is string => Boolean(tag));\n if (tags.length !== value.length) {\n issues.push({\n code: \"manifest.tags\",\n message: \"tags must only contain non-empty strings.\",\n path: \"$.tags\"\n });\n }\n\n return Array.from(new Set(tags));\n}\n\nfunction validateLocalizationInfo(\n value: unknown,\n issues: WorkspaceAppManifestValidationIssue[]\n): WorkspaceAppManifest[\"localizationInfo\"] | undefined {\n if (value === undefined) {\n return undefined;\n }\n\n if (!isRecord(value)) {\n issues.push({\n code: \"manifest.localizationInfo\",\n message: \"localizationInfo must be an object when provided.\",\n path: \"$.localizationInfo\"\n });\n return undefined;\n }\n\n const defaultLocale = readOptionalString(value.defaultLocale);\n if (!defaultLocale) {\n issues.push({\n code: \"manifest.localizationInfo\",\n message: \"localizationInfo.defaultLocale is required.\",\n path: \"$.localizationInfo.defaultLocale\"\n });\n }\n\n const additionalLocalesValue = value.additionalLocales;\n if (\n additionalLocalesValue !== undefined &&\n !Array.isArray(additionalLocalesValue)\n ) {\n issues.push({\n code: \"manifest.localizationInfo\",\n message: \"localizationInfo.additionalLocales must be an array.\",\n path: \"$.localizationInfo.additionalLocales\"\n });\n return undefined;\n }\n\n const seenLocales = new Set(\n defaultLocale ? [defaultLocale.toLowerCase()] : []\n );\n const additionalLocales: {\n readonly file: string;\n readonly locale: string;\n }[] = [];\n for (const [index, entry] of (additionalLocalesValue ?? []).entries()) {\n if (!isRecord(entry)) {\n issues.push({\n code: \"manifest.localizationInfo\",\n message: \"localizationInfo.additionalLocales entries must be objects.\",\n path: `$.localizationInfo.additionalLocales[${index}]`\n });\n continue;\n }\n\n const locale = readOptionalString(entry.locale);\n const file = readOptionalString(entry.file);\n if (!locale || !file || !isRelativePackagePath(file)) {\n issues.push({\n code: \"manifest.localizationInfo\",\n message:\n \"localizationInfo.additionalLocales entries must include locale and a relative file path.\",\n path: `$.localizationInfo.additionalLocales[${index}]`\n });\n continue;\n }\n\n const localeKey = locale.toLowerCase();\n if (seenLocales.has(localeKey)) {\n issues.push({\n code: \"manifest.localizationInfo\",\n message: \"localizationInfo locales must be unique.\",\n path: `$.localizationInfo.additionalLocales[${index}].locale`\n });\n continue;\n }\n\n seenLocales.add(localeKey);\n additionalLocales.push({ locale, file });\n }\n\n if (\n !defaultLocale ||\n issues.some((issue) => issue.code === \"manifest.localizationInfo\")\n ) {\n return undefined;\n }\n\n return {\n defaultLocale,\n ...(additionalLocales.length > 0 ? { additionalLocales } : {})\n };\n}\n\nfunction readOptionalString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction isRelativePackagePath(value: string): boolean {\n return !value.startsWith(\"/\") && !value.split(/[\\\\/]/u).includes(\"..\");\n}\n\nfunction isRelativeUrlPath(value: string): boolean {\n const trimmed = value.trim();\n if (\n !trimmed ||\n !trimmed.startsWith(\"/\") ||\n trimmed.startsWith(\"//\") ||\n trimmed.includes(\"\\0\") ||\n trimmed.includes(\"?\") ||\n trimmed.includes(\"#\") ||\n trimmed.includes(\"%\")\n ) {\n return false;\n }\n return true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type {\n WorkspaceAppRuntimeState,\n WorkspaceAppRuntimeStatus\n} from \"../contracts/runtime.ts\";\nimport type { WorkspaceAppStatusTone } from \"../contracts/viewModel.ts\";\n\nexport interface WorkspaceAppStatusPresentation {\n readonly labelKey: string;\n readonly pulse: boolean;\n readonly tone: WorkspaceAppStatusTone;\n}\n\nconst statusAliases = new Map<string, WorkspaceAppRuntimeStatus>([\n [\"active\", \"running\"],\n [\"created\", \"idle\"],\n [\"crashed\", \"failed\"],\n [\"error\", \"failed\"],\n [\"failed\", \"failed\"],\n [\"idle\", \"idle\"],\n [\"installed\", \"idle\"],\n [\"installing\", \"installing\"],\n [\"downloading_runtime\", \"preparing\"],\n [\"launching\", \"starting\"],\n [\"pending\", \"starting\"],\n [\"preparing\", \"preparing\"],\n [\"ready\", \"idle\"],\n [\"running\", \"running\"],\n [\"runner_unavailable\", \"unavailable\"],\n [\"runtime_unavailable\", \"unavailable\"],\n [\"sandbox_unavailable\", \"unavailable\"],\n [\"started\", \"running\"],\n [\"starting\", \"starting\"],\n [\"stale\", \"unavailable\"],\n [\"stopped\", \"idle\"],\n [\"stopping\", \"stopping\"],\n [\"terminated\", \"idle\"],\n [\"terminating\", \"stopping\"],\n [\"unavailable\", \"unavailable\"],\n [\"unreachable\", \"unavailable\"]\n]);\n\nexport function mapWorkspaceAppRuntimeStatus(\n value: unknown\n): WorkspaceAppRuntimeStatus {\n if (typeof value !== \"string\") {\n return \"idle\";\n }\n\n return statusAliases.get(value.trim().toLowerCase()) ?? \"idle\";\n}\n\nexport function normalizeWorkspaceAppRuntimeState(\n state: Omit<WorkspaceAppRuntimeState, \"status\"> & {\n readonly status?: unknown;\n }\n): WorkspaceAppRuntimeState {\n return {\n ...state,\n status: mapWorkspaceAppRuntimeStatus(state.status)\n };\n}\n\nexport function resolveWorkspaceAppStatusPresentation(\n status: WorkspaceAppRuntimeStatus\n): WorkspaceAppStatusPresentation {\n switch (status) {\n case \"installing\":\n return {\n labelKey: \"status.installing\",\n pulse: true,\n tone: \"blue\"\n };\n case \"preparing\":\n return {\n labelKey: \"status.preparing\",\n pulse: true,\n tone: \"blue\"\n };\n case \"starting\":\n return {\n labelKey: \"status.starting\",\n pulse: true,\n tone: \"blue\"\n };\n case \"running\":\n return {\n labelKey: \"status.running\",\n pulse: false,\n tone: \"green\"\n };\n case \"failed\":\n return {\n labelKey: \"status.failed\",\n pulse: false,\n tone: \"red\"\n };\n case \"stopping\":\n return {\n labelKey: \"status.stopping\",\n pulse: true,\n tone: \"amber\"\n };\n case \"unavailable\":\n return {\n labelKey: \"status.unavailable\",\n pulse: false,\n tone: \"amber\"\n };\n case \"idle\":\n return {\n labelKey: \"actions.openApp\",\n pulse: false,\n tone: \"neutral\"\n };\n }\n}\n","import type {\n WorkspaceAppCatalogEntry,\n WorkspaceAppCatalogSourceKind,\n WorkspaceAppCatalogLocalization,\n WorkspaceAppInstallRecord,\n WorkspaceAppRecord\n} from \"../contracts/catalog.ts\";\nimport type {\n AppCenterViewModel,\n WorkspaceAppFactoryJobStatus,\n WorkspaceAppFactoryJobViewModel,\n WorkspaceAppPrimaryAction\n} from \"../contracts/viewModel.ts\";\nimport type { WorkspaceAppRuntimeState } from \"../contracts/runtime.ts\";\nimport { mapWorkspaceAppRuntimeStatus } from \"./statusMapping.ts\";\nimport { resolveWorkspaceAppStatusPresentation } from \"./statusMapping.ts\";\n\nexport interface CreateAppCenterViewModelInput {\n readonly apps: readonly WorkspaceAppRecord[];\n readonly factoryJobs?: readonly WorkspaceAppFactoryJobInput[];\n readonly locale?: string | null;\n readonly replaceableIconAppIds?: readonly string[];\n readonly runtimeStates?: readonly WorkspaceAppRuntimeState[];\n}\n\nexport interface WorkspaceAppFactoryJobInput {\n readonly agentSessionId?: string | null;\n readonly appId?: string | null;\n readonly displayName: string;\n readonly failureReason?: string | null;\n readonly jobId: string;\n readonly prompt: string;\n readonly provider?: string | null;\n readonly publishedVersion?: string | null;\n readonly status: WorkspaceAppFactoryJobStatus;\n readonly updatedAtUnixMs: number;\n readonly validationResult?: Record<string, unknown> | null;\n}\n\nexport function createAppCenterViewModel({\n apps,\n factoryJobs = [],\n locale = null,\n replaceableIconAppIds = [],\n runtimeStates = []\n}: CreateAppCenterViewModelInput): AppCenterViewModel {\n const runtimeStateMaps = createRuntimeStateMaps(runtimeStates);\n const appFactoryJobByAppId = createAppFactoryJobByAppId(factoryJobs);\n const replaceableIconAppIdSet = new Set(\n replaceableIconAppIds.map((appId) => appId.trim()).filter(Boolean)\n );\n\n const appCards = apps\n .map((app) => {\n const installationId = normalizeOptionalString(\n app.install?.installationId\n );\n const runtime = findRuntimeStateForApp(\n runtimeStateMaps,\n app.manifest.appId,\n installationId\n );\n const factoryJob = appFactoryJobByAppId.get(app.manifest.appId);\n const metadata = resolveWorkspaceAppCatalogMetadata({\n catalog: app.catalog,\n locale,\n manifest: app.manifest\n });\n const factoryAgentSessionId = factoryJob?.agentSessionId?.trim() || null;\n const status = runtime?.status ?? \"idle\";\n const presentation = resolveWorkspaceAppStatusPresentation(status);\n const installed = Boolean(app.install);\n const sourceKind = resolveCatalogSourceKind(app.catalog);\n const localApp = sourceKind === \"local\";\n const runtimeId = normalizeOptionalString(runtime?.runtimeId);\n const launchUrl = normalizeOptionalString(runtime?.launchUrl);\n const installedVersion = normalizeOptionalString(app.install?.version);\n const manifestVersion = normalizeOptionalString(app.manifest.version);\n const displayVersion = installedVersion ?? manifestVersion;\n const comingSoon =\n isComingSoonApp(metadata.tags) ||\n isComingSoonApp(app.manifest.tags ?? []);\n const busy = isBusyRuntimeStatus(status);\n const unavailable = status === \"unavailable\";\n const canUpdate =\n !comingSoon &&\n !busy &&\n !unavailable &&\n installed &&\n (app.updateAvailable ?? false);\n const canOpen = !comingSoon && installed && canOpenInstalledApp(status);\n const canRetry = installed && status === \"failed\";\n const primaryAction = resolvePrimaryAction({\n canOpen,\n canRetry,\n canUpdate,\n comingSoon,\n installed,\n status\n });\n\n return {\n id: app.manifest.appId,\n installationId,\n runtimeId,\n launchUrl,\n name: metadata.name,\n createdAtUnixMs: app.createdAtUnixMs ?? null,\n ...(metadata.description ? { description: metadata.description } : {}),\n ...(displayVersion && !comingSoon ? { version: displayVersion } : {}),\n ...(app.availableVersion && !comingSoon\n ? { availableVersion: app.availableVersion }\n : {}),\n ...(app.category?.trim() ? { category: app.category.trim() } : {}),\n updateAvailable: app.updateAvailable ?? false,\n ...(app.manifest.icon ? { icon: app.manifest.icon } : {}),\n tags: metadata.tags,\n installed,\n status,\n statusLabelKey: comingSoon\n ? \"status.comingSoon\"\n : resolvePrimaryActionLabelKey(primaryAction, presentation.labelKey),\n statusTone: presentation.tone,\n statusPulse: presentation.pulse,\n primaryAction,\n sourceKind,\n canOpen,\n canExport: localApp,\n canDelete: localApp,\n canReplaceIcon: replaceableIconAppIdSet.has(app.manifest.appId),\n canOpenFolder: installed,\n canOpenPackageFolder: installed && localApp && Boolean(displayVersion),\n canOpenFactorySession: Boolean(factoryAgentSessionId),\n canPublishFactoryUpdate:\n installed &&\n factoryJob?.status === \"ready\" &&\n Boolean(factoryJob.publishedVersion?.trim()),\n canUninstall: installed,\n canRetry,\n canUpdate,\n ...(factoryAgentSessionId ? { factoryAgentSessionId } : {}),\n ...(factoryJob?.jobId ? { factoryJobId: factoryJob.jobId } : {}),\n ...(factoryJob?.provider\n ? { factoryProvider: factoryJob.provider }\n : {}),\n ...(runtime?.error?.message\n ? { errorMessage: runtime.error.message }\n : {})\n };\n })\n .sort((left, right) => left.name.localeCompare(right.name));\n\n return {\n apps: appCards,\n factoryJobs: factoryJobs\n .filter((job) => !isPublishedAppFactoryJob(job))\n .map(createFactoryJobViewModel),\n empty: appCards.length === 0,\n failedCount: appCards.filter((app) => app.status === \"failed\").length,\n installedCount: appCards.filter((app) => app.installed).length,\n runningCount: appCards.filter((app) => app.status === \"running\").length\n };\n}\n\ninterface WorkspaceAppRuntimeStateMaps {\n readonly fallbackByAppId: Map<string, WorkspaceAppRuntimeState>;\n readonly byInstallationId: Map<string, WorkspaceAppRuntimeState>;\n}\n\nfunction createRuntimeStateMaps(\n runtimeStates: readonly WorkspaceAppRuntimeState[]\n): WorkspaceAppRuntimeStateMaps {\n const fallbackByAppId = new Map<string, WorkspaceAppRuntimeState>();\n const byInstallationId = new Map<string, WorkspaceAppRuntimeState>();\n\n for (const state of runtimeStates) {\n const runtime = {\n ...state,\n status: mapWorkspaceAppRuntimeStatus(state.status)\n };\n const installationId = normalizeOptionalString(runtime.installationId);\n if (installationId) {\n byInstallationId.set(installationId, runtime);\n continue;\n }\n\n const appId = normalizeOptionalString(runtime.appId);\n if (appId) {\n fallbackByAppId.set(appId, runtime);\n }\n }\n\n return {\n fallbackByAppId,\n byInstallationId\n };\n}\n\nfunction findRuntimeStateForApp(\n maps: WorkspaceAppRuntimeStateMaps,\n appId: string,\n installationId: string | null\n): WorkspaceAppRuntimeState | undefined {\n if (installationId) {\n const runtime = maps.byInstallationId.get(installationId);\n if (runtime) {\n return runtime;\n }\n }\n\n return maps.fallbackByAppId.get(appId);\n}\n\nfunction resolveCatalogSourceKind(\n catalog: WorkspaceAppCatalogEntry | null | undefined\n): WorkspaceAppCatalogSourceKind {\n return catalog?.source?.kind ?? \"bundled\";\n}\n\nexport function resolveWorkspaceAppCatalogMetadata(input: {\n readonly catalog?: Pick<WorkspaceAppCatalogEntry, \"localizations\"> | null;\n readonly locale?: string | null;\n readonly manifest: Pick<\n WorkspaceAppRecord[\"manifest\"],\n \"description\" | \"name\" | \"tags\"\n >;\n}): {\n readonly description: string;\n readonly name: string;\n readonly tags: readonly string[];\n} {\n const manifest = input.manifest;\n const localization = findWorkspaceAppCatalogLocalization(\n input.catalog,\n input.locale\n );\n const name = localization?.name?.trim() || manifest.name;\n const description =\n localization?.description?.trim() || manifest.description || \"\";\n const tags =\n localization?.tags\n ?.map((tag) => tag.trim())\n .filter((tag) => tag.length > 0) ??\n manifest.tags ??\n [];\n return {\n description,\n name,\n tags: Array.from(new Set(tags))\n };\n}\n\nfunction findWorkspaceAppCatalogLocalization(\n catalog: Pick<WorkspaceAppCatalogEntry, \"localizations\"> | null | undefined,\n locale: string | null | undefined\n): WorkspaceAppCatalogLocalization | null {\n const localizations = catalog?.localizations ?? [];\n const normalizedLocale = normalizeLocale(locale);\n if (!normalizedLocale || localizations.length === 0) {\n return null;\n }\n\n const exact = localizations.find(\n (localization) => normalizeLocale(localization.locale) === normalizedLocale\n );\n if (exact) {\n return exact;\n }\n\n const language = normalizedLocale.split(\"-\")[0];\n if (!language) {\n return null;\n }\n return (\n localizations.find(\n (localization) =>\n normalizeLocale(localization.locale)?.split(\"-\")[0] === language\n ) ?? null\n );\n}\n\nfunction normalizeLocale(value: string | null | undefined): string | null {\n const normalized = value?.trim().replace(/_/gu, \"-\").toLowerCase() ?? \"\";\n return normalized.length > 0 ? normalized : null;\n}\n\nfunction normalizeOptionalString(\n value: string | null | undefined\n): string | null {\n const normalized = value?.trim() ?? \"\";\n return normalized.length > 0 ? normalized : null;\n}\n\nfunction resolvePrimaryAction(input: {\n readonly canOpen: boolean;\n readonly canRetry: boolean;\n readonly canUpdate: boolean;\n readonly comingSoon: boolean;\n readonly installed: boolean;\n readonly status: WorkspaceAppRuntimeState[\"status\"];\n}): WorkspaceAppPrimaryAction {\n if (input.comingSoon) {\n return \"none\";\n }\n if (isBusyRuntimeStatus(input.status)) {\n return \"none\";\n }\n if (input.status === \"unavailable\") {\n return \"none\";\n }\n if (!input.installed) {\n return \"install\";\n }\n if (input.canUpdate) {\n return \"update\";\n }\n if (input.canRetry) {\n return \"retry\";\n }\n if (input.canOpen) {\n return \"open\";\n }\n return \"none\";\n}\n\nfunction isComingSoonApp(tags: readonly string[]): boolean {\n return tags.some((tag) => tag.trim().toLowerCase() === \"coming-soon\");\n}\n\nfunction canOpenInstalledApp(\n status: WorkspaceAppRuntimeState[\"status\"]\n): boolean {\n return status === \"idle\" || status === \"running\";\n}\n\nfunction isBusyRuntimeStatus(\n status: WorkspaceAppRuntimeState[\"status\"]\n): boolean {\n return (\n status === \"installing\" ||\n status === \"preparing\" ||\n status === \"starting\" ||\n status === \"stopping\"\n );\n}\n\nfunction resolvePrimaryActionLabelKey(\n primaryAction: WorkspaceAppPrimaryAction,\n fallbackLabelKey: string\n): string {\n switch (primaryAction) {\n case \"install\":\n return \"actions.installApp\";\n case \"open\":\n return \"actions.openApp\";\n case \"retry\":\n return \"actions.retryApp\";\n case \"update\":\n return \"actions.updateApp\";\n case \"none\":\n return fallbackLabelKey;\n }\n}\n\nfunction createAppFactoryJobByAppId(\n factoryJobs: readonly WorkspaceAppFactoryJobInput[]\n): Map<string, WorkspaceAppFactoryJobInput> {\n const result = new Map<string, WorkspaceAppFactoryJobInput>();\n for (const job of [...factoryJobs].sort(\n (left, right) => right.updatedAtUnixMs - left.updatedAtUnixMs\n )) {\n if (!isPublishedAppFactoryJob(job)) {\n continue;\n }\n const appId = job.appId?.trim();\n if (!appId || result.has(appId)) {\n continue;\n }\n result.set(appId, job);\n }\n return result;\n}\n\nfunction isPublishedAppFactoryJob(job: WorkspaceAppFactoryJobInput): boolean {\n return job.status === \"published\" || Boolean(job.publishedVersion?.trim());\n}\n\nfunction createFactoryJobViewModel(\n job: WorkspaceAppFactoryJobInput\n): WorkspaceAppFactoryJobViewModel {\n const statusLabelKey = `factory.status.${job.status}`;\n const title = job.displayName.trim();\n const agentSessionId = job.agentSessionId?.trim() || null;\n const canFixValidationFailure =\n job.status === \"failed\" && job.validationResult != null;\n return {\n id: job.jobId,\n agentSessionId,\n appId: job.appId,\n title,\n prompt: job.prompt,\n provider: job.provider,\n status: job.status,\n statusLabelKey,\n canCancel:\n job.status === \"queued\" ||\n job.status === \"generating\" ||\n job.status === \"preparing\" ||\n job.status === \"validating\",\n canDelete:\n job.status === \"canceled\" ||\n job.status === \"failed\" ||\n job.status === \"published\" ||\n job.status === \"ready\",\n canFix: canFixValidationFailure,\n canOpenAgentSession: Boolean(agentSessionId),\n canPublish: job.status === \"ready\",\n canRetryValidation: canFixValidationFailure,\n failureReason: job.failureReason,\n updatedAtUnixMs: job.updatedAtUnixMs\n };\n}\n\nexport function createWorkspaceAppRecord(input: {\n readonly catalog?: WorkspaceAppCatalogEntry | null;\n readonly category?: string | null;\n readonly createdAtUnixMs?: number | null;\n readonly install?: WorkspaceAppInstallRecord | null;\n}): WorkspaceAppRecord {\n const manifest = input.catalog?.manifest;\n if (!manifest) {\n throw new Error(\"catalog manifest is required.\");\n }\n\n return {\n catalog: input.catalog,\n category: input.category,\n createdAtUnixMs: input.createdAtUnixMs ?? null,\n install: input.install ?? null,\n manifest\n };\n}\n"],"mappings":"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","names":[]}
@@ -6,10 +6,11 @@ var workspaceAppRuntimeStatuses = [
6
6
  "starting",
7
7
  "running",
8
8
  "failed",
9
- "stopping"
9
+ "stopping",
10
+ "unavailable"
10
11
  ];
11
12
 
12
13
  export {
13
14
  workspaceAppRuntimeStatuses
14
15
  };
15
- //# sourceMappingURL=chunk-VLUZD2IT.js.map
16
+ //# sourceMappingURL=chunk-PD2WLRHE.js.map