mobsession 0.1.0 → 0.1.1

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.
Files changed (3) hide show
  1. package/README.md +4 -4
  2. package/index.js +1 -1
  3. package/package.json +4 -4
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Mob Squad (msq)
1
+ # mobsession
2
2
 
3
- Drive Claude Code together. `msq` runs a real Claude Code session on your machine and shares a
3
+ Drive Claude Code together. `mobsession` runs a real Claude Code session on your machine and shares a
4
4
  link so your whole team can steer it in real time, with your own Claude subscription.
5
5
 
6
6
  ## Install
@@ -14,8 +14,8 @@ npm i -g mobsession
14
14
  In any project directory:
15
15
 
16
16
  ```bash
17
- msq start
17
+ mobsession start # or the short alias: mss start
18
18
  ```
19
19
 
20
20
  It prints a link. Open it (and share it) at https://mobsession.ai to watch the session live and add
21
- prompts together. No account required.
21
+ prompts together.
package/index.js CHANGED
@@ -39,4 +39,4 @@ Expecting one of '${s.join("', '")}'`);let n=`${e}Help`;return this.on(n,i=>{let
39
39
  `)+`\r
40
40
  \r
41
41
  `+d)}function y(f,S,d,T,E,W){if(f.listenerCount("wsClientError")){let C=new Error(E);Error.captureStackTrace(C,y),f.emit("wsClientError",C,d,S)}else q(d,T,E,W)}}}),wp=Xe(vl(),1),xp=Xe(on(),1),Sp=Xe(gr(),1),Cp=Xe(vo(),1),kp=Xe(bo(),1),Ep=Xe(wo(),1),wl=Xe(an(),1),Tp=Xe(bl(),1),xl=wl.default,Sl=xl;go(Sl);var $g=H.object({numItems:H.number(),cursor:H.union(H.string(),H.null()),endCursor:H.optional(H.union(H.string(),H.null())),id:H.optional(H.number()),maximumRowsRead:H.optional(H.number()),maximumBytesRead:H.optional(H.number())});function xo(r,e){let t={get(s,n){if(typeof n=="string"){let i=[...e,n];return xo(r,i)}else if(n===Xs){if(e.length<1){let i=[r,...e].join(".");throw new Error(`API path is expected to be of the form \`${r}.childComponent.functionName\`. Found: \`${i}\``)}return"_reference/childComponent/"+e.join("/")}else return}};return new Proxy({},t)}var un=()=>xo("components",[]);var Tl=Symbol("var.requestId"),Ol=Symbol("var.ip"),Al=Symbol("var.userAgent"),Rl=Symbol("var.now"),Il={[Tl]:"requestId",[Ol]:"ip",[Al]:"userAgent",[Rl]:"now"};var Pl=Object.defineProperty,Nl=(r,e,t)=>e in r?Pl(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,je=(r,e,t)=>Nl(r,typeof e!="symbol"?e+"":e,t),is=class{constructor(e){je(this,"indexes"),je(this,"stagedDbIndexes"),je(this,"searchIndexes"),je(this,"stagedSearchIndexes"),je(this,"vectorIndexes"),je(this,"stagedVectorIndexes"),je(this,"validator"),this.indexes=[],this.stagedDbIndexes=[],this.searchIndexes=[],this.stagedSearchIndexes=[],this.vectorIndexes=[],this.stagedVectorIndexes=[],this.validator=e}" indexes"(){return this.indexes}index(e,t){return Array.isArray(t)?this.indexes.push({indexDescriptor:e,fields:t}):t.staged?this.stagedDbIndexes.push({indexDescriptor:e,fields:t.fields}):this.indexes.push({indexDescriptor:e,fields:t.fields}),this}searchIndex(e,t){return t.staged?this.stagedSearchIndexes.push({indexDescriptor:e,searchField:t.searchField,filterFields:t.filterFields||[]}):this.searchIndexes.push({indexDescriptor:e,searchField:t.searchField,filterFields:t.filterFields||[]}),this}vectorIndex(e,t){return t.staged?this.stagedVectorIndexes.push({indexDescriptor:e,vectorField:t.vectorField,dimensions:t.dimensions,filterFields:t.filterFields||[]}):this.vectorIndexes.push({indexDescriptor:e,vectorField:t.vectorField,dimensions:t.dimensions,filterFields:t.filterFields||[]}),this}self(){return this}export(){let e=this.validator.json;if(typeof e!="object")throw new Error("Invalid validator: please make sure that the parameter of `defineTable` is valid (see https://docs.convex.dev/database/schemas)");return{indexes:this.indexes,stagedDbIndexes:this.stagedDbIndexes,searchIndexes:this.searchIndexes,stagedSearchIndexes:this.stagedSearchIndexes,vectorIndexes:this.vectorIndexes,stagedVectorIndexes:this.stagedVectorIndexes,documentType:e}}};function ln(r){return Gs(r)?new is(r):new is(H.object(r))}var hn=class{constructor(e,t){je(this,"tables"),je(this,"strictTableNameTypes"),je(this,"schemaValidation"),this.tables=e,this.schemaValidation=t?.schemaValidation===void 0?!0:t.schemaValidation}export(){return JSON.stringify({tables:Object.entries(this.tables).map(([e,t])=>{let{indexes:s,stagedDbIndexes:n,searchIndexes:i,stagedSearchIndexes:o,vectorIndexes:c,stagedVectorIndexes:a,documentType:u}=t.export();return{tableName:e,indexes:s,stagedDbIndexes:n,searchIndexes:i,stagedSearchIndexes:o,vectorIndexes:c,stagedVectorIndexes:a,documentType:u}}),schemaValidation:this.schemaValidation})}};function So(r,e){return new hn(r,e)}var oy=So({_scheduled_functions:ln({name:H.string(),args:H.array(H.any()),scheduledTime:H.float64(),completedTime:H.optional(H.float64()),state:H.union(H.object({kind:H.literal("pending")}),H.object({kind:H.literal("inProgress")}),H.object({kind:H.literal("success")}),H.object({kind:H.literal("failed"),error:H.string()}),H.object({kind:H.literal("canceled")}))}),_storage:ln({sha256:H.string(),size:H.float64(),contentType:H.optional(H.string())})});var He=en;var By=un();var $l={maxBatch:25,windowMs:200,setTimer:(r,e)=>setTimeout(r,e),clearTimer:r=>clearTimeout(r)},os=class{constructor(e,t={}){this.flush=e;this.opts={...$l,...t}}flush;buffer=[];nextClientEventId=0;timer=null;opts;add(e){this.buffer.push({v:1,clientEventId:this.nextClientEventId++,event:e}),this.buffer.length>=this.opts.maxBatch?this.flushNow():this.timer===null&&(this.timer=this.opts.setTimer(()=>this.flushNow(),this.opts.windowMs))}flushNow(){if(this.timer!==null&&(this.opts.clearTimer(this.timer),this.timer=null),this.buffer.length===0)return;let e=Ml(this.buffer);this.buffer=[],this.flush(e)}};function Ml(r){let e=[];for(let t of r){let s=e[e.length-1];t.event.type==="agent.text"&&s&&s.event.type==="agent.text"&&s.event.turnId===t.event.turnId?s.event={...s.event,text:s.event.text+t.event.text}:e.push(t)}return e}async function Co(r){let e=new Ct(r.convexUrl),t=!1,s=!1,n=null,i=null,o=[],c=new Set,a=v=>{let k=n;t=!1,n=null,i=null,k&&e.mutation(He.prompts.markTurn,{promptId:k,status:v}).catch(()=>{}),l()};async function u(v){if(!v.attachments?.length)return[];let k=await e.query(He.files.attachmentUrls,{storageIds:v.attachments.map(f=>f.storageId)}),q=new Map(k.map(f=>[f.storageId,f.url])),y=[];for(let f of v.attachments){let S=q.get(f.storageId);if(S)try{let d=await fetch(S),T=Buffer.from(await d.arrayBuffer()).toString("base64");y.push({mediaType:f.mediaType,data:T})}catch{}}return y}async function l(){if(!(t||s)){s=!0;try{let v=[...o].sort((k,q)=>k.queueOrder-q.queueOrder);for(let k of v)if(await e.mutation(He.prompts.claimPrompt,{promptId:k._id})){t=!0,n=k._id;try{let y=await u(k);i=r.agent.sendPrompt(k.text,y),r.onPromptInjected?.({text:k.text,submittedBy:k.submittedBy,local:c.has(k._id)})}catch{a("failed");continue}return}}finally{s=!1}}}let h=null,p=[];r.agent.onEvent(v=>{v.type==="agent.turn_result"&&i&&v.turnId===i?a(v.success?"done":"failed"):v.type==="agent.error"&&t&&a("failed"),r.onAgentEvent?.(v),h?h.add(v):p.push(v)}),r.agent.onError(v=>{let k={type:"agent.error",message:v.message};r.onAgentEvent?.(k),h?h.add(k):p.push(k),t&&a("failed")});let m;try{m=await e.mutation(He.sessions.createSession,{cwd:r.cwd,model:r.model})}catch(v){throw await r.agent.stop(),await e.close(),v}let{sessionId:g,joinCode:O}=m,P=Promise.resolve(),j=v=>new Promise(k=>setTimeout(k,v));h=new os(v=>{P=P.then(async()=>{for(let k=0;k<3;k+=1)try{await e.mutation(He.events.appendEvents,{sessionId:g,events:v});return}catch(q){if(k===2){console.error(`Failed to mirror ${v.length} events after retries:`,q);return}await j(200*(k+1))}})});for(let v of p)h.add(v);p.length=0;let w=e.onUpdate(He.prompts.pendingPrompts,{sessionId:g},v=>{o=v,l()});return{joinCode:O,submitLocalPrompt:async v=>{let k=await e.mutation(He.prompts.submitLocalPrompt,{sessionId:g,text:v});c.add(k)},stop:async()=>{h?.flushNow(),await P,w(),await e.mutation(He.sessions.endSession,{sessionId:g}).catch(()=>{}),await e.close()}}}var ql=6e3;async function ko(r){let e=ir({cwd:r.cwd}),t=tt.createInterface({input:process.stdin,output:process.stdout,prompt:"you> "}),s=!1,n=l=>{s&&process.stdout.isTTY&&(tt.cursorTo(process.stdout,0),tt.clearLine(process.stdout,0)),console.log(l),s&&t.prompt(!0)},i=!1,o=l=>{if(l.type==="agent.text"){i||(s&&process.stdout.isTTY&&(tt.cursorTo(process.stdout,0),tt.clearLine(process.stdout,0)),process.stdout.write("claude> "),i=!0),process.stdout.write(l.text);return}i&&(process.stdout.write(`
42
- `),i=!1);let h=Rr(l);h!==null&&n(h)},c,a=!1,u=async()=>{if(a)return;a=!0,t.close();let l=setTimeout(()=>process.exit(0),ql);try{await c?.stop(),await e.stop()}finally{clearTimeout(l),process.exit(0)}};e.onError(l=>n(`[agent error] ${l.message}`)),process.on("SIGINT",()=>{u()}),process.on("SIGTERM",()=>{u()}),process.on("uncaughtException",l=>{console.error("[fatal]",l),u()}),process.on("unhandledRejection",l=>{console.error("[fatal]",l),u()}),t.on("close",()=>{u()});try{c=await Co({convexUrl:r.convexUrl,cwd:r.cwd,model:r.model,agent:e,onAgentEvent:o,onPromptInjected:({text:l,submittedBy:h,local:p})=>{p||n(`${h}> ${l}`)}})}catch(l){console.error("Could not start the session:",l instanceof Error?l.message:l),await e.stop(),process.exit(1);return}console.log("Mob Squad session is live."),console.log(`Join: ${r.webBaseUrl}/s/${c.joinCode}`),console.log("You and everyone on the link share this agent. Type a prompt and press Enter. Ctrl+C to end."),s=!0,t.prompt(),t.on("line",l=>{let h=l.trim();h&&c?.submitLocalPrompt(h),t.prompt()})}var Ll="https://standing-mongoose-114.convex.cloud",Vl="https://mobsession.ai",as=new jn;as.name("msq").description("Mob Squad daemon");as.command("dev").description("Run a local agent session and round-trip prompts from the terminal (no cloud)").option("--cwd <dir>","working directory for the agent",process.cwd()).action(r=>Wi(r.cwd));as.command("start").description("Run a cloud session: mirror the agent to the web and inject approved prompts").option("--cwd <dir>","working directory for the agent",process.cwd()).option("--convex-url <url>","Convex deployment URL",process.env.MOB_SQUAD_CONVEX_URL??Ll).option("--web-url <url>","web app base URL for the join link",process.env.MOB_SQUAD_WEB_URL??Vl).option("--model <model>","model label for the session","claude").action(r=>{if(!r.convexUrl){console.error("Missing Convex URL. Set MOB_SQUAD_CONVEX_URL or pass --convex-url."),process.exitCode=1;return}ko({cwd:r.cwd,convexUrl:r.convexUrl,webBaseUrl:r.webUrl,model:r.model})});as.parse();
42
+ `),i=!1);let h=Rr(l);h!==null&&n(h)},c,a=!1,u=async()=>{if(a)return;a=!0,t.close();let l=setTimeout(()=>process.exit(0),ql);try{await c?.stop(),await e.stop()}finally{clearTimeout(l),process.exit(0)}};e.onError(l=>n(`[agent error] ${l.message}`)),process.on("SIGINT",()=>{u()}),process.on("SIGTERM",()=>{u()}),process.on("uncaughtException",l=>{console.error("[fatal]",l),u()}),process.on("unhandledRejection",l=>{console.error("[fatal]",l),u()}),t.on("close",()=>{u()});try{c=await Co({convexUrl:r.convexUrl,cwd:r.cwd,model:r.model,agent:e,onAgentEvent:o,onPromptInjected:({text:l,submittedBy:h,local:p})=>{p||n(`${h}> ${l}`)}})}catch(l){console.error("Could not start the session:",l instanceof Error?l.message:l),await e.stop(),process.exit(1);return}console.log("mobsession is live."),console.log(`Join: ${r.webBaseUrl}/s/${c.joinCode}`),console.log("You and everyone on the link share this agent. Type a prompt and press Enter. Ctrl+C to end."),s=!0,t.prompt(),t.on("line",l=>{let h=l.trim();h&&c?.submitLocalPrompt(h),t.prompt()})}var Ll="https://standing-mongoose-114.convex.cloud",Vl="https://mobsession.ai",as=new jn;as.name("mobsession").description("mobsession: drive Claude Code together");as.command("dev").description("Run a local agent session and round-trip prompts from the terminal (no cloud)").option("--cwd <dir>","working directory for the agent",process.cwd()).action(r=>Wi(r.cwd));as.command("start").description("Run a cloud session: mirror the agent to the web and inject approved prompts").option("--cwd <dir>","working directory for the agent",process.cwd()).option("--convex-url <url>","Convex deployment URL",process.env.MOB_SQUAD_CONVEX_URL??Ll).option("--web-url <url>","web app base URL for the join link",process.env.MOB_SQUAD_WEB_URL??Vl).option("--model <model>","model label for the session","claude").action(r=>{if(!r.convexUrl){console.error("Missing Convex URL. Set MOB_SQUAD_CONVEX_URL or pass --convex-url."),process.exitCode=1;return}ko({cwd:r.cwd,convexUrl:r.convexUrl,webBaseUrl:r.webUrl,model:r.model})});as.parse();
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "mobsession",
3
- "version": "0.1.0",
4
- "description": "Mob Squad: drive Claude Code together. A shared, collaborative Claude Code session your whole team can steer.",
3
+ "version": "0.1.1",
4
+ "description": "mobsession: drive Claude Code together. A shared, collaborative Claude Code session your whole team can steer.",
5
5
  "type": "module",
6
6
  "bin": {
7
- "msq": "./index.js",
8
- "mobsession": "./index.js"
7
+ "mobsession": "./index.js",
8
+ "mss": "./index.js"
9
9
  },
10
10
  "engines": {
11
11
  "node": ">=22"