craig-cli 0.17.0 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +1 -1
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  var kw=Object.defineProperty;var xs=(e,t)=>{for(var n in t)kw(e,n,{get:t[n],enumerable:!0})};import{realpath as GE}from"node:fs/promises";import ke from"node:path";function Ae(e){let t=ke.join(e,".craig");return{workspaceRoot:e,repoRoot:e,craigDir:t,indexFile:ke.join(t,"index.json"),reposDir:ke.join(t,"repos"),workspacesDir:ke.join(t,"workspaces"),runtimeDir:ke.join(t,"runtime"),uiStateFile:ke.join(t,"runtime","ui-state.json"),tasksDir:ke.join(t,"tasks"),jobsDir:ke.join(t,"jobs"),commandsDir:ke.join(t,"commands"),eventsDir:ke.join(t,"events"),orchestrationDir:ke.join(t,"orchestration"),logsDir:ke.join(t,"logs"),logFile:ke.join(t,"logs","craig.jsonl"),artifactsDir:ke.join(t,"artifacts"),worktreesDir:ke.join(t,"worktrees"),configFile:ke.join(t,"config.json")}}import ru from"node:path";import{readFile as NI}from"node:fs/promises";import{readFile as Cw}from"node:fs/promises";import{randomUUID as Tw}from"node:crypto";import{chmod as bw,open as Rw,readFile as Pw,rename as Sw,rm as Iw}from"node:fs/promises";import oa from"node:path";async function q(e,t,n={}){let r=oa.dirname(e),s=oa.join(r,`.${oa.basename(e)}.${process.pid}.${Date.now()}.${Tw()}.tmp`),i=await Rw(s,"w",n.mode);try{let o=`${JSON.stringify(t,null,2)}
3
3
  `;await i.writeFile(o,"utf8"),await i.sync(),await i.close(),await Sw(s,e),n.mode!==void 0&&await bw(e,n.mode)}catch(o){throw await i.close().catch(()=>{}),await Iw(s,{force:!0}).catch(()=>{}),o}}async function Fs(e){try{let t=await Pw(e,"utf8");return JSON.parse(t)}catch(t){if(vw(t))return null;throw t}}function vw(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}async function qn(e){try{let t=await Cw(e.uiStateFile,"utf8"),n=JSON.parse(t);return Aw(n,e.uiStateFile)}catch(t){if(Ow(t))return null;throw t}}async function Vt(e,t){await q(e.uiStateFile,{...t,updatedAt:new Date().toISOString()})}function Ms(){return{version:1,selectedRepoId:null,selectedWorkspaceId:null,selectedTaskId:null,selectedPtyTabId:null,inputMode:"control",focusedRegion:"tasks",activeTab:"agent",inspectorSection:"task",inspectionMode:"files",openInspectionKind:null,selectedFileTreePath:null,selectedFilePath:null,selectedDiffPath:null,collapsedFileTreePaths:[],selectedActionId:"commit",updatedAt:new Date().toISOString()}}function Aw(e,t){if(typeof e!="object"||e===null||e.version!==1||!(e.selectedRepoId===null||typeof e.selectedRepoId=="string")||!(e.selectedWorkspaceId===null||typeof e.selectedWorkspaceId=="string")||!(e.selectedTaskId===null||typeof e.selectedTaskId=="string")||!(e.selectedPtyTabId===void 0||e.selectedPtyTabId===null||typeof e.selectedPtyTabId=="string")||!jn(e,"inputMode")||!jn(e,"focusedRegion")||!jn(e,"activeTab")||!jn(e,"inspectorSection")||!jn(e,"inspectionMode")||!Ls(e,"openInspectionKind")||!Ls(e,"selectedFileTreePath")||!Ls(e,"selectedFilePath")||!Ls(e,"selectedDiffPath")||!Ew(e,"collapsedFileTreePaths")||!jn(e,"selectedActionId")||typeof e.updatedAt!="string")throw new Error(`Craig UI state at ${t} is invalid. Remove or repair the file before rerunning Craig.`);return e}function jn(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||typeof e[t]=="string")}function Ls(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||e[t]===null||typeof e[t]=="string")}function Ew(e,t){return typeof e=="object"&&e!==null&&(!(t in e)||Array.isArray(e[t])&&e[t].every(n=>typeof n=="string"))}function Ow(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var aa={};xs(aa,{RUNNER_IDS:()=>ue,STABLE_RUNNER_IDS:()=>mt,assertEnabled:()=>kd,buildCommand:()=>Rd,getConfiguredProfile:()=>js,getDefault:()=>wd,getDisplayName:()=>bd,getEnabled:()=>qs,getProfile:()=>Un,isRunnerType:()=>Us,parse:()=>Td,setRunnerEnabled:()=>Pd,setRunnerPath:()=>Sd});var mt=["codex","cursor","claude"],ue=[...mt,"pi"];var yd={codex:{id:"codex",displayName:"Codex",executable:"codex",defaultAgentTitle:"Codex"},cursor:{id:"cursor",displayName:"Cursor",executable:"cursor-agent",defaultAgentTitle:"Cursor"},claude:{id:"claude",displayName:"Claude",executable:"claude",defaultAgentTitle:"Claude"},pi:{id:"pi",displayName:"Pi",executable:"pi",defaultAgentTitle:"Pi"}};var Un=e=>yd[e];var js=(e,t={})=>{let n=Un(e),r=t.runners?.[e]?.path?.trim();return{...n,executable:r&&r.length>0?r:n.executable}};var qs=(e={})=>ue.filter(t=>t!=="pi"||e.previews?.piRunner===!0).filter(t=>e.runners?.[t]?.enabled!==!1);var wd=(e={})=>{let t=qs(e);if(t.length===0)throw new Error("No runners are enabled. Enable at least one runner in .craig/config.json.");return t.includes("codex")?"codex":t[0]};var kd=(e,t={})=>{if(e==="pi"&&t.previews?.piRunner!==!0)throw new Error('Runner "pi" is experimental. Enable the piRunner feature preview in .craig/config.json.');if(t.runners?.[e]?.enabled===!1)throw new Error(`Runner "${e}" is disabled in .craig/config.json.`)};var Us=e=>ue.includes(e);var Td=e=>{if(!e||e.length===0)return"codex";if(!Us(e))throw new Error(`Unsupported runner "${e}". Expected one of: ${ue.join(", ")}.`);return e};var bd=e=>Un(e).displayName;var Rd=(e,t,n={})=>{let r=[js(e,n).executable];return t&&t.length>0&&r.push(t),r};var Pd=(e,t,n)=>({...e,runners:{...e.runners??{},[t]:{...e.runners?.[t]??{},enabled:n}}});var Sd=(e,t,n)=>{let r=e.runners?.[t]??{},{path:s,...i}=r;return{...e,runners:{...e.runners??{},[t]:n!=null?{...r,path:n}:i}}};var la={};xs(la,{PREVIEW_FEATURE_IDS:()=>Xe,isEnabled:()=>Id,setEnabled:()=>vd});var Xe=["agentOrchestration","piRunner","fileOpen"];function Id(e,t){return e.previews?.[t]===!0}function vd(e,t,n){return{...e,previews:{...e.previews,[t]:n}}}import{mkdir as $w,readFile as Nw,writeFile as Dw}from"node:fs/promises";import _w from"node:path";var xw=e=>typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT",Cd=async e=>{try{return await Nw(e,"utf8")}catch(t){if(xw(t))return null;throw t}},Ad=async(e,t)=>{await $w(_w.dirname(e),{recursive:!0}),await Dw(e,t,"utf8")};var Fw=["incrementalCenterPane","agentActivityIndicators"],Ws=(e,t)=>{if(typeof e!="object"||e===null)throw new Error(`Craig config at ${t} is invalid. Expected a JSON object.`);let n=e;if(n.runners!==void 0){if(typeof n.runners!="object"||n.runners===null||Array.isArray(n.runners))throw new Error(`Craig config at ${t} is invalid. "runners" must be an object.`);for(let[r,s]of Object.entries(n.runners)){if(!ue.includes(r))throw new Error(`Craig config at ${t} is invalid. "runners.${r}" is not supported. Expected one of: ${ue.join(", ")}.`);if(typeof s!="object"||s===null||Array.isArray(s))throw new Error(`Craig config at ${t} is invalid. "runners.${r}" must be an object.`);let i=s;if(i.enabled!==void 0&&typeof i.enabled!="boolean")throw new Error(`Craig config at ${t} is invalid. "runners.${r}.enabled" must be a boolean.`);if(i.path!==void 0&&(typeof i.path!="string"||i.path.trim().length===0))throw new Error(`Craig config at ${t} is invalid. "runners.${r}.path" must be a non-empty string.`)}}if(n.checks!==void 0&&(typeof n.checks!="object"||n.checks===null||!Array.isArray(n.checks.commands)||!n.checks.commands.every(r=>typeof r=="string")))throw new Error(`Craig config at ${t} is invalid. "checks.commands" must be an array of strings.`);if(n.open!==void 0&&(typeof n.open!="object"||n.open===null||!Array.isArray(n.open.command)||!n.open.command.every(r=>typeof r=="string")))throw new Error(`Craig config at ${t} is invalid. "open.command" must be an array of strings.`);if(n.github!==void 0){if(typeof n.github!="object"||n.github===null)throw new Error(`Craig config at ${t} is invalid. "github" must be an object.`);if(n.github.mergeMethod!==void 0&&n.github.mergeMethod!=="merge"&&n.github.mergeMethod!=="rebase"&&n.github.mergeMethod!=="squash")throw new Error(`Craig config at ${t} is invalid. "github.mergeMethod" must be "merge", "rebase", or "squash".`);if(n.github.watchIntervalSeconds!==void 0&&(!Number.isInteger(n.github.watchIntervalSeconds)||n.github.watchIntervalSeconds<=0))throw new Error(`Craig config at ${t} is invalid. "github.watchIntervalSeconds" must be a positive integer.`)}if(n.previews!==void 0){if(typeof n.previews!="object"||n.previews===null||Array.isArray(n.previews))throw new Error(`Craig config at ${t} is invalid. "previews" must be an object.`);for(let[r,s]of Object.entries(n.previews)){if(!Fw.includes(r)&&!Xe.includes(r))throw new Error(`Craig config at ${t} is invalid. "previews.${r}" is not supported. Expected one of: ${Xe.join(", ")}.`);if(typeof s!="boolean")throw new Error(`Craig config at ${t} is invalid. "previews.${r}" must be a boolean.`)}}return n};var ca=async(e,t={readConfigFile:Cd})=>{let n=await t.readConfigFile(e.configFile);if(!n)return{};if(n.trimStart()[0]!=="{")throw new Error(`Craig config at ${e.configFile} is malformed. Remove or repair the file before rerunning Craig.`);let r;try{r=JSON.parse(n)}catch{throw new Error(`Craig config at ${e.configFile} is malformed. Remove or repair the file before rerunning Craig.`)}return Ws(r,e.configFile)};var ua=async(e,t,n={writeConfigFile:Ad})=>{Ws(t,e.configFile),await n.writeConfigFile(e.configFile,`${JSON.stringify(t,null,2)}
4
- `)};var da={};xs(da,{checkForUpdate:()=>Ed,getCurrent:()=>Bs});var Bs=()=>{try{return"0.17.0"}catch{return"unknown"}};var Lw="https://registry.npmjs.org/craig-cli/latest",Mw=3600*1e3,jw={value:null},qw=(e,t)=>{let n=c=>c.split(".").map(Number),[r=0,s=0,i=0]=n(e),[o=0,a=0,l=0]=n(t);return r!==o?r>o:s!==a?s>a:i>l},Ed=async(e={fetch:globalThis.fetch,getCurrent:Bs,cache:jw})=>{let t=e.getCurrent(),n=Date.now();if(e.cache.value&&n-e.cache.value.cachedAt<Mw)return e.cache.value.result;let r=null;try{let i=await e.fetch(Lw,{signal:AbortSignal.timeout(5e3)});i.ok&&(r=(await i.json()).version??null)}catch{}let s={current:t,latest:r,updateAvailable:r!==null&&r!==t&&qw(r,t)};return e.cache.value={result:s,cachedAt:n},s};var T={load:ca,save:ua,previews:la,runners:aa,version:da};var Od={CLI_USAGE:2,INPUT_REQUIRED:2,WORKSPACE_CONTEXT_NOT_FOUND:3,WORKSPACE_CONTEXT_INVALID:4,WORKSPACE_NOT_FOUND:3,WORKSPACE_RECORD_INVALID:2,TASK_CONTEXT_NOT_FOUND:3,TASK_CONTEXT_AMBIGUOUS:4,TASK_CONTEXT_CONFLICT:4,TASK_NOT_FOUND:3,TASK_RECORD_INVALID:2,REPO_NOT_FOUND:3,REPO_RECORD_INVALID:2,PR_REPOSITORY_MISMATCH:4,PR_BRANCH_MISMATCH:4,EXTERNAL_DEPENDENCY_FAILED:5,OPERATION_TIMEOUT:6,OPERATION_CANCELLED:6,EVENT_CURSOR_INVALID:2,EVENT_CURSOR_EXPIRED:4,EVENT_JOURNAL_CORRUPT:2,COMMAND_NOT_FOUND:3,COMMAND_RECORD_INVALID:2,COMMAND_STATE_CONFLICT:4,CAPABILITY_NOT_FOUND:3,CAPABILITY_RECORD_INVALID:2,CAPABILITY_DENIED:4,DELEGATION_LIMIT_EXCEEDED:4,FURY_DEFINITION_INVALID:2,FURY_INPUT_INVALID:2,FURY_PLAN_NOT_FOUND:3,FURY_APPROVAL_REQUIRED:4,FURY_RUN_NOT_FOUND:3,FURY_REVIEW_NOT_FOUND:3,FURY_RECORD_INVALID:2,FURY_STATE_CONFLICT:4,FURY_OUTPUT_INVALID:4,PARTIAL_RESULT:7,INTERNAL_ERROR:1},g=class extends Error{code;exitCode;retryable;details;constructor(t,n,r){super(n,r.cause===void 0?void 0:{cause:r.cause}),this.name="CraigError",this.code=t,this.exitCode=Od[t],this.retryable=r.retryable??!1,this.details=r.details??{}}};function pa(e){return e instanceof g?e:new g("INTERNAL_ERROR",e instanceof Error?e.message:"Unknown Craig error",{cause:e})}import{appendFile as Uw,mkdir as Ww,readFile as Bw}from"node:fs/promises";import Vw from"node:path";var $d=80,Vs=async(e,t)=>{await Ww(Vw.dirname(e.logFile),{recursive:!0});let n={timestamp:new Date().toISOString(),...t};await Uw(e.logFile,`${JSON.stringify(n)}
4
+ `)};var da={};xs(da,{checkForUpdate:()=>Ed,getCurrent:()=>Bs});var Bs=()=>{try{return"0.17.1"}catch{return"unknown"}};var Lw="https://registry.npmjs.org/craig-cli/latest",Mw=3600*1e3,jw={value:null},qw=(e,t)=>{let n=c=>c.split(".").map(Number),[r=0,s=0,i=0]=n(e),[o=0,a=0,l=0]=n(t);return r!==o?r>o:s!==a?s>a:i>l},Ed=async(e={fetch:globalThis.fetch,getCurrent:Bs,cache:jw})=>{let t=e.getCurrent(),n=Date.now();if(e.cache.value&&n-e.cache.value.cachedAt<Mw)return e.cache.value.result;let r=null;try{let i=await e.fetch(Lw,{signal:AbortSignal.timeout(5e3)});i.ok&&(r=(await i.json()).version??null)}catch{}let s={current:t,latest:r,updateAvailable:r!==null&&r!==t&&qw(r,t)};return e.cache.value={result:s,cachedAt:n},s};var T={load:ca,save:ua,previews:la,runners:aa,version:da};var Od={CLI_USAGE:2,INPUT_REQUIRED:2,WORKSPACE_CONTEXT_NOT_FOUND:3,WORKSPACE_CONTEXT_INVALID:4,WORKSPACE_NOT_FOUND:3,WORKSPACE_RECORD_INVALID:2,TASK_CONTEXT_NOT_FOUND:3,TASK_CONTEXT_AMBIGUOUS:4,TASK_CONTEXT_CONFLICT:4,TASK_NOT_FOUND:3,TASK_RECORD_INVALID:2,REPO_NOT_FOUND:3,REPO_RECORD_INVALID:2,PR_REPOSITORY_MISMATCH:4,PR_BRANCH_MISMATCH:4,EXTERNAL_DEPENDENCY_FAILED:5,OPERATION_TIMEOUT:6,OPERATION_CANCELLED:6,EVENT_CURSOR_INVALID:2,EVENT_CURSOR_EXPIRED:4,EVENT_JOURNAL_CORRUPT:2,COMMAND_NOT_FOUND:3,COMMAND_RECORD_INVALID:2,COMMAND_STATE_CONFLICT:4,CAPABILITY_NOT_FOUND:3,CAPABILITY_RECORD_INVALID:2,CAPABILITY_DENIED:4,DELEGATION_LIMIT_EXCEEDED:4,FURY_DEFINITION_INVALID:2,FURY_INPUT_INVALID:2,FURY_PLAN_NOT_FOUND:3,FURY_APPROVAL_REQUIRED:4,FURY_RUN_NOT_FOUND:3,FURY_REVIEW_NOT_FOUND:3,FURY_RECORD_INVALID:2,FURY_STATE_CONFLICT:4,FURY_OUTPUT_INVALID:4,PARTIAL_RESULT:7,INTERNAL_ERROR:1},g=class extends Error{code;exitCode;retryable;details;constructor(t,n,r){super(n,r.cause===void 0?void 0:{cause:r.cause}),this.name="CraigError",this.code=t,this.exitCode=Od[t],this.retryable=r.retryable??!1,this.details=r.details??{}}};function pa(e){return e instanceof g?e:new g("INTERNAL_ERROR",e instanceof Error?e.message:"Unknown Craig error",{cause:e})}import{appendFile as Uw,mkdir as Ww,readFile as Bw}from"node:fs/promises";import Vw from"node:path";var $d=80,Vs=async(e,t)=>{await Ww(Vw.dirname(e.logFile),{recursive:!0});let n={timestamp:new Date().toISOString(),...t};await Uw(e.logFile,`${JSON.stringify(n)}
5
5
  `,"utf8")},Nd=async(e,t)=>{try{await Vs(e,t)}catch{}},Ks=async(e,t=$d)=>{try{let s=(await Bw(e.logFile,"utf8")).trimEnd().split(`
6
6
  `).filter(i=>i.length>0).map(Kw);return{path:e.logFile,lines:s.slice(Math.max(0,s.length-t)),empty:s.length===0}}catch(n){if(Hw(n))return{path:e.logFile,lines:[],empty:!0};throw n}},fa=async(e,t)=>Vs(e,{level:"error",component:"application",event:Gw(t.context),message:t.message,...t.details?{details:t.details}:{}}),Dd=async(e,t)=>{try{await fa(e,t)}catch{}},_d=Ks,xd=async(e,t=$d)=>Ks(e,t);function Kw(e){try{let t=JSON.parse(e);if(!t.timestamp||!t.level||!t.component||!t.event||!t.message)return e;let n=[t.taskId,t.tabId].filter(Boolean).join("/");return`[${t.timestamp}] ${t.level.toUpperCase().padEnd(5)} ${t.component}.${t.event}${n?` ${n}`:""} \u2014 ${t.message}`}catch{return e}}function Gw(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,".").replace(/^\.+|\.+$/g,"")||"error"}function Hw(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"&&e.code==="ENOENT"}var de={appendErrorLog:fa,appendErrorLogBestEffort:Dd,appendLog:Vs,appendLogBestEffort:Nd,readLog:Ks,readErrorLog:_d,readRecentErrorLines:xd};function jd(e){let{commandTokens:t,options:n,help:r}=zw(e);if(r)return Ld({kind:"help"},n);if(t.length===0)return{mode:"interactive",options:n};let[s,i,...o]=t,a;switch(`${s??""}:${i??""}`){case"context:show":Er(o,"context show"),a={kind:"showContext"};break;case"repo:add":a={kind:"addRepo",path:ma(o,"Repo path")};break;case"repo:list":Er(o,"repo list"),a={kind:"listRepos"};break;case"repo:remove":a={kind:"removeRepo",repoId:X(o,"Repo id")};break;case"workspace:add":a={kind:"addWorkspace",path:ma(o,"Workspace path")};break;case"workspace:list":a=Jw(o);break;case"workspace:archive":a={kind:"archiveWorkspace",workspaceId:X(o,"Workspace id")};break;case"workspace:restore":a={kind:"restoreWorkspace",workspaceId:X(o,"Workspace id")};break;case"workspace:remove":a={kind:"removeWorkspace",workspaceId:X(o,"Workspace id")};break;case"file:open":a={kind:"openFile",path:X(o,"File path")};break;case"task:new":a=Qw(o);break;case"task:create-child":a=Zw(o);break;case"task:children":a={kind:"listTaskChildren",...o.length===0?{}:{taskId:X(o,"Task id")}};break;case"task:cancel-tree":a={kind:"cancelTaskTree",...o.length===0?{}:{taskId:X(o,"Task id")}};break;case"task:list":a=Xw(o);break;case"task:current":Er(o,"task current"),a={kind:"currentTask"};break;case"task:rename":a={kind:"renameTask",title:ma(o,"Task title")};break;case"task:show":a=o.length===0?{kind:"showCurrentTask"}:{kind:"showTask",taskId:X(o,"Task id")};break;case"task:pr":a=ek(o);break;case"task:repo":if(o[0]!=="add")throw S(`Unsupported task repo command: ${o.join(" ")}`);Hs(o,3,"task repo add"),a={kind:"addTaskRepoTarget",taskId:Gs(o,1,"Task id"),repoId:Gs(o,2,"Repo id")};break;case"task:wait":a=ak(o);break;case"agent:list":Er(o,"agent list"),a={kind:"listAgents"};break;case"agent:status":a=rk(o);break;case"agent:send":a=sk(o);break;case"command:show":a={kind:"showPromptCommand",commandId:X(o,"Command id")};break;case"command:list":Er(o,"command list"),a={kind:"listPromptCommands"};break;case"command:cancel":a={kind:"cancelPromptCommand",commandId:X(o,"Command id")};break;case"command:wait":a=ik(o);break;case"events:list":a=Fd(o,!1);break;case"events:watch":a=Fd(o,!0);break;case"fury:validate":a={kind:"validateFury",file:X(o,"Fury file")};break;case"fury:plan":a=lk(o);break;case"fury:approve":a={kind:"approveFury",planId:X(o,"Fury plan id")};break;case"fury:run":a={kind:"runFury",planId:X(o,"Fury plan id")};break;case"fury:status":a={kind:"showFury",runId:X(o,"Fury run id")};break;case"fury:watch":a=ck(o);break;case"fury:cancel":a={kind:"cancelFury",runId:X(o,"Fury run id")};break;case"fury:resume":a={kind:"resumeFury",runId:X(o,"Fury run id")};break;case"fury:step":a=uk(o);break;case"fury:reviews":a=dk(o);break;case"fury:review":a=pk(o);break;case"task:logs":a={kind:"streamTaskLogs",taskId:X(o,"Task id")};break;case"task:diff":a={kind:"showTaskDiff",taskId:X(o,"Task id")};break;case"task:open":a={kind:"openTask",taskId:X(o,"Task id")};break;case"task:check":a={kind:"runChecks",taskId:X(o,"Task id")};break;case"task:commit":a={kind:"commitTask",taskId:X(o,"Task id")};break;case"link:add":a={kind:"addTaskLink",taskId:Gs(o,0,"Task id"),repoId:Gs(o,1,"Repo id")},Hs(o,2,"link add");break;case"link:list":a={kind:"listTaskLinks",taskId:X(o,"Task id")};break;default:if(t.length===1&&(s==="help"||s==="--help"||s==="-h")){a={kind:"help"};break}throw S(`Unsupported command: ${t.join(" ")}`)}return Ld(a,n)}function qd(e){let t=e[0]==="--"?e.slice(1):e,n=!0;for(let r of t){if(r==="--"){n=!1;continue}if(n&&r==="--json")return!0}return!1}function Yw(e){return e.kind==="actFuryReview"?`fury.review.${e.action==="request_changes"?"request-changes":e.action}`:{addWorkspace:"workspace.add",addRepo:"repo.add",listRepos:"repo.list",removeRepo:"repo.remove",listWorkspaces:"workspace.list",archiveWorkspace:"workspace.archive",restoreWorkspace:"workspace.restore",removeWorkspace:"workspace.remove",createTask:"task.new",createChildTask:"task.create-child",listTaskChildren:"task.children",cancelTaskTree:"task.cancel-tree",validateFury:"fury.validate",planFury:"fury.plan",approveFury:"fury.approve",runFury:"fury.run",showFury:"fury.status",watchFury:"fury.watch",cancelFury:"fury.cancel",resumeFury:"fury.resume",completeFuryStep:"fury.step.complete",failFuryStep:"fury.step.fail",listFuryReviews:"fury.reviews.list",showFuryReview:"fury.review.show",actFuryReview:"fury.review.action",listTasks:"task.list",currentTask:"task.current",renameTask:"task.rename",showTask:"task.show",showCurrentTask:"task.show",showTaskPr:"task.pr.show",discoverTaskPr:"task.pr.discover",linkTaskPr:"task.pr.link",refreshTaskPr:"task.pr.refresh",unlinkTaskPr:"task.pr.unlink",listAgents:"agent.list",showAgentStatus:"agent.status",sendAgentPrompt:"agent.send",showPromptCommand:"command.show",listPromptCommands:"command.list",cancelPromptCommand:"command.cancel",waitPromptCommand:"command.wait",waitTask:"task.wait",listEvents:"events.list",watchEvents:"events.watch",addTaskLink:"link.add",addTaskRepoTarget:"task.repo.add",listTaskLinks:"link.list",openFile:"file.open",refreshInteractiveState:"interactive.refresh",showSelectedTask:"task.show",streamTaskLogs:"task.logs",streamSelectedTaskLogs:"task.logs",showTaskDiff:"task.diff",showSelectedTaskDiff:"task.diff",openTask:"task.open",openSelectedTask:"task.open",runChecks:"task.check",runSelectedTaskChecks:"task.check",commitTask:"task.commit",commitSelectedTask:"task.commit",showContext:"context.show",help:"help",exit:"exit"}[e.kind]}function ha(){return["Craig commands:"," craig [--workspace-root <path>] [--task <id>] [--json] [--no-input] <command>"," craig context show Show resolved workspace, task, and agent-tab context"," craig repo add <path> Register a repo in the current Craig workspace"," craig workspace add <path> Register a repo or parent-directory workspace"," craig repo list List registered repos"," craig repo remove <id> Remove a registered repo"," craig workspace list [--archived] List workspaces"," craig workspace archive <id> Archive a workspace"," craig workspace restore <id> Restore an archived workspace"," craig workspace remove <id> Remove an archived workspace"," craig file open <path> Open a readable file in the active Craig TUI (preview)"," craig task new --repo <repo-id> [--runner codex|cursor|claude|pi] <prompt>"," craig task new --workspace <workspace-id> [--runner codex|cursor|claude|pi] <prompt>"," craig task create-child [--parent <task-id>] [--repo <repo-id> | --workspace <workspace-id>] [--runner codex|cursor|claude|pi] [--idempotency-key <key>] <prompt>"," craig task children [<task-id>] List direct child tasks"," craig task cancel-tree [<task-id>] Cancel a task and all descendants"," craig task list [--repo <repo-id>] List known Craig tasks"," craig task current Show the task resolved from flags, environment, or cwd"," craig task rename <name> Rename the resolved task without changing its ID or worktree"," craig task show [<id>] Show task details; omit id to use resolved context"," craig task repo add <task-id> <repo-id> Provision a repo target in an existing project task"," craig task pr show [<id>] [--repo <repo-id>]"," craig task pr discover [<id>] [--repo <repo-id>]"," craig task pr link [<id>] --pr <url|number> [--repo <repo-id>]"," craig task pr refresh [<id>] [--repo <repo-id>]"," craig task pr unlink [<id>] --pr <url|number> [--repo <repo-id>]"," craig agent list [--task <task-id>] List agent-tab and task roll-up states"," craig agent status [--task <task-id>] [--tab <tab-id>] Show agent state details"," craig agent send --task <task-id> [--tab <tab-id>] (--prompt <text> | --prompt-file <path> | --stdin)"," [--delivery when-ready|immediate] [--timeout <duration>] [--idempotency-key <key>]"," craig command show <command-id> Show a durable prompt command"," craig command list [--task <task-id>] List durable prompt commands"," craig command cancel <command-id> Cancel a queued prompt command"," craig command wait <command-id> [--state <states>] [--timeout <duration>]"," craig task wait [<id>] --state <states> [--tab <tab-id>] [--timeout <duration>]"," craig events list [--task <task-id>] [--type <glob>] [--after <cursor>] --json"," craig events watch [--task <task-id>] [--type <glob>] [--after <cursor>] [--format jsonl]"," craig fury validate <file> Validate a versioned fury YAML definition"," craig fury plan <file> [--root-task <id>] [--input key=value] Create an immutable approval plan"," craig fury approve <plan-id> Approve an exact validated plan (human only)"," craig fury run <plan-id> Start the single run authorized by an approved plan"," craig fury status|watch|cancel|resume <run-id> Inspect or control a durable run"," craig fury step complete|fail --run <run-id> --step <step-id> Explicitly finish agent work"," craig fury reviews list [--run <run-id>] [--state <state>] List human checkpoints"," craig fury review show|approve|reject|request-changes|resubmit <review-id>"," craig task logs <id> Stream Craig-managed logs for a task"," craig task diff <id> Show the current worktree diff for a task"," craig task open <id> Open the task worktree or print its path"," craig task check <id> Run configured checks for a task"," craig task commit <id> Commit all task worktree changes"," craig link add <task-id> <repo-id> Add contextual repo linkage only (does not provision a target)"," craig link list <task-id> List linked repos for a task"].join(`
7
7
  `)}function zw(e){let t=[...e];t[0]==="--"&&t.shift();let n=[],r={json:!1,noInput:!1},s=new Set,i=!1,o=!0;for(let a=0;a<t.length;a+=1){let l=t[a];if(l==="--"){o=!1,n.push(l);continue}if(!o||!Md(l)){n.push(l);continue}if(s.has(l))throw S(`Global option ${l} may only be provided once.`);if(s.add(l),l==="--json"){r.json=!0;continue}if(l==="--no-input"){r.noInput=!0;continue}if(l==="--help"||l==="-h"){i=!0;continue}let c=t[a+1];if(c===void 0||c==="--"||Md(c))throw S(`Global option ${l} requires a value.`);a+=1,l==="--workspace-root"?r.workspaceRoot=L(c,"Workspace root"):r.taskId=L(c,"Task id")}return{commandTokens:n,options:r,help:i}}function Jw(e){if(e.length===0)return{kind:"listWorkspaces",archived:!1};if(e.length===1&&e[0]==="--archived")return{kind:"listWorkspaces",archived:!0};throw S(`Unsupported command: workspace list ${e.join(" ")}`)}function Xw(e){if(e.length===0)return{kind:"listTasks"};if(e.length===2&&e[0]==="--repo")return{kind:"listTasks",repoId:L(e[1],"Repo id")};throw S(`Unsupported command: task list ${e.join(" ")}`)}function Qw(e){let t,n,r,s=[],i=!0;for(let a=0;a<e.length;a+=1){let l=e[a];if(l==="--"){i=!1;continue}if(!i||!["--repo","--workspace","--runner"].includes(l)){if(i&&l.startsWith("--"))throw S(`Unsupported task new option: ${l}`);s.push(l);continue}let c=e[a+1];if(c===void 0||c==="--")throw S(`Task option ${l} requires a value.`);if(a+=1,l==="--repo"){if(t!==void 0)throw S("Task option --repo may only be provided once.");t=L(c,"Repo id")}else if(l==="--workspace"){if(n!==void 0)throw S("Task option --workspace may only be provided once.");n=L(c,"Workspace id")}else{if(r!==void 0)throw S("Task option --runner may only be provided once.");try{r=T.runners.parse(c)}catch(d){throw S(d instanceof Error?d.message:"Unsupported runner.")}}}if(!t&&!n)throw S("Task creation requires '--repo <repo-id>' or '--workspace <workspace-id>'.");if(t&&n)throw S("Task creation accepts either '--repo' or '--workspace', not both.");let o=L(s.join(" "),"Task prompt");return{kind:"createTask",...t?{repoId:t}:{},...n?{workspaceId:n}:{},...r?{runner:r}:{},prompt:o}}function Zw(e){let t,n,r,s,i,o=[],a=!0;for(let l=0;l<e.length;l+=1){let c=e[l];if(c==="--"){a=!1;continue}if(!a||!["--parent","--repo","--workspace","--runner","--idempotency-key"].includes(c)){if(a&&c.startsWith("--"))throw S(`Unsupported task create-child option: ${c}`);o.push(c);continue}let d=e[l+1];if(d===void 0||d==="--")throw S(`Task option ${c} requires a value.`);if(l+=1,c==="--parent"){if(t)throw S("Task option --parent may only be provided once.");t=L(d,"Parent task id")}else if(c==="--repo"){if(n)throw S("Task option --repo may only be provided once.");n=L(d,"Repo id")}else if(c==="--workspace"){if(r)throw S("Task option --workspace may only be provided once.");r=L(d,"Workspace id")}else if(c==="--runner"){if(s)throw S("Task option --runner may only be provided once.");try{s=T.runners.parse(d)}catch(u){throw S(u instanceof Error?u.message:"Unsupported runner.")}}else{if(i)throw S("Task option --idempotency-key may only be provided once.");i=L(d,"Idempotency key")}}if(n&&r)throw S("Child task creation accepts only one of --repo or --workspace.");return{kind:"createChildTask",...t?{parentTaskId:t}:{},...n?{repoId:n}:{},...r?{workspaceId:r}:{},prompt:L(o.join(" "),"Child task prompt"),...s?{runner:s}:{},...i?{idempotencyKey:i}:{}}}function ek(e){let[t,...n]=e;if(!["show","discover","link","refresh","unlink"].includes(t??""))throw S(`Unsupported command: task pr ${e.join(" ")}`);let r,s,i;for(let a=0;a<n.length;a+=1){let l=n[a];if(l!=="--repo"&&l!=="--pr"){if(l.startsWith("--"))throw S(`Unsupported task pr ${t} option: ${l}`);if(r!==void 0)throw S(`task pr ${t} accepts at most one task id.`);r=L(l,"Task id");continue}let c=n[a+1];if(c===void 0||c==="--")throw S(`Task PR option ${l} requires a value.`);if(a+=1,l==="--repo"){if(s!==void 0)throw S("Task PR option --repo may only be provided once.");s=L(c,"Repo id")}else{if(i!==void 0)throw S("Task PR option --pr may only be provided once.");i=L(c,"Pull request selector")}}if((t==="link"||t==="unlink")&&i===void 0)throw S(`task pr ${t} requires --pr <url|number>.`);if(t!=="link"&&t!=="unlink"&&i!==void 0)throw S(`task pr ${t} does not accept --pr.`);let o={...r?{taskId:r}:{},...s?{repoId:s}:{}};switch(t){case"show":return{kind:"showTaskPr",...o};case"discover":return{kind:"discoverTaskPr",...o};case"link":return{kind:"linkTaskPr",...o,pullRequest:i};case"refresh":return{kind:"refreshTaskPr",...o};case"unlink":return{kind:"unlinkTaskPr",...o,pullRequest:i};default:throw S(`Unsupported command: task pr ${e.join(" ")}`)}}var ga=300*1e3,tk=new Set(["idle","working","ready","error"]),nk=new Set(["queued","delivering","delivered","failed","cancelled"]);function rk(e){if(e.length===0)return{kind:"showAgentStatus"};if(e.length===2&&e[0]==="--tab")return{kind:"showAgentStatus",tabId:L(e[1],"Agent tab id")};throw S(`Unsupported command: agent status ${e.join(" ")}`)}function sk(e){let t,n,r="when-ready",s=ga,i,o=new Set;for(let a=0;a<e.length;a+=1){let l=e[a];if(!["--prompt","--prompt-file","--stdin","--tab","--delivery","--timeout","--idempotency-key"].includes(l))throw S(`Unsupported agent send option: ${l}`);if(o.has(l))throw S(`Agent send option ${l} may only be provided once.`);if(o.add(l),l==="--stdin"){if(t)throw S("Agent send accepts exactly one prompt source.");t={source:"stdin"};continue}let c=e[a+1];if(c===void 0||c.startsWith("--"))throw S(`Agent send option ${l} requires a value.`);if(a+=1,l==="--prompt"||l==="--prompt-file"){if(t)throw S("Agent send accepts exactly one prompt source.");t=l==="--prompt"?{source:"inline",text:L(c,"Prompt")}:{source:"file",path:L(c,"Prompt file")}}else if(l==="--tab")n=L(c,"Agent tab id");else if(l==="--delivery"){if(c!=="when-ready"&&c!=="immediate")throw S('Agent send delivery must be "when-ready" or "immediate".');r=c}else l==="--timeout"?s=wa(c):i=L(c,"Idempotency key")}if(!t)throw S("Agent send requires --prompt, --prompt-file, or --stdin.");return{kind:"sendAgentPrompt",prompt:t,delivery:r,timeoutMs:s,...n?{tabId:n}:{},...i?{idempotencyKey:i}:{}}}function ik(e){let t=L(e[0]??"","Command id"),n,r=ga,s=new Set;for(let i=1;i<e.length;i+=1){let o=e[i];if(o!=="--state"&&o!=="--timeout")throw S(`Unsupported command wait option: ${o}`);if(s.has(o))throw S(`Command wait option ${o} may only be provided once.`);s.add(o);let a=e[i+1];if(a===void 0||a.startsWith("--"))throw S(`Command wait option ${o} requires a value.`);i+=1,o==="--state"?n=ok(a):r=wa(a)}return{kind:"waitPromptCommand",commandId:t,...n?{states:n}:{},timeoutMs:r}}function ok(e){let t=e.split(",").map(n=>n.trim()).filter(Boolean);if(t.length===0||t.some(n=>!nk.has(n)))throw S(`Invalid command state list "${e}". Use queued, delivering, delivered, failed, or cancelled.`);return[...new Set(t)]}function Fd(e,t){let n,r,s="human",i=new Set;for(let a=0;a<e.length;a+=1){let l=e[a];if(!["--type","--after","--format"].includes(l))throw S(`Unsupported events ${t?"watch":"list"} option: ${l}`);if(!t&&l==="--format")throw S("--format is supported only by events watch.");if(i.has(l))throw S(`Events option ${l} may only be provided once.`);i.add(l);let c=e[a+1];if(c===void 0||c.startsWith("--"))throw S(`Events option ${l} requires a value.`);if(a+=1,l==="--type")n=L(c,"Event type glob");else if(l==="--after")r=L(c,"Event cursor");else if(c==="jsonl")s="jsonl";else throw S('Events watch format must be "jsonl".')}let o={...n?{typeGlob:n}:{},...r?{after:r}:{}};return t?{kind:"watchEvents",...o,format:s}:{kind:"listEvents",...o}}function ak(e){let t,n,r,s=ga,i=new Set;for(let o=0;o<e.length;o+=1){let a=e[o];if(!["--state","--tab","--timeout"].includes(a)){if(a.startsWith("--"))throw S(`Unsupported task wait option: ${a}`);if(t!==void 0)throw S("task wait accepts at most one task id.");t=L(a,"Task id");continue}if(i.has(a))throw S(`Task wait option ${a} may only be provided once.`);i.add(a);let l=e[o+1];if(l===void 0||l.startsWith("--"))throw S(`Task wait option ${a} requires a value.`);o+=1,a==="--state"?n=fk(l):a==="--tab"?r=L(l,"Agent tab id"):s=wa(l)}if(!n)throw S("task wait requires --state <idle|working|ready|error>[,...].");return{kind:"waitTask",...t?{taskId:t}:{},states:n,...r?{tabId:r}:{},timeoutMs:s}}function lk(e){let t,n,r={};for(let s=0;s<e.length;s+=1){let i=e[s];if(i!=="--input"&&i!=="--root-task"){if(i.startsWith("--"))throw S(`Unsupported fury plan option: ${i}`);if(t!==void 0)throw S("fury plan accepts exactly one definition file.");t=L(i,"Fury file");continue}let o=e[s+1];if(o===void 0||o.startsWith("--"))throw S(`Fury plan option ${i} requires a value.`);if(s+=1,i==="--root-task"){if(n)throw S("Fury plan option --root-task may only be provided once.");n=L(o,"Root task id");continue}let a=o.indexOf("=");if(a<1)throw S(`Invalid fury input "${o}". Use key=value.`);let l=L(o.slice(0,a),"Fury input name");if(Object.hasOwn(r,l))throw S(`Fury input "${l}" may only be provided once.`);r[l]=o.slice(a+1)}if(!t)throw S("fury plan requires a definition file.");return{kind:"planFury",file:t,inputs:r,...n?{rootTaskId:n}:{}}}function ck(e){let t=L(e[0]??"","Fury run id"),n,r="human";for(let s=1;s<e.length;s+=2){let i=e[s],o=e[s+1];if(!o||!["--after","--format"].includes(i??""))throw S("fury watch supports --after and --format jsonl.");if(i==="--after")n=L(o,"Event cursor");else if(o==="jsonl")r=o;else throw S("fury watch format must be jsonl.")}return{kind:"watchFury",runId:t,...n?{after:n}:{},format:r}}function uk(e){let t=e[0];if(t!=="complete"&&t!=="fail")throw S("fury step requires complete or fail.");let n=ya(e.slice(1),["--run","--step","--output","--output-file","--stdin","--reason"]),r=L(n.get("--run")??"","Fury run id"),s=L(n.get("--step")??"","Fury step id");if(t==="fail"){if(["--output","--output-file","--stdin"].some(a=>n.has(a)))throw S("fury step fail accepts only --reason.");return{kind:"failFuryStep",runId:r,stepId:s,reason:L(n.get("--reason")??"","Failure reason")}}if(n.has("--reason"))throw S("fury step complete does not accept --reason.");let i=["--output","--output-file","--stdin"].filter(a=>n.has(a));if(i.length>1)throw S("fury step complete accepts only one output source.");let o=i[0];return{kind:"completeFuryStep",runId:r,stepId:s,...o==="--output"?{output:{source:"inline",text:n.get(o)}}:o==="--output-file"?{output:{source:"file",path:n.get(o)}}:o==="--stdin"?{output:{source:"stdin"}}:{}}}function dk(e){if(e[0]!=="list")throw S("fury reviews requires list.");let t=ya(e.slice(1),["--run","--state"]),n=t.get("--run"),r=t.get("--state");if(r&&!["waiting_for_review","changes_requested","approved","rejected","timed_out","cancelled"].includes(r))throw S(`Unsupported fury review state: ${r}`);return{kind:"listFuryReviews",...n?{runId:n}:{},...r?{state:r}:{}}}function pk(e){let t=e[0],n=L(e[1]??"","Fury review id");if(t==="show")return Hs(e,2,"fury review show"),{kind:"showFuryReview",reviewId:n};if(!t||!["approve","reject","request-changes","resubmit"].includes(t))throw S("Unsupported fury review action.");let r=ya(e.slice(2),["--note","--reason","--summary"]),s=t==="request-changes"?"request_changes":t,i=r.get("--note")??r.get("--reason")??r.get("--summary"),o=t==="approve"?"--note":t==="resubmit"?"--summary":"--reason";if([...r.keys()].some(a=>a!==o))throw S(`fury review ${t} accepts only ${o}.`);return{kind:"actFuryReview",reviewId:n,action:s,...i?{message:i}:{}}}function ya(e,t){let n=new Map;for(let r=0;r<e.length;r+=1){let s=e[r];if(!t.includes(s)||n.has(s))throw S(`Unsupported or duplicate option: ${s}`);if(s==="--stdin"){n.set(s,"true");continue}let i=e[++r];if(i===void 0||i.startsWith("--"))throw S(`Option ${s} requires a value.`);n.set(s,L(i,s))}return n}function fk(e){let t=e.split(",").map(n=>n.trim()).filter(Boolean);if(t.length===0||t.some(n=>!tk.has(n)))throw S(`Invalid agent state list "${e}". Use idle, working, ready, or error.`);return[...new Set(t)]}function wa(e){let t=/^(\d+)(ms|s|m|h)$/.exec(e.trim());if(!t)throw S(`Invalid duration "${e}". Use values such as 500ms, 30s, 5m, or 1h.`);let n=Number(t[1]),r={ms:1,s:1e3,m:6e4,h:36e5}[t[2]],s=n*r;if(!Number.isSafeInteger(s))throw S(`Duration "${e}" is too large.`);return s}function Ld(e,t){return{mode:"command",command:e,commandName:Yw(e),options:t}}function Md(e){return["--json","--no-input","--workspace-root","--task","--help","-h"].includes(e)}function Er(e,t){Hs(e,0,t)}function Hs(e,t,n){if(e.length!==t)throw S(`Command ${n} received an unexpected number of arguments.`)}function X(e,t){if(e.length!==1)throw S(`${t} is required and must be provided once.`);return L(e[0],t)}function ma(e,t){return L(e.join(" "),t)}function Gs(e,t,n){return L(e[t]??"",n)}function L(e,t){let n=e.trim();if(n.length===0)throw S(`${t} cannot be empty.`);return n}function S(e){return new g("CLI_USAGE",`${e}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "craig-cli",
3
- "version": "0.17.0",
3
+ "version": "0.17.1",
4
4
  "description": "Craig local control plane CLI",
5
5
  "license": "MIT",
6
6
  "keywords": [