@terminals-tech/sdk 1.0.0-rc.2 → 1.0.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/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  getSkillCount,
6
6
  getSkillsByCategory,
7
7
  registerSkill
8
- } from "./chunk-UKVUPKZP.js";
8
+ } from "./chunk-L45BSQDJ.js";
9
9
  import {
10
10
  createDAG,
11
11
  createDelegationChain,
@@ -24,7 +24,7 @@ import {
24
24
  wrapTo2Pi,
25
25
  wrapToPi
26
26
  } from "./chunk-WU4OTGJE.js";
27
- import "./chunk-3CEM77QZ.js";
27
+ import "./chunk-OCLSAUCD.js";
28
28
  import "./chunk-BYXBJQAS.js";
29
29
  import {
30
30
  SKILL_CATEGORIES,
@@ -938,6 +938,85 @@ __export(brain_exports, {
938
938
  wrapToPi: () => wrapToPi
939
939
  });
940
940
 
941
+ // ../../lib/terminals-tech/core/primitives/coherence-heuristics.ts
942
+ var DEFAULT_HEDGING_PATTERNS = [
943
+ /\bi think\b/gi,
944
+ /\bmaybe\b/gi,
945
+ /\bperhaps\b/gi,
946
+ /\bpossibly\b/gi,
947
+ /\buncertain\b/gi,
948
+ /\bmight\b/gi
949
+ ];
950
+ var DEFAULT_CONTRADICTION_PATTERNS = [
951
+ /\bhowever\b.*\bnot\b/gi,
952
+ /\bbut\b.*\bnot\b/gi,
953
+ /\bcontrary\b/gi,
954
+ /\bcontradicts?\b/gi
955
+ ];
956
+ var DEFAULT_STRUCTURE_PATTERN = /[-*\u2022]\s|^\d+\.|#{1,3}\s/m;
957
+ var DEFAULT_ACTION_PATTERN = /\b(do|make|create|implement|use|try|start|begin|ensure|verify)\b/gi;
958
+ var DEFAULT_QUALIFIER_PATTERN = /\b(very|really|extremely|quite|somewhat|fairly)\b/gi;
959
+ function detectHedging(text, patterns = DEFAULT_HEDGING_PATTERNS) {
960
+ const hedgeCount = patterns.reduce(
961
+ (count, pattern) => count + (text.match(pattern)?.length ?? 0),
962
+ 0
963
+ );
964
+ const wordCount = text.split(/\s+/).length;
965
+ const hedgeRatio = hedgeCount / Math.max(wordCount / 50, 1);
966
+ return Math.min(1, hedgeRatio * 0.2);
967
+ }
968
+ function detectContradictions(text, patterns = DEFAULT_CONTRADICTION_PATTERNS) {
969
+ let score = 0;
970
+ for (const pattern of patterns) {
971
+ const matches = text.match(pattern);
972
+ if (matches) {
973
+ score += matches.length * 0.1;
974
+ }
975
+ }
976
+ return Math.min(1, score);
977
+ }
978
+ function measureTopicDivergence(current, history) {
979
+ if (history.length === 0) return 0;
980
+ const currentTerms = new Set(current.toLowerCase().split(/\s+/));
981
+ const historyTerms = new Set(
982
+ history.flatMap((h) => h.toLowerCase().split(/\s+/))
983
+ );
984
+ const overlap = [...currentTerms].filter((t) => historyTerms.has(t)).length;
985
+ const overlapRatio = overlap / currentTerms.size;
986
+ return overlapRatio < 0.1 ? 0.2 : 0;
987
+ }
988
+ function scoreStructure(text, config) {
989
+ const structurePattern = config?.structurePattern ?? DEFAULT_STRUCTURE_PATTERN;
990
+ const actionPattern = config?.actionPattern ?? DEFAULT_ACTION_PATTERN;
991
+ const qualifierPattern = config?.qualifierPattern ?? DEFAULT_QUALIFIER_PATTERN;
992
+ const minWords = config?.minWords ?? 10;
993
+ const maxWords = config?.maxWords ?? 500;
994
+ let adjustment = 0;
995
+ const wordCount = text.split(/\s+/).length;
996
+ if (wordCount < minWords) adjustment -= 0.2;
997
+ if (wordCount > maxWords) adjustment -= 0.1;
998
+ if (structurePattern.test(text)) adjustment += 0.1;
999
+ const actionMatches = text.match(actionPattern);
1000
+ if (actionMatches && actionMatches.length > 2) adjustment += 0.1;
1001
+ const qualifierCount = (text.match(qualifierPattern) ?? []).length;
1002
+ if (qualifierCount > 5) adjustment -= 0.1;
1003
+ return adjustment;
1004
+ }
1005
+ function computeFactOverlap(text, facts) {
1006
+ if (facts.length === 0) return 0;
1007
+ const textTerms = new Set(
1008
+ text.toLowerCase().split(/\W+/).filter((t) => t.length > 2)
1009
+ );
1010
+ let totalOverlap = 0;
1011
+ for (const fact of facts) {
1012
+ const factTerms = fact.toLowerCase().split(/\W+/).filter((t) => t.length > 2);
1013
+ if (factTerms.length === 0) continue;
1014
+ const matched = factTerms.filter((t) => textTerms.has(t)).length;
1015
+ totalOverlap += matched / factTerms.length;
1016
+ }
1017
+ return totalOverlap / facts.length;
1018
+ }
1019
+
941
1020
  // ../../lib/terminals-tech/brains/core/core.brain.coherence.ts
942
1021
  var DEFAULT_CONFIG = {
943
1022
  groundingWeight: 0.4,
@@ -947,75 +1026,20 @@ var DEFAULT_CONFIG = {
947
1026
  };
948
1027
  function calculateGrounding(output, groundTruth) {
949
1028
  if (!groundTruth || groundTruth.length === 0) {
950
- const hedgingPatterns = [
951
- /\bi think\b/gi,
952
- /\bmaybe\b/gi,
953
- /\bperhaps\b/gi,
954
- /\bpossibly\b/gi,
955
- /\buncertain\b/gi,
956
- /\bmight\b/gi
957
- ];
958
- const hedgeCount = hedgingPatterns.reduce(
959
- (count, pattern) => count + (output.match(pattern)?.length || 0),
960
- 0
961
- );
962
- const wordCount = output.split(/\s+/).length;
963
- const hedgeRatio = hedgeCount / Math.max(wordCount / 50, 1);
964
- return Math.max(0, 1 - hedgeRatio * 0.2);
1029
+ return Math.max(0, 1 - detectHedging(output));
965
1030
  }
966
- const outputTerms = new Set(
967
- output.toLowerCase().split(/\W+/).filter((t) => t.length > 2)
968
- );
969
- let totalOverlap = 0;
970
- for (const fact of groundTruth) {
971
- const factTerms = fact.toLowerCase().split(/\W+/).filter((t) => t.length > 2);
972
- if (factTerms.length === 0) continue;
973
- const matched = factTerms.filter((t) => outputTerms.has(t)).length;
974
- totalOverlap += matched / factTerms.length;
975
- }
976
- return totalOverlap / groundTruth.length;
1031
+ return computeFactOverlap(output, groundTruth);
977
1032
  }
978
1033
  function calculateInternal(output, history) {
979
1034
  const sentences = output.split(/[.!?]+/).filter((s) => s.trim());
980
1035
  if (sentences.length < 2) return 1;
981
- const negations = [
982
- /\bhowever\b.*\bnot\b/gi,
983
- /\bbut\b.*\bnot\b/gi,
984
- /\bcontrary\b/gi,
985
- /\bcontradicts?\b/gi
986
- ];
987
- let contradictionScore = 0;
988
- for (const pattern of negations) {
989
- const matches = output.match(pattern);
990
- if (matches) {
991
- contradictionScore += matches.length * 0.1;
992
- }
993
- }
994
- if (history && history.length > 0) {
995
- const currentTerms = new Set(output.toLowerCase().split(/\s+/));
996
- const historyTerms = new Set(history.flatMap((h) => h.toLowerCase().split(/\s+/)));
997
- const overlap = [...currentTerms].filter((t) => historyTerms.has(t)).length;
998
- const overlapRatio = overlap / currentTerms.size;
999
- if (overlapRatio < 0.1) {
1000
- contradictionScore += 0.2;
1001
- }
1002
- }
1003
- return Math.max(0, 1 - contradictionScore);
1036
+ const contradictionPenalty = detectContradictions(output);
1037
+ const divergencePenalty = history && history.length > 0 ? measureTopicDivergence(output, history) : 0;
1038
+ return Math.max(0, 1 - contradictionPenalty - divergencePenalty);
1004
1039
  }
1005
1040
  function calculateCrystallization(output) {
1006
- let score = 1;
1007
- const wordCount = output.split(/\s+/).length;
1008
- if (wordCount < 10) score -= 0.2;
1009
- if (wordCount > 500) score -= 0.1;
1010
- const hasStructure = /[-*•]\s|^\d+\.|#{1,3}\s/m.test(output);
1011
- if (hasStructure) score += 0.1;
1012
- const actionWords = /\b(do|make|create|implement|use|try|start|begin|ensure|verify)\b/gi;
1013
- const actionMatches = output.match(actionWords);
1014
- if (actionMatches && actionMatches.length > 2) score += 0.1;
1015
- const qualifiers = /\b(very|really|extremely|quite|somewhat|fairly)\b/gi;
1016
- const qualifierCount = (output.match(qualifiers) || []).length;
1017
- if (qualifierCount > 5) score -= 0.1;
1018
- return Math.max(0, Math.min(1, score));
1041
+ const adjustment = scoreStructure(output);
1042
+ return Math.max(0, Math.min(1, 1 + adjustment));
1019
1043
  }
1020
1044
  function calculateCoherence(input, config = {}) {
1021
1045
  const cfg = { ...DEFAULT_CONFIG, ...config };
@@ -1269,6 +1293,2061 @@ var SIGNAL_CODE_TO_EVENT = {
1269
1293
  [SKILL_SIGNAL_CODES.SKILL_ERROR]: "skill:error"
1270
1294
  };
1271
1295
 
1296
+ // ../../lib/terminals-tech/sdk/manifold.ts
1297
+ var manifold_exports = {};
1298
+ __export(manifold_exports, {
1299
+ annihilate: () => annihilate,
1300
+ manifold: () => manifold
1301
+ });
1302
+
1303
+ // ../../lib/terminals-tech/core/L0/dmt-55dim-combinatorial.ts
1304
+ var DMT55CombinatorialEngine = class {
1305
+ constructor() {
1306
+ }
1307
+ /**
1308
+ * Treat the observer configuration mapping:
1309
+ * 1 sat = 18 ordinal dimensions = 37 DMT
1310
+ */
1311
+ getObserverConfiguration(sats) {
1312
+ const ordinalDimensions = sats * 18;
1313
+ const dmtDimensions = sats * 37;
1314
+ return {
1315
+ sats,
1316
+ ordinalDimensions,
1317
+ dmtDimensions,
1318
+ totalDimensions: ordinalDimensions + dmtDimensions
1319
+ // 55 per sat
1320
+ };
1321
+ }
1322
+ /**
1323
+ * Continuous generation of evidence via MicroLM architecture
1324
+ */
1325
+ generateMicroLMEvidence(sats) {
1326
+ const config = this.getObserverConfiguration(sats);
1327
+ const manifoldState = Array.from(
1328
+ { length: config.totalDimensions },
1329
+ () => Math.random() * 2 - 1
1330
+ );
1331
+ const evidence = {
1332
+ evidenceId: `microlm-ev-${Date.now()}-${Math.floor(Math.random() * 1e3)}`,
1333
+ confidence: 0.85 + Math.random() * 0.14,
1334
+ manifoldState,
1335
+ timestamp: Date.now()
1336
+ };
1337
+ emitSignal("mesh_update", "L1", "L3", {
1338
+ node: "DMT55Engine",
1339
+ evidence,
1340
+ config
1341
+ });
1342
+ return evidence;
1343
+ }
1344
+ };
1345
+ var dmt55Engine = new DMT55CombinatorialEngine();
1346
+
1347
+ // ../../lib/terminals-tech/brains/state-mirror.ts
1348
+ import { BehaviorSubject } from "rxjs";
1349
+ var DEFAULT_STATE = {
1350
+ activeUrl: "/",
1351
+ focusedComponent: null,
1352
+ recentIntents: [],
1353
+ audioEntropy: 0.5,
1354
+ nanoFoldActive: false,
1355
+ coherenceR: 0,
1356
+ activeProject: null
1357
+ };
1358
+ var StateMirror = class {
1359
+ state$ = new BehaviorSubject(DEFAULT_STATE);
1360
+ bridgeOwnerId = null;
1361
+ bridgeOrder = [];
1362
+ constructor() {
1363
+ this.initSubscriptions();
1364
+ }
1365
+ initSubscriptions() {
1366
+ if (typeof window === "undefined") return;
1367
+ const bus = getSignalBus();
1368
+ bus.subscribe("audio_metrics_update", (signal) => {
1369
+ const payload = signal.payload;
1370
+ if (payload && typeof payload.entropy === "number") {
1371
+ this.update({ audioEntropy: payload.entropy });
1372
+ }
1373
+ });
1374
+ bus.subscribe("ui_surface_opened", (signal) => {
1375
+ const payload = signal.payload;
1376
+ if (payload && payload.surface) {
1377
+ this.update({ focusedComponent: payload.surface });
1378
+ }
1379
+ });
1380
+ bus.subscribe("intent_signal_emitted", (signal) => {
1381
+ const payload = signal.payload;
1382
+ if (payload && payload.intent) {
1383
+ const current = this.state$.value.recentIntents;
1384
+ this.update({ recentIntents: [payload.intent, ...current].slice(0, 5) });
1385
+ }
1386
+ });
1387
+ }
1388
+ /** Gets the observable stream of state changes */
1389
+ get stream$() {
1390
+ return this.state$.asObservable();
1391
+ }
1392
+ /** Gets a synchronous snapshot of the current state */
1393
+ get snapshot() {
1394
+ return this.state$.value;
1395
+ }
1396
+ claimBridge(bridgeId) {
1397
+ this.bridgeOrder = [...this.bridgeOrder.filter((id) => id !== bridgeId), bridgeId];
1398
+ this.bridgeOwnerId = bridgeId;
1399
+ }
1400
+ releaseBridge(bridgeId) {
1401
+ this.bridgeOrder = this.bridgeOrder.filter((id) => id !== bridgeId);
1402
+ if (this.bridgeOwnerId === bridgeId) {
1403
+ this.bridgeOwnerId = this.bridgeOrder[this.bridgeOrder.length - 1] ?? null;
1404
+ }
1405
+ }
1406
+ /** Partially updates the mirror state */
1407
+ update(partial) {
1408
+ const next = { ...this.state$.value, ...partial };
1409
+ this.state$.next(next);
1410
+ }
1411
+ /**
1412
+ * Bridge-scoped update to prevent multiple mounted app shells from racing
1413
+ * against the same singleton mirror.
1414
+ */
1415
+ updateFromBridge(bridgeId, partial) {
1416
+ if (!this.bridgeOrder.includes(bridgeId)) {
1417
+ this.claimBridge(bridgeId);
1418
+ }
1419
+ if (this.bridgeOwnerId && this.bridgeOwnerId !== bridgeId) {
1420
+ return;
1421
+ }
1422
+ this.bridgeOwnerId = bridgeId;
1423
+ this.update(partial);
1424
+ }
1425
+ /**
1426
+ * Flattens the continuous state into a dense text manifold.
1427
+ * This is passed to the ObserverKernel to ground it in the immediate UI/UX reality.
1428
+ */
1429
+ encodeToManifold() {
1430
+ const s = this.snapshot;
1431
+ return `
1432
+ [StateMirror: Active]
1433
+ Location: ${s.activeUrl}
1434
+ Focus: ${s.focusedComponent || "ambient"}
1435
+ Workspace: ${s.activeProject || "global"}
1436
+ Acoustic Entropy: ${s.audioEntropy.toFixed(3)}
1437
+ Resonance R: ${s.coherenceR.toFixed(3)}
1438
+ NanoFold Topology: ${s.nanoFoldActive ? "Rendering" : "Collapsed"}
1439
+ Recent Intents: ${s.recentIntents.length > 0 ? s.recentIntents.join(" -> ") : "None"}
1440
+ `.trim();
1441
+ }
1442
+ };
1443
+ var globalStateMirror = new StateMirror();
1444
+
1445
+ // ../../lib/terminals-tech/brains/observable-evidence.ts
1446
+ function metricToneFromValue(value, invert = false) {
1447
+ const normalized = invert ? 1 - value : value;
1448
+ if (normalized >= 0.85) return "mint";
1449
+ if (normalized >= 0.6) return "cyan";
1450
+ if (normalized >= 0.35) return "violet";
1451
+ return "amber";
1452
+ }
1453
+ function toneColor(tone) {
1454
+ switch (tone) {
1455
+ case "mint":
1456
+ return "#6EE7B7";
1457
+ case "cyan":
1458
+ return "#67E8F9";
1459
+ case "violet":
1460
+ return "#A78BFA";
1461
+ case "amber":
1462
+ return "#FBBF24";
1463
+ default:
1464
+ return "#67E8F9";
1465
+ }
1466
+ }
1467
+ function buildStatus(constructive, witness) {
1468
+ if (constructive) return "constructive";
1469
+ if (witness.converged || witness.R >= 0.75) return "stable";
1470
+ if (witness.R >= 0.35) return "searching";
1471
+ return "ambient";
1472
+ }
1473
+ function buildThoughtspace(witness, constructive, strategyLabel, entropyLabel) {
1474
+ const stabilityTone = metricToneFromValue(witness.R);
1475
+ const entropyTone = metricToneFromValue(witness.activationEntropy, true);
1476
+ const routeTone = constructive ? "violet" : "amber";
1477
+ return [
1478
+ {
1479
+ id: "stability",
1480
+ shape: "circle",
1481
+ label: "Core",
1482
+ detail: `This dot is the center of the thought. Bigger + brighter means the pattern is holding together (R=${witness.R.toFixed(2)}).`,
1483
+ color: toneColor(stabilityTone),
1484
+ x: 52,
1485
+ y: 44,
1486
+ size: 12 + witness.R * 10,
1487
+ opacity: 0.65 + witness.R * 0.3
1488
+ },
1489
+ {
1490
+ id: "entropy",
1491
+ shape: "diamond",
1492
+ label: "Search",
1493
+ detail: `This shape shows how noisy the signal is. ${entropyLabel}`,
1494
+ color: toneColor(entropyTone),
1495
+ x: 22 + witness.activationEntropy * 18,
1496
+ y: 78 - witness.activationEntropy * 18,
1497
+ size: 8 + witness.activationEntropy * 9,
1498
+ opacity: 0.45 + witness.activationEntropy * 0.4
1499
+ },
1500
+ {
1501
+ id: "route",
1502
+ shape: "triangle",
1503
+ label: "Route",
1504
+ detail: `This pointer shows which engine is carrying the thought right now: ${strategyLabel}.`,
1505
+ color: toneColor(routeTone),
1506
+ x: 82,
1507
+ y: constructive ? 30 : 62,
1508
+ size: 10 + (constructive ? 4 : 0),
1509
+ opacity: constructive ? 0.9 : 0.6
1510
+ }
1511
+ ];
1512
+ }
1513
+ function parseFoldedPayload(payload) {
1514
+ if (typeof payload !== "string") return payload;
1515
+ try {
1516
+ return JSON.parse(payload);
1517
+ } catch {
1518
+ return payload;
1519
+ }
1520
+ }
1521
+ function toReduction(payload) {
1522
+ if (!payload || typeof payload !== "object") return {};
1523
+ const reduction = payload.reduction;
1524
+ if (!reduction || typeof reduction !== "object") return {};
1525
+ return reduction;
1526
+ }
1527
+ function toContextHint(payload) {
1528
+ if (!payload || typeof payload !== "object") return void 0;
1529
+ const candidate = payload.contextSnapshot;
1530
+ return typeof candidate === "string" && candidate.length > 0 ? candidate : void 0;
1531
+ }
1532
+ function buildObservableEvidenceFromSematon(sematon, title) {
1533
+ const payload = parseFoldedPayload(sematon.payload);
1534
+ const reduction = toReduction(payload);
1535
+ const status = buildStatus(sematon.constructive, sematon.witness);
1536
+ const strategyLabel = reduction.strategy ?? reduction.runtime ?? sematon.source;
1537
+ const entropyLabel = sematon.witness.activationEntropy >= 0.7 ? "Higher means the system is still exploring a lot of possibilities." : "Lower means the system has narrowed into a smaller, steadier shape.";
1538
+ return {
1539
+ id: sematon.id,
1540
+ source: sematon.source,
1541
+ title: title ?? (sematon.source.includes("ohm") || sematon.source.includes("Ohm") ? "Ohm Thoughtspace" : "Observable Evidence"),
1542
+ summary: sematon.constructive ? "The pattern held together and can be built on again." : sematon.witness.converged ? "The pattern is stable, but it is not yet a reusable construction." : "The system is still searching for a stable shape.",
1543
+ status,
1544
+ constructive: sematon.constructive,
1545
+ witness: sematon.witness,
1546
+ strategy: reduction.strategy,
1547
+ runtime: reduction.runtime,
1548
+ durationMs: reduction.durationMs,
1549
+ metrics: [
1550
+ {
1551
+ id: "stability",
1552
+ label: "Stability",
1553
+ value: sematon.witness.R.toFixed(2),
1554
+ detail: "How locked-in the thought is. Closer to 1 means the pattern is holding together instead of wobbling.",
1555
+ tone: metricToneFromValue(sematon.witness.R)
1556
+ },
1557
+ {
1558
+ id: "signal",
1559
+ label: "Signal",
1560
+ value: sematon.witness.activationEntropy.toFixed(2),
1561
+ detail: "How noisy the search still is. Higher means more exploring, lower means more focus.",
1562
+ tone: metricToneFromValue(sematon.witness.activationEntropy, true)
1563
+ },
1564
+ {
1565
+ id: "route",
1566
+ label: "Route",
1567
+ value: strategyLabel,
1568
+ detail: "Which engine is carrying the construction right now. This tells you where the work actually happened.",
1569
+ tone: sematon.constructive ? "violet" : "amber"
1570
+ },
1571
+ {
1572
+ id: "buildable",
1573
+ label: "Buildable",
1574
+ value: sematon.constructive ? "yes" : "not yet",
1575
+ detail: "If this says yes, the result can be reused and extended instead of collapsing when you touch it.",
1576
+ tone: sematon.constructive ? "mint" : "amber"
1577
+ }
1578
+ ],
1579
+ thoughtspace: buildThoughtspace(
1580
+ sematon.witness,
1581
+ sematon.constructive,
1582
+ strategyLabel,
1583
+ entropyLabel
1584
+ ),
1585
+ contextHint: toContextHint(payload),
1586
+ observedAt: sematon.createdAt ?? Date.now()
1587
+ };
1588
+ }
1589
+
1590
+ // ../../lib/py2bend/parser.ts
1591
+ function tokenizeLines(source) {
1592
+ return source.split("\n").map((raw, i) => {
1593
+ const text = raw;
1594
+ const trimmed = raw.trimStart();
1595
+ const indent2 = raw.length - trimmed.length;
1596
+ return { text: trimmed, indent: indent2, lineNo: i + 1 };
1597
+ }).filter((l) => l.text.length > 0 && !l.text.startsWith("#"));
1598
+ }
1599
+ var Cursor = class {
1600
+ constructor(lines, pos = 0) {
1601
+ this.lines = lines;
1602
+ this.pos = pos;
1603
+ }
1604
+ done() {
1605
+ return this.pos >= this.lines.length;
1606
+ }
1607
+ peek() {
1608
+ return this.done() ? null : this.lines[this.pos];
1609
+ }
1610
+ advance() {
1611
+ return this.lines[this.pos++];
1612
+ }
1613
+ /** Collect the body block: all lines with indent > parentIndent */
1614
+ collectBlock(parentIndent) {
1615
+ const block = [];
1616
+ while (!this.done()) {
1617
+ const next = this.peek();
1618
+ if (next.indent <= parentIndent) break;
1619
+ block.push(this.advance());
1620
+ }
1621
+ return block;
1622
+ }
1623
+ };
1624
+ var UNSUPPORTED_KEYWORDS = [
1625
+ /^async\s+def\b/,
1626
+ /^await\b/,
1627
+ /^yield\b/,
1628
+ /^import\b/,
1629
+ /^from\s+\S+\s+import\b/,
1630
+ /^with\b/,
1631
+ /^assert\b/,
1632
+ /^raise\b/,
1633
+ /^del\b/,
1634
+ /^global\b/,
1635
+ /^nonlocal\b/
1636
+ ];
1637
+ function parsePython(source) {
1638
+ const errors = [];
1639
+ const lines = tokenizeLines(source);
1640
+ validateIndentation(lines, errors);
1641
+ if (errors.some((error) => error.severity === "error")) {
1642
+ return { ast: null, errors };
1643
+ }
1644
+ try {
1645
+ const cursor = new Cursor(lines);
1646
+ const body = parseBlock(cursor, -1, errors);
1647
+ return { ast: { type: "Module", body }, errors };
1648
+ } catch (e) {
1649
+ errors.push({
1650
+ message: e.message,
1651
+ severity: "error"
1652
+ });
1653
+ return { ast: null, errors };
1654
+ }
1655
+ }
1656
+ function parseBlock(cursor, parentIndent, errors) {
1657
+ const stmts = [];
1658
+ while (!cursor.done()) {
1659
+ const line = cursor.peek();
1660
+ if (line.indent <= parentIndent) break;
1661
+ cursor.advance();
1662
+ const stmt = parseStatement(line, cursor, errors);
1663
+ if (stmt) stmts.push(stmt);
1664
+ }
1665
+ return stmts;
1666
+ }
1667
+ function parseStatement(line, cursor, errors) {
1668
+ const text = line.text;
1669
+ for (const pattern of UNSUPPORTED_KEYWORDS) {
1670
+ if (pattern.test(text)) {
1671
+ errors.push({
1672
+ message: `Unsupported syntax: ${text}`,
1673
+ line: line.lineNo,
1674
+ severity: "error"
1675
+ });
1676
+ cursor.collectBlock(line.indent);
1677
+ return null;
1678
+ }
1679
+ }
1680
+ if (text.startsWith("@")) {
1681
+ const decorators = [text.slice(1).trim()];
1682
+ while (!cursor.done() && cursor.peek().text.startsWith("@")) {
1683
+ decorators.push(cursor.advance().text.slice(1).trim());
1684
+ }
1685
+ if (!cursor.done()) {
1686
+ const defLine = cursor.advance();
1687
+ const stmt = parseStatement(defLine, cursor, errors);
1688
+ if (stmt && stmt.type === "FunctionDef") {
1689
+ stmt.decorators = decorators;
1690
+ }
1691
+ return stmt;
1692
+ }
1693
+ return null;
1694
+ }
1695
+ if (text.startsWith("def ")) {
1696
+ return parseFunctionDef(text, line, cursor, errors);
1697
+ }
1698
+ if (text.startsWith("class ")) {
1699
+ return parseClassDef(text, line, cursor, errors);
1700
+ }
1701
+ if (text.startsWith("if ")) {
1702
+ return parseIf(text, line, cursor, errors);
1703
+ }
1704
+ if (text.startsWith("for ")) {
1705
+ return parseFor(text, line, cursor, errors);
1706
+ }
1707
+ if (text.startsWith("while ")) {
1708
+ return parseWhile(text, line, cursor, errors);
1709
+ }
1710
+ if (text.startsWith("try:")) {
1711
+ return parseTry(line, cursor, errors);
1712
+ }
1713
+ if (text === "return" || text.startsWith("return ")) {
1714
+ return parseReturn(text, line, errors);
1715
+ }
1716
+ if (text === "pass") {
1717
+ return null;
1718
+ }
1719
+ if (text.startsWith("elif ") || text === "else:" || text.startsWith("except")) {
1720
+ cursor.collectBlock(line.indent);
1721
+ return null;
1722
+ }
1723
+ const augMatch = text.match(
1724
+ /^([A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*)\s*(\+\=|\-\=|\*\=|\/\=|\/\/\=|%\=|\*\*\=|&\=|\|\=)\s*(.+)$/
1725
+ );
1726
+ if (augMatch) {
1727
+ return {
1728
+ type: "AugAssign",
1729
+ target: augMatch[1],
1730
+ op: augMatch[2],
1731
+ value: parseExpr(augMatch[3].trim(), line.lineNo, errors)
1732
+ };
1733
+ }
1734
+ const assignMatch = text.match(
1735
+ /^([A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*(?:\[[^\]]+\])?)\s*=\s*(.+)$/
1736
+ );
1737
+ if (assignMatch) {
1738
+ const afterTarget = text.slice(assignMatch[1].length).trimStart();
1739
+ if (afterTarget.startsWith("==")) {
1740
+ } else {
1741
+ return {
1742
+ type: "Assign",
1743
+ target: assignMatch[1],
1744
+ value: parseExpr(assignMatch[2].trim(), line.lineNo, errors)
1745
+ };
1746
+ }
1747
+ }
1748
+ const expr = parseExpr(text, line.lineNo, errors);
1749
+ return {
1750
+ type: "Expr",
1751
+ value: expr
1752
+ };
1753
+ }
1754
+ function parseFunctionDef(text, line, cursor, errors) {
1755
+ const nameMatch = text.match(/^def\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(/);
1756
+ const openParenIdx = text.indexOf("(");
1757
+ const closeParenIdx = openParenIdx >= 0 ? findMatchingClose(text, openParenIdx, "(", ")") : -1;
1758
+ if (!nameMatch || openParenIdx < 0 || closeParenIdx < 0) {
1759
+ errors.push({
1760
+ message: `Invalid function definition: ${text}`,
1761
+ line: line.lineNo,
1762
+ severity: "error"
1763
+ });
1764
+ cursor.collectBlock(line.indent);
1765
+ return {
1766
+ type: "FunctionDef",
1767
+ name: "unknown",
1768
+ params: [],
1769
+ body: [],
1770
+ decorators: []
1771
+ };
1772
+ }
1773
+ const trailing = text.slice(closeParenIdx + 1).trim();
1774
+ if (!trailing.startsWith(":")) {
1775
+ errors.push({
1776
+ message: `Invalid function definition: ${text}`,
1777
+ line: line.lineNo,
1778
+ severity: "error"
1779
+ });
1780
+ cursor.collectBlock(line.indent);
1781
+ return {
1782
+ type: "FunctionDef",
1783
+ name: nameMatch[1],
1784
+ params: [],
1785
+ body: [],
1786
+ decorators: []
1787
+ };
1788
+ }
1789
+ const name = nameMatch[1];
1790
+ const paramsStr = text.slice(openParenIdx + 1, closeParenIdx).trim();
1791
+ const params = paramsStr ? splitArgs(paramsStr).map((param) => extractParameterName(param)).filter((param) => Boolean(param)) : [];
1792
+ const bodyLines = cursor.collectBlock(line.indent);
1793
+ const bodyCursor = new Cursor(bodyLines);
1794
+ const body = parseBlock(bodyCursor, line.indent, errors);
1795
+ return {
1796
+ type: "FunctionDef",
1797
+ name,
1798
+ params,
1799
+ body,
1800
+ decorators: []
1801
+ };
1802
+ }
1803
+ function parseClassDef(text, line, cursor, errors) {
1804
+ const match = text.match(/^class\s+([A-Za-z_][A-Za-z0-9_]*)(?:\(([^)]*)\))?\s*:/);
1805
+ if (!match) {
1806
+ errors.push({
1807
+ message: `Invalid class definition: ${text}`,
1808
+ line: line.lineNo,
1809
+ severity: "error"
1810
+ });
1811
+ cursor.collectBlock(line.indent);
1812
+ return { type: "ClassDef", name: "unknown", bases: [], body: [] };
1813
+ }
1814
+ const name = match[1];
1815
+ const basesStr = match[2]?.trim() ?? "";
1816
+ const bases = basesStr ? basesStr.split(",").map((b) => b.trim()) : [];
1817
+ const bodyLines = cursor.collectBlock(line.indent);
1818
+ const bodyCursor = new Cursor(bodyLines);
1819
+ const body = parseBlock(bodyCursor, line.indent, errors);
1820
+ return { type: "ClassDef", name, bases, body };
1821
+ }
1822
+ function parseIf(text, line, cursor, errors) {
1823
+ const condStr = text.replace(/^if\s+/, "").replace(/\s*:\s*$/, "");
1824
+ const test = parseExpr(condStr, line.lineNo, errors);
1825
+ const bodyLines = cursor.collectBlock(line.indent);
1826
+ const bodyCursor = new Cursor(bodyLines);
1827
+ const body = parseBlock(bodyCursor, line.indent, errors);
1828
+ let orelse = [];
1829
+ if (!cursor.done()) {
1830
+ const next = cursor.peek();
1831
+ if (next.indent === line.indent && next.text.startsWith("elif ")) {
1832
+ cursor.advance();
1833
+ const elifText = next.text.replace(/^elif\s+/, "if ");
1834
+ const elifIf = parseIf(elifText, next, cursor, errors);
1835
+ orelse = [elifIf];
1836
+ } else if (next.indent === line.indent && next.text === "else:") {
1837
+ cursor.advance();
1838
+ const elseLines = cursor.collectBlock(line.indent);
1839
+ const elseCursor = new Cursor(elseLines);
1840
+ orelse = parseBlock(elseCursor, line.indent, errors);
1841
+ }
1842
+ }
1843
+ return { type: "If", test, body, orelse };
1844
+ }
1845
+ function parseFor(text, line, cursor, errors) {
1846
+ const match = text.match(/^for\s+([A-Za-z_][A-Za-z0-9_]*)\s+in\s+(.+)\s*:\s*$/);
1847
+ if (!match) {
1848
+ errors.push({
1849
+ message: `Invalid for loop: ${text}`,
1850
+ line: line.lineNo,
1851
+ severity: "error"
1852
+ });
1853
+ cursor.collectBlock(line.indent);
1854
+ return {
1855
+ type: "For",
1856
+ target: "unknown",
1857
+ iter: { type: "Name", id: "unknown" },
1858
+ body: []
1859
+ };
1860
+ }
1861
+ const target = match[1];
1862
+ const iterExpr = parseExpr(match[2].trim(), line.lineNo, errors);
1863
+ const bodyLines = cursor.collectBlock(line.indent);
1864
+ const bodyCursor = new Cursor(bodyLines);
1865
+ const body = parseBlock(bodyCursor, line.indent, errors);
1866
+ return { type: "For", target, iter: iterExpr, body };
1867
+ }
1868
+ function parseWhile(text, line, cursor, errors) {
1869
+ const condStr = text.replace(/^while\s+/, "").replace(/\s*:\s*$/, "");
1870
+ const test = parseExpr(condStr, line.lineNo, errors);
1871
+ const bodyLines = cursor.collectBlock(line.indent);
1872
+ const bodyCursor = new Cursor(bodyLines);
1873
+ const body = parseBlock(bodyCursor, line.indent, errors);
1874
+ return { type: "While", test, body };
1875
+ }
1876
+ function parseTry(line, cursor, errors) {
1877
+ const tryBodyLines = cursor.collectBlock(line.indent);
1878
+ const tryCursor = new Cursor(tryBodyLines);
1879
+ const tryBody = parseBlock(tryCursor, line.indent, errors);
1880
+ let handler = null;
1881
+ if (!cursor.done()) {
1882
+ const next = cursor.peek();
1883
+ if (next.indent === line.indent && next.text.startsWith("except")) {
1884
+ cursor.advance();
1885
+ const exceptMatch = next.text.match(
1886
+ /^except\s*(?:([A-Za-z_][A-Za-z0-9_]*))?(?:\s+as\s+([A-Za-z_][A-Za-z0-9_]*))?\s*:\s*$/
1887
+ );
1888
+ const handlerType = exceptMatch?.[1] ?? null;
1889
+ const handlerName = exceptMatch?.[2] ?? null;
1890
+ const handlerBodyLines = cursor.collectBlock(line.indent);
1891
+ const handlerCursor = new Cursor(handlerBodyLines);
1892
+ const handlerBody = parseBlock(handlerCursor, line.indent, errors);
1893
+ handler = { type: handlerType, name: handlerName, body: handlerBody };
1894
+ }
1895
+ }
1896
+ return { type: "Try", body: tryBody, handler };
1897
+ }
1898
+ function parseReturn(text, line, errors) {
1899
+ const valueStr = text.replace(/^return\s*/, "").trim();
1900
+ if (!valueStr) {
1901
+ return { type: "Return", value: null };
1902
+ }
1903
+ return { type: "Return", value: parseExpr(valueStr, line.lineNo, errors) };
1904
+ }
1905
+ function parseExpr(text, lineNo, errors) {
1906
+ text = text.trim();
1907
+ if (!text) {
1908
+ return { type: "Constant", value: null, kind: "none" };
1909
+ }
1910
+ if (text.startsWith("lambda")) {
1911
+ return parseLambda(text, lineNo, errors);
1912
+ }
1913
+ return parseBoolOr(text, lineNo, errors);
1914
+ }
1915
+ function parseLambda(text, lineNo, errors) {
1916
+ const match = text.match(/^lambda\s*([^:]*)\s*:\s*(.+)$/);
1917
+ if (!match) {
1918
+ return {
1919
+ type: "Lambda",
1920
+ params: [],
1921
+ body: { type: "Constant", value: null, kind: "none" }
1922
+ };
1923
+ }
1924
+ const paramsStr = match[1].trim();
1925
+ const params = paramsStr ? paramsStr.split(",").map((p) => p.trim()) : [];
1926
+ const body = parseExpr(match[2].trim(), lineNo, errors);
1927
+ return { type: "Lambda", params, body };
1928
+ }
1929
+ function parseBoolOr(text, lineNo, errors) {
1930
+ const parts = splitTopLevel(text, " or ");
1931
+ if (parts.length === 1) return parseBoolAnd(parts[0], lineNo, errors);
1932
+ const values = parts.map((p) => parseBoolAnd(p, lineNo, errors));
1933
+ return { type: "BoolOp", op: "or", values };
1934
+ }
1935
+ function parseBoolAnd(text, lineNo, errors) {
1936
+ const parts = splitTopLevel(text, " and ");
1937
+ if (parts.length === 1) return parseNot(parts[0], lineNo, errors);
1938
+ const values = parts.map((p) => parseNot(p, lineNo, errors));
1939
+ return { type: "BoolOp", op: "and", values };
1940
+ }
1941
+ function parseNot(text, lineNo, errors) {
1942
+ text = text.trim();
1943
+ if (text.startsWith("not ")) {
1944
+ const operand = parseNot(text.slice(4).trim(), lineNo, errors);
1945
+ return { type: "UnaryOp", op: "not", operand };
1946
+ }
1947
+ return parseComparison(text, lineNo, errors);
1948
+ }
1949
+ var COMPARISON_OPS = [" not in ", " in ", "<=", ">=", "!=", "==", "<", ">"];
1950
+ function parseComparison(text, lineNo, errors) {
1951
+ let bestIdx = -1;
1952
+ let bestOp = "";
1953
+ for (const op of COMPARISON_OPS) {
1954
+ const idx = findTopLevel(text, op);
1955
+ if (idx !== -1 && (bestIdx === -1 || idx < bestIdx)) {
1956
+ bestIdx = idx;
1957
+ bestOp = op;
1958
+ }
1959
+ }
1960
+ if (bestIdx === -1) {
1961
+ return parseAddSub(text, lineNo, errors);
1962
+ }
1963
+ const left2 = parseAddSub(text.slice(0, bestIdx).trim(), lineNo, errors);
1964
+ const right2 = parseComparison(text.slice(bestIdx + bestOp.length).trim(), lineNo, errors);
1965
+ if (right2.type === "Compare") {
1966
+ const rightCmp = right2;
1967
+ return {
1968
+ type: "Compare",
1969
+ left: left2,
1970
+ ops: [bestOp.trim(), ...rightCmp.ops],
1971
+ comparators: [rightCmp.left, ...rightCmp.comparators]
1972
+ };
1973
+ }
1974
+ return {
1975
+ type: "Compare",
1976
+ left: left2,
1977
+ ops: [bestOp.trim()],
1978
+ comparators: [right2]
1979
+ };
1980
+ }
1981
+ function parseAddSub(text, lineNo, errors) {
1982
+ let parenDepth = 0;
1983
+ let bracketDepth = 0;
1984
+ let braceDepth = 0;
1985
+ let inStr = null;
1986
+ let splitIdx = -1;
1987
+ let splitOp = "";
1988
+ for (let i = text.length - 1; i >= 1; i--) {
1989
+ const ch = text[i];
1990
+ if ((ch === '"' || ch === "'") && text[i - 1] !== "\\") {
1991
+ if (inStr === ch) {
1992
+ inStr = null;
1993
+ continue;
1994
+ } else if (!inStr) {
1995
+ inStr = ch;
1996
+ continue;
1997
+ }
1998
+ }
1999
+ if (inStr) continue;
2000
+ if (ch === ")") parenDepth++;
2001
+ else if (ch === "(") parenDepth--;
2002
+ else if (ch === "]") bracketDepth++;
2003
+ else if (ch === "[") bracketDepth--;
2004
+ else if (ch === "}") braceDepth++;
2005
+ else if (ch === "{") braceDepth--;
2006
+ if (parenDepth === 0 && bracketDepth === 0 && braceDepth === 0) {
2007
+ if ((ch === "+" || ch === "-") && text[i - 1] !== "*" && text[i + 1] !== "=" && text[i - 1] !== "=") {
2008
+ const before = text.slice(0, i).trim();
2009
+ if (before.length > 0 && !before.endsWith("(") && !before.endsWith(",") && !before.endsWith("[")) {
2010
+ splitIdx = i;
2011
+ splitOp = ch;
2012
+ break;
2013
+ }
2014
+ }
2015
+ }
2016
+ }
2017
+ if (splitIdx === -1) {
2018
+ return parseMulDiv(text, lineNo, errors);
2019
+ }
2020
+ const left2 = parseAddSub(text.slice(0, splitIdx).trim(), lineNo, errors);
2021
+ const right2 = parseMulDiv(text.slice(splitIdx + 1).trim(), lineNo, errors);
2022
+ return { type: "BinOp", left: left2, op: splitOp, right: right2 };
2023
+ }
2024
+ function parseMulDiv(text, lineNo, errors) {
2025
+ let parenDepth = 0;
2026
+ let bracketDepth = 0;
2027
+ let braceDepth = 0;
2028
+ let inStr = null;
2029
+ let splitIdx = -1;
2030
+ let splitOp = "";
2031
+ for (let i = text.length - 1; i >= 0; i--) {
2032
+ const ch = text[i];
2033
+ if ((ch === '"' || ch === "'") && (i === 0 || text[i - 1] !== "\\")) {
2034
+ if (inStr === ch) {
2035
+ inStr = null;
2036
+ continue;
2037
+ } else if (!inStr) {
2038
+ inStr = ch;
2039
+ continue;
2040
+ }
2041
+ }
2042
+ if (inStr) continue;
2043
+ if (ch === ")") parenDepth++;
2044
+ else if (ch === "(") parenDepth--;
2045
+ else if (ch === "]") bracketDepth++;
2046
+ else if (ch === "[") bracketDepth--;
2047
+ else if (ch === "}") braceDepth++;
2048
+ else if (ch === "{") braceDepth--;
2049
+ if (parenDepth === 0 && bracketDepth === 0 && braceDepth === 0) {
2050
+ if (ch === "*" && i > 0 && text[i - 1] !== "*" && (i + 1 >= text.length || text[i + 1] !== "*")) {
2051
+ splitIdx = i;
2052
+ splitOp = "*";
2053
+ break;
2054
+ }
2055
+ if (ch === "/" && i > 0) {
2056
+ if (text[i - 1] === "/") {
2057
+ splitIdx = i - 1;
2058
+ splitOp = "//";
2059
+ break;
2060
+ }
2061
+ splitIdx = i;
2062
+ splitOp = "/";
2063
+ break;
2064
+ }
2065
+ if (ch === "%") {
2066
+ splitIdx = i;
2067
+ splitOp = "%";
2068
+ break;
2069
+ }
2070
+ }
2071
+ }
2072
+ if (splitIdx === -1) {
2073
+ return parsePower(text, lineNo, errors);
2074
+ }
2075
+ const left2 = parseMulDiv(text.slice(0, splitIdx).trim(), lineNo, errors);
2076
+ const right2 = parsePower(text.slice(splitIdx + splitOp.length).trim(), lineNo, errors);
2077
+ return { type: "BinOp", left: left2, op: splitOp, right: right2 };
2078
+ }
2079
+ function parsePower(text, lineNo, errors) {
2080
+ const idx = findTopLevel(text, "**");
2081
+ if (idx === -1) {
2082
+ return parseUnary(text, lineNo, errors);
2083
+ }
2084
+ const left2 = parseUnary(text.slice(0, idx).trim(), lineNo, errors);
2085
+ const right2 = parsePower(text.slice(idx + 2).trim(), lineNo, errors);
2086
+ return { type: "BinOp", left: left2, op: "**", right: right2 };
2087
+ }
2088
+ function parseUnary(text, lineNo, errors) {
2089
+ text = text.trim();
2090
+ if (text.startsWith("-") && text.length > 1) {
2091
+ const rest = text.slice(1).trim();
2092
+ if (rest && !/^\d/.test(rest)) {
2093
+ const operand = parseUnary(rest, lineNo, errors);
2094
+ return { type: "UnaryOp", op: "-", operand };
2095
+ }
2096
+ }
2097
+ if (text.startsWith("+") && text.length > 1) {
2098
+ const rest = text.slice(1).trim();
2099
+ if (rest && !/^\d/.test(rest)) {
2100
+ const operand = parseUnary(rest, lineNo, errors);
2101
+ return { type: "UnaryOp", op: "+", operand };
2102
+ }
2103
+ }
2104
+ return parsePostfix(text, lineNo, errors);
2105
+ }
2106
+ function parsePostfix(text, lineNo, errors) {
2107
+ text = text.trim();
2108
+ let node = parsePrimary(text, lineNo, errors);
2109
+ const parsed = parsePrimaryWithPostfix(text, lineNo, errors);
2110
+ return parsed;
2111
+ }
2112
+ function parsePrimaryWithPostfix(text, lineNo, errors) {
2113
+ text = text.trim();
2114
+ let pos = 0;
2115
+ const { node, endPos } = parsePrimaryAt(text, pos, lineNo, errors);
2116
+ pos = endPos;
2117
+ let current = node;
2118
+ while (pos < text.length) {
2119
+ const ch = text[pos];
2120
+ if (ch === ".") {
2121
+ pos++;
2122
+ const attrMatch = text.slice(pos).match(/^[A-Za-z_][A-Za-z0-9_]*/);
2123
+ if (attrMatch) {
2124
+ const attr = attrMatch[0];
2125
+ pos += attr.length;
2126
+ current = { type: "Attribute", value: current, attr };
2127
+ } else {
2128
+ break;
2129
+ }
2130
+ } else if (ch === "[") {
2131
+ const closeIdx = findMatchingClose(text, pos, "[", "]");
2132
+ if (closeIdx === -1) break;
2133
+ const sliceStr = text.slice(pos + 1, closeIdx).trim();
2134
+ const sliceNode = parseExpr(sliceStr, lineNo, errors);
2135
+ current = { type: "Subscript", value: current, slice: sliceNode };
2136
+ pos = closeIdx + 1;
2137
+ } else if (ch === "(") {
2138
+ const closeIdx = findMatchingClose(text, pos, "(", ")");
2139
+ if (closeIdx === -1) break;
2140
+ const argsStr = text.slice(pos + 1, closeIdx).trim();
2141
+ const { args, kwargs } = parseCallArgs(argsStr, lineNo, errors);
2142
+ current = { type: "Call", func: current, args, kwargs };
2143
+ pos = closeIdx + 1;
2144
+ } else if (ch === " " || ch === " ") {
2145
+ pos++;
2146
+ } else {
2147
+ break;
2148
+ }
2149
+ }
2150
+ return current;
2151
+ }
2152
+ function parsePrimaryAt(text, pos, lineNo, errors) {
2153
+ while (pos < text.length && (text[pos] === " " || text[pos] === " ")) pos++;
2154
+ if (pos >= text.length) {
2155
+ return {
2156
+ node: { type: "Constant", value: null, kind: "none" },
2157
+ endPos: pos
2158
+ };
2159
+ }
2160
+ const remaining = text.slice(pos);
2161
+ if (remaining[0] === "(") {
2162
+ const closeIdx = findMatchingClose(text, pos, "(", ")");
2163
+ if (closeIdx !== -1) {
2164
+ const inner = text.slice(pos + 1, closeIdx).trim();
2165
+ const node = parseExpr(inner, lineNo, errors);
2166
+ return { node, endPos: closeIdx + 1 };
2167
+ }
2168
+ }
2169
+ if (remaining[0] === "[") {
2170
+ const closeIdx = findMatchingClose(text, pos, "[", "]");
2171
+ if (closeIdx !== -1) {
2172
+ const inner = text.slice(pos + 1, closeIdx).trim();
2173
+ const elts = inner ? splitArgs(inner).map((e) => parseExpr(e.trim(), lineNo, errors)) : [];
2174
+ return {
2175
+ node: { type: "List", elts },
2176
+ endPos: closeIdx + 1
2177
+ };
2178
+ }
2179
+ }
2180
+ if (remaining[0] === "{") {
2181
+ const closeIdx = findMatchingClose(text, pos, "{", "}");
2182
+ if (closeIdx !== -1) {
2183
+ const inner = text.slice(pos + 1, closeIdx).trim();
2184
+ const keys = [];
2185
+ const values = [];
2186
+ if (inner) {
2187
+ const entries = splitArgs(inner);
2188
+ for (const entry of entries) {
2189
+ const colonIdx = findTopLevel(entry, ":");
2190
+ if (colonIdx !== -1) {
2191
+ keys.push(parseExpr(entry.slice(0, colonIdx).trim(), lineNo, errors));
2192
+ values.push(parseExpr(entry.slice(colonIdx + 1).trim(), lineNo, errors));
2193
+ }
2194
+ }
2195
+ }
2196
+ return {
2197
+ node: { type: "Dict", keys, values },
2198
+ endPos: closeIdx + 1
2199
+ };
2200
+ }
2201
+ }
2202
+ if (remaining[0] === '"' || remaining[0] === "'") {
2203
+ const quote = remaining[0];
2204
+ if (remaining.startsWith(quote + quote + quote)) {
2205
+ const endQuote = remaining.indexOf(quote + quote + quote, 3);
2206
+ if (endQuote !== -1) {
2207
+ const value = remaining.slice(3, endQuote);
2208
+ return {
2209
+ node: { type: "Constant", value, kind: "str" },
2210
+ endPos: pos + endQuote + 3
2211
+ };
2212
+ }
2213
+ }
2214
+ let i = 1;
2215
+ while (i < remaining.length) {
2216
+ if (remaining[i] === "\\" && i + 1 < remaining.length) {
2217
+ i += 2;
2218
+ continue;
2219
+ }
2220
+ if (remaining[i] === quote) {
2221
+ const value = remaining.slice(1, i);
2222
+ return {
2223
+ node: { type: "Constant", value, kind: "str" },
2224
+ endPos: pos + i + 1
2225
+ };
2226
+ }
2227
+ i++;
2228
+ }
2229
+ return {
2230
+ node: {
2231
+ type: "Constant",
2232
+ value: remaining.slice(1),
2233
+ kind: "str"
2234
+ },
2235
+ endPos: pos + remaining.length
2236
+ };
2237
+ }
2238
+ if ((remaining[0] === "f" || remaining[0] === "F") && remaining.length > 1 && (remaining[1] === '"' || remaining[1] === "'")) {
2239
+ const quote = remaining[1];
2240
+ let i = 2;
2241
+ while (i < remaining.length) {
2242
+ if (remaining[i] === "\\" && i + 1 < remaining.length) {
2243
+ i += 2;
2244
+ continue;
2245
+ }
2246
+ if (remaining[i] === quote) {
2247
+ const value = remaining.slice(2, i);
2248
+ return {
2249
+ node: { type: "Constant", value, kind: "str" },
2250
+ endPos: pos + i + 1
2251
+ };
2252
+ }
2253
+ i++;
2254
+ }
2255
+ return {
2256
+ node: {
2257
+ type: "Constant",
2258
+ value: remaining.slice(2),
2259
+ kind: "str"
2260
+ },
2261
+ endPos: pos + remaining.length
2262
+ };
2263
+ }
2264
+ const numMatch = remaining.match(/^-?\d+(\.\d+)?/);
2265
+ if (numMatch) {
2266
+ const numStr = numMatch[0];
2267
+ const isFloat = numStr.includes(".");
2268
+ return {
2269
+ node: {
2270
+ type: "Constant",
2271
+ value: isFloat ? parseFloat(numStr) : parseInt(numStr, 10),
2272
+ kind: isFloat ? "float" : "int"
2273
+ },
2274
+ endPos: pos + numStr.length
2275
+ };
2276
+ }
2277
+ const identMatch = remaining.match(/^[A-Za-z_][A-Za-z0-9_]*/);
2278
+ if (identMatch) {
2279
+ const id = identMatch[0];
2280
+ const endPos = pos + id.length;
2281
+ if (id === "True") {
2282
+ return {
2283
+ node: { type: "Constant", value: true, kind: "bool" },
2284
+ endPos
2285
+ };
2286
+ }
2287
+ if (id === "False") {
2288
+ return {
2289
+ node: { type: "Constant", value: false, kind: "bool" },
2290
+ endPos
2291
+ };
2292
+ }
2293
+ if (id === "None") {
2294
+ return {
2295
+ node: { type: "Constant", value: null, kind: "none" },
2296
+ endPos
2297
+ };
2298
+ }
2299
+ return {
2300
+ node: { type: "Name", id },
2301
+ endPos
2302
+ };
2303
+ }
2304
+ errors.push({
2305
+ message: `Unexpected token: ${remaining.slice(0, 20)}`,
2306
+ line: lineNo,
2307
+ severity: "error"
2308
+ });
2309
+ return {
2310
+ node: { type: "Name", id: remaining.trim() },
2311
+ endPos: pos + remaining.length
2312
+ };
2313
+ }
2314
+ function parsePrimary(text, lineNo, errors) {
2315
+ const { node } = parsePrimaryAt(text, 0, lineNo, errors);
2316
+ return node;
2317
+ }
2318
+ function splitTopLevel(text, delimiter) {
2319
+ const parts = [];
2320
+ let parenDepth = 0;
2321
+ let bracketDepth = 0;
2322
+ let braceDepth = 0;
2323
+ let inStr = null;
2324
+ let start = 0;
2325
+ for (let i = 0; i <= text.length - delimiter.length; i++) {
2326
+ const ch = text[i];
2327
+ if ((ch === '"' || ch === "'") && (i === 0 || text[i - 1] !== "\\")) {
2328
+ if (inStr === ch) {
2329
+ inStr = null;
2330
+ continue;
2331
+ } else if (!inStr) {
2332
+ inStr = ch;
2333
+ continue;
2334
+ }
2335
+ }
2336
+ if (inStr) continue;
2337
+ if (ch === "(") parenDepth++;
2338
+ else if (ch === ")") parenDepth--;
2339
+ else if (ch === "[") bracketDepth++;
2340
+ else if (ch === "]") bracketDepth--;
2341
+ else if (ch === "{") braceDepth++;
2342
+ else if (ch === "}") braceDepth--;
2343
+ if (parenDepth === 0 && bracketDepth === 0 && braceDepth === 0 && text.slice(i, i + delimiter.length) === delimiter) {
2344
+ parts.push(text.slice(start, i).trim());
2345
+ start = i + delimiter.length;
2346
+ i = start - 1;
2347
+ }
2348
+ }
2349
+ parts.push(text.slice(start).trim());
2350
+ return parts;
2351
+ }
2352
+ function findTopLevel(text, needle) {
2353
+ let parenDepth = 0;
2354
+ let bracketDepth = 0;
2355
+ let braceDepth = 0;
2356
+ let inStr = null;
2357
+ for (let i = 0; i <= text.length - needle.length; i++) {
2358
+ const ch = text[i];
2359
+ if ((ch === '"' || ch === "'") && (i === 0 || text[i - 1] !== "\\")) {
2360
+ if (inStr === ch) {
2361
+ inStr = null;
2362
+ continue;
2363
+ } else if (!inStr) {
2364
+ inStr = ch;
2365
+ continue;
2366
+ }
2367
+ }
2368
+ if (inStr) continue;
2369
+ if (ch === "(") parenDepth++;
2370
+ else if (ch === ")") parenDepth--;
2371
+ else if (ch === "[") bracketDepth++;
2372
+ else if (ch === "]") bracketDepth--;
2373
+ else if (ch === "{") braceDepth++;
2374
+ else if (ch === "}") braceDepth--;
2375
+ if (parenDepth === 0 && bracketDepth === 0 && braceDepth === 0 && text.slice(i, i + needle.length) === needle) {
2376
+ return i;
2377
+ }
2378
+ }
2379
+ return -1;
2380
+ }
2381
+ function findMatchingClose(text, openIdx, open, close) {
2382
+ let depth = 0;
2383
+ let inStr = null;
2384
+ for (let i = openIdx; i < text.length; i++) {
2385
+ const ch = text[i];
2386
+ if ((ch === '"' || ch === "'") && (i === 0 || text[i - 1] !== "\\")) {
2387
+ if (inStr === ch) {
2388
+ inStr = null;
2389
+ continue;
2390
+ } else if (!inStr) {
2391
+ inStr = ch;
2392
+ continue;
2393
+ }
2394
+ }
2395
+ if (inStr) continue;
2396
+ if (ch === open) depth++;
2397
+ else if (ch === close) {
2398
+ depth--;
2399
+ if (depth === 0) return i;
2400
+ }
2401
+ }
2402
+ return -1;
2403
+ }
2404
+ function splitArgs(text) {
2405
+ return splitTopLevel(text, ",");
2406
+ }
2407
+ function extractParameterName(param) {
2408
+ const trimmed = param.trim();
2409
+ if (!trimmed || trimmed === "*" || trimmed === "/") return null;
2410
+ const match = trimmed.match(/^\*{0,2}([A-Za-z_][A-Za-z0-9_]*)/);
2411
+ return match?.[1] ?? null;
2412
+ }
2413
+ function opensBlock(text) {
2414
+ return text === "else:" || text.startsWith("except") || /^(def|class|if|elif|for|while)\b/.test(text) && text.trimEnd().endsWith(":") || text === "try:";
2415
+ }
2416
+ function validateIndentation(lines, errors) {
2417
+ const indentStack = [0];
2418
+ let indentUnit = null;
2419
+ let previousOpenedBlock = false;
2420
+ for (const line of lines) {
2421
+ const currentIndent = line.indent;
2422
+ let topIndent = indentStack[indentStack.length - 1];
2423
+ if (currentIndent > topIndent) {
2424
+ const delta = currentIndent - topIndent;
2425
+ if (!previousOpenedBlock) {
2426
+ errors.push({
2427
+ message: `Unexpected indentation on line ${line.lineNo}`,
2428
+ line: line.lineNo,
2429
+ severity: "error"
2430
+ });
2431
+ }
2432
+ if (indentUnit === null) {
2433
+ indentUnit = delta;
2434
+ } else if (delta !== indentUnit) {
2435
+ errors.push({
2436
+ message: `Inconsistent indentation width on line ${line.lineNo}`,
2437
+ line: line.lineNo,
2438
+ severity: "error"
2439
+ });
2440
+ }
2441
+ indentStack.push(currentIndent);
2442
+ topIndent = currentIndent;
2443
+ } else if (currentIndent < topIndent) {
2444
+ while (indentStack.length > 1 && currentIndent < topIndent) {
2445
+ indentStack.pop();
2446
+ topIndent = indentStack[indentStack.length - 1];
2447
+ }
2448
+ if (currentIndent !== topIndent) {
2449
+ errors.push({
2450
+ message: `Inconsistent dedent on line ${line.lineNo}`,
2451
+ line: line.lineNo,
2452
+ severity: "error"
2453
+ });
2454
+ }
2455
+ }
2456
+ previousOpenedBlock = opensBlock(line.text);
2457
+ }
2458
+ }
2459
+ function parseCallArgs(text, lineNo, errors) {
2460
+ if (!text.trim()) return { args: [], kwargs: [] };
2461
+ const parts = splitArgs(text);
2462
+ const args = [];
2463
+ const kwargs = [];
2464
+ for (const part of parts) {
2465
+ const trimmed = part.trim();
2466
+ const kwMatch = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=(?!=)\s*(.+)$/);
2467
+ if (kwMatch) {
2468
+ kwargs.push({
2469
+ key: kwMatch[1],
2470
+ value: parseExpr(kwMatch[2].trim(), lineNo, errors)
2471
+ });
2472
+ } else {
2473
+ args.push(parseExpr(trimmed, lineNo, errors));
2474
+ }
2475
+ }
2476
+ return { args, kwargs };
2477
+ }
2478
+
2479
+ // ../../lib/py2bend/transforms.ts
2480
+ function transformModule(ast) {
2481
+ return {
2482
+ type: "BendModule",
2483
+ source: "Module",
2484
+ body: transformNodes(ast.body)
2485
+ };
2486
+ }
2487
+ function transformNodes(nodes) {
2488
+ return nodes.map(transformNode);
2489
+ }
2490
+ function transformNode(node) {
2491
+ switch (node.type) {
2492
+ case "FunctionDef":
2493
+ return transformFunctionDef(node);
2494
+ case "For":
2495
+ return transformFor(node);
2496
+ case "While":
2497
+ return transformWhile(node);
2498
+ case "ClassDef":
2499
+ return transformClass(node);
2500
+ case "Try":
2501
+ return transformTry(node);
2502
+ default:
2503
+ return passthrough(node);
2504
+ }
2505
+ }
2506
+ function transformFunctionDef(node) {
2507
+ return {
2508
+ type: "BendFunctionDef",
2509
+ source: "FunctionDef",
2510
+ name: node.name,
2511
+ params: node.params,
2512
+ body: transformNodes(node.body),
2513
+ decorators: node.decorators
2514
+ };
2515
+ }
2516
+ function transformFor(node) {
2517
+ const accumulator = findAccumulator(node.body);
2518
+ return {
2519
+ type: "BendFold",
2520
+ source: "For",
2521
+ target: node.target,
2522
+ iter: node.iter,
2523
+ body: transformNodes(node.body),
2524
+ accumulator
2525
+ };
2526
+ }
2527
+ function findAccumulator(body) {
2528
+ for (const stmt of body) {
2529
+ if (stmt.type === "AugAssign") {
2530
+ return stmt.target;
2531
+ }
2532
+ }
2533
+ return null;
2534
+ }
2535
+ function transformWhile(node) {
2536
+ return {
2537
+ type: "BendLoop",
2538
+ source: "While",
2539
+ test: node.test,
2540
+ body: transformNodes(node.body),
2541
+ stateVars: collectLoopStateVars(node.body)
2542
+ };
2543
+ }
2544
+ function collectLoopStateVars(body) {
2545
+ const vars = /* @__PURE__ */ new Set();
2546
+ for (const stmt of body) {
2547
+ if (stmt.type === "Assign") {
2548
+ const target = stmt.target;
2549
+ if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(target)) {
2550
+ vars.add(target);
2551
+ }
2552
+ }
2553
+ if (stmt.type === "AugAssign") {
2554
+ const target = stmt.target;
2555
+ if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(target)) {
2556
+ vars.add(target);
2557
+ }
2558
+ }
2559
+ }
2560
+ return Array.from(vars);
2561
+ }
2562
+ function transformClass(node) {
2563
+ const fields = extractFields(node.body);
2564
+ const methods = [];
2565
+ for (const member of node.body) {
2566
+ if (member.type === "FunctionDef") {
2567
+ methods.push(transformFunctionDef(member));
2568
+ }
2569
+ }
2570
+ return {
2571
+ type: "BendObject",
2572
+ source: "ClassDef",
2573
+ name: node.name,
2574
+ bases: node.bases,
2575
+ fields,
2576
+ methods
2577
+ };
2578
+ }
2579
+ function extractFields(body) {
2580
+ const fields = [];
2581
+ const initMethod = body.find(
2582
+ (n) => n.type === "FunctionDef" && n.name === "__init__"
2583
+ );
2584
+ if (!initMethod) return fields;
2585
+ for (const stmt of initMethod.body) {
2586
+ if (stmt.type === "Assign") {
2587
+ const assign = stmt;
2588
+ const fieldMatch = assign.target.match(/^self\.([A-Za-z_][A-Za-z0-9_]*)$/);
2589
+ if (fieldMatch) {
2590
+ fields.push(fieldMatch[1]);
2591
+ }
2592
+ }
2593
+ }
2594
+ return fields;
2595
+ }
2596
+ function transformTry(node) {
2597
+ return {
2598
+ type: "BendWith",
2599
+ source: "Try",
2600
+ body: transformNodes(node.body),
2601
+ handler: node.handler ? {
2602
+ name: node.handler.name,
2603
+ type: node.handler.type,
2604
+ body: transformNodes(node.handler.body)
2605
+ } : null
2606
+ };
2607
+ }
2608
+ function passthrough(node) {
2609
+ return {
2610
+ type: "BendPassthrough",
2611
+ source: node.type,
2612
+ node
2613
+ };
2614
+ }
2615
+
2616
+ // ../../lib/py2bend/media-stdlib.ts
2617
+ var MEDIA_BUILTIN_MAP = {
2618
+ // Frame generation
2619
+ "render_frame": "Media/render_frame",
2620
+ "encode_video": "Media/encode_video",
2621
+ "encode_audio": "Media/encode_audio",
2622
+ // Kuramoto utilities
2623
+ "kuramoto_step": "Phase/kuramoto_step",
2624
+ "order_parameter": "Phase/order_parameter",
2625
+ // Audio synthesis
2626
+ "oscillator": "Audio/oscillator",
2627
+ "mix_channels": "Audio/mix",
2628
+ "soft_clip": "Audio/soft_clip",
2629
+ "fade": "Audio/fade",
2630
+ // Math shortcuts
2631
+ "linspace": "List/linspace",
2632
+ "zeros": "List/zeros",
2633
+ "sin": "Num/sin",
2634
+ "cos": "Num/cos",
2635
+ "tanh": "Num/tanh",
2636
+ "exp": "Num/exp",
2637
+ "log2": "Num/log2",
2638
+ "pi": "Num/pi"
2639
+ };
2640
+
2641
+ // ../../lib/py2bend/stdlib.ts
2642
+ var BUILTIN_MAP = {
2643
+ len: "List/len",
2644
+ print: "IO/print",
2645
+ range: "List/range",
2646
+ int: "Num/to_int",
2647
+ float: "Num/to_float",
2648
+ str: "Str/from",
2649
+ bool: "Bool/from",
2650
+ abs: "Num/abs",
2651
+ min: "Num/min",
2652
+ max: "Num/max",
2653
+ sum: "List/sum",
2654
+ sorted: "List/sort",
2655
+ reversed: "List/reverse",
2656
+ enumerate: "List/enumerate",
2657
+ zip: "List/zip",
2658
+ map: "List/map",
2659
+ filter: "List/filter",
2660
+ any: "List/any",
2661
+ all: "List/all",
2662
+ isinstance: "Type/is",
2663
+ type: "Type/of",
2664
+ input: "IO/input",
2665
+ open: "IO/open",
2666
+ round: "Num/round",
2667
+ list: "List/from",
2668
+ dict: "Map/from",
2669
+ tuple: "Tuple/from",
2670
+ set: "Set/from",
2671
+ // Media builtins (from media-stdlib.ts)
2672
+ ...MEDIA_BUILTIN_MAP
2673
+ };
2674
+ var OP_MAP = {
2675
+ "+": "+",
2676
+ "-": "-",
2677
+ "*": "*",
2678
+ "/": "/",
2679
+ "//": "/",
2680
+ "%": "%",
2681
+ "**": "**",
2682
+ "&": "&",
2683
+ "|": "|",
2684
+ "==": "==",
2685
+ "!=": "!=",
2686
+ "<": "<",
2687
+ ">": ">",
2688
+ "<=": "<=",
2689
+ ">=": ">=",
2690
+ and: "&",
2691
+ or: "|",
2692
+ not: "!",
2693
+ in: "List/contains",
2694
+ "not in": "List/not_contains"
2695
+ };
2696
+
2697
+ // ../../lib/py2bend/codegen.ts
2698
+ function generateBend(module) {
2699
+ const lines = [];
2700
+ for (const node of module.body) {
2701
+ lines.push(generateNode(node, 0));
2702
+ }
2703
+ return lines.join("\n\n") + "\n";
2704
+ }
2705
+ function generateNode(node, depth) {
2706
+ switch (node.type) {
2707
+ case "BendFunctionDef":
2708
+ return generateFunctionDef(node, depth);
2709
+ case "BendFold":
2710
+ return generateFold(node, depth);
2711
+ case "BendLoop":
2712
+ return generateLoop(node, depth);
2713
+ case "BendObject":
2714
+ return generateObject(node, depth);
2715
+ case "BendWith":
2716
+ return generateWith(node, depth);
2717
+ case "BendPassthrough":
2718
+ return generatePassthrough(node, depth);
2719
+ default:
2720
+ return indent(depth) + `# unsupported: ${node.type}`;
2721
+ }
2722
+ }
2723
+ function generateFunctionDef(node, depth) {
2724
+ const params = node.params.join(", ");
2725
+ const head = `${indent(depth)}def ${node.name}(${params}):`;
2726
+ const bodyLines = node.body.map((n) => generateNode(n, depth + 1));
2727
+ if (bodyLines.length === 0) {
2728
+ return head + "\n" + indent(depth + 1) + "return *";
2729
+ }
2730
+ return head + "\n" + bodyLines.join("\n");
2731
+ }
2732
+ function generateFold(node, depth) {
2733
+ const iterExpr = generateExpr(node.iter, depth);
2734
+ const head = `${indent(depth)}fold ${iterExpr}:`;
2735
+ const consCase = `${indent(depth + 1)}case List/Cons:`;
2736
+ const bodyLines = node.body.map((n) => generateNode(n, depth + 2));
2737
+ const nilCase = `${indent(depth + 1)}case List/Nil:`;
2738
+ const nilBody = node.accumulator ? `${indent(depth + 2)}${node.accumulator}` : `${indent(depth + 2)}*`;
2739
+ return [head, consCase, ...bodyLines, nilCase, nilBody].join("\n");
2740
+ }
2741
+ function generateLoop(node, depth) {
2742
+ const testExpr = generateExpr(node.test, depth);
2743
+ const head = `${indent(depth)}bend x = 0:`;
2744
+ const whenLine = `${indent(depth + 1)}when ${testExpr}:`;
2745
+ const bodyLines = node.body.map((n) => generateNode(n, depth + 2));
2746
+ const forkLine = `${indent(depth + 2)}fork(x + 1)`;
2747
+ const elseLine = `${indent(depth + 1)}else:`;
2748
+ const elseBody = `${indent(depth + 2)}x`;
2749
+ return [head, whenLine, ...bodyLines, forkLine, elseLine, elseBody].join(
2750
+ "\n"
2751
+ );
2752
+ }
2753
+ function generateObject(node, depth) {
2754
+ const fieldsStr = node.fields.length > 0 ? ` { ${node.fields.join(", ")} }` : "";
2755
+ const head = `${indent(depth)}object ${node.name}${fieldsStr}`;
2756
+ if (node.methods.length === 0) {
2757
+ return head;
2758
+ }
2759
+ const nonInitMethods = node.methods.filter((m) => m.name !== "__init__");
2760
+ if (nonInitMethods.length === 0) {
2761
+ return head;
2762
+ }
2763
+ const methodLines = nonInitMethods.map(
2764
+ (m) => generateFunctionDef(m, depth)
2765
+ );
2766
+ return head + "\n\n" + methodLines.join("\n\n");
2767
+ }
2768
+ function generateWith(node, depth) {
2769
+ const head = `${indent(depth)}with Result:`;
2770
+ const bodyLines = node.body.map((n) => generateNode(n, depth + 1));
2771
+ if (!node.handler) {
2772
+ return [head, ...bodyLines].join("\n");
2773
+ }
2774
+ const handlerLines = node.handler.body.map(
2775
+ (n) => generateNode(n, depth + 1)
2776
+ );
2777
+ const handlerHead = node.handler.name ? `${indent(depth)}catch ${node.handler.name}:` : `${indent(depth)}catch _err:`;
2778
+ return [head, ...bodyLines, handlerHead, ...handlerLines].join("\n");
2779
+ }
2780
+ function generatePassthrough(node, depth) {
2781
+ return generatePyStatement(node.node, depth);
2782
+ }
2783
+ function generatePyStatement(node, depth) {
2784
+ switch (node.type) {
2785
+ case "Return":
2786
+ return generateReturn(node, depth);
2787
+ case "Assign":
2788
+ return generateAssign(node, depth);
2789
+ case "AugAssign":
2790
+ return generateAugAssign(node, depth);
2791
+ case "If":
2792
+ return generateIf(node, depth);
2793
+ case "Expr":
2794
+ return indent(depth) + generateExpr(node.value, depth);
2795
+ default:
2796
+ return indent(depth) + generateExpr(node, depth);
2797
+ }
2798
+ }
2799
+ function generateReturn(node, depth) {
2800
+ if (!node.value) {
2801
+ return `${indent(depth)}return *`;
2802
+ }
2803
+ return `${indent(depth)}return ${generateExpr(node.value, depth)}`;
2804
+ }
2805
+ function generateAssign(node, depth) {
2806
+ return `${indent(depth)}let ${node.target} = ${generateExpr(node.value, depth)}`;
2807
+ }
2808
+ function generateAugAssign(node, depth) {
2809
+ const op = node.op.slice(0, -1);
2810
+ const mappedOp = OP_MAP[op] ?? op;
2811
+ return `${indent(depth)}let ${node.target} = (${node.target} ${mappedOp} ${generateExpr(node.value, depth)})`;
2812
+ }
2813
+ function generateIf(node, depth) {
2814
+ const testExpr = generateExpr(node.test, depth);
2815
+ const head = `${indent(depth)}if ${testExpr}:`;
2816
+ const bodyLines = node.body.map(
2817
+ (n) => generatePyStatement(n, depth + 1)
2818
+ );
2819
+ if (!node.orelse || node.orelse.length === 0) {
2820
+ return [head, ...bodyLines].join("\n");
2821
+ }
2822
+ const elseLine = `${indent(depth)}else:`;
2823
+ const elseLines = node.orelse.map(
2824
+ (n) => generatePyStatement(n, depth + 1)
2825
+ );
2826
+ return [head, ...bodyLines, elseLine, ...elseLines].join("\n");
2827
+ }
2828
+ function generateExpr(node, _depth) {
2829
+ switch (node.type) {
2830
+ case "Name":
2831
+ return node.id;
2832
+ case "Constant":
2833
+ return generateConstant(node);
2834
+ case "BinOp": {
2835
+ const binop = node;
2836
+ const mappedOp = OP_MAP[binop.op] ?? binop.op;
2837
+ return `(${generateExpr(binop.left, _depth)} ${mappedOp} ${generateExpr(binop.right, _depth)})`;
2838
+ }
2839
+ case "UnaryOp": {
2840
+ const unary = node;
2841
+ const mappedOp = OP_MAP[unary.op] ?? unary.op;
2842
+ if (mappedOp === "!") {
2843
+ return `(!${generateExpr(unary.operand, _depth)})`;
2844
+ }
2845
+ return `(${mappedOp}${generateExpr(unary.operand, _depth)})`;
2846
+ }
2847
+ case "Compare": {
2848
+ const cmp = node;
2849
+ if (cmp.ops.length === 1) {
2850
+ const mappedOp = OP_MAP[cmp.ops[0]] ?? cmp.ops[0];
2851
+ return `(${generateExpr(cmp.left, _depth)} ${mappedOp} ${generateExpr(cmp.comparators[0], _depth)})`;
2852
+ }
2853
+ const parts = [];
2854
+ let prevExpr = generateExpr(cmp.left, _depth);
2855
+ for (let i = 0; i < cmp.ops.length; i++) {
2856
+ const mappedOp = OP_MAP[cmp.ops[i]] ?? cmp.ops[i];
2857
+ const rightExpr = generateExpr(cmp.comparators[i], _depth);
2858
+ parts.push(`(${prevExpr} ${mappedOp} ${rightExpr})`);
2859
+ prevExpr = rightExpr;
2860
+ }
2861
+ return parts.join(" & ");
2862
+ }
2863
+ case "BoolOp": {
2864
+ const boolop = node;
2865
+ const mappedOp = OP_MAP[boolop.op] ?? boolop.op;
2866
+ const exprs = boolop.values.map((v) => generateExpr(v, _depth));
2867
+ return `(${exprs.join(` ${mappedOp} `)})`;
2868
+ }
2869
+ case "Call": {
2870
+ const call = node;
2871
+ const funcName = generateExpr(call.func, _depth);
2872
+ const mappedName = BUILTIN_MAP[funcName] ?? funcName;
2873
+ const args = call.args.map((a) => generateExpr(a, _depth));
2874
+ const kwargs = call.kwargs.map(
2875
+ (kw) => `${kw.key}=${generateExpr(kw.value, _depth)}`
2876
+ );
2877
+ const allArgs = [...args, ...kwargs].join(", ");
2878
+ return `${mappedName}(${allArgs})`;
2879
+ }
2880
+ case "Attribute": {
2881
+ const attr = node;
2882
+ return `${generateExpr(attr.value, _depth)}.${attr.attr}`;
2883
+ }
2884
+ case "Subscript": {
2885
+ const sub = node;
2886
+ return `List/get(${generateExpr(sub.value, _depth)}, ${generateExpr(sub.slice, _depth)})`;
2887
+ }
2888
+ case "List": {
2889
+ const list = node;
2890
+ const elts = list.elts.map((e) => generateExpr(e, _depth));
2891
+ return `[${elts.join(", ")}]`;
2892
+ }
2893
+ case "Dict": {
2894
+ const dict = node;
2895
+ const entries = dict.keys.map(
2896
+ (k, i) => `${generateExpr(k, _depth)}: ${generateExpr(dict.values[i], _depth)}`
2897
+ );
2898
+ return `{${entries.join(", ")}}`;
2899
+ }
2900
+ case "Lambda": {
2901
+ const lam = node;
2902
+ const params = lam.params.join(", ");
2903
+ return `@${params} ${generateExpr(lam.body, _depth)}`;
2904
+ }
2905
+ default:
2906
+ return `/* unsupported: ${node.type} */`;
2907
+ }
2908
+ }
2909
+ function generateConstant(node) {
2910
+ switch (node.kind) {
2911
+ case "str":
2912
+ return `"${String(node.value).replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
2913
+ case "int":
2914
+ case "float":
2915
+ return String(node.value);
2916
+ case "bool":
2917
+ return node.value ? "True" : "False";
2918
+ case "none":
2919
+ return "*";
2920
+ default:
2921
+ return String(node.value);
2922
+ }
2923
+ }
2924
+ function indent(depth) {
2925
+ return " ".repeat(depth);
2926
+ }
2927
+
2928
+ // ../../lib/py2bend/index.ts
2929
+ function compile(pythonSource) {
2930
+ const warnings = [];
2931
+ const { ast, errors: parseErrors } = parsePython(pythonSource);
2932
+ if (!ast) {
2933
+ return {
2934
+ bend: "",
2935
+ errors: parseErrors,
2936
+ warnings
2937
+ };
2938
+ }
2939
+ const errors = parseErrors.filter((e) => e.severity === "error");
2940
+ const parseWarnings = parseErrors.filter((e) => e.severity === "warning");
2941
+ warnings.push(...parseWarnings.map((w) => w.message));
2942
+ const bendModule = transformModule(ast);
2943
+ const bend = generateBend(bendModule);
2944
+ return {
2945
+ bend,
2946
+ errors,
2947
+ warnings
2948
+ };
2949
+ }
2950
+
2951
+ // ../../lib/hermes/hvm-bridge.ts
2952
+ var HermesHVMBridge = class {
2953
+ metrics = {
2954
+ totalReductions: 0,
2955
+ lastDurationMs: 0,
2956
+ avgDurationMs: 0,
2957
+ lastStrategy: "none"
2958
+ };
2959
+ /**
2960
+ * Create an HVM-compatible manifest from Bend source.
2961
+ * Returns a NodeManifestV0 with a "wasm-hvm" entrypoint pointing
2962
+ * to an .hvm module for the HVM runner to execute.
2963
+ */
2964
+ createManifest(bendSource) {
2965
+ return {
2966
+ id: `hermes-bend-${Date.now()}`,
2967
+ version: "1.0.0",
2968
+ kind: "custom",
2969
+ name: "Hermes Bend Execution",
2970
+ runtimes: ["wasm-hvm"],
2971
+ entrypoints: {
2972
+ "wasm-hvm": {
2973
+ module: "hermes-compiled.hvm",
2974
+ function: "main"
2975
+ }
2976
+ },
2977
+ metadata: {
2978
+ source: "py2bend",
2979
+ bendSource
2980
+ }
2981
+ };
2982
+ }
2983
+ /**
2984
+ * Compute logit bias hints from py2bend compilation structure.
2985
+ * Analyzes the Bend output for structural features (fold count,
2986
+ * bend count, object count) and maps them to control token bias
2987
+ * hints that downstream adapters can translate into provider-specific
2988
+ * logit_bias token IDs.
2989
+ */
2990
+ computeLogitBias(compiled) {
2991
+ const lines = compiled.bend.split("\n");
2992
+ const bias = {};
2993
+ let foldCount = 0;
2994
+ let bendCount = 0;
2995
+ let objectCount = 0;
2996
+ for (const line of lines) {
2997
+ const trimmed = line.trim();
2998
+ if (trimmed.startsWith("fold")) foldCount++;
2999
+ if (trimmed.startsWith("bend")) bendCount++;
3000
+ if (trimmed.startsWith("object")) objectCount++;
3001
+ }
3002
+ if (foldCount > 0) {
3003
+ bias["control:decompose"] = 0.15 * Math.min(foldCount, 5);
3004
+ bias["control:structure"] = 0.1;
3005
+ }
3006
+ if (bendCount > 0) {
3007
+ bias["control:parallel"] = 0.15 * Math.min(bendCount, 5);
3008
+ bias["control:branch"] = 0.1;
3009
+ }
3010
+ if (objectCount > 0) {
3011
+ bias["control:synthesize"] = 0.1 * Math.min(objectCount, 5);
3012
+ }
3013
+ return bias;
3014
+ }
3015
+ /**
3016
+ * Execute Bend source through the HVM runner.
3017
+ * Dynamically imports runInHVM, creates a manifest, executes,
3018
+ * and updates internal reduction metrics.
3019
+ */
3020
+ async executeBend(bendSource) {
3021
+ const manifest = this.createManifest(bendSource);
3022
+ try {
3023
+ const { runInHVM } = await import("./hvm-CBEP3M4F.js");
3024
+ const output = await runInHVM(
3025
+ manifest,
3026
+ { bendSource },
3027
+ { stackId: "hermes", nodeId: "bend-exec" }
3028
+ );
3029
+ const hvmResult = output != null && typeof output === "object" ? output : {};
3030
+ const rawHvm = hvmResult._hvm;
3031
+ const hvm = rawHvm != null && typeof rawHvm === "object" ? rawHvm : {};
3032
+ const durationMs = typeof hvm.durationMs === "number" ? hvm.durationMs : 0;
3033
+ this.metrics.totalReductions++;
3034
+ this.metrics.lastDurationMs = durationMs;
3035
+ this.metrics.lastStrategy = typeof hvm.strategy === "string" ? hvm.strategy : "unknown";
3036
+ this.metrics.avgDurationMs = (this.metrics.avgDurationMs * (this.metrics.totalReductions - 1) + durationMs) / this.metrics.totalReductions;
3037
+ return {
3038
+ result: hvmResult.result,
3039
+ reduced: typeof hvm.reduced === "boolean" ? hvm.reduced : false,
3040
+ strategy: typeof hvm.strategy === "string" ? hvm.strategy : "unknown",
3041
+ durationMs,
3042
+ ...typeof hvmResult.error === "string" ? { error: hvmResult.error } : {}
3043
+ };
3044
+ } catch (error) {
3045
+ console.warn("[HermesHVMBridge] executeBend failed:", error);
3046
+ const message = error instanceof Error ? error.message : String(error);
3047
+ return {
3048
+ result: null,
3049
+ reduced: false,
3050
+ strategy: "error",
3051
+ durationMs: 0,
3052
+ error: message
3053
+ };
3054
+ }
3055
+ }
3056
+ /** Returns a snapshot of current reduction metrics */
3057
+ getMetrics() {
3058
+ return { ...this.metrics };
3059
+ }
3060
+ };
3061
+
3062
+ // ../../lib/terminals-tech/sdk/manifold.ts
3063
+ function now() {
3064
+ return typeof performance !== "undefined" ? performance.now() : Date.now();
3065
+ }
3066
+ function clamp(value, min, max) {
3067
+ return Math.min(max, Math.max(min, value));
3068
+ }
3069
+ function normalizeWhitespace(value) {
3070
+ return value.replace(/\s+/g, " ").trim();
3071
+ }
3072
+ function toPythonProjection(intent, context) {
3073
+ const normalizedIntent = normalizeWhitespace(intent);
3074
+ const normalizedContext = normalizeWhitespace(context).slice(0, 180);
3075
+ const target = normalizeWhitespace(intent.replace(/[^a-zA-Z0-9 ]/g, "")).slice(0, 80);
3076
+ return [
3077
+ "def collapsed_intent(context_state):",
3078
+ ` # Intent: ${normalizedIntent.replace(/#/g, "")}`,
3079
+ ` # Context: ${normalizedContext.replace(/#/g, "")}`,
3080
+ ` target = ${JSON.stringify(target || normalizedIntent || "resolve")}`,
3081
+ " return target"
3082
+ ].join("\n");
3083
+ }
3084
+ function computeNormalizedEntropy(value) {
3085
+ if (!value) return 0;
3086
+ const counts = /* @__PURE__ */ new Map();
3087
+ for (const ch of value) {
3088
+ counts.set(ch, (counts.get(ch) ?? 0) + 1);
3089
+ }
3090
+ let bits = 0;
3091
+ for (const count of counts.values()) {
3092
+ const p = count / value.length;
3093
+ bits -= p * Math.log2(p);
3094
+ }
3095
+ return clamp(bits / 6, 0, 1);
3096
+ }
3097
+ function deriveSteps(bend, maxSteps, durationMs) {
3098
+ const structuralLines = bend.split("\n").map((line) => line.trim()).filter(Boolean).length;
3099
+ const runtimeUnits = durationMs ? Math.ceil(durationMs) : 0;
3100
+ return clamp(Math.max(structuralLines, runtimeUnits, 1), 1, maxSteps);
3101
+ }
3102
+ function buildResultMessage(reduction, steps) {
3103
+ if (reduction.reduced) {
3104
+ return `Manifold annihilated through ${reduction.strategy} in ${reduction.durationMs.toFixed(2)}ms across ${steps} reduction units.`;
3105
+ }
3106
+ if (reduction.errors.length > 0) {
3107
+ return `Manifold annihilation failed after compilation: ${reduction.errors[0]}`;
3108
+ }
3109
+ if (reduction.compiled) {
3110
+ return `Manifold compiled to Bend but did not reduce in HVM. Strategy: ${reduction.strategy}.`;
3111
+ }
3112
+ return reduction.errors[0] ? `Manifold annihilation failed at compile boundary: ${reduction.errors[0]}` : "Manifold annihilation failed before structural reduction.";
3113
+ }
3114
+ async function annihilate(intent, context, options = {}) {
3115
+ const maxSteps = options.maxSteps ?? 2e3;
3116
+ const threshold = options.convergenceThreshold ?? 0.9;
3117
+ const gravity = options.gravity ?? 2.5;
3118
+ const gravityScale = clamp(gravity / 2.5, 0.5, 1.5);
3119
+ const resolvedContext = context ?? globalStateMirror.encodeToManifold();
3120
+ const config = dmt55Engine.getObserverConfiguration(1);
3121
+ const evidence = dmt55Engine.generateMicroLMEvidence(1);
3122
+ emitSignal("mesh_update", "L4", "L3", {
3123
+ type: "manifold_annihilation_start",
3124
+ intentLength: intent.length,
3125
+ contextLength: resolvedContext.length,
3126
+ dimensions: config.totalDimensions,
3127
+ gravity
3128
+ });
3129
+ const pythonSource = intent.includes("def ") || intent.includes("class ") ? intent : toPythonProjection(intent, resolvedContext);
3130
+ const compileStart = now();
3131
+ const compileResult = compile(pythonSource);
3132
+ const compileDurationMs = now() - compileStart;
3133
+ const compileErrors = compileResult.errors.map((error) => error.message);
3134
+ const hvmBridge = new HermesHVMBridge();
3135
+ const logitBias = hvmBridge.computeLogitBias(compileResult);
3136
+ let reduction = {
3137
+ compiled: compileErrors.length === 0,
3138
+ reduced: false,
3139
+ strategy: "compile-only",
3140
+ runtime: "compile-only",
3141
+ durationMs: compileDurationMs,
3142
+ warnings: [...compileResult.warnings],
3143
+ errors: compileErrors,
3144
+ logitBias
3145
+ };
3146
+ if (reduction.compiled && compileResult.bend.trim().length > 0) {
3147
+ const hvmExecution = await hvmBridge.executeBend(compileResult.bend);
3148
+ const runtimeErrors = [...compileErrors, ...hvmExecution.error ? [hvmExecution.error] : []];
3149
+ reduction = {
3150
+ compiled: true,
3151
+ reduced: hvmExecution.reduced,
3152
+ strategy: hvmExecution.strategy,
3153
+ runtime: "wasm-hvm",
3154
+ durationMs: hvmExecution.durationMs || compileDurationMs,
3155
+ warnings: [...compileResult.warnings],
3156
+ errors: hvmExecution.reduced ? [] : runtimeErrors,
3157
+ logitBias
3158
+ };
3159
+ }
3160
+ const steps = deriveSteps(compileResult.bend, maxSteps, reduction.durationMs);
3161
+ const entropySeed = reduction.reduced ? `${compileResult.bend}
3162
+ ${JSON.stringify(reduction.logitBias)}` : reduction.errors.join(" | ") || compileErrors.join(" | ") || intent;
3163
+ const activationEntropy = computeNormalizedEntropy(entropySeed);
3164
+ let R = evidence.confidence;
3165
+ if (!reduction.compiled) {
3166
+ R = clamp(
3167
+ 0.18 + compileResult.warnings.length * 0.01 - compileErrors.length * 0.03 + (gravityScale - 1) * 0.04,
3168
+ 0.05,
3169
+ 0.58
3170
+ );
3171
+ } else if (reduction.reduced) {
3172
+ const speedBonus = clamp((0.08 - reduction.durationMs / 2500) * gravityScale, 0, 0.08);
3173
+ const strategyBonus = reduction.strategy === "wasm" || reduction.strategy === "hvm-core" ? 0.03 : 0;
3174
+ const warningPenalty = Math.min(reduction.warnings.length * 0.01, 0.05);
3175
+ R = clamp(threshold + 0.02 + speedBonus + strategyBonus - warningPenalty, threshold, 0.99);
3176
+ } else {
3177
+ R = clamp(
3178
+ 0.62 - reduction.warnings.length * 0.02 + (gravityScale - 1) * 0.03,
3179
+ 0.3,
3180
+ threshold - 0.01
3181
+ );
3182
+ }
3183
+ const result = buildResultMessage(reduction, steps);
3184
+ const sematon = createSematon({
3185
+ kind: "interaction",
3186
+ payload: {
3187
+ result,
3188
+ steps,
3189
+ intent,
3190
+ contextSnapshot: resolvedContext.substring(0, 140),
3191
+ bendCode: reduction.compiled ? compileResult.bend : void 0,
3192
+ reduction
3193
+ },
3194
+ witness: {
3195
+ R,
3196
+ activationEntropy,
3197
+ converged: reduction.reduced && R >= threshold,
3198
+ step: steps
3199
+ },
3200
+ source: "manifold_annihilation"
3201
+ });
3202
+ const observableEvidence = buildObservableEvidenceFromSematon(sematon, "Reduction Witness");
3203
+ emitSignal("sematon_created", "L4", "L3", {
3204
+ sematonId: sematon.id,
3205
+ source: "manifold_annihilation"
3206
+ });
3207
+ emitSignal("sematon_realized", "L4", "L3", {
3208
+ sematonId: sematon.id,
3209
+ converged: sematon.witness.converged
3210
+ });
3211
+ emitSignal("mesh_update", "L4", "L3", {
3212
+ type: "manifold_annihilation_complete",
3213
+ sematonId: sematon.id,
3214
+ R,
3215
+ durationMs: reduction.durationMs,
3216
+ strategy: reduction.strategy,
3217
+ observableEvidence
3218
+ });
3219
+ return sematon;
3220
+ }
3221
+ var manifold = {
3222
+ annihilate
3223
+ };
3224
+
3225
+ // ../../lib/terminals-tech/sdk/observer.ts
3226
+ var observer_exports = {};
3227
+ __export(observer_exports, {
3228
+ ObserverKernel: () => ObserverKernel,
3229
+ disposeObserverKernel: () => disposeObserverKernel,
3230
+ getObserverKernel: () => getObserverKernel
3231
+ });
3232
+ import { BehaviorSubject as BehaviorSubject2 } from "rxjs";
3233
+ var ObserverKernel = class {
3234
+ id;
3235
+ heartbeatHz;
3236
+ mirror;
3237
+ activeNeurons = /* @__PURE__ */ new Map();
3238
+ coherenceR$ = new BehaviorSubject2(0);
3239
+ pulseTimer = null;
3240
+ constructor(config) {
3241
+ this.id = config.id;
3242
+ this.heartbeatHz = config.heartbeatHz ?? 60;
3243
+ this.mirror = config.stateMirror ?? globalStateMirror;
3244
+ }
3245
+ get coherence() {
3246
+ return this.coherenceR$.value;
3247
+ }
3248
+ get isRunning() {
3249
+ return this.pulseTimer !== null;
3250
+ }
3251
+ /** Starts the continuous heartbeat */
3252
+ start() {
3253
+ if (this.pulseTimer) return;
3254
+ const intervalMs = 1e3 / this.heartbeatHz;
3255
+ this.pulseTimer = setInterval(() => this.pulse(), intervalMs);
3256
+ getSignalBus().emit("mesh_update", "L4", "L3", {
3257
+ type: "observer_started",
3258
+ observerId: this.id
3259
+ });
3260
+ }
3261
+ /** Stops the heartbeat */
3262
+ stop() {
3263
+ if (this.pulseTimer) {
3264
+ clearInterval(this.pulseTimer);
3265
+ this.pulseTimer = null;
3266
+ }
3267
+ }
3268
+ /** The continuous observation loop */
3269
+ pulse() {
3270
+ const state = this.mirror.snapshot;
3271
+ const targetR = state.coherenceR;
3272
+ const currentR = this.coherenceR$.value;
3273
+ const nextR = currentR * 0.95 + targetR * 0.05;
3274
+ this.coherenceR$.next(nextR);
3275
+ }
3276
+ /** Equips a new geometric constraint (Neuron) onto the observer */
3277
+ equipNeuron(neuron) {
3278
+ this.activeNeurons.set(neuron.id, neuron);
3279
+ getSignalBus().emit("mesh_update", "L4", "L3", {
3280
+ type: "neuron_equipped",
3281
+ observerId: this.id,
3282
+ neuronId: neuron.id
3283
+ });
3284
+ }
3285
+ /** Unequips a Neuron */
3286
+ unequipNeuron(neuronId) {
3287
+ this.activeNeurons.delete(neuronId);
3288
+ }
3289
+ /** Replace the active neuron field in one operation. */
3290
+ syncNeurons(neurons) {
3291
+ this.activeNeurons.clear();
3292
+ for (const neuron of neurons) {
3293
+ this.activeNeurons.set(neuron.id, neuron);
3294
+ }
3295
+ getSignalBus().emit("mesh_update", "L4", "L3", {
3296
+ type: "observer_field_synced",
3297
+ observerId: this.id,
3298
+ neuronCount: neurons.length
3299
+ });
3300
+ }
3301
+ /**
3302
+ * The core execution path:
3303
+ * Flattens the active Neurons + StateMirror context, then drops them into the Annihilator.
3304
+ */
3305
+ async resolve(intent) {
3306
+ this.pulse();
3307
+ const contextManifold = this.mirror.encodeToManifold();
3308
+ let injectedIntent = intent;
3309
+ if (this.activeNeurons.size > 0) {
3310
+ const neuronIds = Array.from(this.activeNeurons.keys()).join(", ");
3311
+ injectedIntent = `
3312
+ @apply_neurons(${neuronIds})
3313
+ ${intent}
3314
+ `.trim();
3315
+ }
3316
+ return await annihilate(injectedIntent, contextManifold, {
3317
+ convergenceThreshold: 0.9,
3318
+ gravity: 2.5
3319
+ });
3320
+ }
3321
+ };
3322
+ var OBSERVER_IDLE_TTL_MS = 5 * 60 * 1e3;
3323
+ var observerRegistry = /* @__PURE__ */ new Map();
3324
+ function pruneObserverRegistry(now2) {
3325
+ for (const [id, entry] of observerRegistry.entries()) {
3326
+ if (entry.kernel.isRunning) continue;
3327
+ if (now2 - entry.lastUsedAt > OBSERVER_IDLE_TTL_MS) {
3328
+ observerRegistry.delete(id);
3329
+ }
3330
+ }
3331
+ }
3332
+ function disposeObserverKernel(id) {
3333
+ const entry = observerRegistry.get(id);
3334
+ if (!entry) return;
3335
+ entry.kernel.stop();
3336
+ observerRegistry.delete(id);
3337
+ }
3338
+ function getObserverKernel(id, config = {}) {
3339
+ const now2 = Date.now();
3340
+ pruneObserverRegistry(now2);
3341
+ const existing = observerRegistry.get(id);
3342
+ if (existing) {
3343
+ existing.lastUsedAt = now2;
3344
+ return existing.kernel;
3345
+ }
3346
+ const kernel = new ObserverKernel({ id, ...config });
3347
+ observerRegistry.set(id, { kernel, lastUsedAt: now2 });
3348
+ return kernel;
3349
+ }
3350
+
1272
3351
  // ../../lib/terminals-tech/axon/protocol.ts
1273
3352
  var AXON_CONSTANTS = {
1274
3353
  HEADER_SIZE: 16,
@@ -1817,13 +3896,15 @@ function createAxonBus() {
1817
3896
  }
1818
3897
 
1819
3898
  // src/index.ts
1820
- var SDK_VERSION = "1.0.0-rc.1";
3899
+ var SDK_VERSION = "1.0.0";
1821
3900
  export {
1822
3901
  brain_exports as Brain,
1823
3902
  core_exports as Core,
1824
3903
  InMemoryAxonBus,
1825
3904
  L0_exports as L0,
3905
+ manifold_exports as Manifold,
1826
3906
  mesh_exports as Mesh,
3907
+ observer_exports as Observer,
1827
3908
  protocol_exports as Protocol,
1828
3909
  ProtocolBridge,
1829
3910
  SDK_VERSION,