Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
371 lines
13 KiB
Go
371 lines
13 KiB
Go
package workspace
|
|
|
|
import (
|
|
"strings"
|
|
|
|
tuttigenerated "github.com/tutti-os/tutti/services/tuttid/api/generated"
|
|
workspacebiz "github.com/tutti-os/tutti/services/tuttid/biz/workspace"
|
|
)
|
|
|
|
func GeneratedAppFromBiz(app workspacebiz.WorkspaceApp) tuttigenerated.WorkspaceApp {
|
|
return tuttigenerated.WorkspaceApp{
|
|
AppId: app.Package.AppID,
|
|
DisplayName: app.Package.DisplayName(),
|
|
Version: app.Package.Version,
|
|
Description: app.Package.Description(),
|
|
Authors: generatedAppAuthorsFromBiz(app.Package.Manifest),
|
|
Repository: generatedAppRepositoryFromBiz(app.Package.Manifest),
|
|
CreatedAtUnixMs: app.Package.CreatedAtUnixMs,
|
|
IconUrl: app.ResolvedIconURL(),
|
|
AvailableVersion: app.AvailableVersion,
|
|
AvailableIconUrl: app.AvailableIconURL,
|
|
UpdateAvailable: app.UpdateAvailable,
|
|
Installed: app.Installation != nil,
|
|
Enabled: app.Installation != nil && app.Installation.Enabled,
|
|
Status: generatedAppRuntimeStatus(app.Runtime.Status),
|
|
StateRevision: app.StateRevision,
|
|
LaunchUrl: app.Runtime.LaunchURL,
|
|
Port: app.Runtime.Port,
|
|
FailurePhase: generatedAppFailurePhase(app.Runtime.FailurePhase),
|
|
FailureReason: app.Runtime.FailureReason,
|
|
LastError: app.Runtime.LastError,
|
|
StartedAtUnixMs: app.Runtime.StartedAtUnixMs,
|
|
UpdatedAtUnixMs: app.Runtime.UpdatedAtUnixMs,
|
|
Source: generatedAppSource(app.Package.Source),
|
|
Exportable: app.Package.Source == workspacebiz.AppPackageSourceGenerated || app.Package.Source == workspacebiz.AppPackageSourceImported,
|
|
LocalPackageDir: generatedAppLocalPackageDir(app.Package),
|
|
Tags: nonNilStrings(app.Package.Manifest.Tags),
|
|
Localizations: GeneratedAppLocalizationsFromBiz(app.Package.Localizations()),
|
|
MinimizeBehavior: tuttigenerated.WorkspaceAppMinimizeBehavior(app.Package.MinimizeBehavior()),
|
|
WindowMinWidth: app.Package.WindowMinWidth(),
|
|
WindowMinHeight: app.Package.WindowMinHeight(),
|
|
Cli: generatedAppCLIState(app.CLI),
|
|
References: generatedAppReferencesStateFromBiz(app),
|
|
InstallProgress: generatedAppInstallProgressFromBiz(app.InstallProgress),
|
|
}
|
|
}
|
|
|
|
func generatedAppFailurePhase(value *workspacebiz.AppFailurePhase) *tuttigenerated.WorkspaceAppFailurePhase {
|
|
if value == nil {
|
|
return nil
|
|
}
|
|
result := tuttigenerated.WorkspaceAppFailurePhase(*value)
|
|
return &result
|
|
}
|
|
|
|
func generatedAppAuthorsFromBiz(manifest workspacebiz.AppManifest) []tuttigenerated.WorkspaceAppAuthor {
|
|
authors := manifest.Authors
|
|
if len(authors) == 0 && manifest.Author != nil {
|
|
authors = []workspacebiz.AppManifestAuthor{*manifest.Author}
|
|
}
|
|
result := make([]tuttigenerated.WorkspaceAppAuthor, 0, len(authors))
|
|
for _, author := range authors {
|
|
name := trimString(author.Name)
|
|
if name == "" {
|
|
continue
|
|
}
|
|
result = append(result, tuttigenerated.WorkspaceAppAuthor{
|
|
Name: name,
|
|
AvatarUrl: nullableString(trimString(author.AvatarURL)),
|
|
Url: nullableString(trimString(author.URL)),
|
|
})
|
|
}
|
|
return result
|
|
}
|
|
|
|
func generatedAppRepositoryFromBiz(manifest workspacebiz.AppManifest) *tuttigenerated.WorkspaceAppRepository {
|
|
if manifest.Source == nil {
|
|
return nil
|
|
}
|
|
repositoryType := trimString(manifest.Source.Type)
|
|
repositoryURL := trimString(manifest.Source.URL)
|
|
if repositoryType != "github" || repositoryURL == "" {
|
|
return nil
|
|
}
|
|
return &tuttigenerated.WorkspaceAppRepository{
|
|
Type: tuttigenerated.Github,
|
|
Url: repositoryURL,
|
|
}
|
|
}
|
|
|
|
func generatedAppInstallProgressFromBiz(progress *workspacebiz.AppInstallProgress) *tuttigenerated.WorkspaceAppInstallProgress {
|
|
if progress == nil {
|
|
return nil
|
|
}
|
|
return &tuttigenerated.WorkspaceAppInstallProgress{
|
|
UserPhase: generatedAppInstallUserPhase(progress.UserPhase),
|
|
OverallPercent: float32(progress.OverallPercent),
|
|
DownloadedBytes: progress.DownloadedBytes,
|
|
TotalBytes: progress.TotalBytes,
|
|
Indeterminate: progress.Indeterminate,
|
|
}
|
|
}
|
|
|
|
func generatedAppInstallUserPhase(phase workspacebiz.AppInstallUserPhase) tuttigenerated.WorkspaceAppInstallUserPhase {
|
|
switch phase {
|
|
case workspacebiz.AppInstallUserPhaseInstalling:
|
|
return tuttigenerated.WorkspaceAppInstallUserPhaseInstalling
|
|
case workspacebiz.AppInstallUserPhaseStarting:
|
|
return tuttigenerated.WorkspaceAppInstallUserPhaseStarting
|
|
default:
|
|
return tuttigenerated.WorkspaceAppInstallUserPhaseDownloading
|
|
}
|
|
}
|
|
|
|
func GeneratedAppsFromBiz(apps []workspacebiz.WorkspaceApp) []tuttigenerated.WorkspaceApp {
|
|
result := make([]tuttigenerated.WorkspaceApp, 0, len(apps))
|
|
for _, app := range apps {
|
|
result = append(result, GeneratedAppFromBiz(app))
|
|
}
|
|
return result
|
|
}
|
|
|
|
func GeneratedAppReferenceListResultFromBiz(workspaceID string, appID string, result workspacebiz.AppReferenceListResult) tuttigenerated.AppReferenceListResponse {
|
|
return tuttigenerated.AppReferenceListResponse{
|
|
WorkspaceId: workspaceID,
|
|
AppId: appID,
|
|
Items: generatedAppReferenceListItemsFromBiz(result.Items),
|
|
NextCursor: result.NextCursor,
|
|
}
|
|
}
|
|
|
|
func GeneratedAppReferenceSearchResultFromBiz(workspaceID string, appID string, result workspacebiz.AppReferenceListResult) tuttigenerated.AppReferenceSearchResponse {
|
|
return tuttigenerated.AppReferenceSearchResponse{
|
|
WorkspaceId: workspaceID,
|
|
AppId: appID,
|
|
Items: generatedAppReferenceSearchItemsFromBiz(result.Items),
|
|
NextCursor: result.NextCursor,
|
|
}
|
|
}
|
|
|
|
func generatedAppReferenceSearchItemsFromBiz(items []workspacebiz.AppReferenceListItem) []tuttigenerated.AppReferenceListReferenceItem {
|
|
result := make([]tuttigenerated.AppReferenceListReferenceItem, 0, len(items))
|
|
for _, item := range items {
|
|
referenceItem, ok := item.(workspacebiz.AppReferenceListReferenceItem)
|
|
if !ok {
|
|
continue
|
|
}
|
|
reference, ok := generatedAppReferenceFromBiz(referenceItem.Reference)
|
|
if !ok {
|
|
continue
|
|
}
|
|
result = append(result, tuttigenerated.AppReferenceListReferenceItem{
|
|
Type: tuttigenerated.AppReferenceListReferenceItemTypeReference,
|
|
Reference: reference,
|
|
})
|
|
}
|
|
return result
|
|
}
|
|
|
|
func GeneratedAppLocalizationsFromBiz(localizations []workspacebiz.AppManifestLocalization) []tuttigenerated.WorkspaceAppLocalization {
|
|
result := make([]tuttigenerated.WorkspaceAppLocalization, 0, len(localizations))
|
|
for _, localization := range localizations {
|
|
result = append(result, tuttigenerated.WorkspaceAppLocalization{
|
|
Locale: localization.Locale,
|
|
DisplayName: nullableString(localization.Name),
|
|
Description: nullableString(localization.Description),
|
|
Tags: nonNilStrings(localization.Tags),
|
|
})
|
|
}
|
|
return result
|
|
}
|
|
|
|
func GeneratedAppCatalogLoadStateFromBiz(state workspacebiz.AppCatalogLoadState) tuttigenerated.WorkspaceAppCatalogLoadState {
|
|
return tuttigenerated.WorkspaceAppCatalogLoadState{
|
|
Status: generatedAppCatalogLoadStatus(state.Status),
|
|
LastError: state.LastError,
|
|
UpdatedAtUnixMs: state.UpdatedAtUnixMs,
|
|
}
|
|
}
|
|
|
|
func generatedAppReferencesStateFromBiz(app workspacebiz.WorkspaceApp) tuttigenerated.WorkspaceAppReferencesState {
|
|
return tuttigenerated.WorkspaceAppReferencesState{
|
|
ListSupported: app.Package.ReferenceListSupported(),
|
|
SearchSupported: app.Package.ReferenceSearchSupported(),
|
|
}
|
|
}
|
|
|
|
func generatedAppReferenceListItemsFromBiz(items []workspacebiz.AppReferenceListItem) []tuttigenerated.AppReferenceListItem {
|
|
result := make([]tuttigenerated.AppReferenceListItem, 0, len(items))
|
|
for _, item := range items {
|
|
generated, ok := generatedAppReferenceListItemFromBiz(item)
|
|
if ok {
|
|
result = append(result, generated)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func generatedAppReferenceListItemFromBiz(item workspacebiz.AppReferenceListItem) (tuttigenerated.AppReferenceListItem, bool) {
|
|
switch typed := item.(type) {
|
|
case workspacebiz.AppReferenceGroup:
|
|
var generated tuttigenerated.AppReferenceListItem
|
|
if err := generated.FromAppReferenceGroup(tuttigenerated.AppReferenceGroup{
|
|
Type: tuttigenerated.AppReferenceGroupTypeGroup,
|
|
Id: typed.ID,
|
|
DisplayName: typed.DisplayName,
|
|
Description: nullableString(typed.Description),
|
|
ReferenceCount: typed.ReferenceCount,
|
|
}); err != nil {
|
|
return tuttigenerated.AppReferenceListItem{}, false
|
|
}
|
|
return generated, true
|
|
case workspacebiz.AppReferenceListReferenceItem:
|
|
reference, ok := generatedAppReferenceFromBiz(typed.Reference)
|
|
if !ok {
|
|
return tuttigenerated.AppReferenceListItem{}, false
|
|
}
|
|
var generated tuttigenerated.AppReferenceListItem
|
|
if err := generated.FromAppReferenceListReferenceItem(tuttigenerated.AppReferenceListReferenceItem{
|
|
Type: tuttigenerated.AppReferenceListReferenceItemTypeReference,
|
|
Reference: reference,
|
|
}); err != nil {
|
|
return tuttigenerated.AppReferenceListItem{}, false
|
|
}
|
|
return generated, true
|
|
default:
|
|
return tuttigenerated.AppReferenceListItem{}, false
|
|
}
|
|
}
|
|
|
|
func generatedAppReferenceFromBiz(reference workspacebiz.AppReference) (tuttigenerated.AppReference, bool) {
|
|
switch typed := reference.(type) {
|
|
case workspacebiz.AppFileReference:
|
|
var generated tuttigenerated.AppReference
|
|
if err := generated.FromAppFileReference(generatedAppFileReferenceFromBiz(typed)); err != nil {
|
|
return tuttigenerated.AppReference{}, false
|
|
}
|
|
return generated, true
|
|
default:
|
|
return tuttigenerated.AppReference{}, false
|
|
}
|
|
}
|
|
|
|
func generatedAppFileReferenceFromBiz(reference workspacebiz.AppFileReference) tuttigenerated.AppFileReference {
|
|
return tuttigenerated.AppFileReference{
|
|
Kind: tuttigenerated.AppFileReferenceKindFile,
|
|
DisplayName: nullableString(reference.DisplayName),
|
|
Description: nullableString(reference.Description),
|
|
Path: reference.Path,
|
|
SizeBytes: reference.SizeBytes,
|
|
MtimeMs: reference.MtimeMs,
|
|
MimeType: nullableString(reference.MimeType),
|
|
Score: nullableFloat32(reference.Score),
|
|
ParentGroupLabel: nullableString(reference.ParentGroupLabel),
|
|
}
|
|
}
|
|
|
|
func nullableString(value string) *string {
|
|
if value == "" {
|
|
return nil
|
|
}
|
|
return &value
|
|
}
|
|
|
|
func trimString(value string) string {
|
|
return strings.TrimSpace(value)
|
|
}
|
|
|
|
func nullableFloat32(value *float64) *float32 {
|
|
if value == nil {
|
|
return nil
|
|
}
|
|
converted := float32(*value)
|
|
return &converted
|
|
}
|
|
|
|
func nonNilStrings(values []string) []string {
|
|
if values == nil {
|
|
return []string{}
|
|
}
|
|
return values
|
|
}
|
|
|
|
func generatedAppSource(source workspacebiz.AppPackageSource) tuttigenerated.WorkspaceAppSource {
|
|
switch source {
|
|
case workspacebiz.AppPackageSourceGenerated:
|
|
return tuttigenerated.WorkspaceAppSourceGenerated
|
|
case workspacebiz.AppPackageSourceImported:
|
|
return tuttigenerated.WorkspaceAppSourceImported
|
|
case workspacebiz.AppPackageSourceLocalDev:
|
|
return tuttigenerated.WorkspaceAppSourceLocalDev
|
|
default:
|
|
return tuttigenerated.WorkspaceAppSourceBuiltin
|
|
}
|
|
}
|
|
|
|
func generatedAppLocalPackageDir(appPackage workspacebiz.AppPackage) *string {
|
|
if appPackage.Source != workspacebiz.AppPackageSourceLocalDev {
|
|
return nil
|
|
}
|
|
return nullableString(appPackage.PackageDir)
|
|
}
|
|
|
|
func generatedAppCatalogLoadStatus(status workspacebiz.AppCatalogLoadStatus) tuttigenerated.WorkspaceAppCatalogLoadStatus {
|
|
switch status {
|
|
case workspacebiz.AppCatalogLoadStatusLoading:
|
|
return tuttigenerated.WorkspaceAppCatalogLoadStatusLoading
|
|
case workspacebiz.AppCatalogLoadStatusReady:
|
|
return tuttigenerated.WorkspaceAppCatalogLoadStatusReady
|
|
case workspacebiz.AppCatalogLoadStatusFailed:
|
|
return tuttigenerated.WorkspaceAppCatalogLoadStatusFailed
|
|
default:
|
|
return tuttigenerated.WorkspaceAppCatalogLoadStatusDisabled
|
|
}
|
|
}
|
|
|
|
func generatedAppRuntimeStatus(status workspacebiz.AppRuntimeStatus) tuttigenerated.WorkspaceAppRuntimeStatus {
|
|
switch status {
|
|
case workspacebiz.AppRuntimeStatusRunning:
|
|
return tuttigenerated.WorkspaceAppRuntimeStatusRunning
|
|
case workspacebiz.AppRuntimeStatusInstalledPendingRestart:
|
|
return tuttigenerated.WorkspaceAppRuntimeStatusInstalledPendingRestart
|
|
case workspacebiz.AppRuntimeStatusPreparing:
|
|
return tuttigenerated.WorkspaceAppRuntimeStatusPreparing
|
|
case workspacebiz.AppRuntimeStatusStarting:
|
|
return tuttigenerated.WorkspaceAppRuntimeStatusStarting
|
|
case workspacebiz.AppRuntimeStatusFailed:
|
|
return tuttigenerated.WorkspaceAppRuntimeStatusFailed
|
|
case workspacebiz.AppRuntimeStatusStopping:
|
|
return tuttigenerated.WorkspaceAppRuntimeStatusStopping
|
|
default:
|
|
return tuttigenerated.WorkspaceAppRuntimeStatusIdle
|
|
}
|
|
}
|
|
|
|
func generatedAppCLIState(state workspacebiz.AppCLIState) tuttigenerated.WorkspaceAppCliState {
|
|
return tuttigenerated.WorkspaceAppCliState{
|
|
Status: generatedAppCLIStatus(state.Status),
|
|
Scope: nullableString(state.Scope),
|
|
Active: state.Active,
|
|
Issues: generatedAppCLIIssues(state.Issues),
|
|
}
|
|
}
|
|
|
|
func generatedAppCLIIssues(issues []workspacebiz.AppCLIIssue) []tuttigenerated.WorkspaceAppCliIssue {
|
|
result := make([]tuttigenerated.WorkspaceAppCliIssue, 0, len(issues))
|
|
for _, issue := range issues {
|
|
result = append(result, tuttigenerated.WorkspaceAppCliIssue{
|
|
Code: issue.Code,
|
|
Message: issue.Message,
|
|
Path: nullableString(issue.Path),
|
|
})
|
|
}
|
|
return result
|
|
}
|
|
|
|
func generatedAppCLIStatus(status workspacebiz.AppCLIStatus) tuttigenerated.WorkspaceAppCliStatus {
|
|
switch status {
|
|
case workspacebiz.AppCLIStatusPending:
|
|
return tuttigenerated.WorkspaceAppCliStatusPending
|
|
case workspacebiz.AppCLIStatusActive:
|
|
return tuttigenerated.WorkspaceAppCliStatusActive
|
|
case workspacebiz.AppCLIStatusWarning:
|
|
return tuttigenerated.WorkspaceAppCliStatusWarning
|
|
case workspacebiz.AppCLIStatusError:
|
|
return tuttigenerated.WorkspaceAppCliStatusError
|
|
default:
|
|
return tuttigenerated.WorkspaceAppCliStatusNone
|
|
}
|
|
}
|