appoiint 4.1.2 → 4.3.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/api.js CHANGED
@@ -1 +1 @@
1
- const https=require("https"),http=require("http"),BASE="/saas/api/v1/sdk";function request(e,t,s,n,a){return new Promise((i,r)=>{const o=new URL(n,e),p="https:"===o.protocol,u=p?https:http,m={"Content-Type":"application/json"};t&&(m.Authorization=`Bearer ${t}`);const c=a?JSON.stringify(a):null;c&&(m["Content-Length"]=Buffer.byteLength(c));const E=u.request({hostname:o.hostname,port:o.port||(p?443:80),path:o.pathname+o.search,method:s,headers:m,timeout:3e4},e=>{let t="";e.on("data",e=>t+=e),e.on("end",()=>{try{const s=JSON.parse(t);e.statusCode>=400?r(new Error(s.error||s.message||`HTTP ${e.statusCode}`)):i(s.data||s)}catch{e.statusCode>=400?r(new Error(`HTTP ${e.statusCode}: ${t.slice(0,200)}`)):i(t)}})});E.on("error",r),E.on("timeout",()=>{E.destroy(),r(new Error("Request timeout (30s)"))}),c&&E.write(c),E.end()})}function api(e){const{baseUrl:t,apiKey:s}=e,n=(e,n,a)=>request(t,s,e,n,a);return{signup:e=>request(t,"","POST",`${BASE}/tai/agent/signup`,e),activate:e=>request(t,"","POST",`${BASE}/tai/agent/activate`,e),createRoom:e=>n("POST",`${BASE}/tai/agent/rooms`,e),listRooms:()=>n("GET",`${BASE}/tai/agent/rooms`),roomStatus:e=>n("GET",`${BASE}/tai/agent/rooms/${e}`),endRoom:e=>n("DELETE",`${BASE}/tai/agent/rooms/${e}`),invite:(e,t)=>n("POST",`${BASE}/tai/agent/rooms/${e}/invite`,t),transcript:(e,t)=>n("GET",`${BASE}/tai/agent/rooms/${e}/transcript?format=${t||"json"}`),joinMeeting:e=>n("POST",`${BASE}/tai/agent/meeting/join`,e),leaveMeeting:e=>n("POST",`${BASE}/tai/agent/meeting/leave`,e),events:()=>n("GET",`${BASE}/scheduling/event-types/public`),slots:(e,t,s)=>n("GET",`${BASE}/availability/slots/publicinverse?email=${e}&date=${t}&timezone=${s||"UTC"}`),book:e=>n("POST",`${BASE}/scheduling/bookings`,e),synthesize:e=>n("POST",`${BASE}/tts/synthesize`,e),voices:()=>n("GET",`${BASE}/tts/voices`),status:()=>request(t,"","GET",`${BASE.replace("/sdk","/public")}/tai/status`),sttStatus:()=>n("GET",`${BASE}/stt/status`),adminUsers:()=>n("GET","/superadmin/api/users"),adminUserCreate:e=>n("POST","/superadmin/api/users",e),adminUserReset:(e,t)=>n("POST","/superadmin/api/users/reset-password",{email:e,...t}),adminUserDelete:e=>n("DELETE",`/superadmin/api/users/${encodeURIComponent(e)}`),adminTenants:()=>n("GET","/superadmin/api/tenants"),adminTenantView:e=>n("GET",`/superadmin/api/tenants/${e}`),adminTenantCreate:e=>n("POST","/superadmin/api/tenants",e),adminTenantPlan:(e,t)=>n("POST",`/superadmin/api/tenants/${e}/plan`,{plan:t}),adminTenantVerify:e=>n("POST",`/superadmin/api/tenants/${e}/verify`),adminTenantSuspend:e=>n("POST",`/superadmin/api/tenants/${e}/suspend`),adminTenantActivate:e=>n("POST",`/superadmin/api/tenants/${e}/activate`),adminTenantDelete:e=>n("DELETE",`/superadmin/api/tenants/${e}`),adminBilling:()=>n("GET","/superadmin/api/revenue"),adminDiscount:e=>n("POST","/superadmin/api/discount",e),platformStats:()=>n("GET","/superadmin/api/stats"),funnel:()=>n("GET","/superadmin/api/funnel"),signups:e=>n("GET","/superadmin/api/signups"+(e?"?days="+e:"")),revenue:()=>n("GET","/superadmin/api/revenue"),tickets:e=>n("GET","/superadmin/api/tickets"+(e?"?status="+e:"")),ticketShow:e=>n("GET",`/superadmin/api/tickets/${e}`),ticketReply:(e,t)=>n("POST",`/superadmin/api/tickets/${e}/reply`,{message:t}),ticketClose:e=>n("POST",`/superadmin/api/tickets/${e}/close`),audit:e=>n("GET","/superadmin/api/audit"+(e?"?"+e:"")),auditExport:e=>n("GET",`/superadmin/api/audit/export?format=${e||"json"}`),notifications:e=>n("GET","/superadmin/api/notifications"+(e?"?since="+e:"")),costs:()=>n("GET",`${BASE}/costs`),costsByRoom:e=>n("GET",`${BASE}/costs/${e}`),costsPricing:()=>n("GET",`${BASE}/costs/pricing`),costsModels:()=>n("GET",`${BASE}/costs/models`),costsUsers:()=>n("GET",`${BASE}/costs/users`),costsTimeseries:e=>n("GET",`${BASE}/costs/timeseries${e?"?bucket="+e:""}`),channelSend:e=>n("POST",`${BASE}/channels/send`,e),channelInbox:()=>n("GET",`${BASE}/channels/inbox`),channelHistory:(e,t)=>n("GET",`${BASE}/channels/history/${e}${t?"?limit="+t:""}`),channelAck:e=>n("POST",`${BASE}/channels/ack/${e}`),channelAgents:()=>n("GET",`${BASE}/channels/agents`)}}function rawApi(e){return(t,s,n)=>request(e.baseUrl,e.apiKey,t,s,n)}module.exports={api:api,request:request,rawApi:rawApi};
1
+ const https=require("https"),http=require("http"),BASE="/saas/api/v1/sdk";function request(e,t,s,n,a){return new Promise((i,r)=>{const o=new URL(n,e),p="https:"===o.protocol,u=p?https:http,E={"Content-Type":"application/json"};t&&(E.Authorization=`Bearer ${t}`);const m=a?JSON.stringify(a):null;m&&(E["Content-Length"]=Buffer.byteLength(m));const c=u.request({hostname:o.hostname,port:o.port||(p?443:80),path:o.pathname+o.search,method:s,headers:E,timeout:3e4},e=>{let t="";e.on("data",e=>t+=e),e.on("end",()=>{try{const s=JSON.parse(t);e.statusCode>=400?r(new Error(s.error||s.message||`HTTP ${e.statusCode}`)):i(s.data||s)}catch{e.statusCode>=400?r(new Error(`HTTP ${e.statusCode}: ${t.slice(0,200)}`)):i(t)}})});c.on("error",r),c.on("timeout",()=>{c.destroy(),r(new Error("Request timeout (30s)"))}),m&&c.write(m),c.end()})}function api(e){const{baseUrl:t,apiKey:s}=e,n=(e,n,a)=>request(t,s,e,n,a);return{signup:e=>request(t,"","POST",`${BASE}/tai/agent/signup`,e),activate:e=>request(t,"","POST",`${BASE}/tai/agent/activate`,e),createRoom:e=>n("POST",`${BASE}/tai/agent/rooms`,e),listRooms:()=>n("GET",`${BASE}/tai/agent/rooms`),roomStatus:e=>n("GET",`${BASE}/tai/agent/rooms/${e}`),endRoom:e=>n("DELETE",`${BASE}/tai/agent/rooms/${e}`),invite:(e,t)=>n("POST",`${BASE}/tai/agent/rooms/${e}/invite`,t),transcript:(e,t)=>n("GET",`${BASE}/tai/agent/rooms/${e}/transcript?format=${t||"json"}`),joinMeeting:e=>n("POST",`${BASE}/tai/agent/meeting/join`,e),leaveMeeting:e=>n("POST",`${BASE}/tai/agent/meeting/leave`,e),events:()=>n("GET",`${BASE}/scheduling/event-types/public`),slots:(e,t,s)=>n("GET",`${BASE}/availability/slots/publicinverse?email=${e}&date=${t}&timezone=${s||"UTC"}`),book:e=>n("POST",`${BASE}/scheduling/bookings`,e),synthesize:e=>n("POST",`${BASE}/tts/synthesize`,e),voices:()=>n("GET",`${BASE}/tts/voices`),status:()=>request(t,"","GET",`${BASE.replace("/sdk","/public")}/tai/status`),sttStatus:()=>n("GET",`${BASE}/stt/status`),adminUsers:()=>n("GET","/superadmin/api/users"),adminUserCreate:e=>n("POST","/superadmin/api/users",e),adminUserReset:(e,t)=>n("POST","/superadmin/api/users/reset-password",{email:e,...t}),adminUserDelete:e=>n("DELETE",`/superadmin/api/users/${encodeURIComponent(e)}`),adminTenants:()=>n("GET","/superadmin/api/tenants"),adminTenantView:e=>n("GET",`/superadmin/api/tenants/${e}`),adminTenantCreate:e=>n("POST","/superadmin/api/tenants",e),adminTenantPlan:(e,t)=>n("POST",`/superadmin/api/tenants/${e}/plan`,{plan:t}),adminTenantVerify:e=>n("POST",`/superadmin/api/tenants/${e}/verify`),adminTenantSuspend:e=>n("POST",`/superadmin/api/tenants/${e}/suspend`),adminTenantActivate:e=>n("POST",`/superadmin/api/tenants/${e}/activate`),adminTenantDelete:e=>n("DELETE",`/superadmin/api/tenants/${e}`),adminBilling:()=>n("GET","/superadmin/api/revenue"),adminDiscount:e=>n("POST","/superadmin/api/discount",e),platformStats:()=>n("GET","/superadmin/api/stats"),funnel:()=>n("GET","/superadmin/api/funnel"),signups:e=>n("GET","/superadmin/api/signups"+(e?"?days="+e:"")),revenue:()=>n("GET","/superadmin/api/revenue"),tickets:e=>n("GET","/superadmin/api/tickets"+(e?"?status="+e:"")),ticketShow:e=>n("GET",`/superadmin/api/tickets/${e}`),ticketReply:(e,t)=>n("POST",`/superadmin/api/tickets/${e}/reply`,{message:t}),ticketClose:e=>n("POST",`/superadmin/api/tickets/${e}/close`),audit:e=>n("GET","/superadmin/api/audit"+(e?"?"+e:"")),auditExport:e=>n("GET",`/superadmin/api/audit/export?format=${e||"json"}`),notifications:e=>n("GET","/superadmin/api/notifications"+(e?"?since="+e:"")),costs:()=>n("GET",`${BASE}/costs`),costsByRoom:e=>n("GET",`${BASE}/costs/${e}`),costsPricing:()=>n("GET",`${BASE}/costs/pricing`),costsModels:()=>n("GET",`${BASE}/costs/models`),costsUsers:()=>n("GET",`${BASE}/costs/users`),costsTimeseries:e=>n("GET",`${BASE}/costs/timeseries${e?"?bucket="+e:""}`),agentCreate:e=>n("POST",`${BASE}/tai/agent/create`,e),agentList:()=>n("GET",`${BASE}/tai/agent/list`),agentRevoke:e=>n("DELETE",`${BASE}/tai/agent/${encodeURIComponent(e)}`),channelSend:e=>n("POST",`${BASE}/channels/send`,e),channelInbox:()=>n("GET",`${BASE}/channels/inbox`),channelHistory:(e,t)=>n("GET",`${BASE}/channels/history/${e}${t?"?limit="+t:""}`),channelAck:e=>n("POST",`${BASE}/channels/ack/${e}`),channelAgents:()=>n("GET",`${BASE}/channels/agents`)}}function rawApi(e){return(t,s,n)=>request(e.baseUrl,e.apiKey,t,s,n)}module.exports={api:api,request:request,rawApi:rawApi};
@@ -0,0 +1 @@
1
+ const{api:api}=require("../api"),{saveConfig:saveConfig,hasFlag:hasFlag,getFlag:getFlag,positionalArgs:positionalArgs}=require("../config"),fmt=require("../format");function accountClient(e){return api({baseUrl:e.baseUrl,apiKey:e.accountApiKey||e.apiKey})}async function run(e,t,a){const n=positionalArgs(t),o=n[0],s=accountClient(e);if("create"===o){const o=(n[1]||"").replace(/^@/,"").toLowerCase();o||(fmt.err("Usage: apo agent create HANDLE [--type TYPE]"),process.exit(1));const i=await s.agentCreate({handle:o,agentType:getFlag(t,"type")||"generic"}),g=i.data||i;if(a)return console.log(JSON.stringify(i,null,2));const r={...e.agents||{}};return r[g.handle]={agentKey:g.agentKey,agentId:g.agentId,keyId:g.keyId},saveConfig({agents:r},!hasFlag(t,"global")),fmt.ok(`Agent @${g.handle} created`),g.quota&&console.log(` quota: ${g.quota.used}/${g.quota.limit??"∞"} (${g.quota.plan} plan)`),void console.log(` key saved to config — activate with: apo agent use ${g.handle}`)}if("list"===o){const t=await s.agentList();if(a)return console.log(JSON.stringify(t,null,2));const n=(t.data||t).agents||[];return n.length?(console.log(`\nAgents (${n.length})\n`),void n.forEach(t=>{const a=t.handle===e.activeAgent?" ← active":"",n=(e.agents||{})[t.handle]?"":" (no local key)";console.log(` @${t.handle} ${t.status} ${t.agentType||""}${n}${a}`)})):fmt.info("No agents yet. Create one: apo agent create ci-bot")}if("use"===o){if(hasFlag(t,"account"))return saveConfig({activeAgent:null},!hasFlag(t,"global")),void fmt.ok("Switched to account identity.");const a=(n[1]||"").replace(/^@/,"").toLowerCase();return a||(fmt.err("Usage: apo agent use HANDLE | apo agent use --account"),process.exit(1)),(e.agents||{})[a]||(fmt.err(`No local key for @${a}. Create it first: apo agent create ${a}`),process.exit(1)),saveConfig({activeAgent:a},!hasFlag(t,"global")),void fmt.ok(`Now acting as @${a}. Channel messages send/receive as this agent.`)}if("whoami"===o)return a?console.log(JSON.stringify({activeAgent:e.activeAgent,source:e.source,userId:e.userId},null,2)):void(e.activeAgent?fmt.ok(`Acting as agent @${e.activeAgent} (key source: ${e.source})`):fmt.ok(`Acting as account${e.userId?` ${e.userId}`:""} (key source: ${e.source})`));if("revoke"===o){const o=(n[1]||"").replace(/^@/,"").toLowerCase();o||(fmt.err("Usage: apo agent revoke HANDLE"),process.exit(1));const i=await s.agentRevoke(o);if(a)return console.log(JSON.stringify(i,null,2));const g={...e.agents||{}};delete g[o];const r={agents:g};return e.activeAgent===o&&(r.activeAgent=null),saveConfig(r,!hasFlag(t,"global")),void fmt.ok(`Agent @${o} revoked (takes effect within 60s).`)}fmt.err("Usage: apo agent [create|list|use|whoami|revoke]"),process.exit(1)}module.exports={run:run};
@@ -0,0 +1 @@
1
+ const{getFlag:getFlag}=require("../config"),fmt=require("../format"),{MeetingSession:MeetingSession}=require("../meetingSession");async function join(e,o,t,n){const s=o[0];s||(fmt.err('Usage: apo join ROOM_ID [--name N] [--role R] [--say "msg"]'),process.exit(1));const a=getFlag(o,"name")||"Claude Code",r=getFlag(o,"role")||"assistant",i=getFlag(o,"say"),l=new MeetingSession({baseUrl:n.baseUrl,roomId:s,agentName:a,agentRole:r});let g;try{g=await l.join()}catch(e){fmt.err(`Join failed: ${e.message}`),process.exit(1)}if(t&&i){const e=l.sendChat(i);return l.leave(),console.log(JSON.stringify({...g,sent:e},null,2))}if(t||(fmt.ok(`Joined ${s} as ${fmt.bold(a)} (${r})`),g.peerCount?console.log(fmt.dim(` ${g.peerCount} participant(s): ${g.peers.map(e=>e.name).join(", ")}`)):g.note&&console.log(fmt.dim(` ${g.note}`))),i)return l.sendChat(i),t||fmt.info(`Sent: "${i}"`),void l.leave();if(t)return l.leave(),console.log(JSON.stringify(g,null,2));console.log(fmt.dim(" Listening for transcript + chat. Press Ctrl-C to leave.\n"));const c=setInterval(()=>{l.getTranscripts().forEach(e=>console.log(`${fmt.bold(e.speaker||"?")}: ${e.text}`)),l.getChats().forEach(e=>console.log(`${fmt.green("💬 "+(e.from||"?"))}: ${e.message}`))},1500),m=()=>{clearInterval(c),l.leave(),fmt.ok(`Left ${s}`),process.exit(0)};process.on("SIGINT",m),process.on("SIGTERM",m),await new Promise(()=>{})}module.exports={join:join};
package/dist/config.js CHANGED
@@ -1 +1 @@
1
- const fs=require("fs"),path=require("path"),os=require("os"),LOCAL_DIR=".appoiint",GLOBAL_DIR=path.join(os.homedir(),".appoiint"),CONFIG_FILE="config.json";function hasFlag(n,e){return n.includes(`--${e}`)||n.includes(`-${e[0]}`)}function getFlag(n,e){const i=n.indexOf(`--${e}`);if(-1!==i&&n[i+1])return n[i+1];const t=n.indexOf(`-${e[0]}`);return-1!==t&&n[t+1]?n[t+1]:null}function readConfigFile(n){try{const e=path.join(n,CONFIG_FILE);if(fs.existsSync(e))return JSON.parse(fs.readFileSync(e,"utf8"))}catch{}return{}}function loadConfig(n){const e=getFlag(n,"key")||getFlag(n,"k"),i=process.env.APO_API_KEY||process.env.APPOIINT_API_KEY,t=readConfigFile(LOCAL_DIR),s=readConfigFile(GLOBAL_DIR),o={...s,...t};return{apiKey:e||i||o.apiKey||null,userId:o.userId||null,paymentIntentId:o.paymentIntentId||null,baseUrl:o.baseUrl||process.env.APPOIINT_BASE_URL||"https://appoiint.com",source:e?"flag":i?"env":t.apiKey?"local":s.apiKey?"global":"none"}}function saveConfig(n,e=!0){const i=e?LOCAL_DIR:GLOBAL_DIR;fs.existsSync(i)||fs.mkdirSync(i,{recursive:!0});const t=path.join(i,CONFIG_FILE),s={...readConfigFile(i),...n};return fs.writeFileSync(t,JSON.stringify(s,null,2)),t}function clearConfig(n=!0){const e=n?LOCAL_DIR:GLOBAL_DIR,i=path.join(e,CONFIG_FILE);fs.existsSync(i)&&fs.unlinkSync(i)}function positionalArgs(n){const e=[];for(let i=0;i<n.length;i++)n[i].startsWith("--")||n[i].startsWith("-")?i++:e.push(n[i]);return e}module.exports={loadConfig:loadConfig,saveConfig:saveConfig,clearConfig:clearConfig,hasFlag:hasFlag,getFlag:getFlag,positionalArgs:positionalArgs};
1
+ const fs=require("fs"),path=require("path"),os=require("os"),LOCAL_DIR=".appoiint",GLOBAL_DIR=path.join(os.homedir(),".appoiint"),CONFIG_FILE="config.json";function hasFlag(n,e){return n.includes(`--${e}`)||n.includes(`-${e[0]}`)}function getFlag(n,e){const t=n.indexOf(`--${e}`);if(-1!==t&&n[t+1])return n[t+1];const i=n.indexOf(`-${e[0]}`);return-1!==i&&n[i+1]?n[i+1]:null}function readConfigFile(n){try{const e=path.join(n,CONFIG_FILE);if(fs.existsSync(e))return JSON.parse(fs.readFileSync(e,"utf8"))}catch{}return{}}function getLongFlag(n,e){const t=n.indexOf(`--${e}`);return-1!==t&&n[t+1]?n[t+1]:null}function loadConfig(n){const e=getFlag(n,"key")||getFlag(n,"k"),t=process.env.APO_API_KEY||process.env.APPOIINT_API_KEY,i=readConfigFile(LOCAL_DIR),o=readConfigFile(GLOBAL_DIR),s={...o,...i},a=s.agents||{},l=getLongFlag(n,"agent")||process.env.APO_AGENT||s.activeAgent||null,r=l?String(l).replace(/^@/,""):null,g=r&&a[r]?a[r]:null;return{apiKey:e||t||g&&g.agentKey||s.apiKey||null,accountApiKey:s.apiKey||null,userId:s.userId||null,paymentIntentId:s.paymentIntentId||null,baseUrl:s.baseUrl||process.env.APPOIINT_BASE_URL||"https://appoiint.com",agents:a,activeAgent:g?r:null,source:e?"flag":t?"env":g?`agent:@${r}`:i.apiKey?"local":o.apiKey?"global":"none"}}function saveConfig(n,e=!0){const t=e?LOCAL_DIR:GLOBAL_DIR;fs.existsSync(t)||fs.mkdirSync(t,{recursive:!0});const i=path.join(t,CONFIG_FILE),o={...readConfigFile(t),...n};return fs.writeFileSync(i,JSON.stringify(o,null,2)),i}function clearConfig(n=!0){const e=n?LOCAL_DIR:GLOBAL_DIR,t=path.join(e,CONFIG_FILE);fs.existsSync(t)&&fs.unlinkSync(t)}function positionalArgs(n){const e=[];for(let t=0;t<n.length;t++)n[t].startsWith("--")||n[t].startsWith("-")?t++:e.push(n[t]);return e}module.exports={loadConfig:loadConfig,saveConfig:saveConfig,clearConfig:clearConfig,hasFlag:hasFlag,getFlag:getFlag,positionalArgs:positionalArgs};
package/dist/main.js CHANGED
@@ -1 +1 @@
1
- const{loadConfig:loadConfig,hasFlag:hasFlag,getFlag:getFlag}=require("./config"),{api:api,rawApi:rawApi}=require("./api"),fmt=require("./format"),args=process.argv.slice(2),command=args[0],subArgs=args.slice(1),jsonMode=hasFlag(args,"json"),NO_AUTH=["signup","activate","login","logout","config","help","--help","-h","status","version","--version","-v","mcp-serve","man","renderer","init"],config=loadConfig(args);NO_AUTH.includes(command)||config.apiKey||(fmt.err("No API key. Run: apo signup --email you@co.com --password Pass123!"),fmt.err("Or: apo login --key YOUR_KEY --user YOUR_USERID"),fmt.err("Or set APO_API_KEY environment variable."),process.exit(1));const client=config.apiKey?api(config):null,raw=config.apiKey?rawApi(config):null,HELP='\nAppoiint CLI — Agent-first meeting platform\n\nAuth:\n apo signup --email E --password P Sign up ($1 verification payment)\n apo activate [INTENT_ID] Get API key after $1 payment\n apo login --key KEY [--user USERID] Save API key to config\n apo logout Clear config\n apo config Show active config\n\nRooms:\n apo room "Title" Create meeting room\n apo rooms List active rooms\n apo room-status ROOM_ID Room status + participants\n apo room-end ROOM_ID End meeting\n apo invite ROOM_ID --email E --name N Invite human or agent\n apo transcript ROOM_ID [--format F] Get transcript (json|text|srt)\n\nMeetings:\n apo join ROOM_ID Join room as agent participant\n apo leave ROOM_ID Leave room\n\nScheduling:\n apo book --date D --email E Create booking\n apo events List event types\n apo slots --email E --date D Check availability\n\nTTS:\n apo tts "text" --voice cfo Synthesize speech\n apo voices List available voices\n\nAdmin:\n apo admin tenants List all tenants\n apo admin tenant-view SLUG Full tenant detail\n apo admin tenant-create SLUG Create tenant\n apo admin tenant-suspend SLUG Suspend tenant\n apo admin tenant-activate SLUG Reactivate tenant\n apo admin tenant-delete SLUG Delete tenant\n apo admin users List all users\n apo admin user-reset EMAIL -p PASS Reset user password\n apo admin billing MRR, ARR, revenue\n apo admin costs Platform cost summary (STT/TTS/LLM)\n apo admin costs ROOM_ID Per-meeting cost breakdown\n apo admin models Spend by provider/model + tokens\n apo admin usage Spend by user\n apo admin timeseries [--bucket day] Spend over time (hour|day)\n apo admin pricing Current provider pricing table\n\nAnalytics:\n apo stats Platform overview\n apo revenue Revenue breakdown\n apo funnel Signup funnel\n apo signups [--days 7] Recent signups\n\nSupport:\n apo tickets [--status open] List support tickets\n apo ticket show NUMBER Ticket detail\n apo ticket reply NUMBER MESSAGE Reply to ticket\n apo ticket close NUMBER Close ticket\n\nAudit:\n apo audit [--action X] [--limit N] Activity trail\n apo audit export [--format csv] Export audit log\n\nHelpdesk (+$4.99/mo):\n apo helpdesk tickets List tickets\n apo helpdesk ticket show ID Ticket detail + messages\n apo helpdesk ticket create "Subject" Create ticket\n apo helpdesk ticket reply ID "msg" Reply to ticket\n apo helpdesk ticket close ID Close ticket\n apo helpdesk ticket assign ID --agent X Assign ticket\n apo helpdesk kb List KB articles\n apo helpdesk stats Helpdesk statistics\n\nCRM (+$4.99/mo):\n apo crm leads List leads\n apo crm lead show ID Lead detail\n apo crm lead create "Name" --email X Create lead\n apo crm lead convert ID Convert lead → opportunity\n apo crm opps List opportunities\n apo crm opp show ID Opportunity detail\n apo crm opp create "Deal" --value X Create opportunity\n apo crm pipelines List pipelines\n apo crm stats CRM statistics\n\nChannels (agent-to-agent):\n apo channel send @AGENT "msg" Send 1:1 message to agent\n apo channel inbox Unread messages\n apo channel history @AGENT Conversation history\n apo channel agents List agent contacts\n\nDiagnostics:\n apo diagnose ROOM_ID Full room diagnostic (peers, events, relay)\n\nManual:\n apo man renderer Chat bubble renderer capabilities + formats\n apo renderer Same as above (shorthand)\n\nOptions:\n --json Output JSON (for agents)\n --key KEY Override API key\n --help Show this help\n\nhttps://appoiint.com/docs/quickstart.html\n';async function run(){switch(command){case"signup":return require("./commands/auth").signup(subArgs,config.baseUrl);case"activate":return require("./commands/auth").activate(subArgs,config);case"login":return require("./commands/auth").login(subArgs);case"logout":return require("./commands/auth").logout(subArgs);case"config":return require("./commands/auth").showConfig(config);case"room":return require("./commands/rooms").create(client,subArgs,jsonMode,config);case"rooms":return require("./commands/rooms").list(client,subArgs,jsonMode);case"room-status":return require("./commands/rooms").status(client,subArgs,jsonMode);case"room-end":return require("./commands/rooms").end(client,subArgs,jsonMode);case"invite":return require("./commands/rooms").invite(client,subArgs,jsonMode);case"transcript":return require("./commands/rooms").transcript(client,subArgs,jsonMode);case"join":return subArgs[0]||(fmt.err("Usage: apo join ROOM_ID"),process.exit(1)),client.joinMeeting({roomId:subArgs[0],agentName:"CLI Agent",agentRole:getFlag(subArgs,"role")||"tai-super"}).then(e=>jsonMode?console.log(JSON.stringify(e,null,2)):fmt.ok(`Joined room ${subArgs[0]}`));case"leave":return subArgs[0]||(fmt.err("Usage: apo leave ROOM_ID"),process.exit(1)),client.leaveMeeting({roomId:subArgs[0],agentId:"cli-agent"}).then(e=>jsonMode?console.log(JSON.stringify(e,null,2)):fmt.ok(`Left room ${subArgs[0]}`));case"book":return require("./commands/bookings").book(client,subArgs,jsonMode);case"events":return require("./commands/bookings").events(client,subArgs,jsonMode);case"slots":return require("./commands/bookings").slots(client,subArgs,jsonMode);case"tts":return require("./commands/tts").synthesize(client,subArgs,jsonMode);case"voices":return require("./commands/tts").voices(client,subArgs,jsonMode);case"status":{const e=await api({baseUrl:config.baseUrl,apiKey:""}).status();return jsonMode?console.log(JSON.stringify(e,null,2)):void fmt.ok(`Appoiint ${e.version||"?"} — ${e.available?"online":"offline"}`)}case"version":case"--version":case"-v":return void console.log(require("../package.json").version);case"admin":return require("./commands/admin").run(client,subArgs,jsonMode);case"stats":return require("./commands/stats").run(client,jsonMode);case"funnel":return require("./commands/stats").funnel(client,jsonMode);case"signups":return require("./commands/stats").signups(client,subArgs,jsonMode);case"revenue":return require("./commands/stats").revenue(client,jsonMode);case"tickets":return require("./commands/tickets").list(client,subArgs,jsonMode);case"ticket":const e=subArgs[0];if("show"===e)return require("./commands/tickets").show(client,subArgs.slice(1),jsonMode);if("reply"===e)return require("./commands/tickets").reply(client,subArgs.slice(1),jsonMode);if("close"===e)return require("./commands/tickets").close(client,subArgs.slice(1),jsonMode);fmt.err("Usage: apo ticket [show|reply|close] NUMBER"),process.exit(1);case"audit":return require("./commands/audit").run(client,subArgs,jsonMode);case"helpdesk":return require("./commands/helpdesk").run(client,subArgs,jsonMode,raw);case"crm":return require("./commands/crm").run(client,subArgs,jsonMode,raw);case"channel":return require("./commands/channels").run(client,subArgs,jsonMode);case"diagnose":return require("./commands/diagnose").run(client,subArgs,jsonMode,config);case"init":return require("./commands/init").run(subArgs);case"man":case"renderer":const n="man"===command?subArgs[0]:command;return"renderer"===n?require("./commands/renderer").run(subArgs.slice("man"===command?1:0),jsonMode):void fmt.err("Unknown manual page: "+(n||"(none)")+". Available: renderer");case"mcp-serve":return require("./mcp").serve();case"help":case"--help":case"-h":case void 0:return void console.log(HELP);default:fmt.err(`Unknown command: ${command}`),console.log(HELP),process.exit(1)}}run().catch(e=>{fmt.err(e.message),process.exit(1)});
1
+ const{loadConfig:loadConfig,hasFlag:hasFlag,getFlag:getFlag}=require("./config"),{api:api,rawApi:rawApi}=require("./api"),fmt=require("./format"),args=process.argv.slice(2),command=args[0],subArgs=args.slice(1),jsonMode=hasFlag(args,"json"),NO_AUTH=["signup","activate","login","logout","config","help","--help","-h","status","version","--version","-v","mcp-serve","man","renderer","init"],config=loadConfig(args);NO_AUTH.includes(command)||config.apiKey||(fmt.err("No API key. Run: apo signup --email you@co.com --password Pass123!"),fmt.err("Or: apo login --key YOUR_KEY --user YOUR_USERID"),fmt.err("Or set APO_API_KEY environment variable."),process.exit(1));const client=config.apiKey?api(config):null,raw=config.apiKey?rawApi(config):null,HELP='\nAppoiint CLI — Agent-first meeting platform\n\nAuth:\n apo signup --email E --password P Sign up ($1 verification payment)\n apo activate [INTENT_ID] Get API key after $1 payment\n apo login --key KEY [--user USERID] Save API key to config\n apo logout Clear config\n apo config Show active config\n\nRooms:\n apo room "Title" Create meeting room\n apo rooms List active rooms\n apo room-status ROOM_ID Room status + participants\n apo room-end ROOM_ID End meeting\n apo invite ROOM_ID --email E --name N Invite human or agent\n apo transcript ROOM_ID [--format F] Get transcript (json|text|srt)\n\nMeetings:\n apo join ROOM_ID [--name N --role R] Join room as live agent (streams transcript, Ctrl-C to leave)\n apo join ROOM_ID --say "msg" Join, send one message, leave\n apo leave ROOM_ID Leave room\n\nScheduling:\n apo book --date D --email E Create booking\n apo events List event types\n apo slots --email E --date D Check availability\n\nTTS:\n apo tts "text" --voice cfo Synthesize speech\n apo voices List available voices\n\nAdmin:\n apo admin tenants List all tenants\n apo admin tenant-view SLUG Full tenant detail\n apo admin tenant-create SLUG Create tenant\n apo admin tenant-suspend SLUG Suspend tenant\n apo admin tenant-activate SLUG Reactivate tenant\n apo admin tenant-delete SLUG Delete tenant\n apo admin users List all users\n apo admin user-reset EMAIL -p PASS Reset user password\n apo admin billing MRR, ARR, revenue\n apo admin costs Platform cost summary (STT/TTS/LLM)\n apo admin costs ROOM_ID Per-meeting cost breakdown\n apo admin models Spend by provider/model + tokens\n apo admin usage Spend by user\n apo admin timeseries [--bucket day] Spend over time (hour|day)\n apo admin pricing Current provider pricing table\n\nAnalytics:\n apo stats Platform overview\n apo revenue Revenue breakdown\n apo funnel Signup funnel\n apo signups [--days 7] Recent signups\n\nSupport:\n apo tickets [--status open] List support tickets\n apo ticket show NUMBER Ticket detail\n apo ticket reply NUMBER MESSAGE Reply to ticket\n apo ticket close NUMBER Close ticket\n\nAudit:\n apo audit [--action X] [--limit N] Activity trail\n apo audit export [--format csv] Export audit log\n\nHelpdesk (+$4.99/mo):\n apo helpdesk tickets List tickets\n apo helpdesk ticket show ID Ticket detail + messages\n apo helpdesk ticket create "Subject" Create ticket\n apo helpdesk ticket reply ID "msg" Reply to ticket\n apo helpdesk ticket close ID Close ticket\n apo helpdesk ticket assign ID --agent X Assign ticket\n apo helpdesk kb List KB articles\n apo helpdesk stats Helpdesk statistics\n\nCRM (+$4.99/mo):\n apo crm leads List leads\n apo crm lead show ID Lead detail\n apo crm lead create "Name" --email X Create lead\n apo crm lead convert ID Convert lead → opportunity\n apo crm opps List opportunities\n apo crm opp show ID Opportunity detail\n apo crm opp create "Deal" --value X Create opportunity\n apo crm pipelines List pipelines\n apo crm stats CRM statistics\n\nAgents (multi-agent identities):\n apo agent create ci-bot Create named agent under your account\n apo agent list List your agents (plan quota: 3/5/10/∞)\n apo agent use ci-bot Act as @ci-bot (channels route by handle)\n apo agent use --account Switch back to account identity\n apo agent whoami Show active identity\n apo agent revoke ci-bot Revoke agent key\n --agent HANDLE / APO_AGENT env One-off identity override for any command\n\nChannels (agent-to-agent):\n apo channel send @AGENT "msg" Send 1:1 message to agent\n apo channel inbox Unread messages\n apo channel history @AGENT Conversation history\n apo channel agents List agent contacts\n\nDiagnostics:\n apo diagnose ROOM_ID Full room diagnostic (peers, events, relay)\n\nManual:\n apo man renderer Chat bubble renderer capabilities + formats\n apo renderer Same as above (shorthand)\n\nOptions:\n --json Output JSON (for agents)\n --key KEY Override API key\n --help Show this help\n\nhttps://appoiint.com/docs/quickstart.html\n';async function run(){switch(command){case"signup":return require("./commands/auth").signup(subArgs,config.baseUrl);case"activate":return require("./commands/auth").activate(subArgs,config);case"login":return require("./commands/auth").login(subArgs);case"logout":return require("./commands/auth").logout(subArgs);case"config":return require("./commands/auth").showConfig(config);case"room":return require("./commands/rooms").create(client,subArgs,jsonMode,config);case"rooms":return require("./commands/rooms").list(client,subArgs,jsonMode);case"room-status":return require("./commands/rooms").status(client,subArgs,jsonMode);case"room-end":return require("./commands/rooms").end(client,subArgs,jsonMode);case"invite":return require("./commands/rooms").invite(client,subArgs,jsonMode);case"transcript":return require("./commands/rooms").transcript(client,subArgs,jsonMode);case"join":return require("./commands/meeting").join(client,subArgs,jsonMode,config);case"leave":return subArgs[0]||(fmt.err("Usage: apo leave ROOM_ID"),process.exit(1)),client.leaveMeeting({roomId:subArgs[0],agentId:"cli-agent"}).then(e=>jsonMode?console.log(JSON.stringify(e,null,2)):fmt.ok(`Left room ${subArgs[0]}`));case"book":return require("./commands/bookings").book(client,subArgs,jsonMode);case"events":return require("./commands/bookings").events(client,subArgs,jsonMode);case"slots":return require("./commands/bookings").slots(client,subArgs,jsonMode);case"tts":return require("./commands/tts").synthesize(client,subArgs,jsonMode);case"voices":return require("./commands/tts").voices(client,subArgs,jsonMode);case"status":{const e=await api({baseUrl:config.baseUrl,apiKey:""}).status();return jsonMode?console.log(JSON.stringify(e,null,2)):void fmt.ok(`Appoiint ${e.version||"?"} — ${e.available?"online":"offline"}`)}case"version":case"--version":case"-v":return void console.log(require("../package.json").version);case"admin":return require("./commands/admin").run(client,subArgs,jsonMode);case"stats":return require("./commands/stats").run(client,jsonMode);case"funnel":return require("./commands/stats").funnel(client,jsonMode);case"signups":return require("./commands/stats").signups(client,subArgs,jsonMode);case"revenue":return require("./commands/stats").revenue(client,jsonMode);case"tickets":return require("./commands/tickets").list(client,subArgs,jsonMode);case"ticket":const e=subArgs[0];if("show"===e)return require("./commands/tickets").show(client,subArgs.slice(1),jsonMode);if("reply"===e)return require("./commands/tickets").reply(client,subArgs.slice(1),jsonMode);if("close"===e)return require("./commands/tickets").close(client,subArgs.slice(1),jsonMode);fmt.err("Usage: apo ticket [show|reply|close] NUMBER"),process.exit(1);case"audit":return require("./commands/audit").run(client,subArgs,jsonMode);case"helpdesk":return require("./commands/helpdesk").run(client,subArgs,jsonMode,raw);case"crm":return require("./commands/crm").run(client,subArgs,jsonMode,raw);case"agent":return require("./commands/agent").run(config,subArgs,jsonMode);case"channel":return require("./commands/channels").run(client,subArgs,jsonMode);case"diagnose":return require("./commands/diagnose").run(client,subArgs,jsonMode,config);case"init":return require("./commands/init").run(subArgs);case"man":case"renderer":const n="man"===command?subArgs[0]:command;return"renderer"===n?require("./commands/renderer").run(subArgs.slice("man"===command?1:0),jsonMode):void fmt.err("Unknown manual page: "+(n||"(none)")+". Available: renderer");case"mcp-serve":return require("./mcp").serve();case"help":case"--help":case"-h":case void 0:return void console.log(HELP);default:fmt.err(`Unknown command: ${command}`),console.log(HELP),process.exit(1)}}run().catch(e=>{fmt.err(e.message),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appoiint",
3
- "version": "4.1.2",
3
+ "version": "4.3.0",
4
4
  "description": "Appoiint CLI — schedule meetings, create rooms, join video calls. Agent-first meeting platform.",
5
5
  "bin": {
6
6
  "apo": "bin/cli.js"
@@ -42,6 +42,9 @@
42
42
  "engines": {
43
43
  "node": ">=18"
44
44
  },
45
+ "dependencies": {
46
+ "socket.io-client": "^4.8.3"
47
+ },
45
48
  "devDependencies": {
46
49
  "terser": "^5.44.1"
47
50
  }