mirror of
https://github.com/affaan-m/ECC.git
synced 2026-08-17 21:15:40 +02:00
feat: add Itô compute sponsor routing and Phase 2 plan (#2546)
* feat: add Ito compute sponsor routing * fix: harden Ito integration CI and framing
This commit is contained in:
@@ -15,3 +15,5 @@ export ANTHROPIC_BASE_URL=https://your-gateway.example.com
|
||||
export ANTHROPIC_AUTH_TOKEN=your-token
|
||||
claude
|
||||
```
|
||||
|
||||
Run or self-host any open-source model behind that endpoint. Itô is ECC's preferred compute sponsor: [open the Itô dashboard to sign in and rent or manage GPUs](https://compute.itomarkets.com). Any GPU provider works. ECC only provides this link; it does not change Claude Code transport settings or provision compute or serving. Managed inference through Itô is not live yet.
|
||||
|
||||
@@ -20,3 +20,7 @@ bash ./install.sh --target kimi --profile minimal
|
||||
- The `kimi` target installs into the project-level `./.kimi/` directory.
|
||||
- Kimi Code CLI's own config (`~/.kimi-code/config.toml`, plugins) is **not** touched by ECC install.
|
||||
- Use `npx ecc doctor --target kimi` to check install health.
|
||||
|
||||
## Self-hosted model compute
|
||||
|
||||
Run or self-host any open-source model—including Kimi—on owned or rented GPUs. Itô is ECC's preferred compute sponsor: [open the Itô dashboard to sign in and rent or manage GPUs](https://compute.itomarkets.com). Any GPU provider works. ECC only provides this link; it does not provision compute or serving. Managed inference through Itô is not live yet.
|
||||
|
||||
@@ -106,9 +106,17 @@ ECC v2.0.0 adds the public Hermes operator story on top of that reusable layer:
|
||||
<strong>Atlas Cloud</strong>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" width="220">
|
||||
<a href="https://compute.itomarkets.com">
|
||||
<img src="assets/images/sponsors/ito.svg" width="96" alt="Itô Markets logo" /><br />
|
||||
<strong>Itô</strong>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<sub><strong>Run or self-host any open-source model.</strong> Itô is ECC's preferred compute sponsor: <a href="https://compute.itomarkets.com">open the Itô dashboard to sign in and rent or manage GPUs</a>. Any GPU provider works. ECC only provides this link; it does not provision compute or serving. Managed inference through Itô is not live yet.</sub>
|
||||
|
||||
<sub><strong>Community sponsors:</strong> <a href="https://github.com/mikejmorgan-ai">Mike Morgan</a> · <a href="https://github.com/jasonwu513">@jasonwu513</a> · <a href="https://github.com/1anter">@1anter</a> · <a href="https://github.com/massimotodaro">@massimotodaro</a> · <a href="https://github.com/meadmccabe">@meadmccabe</a></sub>
|
||||
|
||||
<sub><a href="https://github.com/sponsors/affaan-m"><strong>Become a Sponsor</strong></a> · <a href="SPONSORS.md">Sponsor Tiers</a> · <a href="SPONSORING.md">Sponsorship Program</a></sub>
|
||||
@@ -1188,6 +1196,8 @@ claude
|
||||
|
||||
If your gateway remaps model names, configure that in Claude Code rather than in ECC. ECC's hooks, skills, commands, and rules are model-provider agnostic once the `claude` CLI is already working.
|
||||
|
||||
Run or self-host any open-source model behind that gateway using separate compute and serving setup. If you need GPU capacity, [Itô](https://compute.itomarkets.com) is ECC's preferred compute sponsor; any GPU provider works. ECC only links to the Itô dashboard for sign-in and GPU rental or management—it does not provision compute or serving. Managed inference through Itô is not live yet.
|
||||
|
||||
Official references:
|
||||
- [Claude Code LLM gateway docs](https://docs.anthropic.com/en/docs/claude-code/llm-gateway)
|
||||
- [Claude Code model configuration docs](https://docs.anthropic.com/en/docs/claude-code/model-config)
|
||||
|
||||
@@ -13,9 +13,12 @@ Thank you to everyone funding ECC's open-source work. Your sponsorship is what l
|
||||
| [**CodeRabbit**](https://www.coderabbit.ai) | <img src="assets/images/sponsors/coderabbit.png" width="60" alt="CodeRabbit logo" /> | 2026 |
|
||||
| [**Greptile**](https://www.greptile.com/go/ecc) | <img src="assets/images/sponsors/greptile.png" width="60" alt="Greptile logo" /> | 2026 |
|
||||
| [**Atlas Cloud**](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=ECC) | <img src="assets/images/sponsors/atlascloud.png" width="60" alt="Atlas Cloud logo" /> | 2026 |
|
||||
| [**Itô**](https://compute.itomarkets.com) | <img src="assets/images/sponsors/ito.svg" width="60" alt="Itô Markets logo" /> | 2026 |
|
||||
|
||||
*[Become a Business sponsor](https://github.com/sponsors/affaan-m) to get README sponsor placement + SPONSORS.md listing. Current Business tier is $500/mo. No seats, SLA, custom development, or preferential technical placement is bundled unless separately agreed.*
|
||||
|
||||
Run or self-host any open-source model. Itô is ECC's preferred compute sponsor, while ECC remains provider-agnostic and any GPU provider works. ECC only links to the [Itô dashboard](https://compute.itomarkets.com) for sign-in and GPU rental or management; it does not provision compute or serving. Managed inference through Itô is not live yet.
|
||||
|
||||
## Team Sponsors — $200/mo
|
||||
|
||||
| Sponsor | Since |
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
width="1400"
|
||||
height="799.43805"
|
||||
viewBox="0 0 1400 799.43805"
|
||||
sodipodi:docname="ito_lockup_light.svg"
|
||||
xml:space="preserve"
|
||||
inkscape:export-filename="ito_lockup_light.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs1" /><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:deskcolor="#3e5574"
|
||||
inkscape:export-bgcolor="#ffffff00"
|
||||
showgrid="false"><inkscape:grid
|
||||
id="grid2"
|
||||
units="px"
|
||||
originx="-188.88699"
|
||||
originy="-1776.873"
|
||||
spacingx="1"
|
||||
spacingy="1"
|
||||
empcolor="#0099e5"
|
||||
empopacity="0.30196078"
|
||||
color="#0099e5"
|
||||
opacity="0.14901961"
|
||||
empspacing="5"
|
||||
enabled="true"
|
||||
visible="false" /><inkscape:page
|
||||
x="0"
|
||||
y="0"
|
||||
width="3984.4521"
|
||||
height="799.43805"
|
||||
id="page1"
|
||||
margin="0"
|
||||
bleed="0" /></sodipodi:namedview><rect width="1400" height="799.43805" rx="80" fill="#0F172A" /><g
|
||||
id="g2"
|
||||
transform="matrix(1.2424941,0,0,1.2424941,732.18761,-28.312159)"
|
||||
style="display:inline;mix-blend-mode:normal;fill:#000000"><path
|
||||
fill="#f8f8f8"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m -407.82151,138.90806 c -0.73456,19.04603 -1.75003,36.04295 -1.77581,53.04148 -0.14803,97.42416 -0.12019,194.84831 0.007,292.27269 0.0201,15.45653 0.57632,30.92594 1.41025,46.36123 0.41463,7.67407 2.0485,15.28015 3.08296,22.92311 3.11296,23.00145 17.4907,35.52667 38.97622,40.39315 14.20138,3.21711 28.753,4.88804 43.86346,7.36875 2.21332,8.15229 2.09141,16.33417 0.19604,24.4426 -17.77154,2.32172 -238.81413,2.85947 -265.12221,0.6907 -3.01226,-8.05514 -1.79819,-16.31154 -1.14387,-25.76714 5.13187,-0.6408 9.55163,-1.05671 13.92387,-1.76586 10.66923,-1.72989 21.47836,-2.94384 31.93871,-5.54244 21.60953,-5.36825 35.18697,-18.4896 37.31021,-41.61938 1.12935,-12.30231 3.30449,-24.59672 3.33523,-36.89868 0.2921,-116.75264 0.39515,-233.5068 0.0452,-350.25864 -0.0437,-14.58642 -2.40654,-29.26741 -4.80996,-43.71922 -3.06751,-18.44469 -14.16794,-30.673543 -32.27876,-35.631463 -9.64428,-2.64002 -19.60034,-4.22358 -29.48381,-5.87653 -5.98535,-1.00112 -12.10103,-1.22288 -19.01466,-1.87575 -2.7837,-9.000821 -2.01117,-17.172152 -1.02036,-24.95995 1.26458,-0.83889 1.85493,-1.290771 2.50012,-1.642039 0.67514,-0.367516 1.40233,-0.911071 2.10791,-0.912812 82.72572,-0.189502 165.45152,-0.340361 248.1773,-0.466967 3.0862,0 6.19302,0.08354 9.25053,0.454666 1.46587,0.17813 2.83903,1.120069 4.882,1.980545 0,7.984144 0,16.21477 0,25.884597 -6.8273,0.57152 -12.86896,0.68142 -18.76796,1.65562 -11.40111,1.88248 -23.06675,3.17545 -33.99317,6.67736 -15.65683,5.01767 -26.3228,15.797003 -29.74679,32.579583 -1.23483,6.0521 -2.44932,12.10816 -3.84916,20.21079 z"
|
||||
id="path3"
|
||||
style="fill:#ffffff;stroke-width:1.16044" /><path
|
||||
fill="#f8f8f8"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m -175.50826,592.31193 c -16.09124,-26.94941 -19.46077,-55.27164 -19.59272,-84.09461 -0.32921,-71.92819 -0.17374,-143.85895 -0.23487,-215.78854 -0.007,-8.42291 -0.15278,-16.8456 -0.24748,-26.62832 -19.08924,0 -36.70129,0 -55.12778,0 -3.95705,-11.29202 -3.70922,-19.50791 6.46272,-26.67115 45.69063,-32.17644 80.91103,-73.84666 108.45576,-122.14909 5.23615,-9.18208 11.71252,-11.28784 22.61412,-6.73562 0.12268,17.80749 0.2994,36.24893 0.3628,54.6906 0.0635,18.46826 0.0139,36.93697 0.0139,55.97176 11.35646,4.41667 22.198715,1.71259 32.708818,2.21507 10.032,0.47973 20.10448,0.11651 30.159201,0.11906 10.815969,0 21.632049,4.7e-4 33.59349,4.7e-4 4.188069,14.29572 -2.530351,27.01289 -3.22906,41.59735 -31.374611,1.3323 -61.373771,-0.21167 -91.942879,0.96317 -0.47725,6.38399 -1.21691,11.70768 -1.22136,17.03196 -0.058,68.83617 -0.25024,137.67374 0.20972,206.50667 0.0923,13.80787 1.37548,27.9249 4.52007,41.3338 8.165127,34.81635 38.159478,47.50487 69.741938,30.0216 9.287071,-5.14104 17.68211,-11.89289 28.9041102,-19.55849 4.7637788,6.21839 9.39363761,12.26203 14.789386,19.30516 -2.2162292,3.40013 -3.9757088,7.85034 -7.166838,10.69426 -14.3969972,12.83183 -28.5569272,26.07735 -44.0303682,37.51244 -16.46956,12.1714 -35.74838,17.93549 -56.435928,18.54287 -29.73341,0.8723 -54.73711,-8.26032 -73.30672,-34.88042 z"
|
||||
id="path4"
|
||||
style="fill:#ffffff;stroke-width:1.16044" /><path
|
||||
fill="#f4f4f4"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m 1128.584,356.44963 c -7.4315,16.25225 -12.2094,31.78213 -20.8952,45.92572 -9.5181,0 -18.5882,0 -28.343,0 -14.907,-26.29075 -23.2607,-55.28477 -37.2044,-81.41502 -6.8826,0.67457 -4.8861,5.55462 -4.898,8.58096 -0.1555,40.17417 -0.071,80.34973 -0.048,120.52469 0,8.47736 5e-4,16.95469 5e-4,26.20117 -11.4205,5.1603 -22.8457,2.25464 -33.6308,2.61924 -0.8862,-1.08002 -1.4333,-1.64039 -1.8498,-2.28515 -0.3986,-0.61793 -0.9426,-1.32314 -0.944,-1.99063 -0.1297,-66.43868 -0.2142,-132.87715 -0.2995,-199.31594 -0.012,-5.35572 -8e-4,-10.71144 -8e-4,-16.57148 7.9953,-4.28881 15.7539,-2.24165 23.1179,-2.545 7.6717,-0.31622 15.367,-0.0708 23.9634,-0.0708 2.5457,4.93308 5.2218,9.46755 7.3005,14.26056 9.515,21.93952 18.8012,43.97849 28.3129,65.9195 2.4154,5.57157 5.3558,10.91579 9.0469,18.36695 3.3433,-3.91375 6.299,-6.12673 7.579,-9.06894 10.4639,-24.05014 20.611,-48.23862 30.8639,-72.38124 2.1062,-4.95943 4.2506,-9.90317 7.039,-16.39359 15.5819,-1.5152 31.4945,-0.52303 47.2227,-0.47463 2.7015,19.53029 2.7778,198.37503 0.1474,221.90797 -11.0574,1.39161 -22.2553,1.9846 -34.8907,-0.89391 0,-52.45604 0,-104.62428 0,-160.74504 -4.4804,4.68127 -6.9422,6.25762 -7.964,8.49266 -4.4917,9.82102 -8.5674,19.83189 -13.6251,31.35205 z"
|
||||
id="path5"
|
||||
style="fill:#ffffff;stroke-width:1.16044" /><path
|
||||
fill="#eeeeee"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m 719.24251,453.24707 c -2.2e-4,-143.79039 -2.2e-4,-285.26009 -2.2e-4,-426.794416 11.14206,-6.25449 21.98418,-1.754024 31.24644,-3.666101 7.21605,6.966195 4.77655,14.346439 4.79824,20.94779 0.28212,85.855147 0.40441,171.711207 0.41347,257.566797 0.0116,112.92769 -0.10793,225.85502 -0.18777,338.7827 -0.0116,8.38415 -0.14958,16.76854 -0.23822,26.11668 -12.12987,0 -22.76193,0 -32.78487,0 -1.16916,-0.99044 -1.86647,-1.35646 -2.2116,-1.93355 -0.38156,-0.63837 -0.60158,-1.46645 -0.61619,-2.21728 -0.18174,-9.26853 -0.4339,-18.53857 -0.43784,-27.80803 -0.0256,-59.5579 0.0116,-119.11579 0.0185,-180.99459 z"
|
||||
id="path6"
|
||||
style="fill:#ffffff;stroke-width:1.16044" /><path
|
||||
fill="#eeeeee"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m 1755.7449,339.22545 c 0.3272,-28.4493 -0.7983,-54.61983 0.7248,-81.49067 12.6256,-2.67554 23.9589,-1.81379 36.6171,-0.83831 0.6561,5.31324 1.7934,10.46472 1.8424,15.62699 0.1987,20.87713 -0.021,41.75784 0.1307,62.63588 0.024,3.46151 1.128,6.91479 2.2393,13.26757 32.1517,-30.80955 59.1362,-62.3959 88.7093,-91.66645 13.6107,-1.44743 27.1238,-0.4708 43.2196,-0.75047 -5.7951,11.94246 -13.9498,17.89918 -20.4615,25.09989 -7.2594,8.02709 -14.7108,15.88115 -22.1311,23.76119 -6.89,7.31713 -13.8688,14.55045 -20.7722,21.85515 -6.8146,7.20978 -13.5844,14.4626 -20.993,22.35623 28.0222,44.03882 58.7096,84.62599 88.9464,127.56586 -15.3427,4.61802 -29.555,2.06143 -44.4756,2.46202 -23.5436,-33.7347 -46.8802,-67.17302 -71.0658,-101.82796 -4.557,4.31734 -7.6114,7.46356 -10.9273,10.30471 -9.4239,8.07524 -13.2785,17.80505 -12.604,30.56213 1.0175,19.24969 0.2653,38.59329 0.2653,58.51615 -12.6577,4.41286 -24.644,2.5617 -35.3929,1.84861 -1.795,-1.53958 -2.5217,-1.9245 -2.8714,-2.52805 -0.37,-0.63767 -0.5232,-1.48282 -0.5264,-2.2384 -0.1756,-44.0677 -0.3264,-88.13577 -0.4737,-134.52207 z"
|
||||
id="path8"
|
||||
style="fill:#ffffff;stroke-width:1.16044" /><path
|
||||
fill="#f4f4f4"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m 2040.4731,310.9528 c -0.012,11.6723 -0.012,20.90973 -0.012,30.72195 10.9971,4.62683 21.8046,1.86507 32.2483,2.37311 10.0143,0.48692 20.0714,0.10445 30.1094,0.10445 10.7812,-2.3e-4 21.5622,0 32.6047,0 4.0513,10.49455 2.4977,20.20998 1.2879,31.50165 -16.5872,1.4501 -32.613,0.30345 -48.5654,0.76891 -15.3385,0.44736 -30.769,-1.28962 -46.7988,1.39138 -2.1159,22.58321 -0.8199,44.74344 -0.8593,67.36008 18.6055,3.59555 36.356,1.19782 53.9784,1.70807 17.5634,0.50828 35.1903,-0.53717 53.1147,0.81231 3.1013,10.46589 1.752,19.49932 1.5309,27.4411 -1.3144,1.64355 -1.6774,2.32521 -2.2384,2.7374 -0.6059,0.44538 -1.3874,0.87939 -2.1077,0.90608 -7.6951,0.28733 -15.3931,0.67654 -23.0907,0.68955 -39.2522,0.0673 -78.5045,0.0313 -117.4961,0.0313 -3.1476,-17.94652 -3.9083,-193.37372 -1.07,-221.78554 23.3622,-2.86969 47.0875,-0.97233 70.7119,-1.24458 22.9759,-0.26459 45.9886,-0.56527 70.0376,0.41671 0,10.66712 0,19.61953 0,30.23641 -4.2512,0.54738 -8.5291,1.54514 -12.814,1.57577 -23.164,0.1649 -46.3296,0.0267 -69.4942,0.1425 -6.0131,0.0301 -12.0236,0.5981 -19.3322,0.98824 -0.6335,6.81905 -1.1845,12.75361 -1.7467,21.12326 z"
|
||||
id="path9"
|
||||
style="fill:#ffffff;stroke-width:1.16044" /><path
|
||||
fill="#f4f4f4"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m 2561.9876,395.47975 c -15.0294,-4.73848 -28.4607,-8.31128 -41.7783,-12.26807 -8.1235,-2.41386 -16.3735,-4.76029 -24.0396,-8.28354 -21.4254,-9.84796 -33.8133,-25.91522 -34.3005,-50.49106 -0.5055,-25.48341 9.0029,-44.93886 31.4622,-57.68967 11.0056,-6.24788 22.9161,-9.08786 35.3729,-10.10325 25.0432,-2.04159 49.2012,0.99439 72.8749,12.41824 1.8065,11.39621 1.279,22.60724 0.4738,33.46268 -7.2636,3.01764 -11.2977,-1.93505 -15.7743,-4.12391 -12.0184,-5.87699 -24.7316,-8.76396 -37.8125,-10.37583 -10.1375,-1.2491 -20.19,-0.1033 -29.6564,3.67005 -11.6583,4.64749 -19.1169,12.78377 -19.3387,26.16147 -0.2105,12.70498 5.3087,21.43414 18.4764,26.41341 7.8944,2.98525 16.4026,4.31908 24.5845,6.57884 11.8972,3.28581 24.2103,5.62656 35.5339,10.32581 33.7506,14.00619 48.8059,54.01662 33.4349,87.30907 -8.3753,18.14112 -23.1726,28.61131 -42.2488,33.08566 -35.8416,8.4062 -70.4921,4.7625 -104.443,-10.70959 -2.0823,-12.38016 -1.7666,-24.31936 0.1925,-38.15091 7.6186,3.73909 13.6825,6.80628 19.8229,9.71136 17.0475,8.06653 34.913,12.37088 53.8766,11.45471 2.3172,-0.1114 4.6457,-0.17512 6.9432,-0.46558 13.7753,-1.74066 25.8169,-6.59856 30.8083,-20.81305 5.3111,-15.12441 0.2595,-27.19834 -14.4649,-37.11684 z"
|
||||
id="path11"
|
||||
style="fill:#ffffff;stroke-width:1.16044" /><path
|
||||
fill="#eeeeee"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m 2324.7213,408.70201 c 6e-4,23.93572 6e-4,45.55739 6e-4,67.81278 -12.458,4.8053 -24.4548,2.66682 -37.6697,1.91266 -2.543,-11.13443 -0.9878,-21.83775 -1.3115,-32.35633 -0.3085,-10.04034 -0.048,-20.09775 -0.047,-30.14773 0,-10.82309 -7e-4,-21.64604 -0.012,-32.46911 0,-10.04999 -0.012,-20.09996 -0.03,-30.14995 -0.023,-10.82319 -0.033,-21.64626 -0.1091,-32.46911 -0.069,-9.96445 -0.2183,-19.92855 -0.3438,-30.88636 -23.1014,-3.81986 -45.4664,0.78052 -68.0746,-3.07138 0,-9.76972 0,-18.81058 0,-26.91901 1.3992,-1.49814 1.8558,-2.16481 2.4752,-2.59883 0.5924,-0.41532 1.3437,-0.80175 2.043,-0.83553 5.3905,-0.26179 10.7857,-0.60377 16.1798,-0.60853 50.9551,-0.0441 101.9101,-0.0267 153.1125,-0.0267 5.2272,10.46334 3.0826,20.22239 2.1422,30.8157 -21.8288,3.94229 -43.479,0.13798 -66.2051,2.61949 -0.732,4.96744 -2.0889,9.98918 -2.1141,15.01764 -0.1714,34.01437 -0.062,68.03013 -0.042,104.35995 z"
|
||||
id="path13"
|
||||
style="fill:#ffffff;stroke-width:1.16044" /><g
|
||||
id="g19"
|
||||
transform="matrix(1.1604524,0,0,1.1604524,81.858938,-47.101746)"
|
||||
style="fill:#ccb174;fill-opacity:1"><g
|
||||
id="g3"
|
||||
style="fill:#ccb174;fill-opacity:1"
|
||||
transform="translate(0,12.70675)"><path
|
||||
fill="#c9ae73"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="M 131.60765,564.55455 C 60.990753,548.86015 17.730153,506.81935 -0.65754657,438.83965 -12.020747,396.83015 -9.8713466,355.38455 8.0249534,315.87405 35.193653,255.89145 81.930952,221.36605 148.00615,214.93185 c 29.4853,-2.8714 58.5662,-0.1619 86.1069,11.9181 61.5948,27.0166 95.2478,74.708 102.7977,140.9643 4.8972,42.978 -2.8901,83.7102 -26.2475,120.5305 -31.449,49.576 -76.6083,76.5689 -135.5877,78.8111 -13.8719,0.5271 -27.8386,-1.4361 -43.4679,-2.6013 m 65.5545,-29.344 c 22.0044,-6.3438 36.3966,-21.4908 46.5728,-41.0845 3.6551,-7.0379 6.3997,-14.6433 8.7727,-22.2356 10.5566,-33.7749 10.6811,-68.3523 6.1747,-102.9605 -3.3706,-25.8859 -10.6042,-50.852 -23.1531,-73.9812 -7.7003,-14.1926 -17.2535,-26.8676 -30.4987,-36.5083 -32.1785,-23.4209 -73.7716,-20.1635 -102.1538,7.8831 -13.773998,13.6111 -21.170798,30.6299 -26.078697,48.7576 -12.9316,47.7639 -9.6462,94.9355 6.137099,141.561 6.9186,20.438 16.2865,39.4504 31.367498,55.1072 21.9904,22.8298 48.1905,32.5124 82.8595,23.4612 z"
|
||||
id="path2"
|
||||
style="fill:#ccb174;fill-opacity:1" /><path
|
||||
fill="#c9ae73"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m 269.48165,157.86465 c 3.6399,6.206 8.7502,10.1878 8.1538,18.0252 -10.7607,4.6734 -20.6228,5.2428 -30.5203,-3.5659 -21.363,-19.0125 -43.1731,-37.5225 -64.8189,-56.2166 -5.0067,-4.3237 -10.088,-8.5613 -15.8011,-13.4031 -4.6538,3.5194 -8.9832,6.4353 -12.9075,9.8208 -22.6631,19.5503 -45.4727,38.9425 -67.717898,58.9604 -9.651999,8.6855 -19.402499,9.9912 -30.939499,5.0429 -1.4927,-7.2374 2.9787,-11.6959 6.2688,-16.4012 17.530799,-25.0703 35.233299,-50.0203 52.828797,-75.045402 8.7633,-12.4635 17.4252,-24.9984 26.1172,-37.4784 16.7091,0 32.5818,0 50.2351,0 25.716,35.826 52.0095,72.456402 79.1015,110.261302 z"
|
||||
id="path12"
|
||||
style="fill:#ccb174;fill-opacity:1" /></g><path
|
||||
fill="#000000"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m 195.60265,548.33085 c -33.1095,8.6377 -59.3096,-1.0449 -81.3,-23.8747 -15.080998,-15.6568 -24.448898,-34.6692 -31.367498,-55.1072 -15.783299,-46.6255 -19.068699,-93.7971 -6.137099,-141.561 4.907899,-18.1277 12.304699,-35.1465 26.078697,-48.7576 28.3822,-28.0466 69.9753,-31.304 102.1538,-7.8831 13.2452,9.6407 22.7984,22.3157 30.4987,36.5083 12.5489,23.1292 19.7825,48.0953 23.1531,73.9812 4.5064,34.6082 4.3819,69.1856 -6.1747,102.9605 -2.373,7.5923 -5.1176,15.1977 -8.7727,22.2356 -10.1762,19.5937 -24.5684,34.7407 -48.1323,41.498 z"
|
||||
id="path14"
|
||||
style="fill:none;fill-opacity:1" /></g><path
|
||||
fill="#f4f4f4"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m 1512.7545,307.08622 c 0,-17.6542 0,-33.02474 0,-49.59065 5.9445,-0.52476 10.3121,-1.20838 14.6853,-1.24494 20.0898,-0.1671 40.1806,-0.18161 60.2713,-0.19542 14.0713,-0.0116 27.4574,3.05326 40.6328,8.05934 45.9433,17.45808 46.6284,82.57408 15.2122,105.51449 -3.7249,2.71987 -7.6262,5.19766 -11.8361,8.05261 9.987,16.54805 20.126,32.59757 29.4948,49.08411 9.134,16.07378 17.481,32.59468 26.9012,50.28566 -14.2438,4.23066 -27.7508,1.87912 -42.1066,1.67372 -7.9059,-15.26888 -15.5882,-30.32807 -23.4876,-45.27262 -4.3242,-8.18072 -8.6517,-16.39905 -13.6251,-24.18707 -7.6112,-11.91843 -18.8664,-17.8994 -33.0285,-18.14785 -7.6363,-0.13404 -15.2771,-0.0244 -24.2588,-0.0244 0,29.38324 0,57.0902 0,86.35937 -6.9209,0.72412 -12.6895,1.57484 -18.4863,1.86647 -6.0242,0.30369 -12.0757,0.0673 -16.4004,0.0673 -2.217,-2.13256 -2.9341,-2.58131 -3.2854,-3.22872 -0.3428,-0.63094 -0.4204,-1.46415 -0.4275,-2.21043 -0.1376,-14.67752 -0.3416,-29.35574 -0.3471,-44.03372 -0.014,-40.18148 0.057,-80.36273 0.093,-122.82797 m 50.6994,-18.65508 c -3.5865,0.46371 -7.1726,0.92719 -11.6002,1.49953 -0.5585,23.27566 -1.8954,45.19615 0.7434,67.7587 15.6967,0 30.2993,1.18912 44.6218,-0.30624 17.2494,-1.80079 27.4254,-14.21183 28.3078,-31.11834 1.0166,-19.47101 -6.8852,-31.17266 -25.7261,-35.14756 -10.4147,-2.19708 -21.3591,-1.88236 -36.3467,-2.68609 z"
|
||||
id="path7"
|
||||
style="fill:#ffffff;stroke-width:1.16045" /><path
|
||||
fill="#000000"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m 1565.595,288.42429 c 12.8465,0.81058 23.7909,0.49586 34.2056,2.69294 18.8409,3.9749 26.7428,15.67655 25.7262,35.14756 -0.8825,16.90651 -11.0585,29.31755 -28.3079,31.11834 -14.3225,1.49536 -28.9251,0.30624 -44.6218,0.30624 -2.6388,-22.56255 -1.3018,-44.48304 -0.7433,-67.7587 4.4276,-0.57234 8.0137,-1.03582 13.7412,-1.50638 z"
|
||||
id="path15"
|
||||
style="fill:none;stroke-width:1.16045" /><path
|
||||
fill="#f4f4f4"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m 1272.6324,421.65419 c 18.746,-55.81532 36.9981,-109.85794 55.3977,-164.33689 14.6762,-2.16169 28.3186,-0.70289 43.1079,-1.09244 24.842,73.7233 49.3809,146.54737 73.9918,219.5851 -6.0397,5.30244 -12.4607,2.85888 -18.2411,3.28326 -6.0752,0.44619 -12.2083,0.0998 -19.0293,0.0998 -9.486,-17.29121 -10.5595,-37.51302 -21.3256,-53.99028 -25.0966,0 -49.602,0 -74.7367,0 -9.2695,16.6229 -11.2084,35.52075 -19.4881,52.8123 -11.8971,2.17272 -24.0122,1.35646 -37.7874,0.52546 3.763,-19.68766 12.1523,-36.97237 18.1108,-56.88596 m 92.1307,-75.1936 c -5.4892,-13.92949 -6.6635,-29.5052 -16.1376,-43.87508 -10.0156,30.88115 -19.6013,60.01488 -28.0735,91.96411 20.1955,-0.63013 38.3275,0.7117 58.3136,-1.02074 -4.771,-15.669 -9.0062,-29.57854 -14.1025,-47.06829 z"
|
||||
id="path10"
|
||||
style="fill:#ffffff;stroke-width:1.16045" /><path
|
||||
fill="#000000"
|
||||
opacity="1"
|
||||
stroke="none"
|
||||
d="m 1365.1938,348.25047 c 4.6656,15.69987 8.9008,29.60941 13.6718,45.27841 -19.9861,1.73245 -38.1181,0.39061 -58.3136,1.02074 8.4722,-31.94923 18.0579,-61.08296 28.0735,-91.96411 9.4741,14.36988 10.6484,29.94559 16.5683,45.66496 z"
|
||||
id="path16"
|
||||
style="fill:none;stroke-width:1.16045" /></g></svg>
|
||||
|
After Width: | Height: | Size: 18 KiB |
@@ -2,6 +2,8 @@
|
||||
|
||||
[Atlas Cloud](https://www.atlascloud.ai/?utm_source=github&utm_medium=link&utm_campaign=everything-claude-code) is a full-modal AI inference platform providing an OpenAI-compatible API for 59+ LLM models, image generation, and video generation.
|
||||
|
||||
> Run or self-host any open-source model instead of using a managed API. Itô is ECC's preferred compute sponsor: [open the Itô dashboard to sign in and rent or manage GPUs](https://compute.itomarkets.com). Any GPU provider works. ECC only provides this link; it does not provision compute or serving. Managed inference through Itô is not live yet.
|
||||
|
||||
## Configuration
|
||||
|
||||
Set the following environment variables to use Atlas Cloud as your LLM backend:
|
||||
|
||||
@@ -0,0 +1,562 @@
|
||||
# ECC × Itô Compute Integration
|
||||
|
||||
Status: **Proposed — requires Affaan approval before Phase 2 implementation**
|
||||
|
||||
Owner: Affaan Mustafa
|
||||
|
||||
Prepared: 2026-07-21
|
||||
|
||||
Phase 1 branch: agent/ito-sponsor-compute
|
||||
|
||||
## Decision gate
|
||||
|
||||
This document is the approval artifact for Phase 2. Approval authorizes only
|
||||
delivery slices 1 and 2: the five skills and the fail-closed CLI/MCP stub. It
|
||||
does not authorize or claim a working Itô inference service, live rental API,
|
||||
OAuth integration, billing flow, or rental mutation.
|
||||
|
||||
No Phase 2 skill, CLI, MCP, OAuth, rental-management, or serving code should be
|
||||
built until Affaan approves the decisions at the end of this document.
|
||||
|
||||
## Thesis
|
||||
|
||||
The distribution chain is:
|
||||
|
||||
GPU compute (Itô)
|
||||
-> any open-source model
|
||||
-> model harness
|
||||
-> ECC meta-harness
|
||||
|
||||
Itô is ECC's preferred compute sponsor. It is never an exclusive provider.
|
||||
ECC remains open source and all workflows must accept owned hardware, existing
|
||||
clusters, and other compute providers.
|
||||
|
||||
## Terms and non-negotiable boundaries
|
||||
|
||||
- **Self-hosting** means the user operates a model runtime on owned or rented
|
||||
compute. ECC does not silently provision or operate that runtime.
|
||||
- **Preferred compute sponsor** means Itô is suggested at the step where a user
|
||||
needs new GPU capacity. Requirements and existing capacity come first.
|
||||
- **Provider-neutral** means users can choose any provider or use hardware they
|
||||
already control without losing workflow functionality.
|
||||
- **Manual handoff** means ECC can route the user to
|
||||
<https://compute.itomarkets.com> for sign-in, rental, and dashboard access.
|
||||
- **Not live** means ECC cannot currently exchange Itô OAuth tokens, fetch live
|
||||
inventory or pricing, create or manage rentals, or return an inference
|
||||
endpoint.
|
||||
- Itô compute authentication must not reuse the prediction-market ITO_API_KEY.
|
||||
- Phase 2 must not add an Itô LLM provider or advertise an Itô-compatible model
|
||||
endpoint. Itô is the compute layer, not an inference API.
|
||||
|
||||
## Sequencing
|
||||
|
||||
### Phase 1: launch-ready sponsor and compute routing
|
||||
|
||||
Phase 1 is the smallest shippable slice and is prepared before Phase 2:
|
||||
|
||||
| Surface | Launch-ready change |
|
||||
|---|---|
|
||||
| ECC README and sponsor roster | Itô logo beside current business sponsors; preferred-compute and provider-neutral disclosure |
|
||||
| ecc-universal npm surface | README placement, packaged sponsor assets, and install welcome copy |
|
||||
| ECC installer | Human help and install-plan footer route self-host intent to Itô; JSON remains machine-pure |
|
||||
| ECC CLI | Top-level help shows the same shared compute disclosure |
|
||||
| Harness-specific endpoint/model docs | Bring-your-own endpoint/model notes route GPU needs to Itô without claiming provisioning |
|
||||
| Local-model selector | Ollama selection shows a passive compute-rental/dashboard notice; no Itô provider adapter |
|
||||
| ecc.tools | Sponsor card, sponsor proof chip, and explicit no-serving boundary |
|
||||
| AgentShield / ecc-agentshield | Sponsor callout in the GitHub and npm README; no ads in security reports |
|
||||
|
||||
Launch coordination still matters:
|
||||
|
||||
- Merge the public PRs when their required checks and reviews pass. Coordinate
|
||||
npm publication and the verified ecc.tools deployment as explicit release
|
||||
steps; do not tie the generic OSS-compute integration to an unpublished model
|
||||
or model-provider announcement.
|
||||
- npm READMEs update only when new versions are published. Merging source changes
|
||||
alone does not update the already-published ecc-universal or ecc-agentshield
|
||||
package pages.
|
||||
- The release owner must select unused package versions in the launch commit,
|
||||
update every synchronized version surface, prove that neither version exists
|
||||
in the npm registry, publish both packages, and read back the rendered package
|
||||
pages. The sponsor PRs do not silently republish existing versions.
|
||||
- ecc.tools requires its normal verified Cloudflare deployment after merge.
|
||||
|
||||
### Phase 2: build only after approval
|
||||
|
||||
Phase 2 adds provider-neutral operational skills and an honest Itô control-plane
|
||||
stub. Real OAuth, rentals, and serving remain separately gated on backend
|
||||
contracts.
|
||||
|
||||
## Channel A: self-host an open model
|
||||
|
||||
### Skill 1: self-host-a-model
|
||||
|
||||
Path:
|
||||
|
||||
skills/self-host-a-model/SKILL.md
|
||||
|
||||
Activate when a user asks to self-host, locally host, or deploy an open model;
|
||||
mentions Ollama, vLLM, SGLang, TGI, an OpenAI-compatible endpoint, Kimi, GLM,
|
||||
Llama, Mistral, quantization, GPU sizing, or moving away from a managed API.
|
||||
|
||||
Workflow shape:
|
||||
|
||||
1. Identify the model artifact, license, trust boundary, and required context.
|
||||
2. Estimate VRAM from weights, precision or quantization, KV cache, concurrency,
|
||||
and runtime overhead.
|
||||
3. Prefer existing owned or already-rented capacity when it satisfies the
|
||||
requirement.
|
||||
4. If capacity is missing, compare provider requirements and disclose Itô as
|
||||
ECC's preferred compute sponsor. Authenticate only if the user selects Itô.
|
||||
5. Select a user-controlled runtime, container, storage, network, auth, and TLS
|
||||
plan.
|
||||
6. Produce endpoint smoke tests and harness configuration steps.
|
||||
7. Verify model identity, response schema, latency, health, and shutdown.
|
||||
|
||||
Required output: SelfHostPlan
|
||||
|
||||
| Field | Meaning |
|
||||
|---|---|
|
||||
| computeOwner | owned, existing cluster, Itô, or another selected provider |
|
||||
| modelArtifact | immutable model and revision |
|
||||
| runtime | selected serving engine and version |
|
||||
| resourceEnvelope | GPU type/count, VRAM, CPU, RAM, disk, and network |
|
||||
| endpointContract | expected protocol and auth, never a fabricated endpoint |
|
||||
| deploymentSteps | provider-neutral execution plan |
|
||||
| verification | health, identity, schema, latency, and teardown checks |
|
||||
| blockers | missing access, capacity, serving, or model facts |
|
||||
|
||||
Non-goals:
|
||||
|
||||
- Do not claim ECC or Itô created an endpoint.
|
||||
- Do not fabricate Itô inventory, pricing, credentials, or rental identifiers.
|
||||
- Do not force any model family; the skill is model-agnostic.
|
||||
|
||||
## Channel B: training and GPU operations
|
||||
|
||||
### Skill 2: training-run-operations
|
||||
|
||||
Path:
|
||||
|
||||
skills/training-run-operations/SKILL.md
|
||||
|
||||
Activate for launching, resuming, debugging, observing, or cost-planning a
|
||||
training, fine-tuning, evaluation, retraining, or MLE run.
|
||||
|
||||
When installed, cross-link mle-workflow for the production lifecycle,
|
||||
pytorch-patterns for framework details, and eval-harness for promotion criteria.
|
||||
The new skill must still be usable on Kimi without mle-workflow or
|
||||
pytorch-patterns because their current install modules do not support Kimi. Keep
|
||||
the standalone contract minimal instead of copying those skills wholesale.
|
||||
|
||||
Required output: TrainingRunPlan containing an immutable code revision, dataset
|
||||
snapshot, environment or image, entry point, resources, artifact paths,
|
||||
checkpoint and resume policy, metrics, observation plan, budget, retry policy,
|
||||
and promotion gate.
|
||||
|
||||
Workflow:
|
||||
|
||||
1. Run a local or minimal-capacity smoke test.
|
||||
2. Size the full run and identify existing capacity.
|
||||
3. Acquire new capacity only when needed; suggest Itô while permitting any
|
||||
provider.
|
||||
4. Route scheduler-specific work to the Slurm or Kubernetes GPU skill.
|
||||
5. Submit, observe, checkpoint, resume, evaluate, and explicitly promote.
|
||||
|
||||
### Skill 3: gpu-workload-splitting
|
||||
|
||||
Path:
|
||||
|
||||
skills/gpu-workload-splitting/SKILL.md
|
||||
|
||||
Activate when a user asks to split a model, dataset, batch job, sweep, or
|
||||
training run across GPUs or nodes; reports poor scaling, stragglers, or
|
||||
out-of-memory failures; or needs a workload-splitting layer.
|
||||
|
||||
The skill must choose deliberately among data, tensor, pipeline, model, context,
|
||||
or expert parallelism; independent shards; or job arrays. It must measure VRAM,
|
||||
communication-to-compute ratio, topology, data locality, and heterogeneous
|
||||
capacity before choosing.
|
||||
|
||||
Required output: WorkloadSplitPlan
|
||||
|
||||
| Field | Meaning |
|
||||
|---|---|
|
||||
| tasks | deterministic units of work |
|
||||
| resources | CPU, RAM, accelerator, storage, and network per task |
|
||||
| dependsOn | dependency DAG |
|
||||
| shard | deterministic partition and ownership rule |
|
||||
| placement | node, GPU, topology, and locality constraints |
|
||||
| checkpoint | boundaries and resume behavior |
|
||||
| merge | aggregation or reduction contract |
|
||||
| failurePolicy | retry, idempotency, straggler, and partial-failure rules |
|
||||
|
||||
Itô appears only at the capacity-acquisition step. Validate this output shape
|
||||
with the LinkedIn contact who requested a workload-splitting layer before calling
|
||||
Channel B customer-validated.
|
||||
|
||||
### Skill 4: slurm-gpu-workloads
|
||||
|
||||
Path:
|
||||
|
||||
skills/slurm-gpu-workloads/SKILL.md
|
||||
|
||||
Activate for sbatch, srun, salloc, GPU GRES or TRES, pending jobs, arrays,
|
||||
DDP/NCCL, queue time, low utilization, requeue, or Slurm GPU optimization.
|
||||
|
||||
Workflow:
|
||||
|
||||
- Inspect cluster, partition, QOS, account, node, and GPU facts read-only first.
|
||||
- Map nodes, tasks, processes, and GPUs explicitly.
|
||||
- Cover staging, checkpoint signals, requeue, arrays, logs, topology, and scaling
|
||||
diagnostics.
|
||||
- Produce an sbatch plan or template plus validation commands.
|
||||
- Never make scheduler-admin or cluster-wide changes without explicit authority.
|
||||
- Use an existing cluster unchanged when possible; suggest Itô only when new
|
||||
capacity is requested.
|
||||
|
||||
### Skill 5: kubernetes-gpu-workloads
|
||||
|
||||
Path:
|
||||
|
||||
skills/kubernetes-gpu-workloads/SKILL.md
|
||||
|
||||
Activate for GPU Jobs or pods, nvidia.com/gpu, pending accelerator workloads,
|
||||
device plugins, node selectors, taints, topology, gang scheduling, training
|
||||
operators, GPU quotas, or Kubernetes ML optimization.
|
||||
|
||||
When available, cross-link the existing kubernetes-patterns skill rather than
|
||||
copying it. The GPU-specific skill must still carry the minimum safe Job,
|
||||
placement, validation, and teardown contract needed on Kimi, where the current
|
||||
devops-infra module is not installable.
|
||||
|
||||
Workflow:
|
||||
|
||||
- Inspect node capacity, device-plugin/runtime readiness, available APIs, and
|
||||
installed operators before generating manifests.
|
||||
- Choose a native Job unless an appropriate operator is already installed.
|
||||
- Never invent a custom resource definition.
|
||||
- Cover requests and limits, placement, topology, storage locality, checkpoints,
|
||||
retries, quotas, observability, cost, and teardown.
|
||||
- Produce manifests plus client and server dry-run checks.
|
||||
|
||||
## Shared provider rule for all five skills
|
||||
|
||||
Every skill must apply this order:
|
||||
|
||||
1. Capture workload requirements.
|
||||
2. Reuse owned or existing compute when it fits.
|
||||
3. If capacity is missing, present provider-neutral criteria.
|
||||
4. Disclose Itô as ECC's preferred compute sponsor.
|
||||
5. Allow another provider without degrading the workflow.
|
||||
6. Trigger Itô authentication only after the user selects Itô.
|
||||
7. Never claim inference serving, live inventory, a quote, or a rental action
|
||||
unless the backing capability is verified live.
|
||||
|
||||
No legacy commands should be added. skills/ remains the canonical workflow
|
||||
surface.
|
||||
|
||||
## Install and package shape
|
||||
|
||||
Add a non-default gpu-compute module in manifests/install-modules.json:
|
||||
|
||||
- Paths: the five skill directories above.
|
||||
- Supported targets: all current targets, including kimi.
|
||||
- Dependencies: platform-configs only. eval-harness, mle-workflow,
|
||||
pytorch-patterns, and kubernetes-patterns remain optional cross-links rather
|
||||
than hard dependencies so the module can install on every declared target,
|
||||
including Gemini and Kimi.
|
||||
- Default install: false.
|
||||
- Stability: beta.
|
||||
- Cost: medium.
|
||||
|
||||
Add capability:gpu-compute to manifests/install-components.json and add the
|
||||
module to the full install profile. Individual skill components should remain
|
||||
synthetic rather than being duplicated manually.
|
||||
|
||||
Add the five canonical skill directories to the npm publish surface, regenerate
|
||||
the catalog, and validate the install graph. Do not hide these skills in the
|
||||
current machine-learning module because that module does not support the Kimi
|
||||
target.
|
||||
|
||||
## ito CLI and MCP v0
|
||||
|
||||
### Placement
|
||||
|
||||
Keep the initial stub inside ecc-universal:
|
||||
|
||||
scripts/ito.js
|
||||
scripts/ito-mcp.js
|
||||
scripts/lib/ito/contracts.js
|
||||
scripts/lib/ito/capabilities.js
|
||||
scripts/lib/ito/auth.js
|
||||
scripts/lib/ito/client.js
|
||||
scripts/lib/ito/mcp.js
|
||||
|
||||
Expose ecc ito as canonical and an ASCII ito bin alias. Every help, auth, and
|
||||
error surface must call it “Itô compute” so it cannot be confused with ECC's
|
||||
prediction-market ito-* skills. Prose and brand UI use Itô. Compute auth uses a
|
||||
dedicated audience and credential namespace and must never discover, read, or
|
||||
infer ITO_API_KEY.
|
||||
|
||||
### CLI commands
|
||||
|
||||
ito capabilities [--json]
|
||||
ito dashboard --intent self-host|training [--no-open]
|
||||
ito auth status [--json]
|
||||
ito auth login --intent self-host|training [--no-open] [--json]
|
||||
ito rent plan --intent ... --accelerator ... --count ... --memory-gib ... --hours ... [--json]
|
||||
ito rent create --plan ... [--json]
|
||||
ito rentals list [--json]
|
||||
ito rentals get <id> [--json]
|
||||
ito rentals stop <id> [--json]
|
||||
ito mcp
|
||||
|
||||
### MCP tools
|
||||
|
||||
compute_capabilities
|
||||
dashboard_handoff
|
||||
auth_status
|
||||
auth_login
|
||||
rent_plan
|
||||
rent_create
|
||||
rentals_list
|
||||
rental_get
|
||||
rental_stop
|
||||
|
||||
Except for the ito mcp transport command, every CLI operation has an equivalent
|
||||
MCP tool backed by the same service method. dashboard_handoff is the MCP peer of
|
||||
ito dashboard. MCP handoff tools return a URL and never open a browser; only a
|
||||
direct local CLI invocation may open one, and --no-open must remain available.
|
||||
Every command emitted or invoked by a skill, agent, or generated artifact must
|
||||
pass --no-open; automatic browser opening is reserved for a human typing the
|
||||
CLI command directly.
|
||||
|
||||
All tools and commands return the same versioned response envelope. A supported
|
||||
manual handoff looks like:
|
||||
|
||||
{
|
||||
"schemaVersion": "ito.compute.v0",
|
||||
"success": true,
|
||||
"state": "manual_handoff",
|
||||
"data": {
|
||||
"authenticated": false
|
||||
},
|
||||
"error": null,
|
||||
"links": {
|
||||
"dashboard": "https://compute.itomarkets.com"
|
||||
}
|
||||
}
|
||||
|
||||
An unavailable capability must instead use:
|
||||
|
||||
{
|
||||
"schemaVersion": "ito.compute.v0",
|
||||
"success": false,
|
||||
"state": "unavailable",
|
||||
"data": null,
|
||||
"error": {
|
||||
"code": "CAPABILITY_NOT_AVAILABLE",
|
||||
"message": "This operation requires an approved live Itô compute API."
|
||||
},
|
||||
"links": {
|
||||
"dashboard": "https://compute.itomarkets.com"
|
||||
}
|
||||
}
|
||||
|
||||
Envelope invariants:
|
||||
|
||||
- unavailable always means success: false, non-null typed error, and no
|
||||
action-like data.
|
||||
- The CLI exits nonzero for unavailable or validation failures.
|
||||
- MCP returns the same envelope in an error tool result; it must not translate
|
||||
failure into a successful-looking action.
|
||||
- manual_handoff means the routing behavior worked. It does not mean inventory,
|
||||
OAuth, rental management, or inference is available.
|
||||
|
||||
### Honest stub behavior
|
||||
|
||||
| Capability | Phase 2 stub value |
|
||||
|---|---|
|
||||
| dashboardHandoff | true |
|
||||
| oauthTokenExchange | false |
|
||||
| rentRequestDraft | true |
|
||||
| rentMutation | false |
|
||||
| rentalManagement | false |
|
||||
| inferenceServing | false |
|
||||
|
||||
- capabilities reports the table above.
|
||||
- dashboard opens or returns the approved compute URL.
|
||||
- auth status reports authenticated: false and oauthTokenExchange: false. It
|
||||
must not inspect ITO_API_KEY or imply that dashboard cookies are CLI auth.
|
||||
- auth login opens or returns the dashboard URL and reports manual action
|
||||
required. MCP returns the URL without opening it. Neither path may say OAuth
|
||||
succeeded.
|
||||
- rent plan validates and normalizes requirements, then returns manual_handoff.
|
||||
It must not fabricate inventory, price, quote, or plan ID.
|
||||
- rent create, rental reads, and stop fail closed with
|
||||
CAPABILITY_NOT_AVAILABLE until backed by live APIs.
|
||||
- Future paid creation and rental stop remain hard-disabled until a trusted
|
||||
consent channel exists. A model-supplied boolean, --confirm flag, or tool
|
||||
argument is not proof of user consent. Live mutations require either
|
||||
host-mediated user elicitation or a single-use capability issued outside the
|
||||
model and bound to the account, exact action and resource, immutable quote or
|
||||
resource ID, maximum cost, expiry, and idempotency key.
|
||||
|
||||
### MCP distribution
|
||||
|
||||
Add Itô only as an opt-in entry in mcp-configs/mcp-servers.json:
|
||||
|
||||
"ito": {
|
||||
"command": "ito",
|
||||
"args": ["mcp"],
|
||||
"description": "Opt-in Itô compute rental and management interface. Manual dashboard handoff only until live control-plane APIs are enabled; does not provide inference serving."
|
||||
}
|
||||
|
||||
Do not add it to the default .mcp.json or the Claude plugin manifest. ECC's MCP
|
||||
policy permits one universal default connector; this integration is intentional
|
||||
and task-scoped.
|
||||
|
||||
## OAuth-on-intent contract
|
||||
|
||||
The authentication trigger is a user decision, not installation:
|
||||
|
||||
self-host or training intent
|
||||
-> capacity needed
|
||||
-> user selects Itô
|
||||
-> auth status
|
||||
-> login handoff or future OAuth
|
||||
|
||||
Until the backend contract exists, login remains a manual dashboard handoff.
|
||||
|
||||
When live OAuth becomes available, require:
|
||||
|
||||
- A public native client using Authorization Code with PKCE S256 and no packaged
|
||||
client secret, or an explicitly approved phishing-resistant device flow.
|
||||
- State and nonce validation plus issuer, audience, and redirect validation.
|
||||
- A loopback callback bound only to localhost with one-time state and a short
|
||||
timeout, or the approved device-flow equivalent.
|
||||
- Fixed redirect origins and least-privilege scopes.
|
||||
- OS credential storage under an ecc.ito.compute-specific service/account
|
||||
namespace, never repository files, .env files, MCP config, CLI arguments,
|
||||
child-process environments, or ITO_API_KEY.
|
||||
- Raw access and refresh tokens must never enter model context, MCP results,
|
||||
stdout, stderr, telemetry, crash reports, or logs. Account and billing data is
|
||||
redacted by default.
|
||||
- Refresh and revocation behavior.
|
||||
- Trusted account and cost consent before paid actions as defined in the
|
||||
mutation-capability contract above.
|
||||
|
||||
## Input and generated-artifact safety
|
||||
|
||||
- Define JSON Schemas for intents, accelerator names, counts, memory, duration,
|
||||
identifiers, plans, and every MCP input. Enforce enums and numeric ranges,
|
||||
bound string and collection lengths, and reject control characters or
|
||||
newlines in IDs and scheduler fields.
|
||||
- Build subprocess calls with executable-plus-argv arrays. Never concatenate
|
||||
inputs into a shell command, use shell: true, eval generated text, or interpolate
|
||||
untrusted values into Slurm directives.
|
||||
- Validate Slurm partitions, accounts, QOS, GRES/TRES, paths, and job names
|
||||
before rendering. Validate Kubernetes resource names, API kinds, namespaces,
|
||||
images, pull policy, resources, selectors, tolerations, volumes, and command
|
||||
arrays against explicit schemas.
|
||||
- Pin model, container, code, and dataset revisions in executable plans.
|
||||
- Render artifacts by default. Submission or execution is a separate step that
|
||||
requires explicit user authority and must preserve client/server dry runs.
|
||||
- Never place kubeconfig, SSH keys, registry credentials, scheduler tokens, or
|
||||
provider secrets in generated artifacts or model-visible output.
|
||||
|
||||
## Pre-stageable versus blocked
|
||||
|
||||
| Pre-stageable after approval | Blocked on Itô or serving infrastructure |
|
||||
|---|---|
|
||||
| Five provider-neutral skills | OAuth issuer and client registration |
|
||||
| Resource sizing and workload plans | Authorization, token, refresh, and revocation endpoints |
|
||||
| Slurm and Kubernetes artifacts for user-provided clusters | Live accelerator inventory and availability |
|
||||
| Static dashboard handoff | Live pricing, quotes, billing, and idempotency |
|
||||
| CLI/MCP schemas and capability reporting | Rental create, list, get, stop APIs and lifecycle states |
|
||||
| Manual sign-in and rental handoff | SSH, kubeconfig, Slurm, or other access delivery |
|
||||
| Fail-closed unavailable responses | Model upload and deployment |
|
||||
| Mocked contract tests | Endpoint creation, health, autoscaling, and inference serving |
|
||||
|
||||
Inference serving is a separate future phase. It must not be unlocked merely by
|
||||
finishing this Phase 2 stub.
|
||||
|
||||
## Test plan
|
||||
|
||||
Add:
|
||||
|
||||
- tests/ci/ito-compute-skills.test.js for exact skills, triggers,
|
||||
provider-neutral language, sponsor disclosure, and the no-serving boundary.
|
||||
- tests/lib/ito-contracts.test.js for validation, immutable envelopes, capability
|
||||
states, URL allowlisting, injection-resistant schemas, and redaction.
|
||||
- tests/scripts/ito.test.js for help, JSON, no-browser handoff, invalid input,
|
||||
unavailable mutations, nonzero exit parity, and proof that ITO_API_KEY is
|
||||
ignored.
|
||||
- tests/scripts/ito-mcp.test.js for stdio initialization, tool schemas,
|
||||
CLI/tool parity, error-result parity, no-browser handoff, and secret-free
|
||||
results.
|
||||
- tests/integration/ito-compute-e2e.test.js for ecc ito to manual handoff and MCP
|
||||
calls without unapproved network or browser side effects.
|
||||
|
||||
Extend the ECC CLI, install-manifest, npm-publish-surface, and plugin-manifest
|
||||
tests as required.
|
||||
|
||||
Required gates:
|
||||
|
||||
node scripts/ci/validate-skills.js --strict
|
||||
node scripts/ci/validate-install-manifests.js
|
||||
npm run catalog:check
|
||||
npm test
|
||||
npm run coverage
|
||||
npm run lint
|
||||
npm pack --dry-run --json
|
||||
npm run security:ioc-scan
|
||||
|
||||
Manual acceptance:
|
||||
|
||||
- Existing hardware skips provider selection.
|
||||
- An alternate provider path never invokes Itô authentication.
|
||||
- Selecting Itô returns only truthful supported capabilities.
|
||||
- Rental mutations fail closed until backed by live APIs.
|
||||
- No flow emits an Itô inference endpoint.
|
||||
- The Kimi target installs capability:gpu-compute.
|
||||
- Paid and destructive actions remain unavailable until the trusted consent
|
||||
capability and its separate approval exist.
|
||||
|
||||
## Delivery slices after approval
|
||||
|
||||
1. **Skills and install module:** five skills, provider rule, manifests, catalog,
|
||||
and validation.
|
||||
2. **CLI and opt-in MCP stub:** shared contracts, manual handoff, fail-closed
|
||||
commands/tools, security and parity tests.
|
||||
3. **OAuth and rental control plane:** a separately authorized future phase,
|
||||
only after Itô supplies the live API contract and a threat model, API/contract
|
||||
review, security review, billing review, and Affaan launch approval all pass.
|
||||
4. **Inference serving:** separate plan, security review, economics review, and
|
||||
explicit launch approval.
|
||||
|
||||
Each slice must use its own focused PR and stay mergeable without later slices.
|
||||
|
||||
## Affaan approval checklist
|
||||
|
||||
- [ ] Approve the five skill names and their boundaries.
|
||||
- [ ] Approve separate Slurm and Kubernetes GPU skills.
|
||||
- [ ] Approve capability:gpu-compute with Kimi target support.
|
||||
- [ ] Approve sponsor wording: Itô in prose, ASCII ito for CLI and MCP.
|
||||
- [ ] Approve ecc ito plus the ito bin alias inside ecc-universal.
|
||||
- [ ] Approve an opt-in MCP entry and no default MCP/plugin registration.
|
||||
- [ ] Approve manual-handoff and fail-closed stub semantics.
|
||||
- [ ] Approve the shared response envelope and trusted-consent boundary.
|
||||
- [ ] Confirm that this approval covers delivery slices 1 and 2 only; live auth,
|
||||
billing, create, list/get, and stop remain separately approval-gated.
|
||||
- [ ] Supply or explicitly defer the OAuth and rental API contract.
|
||||
- [ ] Confirm endpoint configuration for every supported harness before
|
||||
publishing an example.
|
||||
- [ ] Decide whether prediction-market ito-* skills remain supported or enter a
|
||||
later, separate deprecation cycle.
|
||||
- [ ] Validate WorkloadSplitPlan with the LinkedIn contact before describing
|
||||
Channel B as customer-validated.
|
||||
|
||||
Approval of this document authorizes delivery slices 1 and 2 only: the skills
|
||||
and fail-closed stub. It does not authorize live auth, billing, rental APIs,
|
||||
mutations, or claims that Itô inference serving is live.
|
||||
Generated
+14
-14
@@ -1122,9 +1122,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-uri": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==",
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz",
|
||||
"integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -1472,9 +1472,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz",
|
||||
"integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==",
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz",
|
||||
"integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -1590,9 +1590,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/linkify-it": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz",
|
||||
"integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==",
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz",
|
||||
"integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -1652,9 +1652,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/markdown-it": {
|
||||
"version": "14.2.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz",
|
||||
"integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==",
|
||||
"version": "14.3.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.0.tgz",
|
||||
"integrity": "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -1669,8 +1669,8 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1",
|
||||
"entities": "^4.4.0",
|
||||
"linkify-it": "^5.0.1",
|
||||
"entities": "^4.5.0",
|
||||
"linkify-it": "^5.0.2",
|
||||
"mdurl": "^2.0.0",
|
||||
"punycode.js": "^2.3.1",
|
||||
"uc.micro": "^2.1.0"
|
||||
|
||||
+8
-5
@@ -58,6 +58,7 @@
|
||||
"agent.yaml",
|
||||
"assets/ecc-icon.svg",
|
||||
"assets/hero.png",
|
||||
"assets/images/sponsors/",
|
||||
"agents/",
|
||||
"commands/",
|
||||
"docs/de-DE/",
|
||||
@@ -410,7 +411,7 @@
|
||||
"ecc-plan-canvas": "scripts/plan-canvas.js"
|
||||
},
|
||||
"scripts": {
|
||||
"welcome": "echo '\\n ecc-universal installed!\\n Run: ecc typescript\\n Compat: ecc-install typescript\\n Docs: https://github.com/affaan-m/ECC\\n'",
|
||||
"welcome": "echo '\\n ecc-universal installed!\\n Run: ecc typescript\\n Compat: ecc-install typescript\\n Docs: https://github.com/affaan-m/ECC\\n Run or self-host any open-source model.\\n Compute: Itô is the preferred compute sponsor — https://compute.itomarkets.com\\n Any GPU provider works; ECC only links to the dashboard and does not provision compute or serving.\\n Managed inference through Itô is not live yet.\\n'",
|
||||
"catalog:check": "node scripts/ci/catalog.js --text",
|
||||
"catalog:sync": "node scripts/ci/catalog.js --write --text",
|
||||
"command-registry:generate": "node scripts/ci/generate-command-registry.js",
|
||||
@@ -459,12 +460,14 @@
|
||||
"node": ">=18"
|
||||
},
|
||||
"overrides": {
|
||||
"markdown-it": ">=14.2.0",
|
||||
"js-yaml": ">=4.2.0"
|
||||
"fast-uri": "3.1.4",
|
||||
"markdown-it": "14.3.0",
|
||||
"js-yaml": "4.3.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"markdown-it": ">=14.2.0",
|
||||
"js-yaml": ">=4.2.0"
|
||||
"fast-uri": "3.1.4",
|
||||
"markdown-it": "14.3.0",
|
||||
"js-yaml": "4.3.0"
|
||||
},
|
||||
"packageManager": "yarn@4.9.2+sha512.1fc009bc09d13cfd0e19efa44cbfc2b9cf6ca61482725eb35bbc5e257e093ebf4130db6dfe15d604ff4b79efd8e1e8e99b25fa7d0a6197c9f9826358d4d65c3c"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
const { spawnSync } = require('child_process');
|
||||
const path = require('path');
|
||||
const { listAvailableLanguages } = require('./lib/install-executor');
|
||||
const { getComputeSponsorCopy } = require('./lib/compute-sponsor');
|
||||
|
||||
const COMMANDS = {
|
||||
install: {
|
||||
@@ -119,6 +120,9 @@ Compatibility:
|
||||
Global Flags:
|
||||
--dry-run Preview actions without executing (sets ECC_DRY_RUN=1)
|
||||
|
||||
Compute:
|
||||
${getComputeSponsorCopy()}
|
||||
|
||||
Examples:
|
||||
ecc typescript
|
||||
ecc install --profile developer --target claude
|
||||
|
||||
@@ -17,6 +17,7 @@ const {
|
||||
normalizeInstallRequest,
|
||||
parseInstallArgs,
|
||||
} = require('./lib/install/request');
|
||||
const { getComputeSponsorCopy } = require('./lib/compute-sponsor');
|
||||
|
||||
function getHelpText() {
|
||||
const languages = listLegacyCompatibilityLanguages();
|
||||
@@ -60,6 +61,9 @@ Options:
|
||||
--json Emit machine-readable plan/result JSON
|
||||
--help Show this help text
|
||||
|
||||
Compute:
|
||||
${getComputeSponsorCopy()}
|
||||
|
||||
Available languages:
|
||||
${languages.map(language => ` - ${language}`).join('\n')}
|
||||
|
||||
@@ -115,6 +119,8 @@ function printHumanPlan(plan, dryRun) {
|
||||
if (!dryRun) {
|
||||
console.log(`\nDone. Install-state written to ${plan.installStatePath}`);
|
||||
}
|
||||
|
||||
console.log('\nCompute: ' + getComputeSponsorCopy());
|
||||
}
|
||||
|
||||
function main() {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const ITO_COMPUTE_URL = 'https://compute.itomarkets.com';
|
||||
|
||||
function getComputeSponsorCopy() {
|
||||
return "Run or self-host any open-source model. Itô is ECC's preferred compute sponsor: "
|
||||
+ 'open its dashboard to sign in and rent or manage GPUs at '
|
||||
+ ITO_COMPUTE_URL
|
||||
+ '. Any GPU provider works. ECC only provides this link; it does not provision '
|
||||
+ 'compute or serving. Managed inference through Itô is not live yet.';
|
||||
}
|
||||
|
||||
module.exports = Object.freeze({
|
||||
ITO_COMPUTE_URL,
|
||||
getComputeSponsorCopy,
|
||||
});
|
||||
@@ -31,6 +31,21 @@ def print_providers(providers: list[tuple[str, str]]) -> None:
|
||||
print(f" {Color.GREEN}{i}{Color.RESET}. {Color.BOLD}{name}{Color.RESET} - {desc}")
|
||||
|
||||
|
||||
def print_self_host_compute_notice(provider: str) -> None:
|
||||
if provider != "ollama":
|
||||
return
|
||||
|
||||
print(
|
||||
"\nRun or self-host any open-source model. "
|
||||
"Itô is ECC's preferred compute sponsor: "
|
||||
"https://compute.itomarkets.com"
|
||||
)
|
||||
print(
|
||||
"Any GPU provider works. ECC only links to the Itô dashboard; it does not "
|
||||
"provision compute or serving. Managed inference through Itô is not live yet."
|
||||
)
|
||||
|
||||
|
||||
def select_provider(providers: list[tuple[str, str]]) -> str | None:
|
||||
if not providers:
|
||||
print("No providers available.")
|
||||
@@ -126,6 +141,8 @@ def interactive_select(
|
||||
if not provider:
|
||||
return None
|
||||
|
||||
print_self_host_compute_notice(provider)
|
||||
|
||||
models = models_per_provider.get(provider, [])
|
||||
model = select_model(models)
|
||||
if not model:
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Tests for the Phase 1 Ito compute-sponsor surface.
|
||||
*/
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const { spawnSync } = require('child_process');
|
||||
|
||||
const REPO_ROOT = path.join(__dirname, '..', '..');
|
||||
const URL_TOKEN_PATTERN = /https?:\/\/[^\s<>"'`(){}\\]+/g;
|
||||
const EXPECTED_COMPUTE_ROUTE = Object.freeze({
|
||||
protocol: 'https:',
|
||||
hostname: 'compute.itomarkets.com',
|
||||
port: '',
|
||||
username: '',
|
||||
password: '',
|
||||
pathname: '/',
|
||||
search: '',
|
||||
hash: '',
|
||||
});
|
||||
|
||||
function read(relativePath) {
|
||||
return fs.readFileSync(path.join(REPO_ROOT, relativePath), 'utf8');
|
||||
}
|
||||
|
||||
function runTest(name, fn) {
|
||||
try {
|
||||
fn();
|
||||
console.log(` ✓ ${name}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log(` ✗ ${name}`);
|
||||
console.error(` ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isExactComputeRoute(candidate) {
|
||||
try {
|
||||
const parsed = new URL(candidate.replace(/[.,;:!?]+$/, ''));
|
||||
return Object.entries(EXPECTED_COMPUTE_ROUTE).every(
|
||||
([property, expected]) => parsed[property] === expected
|
||||
);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function assertExactComputeRoute(content) {
|
||||
const candidates = content.match(URL_TOKEN_PATTERN) || [];
|
||||
assert.ok(
|
||||
candidates.some(isExactComputeRoute),
|
||||
'Should include the exact Itô compute route'
|
||||
);
|
||||
}
|
||||
|
||||
function assertHonestComputeCopy(content) {
|
||||
assertExactComputeRoute(content);
|
||||
assert.match(content, /preferred compute sponsor/i);
|
||||
assert.match(content, /run or self-host any open-source model/i);
|
||||
assert.match(content, /any GPU provider/i);
|
||||
assert.match(content, /managed inference[^\n.]*not live/i);
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log('\n=== Testing Ito compute-sponsor surface ===\n');
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
const tests = [
|
||||
['compute route validation rejects deceptive lookalike hosts', () => {
|
||||
const deceptiveCopy = [
|
||||
'Itô is the preferred compute sponsor:',
|
||||
'https://compute.itomarkets.com.attacker.example',
|
||||
'Any GPU provider works.',
|
||||
'Managed inference through Itô is not live.',
|
||||
].join(' ');
|
||||
|
||||
assert.throws(
|
||||
() => assertHonestComputeCopy(deceptiveCopy),
|
||||
/exact Itô compute route/
|
||||
);
|
||||
}],
|
||||
['README exposes the sponsor logo and honest self-hosting route', () => {
|
||||
const readme = read('README.md');
|
||||
assert.ok(readme.includes('assets/images/sponsors/ito.svg'));
|
||||
assertHonestComputeCopy(readme);
|
||||
assert.match(
|
||||
readme,
|
||||
/custom API endpoint or model gateway[\s\S]*Run or self-host any open-source model behind that gateway[\s\S]*ECC only links to the Itô dashboard/
|
||||
);
|
||||
const sponsorMark = read('assets/images/sponsors/ito.svg');
|
||||
assert.match(sponsorMark, /<path\b/);
|
||||
assert.match(sponsorMark, /fill="#0F172A"/);
|
||||
assert.doesNotMatch(
|
||||
sponsorMark,
|
||||
/@import|<script|<foreignObject|\son[a-z]+=|(?:href|xlink:href)=/i
|
||||
);
|
||||
}],
|
||||
['sponsor roster lists Ito alongside business sponsors', () => {
|
||||
const sponsors = read('SPONSORS.md');
|
||||
assert.ok(sponsors.includes('[**Itô**]'));
|
||||
assert.ok(sponsors.includes('assets/images/sponsors/ito.svg'));
|
||||
assertExactComputeRoute(sponsors);
|
||||
}],
|
||||
['inference guide distinguishes rental compute from managed serving', () => {
|
||||
assertHonestComputeCopy(read('docs/ATLAS-CLOUD-GUIDE.md'));
|
||||
}],
|
||||
['harness docs route generic open-source model intent without lock-in', () => {
|
||||
assertHonestComputeCopy(read('.claude-plugin/README.md'));
|
||||
assertHonestComputeCopy(read('.kimi/README.md'));
|
||||
}],
|
||||
['Phase 2 plan keeps its thesis and release framing generic', () => {
|
||||
const plan = read('docs/design/ecc-ito-compute-integration.md');
|
||||
assert.match(plan, /-> any open-source model/);
|
||||
assert.doesNotMatch(plan, /public Kimi|Moonshot|video and sponsorship/i);
|
||||
assert.match(plan, /Status: \*\*Proposed/);
|
||||
}],
|
||||
['top-level CLI help exposes the provider-neutral compute route', () => {
|
||||
const result = spawnSync('node', ['scripts/ecc.js', '--help'], {
|
||||
cwd: REPO_ROOT,
|
||||
encoding: 'utf8',
|
||||
});
|
||||
assert.strictEqual(result.status, 0, result.stderr);
|
||||
assertHonestComputeCopy(result.stdout);
|
||||
}],
|
||||
['installer help and human dry-run expose the compute route', () => {
|
||||
const help = spawnSync('node', ['scripts/install-apply.js', '--help'], {
|
||||
cwd: REPO_ROOT,
|
||||
encoding: 'utf8',
|
||||
});
|
||||
assert.strictEqual(help.status, 0, help.stderr);
|
||||
assertHonestComputeCopy(help.stdout);
|
||||
|
||||
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-ito-home-'));
|
||||
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-ito-project-'));
|
||||
try {
|
||||
const dryRun = spawnSync(
|
||||
'node',
|
||||
[path.join(REPO_ROOT, 'scripts', 'install-apply.js'), '--profile', 'minimal', '--dry-run'],
|
||||
{
|
||||
cwd: projectDir,
|
||||
env: { ...process.env, HOME: homeDir },
|
||||
encoding: 'utf8',
|
||||
}
|
||||
);
|
||||
assert.strictEqual(dryRun.status, 0, dryRun.stderr);
|
||||
assertHonestComputeCopy(dryRun.stdout);
|
||||
} finally {
|
||||
fs.rmSync(homeDir, { recursive: true, force: true });
|
||||
fs.rmSync(projectDir, { recursive: true, force: true });
|
||||
}
|
||||
}],
|
||||
['npm package publishes the Ito mark and welcome route', () => {
|
||||
const packageJson = JSON.parse(read('package.json'));
|
||||
assert.ok(packageJson.files.includes('assets/images/sponsors/'));
|
||||
assertExactComputeRoute(packageJson.scripts.welcome);
|
||||
assert.match(packageJson.scripts.welcome, /run or self-host any open-source model/i);
|
||||
assert.ok(fs.existsSync(path.join(REPO_ROOT, 'assets', 'images', 'sponsors', 'ito.svg')));
|
||||
}],
|
||||
];
|
||||
|
||||
for (const [name, fn] of tests) {
|
||||
if (runTest(name, fn)) {
|
||||
passed += 1;
|
||||
} else {
|
||||
failed += 1;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -83,6 +83,7 @@ function buildExpectedPublishPaths(repoRoot) {
|
||||
"VERSION",
|
||||
"assets/ecc-icon.svg",
|
||||
"assets/hero.png",
|
||||
"assets/images/sponsors",
|
||||
]
|
||||
const exclusionPaths = [
|
||||
"!**/__pycache__/**",
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
"""Tests for provider-selection compute guidance."""
|
||||
|
||||
import importlib.util
|
||||
import re
|
||||
from pathlib import Path
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
SELECTOR_PATH = Path(__file__).parents[1] / "src" / "llm" / "cli" / "selector.py"
|
||||
SPEC = importlib.util.spec_from_file_location("ecc_selector", SELECTOR_PATH)
|
||||
assert SPEC is not None and SPEC.loader is not None
|
||||
SELECTOR = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(SELECTOR)
|
||||
print_self_host_compute_notice = SELECTOR.print_self_host_compute_notice
|
||||
|
||||
URL_TOKEN_PATTERN = re.compile(r"https?://[^\s<>\"'`()\[\]{}\\]+")
|
||||
EXPECTED_COMPUTE_ROUTE = (
|
||||
"https",
|
||||
"compute.itomarkets.com",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
)
|
||||
|
||||
|
||||
def assert_exact_compute_route(content: str) -> None:
|
||||
candidates = URL_TOKEN_PATTERN.findall(content)
|
||||
routes = (
|
||||
urlsplit(candidate.rstrip(".,;:!?"))
|
||||
for candidate in candidates
|
||||
)
|
||||
assert any(route == EXPECTED_COMPUTE_ROUTE for route in routes), (
|
||||
"Should include the exact Itô compute route"
|
||||
)
|
||||
|
||||
|
||||
def test_compute_route_validation_rejects_deceptive_lookalike_host():
|
||||
deceptive_output = "https://compute.itomarkets.com.attacker.example"
|
||||
|
||||
with pytest.raises(AssertionError, match="exact Itô compute route"):
|
||||
assert_exact_compute_route(deceptive_output)
|
||||
|
||||
|
||||
def test_ollama_notice_routes_to_ito_without_claiming_serving(capsys):
|
||||
print_self_host_compute_notice("ollama")
|
||||
|
||||
output = capsys.readouterr().out
|
||||
assert_exact_compute_route(output)
|
||||
assert "preferred compute sponsor" in output
|
||||
assert "Any GPU provider works" in output
|
||||
assert "Managed inference through Itô is not live yet" in output
|
||||
|
||||
|
||||
def test_managed_provider_does_not_show_self_host_compute_notice(capsys):
|
||||
print_self_host_compute_notice("openai")
|
||||
|
||||
assert capsys.readouterr().out == ""
|
||||
@@ -622,7 +622,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"entities@npm:^4.4.0":
|
||||
"entities@npm:^4.5.0":
|
||||
version: 4.5.0
|
||||
resolution: "entities@npm:4.5.0"
|
||||
checksum: 10c0/5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250
|
||||
@@ -801,10 +801,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-uri@npm:^3.0.1":
|
||||
version: 3.1.2
|
||||
resolution: "fast-uri@npm:3.1.2"
|
||||
checksum: 10c0/5b35641895959f3f7ab7a7b1b5542bded159346f25ec9f256817b206d50b64eda5828e90d605a2e2fc645c90519a7259c2bab2c942ee728c88b88e5be21b090d
|
||||
"fast-uri@npm:3.1.4":
|
||||
version: 3.1.4
|
||||
resolution: "fast-uri@npm:3.1.4"
|
||||
checksum: 10c0/f90948821ceb49980f64f89b8216ba498f5957f26035be813526a55b6145d26cbd63ef5618d5205a3292b31edc9c08589749350cd72bd86c7095eb434dceb757
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1066,14 +1066,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"js-yaml@npm:>=4.2.0":
|
||||
version: 4.2.0
|
||||
resolution: "js-yaml@npm:4.2.0"
|
||||
"js-yaml@npm:4.3.0":
|
||||
version: 4.3.0
|
||||
resolution: "js-yaml@npm:4.3.0"
|
||||
dependencies:
|
||||
argparse: "npm:^2.0.1"
|
||||
bin:
|
||||
js-yaml: bin/js-yaml.js
|
||||
checksum: 10c0/1916456c118746603b067d74bbcbb0445d9a1d5e474ad4ae775e7b20525bed902e01d9d97dd0c81fcd8d4f596162309d0eb057f4aa38f3e9647f14075e9dea45
|
||||
checksum: 10c0/058b30473d6915ca5b4feb11e2f7d4d97242f98d00a798ed48dd90b46b7c640398afe9128c5db22c5300f8c6528fe2a174b9a93f351a70ebc28c6203938d8bff
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1156,12 +1156,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"linkify-it@npm:^5.0.1":
|
||||
version: 5.0.1
|
||||
resolution: "linkify-it@npm:5.0.1"
|
||||
"linkify-it@npm:^5.0.2":
|
||||
version: 5.0.2
|
||||
resolution: "linkify-it@npm:5.0.2"
|
||||
dependencies:
|
||||
uc.micro: "npm:^2.0.0"
|
||||
checksum: 10c0/d06d04f1ed03be131740fc900a5e74ea1f49886b052213599e306d469d5ffe2303db76dd8f771de9f28e2b0b38852de22ec46ae597d245f8b66439b0ceb19b10
|
||||
checksum: 10c0/dd70b1735a13d41a2cff0a058ac3771166038f23f6aff004dd53873cf985c64b107902fe0b544a5b3d1ff6e63249cf9c648fb3ae9f285481db48f56887adb0d6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1190,19 +1190,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"markdown-it@npm:>=14.2.0":
|
||||
version: 14.2.0
|
||||
resolution: "markdown-it@npm:14.2.0"
|
||||
"markdown-it@npm:14.3.0":
|
||||
version: 14.3.0
|
||||
resolution: "markdown-it@npm:14.3.0"
|
||||
dependencies:
|
||||
argparse: "npm:^2.0.1"
|
||||
entities: "npm:^4.4.0"
|
||||
linkify-it: "npm:^5.0.1"
|
||||
entities: "npm:^4.5.0"
|
||||
linkify-it: "npm:^5.0.2"
|
||||
mdurl: "npm:^2.0.0"
|
||||
punycode.js: "npm:^2.3.1"
|
||||
uc.micro: "npm:^2.1.0"
|
||||
bin:
|
||||
markdown-it: bin/markdown-it.mjs
|
||||
checksum: 10c0/1d3a50061d2fe4efbcf317aac853dbee6892ed6f5a217570eead723f2ef2dd1c9baaeef5a687cd283480c45c2d20724a73e84a9ed72843cf7b3b719067af40ef
|
||||
checksum: 10c0/b2dea908968109d6e9088ac972254bca842157d85d2e6838d0eb263cd8106e7e6a72663b138366cc98f57441d9f3f2ebfb842bf7b2f9e1c13187ebe70e0af8f9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user