@oxgeneral/orch 1.0.22 → 1.0.24

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.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import {a as a$2}from'./chunk-N4OXN2HW.js';import {c as c$1,b as b$3}from'./chunk-HXOMNULD.js';import {b as b$2,a as a$1}from'./chunk-KR7VDF23.js';import {a}from'./chunk-CHRW4CLD.js';import {b}from'./chunk-6E6DC7OE.js';import {b as b$1,c,j,d,e,l as l$1,f as f$1,h,i as i$1,g as g$1,k as k$1}from'./chunk-ZMLF5HI5.js';import {c as c$2,l,j as j$1,k,g,f,i}from'./chunk-LRYVT4D4.js';import tt from'path';import Z,{mkdir}from'fs/promises';import {createReadStream}from'fs';import {homedir}from'os';import {nanoid}from'nanoid';var P={tui:{activity_filter:"all",notifications:{toast:true,bell:false}}};var w=class{indexPath;dir;ext;itemPath;fileFilter;readItemFn;mutex=Promise.resolve();insideMutex=false;constructor(t){this.dir=t.dir,this.ext=t.ext,this.itemPath=t.itemPath,this.indexPath=tt.join(t.dir,"_index.json"),this.fileFilter=t.fileFilter??(()=>true),t.readItem?this.readItemFn=t.readItem:t.ext===".yml"?this.readItemFn=e=>b$1(e):this.readItemFn=e=>d(e);}async readIndex(){try{let t=await d(this.indexPath);if(Array.isArray(t))return t}catch{}return this.rebuildIndex()}async rebuildIndex(){await j(this.dir);let t=await l$1(this.dir,this.ext),e=await Promise.all(t.filter(this.fileFilter).map(r=>{let a=r.replace(this.ext,"");return this.readItemFn(this.itemPath(a))})),s=[];for(let r of e)r!=null&&s.push(r);return this.insideMutex?await this.writeIndexUnsafe(s):await this.withMutex(()=>this.writeIndexUnsafe(s)),s}async writeIndex(t){return this.withMutex(()=>this.writeIndexUnsafe(t))}async updateIndex(t){return this.withMutex(async()=>{let e=await this.readIndex(),s=t(e);await this.writeIndexUnsafe(s);})}async writeIndexUnsafe(t){await j(this.dir),await e(this.indexPath,t);}withMutex(t){let e,s=new Promise(a=>{e=a;}),r=this.mutex;return this.mutex=s,r.then(async()=>{this.insideMutex=true;try{return await t()}finally{this.insideMutex=false,e();}})}};var M=class{constructor(t){this.paths=t;this.index=new w({dir:t.tasksDir,ext:".yml",itemPath:e=>t.taskPath(e)});}index;async list(t){return (await this.index.readIndex()).filter(r=>r!==null&&(!t?.status||r.status===t.status)&&(!t?.goalId||r.goalId===t.goalId)).sort((r,a)=>{let n=ht(r.status)-ht(a.status);if(n!==0)return n;let i=a.updated_at??"",o=r.updated_at??"";return i<o?-1:i>o?1:0})}async get(t){return b$1(this.paths.taskPath(t))}async save(t){await j(this.paths.tasksDir),await c(this.paths.taskPath(t.id),t),await this.index.updateIndex(e=>{let s=e.filter(r=>r.id!==t.id);return s.push(t),s});}async delete(t){try{await Z.unlink(this.paths.taskPath(t));}catch(e){if(e.code!=="ENOENT")throw e}await this.index.updateIndex(e=>e.filter(s=>s.id!==t));}};function ht(m){return {in_progress:0,retrying:1,review:2,todo:3,done:4,failed:5,cancelled:6}[m]}var D=class{constructor(t){this.paths=t;this.index=new w({dir:t.agentsDir,ext:".yml",itemPath:e=>t.agentPath(e)});}index;async list(){return this.index.readIndex()}async get(t){return b$1(this.paths.agentPath(t))}async getByName(t){return (await this.list()).find(s=>s.name===t)??null}async save(t){await j(this.paths.agentsDir),await c(this.paths.agentPath(t.id),t),await this.index.updateIndex(e=>{let s=e.filter(r=>r.id!==t.id);return s.push(t),s});}async delete(t){try{await Z.unlink(this.paths.agentPath(t));}catch(e){if(e.code!=="ENOENT")throw e}await this.index.updateIndex(e=>e.filter(s=>s.id!==t));}};var R=class{constructor(t){this.paths=t;}async save(t){await j(this.paths.runsDir),await e(this.paths.runPath(t.id),t);}async get(t){return d(this.paths.runPath(t))}async listAll(){return this.listFiltered(()=>true)}async listForTask(t){return this.listFiltered(e=>e.task_id===t)}async listForAgent(t){return this.listFiltered(e=>e.agent_id===t)}async appendEvent(t,e){await j(this.paths.runsDir),await f$1(this.paths.runEventsPath(t),e);}async readEvents(t){return h(this.paths.runEventsPath(t))}async readEventsTail(t,e){return i$1(this.paths.runEventsPath(t),e)}closeRunEvents(t){g$1(this.paths.runEventsPath(t));}async*streamEvents(t,e){let s=this.paths.runEventsPath(t),r=Date.now()+3e4;for(;!e?.aborted&&Date.now()<r&&!await k$1(s);)await new Promise(i=>setTimeout(i,100));if(e?.aborted||Date.now()>=r)return;let a=createReadStream(s),{readLines:n}=await import('./process-manager-33H27MQF.js');try{for await(let i of n(a)){if(e?.aborted)break;if(i.trim())try{yield JSON.parse(i);}catch{process.stderr.write(`[RunStore] skipping corrupt JSONL line: ${i.slice(0,200)}
3
+ `);}}}finally{a.destroy();}}async listFiltered(t){await j(this.paths.runsDir);let e=await l$1(this.paths.runsDir,".json"),s=64,r=[];for(let a=0;a<e.length;a+=s){let n=e.slice(a,a+s),i=await Promise.all(n.map(o=>{let c=o.endsWith(".json")?o.slice(0,-5):o;return d(this.paths.runPath(c))}));for(let o of i)o!==null&&t(o)&&r.push(o);}return r.sort((a,n)=>new Date(n.started_at).getTime()-new Date(a.started_at).getTime())}};var Q={version:1,onboardingCompleted:false,running:{},claimed:new Set,retry_queue:[],stats:{total_runs:0,total_tasks_completed:0,total_tasks_failed:0,total_tokens:{input:0,output:0,reasoning:0,total:0,cache_read:0,cache_write:0},total_runtime_ms:0}};var O=class{constructor(t){this.paths=t;}async read(){let t=await d(this.paths.statePath);if(!t)return structuredClone(Q);let e=structuredClone(Q);return {version:t.version??e.version,pid:t.pid,started_at:t.started_at,onboardingCompleted:typeof t.onboardingCompleted=="boolean"?t.onboardingCompleted:false,running:t.running&&typeof t.running=="object"?t.running:e.running,claimed:Array.isArray(t.claimed)?new Set(t.claimed):new Set(e.claimed),retry_queue:Array.isArray(t.retry_queue)?t.retry_queue:e.retry_queue,stats:{total_runs:t.stats?.total_runs??e.stats.total_runs,total_tasks_completed:t.stats?.total_tasks_completed??e.stats.total_tasks_completed,total_tasks_failed:t.stats?.total_tasks_failed??e.stats.total_tasks_failed,total_tokens:{...e.stats.total_tokens,...t.stats?.total_tokens??{}},total_runtime_ms:t.stats?.total_runtime_ms??e.stats.total_runtime_ms}}}async write(t){let e$1={...t,claimed:Array.from(t.claimed)};await e(this.paths.statePath,e$1);}};var G=class{constructor(t){this.paths=t;}async read(){let t=await b$1(this.paths.configPath);return ft(a$2,t??{})}async write(t){await c(this.paths.configPath,t);}async get(t){let e=await this.read();return jt(e,t)}async set(t,e){let s=await this.read();Mt(s,t,e),await this.write(s);}};function jt(m,t){let e=t.split("."),s=m;for(let r of e){if(s==null||typeof s!="object")return;s=s[r];}return s}function Mt(m,t,e){let s=t.split("."),r=m;for(let n=0;n<s.length-1;n++){let i=s[n];(typeof r[i]!="object"||r[i]===null)&&(r[i]={}),r=r[i];}let a=s[s.length-1];r[a]=e;}function ft(m,t){let e={...m};for(let s of Object.keys(t)){let r=t[s],a=e[s];r!=null&&typeof r=="object"&&!Array.isArray(r)&&typeof a=="object"&&a!==null&&!Array.isArray(a)?e[s]=ft(a,r):e[s]=r;}return e}var St=tt.join(homedir(),".orchestry"),wt=tt.join(St,"global.yml"),L=class{async read(){let t=await b$1(wt);if(!t)return {...P,tui:{...P.tui,notifications:{...P.tui.notifications}}};let e=t.tui,s=e?.notifications;return {tui:{activity_filter:e?.activity_filter??P.tui.activity_filter,notifications:{toast:typeof s?.toast=="boolean"?s.toast:P.tui.notifications.toast,bell:typeof s?.bell=="boolean"?s.bell:P.tui.notifications.bell}}}}async write(t){await mkdir(St,{recursive:true}),await c(wt,t);}async set(t,e){let s=await this.read();s.tui[t]=e,await this.write(s);}};var B=class m{constructor(t){this.paths=t;this.index=new w({dir:t.contextDir,ext:".json",itemPath:e=>t.contextPath(e),fileFilter:e=>e!=="_index.json"});}index;async get(t){let e=await d(this.paths.contextPath(t));return e?_t(e)?(await this.delete(t),null):e:null}static MAX_TTL_MS=720*60*60*1e3;async set(t,e$1,s){if(s!==void 0&&(!Number.isFinite(s)||s<=0||s>m.MAX_TTL_MS))throw new Error(`TTL must be a positive number up to ${m.MAX_TTL_MS}ms (30 days)`);await j(this.paths.contextDir);let r=new Date().toISOString(),a=await d(this.paths.contextPath(t)),n={key:t,value:e$1,created_at:a?.created_at??r,updated_at:r,ttl_ms:s,expires_at:s?new Date(Date.now()+s).toISOString():void 0};await e(this.paths.contextPath(t),n),await this.index.updateIndex(i=>{let o=i.filter(c=>c.key!==t);return o.push(n),o});}async delete(t){try{await Z.unlink(this.paths.contextPath(t));}catch(e){if(e.code!=="ENOENT")throw e}await this.index.updateIndex(e=>e.filter(s=>s.key!==t));}async list(){let t=await this.index.readIndex(),e=[],s=[];for(let r of t)_t(r)?e.push(r):s.push(r);return e.length>0&&(await Promise.all(e.map(r=>this.deleteFile(r.key))),await this.index.writeIndex(s)),s.sort((r,a)=>r.key.localeCompare(a.key))}async getAll(){let t=await this.list(),e={};for(let s of t)e[s.key]=s.value;return e}async deleteFile(t){try{await Z.unlink(this.paths.contextPath(t));}catch(e){if(e.code!=="ENOENT")throw e}}};function _t(m){return m.expires_at?new Date(m.expires_at).getTime()<Date.now():false}var F=class{constructor(t){this.paths=t;this.index=new w({dir:t.messagesDir,ext:".json",itemPath:e=>t.messagePath(e),fileFilter:e=>e!=="_index.json"});}index;async save(t){await j(this.paths.messagesDir),await e(this.paths.messagePath(t.id),t),await this.index.updateIndex(e=>{let s=e.filter(r=>r.id!==t.id);return s.push(t),s});}async get(t){return d(this.paths.messagePath(t))}async list(){return (await this.index.readIndex()).filter(e=>e!==null).sort((e,s)=>e.created_at.localeCompare(s.created_at))}async listPending(t){let e=await this.list(),s=Date.now();return e.filter(r=>r.status!=="pending"||r.expires_at&&new Date(r.expires_at).getTime()<s?false:r.to_agent_id===t)}async markDelivered(t){let e$1=await this.get(t);e$1&&(e$1.status="delivered",e$1.delivered_at=new Date().toISOString(),await e(this.paths.messagePath(t),e$1),await this.index.updateIndex(s=>{let r=s.filter(a=>a.id!==t);return r.push(e$1),r}));}async delete(t){try{await Z.unlink(this.paths.messagePath(t));}catch(e){if(e.code!=="ENOENT")throw e}await this.index.updateIndex(e=>e.filter(s=>s.id!==t));}async purgeExpired(){let t=await this.list(),e=Date.now(),s=t.filter(a=>{let n=a.expires_at&&new Date(a.expires_at).getTime()<e,i=a.delivered_at&&e-new Date(a.delivered_at).getTime()>36e5;return n||i}),r=new Set(s.map(a=>a.id));return await Promise.all(s.map(async a=>{try{await Z.unlink(this.paths.messagePath(a.id));}catch(n){if(n.code!=="ENOENT")throw n}})),await this.index.updateIndex(a=>a.filter(n=>!r.has(n.id))),s.length}};var N=class{constructor(t){this.paths=t;this.index=new w({dir:t.goalsDir,ext:".yml",itemPath:e=>t.goalPath(e)});}index;async list(t){return (await this.index.readIndex()).filter(r=>r!==null&&(!t?.status||r.status===t.status)).sort((r,a)=>{let n=c$1[r.status]-c$1[a.status];if(n!==0)return n;let i=a.updated_at??"",o=r.updated_at??"";return i<o?-1:i>o?1:0})}async get(t){return b$1(this.paths.goalPath(t))}async save(t){await j(this.paths.goalsDir),await c(this.paths.goalPath(t.id),t),await this.index.updateIndex(e=>{let s=e.filter(r=>r.id!==t.id);return s.push(t),s});}async delete(t){try{await Z.unlink(this.paths.goalPath(t));}catch(e){if(e.code!=="ENOENT")throw e}await this.index.updateIndex(e=>e.filter(s=>s.id!==t));}};var $=class{constructor(t){this.paths=t;}async save(t){await j(this.paths.teamsDir),await c(this.paths.teamPath(t.id),t);}async get(t){return b$1(this.paths.teamPath(t))}async getByName(t){return (await this.list()).find(s=>s.name===t)??null}async list(){await j(this.paths.teamsDir);let t=await l$1(this.paths.teamsDir,".yml");return (await Promise.all(t.map(s=>b$1(this.paths.teamPath(s.replace(".yml","")))))).filter(s=>s!==null)}async delete(t){try{await Z.unlink(this.paths.teamPath(t));}catch(e){if(e.code!=="ENOENT")throw e}}};var U=class{handlers=new Map;wildcardHandlers=new Set;maxListeners=10;warnedTypes=new Set;setMaxListeners(t){this.maxListeners=t;}getMaxListeners(){return this.maxListeners}listenerCount(t){return this.handlers.get(t)?.size??0}on(t,e){this.handlers.has(t)||this.handlers.set(t,new Set);let s=this.handlers.get(t);return s.add(e),this.maxListeners>0&&s.size>this.maxListeners&&!this.warnedTypes.has(t)&&(this.warnedTypes.add(t),console.warn(`EventBus: possible memory leak detected. ${s.size} listeners added for "${t}". Use setMaxListeners() to increase limit if this is intentional.`)),()=>this.off(t,e)}once(t,e){let s=r=>{this.off(t,s),e(r);};return this.on(t,s)}off(t,e){this.handlers.get(t)?.delete(e);}emit(t){let e=this.handlers.get(t.type);e&&this.dispatchToSet(e,t,"handler"),this.dispatchToSet(this.wildcardHandlers,t,"wildcard handler");}dispatchToSet(t,e,s){for(let r of t)try{r(e);}catch(a){console.error(`EventBus ${s} error for "${e.type}":`,a);}}onAny(t){return this.wildcardHandlers.add(t),this.maxListeners>0&&this.wildcardHandlers.size>this.maxListeners&&!this.warnedTypes.has("*")&&(this.warnedTypes.add("*"),console.warn(`EventBus: possible memory leak detected. ${this.wildcardHandlers.size} wildcard listeners added. Use setMaxListeners() to increase limit if this is intentional.`)),()=>{this.wildcardHandlers.delete(t);}}clear(){this.handlers.clear(),this.wildcardHandlers.clear(),this.warnedTypes.clear();}};var J=class{constructor(t,e,s,r,a){this.taskStore=t;this.eventBus=e;this.config=s;this.paths=r;this.agentStore=a;}async create(t){if(!t.title.trim())throw new c$2("Task title is required");let e=t.priority??this.config.defaults.task.priority;if(!Number.isInteger(e)||e<1||e>4)throw new c$2("Priority must be an integer between 1 and 4");if(t.depends_on?.length){let i=(await Promise.all(t.depends_on.map(async o=>({depId:o,exists:!!await this.taskStore.get(o)})))).filter(o=>!o.exists).map(o=>o.depId);if(i.length>0)throw new c$2(`Unknown depends_on task ID(s): ${i.join(", ")}`)}let s=await this.resolveAssignee(t.assignee),r=new Date().toISOString(),a={id:`tsk_${nanoid(7)}`,title:t.title.trim(),description:t.description?.trim()??"",status:"todo",priority:e,assignee:s,labels:t.labels??[],depends_on:t.depends_on??[],created_at:r,updated_at:r,attempts:0,max_attempts:t.max_attempts??this.config.defaults.task.max_attempts,workspace_mode:t.workspace_mode,review_criteria:t.review_criteria,scope:t.scope,goalId:t.goalId};if(t.attachments?.length&&this.paths){let n=await this.copyAttachments(a.id,t.attachments);a.attachments=n;}return await this.taskStore.save(a),this.eventBus.emit({type:"task:created",task:a}),a}async list(t){return this.taskStore.list(t)}async get(t){let e=await this.taskStore.get(t);if(!e)throw new f(t);return e}async updateStatus(t,e){let s=await this.get(t),r=s.status;if(!a$1(r,e))throw new i(t,r,e);return s.status=e,s.updated_at=new Date().toISOString(),await this.taskStore.save(s),this.eventBus.emit({type:"task:status_changed",taskId:t,from:r,to:e}),s}async assign(t,e){let s=await this.get(t);return s.assignee=await this.resolveAssignee(e),s.updated_at=new Date().toISOString(),await this.taskStore.save(s),this.eventBus.emit({type:"task:assigned",taskId:t,agentId:e}),s}async cancel(t){let e=await this.get(t);if(b$2(e.status))throw new i(t,e.status,"cancelled");return this.updateStatus(t,"cancelled")}async retry(t){let e=await this.get(t);if(e.status!=="failed"&&e.status!=="cancelled")throw new i(t,e.status,"todo");let s=e.status;return e.status="todo",e.attempts=0,e.updated_at=new Date().toISOString(),await this.taskStore.save(e),this.eventBus.emit({type:"task:status_changed",taskId:t,from:s,to:"todo"}),e}async reject(t,e){let s=await this.get(t);if(s.status!=="review")throw new i(t,s.status,"todo");let r=s.status;return s.status="todo",s.attempts=0,s.feedback=e,s.updated_at=new Date().toISOString(),await this.taskStore.save(s),this.eventBus.emit({type:"task:status_changed",taskId:t,from:r,to:"todo"}),s}async update(t,e){let s=await this.get(t);if(e.title!==void 0){if(!e.title.trim())throw new c$2("Task title cannot be empty");s.title=e.title.trim();}if(e.description!==void 0&&(s.description=e.description.trim()),e.priority!==void 0){if(!Number.isInteger(e.priority)||e.priority<1||e.priority>4)throw new c$2("Priority must be an integer between 1 and 4");s.priority=e.priority;}if(e.labels!==void 0&&(s.labels=e.labels),e.attachments?.length&&this.paths){let r=await this.copyAttachments(t,e.attachments);s.attachments=[...s.attachments??[],...r];}return s.updated_at=new Date().toISOString(),await this.taskStore.save(s),s}async delete(t){if((await this.get(t)).status==="in_progress")throw new c$2("Cannot delete a running task. Cancel it first.");if(await this.taskStore.delete(t),this.paths){let s=this.paths.taskAttachmentsDir(t);await Z.rm(s,{recursive:true,force:true});}}getAttachmentPath(t,e){if(!this.paths)throw new c$2("Paths not configured");return tt.join(this.paths.taskAttachmentsDir(t),e)}async copyAttachments(t,e){if(!this.paths)return [];let s=this.paths.taskAttachmentsDir(t);return await j(s),await Promise.all(e.map(async a=>{try{await Z.access(a);}catch{throw new c$2(`Attachment file not found: ${a}`)}})),await Promise.all(e.map(async a=>{let n=tt.basename(a);return await Z.copyFile(a,tt.join(s,n)),n}))}async incrementAttempts(t){let e=await this.get(t);return e.attempts+=1,e.updated_at=new Date().toISOString(),await this.taskStore.save(e),e}async resolveAssignee(t){if(!t)return;if(!this.agentStore)return t;if(t.startsWith("agt_")){let s=await this.agentStore.get(t);if(s)return s.id;throw new c$2(`Unknown agent ID: "${t}". No agent with this ID exists.`)}let e=await this.agentStore.getByName(t);if(e)return e.id;throw new c$2(`Unknown agent: "${t}". Use an agent ID (agt_xxx) or an exact agent name.`)}};var H=class{constructor(t,e,s,r){this.agentStore=t;this.stateStore=e;this.eventBus=s;this.config=r;}async create(t){if(!t.name.trim())throw new c$2("Agent name is required");if(await this.agentStore.getByName(t.name))throw new c$2(`Agent "${t.name}" already exists`);let s={id:`agt_${nanoid(7)}`,name:t.name.trim(),adapter:t.adapter||this.config.defaults.agent.adapter,role:t.role,config:{command:t.command,model:t.model,effort:t.effort,approval_policy:t.approval_policy??this.config.defaults.agent.approval_policy,max_turns:t.max_turns??this.config.defaults.agent.max_turns,timeout_ms:t.timeout_ms??this.config.defaults.agent.timeout_ms,stall_timeout_ms:t.stall_timeout_ms??this.config.defaults.agent.stall_timeout_ms,env:t.env,system_prompt:t.system_prompt,workspace_mode:t.workspace_mode,skills:t.skills},status:"idle",stats:{tasks_completed:0,tasks_failed:0,total_runs:0,total_runtime_ms:0}};return await this.agentStore.save(s),s}async list(){return this.agentStore.list()}async get(t){let e=await this.agentStore.get(t);if(!e)throw new g(t);return e}async remove(t){let e=await this.get(t);if(e.status==="running"){let s=await this.stateStore.read();if(Object.values(s.running).some(a=>a.agent_id===t))throw new c$2("Cannot remove a running agent. Stop it first.");e.status="idle",await this.agentStore.save(e);}await this.agentStore.delete(t);}async update(t,e){let s=await this.get(t);if(e.name!==void 0){if(!e.name.trim())throw new c$2("Agent name cannot be empty");let r=await this.agentStore.getByName(e.name.trim());if(r&&r.id!==t)throw new c$2(`Agent "${e.name}" already exists`);s.name=e.name.trim();}return e.role!==void 0&&(s.role=e.role||void 0),e.model!==void 0&&(s.config.model=e.model||void 0),e.effort!==void 0&&(s.config.effort=e.effort||void 0),e.approval_policy!==void 0&&(s.config.approval_policy=e.approval_policy),await this.agentStore.save(s),s}async disable(t){return this.setStatus(t,"disabled")}async enable(t){return this.setStatus(t,"idle")}async setAutonomous(t,e){let s=await this.get(t);return s.autonomous=e,await this.agentStore.save(s),this.eventBus.emit({type:"agent:autonomous_toggled",agentId:t,autonomous:e}),s}async setStatus(t,e){let s=await this.get(t);return s.status=e,await this.agentStore.save(s),s}async updateStats(t,e){let s=await this.get(t);return Object.assign(s.stats,e),await this.agentStore.save(s),s}async findBestAgent(t){let e=await this.agentStore.list(),s=e.filter(n=>n.status==="idle");if(s.length===0)return null;if(t.assignee){let n=e.find(i=>i.id===t.assignee||i.name===t.assignee);return n&&n.status==="idle"?n:null}let r=t.labels?.length?t.labels.map(n=>n.toLowerCase()):void 0,a=s.map(n=>{let i=0;if(r&&n.config.skills?.length){let c=new Set(n.config.skills.map(d=>d.toLowerCase()));for(let d of r)c.has(d)&&(i+=50);}if(r&&n.role){let c=n.role.toLowerCase();r.some(d=>c.includes(d))&&(i+=30);}n.status==="idle"&&(i+=20);let o=n.stats.tasks_completed+n.stats.tasks_failed;return o>0&&(i+=Math.round(n.stats.tasks_completed/o*10)),{agent:n,score:i}});return a.sort((n,i)=>i.score-n.score),a[0]?.agent??null}};var q=class{constructor(t,e){this.runStore=t;this.eventBus=e;}async create(t){let e={id:`run_${nanoid(7)}`,task_id:t.taskId,agent_id:t.agentId,attempt:t.attempt,status:"preparing",started_at:new Date().toISOString(),workspace_path:t.workspacePath,prompt:t.prompt};return await this.runStore.save(e),e}async get(t){return this.runStore.get(t)}async start(t,e){let s=await this.runStore.get(t);if(!s)throw new Error(`Run not found: ${t}`);return s.status="running",s.pid=e,await this.runStore.save(s),this.eventBus.emit({type:"agent:started",agentId:s.agent_id,taskId:s.task_id,runId:t}),s}async finish(t,e,s,r){let a=await this.runStore.get(t);if(!a)throw new Error(`Run not found: ${t}`);return a.status=e,a.finished_at=new Date().toISOString(),a.tokens=s,a.error=r,await this.runStore.save(a),this.eventBus.emit({type:"agent:completed",runId:t,agentId:a.agent_id,success:e==="succeeded"}),a}async appendEvent(t,e){await this.runStore.appendEvent(t,e);}async listAll(){return this.runStore.listAll()}async listForTask(t){return this.runStore.listForTask(t)}async listForAgent(t){return this.runStore.listForAgent(t)}async readEvents(t){return this.runStore.readEvents(t)}async readEventsTail(t,e){return this.runStore.readEventsTail(t,e)}async getLastFailedRunContext(t){let s=(await this.runStore.listForTask(t)).filter(n=>n.status==="failed").sort((n,i)=>(i.finished_at??"").localeCompare(n.finished_at??""))[0];if(!s)return null;let r=s.error??"Unknown error",a="";try{a=(await this.runStore.readEventsTail(s.id,50)).filter(i=>i.type==="agent_output"||i.type==="error").map(i=>typeof i.data=="string"?i.data:JSON.stringify(i.data)).join(`
4
+ `);}catch{}return {error:r,output:a}}};var Y=class{constructor(t,e,s,r){this.messageStore=t;this.agentStore=e;this.teamStore=s;this.eventBus=r;}async send(t){if(!t.body.trim())throw new c$2("Message body is required");let e=t.ttl_ms??864e5;if(e<=0||e>6048e5)throw new c$2(`TTL must be between 1ms and ${6048e5}ms`);if(!await this.agentStore.get(t.from_agent_id)&&t.from_agent_id!=="cli")throw new c$2(`Sender agent not found: ${t.from_agent_id}`);let r=new Date,a={channel:t.channel,from_agent_id:t.from_agent_id,subject:(t.subject||"(no subject)").slice(0,200),body:t.body.slice(0,4e3),created_at:r.toISOString(),expires_at:new Date(r.getTime()+e).toISOString(),status:"pending",team_id:t.team_id,reply_to:t.reply_to},n=[];if(t.channel==="broadcast"){let i=await this.agentStore.list();if(t.team_id){let d=await this.teamStore.get(t.team_id);if(d){let k=new Set(d.members.map(S=>S.agent_id));i=i.filter(S=>k.has(S.id));}}let c=i.filter(d=>d.id!==t.from_agent_id&&d.status!=="disabled").map(d=>({...a,id:`msg_${nanoid(7)}`,to_agent_id:d.id}));await Promise.all(c.map(d=>this.messageStore.save(d)));for(let d of c)n.push(d),this.emitSent(d);}else if(t.channel==="lead"){if(!t.team_id)throw new c$2("team_id is required for lead channel");let i=await this.teamStore.get(t.team_id);if(!i)throw new c$2(`Team not found: ${t.team_id}`);let o={...a,id:`msg_${nanoid(7)}`,to_agent_id:i.lead_agent_id};await this.messageStore.save(o),n.push(o),this.emitSent(o);}else {if(!t.to_agent_id)throw new c$2("to_agent_id is required for direct messages");if(!await this.agentStore.get(t.to_agent_id))throw new c$2(`Recipient agent not found: ${t.to_agent_id}`);let o={...a,id:`msg_${nanoid(7)}`,to_agent_id:t.to_agent_id};await this.messageStore.save(o),n.push(o),this.emitSent(o);}return n}async drainMailbox(t,e){let s=await this.messageStore.listPending(t);await Promise.all(s.map(r=>this.messageStore.markDelivered(r.id)));for(let r of s)this.eventBus.emit({type:"message:delivered",messageId:r.id,toAgentId:t,taskId:e});return s}async listAll(){return this.messageStore.list()}async listPendingForAgent(t){return this.messageStore.listPending(t)}async listForAgent(t){return (await this.messageStore.list()).filter(s=>s.to_agent_id===t||s.from_agent_id===t)}async purgeExpired(){return this.messageStore.purgeExpired()}emitSent(t){this.eventBus.emit({type:"message:sent",messageId:t.id,fromAgentId:t.from_agent_id,toAgentId:t.to_agent_id,channel:t.channel});}};var Ut={active:["paused","achieved","abandoned"],paused:["active","achieved","abandoned"],achieved:[],abandoned:[]},z=class{constructor(t,e,s,r,a){this.goalStore=t;this.eventBus=e;this.agentService=s;this.taskService=r;this.contextStore=a;}async create(t){if(!t.title.trim())throw new c$2("Goal title is required");let e=new Date().toISOString(),s={id:`goal_${nanoid(7)}`,title:t.title.trim(),description:t.description?.trim()??"",status:"active",assignee:t.assignee,created_at:e,updated_at:e};return await this.goalStore.save(s),this.eventBus.emit({type:"goal:created",goalId:s.id,title:s.title}),s.assignee&&await this.enableAutonomous(s.assignee),s}async list(t){return this.goalStore.list(t)}async get(t){let e=await this.goalStore.get(t);if(!e)throw new j$1(t);return e}async updateStatus(t,e,s){let r=await this.get(t),a$1=r.status;if(!Ut[a$1].includes(e))throw new c$2(`Cannot transition goal from '${a$1}' to '${e}'`);if(e==="achieved"&&this.taskService){let i=(await this.taskService.list({goalId:t})).filter(o=>!b$2(o.status)&&!o.labels?.includes(a));if(i.length>0)if(s?.force){let o=i.filter(d=>d.status!=="in_progress"),c=i.filter(d=>d.status==="in_progress");if(await Promise.all(o.map(d=>this.taskService.cancel(d.id).catch(()=>{}))),c.length>0){let d=c.map(k=>`${k.id} (in_progress)`).join(", ");throw new k(t,c.length,d)}}else {let o=i.map(c=>`${c.id} (${c.status})`).join(", ");throw new k(t,i.length,o)}}return r.status=e,r.updated_at=new Date().toISOString(),await this.goalStore.save(r),this.eventBus.emit({type:"goal:status_changed",goalId:t,from:a$1,to:e}),r.assignee&&(e==="paused"?(await this.maybeDisableAutonomous(r.assignee),await this.cancelPendingAutonomousTasks(r.assignee)):e==="active"&&a$1==="paused"?await this.enableAutonomous(r.assignee):b$3(e)&&await this.maybeDisableAutonomous(r.assignee)),r}async update(t,e){let s=await this.get(t),r=s.assignee;if(e.title!==void 0){if(!e.title.trim())throw new c$2("Goal title cannot be empty");s.title=e.title.trim();}e.description!==void 0&&(s.description=e.description.trim()),e.assignee!==void 0&&(s.assignee=e.assignee||void 0),s.updated_at=new Date().toISOString(),await this.goalStore.save(s),this.eventBus.emit({type:"goal:updated",goalId:t});let a=s.assignee;if(a!==r){let n=[];a&&n.push(this.enableAutonomous(a)),r&&n.push(this.maybeDisableAutonomous(r)),await Promise.all(n);}return s}async delete(t){let e=await this.get(t),{assignee:s}=e;await this.goalStore.delete(t),this.eventBus.emit({type:"goal:deleted",goalId:t}),s&&await this.maybeDisableAutonomous(s);}async listTasksForGoal(t){return this.taskService?.list({goalId:t})??[]}async getProgressReport(t){return this.contextStore?(await this.contextStore.get(`${t}-progress`))?.value:void 0}async enableAutonomous(t){if(this.agentService)try{await this.agentService.setAutonomous(t,!0);}catch{}}async hasActiveGoalsForAgent(t){return (await this.goalStore.list({status:"active"})).some(s=>s.assignee===t)}async cancelPendingAutonomousTasks(t){if(this.taskService)try{let[e,s]=await Promise.all([this.taskService.list({status:"todo"}),this.taskService.list({status:"retrying"})]),r=[...e,...s].filter(a$1=>a$1.assignee===t&&a$1.labels?.includes(a));await Promise.all(r.map(a=>this.taskService.cancel(a.id).catch(()=>{})));}catch{}}async maybeDisableAutonomous(t){if(this.agentService)try{await this.hasActiveGoalsForAgent(t)||await this.agentService.setAutonomous(t,!1);}catch{}}};var xt={auto_claim:true,message_ttl_ms:864e5};var W=class{constructor(t,e,s,r){this.teamStore=t;this.agentStore=e;this.taskStore=s;this.eventBus=r;}async create(t){if(!t.name.trim())throw new c$2("Team name is required");if(!await this.agentStore.get(t.lead_agent_id))throw new c$2(`Lead agent not found: ${t.lead_agent_id}`);if(await this.teamStore.getByName(t.name.trim()))throw new c$2(`Team "${t.name}" already exists`);let r=new Date().toISOString(),a={agent_id:t.lead_agent_id,role:"lead",joined_at:r},n=[];for(let o of t.member_agent_ids??[]){if(o===t.lead_agent_id)continue;if(!await this.agentStore.get(o))throw new c$2(`Member agent not found: ${o}`);n.push({agent_id:o,role:"member",joined_at:r});}let i={id:`team_${nanoid(7)}`,name:t.name.trim(),description:t.description,status:"active",members:[a,...n],task_pool:[],lead_agent_id:t.lead_agent_id,created_at:r,updated_at:r,config:{...xt,...t.config??{}}};await this.teamStore.save(i),this.eventBus.emit({type:"team:created",teamId:i.id,name:i.name,leadAgentId:i.lead_agent_id});for(let o of n)this.eventBus.emit({type:"team:member_joined",teamId:i.id,agentId:o.agent_id});return i}async get(t){let e=await this.teamStore.get(t);if(!e)throw new l(t);return e}async list(){return this.teamStore.list()}async join(t,e){let s=await this.get(t);if(s.members.some(a=>a.agent_id===e))throw new c$2(`Agent ${e} is already a member of team ${t}`);if(!await this.agentStore.get(e))throw new c$2(`Agent not found: ${e}`);return s.members.push({agent_id:e,role:"member",joined_at:new Date().toISOString()}),s.updated_at=new Date().toISOString(),await this.teamStore.save(s),this.eventBus.emit({type:"team:member_joined",teamId:t,agentId:e}),s}async leave(t,e){let s=await this.get(t);if(e===s.lead_agent_id)throw new c$2("Lead cannot leave team. Disband the team or transfer lead first.");return s.members=s.members.filter(r=>r.agent_id!==e),s.updated_at=new Date().toISOString(),await this.teamStore.save(s),this.eventBus.emit({type:"team:member_left",teamId:t,agentId:e}),s}async addTask(t,e){let s=await this.get(t);if(!await this.taskStore.get(e))throw new c$2(`Task not found: ${e}`);return s.task_pool.includes(e)||(s.task_pool.push(e),s.updated_at=new Date().toISOString(),await this.teamStore.save(s),this.eventBus.emit({type:"team:task_added",teamId:t,taskId:e})),s}async removeTask(t,e){let s=await this.get(t);return s.task_pool=s.task_pool.filter(r=>r!==e),s.updated_at=new Date().toISOString(),await this.teamStore.save(s),s}async setLead(t,e){let s=await this.get(t),r=s.members.find(n=>n.agent_id===e);if(!r)throw new c$2(`Agent ${e} is not a member of team ${t}`);let a=s.members.find(n=>n.agent_id===s.lead_agent_id);return a&&(a.role="member"),r.role="lead",s.lead_agent_id=e,s.updated_at=new Date().toISOString(),await this.teamStore.save(s),s}async disband(t){let e=await this.get(t);e.status="disbanded",e.updated_at=new Date().toISOString(),await this.teamStore.save(e),this.eventBus.emit({type:"team:disbanded",teamId:t});}async findTeamForAgent(t){return (await this.teamStore.list()).find(s=>s.status==="active"&&s.members.some(r=>r.agent_id===t))??null}};async function Ht(m){let t=new b(m.projectRoot),e=new G(t),s=new L,[,r]=await Promise.all([t.requireInit(),e.read()]),a=new M(t),n=new D(t),i=new R(t),o=new O(t),c=new B(t),d=new F(t),k=new N(t),S=new $(t),v=new U,b$1=new J(a,v,r,t,n),I=new H(n,o,v,r),h=new q(i,v),A=new Y(d,n,S,v),E=new z(k,v,I,b$1,c),C=new W(S,n,a,v);return {context:m,paths:t,config:r,taskStore:a,agentStore:n,runStore:i,stateStore:o,configStore:e,globalConfigStore:s,globalConfig:P,contextStore:c,messageStore:d,goalStore:k,teamStore:S,eventBus:v,taskService:b$1,agentService:I,runService:h,messageService:A,goalService:E,teamService:C}}async function qt(m){let t=await Ht(m),e=await t.globalConfigStore.read();t.globalConfig=e;let[{ProcessManager:s},{AdapterRegistry:r},{ClaudeAdapter:a},{CodexAdapter:n},{CursorAdapter:i},{ShellAdapter:o},{OpenCodeAdapter:c},{PiAdapter:d},{WorkspaceManager:k},{LiquidTemplateEngine:S},{SkillLoader:v},{Orchestrator:b},{DoctorService:I}]=await Promise.all([import('./process-manager-33H27MQF.js'),import('./registry-BO2PPRNG.js'),import('./claude-PH7LT3OH.js'),import('./codex-URQN4JLZ.js'),import('./cursor-EMX3ECDY.js'),import('./shell-NPNTWDMU.js'),import('./opencode-K22RCQ5C.js'),import('./pi-XEINSHUN.js'),import('./workspace-manager-ZI5SVXJU.js'),import('./template-engine-VLIOJ3WX.js'),import('./skill-loader-IGRIELEM.js'),import('./orchestrator-AVJ23Q5T.js'),import('./doctor-service-PB7YBH3F.js')]),h=new s,A=new S,E=new v,C=new k(m.projectRoot,t.paths.root,h),_=new r;_.register(new a(h)),_.register(new n(h)),_.register(new i(h)),_.register(new o(h)),_.register(new c(h)),_.register(new d(h));let Tt=new I(_,h,m.projectRoot),bt=new b({taskStore:t.taskStore,agentStore:t.agentStore,runStore:t.runStore,stateStore:t.stateStore,adapterRegistry:_,workspaceManager:C,templateEngine:A,processManager:h,eventBus:t.eventBus,taskService:t.taskService,agentService:t.agentService,runService:t.runService,contextStore:t.contextStore,messageService:t.messageService,goalStore:t.goalStore,skillLoader:E,config:t.config,projectRoot:m.projectRoot,lockPath:t.paths.lockPath});return {...t,processManager:h,adapterRegistry:_,workspaceManager:C,templateEngine:A,skillLoader:E,doctorService:Tt,orchestrator:bt}}async function Cs(m){return qt(m)}export{Cs as buildContainer,qt as buildFullContainer,Ht as buildLightContainer};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import {a as a$4}from'./chunk-SJG3HXO5.js';import {a as a$5}from'./chunk-HMMPM7MF.js';import {p,c,q}from'./chunk-64WUDYEM.js';import {b}from'./chunk-6E6DC7OE.js';import'./chunk-ZMLF5HI5.js';import {a as a$1}from'./chunk-CDFA4IIQ.js';import {a as a$2}from'./chunk-DEHFYICU.js';import {a as a$3}from'./chunk-ITMAWW3J.js';import'./chunk-C7C7Q7XO.js';import'./chunk-P4JTJBWO.js';import'./chunk-LRYVT4D4.js';import {a}from'./chunk-6MJ7V6VY.js';import a$6 from'chalk';function z(y,t){y.command("doctor").description("Check adapters and dependencies").action(async()=>{let c$1,n,d=false;if(t)c$1=t.doctorService,n=t.paths,d=true;else {let o=new a,e=new a$1;e.register(new a$2(o)),e.register(new a$3(o)),e.register(new a$4(o)),c$1=new a$5(e,o,process.cwd()),n=new b(process.cwd());}console.log(),console.log(` ${p("orch doctor")} \xB7 checking adapters and dependencies`),console.log();let i=await c$1.runAll();if(t?.context.json){console.log(JSON.stringify(i,null,2));return}for(let o of i.checks){let e=o.status==="ok"?a$6.ansi256(72)(c("done")):o.status==="fail"?a$6.ansi256(167)(c("failed")):q("\u2014"),l=o.detail?q(` ${o.detail}`):"";console.log(` ${e} ${o.name.padEnd(12)}${l}`);}if(n){let o=await n.isInitialized();if(o&&d){let e=await t.agentService.list(),l=await t.taskService.list();console.log(),console.log(` ${a$6.ansi256(72)(c("done"))} .orchestry/ ${q(`exists \xB7 ${e.length} agents \xB7 ${l.length} tasks`)}`);}else o||(console.log(),console.log(` ${a$6.ansi256(167)(c("failed"))} .orchestry/ ${q("not found \u2014 run: orch init")}`));}console.log(),console.log(` ${i.adaptersReady} of ${i.adaptersTotal} adapters ready`),console.log();});}export{z as registerDoctorCommand};
package/dist/index.d.ts CHANGED
@@ -558,8 +558,8 @@ declare function resolveFailureStatus(task: Task): TaskStatus;
558
558
  * instead of hardcoded model strings. At instantiation time, the actual model
559
559
  * is resolved based on the user's chosen adapter.
560
560
  */
561
- /** The five supported adapter kinds. */
562
- type AdapterKind = 'claude' | 'opencode' | 'codex' | 'cursor' | 'shell';
561
+ /** The supported adapter kinds. */
562
+ type AdapterKind = 'claude' | 'opencode' | 'codex' | 'cursor' | 'pi' | 'shell';
563
563
  /**
564
564
  * Semantic capability tiers — adapter-agnostic.
565
565
  * capable — most powerful / highest quality (opus, gpt-5.4)
@@ -1012,6 +1012,35 @@ interface ExecuteParams {
1012
1012
  config: AgentConfig;
1013
1013
  signal?: AbortSignal;
1014
1014
  }
1015
+ /**
1016
+ * Canonical `data` shape per AgentEvent type. Each adapter should emit `data`
1017
+ * that matches its event's row below so that downstream consumers (TUI logs,
1018
+ * `orch logs` CLI, serve daemon) can render events without knowing adapter
1019
+ * internals.
1020
+ *
1021
+ * | type | data shape |
1022
+ * |-------------|---------------------------------------------------|
1023
+ * | output | { text: string, raw?: unknown } |
1024
+ * | tool_call | { name: string, input?: unknown, raw?: unknown } |
1025
+ * | command | { command: string, result?: unknown, raw?: unknown } |
1026
+ * | file_change | { paths: string[], raw?: unknown } |
1027
+ * | error | { message: string, raw?: unknown } |
1028
+ * | done | { result?: string, raw?: unknown } |
1029
+ *
1030
+ * - `raw` is an optional escape hatch for the full provider payload; logs
1031
+ * renderers must not include it in the default summary.
1032
+ * - Adapters should emit ONE `output` per logical assistant message (per
1033
+ * text-block or per turn), not per-character delta. Use adapter-local state
1034
+ * to aggregate streaming deltas before emitting.
1035
+ * - Intermediate progress events (tool-in-flight, "thinking" pings) should be
1036
+ * dropped at the adapter boundary — they belong in adapter-specific UIs,
1037
+ * not in the orchestrator event stream.
1038
+ *
1039
+ * Existing adapters predate this contract and emit a variety of shapes
1040
+ * (claude/cursor: full `parsed.message`; codex: `item`). The TUI renderer
1041
+ * (`formatAgentOutput` in src/tui/App.tsx) is defensive and accepts both
1042
+ * canonical and legacy shapes during the migration window.
1043
+ */
1015
1044
  interface AgentEvent {
1016
1045
  type: 'output' | 'file_change' | 'command' | 'tool_call' | 'error' | 'done';
1017
1046
  timestamp: string;
package/dist/index.js CHANGED
@@ -38,6 +38,11 @@ var MODEL_TIER_MAP = {
38
38
  balanced: "auto",
39
39
  fast: "auto"
40
40
  },
41
+ pi: {
42
+ capable: "openai-codex/gpt-5.5",
43
+ balanced: "openai-codex/gpt-5.5",
44
+ fast: "openai-codex/gpt-5.5"
45
+ },
41
46
  shell: {
42
47
  capable: "",
43
48
  balanced: "",
@@ -58,7 +63,7 @@ function isAdapterKind(value) {
58
63
  function isModelTier(value) {
59
64
  return value === "capable" || value === "balanced" || value === "fast";
60
65
  }
61
- var SUPPORTED_ADAPTERS = ["claude", "opencode", "codex", "cursor", "shell"];
66
+ var SUPPORTED_ADAPTERS = ["claude", "opencode", "codex", "cursor", "pi", "shell"];
62
67
 
63
68
  // src/domain/agent-shop.ts
64
69
  var BACKEND_DEV_ROLE = `Backend engineer \u2014 builds APIs, services, database layers, and server-side business logic.
@@ -2538,6 +2543,7 @@ async function buildFullContainer(context) {
2538
2543
  { CursorAdapter },
2539
2544
  { ShellAdapter },
2540
2545
  { OpenCodeAdapter },
2546
+ { PiAdapter },
2541
2547
  { WorkspaceManager },
2542
2548
  { LiquidTemplateEngine },
2543
2549
  { SkillLoader: SkillLoader2 },
@@ -2551,6 +2557,7 @@ async function buildFullContainer(context) {
2551
2557
  import('./cursor-O6M6XOMT.js'),
2552
2558
  import('./shell-C2J4AIAV.js'),
2553
2559
  import('./opencode-HOX5TCMD.js'),
2560
+ import('./pi-GFJCLRZJ.js'),
2554
2561
  import('./workspace-manager-QH27FF55.js'),
2555
2562
  import('./template-engine-XOH3FZPU.js'),
2556
2563
  import('./skill-loader-RHCFIK74.js'),
@@ -2571,6 +2578,7 @@ async function buildFullContainer(context) {
2571
2578
  adapterRegistry.register(new CursorAdapter(processManager));
2572
2579
  adapterRegistry.register(new ShellAdapter(processManager));
2573
2580
  adapterRegistry.register(new OpenCodeAdapter(processManager));
2581
+ adapterRegistry.register(new PiAdapter(processManager));
2574
2582
  const doctorService = new DoctorService(adapterRegistry, processManager, context.projectRoot);
2575
2583
  const orchestrator = new Orchestrator2({
2576
2584
  taskStore: light.taskStore,