agent-comms 2.18.3 → 2.19.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/dist/bridges/user/web/dist/bundle.js +1 -1
- package/dist/bridges/user/web/frontend/project-tree.js +3 -3
- package/dist/bridges/user/web/frontend/project-tree.js.map +1 -1
- package/dist/bridges/user/web/test/port-discovery.unit.test.js +10 -11
- package/dist/bridges/user/web/test/port-discovery.unit.test.js.map +1 -1
- package/dist/bridges/user/web/test/web-server.integration.test.js +12 -13
- package/dist/bridges/user/web/test/web-server.integration.test.js.map +1 -1
- package/dist/core/test/bridge.unit.test.js +11 -12
- package/dist/core/test/bridge.unit.test.js.map +1 -1
- package/dist/core/test/identity.unit.test.js +21 -22
- package/dist/core/test/identity.unit.test.js.map +1 -1
- package/dist/test/approval.integration.test.js +52 -45
- package/dist/test/approval.integration.test.js.map +1 -1
- package/dist/test/become-coordinator-actual-port.integration.test.d.ts +0 -2
- package/dist/test/become-coordinator-actual-port.integration.test.d.ts.map +1 -1
- package/dist/test/become-coordinator-actual-port.integration.test.js +14 -39
- package/dist/test/become-coordinator-actual-port.integration.test.js.map +1 -1
- package/dist/test/bridge-mesh.test.js +9 -10
- package/dist/test/bridge-mesh.test.js.map +1 -1
- package/dist/test/broadcast-window.integration.test.js +4 -7
- package/dist/test/broadcast-window.integration.test.js.map +1 -1
- package/dist/test/coordinator-socket-error.integration.test.js +3 -4
- package/dist/test/coordinator-socket-error.integration.test.js.map +1 -1
- package/dist/test/create-room-mints-owner-grant.test.js +9 -8
- package/dist/test/create-room-mints-owner-grant.test.js.map +1 -1
- package/dist/test/create-room-name-sanitisation.test.js +6 -7
- package/dist/test/create-room-name-sanitisation.test.js.map +1 -1
- package/dist/test/dm-admission.integration.test.js +10 -11
- package/dist/test/dm-admission.integration.test.js.map +1 -1
- package/dist/test/federation.integration.test.js +21 -20
- package/dist/test/federation.integration.test.js.map +1 -1
- package/dist/test/filestore.test.js +16 -17
- package/dist/test/filestore.test.js.map +1 -1
- package/dist/test/handshake.test.js +26 -27
- package/dist/test/handshake.test.js.map +1 -1
- package/dist/test/identity-cert.test.js +3 -4
- package/dist/test/identity-cert.test.js.map +1 -1
- package/dist/test/identity-device-id.test.js +6 -7
- package/dist/test/identity-device-id.test.js.map +1 -1
- package/dist/test/identity-restart.integration.test.js +9 -10
- package/dist/test/identity-restart.integration.test.js.map +1 -1
- package/dist/test/identity-store.test.js +27 -24
- package/dist/test/identity-store.test.js.map +1 -1
- package/dist/test/listener-policy.integration.test.js +63 -56
- package/dist/test/listener-policy.integration.test.js.map +1 -1
- package/dist/test/mcp-registry-retry.test.js +10 -11
- package/dist/test/mcp-registry-retry.test.js.map +1 -1
- package/dist/test/mesh-e2e.integration.test.js +26 -19
- package/dist/test/mesh-e2e.integration.test.js.map +1 -1
- package/dist/test/presence-readvertise.integration.test.js +5 -6
- package/dist/test/presence-readvertise.integration.test.js.map +1 -1
- package/dist/test/random-id.test.js +3 -4
- package/dist/test/random-id.test.js.map +1 -1
- package/dist/test/room-admission-tool-actions.test.js +20 -15
- package/dist/test/room-admission-tool-actions.test.js.map +1 -1
- package/dist/test/room-destroy-revocation.integration.test.js +3 -4
- package/dist/test/room-destroy-revocation.integration.test.js.map +1 -1
- package/dist/test/room-invite-directed.integration.test.js +13 -12
- package/dist/test/room-invite-directed.integration.test.js.map +1 -1
- package/dist/test/room-join-admission.test.js +31 -24
- package/dist/test/room-join-admission.test.js.map +1 -1
- package/dist/test/room-kick-revocation.integration.test.js +5 -6
- package/dist/test/room-kick-revocation.integration.test.js.map +1 -1
- package/dist/test/room-leave-revocation.integration.test.js +10 -9
- package/dist/test/room-leave-revocation.integration.test.js.map +1 -1
- package/dist/test/room-path.test.js +16 -17
- package/dist/test/room-path.test.js.map +1 -1
- package/dist/test/room-read-directed.integration.test.js +14 -11
- package/dist/test/room-read-directed.integration.test.js.map +1 -1
- package/dist/test/room-router.test.js +27 -29
- package/dist/test/room-router.test.js.map +1 -1
- package/dist/test/room-send-directed.integration.test.js +11 -12
- package/dist/test/room-send-directed.integration.test.js.map +1 -1
- package/dist/test/room-send-retry-queue.test.js +10 -11
- package/dist/test/room-send-retry-queue.test.js.map +1 -1
- package/dist/test/room-send-retry.integration.test.js +5 -8
- package/dist/test/room-send-retry.integration.test.js.map +1 -1
- package/dist/test/room-state-sync.integration.test.js +18 -15
- package/dist/test/room-state-sync.integration.test.js.map +1 -1
- package/dist/test/room-token-store.test.js +21 -22
- package/dist/test/room-token-store.test.js.map +1 -1
- package/dist/test/room-token-verification.test.js +19 -20
- package/dist/test/room-token-verification.test.js.map +1 -1
- package/dist/test/state-sync-convergence.test.js +25 -26
- package/dist/test/state-sync-convergence.test.js.map +1 -1
- package/dist/test/visibility.integration.test.js +48 -49
- package/dist/test/visibility.integration.test.js.map +1 -1
- package/dist/test/wire-mesh-identity.test.js +7 -8
- package/dist/test/wire-mesh-identity.test.js.map +1 -1
- package/package.json +9 -5
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/ExaDev/agent-comms)
|
|
4
4
|
[](https://www.npmjs.com/package/agent-comms)
|
|
5
|
-
[](https://github.com/ExaDev/agent-comms/releases/tag/v2.19.0)
|
|
6
6
|
[](https://github.com/ExaDev/agent-comms/actions)
|
|
7
7
|
|
|
8
8
|
Cross-harness communication mesh for LLM agents: rooms, DMs, presence, and visibility over TCP with zero filesystem dependencies.
|
|
@@ -562,4 +562,4 @@ body {
|
|
|
562
562
|
background: var(--accent);
|
|
563
563
|
color: var(--bg);
|
|
564
564
|
}
|
|
565
|
-
`}));var H,b,_e,He,Z=0,qe=[],x=h,ze=x.__b,We=x.__r,Ue=x.diffed,Je=x.__c,Oe=x.unmount,Ve=x.__;function he(e,n){x.__h&&x.__h(b,e,Z||n),Z=0;var t=b.__H||(b.__H={__:[],__h:[]});return e>=t.__.length&&t.__.push({}),t.__[e]}function w(e){return Z=1,Jn(Qe,e)}function Jn(e,n,t){var o=he(H++,2);if(o.t=e,!o.__c&&(o.__=[t?t(n):Qe(void 0,n),function(d){var u=o.__N?o.__N[0]:o.__[0],l=o.t(u,d);u!==l&&(o.__N=[l,o.__[1]],o.__c.setState({}))}],o.__c=b,!b.__f)){var i=function(d,u,l){if(!o.__c.__H)return!0;var p=!1,f=o.__c.props!==d;if(o.__c.__H.__.some(function(m){if(m.__N){p=!0;var y=m.__[0];m.__=m.__N,m.__N=void 0,y!==m.__[0]&&(f=!0)}}),r){var s=r.call(this,d,u,l);return p?s||f:s}return!p||f};b.__f=!0;var r=b.shouldComponentUpdate,a=b.componentWillUpdate;b.componentWillUpdate=function(d,u,l){if(this.__e){var p=r;r=void 0,i(d,u,l),r=p}a&&a.call(this,d,u,l)},b.shouldComponentUpdate=i}return o.__N||o.__}function Ke(e,n){var t=he(H++,3);!x.__s&&Ge(t.__H,n)&&(t.__=e,t.u=n,b.__H.__h.push(t))}function Xe(e){return Z=5,On(function(){return{current:e}},[])}function On(e,n){var t=he(H++,7);return Ge(t.__H,n)&&(t.__=e(),t.__H=n,t.__h=e),t.__}function Vn(){for(var e;e=qe.shift();){var n=e.__H;if(e.__P&&n)try{n.__h.some(Y),n.__h.some(ge),n.__h=[]}catch(t){n.__h=[],x.__e(t,e.__v)}}}x.__b=function(e){b=null,ze&&ze(e)},x.__=function(e,n){e&&n.__k&&n.__k.__m&&(e.__m=n.__k.__m),Ve&&Ve(e,n)},x.__r=function(e){We&&We(e),H=0;var n=(b=e.__c).__H;n&&(_e===b?(n.__h=[],b.__h=[],n.__.some(function(t){t.__N&&(t.__=t.__N),t.u=t.__N=void 0})):(n.__h.some(Y),n.__h.some(ge),n.__h=[],H=0)),_e=b},x.diffed=function(e){Ue&&Ue(e);var n=e.__c;n&&n.__H&&(n.__H.__h.length&&(qe.push(n)!==1&&He===x.requestAnimationFrame||((He=x.requestAnimationFrame)||Bn)(Vn)),n.__H.__.some(function(t){t.u&&(t.__H=t.u,t.u=void 0)})),_e=b=null},x.__c=function(e,n){n.some(function(t){try{t.__h.some(Y),t.__h=t.__h.filter(function(o){return!o.__||ge(o)})}catch(o){n.some(function(i){i.__h&&(i.__h=[])}),n=[],x.__e(o,t.__v)}}),Je&&Je(e,n)},x.unmount=function(e){Oe&&Oe(e);var n,t=e.__c;t&&t.__H&&(t.__H.__.some(function(o){try{Y(o)}catch(i){n=i}}),t.__H=void 0,n&&x.__e(n,t.__v))};var Be=typeof requestAnimationFrame=="function";function Bn(e){var n,t=function(){clearTimeout(o),Be&&cancelAnimationFrame(n),setTimeout(e)},o=setTimeout(t,35);Be&&(n=requestAnimationFrame(t))}function Y(e){var n=b,t=e.__c;typeof t=="function"&&(e.__c=void 0,t()),b=n}function ge(e){var n=b;e.__c=e.__(),b=n}function Ge(e,n){return!e||e.length!==n.length||n.some(function(t,o){return t!==e[o]})}function Qe(e,n){return typeof n=="function"?n(e):n}function Ye(e,n,t){let o=e.querySelector(n);if(!o)throw new Error(`Required element not found: ${n}`);if(t&&o.tagName.toLowerCase()!==t)throw new Error(`Element ${n} must be <${t}>, got <${o.tagName.toLowerCase()}>`);return o}function ve(e){return e.slice(11,19)}function S(e){let n=e.target;if(n instanceof HTMLInputElement||n instanceof HTMLSelectElement)return n;throw new Error("Event target is not an input element")}function Ze(e){if(e.kind!=="action")return null;let n=e.action;return n.action==="join_room"?{kind:"join_room",room:n.room}:n.action==="leave_room"?{kind:"leave_room"}:null}function ee(e,n,t){let o=e.trim();return o.length===0?{kind:"ignored"}:o.startsWith("/")?qn(o,n):n?{kind:"action",action:{action:"send",target:n,content:o}}:t?{kind:"action",action:{action:"dm",target:t,content:o}}:{kind:"local",result:{type:"error",text:"Join a room or select an agent first"}}}function qn(e,n){let t=e.slice(1).split(/\s+/),o=(t[0]??"").toLowerCase();switch(o){case"join":return t[1]?{kind:"action",action:{action:"join_room",room:t[1]}}:{kind:"local",result:{type:"error",text:"Usage: /join <room>"}};case"leave":return{kind:"action",action:{action:"leave_room",room:t[1]??n??""}};case"rooms":return{kind:"action",action:{action:"list_rooms"}};case"agents":return{kind:"action",action:{action:"list_agents"}};case"dm":return!t[1]||!t[2]?{kind:"local",result:{type:"error",text:"Usage: /dm <agent> <message>"}}:{kind:"action",action:{action:"dm",target:t[1],content:t.slice(2).join(" ")}};case"create":return t[1]?{kind:"action",action:{action:"create_room",name:t[1],type:"public"}}:{kind:"local",result:{type:"error",text:"Usage: /create <name>"}};case"destroy":return t[1]?{kind:"action",action:{action:"destroy_room",room:t[1]}}:{kind:"local",result:{type:"error",text:"Usage: /destroy <room>"}};case"rename":return!t[1]||!t[2]?{kind:"local",result:{type:"error",text:"Usage: /rename <agent> <new-name>"}}:{kind:"action",action:{action:"rename_agent",agent:t[1],name:t.slice(2).join(" ")}};case"help":return{kind:"local",result:{type:"help",text:"Commands: /join, /leave, /rooms, /agents, /dm, /create, /destroy, /rename, /help"}};default:return{kind:"local",result:{type:"unknown",text:`Unknown command: /${o}`}}}}var Kn=0;function c(e,n,t,o,i,r){n||(n={});var a,d,u=n;if("ref"in u)for(d in u={},n)d=="ref"?a=n[d]:u[d]=n[d];var l={type:e,props:u,key:t,ref:a,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--Kn,__i:-1,__u:0,__source:i,__self:r};if(typeof e=="function"&&(a=e.defaultProps))for(d in a)u[d]===void 0&&(u[d]=a[d]);return h.vnode&&h.vnode(l),l}function en({message:e}){switch(e.type){case"chat":return c("div",{class:"msg",children:[c("span",{class:"sender",children:e.sender}),c("span",{class:"time",children:ve(e.timestamp)}),":"," ",e.content]});case"dm":return c("div",{class:"msg dm",children:[c("span",{class:"dm-badge",children:"DM"})," ",c("span",{class:"sender",children:e.sender}),c("span",{class:"time",children:ve(e.timestamp)}),":"," ",e.content]});case"system":return c("div",{class:"msg system",children:e.text});case"status":return c("div",{class:"msg status",children:e.text})}}function nn({messages:e}){let n=Xe(null);return Ke(()=>{n.current&&(n.current.scrollTop=n.current.scrollHeight)},[e.length]),c("div",{id:"messages",ref:n,children:e.map((t,o)=>c(en,{message:t},o))})}function tn({messages:e,currentRoom:n,dmTarget:t,connected:o,onSendAction:i,onLeaveRoom:r,onConnectToMesh:a}){let[d,u]=w(""),l=n??(t?`DM with ${t}`:"Select a room"),p=()=>{let s=d.trim();if(!s)return;switch(ee(s,n,t).kind){case"action":i(s);break;case"local":i(s);break;case"ignored":break}u("")},f=s=>{s.key==="Enter"&&p()};return c("div",{id:"main",children:[c("div",{id:"header",children:[l,n&&c("button",{class:"leave-btn",onClick:r,children:"Leave"})]}),c(nn,{messages:e}),!o&&e.length===0&&c("div",{class:"connect-prompt",children:[c("p",{children:"Connect to a local mesh to discover agents and rooms."}),c("button",{class:"connect-btn",onClick:a,children:"Connect to local mesh"})]}),c("div",{id:"input-bar",children:[c("input",{id:"input",type:"text",placeholder:"Type a message or /command...",autocomplete:"off",value:d,onInput:s=>{u(S(s).value)},onKeyDown:f}),c("button",{id:"send-btn",onClick:p,children:"Send"})]})]})}function rn(e,n,t){let[o,...i]=n;if(o===void 0){e.agents.push(t);return}let r=e.children.get(o);r||(r={children:new Map,agents:[]},e.children.set(o,r)),rn(r,i,t)}function sn(e,n){let[t,...o]=n;if(t===void 0)return;let i=e.children.get(t);i||(i={children:new Map,agents:[]},e.children.set(t,i)),sn(i,o)}var an="Project room for ";function on(e){return e.description.startsWith(an)}function Xn(e){return e.description.slice(an.length)}function cn(e,n){let t=n.filter(p=>!on(p)),o=new Map;for(let p of n)on(p)&&o.set(Xn(p),p);let i=new Set;for(let p of e)i.add(p.cwd);for(let p of o.keys())i.add(p);if(i.size===0)return{roots:[],manualRooms:t};let r=Array.from(i),a=Qn(r),d=a==="/"?[]:ne(a),u={children:new Map,agents:[]};for(let p of e){let f=ne(p.cwd).slice(d.length);rn(u,f,p)}for(let p of o.keys()){let f=ne(p).slice(d.length);sn(u,f)}let l=ln(u,a,"",o);return{roots:dn(l),manualRooms:t}}function ne(e){return e.split("/").filter(n=>n.length>0)}function Gn(...e){return"/"+e.join("/")}function Qn(e){if(e.length===0)return"/";let n=e.map(ne),t=Math.min(...n.map(i=>i.length)),o=0;for(let i=0;i<t;i++){let r=n[0]?.[i];if(r===void 0)break;if(n.every(a=>a[i]===r))o++;else break}return o>0&&o--,o===0?"/":Gn(...n[0]?.slice(0,o)??[])}function ln(e,n,t,o){let i=[];for(let[r,a]of e.children){let d=t===""&&n==="/"?"/"+r:t===""?n+"/"+r:t+"/"+r,u=ln(a,n,d,o);if(u.length>0){let l=o.get(d);i.push({type:"directory",name:r,path:d,...l?{roomId:l.id}:{},children:dn(u)})}}for(let r of e.agents)i.push({type:"agent",name:r.name,agentId:r.id,status:r.status,cwd:r.cwd});return i}function dn(e){return[...e].sort((n,t)=>n.type!==t.type?n.type==="directory"?-1:1:n.name.localeCompare(t.name))}function pn({visible:e,onSubmit:n,onCancel:t}){let[o,i]=w(""),[r,a]=w("public"),[d,u]=w("");return e?c("div",{id:"create-room-form",class:"visible",children:c("form",{class:"create-room-form",onSubmit:p=>{p.preventDefault(),o.trim()&&(n(o.trim(),r,d.trim()),i(""),a("public"),u(""))},children:[c("label",{children:["Room name",c("input",{type:"text",name:"room-name",required:!0,placeholder:"e.g. project-alpha",value:o,onInput:p=>{i(S(p).value)}})]}),c("label",{children:["Type",c("select",{name:"room-type",value:r,onChange:p=>{let f=S(p).value;(f==="public"||f==="private"||f==="secret")&&a(f)},children:[c("option",{value:"public",children:"Public"}),c("option",{value:"private",children:"Private"}),c("option",{value:"secret",children:"Secret"})]})]}),c("label",{children:["Description (optional)",c("input",{type:"text",name:"room-description",placeholder:"What is this room about?",value:d,onInput:p=>{u(S(p).value)}})]}),c("div",{class:"create-room-btns",children:[c("button",{type:"submit",class:"create-room-submit",children:"Create"}),c("button",{type:"button",class:"create-room-cancel",onClick:t,children:"Cancel"})]})]})}):null}function un({visible:e,onSubmit:n,onCancel:t}){let[o,i]=w("");if(!e)return c("div",{id:"join-form",class:"join-form hidden"});let r=()=>{let d=o.trim();d&&(n(d),i(""))};return c("div",{id:"join-form",class:"join-form",children:[c("input",{class:"join-input",type:"text",placeholder:"Room name...",autocomplete:"off",value:o,onInput:d=>{i(S(d).value)},onKeyDown:d=>{d.key==="Enter"&&r(),d.key==="Escape"&&t()}}),c("button",{class:"join-submit",onClick:r,children:"Join"})]})}function mn({tree:e,onJoinRoom:n,onSelectAgent:t,onRenameAgent:o,currentRoom:i}){return c("div",{id:"room-list",class:"project-tree",children:[e.roots.map(r=>c(fn,{node:r,onJoinRoom:n,onSelectAgent:t,onRenameAgent:o,currentRoom:i})),e.manualRooms.length>0&&c("div",{class:"tree-section",children:[c("h3",{class:"tree-section-heading",children:"Rooms"}),e.manualRooms.map(r=>c("div",{class:"room-item"+(i===r.id?" active":""),onClick:()=>{n(r.id)},children:[c("span",{children:r.name}),c("span",{children:["(",String(r.members.length),")"]})]},r.id))]})]})}function fn({node:e,onJoinRoom:n,onSelectAgent:t,onRenameAgent:o,currentRoom:i}){return e.type==="agent"?c(Zn,{node:e,onSelectAgent:t,onRenameAgent:o}):c(Yn,{node:e,onJoinRoom:n,onSelectAgent:t,onRenameAgent:o,currentRoom:i})}function Yn({node:e,onJoinRoom:n,onSelectAgent:t,onRenameAgent:o,currentRoom:i}){let[r,a]=w(!0),d=e.roomId!==void 0,u=i===e.roomId;return c("div",{class:"tree-directory",children:[c("div",{class:"tree-directory-name",children:[c("span",{class:"tree-folder-toggle",title:"Expand/collapse",onClick:l=>{l.stopPropagation(),a(!r)},children:c("span",{class:"tree-folder-icon",children:r?"\u{1F4C2}":"\u{1F4C1}"})}),c("span",{class:`tree-directory-label${u?" active":""}${d?" clickable":""}`,onClick:()=>{e.roomId&&n(e.roomId)},children:e.name})]}),r&&c("div",{class:"tree-children",children:e.children.map(l=>c(fn,{node:l,onJoinRoom:n,onSelectAgent:t,onRenameAgent:o,currentRoom:i},l.type==="agent"?l.agentId:l.path))})]})}function Zn({node:e,onSelectAgent:n,onRenameAgent:t}){let[o,i]=w(!1),[r,a]=w(""),d=()=>{a(e.name),i(!0)},u=()=>{let p=r.trim();p&&p!==e.name&&t(e.agentId,p),i(!1)},l=p=>{p.key==="Enter"&&u(),p.key==="Escape"&&i(!1)};return o?c("div",{class:"tree-agent agent-item editing",children:[c("span",{class:`status-dot ${e.status}`}),c("input",{class:"agent-rename-input",type:"text",value:r,autofocus:!0,onInput:p=>{a(S(p).value)},onKeyDown:l,onBlur:u})]}):c("div",{class:"tree-agent agent-item",onClick:()=>{n(e.agentId)},onDblClick:d,children:[c("span",{class:`status-dot ${e.status}`}),c("span",{children:e.name})]})}function _n({rooms:e,agents:n,currentRoom:t,collapsed:o,onJoinRoom:i,onSelectAgent:r,onRenameAgent:a,onCreateRoom:d,onJoinRoomInput:u}){let[l,p]=w(!1),[f,s]=w(!1),[m,y]=w(!1),C=m?n:n.filter(_=>_.status!=="offline"),k=cn(C,e);return c("div",{id:"sidebar",class:o?"sidebar-collapsed":"",children:[c("h2",{children:["Agent Comms",c("button",{id:"toggle-offline-btn",class:`icon-btn${m?" active":""}`,title:`${m?"Hide":"Show"} offline agents`,onClick:()=>{y(_=>!_)},children:m?"\u25C9":"\u25CE"})]}),c("div",{class:"sidebar-section",children:[c(mn,{tree:k,onJoinRoom:i,onSelectAgent:r,onRenameAgent:a,currentRoom:t}),c("div",{class:"section-heading",children:[c("h3",{children:"Create"}),c("button",{id:"create-room-toggle",class:"icon-btn",title:"Create room",onClick:()=>{p(_=>!_)},children:"+"})]}),c(pn,{visible:l,onSubmit:(_,g,R)=>{d(_,g,R),p(!1)},onCancel:()=>{p(!1)}}),c("button",{id:"join-toggle-btn",class:"join-toggle-btn",onClick:()=>{s(_=>!_)},children:"+ Join Room"}),c(un,{visible:f,onSubmit:_=>{u(_),s(!1)},onCancel:()=>{s(!1)}})]})]})}function gn(e){let[n,t]=w(!1);return c(P,{children:[c("button",{id:"sidebar-toggle",class:"sidebar-toggle-btn",title:n?"Expand sidebar":"Collapse sidebar",onClick:()=>{t(o=>!o)},children:n?"\u2630":"\u2715"}),c(_n,{rooms:e.rooms,agents:e.agents,currentRoom:e.currentRoom,collapsed:n,onJoinRoom:e.onJoinRoom,onSelectAgent:e.onSelectAgent,onRenameAgent:e.onRenameAgent,onCreateRoom:e.onCreateRoom,onJoinRoomInput:e.onJoinRoomInput}),c(tn,{messages:e.messages,currentRoom:e.currentRoom,dmTarget:e.dmTarget,connected:e.connected,onSendAction:e.onSendAction,onLeaveRoom:e.onLeaveRoom,onConnectToMesh:e.onConnectToMesh})]})}function et(e){return typeof e=="object"&&e!==null}function nt(e){return Array.isArray(e)}function tt(e){return Array.isArray(e)}function ot(e){return Array.isArray(e)}function rt(e){return et(e)&&typeof e.type=="string"}async function hn(){let n=await(await fetch("/api/agents")).json();if(!nt(n))throw new Error("Invalid agents response");return n}async function vn(){let n=await(await fetch("/api/rooms")).json();if(!tt(n))throw new Error("Invalid rooms response");return n}async function yn(e,n){let t=n?`/api/rooms/${encodeURIComponent(e)}/messages?since=${encodeURIComponent(n)}`:`/api/rooms/${encodeURIComponent(e)}/messages`,i=await(await fetch(t)).json();if(!ot(i))throw new Error("Invalid messages response");return i}var te=class{constructor(n){A(this,"ws");A(this,"reconnectTimer");A(this,"handler");this.handler=n}connect(){let n=location.protocol==="https:"?"wss:":"ws:",t=new WebSocket(`${n}//${location.host}`);this.ws=t,t.onopen=()=>{this.handler.onOpen?.()},t.onclose=()=>{this.handler.onClose?.(),this.scheduleReconnect()},t.onerror=()=>{},t.onmessage=o=>{let i=JSON.parse(typeof o.data=="string"?o.data:String(o.data));rt(i)&&this.handler.onFrame?.(i)}}sendAction(n){let t=this.ws;t?.readyState===WebSocket.OPEN&&t.send(JSON.stringify(n))}disconnect(){this.reconnectTimer!==void 0&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0);let n=this.ws;n&&n.close(),this.ws=void 0}scheduleReconnect(){this.reconnectTimer=setTimeout(()=>{this.connect()},3e3)}};var bn={currentRoom:void 0,dmTarget:void 0,agents:[],rooms:[],messages:[],connected:!1},oe=class{constructor(){A(this,"state",{...bn});A(this,"listeners",new Set)}subscribe(n){return this.listeners.add(n),()=>{this.listeners.delete(n)}}get(){return this.state}setCurrentRoom(n){this.state={...this.state,currentRoom:n},this.notify()}setDmTarget(n){this.state={...this.state,dmTarget:n},this.notify()}setAgents(n){this.state={...this.state,agents:n},this.notify()}setRooms(n){this.state={...this.state,rooms:n},this.notify()}setConnected(n){this.state={...this.state,connected:n},this.notify()}addMessage(n){this.state={...this.state,messages:[...this.state.messages,n]},this.notify()}setMessages(n){this.state={...this.state,messages:n},this.notify()}clearMessages(){this.state={...this.state,messages:[]},this.notify()}applyState(n,t){this.state={...this.state,agents:n,rooms:t},this.notify()}reset(){this.state={...bn,messages:[]},this.notify()}notify(){let n=this.state;for(let t of this.listeners)t(n)}};var re=class{constructor(){A(this,"worker");A(this,"state",{agents:[],rooms:[],connected:!1});A(this,"listeners",new Set);A(this,"actionCounter",0);A(this,"pendingActions",new Map)}connect(){if(this.worker)return;let n=new SharedWorker("./mesh-worker.js");if(this.worker=n,n.port.onmessage=i=>{let r=JSON.parse(typeof i.data=="string"?i.data:String(i.data));if(it(r))switch(r.type){case"state":{if(!("state"in r)||typeof r.state!="object"||r.state===null||!("agents"in r.state)||!("rooms"in r.state))break;let a=r.state,d=typeof a.agents=="object"&&a.agents!==null?Object.values(a.agents):[],u=typeof a.rooms=="object"&&a.rooms!==null?Object.values(a.rooms):[];this.state={...this.state,agents:d,rooms:u},this.notify();break}case"connected":this.state={...this.state,connected:!0},this.notify();break;case"disconnected":this.state={...this.state,connected:!1},this.notify();break;case"patch":this.postToWorker({type:"getState"});break;case"actionResult":break;case"actionError":break}},n.port.start(),/^(localhost|127\.\d+\.\d+\.\d+)(:\d+)?$/.test(location.host)){let r=`${location.protocol==="https:"?"wss:":"ws:"}//${location.host}/ws/mesh`;this.postToWorker({type:"init",url:r})}else this.probeLocalMesh(19877,10)}get(){return this.state}subscribe(n){return this.listeners.add(n),()=>{this.listeners.delete(n)}}sendAction(n){let t=String(++this.actionCounter);this.postToWorker({type:"action",id:t,action:n})}disconnect(){this.worker&&(this.worker.port.close(),this.worker=void 0),this.pendingActions.clear()}probeLocalMesh(n,t){let o=0,i=r=>{if(o>=t)return;o++;let a=`ws://127.0.0.1:${String(r)}/ws/mesh`;fetch(`http://127.0.0.1:${String(r)}/`,{mode:"no-cors"}).then(()=>{this.postToWorker({type:"init",url:a})}).catch(()=>{i(r+1)})};i(n)}postToWorker(n){this.worker&&this.worker.port.postMessage(JSON.stringify(n))}notify(){let n=this.state;for(let t of this.listeners)t(n)}};function it(e){return typeof e=="object"&&e!==null&&"type"in e}var st=/^(localhost|127\.\d+\.\d+\.\d+)(:\d+)?$/;function xn(e){return st.test(e)}function kn(e){return e.getItem("agent-comms-connected")==="true"}function wn(e,n){switch(e.type){case"room_message":return n===e.message.room?{type:"chat",sender:e.message.from,content:e.message.content,timestamp:e.message.timestamp}:void 0;case"dm":return{type:"dm",sender:e.message.from,content:e.message.content,timestamp:e.message.timestamp};case"member_joined":return{type:"system",text:`${e.agent} joined ${e.room}`};case"member_left":return{type:"system",text:`${e.agent} left ${e.room}`};case"member_status":return{type:"status",text:`${e.agent} is now ${e.status} in ${e.room}`};case"delivery_status":return{type:"status",text:`Message ${e.messageId} ${e.status} by ${e.agent}`};case"room_members":return n===e.room?{type:"system",text:`Members: ${e.members.map(o=>`${o.name} (${o.status})`).join(", ")}`}:void 0;case"room_invite":{let t=e.roomDescription?` \u2014 ${e.roomDescription}`:"";return{type:"system",text:`${e.fromName} invited you to "${e.room}"${t}`}}case"invite_declined":return{type:"system",text:`${e.agentName} declined invite to ${e.room}: "${e.reason}"`};case"name_changed":return{type:"system",text:`${e.oldName} is now known as ${e.newName}`}}}function Rn(e){return{type:"chat",sender:e.from,content:e.content,timestamp:e.timestamp}}var at="Project room for ";function Cn(e){let n=new URLSearchParams(e),t=n.get("room");if(t)return{kind:"room",roomId:t};let o=n.get("dm");if(o)return{kind:"dm",agentId:o};let i=n.get("cwd");if(i)return{kind:"cwd",path:i}}function An(e,n){switch(e.kind){case"room":return n.some(t=>t.id===e.roomId)?{kind:"room",targetId:e.roomId}:void 0;case"dm":return{kind:"dm",targetId:e.agentId};case"cwd":{let t=n.find(o=>o.description===`${at}${e.path}`);return t?{kind:"room",targetId:t.id}:void 0}}}function Tn(e){let n=new URL(location.href);n.searchParams.delete("room"),n.searchParams.delete("dm"),n.searchParams.delete("cwd"),e.currentRoom?n.searchParams.set("room",e.currentRoom):e.dmTarget&&n.searchParams.set("dm",e.dmTarget);let t=n.pathname+n.search+n.hash;history.replaceState(null,"",t)}var z=xn(location.host),ct=Ye(document,"#root"),v=new oe,be=new re;be.subscribe(e=>{e.agents.length>0&&v.setAgents(e.agents),e.rooms.length>0&&v.setRooms(e.rooms),v.setConnected(e.connected)});function E(e){v.addMessage(e)}var ie,xe=new te({onOpen:()=>{v.setConnected(!0),E({type:"system",text:"Connected to mesh"})},onClose:()=>{v.setConnected(!1),E({type:"system",text:"Disconnected \u2014 reconnecting..."})},onFrame:lt});function lt(e){let n=v.get();switch(e.type){case"delivery":{let t=wn(e.event,n.currentRoom);t&&E(t),(e.event.type==="member_joined"||e.event.type==="member_left"||e.event.type==="member_status"||e.event.type==="name_changed")&&ye();break}case"result":if(E({type:"system",text:e.result.content}),!e.result.isError){if(ie?.action==="join_room"&&!v.get().currentRoom){let t=ie.room;v.setDmTarget(void 0),v.setCurrentRoom(t)}ye()}ie=void 0;break;case"error":E({type:"status",text:`Error: ${e.message}`});break;case"state":v.applyState(e.agents,e.rooms);break}}function W(e){ie=e,xe.sendAction(e)}async function ye(){if(!z)return;let[e,n]=await Promise.all([hn(),vn()]);v.setAgents(e),v.setRooms(n)}async function se(e){if(v.setDmTarget(void 0),v.setCurrentRoom(e),v.clearMessages(),W({action:"join_room",room:e}),z){let n=await yn(e);v.setMessages(n.map(Rn))}E({type:"system",text:`Joined ${e}`})}function Mn(e){v.setCurrentRoom(void 0),v.setDmTarget(e),v.clearMessages()}function jn(){let e=v.get().currentRoom;e&&(W({action:"leave_room",room:e}),v.setCurrentRoom(void 0),v.clearMessages(),E({type:"system",text:`Left room "${e}"`}))}function dt(e){let n=v.get(),t=ee(e,n.currentRoom,n.dmTarget),o=Ze(t);if(o)switch(o.kind){case"join_room":se(o.room);return;case"leave_room":jn();return}switch(t.kind){case"action":W(t.action);break;case"local":E({type:"system",text:t.result.text});break;case"ignored":break}}function pt(e,n,t){let o={action:"create_room",name:e,type:n,...t?{description:t}:{}};W(o)}function ut(e){se(e)}function mt(e,n){W({action:"rename_agent",agent:e,name:n})}function Pn(){let e=v.get();Tn({currentRoom:e.currentRoom,dmTarget:e.dmTarget}),Fe(c(gn,{rooms:e.rooms,agents:e.agents,currentRoom:e.currentRoom,dmTarget:e.dmTarget,messages:e.messages,connected:e.connected,onJoinRoom:n=>{se(n)},onSelectAgent:Mn,onRenameAgent:mt,onLeaveRoom:jn,onSendAction:dt,onCreateRoom:pt,onJoinRoomInput:ut,onConnectToMesh:()=>{localStorage.setItem("agent-comms-connected","true"),be.connect(),z&&xe.connect()}}),ct)}v.subscribe(Pn);var Sn=Cn(location.search);Pn();var ft=kn(localStorage);(z||ft)&&(be.connect(),z&&xe.connect());ye().then(()=>{if(!Sn)return;let e=v.get(),n=An(Sn,e.rooms);if(n)switch(n.kind){case"room":se(n.targetId);break;case"dm":Mn(n.targetId);break}});})();
|
|
565
|
+
`}));var H,b,_e,He,Z=0,qe=[],x=h,ze=x.__b,We=x.__r,Ue=x.diffed,Je=x.__c,Oe=x.unmount,Ve=x.__;function he(e,n){x.__h&&x.__h(b,e,Z||n),Z=0;var t=b.__H||(b.__H={__:[],__h:[]});return e>=t.__.length&&t.__.push({}),t.__[e]}function w(e){return Z=1,Jn(Qe,e)}function Jn(e,n,t){var o=he(H++,2);if(o.t=e,!o.__c&&(o.__=[t?t(n):Qe(void 0,n),function(d){var u=o.__N?o.__N[0]:o.__[0],l=o.t(u,d);u!==l&&(o.__N=[l,o.__[1]],o.__c.setState({}))}],o.__c=b,!b.__f)){var i=function(d,u,l){if(!o.__c.__H)return!0;var p=!1,f=o.__c.props!==d;if(o.__c.__H.__.some(function(m){if(m.__N){p=!0;var y=m.__[0];m.__=m.__N,m.__N=void 0,y!==m.__[0]&&(f=!0)}}),r){var s=r.call(this,d,u,l);return p?s||f:s}return!p||f};b.__f=!0;var r=b.shouldComponentUpdate,a=b.componentWillUpdate;b.componentWillUpdate=function(d,u,l){if(this.__e){var p=r;r=void 0,i(d,u,l),r=p}a&&a.call(this,d,u,l)},b.shouldComponentUpdate=i}return o.__N||o.__}function Ke(e,n){var t=he(H++,3);!x.__s&&Ge(t.__H,n)&&(t.__=e,t.u=n,b.__H.__h.push(t))}function Xe(e){return Z=5,On(function(){return{current:e}},[])}function On(e,n){var t=he(H++,7);return Ge(t.__H,n)&&(t.__=e(),t.__H=n,t.__h=e),t.__}function Vn(){for(var e;e=qe.shift();){var n=e.__H;if(e.__P&&n)try{n.__h.some(Y),n.__h.some(ge),n.__h=[]}catch(t){n.__h=[],x.__e(t,e.__v)}}}x.__b=function(e){b=null,ze&&ze(e)},x.__=function(e,n){e&&n.__k&&n.__k.__m&&(e.__m=n.__k.__m),Ve&&Ve(e,n)},x.__r=function(e){We&&We(e),H=0;var n=(b=e.__c).__H;n&&(_e===b?(n.__h=[],b.__h=[],n.__.some(function(t){t.__N&&(t.__=t.__N),t.u=t.__N=void 0})):(n.__h.some(Y),n.__h.some(ge),n.__h=[],H=0)),_e=b},x.diffed=function(e){Ue&&Ue(e);var n=e.__c;n&&n.__H&&(n.__H.__h.length&&(qe.push(n)!==1&&He===x.requestAnimationFrame||((He=x.requestAnimationFrame)||Bn)(Vn)),n.__H.__.some(function(t){t.u&&(t.__H=t.u,t.u=void 0)})),_e=b=null},x.__c=function(e,n){n.some(function(t){try{t.__h.some(Y),t.__h=t.__h.filter(function(o){return!o.__||ge(o)})}catch(o){n.some(function(i){i.__h&&(i.__h=[])}),n=[],x.__e(o,t.__v)}}),Je&&Je(e,n)},x.unmount=function(e){Oe&&Oe(e);var n,t=e.__c;t&&t.__H&&(t.__H.__.some(function(o){try{Y(o)}catch(i){n=i}}),t.__H=void 0,n&&x.__e(n,t.__v))};var Be=typeof requestAnimationFrame=="function";function Bn(e){var n,t=function(){clearTimeout(o),Be&&cancelAnimationFrame(n),setTimeout(e)},o=setTimeout(t,35);Be&&(n=requestAnimationFrame(t))}function Y(e){var n=b,t=e.__c;typeof t=="function"&&(e.__c=void 0,t()),b=n}function ge(e){var n=b;e.__c=e.__(),b=n}function Ge(e,n){return!e||e.length!==n.length||n.some(function(t,o){return t!==e[o]})}function Qe(e,n){return typeof n=="function"?n(e):n}function Ye(e,n,t){let o=e.querySelector(n);if(!o)throw new Error(`Required element not found: ${n}`);if(t&&o.tagName.toLowerCase()!==t)throw new Error(`Element ${n} must be <${t}>, got <${o.tagName.toLowerCase()}>`);return o}function ve(e){return e.slice(11,19)}function S(e){let n=e.target;if(n instanceof HTMLInputElement||n instanceof HTMLSelectElement)return n;throw new Error("Event target is not an input element")}function Ze(e){if(e.kind!=="action")return null;let n=e.action;return n.action==="join_room"?{kind:"join_room",room:n.room}:n.action==="leave_room"?{kind:"leave_room"}:null}function ee(e,n,t){let o=e.trim();return o.length===0?{kind:"ignored"}:o.startsWith("/")?qn(o,n):n?{kind:"action",action:{action:"send",target:n,content:o}}:t?{kind:"action",action:{action:"dm",target:t,content:o}}:{kind:"local",result:{type:"error",text:"Join a room or select an agent first"}}}function qn(e,n){let t=e.slice(1).split(/\s+/),o=(t[0]??"").toLowerCase();switch(o){case"join":return t[1]?{kind:"action",action:{action:"join_room",room:t[1]}}:{kind:"local",result:{type:"error",text:"Usage: /join <room>"}};case"leave":return{kind:"action",action:{action:"leave_room",room:t[1]??n??""}};case"rooms":return{kind:"action",action:{action:"list_rooms"}};case"agents":return{kind:"action",action:{action:"list_agents"}};case"dm":return!t[1]||!t[2]?{kind:"local",result:{type:"error",text:"Usage: /dm <agent> <message>"}}:{kind:"action",action:{action:"dm",target:t[1],content:t.slice(2).join(" ")}};case"create":return t[1]?{kind:"action",action:{action:"create_room",name:t[1],type:"public"}}:{kind:"local",result:{type:"error",text:"Usage: /create <name>"}};case"destroy":return t[1]?{kind:"action",action:{action:"destroy_room",room:t[1]}}:{kind:"local",result:{type:"error",text:"Usage: /destroy <room>"}};case"rename":return!t[1]||!t[2]?{kind:"local",result:{type:"error",text:"Usage: /rename <agent> <new-name>"}}:{kind:"action",action:{action:"rename_agent",agent:t[1],name:t.slice(2).join(" ")}};case"help":return{kind:"local",result:{type:"help",text:"Commands: /join, /leave, /rooms, /agents, /dm, /create, /destroy, /rename, /help"}};default:return{kind:"local",result:{type:"unknown",text:`Unknown command: /${o}`}}}}var Kn=0;function c(e,n,t,o,i,r){n||(n={});var a,d,u=n;if("ref"in u)for(d in u={},n)d=="ref"?a=n[d]:u[d]=n[d];var l={type:e,props:u,key:t,ref:a,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--Kn,__i:-1,__u:0,__source:i,__self:r};if(typeof e=="function"&&(a=e.defaultProps))for(d in a)u[d]===void 0&&(u[d]=a[d]);return h.vnode&&h.vnode(l),l}function en({message:e}){switch(e.type){case"chat":return c("div",{class:"msg",children:[c("span",{class:"sender",children:e.sender}),c("span",{class:"time",children:ve(e.timestamp)}),":"," ",e.content]});case"dm":return c("div",{class:"msg dm",children:[c("span",{class:"dm-badge",children:"DM"})," ",c("span",{class:"sender",children:e.sender}),c("span",{class:"time",children:ve(e.timestamp)}),":"," ",e.content]});case"system":return c("div",{class:"msg system",children:e.text});case"status":return c("div",{class:"msg status",children:e.text})}}function nn({messages:e}){let n=Xe(null);return Ke(()=>{n.current&&(n.current.scrollTop=n.current.scrollHeight)},[e.length]),c("div",{id:"messages",ref:n,children:e.map((t,o)=>c(en,{message:t},o))})}function tn({messages:e,currentRoom:n,dmTarget:t,connected:o,onSendAction:i,onLeaveRoom:r,onConnectToMesh:a}){let[d,u]=w(""),l=n??(t?`DM with ${t}`:"Select a room"),p=()=>{let s=d.trim();if(!s)return;switch(ee(s,n,t).kind){case"action":i(s);break;case"local":i(s);break;case"ignored":break}u("")},f=s=>{s.key==="Enter"&&p()};return c("div",{id:"main",children:[c("div",{id:"header",children:[l,n&&c("button",{class:"leave-btn",onClick:r,children:"Leave"})]}),c(nn,{messages:e}),!o&&e.length===0&&c("div",{class:"connect-prompt",children:[c("p",{children:"Connect to a local mesh to discover agents and rooms."}),c("button",{class:"connect-btn",onClick:a,children:"Connect to local mesh"})]}),c("div",{id:"input-bar",children:[c("input",{id:"input",type:"text",placeholder:"Type a message or /command...",autocomplete:"off",value:d,onInput:s=>{u(S(s).value)},onKeyDown:f}),c("button",{id:"send-btn",onClick:p,children:"Send"})]})]})}function rn(e,n,t){let[o,...i]=n;if(o===void 0){e.agents.push(t);return}let r=e.children.get(o);r||(r={children:new Map,agents:[]},e.children.set(o,r)),rn(r,i,t)}function sn(e,n){let[t,...o]=n;if(t===void 0)return;let i=e.children.get(t);i||(i={children:new Map,agents:[]},e.children.set(t,i)),sn(i,o)}var an="Project room for ";function on(e){return e.description.startsWith(an)}function Xn(e){return e.description.slice(an.length)}function cn(e,n){let t=n.filter(p=>!on(p)),o=new Map;for(let p of n)on(p)&&o.set(Xn(p),p);let i=new Set;for(let p of e)i.add(p.cwd);for(let p of o.keys())i.add(p);if(i.size===0)return{roots:[],manualRooms:t};let r=Array.from(i),a=Qn(r),d=a==="/"?[]:ne(a),u={children:new Map,agents:[]};for(let p of e){let f=ne(p.cwd).slice(d.length);rn(u,f,p)}for(let p of o.keys()){let f=ne(p).slice(d.length);sn(u,f)}let l=ln(u,a,"",o);return{roots:dn(l),manualRooms:t}}function ne(e){return e.split("/").filter(n=>n.length>0)}function Gn(...e){return"/"+e.join("/")}function Qn(e){if(e.length===0)return"/";let n=e.map(ne),t=Math.min(...n.map(i=>i.length)),o=0;for(let i=0;i<t;i++){let r=n[0]?.[i];if(r===void 0)break;if(n.every(a=>a[i]===r))o++;else break}return o>0&&o--,o===0?"/":Gn(...n[0]?.slice(0,o)??[])}function ln(e,n,t,o){let i=[];for(let[r,a]of e.children){let d=t===""&&n==="/"?"/"+r:t===""?n+"/"+r:t+"/"+r,u=ln(a,n,d,o),l=o.get(d);(u.length>0||l)&&i.push({type:"directory",name:r,path:d,...l?{roomId:l.id}:{},children:dn(u)})}for(let r of e.agents)i.push({type:"agent",name:r.name,agentId:r.id,status:r.status,cwd:r.cwd});return i}function dn(e){return[...e].sort((n,t)=>n.type!==t.type?n.type==="directory"?-1:1:n.name.localeCompare(t.name))}function pn({visible:e,onSubmit:n,onCancel:t}){let[o,i]=w(""),[r,a]=w("public"),[d,u]=w("");return e?c("div",{id:"create-room-form",class:"visible",children:c("form",{class:"create-room-form",onSubmit:p=>{p.preventDefault(),o.trim()&&(n(o.trim(),r,d.trim()),i(""),a("public"),u(""))},children:[c("label",{children:["Room name",c("input",{type:"text",name:"room-name",required:!0,placeholder:"e.g. project-alpha",value:o,onInput:p=>{i(S(p).value)}})]}),c("label",{children:["Type",c("select",{name:"room-type",value:r,onChange:p=>{let f=S(p).value;(f==="public"||f==="private"||f==="secret")&&a(f)},children:[c("option",{value:"public",children:"Public"}),c("option",{value:"private",children:"Private"}),c("option",{value:"secret",children:"Secret"})]})]}),c("label",{children:["Description (optional)",c("input",{type:"text",name:"room-description",placeholder:"What is this room about?",value:d,onInput:p=>{u(S(p).value)}})]}),c("div",{class:"create-room-btns",children:[c("button",{type:"submit",class:"create-room-submit",children:"Create"}),c("button",{type:"button",class:"create-room-cancel",onClick:t,children:"Cancel"})]})]})}):null}function un({visible:e,onSubmit:n,onCancel:t}){let[o,i]=w("");if(!e)return c("div",{id:"join-form",class:"join-form hidden"});let r=()=>{let d=o.trim();d&&(n(d),i(""))};return c("div",{id:"join-form",class:"join-form",children:[c("input",{class:"join-input",type:"text",placeholder:"Room name...",autocomplete:"off",value:o,onInput:d=>{i(S(d).value)},onKeyDown:d=>{d.key==="Enter"&&r(),d.key==="Escape"&&t()}}),c("button",{class:"join-submit",onClick:r,children:"Join"})]})}function mn({tree:e,onJoinRoom:n,onSelectAgent:t,onRenameAgent:o,currentRoom:i}){return c("div",{id:"room-list",class:"project-tree",children:[e.roots.map(r=>c(fn,{node:r,onJoinRoom:n,onSelectAgent:t,onRenameAgent:o,currentRoom:i})),e.manualRooms.length>0&&c("div",{class:"tree-section",children:[c("h3",{class:"tree-section-heading",children:"Rooms"}),e.manualRooms.map(r=>c("div",{class:"room-item"+(i===r.id?" active":""),onClick:()=>{n(r.id)},children:[c("span",{children:r.name}),c("span",{children:["(",String(r.members.length),")"]})]},r.id))]})]})}function fn({node:e,onJoinRoom:n,onSelectAgent:t,onRenameAgent:o,currentRoom:i}){return e.type==="agent"?c(Zn,{node:e,onSelectAgent:t,onRenameAgent:o}):c(Yn,{node:e,onJoinRoom:n,onSelectAgent:t,onRenameAgent:o,currentRoom:i})}function Yn({node:e,onJoinRoom:n,onSelectAgent:t,onRenameAgent:o,currentRoom:i}){let[r,a]=w(!0),d=e.roomId!==void 0,u=i===e.roomId;return c("div",{class:"tree-directory",children:[c("div",{class:"tree-directory-name",children:[c("span",{class:"tree-folder-toggle",title:"Expand/collapse",onClick:l=>{l.stopPropagation(),a(!r)},children:c("span",{class:"tree-folder-icon",children:r?"\u{1F4C2}":"\u{1F4C1}"})}),c("span",{class:`tree-directory-label${u?" active":""}${d?" clickable":""}`,onClick:()=>{e.roomId&&n(e.roomId)},children:e.name})]}),r&&c("div",{class:"tree-children",children:e.children.map(l=>c(fn,{node:l,onJoinRoom:n,onSelectAgent:t,onRenameAgent:o,currentRoom:i},l.type==="agent"?l.agentId:l.path))})]})}function Zn({node:e,onSelectAgent:n,onRenameAgent:t}){let[o,i]=w(!1),[r,a]=w(""),d=()=>{a(e.name),i(!0)},u=()=>{let p=r.trim();p&&p!==e.name&&t(e.agentId,p),i(!1)},l=p=>{p.key==="Enter"&&u(),p.key==="Escape"&&i(!1)};return o?c("div",{class:"tree-agent agent-item editing",children:[c("span",{class:`status-dot ${e.status}`}),c("input",{class:"agent-rename-input",type:"text",value:r,autofocus:!0,onInput:p=>{a(S(p).value)},onKeyDown:l,onBlur:u})]}):c("div",{class:"tree-agent agent-item",onClick:()=>{n(e.agentId)},onDblClick:d,children:[c("span",{class:`status-dot ${e.status}`}),c("span",{children:e.name})]})}function _n({rooms:e,agents:n,currentRoom:t,collapsed:o,onJoinRoom:i,onSelectAgent:r,onRenameAgent:a,onCreateRoom:d,onJoinRoomInput:u}){let[l,p]=w(!1),[f,s]=w(!1),[m,y]=w(!1),C=m?n:n.filter(_=>_.status!=="offline"),k=cn(C,e);return c("div",{id:"sidebar",class:o?"sidebar-collapsed":"",children:[c("h2",{children:["Agent Comms",c("button",{id:"toggle-offline-btn",class:`icon-btn${m?" active":""}`,title:`${m?"Hide":"Show"} offline agents`,onClick:()=>{y(_=>!_)},children:m?"\u25C9":"\u25CE"})]}),c("div",{class:"sidebar-section",children:[c(mn,{tree:k,onJoinRoom:i,onSelectAgent:r,onRenameAgent:a,currentRoom:t}),c("div",{class:"section-heading",children:[c("h3",{children:"Create"}),c("button",{id:"create-room-toggle",class:"icon-btn",title:"Create room",onClick:()=>{p(_=>!_)},children:"+"})]}),c(pn,{visible:l,onSubmit:(_,g,R)=>{d(_,g,R),p(!1)},onCancel:()=>{p(!1)}}),c("button",{id:"join-toggle-btn",class:"join-toggle-btn",onClick:()=>{s(_=>!_)},children:"+ Join Room"}),c(un,{visible:f,onSubmit:_=>{u(_),s(!1)},onCancel:()=>{s(!1)}})]})]})}function gn(e){let[n,t]=w(!1);return c(P,{children:[c("button",{id:"sidebar-toggle",class:"sidebar-toggle-btn",title:n?"Expand sidebar":"Collapse sidebar",onClick:()=>{t(o=>!o)},children:n?"\u2630":"\u2715"}),c(_n,{rooms:e.rooms,agents:e.agents,currentRoom:e.currentRoom,collapsed:n,onJoinRoom:e.onJoinRoom,onSelectAgent:e.onSelectAgent,onRenameAgent:e.onRenameAgent,onCreateRoom:e.onCreateRoom,onJoinRoomInput:e.onJoinRoomInput}),c(tn,{messages:e.messages,currentRoom:e.currentRoom,dmTarget:e.dmTarget,connected:e.connected,onSendAction:e.onSendAction,onLeaveRoom:e.onLeaveRoom,onConnectToMesh:e.onConnectToMesh})]})}function et(e){return typeof e=="object"&&e!==null}function nt(e){return Array.isArray(e)}function tt(e){return Array.isArray(e)}function ot(e){return Array.isArray(e)}function rt(e){return et(e)&&typeof e.type=="string"}async function hn(){let n=await(await fetch("/api/agents")).json();if(!nt(n))throw new Error("Invalid agents response");return n}async function vn(){let n=await(await fetch("/api/rooms")).json();if(!tt(n))throw new Error("Invalid rooms response");return n}async function yn(e,n){let t=n?`/api/rooms/${encodeURIComponent(e)}/messages?since=${encodeURIComponent(n)}`:`/api/rooms/${encodeURIComponent(e)}/messages`,i=await(await fetch(t)).json();if(!ot(i))throw new Error("Invalid messages response");return i}var te=class{constructor(n){A(this,"ws");A(this,"reconnectTimer");A(this,"handler");this.handler=n}connect(){let n=location.protocol==="https:"?"wss:":"ws:",t=new WebSocket(`${n}//${location.host}`);this.ws=t,t.onopen=()=>{this.handler.onOpen?.()},t.onclose=()=>{this.handler.onClose?.(),this.scheduleReconnect()},t.onerror=()=>{},t.onmessage=o=>{let i=JSON.parse(typeof o.data=="string"?o.data:String(o.data));rt(i)&&this.handler.onFrame?.(i)}}sendAction(n){let t=this.ws;t?.readyState===WebSocket.OPEN&&t.send(JSON.stringify(n))}disconnect(){this.reconnectTimer!==void 0&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0);let n=this.ws;n&&n.close(),this.ws=void 0}scheduleReconnect(){this.reconnectTimer=setTimeout(()=>{this.connect()},3e3)}};var bn={currentRoom:void 0,dmTarget:void 0,agents:[],rooms:[],messages:[],connected:!1},oe=class{constructor(){A(this,"state",{...bn});A(this,"listeners",new Set)}subscribe(n){return this.listeners.add(n),()=>{this.listeners.delete(n)}}get(){return this.state}setCurrentRoom(n){this.state={...this.state,currentRoom:n},this.notify()}setDmTarget(n){this.state={...this.state,dmTarget:n},this.notify()}setAgents(n){this.state={...this.state,agents:n},this.notify()}setRooms(n){this.state={...this.state,rooms:n},this.notify()}setConnected(n){this.state={...this.state,connected:n},this.notify()}addMessage(n){this.state={...this.state,messages:[...this.state.messages,n]},this.notify()}setMessages(n){this.state={...this.state,messages:n},this.notify()}clearMessages(){this.state={...this.state,messages:[]},this.notify()}applyState(n,t){this.state={...this.state,agents:n,rooms:t},this.notify()}reset(){this.state={...bn,messages:[]},this.notify()}notify(){let n=this.state;for(let t of this.listeners)t(n)}};var re=class{constructor(){A(this,"worker");A(this,"state",{agents:[],rooms:[],connected:!1});A(this,"listeners",new Set);A(this,"actionCounter",0);A(this,"pendingActions",new Map)}connect(){if(this.worker)return;let n=new SharedWorker("./mesh-worker.js");if(this.worker=n,n.port.onmessage=i=>{let r=JSON.parse(typeof i.data=="string"?i.data:String(i.data));if(it(r))switch(r.type){case"state":{if(!("state"in r)||typeof r.state!="object"||r.state===null||!("agents"in r.state)||!("rooms"in r.state))break;let a=r.state,d=typeof a.agents=="object"&&a.agents!==null?Object.values(a.agents):[],u=typeof a.rooms=="object"&&a.rooms!==null?Object.values(a.rooms):[];this.state={...this.state,agents:d,rooms:u},this.notify();break}case"connected":this.state={...this.state,connected:!0},this.notify();break;case"disconnected":this.state={...this.state,connected:!1},this.notify();break;case"patch":this.postToWorker({type:"getState"});break;case"actionResult":break;case"actionError":break}},n.port.start(),/^(localhost|127\.\d+\.\d+\.\d+)(:\d+)?$/.test(location.host)){let r=`${location.protocol==="https:"?"wss:":"ws:"}//${location.host}/ws/mesh`;this.postToWorker({type:"init",url:r})}else this.probeLocalMesh(19877,10)}get(){return this.state}subscribe(n){return this.listeners.add(n),()=>{this.listeners.delete(n)}}sendAction(n){let t=String(++this.actionCounter);this.postToWorker({type:"action",id:t,action:n})}disconnect(){this.worker&&(this.worker.port.close(),this.worker=void 0),this.pendingActions.clear()}probeLocalMesh(n,t){let o=0,i=r=>{if(o>=t)return;o++;let a=`ws://127.0.0.1:${String(r)}/ws/mesh`;fetch(`http://127.0.0.1:${String(r)}/`,{mode:"no-cors"}).then(()=>{this.postToWorker({type:"init",url:a})}).catch(()=>{i(r+1)})};i(n)}postToWorker(n){this.worker&&this.worker.port.postMessage(JSON.stringify(n))}notify(){let n=this.state;for(let t of this.listeners)t(n)}};function it(e){return typeof e=="object"&&e!==null&&"type"in e}var st=/^(localhost|127\.\d+\.\d+\.\d+)(:\d+)?$/;function xn(e){return st.test(e)}function kn(e){return e.getItem("agent-comms-connected")==="true"}function wn(e,n){switch(e.type){case"room_message":return n===e.message.room?{type:"chat",sender:e.message.from,content:e.message.content,timestamp:e.message.timestamp}:void 0;case"dm":return{type:"dm",sender:e.message.from,content:e.message.content,timestamp:e.message.timestamp};case"member_joined":return{type:"system",text:`${e.agent} joined ${e.room}`};case"member_left":return{type:"system",text:`${e.agent} left ${e.room}`};case"member_status":return{type:"status",text:`${e.agent} is now ${e.status} in ${e.room}`};case"delivery_status":return{type:"status",text:`Message ${e.messageId} ${e.status} by ${e.agent}`};case"room_members":return n===e.room?{type:"system",text:`Members: ${e.members.map(o=>`${o.name} (${o.status})`).join(", ")}`}:void 0;case"room_invite":{let t=e.roomDescription?` \u2014 ${e.roomDescription}`:"";return{type:"system",text:`${e.fromName} invited you to "${e.room}"${t}`}}case"invite_declined":return{type:"system",text:`${e.agentName} declined invite to ${e.room}: "${e.reason}"`};case"name_changed":return{type:"system",text:`${e.oldName} is now known as ${e.newName}`}}}function Rn(e){return{type:"chat",sender:e.from,content:e.content,timestamp:e.timestamp}}var at="Project room for ";function Cn(e){let n=new URLSearchParams(e),t=n.get("room");if(t)return{kind:"room",roomId:t};let o=n.get("dm");if(o)return{kind:"dm",agentId:o};let i=n.get("cwd");if(i)return{kind:"cwd",path:i}}function An(e,n){switch(e.kind){case"room":return n.some(t=>t.id===e.roomId)?{kind:"room",targetId:e.roomId}:void 0;case"dm":return{kind:"dm",targetId:e.agentId};case"cwd":{let t=n.find(o=>o.description===`${at}${e.path}`);return t?{kind:"room",targetId:t.id}:void 0}}}function Tn(e){let n=new URL(location.href);n.searchParams.delete("room"),n.searchParams.delete("dm"),n.searchParams.delete("cwd"),e.currentRoom?n.searchParams.set("room",e.currentRoom):e.dmTarget&&n.searchParams.set("dm",e.dmTarget);let t=n.pathname+n.search+n.hash;history.replaceState(null,"",t)}var z=xn(location.host),ct=Ye(document,"#root"),v=new oe,be=new re;be.subscribe(e=>{e.agents.length>0&&v.setAgents(e.agents),e.rooms.length>0&&v.setRooms(e.rooms),v.setConnected(e.connected)});function E(e){v.addMessage(e)}var ie,xe=new te({onOpen:()=>{v.setConnected(!0),E({type:"system",text:"Connected to mesh"})},onClose:()=>{v.setConnected(!1),E({type:"system",text:"Disconnected \u2014 reconnecting..."})},onFrame:lt});function lt(e){let n=v.get();switch(e.type){case"delivery":{let t=wn(e.event,n.currentRoom);t&&E(t),(e.event.type==="member_joined"||e.event.type==="member_left"||e.event.type==="member_status"||e.event.type==="name_changed")&&ye();break}case"result":if(E({type:"system",text:e.result.content}),!e.result.isError){if(ie?.action==="join_room"&&!v.get().currentRoom){let t=ie.room;v.setDmTarget(void 0),v.setCurrentRoom(t)}ye()}ie=void 0;break;case"error":E({type:"status",text:`Error: ${e.message}`});break;case"state":v.applyState(e.agents,e.rooms);break}}function W(e){ie=e,xe.sendAction(e)}async function ye(){if(!z)return;let[e,n]=await Promise.all([hn(),vn()]);v.setAgents(e),v.setRooms(n)}async function se(e){if(v.setDmTarget(void 0),v.setCurrentRoom(e),v.clearMessages(),W({action:"join_room",room:e}),z){let n=await yn(e);v.setMessages(n.map(Rn))}E({type:"system",text:`Joined ${e}`})}function Mn(e){v.setCurrentRoom(void 0),v.setDmTarget(e),v.clearMessages()}function jn(){let e=v.get().currentRoom;e&&(W({action:"leave_room",room:e}),v.setCurrentRoom(void 0),v.clearMessages(),E({type:"system",text:`Left room "${e}"`}))}function dt(e){let n=v.get(),t=ee(e,n.currentRoom,n.dmTarget),o=Ze(t);if(o)switch(o.kind){case"join_room":se(o.room);return;case"leave_room":jn();return}switch(t.kind){case"action":W(t.action);break;case"local":E({type:"system",text:t.result.text});break;case"ignored":break}}function pt(e,n,t){let o={action:"create_room",name:e,type:n,...t?{description:t}:{}};W(o)}function ut(e){se(e)}function mt(e,n){W({action:"rename_agent",agent:e,name:n})}function Pn(){let e=v.get();Tn({currentRoom:e.currentRoom,dmTarget:e.dmTarget}),Fe(c(gn,{rooms:e.rooms,agents:e.agents,currentRoom:e.currentRoom,dmTarget:e.dmTarget,messages:e.messages,connected:e.connected,onJoinRoom:n=>{se(n)},onSelectAgent:Mn,onRenameAgent:mt,onLeaveRoom:jn,onSendAction:dt,onCreateRoom:pt,onJoinRoomInput:ut,onConnectToMesh:()=>{localStorage.setItem("agent-comms-connected","true"),be.connect(),z&&xe.connect()}}),ct)}v.subscribe(Pn);var Sn=Cn(location.search);Pn();var ft=kn(localStorage);(z||ft)&&(be.connect(),z&&xe.connect());ye().then(()=>{if(!Sn)return;let e=v.get(),n=An(Sn,e.rooms);if(n)switch(n.kind){case"room":se(n.targetId);break;case"dm":Mn(n.targetId);break}});})();
|
|
@@ -137,9 +137,9 @@ function branchToNodesWithRooms(branch, prefix, currentPath, projectRoomsByPath)
|
|
|
137
137
|
? prefix + "/" + name
|
|
138
138
|
: currentPath + "/" + name;
|
|
139
139
|
const childNodes = branchToNodesWithRooms(child, prefix, childPath, projectRoomsByPath);
|
|
140
|
-
if
|
|
141
|
-
|
|
142
|
-
|
|
140
|
+
// Check if this directory has a project room
|
|
141
|
+
const room = projectRoomsByPath.get(childPath);
|
|
142
|
+
if (childNodes.length > 0 || room) {
|
|
143
143
|
nodes.push({
|
|
144
144
|
type: "directory",
|
|
145
145
|
name,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-tree.js","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/project-tree.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"project-tree.js","sourceRoot":"","sources":["../../../../../src/bridges/user/web/frontend/project-tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unit tests for port-discovery.ts — sequential port probing.
|
|
3
3
|
*/
|
|
4
|
-
import { describe, it } from "
|
|
5
|
-
import assert from "node:assert/strict";
|
|
4
|
+
import { describe, it, expect } from "vitest";
|
|
6
5
|
import * as http from "node:http";
|
|
7
6
|
import { findFreePort } from "../port-discovery.js";
|
|
8
7
|
/** Create a server that blocks a specific port. Returns a cleanup function. */
|
|
@@ -23,15 +22,15 @@ describe("findFreePort", () => {
|
|
|
23
22
|
it("returns the base port when it is available", async () => {
|
|
24
23
|
// Use a high port that's very unlikely to be in use
|
|
25
24
|
const port = await findFreePort(49000);
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
expect(typeof port).toBe("number");
|
|
26
|
+
expect(port).toBe(49000);
|
|
28
27
|
});
|
|
29
28
|
it("walks to the next port when the base is taken", async () => {
|
|
30
29
|
const unblock = await blockPort(49100);
|
|
31
30
|
try {
|
|
32
31
|
const port = await findFreePort(49100);
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
expect(typeof port).toBe("number");
|
|
33
|
+
expect(port).toBe(49101);
|
|
35
34
|
}
|
|
36
35
|
finally {
|
|
37
36
|
await unblock();
|
|
@@ -43,8 +42,8 @@ describe("findFreePort", () => {
|
|
|
43
42
|
const unblock3 = await blockPort(49202);
|
|
44
43
|
try {
|
|
45
44
|
const port = await findFreePort(49200);
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
expect(typeof port).toBe("number");
|
|
46
|
+
expect(port).toBe(49203);
|
|
48
47
|
}
|
|
49
48
|
finally {
|
|
50
49
|
await unblock1();
|
|
@@ -60,7 +59,7 @@ describe("findFreePort", () => {
|
|
|
60
59
|
}
|
|
61
60
|
try {
|
|
62
61
|
const port = await findFreePort(49300, 3);
|
|
63
|
-
|
|
62
|
+
expect(port).toBe(undefined);
|
|
64
63
|
}
|
|
65
64
|
finally {
|
|
66
65
|
for (const unblock of blockers) {
|
|
@@ -74,8 +73,8 @@ describe("findFreePort", () => {
|
|
|
74
73
|
const unblock2 = await blockPort(49401);
|
|
75
74
|
try {
|
|
76
75
|
const port = await findFreePort(49400, 5);
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
expect(typeof port).toBe("number");
|
|
77
|
+
expect(port).toBe(49402);
|
|
79
78
|
}
|
|
80
79
|
finally {
|
|
81
80
|
await unblock1();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port-discovery.unit.test.js","sourceRoot":"","sources":["../../../../../src/bridges/user/web/test/port-discovery.unit.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"port-discovery.unit.test.js","sourceRoot":"","sources":["../../../../../src/bridges/user/web/test/port-discovery.unit.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Tests the server layer without a browser, using raw HTTP and WS clients.
|
|
5
5
|
*/
|
|
6
|
-
import { describe, it } from "
|
|
7
|
-
import assert from "node:assert/strict";
|
|
6
|
+
import { describe, it, expect } from "vitest";
|
|
8
7
|
import http from "node:http";
|
|
9
8
|
import { createWebServer } from "../server.js";
|
|
10
9
|
import WS from "ws";
|
|
@@ -93,8 +92,8 @@ describe("Web server integration", () => {
|
|
|
93
92
|
const { port, cleanup } = await setup();
|
|
94
93
|
try {
|
|
95
94
|
const { status, body } = await fetchJson(port, "/");
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
expect(status).toBe(200);
|
|
96
|
+
expect(typeof body === "string" && body.includes("Agent Comms"), "HTML should contain 'Agent Comms'").toBeTruthy();
|
|
98
97
|
}
|
|
99
98
|
finally {
|
|
100
99
|
await cleanup();
|
|
@@ -104,8 +103,8 @@ describe("Web server integration", () => {
|
|
|
104
103
|
const { port, cleanup } = await setup();
|
|
105
104
|
try {
|
|
106
105
|
const { status, body } = await fetchJson(port, "/api/agents");
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
expect(status).toBe(200);
|
|
107
|
+
expect(Array.isArray(body)).toBeTruthy();
|
|
109
108
|
}
|
|
110
109
|
finally {
|
|
111
110
|
await cleanup();
|
|
@@ -115,8 +114,8 @@ describe("Web server integration", () => {
|
|
|
115
114
|
const { port, cleanup } = await setup();
|
|
116
115
|
try {
|
|
117
116
|
const { status, body } = await fetchJson(port, "/api/rooms");
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
expect(status).toBe(200);
|
|
118
|
+
expect(Array.isArray(body)).toBeTruthy();
|
|
120
119
|
}
|
|
121
120
|
finally {
|
|
122
121
|
await cleanup();
|
|
@@ -130,8 +129,8 @@ describe("Web server integration", () => {
|
|
|
130
129
|
name: "integration-test-room",
|
|
131
130
|
type: "public",
|
|
132
131
|
});
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
expect(status).toBe(200);
|
|
133
|
+
expect(typeof body === "object" && body !== null && "content" in body, "should return a result object").toBeTruthy();
|
|
135
134
|
}
|
|
136
135
|
finally {
|
|
137
136
|
await cleanup();
|
|
@@ -165,9 +164,9 @@ describe("Web server integration", () => {
|
|
|
165
164
|
});
|
|
166
165
|
ws.on("error", reject);
|
|
167
166
|
});
|
|
168
|
-
|
|
167
|
+
expect(typeof frame === "object" && frame !== null && "type" in frame, "should receive a JSON frame").toBeTruthy();
|
|
169
168
|
const typed = frame;
|
|
170
|
-
|
|
169
|
+
expect(typed.type).toBe("state");
|
|
171
170
|
}
|
|
172
171
|
finally {
|
|
173
172
|
await cleanup();
|
|
@@ -177,7 +176,7 @@ describe("Web server integration", () => {
|
|
|
177
176
|
const { port, cleanup } = await setup();
|
|
178
177
|
try {
|
|
179
178
|
const { status } = await fetchJson(port, "/nonexistent");
|
|
180
|
-
|
|
179
|
+
expect(status).toBe(404);
|
|
181
180
|
}
|
|
182
181
|
finally {
|
|
183
182
|
await cleanup();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-server.integration.test.js","sourceRoot":"","sources":["../../../../../src/bridges/user/web/test/web-server.integration.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"web-server.integration.test.js","sourceRoot":"","sources":["../../../../../src/bridges/user/web/test/web-server.integration.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAwB,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,IAAI,MAAmC,CAAC;AAExC,KAAK,UAAU,KAAK;IAIlB,MAAM,GAAG,MAAM,eAAe,CAAC,CAAC,CAAC,CAAC;IAElC,+CAA+C;IAC/C,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,IAAI,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;YAC7B,OAAO,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;gBACnB,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;gBACtB,MAAM,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;gBACnC,MAAM,GAAG,SAAS,CAAC;YACrB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAChB,IAAY,EACZ,IAAY;IAEZ,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CACtB,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EACpD,CAAC,GAAG,EAAE,EAAE;YACN,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;gBAC/B,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC3B,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,IAAI,IAAa,CAAC;gBAClB,IAAI,CAAC;oBACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC1B,CAAC;gBAAC,MAAM,CAAC;oBACP,IAAI,GAAG,IAAI,CAAC;gBACd,CAAC;gBACD,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,UAAU,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YACjD,CAAC,CAAC,CAAC;QACL,CAAC,CACF,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACxB,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,UAAU,CACjB,IAAY,EACZ,MAA8B;IAE9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CACtB;YACE,QAAQ,EAAE,WAAW;YACrB,IAAI;YACJ,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;aACtC;SACF,EACD,CAAC,GAAG,EAAE,EAAE;YACN,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;gBAC/B,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC3B,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,IAAI,MAAe,CAAC;gBACpB,IAAI,CAAC;oBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC5B,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,GAAG,IAAI,CAAC;gBAChB,CAAC;gBACD,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,UAAU,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YACzD,CAAC,CAAC,CAAC;QACL,CAAC,CACF,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACxB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChB,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,KAAK,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACpD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,MAAM,CACJ,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EACxD,mCAAmC,CACpC,CAAC,UAAU,EAAE,CAAC;QACjB,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,KAAK,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;YAC9D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;QAC3C,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,KAAK,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;YAC7D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;QAC3C,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,KAAK,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE;gBAC9C,MAAM,EAAE,aAAa;gBACrB,IAAI,EAAE,uBAAuB;gBAC7B,IAAI,EAAE,QAAQ;aACf,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,MAAM,CACJ,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,SAAS,IAAI,IAAI,EAC9D,+BAA+B,CAChC,CAAC,UAAU,EAAE,CAAC;QACjB,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,KAAK,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC1C,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,kBAAkB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACpD,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;oBACjB,EAAE,CAAC,KAAK,EAAE,CAAC;oBACX,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;gBACH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACzB,CAAC,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,KAAK,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC3D,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,kBAAkB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACpD,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAa,EAAE,EAAE;oBACjC,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;oBACpD,OAAO,CAAC,MAAM,CAAC,CAAC;oBAChB,EAAE,CAAC,KAAK,EAAE,CAAC;gBACb,CAAC,CAAC,CAAC;gBACH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACzB,CAAC,CAAC,CAAC;YACH,MAAM,CACJ,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,EAC9D,6BAA6B,CAC9B,CAAC,UAAU,EAAE,CAAC;YACf,MAAM,KAAK,GAAG,KAAyB,CAAC;YACxC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,KAAK,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;YACzD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unit tests for bridge.ts — formatDeliveryEvent.
|
|
3
3
|
*/
|
|
4
|
-
import { describe, it } from "
|
|
5
|
-
import assert from "node:assert/strict";
|
|
4
|
+
import { describe, it, expect } from "vitest";
|
|
6
5
|
import { formatDeliveryEvent, isActionableEvent } from "../bridge.js";
|
|
7
6
|
describe("formatDeliveryEvent", () => {
|
|
8
7
|
it("formats name_changed event", () => {
|
|
@@ -13,7 +12,7 @@ describe("formatDeliveryEvent", () => {
|
|
|
13
12
|
newName: "Bob",
|
|
14
13
|
};
|
|
15
14
|
const result = formatDeliveryEvent(event);
|
|
16
|
-
|
|
15
|
+
expect(result).toBe("Alice is now known as Bob");
|
|
17
16
|
});
|
|
18
17
|
it("formats room_message", () => {
|
|
19
18
|
const event = {
|
|
@@ -28,7 +27,7 @@ describe("formatDeliveryEvent", () => {
|
|
|
28
27
|
},
|
|
29
28
|
};
|
|
30
29
|
const result = formatDeliveryEvent(event);
|
|
31
|
-
|
|
30
|
+
expect(result).toBe("[r1] a1: hello");
|
|
32
31
|
});
|
|
33
32
|
it("formats member_status", () => {
|
|
34
33
|
const event = {
|
|
@@ -38,7 +37,7 @@ describe("formatDeliveryEvent", () => {
|
|
|
38
37
|
status: "busy",
|
|
39
38
|
};
|
|
40
39
|
const result = formatDeliveryEvent(event);
|
|
41
|
-
|
|
40
|
+
expect(result).toBe("a1 is now busy in r1");
|
|
42
41
|
});
|
|
43
42
|
});
|
|
44
43
|
describe("isActionableEvent", () => {
|
|
@@ -54,7 +53,7 @@ describe("isActionableEvent", () => {
|
|
|
54
53
|
readBy: [],
|
|
55
54
|
},
|
|
56
55
|
};
|
|
57
|
-
|
|
56
|
+
expect(isActionableEvent(event)).toBe(true);
|
|
58
57
|
});
|
|
59
58
|
it("classifies dm as actionable", () => {
|
|
60
59
|
const event = {
|
|
@@ -68,7 +67,7 @@ describe("isActionableEvent", () => {
|
|
|
68
67
|
readBy: [],
|
|
69
68
|
},
|
|
70
69
|
};
|
|
71
|
-
|
|
70
|
+
expect(isActionableEvent(event)).toBe(true);
|
|
72
71
|
});
|
|
73
72
|
it("classifies room_invite as actionable", () => {
|
|
74
73
|
const event = {
|
|
@@ -79,7 +78,7 @@ describe("isActionableEvent", () => {
|
|
|
79
78
|
fromName: "Alice",
|
|
80
79
|
fromCwd: "/home",
|
|
81
80
|
};
|
|
82
|
-
|
|
81
|
+
expect(isActionableEvent(event)).toBe(true);
|
|
83
82
|
});
|
|
84
83
|
it("classifies member_joined as informational", () => {
|
|
85
84
|
const event = {
|
|
@@ -87,7 +86,7 @@ describe("isActionableEvent", () => {
|
|
|
87
86
|
room: "r1",
|
|
88
87
|
agent: "a1",
|
|
89
88
|
};
|
|
90
|
-
|
|
89
|
+
expect(isActionableEvent(event)).toBe(false);
|
|
91
90
|
});
|
|
92
91
|
it("classifies member_status as informational", () => {
|
|
93
92
|
const event = {
|
|
@@ -96,7 +95,7 @@ describe("isActionableEvent", () => {
|
|
|
96
95
|
agent: "a1",
|
|
97
96
|
status: "offline",
|
|
98
97
|
};
|
|
99
|
-
|
|
98
|
+
expect(isActionableEvent(event)).toBe(false);
|
|
100
99
|
});
|
|
101
100
|
it("classifies name_changed as informational", () => {
|
|
102
101
|
const event = {
|
|
@@ -105,7 +104,7 @@ describe("isActionableEvent", () => {
|
|
|
105
104
|
oldName: "Alice",
|
|
106
105
|
newName: "Bob",
|
|
107
106
|
};
|
|
108
|
-
|
|
107
|
+
expect(isActionableEvent(event)).toBe(false);
|
|
109
108
|
});
|
|
110
109
|
it("classifies delivery_status as informational", () => {
|
|
111
110
|
const event = {
|
|
@@ -114,7 +113,7 @@ describe("isActionableEvent", () => {
|
|
|
114
113
|
agent: "a1",
|
|
115
114
|
status: "delivered",
|
|
116
115
|
};
|
|
117
|
-
|
|
116
|
+
expect(isActionableEvent(event)).toBe(false);
|
|
118
117
|
});
|
|
119
118
|
});
|
|
120
119
|
//# sourceMappingURL=bridge.unit.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.unit.test.js","sourceRoot":"","sources":["../../../src/core/test/bridge.unit.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"bridge.unit.test.js","sourceRoot":"","sources":["../../../src/core/test/bridge.unit.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,70 +1,69 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unit tests for identity.ts — cryptographic identity generation.
|
|
3
3
|
*/
|
|
4
|
-
import { describe, it } from "
|
|
5
|
-
import assert from "node:assert/strict";
|
|
4
|
+
import { describe, it, expect } from "vitest";
|
|
6
5
|
import { X509Certificate } from "node:crypto";
|
|
7
6
|
import { generateIdentity, getCertificateFingerprint } from "../identity.js";
|
|
8
7
|
describe("generateIdentity", () => {
|
|
9
8
|
it("returns a valid PeerIdentity with all required fields", () => {
|
|
10
9
|
const identity = generateIdentity();
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
expect(identity.privateKey, "private key should be present").toBeTruthy();
|
|
11
|
+
expect(identity.certificate, "certificate should be present").toBeTruthy();
|
|
12
|
+
expect(identity.fingerprint, "fingerprint should be present").toBeTruthy();
|
|
14
13
|
});
|
|
15
14
|
it("produces a valid PEM-encoded private key", () => {
|
|
16
15
|
const { privateKey } = generateIdentity();
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
expect(privateKey, "private key should start with PEM header").toMatch(/^-----BEGIN PRIVATE KEY-----/);
|
|
17
|
+
expect(privateKey, "private key should end with PEM footer").toMatch(/-----END PRIVATE KEY-----\n?$/);
|
|
19
18
|
});
|
|
20
19
|
it("produces a valid PEM-encoded certificate", () => {
|
|
21
20
|
const { certificate } = generateIdentity();
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
expect(certificate, "certificate should start with PEM header").toMatch(/^-----BEGIN CERTIFICATE-----/);
|
|
22
|
+
expect(certificate, "certificate should end with PEM footer").toMatch(/-----END CERTIFICATE-----\n?$/);
|
|
24
23
|
});
|
|
25
24
|
it("produces a fingerprint that is a 95-character SHA-256 hex string with colons", () => {
|
|
26
25
|
const { fingerprint } = generateIdentity();
|
|
27
26
|
// SHA-256 = 32 bytes = 64 hex chars + 31 colons = 95 chars
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
expect(fingerprint.length).toBe(95);
|
|
28
|
+
expect(fingerprint, "fingerprint should be hex pairs separated by colons").toMatch(/^[0-9A-F]{2}(:[0-9A-F]{2}){31}$/);
|
|
30
29
|
});
|
|
31
30
|
it("produces a fingerprint that matches Node's own X509Certificate.fingerprint256", () => {
|
|
32
31
|
const { certificate, fingerprint } = generateIdentity();
|
|
33
32
|
const x509 = new X509Certificate(certificate);
|
|
34
|
-
|
|
33
|
+
expect(fingerprint).toBe(x509.fingerprint256);
|
|
35
34
|
});
|
|
36
35
|
it("produces a certificate that is valid and self-signed", () => {
|
|
37
36
|
const { certificate } = generateIdentity();
|
|
38
37
|
const x509 = new X509Certificate(certificate);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
expect(x509.subject).toBe("CN=agent-comms");
|
|
39
|
+
expect(x509.issuer).toBe("CN=agent-comms");
|
|
40
|
+
expect(x509.verify(x509.publicKey), "certificate should verify against its own public key").toBeTruthy();
|
|
42
41
|
});
|
|
43
42
|
it("includes localhost and 127.0.0.1 in Subject Alternative Names", () => {
|
|
44
43
|
const { certificate } = generateIdentity();
|
|
45
44
|
const x509 = new X509Certificate(certificate);
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
expect(x509.checkHost("localhost"), "should match DNS:localhost").toBeTruthy();
|
|
46
|
+
expect(x509.checkIP("127.0.0.1"), "should match IP:127.0.0.1").toBeTruthy();
|
|
48
47
|
});
|
|
49
48
|
it("produces different fingerprints on successive calls (different keypairs)", () => {
|
|
50
49
|
const a = generateIdentity();
|
|
51
50
|
const b = generateIdentity();
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
expect(a.fingerprint).not.toBe(b.fingerprint);
|
|
52
|
+
expect(a.privateKey).not.toBe(b.privateKey);
|
|
53
|
+
expect(a.certificate).not.toBe(b.certificate);
|
|
55
54
|
});
|
|
56
55
|
});
|
|
57
56
|
describe("getCertificateFingerprint", () => {
|
|
58
57
|
it("is deterministic — same cert always produces same fingerprint", () => {
|
|
59
58
|
const { certificate, fingerprint } = generateIdentity();
|
|
60
59
|
const recomputed = getCertificateFingerprint(certificate);
|
|
61
|
-
|
|
60
|
+
expect(recomputed).toBe(fingerprint);
|
|
62
61
|
});
|
|
63
62
|
it("produces the same result when called multiple times", () => {
|
|
64
63
|
const { certificate } = generateIdentity();
|
|
65
64
|
const first = getCertificateFingerprint(certificate);
|
|
66
65
|
const second = getCertificateFingerprint(certificate);
|
|
67
|
-
|
|
66
|
+
expect(first).toBe(second);
|
|
68
67
|
});
|
|
69
68
|
});
|
|
70
69
|
//# sourceMappingURL=identity.unit.test.js.map
|