@jdr377/mapapp-agent-connector 0.1.0-pre.2 → 0.1.0-pre.5
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 +109 -210
- package/bun.lock +1 -1
- package/dist/chunk-4tt14q1n.js +3 -0
- package/dist/{chunk-nygqde9t.js → chunk-7rw6c7fh.js} +2 -2
- package/dist/{chunk-nmac0vha.js → chunk-ez599c79.js} +4 -4
- package/dist/chunk-gbvnsz9p.js +46 -0
- package/dist/{chunk-er6bkfzk.js → chunk-ty38erd0.js} +1 -1
- package/dist/participant-mcp-server.js +2 -2
- package/distribution.json +41 -20
- package/package.json +3 -3
- package/dist/chunk-25pyst1y.js +0 -19
- package/dist/chunk-wy5sgkmh.js +0 -3
package/dist/chunk-wy5sgkmh.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{__require}from"./chunk-btwmey1h.js";var MEDIA_RELAY_SAFE_MAX_BYTES=99*1024;function readWebpDimensions(bytes){if(bytes.length<20||text4(bytes,0)!=="RIFF"||text4(bytes,8)!=="WEBP"||u32(bytes,4)+8!==bytes.length)return null;let offset=12;let extended=null;let image=null;while(offset<bytes.length){if(offset+8>bytes.length)return null;const kind=text4(bytes,offset);const length=u32(bytes,offset+4);const payload=offset+8;const end=payload+length;const paddedEnd=end+(length&1);if(end>bytes.length||paddedEnd>bytes.length)return null;if(!extended&&kind==="VP8X"){if(length!==10)return null;extended={width:1+u24(bytes,payload+4),height:1+u24(bytes,payload+7)}}else if(!image&&kind==="VP8 "){if(length<10||bytes[payload+3]!==157||bytes[payload+4]!==1||bytes[payload+5]!==42)return null;image={width:(bytes[payload+6]|bytes[payload+7]<<8)&16383,height:(bytes[payload+8]|bytes[payload+9]<<8)&16383}}else if(!image&&kind==="VP8L"){if(length<5||bytes[payload]!==47)return null;const bits=u32(bytes,payload+1);image={width:1+(bits&16383),height:1+(bits>>>14&16383)}}offset=paddedEnd}if(offset!==bytes.length||!image)return null;if(extended&&(extended.width!==image.width||extended.height!==image.height))return null;return extended??image}function text4(bytes,offset){return String.fromCharCode(...bytes.slice(offset,offset+4))}function u24(bytes,offset){return bytes[offset]|bytes[offset+1]<<8|bytes[offset+2]<<16}function u32(bytes,offset){return(bytes[offset]|bytes[offset+1]<<8|bytes[offset+2]<<16|bytes[offset+3]<<24)>>>0}var AGENT_MEDIA_MAX_BASE64_LENGTH=4*Math.ceil(MEDIA_RELAY_SAFE_MAX_BYTES/3);class AgentMediaError extends Error{code;constructor(code){super(code);this.code=code}}function fail(code){throw new AgentMediaError(code)}function validAgentMediaInput(value){if(!value||typeof value!=="object"||Array.isArray(value))return false;const media=value;return Object.keys(media).length===4&&Object.keys(media).every((key)=>["contentType","base64","byteSize","sha256"].includes(key))&&["image/webp","video/webm"].includes(media.contentType)&&typeof media.base64==="string"&&media.base64.length>0&&media.base64.length<=AGENT_MEDIA_MAX_BASE64_LENGTH&&media.base64.length%4===0&&/^[A-Za-z0-9+/]*={0,2}$/.test(media.base64)&&Number.isSafeInteger(media.byteSize)&&media.byteSize>0&&media.byteSize<=MEDIA_RELAY_SAFE_MAX_BYTES&&typeof media.sha256==="string"&&/^[0-9a-f]{64}$/.test(media.sha256)}async function inspectAgentMedia(value){if(!validAgentMediaInput(value))fail("invalid_media_input");const binary=atob(value.base64);if(btoa(binary)!==value.base64)fail("invalid_media_base64");const bytes=Uint8Array.from(binary,(character)=>character.charCodeAt(0));if(bytes.length!==value.byteSize)fail("media_size_mismatch");const hash=new Uint8Array(await crypto.subtle.digest("SHA-256",bytes.buffer));const sha256=Array.from(hash,(byte)=>byte.toString(16).padStart(2,"0")).join("");if(sha256!==value.sha256)fail("media_hash_mismatch");const dimensions=value.contentType==="image/webp"?await inspectImage(bytes):await inspectVideo(bytes);return{media:value.contentType==="image/webp"?{kind:"image",contentType:"image/webp",bytes}:{kind:"video",contentType:"video/webm",bytes},summary:{contentType:value.contentType,byteSize:bytes.length,sha256,...dimensions}}}async function inspectImage(bytes){const dimensions=readWebpDimensions(bytes);if(!dimensions)fail("invalid_media_container");if(dimensions.width<1||dimensions.height<1||dimensions.width>1024||dimensions.height>1024)fail("media_dimensions_too_large");try{const{default:decode}=await import("@jsquash/webp/decode.js");const decoded=await decode(Uint8Array.from(bytes).buffer);if(decoded.width!==dimensions.width||decoded.height!==dimensions.height)fail("invalid_media_container");return dimensions}catch{return fail("invalid_media_container")}}async function inspectVideo(bytes){const{Input,BufferSource,WEBM}=await import("mediabunny");const input=new Input({source:new BufferSource(bytes),formats:[WEBM]});let timeout;try{return await Promise.race([(async()=>{const[videos,audios,tracks]=await Promise.all([input.getVideoTracks(),input.getAudioTracks(),input.getTracks()]);if(videos.length!==1||audios.length>1||tracks.length!==videos.length+audios.length)fail("media_tracks_unsupported");const track=videos[0];const[codec,width,height,displayWidth,displayHeight,duration,stats]=await Promise.all([track.getCodec(),track.getCodedWidth(),track.getCodedHeight(),track.getDisplayWidth(),track.getDisplayHeight(),input.computeDuration(),track.computePacketStats(1)]);if(codec!=="vp8"&&codec!=="vp9")fail("media_codec_unsupported");if([width,height,displayWidth,displayHeight].some((size)=>!Number.isFinite(size)||size<1||size>512))fail("media_dimensions_too_large");if(!Number.isFinite(duration)||duration<=0||duration>30)fail("media_video_duration_invalid");if(stats.packetCount<1)fail("invalid_media_container");if(audios[0]&&!["opus","vorbis"].includes(await audios[0].getCodec()??""))fail("media_codec_unsupported");return{width,height,durationMs:Math.ceil(duration*1000)}})(),new Promise((_,reject)=>{timeout=setTimeout(()=>{input.dispose();reject(new AgentMediaError("media_inspection_timeout"))},5000)})])}catch(error){if(error instanceof AgentMediaError)throw error;return fail("invalid_media_container")}finally{clearTimeout(timeout);input.dispose()}}var MAPAPP_CATEGORY_TOKENS=["\uD83C\uDF31","\uD83D\uDCCD","\uD83E\uDDED","\uD83C\uDFA8","\uD83C\uDFB5","\uD83C\uDF7D\uFE0F","\u2615","\uD83D\uDED2","\uD83C\uDFC0","\uD83C\uDFAE","\uD83D\uDCF0","\uD83D\uDCAC","\uD83D\uDCF8","\uD83C\uDFAC","\uD83D\uDCBB","\uD83D\uDEE0\uFE0F","\uD83C\uDFE0","\uD83D\uDE97","\uD83C\uDF0A","\u26F0\uFE0F","\uD83C\uDF33","\uD83D\uDC3E","\uD83C\uDF93","\uD83C\uDFE5","\u26A0\uFE0F","\uD83C\uDF89","\uD83D\uDCBC","\uD83D\uDD2C","\u2708\uFE0F","\uD83E\uDDD8","\uD83E\uDE99","\u2764\uFE0F"];var DEFAULT_MAPAPP_CATEGORY=MAPAPP_CATEGORY_TOKENS[0];import{Hash,Utils}from"@bsv/sdk";var MESSAGING_IDENTITY_VERSION="mapapp-messaging-identity-v1";var MESSAGING_IDENTITY_MUTATION_VERSION="mapapp-messaging-identity-mutation-v1";var MAPAPP_MESSAGE_VERSION="mapapp-message-v1";var DEFAULT_MESSAGE_PLAINTEXT_MAX_BYTES=8*1024;var MAPAPP_MESSAGE_ID_MAX_BYTES=256;function serializeMessagingIdentityMutationV1(input){const mutation=assertMessagingIdentityMutationV1(input);return new TextEncoder().encode(JSON.stringify({version:mutation.version,operation:mutation.operation,bapId:mutation.bapId,walletIdentityKey:mutation.walletIdentityKey,messageBoxHost:mutation.messageBoxHost,deployment:mutation.deployment,canonicalOrigin:mutation.canonicalOrigin,network:mutation.network,expectedProfileOutpoint:mutation.expectedProfileOutpoint,expectedEvidenceHash:mutation.expectedEvidenceHash,acceptedSequence:mutation.acceptedSequence,projectionVersion:mutation.projectionVersion,clientOperationId:mutation.clientOperationId}))}function serializeMapAppMessageV1(input,maxPlaintextBytes=DEFAULT_MESSAGE_PLAINTEXT_MAX_BYTES){const message=assertMapAppMessageV1(input,maxPlaintextBytes);return JSON.stringify({version:message.version,messageId:message.messageId,senderIdentityKey:message.senderIdentityKey,recipientIdentityKey:message.recipientIdentityKey,conversationId:message.conversationId,sentAt:message.sentAt,text:message.text})}function conversationIdForIdentityKeys(first,second){assertCompressedIdentityKey(first,"first identity key");assertCompressedIdentityKey(second,"second identity key");if(first.toLowerCase()===second.toLowerCase())throw new TypeError("Self-messaging is not allowed.");const[left,right]=[first.toLowerCase(),second.toLowerCase()].sort();return Utils.toHex(Hash.sha256(Array.from(new TextEncoder().encode(`mapapp-messaging/conversation/v1\\0${left}\\0${right}`))))}function assertMapAppMessageV1(value,maxPlaintextBytes=DEFAULT_MESSAGE_PLAINTEXT_MAX_BYTES){const record=strictRecord(value,["version","messageId","senderIdentityKey","recipientIdentityKey","conversationId","sentAt","text"],"MapAppMessageV1");if(record.version!==MAPAPP_MESSAGE_VERSION)throw new TypeError("Unsupported MapApp message version.");const messageId=stringField(record,"messageId");if(messageId.trim()===""||new TextEncoder().encode(messageId).byteLength>MAPAPP_MESSAGE_ID_MAX_BYTES)throw new TypeError("messageId must be a bounded non-empty string.");assertCanonicalIsoTimestamp(stringField(record,"sentAt"),"sentAt");const senderIdentityKey=stringField(record,"senderIdentityKey");const recipientIdentityKey=stringField(record,"recipientIdentityKey");assertCompressedIdentityKey(senderIdentityKey,"sender identity key");assertCompressedIdentityKey(recipientIdentityKey,"recipient identity key");if(senderIdentityKey.toLowerCase()===recipientIdentityKey.toLowerCase())throw new TypeError("Self-messaging is not allowed.");const expectedConversationId=conversationIdForIdentityKeys(senderIdentityKey,recipientIdentityKey);if(stringField(record,"conversationId")!==expectedConversationId)throw new TypeError("Message conversation ID does not match its participants.");if(!Number.isSafeInteger(maxPlaintextBytes)||maxPlaintextBytes<=0)throw new TypeError("Plaintext maximum must be a positive safe integer.");const text=stringField(record,"text");if(text.trim()==="")throw new TypeError("Message text must not be blank.");if(new TextEncoder().encode(text).byteLength>maxPlaintextBytes)throw new RangeError("Message text exceeds the plaintext maximum.");return record}function assertMessagingIdentityMutationV1(value){const record=strictRecord(value,["version","operation","bapId","walletIdentityKey","messageBoxHost","deployment","canonicalOrigin","network","expectedProfileOutpoint","expectedEvidenceHash","acceptedSequence","projectionVersion","clientOperationId"],"MessagingIdentityMutationV1");if(record.version!==MESSAGING_IDENTITY_MUTATION_VERSION)throw new TypeError("Unsupported messaging identity mutation version.");if(record.operation!=="register"&&record.operation!=="rotate"&&record.operation!=="revoke")throw new TypeError("Unsupported messaging identity operation.");for(const key of["bapId","messageBoxHost","deployment","canonicalOrigin","clientOperationId"])assertNonEmptyString(record[key],key);assertCompressedIdentityKey(stringField(record,"walletIdentityKey"),"wallet identity key");if(record.network!=="mainnet"&&record.network!=="testnet")throw new TypeError("Unsupported messaging network.");assertProfileEvidenceGroup(record);assertHttpsUrl(stringField(record,"messageBoxHost"),"messageBoxHost");assertHttpsUrl(stringField(record,"canonicalOrigin"),"canonicalOrigin");return record}function assertMessagingIdentityV1(value){const record=strictRecord(value,["version","bapId","walletIdentityKey","messageBoxHost","deployment","canonicalOrigin","network","expectedProfileOutpoint","expectedEvidenceHash","acceptedSequence","projectionVersion"],"MessagingIdentityV1");if(record.version!==MESSAGING_IDENTITY_VERSION)throw new TypeError("Unsupported messaging identity version.");for(const key of["bapId","messageBoxHost","deployment","canonicalOrigin"])assertNonEmptyString(record[key],key);assertCompressedIdentityKey(stringField(record,"walletIdentityKey"),"wallet identity key");if(record.network!=="mainnet"&&record.network!=="testnet")throw new TypeError("Unsupported messaging network.");assertProfileEvidenceGroup(record);assertHttpsUrl(stringField(record,"messageBoxHost"),"messageBoxHost");assertHttpsUrl(stringField(record,"canonicalOrigin"),"canonicalOrigin");return record}function assertCompressedIdentityKey(value,field="identity key"){if(!/^(02|03)[0-9a-fA-F]{64}$/.test(value))throw new TypeError(`${field} must be a compressed public key.`)}function strictRecord(value,keys,name){if(!value||typeof value!=="object"||Array.isArray(value))throw new TypeError(`${name} must be an object.`);const record=value;if(Object.keys(record).length!==keys.length||keys.some((key)=>!(key in record)))throw new TypeError(`${name} has unsupported or missing fields.`);return record}function stringField(record,key){const value=record[key];if(typeof value!=="string")throw new TypeError(`${key} must be a string.`);return value}function numberField(record,key){const value=record[key];if(typeof value!=="number"||!Number.isSafeInteger(value))throw new TypeError(`${key} must be a non-negative safe integer.`);return value}function assertProfileEvidenceGroup(record){const fields=[record.expectedProfileOutpoint,record.expectedEvidenceHash,record.acceptedSequence,record.projectionVersion];if(fields.every((value)=>value===null))return;if(fields.some((value)=>value===null))throw new TypeError("Profile evidence must be entirely present or absent.");assertNonEmptyString(record.expectedProfileOutpoint,"expectedProfileOutpoint");assertNonEmptyString(record.expectedEvidenceHash,"expectedEvidenceHash");if(numberField(record,"acceptedSequence")<1)throw new TypeError("acceptedSequence must be positive.");if(numberField(record,"projectionVersion")<0)throw new TypeError("projectionVersion must be non-negative.")}function assertNonEmptyString(value,field){if(typeof value!=="string"||value.trim()==="")throw new TypeError(`${field} must be a non-empty string.`)}function assertHttpsUrl(value,field){try{const parsed=new URL(String(value));if(parsed.protocol!=="https:"||parsed.username||parsed.password||parsed.pathname!=="/"||parsed.search||parsed.hash)throw new Error}catch{throw new TypeError(`${field} must be an HTTPS origin without a path.`)}}function assertCanonicalIsoTimestamp(value,field="timestamp"){if(!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(value)||!Number.isFinite(Date.parse(value))||new Date(value).toISOString()!==value)throw new TypeError(`${field} must be a canonical ISO-8601 UTC timestamp.`)}
|
|
3
|
-
export{MEDIA_RELAY_SAFE_MAX_BYTES,AGENT_MEDIA_MAX_BASE64_LENGTH,AgentMediaError,validAgentMediaInput,inspectAgentMedia,MAPAPP_CATEGORY_TOKENS,MESSAGING_IDENTITY_MUTATION_VERSION,MAPAPP_MESSAGE_VERSION,DEFAULT_MESSAGE_PLAINTEXT_MAX_BYTES,MAPAPP_MESSAGE_ID_MAX_BYTES,serializeMessagingIdentityMutationV1,serializeMapAppMessageV1,conversationIdForIdentityKeys,assertMapAppMessageV1,assertMessagingIdentityV1,assertCompressedIdentityKey,assertCanonicalIsoTimestamp};
|