octomux 1.0.32 → 1.0.34
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-server/agents-75BBHCTY.js +1 -0
- package/dist-server/chunk-3PYPZRQV.js +1 -0
- package/dist-server/{chunk-RB2T3IO7.js → chunk-4DGDU2NU.js} +22 -22
- package/dist-server/{chunk-O2SQP4SR.js → chunk-4GEKZIZ6.js} +1 -1
- package/dist-server/{chunk-RHMOEXMR.js → chunk-BTEWK6EA.js} +10 -10
- package/dist-server/chunk-FJPTEYLR.js +1 -0
- package/dist-server/{chunk-6WY5EP6F.js → chunk-MCI4HOI7.js} +1 -1
- package/dist-server/chunk-MYIYBV6O.js +16 -0
- package/dist-server/{chunk-PBZCZYAH.js → chunk-NHDUWYXX.js} +1 -1
- package/dist-server/{chunk-YMZYMBMF.js → chunk-NUVE5API.js} +1 -1
- package/dist-server/chunk-OSXDDM27.js +1 -0
- package/dist-server/{chunk-34KJHQCF.js → chunk-RFWGJ3HT.js} +1 -1
- package/dist-server/chunk-TWPYSNU6.js +1 -0
- package/dist-server/{chunk-5XTSTJXV.js → chunk-YKFMOBXG.js} +2 -2
- package/dist-server/{chunk-L74QMQAV.js → chunk-ZV3CXK7O.js} +1 -1
- package/dist-server/claude-code-SUTWME7T.js +1 -0
- package/dist-server/harnesses-ACMXKLJO.js +1 -0
- package/dist-server/hook-settings-VQOP567H.js +1 -0
- package/dist-server/hooks-install-5WIG6NCP.js +1 -0
- package/dist-server/index.js +58 -58
- package/dist-server/{prefill-3FPWBCW4.js → prefill-IKIJSGHJ.js} +1 -1
- package/dist-server/{preflight-KHWEEL74.js → preflight-W4357G4A.js} +1 -1
- package/dist-server/{publish-review-TFPK32KX.js → publish-review-3X766STN.js} +1 -1
- package/dist-server/settings-VDSTIV6M.js +1 -0
- package/dist-server/setup-status-TDHBDU7E.js +1 -0
- package/dist-server/startup.js +1 -1
- package/dist-server/store-7ATWFPHP.js +1 -0
- package/dist-server/{teams-QXITPB5J.js → teams-DOJN7H42.js} +1 -1
- package/package.json +5 -5
- package/scripts/electron-adhoc-sign.cjs +34 -0
- package/dist-server/agents-XWAPBJ6K.js +0 -1
- package/dist-server/chunk-72XPVTY6.js +0 -16
- package/dist-server/chunk-E5HYNQ6D.js +0 -1
- package/dist-server/chunk-F5R6D6FU.js +0 -1
- package/dist-server/chunk-YUNRZQSW.js +0 -1
- package/dist-server/claude-code-FPRNRVIA.js +0 -1
- package/dist-server/harnesses-ZAGCSSES.js +0 -1
- package/dist-server/hook-settings-BSWHE3FL.js +0 -1
- package/dist-server/hooks-install-KIDJPWBY.js +0 -1
- package/dist-server/settings-2RRBPIQP.js +0 -1
- package/dist-server/setup-status-LKN6RF2T.js +0 -1
- package/dist-server/store-VYXJD5ZW.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a,b,c,d,e,f,g,h}from"./chunk-3PYPZRQV.js";import"./chunk-TWPYSNU6.js";export{f as createAgent,h as deleteAgent,c as getAgent,a as isBuiltInAgent,b as listAgents,e as resetAgent,d as saveAgent,g as syncAgents};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as p}from"./chunk-TWPYSNU6.js";import s from"fs";import o from"path";import{fileURLToPath as w}from"url";var h=o.dirname(w(import.meta.url));function d(){return o.resolve(h,"..","agents")}function m(){return process.env.OCTOMUX_AGENTS_DIR||o.join(p(),"agents")}function g(t){let i=t.match(/^---\n([\s\S]*?)\n---/);if(!i)return{name:"",description:""};let n=i[1],r=n.match(/^name:\s*(.+)$/m),e=n.match(/^description:\s*(.+)$/m);return{name:r?r[1].trim():"",description:e?e[1].trim():""}}function C(t){return s.existsSync(o.join(d(),`${t}.md`))}async function c(t){try{return await s.promises.access(t),!0}catch{return!1}}async function j(){let t=d(),i=m(),n=new Map;if(await c(t)){let r=await s.promises.readdir(t);for(let e of r){if(!e.endsWith(".md"))continue;let a=e.replace(".md",""),u=await s.promises.readFile(o.join(t,e),"utf-8"),f=g(u);n.set(a,{name:a,description:f.description,isCustom:!1})}}if(await c(i)){let r=await s.promises.readdir(i);for(let e of r){if(!e.endsWith(".md"))continue;let a=e.replace(".md",""),u=await s.promises.readFile(o.join(i,e),"utf-8"),f=g(u),l=n.get(a);n.set(a,{name:a,description:f.description||l?.description||"",isCustom:!0})}}return Array.from(n.values()).sort((r,e)=>r.name.localeCompare(e.name))}async function v(t){let i=o.join(d(),`${t}.md`),n=o.join(m(),`${t}.md`),r=await c(i),e=await c(n);if(!r&&!e)throw new Error(`Agent not found: ${t}`);let a=r?await s.promises.readFile(i,"utf-8"):"",u=e?await s.promises.readFile(n,"utf-8"):null;return{name:t,content:u??a,defaultContent:a,isCustom:e}}async function A(t,i){let n=m();await s.promises.mkdir(n,{recursive:!0}),await s.promises.writeFile(o.join(n,`${t}.md`),i,"utf-8")}async function b(t){let i=o.join(m(),`${t}.md`);try{await s.promises.unlink(i)}catch(n){if(n.code==="ENOENT")return;throw n}}async function E(t,i){let n=o.join(m(),`${t}.md`);if(await c(n))throw new Error(`Agent already exists: ${t}`);await A(t,i)}async function D(t){let{claudeCodeHarness:i}=await import("./claude-code-SUTWME7T.js");await i.syncAgents(t??process.cwd())}async function I(t){let i=o.join(d(),`${t}.md`);if(await c(i))throw new Error(`Cannot delete built-in agent: ${t}. Use reset to restore defaults.`);let n=o.join(m(),`${t}.md`);if(!await c(n))throw new Error(`Agent not found: ${t}`);await s.promises.unlink(n)}export{C as a,j as b,v as c,A as d,b as e,E as f,D as g,I as h};
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import{a as A}from"./chunk-BYZCD2AS.js";import{a as v}from"./chunk-G45FZHCE.js";import{a as u,d as I,g as
|
|
1
|
+
import{a as A}from"./chunk-BYZCD2AS.js";import{a as v}from"./chunk-G45FZHCE.js";import{a as u,d as I,g as S}from"./chunk-MYIYBV6O.js";import{b as C}from"./chunk-OSXDDM27.js";import{a as f}from"./chunk-BTEWK6EA.js";import{a as F}from"./chunk-FJPTEYLR.js";import{a as W}from"./chunk-TWPYSNU6.js";import{execFile as he}from"child_process";import{promisify as fe}from"util";import X from"crypto";import b from"path";import w from"fs";import{nanoid as O}from"nanoid";import{execFile as ie}from"child_process";import{promisify as oe}from"util";var J=oe(ie);async function V(e){let t=f(),n=t.prepare("SELECT * FROM repo_configs WHERE repo_path = ?").get(e);if(n)return n;let i=null;try{let{stdout:s}=await J("git",["-C",e,"symbolic-ref","refs/remotes/origin/HEAD"]);i=s.trim().replace("refs/remotes/origin/","")}catch{let s=["main","master","staging"],r=(await Promise.all(s.map(a=>J("git",["-C",e,"rev-parse","--verify",a]).then(()=>!0).catch(()=>!1)))).findIndex(a=>a);r>=0&&(i=s[r])}return t.prepare("INSERT INTO repo_configs (repo_path, base_branch) VALUES (?, ?) RETURNING *").get(e,i)}function ve(e,t){let n=f(),i=n.prepare("SELECT * FROM repo_configs WHERE repo_path = ?").get(e);if(!i)throw new Error(`No config found for repo: ${e}`);let s=[],o=[];for(let[r,a]of Object.entries(t))a!==void 0&&(s.push(`${r} = ?`),o.push(a));return s.length>0?(s.push("updated_at = datetime('now')"),o.push(e),n.prepare(`UPDATE repo_configs SET ${s.join(", ")} WHERE repo_path = ? RETURNING *`).get(...o)):i}function Ae(){return f().prepare("SELECT * FROM repo_configs ORDER BY repo_path").all()}function ae(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null&&typeof n.integration=="string"&&typeof n.pattern=="string"):[]}catch{return[]}}function K(e,t,n){let i=ae(t.ref_inference_json);if(i.length===0)return[];let s=new Set,o=[];for(let r of i){if(s.has(r.integration))continue;let a;try{a=new RegExp(r.pattern)}catch{continue}let d=e.match(a);if(!d)continue;let l=d[1]??d[0],E=r.url_template?r.url_template.replace("{ref}",l):void 0;s.add(r.integration),o.push({task_id:n,integration:r.integration,ref:l,url:E??null,metadata:null,created_at:new Date().toISOString()})}return o}import de from"crypto";import z from"path";import N from"fs";import{nanoid as ce}from"nanoid";var y=F("chats");function le(){return z.join(W(),"chats")}function U(e){return z.join(le(),e)}function G(e){return`octomux-chat-${e}`}async function Ve(e={}){let t=f(),n=ce(12),i=e.label??"Chat",s=e.cwd??U(n),o=e.agent??null;N.mkdirSync(s,{recursive:!0});let r=G(n),a=S(e.harnessId??null),d=n,l=de.randomBytes(32).toString("hex"),E=a.resolveFlags(await C()),m,h;if(a.sessionIdMode==="orchestrator-assigned"){let _=a.newSessionId();m=_,h=_}else m=null,h=a.newSessionId();t.prepare(`INSERT INTO agents
|
|
2
2
|
(id, task_id, window_index, label, status, harness_id, harness_session_id,
|
|
3
3
|
hook_token, hook_activity, tmux_session, agent, created_at)
|
|
4
|
-
VALUES (?, NULL, 0, ?, 'running', ?, ?, ?, 'active', ?, ?, datetime('now'))`).run(n,i,a.id,m,l,r,o);try{await a.syncAgents(s),await a.installHooks(s,v(),l),await u(["new-session","-d","-s",r,"-c",s]),await u(["set-option","-t",r,"aggressive-resize","on"]);let x=a.buildLaunchCommand({sessionId:h,agent:o,flags:E,workspacePath:s}),p=null,g=e.prompt?.trim();if(g&&(p=
|
|
4
|
+
VALUES (?, NULL, 0, ?, 'running', ?, ?, ?, 'active', ?, ?, datetime('now'))`).run(n,i,a.id,m,l,r,o);try{await a.syncAgents(s),await a.installHooks(s,v(),l),await u(["new-session","-d","-s",r,"-c",s]),await u(["set-option","-t",r,"aggressive-resize","on"]);let x=a.buildLaunchCommand({sessionId:h,agent:o,flags:E,workspacePath:s}),p=null,g=e.prompt?.trim();if(g&&(p=z.join(s,`.claude-prompt-${d}`),N.writeFileSync(p,g,{mode:384,flag:"wx"}),x+=` "$(cat ${I(p)})"`),await u(["send-keys","-t",r,x,"Enter"]),p){let R=p;setTimeout(()=>{try{N.unlinkSync(R)}catch{}},3e4)}y.info({chat_id:n,tmux_session:r,cwd:s,agent:o,harness:a.id,harness_session_id:m,operation:"createChat"},"createChat: complete")}catch(_){throw y.error({chat_id:n,operation:"createChat",err:_},"createChat: failed"),t.prepare("UPDATE agents SET status = 'stopped' WHERE id = ?").run(n),_}return t.prepare("SELECT * FROM agents WHERE id = ?").get(n)}function ze(){return f().prepare(`SELECT * FROM agents
|
|
5
5
|
WHERE task_id IS NULL
|
|
6
|
-
ORDER BY created_at ASC`).all()}function
|
|
6
|
+
ORDER BY created_at ASC`).all()}function Ge(e){return f().prepare("SELECT * FROM agents WHERE id = ? AND task_id IS NULL").get(e)??null}function ue(e){let t=e?.stderr??"";return/can't find (?:session|window|pane):/i.test(t)}async function Q(e,t,n){try{await u(["kill-session","-t",t]),y.info({chat_id:e,operation:n,tmux_session:t},`${n}: tmux session killed`)}catch(i){ue(i)?y.debug({chat_id:e,operation:n,tmux_session:t},`${n}: tmux session already gone`):y.warn({chat_id:e,operation:n,tmux_session:t,err:i},`${n}: tmux kill-session failed`)}}async function Ye(e){let t=f();y.info({chat_id:e.id,operation:"closeChat"},"closeChat: start"),t.prepare(`UPDATE agents SET status = 'stopped', hook_activity = 'idle',
|
|
7
7
|
hook_activity_updated_at = datetime('now')
|
|
8
|
-
WHERE id = ?`).run(e.id),e.tmux_session&&await
|
|
9
|
-
`).filter(Boolean),l=d.length>s;return l&&(d.length=s),{commits:d.map(m=>{let[h,_,x,p,g,
|
|
10
|
-
`).filter(Boolean).map(r=>r.replace(/^origin\//,"")),i=[...new Set(n)].filter(r=>r!=="HEAD").sort(),s=null;try{let{stdout:r}=await H("git",["-C",e,"symbolic-ref","--short","HEAD"],{env:A()});s=r.trim()||null}catch{s=null}let o=null;try{let{stdout:r}=await H("git",["-C",e,"symbolic-ref","--short","refs/remotes/origin/HEAD"],{env:A()});o=r.trim().replace(/^origin\//,"")||null}catch{o=null}return{branches:i,current:s,default:o}}var c=
|
|
11
|
-
`).map(Number);return Math.max(...n)}var
|
|
12
|
-
`).filter(s=>s.startsWith(n));for(let s of i)await u(["kill-session","-t",s]).catch(()=>{})}async function
|
|
13
|
-
`).filter(Boolean)),n=/^(octomux-agent-.+)-v-/;for(let i of t){let s=i.match(n);if(s){let o=s[1];t.has(o)||await u(["kill-session","-t",i]).catch(()=>{})}}}function
|
|
8
|
+
WHERE id = ?`).run(e.id),e.tmux_session&&await Q(e.id,e.tmux_session,"closeChat"),y.info({chat_id:e.id,operation:"closeChat"},"closeChat: complete")}async function Je(e){let t=f();y.info({chat_id:e.id,operation:"deleteChat"},"deleteChat: start"),e.tmux_session&&await Q(e.id,e.tmux_session,"deleteChat");let n=U(e.id);try{N.rmSync(n,{recursive:!0,force:!0}),y.info({chat_id:e.id,operation:"deleteChat",chat_dir:n},"deleteChat: scratch dir removed")}catch(i){y.warn({chat_id:e.id,operation:"deleteChat",chat_dir:n,err:i},"deleteChat: scratch dir remove failed (may already be gone)")}t.prepare("DELETE FROM agents WHERE id = ?").run(e.id),y.info({chat_id:e.id,operation:"deleteChat"},"deleteChat: complete")}import{execFile as pe}from"child_process";import{promisify as me}from"util";var H=me(pe);async function _e(e,t){let{stdout:n}=await H("git",["-C",e,...t],{maxBuffer:16777216,env:A()});return n}async function q(e,t,n){let{stdout:i}=await H("git",["-C",e,"merge-base",t,n],{env:A()});return i.trim()}async function Ze(e,t){let{from:n,to:i="HEAD",limit:s}=t,o=n?`${n}..${i}`:i,r=["log","--pretty=format:%H%x09%h%x09%s%x09%an%x09%ae%x09%aI","-n",String(s+1),o],a="";try{a=await _e(e,r)}catch(m){let h=m.message;if(h.includes("unknown revision")||h.includes("does not have any commits yet")||h.includes("bad revision"))return{commits:[],truncated:!1};throw m}let d=a.split(`
|
|
9
|
+
`).filter(Boolean),l=d.length>s;return l&&(d.length=s),{commits:d.map(m=>{let[h,_,x,p,g,R]=m.split(" ");return{sha:h??"",short_sha:_??"",subject:x??"",author:p??"",author_email:g??"",authored_at:R??""}}),truncated:l}}async function et(e){let{stdout:t}=await H("git",["-C",e,"branch","-a","--format=%(refname:short)"],{env:A()}),n=t.trim().split(`
|
|
10
|
+
`).filter(Boolean).map(r=>r.replace(/^origin\//,"")),i=[...new Set(n)].filter(r=>r!=="HEAD").sort(),s=null;try{let{stdout:r}=await H("git",["-C",e,"symbolic-ref","--short","HEAD"],{env:A()});s=r.trim()||null}catch{s=null}let o=null;try{let{stdout:r}=await H("git",["-C",e,"symbolic-ref","--short","refs/remotes/origin/HEAD"],{env:A()});o=r.trim().replace(/^origin\//,"")||null}catch{o=null}return{branches:i,current:s,default:o}}var c=F("task-runner"),k=fe(he);function Z(){return b.join(W(),"scratch")}function ee(e){return b.join(Z(),e)}function L(e){let t=e?.stderr??"";return/can't find (?:session|window|pane):/i.test(t)}async function Y(e){let{stdout:t}=await u(["display-message","-t",e,"-p","#{window_index}"]);return parseInt(t.trim(),10)}async function $(e){let{stdout:t}=await u(["list-windows","-t",e,"-F","#{window_index}"]),n=t.trim().split(`
|
|
11
|
+
`).map(Number);return Math.max(...n)}var ge=6e4,te=["remember@claude-plugins-official"];function we(e){let t=b.join(e,".claude");w.mkdirSync(t,{recursive:!0});let n=b.join(t,"settings.local.json");if(w.existsSync(n))return;let i={};for(let s of te)i[s]=!1;w.writeFileSync(n,JSON.stringify({plugins:i},null,2))}function B(e){let t=e.baseCmd;if(e.prompt&&e.worktreePath&&e.agentId){let s=b.join(e.worktreePath,`.claude-prompt-${e.agentId}`);w.writeFileSync(s,e.prompt,{mode:384,flag:"wx"}),t+=` "$(cat ${I(s)})"`,setTimeout(()=>{try{w.unlinkSync(s)}catch{}},ge)}let n=process.env.SHELL||"/bin/sh",i=`${t}; exec ${n} -i`;return`${n} -ic ${I(i)}`}async function Ee(e,t){try{await k("sh",["-c",t.format_command],{cwd:e})}catch{}try{await k("sh",["-c",t.lint_command],{cwd:e})}catch{}let{stdout:n}=await k("git",["diff","--name-only"],{cwd:e});n.trim()&&(await k("git",["add","-A"],{cwd:e}),await k("git",["commit","-m","chore: fix pre-existing formatting"],{cwd:e}))}async function j(e){let t;try{({stdout:t}=await u(["list-sessions","-F","#{session_name}"]))}catch{return}let n=`${e}-v-`,i=t.trim().split(`
|
|
12
|
+
`).filter(s=>s.startsWith(n));for(let s of i)await u(["kill-session","-t",s]).catch(()=>{})}async function kt(){let e;try{({stdout:e}=await u(["list-sessions","-F","#{session_name}"]))}catch{return}let t=new Set(e.trim().split(`
|
|
13
|
+
`).filter(Boolean)),n=/^(octomux-agent-.+)-v-/;for(let i of t){let s=i.match(n);if(s){let o=s[1];t.has(o)||await u(["kill-session","-t",i]).catch(()=>{})}}}function ke(e,t){let n=e.normalize("NFKD").replace(/[̀-ͯ]/g,"").toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/-{2,}/g,"-").replace(/^-|-$/g,"").slice(0,50),i=t.slice(0,6);return`${n}-${i}`}async function xt(){let e=f(),t=e.prepare("SELECT id, tmux_session FROM tasks WHERE runtime_state = 'setting_up'").all();for(let n of t){let i=!1;if(n.tmux_session)try{await u(["has-session","-t",n.tmux_session]),i=!0}catch{i=!1}i||(e.prepare("UPDATE tasks SET runtime_state = 'error', error = ?, updated_at = datetime('now') WHERE id = ?").run("orphan setting_up on boot",n.id),c.warn({task_id:n.id,operation:"reconcileOrphanSettingUp"},"transitioned orphan setting_up task to error"))}}async function Tt(){let e=Z();if(!w.existsSync(e))return;let t=f(),n=new Set(t.prepare(`SELECT t.id AS id FROM tasks t
|
|
14
14
|
LEFT JOIN worktrees w ON t.worktree_id = w.id
|
|
15
15
|
WHERE w.mode = 'scratch' AND t.runtime_state IN ('idle','setting_up','running')
|
|
16
|
-
AND t.deleted_at IS NULL`).all().map(s=>s.id)),i=w.readdirSync(e,{withFileTypes:!0});for(let s of i){if(!s.isDirectory()||n.has(s.name))continue;let o=b.join(e,s.name);try{w.rmSync(o,{recursive:!0,force:!0}),c.info({scratch_dir:o,operation:"scratch_gc_removed"},"scratch_gc_removed")}catch(r){c.warn({scratch_dir:o,operation:"scratch_gc_removed",err:r},"scratch_gc_remove_failed")}}}async function
|
|
17
|
-
`).map(n=>n.trim()).filter(Boolean)}async function
|
|
16
|
+
AND t.deleted_at IS NULL`).all().map(s=>s.id)),i=w.readdirSync(e,{withFileTypes:!0});for(let s of i){if(!s.isDirectory()||n.has(s.name))continue;let o=b.join(e,s.name);try{w.rmSync(o,{recursive:!0,force:!0}),c.info({scratch_dir:o,operation:"scratch_gc_removed"},"scratch_gc_removed")}catch(r){c.warn({scratch_dir:o,operation:"scratch_gc_removed",err:r},"scratch_gc_remove_failed")}}}async function ne(e){if(!w.existsSync(e))throw new Error(`Repository path does not exist: ${e}`);await k("git",["-C",e,"rev-parse","--is-inside-work-tree"])}async function M(e,t="HEAD"){let{stdout:n}=await k("git",["-C",e,"rev-parse",`${t}^{commit}`]);return n.trim()}async function re(e){let{stdout:t}=await k("git",["-C",e,"status","--porcelain=v1"]);return t.split(`
|
|
17
|
+
`).map(n=>n.trim()).filter(Boolean)}async function xe(e){await ne(e.repo_path);let t=ke(e.title,e.id),n=e.branch||`agents/${t}`,i=e.branch||t,s=b.join(e.repo_path,".worktrees",i),o=b.join(e.repo_path,".worktrees");w.mkdirSync(o,{recursive:!0});let r=["-C",e.repo_path,"worktree","add",s,"-b",n];if(e.base_branch&&r.push(e.base_branch),await k("git",r),e.source==="auto_review"&&e.pr_head_sha){if(e.pr_number)try{await k("git",["-C",e.repo_path,"fetch","origin",`pull/${e.pr_number}/head`])}catch(m){c.warn({task_id:e.id,operation:"createTask",err:m},"createTask: failed to fetch PR head; review may show no files")}try{await k("git",["-C",s,"reset","--hard",e.pr_head_sha])}catch(m){c.warn({task_id:e.id,operation:"createTask",err:m},"createTask: failed to reset worktree to pr_head_sha; leaving at base-branch tip")}}let a=e.base_branch||"HEAD",d;if(e.source==="auto_review"&&e.pr_head_sha&&e.base_branch)try{d=await q(e.repo_path,e.base_branch,e.pr_head_sha)}catch(m){c.warn({task_id:e.id,operation:"createTask",err:m},"createTask: git merge-base failed, falling back to rev-parse"),d=await M(e.repo_path,a)}else d=await M(e.repo_path,a);let l=b.join(e.repo_path,".claude","settings.local.json"),E=b.join(s,".claude","settings.local.json");return w.existsSync(l)&&(w.mkdirSync(b.dirname(E),{recursive:!0}),w.copyFileSync(l,E)),we(s),c.info({task_id:e.id,operation:"createTask",settings_path:E,disabled_plugins:te.length},"createTask: wrote agent-local settings"),{worktreePath:s,branch:n,baseBranch:e.base_branch,baseSha:d,installHooksAt:s,runPreflight:!0}}async function Te(e){let t=e.worktree;if(!t)throw new Error("existing mode requires a worktree path");if(!w.existsSync(t))throw new Error(`existing worktree does not exist: ${t}`);await k("git",["-C",t,"rev-parse","--is-inside-work-tree"]);let n=await M(t),i=null;try{let{stdout:o}=await k("git",["-C",t,"rev-parse","--abbrev-ref","HEAD"]),r=o.trim();i=r==="HEAD"?null:r}catch{i=null}let s=null;try{let{stdout:o}=await k("git",["-C",t,"rev-parse","--abbrev-ref","--symbolic-full-name","@{upstream}"]),r=o.trim();r&&(s=r.replace(/^origin\//,""))}catch{s=i}return{worktreePath:t,branch:i,baseBranch:s,baseSha:n,installHooksAt:t,runPreflight:!1}}async function be(e){await ne(e.repo_path);let{stdout:t}=await k("git",["-C",e.repo_path,"rev-parse","--abbrev-ref","HEAD"]),n=t.trim(),i=e.base_branch?.trim()||null;if(i){let{preflightNoneMode:r}=await import("./preflight-W4357G4A.js"),a=await r(e.repo_path,i,e.id);if(!a.ok){let d=a.conflicts.length?`another chat is active on a different branch at ${e.repo_path}: ${a.conflicts.map(l=>`${l.task_id} (${l.branch??"unknown"})`).join(", ")}`:`working tree at ${e.repo_path} has ${a.dirty.count} uncommitted changes`;throw new Error(`none mode preflight failed: ${d}`)}i!==n&&await k("git",["-C",e.repo_path,"checkout",i])}else{let r=await re(e.repo_path);if(r.length>0){let a=r.slice(0,5).join(", "),d=r.length>5?` (+${r.length-5} more)`:"";throw new Error(`none mode refuses dirty checkout at ${e.repo_path}: ${a}${d}`)}}let s=i??n,o=await M(e.repo_path);return{worktreePath:e.repo_path,branch:s,baseBranch:i,baseSha:o,installHooksAt:e.repo_path,runPreflight:!1}}async function ye(e){let t=ee(e.id);return w.mkdirSync(t,{recursive:!0}),{worktreePath:t,branch:null,baseBranch:null,baseSha:null,installHooksAt:t,runPreflight:!1}}async function bt(e){let t=f(),n=e.id,i=`octomux-agent-${n}`,s=e.run_mode;c.info({task_id:n,operation:"createTask",run_mode:s,repo_path:e.repo_path},"createTask: start");let o="validate";try{o="mode_setup";let r;switch(s){case"new":r=await xe(e);break;case"existing":r=await Te(e);break;case"none":r=await be(e);break;case"scratch":r=await ye(e);break;default:throw new Error(`unknown run_mode: ${String(s)}`)}t.prepare("UPDATE tasks SET runtime_state = 'setting_up', updated_at = datetime('now') WHERE id = ?").run(n);let a=s==="scratch"?null:e.repo_path;if(e.worktree_id)t.prepare(`UPDATE worktrees
|
|
18
18
|
SET path = ?, repo_path = ?, branch = ?, base_branch = ?, base_sha = ?,
|
|
19
19
|
mode = ?, status = 'in_use', last_used_at = datetime('now')
|
|
20
|
-
WHERE id = ?`).run(r.worktreePath,a,r.branch,r.baseBranch,r.baseSha,s,e.worktree_id);else{let T=
|
|
20
|
+
WHERE id = ?`).run(r.worktreePath,a,r.branch,r.baseBranch,r.baseSha,s,e.worktree_id);else{let T=O(12);t.prepare(`INSERT INTO worktrees
|
|
21
21
|
(id, path, repo_path, branch, base_branch, base_sha, mode, status, last_used_at)
|
|
22
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, 'in_use', datetime('now'))`).run(T,r.worktreePath,a,r.branch,r.baseBranch,r.baseSha,s),t.prepare("UPDATE tasks SET worktree_id = ? WHERE id = ?").run(T,n)}if(c.info({task_id:n,operation:"createTask",run_mode:s,branch:r.branch,worktree:r.worktreePath,base_sha:r.baseSha},"createTask: setup complete"),r.branch&&e.repo_path)try{let T=await
|
|
23
|
-
VALUES (?, ?, ?, ?, datetime('now'))`);for(let D of P)
|
|
22
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, 'in_use', datetime('now'))`).run(T,r.worktreePath,a,r.branch,r.baseBranch,r.baseSha,s),t.prepare("UPDATE tasks SET worktree_id = ? WHERE id = ?").run(T,n)}if(c.info({task_id:n,operation:"createTask",run_mode:s,branch:r.branch,worktree:r.worktreePath,base_sha:r.baseSha},"createTask: setup complete"),r.branch&&e.repo_path)try{let T=await V(e.repo_path),P=K(r.branch,T,n);if(P.length>0){let se=t.prepare(`INSERT OR IGNORE INTO task_external_refs (task_id, integration, ref, url, created_at)
|
|
23
|
+
VALUES (?, ?, ?, ?, datetime('now'))`);for(let D of P)se.run(n,D.integration,D.ref,D.url),c.info({task_id:n,integration:D.integration,ref:D.ref},"ref-inference: inferred ref from branch name")}}catch(T){c.warn({task_id:n,err:T},"ref-inference: error during inference")}if(r.runPreflight){o="preflight";let T=await V(e.repo_path);await Ee(r.worktreePath,T)}o="launch_agent";let d=S(e.harness_id),l=O(12),E=e.agent??null,m=X.randomBytes(32).toString("hex"),h=d.resolveFlags(await C()),_,x;if(d.sessionIdMode==="orchestrator-assigned"){let T=d.newSessionId();_=T,x=T}else _=null,x=d.newSessionId();await d.syncAgents(r.worktreePath),await d.installHooks(r.worktreePath,v(),m);let p=d.buildLaunchCommand({sessionId:x,agent:E,flags:h,model:e.model??null,workspacePath:r.worktreePath}),g=B({baseCmd:p,prompt:e.initial_prompt,worktreePath:r.worktreePath,agentId:l});o="tmux_session",await u(["new-session","-d","-s",i,"-c",r.worktreePath,g]),await u(["set-option","-t",i,"aggressive-resize","on"]),t.prepare("UPDATE tasks SET tmux_session = ?, updated_at = datetime('now') WHERE id = ?").run(i,n),c.info({task_id:n,operation:"createTask",tmux_session:i},"createTask: tmux session created");let R=await Y(i);t.prepare(`INSERT INTO agents
|
|
24
24
|
(id, task_id, window_index, label, harness_id, harness_session_id, hook_token, agent)
|
|
25
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(l,n,
|
|
25
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(l,n,R,"Agent 1",d.id,_,m,E),d.postLaunch?.(`${i}:${R}`),c.info({task_id:n,agent_id:l,operation:"createTask",window_index:R,harness:d.id,harness_session_id:_},"createTask: first agent launched"),t.prepare(`UPDATE tasks SET runtime_state = 'running', error = NULL,
|
|
26
26
|
workflow_status = CASE
|
|
27
27
|
WHEN workflow_status IN ('backlog', 'planned') THEN 'in_progress'
|
|
28
28
|
ELSE workflow_status
|
|
29
29
|
END,
|
|
30
|
-
updated_at = datetime('now') WHERE id = ?`).run(n),c.info({task_id:n,operation:"createTask"},"createTask: complete")}catch(r){c.error({task_id:n,operation:"createTask",stage:o,run_mode:s,err:r},"createTask: failed during setup stage"),t.prepare("UPDATE tasks SET runtime_state = 'error', error = ?, updated_at = datetime('now') WHERE id = ?").run(r.message,n)}}async function
|
|
30
|
+
updated_at = datetime('now') WHERE id = ?`).run(n),c.info({task_id:n,operation:"createTask"},"createTask: complete")}catch(r){c.error({task_id:n,operation:"createTask",stage:o,run_mode:s,err:r},"createTask: failed during setup stage"),t.prepare("UPDATE tasks SET runtime_state = 'error', error = ?, updated_at = datetime('now') WHERE id = ?").run(r.message,n)}}async function yt(e,t={}){let n=f(),i=t.agent??null;c.info({task_id:e.id,operation:"addAgent",agent:i},"addAgent: start");let s=n.prepare("SELECT * FROM agents WHERE task_id = ? AND status != 'stopped' ORDER BY window_index").all(e.id),o=t.label??`Agent ${s.length+1}`,r=S(e.harness_id),a=O(12),l=n.prepare("SELECT hook_token FROM agents WHERE task_id = ? AND hook_token != '' LIMIT 1").get(e.id)?.hook_token??X.randomBytes(32).toString("hex"),E=r.resolveFlags(await C()),m=t.prompt;if(t.skeleton){let T=b.join(e.worktree,".octomux","agents",`${t.skeleton}.md`);if(!w.existsSync(T))throw new Error(`skeleton not found: ${t.skeleton} (expected at ${T})`);let P=w.readFileSync(T,"utf-8");m=t.prompt?`${P}
|
|
31
31
|
|
|
32
32
|
# Task
|
|
33
33
|
|
|
34
|
-
${t.prompt}`:P}let h,_;if(r.sessionIdMode==="orchestrator-assigned"){let T=r.newSessionId();h=T,_=T}else h=null,_=r.newSessionId();await r.syncAgents(e.worktree),await r.installHooks(e.worktree,v(),l);let x=r.buildLaunchCommand({sessionId:_,agent:i,flags:E,model:t.model??e.model??null,workspacePath:e.worktree}),p=
|
|
34
|
+
${t.prompt}`:P}let h,_;if(r.sessionIdMode==="orchestrator-assigned"){let T=r.newSessionId();h=T,_=T}else h=null,_=r.newSessionId();await r.syncAgents(e.worktree),await r.installHooks(e.worktree,v(),l);let x=r.buildLaunchCommand({sessionId:_,agent:i,flags:E,model:t.model??e.model??null,workspacePath:e.worktree}),p=B({baseCmd:x,prompt:m,worktreePath:e.worktree,agentId:a});await u(["new-window","-t",e.tmux_session,"-c",e.worktree,p]);let g=await $(e.tmux_session),R=`${e.tmux_session}:${g}`;return n.prepare(`INSERT INTO agents
|
|
35
35
|
(id, task_id, window_index, label, harness_id, harness_session_id, hook_token, agent, notify_agent_id)
|
|
36
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(a,e.id,g,o,r.id,h,l,i,t.notify_agent_id??null),r.postLaunch?.(
|
|
36
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(a,e.id,g,o,r.id,h,l,i,t.notify_agent_id??null),r.postLaunch?.(R),c.info({task_id:e.id,agent_id:a,operation:"addAgent",window_index:g,harness:r.id,harness_session_id:h},"addAgent: claude launched"),{id:a,task_id:e.id,window_index:g,label:o,status:"running",harness_id:r.id,harness_session_id:h,hook_token:l,hook_activity:"active",hook_activity_updated_at:null,tmux_session:null,agent:i,notify_agent_id:t.notify_agent_id??null,created_at:new Date().toISOString()}}async function Rt(e){let t=f();if(c.info({task_id:e.id,operation:"closeTask",run_mode:e.run_mode},"closeTask: start"),t.prepare(`UPDATE permission_prompts SET status = 'resolved', resolved_at = datetime('now')
|
|
37
37
|
WHERE task_id = ? AND status = 'pending'`).run(e.id),t.prepare("DELETE FROM user_terminals WHERE task_id = ?").run(e.id),t.prepare("UPDATE tasks SET runtime_state = 'idle', updated_at = datetime('now') WHERE id = ?").run(e.id),t.prepare("UPDATE agents SET status = 'stopped', hook_activity = 'idle', hook_activity_updated_at = datetime('now') WHERE task_id = ?").run(e.id),t.prepare(`UPDATE worktrees SET status = 'available', last_used_at = datetime('now')
|
|
38
|
-
WHERE id = (SELECT worktree_id FROM tasks WHERE id = ?)`).run(e.id),c.info({task_id:e.id,operation:"closeTask"},"closeTask: DB marked task closed + agents stopped"),e.tmux_session){await
|
|
38
|
+
WHERE id = (SELECT worktree_id FROM tasks WHERE id = ?)`).run(e.id),c.info({task_id:e.id,operation:"closeTask"},"closeTask: DB marked task closed + agents stopped"),e.tmux_session){await j(e.tmux_session);try{await u(["kill-session","-t",e.tmux_session]),c.info({task_id:e.id,operation:"closeTask",tmux_session:e.tmux_session},"closeTask: tmux session killed")}catch(n){L(n)?c.debug({task_id:e.id,operation:"closeTask",tmux_session:e.tmux_session},"closeTask: tmux session already gone"):c.warn({task_id:e.id,operation:"closeTask",tmux_session:e.tmux_session,err:n},"closeTask: tmux kill-session failed")}}c.info({task_id:e.id,operation:"closeTask"},"closeTask: complete")}async function St(e){let t=f();if(c.info({task_id:e.id,operation:"softDeleteTask"},"softDeleteTask: start"),e.tmux_session){await j(e.tmux_session);try{await u(["kill-session","-t",e.tmux_session])}catch(n){L(n)||c.warn({task_id:e.id,tmux_session:e.tmux_session,err:n},"softDeleteTask: tmux kill-session failed")}}t.prepare(`UPDATE tasks SET deleted_at = datetime('now'),
|
|
39
39
|
runtime_state = 'idle',
|
|
40
40
|
updated_at = datetime('now')
|
|
41
41
|
WHERE id = ?`).run(e.id),t.prepare(`UPDATE agents
|
|
42
42
|
SET status = 'stopped',
|
|
43
43
|
hook_activity = 'idle',
|
|
44
44
|
hook_activity_updated_at = datetime('now')
|
|
45
|
-
WHERE task_id = ? AND status = 'running'`).run(e.id),c.info({task_id:e.id,operation:"softDeleteTask"},"softDeleteTask: complete")}async function
|
|
46
|
-
WHERE agent_id = ? AND status = 'pending'`).run(t.id),await u(["kill-window","-t",`${e.tmux_session}:${t.window_index}`]).catch(i=>{L(i)?c.debug({task_id:e.id,agent_id:t.id,operation:"stopAgent"},"stopAgent: tmux window already gone"):c.warn({task_id:e.id,agent_id:t.id,operation:"stopAgent",err:i},"stopAgent: kill-window failed")}),n.prepare("UPDATE agents SET status = 'stopped', hook_activity = 'idle', hook_activity_updated_at = datetime('now') WHERE id = ?").run(t.id),c.info({task_id:e.id,agent_id:t.id,operation:"stopAgent"},"stopAgent: complete")}async function
|
|
45
|
+
WHERE task_id = ? AND status = 'running'`).run(e.id),c.info({task_id:e.id,operation:"softDeleteTask"},"softDeleteTask: complete")}async function Ct(e){let t=f();if(c.info({task_id:e.id,operation:"deleteTask",run_mode:e.run_mode},"deleteTask: start"),e.tmux_session){await j(e.tmux_session);try{await u(["kill-session","-t",e.tmux_session]),c.info({task_id:e.id,operation:"deleteTask",tmux_session:e.tmux_session},"deleteTask: tmux session killed")}catch(i){L(i)?c.debug({task_id:e.id,operation:"deleteTask",tmux_session:e.tmux_session},"deleteTask: tmux session already gone"):c.warn({task_id:e.id,operation:"deleteTask",tmux_session:e.tmux_session,err:i},"deleteTask: tmux kill-session failed")}}switch(e.run_mode){case"new":{if(e.worktree)try{await k("git",["-C",e.repo_path,"worktree","remove",e.worktree,"--force"]),c.info({task_id:e.id,operation:"deleteTask",worktree:e.worktree},"deleteTask: worktree removed")}catch(i){c.warn({task_id:e.id,operation:"deleteTask",worktree:e.worktree,err:i},"deleteTask: worktree remove failed (may already be gone)")}if(e.branch)try{await k("git",["-C",e.repo_path,"branch","-D",e.branch]),c.info({task_id:e.id,operation:"deleteTask",branch:e.branch},"deleteTask: branch deleted")}catch(i){c.warn({task_id:e.id,operation:"deleteTask",branch:e.branch,err:i},"deleteTask: branch delete failed (may already be gone)")}break}case"existing":case"none":c.info({task_id:e.id,operation:"deleteTask",run_mode:e.run_mode},"deleteTask: skipped filesystem cleanup (user-owned path)");break;case"scratch":{let i=e.worktree||ee(e.id);try{w.rmSync(i,{recursive:!0,force:!0}),c.info({task_id:e.id,operation:"deleteTask",scratch_dir:i},"deleteTask: scratch dir removed")}catch(s){c.warn({task_id:e.id,operation:"deleteTask",scratch_dir:i,err:s},"deleteTask: scratch dir remove failed (may already be gone)")}break}}let n=e.worktree_id;n&&(t.prepare("UPDATE tasks SET worktree_id = NULL WHERE id = ?").run(e.id),e.run_mode==="new"||e.run_mode==="scratch"?t.prepare("DELETE FROM worktrees WHERE id = ?").run(n):t.prepare("UPDATE worktrees SET status = 'available', last_used_at = datetime('now') WHERE id = ?").run(n)),c.info({task_id:e.id,operation:"deleteTask"},"deleteTask: complete")}async function vt(e,t){let n=f();c.info({task_id:e.id,agent_id:t.id,operation:"stopAgent",window_index:t.window_index},"stopAgent: start"),n.prepare(`UPDATE permission_prompts SET status = 'resolved', resolved_at = datetime('now')
|
|
46
|
+
WHERE agent_id = ? AND status = 'pending'`).run(t.id),await u(["kill-window","-t",`${e.tmux_session}:${t.window_index}`]).catch(i=>{L(i)?c.debug({task_id:e.id,agent_id:t.id,operation:"stopAgent"},"stopAgent: tmux window already gone"):c.warn({task_id:e.id,agent_id:t.id,operation:"stopAgent",err:i},"stopAgent: kill-window failed")}),n.prepare("UPDATE agents SET status = 'stopped', hook_activity = 'idle', hook_activity_updated_at = datetime('now') WHERE id = ?").run(t.id),c.info({task_id:e.id,agent_id:t.id,operation:"stopAgent"},"stopAgent: complete")}async function At(e){let n=(await C()).editor;if(n==="vscode"||n==="cursor")return await k(n==="vscode"?"code":"cursor",[e.worktree]),{editor:n,windowIndex:null};if(e.user_window_index!==null&&e.user_window_index!==void 0)return{editor:n,windowIndex:e.user_window_index};let i=f();await u(["new-window","-t",e.tmux_session,"-c",e.worktree]);let s=await $(e.tmux_session);return await u(["send-keys","-t",`${e.tmux_session}:${s}`,"nvim .","Enter"]),i.prepare("UPDATE tasks SET user_window_index = ?, updated_at = datetime('now') WHERE id = ?").run(s,e.id),{editor:"nvim",windowIndex:s}}async function Pt(e){let t=f();await u(["new-window","-t",e.tmux_session,"-c",e.worktree]);let n=await $(e.tmux_session),{count:i}=t.prepare("SELECT COUNT(*) as count FROM user_terminals WHERE task_id = ?").get(e.id),s=`Terminal ${i+1}`,o=O(12);return t.prepare("INSERT INTO user_terminals (id, task_id, window_index, label) VALUES (?, ?, ?, ?)").run(o,e.id,n,s),{id:o,task_id:e.id,window_index:n,label:s,status:"idle",created_at:new Date().toISOString()}}async function Dt(e,t){let n=f();await u(["kill-window","-t",`${e.tmux_session}:${t.window_index}`]).catch(()=>{}),n.prepare("DELETE FROM user_terminals WHERE id = ?").run(t.id)}async function It(e){let t=f(),n=e.tmux_session,i=e.run_mode;c.info({task_id:e.id,operation:"resumeTask",run_mode:i,tmux_session:n,worktree:e.worktree},"resumeTask: start");try{if(i==="existing"){if(!e.worktree||!w.existsSync(e.worktree))throw new Error(`existing worktree no longer exists: ${e.worktree??"<null>"}`)}else if(i==="scratch"){if(!e.worktree||!w.existsSync(e.worktree))throw new Error(`scratch dir no longer exists: ${e.worktree??"<null>"}`)}else if(i==="none"){if(!w.existsSync(e.repo_path))throw new Error(`repo_path no longer exists: ${e.repo_path}`);let a=await re(e.repo_path);if(a.length>0){let d=a.slice(0,5).join(", "),l=a.length>5?` (+${a.length-5} more)`:"";throw new Error(`none mode refuses dirty checkout at ${e.repo_path}: ${d}${l}`)}}t.prepare("UPDATE tasks SET runtime_state = 'setting_up', error = NULL, user_window_index = NULL, updated_at = datetime('now') WHERE id = ?").run(e.id),t.prepare("DELETE FROM user_terminals WHERE task_id = ?").run(e.id),await j(n),await u(["kill-session","-t",n]).catch(()=>{}),t.prepare("UPDATE agents SET status = 'stopped', hook_activity = 'idle', hook_activity_updated_at = datetime('now') WHERE task_id = ? AND status != 'stopped'").run(e.id);let s=e.worktree,o=t.prepare("SELECT * FROM agents WHERE task_id = ? AND status = 'stopped' ORDER BY window_index").all(e.id);if(o.length>0){let a=S(o[0].harness_id);await a.syncAgents(s),await a.installHooks(s,v(),o[0].hook_token)}else await u(["new-session","-d","-s",n,"-c",s]),await u(["set-option","-t",n,"aggressive-resize","on"]);let r=!1;for(let a=0;a<o.length;a++){let d=o[a],l=S(d.harness_id),E=l.resolveFlags(await C()),m=e.model??null,h;if(d.harness_session_id)h=l.buildResumeCommand({sessionId:d.harness_session_id,flags:E,model:m,workspacePath:s});else{let p=l.newSessionId(),g=l.buildContinueCommand({sessionId:p,flags:E,model:m,workspacePath:s});g!==null?h=g:(h=l.buildLaunchCommand({sessionId:p,agent:d.agent,flags:E,model:m,workspacePath:s}),c.warn({agent_id:d.id,harness:l.id},"continue unsupported, launching fresh")),l.sessionIdMode==="orchestrator-assigned"&&t.prepare("UPDATE agents SET harness_session_id = ? WHERE id = ?").run(p,d.id)}let _=B({baseCmd:h}),x;r?(await u(["new-window","-t",n,"-c",s,_]),x=await $(n)):(await u(["new-session","-d","-s",n,"-c",s,_]),await u(["set-option","-t",n,"aggressive-resize","on"]),r=!0,x=await Y(n)),l.postLaunch?.(`${n}:${x}`),t.prepare("UPDATE agents SET window_index = ?, status = 'running' WHERE id = ?").run(x,d.id),c.info({task_id:e.id,agent_id:d.id,operation:"resumeTask",window_index:x,harness:l.id,harness_session_id:d.harness_session_id},"resumeTask: agent recovered")}t.prepare("UPDATE tasks SET runtime_state = 'running', updated_at = datetime('now') WHERE id = ?").run(e.id),c.info({task_id:e.id,operation:"resumeTask",recovered_agents:o.length},"resumeTask: complete")}catch(s){c.error({task_id:e.id,operation:"resumeTask",err:s},"resumeTask: failed"),t.prepare("UPDATE tasks SET runtime_state = 'error', error = ?, updated_at = datetime('now') WHERE id = ?").run(s.message,e.id)}}async function Ht(e,t){let n=f(),i=e.task_id;c.info({agent_id:e.id,from_task_id:i,to_task_id:t,operation:"task_hop"},"task_hop: start");let s=null;if(e.task_id){let p=n.prepare("SELECT tmux_session FROM tasks WHERE id = ?").get(e.task_id);p?.tmux_session&&(s={session:p.tmux_session,window:e.window_index})}else e.tmux_session&&(s={session:e.tmux_session,window:e.window_index});let o,r,a;if(t===null)a=!0,o=G(e.id),r=U(e.id),w.mkdirSync(r,{recursive:!0});else{a=!1;let p=n.prepare("SELECT * FROM tasks WHERE id = ?").get(t);if(!p)throw new Error(`Task not found: ${t}`);if(!p.worktree_id)throw new Error(`Task ${t} has no worktree`);let g=n.prepare("SELECT * FROM worktrees WHERE id = ?").get(p.worktree_id);if(!g)throw new Error(`Worktree not found for task ${t}`);if(!g.path||!w.existsSync(g.path))throw new Error(`Worktree path does not exist: ${g.path}`);if(!p.tmux_session)throw new Error(`Task ${t} has no tmux session (not running)`);o=p.tmux_session,r=g.path}if(s)try{!e.task_id&&e.tmux_session?await u(["kill-session","-t",e.tmux_session]):await u(["kill-window","-t",`${s.session}:${s.window}`])}catch(p){L(p)||c.warn({agent_id:e.id,operation:"task_hop",err:p},"task_hop: kill old tmux target failed")}let d=S(e.harness_id),l=d.resolveFlags(await C()),E=null;t&&(E=n.prepare("SELECT model FROM tasks WHERE id = ?").get(t)?.model??null),await d.syncAgents(r),await d.installHooks(r,v(),e.hook_token);let m;if(e.harness_session_id)m=d.buildResumeCommand({sessionId:e.harness_session_id,flags:l,model:E,workspacePath:r});else{let p=d.newSessionId(),g=d.buildContinueCommand({sessionId:p,flags:l,model:E,workspacePath:r});g!==null?m=g:(m=d.buildLaunchCommand({sessionId:p,agent:e.agent,flags:l,model:E,workspacePath:r}),c.warn({agent_id:e.id,harness:d.id},"continue unsupported, launching fresh")),d.sessionIdMode==="orchestrator-assigned"&&n.prepare("UPDATE agents SET harness_session_id = ? WHERE id = ?").run(p,e.id)}let h=B({baseCmd:m}),_;a?(await u(["new-session","-d","-s",o,"-c",r,h]),await u(["set-option","-t",o,"aggressive-resize","on"]),_=await Y(o)):(await u(["new-window","-t",o,"-c",r,h]),_=await $(o));let x=`${o}:${_}`;return d.postLaunch?.(x),n.prepare(`UPDATE agents
|
|
47
47
|
SET task_id = ?, window_index = ?, tmux_session = ?, status = 'running',
|
|
48
48
|
hook_activity = 'active', hook_activity_updated_at = datetime('now')
|
|
49
|
-
WHERE id = ?`).run(t,_,a?o:null,e.id),c.info({agent_id:e.id,from_task_id:i,to_task_id:t,new_window_index:_,new_tmux_session:o,operation:"task_hop"},"task_hop: complete"),n.prepare("SELECT * FROM agents WHERE id = ?").get(e.id)}export{
|
|
49
|
+
WHERE id = ?`).run(t,_,a?o:null,e.id),c.info({agent_id:e.id,from_task_id:i,to_task_id:t,new_window_index:_,new_tmux_session:o,operation:"task_hop"},"task_hop: complete"),n.prepare("SELECT * FROM agents WHERE id = ?").get(e.id)}export{V as a,ve as b,Ae as c,Ve as d,ze as e,Ge as f,Ye as g,Je as h,Ze as i,et as j,kt as k,xt as l,Tt as m,bt as n,yt as o,Rt as p,St as q,Ct as r,vt as s,At as t,Pt as u,Dt as v,It as w,Ht as x};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as l,c as m}from"./chunk-GAXJZSQT.js";import{a as c}from"./chunk-
|
|
1
|
+
import{a as l,c as m}from"./chunk-GAXJZSQT.js";import{a as c}from"./chunk-FJPTEYLR.js";import{execFileSync as f}from"child_process";import{existsSync as p,readdirSync as d}from"fs";import a from"path";var o=c("startup");function x({cmd:n,checkArgs:r,name:i,brewPkg:e,installUrl:s}){let t=i||n;if(l({cmd:n,checkArgs:r}).ok||e&&process.platform==="darwin"&&m(e,{cmd:n,checkArgs:r})&&l({cmd:n,checkArgs:r}).ok)return;let u=s||`https://formulae.brew.sh/formula/${e||n}`;o.error({label:t,install_url:u},`${t} not found \u2014 install it manually`),process.exit(1)}function S({cmd:n,checkArgs:r,name:i,installUrl:e,brewPkg:s}){let t=i||n;if(l({cmd:n,checkArgs:r}).ok)return;let u=e||(s?`https://formulae.brew.sh/formula/${s}`:void 0);o.warn({label:t,install_url:u},`${t} not found \u2014 install from the Setup page or run: octomux start after fixing`)}function _(){let n;try{let i=f("nvim",["--version"],{encoding:"utf8"}).match(/(\d+)\.(\d+)\.(\d+)/);i&&(n={major:parseInt(i[1],10),minor:parseInt(i[2],10),raw:i[0]})}catch{}n||(o.error("Could not determine neovim version"),process.exit(1)),n.major===0&&n.minor<10&&o.warn({found:n.raw,required:">=0.10.0"},"Neovim version too old \u2014 upgrade with: brew upgrade neovim (or use VS Code/Cursor editor in Setup)")}function D(n){let r=a.join(n,".local","share","nvim","lazy");if(!p(r)||d(r).length===0){o.info("Syncing LazyVim plugins (first run \u2014 this may take a minute)");try{f("nvim",["--headless","+Lazy! sync","+qa"],{stdio:"inherit",env:{...process.env,XDG_CONFIG_HOME:a.join(n,".config"),XDG_DATA_HOME:a.join(n,".local","share"),XDG_STATE_HOME:a.join(n,".local","state"),XDG_CACHE_HOME:a.join(n,".local","cache")}})}catch(e){o.warn({err:e},"LazyVim plugin sync failed \u2014 editor may not work correctly")}}}export{x as a,S as b,_ as c,D as d};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as I}from"./chunk-
|
|
1
|
+
import{a as S}from"./chunk-FJPTEYLR.js";import{a as I}from"./chunk-TWPYSNU6.js";import H from"better-sqlite3";import d from"path";import u from"fs";import{nanoid as K}from"nanoid";import{fileURLToPath as W}from"url";var D=d.dirname(W(import.meta.url)),g=S("db"),h=process.env.NODE_ENV==="production",G=d.join(I(),"data"),j=d.join(D,"..","data"),F=h?G:j,O=process.env.OCTOMUX_DB_PATH??d.join(F,"tasks.db"),l=d.join(D,"..","data","tasks.db"),V=`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS worktrees (
|
|
3
3
|
id TEXT PRIMARY KEY,
|
|
4
4
|
path TEXT NOT NULL,
|
|
@@ -197,7 +197,7 @@ CREATE INDEX IF NOT EXISTS idx_team_runs_status ON team_runs(status);
|
|
|
197
197
|
hook_token TEXT NOT NULL DEFAULT '',
|
|
198
198
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
199
199
|
);
|
|
200
|
-
`);let a=["id","task_id","window_index","label","status",t("harness_session_id")?"harness_session_id":"NULL AS harness_session_id",t("hook_activity")?"hook_activity":"'active' AS hook_activity",t("hook_activity_updated_at")?"hook_activity_updated_at":"NULL AS hook_activity_updated_at",t("harness_id")?"harness_id":"'claude-code' AS harness_id",t("hook_token")?"hook_token":"'' AS hook_token","created_at"].join(", ");e.exec(`INSERT INTO agents_new SELECT ${a} FROM agents`),e.exec("DROP TABLE agents"),e.exec("ALTER TABLE agents_new RENAME TO agents"),e.exec("CREATE INDEX IF NOT EXISTS idx_agents_task ON agents(task_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_agents_harness_session_id ON agents(harness_session_id)")}).default()}var A;function ie(){if(!A){u.mkdirSync(
|
|
200
|
+
`);let a=["id","task_id","window_index","label","status",t("harness_session_id")?"harness_session_id":"NULL AS harness_session_id",t("hook_activity")?"hook_activity":"'active' AS hook_activity",t("hook_activity_updated_at")?"hook_activity_updated_at":"NULL AS hook_activity_updated_at",t("harness_id")?"harness_id":"'claude-code' AS harness_id",t("hook_token")?"hook_token":"'' AS hook_token","created_at"].join(", ");e.exec(`INSERT INTO agents_new SELECT ${a} FROM agents`),e.exec("DROP TABLE agents"),e.exec("ALTER TABLE agents_new RENAME TO agents"),e.exec("CREATE INDEX IF NOT EXISTS idx_agents_task ON agents(task_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_agents_harness_session_id ON agents(harness_session_id)")}).default()}var A;function ie(){if(!A){u.mkdirSync(F,{recursive:!0}),h&&l!==O&&u.existsSync(l)&&g.info({old_path:l,new_path:O},"Found database at old location \u2014 copy to new location to migrate"),A=new H(O);try{u.chmodSync(O,384)}catch{}q(A)}return A}function q(e){e.pragma("journal_mode = WAL"),e.pragma("foreign_keys = ON"),e.exec(V);let T=s=>{let r=e.pragma(`table_info(${s})`);return new Set(r.map(n=>n.name))},t=(s,r,n,i)=>{i.has(r)||(e.exec(`ALTER TABLE ${s} ADD COLUMN ${n}`),i.add(r))},a=T("tasks"),_=T("agents");_.has("claude_session_id")&&!_.has("harness_session_id")&&(e.exec("ALTER TABLE agents RENAME COLUMN claude_session_id TO harness_session_id"),e.exec("DROP INDEX IF EXISTS idx_agents_claude_session_id"),_.delete("claude_session_id"),_.add("harness_session_id")),t("agents","harness_session_id","harness_session_id TEXT",_),t("agents","hook_activity","hook_activity TEXT NOT NULL DEFAULT 'active'",_),t("agents","hook_activity_updated_at","hook_activity_updated_at TEXT",_),t("agents","harness_id","harness_id TEXT NOT NULL DEFAULT 'claude-code'",_),t("agents","hook_token","hook_token TEXT NOT NULL DEFAULT ''",_);let C=T("task_external_refs");t("task_external_refs","metadata","metadata TEXT",C);let w=T("file_review_state");t("file_review_state","reviewed_blob_sha","reviewed_blob_sha TEXT",w),e.exec("CREATE INDEX IF NOT EXISTS idx_agents_harness_session_id ON agents(harness_session_id)"),a.has("no_worktree")&&!a.has("run_mode")?e.transaction(()=>{e.exec("ALTER TABLE tasks ADD COLUMN run_mode TEXT"),a.add("run_mode"),e.exec(`
|
|
201
201
|
UPDATE tasks SET run_mode = CASE
|
|
202
202
|
WHEN no_worktree = 1 AND (repo_path IS NULL OR repo_path = '') THEN 'scratch'
|
|
203
203
|
WHEN no_worktree = 1 THEN 'none'
|
|
@@ -211,14 +211,14 @@ CREATE INDEX IF NOT EXISTS idx_team_runs_status ON team_runs(status);
|
|
|
211
211
|
ELSE 'new'
|
|
212
212
|
END
|
|
213
213
|
WHERE run_mode IS NULL
|
|
214
|
-
`),e.exec("ALTER TABLE tasks DROP COLUMN no_worktree"),a.delete("no_worktree")}).default();let
|
|
214
|
+
`),e.exec("ALTER TABLE tasks DROP COLUMN no_worktree"),a.delete("no_worktree")}).default();let f=$(e),b=a.has("worktree");e.transaction(()=>{if(a.has("worktree_id")||(e.exec("ALTER TABLE tasks ADD COLUMN worktree_id TEXT REFERENCES worktrees(id)"),a.add("worktree_id")),!b)return;let s=e.prepare(`SELECT id, repo_path, branch, base_branch, base_sha, worktree, run_mode, created_at
|
|
215
215
|
FROM tasks
|
|
216
216
|
WHERE worktree IS NOT NULL AND worktree_id IS NULL`).all(),r=e.prepare(`INSERT INTO worktrees (id, path, repo_path, branch, base_branch, base_sha, mode, status, created_at)
|
|
217
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, 'in_use', ?)`),n=e.prepare("UPDATE tasks SET worktree_id = ? WHERE id = ?");for(let i of s){let U=K(12),N=i.run_mode||"new",
|
|
218
|
-
ON tasks(deleted_at) WHERE deleted_at IS NOT NULL`);let
|
|
217
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, 'in_use', ?)`),n=e.prepare("UPDATE tasks SET worktree_id = ? WHERE id = ?");for(let i of s){let U=K(12),N=i.run_mode||"new",P=N==="scratch"?null:i.repo_path,Y=N==="scratch"?null:i.branch,y=N==="scratch"?null:i.base_branch,B=N==="scratch"?null:i.base_sha;r.run(U,i.worktree,P,Y,y,B,N,i.created_at),n.run(U,i.id)}}).default(),f&&Q(e);let L=T("agents");t("agents","tmux_session","tmux_session TEXT",L),t("agents","agent","agent TEXT",L),L.has("pinned")&&(e.exec("ALTER TABLE agents DROP COLUMN pinned"),L.delete("pinned"));let m=T("tasks");t("tasks","agent","agent TEXT",m),t("tasks","harness_id","harness_id TEXT NOT NULL DEFAULT 'claude-code'",m),t("tasks","model","model TEXT",m);let c=T("tasks"),k=["worktree","run_mode","repo_path","branch","base_branch","base_sha"];k.some(s=>c.has(s))&&e.transaction(()=>{e.exec("DROP INDEX IF EXISTS idx_tasks_existing_path"),e.exec("DROP INDEX IF EXISTS idx_tasks_none_repo");for(let s of k)c.has(s)&&e.exec(`ALTER TABLE tasks DROP COLUMN ${s}`)}).default(),e.exec("DROP INDEX IF EXISTS idx_tasks_active_worktree"),e.prepare("DELETE FROM agents WHERE id = 'orchestrator' AND task_id IS NULL").run();let o=T("tasks");t("tasks","runtime_state","runtime_state TEXT NOT NULL DEFAULT 'idle'",o),t("tasks","workflow_status","workflow_status TEXT NOT NULL DEFAULT 'backlog'",o),t("tasks","current_summary","current_summary TEXT",o),t("tasks","current_summary_updated_at","current_summary_updated_at TEXT",o),t("tasks","deleted_at","deleted_at TEXT",o),t("tasks","notify_task_id","notify_task_id TEXT",o),e.exec(`CREATE INDEX IF NOT EXISTS idx_tasks_deleted_at
|
|
218
|
+
ON tasks(deleted_at) WHERE deleted_at IS NOT NULL`);let R=e.prepare("SELECT COUNT(*) AS n FROM tasks WHERE workflow_status = 'archived'").get().n;R>0&&(e.prepare(`UPDATE tasks SET workflow_status = 'done',
|
|
219
219
|
deleted_at = datetime('now'),
|
|
220
220
|
updated_at = datetime('now')
|
|
221
|
-
WHERE workflow_status = 'archived'`).run(),
|
|
221
|
+
WHERE workflow_status = 'archived'`).run(),g.warn({migrated:R},"migrated legacy archived tasks to trash; will purge after deleteGraceHours")),T("tasks").has("workflow_status")&&e.exec(`
|
|
222
222
|
UPDATE tasks SET workflow_status = CASE
|
|
223
223
|
WHEN runtime_state IN ('running', 'setting_up', 'error') THEN 'in_progress'
|
|
224
224
|
WHEN runtime_state = 'idle' AND initial_prompt IS NULL THEN 'backlog'
|
|
@@ -227,7 +227,7 @@ CREATE INDEX IF NOT EXISTS idx_team_runs_status ON team_runs(status);
|
|
|
227
227
|
ELSE 'backlog'
|
|
228
228
|
END
|
|
229
229
|
WHERE workflow_status = 'backlog'
|
|
230
|
-
`);let
|
|
230
|
+
`);let x=T("repo_configs");t("repo_configs","ref_inference_json","ref_inference_json TEXT",x);let X=new Set(e.prepare("SELECT name FROM sqlite_master WHERE type='table'").all().map(s=>s.name));X.has("task_updates")||e.exec(`
|
|
231
231
|
CREATE TABLE IF NOT EXISTS task_updates (
|
|
232
232
|
id TEXT PRIMARY KEY,
|
|
233
233
|
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
@@ -276,7 +276,7 @@ CREATE INDEX IF NOT EXISTS idx_team_runs_status ON team_runs(status);
|
|
|
276
276
|
WHERE runtime_state IS NULL
|
|
277
277
|
`),e.exec("DROP INDEX IF EXISTS idx_tasks_status"),e.exec("ALTER TABLE tasks DROP COLUMN status")}).default(),e.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_tasks_active_worktree
|
|
278
278
|
ON tasks(worktree_id)
|
|
279
|
-
WHERE runtime_state IN ('setting_up','running') AND worktree_id IS NOT NULL`);let
|
|
279
|
+
WHERE runtime_state IN ('setting_up','running') AND worktree_id IS NOT NULL`);let p=e.pragma("table_info(permission_prompts)").find(s=>s.name==="session_id");p&&p.notnull===1&&e.transaction(()=>{e.exec("ALTER TABLE permission_prompts RENAME TO permission_prompts_old"),e.exec(`
|
|
280
280
|
CREATE TABLE permission_prompts (
|
|
281
281
|
id TEXT PRIMARY KEY,
|
|
282
282
|
task_id TEXT NOT NULL,
|
|
@@ -329,5 +329,5 @@ CREATE INDEX IF NOT EXISTS idx_team_runs_status ON team_runs(status);
|
|
|
329
329
|
created_at TIMESTAMP NOT NULL DEFAULT (datetime('now'))
|
|
330
330
|
);
|
|
331
331
|
CREATE INDEX IF NOT EXISTS idx_review_learnings_repo ON review_learnings(repo_path);
|
|
332
|
-
`);let E=T("inline_comments");t("inline_comments","status","status TEXT NOT NULL DEFAULT 'draft'",E),t("inline_comments","review_run_id","review_run_id TEXT REFERENCES review_runs(id)",E),t("inline_comments","severity","severity TEXT",E),t("inline_comments","bucket","bucket TEXT",E),t("inline_comments","kind","kind TEXT NOT NULL DEFAULT 'comment'",E),t("inline_comments","existing_code","existing_code TEXT",E),t("inline_comments","suggested_code","suggested_code TEXT",E),t("inline_comments","published_review_id","published_review_id TEXT REFERENCES published_reviews(id)",E),t("inline_comments","github_comment_id","github_comment_id INTEGER",E),t("inline_comments","re_flag_of","re_flag_of TEXT REFERENCES inline_comments(id)",E),t("inline_comments","last_check_run_id","last_check_run_id TEXT REFERENCES review_runs(id)",E),t("inline_comments","last_check_status","last_check_status TEXT",E),t("inline_comments","auto_resolved_at","auto_resolved_at TIMESTAMP",E),t("inline_comments","auto_resolved_reason","auto_resolved_reason TEXT",E);let
|
|
333
|
-
ON tasks(review_of_task_id) WHERE review_of_task_id IS NOT NULL`);let
|
|
332
|
+
`);let E=T("inline_comments");t("inline_comments","status","status TEXT NOT NULL DEFAULT 'draft'",E),t("inline_comments","review_run_id","review_run_id TEXT REFERENCES review_runs(id)",E),t("inline_comments","severity","severity TEXT",E),t("inline_comments","bucket","bucket TEXT",E),t("inline_comments","kind","kind TEXT NOT NULL DEFAULT 'comment'",E),t("inline_comments","existing_code","existing_code TEXT",E),t("inline_comments","suggested_code","suggested_code TEXT",E),t("inline_comments","published_review_id","published_review_id TEXT REFERENCES published_reviews(id)",E),t("inline_comments","github_comment_id","github_comment_id INTEGER",E),t("inline_comments","re_flag_of","re_flag_of TEXT REFERENCES inline_comments(id)",E),t("inline_comments","last_check_run_id","last_check_run_id TEXT REFERENCES review_runs(id)",E),t("inline_comments","last_check_status","last_check_status TEXT",E),t("inline_comments","auto_resolved_at","auto_resolved_at TIMESTAMP",E),t("inline_comments","auto_resolved_reason","auto_resolved_reason TEXT",E);let v=T("tasks");t("tasks","review_of_task_id","review_of_task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL",v),e.exec(`CREATE INDEX IF NOT EXISTS idx_tasks_review_of_task_id
|
|
333
|
+
ON tasks(review_of_task_id) WHERE review_of_task_id IS NOT NULL`);let M=T("agents");t("agents","notify_agent_id","notify_agent_id TEXT",M)}export{ie as a};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as u}from"./chunk-TWPYSNU6.js";import i from"pino";import e from"path";import m from"fs";import{fileURLToPath as d}from"url";var v=e.dirname(d(import.meta.url)),s=process.env.NODE_ENV==="production",p=process.env.NODE_ENV==="test";function f(){return s?e.join(u(),"logs"):e.join(v,"..","data","logs")}function y(){return e.join(f(),"octomux.log")}function h(){return process.env.LOG_LEVEL?process.env.LOG_LEVEL:p?"silent":s?"info":"debug"}function c(r){return{target:"pino-roll",level:r,options:{file:y(),frequency:"daily",size:"10m",mkdir:!0,limit:{count:7}}}}function E(){let r=h();return p?i({level:r}):(m.mkdirSync(f(),{recursive:!0}),s?i({level:r,transport:c(r)}):i({level:r,transport:{targets:[{target:"pino-pretty",level:r,options:{colorize:!0,translateTime:"SYS:HH:MM:ss.l"}},c(r)]}}))}var g=null;function T(){return g||(g=E()),g}function V(r){let o=null,a=()=>{let t=T();return(!o||o.root!==t)&&(o={root:t,child:t.child({module:r})}),o.child};return new Proxy({},{get(t,L){let l=a(),n=Reflect.get(l,L);return typeof n=="function"?n.bind(l):n}})}export{V as a};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as t}from"./chunk-
|
|
1
|
+
import{a as t}from"./chunk-BTEWK6EA.js";import{a as g}from"./chunk-FJPTEYLR.js";import{execFile as u}from"child_process";import{promisify as l}from"util";var o=g("github-login"),s=l(u),i;function d(){return process.env.OCTOMUX_GITHUB_LOGIN?process.env.OCTOMUX_GITHUB_LOGIN:(i!==void 0||(i=t().prepare("SELECT github_login FROM config WHERE id = 1").get()?.github_login??null),i)}function c(e){t().prepare(`INSERT INTO config (id, github_login, updated_at) VALUES (1, ?, datetime('now'))
|
|
2
2
|
ON CONFLICT(id) DO UPDATE SET github_login = excluded.github_login, updated_at = datetime('now')`).run(e),i=e}async function b(){if(process.env.OCTOMUX_GITHUB_LOGIN)return process.env.OCTOMUX_GITHUB_LOGIN;let e=d();if(e)return e;try{let{stdout:r}=await s("gh",["api","user","-q",".login"]),n=r.trim();return n?(c(n),o.info({github_login:n},"cached GitHub login for reviewer polling"),n):(o.warn("gh api user returned empty login \u2014 reviewer polling disabled this session"),null)}catch(r){return o.warn({err:r.message},"failed to resolve GitHub login (gh missing/unauthed?) \u2014 reviewer polling disabled"),null}}export{d as a,b};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import{a as l}from"./chunk-GAXJZSQT.js";import{a as _,b as w,c as g}from"./chunk-YKFMOBXG.js";import{a as y}from"./chunk-FJPTEYLR.js";import{a as D}from"./chunk-TWPYSNU6.js";import q from"crypto";import i from"fs";import d from"path";import{fileURLToPath as z}from"url";import{execFile as N}from"child_process";import{promisify as U}from"util";import{createRequire as E}from"module";import p from"path";import v from"fs";import{fileURLToPath as B}from"url";var S=y("tmux-bin"),M=U(N),J=p.dirname(B(import.meta.url)),V=process.env.NODE_ENV==="production",W=D(),X=p.join(J,"..","data"),T=V?W:X,m=null;function A(){if(m)return m;if(process.env.OCTOMUX_TMUX_BIN){let t=process.env.OCTOMUX_TMUX_BIN,n=l({cmd:t,checkArgs:["-V"]}).ok;return m={path:t,source:"env",verified:n},S.debug({path:t,source:"env",verified:n},"tmux resolved via env override"),m}if(process.env.NODE_ENV==="test")return m={path:"tmux",source:"path",verified:l({cmd:"tmux",checkArgs:["-V"]}).ok},m;let r=process.resourcesPath;if(process.versions.electron&&r)try{let t=process.platform,n=process.arch,o=`@octomux/tmux-${t}-${n}`,s=p.join(r,"app.asar.unpacked","node_modules",o),c=p.join(s,"index.js");if(v.existsSync(c)){let a=E(c)(c);if(a.tmuxBin&&v.existsSync(a.tmuxBin)){let f=l({cmd:a.tmuxBin,checkArgs:["-V"]}).ok;return m={path:a.tmuxBin,source:"bundled",verified:f,terminfoDir:a.terminfoDir},S.debug({path:a.tmuxBin,source:"bundled",verified:f,terminfoDir:a.terminfoDir,electron:!0},"tmux resolved via packaged Electron asar.unpacked"),m}}}catch{}try{let t=process.platform,n=process.arch,o=`@octomux/tmux-${t}-${n}`,c=E(import.meta.url)(o);if(c.tmuxBin){let u=l({cmd:c.tmuxBin,checkArgs:["-V"]}).ok;return m={path:c.tmuxBin,source:"bundled",verified:u,terminfoDir:c.terminfoDir},S.debug({path:c.tmuxBin,source:"bundled",verified:u,terminfoDir:c.terminfoDir},"tmux resolved via bundled package"),m}}catch{}let e=l({cmd:"tmux",checkArgs:["-V"]}).ok;return m={path:"tmux",source:"path",verified:e},S.debug({source:"path",verified:e},"tmux resolved via PATH fallback"),m}function O(){return A().path}function P(){return["-S",p.join(T,"run","tmux.sock")]}function j(r=process.env){let{terminfoDir:e}=A();return e?{...r,TERMINFO_DIRS:`${e}:${r.TERMINFO_DIRS??""}`}:{...r}}async function R(r,e){let t=O(),n=[...P(),...r],o=j();return M(t,n,{...e,env:o})}function pr(r){return{file:O(),args:[...P(),...r],env:j()}}var b=!1;function gr(){if(b)return;let r=p.join(T,"run");v.mkdirSync(r,{recursive:!0}),b=!0}function H(r){return`'${r.replace(/'/g,"'\\''")}'`}var h=y("harness:cursor"),Z="composer-2.5",Q=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;function $(r){let e=r.trim();if(!Q.test(e))throw new Error(`Invalid harnesses.cursor.model: ${JSON.stringify(r)}. Use an id from cursor-agent --list-models`);return e}var F="octomux-agent-",G=/trust this (?:workspace|folder)|do you trust/i,K=200,C=5e3;function L(r){return` --workspace ${H(r)}`}function Y(r){let e=r.match(/^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/);if(!e)return{fm:{},body:r.trim()};let t={};for(let n of e[1].split(`
|
|
2
|
+
`)){let o=n.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);if(!o)continue;let s=o[2].trim();(s.startsWith('"')&&s.endsWith('"')||s.startsWith("'")&&s.endsWith("'"))&&(s=s.slice(1,-1)),t[o[1]]=s}return{fm:t,body:e[2].trim()}}function rr(r,e){let{fm:t,body:n}=Y(e),o=t.description||t.name?[t.description,t.name===r?void 0:t.name].filter(Boolean).join(" \xB7 "):"",s=o.trim()?o:`Octomux agent (${r})`;return`---
|
|
3
|
+
description: ${JSON.stringify(s)}
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!--
|
|
8
|
+
Synced from octomux agent definitions for Cursor CLI sessions in this workspace.
|
|
9
|
+
Personas mirror Claude Code --agent presets; edit definitions under Settings \u2192 Agents.
|
|
10
|
+
Harness \u2192 Cursor lets you append CLI flags (--resume, --model, etc.).
|
|
11
|
+
-->
|
|
12
|
+
|
|
13
|
+
${n}
|
|
14
|
+
`}function er(r){if(i.existsSync(r))for(let e of i.readdirSync(r,{withFileTypes:!0}))e.isFile()&&e.name.startsWith(F)&&(e.name.endsWith(".mdc")||e.name.endsWith(".md"))&&i.unlinkSync(d.join(r,e.name))}function tr(r){let e={command:r,type:"command",timeout:5};return JSON.stringify({version:1,hooks:{sessionStart:[e],beforeSubmitPrompt:[e],beforeShellExecution:[e],postToolUse:[e],afterFileEdit:[e]}},null,2)+`
|
|
15
|
+
`}function nr(){let r=d.dirname(z(import.meta.url)),e=r;for(let t=0;t<6;t++){let n=d.join(e,"bin","octomux-hook-bridge.js");if(i.existsSync(n))return n;let o=d.dirname(e);if(o===e)break;e=o}throw new Error(`Cannot locate bin/octomux-hook-bridge.js from ${r} (walked up 6 levels)`)}var k={id:"cursor",displayName:"Cursor",sessionIdMode:"harness-issued",newSessionId(){return q.randomUUID()},buildLaunchCommand({flags:r="",workspacePath:e}){return`cursor-agent${e?L(e):""}${r}`},buildResumeCommand({sessionId:r,flags:e="",workspacePath:t}){return`cursor-agent${t?L(t):""} --resume ${r}${e}`},buildContinueCommand(r){return null},async installHooks(r,e,t){let n=d.join(r,".octomux-hooks");i.mkdirSync(n,{recursive:!0,mode:448}),i.chmodSync(n,448);let o=nr(),s=d.join(n,"bridge.js");try{i.existsSync(s)&&i.chmodSync(s,384)}catch{}i.copyFileSync(o,s),i.chmodSync(s,320);let c=JSON.stringify({baseUrl:e,token:t},null,2)+`
|
|
16
|
+
`,u=d.join(n,"config.json");try{(!i.existsSync(u)||i.readFileSync(u,"utf-8")!==c)&&i.writeFileSync(u,c,{mode:384})}catch{i.writeFileSync(u,c,{mode:384})}i.chmodSync(u,384);let a=tr(s),f=d.join(r,".cursor");i.mkdirSync(f,{recursive:!0});let x=d.join(f,"hooks.json");try{(!i.existsSync(x)||i.readFileSync(x,"utf-8")!==a)&&i.writeFileSync(x,a)}catch{i.writeFileSync(x,a)}},async syncAgents(r){let{listAgents:e,getAgent:t}=await import("./agents-75BBHCTY.js"),n=d.join(r,".cursor","rules");i.mkdirSync(n,{recursive:!0}),er(n);let o=await e();for(let s of o)try{let c=await t(s.name),u=`${F}${s.name}.mdc`,a=d.join(n,u),f=rr(s.name,c.content);try{if(i.existsSync(a)&&i.readFileSync(a,"utf-8")===f)continue}catch{}i.writeFileSync(a,f,"utf-8")}catch(c){h.warn({worktree_path:r,agent:s.name,err:c.message},"cursor syncAgents: failed to mirror agent definition")}},async postLaunch(r){if(process.env.NODE_ENV==="test")return;let e=Date.now();for(;Date.now()-e<C;){let t;try{({stdout:t}=await R(["capture-pane","-t",r,"-p"]))}catch(n){h.warn({target:r,err:n.message},"cursor postLaunch: tmux capture-pane failed; abandoning trust auto-accept");return}if(G.test(t)){try{await R(["send-keys","-t",r,"a"]),h.info({target:r,elapsed_ms:Date.now()-e},"cursor postLaunch: accepted Workspace Trust prompt")}catch(n){h.warn({target:r,err:n.message},"cursor postLaunch: tmux send-keys failed while accepting trust prompt")}return}await new Promise(n=>setTimeout(n,K))}h.info({target:r,timeout_ms:C},"cursor postLaunch: no Workspace Trust prompt detected within timeout (workspace probably already trusted)")},resolveFlags(r){let e=r.harnesses?.["claude-code"],n=(typeof e?.dangerouslySkipPermissions=="boolean"?e.dangerouslySkipPermissions:!1)||!!r.dangerouslySkipPermissions,o=r.harnesses?.cursor??{},s=[];(o.force||n)&&s.push("--force"),o.flags&&s.push(w(o.flags,"harnesses.cursor.flags"));let c=s.join(" ");if(!/\B--model\b/.test(c)){let u=typeof o.model=="string"&&o.model.trim()?$(o.model):Z;s.push(`--model ${u}`)}return s.length>0?` ${s.join(" ")}`:""},validateSettings(r){if(typeof r!="object"||r===null||Array.isArray(r))throw new Error("Invalid cursor settings: expected object");let e=r,t={},n=new Set(["flags","force","model"]);for(let o of Object.keys(e))if(!n.has(o))throw new Error(`Invalid cursor settings: unknown key "${o}"`);if(e.flags!==void 0&&(t.flags=w(e.flags,"harnesses.cursor.flags")),e.force!==void 0){if(typeof e.force!="boolean")throw new Error("Invalid cursor.force: expected boolean");t.force=e.force}if(e.model!==void 0){if(typeof e.model!="string")throw new Error("Invalid cursor.model: expected string");let o=e.model.trim();o&&(t.model=$(o))}return t},validateAgentName(r){return _(r)}};var I=new Map([[g.id,g],[k.id,k]]),or=g.id;function Ar(r){let e=r??or,t=I.get(e);if(!t)throw new Error(`Unknown harness: ${e}`);return t}function Or(){return Array.from(I.values())}export{R as a,pr as b,gr as c,H as d,k as e,or as f,Ar as g,Or as h};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as o}from"./chunk-
|
|
1
|
+
import{a as o}from"./chunk-BTEWK6EA.js";import{nanoid as g}from"nanoid";function d(n){let t;try{t=JSON.parse(n.config_json)}catch{t={}}return{id:n.id,kind:n.kind,name:n.name,config:t,enabled:n.enabled===1,created_at:n.created_at,updated_at:n.updated_at}}function c(){return o().prepare("SELECT * FROM integrations ORDER BY created_at ASC").all().map(d)}function a(n){let r=o().prepare("SELECT * FROM integrations WHERE id = ?").get(n);if(r)return d(r)}function b(n,t,r){let e=o(),i=g(12),s=JSON.stringify(r);return e.prepare(`INSERT INTO integrations (id, kind, name, config_json, enabled, created_at, updated_at)
|
|
2
2
|
VALUES (?, ?, ?, ?, 1, datetime('now'), datetime('now'))`).run(i,n,t,s),a(i)}function u(n,t){let r=o(),e=[],i=[];return t.name!==void 0&&(e.push("name = ?"),i.push(t.name)),t.config!==void 0&&(e.push("config_json = ?"),i.push(JSON.stringify(t.config))),t.enabled!==void 0&&(e.push("enabled = ?"),i.push(t.enabled?1:0)),e.length===0||(e.push("updated_at = datetime('now')"),i.push(n),r.prepare(`UPDATE integrations SET ${e.join(", ")} WHERE id = ?`).run(...i)),a(n)}function m(n){o().prepare("DELETE FROM integrations WHERE id = ?").run(n)}function l(n,t){return u(n,{enabled:t})}export{c as a,a as b,b as c,u as d,m as e,l as f};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as R}from"./chunk-BYZCD2AS.js";import{a as g}from"./chunk-
|
|
1
|
+
import{a as R}from"./chunk-BYZCD2AS.js";import{a as g}from"./chunk-BTEWK6EA.js";import{a as k}from"./chunk-FJPTEYLR.js";import{nanoid as be}from"nanoid";var P=k("inline-comments");function Ze(e){let t=be(12);g().prepare(`INSERT INTO inline_comments
|
|
2
2
|
(id, task_id, agent_id, file_path, line, side, original_commit_sha, body,
|
|
3
3
|
kind, severity, bucket, review_run_id, existing_code, suggested_code, re_flag_of)
|
|
4
4
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(t,e.task_id,e.agent_id??null,e.file_path,e.line,e.side,e.original_commit_sha,e.body,e.kind??"comment",e.severity??null,e.bucket??null,e.review_run_id??null,e.existing_code??null,e.suggested_code??null,e.re_flag_of??null);let r=S(t);if(!r)throw new Error("Failed to read inline comment after insert");return P.info({task_id:e.task_id,comment_id:t,file_path:e.file_path,line:e.line},"inline comment created"),r}function Qe(e,t){return t?.file?g().prepare(`SELECT * FROM inline_comments
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as g}from"./chunk-FJPTEYLR.js";import{a as c}from"./chunk-TWPYSNU6.js";import l from"fs";import S from"path";var m=g("settings"),u={editor:"nvim",defaultHarnessId:"claude-code",harnesses:{}},y=["nvim","vscode","cursor"];function T(){return S.join(c(),"settings.json")}var k=!1;async function p(){let e;try{let n=await l.promises.readFile(T(),"utf-8");e=JSON.parse(n)}catch(n){if(n.code==="ENOENT")return{...u};throw n}let r=e.harnesses??{},s={...r["claude-code"]??{}},a=!1;e.claudeFlags!==void 0&&s.flags===void 0&&(s.flags=e.claudeFlags,a=!0),e.dangerouslySkipPermissions!==void 0&&s.dangerouslySkipPermissions===void 0&&(s.dangerouslySkipPermissions=e.dangerouslySkipPermissions,a=!0);let t={...r,"claude-code":s},{listHarnesses:d}=await import("./harnesses-ACMXKLJO.js");for(let n of d())if(t[n.id])try{t[n.id]=n.validateSettings(t[n.id])}catch(o){m.warn({harness:n.id,err:o.message},"invalid harness settings; ignoring blob"),delete t[n.id]}return a&&!k&&(m.warn("settings.json contains deprecated top-level keys (claudeFlags, dangerouslySkipPermissions); they will be removed on next save"),k=!0),{editor:e.editor??u.editor,defaultHarnessId:e.defaultHarnessId??u.defaultHarnessId,harnesses:t,defaultTracker:e.defaultTracker==="jira"||e.defaultTracker==="linear"?e.defaultTracker:void 0,defaultJiraBaseUrl:typeof e.defaultJiraBaseUrl=="string"?e.defaultJiraBaseUrl:void 0,defaultJiraProjectKey:typeof e.defaultJiraProjectKey=="string"?e.defaultJiraProjectKey:void 0,defaultLinearTeamKey:typeof e.defaultLinearTeamKey=="string"?e.defaultLinearTeamKey:void 0,defaultBaseBranch:typeof e.defaultBaseBranch=="string"?e.defaultBaseBranch:void 0,onboardingCompletedAt:typeof e.onboardingCompletedAt=="string"?e.onboardingCompletedAt:void 0,deleteGraceHours:typeof e.deleteGraceHours=="number"?e.deleteGraceHours:void 0}}async function B(e){if(e.editor&&!y.includes(e.editor))throw new Error(`Invalid editor: ${e.editor}. Must be one of: ${y.join(", ")}`);if(e.deleteGraceHours!==void 0&&(!Number.isFinite(e.deleteGraceHours)||e.deleteGraceHours<0))throw new Error(`Invalid deleteGraceHours: ${e.deleteGraceHours}. Must be a number >= 0.`);if(e.defaultTracker!==void 0&&e.defaultTracker!=="jira"&&e.defaultTracker!=="linear")throw new Error(`Invalid defaultTracker: ${e.defaultTracker}. Must be 'jira' or 'linear'.`);let r=await p(),s={...r.harnesses},{listHarnesses:a,getHarness:t}=await import("./harnesses-ACMXKLJO.js");if(e.harnesses){let o=new Set(a().map(i=>i.id));for(let[i,f]of Object.entries(e.harnesses))o.has(i)?s[i]=t(i).validateSettings(f):s[i]=f}if(e.claudeFlags!==void 0||e.dangerouslySkipPermissions!==void 0){let i={...s["claude-code"]??{}};e.claudeFlags!==void 0&&(i.flags=e.claudeFlags),e.dangerouslySkipPermissions!==void 0&&(i.dangerouslySkipPermissions=e.dangerouslySkipPermissions),s["claude-code"]=t("claude-code").validateSettings(i)}let d={editor:e.editor??r.editor,defaultHarnessId:e.defaultHarnessId??r.defaultHarnessId,harnesses:s,defaultTracker:e.defaultTracker!==void 0?e.defaultTracker:r.defaultTracker,defaultJiraBaseUrl:e.defaultJiraBaseUrl!==void 0?e.defaultJiraBaseUrl:r.defaultJiraBaseUrl,defaultJiraProjectKey:e.defaultJiraProjectKey!==void 0?e.defaultJiraProjectKey:r.defaultJiraProjectKey,defaultLinearTeamKey:e.defaultLinearTeamKey!==void 0?e.defaultLinearTeamKey:r.defaultLinearTeamKey,defaultBaseBranch:e.defaultBaseBranch!==void 0?e.defaultBaseBranch:r.defaultBaseBranch,onboardingCompletedAt:e.onboardingCompletedAt!==void 0?e.onboardingCompletedAt:r.onboardingCompletedAt,deleteGraceHours:e.deleteGraceHours!==void 0?e.deleteGraceHours:r.deleteGraceHours},n=T();return await l.promises.mkdir(S.dirname(n),{recursive:!0}),await l.promises.writeFile(n,JSON.stringify(d,null,2),"utf-8"),d}function v(e){let r=process.env.OCTOMUX_CLAUDE_FLAGS?.trim();if(r)return` ${r}`;let s=e.harnesses?.["claude-code"]??{},a=[];s.dangerouslySkipPermissions&&a.push("--dangerously-skip-permissions");let t=(s.flags??"").trim();return t&&a.push(t),a.length>0?` ${a.join(" ")}`:""}export{u as a,p as b,B as c,v as d};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as s}from"./chunk-G45FZHCE.js";import{g as a}from"./chunk-
|
|
1
|
+
import{a as s}from"./chunk-G45FZHCE.js";import{g as a}from"./chunk-MYIYBV6O.js";var g=["Bash(git push --force:*)","Bash(git reset --hard:*)","Bash(rm -rf:*)"],e=["Bash(cat:*)","Bash(cd:*)","Bash(echo:*)","Bash(env:*)","Bash(find:*)","Bash(grep:*)","Bash(head:*)","Bash(jq:*)","Bash(ls:*)","Bash(lsof:*)","Bash(pwd:*)","Bash(rg:*)","Bash(sed:*)","Bash(sort:*)","Bash(sqlite3:*)","Bash(stat:*)","Bash(tail:*)","Bash(tree:*)","Bash(wc:*)","Bash(which:*)","Bash(xargs:*)","Bash(bun:*)","Bash(bunx:*)","Bash(go:*)","Bash(node:*)","Bash(npx:*)","Bash(npm:*)","Bash(python3:*)","Bash(tsc:*)","Bash(vitest:*)","Bash(playwright:*)","Bash(git add:*)","Bash(git branch:*)","Bash(git checkout:*)","Bash(git diff:*)","Bash(git log:*)","Bash(git pull:*)","Bash(git push:*)","Bash(git stash:*)","Bash(git status:*)","Bash(git show:*)","Bash(git rev-parse:*)","Bash(git worktree:*)","Bash(git ls-remote:*)","Bash(git remote:*)","Bash(git fetch:*)","Bash(git merge:*)","Bash(git rebase:*)","Bash(git cherry-pick:*)","Bash(git tag:*)","Bash(gh issue:*)","Bash(gh api:*)","Bash(gh repo view:*)","Bash(gh pr view:*)","Bash(gh pr list:*)","Bash(cp:*)","Bash(mkdir:*)","Bash(chmod:*)","Bash(touch:*)","Bash(mv:*)","Bash(curl:*)","Bash(for:*)","ExitPlanMode","AskUserQuestion","mcp__plugin_atlassian_atlassian__getJiraIssue","mcp__plugin_atlassian_atlassian__searchJiraIssuesUsingJql","mcp__plugin_atlassian_atlassian__getVisibleJiraProjects","mcp__plugin_atlassian_atlassian__getConfluencePage","mcp__plugin_atlassian_atlassian__searchConfluenceUsingCql","mcp__plugin_atlassian_atlassian__searchAtlassian","mcp__plugin_playwright_playwright__browser_click","mcp__plugin_playwright_playwright__browser_close","mcp__plugin_playwright_playwright__browser_console_messages","mcp__plugin_playwright_playwright__browser_evaluate","mcp__plugin_playwright_playwright__browser_fill_form","mcp__plugin_playwright_playwright__browser_navigate","mcp__plugin_playwright_playwright__browser_run_code","mcp__plugin_playwright_playwright__browser_snapshot","mcp__plugin_playwright_playwright__browser_take_screenshot","mcp__plugin_playwright_playwright__browser_type"];async function l(h,_="claude-code",i=""){await a(_).installHooks(h,s(),i)}export{g as a,e as b,l as c};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import o from"path";import r from"os";function i(){return process.env.OCTOMUX_DATA_DIR??o.join(r.homedir(),".octomux")}export{i as a};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import $ from"crypto";import g from"fs";import d from"path";var p=/^[A-Za-z0-9_-]{1,64}$/,O=/[`;|&><\n\r]|\$\(/;function c(s){if(!p.test(s))throw new Error(`Invalid agent name: ${JSON.stringify(s)}. Must match ${p}`);return s}function u(s,n){if(typeof s!="string")throw new Error(`Invalid ${n}: must be a string`);let e=s.trim();if(O.test(e))throw new Error(`Invalid ${n}: contains forbidden shell metacharacter (one of \` ; | & > < $( or newline)`);let t=(e.match(/'/g)??[]).length,o=(e.match(/"/g)??[]).length;if(t%2!==0||o%2!==0)throw new Error(`Invalid ${n}: unbalanced quotes`);return e}function m(s,n){return n?`${s.replace(/\s*--model\s+\S+/g,"")} --model ${n}`:s}function P(s,n){let e=t=>`${s}/api/hooks/${t}?token=${encodeURIComponent(n)}`;return{UserPromptSubmit:[{hooks:[{type:"http",url:e("user-prompt-submit"),timeout:5}]}],PermissionRequest:[{hooks:[{type:"http",url:e("permission-request"),timeout:5}]}],PostToolUse:[{hooks:[{type:"http",url:e("post-tool-use"),timeout:5}]}],Stop:[{hooks:[{type:"http",url:e("stop"),timeout:5}]}]}}var C={id:"claude-code",displayName:"Claude Code",sessionIdMode:"orchestrator-assigned",newSessionId(){return $.randomUUID()},buildLaunchCommand({sessionId:s,agent:n,flags:e="",model:t}){let o=n?` --agent ${c(n)}`:"",i=m(e,t);return`claude${o} --session-id ${s}${i}`},buildResumeCommand({sessionId:s,flags:n="",model:e}){let t=m(n,e);return`claude --resume ${s}${t}`},buildContinueCommand({sessionId:s,flags:n="",model:e}){let t=m(n,e);return`claude --continue --session-id ${s}${t}`},async installHooks(s,n,e){let{ALLOWED_TOOLS:t,DENIED_TOOLS:o}=await import("./hook-settings-
|
|
2
|
-
`)},async syncAgents(s){let{listAgents:n,getAgent:e}=await import("./agents-
|
|
1
|
+
import $ from"crypto";import g from"fs";import d from"path";var p=/^[A-Za-z0-9_-]{1,64}$/,O=/[`;|&><\n\r]|\$\(/;function c(s){if(!p.test(s))throw new Error(`Invalid agent name: ${JSON.stringify(s)}. Must match ${p}`);return s}function u(s,n){if(typeof s!="string")throw new Error(`Invalid ${n}: must be a string`);let e=s.trim();if(O.test(e))throw new Error(`Invalid ${n}: contains forbidden shell metacharacter (one of \` ; | & > < $( or newline)`);let t=(e.match(/'/g)??[]).length,o=(e.match(/"/g)??[]).length;if(t%2!==0||o%2!==0)throw new Error(`Invalid ${n}: unbalanced quotes`);return e}function m(s,n){return n?`${s.replace(/\s*--model\s+\S+/g,"")} --model ${n}`:s}function P(s,n){let e=t=>`${s}/api/hooks/${t}?token=${encodeURIComponent(n)}`;return{UserPromptSubmit:[{hooks:[{type:"http",url:e("user-prompt-submit"),timeout:5}]}],PermissionRequest:[{hooks:[{type:"http",url:e("permission-request"),timeout:5}]}],PostToolUse:[{hooks:[{type:"http",url:e("post-tool-use"),timeout:5}]}],Stop:[{hooks:[{type:"http",url:e("stop"),timeout:5}]}]}}var C={id:"claude-code",displayName:"Claude Code",sessionIdMode:"orchestrator-assigned",newSessionId(){return $.randomUUID()},buildLaunchCommand({sessionId:s,agent:n,flags:e="",model:t}){let o=n?` --agent ${c(n)}`:"",i=m(e,t);return`claude${o} --session-id ${s}${i}`},buildResumeCommand({sessionId:s,flags:n="",model:e}){let t=m(n,e);return`claude --resume ${s}${t}`},buildContinueCommand({sessionId:s,flags:n="",model:e}){let t=m(n,e);return`claude --continue --session-id ${s}${t}`},async installHooks(s,n,e){let{ALLOWED_TOOLS:t,DENIED_TOOLS:o}=await import("./hook-settings-VQOP567H.js"),i=d.join(s,".claude"),l=d.join(i,"settings.local.json");g.mkdirSync(i,{recursive:!0});let r={};try{let v=g.readFileSync(l,"utf-8");r=JSON.parse(v),(typeof r!="object"||r===null||Array.isArray(r))&&(r={})}catch{r={}}let y={...typeof r.hooks=="object"&&r.hooks!==null&&!Array.isArray(r.hooks)?r.hooks:{},...P(n,e)},a=typeof r.permissions=="object"&&r.permissions!==null&&!Array.isArray(r.permissions)?r.permissions:{},f=Array.isArray(a.allow)?a.allow:[],h=[...new Set([...t,...f])],w=Array.isArray(a.deny)?a.deny:[],k=[...new Set([...o,...w])],S={...a,allow:h,deny:k},A={...r,permissions:S,hooks:y};g.writeFileSync(l,JSON.stringify(A,null,2)+`
|
|
2
|
+
`)},async syncAgents(s){let{listAgents:n,getAgent:e}=await import("./agents-75BBHCTY.js"),t=d.join(s,".claude","agents");await g.promises.mkdir(t,{recursive:!0});let o=await n();for(let i of o){let l=await e(i.name);await g.promises.writeFile(d.join(t,`${i.name}.md`),l.content,"utf-8")}},resolveFlags(s){let n=process.env.OCTOMUX_CLAUDE_FLAGS?.trim();if(n)return` ${u(n,"OCTOMUX_CLAUDE_FLAGS")}`;let e=s.harnesses?.["claude-code"]??{},t=[];return e.dangerouslySkipPermissions&&t.push("--dangerously-skip-permissions"),e.flags&&t.push(u(e.flags,"harnesses.claude-code.flags")),t.length>0?` ${t.join(" ")}`:""},validateSettings(s){if(typeof s!="object"||s===null||Array.isArray(s))throw new Error("Invalid claude-code settings: expected object");let n=s,e={};if(n.flags!==void 0&&(e.flags=u(n.flags,"harnesses.claude-code.flags")),n.dangerouslySkipPermissions!==void 0){if(typeof n.dangerouslySkipPermissions!="boolean")throw new Error("Invalid claude-code.dangerouslySkipPermissions: expected boolean");e.dangerouslySkipPermissions=n.dangerouslySkipPermissions}return e},validateAgentName(s){return c(s)}};export{c as a,u as b,C as c};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as i}from"./chunk-
|
|
1
|
+
import{a as i}from"./chunk-FJPTEYLR.js";var c=i("integrations:linear:graphql"),e=class extends Error{constructor(o,t){super(o);this.code=t;this.name="LinearApiError"}code};async function g(s,a,o){let t=await fetch("https://api.linear.app/graphql",{method:"POST",headers:{Authorization:s,"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({query:a,...o?{variables:o}:{}})});if(!t.ok){let n=await t.text().catch(()=>"");throw c.warn({status:t.status,body:n},"linear graphql non-2xx"),new e(`Linear API HTTP ${t.status} ${t.statusText??""}: ${n}`)}let r=await t.json();if(r.errors&&r.errors.length>0){let n=r.errors[0];throw new e(n.message,n.extensions?.code)}if(r.data===void 0)throw new e("Linear API returned no data and no errors");return r.data}export{e as a,g as b};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as a}from"./chunk-YKFMOBXG.js";export{a as claudeCodeHarness};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{e as d,f as e,g as f,h as g}from"./chunk-MYIYBV6O.js";import"./chunk-GAXJZSQT.js";import{a,b,c}from"./chunk-YKFMOBXG.js";import"./chunk-FJPTEYLR.js";import"./chunk-TWPYSNU6.js";export{e as DEFAULT_HARNESS_ID,c as claudeCodeHarness,d as cursorHarness,f as getHarness,g as listHarnesses,a as validateAgentName,b as validateFlagString};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a,b,c}from"./chunk-RFWGJ3HT.js";import"./chunk-G45FZHCE.js";import"./chunk-MYIYBV6O.js";import"./chunk-GAXJZSQT.js";import"./chunk-YKFMOBXG.js";import"./chunk-FJPTEYLR.js";import"./chunk-TWPYSNU6.js";export{b as ALLOWED_TOOLS,a as DENIED_TOOLS,c as installHookSettings};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as d}from"./chunk-FJPTEYLR.js";import{a as m}from"./chunk-TWPYSNU6.js";import o from"fs";import e from"path";import{fileURLToPath as j}from"url";var y=d("hooks-install"),h=e.dirname(j(import.meta.url));function p(){let t=[e.resolve(h,"..","templates","hooks"),e.resolve(h,"..","..","templates","hooks")];for(let n of t)if(o.existsSync(n))return n;return t[0]}function S(){let t=p();return o.existsSync(t)?o.readdirSync(t).filter(n=>{try{return o.statSync(e.join(t,n)).isDirectory()}catch{return!1}}):[]}function $(t,n=e.join(m(),"hooks")){let r=g(t);if(!r)return!1;let i=e.join(n,`${r.event}.d`);return r.files.every(s=>o.existsSync(e.join(i,s)))}function g(t){let n=e.join(p(),t,"template.json");if(!o.existsSync(n))return null;try{return JSON.parse(o.readFileSync(n,"utf8"))}catch(r){return y.warn({template:t,err:r},"failed to parse template.json"),null}}function D(t,n=e.join(m(),"hooks")){let r=p(),i=e.join(r,t);if(!o.existsSync(i))throw new Error(`Template "${t}" not found. Available: ${S().join(", ")||"(none)"}`);let s=g(t);if(!s)throw new Error(`template.json not found or invalid for "${t}"`);let u=e.join(n,`${s.event}.d`);o.mkdirSync(u,{recursive:!0});let a=[];for(let l of s.files){let f=e.join(i,l),c=e.join(u,l);if(!o.existsSync(f))throw new Error(`Template file not found: ${f}`);o.copyFileSync(f,c),l.endsWith(".json")||o.chmodSync(c,493),a.push(c)}return y.info({template:t,hooks_base:n,files:a},"installed hook template"),a}export{D as installHookTemplate,$ as isHookTemplateInstalled,S as listHookTemplates,p as resolveTemplatesHooksDir};
|