@whoz-oss/coday-server 0.114.0 → 0.114.2
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/package.json +1 -1
- package/server.js +7 -5
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -1235,17 +1235,19 @@ ${_}`}else this.interactor.debug(`[WORKTREE] Path does not exist, falling back t
|
|
|
1235
1235
|
approver_ids=None
|
|
1236
1236
|
approved=yes
|
|
1237
1237
|
approved=no
|
|
1238
|
-
page=2`}}},parse:JSON.parse,function:p}},m=({mergeRequestId:y,comment:x})=>f6e({mergeRequestId:y,comment:x,gitlabBaseUrl:i,gitlabApiToken:a,interactor:this.interactor}),h={type:"function",function:{name:`${this.name}__addGlobalComment`,description:"Add a global comment to a GitLab merge request. Use only when reviewing a merge request.",parameters:{type:"object",properties:{mergeRequestId:{type:"string",description:"GitLab merge request ID"},comment:{type:"string",description:"Comment to add"}}},parse:JSON.parse,function:m}},g=({mergeRequestId:y,base_sha:x,head_sha:_,start_sha:S,oldFilePath:A,newFilePath:$,comment:O,oldLineNumber:w,newLineNumber:k})=>d6e({mergeRequestId:y,base_sha:x,head_sha:_,start_sha:S,oldFilePath:A,newFilePath:$,comment:O,oldLineNumber:w,newLineNumber:k,gitlabBaseUrl:i,gitlabApiToken:a,interactor:this.interactor}),v={type:"function",function:{name:`${this.name}__addMRThread`,description:"Use only when reviewing a merge request. Add feedback to a specific change of file of a MR located at a specific line. The file is identified by its old file path and its new file path. The line of code is identified by its old line number and its new line number. For a new line, the old line number should be null and for removed line the new line number should null.",parameters:{type:"object",properties:{mergeRequestId:{type:"string",description:"GitLab merge request ID"},base_sha:{type:"string",description:"Base SHA of the merge request"},head_sha:{type:"string",description:"Head SHA of the merge request"},start_sha:{type:"string",description:"Start SHA of the merge request"},oldFilePath:{type:"string",description:"Path of the file before changes"},newFilePath:{type:"string",description:"Path of the file after changes"},comment:{type:"string",description:"Comment to add to the merge request"},oldLineNumber:{type:["number","null"],description:"Line number in the old file (use null if the line is new)"},newLineNumber:{type:["number","null"],description:"Line number in the new file (use null if the line is removed)"}}},parse:JSON.parse,function:g}};return t.push(s),t.push(d),t.push(u),t.push(f),t.push(h),t.push(v),t}};var M9e=ur(F9e(),1),L9e=new M9e.default({headingStyle:"atx",codeBlockStyle:"fenced",bulletListMarker:"-"});L9e.remove(["script","style","nav","footer"]);async function K8t(r,e=2e3){return new Promise((t,n)=>{let i=setTimeout(()=>{n(new Error(`HTML to Markdown conversion timed out after ${e}ms (possible ReDoS attack)`))},e);try{let a=L9e.turndown(r);clearTimeout(i),t(a)}catch(a){clearTimeout(i),n(a)}})}async function q9e(r,e,t,n,i){if(!e||!t||!n)throw new Error("Confluence integration incorrectly set");try{let a=await rr.get(`${e}/wiki/api/v2/pages/${r}?body-format=view`,{auth:{username:n,password:t}}),o=a.data.body?.view?.value||"";if(!o)return`No content found for Confluence page ${r}`;let s;try{s=await K8t(o,2e3)}catch(
|
|
1238
|
+
page=2`}}},parse:JSON.parse,function:p}},m=({mergeRequestId:y,comment:x})=>f6e({mergeRequestId:y,comment:x,gitlabBaseUrl:i,gitlabApiToken:a,interactor:this.interactor}),h={type:"function",function:{name:`${this.name}__addGlobalComment`,description:"Add a global comment to a GitLab merge request. Use only when reviewing a merge request.",parameters:{type:"object",properties:{mergeRequestId:{type:"string",description:"GitLab merge request ID"},comment:{type:"string",description:"Comment to add"}}},parse:JSON.parse,function:m}},g=({mergeRequestId:y,base_sha:x,head_sha:_,start_sha:S,oldFilePath:A,newFilePath:$,comment:O,oldLineNumber:w,newLineNumber:k})=>d6e({mergeRequestId:y,base_sha:x,head_sha:_,start_sha:S,oldFilePath:A,newFilePath:$,comment:O,oldLineNumber:w,newLineNumber:k,gitlabBaseUrl:i,gitlabApiToken:a,interactor:this.interactor}),v={type:"function",function:{name:`${this.name}__addMRThread`,description:"Use only when reviewing a merge request. Add feedback to a specific change of file of a MR located at a specific line. The file is identified by its old file path and its new file path. The line of code is identified by its old line number and its new line number. For a new line, the old line number should be null and for removed line the new line number should null.",parameters:{type:"object",properties:{mergeRequestId:{type:"string",description:"GitLab merge request ID"},base_sha:{type:"string",description:"Base SHA of the merge request"},head_sha:{type:"string",description:"Head SHA of the merge request"},start_sha:{type:"string",description:"Start SHA of the merge request"},oldFilePath:{type:"string",description:"Path of the file before changes"},newFilePath:{type:"string",description:"Path of the file after changes"},comment:{type:"string",description:"Comment to add to the merge request"},oldLineNumber:{type:["number","null"],description:"Line number in the old file (use null if the line is new)"},newLineNumber:{type:["number","null"],description:"Line number in the new file (use null if the line is removed)"}}},parse:JSON.parse,function:g}};return t.push(s),t.push(d),t.push(u),t.push(f),t.push(h),t.push(v),t}};var M9e=ur(F9e(),1),L9e=new M9e.default({headingStyle:"atx",codeBlockStyle:"fenced",bulletListMarker:"-"});L9e.remove(["script","style","nav","footer"]);async function K8t(r,e=2e3){return new Promise((t,n)=>{let i=setTimeout(()=>{n(new Error(`HTML to Markdown conversion timed out after ${e}ms (possible ReDoS attack)`))},e);try{let a=L9e.turndown(r);clearTimeout(i),t(a)}catch(a){clearTimeout(i),n(a)}})}async function q9e(r,e,t,n,i){if(!e||!t||!n)throw new Error("Confluence integration incorrectly set");try{let a=await rr.get(`${e}/wiki/api/v2/pages/${r}?body-format=view&include-properties=true&include-version=true`,{auth:{username:n,password:t}}),o=a.data.body?.view?.value||"";if(!o)return`No content found for Confluence page ${r}`;let s;try{s=await K8t(o,2e3)}catch(_){i.warn(`HTML conversion failed or timed out: ${_.message}`);let S=o.replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim();return`# Confluence Page ${r} (conversion failed)
|
|
1239
1239
|
|
|
1240
1240
|
**Note:** HTML to Markdown conversion failed. Showing plain text instead.
|
|
1241
1241
|
|
|
1242
|
-
${
|
|
1242
|
+
${S.substring(0,1e4)}...`}let c=a.data.title||"Untitled",u=`${e}/wiki/pages/${r}`,l=a.data.version,f=l?.number,p=l?.createdAt,d=a.data.createdAt,g=(a.data.properties?.results??[]).find(_=>_.key==="page-status")?.value?.label,v=[];g&&v.push(`**Status:** ${g}`),f!==void 0&&v.push(`**Version:** ${f}`),p&&v.push(`**Last modified:** ${p}`),d&&v.push(`**Created:** ${d}`);let y=v.length>0?`${v.join(`
|
|
1243
|
+
`)}
|
|
1243
1244
|
|
|
1244
|
-
|
|
1245
|
+
`:"",x=`# ${c}
|
|
1245
1246
|
|
|
1246
|
-
|
|
1247
|
+
**Source:** [${u}](${u})
|
|
1248
|
+
${y}---
|
|
1247
1249
|
|
|
1248
|
-
${s}`;return i.debug(`\u2713 Successfully converted Confluence page to Markdown, from ${o?.length} to ${l.length} chars.`),l}catch(a){return i.warn("Failed to retrieve Confluence page"),`Failed to retrieve Confluence page with ID ${r}: ${a.message}`}}async function U9e(r,e,t,n,i){if(!e||!t||!n)throw new Error("Confluence integration incorrectly set");try{i.displayText(`Searching Confluence for query: "${r}"...`);let o=[...r.split(" ").map(l=>`text ~ ${l}`),"type = page"].join(" AND "),s=`${e}/wiki/rest/api/search?cql=${encodeURIComponent(o)}&limit=10&expand=body.editor2`,c=await rr.get(s,{auth:{username:n,password:t}});i.displayText("... received search results from Confluence.");let u=JSON.stringify(c.data.results).replace(/@@@hl@@@|@@@endhl@@@/g,"");return JSON.parse(u)}catch(a){return i.warn("Failed to search Confluence content"),`Failed to perform search: "${r}": ${a.message}`}}var w9=class extends Vt{constructor(t,n,i,a){super(t,i,a);this.integrationService=n}static TYPE="CONFLUENCE";async buildTools(){let t=[];if(!this.integrationService.hasIntegration("CONFLUENCE"))return t;let n=this.integrationService.getApiUrl("CONFLUENCE"),i=this.integrationService.getUsername("CONFLUENCE"),a=this.integrationService.getApiKey("CONFLUENCE");if(!(n&&i&&a))return t;let o={type:"function",function:{name:`${this.name}__getPage`,description:"Get Confluence wiki page by page ID.",parameters:{type:"object",properties:{pageId:{type:"string",description:"Confluence page ID"}}},parse:JSON.parse,function:c=>q9e(c.pageId,n,a,i,this.interactor)}},s={type:"function",function:{name:`${this.name}__search`,description:"Search Confluence pages by words, returns list of page matches. If several pages seem relevant, you **should** read them. Use several searches if many words to check.",parameters:{type:"object",properties:{query:{type:"string",description:"Search words, can be in any order, the query will be split and joined by an AND condition for text search. Keep word count preferably low (1 or 2) to avoid too restrictive search. "}}},parse:JSON.parse,function:c=>U9e(c.query,n,a,i,this.interactor)}};return t.push(o,s),t}};async function z9e(r,e,t,n,i,a){if(!e||!t||!n)throw new Error("Zendesk integration incorrectly set");try{i.displayText(`Retrieving Zendesk article ${r}...`);let o=a?`/${a}`:"",s=`https://${e}.zendesk.com/api/v2/help_center${o}/articles/${r}.json`,c=await rr.get(s,{auth:{username:`${t}/token`,password:n},headers:{"Content-Type":"application/json"}});i.displayText("... received article from Zendesk.");let u=c.data.article;return{id:u.id,title:u.title,body:u.body,author_id:u.author_id,section_id:u.section_id,locale:u.locale,created_at:u.created_at,updated_at:u.updated_at,html_url:u.html_url,draft:u.draft,promoted:u.promoted,vote_sum:u.vote_sum,comments_disabled:u.comments_disabled}}catch(o){return i.warn(`Failed to retrieve Zendesk article ${r}`),`Failed to retrieve article ${r}: ${o.message}`}}async function B9e(r,e,t,n,i,a){if(!e||!t||!n)throw new Error("Zendesk integration incorrectly set");try{i.displayText(`Searching Zendesk articles for query: "${r}"...`);let o=`https://${e}.zendesk.com/api/v2/help_center/articles/search.json`,s=new URLSearchParams;s.append("query",r),a&&s.append("locale",a);let c=`${o}?${s.toString()}`,u=await rr.get(c,{auth:{username:`${t}/token`,password:n},headers:{"Content-Type":"application/json"}});return i.displayText(`... received ${u.data.results?.length||0} search results from Zendesk.`),u.data.results.map(l=>({id:l.id,title:l.title,snippet:l.snippet?.replace(/<\/?em>/g,""),url:l.html_url,locale:l.locale,updated_at:l.updated_at}))}catch(o){return i.warn("Failed to search Zendesk articles"),`Failed to perform search: "${r}": ${o.message}`}}var _9=class extends Vt{constructor(t,n,i,a){super(t,i,a);this.integrationService=n}static TYPE="ZENDESK";async buildTools(){let t=[];if(!this.integrationService.hasIntegration(this.name))return t;let n=this.integrationService.getApiUrl(this.name),i=this.integrationService.getUsername(this.name),a=this.integrationService.getApiKey(this.name);if(!(n&&i&&a))return t;let o={type:"function",function:{name:`${this.name}__getArticle`,description:"Retrieve a Zendesk Help Center article by article ID. Returns the full article content including HTML body.",parameters:{type:"object",properties:{articleId:{type:"string",description:"Zendesk article ID (numeric)"},locale:{type:"string",description:'Optional locale code (e.g., "en-us", "fr"). If not provided, returns article in default locale.'}}},parse:JSON.parse,function:c=>z9e(c.articleId,n,i,a,this.interactor,c.locale)}},s={type:"function",function:{name:`${this.name}__searchArticles`,description:"Search Zendesk Help Center articles by query text. Returns a list of matching articles with ID, title, snippet, and URL. If several articles seem relevant, you **should** retrieve them using retrieveZendeskArticle. Keep queries simple and focused for best results.",parameters:{type:"object",properties:{query:{type:"string",description:"Search query text. Can include multiple words. Zendesk will search across article titles and content."},locale:{type:"string",description:'Optional locale code to search in (e.g., "en-us", "fr"). If not provided, searches in default locale. Use "*" to search across all locales.'}}},parse:JSON.parse,function:c=>B9e(c.query,n,i,a,this.interactor,c.locale)}};return t.push(o,s),t}};async function H9e(r,e,t,n,i,a){let o=`${t}/rest/api/2/issue/${r}/comment`,s=Buffer.from(`${i}:${n}`).toString("base64");try{let c=await fetch(o,{method:"POST",headers:{Authorization:`Basic ${s}`,"Content-Type":"application/json"},body:JSON.stringify({body:e})});if(!c.ok){let u=await c.text();throw new Error(`Failed to add comment to Jira ticket ${r}: ${u}`)}a.displayText(`Successfully added comment to Jira ticket ${r}`)}catch(c){throw a.error(`Error adding comment to Jira ticket ${r}: ${c}`),c}}async function W9e(r,e,t,n,i,a){let o=`${t}/rest/api/2/issue/${r}/comment`,s=Buffer.from(`${i}:${n}`).toString("base64");try{let c=await fetch(o,{method:"POST",headers:{Authorization:`Basic ${s}`,"Content-Type":"application/json"},body:JSON.stringify({body:e,properties:[{key:"sd.public.comment",value:{internal:!0}}]})});if(!c.ok){let u=await c.text();throw new Error(`Failed to add internal note to Jira ticket ${r}: ${u}`)}a.displayText(`Successfully added internal note to Jira ticket ${r}`)}catch(c){throw a.error(`Error adding internal note to Jira ticket ${r}: ${c}`),c}}function V9e(r,e){let t=Q8t(e);return Array.from(t.entries()).map(([n,i])=>{let a=Y8t(r,n);return{name:a?.displayName||n,jqlQueryKey:a?.cfid||a?.value||n,ticketCreationKey:n,custom:!!a?.cfid||n.startsWith("customfield_"),searchable:a?.searchable,cfid:a?.cfid,autocompleteValue:Array.from(i).slice(0,10),operators:a?.operators}})}function KV(r,e){console.log(r,"jql");let t=r.split(/\s+AND\s+|\s+OR\s+/i);console.log("Split conditions:",t);for(let n of t){let i=n.match(/([\w\[\]\d]+)\s*([=!<>~]+|\s+in\s+|\s+not\s+in\s+|\s+is\s+|\s+is\s+not\s+)\s*("[^"]*"|-?\d+d?|'[^']*'|\([^)]*\)|\w+)/);if(!i){console.log(`Could not parse condition: ${n}, ask user for jql query validation`);continue}let[,a,o]=i,s=e.find(l=>l.name===a||l.jqlQueryKey===a||l.ticketCreationKey===a);if(console.log("Mapped field for",a,":",s),!s)throw new Error(`Field ${a} not found in mapping`);let c=o.trim(),u=s.operators||[];if(!u.includes(c))throw new Error(`Invalid operator '${c}' for field '${a}'. Repeat by use an operator from this allowed list: ${u.join(", ")}`)}}function Y8t(r,e){let t=e.split("_"),n=t.length>1?t[1]:void 0;return r.find(i=>n?i.cfid?.includes(n)||i.value.includes(n)||i.displayName.includes(n):i.value===e||i.value.slice(0,-1)===e||i.value===e.slice(0,-1))}function JV(r){return r==null?!1:Array.isArray(r)?r.length>0:!0}function G9e(r){return r?.value??r?.name??r?.displayName??r}function X8t(r,e,t){if(!JV(e))return;t.has(r)||t.set(r,new Set),(Array.isArray(e)?e:[e]).forEach(i=>{JV(i)&&t.get(r).add(G9e(i))})}function Q8t(r){return r.reduce((e,t)=>(Object.keys(t.fields).forEach(n=>{X8t(n,t.fields[n],e)}),e),new Map)}var e9t={minimal:["key","summary"],basic:["key","summary","status"],detailed:["key","summary","status","description","priority"],dates:["created","updated","duedate"],navigation:["key","parent","subtasks","issuelinks"],tracking:["assignee","reporter","created","updated","status"]};function Z9e(r=["basic"]){if(r.includes("*all")||r.includes("*navigable"))return r;let e=r.flatMap(t=>e9t[t.toLowerCase()]||t);return Array.from(new Set(e))}function J9e(r,e=[]){return r.reduce((t,n)=>(t[n.key]={},Object.entries(n.fields).forEach(([i,a])=>{!e.includes(i)&&JV(a)&&(t[n.key][i]=G9e(a))}),t),{})}function WC(r,e){let t=encodeURIComponent(e);return`${r}/issues/?jql=${t}`}async function K9e(r,e,t,n,i){if(!e||!t||!n)throw new Error("Jira integration incorrectly configured");let a=WC(e,r);try{i.displayText(`Counting JIRA issues matching query: ${r}...`);let o=await rr.post(`${e}/rest/api/3/search/approximate-count`,{jql:r},{auth:{username:n,password:t}});return i.displayText(`... found ${JSON.stringify(o.data.count)} issues matching your jql: ${a}`),{count:o.data.count,jqlUrl:a}}catch(o){let s=o instanceof Error?o.message:String(o);return i.warn(`Ticket Count Error: ${s} for the jql: ${a}`),{count:0,jqlUrl:a}}}function at(r,e,t,n){if(e<=t&&t!==0){let i="";e===1?i="[error] ":e===2?i="[warning] ":e===3?i="[info] ":e===4&&(i="[debug] "),n.displayText(`${i}${r}`)}}function XV(r,e,t,n=3){let i=`${e.name} (${e.key})`;if(at(`Converting input for array field: ${i}`,4,n,t),r==null)return at(`No value provided for ${i}.`,2,n,t),[];if(Array.isArray(r))return at(`Input is already an array for ${i}: ${JSON.stringify(r)}`,4,n,t),r;if(typeof r=="string"){at(`Input is a string, attempting to split into array for ${i}. Input: "${r}"`,4,n,t);let a=r.split(",").map(o=>o.trim()).filter(Boolean);if(e.key==="labels")return at(`Treated as labels array: ${JSON.stringify(a)}`,3,n,t),a;if(e.key==="components"||e.key==="fixVersions"){let o=a.map(s=>({name:s}));return at(`Treated as array of {name}: ${JSON.stringify(o)}`,3,n,t),o}if(e.schema.items==="string")return at(`Treated as generic string array: ${JSON.stringify(a)}`,3,n,t),a;if(e.schema.items==="option"){let o=a.map(s=>({value:s}));return at(`Treated as array of {value}: ${JSON.stringify(o)}`,3,n,t),o}return at(`String array conversion did not match a known schema for ${i}. Result: ${JSON.stringify(a)}`,2,n,t),a}return typeof r=="object"?(at(`Input is an object, wrapping in array for ${i}.`,3,n,t),[r]):(at(`Unexpected value type (${typeof r}) for ${i}; wrapping as single-value array.`,2,n,t),[r])}async function QV(r,e,t,n,i,a=3){let o=0;for(;o<a;){o++;let s=await r(),c=e(s);if(!c)return o>1&&at(`Successfully entered a valid value for ${i}.`,3,n,t),s;if(at(`${c} (Attempt ${o}/${a})`,2,n,t),o===a){at(`Maximum attempts reached for ${i}.`,1,n,t);return}at(`Please try again for ${i}.`,3,n,t)}}function r9t(r,e,t,n){return e.required&&(!r||r.length===0)?(at(`Required array field ${e.name} cannot be empty.`,2,n,t),!1):!0}function Qs(r,e,t){at(r.error,1,t,e),r.suggestion&&at(r.suggestion,3,t,e),r.failedField&&at(`Issue with field: ${r.failedField}`,2,t,e),r.httpStatus&&at(`HTTP Status: ${r.httpStatus}`,1,t,e),r.httpBody&&at(`HTTP Response: ${JSON.stringify(r.httpBody)}`,1,t,e)}async function n9t(r,e,t,n,i,a=3){try{at(`Retrieving Jira user ID for username: ${r}`,3,a,i);let o=`${e}/rest/api/2/user/search?query=${encodeURIComponent(r)}`,s=await rr.get(o,{auth:{username:n,password:t}});if(s.data&&Array.isArray(s.data)&&s.data.length>0){let c=s.data[0].accountId;return at(`Found user ID: ${c} for username: ${r}`,4,a,i),c}else return at(`No user found with username: ${r}`,2,a,i),null}catch(o){return at(`Error retrieving user ID: ${o.message}`,1,a,i),null}}async function eG(r={},e,t,n,i,a=3){let o={...r},s=null,c=3,u=0,l=o.projectKey,f=o.issuetype,p,d;function m(h){return d?.fields.find(g=>g.key===h)}for(;u<c;)try{if(!l&&(l=await i.promptText("Enter the Jira project key (e.g., PROJ):"),!l))return s={error:"Project key is required.",suggestion:"Enter a valid Jira project key (e.g., PROJ).",partialRequest:o},Qs(s,i,a),s;if(o.projectKey=l,o.project={key:l},!o.reporter)if(r.reporter)o.reporter=r.reporter,at(`Using provided reporter: ${JSON.stringify(r.reporter)}`,3,a,i);else{at(`Setting reporter to current user (${n})`,3,a,i);let A=await n9t(n,e,t,n,i,a);A?(o.reporter={id:A},at(`Using reporter ID: ${A}`,4,a,i)):(at(`Could not retrieve user ID for ${n}, falling back to username`,2,a,i),o.reporter={name:n})}try{let A=`${e}/rest/api/2/project/${l}`;await rr.get(A,{auth:{username:n,password:t}}),at(`Project key ${l} is valid.`,3,a,i)}catch(A){s={error:`Project key ${l} not found or not accessible.`,suggestion:"Check your Jira project key and permissions.",partialRequest:o,httpStatus:A?.response?.status,httpBody:A?.response?.data},Qs(s,i,a),u++,l=void 0;continue}let h=[];try{let A=`${e}/rest/api/2/issue/createmeta?projectKeys=${l}&expand=projects.issuetypes.fields`,O=(await rr.get(A,{auth:{username:n,password:t}})).data.projects?.[0];if(!O){s={error:`No project data found for ${l}`,suggestion:"Ensure the project key is correct and API credentials are valid.",partialRequest:o,projectKey:l},Qs(s,i,a),u++;continue}h=O.issuetypes.map(w=>({id:w.id,name:w.name})),at(`Loaded ${h.length} issue types for project ${l}.`,4,a,i)}catch(A){s={error:`Failed to retrieve issue types for project ${l}.`,suggestion:"Ensure the project key is correct and API credentials are valid.",partialRequest:o,httpStatus:A?.response?.status,httpBody:A?.response?.data},Qs(s,i,a),u++;continue}if(f)o.issuetype=f;else{let A=h.map($=>$.name);f=await i.chooseOption(A,"Select an issue type:","Please choose one of the available issue types."),o.issuetype=f}let g=h.find(A=>A.name===f);if(!g&&f){at(`Issue type "${f}" not found, trying fuzzy matching...`,3,a,i);let A=f.toLowerCase().trim(),$=null;for(let O of h){let w=O.name.toLowerCase();if(w.includes(A)||A.includes(w)){let k=Math.abs(w.length-A.length);(!$||k<$.score)&&($={...O,score:k})}}$&&(g={id:$.id,name:$.name},at(`Found fuzzy match: "${f}" -> "${$.name}"`,3,a,i),o.issuetype=$.name,f=$.name)}if(!g){s={error:`Issue type "${f}" not found in project ${l}.`,suggestion:`Choose a valid issue type. Available: ${h.map(A=>A.name).join(", ")}`,partialRequest:o,projectKey:l},Qs(s,i,a),u++,f=void 0;continue}p=g.id;try{let A=`${e}/rest/api/2/issue/createmeta?projectKeys=${l}&issuetypeIds=${p}&expand=projects.issuetypes.fields`,w=(await rr.get(A,{auth:{username:n,password:t}})).data.projects?.[0]?.issuetypes?.[0];if(!w){s={error:`No metadata found for issue type ${p}`,suggestion:"Check Jira permissions and API credentials.",partialRequest:o,projectKey:l,issueTypeName:f,issueTypeId:p},Qs(s,i,a),u++;continue}let k=Object.entries(w.fields||{}).map(([b,T])=>({...T,key:b}));d={id:w.id,name:w.name,subtask:w.subtask,fields:k},at(`Loaded metadata for issue type "${f}".`,4,a,i)}catch(A){s={error:`Failed to retrieve metadata for issue type ${f}.`,suggestion:"Check Jira permissions and API credentials.",partialRequest:o,projectKey:l,issueTypeName:f,issueTypeId:p,httpStatus:A?.response?.status,httpBody:A?.response?.data},Qs(s,i,a),u++;continue}let v=d.fields.filter(A=>A.required&&!o[A.key]&&!r[A.key]);for(let A of d.fields){let $=A.key;r[$]!==void 0&&o[$]===void 0?(o[$]=r[$],at(`Using provided value for ${A.name} (${A.key})`,3,a,i)):A.hasDefaultValue&&A.defaultValue!==void 0&&o[$]===void 0&&r[$]===void 0&&(o[$]=A.defaultValue,at(`Using default value for ${A.name} (${A.key}): ${JSON.stringify(A.defaultValue)}`,3,a,i))}for(let A of v){let $;if(A.schema.type==="array")$=await QV(async()=>{let O=await i.promptText(`Enter values for ${A.name} (${A.key}), separated by commas:`,A.hasDefaultValue&&A.defaultValue?A.defaultValue:null);return O===""&&A.hasDefaultValue&&A.defaultValue?A.defaultValue:O},O=>{let w=XV(O,A,i,a);return r9t(w,A,i,a)?null:"At least one value required."},i,a,A.name||A.key||"field",3),$!==void 0&&($=XV($,A,i,a));else if(Array.isArray(A.allowedValues)&&A.allowedValues.length>0){let O=[...A.allowedValues.map(k=>k.name||k.value||k.key||k.id)],w;if(A.hasDefaultValue&&A.defaultValue){let k=typeof A.defaultValue=="object"?A.defaultValue.id:A.defaultValue,b=A.allowedValues.find(T=>T.id===k||T.value===k||T.key===k);b&&(w=b.name||b.value||b.key||b.id,at(`Found default option for ${A.name}: ${w}`,4,a,i))}if($=await QV(async()=>w&&O.includes(w)?i.chooseOption(O,`Select value for ${A.name} (${A.key}) [default: ${w}]:`,"Choose an option"):i.chooseOption(O,`Select value for ${A.name} (${A.key}):`,"Choose an option"),k=>O.includes(k)?null:"Invalid selection.",i,a,A.name||A.key||"field",3),$!==void 0){let k=A.allowedValues.find(b=>b.name===$||b.value===$||b.key===$||b.id===$);k&&(k.id?$={id:k.id}:k.key?$={key:k.key}:k.value&&($={value:k.value}),at(`Formatted ${A.name} value to: ${JSON.stringify($)}`,4,a,i))}}else{let O=A.hasDefaultValue&&A.defaultValue?`Enter ${A.name} (${A.key}) [default: ${JSON.stringify(A.defaultValue)}]:`:`Enter ${A.name} (${A.key}):`;$=await QV(async()=>{let w=await i.promptText(O);return w===""&&A.hasDefaultValue&&A.defaultValue?A.defaultValue:w},w=>A.required&&(!w||typeof w=="string"&&w.trim()==="")?"Field is required.":null,i,a,A.name||A.key||"field",3)}o[A.key]=$}let y=d.fields.find(A=>A.required&&(!o[A.key]||Array.isArray(o[A.key])&&o[A.key].length===0));if(y){s={error:`Missing required field: ${y.name} (${y.key})`,suggestion:"Please provide a value.",failedField:y.key,partialRequest:o,metadata:d,projectKey:l,issueTypeName:f,issueTypeId:p},Qs(s,i,a),u++;continue}let x=`${e}/rest/api/2/issue`,_=Buffer.from(`${n}:${t}`).toString("base64"),S={};if(S.issuetype={id:p},o.summary&&(S.summary=o.summary),o.description&&(S.description=o.description),o.parent&&o.parent.key){at(`Setting parent relationship: Issue will be a child of ${o.parent.key}`,3,a,i);try{let A=`${e}/rest/api/2/issue/${o.parent.key}?fields=issuetype`;(await fetch(A,{method:"GET",headers:{Authorization:`Basic ${_}`,Accept:"application/json"}})).ok?(S.parent={key:o.parent.key},at(`Parent issue ${o.parent.key} verified and will be set during creation`,3,a,i)):at(`Warning: Parent issue ${o.parent.key} not found or not accessible. Parent relationship will not be set.`,2,a,i)}catch(A){at(`Error checking parent issue ${o.parent.key}: ${A}`,1,a,i),at("Will continue without setting parent relationship",2,a,i)}}for(let[A,$]of Object.entries(o)){if(["projectKey","issuetype","summary","description"].includes(A))continue;let O=m(A);if(O){if(A.startsWith("customfield_")&&O.allowedValues&&Array.isArray(O.allowedValues)&&O.allowedValues.length>0){if(typeof $=="string"){let w=O.allowedValues.find(k=>(k.name||"").toLowerCase()===$.toLowerCase()||(k.value||"").toLowerCase()===$.toLowerCase());if(w){S[A]={id:w.id},at(`Mapped ${A} string value "${$}" to ID: ${w.id}`,3,a,i);continue}else{if(O.allowedValues.find(b=>b.id===$)){S[A]={id:$},at(`Used ${A} value "${$}" directly as ID`,3,a,i);continue}at(`Warning: Could not match ${A} value "${$}" to any allowed values. Will try as-is.`,2,a,i),S[A]={name:$};continue}}else if(typeof $=="object"&&$!==null){if($.id){S[A]={id:$.id},at(`Used object with ID for ${A}: ${$.id}`,3,a,i);continue}else if($.name){S[A]={name:$.name},at(`Used object with name for ${A}: ${$.name}`,3,a,i);continue}}}if(O.schema.type==="array")S[A]=XV($,O,i,a);else if(Array.isArray(O.allowedValues)&&O.allowedValues.length>0)if(typeof $=="string"){let w=O.allowedValues.find(k=>k.name===$||k.value===$||k.key===$||k.id===$);w?(w.id?S[A]={id:w.id}:w.key?S[A]={key:w.key}:w.value?S[A]={value:w.value}:S[A]=$,at(`Mapped ${A} string value "${$}" to: ${JSON.stringify(S[A])}`,3,a,i)):S[A]=$}else S[A]=$;else S[A]=$}}try{at("Creating Jira issue...",3,a,i);let A=await fetch(x,{method:"POST",headers:{Authorization:`Basic ${_}`,"Content-Type":"application/json"},body:JSON.stringify({fields:S})});if(!A.ok){let k=await A.text();s={error:`Failed to create Jira issue (${A.status}): ${k}`,suggestion:"Check required fields, permissions, and API configuration.",partialRequest:o,metadata:d,projectKey:l,issueTypeName:f,issueTypeId:p,httpStatus:A.status,httpBody:k},Qs(s,i,a),u++;continue}let O=(await A.json()).key,w=`${e}/browse/${O}`;if(at(`Successfully created Jira issue ${O}`,3,a,i),at(`Issue can be accessed at: ${w}`,3,a,i),o.linkedIssues&&o.linkedIssues.length>0){at(`Processing ${o.linkedIssues.length} linked issues for ${O}...`,3,a,i);let{linkJiraIssues:k}=await Promise.resolve().then(()=>(VC(),Y9e)),b=f?.toLowerCase()==="epic";for(let T of o.linkedIssues)try{let D=T.linkType||(b?"is part of":"relates to"),C=T.isEpicLink!==void 0?T.isEpicLink:b,P=await k({inwardIssueKey:O,outwardIssueKey:T.key,linkType:D,isEpicLink:C},e,t,n,i);P.success?at(`Successfully linked issue ${T.key} to ${O}: ${P.message}`,3,a,i):at(`Failed to link issue ${T.key} to ${O}: ${P.message}`,2,a,i)}catch(D){at(`Error linking issue ${T.key} to ${O}: ${D}`,1,a,i)}}return{issueKey:O,issueUrl:w}}catch(A){s={error:`Error creating Jira issue: ${A.message}`,suggestion:"Check your network connection and Jira API status.",partialRequest:o,metadata:d,projectKey:l,issueTypeName:f,issueTypeId:p},Qs(s,i,a),u++}}catch(h){return s={error:`Fatal error: ${h.message}`,partialRequest:o},Qs(s,i,a),s}return s||{error:"Failed to create Jira issue after multiple attempts.",partialRequest:o}}async function X9e(r,e,t,n){if(!r||!e||!t)throw new Error("Jira integration incorrectly set");try{n.displayText("Fetching JIRA autocomplete suggestions...");let i=await rr.get(`${r}/rest/api/3/jql/autocompletedata`,{auth:{username:t,password:e}});return i.data||n.warn("Empty response from Jira API on autocomplete data"),n.displayText("Successfully retrieved JIRA autocomplete suggestions"),i.data||{visibleFieldNames:[]}}catch(i){return n.warn(`Could not fetch autocomplete data: ${i}`),{visibleFieldNames:[]}}}async function tG({request:r,jiraBaseUrl:e,jiraApiToken:t,jiraUsername:n,interactor:i}){if(!e||!t||!n)throw new Error("Jira integration incorrectly configured");let a=WC(e,r.jql);try{i.displayText(`Searching JIRA issues with query: ${r.jql}...`);let o=await rr.post(`${e}/rest/api/3/search/jql`,{jql:r.jql,maxResults:r.maxResults,fields:r.fields,nextPageToken:r.nextPageToken??null},{auth:{username:n,password:t}}),s=o.data.issues,c=o.data?.nextPageToken;return i.displayText(`... found ${JSON.stringify(s.length)} matching jql: ${a}. The max results is set to ${r.maxResults}`),{issues:s,nextPageToken:c,jqlUrl:a}}catch(o){let s=o instanceof Error?o.message:String(o);return i.warn(`Ticket Search Error: ${s} for the jql: ${a}`),{issues:[],nextPageToken:null,jqlUrl:a}}}async function Q9e({jql:r,nextPageToken:e,maxResults:t=50,fields:n=["basic"],jiraBaseUrl:i,jiraApiToken:a,jiraUsername:o,interactor:s}){try{let c=Z9e(n);s.displayText(`Fetching issues and filter response on those fields: ${c.join(", ")}`);let u=await tG({request:{jql:r,fields:c,maxResults:t,nextPageToken:e},jiraBaseUrl:i,jiraApiToken:a,jiraUsername:o,interactor:s});return u.nextPageToken&&s.displayText("Additional pages of results are available. Use nextPageToken to fetch more."),{issues:J9e(u.issues),nextPageToken:u.nextPageToken,jqlUrl:u.jqlUrl}}catch(c){throw console.error("Jira Search Error:",c),c}}var rG=class{baseUrl;apiToken;username;interactor;constructor(e,t,n,i){this.baseUrl=e,this.apiToken=t,this.username=n,this.interactor=i}async generateFieldMapping(e=100){try{let[t,n]=await Promise.all([X9e(this.baseUrl,this.apiToken,this.username,this.interactor),tG({request:{jql:"project = 'WZ' AND labels = coday_template",maxResults:e,fields:["*all"]},jiraBaseUrl:this.baseUrl,jiraApiToken:this.apiToken,jiraUsername:this.username,interactor:this.interactor})]),i=V9e(t.visibleFieldNames,n.issues),a=this.generateMappingDescription(i);return{mappings:i,autocompleteData:t,description:a}}catch(t){return this.interactor.warn(`Error creating field mapping: ${t}`),{mappings:[],autocompleteData:{visibleFieldNames:[]},description:{customFields:"Failed to generate the jira ticket creation description",jqlResearchDescription:"Failed to generate the jira jql research description"}}}}generateMappingDescription(e){let t=e.map(i=>` ${i.name} - ${i.custom?"Custom":"Standard"}
|
|
1250
|
+
${s}`;return i.debug(`\u2713 Successfully converted Confluence page to Markdown, from ${o?.length} to ${x.length} chars.`),x}catch(a){return i.warn("Failed to retrieve Confluence page"),`Failed to retrieve Confluence page with ID ${r}: ${a.message}`}}async function U9e(r,e,t,n,i){if(!e||!t||!n)throw new Error("Confluence integration incorrectly set");try{i.displayText(`Searching Confluence for query: "${r}"...`);let o=[...r.split(" ").map(u=>`text ~ ${u}`),"type = page"].join(" AND "),s=`${e}/wiki/rest/api/search?cql=${encodeURIComponent(o)}&limit=10&expand=body.editor2`,c=await rr.get(s,{auth:{username:n,password:t}});return i.displayText("... received search results from Confluence."),c.data.results.map(u=>({id:u.content?.id,title:u.title,excerpt:u.excerpt?.replace(/@@@hl@@@|@@@endhl@@@/g,"").trim(),url:u.url,space:u.resultGlobalContainer?.title,lastModified:u.lastModified}))}catch(a){return i.warn("Failed to search Confluence content"),`Failed to perform search: "${r}": ${a.message}`}}var w9=class extends Vt{constructor(t,n,i,a){super(t,i,a);this.integrationService=n}static TYPE="CONFLUENCE";async buildTools(){let t=[];if(!this.integrationService.hasIntegration("CONFLUENCE"))return t;let n=this.integrationService.getApiUrl("CONFLUENCE"),i=this.integrationService.getUsername("CONFLUENCE"),a=this.integrationService.getApiKey("CONFLUENCE");if(!(n&&i&&a))return t;let o={type:"function",function:{name:`${this.name}__getPage`,description:"Get Confluence wiki page by page ID.",parameters:{type:"object",properties:{pageId:{type:"string",description:"Confluence page ID"}}},parse:JSON.parse,function:c=>q9e(c.pageId,n,a,i,this.interactor)}},s={type:"function",function:{name:`${this.name}__search`,description:"Search Confluence pages by words, returns list of page matches. If several pages seem relevant, you **should** read them. Use several searches if many words to check.",parameters:{type:"object",properties:{query:{type:"string",description:"Search words, can be in any order, the query will be split and joined by an AND condition for text search. Keep word count preferably low (1 or 2) to avoid too restrictive search. "}}},parse:JSON.parse,function:c=>U9e(c.query,n,a,i,this.interactor)}};return t.push(o,s),t}};async function z9e(r,e,t,n,i,a){if(!e||!t||!n)throw new Error("Zendesk integration incorrectly set");try{i.displayText(`Retrieving Zendesk article ${r}...`);let o=a?`/${a}`:"",s=`https://${e}.zendesk.com/api/v2/help_center${o}/articles/${r}.json`,c=await rr.get(s,{auth:{username:`${t}/token`,password:n},headers:{"Content-Type":"application/json"}});i.displayText("... received article from Zendesk.");let u=c.data.article;return{id:u.id,title:u.title,body:u.body,author_id:u.author_id,section_id:u.section_id,locale:u.locale,created_at:u.created_at,updated_at:u.updated_at,html_url:u.html_url,draft:u.draft,promoted:u.promoted,vote_sum:u.vote_sum,comments_disabled:u.comments_disabled}}catch(o){return i.warn(`Failed to retrieve Zendesk article ${r}`),`Failed to retrieve article ${r}: ${o.message}`}}async function B9e(r,e,t,n,i,a){if(!e||!t||!n)throw new Error("Zendesk integration incorrectly set");try{i.displayText(`Searching Zendesk articles for query: "${r}"...`);let o=`https://${e}.zendesk.com/api/v2/help_center/articles/search.json`,s=new URLSearchParams;s.append("query",r),a&&s.append("locale",a);let c=`${o}?${s.toString()}`,u=await rr.get(c,{auth:{username:`${t}/token`,password:n},headers:{"Content-Type":"application/json"}});return i.displayText(`... received ${u.data.results?.length||0} search results from Zendesk.`),u.data.results.map(l=>({id:l.id,title:l.title,snippet:l.snippet?.replace(/<\/?em>/g,""),url:l.html_url,locale:l.locale,updated_at:l.updated_at}))}catch(o){return i.warn("Failed to search Zendesk articles"),`Failed to perform search: "${r}": ${o.message}`}}var _9=class extends Vt{constructor(t,n,i,a){super(t,i,a);this.integrationService=n}static TYPE="ZENDESK";async buildTools(){let t=[];if(!this.integrationService.hasIntegration(this.name))return t;let n=this.integrationService.getApiUrl(this.name),i=this.integrationService.getUsername(this.name),a=this.integrationService.getApiKey(this.name);if(!(n&&i&&a))return t;let o={type:"function",function:{name:`${this.name}__getArticle`,description:"Retrieve a Zendesk Help Center article by article ID. Returns the full article content including HTML body.",parameters:{type:"object",properties:{articleId:{type:"string",description:"Zendesk article ID (numeric)"},locale:{type:"string",description:'Optional locale code (e.g., "en-us", "fr"). If not provided, returns article in default locale.'}}},parse:JSON.parse,function:c=>z9e(c.articleId,n,i,a,this.interactor,c.locale)}},s={type:"function",function:{name:`${this.name}__searchArticles`,description:"Search Zendesk Help Center articles by query text. Returns a list of matching articles with ID, title, snippet, and URL. If several articles seem relevant, you **should** retrieve them using retrieveZendeskArticle. Keep queries simple and focused for best results.",parameters:{type:"object",properties:{query:{type:"string",description:"Search query text. Can include multiple words. Zendesk will search across article titles and content."},locale:{type:"string",description:'Optional locale code to search in (e.g., "en-us", "fr"). If not provided, searches in default locale. Use "*" to search across all locales.'}}},parse:JSON.parse,function:c=>B9e(c.query,n,i,a,this.interactor,c.locale)}};return t.push(o,s),t}};async function H9e(r,e,t,n,i,a){let o=`${t}/rest/api/2/issue/${r}/comment`,s=Buffer.from(`${i}:${n}`).toString("base64");try{let c=await fetch(o,{method:"POST",headers:{Authorization:`Basic ${s}`,"Content-Type":"application/json"},body:JSON.stringify({body:e})});if(!c.ok){let u=await c.text();throw new Error(`Failed to add comment to Jira ticket ${r}: ${u}`)}a.displayText(`Successfully added comment to Jira ticket ${r}`)}catch(c){throw a.error(`Error adding comment to Jira ticket ${r}: ${c}`),c}}async function W9e(r,e,t,n,i,a){let o=`${t}/rest/api/2/issue/${r}/comment`,s=Buffer.from(`${i}:${n}`).toString("base64");try{let c=await fetch(o,{method:"POST",headers:{Authorization:`Basic ${s}`,"Content-Type":"application/json"},body:JSON.stringify({body:e,properties:[{key:"sd.public.comment",value:{internal:!0}}]})});if(!c.ok){let u=await c.text();throw new Error(`Failed to add internal note to Jira ticket ${r}: ${u}`)}a.displayText(`Successfully added internal note to Jira ticket ${r}`)}catch(c){throw a.error(`Error adding internal note to Jira ticket ${r}: ${c}`),c}}function V9e(r,e){let t=Q8t(e);return Array.from(t.entries()).map(([n,i])=>{let a=Y8t(r,n);return{name:a?.displayName||n,jqlQueryKey:a?.cfid||a?.value||n,ticketCreationKey:n,custom:!!a?.cfid||n.startsWith("customfield_"),searchable:a?.searchable,cfid:a?.cfid,autocompleteValue:Array.from(i).slice(0,10),operators:a?.operators}})}function KV(r,e){console.log(r,"jql");let t=r.split(/\s+AND\s+|\s+OR\s+/i);console.log("Split conditions:",t);for(let n of t){let i=n.match(/([\w\[\]\d]+)\s*([=!<>~]+|\s+in\s+|\s+not\s+in\s+|\s+is\s+|\s+is\s+not\s+)\s*("[^"]*"|-?\d+d?|'[^']*'|\([^)]*\)|\w+)/);if(!i){console.log(`Could not parse condition: ${n}, ask user for jql query validation`);continue}let[,a,o]=i,s=e.find(l=>l.name===a||l.jqlQueryKey===a||l.ticketCreationKey===a);if(console.log("Mapped field for",a,":",s),!s)throw new Error(`Field ${a} not found in mapping`);let c=o.trim(),u=s.operators||[];if(!u.includes(c))throw new Error(`Invalid operator '${c}' for field '${a}'. Repeat by use an operator from this allowed list: ${u.join(", ")}`)}}function Y8t(r,e){let t=e.split("_"),n=t.length>1?t[1]:void 0;return r.find(i=>n?i.cfid?.includes(n)||i.value.includes(n)||i.displayName.includes(n):i.value===e||i.value.slice(0,-1)===e||i.value===e.slice(0,-1))}function JV(r){return r==null?!1:Array.isArray(r)?r.length>0:!0}function G9e(r){return r?.value??r?.name??r?.displayName??r}function X8t(r,e,t){if(!JV(e))return;t.has(r)||t.set(r,new Set),(Array.isArray(e)?e:[e]).forEach(i=>{JV(i)&&t.get(r).add(G9e(i))})}function Q8t(r){return r.reduce((e,t)=>(Object.keys(t.fields).forEach(n=>{X8t(n,t.fields[n],e)}),e),new Map)}var e9t={minimal:["key","summary"],basic:["key","summary","status"],detailed:["key","summary","status","description","priority"],dates:["created","updated","duedate"],navigation:["key","parent","subtasks","issuelinks"],tracking:["assignee","reporter","created","updated","status"]};function Z9e(r=["basic"]){if(r.includes("*all")||r.includes("*navigable"))return r;let e=r.flatMap(t=>e9t[t.toLowerCase()]||t);return Array.from(new Set(e))}function J9e(r,e=[]){return r.reduce((t,n)=>(t[n.key]={},Object.entries(n.fields).forEach(([i,a])=>{!e.includes(i)&&JV(a)&&(t[n.key][i]=G9e(a))}),t),{})}function WC(r,e){let t=encodeURIComponent(e);return`${r}/issues/?jql=${t}`}async function K9e(r,e,t,n,i){if(!e||!t||!n)throw new Error("Jira integration incorrectly configured");let a=WC(e,r);try{i.displayText(`Counting JIRA issues matching query: ${r}...`);let o=await rr.post(`${e}/rest/api/3/search/approximate-count`,{jql:r},{auth:{username:n,password:t}});return i.displayText(`... found ${JSON.stringify(o.data.count)} issues matching your jql: ${a}`),{count:o.data.count,jqlUrl:a}}catch(o){let s=o instanceof Error?o.message:String(o);return i.warn(`Ticket Count Error: ${s} for the jql: ${a}`),{count:0,jqlUrl:a}}}function at(r,e,t,n){if(e<=t&&t!==0){let i="";e===1?i="[error] ":e===2?i="[warning] ":e===3?i="[info] ":e===4&&(i="[debug] "),n.displayText(`${i}${r}`)}}function XV(r,e,t,n=3){let i=`${e.name} (${e.key})`;if(at(`Converting input for array field: ${i}`,4,n,t),r==null)return at(`No value provided for ${i}.`,2,n,t),[];if(Array.isArray(r))return at(`Input is already an array for ${i}: ${JSON.stringify(r)}`,4,n,t),r;if(typeof r=="string"){at(`Input is a string, attempting to split into array for ${i}. Input: "${r}"`,4,n,t);let a=r.split(",").map(o=>o.trim()).filter(Boolean);if(e.key==="labels")return at(`Treated as labels array: ${JSON.stringify(a)}`,3,n,t),a;if(e.key==="components"||e.key==="fixVersions"){let o=a.map(s=>({name:s}));return at(`Treated as array of {name}: ${JSON.stringify(o)}`,3,n,t),o}if(e.schema.items==="string")return at(`Treated as generic string array: ${JSON.stringify(a)}`,3,n,t),a;if(e.schema.items==="option"){let o=a.map(s=>({value:s}));return at(`Treated as array of {value}: ${JSON.stringify(o)}`,3,n,t),o}return at(`String array conversion did not match a known schema for ${i}. Result: ${JSON.stringify(a)}`,2,n,t),a}return typeof r=="object"?(at(`Input is an object, wrapping in array for ${i}.`,3,n,t),[r]):(at(`Unexpected value type (${typeof r}) for ${i}; wrapping as single-value array.`,2,n,t),[r])}async function QV(r,e,t,n,i,a=3){let o=0;for(;o<a;){o++;let s=await r(),c=e(s);if(!c)return o>1&&at(`Successfully entered a valid value for ${i}.`,3,n,t),s;if(at(`${c} (Attempt ${o}/${a})`,2,n,t),o===a){at(`Maximum attempts reached for ${i}.`,1,n,t);return}at(`Please try again for ${i}.`,3,n,t)}}function r9t(r,e,t,n){return e.required&&(!r||r.length===0)?(at(`Required array field ${e.name} cannot be empty.`,2,n,t),!1):!0}function Qs(r,e,t){at(r.error,1,t,e),r.suggestion&&at(r.suggestion,3,t,e),r.failedField&&at(`Issue with field: ${r.failedField}`,2,t,e),r.httpStatus&&at(`HTTP Status: ${r.httpStatus}`,1,t,e),r.httpBody&&at(`HTTP Response: ${JSON.stringify(r.httpBody)}`,1,t,e)}async function n9t(r,e,t,n,i,a=3){try{at(`Retrieving Jira user ID for username: ${r}`,3,a,i);let o=`${e}/rest/api/2/user/search?query=${encodeURIComponent(r)}`,s=await rr.get(o,{auth:{username:n,password:t}});if(s.data&&Array.isArray(s.data)&&s.data.length>0){let c=s.data[0].accountId;return at(`Found user ID: ${c} for username: ${r}`,4,a,i),c}else return at(`No user found with username: ${r}`,2,a,i),null}catch(o){return at(`Error retrieving user ID: ${o.message}`,1,a,i),null}}async function eG(r={},e,t,n,i,a=3){let o={...r},s=null,c=3,u=0,l=o.projectKey,f=o.issuetype,p,d;function m(h){return d?.fields.find(g=>g.key===h)}for(;u<c;)try{if(!l&&(l=await i.promptText("Enter the Jira project key (e.g., PROJ):"),!l))return s={error:"Project key is required.",suggestion:"Enter a valid Jira project key (e.g., PROJ).",partialRequest:o},Qs(s,i,a),s;if(o.projectKey=l,o.project={key:l},!o.reporter)if(r.reporter)o.reporter=r.reporter,at(`Using provided reporter: ${JSON.stringify(r.reporter)}`,3,a,i);else{at(`Setting reporter to current user (${n})`,3,a,i);let A=await n9t(n,e,t,n,i,a);A?(o.reporter={id:A},at(`Using reporter ID: ${A}`,4,a,i)):(at(`Could not retrieve user ID for ${n}, falling back to username`,2,a,i),o.reporter={name:n})}try{let A=`${e}/rest/api/2/project/${l}`;await rr.get(A,{auth:{username:n,password:t}}),at(`Project key ${l} is valid.`,3,a,i)}catch(A){s={error:`Project key ${l} not found or not accessible.`,suggestion:"Check your Jira project key and permissions.",partialRequest:o,httpStatus:A?.response?.status,httpBody:A?.response?.data},Qs(s,i,a),u++,l=void 0;continue}let h=[];try{let A=`${e}/rest/api/2/issue/createmeta?projectKeys=${l}&expand=projects.issuetypes.fields`,O=(await rr.get(A,{auth:{username:n,password:t}})).data.projects?.[0];if(!O){s={error:`No project data found for ${l}`,suggestion:"Ensure the project key is correct and API credentials are valid.",partialRequest:o,projectKey:l},Qs(s,i,a),u++;continue}h=O.issuetypes.map(w=>({id:w.id,name:w.name})),at(`Loaded ${h.length} issue types for project ${l}.`,4,a,i)}catch(A){s={error:`Failed to retrieve issue types for project ${l}.`,suggestion:"Ensure the project key is correct and API credentials are valid.",partialRequest:o,httpStatus:A?.response?.status,httpBody:A?.response?.data},Qs(s,i,a),u++;continue}if(f)o.issuetype=f;else{let A=h.map($=>$.name);f=await i.chooseOption(A,"Select an issue type:","Please choose one of the available issue types."),o.issuetype=f}let g=h.find(A=>A.name===f);if(!g&&f){at(`Issue type "${f}" not found, trying fuzzy matching...`,3,a,i);let A=f.toLowerCase().trim(),$=null;for(let O of h){let w=O.name.toLowerCase();if(w.includes(A)||A.includes(w)){let k=Math.abs(w.length-A.length);(!$||k<$.score)&&($={...O,score:k})}}$&&(g={id:$.id,name:$.name},at(`Found fuzzy match: "${f}" -> "${$.name}"`,3,a,i),o.issuetype=$.name,f=$.name)}if(!g){s={error:`Issue type "${f}" not found in project ${l}.`,suggestion:`Choose a valid issue type. Available: ${h.map(A=>A.name).join(", ")}`,partialRequest:o,projectKey:l},Qs(s,i,a),u++,f=void 0;continue}p=g.id;try{let A=`${e}/rest/api/2/issue/createmeta?projectKeys=${l}&issuetypeIds=${p}&expand=projects.issuetypes.fields`,w=(await rr.get(A,{auth:{username:n,password:t}})).data.projects?.[0]?.issuetypes?.[0];if(!w){s={error:`No metadata found for issue type ${p}`,suggestion:"Check Jira permissions and API credentials.",partialRequest:o,projectKey:l,issueTypeName:f,issueTypeId:p},Qs(s,i,a),u++;continue}let k=Object.entries(w.fields||{}).map(([b,T])=>({...T,key:b}));d={id:w.id,name:w.name,subtask:w.subtask,fields:k},at(`Loaded metadata for issue type "${f}".`,4,a,i)}catch(A){s={error:`Failed to retrieve metadata for issue type ${f}.`,suggestion:"Check Jira permissions and API credentials.",partialRequest:o,projectKey:l,issueTypeName:f,issueTypeId:p,httpStatus:A?.response?.status,httpBody:A?.response?.data},Qs(s,i,a),u++;continue}let v=d.fields.filter(A=>A.required&&!o[A.key]&&!r[A.key]);for(let A of d.fields){let $=A.key;r[$]!==void 0&&o[$]===void 0?(o[$]=r[$],at(`Using provided value for ${A.name} (${A.key})`,3,a,i)):A.hasDefaultValue&&A.defaultValue!==void 0&&o[$]===void 0&&r[$]===void 0&&(o[$]=A.defaultValue,at(`Using default value for ${A.name} (${A.key}): ${JSON.stringify(A.defaultValue)}`,3,a,i))}for(let A of v){let $;if(A.schema.type==="array")$=await QV(async()=>{let O=await i.promptText(`Enter values for ${A.name} (${A.key}), separated by commas:`,A.hasDefaultValue&&A.defaultValue?A.defaultValue:null);return O===""&&A.hasDefaultValue&&A.defaultValue?A.defaultValue:O},O=>{let w=XV(O,A,i,a);return r9t(w,A,i,a)?null:"At least one value required."},i,a,A.name||A.key||"field",3),$!==void 0&&($=XV($,A,i,a));else if(Array.isArray(A.allowedValues)&&A.allowedValues.length>0){let O=[...A.allowedValues.map(k=>k.name||k.value||k.key||k.id)],w;if(A.hasDefaultValue&&A.defaultValue){let k=typeof A.defaultValue=="object"?A.defaultValue.id:A.defaultValue,b=A.allowedValues.find(T=>T.id===k||T.value===k||T.key===k);b&&(w=b.name||b.value||b.key||b.id,at(`Found default option for ${A.name}: ${w}`,4,a,i))}if($=await QV(async()=>w&&O.includes(w)?i.chooseOption(O,`Select value for ${A.name} (${A.key}) [default: ${w}]:`,"Choose an option"):i.chooseOption(O,`Select value for ${A.name} (${A.key}):`,"Choose an option"),k=>O.includes(k)?null:"Invalid selection.",i,a,A.name||A.key||"field",3),$!==void 0){let k=A.allowedValues.find(b=>b.name===$||b.value===$||b.key===$||b.id===$);k&&(k.id?$={id:k.id}:k.key?$={key:k.key}:k.value&&($={value:k.value}),at(`Formatted ${A.name} value to: ${JSON.stringify($)}`,4,a,i))}}else{let O=A.hasDefaultValue&&A.defaultValue?`Enter ${A.name} (${A.key}) [default: ${JSON.stringify(A.defaultValue)}]:`:`Enter ${A.name} (${A.key}):`;$=await QV(async()=>{let w=await i.promptText(O);return w===""&&A.hasDefaultValue&&A.defaultValue?A.defaultValue:w},w=>A.required&&(!w||typeof w=="string"&&w.trim()==="")?"Field is required.":null,i,a,A.name||A.key||"field",3)}o[A.key]=$}let y=d.fields.find(A=>A.required&&(!o[A.key]||Array.isArray(o[A.key])&&o[A.key].length===0));if(y){s={error:`Missing required field: ${y.name} (${y.key})`,suggestion:"Please provide a value.",failedField:y.key,partialRequest:o,metadata:d,projectKey:l,issueTypeName:f,issueTypeId:p},Qs(s,i,a),u++;continue}let x=`${e}/rest/api/2/issue`,_=Buffer.from(`${n}:${t}`).toString("base64"),S={};if(S.issuetype={id:p},o.summary&&(S.summary=o.summary),o.description&&(S.description=o.description),o.parent&&o.parent.key){at(`Setting parent relationship: Issue will be a child of ${o.parent.key}`,3,a,i);try{let A=`${e}/rest/api/2/issue/${o.parent.key}?fields=issuetype`;(await fetch(A,{method:"GET",headers:{Authorization:`Basic ${_}`,Accept:"application/json"}})).ok?(S.parent={key:o.parent.key},at(`Parent issue ${o.parent.key} verified and will be set during creation`,3,a,i)):at(`Warning: Parent issue ${o.parent.key} not found or not accessible. Parent relationship will not be set.`,2,a,i)}catch(A){at(`Error checking parent issue ${o.parent.key}: ${A}`,1,a,i),at("Will continue without setting parent relationship",2,a,i)}}for(let[A,$]of Object.entries(o)){if(["projectKey","issuetype","summary","description"].includes(A))continue;let O=m(A);if(O){if(A.startsWith("customfield_")&&O.allowedValues&&Array.isArray(O.allowedValues)&&O.allowedValues.length>0){if(typeof $=="string"){let w=O.allowedValues.find(k=>(k.name||"").toLowerCase()===$.toLowerCase()||(k.value||"").toLowerCase()===$.toLowerCase());if(w){S[A]={id:w.id},at(`Mapped ${A} string value "${$}" to ID: ${w.id}`,3,a,i);continue}else{if(O.allowedValues.find(b=>b.id===$)){S[A]={id:$},at(`Used ${A} value "${$}" directly as ID`,3,a,i);continue}at(`Warning: Could not match ${A} value "${$}" to any allowed values. Will try as-is.`,2,a,i),S[A]={name:$};continue}}else if(typeof $=="object"&&$!==null){if($.id){S[A]={id:$.id},at(`Used object with ID for ${A}: ${$.id}`,3,a,i);continue}else if($.name){S[A]={name:$.name},at(`Used object with name for ${A}: ${$.name}`,3,a,i);continue}}}if(O.schema.type==="array")S[A]=XV($,O,i,a);else if(Array.isArray(O.allowedValues)&&O.allowedValues.length>0)if(typeof $=="string"){let w=O.allowedValues.find(k=>k.name===$||k.value===$||k.key===$||k.id===$);w?(w.id?S[A]={id:w.id}:w.key?S[A]={key:w.key}:w.value?S[A]={value:w.value}:S[A]=$,at(`Mapped ${A} string value "${$}" to: ${JSON.stringify(S[A])}`,3,a,i)):S[A]=$}else S[A]=$;else S[A]=$}}try{at("Creating Jira issue...",3,a,i);let A=await fetch(x,{method:"POST",headers:{Authorization:`Basic ${_}`,"Content-Type":"application/json"},body:JSON.stringify({fields:S})});if(!A.ok){let k=await A.text();s={error:`Failed to create Jira issue (${A.status}): ${k}`,suggestion:"Check required fields, permissions, and API configuration.",partialRequest:o,metadata:d,projectKey:l,issueTypeName:f,issueTypeId:p,httpStatus:A.status,httpBody:k},Qs(s,i,a),u++;continue}let O=(await A.json()).key,w=`${e}/browse/${O}`;if(at(`Successfully created Jira issue ${O}`,3,a,i),at(`Issue can be accessed at: ${w}`,3,a,i),o.linkedIssues&&o.linkedIssues.length>0){at(`Processing ${o.linkedIssues.length} linked issues for ${O}...`,3,a,i);let{linkJiraIssues:k}=await Promise.resolve().then(()=>(VC(),Y9e)),b=f?.toLowerCase()==="epic";for(let T of o.linkedIssues)try{let D=T.linkType||(b?"is part of":"relates to"),C=T.isEpicLink!==void 0?T.isEpicLink:b,P=await k({inwardIssueKey:O,outwardIssueKey:T.key,linkType:D,isEpicLink:C},e,t,n,i);P.success?at(`Successfully linked issue ${T.key} to ${O}: ${P.message}`,3,a,i):at(`Failed to link issue ${T.key} to ${O}: ${P.message}`,2,a,i)}catch(D){at(`Error linking issue ${T.key} to ${O}: ${D}`,1,a,i)}}return{issueKey:O,issueUrl:w}}catch(A){s={error:`Error creating Jira issue: ${A.message}`,suggestion:"Check your network connection and Jira API status.",partialRequest:o,metadata:d,projectKey:l,issueTypeName:f,issueTypeId:p},Qs(s,i,a),u++}}catch(h){return s={error:`Fatal error: ${h.message}`,partialRequest:o},Qs(s,i,a),s}return s||{error:"Failed to create Jira issue after multiple attempts.",partialRequest:o}}async function X9e(r,e,t,n){if(!r||!e||!t)throw new Error("Jira integration incorrectly set");try{n.displayText("Fetching JIRA autocomplete suggestions...");let i=await rr.get(`${r}/rest/api/3/jql/autocompletedata`,{auth:{username:t,password:e}});return i.data||n.warn("Empty response from Jira API on autocomplete data"),n.displayText("Successfully retrieved JIRA autocomplete suggestions"),i.data||{visibleFieldNames:[]}}catch(i){return n.warn(`Could not fetch autocomplete data: ${i}`),{visibleFieldNames:[]}}}async function tG({request:r,jiraBaseUrl:e,jiraApiToken:t,jiraUsername:n,interactor:i}){if(!e||!t||!n)throw new Error("Jira integration incorrectly configured");let a=WC(e,r.jql);try{i.displayText(`Searching JIRA issues with query: ${r.jql}...`);let o=await rr.post(`${e}/rest/api/3/search/jql`,{jql:r.jql,maxResults:r.maxResults,fields:r.fields,nextPageToken:r.nextPageToken??null},{auth:{username:n,password:t}}),s=o.data.issues,c=o.data?.nextPageToken;return i.displayText(`... found ${JSON.stringify(s.length)} matching jql: ${a}. The max results is set to ${r.maxResults}`),{issues:s,nextPageToken:c,jqlUrl:a}}catch(o){let s=o instanceof Error?o.message:String(o);return i.warn(`Ticket Search Error: ${s} for the jql: ${a}`),{issues:[],nextPageToken:null,jqlUrl:a}}}async function Q9e({jql:r,nextPageToken:e,maxResults:t=50,fields:n=["basic"],jiraBaseUrl:i,jiraApiToken:a,jiraUsername:o,interactor:s}){try{let c=Z9e(n);s.displayText(`Fetching issues and filter response on those fields: ${c.join(", ")}`);let u=await tG({request:{jql:r,fields:c,maxResults:t,nextPageToken:e},jiraBaseUrl:i,jiraApiToken:a,jiraUsername:o,interactor:s});return u.nextPageToken&&s.displayText("Additional pages of results are available. Use nextPageToken to fetch more."),{issues:J9e(u.issues),nextPageToken:u.nextPageToken,jqlUrl:u.jqlUrl}}catch(c){throw console.error("Jira Search Error:",c),c}}var rG=class{baseUrl;apiToken;username;interactor;constructor(e,t,n,i){this.baseUrl=e,this.apiToken=t,this.username=n,this.interactor=i}async generateFieldMapping(e=100){try{let[t,n]=await Promise.all([X9e(this.baseUrl,this.apiToken,this.username,this.interactor),tG({request:{jql:"project = 'WZ' AND labels = coday_template",maxResults:e,fields:["*all"]},jiraBaseUrl:this.baseUrl,jiraApiToken:this.apiToken,jiraUsername:this.username,interactor:this.interactor})]),i=V9e(t.visibleFieldNames,n.issues),a=this.generateMappingDescription(i);return{mappings:i,autocompleteData:t,description:a}}catch(t){return this.interactor.warn(`Error creating field mapping: ${t}`),{mappings:[],autocompleteData:{visibleFieldNames:[]},description:{customFields:"Failed to generate the jira ticket creation description",jqlResearchDescription:"Failed to generate the jira jql research description"}}}}generateMappingDescription(e){let t=e.map(i=>` ${i.name} - ${i.custom?"Custom":"Standard"}
|
|
1249
1251
|
Name: ${i.name}
|
|
1250
1252
|
Key: ${i.ticketCreationKey}`).join(`
|
|
1251
1253
|
|