@tutti-os/workspace-app-center 0.0.1
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.
- package/LICENSE +202 -0
- package/README.md +5 -0
- package/dist/chunk-3Z2WIHMP.js +7 -0
- package/dist/chunk-3Z2WIHMP.js.map +1 -0
- package/dist/chunk-FENSLRNH.js +690 -0
- package/dist/chunk-FENSLRNH.js.map +1 -0
- package/dist/chunk-LBSZLLZK.js +94 -0
- package/dist/chunk-LBSZLLZK.js.map +1 -0
- package/dist/chunk-VLUZD2IT.js +15 -0
- package/dist/chunk-VLUZD2IT.js.map +1 -0
- package/dist/contracts/index.d.ts +158 -0
- package/dist/contracts/index.js +11 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/core/index.d.ts +16 -0
- package/dist/core/index.js +42 -0
- package/dist/core/index.js.map +1 -0
- package/dist/i18n/index.d.ts +18 -0
- package/dist/i18n/index.js +574 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/index-Bert0Egy.d.ts +71 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/ui/index.d.ts +88 -0
- package/dist/ui/index.js +1619 -0
- package/dist/ui/index.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/appIdentity.ts","../src/core/manifestValidation.ts","../src/core/statusMapping.ts","../src/core/appCenterViewModel.ts"],"sourcesContent":["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.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 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 ...(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 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 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 [\"started\", \"running\"],\n [\"starting\", \"starting\"],\n [\"stopped\", \"idle\"],\n [\"stopping\", \"stopping\"],\n [\"terminated\", \"idle\"],\n [\"terminating\", \"stopping\"]\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 \"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 runtimeByAppId = new Map(\n runtimeStates.map((state) => [\n state.appId,\n {\n ...state,\n status: mapWorkspaceAppRuntimeStatus(state.status)\n }\n ])\n );\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 runtime = runtimeByAppId.get(app.manifest.appId);\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 comingSoon =\n isComingSoonApp(metadata.tags) ||\n isComingSoonApp(app.manifest.tags ?? []);\n const canUpdate = installed && (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 name: metadata.name,\n createdAtUnixMs: app.createdAtUnixMs ?? null,\n ...(metadata.description ? { description: metadata.description } : {}),\n ...(app.manifest.version && !comingSoon\n ? { version: app.manifest.version }\n : {}),\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:\n installed && localApp && Boolean(app.manifest.version?.trim()),\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\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 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.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":[]}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// src/core/appCenterAppOrdering.ts
|
|
2
|
+
function sortMyAppsByCreatedDesc(apps) {
|
|
3
|
+
return [...apps].sort((left, right) => {
|
|
4
|
+
const createdOrder = (right.createdAtUnixMs ?? 0) - (left.createdAtUnixMs ?? 0);
|
|
5
|
+
if (createdOrder !== 0) {
|
|
6
|
+
return createdOrder;
|
|
7
|
+
}
|
|
8
|
+
const nameOrder = left.name.localeCompare(right.name);
|
|
9
|
+
if (nameOrder !== 0) {
|
|
10
|
+
return nameOrder;
|
|
11
|
+
}
|
|
12
|
+
return left.id.localeCompare(right.id);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function sortRecommendedApps(apps) {
|
|
16
|
+
return [...apps].sort((left, right) => {
|
|
17
|
+
const categoryOrder = getRecommendedAppCategoryRank(left) - getRecommendedAppCategoryRank(right);
|
|
18
|
+
if (categoryOrder !== 0) {
|
|
19
|
+
return categoryOrder;
|
|
20
|
+
}
|
|
21
|
+
const comingSoonOrder = getRecommendedAppComingSoonRank(left) - getRecommendedAppComingSoonRank(right);
|
|
22
|
+
if (comingSoonOrder !== 0) {
|
|
23
|
+
return comingSoonOrder;
|
|
24
|
+
}
|
|
25
|
+
return left.name.localeCompare(right.name);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function sortRecommendedAppsForAllTab(apps) {
|
|
29
|
+
return [...apps].sort((left, right) => {
|
|
30
|
+
const comingSoonOrder = getRecommendedAppComingSoonRank(left) - getRecommendedAppComingSoonRank(right);
|
|
31
|
+
if (comingSoonOrder !== 0) {
|
|
32
|
+
return comingSoonOrder;
|
|
33
|
+
}
|
|
34
|
+
const categoryOrder = getRecommendedAppCategoryRank(left) - getRecommendedAppCategoryRank(right);
|
|
35
|
+
if (categoryOrder !== 0) {
|
|
36
|
+
return categoryOrder;
|
|
37
|
+
}
|
|
38
|
+
return left.name.localeCompare(right.name);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function getRecommendedAppComingSoonRank(app) {
|
|
42
|
+
return app.statusLabelKey === "status.comingSoon" || app.tags.some((tag) => tag.trim().toLowerCase() === "coming-soon") ? 1 : 0;
|
|
43
|
+
}
|
|
44
|
+
function getRecommendedAppCategoryRank(app) {
|
|
45
|
+
const category = app.category?.trim().toLowerCase() ?? "";
|
|
46
|
+
if (category === "\u4EA7\u54C1\u4E0E\u8BBE\u8BA1" || category === "product and design") {
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
if (category === "\u529E\u516C" || category === "office") {
|
|
50
|
+
return 1;
|
|
51
|
+
}
|
|
52
|
+
if (category === "\u5DE5\u5177" || category === "tools" || category === "productivity") {
|
|
53
|
+
return 2;
|
|
54
|
+
}
|
|
55
|
+
if (category === "\u5185\u5BB9\u521B\u4F5C" || category === "content creation") {
|
|
56
|
+
return 3;
|
|
57
|
+
}
|
|
58
|
+
const searchableText = [app.id, app.name, app.description, ...app.tags].filter(Boolean).join(" ").toLowerCase();
|
|
59
|
+
if (/\b(automation|schedule|recurring|productivity|efficiency|workflow|task)\b/.test(
|
|
60
|
+
searchableText
|
|
61
|
+
)) {
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
if (/\b(media|canvas|video|edit|design|prototype|creative|creation)\b/.test(
|
|
65
|
+
searchableText
|
|
66
|
+
)) {
|
|
67
|
+
return 1;
|
|
68
|
+
}
|
|
69
|
+
return 2;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/core/appFactoryProviderDefaults.ts
|
|
73
|
+
var DEFAULT_APP_FACTORY_PROVIDER = "codex";
|
|
74
|
+
function resolveDefaultAppFactoryProvider(options, preferredProvider) {
|
|
75
|
+
const normalizedPreferredProvider = preferredProvider?.trim() ?? "";
|
|
76
|
+
return options.find(
|
|
77
|
+
(option) => normalizedPreferredProvider !== "" && option.disabled !== true && option.provider === normalizedPreferredProvider
|
|
78
|
+
)?.provider ?? options.find(
|
|
79
|
+
(option) => option.disabled !== true && option.provider === DEFAULT_APP_FACTORY_PROVIDER
|
|
80
|
+
)?.provider ?? options.find((option) => option.disabled !== true)?.provider ?? options.find((option) => option.provider === DEFAULT_APP_FACTORY_PROVIDER)?.provider ?? options[0]?.provider ?? "";
|
|
81
|
+
}
|
|
82
|
+
function resolveSelectedAppFactoryProvider(currentProvider, options, preferredProvider) {
|
|
83
|
+
return options.some((option) => option.provider === currentProvider) ? currentProvider : resolveDefaultAppFactoryProvider(options, preferredProvider);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export {
|
|
87
|
+
sortMyAppsByCreatedDesc,
|
|
88
|
+
sortRecommendedApps,
|
|
89
|
+
sortRecommendedAppsForAllTab,
|
|
90
|
+
DEFAULT_APP_FACTORY_PROVIDER,
|
|
91
|
+
resolveDefaultAppFactoryProvider,
|
|
92
|
+
resolveSelectedAppFactoryProvider
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=chunk-LBSZLLZK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/appCenterAppOrdering.ts","../src/core/appFactoryProviderDefaults.ts"],"sourcesContent":["import type { AppCenterViewModel } from \"../contracts/viewModel.ts\";\n\nexport function sortMyAppsByCreatedDesc(\n apps: readonly AppCenterViewModel[\"apps\"][number][]\n): AppCenterViewModel[\"apps\"] {\n return [...apps].sort((left, right) => {\n const createdOrder =\n (right.createdAtUnixMs ?? 0) - (left.createdAtUnixMs ?? 0);\n if (createdOrder !== 0) {\n return createdOrder;\n }\n const nameOrder = left.name.localeCompare(right.name);\n if (nameOrder !== 0) {\n return nameOrder;\n }\n return left.id.localeCompare(right.id);\n });\n}\n\nexport function sortRecommendedApps(\n apps: readonly AppCenterViewModel[\"apps\"][number][]\n): AppCenterViewModel[\"apps\"] {\n return [...apps].sort((left, right) => {\n const categoryOrder =\n getRecommendedAppCategoryRank(left) -\n getRecommendedAppCategoryRank(right);\n if (categoryOrder !== 0) {\n return categoryOrder;\n }\n const comingSoonOrder =\n getRecommendedAppComingSoonRank(left) -\n getRecommendedAppComingSoonRank(right);\n if (comingSoonOrder !== 0) {\n return comingSoonOrder;\n }\n return left.name.localeCompare(right.name);\n });\n}\n\nexport function sortRecommendedAppsForAllTab(\n apps: readonly AppCenterViewModel[\"apps\"][number][]\n): AppCenterViewModel[\"apps\"] {\n return [...apps].sort((left, right) => {\n const comingSoonOrder =\n getRecommendedAppComingSoonRank(left) -\n getRecommendedAppComingSoonRank(right);\n if (comingSoonOrder !== 0) {\n return comingSoonOrder;\n }\n const categoryOrder =\n getRecommendedAppCategoryRank(left) -\n getRecommendedAppCategoryRank(right);\n if (categoryOrder !== 0) {\n return categoryOrder;\n }\n return left.name.localeCompare(right.name);\n });\n}\n\nfunction getRecommendedAppComingSoonRank(\n app: AppCenterViewModel[\"apps\"][number]\n): number {\n return app.statusLabelKey === \"status.comingSoon\" ||\n app.tags.some((tag) => tag.trim().toLowerCase() === \"coming-soon\")\n ? 1\n : 0;\n}\n\nfunction getRecommendedAppCategoryRank(\n app: AppCenterViewModel[\"apps\"][number]\n): number {\n const category = app.category?.trim().toLowerCase() ?? \"\";\n if (category === \"产品与设计\" || category === \"product and design\") {\n return 0;\n }\n if (category === \"办公\" || category === \"office\") {\n return 1;\n }\n if (\n category === \"工具\" ||\n category === \"tools\" ||\n category === \"productivity\"\n ) {\n return 2;\n }\n if (category === \"内容创作\" || category === \"content creation\") {\n return 3;\n }\n\n const searchableText = [app.id, app.name, app.description, ...app.tags]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n\n if (\n /\\b(automation|schedule|recurring|productivity|efficiency|workflow|task)\\b/.test(\n searchableText\n )\n ) {\n return 0;\n }\n\n if (\n /\\b(media|canvas|video|edit|design|prototype|creative|creation)\\b/.test(\n searchableText\n )\n ) {\n return 1;\n }\n\n return 2;\n}\n","export interface AppFactoryProviderDefaultOption {\n readonly disabled?: boolean;\n readonly provider: string;\n}\n\nexport const DEFAULT_APP_FACTORY_PROVIDER = \"codex\";\n\nexport function resolveDefaultAppFactoryProvider(\n options: readonly AppFactoryProviderDefaultOption[],\n preferredProvider?: string | null\n): string {\n const normalizedPreferredProvider = preferredProvider?.trim() ?? \"\";\n return (\n options.find(\n (option) =>\n normalizedPreferredProvider !== \"\" &&\n option.disabled !== true &&\n option.provider === normalizedPreferredProvider\n )?.provider ??\n options.find(\n (option) =>\n option.disabled !== true &&\n option.provider === DEFAULT_APP_FACTORY_PROVIDER\n )?.provider ??\n options.find((option) => option.disabled !== true)?.provider ??\n options.find((option) => option.provider === DEFAULT_APP_FACTORY_PROVIDER)\n ?.provider ??\n options[0]?.provider ??\n \"\"\n );\n}\n\nexport function resolveSelectedAppFactoryProvider(\n currentProvider: string,\n options: readonly AppFactoryProviderDefaultOption[],\n preferredProvider?: string | null\n): string {\n return options.some((option) => option.provider === currentProvider)\n ? currentProvider\n : resolveDefaultAppFactoryProvider(options, preferredProvider);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// src/contracts/runtime.ts
|
|
2
|
+
var workspaceAppRuntimeStatuses = [
|
|
3
|
+
"idle",
|
|
4
|
+
"installing",
|
|
5
|
+
"preparing",
|
|
6
|
+
"starting",
|
|
7
|
+
"running",
|
|
8
|
+
"failed",
|
|
9
|
+
"stopping"
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
workspaceAppRuntimeStatuses
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=chunk-VLUZD2IT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/contracts/runtime.ts"],"sourcesContent":["export const workspaceAppRuntimeStatuses = [\n \"idle\",\n \"installing\",\n \"preparing\",\n \"starting\",\n \"running\",\n \"failed\",\n \"stopping\"\n] as const;\n\nexport type WorkspaceAppRuntimeStatus =\n (typeof workspaceAppRuntimeStatuses)[number];\n\nexport interface WorkspaceAppRuntimeError {\n readonly code?: string;\n readonly message: string;\n}\n\nexport interface WorkspaceAppRuntimeState {\n readonly appId: string;\n readonly status: WorkspaceAppRuntimeStatus;\n readonly error?: WorkspaceAppRuntimeError | null;\n readonly startedAt?: string | null;\n readonly updatedAt?: string | null;\n}\n"],"mappings":";AAAO,IAAM,8BAA8B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
declare const workspaceAppManifestSchemaVersion = "nextop.app.manifest.v1";
|
|
2
|
+
type WorkspaceAppManifestSchemaVersion = typeof workspaceAppManifestSchemaVersion;
|
|
3
|
+
interface WorkspaceAppManifestIcon {
|
|
4
|
+
readonly type: "asset";
|
|
5
|
+
readonly src: string;
|
|
6
|
+
}
|
|
7
|
+
interface WorkspaceAppManifestRuntime {
|
|
8
|
+
readonly bootstrap: string;
|
|
9
|
+
readonly healthcheckPath: string;
|
|
10
|
+
}
|
|
11
|
+
type WorkspaceAppManifestWindowMinimizeBehavior = "hibernate" | "keep-mounted";
|
|
12
|
+
interface WorkspaceAppManifestWindow {
|
|
13
|
+
readonly minimizeBehavior?: WorkspaceAppManifestWindowMinimizeBehavior;
|
|
14
|
+
readonly minHeight?: number;
|
|
15
|
+
readonly minWidth?: number;
|
|
16
|
+
}
|
|
17
|
+
interface WorkspaceAppManifestAuthor {
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly url?: string;
|
|
20
|
+
}
|
|
21
|
+
interface WorkspaceAppManifestLocalizationInfo {
|
|
22
|
+
readonly defaultLocale: string;
|
|
23
|
+
readonly additionalLocales?: readonly WorkspaceAppManifestLocalizationFile[];
|
|
24
|
+
}
|
|
25
|
+
interface WorkspaceAppManifestLocalizationFile {
|
|
26
|
+
readonly locale: string;
|
|
27
|
+
readonly file: string;
|
|
28
|
+
}
|
|
29
|
+
interface WorkspaceAppManifest {
|
|
30
|
+
readonly schemaVersion: WorkspaceAppManifestSchemaVersion;
|
|
31
|
+
readonly appId: string;
|
|
32
|
+
readonly name: string;
|
|
33
|
+
readonly version: string;
|
|
34
|
+
readonly description: string;
|
|
35
|
+
readonly icon?: WorkspaceAppManifestIcon;
|
|
36
|
+
readonly runtime: WorkspaceAppManifestRuntime;
|
|
37
|
+
readonly window?: WorkspaceAppManifestWindow;
|
|
38
|
+
readonly author?: WorkspaceAppManifestAuthor;
|
|
39
|
+
readonly tags?: readonly string[];
|
|
40
|
+
readonly localizationInfo?: WorkspaceAppManifestLocalizationInfo;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type WorkspaceAppCatalogSourceKind = "bundled" | "local" | "remote";
|
|
44
|
+
interface WorkspaceAppCatalogSource {
|
|
45
|
+
readonly id?: string;
|
|
46
|
+
readonly kind: WorkspaceAppCatalogSourceKind;
|
|
47
|
+
readonly label?: string;
|
|
48
|
+
}
|
|
49
|
+
interface WorkspaceAppCatalogLocalization {
|
|
50
|
+
readonly locale: string;
|
|
51
|
+
readonly name?: string | null;
|
|
52
|
+
readonly description?: string | null;
|
|
53
|
+
readonly tags?: readonly string[];
|
|
54
|
+
}
|
|
55
|
+
interface WorkspaceAppCatalogEntry {
|
|
56
|
+
readonly localizations?: readonly WorkspaceAppCatalogLocalization[];
|
|
57
|
+
readonly manifest: WorkspaceAppManifest;
|
|
58
|
+
readonly source?: WorkspaceAppCatalogSource;
|
|
59
|
+
}
|
|
60
|
+
interface WorkspaceAppInstallRecord {
|
|
61
|
+
readonly appId: string;
|
|
62
|
+
readonly installedAt?: string | null;
|
|
63
|
+
readonly updatedAt?: string | null;
|
|
64
|
+
readonly catalogSourceId?: string | null;
|
|
65
|
+
}
|
|
66
|
+
interface WorkspaceAppRecord {
|
|
67
|
+
readonly availableIconUrl?: string | null;
|
|
68
|
+
readonly availableVersion?: string | null;
|
|
69
|
+
readonly catalog?: WorkspaceAppCatalogEntry | null;
|
|
70
|
+
readonly category?: string | null;
|
|
71
|
+
readonly createdAtUnixMs?: number | null;
|
|
72
|
+
readonly install?: WorkspaceAppInstallRecord | null;
|
|
73
|
+
readonly manifest: WorkspaceAppManifest;
|
|
74
|
+
readonly updateAvailable?: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
declare const workspaceAppRuntimeStatuses: readonly ["idle", "installing", "preparing", "starting", "running", "failed", "stopping"];
|
|
78
|
+
type WorkspaceAppRuntimeStatus = (typeof workspaceAppRuntimeStatuses)[number];
|
|
79
|
+
interface WorkspaceAppRuntimeError {
|
|
80
|
+
readonly code?: string;
|
|
81
|
+
readonly message: string;
|
|
82
|
+
}
|
|
83
|
+
interface WorkspaceAppRuntimeState {
|
|
84
|
+
readonly appId: string;
|
|
85
|
+
readonly status: WorkspaceAppRuntimeStatus;
|
|
86
|
+
readonly error?: WorkspaceAppRuntimeError | null;
|
|
87
|
+
readonly startedAt?: string | null;
|
|
88
|
+
readonly updatedAt?: string | null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
type WorkspaceAppStatusTone = "neutral" | "blue" | "green" | "amber" | "red";
|
|
92
|
+
type WorkspaceAppPrimaryAction = "install" | "open" | "retry" | "update" | "none";
|
|
93
|
+
interface WorkspaceAppCardViewModel {
|
|
94
|
+
readonly id: string;
|
|
95
|
+
readonly name: string;
|
|
96
|
+
readonly createdAtUnixMs: number | null;
|
|
97
|
+
readonly description?: string;
|
|
98
|
+
readonly version?: string;
|
|
99
|
+
readonly availableVersion?: string;
|
|
100
|
+
readonly category?: string | null;
|
|
101
|
+
readonly updateAvailable: boolean;
|
|
102
|
+
readonly icon?: {
|
|
103
|
+
readonly type: "asset";
|
|
104
|
+
readonly src: string;
|
|
105
|
+
};
|
|
106
|
+
readonly tags: readonly string[];
|
|
107
|
+
readonly installed: boolean;
|
|
108
|
+
readonly status: WorkspaceAppRuntimeStatus;
|
|
109
|
+
readonly statusLabelKey: string;
|
|
110
|
+
readonly statusTone: WorkspaceAppStatusTone;
|
|
111
|
+
readonly statusPulse: boolean;
|
|
112
|
+
readonly primaryAction: WorkspaceAppPrimaryAction;
|
|
113
|
+
readonly sourceKind: WorkspaceAppCatalogSourceKind;
|
|
114
|
+
readonly canOpen: boolean;
|
|
115
|
+
readonly canOpenFolder: boolean;
|
|
116
|
+
readonly canOpenPackageFolder: boolean;
|
|
117
|
+
readonly canExport: boolean;
|
|
118
|
+
readonly canDelete: boolean;
|
|
119
|
+
readonly canReplaceIcon: boolean;
|
|
120
|
+
readonly canOpenFactorySession: boolean;
|
|
121
|
+
readonly canPublishFactoryUpdate: boolean;
|
|
122
|
+
readonly canUninstall: boolean;
|
|
123
|
+
readonly canRetry: boolean;
|
|
124
|
+
readonly canUpdate: boolean;
|
|
125
|
+
readonly errorMessage?: string;
|
|
126
|
+
readonly factoryAgentSessionId?: string | null;
|
|
127
|
+
readonly factoryJobId?: string | null;
|
|
128
|
+
readonly factoryProvider?: string | null;
|
|
129
|
+
}
|
|
130
|
+
interface AppCenterViewModel {
|
|
131
|
+
readonly apps: readonly WorkspaceAppCardViewModel[];
|
|
132
|
+
readonly factoryJobs?: readonly WorkspaceAppFactoryJobViewModel[];
|
|
133
|
+
readonly installedCount: number;
|
|
134
|
+
readonly runningCount: number;
|
|
135
|
+
readonly failedCount: number;
|
|
136
|
+
readonly empty: boolean;
|
|
137
|
+
}
|
|
138
|
+
type WorkspaceAppFactoryJobStatus = "canceled" | "failed" | "generating" | "preparing" | "published" | "queued" | "ready" | "validating";
|
|
139
|
+
interface WorkspaceAppFactoryJobViewModel {
|
|
140
|
+
readonly id: string;
|
|
141
|
+
readonly agentSessionId?: string | null;
|
|
142
|
+
readonly appId?: string | null;
|
|
143
|
+
readonly title: string;
|
|
144
|
+
readonly prompt: string;
|
|
145
|
+
readonly provider?: string | null;
|
|
146
|
+
readonly status: WorkspaceAppFactoryJobStatus;
|
|
147
|
+
readonly statusLabelKey: string;
|
|
148
|
+
readonly canCancel: boolean;
|
|
149
|
+
readonly canDelete: boolean;
|
|
150
|
+
readonly canFix: boolean;
|
|
151
|
+
readonly canOpenAgentSession: boolean;
|
|
152
|
+
readonly canPublish: boolean;
|
|
153
|
+
readonly canRetryValidation: boolean;
|
|
154
|
+
readonly failureReason?: string | null;
|
|
155
|
+
readonly updatedAtUnixMs: number;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export { type AppCenterViewModel, type WorkspaceAppCardViewModel, type WorkspaceAppCatalogEntry, type WorkspaceAppCatalogLocalization, type WorkspaceAppCatalogSource, type WorkspaceAppCatalogSourceKind, type WorkspaceAppFactoryJobStatus, type WorkspaceAppFactoryJobViewModel, type WorkspaceAppInstallRecord, type WorkspaceAppManifest, type WorkspaceAppManifestAuthor, type WorkspaceAppManifestIcon, type WorkspaceAppManifestLocalizationFile, type WorkspaceAppManifestLocalizationInfo, type WorkspaceAppManifestRuntime, type WorkspaceAppManifestSchemaVersion, type WorkspaceAppManifestWindow, type WorkspaceAppManifestWindowMinimizeBehavior, type WorkspaceAppPrimaryAction, type WorkspaceAppRecord, type WorkspaceAppRuntimeError, type WorkspaceAppRuntimeState, type WorkspaceAppRuntimeStatus, type WorkspaceAppStatusTone, workspaceAppManifestSchemaVersion, workspaceAppRuntimeStatuses };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
workspaceAppRuntimeStatuses
|
|
3
|
+
} from "../chunk-VLUZD2IT.js";
|
|
4
|
+
import {
|
|
5
|
+
workspaceAppManifestSchemaVersion
|
|
6
|
+
} from "../chunk-3Z2WIHMP.js";
|
|
7
|
+
export {
|
|
8
|
+
workspaceAppManifestSchemaVersion,
|
|
9
|
+
workspaceAppRuntimeStatuses
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { C as CreateAppCenterViewModelInput, W as WorkspaceAppFactoryJobInput, a as WorkspaceAppManifestValidationIssue, b as WorkspaceAppManifestValidationIssueCode, c as WorkspaceAppManifestValidationResult, d as WorkspaceAppStatusPresentation, e as createAppCenterViewModel, f as createWorkspaceAppIdentity, g as createWorkspaceAppRecord, i as isWorkspaceAppId, m as mapWorkspaceAppRuntimeStatus, n as normalizeWorkspaceAppId, h as normalizeWorkspaceAppRuntimeState, r as resolveWorkspaceAppCatalogMetadata, j as resolveWorkspaceAppStatusPresentation, v as validateWorkspaceAppManifest, w as workspaceAppIdPattern } from '../index-Bert0Egy.js';
|
|
2
|
+
import { AppCenterViewModel } from '../contracts/index.js';
|
|
3
|
+
|
|
4
|
+
declare function sortMyAppsByCreatedDesc(apps: readonly AppCenterViewModel["apps"][number][]): AppCenterViewModel["apps"];
|
|
5
|
+
declare function sortRecommendedApps(apps: readonly AppCenterViewModel["apps"][number][]): AppCenterViewModel["apps"];
|
|
6
|
+
declare function sortRecommendedAppsForAllTab(apps: readonly AppCenterViewModel["apps"][number][]): AppCenterViewModel["apps"];
|
|
7
|
+
|
|
8
|
+
interface AppFactoryProviderDefaultOption {
|
|
9
|
+
readonly disabled?: boolean;
|
|
10
|
+
readonly provider: string;
|
|
11
|
+
}
|
|
12
|
+
declare const DEFAULT_APP_FACTORY_PROVIDER = "codex";
|
|
13
|
+
declare function resolveDefaultAppFactoryProvider(options: readonly AppFactoryProviderDefaultOption[], preferredProvider?: string | null): string;
|
|
14
|
+
declare function resolveSelectedAppFactoryProvider(currentProvider: string, options: readonly AppFactoryProviderDefaultOption[], preferredProvider?: string | null): string;
|
|
15
|
+
|
|
16
|
+
export { type AppFactoryProviderDefaultOption, DEFAULT_APP_FACTORY_PROVIDER, resolveDefaultAppFactoryProvider, resolveSelectedAppFactoryProvider, sortMyAppsByCreatedDesc, sortRecommendedApps, sortRecommendedAppsForAllTab };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAppCenterViewModel,
|
|
3
|
+
createWorkspaceAppIdentity,
|
|
4
|
+
createWorkspaceAppRecord,
|
|
5
|
+
isWorkspaceAppId,
|
|
6
|
+
mapWorkspaceAppRuntimeStatus,
|
|
7
|
+
normalizeWorkspaceAppId,
|
|
8
|
+
normalizeWorkspaceAppRuntimeState,
|
|
9
|
+
resolveWorkspaceAppCatalogMetadata,
|
|
10
|
+
resolveWorkspaceAppStatusPresentation,
|
|
11
|
+
validateWorkspaceAppManifest,
|
|
12
|
+
workspaceAppIdPattern
|
|
13
|
+
} from "../chunk-FENSLRNH.js";
|
|
14
|
+
import "../chunk-3Z2WIHMP.js";
|
|
15
|
+
import {
|
|
16
|
+
DEFAULT_APP_FACTORY_PROVIDER,
|
|
17
|
+
resolveDefaultAppFactoryProvider,
|
|
18
|
+
resolveSelectedAppFactoryProvider,
|
|
19
|
+
sortMyAppsByCreatedDesc,
|
|
20
|
+
sortRecommendedApps,
|
|
21
|
+
sortRecommendedAppsForAllTab
|
|
22
|
+
} from "../chunk-LBSZLLZK.js";
|
|
23
|
+
export {
|
|
24
|
+
DEFAULT_APP_FACTORY_PROVIDER,
|
|
25
|
+
createAppCenterViewModel,
|
|
26
|
+
createWorkspaceAppIdentity,
|
|
27
|
+
createWorkspaceAppRecord,
|
|
28
|
+
isWorkspaceAppId,
|
|
29
|
+
mapWorkspaceAppRuntimeStatus,
|
|
30
|
+
normalizeWorkspaceAppId,
|
|
31
|
+
normalizeWorkspaceAppRuntimeState,
|
|
32
|
+
resolveDefaultAppFactoryProvider,
|
|
33
|
+
resolveSelectedAppFactoryProvider,
|
|
34
|
+
resolveWorkspaceAppCatalogMetadata,
|
|
35
|
+
resolveWorkspaceAppStatusPresentation,
|
|
36
|
+
sortMyAppsByCreatedDesc,
|
|
37
|
+
sortRecommendedApps,
|
|
38
|
+
sortRecommendedAppsForAllTab,
|
|
39
|
+
validateWorkspaceAppManifest,
|
|
40
|
+
workspaceAppIdPattern
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as _tutti_os_ui_i18n_runtime from '@tutti-os/ui-i18n-runtime';
|
|
2
|
+
import { I18nRuntime, I18nDictionary } from '@tutti-os/ui-i18n-runtime';
|
|
3
|
+
|
|
4
|
+
declare const appCenterI18nNamespace = "appCenter";
|
|
5
|
+
declare const nextopI18nModule: _tutti_os_ui_i18n_runtime.ScopedLocaleObjectsI18nModuleManifest;
|
|
6
|
+
type AppCenterI18nKey = string;
|
|
7
|
+
type AppCenterI18nRuntime = I18nRuntime<AppCenterI18nKey>;
|
|
8
|
+
declare const appCenterI18nResources: {
|
|
9
|
+
readonly en: {
|
|
10
|
+
readonly appCenter: I18nDictionary;
|
|
11
|
+
};
|
|
12
|
+
readonly "zh-CN": {
|
|
13
|
+
readonly appCenter: I18nDictionary;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
declare function createAppCenterI18nRuntime(runtime: I18nRuntime<string> | undefined): AppCenterI18nRuntime;
|
|
17
|
+
|
|
18
|
+
export { type AppCenterI18nKey, type AppCenterI18nRuntime, appCenterI18nNamespace, appCenterI18nResources, createAppCenterI18nRuntime, nextopI18nModule };
|