@holoscript/core 2.0.1 → 2.1.0
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/dist/chunk-2XXE34KS.js +344 -0
- package/dist/chunk-2XXE34KS.js.map +1 -0
- package/dist/chunk-3X2EGU7Z.cjs +52 -0
- package/dist/chunk-3X2EGU7Z.cjs.map +1 -0
- package/dist/chunk-AFFVFO4D.js +1689 -0
- package/dist/chunk-AFFVFO4D.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +10 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/{src/HoloScriptDebugger.ts → dist/chunk-DOY73HDH.js} +118 -257
- package/dist/chunk-DOY73HDH.js.map +1 -0
- package/dist/chunk-JEQ2X3Z6.cjs +12 -0
- package/dist/chunk-JEQ2X3Z6.cjs.map +1 -0
- package/dist/chunk-L6VLNVKP.cjs +1691 -0
- package/dist/chunk-L6VLNVKP.cjs.map +1 -0
- package/dist/chunk-MFNO57XL.cjs +347 -0
- package/dist/chunk-MFNO57XL.cjs.map +1 -0
- package/dist/chunk-R75MREOS.cjs +424 -0
- package/dist/chunk-R75MREOS.cjs.map +1 -0
- package/dist/chunk-SATNCODL.js +45 -0
- package/dist/chunk-SATNCODL.js.map +1 -0
- package/dist/chunk-T57ZL7KR.cjs +1281 -0
- package/dist/chunk-T57ZL7KR.cjs.map +1 -0
- package/dist/chunk-U72GEJZT.js +1279 -0
- package/dist/chunk-U72GEJZT.js.map +1 -0
- package/dist/debugger.cjs +20 -0
- package/dist/debugger.cjs.map +1 -0
- package/dist/debugger.d.cts +171 -0
- package/dist/debugger.d.ts +171 -0
- package/dist/debugger.js +7 -0
- package/dist/debugger.js.map +1 -0
- package/dist/index.cjs +6803 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4093 -0
- package/dist/index.d.ts +4093 -0
- package/dist/index.js +6715 -0
- package/dist/index.js.map +1 -0
- package/dist/parser.cjs +14 -0
- package/dist/parser.cjs.map +1 -0
- package/dist/parser.d.cts +172 -0
- package/dist/parser.d.ts +172 -0
- package/dist/parser.js +5 -0
- package/dist/parser.js.map +1 -0
- package/dist/runtime.cjs +14 -0
- package/dist/runtime.cjs.map +1 -0
- package/dist/runtime.d.cts +200 -0
- package/dist/runtime.d.ts +200 -0
- package/dist/runtime.js +5 -0
- package/dist/runtime.js.map +1 -0
- package/dist/type-checker.cjs +17 -0
- package/dist/type-checker.cjs.map +1 -0
- package/dist/type-checker.d.cts +105 -0
- package/dist/type-checker.d.ts +105 -0
- package/dist/type-checker.js +4 -0
- package/dist/type-checker.js.map +1 -0
- package/dist/types-4h8cbtF_.d.cts +329 -0
- package/dist/types-4h8cbtF_.d.ts +329 -0
- package/package.json +17 -13
- package/src/HoloScript2DParser.js +0 -227
- package/src/HoloScript2DParser.ts +0 -261
- package/src/HoloScriptCodeParser.js +0 -1102
- package/src/HoloScriptCodeParser.ts +0 -1188
- package/src/HoloScriptDebugger.js +0 -458
- package/src/HoloScriptParser.js +0 -338
- package/src/HoloScriptParser.ts +0 -397
- package/src/HoloScriptPlusParser.js +0 -371
- package/src/HoloScriptPlusParser.ts +0 -543
- package/src/HoloScriptRuntime.js +0 -1399
- package/src/HoloScriptRuntime.test.js +0 -351
- package/src/HoloScriptRuntime.test.ts +0 -436
- package/src/HoloScriptRuntime.ts +0 -1653
- package/src/HoloScriptTypeChecker.js +0 -356
- package/src/HoloScriptTypeChecker.ts +0 -475
- package/src/__tests__/GraphicsServices.test.js +0 -357
- package/src/__tests__/GraphicsServices.test.ts +0 -427
- package/src/__tests__/HoloScriptPlusParser.test.js +0 -317
- package/src/__tests__/HoloScriptPlusParser.test.ts +0 -392
- package/src/__tests__/integration.test.js +0 -336
- package/src/__tests__/integration.test.ts +0 -416
- package/src/__tests__/performance.bench.js +0 -218
- package/src/__tests__/performance.bench.ts +0 -262
- package/src/__tests__/type-checker.test.js +0 -60
- package/src/__tests__/type-checker.test.ts +0 -73
- package/src/index.js +0 -217
- package/src/index.ts +0 -426
- package/src/interop/Interoperability.js +0 -413
- package/src/interop/Interoperability.ts +0 -494
- package/src/logger.js +0 -42
- package/src/logger.ts +0 -57
- package/src/parser/EnhancedParser.js +0 -205
- package/src/parser/EnhancedParser.ts +0 -251
- package/src/parser/HoloScriptPlusParser.js +0 -928
- package/src/parser/HoloScriptPlusParser.ts +0 -1089
- package/src/runtime/HoloScriptPlusRuntime.js +0 -674
- package/src/runtime/HoloScriptPlusRuntime.ts +0 -861
- package/src/runtime/PerformanceTelemetry.js +0 -323
- package/src/runtime/PerformanceTelemetry.ts +0 -467
- package/src/runtime/RuntimeOptimization.js +0 -361
- package/src/runtime/RuntimeOptimization.ts +0 -416
- package/src/services/HololandGraphicsPipelineService.js +0 -506
- package/src/services/HololandGraphicsPipelineService.ts +0 -662
- package/src/services/PlatformPerformanceOptimizer.js +0 -356
- package/src/services/PlatformPerformanceOptimizer.ts +0 -503
- package/src/state/ReactiveState.js +0 -427
- package/src/state/ReactiveState.ts +0 -572
- package/src/tools/DeveloperExperience.js +0 -376
- package/src/tools/DeveloperExperience.ts +0 -438
- package/src/traits/AIDriverTrait.js +0 -322
- package/src/traits/AIDriverTrait.test.js +0 -329
- package/src/traits/AIDriverTrait.test.ts +0 -357
- package/src/traits/AIDriverTrait.ts +0 -474
- package/src/traits/LightingTrait.js +0 -313
- package/src/traits/LightingTrait.test.js +0 -410
- package/src/traits/LightingTrait.test.ts +0 -462
- package/src/traits/LightingTrait.ts +0 -505
- package/src/traits/MaterialTrait.js +0 -194
- package/src/traits/MaterialTrait.test.js +0 -286
- package/src/traits/MaterialTrait.test.ts +0 -329
- package/src/traits/MaterialTrait.ts +0 -324
- package/src/traits/RenderingTrait.js +0 -356
- package/src/traits/RenderingTrait.test.js +0 -363
- package/src/traits/RenderingTrait.test.ts +0 -427
- package/src/traits/RenderingTrait.ts +0 -555
- package/src/traits/VRTraitSystem.js +0 -740
- package/src/traits/VRTraitSystem.ts +0 -1040
- package/src/traits/VoiceInputTrait.js +0 -284
- package/src/traits/VoiceInputTrait.test.js +0 -226
- package/src/traits/VoiceInputTrait.test.ts +0 -252
- package/src/traits/VoiceInputTrait.ts +0 -401
- package/src/types/AdvancedTypeSystem.js +0 -226
- package/src/types/AdvancedTypeSystem.ts +0 -494
- package/src/types/HoloScriptPlus.d.ts +0 -853
- package/src/types.js +0 -6
- package/src/types.ts +0 -369
- package/tsconfig.json +0 -23
- package/tsup.config.d.ts +0 -2
- package/tsup.config.js +0 -18
- package/tsup.config.ts +0 -19
|
@@ -0,0 +1,1689 @@
|
|
|
1
|
+
import { logger } from './chunk-SATNCODL.js';
|
|
2
|
+
|
|
3
|
+
// src/ReactiveState.ts
|
|
4
|
+
var ReactiveState = class {
|
|
5
|
+
constructor(initialState = {}) {
|
|
6
|
+
this.subscribers = /* @__PURE__ */ new Set();
|
|
7
|
+
this.state = { ...initialState };
|
|
8
|
+
this.proxy = this.createReactiveProxy(this.state);
|
|
9
|
+
}
|
|
10
|
+
createReactiveProxy(target) {
|
|
11
|
+
const self = this;
|
|
12
|
+
return new Proxy(target, {
|
|
13
|
+
get(obj, key) {
|
|
14
|
+
const val = obj[key];
|
|
15
|
+
if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
16
|
+
return self.createReactiveProxy(val);
|
|
17
|
+
}
|
|
18
|
+
return val;
|
|
19
|
+
},
|
|
20
|
+
set(obj, key, value) {
|
|
21
|
+
const oldVal = obj[key];
|
|
22
|
+
obj[key] = value;
|
|
23
|
+
if (oldVal !== value) {
|
|
24
|
+
self.notify();
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
get(key) {
|
|
31
|
+
return this.proxy[key];
|
|
32
|
+
}
|
|
33
|
+
set(key, value) {
|
|
34
|
+
this.proxy[key] = value;
|
|
35
|
+
}
|
|
36
|
+
update(updates) {
|
|
37
|
+
Object.assign(this.proxy, updates);
|
|
38
|
+
}
|
|
39
|
+
subscribe(callback) {
|
|
40
|
+
this.subscribers.add(callback);
|
|
41
|
+
return () => this.subscribers.delete(callback);
|
|
42
|
+
}
|
|
43
|
+
getSnapshot() {
|
|
44
|
+
return { ...this.state };
|
|
45
|
+
}
|
|
46
|
+
notify() {
|
|
47
|
+
this.subscribers.forEach((cb) => cb(this.getSnapshot()));
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
var ExpressionEvaluator = class {
|
|
51
|
+
constructor(context = {}) {
|
|
52
|
+
this.context = context;
|
|
53
|
+
}
|
|
54
|
+
evaluate(expression) {
|
|
55
|
+
if (typeof expression !== "string") return expression;
|
|
56
|
+
const dangerousPatterns = [
|
|
57
|
+
/\beval\s*\(/,
|
|
58
|
+
/\brequire\s*\(/,
|
|
59
|
+
/\bimport\s*\(/,
|
|
60
|
+
/\bprocess\s*\./,
|
|
61
|
+
/\bglobal\s*\./,
|
|
62
|
+
/\b__dirname\b/,
|
|
63
|
+
/\b__filename\b/,
|
|
64
|
+
/\bfs\s*\./,
|
|
65
|
+
/\bchild_process\s*\./,
|
|
66
|
+
/\bfs\.writeFileSync/,
|
|
67
|
+
/\bfs\.readFileSync/
|
|
68
|
+
];
|
|
69
|
+
for (const pattern of dangerousPatterns) {
|
|
70
|
+
if (pattern.test(expression)) {
|
|
71
|
+
console.warn(`Security: Blocked suspicious expression: ${expression}`);
|
|
72
|
+
return void 0;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (expression.includes("${")) {
|
|
76
|
+
const trimmed = expression.trim();
|
|
77
|
+
const match = trimmed.match(/^\$\{([^}]+)\}$/);
|
|
78
|
+
if (match) {
|
|
79
|
+
return this.evaluate(match[1]);
|
|
80
|
+
}
|
|
81
|
+
return this.interpolate(expression);
|
|
82
|
+
}
|
|
83
|
+
const keys = Object.keys(this.context);
|
|
84
|
+
const values = Object.values(this.context);
|
|
85
|
+
try {
|
|
86
|
+
const fn = new Function(...keys, `return (${expression})`);
|
|
87
|
+
return fn(...values);
|
|
88
|
+
} catch (e) {
|
|
89
|
+
return expression;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
interpolate(str) {
|
|
93
|
+
return str.replace(/\$\{([^}]+)\}/g, (_, expr) => {
|
|
94
|
+
const val = this.evaluate(expr);
|
|
95
|
+
return val !== void 0 ? String(val) : "";
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
updateContext(updates) {
|
|
99
|
+
Object.assign(this.context, updates);
|
|
100
|
+
}
|
|
101
|
+
setContext(context) {
|
|
102
|
+
this.context = { ...context };
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
function createState(initial = {}) {
|
|
106
|
+
return new ReactiveState(initial);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/HoloScriptRuntime.ts
|
|
110
|
+
var RUNTIME_SECURITY_LIMITS = {
|
|
111
|
+
maxExecutionDepth: 50,
|
|
112
|
+
maxTotalNodes: 1e3,
|
|
113
|
+
maxExecutionTimeMs: 5e3,
|
|
114
|
+
maxParticlesPerSystem: 1e3,
|
|
115
|
+
maxCallStackDepth: 100
|
|
116
|
+
};
|
|
117
|
+
var HoloScriptRuntime = class {
|
|
118
|
+
constructor(_importLoader, customFunctions) {
|
|
119
|
+
this.particleSystems = /* @__PURE__ */ new Map();
|
|
120
|
+
this.executionHistory = [];
|
|
121
|
+
this.startTime = 0;
|
|
122
|
+
this.nodeCount = 0;
|
|
123
|
+
this.callStack = [];
|
|
124
|
+
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
125
|
+
this.animations = /* @__PURE__ */ new Map();
|
|
126
|
+
this.uiElements = /* @__PURE__ */ new Map();
|
|
127
|
+
this.context = this.createEmptyContext();
|
|
128
|
+
this.currentScope = { variables: this.context.variables };
|
|
129
|
+
this.builtinFunctions = this.initBuiltins(customFunctions);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Initialize built-in functions
|
|
133
|
+
*/
|
|
134
|
+
initBuiltins(customFunctions) {
|
|
135
|
+
const builtins = /* @__PURE__ */ new Map();
|
|
136
|
+
if (customFunctions) {
|
|
137
|
+
for (const [name, func] of Object.entries(customFunctions)) {
|
|
138
|
+
builtins.set(name, func);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
builtins.set("show", (args) => {
|
|
142
|
+
const target = String(args[0]);
|
|
143
|
+
const element = this.uiElements.get(target);
|
|
144
|
+
if (element) element.visible = true;
|
|
145
|
+
const hologram = this.context.hologramState.get(target);
|
|
146
|
+
if (hologram) {
|
|
147
|
+
this.createParticleEffect(`${target}_show`, { x: 0, y: 0, z: 0 }, hologram.color, 15);
|
|
148
|
+
}
|
|
149
|
+
logger.info("show", { target });
|
|
150
|
+
return { shown: target };
|
|
151
|
+
});
|
|
152
|
+
builtins.set("hide", (args) => {
|
|
153
|
+
const target = String(args[0]);
|
|
154
|
+
const element = this.uiElements.get(target);
|
|
155
|
+
if (element) element.visible = false;
|
|
156
|
+
logger.info("hide", { target });
|
|
157
|
+
return { hidden: target };
|
|
158
|
+
});
|
|
159
|
+
builtins.set("pulsate", (args) => {
|
|
160
|
+
const target = String(args[0]);
|
|
161
|
+
const options = args[1] || {};
|
|
162
|
+
const duration = Number(options.duration) || 1e3;
|
|
163
|
+
const color = String(options.color || "#ffffff");
|
|
164
|
+
const position = this.context.spatialMemory.get(target) || { x: 0, y: 0, z: 0 };
|
|
165
|
+
this.createParticleEffect(`${target}_pulse`, position, color, 30);
|
|
166
|
+
return { pulsing: target, duration };
|
|
167
|
+
});
|
|
168
|
+
builtins.set("animate", (args) => {
|
|
169
|
+
const target = String(args[0]);
|
|
170
|
+
const options = args[1] || {};
|
|
171
|
+
const animation = {
|
|
172
|
+
target,
|
|
173
|
+
property: String(options.property || "position.y"),
|
|
174
|
+
from: Number(options.from || 0),
|
|
175
|
+
to: Number(options.to || 1),
|
|
176
|
+
duration: Number(options.duration || 1e3),
|
|
177
|
+
startTime: Date.now(),
|
|
178
|
+
easing: String(options.easing || "linear"),
|
|
179
|
+
loop: Boolean(options.loop),
|
|
180
|
+
yoyo: Boolean(options.yoyo)
|
|
181
|
+
};
|
|
182
|
+
this.animations.set(`${target}_${animation.property}`, animation);
|
|
183
|
+
return { animating: target, animation };
|
|
184
|
+
});
|
|
185
|
+
builtins.set("spawn", (args) => {
|
|
186
|
+
const target = String(args[0]);
|
|
187
|
+
const position = args[1] || { x: 0, y: 0, z: 0 };
|
|
188
|
+
this.context.spatialMemory.set(target, position);
|
|
189
|
+
this.createParticleEffect(`${target}_spawn`, position, "#00ff00", 25);
|
|
190
|
+
return { spawned: target, at: position };
|
|
191
|
+
});
|
|
192
|
+
builtins.set("move", (args) => {
|
|
193
|
+
const target = String(args[0]);
|
|
194
|
+
const position = args[1] || { x: 0, y: 0, z: 0 };
|
|
195
|
+
const current = this.context.spatialMemory.get(target);
|
|
196
|
+
if (current) {
|
|
197
|
+
this.context.spatialMemory.set(target, position);
|
|
198
|
+
this.createConnectionStream(target, `${target}_dest`, current, position, "move");
|
|
199
|
+
}
|
|
200
|
+
return { moved: target, to: position };
|
|
201
|
+
});
|
|
202
|
+
builtins.set("set", (args) => {
|
|
203
|
+
const target = String(args[0]);
|
|
204
|
+
const value = args[1];
|
|
205
|
+
this.setVariable(target, value);
|
|
206
|
+
return { set: target, value };
|
|
207
|
+
});
|
|
208
|
+
builtins.set("get", (args) => {
|
|
209
|
+
const target = String(args[0]);
|
|
210
|
+
return this.getVariable(target);
|
|
211
|
+
});
|
|
212
|
+
builtins.set("add", (args) => Number(args[0]) + Number(args[1]));
|
|
213
|
+
builtins.set("subtract", (args) => Number(args[0]) - Number(args[1]));
|
|
214
|
+
builtins.set("multiply", (args) => Number(args[0]) * Number(args[1]));
|
|
215
|
+
builtins.set("divide", (args) => Number(args[1]) !== 0 ? Number(args[0]) / Number(args[1]) : 0);
|
|
216
|
+
builtins.set("mod", (args) => Number(args[0]) % Number(args[1]));
|
|
217
|
+
builtins.set("abs", (args) => Math.abs(Number(args[0])));
|
|
218
|
+
builtins.set("floor", (args) => Math.floor(Number(args[0])));
|
|
219
|
+
builtins.set("ceil", (args) => Math.ceil(Number(args[0])));
|
|
220
|
+
builtins.set("round", (args) => Math.round(Number(args[0])));
|
|
221
|
+
builtins.set("min", (args) => Math.min(...args.map(Number)));
|
|
222
|
+
builtins.set("max", (args) => Math.max(...args.map(Number)));
|
|
223
|
+
builtins.set("random", () => Math.random());
|
|
224
|
+
builtins.set("concat", (args) => args.map(String).join(""));
|
|
225
|
+
builtins.set("length", (args) => {
|
|
226
|
+
const val = args[0];
|
|
227
|
+
if (typeof val === "string") return val.length;
|
|
228
|
+
if (Array.isArray(val)) return val.length;
|
|
229
|
+
return 0;
|
|
230
|
+
});
|
|
231
|
+
builtins.set("substring", (args) => String(args[0]).substring(Number(args[1]), Number(args[2])));
|
|
232
|
+
builtins.set("uppercase", (args) => String(args[0]).toUpperCase());
|
|
233
|
+
builtins.set("lowercase", (args) => String(args[0]).toLowerCase());
|
|
234
|
+
builtins.set("push", (args) => {
|
|
235
|
+
const arr = args[0];
|
|
236
|
+
if (Array.isArray(arr)) {
|
|
237
|
+
arr.push(args[1]);
|
|
238
|
+
return arr;
|
|
239
|
+
}
|
|
240
|
+
return [args[0], args[1]];
|
|
241
|
+
});
|
|
242
|
+
builtins.set("pop", (args) => {
|
|
243
|
+
const arr = args[0];
|
|
244
|
+
if (Array.isArray(arr)) return arr.pop();
|
|
245
|
+
return void 0;
|
|
246
|
+
});
|
|
247
|
+
builtins.set("at", (args) => {
|
|
248
|
+
const arr = args[0];
|
|
249
|
+
const index = Number(args[1]);
|
|
250
|
+
if (Array.isArray(arr)) return arr[index];
|
|
251
|
+
return void 0;
|
|
252
|
+
});
|
|
253
|
+
builtins.set("showSettings", () => {
|
|
254
|
+
this.emit("show-settings");
|
|
255
|
+
return true;
|
|
256
|
+
});
|
|
257
|
+
builtins.set("openChat", (args) => {
|
|
258
|
+
const config = args[0] || {};
|
|
259
|
+
this.emit("show-chat", config);
|
|
260
|
+
return true;
|
|
261
|
+
});
|
|
262
|
+
builtins.set("log", (args) => {
|
|
263
|
+
logger.info("HoloScript log", { args });
|
|
264
|
+
return args[0];
|
|
265
|
+
});
|
|
266
|
+
builtins.set("print", (args) => {
|
|
267
|
+
const message = args.map(String).join(" ");
|
|
268
|
+
logger.info("print", { message });
|
|
269
|
+
return message;
|
|
270
|
+
});
|
|
271
|
+
builtins.set("typeof", (args) => typeof args[0]);
|
|
272
|
+
builtins.set("isArray", (args) => Array.isArray(args[0]));
|
|
273
|
+
builtins.set("isNumber", (args) => typeof args[0] === "number" && !isNaN(args[0]));
|
|
274
|
+
builtins.set("isString", (args) => typeof args[0] === "string");
|
|
275
|
+
builtins.set("shop", (args) => this.handleShop(args));
|
|
276
|
+
builtins.set("inventory", (args) => this.handleInventory(args));
|
|
277
|
+
builtins.set("purchase", (args) => this.handlePurchase(args));
|
|
278
|
+
builtins.set("presence", (args) => this.handlePresence(args));
|
|
279
|
+
builtins.set("invite", (args) => this.handleInvite(args));
|
|
280
|
+
builtins.set("share", (args) => this.handleShare(args));
|
|
281
|
+
builtins.set("physics", (args) => this.handlePhysics(args));
|
|
282
|
+
builtins.set("gravity", (args) => this.handleGravity(args));
|
|
283
|
+
builtins.set("collide", (args) => this.handleCollide(args));
|
|
284
|
+
builtins.set("animate", (args) => this.handleAnimate(args));
|
|
285
|
+
builtins.set("calculate_arc", (args) => this.handleCalculateArc(args));
|
|
286
|
+
return builtins;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Execute a single AST node
|
|
290
|
+
*/
|
|
291
|
+
async executeNode(node) {
|
|
292
|
+
const startTime = Date.now();
|
|
293
|
+
try {
|
|
294
|
+
this.context.executionStack.push(node);
|
|
295
|
+
let result;
|
|
296
|
+
switch (node.type) {
|
|
297
|
+
case "orb":
|
|
298
|
+
result = await this.executeOrb(node);
|
|
299
|
+
break;
|
|
300
|
+
case "method":
|
|
301
|
+
case "function":
|
|
302
|
+
result = await this.executeFunction(node);
|
|
303
|
+
break;
|
|
304
|
+
case "connection":
|
|
305
|
+
result = await this.executeConnection(node);
|
|
306
|
+
break;
|
|
307
|
+
case "gate":
|
|
308
|
+
result = await this.executeGate(node);
|
|
309
|
+
break;
|
|
310
|
+
case "stream":
|
|
311
|
+
result = await this.executeStream(node);
|
|
312
|
+
break;
|
|
313
|
+
case "call":
|
|
314
|
+
result = await this.executeCall(node);
|
|
315
|
+
break;
|
|
316
|
+
case "debug":
|
|
317
|
+
result = await this.executeDebug(node);
|
|
318
|
+
break;
|
|
319
|
+
case "visualize":
|
|
320
|
+
result = await this.executeVisualize(node);
|
|
321
|
+
break;
|
|
322
|
+
case "2d-element":
|
|
323
|
+
result = await this.executeUIElement(node);
|
|
324
|
+
break;
|
|
325
|
+
case "nexus":
|
|
326
|
+
case "building":
|
|
327
|
+
result = await this.executeStructure(node);
|
|
328
|
+
break;
|
|
329
|
+
case "assignment":
|
|
330
|
+
result = await this.executeAssignment(node);
|
|
331
|
+
break;
|
|
332
|
+
case "return":
|
|
333
|
+
result = await this.executeReturn(node);
|
|
334
|
+
break;
|
|
335
|
+
case "generic":
|
|
336
|
+
result = await this.executeGeneric(node);
|
|
337
|
+
break;
|
|
338
|
+
case "expression-statement":
|
|
339
|
+
result = await this.executeCall(node);
|
|
340
|
+
break;
|
|
341
|
+
case "scale":
|
|
342
|
+
result = await this.executeScale(node);
|
|
343
|
+
break;
|
|
344
|
+
case "focus":
|
|
345
|
+
result = await this.executeFocus(node);
|
|
346
|
+
break;
|
|
347
|
+
case "environment":
|
|
348
|
+
result = await this.executeEnvironment(node);
|
|
349
|
+
break;
|
|
350
|
+
case "composition":
|
|
351
|
+
result = await this.executeComposition(node);
|
|
352
|
+
break;
|
|
353
|
+
case "template":
|
|
354
|
+
result = await this.executeTemplate(node);
|
|
355
|
+
break;
|
|
356
|
+
case "server":
|
|
357
|
+
result = await this.executeServerNode(node);
|
|
358
|
+
break;
|
|
359
|
+
case "database":
|
|
360
|
+
result = await this.executeDatabaseNode(node);
|
|
361
|
+
break;
|
|
362
|
+
case "fetch":
|
|
363
|
+
result = await this.executeFetchNode(node);
|
|
364
|
+
break;
|
|
365
|
+
case "execute":
|
|
366
|
+
result = await this.executeTarget(node);
|
|
367
|
+
break;
|
|
368
|
+
case "state-declaration":
|
|
369
|
+
result = await this.executeStateDeclaration(node);
|
|
370
|
+
break;
|
|
371
|
+
default:
|
|
372
|
+
result = {
|
|
373
|
+
success: false,
|
|
374
|
+
error: `Unknown node type: ${node.type}`,
|
|
375
|
+
executionTime: Date.now() - startTime
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
result.executionTime = Date.now() - startTime;
|
|
379
|
+
this.executionHistory.push(result);
|
|
380
|
+
this.context.executionStack.pop();
|
|
381
|
+
return result;
|
|
382
|
+
} catch (error) {
|
|
383
|
+
const execTime = Date.now() - startTime;
|
|
384
|
+
const errorResult = {
|
|
385
|
+
success: false,
|
|
386
|
+
error: error instanceof Error ? error.message : String(error),
|
|
387
|
+
executionTime: execTime
|
|
388
|
+
};
|
|
389
|
+
this.executionHistory.push(errorResult);
|
|
390
|
+
this.context.executionStack.pop();
|
|
391
|
+
return errorResult;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Execute multiple nodes or a single node (unified entry point)
|
|
396
|
+
*/
|
|
397
|
+
async execute(nodes) {
|
|
398
|
+
if (Array.isArray(nodes)) {
|
|
399
|
+
const results = await this.executeProgram(nodes);
|
|
400
|
+
const success = results.every((r) => r.success);
|
|
401
|
+
return {
|
|
402
|
+
success,
|
|
403
|
+
output: success ? `Program executed (${results.length} nodes)` : "Program failed",
|
|
404
|
+
error: results.find((r) => !r.success)?.error
|
|
405
|
+
};
|
|
406
|
+
} else {
|
|
407
|
+
return this.executeNode(nodes);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Execute multiple nodes in sequence
|
|
412
|
+
*/
|
|
413
|
+
async executeProgram(nodes, depth = 0) {
|
|
414
|
+
if (depth === 0) {
|
|
415
|
+
this.startTime = Date.now();
|
|
416
|
+
this.nodeCount = 0;
|
|
417
|
+
}
|
|
418
|
+
if (depth > RUNTIME_SECURITY_LIMITS.maxExecutionDepth) {
|
|
419
|
+
logger.error("Max execution depth exceeded", { depth });
|
|
420
|
+
return [{
|
|
421
|
+
success: false,
|
|
422
|
+
error: `Max execution depth exceeded (${RUNTIME_SECURITY_LIMITS.maxExecutionDepth})`,
|
|
423
|
+
executionTime: 0
|
|
424
|
+
}];
|
|
425
|
+
}
|
|
426
|
+
const results = [];
|
|
427
|
+
for (const node of nodes) {
|
|
428
|
+
this.nodeCount++;
|
|
429
|
+
if (this.nodeCount > RUNTIME_SECURITY_LIMITS.maxTotalNodes) {
|
|
430
|
+
logger.error("Max total nodes exceeded", { count: this.nodeCount });
|
|
431
|
+
results.push({
|
|
432
|
+
success: false,
|
|
433
|
+
error: "Max total nodes exceeded",
|
|
434
|
+
executionTime: Date.now() - this.startTime
|
|
435
|
+
});
|
|
436
|
+
break;
|
|
437
|
+
}
|
|
438
|
+
if (Date.now() - this.startTime > RUNTIME_SECURITY_LIMITS.maxExecutionTimeMs) {
|
|
439
|
+
logger.error("Execution timeout", { duration: Date.now() - this.startTime });
|
|
440
|
+
results.push({
|
|
441
|
+
success: false,
|
|
442
|
+
error: "Execution timeout",
|
|
443
|
+
executionTime: Date.now() - this.startTime
|
|
444
|
+
});
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
const result = await this.executeNode(node);
|
|
448
|
+
results.push(result);
|
|
449
|
+
if (!result.success && node.type !== "visualize") {
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
if (node.type === "return") {
|
|
453
|
+
break;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return results;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Call a function with arguments
|
|
460
|
+
*/
|
|
461
|
+
async callFunction(name, args = []) {
|
|
462
|
+
const builtin = this.builtinFunctions.get(name);
|
|
463
|
+
if (builtin) {
|
|
464
|
+
try {
|
|
465
|
+
const result = builtin(args);
|
|
466
|
+
return {
|
|
467
|
+
success: true,
|
|
468
|
+
output: result
|
|
469
|
+
};
|
|
470
|
+
} catch (error) {
|
|
471
|
+
return {
|
|
472
|
+
success: false,
|
|
473
|
+
error: `Built-in function ${name} failed: ${error}`
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
const func = this.context.functions.get(name);
|
|
478
|
+
if (!func) {
|
|
479
|
+
return {
|
|
480
|
+
success: false,
|
|
481
|
+
error: `Function '${name}' not found`
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
if (this.callStack.length >= RUNTIME_SECURITY_LIMITS.maxCallStackDepth) {
|
|
485
|
+
return {
|
|
486
|
+
success: false,
|
|
487
|
+
error: `Max call stack depth exceeded (${RUNTIME_SECURITY_LIMITS.maxCallStackDepth})`
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
const parentScope = this.currentScope;
|
|
491
|
+
this.currentScope = {
|
|
492
|
+
variables: /* @__PURE__ */ new Map(),
|
|
493
|
+
parent: parentScope
|
|
494
|
+
};
|
|
495
|
+
func.parameters.forEach((param, index) => {
|
|
496
|
+
const value = index < args.length ? args[index] : param.defaultValue;
|
|
497
|
+
this.currentScope.variables.set(param.name, value);
|
|
498
|
+
});
|
|
499
|
+
this.callStack.push(name);
|
|
500
|
+
let returnValue = void 0;
|
|
501
|
+
try {
|
|
502
|
+
const results = await this.executeProgram(func.body, this.callStack.length);
|
|
503
|
+
const lastResult = results[results.length - 1];
|
|
504
|
+
if (lastResult?.output !== void 0) {
|
|
505
|
+
returnValue = lastResult.output;
|
|
506
|
+
}
|
|
507
|
+
this.createExecutionEffect(name, func.position || { x: 0, y: 0, z: 0 });
|
|
508
|
+
return {
|
|
509
|
+
success: results.every((r) => r.success),
|
|
510
|
+
output: returnValue,
|
|
511
|
+
hologram: func.hologram,
|
|
512
|
+
spatialPosition: func.position
|
|
513
|
+
};
|
|
514
|
+
} finally {
|
|
515
|
+
this.currentScope = parentScope;
|
|
516
|
+
this.callStack.pop();
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Set a variable in current scope
|
|
521
|
+
*/
|
|
522
|
+
setVariable(name, value) {
|
|
523
|
+
if (name.includes(".")) {
|
|
524
|
+
const parts = name.split(".");
|
|
525
|
+
const objName = parts[0];
|
|
526
|
+
const propPath = parts.slice(1);
|
|
527
|
+
let obj = this.getVariable(objName);
|
|
528
|
+
if (obj === void 0 || typeof obj !== "object" || obj === null) {
|
|
529
|
+
obj = {};
|
|
530
|
+
this.currentScope.variables.set(objName, obj);
|
|
531
|
+
}
|
|
532
|
+
let current = obj;
|
|
533
|
+
for (let i = 0; i < propPath.length - 1; i++) {
|
|
534
|
+
if (current[propPath[i]] === void 0 || typeof current[propPath[i]] !== "object") {
|
|
535
|
+
current[propPath[i]] = {};
|
|
536
|
+
}
|
|
537
|
+
current = current[propPath[i]];
|
|
538
|
+
}
|
|
539
|
+
current[propPath[propPath.length - 1]] = value;
|
|
540
|
+
} else {
|
|
541
|
+
this.currentScope.variables.set(name, value);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Get a variable from scope chain
|
|
546
|
+
*/
|
|
547
|
+
getVariable(name) {
|
|
548
|
+
if (name.includes(".")) {
|
|
549
|
+
const parts = name.split(".");
|
|
550
|
+
let value = this.getVariable(parts[0]);
|
|
551
|
+
for (let i = 1; i < parts.length && value !== void 0; i++) {
|
|
552
|
+
if (typeof value === "object" && value !== null) {
|
|
553
|
+
value = value[parts[i]];
|
|
554
|
+
} else {
|
|
555
|
+
return void 0;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
return value;
|
|
559
|
+
}
|
|
560
|
+
let scope = this.currentScope;
|
|
561
|
+
while (scope) {
|
|
562
|
+
if (scope.variables.has(name)) {
|
|
563
|
+
return scope.variables.get(name);
|
|
564
|
+
}
|
|
565
|
+
scope = scope.parent;
|
|
566
|
+
}
|
|
567
|
+
if (this.context.variables.has(name)) {
|
|
568
|
+
return this.context.variables.get(name);
|
|
569
|
+
}
|
|
570
|
+
if (this.context.functions.has(name)) {
|
|
571
|
+
return this.context.functions.get(name);
|
|
572
|
+
}
|
|
573
|
+
return void 0;
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Evaluate an expression
|
|
577
|
+
*/
|
|
578
|
+
evaluateExpression(expr) {
|
|
579
|
+
if (!expr || typeof expr !== "string") return expr;
|
|
580
|
+
const evaluator = new ExpressionEvaluator(this.context.state.getSnapshot());
|
|
581
|
+
const varContext = {};
|
|
582
|
+
this.context.variables.forEach((v, k) => varContext[k] = v);
|
|
583
|
+
evaluator.updateContext(varContext);
|
|
584
|
+
return evaluator.evaluate(expr);
|
|
585
|
+
}
|
|
586
|
+
// ============================================================================
|
|
587
|
+
// Node Executors
|
|
588
|
+
// ============================================================================
|
|
589
|
+
async executeOrb(node) {
|
|
590
|
+
const scale = this.context.currentScale || 1;
|
|
591
|
+
const adjustedPos = node.position ? {
|
|
592
|
+
x: node.position.x * scale,
|
|
593
|
+
y: node.position.y * scale,
|
|
594
|
+
z: node.position.z * scale
|
|
595
|
+
} : { x: 0, y: 0, z: 0 };
|
|
596
|
+
if (node.position) {
|
|
597
|
+
this.context.spatialMemory.set(node.name, adjustedPos);
|
|
598
|
+
}
|
|
599
|
+
const hologram = node.hologram ? {
|
|
600
|
+
...node.hologram,
|
|
601
|
+
size: (node.hologram.size || 1) * scale
|
|
602
|
+
} : void 0;
|
|
603
|
+
const evaluatedProperties = {};
|
|
604
|
+
for (const [key, val] of Object.entries(node.properties)) {
|
|
605
|
+
if (typeof val === "string") {
|
|
606
|
+
evaluatedProperties[key] = this.evaluateExpression(val);
|
|
607
|
+
} else {
|
|
608
|
+
evaluatedProperties[key] = val;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
const orbData = {
|
|
612
|
+
__type: "orb",
|
|
613
|
+
name: node.name,
|
|
614
|
+
properties: evaluatedProperties,
|
|
615
|
+
traits: node.directives?.filter((d) => d.type === "trait").map((d) => d.name) || [],
|
|
616
|
+
directives: node.directives || [],
|
|
617
|
+
position: adjustedPos,
|
|
618
|
+
hologram,
|
|
619
|
+
created: Date.now(),
|
|
620
|
+
// Methods bound to this orb
|
|
621
|
+
show: () => this.builtinFunctions.get("show")([node.name]),
|
|
622
|
+
hide: () => this.builtinFunctions.get("hide")([node.name]),
|
|
623
|
+
pulse: (opts) => this.builtinFunctions.get("pulse")([node.name, opts])
|
|
624
|
+
};
|
|
625
|
+
this.context.variables.set(node.name, orbData);
|
|
626
|
+
if (hologram) {
|
|
627
|
+
this.context.hologramState.set(node.name, hologram);
|
|
628
|
+
}
|
|
629
|
+
if (node.directives) {
|
|
630
|
+
this.applyDirectives(node);
|
|
631
|
+
}
|
|
632
|
+
this.createParticleEffect(`${node.name}_creation`, adjustedPos, "#00ffff", 20);
|
|
633
|
+
logger.info("Orb created", { name: node.name, properties: Object.keys(node.properties), scale });
|
|
634
|
+
return {
|
|
635
|
+
success: true,
|
|
636
|
+
output: orbData,
|
|
637
|
+
hologram,
|
|
638
|
+
spatialPosition: adjustedPos
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
async executeFunction(node) {
|
|
642
|
+
this.context.functions.set(node.name, node);
|
|
643
|
+
const hologram = {
|
|
644
|
+
shape: "cube",
|
|
645
|
+
color: "#ff6b35",
|
|
646
|
+
size: 1.5,
|
|
647
|
+
glow: true,
|
|
648
|
+
interactive: true,
|
|
649
|
+
...node.hologram
|
|
650
|
+
};
|
|
651
|
+
this.context.hologramState.set(node.name, hologram);
|
|
652
|
+
logger.info("Function defined", { name: node.name, params: node.parameters.map((p) => p.name) });
|
|
653
|
+
return {
|
|
654
|
+
success: true,
|
|
655
|
+
output: `Function '${node.name}' defined with ${node.parameters.length} parameter(s)`,
|
|
656
|
+
hologram,
|
|
657
|
+
spatialPosition: node.position
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
async executeConnection(node) {
|
|
661
|
+
this.context.connections.push(node);
|
|
662
|
+
const fromPos = this.context.spatialMemory.get(node.from);
|
|
663
|
+
const toPos = this.context.spatialMemory.get(node.to);
|
|
664
|
+
if (fromPos && toPos) {
|
|
665
|
+
this.createConnectionStream(node.from, node.to, fromPos, toPos, node.dataType);
|
|
666
|
+
}
|
|
667
|
+
if (node.bidirectional) {
|
|
668
|
+
this.on(`${node.from}.changed`, async (data) => {
|
|
669
|
+
this.setVariable(node.to, data);
|
|
670
|
+
this.emit(`${node.to}.changed`, data);
|
|
671
|
+
});
|
|
672
|
+
this.on(`${node.to}.changed`, async (data) => {
|
|
673
|
+
this.setVariable(node.from, data);
|
|
674
|
+
this.emit(`${node.from}.changed`, data);
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
logger.info("Connection created", { from: node.from, to: node.to, dataType: node.dataType });
|
|
678
|
+
return {
|
|
679
|
+
success: true,
|
|
680
|
+
output: `Connected '${node.from}' to '${node.to}' (${node.dataType})`,
|
|
681
|
+
hologram: {
|
|
682
|
+
shape: "cylinder",
|
|
683
|
+
color: this.getDataTypeColor(node.dataType),
|
|
684
|
+
size: 0.1,
|
|
685
|
+
glow: true,
|
|
686
|
+
interactive: false
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
async executeGate(node) {
|
|
691
|
+
try {
|
|
692
|
+
const condition = this.evaluateCondition(node.condition);
|
|
693
|
+
const path = condition ? node.truePath : node.falsePath;
|
|
694
|
+
logger.info("Gate evaluation", { condition: node.condition, result: condition });
|
|
695
|
+
if (path.length > 0) {
|
|
696
|
+
await this.executeProgram(path, this.callStack.length + 1);
|
|
697
|
+
}
|
|
698
|
+
return {
|
|
699
|
+
success: true,
|
|
700
|
+
output: `Gate: took ${condition ? "true" : "false"} path`,
|
|
701
|
+
hologram: {
|
|
702
|
+
shape: "pyramid",
|
|
703
|
+
color: condition ? "#00ff00" : "#ff0000",
|
|
704
|
+
size: 1,
|
|
705
|
+
glow: true,
|
|
706
|
+
interactive: true
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
} catch (error) {
|
|
710
|
+
return {
|
|
711
|
+
success: false,
|
|
712
|
+
error: `Gate execution failed: ${error}`
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
async executeStream(node) {
|
|
717
|
+
let data = this.getVariable(node.source);
|
|
718
|
+
logger.info("Stream processing", { name: node.name, source: node.source, transforms: node.transformations.length });
|
|
719
|
+
for (const transform of node.transformations) {
|
|
720
|
+
data = await this.applyTransformation(data, transform);
|
|
721
|
+
}
|
|
722
|
+
this.setVariable(`${node.name}_result`, data);
|
|
723
|
+
this.createFlowingStream(node.name, node.position || { x: 0, y: 0, z: 0 }, data);
|
|
724
|
+
return {
|
|
725
|
+
success: true,
|
|
726
|
+
output: `Stream '${node.name}' processed ${Array.isArray(data) ? data.length : 1} item(s)`,
|
|
727
|
+
hologram: node.hologram,
|
|
728
|
+
spatialPosition: node.position
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
async executeCall(node) {
|
|
732
|
+
const funcName = node.target || "";
|
|
733
|
+
const args = node.args || [];
|
|
734
|
+
return this.callFunction(funcName, args);
|
|
735
|
+
}
|
|
736
|
+
async executeDebug(node) {
|
|
737
|
+
const debugInfo = {
|
|
738
|
+
variables: Object.fromEntries(this.currentScope.variables),
|
|
739
|
+
contextVariables: Object.fromEntries(this.context.variables),
|
|
740
|
+
functions: Array.from(this.context.functions.keys()),
|
|
741
|
+
connections: this.context.connections.length,
|
|
742
|
+
callStack: [...this.callStack],
|
|
743
|
+
uiElements: Array.from(this.uiElements.keys()),
|
|
744
|
+
animations: Array.from(this.animations.keys()),
|
|
745
|
+
executionHistory: this.executionHistory.slice(-10)
|
|
746
|
+
};
|
|
747
|
+
const debugOrb = {
|
|
748
|
+
shape: "pyramid",
|
|
749
|
+
color: "#ff1493",
|
|
750
|
+
size: 0.8,
|
|
751
|
+
glow: true,
|
|
752
|
+
interactive: true
|
|
753
|
+
};
|
|
754
|
+
this.context.hologramState.set(`debug_${node.target || "program"}`, debugOrb);
|
|
755
|
+
logger.info("Debug info", debugInfo);
|
|
756
|
+
return {
|
|
757
|
+
success: true,
|
|
758
|
+
output: debugInfo,
|
|
759
|
+
hologram: debugOrb
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
async executeVisualize(node) {
|
|
763
|
+
const target = node.target || "";
|
|
764
|
+
const data = this.getVariable(target);
|
|
765
|
+
if (data === void 0) {
|
|
766
|
+
return {
|
|
767
|
+
success: false,
|
|
768
|
+
error: `No data found for '${target}'`
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
const visHologram = {
|
|
772
|
+
shape: "cylinder",
|
|
773
|
+
color: "#32cd32",
|
|
774
|
+
size: 1.5,
|
|
775
|
+
glow: true,
|
|
776
|
+
interactive: true
|
|
777
|
+
};
|
|
778
|
+
this.createDataVisualization(target, data, node.position || { x: 0, y: 0, z: 0 });
|
|
779
|
+
return {
|
|
780
|
+
success: true,
|
|
781
|
+
output: { visualizing: target, data },
|
|
782
|
+
hologram: visHologram
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
async executeUIElement(node) {
|
|
786
|
+
const element = {
|
|
787
|
+
type: node.elementType,
|
|
788
|
+
name: node.name,
|
|
789
|
+
properties: { ...node.properties },
|
|
790
|
+
visible: true,
|
|
791
|
+
enabled: true
|
|
792
|
+
};
|
|
793
|
+
if (node.elementType === "textinput") {
|
|
794
|
+
element.value = node.properties.value || "";
|
|
795
|
+
} else if (node.elementType === "slider") {
|
|
796
|
+
element.value = node.properties.value || node.properties.min || 0;
|
|
797
|
+
} else if (node.elementType === "toggle") {
|
|
798
|
+
element.value = node.properties.checked || false;
|
|
799
|
+
}
|
|
800
|
+
this.uiElements.set(node.name, element);
|
|
801
|
+
if (node.events) {
|
|
802
|
+
for (const [eventName, handlerName] of Object.entries(node.events)) {
|
|
803
|
+
this.on(`${node.name}.${eventName}`, async () => {
|
|
804
|
+
await this.callFunction(handlerName);
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
logger.info("UI element created", { type: node.elementType, name: node.name });
|
|
809
|
+
return {
|
|
810
|
+
success: true,
|
|
811
|
+
output: element
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Execute generic voice commands
|
|
816
|
+
* Handles commands like: show, hide, animate, pulse, create
|
|
817
|
+
*/
|
|
818
|
+
async executeGeneric(_node) {
|
|
819
|
+
const genericNode = _node;
|
|
820
|
+
const command = String(genericNode.command || "").trim().toLowerCase();
|
|
821
|
+
const tokens = command.split(/\s+/);
|
|
822
|
+
const action = tokens[0];
|
|
823
|
+
const target = tokens[1];
|
|
824
|
+
logger.info("Executing generic command", { command, action, target });
|
|
825
|
+
try {
|
|
826
|
+
let result;
|
|
827
|
+
switch (action) {
|
|
828
|
+
case "show":
|
|
829
|
+
result = await this.executeShowCommand(target, genericNode);
|
|
830
|
+
break;
|
|
831
|
+
case "hide":
|
|
832
|
+
result = await this.executeHideCommand(target, genericNode);
|
|
833
|
+
break;
|
|
834
|
+
case "create":
|
|
835
|
+
case "summon":
|
|
836
|
+
result = await this.executeCreateCommand(tokens.slice(1), genericNode);
|
|
837
|
+
break;
|
|
838
|
+
case "animate":
|
|
839
|
+
result = await this.executeAnimateCommand(target, tokens.slice(2), genericNode);
|
|
840
|
+
break;
|
|
841
|
+
case "pulse":
|
|
842
|
+
result = await this.executePulseCommand(target, tokens.slice(2), genericNode);
|
|
843
|
+
break;
|
|
844
|
+
case "move":
|
|
845
|
+
result = await this.executeMoveCommand(target, tokens.slice(2), genericNode);
|
|
846
|
+
break;
|
|
847
|
+
case "delete":
|
|
848
|
+
case "remove":
|
|
849
|
+
result = await this.executeDeleteCommand(target, genericNode);
|
|
850
|
+
break;
|
|
851
|
+
default:
|
|
852
|
+
logger.warn("Unknown voice command action", { action, command });
|
|
853
|
+
result = {
|
|
854
|
+
executed: false,
|
|
855
|
+
message: `Unknown command: ${action}`
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
return {
|
|
859
|
+
success: true,
|
|
860
|
+
output: result
|
|
861
|
+
};
|
|
862
|
+
} catch (error) {
|
|
863
|
+
return {
|
|
864
|
+
success: false,
|
|
865
|
+
error: `Generic command execution failed: ${String(error)}`
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Execute 'show' command
|
|
871
|
+
*/
|
|
872
|
+
async executeShowCommand(target, _node) {
|
|
873
|
+
const hologram = _node.hologram || {
|
|
874
|
+
shape: "orb",
|
|
875
|
+
color: "#00ffff",
|
|
876
|
+
size: 0.8,
|
|
877
|
+
glow: true,
|
|
878
|
+
interactive: true
|
|
879
|
+
};
|
|
880
|
+
const position = _node.position || { x: 0, y: 0, z: 0 };
|
|
881
|
+
this.context.spatialMemory.set(target, position);
|
|
882
|
+
this.createParticleEffect(`${target}_show`, position, hologram.color, 15);
|
|
883
|
+
logger.info("Show command executed", { target, position });
|
|
884
|
+
return {
|
|
885
|
+
showed: target,
|
|
886
|
+
hologram,
|
|
887
|
+
position
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Execute 'hide' command
|
|
892
|
+
*/
|
|
893
|
+
async executeHideCommand(target, _node) {
|
|
894
|
+
const position = this.context.spatialMemory.get(target) || { x: 0, y: 0, z: 0 };
|
|
895
|
+
this.createParticleEffect(`${target}_hide`, position, "#ff0000", 10);
|
|
896
|
+
logger.info("Hide command executed", { target });
|
|
897
|
+
return {
|
|
898
|
+
hidden: target
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Execute 'create' command
|
|
903
|
+
*/
|
|
904
|
+
async executeCreateCommand(tokens, _node) {
|
|
905
|
+
if (tokens.length < 2) {
|
|
906
|
+
return { error: "Create command requires shape and name" };
|
|
907
|
+
}
|
|
908
|
+
const shape = tokens[0];
|
|
909
|
+
const name = tokens[1];
|
|
910
|
+
const position = _node.position || { x: 0, y: 0, z: 0 };
|
|
911
|
+
const hologram = {
|
|
912
|
+
shape,
|
|
913
|
+
color: _node.hologram?.color || "#00ffff",
|
|
914
|
+
size: _node.hologram?.size || 1,
|
|
915
|
+
glow: _node.hologram?.glow !== false,
|
|
916
|
+
interactive: _node.hologram?.interactive !== false
|
|
917
|
+
};
|
|
918
|
+
this.context.spatialMemory.set(name, position);
|
|
919
|
+
this.createParticleEffect(`${name}_create`, position, hologram.color, 20);
|
|
920
|
+
logger.info("Create command executed", { shape, name, position });
|
|
921
|
+
return {
|
|
922
|
+
created: name,
|
|
923
|
+
shape,
|
|
924
|
+
hologram,
|
|
925
|
+
position
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Execute 'animate' command
|
|
930
|
+
*/
|
|
931
|
+
async executeAnimateCommand(target, tokens, _node) {
|
|
932
|
+
const property = tokens[0] || "position.y";
|
|
933
|
+
const duration = parseInt(tokens[1] || "1000", 10);
|
|
934
|
+
const animation = {
|
|
935
|
+
target,
|
|
936
|
+
property,
|
|
937
|
+
from: 0,
|
|
938
|
+
to: 1,
|
|
939
|
+
duration,
|
|
940
|
+
startTime: Date.now(),
|
|
941
|
+
easing: "ease-in-out"
|
|
942
|
+
};
|
|
943
|
+
this.animations.set(`${target}_${property}`, animation);
|
|
944
|
+
logger.info("Animate command executed", { target, property, duration });
|
|
945
|
+
return {
|
|
946
|
+
animating: target,
|
|
947
|
+
animation
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Execute 'pulse' command
|
|
952
|
+
*/
|
|
953
|
+
async executePulseCommand(target, tokens, _node) {
|
|
954
|
+
const duration = parseInt(tokens[0] || "500", 10);
|
|
955
|
+
const position = this.context.spatialMemory.get(target) || { x: 0, y: 0, z: 0 };
|
|
956
|
+
this.createParticleEffect(`${target}_pulse`, position, "#ffff00", 30);
|
|
957
|
+
const animation = {
|
|
958
|
+
target,
|
|
959
|
+
property: "scale",
|
|
960
|
+
from: 1,
|
|
961
|
+
to: 1.5,
|
|
962
|
+
duration,
|
|
963
|
+
startTime: Date.now(),
|
|
964
|
+
easing: "sine",
|
|
965
|
+
yoyo: true,
|
|
966
|
+
loop: true
|
|
967
|
+
};
|
|
968
|
+
this.animations.set(`${target}_pulse`, animation);
|
|
969
|
+
logger.info("Pulse command executed", { target, duration });
|
|
970
|
+
return {
|
|
971
|
+
pulsing: target,
|
|
972
|
+
duration
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Execute 'move' command
|
|
977
|
+
*/
|
|
978
|
+
async executeMoveCommand(target, tokens, _node) {
|
|
979
|
+
const x = parseFloat(tokens[0] || "0");
|
|
980
|
+
const y = parseFloat(tokens[1] || "0");
|
|
981
|
+
const z = parseFloat(tokens[2] || "0");
|
|
982
|
+
const position = { x, y, z };
|
|
983
|
+
const current = this.context.spatialMemory.get(target);
|
|
984
|
+
if (current) {
|
|
985
|
+
this.context.spatialMemory.set(target, position);
|
|
986
|
+
this.createConnectionStream(target, `${target}_move`, current, position, "movement");
|
|
987
|
+
} else {
|
|
988
|
+
this.context.spatialMemory.set(target, position);
|
|
989
|
+
}
|
|
990
|
+
logger.info("Move command executed", { target, position });
|
|
991
|
+
return {
|
|
992
|
+
moved: target,
|
|
993
|
+
to: position
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Execute 'delete' command
|
|
998
|
+
*/
|
|
999
|
+
async executeDeleteCommand(target, _node) {
|
|
1000
|
+
const position = this.context.spatialMemory.get(target);
|
|
1001
|
+
if (position) {
|
|
1002
|
+
this.createParticleEffect(`${target}_delete`, position, "#ff0000", 15);
|
|
1003
|
+
this.context.spatialMemory.delete(target);
|
|
1004
|
+
}
|
|
1005
|
+
logger.info("Delete command executed", { target });
|
|
1006
|
+
return {
|
|
1007
|
+
deleted: target
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
1010
|
+
async executeStructure(node) {
|
|
1011
|
+
const hologram = node.hologram || {
|
|
1012
|
+
shape: node.type === "nexus" ? "sphere" : "cube",
|
|
1013
|
+
color: node.type === "nexus" ? "#9b59b6" : "#e74c3c",
|
|
1014
|
+
size: node.type === "nexus" ? 3 : 4,
|
|
1015
|
+
glow: true,
|
|
1016
|
+
interactive: true
|
|
1017
|
+
};
|
|
1018
|
+
return {
|
|
1019
|
+
success: true,
|
|
1020
|
+
output: { type: node.type, created: true },
|
|
1021
|
+
hologram,
|
|
1022
|
+
spatialPosition: node.position
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
async executeAssignment(node) {
|
|
1026
|
+
const value = this.evaluateExpression(String(node.value));
|
|
1027
|
+
this.setVariable(node.name, value);
|
|
1028
|
+
return {
|
|
1029
|
+
success: true,
|
|
1030
|
+
output: { assigned: node.name, value }
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
async executeReturn(node) {
|
|
1034
|
+
const value = this.evaluateExpression(String(node.value));
|
|
1035
|
+
return {
|
|
1036
|
+
success: true,
|
|
1037
|
+
output: value
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
// ============================================================================
|
|
1041
|
+
// Condition Evaluation
|
|
1042
|
+
// ============================================================================
|
|
1043
|
+
evaluateCondition(condition) {
|
|
1044
|
+
if (!condition) return false;
|
|
1045
|
+
const suspiciousKeywords = ["eval", "process", "require", "__proto__", "constructor"];
|
|
1046
|
+
if (suspiciousKeywords.some((kw) => condition.toLowerCase().includes(kw))) {
|
|
1047
|
+
logger.warn("Suspicious condition blocked", { condition });
|
|
1048
|
+
return false;
|
|
1049
|
+
}
|
|
1050
|
+
try {
|
|
1051
|
+
if (condition.trim().toLowerCase() === "true") return true;
|
|
1052
|
+
if (condition.trim().toLowerCase() === "false") return false;
|
|
1053
|
+
const comparisonPatterns = [
|
|
1054
|
+
{ regex: /^(.+?)\s*(===|!==)\s*(.+)$/ },
|
|
1055
|
+
{ regex: /^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/ },
|
|
1056
|
+
{ regex: /^(.+?)\s*(&&)\s*(.+)$/, logical: "and" },
|
|
1057
|
+
{ regex: /^(.+?)\s*(\|\|)\s*(.+)$/, logical: "or" }
|
|
1058
|
+
];
|
|
1059
|
+
for (const { regex, logical } of comparisonPatterns) {
|
|
1060
|
+
const match = condition.match(regex);
|
|
1061
|
+
if (match) {
|
|
1062
|
+
const [, leftExpr, operator, rightExpr] = match;
|
|
1063
|
+
const left = this.evaluateExpression(leftExpr.trim());
|
|
1064
|
+
const right = this.evaluateExpression(rightExpr.trim());
|
|
1065
|
+
if (logical === "and") return Boolean(left) && Boolean(right);
|
|
1066
|
+
if (logical === "or") return Boolean(left) || Boolean(right);
|
|
1067
|
+
switch (operator) {
|
|
1068
|
+
case "===":
|
|
1069
|
+
return left === right;
|
|
1070
|
+
case "!==":
|
|
1071
|
+
return left !== right;
|
|
1072
|
+
case "==":
|
|
1073
|
+
return left == right;
|
|
1074
|
+
case "!=":
|
|
1075
|
+
return left != right;
|
|
1076
|
+
case ">=":
|
|
1077
|
+
return Number(left) >= Number(right);
|
|
1078
|
+
case "<=":
|
|
1079
|
+
return Number(left) <= Number(right);
|
|
1080
|
+
case ">":
|
|
1081
|
+
return Number(left) > Number(right);
|
|
1082
|
+
case "<":
|
|
1083
|
+
return Number(left) < Number(right);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
if (condition.startsWith("!")) {
|
|
1088
|
+
return !this.evaluateCondition(condition.slice(1).trim());
|
|
1089
|
+
}
|
|
1090
|
+
const value = this.evaluateExpression(condition.trim());
|
|
1091
|
+
return Boolean(value);
|
|
1092
|
+
} catch (error) {
|
|
1093
|
+
logger.error("Condition evaluation error", { condition, error });
|
|
1094
|
+
return false;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
// ============================================================================
|
|
1098
|
+
// Transformation
|
|
1099
|
+
// ============================================================================
|
|
1100
|
+
async applyTransformation(data, transform) {
|
|
1101
|
+
const params = transform.parameters || {};
|
|
1102
|
+
switch (transform.operation) {
|
|
1103
|
+
case "filter": {
|
|
1104
|
+
if (!Array.isArray(data)) return data;
|
|
1105
|
+
const predicate = params.predicate;
|
|
1106
|
+
if (predicate) {
|
|
1107
|
+
return data.filter((item) => {
|
|
1108
|
+
this.setVariable("_item", item);
|
|
1109
|
+
return this.evaluateCondition(predicate);
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
return data.filter((item) => item !== null && item !== void 0);
|
|
1113
|
+
}
|
|
1114
|
+
case "map": {
|
|
1115
|
+
if (!Array.isArray(data)) return data;
|
|
1116
|
+
const mapper = params.mapper;
|
|
1117
|
+
if (mapper) {
|
|
1118
|
+
return data.map((item) => {
|
|
1119
|
+
this.setVariable("_item", item);
|
|
1120
|
+
return this.evaluateExpression(mapper);
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
return data.map((item) => ({ value: item, processed: true }));
|
|
1124
|
+
}
|
|
1125
|
+
case "reduce": {
|
|
1126
|
+
if (!Array.isArray(data)) return data;
|
|
1127
|
+
const initial = params.initial ?? 0;
|
|
1128
|
+
const reducer = params.reducer;
|
|
1129
|
+
if (reducer) {
|
|
1130
|
+
return data.reduce((acc, item) => {
|
|
1131
|
+
this.setVariable("_acc", acc);
|
|
1132
|
+
this.setVariable("_item", item);
|
|
1133
|
+
return this.evaluateExpression(reducer);
|
|
1134
|
+
}, initial);
|
|
1135
|
+
}
|
|
1136
|
+
return data.reduce((acc, item) => acc + (typeof item === "number" ? item : 0), 0);
|
|
1137
|
+
}
|
|
1138
|
+
case "sort": {
|
|
1139
|
+
if (!Array.isArray(data)) return data;
|
|
1140
|
+
const key = params.key;
|
|
1141
|
+
const desc = params.descending;
|
|
1142
|
+
const sorted = [...data].sort((a, b) => {
|
|
1143
|
+
const aVal = key ? a[key] : a;
|
|
1144
|
+
const bVal = key ? b[key] : b;
|
|
1145
|
+
if (aVal < bVal) return desc ? 1 : -1;
|
|
1146
|
+
if (aVal > bVal) return desc ? -1 : 1;
|
|
1147
|
+
return 0;
|
|
1148
|
+
});
|
|
1149
|
+
return sorted;
|
|
1150
|
+
}
|
|
1151
|
+
case "sum":
|
|
1152
|
+
return Array.isArray(data) ? data.reduce((sum, item) => sum + (typeof item === "number" ? item : 0), 0) : data;
|
|
1153
|
+
case "count":
|
|
1154
|
+
return Array.isArray(data) ? data.length : 1;
|
|
1155
|
+
case "unique":
|
|
1156
|
+
return Array.isArray(data) ? Array.from(new Set(data)) : data;
|
|
1157
|
+
case "flatten":
|
|
1158
|
+
return Array.isArray(data) ? data.flat() : data;
|
|
1159
|
+
case "reverse":
|
|
1160
|
+
return Array.isArray(data) ? [...data].reverse() : data;
|
|
1161
|
+
case "take": {
|
|
1162
|
+
if (!Array.isArray(data)) return data;
|
|
1163
|
+
const count = Number(params.count) || 10;
|
|
1164
|
+
return data.slice(0, count);
|
|
1165
|
+
}
|
|
1166
|
+
case "skip": {
|
|
1167
|
+
if (!Array.isArray(data)) return data;
|
|
1168
|
+
const count = Number(params.count) || 0;
|
|
1169
|
+
return data.slice(count);
|
|
1170
|
+
}
|
|
1171
|
+
default:
|
|
1172
|
+
logger.warn("Unknown transformation", { operation: transform.operation });
|
|
1173
|
+
return data;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
// ============================================================================
|
|
1177
|
+
// Event System
|
|
1178
|
+
// ============================================================================
|
|
1179
|
+
/**
|
|
1180
|
+
* Register event handler
|
|
1181
|
+
*/
|
|
1182
|
+
on(event, handler) {
|
|
1183
|
+
const handlers = this.eventHandlers.get(event) || [];
|
|
1184
|
+
handlers.push(handler);
|
|
1185
|
+
this.eventHandlers.set(event, handlers);
|
|
1186
|
+
}
|
|
1187
|
+
/**
|
|
1188
|
+
* Register host function
|
|
1189
|
+
*/
|
|
1190
|
+
registerFunction(name, handler) {
|
|
1191
|
+
this.builtinFunctions.set(name, handler);
|
|
1192
|
+
logger.info(`Host function registered: ${name}`);
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Remove event handler
|
|
1196
|
+
*/
|
|
1197
|
+
off(event, handler) {
|
|
1198
|
+
if (!handler) {
|
|
1199
|
+
this.eventHandlers.delete(event);
|
|
1200
|
+
} else {
|
|
1201
|
+
const handlers = this.eventHandlers.get(event) || [];
|
|
1202
|
+
this.eventHandlers.set(event, handlers.filter((h) => h !== handler));
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
/**
|
|
1206
|
+
* Emit event
|
|
1207
|
+
*/
|
|
1208
|
+
async emit(event, data) {
|
|
1209
|
+
const handlers = this.eventHandlers.get(event) || [];
|
|
1210
|
+
for (const handler of handlers) {
|
|
1211
|
+
try {
|
|
1212
|
+
await handler(data);
|
|
1213
|
+
} catch (error) {
|
|
1214
|
+
logger.error("Event handler error", { event, error });
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
/**
|
|
1219
|
+
* Trigger UI event
|
|
1220
|
+
*/
|
|
1221
|
+
async triggerUIEvent(elementName, eventType, data) {
|
|
1222
|
+
const element = this.uiElements.get(elementName);
|
|
1223
|
+
if (!element) {
|
|
1224
|
+
logger.warn("UI element not found", { elementName });
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
if (eventType === "change" && data !== void 0) {
|
|
1228
|
+
element.value = data;
|
|
1229
|
+
}
|
|
1230
|
+
await this.emit(`${elementName}.${eventType}`, data);
|
|
1231
|
+
}
|
|
1232
|
+
// ============================================================================
|
|
1233
|
+
// Animation System
|
|
1234
|
+
// ============================================================================
|
|
1235
|
+
/**
|
|
1236
|
+
* Update all animations
|
|
1237
|
+
*/
|
|
1238
|
+
updateAnimations() {
|
|
1239
|
+
const now = Date.now();
|
|
1240
|
+
for (const [key, anim] of this.animations) {
|
|
1241
|
+
const elapsed = now - anim.startTime;
|
|
1242
|
+
let progress = Math.min(elapsed / anim.duration, 1);
|
|
1243
|
+
progress = this.applyEasing(progress, anim.easing);
|
|
1244
|
+
let currentValue = anim.from + (anim.to - anim.from) * progress;
|
|
1245
|
+
if (anim.yoyo && progress >= 1) {
|
|
1246
|
+
anim.startTime = now;
|
|
1247
|
+
[anim.from, anim.to] = [anim.to, anim.from];
|
|
1248
|
+
}
|
|
1249
|
+
this.setVariable(`${anim.target}.${anim.property}`, currentValue);
|
|
1250
|
+
if (progress >= 1 && !anim.loop && !anim.yoyo) {
|
|
1251
|
+
this.animations.delete(key);
|
|
1252
|
+
} else if (progress >= 1 && anim.loop) {
|
|
1253
|
+
anim.startTime = now;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
this.updateSystemVariables();
|
|
1257
|
+
}
|
|
1258
|
+
/**
|
|
1259
|
+
* Update real-life and system variables ($time, $user, etc.)
|
|
1260
|
+
*/
|
|
1261
|
+
updateSystemVariables() {
|
|
1262
|
+
const now = /* @__PURE__ */ new Date();
|
|
1263
|
+
this.setVariable("$time", now.toLocaleTimeString());
|
|
1264
|
+
this.setVariable("$date", now.toLocaleDateString());
|
|
1265
|
+
this.setVariable("$timestamp", now.getTime());
|
|
1266
|
+
this.setVariable("$hour", now.getHours());
|
|
1267
|
+
this.setVariable("$minute", now.getMinutes());
|
|
1268
|
+
this.setVariable("$second", now.getSeconds());
|
|
1269
|
+
if (this.getVariable("$user") === void 0) {
|
|
1270
|
+
this.setVariable("$user", {
|
|
1271
|
+
id: "user_123",
|
|
1272
|
+
name: "Alpha Explorer",
|
|
1273
|
+
level: 42,
|
|
1274
|
+
rank: "Legendary",
|
|
1275
|
+
achievements: ["First World", "Spirit Guide"],
|
|
1276
|
+
preferences: { theme: "holographic", language: "en" }
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
if (this.getVariable("$location") === void 0) {
|
|
1280
|
+
this.setVariable("$location", {
|
|
1281
|
+
city: "Neo Tokyo",
|
|
1282
|
+
region: "Holo-Sector 7",
|
|
1283
|
+
coordinates: { lat: 35.6895, lng: 139.6917 },
|
|
1284
|
+
altitude: 450
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
if (this.getVariable("$weather") === void 0) {
|
|
1288
|
+
this.setVariable("$weather", {
|
|
1289
|
+
condition: "Neon Mist",
|
|
1290
|
+
temperature: 24,
|
|
1291
|
+
humidity: 65,
|
|
1292
|
+
windSpeed: 12,
|
|
1293
|
+
unit: "C"
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
if (this.getVariable("$wallet") === void 0) {
|
|
1297
|
+
this.setVariable("$wallet", {
|
|
1298
|
+
address: "0xHolo...42ff",
|
|
1299
|
+
balance: 1337.5,
|
|
1300
|
+
currency: "HOLO",
|
|
1301
|
+
network: "MainNet"
|
|
1302
|
+
});
|
|
1303
|
+
}
|
|
1304
|
+
if (this.getVariable("$ai_config") === void 0) {
|
|
1305
|
+
const savedKeys = typeof localStorage !== "undefined" ? localStorage.getItem("brittney_api_keys") : null;
|
|
1306
|
+
let configuredCount = 0;
|
|
1307
|
+
if (savedKeys) {
|
|
1308
|
+
try {
|
|
1309
|
+
const keys = JSON.parse(savedKeys);
|
|
1310
|
+
configuredCount = Object.values(keys).filter((k) => !!k).length;
|
|
1311
|
+
} catch (e) {
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
this.setVariable("$ai_config", {
|
|
1315
|
+
status: configuredCount > 0 ? "configured" : "pending",
|
|
1316
|
+
providerCount: configuredCount,
|
|
1317
|
+
lastUpdated: Date.now()
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
if (this.getVariable("$chat_status") === void 0) {
|
|
1321
|
+
this.setVariable("$chat_status", {
|
|
1322
|
+
active: true,
|
|
1323
|
+
typing: false,
|
|
1324
|
+
version: "1.0.0-brittney"
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
// ==========================================================================
|
|
1329
|
+
// COMMERCE PRIMITIVES
|
|
1330
|
+
// ==========================================================================
|
|
1331
|
+
handleShop(args) {
|
|
1332
|
+
const config = args[0] || {};
|
|
1333
|
+
this.emit("shop", config);
|
|
1334
|
+
return { success: true, type: "shop", config };
|
|
1335
|
+
}
|
|
1336
|
+
handleInventory(args) {
|
|
1337
|
+
const item = args[0];
|
|
1338
|
+
const action = args[1] || "add";
|
|
1339
|
+
this.emit("inventory", { item, action });
|
|
1340
|
+
return { success: true, item, action };
|
|
1341
|
+
}
|
|
1342
|
+
handlePurchase(args) {
|
|
1343
|
+
const productId = args[0];
|
|
1344
|
+
this.emit("purchase", { productId });
|
|
1345
|
+
return { success: true, productId, status: "pending" };
|
|
1346
|
+
}
|
|
1347
|
+
// ==========================================================================
|
|
1348
|
+
// SOCIAL PRIMITIVES
|
|
1349
|
+
// ==========================================================================
|
|
1350
|
+
handlePresence(args) {
|
|
1351
|
+
const config = args[0] || {};
|
|
1352
|
+
this.emit("presence", config);
|
|
1353
|
+
return { success: true, active: true };
|
|
1354
|
+
}
|
|
1355
|
+
handleInvite(args) {
|
|
1356
|
+
const userId = args[0];
|
|
1357
|
+
this.emit("invite", { userId });
|
|
1358
|
+
return { success: true, userId };
|
|
1359
|
+
}
|
|
1360
|
+
handleShare(args) {
|
|
1361
|
+
const scriptId = args[0];
|
|
1362
|
+
const targetUserId = args[1];
|
|
1363
|
+
this.emit("share", { scriptId, targetUserId });
|
|
1364
|
+
return { success: true, scriptId };
|
|
1365
|
+
}
|
|
1366
|
+
// ==========================================================================
|
|
1367
|
+
// PHYSICS PRIMITIVES
|
|
1368
|
+
// ==========================================================================
|
|
1369
|
+
handlePhysics(args) {
|
|
1370
|
+
const config = args[0] || {};
|
|
1371
|
+
this.emit("physics", config);
|
|
1372
|
+
return { success: true, enabled: config.enabled !== false };
|
|
1373
|
+
}
|
|
1374
|
+
handleGravity(args) {
|
|
1375
|
+
const value = args[0] ?? 9.81;
|
|
1376
|
+
this.emit("gravity", { value });
|
|
1377
|
+
return { success: true, value };
|
|
1378
|
+
}
|
|
1379
|
+
handleCollide(args) {
|
|
1380
|
+
const target = args[0];
|
|
1381
|
+
const handler = args[1];
|
|
1382
|
+
this.emit("collide", { target, handler });
|
|
1383
|
+
return { success: true, target };
|
|
1384
|
+
}
|
|
1385
|
+
/**
|
|
1386
|
+
* Handle calculate_arc(start, end, speed)
|
|
1387
|
+
*/
|
|
1388
|
+
handleCalculateArc(args) {
|
|
1389
|
+
if (args.length < 3) return { x: 0, y: 0, z: 0 };
|
|
1390
|
+
const start = args[0];
|
|
1391
|
+
const end = args[1];
|
|
1392
|
+
const speed = args[2];
|
|
1393
|
+
const dx = end.x - start.x;
|
|
1394
|
+
const dz = end.z - start.z;
|
|
1395
|
+
const dy = end.y - start.y;
|
|
1396
|
+
const dist = Math.sqrt(dx * dx + dz * dz);
|
|
1397
|
+
if (dist < 0.1) return { x: 0, y: speed, z: 0 };
|
|
1398
|
+
const t = dist / speed;
|
|
1399
|
+
const vx = dx / t;
|
|
1400
|
+
const vz = dz / t;
|
|
1401
|
+
const vy = dy / t + 0.5 * 9.81 * t;
|
|
1402
|
+
return { x: vx, y: vy, z: vz };
|
|
1403
|
+
}
|
|
1404
|
+
handleAnimate(args) {
|
|
1405
|
+
const options = args[0] || {};
|
|
1406
|
+
this.emit("animate", options);
|
|
1407
|
+
return { success: true, options };
|
|
1408
|
+
}
|
|
1409
|
+
applyEasing(t, easing) {
|
|
1410
|
+
switch (easing) {
|
|
1411
|
+
case "easeIn":
|
|
1412
|
+
return t * t;
|
|
1413
|
+
case "easeOut":
|
|
1414
|
+
return t * (2 - t);
|
|
1415
|
+
case "easeInOut":
|
|
1416
|
+
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
|
1417
|
+
case "easeInQuad":
|
|
1418
|
+
return t * t;
|
|
1419
|
+
case "easeOutQuad":
|
|
1420
|
+
return t * (2 - t);
|
|
1421
|
+
case "easeInOutQuad":
|
|
1422
|
+
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
|
1423
|
+
case "linear":
|
|
1424
|
+
default:
|
|
1425
|
+
return t;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
// ============================================================================
|
|
1429
|
+
// Particle Effects
|
|
1430
|
+
// ============================================================================
|
|
1431
|
+
createParticleEffect(name, position, color, count) {
|
|
1432
|
+
const limitedCount = Math.min(count, RUNTIME_SECURITY_LIMITS.maxParticlesPerSystem);
|
|
1433
|
+
const particles = [];
|
|
1434
|
+
for (let i = 0; i < limitedCount; i++) {
|
|
1435
|
+
particles.push({
|
|
1436
|
+
x: position.x + (Math.random() - 0.5) * 2,
|
|
1437
|
+
y: position.y + (Math.random() - 0.5) * 2,
|
|
1438
|
+
z: position.z + (Math.random() - 0.5) * 2
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1441
|
+
this.particleSystems.set(name, {
|
|
1442
|
+
particles,
|
|
1443
|
+
color,
|
|
1444
|
+
lifetime: 3e3,
|
|
1445
|
+
speed: 0.01
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
createConnectionStream(from, to, fromPos, toPos, dataType) {
|
|
1449
|
+
const streamName = `connection_${from}_${to}`;
|
|
1450
|
+
const particles = [];
|
|
1451
|
+
const steps = 20;
|
|
1452
|
+
for (let i = 0; i <= steps; i++) {
|
|
1453
|
+
const t = i / steps;
|
|
1454
|
+
particles.push({
|
|
1455
|
+
x: fromPos.x + (toPos.x - fromPos.x) * t,
|
|
1456
|
+
y: fromPos.y + (toPos.y - fromPos.y) * t,
|
|
1457
|
+
z: fromPos.z + (toPos.z - fromPos.z) * t
|
|
1458
|
+
});
|
|
1459
|
+
}
|
|
1460
|
+
this.particleSystems.set(streamName, {
|
|
1461
|
+
particles,
|
|
1462
|
+
color: this.getDataTypeColor(dataType),
|
|
1463
|
+
lifetime: 5e3,
|
|
1464
|
+
speed: 0.02
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
createFlowingStream(name, position, data) {
|
|
1468
|
+
const count = Array.isArray(data) ? Math.min(data.length, 50) : 10;
|
|
1469
|
+
this.createParticleEffect(`${name}_flow`, position, "#45b7d1", count);
|
|
1470
|
+
}
|
|
1471
|
+
createExecutionEffect(name, position) {
|
|
1472
|
+
this.createParticleEffect(`${name}_execution`, position, "#ff4500", 30);
|
|
1473
|
+
}
|
|
1474
|
+
createDataVisualization(name, data, position) {
|
|
1475
|
+
let count = 10;
|
|
1476
|
+
if (Array.isArray(data)) {
|
|
1477
|
+
count = Math.min(data.length, 100);
|
|
1478
|
+
} else if (typeof data === "object" && data !== null) {
|
|
1479
|
+
count = Math.min(Object.keys(data).length * 5, 50);
|
|
1480
|
+
}
|
|
1481
|
+
this.createParticleEffect(`${name}_visualization`, position, "#32cd32", count);
|
|
1482
|
+
}
|
|
1483
|
+
getDataTypeColor(dataType) {
|
|
1484
|
+
const colors = {
|
|
1485
|
+
"string": "#ff6b35",
|
|
1486
|
+
"number": "#4ecdc4",
|
|
1487
|
+
"boolean": "#45b7d1",
|
|
1488
|
+
"object": "#96ceb4",
|
|
1489
|
+
"array": "#ffeaa7",
|
|
1490
|
+
"any": "#dda0dd",
|
|
1491
|
+
"move": "#ff69b4"
|
|
1492
|
+
};
|
|
1493
|
+
return colors[dataType] || "#ffffff";
|
|
1494
|
+
}
|
|
1495
|
+
// ============================================================================
|
|
1496
|
+
// Public API
|
|
1497
|
+
// ============================================================================
|
|
1498
|
+
getParticleSystems() {
|
|
1499
|
+
return new Map(this.particleSystems);
|
|
1500
|
+
}
|
|
1501
|
+
updateParticles(deltaTime) {
|
|
1502
|
+
for (const [name, system] of this.particleSystems) {
|
|
1503
|
+
system.lifetime -= deltaTime;
|
|
1504
|
+
system.particles.forEach((particle) => {
|
|
1505
|
+
particle.x += (Math.random() - 0.5) * system.speed;
|
|
1506
|
+
particle.y += (Math.random() - 0.5) * system.speed;
|
|
1507
|
+
particle.z += (Math.random() - 0.5) * system.speed;
|
|
1508
|
+
});
|
|
1509
|
+
if (system.lifetime <= 0) {
|
|
1510
|
+
this.particleSystems.delete(name);
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
getContext() {
|
|
1515
|
+
return { ...this.context };
|
|
1516
|
+
}
|
|
1517
|
+
getUIElements() {
|
|
1518
|
+
return new Map(this.uiElements);
|
|
1519
|
+
}
|
|
1520
|
+
getUIElement(name) {
|
|
1521
|
+
return this.uiElements.get(name);
|
|
1522
|
+
}
|
|
1523
|
+
getAnimations() {
|
|
1524
|
+
return new Map(this.animations);
|
|
1525
|
+
}
|
|
1526
|
+
reset() {
|
|
1527
|
+
this.context = this.createEmptyContext();
|
|
1528
|
+
this.currentScope = { variables: this.context.variables };
|
|
1529
|
+
this.callStack = [];
|
|
1530
|
+
this.particleSystems.clear();
|
|
1531
|
+
this.executionHistory = [];
|
|
1532
|
+
this.eventHandlers.clear();
|
|
1533
|
+
this.animations.clear();
|
|
1534
|
+
this.uiElements.clear();
|
|
1535
|
+
}
|
|
1536
|
+
createEmptyContext() {
|
|
1537
|
+
return {
|
|
1538
|
+
variables: /* @__PURE__ */ new Map(),
|
|
1539
|
+
functions: /* @__PURE__ */ new Map(),
|
|
1540
|
+
exports: /* @__PURE__ */ new Map(),
|
|
1541
|
+
connections: [],
|
|
1542
|
+
spatialMemory: /* @__PURE__ */ new Map(),
|
|
1543
|
+
hologramState: /* @__PURE__ */ new Map(),
|
|
1544
|
+
executionStack: [],
|
|
1545
|
+
currentScale: 1,
|
|
1546
|
+
scaleMagnitude: "standard",
|
|
1547
|
+
focusHistory: [],
|
|
1548
|
+
environment: {},
|
|
1549
|
+
templates: /* @__PURE__ */ new Map(),
|
|
1550
|
+
state: createState({})
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1553
|
+
async executeScale(node) {
|
|
1554
|
+
const parentScale = this.context.currentScale;
|
|
1555
|
+
this.context.currentScale *= node.multiplier;
|
|
1556
|
+
this.context.scaleMagnitude = node.magnitude;
|
|
1557
|
+
logger.info("Scale context entering", { magnitude: node.magnitude, multiplier: this.context.currentScale });
|
|
1558
|
+
this.emit("scale:change", { multiplier: this.context.currentScale, magnitude: node.magnitude });
|
|
1559
|
+
const results = await this.executeProgram(node.body, this.context.executionStack.length);
|
|
1560
|
+
this.context.currentScale = parentScale;
|
|
1561
|
+
this.emit("scale:change", { multiplier: this.context.currentScale });
|
|
1562
|
+
return {
|
|
1563
|
+
success: results.every((r) => r.success),
|
|
1564
|
+
output: `Executed scale block: ${node.magnitude}`
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
async executeFocus(node) {
|
|
1568
|
+
this.context.focusHistory.push(node.target);
|
|
1569
|
+
const results = await this.executeProgram(node.body, this.context.executionStack.length);
|
|
1570
|
+
return {
|
|
1571
|
+
success: results.every((r) => r.success),
|
|
1572
|
+
output: `Focused on ${node.target}`
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1575
|
+
async executeEnvironment(node) {
|
|
1576
|
+
this.context.environment = { ...this.context.environment, ...node.settings };
|
|
1577
|
+
return { success: true, output: "Environment updated" };
|
|
1578
|
+
}
|
|
1579
|
+
async executeComposition(node) {
|
|
1580
|
+
return {
|
|
1581
|
+
success: (await this.executeProgram(node.children, this.context.executionStack.length)).every((r) => r.success),
|
|
1582
|
+
output: `Composition ${node.name} executed`
|
|
1583
|
+
};
|
|
1584
|
+
}
|
|
1585
|
+
async executeTemplate(node) {
|
|
1586
|
+
this.context.templates.set(node.name, node);
|
|
1587
|
+
return { success: true, output: `Template ${node.name} registered` };
|
|
1588
|
+
}
|
|
1589
|
+
async executeServerNode(node) {
|
|
1590
|
+
if (this.context.mode === "public") {
|
|
1591
|
+
return { success: false, error: "SecurityViolation: Server creation blocked in public mode.", executionTime: 0 };
|
|
1592
|
+
}
|
|
1593
|
+
logger.info(`Starting server on port ${node.port}`);
|
|
1594
|
+
return {
|
|
1595
|
+
success: true,
|
|
1596
|
+
output: `Server listening on port ${node.port}`,
|
|
1597
|
+
hologram: node.hologram,
|
|
1598
|
+
executionTime: 0
|
|
1599
|
+
};
|
|
1600
|
+
}
|
|
1601
|
+
async executeDatabaseNode(node) {
|
|
1602
|
+
if (this.context.mode === "public") {
|
|
1603
|
+
return { success: false, error: "SecurityViolation: DB access blocked in public mode.", executionTime: 0 };
|
|
1604
|
+
}
|
|
1605
|
+
logger.info(`Executing Query: ${node.query}`);
|
|
1606
|
+
return {
|
|
1607
|
+
success: true,
|
|
1608
|
+
output: `Query executed: ${node.query}`,
|
|
1609
|
+
hologram: node.hologram,
|
|
1610
|
+
executionTime: 0
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
async executeFetchNode(node) {
|
|
1614
|
+
if (this.context.mode === "public") {
|
|
1615
|
+
return { success: false, error: "SecurityViolation: External fetch blocked in public mode.", executionTime: 0 };
|
|
1616
|
+
}
|
|
1617
|
+
logger.info(`Fetching: ${node.url}`);
|
|
1618
|
+
return {
|
|
1619
|
+
success: true,
|
|
1620
|
+
output: `Fetched data from ${node.url}`,
|
|
1621
|
+
hologram: node.hologram,
|
|
1622
|
+
executionTime: 0
|
|
1623
|
+
};
|
|
1624
|
+
}
|
|
1625
|
+
async executeTarget(node) {
|
|
1626
|
+
const target = this.context.functions.get(node.target);
|
|
1627
|
+
if (!target) {
|
|
1628
|
+
return {
|
|
1629
|
+
success: false,
|
|
1630
|
+
error: `Function ${node.target} not found`,
|
|
1631
|
+
executionTime: 0
|
|
1632
|
+
};
|
|
1633
|
+
}
|
|
1634
|
+
const result = await this.executeFunction(target);
|
|
1635
|
+
this.createExecutionEffect(node.target, target.position || { x: 0, y: 0, z: 0 });
|
|
1636
|
+
return {
|
|
1637
|
+
success: true,
|
|
1638
|
+
output: `Executed ${node.target}`,
|
|
1639
|
+
hologram: {
|
|
1640
|
+
shape: "sphere",
|
|
1641
|
+
color: "#ff4500",
|
|
1642
|
+
size: 1.2,
|
|
1643
|
+
glow: true,
|
|
1644
|
+
interactive: false
|
|
1645
|
+
},
|
|
1646
|
+
executionTime: result.executionTime
|
|
1647
|
+
};
|
|
1648
|
+
}
|
|
1649
|
+
async executeStateDeclaration(node) {
|
|
1650
|
+
const stateDirective = node.directives?.find((d) => d.type === "state");
|
|
1651
|
+
if (stateDirective) {
|
|
1652
|
+
this.context.state.update(stateDirective.body);
|
|
1653
|
+
}
|
|
1654
|
+
return { success: true, output: "State updated" };
|
|
1655
|
+
}
|
|
1656
|
+
applyDirectives(node) {
|
|
1657
|
+
if (!node.directives) return;
|
|
1658
|
+
for (const d of node.directives) {
|
|
1659
|
+
if (d.type === "trait") {
|
|
1660
|
+
logger.info(`Applying trait ${d.name} to ${node.type}`);
|
|
1661
|
+
if (d.name === "chat") {
|
|
1662
|
+
this.emit("show-chat", d.config);
|
|
1663
|
+
}
|
|
1664
|
+
} else if (d.type === "state") {
|
|
1665
|
+
this.context.state.update(d.body);
|
|
1666
|
+
} else if (d.type === "lifecycle") {
|
|
1667
|
+
if (d.hook === "on_mount") {
|
|
1668
|
+
this.evaluateExpression(d.body);
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
getExecutionHistory() {
|
|
1674
|
+
return [...this.executionHistory];
|
|
1675
|
+
}
|
|
1676
|
+
getHologramStates() {
|
|
1677
|
+
return new Map(this.context.hologramState);
|
|
1678
|
+
}
|
|
1679
|
+
getCallStack() {
|
|
1680
|
+
return [...this.callStack];
|
|
1681
|
+
}
|
|
1682
|
+
getState() {
|
|
1683
|
+
return this.context.state.getSnapshot();
|
|
1684
|
+
}
|
|
1685
|
+
};
|
|
1686
|
+
|
|
1687
|
+
export { HoloScriptRuntime };
|
|
1688
|
+
//# sourceMappingURL=chunk-AFFVFO4D.js.map
|
|
1689
|
+
//# sourceMappingURL=chunk-AFFVFO4D.js.map
|