package runtime import ( "fmt" // Import the CONCRETE implementations from the internal packages. "forge.lthn.ai/core/gui/pkg/config" "forge.lthn.ai/core/gui/pkg/crypt" "forge.lthn.ai/core/gui/pkg/display" "forge.lthn.ai/core/gui/pkg/docs" "forge.lthn.ai/core/gui/pkg/help" "forge.lthn.ai/core/gui/pkg/i18n" "forge.lthn.ai/core/gui/pkg/ide" "forge.lthn.ai/core/gui/pkg/io" "forge.lthn.ai/core/gui/pkg/module" "forge.lthn.ai/core/gui/pkg/workspace" // Import the ABSTRACT contracts (interfaces). "forge.lthn.ai/core/gui/pkg/core" ) // App is the runtime container that holds all instantiated services. // Its fields are the concrete types, allowing Wails to bind them directly. type Runtime struct { Core *core.Core Config *config.Service Display *display.Service Docs *docs.Service Help *help.Service Crypt *crypt.Service I18n *i18n.Service IDE *ide.Service Module *module.Service Workspace *workspace.Service } // ServiceFactory defines a function that creates a service instance. type ServiceFactory func() (any, error) // newWithFactories creates a new Runtime instance using the provided service factories. func newWithFactories(factories map[string]ServiceFactory) (*Runtime, error) { services := make(map[string]any) coreOpts := []core.Option{} for _, name := range []string{"config", "display", "docs", "help", "crypt", "i18n", "ide", "module", "workspace"} { factory, ok := factories[name] if !ok { return nil, fmt.Errorf("service %s factory not provided", name) } svc, err := factory() if err != nil { return nil, fmt.Errorf("failed to create service %s: %w", name, err) } services[name] = svc svcCopy := svc coreOpts = append(coreOpts, core.WithService(func(c *core.Core) (any, error) { return svcCopy, nil })) } coreInstance, err := core.New(coreOpts...) if err != nil { return nil, err } configSvc, ok := services["config"].(*config.Service) if !ok { return nil, fmt.Errorf("config service has unexpected type") } displaySvc, ok := services["display"].(*display.Service) if !ok { return nil, fmt.Errorf("display service has unexpected type") } docsSvc, ok := services["docs"].(*docs.Service) if !ok { return nil, fmt.Errorf("docs service has unexpected type") } helpSvc, ok := services["help"].(*help.Service) if !ok { return nil, fmt.Errorf("help service has unexpected type") } cryptSvc, ok := services["crypt"].(*crypt.Service) if !ok { return nil, fmt.Errorf("crypt service has unexpected type") } i18nSvc, ok := services["i18n"].(*i18n.Service) if !ok { return nil, fmt.Errorf("i18n service has unexpected type") } ideSvc, ok := services["ide"].(*ide.Service) if !ok { return nil, fmt.Errorf("ide service has unexpected type") } moduleSvc, ok := services["module"].(*module.Service) if !ok { return nil, fmt.Errorf("module service has unexpected type") } workspaceSvc, ok := services["workspace"].(*workspace.Service) if !ok { return nil, fmt.Errorf("workspace service has unexpected type") } // Set core reference for services that need it docsSvc.SetCore(coreInstance) // Set up ServiceRuntime for workspace (needs Config access) workspaceSvc.ServiceRuntime = core.NewServiceRuntime(coreInstance, workspace.Options{}) // Set up ServiceRuntime for IDE ideSvc.ServiceRuntime = core.NewServiceRuntime(coreInstance, ide.Options{}) // Set up ServiceRuntime for Module and register builtins moduleSvc.ServiceRuntime = core.NewServiceRuntime(coreInstance, module.Options{}) module.RegisterBuiltins(moduleSvc.Registry()) app := &Runtime{ Core: coreInstance, Config: configSvc, Display: displaySvc, Docs: docsSvc, Help: helpSvc, Crypt: cryptSvc, I18n: i18nSvc, IDE: ideSvc, Module: moduleSvc, Workspace: workspaceSvc, } return app, nil } // New creates and wires together all application services using static dependency injection. func New() (*Runtime, error) { return newWithFactories(map[string]ServiceFactory{ "config": func() (any, error) { return config.New() }, "display": func() (any, error) { return display.New() }, "docs": func() (any, error) { return docs.New(docs.Options{BaseURL: "https://docs.lethean.io"}) }, "help": func() (any, error) { return help.New(help.Options{}) }, "crypt": func() (any, error) { return crypt.New() }, "i18n": func() (any, error) { return i18n.New() }, "ide": func() (any, error) { return ide.New() }, "module": func() (any, error) { return module.NewService(module.Options{AppsDir: "apps"}) }, "workspace": func() (any, error) { return workspace.New(io.Local) }, }) }