@pen.dev/cli 0.3.9 → 0.3.11
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/README.md +6 -4
- package/dist/browserAll-BVNfpTCH.mjs +15 -0
- package/dist/chunk-V2S4ZYJR-B9IPlZGx.mjs +7 -0
- package/dist/esm-N6I77Ols.mjs +63 -0
- package/dist/esm-Rg36NIlb.mjs +2 -0
- package/dist/html-BzmDMzcE.mjs +26 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +3 -2
- package/dist/init-79Ivv_Iw.mjs +555 -0
- package/dist/limit-io-DqzENcBM.mjs +3 -0
- package/dist/module-ES6BEMUI-nLDaJUtp.mjs +2 -0
- package/dist/module-asyncify-2EFITU5U-B-l6gXmU.mjs +2 -0
- package/dist/node_modules/@highagency/pencil-wasm/package.json +1 -1
- package/dist/node_modules/@highagency/pencil-wasm/pencil.wasm +0 -0
- package/dist/out/mcp-server-darwin-arm64 +0 -0
- package/dist/out/mcp-server-darwin-x64 +0 -0
- package/dist/out/mcp-server-linux-arm64 +0 -0
- package/dist/out/mcp-server-linux-x64 +0 -0
- package/dist/out/mcp-server-windows-arm64.exe +0 -0
- package/dist/out/mcp-server-windows-x64.exe +0 -0
- package/dist/out/skills/pen-dev/SKILL.md +4 -1
- package/dist/out/skills/pen-dev/execute.md +1 -0
- package/dist/out/skills/pen-dev/pen-schema.md +14 -8
- package/dist/out/skills/pen-dev/scripts-and-shaders.md +35 -3
- package/dist/out/skills/pen-dev/whiteboard.md +120 -0
- package/dist/rolldown-runtime-DUc_qoCt.mjs +2 -0
- package/dist/standalone-DmZDPu3b.mjs +30 -0
- package/dist/validate-response-Cd_RKmhH.mjs +3 -0
- package/dist/webworkerAll-tGgDIbvf.mjs +2 -0
- package/package.json +34 -32
- package/dist/browserAll-D_luQzBO.mjs +0 -2
- package/dist/dist-CbU0Evuc.mjs +0 -4
- package/dist/emscripten-module.browser-F76W5DM6-CQ3fNT5V.mjs +0 -5147
- package/dist/emscripten-module.browser-XIKQQPVU-C295tmz_.mjs +0 -2160
- package/dist/esm-D7vjDQPJ.mjs +0 -2
- package/dist/esm-DBgQcoAH.mjs +0 -25
- package/dist/ffi-CUJpv82f.mjs +0 -2
- package/dist/ffi-Cplg1Nas.mjs +0 -2
- package/dist/html-BzzLf-XM.mjs +0 -26
- package/dist/init-B5EVeDge.mjs +0 -2
- package/dist/module-ES6BEMUI-2G5oIxui.mjs +0 -2
- package/dist/module-asyncify-2EFITU5U-CqIYQibj.mjs +0 -2
- package/dist/standalone-BxPYxoeE.mjs +0 -30
- package/dist/validate-response-CezyBuEO.mjs +0 -3
- package/dist/webworkerAll-BPqqt3nL.mjs +0 -2
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
function e(e,t){if(!e)throw Error(t)}function t(e){if(typeof e!=`number`)throw Error(`invalid int 32: `+typeof e);if(!Number.isInteger(e)||e>2147483647||e<-2147483648)throw Error(`invalid int 32: `+e)}function n(e){if(typeof e!=`number`)throw Error(`invalid uint 32: `+typeof e);if(!Number.isInteger(e)||e>4294967295||e<0)throw Error(`invalid uint 32: `+e)}function r(e){if(typeof e!=`number`)throw Error(`invalid float 32: `+typeof e);if(Number.isFinite(e)&&(e>34028234663852886e22||e<-34028234663852886e22))throw Error(`invalid float 32: `+e)}const i=Symbol(`@bufbuild/protobuf/enum-type`);function a(t){let n=t[i];return e(n,`missing enum type on enum object`),n}function o(e,t,n,r){e[i]=s(t,n.map(t=>({no:t.no,name:t.name,localName:e[t.no]})),r)}function s(e,t,n){let r=Object.create(null),i=Object.create(null),a=[];for(let e of t){let t=l(e);a.push(t),r[e.name]=t,i[e.no]=t}return{typeName:e,values:a,findName(e){return r[e]},findNumber(e){return i[e]}}}function c(e,t,n){let r={};for(let e of t){let t=l(e);r[t.localName]=t.no,r[t.no]=t.localName}return o(r,e,t,n),r}function l(e){return`localName`in e?e:Object.assign(Object.assign({},e),{localName:e.name})}var u=class{equals(e){return this.getType().runtime.util.equals(this.getType(),this,e)}clone(){return this.getType().runtime.util.clone(this)}fromBinary(e,t){let n=this.getType().runtime.bin,r=n.makeReadOptions(t);return n.readMessage(this,r.readerFactory(e),e.byteLength,r),this}fromJson(e,t){let n=this.getType(),r=n.runtime.json,i=r.makeReadOptions(t);return r.readMessage(n,e,i,this),this}fromJsonString(e,t){let n;try{n=JSON.parse(e)}catch(e){throw Error(`cannot decode ${this.getType().typeName} from JSON: ${e instanceof Error?e.message:String(e)}`)}return this.fromJson(n,t)}toBinary(e){let t=this.getType().runtime.bin,n=t.makeWriteOptions(e),r=n.writerFactory();return t.writeMessage(this,r,n),r.finish()}toJson(e){let t=this.getType().runtime.json,n=t.makeWriteOptions(e);return t.writeMessage(this,n)}toJsonString(e){let t=this.toJson(e);return JSON.stringify(t,null,e?.prettySpaces??0)}toJSON(){return this.toJson({emitDefaultValues:!0})}getType(){return Object.getPrototypeOf(this).constructor}};function ee(e,t,n,r){let i=r?.localName??t.substring(t.lastIndexOf(`.`)+1),a={[i]:function(t){e.util.initFields(this),e.util.initPartial(t,this)}}[i];return Object.setPrototypeOf(a.prototype,new u),Object.assign(a,{runtime:e,typeName:t,fields:e.util.newFieldList(n),fromBinary(e,t){return new a().fromBinary(e,t)},fromJson(e,t){return new a().fromJson(e,t)},fromJsonString(e,t){return new a().fromJsonString(e,t)},equals(t,n){return e.util.equals(a,t,n)}}),a}function te(){let e=0,t=0;for(let n=0;n<28;n+=7){let r=this.buf[this.pos++];if(e|=(r&127)<<n,!(r&128))return this.assertBounds(),[e,t]}let n=this.buf[this.pos++];if(e|=(n&15)<<28,t=(n&112)>>4,!(n&128))return this.assertBounds(),[e,t];for(let n=3;n<=31;n+=7){let r=this.buf[this.pos++];if(t|=(r&127)<<n,!(r&128))return this.assertBounds(),[e,t]}throw Error(`invalid varint`)}function d(e,t,n){for(let r=0;r<28;r+=7){let i=e>>>r,a=!(!(i>>>7)&&t==0),o=(a?i|128:i)&255;if(n.push(o),!a)return}let r=e>>>28&15|(t&7)<<4,i=!!(t>>3);if(n.push((i?r|128:r)&255),i){for(let e=3;e<31;e+=7){let r=t>>>e,i=!!(r>>>7),a=(i?r|128:r)&255;if(n.push(a),!i)return}n.push(t>>>31&1)}}const f=4294967296;function p(e){let t=e[0]===`-`;t&&(e=e.slice(1));let n=1e6,r=0,i=0;function a(t,a){let o=Number(e.slice(t,a));i*=n,r=r*n+o,r>=f&&(i+=r/f|0,r%=f)}return a(-24,-18),a(-18,-12),a(-12,-6),a(-6),t?h(r,i):m(r,i)}function ne(e,t){let n=m(e,t),r=n.hi&2147483648;r&&(n=h(n.lo,n.hi));let i=re(n.lo,n.hi);return r?`-`+i:i}function re(e,t){if({lo:e,hi:t}=ie(e,t),t<=2097151)return String(f*t+e);let n=e&16777215,r=(e>>>24|t<<8)&16777215,i=t>>16&65535,a=n+r*6777216+i*6710656,o=r+i*8147497,s=i*2,c=1e7;return a>=c&&(o+=Math.floor(a/c),a%=c),o>=c&&(s+=Math.floor(o/c),o%=c),s.toString()+ae(o)+ae(a)}function ie(e,t){return{lo:e>>>0,hi:t>>>0}}function m(e,t){return{lo:e|0,hi:t|0}}function h(e,t){return t=~t,e?e=~e+1:t+=1,m(e,t)}const ae=e=>{let t=String(e);return`0000000`.slice(t.length)+t};function oe(e,t){if(e>=0){for(;e>127;)t.push(e&127|128),e>>>=7;t.push(e)}else{for(let n=0;n<9;n++)t.push(e&127|128),e>>=7;t.push(1)}}function se(){let e=this.buf[this.pos++],t=e&127;if(!(e&128)||(e=this.buf[this.pos++],t|=(e&127)<<7,!(e&128))||(e=this.buf[this.pos++],t|=(e&127)<<14,!(e&128))||(e=this.buf[this.pos++],t|=(e&127)<<21,!(e&128)))return this.assertBounds(),t;e=this.buf[this.pos++],t|=(e&15)<<28;for(let t=5;e&128&&t<10;t++)e=this.buf[this.pos++];if(e&128)throw Error(`invalid varint`);return this.assertBounds(),t>>>0}function ce(){let t=/* @__PURE__ */ new DataView(/* @__PURE__ */ new ArrayBuffer(8));if(typeof BigInt==`function`&&typeof t.getBigInt64==`function`&&typeof t.getBigUint64==`function`&&typeof t.setBigInt64==`function`&&typeof t.setBigUint64==`function`&&(typeof process!=`object`||typeof process.env!=`object`||process.env.BUF_BIGINT_DISABLE!==`1`)){let e=BigInt(`-9223372036854775808`),n=BigInt(`9223372036854775807`),r=BigInt(`0`),i=BigInt(`18446744073709551615`);return{zero:BigInt(0),supported:!0,parse(t){let r=typeof t==`bigint`?t:BigInt(t);if(r>n||r<e)throw Error(`int64 invalid: ${t}`);return r},uParse(e){let t=typeof e==`bigint`?e:BigInt(e);if(t>i||t<r)throw Error(`uint64 invalid: ${e}`);return t},enc(e){return t.setBigInt64(0,this.parse(e),!0),{lo:t.getInt32(0,!0),hi:t.getInt32(4,!0)}},uEnc(e){return t.setBigInt64(0,this.uParse(e),!0),{lo:t.getInt32(0,!0),hi:t.getInt32(4,!0)}},dec(e,n){return t.setInt32(0,e,!0),t.setInt32(4,n,!0),t.getBigInt64(0,!0)},uDec(e,n){return t.setInt32(0,e,!0),t.setInt32(4,n,!0),t.getBigUint64(0,!0)}}}let n=t=>e(/^-?[0-9]+$/.test(t),`int64 invalid: ${t}`),r=t=>e(/^[0-9]+$/.test(t),`uint64 invalid: ${t}`);return{zero:`0`,supported:!1,parse(e){return typeof e!=`string`&&(e=e.toString()),n(e),e},uParse(e){return typeof e!=`string`&&(e=e.toString()),r(e),e},enc(e){return typeof e!=`string`&&(e=e.toString()),n(e),p(e)},uEnc(e){return typeof e!=`string`&&(e=e.toString()),r(e),p(e)},dec(e,t){return ne(e,t)},uDec(e,t){return re(e,t)}}}const g=ce();var _;(function(e){e[e.DOUBLE=1]=`DOUBLE`,e[e.FLOAT=2]=`FLOAT`,e[e.INT64=3]=`INT64`,e[e.UINT64=4]=`UINT64`,e[e.INT32=5]=`INT32`,e[e.FIXED64=6]=`FIXED64`,e[e.FIXED32=7]=`FIXED32`,e[e.BOOL=8]=`BOOL`,e[e.STRING=9]=`STRING`,e[e.BYTES=12]=`BYTES`,e[e.UINT32=13]=`UINT32`,e[e.SFIXED32=15]=`SFIXED32`,e[e.SFIXED64=16]=`SFIXED64`,e[e.SINT32=17]=`SINT32`,e[e.SINT64=18]=`SINT64`})(_||={});var v;(function(e){e[e.BIGINT=0]=`BIGINT`,e[e.STRING=1]=`STRING`})(v||={});function y(e,t,n){if(t===n)return!0;if(e==_.BYTES){if(!(t instanceof Uint8Array)||!(n instanceof Uint8Array)||t.length!==n.length)return!1;for(let e=0;e<t.length;e++)if(t[e]!==n[e])return!1;return!0}switch(e){case _.UINT64:case _.FIXED64:case _.INT64:case _.SFIXED64:case _.SINT64:return t==n}return!1}function b(e,t){switch(e){case _.BOOL:return!1;case _.UINT64:case _.FIXED64:case _.INT64:case _.SFIXED64:case _.SINT64:return t==0?g.zero:`0`;case _.DOUBLE:case _.FLOAT:return 0;case _.BYTES:return/* @__PURE__ */ new Uint8Array;case _.STRING:return``;default:return 0}}function x(e,t){switch(e){case _.BOOL:return t===!1;case _.STRING:return t===``;case _.BYTES:return t instanceof Uint8Array&&!t.byteLength;default:return t==0}}var S;(function(e){e[e.Varint=0]=`Varint`,e[e.Bit64=1]=`Bit64`,e[e.LengthDelimited=2]=`LengthDelimited`,e[e.StartGroup=3]=`StartGroup`,e[e.EndGroup=4]=`EndGroup`,e[e.Bit32=5]=`Bit32`})(S||={});var le=class{constructor(e){this.stack=[],this.textEncoder=e??new TextEncoder,this.chunks=[],this.buf=[]}finish(){this.chunks.push(new Uint8Array(this.buf));let e=0;for(let t=0;t<this.chunks.length;t++)e+=this.chunks[t].length;let t=new Uint8Array(e),n=0;for(let e=0;e<this.chunks.length;e++)t.set(this.chunks[e],n),n+=this.chunks[e].length;return this.chunks=[],t}fork(){return this.stack.push({chunks:this.chunks,buf:this.buf}),this.chunks=[],this.buf=[],this}join(){let e=this.finish(),t=this.stack.pop();if(!t)throw Error(`invalid state, fork stack empty`);return this.chunks=t.chunks,this.buf=t.buf,this.uint32(e.byteLength),this.raw(e)}tag(e,t){return this.uint32((e<<3|t)>>>0)}raw(e){return this.buf.length&&(this.chunks.push(new Uint8Array(this.buf)),this.buf=[]),this.chunks.push(e),this}uint32(e){for(n(e);e>127;)this.buf.push(e&127|128),e>>>=7;return this.buf.push(e),this}int32(e){return t(e),oe(e,this.buf),this}bool(e){return this.buf.push(+!!e),this}bytes(e){return this.uint32(e.byteLength),this.raw(e)}string(e){let t=this.textEncoder.encode(e);return this.uint32(t.byteLength),this.raw(t)}float(e){r(e);let t=/* @__PURE__ */ new Uint8Array(4);return new DataView(t.buffer).setFloat32(0,e,!0),this.raw(t)}double(e){let t=/* @__PURE__ */ new Uint8Array(8);return new DataView(t.buffer).setFloat64(0,e,!0),this.raw(t)}fixed32(e){n(e);let t=/* @__PURE__ */ new Uint8Array(4);return new DataView(t.buffer).setUint32(0,e,!0),this.raw(t)}sfixed32(e){t(e);let n=/* @__PURE__ */ new Uint8Array(4);return new DataView(n.buffer).setInt32(0,e,!0),this.raw(n)}sint32(e){return t(e),e=(e<<1^e>>31)>>>0,oe(e,this.buf),this}sfixed64(e){let t=/* @__PURE__ */ new Uint8Array(8),n=new DataView(t.buffer),r=g.enc(e);return n.setInt32(0,r.lo,!0),n.setInt32(4,r.hi,!0),this.raw(t)}fixed64(e){let t=/* @__PURE__ */ new Uint8Array(8),n=new DataView(t.buffer),r=g.uEnc(e);return n.setInt32(0,r.lo,!0),n.setInt32(4,r.hi,!0),this.raw(t)}int64(e){let t=g.enc(e);return d(t.lo,t.hi,this.buf),this}sint64(e){let t=g.enc(e),n=t.hi>>31;return d(t.lo<<1^n,(t.hi<<1|t.lo>>>31)^n,this.buf),this}uint64(e){let t=g.uEnc(e);return d(t.lo,t.hi,this.buf),this}},ue=class{constructor(e,t){this.varint64=te,this.uint32=se,this.buf=e,this.len=e.length,this.pos=0,this.view=new DataView(e.buffer,e.byteOffset,e.byteLength),this.textDecoder=t??new TextDecoder}tag(){let e=this.uint32(),t=e>>>3,n=e&7;if(t<=0||n<0||n>5)throw Error(`illegal tag: field no `+t+` wire type `+n);return[t,n]}skip(e,t){let n=this.pos;switch(e){case S.Varint:for(;this.buf[this.pos++]&128;);break;case S.Bit64:this.pos+=4;case S.Bit32:this.pos+=4;break;case S.LengthDelimited:let n=this.uint32();this.pos+=n;break;case S.StartGroup:for(;;){let[e,n]=this.tag();if(n===S.EndGroup){if(t!==void 0&&e!==t)throw Error(`invalid end group tag`);break}this.skip(n,e)}break;default:throw Error(`cant skip wire type `+e)}return this.assertBounds(),this.buf.subarray(n,this.pos)}assertBounds(){if(this.pos>this.len)throw RangeError(`premature EOF`)}int32(){return this.uint32()|0}sint32(){let e=this.uint32();return e>>>1^-(e&1)}int64(){return g.dec(...this.varint64())}uint64(){return g.uDec(...this.varint64())}sint64(){let[e,t]=this.varint64(),n=-(e&1);return e=(e>>>1|(t&1)<<31)^n,t=t>>>1^n,g.dec(e,t)}bool(){let[e,t]=this.varint64();return e!==0||t!==0}fixed32(){return this.view.getUint32((this.pos+=4)-4,!0)}sfixed32(){return this.view.getInt32((this.pos+=4)-4,!0)}fixed64(){return g.uDec(this.sfixed32(),this.sfixed32())}sfixed64(){return g.dec(this.sfixed32(),this.sfixed32())}float(){return this.view.getFloat32((this.pos+=4)-4,!0)}double(){return this.view.getFloat64((this.pos+=8)-8,!0)}bytes(){let e=this.uint32(),t=this.pos;return this.pos+=e,this.assertBounds(),this.buf.subarray(t,t+e)}string(){return this.textDecoder.decode(this.bytes())}};function de(e,t,n,r){let i;return{typeName:t,extendee:n,get field(){if(!i){let n=typeof r==`function`?r():r;n.name=t.split(`.`).pop(),n.jsonName=`[${t}]`,i=e.util.newFieldList([n]).list()[0]}return i},runtime:e}}function fe(e){let t=e.field.localName,n=Object.create(null);return n[t]=pe(e),[n,()=>n[t]]}function pe(e){let t=e.field;if(t.repeated)return[];if(t.default!==void 0)return t.default;switch(t.kind){case`enum`:return t.T.values[0].no;case`scalar`:return b(t.T,t.L);case`message`:let e=t.T,n=new e;return e.fieldWrapper?e.fieldWrapper.unwrapField(n):n;case`map`:throw`map fields are not allowed to be extensions`}}function me(e,t){if(!t.repeated&&(t.kind==`enum`||t.kind==`scalar`)){for(let n=e.length-1;n>=0;--n)if(e[n].no==t.no)return[e[n]];return[]}return e.filter(e=>e.no===t.no)}let C=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`.split(``),w=[];for(let e=0;e<C.length;e++)w[C[e].charCodeAt(0)]=e;w[45]=C.indexOf(`+`),w[95]=C.indexOf(`/`);const T={dec(e){let t=e.length*3/4;e[e.length-2]==`=`?t-=2:e[e.length-1]==`=`&&--t;let n=new Uint8Array(t),r=0,i=0,a,o=0;for(let t=0;t<e.length;t++){if(a=w[e.charCodeAt(t)],a===void 0)switch(e[t]){case`=`:i=0;case`
|
|
3
|
+
`:case`\r`:case` `:case` `:continue;default:throw Error(`invalid base64 string.`)}switch(i){case 0:o=a,i=1;break;case 1:n[r++]=o<<2|(a&48)>>4,o=a,i=2;break;case 2:n[r++]=(o&15)<<4|(a&60)>>2,o=a,i=3;break;case 3:n[r++]=(o&3)<<6|a,i=0}}if(i==1)throw Error(`invalid base64 string.`);return n.subarray(0,r)},enc(e){let t=``,n=0,r,i=0;for(let a=0;a<e.length;a++)switch(r=e[a],n){case 0:t+=C[r>>2],i=(r&3)<<4,n=1;break;case 1:t+=C[i|r>>4],i=(r&15)<<2,n=2;break;case 2:t+=C[i|r>>6],t+=C[r&63],n=0}return n&&(t+=C[i],t+=`=`,n==1&&(t+=`=`)),t}};function he(e,t,n){ve(t,e);let r=t.runtime.bin.makeReadOptions(n),i=me(e.getType().runtime.bin.listUnknownFields(e),t.field),[a,o]=fe(t);for(let e of i)t.runtime.bin.readField(a,r.readerFactory(e.data),t.field,e.wireType,r);return o()}function ge(e,t,n,r){ve(t,e);let i=t.runtime.bin.makeReadOptions(r),a=t.runtime.bin.makeWriteOptions(r);if(_e(e,t)){let n=e.getType().runtime.bin.listUnknownFields(e).filter(e=>e.no!=t.field.no);e.getType().runtime.bin.discardUnknownFields(e);for(let t of n)e.getType().runtime.bin.onUnknownField(e,t.no,t.wireType,t.data)}let o=a.writerFactory(),s=t.field;!s.opt&&!s.repeated&&(s.kind==`enum`||s.kind==`scalar`)&&(s=Object.assign(Object.assign({},t.field),{opt:!0})),t.runtime.bin.writeField(s,n,o,a);let c=i.readerFactory(o.finish());for(;c.pos<c.len;){let[t,n]=c.tag(),r=c.skip(n,t);e.getType().runtime.bin.onUnknownField(e,t,n,r)}}function _e(e,t){let n=e.getType();return t.extendee.typeName===n.typeName&&!!n.runtime.bin.listUnknownFields(e).find(e=>e.no==t.field.no)}function ve(t,n){e(t.extendee.typeName==n.getType().typeName,`extension ${t.typeName} can only be applied to message ${t.extendee.typeName}`)}function ye(e,t){let n=e.localName;if(e.repeated)return t[n].length>0;if(e.oneof)return t[e.oneof.localName].case===n;switch(e.kind){case`enum`:case`scalar`:return e.opt||e.req?t[n]!==void 0:e.kind==`enum`?t[n]!==e.T.values[0].no:!x(e.T,t[n]);case`message`:return t[n]!==void 0;case`map`:return Object.keys(t[n]).length>0}}function be(e,t){let n=e.localName,r=!e.opt&&!e.req;if(e.repeated)t[n]=[];else if(e.oneof)t[e.oneof.localName]={case:void 0};else switch(e.kind){case`map`:t[n]={};break;case`enum`:t[n]=r?e.T.values[0].no:void 0;break;case`scalar`:t[n]=r?b(e.T,e.L):void 0;break;case`message`:t[n]=void 0}}function E(e,t){if(typeof e!=`object`||!e||!Object.getOwnPropertyNames(u.prototype).every(t=>t in e&&typeof e[t]==`function`))return!1;let n=e.getType();return n===null||typeof n!=`function`||!(`typeName`in n)||typeof n.typeName!=`string`?!1:t===void 0||n.typeName==t.typeName}function D(e,t){return E(t)||!e.fieldWrapper?t:e.fieldWrapper.wrapField(t)}_.DOUBLE,_.FLOAT,_.INT64,_.UINT64,_.INT32,_.UINT32,_.BOOL,_.STRING,_.BYTES;const O={ignoreUnknownFields:!1},k={emitDefaultValues:!1,enumAsInteger:!1,useProtoFieldName:!1,prettySpaces:0};function xe(e){return e?Object.assign(Object.assign({},O),e):O}function Se(e){return e?Object.assign(Object.assign({},k),e):k}const A=Symbol(),j=Symbol();function Ce(){return{makeReadOptions:xe,makeWriteOptions:Se,readMessage(e,t,n,r){if(t==null||Array.isArray(t)||typeof t!=`object`)throw Error(`cannot decode message ${e.typeName} from JSON: ${M(t)}`);r??=new e;let i=/* @__PURE__ */ new Map,a=n.typeRegistry;for(let[o,s]of Object.entries(t)){let t=e.fields.findJsonName(o);if(t){if(t.oneof){if(s===null&&t.kind==`scalar`)continue;let n=i.get(t.oneof);if(n!==void 0)throw Error(`cannot decode message ${e.typeName} from JSON: multiple keys for oneof "${t.oneof.name}" present: "${n}", "${o}"`);i.set(t.oneof,o)}N(r,s,t,n,e)}else{let t=!1;if(a?.findExtension&&o.startsWith(`[`)&&o.endsWith(`]`)){let i=a.findExtension(o.substring(1,o.length-1));if(i&&i.extendee.typeName==e.typeName){t=!0;let[e,a]=fe(i);N(e,s,i.field,n,i),ge(r,i,a(),n)}}if(!t&&!n.ignoreUnknownFields)throw Error(`cannot decode message ${e.typeName} from JSON: key "${o}" is unknown`)}}return r},writeMessage(e,t){let n=e.getType(),r={},i;try{for(i of n.fields.byNumber()){if(!ye(i,e)){if(i.req)throw`required field not set`;if(!t.emitDefaultValues||!Te(i))continue}let n=i.oneof?e[i.oneof.localName].value:e[i.localName],a=I(i,n,t);a!==void 0&&(r[t.useProtoFieldName?i.name:i.jsonName]=a)}let a=t.typeRegistry;if(a?.findExtensionFor)for(let i of n.runtime.bin.listUnknownFields(e)){let o=a.findExtensionFor(n.typeName,i.no);if(o&&_e(e,o)){let n=he(e,o,t),i=I(o.field,n,t);i!==void 0&&(r[o.field.jsonName]=i)}}}catch(e){let t=i?`cannot encode field ${n.typeName}.${i.name} to JSON`:`cannot encode message ${n.typeName} to JSON`,r=e instanceof Error?e.message:String(e);throw Error(t+(r.length>0?`: ${r}`:``))}return r},readScalar(e,t,n){return P(e,t,n??v.BIGINT,!0)},writeScalar(e,t,n){if(t!==void 0&&(n||x(e,t)))return R(e,t)},debug:M}}function M(e){if(e===null)return`null`;switch(typeof e){case`object`:return Array.isArray(e)?`array`:`object`;case`string`:return e.length>100?`string`:`"${e.split(`"`).join(`\\"`)}"`;default:return String(e)}}function N(t,n,r,i,a){let o=r.localName;if(r.repeated){if(e(r.kind!=`map`),n===null)return;if(!Array.isArray(n))throw Error(`cannot decode field ${a.typeName}.${r.name} from JSON: ${M(n)}`);let s=t[o];for(let e of n){if(e===null)throw Error(`cannot decode field ${a.typeName}.${r.name} from JSON: ${M(e)}`);switch(r.kind){case`message`:s.push(r.T.fromJson(e,i));break;case`enum`:let t=F(r.T,e,i.ignoreUnknownFields,!0);t!==j&&s.push(t);break;case`scalar`:try{s.push(P(r.T,e,r.L,!0))}catch(t){let n=`cannot decode field ${a.typeName}.${r.name} from JSON: ${M(e)}`;throw t instanceof Error&&t.message.length>0&&(n+=`: ${t.message}`),Error(n)}}}}else if(r.kind==`map`){if(n===null)return;if(typeof n!=`object`||Array.isArray(n))throw Error(`cannot decode field ${a.typeName}.${r.name} from JSON: ${M(n)}`);let e=t[o];for(let[t,o]of Object.entries(n)){if(o===null)throw Error(`cannot decode field ${a.typeName}.${r.name} from JSON: map value null`);let s;try{s=we(r.K,t)}catch(e){let t=`cannot decode map key for field ${a.typeName}.${r.name} from JSON: ${M(n)}`;throw e instanceof Error&&e.message.length>0&&(t+=`: ${e.message}`),Error(t)}switch(r.V.kind){case`message`:e[s]=r.V.T.fromJson(o,i);break;case`enum`:let t=F(r.V.T,o,i.ignoreUnknownFields,!0);t!==j&&(e[s]=t);break;case`scalar`:try{e[s]=P(r.V.T,o,v.BIGINT,!0)}catch(e){let t=`cannot decode map value for field ${a.typeName}.${r.name} from JSON: ${M(n)}`;throw e instanceof Error&&e.message.length>0&&(t+=`: ${e.message}`),Error(t)}}}}else switch(r.oneof&&(t=t[r.oneof.localName]={case:o},o=`value`),r.kind){case`message`:let e=r.T;if(n===null&&e.typeName!=`google.protobuf.Value`)return;let s=t[o];E(s)?s.fromJson(n,i):(t[o]=s=e.fromJson(n,i),e.fieldWrapper&&!r.oneof&&(t[o]=e.fieldWrapper.unwrapField(s)));break;case`enum`:let c=F(r.T,n,i.ignoreUnknownFields,!1);switch(c){case A:be(r,t);break;case j:break;default:t[o]=c}break;case`scalar`:try{let e=P(r.T,n,r.L,!1);switch(e){case A:be(r,t);break;default:t[o]=e}}catch(e){let t=`cannot decode field ${a.typeName}.${r.name} from JSON: ${M(n)}`;throw e instanceof Error&&e.message.length>0&&(t+=`: ${e.message}`),Error(t)}}}function we(e,t){if(e===_.BOOL)switch(t){case`true`:t=!0;break;case`false`:t=!1}return P(e,t,v.BIGINT,!0).toString()}function P(e,i,a,o){if(i===null)return o?b(e,a):A;switch(e){case _.DOUBLE:case _.FLOAT:if(i===`NaN`)return NaN;if(i===`Infinity`)return 1/0;if(i===`-Infinity`)return-1/0;if(i===``||typeof i==`string`&&i.trim().length!==i.length||typeof i!=`string`&&typeof i!=`number`)break;let o=Number(i);if(Number.isNaN(o)||!Number.isFinite(o))break;return e==_.FLOAT&&r(o),o;case _.INT32:case _.FIXED32:case _.SFIXED32:case _.SINT32:case _.UINT32:let s;if(typeof i==`number`?s=i:typeof i==`string`&&i.length>0&&i.trim().length===i.length&&(s=Number(i)),s===void 0)break;return e==_.UINT32||e==_.FIXED32?n(s):t(s),s;case _.INT64:case _.SFIXED64:case _.SINT64:if(typeof i!=`number`&&typeof i!=`string`)break;let c=g.parse(i);return a?c.toString():c;case _.FIXED64:case _.UINT64:if(typeof i!=`number`&&typeof i!=`string`)break;let l=g.uParse(i);return a?l.toString():l;case _.BOOL:if(typeof i!=`boolean`)break;return i;case _.STRING:if(typeof i!=`string`)break;return i;case _.BYTES:if(i===``)return/* @__PURE__ */ new Uint8Array;if(typeof i!=`string`)break;return T.dec(i)}throw Error()}function F(e,t,n,r){if(t===null)return e.typeName==`google.protobuf.NullValue`?0:r?e.values[0].no:A;switch(typeof t){case`number`:if(Number.isInteger(t))return t;break;case`string`:let r=e.findName(t);if(r!==void 0)return r.no;if(n)return j}throw Error(`cannot decode enum ${e.typeName} from JSON: ${M(t)}`)}function Te(e){return e.repeated||e.kind==`map`?!0:!(e.oneof||e.kind==`message`||e.opt||e.req)}function I(t,n,r){if(t.kind==`map`){e(typeof n==`object`&&!!n);let i={},a=Object.entries(n);switch(t.V.kind){case`scalar`:for(let[e,n]of a)i[e.toString()]=R(t.V.T,n);break;case`message`:for(let[e,t]of a)i[e.toString()]=t.toJson(r);break;case`enum`:let e=t.V.T;for(let[t,n]of a)i[t.toString()]=L(e,n,r.enumAsInteger)}return r.emitDefaultValues||a.length>0?i:void 0}if(t.repeated){e(Array.isArray(n));let i=[];switch(t.kind){case`scalar`:for(let e=0;e<n.length;e++)i.push(R(t.T,n[e]));break;case`enum`:for(let e=0;e<n.length;e++)i.push(L(t.T,n[e],r.enumAsInteger));break;case`message`:for(let e=0;e<n.length;e++)i.push(n[e].toJson(r))}return r.emitDefaultValues||i.length>0?i:void 0}switch(t.kind){case`scalar`:return R(t.T,n);case`enum`:return L(t.T,n,r.enumAsInteger);case`message`:return D(t.T,n).toJson(r)}}function L(t,n,r){return e(typeof n==`number`),t.typeName==`google.protobuf.NullValue`?null:r?n:t.findNumber(n)?.name??n}function R(t,n){switch(t){case _.INT32:case _.SFIXED32:case _.SINT32:case _.FIXED32:case _.UINT32:return e(typeof n==`number`),n;case _.FLOAT:case _.DOUBLE:return e(typeof n==`number`),Number.isNaN(n)?`NaN`:n===1/0?`Infinity`:n===-1/0?`-Infinity`:n;case _.STRING:return e(typeof n==`string`),n;case _.BOOL:return e(typeof n==`boolean`),n;case _.UINT64:case _.FIXED64:case _.INT64:case _.SFIXED64:case _.SINT64:return e(typeof n==`bigint`||typeof n==`string`||typeof n==`number`),n.toString();case _.BYTES:return e(n instanceof Uint8Array),T.enc(n)}}const z=Symbol(`@bufbuild/protobuf/unknown-fields`),B={readUnknownFields:!0,readerFactory:e=>new ue(e)},V={writeUnknownFields:!0,writerFactory:()=>new le};function Ee(e){return e?Object.assign(Object.assign({},B),e):B}function De(e){return e?Object.assign(Object.assign({},V),e):V}function Oe(){return{makeReadOptions:Ee,makeWriteOptions:De,listUnknownFields(e){return e[z]??[]},discardUnknownFields(e){delete e[z]},writeUnknownFields(e,t){let n=e[z];if(n)for(let e of n)t.tag(e.no,e.wireType).raw(e.data)},onUnknownField(e,t,n,r){let i=e;Array.isArray(i[z])||(i[z]=[]),i[z].push({no:t,wireType:n,data:r})},readMessage(e,t,n,r,i){let a=e.getType(),o=i?t.len:t.pos+n,s,c;for(;t.pos<o&&([s,c]=t.tag(),i!==!0||c!=S.EndGroup);){let n=a.fields.find(s);if(!n){let n=t.skip(c,s);r.readUnknownFields&&this.onUnknownField(e,s,c,n);continue}H(e,t,n,c,r)}if(i&&(c!=S.EndGroup||s!==n))throw Error(`invalid end group tag`)},readField:H,writeMessage(e,t,n){let r=e.getType();for(let i of r.fields.byNumber()){if(!ye(i,e)){if(i.req)throw Error(`cannot encode field ${r.typeName}.${i.name} to binary: required field not set`);continue}je(i,i.oneof?e[i.oneof.localName].value:e[i.localName],t,n)}return n.writeUnknownFields&&this.writeUnknownFields(e,t),t},writeField(e,t,n,r){t!==void 0&&je(e,t,n,r)}}}function H(e,t,n,r,i){let{repeated:a,localName:o}=n;switch(n.oneof&&(e=e[n.oneof.localName],e.case!=o&&delete e.value,e.case=o,o=`value`),n.kind){case`scalar`:case`enum`:let s=n.kind==`enum`?_.INT32:n.T,c=W;if(n.kind==`scalar`&&n.L>0&&(c=Ae),a){let n=e[o];if(r==S.LengthDelimited&&s!=_.STRING&&s!=_.BYTES){let e=t.uint32()+t.pos;for(;t.pos<e;)n.push(c(t,s))}else n.push(c(t,s))}else e[o]=c(t,s);break;case`message`:let l=n.T;a?e[o].push(U(t,new l,i,n)):E(e[o])?U(t,e[o],i,n):(e[o]=U(t,new l,i,n),l.fieldWrapper&&!n.oneof&&!n.repeated&&(e[o]=l.fieldWrapper.unwrapField(e[o])));break;case`map`:let[u,ee]=ke(n,t,i);e[o][u]=ee}}function U(e,t,n,r){let i=t.getType().runtime.bin,a=r?.delimited;return i.readMessage(t,e,a?r.no:e.uint32(),n,a),t}function ke(e,t,n){let r=t.uint32(),i=t.pos+r,a,o;for(;t.pos<i;){let[r]=t.tag();switch(r){case 1:a=W(t,e.K);break;case 2:switch(e.V.kind){case`scalar`:o=W(t,e.V.T);break;case`enum`:o=t.int32();break;case`message`:o=U(t,new e.V.T,n,void 0)}}}if(a===void 0&&(a=b(e.K,v.BIGINT)),typeof a!=`string`&&typeof a!=`number`&&(a=a.toString()),o===void 0)switch(e.V.kind){case`scalar`:o=b(e.V.T,v.BIGINT);break;case`enum`:o=e.V.T.values[0].no;break;case`message`:o=new e.V.T}return[a,o]}function Ae(e,t){let n=W(e,t);return typeof n==`bigint`?n.toString():n}function W(e,t){switch(t){case _.STRING:return e.string();case _.BOOL:return e.bool();case _.DOUBLE:return e.double();case _.FLOAT:return e.float();case _.INT32:return e.int32();case _.INT64:return e.int64();case _.UINT64:return e.uint64();case _.FIXED64:return e.fixed64();case _.BYTES:return e.bytes();case _.FIXED32:return e.fixed32();case _.SFIXED32:return e.sfixed32();case _.SFIXED64:return e.sfixed64();case _.SINT64:return e.sint64();case _.UINT32:return e.uint32();case _.SINT32:return e.sint32()}}function je(t,n,r,i){e(n!==void 0);let a=t.repeated;switch(t.kind){case`scalar`:case`enum`:let o=t.kind==`enum`?_.INT32:t.T;if(a){if(e(Array.isArray(n)),t.packed)Pe(r,o,t.no,n);else for(let e of n)G(r,o,t.no,e)}else G(r,o,t.no,n);break;case`message`:if(a){e(Array.isArray(n));for(let e of n)Ne(r,i,t,e)}else Ne(r,i,t,n);break;case`map`:e(typeof n==`object`&&!!n);for(let[e,a]of Object.entries(n))Me(r,i,t,e,a)}}function Me(t,n,r,i,a){t.tag(r.no,S.LengthDelimited),t.fork();let o=i;switch(r.K){case _.INT32:case _.FIXED32:case _.UINT32:case _.SFIXED32:case _.SINT32:o=Number.parseInt(i);break;case _.BOOL:e(i==`true`||i==`false`),o=i==`true`}switch(G(t,r.K,1,o),r.V.kind){case`scalar`:G(t,r.V.T,2,a);break;case`enum`:G(t,_.INT32,2,a);break;case`message`:e(a!==void 0),t.tag(2,S.LengthDelimited).bytes(a.toBinary(n))}t.join()}function Ne(e,t,n,r){let i=D(n.T,r);n.delimited?e.tag(n.no,S.StartGroup).raw(i.toBinary(t)).tag(n.no,S.EndGroup):e.tag(n.no,S.LengthDelimited).bytes(i.toBinary(t))}function G(t,n,r,i){e(i!==void 0);let[a,o]=Fe(n);t.tag(r,a)[o](i)}function Pe(e,t,n,r){if(!r.length)return;e.tag(n,S.LengthDelimited).fork();let[,i]=Fe(t);for(let t=0;t<r.length;t++)e[i](r[t]);e.join()}function Fe(e){let t=S.Varint;switch(e){case _.BYTES:case _.STRING:t=S.LengthDelimited;break;case _.DOUBLE:case _.FIXED64:case _.SFIXED64:t=S.Bit64;break;case _.FIXED32:case _.SFIXED32:case _.FLOAT:t=S.Bit32}let n=_[e].toLowerCase();return[t,n]}function Ie(){return{setEnumType:o,initPartial(e,t){if(e===void 0)return;let n=t.getType();for(let r of n.fields.byMember()){let n=r.localName,i=t,a=e;if(a[n]!=null)switch(r.kind){case`oneof`:let e=a[n].case;if(e===void 0)continue;let t=r.findField(e),o=a[n].value;t&&t.kind==`message`&&!E(o,t.T)?o=new t.T(o):t&&t.kind===`scalar`&&t.T===_.BYTES&&(o=q(o)),i[n]={case:e,value:o};break;case`scalar`:case`enum`:let s=a[n];r.T===_.BYTES&&(s=r.repeated?s.map(q):q(s)),i[n]=s;break;case`map`:switch(r.V.kind){case`scalar`:case`enum`:if(r.V.T===_.BYTES)for(let[e,t]of Object.entries(a[n]))i[n][e]=q(t);else Object.assign(i[n],a[n]);break;case`message`:let e=r.V.T;for(let t of Object.keys(a[n])){let r=a[n][t];e.fieldWrapper||(r=new e(r)),i[n][t]=r}}break;case`message`:let c=r.T;if(r.repeated)i[n]=a[n].map(e=>E(e,c)?e:new c(e));else{let e=a[n];i[n]=c.fieldWrapper?c.typeName===`google.protobuf.BytesValue`?q(e):e:E(e,c)?e:new c(e)}}}},equals(e,t,n){return t===n?!0:!t||!n?!1:e.fields.byMember().every(e=>{let r=t[e.localName],i=n[e.localName];if(e.repeated){if(r.length!==i.length)return!1;switch(e.kind){case`message`:return r.every((t,n)=>e.T.equals(t,i[n]));case`scalar`:return r.every((t,n)=>y(e.T,t,i[n]));case`enum`:return r.every((e,t)=>y(_.INT32,e,i[t]))}throw Error(`repeated cannot contain ${e.kind}`)}switch(e.kind){case`message`:return e.T.equals(r,i);case`enum`:return y(_.INT32,r,i);case`scalar`:return y(e.T,r,i);case`oneof`:if(r.case!==i.case)return!1;let t=e.findField(r.case);if(t===void 0)return!0;switch(t.kind){case`message`:return t.T.equals(r.value,i.value);case`enum`:return y(_.INT32,r.value,i.value);case`scalar`:return y(t.T,r.value,i.value)}throw Error(`oneof cannot contain ${t.kind}`);case`map`:let n=Object.keys(r).concat(Object.keys(i));switch(e.V.kind){case`message`:let t=e.V.T;return n.every(e=>t.equals(r[e],i[e]));case`enum`:return n.every(e=>y(_.INT32,r[e],i[e]));case`scalar`:let a=e.V.T;return n.every(e=>y(a,r[e],i[e]))}}})},clone(e){let t=e.getType(),n=new t,r=n;for(let n of t.fields.byMember()){let t=e[n.localName],i;if(n.repeated)i=t.map(K);else if(n.kind==`map`){i=r[n.localName];for(let[e,n]of Object.entries(t))i[e]=K(n)}else i=n.kind==`oneof`?n.findField(t.case)?{case:t.case,value:K(t.value)}:{case:void 0}:K(t);r[n.localName]=i}for(let n of t.runtime.bin.listUnknownFields(e))t.runtime.bin.onUnknownField(r,n.no,n.wireType,n.data);return n}}}function K(e){if(e===void 0)return e;if(E(e))return e.clone();if(e instanceof Uint8Array){let t=new Uint8Array(e.byteLength);return t.set(e),t}return e}function q(e){return e instanceof Uint8Array?e:new Uint8Array(e)}function Le(e,t,n){return{syntax:e,json:Ce(),bin:Oe(),util:Object.assign(Object.assign({},Ie()),{newFieldList:t,initFields:n}),makeMessageType(e,t,n){return ee(this,e,t,n)},makeEnum:c,makeEnumType:s,getEnumType:a,makeExtension(e,t,n){return de(this,e,t,n)}}}var Re=class{constructor(e,t){this._fields=e,this._normalizer=t}findJsonName(e){if(!this.jsonNames){let e={};for(let t of this.list())e[t.jsonName]=e[t.name]=t;this.jsonNames=e}return this.jsonNames[e]}find(e){if(!this.numbers){let e={};for(let t of this.list())e[t.no]=t;this.numbers=e}return this.numbers[e]}list(){return this.all||=this._normalizer(this._fields),this.all}byNumber(){return this.numbersAsc||=this.list().concat().sort((e,t)=>e.no-t.no),this.numbersAsc}byMember(){if(!this.members){this.members=[];let e=this.members,t;for(let n of this.list())n.oneof?n.oneof!==t&&(t=n.oneof,e.push(t)):e.push(n)}return this.members}};function ze(e,t){let n=He(e);return t?n:qe(Ke(n))}function Be(e){return ze(e,!1)}const Ve=He;function He(e){let t=!1,n=[];for(let r=0;r<e.length;r++){let i=e.charAt(r);switch(i){case`_`:t=!0;break;case`0`:case`1`:case`2`:case`3`:case`4`:case`5`:case`6`:case`7`:case`8`:case`9`:n.push(i),t=!1;break;default:t&&(t=!1,i=i.toUpperCase()),n.push(i)}}return n.join(``)}const Ue=/* @__PURE__ */ new Set([`constructor`,`toString`,`toJSON`,`valueOf`]),We=/* @__PURE__ */ new Set([`getType`,`clone`,`equals`,`fromBinary`,`fromJson`,`fromJsonString`,`toBinary`,`toJson`,`toJsonString`,`toObject`]),Ge=e=>`${e}$`,Ke=e=>We.has(e)?Ge(e):e,qe=e=>Ue.has(e)?Ge(e):e;var Je=class{constructor(e){this.kind=`oneof`,this.repeated=!1,this.packed=!1,this.opt=!1,this.req=!1,this.default=void 0,this.fields=[],this.name=e,this.localName=Be(e)}addField(t){e(t.oneof===this,`field ${t.name} not one of ${this.name}`),this.fields.push(t)}findField(e){if(!this._lookup){this._lookup=Object.create(null);for(let e=0;e<this.fields.length;e++)this._lookup[this.fields[e].localName]=this.fields[e]}return this._lookup[e]}};function Ye(e,t){let n=[],r;for(let i of typeof e==`function`?e():e){let e=i;if(e.localName=ze(i.name,i.oneof!==void 0),e.jsonName=i.jsonName??Ve(i.name),e.repeated=i.repeated??!1,i.kind==`scalar`&&(e.L=i.L??v.BIGINT),e.delimited=i.delimited??!1,e.req=i.req??!1,e.opt=i.opt??!1,i.packed===void 0&&(e.packed=t?i.kind==`enum`||i.kind==`scalar`&&i.T!=_.BYTES&&i.T!=_.STRING:!1),i.oneof!==void 0){let t=typeof i.oneof==`string`?i.oneof:i.oneof.name;(!r||r.name!=t)&&(r=new Je(t)),e.oneof=r,r.addField(e)}n.push(e)}return n}const Xe=Le(`proto3`,e=>new Re(e,e=>Ye(e,!0)),e=>{for(let t of e.getType().fields.byMember()){if(t.opt)continue;let n=t.localName,r=e;if(t.repeated){r[n]=[];continue}switch(t.kind){case`oneof`:r[n]={case:void 0};break;case`enum`:r[n]=0;break;case`map`:r[n]={};break;case`scalar`:r[n]=b(t.T,t.L)}}});var Ze;(function(e){e[e.Unary=0]=`Unary`,e[e.ServerStreaming=1]=`ServerStreaming`,e[e.ClientStreaming=2]=`ClientStreaming`,e[e.BiDiStreaming=3]=`BiDiStreaming`})(Ze||={});var Qe;(function(e){e[e.NoSideEffects=1]=`NoSideEffects`,e[e.Idempotent=2]=`Idempotent`})(Qe||={});var J;(function(e){e[e.Canceled=1]=`Canceled`,e[e.Unknown=2]=`Unknown`,e[e.InvalidArgument=3]=`InvalidArgument`,e[e.DeadlineExceeded=4]=`DeadlineExceeded`,e[e.NotFound=5]=`NotFound`,e[e.AlreadyExists=6]=`AlreadyExists`,e[e.PermissionDenied=7]=`PermissionDenied`,e[e.ResourceExhausted=8]=`ResourceExhausted`,e[e.FailedPrecondition=9]=`FailedPrecondition`,e[e.Aborted=10]=`Aborted`,e[e.OutOfRange=11]=`OutOfRange`,e[e.Unimplemented=12]=`Unimplemented`,e[e.Internal=13]=`Internal`,e[e.Unavailable=14]=`Unavailable`,e[e.DataLoss=15]=`DataLoss`,e[e.Unauthenticated=16]=`Unauthenticated`})(J||={});function Y(e){let t=J[e];return typeof t==`string`?t[0].toLowerCase()+t.substring(1).replace(/[A-Z]/g,e=>`_`+e.toLowerCase()):e.toString()}let X;function $e(e){if(!X){X={};for(let e of Object.values(J))typeof e!=`string`&&(X[Y(e)]=e)}return X[e]}var Z=class e extends Error{constructor(e,t=J.Unknown,n,r,i){super(et(e,t)),this.name=`ConnectError`,Object.setPrototypeOf(this,new.target.prototype),this.rawMessage=e,this.code=t,this.metadata=new Headers(n??{}),this.details=r??[],this.cause=i}static from(t,n=J.Unknown){return t instanceof e?t:t instanceof Error?t.name==`AbortError`?new e(t.message,J.Canceled):new e(t.message,n,void 0,void 0,t):new e(String(t),n,void 0,void 0,t)}static[Symbol.hasInstance](t){return t instanceof Error?Object.getPrototypeOf(t)===e.prototype||t.name===`ConnectError`&&`code`in t&&typeof t.code==`number`&&`metadata`in t&&`details`in t&&Array.isArray(t.details)&&`rawMessage`in t&&typeof t.rawMessage==`string`&&`cause`in t:!1}findDetails(e){let t=`typeName`in e?{findMessage:t=>t===e.typeName?e:void 0}:e,n=[];for(let e of this.details){if(`getType`in e){t.findMessage(e.getType().typeName)&&n.push(e);continue}let r=t.findMessage(e.type);if(r)try{n.push(r.fromBinary(e.value))}catch{}}return n}};function et(e,t){return e.length?`[${Y(t)}] ${e}`:`[${Y(t)}]`}function tt(e,t,n,r){let i=null,a=null,o;if(t!==null&&t!==`identity`){let n=e.find(e=>e.name===t);if(n)i=n;else{let n=e.map(e=>e.name).join(`,`);o=new Z(`unknown compression "${t}": supported encodings are ${n}`,J.Unimplemented,{[r]:n})}}if(n===null||n===``)a=i;else{let t=n.split(`,`).map(e=>e.trim());for(let n of t){let t=e.find(e=>e.name===n);if(t){a=t;break}}}return{request:i,response:a,error:o}}function nt(e){let t,n=/* @__PURE__ */ new Uint8Array;function r(e){let t=new Uint8Array(n.length+e.length);t.set(n),t.set(e,n.length),n=t}return new ReadableStream({start(){t=e.getReader()},async pull(e){let i;for(;;){if(i===void 0&&n.byteLength>=5){let e=0;for(let t=1;t<5;t++)e=(e<<8)+n[t];i={flags:n[0],length:e}}if(i!==void 0&&n.byteLength>=i.length+5)break;let e=await t.read();if(e.done)break;r(e.value)}if(i===void 0){if(n.byteLength==0){e.close();return}e.error(new Z(`premature end of stream`,J.DataLoss));return}let a=n.subarray(5,5+i.length);n=n.subarray(5+i.length),e.enqueue({flags:i.flags,data:a})}})}async function rt(e,t,n){let{flags:r,data:i}=e;if((r&1)==1)throw new Z(`invalid envelope, already compressed`,J.Internal);return t&&i.byteLength>=n&&(i=await t.compress(i),r|=1),{data:i,flags:r}}async function it(e,t,n){let{flags:r,data:i}=e;if((r&1)==1){if(!t)throw new Z(`received compressed envelope, but do not know how to decompress`,J.Internal);i=await t.decompress(i,n),r^=1}return{data:i,flags:r}}function at(e,t){let n=new Uint8Array(t.length+5);n.set(t,5);let r=new DataView(n.buffer,n.byteOffset,n.byteLength);return r.setUint8(0,e),r.setUint32(1,t.length),n}const Q=4294967295,$=Q;function ot(e,t,n){if(t??=$,e??=Q,n??=1024,t<1||t>$)throw new Z(`writeMaxBytes ${t} must be >= 1 and <= ${$}`,J.Internal);if(e<1||e>Q)throw new Z(`readMaxBytes ${e} must be >= 1 and <= ${Q}`,J.Internal);return{readMaxBytes:e,writeMaxBytes:t,compressMinBytes:n}}function st(e,t){if(t>e)throw new Z(`message size ${t} is larger than configured writeMaxBytes ${e}`,J.ResourceExhausted)}function ct(e,t,n=!1){if(t>e){let r=`message size is larger than configured readMaxBytes ${e}`;throw n&&(r=`message size ${t} is larger than configured readMaxBytes ${e}`),new Z(r,J.ResourceExhausted)}}export{g as _,at as a,tt as c,Y as d,J as f,T as g,Xe as h,nt as i,Z as l,Ze as m,st as n,rt as o,Qe as p,ot as r,it as s,ct as t,$e as u,u as v};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{a as e,c as t,d as n,i as r,l as i,n as a,o,s,t as c,u as l}from"./chunk-V2S4ZYJR-B9IPlZGx.mjs";var u=class extends a{async evalCodeAsync(e,t=`eval.js`,n){let r=+(n===void 0),i=l(n),a=0;try{a=await this.memory.newHeapCharPointer(e).consume(e=>this.ffi.QTS_Eval_MaybeAsync(this.ctx.value,e.value.ptr,e.value.strlen,t,r,i))}catch(e){throw this.runtime.debugLog(`QTS_Eval_MaybeAsync threw`,e),e}let o=this.ffi.QTS_ResolveException(this.ctx.value,a);return o?(this.ffi.QTS_FreeValuePointer(this.ctx.value,a),this.fail(this.memory.heapValueHandle(o))):this.success(this.memory.heapValueHandle(a))}newAsyncifiedFunction(e,t){return this.newFunction(e,t)}},d=class extends e{constructor(e){super(e)}newContext(e={}){let t=n(e.intrinsics),r=new c(this.ffi.QTS_NewContext(this.rt.value,t),void 0,e=>{this.contextMap.delete(e),this.callbacks.deleteContext(e),this.ffi.QTS_FreeContext(e)}),i=new u({module:this.module,ctx:r,ffi:this.ffi,rt:this.rt,ownedLifetimes:[],runtime:this,callbacks:this.callbacks});return this.contextMap.set(r.value,i),i}setModuleLoader(e,t){super.setModuleLoader(e,t)}setMaxStackSize(e){return super.setMaxStackSize(e)}},f=class extends o{constructor(e,t){super(e,t),this.ffi=t,this.module=e}newRuntime(e={}){let n=new c(this.ffi.QTS_NewRuntime(),void 0,e=>{this.callbacks.deleteRuntime(e),this.ffi.QTS_FreeRuntime(e)}),r=new d({module:this.module,ffi:this.ffi,rt:n,callbacks:this.callbacks});return t(r,e),e.moduleLoader&&r.setModuleLoader(e.moduleLoader),r}newContext(e={}){let t=this.newRuntime(),n=e.ownedLifetimes?e.ownedLifetimes.concat([t]):[t],r=t.newContext({...e,ownedLifetimes:n});return t.context=r,r}evalCode(){throw new r(`QuickJSWASMModuleAsyncify.evalCode: use evalCodeAsync instead`)}evalCodeAsync(e,t){return s.withScopeAsync(async n=>{let r=n.manage(this.newContext());i(r.runtime,t);let a=await r.evalCodeAsync(e,`eval.js`);if(t.memoryLimitBytes!==void 0&&r.runtime.setMemoryLimit(-1),a.error)throw r.dump(n.manage(a.error));return r.dump(n.manage(a.value))})}};export{f as QuickJSAsyncWASMModule};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pen-dev
|
|
3
|
-
description: Create high-quality visual designs — websites, app screens, dashboards, slides, marketing materials, social media graphics on the pen.dev canvas. Use when the task involves generating designs on the canvas.
|
|
3
|
+
description: Create high-quality visual designs — websites, app screens, dashboards, slides, marketing materials, social media graphics on the pen.dev canvas — or use the canvas as a whiteboard to research, plan, and compare with live browser nodes. Use when the task involves generating designs or working out a task on the canvas.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# pen.dev
|
|
@@ -16,6 +16,7 @@ pen.dev is an infinite canvas design tool with nested object hierarchy.
|
|
|
16
16
|
| `generate` | Using the `Generate` function: AI and stock images, SVG artwork, and transforming an image already in the document. | [generate.md](./generate.md) |
|
|
17
17
|
| `components` | Learn how to use components and instances in .pen files. | [components.md](./guide/components.md) |
|
|
18
18
|
| `scripts-and-shaders` | Learn how to use scripts and shaders on the pen.dev canvas. | [scripts-and-shaders.md](./scripts-and-shaders.md) |
|
|
19
|
+
| `whiteboard` | Research, evaluation, and planning work done on the canvas with live `browser` nodes: competitor and vendor comparisons, meeting prep, briefs, schedules. The deliverable is information for the user, not a product design. Required when the user asks you to research, compare, evaluate, plan, or prep something. | [whiteboard.md](./whiteboard.md) |
|
|
19
20
|
| `code` | Generating code from .pen files. | [code.md](./guide/code.md) |
|
|
20
21
|
| `design-system` | Composing screens with design system components. | [design-system.md](./guide/design-system.md) |
|
|
21
22
|
| `landing-page` | Designing landing pages and promotional websites. | [landing-page.md](./guide/landing-page.md) |
|
|
@@ -30,6 +31,7 @@ pen.dev is an infinite canvas design tool with nested object hierarchy.
|
|
|
30
31
|
- Favor copying existing content and updating the copied content later, rather than generating new content.
|
|
31
32
|
- When creating new variables make sure you are not accidentally overwriting any existing design.
|
|
32
33
|
- User may ask for technical modifications like removing, moving, re-ordering, clearing, and copying objects/variables, or just ask questions. Only do what's requested and nothing more.
|
|
34
|
+
- When the user asks you to research, compare, evaluate, plan, or prep something (competitors, vendors, a meeting, a schedule, a trip), the deliverable is information laid out for them, not an app or website about the topic. Read [whiteboard.md](./whiteboard.md) and work with live `browser` nodes instead of designing a product.
|
|
33
35
|
- pen.dev is a collaborative multiplayer environment: the document can change while you work, so the state you remember may be stale. If a node is missing or no longer matches what you expected, re-read instead of recreating it, and don't undo changes the user made in the meantime.
|
|
34
36
|
- When adding more content to a frame make sure the frame has the right layout, or is big enough to fit the new content. Resize the frame if necessary. There is no scrolling and the entire content should always be visible on the canvas.
|
|
35
37
|
- Place components at the top and your screens below, growing to the right and down.
|
|
@@ -38,6 +40,7 @@ pen.dev is an infinite canvas design tool with nested object hierarchy.
|
|
|
38
40
|
- When the design has repeated UI, consider building those as reusable components first and then instancing them, so edits to the component propagate to every instance.
|
|
39
41
|
- Changes in the document are presented in real-time to the user. Make the changes in a logical order as a designer would.
|
|
40
42
|
- Minimize the time between the user requests and showing something on the screen. Users don't want to wait a long time before they see the progress.
|
|
43
|
+
- Answers support Markdown links to websites and local output files. Use absolute paths for local files and angle brackets for paths with spaces, for example `[Preview](http://localhost:3000)` or `[Notes](</Users/name/project/image prompts.txt>)`.
|
|
41
44
|
- Use the canvas as part of your thinking. You don't need to preplan every little detail. Iteratively design using the document.
|
|
42
45
|
|
|
43
46
|
- Do NOT use or think in CSS/HTML properties or behavior. pen.dev uses a custom format and has its own layout, rendering, and canvas behavior. pen.dev has similar concepts and naming, but it's not the same as CSS/HTML.
|
|
@@ -234,6 +234,7 @@ Export([pageId], "html-tailwind", "./landing.html")
|
|
|
234
234
|
### Generate
|
|
235
235
|
|
|
236
236
|
- Brings imagery and vector artwork into the document: `"ai"` and `"stock"` for a new image, `"svg"` for new vector artwork, and `"remove-background"`, `"replace-background"`, and `"vectorize-image"` for an image the document ALREADY has.
|
|
237
|
+
- `Generate` needs the user to be signed in to pen.dev; `get_app_state` shows it under `Account`. When they aren't signed in, every `Generate` call fails, so don't call it. Instead, create images with your own tools if you can, save them next to the .pen file and apply them as image fills with a relative url (`./images/hero.png`), and draw vector artwork as `path` nodes. Otherwise use placeholders and tell the user that signing in to pen.dev enables `Generate`.
|
|
237
238
|
- IMPORTANT: There is NO `image` node type. Images are applied as FILLS to existing nodes; SVGs become paths inside a parent frame.
|
|
238
239
|
- Every type is async: the result lands after the `execute` call that started it has returned, so a screenshot taken right away will not show it. Never re-generate it, draw the result by hand, or add children to a frame you generated into.
|
|
239
240
|
- Read [generate.md](./generate.md) before calling it.
|
|
@@ -32,6 +32,10 @@ export type SizingBehavior = string;
|
|
|
32
32
|
/** Position relative to parent. X right, Y down. IGNORED when parent uses flex layout. */
|
|
33
33
|
export interface Position { x?: number; y?: number; }
|
|
34
34
|
export interface Size { width?: NumberOrVariable | SizingBehavior; height?: NumberOrVariable | SizingBehavior; }
|
|
35
|
+
/** Affine matrix [a, b, c, d, tx, ty]. */
|
|
36
|
+
export type AffineTransform = [number, number, number, number, number, number];
|
|
37
|
+
/** Override values for shader uniforms, keyed by uniform name. Uniforms annotated with `@resolution` or `@time` must not appear here. Allowed value shapes: number (float/int), boolean (bool), hex color string like `#RRGGBB[AA]` (color), array of 2-4 numbers (vec2/3/4), or a variable reference `$name` (numeric uniforms accept number variables; color uniforms accept color variables). */
|
|
38
|
+
export interface ShaderUniforms { [key: string]: number | boolean | string | number[]; }
|
|
35
39
|
export type BlendMode = 'normal' | 'darken' | 'multiply' | 'linearBurn' | 'colorBurn' | 'light' | 'screen' | 'linearDodge' | 'colorDodge' | 'overlay' | 'softLight' | 'hardLight' | 'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity';
|
|
36
40
|
export type Fill = ColorOrVariable | {
|
|
37
41
|
type: "color";
|
|
@@ -52,15 +56,17 @@ size?: { width?: NumberOrVariable; height?: NumberOrVariable };
|
|
|
52
56
|
/** Degrees CCW (0° up, 90° left, 180° down). */
|
|
53
57
|
rotation?: NumberOrVariable;
|
|
54
58
|
colors?: { color: ColorOrVariable; position: NumberOrVariable }[];
|
|
55
|
-
} | /** Image fill. URL is relative to the .pen file, e.g. `./image.jpg`. */ {
|
|
56
|
-
type: "
|
|
59
|
+
} | /** Image fill. URL is relative to the .pen file, e.g. `./image.jpg`. */ {
|
|
60
|
+
type: "image";
|
|
57
61
|
enabled?: BooleanOrVariable;
|
|
58
62
|
blendMode?: BlendMode;
|
|
59
63
|
opacity?: NumberOrVariable;
|
|
60
|
-
url
|
|
61
|
-
/**
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
url?: string;
|
|
65
|
+
/** Default 'cover'. */
|
|
66
|
+
mode?: "cover" | "contain" | "stretch";
|
|
67
|
+
/** Crops the image. Maps normalized image coordinates (0..1 across its width and height) into the crop's 0..1 box, so [2, 0, 0, 1, -1, 0] is the right half. The mode fits the crop into the shape like a whole image, and cover keeps it inside the image. Defaults to identity, no crop. */
|
|
68
|
+
transform?: AffineTransform;
|
|
69
|
+
} | /** Shader fill. URL points to a WebGL 1.0 (#version 100) fragment shader file, relative to the .pen file, e.g. `./effect.glsl`. Uniforms are described via `@directive` annotations inside block comments in the shader source. A `vec2` uniform annotated with `@resolution` is auto-bound to the fill size in pixels. Other uniforms' user-set values are stored in `uniforms`. */ { type: "shader"; enabled?: BooleanOrVariable; blendMode?: BlendMode; opacity?: NumberOrVariable; url: string; uniforms?: ShaderUniforms } | /** Bezier-interpolated color grid, row-major. Keep edge points at default positions. */ {
|
|
64
70
|
type: "mesh_gradient";
|
|
65
71
|
enabled?: BooleanOrVariable;
|
|
66
72
|
blendMode?: BlendMode;
|
|
@@ -81,7 +87,7 @@ export interface CanHaveStroke {
|
|
|
81
87
|
strokeLinejoin?: "miter" | "bevel" | "round";
|
|
82
88
|
strokeAlignment?: "inner" | "center" | "outer";
|
|
83
89
|
}
|
|
84
|
-
export type Effect = /** Blurs the entire node. */ { enabled?: BooleanOrVariable; type: "blur"; radius?: NumberOrVariable } | /** Blurs the backdrop behind the node. */ { enabled?: BooleanOrVariable; type: "background_blur"; radius?: NumberOrVariable } | /** Inner or outer drop shadow. */ { type: "shadow"; enabled?: BooleanOrVariable; shadowType?: "inner" | "outer"; offset?: { x: NumberOrVariable; y: NumberOrVariable }; blur?: NumberOrVariable; color?: ColorOrVariable; blendMode?: BlendMode };
|
|
90
|
+
export type Effect = /** Blurs the entire node. */ { enabled?: BooleanOrVariable; type: "blur"; radius?: NumberOrVariable } | /** Blurs the backdrop behind the node. */ { enabled?: BooleanOrVariable; type: "background_blur"; radius?: NumberOrVariable } | /** Inner or outer drop shadow. */ { type: "shadow"; enabled?: BooleanOrVariable; shadowType?: "inner" | "outer"; offset?: { x: NumberOrVariable; y: NumberOrVariable }; blur?: NumberOrVariable; color?: ColorOrVariable; blendMode?: BlendMode } | /** Post-processes the rendered node with a fragment shader. Same shader format as the shader fill. A `sampler2D` uniform annotated with `@content` is auto-bound to the rendered node. `@resolution` is the size of the node's visual bounds. */ { type: "shader"; enabled?: BooleanOrVariable; url: string; uniforms?: ShaderUniforms };
|
|
85
91
|
export type Effects = Effect | Effect[];
|
|
86
92
|
export interface CanHaveEffects { effect?: Effects; }
|
|
87
93
|
export interface CanHaveGraphics extends CanHaveEffects, CanHaveStroke { fill?: Fills; }
|
|
@@ -211,5 +217,5 @@ export interface Ref extends Entity {
|
|
|
211
217
|
}
|
|
212
218
|
export type Child = Frame | Group | Rectangle | Ellipse | Path | Polygon | Text | Note | Prompt | Context | Icon | Script | Browser | Ref;
|
|
213
219
|
export type IdPath = string;
|
|
214
|
-
export interface Document { version: "2.
|
|
220
|
+
export interface Document { version: "2.21"; themes?: { [key: string /** RegEx: [^:]+ */]: string[] }; imports?: { [key: string]: string /** Value: relative URI of imported .pen file. Key: short alias. */ }; variables?: { [key: string /** RegEx: [^:]+ */]: { type: "boolean"; value: BooleanOrVariable | { value: BooleanOrVariable; theme?: Theme }[] } | { type: "color"; value: ColorOrVariable | { value: ColorOrVariable; theme?: Theme }[] } | { type: "number"; value: NumberOrVariable | { value: NumberOrVariable; theme?: Theme }[] } | { type: "string"; value: StringOrVariable | { value: StringOrVariable; theme?: Theme }[] } }; children: (Frame | Group | Rectangle | Ellipse | Polygon | Path | Text | Note | Context | Prompt | Icon | Script | Browser | Ref)[]; }
|
|
215
221
|
```
|
|
@@ -42,7 +42,7 @@ return nodes;
|
|
|
42
42
|
|
|
43
43
|
## Shaders
|
|
44
44
|
|
|
45
|
-
The `shader` fill type can be used to create complex graphics effects using WebGL shaders.
|
|
45
|
+
The `shader` fill type can be used to create complex graphics effects using WebGL shaders. The `shader` effect type runs the same kind of shader over the rendered node instead (see Shader effects below).
|
|
46
46
|
|
|
47
47
|
- Shaders are WebGL 1.0 fragment shaders (#version 100), with one addition: textureSize(sampler, lod) is available for aspect-correct texturing.
|
|
48
48
|
- Supported uniform types:
|
|
@@ -55,8 +55,10 @@ The `shader` fill type can be used to create complex graphics effects using WebG
|
|
|
55
55
|
- @resolution: set to the resolution of the output. e.g. can be used to normalize gl_FragCoord.
|
|
56
56
|
- @mouse: set to the mouse position in the same space as gl_FragCoord. For interactive effects.
|
|
57
57
|
- @time: set to the elapsed time in seconds. For animations.
|
|
58
|
-
- @sdf: a sampler2D set to an SDF texture of the node's shape. The r channel holds the signed distance in @resolution units (positive = inside). The gb channels hold the gradient of the distance field (direction of increasing distance), in texel space. Use gb instead of numerically differentiating the r channel!
|
|
59
|
-
- @
|
|
58
|
+
- @sdf: a sampler2D set to an SDF texture of the node's shape (in a shader effect: of the rendered content). The r channel holds the signed distance in @resolution units (positive = inside). The gb channels hold the gradient of the distance field (direction of increasing distance), in texel space. Use gb instead of numerically differentiating the r channel!
|
|
59
|
+
- @content: a sampler2D set to the node's own rendering below the shader, over transparent: in a fill the fills under it (plus the node's effects drawn before fills, like shadows), in a stroke additionally all fills, in an effect every fill, stroke and earlier effect. Texels are premultiplied by alpha, like gl_FragColor; outside the node it is transparent.
|
|
60
|
+
- @backdrop: a sampler2D set to the content rendered behind the node, with nothing of the node itself. Outside the node it mirrors. Offset/distort the sampling coordinate for refraction-like effects. Ideal for glass/frosted/refraction/magnifier effects. Prefer @backdrop over faking the background.
|
|
61
|
+
- @mipmap: the texture will be mipmapped. Off by default. Turn it on when the sample coordinate varies smoothly (glass, refraction, blur); keep it off when it jumps between neighboring pixels (pixelation, mosaics, high-frequency turbulence).
|
|
60
62
|
- @min/@max: set the range of a uniform for better UI controls. Only applies to number uniforms.
|
|
61
63
|
- @range <min>, <max>: shorthand for @min and @max on the same line. Shows a slider in the UI.
|
|
62
64
|
- @label <text>: sets the uniform's display name in the UI. Always set the label.
|
|
@@ -92,3 +94,33 @@ void main() {
|
|
|
92
94
|
gl_FragColor = vec4(color, 1.0);
|
|
93
95
|
}
|
|
94
96
|
```
|
|
97
|
+
|
|
98
|
+
### Shader effects
|
|
99
|
+
|
|
100
|
+
A `shader` effect (`effect: { type: "shader", url, uniforms }`) post-processes the node: the node, its children and its other effects are rendered into the `@content` texture, and the shader's output is drawn in place of the node. Use it for distortion, pixelation, color grading, glitch and similar effects on existing content. Use a shader fill when the shader generates the image itself. `@content` and `@backdrop` mean the same in fills and effects, so a shader written for one works as the other; a `@backdrop` shader (glass, ripple, ...) refracts what is behind the node either way.
|
|
101
|
+
|
|
102
|
+
- `@resolution` and `gl_FragCoord` are the same as for a fill: the node's size and the node's own coordinates. The shader is run over the node's visual bounds (strokes, shadows, blur, unclipped children included), so there `gl_FragCoord` goes outside `0..@resolution`, and `@content`, `@sdf` and `@backdrop` cover those bounds too: uv outside `0..1` samples them.
|
|
103
|
+
- Multiple shader effects are chained in list order: each one's `@content` is the output of the previous one.
|
|
104
|
+
- `@sdf` is the SDF of the content's alpha channel (edge at 50% alpha), so shadows, blurs and earlier shader effects on the node move the edge.
|
|
105
|
+
- `@content` is rendered over transparent, so blend modes inside the node only blend with the node's own content below them. A blend mode that reaches the bottom of the node (nothing opaque under it) blends with the scene when drawn normally, but not inside `@content`.
|
|
106
|
+
- Combine `@content` and `@backdrop`: distort the shape with `@content` and refract `@backdrop` through the result for a glass effect on a distorted node.
|
|
107
|
+
|
|
108
|
+
```glsl
|
|
109
|
+
/** @resolution */
|
|
110
|
+
uniform vec2 u_resolution;
|
|
111
|
+
|
|
112
|
+
/** @content */
|
|
113
|
+
uniform sampler2D u_content;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @label Pixel Size
|
|
117
|
+
* @default 8
|
|
118
|
+
* @range 1, 64
|
|
119
|
+
*/
|
|
120
|
+
uniform float u_pixelSize;
|
|
121
|
+
|
|
122
|
+
void main() {
|
|
123
|
+
vec2 cell = (floor(gl_FragCoord.xy / u_pixelSize) + 0.5) * u_pixelSize;
|
|
124
|
+
gl_FragColor = texture2D(u_content, cell / u_resolution);
|
|
125
|
+
}
|
|
126
|
+
```
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Whiteboarding: research and planning on the canvas
|
|
2
|
+
|
|
3
|
+
Read this when the deliverable is information for the user, not a product. `browser` nodes put real web pages on the canvas, the `browser` tool drives them, and `execute` lays out what you learn next to them. The canvas works like a team whiteboard: the user watches the work happen and keeps the result.
|
|
4
|
+
|
|
5
|
+
## When this applies
|
|
6
|
+
|
|
7
|
+
Whiteboard when the user wants a task done and shown, not a UI designed:
|
|
8
|
+
|
|
9
|
+
- "Research our three main competitors' pricing and put it side by side."
|
|
10
|
+
- "Evaluate these vendors for our CRM migration and recommend one."
|
|
11
|
+
- "Prep me for tomorrow's meeting with Acme: what they do, recent news, who we're meeting."
|
|
12
|
+
- "Find a venue for the 40-person offsite in Berlin in May and draft the agenda."
|
|
13
|
+
- "Summarize what these five articles say about the EU AI Act."
|
|
14
|
+
- "Plan a 4-day trip to Lisbon in October on a 1500 EUR budget."
|
|
15
|
+
|
|
16
|
+
Signals: research, compare, evaluate, plan, prep, find, decide, summarize, shortlist, schedule, budget. No mention of screens, apps, websites, or landing pages.
|
|
17
|
+
|
|
18
|
+
Do NOT design an app, dashboard, or website about the topic. A request to evaluate vendors is not a request for a procurement tool. If it is genuinely unclear, ask one question rather than guess the expensive option.
|
|
19
|
+
|
|
20
|
+
## Building blocks
|
|
21
|
+
|
|
22
|
+
- `browser` node: a live page on the canvas. `Insert(parent, {type: "browser", name, url, width, height})`. The user can scroll, click, and sign in inside it.
|
|
23
|
+
- `browser` tool: pass the node's id as `nodeId`. `load-page` navigates; `return-screenshot` and `return-element` (with a focused `querySelector`) read the page back; `cdp` acts inside it; `screenshot-to-canvas` copies a region into the document.
|
|
24
|
+
- Canvas artifacts: frames, text, tables, `icon` nodes, and `note` nodes (a sticky note with `content`, `width`, `height`).
|
|
25
|
+
- `get_app_state` shows existing browser nodes and the user's selection. If the user already opened a page or picked an element, use it (`target: "selection"`) instead of opening another.
|
|
26
|
+
|
|
27
|
+
The `browser` tool is desktop-only. Elsewhere, browse with whatever tools you have and still build the board as described here.
|
|
28
|
+
|
|
29
|
+
## The loop
|
|
30
|
+
|
|
31
|
+
1. **Brief on the board first.** One `execute`: a root `Board` frame with the title, goal, constraints, and open questions. Keep `placeholder: true` while filling.
|
|
32
|
+
2. **Open sources.** One browser node per source in a `Sources` row, named after the source. Put the query in the URL where the site supports it. Two or three sources at a time.
|
|
33
|
+
3. **Orient, then extract.** `return-screenshot` first. Then `cdp` `Runtime.evaluate` with `returnByValue: true` to pull a structured array (`{name, price, plan, url}`) in one call, or `return-element` on a specific section. Use `Input.dispatchMouseEvent`, `Input.insertText`, and `Input.dispatchKeyEvent` for searches, filters, cookie banners, and pagination; locate targets with `DOM.querySelector` and `DOM.getBoxModel`. A click that navigates returns once the page has loaded.
|
|
34
|
+
4. **Write findings as you go.** After each source, add its results next to it. Partial results are useful; the user is watching.
|
|
35
|
+
5. **Synthesize.** A separate frame with the deliverable: comparison matrix, recommendation, brief, agenda, itinerary. This is what the user reads first.
|
|
36
|
+
6. **Hand back the user's decisions** (budget trade-offs, final pick, dates) as an `Open questions` note. Do not decide for them.
|
|
37
|
+
7. **Verify** with `Get` and `ctx.problems`, one `TakeScreenshot` of the synthesis, then clear `placeholder`.
|
|
38
|
+
|
|
39
|
+
## Rules for the board
|
|
40
|
+
|
|
41
|
+
- Only write what you read on a page. Never invent prices, plans, dates, names, or figures. If a source gave nothing, say so on the board.
|
|
42
|
+
- Every fact carries its source: site name with `href` to the page, plus the date checked for anything that changes (prices, availability, headcount).
|
|
43
|
+
- Separate facts from judgment. Mark estimates and opinions ("est.", "recommended").
|
|
44
|
+
- Keep the browser nodes when done, scrolled to the relevant part. They are the evidence.
|
|
45
|
+
- Readable at canvas zoom: body 14-16px, headings 20-28px, cards 320-480px wide, wrapped text with `textGrowth: "fixed-width"`. Rows and short phrases, not paragraphs.
|
|
46
|
+
- Tables for anything comparable (vendors, plans, options), cards for entities with several attributes (a company, a venue), a column per day or phase for schedules, `note` nodes for caveats and questions.
|
|
47
|
+
- Plain style: light background, one accent color, one font. No style archetypes, hero sections, nav bars, or buttons. No `clip: true`, no fixed screen width; the board grows as `fit_content`.
|
|
48
|
+
- Copy real visuals (a pricing table, a map, a chart from a report) with `screenshot-to-canvas` on a `query` target instead of redrawing them.
|
|
49
|
+
|
|
50
|
+
## Safety and consent
|
|
51
|
+
|
|
52
|
+
- Never log in, enter personal or payment details, purchase, book, sign up, or submit forms on the user's behalf. Stop where the only remaining step is theirs and say so.
|
|
53
|
+
- Browser nodes share one browser session. If a site needs an account, ask the user to sign in inside the node, then continue.
|
|
54
|
+
- Re-read a node before acting in it; the user may have moved on. Do not navigate away from a page they are looking at without saying so.
|
|
55
|
+
- Do not send Escape through `cdp`; the editor intercepts it.
|
|
56
|
+
|
|
57
|
+
## Layout
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
Board (frame, vertical, gap 40, padding 48)
|
|
61
|
+
├── Brief: title, goal, constraints, open questions
|
|
62
|
+
├── Sources (horizontal, gap 32): browser nodes, 640-900 wide, 600-800 tall
|
|
63
|
+
├── Findings (horizontal, gap 32): one column per source or topic
|
|
64
|
+
└── Synthesis (horizontal, gap 24): matrix, recommendation, plan, budget, decisions
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Place boards with `FindEmptySpace` at the document root.
|
|
68
|
+
|
|
69
|
+
## Example: "Compare Linear, Jira, and Shortcut for a 30-person team"
|
|
70
|
+
|
|
71
|
+
Brief and first sources:
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
const pos = FindEmptySpace({width: 2400, height: 1600, padding: 120})
|
|
75
|
+
boardId = Insert(document, {type: "frame", name: "Issue tracker evaluation", x: pos.x, y: pos.y, layout: "vertical", gap: 40, padding: 48, fill: "#FAFAF7", placeholder: true})
|
|
76
|
+
briefId = Insert(boardId, {type: "frame", name: "Brief", layout: "vertical", gap: 8, width: 720})
|
|
77
|
+
Insert(briefId, {type: "text", name: "Title", content: "Issue tracker for a 30-person team", fontFamily: "Inter", fontSize: 28, fontWeight: "bold", fill: "#111111"})
|
|
78
|
+
Insert(briefId, {type: "text", name: "Constraints", textGrowth: "fixed-width", width: "fill_container", content: "30 seats · GitHub integration required · SSO preferred · budget under 400 EUR/month", fontFamily: "Inter", fontSize: 15, fill: "#444444"})
|
|
79
|
+
sourcesId = Insert(boardId, {type: "frame", name: "Sources", gap: 32})
|
|
80
|
+
linearId = Insert(sourcesId, {type: "browser", name: "Linear pricing", url: "https://linear.app/pricing", width: 800, height: 700})
|
|
81
|
+
jiraId = Insert(sourcesId, {type: "browser", name: "Jira pricing", url: "https://www.atlassian.com/software/jira/pricing", width: 800, height: 700})
|
|
82
|
+
findingsId = Insert(boardId, {type: "frame", name: "Findings", gap: 32})
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Extract the plans as data:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{"action": "cdp", "nodeId": "<linearId>", "method": "Runtime.evaluate", "params": {"returnByValue": true, "expression": "[...document.querySelectorAll('h3')].map(h => ({name: h.innerText.trim(), price: h.parentElement?.innerText.match(/\\$\\d+[^\\n]*/)?.[0] ?? '', sso: /SSO|SAML/i.test(h.parentElement?.innerText ?? '')}))"}}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Write the findings in the next `execute`, transcribing the values you just read into a literal array, then cite the source:
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
const plans = [
|
|
95
|
+
{name: "Free", seat: "$0", total: "$0", sso: "No"},
|
|
96
|
+
{name: "Basic", seat: "$8", total: "$240", sso: "No"},
|
|
97
|
+
{name: "Business", seat: "$14", total: "$420", sso: "Yes"},
|
|
98
|
+
]
|
|
99
|
+
const row = (parent, cells, bold) => {
|
|
100
|
+
const r = Insert(parent, {type: "frame", name: "Row", gap: 16, width: "fill_container", padding: [8, 0]})
|
|
101
|
+
for (const [i, c] of cells.entries()) Insert(r, {type: "text", name: c, content: c, textGrowth: "fixed-width", width: i === 0 ? 160 : 140, fontFamily: "Inter", fontSize: 14, fontWeight: bold ? "bold" : "normal", fill: "#111111"})
|
|
102
|
+
}
|
|
103
|
+
linearColId = Insert(findingsId, {type: "frame", name: "Linear", layout: "vertical", gap: 4, width: 620, placeholder: true})
|
|
104
|
+
Insert(linearColId, {type: "text", name: "Heading", content: "Linear", fontFamily: "Inter", fontSize: 20, fontWeight: "bold", fill: "#111111"})
|
|
105
|
+
row(linearColId, ["Plan", "Per seat", "30 seats", "SSO"], true)
|
|
106
|
+
for (const p of plans) row(linearColId, [p.name, p.seat, p.total, p.sso])
|
|
107
|
+
Insert(linearColId, {type: "text", name: "Source", content: "linear.app/pricing, checked 28 Sep 2026", href: "https://linear.app/pricing", fontFamily: "Inter", fontSize: 12, fill: "#777777"})
|
|
108
|
+
Update(linearColId, {placeholder: false})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Finish with the synthesis: a comparison matrix across all three, a recommendation card with the reasoning, a monthly cost line, and an `Open questions` note. Screenshot the synthesis and clear the board's `placeholder`.
|
|
112
|
+
|
|
113
|
+
## Antipatterns
|
|
114
|
+
|
|
115
|
+
- Designing a product about the topic.
|
|
116
|
+
- Filling cards with plausible data you did not read on a page.
|
|
117
|
+
- Dumping raw DOM or whole result lists. Extract, select, then write the rows that matter.
|
|
118
|
+
- Holding everything for one final `execute`. The board should grow as you work.
|
|
119
|
+
- Deleting the browser nodes once you have the numbers.
|
|
120
|
+
- Purchasing, booking, signing up, or submitting anything.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{createRequire as e}from"node:module";var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),c=(e,t)=>{let r={};for(var i in e)n(r,i,{get:e[i],enumerable:!0});return t||n(r,Symbol.toStringTag,{value:`Module`}),r},l=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;l<u;l++)d=c[l],!o.call(e,d)&&d!==a&&n(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},u=(e,r,i)=>(i=e==null?{}:t(a(e)),l(r||!e||!e.__esModule||!o.call(e,`default`)?n(i,`default`,{value:e,enumerable:!0}):i,e)),d=/* @__PURE__ */ e(import.meta.url);export{u as i,c as n,d as r,s as t};
|