@go-go-golems/os-scripting 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -13,6 +13,28 @@ npm install react react-dom react-redux @reduxjs/toolkit
13
13
 
14
14
  `react`, `react-dom`, `react-redux`, and `@reduxjs/toolkit` are peer dependencies.
15
15
 
16
+ ## Bundler note
17
+
18
+ Starting with `@go-go-golems/os-scripting@0.1.1`, package-internal QuickJS bootstrap code is shipped as ordinary generated JavaScript string modules. Consumers do **not** need package-specific Vite dependency-optimization workarounds such as:
19
+
20
+ ```ts
21
+ optimizeDeps: {
22
+ exclude: ['@go-go-golems/os-scripting'],
23
+ include: ['debug'],
24
+ }
25
+ ```
26
+
27
+ If your own application imports local VM bundle files with Vite raw imports, for example `import code from './bundle.vm.js?raw'`, keep a local declaration such as:
28
+
29
+ ```ts
30
+ declare module '*.vm.js?raw' {
31
+ const source: string;
32
+ export default source;
33
+ }
34
+ ```
35
+
36
+ That declaration is for your app-authored VM bundles only; it is not required because of package internals.
37
+
16
38
  ## Main exports
17
39
 
18
40
  ```ts
@@ -65,25 +87,42 @@ export function AppProviders({ children }: { children: React.ReactNode }) {
65
87
  }
66
88
  ```
67
89
 
68
- Use `createAppStore` when rendering VM surfaces. It includes `runtimeSessions`, runtime lifecycle middleware, and artifact projection middleware. For shell-only apps that never render VM surfaces, `createLauncherStore` from `@go-go-golems/os-shell` is lighter.
90
+ Use `createAppStore` when rendering VM surfaces. It includes `runtimeSessions`, `notifications`, runtime lifecycle middleware, and artifact projection middleware. For shell-only apps that never render VM surfaces, `createLauncherStore` from `@go-go-golems/os-shell` is lighter.
69
91
 
70
92
  ## Minimal surface host
71
93
 
72
94
  ```tsx
73
- import { RuntimeSurfaceSessionHost } from '@go-go-golems/os-scripting';
95
+ import { clearToast, selectToast, Toast } from '@go-go-golems/os-core';
96
+ import { RuntimeSurfaceSessionHost, createAppStore } from '@go-go-golems/os-scripting';
74
97
  import type { RuntimeBundleDefinition } from '@go-go-golems/os-shell';
98
+ import { Provider, useDispatch, useSelector } from 'react-redux';
99
+
100
+ const { store } = createAppStore({});
101
+
102
+ function RuntimeToastHost() {
103
+ const dispatch = useDispatch();
104
+ const toast = useSelector((state) => selectToast(state as any));
105
+
106
+ if (!toast) return null;
107
+ return <Toast message={toast} onDone={() => dispatch(clearToast())} />;
108
+ }
75
109
 
76
110
  export function RuntimeWindow({ bundle }: { bundle: RuntimeBundleDefinition }) {
77
111
  return (
78
- <RuntimeSurfaceSessionHost
79
- windowId="window:demo"
80
- sessionId="session:demo"
81
- bundle={bundle}
82
- />
112
+ <Provider store={store}>
113
+ <RuntimeSurfaceSessionHost
114
+ windowId="window:demo"
115
+ sessionId="session:demo"
116
+ bundle={bundle}
117
+ />
118
+ <RuntimeToastHost />
119
+ </Provider>
83
120
  );
84
121
  }
85
122
  ```
86
123
 
124
+ `RuntimeSurfaceSessionHost` routes host effects such as `notify.show` into Redux. Mount host chrome such as `Toast` inside the same `Provider` if your runtime bundles use notification capabilities.
125
+
87
126
  ## Runtime bundle shape
88
127
 
89
128
  Host TypeScript:
@@ -100,7 +139,7 @@ export const BUNDLE: RuntimeBundleDefinition = {
100
139
  plugin: {
101
140
  packageIds: ['ui'],
102
141
  bundleCode,
103
- capabilities: { domain: [], system: [] },
142
+ capabilities: { domain: [], system: ['notify.show'] },
104
143
  },
105
144
  surfaces: {
106
145
  home: {
@@ -128,8 +167,17 @@ defineRuntimeBundle(({ ui }) => ({
128
167
  return ui.panel([
129
168
  ui.text('Hello from QuickJS'),
130
169
  ui.text('Session: ' + state.self.sessionId),
170
+ ui.button('Notify host', { onClick: { handler: 'notify' } }),
131
171
  ]);
132
172
  },
173
+ handlers: {
174
+ notify(ctx) {
175
+ ctx.dispatch({
176
+ type: 'notify.show',
177
+ payload: { message: 'Hello from the VM' },
178
+ });
179
+ },
180
+ },
133
181
  },
134
182
  },
135
183
  }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-go-golems/os-scripting",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "description": "QuickJS runtime, plugin, and REPL-session support for go-go-os.",
6
6
  "keywords": [
@@ -1,7 +1,7 @@
1
1
  import { validateRuntimeActions } from './intentSchema';
2
2
  import { getRuntimePackageOrThrow, resolveRuntimePackageInstallOrder } from '../runtime-packages';
3
3
  import { getRuntimeSurfaceTypeOrThrow } from '../runtime-packs';
4
- import stackBootstrapSource from './stack-bootstrap.vm.js?raw';
4
+ import stackBootstrapSource from './stackBootstrapSource.generated';
5
5
  import { toJsLiteral } from './quickJsSessionCore';
6
6
  import { JsSessionService } from './jsSessionService';
7
7
  const DEFAULT_OPTIONS = {
@@ -0,0 +1,2 @@
1
+ declare const source = "const __runtimePackageState =\n globalThis.__runtimePackageState && typeof globalThis.__runtimePackageState === 'object'\n ? globalThis.__runtimePackageState\n : {\n packageIds: [],\n apis: {},\n };\n\nglobalThis.__runtimePackageState = __runtimePackageState;\n\nlet __runtimeBundle = null;\nlet __runtimeActions = [];\n\nfunction isPlainObject(value) {\n return value && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction mergeRuntimeApiValue(existingValue, incomingValue) {\n if (isPlainObject(existingValue) && isPlainObject(incomingValue)) {\n const merged = { ...existingValue };\n for (const [key, value] of Object.entries(incomingValue)) {\n merged[key] = mergeRuntimeApiValue(merged[key], value);\n }\n return merged;\n }\n\n return incomingValue;\n}\n\nfunction registerRuntimePackageApi(packageId, apiExports) {\n const normalizedPackageId = String(packageId || '').trim();\n if (!normalizedPackageId) {\n throw new Error('registerRuntimePackageApi requires a package id');\n }\n\n if (!__runtimePackageState.packageIds.includes(normalizedPackageId)) {\n __runtimePackageState.packageIds.push(normalizedPackageId);\n }\n\n if (!isPlainObject(apiExports)) {\n return;\n }\n\n for (const [exportName, exportValue] of Object.entries(apiExports)) {\n const mergedValue = mergeRuntimeApiValue(__runtimePackageState.apis[exportName], exportValue);\n __runtimePackageState.apis[exportName] = mergedValue;\n globalThis[exportName] = mergedValue;\n }\n}\n\nfunction collectRuntimePackageApis() {\n return { ...__runtimePackageState.apis };\n}\n\nfunction defineRuntimeBundleImpl(factory) {\n if (typeof factory !== 'function') {\n throw new Error('defineRuntimeBundle requires a factory function');\n }\n\n __runtimeBundle = factory(collectRuntimePackageApis());\n}\n\nfunction assertStackBundleReady() {\n if (!__runtimeBundle || typeof __runtimeBundle !== 'object') {\n throw new Error('Runtime bundle did not register via defineRuntimeBundle');\n }\n}\n\nfunction assertSurfacesMap() {\n assertStackBundleReady();\n if (!__runtimeBundle.surfaces || typeof __runtimeBundle.surfaces !== 'object') {\n __runtimeBundle.surfaces = {};\n }\n return __runtimeBundle.surfaces;\n}\n\nfunction normalizeRuntimeSurfacePackId(surfaceId, packId) {\n const normalizedPackId = typeof packId === 'string' ? packId.trim() : '';\n if (!normalizedPackId) {\n throw new Error('Runtime surface packId is required for surface: ' + String(surfaceId));\n }\n return normalizedPackId;\n}\n\nfunction normalizeRuntimeSurfaceDefinition(surfaceId, definitionOrFactory, packId) {\n const normalizedPackId = normalizeRuntimeSurfacePackId(surfaceId, packId);\n const definition =\n typeof definitionOrFactory === 'function'\n ? definitionOrFactory(collectRuntimePackageApis())\n : definitionOrFactory;\n\n if (!definition || typeof definition !== 'object') {\n throw new Error('Runtime surface definition must be an object for surface: ' + String(surfaceId));\n }\n\n if (typeof definition.render !== 'function') {\n throw new Error('Runtime surface definition render() is required for surface: ' + String(surfaceId));\n }\n\n if (definition.handlers !== undefined) {\n if (!definition.handlers || typeof definition.handlers !== 'object' || Array.isArray(definition.handlers)) {\n throw new Error('Runtime surface definition handlers must be an object for surface: ' + String(surfaceId));\n }\n } else {\n definition.handlers = {};\n }\n\n definition.packId = normalizedPackId;\n return definition;\n}\n\nfunction ensureRuntimeSurfaceRecord(surfaceId) {\n const surfaces = assertSurfacesMap();\n const key = String(surfaceId);\n const existing = surfaces[key];\n if (!existing || typeof existing !== 'object') {\n surfaces[key] = {\n handlers: {},\n };\n } else if (!existing.handlers || typeof existing.handlers !== 'object') {\n existing.handlers = {};\n }\n return surfaces[key];\n}\n\nfunction defineRuntimeSurfaceImpl(surfaceId, definitionOrFactory, packId) {\n const surfaces = assertSurfacesMap();\n const key = String(surfaceId);\n surfaces[key] = normalizeRuntimeSurfaceDefinition(key, definitionOrFactory, packId);\n}\n\nfunction defineRuntimeSurfaceRenderImpl(surfaceId, renderFn) {\n if (typeof renderFn !== 'function') {\n throw new Error('defineRuntimeSurfaceRender requires a render function');\n }\n\n const surface = ensureRuntimeSurfaceRecord(surfaceId);\n surface.render = renderFn;\n}\n\nfunction defineRuntimeSurfaceHandlerImpl(surfaceId, handlerName, handlerFn) {\n if (typeof handlerFn !== 'function') {\n throw new Error('defineRuntimeSurfaceHandler requires a handler function');\n }\n\n const surface = ensureRuntimeSurfaceRecord(surfaceId);\n surface.handlers[String(handlerName)] = handlerFn;\n}\n\nglobalThis.defineRuntimeBundle = defineRuntimeBundleImpl;\nglobalThis.defineRuntimeSurface = defineRuntimeSurfaceImpl;\nglobalThis.defineRuntimeSurfaceRender = defineRuntimeSurfaceRenderImpl;\nglobalThis.defineRuntimeSurfaceHandler = defineRuntimeSurfaceHandlerImpl;\nglobalThis.registerRuntimePackageApi = registerRuntimePackageApi;\n\nglobalThis.__runtimeBundleHost = {\n getMeta() {\n if (!__runtimeBundle || typeof __runtimeBundle !== 'object') {\n throw new Error('Runtime bundle did not register via defineRuntimeBundle');\n }\n\n if (!__runtimeBundle.surfaces || typeof __runtimeBundle.surfaces !== 'object') {\n throw new Error('Runtime bundle surfaces must be an object');\n }\n\n return {\n declaredId: typeof __runtimeBundle.id === 'string' ? __runtimeBundle.id : undefined,\n title: String(__runtimeBundle.title ?? 'Untitled Bundle'),\n description: typeof __runtimeBundle.description === 'string' ? __runtimeBundle.description : undefined,\n packageIds: Array.isArray(__runtimeBundle.packageIds)\n ? __runtimeBundle.packageIds.map((packageId) => String(packageId)).filter((packageId) => packageId.length > 0)\n : [],\n initialSessionState: __runtimeBundle.initialSessionState,\n initialSurfaceState: __runtimeBundle.initialSurfaceState,\n surfaces: Object.keys(__runtimeBundle.surfaces),\n surfaceTypes: Object.fromEntries(\n Object.entries(__runtimeBundle.surfaces).map(([key, surface]) => [\n key,\n normalizeRuntimeSurfacePackId(key, surface?.packId),\n ]),\n ),\n };\n },\n\n renderRuntimeSurface(surfaceId, state) {\n const surface = __runtimeBundle?.surfaces?.[surfaceId];\n if (!surface || typeof surface.render !== 'function') {\n throw new Error('Runtime surface not found or render() is missing: ' + String(surfaceId));\n }\n\n return surface.render({ state });\n },\n\n eventRuntimeSurface(surfaceId, handlerName, args, state) {\n const surface = __runtimeBundle?.surfaces?.[surfaceId];\n if (!surface) {\n throw new Error('Runtime surface not found: ' + String(surfaceId));\n }\n\n const handler = surface.handlers?.[handlerName];\n if (typeof handler !== 'function') {\n throw new Error('Handler not found: ' + String(handlerName));\n }\n\n __runtimeActions = [];\n\n const dispatch = (action) => {\n __runtimeActions.push(action);\n };\n\n handler(\n {\n state,\n dispatch,\n },\n args\n );\n\n return __runtimeActions.slice();\n },\n\n defineRuntimeSurface(surfaceId, definitionOrFactory, packId) {\n defineRuntimeSurfaceImpl(surfaceId, definitionOrFactory, packId);\n return this.getMeta();\n },\n\n defineRuntimeSurfaceRender(surfaceId, renderFn) {\n defineRuntimeSurfaceRenderImpl(surfaceId, renderFn);\n return this.getMeta();\n },\n\n defineRuntimeSurfaceHandler(surfaceId, handlerName, handlerFn) {\n defineRuntimeSurfaceHandlerImpl(surfaceId, handlerName, handlerFn);\n return this.getMeta();\n },\n};\n";
2
+ export default source;
@@ -0,0 +1,5 @@
1
+ // Generated by scripts/packages/generate-vm-source-modules.mjs.
2
+ // Source: stack-bootstrap.vm.js
3
+ // Do not edit by hand.
4
+ const source = "const __runtimePackageState =\n globalThis.__runtimePackageState && typeof globalThis.__runtimePackageState === 'object'\n ? globalThis.__runtimePackageState\n : {\n packageIds: [],\n apis: {},\n };\n\nglobalThis.__runtimePackageState = __runtimePackageState;\n\nlet __runtimeBundle = null;\nlet __runtimeActions = [];\n\nfunction isPlainObject(value) {\n return value && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction mergeRuntimeApiValue(existingValue, incomingValue) {\n if (isPlainObject(existingValue) && isPlainObject(incomingValue)) {\n const merged = { ...existingValue };\n for (const [key, value] of Object.entries(incomingValue)) {\n merged[key] = mergeRuntimeApiValue(merged[key], value);\n }\n return merged;\n }\n\n return incomingValue;\n}\n\nfunction registerRuntimePackageApi(packageId, apiExports) {\n const normalizedPackageId = String(packageId || '').trim();\n if (!normalizedPackageId) {\n throw new Error('registerRuntimePackageApi requires a package id');\n }\n\n if (!__runtimePackageState.packageIds.includes(normalizedPackageId)) {\n __runtimePackageState.packageIds.push(normalizedPackageId);\n }\n\n if (!isPlainObject(apiExports)) {\n return;\n }\n\n for (const [exportName, exportValue] of Object.entries(apiExports)) {\n const mergedValue = mergeRuntimeApiValue(__runtimePackageState.apis[exportName], exportValue);\n __runtimePackageState.apis[exportName] = mergedValue;\n globalThis[exportName] = mergedValue;\n }\n}\n\nfunction collectRuntimePackageApis() {\n return { ...__runtimePackageState.apis };\n}\n\nfunction defineRuntimeBundleImpl(factory) {\n if (typeof factory !== 'function') {\n throw new Error('defineRuntimeBundle requires a factory function');\n }\n\n __runtimeBundle = factory(collectRuntimePackageApis());\n}\n\nfunction assertStackBundleReady() {\n if (!__runtimeBundle || typeof __runtimeBundle !== 'object') {\n throw new Error('Runtime bundle did not register via defineRuntimeBundle');\n }\n}\n\nfunction assertSurfacesMap() {\n assertStackBundleReady();\n if (!__runtimeBundle.surfaces || typeof __runtimeBundle.surfaces !== 'object') {\n __runtimeBundle.surfaces = {};\n }\n return __runtimeBundle.surfaces;\n}\n\nfunction normalizeRuntimeSurfacePackId(surfaceId, packId) {\n const normalizedPackId = typeof packId === 'string' ? packId.trim() : '';\n if (!normalizedPackId) {\n throw new Error('Runtime surface packId is required for surface: ' + String(surfaceId));\n }\n return normalizedPackId;\n}\n\nfunction normalizeRuntimeSurfaceDefinition(surfaceId, definitionOrFactory, packId) {\n const normalizedPackId = normalizeRuntimeSurfacePackId(surfaceId, packId);\n const definition =\n typeof definitionOrFactory === 'function'\n ? definitionOrFactory(collectRuntimePackageApis())\n : definitionOrFactory;\n\n if (!definition || typeof definition !== 'object') {\n throw new Error('Runtime surface definition must be an object for surface: ' + String(surfaceId));\n }\n\n if (typeof definition.render !== 'function') {\n throw new Error('Runtime surface definition render() is required for surface: ' + String(surfaceId));\n }\n\n if (definition.handlers !== undefined) {\n if (!definition.handlers || typeof definition.handlers !== 'object' || Array.isArray(definition.handlers)) {\n throw new Error('Runtime surface definition handlers must be an object for surface: ' + String(surfaceId));\n }\n } else {\n definition.handlers = {};\n }\n\n definition.packId = normalizedPackId;\n return definition;\n}\n\nfunction ensureRuntimeSurfaceRecord(surfaceId) {\n const surfaces = assertSurfacesMap();\n const key = String(surfaceId);\n const existing = surfaces[key];\n if (!existing || typeof existing !== 'object') {\n surfaces[key] = {\n handlers: {},\n };\n } else if (!existing.handlers || typeof existing.handlers !== 'object') {\n existing.handlers = {};\n }\n return surfaces[key];\n}\n\nfunction defineRuntimeSurfaceImpl(surfaceId, definitionOrFactory, packId) {\n const surfaces = assertSurfacesMap();\n const key = String(surfaceId);\n surfaces[key] = normalizeRuntimeSurfaceDefinition(key, definitionOrFactory, packId);\n}\n\nfunction defineRuntimeSurfaceRenderImpl(surfaceId, renderFn) {\n if (typeof renderFn !== 'function') {\n throw new Error('defineRuntimeSurfaceRender requires a render function');\n }\n\n const surface = ensureRuntimeSurfaceRecord(surfaceId);\n surface.render = renderFn;\n}\n\nfunction defineRuntimeSurfaceHandlerImpl(surfaceId, handlerName, handlerFn) {\n if (typeof handlerFn !== 'function') {\n throw new Error('defineRuntimeSurfaceHandler requires a handler function');\n }\n\n const surface = ensureRuntimeSurfaceRecord(surfaceId);\n surface.handlers[String(handlerName)] = handlerFn;\n}\n\nglobalThis.defineRuntimeBundle = defineRuntimeBundleImpl;\nglobalThis.defineRuntimeSurface = defineRuntimeSurfaceImpl;\nglobalThis.defineRuntimeSurfaceRender = defineRuntimeSurfaceRenderImpl;\nglobalThis.defineRuntimeSurfaceHandler = defineRuntimeSurfaceHandlerImpl;\nglobalThis.registerRuntimePackageApi = registerRuntimePackageApi;\n\nglobalThis.__runtimeBundleHost = {\n getMeta() {\n if (!__runtimeBundle || typeof __runtimeBundle !== 'object') {\n throw new Error('Runtime bundle did not register via defineRuntimeBundle');\n }\n\n if (!__runtimeBundle.surfaces || typeof __runtimeBundle.surfaces !== 'object') {\n throw new Error('Runtime bundle surfaces must be an object');\n }\n\n return {\n declaredId: typeof __runtimeBundle.id === 'string' ? __runtimeBundle.id : undefined,\n title: String(__runtimeBundle.title ?? 'Untitled Bundle'),\n description: typeof __runtimeBundle.description === 'string' ? __runtimeBundle.description : undefined,\n packageIds: Array.isArray(__runtimeBundle.packageIds)\n ? __runtimeBundle.packageIds.map((packageId) => String(packageId)).filter((packageId) => packageId.length > 0)\n : [],\n initialSessionState: __runtimeBundle.initialSessionState,\n initialSurfaceState: __runtimeBundle.initialSurfaceState,\n surfaces: Object.keys(__runtimeBundle.surfaces),\n surfaceTypes: Object.fromEntries(\n Object.entries(__runtimeBundle.surfaces).map(([key, surface]) => [\n key,\n normalizeRuntimeSurfacePackId(key, surface?.packId),\n ]),\n ),\n };\n },\n\n renderRuntimeSurface(surfaceId, state) {\n const surface = __runtimeBundle?.surfaces?.[surfaceId];\n if (!surface || typeof surface.render !== 'function') {\n throw new Error('Runtime surface not found or render() is missing: ' + String(surfaceId));\n }\n\n return surface.render({ state });\n },\n\n eventRuntimeSurface(surfaceId, handlerName, args, state) {\n const surface = __runtimeBundle?.surfaces?.[surfaceId];\n if (!surface) {\n throw new Error('Runtime surface not found: ' + String(surfaceId));\n }\n\n const handler = surface.handlers?.[handlerName];\n if (typeof handler !== 'function') {\n throw new Error('Handler not found: ' + String(handlerName));\n }\n\n __runtimeActions = [];\n\n const dispatch = (action) => {\n __runtimeActions.push(action);\n };\n\n handler(\n {\n state,\n dispatch,\n },\n args\n );\n\n return __runtimeActions.slice();\n },\n\n defineRuntimeSurface(surfaceId, definitionOrFactory, packId) {\n defineRuntimeSurfaceImpl(surfaceId, definitionOrFactory, packId);\n return this.getMeta();\n },\n\n defineRuntimeSurfaceRender(surfaceId, renderFn) {\n defineRuntimeSurfaceRenderImpl(surfaceId, renderFn);\n return this.getMeta();\n },\n\n defineRuntimeSurfaceHandler(surfaceId, handlerName, handlerFn) {\n defineRuntimeSurfaceHandlerImpl(surfaceId, handlerName, handlerFn);\n return this.getMeta();\n },\n};\n";
5
+ export default source;