@ultrst-armada/kloks 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -2,5 +2,6 @@ export * from './packages/functions/dist/index.d.ts';
2
2
  export * from './packages/state-graph/dist/index.d.ts';
3
3
  export * from './packages/audio-midi/dist/index.d.ts';
4
4
  export * from './packages/services/dist/index.d.ts';
5
+ export * from './packages/backend/dist/index.d.ts';
5
6
  export * from './packages/orchestrations/dist/index.d.ts';
6
7
  export * from './packages/contracts/dist/index.d.ts';
package/index.js CHANGED
@@ -2,5 +2,6 @@ export * from './packages/functions/dist/index.js';
2
2
  export * from './packages/state-graph/dist/index.js';
3
3
  export * from './packages/audio-midi/dist/index.js';
4
4
  export * from './packages/services/dist/index.js';
5
+ export * from './packages/backend/dist/index.js';
5
6
  export * from './packages/orchestrations/dist/index.js';
6
7
  export * from './packages/contracts/dist/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultrst-armada/kloks",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -84,6 +84,11 @@
84
84
  "import": "./packages/backend/dist/execution/index.js",
85
85
  "default": "./packages/backend/dist/execution/index.js"
86
86
  },
87
+ "./backend/krnl-services": {
88
+ "types": "./packages/backend/dist/krnl-services.d.ts",
89
+ "import": "./packages/backend/dist/krnl-services.js",
90
+ "default": "./packages/backend/dist/krnl-services.js"
91
+ },
87
92
  "./orchestrations": {
88
93
  "types": "./packages/orchestrations/dist/index.d.ts",
89
94
  "import": "./packages/orchestrations/dist/index.js",
@@ -95,13 +100,6 @@
95
100
  "default": "./packages/contracts/dist/index.js"
96
101
  }
97
102
  },
98
- "scripts": {
99
- "build": "pnpm -r run build",
100
- "postbuild": "node -e \"import('fs').then(fs => { for (const pkg of fs.readdirSync('packages')) { const d = 'packages/' + pkg + '/dist'; if (!fs.existsSync(d)) continue; for (const f of fs.readdirSync(d, { recursive: true })) { const p = d + '/' + f; if (fs.statSync(p).isFile() && (p.endsWith('.js') || p.endsWith('.d.ts'))) { const c = fs.readFileSync(p, 'utf8'); const n = c.replaceAll('@kloks/', '@ultrst-armada/kloks/').replaceAll('@ultrst/kloks/', '@ultrst-armada/kloks/').replaceAll('\\\"kloks/', '\\\"@ultrst-armada/kloks/').replaceAll('\\'kloks/', '\\'@ultrst-armada/kloks/'); if (c !== n) fs.writeFileSync(p, n); } } } })\"",
101
- "test": "vitest run",
102
- "typecheck": "pnpm -r run typecheck",
103
- "clean": "pnpm -r run clean"
104
- },
105
103
  "dependencies": {
106
104
  "bullmq": "^6.3.8",
107
105
  "zod": "^3.24.1",
@@ -124,5 +122,11 @@
124
122
  "typescript": "^5.7.3",
125
123
  "vitest": "^3.1.0"
126
124
  },
127
- "packageManager": "pnpm@9.15.0"
128
- }
125
+ "scripts": {
126
+ "build": "pnpm -r run build",
127
+ "postbuild": "node -e \"import('fs').then(fs => { for (const pkg of fs.readdirSync('packages')) { const d = 'packages/' + pkg + '/dist'; if (!fs.existsSync(d)) continue; for (const f of fs.readdirSync(d, { recursive: true })) { const p = d + '/' + f; if (fs.statSync(p).isFile() && (p.endsWith('.js') || p.endsWith('.d.ts'))) { const c = fs.readFileSync(p, 'utf8'); const n = c.replaceAll('@kloks/', '@ultrst-armada/kloks/').replaceAll('@ultrst/kloks/', '@ultrst-armada/kloks/').replaceAll('\\\"kloks/', '\\\"@ultrst-armada/kloks/').replaceAll('\\'kloks/', '\\'@ultrst-armada/kloks/'); if (c !== n) fs.writeFileSync(p, n); } } } })\"",
128
+ "test": "vitest run",
129
+ "typecheck": "pnpm -r run typecheck",
130
+ "clean": "pnpm -r run clean"
131
+ }
132
+ }
@@ -1,4 +1,4 @@
1
- import { N as NodePosition, b as NodeSize, B as BaseNode } from './BaseNode-1HCEqmap.js';
1
+ import { N as NodePosition, a as NodeSize, b as BaseNode } from './BaseNode-DTcd3K1B.js';
2
2
  import { B as BaseConnection } from './BaseConnection-CMRrL6Fe.js';
3
3
 
4
4
  type DynamicState = 'INACTIVE' | 'ACTIVE' | 'PINNED_LIVE';
@@ -120,4 +120,4 @@ declare class CustomNode extends BaseNode {
120
120
  customDefinition?: NodeDefinition;
121
121
  }
122
122
 
123
- export { BaseNode as B, type ConnectionMode as C, DataHandle as D, type HandleCategory as H, type NodePosition as N, ViewHandle as V, BaseHandle as a, type NodeSize as b, type BaseHandleProps as c, type BaseNodeProps as d, CustomNode as e, type HandleDefinition as f, type HandleDirection as g, type HandleOffset as h, type HandlePosition as i, type NodeDefinition as j };
123
+ export { BaseHandle as B, type ConnectionMode as C, DataHandle as D, type HandleCategory as H, type NodePosition as N, ViewHandle as V, type NodeSize as a, BaseNode as b, type HandleDirection as c, type BaseHandleProps as d, type BaseNodeProps as e, CustomNode as f, type HandleDefinition as g, type HandleOffset as h, type HandlePosition as i, type NodeDefinition as j };
@@ -1,4 +1,4 @@
1
- import { a as BaseHandle, H as HandleCategory } from './BaseNode-1HCEqmap.js';
1
+ import { B as BaseHandle, H as HandleCategory } from './BaseNode-DTcd3K1B.js';
2
2
 
3
3
  interface CompatibilityRule {
4
4
  sourceCategory: HandleCategory;
@@ -0,0 +1,459 @@
1
+ import {
2
+ ConnectionRuleStore,
3
+ WireTypeRegistry
4
+ } from "./chunk-TZOL3RN7.js";
5
+
6
+ // src/spatial/AttractionEngine.ts
7
+ var AttractionEngine = class {
8
+ static computeSimilarity(nodeA, nodeB) {
9
+ if (nodeA.id === nodeB.id) return 1;
10
+ let score = 0;
11
+ let factors = 0;
12
+ factors += 1;
13
+ if (nodeA.type === nodeB.type) {
14
+ score += 1;
15
+ }
16
+ factors += 1;
17
+ const inTypesA = new Set(nodeA.handles.filter((h) => h.direction === "INPUT").map((h) => h.dataType));
18
+ const inTypesB = new Set(nodeB.handles.filter((h) => h.direction === "INPUT").map((h) => h.dataType));
19
+ const sharedIn = [...inTypesA].filter((t) => inTypesB.has(t)).length;
20
+ const totalIn = Math.max(1, (/* @__PURE__ */ new Set([...inTypesA, ...inTypesB])).size);
21
+ score += sharedIn / totalIn;
22
+ factors += 1;
23
+ const outTypesA = new Set(nodeA.handles.filter((h) => h.direction === "OUTPUT").map((h) => h.dataType));
24
+ const outTypesB = new Set(nodeB.handles.filter((h) => h.direction === "OUTPUT").map((h) => h.dataType));
25
+ const sharedOut = [...outTypesA].filter((t) => outTypesB.has(t)).length;
26
+ const totalOut = Math.max(1, (/* @__PURE__ */ new Set([...outTypesA, ...outTypesB])).size);
27
+ score += sharedOut / totalOut;
28
+ return factors > 0 ? score / factors : 0;
29
+ }
30
+ static calculateStep(nodes, strength = 1, speed = 1) {
31
+ const updatedPositions = /* @__PURE__ */ new Map();
32
+ for (let i = 0; i < nodes.length; i++) {
33
+ const nodeA = nodes[i];
34
+ if (nodeA.positionLocked) {
35
+ updatedPositions.set(nodeA.id, { ...nodeA.position });
36
+ continue;
37
+ }
38
+ let forceX = 0;
39
+ let forceY = 0;
40
+ for (let j = 0; j < nodes.length; j++) {
41
+ if (i === j) continue;
42
+ const nodeB = nodes[j];
43
+ const similarity = this.computeSimilarity(nodeA, nodeB);
44
+ if (similarity <= 0.1) continue;
45
+ const dx = nodeB.position.x - nodeA.position.x;
46
+ const dy = nodeB.position.y - nodeA.position.y;
47
+ const dist = Math.max(20, Math.sqrt(dx * dx + dy * dy));
48
+ const f = similarity * strength * speed;
49
+ forceX += dx / dist * f;
50
+ forceY += dy / dist * f;
51
+ }
52
+ updatedPositions.set(nodeA.id, {
53
+ x: nodeA.position.x + forceX,
54
+ y: nodeA.position.y + forceY
55
+ });
56
+ }
57
+ return updatedPositions;
58
+ }
59
+ };
60
+
61
+ // src/spatial/socketCoordinates.ts
62
+ function calculateSocketCoordinates(baseY, options) {
63
+ const clearance = Math.max(12, options.clearance ?? 14);
64
+ const nudge = options.nudge ?? { x: 0, y: 0 };
65
+ const halfWidth = options.cardWidth / 2;
66
+ const halfHeight = (options.cardHeight ?? 80) / 2;
67
+ const baseX = options.isOutput ? halfWidth + clearance : -halfWidth - clearance;
68
+ let effectiveX = baseX + nudge.x;
69
+ let effectiveY = baseY + nudge.y;
70
+ const minMargin = 4;
71
+ const bodyLeft = -halfWidth;
72
+ const bodyRight = halfWidth;
73
+ const bodyTop = -halfHeight;
74
+ const bodyBottom = halfHeight;
75
+ if (effectiveX > bodyLeft - minMargin && effectiveX < bodyRight + minMargin && effectiveY > bodyTop - minMargin && effectiveY < bodyBottom + minMargin) {
76
+ if (options.isOutput) {
77
+ effectiveX = bodyRight + Math.max(minMargin, clearance / 2);
78
+ } else {
79
+ effectiveX = bodyLeft - Math.max(minMargin, clearance / 2);
80
+ }
81
+ }
82
+ return {
83
+ baseX,
84
+ effectiveX,
85
+ effectiveY,
86
+ nudge: {
87
+ x: effectiveX - baseX,
88
+ y: effectiveY - baseY
89
+ }
90
+ };
91
+ }
92
+ var getBeamPoints = (nudge, baseW = 5, headW = 1.2) => {
93
+ const vx = -nudge.x;
94
+ const vy = -nudge.y;
95
+ const d = Math.sqrt(vx * vx + vy * vy);
96
+ if (d < 1) return "";
97
+ const px = -vy / d;
98
+ const py = vx / d;
99
+ const hL_x = -px * headW;
100
+ const hL_y = -py * headW;
101
+ const hR_x = px * headW;
102
+ const hR_y = py * headW;
103
+ const bR_x = vx + px * baseW;
104
+ const bR_y = vy + py * baseW;
105
+ const bL_x = vx - px * baseW;
106
+ const bL_y = vy - py * baseW;
107
+ return `${hL_x},${hL_y} ${hR_x},${hR_y} ${bR_x},${bR_y} ${bL_x},${bL_y}`;
108
+ };
109
+
110
+ // src/spatial/useMagneticTraces.ts
111
+ import { useMemo, useCallback } from "react";
112
+ function getSocketCanvasPos(node, socket, isOut, idx, total) {
113
+ const h = node.height ?? 130;
114
+ const w = node.width ?? 130;
115
+ const topOffset = total === 1 ? h * 0.5 : h * 0.25 + idx * 24;
116
+ const nudge = socket.offset ?? { x: 0, y: 0 };
117
+ const baseX = isOut ? node.position.x + w : node.position.x;
118
+ return {
119
+ x: baseX + nudge.x,
120
+ y: node.position.y + topOffset + nudge.y
121
+ };
122
+ }
123
+ function useMagneticTraces({
124
+ nodes,
125
+ edges,
126
+ config,
127
+ onEdgesChange
128
+ }) {
129
+ const isEnabled = config?.magneticTracesEnabled !== false && config?.tracingEnabled !== false;
130
+ const cutoff = config?.traceCutoffDistance ?? 220;
131
+ const traces = useMemo(() => {
132
+ if (!isEnabled || nodes.length < 2) return [];
133
+ const existingEdgeKeys = new Set(
134
+ edges.map((e) => `${e.source}:${e.sourceSocket}->${e.target}:${e.targetSocket}`)
135
+ );
136
+ const candidates = [];
137
+ for (let i = 0; i < nodes.length; i++) {
138
+ const srcNode = nodes[i];
139
+ const outputs = srcNode.outputs ?? [];
140
+ if (outputs.length === 0) continue;
141
+ for (let j = 0; j < nodes.length; j++) {
142
+ if (i === j) continue;
143
+ const tgtNode = nodes[j];
144
+ const inputs = tgtNode.inputs ?? [];
145
+ if (inputs.length === 0) continue;
146
+ outputs.forEach((outSock, outIdx) => {
147
+ const outPos = getSocketCanvasPos(srcNode, outSock, true, outIdx, outputs.length);
148
+ inputs.forEach((inSock, inIdx) => {
149
+ const edgeKey = `${srcNode.id}:${outSock.id}->${tgtNode.id}:${inSock.id}`;
150
+ if (existingEdgeKeys.has(edgeKey)) return;
151
+ const inPos = getSocketCanvasPos(tgtNode, inSock, false, inIdx, inputs.length);
152
+ const dist = Math.hypot(inPos.x - outPos.x, inPos.y - outPos.y);
153
+ if (dist <= cutoff) {
154
+ const canConnect = ConnectionRuleStore.canConnect(
155
+ { dataType: outSock.dataType || "ANY", direction: "OUTPUT", handleCategory: "DATA" },
156
+ { dataType: inSock.dataType || "ANY", direction: "INPUT", handleCategory: "DATA" }
157
+ );
158
+ if (canConnect) {
159
+ const resolution = ConnectionRuleStore.resolve(
160
+ { dataType: outSock.dataType || "ANY", direction: "OUTPUT", handleCategory: "DATA" },
161
+ { dataType: inSock.dataType || "ANY", direction: "INPUT", handleCategory: "DATA" }
162
+ );
163
+ const wireType = resolution.wireType || "DEFAULT";
164
+ const wireDef = WireTypeRegistry.get(wireType);
165
+ const color = wireDef?.color || "#61afef";
166
+ const delta = Math.max(Math.abs(inPos.x - outPos.x) * 0.5, 40);
167
+ const pathD = `M ${outPos.x},${outPos.y} C ${outPos.x + delta},${outPos.y} ${inPos.x - delta},${inPos.y} ${inPos.x},${inPos.y}`;
168
+ candidates.push({
169
+ id: `mag-${srcNode.id}-${outSock.id}->${tgtNode.id}-${inSock.id}`,
170
+ sourceNodeId: srcNode.id,
171
+ sourceSocketId: outSock.id,
172
+ targetNodeId: tgtNode.id,
173
+ targetSocketId: inSock.id,
174
+ wireType,
175
+ color,
176
+ pathD,
177
+ midpoint: { x: (outPos.x + inPos.x) / 2, y: (outPos.y + inPos.y) / 2 },
178
+ distance: dist
179
+ });
180
+ }
181
+ }
182
+ });
183
+ });
184
+ }
185
+ }
186
+ candidates.sort((a, b) => a.distance - b.distance);
187
+ const claimedOutputs = /* @__PURE__ */ new Set();
188
+ const claimedInputs = /* @__PURE__ */ new Set();
189
+ const filtered = [];
190
+ for (const c of candidates) {
191
+ const outKey = `${c.sourceNodeId}:${c.sourceSocketId}`;
192
+ const inKey = `${c.targetNodeId}:${c.targetSocketId}`;
193
+ if (!claimedOutputs.has(outKey) && !claimedInputs.has(inKey)) {
194
+ claimedOutputs.add(outKey);
195
+ claimedInputs.add(inKey);
196
+ filtered.push(c);
197
+ }
198
+ }
199
+ return filtered;
200
+ }, [nodes, edges, isEnabled, cutoff]);
201
+ const solidifyTrace = useCallback((traceId) => {
202
+ const trace = traces.find((t) => t.id === traceId);
203
+ if (!trace || !onEdgesChange) return;
204
+ const newEdge = {
205
+ id: `edge-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
206
+ source: trace.sourceNodeId,
207
+ sourceSocket: trace.sourceSocketId,
208
+ target: trace.targetNodeId,
209
+ targetSocket: trace.targetSocketId,
210
+ wireType: trace.wireType,
211
+ color: trace.color,
212
+ locked: true
213
+ };
214
+ onEdgesChange([...edges, newEdge]);
215
+ }, [traces, edges, onEdgesChange]);
216
+ const solidifyAll = useCallback(() => {
217
+ if (traces.length === 0 || !onEdgesChange) return;
218
+ const newEdges = traces.map((t, idx) => ({
219
+ id: `edge-${Date.now()}-${idx}`,
220
+ source: t.sourceNodeId,
221
+ sourceSocket: t.sourceSocketId,
222
+ target: t.targetNodeId,
223
+ targetSocket: t.targetSocketId,
224
+ wireType: t.wireType,
225
+ color: t.color,
226
+ locked: true
227
+ }));
228
+ onEdgesChange([...edges, ...newEdges]);
229
+ }, [traces, edges, onEdgesChange]);
230
+ return {
231
+ traces,
232
+ isEnabled,
233
+ solidifyTrace,
234
+ solidifyAll
235
+ };
236
+ }
237
+
238
+ // src/spatial/prediction/GhostInferenceEngine.ts
239
+ var GhostInferenceEngine = class {
240
+ static inferNextNodes(selectedNodes, allNodeDefs, options = {}) {
241
+ if (selectedNodes.length === 0 || allNodeDefs.length === 0) {
242
+ return [];
243
+ }
244
+ const scenarioCount = Math.max(1, options.scenarioCount ?? 3);
245
+ const maxSuggestions = options.maxSuggestionsPerNode ?? 2;
246
+ const candidates = [];
247
+ for (const sourceNode of selectedNodes) {
248
+ const outputSockets = sourceNode.outputs ?? [];
249
+ if (outputSockets.length === 0) continue;
250
+ const scoredDefs = [];
251
+ for (const def of allNodeDefs) {
252
+ if (def.type === sourceNode.type) continue;
253
+ const mappings = this.resolveSocketMappings(outputSockets, def);
254
+ if (mappings.length === 0) continue;
255
+ let score = mappings.length * 10;
256
+ if (options.customScorer) {
257
+ score += options.customScorer(sourceNode.type, def.type);
258
+ } else {
259
+ score += this.computeAffinityScore(sourceNode.type, def.type);
260
+ }
261
+ scoredDefs.push({ def, mappings, score });
262
+ }
263
+ scoredDefs.sort((a, b) => b.score - a.score);
264
+ for (let sIdx = 0; sIdx < scenarioCount; sIdx++) {
265
+ const slice = scoredDefs.slice(sIdx * maxSuggestions, (sIdx + 1) * maxSuggestions);
266
+ for (let i = 0; i < slice.length; i++) {
267
+ const match = slice[i];
268
+ const yOffset = (i - (slice.length - 1) / 2) * 140;
269
+ candidates.push({
270
+ id: `ghost-${sourceNode.id}-${match.def.type}-s${sIdx}-${i}`,
271
+ nodeType: match.def.type,
272
+ label: match.def.label || match.def.type,
273
+ scenarioIndex: sIdx,
274
+ score: match.score,
275
+ sourceNodeId: sourceNode.id,
276
+ socketMappings: match.mappings,
277
+ relativeOffset: { x: 260, y: yOffset }
278
+ });
279
+ }
280
+ }
281
+ }
282
+ return candidates;
283
+ }
284
+ static resolveSocketMappings(sourceOutputs, targetDef) {
285
+ const mappings = [];
286
+ const targetInputs = targetDef.inputs ?? [];
287
+ for (const outSocket of sourceOutputs) {
288
+ const matchingInput = targetInputs.find((inp) => {
289
+ return ConnectionRuleStore.canConnect(
290
+ { dataType: outSocket.dataType || "ANY", direction: "OUTPUT", handleCategory: "DATA" },
291
+ { dataType: inp.dataType || "ANY", direction: "INPUT", handleCategory: "DATA" }
292
+ );
293
+ });
294
+ if (matchingInput) {
295
+ const resolution = ConnectionRuleStore.resolve(
296
+ { dataType: outSocket.dataType || "ANY", direction: "OUTPUT", handleCategory: "DATA" },
297
+ { dataType: matchingInput.dataType || "ANY", direction: "INPUT", handleCategory: "DATA" }
298
+ );
299
+ mappings.push({
300
+ sourceSocketId: outSocket.id,
301
+ targetSocketId: matchingInput.id,
302
+ wireType: resolution.wireType || "DEFAULT"
303
+ });
304
+ }
305
+ }
306
+ return mappings;
307
+ }
308
+ static computeAffinityScore(sourceType, targetType) {
309
+ const s = sourceType.toLowerCase();
310
+ const t = targetType.toLowerCase();
311
+ if ((s.includes("source") || s.includes("input")) && (t.includes("process") || t.includes("filter"))) return 15;
312
+ if ((s.includes("process") || s.includes("filter")) && (t.includes("sink") || t.includes("output"))) return 15;
313
+ if (s.includes("audio") && t.includes("audio")) return 12;
314
+ if (s.includes("data") && t.includes("data")) return 10;
315
+ return 5;
316
+ }
317
+ };
318
+
319
+ // src/spatial/prediction/GhostLayoutResolver.ts
320
+ var GhostLayoutResolver = class {
321
+ static resolveLayout(candidates, existingNodes, allNodeDefs) {
322
+ const nodeMap = new Map(existingNodes.map((n) => [n.id, n]));
323
+ const defMap = new Map(allNodeDefs.map((d) => [d.type, d]));
324
+ const occupiedRects = existingNodes.map((n) => ({
325
+ x: n.position.x,
326
+ y: n.position.y,
327
+ width: n.width ?? 180,
328
+ height: n.height ?? 120
329
+ }));
330
+ const resolved = [];
331
+ for (const cand of candidates) {
332
+ const source = nodeMap.get(cand.sourceNodeId);
333
+ const def = defMap.get(cand.nodeType);
334
+ const width = 180;
335
+ const height = 120;
336
+ const baseX = (source ? source.position.x + (source.width ?? 180) : 0) + 80;
337
+ const baseY = (source ? source.position.y : 0) + cand.relativeOffset.y;
338
+ const placedRect = this.findNonOverlappingPosition(
339
+ { x: baseX, y: baseY, width, height },
340
+ occupiedRects
341
+ );
342
+ occupiedRects.push(placedRect);
343
+ const inputs = (def?.inputs ?? []).map((h) => ({
344
+ id: h.id,
345
+ label: h.label || h.id,
346
+ type: "input",
347
+ dataType: h.dataType,
348
+ direction: "INPUT"
349
+ }));
350
+ const outputs = (def?.outputs ?? []).map((h) => ({
351
+ id: h.id,
352
+ label: h.label || h.id,
353
+ type: "output",
354
+ dataType: h.dataType,
355
+ direction: "OUTPUT"
356
+ }));
357
+ resolved.push({
358
+ id: cand.id,
359
+ nodeType: cand.nodeType,
360
+ label: cand.label,
361
+ position: { x: placedRect.x, y: placedRect.y },
362
+ size: { width, height },
363
+ scenarioIndex: cand.scenarioIndex,
364
+ sourceNodeId: cand.sourceNodeId,
365
+ socketMappings: cand.socketMappings,
366
+ inputs,
367
+ outputs
368
+ });
369
+ }
370
+ return resolved;
371
+ }
372
+ static findNonOverlappingPosition(ideal, existing) {
373
+ let curr = { ...ideal };
374
+ let collision = true;
375
+ let attempts = 0;
376
+ const padding = 20;
377
+ while (collision && attempts < 15) {
378
+ collision = false;
379
+ for (const box of existing) {
380
+ if (this.intersects(curr, box, padding)) {
381
+ collision = true;
382
+ curr.y = box.y + box.height + padding;
383
+ curr.x = ideal.x + (attempts % 2 === 1 ? 24 : 0);
384
+ break;
385
+ }
386
+ }
387
+ attempts++;
388
+ }
389
+ return curr;
390
+ }
391
+ static intersects(a, b, pad) {
392
+ return !(a.x + a.width + pad <= b.x || b.x + b.width + pad <= a.x || a.y + a.height + pad <= b.y || b.y + b.height + pad <= a.y);
393
+ }
394
+ };
395
+
396
+ // src/spatial/prediction/GhostTracePathBuilder.ts
397
+ var GhostTracePathBuilder = class {
398
+ static buildGhostTraces(ghostNodes, existingNodes) {
399
+ const nodeMap = new Map(existingNodes.map((n) => [n.id, n]));
400
+ const traces = [];
401
+ for (const ghost of ghostNodes) {
402
+ const source = nodeMap.get(ghost.sourceNodeId);
403
+ if (!source) continue;
404
+ for (const mapping of ghost.socketMappings) {
405
+ const start = this.getRealSocketPosition(source, mapping.sourceSocketId, "output");
406
+ const end = this.getGhostSocketPosition(ghost, mapping.targetSocketId, "input");
407
+ const pathD = this.renderBezier(start.x, start.y, end.x, end.y);
408
+ traces.push({
409
+ id: `trace-ghost-${source.id}-${mapping.sourceSocketId}->${ghost.id}-${mapping.targetSocketId}`,
410
+ sourceNodeId: source.id,
411
+ sourceSocketId: mapping.sourceSocketId,
412
+ targetGhostNodeId: ghost.id,
413
+ targetSocketId: mapping.targetSocketId,
414
+ wireType: mapping.wireType,
415
+ pathD,
416
+ scenarioIndex: ghost.scenarioIndex
417
+ });
418
+ }
419
+ }
420
+ return traces;
421
+ }
422
+ static getRealSocketPosition(node, socketId, type) {
423
+ const sockets = type === "input" ? node.inputs : node.outputs;
424
+ const socket = sockets?.find((s) => s.id === socketId);
425
+ const index = sockets && socket ? sockets.indexOf(socket) : 0;
426
+ const w = node.width ?? 180;
427
+ const count = Math.max(1, sockets?.length ?? 1);
428
+ const x = type === "input" ? node.position.x : node.position.x + w;
429
+ const y = node.position.y + (index + 1) * (node.height ?? 120) / (count + 1);
430
+ return {
431
+ x: x + (socket?.offset?.x ?? 0),
432
+ y: y + (socket?.offset?.y ?? 0)
433
+ };
434
+ }
435
+ static getGhostSocketPosition(ghost, socketId, type) {
436
+ const sockets = type === "input" ? ghost.inputs : ghost.outputs;
437
+ const socket = sockets?.find((s) => s.id === socketId);
438
+ const index = sockets && socket ? sockets.indexOf(socket) : 0;
439
+ const w = ghost.size.width;
440
+ const count = Math.max(1, sockets?.length ?? 1);
441
+ const x = type === "input" ? ghost.position.x : ghost.position.x + w;
442
+ const y = ghost.position.y + (index + 1) * ghost.size.height / (count + 1);
443
+ return { x, y };
444
+ }
445
+ static renderBezier(startX, startY, endX, endY) {
446
+ const delta = Math.max(Math.abs(endX - startX) * 0.5, 45);
447
+ return `M ${startX},${startY} C ${startX + delta},${startY} ${endX - delta},${endY} ${endX},${endY}`;
448
+ }
449
+ };
450
+
451
+ export {
452
+ AttractionEngine,
453
+ calculateSocketCoordinates,
454
+ getBeamPoints,
455
+ useMagneticTraces,
456
+ GhostInferenceEngine,
457
+ GhostLayoutResolver,
458
+ GhostTracePathBuilder
459
+ };
File without changes
@@ -1,8 +1,8 @@
1
- import { B as BaseNode, a as BaseHandle, d as BaseNodeProps, D as DataHandle, N as NodePosition } from '../BaseNode-1HCEqmap.js';
2
- export { c as BaseHandleProps, C as ConnectionMode, e as CustomNode, H as HandleCategory, f as HandleDefinition, g as HandleDirection, h as HandleOffset, i as HandlePosition, j as NodeDefinition, b as NodeSize, V as ViewHandle } from '../BaseNode-1HCEqmap.js';
1
+ import { b as BaseNode, B as BaseHandle, e as BaseNodeProps, D as DataHandle, N as NodePosition } from '../BaseNode-DTcd3K1B.js';
2
+ export { d as BaseHandleProps, C as ConnectionMode, f as CustomNode, H as HandleCategory, g as HandleDefinition, c as HandleDirection, h as HandleOffset, i as HandlePosition, j as NodeDefinition, a as NodeSize, V as ViewHandle } from '../BaseNode-DTcd3K1B.js';
3
3
  import { B as BaseConnection } from '../BaseConnection-CMRrL6Fe.js';
4
4
  export { a as BaseConnectionProps, S as SolidConnection, b as SolidConnectionProps, V as ViewLink, c as ViewLinkProps } from '../BaseConnection-CMRrL6Fe.js';
5
- export { B as BaseGraph, a as BaseViewWindow, b as BaseViewWindowProps, C as CustomGraph, c as CustomViewWindow, D as DEFAULT_GRAPH_SETTINGS, d as DynamicState, G as GraphSettings, e as GraphView, f as Group, L as Landmark } from '../BaseGraph-Bl2f7Pqx.js';
5
+ export { B as BaseGraph, a as BaseViewWindow, b as BaseViewWindowProps, C as CustomGraph, c as CustomViewWindow, D as DEFAULT_GRAPH_SETTINGS, d as DynamicState, G as GraphSettings, e as GraphView, f as Group, L as Landmark } from '../BaseGraph-BvkSYOTw.js';
6
6
 
7
7
  interface GroupNodeProps extends Partial<BaseNodeProps> {
8
8
  innerNodes?: BaseNode[];
@@ -2,19 +2,18 @@ import * as _ultrst_armada_krnl from '@ultrst-armada/krnl';
2
2
  import { ServiceDefinition } from '@ultrst-armada/krnl';
3
3
  export { LifecycleCycleError, LifecycleDescriptor, LifecycleGraph, LifecycleGraphNode, LifecycleScopeType, SKIPO_STATE, SkipoStateApi, SkipoStateEngine, StateDeclaration, StateEntry, StateUpdater, useLifecycleScope, useSkipoBind, useSkipoState } from './state/index.js';
4
4
  export { BullMQAdapter, BullMQAdapterOptions, CommandBus, CommandExecutionState, EnqueueOptions, ExecutionJob, ExecutionQueueAdapter, ExecutionResult, JobPriority, JobStatus, RetryPolicy, SKIPO_EXECUTION, SkipoCommand, SkipoExecutionEngine, useCommand } from './execution/index.js';
5
- import { B as BaseNode, D as DataHandle } from './BaseNode-1HCEqmap.js';
6
- export { a as BaseHandle, c as BaseHandleProps, d as BaseNodeProps, C as ConnectionMode, e as CustomNode, H as HandleCategory, f as HandleDefinition, g as HandleDirection, h as HandleOffset, i as HandlePosition, j as NodeDefinition, N as NodePosition, b as NodeSize, V as ViewHandle } from './BaseNode-1HCEqmap.js';
5
+ import { b as BaseNode, D as DataHandle } from './BaseNode-DTcd3K1B.js';
6
+ export { B as BaseHandle, d as BaseHandleProps, e as BaseNodeProps, C as ConnectionMode, f as CustomNode, H as HandleCategory, g as HandleDefinition, c as HandleDirection, h as HandleOffset, i as HandlePosition, j as NodeDefinition, N as NodePosition, a as NodeSize, V as ViewHandle } from './BaseNode-DTcd3K1B.js';
7
7
  import { S as SolidConnection } from './BaseConnection-CMRrL6Fe.js';
8
8
  export { B as BaseConnection, a as BaseConnectionProps, b as SolidConnectionProps, V as ViewLink, c as ViewLinkProps } from './BaseConnection-CMRrL6Fe.js';
9
- export { B as BaseGraph, a as BaseViewWindow, b as BaseViewWindowProps, C as CustomGraph, c as CustomViewWindow, D as DEFAULT_GRAPH_SETTINGS, d as DynamicState, G as GraphSettings, e as GraphView, f as Group } from './BaseGraph-Bl2f7Pqx.js';
9
+ export { B as BaseGraph, a as BaseViewWindow, b as BaseViewWindowProps, C as CustomGraph, c as CustomViewWindow, D as DEFAULT_GRAPH_SETTINGS, d as DynamicState, G as GraphSettings, e as GraphView, f as Group } from './BaseGraph-BvkSYOTw.js';
10
10
  export { GroupNode as DomainGroupNode, SubgraphNode as DomainSubgraphNode, GroupNodeProps, SignalVariant, SubgraphNodeProps, instantiateSubgraph } from './domain/index.js';
11
11
  export { ConnectionRuleStore, HandleDescriptor, HandleTypeDefinition, HandleTypeRegistry, WireTypeDefinition, WireTypeRegistry, initializeDefaultGraphRules } from './rules/index.js';
12
- export { a as CompatibilityMatrix, C as CompatibilityResolution, b as CompatibilityResolverDelegate, c as CompatibilityRule } from './CompatibilityMatrix-DX307_vS.js';
13
- export { AttractionEngine, AutoSolidify, SocketCoordOptions, SocketCoordResult, SpatialEngine, calculateSocketCoordinates, getBeamPoints } from './spatial/index.js';
14
- import { T as Trace } from './TraceEngine-CJVpUb80.js';
15
- export { a as TraceEngine } from './TraceEngine-CJVpUb80.js';
16
- import { V as ViewportState, N as NodeGraphConfig, G as GraphNode } from './index-CiekWEH3.js';
17
- export { C as CommandApi, a as GhostStore, b as GhostStoreListener, c as GraphEdge, d as GraphListener, e as GraphStore, f as NodeGraphPlugin, S as Socket, g as SocketType } from './index-CiekWEH3.js';
12
+ export { a as CompatibilityMatrix, C as CompatibilityResolution, b as CompatibilityResolverDelegate, c as CompatibilityRule } from './CompatibilityMatrix-Dj-tCWUA.js';
13
+ export { AttractionEngine, AutoSolidify, GhostInferenceEngine, GhostLayoutResolver, GhostTracePathBuilder, MagneticTraceRecord, SocketCoordOptions, SocketCoordResult, SpatialEngine, UseMagneticTracesParams, calculateSocketCoordinates, getBeamPoints, useMagneticTraces } from './spatial/index.js';
14
+ import { V as ViewportState, N as NodeGraphConfig, G as GraphNode, T as Trace } from './types-VDoc4FIc.js';
15
+ export { a as GhostCandidate, b as GhostInferenceOptions, c as GhostNodeRecord, d as GhostSocketMapping, e as GhostTraceRecord, f as GraphEdge, g as NodeGraphPlugin, S as Socket, h as SocketType, i as TraceEngine } from './types-VDoc4FIc.js';
16
+ export { CommandApi, GhostStore, GhostStoreListener, GraphListener, GraphStore } from './store/index.js';
18
17
  import React from 'react';
19
18
  import 'zustand/vanilla';
20
19
 
@@ -13,12 +13,22 @@ import {
13
13
  SkipoExecutionEngine,
14
14
  useCommand
15
15
  } from "./chunk-ZTHBPV24.js";
16
+ import "./chunk-RHRXPY2U.js";
17
+ import {
18
+ AttractionEngine,
19
+ GhostInferenceEngine,
20
+ GhostLayoutResolver,
21
+ GhostTracePathBuilder,
22
+ calculateSocketCoordinates,
23
+ getBeamPoints,
24
+ useMagneticTraces
25
+ } from "./chunk-JXDJZSFW.js";
16
26
  import {
17
27
  ConnectionRuleStore,
18
28
  HandleTypeRegistry,
19
29
  WireTypeRegistry,
20
30
  initializeDefaultGraphRules
21
- } from "./chunk-QN74PLMF.js";
31
+ } from "./chunk-TZOL3RN7.js";
22
32
  import "./chunk-Q5I42UX7.js";
23
33
  import {
24
34
  LifecycleCycleError,
@@ -29,11 +39,6 @@ import {
29
39
  useSkipoBind,
30
40
  useSkipoState
31
41
  } from "./chunk-SHIBCPGQ.js";
32
- import {
33
- AttractionEngine,
34
- calculateSocketCoordinates,
35
- getBeamPoints
36
- } from "./chunk-YTWCH6P2.js";
37
42
  import {
38
43
  CommandApi,
39
44
  GhostStore,
@@ -9561,7 +9566,10 @@ export {
9561
9566
  EffectNodeModel,
9562
9567
  GM_DRUM_NOTES,
9563
9568
  GRAPH_TYPE_DEFINITIONS,
9569
+ GhostInferenceEngine,
9570
+ GhostLayoutResolver,
9564
9571
  GhostStore,
9572
+ GhostTracePathBuilder,
9565
9573
  GraphBridgeNode,
9566
9574
  GraphConcepts,
9567
9575
  GraphDataService,
@@ -9804,6 +9812,7 @@ export {
9804
9812
  updateNamedMidiProfile,
9805
9813
  useCommand,
9806
9814
  useLifecycleScope,
9815
+ useMagneticTraces,
9807
9816
  useSkipoBind,
9808
9817
  useSkipoState,
9809
9818
  validateComponentSocketConnection,
@@ -1,6 +1,6 @@
1
- import { c as CompatibilityRule, C as CompatibilityResolution } from '../CompatibilityMatrix-DX307_vS.js';
2
- export { a as CompatibilityMatrix, b as CompatibilityResolverDelegate } from '../CompatibilityMatrix-DX307_vS.js';
3
- import { j as NodeDefinition, a as BaseHandle, g as HandleDirection, H as HandleCategory, f as HandleDefinition } from '../BaseNode-1HCEqmap.js';
1
+ import { c as CompatibilityRule, C as CompatibilityResolution } from '../CompatibilityMatrix-Dj-tCWUA.js';
2
+ export { a as CompatibilityMatrix, b as CompatibilityResolverDelegate } from '../CompatibilityMatrix-Dj-tCWUA.js';
3
+ import { j as NodeDefinition, B as BaseHandle, c as HandleDirection, H as HandleCategory, g as HandleDefinition } from '../BaseNode-DTcd3K1B.js';
4
4
 
5
5
  interface HandleTypeDefinition {
6
6
  dataType: string;
@@ -1,9 +1,10 @@
1
+ import "../chunk-RHRXPY2U.js";
1
2
  import {
2
3
  ConnectionRuleStore,
3
4
  HandleTypeRegistry,
4
5
  WireTypeRegistry,
5
6
  initializeDefaultGraphRules
6
- } from "../chunk-QN74PLMF.js";
7
+ } from "../chunk-TZOL3RN7.js";
7
8
  import {
8
9
  CompatibilityMatrix
9
10
  } from "../chunk-ISFNY7EZ.js";