k-l-lambda commited on
Commit
4b26793
·
1 Parent(s): 66d6d4a

fix onnx model loading

Browse files
trigo-web/ONNXRUNTIME_NODE_FIX.md ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # onnxruntime-node 安装问题修复方案
2
+
3
+ ## 问题描述
4
+
5
+ `[email protected]` 的 postinstall 脚本在下载二进制文件时无法正确处理 HTTP 302 重定向,导致安装失败:
6
+
7
+ ```
8
+ Error: Failed to download build list. HTTP status code = 302
9
+ ```
10
+
11
+ ## 根本原因
12
+
13
+ Node.js 原生的 `https.get()` 不会自动跟随 HTTP 重定向。`onnxruntime-node` 的 `install-utils.js` 中的 `downloadFile()` 和 `downloadJson()` 函数缺少重定向处理逻辑。
14
+
15
+ ## 解决方案
16
+
17
+ ### 方案 A: 应用 Patch(推荐)
18
+
19
+ 已创建 patch 文件来修复重定向问题:
20
+
21
+ ```bash
22
+ cd ~/work/trigoRL/third_party/trigo/trigo-web/node_modules/onnxruntime-node/script
23
+ patch -p0 < ~/work/trigoRL/third_party/trigo/trigo-web/onnxruntime-node-redirect-fix.patch
24
+ ```
25
+
26
+ **Patch 修改内容:**
27
+ 1. 为 `downloadFile()` 和 `downloadJson()` 添加 `maxRedirects` 参数(默认值 5)
28
+ 2. 检测 HTTP 状态码 300-399 并提取 `Location` 头
29
+ 3. 递归调用自身跟随重定向,直到获得 200 状态码或达到最大重定向次数
30
+
31
+ ### 方案 B: 跳过安装(仅用于不需要 ONNX 推理的场景)
32
+
33
+ ```bash
34
+ yarn install --ignore-scripts
35
+ ```
36
+
37
+ **限制:** onnxruntime-node 的 CUDA 和 TensorRT 二进制文件不会被下载,无法在 Node.js 中进行 GPU 推理。
38
+
39
+ ## 修复验证
40
+
41
+ ### 1. 测试安装脚本
42
+
43
+ ```bash
44
+ cd ~/work/trigoRL/third_party/trigo/trigo-web/node_modules/onnxruntime-node
45
+ node ./script/install
46
+ ```
47
+
48
+ **预期输出:**
49
+ ```
50
+ Following redirect to https://nuget.azure.cn/v3/index.json
51
+ Following redirect to https://nuget.azure.cn/v3-flatcontainer/...
52
+ Downloading https://api.nuget.org/v3-flatcontainer/...
53
+ Extracting runtimes/linux-x64/native/libonnxruntime_providers_cuda.so to ...
54
+ Extracting runtimes/linux-x64/native/libonnxruntime_providers_shared.so to ...
55
+ Extracting runtimes/linux-x64/native/libonnxruntime_providers_tensorrt.so to ...
56
+ ```
57
+
58
+ ### 2. 验证模块加载
59
+
60
+ ```bash
61
+ cd ~/work/trigoRL/third_party/trigo/trigo-web
62
+ node -e "const ort = require('onnxruntime-node'); console.log('Supported backends:', ort.listSupportedBackends());"
63
+ ```
64
+
65
+ **预期输出:**
66
+ ```javascript
67
+ Supported backends: [
68
+ { name: 'cpu', bundled: true },
69
+ { name: 'webgpu', bundled: true },
70
+ { name: 'cuda', bundled: false },
71
+ { name: 'tensorrt', bundled: false }
72
+ ]
73
+ ```
74
+
75
+ ### 3. 检查二进制文件
76
+
77
+ ```bash
78
+ ls -lh ~/work/trigoRL/third_party/trigo/trigo-web/node_modules/onnxruntime-node/bin/napi-v6/linux/x64/*.so
79
+ ```
80
+
81
+ **预期输出:**
82
+ ```
83
+ -rw-rw-rw- 1 camus camus 352M libonnxruntime_providers_cuda.so
84
+ -rw-rw-rw- 1 camus camus 15K libonnxruntime_providers_shared.so
85
+ -rw-rw-rw- 1 camus camus 811K libonnxruntime_providers_tensorrt.so
86
+ ```
87
+
88
+ ## 技术细节
89
+
90
+ ### 修改的函数
91
+
92
+ #### downloadFile()
93
+ 添加递归重定向处理:
94
+ ```javascript
95
+ async function downloadFile(url, dest, maxRedirects = 5) {
96
+ // 检查重定向次数
97
+ if (maxRedirects < 0) {
98
+ reject(new Error('Too many redirects'));
99
+ return;
100
+ }
101
+
102
+ // 检测 300-399 状态码
103
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
104
+ const redirectUrl = new URL(res.headers.location, url).toString();
105
+ downloadFile(redirectUrl, dest, maxRedirects - 1).then(resolve).catch(reject);
106
+ return;
107
+ }
108
+ // ...
109
+ }
110
+ ```
111
+
112
+ #### downloadJson()
113
+ 类似的重定向处理逻辑应用于 JSON 下载。
114
+
115
+ ### 为什么需要这个修复
116
+
117
+ 1. **NuGet CDN 重定向:** onnxruntime 使用 NuGet 包托管,某些 CDN 节点会返回 302 重定向
118
+ 2. **代理环境:** 在使用代理的网络环境中,重定向更为常见
119
+ 3. **地理位置优化:** NuGet 会根据地理位置重定向到最近的镜像服务器
120
+
121
+ ## 未来维护
122
+
123
+ 当 `onnxruntime-node` 更新到新版本时:
124
+
125
+ 1. **检查是否已修复:** 新版本可能已经包含重定向处理
126
+ 2. **重新应用 patch:** 如果未修复,需要在新版本的 `install-utils.js` 上重新应用 patch
127
+ 3. **提交上游 PR:** 可以向 onnxruntime 项目提交 Pull Request 来永久修复这个问题
128
+
129
+ ## 相关文件
130
+
131
+ - **Patch 文件:** `onnxruntime-node-redirect-fix.patch`
132
+ - **原始脚本:** `node_modules/onnxruntime-node/script/install-utils.js`
133
+ - **备份文件:** `node_modules/onnxruntime-node/script/install-utils.js.backup`
134
+
135
+ ## 环境信息
136
+
137
+ - **修复日期:** 2025-11-21
138
+ - **onnxruntime-node 版本:** 1.23.2
139
+ - **Node.js 版本:** v24.11.1
140
+ - **操作系统:** Ubuntu 22.04 (LXD container)
141
+ - **GPU:** 8x NVIDIA H20
142
+
143
+ ## 状态
144
+
145
+ ✅ **已彻底解决** - onnxruntime-node 的 CUDA 和 TensorRT 后端已成功安装并可用于 Node.js ONNX 模型推理。
trigo-web/app/package-lock.json CHANGED
@@ -8,6 +8,8 @@
8
  "name": "trigo-app",
9
  "version": "0.0.0",
10
  "dependencies": {
 
 
11
  "pinia": "^2.1.6",
12
  "socket.io-client": "^4.5.2",
13
  "three": "^0.156.1",
@@ -740,6 +742,60 @@
740
  "url": "https://opencollective.com/parcel"
741
  }
742
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
743
  "node_modules/@rollup/rollup-android-arm-eabi": {
744
  "version": "4.52.5",
745
  "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz",
@@ -1041,9 +1097,6 @@
1041
  "version": "24.10.1",
1042
  "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz",
1043
  "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
1044
- "dev": true,
1045
- "optional": true,
1046
- "peer": true,
1047
  "dependencies": {
1048
  "undici-types": "~7.16.0"
1049
  }
@@ -1436,6 +1489,11 @@
1436
  "node": ">=8"
1437
  }
1438
  },
 
 
 
 
 
1439
  "node_modules/fsevents": {
1440
  "version": "2.3.3",
1441
  "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -1450,6 +1508,11 @@
1450
  "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1451
  }
1452
  },
 
 
 
 
 
1453
  "node_modules/has-flag": {
1454
  "version": "4.0.0",
1455
  "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -1507,6 +1570,11 @@
1507
  "node": ">=0.12.0"
1508
  }
1509
  },
 
 
 
 
 
1510
  "node_modules/magic-string": {
1511
  "version": "0.30.19",
1512
  "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
@@ -1585,6 +1653,24 @@
1585
  "dev": true,
1586
  "optional": true
1587
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1588
  "node_modules/path-browserify": {
1589
  "version": "1.0.1",
1590
  "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
@@ -1630,6 +1716,11 @@
1630
  }
1631
  }
1632
  },
 
 
 
 
 
1633
  "node_modules/postcss": {
1634
  "version": "8.5.6",
1635
  "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
@@ -1657,6 +1748,29 @@
1657
  "node": "^10 || ^12 || >=14"
1658
  }
1659
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1660
  "node_modules/readdirp": {
1661
  "version": "4.1.2",
1662
  "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
@@ -2182,10 +2296,7 @@
2182
  "node_modules/undici-types": {
2183
  "version": "7.16.0",
2184
  "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
2185
- "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
2186
- "dev": true,
2187
- "optional": true,
2188
- "peer": true
2189
  },
2190
  "node_modules/varint": {
2191
  "version": "6.0.0",
 
8
  "name": "trigo-app",
9
  "version": "0.0.0",
10
  "dependencies": {
11
+ "onnxruntime-common": "^1.23.2",
12
+ "onnxruntime-web": "^1.23.2",
13
  "pinia": "^2.1.6",
14
  "socket.io-client": "^4.5.2",
15
  "three": "^0.156.1",
 
742
  "url": "https://opencollective.com/parcel"
743
  }
744
  },
745
+ "node_modules/@protobufjs/aspromise": {
746
+ "version": "1.1.2",
747
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
748
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="
749
+ },
750
+ "node_modules/@protobufjs/base64": {
751
+ "version": "1.1.2",
752
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
753
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
754
+ },
755
+ "node_modules/@protobufjs/codegen": {
756
+ "version": "2.0.4",
757
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
758
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
759
+ },
760
+ "node_modules/@protobufjs/eventemitter": {
761
+ "version": "1.1.0",
762
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
763
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="
764
+ },
765
+ "node_modules/@protobufjs/fetch": {
766
+ "version": "1.1.0",
767
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
768
+ "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
769
+ "dependencies": {
770
+ "@protobufjs/aspromise": "^1.1.1",
771
+ "@protobufjs/inquire": "^1.1.0"
772
+ }
773
+ },
774
+ "node_modules/@protobufjs/float": {
775
+ "version": "1.0.2",
776
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
777
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="
778
+ },
779
+ "node_modules/@protobufjs/inquire": {
780
+ "version": "1.1.0",
781
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
782
+ "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="
783
+ },
784
+ "node_modules/@protobufjs/path": {
785
+ "version": "1.1.2",
786
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
787
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="
788
+ },
789
+ "node_modules/@protobufjs/pool": {
790
+ "version": "1.1.0",
791
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
792
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="
793
+ },
794
+ "node_modules/@protobufjs/utf8": {
795
+ "version": "1.1.0",
796
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
797
+ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
798
+ },
799
  "node_modules/@rollup/rollup-android-arm-eabi": {
800
  "version": "4.52.5",
801
  "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz",
 
1097
  "version": "24.10.1",
1098
  "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz",
1099
  "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
 
 
 
1100
  "dependencies": {
1101
  "undici-types": "~7.16.0"
1102
  }
 
1489
  "node": ">=8"
1490
  }
1491
  },
1492
+ "node_modules/flatbuffers": {
1493
+ "version": "25.9.23",
1494
+ "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz",
1495
+ "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ=="
1496
+ },
1497
  "node_modules/fsevents": {
1498
  "version": "2.3.3",
1499
  "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
 
1508
  "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1509
  }
1510
  },
1511
+ "node_modules/guid-typescript": {
1512
+ "version": "1.0.9",
1513
+ "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz",
1514
+ "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ=="
1515
+ },
1516
  "node_modules/has-flag": {
1517
  "version": "4.0.0",
1518
  "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
 
1570
  "node": ">=0.12.0"
1571
  }
1572
  },
1573
+ "node_modules/long": {
1574
+ "version": "5.3.2",
1575
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
1576
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="
1577
+ },
1578
  "node_modules/magic-string": {
1579
  "version": "0.30.19",
1580
  "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
 
1653
  "dev": true,
1654
  "optional": true
1655
  },
1656
+ "node_modules/onnxruntime-common": {
1657
+ "version": "1.23.2",
1658
+ "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.23.2.tgz",
1659
+ "integrity": "sha512-5LFsC9Dukzp2WV6kNHYLNzp8sT6V02IubLCbzw2Xd6X5GOlr65gAX6xiJwyi2URJol/s71gaQLC5F2C25AAR2w=="
1660
+ },
1661
+ "node_modules/onnxruntime-web": {
1662
+ "version": "1.23.2",
1663
+ "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.23.2.tgz",
1664
+ "integrity": "sha512-T09JUtMn+CZLk3mFwqiH0lgQf+4S7+oYHHtk6uhaYAAJI95bTcKi5bOOZYwORXfS/RLZCjDDEXGWIuOCAFlEjg==",
1665
+ "dependencies": {
1666
+ "flatbuffers": "^25.1.24",
1667
+ "guid-typescript": "^1.0.9",
1668
+ "long": "^5.2.3",
1669
+ "onnxruntime-common": "1.23.2",
1670
+ "platform": "^1.3.6",
1671
+ "protobufjs": "^7.2.4"
1672
+ }
1673
+ },
1674
  "node_modules/path-browserify": {
1675
  "version": "1.0.1",
1676
  "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
 
1716
  }
1717
  }
1718
  },
1719
+ "node_modules/platform": {
1720
+ "version": "1.3.6",
1721
+ "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz",
1722
+ "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg=="
1723
+ },
1724
  "node_modules/postcss": {
1725
  "version": "8.5.6",
1726
  "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
 
1748
  "node": "^10 || ^12 || >=14"
1749
  }
1750
  },
1751
+ "node_modules/protobufjs": {
1752
+ "version": "7.5.4",
1753
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz",
1754
+ "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==",
1755
+ "hasInstallScript": true,
1756
+ "dependencies": {
1757
+ "@protobufjs/aspromise": "^1.1.2",
1758
+ "@protobufjs/base64": "^1.1.2",
1759
+ "@protobufjs/codegen": "^2.0.4",
1760
+ "@protobufjs/eventemitter": "^1.1.0",
1761
+ "@protobufjs/fetch": "^1.1.0",
1762
+ "@protobufjs/float": "^1.0.2",
1763
+ "@protobufjs/inquire": "^1.1.0",
1764
+ "@protobufjs/path": "^1.1.2",
1765
+ "@protobufjs/pool": "^1.1.0",
1766
+ "@protobufjs/utf8": "^1.1.0",
1767
+ "@types/node": ">=13.7.0",
1768
+ "long": "^5.0.0"
1769
+ },
1770
+ "engines": {
1771
+ "node": ">=12.0.0"
1772
+ }
1773
+ },
1774
  "node_modules/readdirp": {
1775
  "version": "4.1.2",
1776
  "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
 
2296
  "node_modules/undici-types": {
2297
  "version": "7.16.0",
2298
  "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
2299
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="
 
 
 
2300
  },
2301
  "node_modules/varint": {
2302
  "version": "6.0.0",
trigo-web/app/src/views/TrigoView.vue CHANGED
@@ -917,7 +917,7 @@
917
  if (entry.target === viewportCanvas.value && viewport) {
918
  // Trigger viewport resize
919
  const rect = viewportCanvas.value.getBoundingClientRect();
920
- console.log(`Canvas resized: ${rect.width}x${rect.height}`);
921
 
922
  // Call the viewport's resize handler directly
923
  // The onWindowResize method updates camera aspect and renderer size
@@ -951,6 +951,27 @@
951
  window.addEventListener("keydown", handleKeyPress);
952
  });
953
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
954
  onUnmounted(() => {
955
  console.log("TrigoDemo component unmounted");
956
 
 
917
  if (entry.target === viewportCanvas.value && viewport) {
918
  // Trigger viewport resize
919
  const rect = viewportCanvas.value.getBoundingClientRect();
920
+ //console.log(`Canvas resized: ${rect.width}x${rect.height}`);
921
 
922
  // Call the viewport's resize handler directly
923
  // The onWindowResize method updates camera aspect and renderer size
 
951
  window.addEventListener("keydown", handleKeyPress);
952
  });
953
 
954
+ // Watch for game mode changes and initialize AI when switching to vs-ai
955
+ watch(gameMode, (newMode, oldMode) => {
956
+ console.log(`[TrigoView] Game mode changed: ${oldMode} -> ${newMode}`);
957
+
958
+ if (newMode === "vs-ai" && !aiReady.value) {
959
+ console.log("[TrigoView] Switching to VS AI mode, initializing AI agent...");
960
+ aiAgent.initialize()
961
+ .then(() => {
962
+ // After AI is ready, if it's AI's turn, generate move
963
+ if (gameStarted.value && currentPlayer.value === aiPlayerColor.value) {
964
+ setTimeout(() => {
965
+ generateAIMove();
966
+ }, 100);
967
+ }
968
+ })
969
+ .catch((err) => {
970
+ console.error("[TrigoView] Failed to initialize AI agent:", err);
971
+ });
972
+ }
973
+ });
974
+
975
  onUnmounted(() => {
976
  console.log("TrigoDemo component unmounted");
977
 
trigo-web/onnxruntime-node-redirect-fix.patch ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ --- install-utils.js.backup 2025-11-21 07:38:06.154213581 +0000
2
+ +++ install-utils.js 2025-11-21 07:38:44.799438104 +0000
3
+ @@ -10,11 +10,27 @@
4
+ const os = require('os');
5
+ const AdmZip = require('adm-zip'); // Use adm-zip instead of spawn
6
+
7
+ -async function downloadFile(url, dest) {
8
+ +async function downloadFile(url, dest, maxRedirects = 5) {
9
+ return new Promise((resolve, reject) => {
10
+ + if (maxRedirects < 0) {
11
+ + reject(new Error('Too many redirects'));
12
+ + return;
13
+ + }
14
+ +
15
+ const file = fs.createWriteStream(dest);
16
+ https
17
+ .get(url, (res) => {
18
+ + // Handle redirects (301, 302, 303, 307, 308)
19
+ + if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
20
+ + file.close();
21
+ + fs.unlinkSync(dest);
22
+ + // Follow redirect
23
+ + const redirectUrl = new URL(res.headers.location, url).toString();
24
+ + console.log(`Following redirect to ${redirectUrl}`);
25
+ + downloadFile(redirectUrl, dest, maxRedirects - 1).then(resolve).catch(reject);
26
+ + return;
27
+ + }
28
+ +
29
+ if (res.statusCode !== 200) {
30
+ file.close();
31
+ fs.unlinkSync(dest);
32
+ @@ -39,8 +55,13 @@
33
+ });
34
+ }
35
+
36
+ -async function downloadJson(url) {
37
+ +async function downloadJson(url, maxRedirects = 5) {
38
+ return new Promise((resolve, reject) => {
39
+ + if (maxRedirects < 0) {
40
+ + reject(new Error('Too many redirects'));
41
+ + return;
42
+ + }
43
+ +
44
+ https
45
+ .get(url, (res) => {
46
+ const { statusCode } = res;
47
+ @@ -50,6 +71,16 @@
48
+ reject(new Error('No response statud code from server.'));
49
+ return;
50
+ }
51
+ +
52
+ + // Handle redirects (301, 302, 303, 307, 308)
53
+ + if (statusCode >= 300 && statusCode < 400 && res.headers.location) {
54
+ + // Follow redirect
55
+ + const redirectUrl = new URL(res.headers.location, url).toString();
56
+ + console.log(`Following redirect to ${redirectUrl}`);
57
+ + downloadJson(redirectUrl, maxRedirects - 1).then(resolve).catch(reject);
58
+ + return;
59
+ + }
60
+ +
61
+ if (statusCode >= 400 && statusCode < 500) {
62
+ resolve(null);
63
+ return;
trigo-web/package-lock.json DELETED
The diff for this file is too large to render. See raw diff
 
trigo-web/yarn.lock CHANGED
The diff for this file is too large to render. See raw diff