@kauakdev/kauak 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +186 -2
- package/bin/kauak.js +12 -0
- package/bridge/config.js +34 -0
- package/bridge/context_remote.py +344 -0
- package/bridge/diffs_remote.py +85 -0
- package/bridge/server.js +2387 -0
- package/cli/commands/serve.js +97 -0
- package/cli/errors.js +2 -0
- package/cli/main.js +101 -0
- package/dist/THIRD_PARTY_LICENSES.txt +183 -0
- package/dist/assets/BufferResource-CHYsmqd5.js +195 -0
- package/dist/assets/CanvasRenderer-DY1TnK1M.js +1 -0
- package/dist/assets/Filter-IrwvDh3w.js +1 -0
- package/dist/assets/RenderTargetSystem-CBR4meCp.js +184 -0
- package/dist/assets/WebGLRenderer-DprtkQRW.js +156 -0
- package/dist/assets/WebGPURenderer-ByQ-10KB.js +42 -0
- package/dist/assets/browserAll-B-9xDvMq.js +14 -0
- package/dist/assets/contours-DG3HeJNa.svg +68 -0
- package/dist/assets/demo-DyZsh87s.css +1 -0
- package/dist/assets/demo-mFndvU9t.js +5 -0
- package/dist/assets/index-BxvDL43s.css +32 -0
- package/dist/assets/index-Do5XwO_P.js +349 -0
- package/dist/assets/webworkerAll-gM2Z784I.js +83 -0
- package/dist/index.html +160 -0
- package/dist/kauak.png +0 -0
- package/package.json +24 -4
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import{M as k,h as O,X as A,aw as M,a4 as P,l as b,G as U,b as E,W as z,L as V,a5 as _,T as v,ao as Y,R as X,w as q,x as R}from"./index-Do5XwO_P.js";import{F as L}from"./Filter-IrwvDh3w.js";const y=new k;function G(g,e){e.clear();const t=e.matrix;for(let r=0;r<g.length;r++){const i=g[r];if(i.globalDisplayStatus<7)continue;const n=i.renderGroup??i.parentRenderGroup;n!=null&&n.isCachedAsTexture?e.matrix=y.copyFrom(n.textureOffsetInverseTransform).append(i.worldTransform):n!=null&&n._parentCacheAsTextureRenderGroup?e.matrix=y.copyFrom(n._parentCacheAsTextureRenderGroup.inverseWorldTransform).append(i.groupTransform):e.matrix=i.worldTransform,e.addBounds(i.bounds)}return e.matrix=t,e}function w(g){return typeof g.getCanvasFilterString=="function"}class W{constructor(){this.skip=!1,this.useClip=!1,this.filters=null,this.container=null,this.bounds=new P,this.cssFilterString=""}}class C{constructor(e){this._filterStack=[],this._filterStackIndex=0,this._savedStates=[],this._alphaMultiplier=1,this._warnedFilterTypes=new Set,this.renderer=e}push(e){const t=this._pushFilterFrame(),r=e.filterEffect.filters;if(t.skip=!1,t.useClip=!1,t.filters=r,t.container=e.container,t.cssFilterString="",r.every(o=>!o.enabled)){t.skip=!0;return}const i=[],n=1;for(const o of r){if(!o.enabled)continue;if(!w(o)){this._warnUnsupportedFilter(o);continue}const l=o.getCanvasFilterString();if(l===null){this._warnUnsupportedFilter(o);continue}l&&i.push(l)}if(i.length===0&&n===1){t.skip=!0;return}t.cssFilterString=i.join(" "),this._calculateFilterArea(e,t.bounds),t.useClip=!!e.filterEffect.filterArea;const s=this.renderer.canvasContext.activeContext,a=s.filter||"none";if(this._savedStates.push({filter:a,alphaMultiplier:this._alphaMultiplier}),t.useClip&&Number.isFinite(t.bounds.width)&&Number.isFinite(t.bounds.height)&&t.bounds.width>0&&t.bounds.height>0){const o=this.renderer.canvasContext.activeResolution||1;s.save(),s.setTransform(1,0,0,1,0,0),s.beginPath(),s.rect(t.bounds.x*o,t.bounds.y*o,t.bounds.width*o,t.bounds.height*o),s.clip()}else t.useClip=!1;t.cssFilterString&&(s.filter=a!=="none"?`${a} ${t.cssFilterString}`:t.cssFilterString)}pop(){const e=this._popFilterFrame();if(e.skip)return;const t=this._savedStates.pop();if(!t)return;const r=this.renderer.canvasContext.activeContext;e.useClip?r.restore():r.filter=t.filter,this._alphaMultiplier=t.alphaMultiplier}generateFilteredTexture({texture:e,filters:t}){if(!(t!=null&&t.length)||t.every(h=>!h.enabled))return e;const r=[],i=1;for(const h of t){if(!h.enabled)continue;if(!w(h)){this._warnUnsupportedFilter(h);continue}const T=h.getCanvasFilterString();if(T===null){this._warnUnsupportedFilter(h);continue}T&&r.push(T)}if(r.length===0&&i===1)return e;const n=O.getCanvasSource(e);if(!n)return e;const s=e.frame,a=e.source._resolution??e.source.resolution??1,o=s.width,l=s.height,f=A.getOptimalCanvasAndContext(o,l,a),{canvas:c,context:u}=f;u.setTransform(1,0,0,1,0,0),u.clearRect(0,0,c.width,c.height),r.length&&(u.filter=r.join(" "));const p=s.x*a,d=s.y*a,x=o*a,F=l*a;return u.drawImage(n,p,d,x,F,0,0,x,F),u.filter="none",u.globalAlpha=1,M(c,o,l,a)}_calculateFilterArea(e,t){if(e.renderables?G(e.renderables,t):e.filterEffect.filterArea?(t.clear(),t.addRect(e.filterEffect.filterArea),t.applyMatrix(e.container.worldTransform)):e.container.getFastGlobalBounds(!0,t),e.container){const r=e.container.renderGroup||e.container.parentRenderGroup,i=r==null?void 0:r.cacheToLocalTransform;i&&t.applyMatrix(i)}}_warnUnsupportedFilter(e){var r;const t=((r=e==null?void 0:e.constructor)==null?void 0:r.name)||"Filter";this._warnedFilterTypes.has(t)||(this._warnedFilterTypes.add(t),console.warn(`CanvasRenderer: filter "${t}" is not supported in Canvas2D and will be skipped.`))}get alphaMultiplier(){return this._alphaMultiplier}_pushFilterFrame(){let e=this._filterStack[this._filterStackIndex];return e||(e=this._filterStack[this._filterStackIndex]=new W),this._filterStackIndex++,e}_popFilterFrame(){return this._filterStackIndex<=0?this._filterStack[0]:(this._filterStackIndex--,this._filterStack[this._filterStackIndex])}destroy(){this._filterStack=null,this._savedStates=null,this._warnedFilterTypes=null,this._alphaMultiplier=1}}C.extension={type:[b.CanvasSystem],name:"filter"};var j=`in vec2 aPosition;
|
|
2
|
+
out vec2 vTextureCoord;
|
|
3
|
+
|
|
4
|
+
uniform vec4 uInputSize;
|
|
5
|
+
uniform vec4 uOutputFrame;
|
|
6
|
+
uniform vec4 uOutputTexture;
|
|
7
|
+
|
|
8
|
+
vec4 filterVertexPosition( void )
|
|
9
|
+
{
|
|
10
|
+
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
|
11
|
+
|
|
12
|
+
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
|
13
|
+
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
|
14
|
+
|
|
15
|
+
return vec4(position, 0.0, 1.0);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
vec2 filterTextureCoord( void )
|
|
19
|
+
{
|
|
20
|
+
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
void main(void)
|
|
24
|
+
{
|
|
25
|
+
gl_Position = filterVertexPosition();
|
|
26
|
+
vTextureCoord = filterTextureCoord();
|
|
27
|
+
}
|
|
28
|
+
`,N=`in vec2 vTextureCoord;
|
|
29
|
+
out vec4 finalColor;
|
|
30
|
+
uniform sampler2D uTexture;
|
|
31
|
+
void main() {
|
|
32
|
+
finalColor = texture(uTexture, vTextureCoord);
|
|
33
|
+
}
|
|
34
|
+
`,S=`struct GlobalFilterUniforms {
|
|
35
|
+
uInputSize: vec4<f32>,
|
|
36
|
+
uInputPixel: vec4<f32>,
|
|
37
|
+
uInputClamp: vec4<f32>,
|
|
38
|
+
uOutputFrame: vec4<f32>,
|
|
39
|
+
uGlobalFrame: vec4<f32>,
|
|
40
|
+
uOutputTexture: vec4<f32>,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
@group(0) @binding(0) var <uniform> gfu: GlobalFilterUniforms;
|
|
44
|
+
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
|
45
|
+
@group(0) @binding(2) var uSampler: sampler;
|
|
46
|
+
|
|
47
|
+
struct VSOutput {
|
|
48
|
+
@builtin(position) position: vec4<f32>,
|
|
49
|
+
@location(0) uv: vec2<f32>
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
fn filterVertexPosition(aPosition: vec2<f32>) -> vec4<f32>
|
|
53
|
+
{
|
|
54
|
+
var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;
|
|
55
|
+
|
|
56
|
+
position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;
|
|
57
|
+
position.y = position.y * (2.0 * gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;
|
|
58
|
+
|
|
59
|
+
return vec4(position, 0.0, 1.0);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
fn filterTextureCoord(aPosition: vec2<f32>) -> vec2<f32>
|
|
63
|
+
{
|
|
64
|
+
return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@vertex
|
|
68
|
+
fn mainVertex(
|
|
69
|
+
@location(0) aPosition: vec2<f32>,
|
|
70
|
+
) -> VSOutput {
|
|
71
|
+
return VSOutput(
|
|
72
|
+
filterVertexPosition(aPosition),
|
|
73
|
+
filterTextureCoord(aPosition)
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@fragment
|
|
78
|
+
fn mainFragment(
|
|
79
|
+
@location(0) uv: vec2<f32>,
|
|
80
|
+
) -> @location(0) vec4<f32> {
|
|
81
|
+
return textureSample(uTexture, uSampler, uv);
|
|
82
|
+
}
|
|
83
|
+
`;class $ extends L{constructor(){const e=U.from({vertex:{source:S,entryPoint:"mainVertex"},fragment:{source:S,entryPoint:"mainFragment"},name:"passthrough-filter"}),t=E.from({vertex:j,fragment:N,name:"passthrough-filter"});super({gpuProgram:e,glProgram:t})}}class I{constructor(e){this._renderer=e}push(e,t,r){this._renderer.renderPipes.batch.break(r),r.add({renderPipeId:"filter",canBundle:!1,action:"pushFilter",container:t,filterEffect:e})}pop(e,t,r){this._renderer.renderPipes.batch.break(r),r.add({renderPipeId:"filter",action:"popFilter",canBundle:!1})}execute(e){e.action==="pushFilter"?this._renderer.filter.push(e):e.action==="popFilter"&&this._renderer.filter.pop()}destroy(){this._renderer=null}}I.extension={type:[b.WebGLPipes,b.WebGPUPipes,b.CanvasPipes],name:"filter"};const H=new Y({attributes:{aPosition:{buffer:new Float32Array([0,0,1,0,1,1,0,1]),format:"float32x2",stride:8,offset:0}},indexBuffer:new Uint32Array([0,1,2,0,2,3])});class J{constructor(){this.skip=!1,this.inputTexture=null,this.backTexture=null,this.filters=null,this.bounds=new P,this.container=null,this.blendRequired=!1,this.outputRenderSurface=null,this.globalFrame={x:0,y:0,width:0,height:0},this.firstEnabledIndex=-1,this.lastEnabledIndex=-1}}class B{constructor(e){this._filterStackIndex=0,this._filterStack=[],this._filterGlobalUniforms=new z({uInputSize:{value:new Float32Array(4),type:"vec4<f32>"},uInputPixel:{value:new Float32Array(4),type:"vec4<f32>"},uInputClamp:{value:new Float32Array(4),type:"vec4<f32>"},uOutputFrame:{value:new Float32Array(4),type:"vec4<f32>"},uGlobalFrame:{value:new Float32Array(4),type:"vec4<f32>"},uOutputTexture:{value:new Float32Array(4),type:"vec4<f32>"}}),this._globalFilterBindGroup=new V({}),this.renderer=e}get activeBackTexture(){var e;return(e=this._activeFilterData)==null?void 0:e.backTexture}push(e){const t=this.renderer,r=e.filterEffect.filters,i=this._pushFilterData();i.skip=!1,i.filters=r,i.container=e.container,i.outputRenderSurface=t.renderTarget.renderSurface;const n=t.renderTarget.renderTarget.colorTexture.source,s=n.resolution,a=n.antialias;if(r.every(p=>!p.enabled)){i.skip=!0;return}const o=i.bounds;if(this._calculateFilterArea(e,o),this._calculateFilterBounds(i,t.renderTarget.rootViewPort,a,s,1),i.skip)return;const l=this._getPreviousFilterData(),f=this._findFilterResolution(s);let c=0,u=0;l&&(c=l.bounds.minX,u=l.bounds.minY),this._calculateGlobalFrame(i,c,u,f,n.width,n.height),this._setupFilterTextures(i,o,t,l)}generateFilteredTexture({texture:e,filters:t}){const r=this._pushFilterData();this._activeFilterData=r,r.skip=!1,r.filters=t;const i=e.source,n=i.resolution,s=i.antialias;if(t.every(p=>!p.enabled))return r.skip=!0,e;const a=r.bounds;if(a.addRect(e.frame),this._calculateFilterBounds(r,a.rectangle,s,n,0),r.skip)return e;const o=n;this._calculateGlobalFrame(r,0,0,o,i.width,i.height),r.outputRenderSurface=_.getOptimalTexture({width:a.width,height:a.height,resolution:r.resolution,antialias:r.antialias}),r.backTexture=v.EMPTY,r.inputTexture=e,this.renderer.renderTarget.finishRenderPass(),this._applyFiltersToTexture(r,!0);const u=r.outputRenderSurface;return u.source.alphaMode="premultiplied-alpha",u}pop(){const e=this.renderer,t=this._popFilterData();t.skip||(e.globalUniforms.pop(),e.renderTarget.finishRenderPass(),this._activeFilterData=t,this._applyFiltersToTexture(t,!1),t.blendRequired&&_.returnTexture(t.backTexture),_.returnTexture(t.inputTexture))}getBackTexture(e,t,r){const i=e.colorTexture.source._resolution,n=_.getOptimalTexture({width:t.width,height:t.height,resolution:i});let s=t.minX,a=t.minY;r&&(s-=r.minX,a-=r.minY),s=Math.floor(s*i),a=Math.floor(a*i);const o=Math.ceil(t.width*i),l=Math.ceil(t.height*i);return this.renderer.renderTarget.copyToTexture(e,n,{x:s,y:a},{width:o,height:l},{x:0,y:0}),n}applyFilter(e,t,r,i){const n=this.renderer,s=this._activeFilterData,o=s.outputRenderSurface===r,l=n.renderTarget.rootRenderTarget.colorTexture.source._resolution,f=this._findFilterResolution(l);let c=0,u=0;if(o){const d=this._findPreviousFilterOffset();c=d.x,u=d.y}this._updateFilterUniforms(t,r,s,c,u,f,o,i);const p=e.enabled?e:this._getPassthroughFilter();this._setupBindGroupsAndRender(p,t,n)}calculateSpriteMatrix(e,t){const r=this._activeFilterData,i=e.set(r.inputTexture._source.width,0,0,r.inputTexture._source.height,r.bounds.minX,r.bounds.minY),n=t.worldTransform.copyTo(k.shared),s=t.renderGroup||t.parentRenderGroup;return s&&s.cacheToLocalTransform&&n.prepend(s.cacheToLocalTransform),n.invert(),i.prepend(n),i.scale(1/t.texture.orig.width,1/t.texture.orig.height),i.translate(t.anchor.x,t.anchor.y),i}destroy(){var e;(e=this._passthroughFilter)==null||e.destroy(!0),this._passthroughFilter=null}_getPassthroughFilter(){return this._passthroughFilter??(this._passthroughFilter=new $),this._passthroughFilter}_setupBindGroupsAndRender(e,t,r){if(r.renderPipes.uniformBatch){const i=r.renderPipes.uniformBatch.getUboResource(this._filterGlobalUniforms);this._globalFilterBindGroup.setResource(i,0)}else this._globalFilterBindGroup.setResource(this._filterGlobalUniforms,0);this._globalFilterBindGroup.setResource(t.source,1),this._globalFilterBindGroup.setResource(t.source.style,2),e.groups[0]=this._globalFilterBindGroup,r.encoder.draw({geometry:H,shader:e,state:e._state,topology:"triangle-list"}),r.type===X.WEBGL&&r.renderTarget.finishRenderPass()}_setupFilterTextures(e,t,r,i){if(e.backTexture=v.EMPTY,e.inputTexture=_.getOptimalTexture({width:t.width,height:t.height,resolution:e.resolution,antialias:e.antialias}),e.blendRequired){r.renderTarget.finishRenderPass();const n=r.renderTarget.getRenderTarget(e.outputRenderSurface);e.backTexture=this.getBackTexture(n,t,i==null?void 0:i.bounds)}r.renderTarget.bind({target:e.inputTexture,clear:!0}),r.globalUniforms.push({offset:t})}_calculateGlobalFrame(e,t,r,i,n,s){const a=e.globalFrame;a.x=t*i,a.y=r*i,a.width=n*i,a.height=s*i}_updateFilterUniforms(e,t,r,i,n,s,a,o){const l=this._filterGlobalUniforms.uniforms,f=l.uOutputFrame,c=l.uInputSize,u=l.uInputPixel,p=l.uInputClamp,d=l.uGlobalFrame,x=l.uOutputTexture;a?(f[0]=r.bounds.minX-i,f[1]=r.bounds.minY-n):(f[0]=0,f[1]=0),f[2]=e.frame.width,f[3]=e.frame.height,c[0]=e.source.width,c[1]=e.source.height,c[2]=1/c[0],c[3]=1/c[1],u[0]=e.source.pixelWidth,u[1]=e.source.pixelHeight,u[2]=1/u[0],u[3]=1/u[1],p[0]=.5*u[2],p[1]=.5*u[3],p[2]=e.frame.width*c[2]-.5*u[2],p[3]=e.frame.height*c[3]-.5*u[3];const F=this.renderer.renderTarget.rootRenderTarget.colorTexture;d[0]=i*s,d[1]=n*s,d[2]=F.source.width*s,d[3]=F.source.height*s,t instanceof v&&(t.source.resource=null);const h=this.renderer.renderTarget.getRenderTarget(t);this.renderer.renderTarget.bind({target:t,clear:!!o}),t instanceof v?(x[0]=t.frame.width,x[1]=t.frame.height):(x[0]=h.width,x[1]=h.height),x[2]=h.isRoot?-1:1,this._filterGlobalUniforms.update()}_findFilterResolution(e){let t=this._filterStackIndex-1;for(;t>0&&this._filterStack[t].skip;)--t;return t>0&&this._filterStack[t].inputTexture?this._filterStack[t].inputTexture.source._resolution:e}_findPreviousFilterOffset(){let e=0,t=0,r=this._filterStackIndex;for(;r>0;){r--;const i=this._filterStack[r];if(!i.skip){e=i.bounds.minX,t=i.bounds.minY;break}}return{x:e,y:t}}_calculateFilterArea(e,t){if(e.renderables?G(e.renderables,t):e.filterEffect.filterArea?(t.clear(),t.addRect(e.filterEffect.filterArea),t.applyMatrix(e.container.worldTransform)):e.container.getFastGlobalBounds(!0,t),e.container){const i=(e.container.renderGroup||e.container.parentRenderGroup).cacheToLocalTransform;i&&t.applyMatrix(i)}}_applyFiltersToTexture(e,t){const r=e.inputTexture,i=e.bounds,n=e.filters,s=e.firstEnabledIndex,a=e.lastEnabledIndex;if(this._globalFilterBindGroup.setResource(r.source.style,2),this._globalFilterBindGroup.setResource(e.backTexture.source,3),s===a)n[s].apply(this,r,e.outputRenderSurface,t);else{let o=e.inputTexture;const l=_.getOptimalTexture({width:i.width,height:i.height,resolution:o.source._resolution});let f=l;for(let c=s;c<a;c++){const u=n[c];if(!u.enabled)continue;u.apply(this,o,f,!0);const p=o;o=f,f=p}n[a].apply(this,o,e.outputRenderSurface,t),_.returnTexture(l)}}_calculateFilterBounds(e,t,r,i,n){var h;const s=this.renderer,a=e.bounds,o=e.filters;let l=1/0,f=0,c=!0,u=!1,p=!1,d=!0,x=-1,F=-1;for(let T=0;T<o.length;T++){const m=o[T];if(!m.enabled)continue;if(x===-1&&(x=T),F=T,l=Math.min(l,m.resolution==="inherit"?i:m.resolution),f+=m.padding,m.antialias==="off"?c=!1:m.antialias==="inherit"&&c&&(c=r),m.clipToViewport||(d=!1),!!!(m.compatibleRenderers&s.type)){p=!1;break}if(m.blendRequired&&!(((h=s.backBuffer)==null?void 0:h.useBackBuffer)??!0)){q("Blend filter requires backBuffer on WebGL renderer to be enabled. Set `useBackBuffer: true` in the renderer options."),p=!1;break}p=!0,u||(u=m.blendRequired)}if(!p){e.skip=!0;return}if(d&&a.fitBounds(0,t.width/i,0,t.height/i),a.scale(l).ceil().scale(1/l).pad((f|0)*n),!a.isPositive){e.skip=!0;return}e.antialias=c,e.resolution=l,e.blendRequired=u,e.firstEnabledIndex=x,e.lastEnabledIndex=F}_popFilterData(){return this._filterStackIndex--,this._filterStack[this._filterStackIndex]}_getPreviousFilterData(){let e,t=this._filterStackIndex-1;for(;t>0&&(t--,e=this._filterStack[t],!!e.skip););return e}_pushFilterData(){let e=this._filterStack[this._filterStackIndex];return e||(e=this._filterStack[this._filterStackIndex]=new J),this._filterStackIndex++,e}}B.extension={type:[b.WebGLSystem,b.WebGPUSystem],name:"filter"};R.add(B,C);R.add(I);
|
package/dist/index.html
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
6
|
+
<title>kauak</title>
|
|
7
|
+
<link rel="icon" type="image/png" href="./kauak.png" />
|
|
8
|
+
<link rel="apple-touch-icon" href="./kauak.png" />
|
|
9
|
+
<meta name="description" content="A Sims-style isometric office that shows what your Herdr coding agents are doing, live." />
|
|
10
|
+
<meta property="og:title" content="kauak" />
|
|
11
|
+
<meta property="og:image" content="https://kauakdev.github.io/kauak/kauak-banner.png" />
|
|
12
|
+
<meta property="og:image:alt" content="kauak — blue mountains and the kauak logo" />
|
|
13
|
+
<meta name="twitter:card" content="summary_large_image" />
|
|
14
|
+
<meta name="twitter:title" content="kauak" />
|
|
15
|
+
<meta name="twitter:image" content="https://kauakdev.github.io/kauak/kauak-banner.png" />
|
|
16
|
+
<meta property="og:description" content="A Sims-style isometric office that shows what your Herdr coding agents are doing, live." />
|
|
17
|
+
<script type="module" crossorigin src="/assets/index-Do5XwO_P.js"></script>
|
|
18
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BxvDL43s.css">
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
<script>if (innerWidth < 900) document.body.classList.add("roster-hidden");</script>
|
|
22
|
+
<div id="app"></div>
|
|
23
|
+
|
|
24
|
+
<div id="topbar">
|
|
25
|
+
<div id="brand">
|
|
26
|
+
<img src="./kauak.png" alt="kauak" width="38" height="38" />
|
|
27
|
+
<span aria-hidden="true">kauak</span>
|
|
28
|
+
</div>
|
|
29
|
+
<div id="conn" class="bad"><i class="dot"></i><span id="conn-text">connecting…</span></div>
|
|
30
|
+
<div id="stats"></div>
|
|
31
|
+
<div id="tools">
|
|
32
|
+
<span id="clock"></span>
|
|
33
|
+
<button class="btn" id="btn-zoom-out" title="Zoom out (-)">−</button>
|
|
34
|
+
<button class="btn" id="btn-zoom-in" title="Zoom in (+)">+</button>
|
|
35
|
+
<button class="btn" id="btn-fit" title="Fit the whole office (F)">Fit<kbd>F</kbd></button>
|
|
36
|
+
<button class="btn" id="btn-roster" title="Toggle roster (R)">Roster<kbd>R</kbd></button>
|
|
37
|
+
<button class="btn" id="btn-feed" title="Toggle activity feed (A)" aria-controls="feed">Activity<kbd>A</kbd></button>
|
|
38
|
+
<button class="btn" id="btn-build" title="Build mode: add desks and rooms (B)" aria-pressed="false">Build<kbd>B</kbd></button>
|
|
39
|
+
<button class="btn" id="btn-radio" title="Radio (M: on/off)" aria-controls="radio" aria-expanded="false"><span class="eq" aria-hidden="true"><i></i><i></i><i></i></span><span class="lbl">Radio</span><kbd>M</kbd></button>
|
|
40
|
+
<button class="btn" id="btn-appearance" title="Office appearance and company banner" aria-label="Appearance settings" aria-controls="appearance" aria-expanded="false">Appearance</button>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<section id="radio" class="card" hidden aria-label="Radio" data-state="off">
|
|
45
|
+
<header><span>Radio</span><button id="radio-power" class="mini" aria-pressed="false" title="Turn the radio on or off (M)"><i class="led"></i>Power</button></header>
|
|
46
|
+
<div id="radio-dial" title="Drag or scroll to tune"><div id="radio-scale"><i id="radio-needle"></i></div></div>
|
|
47
|
+
<div class="readout">
|
|
48
|
+
<span class="freq"><b id="radio-freq">95.5</b> FM</span>
|
|
49
|
+
<span class="lamp" title="Lit when locked on a station">Tuned</span>
|
|
50
|
+
<span class="bars" title="Signal" aria-hidden="true"><i></i><i></i><i></i><i></i></span>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="station"><b id="radio-name">—</b><span id="radio-info"></span></div>
|
|
53
|
+
<div class="controls">
|
|
54
|
+
<button class="btn" id="radio-prev" title="Seek down to the previous station" aria-label="Previous station">◀</button>
|
|
55
|
+
<div id="radio-knob" role="slider" tabindex="0" aria-label="Tuning" aria-valuemin="87.5" aria-valuemax="108"
|
|
56
|
+
title="Drag, scroll or use the arrow keys to tune · PageUp/PageDown seek"><i></i></div>
|
|
57
|
+
<button class="btn" id="radio-next" title="Seek up to the next station" aria-label="Next station">▶</button>
|
|
58
|
+
<label class="vol">Vol<input id="radio-volume" type="range" min="0" max="100" value="60" aria-label="Volume"></label>
|
|
59
|
+
</div>
|
|
60
|
+
<footer id="radio-credit"></footer>
|
|
61
|
+
</section>
|
|
62
|
+
|
|
63
|
+
<aside id="roster" class="card">
|
|
64
|
+
<header><span>Roster</span><span style="font-weight:400;letter-spacing:0;text-transform:none">j / k to cycle</span></header>
|
|
65
|
+
<div id="roster-body"></div>
|
|
66
|
+
</aside>
|
|
67
|
+
|
|
68
|
+
<nav id="floors" class="card" aria-label="Floors">
|
|
69
|
+
<header><span>Floors</span><button id="floor-add-btn" class="mini" title="Add a machine running Herdr as a new floor">+ Add floor</button></header>
|
|
70
|
+
<form id="floor-add" hidden autocomplete="off">
|
|
71
|
+
<label>SSH target<input name="ssh" placeholder="devbox or user@host" spellcheck="false" autocapitalize="off" required></label>
|
|
72
|
+
<label><span>Name <span class="opt">optional</span></span><input name="label" placeholder="shown on the elevator" spellcheck="false"></label>
|
|
73
|
+
<p class="note">Connects with your SSH keys and ~/.ssh/config. The machine must log in without a password prompt and run Herdr.</p>
|
|
74
|
+
<p class="err" hidden></p>
|
|
75
|
+
<div class="row"><button type="submit" class="btn primary">Add floor</button><button type="button" class="btn" data-cancel>Cancel</button></div>
|
|
76
|
+
</form>
|
|
77
|
+
<div id="floor-list" role="list"></div>
|
|
78
|
+
</nav>
|
|
79
|
+
|
|
80
|
+
<form id="build-form" class="card" hidden autocomplete="off" aria-labelledby="build-title">
|
|
81
|
+
<header><span id="build-title">New desk</span><button type="button" class="x" data-cancel aria-label="Cancel">✕</button></header>
|
|
82
|
+
<div class="body">
|
|
83
|
+
<div class="kinds" role="radiogroup" aria-label="Kind of room" data-for="room">
|
|
84
|
+
<label><input type="radio" name="kind" value="worktree">Git branch</label>
|
|
85
|
+
<label><input type="radio" name="kind" value="folder">Folder</label>
|
|
86
|
+
</div>
|
|
87
|
+
<label data-for="room"><span>Folder</span><input name="cwd" spellcheck="false" autocapitalize="off" data-required></label>
|
|
88
|
+
<div class="pair" data-for="worktree">
|
|
89
|
+
<label><span>New branch</span><input name="branch" placeholder="feat/my-change" spellcheck="false" autocapitalize="off" data-required></label>
|
|
90
|
+
<label><span>From <span class="opt">optional</span></span><input name="base" placeholder="current branch" spellcheck="false" autocapitalize="off"></label>
|
|
91
|
+
</div>
|
|
92
|
+
<label data-for="room"><span>Name <span class="opt">optional</span></span><input name="label" placeholder="shown on the room" spellcheck="false"></label>
|
|
93
|
+
<label><span>Agent</span><select name="agent"></select></label>
|
|
94
|
+
<p class="note"></p>
|
|
95
|
+
<p class="err" hidden></p>
|
|
96
|
+
<div class="row"><button type="submit" class="btn primary">Create</button><button type="button" class="btn" data-cancel>Cancel</button></div>
|
|
97
|
+
</div>
|
|
98
|
+
</form>
|
|
99
|
+
|
|
100
|
+
<aside id="feed" class="card">
|
|
101
|
+
<header><span>Activity</span><span style="font-weight:400;letter-spacing:0;text-transform:none">this session<button class="x" id="feed-hide" title="Hide (A)" aria-label="Hide activity">✕</button></span></header>
|
|
102
|
+
<div id="feed-body"></div>
|
|
103
|
+
</aside>
|
|
104
|
+
|
|
105
|
+
<div id="legend">
|
|
106
|
+
<span style="--c:#5ad87a">working</span>
|
|
107
|
+
<span style="--c:#8fb4ff">idle</span>
|
|
108
|
+
<span style="--c:#ff6b6b">blocked</span>
|
|
109
|
+
<span style="--c:#ffd166">done</span>
|
|
110
|
+
<span style="--c:#7a7f93">unknown</span>
|
|
111
|
+
</div>
|
|
112
|
+
<div id="hint">click a desk to open its terminal · drag to pan · wheel to zoom · <kbd>J</kbd>/<kbd>K</kbd> next desk · <kbd>1</kbd>–<kbd>9</kbd> floor · <kbd>F</kbd> fit · <kbd>R</kbd> roster · <kbd>A</kbd> activity · <kbd>B</kbd> build · <kbd>M</kbd> music · <kbd>Esc</kbd> close</div>
|
|
113
|
+
<div id="build-hint">Build mode · click a <b>+</b> to add a desk or a room · <b>B</b> or <b>Esc</b> to leave</div>
|
|
114
|
+
<div id="toast" class="card" role="status" hidden></div>
|
|
115
|
+
<div id="tip"></div>
|
|
116
|
+
<div id="floor-banner" aria-live="polite"></div>
|
|
117
|
+
<div id="empty" class="card" hidden><h2></h2><p></p></div>
|
|
118
|
+
<aside id="demo" class="card" hidden aria-label="About this demo">
|
|
119
|
+
<span class="tag">Demo</span>
|
|
120
|
+
<span class="txt">Simulated agents. Click a desk, then give its agent a task.</span>
|
|
121
|
+
<button class="cmd" data-copy title="Copy the command that runs it on your own machine"><span>$</span> npx @kauakdev/kauak serve<i>copy</i></button>
|
|
122
|
+
<a class="btn" href="https://github.com/kauakdev/kauak" target="_blank" rel="noopener">GitHub</a>
|
|
123
|
+
<button class="x" data-close aria-label="Hide">✕</button>
|
|
124
|
+
</aside>
|
|
125
|
+
|
|
126
|
+
<aside id="panel" data-status="unknown">
|
|
127
|
+
<div id="panel-resize" title="Drag to resize · double-click for the default width"></div>
|
|
128
|
+
<header>
|
|
129
|
+
<div class="status"></div>
|
|
130
|
+
<span id="panel-kind">shell</span>
|
|
131
|
+
<div class="text"><div id="panel-title">—</div><div id="panel-meta"></div></div>
|
|
132
|
+
<span id="panel-ctx" hidden><span class="ctx"><i></i></span><span class="pct"></span></span>
|
|
133
|
+
<span id="panel-status"></span>
|
|
134
|
+
<button id="panel-focus" class="primary"></button>
|
|
135
|
+
<button id="panel-close" title="Close (Esc)">✕</button>
|
|
136
|
+
</header>
|
|
137
|
+
<div id="panel-term"></div>
|
|
138
|
+
<form id="panel-input" autocomplete="off">
|
|
139
|
+
<ul id="panel-slash" role="listbox" aria-label="Commands" hidden></ul>
|
|
140
|
+
<button type="button" id="panel-live" title="Back to the latest output" hidden>Jump to bottom ↓</button>
|
|
141
|
+
<div class="compose">
|
|
142
|
+
<textarea id="panel-text" rows="1" spellcheck="false" autocapitalize="off" role="combobox" aria-expanded="false" aria-label="Message to send to the pane"></textarea>
|
|
143
|
+
<button type="button" id="panel-take" title="Use the suggestion (Tab)" hidden>Tab ↹</button>
|
|
144
|
+
<button type="submit" id="panel-send" class="primary">Enter ↵</button>
|
|
145
|
+
</div>
|
|
146
|
+
<div class="keys">
|
|
147
|
+
<span role="toolbar" aria-label="Send a key to the pane">
|
|
148
|
+
<button type="button" data-key="esc" title="Esc: interrupt an agent or reject its request" aria-label="Escape">Esc</button>
|
|
149
|
+
<button type="button" data-key="ctrl+c" title="Ctrl+C" aria-label="Control C">⌃C</button>
|
|
150
|
+
<button type="button" data-key="up" title="Up arrow: previous option or history" aria-label="Up arrow">↑</button>
|
|
151
|
+
<button type="button" data-key="down" title="Down arrow: next option" aria-label="Down arrow">↓</button>
|
|
152
|
+
<button type="button" data-key="tab" title="Tab" aria-label="Tab">Tab</button>
|
|
153
|
+
<button type="button" data-key="shift+tab" title="Shift+Tab: switch the agent's mode" aria-label="Shift Tab">⇧Tab</button>
|
|
154
|
+
</span>
|
|
155
|
+
<span id="panel-hint" aria-live="polite"></span>
|
|
156
|
+
</div>
|
|
157
|
+
</form>
|
|
158
|
+
</aside>
|
|
159
|
+
</body>
|
|
160
|
+
</html>
|
package/dist/kauak.png
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kauakdev/kauak",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "A Sims-style isometric office that shows what your Herdr coding agents are doing, live",
|
|
5
|
+
"keywords": ["herdr", "coding-agents", "claude-code", "codex", "terminal", "multiplexer", "dashboard", "isometric", "pixijs"],
|
|
6
|
+
"homepage": "https://github.com/kauakdev/kauak#readme",
|
|
7
|
+
"bugs": "https://github.com/kauakdev/kauak/issues",
|
|
8
|
+
"repository": { "type": "git", "url": "git+https://github.com/kauakdev/kauak.git" },
|
|
9
|
+
"license": "Apache-2.0",
|
|
10
|
+
"author": "Agustin Renteria Beltran",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"bin": { "kauak": "bin/kauak.js" },
|
|
13
|
+
"exports": { "./package.json": "./package.json" },
|
|
14
|
+
"files": ["bin", "cli", "bridge", "dist", "!**/*.test.*", "!**/fixtures", "!**/*.d.ts", "!dist/kauak-banner.png"],
|
|
15
|
+
"engines": { "node": ">=22" },
|
|
16
|
+
"publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
|
|
17
|
+
"scripts": {
|
|
18
|
+
"start": "node bin/kauak.js serve",
|
|
19
|
+
"test": "node --test",
|
|
20
|
+
"prepack": "pnpm --filter @kauak/protocol --filter @kauak/bridge --filter @kauak/web typecheck && pnpm --filter @kauak/web build && pnpm --filter @kauak/bridge bundle && node scripts/assemble.js",
|
|
21
|
+
"postpack": "node scripts/assemble.js --clean"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"ws": "^8.18.0"
|
|
25
|
+
}
|
|
26
|
+
}
|