@syntrologie/runtime-sdk 1.0.1-canary.3 → 2.0.0-canary.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.
Files changed (122) hide show
  1. package/CAPABILITIES.md +630 -463
  2. package/README.md +285 -62
  3. package/dist/RuntimeProvider.d.ts +51 -0
  4. package/dist/RuntimeProvider.js +114 -0
  5. package/dist/RuntimeProvider.js.map +1 -0
  6. package/dist/SmartCanvasApp.d.ts +9 -3
  7. package/dist/SmartCanvasApp.js +36 -38
  8. package/dist/SmartCanvasApp.js.map +1 -1
  9. package/dist/actions/ActionEngine.d.ts +11 -0
  10. package/dist/actions/ActionEngine.js +274 -0
  11. package/dist/actions/ActionEngine.js.map +1 -0
  12. package/dist/actions/executors/index.d.ts +118 -0
  13. package/dist/actions/executors/index.js +242 -0
  14. package/dist/actions/executors/index.js.map +1 -0
  15. package/dist/actions/executors/tour.d.ts +18 -0
  16. package/dist/actions/executors/tour.js +332 -0
  17. package/dist/actions/executors/tour.js.map +1 -0
  18. package/dist/actions/index.d.ts +10 -0
  19. package/dist/actions/index.js +12 -0
  20. package/dist/actions/index.js.map +1 -0
  21. package/dist/actions/types.d.ts +399 -0
  22. package/dist/actions/types.js +8 -0
  23. package/dist/actions/types.js.map +1 -0
  24. package/dist/actions/validation.d.ts +14 -0
  25. package/dist/actions/validation.js +603 -0
  26. package/dist/actions/validation.js.map +1 -0
  27. package/dist/api.d.ts +32 -18
  28. package/dist/api.js +56 -39
  29. package/dist/api.js.map +1 -1
  30. package/dist/apps/AppContext.d.ts +31 -0
  31. package/dist/apps/AppContext.js +93 -0
  32. package/dist/apps/AppContext.js.map +1 -0
  33. package/dist/apps/AppLoader.d.ts +84 -0
  34. package/dist/apps/AppLoader.js +250 -0
  35. package/dist/apps/AppLoader.js.map +1 -0
  36. package/dist/apps/AppRegistry.d.ts +102 -0
  37. package/dist/apps/AppRegistry.js +317 -0
  38. package/dist/apps/AppRegistry.js.map +1 -0
  39. package/dist/apps/examples/gamification-app.example.d.ts +305 -0
  40. package/dist/apps/examples/gamification-app.example.js +329 -0
  41. package/dist/apps/examples/gamification-app.example.js.map +1 -0
  42. package/dist/apps/index.d.ts +18 -0
  43. package/dist/apps/index.js +26 -0
  44. package/dist/apps/index.js.map +1 -0
  45. package/dist/apps/types.d.ts +231 -0
  46. package/dist/apps/types.js +8 -0
  47. package/dist/apps/types.js.map +1 -0
  48. package/dist/bootstrap.d.ts +24 -0
  49. package/dist/bootstrap.js +133 -33
  50. package/dist/bootstrap.js.map +1 -1
  51. package/dist/components/ShadowCanvasOverlay.js +36 -9
  52. package/dist/components/ShadowCanvasOverlay.js.map +1 -1
  53. package/dist/components/TileCard.js +37 -18
  54. package/dist/components/TileCard.js.map +1 -1
  55. package/dist/context/schema.d.ts +16 -16
  56. package/dist/decisions/schema.d.ts +96 -96
  57. package/dist/earlyPatcher.d.ts +8 -20
  58. package/dist/earlyPatcher.js +13 -62
  59. package/dist/earlyPatcher.js.map +1 -1
  60. package/dist/editorLoader.d.ts +2 -0
  61. package/dist/editorLoader.js +46 -7
  62. package/dist/editorLoader.js.map +1 -1
  63. package/dist/events/normalizers/posthog.d.ts +24 -0
  64. package/dist/events/normalizers/posthog.js.map +1 -1
  65. package/dist/events/schema.d.ts +8 -8
  66. package/dist/events/types.d.ts +6 -0
  67. package/dist/events/types.js +8 -0
  68. package/dist/events/types.js.map +1 -1
  69. package/dist/hooks/useCanvasOverlays.d.ts +4 -1
  70. package/dist/hooks/useCanvasOverlays.js +53 -6
  71. package/dist/hooks/useCanvasOverlays.js.map +1 -1
  72. package/dist/hooks/useShadowCanvasConfig.d.ts +3 -7
  73. package/dist/hooks/useShadowCanvasConfig.js +2 -3
  74. package/dist/hooks/useShadowCanvasConfig.js.map +1 -1
  75. package/dist/index.d.ts +5 -0
  76. package/dist/index.js +10 -0
  77. package/dist/index.js.map +1 -1
  78. package/dist/overlays/schema.d.ts +153 -153
  79. package/dist/runtime.d.ts +24 -0
  80. package/dist/runtime.js +75 -1
  81. package/dist/runtime.js.map +1 -1
  82. package/dist/smart-canvas.esm.js +162 -55
  83. package/dist/smart-canvas.esm.js.map +4 -4
  84. package/dist/smart-canvas.js +21133 -17957
  85. package/dist/smart-canvas.js.map +4 -4
  86. package/dist/smart-canvas.min.js +162 -55
  87. package/dist/smart-canvas.min.js.map +4 -4
  88. package/dist/store/example.d.ts +1 -0
  89. package/dist/store/example.js +43 -0
  90. package/dist/store/example.js.map +1 -0
  91. package/dist/store/mini-effector.d.ts +46 -0
  92. package/dist/store/mini-effector.js +90 -0
  93. package/dist/store/mini-effector.js.map +1 -0
  94. package/dist/surfaces/Surfaces.d.ts +11 -0
  95. package/dist/surfaces/Surfaces.js +361 -0
  96. package/dist/surfaces/Surfaces.js.map +1 -0
  97. package/dist/surfaces/index.d.ts +9 -0
  98. package/dist/surfaces/index.js +12 -0
  99. package/dist/surfaces/index.js.map +1 -0
  100. package/dist/surfaces/positioning.d.ts +50 -0
  101. package/dist/surfaces/positioning.js +231 -0
  102. package/dist/surfaces/positioning.js.map +1 -0
  103. package/dist/surfaces/types.d.ts +167 -0
  104. package/dist/surfaces/types.js +23 -0
  105. package/dist/surfaces/types.js.map +1 -0
  106. package/dist/telemetry/adapters/posthog.d.ts +6 -0
  107. package/dist/telemetry/adapters/posthog.js +9 -0
  108. package/dist/telemetry/adapters/posthog.js.map +1 -1
  109. package/dist/types-only.d.ts +32 -0
  110. package/dist/types-only.js +11 -0
  111. package/dist/types-only.js.map +1 -0
  112. package/dist/types.d.ts +26 -14
  113. package/dist/types.js +1 -1
  114. package/dist/types.js.map +1 -1
  115. package/dist/widgets/WidgetRegistry.d.ts +139 -0
  116. package/dist/widgets/WidgetRegistry.js +182 -0
  117. package/dist/widgets/WidgetRegistry.js.map +1 -0
  118. package/dist/widgets/index.d.ts +7 -0
  119. package/dist/widgets/index.js +7 -0
  120. package/dist/widgets/index.js.map +1 -0
  121. package/package.json +13 -3
  122. package/schema/canvas-config.schema.json +444 -254
@@ -0,0 +1,250 @@
1
+ /**
2
+ * App Loader
3
+ *
4
+ * Handles loading apps from CDN based on canvas config requirements.
5
+ *
6
+ * Loading Strategy:
7
+ * 1. Core apps (built-in actions) are bundled with runtime - no loading needed
8
+ * 2. External apps are loaded from CDN when config references them
9
+ *
10
+ * The loader determines which apps are needed by scanning the canvas config for:
11
+ * - Action kinds with namespaces (e.g., "gamification:awardBadge")
12
+ * - Widget IDs with namespaces (e.g., "gamification:leaderboard")
13
+ * - Explicit app references in config
14
+ */
15
+ // ============================================================================
16
+ // Core Apps (bundled with runtime)
17
+ // ============================================================================
18
+ /**
19
+ * Core action kinds that are bundled with the runtime.
20
+ * These don't require loading external apps.
21
+ */
22
+ const CORE_ACTION_KINDS = new Set([
23
+ "overlays:highlight",
24
+ "overlays:pulse",
25
+ "overlays:badge",
26
+ "overlays:tooltip",
27
+ "content:insertHtml",
28
+ "content:setText",
29
+ "content:setAttr",
30
+ "content:addClass",
31
+ "content:removeClass",
32
+ "content:setStyle",
33
+ "core:mountWidget",
34
+ "core:wait",
35
+ "core:sequence",
36
+ "core:parallel",
37
+ "navigation:scrollTo",
38
+ "navigation:navigate",
39
+ ]);
40
+ /**
41
+ * Check if an action kind is a core action.
42
+ */
43
+ export function isCoreActionKind(kind) {
44
+ return CORE_ACTION_KINDS.has(kind);
45
+ }
46
+ /**
47
+ * Extract app ID from a namespaced action kind.
48
+ * e.g., "gamification:awardBadge" → "gamification"
49
+ */
50
+ export function getAppIdFromActionKind(kind) {
51
+ if (isCoreActionKind(kind))
52
+ return null;
53
+ const colonIndex = kind.indexOf(":");
54
+ if (colonIndex === -1)
55
+ return null;
56
+ return kind.slice(0, colonIndex);
57
+ }
58
+ /**
59
+ * Extract app ID from a namespaced widget ID.
60
+ * e.g., "gamification:leaderboard" → "gamification"
61
+ */
62
+ export function getAppIdFromWidgetId(widgetId) {
63
+ const colonIndex = widgetId.indexOf(":");
64
+ if (colonIndex === -1)
65
+ return null;
66
+ return widgetId.slice(0, colonIndex);
67
+ }
68
+ // ============================================================================
69
+ // App Loader
70
+ // ============================================================================
71
+ /**
72
+ * Create an app loader instance.
73
+ */
74
+ export function createAppLoader(options) {
75
+ const { cdnBase, registry, timeout = 10000, onLoadStart, onLoadEnd } = options;
76
+ /** Cache of loading promises to avoid duplicate loads */
77
+ const loadingPromises = new Map();
78
+ /** Cache of loaded app URLs */
79
+ const loadedUrls = new Set();
80
+ /**
81
+ * Get the CDN URL for an app.
82
+ */
83
+ function getAppUrl(appId) {
84
+ // Convention: apps are at {cdnBase}/apps/{appId}/index.js
85
+ return `${cdnBase}/apps/${appId}/index.js`;
86
+ }
87
+ /**
88
+ * Load a single app from CDN.
89
+ */
90
+ async function loadApp(appId) {
91
+ var _a;
92
+ // Check if already registered
93
+ if (registry.has(appId)) {
94
+ return { appId, success: true, manifest: (_a = registry.get(appId)) === null || _a === void 0 ? void 0 : _a.manifest };
95
+ }
96
+ // Check if already loading
97
+ if (loadingPromises.has(appId)) {
98
+ return loadingPromises.get(appId);
99
+ }
100
+ // Start loading
101
+ const loadPromise = (async () => {
102
+ onLoadStart === null || onLoadStart === void 0 ? void 0 : onLoadStart(appId);
103
+ try {
104
+ const url = getAppUrl(appId);
105
+ // Skip if already loaded this URL
106
+ if (loadedUrls.has(url)) {
107
+ const registration = registry.get(appId);
108
+ if (registration) {
109
+ onLoadEnd === null || onLoadEnd === void 0 ? void 0 : onLoadEnd(appId, true);
110
+ return { appId, success: true, manifest: registration.manifest };
111
+ }
112
+ }
113
+ // Create timeout promise
114
+ const timeoutPromise = new Promise((_, reject) => {
115
+ setTimeout(() => reject(new Error(`Timeout loading app: ${appId}`)), timeout);
116
+ });
117
+ // Fetch and execute the app bundle
118
+ const loadPromise = loadAppBundle(url, appId);
119
+ await Promise.race([loadPromise, timeoutPromise]);
120
+ loadedUrls.add(url);
121
+ // Get the registered manifest
122
+ const registration = registry.get(appId);
123
+ if (!registration) {
124
+ throw new Error(`App ${appId} did not register after loading`);
125
+ }
126
+ onLoadEnd === null || onLoadEnd === void 0 ? void 0 : onLoadEnd(appId, true);
127
+ return { appId, success: true, manifest: registration.manifest };
128
+ }
129
+ catch (error) {
130
+ const errorMessage = error instanceof Error ? error.message : String(error);
131
+ onLoadEnd === null || onLoadEnd === void 0 ? void 0 : onLoadEnd(appId, false, errorMessage);
132
+ return { appId, success: false, error: errorMessage };
133
+ }
134
+ finally {
135
+ loadingPromises.delete(appId);
136
+ }
137
+ })();
138
+ loadingPromises.set(appId, loadPromise);
139
+ return loadPromise;
140
+ }
141
+ /**
142
+ * Load an app bundle from a URL.
143
+ */
144
+ async function loadAppBundle(url, appId) {
145
+ var _a;
146
+ // For browser environments, we use dynamic import or script loading
147
+ if (typeof window !== "undefined") {
148
+ // Try dynamic import first (for ES modules)
149
+ try {
150
+ const module = await import(/* webpackIgnore: true */ url);
151
+ // The module should export a manifest and optionally auto-register
152
+ if (module.manifest) {
153
+ registry.register(module.manifest);
154
+ }
155
+ else if ((_a = module.default) === null || _a === void 0 ? void 0 : _a.manifest) {
156
+ registry.register(module.default.manifest);
157
+ }
158
+ else if (module.default) {
159
+ // If module.default is the manifest itself
160
+ registry.register(module.default);
161
+ }
162
+ return;
163
+ }
164
+ catch {
165
+ // Fall back to script tag loading for UMD bundles
166
+ }
167
+ // Script tag loading for UMD bundles
168
+ return new Promise((resolve, reject) => {
169
+ const script = document.createElement("script");
170
+ script.src = url;
171
+ script.async = true;
172
+ script.onload = () => {
173
+ // UMD bundles should register themselves via global
174
+ const registered = registry.get(appId);
175
+ if (registered) {
176
+ resolve();
177
+ }
178
+ else {
179
+ reject(new Error(`App ${appId} did not self-register`));
180
+ }
181
+ };
182
+ script.onerror = () => {
183
+ reject(new Error(`Failed to load app script: ${url}`));
184
+ };
185
+ document.head.appendChild(script);
186
+ });
187
+ }
188
+ // For SSR/Node environments, we can't dynamically load apps
189
+ throw new Error("Dynamic app loading not supported in SSR");
190
+ }
191
+ /**
192
+ * Analyze config to determine which apps need to be loaded.
193
+ */
194
+ function getRequiredApps(config) {
195
+ var _a;
196
+ const appIds = new Set();
197
+ // Check explicit app references
198
+ if (config.apps) {
199
+ for (const appId of config.apps) {
200
+ appIds.add(appId);
201
+ }
202
+ }
203
+ // Check action kinds for namespaced actions
204
+ if (config.actions) {
205
+ for (const action of config.actions) {
206
+ const appId = getAppIdFromActionKind(action.kind);
207
+ if (appId) {
208
+ appIds.add(appId);
209
+ }
210
+ // Also check core:mountWidget actions for widget namespaces
211
+ if (action.kind === "core:mountWidget") {
212
+ const widgetId = (_a = action.widget) === null || _a === void 0 ? void 0 : _a.widgetId;
213
+ if (widgetId) {
214
+ const widgetAppId = getAppIdFromWidgetId(widgetId);
215
+ if (widgetAppId) {
216
+ appIds.add(widgetAppId);
217
+ }
218
+ }
219
+ }
220
+ }
221
+ }
222
+ return Array.from(appIds);
223
+ }
224
+ /**
225
+ * Load all apps required by a config.
226
+ */
227
+ async function loadAppsForConfig(config) {
228
+ const requiredApps = getRequiredApps(config);
229
+ if (requiredApps.length === 0) {
230
+ return [];
231
+ }
232
+ // Load all apps in parallel
233
+ const results = await Promise.all(requiredApps.map((appId) => loadApp(appId)));
234
+ return results;
235
+ }
236
+ /**
237
+ * Preload apps without activating them.
238
+ */
239
+ async function preloadApps(appIds) {
240
+ return Promise.all(appIds.map((appId) => loadApp(appId)));
241
+ }
242
+ return {
243
+ loadApp,
244
+ loadAppsForConfig,
245
+ preloadApps,
246
+ getRequiredApps,
247
+ getAppUrl,
248
+ };
249
+ }
250
+ //# sourceMappingURL=AppLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppLoader.js","sourceRoot":"","sources":["../../src/apps/AppLoader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * App Registry
3
+ *
4
+ * Central registry for managing SynOS apps.
5
+ * Handles app registration, activation, deactivation, and lifecycle management.
6
+ */
7
+ import type { SmartCanvasRuntime } from "../runtime";
8
+ import type { AppManifest, AppRegistration, AppRegistryEvent } from "./types";
9
+ /**
10
+ * Callback for app registry events.
11
+ */
12
+ export type AppRegistryEventCallback = (event: AppRegistryEvent) => void;
13
+ /**
14
+ * App registry for managing SynOS apps.
15
+ */
16
+ export declare class AppRegistry {
17
+ private apps;
18
+ private eventListeners;
19
+ private runtime;
20
+ /**
21
+ * Bind the registry to a runtime instance.
22
+ * Must be called before apps can be activated.
23
+ */
24
+ bind(runtime: SmartCanvasRuntime): void;
25
+ /**
26
+ * Unbind from the current runtime.
27
+ * Deactivates all active apps first.
28
+ */
29
+ unbind(): Promise<void>;
30
+ /**
31
+ * Register an app.
32
+ *
33
+ * Registration makes the app available but does not activate it.
34
+ * Call activate() to start the app's runtime extensions.
35
+ */
36
+ register(manifest: AppManifest): AppRegistration;
37
+ /**
38
+ * Activate an app.
39
+ *
40
+ * Activating an app:
41
+ * 1. Creates an AppContext for sandboxed runtime access
42
+ * 2. Registers the app's actions with ExecutorRegistry
43
+ * 3. Registers the app's widgets with WidgetRegistry
44
+ * 4. Sets up the app's event handlers
45
+ */
46
+ activate(appId: string): Promise<void>;
47
+ /**
48
+ * Deactivate an app.
49
+ *
50
+ * Deactivating an app:
51
+ * 1. Runs the cleanup function
52
+ * 2. Unregisters all actions and widgets
53
+ * 3. Removes event handlers
54
+ */
55
+ deactivate(appId: string): Promise<void>;
56
+ /**
57
+ * Unregister an app.
58
+ *
59
+ * The app must be inactive before it can be unregistered.
60
+ */
61
+ unregister(appId: string): Promise<void>;
62
+ /**
63
+ * Get an app registration.
64
+ */
65
+ get(appId: string): AppRegistration | undefined;
66
+ /**
67
+ * Check if an app is registered.
68
+ */
69
+ has(appId: string): boolean;
70
+ /**
71
+ * Check if an app is active.
72
+ */
73
+ isActive(appId: string): boolean;
74
+ /**
75
+ * List all registered apps.
76
+ */
77
+ list(): AppRegistration[];
78
+ /**
79
+ * List all active apps.
80
+ */
81
+ listActive(): AppRegistration[];
82
+ /**
83
+ * List all apps with editor modules.
84
+ */
85
+ listEditable(): AppRegistration[];
86
+ /**
87
+ * Subscribe to registry events.
88
+ */
89
+ subscribe(callback: AppRegistryEventCallback): () => void;
90
+ /**
91
+ * Emit an event to all listeners.
92
+ */
93
+ private emit;
94
+ /**
95
+ * Clean up all apps.
96
+ */
97
+ destroy(): Promise<void>;
98
+ }
99
+ /**
100
+ * Default singleton instance of AppRegistry.
101
+ */
102
+ export declare const appRegistry: AppRegistry;
@@ -0,0 +1,317 @@
1
+ /**
2
+ * App Registry
3
+ *
4
+ * Central registry for managing SynOS apps.
5
+ * Handles app registration, activation, deactivation, and lifecycle management.
6
+ */
7
+ import { createAppContext, cleanupAppContext } from "./AppContext";
8
+ /**
9
+ * App registry for managing SynOS apps.
10
+ */
11
+ export class AppRegistry {
12
+ constructor() {
13
+ this.apps = new Map();
14
+ this.eventListeners = new Set();
15
+ this.runtime = null;
16
+ }
17
+ /**
18
+ * Bind the registry to a runtime instance.
19
+ * Must be called before apps can be activated.
20
+ */
21
+ bind(runtime) {
22
+ this.runtime = runtime;
23
+ }
24
+ /**
25
+ * Unbind from the current runtime.
26
+ * Deactivates all active apps first.
27
+ */
28
+ async unbind() {
29
+ // Deactivate all active apps
30
+ for (const [appId, registration] of this.apps) {
31
+ if (registration.state === "active") {
32
+ await this.deactivate(appId);
33
+ }
34
+ }
35
+ this.runtime = null;
36
+ }
37
+ /**
38
+ * Register an app.
39
+ *
40
+ * Registration makes the app available but does not activate it.
41
+ * Call activate() to start the app's runtime extensions.
42
+ */
43
+ register(manifest) {
44
+ // Validate manifest
45
+ if (!manifest.id || typeof manifest.id !== "string") {
46
+ throw new Error("App manifest must have an 'id' property");
47
+ }
48
+ if (!manifest.version || typeof manifest.version !== "string") {
49
+ throw new Error("App manifest must have a 'version' property");
50
+ }
51
+ if (!manifest.name || typeof manifest.name !== "string") {
52
+ throw new Error("App manifest must have a 'name' property");
53
+ }
54
+ // Check for existing registration
55
+ if (this.apps.has(manifest.id)) {
56
+ const existing = this.apps.get(manifest.id);
57
+ if (existing.state === "active") {
58
+ throw new Error(`Cannot re-register active app: ${manifest.id}`);
59
+ }
60
+ console.warn(`[AppRegistry] Overriding existing app registration: ${manifest.id}`);
61
+ }
62
+ // Create registration
63
+ const registration = {
64
+ manifest,
65
+ state: "registered",
66
+ registeredAt: Date.now(),
67
+ };
68
+ this.apps.set(manifest.id, registration);
69
+ // Emit event
70
+ this.emit({
71
+ type: "app:registered",
72
+ appId: manifest.id,
73
+ manifest,
74
+ });
75
+ return registration;
76
+ }
77
+ /**
78
+ * Activate an app.
79
+ *
80
+ * Activating an app:
81
+ * 1. Creates an AppContext for sandboxed runtime access
82
+ * 2. Registers the app's actions with ExecutorRegistry
83
+ * 3. Registers the app's widgets with WidgetRegistry
84
+ * 4. Sets up the app's event handlers
85
+ */
86
+ async activate(appId) {
87
+ var _a;
88
+ const registration = this.apps.get(appId);
89
+ if (!registration) {
90
+ throw new Error(`App not registered: ${appId}`);
91
+ }
92
+ if (registration.state === "active") {
93
+ console.warn(`[AppRegistry] App already active: ${appId}`);
94
+ return;
95
+ }
96
+ if (!this.runtime) {
97
+ throw new Error("AppRegistry not bound to a runtime. Call bind() first.");
98
+ }
99
+ // Check dependencies
100
+ if (registration.manifest.dependencies) {
101
+ for (const depId of registration.manifest.dependencies) {
102
+ const dep = this.apps.get(depId);
103
+ if (!dep || dep.state !== "active") {
104
+ throw new Error(`App ${appId} depends on ${depId}, which is not active`);
105
+ }
106
+ }
107
+ }
108
+ // Update state
109
+ registration.state = "activating";
110
+ try {
111
+ // Create app context
112
+ const isBuiltIn = ((_a = registration.manifest.metadata) === null || _a === void 0 ? void 0 : _a.isBuiltIn) === true;
113
+ const context = createAppContext({
114
+ appId,
115
+ runtime: this.runtime,
116
+ isBuiltIn,
117
+ });
118
+ // Register runtime extensions
119
+ const { runtime: runtimeExtensions } = registration.manifest;
120
+ const cleanupFns = [];
121
+ if (runtimeExtensions) {
122
+ // Register actions
123
+ if (runtimeExtensions.actions) {
124
+ for (const actionDef of runtimeExtensions.actions) {
125
+ context.registerAction(actionDef);
126
+ }
127
+ }
128
+ // Register widgets
129
+ if (runtimeExtensions.widgets) {
130
+ for (const widgetDef of runtimeExtensions.widgets) {
131
+ context.registerWidget(widgetDef);
132
+ }
133
+ }
134
+ // Set up event handlers
135
+ if (runtimeExtensions.events) {
136
+ for (const handler of runtimeExtensions.events) {
137
+ const unsubscribe = this.runtime.events.subscribe((event) => {
138
+ if (handler.names.includes(event.name)) {
139
+ const eventContext = {
140
+ appId,
141
+ state: context.state,
142
+ telemetry: context.telemetry,
143
+ surfaces: context.surfaces,
144
+ };
145
+ try {
146
+ handler.handler(event, eventContext);
147
+ }
148
+ catch (error) {
149
+ console.error(`[AppRegistry] Event handler error in ${appId}:`, error);
150
+ }
151
+ }
152
+ });
153
+ cleanupFns.push(unsubscribe);
154
+ }
155
+ }
156
+ }
157
+ // Store cleanup function
158
+ registration.cleanup = async () => {
159
+ // Run cleanup functions
160
+ for (const fn of cleanupFns) {
161
+ try {
162
+ await fn();
163
+ }
164
+ catch (error) {
165
+ console.error(`[AppRegistry] Cleanup error in ${appId}:`, error);
166
+ }
167
+ }
168
+ // Clean up app context resources
169
+ cleanupAppContext(appId, this.runtime);
170
+ };
171
+ // Update state
172
+ registration.state = "active";
173
+ registration.activatedAt = Date.now();
174
+ // Emit event
175
+ this.emit({ type: "app:activated", appId });
176
+ }
177
+ catch (error) {
178
+ registration.state = "error";
179
+ registration.error = String(error);
180
+ this.emit({ type: "app:error", appId, error: String(error) });
181
+ throw error;
182
+ }
183
+ }
184
+ /**
185
+ * Deactivate an app.
186
+ *
187
+ * Deactivating an app:
188
+ * 1. Runs the cleanup function
189
+ * 2. Unregisters all actions and widgets
190
+ * 3. Removes event handlers
191
+ */
192
+ async deactivate(appId) {
193
+ var _a;
194
+ const registration = this.apps.get(appId);
195
+ if (!registration) {
196
+ throw new Error(`App not registered: ${appId}`);
197
+ }
198
+ if (registration.state !== "active") {
199
+ console.warn(`[AppRegistry] App not active: ${appId}`);
200
+ return;
201
+ }
202
+ // Check if any active apps depend on this one
203
+ for (const [otherId, other] of this.apps) {
204
+ if (other.state === "active" && ((_a = other.manifest.dependencies) === null || _a === void 0 ? void 0 : _a.includes(appId))) {
205
+ throw new Error(`Cannot deactivate ${appId}: app ${otherId} depends on it`);
206
+ }
207
+ }
208
+ // Update state
209
+ registration.state = "deactivating";
210
+ try {
211
+ // Run cleanup
212
+ if (registration.cleanup) {
213
+ await registration.cleanup();
214
+ registration.cleanup = undefined;
215
+ }
216
+ // Update state
217
+ registration.state = "inactive";
218
+ // Emit event
219
+ this.emit({ type: "app:deactivated", appId });
220
+ }
221
+ catch (error) {
222
+ registration.state = "error";
223
+ registration.error = String(error);
224
+ this.emit({ type: "app:error", appId, error: String(error) });
225
+ throw error;
226
+ }
227
+ }
228
+ /**
229
+ * Unregister an app.
230
+ *
231
+ * The app must be inactive before it can be unregistered.
232
+ */
233
+ async unregister(appId) {
234
+ const registration = this.apps.get(appId);
235
+ if (!registration) {
236
+ return;
237
+ }
238
+ if (registration.state === "active") {
239
+ await this.deactivate(appId);
240
+ }
241
+ this.apps.delete(appId);
242
+ // Emit event
243
+ this.emit({ type: "app:unregistered", appId });
244
+ }
245
+ /**
246
+ * Get an app registration.
247
+ */
248
+ get(appId) {
249
+ return this.apps.get(appId);
250
+ }
251
+ /**
252
+ * Check if an app is registered.
253
+ */
254
+ has(appId) {
255
+ return this.apps.has(appId);
256
+ }
257
+ /**
258
+ * Check if an app is active.
259
+ */
260
+ isActive(appId) {
261
+ const registration = this.apps.get(appId);
262
+ return (registration === null || registration === void 0 ? void 0 : registration.state) === "active";
263
+ }
264
+ /**
265
+ * List all registered apps.
266
+ */
267
+ list() {
268
+ return Array.from(this.apps.values());
269
+ }
270
+ /**
271
+ * List all active apps.
272
+ */
273
+ listActive() {
274
+ return Array.from(this.apps.values()).filter((r) => r.state === "active");
275
+ }
276
+ /**
277
+ * List all apps with editor modules.
278
+ */
279
+ listEditable() {
280
+ return Array.from(this.apps.values()).filter((r) => r.manifest.editor !== undefined);
281
+ }
282
+ /**
283
+ * Subscribe to registry events.
284
+ */
285
+ subscribe(callback) {
286
+ this.eventListeners.add(callback);
287
+ return () => {
288
+ this.eventListeners.delete(callback);
289
+ };
290
+ }
291
+ /**
292
+ * Emit an event to all listeners.
293
+ */
294
+ emit(event) {
295
+ for (const listener of this.eventListeners) {
296
+ try {
297
+ listener(event);
298
+ }
299
+ catch (error) {
300
+ console.error("[AppRegistry] Event listener error:", error);
301
+ }
302
+ }
303
+ }
304
+ /**
305
+ * Clean up all apps.
306
+ */
307
+ async destroy() {
308
+ await this.unbind();
309
+ this.apps.clear();
310
+ this.eventListeners.clear();
311
+ }
312
+ }
313
+ /**
314
+ * Default singleton instance of AppRegistry.
315
+ */
316
+ export const appRegistry = new AppRegistry();
317
+ //# sourceMappingURL=AppRegistry.js.map