@casual-simulation/aux-runtime 3.8.2-alpha.19511653187 → 3.10.3-alpha.20787554310
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 +677 -54
- package/package.json +85 -86
- package/runtime/AuxCompiler.d.ts +11 -2
- package/runtime/AuxCompiler.js +44 -31
- package/runtime/AuxCompiler.js.map +1 -1
- package/runtime/AuxDevice.d.ts +11 -0
- package/runtime/AuxGlobalContext.d.ts +7 -0
- package/runtime/AuxGlobalContext.js +3 -0
- package/runtime/AuxGlobalContext.js.map +1 -1
- package/runtime/AuxLibrary.d.ts +61 -6
- package/runtime/AuxLibrary.js +567 -107
- package/runtime/AuxLibrary.js.map +1 -1
- package/runtime/AuxLibraryDefinitions.def +2432 -671
- package/runtime/AuxRuntime.js +51 -46
- package/runtime/AuxRuntime.js.map +1 -1
- package/runtime/RecordsEvents.d.ts +294 -2
- package/runtime/RecordsEvents.js +178 -12
- package/runtime/RecordsEvents.js.map +1 -1
- package/runtime/RuntimeBot.js +1 -1
- package/runtime/RuntimeBot.js.map +1 -1
- package/runtime/Transpiler.d.ts +27 -2
- package/runtime/Transpiler.js +117 -20
- package/runtime/Transpiler.js.map +1 -1
- package/runtime/test/TestScriptBotFactory.js +1 -2
- package/runtime/test/TestScriptBotFactory.js.map +1 -1
package/README.md
CHANGED
|
@@ -1,82 +1,705 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @casual-simulation/aux-runtime
|
|
2
2
|
|
|
3
|
-
[](https://img.shields.io/npm/v/@casual-simulation/aux-runtime.svg)](https://www.npmjs.com/package/@casual-simulation/aux-runtime)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Runtime execution engine for CasualOS. This package provides the infrastructure to compile, execute, and supervise user scripts (bot tags) with full JavaScript support, rich APIs, and performance management.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
`aux-runtime` is the core execution engine that powers CasualOS user scripts:
|
|
10
|
+
|
|
11
|
+
- **AuxRuntime**: Main runtime orchestrator that manages bot lifecycle and script execution
|
|
12
|
+
- **AuxCompiler**: JavaScript/TypeScript compiler with source maps and debugging support
|
|
13
|
+
- **Transpiler**: Code transformation engine with macro support and version tracking
|
|
14
|
+
- **AuxLibrary**: 500+ built-in APIs available to user scripts (actions, queries, utilities)
|
|
15
|
+
- **RuntimeBot**: Proxy wrapper for bot objects with change tracking and tag masking
|
|
16
|
+
- **AuxGlobalContext**: Execution context management with energy limiting and async control
|
|
17
|
+
- **RuntimeStateVersion**: State version tracking for real-time collaboration
|
|
18
|
+
- **CompiledBot**: Compiled script cache with breakpoint support
|
|
6
19
|
|
|
7
20
|
## Installation
|
|
8
21
|
|
|
9
22
|
```bash
|
|
10
|
-
|
|
23
|
+
npm install @casual-simulation/aux-runtime
|
|
11
24
|
```
|
|
12
25
|
|
|
13
|
-
##
|
|
26
|
+
## Core Components
|
|
27
|
+
|
|
28
|
+
### AuxRuntime
|
|
29
|
+
|
|
30
|
+
The main runtime orchestrator that manages bot state, script compilation, and event execution.
|
|
31
|
+
|
|
32
|
+
**Key Features**:
|
|
33
|
+
|
|
34
|
+
- Bot lifecycle management (add, update, remove)
|
|
35
|
+
- Script compilation and caching
|
|
36
|
+
- Event dispatching (shouts, whispers, actions)
|
|
37
|
+
- Listener registration and execution
|
|
38
|
+
- Energy management to prevent infinite loops
|
|
39
|
+
- Tag masking and bot spaces
|
|
40
|
+
- Module system support (ES6 imports/exports)
|
|
41
|
+
- Real-time edit mode for collaborative editing
|
|
42
|
+
- Error handling and stack trace mapping
|
|
14
43
|
|
|
15
|
-
|
|
44
|
+
**Configuration**:
|
|
16
45
|
|
|
17
46
|
```typescript
|
|
18
47
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} from '@casual-simulation/aux-common';
|
|
48
|
+
AuxRuntime,
|
|
49
|
+
MemoryGlobalContext,
|
|
50
|
+
} from '@casual-simulation/aux-runtime';
|
|
23
51
|
|
|
24
|
-
const
|
|
25
|
-
|
|
52
|
+
const runtime = new AuxRuntime(
|
|
53
|
+
{
|
|
54
|
+
hash: 'v1.0.0',
|
|
55
|
+
version: '1.0.0',
|
|
56
|
+
major: 1,
|
|
57
|
+
minor: 0,
|
|
58
|
+
patch: 0,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
supportsAR: false,
|
|
62
|
+
supportsVR: false,
|
|
63
|
+
isCollaborative: true,
|
|
64
|
+
ab1BootstrapUrl: 'https://bootstrap.example.com',
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
// Initialize with bot state
|
|
69
|
+
await runtime.stateUpdated({
|
|
70
|
+
state: {
|
|
71
|
+
bot1: createBot('bot1', {
|
|
72
|
+
name: 'My Bot',
|
|
73
|
+
onClick: '@os.toast("Clicked!");',
|
|
74
|
+
}),
|
|
75
|
+
},
|
|
76
|
+
addedBots: ['bot1'],
|
|
77
|
+
updatedBots: [],
|
|
78
|
+
removedBots: [],
|
|
26
79
|
});
|
|
27
|
-
|
|
28
|
-
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Example Usage**:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// Execute a shout
|
|
86
|
+
const results = await runtime.shout('onClick', { botId: 'bot1' });
|
|
87
|
+
|
|
88
|
+
for (const result of results) {
|
|
89
|
+
if (result.type === 'action') {
|
|
90
|
+
console.log('Action:', result.action);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Execute a formula
|
|
95
|
+
const value = await runtime.execute('return 1 + 1;');
|
|
96
|
+
console.log('Result:', value); // 2
|
|
97
|
+
|
|
98
|
+
// Subscribe to actions
|
|
99
|
+
runtime.onActions.subscribe((actions) => {
|
|
100
|
+
for (const action of actions) {
|
|
101
|
+
if (action.type === 'show_toast') {
|
|
102
|
+
console.log('Toast:', action.message);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Subscribe to errors
|
|
108
|
+
runtime.onErrors.subscribe((errors) => {
|
|
109
|
+
for (const error of errors) {
|
|
110
|
+
console.error('Script error:', error.error, error.bot, error.tag);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Key Methods**:
|
|
116
|
+
|
|
117
|
+
- `stateUpdated(event)`: Update bot state
|
|
118
|
+
- `shout(name, arg?)`: Broadcast event to all listening bots
|
|
119
|
+
- `whisper(bots, name, arg?)`: Send event to specific bots
|
|
120
|
+
- `execute(script)`: Execute arbitrary JavaScript code
|
|
121
|
+
- `context.recordBotState(bot)`: Record bot for change tracking
|
|
122
|
+
- `context.getBotState(bot)`: Get bot state with changes
|
|
123
|
+
- `context.enqueueAction(action)`: Queue an action for dispatch
|
|
124
|
+
|
|
125
|
+
### AuxCompiler
|
|
126
|
+
|
|
127
|
+
JavaScript/TypeScript compiler that transforms user scripts into executable functions.
|
|
128
|
+
|
|
129
|
+
**Key Features**:
|
|
130
|
+
|
|
131
|
+
- Compiles scripts and formulas to JavaScript functions
|
|
132
|
+
- Source map generation for error stack traces
|
|
133
|
+
- Interpretable function wrapping for step-through execution
|
|
134
|
+
- Module compilation (ES6 imports/exports)
|
|
135
|
+
- TypeScript syntax support
|
|
136
|
+
- Energy check injection for infinite loop detection
|
|
137
|
+
- JSX/TSX support
|
|
138
|
+
|
|
139
|
+
**Configuration**:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { AuxCompiler } from '@casual-simulation/aux-runtime';
|
|
143
|
+
|
|
144
|
+
const compiler = new AuxCompiler();
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Example Usage**:
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// Simple script compilation
|
|
151
|
+
const func = compiler.compile('return 1 + 2');
|
|
152
|
+
const result = func();
|
|
153
|
+
console.log(result); // 3
|
|
154
|
+
|
|
155
|
+
// Compile with variables
|
|
156
|
+
const func2 = compiler.compile('return num1 + num2', {
|
|
157
|
+
variables: {
|
|
158
|
+
num1: () => 10,
|
|
159
|
+
num2: () => 5,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
console.log(func2()); // 15
|
|
163
|
+
|
|
164
|
+
// Compile with constants
|
|
165
|
+
const func3 = compiler.compile('return num;', {
|
|
166
|
+
constants: {
|
|
167
|
+
num: -5,
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
console.log(func3()); // -5
|
|
171
|
+
|
|
172
|
+
// Compile with before/after hooks
|
|
173
|
+
const context = { num: 0 };
|
|
174
|
+
const func4 = compiler.compile('return num', {
|
|
175
|
+
variables: {
|
|
176
|
+
num: (ctx: any) => ctx.num,
|
|
177
|
+
},
|
|
178
|
+
before: (ctx: any) => (ctx.num += 1),
|
|
179
|
+
context,
|
|
180
|
+
});
|
|
181
|
+
console.log(func4()); // 1
|
|
182
|
+
console.log(func4()); // 2
|
|
183
|
+
|
|
184
|
+
// Compile listener script (with @ prefix)
|
|
185
|
+
const func5 = compiler.compile('@return 1 + 2');
|
|
186
|
+
console.log(func5()); // 3
|
|
187
|
+
|
|
188
|
+
// Compile with interpreter for debugging
|
|
189
|
+
import { Interpreter } from '@casual-simulation/js-interpreter';
|
|
190
|
+
const interpreter = new Interpreter();
|
|
191
|
+
const func6 = compiler.compile('return 1 + 2', {
|
|
192
|
+
interpreter,
|
|
193
|
+
});
|
|
194
|
+
// func6 now has an interpretable version for step-through debugging
|
|
195
|
+
|
|
196
|
+
// Compile JSX
|
|
197
|
+
const funcJsx = compiler.compile('return <div></div>', {
|
|
198
|
+
variables: {
|
|
199
|
+
html: () => ({
|
|
200
|
+
h: (type, props, ...children) => ({ type, props, children }),
|
|
201
|
+
}),
|
|
202
|
+
},
|
|
29
203
|
});
|
|
30
|
-
|
|
31
|
-
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Transpiler
|
|
207
|
+
|
|
208
|
+
Code transformation engine that processes JavaScript/TypeScript source code with energy checks and JSX support.
|
|
209
|
+
|
|
210
|
+
**Key Features**:
|
|
211
|
+
|
|
212
|
+
- AST parsing using Acorn
|
|
213
|
+
- Code generation using Astring
|
|
214
|
+
- Source map generation and mapping
|
|
215
|
+
- Infinite loop detection (injects `__energyCheck()` calls)
|
|
216
|
+
- Version vector tracking for Yjs integration
|
|
217
|
+
- TypeScript type stripping
|
|
218
|
+
- JSX/TSX support with configurable factories
|
|
219
|
+
|
|
220
|
+
**Configuration**:
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import { Transpiler } from '@casual-simulation/aux-runtime';
|
|
224
|
+
|
|
225
|
+
// Basic transpiler
|
|
226
|
+
const transpiler = new Transpiler();
|
|
227
|
+
|
|
228
|
+
// With JSX support
|
|
229
|
+
const transpilerJsx = new Transpiler({
|
|
230
|
+
jsxFactory: 'h',
|
|
231
|
+
jsxFragment: 'Fragment',
|
|
32
232
|
});
|
|
233
|
+
```
|
|
33
234
|
|
|
34
|
-
|
|
235
|
+
**Example Usage**:
|
|
35
236
|
|
|
36
|
-
|
|
37
|
-
|
|
237
|
+
```typescript
|
|
238
|
+
// Add energy checks to while loops
|
|
239
|
+
const result1 = transpiler.transpile('while(true) { console.log("Hello"); }');
|
|
240
|
+
console.log(result1);
|
|
241
|
+
// Output: 'while(true) {__energyCheck(); console.log("Hello"); }'
|
|
38
242
|
|
|
39
|
-
|
|
243
|
+
// Add energy checks to for loops
|
|
244
|
+
const result2 = transpiler.transpile(
|
|
245
|
+
'for(let i = 1; i > 0; i++) { console.log("Hello"); }'
|
|
246
|
+
);
|
|
247
|
+
console.log(result2);
|
|
248
|
+
// Output: 'for(let i = 1; i > 0; i++) {__energyCheck(); console.log("Hello"); }'
|
|
40
249
|
|
|
41
|
-
//
|
|
42
|
-
|
|
250
|
+
// Transpile JSX
|
|
251
|
+
const transpilerJsx = new Transpiler({
|
|
252
|
+
jsxFactory: 'h',
|
|
253
|
+
jsxFragment: 'Fragment',
|
|
254
|
+
});
|
|
255
|
+
const result3 = transpilerJsx.transpile('<div>Hello</div>');
|
|
256
|
+
console.log(result3);
|
|
257
|
+
// Output: 'h("div",null,`Hello`,)'
|
|
258
|
+
|
|
259
|
+
// Transpile JSX with attributes
|
|
260
|
+
const result4 = transpilerJsx.transpile(
|
|
261
|
+
'<div val="123" other="str">Hello</div>'
|
|
262
|
+
);
|
|
263
|
+
console.log(result4);
|
|
264
|
+
// Output: 'h("div",{ "val":"123" ,"other":"str"},`Hello`,)'
|
|
265
|
+
|
|
266
|
+
// Transpile nested JSX
|
|
267
|
+
const result5 = transpilerJsx.transpile('<div><h1>Hello, World!</h1></div>');
|
|
268
|
+
console.log(result5);
|
|
269
|
+
// Output: 'h("div",null,h("h1",null,`Hello, World!`,),)'
|
|
270
|
+
|
|
271
|
+
// Calculate original location from transpiled code
|
|
272
|
+
import { calculateOriginalLineLocation } from '@casual-simulation/aux-runtime';
|
|
273
|
+
const result6 = transpiler.transpile('while(true) { break; }');
|
|
274
|
+
const originalLoc = calculateOriginalLineLocation(result6.metadata, {
|
|
275
|
+
lineNumber: 1,
|
|
276
|
+
column: 30,
|
|
277
|
+
});
|
|
43
278
|
```
|
|
44
279
|
|
|
45
|
-
|
|
280
|
+
### AuxLibrary
|
|
281
|
+
|
|
282
|
+
Comprehensive library of 500+ built-in APIs available to user scripts.
|
|
283
|
+
|
|
284
|
+
**API Categories**:
|
|
285
|
+
|
|
286
|
+
- **Bot Operations**: `create()`, `destroy()`, `getBots()`, `getTag()`, `setTag()`
|
|
287
|
+
- **Actions**: `os.toast()`, `os.showInput()`, `os.openURL()`
|
|
288
|
+
- **Events**: `shout()`, `whisper()`, `superShout()`
|
|
289
|
+
- **Queries**: `getBot()`, `getBotTagValues()`, `byTag()`
|
|
290
|
+
- **Math**: `math.sum()`, `math.avg()`, `math.intersect()`
|
|
291
|
+
- **Utilities**: `os.toast()`, `os.showJoinCode()`, `os.download()`
|
|
292
|
+
- **Web**: `web.get()`, `web.post()`, `web.hook()`
|
|
293
|
+
- **Crypto**: `crypto.encrypt()`, `crypto.decrypt()`, `crypto.hash()`
|
|
294
|
+
- **AI**: `ai.chat()`, `ai.generateImage()`, `ai.generateSkybox()`
|
|
295
|
+
- **Records**: `records.data.get()`, `records.file.upload()`
|
|
296
|
+
- **Time**: `DateTime`, `Duration`, timezone functions
|
|
297
|
+
- **Animation**: `animateTag()`, `clearAnimations()`
|
|
298
|
+
|
|
299
|
+
**Configuration**:
|
|
46
300
|
|
|
47
301
|
```typescript
|
|
48
302
|
import {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
303
|
+
createDefaultLibrary,
|
|
304
|
+
MemoryGlobalContext,
|
|
305
|
+
} from '@casual-simulation/aux-runtime';
|
|
306
|
+
|
|
307
|
+
const library = createDefaultLibrary(context);
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Example APIs**:
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
// Bot operations
|
|
314
|
+
const bot = create({ name: 'Player', color: '#ff0000' });
|
|
315
|
+
destroy(bot);
|
|
316
|
+
setTag(bot, 'score', 100);
|
|
317
|
+
|
|
318
|
+
// Player interactions
|
|
319
|
+
os.toast('Hello!');
|
|
320
|
+
const input = await os.showInput('Enter name:');
|
|
321
|
+
os.openURL('https://example.com');
|
|
322
|
+
|
|
323
|
+
// Events
|
|
324
|
+
shout('onClick');
|
|
325
|
+
whisper(bot, 'onTap');
|
|
326
|
+
|
|
327
|
+
// Queries
|
|
328
|
+
const bots = getBots(byTag('color', '#ff0000'));
|
|
329
|
+
const names = getBotTagValues('name');
|
|
330
|
+
|
|
331
|
+
// Math
|
|
332
|
+
const total = math.sum([1, 2, 3, 4]); // 10
|
|
333
|
+
const point = math.intersectPlane({ x: 0, y: 0, z: 0 }, { x: 0, y: 1, z: 0 });
|
|
334
|
+
|
|
335
|
+
// Web requests
|
|
336
|
+
const response = await web.get('https://api.example.com/data');
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
See the [API documentation](https://docs.casualos.com/docs/actions) for the complete list.
|
|
340
|
+
|
|
341
|
+
### RuntimeBot
|
|
342
|
+
|
|
343
|
+
Proxy wrapper for bot objects that enables change tracking, tag masking, and dynamic listeners.
|
|
344
|
+
|
|
345
|
+
**Key Features**:
|
|
346
|
+
|
|
347
|
+
- Transparent proxy over bot objects
|
|
348
|
+
- Tag change tracking and diffing
|
|
349
|
+
- Tag masking (tempLocal, local, remoteTempShared)
|
|
350
|
+
- Bot space support
|
|
351
|
+
- Dynamic listener registration
|
|
352
|
+
- Script tag detection
|
|
353
|
+
- Link resolution
|
|
354
|
+
- Real-time edit mode
|
|
355
|
+
|
|
356
|
+
**Example Usage**:
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
import { createRuntimeBot } from '@casual-simulation/aux-runtime';
|
|
360
|
+
|
|
361
|
+
const runtimeBot = createRuntimeBot(bot, manager);
|
|
362
|
+
|
|
363
|
+
// Access tags
|
|
364
|
+
console.log(runtimeBot.tags.name);
|
|
365
|
+
|
|
366
|
+
// Modify tags (tracked)
|
|
367
|
+
runtimeBot.tags.color = '#00ff00';
|
|
368
|
+
|
|
369
|
+
// Get changes
|
|
370
|
+
const changes = runtimeBot[CLEAR_CHANGES_SYMBOL]();
|
|
371
|
+
console.log(changes); // { color: '#00ff00' }
|
|
372
|
+
|
|
373
|
+
// Tag masking
|
|
374
|
+
runtimeBot[SET_TAG_MASK_SYMBOL]('color', '#ff0000', 'tempLocal');
|
|
375
|
+
console.log(runtimeBot.tags.color); // '#ff0000' (masked value)
|
|
376
|
+
|
|
377
|
+
// Edit tags (operational transform)
|
|
378
|
+
runtimeBot[EDIT_TAG_SYMBOL]('description', [
|
|
379
|
+
{ type: 'insert', index: 0, text: 'Hello ' },
|
|
380
|
+
]);
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### AuxGlobalContext
|
|
384
|
+
|
|
385
|
+
Execution context that provides energy management, async task control, and API access.
|
|
386
|
+
|
|
387
|
+
**Key Features**:
|
|
388
|
+
|
|
389
|
+
- Energy limiting to prevent infinite loops
|
|
390
|
+
- Async task queuing (setTimeout, setInterval, promises)
|
|
391
|
+
- Action queuing for event dispatch
|
|
392
|
+
- Bot state tracking and versioning
|
|
393
|
+
- Tag-specific APIs based on context
|
|
394
|
+
- Debugger integration
|
|
395
|
+
- Performance monitoring
|
|
396
|
+
|
|
397
|
+
**Example Usage**:
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
const context = runtime.context;
|
|
401
|
+
|
|
402
|
+
// Energy management
|
|
403
|
+
context.energy = 50;
|
|
404
|
+
// ... execute code ...
|
|
405
|
+
console.log('Energy used:', 50 - context.energy);
|
|
406
|
+
|
|
407
|
+
// Queue actions
|
|
408
|
+
context.enqueueAction({
|
|
409
|
+
type: 'show_toast',
|
|
410
|
+
message: 'Hello!',
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
const actions = context.dequeueActions();
|
|
414
|
+
|
|
415
|
+
// Async tasks
|
|
416
|
+
const task = context.createTask();
|
|
417
|
+
task.resolve('abc');
|
|
418
|
+
|
|
419
|
+
// Bot manipulation
|
|
420
|
+
const b = context.createBot({
|
|
421
|
+
id: 'test',
|
|
422
|
+
tags: {
|
|
423
|
+
abc: 'def',
|
|
424
|
+
},
|
|
425
|
+
});
|
|
426
|
+
context.destroyBot(b);
|
|
427
|
+
|
|
428
|
+
// ... modify bot ...
|
|
429
|
+
const bot = context.bots[0];
|
|
430
|
+
bot.tags.abc = 'def';
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### RuntimeStateVersion
|
|
434
|
+
|
|
435
|
+
State versioning for real-time collaboration using Yjs version vectors.
|
|
436
|
+
|
|
437
|
+
**Key Features**:
|
|
438
|
+
|
|
439
|
+
- Yjs state vector integration
|
|
440
|
+
- Relative position tracking
|
|
441
|
+
- Version comparison
|
|
442
|
+
- Cross-session synchronization
|
|
443
|
+
|
|
444
|
+
**Example Usage**:
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
import { RuntimeStateVersion } from '@casual-simulation/aux-runtime';
|
|
448
|
+
|
|
449
|
+
const version = new RuntimeStateVersion(yjsDoc, { client1: 5, client2: 10 });
|
|
450
|
+
|
|
451
|
+
// Get current state vector
|
|
452
|
+
const stateVector = version.stateVector;
|
|
453
|
+
|
|
454
|
+
// Create relative position
|
|
455
|
+
const relPos = version.createRelativePosition(botId, tagName, 10);
|
|
456
|
+
|
|
457
|
+
// Restore absolute position
|
|
458
|
+
const absPos = version.restoreAbsolutePosition(relPos);
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
## Architecture
|
|
462
|
+
|
|
463
|
+
```
|
|
464
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
465
|
+
│ CasualOS Runtime │
|
|
466
|
+
├─────────────────────────────────────────────────────────────┤
|
|
467
|
+
│ │
|
|
468
|
+
│ ┌────────────────────────────────────────────────────┐ │
|
|
469
|
+
│ │ AuxRuntime │ │
|
|
470
|
+
│ │ (Orchestrates bot lifecycle and execution) │ │
|
|
471
|
+
│ └────────┬───────────────────────────────────────────┘ │
|
|
472
|
+
│ │ │
|
|
473
|
+
│ ┌────────▼───────────┐ ┌──────────────────────────┐ │
|
|
474
|
+
│ │ AuxCompiler │ │ AuxGlobalContext │ │
|
|
475
|
+
│ │ │ │ │ │
|
|
476
|
+
│ │ • Compile scripts │ │ • Energy management │ │
|
|
477
|
+
│ │ • Source maps │ │ • Async tasks │ │
|
|
478
|
+
│ │ • Breakpoints │ │ • Action queuing │ │
|
|
479
|
+
│ └────────┬───────────┘ └──────────┬───────────────┘ │
|
|
480
|
+
│ │ │ │
|
|
481
|
+
│ ┌────────▼───────────┐ ┌──────────▼───────────────┐ │
|
|
482
|
+
│ │ Transpiler │ │ AuxLibrary │ │
|
|
483
|
+
│ │ │ │ │ │
|
|
484
|
+
│ │ • AST parsing │ │ • 500+ APIs │ │
|
|
485
|
+
│ │ • Macro expansion │ │ • Bot operations │ │
|
|
486
|
+
│ │ • Version tracking │ │ • Actions & events │ │
|
|
487
|
+
│ └────────────────────┘ └──────────────────────────┘ │
|
|
488
|
+
│ │
|
|
489
|
+
│ ┌────────────────────────────────────────────────────┐ │
|
|
490
|
+
│ │ RuntimeBot (Proxy) │ │
|
|
491
|
+
│ │ │ │
|
|
492
|
+
│ │ • Change tracking • Tag masking │ │
|
|
493
|
+
│ │ • Dynamic listeners • Real-time edits │ │
|
|
494
|
+
│ └────────────────────────────────────────────────────┘ │
|
|
495
|
+
│ │
|
|
496
|
+
│ ┌────────────────────────────────────────────────────┐ │
|
|
497
|
+
│ │ CompiledBot (Cache) │ │
|
|
498
|
+
│ │ │ │
|
|
499
|
+
│ │ • Compiled scripts • Breakpoints │ │
|
|
500
|
+
│ │ • Tag listeners • Metadata │ │
|
|
501
|
+
│ └────────────────────────────────────────────────────┘ │
|
|
502
|
+
│ │
|
|
503
|
+
└─────────────────────────────────────────────────────────────┘
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
## Usage Examples
|
|
507
|
+
|
|
508
|
+
### Basic Runtime Setup
|
|
509
|
+
|
|
510
|
+
```typescript
|
|
511
|
+
import {
|
|
512
|
+
AuxRuntime,
|
|
513
|
+
MemoryGlobalContext,
|
|
514
|
+
createDefaultLibrary,
|
|
515
|
+
} from '@casual-simulation/aux-runtime';
|
|
516
|
+
import { createBot } from '@casual-simulation/aux-common';
|
|
517
|
+
|
|
518
|
+
// Create runtime
|
|
519
|
+
const version = { hash: 'v1', version: '1.0.0', major: 1, minor: 0, patch: 0 };
|
|
520
|
+
const device = { supportsAR: false, supportsVR: false, isCollaborative: true };
|
|
521
|
+
const runtime = new AuxRuntime(version, device);
|
|
522
|
+
|
|
523
|
+
// Initialize with bots
|
|
524
|
+
await runtime.stateUpdated({
|
|
525
|
+
state: {
|
|
526
|
+
player1: createBot('player1', {
|
|
527
|
+
name: 'Alice',
|
|
528
|
+
onClick: '@os.toast("Hello!");',
|
|
529
|
+
}),
|
|
530
|
+
counter: createBot('counter', {
|
|
531
|
+
count: 0,
|
|
532
|
+
onClick: '@tags.count += 1; os.toast("Count: " + tags.count);',
|
|
533
|
+
}),
|
|
534
|
+
},
|
|
535
|
+
addedBots: ['player1', 'counter'],
|
|
536
|
+
updatedBots: [],
|
|
537
|
+
removedBots: [],
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
// Execute events
|
|
541
|
+
await runtime.shout('onClick');
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### Executing User Scripts
|
|
545
|
+
|
|
546
|
+
```typescript
|
|
547
|
+
// Execute inline script
|
|
548
|
+
const result = await runtime.execute(`
|
|
549
|
+
const bot = create({ name: 'Dynamic Bot', color: '#00ff00' });
|
|
550
|
+
return bot.id;
|
|
551
|
+
`);
|
|
552
|
+
console.log('Created bot:', result);
|
|
553
|
+
|
|
554
|
+
// Execute with energy limit
|
|
555
|
+
const context = runtime.context;
|
|
556
|
+
context.energy = 50;
|
|
557
|
+
try {
|
|
558
|
+
await runtime.execute('while(true) {}'); // Infinite loop
|
|
559
|
+
} catch (err) {
|
|
560
|
+
console.error('Ran out of energy:', err);
|
|
78
561
|
}
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
### Module System
|
|
565
|
+
|
|
566
|
+
```typescript
|
|
567
|
+
// Bot with module export
|
|
568
|
+
const libBot = createBot('lib', {
|
|
569
|
+
system: 'lib',
|
|
570
|
+
math: `📄
|
|
571
|
+
export function add(a, b) { return a + b; }
|
|
572
|
+
export function multiply(a, b) { return a * b; }
|
|
573
|
+
`,
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
// Bot that imports module
|
|
577
|
+
const userBot = createBot('user', {
|
|
578
|
+
onClick: `@
|
|
579
|
+
import { add, multiply } from 'lib.math';
|
|
580
|
+
const result = multiply(add(2, 3), 4);
|
|
581
|
+
os.toast('Result: ' + result);
|
|
582
|
+
`,
|
|
583
|
+
});
|
|
79
584
|
|
|
80
|
-
|
|
81
|
-
|
|
585
|
+
await runtime.stateUpdated({
|
|
586
|
+
state: { lib: libBot, user: userBot },
|
|
587
|
+
addedBots: ['lib', 'user'],
|
|
588
|
+
updatedBots: [],
|
|
589
|
+
removedBots: [],
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
await runtime.shout('onClick');
|
|
82
593
|
```
|
|
594
|
+
|
|
595
|
+
### Change Tracking
|
|
596
|
+
|
|
597
|
+
```typescript
|
|
598
|
+
import {
|
|
599
|
+
createRuntimeBot,
|
|
600
|
+
CLEAR_CHANGES_SYMBOL,
|
|
601
|
+
} from '@casual-simulation/aux-runtime';
|
|
602
|
+
|
|
603
|
+
const runtimeBot = createRuntimeBot(bot, factoryOptions);
|
|
604
|
+
|
|
605
|
+
// Modify bot
|
|
606
|
+
runtimeBot.tags.score = 100;
|
|
607
|
+
runtimeBot.tags.position = { x: 1, y: 2, z: 3 };
|
|
608
|
+
|
|
609
|
+
// Get changes
|
|
610
|
+
const changes = runtimeBot[CLEAR_CHANGES_SYMBOL]();
|
|
611
|
+
console.log(changes);
|
|
612
|
+
// { score: 100, position: { x: 1, y: 2, z: 3 } }
|
|
613
|
+
|
|
614
|
+
// Changes are now cleared
|
|
615
|
+
const noChanges = runtimeBot[CLEAR_CHANGES_SYMBOL]();
|
|
616
|
+
console.log(noChanges); // {}
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
## Runtime Goals
|
|
620
|
+
|
|
621
|
+
### 1. Full JavaScript Support
|
|
622
|
+
|
|
623
|
+
Supports all JavaScript features the underlying environment provides, including ES6+, async/await, generators, and modules.
|
|
624
|
+
|
|
625
|
+
### 2. System Stability
|
|
626
|
+
|
|
627
|
+
Prevents bad scripts from locking up the system through energy management, infinite loop detection, and graceful error handling.
|
|
628
|
+
|
|
629
|
+
### 3. Rich APIs
|
|
630
|
+
|
|
631
|
+
Provides 500+ built-in APIs for bot manipulation, UI interactions, web requests, cryptography, AI, and more.
|
|
632
|
+
|
|
633
|
+
### 4. Low Overhead
|
|
634
|
+
|
|
635
|
+
Pre-compiles scripts and caches compiled functions to minimize latency. Script execution is as simple as calling a function.
|
|
636
|
+
|
|
637
|
+
### 5. Great Developer Experience
|
|
638
|
+
|
|
639
|
+
Source maps enable accurate stack traces. Type definitions provide IntelliSense. Debugger support allows step-through execution.
|
|
640
|
+
|
|
641
|
+
## Dependencies
|
|
642
|
+
|
|
643
|
+
### Core Dependencies
|
|
644
|
+
|
|
645
|
+
- `@casual-simulation/aux-common`: Common types and utilities
|
|
646
|
+
- `@casual-simulation/aux-records`: Records system integration
|
|
647
|
+
- `@casual-simulation/js-interpreter`: JavaScript interpreter for debugging
|
|
648
|
+
- `@casual-simulation/engine262`: ECMAScript engine
|
|
649
|
+
- `acorn`: JavaScript parser
|
|
650
|
+
- `astring`: JavaScript code generator
|
|
651
|
+
- `estraverse`: AST traversal
|
|
652
|
+
- `lru-cache`: Compilation cache
|
|
653
|
+
|
|
654
|
+
### Utility Dependencies
|
|
655
|
+
|
|
656
|
+
- `seedrandom`: Deterministic random number generation
|
|
657
|
+
- `@tweenjs/tween.js`: Animation tweening
|
|
658
|
+
- `uuid`: Unique identifier generation
|
|
659
|
+
- `fast-json-stable-stringify`: Deterministic JSON serialization
|
|
660
|
+
|
|
661
|
+
## Testing
|
|
662
|
+
|
|
663
|
+
The module includes comprehensive test files:
|
|
664
|
+
|
|
665
|
+
- `AuxRuntime.spec.ts`: Runtime orchestration tests
|
|
666
|
+
- `AuxCompiler.spec.ts`: Compilation tests
|
|
667
|
+
- `Transpiler.spec.ts`: Code transformation tests
|
|
668
|
+
- `AuxLibrary.spec.ts`: API tests
|
|
669
|
+
- `RuntimeBot.spec.ts`: Proxy wrapper tests
|
|
670
|
+
- `AuxGlobalContext.spec.ts`: Context management tests
|
|
671
|
+
|
|
672
|
+
Run tests:
|
|
673
|
+
|
|
674
|
+
```bash
|
|
675
|
+
npm test
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
## License
|
|
679
|
+
|
|
680
|
+
AGPL-3.0-only
|
|
681
|
+
|
|
682
|
+
## Related Packages
|
|
683
|
+
|
|
684
|
+
- `@casual-simulation/aux-common`: Core types and bot system
|
|
685
|
+
- `@casual-simulation/aux-vm`: Virtual machine implementations
|
|
686
|
+
- `@casual-simulation/aux-vm-browser`: Browser VM
|
|
687
|
+
- `@casual-simulation/aux-vm-node`: Node.js VM
|
|
688
|
+
- `@casual-simulation/aux-records`: Records system
|
|
689
|
+
- `@casual-simulation/js-interpreter`: JavaScript interpreter
|
|
690
|
+
|
|
691
|
+
## Contributing
|
|
692
|
+
|
|
693
|
+
See [DEVELOPERS.md](../../DEVELOPERS.md) for development guidelines.
|
|
694
|
+
|
|
695
|
+
## Documentation
|
|
696
|
+
|
|
697
|
+
- [API Documentation](https://docs.casualos.com/docs/actions)
|
|
698
|
+
- [Runtime Architecture](runtime/README.md)
|
|
699
|
+
- [Getting Started Guide](https://docs.casualos.com)
|
|
700
|
+
|
|
701
|
+
## Version
|
|
702
|
+
|
|
703
|
+
Current version: 3.8.1
|
|
704
|
+
|
|
705
|
+
See [CHANGELOG.md](../../CHANGELOG.md) for version history
|