clustr-ai 0.1.29 → 0.1.31

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.
@@ -150,7 +150,7 @@ Now execute the following task:
150
150
  `);if(!e)return;let r=RE(t),i=((ai.get(r)??"")+e).split(`
151
151
  `),s=i.pop()??"";for(let a of i)$r({...t,text:a});ai.set(r,s.slice(-8e3))}function PE(t){let e=RE(t),r=ai.get(e);r&&$r({...t,text:r}),ai.delete(e)}function IE(t,e){return[...ii.get(si(t,e))??[]]}function LE(t,e){e?ii.delete(si(t,e)):(ii.delete(si(t)),ii.delete(si(t,"agent")));for(let r of[...ai.keys()])r.startsWith(`${t}:`)&&(!e||r.startsWith(`${t}:${e}:`))&&ai.delete(r)}import Ft from"fs";import NE from"os";import or from"path";var UD=1e3,zD=256*1024,of=new Map;function HD(t){return or.resolve(t).replace(/\//g,"-")}function WD(t,e){let r=HD(t),n=[...new Set([NE.tmpdir(),"/tmp","/private/tmp"])],i=[];for(let a of n)try{let o=e==="claude"?["claude-"]:["codex-","codex"];i.push(...Ft.readdirSync(a).filter(c=>o.some(l=>c.startsWith(l))).map(c=>or.join(a,c,r)).filter(c=>Ft.existsSync(c)))}catch{}if(e==="codex"){let a=or.join(NE.homedir(),".codex");for(let o of[or.join(a,r),or.join(a,"logs"),or.join(a,"sessions")])Ft.existsSync(o)&&i.push(o)}let s=[];for(let a of i)DE(a,s,0);return[...new Set(s.map(a=>{try{return Ft.realpathSync(a)}catch{return a}}))].sort()}function DE(t,e,r){if(r>5)return;let n=[];try{n=Ft.readdirSync(t,{withFileTypes:!0})}catch{return}for(let i of n){let s=or.join(t,i.name);i.isDirectory()?DE(s,e,r+1):i.isFile()&&(i.name.endsWith(".output")||i.name.endsWith(".log"))&&e.push(s)}}function $D(t,e,r){let n=Math.max(e,r-zD),i=r-n;if(i<=0)return"";let s=Ft.openSync(t,"r");try{let a=Buffer.alloc(i);return Ft.readSync(s,a,0,i,n),a.toString("utf-8")}finally{Ft.closeSync(s)}}function BE(t){for(let e of WD(t.cwd,t.service)){let r;try{r=Ft.statSync(e)}catch{continue}let n=t.offsets.get(e),i=r.size;if(n===void 0){t.offsets.set(e,i);continue}let s=n;if(t.offsets.set(e,i),!(i<=s))try{let a=$D(e,s,i);a&&Pc({agentId:t.agentId,source:"agent",stream:"stdout",data:a})}catch{}}}function Ic(t,e,r){Gr(t);let n={agentId:t,cwd:or.resolve(e),service:r,offsets:new Map,timer:setInterval(()=>BE(n),UD)};n.timer.unref(),of.set(t,n),BE(n)}function Gr(t){let e=of.get(t);e&&(clearInterval(e.timer),of.delete(t))}var KD=VD(import.meta.url),qE=oi.dirname(KD),XD={claude:"npm install -g @anthropic-ai/claude-code",codex:"npm install -g @openai/codex"};function JD(t){try{let e=process.platform==="win32"?"where":"/usr/bin/which";return GD(e,[t],{encoding:"utf-8"}).trim()}catch{return""}}var QD=oi.join(YD.homedir(),".clustr"),cf=oi.join(QD,"mcp-configs"),jE=1e5,cr=new Map,qs=null,UE=null,FE=parseInt(process.env.CLUSTR_MAX_AGENTS||"5",10);function ZD(t,e,r){$r({agentId:e,source:"agent",stream:"stdout",level:"debug",text:"Submitting initial Claude task"});try{t.write(r)}catch(n){$r({agentId:e,source:"agent",stream:"stdout",level:"error",text:`Failed to write initial Claude task: ${n.message}`});return}setTimeout(()=>{try{t.write("\r"),$r({agentId:e,source:"agent",stream:"stdout",level:"debug",text:"Submitted initial Claude task with Enter"})}catch(n){$r({agentId:e,source:"agent",stream:"stdout",level:"error",text:`Failed to submit initial Claude task: ${n.message}`})}},300)}function zE(t,e){qs=t,UE=e??null}function HE(t,e,r){if(cr.size>=FE)throw new Error(`Max concurrent agents (${FE}) reached`);let n=r?.service&&CE(r.service)?r.service:"claude",i=af[n],s=Is();Lc.existsSync(cf)||Lc.mkdirSync(cf,{recursive:!0});let a=oi.resolve(qE,"mcp-stdio-bridge.js");if(Lc.existsSync(a)||(a=oi.resolve(qE,"..","dist","server","mcp-stdio-bridge.js")),!Lc.existsSync(a))throw new Error('MCP bridge not compiled. Run "npm run build:server" first.');let o=oi.join(cf,`${s}.json`),c=`http://127.0.0.1:${process.env.CLUSTR_PORT||"3100"}`;i.writeMcpConfig(o,a,s,c),gc(s,t,n,e,null);let l=r?.cwd||process.cwd();Qe(s,{agent_cwd:l,status:"running"});let p=i.buildPrompt({name:t,id:s,task:e}),u=i.buildArgs({mcpConfigPath:o,systemPrompt:p,task:e,cwd:l}),d={};for(let[A,F]of Object.entries(process.env))F!==void 0&&A!=="CLAUDECODE"&&A!=="NO_COLOR"&&(d[A]=F);d.COLORTERM="truecolor",d.FORCE_COLOR="3",d.TERM="xterm-256color";let h=JD(i.command);if(!h){let A=XD[n]||`Install "${i.command}" and make sure it's in your PATH`;throw new Error(`${i.command} CLI not found. Install with: ${A}`)}let f=ME.spawn(h,u,{name:"xterm-256color",cols:120,rows:30,cwd:l,env:d}),m={pty:f,cwd:l,scrollback:""};cr.set(s,m),Ic(s,l,n),Qe(s,{status:"running",pid:f.pid});let v=0,b=0,y=0,w=/\$(\d+\.?\d*)/,_=/(\d[\d,]+)\s*tokens?/i,E=/total\s*(?:cost|spent)[:\s]*\$(\d+\.?\d*)/i;f.onData(A=>{m.scrollback+=A,m.scrollback.length>jE&&(m.scrollback=m.scrollback.slice(-jE)),qs?.emit(`agent:pty:${s}`,A),Pc({agentId:s,source:"agent",stream:"stdout",data:A});let F=A.replace(/\x1b\[[0-9;]*[a-zA-Z]/g,""),Ee=F.match(E)||F.match(w);if(Ee){let ee=parseFloat(Ee[1]);ee>b&&(b=ee,Qe(s,{total_cost:ee}),qs?.emit("agent:cost",{id:s,total_cost:ee,total_tokens:y}))}let dt=F.match(_);if(dt){let ee=parseInt(dt[1].replace(/,/g,""),10);ee>y&&(y=ee,Qe(s,{total_tokens:ee}),qs?.emit("agent:cost",{id:s,total_cost:b,total_tokens:ee}))}let At=Date.now();At-v>15e3&&(v=At,Qe(s,{last_seen:new Date().toISOString().replace("T"," ").slice(0,19)}))}),f.onExit(({exitCode:A})=>{PE({agentId:s,source:"agent",stream:"stdout"}),Gr(s),cr.delete(s),Qe(s,{status:"done"}),qs?.emit(`agent:pty:${s}`,`\r
152
152
  \x1B[33m--- Process exited (code: ${A}) ---\x1B[0m\r
153
- `),UE?.(),i.cleanupMcpConfig(o,l)});let S=!1,T=()=>{S||(S=!0,n==="claude"&&e.trim()&&ZD(f,s,e))};return i.setupDialogHandlers(f,T),s}function lf(t,e){let r=cr.get(t);return r?(r.pty.write(e),!0):!1}function WE(t,e,r){let n=cr.get(t);if(!n)return!1;let i=r?`Message from ${e}: ${r}`:`You have a new message from ${e}. Use mcp__clustr__read_messages to read and respond.`;return setTimeout(()=>{n.pty.write(i+"\r")},300),!0}function $E(t,e,r){let n=cr.get(t);if(!n)return!1;try{n.pty.resize(e,r)}catch{}return!0}function pf(t){let e=cr.get(t);return e?(Gr(t),e.pty.kill(),!0):!1}function GE(t){return cr.get(t)?.scrollback??""}var VE=null;function YE(t){VE=t}function uf(t,e,r){let n=$_(t,e,r);VE?.emit("messages:new",n);let s=ir(t)?.name||t;return WE(e,s,r),n}function KE(t){return G_(t)}function XE(t,e){let r=vc().filter(i=>i.status==="running"&&i.id!==t),n=[];for(let i of r)n.push(uf(t,i.id,e));return n}var df=null;function JE(t){df=t}function QE(t){return Y_(t)}function ZE(t,e,r){let i=ir(r)?.name||r;X_(t,e,i),df?.emit("context:updated",{key:t,value:e,updatedBy:i})}function eS(t){K_(t),df?.emit("context:removed",{key:t})}import nq from"fs";import Vr from"path";import{execFile as iq}from"child_process";import{promisify as sq}from"util";var js=class{diff(e,r,n={}){let i;typeof n=="function"?(i=n,n={}):"callback"in n&&(i=n.callback);let s=this.castInput(e,n),a=this.castInput(r,n),o=this.removeEmpty(this.tokenize(s,n)),c=this.removeEmpty(this.tokenize(a,n));return this.diffWithOptionsObj(o,c,n,i)}diffWithOptionsObj(e,r,n,i){var s;let a=y=>{if(y=this.postProcess(y,n),i){setTimeout(function(){i(y)},0);return}else return y},o=r.length,c=e.length,l=1,p=o+c;n.maxEditLength!=null&&(p=Math.min(p,n.maxEditLength));let u=(s=n.timeout)!==null&&s!==void 0?s:1/0,d=Date.now()+u,h=[{oldPos:-1,lastComponent:void 0}],f=this.extractCommon(h[0],r,e,0,n);if(h[0].oldPos+1>=c&&f+1>=o)return a(this.buildValues(h[0].lastComponent,r,e));let m=-1/0,v=1/0,b=()=>{for(let y=Math.max(m,-l);y<=Math.min(v,l);y+=2){let w,_=h[y-1],E=h[y+1];_&&(h[y-1]=void 0);let S=!1;if(E){let A=E.oldPos-y;S=E&&0<=A&&A<o}let T=_&&_.oldPos+1<c;if(!S&&!T){h[y]=void 0;continue}if(!T||S&&_.oldPos<E.oldPos?w=this.addToPath(E,!0,!1,0,n):w=this.addToPath(_,!1,!0,1,n),f=this.extractCommon(w,r,e,y,n),w.oldPos+1>=c&&f+1>=o)return a(this.buildValues(w.lastComponent,r,e))||!0;h[y]=w,w.oldPos+1>=c&&(v=Math.min(v,y-1)),f+1>=o&&(m=Math.max(m,y+1))}l++};if(i)(function y(){setTimeout(function(){if(l>p||Date.now()>d)return i(void 0);b()||y()},0)})();else for(;l<=p&&Date.now()<=d;){let y=b();if(y)return y}}addToPath(e,r,n,i,s){let a=e.lastComponent;return a&&!s.oneChangePerToken&&a.added===r&&a.removed===n?{oldPos:e.oldPos+i,lastComponent:{count:a.count+1,added:r,removed:n,previousComponent:a.previousComponent}}:{oldPos:e.oldPos+i,lastComponent:{count:1,added:r,removed:n,previousComponent:a}}}extractCommon(e,r,n,i,s){let a=r.length,o=n.length,c=e.oldPos,l=c-i,p=0;for(;l+1<a&&c+1<o&&this.equals(n[c+1],r[l+1],s);)l++,c++,p++,s.oneChangePerToken&&(e.lastComponent={count:1,previousComponent:e.lastComponent,added:!1,removed:!1});return p&&!s.oneChangePerToken&&(e.lastComponent={count:p,previousComponent:e.lastComponent,added:!1,removed:!1}),e.oldPos=c,l}equals(e,r,n){return n.comparator?n.comparator(e,r):e===r||!!n.ignoreCase&&e.toLowerCase()===r.toLowerCase()}removeEmpty(e){let r=[];for(let n=0;n<e.length;n++)e[n]&&r.push(e[n]);return r}castInput(e,r){return e}tokenize(e,r){return Array.from(e)}join(e){return e.join("")}postProcess(e,r){return e}get useLongestToken(){return!1}buildValues(e,r,n){let i=[],s;for(;e;)i.push(e),s=e.previousComponent,delete e.previousComponent,e=s;i.reverse();let a=i.length,o=0,c=0,l=0;for(;o<a;o++){let p=i[o];if(p.removed)p.value=this.join(n.slice(l,l+p.count)),l+=p.count;else{if(!p.added&&this.useLongestToken){let u=r.slice(c,c+p.count);u=u.map(function(d,h){let f=n[l+h];return f.length>d.length?f:d}),p.value=this.join(u)}else p.value=this.join(r.slice(c,c+p.count));c+=p.count,p.added||(l+=p.count)}}return i}};var ff=class extends js{constructor(){super(...arguments),this.tokenize=tq}equals(e,r,n){return n.ignoreWhitespace?((!n.newlineIsToken||!e.includes(`
153
+ `),UE?.(),i.cleanupMcpConfig(o,l)});let S=!1,T=()=>{S||(S=!0,n==="claude"&&e.trim()&&ZD(f,s,e))};return i.setupDialogHandlers(f,T),s}function lf(t,e){let r=cr.get(t);return r?(r.pty.write(e),!0):!1}function WE(t,e,r){let n=cr.get(t);if(!n)return!1;let i=r?`Message from ${e}: ${r}`:`You have a new message from ${e}. Use mcp__clustr__read_messages to read and respond.`;return n.pty.write(i),setTimeout(()=>{n.pty.write("\r")},100),!0}function $E(t,e,r){let n=cr.get(t);if(!n)return!1;try{n.pty.resize(e,r)}catch{}return!0}function pf(t){let e=cr.get(t);return e?(Gr(t),e.pty.kill(),!0):!1}function GE(t){return cr.get(t)?.scrollback??""}var VE=null;function YE(t){VE=t}function uf(t,e,r){let n=$_(t,e,r);VE?.emit("messages:new",n);let s=ir(t)?.name||t;return WE(e,s,r),n}function KE(t){return G_(t)}function XE(t,e){let r=vc().filter(i=>i.status==="running"&&i.id!==t),n=[];for(let i of r)n.push(uf(t,i.id,e));return n}var df=null;function JE(t){df=t}function QE(t){return Y_(t)}function ZE(t,e,r){let i=ir(r)?.name||r;X_(t,e,i),df?.emit("context:updated",{key:t,value:e,updatedBy:i})}function eS(t){K_(t),df?.emit("context:removed",{key:t})}import nq from"fs";import Vr from"path";import{execFile as iq}from"child_process";import{promisify as sq}from"util";var js=class{diff(e,r,n={}){let i;typeof n=="function"?(i=n,n={}):"callback"in n&&(i=n.callback);let s=this.castInput(e,n),a=this.castInput(r,n),o=this.removeEmpty(this.tokenize(s,n)),c=this.removeEmpty(this.tokenize(a,n));return this.diffWithOptionsObj(o,c,n,i)}diffWithOptionsObj(e,r,n,i){var s;let a=y=>{if(y=this.postProcess(y,n),i){setTimeout(function(){i(y)},0);return}else return y},o=r.length,c=e.length,l=1,p=o+c;n.maxEditLength!=null&&(p=Math.min(p,n.maxEditLength));let u=(s=n.timeout)!==null&&s!==void 0?s:1/0,d=Date.now()+u,h=[{oldPos:-1,lastComponent:void 0}],f=this.extractCommon(h[0],r,e,0,n);if(h[0].oldPos+1>=c&&f+1>=o)return a(this.buildValues(h[0].lastComponent,r,e));let m=-1/0,v=1/0,b=()=>{for(let y=Math.max(m,-l);y<=Math.min(v,l);y+=2){let w,_=h[y-1],E=h[y+1];_&&(h[y-1]=void 0);let S=!1;if(E){let A=E.oldPos-y;S=E&&0<=A&&A<o}let T=_&&_.oldPos+1<c;if(!S&&!T){h[y]=void 0;continue}if(!T||S&&_.oldPos<E.oldPos?w=this.addToPath(E,!0,!1,0,n):w=this.addToPath(_,!1,!0,1,n),f=this.extractCommon(w,r,e,y,n),w.oldPos+1>=c&&f+1>=o)return a(this.buildValues(w.lastComponent,r,e))||!0;h[y]=w,w.oldPos+1>=c&&(v=Math.min(v,y-1)),f+1>=o&&(m=Math.max(m,y+1))}l++};if(i)(function y(){setTimeout(function(){if(l>p||Date.now()>d)return i(void 0);b()||y()},0)})();else for(;l<=p&&Date.now()<=d;){let y=b();if(y)return y}}addToPath(e,r,n,i,s){let a=e.lastComponent;return a&&!s.oneChangePerToken&&a.added===r&&a.removed===n?{oldPos:e.oldPos+i,lastComponent:{count:a.count+1,added:r,removed:n,previousComponent:a.previousComponent}}:{oldPos:e.oldPos+i,lastComponent:{count:1,added:r,removed:n,previousComponent:a}}}extractCommon(e,r,n,i,s){let a=r.length,o=n.length,c=e.oldPos,l=c-i,p=0;for(;l+1<a&&c+1<o&&this.equals(n[c+1],r[l+1],s);)l++,c++,p++,s.oneChangePerToken&&(e.lastComponent={count:1,previousComponent:e.lastComponent,added:!1,removed:!1});return p&&!s.oneChangePerToken&&(e.lastComponent={count:p,previousComponent:e.lastComponent,added:!1,removed:!1}),e.oldPos=c,l}equals(e,r,n){return n.comparator?n.comparator(e,r):e===r||!!n.ignoreCase&&e.toLowerCase()===r.toLowerCase()}removeEmpty(e){let r=[];for(let n=0;n<e.length;n++)e[n]&&r.push(e[n]);return r}castInput(e,r){return e}tokenize(e,r){return Array.from(e)}join(e){return e.join("")}postProcess(e,r){return e}get useLongestToken(){return!1}buildValues(e,r,n){let i=[],s;for(;e;)i.push(e),s=e.previousComponent,delete e.previousComponent,e=s;i.reverse();let a=i.length,o=0,c=0,l=0;for(;o<a;o++){let p=i[o];if(p.removed)p.value=this.join(n.slice(l,l+p.count)),l+=p.count;else{if(!p.added&&this.useLongestToken){let u=r.slice(c,c+p.count);u=u.map(function(d,h){let f=n[l+h];return f.length>d.length?f:d}),p.value=this.join(u)}else p.value=this.join(r.slice(c,c+p.count));c+=p.count,p.added||(l+=p.count)}}return i}};var ff=class extends js{constructor(){super(...arguments),this.tokenize=tq}equals(e,r,n){return n.ignoreWhitespace?((!n.newlineIsToken||!e.includes(`
154
154
  `))&&(e=e.trim()),(!n.newlineIsToken||!r.includes(`
155
155
  `))&&(r=r.trim())):n.ignoreNewlineAtEof&&!n.newlineIsToken&&(e.endsWith(`
156
156
  `)&&(e=e.slice(0,-1)),r.endsWith(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clustr-ai",
3
- "version": "0.1.29",
3
+ "version": "0.1.31",
4
4
  "description": "Local multi-agent workspace for Claude Code and Codex agents that collaborate across your codebase",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Clustr",