@zibby/skills 2.0.25 → 2.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agentMessaging.d.ts +46 -6
- package/dist/agentMessaging.js +59 -29
- package/dist/artifact.d.ts +19 -0
- package/dist/artifact.js +3 -3
- package/dist/codebaseMemory.d.ts +7 -12
- package/dist/codebaseMemory.js +14 -6
- package/dist/git-write.js +9 -9
- package/dist/git.js +2 -2
- package/dist/github.js +5 -5
- package/dist/gitlab.js +5 -5
- package/dist/graphMemory.d.ts +59 -0
- package/dist/graphMemory.js +17 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +242 -186
- package/dist/jira.d.ts +1 -1
- package/dist/jira.js +20 -18
- package/dist/lib/checkout-rules.d.ts +18 -0
- package/dist/lib/checkout-rules.js +1 -0
- package/dist/lib/markup.d.ts +3 -1
- package/dist/lib/markup.js +18 -16
- package/dist/lib/repo-access.d.ts +143 -0
- package/dist/lib/repo-access.js +1 -0
- package/dist/localWorkspace.js +2 -2
- package/dist/package.json +5 -4
- package/dist/personVerification.d.ts +100 -0
- package/dist/personVerification.js +1 -0
- package/dist/report.d.ts +1 -1
- package/dist/trackers/github-adapter.js +5 -5
- package/dist/trackers/index.js +41 -39
- package/dist/trackers/jira-adapter.js +19 -17
- package/dist/triggerAgent.js +1 -1
- package/dist/vikunja.js +21 -19
- package/package.json +5 -4
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
import{existsSync as
|
|
1
|
+
import{existsSync as Le}from"fs";import{dirname as Ce,resolve as Pe}from"path";import{fileURLToPath as qe}from"url";import{resolveIntegrationToken as Ke,clearTokenCache as Be}from"@zibby/core/backend-client.js";var Y=Object.freeze({SENTRY:"sentry",JIRA:"jira",GITHUB:"github",GITLAB:"gitlab",SLACK:"slack",LARK:"lark",LARK_DOCS:"lark_docs",OPENAI_BILLING:"openai_billing",ANTHROPIC_BILLING:"anthropic_billing",CURSOR_ADMIN:"cursor_admin",NOTION:"notion",GOOGLE:"google",PLANE:"plane",LINEAR:"linear",VIKUNJA:"vikunja",FIGMA:"figma",HUBSPOT:"hubspot",OPEN_DESIGN:"open_design",LINKEDIN_PERSONAL:"linkedin_personal",LINKEDIN_BUSINESS:"linkedin_business",DISCORD:"discord"}),Xe=Object.freeze({sentry:{id:"sentry",name:"Sentry",connectPath:"/integrations?provider=sentry"},jira:{id:"jira",name:"Jira",connectPath:"/integrations?provider=jira"},github:{id:"github",name:"GitHub",connectPath:"/integrations?provider=github"},gitlab:{id:"gitlab",name:"GitLab",connectPath:"/integrations?provider=gitlab"},slack:{id:"slack",name:"Slack",connectPath:"/integrations?provider=slack"},lark:{id:"lark",name:"Lark Chat",connectPath:"/integrations?provider=lark"},lark_docs:{id:"lark_docs",name:"Lark App",connectPath:"/integrations?provider=lark_docs"},openai_billing:{id:"openai_billing",name:"OpenAI Admin",connectPath:"/integrations?provider=openai_billing"},anthropic_billing:{id:"anthropic_billing",name:"Anthropic Admin",connectPath:"/integrations?provider=anthropic_billing"},cursor_admin:{id:"cursor_admin",name:"Cursor Admin",connectPath:"/integrations?provider=cursor_admin"},notion:{id:"notion",name:"Notion",connectPath:"/integrations?provider=notion"},google:{id:"google",name:"Google Docs",connectPath:"/integrations?provider=google"},plane:{id:"plane",name:"Plane",connectPath:"/integrations?provider=plane"},linear:{id:"linear",name:"Linear",connectPath:"/integrations?provider=linear"},vikunja:{id:"vikunja",name:"Vikunja",connectPath:"/integrations?provider=vikunja"},figma:{id:"figma",name:"Figma",connectPath:"/integrations?provider=figma"},hubspot:{id:"hubspot",name:"HubSpot",connectPath:"/integrations?provider=hubspot"},open_design:{id:"open_design",name:"OpenDesign",connectPath:"/integrations?provider=open_design"},linkedin_personal:{id:"linkedin_personal",name:"LinkedIn (Personal)",connectPath:"/integrations?provider=linkedin_personal"},linkedin_business:{id:"linkedin_business",name:"LinkedIn (Business)",connectPath:"/integrations?provider=linkedin_business"},discord:{id:"discord",name:"Discord",connectPath:"/integrations?provider=discord"}});var E={api:{knob:"SKILL_API_TIMEOUT_MS",fallback:3e4},transfer:{knob:"SKILL_TRANSFER_TIMEOUT_MS",fallback:12e4},job:{knob:"SKILL_JOB_TIMEOUT_MS",fallback:3e5}};function de(s,n,t=process.env){let e=Number(t?.[s]);return Number.isFinite(e)&&e>0?Math.min(6e5,Math.max(1e3,Math.floor(e))):n}function fe(s="api",n=process.env){let t=E[s]||E.api;return de(t.knob,t.fallback,n)}function P(s){return s?.name==="TimeoutError"||s?.name==="AbortError"}function me(s){try{return new URL(String(s?.url??s)).host||"unknown host"}catch{return"unknown host"}}function ge(s,n){if(!s)return n;let t=new AbortController,e=a=>{t.signal.aborted||t.abort(a)},i=()=>e(s.reason),r=()=>e(n.reason);return t.signal.addEventListener("abort",()=>{s.removeEventListener("abort",i),n.removeEventListener("abort",r)},{once:!0}),s.aborted?e(s.reason):n.aborted?e(n.reason):(s.addEventListener("abort",i,{once:!0}),n.addEventListener("abort",r,{once:!0})),t.signal}async function Q(s,n={},t={}){let e=t.kind||"api",i=(E[e]||E.api).knob,r=t.timeoutMs?Math.min(6e5,Math.max(1e3,Math.floor(t.timeoutMs))):fe(e),a=n?.signal;if(a?.aborted)throw a.reason??new DOMException("This operation was aborted","AbortError");let o=AbortSignal.timeout(r),c=ge(a,o);try{return await fetch(s,{...n,signal:c})}catch(l){throw o.aborted&&P(l)?new Error(`${t.what||"request"} TIMED OUT after ${r}ms against ${me(s)} (${i})`):l}}var he={NOTE:"info",TIP:"success",IMPORTANT:"note",WARNING:"warning",CAUTION:"error"},ie={info:"NOTE",success:"TIP",note:"IMPORTANT",warning:"WARNING",error:"CAUTION"},ye={info:{bg:"rgba(88, 140, 245, 0.16)",rgb:[88,140,245],icon:"\u2139\uFE0F"},note:{bg:"rgba(160, 120, 240, 0.16)",rgb:[160,120,240],icon:"\u{1F4DD}"},warning:{bg:"rgba(236, 170, 60, 0.15)",rgb:[236,170,60],icon:"\u26A0\uFE0F"},success:{bg:"rgba(70, 190, 125, 0.16)",rgb:[70,190,125],icon:"\u2705"},error:{bg:"rgba(235, 90, 80, 0.15)",rgb:[235,90,80],icon:"\u26D4"}},et=Object.keys(ye),ke=2e5,oe=6,be=/^```([A-Za-z0-9_+.-]{0,32})\s*$/,_e=/^(#{1,6})[ \t]+(.*?)\s*$/,Ie=/^(?:-{3,}|\*{3,}|_{3,})\s*$/,X=/^>(?: ?(.*))?$/,q=/^[-*][ \t]+\[([ xX])\][ \t]+(.*)$/,Z=/^[-*][ \t]+(.*)$/,V=/^(\d{1,3})[.)][ \t]+(.*)$/,ee=/^\|.*\|\s*$/,je=/^\|?\s*:?-{1,}:?\s*(?:\|\s*:?-{1,}:?\s*)*\|?\s*$/,ve=/^\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\s*$/i;function te(s){let n=s.trim().replace(/^\|/,"").replace(/\|$/,""),t=[],e="";for(let i=0;i<n.length;i++){let r=n[i];if(r==="\\"&&n[i+1]==="|"){e+="|",i++;continue}if(r==="|"){t.push(e.trim()),e="";continue}e+=r}return t.push(e.trim()),t}function ae(s){let t=String(s??"").slice(0,ke).replace(/\r\n?/g,`
|
|
2
2
|
`).split(`
|
|
3
|
-
`);return
|
|
4
|
-
`)});continue}if(
|
|
5
|
-
`).
|
|
6
|
-
|
|
7
|
-
`;break;case"
|
|
8
|
-
|
|
9
|
-
`;break;case"
|
|
10
|
-
|
|
3
|
+
`);return B(t,0)}function B(s,n){let t=[],e=0;for(;e<s.length;){let i=s[e];if(i.trim()===""){e++;continue}if(/^[ \t]/.test(i)){t.push({t:"paragraph",c:b(i)}),e++;continue}let r;if(r=be.exec(i)){let a=r[1]||"",o=[];for(e++;e<s.length&&!/^```\s*$/.test(s[e]);)o.push(s[e]),e++;e++,t.push({t:"code",lang:a,v:o.join(`
|
|
4
|
+
`)});continue}if(Ie.test(i)){t.push({t:"rule"}),e++;continue}if(r=_e.exec(i)){let a=Math.min(oe,r[1].length);t.push({t:"heading",level:a,c:b(r[2])}),e++;continue}if(X.test(i)&&n<3){let a=[];for(;e<s.length&&(r=X.exec(s[e]));)a.push(r[1]??""),e++;let o=a.findIndex(l=>l.trim()!==""),c=o>=0?ve.exec(a[o].trim()):null;if(c){let l=he[c[1].toUpperCase()];t.push({t:"panel",kind:l,c:B(a.slice(o+1),n+1)})}else t.push({t:"quote",c:B(a,n+1)});continue}if(q.test(i)){let a=[];for(;e<s.length&&(r=q.exec(s[e]));)a.push({checked:r[1]!==" ",c:b(r[2])}),e++;t.push({t:"task",items:a});continue}if(Z.test(i)){let a=[];for(;e<s.length&&!q.test(s[e])&&(r=Z.exec(s[e]));)a.push([{t:"paragraph",c:b(r[1])}]),e++;t.push({t:"bullet",items:a});continue}if(r=V.exec(i)){let a=Math.max(1,parseInt(r[1],10)||1),o=[];for(;e<s.length&&(r=V.exec(s[e]));)o.push([{t:"paragraph",c:b(r[2])}]),e++;t.push({t:"ordered",start:a,items:o});continue}if(ee.test(i)&&e+1<s.length&&je.test(s[e+1])){let a=te(i).map(b);e+=2;let o=[];for(;e<s.length&&ee.test(s[e]);)o.push(te(s[e]).map(b)),e++;t.push({t:"table",header:a,rows:o});continue}t.push({t:"paragraph",c:b(i)}),e++}return t}var we=/^https?:\/\/[^\s<>()[\]]+/,Se=/^\[([^\]\n]{1,300})\]\((https?:\/\/[^\s)]{1,2000})\)/,Te=/[.,;:!?'"]+$/;function Ae(s,n){return n<=0?!0:/[\s([{"'“‘>:—–-]/.test(s[n-1])}function xe(s,n){return n>=s.length?!0:/[\s)\]}"'”’.,;:!?—–-]/.test(s[n])}function Ne(s,n,t){let e=n;for(;e<s.length;){let i=s.indexOf(t,e);if(i<0)return-1;let r=s[i-1],a=s[i+t.length],o=t.length===1&&(r===t||a===t);if(i>n&&r&&!/\s/.test(r)&&!o&&xe(s,i+t.length))return i;e=i+1}return-1}function b(s){let n=String(s??""),t=[],e="",i=()=>{e&&(t.push({t:"text",v:e}),e="")},r=0;for(;r<n.length;){let a=n[r];if(a==="`"){let o=1;for(;n[r+o]==="`";)o++;let c="`".repeat(o),l=n.indexOf(c,r+o);if(l>r+o-1&&l!==-1){let u=n.slice(r+o,l);if(u.trim()){i(),t.push({t:"code",v:u.length>1&&u.startsWith(" ")&&u.endsWith(" ")?u.slice(1,-1):u}),r=l+o;continue}}e+=c,r+=o;continue}if(a==="["){let o=Se.exec(n.slice(r));if(o){i(),t.push({t:"link",href:o[2],c:b(o[1])}),r+=o[0].length;continue}}if((a==="*"||a==="_"||a==="~")&&Ae(n,r)){let o=n[r+1]===a;if(a==="~"&&!o){e+=a,r++;continue}let c=o?a+a:a,l=r+c.length;if(l<n.length&&!/\s/.test(n[l])){let u=Ne(n,l,c);if(u>l){i();let d=b(n.slice(l,u));t.push(a==="~"?{t:"strike",c:d}:o?{t:"strong",c:d}:{t:"em",c:d}),r=u+c.length;continue}}}if(a==="h"&&(r===0||/[\s(<]/.test(n[r-1]))){let o=we.exec(n.slice(r));if(o){let c=o[0],l=Te.exec(c);if(l&&(c=c.slice(0,-l[0].length)),c.length>8){i(),t.push({t:"link",href:c,c:[{t:"text",v:c}]}),r+=c.length;continue}}}e+=a,r++}return i(),t}function T(s,n=[]){let t=[];for(let e of s)switch(e.t){case"text":e.v&&t.push({type:"text",text:e.v,...n.length?{marks:n}:{}});break;case"br":t.push({type:"hardBreak"});break;case"code":t.push({type:"text",text:e.v,marks:[{type:"code"},...n.filter(i=>i.type==="link")]});break;case"strong":t.push(...T(e.c,R(n,{type:"strong"})));break;case"em":t.push(...T(e.c,R(n,{type:"em"})));break;case"strike":t.push(...T(e.c,R(n,{type:"strike"})));break;case"link":t.push(...T(e.c,R(n,{type:"link",attrs:{href:e.href}})));break}return t}function R(s,n){return s.some(t=>t.type===n.type)?s:[...s,n]}var K=0;function ne(){return K=(K+1)%1e6,`m${Date.now().toString(36)}-${K}`}var x=s=>{let n=T(s);return n.length?{type:"paragraph",content:n}:{type:"paragraph"}};function S(s,n){let t=[];for(let e of s)switch(e.t){case"paragraph":t.push(x(e.c));break;case"heading":if(n==="quote"||n==="item")t.push(x([{t:"strong",c:e.c}]));else{let i=T(e.c);i.length&&t.push({type:"heading",attrs:{level:e.level},content:i})}break;case"bullet":t.push({type:"bulletList",content:e.items.map(i=>({type:"listItem",content:L(S(i,"item"))}))});break;case"ordered":t.push({type:"orderedList",attrs:{order:e.start},content:e.items.map(i=>({type:"listItem",content:L(S(i,"item"))}))});break;case"task":n==="quote"||n==="item"?t.push({type:"bulletList",content:e.items.map(i=>({type:"listItem",content:[x([{t:"text",v:i.checked?"\u2611 ":"\u2610 "},...i.c])]}))}):t.push({type:"taskList",attrs:{localId:ne()},content:e.items.map(i=>({type:"taskItem",attrs:{localId:ne(),state:i.checked?"DONE":"TODO"},content:Oe(T(i.c))}))});break;case"code":t.push({type:"codeBlock",attrs:e.lang?{language:e.lang}:{},...e.v?{content:[{type:"text",text:e.v}]}:{}});break;case"quote":n==="quote"||n==="item"?t.push(...S(e.c,n)):n==="panel"?t.push(...se(e).map(i=>({type:"paragraph",content:[{type:"text",text:i}]}))):t.push({type:"blockquote",content:L(S(e.c,"quote"))});break;case"panel":n==="panel"?t.push(...se(e).map(i=>({type:"paragraph",content:[{type:"text",text:i}]}))):n!=="doc"?t.push(...S(e.c,n)):t.push({type:"panel",attrs:{panelType:e.kind},content:L(S(e.c,"panel"))});break;case"rule":if(n==="quote"||n==="item")break;t.push({type:"rule"});break;case"table":{if(n!=="doc"){for(let r of[...e.header?[e.header]:[],...e.rows])t.push(x($e(r)));break}let i=[];e.header&&i.push({type:"tableRow",content:e.header.map(r=>({type:"tableHeader",attrs:{},content:[x(r)]}))});for(let r of e.rows)i.push({type:"tableRow",content:r.map(a=>({type:"tableCell",attrs:{},content:[x(a)]}))});i.length&&t.push({type:"table",attrs:{isNumberColumnEnabled:!1,layout:"default"},content:i});break}}return t}function L(s){return s.length?s:[{type:"paragraph"}]}function se(s){return A([s]).replace(/\n$/,"").split(`
|
|
5
|
+
`).filter(n=>n!=="")}function Oe(s){return s.length?s:[{type:"text",text:" "}]}function $e(s){let n=[];return s.forEach((t,e)=>{e&&n.push({t:"text",v:" \xB7 "}),n.push(...t)}),n}function M(s){return{type:"doc",version:1,content:String(s??"").split(`
|
|
6
|
+
`).map(n=>({type:"paragraph",...n?{content:[{type:"text",text:n}]}:{}}))}}function ce(s){try{let n=S(ae(s),"doc");return{type:"doc",version:1,content:n.length?n:[{type:"paragraph"}]}}catch{return M(s)}}function v(s){let n="";for(let t of s)switch(t.t){case"text":n+=t.v;break;case"br":n+=`
|
|
7
|
+
`;break;case"code":n+=`\`${t.v}\``;break;case"strong":n+=`**${v(t.c)}**`;break;case"em":n+=`_${v(t.c)}_`;break;case"strike":n+=`~~${v(t.c)}~~`;break;case"link":{let e=v(t.c);n+=!e||e===t.href?t.href:`[${e}](${t.href})`;break}}return n}function A(s){let n="",t=!1;for(let e of s){let i=e.t==="quote"||e.t==="panel";switch(i&&t&&(n+=`
|
|
8
|
+
`),t=i,e.t){case"paragraph":n+=`${v(e.c)}
|
|
9
|
+
`;break;case"heading":n+=`${"#".repeat(Math.max(1,Math.min(oe,e.level)))} ${v(e.c)}
|
|
10
|
+
`;break;case"bullet":for(let r of e.items)n+=`- ${A(r).trim()}
|
|
11
|
+
`;break;case"ordered":e.items.forEach((r,a)=>{n+=`${e.start+a}. ${A(r).trim()}
|
|
12
|
+
`});break;case"task":for(let r of e.items)n+=`- [${r.checked?"x":" "}] ${v(r.c)}
|
|
11
13
|
`;break;case"code":n+=`\`\`\`${e.lang}
|
|
12
14
|
${e.v}
|
|
13
15
|
\`\`\`
|
|
14
|
-
`;break;case"quote":n+=
|
|
15
|
-
${
|
|
16
|
-
`;break;case"table":{let
|
|
17
|
-
`;e.header&&(n+=
|
|
18
|
-
`);for(let
|
|
16
|
+
`;break;case"quote":n+=re(A(e.c));break;case"panel":n+=`> [!${ie[e.kind]}]
|
|
17
|
+
${re(A(e.c))}`;break;case"rule":n+=`---
|
|
18
|
+
`;break;case"table":{let r=a=>`| ${a.map(o=>v(o).replace(/\|/g,"\\|")).join(" | ")} |
|
|
19
|
+
`;e.header&&(n+=r(e.header)+`|${e.header.map(()=>" --- |").join("")}
|
|
20
|
+
`);for(let a of e.rows)n+=r(a);break}}}return n}function Ee(s){return s.replace(/^\n+/,"").replace(/\s+$/,"")}function re(s){return s.replace(/\n$/,"").split(`
|
|
19
21
|
`).map(n=>n?`> ${n}`:">").join(`
|
|
20
22
|
`)+`
|
|
21
|
-
`}function x(s){let n=[];for(let e of s||[])if(!(!e||typeof e!="object"))switch(e.type){case"text":{let t={t:"text",v:String(e.text??"")},i=Array.isArray(e.marks)?e.marks:[];i.some(r=>r?.type==="code")&&(t={t:"code",v:String(e.text??"")});for(let r of i)!r||r.type==="code"||(r.type==="strong"?t={t:"strong",c:[t]}:r.type==="em"?t={t:"em",c:[t]}:r.type==="strike"?t={t:"strike",c:[t]}:r.type==="link"&&r.attrs?.href&&(t={t:"link",href:String(r.attrs.href),c:[t]}));n.push(t);break}case"hardBreak":n.push({t:"br"});break;case"mention":n.push({t:"text",v:String(e.attrs?.text||(e.attrs?.id?`@${e.attrs.id}`:"@someone"))});break;case"emoji":n.push({t:"text",v:String(e.attrs?.text||e.attrs?.shortName||"")});break;case"status":n.push({t:"text",v:String(e.attrs?.text||"")});break;case"date":n.push({t:"text",v:e.attrs?.timestamp?new Date(Number(e.attrs.timestamp)).toISOString().slice(0,10):""});break;case"inlineCard":{let t=String(e.attrs?.url||"");t&&n.push({t:"link",href:t,c:[{t:"text",v:t}]});break}default:Array.isArray(e.content)?n.push(...x(e.content)):typeof e.text=="string"&&n.push({t:"text",v:e.text})}return n}function _(s){let n=[];for(let e of s||[])if(!(!e||typeof e!="object"))switch(e.type){case"paragraph":n.push({t:"paragraph",c:x(e.content)});break;case"heading":n.push({t:"heading",level:Number(e.attrs?.level)||1,c:x(e.content)});break;case"bulletList":n.push({t:"bullet",items:(e.content||[]).map(t=>_(t?.content))});break;case"orderedList":n.push({t:"ordered",start:Number(e.attrs?.order)||1,items:(e.content||[]).map(t=>_(t?.content))});break;case"taskList":n.push({t:"task",items:(e.content||[]).map(t=>({checked:t?.attrs?.state==="DONE",c:x(t?.content)}))});break;case"decisionList":n.push({t:"bullet",items:(e.content||[]).map(t=>[{t:"paragraph",c:x(t?.content)}])});break;case"codeBlock":n.push({t:"code",lang:String(e.attrs?.language||""),v:(e.content||[]).map(t=>String(t?.text??"")).join("")});break;case"blockquote":n.push({t:"quote",c:_(e.content)});break;case"panel":{let t=String(e.attrs?.panelType||"info");n.push({t:"panel",kind:t in re?t:"info",c:_(e.content)});break}case"rule":n.push({t:"rule"});break;case"table":{let t=(e.content||[]).filter(o=>o?.type==="tableRow"),i=o=>(o.content||[]).map(c=>{let l=_(c?.content);return b(N(l).trim().replace(/\n+/g," "))}),r=o=>(o.content||[]).length>0&&(o.content||[]).every(c=>c?.type==="tableHeader"),a=t.length&&r(t[0])?i(t[0]):null;n.push({t:"table",header:a,rows:t.slice(a?1:0).map(i)});break}case"mediaSingle":case"mediaGroup":case"media":case"mediaInline":n.push({t:"paragraph",c:[{t:"text",v:"[attachment]"}]});break;case"expand":case"nestedExpand":{let t=String(e.attrs?.title||"").trim();t&&n.push({t:"paragraph",c:[{t:"strong",c:[{t:"text",v:t}]}]}),n.push(..._(e.content));break}default:{let t=Array.isArray(e.content)?e.content:[];t.some(i=>i?.type==="text"||i?.type==="hardBreak")?n.push({t:"paragraph",c:x(t)}):t.length?n.push(..._(t)):typeof e.text=="string"&&e.text&&n.push({t:"paragraph",c:[{t:"text",v:e.text}]})}}return n}function $e(s){try{if(Array.isArray(s))return _(s);if(s&&typeof s=="object"){let n=s;return n.type==="doc"||!n.type&&Array.isArray(n.content)?_(n.content):_([n])}if(typeof s=="string")return oe(s)}catch{}return[]}function J(s){try{return Oe(N($e(s)))}catch{return""}}function Ke(){if(process.env.MCP_SKILL_PATH)return process.env.MCP_SKILL_PATH;let s=Re(Ce(import.meta.url)),n=Le(s,"..","bin","mcp-skill.mjs");return Ee(n)?n:null}function Me(s){return ae(s)}async function U(s,n){try{return await s(Me(n))}catch(e){let t=Number(e?.status);if(!(t>=400&&t<500))throw e;return console.warn(`[jira] rich body rejected (${t}) \u2014 retrying as plain text: ${String(e?.message||e).slice(0,200)}`),await s(B(n))}}function O(s){return String(s||"").toLowerCase().replace(/\s+/g,"").replace(/[()\-_::"'`]/g,"")}function D(s){return O(s).replace(/[a-z0-9]+/g,"")}function C(s,n){let e=O(s),t=O(n);if(!e||!t)return 0;if(e===t)return 1;if(e.length===1||t.length===1)return e===t?1:0;let i=u=>{let d=new Map;for(let f=0;f<u.length-1;f++){let y=u.slice(f,f+2);d.set(y,(d.get(y)||0)+1)}return d},r=i(e),a=i(t),o=0,c=0,l=0;for(let u of r.values())c+=u;for(let u of a.values())l+=u;for(let[u,d]of r.entries()){let f=a.get(u)||0;o+=Math.min(d,f)}return 2*o/Math.max(1,c+l)}function w(s){return String(s||"").toLowerCase().replace(/\s+/g,"").replace(/[()\-_::"'`]/g,"")}function Be(s,n=[]){let e=Array.isArray(n)?n:[];if(e.length===0)return{requested:s||null,resolved:null,strategy:"none"};let t=e.filter(o=>!o.subtask),i=t.length>0?t:e,r=w(s);if(r){let o=i.find(u=>w(u.name)===r);if(o)return{requested:s,resolved:o,strategy:"exact"};let c={task:["task","\u4EFB\u52A1","\u4E8B\u9879","to do","todo"],story:["story","\u7528\u6237\u6545\u4E8B","\u9700\u6C42"],bug:["bug","\u7F3A\u9677","\u95EE\u9898"],improvement:["improvement","\u4F18\u5316","\u6539\u8FDB"],epic:["epic","\u53F2\u8BD7"]};for(let u of Object.values(c)){if(!u.some(f=>w(f)===r))continue;let d=i.find(f=>u.some(y=>w(y)===w(f.name)));if(d)return{requested:s,resolved:d,strategy:"alias"}}let l=i.map(u=>({t:u,score:C(s,u.name)})).sort((u,d)=>d.score-u.score);if(l[0]&&l[0].score>=.5)return{requested:s,resolved:l[0].t,strategy:"fuzzy"}}let a=["task","story","bug","improvement","epic"];for(let o of a){let c=i.find(l=>w(l.name)===o);if(c)return{requested:s||null,resolved:c,strategy:"default-preferred"}}return{requested:s||null,resolved:i[0],strategy:"default-first"}}async function ce(s){let n=`projectKeys=${encodeURIComponent(s)}&expand=projects.issuetypes`,e=await m(`/rest/api/3/issue/createmeta?${n}`),t=Array.isArray(e?.projects)?e.projects:[],r=t.find(o=>String(o?.key||"").toUpperCase()===String(s||"").toUpperCase())||t[0]||null;return(Array.isArray(r?.issuetypes)?r.issuetypes:[]).map(o=>({id:o.id,name:o.name,subtask:!!o.subtask,description:o.description||null}))}async function le(s,n){if(!s)throw new Error("projectKey is required");let e="sprint is not EMPTY";n==="active"?e="sprint in openSprints()":n==="closed"?e="sprint in closedSprints()":n==="future"&&(e="sprint in futureSprints()");let t=`project = ${s} AND ${e} ORDER BY updated DESC`,i=`jql=${encodeURIComponent(t)}&maxResults=100&fields=customfield_10020`,r=await m(`/rest/api/3/search/jql?${i}`),a=new Map;for(let o of r.issues||[])for(let c of o.fields?.customfield_10020||[])c&&!a.has(c.id)&&a.set(c.id,{id:c.id,name:c.name,state:c.state,boardId:c.boardId||null,startDate:c.startDate||null,endDate:c.endDate||null,goal:c.goal||null});return[...a.values()].sort((o,c)=>{let l={active:0,future:1,closed:2},u=(l[o.state]??3)-(l[c.state]??3);return u!==0?u:String(c.startDate||"").localeCompare(String(o.startDate||""))})}function Je(s,{sprintId:n,sprintName:e,target:t}={}){let i=Array.isArray(s)?s:[];if(!i.length)return{sprint:null,selectedBy:"none"};if(n!=null&&String(n).trim()!=="")return{sprint:i.find(o=>String(o.id)===String(n))||null,selectedBy:"id"};if(e&&String(e).trim()){let a=String(e).trim(),o=i.find(l=>String(l.name||"").toLowerCase()===a.toLowerCase());if(o)return{sprint:o,selectedBy:"name-exact"};let c=i.map(l=>({s:l,score:C(a,l.name||"")})).sort((l,u)=>u.score-l.score);return c[0]&&c[0].score>=.5?{sprint:c[0].s,selectedBy:"name-fuzzy"}:{sprint:null,selectedBy:"name-none"}}let r=String(t||"current").trim().toLowerCase();return r==="active"||r==="current"||r==="latest"?{sprint:i[0],selectedBy:r}:{sprint:i[0],selectedBy:"default"}}function Ue(s,n){let e=s?.fields?.customfield_10020;return Array.isArray(e)?e.some(t=>String(t?.id)===String(n)):!1}async function De({issueKey:s,projectKey:n,sprintId:e,attempts:t=3,delayMs:i=450}){let r=[];for(let a=0;a<t;a++){try{let o=`project = ${n} AND key = ${s} AND sprint = ${e}`,c=`jql=${encodeURIComponent(o)}&maxResults=1&fields=key,status`,l=await m(`/rest/api/3/search/jql?${c}`);if(Number(l?.total||0)>0)return r.push({attempt:a+1,jql:!0,issueField:null}),{ok:!0,method:"jql",traces:r};let d=await m(`/rest/api/3/issue/${s}?fields=customfield_10020,status`),f=Ue(d,e);if(r.push({attempt:a+1,jql:!1,issueField:f}),f)return{ok:!0,method:"issue_field",traces:r}}catch(o){r.push({attempt:a+1,error:String(o?.message||o)})}a<t-1&&await new Promise(o=>setTimeout(o,i))}return{ok:!1,method:"none",traces:r}}async function G({issueKey:s,projectKey:n,sprintId:e,sprintName:t,target:i}){if(!s)return{ok:!1,error:"issueKey is required"};let r=n;if(!r&&(r=(await m(`/rest/api/3/issue/${s}?fields=project`))?.fields?.project?.key||null,!r))return{ok:!1,error:`Could not resolve project for ${s}`};let a=await le(r,"active");if(!a.length)return{ok:!1,error:`No assignable active sprint found for project ${r}`};let{sprint:o,selectedBy:c}=Je(a,{sprintId:e,sprintName:t,target:i});if(!o)return{ok:!1,error:`No matching sprint found in ${r}`,requested:{sprintId:e??null,sprintName:t??null,target:i??"current"},availableSprints:a.map(d=>({id:d.id,name:d.name,state:d.state}))};await m(`/rest/api/3/issue/${s}`,{method:"PUT",body:{fields:{customfield_10020:Number(o.id)}}});let l=await De({issueKey:s,projectKey:r,sprintId:o.id}),u=l.ok;return{ok:u,issueKey:s,projectKey:r,sprintId:o.id,sprintName:o.name,selectedBy:c,verifiedBy:l.method,verified:u,verificationTrace:l.traces,warning:u?null:`Sprint assignment attempted but verification did not find ${s} in sprint ${o.id}`}}async function Ge(){let s=process.env.JIRA_API_TOKEN,n=process.env.JIRA_EMAIL,e=process.env.JIRA_BASE_URL;if(s&&n&&e)return{authType:"token",apiToken:s,email:n,baseUrl:e};let t=await Pe("jira");return(t?.authType?t.authType!=="token":!!t?.cloudId)?{authType:"oauth",accessToken:t.token,cloudId:t.cloudId}:{authType:"token",apiToken:t?.token,email:n||t?.email||"",baseUrl:e||t?.baseUrl||t?.instanceUrl||process.env.ATLASSIAN_INSTANCE_URL||""}}function Fe(s,n,e={}){let t=s||{},i={Accept:"application/json",...e.body?{"Content-Type":"application/json"}:{},...e.headers};if(t.authType==="token"){let r=String(t.baseUrl||t.instanceUrl||"").trim().replace(/\/+$/,""),a=t.apiToken||t.accessToken||"";if(!r)throw new Error("Jira token connection has no base URL \u2014 reconnect Jira with its instance URL, or set JIRA_BASE_URL.");if(!t.email)throw new Error("Jira token connection has no account email \u2014 reconnect Jira with the account email, or set JIRA_EMAIL.");if(!a)throw new Error("Jira token connection has no API token \u2014 reconnect Jira, or set JIRA_API_TOKEN.");return{url:`${r}${n}`,headers:{Authorization:"Basic "+Buffer.from(`${t.email}:${a}`).toString("base64"),...i}}}if(typeof t.accessToken!="string"||!t.accessToken)throw new Error(`Invalid jira token type: ${typeof t.accessToken}`);if(!t.cloudId)throw new Error("Invalid jira cloudId: missing");return{url:`https://api.atlassian.com/ex/jira/${t.cloudId}${n}`,headers:{Authorization:`Bearer ${t.accessToken}`,...i}}}async function m(s,n={}){let e=async()=>{let t=await Ge(),{url:i,headers:r}=Fe(t,s,n),a=await Q(i,{method:n.method||"GET",headers:r,body:n.body?JSON.stringify(n.body):void 0,signal:n.signal},{kind:/\/search\b/.test(String(s))?"job":"api",what:`Jira ${n.method||"GET"} ${s}`}),o=()=>a.text().catch(l=>{if(P(l)||n.signal?.aborted)throw l;return""});if(!a.ok){let l=await o(),u=new Error(`Jira API ${a.status}: ${l.slice(0,300)}`);throw u.status=a.status,u}let c=await o();if(!c||!c.trim())return{};try{return JSON.parse(c)}catch{return{raw:c}}};try{return await e()}catch(t){if(n.signal?.aborted)throw t;let i=String(t?.message||t||"").toLowerCase();if(!(i.includes("token")||i.includes("401")||i.includes("403")||i.includes("substring")))throw t;return qe("jira"),e()}}var $={id:"jira",callsBackend:!0,serverName:"jira",allowedTools:["mcp__jira__*"],requiresIntegration:Y.JIRA,envKeys:["ATLASSIAN_ACCESS_TOKEN","ATLASSIAN_CLOUD_ID"],description:"Zibby Jira MCP Server (OAuth Bearer)",promptFragment:`## Jira
|
|
23
|
+
`}function N(s){let n=[];for(let t of s||[])if(!(!t||typeof t!="object"))switch(t.type){case"text":{let e={t:"text",v:String(t.text??"")},i=Array.isArray(t.marks)?t.marks:[];i.some(r=>r?.type==="code")&&(e={t:"code",v:String(t.text??"")});for(let r of i)!r||r.type==="code"||(r.type==="strong"?e={t:"strong",c:[e]}:r.type==="em"?e={t:"em",c:[e]}:r.type==="strike"?e={t:"strike",c:[e]}:r.type==="link"&&r.attrs?.href&&(e={t:"link",href:String(r.attrs.href),c:[e]}));n.push(e);break}case"hardBreak":n.push({t:"br"});break;case"mention":n.push({t:"text",v:String(t.attrs?.text||(t.attrs?.id?`@${t.attrs.id}`:"@someone"))});break;case"emoji":n.push({t:"text",v:String(t.attrs?.text||t.attrs?.shortName||"")});break;case"status":n.push({t:"text",v:String(t.attrs?.text||"")});break;case"date":n.push({t:"text",v:t.attrs?.timestamp?new Date(Number(t.attrs.timestamp)).toISOString().slice(0,10):""});break;case"inlineCard":{let e=String(t.attrs?.url||"");e&&n.push({t:"link",href:e,c:[{t:"text",v:e}]});break}default:Array.isArray(t.content)?n.push(...N(t.content)):typeof t.text=="string"&&n.push({t:"text",v:t.text})}return n}function _(s){let n=[];for(let t of s||[])if(!(!t||typeof t!="object"))switch(t.type){case"paragraph":n.push({t:"paragraph",c:N(t.content)});break;case"heading":n.push({t:"heading",level:Number(t.attrs?.level)||1,c:N(t.content)});break;case"bulletList":n.push({t:"bullet",items:(t.content||[]).map(e=>_(e?.content))});break;case"orderedList":n.push({t:"ordered",start:Number(t.attrs?.order)||1,items:(t.content||[]).map(e=>_(e?.content))});break;case"taskList":n.push({t:"task",items:(t.content||[]).map(e=>({checked:e?.attrs?.state==="DONE",c:N(e?.content)}))});break;case"decisionList":n.push({t:"bullet",items:(t.content||[]).map(e=>[{t:"paragraph",c:N(e?.content)}])});break;case"codeBlock":n.push({t:"code",lang:String(t.attrs?.language||""),v:(t.content||[]).map(e=>String(e?.text??"")).join("")});break;case"blockquote":n.push({t:"quote",c:_(t.content)});break;case"panel":{let e=String(t.attrs?.panelType||"info");n.push({t:"panel",kind:e in ie?e:"info",c:_(t.content)});break}case"rule":n.push({t:"rule"});break;case"table":{let e=(t.content||[]).filter(o=>o?.type==="tableRow"),i=o=>(o.content||[]).map(c=>{let l=_(c?.content);return b(A(l).trim().replace(/\n+/g," "))}),r=o=>(o.content||[]).length>0&&(o.content||[]).every(c=>c?.type==="tableHeader"),a=e.length&&r(e[0])?i(e[0]):null;n.push({t:"table",header:a,rows:e.slice(a?1:0).map(i)});break}case"mediaSingle":case"mediaGroup":case"media":case"mediaInline":n.push({t:"paragraph",c:[{t:"text",v:"[attachment]"}]});break;case"expand":case"nestedExpand":{let e=String(t.attrs?.title||"").trim();e&&n.push({t:"paragraph",c:[{t:"strong",c:[{t:"text",v:e}]}]}),n.push(..._(t.content));break}default:{let e=Array.isArray(t.content)?t.content:[];e.some(i=>i?.type==="text"||i?.type==="hardBreak")?n.push({t:"paragraph",c:N(e)}):e.length?n.push(..._(e)):typeof t.text=="string"&&t.text&&n.push({t:"paragraph",c:[{t:"text",v:t.text}]})}}return n}function Re(s){try{if(Array.isArray(s))return _(s);if(s&&typeof s=="object"){let n=s;return n.type==="doc"||!n.type&&Array.isArray(n.content)?_(n.content):_([n])}if(typeof s=="string")return ae(s)}catch{}return[]}function J(s){try{return Ee(A(Re(s)))}catch{return""}}function Me(){if(process.env.MCP_SKILL_PATH)return process.env.MCP_SKILL_PATH;let s=Ce(qe(import.meta.url)),n=Pe(s,"..","bin","mcp-skill.mjs");return Le(n)?n:null}function Je(s){return ce(s)}async function U(s,n){try{return await s(Je(n))}catch(t){let e=Number(t?.status);if(!(e>=400&&e<500))throw t;return console.warn(`[jira] rich body rejected (${e}) \u2014 retrying as plain text: ${String(t?.message||t).slice(0,200)}`),await s(M(n))}}function O(s){return String(s||"").toLowerCase().replace(/\s+/g,"").replace(/[()\-_::"'`]/g,"")}function D(s){return O(s).replace(/[a-z0-9]+/g,"")}function C(s,n){let t=O(s),e=O(n);if(!t||!e)return 0;if(t===e)return 1;if(t.length===1||e.length===1)return t===e?1:0;let i=u=>{let d=new Map;for(let m=0;m<u.length-1;m++){let h=u.slice(m,m+2);d.set(h,(d.get(h)||0)+1)}return d},r=i(t),a=i(e),o=0,c=0,l=0;for(let u of r.values())c+=u;for(let u of a.values())l+=u;for(let[u,d]of r.entries()){let m=a.get(u)||0;o+=Math.min(d,m)}return 2*o/Math.max(1,c+l)}function w(s){return String(s||"").toLowerCase().replace(/\s+/g,"").replace(/[()\-_::"'`]/g,"")}function Ue(s,n=[]){let t=Array.isArray(n)?n:[];if(t.length===0)return{requested:s||null,resolved:null,strategy:"none"};let e=t.filter(o=>!o.subtask),i=e.length>0?e:t,r=w(s);if(r){let o=i.find(u=>w(u.name)===r);if(o)return{requested:s,resolved:o,strategy:"exact"};let c={task:["task","\u4EFB\u52A1","\u4E8B\u9879","to do","todo"],story:["story","\u7528\u6237\u6545\u4E8B","\u9700\u6C42"],bug:["bug","\u7F3A\u9677","\u95EE\u9898"],improvement:["improvement","\u4F18\u5316","\u6539\u8FDB"],epic:["epic","\u53F2\u8BD7"]};for(let u of Object.values(c)){if(!u.some(m=>w(m)===r))continue;let d=i.find(m=>u.some(h=>w(h)===w(m.name)));if(d)return{requested:s,resolved:d,strategy:"alias"}}let l=i.map(u=>({t:u,score:C(s,u.name)})).sort((u,d)=>d.score-u.score);if(l[0]&&l[0].score>=.5)return{requested:s,resolved:l[0].t,strategy:"fuzzy"}}let a=["task","story","bug","improvement","epic"];for(let o of a){let c=i.find(l=>w(l.name)===o);if(c)return{requested:s||null,resolved:c,strategy:"default-preferred"}}return{requested:s||null,resolved:i[0],strategy:"default-first"}}async function le(s){let n=`projectKeys=${encodeURIComponent(s)}&expand=projects.issuetypes`,t=await f(`/rest/api/3/issue/createmeta?${n}`),e=Array.isArray(t?.projects)?t.projects:[],r=e.find(o=>String(o?.key||"").toUpperCase()===String(s||"").toUpperCase())||e[0]||null;return(Array.isArray(r?.issuetypes)?r.issuetypes:[]).map(o=>({id:o.id,name:o.name,subtask:!!o.subtask,description:o.description||null}))}async function ue(s,n){if(!s)throw new Error("projectKey is required");let t="sprint is not EMPTY";n==="active"?t="sprint in openSprints()":n==="closed"?t="sprint in closedSprints()":n==="future"&&(t="sprint in futureSprints()");let e=`project = ${s} AND ${t} ORDER BY updated DESC`,i=`jql=${encodeURIComponent(e)}&maxResults=100&fields=customfield_10020`,r=await f(`/rest/api/3/search/jql?${i}`),a=new Map;for(let o of r.issues||[])for(let c of o.fields?.customfield_10020||[])c&&!a.has(c.id)&&a.set(c.id,{id:c.id,name:c.name,state:c.state,boardId:c.boardId||null,startDate:c.startDate||null,endDate:c.endDate||null,goal:c.goal||null});return[...a.values()].sort((o,c)=>{let l={active:0,future:1,closed:2},u=(l[o.state]??3)-(l[c.state]??3);return u!==0?u:String(c.startDate||"").localeCompare(String(o.startDate||""))})}function De(s,{sprintId:n,sprintName:t,target:e}={}){let i=Array.isArray(s)?s:[];if(!i.length)return{sprint:null,selectedBy:"none"};if(n!=null&&String(n).trim()!=="")return{sprint:i.find(o=>String(o.id)===String(n))||null,selectedBy:"id"};if(t&&String(t).trim()){let a=String(t).trim(),o=i.find(l=>String(l.name||"").toLowerCase()===a.toLowerCase());if(o)return{sprint:o,selectedBy:"name-exact"};let c=i.map(l=>({s:l,score:C(a,l.name||"")})).sort((l,u)=>u.score-l.score);return c[0]&&c[0].score>=.5?{sprint:c[0].s,selectedBy:"name-fuzzy"}:{sprint:null,selectedBy:"name-none"}}let r=String(e||"current").trim().toLowerCase();return r==="active"||r==="current"||r==="latest"?{sprint:i[0],selectedBy:r}:{sprint:i[0],selectedBy:"default"}}function Ge(s,n){let t=s?.fields?.customfield_10020;return Array.isArray(t)?t.some(e=>String(e?.id)===String(n)):!1}async function Fe({issueKey:s,projectKey:n,sprintId:t,attempts:e=3,delayMs:i=450}){let r=[];for(let a=0;a<e;a++){try{let o=`project = ${n} AND key = ${s} AND sprint = ${t}`,c=`jql=${encodeURIComponent(o)}&maxResults=1&fields=key,status`,l=await f(`/rest/api/3/search/jql?${c}`);if(Number(l?.total||0)>0)return r.push({attempt:a+1,jql:!0,issueField:null}),{ok:!0,method:"jql",traces:r};let d=await f(`/rest/api/3/issue/${s}?fields=customfield_10020,status`),m=Ge(d,t);if(r.push({attempt:a+1,jql:!1,issueField:m}),m)return{ok:!0,method:"issue_field",traces:r}}catch(o){r.push({attempt:a+1,error:String(o?.message||o)})}a<e-1&&await new Promise(o=>setTimeout(o,i))}return{ok:!1,method:"none",traces:r}}async function G({issueKey:s,projectKey:n,sprintId:t,sprintName:e,target:i}){if(!s)return{ok:!1,error:"issueKey is required"};let r=n;if(!r&&(r=(await f(`/rest/api/3/issue/${s}?fields=project`))?.fields?.project?.key||null,!r))return{ok:!1,error:`Could not resolve project for ${s}`};let a=await ue(r,"active");if(!a.length)return{ok:!1,error:`No assignable active sprint found for project ${r}`};let{sprint:o,selectedBy:c}=De(a,{sprintId:t,sprintName:e,target:i});if(!o)return{ok:!1,error:`No matching sprint found in ${r}`,requested:{sprintId:t??null,sprintName:e??null,target:i??"current"},availableSprints:a.map(d=>({id:d.id,name:d.name,state:d.state}))};await f(`/rest/api/3/issue/${s}`,{method:"PUT",body:{fields:{customfield_10020:Number(o.id)}}});let l=await Fe({issueKey:s,projectKey:r,sprintId:o.id}),u=l.ok;return{ok:u,issueKey:s,projectKey:r,sprintId:o.id,sprintName:o.name,selectedBy:c,verifiedBy:l.method,verified:u,verificationTrace:l.traces,warning:u?null:`Sprint assignment attempted but verification did not find ${s} in sprint ${o.id}`}}async function We(){let s=process.env.JIRA_API_TOKEN,n=process.env.JIRA_EMAIL,t=process.env.JIRA_BASE_URL;if(s&&n&&t)return{authType:"token",apiToken:s,email:n,baseUrl:t};let e=await Ke("jira");return(e?.authType?e.authType!=="token":!!e?.cloudId)?{authType:"oauth",accessToken:e.token,cloudId:e.cloudId}:{authType:"token",apiToken:e?.token,email:n||e?.email||"",baseUrl:t||e?.baseUrl||e?.instanceUrl||process.env.ATLASSIAN_INSTANCE_URL||""}}function ze(s,n,t={}){let e=s||{},i={Accept:"application/json",...t.body&&!t.form?{"Content-Type":"application/json"}:{},...t.headers};if(e.authType==="token"){let r=String(e.baseUrl||e.instanceUrl||"").trim().replace(/\/+$/,""),a=e.apiToken||e.accessToken||"";if(!r)throw new Error("Jira token connection has no base URL \u2014 reconnect Jira with its instance URL, or set JIRA_BASE_URL.");if(!e.email)throw new Error("Jira token connection has no account email \u2014 reconnect Jira with the account email, or set JIRA_EMAIL.");if(!a)throw new Error("Jira token connection has no API token \u2014 reconnect Jira, or set JIRA_API_TOKEN.");return{url:`${r}${n}`,headers:{Authorization:"Basic "+Buffer.from(`${e.email}:${a}`).toString("base64"),...i}}}if(typeof e.accessToken!="string"||!e.accessToken)throw new Error(`Invalid jira token type: ${typeof e.accessToken}`);if(!e.cloudId)throw new Error("Invalid jira cloudId: missing");return{url:`https://api.atlassian.com/ex/jira/${e.cloudId}${n}`,headers:{Authorization:`Bearer ${e.accessToken}`,...i}}}async function f(s,n={}){let t=async()=>{let e=await We(),{url:i,headers:r}=ze(e,s,n),a=await Q(i,{method:n.method||"GET",headers:r,body:n.form?n.form:n.body?JSON.stringify(n.body):void 0,signal:n.signal},{kind:/\/search\b/.test(String(s))?"job":"api",what:`Jira ${n.method||"GET"} ${s}`}),o=()=>a.text().catch(l=>{if(P(l)||n.signal?.aborted)throw l;return""});if(!a.ok){let l=await o(),u=new Error(`Jira API ${a.status}: ${l.slice(0,300)}`);throw u.status=a.status,u}let c=await o();if(!c||!c.trim())return{};try{return JSON.parse(c)}catch{return{raw:c}}};try{return await t()}catch(e){if(n.signal?.aborted)throw e;let i=String(e?.message||e||"").toLowerCase();if(!(i.includes("token")||i.includes("401")||i.includes("403")||i.includes("substring")))throw e;return Be("jira"),t()}}var $={id:"jira",callsBackend:!0,serverName:"jira",allowedTools:["mcp__jira__*"],requiresIntegration:Y.JIRA,envKeys:["ATLASSIAN_ACCESS_TOKEN","ATLASSIAN_CLOUD_ID"],description:"Zibby Jira MCP Server (OAuth Bearer)",promptFragment:`## Jira
|
|
22
24
|
You have direct access to the user's Jira. Use these tools proactively:
|
|
23
25
|
|
|
24
26
|
### Issue tools
|
|
@@ -68,6 +70,6 @@ When user asks to move/transition ticket status:
|
|
|
68
70
|
3. Pick the correct transition from returned list (match by "to" status name, not guesswork), then call jira_transition_issue with transitionId.
|
|
69
71
|
4. Call jira_get_issue(issueKey) to verify final status before claiming success.
|
|
70
72
|
5. If target wording differs (e.g. \u5DF2\u7ECF\u9A8C\u6536 vs \u5DF2\u9A8C\u6536), try toStatus first; only ask user to confirm when no reasonable match exists.
|
|
71
|
-
6. IMPORTANT: When target is clear, complete transition + verification in SAME turn. Do NOT stop after listing options.`,resolve(){let s=Ke();if(!s)return{command:null,args:[],env:{},description:this.description};let n={};for(let e of this.envKeys)process.env[e]&&(n[e]=process.env[e]);process.env.ATLASSIAN_INSTANCE_URL&&(n.ATLASSIAN_INSTANCE_URL=process.env.ATLASSIAN_INSTANCE_URL);for(let e of["JIRA_API_TOKEN","JIRA_EMAIL","JIRA_BASE_URL"])process.env[e]&&(n[e]=process.env[e]);return{type:"stdio",command:"node",args:[s,"../dist/jira.js","jiraSkill"],env:n,description:this.description}},async handleToolCall(s,n){try{switch(s){case"jira_list_projects":{let e=await m("/rest/api/3/project"),t=(Array.isArray(e)?e:[]).map(i=>({id:i.id,key:i.key,name:i.name,style:i.style}));return JSON.stringify({count:t.length,projects:t})}case"jira_list_statuses":{let{projectKey:e}=n||{};if(e){let r=await m(`/rest/api/3/project/${encodeURIComponent(e)}/statuses`),a=Array.isArray(r)?r:[],o=new Map;for(let l of a)for(let u of l.statuses||[])u?.id&&(o.has(u.id)||o.set(u.id,{id:u.id,name:u.name,category:u.statusCategory?.name||null}));let c=[...o.values()].sort((l,u)=>String(l.name).localeCompare(String(u.name)));return JSON.stringify({scope:"project",projectKey:e,count:c.length,statuses:c})}let t=await m("/rest/api/3/status"),i=(Array.isArray(t)?t:[]).map(r=>({id:r.id,name:r.name,category:r.statusCategory?.name||null})).sort((r,a)=>String(r.name).localeCompare(String(a.name)));return JSON.stringify({scope:"global",count:i.length,statuses:i})}case"jira_list_issue_types":{let{projectKey:e}=n||{};if(!e)return JSON.stringify({error:"projectKey is required"});let t=await ce(e);return JSON.stringify({projectKey:e,count:t.length,issueTypes:t})}case"jira_search":{let e=n.jql||"",t=n.maxResults||20;e.replace(/\s*ORDER\s+BY\s+.*/i,"").trim()||(e=`created >= -365d ${e}`.trim());let r=`jql=${encodeURIComponent(e)}&maxResults=${t}&fields=summary,status,assignee,priority,updated,issuetype,project`,o=((await m(`/rest/api/3/search/jql?${r}`)).issues||[]).map(c=>({key:c.key,project:c.fields?.project?.key,summary:c.fields?.summary,status:c.fields?.status?.name,assignee:c.fields?.assignee?.displayName||"Unassigned",priority:c.fields?.priority?.name,type:c.fields?.issuetype?.name}));return JSON.stringify({count:o.length,issues:o})}case"jira_get_issue":{let e=n.issueKey;if(!e)return JSON.stringify({error:"issueKey is required"});let t=await m(`/rest/api/3/issue/${e}`);return JSON.stringify({key:t.key,project:t.fields?.project?.key,summary:t.fields?.summary,description:t.fields?.description?J(t.fields.description):t.fields?.description??null,status:t.fields?.status?.name,assignee:t.fields?.assignee?.displayName||"Unassigned",priority:t.fields?.priority?.name,type:t.fields?.issuetype?.name,labels:t.fields?.labels,created:t.fields?.created,updated:t.fields?.updated})}case"jira_create_issue":{let{projectKey:e,summary:t,issueType:i,description:r,priority:a,labels:o,assigneeId:c,moveToSprint:l,moveToActiveSprint:u,sprintId:d,sprintName:f,target:y}=n;if(!e||!t)return JSON.stringify({error:"projectKey and summary are required"});let p={requested:i||null,resolved:null,strategy:"none"},g=[];try{g=await ce(e),p=Be(i,g)}catch{}let h={project:{key:e},summary:t,issuetype:p?.resolved?.id?{id:p.resolved.id}:{name:i||"Task"}};a&&(h.priority={name:a}),o?.length&&(h.labels=o),c&&(h.assignee={id:c});let I=r?await U(j=>m("/rest/api/3/issue",{method:"POST",body:{fields:{...h,description:j}}}),r):await m("/rest/api/3/issue",{method:"POST",body:{fields:h}}),k={ok:!0,key:I.key,id:I.id,self:I.self};return p?.resolved&&(k.issueType=p.resolved.name,k.issueTypeResolution=p.strategy,p.strategy!=="exact"&&p.requested&&w(p.requested)!==w(p.resolved.name)&&(k.issueTypeWarning=`Requested "${p.requested}" is not available in ${e}; used "${p.resolved.name}" instead.`)),g.length>0&&(k.availableIssueTypes=g.map(j=>j.name)),(l||u)&&(k.sprintMove=await G({issueKey:I.key,projectKey:e,sprintId:d,sprintName:f,target:y})),JSON.stringify(k)}case"jira_list_sprints":{let{projectKey:e,state:t}=n,i=await le(e,t);return JSON.stringify({count:i.length,sprints:i})}case"jira_move_to_active_sprint":{let{issueKey:e,projectKey:t,sprintId:i,sprintName:r,target:a}=n||{},o=await G({issueKey:e,projectKey:t,sprintId:i,sprintName:r,target:a||"current"});return JSON.stringify(o)}case"jira_move_issue_to_sprint":{let{issueKey:e,projectKey:t,sprintId:i,sprintName:r,target:a}=n||{},o=await G({issueKey:e,projectKey:t,sprintId:i,sprintName:r,target:a});return JSON.stringify(o)}case"jira_get_sprint_issues":{let{sprintName:e,sprintId:t,projectKey:i,status:r,maxResults:a}=n;if(!e&&!t)return JSON.stringify({error:"sprintName or sprintId is required"});let o=a||50,c=t?`sprint = ${t}`:`sprint = "${e}"`,l=i?`project = ${i} AND `:"",u=r?` AND status = "${r}"`:"",d=`${l}${c}${u} ORDER BY status ASC, priority DESC`,f=`jql=${encodeURIComponent(d)}&maxResults=${o}&fields=summary,status,assignee,priority,issuetype,project`,y=await m(`/rest/api/3/search/jql?${f}`),p=(y.issues||[]).map(h=>({key:h.key,project:h.fields?.project?.key,summary:h.fields?.summary,status:h.fields?.status?.name,assignee:h.fields?.assignee?.displayName||"Unassigned",priority:h.fields?.priority?.name,type:h.fields?.issuetype?.name})),g={};for(let h of p)g[h.status]=(g[h.status]||0)+1;return JSON.stringify({count:p.length,total:y.total||p.length,statusCounts:g,issues:p})}case"jira_get_comments":{let{issueKey:e,maxResults:t}=n;if(!e)return JSON.stringify({error:"issueKey is required"});let r=await m(`/rest/api/3/issue/${e}/comment?maxResults=${t||50}&orderBy=-created`),a=(r.comments||[]).map(o=>{let c=o.body?.content?J(o.body):"";return{id:o.id,author:o.author?.displayName||"Unknown",body:c,created:o.created,updated:o.updated}});return JSON.stringify({count:a.length,total:r.total||a.length,comments:a})}case"jira_add_comment":{let{issueKey:e,body:t}=n;return!e||!t?JSON.stringify({error:"issueKey and body are required"}):(await U(i=>m(`/rest/api/3/issue/${e}/comment`,{method:"POST",body:{body:i}}),t),JSON.stringify({ok:!0,issueKey:e}))}case"jira_edit_issue":{let{issueKey:e,fields:t}=n;if(!e||!t)return JSON.stringify({error:"issueKey and fields are required"});if(typeof t.description=="string"){let{description:i,...r}=t;await U(a=>m(`/rest/api/3/issue/${e}`,{method:"PUT",body:{fields:{...r,description:a}}}),i)}else await m(`/rest/api/3/issue/${e}`,{method:"PUT",body:{fields:t}});return JSON.stringify({ok:!0,issueKey:e})}case"jira_transition_issue":{let{issueKey:e,transitionId:t,toStatus:i,statusName:r,status:a}=n;if(!e)return JSON.stringify({error:"issueKey is required"});let o=String(i||r||a||"").trim();if(!t&&!o){let d=((await m(`/rest/api/3/issue/${e}/transitions`)).transitions||[]).map(f=>({id:f.id,name:f.name,to:f.to?.name}));return JSON.stringify({ok:!1,error:"transitionId or toStatus is required",issueKey:e,availableTransitions:d})}let c=t;if(!c){let d=(await m(`/rest/api/3/issue/${e}/transitions`)).transitions||[],f=O(o),y=d.find(p=>O(p?.name||"")===f||O(p?.to?.name||"")===f);if(!y){let p=D(o);p.length>=2&&(y=d.find(g=>{let h=D(g?.name||""),I=D(g?.to?.name||""),k=h.length>=2&&(h.includes(p)||p.includes(h)),j=I.length>=2&&(I.includes(p)||p.includes(I));return k||j}))}if(!y){let p=d.map(k=>{let j=C(o,k?.name||""),ue=C(o,k?.to?.name||"");return{t:k,score:Math.max(j,ue)}}).sort((k,j)=>j.score-k.score),g=p[0],h=p[1];g&&g.score>=.45&&(!h||g.score-h.score>=.12)&&(y=g.t)}if(!y?.id)return JSON.stringify({ok:!1,error:`No transition matches target status: "${o}"`,issueKey:e,availableTransitions:d.map(p=>({id:p.id,name:p.name,to:p.to?.name}))});c=y.id}await m(`/rest/api/3/issue/${e}/transitions`,{method:"POST",body:{transition:{id:c}}});let l=await m(`/rest/api/3/issue/${e}?fields=status`);return JSON.stringify({ok:!0,issueKey:e,transitionId:c,statusAfter:l?.fields?.status?.name||null})}default:return JSON.stringify({error:`Unknown tool: ${s}`})}}catch(e){return JSON.stringify({error:e.message})}},tools:[{name:"jira_list_projects",description:"List all Jira projects accessible to the user",input_schema:{type:"object",properties:{}}},{name:"jira_list_statuses",description:"List Jira statuses. Use projectKey to get statuses applicable in that project workflow.",input_schema:{type:"object",properties:{projectKey:{type:"string",description:"Optional project key (e.g. PROJ). If omitted, returns global status catalog."}}}},{name:"jira_list_issue_types",description:"List issue types allowed for issue creation in the given project.",input_schema:{type:"object",properties:{projectKey:{type:"string",description:"Project key, e.g. PROJ"}},required:["projectKey"]}},{name:"jira_search",description:"Search Jira issues using JQL",input_schema:{type:"object",properties:{jql:{type:"string",description:'JQL query string, e.g. "project = PROJ AND status = Open"'},maxResults:{type:"number",description:"Max results to return (default 20)"}},required:["jql"]}},{name:"jira_get_issue",description:"Get details of a specific Jira issue",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"}},required:["issueKey"]}},{name:"jira_create_issue",description:"Create a new Jira issue",input_schema:{type:"object",properties:{projectKey:{type:"string",description:"Project key, e.g. PROJ"},summary:{type:"string",description:"Issue title/summary"},issueType:{type:"string",description:"Issue type (default: Task). Common: Task, Bug, Story, Epic"},description:{type:"string",description:"Issue description. Markdown is rendered (headings, **bold**, `code`, lists, - [ ] tasks, links, tables, > quotes, > [!NOTE]/[!TIP]/[!WARNING]/[!CAUTION] panels)."},priority:{type:"string",description:"Priority name, e.g. High, Medium, Low"},labels:{type:"array",items:{type:"string"},description:"Array of label strings"},assigneeId:{type:"string",description:"Atlassian account ID to assign to"},moveToSprint:{type:"boolean",description:"If true, move created issue to a sprint and verify."},moveToActiveSprint:{type:"boolean",description:"Backward-compatible alias for moveToSprint."},sprintId:{type:"number",description:"Optional sprint id for placement."},sprintName:{type:"string",description:"Optional sprint name for placement."},target:{type:"string",description:"Placement target when sprintId/sprintName omitted: current|active|latest (default: current)."}},required:["projectKey","summary"]}},{name:"jira_list_sprints",description:"List sprints for a Jira project (returns sprint names, IDs, states, dates)",input_schema:{type:"object",properties:{projectKey:{type:"string",description:"Project key, e.g. PROJ"},state:{type:"string",description:"Filter: active, closed, future. Omit for all."}},required:["projectKey"]}},{name:"jira_get_sprint_issues",description:"Get all issues in a sprint, optionally filtered by status column name",input_schema:{type:"object",properties:{sprintName:{type:"string",description:"Sprint name (from jira_list_sprints). Use this OR sprintId."},sprintId:{type:"number",description:"Sprint ID (from jira_list_sprints). Use this OR sprintName."},projectKey:{type:"string",description:"Project key to scope the search (optional)"},status:{type:"string",description:'Filter by status name (e.g. "\u8FDB\u884C\u4E2D", "\u6D4B\u8BD5", "Done")'},maxResults:{type:"number",description:"Max issues to return (default 50)"}}}},{name:"jira_move_to_active_sprint",description:"Backward-compatible alias: move issue to sprint target and verify membership.",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"},projectKey:{type:"string",description:"Optional project key. If omitted, inferred from issue."},sprintId:{type:"number",description:"Optional sprint id."},sprintName:{type:"string",description:"Optional sprint name."},target:{type:"string",description:"Target when sprintId/sprintName omitted: current|active|latest (default: current)."}},required:["issueKey"]}},{name:"jira_move_issue_to_sprint",description:"Move an issue to a sprint by id/name/target and verify membership.",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"},projectKey:{type:"string",description:"Optional project key. If omitted, inferred from issue."},sprintId:{type:"number",description:"Optional sprint id."},sprintName:{type:"string",description:"Optional sprint name."},target:{type:"string",description:"Target when sprintId/sprintName omitted: current|active|latest (default: current)."}},required:["issueKey"]}},{name:"jira_get_comments",description:"Get comments on a Jira issue (newest first)",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"},maxResults:{type:"number",description:"Max comments to return (default 50)"}},required:["issueKey"]}},{name:"jira_add_comment",description:"Add a comment to a Jira issue",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"},body:{type:"string",description:"Comment text. Markdown is rendered: headings, **bold**, `code`, lists, - [ ] tasks, links, tables, > quotes, > [!NOTE]/[!TIP]/[!WARNING]/[!CAUTION] panels."}},required:["issueKey","body"]}},{name:"jira_edit_issue",description:"Update fields on a Jira issue (summary, description, story points, labels, priority). A string `description` is Markdown and is rendered.",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"},fields:{type:"object",description:"Object of field names to values",additionalProperties:!0}},required:["issueKey","fields"]}},{name:"jira_transition_issue",description:"Move a Jira issue to a different status. Always pass toStatus when user gave a target; only pass issueKey alone when you explicitly need to list transitions.",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"},transitionId:{type:"string",description:"Transition ID to perform (optional if toStatus is provided)"},toStatus:{type:"string",description:'Target status/column name (e.g. "\u5DF2\u7ECF\u9A8C\u6536", "Done", "In Progress"). If provided, tool resolves matching transition automatically.'}},required:["issueKey"]}}]};var We={new:"todo",indeterminate:"in_progress",done:"done"},ze=/\b(blocked|on[\s-]?hold|waiting|stuck)\b/i;function z(s){if(!s)return"unknown";if(s.name&&ze.test(s.name))return"blocked";let n=s.statusCategory?.key;return We[n]||"unknown"}function H(s){if(!s)return"";if(Array.isArray(s))return s.map(H).join("");if(s.type==="text")return s.text||"";if(s.type==="hardBreak"||s.type==="rule")return`
|
|
73
|
+
6. IMPORTANT: When target is clear, complete transition + verification in SAME turn. Do NOT stop after listing options.`,resolve(){let s=Me();if(!s)return{command:null,args:[],env:{},description:this.description};let n={};for(let t of this.envKeys)process.env[t]&&(n[t]=process.env[t]);process.env.ATLASSIAN_INSTANCE_URL&&(n.ATLASSIAN_INSTANCE_URL=process.env.ATLASSIAN_INSTANCE_URL);for(let t of["JIRA_API_TOKEN","JIRA_EMAIL","JIRA_BASE_URL"])process.env[t]&&(n[t]=process.env[t]);return{type:"stdio",command:"node",args:[s,"../dist/jira.js","jiraSkill"],env:n,description:this.description}},async handleToolCall(s,n){try{switch(s){case"jira_list_projects":{let t=await f("/rest/api/3/project"),e=(Array.isArray(t)?t:[]).map(i=>({id:i.id,key:i.key,name:i.name,style:i.style}));return JSON.stringify({count:e.length,projects:e})}case"jira_list_statuses":{let{projectKey:t}=n||{};if(t){let r=await f(`/rest/api/3/project/${encodeURIComponent(t)}/statuses`),a=Array.isArray(r)?r:[],o=new Map;for(let l of a)for(let u of l.statuses||[])u?.id&&(o.has(u.id)||o.set(u.id,{id:u.id,name:u.name,category:u.statusCategory?.name||null}));let c=[...o.values()].sort((l,u)=>String(l.name).localeCompare(String(u.name)));return JSON.stringify({scope:"project",projectKey:t,count:c.length,statuses:c})}let e=await f("/rest/api/3/status"),i=(Array.isArray(e)?e:[]).map(r=>({id:r.id,name:r.name,category:r.statusCategory?.name||null})).sort((r,a)=>String(r.name).localeCompare(String(a.name)));return JSON.stringify({scope:"global",count:i.length,statuses:i})}case"jira_list_issue_types":{let{projectKey:t}=n||{};if(!t)return JSON.stringify({error:"projectKey is required"});let e=await le(t);return JSON.stringify({projectKey:t,count:e.length,issueTypes:e})}case"jira_search":{let t=n.jql||"",e=n.maxResults||20;t.replace(/\s*ORDER\s+BY\s+.*/i,"").trim()||(t=`created >= -365d ${t}`.trim());let r=`jql=${encodeURIComponent(t)}&maxResults=${e}&fields=summary,status,assignee,priority,updated,issuetype,project`,o=((await f(`/rest/api/3/search/jql?${r}`)).issues||[]).map(c=>({key:c.key,project:c.fields?.project?.key,summary:c.fields?.summary,status:c.fields?.status?.name,assignee:c.fields?.assignee?.displayName||"Unassigned",priority:c.fields?.priority?.name,type:c.fields?.issuetype?.name}));return JSON.stringify({count:o.length,issues:o})}case"jira_get_issue":{let t=n.issueKey;if(!t)return JSON.stringify({error:"issueKey is required"});let e=await f(`/rest/api/3/issue/${t}`);return JSON.stringify({key:e.key,project:e.fields?.project?.key,summary:e.fields?.summary,description:e.fields?.description?J(e.fields.description):e.fields?.description??null,status:e.fields?.status?.name,assignee:e.fields?.assignee?.displayName||"Unassigned",priority:e.fields?.priority?.name,type:e.fields?.issuetype?.name,labels:e.fields?.labels,created:e.fields?.created,updated:e.fields?.updated})}case"jira_create_issue":{let{projectKey:t,summary:e,issueType:i,description:r,priority:a,labels:o,assigneeId:c,moveToSprint:l,moveToActiveSprint:u,sprintId:d,sprintName:m,target:h}=n;if(!t||!e)return JSON.stringify({error:"projectKey and summary are required"});let p={requested:i||null,resolved:null,strategy:"none"},y=[];try{y=await le(t),p=Ue(i,y)}catch{}let g={project:{key:t},summary:e,issuetype:p?.resolved?.id?{id:p.resolved.id}:{name:i||"Task"}};a&&(g.priority={name:a}),o?.length&&(g.labels=o),c&&(g.assignee={id:c});let I=r?await U(j=>f("/rest/api/3/issue",{method:"POST",body:{fields:{...g,description:j}}}),r):await f("/rest/api/3/issue",{method:"POST",body:{fields:g}}),k={ok:!0,key:I.key,id:I.id,self:I.self};return p?.resolved&&(k.issueType=p.resolved.name,k.issueTypeResolution=p.strategy,p.strategy!=="exact"&&p.requested&&w(p.requested)!==w(p.resolved.name)&&(k.issueTypeWarning=`Requested "${p.requested}" is not available in ${t}; used "${p.resolved.name}" instead.`)),y.length>0&&(k.availableIssueTypes=y.map(j=>j.name)),(l||u)&&(k.sprintMove=await G({issueKey:I.key,projectKey:t,sprintId:d,sprintName:m,target:h})),JSON.stringify(k)}case"jira_list_sprints":{let{projectKey:t,state:e}=n,i=await ue(t,e);return JSON.stringify({count:i.length,sprints:i})}case"jira_move_to_active_sprint":{let{issueKey:t,projectKey:e,sprintId:i,sprintName:r,target:a}=n||{},o=await G({issueKey:t,projectKey:e,sprintId:i,sprintName:r,target:a||"current"});return JSON.stringify(o)}case"jira_move_issue_to_sprint":{let{issueKey:t,projectKey:e,sprintId:i,sprintName:r,target:a}=n||{},o=await G({issueKey:t,projectKey:e,sprintId:i,sprintName:r,target:a});return JSON.stringify(o)}case"jira_get_sprint_issues":{let{sprintName:t,sprintId:e,projectKey:i,status:r,maxResults:a}=n;if(!t&&!e)return JSON.stringify({error:"sprintName or sprintId is required"});let o=a||50,c=e?`sprint = ${e}`:`sprint = "${t}"`,l=i?`project = ${i} AND `:"",u=r?` AND status = "${r}"`:"",d=`${l}${c}${u} ORDER BY status ASC, priority DESC`,m=`jql=${encodeURIComponent(d)}&maxResults=${o}&fields=summary,status,assignee,priority,issuetype,project`,h=await f(`/rest/api/3/search/jql?${m}`),p=(h.issues||[]).map(g=>({key:g.key,project:g.fields?.project?.key,summary:g.fields?.summary,status:g.fields?.status?.name,assignee:g.fields?.assignee?.displayName||"Unassigned",priority:g.fields?.priority?.name,type:g.fields?.issuetype?.name})),y={};for(let g of p)y[g.status]=(y[g.status]||0)+1;return JSON.stringify({count:p.length,total:h.total||p.length,statusCounts:y,issues:p})}case"jira_get_comments":{let{issueKey:t,maxResults:e}=n;if(!t)return JSON.stringify({error:"issueKey is required"});let r=await f(`/rest/api/3/issue/${t}/comment?maxResults=${e||50}&orderBy=-created`),a=(r.comments||[]).map(o=>{let c=o.body?.content?J(o.body):"";return{id:o.id,author:o.author?.displayName||"Unknown",body:c,created:o.created,updated:o.updated}});return JSON.stringify({count:a.length,total:r.total||a.length,comments:a})}case"jira_add_comment":{let{issueKey:t,body:e}=n;return!t||!e?JSON.stringify({error:"issueKey and body are required"}):(await U(i=>f(`/rest/api/3/issue/${t}/comment`,{method:"POST",body:{body:i}}),e),JSON.stringify({ok:!0,issueKey:t}))}case"jira_edit_issue":{let{issueKey:t,fields:e}=n;if(!t||!e)return JSON.stringify({error:"issueKey and fields are required"});if(typeof e.description=="string"){let{description:i,...r}=e;await U(a=>f(`/rest/api/3/issue/${t}`,{method:"PUT",body:{fields:{...r,description:a}}}),i)}else await f(`/rest/api/3/issue/${t}`,{method:"PUT",body:{fields:e}});return JSON.stringify({ok:!0,issueKey:t})}case"jira_transition_issue":{let{issueKey:t,transitionId:e,toStatus:i,statusName:r,status:a}=n;if(!t)return JSON.stringify({error:"issueKey is required"});let o=String(i||r||a||"").trim();if(!e&&!o){let d=((await f(`/rest/api/3/issue/${t}/transitions`)).transitions||[]).map(m=>({id:m.id,name:m.name,to:m.to?.name}));return JSON.stringify({ok:!1,error:"transitionId or toStatus is required",issueKey:t,availableTransitions:d})}let c=e;if(!c){let d=(await f(`/rest/api/3/issue/${t}/transitions`)).transitions||[],m=O(o),h=d.find(p=>O(p?.name||"")===m||O(p?.to?.name||"")===m);if(!h){let p=D(o);p.length>=2&&(h=d.find(y=>{let g=D(y?.name||""),I=D(y?.to?.name||""),k=g.length>=2&&(g.includes(p)||p.includes(g)),j=I.length>=2&&(I.includes(p)||p.includes(I));return k||j}))}if(!h){let p=d.map(k=>{let j=C(o,k?.name||""),pe=C(o,k?.to?.name||"");return{t:k,score:Math.max(j,pe)}}).sort((k,j)=>j.score-k.score),y=p[0],g=p[1];y&&y.score>=.45&&(!g||y.score-g.score>=.12)&&(h=y.t)}if(!h?.id)return JSON.stringify({ok:!1,error:`No transition matches target status: "${o}"`,issueKey:t,availableTransitions:d.map(p=>({id:p.id,name:p.name,to:p.to?.name}))});c=h.id}await f(`/rest/api/3/issue/${t}/transitions`,{method:"POST",body:{transition:{id:c}}});let l=await f(`/rest/api/3/issue/${t}?fields=status`);return JSON.stringify({ok:!0,issueKey:t,transitionId:c,statusAfter:l?.fields?.status?.name||null})}default:return JSON.stringify({error:`Unknown tool: ${s}`})}}catch(t){return JSON.stringify({error:t.message})}},tools:[{name:"jira_list_projects",description:"List all Jira projects accessible to the user",input_schema:{type:"object",properties:{}}},{name:"jira_list_statuses",description:"List Jira statuses. Use projectKey to get statuses applicable in that project workflow.",input_schema:{type:"object",properties:{projectKey:{type:"string",description:"Optional project key (e.g. PROJ). If omitted, returns global status catalog."}}}},{name:"jira_list_issue_types",description:"List issue types allowed for issue creation in the given project.",input_schema:{type:"object",properties:{projectKey:{type:"string",description:"Project key, e.g. PROJ"}},required:["projectKey"]}},{name:"jira_search",description:"Search Jira issues using JQL",input_schema:{type:"object",properties:{jql:{type:"string",description:'JQL query string, e.g. "project = PROJ AND status = Open"'},maxResults:{type:"number",description:"Max results to return (default 20)"}},required:["jql"]}},{name:"jira_get_issue",description:"Get details of a specific Jira issue",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"}},required:["issueKey"]}},{name:"jira_create_issue",description:"Create a new Jira issue",input_schema:{type:"object",properties:{projectKey:{type:"string",description:"Project key, e.g. PROJ"},summary:{type:"string",description:"Issue title/summary"},issueType:{type:"string",description:"Issue type (default: Task). Common: Task, Bug, Story, Epic"},description:{type:"string",description:"Issue description. Markdown is rendered (headings, **bold**, `code`, lists, - [ ] tasks, links, tables, > quotes, > [!NOTE]/[!TIP]/[!WARNING]/[!CAUTION] panels)."},priority:{type:"string",description:"Priority name, e.g. High, Medium, Low"},labels:{type:"array",items:{type:"string"},description:"Array of label strings"},assigneeId:{type:"string",description:"Atlassian account ID to assign to"},moveToSprint:{type:"boolean",description:"If true, move created issue to a sprint and verify."},moveToActiveSprint:{type:"boolean",description:"Backward-compatible alias for moveToSprint."},sprintId:{type:"number",description:"Optional sprint id for placement."},sprintName:{type:"string",description:"Optional sprint name for placement."},target:{type:"string",description:"Placement target when sprintId/sprintName omitted: current|active|latest (default: current)."}},required:["projectKey","summary"]}},{name:"jira_list_sprints",description:"List sprints for a Jira project (returns sprint names, IDs, states, dates)",input_schema:{type:"object",properties:{projectKey:{type:"string",description:"Project key, e.g. PROJ"},state:{type:"string",description:"Filter: active, closed, future. Omit for all."}},required:["projectKey"]}},{name:"jira_get_sprint_issues",description:"Get all issues in a sprint, optionally filtered by status column name",input_schema:{type:"object",properties:{sprintName:{type:"string",description:"Sprint name (from jira_list_sprints). Use this OR sprintId."},sprintId:{type:"number",description:"Sprint ID (from jira_list_sprints). Use this OR sprintName."},projectKey:{type:"string",description:"Project key to scope the search (optional)"},status:{type:"string",description:'Filter by status name (e.g. "\u8FDB\u884C\u4E2D", "\u6D4B\u8BD5", "Done")'},maxResults:{type:"number",description:"Max issues to return (default 50)"}}}},{name:"jira_move_to_active_sprint",description:"Backward-compatible alias: move issue to sprint target and verify membership.",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"},projectKey:{type:"string",description:"Optional project key. If omitted, inferred from issue."},sprintId:{type:"number",description:"Optional sprint id."},sprintName:{type:"string",description:"Optional sprint name."},target:{type:"string",description:"Target when sprintId/sprintName omitted: current|active|latest (default: current)."}},required:["issueKey"]}},{name:"jira_move_issue_to_sprint",description:"Move an issue to a sprint by id/name/target and verify membership.",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"},projectKey:{type:"string",description:"Optional project key. If omitted, inferred from issue."},sprintId:{type:"number",description:"Optional sprint id."},sprintName:{type:"string",description:"Optional sprint name."},target:{type:"string",description:"Target when sprintId/sprintName omitted: current|active|latest (default: current)."}},required:["issueKey"]}},{name:"jira_get_comments",description:"Get comments on a Jira issue (newest first)",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"},maxResults:{type:"number",description:"Max comments to return (default 50)"}},required:["issueKey"]}},{name:"jira_add_comment",description:"Add a comment to a Jira issue",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"},body:{type:"string",description:"Comment text. Markdown is rendered: headings, **bold**, `code`, lists, - [ ] tasks, links, tables, > quotes, > [!NOTE]/[!TIP]/[!WARNING]/[!CAUTION] panels."}},required:["issueKey","body"]}},{name:"jira_edit_issue",description:"Update fields on a Jira issue (summary, description, story points, labels, priority). A string `description` is Markdown and is rendered.",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"},fields:{type:"object",description:"Object of field names to values",additionalProperties:!0}},required:["issueKey","fields"]}},{name:"jira_transition_issue",description:"Move a Jira issue to a different status. Always pass toStatus when user gave a target; only pass issueKey alone when you explicitly need to list transitions.",input_schema:{type:"object",properties:{issueKey:{type:"string",description:"Issue key, e.g. PROJ-123"},transitionId:{type:"string",description:"Transition ID to perform (optional if toStatus is provided)"},toStatus:{type:"string",description:'Target status/column name (e.g. "\u5DF2\u7ECF\u9A8C\u6536", "Done", "In Progress"). If provided, tool resolves matching transition automatically.'}},required:["issueKey"]}}]};var He={new:"todo",indeterminate:"in_progress",done:"done"},Ye=/\b(blocked|on[\s-]?hold|waiting|stuck)\b/i;function z(s){if(!s)return"unknown";if(s.name&&Ye.test(s.name))return"blocked";let n=s.statusCategory?.key;return He[n]||"unknown"}function H(s){if(!s)return"";if(Array.isArray(s))return s.map(H).join("");if(s.type==="text")return s.text||"";if(s.type==="hardBreak"||s.type==="rule")return`
|
|
72
74
|
`;let n=s.content?H(s.content):"";return/^(paragraph|heading|listItem|blockquote|codeBlock|panel)$/.test(s.type)&&(n+=`
|
|
73
|
-
`),n}function F(s,n){let
|
|
75
|
+
`),n}function F(s,n){let t=s.fields||{},e=t.status||null,i=null;if(s.self&&s.key)try{i=`${new URL(s.self).origin}/browse/${s.key}`}catch{i=null}return!i&&n&&s.key&&(i=`${String(n).replace(/\/+$/,"")}/browse/${s.key}`),{id:String(s.id??s.key??""),key:s.key,title:t.summary||"",body:typeof t.description=="string"?t.description:H(t.description?.content).trim(),state:e?.name||null,stateCategory:z(e),assignee:t.assignee?.displayName||null,url:i,_raw:s}}function W(s){let n=JSON.parse(s);if(n&&n.error)throw new Error(n.error);return n}var Qe={id:"jira",toStateCategory:z,toNeutral:F,async listCandidates(s={}){let n=s.query||"";if(!n.trim()){let r=[];if(s.state&&r.push(`status = "${s.state}"`),s.labels){let a=Array.isArray(s.labels)?s.labels:[s.labels];for(let o of a)r.push(`labels = "${o}"`)}s.updatedAfter&&r.push(`updated >= "${s.updatedAfter}"`),n=r.length?`${r.join(" AND ")} ORDER BY updated DESC`:"ORDER BY updated DESC"}let t=Number(s.limit)||30,e=`jql=${encodeURIComponent(n)}&maxResults=${t}&fields=summary,description,status,assignee,labels,project,updated,created`;return((await f(`/rest/api/3/search/jql?${e}`)).issues||[]).map(r=>F(r))},async getTicket(s){if(!s)throw new Error("key is required");let n=await f(`/rest/api/3/issue/${encodeURIComponent(s)}`);return!n||!n.key?null:F(n)},async getComments(s){if(!s)throw new Error("key is required");return(W(await $.handleToolCall("jira_get_comments",{issueKey:s})).comments||[]).map(t=>({id:String(t.id),author:t.author||"Unknown",body:t.body||"",createdAt:t.created||null,updatedAt:t.updated||null,_raw:t}))},async addComment(s,n){if(!s||!n)throw new Error("key and body are required");return{ok:!!W(await $.handleToolCall("jira_add_comment",{issueKey:s,body:n})).ok,id:null}},async transition(s,n){if(!s)throw new Error("key is required");let t=JSON.parse(await $.handleToolCall("jira_transition_issue",{issueKey:s,toStatus:n}));if(!t.ok)return{ok:!1,error:t.error||"transition failed",_raw:t};let e=t.statusAfter||null;return{ok:!0,stateAfter:e,stateCategoryAfter:z(e?{name:e}:null),_raw:t}},async linkPullRequest(s,n,t){if(!s||!n)throw new Error("key and prUrl are required");try{return await f(`/rest/api/3/issue/${encodeURIComponent(s)}/remotelink`,{method:"POST",body:{object:{url:n,title:t||n,icon:{url16x16:"https://github.com/favicon.ico",title:"GitHub"}}}}),{ok:!0,via:"remotelink"}}catch(e){let i=`${t?`${t}: `:"Linked PR: "}${n}`;return{ok:!!W(await $.handleToolCall("jira_add_comment",{issueKey:s,body:i})).ok,via:"comment",error:String(e?.message||e)}}}},pt=Qe;export{pt as default,Qe as jiraAdapter};
|
package/dist/triggerAgent.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dirname as
|
|
1
|
+
import{dirname as I,resolve as y}from"path";import{fileURLToPath as w}from"url";import{existsSync as S}from"fs";import{EFFORT_LEVELS as p}from"@zibby/agent-workflow";var f={api:{knob:"SKILL_API_TIMEOUT_MS",fallback:3e4},transfer:{knob:"SKILL_TRANSFER_TIMEOUT_MS",fallback:12e4},job:{knob:"SKILL_JOB_TIMEOUT_MS",fallback:3e5}};function h(e,t,r=process.env){let o=Number(r?.[e]);return Number.isFinite(o)&&o>0?Math.min(6e5,Math.max(1e3,Math.floor(o))):t}function T(e="api",t=process.env){let r=f[e]||f.api;return h(r.knob,r.fallback,t)}function _(e){return e?.name==="TimeoutError"||e?.name==="AbortError"}function m(e){try{return new URL(String(e?.url??e)).host||"unknown host"}catch{return"unknown host"}}function O(e,t){if(!e)return t;let r=new AbortController,o=s=>{r.signal.aborted||r.abort(s)},a=()=>o(e.reason),n=()=>o(t.reason);return r.signal.addEventListener("abort",()=>{e.removeEventListener("abort",a),t.removeEventListener("abort",n)},{once:!0}),e.aborted?o(e.reason):t.aborted?o(t.reason):(e.addEventListener("abort",a,{once:!0}),t.addEventListener("abort",n,{once:!0})),r.signal}async function g(e,t={},r={}){let o=r.kind||"api",a=(f[o]||f.api).knob,n=r.timeoutMs?Math.min(6e5,Math.max(1e3,Math.floor(r.timeoutMs))):T(o),s=t?.signal;if(s?.aborted)throw s.reason??new DOMException("This operation was aborted","AbortError");let c=AbortSignal.timeout(n),l=O(s,c);try{return await fetch(e,{...t,signal:l})}catch(i){throw c.aborted&&_(i)?new Error(`${r.what||"request"} TIMED OUT after ${n}ms against ${m(e)} (${a})`):i}}function b(){if(process.env.MCP_SKILL_PATH)return process.env.MCP_SKILL_PATH;let e=I(w(import.meta.url)),t=y(e,"..","bin","mcp-skill.mjs");return S(t)?t:null}function k(){return process.env.PROJECT_API_TOKEN||process.env.ZIBBY_USER_TOKEN||null}function E(){return((process.env.PROGRESS_API_URL||"").replace(/\/executions\/?$/,"")||process.env.ZIBBY_ACCOUNT_API_URL||process.env.ZIBBY_PROD_ACCOUNT_API_URL||(process.env.ZIBBY_ENV==="local"?"http://localhost:3001":"https://api-prod.zibby.app")).replace(/\/+$/,"")}var L={name:"trigger_agent",description:"Trigger another Zibby workflow/agent run in THIS project (fire-and-forget). Call it once per run you want to start \u2014 the agent decides which and how many. Omit workflowType to re-run THIS same agent (self-dispatch, e.g. with a different trigger input). Returns the started run's executionId; does NOT wait for it to finish.",input_schema:{type:"object",properties:{workflowType:{type:"string",description:"Which workflow to trigger (its type/slug in this project). Omit to trigger THIS same agent (self-dispatch)."},input:{type:"object",description:"The trigger payload passed to the target workflow (validated against its state schema)."},effort:{type:"string",enum:[...p],description:"Optional: how hard the started run's model should think (low = quick/cheap, max = deepest). Omit for that agent's default."}},required:[]}},A={id:"trigger-agent",callsBackend:!0,serverName:"trigger",allowedTools:["mcp__trigger__*"],envKeys:[],description:"Trigger another Zibby workflow/agent run in this project (agent-driven, fire-and-forget; cloud + self-hosted).",promptFragment:"## Trigger another agent (agent-driven)\nYou can start another Zibby agent run yourself with the `trigger_agent`\ntool \u2014 and YOU decide when and how many times to call it. Each call starts ONE\nindependent run (fire-and-forget) and returns its executionId; it does NOT wait for\nthat run to finish.\n- To re-run THIS same agent (self-dispatch) \u2014 e.g. to hand an item to another of\n this agent's scenarios \u2014 OMIT `workflowType` and pass the `input` for that run.\n- To trigger a DIFFERENT agent in the project, pass its `workflowType` + `input`.\n- Optional `effort` (low\u2026max) sets how hard that run's model thinks; omit it for the agent's default.\nCall it once per run you want to start (loop over your items and call it for each).\nIt never throws \u2014 a failure comes back as { ok:false, error }; log it and move on.",resolve(){let e=b();if(!e)return{command:null,args:[],env:{},description:this.description};let t={};for(let r of["PROJECT_API_TOKEN","PROJECT_ID","WORKFLOW_TYPE","PROGRESS_API_URL","ZIBBY_ACCOUNT_API_URL","ZIBBY_PROD_ACCOUNT_API_URL","ZIBBY_ENV","ZIBBY_USER_TOKEN"])process.env[r]&&(t[r]=process.env[r]);return{type:"stdio",command:"node",args:[e,"../dist/triggerAgent.js","triggerAgentSkill"],env:t,description:this.description,alwaysLoad:!1}},async handleToolCall(e,t={}){if(e!=="trigger_agent")return JSON.stringify({ok:!1,error:`unknown tool: ${e}`});try{let r=process.env.PROJECT_ID,o=k(),a=typeof t.workflowType=="string"&&t.workflowType.trim()?t.workflowType.trim():(process.env.WORKFLOW_TYPE||"").trim();if(!r)return JSON.stringify({ok:!1,error:"PROJECT_ID not set \u2014 cannot resolve the target project."});if(!o)return JSON.stringify({ok:!1,error:"PROJECT_API_TOKEN not set \u2014 cannot authenticate the trigger."});if(!a)return JSON.stringify({ok:!1,error:"No workflowType given and WORKFLOW_TYPE is unset \u2014 nothing to trigger."});let n=null;if(t.effort!==void 0&&t.effort!==null&&t.effort!==""){let d=typeof t.effort=="string"?t.effort.trim().toLowerCase():"";if(!p.includes(d))return JSON.stringify({ok:!1,error:`unknown effort "${String(t.effort).slice(0,40)}" \u2014 use one of: ${p.join(", ")}`});n=d}let s=`${E()}/projects/${encodeURIComponent(r)}/workflows/${encodeURIComponent(a)}/trigger`,c=await g(s,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${o}`},body:JSON.stringify({input:t.input&&typeof t.input=="object"?t.input:{},...n?{effort:n}:{}})},{kind:"api",what:`trigger agent ${a}`}),l=await c.text().catch(()=>""),i;try{i=l?JSON.parse(l):{}}catch{i={raw:l}}if(!c.ok)return JSON.stringify({ok:!1,error:`trigger failed (HTTP ${c.status})`,detail:i&&(i.error||i.message)||l.slice(0,300)});let u=i.executionId||i.execution?.id||i.id||null;return JSON.stringify(u?{ok:!0,workflowType:a,executionId:u,...n?{effort:n}:{},note:"run started (fire-and-forget)"}:{ok:!1,workflowType:a,error:`the platform answered HTTP ${c.status} with no execution id, so this run may or may not have started`,detail:l.slice(0,300),note:"Do NOT record this as dispatched. Check whether a run for this agent exists before triggering it again."})}catch(r){return JSON.stringify({ok:!1,error:`trigger_agent failed: ${r?.message||String(r)}`})}},tools:[L]};export{A as triggerAgentSkill};
|
package/dist/vikunja.js
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
import{existsSync as
|
|
1
|
+
import{existsSync as qt}from"fs";var ut={NOTE:"info",TIP:"success",IMPORTANT:"note",WARNING:"warning",CAUTION:"error"},dt={info:"NOTE",success:"TIP",note:"IMPORTANT",warning:"WARNING",error:"CAUTION"},R={info:{bg:"rgba(88, 140, 245, 0.16)",rgb:[88,140,245],icon:"\u2139\uFE0F"},note:{bg:"rgba(160, 120, 240, 0.16)",rgb:[160,120,240],icon:"\u{1F4DD}"},warning:{bg:"rgba(236, 170, 60, 0.15)",rgb:[236,170,60],icon:"\u26A0\uFE0F"},success:{bg:"rgba(70, 190, 125, 0.16)",rgb:[70,190,125],icon:"\u2705"},error:{bg:"rgba(235, 90, 80, 0.15)",rgb:[235,90,80],icon:"\u26D4"}},pt=Object.keys(R),kt=2e5,tt=6,ht=/^```([A-Za-z0-9_+.-]{0,32})\s*$/,gt=/^(#{1,6})[ \t]+(.*?)\s*$/,ft=/^(?:-{3,}|\*{3,}|_{3,})\s*$/,F=/^>(?: ?(.*))?$/,q=/^[-*][ \t]+\[([ xX])\][ \t]+(.*)$/,V=/^[-*][ \t]+(.*)$/,H=/^(\d{1,3})[.)][ \t]+(.*)$/,W=/^\|.*\|\s*$/,mt=/^\|?\s*:?-{1,}:?\s*(?:\|\s*:?-{1,}:?\s*)*\|?\s*$/,bt=/^\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\s*$/i;function z(n){let r=n.trim().replace(/^\|/,"").replace(/\|$/,""),t=[],e="";for(let i=0;i<r.length;i++){let s=r[i];if(s==="\\"&&r[i+1]==="|"){e+="|",i++;continue}if(s==="|"){t.push(e.trim()),e="";continue}e+=s}return t.push(e.trim()),t}function et(n){let t=String(n??"").slice(0,kt).replace(/\r\n?/g,`
|
|
2
2
|
`).split(`
|
|
3
|
-
`);return D(t,0)}function D(n,
|
|
4
|
-
`)});continue}if(
|
|
5
|
-
`).
|
|
6
|
-
|
|
7
|
-
`;break;case"
|
|
8
|
-
|
|
9
|
-
`;break;case"
|
|
10
|
-
|
|
11
|
-
`;break;case"
|
|
12
|
-
${
|
|
3
|
+
`);return D(t,0)}function D(n,r){let t=[],e=0;for(;e<n.length;){let i=n[e];if(i.trim()===""){e++;continue}if(/^[ \t]/.test(i)){t.push({t:"paragraph",c:_(i)}),e++;continue}let s;if(s=ht.exec(i)){let o=s[1]||"",a=[];for(e++;e<n.length&&!/^```\s*$/.test(n[e]);)a.push(n[e]),e++;e++,t.push({t:"code",lang:o,v:a.join(`
|
|
4
|
+
`)});continue}if(ft.test(i)){t.push({t:"rule"}),e++;continue}if(s=gt.exec(i)){let o=Math.min(tt,s[1].length);t.push({t:"heading",level:o,c:_(s[2])}),e++;continue}if(F.test(i)&&r<3){let o=[];for(;e<n.length&&(s=F.exec(n[e]));)o.push(s[1]??""),e++;let a=o.findIndex(c=>c.trim()!==""),d=a>=0?bt.exec(o[a].trim()):null;if(d){let c=ut[d[1].toUpperCase()];t.push({t:"panel",kind:c,c:D(o.slice(a+1),r+1)})}else t.push({t:"quote",c:D(o,r+1)});continue}if(q.test(i)){let o=[];for(;e<n.length&&(s=q.exec(n[e]));)o.push({checked:s[1]!==" ",c:_(s[2])}),e++;t.push({t:"task",items:o});continue}if(V.test(i)){let o=[];for(;e<n.length&&!q.test(n[e])&&(s=V.exec(n[e]));)o.push([{t:"paragraph",c:_(s[1])}]),e++;t.push({t:"bullet",items:o});continue}if(s=H.exec(i)){let o=Math.max(1,parseInt(s[1],10)||1),a=[];for(;e<n.length&&(s=H.exec(n[e]));)a.push([{t:"paragraph",c:_(s[2])}]),e++;t.push({t:"ordered",start:o,items:a});continue}if(W.test(i)&&e+1<n.length&&mt.test(n[e+1])){let o=z(i).map(_);e+=2;let a=[];for(;e<n.length&&W.test(n[e]);)a.push(z(n[e]).map(_)),e++;t.push({t:"table",header:o,rows:a});continue}t.push({t:"paragraph",c:_(i)}),e++}return t}var yt=/^https?:\/\/[^\s<>()[\]]+/,vt=/^\[([^\]\n]{1,300})\]\((https?:\/\/[^\s)]{1,2000})\)/,_t=/[.,;:!?'"]+$/;function It(n,r){return r<=0?!0:/[\s([{"'“‘>:—–-]/.test(n[r-1])}function wt(n,r){return r>=n.length?!0:/[\s)\]}"'”’.,;:!?—–-]/.test(n[r])}function Tt(n,r,t){let e=r;for(;e<n.length;){let i=n.indexOf(t,e);if(i<0)return-1;let s=n[i-1],o=n[i+t.length],a=t.length===1&&(s===t||o===t);if(i>r&&s&&!/\s/.test(s)&&!a&&wt(n,i+t.length))return i;e=i+1}return-1}function _(n){let r=String(n??""),t=[],e="",i=()=>{e&&(t.push({t:"text",v:e}),e="")},s=0;for(;s<r.length;){let o=r[s];if(o==="`"){let a=1;for(;r[s+a]==="`";)a++;let d="`".repeat(a),c=r.indexOf(d,s+a);if(c>s+a-1&&c!==-1){let l=r.slice(s+a,c);if(l.trim()){i(),t.push({t:"code",v:l.length>1&&l.startsWith(" ")&&l.endsWith(" ")?l.slice(1,-1):l}),s=c+a;continue}}e+=d,s+=a;continue}if(o==="["){let a=vt.exec(r.slice(s));if(a){i(),t.push({t:"link",href:a[2],c:_(a[1])}),s+=a[0].length;continue}}if((o==="*"||o==="_"||o==="~")&&It(r,s)){let a=r[s+1]===o;if(o==="~"&&!a){e+=o,s++;continue}let d=a?o+o:o,c=s+d.length;if(c<r.length&&!/\s/.test(r[c])){let l=Tt(r,c,d);if(l>c){i();let u=_(r.slice(c,l));t.push(o==="~"?{t:"strike",c:u}:a?{t:"strong",c:u}:{t:"em",c:u}),s=l+d.length;continue}}}if(o==="h"&&(s===0||/[\s(<]/.test(r[s-1]))){let a=yt.exec(r.slice(s));if(a){let d=a[0],c=_t.exec(d);if(c&&(d=d.slice(0,-c[0].length)),d.length>8){i(),t.push({t:"link",href:d,c:[{t:"text",v:d}]}),s+=d.length;continue}}}e+=o,s++}return i(),t}function xt(n){return w([n]).replace(/\n$/,"").split(`
|
|
5
|
+
`).filter(r=>r!=="")}function jt(n){let r=[];return n.forEach((t,e)=>{e&&r.push({t:"text",v:" \xB7 "}),r.push(...t)}),r}function j(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function I(n){let r="";for(let t of n)switch(t.t){case"text":r+=j(t.v);break;case"br":r+="<br>";break;case"code":r+=`<code>${j(t.v)}</code>`;break;case"strong":r+=`<strong>${I(t.c)}</strong>`;break;case"em":r+=`<em>${I(t.c)}</em>`;break;case"strike":r+=`<s>${I(t.c)}</s>`;break;case"link":r+=`<a href="${j(t.href)}" target="_blank" rel="noopener noreferrer">${I(t.c)}</a>`;break}return r}function Nt(n){return n.length&&n[0].t==="text"&&/^ /.test(n[0].v)?[{t:"text",v:`\xA0${n[0].v.slice(1)}`},...n.slice(1)]:n}function E(n,r=!0){let t="";for(let e of n)switch(e.t){case"paragraph":t+=`<p>${I(Nt(e.c))}</p>`;break;case"heading":t+=`<h${e.level}>${I(e.c)}</h${e.level}>`;break;case"bullet":t+=`<ul>${e.items.map(i=>`<li>${E(i,!1)}</li>`).join("")}</ul>`;break;case"ordered":t+=`<ol${e.start!==1?` start="${e.start}"`:""}>${e.items.map(i=>`<li>${E(i,!1)}</li>`).join("")}</ol>`;break;case"task":t+=`<ul data-type="taskList">${e.items.map(i=>`<li data-type="taskItem" data-checked="${i.checked?"true":"false"}"><label><input type="checkbox"${i.checked?' checked="checked"':""}><span></span></label><div><p>${I(i.c)}</p></div></li>`).join("")}</ul>`;break;case"code":t+=`<pre><code${e.lang?` class="language-${j(e.lang)}"`:""}>${j(e.v)}</code></pre>`;break;case"quote":t+=`<blockquote>${E(e.c,!1)}</blockquote>`;break;case"panel":{if(!r){t+=xt(e).map(c=>`<p>${j(c)}</p>`).join("");break}let i=R[e.kind],s=e.c.flatMap(c=>c.t==="table"?[...c.header?[c.header]:[],...c.rows].map(l=>({t:"paragraph",c:jt(l)})):[c]),[o,...a]=s,d=o&&o.t==="heading"?[{...o,c:[{t:"text",v:`${i.icon} `},...o.c]},...a]:s;t+=`<table><tbody><tr><td data-background-color="${i.bg}" style="background-color: ${i.bg}">${E(d,!1)||"<p></p>"}</td></tr></tbody></table>`;break}case"rule":t+="<hr>";break;case"table":{let i="<table><tbody>";e.header&&(i+=`<tr>${e.header.map(s=>`<th><p>${I(s)}</p></th>`).join("")}</tr>`);for(let s of e.rows)i+=`<tr>${s.map(o=>`<td><p>${I(o)}</p></td>`).join("")}</tr>`;t+=`${i}</tbody></table>`;break}}return t}function nt(n){try{return E(et(n))||`<p>${j(String(n??""))}</p>`}catch{return String(n??"").split(`
|
|
6
|
+
`).map(r=>`<p>${j(r)}</p>`).join("")}}function x(n){let r="";for(let t of n)switch(t.t){case"text":r+=t.v;break;case"br":r+=`
|
|
7
|
+
`;break;case"code":r+=`\`${t.v}\``;break;case"strong":r+=`**${x(t.c)}**`;break;case"em":r+=`_${x(t.c)}_`;break;case"strike":r+=`~~${x(t.c)}~~`;break;case"link":{let e=x(t.c);r+=!e||e===t.href?t.href:`[${e}](${t.href})`;break}}return r}function w(n){let r="",t=!1;for(let e of n){let i=e.t==="quote"||e.t==="panel";switch(i&&t&&(r+=`
|
|
8
|
+
`),t=i,e.t){case"paragraph":r+=`${x(e.c)}
|
|
9
|
+
`;break;case"heading":r+=`${"#".repeat(Math.max(1,Math.min(tt,e.level)))} ${x(e.c)}
|
|
10
|
+
`;break;case"bullet":for(let s of e.items)r+=`- ${w(s).trim()}
|
|
11
|
+
`;break;case"ordered":e.items.forEach((s,o)=>{r+=`${e.start+o}. ${w(s).trim()}
|
|
12
|
+
`});break;case"task":for(let s of e.items)r+=`- [${s.checked?"x":" "}] ${x(s.c)}
|
|
13
|
+
`;break;case"code":r+=`\`\`\`${e.lang}
|
|
14
|
+
${e.v}
|
|
13
15
|
\`\`\`
|
|
14
|
-
`;break;case"quote":
|
|
15
|
-
${
|
|
16
|
-
`;break;case"table":{let
|
|
17
|
-
`;
|
|
18
|
-
`);for(let
|
|
19
|
-
`).map(
|
|
16
|
+
`;break;case"quote":r+=X(w(e.c));break;case"panel":r+=`> [!${dt[e.kind]}]
|
|
17
|
+
${X(w(e.c))}`;break;case"rule":r+=`---
|
|
18
|
+
`;break;case"table":{let s=o=>`| ${o.map(a=>x(a).replace(/\|/g,"\\|")).join(" | ")} |
|
|
19
|
+
`;e.header&&(r+=s(e.header)+`|${e.header.map(()=>" --- |").join("")}
|
|
20
|
+
`);for(let o of e.rows)r+=s(o);break}}}return r}function At(n){return n.replace(/^\n+/,"").replace(/\s+$/,"")}function X(n){return n.replace(/\n$/,"").split(`
|
|
21
|
+
`).map(r=>r?`> ${r}`:">").join(`
|
|
20
22
|
`)+`
|
|
21
|
-
`}var Tt={amp:"&",lt:"<",gt:">",quot:'"',apos:"'",nbsp:"\xA0",hellip:"\u2026",mdash:"\u2014",ndash:"\u2013",lsquo:"\u2018",rsquo:"\u2019",ldquo:"\u201C",rdquo:"\u201D",copy:"\xA9",reg:"\xAE",trade:"\u2122"};function X(n){return n.replace(/&(#x[0-9a-f]+|#\d+|[a-z]+);/gi,(e,t)=>{if(t[0]==="#"){let i=t[1]==="x"||t[1]==="X"?parseInt(t.slice(2),16):parseInt(t.slice(1),10);return Number.isFinite(i)&&i>0&&i<1114112?String.fromCodePoint(i):e}let r=Tt[t.toLowerCase()];return r===void 0?e:r})}function xt(n){let e=[],t=/<!--[\s\S]*?-->|<\/([A-Za-z][\w:-]*)\s*>|<([A-Za-z][\w:-]*)((?:\s+[^\s=>/]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?)*)\s*(\/?)>|([^<]+)|(<)/g,r;for(;r=t.exec(n);)if(r[1])e.push({kind:"close",name:r[1].toLowerCase()});else if(r[2]){let i={},s=/([^\s=>/]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+)))?/g,a;for(;a=s.exec(r[3]||"");)i[a[1].toLowerCase()]=X(a[2]??a[3]??a[4]??"");let o=r[2].toLowerCase();e.push({kind:"open",name:o,attrs:i,selfClose:!!r[4]||o==="br"||o==="hr"||o==="img"||o==="input"})}else r[5]!==void 0?e.push({kind:"text",v:X(r[5])}):r[6]&&e.push({kind:"text",v:"<"});return e}var Y=new Set(["p","div","h1","h2","h3","h4","h5","h6","ul","ol","li","blockquote","pre","hr","table","thead","tbody","tfoot","tr","td","th","section","article","header","footer","details","summary","figure","figcaption"]),jt=new Set(["script","style","label","input","button","svg","head","title"]);function A(n){let e=[],t=0,r=[],i=[],s=c=>{let l=At(r);r=[],l.length&&e.push(c?c(l):{t:"paragraph",c:l})},a=c=>{if(!c)return;let l={t:"text",v:c};for(let u=i.length-1;u>=0;u--){let p=i[u];p==="strong"?l={t:"strong",c:[l]}:p==="em"?l={t:"em",c:[l]}:p==="strike"?l={t:"strike",c:[l]}:l={t:"link",href:p.link,c:[l]}}r.push(l)},o=c=>{let l=[],u=1;for(;t<n.length;){let p=n[t++];if(p.kind==="open"&&p.name===c&&!p.selfClose&&u++,p.kind==="close"&&p.name===c&&(u--,u===0))break;l.push(p)}return l},d=c=>c.filter(l=>l.kind==="text").map(l=>l.v).join("");for(;t<n.length;){let c=n[t++];if(c.kind==="text"){a(c.v.replace(/\s+/g," "));continue}if(c.kind==="close"){if(c.name==="strong"||c.name==="b")q(i,"strong");else if(c.name==="em"||c.name==="i")q(i,"em");else if(c.name==="s"||c.name==="del"||c.name==="strike")q(i,"strike");else if(c.name==="a"){let u=i.map(p=>typeof p=="object").lastIndexOf(!0);u>=0&&i.splice(u,1)}else Y.has(c.name)&&s();continue}let l=c.name;if(jt.has(l)){c.selfClose||o(l);continue}if(l==="br"){r.push({t:"br"});continue}if(l==="hr"){s(),e.push({t:"rule"});continue}if(l==="strong"||l==="b"){i.push("strong");continue}if(l==="em"||l==="i"){i.push("em");continue}if(l==="s"||l==="del"||l==="strike"){i.push("strike");continue}if(l==="a"){c.attrs.href?i.push({link:c.attrs.href}):i.push({link:""});continue}if(l==="code"){let u=d(o("code"));u&&r.push({t:"code",v:u});continue}if(l==="pre"){s();let u=o("pre"),p=u.find(_=>_.kind==="open"&&_.name==="code"),y=p&&/language-([\w+.-]+)/.exec(p.attrs.class||"")?.[1]||"";e.push({t:"code",lang:y,v:d(u).replace(/\n$/,"")});continue}if(/^h[1-6]$/.test(l)){s();let u=Number(l[1]),p=A(o(l));e.push({t:"heading",level:u,c:f(w(p).trim().replace(/\n+/g," "))});continue}if(l==="blockquote"){s(),e.push({t:"quote",c:A(o(l))});continue}if(l==="ul"||l==="ol"){s();let u=o(l),p=(c.attrs["data-type"]||"")==="tasklist",y=[],_=[],T=0;for(;T<u.length;){let h=u[T++];if(h.kind==="open"&&h.name==="li"){let b=[],x=1;for(;T<u.length;){let g=u[T++];if(g.kind==="open"&&g.name==="li"&&!g.selfClose&&x++,g.kind==="close"&&g.name==="li"&&(x--,x===0))break;b.push(g)}y.push(b);let j=(h.attrs["data-checked"]||"")==="true"||b.some(g=>g.kind==="open"&&g.name==="input"&&"checked"in g.attrs);_.push(j)}}p||y.some(h=>h.some(b=>b.kind==="open"&&b.name==="input"&&(b.attrs.type||"")==="checkbox"))?e.push({t:"task",items:y.map((h,b)=>({checked:_[b],c:f(w(A(h)).trim().replace(/\n+/g," "))}))}):l==="ul"?e.push({t:"bullet",items:y.map(h=>Z(A(h)))}):e.push({t:"ordered",start:Math.max(1,parseInt(c.attrs.start||"1",10)||1),items:y.map(h=>Z(A(h)))});continue}if(l==="table"){s();let u=o("table"),p=[],y=[],_=0;for(;_<u.length;){let P=u[_++];if(P.kind==="open"&&P.name==="tr"){let h=[],b=!0,x=1,j=[];for(;_<u.length;){let m=u[_++];if(m.kind==="open"&&m.name==="tr"&&!m.selfClose&&x++,m.kind==="close"&&m.name==="tr"&&(x--,x===0))break;j.push(m)}let g=0;for(;g<j.length;){let m=j[g++];if(m.kind==="open"&&(m.name==="td"||m.name==="th")){m.name!=="th"&&(b=!1);let G=[],M=1;for(;g<j.length;){let $=j[g++];if($.kind==="open"&&$.name===m.name&&!$.selfClose&&M++,$.kind==="close"&&$.name===m.name&&(M--,M===0))break;G.push($)}h.push(f(w(A(G)).trim().replace(/\n+/g," ")))}}h.length&&(p.push(h),y.push(b))}}let T=p.length&&y[0]?p[0]:null;e.push({t:"table",header:T,rows:p.slice(T?1:0)});continue}if(Y.has(l)){s();continue}}return s(),e}function q(n,e){let t=n.lastIndexOf(e);t>=0&&n.splice(t,1)}function Z(n){return n.length?n:[{t:"paragraph",c:[]}]}function At(n){let e=[...n];for(;e.length&&e[0].t==="text"&&!e[0].v.trim();)e.shift();for(;e.length&&e[e.length-1].t==="text"&&!e[e.length-1].v.trim();)e.pop();e.length&&e[0].t==="text"&&(e[0]={t:"text",v:e[0].v.replace(/^\s+/," ")});let t=e.length-1;return t>=0&&e[t].t==="text"&&(e[t]={t:"text",v:e[t].v.replace(/\s+$/,"")}),e}function Nt(n){try{let e=String(n??"");return/<[a-z][\s\S]*>/i.test(e)?A(xt(e)):tt(e)}catch{return[]}}function nt(n){try{return wt(w(Nt(n)))}catch{return""}}import{fileURLToPath as Ct}from"url";import{dirname as Pt,resolve as Mt}from"path";var rt=Object.freeze({SENTRY:"sentry",JIRA:"jira",GITHUB:"github",GITLAB:"gitlab",SLACK:"slack",LARK:"lark",LARK_DOCS:"lark_docs",OPENAI_BILLING:"openai_billing",ANTHROPIC_BILLING:"anthropic_billing",CURSOR_ADMIN:"cursor_admin",NOTION:"notion",GOOGLE:"google",PLANE:"plane",LINEAR:"linear",VIKUNJA:"vikunja",FIGMA:"figma",HUBSPOT:"hubspot",OPEN_DESIGN:"open_design",LINKEDIN_PERSONAL:"linkedin_personal",LINKEDIN_BUSINESS:"linkedin_business",DISCORD:"discord"}),Dt=Object.freeze({sentry:{id:"sentry",name:"Sentry",connectPath:"/integrations?provider=sentry"},jira:{id:"jira",name:"Jira",connectPath:"/integrations?provider=jira"},github:{id:"github",name:"GitHub",connectPath:"/integrations?provider=github"},gitlab:{id:"gitlab",name:"GitLab",connectPath:"/integrations?provider=gitlab"},slack:{id:"slack",name:"Slack",connectPath:"/integrations?provider=slack"},lark:{id:"lark",name:"Lark Chat",connectPath:"/integrations?provider=lark"},lark_docs:{id:"lark_docs",name:"Lark App",connectPath:"/integrations?provider=lark_docs"},openai_billing:{id:"openai_billing",name:"OpenAI Admin",connectPath:"/integrations?provider=openai_billing"},anthropic_billing:{id:"anthropic_billing",name:"Anthropic Admin",connectPath:"/integrations?provider=anthropic_billing"},cursor_admin:{id:"cursor_admin",name:"Cursor Admin",connectPath:"/integrations?provider=cursor_admin"},notion:{id:"notion",name:"Notion",connectPath:"/integrations?provider=notion"},google:{id:"google",name:"Google Docs",connectPath:"/integrations?provider=google"},plane:{id:"plane",name:"Plane",connectPath:"/integrations?provider=plane"},linear:{id:"linear",name:"Linear",connectPath:"/integrations?provider=linear"},vikunja:{id:"vikunja",name:"Vikunja",connectPath:"/integrations?provider=vikunja"},figma:{id:"figma",name:"Figma",connectPath:"/integrations?provider=figma"},hubspot:{id:"hubspot",name:"HubSpot",connectPath:"/integrations?provider=hubspot"},open_design:{id:"open_design",name:"OpenDesign",connectPath:"/integrations?provider=open_design"},linkedin_personal:{id:"linkedin_personal",name:"LinkedIn (Personal)",connectPath:"/integrations?provider=linkedin_personal"},linkedin_business:{id:"linkedin_business",name:"LinkedIn (Business)",connectPath:"/integrations?provider=linkedin_business"},discord:{id:"discord",name:"Discord",connectPath:"/integrations?provider=discord"}});import{resolveIntegrationToken as Ut}from"@zibby/core/backend-client.js";var O={api:{knob:"SKILL_API_TIMEOUT_MS",fallback:3e4},transfer:{knob:"SKILL_TRANSFER_TIMEOUT_MS",fallback:12e4},job:{knob:"SKILL_JOB_TIMEOUT_MS",fallback:3e5}};function St(n,e,t=process.env){let r=Number(t?.[n]);return Number.isFinite(r)&&r>0?Math.min(6e5,Math.max(1e3,Math.floor(r))):e}function $t(n="api",e=process.env){let t=O[n]||O.api;return St(t.knob,t.fallback,e)}function Et(n){return n?.name==="TimeoutError"||n?.name==="AbortError"}function Lt(n){try{return new URL(String(n?.url??n)).host||"unknown host"}catch{return"unknown host"}}function Ot(n,e){if(!n)return e;let t=new AbortController,r=a=>{t.signal.aborted||t.abort(a)},i=()=>r(n.reason),s=()=>r(e.reason);return t.signal.addEventListener("abort",()=>{n.removeEventListener("abort",i),e.removeEventListener("abort",s)},{once:!0}),n.aborted?r(n.reason):e.aborted?r(e.reason):(n.addEventListener("abort",i,{once:!0}),e.addEventListener("abort",s,{once:!0})),t.signal}async function it(n,e={},t={}){let r=t.kind||"api",i=(O[r]||O.api).knob,s=t.timeoutMs?Math.min(6e5,Math.max(1e3,Math.floor(t.timeoutMs))):$t(r),a=e?.signal;if(a?.aborted)throw a.reason??new DOMException("This operation was aborted","AbortError");let o=AbortSignal.timeout(s),d=Ot(a,o);try{return await fetch(n,{...e,signal:d})}catch(c){throw o.aborted&&Et(c)?new Error(`${t.what||"request"} TIMED OUT after ${s}ms against ${Lt(n)} (${i})`):c}}function qt(){if(process.env.MCP_SKILL_PATH)return process.env.MCP_SKILL_PATH;let n=Pt(Ct(import.meta.url)),e=Mt(n,"..","bin","mcp-skill.mjs");return Rt(e)?e:null}function st(n){return String(n||"").trim().replace(/\/+$/,"").replace(/\/api\/v1$/,"")}var S=null;async function L(){if(S)return S;let n=st(process.env.VIKUNJA_URL),e=(process.env.VIKUNJA_TOKEN||"").trim();try{let t=await Ut("vikunja"),r=String(t?.token||"").trim(),i=st(t?.instanceUrl);if(r&&i)return S={origin:i,token:r},S;if(r&&!i)throw new Error("The connected Vikunja integration has no instance URL \u2014 reconnect it in Integrations \u2192 Vikunja.")}catch(t){if(!(n&&e))throw t}if(!(n&&e))throw new Error("No Vikunja credentials. Connect the board under Integrations \u2192 Vikunja (instance URL + an API token minted in the board's Settings \u2192 API Tokens).");return S={origin:n,token:e},S}function Yt(){S=null}async function k(n,e,t={}){let{origin:r,token:i}=await L(),s=`${r}/api/v1${e}`;if(t.query&&Object.keys(t.query).length){let d=new URLSearchParams;for(let[l,u]of Object.entries(t.query))u!=null&&u!==""&&d.set(l,String(u));let c=d.toString();c&&(s+=`?${c}`)}let a=await it(s,{method:n,headers:{Authorization:`Bearer ${i}`,...t.body?{"Content-Type":"application/json"}:{}},...t.body?{body:JSON.stringify(t.body)}:{}},{kind:"api",what:`Vikunja ${n} ${e}`}),o=await a.text();if(!a.ok)throw new Error(`Vikunja ${n} ${e} \u2192 ${a.status}: ${o.slice(0,300)}`);if(!o)return null;try{return JSON.parse(o)}catch{return o}}function ct(n){return typeof n!="string"||!n?"":nt(n)}function K(n){return et(n)}function ot(n){if(n==null||n==="")return null;if(typeof n=="number"&&Number.isFinite(n))return Math.max(0,Math.min(5,Math.round(n)));let e=String(n).trim().toLowerCase(),t={unset:0,none:0,low:1,medium:2,normal:2,high:3,urgent:4,now:5,critical:5,blocker:5,do_now:5,"do now":5};return Object.prototype.hasOwnProperty.call(t,e)?t[e]:null}function R(n,e){return n?{id:String(n.id),identifier:n.identifier||null,projectId:n.project_id??null,title:n.title||"",description:ct(n.description),done:!!n.done,priority:n.priority??0,labels:(Array.isArray(n.labels)?n.labels:[]).map(t=>t?.title).filter(Boolean),assignees:(Array.isArray(n.assignees)?n.assignees:[]).map(t=>t?.username).filter(Boolean),dueDate:n.due_date&&!String(n.due_date).startsWith("0001-")?n.due_date:null,url:e?`${e}/tasks/${n.id}`:void 0}:null}async function C(n,{create:e=!1}={}){let t=String(n||"").trim();if(!t)return null;let r=await k("GET","/labels",{query:{s:t}}),i=(Array.isArray(r)?r:[]).find(a=>(a?.title||"").trim().toLowerCase()===t.toLowerCase());return i?.id?i.id:e?(await k("PUT","/labels",{body:{title:t}}))?.id??null:null}async function at(n){let e=encodeURIComponent(String(n)),t=await k("GET",`/projects/${e}/views`),r=(Array.isArray(t)?t:[]).find(s=>s?.view_kind==="kanban");if(!r?.id)throw new Error(`Project ${n} has no kanban view \u2014 there are no columns to move between.`);let i=await k("GET",`/projects/${e}/views/${r.id}/buckets`);return{viewId:r.id,buckets:Array.isArray(i)?i:[]}}var Zt={id:"vikunja",serverName:"vikunja",allowedTools:["mcp__vikunja__*"],requiresIntegration:rt.VIKUNJA,callsBackend:!0,envKeys:["VIKUNJA_URL","VIKUNJA_TOKEN"],description:"Vikunja \u2014 kanban board: tasks, columns, labels, comments (API token)",promptFragment:`## Vikunja
|
|
23
|
+
`}var St={amp:"&",lt:"<",gt:">",quot:'"',apos:"'",nbsp:"\xA0",hellip:"\u2026",mdash:"\u2014",ndash:"\u2013",lsquo:"\u2018",rsquo:"\u2019",ldquo:"\u201C",rdquo:"\u201D",copy:"\xA9",reg:"\xAE",trade:"\u2122"};function Y(n){return n.replace(/&(#x[0-9a-f]+|#\d+|[a-z]+);/gi,(r,t)=>{if(t[0]==="#"){let i=t[1]==="x"||t[1]==="X"?parseInt(t.slice(2),16):parseInt(t.slice(1),10);return Number.isFinite(i)&&i>0&&i<1114112?String.fromCodePoint(i):r}let e=St[t.toLowerCase()];return e===void 0?r:e})}function $t(n){let r=[],t=/<!--[\s\S]*?-->|<\/([A-Za-z][\w:-]*)\s*>|<([A-Za-z][\w:-]*)((?:\s+[^\s=>/]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?)*)\s*(\/?)>|([^<]+)|(<)/g,e;for(;e=t.exec(n);)if(e[1])r.push({kind:"close",name:e[1].toLowerCase()});else if(e[2]){let i={},s=/([^\s=>/]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+)))?/g,o;for(;o=s.exec(e[3]||"");)i[o[1].toLowerCase()]=Y(o[2]??o[3]??o[4]??"");let a=e[2].toLowerCase();r.push({kind:"open",name:a,attrs:i,selfClose:!!e[4]||a==="br"||a==="hr"||a==="img"||a==="input"})}else e[5]!==void 0?r.push({kind:"text",v:Y(e[5])}):e[6]&&r.push({kind:"text",v:"<"});return r}var Z=new Set(["p","div","h1","h2","h3","h4","h5","h6","ul","ol","li","blockquote","pre","hr","table","thead","tbody","tfoot","tr","td","th","section","article","header","footer","details","summary","figure","figcaption"]),Et=new Set(["script","style","label","input","button","svg","head","title"]);function T(n){let r=[],t=0,e=[],i=[],s=c=>{let l=Lt(e);e=[],l.length&&r.push(c?c(l):{t:"paragraph",c:l})},o=c=>{if(!c)return;let l={t:"text",v:c};for(let u=i.length-1;u>=0;u--){let k=i[u];k==="strong"?l={t:"strong",c:[l]}:k==="em"?l={t:"em",c:[l]}:k==="strike"?l={t:"strike",c:[l]}:l={t:"link",href:k.link,c:[l]}}e.push(l)},a=c=>{let l=[],u=1;for(;t<n.length;){let k=n[t++];if(k.kind==="open"&&k.name===c&&!k.selfClose&&u++,k.kind==="close"&&k.name===c&&(u--,u===0))break;l.push(k)}return l},d=c=>c.filter(l=>l.kind==="text").map(l=>l.v).join("");for(;t<n.length;){let c=n[t++];if(c.kind==="text"){o(c.v.replace(/\s+/g," "));continue}if(c.kind==="close"){if(c.name==="strong"||c.name==="b")K(i,"strong");else if(c.name==="em"||c.name==="i")K(i,"em");else if(c.name==="s"||c.name==="del"||c.name==="strike")K(i,"strike");else if(c.name==="a"){let u=i.map(k=>typeof k=="object").lastIndexOf(!0);u>=0&&i.splice(u,1)}else Z.has(c.name)&&s();continue}let l=c.name;if(Et.has(l)){c.selfClose||a(l);continue}if(l==="br"){e.push({t:"br"});continue}if(l==="hr"){s(),r.push({t:"rule"});continue}if(l==="strong"||l==="b"){i.push("strong");continue}if(l==="em"||l==="i"){i.push("em");continue}if(l==="s"||l==="del"||l==="strike"){i.push("strike");continue}if(l==="a"){c.attrs.href?i.push({link:c.attrs.href}):i.push({link:""});continue}if(l==="code"){let u=d(a("code"));u&&e.push({t:"code",v:u});continue}if(l==="pre"){s();let u=a("pre"),k=u.find(b=>b.kind==="open"&&b.name==="code"),p=k&&/language-([\w+.-]+)/.exec(k.attrs.class||"")?.[1]||"";r.push({t:"code",lang:p,v:d(u).replace(/\n$/,"")});continue}if(/^h[1-6]$/.test(l)){s();let u=Number(l[1]),k=T(a(l));r.push({t:"heading",level:u,c:_(w(k).trim().replace(/\n+/g," "))});continue}if(l==="blockquote"){s(),r.push({t:"quote",c:T(a(l))});continue}if(l==="ul"||l==="ol"){s();let u=a(l),k=(c.attrs["data-type"]||"")==="tasklist",p=[],b=[],f=0;for(;f<u.length;){let m=u[f++];if(m.kind==="open"&&m.name==="li"){let y=[],A=1;for(;f<u.length;){let g=u[f++];if(g.kind==="open"&&g.name==="li"&&!g.selfClose&&A++,g.kind==="close"&&g.name==="li"&&(A--,A===0))break;y.push(g)}p.push(y);let $=(m.attrs["data-checked"]||"")==="true"||y.some(g=>g.kind==="open"&&g.name==="input"&&"checked"in g.attrs);b.push($)}}k||p.some(m=>m.some(y=>y.kind==="open"&&y.name==="input"&&(y.attrs.type||"")==="checkbox"))?r.push({t:"task",items:p.map((m,y)=>({checked:b[y],c:_(w(T(m)).trim().replace(/\n+/g," "))}))}):l==="ul"?r.push({t:"bullet",items:p.map(m=>Q(T(m)))}):r.push({t:"ordered",start:Math.max(1,parseInt(c.attrs.start||"1",10)||1),items:p.map(m=>Q(T(m)))});continue}if(l==="table"){s();let u=a("table"),k=Ot(u);if(k){r.push(k);continue}let p=[],b=[],f=0;for(;f<u.length;){let m=u[f++];if(m.kind==="open"&&m.name==="tr"){let y=[],A=!0,$=1,g=[];for(;f<u.length;){let v=u[f++];if(v.kind==="open"&&v.name==="tr"&&!v.selfClose&&$++,v.kind==="close"&&v.name==="tr"&&($--,$===0))break;g.push(v)}let L=0;for(;L<g.length;){let v=g[L++];if(v.kind==="open"&&(v.name==="td"||v.name==="th")){v.name!=="th"&&(A=!1);let J=[],B=1;for(;L<g.length;){let S=g[L++];if(S.kind==="open"&&S.name===v.name&&!S.selfClose&&B++,S.kind==="close"&&S.name===v.name&&(B--,B===0))break;J.push(S)}y.push(_(w(T(J)).trim().replace(/\n+/g," ")))}}y.length&&(p.push(y),b.push(A))}}let U=p.length&&b[0]?p[0]:null;r.push({t:"table",header:U,rows:p.slice(U?1:0)});continue}if(Z.has(l)){s();continue}}return s(),r}function Ot(n){let r=n.filter(p=>p.kind==="open"),t=r.filter(p=>p.name==="tr"),e=r.filter(p=>p.name==="td"||p.name==="th");if(t.length!==1||e.length!==1||r.some(p=>p.name==="table"))return null;let i=e[0],s=i.attrs["data-background-color"]||/background-color\s*:\s*([^;]+)/i.exec(i.attrs.style||"")?.[1]||"",o=/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})/i.exec(s);if(!o)return null;let a=pt.find(p=>R[p].rgb.every((b,f)=>b===Number(o[f+1])));if(!a)return null;let d=n.indexOf(i)+1,c=1,l=d;for(;l<n.length;l++){let p=n[l];if(p.kind==="open"&&p.name===i.name&&!p.selfClose&&c++,p.kind==="close"&&p.name===i.name&&--c===0)break}let u=T(n.slice(d,l)),k=u[0];if(k&&k.t==="heading"&&k.c[0]?.t==="text"){let p=R[a].icon.replace(/\ufe0f$/,""),b=k.c[0].v;if(b.startsWith(p)){let f=b.slice(p.length).replace(/^\ufe0f/,"").replace(/^\s+/,"");u[0]={...k,c:f?[{t:"text",v:f},...k.c.slice(1)]:k.c.slice(1)}}}return{t:"panel",kind:a,c:u}}function K(n,r){let t=n.lastIndexOf(r);t>=0&&n.splice(t,1)}function Q(n){return n.length?n:[{t:"paragraph",c:[]}]}function Lt(n){let r=[...n];for(;r.length&&r[0].t==="text"&&!r[0].v.trim();)r.shift();for(;r.length&&r[r.length-1].t==="text"&&!r[r.length-1].v.trim();)r.pop();r.length&&r[0].t==="text"&&(r[0]={t:"text",v:r[0].v.replace(/^\s+/," ")});let t=r.length-1;return t>=0&&r[t].t==="text"&&(r[t]={t:"text",v:r[t].v.replace(/\s+$/,"")}),r}function Rt(n){try{let r=String(n??"");return/<[a-z][\s\S]*>/i.test(r)?T($t(r)):et(r)}catch{return[]}}function rt(n){try{return At(w(Rt(n)))}catch{return""}}import{fileURLToPath as Kt}from"url";import{dirname as Dt,resolve as Gt}from"path";var it=Object.freeze({SENTRY:"sentry",JIRA:"jira",GITHUB:"github",GITLAB:"gitlab",SLACK:"slack",LARK:"lark",LARK_DOCS:"lark_docs",OPENAI_BILLING:"openai_billing",ANTHROPIC_BILLING:"anthropic_billing",CURSOR_ADMIN:"cursor_admin",NOTION:"notion",GOOGLE:"google",PLANE:"plane",LINEAR:"linear",VIKUNJA:"vikunja",FIGMA:"figma",HUBSPOT:"hubspot",OPEN_DESIGN:"open_design",LINKEDIN_PERSONAL:"linkedin_personal",LINKEDIN_BUSINESS:"linkedin_business",DISCORD:"discord"}),Ht=Object.freeze({sentry:{id:"sentry",name:"Sentry",connectPath:"/integrations?provider=sentry"},jira:{id:"jira",name:"Jira",connectPath:"/integrations?provider=jira"},github:{id:"github",name:"GitHub",connectPath:"/integrations?provider=github"},gitlab:{id:"gitlab",name:"GitLab",connectPath:"/integrations?provider=gitlab"},slack:{id:"slack",name:"Slack",connectPath:"/integrations?provider=slack"},lark:{id:"lark",name:"Lark Chat",connectPath:"/integrations?provider=lark"},lark_docs:{id:"lark_docs",name:"Lark App",connectPath:"/integrations?provider=lark_docs"},openai_billing:{id:"openai_billing",name:"OpenAI Admin",connectPath:"/integrations?provider=openai_billing"},anthropic_billing:{id:"anthropic_billing",name:"Anthropic Admin",connectPath:"/integrations?provider=anthropic_billing"},cursor_admin:{id:"cursor_admin",name:"Cursor Admin",connectPath:"/integrations?provider=cursor_admin"},notion:{id:"notion",name:"Notion",connectPath:"/integrations?provider=notion"},google:{id:"google",name:"Google Docs",connectPath:"/integrations?provider=google"},plane:{id:"plane",name:"Plane",connectPath:"/integrations?provider=plane"},linear:{id:"linear",name:"Linear",connectPath:"/integrations?provider=linear"},vikunja:{id:"vikunja",name:"Vikunja",connectPath:"/integrations?provider=vikunja"},figma:{id:"figma",name:"Figma",connectPath:"/integrations?provider=figma"},hubspot:{id:"hubspot",name:"HubSpot",connectPath:"/integrations?provider=hubspot"},open_design:{id:"open_design",name:"OpenDesign",connectPath:"/integrations?provider=open_design"},linkedin_personal:{id:"linkedin_personal",name:"LinkedIn (Personal)",connectPath:"/integrations?provider=linkedin_personal"},linkedin_business:{id:"linkedin_business",name:"LinkedIn (Business)",connectPath:"/integrations?provider=linkedin_business"},discord:{id:"discord",name:"Discord",connectPath:"/integrations?provider=discord"}});import{resolveIntegrationToken as Jt}from"@zibby/core/backend-client.js";var P={api:{knob:"SKILL_API_TIMEOUT_MS",fallback:3e4},transfer:{knob:"SKILL_TRANSFER_TIMEOUT_MS",fallback:12e4},job:{knob:"SKILL_JOB_TIMEOUT_MS",fallback:3e5}};function Pt(n,r,t=process.env){let e=Number(t?.[n]);return Number.isFinite(e)&&e>0?Math.min(6e5,Math.max(1e3,Math.floor(e))):r}function Ct(n="api",r=process.env){let t=P[n]||P.api;return Pt(t.knob,t.fallback,r)}function Mt(n){return n?.name==="TimeoutError"||n?.name==="AbortError"}function Ut(n){try{return new URL(String(n?.url??n)).host||"unknown host"}catch{return"unknown host"}}function Bt(n,r){if(!n)return r;let t=new AbortController,e=o=>{t.signal.aborted||t.abort(o)},i=()=>e(n.reason),s=()=>e(r.reason);return t.signal.addEventListener("abort",()=>{n.removeEventListener("abort",i),r.removeEventListener("abort",s)},{once:!0}),n.aborted?e(n.reason):r.aborted?e(r.reason):(n.addEventListener("abort",i,{once:!0}),r.addEventListener("abort",s,{once:!0})),t.signal}async function st(n,r={},t={}){let e=t.kind||"api",i=(P[e]||P.api).knob,s=t.timeoutMs?Math.min(6e5,Math.max(1e3,Math.floor(t.timeoutMs))):Ct(e),o=r?.signal;if(o?.aborted)throw o.reason??new DOMException("This operation was aborted","AbortError");let a=AbortSignal.timeout(s),d=Bt(o,a);try{return await fetch(n,{...r,signal:d})}catch(c){throw a.aborted&&Mt(c)?new Error(`${t.what||"request"} TIMED OUT after ${s}ms against ${Ut(n)} (${i})`):c}}function Ft(){if(process.env.MCP_SKILL_PATH)return process.env.MCP_SKILL_PATH;let n=Dt(Kt(import.meta.url)),r=Gt(n,"..","bin","mcp-skill.mjs");return qt(r)?r:null}function ot(n){return String(n||"").trim().replace(/\/+$/,"").replace(/\/api\/v1$/,"")}var N=null;async function O(){if(N)return N;let n=ot(process.env.VIKUNJA_URL),r=(process.env.VIKUNJA_TOKEN||"").trim();try{let t=await Jt("vikunja"),e=String(t?.token||"").trim(),i=ot(t?.instanceUrl);if(e&&i)return N={origin:i,token:e},N;if(e&&!i)throw new Error("The connected Vikunja integration has no instance URL \u2014 reconnect it in Integrations \u2192 Vikunja.")}catch(t){if(!(n&&r))throw t}if(!(n&&r))throw new Error("No Vikunja credentials. Connect the board under Integrations \u2192 Vikunja (instance URL + an API token minted in the board's Settings \u2192 API Tokens).");return N={origin:n,token:r},N}function re(){N=null}async function h(n,r,t={}){let{origin:e,token:i}=await O(),s=`${e}/api/v1${r}`;if(t.query&&Object.keys(t.query).length){let d=new URLSearchParams;for(let[l,u]of Object.entries(t.query))u!=null&&u!==""&&d.set(l,String(u));let c=d.toString();c&&(s+=`?${c}`)}let o=await st(s,{method:n,headers:{Authorization:`Bearer ${i}`,...t.body?{"Content-Type":"application/json"}:{}},...t.body?{body:JSON.stringify(t.body)}:{}},{kind:"api",what:`Vikunja ${n} ${r}`}),a=await o.text();if(!o.ok)throw new Error(`Vikunja ${n} ${r} \u2192 ${o.status}: ${a.slice(0,300)}`);if(!a)return null;try{return JSON.parse(a)}catch{return a}}function lt(n){return typeof n!="string"||!n?"":rt(n)}function G(n){return nt(n)}function at(n){if(n==null||n==="")return null;if(typeof n=="number"&&Number.isFinite(n))return Math.max(0,Math.min(5,Math.round(n)));let r=String(n).trim().toLowerCase(),t={unset:0,none:0,low:1,medium:2,normal:2,high:3,urgent:4,now:5,critical:5,blocker:5,do_now:5,"do now":5};return Object.prototype.hasOwnProperty.call(t,r)?t[r]:null}function C(n,r){return n?{id:String(n.id),identifier:n.identifier||null,projectId:n.project_id??null,title:n.title||"",description:lt(n.description),done:!!n.done,priority:n.priority??0,labels:(Array.isArray(n.labels)?n.labels:[]).map(t=>t?.title).filter(Boolean),assignees:(Array.isArray(n.assignees)?n.assignees:[]).map(t=>t?.username).filter(Boolean),dueDate:n.due_date&&!String(n.due_date).startsWith("0001-")?n.due_date:null,url:r?`${r}/tasks/${n.id}`:void 0}:null}async function M(n,{create:r=!1}={}){let t=String(n||"").trim();if(!t)return null;let e=await h("GET","/labels",{query:{s:t}}),i=(Array.isArray(e)?e:[]).find(o=>(o?.title||"").trim().toLowerCase()===t.toLowerCase());return i?.id?i.id:r?(await h("PUT","/labels",{body:{title:t}}))?.id??null:null}async function ct(n){let r=encodeURIComponent(String(n)),t=await h("GET",`/projects/${r}/views`),e=(Array.isArray(t)?t:[]).find(s=>s?.view_kind==="kanban");if(!e?.id)throw new Error(`Project ${n} has no kanban view \u2014 there are no columns to move between.`);let i=await h("GET",`/projects/${r}/views/${e.id}/buckets`);return{viewId:e.id,buckets:Array.isArray(i)?i:[]}}var ie={id:"vikunja",serverName:"vikunja",allowedTools:["mcp__vikunja__*"],requiresIntegration:it.VIKUNJA,callsBackend:!0,envKeys:["VIKUNJA_URL","VIKUNJA_TOKEN"],description:"Vikunja \u2014 kanban board: tasks, columns, labels, comments (API token)",promptFragment:`## Vikunja
|
|
22
24
|
You can operate the user's Vikunja board directly. Tools:
|
|
23
25
|
|
|
24
26
|
### Discovery
|
|
@@ -39,4 +41,4 @@ You can operate the user's Vikunja board directly. Tools:
|
|
|
39
41
|
### Notes
|
|
40
42
|
- Address tasks by their NUMERIC id. The '#1' identifier shown in the UI is per-project and not unique.
|
|
41
43
|
- Descriptions may come back as plain text converted from HTML \u2014 that is expected.
|
|
42
|
-
- Priority accepts a number 0-5 or a word: low, medium, high, urgent, now.`,resolve(){let n={};for(let t of this.envKeys)process.env[t]&&(n[t]=process.env[t]);let
|
|
44
|
+
- Priority accepts a number 0-5 or a word: low, medium, high, urgent, now.`,resolve(){let n={};for(let t of this.envKeys)process.env[t]&&(n[t]=process.env[t]);let r=Ft();return r?{type:"stdio",command:"node",args:[r,"../dist/vikunja.js","vikunjaSkill"],env:n,description:this.description}:{command:null,args:[],env:n,description:this.description}},async handleToolCall(n,r){try{let t=r||{};switch(n){case"vikunja_list_projects":{let e=await h("GET","/projects"),i=(Array.isArray(e)?e:[]).map(s=>({id:String(s.id),title:s.title||"",description:lt(s.description)}));return JSON.stringify({count:i.length,projects:i})}case"vikunja_list_buckets":{let{viewId:e,buckets:i}=await ct(t.projectId);return JSON.stringify({viewId:e,count:i.length,buckets:i.map(s=>({id:s.id,title:s.title,taskCount:s.count??null}))})}case"vikunja_list_labels":{let e=await h("GET","/labels",{query:{s:t.search}}),i=(Array.isArray(e)?e:[]).map(s=>({id:s.id,title:s.title}));return JSON.stringify({count:i.length,labels:i})}case"vikunja_list_tasks":{let{origin:e}=await O(),i=[];if(t.label){let a=await M(t.label);if(!a)return JSON.stringify({count:0,tasks:[],note:`No label named "${t.label}" exists.`});i.push(`labels in ${a}`)}(t.done===!0||t.done===!1)&&i.push(`done = ${t.done}`);let s=await h("GET",`/projects/${encodeURIComponent(String(t.projectId))}/tasks`,{query:{...i.length?{filter:i.join(" && ")}:{},sort_by:"updated",order_by:"desc",per_page:Math.min(Number(t.limit)||25,50)}}),o=(Array.isArray(s)?s:[]).map(a=>C(a,e));return JSON.stringify({count:o.length,tasks:o})}case"vikunja_get_task":{let{origin:e}=await O(),i=await h("GET",`/tasks/${encodeURIComponent(String(t.taskId))}`);return JSON.stringify({task:C(i,e)})}case"vikunja_create_task":{let{origin:e}=await O(),i=at(t.priority),s=await h("PUT",`/projects/${encodeURIComponent(String(t.projectId))}/tasks`,{body:{title:t.title,...t.description?{description:G(t.description)}:{},...i!==null?{priority:i}:{},...t.dueDate?{due_date:t.dueDate}:{}}});if(!s?.id)throw new Error("Vikunja created no task (no id in the response)");let o=[];for(let d of Array.isArray(t.labels)?t.labels:[])try{let c=await M(d,{create:!0});c&&await h("PUT",`/tasks/${s.id}/labels`,{body:{label_id:c}})}catch(c){o.push(`${d}: ${c?.message||c}`)}let a=await h("GET",`/tasks/${s.id}`);return JSON.stringify({created:C(a||s,e),...o.length?{labelErrors:o}:{}})}case"vikunja_update_task":{let{origin:e}=await O(),i=encodeURIComponent(String(t.taskId)),s=await h("GET",`/tasks/${i}`);if(!s?.id)throw new Error(`No task ${t.taskId}`);let o=at(t.priority),a=await h("POST",`/tasks/${i}`,{body:{...s,...t.title!==void 0?{title:t.title}:{},...t.description!==void 0?{description:G(t.description)}:{},...o!==null?{priority:o}:{},...t.done!==void 0?{done:!!t.done}:{},...t.dueDate!==void 0?{due_date:t.dueDate}:{}}});return JSON.stringify({updated:C(a,e)})}case"vikunja_move_task":{let e=await h("GET",`/tasks/${encodeURIComponent(String(t.taskId))}`);if(!e?.id)throw new Error(`No task ${t.taskId}`);let i=t.projectId??e.project_id,s=String(t.column||"").trim().toLowerCase();if(!s)throw new Error("No target column given.");let{viewId:o,buckets:a}=await ct(i),d=a.find(c=>(c?.title||"").trim().toLowerCase()===s);return d?.id?(await h("POST",`/projects/${encodeURIComponent(String(i))}/views/${o}/buckets/${d.id}/tasks`,{body:{task_id:Number(e.id)}}),JSON.stringify({moved:!0,taskId:String(e.id),column:d.title})):JSON.stringify({moved:!1,error:`No column named "${t.column}".`,availableColumns:a.map(c=>c.title)})}case"vikunja_add_label":{let e=await M(t.label,{create:t.create!==!1});return e?(await h("PUT",`/tasks/${encodeURIComponent(String(t.taskId))}/labels`,{body:{label_id:e}}),JSON.stringify({ok:!0,taskId:String(t.taskId),label:t.label})):JSON.stringify({ok:!1,error:`No label named "${t.label}" and creating it was declined.`})}case"vikunja_remove_label":{let e=await M(t.label);return e?(await h("DELETE",`/tasks/${encodeURIComponent(String(t.taskId))}/labels/${e}`),JSON.stringify({ok:!0,taskId:String(t.taskId),label:t.label})):JSON.stringify({ok:!1,error:`No label named "${t.label}".`})}case"vikunja_add_comment":{let e=await h("PUT",`/tasks/${encodeURIComponent(String(t.taskId))}/comments`,{body:{comment:G(t.comment)}});return JSON.stringify({ok:!0,commentId:e?.id??null})}case"vikunja_assign":{let e=await h("GET","/users",{query:{s:t.username}}),i=(Array.isArray(e)?e:[]).find(s=>(s?.username||"").toLowerCase()===String(t.username||"").toLowerCase());return i?.id?(await h("PUT",`/tasks/${encodeURIComponent(String(t.taskId))}/assignees`,{body:{user_id:i.id}}),JSON.stringify({ok:!0,taskId:String(t.taskId),assignee:i.username})):JSON.stringify({ok:!1,error:`No user "${t.username}".`})}default:return JSON.stringify({error:`Unknown vikunja tool: ${n}`})}}catch(t){return JSON.stringify({error:t?.message||String(t)})}},tools:[{name:"vikunja_list_projects",description:"List Vikunja projects/boards (id, title). Everything else is project-scoped \u2014 start here when you do not already have a project id.",input_schema:{type:"object",properties:{}}},{name:"vikunja_list_buckets",description:"List a project's kanban COLUMNS (bucket id + title). Call this before moving a card so you use a column that exists.",input_schema:{type:"object",properties:{projectId:{type:"string",description:"Project id"}},required:["projectId"]}},{name:"vikunja_list_labels",description:"List labels (id, title). Optionally narrow with a search string.",input_schema:{type:"object",properties:{search:{type:"string",description:"Optional server-side search on the label title"}}}},{name:"vikunja_list_tasks",description:"List a project's tasks, newest-updated first. Optionally filter by label title and/or done-state.",input_schema:{type:"object",properties:{projectId:{type:"string",description:"Project id"},label:{type:"string",description:"Only tasks carrying this label title"},done:{type:"boolean",description:"Filter on completion state"},limit:{type:"number",description:"Max tasks (default 25, max 50)"}},required:["projectId"]}},{name:"vikunja_get_task",description:'Get one task by its NUMERIC id (the "#1" identifier shown in the UI is per-project and not unique).',input_schema:{type:"object",properties:{taskId:{type:"string",description:"Numeric task id"}},required:["taskId"]}},{name:"vikunja_create_task",description:"Create a task in a project. Labels are attached after creation and fail soft \u2014 the task survives a label error.",input_schema:{type:"object",properties:{projectId:{type:"string",description:"Project id"},title:{type:"string",description:"Task title"},description:{type:"string",description:"Task body. Markdown is rendered (headings, **bold**, `code`, lists, - [ ] tasks, links, tables, > quotes)."},priority:{type:"string",description:"A number 0-5 or a word: low, medium, high, urgent, now"},labels:{type:"array",items:{type:"string"},description:"Label titles; created if missing"},dueDate:{type:"string",description:"RFC3339 timestamp"}},required:["projectId","title"]}},{name:"vikunja_update_task",description:"Change a task's title, description, priority, due date, or done state. To move it to another COLUMN use vikunja_move_task \u2014 a column is not a field on the task.",input_schema:{type:"object",properties:{taskId:{type:"string",description:"Numeric task id"},title:{type:"string"},description:{type:"string"},priority:{type:"string",description:"A number 0-5 or a word: low, medium, high, urgent, now"},done:{type:"boolean"},dueDate:{type:"string",description:"RFC3339 timestamp"}},required:["taskId"]}},{name:"vikunja_move_task",description:`Move a card to a kanban COLUMN by name (e.g. "Doing"). Vikunja has no task.status: a column is a bucket on the project's kanban view, so this resolves the view and puts the task in the matching bucket. Returns the available column names when the name does not match.`,input_schema:{type:"object",properties:{taskId:{type:"string",description:"Numeric task id"},column:{type:"string",description:"Target column (bucket) title"},projectId:{type:"string",description:"Optional; defaults to the task's own project"}},required:["taskId","column"]}},{name:"vikunja_add_label",description:"Attach a label to a task by title. Creates the label when it does not exist (pass create=false to refuse instead).",input_schema:{type:"object",properties:{taskId:{type:"string",description:"Numeric task id"},label:{type:"string",description:"Label title"},create:{type:"boolean",description:"Create the label if missing (default true)"}},required:["taskId","label"]}},{name:"vikunja_remove_label",description:"Detach a label from a task by title.",input_schema:{type:"object",properties:{taskId:{type:"string",description:"Numeric task id"},label:{type:"string",description:"Label title"}},required:["taskId","label"]}},{name:"vikunja_add_comment",description:"Add a comment to a task.",input_schema:{type:"object",properties:{taskId:{type:"string",description:"Numeric task id"},comment:{type:"string",description:"Comment body. Markdown is rendered (headings, **bold**, `code`, lists, - [ ] tasks, links, tables, > quotes)."}},required:["taskId","comment"]}},{name:"vikunja_assign",description:"Assign a user to a task by username.",input_schema:{type:"object",properties:{taskId:{type:"string",description:"Numeric task id"},username:{type:"string",description:"Vikunja username"}},required:["taskId","username"]}}]};export{re as clearVikunjaCredsCache,ie as vikunjaSkill,lt as vkPlainText,at as vkPriority,G as vkRichHtml};
|