@lampdotdev/lamp 0.0.0-stage → 0.36.2-nightly.16
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/LICENSE +21 -0
- package/README.md +397 -2
- package/Resources/Devices/roku.json +410 -0
- package/Resources/Devices/xbox-one.json +367 -0
- package/Resources/GameKit/NOTICE.md +63 -0
- package/Resources/GameKit/apple/LampPage.swift +1813 -0
- package/Resources/GameKit/apple/LampPlayer.swift +46 -0
- package/Resources/GameKit/apple/LampWebApp.swift +63 -0
- package/Resources/GameKit/apple/LampWebGame.swift +87 -0
- package/Resources/GameKit/apple/Native.swift +12 -0
- package/Resources/GameKit/build.sh +55 -0
- package/Resources/GameKit/lamp_game.h +116 -0
- package/Resources/GameKit/lamp_host.h +19 -0
- package/Resources/GameKit/lamp_kit.cpp +61 -0
- package/Resources/GameKit/lamp_sound.cpp +455 -0
- package/Resources/GameKit/lamp_xbox.cpp +374 -0
- package/Resources/GameKit/libraries/HandmadeMath.h +3940 -0
- package/Resources/GameKit/libraries/cgltf.h +7240 -0
- package/Resources/GameKit/libraries/dr_mp3.h +5430 -0
- package/Resources/GameKit/libraries/dr_wav.h +9209 -0
- package/Resources/GameKit/libraries/sokol_debugtext.h +4754 -0
- package/Resources/GameKit/libraries/sokol_gfx.h +29558 -0
- package/Resources/GameKit/libraries/sokol_gl.h +4538 -0
- package/Resources/GameKit/libraries/sokol_log.h +335 -0
- package/Resources/GameKit/libraries/sokol_shape.h +1531 -0
- package/Resources/GameKit/libraries/stb_image.h +7988 -0
- package/Resources/GameKit/libraries/stb_vorbis.c +5584 -0
- package/Resources/GameKit/page/lamp-live.js +672 -0
- package/Resources/GameKit/scaffold/Game/game.cpp +142 -0
- package/Resources/GameKit/scaffold/Game/scene.glsl +49 -0
- package/Resources/GameKit/scaffold-web/Web/game.js +31 -0
- package/Resources/GameKit/scaffold-web/Web/index.html +13 -0
- package/Resources/GameKit/scaffold-web/Web/making.js +33 -0
- package/Resources/GameKit/scaffold-web/Web/world.js +33 -0
- package/Resources/GameKit/web/lamp-game.js +3042 -0
- package/Resources/GameKit/web/lamp-phaser.js +128 -0
- package/Resources/WebHost/App.exe +0 -0
- package/Resources/WebHost/Microsoft.Web.WebView2.Core.dll +0 -0
- package/Resources/WebHost/WebView2-LICENSE.txt +27 -0
- package/Resources/WebHost/lamp_controllers.h +1506 -0
- package/Resources/WebHost/lamp_web_host.cpp +1173 -0
- package/Resources/WebLibraries/earlier.txt +318 -0
- package/Resources/WebLibraries/phaser/LICENSE.md +20 -0
- package/Resources/WebLibraries/phaser/NOTICE.md +2 -0
- package/Resources/WebLibraries/phaser/phaser.esm.min.js +1 -0
- package/Resources/WebLibraries/qrcode/LICENSE +21 -0
- package/Resources/WebLibraries/qrcode/NOTICE.md +4 -0
- package/Resources/WebLibraries/qrcode/qrcode.js +2297 -0
- package/Resources/WebLibraries/rapier/LICENSE +201 -0
- package/Resources/WebLibraries/rapier/NOTICE.md +3 -0
- package/Resources/WebLibraries/rapier/rapier.js +2 -0
- package/Resources/WebLibraries/three/LICENSE +21 -0
- package/Resources/WebLibraries/three/NOTICE.md +4 -0
- package/Resources/WebLibraries/three/addons/animation/AnimationClipCreator.js +168 -0
- package/Resources/WebLibraries/three/addons/animation/CCDIKSolver.js +607 -0
- package/Resources/WebLibraries/three/addons/controls/ArcballControls.js +3543 -0
- package/Resources/WebLibraries/three/addons/controls/DragControls.js +452 -0
- package/Resources/WebLibraries/three/addons/controls/FirstPersonControls.js +512 -0
- package/Resources/WebLibraries/three/addons/controls/FlyControls.js +384 -0
- package/Resources/WebLibraries/three/addons/controls/MapControls.js +116 -0
- package/Resources/WebLibraries/three/addons/controls/OrbitControls.js +1985 -0
- package/Resources/WebLibraries/three/addons/controls/PointerLockControls.js +264 -0
- package/Resources/WebLibraries/three/addons/controls/TrackballControls.js +1106 -0
- package/Resources/WebLibraries/three/addons/controls/TransformControls.js +2003 -0
- package/Resources/WebLibraries/three/addons/curves/CurveExtras.js +694 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSCurve.js +169 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSSurface.js +98 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSUtils.js +532 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSVolume.js +82 -0
- package/Resources/WebLibraries/three/addons/effects/AnaglyphEffect.js +274 -0
- package/Resources/WebLibraries/three/addons/effects/AsciiEffect.js +323 -0
- package/Resources/WebLibraries/three/addons/effects/OutlineEffect.js +489 -0
- package/Resources/WebLibraries/three/addons/effects/ParallaxBarrierEffect.js +155 -0
- package/Resources/WebLibraries/three/addons/effects/StereoEffect.js +91 -0
- package/Resources/WebLibraries/three/addons/environments/ColorEnvironment.js +59 -0
- package/Resources/WebLibraries/three/addons/environments/DebugEnvironment.js +102 -0
- package/Resources/WebLibraries/three/addons/environments/RoomEnvironment.js +185 -0
- package/Resources/WebLibraries/three/addons/geometries/BoxLineGeometry.js +92 -0
- package/Resources/WebLibraries/three/addons/geometries/ConvexGeometry.js +72 -0
- package/Resources/WebLibraries/three/addons/geometries/DecalGeometry.js +420 -0
- package/Resources/WebLibraries/three/addons/geometries/LoftGeometry.js +355 -0
- package/Resources/WebLibraries/three/addons/geometries/ParametricFunctions.js +100 -0
- package/Resources/WebLibraries/three/addons/geometries/ParametricGeometry.js +172 -0
- package/Resources/WebLibraries/three/addons/geometries/RoundedBoxGeometry.js +216 -0
- package/Resources/WebLibraries/three/addons/geometries/TeapotGeometry.js +689 -0
- package/Resources/WebLibraries/three/addons/geometries/TextGeometry.js +102 -0
- package/Resources/WebLibraries/three/addons/helpers/AnimationPathHelper.js +302 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelper.js +166 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelperWebGL.js +221 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeHelper.js +166 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeHelperGPU.js +102 -0
- package/Resources/WebLibraries/three/addons/helpers/OctreeHelper.js +109 -0
- package/Resources/WebLibraries/three/addons/helpers/PositionalAudioHelper.js +169 -0
- package/Resources/WebLibraries/three/addons/helpers/RapierHelper.js +59 -0
- package/Resources/WebLibraries/three/addons/helpers/RectAreaLightHelper.js +118 -0
- package/Resources/WebLibraries/three/addons/helpers/TextureHelper.js +265 -0
- package/Resources/WebLibraries/three/addons/helpers/TextureHelperGPU.js +214 -0
- package/Resources/WebLibraries/three/addons/helpers/VertexNormalsHelper.js +155 -0
- package/Resources/WebLibraries/three/addons/helpers/VertexTangentsHelper.js +133 -0
- package/Resources/WebLibraries/three/addons/helpers/ViewHelper.js +529 -0
- package/Resources/WebLibraries/three/addons/interactive/HTMLMesh.js +617 -0
- package/Resources/WebLibraries/three/addons/interactive/InteractiveGroup.js +224 -0
- package/Resources/WebLibraries/three/addons/interactive/SelectionBox.js +324 -0
- package/Resources/WebLibraries/three/addons/interactive/SelectionHelper.js +150 -0
- package/Resources/WebLibraries/three/addons/libs/fflate.module.js +2699 -0
- package/Resources/WebLibraries/three/addons/libs/lil-gui.module.min.js +8 -0
- package/Resources/WebLibraries/three/addons/libs/meshopt_decoder.module.js +196 -0
- package/Resources/WebLibraries/three/addons/libs/potpack.module.js +125 -0
- package/Resources/WebLibraries/three/addons/libs/stats.module.js +167 -0
- package/Resources/WebLibraries/three/addons/libs/tween.module.js +876 -0
- package/Resources/WebLibraries/three/addons/lighting/ClusteredLighting.js +153 -0
- package/Resources/WebLibraries/three/addons/lighting/DynamicLighting.js +82 -0
- package/Resources/WebLibraries/three/addons/lighting/LightMapper.js +295 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGrid.js +923 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGridUtils.js +107 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGridWebGL.js +846 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIConeTracer.js +243 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIIrradiance.js +43 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGINode.js +617 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGISceneCollector.js +793 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIVolume.js +1440 -0
- package/Resources/WebLibraries/three/addons/lights/LightProbeGenerator.js +337 -0
- package/Resources/WebLibraries/three/addons/lights/RectAreaLightTexturesLib.js +127 -0
- package/Resources/WebLibraries/three/addons/lights/RectAreaLightUniformsLib.js +40 -0
- package/Resources/WebLibraries/three/addons/lights/SunLight.js +100 -0
- package/Resources/WebLibraries/three/addons/lights/SunLightNode.js +56 -0
- package/Resources/WebLibraries/three/addons/lights/SunLightShadow.js +319 -0
- package/Resources/WebLibraries/three/addons/lights/SunShadowNode.js +312 -0
- package/Resources/WebLibraries/three/addons/lines/Line2.js +56 -0
- package/Resources/WebLibraries/three/addons/lines/LineGeometry.js +157 -0
- package/Resources/WebLibraries/three/addons/lines/LineMaterial.js +742 -0
- package/Resources/WebLibraries/three/addons/lines/LineSegments2.js +434 -0
- package/Resources/WebLibraries/three/addons/lines/LineSegmentsGeometry.js +298 -0
- package/Resources/WebLibraries/three/addons/lines/Wireframe.js +108 -0
- package/Resources/WebLibraries/three/addons/lines/WireframeGeometry2.js +49 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/Line2.js +46 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/LineSegments2.js +419 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/Wireframe.js +86 -0
- package/Resources/WebLibraries/three/addons/loaders/EXRLoader.js +3411 -0
- package/Resources/WebLibraries/three/addons/loaders/FBXLoader.js +4660 -0
- package/Resources/WebLibraries/three/addons/loaders/FontLoader.js +262 -0
- package/Resources/WebLibraries/three/addons/loaders/GLTFLoader.js +5006 -0
- package/Resources/WebLibraries/three/addons/loaders/HDRLoader.js +463 -0
- package/Resources/WebLibraries/three/addons/loaders/MTLLoader.js +601 -0
- package/Resources/WebLibraries/three/addons/loaders/OBJLoader.js +961 -0
- package/Resources/WebLibraries/three/addons/loaders/PLYLoader.js +992 -0
- package/Resources/WebLibraries/three/addons/loaders/RGBELoader.js +18 -0
- package/Resources/WebLibraries/three/addons/loaders/STLLoader.js +423 -0
- package/Resources/WebLibraries/three/addons/loaders/SVGLoader.js +3297 -0
- package/Resources/WebLibraries/three/addons/loaders/TGALoader.js +539 -0
- package/Resources/WebLibraries/three/addons/loaders/UltraHDRLoader.js +757 -0
- package/Resources/WebLibraries/three/addons/math/Capsule.js +159 -0
- package/Resources/WebLibraries/three/addons/math/ColorConverter.js +62 -0
- package/Resources/WebLibraries/three/addons/math/ColorSpaces.js +147 -0
- package/Resources/WebLibraries/three/addons/math/ConvexHull.js +1695 -0
- package/Resources/WebLibraries/three/addons/math/ImprovedNoise.js +88 -0
- package/Resources/WebLibraries/three/addons/math/Lut.js +317 -0
- package/Resources/WebLibraries/three/addons/math/MeshSurfaceSampler.js +315 -0
- package/Resources/WebLibraries/three/addons/math/OBB.js +535 -0
- package/Resources/WebLibraries/three/addons/math/Octree.js +825 -0
- package/Resources/WebLibraries/three/addons/math/SimplexNoise.js +470 -0
- package/Resources/WebLibraries/three/addons/misc/ConvexObjectBreaker.js +539 -0
- package/Resources/WebLibraries/three/addons/misc/GPUComputationRenderer.js +508 -0
- package/Resources/WebLibraries/three/addons/misc/Gyroscope.js +78 -0
- package/Resources/WebLibraries/three/addons/misc/MorphAnimMesh.js +119 -0
- package/Resources/WebLibraries/three/addons/misc/MorphBlendMesh.js +425 -0
- package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMap.js +370 -0
- package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMapGPU.js +322 -0
- package/Resources/WebLibraries/three/addons/misc/RollerCoaster.js +661 -0
- package/Resources/WebLibraries/three/addons/misc/Sculptor.js +1679 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorMesh.js +1504 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorTools.js +1180 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorUtils.js +345 -0
- package/Resources/WebLibraries/three/addons/misc/TileCreasedNormalsPlugin.js +270 -0
- package/Resources/WebLibraries/three/addons/misc/TubePainter.js +611 -0
- package/Resources/WebLibraries/three/addons/misc/Volume.js +520 -0
- package/Resources/WebLibraries/three/addons/misc/VolumeSlice.js +275 -0
- package/Resources/WebLibraries/three/addons/modifiers/CurveModifier.js +374 -0
- package/Resources/WebLibraries/three/addons/modifiers/CurveModifierGPU.js +256 -0
- package/Resources/WebLibraries/three/addons/modifiers/EdgeSplitModifier.js +299 -0
- package/Resources/WebLibraries/three/addons/modifiers/TessellateModifier.js +340 -0
- package/Resources/WebLibraries/three/addons/objects/GroundedSkybox.js +69 -0
- package/Resources/WebLibraries/three/addons/objects/Lensflare.js +489 -0
- package/Resources/WebLibraries/three/addons/objects/LensflareMesh.js +376 -0
- package/Resources/WebLibraries/three/addons/objects/MarchingCubes.js +1261 -0
- package/Resources/WebLibraries/three/addons/objects/Reflector.js +390 -0
- package/Resources/WebLibraries/three/addons/objects/ReflectorForSSRPass.js +393 -0
- package/Resources/WebLibraries/three/addons/objects/Refractor.js +389 -0
- package/Resources/WebLibraries/three/addons/objects/ShadowMesh.js +130 -0
- package/Resources/WebLibraries/three/addons/objects/Sky.js +342 -0
- package/Resources/WebLibraries/three/addons/objects/SkyMesh.js +403 -0
- package/Resources/WebLibraries/three/addons/objects/Water.js +374 -0
- package/Resources/WebLibraries/three/addons/objects/Water2.js +403 -0
- package/Resources/WebLibraries/three/addons/objects/Water2Mesh.js +199 -0
- package/Resources/WebLibraries/three/addons/objects/WaterMesh.js +194 -0
- package/Resources/WebLibraries/three/addons/postprocessing/AfterimagePass.js +187 -0
- package/Resources/WebLibraries/three/addons/postprocessing/BloomPass.js +274 -0
- package/Resources/WebLibraries/three/addons/postprocessing/BokehPass.js +218 -0
- package/Resources/WebLibraries/three/addons/postprocessing/ClearPass.js +97 -0
- package/Resources/WebLibraries/three/addons/postprocessing/CubeTexturePass.js +146 -0
- package/Resources/WebLibraries/three/addons/postprocessing/DotScreenPass.js +114 -0
- package/Resources/WebLibraries/three/addons/postprocessing/EffectComposer.js +365 -0
- package/Resources/WebLibraries/three/addons/postprocessing/FXAAPass.js +40 -0
- package/Resources/WebLibraries/three/addons/postprocessing/FilmPass.js +113 -0
- package/Resources/WebLibraries/three/addons/postprocessing/GTAOPass.js +735 -0
- package/Resources/WebLibraries/three/addons/postprocessing/GlitchPass.js +177 -0
- package/Resources/WebLibraries/three/addons/postprocessing/HalftonePass.js +134 -0
- package/Resources/WebLibraries/three/addons/postprocessing/LUTPass.js +138 -0
- package/Resources/WebLibraries/three/addons/postprocessing/MaskPass.js +195 -0
- package/Resources/WebLibraries/three/addons/postprocessing/OutlinePass.js +776 -0
- package/Resources/WebLibraries/three/addons/postprocessing/OutputPass.js +148 -0
- package/Resources/WebLibraries/three/addons/postprocessing/Pass.js +191 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderPass.js +193 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderPixelatedPass.js +314 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderTransitionPass.js +267 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SAOPass.js +407 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SMAAPass.js +230 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSAARenderPass.js +313 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSAOPass.js +527 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSRPass.js +858 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SavePass.js +132 -0
- package/Resources/WebLibraries/three/addons/postprocessing/ShaderPass.js +135 -0
- package/Resources/WebLibraries/three/addons/postprocessing/TAARenderPass.js +243 -0
- package/Resources/WebLibraries/three/addons/postprocessing/TexturePass.js +131 -0
- package/Resources/WebLibraries/three/addons/postprocessing/UnrealBloomPass.js +541 -0
- package/Resources/WebLibraries/three/addons/shaders/ACESFilmicToneMappingShader.js +96 -0
- package/Resources/WebLibraries/three/addons/shaders/AfterimageShader.js +63 -0
- package/Resources/WebLibraries/three/addons/shaders/BasicShader.js +36 -0
- package/Resources/WebLibraries/three/addons/shaders/BleachBypassShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/BlendShader.js +56 -0
- package/Resources/WebLibraries/three/addons/shaders/BokehShader.js +151 -0
- package/Resources/WebLibraries/three/addons/shaders/BokehShader2.js +404 -0
- package/Resources/WebLibraries/three/addons/shaders/BrightnessContrastShader.js +62 -0
- package/Resources/WebLibraries/three/addons/shaders/ColorCorrectionShader.js +59 -0
- package/Resources/WebLibraries/three/addons/shaders/ColorifyShader.js +57 -0
- package/Resources/WebLibraries/three/addons/shaders/ConvolutionShader.js +74 -0
- package/Resources/WebLibraries/three/addons/shaders/CopyShader.js +52 -0
- package/Resources/WebLibraries/three/addons/shaders/DOFMipMapShader.js +63 -0
- package/Resources/WebLibraries/three/addons/shaders/DepthLimitedBlurShader.js +183 -0
- package/Resources/WebLibraries/three/addons/shaders/DigitalGlitch.js +104 -0
- package/Resources/WebLibraries/three/addons/shaders/DotScreenShader.js +75 -0
- package/Resources/WebLibraries/three/addons/shaders/ExposureShader.js +51 -0
- package/Resources/WebLibraries/three/addons/shaders/FXAAShader.js +298 -0
- package/Resources/WebLibraries/three/addons/shaders/FilmShader.js +73 -0
- package/Resources/WebLibraries/three/addons/shaders/FocusShader.js +94 -0
- package/Resources/WebLibraries/three/addons/shaders/FreiChenShader.js +103 -0
- package/Resources/WebLibraries/three/addons/shaders/GTAOShader.js +437 -0
- package/Resources/WebLibraries/three/addons/shaders/GammaCorrectionShader.js +52 -0
- package/Resources/WebLibraries/three/addons/shaders/HalftoneShader.js +332 -0
- package/Resources/WebLibraries/three/addons/shaders/HorizontalBlurShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/HorizontalTiltShiftShader.js +70 -0
- package/Resources/WebLibraries/three/addons/shaders/HueSaturationShader.js +74 -0
- package/Resources/WebLibraries/three/addons/shaders/KaleidoShader.js +65 -0
- package/Resources/WebLibraries/three/addons/shaders/LuminosityHighPassShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/LuminosityShader.js +54 -0
- package/Resources/WebLibraries/three/addons/shaders/MirrorShader.js +62 -0
- package/Resources/WebLibraries/three/addons/shaders/NormalMapShader.js +60 -0
- package/Resources/WebLibraries/three/addons/shaders/OutputShader.js +103 -0
- package/Resources/WebLibraries/three/addons/shaders/PoissonDenoiseShader.js +230 -0
- package/Resources/WebLibraries/three/addons/shaders/RGBShiftShader.js +61 -0
- package/Resources/WebLibraries/three/addons/shaders/SAOShader.js +201 -0
- package/Resources/WebLibraries/three/addons/shaders/SMAAShader.js +489 -0
- package/Resources/WebLibraries/three/addons/shaders/SSAOShader.js +331 -0
- package/Resources/WebLibraries/three/addons/shaders/SSRShader.js +396 -0
- package/Resources/WebLibraries/three/addons/shaders/SepiaShader.js +57 -0
- package/Resources/WebLibraries/three/addons/shaders/SobelOperatorShader.js +98 -0
- package/Resources/WebLibraries/three/addons/shaders/SubsurfaceScatteringShader.js +95 -0
- package/Resources/WebLibraries/three/addons/shaders/TechnicolorShader.js +51 -0
- package/Resources/WebLibraries/three/addons/shaders/ToonShader.js +349 -0
- package/Resources/WebLibraries/three/addons/shaders/TriangleBlurShader.js +79 -0
- package/Resources/WebLibraries/three/addons/shaders/UnpackDepthRGBAShader.js +60 -0
- package/Resources/WebLibraries/three/addons/shaders/VelocityShader.js +137 -0
- package/Resources/WebLibraries/three/addons/shaders/VerticalBlurShader.js +66 -0
- package/Resources/WebLibraries/three/addons/shaders/VerticalTiltShiftShader.js +70 -0
- package/Resources/WebLibraries/three/addons/shaders/VignetteShader.js +56 -0
- package/Resources/WebLibraries/three/addons/shaders/VolumeShader.js +285 -0
- package/Resources/WebLibraries/three/addons/shaders/WaterRefractionShader.js +106 -0
- package/Resources/WebLibraries/three/addons/textures/FlakesTexture.js +54 -0
- package/Resources/WebLibraries/three/addons/tsl/WebGLNodesHandler.js +607 -0
- package/Resources/WebLibraries/three/addons/tsl/display/AfterImageNode.js +256 -0
- package/Resources/WebLibraries/three/addons/tsl/display/AnaglyphPassNode.js +550 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BilateralBlurNode.js +377 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BleachBypass.js +33 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BloomNode.js +599 -0
- package/Resources/WebLibraries/three/addons/tsl/display/CRT.js +150 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ChromaticAberrationNode.js +163 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DenoiseNode.js +354 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DepthOfFieldNode.js +572 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DotScreenNode.js +104 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FSR1Node.js +481 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FXAANode.js +357 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FilmNode.js +101 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GTAONode.js +727 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GaussianBlurNode.js +412 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GodraysNode.js +604 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ImportanceSampledEnvironment.js +564 -0
- package/Resources/WebLibraries/three/addons/tsl/display/LensflareNode.js +282 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Lut3DNode.js +109 -0
- package/Resources/WebLibraries/three/addons/tsl/display/MotionBlur.js +33 -0
- package/Resources/WebLibraries/three/addons/tsl/display/OITPassNode.js +341 -0
- package/Resources/WebLibraries/three/addons/tsl/display/OutlineNode.js +916 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ParallaxBarrierPassNode.js +90 -0
- package/Resources/WebLibraries/three/addons/tsl/display/PixelationPassNode.js +227 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RGBShiftNode.js +96 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RecurrentDenoiseNode.js +812 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RetroPassNode.js +263 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SMAANode.js +729 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSAAPassNode.js +344 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSAONode.js +422 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSGINode.js +698 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSRNode.js +1430 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSSNode.js +479 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Sepia.js +24 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Shape.js +29 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SharpenNode.js +284 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SobelOperatorNode.js +168 -0
- package/Resources/WebLibraries/three/addons/tsl/display/StereoCompositePassNode.js +190 -0
- package/Resources/WebLibraries/three/addons/tsl/display/StereoPassNode.js +117 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TAAUNode.js +700 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TRAANode.js +609 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TemporalReprojectNode.js +1024 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TransitionNode.js +141 -0
- package/Resources/WebLibraries/three/addons/tsl/display/boxBlur.js +65 -0
- package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlend.js +80 -0
- package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlur.js +63 -0
- package/Resources/WebLibraries/three/addons/tsl/display/hashBlur.js +55 -0
- package/Resources/WebLibraries/three/addons/tsl/display/lensDirt.js +30 -0
- package/Resources/WebLibraries/three/addons/tsl/display/radialBlur.js +68 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/ClusteredLightsNode.js +994 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/DynamicLightsNode.js +201 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/LightProbeGridNode.js +183 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/AmbientLightDataNode.js +67 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/DirectionalLightDataNode.js +117 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/HemisphereLightDataNode.js +105 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/PointLightDataNode.js +140 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/SpotLightDataNode.js +167 -0
- package/Resources/WebLibraries/three/addons/tsl/math/Bayer.js +84 -0
- package/Resources/WebLibraries/three/addons/tsl/math/curlNoise.js +107 -0
- package/Resources/WebLibraries/three/addons/tsl/math/voronoiNoise.js +112 -0
- package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNode.js +542 -0
- package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNodeHelper.js +212 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/GroundedSkybox.js +62 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/RNoise.js +51 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/Raymarching.js +70 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/SoftParticles.js +53 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/SpecularHelpers.js +302 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/TAAUtils.js +184 -0
- package/Resources/WebLibraries/three/addons/utils/BufferGeometryUtils.js +1523 -0
- package/Resources/WebLibraries/three/addons/utils/CameraUtils.js +82 -0
- package/Resources/WebLibraries/three/addons/utils/ColorUtils.js +76 -0
- package/Resources/WebLibraries/three/addons/utils/GaussianSplatUtils.js +229 -0
- package/Resources/WebLibraries/three/addons/utils/GeometryCompressionUtils.js +547 -0
- package/Resources/WebLibraries/three/addons/utils/GeometryUtils.js +226 -0
- package/Resources/WebLibraries/three/addons/utils/LDrawUtils.js +211 -0
- package/Resources/WebLibraries/three/addons/utils/SceneOptimizer.js +459 -0
- package/Resources/WebLibraries/three/addons/utils/SceneUtils.js +363 -0
- package/Resources/WebLibraries/three/addons/utils/ShadowMapViewer.js +244 -0
- package/Resources/WebLibraries/three/addons/utils/ShadowMapViewerGPU.js +233 -0
- package/Resources/WebLibraries/three/addons/utils/SkeletonUtils.js +496 -0
- package/Resources/WebLibraries/three/addons/utils/SortUtils.js +175 -0
- package/Resources/WebLibraries/three/addons/utils/UVsDebug.js +173 -0
- package/Resources/WebLibraries/three/addons/utils/WebGLTextureUtils.js +115 -0
- package/Resources/WebLibraries/three/addons/utils/WebGPUTextureUtils.js +81 -0
- package/Resources/WebLibraries/three/addons/utils/WorkerPool.js +167 -0
- package/Resources/WebLibraries/three/addons/utils/unwrapUVs.js +865 -0
- package/Resources/WebLibraries/three/three.core.js +61162 -0
- package/Resources/WebLibraries/three/three.module.js +19537 -0
- package/Resources/WebLibraries/three/three.tsl.js +41903 -0
- package/Resources/WebLibraries/three/three.webgpu.js +53714 -0
- package/Resources/share-rules.json +64 -0
- package/Resources/skills/2d-game/SKILL.md +305 -0
- package/Resources/skills/3d-game/SKILL.md +274 -0
- package/Resources/skills/accounts/SKILL.md +41 -0
- package/Resources/skills/android-design/SKILL.md +159 -0
- package/Resources/skills/app-ai/SKILL.md +154 -0
- package/Resources/skills/app-intents/SKILL.md +31 -0
- package/Resources/skills/app-kinds/SKILL.md +122 -0
- package/Resources/skills/apple-watch/SKILL.md +43 -0
- package/Resources/skills/assets/SKILL.md +183 -0
- package/Resources/skills/building-blocks/SKILL.md +97 -0
- package/Resources/skills/device-control/SKILL.md +56 -0
- package/Resources/skills/device-integrations/SKILL.md +278 -0
- package/Resources/skills/finder-files/SKILL.md +19 -0
- package/Resources/skills/game/SKILL.md +416 -0
- package/Resources/skills/game-3d/SKILL.md +12 -0
- package/Resources/skills/game-art/SKILL.md +11 -0
- package/Resources/skills/game-feel/SKILL.md +13 -0
- package/Resources/skills/game-levels/SKILL.md +12 -0
- package/Resources/skills/game-live/SKILL.md +12 -0
- package/Resources/skills/game-physics/SKILL.md +13 -0
- package/Resources/skills/game-playtest/SKILL.md +26 -0
- package/Resources/skills/game-ui/SKILL.md +278 -0
- package/Resources/skills/github-projects/SKILL.md +62 -0
- package/Resources/skills/icloud-sync/SKILL.md +30 -0
- package/Resources/skills/iphone-hardware/SKILL.md +57 -0
- package/Resources/skills/iphone-widgets/SKILL.md +53 -0
- package/Resources/skills/lg-developer-mode/SKILL.md +152 -0
- package/Resources/skills/mac-widgets/SKILL.md +60 -0
- package/Resources/skills/maps/SKILL.md +8 -0
- package/Resources/skills/menu-bar/SKILL.md +36 -0
- package/Resources/skills/more-apps/SKILL.md +53 -0
- package/Resources/skills/phone-controllers/SKILL.md +79 -0
- package/Resources/skills/phone-pages/SKILL.md +173 -0
- package/Resources/skills/roku-developer-mode/SKILL.md +106 -0
- package/Resources/skills/scene-3d/SKILL.md +27 -0
- package/Resources/skills/scripting/SKILL.md +17 -0
- package/Resources/skills/share-extension/SKILL.md +22 -0
- package/Resources/skills/tv-design/SKILL.md +72 -0
- package/Resources/skills/web-app/SKILL.md +170 -0
- package/Resources/skills/web-game/SKILL.md +95 -0
- package/Resources/skills/web-or-native/SKILL.md +108 -0
- package/Resources/skills/wish-links/SKILL.md +156 -0
- package/THIRD_PARTY_NOTICES.md +170 -0
- package/cli/ai.mjs +237 -0
- package/cli/android.mjs +941 -0
- package/cli/app-ai.mjs +473 -0
- package/cli/browser.mjs +284 -0
- package/cli/calls.mjs +594 -0
- package/cli/dev.mjs +820 -0
- package/cli/devices.mjs +984 -0
- package/cli/lamp.mjs +1326 -0
- package/cli/lampapp.mjs +332 -0
- package/cli/lamps/android-host/LampPageGateway.kt +345 -0
- package/cli/lamps/android-host/app/build.gradle.kts +40 -0
- package/cli/lamps/android-host/build.gradle.kts +4 -0
- package/cli/lamps/android-host/game/AndroidManifest.xml +33 -0
- package/cli/lamps/android-host/game/MainActivity.kt +173 -0
- package/cli/lamps/android-host/gradle/libs.versions.toml +39 -0
- package/cli/lamps/android-host/gradle.properties +8 -0
- package/cli/lamps/android-host/page/AndroidManifest.xml +35 -0
- package/cli/lamps/android-host/page/MainActivity.kt +193 -0
- package/cli/lamps/android-host/settings.gradle.kts +30 -0
- package/cli/lamps/android-host/tools.json +43 -0
- package/cli/lamps/lamp-controllers.js +2 -0
- package/cli/lamps/lamp-for-games.js +6922 -0
- package/cli/lamps/lamp.js +7082 -0
- package/cli/lamps/mac-starter/.lamp/meta.json +1 -0
- package/cli/lamps/mac-starter/APP.md +12 -0
- package/cli/lamps/mac-starter/Package.swift +8 -0
- package/cli/lamps/mac-starter/Sources/App.swift +11 -0
- package/cli/lamps/mac-starter/Sources/ContentView.swift +17 -0
- package/cli/lamps/mac-starter/Sources/LampSupport.swift +18215 -0
- package/cli/lamps/mac-starter/build.sh +336 -0
- package/cli/lamps/mac-starter/gitignore +3 -0
- package/cli/lamps/mac-starter/lamp-starter.json +6 -0
- package/cli/lamps/web-starter/APP.md +8 -0
- package/cli/lamps/web-starter/app.js +1 -0
- package/cli/lamps/web-starter/index.html +17 -0
- package/cli/lamps/web-starter/lamp-starter.json +5 -0
- package/cli/lamps/web-starter/lamp.js +7082 -0
- package/cli/lamps/web-starter/style.css +25 -0
- package/cli/link.mjs +202 -0
- package/cli/local-ai.mjs +193 -0
- package/cli/mac.mjs +621 -0
- package/cli/mdns.mjs +205 -0
- package/cli/msix.mjs +413 -0
- package/cli/network.mjs +209 -0
- package/cli/openrouter.mjs +133 -0
- package/cli/outside.mjs +203 -0
- package/cli/page.js +317 -0
- package/cli/place.mjs +298 -0
- package/cli/png.mjs +184 -0
- package/cli/share.mjs +270 -0
- package/cli/skill/SKILL.md +280 -0
- package/cli/skills.mjs +71 -0
- package/cli/state.mjs +176 -0
- package/cli/update.mjs +162 -0
- package/package.json +20 -4
- package/site/lib/quota.js +59 -0
- package/site/lib/shared-wishes.js +1727 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
:root { --u: max(0.8vmin, 4px); }
|
|
2
|
+
html, body {
|
|
3
|
+
margin: 0;
|
|
4
|
+
width: 100%;
|
|
5
|
+
height: 100%;
|
|
6
|
+
overflow: hidden;
|
|
7
|
+
background: #101418;
|
|
8
|
+
color: #f2f4f6;
|
|
9
|
+
font-family: -apple-system, "Samsung One", "LG Smart UI", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
10
|
+
font-size: calc(var(--u) * 3.6);
|
|
11
|
+
}
|
|
12
|
+
#app {
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
height: 100%;
|
|
15
|
+
padding: calc(var(--u) * 5);
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
align-items: center;
|
|
20
|
+
text-align: center;
|
|
21
|
+
}
|
|
22
|
+
h1 { font-size: calc(var(--u) * 8); margin: 0 0 calc(var(--u) * 2); }
|
|
23
|
+
.status { opacity: 0.7; }
|
|
24
|
+
/* What has the remote's focus is always plain to see from the sofa. */
|
|
25
|
+
:focus { outline: calc(var(--u) * 0.6) solid #4da3ff; outline-offset: calc(var(--u) * 0.6); }
|
package/cli/link.mjs
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// lamp.dev's API for a shared link (site/lib/shared-wishes.js, which the limits here are read from), for lamp's own
|
|
2
|
+
// `share` and for Lamp's app's Share Link card alike: a link made or changed, what it has now, its file or its playable
|
|
3
|
+
// page sent in parts, the ideas people send, and taking it down. Only the link's secret changes it; the secret is
|
|
4
|
+
// whoever shared it's alone, and is kept by whoever asks, never here.
|
|
5
|
+
|
|
6
|
+
import { FILE_LIMITS, LIMITS } from "../site/lib/shared-wishes.js";
|
|
7
|
+
import { Problem } from "./state.mjs";
|
|
8
|
+
|
|
9
|
+
/** The site links are made on: lamp.dev, or another given for trying this against a copy of the site. */
|
|
10
|
+
export const siteOrigin = () => (process.env.LAMP_SITE || "https://lamp.dev").replace(/\/+$/, "");
|
|
11
|
+
|
|
12
|
+
const sleep = (ms) => new Promise((done) => setTimeout(done, ms));
|
|
13
|
+
const megabytes = (bytes) => `${(bytes / 1_000_000).toFixed(bytes < 10_000_000 ? 1 : 0)} MB`;
|
|
14
|
+
|
|
15
|
+
// What the site says when it turns something down, in plain words.
|
|
16
|
+
const REFUSALS = {
|
|
17
|
+
invalid_wish: `the site didn't take the link's words or picture (a name of at most ${LIMITS.name} characters, words of at most ${LIMITS.words}, a line of at most ${LIMITS.line})`,
|
|
18
|
+
invalid_page: "the site didn't take the page: it needs index.html at its top",
|
|
19
|
+
invalid_part: "the site didn't take a part of the page",
|
|
20
|
+
parts_missing: "a part of the page didn't reach the site: share again",
|
|
21
|
+
file_too_large: `the page is more than the ${megabytes(FILE_LIMITS.total)} a link carries, packed`,
|
|
22
|
+
rate_limited: "the site has taken as many as it takes for now: try again in a while",
|
|
23
|
+
service_unavailable: "the site can't keep it just now: try again in a moment",
|
|
24
|
+
not_found: "the link is no longer there",
|
|
25
|
+
invalid_username: "a username is 2 to 30 lowercase letters, digits and dashes, starting and ending with a letter or digit, and not one of the site's own words",
|
|
26
|
+
username_taken: "that username is someone else's: choose another",
|
|
27
|
+
invalid_email: "that isn't an email address the site can write to",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** The site couldn't be reached at all: offline, or the site is down. */
|
|
31
|
+
export class Unreachable extends Problem {}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* One request to the site. A request that's the same however often it arrives is tried again, `tries` times in all,
|
|
35
|
+
* a little later each time, when the site can't be reached or can't answer just now; any other is sent once. A refusal
|
|
36
|
+
* carries the status the site gave it. No redirect is followed: a link's secret goes to the site and nowhere else.
|
|
37
|
+
*/
|
|
38
|
+
export async function call(method, url, { secret, account, json, bytes, tries = 1, seconds = 120 } = {}) {
|
|
39
|
+
const headers = {
|
|
40
|
+
...(secret ? { authorization: `Bearer ${secret}` } : {}),
|
|
41
|
+
...(account ? { "x-lamp-account": account } : {}),
|
|
42
|
+
...(json ? { "content-type": "application/json" } : bytes ? { "content-type": "application/octet-stream" } : {}),
|
|
43
|
+
};
|
|
44
|
+
for (let attempt = 0; ; attempt++) {
|
|
45
|
+
let answer = null;
|
|
46
|
+
try { answer = await fetch(url, { method, headers, body: json ? JSON.stringify(json) : bytes, redirect: "manual", signal: AbortSignal.timeout(seconds * 1000) }); } catch {}
|
|
47
|
+
if (answer && answer.status < 500) {
|
|
48
|
+
const said = await answer.json().catch(() => null);
|
|
49
|
+
if (answer.ok) return { status: answer.status, said: said ?? {} };
|
|
50
|
+
const problem = new Problem(REFUSALS[said?.error] ?? `the site answered ${answer.status}`);
|
|
51
|
+
problem.status = answer.status;
|
|
52
|
+
throw problem;
|
|
53
|
+
}
|
|
54
|
+
if (attempt >= tries - 1) {
|
|
55
|
+
if (answer) { const problem = new Problem(REFUSALS.service_unavailable); problem.status = answer.status; throw problem; }
|
|
56
|
+
throw new Unreachable(`couldn't reach ${new URL(url).host}`);
|
|
57
|
+
}
|
|
58
|
+
await sleep(600 * 2 ** attempt);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** An address the site gave, only when it's on the site itself. */
|
|
63
|
+
function onSite(site, address) {
|
|
64
|
+
try { const url = new URL(address), home = new URL(site); return url.protocol === home.protocol && url.host === home.host ? url.href : null; } catch { return null; }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Makes the link, or changes what it shows (`earlier`: its id and secret), with `body` as the site takes it (its
|
|
69
|
+
* name, line, words, who it's by, the questions its page asks, its shape, picture and icon). A link the site no longer
|
|
70
|
+
* has is made again. Answers its id, its address and its secret.
|
|
71
|
+
*/
|
|
72
|
+
export async function publishLink({ site = siteOrigin(), body, earlier, account }) {
|
|
73
|
+
if (earlier) {
|
|
74
|
+
try {
|
|
75
|
+
const { said } = await call("PUT", `${site}/api/wishes?id=${encodeURIComponent(earlier.id)}`, { secret: earlier.secret, account, json: body });
|
|
76
|
+
// A change keeps the link; its address follows the name, so a rename shows in it (the old one still works).
|
|
77
|
+
return { id: earlier.id, url: onSite(site, said.url) ?? earlier.url ?? null, secret: earlier.secret };
|
|
78
|
+
} catch (error) { if (error.status !== 404) throw error; }
|
|
79
|
+
}
|
|
80
|
+
const { said } = await call("POST", `${site}/api/wishes`, { account, json: body });
|
|
81
|
+
const url = onSite(site, said.url);
|
|
82
|
+
if (typeof said.id !== "string" || typeof said.secret !== "string" || !url) throw new Problem("the site's answer couldn't be read");
|
|
83
|
+
return { id: said.id, url, secret: said.secret };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Asks for a maker's account (`username` and `email`), or with an address that has one, to sign in to it: answers
|
|
88
|
+
* `{ username, key, existing, sent }`. The key is the account's once the email's link is opened.
|
|
89
|
+
*/
|
|
90
|
+
export async function askAccount({ site = siteOrigin(), username, email }) {
|
|
91
|
+
const { said } = await call("POST", `${site}/api/accounts`, { json: { ...(username ? { username } : {}), email } });
|
|
92
|
+
if (typeof said.key !== "string" || typeof said.username !== "string") throw new Problem("the site's answer couldn't be read");
|
|
93
|
+
return said;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** The username a key is an account's, once the email's link was opened; null before. */
|
|
97
|
+
export async function accountName({ site = siteOrigin(), key }) {
|
|
98
|
+
const { said } = await call("GET", `${site}/api/accounts`, { secret: key, seconds: 20 });
|
|
99
|
+
return typeof said.username === "string" ? said.username : null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* What a followed link has now: its name, who it's by (null for nobody), its file's version (0 with no file), and the
|
|
104
|
+
* file's address, only from where the site keeps them. Null when it can't be asked, or is gone. Asks with nothing of
|
|
105
|
+
* the person's.
|
|
106
|
+
*/
|
|
107
|
+
export async function latestOf({ site = siteOrigin(), id, user, app }) {
|
|
108
|
+
let said;
|
|
109
|
+
const asked = id ? `id=${encodeURIComponent(id)}` : `user=${encodeURIComponent(user)}&app=${encodeURIComponent(app)}`;
|
|
110
|
+
try { ({ said } = await call("GET", `${site}/api/wishes?${asked}`)); } catch { return null; }
|
|
111
|
+
if (said.format !== 1 || !Number.isInteger(said.version)) return null;
|
|
112
|
+
let file = null;
|
|
113
|
+
try { const url = new URL(said.file); if (url.protocol === "https:" || (url.protocol === "data:" && new URL(site).protocol === "http:")) file = url.href; } catch {}
|
|
114
|
+
const by = typeof said.by === "string" ? said.by.trim().slice(0, LIMITS.by) : "";
|
|
115
|
+
return { id: typeof said.id === "string" ? said.id : id ?? null, name: typeof said.name === "string" ? said.name : null, by: by || null, version: said.version, file,
|
|
116
|
+
// Absent from a site from before that doesn't say; null while a link's first page is still being stored.
|
|
117
|
+
page: !("page" in said) ? undefined : Number.isInteger(said.page) ? said.page : null };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The site stores a page's files after it answers its last part, and the link shows the page before until they're in:
|
|
122
|
+
* waits until it shows `version` (a minute at most; a site from before that doesn't say is taken at its word).
|
|
123
|
+
*/
|
|
124
|
+
export async function pageUp({ site = siteOrigin(), id, version, said = () => {} }) {
|
|
125
|
+
for (let waited = 0; waited < 60; waited += 2) {
|
|
126
|
+
const now = await latestOf({ site, id });
|
|
127
|
+
if (!now || now.page === undefined || (Number.isInteger(now.page) && now.page >= version)) return;
|
|
128
|
+
if (waited === 0) said("Waiting for lamp.dev to put the page up…");
|
|
129
|
+
await sleep(2000);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const fileAddress = (site, id, more = "") => `${site}/api/wish-file?id=${encodeURIComponent(id)}${more}`;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Sends the link's file in parts, and has the site put them together in place of any it had: the wish's file, or with
|
|
137
|
+
* `page` its playable page, which the site unpacks and serves on the link's page. A part is the same whenever it's
|
|
138
|
+
* sent, so one whose connection dropped goes again. Answers the version the site gave it.
|
|
139
|
+
*/
|
|
140
|
+
export async function sendFile({ site = siteOrigin(), link, bytes, page = false, said = () => {} }) {
|
|
141
|
+
if (bytes.length > FILE_LIMITS.total) throw Object.assign(new Problem(`it's more than the ${megabytes(FILE_LIMITS.total)} a link carries`), { status: 413 });
|
|
142
|
+
const what = page ? "&what=page" : "", count = Math.max(1, Math.ceil(bytes.length / FILE_LIMITS.part));
|
|
143
|
+
for (let n = 0; n < count; n++) {
|
|
144
|
+
said(`Sending ${page ? "the page" : "the file"}: part ${n + 1} of ${count}`);
|
|
145
|
+
await call("PUT", fileAddress(site, link.id, `${what}&part=${n}&of=${count}`), { secret: link.secret, bytes: bytes.subarray(n * FILE_LIMITS.part, (n + 1) * FILE_LIMITS.part), tries: 4 });
|
|
146
|
+
}
|
|
147
|
+
// Putting a page together stores each of its files, which for a big game's takes minutes (the site gives it five).
|
|
148
|
+
return (await call("POST", fileAddress(site, link.id, what), { secret: link.secret, seconds: 330 })).said.version ?? null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Takes the link's file away, which keeps showing the idea, and its page with it; with `page` only the page. */
|
|
152
|
+
export async function removeFile({ site = siteOrigin(), link, page = false }) {
|
|
153
|
+
try { await call("DELETE", fileAddress(site, link.id, page ? "&what=page" : ""), { secret: link.secret, tries: 3 }); }
|
|
154
|
+
catch (error) { if (error.status !== 404) throw error; }
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** The ideas sent to the link that are still open, oldest first: each with its number. Only the link's secret reads them. */
|
|
158
|
+
export async function ideasOf({ site = siteOrigin(), link, earlier = false }) {
|
|
159
|
+
try { return (await call("GET", `${site}/api/wish-ideas?id=${encodeURIComponent(link.id)}${earlier ? "&earlier=1" : ""}`, { secret: link.secret })).said.ideas ?? []; }
|
|
160
|
+
catch (error) { if (error.status === 404) return []; throw error; }
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Lets an idea go: with `built` it's in, and the site first writes to whoever asked to hear. Whether it did. */
|
|
164
|
+
export async function removeIdea({ site = siteOrigin(), link, n, built = false, note }) {
|
|
165
|
+
try {
|
|
166
|
+
const { said } = await call("DELETE", `${site}/api/wish-ideas?id=${encodeURIComponent(link.id)}&n=${Number(n)}${built ? "&built=1" : ""}`,
|
|
167
|
+
{ secret: link.secret, ...(note ? { json: { note } } : {}) });
|
|
168
|
+
return { notified: said.notified === true };
|
|
169
|
+
} catch (error) { if (error.status === 404) return { notified: false }; throw error; }
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Says something more about an idea, its sender emailed if they gave an address, and answers whether they were;
|
|
174
|
+
* without a note, only that the maker has seen to their answer.
|
|
175
|
+
*/
|
|
176
|
+
export async function replyIdea({ site = siteOrigin(), link, n, note }) {
|
|
177
|
+
try {
|
|
178
|
+
const { said } = await call("PATCH", `${site}/api/wish-ideas?id=${encodeURIComponent(link.id)}&n=${Number(n)}`,
|
|
179
|
+
{ secret: link.secret, ...(note ? { json: { note } } : {}) });
|
|
180
|
+
return { notified: said.notified === true };
|
|
181
|
+
} catch (error) {
|
|
182
|
+
if (error.status === 404) throw new Problem(`there's no idea ${Number(n)} on this link`);
|
|
183
|
+
if (error.status === 429) throw new Problem(`idea ${Number(n)} has as many messages as it can keep`);
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* The maker's own address for the link's ideas and replies, as `{ email, confirmed }`; with `email`, given ("" takes it
|
|
190
|
+
* away), and the site emails it to confirm first.
|
|
191
|
+
*/
|
|
192
|
+
export async function makerOf({ site = siteOrigin(), link, email }) {
|
|
193
|
+
const { said } = await call(email === undefined ? "GET" : "PUT", `${site}/api/wish-ideas?id=${encodeURIComponent(link.id)}&maker=1`,
|
|
194
|
+
{ secret: link.secret, ...(email === undefined ? {} : { json: { email } }) });
|
|
195
|
+
return { email: typeof said.email === "string" ? said.email : null, confirmed: said.confirmed === true, ...(email ? { sent: said.sent === true } : {}) };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** Takes the link down, with its page and the ideas sent to it. A link the site no longer has is down already. */
|
|
199
|
+
export async function removeLink({ site = siteOrigin(), link }) {
|
|
200
|
+
try { await call("DELETE", `${site}/api/wishes?id=${encodeURIComponent(link.id)}`, { secret: link.secret }); }
|
|
201
|
+
catch (error) { if (error.status !== 404) throw error; }
|
|
202
|
+
}
|
package/cli/local-ai.mjs
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// `lamp ai`: the AI for a page shared on lamp.dev, answered on this computer with the person's own Claude Code or
|
|
2
|
+
// Codex (ai.mjs), the way `lamp dev` answers a page it serves. A shared page is away from Lamp, so lamp.js asks here,
|
|
3
|
+
// at a port of this computer's own (127.0.0.1), where a browser lets an https page call plain http.
|
|
4
|
+
//
|
|
5
|
+
// Only the person decides which pages spend their subscription. Each shared link plays from an origin of its own
|
|
6
|
+
// (`playOrigin` in site/lib/shared-wishes.js: <the link's id in hex>.play.lamp.dev), which a browser always names in
|
|
7
|
+
// the request and a page can't change, so an approval is for one link's page: the first time it asks, the person is
|
|
8
|
+
// asked in the terminal, and the page is given a token it keeps and sends from then on. Nothing else is answered:
|
|
9
|
+
// another site, another link's page, or a request naming this computer by another name (a site that rebinds its own
|
|
10
|
+
// name to 127.0.0.1) is refused. Whether there's an AI here (`/ai/status` and the probes) is answered without one, so a
|
|
11
|
+
// page can say what it can do before anyone is asked.
|
|
12
|
+
|
|
13
|
+
import { createServer } from "node:http";
|
|
14
|
+
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
15
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { homedir } from "node:os";
|
|
17
|
+
import { dirname, join } from "node:path";
|
|
18
|
+
import { createInterface } from "node:readline";
|
|
19
|
+
import { answer as answerAI, engine } from "./ai.mjs";
|
|
20
|
+
|
|
21
|
+
/** The port lamp.js on a shared page asks (`LOCAL_AI` there): one, fixed, since the page can't be told another. */
|
|
22
|
+
export const LOCAL_AI_PORT = 47423;
|
|
23
|
+
const PLAY_HOST = "play.lamp.dev";
|
|
24
|
+
const MOST = 2_000_000, AT_ONCE = 3, ASKING_FOR = 120_000;
|
|
25
|
+
const ROUTES = new Set(["/ai/status", "/ai", "/ai/act", "/ai/decide", "/ai/hear", "/ai/image"]);
|
|
26
|
+
|
|
27
|
+
const keptFile = () => join(process.env.LAMP_DEV_HOME || join(homedir(), ".lamp", "dev"), "shared-pages-ai.json");
|
|
28
|
+
|
|
29
|
+
/** The pages the person has let use their AI, by origin: `{ token, id, name, at }`. */
|
|
30
|
+
export function allowed() {
|
|
31
|
+
try { const kept = JSON.parse(readFileSync(keptFile(), "utf8")); return kept && typeof kept === "object" ? kept : {}; } catch { return {}; }
|
|
32
|
+
}
|
|
33
|
+
function keep(all) {
|
|
34
|
+
const file = keptFile();
|
|
35
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
36
|
+
writeFileSync(file + ".new", JSON.stringify(all, null, 2), { mode: 0o600 });
|
|
37
|
+
renameSync(file + ".new", file);
|
|
38
|
+
}
|
|
39
|
+
/** Forgets every page let in: each asks again. */
|
|
40
|
+
export function forgetAllowed() { if (existsSync(keptFile())) rmSync(keptFile()); }
|
|
41
|
+
|
|
42
|
+
/** Forgets one page let in, by its origin: it asks again the next time it uses the AI. */
|
|
43
|
+
export function forgetPage(origin) {
|
|
44
|
+
const all = allowed();
|
|
45
|
+
if (!(origin in all)) return;
|
|
46
|
+
delete all[origin];
|
|
47
|
+
if (Object.keys(all).length) keep(all); else forgetAllowed();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** The link a shared page's origin plays, by its id, or null for any other origin. */
|
|
51
|
+
export function linkOf(origin) {
|
|
52
|
+
let url;
|
|
53
|
+
try { url = new URL(origin); } catch { return null; }
|
|
54
|
+
if (url.protocol !== "https:" || url.port || !url.host.endsWith("." + PLAY_HOST)) return null;
|
|
55
|
+
const hex = url.host.slice(0, -PLAY_HOST.length - 1);
|
|
56
|
+
if (!/^(?:[0-9a-f]{2}){10}$/.test(hex)) return null;
|
|
57
|
+
const id = Buffer.from(hex, "hex").toString();
|
|
58
|
+
return /^[A-Za-z0-9]{10}$/.test(id) ? id : null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const same = (a, b) => {
|
|
62
|
+
if (typeof a !== "string" || typeof b !== "string") return false;
|
|
63
|
+
const x = Buffer.from(a), y = Buffer.from(b);
|
|
64
|
+
return x.length === y.length && timingSafeEqual(x, y);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Answers shared pages' AI until it's closed. `ask(question, page)` puts a yes-or-no to the person and resolves true
|
|
69
|
+
* for yes; by default it's the terminal's, and without a terminal nothing is let in. `answer(path, body, page)` is the
|
|
70
|
+
* AI's [status, reply]: the person's Claude Code, Codex or OpenRouter key by default, Lamp's own AI when Lamp's app runs this
|
|
71
|
+
* (`sharedPages` in calls.mjs). Resolves to the server once it listens.
|
|
72
|
+
*/
|
|
73
|
+
export async function serveLocalAI({ port = LOCAL_AI_PORT, ask = askInTerminal(), answer = answerAI, said = console.log } = {}) {
|
|
74
|
+
const busy = new Map(), queued = new Map(), refused = new Set(), waiting = new Map();
|
|
75
|
+
// A few of a page's requests run at once and the rest wait their turn, since lamp.js asks many at a time
|
|
76
|
+
// (`LampAI.decideEach`) and takes a refusal as that item's answer.
|
|
77
|
+
const turn = (origin) => {
|
|
78
|
+
if ((busy.get(origin) || 0) < AT_ONCE) { busy.set(origin, (busy.get(origin) || 0) + 1); return Promise.resolve(); }
|
|
79
|
+
return new Promise((go) => queued.set(origin, [...(queued.get(origin) || []), go]));
|
|
80
|
+
};
|
|
81
|
+
const done = (origin) => {
|
|
82
|
+
const next = queued.get(origin)?.shift();
|
|
83
|
+
if (next) next();
|
|
84
|
+
else busy.set(origin, busy.get(origin) - 1);
|
|
85
|
+
};
|
|
86
|
+
// One question at a time in the terminal; a page that asks again while it's waiting gets the same answer, and one
|
|
87
|
+
// the person said no to isn't asked about again while this runs.
|
|
88
|
+
let asking = Promise.resolve();
|
|
89
|
+
const askAbout = (origin, id, name) => {
|
|
90
|
+
if (waiting.has(origin)) return waiting.get(origin);
|
|
91
|
+
const asked = asking.then(async () => {
|
|
92
|
+
const kept = allowed()[origin];
|
|
93
|
+
if (kept) return kept.token;
|
|
94
|
+
const titled = name ? `"${name}" ` : "A page ";
|
|
95
|
+
const yes = await ask(`${titled}shared at lamp.dev/w/${id} wants to use your ${engineName()} here. Allow it?`, { id, name });
|
|
96
|
+
if (!yes) { refused.add(origin); return null; }
|
|
97
|
+
const token = randomBytes(32).toString("base64url");
|
|
98
|
+
keep({ ...allowed(), [origin]: { token, id, name: name || "", at: new Date().toISOString() } });
|
|
99
|
+
said(`Allowed ${name ? `"${name}"` : `lamp.dev/w/${id}`}. lamp ai --forget takes it back.`);
|
|
100
|
+
return token;
|
|
101
|
+
});
|
|
102
|
+
asking = asked.catch(() => {});
|
|
103
|
+
waiting.set(origin, asked);
|
|
104
|
+
asked.finally(() => waiting.delete(origin));
|
|
105
|
+
return asked;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const server = createServer(async (request, response) => {
|
|
109
|
+
const origin = request.headers.origin || "";
|
|
110
|
+
const id = linkOf(origin);
|
|
111
|
+
const reply = (status, body) => {
|
|
112
|
+
const headers = { "Content-Type": "application/json", "Cache-Control": "no-store", Vary: "Origin" };
|
|
113
|
+
if (id) headers["Access-Control-Allow-Origin"] = origin;
|
|
114
|
+
response.writeHead(status, headers);
|
|
115
|
+
response.end(JSON.stringify(body));
|
|
116
|
+
};
|
|
117
|
+
// Only this computer's own name for itself: a site that points a name of its own at 127.0.0.1 is someone else.
|
|
118
|
+
const host = String(request.headers.host || "").replace(/:\d+$/, "");
|
|
119
|
+
if (host !== "127.0.0.1" && host !== "localhost") return reply(403, { error: "Not here." });
|
|
120
|
+
if (!id) return reply(403, { error: "Only a page shared on lamp.dev can ask here." });
|
|
121
|
+
const url = new URL(request.url, "http://127.0.0.1");
|
|
122
|
+
if (request.method === "OPTIONS") {
|
|
123
|
+
response.writeHead(204, {
|
|
124
|
+
"Access-Control-Allow-Origin": origin,
|
|
125
|
+
"Access-Control-Allow-Methods": "POST",
|
|
126
|
+
"Access-Control-Allow-Headers": "Authorization, Content-Type",
|
|
127
|
+
"Access-Control-Allow-Private-Network": "true",
|
|
128
|
+
"Access-Control-Max-Age": "600",
|
|
129
|
+
Vary: "Origin",
|
|
130
|
+
});
|
|
131
|
+
return response.end();
|
|
132
|
+
}
|
|
133
|
+
if (request.method !== "POST") return reply(405, { error: "Method not allowed." });
|
|
134
|
+
|
|
135
|
+
let body = {};
|
|
136
|
+
try {
|
|
137
|
+
const chunks = [];
|
|
138
|
+
let size = 0;
|
|
139
|
+
for await (const chunk of request) {
|
|
140
|
+
size += chunk.length;
|
|
141
|
+
if (size > MOST) return reply(413, { error: "That's too much to ask at once." });
|
|
142
|
+
chunks.push(chunk);
|
|
143
|
+
}
|
|
144
|
+
const text = Buffer.concat(chunks).toString();
|
|
145
|
+
body = text ? JSON.parse(text) : {};
|
|
146
|
+
} catch { return reply(400, { error: "That wasn't JSON." }); }
|
|
147
|
+
|
|
148
|
+
if (url.pathname === "/pair") {
|
|
149
|
+
if (refused.has(origin)) return reply(403, { error: "Not allowed on this computer." });
|
|
150
|
+
const name = typeof body?.name === "string" ? body.name.replace(/[\u0000-\u001f\u007f]/g, " ").trim().slice(0, 60) : "";
|
|
151
|
+
const token = await askAbout(origin, id, name);
|
|
152
|
+
return token ? reply(200, { token }) : reply(403, { error: "Not allowed on this computer." });
|
|
153
|
+
}
|
|
154
|
+
if (!ROUTES.has(url.pathname)) return reply(404, { error: "Not found." });
|
|
155
|
+
// What there is to answer with, asked before anyone is let in: only the routes whose probe asks no model.
|
|
156
|
+
const asksNothing = url.pathname === "/ai/status" || (body?.probe === true && (url.pathname === "/ai/act" || url.pathname === "/ai/hear"));
|
|
157
|
+
if (asksNothing) {
|
|
158
|
+
const [status, answered] = await answer(url.pathname, url.pathname === "/ai/status" ? {} : { probe: true }, { id });
|
|
159
|
+
return reply(status, answered);
|
|
160
|
+
}
|
|
161
|
+
const kept = allowed()[origin];
|
|
162
|
+
const given = String(request.headers.authorization || "").replace(/^Bearer\s+/i, "");
|
|
163
|
+
if (!kept || !same(given, kept.token)) return reply(401, { error: "This page isn't allowed to use the AI here yet." });
|
|
164
|
+
await turn(origin);
|
|
165
|
+
try {
|
|
166
|
+
const [status, answered] = await answer(url.pathname, body, { id });
|
|
167
|
+
reply(status, answered);
|
|
168
|
+
} catch (error) {
|
|
169
|
+
reply(502, { error: error?.message || "The AI didn't answer." });
|
|
170
|
+
} finally {
|
|
171
|
+
done(origin);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
await new Promise((done, fail) => { server.once("error", fail); server.listen(port, "127.0.0.1", () => { server.off("error", fail); done(); }); });
|
|
175
|
+
return server;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const engineName = () => ({ codex: "Codex", openrouter: "OpenRouter key" })[engine()] ?? "Claude Code";
|
|
179
|
+
|
|
180
|
+
/** A yes-or-no in the terminal, or always no without one. */
|
|
181
|
+
export function askInTerminal({ input = process.stdin, output = process.stdout } = {}) {
|
|
182
|
+
return (question) => {
|
|
183
|
+
if (!input.isTTY) {
|
|
184
|
+
output.write(`${question} No: lamp ai can only ask in a terminal.\n`);
|
|
185
|
+
return Promise.resolve(false);
|
|
186
|
+
}
|
|
187
|
+
const lines = createInterface({ input, output });
|
|
188
|
+
return new Promise((done) => {
|
|
189
|
+
const timer = setTimeout(() => { output.write("\nNo answer, so not allowed.\n"); lines.close(); done(false); }, ASKING_FOR);
|
|
190
|
+
lines.question(`${question} [y/N] `, (said) => { clearTimeout(timer); lines.close(); done(/^y(es)?$/i.test(said.trim())); });
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
}
|