opencharm 0.8.8 → 0.9.0
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/dist/main.mjs +3 -3
- package/package.json +1 -1
- package/sim/charm_sim.js +1 -1
- package/sim/charm_sim.wasm +0 -0
- package/sim/index.html +9 -3
- package/sim/sim.css +10 -0
- package/sim/sim.js +48 -0
package/dist/main.mjs
CHANGED
|
@@ -997,7 +997,7 @@ function sendAdmin(socketPath, request) {
|
|
|
997
997
|
}
|
|
998
998
|
//#endregion
|
|
999
999
|
//#region package.json
|
|
1000
|
-
var version = "0.
|
|
1000
|
+
var version = "0.9.0";
|
|
1001
1001
|
function channelToCube(value) {
|
|
1002
1002
|
if (value < 48) return 0;
|
|
1003
1003
|
if (value < 115) return 1;
|
|
@@ -3945,7 +3945,7 @@ function createAcpAgent(options) {
|
|
|
3945
3945
|
await agent.context.request(acp.methods.agent.session.setMode, {
|
|
3946
3946
|
sessionId: created.sessionId,
|
|
3947
3947
|
modeId: mode
|
|
3948
|
-
});
|
|
3948
|
+
}).catch((error) => log(`mode "${mode}" refused, staying in "${created.modes?.currentModeId}": ${friendly(error, program).message}`));
|
|
3949
3949
|
}
|
|
3950
3950
|
return {
|
|
3951
3951
|
agent,
|
|
@@ -5056,7 +5056,7 @@ function formatIdentity(unit, version, commit) {
|
|
|
5056
5056
|
let cached;
|
|
5057
5057
|
function identity() {
|
|
5058
5058
|
if (cached) return cached;
|
|
5059
|
-
const commit = "
|
|
5059
|
+
const commit = "2cd5780";
|
|
5060
5060
|
cached = {
|
|
5061
5061
|
version: `cli@${version}`,
|
|
5062
5062
|
commit,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencharm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "An open-source body for the AI agent you already run: a face, a voice, one key. Claude Code, Codex, Gemini CLI, Hermes, OpenClaw or any ACP or OpenAI-compatible agent; on a small board, your Mac's notch or the browser.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/sim/charm_sim.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
async function createCharm(moduleArg={}){var Module=moduleArg;var ENVIRONMENT_IS_WEB=true;var ENVIRONMENT_IS_WORKER=false;var programArgs=[];var thisProgram="./this.program";var _scriptName=import.meta.url;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{readAsync=async url=>{var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;class EmscriptenEH{}class EmscriptenSjLj extends EmscriptenEH{}var runtimeInitialized=false;function getMemoryBuffer(){return wasmMemory.buffer}function updateMemoryViews(){if(HEAP8?.buffer?.resizable)return;var b=getMemoryBuffer();HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b)}function preRun(){var preRun=Module["preRun"];if(preRun){if(typeof preRun=="function")preRun=[preRun];onPreRuns.push(...preRun)}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["r"]()}function postRun(){var postRun=Module["postRun"];if(postRun){if(typeof postRun=="function")postRun=[postRun];onPostRuns.push(...postRun)}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what=`Aborted(${what})`;err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var wasmBinaryFile;function findWasmBinary(){if(Module["locateFile"]){return locateFile("charm_sim.wasm")}return new URL("charm_sim.wasm",import.meta.url).href}function getBinarySync(file){if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();var instantiateWasm=Module["instantiateWasm"];if(instantiateWasm){return new Promise(resolve=>{instantiateWasm(info,inst=>resolve(receiveInstance(inst)))})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var HEAP8;var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var onPreRuns=[];var noExitRuntime=true;var HEAPU32;class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var uncaughtExceptionCount=0;var __Unwind_RaiseException=ex=>{abort()};var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);uncaughtExceptionCount++;__Unwind_RaiseException(ptr)};var __abort_js=()=>abort("");var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var HEAPU8;var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var _fd_close=fd=>52;var printCharBuffers=[null,[],[]];var UTF8Decoder=globalThis.TextDecoder&&new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx<endPtr){var u0=heapOrArray[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heapOrArray[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heapOrArray[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|heapOrArray[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}return str};var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(!curr||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer));buffer.length=0}else{buffer.push(curr)}};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j<len;j++){printChar(fd,HEAPU8[ptr+j])}num+=len}HEAPU32[pnum>>2]=num;return 0};var HEAPF32;var HEAP16;var HEAP32;var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.codePointAt(i);if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i<str.length;++i){var c=str.charCodeAt(i);if(c<=127){len++}else if(c<=2047){len+=2}else if(c>=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["arguments"])programArgs=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];var preInit=Module["preInit"];if(preInit){if(typeof preInit=="function")Module["preInit"]=preInit=[preInit];while(preInit.length>0){preInit.shift()()}}}Module["UTF8ToString"]=UTF8ToString;Module["stringToUTF8"]=stringToUTF8;Module["lengthBytesUTF8"]=lengthBytesUTF8;function js_panel(open,height){charmSim.panel(!!open,height)}function js_send_text(json){charmSim.sendText(UTF8ToString(json))}function js_send_binary(data,size){charmSim.sendBinary(HEAPU8.slice(data,data+size))}function js_mic(on){charmSim.mic(!!on)}function js_play_pcm(pcm,samples){charmSim.playPcm(HEAPF32.slice(pcm>>2,(pcm>>2)+samples))}function js_stop_audio(){charmSim.stopAudio()}function js_brightness(percent){charmSim.brightness(percent)}function js_store_get(key){var value=localStorage.getItem((globalThis.charmStore||"opencharm.")+UTF8ToString(key));if(value===null)return 0;var size=lengthBytesUTF8(value)+1;var ptr=_malloc(size);stringToUTF8(value,ptr,size);return ptr}function js_store_set(key,value){localStorage.setItem((globalThis.charmStore||"opencharm.")+UTF8ToString(key),UTF8ToString(value))}function js_store_erase(key){localStorage.removeItem((globalThis.charmStore||"opencharm.")+UTF8ToString(key))}function js_reconnect(){charmSim.reconnect()}var _sim_set_build,_sim_commit,_sim_panel_radius,_sim_init,_sim_frame,_sim_pin_key,_sim_pin_ready,_sim_frame_box,_sim_frame_dirty,_sim_tick,_sim_pointer,_sim_key,_sim_connected,_sim_disconnected,_sim_text,_sim_type,_sim_audio,_sim_mic_pcm,_sim_token,_sim_forget,_free,_malloc,memory,__indirect_function_table,wasmMemory;function assignWasmExports(wasmExports){_sim_set_build=Module["_sim_set_build"]=wasmExports["s"];_sim_commit=Module["_sim_commit"]=wasmExports["t"];_sim_panel_radius=Module["_sim_panel_radius"]=wasmExports["u"];_sim_init=Module["_sim_init"]=wasmExports["v"];_sim_frame=Module["_sim_frame"]=wasmExports["w"];_sim_pin_key=Module["_sim_pin_key"]=wasmExports["x"];_sim_pin_ready=Module["_sim_pin_ready"]=wasmExports["y"];_sim_frame_box=Module["_sim_frame_box"]=wasmExports["z"];_sim_frame_dirty=Module["_sim_frame_dirty"]=wasmExports["A"];_sim_tick=Module["_sim_tick"]=wasmExports["B"];_sim_pointer=Module["_sim_pointer"]=wasmExports["C"];_sim_key=Module["_sim_key"]=wasmExports["D"];_sim_connected=Module["_sim_connected"]=wasmExports["E"];_sim_disconnected=Module["_sim_disconnected"]=wasmExports["F"];_sim_text=Module["_sim_text"]=wasmExports["G"];_sim_type=Module["_sim_type"]=wasmExports["H"];_sim_audio=Module["_sim_audio"]=wasmExports["I"];_sim_mic_pcm=Module["_sim_mic_pcm"]=wasmExports["J"];_sim_token=Module["_sim_token"]=wasmExports["K"];_sim_forget=Module["_sim_forget"]=wasmExports["L"];_free=Module["_free"]=wasmExports["M"];_malloc=Module["_malloc"]=wasmExports["N"];memory=wasmMemory=wasmExports["q"];__indirect_function_table=wasmExports["__indirect_function_table"]}var wasmImports={o:___cxa_throw,l:__abort_js,j:_emscripten_resize_heap,k:_fd_close,b:_fd_write,e:js_brightness,a:js_mic,p:js_panel,g:js_play_pcm,m:js_reconnect,h:js_send_binary,i:js_send_text,f:js_stop_audio,n:js_store_erase,d:js_store_get,c:js_store_set};async function run(){preRun();var setStatus=Module["setStatus"];if(setStatus){setStatus("Running...");await new Promise(resolve=>setTimeout(resolve,1));setTimeout(setStatus,1,"")}if(ABORT)return;initRuntime();Module["onRuntimeInitialized"]?.();postRun()}var wasmExports;wasmExports=await createWasm();await run();
|
|
1
|
+
async function createCharm(moduleArg={}){var Module=moduleArg;var ENVIRONMENT_IS_WEB=true;var ENVIRONMENT_IS_WORKER=false;var programArgs=[];var thisProgram="./this.program";var _scriptName=import.meta.url;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{readAsync=async url=>{var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;class EmscriptenEH{}class EmscriptenSjLj extends EmscriptenEH{}var runtimeInitialized=false;function getMemoryBuffer(){return wasmMemory.buffer}function updateMemoryViews(){if(HEAP8?.buffer?.resizable)return;var b=getMemoryBuffer();HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b)}function preRun(){var preRun=Module["preRun"];if(preRun){if(typeof preRun=="function")preRun=[preRun];onPreRuns.push(...preRun)}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["r"]()}function postRun(){var postRun=Module["postRun"];if(postRun){if(typeof postRun=="function")postRun=[postRun];onPostRuns.push(...postRun)}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what=`Aborted(${what})`;err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var wasmBinaryFile;function findWasmBinary(){if(Module["locateFile"]){return locateFile("charm_sim.wasm")}return new URL("charm_sim.wasm",import.meta.url).href}function getBinarySync(file){if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();var instantiateWasm=Module["instantiateWasm"];if(instantiateWasm){return new Promise(resolve=>{instantiateWasm(info,inst=>resolve(receiveInstance(inst)))})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var HEAP8;var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var onPreRuns=[];var noExitRuntime=true;var HEAPU32;class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var uncaughtExceptionCount=0;var __Unwind_RaiseException=ex=>{abort()};var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);uncaughtExceptionCount++;__Unwind_RaiseException(ptr)};var __abort_js=()=>abort("");var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var HEAPU8;var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var _fd_close=fd=>52;var printCharBuffers=[null,[],[]];var UTF8Decoder=globalThis.TextDecoder&&new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx<endPtr){var u0=heapOrArray[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heapOrArray[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heapOrArray[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|heapOrArray[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}return str};var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(!curr||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer));buffer.length=0}else{buffer.push(curr)}};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j<len;j++){printChar(fd,HEAPU8[ptr+j])}num+=len}HEAPU32[pnum>>2]=num;return 0};var HEAPF32;var HEAP16;var HEAP32;var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.codePointAt(i);if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i<str.length;++i){var c=str.charCodeAt(i);if(c<=127){len++}else if(c<=2047){len+=2}else if(c>=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["arguments"])programArgs=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];var preInit=Module["preInit"];if(preInit){if(typeof preInit=="function")Module["preInit"]=preInit=[preInit];while(preInit.length>0){preInit.shift()()}}}Module["UTF8ToString"]=UTF8ToString;Module["stringToUTF8"]=stringToUTF8;Module["lengthBytesUTF8"]=lengthBytesUTF8;function js_panel(open,height){charmSim.panel(!!open,height)}function js_send_text(json){charmSim.sendText(UTF8ToString(json))}function js_send_binary(data,size){charmSim.sendBinary(HEAPU8.slice(data,data+size))}function js_mic(on){charmSim.mic(!!on)}function js_play_pcm(pcm,samples){charmSim.playPcm(HEAPF32.slice(pcm>>2,(pcm>>2)+samples))}function js_stop_audio(){charmSim.stopAudio()}function js_brightness(percent){charmSim.brightness(percent)}function js_store_get(key){var value=localStorage.getItem((globalThis.charmStore||"opencharm.")+UTF8ToString(key));if(value===null)return 0;var size=lengthBytesUTF8(value)+1;var ptr=_malloc(size);stringToUTF8(value,ptr,size);return ptr}function js_store_set(key,value){localStorage.setItem((globalThis.charmStore||"opencharm.")+UTF8ToString(key),UTF8ToString(value))}function js_store_erase(key){localStorage.removeItem((globalThis.charmStore||"opencharm.")+UTF8ToString(key))}function js_reconnect(){charmSim.reconnect()}var _sim_set_build,_sim_commit,_sim_panel_radius,_sim_init,_sim_frame,_sim_pin_key,_sim_pin_ready,_sim_frame_box,_sim_frame_dirty,_sim_tick,_sim_pointer,_sim_key,_sim_connected,_sim_disconnected,_sim_text,_sim_type,_sim_audio,_sim_mic_pcm,_sim_token,_sim_forget,_sim_status_open,_sim_status,_free,_malloc,memory,__indirect_function_table,wasmMemory;function assignWasmExports(wasmExports){_sim_set_build=Module["_sim_set_build"]=wasmExports["s"];_sim_commit=Module["_sim_commit"]=wasmExports["t"];_sim_panel_radius=Module["_sim_panel_radius"]=wasmExports["u"];_sim_init=Module["_sim_init"]=wasmExports["v"];_sim_frame=Module["_sim_frame"]=wasmExports["w"];_sim_pin_key=Module["_sim_pin_key"]=wasmExports["x"];_sim_pin_ready=Module["_sim_pin_ready"]=wasmExports["y"];_sim_frame_box=Module["_sim_frame_box"]=wasmExports["z"];_sim_frame_dirty=Module["_sim_frame_dirty"]=wasmExports["A"];_sim_tick=Module["_sim_tick"]=wasmExports["B"];_sim_pointer=Module["_sim_pointer"]=wasmExports["C"];_sim_key=Module["_sim_key"]=wasmExports["D"];_sim_connected=Module["_sim_connected"]=wasmExports["E"];_sim_disconnected=Module["_sim_disconnected"]=wasmExports["F"];_sim_text=Module["_sim_text"]=wasmExports["G"];_sim_type=Module["_sim_type"]=wasmExports["H"];_sim_audio=Module["_sim_audio"]=wasmExports["I"];_sim_mic_pcm=Module["_sim_mic_pcm"]=wasmExports["J"];_sim_token=Module["_sim_token"]=wasmExports["K"];_sim_forget=Module["_sim_forget"]=wasmExports["L"];_sim_status_open=Module["_sim_status_open"]=wasmExports["M"];_sim_status=Module["_sim_status"]=wasmExports["N"];_free=Module["_free"]=wasmExports["O"];_malloc=Module["_malloc"]=wasmExports["P"];memory=wasmMemory=wasmExports["q"];__indirect_function_table=wasmExports["__indirect_function_table"]}var wasmImports={c:___cxa_throw,m:__abort_js,k:_emscripten_resize_heap,l:_fd_close,b:_fd_write,f:js_brightness,a:js_mic,p:js_panel,h:js_play_pcm,n:js_reconnect,i:js_send_binary,j:js_send_text,g:js_stop_audio,o:js_store_erase,e:js_store_get,d:js_store_set};async function run(){preRun();var setStatus=Module["setStatus"];if(setStatus){setStatus("Running...");await new Promise(resolve=>setTimeout(resolve,1));setTimeout(setStatus,1,"")}if(ABORT)return;initRuntime();Module["onRuntimeInitialized"]?.();postRun()}var wasmExports;wasmExports=await createWasm();await run();
|
|
2
2
|
;return Module}export default createCharm;
|
package/sim/charm_sim.wasm
CHANGED
|
Binary file
|
package/sim/index.html
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
<p>
|
|
33
33
|
<b>Hold Space</b> (or the key on the right side) to talk. A short
|
|
34
34
|
press stops speech or dismisses a line. Tap the face. Type the PIN
|
|
35
|
-
on the screen.
|
|
35
|
+
on the screen. <b>Touch and hold the face</b> for the status screen.
|
|
36
36
|
</p>
|
|
37
37
|
<p>
|
|
38
38
|
<b>Orange means it needs you.</b> On a question, hold for yes, press
|
|
@@ -46,15 +46,21 @@
|
|
|
46
46
|
<p class="mono small" id="url"></p>
|
|
47
47
|
<p class="mono dim">BUILD</p>
|
|
48
48
|
<p class="mono small" id="build"></p>
|
|
49
|
+
<p class="mono dim">BATTERY</p>
|
|
50
|
+
<div class="battery">
|
|
51
|
+
<input type="range" id="battery" min="0" max="100" value="80" />
|
|
52
|
+
<span class="mono small" id="battery-value">80%</span>
|
|
53
|
+
</div>
|
|
49
54
|
<div class="buttons">
|
|
55
|
+
<button class="pill" id="usb">Plug in USB</button>
|
|
50
56
|
<button class="pill" id="wifi">Drop Wi-Fi</button>
|
|
51
57
|
<button class="pill" id="shape">Round screen</button>
|
|
52
58
|
<button class="pill" id="forget">Forget pairing</button>
|
|
53
59
|
</div>
|
|
54
60
|
<p class="mono dim">LATER</p>
|
|
55
61
|
<p class="small dim">
|
|
56
|
-
Pick up, face-down
|
|
57
|
-
|
|
62
|
+
Pick up, face-down and shake arrive with the motion sensor work
|
|
63
|
+
(after the MVP).
|
|
58
64
|
</p>
|
|
59
65
|
<p class="small dim">
|
|
60
66
|
Same code as the charm: firmware/core compiled to WebAssembly. No
|
package/sim/sim.css
CHANGED
package/sim/sim.js
CHANGED
|
@@ -52,6 +52,7 @@ const trace = {
|
|
|
52
52
|
micReady: false, // the microphone is open right now (only while the key is held)
|
|
53
53
|
micOpens: 0, // how many times it was opened
|
|
54
54
|
micLatencyMs: null, // key-down to the first mic frame the core took, last hold (includes a 60 ms frame)
|
|
55
|
+
statusOpen: false, // the status screen is up (spec 009)
|
|
55
56
|
};
|
|
56
57
|
window.__charm = trace;
|
|
57
58
|
|
|
@@ -204,6 +205,7 @@ async function connect() {
|
|
|
204
205
|
trace.connected = true;
|
|
205
206
|
statusEl.textContent = "CONNECTED";
|
|
206
207
|
M._sim_connected();
|
|
208
|
+
sendStatus();
|
|
207
209
|
};
|
|
208
210
|
ws.onmessage = (event) => {
|
|
209
211
|
if (typeof event.data === "string") {
|
|
@@ -224,6 +226,7 @@ async function connect() {
|
|
|
224
226
|
trace.connected = false;
|
|
225
227
|
statusEl.textContent = wifiOn ? "RECONNECTING" : "WI-FI OFF";
|
|
226
228
|
M._sim_disconnected();
|
|
229
|
+
sendStatus();
|
|
227
230
|
setTimeout(connect, 1500);
|
|
228
231
|
};
|
|
229
232
|
}
|
|
@@ -414,6 +417,50 @@ document.getElementById("forget").addEventListener("click", () => {
|
|
|
414
417
|
ws?.close();
|
|
415
418
|
});
|
|
416
419
|
|
|
420
|
+
// The battery and status screen (spec 009): the board reads its own once a second; here the side
|
|
421
|
+
// panel stands in for it. The desktop charm (notch) has no battery, so it sends none.
|
|
422
|
+
const batteryEl = document.getElementById("battery");
|
|
423
|
+
const batteryValueEl = document.getElementById("battery-value");
|
|
424
|
+
const usbEl = document.getElementById("usb");
|
|
425
|
+
let usb = false;
|
|
426
|
+
function charmdHost() {
|
|
427
|
+
try {
|
|
428
|
+
return new URL(ws?.url || baseUrl).host;
|
|
429
|
+
} catch {
|
|
430
|
+
return "";
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
// Sent only when something changed: at rest the emulator (and the desktop charm, which runs this
|
|
434
|
+
// page) must stay at its slow tick.
|
|
435
|
+
let lastStatus = "";
|
|
436
|
+
function sendStatus() {
|
|
437
|
+
const percent = notch ? -1 : Number(batteryEl.value);
|
|
438
|
+
const host = charmdHost();
|
|
439
|
+
const now = [percent, usb, wifiOn, host, trace.connected].join("|");
|
|
440
|
+
if (now === lastStatus) return;
|
|
441
|
+
lastStatus = now;
|
|
442
|
+
withString(host, (ptr) =>
|
|
443
|
+
M._sim_status(
|
|
444
|
+
percent,
|
|
445
|
+
usb ? 1 : 0,
|
|
446
|
+
wifiOn ? 1 : 0,
|
|
447
|
+
ptr,
|
|
448
|
+
trace.connected ? 1 : 0
|
|
449
|
+
)
|
|
450
|
+
);
|
|
451
|
+
wake(400);
|
|
452
|
+
}
|
|
453
|
+
batteryEl.addEventListener("input", () => {
|
|
454
|
+
batteryValueEl.textContent = `${batteryEl.value}%`;
|
|
455
|
+
sendStatus();
|
|
456
|
+
});
|
|
457
|
+
usbEl.addEventListener("click", () => {
|
|
458
|
+
usb = !usb;
|
|
459
|
+
usbEl.classList.toggle("on", usb);
|
|
460
|
+
usbEl.textContent = usb ? "On USB" : "Plug in USB";
|
|
461
|
+
sendStatus();
|
|
462
|
+
});
|
|
463
|
+
|
|
417
464
|
// The charm is always on screen, so it must cost next to nothing at rest. The core only redraws what
|
|
418
465
|
// moved; this loop copies only that box, ticks at 60 Hz while something animates and at 10 Hz at
|
|
419
466
|
// rest (a breath step or a blink now and then), and wakes at once for input or a message.
|
|
@@ -442,6 +489,7 @@ function loop() {
|
|
|
442
489
|
const now = performance.now();
|
|
443
490
|
M._sim_tick(Math.floor(now));
|
|
444
491
|
const drew = M._sim_frame_dirty() === 1;
|
|
492
|
+
trace.statusOpen = M._sim_status_open() === 1;
|
|
445
493
|
if (drew) blit();
|
|
446
494
|
// Two frames in a row means an animation is running: keep up with it.
|
|
447
495
|
const animating = drew && drewLast;
|