i-plane 2.0.0 → 2.0.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.
@@ -1,2 +1,2 @@
1
- import{ea as b,ga as _,ia as T}from"./cli-jq1agk1s.js";var h=(e)=>{let n=process.env.HTTPS_PROXY??process.env.https_proxy,t=process.env.HTTP_PROXY??process.env.http_proxy,r=e==="https:"?n??t:t??n;return r===void 0||r===""?void 0:r},x=(e)=>{let n=e.split(".");if(n.length!==4)return;let t=0;for(let r of n){if(!/^\d{1,3}$/.test(r))return;let s=Number(r);if(s>255)return;t=t*256+s}return t},P=(e,n)=>{let[t,r]=n.split("/");if(t===void 0||r===void 0)return!1;let s=Number(r);if(!Number.isInteger(s)||s<0||s>32)return!1;let a=x(e),o=x(t);if(a===void 0||o===void 0)return!1;let f=s===0?0:4294967295<<32-s>>>0;return(a&f)===(o&f)},v=(e)=>{let n=process.env.NO_PROXY??process.env.no_proxy??"";if(n.trim()==="")return!1;let t=e.toLowerCase().replace(/\.$/,"").replace(/^\[|\]$/g,"");for(let r of n.split(/[,\s]+/)){let s=r.trim().toLowerCase().replace(/\.$/,"").replace(/^\./,"").replace(/^\[|\]$/g,"");if(s==="")continue;if(s==="*")return!0;if(s.includes("/")&&P(t,s))return!0;if(t===s||t.endsWith(`.${s}`))return!0}return!1},w=(e)=>{let n;try{n=new URL(e)}catch{return!1}if(v(n.hostname))return!1;return h(n.protocol)!==void 0},S=(e)=>{let n=new URL(e);if(v(n.hostname))return;return h(n.protocol==="wss:"?"https:":"http:")},R=(e)=>{if(!w(e))return"directly";let n=h(new URL(e).protocol);if(n===void 0)return"directly";try{let t=new URL(n);return`through proxy ${t.protocol}//${t.host}`}catch{return"through the configured proxy"}},p=(e,n=0)=>{if(n>8||e===null||typeof e!=="object")return!1;let t=e;return t.code==="EPERM"||t.code==="EACCES"||p(t.cause,n+1)||Array.isArray(t.errors)&&t.errors.some((r)=>p(r,n+1))},k=async(e)=>{if(!w(e))return;if(process.env.NODE_USE_ENV_PROXY==="1")return;let n=new URL(e),t=h(n.protocol);if(t===void 0)return;let r;try{r=await import("undici")}catch{return}try{let s=new r.ProxyAgent(t);return(a,o)=>r.fetch(a,{...o,dispatcher:s})}catch(s){let a=s instanceof Error?s.message:String(s);throw Error(`Proxy setting is not a usable URL: ${t} (${a})`)}},A=()=>{let[e=0,n=0]=process.versions.node.split(".").map(Number);return e>=24||e===22&&n>=21},O=async(e)=>{if(!w(e))return;if(process.env.NODE_USE_ENV_PROXY==="1")return;if(process.env.I_PLANE_NO_REEXEC==="1")return;if(!A())throw Error(`A proxy is configured, but Node ${process.versions.node} cannot use it with the built-in fetch. Install the optional dependency (npm install undici) or upgrade to Node 22.21 or newer.`);let{spawnSync:n}=await import("node:child_process"),t=process.argv[1];if(t===void 0)return;return n(process.execPath,[...process.execArgv,t,...process.argv.slice(2)],{stdio:"inherit",env:{...process.env,NODE_USE_ENV_PROXY:"1",I_PLANE_NO_REEXEC:"1"}}).status??1};var y=(e,n)=>{if(n==="")return e;let t=T(e).split(n).join("[token]");for(let r of n.split(/\s+/))if(r.length>=12)t=t.split(r).join("[token]");return t};class c extends Error{status;constructor(e,n){super(e);this.name="PlaneError",this.status=n}}var C=20000;class N{config;transport;transportReady=!1;constructor(e){if(this.config=e,e.token.value)_(e.token.value)}async fetcher(e){if(!this.transportReady)this.transport=await k(e),this.transportReady=!0;return this.transport??fetch}async request(e,n={}){let t=e.startsWith("/")?`${this.config.url.value}${e}`:`${this.config.url.value}/api/v1/workspaces/${this.config.workspace.value}/${e}`,r=new URL(t);for(let[i,d]of Object.entries(n.query??{}))if(d!==void 0)r.searchParams.set(i,String(d));let s=n.timeoutMs??C,a=await this.fetcher(r.toString()),o=new AbortController,f=Date.now(),g=setTimeout(()=>o.abort(),s),m=()=>Math.max(0,s-(Date.now()-f)),u;try{u=await a(r.toString(),{method:n.method??"GET",headers:{"X-API-Key":this.config.token.value,Accept:"application/json",...n.body===void 0?{}:{"Content-Type":"application/json"}},body:n.body===void 0?void 0:JSON.stringify(n.body),signal:o.signal,redirect:"error"})}catch(i){if(i instanceof Error&&i.name==="AbortError")throw clearTimeout(g),new c(`No answer from ${this.config.url.value} within ${s/1000}s.`);let d=i instanceof Error?i.message:String(i),l=i instanceof Error?i.cause:void 0,E=l===void 0?d:`${d} (${[l.name,l.code,l.message].filter(Boolean).join(" ")})`;if(clearTimeout(g),p(i))throw new c(y(`Connection to ${this.config.url.value} ${R(r.toString())} was denied by the operating system (EPERM/EACCES). Check sandbox network permissions and local firewall rules. No HTTP response was received from Plane.`,this.config.token.value));throw new c(y(`Cannot reach ${this.config.url.value}: ${E}`,this.config.token.value))}try{if(!u.ok)throw await this.describeFailure(u,m(),o);if(u.status===204)return;let i=await this.readBody(u,m(),o);if(i==="")return;return JSON.parse(i)}catch(i){if(i instanceof c)throw i;throw new c(y(`Expected JSON from ${r.pathname}: ${i instanceof Error?i.message:String(i)}`,this.config.token.value).slice(0,200))}finally{clearTimeout(g)}}async readBody(e,n,t){let r,s=new Promise((a,o)=>{r=setTimeout(()=>{t.abort(),o(new c(`Response body stalled; gave up after ${n/1000}s.`))},n)});try{return await Promise.race([e.text(),s])}finally{if(r!==void 0)clearTimeout(r)}}async listAll(e,n={}){let t=[],r=new Set,s=n.query?.cursor;if(s!==void 0&&s!==null)r.add(String(s));let a;do{let o=await this.request(e,{...n,query:{...n.query,...a===void 0?{}:{cursor:a}}});if(Array.isArray(o)){t.push(...o);break}if(!o||!Array.isArray(o.results)||o.next_page_results!==void 0&&typeof o.next_page_results!=="boolean")throw new c(`Unexpected paginated response: ${e}`);if(t.push(...o.results),o.next_page_results!==!0)break;if(typeof o.next_cursor!=="string"||!o.next_cursor.trim())throw new c(`Missing or invalid pagination cursor: ${e}`);if(r.has(o.next_cursor))throw new c(`Repeated pagination cursor: ${e}`);r.add(o.next_cursor),a=o.next_cursor}while(a!==void 0);return t}async describeFailure(e,n,t){let r=await this.readBody(e,n,t).catch(()=>""),s=y(r,this.config.token.value).slice(0,300);switch(e.status){case 401:case 403:return new c(`Token rejected (${e.status}). The key from ${this.config.configPath} is not valid for workspace "${this.config.workspace.value}".`,e.status);case 404:return new c(`Not found (404): ${e.url}. Check the workspace slug ("${this.config.workspace.value}") and the project identifier.`,404);case 429:return new c("Rate limited (429). Plane allows 60 API calls a minute.",429);default:return new c(`Plane answered ${e.status}${s===""?"":`: ${s}`}`,e.status)}}}
2
- export{w as I,S as J,R as K,p as L,k as M,O as N,c as O,N as P};
1
+ import{ia as b,ka as _,ma as T}from"./cli-5v4ee99d.js";var h=(e)=>{let n=process.env.HTTPS_PROXY??process.env.https_proxy,t=process.env.HTTP_PROXY??process.env.http_proxy,r=e==="https:"?n??t:t??n;return r===void 0||r===""?void 0:r},x=(e)=>{let n=e.split(".");if(n.length!==4)return;let t=0;for(let r of n){if(!/^\d{1,3}$/.test(r))return;let s=Number(r);if(s>255)return;t=t*256+s}return t},P=(e,n)=>{let[t,r]=n.split("/");if(t===void 0||r===void 0)return!1;let s=Number(r);if(!Number.isInteger(s)||s<0||s>32)return!1;let a=x(e),o=x(t);if(a===void 0||o===void 0)return!1;let f=s===0?0:4294967295<<32-s>>>0;return(a&f)===(o&f)},v=(e)=>{let n=process.env.NO_PROXY??process.env.no_proxy??"";if(n.trim()==="")return!1;let t=e.toLowerCase().replace(/\.$/,"").replace(/^\[|\]$/g,"");for(let r of n.split(/[,\s]+/)){let s=r.trim().toLowerCase().replace(/\.$/,"").replace(/^\./,"").replace(/^\[|\]$/g,"");if(s==="")continue;if(s==="*")return!0;if(s.includes("/")&&P(t,s))return!0;if(t===s||t.endsWith(`.${s}`))return!0}return!1},w=(e)=>{let n;try{n=new URL(e)}catch{return!1}if(v(n.hostname))return!1;return h(n.protocol)!==void 0},S=(e)=>{let n=new URL(e);if(v(n.hostname))return;return h(n.protocol==="wss:"?"https:":"http:")},R=(e)=>{if(!w(e))return"directly";let n=h(new URL(e).protocol);if(n===void 0)return"directly";try{let t=new URL(n);return`through proxy ${t.protocol}//${t.host}`}catch{return"through the configured proxy"}},p=(e,n=0)=>{if(n>8||e===null||typeof e!=="object")return!1;let t=e;return t.code==="EPERM"||t.code==="EACCES"||p(t.cause,n+1)||Array.isArray(t.errors)&&t.errors.some((r)=>p(r,n+1))},k=async(e)=>{if(!w(e))return;if(process.env.NODE_USE_ENV_PROXY==="1")return;let n=new URL(e),t=h(n.protocol);if(t===void 0)return;let r;try{r=await import("undici")}catch{return}try{let s=new r.ProxyAgent(t);return(a,o)=>r.fetch(a,{...o,dispatcher:s})}catch(s){let a=s instanceof Error?s.message:String(s);throw Error(`Proxy setting is not a usable URL: ${t} (${a})`)}},A=()=>{let[e=0,n=0]=process.versions.node.split(".").map(Number);return e>=24||e===22&&n>=21},O=async(e)=>{if(!w(e))return;if(process.env.NODE_USE_ENV_PROXY==="1")return;if(process.env.I_PLANE_NO_REEXEC==="1")return;if(!A())throw Error(`A proxy is configured, but Node ${process.versions.node} cannot use it with the built-in fetch. Install the optional dependency (npm install undici) or upgrade to Node 22.21 or newer.`);let{spawnSync:n}=await import("node:child_process"),t=process.argv[1];if(t===void 0)return;return n(process.execPath,[...process.execArgv,t,...process.argv.slice(2)],{stdio:"inherit",env:{...process.env,NODE_USE_ENV_PROXY:"1",I_PLANE_NO_REEXEC:"1"}}).status??1};var y=(e,n)=>{if(n==="")return e;let t=T(e).split(n).join("[token]");for(let r of n.split(/\s+/))if(r.length>=12)t=t.split(r).join("[token]");return t};class c extends Error{status;constructor(e,n){super(e);this.name="PlaneError",this.status=n}}var C=20000;class N{config;transport;transportReady=!1;constructor(e){if(this.config=e,e.token.value)_(e.token.value)}async fetcher(e){if(!this.transportReady)this.transport=await k(e),this.transportReady=!0;return this.transport??fetch}async request(e,n={}){let t=e.startsWith("/")?`${this.config.url.value}${e}`:`${this.config.url.value}/api/v1/workspaces/${this.config.workspace.value}/${e}`,r=new URL(t);for(let[i,d]of Object.entries(n.query??{}))if(d!==void 0)r.searchParams.set(i,String(d));let s=n.timeoutMs??C,a=await this.fetcher(r.toString()),o=new AbortController,f=Date.now(),g=setTimeout(()=>o.abort(),s),m=()=>Math.max(0,s-(Date.now()-f)),u;try{u=await a(r.toString(),{method:n.method??"GET",headers:{"X-API-Key":this.config.token.value,Accept:"application/json",...n.body===void 0?{}:{"Content-Type":"application/json"}},body:n.body===void 0?void 0:JSON.stringify(n.body),signal:o.signal,redirect:"error"})}catch(i){if(i instanceof Error&&i.name==="AbortError")throw clearTimeout(g),new c(`No answer from ${this.config.url.value} within ${s/1000}s.`);let d=i instanceof Error?i.message:String(i),l=i instanceof Error?i.cause:void 0,E=l===void 0?d:`${d} (${[l.name,l.code,l.message].filter(Boolean).join(" ")})`;if(clearTimeout(g),p(i))throw new c(y(`Connection to ${this.config.url.value} ${R(r.toString())} was denied by the operating system (EPERM/EACCES). Check sandbox network permissions and local firewall rules. No HTTP response was received from Plane.`,this.config.token.value));throw new c(y(`Cannot reach ${this.config.url.value}: ${E}`,this.config.token.value))}try{if(!u.ok)throw await this.describeFailure(u,m(),o);if(u.status===204)return;let i=await this.readBody(u,m(),o);if(i==="")return;return JSON.parse(i)}catch(i){if(i instanceof c)throw i;throw new c(y(`Expected JSON from ${r.pathname}: ${i instanceof Error?i.message:String(i)}`,this.config.token.value).slice(0,200))}finally{clearTimeout(g)}}async readBody(e,n,t){let r,s=new Promise((a,o)=>{r=setTimeout(()=>{t.abort(),o(new c(`Response body stalled; gave up after ${n/1000}s.`))},n)});try{return await Promise.race([e.text(),s])}finally{if(r!==void 0)clearTimeout(r)}}async listAll(e,n={}){let t=[],r=new Set,s=n.query?.cursor;if(s!==void 0&&s!==null)r.add(String(s));let a;do{let o=await this.request(e,{...n,query:{...n.query,...a===void 0?{}:{cursor:a}}});if(Array.isArray(o)){t.push(...o);break}if(!o||!Array.isArray(o.results)||o.next_page_results!==void 0&&typeof o.next_page_results!=="boolean")throw new c(`Unexpected paginated response: ${e}`);if(t.push(...o.results),o.next_page_results!==!0)break;if(typeof o.next_cursor!=="string"||!o.next_cursor.trim())throw new c(`Missing or invalid pagination cursor: ${e}`);if(r.has(o.next_cursor))throw new c(`Repeated pagination cursor: ${e}`);r.add(o.next_cursor),a=o.next_cursor}while(a!==void 0);return t}async describeFailure(e,n,t){let r=await this.readBody(e,n,t).catch(()=>""),s=y(r,this.config.token.value).slice(0,300);switch(e.status){case 401:case 403:return new c(`Token rejected (${e.status}). The key from ${this.config.configPath} is not valid for workspace "${this.config.workspace.value}".`,e.status);case 404:return new c(`Not found (404): ${e.url}. Check the workspace slug ("${this.config.workspace.value}") and the project identifier.`,404);case 429:return new c("Rate limited (429). Plane allows 60 API calls a minute.",429);default:return new c(`Plane answered ${e.status}${s===""?"":`: ${s}`}`,e.status)}}}
2
+ export{w as M,S as N,R as O,p as P,k as Q,O as R,c as S,N as T};
@@ -0,0 +1,2 @@
1
+ import{A as ge,B as z,C as Se,D as Z,F as Ye,G as ee,K as P,l as le,n as N,o as O,p as F,x as de,y as fe,z as me}from"./cli-hgk20taa.js";import{N as xe,S as d}from"./cli-tdf7t5es.js";import{aa as h,ba as U,ca as C}from"./cli-2sf0pmt1.js";import{fa as Ue,ga as Re,ka as q,ma as k,na as E}from"./cli-5v4ee99d.js";var se=Re(function(et,ae){var W=!0,ie=!1,oe=!1;ae.exports=function(e,t){if(t)W=!t.enabled,ie=!!t.label,oe=!!t.labelAfter;e.core.ruler.after("inline","github-task-lists",function(r){var n=r.tokens;for(var i=2;i<n.length;i++)if(Me(n,i))Ce(n[i],r.Token),ne(n[i-2],"class","task-list-item"+(!W?" enabled":"")),ne(n[Xe(n,i-2)],"class","contains-task-list")})};function ne(e,t,r){var n=e.attrIndex(t),i=[t,r];if(n<0)e.attrPush(i);else e.attrs[n]=i}function Xe(e,t){var r=e[t].level-1;for(var n=t-1;n>=0;n--)if(e[n].level===r)return n;return-1}function Me(e,t){return je(e[t])&&qe(e[t-1])&&Oe(e[t-2])&&Fe(e[t])}function Ce(e,t){if(e.children.unshift(Te(e,t)),e.children[1].content=e.children[1].content.slice(3),e.content=e.content.slice(3),ie)if(oe){e.children.pop();var r="task-item-"+Math.ceil(Math.random()*1e7-1000);e.children[0].content=e.children[0].content.slice(0,-1)+' id="'+r+'">',e.children.push(De(e.content,r,t))}else e.children.unshift(Ne(t)),e.children.push(Be(t))}function Te(e,t){var r=new t("html_inline","",0),n=W?' disabled="" ':"";if(e.content.indexOf("[ ] ")===0)r.content='<input class="task-list-item-checkbox"'+n+'type="checkbox">';else if(e.content.indexOf("[x] ")===0||e.content.indexOf("[X] ")===0)r.content='<input class="task-list-item-checkbox" checked=""'+n+'type="checkbox">';return r}function Ne(e){var t=new e("html_inline","",0);return t.content="<label>",t}function Be(e){var t=new e("html_inline","",0);return t.content="</label>",t}function De(e,t,r){var n=new r("html_inline","",0);return n.content='<label class="task-list-item-label" for="'+t+'">'+e+"</label>",n.attrs=[{for:t}],n}function je(e){return e.type==="inline"}function qe(e){return e.type==="paragraph_open"}function Oe(e){return e.type==="list_item_open"}function Fe(e){return e.content.indexOf("[ ] ")===0||e.content.indexOf("[x] ")===0||e.content.indexOf("[X] ")===0}});import{readFile as Qe}from"node:fs/promises";import{createHash as Ie,randomUUID as _e}from"node:crypto";var ue=Ue(se(),1);import*as m from"yjs";var X=(e)=>{let t=new Set,r=(n)=>{if(!(n instanceof m.XmlElement))return;if(n.nodeName.toLowerCase()==="knowledgereview")t.add("knowledgeReview");for(let i of n.toArray())r(i)};return e.forEach(r),[...t]},L=(e)=>String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"),x=(e,t)=>t==null||t===""?"":` ${e}="${L(t)}"`,T=(e)=>{if(Array.isArray(e))return e.map(T);if(e&&typeof e==="object")return Object.fromEntries(Object.entries(e).sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>[t,T(r)]));return e},He=new Set(["doc","paragraph","heading","bulletlist","orderedlist","listitem","tasklist","taskitem","blockquote","codeblock","horizontalrule","hardbreak","table","tablerow","tableheader","tablecell","imagecomponent","image","knowledgereview"]),pe=(e,t=!0)=>e instanceof m.XmlText?{text:T(e.toDelta())}:{kind:e.nodeName,attributes:T(Object.fromEntries(Object.entries(e.getAttributes()).filter(([r])=>r!=="id"||!(t||He.has(e.nodeName.toLowerCase()))))),children:e.toArray().map((r)=>pe(r,!1))},J=(e)=>Ie("sha256").update(JSON.stringify(pe(e))).digest("hex"),R=(e)=>e instanceof m.XmlElement&&e.nodeName==="knowledgeReview"?`Reviewed ${String(e.getAttribute("reviewedAt")??"")}: ${String(e.getAttribute("source")??"")}`:e instanceof m.XmlText?e.toDelta().map((t)=>typeof t.insert==="string"?t.insert:JSON.stringify(t.insert)).join(""):e.toArray().map((t)=>R(t)).join(" "),he=(e)=>e.toArray().map((t,r)=>{let n=t instanceof m.XmlElement?String(t.getAttribute("id")??"")||null:null;return{index:r,anchor:n,shortAnchor:n?k(n).slice(0,8):null,kind:t instanceof m.XmlElement?t.nodeName:"text",preview:k(R(t)).replace(/\s+/g," ").trim().slice(0,40)}}),B=(e,t)=>{let r=e.toArray().flatMap((i,a)=>{if(!(i instanceof m.XmlElement))return[];let l=String(i.getAttribute("id")??"");return l.length>0&&l.toLowerCase().startsWith(t.toLowerCase())?[{node:i,index:a,anchor:l}]:[]});if(r.length===0)throw new d(`No top-level block matches "${t}". Run page outline to see current anchors.`,404);if(r.length!==1)throw new h(`Ambiguous block anchor "${t}": ${r.map((i)=>`${i.anchor} [${i.index}]`).join(", ")}`);let n=r[0];if(!n)throw new d("Block disappeared.");return n},K=(e)=>{let t=0;for(let r of e.toArray())if(r instanceof m.XmlElement&&!r.getAttribute("id"))r.setAttribute("id",_e()),t++;return t},D=(e,t,r=!1)=>{if(e instanceof m.XmlText){let o=R(e),s=r?k(o):o;if(s!==o)return t.add("Sensitive text was redacted; the printed block is not a lossless copy"),L(s);return e.toDelta().map((f)=>{let c=L(typeof f.insert==="string"?f.insert:JSON.stringify(f.insert));for(let[p,w]of Object.entries(f.attributes??{})){let y=Object.fromEntries(Object.entries(w&&typeof w==="object"?w:{}).map(([A,b])=>[A,r&&typeof b==="string"?k(b):b]));if(p==="bold")c=`<strong>${c}</strong>`;else if(p==="italic")c=`<em>${c}</em>`;else if(p==="strike")c=`<s>${c}</s>`;else if(p==="code")c=`<code>${c}</code>`;else if(p==="link")c=`<a${x("href",y.href)}${x("title",y.title)}>${c}</a>`;else if(t.add(`Mark ${p} is not representable by this Markdown reader`),p==="underline")c=`&lt;u&gt;${c}&lt;/u&gt;`}return c}).join("")}let n=e.nodeName.toLowerCase(),i=Object.fromEntries(Object.entries(e.getAttributes()).map(([o,s])=>[o,r&&typeof s==="string"?k(s):s])),a=()=>e.toArray().map((o)=>D(o,t,r)).join("");if(i.textAlign&&i.textAlign!=="left")t.add("Text alignment is not representable in Markdown");if(n==="knowledgereview"){let o=String(i.reviewedAt??""),s=String(i.source??"");if(typeof i.reviewedAt!=="string"||typeof i.source!=="string"||!fe(o)||!s.trim())t.add("Review metadata is invalid");if(Object.keys(i).some((f)=>!["id","reviewedAt","source"].includes(f))||e.length)t.add("Additional review attributes or content are not represented in Markdown");if(r&&(i.reviewedAt!==e.getAttribute("reviewedAt")||i.source!==e.getAttribute("source")))t.add("Sensitive review metadata was redacted; the printed block is not a lossless copy");return z({date:o,source:s})}if(n==="doc")return a();if(n==="paragraph")return`<p>${a()}</p>`;if(n==="heading"){let o=Math.min(6,Math.max(1,Number(i.level)||1));return`<h${o}>${a()}</h${o}>`}if(n==="bulletlist")return`<ul>${a()}</ul>`;if(n==="orderedlist")return`<ol${x("start",i.start)}>${a()}</ol>`;if(n==="listitem")return`<li>${a()}</li>`;if(n==="tasklist")return`<ul>${a()}</ul>`;if(n==="taskitem"){let o=`<input type="checkbox"${i.checked===!0||i.checked==="true"?" checked":""}>`,s=a().replace(/^<p>([\s\S]*?)<\/p>/,"$1");return`<li>${o}${s}</li>`}if(n==="blockquote")return`<blockquote>${a()}</blockquote>`;if(n==="codeblock"&&i.language==="knowledge-review")t.add("The knowledge-review fence language is reserved for review metadata");if(n==="codeblock")return`<pre><code${i.language?x("class",`language-${i.language}`):""}>${L(r?k(R(e)):R(e))}</code></pre>`;if(n==="horizontalrule")return"<hr>";if(n==="hardbreak")return"<br>";if(n==="table")return`<table>${a()}</table>`;if(n==="tablerow")return`<tr>${a()}</tr>`;if(n==="tablecell"||n==="tableheader"){let o=e.toArray().filter((c)=>c instanceof m.XmlElement),s=(c)=>c.nodeName.toLowerCase()==="hardbreak"||c.toArray().some((p)=>p instanceof m.XmlElement&&s(p));if(o.length>1||o.some((c)=>c.nodeName.toLowerCase()!=="paragraph"||s(c)))t.add("Multiple paragraphs, line breaks or block structure inside table cells are flattened in Markdown");if(Number(i.colspan??1)!==1||Number(i.rowspan??1)!==1)t.add("Merged table cells are not representable in Markdown");if(i.background||i.colwidth)t.add("Table styling is not representable in Markdown");let f=n==="tablecell"?"td":"th";return`<${f}>${a()}</${f}>`}if(n==="imagecomponent"||n==="image"){if(i.width||i.height||i.alignment)t.add("Image dimensions or alignment are not representable in Markdown");return`<img${x("src",i.src)}${x("alt",i.alt)}${x("title",i.title)}>`}t.add(`Unsupported node ${e.nodeName}; preserved as XML text`);let l=e.toString();return`<pre><code class="language-xml">${L(r?de(l):l)}</code></pre>`},We=(e)=>{let t=new Set,r=e.toArray().map((n)=>D(n,t)).join("");return{markdown:N(r),losses:[...t]}},we=(e,t)=>{let{node:r,anchor:n}=B(e,t),i=new Set;return{anchor:n,fingerprint:J(r),markdown:N(D(r,i,!0)),losses:[...i]}},ke=(e)=>{let t=new Set;for(let r of e)D(r,t);return[...t]},M=new le({html:!1}).use(ue.default),ze=M.renderer.rules.fence;M.renderer.rules.fence=(e,t,r,n,i)=>{let a=e[t];if(/^knowledge-review\s/.test(a?.info.trim()??""))throw new h("A knowledge-review fence does not accept additional info fields.");if(a?.info.trim()==="knowledge-review"){let l=me(a.content);if(!n?.reviewAsCode&&n?.requiredNodes instanceof Set)n.requiredNodes.add("knowledgeReview");return n?.reviewAsCode?z(l):ge(l)}return ze?.(e,t,r,n,i)??i.renderToken(e,t,r)};M.core.ruler.before("github-task-lists","empty-task-items",(e)=>{for(let t=2;t<e.tokens.length;t++){let r=e.tokens[t],n=r?.children?.[0];if(r&&n&&/^\[[ xX]\]$/.test(r.content)&&e.tokens[t-1]?.tag==="p"&&e.tokens[t-2]?.tag==="li")r.content+=" ",n.content+=" "}});var be=(e)=>e.toArray().flatMap((t)=>t instanceof m.XmlElement?[...t.nodeName.toLowerCase()==="codeblock"?[t]:[],...be(t)]:[]),ce=(e,t=!1,r)=>M.render(e,{reviewAsCode:t,requiredNodes:r}).trim().replace(/(<li class="task-list-item">)\s*<p>([\s\S]*?)<\/p>/g,"$1$2").replace(/(<input class="task-list-item-checkbox"[^>]*>) /g,"$1"),ye=async(e,t)=>{let r=new Set,n=ce(t,!1,r);if(r.size)P([...r],await e.nodeReaders?.()??[]);if(!n){let o=new m.Doc;return{doc:o,fragment:o.getXmlFragment("default"),losses:[]}}let i=n.replace(/<img([^>]*?)\s*\/?>/g,"<image-component$1></image-component>").replace(/<ul class="contains-task-list">/g,'<ul data-type="taskList">').replace(/<li class="task-list-item">(\s*<p>)?<input\b([^>]*)>/g,(o,s,f)=>`<li data-type="taskItem" data-checked="${/\bchecked=/.test(f)}">${s??""}`),a=await e.request("/live/convert-document",{method:"POST",body:{description_html:i,variant:"rich"}}),l=new m.Doc;try{if(typeof a.description_binary!=="string"||!a.description_binary)throw Error("Missing document binary");m.applyUpdate(l,Buffer.from(a.description_binary,"base64"));let o=l.getXmlFragment("default"),s=M.parse(t,{}).filter((w)=>w.block&&w.tag==="code"&&w.info.trim()!=="knowledge-review").map((w)=>w.info.trim().split(/\s+/)[0]||null),f=be(o),c=[];if(s.length!==f.length)c.push("The converter changed the number of code blocks");else l.transact(()=>f.forEach((w,S)=>{let y=s[S];if(y)w.setAttribute("language",y);else w.removeAttribute("language")}));if(We(o).markdown!==N(ce(t,!0)))c.push("The converter changed Markdown content or formatting");return l.transact(()=>K(o)),{doc:l,fragment:o,losses:c}}catch(o){if(l.destroy(),o instanceof d)throw o;throw new d(`Cannot decode the converted document: ${o instanceof Error?o.message:String(o)}`)}};import*as j from"yjs";var V=(e,t=!1)=>{if(e.length&&!t)throw new h(`This edit can lose content or formatting: ${e.join("; ")}. Inspect the document, then pass --allow-loss to accept these losses.`)},ve=(e,t,r)=>{let n=t.block?B(e,t.block):void 0;if(n&&t.ifMatch&&!t.force&&J(n.node)!==t.ifMatch)throw new d("Block content changed since page read. Read it again and use its new --if-match fingerprint, or pass --force to overwrite the concurrent edit.",409);let i=r?.fragment.length??0;if(t.kind!=="rm"&&!r)throw new h("Expected Markdown content.");if((t.kind==="insert"||n&&t.kind==="set")&&i===0)throw new h("Empty block content. Use page rm --block to remove a block.");let a=t.kind==="insert"?[]:n?[n.node]:e.toArray(),l=[...new Set([...r?.losses??[],...ke(a)])];if(t.kind!=="rm")V(l,t.allowLoss);let o=n?.index??0;if(t.kind==="insert")o=t.after?B(e,t.after).index+1:e.length;let s=r?.fragment.toArray().map((c)=>{if(!(c instanceof j.XmlElement)&&!(c instanceof j.XmlText))throw new d("Unsupported document block; no changes were made.");return c.clone()})??[],f=e.toArray();if(t.kind!=="insert")f.splice(o,n?1:f.length);if(P(X([...f,...t.kind==="rm"?[]:r?.fragment.toArray()??[]]),t.nodeReaders??[]),t.kind!=="insert")e.delete(o,n?1:e.length);if(t.kind!=="rm"&&s.length){if(e.insert(o,s),n&&s[0]&&"setAttribute"in s[0])s[0].setAttribute("id",n.anchor)}return t.kind==="rm"?[]:l};import{HocuspocusProvider as Je,HocuspocusProviderWebsocket as Ke}from"@hocuspocus/provider";import{HttpsProxyAgent as Ve}from"https-proxy-agent";import Ge from"ws";import*as $e from"yjs";class G extends d{}class Ae{doc=new $e.Doc;fragment=this.doc.getXmlFragment("default");socket;provider;agent;pending;failure;writing=!1;acknowledged=!1;disposed=!1;deadline;constructor(e,t,r,n=20000){this.deadline=n,q(r);let i=xe(e);if(i)q(i),this.agent=new Ve(i);let a=this.agent;class l extends Ge{constructor(o){super(o,{agent:a,handshakeTimeout:n})}}this.socket=new Ke({url:e,WebSocketPolyfill:l,autoConnect:!1,maxAttempts:1,onClose:()=>this.fail(new d("Live connection closed."))}),this.socket.on("maxAttemptsFailed",()=>this.fail(new d("Cannot connect to the live server."))),this.provider=new Je({websocketProvider:this.socket,name:t,document:this.doc,awareness:null,token:r,forceSyncInterval:!1,flushDelay:!1,onClose:()=>this.fail(new d("Live document connection closed.")),onSynced:()=>this.progress(),onUnsyncedChanges:()=>this.progress(),onAuthenticationFailed:()=>this.fail(new G("Live authentication was refused."))}),this.provider.attach()}progress(){if(this.disposed||this.failure||!this.provider?.isSynced||this.provider.hasUnsyncedChanges)return;if(this.writing)this.acknowledged=!0;this.pending?.resolve()}fail(e){if(this.disposed||this.failure)return;if(this.writing&&!this.acknowledged)e=new d("Live connection failed after sending changes; delivery is uncertain. Inspect the live document before retrying. The command was not replayed.");this.failure=e,this.socket.shouldConnect=!1,this.pending?.reject(e)}async wait(e){if(this.failure)throw this.failure;let t;try{await new Promise((r,n)=>{this.pending={resolve:r,reject:n},t=setTimeout(()=>this.fail(new d("Live synchronization timed out.")),this.deadline),e(),this.progress()})}finally{clearTimeout(t),this.pending=void 0}}async ready(){await this.wait(()=>{this.socket.connect().catch(()=>this.fail(new d("Cannot connect to the live server.")))})}async write(e){if(this.failure)throw this.failure;if(!this.provider.isSynced)throw new d("Live document is not synchronized.");if(this.provider.authorizedScope!=="read-write")throw new d("The connection does not allow writing this page.");let t=!1,r=(n,i)=>{if(i===this)t=!0};this.doc.on("update",r);try{return await this.wait(()=>{this.writing=!0,this.doc.transact(()=>e(this.fragment),this)}),{delivery:t?"acknowledged":"unchanged",persistence:"asynchronous"}}finally{this.doc.off("update",r)}}destroy(){if(this.disposed)return;this.disposed=!0,this.provider.destroy(),this.socket.destroy(),this.agent?.destroy(),this.doc.destroy()}}var Pe=async(e,t,r,n={})=>{await e.preparePages?.(t);let i=!!n.writable,a=await e.liveCredentials?.(i);if(!a){q(e.config.token.value);let l=await e.request("/api/extensions/configuration/").catch((o)=>{if(o instanceof d&&o.status===404)throw new d("Page commands require the for-plane API-key pages extension.",404);throw o});if(typeof l.release!=="string"||!l.release)throw new d("The for-plane runtime has no active extension release.");a={release:l.release,token:JSON.stringify({apiKey:e.config.token.value,readOnly:!i})}}for(let l=0;l<2;l++){let o=new URL(`${e.config.url.value}/live/collaboration`);if(o.protocol=o.protocol==="https:"?"wss:":"ws:",o.searchParams.set("documentType","project_page"),o.searchParams.set("projectId",t),o.searchParams.set("workspaceSlug",e.config.workspace.value),a.release)o.searchParams.set("forPlaneRelease",a.release);let s=new Ae(o.href,r,a.token);try{return await s.ready(),s}catch(f){if(s.destroy(),l===0&&f instanceof G){let c=await e.liveCredentials?.(i,!0);if(c){a=c;continue}}throw new d(k(f instanceof Error?f.message:String(f)))}}throw new d("Live session authentication failed after one refresh.")};var Ze=async(e,t=!1)=>{let r=U(e,"file"),n=U(e,"text");if(r!==void 0&&n!==void 0)throw new h("--file and --text are mutually exclusive.");if(r!==void 0)try{return await Qe(r,"utf8")}catch{throw new h(`Cannot read Markdown file "${r}".`)}if(n!==void 0||t)return n;throw new h("Expected --file <path> or --text <markdown>.")},Ee=(e)=>{if(e.length)console.error(k(`Warning: ${e.join("; ")}`))},Q=(e)=>`${e.id} ${e.deleted?"deleted":e.delivery??"created"}${e.stamped!==void 0?`; stamped ${e.stamped} blocks`:""}${e.delivery?"; database persistence is asynchronous":""}`,Ct=async(e,t,r,n)=>{let i=O(r.positionals[0],"a project"),a=e==="page create",l=e==="page rm",o=a?F(r,"name"):O(r.positionals[1],"a page UUID or name"),s=r.flags.has("block")?F(r,"block"):void 0,f=r.flags.has("after")?F(r,"after"):void 0,c=C(r,"at-end"),p=U(r,"if-match"),w=C(r,"force"),S=C(r,"allow-loss");if(l&&!C(r,"yes"))throw new h("Deletion requires --yes.");if((p!==void 0||w)&&!s)throw new h("--if-match and --force require --block.");if(p!==void 0&&!/^[a-f0-9]{64}$/i.test(p))throw new h("--if-match expects the SHA-256 fingerprint from page read --json.");if(e==="page read"&&!s)throw new h("Expected --block <anchor>.");if(e==="page insert"&&Boolean(f)===c)throw new h("Choose exactly one of --after <anchor> or --at-end.");let y=a||e==="page set"||e==="page insert"?await Ze(r,a):void 0,A=await Se(t,i),b,I;try{if(y!==void 0)b=await ye(t,y),V(b.losses,S);let g=a?await t.request(Z(A.id),{method:"POST",body:{name:o,access:0}}):await Ye(t,A.id,o);if(a)I=g;if(a&&!b){E({id:g.id,name:g.name},n,Q);return}if(l&&!s){ee(g,!0);let v=`${Z(A.id)}${g.id}/`;if(!g.archived_at)try{await t.request(`${v}archive/`,{method:"POST"})}catch(u){throw new d(`Archiving page ${g.id} was not confirmed: ${u instanceof Error?u.message:String(u)}. Inspect this UUID before retrying; deletion was not attempted.`)}try{await t.request(v,{method:"DELETE"})}catch(u){throw new d(`Page ${g.id} was archived, but deletion was not confirmed: ${u instanceof Error?u.message:String(u)}. Inspect it by UUID before retrying.`)}E({id:g.id,deleted:!0},n,Q);return}let te=e==="page outline"||e==="page read";if(!te)ee(g);let Y=await Pe(t,A.id,g.id,{writable:!te});try{if(e==="page outline")E(he(Y.fragment),n,(v)=>v.map((u)=>`${u.index} ${u.shortAnchor??"(no anchor)"} ${u.kind} ${u.preview}`).join(`
2
+ `));else if(e==="page read"){let v=we(Y.fragment,O(s,"--block <anchor>"));Ee(v.losses),E(v,n,(u)=>u.markdown)}else{let u=X([...Y.fragment.toArray(),...b?.fragment.toArray()??[]]).length?await t.nodeReaders?.()??[]:[],re,_=[];t.markPageMutation?.();let Le=await Y.write((H)=>{if(e==="page stamp")P(X(H.toArray()),u),re=K(H);else _=ve(H,{kind:l?"rm":e==="page insert"?"insert":"set",block:s,after:f,atEnd:c,ifMatch:p?.toLowerCase(),force:w,allowLoss:S,nodeReaders:u},b)});Ee(_),E({id:g.id,...Le,stamped:re,losses:_},n,Q)}}finally{Y.destroy()}}catch(g){if(I)throw new d(`Page ${I.id} was created, but its content operation did not complete: ${g instanceof Error?g.message:String(g)}. Inspect this page before retrying; do not create a duplicate.`);throw g}finally{b?.doc.destroy()}};export{Ct as runPageContent};
@@ -0,0 +1 @@
1
+ import{a as l}from"./cli-8wxcra9k.js";import{aa as d}from"./cli-2sf0pmt1.js";import{ka as f}from"./cli-5v4ee99d.js";import{homedir as p}from"node:os";import{join as a}from"node:path";var u=(o,c)=>{let g=l(o.configPath,["PLANE_LOGIN","PLANE_PASSWORD"]),n=(s)=>{let i=process.env[s];if(i)return{value:i,origin:"env"};let t=g.get(s);return t?{value:t,origin:"file"}:void 0},r=n("PLANE_LOGIN"),e=n("PLANE_PASSWORD");if(e)f(e.value);if(!r||!e)throw new d(`This Plane does not expose the API-key pages endpoint. Set PLANE_LOGIN and PLANE_PASSWORD in the environment or ${o.configPath} to use its session API. If extensions were just installed, retry with --refresh-pages.`);return{...o,login:r,password:e,cacheDirectory:c??process.env.PLANE_SESSION_CACHE??a(process.env.XDG_CACHE_HOME??a(p(),".cache"),"i-plane","sessions")}};export{u as resolveSessionConfig};
@@ -0,0 +1 @@
1
+ import{O,P as R,Q as b,S as a}from"./cli-tdf7t5es.js";import{ka as u,ma as S}from"./cli-5v4ee99d.js";import{createHash as T,randomUUID as D}from"node:crypto";import{constants as y}from"node:fs";import{chmod as N,lstat as _,mkdir as q,open as k,rename as E,stat as F,unlink as g}from"node:fs/promises";import{join as L}from"node:path";import{setTimeout as j}from"node:timers/promises";var H=20000,x=(e)=>(u(e.sessionId),u(e.csrf),u(P(e)),e),P=(e)=>`session-id=${e.sessionId}; csrftoken=${e.csrf}`,J=(e,i,t)=>L(t,`${T("sha256").update(JSON.stringify([e,i])).digest("hex")}.json`),C=async(e)=>{try{let i=await k(e,y.O_RDONLY|y.O_NOFOLLOW|y.O_NONBLOCK),t;try{let r=await i.stat();if((r.mode&63)!==0||!r.isFile()||r.size>16384)return;t=JSON.parse(await i.readFile("utf8"))}finally{await i.close()}if(t.version!==1||typeof t.userId!=="string"||!t.userId||typeof t.sessionId!=="string"||!t.sessionId||typeof t.csrf!=="string"||!t.csrf||/[;\r\n]/.test(t.sessionId+t.csrf)||typeof t.expiresAt!=="number"||!Number.isFinite(t.expiresAt))return;return x(t),t.expiresAt>Date.now()?t:void 0}catch{return}};class U{config;cachePath;current;flight;constructor(e){if(this.config=e,this.cachePath=J(e.url.value,e.login.value,e.cacheDirectory),u(e.password.value),e.token.value)u(e.token.value)}async raw(e,i={},t=H){let r=`${this.config.url.value}${e}`,o=new AbortController,n;try{let s=await b(r)??fetch,c=new Promise((d,f)=>{n=setTimeout(()=>{o.abort(),f(new a(`Session request timed out after ${t/1000}s: ${e}`))},t)});return await Promise.race([(async()=>{let d=await s(r,{...i,redirect:"manual",signal:o.signal});return{status:d.status,headers:d.headers,text:await d.text()}})(),c])}catch(s){if(s instanceof a)throw s;let c=R(s)?`Connection ${O(r)} denied by the operating system; check sandbox network permissions.`:s instanceof Error?s.message:String(s);throw new a(S(`Session request failed: ${c}`))}finally{if(n!==void 0)clearTimeout(n)}}parse(e,i){if(e.status<200||e.status>=300){let t=e.status===403?" Check page permissions, lock state and CSRF credentials.":"";throw new a(S(`Plane session API answered ${e.status} for ${i}.${t} ${e.text}`).slice(0,450),e.status)}if(!e.text||e.status===204)return;try{return JSON.parse(e.text)}catch{throw new a(`Expected JSON from session API: ${i}`)}}async authenticate(){let e=new Map,i=Date.now()+86400000,t=(w)=>{for(let h of w.getSetCookie()){let[m=""]=h.split(";"),p=m.indexOf("="),I=m.slice(0,p).trim(),l=m.slice(p+1).trim();if(p<1||!["session-id","csrftoken"].includes(I))continue;if(/[;\r\n]/.test(l))throw new a("Invalid session cookie received.");if(l)u(l);e.set(I,l);let A=/(?:^|;)\s*max-age=(-?\d+)/i.exec(h)?.[1];if(A!==void 0)i=Math.min(i,Date.now()+Number(A)*1000)}},r=await this.raw("/auth/get-csrf-token/");t(r.headers);let o=this.parse(r,"/auth/get-csrf-token/").csrf_token??e.get("csrftoken");if(!o)throw new a("Plane did not provide a CSRF token.");u(o);let n=[...e].map(([w,h])=>`${w}=${h}`).join("; ");if(n)u(n);let s=await this.raw("/auth/sign-in/",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Referer:`${this.config.url.value}/`,Cookie:n},body:new URLSearchParams({csrfmiddlewaretoken:o,email:this.config.login.value,password:this.config.password.value}).toString()});t(s.headers);let c=e.get("session-id"),d=e.get("csrftoken");if(![200,302,303].includes(s.status)||!c||!d)throw new a("Plane sign-in failed. Check PLANE_LOGIN and PLANE_PASSWORD; this authentication flow requires password sign-in.",s.status);let f=x({userId:"",sessionId:c,csrf:d,expiresAt:i}),v=this.parse(await this.raw("/api/users/me/",{headers:{Cookie:P(f)}}),"/api/users/me/");if(!v.id)throw new a("Session was not authenticated: no user identifier returned.");return x({...f,userId:v.id})}async session(e=!1){if(!e&&this.current&&this.current.expiresAt>Date.now())return this.current;if(this.flight)return this.flight;let i=this.current;this.flight=(async()=>{let t=await C(this.cachePath);if(t&&(!e||t.sessionId!==i?.sessionId))return t;try{await q(this.config.cacheDirectory,{recursive:!0,mode:448});let s=await _(this.config.cacheDirectory);if(!s.isDirectory()||s.isSymbolicLink())throw Error("Invalid session cache directory");await N(this.config.cacheDirectory,448)}catch{throw new a(`Cannot write session cache in ${this.config.cacheDirectory}. Set PLANE_SESSION_CACHE or --session-cache to a private writable directory.`)}let r=`${this.cachePath}.lock`,o=Date.now(),n;while(!n)try{n=await k(r,"wx",384)}catch(s){if(s.code!=="EEXIST")throw new a("Cannot lock the session cache.");let c=await F(r).catch(()=>{return});if(c&&Date.now()-c.mtimeMs>90000){await g(r).catch(()=>{});continue}if(Date.now()-o>1e4)throw new a("Another command is refreshing the session; retry shortly.");await j(100)}try{let s=await C(this.cachePath);if(s&&(!e||s.sessionId!==i?.sessionId))return s;let c=await this.authenticate(),d=`${this.cachePath}.${D()}.tmp`;try{let f=await k(d,"wx",384);try{await f.writeFile(JSON.stringify({version:1,...c}))}finally{await f.close()}await E(d,this.cachePath)}finally{await g(d).catch(()=>{})}return c}finally{await n.close(),await g(r).catch(()=>{})}})();try{return this.current=await this.flight,this.current}finally{this.flight=void 0}}async request(e,i={}){let t=e.startsWith("/")?e:`/api/workspaces/${encodeURIComponent(this.config.workspace.value)}/${e}`,r=new URLSearchParams;for(let[n,s]of Object.entries(i.query??{}))if(s!==void 0)r.set(n,String(s));let o=r.size?`${t}?${r}`:t;for(let n=0;n<2;n++){let s=await this.session(n===1),c=await this.raw(o,{method:i.method??"GET",headers:{Cookie:P(s),"X-CSRFToken":s.csrf,Referer:`${this.config.url.value}/`,Accept:"application/json",...i.body===void 0?{}:{"Content-Type":"application/json"}},body:i.body===void 0?void 0:JSON.stringify(i.body)},i.timeoutMs);if(c.status===401&&n===0)continue;return this.parse(c,t)}throw new a("Session authentication failed after one refresh.",401)}async listAll(e,i={}){let t=[],r=new Set,o;do{let n=await this.request(e,{...i,query:{...i.query,...o?{cursor:o}:{}}});if(Array.isArray(n))return[...t,...n];if(!n||typeof n!=="object"||!("results"in n)||!Array.isArray(n.results))throw new a(`Unexpected list response from session API: ${e}`);t.push(...n.results);let s=n;if(o=s.next_page_results?s.next_cursor:void 0,o){if(r.has(o))throw new a("Session API repeated a pagination cursor.");r.add(o)}}while(o);return t}}export{U as SessionClient,J as cacheFile,P as cookieHeader};
package/dist/cli.js CHANGED
@@ -1,39 +1,39 @@
1
1
  #!/usr/bin/env node
2
- import{b as rn,c as sn,d as We}from"./chunks/cli-09mmhmq4.js";import{B as Ee,D as Vt,E as Bt,G as Kt,H as Yt,e as F,f as Z,g as y,h as x,i as k,j as mt,k as j,m as U,n as D,o as p,p as b,q as R,r as S,s as se,t as we,u as v,v as $e}from"./chunks/cli-3n3mxdd7.js";import{I as en,M as tn,N as nn,O as w,P as ae}from"./chunks/cli-ajj9jddd.js";import{$ as Qt,Q as Me,R as Fe,S as Ge,T,U as L,V as Zt,W as Xt,X as W,Y as d,Z as a,_ as P,aa as oe}from"./chunks/cli-q37j0y8m.js";import{ea as Le,fa as h,ga as Ue,ja as C,ka as le,la as N,ma as g,na as be}from"./chunks/cli-jq1agk1s.js";var K=()=>({groups:Me,flow:Ge,notes:Fe,globalOptions:L}),pe=(e)=>`${e.name}${e.args===void 0?"":` ${e.args}`}`,B=(e,t,n)=>{let s=e.split(/\s+/),r=[],o="";for(let i of s)if(o==="")o=i;else if(`${o} ${i}`.length+n.length<=t)o=`${o} ${i}`;else r.push(n+o),o=i;if(o!=="")r.push(n+o);return r},Y=(e)=>{let t=[];for(let n of e.groups){if(t.push(n.title),n.summary!==void 0)t.push(...B(n.summary,96," "),"");t.push(...h(n.commands.map((s)=>({name:pe(s),text:s.alias===void 0?s.summary:`${s.summary} (alias: ${s.alias})`})))),t.push("")}t.push("FLOW"),t.push(...h(e.flow.map((n)=>({name:n.command,text:n.summary})))),t.push(""),t.push(J(e.globalOptions),""),t.push("HOW THIS TOOL BEHAVES");for(let n of e.notes)t.push(` ${n.title}`),t.push(...B(n.body,96," ")),t.push("");return t.push("Flags and examples for one command: i-plane <command> --help"),t.join(`
3
- `)},J=(e=L)=>["GLOBAL OPTIONS",...h(e.map((t)=>({name:`${t.flag}${t.value===void 0?"":` ${t.value}`}`,text:t.summary})))].join(`
4
- `),me=(e,t=!0)=>{let{command:n}=e,s=[`i-plane ${pe(n)}`,"",...B(n.summary,96," ")];if(n.alias!==void 0)s.push("",` alias: ${n.alias}`);let r=(n.options??[]).filter((o)=>o.flag!=="--json");if(r.length>0)s.push("","OPTIONS"),s.push(...h(r.map((o)=>({name:o.value===void 0?o.flag:`${o.flag} ${o.value}`,text:`${o.required===!0?"Required. ":""}${o.summary}`}))));if(n.notes!==void 0&&n.notes.length>0){s.push("","USAGE NOTES");for(let o of n.notes)s.push(...B(o,96," "),"");if(s[s.length-1]==="")s.pop()}if(n.examples!==void 0&&n.examples.length>0){s.push("","EXAMPLES");for(let o of n.examples)s.push(` ${o}`)}if(n.next!==void 0&&n.next.length>0){s.push("","USUALLY NEXT");for(let o of n.next)s.push(` ${o}`)}if(t)s.push("",J(e.globalOptions));return s.join(`
5
- `)},He=(e,t)=>{let n=[t,"",` i-plane ${pe(e)}`];if(e.examples!==void 0&&e.examples.length>0){n.push("");for(let r of e.examples)n.push(` ${r}`)}let s=(e.options??[]).filter((r)=>r.flag!=="--json"&&r.value!==void 0);if(s.length>0)n.push(""," flags:"),n.push(...h(s.map((r)=>({name:`${r.flag} ${r.value}`,text:`${r.required===!0?"Required. ":""}${r.summary}`}))," "));return n.push("",` full help: i-plane ${e.name} --help`),n.join(`
6
- `)};var q=["urgent","high","medium","low","none"],fe=(e)=>{let t=q.indexOf(e);return t===-1?q.length:t},M=["backlog","unstarted","started","completed","cancelled"],E=(e)=>{let t=M.indexOf(e);return t===-1?M.length:t};var Ve=async(e,t)=>{let n=await Z(e),s=await Promise.all(n.map(async(r)=>{let o=await e.request(`projects/${r.id}/summary/`);return{identifier:r.identifier,name:r.name,counts:o.counts}}));return{workspace:t.workspace.value,url:t.url.value,projects:s}},Be=(e)=>{let t=[`WORKSPACE ${e.workspace} ${e.url}`,""];if(e.projects.length===0)t.push("no projects yet");else t.push("PROJECTS"),t.push(...h(e.projects.map((n)=>({name:n.identifier,text:`${n.name} — ${n.counts.issues} work items, ${n.counts.cycles} cycles, ${n.counts.modules} modules`}))));return t.push("","Next: i-plane list <PROJECT> Map: i-plane guide"),t.join(`
7
- `)},Ke=(e)=>e.length===0?"no projects":h(e.map((t)=>({name:t.identifier,text:g(t.name)})),"").join(`
8
- `),Ye=async(e,t)=>{let n=t.positionals[0]??a(t,"project");if(n===void 0)throw new d("Which project?");let s=await y(e,n);return[...await k(e,s.id)].sort((o,i)=>E(o.group)-E(i.group))},Je=(e)=>h(e.map((t)=>({name:t.name,text:t.group+(t.default===!0?" (default)":"")})),"").join(`
9
- `),Ze=async(e,t)=>{let n=t.positionals[0]??a(t,"project");if(n===void 0)throw new d("Which project?");let s=await y(e,n);return e.listAll(`projects/${s.id}/labels/`,{query:{fields:"id,name,color",per_page:100}})},Xe=(e)=>e.length===0?"no labels":e.map((t)=>t.name).join(`
10
- `),Qe=(e)=>e.listAll("members-lite/",{query:{per_page:100}}),et=(e)=>e.length===0?"no members":h(e.map((t)=>({name:t.display_name??t.id,text:t.email??""})),"").join(`
11
- `),tt=(e)=>({url:{value:e.url.value,origin:e.url.origin},workspace:{value:e.workspace.value,origin:e.workspace.origin},token:{value:We(e.token.value),origin:e.token.origin},configPath:e.configPath}),nt=(e)=>h([{name:"url",text:`${e.url.value} (${e.url.origin})`},{name:"workspace",text:`${e.workspace.value} (${e.workspace.origin})`},{name:"token",text:`${e.token.value} (${e.token.origin})`},{name:"file",text:e.configPath},...e.pages?[{name:"pages",text:`${e.pages.mode}: ${e.pages.reason}${e.pages.expiresAt?` Valid until ${e.pages.expiresAt}.`:""}`}]:[]],"").join(`
12
- `),rt=(e)=>e.request("/api/v1/users/me/"),st=(e)=>h([{name:"name",text:e.display_name??"?"},{name:"email",text:e.email??"?"},{name:"id",text:e.id}],"").join(`
13
- `);var ye=async(e,t,n)=>(await e.listAll(`projects/${t}/issues/${n}/comments/`,{query:{fields:"id,comment_html,created_at,actor",per_page:100}})).map((r)=>({id:r.id,author:typeof r.actor==="object"&&r.actor!==null?r.actor.display_name??r.actor.id:r.actor??"?",created_at:r.created_at,body:D(r.comment_html)})).sort((r,o)=>r.created_at.localeCompare(o.created_at)),ot=async(e,t)=>{let n=p(t.positionals[0],"a work item reference"),{issue:s,projectId:r}=await x(e,n,a(t,"project"));return ye(e,r,s.id)},X=(e)=>e.length===0?"no comments":e.map((t)=>`${t.created_at} ${t.author} [${t.id}]
2
+ import{b as Kt,c as Yt,d as De}from"./chunks/cli-8wxcra9k.js";import{C as Ie,E as Lt,F as Et,H as Ut,I as Dt,J as zt,L as Jt,e as F,f as J,g as y,h as j,i as C,j as at,k as x,m as D,n as U,o as u,p as P,q as R,r as v,s as oe,t as ye,u as I,v as he,w as Zt}from"./chunks/cli-hgk20taa.js";import{M as Gt,Q as Wt,R as Vt,S,T as Bt}from"./chunks/cli-tdf7t5es.js";import{$ as W,U as qe,V as Le,W as Ee,X as O,Y as q,Z as Ht,_ as Ft,aa as d,ba as i,ca as h,da as Nt,ea as se}from"./chunks/cli-2sf0pmt1.js";import{ia as sn,ja as w,ka as ve,na as b,oa as ae,pa as z,qa as g,ra as we}from"./chunks/cli-5v4ee99d.js";var K=()=>({groups:qe,flow:Ee,notes:Le,globalOptions:q}),le=(e)=>`${e.name}${e.args===void 0?"":` ${e.args}`}`,B=(e,t,n)=>{let o=e.split(/\s+/),r=[],s="";for(let a of o)if(s==="")s=a;else if(`${s} ${a}`.length+n.length<=t)s=`${s} ${a}`;else r.push(n+s),s=a;if(s!=="")r.push(n+s);return r},Y=(e)=>{let t=[];for(let n of e.groups){if(t.push(n.title),n.summary!==void 0)t.push(...B(n.summary,96," "),"");t.push(...w(n.commands.map((o)=>({name:le(o),text:o.alias===void 0?o.summary:`${o.summary} (alias: ${o.alias})`})))),t.push("")}t.push("FLOW"),t.push(...w(e.flow.map((n)=>({name:n.command,text:n.summary})))),t.push(""),t.push(Z(e.globalOptions),""),t.push("HOW THIS TOOL BEHAVES");for(let n of e.notes)t.push(` ${n.title}`),t.push(...B(n.body,96," ")),t.push("");return t.push("Flags and examples for one command: i-plane <command> --help"),t.join(`
3
+ `)},Z=(e=q)=>["GLOBAL OPTIONS",...w(e.map((t)=>({name:`${t.flag}${t.value===void 0?"":` ${t.value}`}`,text:t.summary})))].join(`
4
+ `),ce=(e,t=!0)=>{let{command:n}=e,o=[`i-plane ${le(n)}`,"",...B(n.summary,96," ")];if(n.alias!==void 0)o.push("",` alias: ${n.alias}`);let r=(n.options??[]).filter((s)=>s.flag!=="--json");if(r.length>0)o.push("","OPTIONS"),o.push(...w(r.map((s)=>({name:s.value===void 0?s.flag:`${s.flag} ${s.value}`,text:`${s.required===!0?"Required. ":""}${s.summary}`}))));if(n.notes!==void 0&&n.notes.length>0){o.push("","USAGE NOTES");for(let s of n.notes)o.push(...B(s,96," "),"");if(o[o.length-1]==="")o.pop()}if(n.examples!==void 0&&n.examples.length>0){o.push("","EXAMPLES");for(let s of n.examples)o.push(` ${s}`)}if(n.next!==void 0&&n.next.length>0){o.push("","USUALLY NEXT");for(let s of n.next)o.push(` ${s}`)}if(t)o.push("",Z(e.globalOptions));return o.join(`
5
+ `)},Ue=(e,t)=>{let n=[t,"",` i-plane ${le(e)}`];if(e.examples!==void 0&&e.examples.length>0){n.push("");for(let r of e.examples)n.push(` ${r}`)}let o=(e.options??[]).filter((r)=>r.flag!=="--json"&&r.value!==void 0);if(o.length>0)n.push(""," flags:"),n.push(...w(o.map((r)=>({name:`${r.flag} ${r.value}`,text:`${r.required===!0?"Required. ":""}${r.summary}`}))," "));return n.push("",` full help: i-plane ${e.name} --help`),n.join(`
6
+ `)};var L=["urgent","high","medium","low","none"],ue=(e)=>{let t=L.indexOf(e);return t===-1?L.length:t},H=["backlog","unstarted","started","completed","cancelled"],E=(e)=>{let t=H.indexOf(e);return t===-1?H.length:t};var ze=async(e,t)=>{let n=await J(e),o=await Promise.all(n.map(async(r)=>{let s=await e.request(`projects/${r.id}/summary/`);return{identifier:r.identifier,name:r.name,counts:s.counts}}));return{workspace:t.workspace.value,url:t.url.value,projects:o}},Me=(e)=>{let t=[`WORKSPACE ${e.workspace} ${e.url}`,""];if(e.projects.length===0)t.push("no projects yet");else t.push("PROJECTS"),t.push(...w(e.projects.map((n)=>({name:n.identifier,text:`${n.name} — ${n.counts.issues} work items, ${n.counts.cycles} cycles, ${n.counts.modules} modules`}))));return t.push("","Next: i-plane list <PROJECT> Map: i-plane guide"),t.join(`
7
+ `)},He=(e)=>e.length===0?"no projects":w(e.map((t)=>({name:t.identifier,text:g(t.name)})),"").join(`
8
+ `),Fe=async(e,t)=>{let n=t.positionals[0]??i(t,"project");if(n===void 0)throw new d("Which project?");let o=await y(e,n);return[...await C(e,o.id)].sort((s,a)=>E(s.group)-E(a.group))},Ne=(e)=>w(e.map((t)=>({name:t.name,text:t.group+(t.default===!0?" (default)":"")})),"").join(`
9
+ `),Ge=async(e,t)=>{let n=t.positionals[0]??i(t,"project");if(n===void 0)throw new d("Which project?");let o=await y(e,n);return e.listAll(`projects/${o.id}/labels/`,{query:{fields:"id,name,color",per_page:100}})},We=(e)=>e.length===0?"no labels":e.map((t)=>t.name).join(`
10
+ `),Ve=(e)=>e.listAll("members-lite/",{query:{per_page:100}}),Be=(e)=>e.length===0?"no members":w(e.map((t)=>({name:t.display_name??t.id,text:t.email??""})),"").join(`
11
+ `),Ke=(e)=>({url:{value:e.url.value,origin:e.url.origin},workspace:{value:e.workspace.value,origin:e.workspace.origin},token:{value:De(e.token.value),origin:e.token.origin},configPath:e.configPath}),Ye=(e)=>w([{name:"url",text:`${e.url.value} (${e.url.origin})`},{name:"workspace",text:`${e.workspace.value} (${e.workspace.origin})`},{name:"token",text:`${e.token.value} (${e.token.origin})`},{name:"file",text:e.configPath},...e.pages?[{name:"pages",text:`${e.pages.mode}: ${e.pages.reason}${e.pages.expiresAt?` Valid until ${e.pages.expiresAt}.`:""}`}]:[]],"").join(`
12
+ `),Ze=(e)=>e.request("/api/v1/users/me/"),Je=(e)=>w([{name:"name",text:e.display_name??"?"},{name:"email",text:e.email??"?"},{name:"id",text:e.id}],"").join(`
13
+ `);var pe=async(e,t,n)=>(await e.listAll(`projects/${t}/issues/${n}/comments/`,{query:{fields:"id,comment_html,created_at,actor",per_page:100}})).map((r)=>({id:r.id,author:typeof r.actor==="object"&&r.actor!==null?r.actor.display_name??r.actor.id:r.actor??"?",created_at:r.created_at,body:U(r.comment_html)})).sort((r,s)=>r.created_at.localeCompare(s.created_at)),Xe=async(e,t)=>{let n=u(t.positionals[0],"a work item reference"),{issue:o,projectId:r}=await j(e,n,i(t,"project"));return pe(e,r,o.id)},X=(e)=>e.length===0?"no comments":e.map((t)=>`${t.created_at} ${t.author} [${t.id}]
14
14
 
15
15
  ${t.body}`).join(`
16
16
 
17
- `);var Q={pending:-2,rejected:-1,snoozed:0,accepted:1,duplicate:2},O=(e,t)=>{let n=e.issue_detail??(typeof e.issue==="object"?e.issue:void 0),s=typeof e.issue==="string"?e.issue:e.issue.id;return{id:e.id,issueId:s,ref:n?.sequence_id===void 0?s:`${t.identifier}-${n.sequence_id}`,name:g(n?.name??s),status:Object.entries(Q).find(([,r])=>r===e.status)?.[0]??String(e.status),statusCode:e.status,priority:n?.priority??"none",description:D(n?.description_html),snoozedUntil:e.snoozed_till??null,duplicateTo:e.duplicate_to??null}},ge=(e,t)=>e.listAll(`projects/${t}/intake-issues/`,{query:{per_page:100}}),dn=async(e,t,n)=>{if(F(n))return e.request(`projects/${t.id}/intake-issues/${n}/`);let r=(await ge(e,t.id)).find((o)=>O(o,t).ref.toLowerCase()===n.toLowerCase());if(r===void 0)throw new d(`No intake work item matches "${n}". Use its readable reference or underlying work item UUID.`);return r},it=async(e,t,n)=>{if(F(n))return{issueId:n,ref:n};let s=(await ge(e,t.id)).find((r)=>O(r,t).ref.toLowerCase()===n.toLowerCase());if(s!==void 0){let r=O(s,t);return{issueId:r.issueId,ref:r.ref}}try{let r=await x(e,n,t.id,"id,project,sequence_id");if(r.projectId!==t.id)throw new d(`${n} does not belong to project ${t.identifier}.`);return{issueId:r.issue.id,ref:`${t.identifier}-${r.issue.sequence_id}`}}catch(r){if(r instanceof w&&r.status===404)throw new d(`Cannot resolve intake reference "${n}". The server can hide expired snoozes from both lookup endpoints. Pass the underlying work item UUID (issueId in JSON).`);throw r}},at=(e)=>{let t={},n=a(e,"name");if(n!==void 0)t.name=p(n,"a work item name");let s=a(e,"priority");if(s!==void 0)t.priority=R(s,q,"priority");let r=a(e,"description");if(r!==void 0)t.description_html=U(r);return t},dt=async(e,t)=>{let n=a(t,"status"),s=n===void 0?void 0:R(n,Object.keys(Q),"status"),r=await y(e,p(t.positionals[0]??a(t,"project"),"a project reference")),o=(await ge(e,r.id)).map((i)=>O(i,r));return s===void 0?o:o.filter((i)=>i.status===s)},lt=async(e,t)=>{let n=p(t.positionals.join(" "),"an intake work item name"),s={issue:{...at(t),name:n}},r=await y(e,b(t,"project")),o=await e.request(`projects/${r.id}/intake-issues/`,{method:"POST",body:s});return O(o,r)},ct=async(e,t)=>{let n=p(t.positionals[0],"an intake work item reference"),s=await y(e,b(t,"project"));return O(await dn(e,s,n),s)},ut=async(e,t)=>{let n=p(t.positionals[0],"an intake work item reference"),s={},r=at(t);if(Object.keys(r).length>0)s.issue=r;let o=a(t,"status"),i=o===void 0?void 0:R(o,Object.keys(Q),"status"),l=a(t,"snooze-until"),u=a(t,"duplicate-of");if(l!==void 0&&i!=="snoozed")throw new d("--snooze-until requires --status snoozed.");if(u!==void 0&&i!=="duplicate")throw new d("--duplicate-of requires --status duplicate.");if(i!==void 0)s.status=Q[i],s.snoozed_till=null,s.duplicate_to=null;if(i==="snoozed"){let _=S(p(l,"--snooze-until YYYY-MM-DD"),"snooze-until");if(_===null)throw new d("A snoozed work item needs a date, not none.");s.snoozed_till=`${_}T00:00:00Z`}if(i==="duplicate")p(u,"--duplicate-of <ID>");v(s);let m=await y(e,b(t,"project")),f=await it(e,m,n);if(u!==void 0){let _=await x(e,u,m.id);if(_.projectId!==m.id)throw new d("The duplicate target must belong to the same project.");if(_.issue.id===f.issueId)throw new d("A work item cannot be a duplicate of itself.");s.duplicate_to=_.issue.id}let A=await e.request(`projects/${m.id}/intake-issues/${f.issueId}/`,{method:"PATCH",body:s});return O(A,m)},pt=async(e,t)=>{if(!P(t,"yes"))throw new d("Deleting cannot be undone. Repeat with --yes.");let n=p(t.positionals[0],"an intake work item reference"),s=await y(e,b(t,"project")),r=await it(e,s,n);return await e.request(`projects/${s.id}/intake-issues/${r.issueId}/`,{method:"DELETE"}),r},he=(e)=>e.length===0?"no intake work items":h(e.map((t)=>({name:t.ref,text:`${t.name} [${t.priority}] (${t.status})`})),"").join(`
18
- `),ee=(e)=>`${he([e])}${e.snoozedUntil===null?"":`
17
+ `);var Q={pending:-2,rejected:-1,snoozed:0,accepted:1,duplicate:2},T=(e,t)=>{let n=e.issue_detail??(typeof e.issue==="object"?e.issue:void 0),o=typeof e.issue==="string"?e.issue:e.issue.id;return{id:e.id,issueId:o,ref:n?.sequence_id===void 0?o:`${t.identifier}-${n.sequence_id}`,name:g(n?.name??o),status:Object.entries(Q).find(([,r])=>r===e.status)?.[0]??String(e.status),statusCode:e.status,priority:n?.priority??"none",description:U(n?.description_html),snoozedUntil:e.snoozed_till??null,duplicateTo:e.duplicate_to??null}},me=(e,t)=>e.listAll(`projects/${t}/intake-issues/`,{query:{per_page:100}}),en=async(e,t,n)=>{if(F(n))return e.request(`projects/${t.id}/intake-issues/${n}/`);let r=(await me(e,t.id)).find((s)=>T(s,t).ref.toLowerCase()===n.toLowerCase());if(r===void 0)throw new d(`No intake work item matches "${n}". Use its readable reference or underlying work item UUID.`);return r},Qe=async(e,t,n)=>{if(F(n))return{issueId:n,ref:n};let o=(await me(e,t.id)).find((r)=>T(r,t).ref.toLowerCase()===n.toLowerCase());if(o!==void 0){let r=T(o,t);return{issueId:r.issueId,ref:r.ref}}try{let r=await j(e,n,t.id,"id,project,sequence_id");if(r.projectId!==t.id)throw new d(`${n} does not belong to project ${t.identifier}.`);return{issueId:r.issue.id,ref:`${t.identifier}-${r.issue.sequence_id}`}}catch(r){if(r instanceof S&&r.status===404)throw new d(`Cannot resolve intake reference "${n}". The server can hide expired snoozes from both lookup endpoints. Pass the underlying work item UUID (issueId in JSON).`);throw r}},et=(e)=>{let t={},n=i(e,"name");if(n!==void 0)t.name=u(n,"a work item name");let o=i(e,"priority");if(o!==void 0)t.priority=R(o,L,"priority");let r=i(e,"description");if(r!==void 0)t.description_html=D(r);return t},tt=async(e,t)=>{let n=i(t,"status"),o=n===void 0?void 0:R(n,Object.keys(Q),"status"),r=await y(e,u(t.positionals[0]??i(t,"project"),"a project reference")),s=(await me(e,r.id)).map((a)=>T(a,r));return o===void 0?s:s.filter((a)=>a.status===o)},nt=async(e,t)=>{let n=u(t.positionals.join(" "),"an intake work item name"),o={issue:{...et(t),name:n}},r=await y(e,P(t,"project")),s=await e.request(`projects/${r.id}/intake-issues/`,{method:"POST",body:o});return T(s,r)},rt=async(e,t)=>{let n=u(t.positionals[0],"an intake work item reference"),o=await y(e,P(t,"project"));return T(await en(e,o,n),o)},ot=async(e,t)=>{let n=u(t.positionals[0],"an intake work item reference"),o={},r=et(t);if(Object.keys(r).length>0)o.issue=r;let s=i(t,"status"),a=s===void 0?void 0:R(s,Object.keys(Q),"status"),l=i(t,"snooze-until"),p=i(t,"duplicate-of");if(l!==void 0&&a!=="snoozed")throw new d("--snooze-until requires --status snoozed.");if(p!==void 0&&a!=="duplicate")throw new d("--duplicate-of requires --status duplicate.");if(a!==void 0)o.status=Q[a],o.snoozed_till=null,o.duplicate_to=null;if(a==="snoozed"){let _=v(u(l,"--snooze-until YYYY-MM-DD"),"snooze-until");if(_===null)throw new d("A snoozed work item needs a date, not none.");o.snoozed_till=`${_}T00:00:00Z`}if(a==="duplicate")u(p,"--duplicate-of <ID>");I(o);let m=await y(e,P(t,"project")),f=await Qe(e,m,n);if(p!==void 0){let _=await j(e,p,m.id);if(_.projectId!==m.id)throw new d("The duplicate target must belong to the same project.");if(_.issue.id===f.issueId)throw new d("A work item cannot be a duplicate of itself.");o.duplicate_to=_.issue.id}let k=await e.request(`projects/${m.id}/intake-issues/${f.issueId}/`,{method:"PATCH",body:o});return T(k,m)},st=async(e,t)=>{if(!h(t,"yes"))throw new d("Deleting cannot be undone. Repeat with --yes.");let n=u(t.positionals[0],"an intake work item reference"),o=await y(e,P(t,"project")),r=await Qe(e,o,n);return await e.request(`projects/${o.id}/intake-issues/${r.issueId}/`,{method:"DELETE"}),r},fe=(e)=>e.length===0?"no intake work items":w(e.map((t)=>({name:t.ref,text:`${t.name} [${t.priority}] (${t.status})`})),"").join(`
18
+ `),ee=(e)=>`${fe([e])}${e.snoozedUntil===null?"":`
19
19
  snoozed until ${e.snoozedUntil}`}${e.duplicateTo===null?"":`
20
20
  duplicate of ${e.duplicateTo}`}${e.description===""?"":`
21
21
 
22
- ${e.description}`}`;var te=async(e,t)=>{if(F(t))return t;let n=await e.listAll("members-lite/",{query:{per_page:100}}),s=n.filter((r)=>r.email?.toLowerCase()===t.toLowerCase());if(s.length===1&&s[0]!==void 0)return s[0].id;if(s.length>1)throw new d(`Ambiguous member "${t}".`);return j(n.map((r)=>({...r,name:r.display_name??r.email??r.id})),t,"member").id},Pe=async(e,t,n,s)=>{let r={},o=a(t,"name");if(o!==void 0)r.name=p(o,"a work item name");let i=a(t,"priority");if(i!==void 0)r.priority=R(i,q,"priority");let l=a(t,"description");if(l!==void 0)r.description_html=U(l);let u=a(t,"due");if(u!==void 0)r.target_date=S(u,"due");let m=a(t,"start");if(m!==void 0)r.start_date=S(m,"start");let f=a(t,"label"),A=a(t,"labels");if(f!==void 0&&A!==void 0)throw new d("Use either --label to add labels or --labels to replace them.");let _=a(t,"state");if(_!==void 0)r.state=mt(await k(e,n),_).id;let ce=a(t,"parent");if(ce!==void 0)if(ce==="none")r.parent=null;else{let I=await x(e,ce,n);if(I.issue.id===s?.id)throw new d("A work item cannot be its own parent.");r.parent=I.issue.id}let Ne=a(t,"assignee");if(Ne!==void 0){let I=[];for(let ue of we(Ne))I.push(await te(e,ue));r.assignees=[...new Set(I)]}let ze=f??A;if(ze!==void 0){let I=we(ze);if(f!==void 0&&I.length===0)throw new d("--label expects labels to add. Use --labels none to clear all labels.");let ue=I.length===0?[]:await e.listAll(`projects/${n}/labels/`,{query:{fields:"id,name",per_page:100}}),on=I.map((an)=>j(ue,an,"label").id);r.labels=[...new Set([...f===void 0?[]:s?.labels??[],...on])]}return r};var ln="id,name,sequence_id,priority,state",cn=(e)=>typeof e.state==="object"&&e.state!==null?{name:e.state.name,group:e.state.group}:{name:"?",group:"?"},xe=(e,t)=>{let n=cn(e);return{ref:`${t}-${e.sequence_id}`,name:g(e.name),state:n.name,group:n.group,priority:e.priority,id:e.id}},un=(e)=>e==="none"||e===""?"":` [${e}]`,ne=(e)=>{let{rows:t,total:n}=e;if(t.length===0)return n===0?"no work items":`showing 0 of ${n} — raise or drop --limit`;let s=[...h(t.map((r)=>({name:r.ref,text:`${be(r.name,72)}${un(r.priority)} (${r.state})`})),"")];if(t.length<n)s.push("",`showing ${t.length} of ${n} — drop --limit to see the rest`);return s.join(`
23
- `)},ft=async(e,t)=>{let n=$e(t),s=t.positionals[0]??a(t,"project");if(s===void 0)throw new d("Which project?");let r=await y(e,s),o=await e.listAll(`projects/${r.id}/issues/`,{query:{fields:ln,expand:"state",per_page:100}}),i=a(t,"state")?.toLowerCase(),l=a(t,"priority")?.toLowerCase(),m=[...o.map((f)=>xe(f,r.identifier)).filter((f)=>{if(i!==void 0){if(!(f.group.toLowerCase()===i||f.state.toLowerCase().startsWith(i)))return!1}if(l!==void 0&&f.priority.toLowerCase()!==l)return!1;return!0})].sort((f,A)=>E(f.group)-E(A.group)||fe(f.priority)-fe(A.priority)||f.ref.localeCompare(A.ref));return{rows:n===void 0?m:m.slice(0,n),total:m.length}},yt=async(e,t,n,s)=>{let r=t.positionals[0];if(r===void 0)throw new d("Which work item?");let{issue:o,projectId:i}=await x(e,r,a(t,"project"),"id,name,sequence_id,priority,state,assignees,target_date,start_date,parent,labels,project,description_html"),u=(await k(e,i)).find((f)=>f.id===o.state);return{ref:`${(await y(e,i)).identifier}-${o.sequence_id}`,name:g(o.name),state:u?.name??"?",group:u?.group??"?",priority:o.priority,id:o.id,description:D(o.description_html),assignees:o.assignees??[],labels:o.labels??[],target_date:o.target_date??null,start_date:o.start_date??null,...P(t,"comments")?{comments:await ye(e,i,o.id)}:{},parent:o.parent??null,url:`${s}/${n}/projects/${i}/issues/${o.id}`}},gt=(e)=>{let t=[{name:e.ref,text:e.name},{name:"state",text:`${e.state} (${e.group})`},{name:"priority",text:e.priority}];if(e.start_date!=null)t.push({name:"start",text:e.start_date});if(e.target_date!=null)t.push({name:"due",text:e.target_date});if(e.assignees.length>0)t.push({name:"assignees",text:String(e.assignees.length)});if(e.labels.length>0)t.push({name:"labels",text:e.labels.join(", ")});if(e.parent!=null)t.push({name:"parent",text:e.parent});t.push({name:"url",text:e.url});let n=h(t,"").join(`
24
- `),s=e.description===""?n:`${n}
22
+ ${e.description}`}`;var te=async(e,t)=>{if(F(t))return t;let n=await e.listAll("members-lite/",{query:{per_page:100}}),o=n.filter((r)=>r.email?.toLowerCase()===t.toLowerCase());if(o.length===1&&o[0]!==void 0)return o[0].id;if(o.length>1)throw new d(`Ambiguous member "${t}".`);return x(n.map((r)=>({...r,name:r.display_name??r.email??r.id})),t,"member").id},ge=async(e,t,n,o)=>{let r={},s=i(t,"name");if(s!==void 0)r.name=u(s,"a work item name");let a=i(t,"priority");if(a!==void 0)r.priority=R(a,L,"priority");let l=i(t,"description");if(l!==void 0)r.description_html=D(l);let p=i(t,"due");if(p!==void 0)r.target_date=v(p,"due");let m=i(t,"start");if(m!==void 0)r.start_date=v(m,"start");let f=i(t,"label"),k=i(t,"labels");if(f!==void 0&&k!==void 0)throw new d("Use either --label to add labels or --labels to replace them.");let _=i(t,"state");if(_!==void 0)r.state=at(await C(e,n),_).id;let ie=i(t,"parent");if(ie!==void 0)if(ie==="none")r.parent=null;else{let A=await j(e,ie,n);if(A.issue.id===o?.id)throw new d("A work item cannot be its own parent.");r.parent=A.issue.id}let Oe=i(t,"assignee");if(Oe!==void 0){let A=[];for(let de of ye(Oe))A.push(await te(e,de));r.assignees=[...new Set(A)]}let Te=f??k;if(Te!==void 0){let A=ye(Te);if(f!==void 0&&A.length===0)throw new d("--label expects labels to add. Use --labels none to clear all labels.");let de=A.length===0?[]:await e.listAll(`projects/${n}/labels/`,{query:{fields:"id,name",per_page:100}}),Xt=A.map((Qt)=>x(de,Qt,"label").id);r.labels=[...new Set([...f===void 0?[]:o?.labels??[],...Xt])]}return r};var tn="id,name,sequence_id,priority,state",nn=(e)=>typeof e.state==="object"&&e.state!==null?{name:e.state.name,group:e.state.group}:{name:"?",group:"?"},Pe=(e,t)=>{let n=nn(e);return{ref:`${t}-${e.sequence_id}`,name:g(e.name),state:n.name,group:n.group,priority:e.priority,id:e.id}},rn=(e)=>e==="none"||e===""?"":` [${e}]`,ne=(e)=>{let{rows:t,total:n}=e;if(t.length===0)return n===0?"no work items":`showing 0 of ${n} — raise or drop --limit`;let o=[...w(t.map((r)=>({name:r.ref,text:`${we(r.name,72)}${rn(r.priority)} (${r.state})`})),"")];if(t.length<n)o.push("",`showing ${t.length} of ${n} — drop --limit to see the rest`);return o.join(`
23
+ `)},it=async(e,t)=>{let n=he(t),o=t.positionals[0]??i(t,"project");if(o===void 0)throw new d("Which project?");let r=await y(e,o),s=await e.listAll(`projects/${r.id}/issues/`,{query:{fields:tn,expand:"state",per_page:100}}),a=i(t,"state")?.toLowerCase(),l=i(t,"priority")?.toLowerCase(),m=[...s.map((f)=>Pe(f,r.identifier)).filter((f)=>{if(a!==void 0){if(!(f.group.toLowerCase()===a||f.state.toLowerCase().startsWith(a)))return!1}if(l!==void 0&&f.priority.toLowerCase()!==l)return!1;return!0})].sort((f,k)=>E(f.group)-E(k.group)||ue(f.priority)-ue(k.priority)||f.ref.localeCompare(k.ref));return{rows:n===void 0?m:m.slice(0,n),total:m.length}},dt=async(e,t,n,o)=>{let r=t.positionals[0];if(r===void 0)throw new d("Which work item?");let{issue:s,projectId:a}=await j(e,r,i(t,"project"),"id,name,sequence_id,priority,state,assignees,target_date,start_date,parent,labels,project,description_html"),p=(await C(e,a)).find((f)=>f.id===s.state);return{ref:`${(await y(e,a)).identifier}-${s.sequence_id}`,name:g(s.name),state:p?.name??"?",group:p?.group??"?",priority:s.priority,id:s.id,description:U(s.description_html),assignees:s.assignees??[],labels:s.labels??[],target_date:s.target_date??null,start_date:s.start_date??null,...h(t,"comments")?{comments:await pe(e,a,s.id)}:{},parent:s.parent??null,url:`${o}/${n}/projects/${a}/issues/${s.id}`}},lt=(e)=>{let t=[{name:e.ref,text:e.name},{name:"state",text:`${e.state} (${e.group})`},{name:"priority",text:e.priority}];if(e.start_date!=null)t.push({name:"start",text:e.start_date});if(e.target_date!=null)t.push({name:"due",text:e.target_date});if(e.assignees.length>0)t.push({name:"assignees",text:String(e.assignees.length)});if(e.labels.length>0)t.push({name:"labels",text:e.labels.join(", ")});if(e.parent!=null)t.push({name:"parent",text:e.parent});t.push({name:"url",text:e.url});let n=w(t,"").join(`
24
+ `),o=e.description===""?n:`${n}
25
25
 
26
- ${e.description}`;return e.comments===void 0?s:`${s}
26
+ ${e.description}`;return e.comments===void 0?o:`${o}
27
27
 
28
28
  COMMENTS
29
29
 
30
- ${X(e.comments)}`},ht=async(e,t)=>{let n=t.positionals.join(" ").trim();if(n==="")throw new d("What is it called?");let s=a(t,"project");if(s===void 0)throw new d("Which project? Pass --project.");let r=await y(e,s),o={...await Pe(e,t,r.id),name:n},i=await e.request(`projects/${r.id}/issues/`,{method:"POST",body:o}),l=`${r.identifier}-${i.sequence_id}`,u;try{u=(await k(e,r.id)).find((f)=>f.id===i.state)}catch(m){let f=m instanceof Error?m.message:String(m);N(`${l} was created; could not read its state: ${f}`)}return{ref:l,name:g(i.name),state:u?.name??"?",group:u?.group??"?",priority:i.priority,id:i.id}},je=async(e,t)=>{let n=t.positionals[0];if(n===void 0)throw new d("Which work item?");let{issue:s,projectId:r}=await x(e,n,a(t,"project")),o=await y(e,r),i=await k(e,r),l=await Pe(e,t,r,s);v(l);let m=await e.request(`projects/${r}/issues/${s.id}/`,{method:"PATCH",body:l})??{...s,...l},f=i.find((A)=>A.id===m.state);return{ref:`${o.identifier}-${m.sequence_id}`,name:g(m.name),state:f?.name??"?",group:f?.group??"?",priority:m.priority,id:m.id}},wt=async(e,t)=>{let n=t.positionals[0];if(n===void 0)throw new d("Which work item?");let{projectId:s}=await x(e,n,a(t,"project")),o=(await k(e,s)).find((l)=>l.group==="completed");if(o===void 0)throw new d("This project has no state in the completed group.");let i=new Map(t.flags);return i.set("state",o.id),je(e,{...t,flags:i})},Pt=async(e,t)=>{let n=t.positionals[0];if(n===void 0)throw new d("Which work item?");if(!P(t,"yes"))throw new d(`Deleting is not undoable. Repeat with --yes to delete ${n}.`);let{issue:s,projectId:r}=await x(e,n,a(t,"project"));return await e.request(`projects/${r}/issues/${s.id}/`,{method:"DELETE"}),`deleted ${n}`},bt=async(e,t)=>{let n=t.positionals[0],s=t.positionals.slice(1).join(" ").trim();if(n===void 0||s==="")throw new d("Which work item, and what does the comment say?");let{issue:r,projectId:o}=await x(e,n,a(t,"project"));return await e.request(`projects/${o}/issues/${r.id}/comments/`,{method:"POST",body:{comment_html:U(s)}}),`commented on ${n}`},$t=async(e,t)=>{let n=$e(t,1,1000)??10,s=t.positionals.join(" ").trim();if(s==="")throw new d("What to search for?");let r=await e.request("issues/search/",{query:{search:s,limit:n+1}});if(!r||!Array.isArray(r.issues))throw new w("Unexpected search response: expected an issues array.");return{rows:r.issues.slice(0,n).map((i)=>({ref:`${i.project__identifier}-${i.sequence_id}`,name:g(i.name),id:i.id})),limit:n,hasMore:r.issues.length>n}},xt=({rows:e,limit:t,hasMore:n})=>{let s=e.length===0?"nothing found":h(e.map((r)=>({name:r.ref,text:be(r.name,80)})),"").join(`
31
- `);return n?`${s}
30
+ ${X(e.comments)}`},ct=async(e,t)=>{let n=t.positionals.join(" ").trim();if(n==="")throw new d("What is it called?");let o=i(t,"project");if(o===void 0)throw new d("Which project? Pass --project.");let r=await y(e,o),s={...await ge(e,t,r.id),name:n},a=await e.request(`projects/${r.id}/issues/`,{method:"POST",body:s}),l=`${r.identifier}-${a.sequence_id}`,p;try{p=(await C(e,r.id)).find((f)=>f.id===a.state)}catch(m){let f=m instanceof Error?m.message:String(m);z(`${l} was created; could not read its state: ${f}`)}return{ref:l,name:g(a.name),state:p?.name??"?",group:p?.group??"?",priority:a.priority,id:a.id}},$e=async(e,t)=>{let n=t.positionals[0];if(n===void 0)throw new d("Which work item?");let{issue:o,projectId:r}=await j(e,n,i(t,"project")),s=await y(e,r),a=await C(e,r),l=await ge(e,t,r,o);I(l);let m=await e.request(`projects/${r}/issues/${o.id}/`,{method:"PATCH",body:l})??{...o,...l},f=a.find((k)=>k.id===m.state);return{ref:`${s.identifier}-${m.sequence_id}`,name:g(m.name),state:f?.name??"?",group:f?.group??"?",priority:m.priority,id:m.id}},ut=async(e,t)=>{let n=t.positionals[0];if(n===void 0)throw new d("Which work item?");let{projectId:o}=await j(e,n,i(t,"project")),s=(await C(e,o)).find((l)=>l.group==="completed");if(s===void 0)throw new d("This project has no state in the completed group.");let a=new Map(t.flags);return a.set("state",s.id),$e(e,{...t,flags:a})},pt=async(e,t)=>{let n=t.positionals[0];if(n===void 0)throw new d("Which work item?");if(!h(t,"yes"))throw new d(`Deleting is not undoable. Repeat with --yes to delete ${n}.`);let{issue:o,projectId:r}=await j(e,n,i(t,"project"));return await e.request(`projects/${r}/issues/${o.id}/`,{method:"DELETE"}),`deleted ${n}`},mt=async(e,t)=>{let n=t.positionals[0],o=t.positionals.slice(1).join(" ").trim();if(n===void 0||o==="")throw new d("Which work item, and what does the comment say?");let{issue:r,projectId:s}=await j(e,n,i(t,"project"));return await e.request(`projects/${s}/issues/${r.id}/comments/`,{method:"POST",body:{comment_html:D(o)}}),`commented on ${n}`},ft=async(e,t)=>{let n=he(t,1,1000)??10,o=t.positionals.join(" ").trim();if(o==="")throw new d("What to search for?");let r=await e.request("issues/search/",{query:{search:o,limit:n+1}});if(!r||!Array.isArray(r.issues))throw new S("Unexpected search response: expected an issues array.");return{rows:r.issues.slice(0,n).map((a)=>({ref:`${a.project__identifier}-${a.sequence_id}`,name:g(a.name),id:a.id})),limit:n,hasMore:r.issues.length>n}},yt=({rows:e,limit:t,hasMore:n})=>{let o=e.length===0?"nothing found":w(e.map((r)=>({name:r.ref,text:we(r.name,80)})),"").join(`
31
+ `);return n?`${o}
32
32
 
33
- showing the first ${t} matches; more exist — raise --limit (up to 1000) or narrow the query`:s};var z=(e,t,n=!1)=>y(e,p((n?t.positionals[0]:void 0)??a(t,"project"),"--project <ref>"),"id,name,identifier,timezone"),Ce=async(e,t,n)=>{let s=await z(e,t,!0);return(await e.listAll(`projects/${s.id}/${n}s/`,{query:{fields:n==="cycle"?"id,name,start_date,end_date":"id,name,start_date,target_date,status",per_page:100}})).map((o)=>ke(o,s,n))},ke=(e,t,n)=>n==="cycle"&&t.timezone!==void 0?{...e,timezone:t.timezone}:e,re=(e,t,n)=>e.listAll(`projects/${t}/${n}s-lite/`,{query:{per_page:100}}),Ct=(e,t)=>{let n={},s=a(e,"name");if(s!==void 0)n.name=p(s,`a ${t} name`);let r=a(e,"description");if(r!==void 0)n.description=r;let o=a(e,"start"),i=t==="cycle"?"end":"due",l=a(e,i),u=o===void 0?null:S(o,"start"),m=l===void 0?null:S(l,i);if(t==="cycle"&&(o===void 0!==(l===void 0)||u===null!==(m===null)))throw new d("A cycle needs both --start and --end, or neither for a draft.");if(u!==null&&m!==null&&u>m)throw new d("The start date must not be after the end date.");if(o!==void 0)n.start_date=u;if(l!==void 0)n[t==="cycle"?"end_date":"target_date"]=m;if(t==="module"){let f=a(e,"status");if(f!==void 0)n.status=R(f,["backlog","planned","in-progress","paused","completed","cancelled"],"status")}return n},Ae=async(e,t,n)=>{let s={...Ct(t,n),name:p(t.positionals.join(" "),`a ${n} name`)},r=await z(e,t);if(n==="cycle"){let i=a(t,"owner");s.owned_by=i===void 0?(await e.request("/api/v1/users/me/")).id:await te(e,i),s.project_id=r.id}let o=await e.request(`projects/${r.id}/${n}s/`,{method:"POST",body:s});return ke(o,r,n)},kt=async(e,t)=>{let n=p(t.positionals[0],"a cycle name or UUID"),s=Ct(t,"cycle"),r=a(t,"owner");if(r===void 0)v(s);let o=await z(e,t),i=j(await re(e,o.id,"cycle"),n,"cycle");if(r!==void 0)s.owned_by=await te(e,r);else{let u=await e.request(`projects/${o.id}/cycles/${i.id}/`,{query:{fields:"id,name,owned_by"}});if(!u.owned_by)throw new w("Cannot preserve the cycle owner: the server did not return owned_by. Pass --owner explicitly.");s.owned_by=u.owned_by}let l=await e.request(`projects/${o.id}/cycles/${i.id}/`,{method:"PATCH",body:s});return ke(l??{...i,...s},o,"cycle")},Re=async(e,t,n)=>{if(t.positionals.length===0)throw new d("Expected one or more work item references.");let s=b(t,n),r=await z(e,t),o=j(await re(e,r.id,n),s,n),i=new Set;for(let l of t.positionals){let u=await x(e,l,r.id);if(u.projectId!==r.id)throw new d(`${l} does not belong to project ${r.identifier}.`);i.add(u.issue.id)}return await e.request(`projects/${r.id}/${n}s/${o.id}/${n}-issues/`,{method:"POST",body:{issues:[...i]}}),{project:r.identifier,id:o.id,name:o.name,issues:[...i]}},_e=async(e,t,n)=>{let s=p(t.positionals[0],`a ${n} name or UUID`),r=await z(e,t),o=j(await re(e,r.id,n),s,n),l=(await e.listAll(`projects/${r.id}/${n}s/${o.id}/${n}-issues/`,{query:{fields:"id,name,sequence_id,priority,state",expand:"state",per_page:100}})).map((u)=>xe(u,r.identifier));return{rows:l,total:l.length}},At=async(e,t)=>{let n=p(t.positionals[0],"a source cycle"),s=p(t.positionals[1],"a target cycle"),r=await z(e,t),o=await re(e,r.id,"cycle"),i=j(o,n,"cycle"),l=j(o,s,"cycle");if(i.id===l.id)throw new d("Source and target cycles must be different.");return await e.request(`projects/${r.id}/cycles/${i.id}/transfer-issues/`,{method:"POST",body:{new_cycle_id:l.id}}),{project:r.identifier,from:i,to:l}},jt=(e,t)=>{if(e==null)return"?";if(/^\d{4}-\d{2}-\d{2}$/.test(e)||t===void 0)return e;try{return new Intl.DateTimeFormat("sv-SE",{timeZone:t,calendar:"iso8601",numberingSystem:"latn",year:"numeric",month:"2-digit",day:"2-digit"}).format(new Date(e))}catch{return e}},G=(e)=>{let t=e.end_date??e.target_date,n=e.start_date==null&&t==null?"":` ${jt(e.start_date,e.timezone)} / ${jt(t,e.timezone)}`;return`${g(e.name)} ${e.id}${n}${e.status===void 0?"":` (${e.status})`}`},Ie=(e)=>e.length===0?"no entries":e.map(G).join(`
34
- `),ve=(e)=>`added ${e.issues.length} work items to ${g(e.name)}`,Rt=(e)=>h([{name:"from",text:g(e.from.name)},{name:"to",text:g(e.to.name)}],"").join(`
35
- `);var _t=(e)=>{let t=p(e,"a project name");if(t.length>255||/[&+,:;$^}{*=?@#|'<>.()%!-]/.test(t))throw new d("Project name cannot contain special characters (including hyphens) or exceed 255 characters.");return t},It=(e)=>{let t=e.trim().toUpperCase();if(!/^[A-Z][A-Z0-9]{0,11}$/.test(t))throw new d("--identifier expects 1–12 letters or digits, starting with a letter.");return t},vt=(e)=>{let t={};for(let[n,s]of[["intake","intake_view"],["cycles","cycle_view"],["modules","module_view"]])if(e.flags.has(n))t[s]=P(e,n);return t},St=async(e,t)=>{let n={...vt(t),name:_t(t.positionals.join(" ")),identifier:It(b(t,"identifier"))},s=a(t,"description");if(s!==void 0)n.description=s;let r=n.intake_view===!0;if(r)delete n.intake_view;let o=await e.request("projects/",{method:"POST",body:n});if(!r)return o;try{return await e.request(`projects/${o.id}/`,{method:"PATCH",body:{intake_view:!0}})??{...o,intake_view:!0}}catch(i){return N(`${o.identifier} was created, but intake setup failed: ${i instanceof Error?i.message:String(i)}. Retry with i-plane project update ${o.id} --intake.`),o}},Tt=async(e,t)=>{let n=p(t.positionals[0],"a project reference"),s={...vt(t)},r=a(t,"name");if(r!==void 0)s.name=_t(r);let o=a(t,"description");if(o!==void 0)s.description=o;let i=a(t,"identifier");if(i!==void 0)s.identifier=It(i);v(s);let l=await y(e,n);return await e.request(`projects/${l.id}/`,{method:"PATCH",body:s})??{...l,...s}},Ot=async(e,t)=>{let n=await y(e,p(t.positionals[0],"a project reference"));return await e.request(`projects/${n.id}/archive/`,{method:"POST"}),n},H=(e)=>`${e.identifier} ${g(e.name)}`,Lt=async(e,t)=>{let n={name:p(t.positionals.join(" "),"a label name")},s=b(t,"project"),r=a(t,"color");n.color=se(r??"#808080");let o=a(t,"description");if(o!==void 0)n.description=o;let i=await y(e,s);return e.request(`projects/${i.id}/labels/`,{method:"POST",body:n})},qt=(e)=>{let t={},n=a(e,"name");if(n!==void 0)t.name=p(n,"a state name");let s=a(e,"color");if(s!==void 0)t.color=se(s);let r=a(e,"group");if(r!==void 0)t.group=R(r,M,"group");let o=a(e,"description");if(o!==void 0)t.description=o;return t},Et=async(e,t)=>{let n=p(t.positionals.join(" "),"a state name"),s=se(b(t,"color")),r=R(b(t,"group"),M,"group"),o={...qt(t),name:n,color:s,group:r},i=await y(e,b(t,"project"));return e.request(`projects/${i.id}/states/`,{method:"POST",body:o})},Dt=async(e,t)=>{let n=p(t.positionals[0],"a state name or UUID"),s=qt(t);v(s);let r=await y(e,b(t,"project")),o=j(await k(e,r.id),n,"state");return await e.request(`projects/${r.id}/states/${o.id}/`,{method:"PATCH",body:s})??{...o,...s}},Se=(e)=>{if(!P(e,"yes"))throw new d("Deleting cannot be undone. Repeat with --yes.")},Ut=async(e,t)=>{Se(t);let n=await y(e,p(t.positionals[0],"a project reference"));return await e.request(`projects/${n.id}/`,{method:"DELETE"}),n},Nt=async(e,t)=>{Se(t);let n=p(t.positionals[0],"a label name or UUID"),s=await y(e,b(t,"project")),r=await e.listAll(`projects/${s.id}/labels/`,{query:{fields:"id,name",per_page:100}}),o=j(r,n,"label");return await e.request(`projects/${s.id}/labels/${o.id}/`,{method:"DELETE"}),o},zt=async(e,t)=>{Se(t);let n=p(t.positionals[0],"a state name or UUID"),s=await y(e,b(t,"project")),r=j(await k(e,s.id),n,"state");return await e.request(`projects/${s.id}/states/${r.id}/`,{method:"DELETE"}),r};var c=(e,t)=>async(n,s)=>C(await e(n),s,t),pn={cycles:c(({client:e,args:t})=>Ce(e,t,"cycle"),Ie),"cycle create":c(({client:e,args:t})=>Ae(e,t,"cycle"),(e)=>`created ${G(e)}`),"cycle update":c(({client:e,args:t})=>kt(e,t),G),"cycle add":c(({client:e,args:t})=>Re(e,t,"cycle"),ve),"cycle issues":c(({client:e,args:t})=>_e(e,t,"cycle"),ne),"cycle transfer":c(({client:e,args:t})=>At(e,t),Rt),modules:c(({client:e,args:t})=>Ce(e,t,"module"),Ie),"module create":c(({client:e,args:t})=>Ae(e,t,"module"),(e)=>`created ${G(e)}`),"module add":c(({client:e,args:t})=>Re(e,t,"module"),ve),"module issues":c(({client:e,args:t})=>_e(e,t,"module"),ne),"intake list":c(({client:e,args:t})=>dt(e,t),he),"intake create":c(({client:e,args:t})=>lt(e,t),(e)=>`created ${ee(e)}`),"intake show":c(({client:e,args:t})=>ct(e,t),ee),"intake update":c(({client:e,args:t})=>ut(e,t),ee),"intake rm":c(({client:e,args:t})=>pt(e,t),(e)=>`deleted intake entry ${e.ref}`),summary:c(({client:e,config:t})=>Ve(e,t),Be),projects:c(({client:e})=>Z(e),Ke),list:c(({client:e,args:t})=>ft(e,t),ne),show:c(({client:e,args:t,config:n})=>yt(e,t,n.workspace.value,n.url.value),gt),create:c(({client:e,args:t})=>ht(e,t),(e)=>`created ${e.ref} ${e.name}`),update:c(({client:e,args:t})=>je(e,t),(e)=>`${e.ref} ${e.name} (${e.state})`),done:c(({client:e,args:t})=>wt(e,t),(e)=>`${e.ref} ${e.state}`),delete:c(({client:e,args:t})=>Pt(e,t),(e)=>e),comment:c(({client:e,args:t})=>bt(e,t),(e)=>e),comments:c(({client:e,args:t})=>ot(e,t),X),search:c(({client:e,args:t})=>$t(e,t),xt),states:c(({client:e,args:t})=>Ye(e,t),Je),labels:c(({client:e,args:t})=>Ze(e,t),Xe),members:c(({client:e})=>Qe(e),et),whoami:c(({client:e})=>rt(e),st),"project create":c(({client:e,args:t})=>St(e,t),(e)=>`created ${H(e)}`),"project update":c(({client:e,args:t})=>Tt(e,t),H),"project archive":c(({client:e,args:t})=>Ot(e,t),(e)=>`archived ${H(e)}`),"project rm":c(({client:e,args:t})=>Ut(e,t),(e)=>`deleted ${H(e)}`),"label create":c(({client:e,args:t})=>Lt(e,t),(e)=>`created ${g(e.name)} ${e.id}`),"label rm":c(({client:e,args:t})=>Nt(e,t),(e)=>`deleted ${g(e.name)}`),"state create":c(({client:e,args:t})=>Et(e,t),(e)=>`created ${g(e.name)} ${e.group}`),"state update":c(({client:e,args:t})=>Dt(e,t),(e)=>`${g(e.name)} ${e.group}`),"state rm":c(({client:e,args:t})=>zt(e,t),(e)=>`deleted ${g(e.name)}`)},Mt=async(e,t,n,s,r)=>{let o=e===void 0?void 0:pn[e];if(o===void 0)throw new d(`No command "${e}". Run i-plane for the map.`);oe(e,n),await o({client:t,args:n,config:s},r)};import{createHash as mn,randomUUID as fn}from"node:crypto";import{constants as Te}from"node:fs";import{chmod as yn,lstat as gn,mkdir as hn,open as Ft,rename as wn,unlink as Gt}from"node:fs/promises";import{homedir as Pn}from"node:os";import{join as Oe}from"node:path";var Ht=300000,bn=()=>process.env.PLANE_PAGE_CACHE??Oe(process.env.XDG_CACHE_HOME??Oe(Pn(),".cache"),"i-plane","page-transports");class ie{path;directory;now;constructor(e,t=bn(),n=Date.now){this.directory=t,this.now=n,this.path=Oe(t,`${mn("sha256").update(new URL(e).href.replace(/\/+$/,"")).digest("hex")}.json`)}async read(){try{let e=await Ft(this.path,Te.O_RDONLY|Te.O_NOFOLLOW|Te.O_NONBLOCK);try{let t=await e.stat();if(!t.isFile()||t.size>2048||t.mode&63)return;let n=JSON.parse(await e.readFile("utf8")),s=this.now();if(n.version!==1||!["api-key","session"].includes(n.mode)||!["public-list","missing-route","extension-disabled"].includes(n.reason)||typeof n.runtime!=="boolean"||typeof n.keyProbe!=="boolean"||!Number.isFinite(n.checkedAt)||!Number.isFinite(n.expiresAt)||n.checkedAt>s||n.expiresAt<=s||n.expiresAt!==n.checkedAt+Ht)return;if(n.mode==="api-key"!==(n.reason==="public-list"))return;return n}finally{await e.close()}}catch{return}}async clear(){try{return await Gt(this.path),!0}catch(e){return e.code==="ENOENT"}}async write(e,t,n,s){let r=this.now(),o={version:1,mode:e,reason:t,runtime:n,keyProbe:s,checkedAt:r,expiresAt:r+Ht},i=`${this.path}.${fn()}.tmp`;try{await hn(this.directory,{recursive:!0,mode:448});let l=await gn(this.directory);if(!l.isDirectory()||l.isSymbolicLink())return o;await yn(this.directory,448);let u=await Ft(i,"wx",384);try{await u.writeFile(JSON.stringify(o))}finally{await u.close()}await wn(i,this.path)}catch{}finally{await Gt(i).catch(()=>{})}return o}}var Wt=async(e,t=!1)=>{let n=new ie(e),s=t?await n.clear():!1,r=s?void 0:await n.read(),o={"public-list":"The public project-page list accepted an API key.","missing-route":"The public page route and extension configuration were absent.","extension-disabled":"The instance reports that API-key pages are unavailable."};return{mode:r?.mode??"unknown",reason:t&&!s?"Could not clear the capability cache. Use --refresh-pages on the page command to bypass it.":r?r.mode==="session"&&!r.keyProbe?"No API key was configured and the instance did not advertise API-key pages.":o[r.reason]:t?"Cached selection cleared; the next page command will detect access again.":"No fresh selection is cached; the next page command will detect access automatically.",checkedAt:r?new Date(r.checkedAt).toISOString():null,expiresAt:r?new Date(r.expiresAt).toISOString():null,cachePath:n.path}};class de extends w{}class qe{config;api;cache;sessionDirectory;selection;initialized=!1;sessionClient;prepared=new Set;firstLists=new Map;refresh;commandScope=!1;mutationStarted=!1;constructor(e,t={}){this.config=e,this.api=new ae(e),this.cache=t.cache??new ie(e.url.value),this.refresh=t.refresh??!1,this.sessionDirectory=t.sessionDirectory}beginPageCommand(){this.commandScope=!0,this.mutationStarted=!1}markPageMutation(){this.mutationStarted=!0}async runtime(){let e;try{e=await this.api.request("/api/extensions/configuration/")}catch(t){if(t instanceof w&&t.status===404)return;throw t}if(!e||!Array.isArray(e.extensions)||!e.extensions.every((t)=>t&&typeof t.id==="string"&&typeof t.enabled==="boolean")||!(e.release===null||typeof e.release==="string"&&e.release.length>0))throw new w("Invalid extension configuration; page access could not be determined.");return e}async selectSession(e){let t=await this.runtime();if(t?.extensions.some((n)=>n.id==="api-key-pages"&&n.enabled)){if(e)throw e;throw new d("This Plane supports API-key pages. Set PLANE_API_KEY or --token before using page commands.")}this.selection=await this.cache.write("session",t?"extension-disabled":"missing-route",!!t,!!this.config.token.value)}async initialize(){if(this.initialized)return;if(this.refresh)await this.cache.clear();if(this.selection=this.refresh?void 0:await this.cache.read(),this.config.token.value&&this.selection&&!this.selection.keyProbe)this.selection=void 0;if(!this.config.token.value){if(this.selection?.mode==="api-key")throw new d("Set PLANE_API_KEY or --token to use this instance's API-key pages.");if(!this.selection)await this.selectSession()}this.initialized=!0}async session(){if(!this.sessionClient){let[{SessionClient:e},{resolveSessionConfig:t}]=await Promise.all([import("./chunks/session-2t143y9g.js"),import("./chunks/session-config-0fbdavjt.js")]);this.sessionClient=new e(t(this.config,this.sessionDirectory))}return this.sessionClient}async preparePages(e){if(await this.initialize(),this.prepared.has(e))return;let t=this.selection?.mode??"api-key";if(!this.selection){let n=`projects/${e}/pages/`;try{let s=await this.api.request(n);this.validateList(s,n),this.selection=await this.cache.write("api-key","public-list",!0,!0),this.firstLists.set(n,s)}catch(s){if(!(s instanceof w)||s.status!==404)throw s;await this.selectSession(s)}}if(this.selection?.mode==="session")await this.session();if(this.prepared.add(e),t!==this.selection?.mode)return"changed-identity"}async request(e,t={}){await this.initialize();let n=/^projects\/([^/]+)\/pages\//.exec(e);if(n?.[1])await this.preparePages(n[1]);if((t.method??"GET")!=="GET"&&e!=="/live/convert-document")this.markPageMutation();if(this.selection?.mode==="session")return(await this.session()).request(e,t);if((t.method??"GET")==="GET"&&!t.query&&this.firstLists.has(e)){let s=this.firstLists.get(e);return this.firstLists.delete(e),s}try{return await this.api.request(e,t)}catch(s){if(s instanceof w&&s.status===404&&/^projects\/[^/]+\/pages\/$/.test(e)&&(t.method??"GET")==="GET"&&!t.query?.cursor){if(await this.cache.clear(),await this.selectSession(s),this.commandScope){if(this.mutationStarted)throw new w("Page access changed after a mutation started. Inspect the page before retrying; no writes were replayed.");throw new de("Page access changed; resolve project references again under the selected identity.")}return(await this.session()).request(e,t)}throw s}}validateList(e,t){if(!Array.isArray(e)&&(!e||typeof e!=="object"||!("results"in e)||!Array.isArray(e.results)))throw new w(`Unexpected page list response: ${t}`)}async listAll(e,t={}){let n=[],s=new Set,r;do{let o=await this.request(e,r?{...t,query:{...t.query,cursor:r}}:t);if(this.validateList(o,e),Array.isArray(o))return[...n,...o];if(n.push(...o.results),r=o.next_page_results?o.next_cursor:void 0,r){if(s.has(r))throw new w("Page API repeated a pagination cursor.");s.add(r)}}while(r);return n}async liveCredentials(e,t=!1){if(this.selection?.mode!=="session")return;let s=await(await this.session()).session(t),r=await this.runtime();if(r&&!r.release&&r.extensions.length)throw new w("The for-plane runtime has no active extension release.");return{token:JSON.stringify({id:s.userId,cookie:`session-id=${s.sessionId}; csrftoken=${s.csrf}`,readOnly:!e}),...r?.release?{release:r.release}:{}}}}var $n=(e)=>async(t,n,s)=>{let{runPageContent:r}=await import("./chunks/page-content-es7q27cn.js");await r(e,t,n,s)},xn={...Object.fromEntries(["page outline","page read","page stamp","page create","page set","page insert","page rm"].map((e)=>[e,$n(e)])),pages:async(e,t,n)=>{let s=await Ee(e,p(t.positionals[0],"a project"));C(await Vt(e,s.id),n,Kt)},"page show":async(e,t,n)=>{let s=p(t.positionals[0],"a project"),r=p(t.positionals[1],"a page UUID or name"),o=await Ee(e,s),i=Yt(await Bt(e,o.id,r));if(i.losses.length)N(`Warning: ${i.losses.join("; ")}`);C(i,n,(l)=>l.markdown)}},De=(e)=>e==="pages"||e.startsWith("page "),Jt=async(e,t,n,s)=>{let r=xn[e];if(!r)throw new d(`Unknown page command "${e}".`);t.beginPageCommand?.();for(let o=0;o<2;o++)try{await r(t,n,s);return}catch(i){if(!(i instanceof de)||o>0)throw i}};var jn="2.0.0",V,Cn=(e,t)=>{let n=e===void 0?void 0:T(e);if(n===void 0){if(e===void 0||e==="help"||e==="version"||W(e).length>0){let o=[...t.flags.keys()].filter((i)=>!Zt.includes(i));if(o.length>0)throw new d(`${e??"i-plane"} does not take ${o.map((i)=>`--${i}`).join(", ")}.`)}return}V=e;let s=Xt(n),r=[...t.flags.keys()].filter((o)=>!s.has(o));if(r.length>0){let o=r.map((i)=>`--${i}`).join(", ");throw new d(`${n.name} does not take ${o}. Its flags are listed below.`)}},kn=(e,t)=>{let n=e.path.length===0?void 0:e.path.join(" "),s=n===void 0?void 0:T(n)?.name??n;if(Cn(s,e),s!==void 0&&W(s).length>0){let r=W(s);if(P(e,"help"))return C({commands:r,globalOptions:L},t,(o)=>`${o.commands.map((i)=>me({command:i},!1)).join(`
33
+ showing the first ${t} matches; more exist — raise --limit (up to 1000) or narrow the query`:o};var M=(e,t,n=!1)=>y(e,u((n?t.positionals[0]:void 0)??i(t,"project"),"--project <ref>"),"id,name,identifier,timezone"),je=async(e,t,n)=>{let o=await M(e,t,!0);return(await e.listAll(`projects/${o.id}/${n}s/`,{query:{fields:n==="cycle"?"id,name,start_date,end_date":"id,name,start_date,target_date,status",per_page:100}})).map((s)=>xe(s,o,n))},xe=(e,t,n)=>n==="cycle"&&t.timezone!==void 0?{...e,timezone:t.timezone}:e,re=(e,t,n)=>e.listAll(`projects/${t}/${n}s-lite/`,{query:{per_page:100}}),wt=(e,t)=>{let n={},o=i(e,"name");if(o!==void 0)n.name=u(o,`a ${t} name`);let r=i(e,"description");if(r!==void 0)n.description=r;let s=i(e,"start"),a=t==="cycle"?"end":"due",l=i(e,a),p=s===void 0?null:v(s,"start"),m=l===void 0?null:v(l,a);if(t==="cycle"&&(s===void 0!==(l===void 0)||p===null!==(m===null)))throw new d("A cycle needs both --start and --end, or neither for a draft.");if(p!==null&&m!==null&&p>m)throw new d("The start date must not be after the end date.");if(s!==void 0)n.start_date=p;if(l!==void 0)n[t==="cycle"?"end_date":"target_date"]=m;if(t==="module"){let f=i(e,"status");if(f!==void 0)n.status=R(f,["backlog","planned","in-progress","paused","completed","cancelled"],"status")}return n},be=async(e,t,n)=>{let o={...wt(t,n),name:u(t.positionals.join(" "),`a ${n} name`)},r=await M(e,t);if(n==="cycle"){let a=i(t,"owner");o.owned_by=a===void 0?(await e.request("/api/v1/users/me/")).id:await te(e,a),o.project_id=r.id}let s=await e.request(`projects/${r.id}/${n}s/`,{method:"POST",body:o});return xe(s,r,n)},ht=async(e,t)=>{let n=u(t.positionals[0],"a cycle name or UUID"),o=wt(t,"cycle"),r=i(t,"owner");if(r===void 0)I(o);let s=await M(e,t),a=x(await re(e,s.id,"cycle"),n,"cycle");if(r!==void 0)o.owned_by=await te(e,r);else{let p=await e.request(`projects/${s.id}/cycles/${a.id}/`,{query:{fields:"id,name,owned_by"}});if(!p.owned_by)throw new S("Cannot preserve the cycle owner: the server did not return owned_by. Pass --owner explicitly.");o.owned_by=p.owned_by}let l=await e.request(`projects/${s.id}/cycles/${a.id}/`,{method:"PATCH",body:o});return xe(l??{...a,...o},s,"cycle")},Ce=async(e,t,n)=>{if(t.positionals.length===0)throw new d("Expected one or more work item references.");let o=P(t,n),r=await M(e,t),s=x(await re(e,r.id,n),o,n),a=new Set;for(let l of t.positionals){let p=await j(e,l,r.id);if(p.projectId!==r.id)throw new d(`${l} does not belong to project ${r.identifier}.`);a.add(p.issue.id)}return await e.request(`projects/${r.id}/${n}s/${s.id}/${n}-issues/`,{method:"POST",body:{issues:[...a]}}),{project:r.identifier,id:s.id,name:s.name,issues:[...a]}},ke=async(e,t,n)=>{let o=u(t.positionals[0],`a ${n} name or UUID`),r=await M(e,t),s=x(await re(e,r.id,n),o,n),l=(await e.listAll(`projects/${r.id}/${n}s/${s.id}/${n}-issues/`,{query:{fields:"id,name,sequence_id,priority,state",expand:"state",per_page:100}})).map((p)=>Pe(p,r.identifier));return{rows:l,total:l.length}},Pt=async(e,t)=>{let n=u(t.positionals[0],"a source cycle"),o=u(t.positionals[1],"a target cycle"),r=await M(e,t),s=await re(e,r.id,"cycle"),a=x(s,n,"cycle"),l=x(s,o,"cycle");if(a.id===l.id)throw new d("Source and target cycles must be different.");return await e.request(`projects/${r.id}/cycles/${a.id}/transfer-issues/`,{method:"POST",body:{new_cycle_id:l.id}}),{project:r.identifier,from:a,to:l}},gt=(e,t)=>{if(e==null)return"?";if(/^\d{4}-\d{2}-\d{2}$/.test(e)||t===void 0)return e;try{return new Intl.DateTimeFormat("sv-SE",{timeZone:t,calendar:"iso8601",numberingSystem:"latn",year:"numeric",month:"2-digit",day:"2-digit"}).format(new Date(e))}catch{return e}},N=(e)=>{let t=e.end_date??e.target_date,n=e.start_date==null&&t==null?"":` ${gt(e.start_date,e.timezone)} / ${gt(t,e.timezone)}`;return`${g(e.name)} ${e.id}${n}${e.status===void 0?"":` (${e.status})`}`},Re=(e)=>e.length===0?"no entries":e.map(N).join(`
34
+ `),_e=(e)=>`added ${e.issues.length} work items to ${g(e.name)}`,$t=(e)=>w([{name:"from",text:g(e.from.name)},{name:"to",text:g(e.to.name)}],"").join(`
35
+ `);var jt=(e)=>{let t=u(e,"a project name");if(t.length>255||/[&+,:;$^}{*=?@#|'<>.()%!-]/.test(t))throw new d("Project name cannot contain special characters (including hyphens) or exceed 255 characters.");return t},xt=(e)=>{let t=e.trim().toUpperCase();if(!/^[A-Z][A-Z0-9]{0,11}$/.test(t))throw new d("--identifier expects 1–12 letters or digits, starting with a letter.");return t},bt=(e)=>{let t={};for(let[n,o]of[["intake","intake_view"],["cycles","cycle_view"],["modules","module_view"]])if(e.flags.has(n))t[o]=h(e,n);return t},Ct=async(e,t)=>{let n={...bt(t),name:jt(t.positionals.join(" ")),identifier:xt(P(t,"identifier"))},o=i(t,"description");if(o!==void 0)n.description=o;let r=n.intake_view===!0;if(r)delete n.intake_view;let s=await e.request("projects/",{method:"POST",body:n});if(!r)return s;try{return await e.request(`projects/${s.id}/`,{method:"PATCH",body:{intake_view:!0}})??{...s,intake_view:!0}}catch(a){return z(`${s.identifier} was created, but intake setup failed: ${a instanceof Error?a.message:String(a)}. Retry with i-plane project update ${s.id} --intake.`),s}},kt=async(e,t)=>{let n=u(t.positionals[0],"a project reference"),o={...bt(t)},r=i(t,"name");if(r!==void 0)o.name=jt(r);let s=i(t,"description");if(s!==void 0)o.description=s;let a=i(t,"identifier");if(a!==void 0)o.identifier=xt(a);I(o);let l=await y(e,n);return await e.request(`projects/${l.id}/`,{method:"PATCH",body:o})??{...l,...o}},Rt=async(e,t)=>{let n=await y(e,u(t.positionals[0],"a project reference"));return await e.request(`projects/${n.id}/archive/`,{method:"POST"}),n},G=(e)=>`${e.identifier} ${g(e.name)}`,_t=async(e,t)=>{let n={name:u(t.positionals.join(" "),"a label name")},o=P(t,"project"),r=i(t,"color");n.color=oe(r??"#808080");let s=i(t,"description");if(s!==void 0)n.description=s;let a=await y(e,o);return e.request(`projects/${a.id}/labels/`,{method:"POST",body:n})},At=(e)=>{let t={},n=i(e,"name");if(n!==void 0)t.name=u(n,"a state name");let o=i(e,"color");if(o!==void 0)t.color=oe(o);let r=i(e,"group");if(r!==void 0)t.group=R(r,H,"group");let s=i(e,"description");if(s!==void 0)t.description=s;return t},It=async(e,t)=>{let n=u(t.positionals.join(" "),"a state name"),o=oe(P(t,"color")),r=R(P(t,"group"),H,"group"),s={...At(t),name:n,color:o,group:r},a=await y(e,P(t,"project"));return e.request(`projects/${a.id}/states/`,{method:"POST",body:s})},St=async(e,t)=>{let n=u(t.positionals[0],"a state name or UUID"),o=At(t);I(o);let r=await y(e,P(t,"project")),s=x(await C(e,r.id),n,"state");return await e.request(`projects/${r.id}/states/${s.id}/`,{method:"PATCH",body:o})??{...s,...o}},Ae=(e)=>{if(!h(e,"yes"))throw new d("Deleting cannot be undone. Repeat with --yes.")},vt=async(e,t)=>{Ae(t);let n=await y(e,u(t.positionals[0],"a project reference"));return await e.request(`projects/${n.id}/`,{method:"DELETE"}),n},Ot=async(e,t)=>{Ae(t);let n=u(t.positionals[0],"a label name or UUID"),o=await y(e,P(t,"project")),r=await e.listAll(`projects/${o.id}/labels/`,{query:{fields:"id,name",per_page:100}}),s=x(r,n,"label");return await e.request(`projects/${o.id}/labels/${s.id}/`,{method:"DELETE"}),s},Tt=async(e,t)=>{Ae(t);let n=u(t.positionals[0],"a state name or UUID"),o=await y(e,P(t,"project")),r=x(await C(e,o.id),n,"state");return await e.request(`projects/${o.id}/states/${r.id}/`,{method:"DELETE"}),r};var c=(e,t)=>async(n,o)=>b(await e(n),o,t),on={cycles:c(({client:e,args:t})=>je(e,t,"cycle"),Re),"cycle create":c(({client:e,args:t})=>be(e,t,"cycle"),(e)=>`created ${N(e)}`),"cycle update":c(({client:e,args:t})=>ht(e,t),N),"cycle add":c(({client:e,args:t})=>Ce(e,t,"cycle"),_e),"cycle issues":c(({client:e,args:t})=>ke(e,t,"cycle"),ne),"cycle transfer":c(({client:e,args:t})=>Pt(e,t),$t),modules:c(({client:e,args:t})=>je(e,t,"module"),Re),"module create":c(({client:e,args:t})=>be(e,t,"module"),(e)=>`created ${N(e)}`),"module add":c(({client:e,args:t})=>Ce(e,t,"module"),_e),"module issues":c(({client:e,args:t})=>ke(e,t,"module"),ne),"intake list":c(({client:e,args:t})=>tt(e,t),fe),"intake create":c(({client:e,args:t})=>nt(e,t),(e)=>`created ${ee(e)}`),"intake show":c(({client:e,args:t})=>rt(e,t),ee),"intake update":c(({client:e,args:t})=>ot(e,t),ee),"intake rm":c(({client:e,args:t})=>st(e,t),(e)=>`deleted intake entry ${e.ref}`),summary:c(({client:e,config:t})=>ze(e,t),Me),projects:c(({client:e})=>J(e),He),list:c(({client:e,args:t})=>it(e,t),ne),show:c(({client:e,args:t,config:n})=>dt(e,t,n.workspace.value,n.url.value),lt),create:c(({client:e,args:t})=>ct(e,t),(e)=>`created ${e.ref} ${e.name}`),update:c(({client:e,args:t})=>$e(e,t),(e)=>`${e.ref} ${e.name} (${e.state})`),done:c(({client:e,args:t})=>ut(e,t),(e)=>`${e.ref} ${e.state}`),delete:c(({client:e,args:t})=>pt(e,t),(e)=>e),comment:c(({client:e,args:t})=>mt(e,t),(e)=>e),comments:c(({client:e,args:t})=>Xe(e,t),X),search:c(({client:e,args:t})=>ft(e,t),yt),states:c(({client:e,args:t})=>Fe(e,t),Ne),labels:c(({client:e,args:t})=>Ge(e,t),We),members:c(({client:e})=>Ve(e),Be),whoami:c(({client:e})=>Ze(e),Je),"project create":c(({client:e,args:t})=>Ct(e,t),(e)=>`created ${G(e)}`),"project update":c(({client:e,args:t})=>kt(e,t),G),"project archive":c(({client:e,args:t})=>Rt(e,t),(e)=>`archived ${G(e)}`),"project rm":c(({client:e,args:t})=>vt(e,t),(e)=>`deleted ${G(e)}`),"label create":c(({client:e,args:t})=>_t(e,t),(e)=>`created ${g(e.name)} ${e.id}`),"label rm":c(({client:e,args:t})=>Ot(e,t),(e)=>`deleted ${g(e.name)}`),"state create":c(({client:e,args:t})=>It(e,t),(e)=>`created ${g(e.name)} ${e.group}`),"state update":c(({client:e,args:t})=>St(e,t),(e)=>`${g(e.name)} ${e.group}`),"state rm":c(({client:e,args:t})=>Tt(e,t),(e)=>`deleted ${g(e.name)}`)},qt=async(e,t,n,o,r)=>{let s=e===void 0?void 0:on[e];if(s===void 0)throw new d(`No command "${e}". Run i-plane for the map.`);se(e,n),await s({client:t,args:n,config:o},r)};var an=(e)=>async(t,n,o)=>{let{runPageContent:r}=await import("./chunks/page-content-kh1zbmn7.js");await r(e,t,n,o)},dn={...Object.fromEntries(["page outline","page read","page stamp","page create","page set","page insert","page rm"].map((e)=>[e,an(e)])),pages:async(e,t,n)=>{let o=await Ie(e,u(t.positionals[0],"a project"));b(await Lt(e,o.id),n,Ut)},"page show":async(e,t,n)=>{let o=u(t.positionals[0],"a project"),r=u(t.positionals[1],"a page UUID or name"),s=await Ie(e,o),a=Dt(await Et(e,s.id,r));if(a.losses.length)z(`Warning: ${a.losses.join("; ")}`);b(a,n,(l)=>l.markdown)}},Se=(e)=>e==="pages"||e.startsWith("page "),Mt=async(e,t,n,o)=>{let r=dn[e];if(!r)throw new d(`Unknown page command "${e}".`);t.beginPageCommand?.();for(let s=0;s<2;s++)try{await r(t,n,o);return}catch(a){if(!(a instanceof zt)||s>0)throw a}};var ln="2.0.1",V,cn=(e,t)=>{let n=e===void 0?void 0:O(e);if(n===void 0){if(e===void 0||e==="help"||e==="version"||W(e).length>0){let s=[...t.flags.keys()].filter((a)=>!Ht.includes(a));if(s.length>0)throw new d(`${e??"i-plane"} does not take ${s.map((a)=>`--${a}`).join(", ")}.`)}return}V=e;let o=Ft(n),r=[...t.flags.keys()].filter((s)=>!o.has(s));if(r.length>0){let s=r.map((a)=>`--${a}`).join(", ");throw new d(`${n.name} does not take ${s}. Its flags are listed below.`)}},un=(e,t)=>{let n=e.path.length===0?void 0:e.path.join(" "),o=n===void 0?void 0:O(n)?.name??n;if(cn(o,e),o!==void 0&&W(o).length>0){let r=W(o);if(h(e,"help"))return b({commands:r,globalOptions:q},t,(s)=>`${s.commands.map((a)=>ce({command:a},!1)).join(`
36
36
 
37
37
  `)}
38
38
 
39
- ${J(o.globalOptions)}`),!0;throw new d(`Expected ${s} <${r.map((o)=>o.name.split(" ")[1]).join("|")}>. Run i-plane ${s} --help.`)}if(s!==void 0&&s!=="help"&&s!=="version"&&T(s)===void 0){let r=W(s.split(" ")[0]??"");throw new d(`No command "${s}". ${r.length?`Available commands: ${r.map((o)=>o.name).join(", ")}. Run i-plane ${s.split(" ")[0]} --help.`:"Run i-plane for the map."}`)}if(s===void 0&&!P(e,"version"))return C(K(),t,Y),!0;if(s==="guide")return C(K(),t,Y),!0;if(s==="version"||P(e,"version"))return C({version:jn},t,(r)=>r.version),!0;if(s!==void 0&&P(e,"help")){let r=T(s);if(r!==void 0)return C({command:r,globalOptions:L},t,(o)=>me(o)),!0}if(s==="help")return C(K(),t,Y),!0;return!1},An=async()=>{let e=Qt(process.argv.slice(2)),t=P(e,"json"),n=rn({token:a(e,"token"),configPath:a(e,"config")});if(n!==void 0)Ue(n);let s=e.path.join(" ");if(V=T(s)?.name,oe(s,e),kn(e,t))return;let r=sn({url:a(e,"url"),token:a(e,"token"),workspace:a(e,"workspace"),configPath:a(e,"config")},s==="config"||De(s));if(r.token.value)Ue(r.token.value);let o=e.path.length===0?void 0:e.path.join(" "),i=o===void 0?void 0:T(o)?.name??o;if(V=i,i==="config"){C({...tt(r),pages:await Wt(r.url.value,P(e,"refresh-pages"))},t,nt);return}if(en(r.url.value)&&await tn(r.url.value)===void 0){let m=await nn(r.url.value);if(m!==void 0)process.exit(m)}let l=new ae(r),u=a(e,"session-cache");if(De(s))await Jt(s,new qe(r,{refresh:P(e,"refresh-pages"),...u?{sessionDirectory:u}:{}}),e,t);else await Mt(i,l,e,r,t)};An().catch((e)=>{if(e instanceof d){let t=V===void 0?void 0:T(V);le(t===void 0?e.message:He(t,e.message),2)}if(e instanceof w)le(e.message,1);le(e instanceof Error?e.message:String(e),1)});
39
+ ${Z(s.globalOptions)}`),!0;throw new d(`Expected ${o} <${r.map((s)=>s.name.split(" ")[1]).join("|")}>. Run i-plane ${o} --help.`)}if(o!==void 0&&o!=="help"&&o!=="version"&&O(o)===void 0){let r=W(o.split(" ")[0]??"");throw new d(`No command "${o}". ${r.length?`Available commands: ${r.map((s)=>s.name).join(", ")}. Run i-plane ${o.split(" ")[0]} --help.`:"Run i-plane for the map."}`)}if(o===void 0&&!h(e,"version"))return b(K(),t,Y),!0;if(o==="guide")return b(K(),t,Y),!0;if(o==="version"||h(e,"version"))return b({version:ln},t,(r)=>r.version),!0;if(o!==void 0&&h(e,"help")){let r=O(o);if(r!==void 0)return b({command:r,globalOptions:q},t,(s)=>ce(s)),!0}if(o==="help")return b(K(),t,Y),!0;return!1},pn=async()=>{let e=Nt(process.argv.slice(2)),t=h(e,"json"),n=Kt({token:i(e,"token"),configPath:i(e,"config")});if(n!==void 0)ve(n);let o=e.path.join(" ");if(V=O(o)?.name,se(o,e),un(e,t))return;let r=Yt({url:i(e,"url"),token:i(e,"token"),workspace:i(e,"workspace"),configPath:i(e,"config")},o==="config"||Se(o));if(r.token.value)ve(r.token.value);let s=e.path.length===0?void 0:e.path.join(" "),a=s===void 0?void 0:O(s)?.name??s;if(V=a,a==="config"){b({...Ke(r),pages:await Zt(r.url.value,h(e,"refresh-pages"))},t,Ye);return}if(Gt(r.url.value)&&await Wt(r.url.value)===void 0){let m=await Vt(r.url.value);if(m!==void 0)process.exit(m)}let l=new Bt(r),p=i(e,"session-cache");if(Se(o))await Mt(o,new Jt(r,{refresh:h(e,"refresh-pages"),...p?{sessionDirectory:p}:{}}),e,t);else await qt(a,l,e,r,t)};pn().catch((e)=>{if(e instanceof d){let t=V===void 0?void 0:O(V);ae(t===void 0?e.message:Ue(t,e.message),2)}if(e instanceof S)ae(e.message,1);ae(e instanceof Error?e.message:String(e),1)});
package/docs/pages.md CHANGED
@@ -149,6 +149,16 @@ supports `--json`. Run `i-plane page set --help` for flags and examples.
149
149
 
150
150
  ## Knowledge review marks
151
151
 
152
+ Writing a product node requires confirmation that the server preserves it.
153
+ Until the reader-capability endpoint is available, `knowledgeReview` writes are
154
+ refused with exit code **1**, before conversion, page creation or document changes.
155
+ This applies to create, replace, insert and edits that would retain an existing
156
+ review node. `--allow-loss` and `--force` cannot override it. Ordinary Markdown
157
+ and explicit removal of the last review node remain supported. Existing review
158
+ content can still be read. Reader discovery will use the existing per-instance
159
+ capability mechanism and `--refresh-pages`; transport support alone is not proof
160
+ of document-schema support.
161
+
152
162
  Saved detail responses from the matching extension include canonical JSON for
153
163
  review restoration. If older HTML lost review attributes, `page show` can recover
154
164
  them by the retained block ID. Missing or ambiguous IDs, invalid canonical fields,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i-plane",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Compact Plane CLI for coding agents: tasks, projects, live pages, cycles, modules and intake.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,2 +0,0 @@
1
- import{A as q,B as $e,C as K,E as Ae,F as V,l as oe,n as C,o as R,p as F,w as ae,x as se,y as ce,z as le}from"./cli-3n3mxdd7.js";import{J as be,O as d}from"./cli-ajj9jddd.js";import{Y as h,Z as U,_ as X}from"./cli-q37j0y8m.js";import{ba as Re,ca as Ee,ga as O,ia as w,ja as P}from"./cli-jq1agk1s.js";var ne=Ee(function(Ve,re){var N=!0,ee=!1,te=!1;re.exports=function(e,t){if(t)N=!t.enabled,ee=!!t.label,te=!!t.labelAfter;e.core.ruler.after("inline","github-task-lists",function(r){var n=r.tokens;for(var i=2;i<n.length;i++)if(Ye(n,i))Le(n[i],r.Token),Z(n[i-2],"class","task-list-item"+(!N?" enabled":"")),Z(n[Se(n,i-2)],"class","contains-task-list")})};function Z(e,t,r){var n=e.attrIndex(t),i=[t,r];if(n<0)e.attrPush(i);else e.attrs[n]=i}function Se(e,t){var r=e[t].level-1;for(var n=t-1;n>=0;n--)if(e[n].level===r)return n;return-1}function Ye(e,t){return De(e[t])&&je(e[t-1])&&Be(e[t-2])&&Oe(e[t])}function Le(e,t){if(e.children.unshift(Xe(e,t)),e.children[1].content=e.children[1].content.slice(3),e.content=e.content.slice(3),ee)if(te){e.children.pop();var r="task-item-"+Math.ceil(Math.random()*1e7-1000);e.children[0].content=e.children[0].content.slice(0,-1)+' id="'+r+'">',e.children.push(Ce(e.content,r,t))}else e.children.unshift(Me(t)),e.children.push(Te(t))}function Xe(e,t){var r=new t("html_inline","",0),n=N?' disabled="" ':"";if(e.content.indexOf("[ ] ")===0)r.content='<input class="task-list-item-checkbox"'+n+'type="checkbox">';else if(e.content.indexOf("[x] ")===0||e.content.indexOf("[X] ")===0)r.content='<input class="task-list-item-checkbox" checked=""'+n+'type="checkbox">';return r}function Me(e){var t=new e("html_inline","",0);return t.content="<label>",t}function Te(e){var t=new e("html_inline","",0);return t.content="</label>",t}function Ce(e,t,r){var n=new r("html_inline","",0);return n.content='<label class="task-list-item-label" for="'+t+'">'+e+"</label>",n.attrs=[{for:t}],n}function De(e){return e.type==="inline"}function je(e){return e.type==="paragraph_open"}function Be(e){return e.type==="list_item_open"}function Oe(e){return e.content.indexOf("[ ] ")===0||e.content.indexOf("[x] ")===0||e.content.indexOf("[X] ")===0}});import{readFile as Je}from"node:fs/promises";import{createHash as Fe,randomUUID as Ue}from"node:crypto";var de=Re(ne(),1);import*as p from"yjs";var S=(e)=>String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"),v=(e,t)=>t==null||t===""?"":` ${e}="${S(t)}"`,T=(e)=>{if(Array.isArray(e))return e.map(T);if(e&&typeof e==="object")return Object.fromEntries(Object.entries(e).sort(([t],[r])=>t.localeCompare(r)).map(([t,r])=>[t,T(r)]));return e},Ie=new Set(["doc","paragraph","heading","bulletlist","orderedlist","listitem","tasklist","taskitem","blockquote","codeblock","horizontalrule","hardbreak","table","tablerow","tableheader","tablecell","imagecomponent","image","knowledgereview"]),fe=(e,t=!0)=>e instanceof p.XmlText?{text:T(e.toDelta())}:{kind:e.nodeName,attributes:T(Object.fromEntries(Object.entries(e.getAttributes()).filter(([r])=>r!=="id"||!(t||Ie.has(e.nodeName.toLowerCase()))))),children:e.toArray().map((r)=>fe(r,!1))},_=(e)=>Fe("sha256").update(JSON.stringify(fe(e))).digest("hex"),Y=(e)=>e instanceof p.XmlElement&&e.nodeName==="knowledgeReview"?`Reviewed ${String(e.getAttribute("reviewedAt")??"")}: ${String(e.getAttribute("source")??"")}`:e instanceof p.XmlText?e.toDelta().map((t)=>typeof t.insert==="string"?t.insert:JSON.stringify(t.insert)).join(""):e.toArray().map((t)=>Y(t)).join(" "),me=(e)=>e.toArray().map((t,r)=>{let n=t instanceof p.XmlElement?String(t.getAttribute("id")??"")||null:null;return{index:r,anchor:n,shortAnchor:n?w(n).slice(0,8):null,kind:t instanceof p.XmlElement?t.nodeName:"text",preview:w(Y(t)).replace(/\s+/g," ").trim().slice(0,40)}}),D=(e,t)=>{let r=e.toArray().flatMap((i,a)=>{if(!(i instanceof p.XmlElement))return[];let s=String(i.getAttribute("id")??"");return s.length>0&&s.toLowerCase().startsWith(t.toLowerCase())?[{node:i,index:a,anchor:s}]:[]});if(r.length===0)throw new d(`No top-level block matches "${t}". Run page outline to see current anchors.`,404);if(r.length!==1)throw new h(`Ambiguous block anchor "${t}": ${r.map((i)=>`${i.anchor} [${i.index}]`).join(", ")}`);let n=r[0];if(!n)throw new d("Block disappeared.");return n},H=(e)=>{let t=0;for(let r of e.toArray())if(r instanceof p.XmlElement&&!r.getAttribute("id"))r.setAttribute("id",Ue()),t++;return t},j=(e,t,r=!1)=>{if(e instanceof p.XmlText){let o=Y(e),c=r?w(o):o;if(c!==o)return t.add("Sensitive text was redacted; the printed block is not a lossless copy"),S(c);return e.toDelta().map((f)=>{let l=S(typeof f.insert==="string"?f.insert:JSON.stringify(f.insert));for(let[m,y]of Object.entries(f.attributes??{})){let E=Object.fromEntries(Object.entries(y&&typeof y==="object"?y:{}).map(([A,k])=>[A,r&&typeof k==="string"?w(k):k]));if(m==="bold")l=`<strong>${l}</strong>`;else if(m==="italic")l=`<em>${l}</em>`;else if(m==="strike")l=`<s>${l}</s>`;else if(m==="code")l=`<code>${l}</code>`;else if(m==="link")l=`<a${v("href",E.href)}${v("title",E.title)}>${l}</a>`;else if(t.add(`Mark ${m} is not representable by this Markdown reader`),m==="underline")l=`&lt;u&gt;${l}&lt;/u&gt;`}return l}).join("")}let n=e.nodeName.toLowerCase(),i=Object.fromEntries(Object.entries(e.getAttributes()).map(([o,c])=>[o,r&&typeof c==="string"?w(c):c])),a=()=>e.toArray().map((o)=>j(o,t,r)).join("");if(i.textAlign&&i.textAlign!=="left")t.add("Text alignment is not representable in Markdown");if(n==="knowledgereview"){let o=String(i.reviewedAt??""),c=String(i.source??"");if(typeof i.reviewedAt!=="string"||typeof i.source!=="string"||!se(o)||!c.trim())t.add("Review metadata is invalid");if(Object.keys(i).some((f)=>!["id","reviewedAt","source"].includes(f))||e.length)t.add("Additional review attributes or content are not represented in Markdown");if(r&&(i.reviewedAt!==e.getAttribute("reviewedAt")||i.source!==e.getAttribute("source")))t.add("Sensitive review metadata was redacted; the printed block is not a lossless copy");return q({date:o,source:c})}if(n==="doc")return a();if(n==="paragraph")return`<p>${a()}</p>`;if(n==="heading"){let o=Math.min(6,Math.max(1,Number(i.level)||1));return`<h${o}>${a()}</h${o}>`}if(n==="bulletlist")return`<ul>${a()}</ul>`;if(n==="orderedlist")return`<ol${v("start",i.start)}>${a()}</ol>`;if(n==="listitem")return`<li>${a()}</li>`;if(n==="tasklist")return`<ul>${a()}</ul>`;if(n==="taskitem"){let o=`<input type="checkbox"${i.checked===!0||i.checked==="true"?" checked":""}>`,c=a().replace(/^<p>([\s\S]*?)<\/p>/,"$1");return`<li>${o}${c}</li>`}if(n==="blockquote")return`<blockquote>${a()}</blockquote>`;if(n==="codeblock"&&i.language==="knowledge-review")t.add("The knowledge-review fence language is reserved for review metadata");if(n==="codeblock")return`<pre><code${i.language?v("class",`language-${i.language}`):""}>${S(r?w(Y(e)):Y(e))}</code></pre>`;if(n==="horizontalrule")return"<hr>";if(n==="hardbreak")return"<br>";if(n==="table")return`<table>${a()}</table>`;if(n==="tablerow")return`<tr>${a()}</tr>`;if(n==="tablecell"||n==="tableheader"){let o=e.toArray().filter((l)=>l instanceof p.XmlElement),c=(l)=>l.nodeName.toLowerCase()==="hardbreak"||l.toArray().some((m)=>m instanceof p.XmlElement&&c(m));if(o.length>1||o.some((l)=>l.nodeName.toLowerCase()!=="paragraph"||c(l)))t.add("Multiple paragraphs, line breaks or block structure inside table cells are flattened in Markdown");if(Number(i.colspan??1)!==1||Number(i.rowspan??1)!==1)t.add("Merged table cells are not representable in Markdown");if(i.background||i.colwidth)t.add("Table styling is not representable in Markdown");let f=n==="tablecell"?"td":"th";return`<${f}>${a()}</${f}>`}if(n==="imagecomponent"||n==="image"){if(i.width||i.height||i.alignment)t.add("Image dimensions or alignment are not representable in Markdown");return`<img${v("src",i.src)}${v("alt",i.alt)}${v("title",i.title)}>`}t.add(`Unsupported node ${e.nodeName}; preserved as XML text`);let s=e.toString();return`<pre><code class="language-xml">${S(r?ae(s):s)}</code></pre>`},Ne=(e)=>{let t=new Set,r=e.toArray().map((n)=>j(n,t)).join("");return{markdown:C(r),losses:[...t]}},ge=(e,t)=>{let{node:r,anchor:n}=D(e,t),i=new Set;return{anchor:n,fingerprint:_(r),markdown:C(j(r,i,!0)),losses:[...i]}},pe=(e)=>{let t=new Set;for(let r of e)j(r,t);return[...t]},L=new oe({html:!1}).use(de.default),qe=L.renderer.rules.fence;L.renderer.rules.fence=(e,t,r,n,i)=>{let a=e[t];if(/^knowledge-review\s/.test(a?.info.trim()??""))throw new h("A knowledge-review fence does not accept additional info fields.");if(a?.info.trim()==="knowledge-review"){let s=ce(a.content);return n?.reviewAsCode?q(s):le(s)}return qe?.(e,t,r,n,i)??i.renderToken(e,t,r)};L.core.ruler.before("github-task-lists","empty-task-items",(e)=>{for(let t=2;t<e.tokens.length;t++){let r=e.tokens[t],n=r?.children?.[0];if(r&&n&&/^\[[ xX]\]$/.test(r.content)&&e.tokens[t-1]?.tag==="p"&&e.tokens[t-2]?.tag==="li")r.content+=" ",n.content+=" "}});var ue=(e)=>e.toArray().flatMap((t)=>t instanceof p.XmlElement?[...t.nodeName.toLowerCase()==="codeblock"?[t]:[],...ue(t)]:[]),ie=(e,t=!1)=>L.render(e,{reviewAsCode:t}).trim().replace(/(<li class="task-list-item">)\s*<p>([\s\S]*?)<\/p>/g,"$1$2").replace(/(<input class="task-list-item-checkbox"[^>]*>) /g,"$1"),he=async(e,t)=>{let r=ie(t);if(!r){let s=new p.Doc;return{doc:s,fragment:s.getXmlFragment("default"),losses:[]}}let n=r.replace(/<img([^>]*?)\s*\/?>/g,"<image-component$1></image-component>").replace(/<ul class="contains-task-list">/g,'<ul data-type="taskList">').replace(/<li class="task-list-item">(\s*<p>)?<input\b([^>]*)>/g,(s,o,c)=>`<li data-type="taskItem" data-checked="${/\bchecked=/.test(c)}">${o??""}`),i=await e.request("/live/convert-document",{method:"POST",body:{description_html:n,variant:"rich"}}),a=new p.Doc;try{if(typeof i.description_binary!=="string"||!i.description_binary)throw Error("Missing document binary");p.applyUpdate(a,Buffer.from(i.description_binary,"base64"));let s=a.getXmlFragment("default"),o=L.parse(t,{}).filter((m)=>m.block&&m.tag==="code"&&m.info.trim()!=="knowledge-review").map((m)=>m.info.trim().split(/\s+/)[0]||null),c=ue(s),f=[];if(o.length!==c.length)f.push("The converter changed the number of code blocks");else a.transact(()=>c.forEach((m,y)=>{let x=o[y];if(x)m.setAttribute("language",x);else m.removeAttribute("language")}));if(Ne(s).markdown!==C(ie(t,!0)))f.push("The converter changed Markdown content or formatting");return a.transact(()=>H(s)),{doc:a,fragment:s,losses:f}}catch(s){if(a.destroy(),s instanceof d)throw s;throw new d(`Cannot decode the converted document: ${s instanceof Error?s.message:String(s)}`)}};import*as B from"yjs";var W=(e,t=!1)=>{if(e.length&&!t)throw new h(`This edit can lose content or formatting: ${e.join("; ")}. Inspect the document, then pass --allow-loss to accept these losses.`)},we=(e,t,r)=>{let n=t.block?D(e,t.block):void 0;if(n&&t.ifMatch&&!t.force&&_(n.node)!==t.ifMatch)throw new d("Block content changed since page read. Read it again and use its new --if-match fingerprint, or pass --force to overwrite the concurrent edit.",409);let i=r?.fragment.length??0;if(t.kind!=="rm"&&!r)throw new h("Expected Markdown content.");if((t.kind==="insert"||n&&t.kind==="set")&&i===0)throw new h("Empty block content. Use page rm --block to remove a block.");let a=t.kind==="insert"?[]:n?[n.node]:e.toArray(),s=[...new Set([...r?.losses??[],...pe(a)])];if(t.kind!=="rm")W(s,t.allowLoss);let o=n?.index??0;if(t.kind==="insert")o=t.after?D(e,t.after).index+1:e.length;let c=r?.fragment.toArray().map((f)=>{if(!(f instanceof B.XmlElement)&&!(f instanceof B.XmlText))throw new d("Unsupported document block; no changes were made.");return f.clone()})??[];if(t.kind!=="insert")e.delete(o,n?1:e.length);if(t.kind!=="rm"&&c.length){if(e.insert(o,c),n&&c[0]&&"setAttribute"in c[0])c[0].setAttribute("id",n.anchor)}return t.kind==="rm"?[]:s};import{HocuspocusProvider as _e,HocuspocusProviderWebsocket as He}from"@hocuspocus/provider";import{HttpsProxyAgent as We}from"https-proxy-agent";import ze from"ws";import*as ke from"yjs";class z extends d{}class ye{doc=new ke.Doc;fragment=this.doc.getXmlFragment("default");socket;provider;agent;pending;failure;writing=!1;acknowledged=!1;disposed=!1;deadline;constructor(e,t,r,n=20000){this.deadline=n,O(r);let i=be(e);if(i)O(i),this.agent=new We(i);let a=this.agent;class s extends ze{constructor(o){super(o,{agent:a,handshakeTimeout:n})}}this.socket=new He({url:e,WebSocketPolyfill:s,autoConnect:!1,maxAttempts:1,onClose:()=>this.fail(new d("Live connection closed."))}),this.socket.on("maxAttemptsFailed",()=>this.fail(new d("Cannot connect to the live server."))),this.provider=new _e({websocketProvider:this.socket,name:t,document:this.doc,awareness:null,token:r,forceSyncInterval:!1,flushDelay:!1,onClose:()=>this.fail(new d("Live document connection closed.")),onSynced:()=>this.progress(),onUnsyncedChanges:()=>this.progress(),onAuthenticationFailed:()=>this.fail(new z("Live authentication was refused."))}),this.provider.attach()}progress(){if(this.disposed||this.failure||!this.provider?.isSynced||this.provider.hasUnsyncedChanges)return;if(this.writing)this.acknowledged=!0;this.pending?.resolve()}fail(e){if(this.disposed||this.failure)return;if(this.writing&&!this.acknowledged)e=new d("Live connection failed after sending changes; delivery is uncertain. Inspect the live document before retrying. The command was not replayed.");this.failure=e,this.socket.shouldConnect=!1,this.pending?.reject(e)}async wait(e){if(this.failure)throw this.failure;let t;try{await new Promise((r,n)=>{this.pending={resolve:r,reject:n},t=setTimeout(()=>this.fail(new d("Live synchronization timed out.")),this.deadline),e(),this.progress()})}finally{clearTimeout(t),this.pending=void 0}}async ready(){await this.wait(()=>{this.socket.connect().catch(()=>this.fail(new d("Cannot connect to the live server.")))})}async write(e){if(this.failure)throw this.failure;if(!this.provider.isSynced)throw new d("Live document is not synchronized.");if(this.provider.authorizedScope!=="read-write")throw new d("The connection does not allow writing this page.");let t=!1,r=(n,i)=>{if(i===this)t=!0};this.doc.on("update",r);try{return await this.wait(()=>{this.writing=!0,this.doc.transact(()=>e(this.fragment),this)}),{delivery:t?"acknowledged":"unchanged",persistence:"asynchronous"}}finally{this.doc.off("update",r)}}destroy(){if(this.disposed)return;this.disposed=!0,this.provider.destroy(),this.socket.destroy(),this.agent?.destroy(),this.doc.destroy()}}var ve=async(e,t,r,n={})=>{await e.preparePages?.(t);let i=!!n.writable,a=await e.liveCredentials?.(i);if(!a){O(e.config.token.value);let s=await e.request("/api/extensions/configuration/").catch((o)=>{if(o instanceof d&&o.status===404)throw new d("Page commands require the for-plane API-key pages extension.",404);throw o});if(typeof s.release!=="string"||!s.release)throw new d("The for-plane runtime has no active extension release.");a={release:s.release,token:JSON.stringify({apiKey:e.config.token.value,readOnly:!i})}}for(let s=0;s<2;s++){let o=new URL(`${e.config.url.value}/live/collaboration`);if(o.protocol=o.protocol==="https:"?"wss:":"ws:",o.searchParams.set("documentType","project_page"),o.searchParams.set("projectId",t),o.searchParams.set("workspaceSlug",e.config.workspace.value),a.release)o.searchParams.set("forPlaneRelease",a.release);let c=new ye(o.href,r,a.token);try{return await c.ready(),c}catch(f){if(c.destroy(),s===0&&f instanceof z){let l=await e.liveCredentials?.(i,!0);if(l){a=l;continue}}throw new d(w(f instanceof Error?f.message:String(f)))}}throw new d("Live session authentication failed after one refresh.")};var Ke=async(e,t=!1)=>{let r=U(e,"file"),n=U(e,"text");if(r!==void 0&&n!==void 0)throw new h("--file and --text are mutually exclusive.");if(r!==void 0)try{return await Je(r,"utf8")}catch{throw new h(`Cannot read Markdown file "${r}".`)}if(n!==void 0||t)return n;throw new h("Expected --file <path> or --text <markdown>.")},xe=(e)=>{if(e.length)console.error(w(`Warning: ${e.join("; ")}`))},J=(e)=>`${e.id} ${e.deleted?"deleted":e.delivery??"created"}${e.stamped!==void 0?`; stamped ${e.stamped} blocks`:""}${e.delivery?"; database persistence is asynchronous":""}`,Et=async(e,t,r,n)=>{let i=R(r.positionals[0],"a project"),a=e==="page create",s=e==="page rm",o=a?F(r,"name"):R(r.positionals[1],"a page UUID or name"),c=r.flags.has("block")?F(r,"block"):void 0,f=r.flags.has("after")?F(r,"after"):void 0,l=X(r,"at-end"),m=U(r,"if-match"),y=X(r,"force"),x=X(r,"allow-loss");if(s&&!X(r,"yes"))throw new h("Deletion requires --yes.");if((m!==void 0||y)&&!c)throw new h("--if-match and --force require --block.");if(m!==void 0&&!/^[a-f0-9]{64}$/i.test(m))throw new h("--if-match expects the SHA-256 fingerprint from page read --json.");if(e==="page read"&&!c)throw new h("Expected --block <anchor>.");if(e==="page insert"&&Boolean(f)===l)throw new h("Choose exactly one of --after <anchor> or --at-end.");let E=a||e==="page set"||e==="page insert"?await Ke(r,a):void 0,A=await $e(t,i),k,I;try{if(E!==void 0)k=await he(t,E),W(k.losses,x);let u=a?await t.request(K(A.id),{method:"POST",body:{name:o,access:0}}):await Ae(t,A.id,o);if(a)I=u;if(a&&!k){P({id:u.id,name:u.name},n,J);return}if(s&&!c){V(u,!0);let b=`${K(A.id)}${u.id}/`;if(!u.archived_at)try{await t.request(`${b}archive/`,{method:"POST"})}catch(g){throw new d(`Archiving page ${u.id} was not confirmed: ${g instanceof Error?g.message:String(g)}. Inspect this UUID before retrying; deletion was not attempted.`)}try{await t.request(b,{method:"DELETE"})}catch(g){throw new d(`Page ${u.id} was archived, but deletion was not confirmed: ${g instanceof Error?g.message:String(g)}. Inspect it by UUID before retrying.`)}P({id:u.id,deleted:!0},n,J);return}let G=e==="page outline"||e==="page read";if(!G)V(u);let M=await ve(t,A.id,u.id,{writable:!G});try{if(e==="page outline")P(me(M.fragment),n,(b)=>b.map((g)=>`${g.index} ${g.shortAnchor??"(no anchor)"} ${g.kind} ${g.preview}`).join(`
2
- `));else if(e==="page read"){let b=ge(M.fragment,R(c,"--block <anchor>"));xe(b.losses),P(b,n,(g)=>g.markdown)}else{let b,g=[];t.markPageMutation?.();let Pe=await M.write((Q)=>{if(e==="page stamp")b=H(Q);else g=we(Q,{kind:s?"rm":e==="page insert"?"insert":"set",block:c,after:f,atEnd:l,ifMatch:m?.toLowerCase(),force:y,allowLoss:x},k)});xe(g),P({id:u.id,...Pe,stamped:b,losses:g},n,J)}}finally{M.destroy()}}catch(u){if(I)throw new d(`Page ${I.id} was created, but its content operation did not complete: ${u instanceof Error?u.message:String(u)}. Inspect this page before retrying; do not create a duplicate.`);throw u}finally{k?.doc.destroy()}};export{Et as runPageContent};
@@ -1 +0,0 @@
1
- import{K as O,L as R,M as b,O as a}from"./cli-ajj9jddd.js";import{ga as u,ia as S}from"./cli-jq1agk1s.js";import{createHash as T,randomUUID as D}from"node:crypto";import{constants as y}from"node:fs";import{chmod as N,lstat as _,mkdir as q,open as k,rename as E,stat as F,unlink as g}from"node:fs/promises";import{join as L}from"node:path";import{setTimeout as j}from"node:timers/promises";var H=20000,x=(e)=>(u(e.sessionId),u(e.csrf),u(P(e)),e),P=(e)=>`session-id=${e.sessionId}; csrftoken=${e.csrf}`,J=(e,i,t)=>L(t,`${T("sha256").update(JSON.stringify([e,i])).digest("hex")}.json`),C=async(e)=>{try{let i=await k(e,y.O_RDONLY|y.O_NOFOLLOW|y.O_NONBLOCK),t;try{let r=await i.stat();if((r.mode&63)!==0||!r.isFile()||r.size>16384)return;t=JSON.parse(await i.readFile("utf8"))}finally{await i.close()}if(t.version!==1||typeof t.userId!=="string"||!t.userId||typeof t.sessionId!=="string"||!t.sessionId||typeof t.csrf!=="string"||!t.csrf||/[;\r\n]/.test(t.sessionId+t.csrf)||typeof t.expiresAt!=="number"||!Number.isFinite(t.expiresAt))return;return x(t),t.expiresAt>Date.now()?t:void 0}catch{return}};class U{config;cachePath;current;flight;constructor(e){if(this.config=e,this.cachePath=J(e.url.value,e.login.value,e.cacheDirectory),u(e.password.value),e.token.value)u(e.token.value)}async raw(e,i={},t=H){let r=`${this.config.url.value}${e}`,o=new AbortController,n;try{let s=await b(r)??fetch,c=new Promise((d,f)=>{n=setTimeout(()=>{o.abort(),f(new a(`Session request timed out after ${t/1000}s: ${e}`))},t)});return await Promise.race([(async()=>{let d=await s(r,{...i,redirect:"manual",signal:o.signal});return{status:d.status,headers:d.headers,text:await d.text()}})(),c])}catch(s){if(s instanceof a)throw s;let c=R(s)?`Connection ${O(r)} denied by the operating system; check sandbox network permissions.`:s instanceof Error?s.message:String(s);throw new a(S(`Session request failed: ${c}`))}finally{if(n!==void 0)clearTimeout(n)}}parse(e,i){if(e.status<200||e.status>=300){let t=e.status===403?" Check page permissions, lock state and CSRF credentials.":"";throw new a(S(`Plane session API answered ${e.status} for ${i}.${t} ${e.text}`).slice(0,450),e.status)}if(!e.text||e.status===204)return;try{return JSON.parse(e.text)}catch{throw new a(`Expected JSON from session API: ${i}`)}}async authenticate(){let e=new Map,i=Date.now()+86400000,t=(w)=>{for(let h of w.getSetCookie()){let[m=""]=h.split(";"),p=m.indexOf("="),I=m.slice(0,p).trim(),l=m.slice(p+1).trim();if(p<1||!["session-id","csrftoken"].includes(I))continue;if(/[;\r\n]/.test(l))throw new a("Invalid session cookie received.");if(l)u(l);e.set(I,l);let A=/(?:^|;)\s*max-age=(-?\d+)/i.exec(h)?.[1];if(A!==void 0)i=Math.min(i,Date.now()+Number(A)*1000)}},r=await this.raw("/auth/get-csrf-token/");t(r.headers);let o=this.parse(r,"/auth/get-csrf-token/").csrf_token??e.get("csrftoken");if(!o)throw new a("Plane did not provide a CSRF token.");u(o);let n=[...e].map(([w,h])=>`${w}=${h}`).join("; ");if(n)u(n);let s=await this.raw("/auth/sign-in/",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Referer:`${this.config.url.value}/`,Cookie:n},body:new URLSearchParams({csrfmiddlewaretoken:o,email:this.config.login.value,password:this.config.password.value}).toString()});t(s.headers);let c=e.get("session-id"),d=e.get("csrftoken");if(![200,302,303].includes(s.status)||!c||!d)throw new a("Plane sign-in failed. Check PLANE_LOGIN and PLANE_PASSWORD; this authentication flow requires password sign-in.",s.status);let f=x({userId:"",sessionId:c,csrf:d,expiresAt:i}),v=this.parse(await this.raw("/api/users/me/",{headers:{Cookie:P(f)}}),"/api/users/me/");if(!v.id)throw new a("Session was not authenticated: no user identifier returned.");return x({...f,userId:v.id})}async session(e=!1){if(!e&&this.current&&this.current.expiresAt>Date.now())return this.current;if(this.flight)return this.flight;let i=this.current;this.flight=(async()=>{let t=await C(this.cachePath);if(t&&(!e||t.sessionId!==i?.sessionId))return t;try{await q(this.config.cacheDirectory,{recursive:!0,mode:448});let s=await _(this.config.cacheDirectory);if(!s.isDirectory()||s.isSymbolicLink())throw Error("Invalid session cache directory");await N(this.config.cacheDirectory,448)}catch{throw new a(`Cannot write session cache in ${this.config.cacheDirectory}. Set PLANE_SESSION_CACHE or --session-cache to a private writable directory.`)}let r=`${this.cachePath}.lock`,o=Date.now(),n;while(!n)try{n=await k(r,"wx",384)}catch(s){if(s.code!=="EEXIST")throw new a("Cannot lock the session cache.");let c=await F(r).catch(()=>{return});if(c&&Date.now()-c.mtimeMs>90000){await g(r).catch(()=>{});continue}if(Date.now()-o>1e4)throw new a("Another command is refreshing the session; retry shortly.");await j(100)}try{let s=await C(this.cachePath);if(s&&(!e||s.sessionId!==i?.sessionId))return s;let c=await this.authenticate(),d=`${this.cachePath}.${D()}.tmp`;try{let f=await k(d,"wx",384);try{await f.writeFile(JSON.stringify({version:1,...c}))}finally{await f.close()}await E(d,this.cachePath)}finally{await g(d).catch(()=>{})}return c}finally{await n.close(),await g(r).catch(()=>{})}})();try{return this.current=await this.flight,this.current}finally{this.flight=void 0}}async request(e,i={}){let t=e.startsWith("/")?e:`/api/workspaces/${encodeURIComponent(this.config.workspace.value)}/${e}`,r=new URLSearchParams;for(let[n,s]of Object.entries(i.query??{}))if(s!==void 0)r.set(n,String(s));let o=r.size?`${t}?${r}`:t;for(let n=0;n<2;n++){let s=await this.session(n===1),c=await this.raw(o,{method:i.method??"GET",headers:{Cookie:P(s),"X-CSRFToken":s.csrf,Referer:`${this.config.url.value}/`,Accept:"application/json",...i.body===void 0?{}:{"Content-Type":"application/json"}},body:i.body===void 0?void 0:JSON.stringify(i.body)},i.timeoutMs);if(c.status===401&&n===0)continue;return this.parse(c,t)}throw new a("Session authentication failed after one refresh.",401)}async listAll(e,i={}){let t=[],r=new Set,o;do{let n=await this.request(e,{...i,query:{...i.query,...o?{cursor:o}:{}}});if(Array.isArray(n))return[...t,...n];if(!n||typeof n!=="object"||!("results"in n)||!Array.isArray(n.results))throw new a(`Unexpected list response from session API: ${e}`);t.push(...n.results);let s=n;if(o=s.next_page_results?s.next_cursor:void 0,o){if(r.has(o))throw new a("Session API repeated a pagination cursor.");r.add(o)}}while(o);return t}}export{U as SessionClient,J as cacheFile,P as cookieHeader};
@@ -1 +0,0 @@
1
- import{a as l}from"./cli-09mmhmq4.js";import{Y as d}from"./cli-q37j0y8m.js";import{ga as f}from"./cli-jq1agk1s.js";import{homedir as p}from"node:os";import{join as a}from"node:path";var u=(o,c)=>{let g=l(o.configPath,["PLANE_LOGIN","PLANE_PASSWORD"]),n=(s)=>{let i=process.env[s];if(i)return{value:i,origin:"env"};let t=g.get(s);return t?{value:t,origin:"file"}:void 0},r=n("PLANE_LOGIN"),e=n("PLANE_PASSWORD");if(e)f(e.value);if(!r||!e)throw new d(`This Plane does not expose the API-key pages endpoint. Set PLANE_LOGIN and PLANE_PASSWORD in the environment or ${o.configPath} to use its session API. If extensions were just installed, retry with --refresh-pages.`);return{...o,login:r,password:e,cacheDirectory:c??process.env.PLANE_SESSION_CACHE??a(process.env.XDG_CACHE_HOME??a(p(),".cache"),"i-plane","sessions")}};export{u as resolveSessionConfig};