@superglue/cli 1.1.230 → 1.1.231

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/cli.js CHANGED
@@ -109,7 +109,7 @@ attempted value: ${s}
109
109
 
110
110
  `)}function Fb(t){return(t.parts||[]).flatMap(e=>e.type==="tool"&&e.tool?[e.tool]:[])}function mM(t){return $b(t)?!0:Fb(t).length>0}function jb(t){return t.role==="assistant"&&!t.isStreaming&&!mM(t)}function UAe(t){return t.role==="system"||t.isHidden?!1:!jb(t)}function xAe(t){return t.filter(e=>!jb(e))}function MAe(t){return t.filter(e=>{let r=$b(e),n=Fb(e).length>0;return(r||n)&&!(e.id==="1"&&!r)})}function LAe(t,e=5e3,r=10){if(t==null)return"null";if(typeof t=="string")return t.length<=e?t:t.slice(0,e)+"... [truncated]";let n=Mb(t);if(n.length<=e)return n;let i=pM(t,r),o=Mb(i);return o.length<=e?o:o.slice(0,e)+"... [truncated]"}function PAe(t,e){if(t.length<=e)return t;let r=Math.ceil(e/2),n=Math.floor(e/2),i=t.length-r-n;return`${t.slice(0,r)}
111
111
  ... [${i} characters omitted] ...
112
- ${t.slice(t.length-n)}`}function $Ae(t){return t instanceof Error?t.message:typeof t=="string"?t:typeof t=="object"&&t!==null&&"message"in t?String(t.message):String(t)}function FAe(t,e){if(!e||Object.keys(e).length===0)return{};let r=/file::([^,\s)}\]"']+)/g,n=typeof t=="string"?t:JSON.stringify(t||{}),i=[...new Set([...n.matchAll(r)].map(o=>{let s=o[1];return s.endsWith(".raw")?s=s.slice(0,-4):s.endsWith(".base64")?s=s.slice(0,-7):s.endsWith(".extracted")&&(s=s.slice(0,-10)),s}))];return Object.fromEntries(i.flatMap(o=>e[o]?[[o,e[o]]]:[]))}function jAe(t){if(!t)return null;let e=t.indexOf(":");if(e===-1)return{source:"simpleicons",name:t};let r=t.substring(0,e),n=t.substring(e+1);return r!=="simpleicons"&&r!=="lucide"?{source:"simpleicons",name:t}:{source:r,name:n}}function zAe(t){return t?typeof t=="string"?t.indexOf(":")!==-1?t:`simpleicons:${t}`:`${t.source}:${t.name}`:null}function yM(t){if(t.op==="remove"||t.value===void 0||typeof t.value!="string")return t;if(t.path==="/inputSchema"||t.path==="/outputSchema"||t.path.startsWith("/inputSchema/properties/")||t.path.startsWith("/outputSchema/properties/")||t.path.match(/^\/steps\/\d+\/config\/pagination$/)||t.path.match(/^\/steps\/\d+\/config\/headers$/)||t.path.match(/^\/steps\/\d+\/config\/queryParams$/))try{return{...t,value:JSON.parse(t.value)}}catch{return t}return t}function HAe(t){return t.map(e=>yM(e))}function qAe(t,e){t||(t=""),e||(e=""),/^(https?|postgres(ql)?|ftp(s)?|sftp|smb|file):\/\//i.test(t)||(t=`https://${t}`);let r=t.endsWith("/")?t.slice(0,-1):t,n=e.startsWith("/")?e.slice(1):e;return`${r}/${n}`}var GAe=new Set(["data","stepResults","toolPayload","rawData","transformedData"]),YAe=8e4;function VAe(t,e=YAe){if(t==null)return t;let r=t;if(typeof t=="string"){if(t.length<=e)return t;try{r=JSON.parse(t)}catch{return{_truncated:!0,_message:"String result too large to parse",_size:t.length}}}if(typeof r!="object")return r;let n=0,i=0,o=(s,a=0)=>{if(a>20||s===null||typeof s!="object")return s;if(Array.isArray(s))return s.map(u=>o(u,a+1));let c={};for(let[u,l]of Object.entries(s))if(GAe.has(u)&&l!==null&&typeof l=="object"){let d=JSON.stringify(l);if(d.length>e){i+=d.length;try{let{jsonString:A,truncatedProps:p}=(0,Vde.default)(d,e);c[u]=JSON.parse(A),n+=p.length}catch{c[u]=l}}else c[u]=l}else c[u]=o(l,a+1);return c};try{if(JSON.stringify(r).length<=e)return r;let a=o(r);return n>0&&typeof a=="object"&&a!==null&&(a._note=`Result truncated: ${n} items omitted (original ${i} characters)`),a}catch{return{_truncated:!0,_message:"Result too large to display"}}}function JAe(t){if(!t.steps)return[];let e=new Set;for(let r of t.steps)r.config&&(0,eM.isRequestConfig)(r.config)&&r.config.systemId&&e.add(r.config.systemId);return Array.from(e)}function Eg(t,e,r=new WeakSet){if(typeof t=="string"){e.push(t);return}if(!(!t||typeof t!="object")&&!r.has(t)){if(r.add(t),Array.isArray(t)){for(let n of t)Eg(n,e,r);return}for(let n of Object.values(t))Eg(n,e,r)}}function WAe(t){let e=[];for(let r of t.matchAll(/<<([\s\S]*?)>>/g)){let n=r[1].trim();n&&e.push(n)}for(let r of t.matchAll(/{{\s*([^{}\s]+)\s*}}/g)){let n=r[1].trim();n&&e.push(n)}return e}function EM(t,e){let r=[];Eg(t,r);let n=`${e}_`,i=new Set;for(let o of r)for(let s of WAe(o)){if(!s.startsWith(n))continue;let a=s.slice(n.length);!a||a==="url"||!k.CREDENTIAL_KEY_PATTERN.test(a)||i.add(a)}return[...i]}var ZAe=/^\s*(async\s+)?(\([^)]*\)|[a-zA-Z_$][a-zA-Z0-9_$]*)\s*=>/,KAe=new Set(["sg_auth_email","sg_auth_jwt"]);function XAe({config:t,systemId:e}){let r=[];Eg(t,r);let n=e?`${e}_`:null,i=new Set;for(let u of r)for(let l of u.matchAll(/<<([\s\S]*?)>>/g)){let d=l[1].trim();d&&(n&&d.startsWith(n)||ZAe.test(d)||KAe.has(d)||i.add(d))}if(i.size===0)return null;let o=[...i].map(u=>`<<${u}>>`).join(", "),s=`Unresolved placeholder${i.size===1?"":"s"} ${o}`;if(!n)return`${s}. Credential placeholders need systemId and the form <<systemId_secretName>>. Nothing was sent.`;let a=[...i].filter(u=>k.CREDENTIAL_KEY_PATTERN.test(u)).map(u=>`<<${n}${u}>>`),c=a.length>0?`Credential placeholders are namespaced by system: use ${a.join(", ")}.`:`Credential placeholders are namespaced by system as <<${n}secretName>>.`;return`${s}. ${c} Nothing was sent.`}function epe(t){let e={};if(!t.steps)return e;for(let r of t.steps){if(!r.config||!(0,eM.isRequestConfig)(r.config)||!r.config.systemId)continue;let n=EM(r.config,r.config.systemId);if(n.length===0)continue;let i=new Set(e[r.config.systemId]||[]);for(let o of n)i.add(o);e[r.config.systemId]=[...i]}return e}function tpe(t){return t.replace(/([a-z])([A-Z])|([A-Z]{2,})([A-Z][a-z])/g,"$1$3 $2$4").replace(/[_-]/g," ").replace(/\b\w/g,e=>e.toUpperCase()).replace(/\b(Id|Url|Api|Ui)\b/g,e=>e.toUpperCase())}});var wM=m(yt=>{"use strict";Object.defineProperty(yt,"__esModule",{value:!0});yt.AGENT_CONTEXT_MEMORY_MESSAGE_ID_PREFIX=void 0;yt.applyToolMutation=IM;yt.mutateToolCallInMessages=npe;yt.buildStreamingAssistantMessage=CM;yt.parseToolOutput=bM;yt.parseAgentStreamEventLine=ope;yt.stopActiveTool=SM;yt.appendContentToMessage=zb;yt.updateMessageWithData=yu;yt.findAwaitingConfirmationToolCallIds=spe;yt.declineAwaitingConfirmationTools=ape;yt.findAndResumeMessageWithTool=cpe;yt.serializeMessageForPersistence=lpe;yt.isTurnContextBlockMessage=Hb;yt.normalizeAgentSessionForkMessages=Ape;yt.normalizeAgentSessionImportMessages=ppe;yt.createAgentTranscriptState=fpe;yt.applyAgentStreamChunk=hpe;var rpe=Lr(),bg=Rn();function IM(t,e){let r=e.frontendOutput!==void 0?e.frontendOutput:t.frontendOutput;return{...t,...e.input!==void 0?{input:e.input}:{},...e.result!==void 0?{result:e.result}:{},...e.status!==void 0?{status:e.status}:{},...e.startTime!==void 0?{startTime:e.startTime}:{},...e.endTime!==void 0?{endTime:e.endTime}:{},...e.error!==void 0?{error:e.error||void 0}:{},...r!==void 0?{frontendOutput:r}:{},...e.llmOutput!==void 0?{llmOutput:e.llmOutput}:{},...e.resultMetadata!==void 0?{resultMetadata:e.resultMetadata}:{},...e.confirmationState!==void 0?{confirmationState:e.confirmationState===null?void 0:e.confirmationState}:{},...e.confirmationData!==void 0?{confirmationData:e.confirmationData===null?void 0:e.confirmationData}:{}}}function npe(t,e,r){return t.map(n=>{let i=!1,o=n.parts?.map(s=>s.type!=="tool"||!s.tool||s.tool.id!==e?s:(i=!0,{...s,tool:IM(s.tool,r)}));return i&&o?{...n,parts:o}:n})}function CM(t){return{id:t,content:"",role:"assistant",timestamp:new Date,parts:[{type:"content",content:"",id:"content-0"}],isStreaming:!0}}function ipe(){return{status:"declined",endTime:new Date,confirmationState:"declined",confirmationData:{reason:"new_user_message",message:"Rejected: the user sent a new message instead of confirming this action. The proposed changes were NOT applied."}}}function bM(t){if(!t)return null;if(typeof t=="string")try{let e=JSON.parse(t);return e&&typeof e=="object"&&!Array.isArray(e)?e:null}catch{return null}return typeof t=="object"&&!Array.isArray(t)?t:null}function ope(t){if(!t.startsWith("data: "))return null;try{let e=JSON.parse(t.slice(6));return e&&typeof e=="object"&&!Array.isArray(e)?e:null}catch{return null}}function SM(t){return t.status==="running"||t.status==="pending"||t.status==="awaiting_confirmation"?{...t,status:"stopped",endTime:new Date,confirmationState:void 0,confirmationData:void 0}:t}function zb(t,e){if(!e)return t;let r=[...t.parts||[]],n=r[r.length-1];return n?.type==="content"?r[r.length-1]={...n,content:(n.content||"")+e}:r.push({type:"content",content:e,id:`content-${r.length}`}),{...t,parts:r,content:""}}function yu(t,e,r){if(t.id!==r.id)return t;switch(e.type){case"content":return zb(t,e.content||"");case"tool_call_start":{let n=t.parts?.find(u=>u.type==="tool"&&u.tool?.id===e.toolCall.id)?.tool,i=e.toolCall.input??n?.input,o=e.executionMode==="confirm"?"awaiting_confirmation":i?"running":"pending",s={...n,id:e.toolCall.id,name:e.toolCall.name,input:i,status:o,startTime:n?.startTime||new Date,...n?.confirmationState!==void 0?{confirmationState:n.confirmationState}:{},...n?.confirmationData!==void 0?{confirmationData:n.confirmationData}:{}},a=[...t.parts||[]],c=a.findIndex(u=>u.type==="tool"&&u.tool?.id===e.toolCall.id);return c===-1?a.push({type:"tool",tool:s,id:`tool-${e.toolCall.id}`}):a[c]={...a[c],tool:s},{...t,parts:a,content:""}}case"tool_call_input":{let n=i=>i.id===e.toolCall.id&&e.toolCall.input!==void 0?{...i,input:e.toolCall.input}:i;return{...t,parts:t.parts?.map(i=>i.type==="tool"&&i.tool?{...i,tool:n(i.tool)}:i)}}case"run_command_effect":{let n=e.effect;if(n?.kind!=="visual"&&n?.kind!=="checklist"||typeof e.toolCallId!="string")return t;let i=o=>{if(o.id!==e.toolCallId)return o;let s=bM(o.frontendOutput)??{},a=(s.effects??[]).filter(c=>c.id!==n.id);return{...o,frontendOutput:{...s,effects:[...a,n]}}};return{...t,parts:t.parts?.map(o=>o.type==="tool"&&o.tool?{...o,tool:i(o.tool)}:o)}}case"tool_call_update":{let n=t.parts?.map(i=>i.type==="tool"&&i.tool?.id===e.toolCall.id?{...i,tool:{...i.tool,executionTraceId:e.toolCall.executionTraceId??i.tool.executionTraceId,status:i.tool.status==="pending"?"running":i.tool.status}}:i)||[];return{...t,parts:n}}case"tool_call_complete":{let n=t.parts?.find(h=>h.type==="tool"&&h.tool?.id===e.toolCall.id)?.tool,i=n?.status==="completed"||n?.status==="declined",o=e.toolCall.result!==void 0||e.toolCall.frontendOutput!==void 0||e.toolCall.status!==void 0||e.toolCall.confirmationState!==void 0||e.toolCall.confirmationData!==void 0;if(i&&!o)return t;let s=null;try{s=typeof e.toolCall.frontendOutput=="string"?JSON.parse(e.toolCall.frontendOutput):e.toolCall.frontendOutput}catch{}let a=s?.success===!1&&s?.error,c=e.toolCall.result?.outcome,u=c==="failure"?"error":c==="rejected"?"declined":c==="aborted"?"stopped":c==="success"?"completed":void 0,l=e.toolCall.status||u||"completed";a&&l==="completed"&&(l="error");let d=l==="awaiting_confirmation",A={...e.toolCall.input!==void 0?{input:e.toolCall.input}:{},...e.toolCall.result!==void 0?{result:e.toolCall.result}:{},status:l,frontendOutput:e.toolCall.frontendOutput,llmOutput:e.toolCall.llmOutput,resultMetadata:e.toolCall.resultMetadata,error:c==="failure"?e.toolCall.result.error.message:a?s.error:null,endTime:d?void 0:new Date,...e.toolCall.confirmationState!==void 0?{confirmationState:e.toolCall.confirmationState}:{},...e.toolCall.confirmationData!==void 0?{confirmationData:e.toolCall.confirmationData}:{}},p=t.parts?.map(h=>h.type==="tool"&&h.tool?.id===e.toolCall.id?{...h,tool:{...h.tool,...A}}:h)||[];return{...t,parts:p}}case"done":{if(!t.isStreaming)return t;let n=(t.parts||[]).map(i=>i.type==="tool"&&i.tool&&i.tool.status!=="awaiting_confirmation"?{...i,tool:SM(i.tool)}:i);return{...t,isStreaming:!1,parts:n,content:""}}default:return t}}function spe(t){let e=new Set;for(let r of t)for(let n of(0,bg.getMessageToolCalls)(r))n.status==="awaiting_confirmation"&&e.add(n.id);return[...e]}function ape(t){let e=ipe();return t.map(r=>({...r,parts:r.parts?.map(n=>n.type==="tool"&&n.tool?.status==="awaiting_confirmation"?{...n,tool:{...n.tool,...e}}:n)}))}function cpe(t,e){let r=t.find(i=>i.parts?.some(o=>o.type==="tool"&&o.tool?.id===e));return r?{messages:t.map(i=>i.id===r.id?{...i,isStreaming:!0}:i),targetMessage:{...r,isStreaming:!0}}:{messages:t,targetMessage:null}}function upe(t){return{id:t.id,name:t.name,status:t.status,input:t.input,result:t.result,frontendOutput:t.frontendOutput,llmOutput:t.llmOutput,resultMetadata:t.resultMetadata,error:t.error,startTime:t.startTime,endTime:t.endTime,confirmationState:t.confirmationState,confirmationData:t.confirmationData}}function lpe(t){let{isStreaming:e,tools:r,...n}=t;return JSON.parse((0,bg.safeStringify)({...n,...t.parts?{parts:t.parts.map(i=>i.type==="tool"&&i.tool?{...i,tool:upe(i.tool)}:i)}:{}},0))}yt.AGENT_CONTEXT_MEMORY_MESSAGE_ID_PREFIX="context-memory-";var dpe=["artifacts"];function Hb(t){let e=t.contextType??"";return rpe.TURN_CONTEXT_BLOCK_TYPES.includes(e)||dpe.includes(e)}function Ape(t){return t.filter(e=>e.role!=="system"&&e.contextType!=="memory_notes"&&!Hb(e)&&!e.id.startsWith(yt.AGENT_CONTEXT_MEMORY_MESSAGE_ID_PREFIX)).map(e=>({...e,stale:void 0,isStreaming:void 0}))}function ppe(t){return t.filter(e=>!e.stale&&!e.isStreaming&&e.contextType!=="memory_notes"&&!Hb(e)&&!!e.id)}function fpe(t=[],e=null){return{messages:t,assistantMessageId:e,outcome:"streaming"}}function Cg(t,e){return(0,bg.getMessageToolCalls)(t).some(r=>r.id===e)}function mu(t,e){let r=t.assistantMessageId?t.messages.find(i=>i.id===t.assistantMessageId):void 0;if(r)return{state:t,target:r};let n=CM(t.assistantMessageId??e.createAssistantMessageId());return{state:{...t,messages:[...t.messages,n],assistantMessageId:n.id},target:n}}function hpe(t,e,r){switch(e.type){case"system_message":{if(!e.systemMessage)return t;let n={id:e.systemMessage.id,role:"system",content:e.systemMessage.content,timestamp:new Date};return{...t,messages:[n,...t.messages]}}case"assistant_message_start":{if(!e.assistantMessageId)return t;let n=t.assistantMessageId?t.messages.find(o=>o.id===t.assistantMessageId):void 0;return t.messages.find(o=>o.id===e.assistantMessageId)?{...t,assistantMessageId:e.assistantMessageId,messages:t.messages.filter(o=>!n||n.id===e.assistantMessageId||o.id!==n.id).map(o=>o.id===e.assistantMessageId?{...o,isStreaming:!0}:o)}:n?{...t,assistantMessageId:e.assistantMessageId,messages:t.messages.map(o=>o.id===n.id?{...o,id:e.assistantMessageId,isStreaming:!0}:o)}:{...t,assistantMessageId:e.assistantMessageId}}case"context_message":{if(!e.contextMessage)return t;let n={id:e.contextMessage.id,role:"user",content:e.contextMessage.content,timestamp:new Date,...e.contextMessage.isHidden?{isHidden:!0}:{},...e.contextMessage.attachedFiles?.length?{attachedFiles:e.contextMessage.attachedFiles}:{}};return{...t,assistantMessageId:null,messages:[...t.messages.map(i=>i.id===t.assistantMessageId?{...i,isStreaming:!1}:i),n]}}case"context_usage":case"compaction_start":return t;case"compaction_complete":{if(!e.compaction)return t;let n=(0,bg.applyAgentCompactionToMessages)(t.messages,e.compaction),i=e.compaction.memoryMessage?t.assistantMessageId:null;return!i||!n.some(o=>o.id===i)?{...t,messages:n}:{...t,assistantMessageId:null,messages:n.map(o=>o.id===i?{...o,isStreaming:!1}:o)}}case"content":{let n=mu(t,r);return{...n.state,messages:n.state.messages.map(i=>i.id===n.target.id?zb(i,e.content||""):i)}}case"error":{let n=mu(t,r);return{...n.state,outcome:"failed",messages:n.state.messages.map(i=>i.id!==n.target.id?i:{...i,parts:[...i.parts||[],{type:"error",content:e.content,errorDetails:e.errorDetails,id:`error-${i.parts?.length??0}`}],isStreaming:!1})}}case"tool_call_start":case"tool_call_update":{if(!e.toolCall)return t;let n=e.type==="tool_call_start"?null:t.messages.find(o=>Cg(o,e.toolCall.id))??null,i=n?{state:t,target:n}:mu(t,r);return{...i.state,messages:i.state.messages.map(o=>yu(o,e,i.target))}}case"run_command_effect":{let n=e.toolCallId;if(!n)return t;let i=t.messages.find(o=>Cg(o,n));return i?{...t,messages:t.messages.map(o=>yu(o,e,i))}:t}case"tool_call_input":{if(!e.toolCall)return t;let n=t.messages.find(i=>Cg(i,e.toolCall.id));return n?{...t,messages:t.messages.map(i=>yu(i,e,n))}:t}case"tool_call_complete":{if(!e.toolCall)return t;let n=t.messages.find(o=>Cg(o,e.toolCall.id)),i=n?{state:t,target:n}:mu(t,r);return{...i.state,messages:i.state.messages.map(o=>yu(o,e,i.target))}}case"paused":{let n=mu(t,r);return{...n.state,outcome:"paused",messages:n.state.messages.map(i=>i.id===n.target.id?{...i,isStreaming:!1}:i)}}case"done":{let n=mu(t,r);return{...n.state,outcome:t.outcome==="failed"?"failed":"completed",messages:n.state.messages.map(i=>yu(i,e,n.target))}}default:return t}}});var Sg=m(Et=>{"use strict";Object.defineProperty(Et,"__esModule",{value:!0});Et.PROJECT_LABEL_COLOR_PATTERN=Et.PROJECT_LABEL_COLORS=Et.PROJECT_LIMITS=Et.PROJECT_TASK_STATUSES=Et.PROJECT_RESOURCE_TYPES=void 0;Et.isProjectResourceType=gpe;Et.nextProjectLabelColor=mpe;Et.projectResourceKey=ype;Et.daysUntilTaskDue=_M;Et.formatTaskDueDate=Epe;Et.groupByContext=Ipe;Et.PROJECT_RESOURCE_TYPES=["file","tool"];function gpe(t){return Et.PROJECT_RESOURCE_TYPES.includes(t)}Et.PROJECT_TASK_STATUSES=["not_started","in_progress","waiting","done"];Et.PROJECT_LIMITS={name:80,description:500,taskName:120,taskDescription:1e4,labelName:40,labels:50,taskLabels:10};Et.PROJECT_LABEL_COLORS=["#6b7280","#ef4444","#f97316","#eab308","#22c55e","#14b8a6","#3b82f6","#6366f1","#a855f7","#ec4899"];Et.PROJECT_LABEL_COLOR_PATTERN=/^#[0-9a-f]{6}$/;function mpe(t){let e=new Set(t.map(r=>r.color));return Et.PROJECT_LABEL_COLORS.find(r=>!e.has(r))??Et.PROJECT_LABEL_COLORS[t.length%Et.PROJECT_LABEL_COLORS.length]}function ype(t){return`${t.type}:${t.id}`}function BM(t){let e=new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(new Date);return new Date(`${e}T00:00:00Z`)}function _M(t,e){let r=new Date(`${t}T00:00:00Z`);return Math.round((r.getTime()-BM(e).getTime())/864e5)}function Epe(t,e){let r=new Date(`${t}T00:00:00Z`),n=BM(e),i=_M(t,e);return i===0?"Due today":i===1?"Due tomorrow":i===-1?"Due yesterday":i<-1?`${-i} days overdue`:i<7?`Due ${r.toLocaleDateString(void 0,{weekday:"long",timeZone:"UTC"})}`:`Due ${r.toLocaleDateString(void 0,{day:"numeric",month:"short",timeZone:"UTC",...r.getUTCFullYear()===n.getUTCFullYear()?{}:{year:"numeric"}})}`}function Ipe(t){let e=new Map;for(let r of t)e.set(r.context,[...e.get(r.context)??[],r]);return[...e].map(([r,n])=>({context:r,items:n})).sort((r,n)=>+!!r.context-+!!n.context)}});var wg=m(Gr=>{"use strict";Object.defineProperty(Gr,"__esModule",{value:!0});Gr.RESOURCE_KINDS=Gr.RESOURCE_DEFINITIONS=void 0;Gr.isResourceKind=Cpe;Gr.getResourceDefinition=bpe;Gr.getResourceAppPath=Spe;Gr.RESOURCE_DEFINITIONS={tool:{label:"Tool",pluralLabel:"Tools",collectionKey:"tools",appPath:"/tools",hasDetailPage:!0,memberDefaultPermission:"editor",pickerDefaultPermission:"editor"},credential:{label:"Connection",pluralLabel:"Connections",collectionKey:"credentials",appPath:"/connections",hasDetailPage:!0,pickerDefaultPermission:"viewer"},playbook:{label:"Playbook",pluralLabel:"Playbooks",collectionKey:"playbooks",appPath:"/brain/playbooks",hasDetailPage:!0,pickerDefaultPermission:"editor"},file:{label:"File",pluralLabel:"Files",collectionKey:"files",appPath:"/brain/files",hasDetailPage:!0,pickerDefaultPermission:"viewer"},project:{label:"Project",pluralLabel:"Projects",collectionKey:"projects",appPath:"/brain/projects",hasDetailPage:!0,pickerDefaultPermission:"viewer"}};Gr.RESOURCE_KINDS=Object.keys(Gr.RESOURCE_DEFINITIONS);function Cpe(t){return typeof t=="string"&&Object.prototype.hasOwnProperty.call(Gr.RESOURCE_DEFINITIONS,t)}function bpe(t){return Gr.RESOURCE_DEFINITIONS[t]}function Spe(t,e){let r=Gr.RESOURCE_DEFINITIONS[t];return r.hasDetailPage?`${r.appPath}/${encodeURIComponent(e)}`:r.appPath}});var DM=m(La=>{"use strict";Object.defineProperty(La,"__esModule",{value:!0});La.SDK_ERROR_DETAILS_SCHEMA=La.SDK_OUTPUT_CONTRACTS=void 0;La.toSdkJsonSchema=vpe;var y=Ia(),wpe=Sg(),Bpe=wg(),_pe=Lr();function vpe({schema:t}){return y.z.toJSONSchema(t,{target:"draft-7",io:"output",unrepresentable:"any"})}var vM=y.z.looseObject({statusCode:y.z.number(),headers:y.z.record(y.z.string(),y.z.union([y.z.string(),y.z.array(y.z.string())])),omittedHeaderCount:y.z.number().optional()}),QM=y.z.looseObject({vfsPath:y.z.string(),storedBytes:y.z.number(),originalOutputBytes:y.z.number(),storageTruncated:y.z.boolean()}),TM=y.z.object({action:y.z.enum(["approve","reject","oauth_success","oauth_failure"]),source:y.z.enum(["user","automatic"])});function Yr(t){return y.z.looseObject({toolCallId:y.z.string(),toolName:y.z.string(),outcome:y.z.literal("success"),confirmation:TM.optional(),data:t})}var qb={http:vM.optional(),credential:y.z.looseObject({id:y.z.string(),name:y.z.string(),isOwner:y.z.boolean()}).optional().describe("The credential the call ran with."),auth:y.z.looseObject({applied:y.z.enum(["bearer","basic","explicit","none","unavailable"]),header:y.z.string().optional(),placeholders:y.z.array(y.z.string()),reason:y.z.string().optional()}).optional().describe("How authentication was sent: a default Bearer or Basic header, the request's own explicit placeholders, none, or unavailable with the reason. placeholders lists the credential's <<systemId_secretName>> strings."),credentialPlaceholders:y.z.looseObject({keys:y.z.array(y.z.string()),resolved:y.z.boolean()}).optional()},Qpe=y.z.discriminatedUnion("protocol",[y.z.looseObject({protocol:y.z.enum(["postgres","odbc"]),data:y.z.array(y.z.record(y.z.string(),y.z.unknown())).describe("Returned database rows."),...qb}),y.z.looseObject({protocol:y.z.literal("mssql"),data:y.z.union([y.z.array(y.z.record(y.z.string(),y.z.unknown())),y.z.array(y.z.array(y.z.record(y.z.string(),y.z.unknown()))),y.z.looseObject({rowsAffected:y.z.array(y.z.number())})]).describe("One recordset, multiple recordsets, or affected row counts."),...qb}),y.z.looseObject({protocol:y.z.enum(_pe.CONNECTION_PROTOCOLS.filter(t=>t!=="postgres"&&t!=="mssql"&&t!=="odbc")),data:y.z.unknown().describe("Complete protocol response payload. Preserve sibling fields, including files and metadata; do not unwrap a nested data field."),...qb})]),Tpe=y.z.union([y.z.looseObject({tools:y.z.array(y.z.unknown()).describe("All tools from every tools/list page, each with name and inputSchema.")}),y.z.looseObject({result:y.z.looseObject({content:y.z.array(y.z.unknown()).optional(),structuredContent:y.z.unknown().optional(),isError:y.z.boolean().optional()}).describe("The tools/call result with content blocks and optional structuredContent.")})]),Dpe=y.z.looseObject({url:y.z.string().describe("The requested URL."),status:y.z.number(),statusText:y.z.string(),headers:y.z.record(y.z.string(),y.z.string()),body:y.z.string().describe("Response body bytes, base64-encoded."),systemId:y.z.string().optional().describe("The system whose credential authenticated the request."),credential:y.z.looseObject({id:y.z.string(),name:y.z.string(),isOwner:y.z.boolean()}).optional().describe("The credential the request ran with.")}),Rpe=y.z.looseObject({stepId:y.z.string(),success:y.z.boolean(),data:y.z.unknown().optional(),error:y.z.string().nullable().optional(),http:vM.optional(),stepFileKeys:y.z.array(y.z.string()).optional()}),Npe=y.z.looseObject({toolId:y.z.string(),success:y.z.boolean(),run:y.z.looseObject({id:y.z.string()}).optional(),data:y.z.unknown().optional().describe("Tool output, determined by its output transform."),error:y.z.string().optional(),stepResults:y.z.array(Rpe),fileArtifacts:y.z.array(y.z.looseObject({fileKey:y.z.string(),filename:y.z.string(),contentType:y.z.string(),size:y.z.number(),downloadUrl:y.z.string().optional()})).optional(),warnings:y.z.array(y.z.string()).optional(),inputSchema:y.z.unknown().optional(),resultMetadata:QM.optional()}),kpe=Yr(y.z.looseObject({resource:y.z.looseObject({id:y.z.string(),name:y.z.string().optional(),path:y.z.string().optional(),version:y.z.union([y.z.number(),y.z.string()]).optional()}),created:y.z.boolean(),projectId:y.z.string().optional(),projectAttribution:y.z.looseObject({attached:y.z.boolean(),projectId:y.z.string(),projectName:y.z.string().optional(),resource:y.z.looseObject({type:y.z.enum(wpe.PROJECT_RESOURCE_TYPES),id:y.z.string()}),error:y.z.string().optional()}).optional()}));La.SDK_OUTPUT_CONTRACTS={assignSessionToProject:{name:"SuperglueSessionProjectResult",schema:Yr(y.z.object({sessionId:y.z.string(),projectId:y.z.string().nullable()})),description:"Returns the saved session ID and project ID, or null when unassigned. Throws SuperglueError on failure."},callSystem:{name:"SuperglueCallSystemResult",schema:Qpe,description:"Returns the complete protocol payload in data, available HTTP metadata, the credential used, and how authentication was sent. Throws SuperglueError on failure; details contains the canonical result and unprojected execution output."},callMcp:{name:"SuperglueCallMcpResult",schema:Tpe,description:"Returns { tools } when tool is omitted, or { result } from tools/call. Throws SuperglueError on HTTP, JSON-RPC, or result.isError failures; details.result.data contains statusCode, rpcError, or the failed result. On result.isError or invalid params, the error message ends with the called tool's input schema when it can be read; large schemas are shortened."},systemFetch:{name:"SuperglueSystemFetchResult",schema:Dpe,description:"Returns the raw HTTP response: status, headers, and the base64 body. HTTP error statuses are returned, not thrown. Throws SuperglueError when the request cannot be authenticated or sent."},runTool:{name:"SuperglueRunToolResult",schema:Npe,description:"Returns successful tool output, step results, files, and available result reference. Throws SuperglueError on failure; details.result.data preserves this result shape with success: false, the error, and available run and step results. details.resultMetadata references the saved failed result when available."},writeResource:{name:"SuperglueWriteResult",schema:kpe,description:"Returns saved resource identity and path, creation status, and available project attribution. Throws SuperglueError on failure."},installBundle:{name:"SuperglueBundleInstallResult",schema:Yr(y.z.looseObject({bundleId:y.z.string(),system:y.z.looseObject({id:y.z.string(),name:y.z.string(),requiredCredentialKeys:y.z.array(y.z.string()),hasUserCredentials:y.z.boolean()}),tools:y.z.array(y.z.looseObject({id:y.z.string(),name:y.z.string().optional()})),mcpServer:y.z.looseObject({id:y.z.string(),name:y.z.string()}).optional(),playbook:y.z.looseObject({id:y.z.string(),name:y.z.string()}).optional()})),description:"Returns the installed system ID, tool, MCP server, and playbook identities, the secret names the user must supply, and whether the user has a complete connection. Throws SuperglueError on failure."},stopBackgroundJob:{name:"SuperglueStopBackgroundJobResult",schema:Yr(y.z.looseObject({job:y.z.looseObject({id:y.z.string(),status:y.z.string(),elapsedMs:y.z.number(),exitCode:y.z.number().optional()})})),description:"Returns the job's status, run time, and exit code after it ended, or status running when the stop is still in progress. Throws SuperglueError when the session has no such running job."},setToolState:{name:"SuperglueToolStateResult",schema:Yr(y.z.looseObject({resource:y.z.looseObject({id:y.z.string()}),action:y.z.enum(["set","reset"])})),description:"Returns the saved tool identity and state action. Throws SuperglueError on failure."},shareResource:{name:"SuperglueShareResult",schema:Yr(y.z.looseObject({resource:y.z.looseObject({kind:y.z.enum(Bpe.RESOURCE_KINDS),id:y.z.string()})})),description:"Returns the shared resource identity. Throws SuperglueError on failure."},useChecklist:{name:"SuperglueChecklistResult",schema:Yr(y.z.strictObject({visible:y.z.boolean(),done:y.z.number(),total:y.z.number()})),description:"Returns whether the session checklist is visible and its completed and total milestone counts. The progress panel updates immediately. Throws SuperglueError on failure."},showVisual:{name:"SuperglueShowVisualResult",schema:Yr(y.z.looseObject({visualId:y.z.string(),check:y.z.looseObject({errors:y.z.array(y.z.string()),blockedRequests:y.z.array(y.z.string()),dataCalls:y.z.array(y.z.string()),contentHeight:y.z.number().optional(),timedOut:y.z.boolean()}).optional(),checkSkipped:y.z.string().optional(),screenshots:y.z.array(y.z.string()).optional()})),description:"Returns the visualId shown to the user. For a custom visual, check holds the test-browser result, and screenshots lists the labels of the screenshots attached to this command's result for you. Throws SuperglueError ETOOL when the visual fails its check; error.details.result.data.check then holds the errors."},notifyUser:{name:"SuperglueNotifyResult",schema:Yr(y.z.looseObject({nextStepIds:y.z.array(y.z.string())})),description:"Returns the nextStepIds of the saved actions, in action order. Throws SuperglueError on failure."},writeOrgSettings:{name:"SuperglueOrgSettingsResult",schema:Yr(y.z.looseObject({updated:y.z.array(y.z.enum(["name","preferences","notifications"])),notificationTest:y.z.looseObject({channel:y.z.enum(["slack","email"]),sent:y.z.boolean(),error:y.z.string().optional()}).optional()})),description:"Returns updated settings and any notification test result. Throws SuperglueError on failure."},writeDesignSystem:{name:"SuperglueDesignSystemResult",schema:Yr(y.z.looseObject({updated:y.z.array(y.z.enum(["tokens","guidelines","logo"])),added:y.z.array(y.z.looseObject({id:y.z.string(),kind:y.z.enum(["logo","font","template","reference"]),name:y.z.string()})),changed:y.z.array(y.z.string()),removed:y.z.array(y.z.string())})),description:"Returns the changed design-system parts and file ids. Throws SuperglueError on failure."},importDesignSystemFromUrl:{name:"SuperglueDesignSystemImportResult",schema:Yr(y.z.looseObject({url:y.z.string(),title:y.z.string().nullable(),tokens:y.z.looseObject({}),palette:y.z.array(y.z.looseObject({color:y.z.string(),weight:y.z.number()})),fonts:y.z.array(y.z.looseObject({family:y.z.string(),usage:y.z.array(y.z.string()),source:y.z.string()})),fontFiles:y.z.array(y.z.looseObject({file:y.z.string(),family:y.z.string().describe("CSS family name the website uses"),roles:y.z.array(y.z.string()),weight:y.z.string(),style:y.z.enum(["normal","italic"])})),logos:y.z.array(y.z.looseObject({file:y.z.string(),source:y.z.string(),width:y.z.number(),height:y.z.number(),light:y.z.boolean().describe("Light artwork meant for dark backgrounds")})),screenshot:y.z.string().nullable()})),description:"Returns a proposed design system from the website; font files, logos, and the screenshot are file:: session uploads. Throws SuperglueError on failure."},readQbm:{name:"SuperglueReadQbmResult",schema:Yr(y.z.looseObject({folder:y.z.string(),objects:y.z.array(y.z.looseObject({type:y.z.string(),files:y.z.array(y.z.string()),records:y.z.number()})),rawTables:y.z.array(y.z.looseObject({table:y.z.string(),files:y.z.array(y.z.string()),rows:y.z.number()})),encryptedValues:y.z.array(y.z.looseObject({table:y.z.string(),column:y.z.string(),values:y.z.number()})),unmappedCodes:y.z.array(y.z.looseObject({field:y.z.string(),code:y.z.string(),records:y.z.number()})).optional(),attachments:y.z.looseObject({documents:y.z.number(),note:y.z.string()}).optional(),rejectedRows:y.z.array(y.z.looseObject({table:y.z.string(),rows:y.z.number()})).optional()})),description:"Returns the folder that holds the extracted files, record counts per object type and raw table, encrypted columns, codes the reader cannot decode, and expected attachments. The folder also holds coverage.json.raw with the same summary plus the mapped source tables. Throws SuperglueError on failure."},previewFile:{name:"SuperglueFilePreviewResult",schema:y.z.looseObject({draftId:y.z.string(),bytes:y.z.number()}),description:"Returns the HTML draft identity and byte count. Throws SuperglueError on failure."}};var Ope=y.z.looseObject({code:y.z.string(),path:y.z.array(y.z.union([y.z.string(),y.z.number(),y.z.symbol()])),message:y.z.string()});La.SDK_ERROR_DETAILS_SCHEMA=y.z.discriminatedUnion("kind",[y.z.looseObject({kind:y.z.literal("tool_result"),resultMetadata:QM.optional(),result:y.z.looseObject({toolCallId:y.z.string(),toolName:y.z.string(),outcome:y.z.enum(["success","failure","rejected","aborted"]),confirmation:TM.optional(),error:y.z.looseObject({message:y.z.string()}).optional(),data:y.z.unknown().optional()}),output:y.z.unknown().describe("Unprojected execution output, including the original error and any available response data or metadata.")}),y.z.looseObject({kind:y.z.enum(["input_validation","output_validation"]),toolName:y.z.string(),issues:y.z.array(Ope),output:y.z.unknown().optional()})])});var jM=m(we=>{"use strict";Object.defineProperty(we,"__esModule",{value:!0});we.SERVER_OWNED_SESSION_RESOURCE_KINDS=we.AgentRequestValidationError=we.AGENT_TOOL_CONTINUATION_ACTION_BY_CONFIRMATION_STATE=we.AGENT_TOOL_CONTINUATION_ACTIONS=we.AGENT_IDENTIFIER_PATTERN=we.AGENT_REQUEST_LIMITS=void 0;we.validateAgentRequestPayload=MM;we.validateResourceBinding=LM;we.validateClientResourceBinding=PM;we.validateAgentSessionIdentity=$M;we.validateAgentSessionTarget=FM;we.validateAgentRequestSubmission=Fpe;we.isAgentMessagePayload=jpe;we.isAgentToolContinuationPayload=zpe;var qo=Lr();we.AGENT_REQUEST_LIMITS={messageContentChars:5e4,identifierChars:256,attachedFiles:20,toolContinuations:20,continuationInputChars:1e5,frontendDraftsChars:2e6,accessRulesContextChars:2e6,pendingMessagesPerSession:10};we.AGENT_IDENTIFIER_PATTERN=/^[A-Za-z0-9._-]+$/;we.AGENT_TOOL_CONTINUATION_ACTIONS=["approve","reject","oauth_success","oauth_failure"];we.AGENT_TOOL_CONTINUATION_ACTION_BY_CONFIRMATION_STATE={[qo.ConfirmationAction.CONFIRMED]:"approve",[qo.ConfirmationAction.DECLINED]:"reject",[qo.ConfirmationAction.OAUTH_SUCCESS]:"oauth_success",[qo.ConfirmationAction.OAUTH_FAILURE]:"oauth_failure"};var Bg=class extends Error{constructor(e){super(e),this.name="AgentRequestValidationError"}};we.AgentRequestValidationError=Bg;function Je(t){throw new Bg(t)}function po(t,e){return(!t||typeof t!="object"||Array.isArray(t))&&Je(`${e} must be an object`),t}function Pa(t,e){(typeof t!="string"||!t.trim())&&Je(`${e} must be a non-empty string`);let r=t.trim();return r.length>we.AGENT_REQUEST_LIMITS.identifierChars&&Je(`${e} exceeds ${we.AGENT_REQUEST_LIMITS.identifierChars} characters`),we.AGENT_IDENTIFIER_PATTERN.test(r)||Je(`${e} may only contain letters, numbers, dots, underscores, and hyphens`),r}function Upe(t,e){return typeof t!="boolean"&&Je(`${e} must be a boolean`),t}function Gb(t,e){try{return JSON.stringify(t).length}catch{return Je(`${e} must be JSON-serializable`)}}function xpe(t,e){if(t!==void 0)return Array.isArray(t)||Je(`${e} must be an array`),t.length>we.AGENT_REQUEST_LIMITS.attachedFiles&&Je(`${e} exceeds ${we.AGENT_REQUEST_LIMITS.attachedFiles} entries`),t.map((r,n)=>{let i=po(r,`${e}[${n}]`);return{...i,key:Pa(i.key,`${e}[${n}].key`)}})}function RM({value:t,label:e,requireHidden:r}){let n=po(t,e),i=Pa(n.id,`${e}.id`);typeof n.content!="string"&&Je(`${e}.content must be a string`);let o=n.content;o.length>we.AGENT_REQUEST_LIMITS.messageContentChars&&Je(`${e}.content exceeds ${we.AGENT_REQUEST_LIMITS.messageContentChars} characters`);let s=Upe(n.isHidden,`${e}.isHidden`);r&&!s&&Je(`${e}.isHidden must be true`);let a=xpe(n.attachedFiles,`${e}.attachedFiles`);return!o.trim()&&!a?.length&&Je(`${e}.content may only be empty when an attachment is present`),{id:i,content:o,isHidden:s,...a?{attachedFiles:a}:{}}}function kM(t){if(t===void 0)return;let e=po(t,"frontendDrafts");return Gb(e,"frontendDrafts")>we.AGENT_REQUEST_LIMITS.frontendDraftsChars&&Je(`frontendDrafts exceeds ${we.AGENT_REQUEST_LIMITS.frontendDraftsChars} characters`),e}function OM(t){if(t===void 0)return;let e=po(t,"accessRulesContext");return Gb(e,"accessRulesContext")>we.AGENT_REQUEST_LIMITS.accessRulesContextChars&&Je(`accessRulesContext exceeds ${we.AGENT_REQUEST_LIMITS.accessRulesContextChars} characters`),e}function UM(t){if(t!==void 0)return(typeof t!="string"||!qo.AGENT_APPROVAL_MODES.includes(t))&&Je(`request.approvalMode must be one of: ${qo.AGENT_APPROVAL_MODES.join(", ")}`),t}function xM(t,e){let r=po(t,e),n=Pa(r.toolCallId,`${e}.toolCallId`);return(typeof r.action!="string"||!we.AGENT_TOOL_CONTINUATION_ACTIONS.includes(r.action))&&Je(`${e}.action must be one of: ${we.AGENT_TOOL_CONTINUATION_ACTIONS.join(", ")}`),r.input!==void 0&&Gb(r.input,`${e}.input`)>we.AGENT_REQUEST_LIMITS.continuationInputChars&&Je(`${e}.input exceeds ${we.AGENT_REQUEST_LIMITS.continuationInputChars} characters`),{toolCallId:n,action:r.action,...r.input!==void 0?{input:r.input}:{}}}function Mpe(t){if(t===void 0)return;(!Array.isArray(t)||t.length===0)&&Je("request.toolContinuations must be a non-empty array"),t.length>we.AGENT_REQUEST_LIMITS.toolContinuations&&Je(`request.toolContinuations exceeds ${we.AGENT_REQUEST_LIMITS.toolContinuations} entries`);let e=t.map((r,n)=>xM(r,`request.toolContinuations[${n}]`));return new Set(e.map(({toolCallId:r})=>r)).size!==e.length&&Je("request.toolContinuations must not contain duplicate toolCallId values"),e}function NM(t,e){if(t===void 0)return;(typeof t!="string"||!t.trim())&&Je(`${e} must be a non-empty string`);let r=t.trim();return r.length>we.AGENT_REQUEST_LIMITS.messageContentChars&&Je(`${e} exceeds ${we.AGENT_REQUEST_LIMITS.messageContentChars} characters`),r}var Lpe=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Ppe(t){let e=RM({value:t.message,label:"request.message"}),r=NM(t.title,"request.title"),n=NM(t.titleInput,"request.titleInput"),i=t.hiddenSteeringMessage===void 0?void 0:RM({value:t.hiddenSteeringMessage,label:"request.hiddenSteeringMessage",requireHidden:!0});i&&i.id===e.id&&Je("request.hiddenSteeringMessage.id must differ from request.message.id");let o=Mpe(t.toolContinuations),s=UM(t.approvalMode),a=kM(t.frontendDrafts),c=OM(t.accessRulesContext);return t.nextStepId!==void 0&&(typeof t.nextStepId!="string"||!Lpe.test(t.nextStepId))&&Je("request.nextStepId must be a UUID"),{kind:"message",message:e,...t.nextStepId?{nextStepId:t.nextStepId}:{},...i?{hiddenSteeringMessage:i}:{},...r?{title:r}:{},...n?{titleInput:n}:{},...o?{toolContinuations:o}:{},...s?{approvalMode:s}:{},...a?{frontendDrafts:a}:{},...c?{accessRulesContext:c}:{}}}function $pe(t){let e=xM(t,"request"),r=UM(t.approvalMode),n=kM(t.frontendDrafts),i=OM(t.accessRulesContext);return{kind:"tool_continuation",...e,...r?{approvalMode:r}:{},...n?{frontendDrafts:n}:{},...i?{accessRulesContext:i}:{}}}function MM(t){let e=po(t,"request");return e.kind==="message"?Ppe(e):e.kind==="tool_continuation"?$pe(e):Je('request.kind must be "message" or "tool_continuation"')}function LM(t,e){let r=po(t,e);return(typeof r.kind!="string"||!qo.AGENT_SESSION_RESOURCE_KINDS.includes(r.kind))&&Je(`${e}.kind must be one of: ${qo.AGENT_SESSION_RESOURCE_KINDS.join(", ")}`),{kind:r.kind,id:Pa(r.id,`${e}.id`)}}we.SERVER_OWNED_SESSION_RESOURCE_KINDS=["briefing"];function PM(t,e){let r=LM(t,e);return we.SERVER_OWNED_SESSION_RESOURCE_KINDS.includes(r.kind)&&Je(`${e}.kind "${r.kind}" is assigned by the server`),r}function $M(t,e="session.createIfMissing"){let r=po(t,e),n=r.projectId===void 0?void 0:Pa(r.projectId,`${e}.projectId`),i=r.taskId===void 0?void 0:Pa(r.taskId,`${e}.taskId`);i&&!n&&Je(`${e}.taskId requires ${e}.projectId`);let o=Object.values(qo.AgentType);(typeof r.agentId!="string"||!o.includes(r.agentId))&&Je(`${e}.agentId must be one of: ${o.join(", ")}`);let s=r.resourceBinding===void 0?void 0:PM(r.resourceBinding,`${e}.resourceBinding`);return{agentId:r.agentId,...n?{projectId:n}:{},...i?{taskId:i}:{},...s?{resourceBinding:s}:{}}}function FM(t){let e=po(t,"session"),r=e.createIfMissing===void 0?void 0:$M(e.createIfMissing);return{id:Pa(e.id,"session.id"),...r?{createIfMissing:r}:{}}}function Fpe(t){let e=po(t,"body");return{session:FM(e.session),request:MM(e.request)}}function jpe(t){return t.kind==="message"}function zpe(t){return t.kind==="tool_continuation"}});var HM=m(Re=>{"use strict";Object.defineProperty(Re,"__esModule",{value:!0});Re.ARTIFACT_EXPORT_FORMATS=Re.ARTIFACT_RESPONSE_RESERVED_FIELD_NAMES=Re.ARTIFACT_RESPONSE_PATCH_DEBOUNCE_MS=Re.MAX_SPREADSHEET_ARTIFACT_BYTES=Re.MAX_HTML_ARTIFACT_IMAGE_BYTES=Re.MAX_HTML_ARTIFACT_BYTES=Re.MAX_SPREADSHEET_CELL_TEXT_LENGTH=Re.MAX_SPREADSHEET_SHEET_NAME_LENGTH=Re.MAX_SPREADSHEET_GRID_CELLS=Re.MAX_SPREADSHEET_SHEETS=Re.SPREADSHEET_CELL_TYPES=Re.XLSX_CONTENT_TYPE=Re.HTML_CONTENT_TYPE=void 0;Re.brainFileDisplayTitle=Hpe;Re.brainFileKind=qpe;Re.isValidSpreadsheetCell=Vpe;Re.isArtifactExportFormat=Jpe;Re.isArtifactExportFormatForKind=Wpe;var zM=Ia();Re.HTML_CONTENT_TYPE="text/html";Re.XLSX_CONTENT_TYPE="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";function Hpe(t){return t.replace(/\.[a-z][a-z0-9]{0,7}$/i,"")||t}function qpe({fileName:t,contentType:e}){let r=e?.split(";")[0].trim().toLowerCase(),n=t.toLowerCase().match(/\.([a-z0-9]+)$/)?.[1];return r===Re.HTML_CONTENT_TYPE||n==="html"||n==="htm"?"html":r===Re.XLSX_CONTENT_TYPE||n==="xlsx"?"spreadsheet":"file"}Re.SPREADSHEET_CELL_TYPES=["text","integer","number","percent","currency","boolean","date","datetime"];Re.MAX_SPREADSHEET_SHEETS=20;Re.MAX_SPREADSHEET_GRID_CELLS=1e6;Re.MAX_SPREADSHEET_SHEET_NAME_LENGTH=31;Re.MAX_SPREADSHEET_CELL_TEXT_LENGTH=32767;var Gpe=zM.z.iso.date(),Ype=zM.z.iso.datetime({offset:!0});function Vpe(t,e){return t===null?!0:e==="text"?typeof t=="string"&&t.length<=Re.MAX_SPREADSHEET_CELL_TEXT_LENGTH:e==="boolean"?typeof t=="boolean":["integer","number","percent","currency"].includes(e)?typeof t=="number"&&Number.isFinite(t)&&(e!=="integer"||Number.isInteger(t)):typeof t!="string"?!1:(e==="datetime"?Ype:Gpe).safeParse(t).success}Re.MAX_HTML_ARTIFACT_BYTES=1024*1024;Re.MAX_HTML_ARTIFACT_IMAGE_BYTES=12*1024*1024;Re.MAX_SPREADSHEET_ARTIFACT_BYTES=10*1024*1024;Re.ARTIFACT_RESPONSE_PATCH_DEBOUNCE_MS=300;Re.ARTIFACT_RESPONSE_RESERVED_FIELD_NAMES=new Set(["__proto__","constructor","prototype"]);Re.ARTIFACT_EXPORT_FORMATS=["pdf","docx","xlsx","pptx"];function Jpe(t){return Re.ARTIFACT_EXPORT_FORMATS.some(e=>e===t)}function Wpe(t,e,r=!1){return t==="spreadsheet"?e==="xlsx":r?e==="pdf"||e==="pptx":e!=="pptx"}});var JM=m(He=>{"use strict";Object.defineProperty(He,"__esModule",{value:!0});He.API_KEY_ACTION_LABELS=He.API_KEY_SURFACE_LABELS=He.API_KEY_SCOPES=He.API_KEY_SURFACE_ACTIONS=He.API_KEY_ACTIONS=He.API_KEY_SURFACES=void 0;He.getApiKeySurface=GM;He.getApiKeyAction=YM;He.getApiKeySurfaceActions=Yb;He.parseApiKeyScopes=VM;He.validateApiKeyScopesInput=efe;He.isApiKeyScopeAllowed=tfe;He.formatApiKeyScopes=rfe;He.API_KEY_SURFACES=["api","mcp"];He.API_KEY_ACTIONS=["read","write","execute"];He.API_KEY_SURFACE_ACTIONS={api:He.API_KEY_ACTIONS,mcp:["execute"]};He.API_KEY_SCOPES=He.API_KEY_SURFACES.flatMap(t=>He.API_KEY_SURFACE_ACTIONS[t].map(e=>`${t}:${e}`));He.API_KEY_SURFACE_LABELS={api:"API & CLI",mcp:"MCP"};He.API_KEY_ACTION_LABELS={read:"Read",write:"Write",execute:"Execute"};var qM=new Set(He.API_KEY_SCOPES),Zpe={"/v1/tools":["read"],"/v1/tools/:toolId/run":["execute"],"/v1/authenticate":["write"],"/v1/memory-notes":["read","write"]},Kpe=new Set(["/v1/api-keys","/v1/api-keys/:id","/v1/api-keys/:id/reveal"]),Xpe=new Set(["/v1/me"]);function GM(t){let e=t.split("?")[0];return e==="/mcp"||e.startsWith("/mcp/")?"mcp":"api"}function YM(t){return t==="read"?"read":t==="execute"?"execute":"write"}function Yb(t,e){return He.API_KEY_SURFACE_ACTIONS[e].filter(r=>(t||[]).includes(`${e}:${r}`))}function VM(t){if(!Array.isArray(t))return null;let e=[...new Set(t.filter(r=>qM.has(r)))];return e.length>0?e:null}function efe(t){if(t==null)return{scopes:null};let e=`Valid scopes: ${He.API_KEY_SCOPES.join(", ")}. Use null for full access.`;if(!Array.isArray(t)||t.length===0)return{error:`scopes must be a non-empty array of API key scopes. ${e}`};let r=t.filter(n=>!qM.has(n));return r.length>0?{error:`Unknown API key scope(s): ${r.map(String).join(", ")}. ${e}`}:{scopes:VM(t)}}function tfe({scopes:t,path:e,type:r}){if(!t||t.length===0)return!0;let n=e.split("?")[0];if(Kpe.has(n))return!1;if(Xpe.has(n))return!0;let i=YM(r),o=GM(n);return o==="api"&&Zpe[n]?.some(s=>s===r)&&Yb(t,"mcp").length>0?!0:t.includes(`${o}:${i}`)}function rfe(t){return!t||t.length===0?"Full access":He.API_KEY_SURFACES.map(e=>({surface:e,actions:Yb(t,e)})).filter(e=>e.actions.length>0).map(e=>He.API_KEY_SURFACE_ACTIONS[e.surface].length===1?He.API_KEY_SURFACE_LABELS[e.surface]:`${He.API_KEY_SURFACE_LABELS[e.surface]} ${e.actions.join("/")}`).join(", ")}});var WM=m(Vb=>{"use strict";Object.defineProperty(Vb,"__esModule",{value:!0});Vb.isValidEmail=nfe;function nfe(t){return/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)*\.[a-zA-Z]{1,}$/.test(t)}});var KM=m(It=>{"use strict";Object.defineProperty(It,"__esModule",{value:!0});It.GATEWAY_UNINSTALL_COMMANDS=It.GATEWAY_API_KEY_NAME_PREFIX=It.GATEWAY_TARGET_NAME_PATTERN=It.GATEWAY_SETUP_GUIDE_URL=It.GATEWAY_DOWNLOAD_BASE_URL=It.GATEWAY_INSTALL_TOKEN_PREFIX=void 0;It.getGatewayServerUrl=ZM;It.buildGatewayInstallToken=ofe;It.buildGatewayInstallCommand=sfe;It.getGatewayApiKeyName=afe;It.GATEWAY_INSTALL_TOKEN_PREFIX="sgi1.";It.GATEWAY_DOWNLOAD_BASE_URL="https://downloads.superglue.cloud";It.GATEWAY_SETUP_GUIDE_URL="https://superglue.ai/docs/guides/secure-gateway/";It.GATEWAY_TARGET_NAME_PATTERN=/^[a-z0-9]([a-z0-9_-]{0,61}[a-z0-9])?$/;function ZM(t){let e=new URL(t);return e.protocol=e.protocol==="http:"?"ws:":"wss:",e.pathname=`${e.pathname.replace(/\/+$/,"")}/ws/tunnels`,e.search="",e.hash="",e.toString()}function ife(t){let e=new TextEncoder().encode(t),r="";for(let n of e)r+=String.fromCharCode(n);return btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function ofe(t){let e={v:1,serverUrl:ZM(t.apiEndpoint),tunnelId:t.tunnelId,apiKey:t.apiKey,targets:t.targets,enableScriptRunner:t.enableScriptRunner};return It.GATEWAY_INSTALL_TOKEN_PREFIX+ife(JSON.stringify(e))}function sfe(t,e){return t==="windows"?[`$install = { ${["$ErrorActionPreference = 'Stop'","[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072","$ProgressPreference = 'SilentlyContinue'","$gateway = Join-Path $env:TEMP 'superglue-gateway.exe'","Remove-Item $gateway -Force -ErrorAction SilentlyContinue",`Invoke-WebRequest -UseBasicParsing '${It.GATEWAY_DOWNLOAD_BASE_URL}/superglue-gateway-windows.exe' -OutFile $gateway`,`'${e}' | & $gateway install -`].join("; ")} }`,`if (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { & $install } else { Start-Process powershell -Verb RunAs -ErrorAction Stop -ArgumentList "-NoExit -Command & {$install}"; 'Continue in the administrator PowerShell window.' }`].join("; "):["d=$(mktemp -d)",`u="${It.GATEWAY_DOWNLOAD_BASE_URL}/superglue-gateway-linux-$(uname -m | sed 's/aarch64/arm64/')"`,'s=$([ "$(id -u)" -eq 0 ] || echo sudo)','{ if command -v curl >/dev/null; then curl -fsSL -o "$d/superglue-gateway" "$u"; else wget -qO "$d/superglue-gateway" "$u"; fi; }','$s install -m 0755 "$d/superglue-gateway" /usr/local/bin/superglue-gateway',`echo '${e}' | $s /usr/local/bin/superglue-gateway install -`].join(" && ")}It.GATEWAY_API_KEY_NAME_PREFIX="Gateway: ";function afe(t){return It.GATEWAY_API_KEY_NAME_PREFIX+t}It.GATEWAY_UNINSTALL_COMMANDS={windows:'& "C:\\Program Files\\superglue Gateway\\superglue-gateway.exe" uninstall',linux:"sudo /usr/local/bin/superglue-gateway uninstall"}});var vg=m(he=>{"use strict";Object.defineProperty(he,"__esModule",{value:!0});he.OAUTH_TOKEN_CREDENTIAL_KEYS=he.OAUTH_CONFIG_CREDENTIAL_KEYS=void 0;he.hasMeaningfulValue=Ct;he.stringValue=Gt;he.validateOAuthConnection=yfe;he.formatOAuthConnectionDisabledReason=Ife;he.objectValue=Yo;he.parseScopes=Hd;he.normalizeGrantType=qd;he.normalizeOAuthClientMode=Zb;he.normalizeSystemAuthentication=fr;he.resolveOAuthClientMode=bfe;he.flattenSystemAuthentication=nL;he.maskedFlatSystemAuthentication=Sfe;he.isMaskedSecretValue=iL;he.pickAgentAuthInputFields=wfe;he.maskSystemAuthenticationForResponse=Bfe;he.restoreMaskedClientSecret=_fe;he.mapAgentAuthInput=oL;he.mergeAgentAuthInput=xfe;he.getAuthenticationConfigCredentialKeys=sL;he.buildAuthenticationEditorModel=Mfe;he.getCredentialRequirements=Lfe;he.isCredentialRequirementSatisfied=aL;he.hasUnsatisfiedCredentialRequirements=Pfe;he.updateAuthenticationEditorField=$fe;he.validateOAuthAuthenticationConfigPlacement=cL;he.authenticationToLegacyCredentials=uL;he.isRuntimeCredentialMetadataKey=Ffe;he.resolveCredentialAuthentication=jfe;he.buildRuntimeCredentialsFromAuthentication=zfe;he.resolveOAuthConfigFromAuthentication=Hfe;he.toCredentialInputValue=Kb;he.getCredentialEntries=qfe;he.getCredentialInputValues=Gfe;he.getCredentialDisplayHiddenKeys=Yfe;he.hasOAuthTokenCredentials=Vfe;he.getOAuthExpiryText=Jfe;he.hasRuntimeCredentialValues=Wfe;he.validateCredentialObjectKeys=Zfe;he.validateCredentialKeyList=Kfe;he.mapOAuthMissingFieldsForAgent=Xfe;he.validateOAuthAuthenticationAndCredentialInputs=ehe;var Rt=Rn(),cfe=fu();he.OAUTH_CONFIG_CREDENTIAL_KEYS=["auth_url","authUrl","token_url","tokenUrl","token_uri","scopes","scope","grant_type","grantType","oauthClientMode","client_id","clientId","client_secret","clientSecret","tokenAuthMethod","tokenContentType","usePKCE","extraHeaders","extraBodyParams"];var _g=["host","port","database","path","homeDirectory"],rL=["type","oauthClientMode","grantType","authUrl","tokenUrl","scopes","clientId","clientSecret","tokenAuthMethod","tokenContentType","usePKCE","extraHeaders","extraBodyParams","resource","protocol",..._g],ufe=new Set(rL),lfe="type, oauthClientMode, grantType, authUrl, tokenUrl, scopes, clientId, clientSecret, tokenAuthMethod, tokenContentType, usePKCE, extraHeaders, extraBodyParams, resource, protocol, host, port, database, path, homeDirectory",dfe=["grantType","authUrl","tokenUrl","scopes","clientId","clientSecret"],Afe={grantType:["grantType","grant_type"],authUrl:["authUrl","auth_url"],tokenUrl:["tokenUrl","token_url","token_uri"],scopes:["scopes","scope"],clientId:["clientId","client_id"],clientSecret:["clientSecret","client_secret"]},zd=["tokenAuthMethod","tokenContentType","usePKCE","extraHeaders","extraBodyParams","resource"],pfe=new Set(dfe);he.OAUTH_TOKEN_CREDENTIAL_KEYS=["access_token","accessToken","refresh_token","refreshToken","expires_at","expiresAt","expires_in","expiresIn","expiry","token_type","tokenType"];var ffe=new Set(he.OAUTH_TOKEN_CREDENTIAL_KEYS),hfe=["access_token","refresh_token","api_key","bearer_token","token","client_id","client_secret","auth_url","token_url","scopes","grant_type","token_type","expires_at","expiry","expires_in","host","hostname","port","database","dbname","db","username","password"],XM=new Map(hfe.map((t,e)=>[(0,Rt.normalizeCredentialKey)(t),e]));function $a(t){return Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0))}function Jb({config:t,key:e,value:r}){let n={...t||{}};return Ct(r)?n[e]=r:delete n[e],Object.keys(n).length>0?n:void 0}function Ct(t){return(0,Rt.hasCredentialValue)(t)}function Gt(t){if(Ct(t))return typeof t=="string"?t:String(t)}var gfe={"grant_type authorization_code or client_credentials":"authorization_code or client_credentials",client_id:"client ID",token_url:"token URL",auth_url:"authorization URL","client_secret or usePKCE":"client secret or PKCE","client_secret or oauth_cert + oauth_key":"client secret or OAuth certificate and key"};function Go(...t){return t.find(e=>Ct(e))}function mfe(t){return t===!0||t==="true"}function yfe(t){let e=t||{},r=Gt(Go(e.grant_type,e.grantType)),n=r==="client_credentials"?"client_credentials":"authorization_code",i=r&&r!=="authorization_code"&&r!=="client_credentials",o=Go(e.client_id,e.clientId),s=Go(e.client_secret,e.clientSecret),a=Go(e.auth_url,e.authUrl),c=Go(e.token_url,e.tokenUrl,e.token_uri),u=Go(e.oauth_cert,e.oauthCert),l=Go(e.oauth_key,e.oauthKey),d=Ct(u)&&Ct(l)||e.hasServerSideCertificateCredentials===!0,A=e.hasServerSideClientSecret===!0,p=Ct(s)||A,h=mfe(Go(e.usePKCE,e.usePkce)),g=[];return i&&g.push("grant_type authorization_code or client_credentials"),Ct(o)||g.push("client_id"),Ct(c)||g.push("token_url"),n==="client_credentials"?!p&&!d&&g.push("client_secret or oauth_cert + oauth_key"):(Ct(a)||g.push("auth_url"),!p&&!h&&g.push("client_secret or usePKCE")),{grantType:n,hasAccessToken:Ct(Go(e.access_token,e.accessToken)),hasCertificateCredentials:d,isReadyToConnect:g.length===0,missingFields:g,usePKCE:h}}function Efe(t){return t.length<=1?t[0]||"":t.length===2?`${t[0]} and ${t[1]}`:`${t.slice(0,-1).join(", ")}, and ${t[t.length-1]}`}function Ife(t){if(!t||t.isReadyToConnect)return null;let e=t.missingFields.map(r=>gfe[r]||r);return`OAuth connection is disabled because ${Efe(e)} ${e.length===1?"is":"are"} missing.`}function Yo(t){if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function fo(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function Hd(t){if(Array.isArray(t))return t.map(String).filter(Boolean);if(Ct(t)){if(typeof t=="string"){let e=t.trim().split(/[,\s]+/).map(r=>r.trim()).filter(Boolean);return e.length>0?e:void 0}return[String(t)]}}function qd(t){let e=Gt(t);if(e==="authorization_code"||e==="client_credentials"||e==="password"||e==="service_account"||e==="custom")return e;if(e)return"custom"}function Zb(t){return t==="managed"||t==="dynamic"||t==="custom"?t:void 0}function Cfe(t){let e=Object.entries(t).filter(([r])=>!pfe.has(r));return e.length>0?Object.fromEntries(e):void 0}function Eu(t,e,r){for(let i of Afe[r])if(r==="scopes"&&Array.isArray(t[i])||Ct(t[i]))return t[i];let n=Yo(t.client);return r==="clientId"&&Ct(n?.id)?n.id:r==="clientSecret"&&Ct(n?.secret)?n.secret:e[r]}function fr(t){if(!t)return;let e=t;if(e.type==="oauth2"){let r=Yo(e.config)||{},n=Cfe(r)||{};return $a({type:"oauth2",oauthClientMode:Zb(e.oauthClientMode),grantType:qd(Eu(e,r,"grantType")),authUrl:Gt(Eu(e,r,"authUrl")),tokenUrl:Gt(Eu(e,r,"tokenUrl")),scopes:Hd(Eu(e,r,"scopes")),oauthAppId:Gt(e.oauthAppId),clientId:Gt(Eu(e,r,"clientId")),clientSecret:Gt(Eu(e,r,"clientSecret")),config:Object.keys(n).length>0?n:void 0})}return e.type==="connection_string"?$a({type:"connection_string",protocol:e.protocol,config:Yo(e.config??e.components)}):e.type==="api_key"||e.type==="basic_auth"||e.type==="none"?$a({type:e.type,config:Yo(e.config)}):{type:"none"}}function bfe({authentication:t,templateManaged:e,templateRegistrationUrl:r}){let n=fr(t);return n?.type!=="oauth2"?"custom":n.oauthAppId?.startsWith("managed:")?"managed":n.oauthClientMode?n.oauthClientMode==="managed"&&!e?"custom":n.oauthClientMode:r?"dynamic":e&&!n.clientSecret?"managed":"custom"}function nL(t){let e=fr(t);if(!e)return;let{config:r,scopes:n,oauthAppId:i,...o}=e,s={};return r&&typeof r=="object"&&Object.assign(s,r),Object.assign(s,o),Array.isArray(n)?s.scopes=n.join(" "):n!==void 0&&(s.scopes=n),s}function Wb(t,e=""){return t==null?t:Array.isArray(t)?t.map(r=>Wb(r)):typeof t=="object"?Object.fromEntries(Object.entries(t).map(([r,n])=>[r,Wb(n,r)])):e&&(0,Rt.isSensitiveCredentialKey)(e)?(0,Rt.maskCredentialValue)(e,t):t}function Sfe(t){let e=nL(t);if(e)return Wb(e)}function iL(t){return(0,Rt.isMaskedValue)(t)||(0,Rt.isFullyMaskedCredentialValue)(t)}function wfe(t){let e=Yo(t);if(!e)return;let r={};for(let n of rL){if(!fo(e,n))continue;let i=e[n];i!==void 0&&(r[n]=i)}return r}function Bfe(t){return!t||t.type!=="oauth2"||!Ct(t.clientSecret)?t:{...t,clientSecret:Rt.FULLY_MASKED_CREDENTIAL_VALUE}}function _fe({incoming:t,existing:e}){if(!t||t.type!=="oauth2"||!iL(t.clientSecret))return t;let r=e?.type==="oauth2"?e.clientSecret:void 0;return{...t,clientSecret:r}}function vfe(t){if(t==="none"||t==="api_key"||t==="basic_auth"||t==="oauth2"||t==="connection_string")return t}function Qfe(t){let e=_g.flatMap(r=>{if(!fo(t,r))return[];let n=t[r];return Ct(n)?[[r,n]]:[]});return e.length>0?Object.fromEntries(e):void 0}function Tfe(t){return _g.filter(e=>fo(t,e))}function Dfe(t){let e=_g.flatMap(r=>fo(t,r)?[[r,t[r]]]:[]);return e.length>0?Object.fromEntries(e):void 0}function Rfe(t){let e=new Set(["oauthClientMode","grantType","authUrl","tokenUrl","scopes","clientId","clientSecret",...zd]);return Object.keys(t).filter(r=>e.has(r))}function oL(t){if(t==null)return{};let e=Yo(t);if(!e)return{error:"auth must be an object."};let r=vfe(e.type);if(!r)return{error:"auth.type is required."};let n=Object.keys(e).filter(a=>!ufe.has(a));if(n.length>0)return{error:`Unknown auth field(s): ${n.join(", ")}. Accepted: ${lfe}.`};let i=Tfe(e);if(r!=="connection_string"&&i.length>0)return{error:`Connection auth field(s) require auth.type 'connection_string': ${i.join(", ")}.`};let o=Rfe(e);if(r!=="oauth2"&&o.length>0)return{error:`OAuth auth field(s) require auth.type 'oauth2': ${o.join(", ")}.`};if(r!=="oauth2"){let a=Qfe(e);return{authentication:$a({type:r,protocol:r==="connection_string"?e.protocol:void 0,config:a})}}let s={...Object.fromEntries(zd.flatMap(a=>{if(!fo(e,a))return[];let c=e[a];return Ct(c)?[[a,c]]:[]}))};return{authentication:$a({type:"oauth2",oauthClientMode:Zb(e.oauthClientMode),grantType:qd(e.grantType),authUrl:Gt(e.authUrl),tokenUrl:Gt(e.tokenUrl),scopes:Hd(e.scopes),clientId:Gt(e.clientId),clientSecret:Gt(e.clientSecret),config:Object.keys(s).length>0?s:void 0})}}function Fa(t){return t===""||t===null||t===void 0}function jd(t,e,r,n){if(fo(e,r)){if(Fa(e[r])){delete t[n];return}t[n]=Gt(e[r])}}function Nfe(t,e){if(fo(e,"scopes")){if(Fa(e.scopes)){delete t.scopes;return}t.scopes=Hd(e.scopes)}}function kfe(t,e){if(fo(e,"grantType")){if(Fa(e.grantType)){delete t.grantType;return}t.grantType=qd(e.grantType)}}function Ofe(t,e,r){if(fo(e,r)){if(Fa(e[r])){delete t[r];return}t[r]=e[r]}}function Ufe(t,e){if(Fa(e))return;let r=Yo(e);if(!r)return t;let n={...t||{}};for(let[i,o]of Object.entries(r))Fa(o)?delete n[i]:n[i]=o;return Object.keys(n).length>0?n:void 0}function xfe(t,e){let r=oL(e);if(r.error)return fr(t)||{type:"none"};let n=r.authentication||{type:"none"},i=Yo(e)||{},o=fr(t),s=o?.type===n.type;if(n.type!=="oauth2"){let d=Dfe(i),A=s&&o?{...o}:{type:n.type};return n.type==="connection_string"&&fo(i,"protocol")&&(Fa(i.protocol)?delete A.protocol:A.protocol=i.protocol),d&&(A.config=Ufe(o?.config,d)),fr(A)||{type:n.type}}let c={...s&&o?.type==="oauth2"?{...o,config:{...o.config||{}}}:{type:"oauth2",config:{}}};jd(c,i,"oauthClientMode","oauthClientMode"),kfe(c,i),jd(c,i,"authUrl","authUrl"),jd(c,i,"tokenUrl","tokenUrl"),Nfe(c,i),jd(c,i,"clientId","clientId"),jd(c,i,"clientSecret","clientSecret");let l={...c.config||{}};for(let d of zd)Ofe(l,i,d);return c.config=Object.keys(l).length>0?l:void 0,fr(c)||{type:"oauth2"}}function sL(t){let e=fr(t);if(!e)return[];let r=new Set;for(let n of Object.keys(e.config||{}))r.add(n);return e.type==="oauth2"&&(e.grantType&&(r.add("grant_type"),r.add("grantType")),e.authUrl&&(r.add("auth_url"),r.add("authUrl")),e.tokenUrl&&(r.add("token_url"),r.add("tokenUrl"),r.add("token_uri")),e.scopes&&(r.add("scopes"),r.add("scope")),e.clientId&&(r.add("client_id"),r.add("clientId")),e.clientSecret&&(r.add("client_secret"),r.add("clientSecret"))),[...r]}function eL(t,e,r){if(r)for(let[n,i]of Object.entries(r))t.push({path:`${e}.${n}`,label:n,value:i})}function Mfe({authentication:t}){let e=fr(t)||{type:"none"},r=[];if(e.type==="oauth2"){r.push({path:"oauth2.clientId",label:"clientId",value:e.clientId},{path:"oauth2.clientSecret",label:"clientSecret",value:e.clientSecret},{path:"oauth2.grantType",label:"grantType",value:e.grantType||"authorization_code"},{path:"oauth2.authUrl",label:"authUrl",value:e.authUrl},{path:"oauth2.tokenUrl",label:"tokenUrl",value:e.tokenUrl},{path:"oauth2.scopes",label:"scopes",value:e.scopes?.join(" ")});for(let n of zd)r.push({path:`oauth2.config.${n}`,label:n,value:e.config?.[n]});for(let[n,i]of Object.entries(e.config||{}))zd.includes(n)||r.push({path:`oauth2.config.${n}`,label:n,value:i})}else e.type==="connection_string"?(e.protocol&&r.push({path:"connection.protocol",label:"protocol",value:e.protocol}),eL(r,"connection.config",e.config)):eL(r,`${e.type}.config`,e.config);return{type:e.type,authentication:e,configFields:r,hiddenCredentialKeys:sL(e)}}function Lfe(t){let e=fr(t);if(!e||e.type!=="connection_string")return[];let r={type:"field",field:{key:"username",aliases:["user"]}},n={type:"field",field:{key:"password"}};switch(e.protocol){case"sftp":return[r,{type:"oneOf",fields:[{key:"password"},{key:"privateKey"}]},{type:"field",field:{key:"passphrase"},optional:!0}];case"smb":return[r,n,{type:"field",field:{key:"domain"},optional:!0}];case"sqlserver":return[{type:"field",field:{key:"user",aliases:["username"]}},n];default:return[r,n]}}function tL(t,e){return(0,Rt.hasCredentialValue)(e[t.key])?!0:(t.aliases??[]).some(r=>(0,Rt.hasCredentialValue)(e[r]))}function aL(t,e){return t.optional?!0:t.type==="field"?tL(t.field,e):t.fields.some(r=>tL(r,e))}function Pfe(t,e){let r=e||{};return t.some(n=>!aL(n,r))}function $fe({authentication:t,path:e,value:r}){let n=fr(t)||{type:"none"};if(n.type==="oauth2"){if(e==="oauth2.grantType")return{...n,grantType:qd(r)};if(e==="oauth2.authUrl")return{...n,authUrl:Gt(r)};if(e==="oauth2.tokenUrl")return{...n,tokenUrl:Gt(r)};if(e==="oauth2.scopes")return{...n,scopes:Hd(r)??[]};if(e==="oauth2.clientId")return{...n,clientId:Gt(r)};if(e==="oauth2.clientSecret")return{...n,clientSecret:Gt(r)};if(e.startsWith("oauth2.config.")){let o=e.slice(14);return{...n,config:Jb({config:n.config,key:o,value:r})}}}if(n.type==="connection_string"){if(e==="connection.protocol")return{...n,protocol:Gt(r)};if(e.startsWith("connection.config.")){let o=e.slice(18);return{...n,config:Jb({config:n.config,key:o,value:r})}}}let i=`${n.type}.config.`;if(e.startsWith(i)){let o=e.slice(i.length);return{...n,config:Jb({config:n.config,key:o,value:r})}}return n}function cL({authentication:t,credentials:e}){if(fr(t)?.type!=="oauth2"||!e||typeof e!="object"||Array.isArray(e))return null;let n=Object.keys(e).filter(i=>he.OAUTH_CONFIG_CREDENTIAL_KEYS.includes(i));return n.length===0?null:`OAuth configuration keys belong in auth, not credentials: ${n.join(", ")}. Move OAuth client ID to auth.clientId, client secret to auth.clientSecret, auth URL to auth.authUrl, token URL to auth.tokenUrl, scopes to auth.scopes, grant type to auth.grantType, and token request settings to auth fields such as tokenAuthMethod/usePKCE/extraHeaders. Runtime OAuth access and refresh tokens are created by connect OAuth authorization.`}function uL(t){let e=fr(t);return e?e.type==="oauth2"?$a({...e.config||{},grant_type:e.grantType,auth_url:e.authUrl,token_url:e.tokenUrl,scopes:e.scopes?.join(" "),client_id:e.clientId,client_secret:e.clientSecret}):e.type==="connection_string"?e.config||{}:e.config||{}:{}}function Ffe(t){return ffe.has(t.trim())}function jfe({credential:t,system:e}){return t?.authentication??e?.authentication??void 0}function zfe({authentication:t,credentials:e}){let r=uL(t);return fr(t)?.type==="oauth2"?{...e||{},...r}:{...r,...e||{}}}function Hfe({input:t,authentication:e,templateOAuth:r}){let n=fr(e),i=n?.type==="oauth2"?n:void 0,o=i?.config||{},s=t||{},a=(...c)=>c.find(u=>u!=null);return $a({grant_type:a(s.grantType,s.grant_type,i?.grantType,r?.grant_type)||"authorization_code",scopes:a(s.scopes,i?.scopes?.join(" "),r?.scopes),client_id:a(s.clientId,s.client_id,i?.clientId),client_secret:a(s.clientSecret,s.client_secret,i?.clientSecret),auth_url:a(s.authUrl,s.auth_url,i?.authUrl,r?.authUrl),token_url:a(s.tokenUrl,s.token_url,i?.tokenUrl,r?.tokenUrl),resource:a(s.resource,o.resource,r?.resource),tokenAuthMethod:a(s.tokenAuthMethod,o.tokenAuthMethod,r?.tokenAuthMethod),tokenContentType:a(s.tokenContentType,o.tokenContentType,r?.tokenContentType),usePKCE:a(s.usePKCE,o.usePKCE,r?.usePKCE),extraHeaders:a(s.extraHeaders,o.extraHeaders,r?.extraHeaders),extraBodyParams:a(s.extraBodyParams,o.extraBodyParams,r?.extraBodyParams)})}function Kb(t){if(t==null)return"";if(typeof t=="string")return t;let e=JSON.stringify(t);return e===void 0?String(t):e}function qfe(t,e={}){let r=new Set((e.hiddenKeys||[]).map(Rt.normalizeCredentialKey));return Object.entries(t).filter(([n])=>!r.has((0,Rt.normalizeCredentialKey)(n))).sort(([n],[i])=>{let o=XM.get((0,Rt.normalizeCredentialKey)(n))??Number.MAX_SAFE_INTEGER,s=XM.get((0,Rt.normalizeCredentialKey)(i))??Number.MAX_SAFE_INTEGER;if(o!==s)return o-s;let a=(0,Rt.isSensitiveCredentialKey)(n),c=(0,Rt.isSensitiveCredentialKey)(i);return a!==c?a?-1:1:n.localeCompare(i)}).map(([n,i])=>({key:n,value:Kb(i),isReservedMasked:e.maskAll||(0,Rt.isSensitiveCredentialKey)(n)}))}function Gfe(t){return Object.fromEntries(Object.entries(t).map(([e,r])=>[e,Kb(r)]))}function Yfe({hideOAuthFiles:t=!1,configKeys:e=[]}){return[...e,...t?["oauth_cert","oauth_key"]:[]]}function Vfe(t){return Ct(t.access_token)||Ct(t.refresh_token)}function Jfe(t){let e=t.expires_at??t.expiry;if(e){let n=(0,cfe.parseUTCDate)(e);if(n)return`Expires ${n.toLocaleString()}`}let r=t.expires_in;return Ct(r)?`Expires in ${r} seconds`:null}function Wfe(t){return!!(t&&typeof t=="object"&&!Array.isArray(t)&&Object.values(t).some(e=>Ct(e)))}function Zfe(t){if(!t||typeof t!="object"||Array.isArray(t))return null;let e=(0,Rt.getInvalidCredentialKeyNames)(Object.keys(t));return e.length===0?null:`${Rt.CREDENTIAL_KEY_VALIDATION_DESCRIPTION} Invalid keys: ${e.join(", ")}`}function Kfe(t){let e=(0,Rt.getInvalidCredentialKeyNames)(t);return e.length===0?null:`${Rt.CREDENTIAL_KEY_VALIDATION_DESCRIPTION} Invalid keys: ${e.join(", ")}`}function Xfe(t){let e={"grant_type authorization_code or client_credentials":"grantType authorization_code or client_credentials",client_id:"clientId",token_url:"tokenUrl",auth_url:"authUrl","client_secret or usePKCE":"clientSecret or usePKCE","client_secret or oauth_cert + oauth_key":"clientSecret or oauth_cert + oauth_key"};return t.map(r=>e[r]||r)}function ehe({authentication:t,credentials:e}){return cL({authentication:t,credentials:e})}});var TL=m(ho=>{"use strict";Object.defineProperty(ho,"__esModule",{value:!0});ho.bundles=void 0;ho.buildBundleAgentLaunch=Ahe;ho.getBundle=phe;ho.listBundles=fhe;var the="https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap",rhe="<<(p) => { const value = p['sage_intacct_entity_id']; if (!value) return ''; const escaped = String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('\"', '&quot;').replaceAll(\"'\", '&apos;'); return `<locationid>${escaped}</locationid>`; }>>",lL="<<() => crypto.randomUUID()>>";function bt(t){return`<?xml version="1.0" encoding="UTF-8"?><request><control><senderid><<sage_intacct_sender_id>></senderid><password><<sage_intacct_sender_password>></password><controlid>${lL}</controlid><uniqueid>false</uniqueid><dtdversion>3.0</dtdversion></control><operation><authentication><login><userid><<sage_intacct_user_id>></userid><companyid><<sage_intacct_company_id>></companyid><password><<sage_intacct_user_password>></password>${rhe}</login></authentication><content><function controlid="${lL}">${t}</function></content></operation></request>`}function Ts({stepId:t,objectNameExpression:e,collectionName:r,mapExpression:n,includeTotalCount:i=!1}){let o=i?"Number(data && data.TOTALCOUNT ? data.TOTALCOUNT : rows.length)":"rows.length",s=n?`rows.map(${n})`:"rows";return`(sourceData) => { const response = sourceData.${t} && sourceData.${t}.data ? sourceData.${t}.data.RESPONSE : undefined; const control = response ? response.CONTROL : undefined; const operation = response ? response.OPERATION : undefined; const authentication = operation ? operation.AUTHENTICATION : undefined; const result = operation ? operation.RESULT : undefined; const statuses = [control && control.STATUS, authentication && authentication.STATUS, result && result.STATUS].filter(Boolean).map((value) => String(value).toLowerCase()); if (statuses.includes('failure')) { const message = (result && result.ERRORMESSAGE) || (authentication && authentication.ERR ? authentication.ERR.ERRORMESSAGE : undefined) || (control && control.ERR ? control.ERR.ERRORMESSAGE : undefined); const rawErrors = message ? message.ERROR : undefined; const errors = Array.isArray(rawErrors) ? rawErrors : (rawErrors ? [rawErrors] : []); const details = errors.map((error) => [error.ERRORNO, error.DESCRIPTION2 || error.DESCRIPTION, error.CORRECTION].filter(Boolean).join(' - ')).filter(Boolean); const supportIds = errors.map((error) => error.SUPPORTID).filter(Boolean); const suffix = supportIds.length ? \` Sage support ID: \${supportIds.join(', ')}.\` : ''; throw new Error(\`Sage Intacct request failed\${details.length ? \`: \${details.join('; ')}\` : '.'}\${suffix}\`); } const data = result ? result.DATA : undefined; const objectName = ${e}; const raw = data ? data[objectName] : undefined; const rows = (Array.isArray(raw) ? raw : (raw ? [raw] : [])).slice(0, (sourceData && sourceData.maxResults) ?? ${i?"1000":"200"}); return { total: ${o}, ${r}: ${s} }; }`}var Ds=`const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&apos;');`,dL="const toIntacctDate = (value) => { const match = String(value).match(/^(\\d{4})-(\\d{2})-(\\d{2})/); if (!match) throw new Error('Dates must be in YYYY-MM-DD format.'); return match[2] + '/' + match[3] + '/' + match[1]; };",AL="const assertBalanced = (lines) => { const balance = lines.reduce((sum, line) => sum + (line.type === 'credit' ? -1 : 1) * Math.abs(Number(line.amount)), 0); if (Math.abs(balance) > 0.005) throw new Error('Journal lines must balance: debits minus credits is ' + balance.toFixed(2) + '.'); };",pL=`const lineXml = (line) => { const amount = Number(line.amount); if (!Number.isFinite(amount) || amount <= 0) throw new Error('Every journal line needs a positive amount.'); const type = line.type === 'credit' ? -1 : line.type === 'debit' ? 1 : null; if (type === null) throw new Error("Every journal line needs type 'debit' or 'credit'."); if (!line.accountNo) throw new Error('Every journal line needs accountNo.'); let xml = '<GLENTRY><ACCOUNTNO>' + esc(line.accountNo) + '</ACCOUNTNO><TR_TYPE>' + type + '</TR_TYPE><TRX_AMOUNT>' + amount + '</TRX_AMOUNT>'; if (line.department) xml += '<DEPARTMENT>' + esc(line.department) + '</DEPARTMENT>'; if (line.location) xml += '<LOCATION>' + esc(line.location) + '</LOCATION>'; if (line.memo) xml += '<DESCRIPTION>' + esc(line.memo) + '</DESCRIPTION>'; return xml + '</GLENTRY>'; };`;function Iu({stepId:t,objectName:e}){return`(sourceData) => { const response = sourceData.${t} && sourceData.${t}.data ? sourceData.${t}.data.RESPONSE : undefined; const control = response ? response.CONTROL : undefined; const operation = response ? response.OPERATION : undefined; const authentication = operation ? operation.AUTHENTICATION : undefined; const result = operation ? operation.RESULT : undefined; const statuses = [control && control.STATUS, authentication && authentication.STATUS, result && result.STATUS].filter(Boolean).map((value) => String(value).toLowerCase()); if (statuses.includes('failure')) { const message = (result && result.ERRORMESSAGE) || (authentication && authentication.ERR ? authentication.ERR.ERRORMESSAGE : undefined) || (control && control.ERR ? control.ERR.ERRORMESSAGE : undefined); const rawErrors = message ? message.ERROR : undefined; const errors = Array.isArray(rawErrors) ? rawErrors : (rawErrors ? [rawErrors] : []); const details = errors.map((error) => [error.ERRORNO, error.DESCRIPTION2 || error.DESCRIPTION, error.CORRECTION].filter(Boolean).join(' - ')).filter(Boolean); const supportIds = errors.map((error) => error.SUPPORTID).filter(Boolean); const suffix = supportIds.length ? \` Sage support ID: \${supportIds.join(', ')}.\` : ''; throw new Error(\`Sage Intacct request failed\${details.length ? \`: \${details.join('; ')}\` : '.'}\${suffix}\`); } const data = result ? result.DATA : undefined; const raw = data ? (data.${e} || data.${e.toLowerCase()}) : undefined; const record = Array.isArray(raw) ? raw[0] : raw; return { recordNo: record && record.RECORDNO ? Number(record.RECORDNO) : undefined, record }; }`}var Jd="netsuite",tS=100,Vd=1e4,Og=String.raw`<<(p) => { const url = String(p['netsuite_url'] || ''); if (!url || url.includes('{accountId}')) throw new Error('NetSuite is not connected yet: set the account ID so the system URL is https://<account>.suitetalk.api.netsuite.com/services/rest'); return url.replace(/\/+$/, ''); }>>`,Ug={Authorization:"Bearer <<netsuite_access_token>>",Accept:"application/json"},rS=String.raw`const has = (value) => value !== undefined && value !== null && value !== ''; const nsId = (value, name) => { const text = String(value ?? '').trim(); if (!/^-?\d+$/.test(text)) throw new Error(name + ' must be a NetSuite internal ID.'); return text; }; const nsDate = (value, name) => { const text = String(value ?? '').trim(); if (!/^\d{4}-\d{2}-\d{2}$/.test(text)) throw new Error(name + ' must be a date in YYYY-MM-DD format.'); return text; }; const ref = (value, name) => ({ id: nsId(value, name) });`,nhe=String.raw`const str = (value) => (value === undefined || value === null || value === '' ? null : String(value)); const num = (value) => (value === undefined || value === null || value === '' ? null : Number(value)); const bool = (value) => value === 'T' || value === true; const ids = (value) => (value === undefined || value === null || value === '' ? [] : String(value).split(',').map((part) => part.trim()).filter(Boolean)); const status = (value) => (value ? String(value).replace(/^[^:]*:\s*/, '') : null);`,fL=String.raw`const stripLinks = (value) => { if (Array.isArray(value)) return value.map(stripLinks); if (value && typeof value === 'object') { const result = {}; for (const [key, entry] of Object.entries(value)) { if (key !== 'links') result[key] = stripLinks(entry); } return result; } return value; };`,ihe={type:"integer",minimum:1,maximum:Vd,description:`Maximum number of records to return (max ${Vd}). Defaults to ${tS}. The result always reports the full match count in total, so use maxResults 1 to count. Prefer filters over large values: big results can exceed an AI client's tool output limit.`},ohe={type:"boolean",description:"Only return active records. Defaults to false (inactive records are included)."},she={type:"string",description:"Optional subsidiary internal ID to filter by."},ahe={type:"string",description:"Optional earliest transaction date as YYYY-MM-DD."},che={type:"string",description:"Optional latest transaction date as YYYY-MM-DD."},uhe={type:"object",description:"Optional extra NetSuite REST field values merged into the record body as-is, e.g. custom fields like { custentity_region: 'EMEA' } or references like { terms: { id: '2' } }. Fields that this tool's own inputs set are rejected; use those inputs instead.",properties:{},additionalProperties:!0},Gd=t=>({input:"activeOnly",kind:"flag",clause:`${t}.isinactive = 'F'`,schema:ohe}),Yd=t=>({input:"subsidiaryId",kind:"id",clause:`${t}.subsidiary = $`,schema:she}),Xb=[{input:"fromDate",kind:"date",clause:"t.trandate >= TO_DATE('$', 'YYYY-MM-DD')",schema:ahe},{input:"toDate",kind:"date",clause:"t.trandate <= TO_DATE('$', 'YYYY-MM-DD')",schema:che}];function lhe(t){let e=`p[${JSON.stringify(t.input)}]`;if(t.kind==="flag")return`if (${e} === true || ${e} === 'true') where.push(${JSON.stringify(t.clause)});`;let[r,n]=t.clause.split("$");if(t.kind==="enum")return`if (has(${e})) { const allowed = ${JSON.stringify(t.values)}; if (!allowed.includes(String(${e}))) throw new Error(${JSON.stringify(`${t.input} must be one of: ${t.values.join(", ")}.`)}); where.push(${JSON.stringify(r)} + String(${e}) + ${JSON.stringify(n)}); }`;if(t.kind==="prefix")return`if (has(${e})) { const text = String(${e}).trim(); if (!/^[A-Za-z0-9._-]{1,40}$/.test(text)) throw new Error(${JSON.stringify(`${t.input} may only contain letters, digits, dots, underscores and hyphens.`)}); where.push(${JSON.stringify(r)} + text + ${JSON.stringify(n)}); }`;let i=t.kind==="id"?"nsId":"nsDate";return`if (has(${e})) where.push(${JSON.stringify(r)} + ${i}(${e}, ${JSON.stringify(t.input)}) + ${JSON.stringify(n)});`}function Rs({id:t,name:e,shortName:r,instruction:n,stepId:i,collection:o,select:s,baseWhere:a=[],orderBy:c,filters:u=[],properties:l={},required:d=[],mapRow:A}){let p=typeof s=="string"?JSON.stringify(s):s.js,h=`<<(p) => { ${rS} const where = ${JSON.stringify(a)}; ${u.map(lhe).join(" ")} return JSON.stringify({ q: ${p} + (where.length ? ' WHERE ' + where.join(' AND ') : '') + ${JSON.stringify(` ORDER BY ${c}`)} }); }>>`;return{id:t,name:e,shortName:r,instruction:`${n} Rows are ordered by internal ID. If more than ${Vd} rows match, narrow with the filters or page with the SuiteQL query tool (ORDER BY id, WHERE id > last id).`,inputSchema:{type:"object",properties:{...l,maxResults:ihe,...Object.fromEntries(u.map(g=>[g.input,g.schema]))},...d.length>0?{required:d}:{},additionalProperties:!1},steps:[{id:i,instruction:"Run the SuiteQL query page by page.",config:{type:"request",systemId:Jd,url:`${Og}/query/v1/suiteql`,method:"POST",headers:{...Ug,"Content-Type":"application/json",Prefer:"transient"},queryParams:{limit:"1000",offset:"<<offset>>"},body:h,pagination:{type:"offsetBased",pageSize:"1000",stopCondition:`(response, pageInfo, sourceData) => { if (sourceData && ["offset", "limit", "page"].some((key) => sourceData[key] !== undefined)) throw new Error("offset, limit and page are not inputs of this tool: use maxResults and the filters."); const page = response && response.data ? response.data : {}; const merged = pageInfo && pageInfo.mergedResult && Array.isArray(pageInfo.mergedResult.items) ? pageInfo.mergedResult.items.length : 0; const max = Math.min(Math.max(Math.floor(Number(sourceData && sourceData.maxResults)) || ${tS}, 1), ${Vd}); return page.hasMore !== true || merged >= max; }`}}}],outputTransform:`(sourceData) => { ${nhe} const raw = sourceData.${i} ? sourceData.${i}.data : undefined; const pages = Array.isArray(raw) ? raw : (raw ? [raw] : []); const items = pages.flatMap((page) => (page && Array.isArray(page.items) ? page.items : [])); const last = pages.length ? pages[pages.length - 1] : {}; const max = Math.min(Math.max(Math.floor(Number(sourceData.maxResults)) || ${tS}, 1), ${Vd}); const rows = items.slice(0, max).map(${A}).map((row) => Object.fromEntries(Object.entries(row).filter((entry) => entry[1] !== null))); const total = last && last.totalResults !== undefined ? Number(last.totalResults) : items.length; return { total, returned: rows.length, hasMore: total > rows.length, ${o}: rows }; }`}}function vr({id:t,name:e,shortName:r,instruction:n,stepId:i,recordType:o,mode:s,properties:a,required:c,body:u,replaceSublist:l}){let d=[...new Set(Array.from(u.matchAll(/record\.([A-Za-z0-9_]+)\s*=/g)).map(p=>p[1]))],A=s==="create"?`/record/v1/${o}`:`/record/v1/${o}/<<(p) => { ${rS} return nsId(p.internalId, 'internalId'); }>>`;return{id:t,name:e,shortName:r,instruction:n,inputSchema:{type:"object",properties:{...s==="update"?{internalId:{type:"string",description:`Internal ID of the ${o} to update.`}}:{},...a,fields:uhe},required:s==="update"?["internalId",...c]:c,additionalProperties:!1},steps:[{id:i,instruction:`${s==="create"?"Create":"Update"} the ${o} record.`,modify:!0,config:{type:"request",systemId:Jd,url:`${Og}${A}`,method:s==="create"?"POST":"PATCH",headers:{...Ug,"Content-Type":"application/json","X-NetSuite-idempotency-key":"<<() => crypto.randomUUID()>>"},...l?{queryParams:{replace:`<<(p) => (Array.isArray(p[${JSON.stringify(l.input)}]) && p[${JSON.stringify(l.input)}].length > 0 ? ${JSON.stringify(l.sublist)} : undefined)>>`}}:{},body:`<<(p) => { ${rS} const record = {}; ${u} if (p.fields && typeof p.fields === 'object' && !Array.isArray(p.fields)) { const managed = ${JSON.stringify(d)}; const reserved = Object.keys(p.fields).filter((key) => managed.includes(key)); if (reserved.length > 0) throw new Error('fields may not set ' + reserved.join(', ') + ': use this tool\\'s own inputs for them.'); Object.assign(record, p.fields); } if (Object.keys(record).length === 0) throw new Error('Provide at least one field to ${s}.'); return JSON.stringify(record); }>>`,captureHttpResponse:!0}}],outputTransform:s==="create"?`(sourceData) => { const step = sourceData.${i} || {}; const location = step.http && step.http.headers ? String(step.http.headers.location || '') : ''; const match = location.match(/\\/record\\/v1\\/[^/]+\\/([^/?#]+)/); if (!match) throw new Error('NetSuite did not return the location of the new ${o}.'); return { id: decodeURIComponent(match[1]), recordType: '${o}' }; }`:`(sourceData) => ({ id: String(sourceData.internalId).trim(), recordType: '${o}', updated: true })`}}var hL=String.raw`const lines = Array.isArray(p.lines) ? p.lines : []; let balance = 0; const items = lines.map((line, index) => { const amount = Number(line && line.amount); if (!Number.isFinite(amount) || amount <= 0) throw new Error('lines[' + index + '].amount must be a positive number.'); if (line.type !== 'debit' && line.type !== 'credit') throw new Error("lines[" + index + "].type must be 'debit' or 'credit'."); balance += line.type === 'debit' ? amount : -amount; const item = { account: ref(line.accountId, 'lines[' + index + '].accountId') }; item[line.type] = amount; if (has(line.memo)) item.memo = String(line.memo); if (has(line.departmentId)) item.department = ref(line.departmentId, 'lines[' + index + '].departmentId'); if (has(line.classId)) item.class = ref(line.classId, 'lines[' + index + '].classId'); if (has(line.locationId)) item.location = ref(line.locationId, 'lines[' + index + '].locationId'); if (has(line.entityId)) item.entity = ref(line.entityId, 'lines[' + index + '].entityId'); return item; }); if (lines.length > 0 && Math.abs(balance) > 0.005) throw new Error('Journal lines must balance: debits minus credits is ' + balance.toFixed(2) + '.'); if (items.length > 0) record.line = { items };`,gL=String.raw`if (has(p.subsidiaryId)) record.subsidiary = ref(p.subsidiaryId, 'subsidiaryId'); if (has(p.date)) record.tranDate = nsDate(p.date, 'date'); if (has(p.memo)) record.memo = String(p.memo); if (has(p.currencyId)) record.currency = ref(p.currencyId, 'currencyId'); if (has(p.externalId)) record.externalId = String(p.externalId);`,mL={type:"object",properties:{accountId:{type:"string",description:"GL account internal ID."},type:{type:"string",enum:["debit","credit"]},amount:{type:"number",description:"Positive amount."},memo:{type:"string",description:"Optional line memo."},departmentId:{type:"string",description:"Optional department internal ID."},classId:{type:"string",description:"Optional class internal ID."},locationId:{type:"string",description:"Optional location internal ID."},entityId:{type:"string",description:"Optional customer, vendor or employee internal ID for the line."}},required:["accountId","type","amount"],additionalProperties:!1},yL=t=>({subsidiaryId:{type:"string",description:t==="create"?"Subsidiary internal ID. Required in OneWorld accounts.":"Optional new subsidiary internal ID."},date:{type:"string",description:t==="create"?"Transaction date as YYYY-MM-DD.":"Optional new transaction date as YYYY-MM-DD."},memo:{type:"string",description:"Journal entry memo."},currencyId:{type:"string",description:"Optional currency internal ID."},externalId:{type:"string",description:"Optional external ID."}}),Qg=String.raw`if (p.isPerson === true || p.isPerson === 'true') record.isPerson = true; if (p.isPerson === false || p.isPerson === 'false') record.isPerson = false; if (has(p.entityId)) record.entityId = String(p.entityId); if (has(p.companyName)) record.companyName = String(p.companyName); if (has(p.firstName)) record.firstName = String(p.firstName); if (has(p.lastName)) record.lastName = String(p.lastName); if (has(p.subsidiaryId)) record.subsidiary = ref(p.subsidiaryId, 'subsidiaryId'); if (has(p.email)) record.email = String(p.email); if (has(p.phone)) record.phone = String(p.phone); if (has(p.currencyId)) record.currency = ref(p.currencyId, 'currencyId'); if (has(p.externalId)) record.externalId = String(p.externalId); if (p.isInactive === true || p.isInactive === 'true') record.isInactive = true; if (p.isInactive === false || p.isInactive === 'false') record.isInactive = false;`;function Tg(t){return{companyName:{type:"string",description:`Company name of the ${t}.`},isPerson:{type:"boolean",description:`True when the ${t} is an individual; then set firstName and lastName.`},firstName:{type:"string",description:"First name for an individual."},lastName:{type:"string",description:"Last name for an individual."},entityId:{type:"string",description:`${t==="customer"?"Customer":"Vendor"} ID. Omit when auto-numbering assigns it.`},subsidiaryId:{type:"string",description:"Primary subsidiary internal ID. Required on create in OneWorld accounts."},email:{type:"string",description:"Email address."},phone:{type:"string",description:"Phone number."},currencyId:{type:"string",description:"Primary currency internal ID."},externalId:{type:"string",description:"Optional external ID."}}}var Dg={isInactive:{type:"boolean",description:"Set true to inactivate, false to reactivate."}},Rg=String.raw`if (Array.isArray(p.subsidiaryIds) && p.subsidiaryIds.length > 0) record.subsidiary = { items: p.subsidiaryIds.map((value, index) => ref(value, 'subsidiaryIds[' + index + ']')) }; if (p.includeChildren === true || p.includeChildren === 'true') record.includeChildren = true; if (p.includeChildren === false || p.includeChildren === 'false') record.includeChildren = false;`,vL={subsidiaryIds:{type:"array",items:{type:"string"},description:"Subsidiary internal IDs the record is available in. On update the list replaces the current subsidiaries."},includeChildren:{type:"boolean",description:"Also make the record available to child subsidiaries."}},nS=["AcctPay","AcctRec","Bank","COGS","CredCard","DeferExpense","DeferRevenue","Equity","Expense","FixedAsset","Income","LongTermLiab","NonPosting","OthAsset","OthCurrAsset","OthCurrLiab","OthExpense","OthIncome","Stat","UnbilledRec"],EL=String.raw`if (has(p.acctNumber)) record.acctNumber = String(p.acctNumber); if (has(p.acctName)) record.acctName = String(p.acctName); if (has(p.acctType)) record.acctType = { id: String(p.acctType) }; if (has(p.parentId)) record.parent = ref(p.parentId, 'parentId'); if (has(p.description)) record.description = String(p.description); if (has(p.currencyId)) record.currency = ref(p.currencyId, 'currencyId'); if (has(p.externalId)) record.externalId = String(p.externalId); if (p.isInactive === true || p.isInactive === 'true') record.isInactive = true; if (p.isInactive === false || p.isInactive === 'false') record.isInactive = false;`,IL={acctNumber:{type:"string",description:"Account number."},acctName:{type:"string",description:"Account name."},acctType:{type:"string",enum:nS,description:"NetSuite account type."},parentId:{type:"string",description:"Optional parent account internal ID."},description:{type:"string",description:"Optional description."},currencyId:{type:"string",description:"Optional currency internal ID (bank and credit card accounts)."},externalId:{type:"string",description:"Optional external ID."},...vL},CL=String.raw`if (has(p.name)) record.name = String(p.name); if (has(p.parentId)) record.parent = ref(p.parentId, 'parentId'); if (has(p.externalId)) record.externalId = String(p.externalId); if (p.isInactive === true || p.isInactive === 'true') record.isInactive = true; if (p.isInactive === false || p.isInactive === 'false') record.isInactive = false;`,bL={name:{type:"string",description:"Department name."},parentId:{type:"string",description:"Optional parent department internal ID."},externalId:{type:"string",description:"Optional external ID."},...vL},Ng=t=>String.raw`if (has(p.${t})) record.entity = ref(p.${t}, '${t}'); if (has(p.subsidiaryId)) record.subsidiary = ref(p.subsidiaryId, 'subsidiaryId'); if (has(p.date)) record.tranDate = nsDate(p.date, 'date'); if (has(p.dueDate)) record.dueDate = nsDate(p.dueDate, 'dueDate'); if (has(p.memo)) record.memo = String(p.memo); if (has(p.currencyId)) record.currency = ref(p.currencyId, 'currencyId'); if (has(p.termsId)) record.terms = ref(p.termsId, 'termsId'); if (has(p.departmentId)) record.department = ref(p.departmentId, 'departmentId'); if (has(p.classId)) record.class = ref(p.classId, 'classId'); if (has(p.locationId)) record.location = ref(p.locationId, 'locationId'); if (has(p.externalId)) record.externalId = String(p.externalId);`,kg=t=>({subsidiaryId:{type:"string",description:t==="create"?"Optional subsidiary internal ID; defaults to the entity's subsidiary.":"Optional new subsidiary internal ID."},date:{type:"string",description:t==="create"?"Transaction date as YYYY-MM-DD.":"Optional new transaction date as YYYY-MM-DD."},dueDate:{type:"string",description:"Optional due date as YYYY-MM-DD."},memo:{type:"string",description:"Optional memo."},currencyId:{type:"string",description:"Optional currency internal ID."},termsId:{type:"string",description:"Optional payment terms internal ID."},departmentId:{type:"string",description:"Optional header department internal ID."},classId:{type:"string",description:"Optional header class internal ID."},locationId:{type:"string",description:"Optional header location internal ID."},externalId:{type:"string",description:"Optional external ID."}}),QL=String.raw`if (has(line.departmentId)) item.department = ref(line.departmentId, 'lines[' + index + '].departmentId'); if (has(line.classId)) item.class = ref(line.classId, 'lines[' + index + '].classId'); if (has(line.locationId)) item.location = ref(line.locationId, 'lines[' + index + '].locationId');`,SL=String.raw`if (Array.isArray(p.lines) && p.lines.length > 0) record.item = { items: p.lines.map((line, index) => { const item = { item: ref(line && line.itemId, 'lines[' + index + '].itemId') }; if (has(line.quantity)) { const quantity = Number(line.quantity); if (!Number.isFinite(quantity)) throw new Error('lines[' + index + '].quantity must be a number.'); item.quantity = quantity; } if (has(line.rate)) { const rate = Number(line.rate); if (!Number.isFinite(rate)) throw new Error('lines[' + index + '].rate must be a number.'); item.rate = rate; } if (has(line.amount)) { const amount = Number(line.amount); if (!Number.isFinite(amount)) throw new Error('lines[' + index + '].amount must be a number.'); item.amount = amount; } if (has(line.description)) item.description = String(line.description); if (has(line.taxCodeId)) item.taxCode = ref(line.taxCodeId, 'lines[' + index + '].taxCodeId'); ${QL} return item; }) };`,wL={type:"object",properties:{itemId:{type:"string",description:"Item internal ID."},quantity:{type:"number",description:"Optional quantity. Defaults to 1."},rate:{type:"number",description:"Optional unit price; defaults to the item price."},amount:{type:"number",description:"Optional line amount."},description:{type:"string",description:"Optional line description."},taxCodeId:{type:"string",description:"Optional tax code internal ID."},departmentId:{type:"string",description:"Optional department internal ID."},classId:{type:"string",description:"Optional class internal ID. Some accounts ignore line classes on invoices; check the saved record."},locationId:{type:"string",description:"Optional location internal ID."}},required:["itemId"],additionalProperties:!1},BL=String.raw`if (Array.isArray(p.lines) && p.lines.length > 0) record.expense = { items: p.lines.map((line, index) => { const amount = Number(line && line.amount); if (!Number.isFinite(amount) || amount <= 0) throw new Error('lines[' + index + '].amount must be a positive number.'); const item = { account: ref(line.accountId, 'lines[' + index + '].accountId'), amount }; if (has(line.memo)) item.memo = String(line.memo); ${QL} return item; }) };`,_L={type:"object",properties:{accountId:{type:"string",description:"Expense account internal ID."},amount:{type:"number",description:"Positive amount."},memo:{type:"string",description:"Optional line memo."},departmentId:{type:"string",description:"Optional department internal ID."},classId:{type:"string",description:"Optional class internal ID."},locationId:{type:"string",description:"Optional location internal ID."}},required:["accountId","amount"],additionalProperties:!1},ja="Re-running this tool creates another record; it is not idempotent.",dhe=[Rs({id:"netsuite-list-accounts",name:"List NetSuite chart of accounts",shortName:"Chart of accounts",instruction:"Lists general ledger accounts (the chart of accounts) from NetSuite with number, name, type, parent and subsidiaries. Useful for validating an imported chart of accounts.",stepId:"queryAccounts",collection:"accounts",select:"SELECT a.id, a.acctnumber, a.accountsearchdisplaynamecopy AS name, a.fullname, a.accttype, a.parent, a.subsidiary, cur.symbol AS currency, a.description, a.issummary, a.isinactive FROM account a LEFT JOIN currency cur ON cur.id = a.currency",orderBy:"a.id",filters:[Gd("a"),{input:"accountType",kind:"enum",values:nS,clause:"a.accttype = '$'",schema:{type:"string",enum:nS,description:"Only accounts of this NetSuite account type, e.g. Bank or Expense."}},{input:"numberPrefix",kind:"prefix",clause:"a.acctnumber LIKE '$%'",schema:{type:"string",description:"Only accounts whose number starts with this value, e.g. 1000 or 60."}}],mapRow:"(row) => ({ id: row.id, number: str(row.acctnumber), name: str(row.name), fullName: str(row.fullname), type: str(row.accttype), parentId: str(row.parent), subsidiaryIds: ids(row.subsidiary), currency: str(row.currency), description: str(row.description), isSummary: bool(row.issummary), isInactive: bool(row.isinactive) })"}),Rs({id:"netsuite-list-customers",name:"List NetSuite customers",shortName:"Customers",instruction:"Lists customer records from NetSuite with subsidiary, currency and open balance. Useful for verifying migrated AR master data.",stepId:"queryCustomers",collection:"customers",select:"SELECT c.id, c.entityid, c.companyname, c.isperson, c.firstname, c.lastname, c.email, c.phone, c.subsidiary, BUILTIN.DF(c.subsidiary) AS subsidiaryname, cur.symbol AS currency, c.balancesearch, c.overduebalancesearch, c.isinactive, TO_CHAR(c.datecreated, 'YYYY-MM-DD') AS datecreated, TO_CHAR(c.lastmodifieddate, 'YYYY-MM-DD') AS lastmodified FROM customer c LEFT JOIN currency cur ON cur.id = c.currency",orderBy:"c.id",filters:[Gd("c"),Yd("c")],mapRow:"(row) => ({ id: row.id, entityId: str(row.entityid), companyName: str(row.companyname), isPerson: bool(row.isperson), firstName: str(row.firstname), lastName: str(row.lastname), email: str(row.email), phone: str(row.phone), subsidiaryId: str(row.subsidiary), subsidiary: str(row.subsidiaryname), currency: str(row.currency), balance: num(row.balancesearch), overdueBalance: num(row.overduebalancesearch), isInactive: bool(row.isinactive), createdOn: str(row.datecreated), modifiedOn: str(row.lastmodified) })"}),Rs({id:"netsuite-list-vendors",name:"List NetSuite vendors",shortName:"Vendors",instruction:"Lists vendor records from NetSuite with subsidiary, currency and balance. Useful for verifying migrated AP master data.",stepId:"queryVendors",collection:"vendors",select:"SELECT v.id, v.entityid, v.companyname, v.isperson, v.firstname, v.lastname, v.email, v.phone, v.subsidiary, BUILTIN.DF(v.subsidiary) AS subsidiaryname, cur.symbol AS currency, v.balance, v.isinactive, TO_CHAR(v.datecreated, 'YYYY-MM-DD') AS datecreated, TO_CHAR(v.lastmodifieddate, 'YYYY-MM-DD') AS lastmodified FROM vendor v LEFT JOIN currency cur ON cur.id = v.currency",orderBy:"v.id",filters:[Gd("v"),Yd("v")],mapRow:"(row) => ({ id: row.id, entityId: str(row.entityid), companyName: str(row.companyname), isPerson: bool(row.isperson), firstName: str(row.firstname), lastName: str(row.lastname), email: str(row.email), phone: str(row.phone), subsidiaryId: str(row.subsidiary), subsidiary: str(row.subsidiaryname), currency: str(row.currency), balance: num(row.balance), isInactive: bool(row.isinactive), createdOn: str(row.datecreated), modifiedOn: str(row.lastmodified) })"}),Rs({id:"netsuite-list-journal-entries",name:"List NetSuite journal entries",shortName:"Journal entries",instruction:"Lists journal entry lines from NetSuite, one row per GL line and accounting book with journal, date, period, account, debit, credit and dimensions. Useful for verifying opening balances and postings at cutover.",stepId:"queryJournalLines",collection:"journalLines",select:"SELECT t.id AS journalid, t.tranid, TO_CHAR(t.trandate, 'YYYY-MM-DD') AS trandate, BUILTIN.DF(t.postingperiod) AS period, t.subsidiary, BUILTIN.DF(t.status) AS status, t.posting, t.memo AS journalmemo, cur.symbol AS currency, tl.id AS lineid, tal.accountingbook, tal.account, a.acctnumber, a.accountsearchdisplaynamecopy AS accountname, tal.debit, tal.credit, tl.memo, tl.department, tl.class, tl.location, tl.entity FROM transaction t JOIN transactionline tl ON tl.transaction = t.id JOIN transactionaccountingline tal ON tal.transaction = tl.transaction AND tal.transactionline = tl.id JOIN account a ON a.id = tal.account LEFT JOIN currency cur ON cur.id = t.currency",baseWhere:["t.type = 'Journal'"],orderBy:"t.id, tl.id, tal.accountingbook",filters:[...Xb,Yd("t")],mapRow:"(row) => ({ journalId: row.journalid, tranId: str(row.tranid), date: str(row.trandate), period: str(row.period), subsidiaryId: str(row.subsidiary), status: status(row.status), posting: bool(row.posting), journalMemo: str(row.journalmemo), currency: str(row.currency), line: num(row.lineid), accountingBookId: str(row.accountingbook), accountId: str(row.account), accountNumber: str(row.acctnumber), accountName: str(row.accountname), debit: num(row.debit), credit: num(row.credit), memo: str(row.memo), departmentId: str(row.department), classId: str(row.class), locationId: str(row.location), entityId: str(row.entity) })"}),Rs({id:"netsuite-list-invoices",name:"List NetSuite invoices",shortName:"Invoices",instruction:"Lists customer invoices from NetSuite with customer, dates, status, total and amount due. Useful for verifying migrated open AR at go-live.",stepId:"queryInvoices",collection:"invoices",select:"SELECT t.id, t.tranid, t.entity, BUILTIN.DF(t.entity) AS customername, TO_CHAR(t.trandate, 'YYYY-MM-DD') AS trandate, TO_CHAR(t.duedate, 'YYYY-MM-DD') AS duedate, BUILTIN.DF(t.status) AS status, cur.symbol AS currency, t.foreigntotal, t.foreignamountunpaid, t.subsidiary, t.memo FROM transaction t LEFT JOIN currency cur ON cur.id = t.currency",baseWhere:["t.type = 'CustInvc'"],orderBy:"t.id",filters:[...Xb,Yd("t"),{input:"openOnly",kind:"flag",clause:"t.status = 'A'",schema:{type:"boolean",description:"Only return open (unpaid) invoices."}}],mapRow:"(row) => ({ id: row.id, tranId: str(row.tranid), customerId: str(row.entity), customer: str(row.customername), date: str(row.trandate), dueDate: str(row.duedate), status: status(row.status), currency: str(row.currency), total: num(row.foreigntotal), amountDue: num(row.foreignamountunpaid), subsidiaryId: str(row.subsidiary), memo: str(row.memo) })"}),Rs({id:"netsuite-list-vendor-bills",name:"List NetSuite vendor bills",shortName:"Vendor bills",instruction:"Lists vendor bills from NetSuite with vendor, dates, status, approval status, total and amount due. Useful for verifying migrated open AP at go-live.",stepId:"queryBills",collection:"bills",select:"SELECT t.id, t.tranid, t.entity, BUILTIN.DF(t.entity) AS vendorname, TO_CHAR(t.trandate, 'YYYY-MM-DD') AS trandate, TO_CHAR(t.duedate, 'YYYY-MM-DD') AS duedate, BUILTIN.DF(t.status) AS status, BUILTIN.DF(t.approvalstatus) AS approvalstatus, cur.symbol AS currency, t.foreigntotal, t.foreignamountunpaid, t.subsidiary, t.memo FROM transaction t LEFT JOIN currency cur ON cur.id = t.currency",baseWhere:["t.type = 'VendBill'"],orderBy:"t.id",filters:[...Xb,Yd("t"),{input:"openOnly",kind:"flag",clause:"t.status = 'A'",schema:{type:"boolean",description:"Only return open bills (approved and not fully paid)."}}],mapRow:"(row) => ({ id: row.id, referenceNo: str(row.tranid), vendorId: str(row.entity), vendor: str(row.vendorname), date: str(row.trandate), dueDate: str(row.duedate), status: status(row.status), approvalStatus: str(row.approvalstatus), currency: str(row.currency), total: row.foreigntotal === undefined ? null : Math.abs(Number(row.foreigntotal)), amountDue: num(row.foreignamountunpaid), subsidiaryId: str(row.subsidiary), memo: str(row.memo) })"}),Rs({id:"netsuite-list-dimensions",name:"List NetSuite departments, classes or locations",shortName:"Departments, classes, locations",instruction:"Lists department, class or location records from NetSuite with hierarchy and subsidiaries. Useful for validating the dimension setup after an implementation and for finding the internal IDs the write tools need.",stepId:"queryDimensions",collection:"records",properties:{dimension:{type:"string",enum:["department","class","location"],description:"Which dimension to list."}},required:["dimension"],select:{js:String.raw`'SELECT d.id, d.name, d.fullname, d.parent, d.subsidiary, d.includechildren, d.isinactive FROM ' + (() => { const table = { department: 'department', class: 'classification', location: 'location' }[String(p.dimension || '')]; if (!table) throw new Error("dimension must be 'department', 'class' or 'location'."); return table; })() + ' d'`},orderBy:"d.id",filters:[Gd("d")],mapRow:"(row) => ({ id: row.id, name: str(row.name), fullName: str(row.fullname), parentId: str(row.parent), subsidiaryIds: ids(row.subsidiary), includeChildren: bool(row.includechildren), isInactive: bool(row.isinactive) })"}),Rs({id:"netsuite-list-subsidiaries",name:"List NetSuite subsidiaries",shortName:"Subsidiaries",instruction:"Lists subsidiaries from NetSuite with hierarchy, country, base currency and elimination flag. Most create tools need a subsidiary ID from this list in OneWorld accounts.",stepId:"querySubsidiaries",collection:"subsidiaries",select:"SELECT s.id, s.name, s.fullname, s.parent, s.country, cur.symbol AS currency, s.iselimination, s.isinactive FROM subsidiary s LEFT JOIN currency cur ON cur.id = s.currency",orderBy:"s.id",filters:[Gd("s")],mapRow:"(row) => ({ id: row.id, name: str(row.name), fullName: str(row.fullname), parentId: str(row.parent), country: str(row.country), currency: str(row.currency), isElimination: bool(row.iselimination), isInactive: bool(row.isinactive) })"}),{id:"netsuite-suiteql-query",name:"Run a NetSuite SuiteQL query",shortName:"SuiteQL query",instruction:"Runs a read-only SuiteQL SELECT query against NetSuite, for any record type, join or aggregate outside the prebuilt lists (for example items, employees, transaction lines or custom records). The workhorse tool for migration validation. Returns up to 1000 rows in one call with the total row count and hasMore; values are strings as NetSuite returns them.",inputSchema:{type:"object",properties:{query:{type:"string",description:`SuiteQL SELECT statement, e.g. "SELECT id, itemid, displayname FROM item WHERE isinactive = 'F' ORDER BY id". Dates come back in the user's date format; use TO_CHAR(field, 'YYYY-MM-DD') for ISO dates and BUILTIN.DF(field) for display names. For more than 1000 rows, page by key: ORDER BY id and add WHERE id > <last id>. Common columns: account (id, acctnumber, accountsearchdisplaynamecopy as the name, fullname, accttype, isinactive; there is no acctname column), customer (id, entityid, companyname, email, subsidiary, balancesearch, isinactive), vendor (id, entityid, companyname, email, subsidiary, balance, isinactive), transaction (id, tranid, type, trandate, entity, status, foreigntotal, foreignamountunpaid, subsidiary). Alias tables and qualify columns: FROM transaction t ... t.subsidiary works, an unqualified subsidiary fails.`},maxResults:{type:"integer",minimum:1,maximum:1e3,description:"Maximum number of rows to return (max 1000). Defaults to 100."}},required:["query"],additionalProperties:!1},steps:[{id:"runSuiteQl",instruction:"Run the SuiteQL query.",config:{type:"request",systemId:Jd,url:`${Og}/query/v1/suiteql`,method:"POST",headers:{...Ug,"Content-Type":"application/json",Prefer:"transient"},queryParams:{limit:"<<(p) => Math.min(Math.max(Math.floor(Number(p.maxResults)) || 100, 2), 1000)>>",offset:"0"},body:String.raw`<<(p) => { const query = String(p.query || '').trim(); if (!/^(select|with)\b/i.test(query)) throw new Error('query must be a SuiteQL SELECT statement.'); return JSON.stringify({ q: query }); }>>`}}],outputTransform:`(sourceData) => { ${fL} const data = sourceData.runSuiteQl && sourceData.runSuiteQl.data ? sourceData.runSuiteQl.data : {}; const items = Array.isArray(data.items) ? data.items : []; const max = Math.min(Math.max(Math.floor(Number(sourceData.maxResults)) || 100, 1), 1000); const records = stripLinks(items.slice(0, max)); const total = data.totalResults !== undefined ? Number(data.totalResults) : items.length; return { total, returned: records.length, hasMore: total > records.length, records }; }`},{id:"netsuite-get-record",name:"Get a NetSuite record",shortName:"Get record",instruction:"Fetches one NetSuite record of any type by internal ID or external ID through the REST record API, including its sublists such as transaction lines. Useful for inspecting a record in full before or after a write.",inputSchema:{type:"object",properties:{recordType:{type:"string",description:'REST record type, e.g. "customer", "vendor", "invoice", "vendorbill", "journalentry", "account", "department" or a custom record like "customrecord_x".'},internalId:{type:"string",description:"Internal ID of the record."},externalId:{type:"string",description:"External ID of the record, used when internalId is not set."},expandSubResources:{type:"boolean",description:"Include sublists and subrecords inline. Defaults to true."}},required:["recordType"],additionalProperties:!1},steps:[{id:"getRecord",instruction:"Fetch the record from the REST record API.",config:{type:"request",systemId:Jd,url:`${Og}/record/v1/<<(p) => { const type = String(p.recordType || '').trim().toLowerCase(); if (!/^[a-z][a-z0-9_]*$/.test(type)) throw new Error('recordType must contain only letters, numbers and underscores.'); return type; }>>/<<(p) => { if (p.internalId !== undefined && p.internalId !== null && p.internalId !== '') { const id = String(p.internalId).trim(); if (!/^-?\\d+$/.test(id)) throw new Error('internalId must be a NetSuite internal ID.'); return id; } if (p.externalId !== undefined && p.externalId !== null && p.externalId !== '') return 'eid:' + encodeURIComponent(String(p.externalId)); throw new Error('Provide internalId or externalId.'); }>>`,method:"GET",headers:Ug,queryParams:{expandSubResources:"<<(p) => (p.expandSubResources === false || p.expandSubResources === 'false' ? 'false' : 'true')>>"}}}],outputTransform:`(sourceData) => { ${fL} const record = sourceData.getRecord ? sourceData.getRecord.data : undefined; if (!record || typeof record !== 'object') throw new Error('NetSuite returned no record.'); return { record: stripLinks(record) }; }`},vr({id:"netsuite-create-journal-entry",name:"Create NetSuite journal entry",shortName:"Create journal entry",instruction:`Creates a journal entry in NetSuite through the REST record API. Debit and credit lines must balance. Returns the new internal ID. ${ja}`,stepId:"createJournalEntry",recordType:"journalentry",mode:"create",properties:{...yL("create"),lines:{type:"array",description:"Journal lines. Debit and credit totals must balance.",items:mL}},required:["date","lines"],body:`${gL} if (!Array.isArray(p.lines) || p.lines.length < 2) throw new Error('lines must contain at least two journal lines.'); ${hL}`}),vr({id:"netsuite-update-journal-entry",name:"Update NetSuite journal entry",shortName:"Update journal entry",instruction:"Updates an existing NetSuite journal entry by internal ID. Only the provided fields change. When lines are provided they replace all existing lines and must balance. Entries in closed periods refuse updates.",stepId:"updateJournalEntry",recordType:"journalentry",mode:"update",properties:{...yL("update"),lines:{type:"array",description:"Optional replacement lines. When set, they replace every existing line and must balance.",items:mL}},required:[],body:`${gL} if (Array.isArray(p.lines) && p.lines.length < 2) throw new Error('lines must contain at least two journal lines; omit lines to keep the current ones.'); ${hL}`,replaceSublist:{input:"lines",sublist:"line"}}),vr({id:"netsuite-create-vendor",name:"Create NetSuite vendor",shortName:"Create vendor",instruction:`Creates a vendor record in NetSuite. OneWorld accounts need a subsidiaryId. Omit entityId when auto-numbering assigns it. ${ja}`,stepId:"createVendor",recordType:"vendor",mode:"create",properties:Tg("vendor"),required:[],body:`if (!has(p.companyName) && !((p.isPerson === true || p.isPerson === 'true') && has(p.lastName))) throw new Error('Provide companyName, or isPerson with lastName.'); ${Qg}`}),vr({id:"netsuite-update-vendor",name:"Update NetSuite vendor",shortName:"Update vendor",instruction:"Updates an existing NetSuite vendor by internal ID. Only the provided fields change; set isInactive to inactivate or reactivate it.",stepId:"updateVendor",recordType:"vendor",mode:"update",properties:{...Tg("vendor"),...Dg},required:[],body:Qg}),vr({id:"netsuite-create-customer",name:"Create NetSuite customer",shortName:"Create customer",instruction:`Creates a customer record in NetSuite. OneWorld accounts need a subsidiaryId. Omit entityId when auto-numbering assigns it. ${ja}`,stepId:"createCustomer",recordType:"customer",mode:"create",properties:Tg("customer"),required:[],body:`if (!has(p.companyName) && !((p.isPerson === true || p.isPerson === 'true') && has(p.lastName))) throw new Error('Provide companyName, or isPerson with lastName.'); ${Qg}`}),vr({id:"netsuite-update-customer",name:"Update NetSuite customer",shortName:"Update customer",instruction:"Updates an existing NetSuite customer by internal ID. Only the provided fields change; set isInactive to inactivate or reactivate it.",stepId:"updateCustomer",recordType:"customer",mode:"update",properties:{...Tg("customer"),...Dg},required:[],body:Qg}),vr({id:"netsuite-create-account",name:"Create NetSuite GL account",shortName:"Create GL account",instruction:`Creates a general ledger account in NetSuite's chart of accounts. ${ja}`,stepId:"createAccount",recordType:"account",mode:"create",properties:IL,required:["acctName","acctType"],body:`if (!has(p.acctName) || !has(p.acctType)) throw new Error('acctName and acctType are required.'); ${EL} ${Rg}`}),vr({id:"netsuite-update-account",name:"Update NetSuite GL account",shortName:"Update GL account",instruction:"Updates an existing NetSuite GL account by internal ID. Only the provided fields change; set isInactive to inactivate or reactivate it. Accounts with transactions may refuse a type change.",stepId:"updateAccount",recordType:"account",mode:"update",properties:{...IL,...Dg},required:[],body:`${EL} ${Rg}`}),vr({id:"netsuite-create-invoice",name:"Create NetSuite invoice",shortName:"Create invoice",instruction:`Creates a customer invoice in NetSuite with item lines. Item, tax and posting rules of the account apply. ${ja}`,stepId:"createInvoice",recordType:"invoice",mode:"create",properties:{customerId:{type:"string",description:"Customer internal ID."},...kg("create"),lines:{type:"array",description:"Item lines.",items:wL}},required:["customerId","lines"],body:`if (!Array.isArray(p.lines) || p.lines.length === 0) throw new Error('lines must contain at least one item line.'); ${Ng("customerId")} ${SL}`}),vr({id:"netsuite-update-invoice",name:"Update NetSuite invoice",shortName:"Update invoice",instruction:"Updates an existing NetSuite invoice by internal ID. Only the provided fields change. When lines are provided they replace all existing item lines. Paid invoices and closed periods may refuse updates.",stepId:"updateInvoice",recordType:"invoice",mode:"update",properties:{customerId:{type:"string",description:"Optional new customer internal ID."},...kg("update"),lines:{type:"array",description:"Optional replacement item lines; they replace every existing item line.",items:wL}},required:[],body:`if (Array.isArray(p.lines) && p.lines.length === 0) throw new Error('lines must contain at least one item line; omit lines to keep the current ones.'); ${Ng("customerId")} ${SL}`,replaceSublist:{input:"lines",sublist:"item"}}),vr({id:"netsuite-create-vendor-bill",name:"Create NetSuite vendor bill",shortName:"Create vendor bill",instruction:`Creates a vendor bill in NetSuite with expense lines. Approval routing of the account applies. ${ja}`,stepId:"createVendorBill",recordType:"vendorbill",mode:"create",properties:{vendorId:{type:"string",description:"Vendor internal ID."},referenceNo:{type:"string",description:"Optional vendor invoice reference number."},...kg("create"),lines:{type:"array",description:"Expense lines.",items:_L}},required:["vendorId","lines"],body:`if (!Array.isArray(p.lines) || p.lines.length === 0) throw new Error('lines must contain at least one expense line.'); ${Ng("vendorId")} if (has(p.referenceNo)) record.tranId = String(p.referenceNo); ${BL}`}),vr({id:"netsuite-update-vendor-bill",name:"Update NetSuite vendor bill",shortName:"Update vendor bill",instruction:"Updates an existing NetSuite vendor bill by internal ID. Only the provided fields change. When lines are provided they replace all existing expense lines. Paid bills and closed periods may refuse updates.",stepId:"updateVendorBill",recordType:"vendorbill",mode:"update",properties:{vendorId:{type:"string",description:"Optional new vendor internal ID."},referenceNo:{type:"string",description:"Optional vendor invoice reference number."},...kg("update"),lines:{type:"array",description:"Optional replacement expense lines; they replace every existing expense line.",items:_L}},required:[],body:`if (Array.isArray(p.lines) && p.lines.length === 0) throw new Error('lines must contain at least one expense line; omit lines to keep the current ones.'); ${Ng("vendorId")} if (has(p.referenceNo)) record.tranId = String(p.referenceNo); ${BL}`,replaceSublist:{input:"lines",sublist:"expense"}}),vr({id:"netsuite-create-department",name:"Create NetSuite department",shortName:"Create department",instruction:`Creates a department in NetSuite. Without subsidiaryIds NetSuite assigns the parent subsidiary. ${ja}`,stepId:"createDepartment",recordType:"department",mode:"create",properties:bL,required:["name"],body:`if (!has(p.name)) throw new Error('name is required.'); ${CL} ${Rg}`}),vr({id:"netsuite-update-department",name:"Update NetSuite department",shortName:"Update department",instruction:"Updates an existing NetSuite department by internal ID. Only the provided fields change; set isInactive to inactivate or reactivate it.",stepId:"updateDepartment",recordType:"department",mode:"update",properties:{...bL,...Dg},required:[],body:`${CL} ${Rg}`})],eS={sap_s4hana:{bundleId:"sap_s4hana",templateId:"sap_s4hana",systemId:"sap_s4hana",displayName:"SAP S/4HANA",description:"Read business partners, sales orders, products and purchase orders from SAP.",systemUrl:the,credentialHint:"Works instantly with SAP's demo data. Add your own key later for your live system.",requiredCredentialKeys:["api_key"],demoCredentials:{api_key:"K8reTgiKCCaqvAPWC4cOjqqiLdLE8dqz"},mcpServer:{name:"sap",displayName:"SAP S/4HANA",description:"Business partners, sales orders, products and purchase orders from SAP."},installMcpServer:!0,agentLaunch:{userPrompt:"I just installed the SAP S/4HANA bundle. What can I do with it?",nextSteps:"Your first reply must be short: SAP is connected to free demo data and works right now, so offer to run one tool immediately as proof. No credential collection is needed to start. If they want their own data: their own free key comes from https://api.sap.com (SAP Business Accelerator Hub), collected and saved directly with a connect field, never via the Connections page; the system URL can then be switched to their own SAP host. Do not list the installed tools, do not add tips or explain SAP concepts unless asked."},tools:[{id:"sap-list-business-partners",name:"List SAP business partners",shortName:"Business partners",instruction:"Lists business partners (customers, suppliers, contacts) from SAP S/4HANA. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "BusinessPartnerCategory eq '2'" for organizations.`},maxResults:{type:"integer",description:"Maximum number of business partners to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchBusinessPartners",instruction:"Fetch business partners, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_BUSINESS_PARTNER/A_BusinessPartner",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:"<<filter>>",$select:"BusinessPartner,BusinessPartnerFullName,BusinessPartnerCategory,BusinessPartnerGrouping,CreationDate"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const d = (v) => { if (typeof v !== 'string' || !v.startsWith('/Date(')) return v; const n = parseInt(v.slice(6), 10); return Number.isFinite(n) ? new Date(n).toISOString().slice(0, 10) : v; }; const rows = (sourceData.fetchBusinessPartners?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, businessPartners: rows.map((r) => ({ id: r.BusinessPartner, name: r.BusinessPartnerFullName, category: r.BusinessPartnerCategory, grouping: r.BusinessPartnerGrouping, createdOn: d(r.CreationDate) })) }; }"},{id:"sap-list-sales-orders",name:"List SAP sales orders",shortName:"Sales orders",instruction:"Lists sales orders from SAP S/4HANA with their net amount, currency and sold-to party. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "SalesOrderType eq 'OR'" or "TotalNetAmount gt 1000".`},maxResults:{type:"integer",description:"Maximum number of sales orders to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchSalesOrders",instruction:"Fetch sales orders, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_SALES_ORDER_SRV/A_SalesOrder",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:"<<filter>>",$select:"SalesOrder,SalesOrderType,SoldToParty,TotalNetAmount,TransactionCurrency,SalesOrderDate,OverallSDProcessStatus"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const d = (v) => { if (typeof v !== 'string' || !v.startsWith('/Date(')) return v; const n = parseInt(v.slice(6), 10); return Number.isFinite(n) ? new Date(n).toISOString().slice(0, 10) : v; }; const rows = (sourceData.fetchSalesOrders?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, salesOrders: rows.map((r) => ({ id: r.SalesOrder, type: r.SalesOrderType, soldToParty: r.SoldToParty, netAmount: Number(r.TotalNetAmount), currency: r.TransactionCurrency, orderDate: d(r.SalesOrderDate), status: r.OverallSDProcessStatus })) }; }"},{id:"sap-list-products",name:"List SAP products",shortName:"Products",instruction:"Lists products (materials) from SAP S/4HANA with their type, group and base unit. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "ProductType eq 'FERT'" for finished goods.`},maxResults:{type:"integer",description:"Maximum number of products to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchProducts",instruction:"Fetch products, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_PRODUCT_SRV/A_Product",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:"<<filter>>",$expand:"to_Description",$select:"Product,ProductType,ProductGroup,BaseUnit,GrossWeight,WeightUnit,CreationDate,to_Description/Language,to_Description/ProductDescription"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const d = (v) => { if (typeof v !== 'string' || !v.startsWith('/Date(')) return v; const n = parseInt(v.slice(6), 10); return Number.isFinite(n) ? new Date(n).toISOString().slice(0, 10) : v; }; const nameOf = (r) => { const list = r.to_Description?.results ?? []; const hit = list.find((x) => x.Language === 'EN') ?? list[0]; return hit?.ProductDescription; }; const rows = (sourceData.fetchProducts?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, products: rows.map((r) => ({ id: r.Product, name: nameOf(r), type: r.ProductType, group: r.ProductGroup, baseUnit: r.BaseUnit, grossWeight: Number(r.GrossWeight), weightUnit: r.WeightUnit, createdOn: d(r.CreationDate) })) }; }"},{id:"sap-list-purchase-orders",name:"List SAP purchase orders",shortName:"Purchase orders",instruction:"Lists purchase orders from SAP S/4HANA with their supplier, currency and creation date. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "PurchaseOrderType eq 'NB'" for standard orders.`},maxResults:{type:"integer",description:"Maximum number of purchase orders to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchPurchaseOrders",instruction:"Fetch purchase orders, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_PURCHASEORDER_PROCESS_SRV/A_PurchaseOrder",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:"<<filter>>",$select:"PurchaseOrder,PurchaseOrderType,Supplier,PurchaseOrderDate,DocumentCurrency,CreatedByUser"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const d = (v) => { if (typeof v !== 'string' || !v.startsWith('/Date(')) return v; const n = parseInt(v.slice(6), 10); return Number.isFinite(n) ? new Date(n).toISOString().slice(0, 10) : v; }; const rows = (sourceData.fetchPurchaseOrders?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, purchaseOrders: rows.map((r) => ({ id: r.PurchaseOrder, type: r.PurchaseOrderType, supplier: r.Supplier, orderDate: d(r.PurchaseOrderDate), currency: r.DocumentCurrency, createdBy: r.CreatedByUser })) }; }"},{id:"sap-list-gl-accounts",name:"List SAP chart of accounts",shortName:"Chart of accounts",instruction:"Lists general ledger accounts (the chart of accounts) from SAP S/4HANA. Supports an optional OData $filter, e.g. by ChartOfAccounts.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "ChartOfAccounts eq 'YCOA'" or "GLAccountType eq 'X'".`},maxResults:{type:"integer",description:"Maximum number of accounts to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchGLAccounts",instruction:"Fetch GL accounts, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_GLACCOUNTINCHARTOFACCOUNTS_SRV/A_GLAccountInChartOfAccounts",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:`<<(p) => p.filter ? "ChartOfAccounts ne '' and (" + p.filter + ")" : "ChartOfAccounts ne ''">>`,$expand:"to_Text",$select:"GLAccount,ChartOfAccounts,GLAccountType,GLAccountGroup,IsBalanceSheetAccount,AccountIsBlockedForPosting,to_Text/Language,to_Text/GLAccountName"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const nameOf = (r) => { const list = r.to_Text?.results ?? []; const hit = list.find((x) => x.Language === 'EN') ?? list[0]; return hit?.GLAccountName; }; const rows = (sourceData.fetchGLAccounts?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, accounts: rows.map((r) => ({ account: r.GLAccount, name: nameOf(r), chartOfAccounts: r.ChartOfAccounts, type: r.GLAccountType, group: r.GLAccountGroup, isBalanceSheet: r.IsBalanceSheetAccount, blockedForPosting: r.AccountIsBlockedForPosting })) }; }"},{id:"sap-list-billing-documents",name:"List SAP billing documents",shortName:"Billing documents",instruction:"Lists billing documents (invoices, credit memos) from SAP S/4HANA with amount, currency and sold-to party. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "BillingDocumentType eq 'F2'" or "TotalNetAmount gt 1000".`},maxResults:{type:"integer",description:"Maximum number of billing documents to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchBillingDocuments",instruction:"Fetch billing documents, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_BILLING_DOCUMENT_SRV/A_BillingDocument",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:"<<filter>>",$select:"BillingDocument,BillingDocumentType,SoldToParty,TotalNetAmount,TransactionCurrency,BillingDocumentDate"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const d = (v) => { if (typeof v !== 'string' || !v.startsWith('/Date(')) return v; const n = parseInt(v.slice(6), 10); return Number.isFinite(n) ? new Date(n).toISOString().slice(0, 10) : v; }; const rows = (sourceData.fetchBillingDocuments?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, billingDocuments: rows.map((r) => ({ id: r.BillingDocument, type: r.BillingDocumentType, soldToParty: r.SoldToParty, netAmount: Number(r.TotalNetAmount), currency: r.TransactionCurrency, date: d(r.BillingDocumentDate) })) }; }"},{id:"sap-list-journal-entry-items",name:"List SAP journal entry line items",shortName:"Journal entries",instruction:"Lists journal entry line items (accounting document items) from SAP S/4HANA with company code, GL account, amount and posting date. Filter by CompanyCode, FiscalYear or PostingDate to keep results focused. Useful for verifying opening balances at cutover.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "CompanyCode eq '1010' and FiscalYear eq '2026'".`},maxResults:{type:"integer",description:"Maximum number of line items to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchJournalItems",instruction:"Fetch accounting document line items, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_OPLACCTGDOCITEMCUBE_SRV/A_OperationalAcctgDocItemCube",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:"<<filter>>",$select:"AccountingDocument,CompanyCode,FiscalYear,GLAccount,AmountInCompanyCodeCurrency,PostingDate"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const d = (v) => { if (typeof v !== 'string' || !v.startsWith('/Date(')) return v; const n = parseInt(v.slice(6), 10); return Number.isFinite(n) ? new Date(n).toISOString().slice(0, 10) : v; }; const rows = (sourceData.fetchJournalItems?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, journalItems: rows.map((r) => ({ document: r.AccountingDocument, companyCode: r.CompanyCode, fiscalYear: r.FiscalYear, account: r.GLAccount, amount: Number(r.AmountInCompanyCodeCurrency), postingDate: d(r.PostingDate) })) }; }"},{id:"sap-query-odata",name:"Query any SAP OData service",shortName:"Query any service",instruction:"Queries any SAP S/4HANA OData service and entity set (for example API_PRODUCT_SRV/A_ProductDescription or API_SALES_ORDER_SRV/A_SalesOrderItem) with optional $select and $filter. The workhorse tool for data checks beyond the prebuilt lists.",inputSchema:{type:"object",properties:{servicePath:{type:"string",description:'Service and entity set in SERVICE/EntitySet form, e.g. "API_SALES_ORDER_SRV/A_SalesOrderItem".'},select:{type:"string",description:"Comma-separated OData $select field list. Omit for all fields."},filter:{type:"string",description:"Optional OData $filter expression."},maxResults:{type:"integer",description:"Maximum number of records to return. Defaults to 100."}},required:["servicePath"],additionalProperties:!0},steps:[{id:"queryService",instruction:"Query the requested OData service and entity set.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/<<servicePath>>",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$select:"<<select>>",$filter:"<<filter>>",$top:"<<pageSize>>",$skip:"<<offset>>"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 100; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const rows = (sourceData.queryService?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 100); return { total: rows.length, records: rows.map((r) => { const { __metadata, ...rest } = r; return rest; }) }; }"}]},sage100:{bundleId:"sage100",templateId:"sage100",systemId:"sage100",displayName:"Sage 100",description:"Connect on-premises Sage 100 through the superglue Secure Gateway, with a guided setup playbook and a connection test against the Business Object Interface.",systemUrl:"script://runner/vbs32",credentialHint:"Your assistant first helps you connect a Secure Gateway on your Sage 100 server, then collects your Sage company and user details.",requiredCredentialKeys:["sage_home","sage_company","sage_user","sage_password"],mcpServer:{name:"sage-100",displayName:"Sage 100",description:"Sage 100 Business Object Interface access through the Secure Gateway."},installMcpServer:!1,playbook:{id:"sage100-native-integration",name:"Sage 100 Native Integration (BOI)",whenToRun:"Use when connecting a Sage 100 installation to superglue, testing that connection, or building tools that read or write Sage 100 data through the Business Object Interface.",inputs:"A Sage 100 installation on a Windows machine the user can access; a superglue API key for the gateway; the Sage company code, a Sage user with module access, and the path to the MAS90\\Home directory; the business outcome once connected.",instructions:"First check /org/tunnels for a connected gateway with a runner target. If none is connected, guide the user step by step: download the Windows gateway from https://downloads.superglue.cloud/superglue-gateway-windows.exe onto the machine where Sage 100 and Workstation Setup are installed (the gateway must run there, ProvideX.Script is a local 32-bit COM class), create a config.yaml next to it with a tunnel_id, the server_url ending in /ws/tunnels (wss://api.superglue.cloud/ws/tunnels for hosted superglue), an API key from the API Keys page, and the line enable_script_runner: true, then run the executable. That flag is required: it opts the gateway into running Sage scripts (it is code execution on their machine, so it is off by default), and it is what registers the built-in runner target. No targets section is needed. If a tunnel is connected but has no runner target, the gateway is either missing enable_script_runner: true or is an outdated build; have the user add the flag and restart, or download the current gateway from the same URL. When the tunnel with the runner target appears, attach it to the Sage 100 connection with tools.writeConnection (tunnel with that tunnelId) and keep the URL script://runner/vbs32. Collect sage_home (full path to the MAS90\\Home directory, for example C:\\Sage\\Sage100\\MAS90\\Home, not the MAS90 directory itself), sage_company, sage_user and sage_password through the secure credential form. Then run the Test Sage 100 connection tool once and interpret the result: retVal 0 failures carry the Sage reason in sLastErrorMsg (wrong credentials, missing role access, wrong company code); COM error 0x80040154 means the gateway is not running on a machine with Sage 100 Workstation Setup; a no-license message means all Sage user seats are in use. For new capabilities, build tools whose steps use the script protocol with VBScript in the body: log on with SY_Session, set module context before touching data (nSetDate with YYYYMMDD dates, nSetModule, nLookupTask, nSetProgram), use _svc service objects for reads and _bus business objects for writes, and always release the session with nCleanup and DropObject so the license seat frees up. For reads, set each key segment with nSetKeyValue then nFind for a single record, or browse with nMoveFirst and nMoveNext, and read each field with nGetValue passing a variable that receives the value. To write a document that has lines, such as a sales order, get the header _bus object, set the header fields, get its oLines object, call nAddLine, set the line fields, then call nWrite on the header to commit the header and its lines together. A write fails with a lock error if the record is open in the Sage desktop or held by another session, so report the lock message instead of retrying. Each running script briefly consumes a Sage user seat. Ask for explicit approval before any script that writes to Sage, and warn that records open in the Sage desktop UI cause lock errors.",completionCriteria:"The gateway is connected, the installed Sage 100 system has the tunnel attached and credentials saved, and the connection test returned company data from Sage 100. Any additional requested capability works end to end, with writes explicitly approved before they ran."},agentLaunch:{userPrompt:"I just installed the Sage 100 integration. Help me connect my Sage 100 server.",nextSteps:"Your first reply must be short: one line confirming the Sage 100 integration and setup playbook are installed, then start the connection flow. Check /org/tunnels for a connected gateway with a runner target first. If none exists, walk the user through it one step at a time: download https://downloads.superglue.cloud/superglue-gateway-windows.exe onto the Windows machine where Sage 100 is installed and Workstation Setup has run, create a config.yaml next to it with tunnel_id, server_url (wss://api.superglue.cloud/ws/tunnels for hosted superglue), an API key from the API Keys page, and the line enable_script_runner: true, then run it. That flag is required: it opts the gateway into running scripts on their machine (off by default because it is code execution) and is what registers the runner target. No targets are needed in the config. If a tunnel is connected but has no runner target, the gateway is missing enable_script_runner: true or is an outdated build: have the user add the flag and restart, or download the current one from the same URL. Wait for the user to confirm, then verify the tunnel appears and attach it to the Sage 100 connection with tools.writeConnection tunnel, keeping the URL script://runner/vbs32. Use connect with the connection id and fields to save sage_home (full path to the MAS90\\Home directory, for example C:\\Sage\\Sage100\\MAS90\\Home, not MAS90 itself), sage_company (for example ABC for the demo company), sage_user and sage_password. Never send the user to the Connections page. Then run the Test Sage 100 connection tool once. If it fails, explain the specific cause in plain language before retrying. Mention that each test briefly uses one Sage user license seat. Do not list tools or add tips unless asked."},tools:[{id:"sage100-test-connection",name:"Test Sage 100 connection",shortName:"Connection test",instruction:"Logs on to Sage 100 through the Secure Gateway, opens the configured company, and reads the first customer record to verify the Business Object Interface end to end. Briefly consumes one Sage user license seat.",steps:[{id:"testConnection",instruction:"Run a VBScript through the gateway script runner that logs on via SY_Session, sets A/R module context, and reads the first customer.",config:{type:"request",systemId:"sage100",url:"<<sage100_url>>",method:"POST",body:["Option Explicit","On Error Resume Next","Dim oScript, oSS, oCust, retVal, custNo, custName, today",'Set oScript = CreateObject("ProvideX.Script")','FailOnErr "CREATE", " (Sage 100 Workstation Setup has not registered ProvideX.Script on this machine; the gateway must run on a prepared Sage 100 machine)"','oScript.Init "<<sage100_sage_home>>"','FailOnErr "INIT", " (sage_home must be the full path to the MAS90\\Home directory, not MAS90 itself)"','Set oSS = oScript.NewObject("SY_Session")','FailOnErr "SESSION", ""','retVal = oSS.nSetUser("<<sage100_sage_user>>", "<<sage100_sage_password>>")','FailOnErr "LOGON", ""',"If retVal = 0 Then",' WScript.Echo "LOGON FAILED: " & oSS.sLastErrorMsg'," WScript.Quit 1","End If",'retVal = oSS.nSetCompany("<<sage100_sage_company>>")','FailOnErr "COMPANY", ""',"If retVal = 0 Then",' WScript.Echo "COMPANY FAILED: " & oSS.sLastErrorMsg'," oSS.nCleanup"," oSS.DropObject"," WScript.Quit 1","End If",'today = Year(Date) & Right("0" & Month(Date), 2) & Right("0" & Day(Date), 2)','retVal = oSS.nSetDate("A/R", today)','FailOnErr "DATE", ""','retVal = oSS.nSetModule("A/R")','FailOnErr "MODULE", ""','retVal = oSS.nSetProgram(oSS.nLookupTask("AR_Customer_ui"))','FailOnErr "TASK", ""',"If retVal = 0 Then",' WScript.Echo "TASK FAILED: " & oSS.sLastErrorMsg'," oSS.nCleanup"," oSS.DropObject"," WScript.Quit 1","End If",'Set oCust = oScript.NewObject("AR_Customer_svc", oSS)','FailOnErr "CUSTOMER OBJECT", ""',"retVal = oCust.nMoveFirst()",'FailOnErr "READ", ""',"If retVal = 0 Then",' WScript.Echo "READ FAILED: " & oCust.sLastErrorMsg',"Else",' custNo = "" : custName = ""',' retVal = oCust.nGetValue("CustomerNo$", custNo)',' retVal = oCust.nGetValue("CustomerName$", custName)',' FailOnErr "READ VALUE", " (ByRef value marshalling failed)"',' WScript.Echo "CONNECTED - company <<sage100_sage_company>>, first customer: " & custNo & " / " & custName',"End If","oCust.DropObject","oSS.nCleanup","oSS.DropObject","If retVal = 0 Then WScript.Quit 1","","Sub FailOnErr(stage, hint)"," If Err.Number <> 0 Then",' WScript.Echo stage & " FAILED: [0x" & Hex(Err.Number) & "] " & Err.Description & hint'," WScript.Quit 1"," End If","End Sub"].join(`
112
+ ${t.slice(t.length-n)}`}function $Ae(t){return t instanceof Error?t.message:typeof t=="string"?t:typeof t=="object"&&t!==null&&"message"in t?String(t.message):String(t)}function FAe(t,e){if(!e||Object.keys(e).length===0)return{};let r=/file::([^,\s)}\]"']+)/g,n=typeof t=="string"?t:JSON.stringify(t||{}),i=[...new Set([...n.matchAll(r)].map(o=>{let s=o[1];return s.endsWith(".raw")?s=s.slice(0,-4):s.endsWith(".base64")?s=s.slice(0,-7):s.endsWith(".extracted")&&(s=s.slice(0,-10)),s}))];return Object.fromEntries(i.flatMap(o=>e[o]?[[o,e[o]]]:[]))}function jAe(t){if(!t)return null;let e=t.indexOf(":");if(e===-1)return{source:"simpleicons",name:t};let r=t.substring(0,e),n=t.substring(e+1);return r!=="simpleicons"&&r!=="lucide"?{source:"simpleicons",name:t}:{source:r,name:n}}function zAe(t){return t?typeof t=="string"?t.indexOf(":")!==-1?t:`simpleicons:${t}`:`${t.source}:${t.name}`:null}function yM(t){if(t.op==="remove"||t.value===void 0||typeof t.value!="string")return t;if(t.path==="/inputSchema"||t.path==="/outputSchema"||t.path.startsWith("/inputSchema/properties/")||t.path.startsWith("/outputSchema/properties/")||t.path.match(/^\/steps\/\d+\/config\/pagination$/)||t.path.match(/^\/steps\/\d+\/config\/headers$/)||t.path.match(/^\/steps\/\d+\/config\/queryParams$/))try{return{...t,value:JSON.parse(t.value)}}catch{return t}return t}function HAe(t){return t.map(e=>yM(e))}function qAe(t,e){t||(t=""),e||(e=""),/^(https?|postgres(ql)?|ftp(s)?|sftp|smb|file):\/\//i.test(t)||(t=`https://${t}`);let r=t.endsWith("/")?t.slice(0,-1):t,n=e.startsWith("/")?e.slice(1):e;return`${r}/${n}`}var GAe=new Set(["data","stepResults","toolPayload","rawData","transformedData"]),YAe=8e4;function VAe(t,e=YAe){if(t==null)return t;let r=t;if(typeof t=="string"){if(t.length<=e)return t;try{r=JSON.parse(t)}catch{return{_truncated:!0,_message:"String result too large to parse",_size:t.length}}}if(typeof r!="object")return r;let n=0,i=0,o=(s,a=0)=>{if(a>20||s===null||typeof s!="object")return s;if(Array.isArray(s))return s.map(u=>o(u,a+1));let c={};for(let[u,l]of Object.entries(s))if(GAe.has(u)&&l!==null&&typeof l=="object"){let d=JSON.stringify(l);if(d.length>e){i+=d.length;try{let{jsonString:A,truncatedProps:p}=(0,Vde.default)(d,e);c[u]=JSON.parse(A),n+=p.length}catch{c[u]=l}}else c[u]=l}else c[u]=o(l,a+1);return c};try{if(JSON.stringify(r).length<=e)return r;let a=o(r);return n>0&&typeof a=="object"&&a!==null&&(a._note=`Result truncated: ${n} items omitted (original ${i} characters)`),a}catch{return{_truncated:!0,_message:"Result too large to display"}}}function JAe(t){if(!t.steps)return[];let e=new Set;for(let r of t.steps)r.config&&(0,eM.isRequestConfig)(r.config)&&r.config.systemId&&e.add(r.config.systemId);return Array.from(e)}function Eg(t,e,r=new WeakSet){if(typeof t=="string"){e.push(t);return}if(!(!t||typeof t!="object")&&!r.has(t)){if(r.add(t),Array.isArray(t)){for(let n of t)Eg(n,e,r);return}for(let n of Object.values(t))Eg(n,e,r)}}function WAe(t){let e=[];for(let r of t.matchAll(/<<([\s\S]*?)>>/g)){let n=r[1].trim();n&&e.push(n)}for(let r of t.matchAll(/{{\s*([^{}\s]+)\s*}}/g)){let n=r[1].trim();n&&e.push(n)}return e}function EM(t,e){let r=[];Eg(t,r);let n=`${e}_`,i=new Set;for(let o of r)for(let s of WAe(o)){if(!s.startsWith(n))continue;let a=s.slice(n.length);!a||a==="url"||!k.CREDENTIAL_KEY_PATTERN.test(a)||i.add(a)}return[...i]}var ZAe=/^\s*(async\s+)?(\([^)]*\)|[a-zA-Z_$][a-zA-Z0-9_$]*)\s*=>/,KAe=new Set(["sg_auth_email","sg_auth_jwt"]);function XAe({config:t,systemId:e}){let r=[];Eg(t,r);let n=e?`${e}_`:null,i=new Set;for(let u of r)for(let l of u.matchAll(/<<([\s\S]*?)>>/g)){let d=l[1].trim();d&&(n&&d.startsWith(n)||ZAe.test(d)||KAe.has(d)||i.add(d))}if(i.size===0)return null;let o=[...i].map(u=>`<<${u}>>`).join(", "),s=`Unresolved placeholder${i.size===1?"":"s"} ${o}`;if(!n)return`${s}. Secret placeholders need systemId and the form <<systemId_secretName>>. Nothing was sent.`;let a=[...i].filter(u=>k.CREDENTIAL_KEY_PATTERN.test(u)).map(u=>`<<${n}${u}>>`),c=a.length>0?`Secret placeholders are namespaced by system: use ${a.join(", ")}.`:`Secret placeholders are namespaced by system as <<${n}secretName>>.`;return`${s}. ${c} Nothing was sent.`}function epe(t){let e={};if(!t.steps)return e;for(let r of t.steps){if(!r.config||!(0,eM.isRequestConfig)(r.config)||!r.config.systemId)continue;let n=EM(r.config,r.config.systemId);if(n.length===0)continue;let i=new Set(e[r.config.systemId]||[]);for(let o of n)i.add(o);e[r.config.systemId]=[...i]}return e}function tpe(t){return t.replace(/([a-z])([A-Z])|([A-Z]{2,})([A-Z][a-z])/g,"$1$3 $2$4").replace(/[_-]/g," ").replace(/\b\w/g,e=>e.toUpperCase()).replace(/\b(Id|Url|Api|Ui)\b/g,e=>e.toUpperCase())}});var wM=m(yt=>{"use strict";Object.defineProperty(yt,"__esModule",{value:!0});yt.AGENT_CONTEXT_MEMORY_MESSAGE_ID_PREFIX=void 0;yt.applyToolMutation=IM;yt.mutateToolCallInMessages=npe;yt.buildStreamingAssistantMessage=CM;yt.parseToolOutput=bM;yt.parseAgentStreamEventLine=ope;yt.stopActiveTool=SM;yt.appendContentToMessage=zb;yt.updateMessageWithData=yu;yt.findAwaitingConfirmationToolCallIds=spe;yt.declineAwaitingConfirmationTools=ape;yt.findAndResumeMessageWithTool=cpe;yt.serializeMessageForPersistence=lpe;yt.isTurnContextBlockMessage=Hb;yt.normalizeAgentSessionForkMessages=Ape;yt.normalizeAgentSessionImportMessages=ppe;yt.createAgentTranscriptState=fpe;yt.applyAgentStreamChunk=hpe;var rpe=Lr(),bg=Rn();function IM(t,e){let r=e.frontendOutput!==void 0?e.frontendOutput:t.frontendOutput;return{...t,...e.input!==void 0?{input:e.input}:{},...e.result!==void 0?{result:e.result}:{},...e.status!==void 0?{status:e.status}:{},...e.startTime!==void 0?{startTime:e.startTime}:{},...e.endTime!==void 0?{endTime:e.endTime}:{},...e.error!==void 0?{error:e.error||void 0}:{},...r!==void 0?{frontendOutput:r}:{},...e.llmOutput!==void 0?{llmOutput:e.llmOutput}:{},...e.resultMetadata!==void 0?{resultMetadata:e.resultMetadata}:{},...e.confirmationState!==void 0?{confirmationState:e.confirmationState===null?void 0:e.confirmationState}:{},...e.confirmationData!==void 0?{confirmationData:e.confirmationData===null?void 0:e.confirmationData}:{}}}function npe(t,e,r){return t.map(n=>{let i=!1,o=n.parts?.map(s=>s.type!=="tool"||!s.tool||s.tool.id!==e?s:(i=!0,{...s,tool:IM(s.tool,r)}));return i&&o?{...n,parts:o}:n})}function CM(t){return{id:t,content:"",role:"assistant",timestamp:new Date,parts:[{type:"content",content:"",id:"content-0"}],isStreaming:!0}}function ipe(){return{status:"declined",endTime:new Date,confirmationState:"declined",confirmationData:{reason:"new_user_message",message:"Rejected: the user sent a new message instead of confirming this action. The proposed changes were NOT applied."}}}function bM(t){if(!t)return null;if(typeof t=="string")try{let e=JSON.parse(t);return e&&typeof e=="object"&&!Array.isArray(e)?e:null}catch{return null}return typeof t=="object"&&!Array.isArray(t)?t:null}function ope(t){if(!t.startsWith("data: "))return null;try{let e=JSON.parse(t.slice(6));return e&&typeof e=="object"&&!Array.isArray(e)?e:null}catch{return null}}function SM(t){return t.status==="running"||t.status==="pending"||t.status==="awaiting_confirmation"?{...t,status:"stopped",endTime:new Date,confirmationState:void 0,confirmationData:void 0}:t}function zb(t,e){if(!e)return t;let r=[...t.parts||[]],n=r[r.length-1];return n?.type==="content"?r[r.length-1]={...n,content:(n.content||"")+e}:r.push({type:"content",content:e,id:`content-${r.length}`}),{...t,parts:r,content:""}}function yu(t,e,r){if(t.id!==r.id)return t;switch(e.type){case"content":return zb(t,e.content||"");case"tool_call_start":{let n=t.parts?.find(u=>u.type==="tool"&&u.tool?.id===e.toolCall.id)?.tool,i=e.toolCall.input??n?.input,o=e.executionMode==="confirm"?"awaiting_confirmation":i?"running":"pending",s={...n,id:e.toolCall.id,name:e.toolCall.name,input:i,status:o,startTime:n?.startTime||new Date,...n?.confirmationState!==void 0?{confirmationState:n.confirmationState}:{},...n?.confirmationData!==void 0?{confirmationData:n.confirmationData}:{}},a=[...t.parts||[]],c=a.findIndex(u=>u.type==="tool"&&u.tool?.id===e.toolCall.id);return c===-1?a.push({type:"tool",tool:s,id:`tool-${e.toolCall.id}`}):a[c]={...a[c],tool:s},{...t,parts:a,content:""}}case"tool_call_input":{let n=i=>i.id===e.toolCall.id&&e.toolCall.input!==void 0?{...i,input:e.toolCall.input}:i;return{...t,parts:t.parts?.map(i=>i.type==="tool"&&i.tool?{...i,tool:n(i.tool)}:i)}}case"run_command_effect":{let n=e.effect;if(n?.kind!=="visual"&&n?.kind!=="checklist"||typeof e.toolCallId!="string")return t;let i=o=>{if(o.id!==e.toolCallId)return o;let s=bM(o.frontendOutput)??{},a=(s.effects??[]).filter(c=>c.id!==n.id);return{...o,frontendOutput:{...s,effects:[...a,n]}}};return{...t,parts:t.parts?.map(o=>o.type==="tool"&&o.tool?{...o,tool:i(o.tool)}:o)}}case"tool_call_update":{let n=t.parts?.map(i=>i.type==="tool"&&i.tool?.id===e.toolCall.id?{...i,tool:{...i.tool,executionTraceId:e.toolCall.executionTraceId??i.tool.executionTraceId,status:i.tool.status==="pending"?"running":i.tool.status}}:i)||[];return{...t,parts:n}}case"tool_call_complete":{let n=t.parts?.find(h=>h.type==="tool"&&h.tool?.id===e.toolCall.id)?.tool,i=n?.status==="completed"||n?.status==="declined",o=e.toolCall.result!==void 0||e.toolCall.frontendOutput!==void 0||e.toolCall.status!==void 0||e.toolCall.confirmationState!==void 0||e.toolCall.confirmationData!==void 0;if(i&&!o)return t;let s=null;try{s=typeof e.toolCall.frontendOutput=="string"?JSON.parse(e.toolCall.frontendOutput):e.toolCall.frontendOutput}catch{}let a=s?.success===!1&&s?.error,c=e.toolCall.result?.outcome,u=c==="failure"?"error":c==="rejected"?"declined":c==="aborted"?"stopped":c==="success"?"completed":void 0,l=e.toolCall.status||u||"completed";a&&l==="completed"&&(l="error");let d=l==="awaiting_confirmation",A={...e.toolCall.input!==void 0?{input:e.toolCall.input}:{},...e.toolCall.result!==void 0?{result:e.toolCall.result}:{},status:l,frontendOutput:e.toolCall.frontendOutput,llmOutput:e.toolCall.llmOutput,resultMetadata:e.toolCall.resultMetadata,error:c==="failure"?e.toolCall.result.error.message:a?s.error:null,endTime:d?void 0:new Date,...e.toolCall.confirmationState!==void 0?{confirmationState:e.toolCall.confirmationState}:{},...e.toolCall.confirmationData!==void 0?{confirmationData:e.toolCall.confirmationData}:{}},p=t.parts?.map(h=>h.type==="tool"&&h.tool?.id===e.toolCall.id?{...h,tool:{...h.tool,...A}}:h)||[];return{...t,parts:p}}case"done":{if(!t.isStreaming)return t;let n=(t.parts||[]).map(i=>i.type==="tool"&&i.tool&&i.tool.status!=="awaiting_confirmation"?{...i,tool:SM(i.tool)}:i);return{...t,isStreaming:!1,parts:n,content:""}}default:return t}}function spe(t){let e=new Set;for(let r of t)for(let n of(0,bg.getMessageToolCalls)(r))n.status==="awaiting_confirmation"&&e.add(n.id);return[...e]}function ape(t){let e=ipe();return t.map(r=>({...r,parts:r.parts?.map(n=>n.type==="tool"&&n.tool?.status==="awaiting_confirmation"?{...n,tool:{...n.tool,...e}}:n)}))}function cpe(t,e){let r=t.find(i=>i.parts?.some(o=>o.type==="tool"&&o.tool?.id===e));return r?{messages:t.map(i=>i.id===r.id?{...i,isStreaming:!0}:i),targetMessage:{...r,isStreaming:!0}}:{messages:t,targetMessage:null}}function upe(t){return{id:t.id,name:t.name,status:t.status,input:t.input,result:t.result,frontendOutput:t.frontendOutput,llmOutput:t.llmOutput,resultMetadata:t.resultMetadata,error:t.error,startTime:t.startTime,endTime:t.endTime,confirmationState:t.confirmationState,confirmationData:t.confirmationData}}function lpe(t){let{isStreaming:e,tools:r,...n}=t;return JSON.parse((0,bg.safeStringify)({...n,...t.parts?{parts:t.parts.map(i=>i.type==="tool"&&i.tool?{...i,tool:upe(i.tool)}:i)}:{}},0))}yt.AGENT_CONTEXT_MEMORY_MESSAGE_ID_PREFIX="context-memory-";var dpe=["artifacts"];function Hb(t){let e=t.contextType??"";return rpe.TURN_CONTEXT_BLOCK_TYPES.includes(e)||dpe.includes(e)}function Ape(t){return t.filter(e=>e.role!=="system"&&e.contextType!=="memory_notes"&&!Hb(e)&&!e.id.startsWith(yt.AGENT_CONTEXT_MEMORY_MESSAGE_ID_PREFIX)).map(e=>({...e,stale:void 0,isStreaming:void 0}))}function ppe(t){return t.filter(e=>!e.stale&&!e.isStreaming&&e.contextType!=="memory_notes"&&!Hb(e)&&!!e.id)}function fpe(t=[],e=null){return{messages:t,assistantMessageId:e,outcome:"streaming"}}function Cg(t,e){return(0,bg.getMessageToolCalls)(t).some(r=>r.id===e)}function mu(t,e){let r=t.assistantMessageId?t.messages.find(i=>i.id===t.assistantMessageId):void 0;if(r)return{state:t,target:r};let n=CM(t.assistantMessageId??e.createAssistantMessageId());return{state:{...t,messages:[...t.messages,n],assistantMessageId:n.id},target:n}}function hpe(t,e,r){switch(e.type){case"system_message":{if(!e.systemMessage)return t;let n={id:e.systemMessage.id,role:"system",content:e.systemMessage.content,timestamp:new Date};return{...t,messages:[n,...t.messages]}}case"assistant_message_start":{if(!e.assistantMessageId)return t;let n=t.assistantMessageId?t.messages.find(o=>o.id===t.assistantMessageId):void 0;return t.messages.find(o=>o.id===e.assistantMessageId)?{...t,assistantMessageId:e.assistantMessageId,messages:t.messages.filter(o=>!n||n.id===e.assistantMessageId||o.id!==n.id).map(o=>o.id===e.assistantMessageId?{...o,isStreaming:!0}:o)}:n?{...t,assistantMessageId:e.assistantMessageId,messages:t.messages.map(o=>o.id===n.id?{...o,id:e.assistantMessageId,isStreaming:!0}:o)}:{...t,assistantMessageId:e.assistantMessageId}}case"context_message":{if(!e.contextMessage)return t;let n={id:e.contextMessage.id,role:"user",content:e.contextMessage.content,timestamp:new Date,...e.contextMessage.isHidden?{isHidden:!0}:{},...e.contextMessage.attachedFiles?.length?{attachedFiles:e.contextMessage.attachedFiles}:{}};return{...t,assistantMessageId:null,messages:[...t.messages.map(i=>i.id===t.assistantMessageId?{...i,isStreaming:!1}:i),n]}}case"context_usage":case"compaction_start":return t;case"compaction_complete":{if(!e.compaction)return t;let n=(0,bg.applyAgentCompactionToMessages)(t.messages,e.compaction),i=e.compaction.memoryMessage?t.assistantMessageId:null;return!i||!n.some(o=>o.id===i)?{...t,messages:n}:{...t,assistantMessageId:null,messages:n.map(o=>o.id===i?{...o,isStreaming:!1}:o)}}case"content":{let n=mu(t,r);return{...n.state,messages:n.state.messages.map(i=>i.id===n.target.id?zb(i,e.content||""):i)}}case"error":{let n=mu(t,r);return{...n.state,outcome:"failed",messages:n.state.messages.map(i=>i.id!==n.target.id?i:{...i,parts:[...i.parts||[],{type:"error",content:e.content,errorDetails:e.errorDetails,id:`error-${i.parts?.length??0}`}],isStreaming:!1})}}case"tool_call_start":case"tool_call_update":{if(!e.toolCall)return t;let n=e.type==="tool_call_start"?null:t.messages.find(o=>Cg(o,e.toolCall.id))??null,i=n?{state:t,target:n}:mu(t,r);return{...i.state,messages:i.state.messages.map(o=>yu(o,e,i.target))}}case"run_command_effect":{let n=e.toolCallId;if(!n)return t;let i=t.messages.find(o=>Cg(o,n));return i?{...t,messages:t.messages.map(o=>yu(o,e,i))}:t}case"tool_call_input":{if(!e.toolCall)return t;let n=t.messages.find(i=>Cg(i,e.toolCall.id));return n?{...t,messages:t.messages.map(i=>yu(i,e,n))}:t}case"tool_call_complete":{if(!e.toolCall)return t;let n=t.messages.find(o=>Cg(o,e.toolCall.id)),i=n?{state:t,target:n}:mu(t,r);return{...i.state,messages:i.state.messages.map(o=>yu(o,e,i.target))}}case"paused":{let n=mu(t,r);return{...n.state,outcome:"paused",messages:n.state.messages.map(i=>i.id===n.target.id?{...i,isStreaming:!1}:i)}}case"done":{let n=mu(t,r);return{...n.state,outcome:t.outcome==="failed"?"failed":"completed",messages:n.state.messages.map(i=>yu(i,e,n.target))}}default:return t}}});var Sg=m(Et=>{"use strict";Object.defineProperty(Et,"__esModule",{value:!0});Et.PROJECT_LABEL_COLOR_PATTERN=Et.PROJECT_LABEL_COLORS=Et.PROJECT_LIMITS=Et.PROJECT_TASK_STATUSES=Et.PROJECT_RESOURCE_TYPES=void 0;Et.isProjectResourceType=gpe;Et.nextProjectLabelColor=mpe;Et.projectResourceKey=ype;Et.daysUntilTaskDue=_M;Et.formatTaskDueDate=Epe;Et.groupByContext=Ipe;Et.PROJECT_RESOURCE_TYPES=["file","tool"];function gpe(t){return Et.PROJECT_RESOURCE_TYPES.includes(t)}Et.PROJECT_TASK_STATUSES=["not_started","in_progress","waiting","done"];Et.PROJECT_LIMITS={name:80,description:500,taskName:120,taskDescription:1e4,labelName:40,labels:50,taskLabels:10};Et.PROJECT_LABEL_COLORS=["#6b7280","#ef4444","#f97316","#eab308","#22c55e","#14b8a6","#3b82f6","#6366f1","#a855f7","#ec4899"];Et.PROJECT_LABEL_COLOR_PATTERN=/^#[0-9a-f]{6}$/;function mpe(t){let e=new Set(t.map(r=>r.color));return Et.PROJECT_LABEL_COLORS.find(r=>!e.has(r))??Et.PROJECT_LABEL_COLORS[t.length%Et.PROJECT_LABEL_COLORS.length]}function ype(t){return`${t.type}:${t.id}`}function BM(t){let e=new Intl.DateTimeFormat("en-CA",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit"}).format(new Date);return new Date(`${e}T00:00:00Z`)}function _M(t,e){let r=new Date(`${t}T00:00:00Z`);return Math.round((r.getTime()-BM(e).getTime())/864e5)}function Epe(t,e){let r=new Date(`${t}T00:00:00Z`),n=BM(e),i=_M(t,e);return i===0?"Due today":i===1?"Due tomorrow":i===-1?"Due yesterday":i<-1?`${-i} days overdue`:i<7?`Due ${r.toLocaleDateString(void 0,{weekday:"long",timeZone:"UTC"})}`:`Due ${r.toLocaleDateString(void 0,{day:"numeric",month:"short",timeZone:"UTC",...r.getUTCFullYear()===n.getUTCFullYear()?{}:{year:"numeric"}})}`}function Ipe(t){let e=new Map;for(let r of t)e.set(r.context,[...e.get(r.context)??[],r]);return[...e].map(([r,n])=>({context:r,items:n})).sort((r,n)=>+!!r.context-+!!n.context)}});var wg=m(Gr=>{"use strict";Object.defineProperty(Gr,"__esModule",{value:!0});Gr.RESOURCE_KINDS=Gr.RESOURCE_DEFINITIONS=void 0;Gr.isResourceKind=Cpe;Gr.getResourceDefinition=bpe;Gr.getResourceAppPath=Spe;Gr.RESOURCE_DEFINITIONS={tool:{label:"Tool",pluralLabel:"Tools",collectionKey:"tools",appPath:"/tools",hasDetailPage:!0,memberDefaultPermission:"editor",pickerDefaultPermission:"editor"},credential:{label:"Connection",pluralLabel:"Connections",collectionKey:"credentials",appPath:"/connections",hasDetailPage:!0,pickerDefaultPermission:"viewer"},playbook:{label:"Playbook",pluralLabel:"Playbooks",collectionKey:"playbooks",appPath:"/brain/playbooks",hasDetailPage:!0,pickerDefaultPermission:"editor"},file:{label:"File",pluralLabel:"Files",collectionKey:"files",appPath:"/brain/files",hasDetailPage:!0,pickerDefaultPermission:"viewer"},project:{label:"Project",pluralLabel:"Projects",collectionKey:"projects",appPath:"/brain/projects",hasDetailPage:!0,pickerDefaultPermission:"viewer"}};Gr.RESOURCE_KINDS=Object.keys(Gr.RESOURCE_DEFINITIONS);function Cpe(t){return typeof t=="string"&&Object.prototype.hasOwnProperty.call(Gr.RESOURCE_DEFINITIONS,t)}function bpe(t){return Gr.RESOURCE_DEFINITIONS[t]}function Spe(t,e){let r=Gr.RESOURCE_DEFINITIONS[t];return r.hasDetailPage?`${r.appPath}/${encodeURIComponent(e)}`:r.appPath}});var DM=m(La=>{"use strict";Object.defineProperty(La,"__esModule",{value:!0});La.SDK_ERROR_DETAILS_SCHEMA=La.SDK_OUTPUT_CONTRACTS=void 0;La.toSdkJsonSchema=vpe;var y=Ia(),wpe=Sg(),Bpe=wg(),_pe=Lr();function vpe({schema:t}){return y.z.toJSONSchema(t,{target:"draft-7",io:"output",unrepresentable:"any"})}var vM=y.z.looseObject({statusCode:y.z.number(),headers:y.z.record(y.z.string(),y.z.union([y.z.string(),y.z.array(y.z.string())])),omittedHeaderCount:y.z.number().optional()}),QM=y.z.looseObject({vfsPath:y.z.string(),storedBytes:y.z.number(),originalOutputBytes:y.z.number(),storageTruncated:y.z.boolean()}),TM=y.z.object({action:y.z.enum(["approve","reject","oauth_success","oauth_failure"]),source:y.z.enum(["user","automatic"])});function Yr(t){return y.z.looseObject({toolCallId:y.z.string(),toolName:y.z.string(),outcome:y.z.literal("success"),confirmation:TM.optional(),data:t})}var qb={http:vM.optional(),connection:y.z.looseObject({id:y.z.string(),name:y.z.string(),isOwner:y.z.boolean()}).optional().describe("The connection the call ran with."),auth:y.z.looseObject({applied:y.z.enum(["bearer","basic","explicit","none","unavailable"]),header:y.z.string().optional(),placeholders:y.z.array(y.z.string()),reason:y.z.string().optional()}).optional().describe("How authentication was sent: a default Bearer or Basic header, the request's own explicit placeholders, none, or unavailable with the reason. placeholders lists the connection's <<systemId_secretName>> strings."),secretPlaceholders:y.z.looseObject({keys:y.z.array(y.z.string()),resolved:y.z.boolean()}).optional()},Qpe=y.z.discriminatedUnion("protocol",[y.z.looseObject({protocol:y.z.enum(["postgres","odbc"]),data:y.z.array(y.z.record(y.z.string(),y.z.unknown())).describe("Returned database rows."),...qb}),y.z.looseObject({protocol:y.z.literal("mssql"),data:y.z.union([y.z.array(y.z.record(y.z.string(),y.z.unknown())),y.z.array(y.z.array(y.z.record(y.z.string(),y.z.unknown()))),y.z.looseObject({rowsAffected:y.z.array(y.z.number())})]).describe("One recordset, multiple recordsets, or affected row counts."),...qb}),y.z.looseObject({protocol:y.z.enum(_pe.CONNECTION_PROTOCOLS.filter(t=>t!=="postgres"&&t!=="mssql"&&t!=="odbc")),data:y.z.unknown().describe("Complete protocol response payload. Preserve sibling fields, including files and metadata; do not unwrap a nested data field."),...qb})]),Tpe=y.z.union([y.z.looseObject({tools:y.z.array(y.z.unknown()).describe("All tools from every tools/list page, each with name and inputSchema.")}),y.z.looseObject({result:y.z.looseObject({content:y.z.array(y.z.unknown()).optional(),structuredContent:y.z.unknown().optional(),isError:y.z.boolean().optional()}).describe("The tools/call result with content blocks and optional structuredContent.")})]),Dpe=y.z.looseObject({url:y.z.string().describe("The requested URL."),status:y.z.number(),statusText:y.z.string(),headers:y.z.record(y.z.string(),y.z.string()),body:y.z.string().describe("Response body bytes, base64-encoded."),systemId:y.z.string().optional().describe("The system whose connection authenticated the request."),connection:y.z.looseObject({id:y.z.string(),name:y.z.string(),isOwner:y.z.boolean()}).optional().describe("The connection the request ran with.")}),Rpe=y.z.looseObject({stepId:y.z.string(),success:y.z.boolean(),data:y.z.unknown().optional(),error:y.z.string().nullable().optional(),http:vM.optional(),stepFileKeys:y.z.array(y.z.string()).optional()}),Npe=y.z.looseObject({toolId:y.z.string(),success:y.z.boolean(),run:y.z.looseObject({id:y.z.string()}).optional(),data:y.z.unknown().optional().describe("Tool output, determined by its output transform."),error:y.z.string().optional(),stepResults:y.z.array(Rpe),fileArtifacts:y.z.array(y.z.looseObject({fileKey:y.z.string(),filename:y.z.string(),contentType:y.z.string(),size:y.z.number(),downloadUrl:y.z.string().optional()})).optional(),warnings:y.z.array(y.z.string()).optional(),inputSchema:y.z.unknown().optional(),resultMetadata:QM.optional()}),kpe=Yr(y.z.looseObject({resource:y.z.looseObject({id:y.z.string(),name:y.z.string().optional(),path:y.z.string().optional(),version:y.z.union([y.z.number(),y.z.string()]).optional()}),created:y.z.boolean(),projectId:y.z.string().optional(),projectAttribution:y.z.looseObject({attached:y.z.boolean(),projectId:y.z.string(),projectName:y.z.string().optional(),resource:y.z.looseObject({type:y.z.enum(wpe.PROJECT_RESOURCE_TYPES),id:y.z.string()}),error:y.z.string().optional()}).optional()}));La.SDK_OUTPUT_CONTRACTS={assignSessionToProject:{name:"SuperglueSessionProjectResult",schema:Yr(y.z.object({sessionId:y.z.string(),projectId:y.z.string().nullable()})),description:"Returns the saved session ID and project ID, or null when unassigned. Throws SuperglueError on failure."},callSystem:{name:"SuperglueCallSystemResult",schema:Qpe,description:"Returns the complete protocol payload in data, available HTTP metadata, the connection used, and how authentication was sent. Throws SuperglueError on failure; details contains the canonical result and unprojected execution output."},callMcp:{name:"SuperglueCallMcpResult",schema:Tpe,description:"Returns { tools } when tool is omitted, or { result } from tools/call. Throws SuperglueError on HTTP, JSON-RPC, or result.isError failures; details.result.data contains statusCode, rpcError, or the failed result. On result.isError or invalid params, the error message ends with the called tool's input schema when it can be read; large schemas are shortened."},systemFetch:{name:"SuperglueSystemFetchResult",schema:Dpe,description:"Returns the raw HTTP response: status, headers, and the base64 body. HTTP error statuses are returned, not thrown. Throws SuperglueError when the request cannot be authenticated or sent."},runTool:{name:"SuperglueRunToolResult",schema:Npe,description:"Returns successful tool output, step results, files, and available result reference. Throws SuperglueError on failure; details.result.data preserves this result shape with success: false, the error, and available run and step results. details.resultMetadata references the saved failed result when available."},writeResource:{name:"SuperglueWriteResult",schema:kpe,description:"Returns saved resource identity and path, creation status, and available project attribution. Throws SuperglueError on failure."},installBundle:{name:"SuperglueBundleInstallResult",schema:Yr(y.z.looseObject({bundleId:y.z.string(),system:y.z.looseObject({id:y.z.string(),name:y.z.string(),requiredCredentialKeys:y.z.array(y.z.string()),hasUserCredentials:y.z.boolean()}),tools:y.z.array(y.z.looseObject({id:y.z.string(),name:y.z.string().optional()})),mcpServer:y.z.looseObject({id:y.z.string(),name:y.z.string()}).optional(),playbook:y.z.looseObject({id:y.z.string(),name:y.z.string()}).optional()})),description:"Returns the installed system ID, tool, MCP server, and playbook identities, the secret names the user must supply, and whether the user has a complete connection. Throws SuperglueError on failure."},stopBackgroundJob:{name:"SuperglueStopBackgroundJobResult",schema:Yr(y.z.looseObject({job:y.z.looseObject({id:y.z.string(),status:y.z.string(),elapsedMs:y.z.number(),exitCode:y.z.number().optional()})})),description:"Returns the job's status, run time, and exit code after it ended, or status running when the stop is still in progress. Throws SuperglueError when the session has no such running job."},setToolState:{name:"SuperglueToolStateResult",schema:Yr(y.z.looseObject({resource:y.z.looseObject({id:y.z.string()}),action:y.z.enum(["set","reset"])})),description:"Returns the saved tool identity and state action. Throws SuperglueError on failure."},shareResource:{name:"SuperglueShareResult",schema:Yr(y.z.looseObject({resource:y.z.looseObject({kind:y.z.enum(Bpe.RESOURCE_KINDS),id:y.z.string()})})),description:"Returns the shared resource identity. Throws SuperglueError on failure."},useChecklist:{name:"SuperglueChecklistResult",schema:Yr(y.z.strictObject({visible:y.z.boolean(),done:y.z.number(),total:y.z.number()})),description:"Returns whether the session checklist is visible and its completed and total milestone counts. The progress panel updates immediately. Throws SuperglueError on failure."},showVisual:{name:"SuperglueShowVisualResult",schema:Yr(y.z.looseObject({visualId:y.z.string(),check:y.z.looseObject({errors:y.z.array(y.z.string()),blockedRequests:y.z.array(y.z.string()),dataCalls:y.z.array(y.z.string()),contentHeight:y.z.number().optional(),timedOut:y.z.boolean()}).optional(),checkSkipped:y.z.string().optional(),screenshots:y.z.array(y.z.string()).optional()})),description:"Returns the visualId shown to the user. For a custom visual, check holds the test-browser result, and screenshots lists the labels of the screenshots attached to this command's result for you. Throws SuperglueError ETOOL when the visual fails its check; error.details.result.data.check then holds the errors."},notifyUser:{name:"SuperglueNotifyResult",schema:Yr(y.z.looseObject({nextStepIds:y.z.array(y.z.string())})),description:"Returns the nextStepIds of the saved actions, in action order. Throws SuperglueError on failure."},writeOrgSettings:{name:"SuperglueOrgSettingsResult",schema:Yr(y.z.looseObject({updated:y.z.array(y.z.enum(["name","preferences","notifications"])),notificationTest:y.z.looseObject({channel:y.z.enum(["slack","email"]),sent:y.z.boolean(),error:y.z.string().optional()}).optional()})),description:"Returns updated settings and any notification test result. Throws SuperglueError on failure."},writeDesignSystem:{name:"SuperglueDesignSystemResult",schema:Yr(y.z.looseObject({updated:y.z.array(y.z.enum(["tokens","guidelines","logo"])),added:y.z.array(y.z.looseObject({id:y.z.string(),kind:y.z.enum(["logo","font","template","reference"]),name:y.z.string()})),changed:y.z.array(y.z.string()),removed:y.z.array(y.z.string())})),description:"Returns the changed design-system parts and file ids. Throws SuperglueError on failure."},importDesignSystemFromUrl:{name:"SuperglueDesignSystemImportResult",schema:Yr(y.z.looseObject({url:y.z.string(),title:y.z.string().nullable(),tokens:y.z.looseObject({}),palette:y.z.array(y.z.looseObject({color:y.z.string(),weight:y.z.number()})),fonts:y.z.array(y.z.looseObject({family:y.z.string(),usage:y.z.array(y.z.string()),source:y.z.string()})),fontFiles:y.z.array(y.z.looseObject({file:y.z.string(),family:y.z.string().describe("CSS family name the website uses"),roles:y.z.array(y.z.string()),weight:y.z.string(),style:y.z.enum(["normal","italic"])})),logos:y.z.array(y.z.looseObject({file:y.z.string(),source:y.z.string(),width:y.z.number(),height:y.z.number(),light:y.z.boolean().describe("Light artwork meant for dark backgrounds")})),screenshot:y.z.string().nullable()})),description:"Returns a proposed design system from the website; font files, logos, and the screenshot are file:: session uploads. Throws SuperglueError on failure."},readQbm:{name:"SuperglueReadQbmResult",schema:Yr(y.z.looseObject({folder:y.z.string(),objects:y.z.array(y.z.looseObject({type:y.z.string(),files:y.z.array(y.z.string()),records:y.z.number()})),rawTables:y.z.array(y.z.looseObject({table:y.z.string(),files:y.z.array(y.z.string()),rows:y.z.number()})),encryptedValues:y.z.array(y.z.looseObject({table:y.z.string(),column:y.z.string(),values:y.z.number()})),unmappedCodes:y.z.array(y.z.looseObject({field:y.z.string(),code:y.z.string(),records:y.z.number()})).optional(),attachments:y.z.looseObject({documents:y.z.number(),note:y.z.string()}).optional(),rejectedRows:y.z.array(y.z.looseObject({table:y.z.string(),rows:y.z.number()})).optional()})),description:"Returns the folder that holds the extracted files, record counts per object type and raw table, encrypted columns, codes the reader cannot decode, and expected attachments. The folder also holds coverage.json.raw with the same summary plus the mapped source tables. Throws SuperglueError on failure."},previewFile:{name:"SuperglueFilePreviewResult",schema:y.z.looseObject({draftId:y.z.string(),bytes:y.z.number()}),description:"Returns the HTML draft identity and byte count. Throws SuperglueError on failure."}};var Ope=y.z.looseObject({code:y.z.string(),path:y.z.array(y.z.union([y.z.string(),y.z.number(),y.z.symbol()])),message:y.z.string()});La.SDK_ERROR_DETAILS_SCHEMA=y.z.discriminatedUnion("kind",[y.z.looseObject({kind:y.z.literal("tool_result"),resultMetadata:QM.optional(),result:y.z.looseObject({toolCallId:y.z.string(),toolName:y.z.string(),outcome:y.z.enum(["success","failure","rejected","aborted"]),confirmation:TM.optional(),error:y.z.looseObject({message:y.z.string()}).optional(),data:y.z.unknown().optional()}),output:y.z.unknown().describe("Unprojected execution output, including the original error and any available response data or metadata.")}),y.z.looseObject({kind:y.z.enum(["input_validation","output_validation"]),toolName:y.z.string(),issues:y.z.array(Ope),output:y.z.unknown().optional()})])});var jM=m(we=>{"use strict";Object.defineProperty(we,"__esModule",{value:!0});we.SERVER_OWNED_SESSION_RESOURCE_KINDS=we.AgentRequestValidationError=we.AGENT_TOOL_CONTINUATION_ACTION_BY_CONFIRMATION_STATE=we.AGENT_TOOL_CONTINUATION_ACTIONS=we.AGENT_IDENTIFIER_PATTERN=we.AGENT_REQUEST_LIMITS=void 0;we.validateAgentRequestPayload=MM;we.validateResourceBinding=LM;we.validateClientResourceBinding=PM;we.validateAgentSessionIdentity=$M;we.validateAgentSessionTarget=FM;we.validateAgentRequestSubmission=Fpe;we.isAgentMessagePayload=jpe;we.isAgentToolContinuationPayload=zpe;var qo=Lr();we.AGENT_REQUEST_LIMITS={messageContentChars:5e4,identifierChars:256,attachedFiles:20,toolContinuations:20,continuationInputChars:1e5,frontendDraftsChars:2e6,accessRulesContextChars:2e6,pendingMessagesPerSession:10};we.AGENT_IDENTIFIER_PATTERN=/^[A-Za-z0-9._-]+$/;we.AGENT_TOOL_CONTINUATION_ACTIONS=["approve","reject","oauth_success","oauth_failure"];we.AGENT_TOOL_CONTINUATION_ACTION_BY_CONFIRMATION_STATE={[qo.ConfirmationAction.CONFIRMED]:"approve",[qo.ConfirmationAction.DECLINED]:"reject",[qo.ConfirmationAction.OAUTH_SUCCESS]:"oauth_success",[qo.ConfirmationAction.OAUTH_FAILURE]:"oauth_failure"};var Bg=class extends Error{constructor(e){super(e),this.name="AgentRequestValidationError"}};we.AgentRequestValidationError=Bg;function Je(t){throw new Bg(t)}function po(t,e){return(!t||typeof t!="object"||Array.isArray(t))&&Je(`${e} must be an object`),t}function Pa(t,e){(typeof t!="string"||!t.trim())&&Je(`${e} must be a non-empty string`);let r=t.trim();return r.length>we.AGENT_REQUEST_LIMITS.identifierChars&&Je(`${e} exceeds ${we.AGENT_REQUEST_LIMITS.identifierChars} characters`),we.AGENT_IDENTIFIER_PATTERN.test(r)||Je(`${e} may only contain letters, numbers, dots, underscores, and hyphens`),r}function Upe(t,e){return typeof t!="boolean"&&Je(`${e} must be a boolean`),t}function Gb(t,e){try{return JSON.stringify(t).length}catch{return Je(`${e} must be JSON-serializable`)}}function xpe(t,e){if(t!==void 0)return Array.isArray(t)||Je(`${e} must be an array`),t.length>we.AGENT_REQUEST_LIMITS.attachedFiles&&Je(`${e} exceeds ${we.AGENT_REQUEST_LIMITS.attachedFiles} entries`),t.map((r,n)=>{let i=po(r,`${e}[${n}]`);return{...i,key:Pa(i.key,`${e}[${n}].key`)}})}function RM({value:t,label:e,requireHidden:r}){let n=po(t,e),i=Pa(n.id,`${e}.id`);typeof n.content!="string"&&Je(`${e}.content must be a string`);let o=n.content;o.length>we.AGENT_REQUEST_LIMITS.messageContentChars&&Je(`${e}.content exceeds ${we.AGENT_REQUEST_LIMITS.messageContentChars} characters`);let s=Upe(n.isHidden,`${e}.isHidden`);r&&!s&&Je(`${e}.isHidden must be true`);let a=xpe(n.attachedFiles,`${e}.attachedFiles`);return!o.trim()&&!a?.length&&Je(`${e}.content may only be empty when an attachment is present`),{id:i,content:o,isHidden:s,...a?{attachedFiles:a}:{}}}function kM(t){if(t===void 0)return;let e=po(t,"frontendDrafts");return Gb(e,"frontendDrafts")>we.AGENT_REQUEST_LIMITS.frontendDraftsChars&&Je(`frontendDrafts exceeds ${we.AGENT_REQUEST_LIMITS.frontendDraftsChars} characters`),e}function OM(t){if(t===void 0)return;let e=po(t,"accessRulesContext");return Gb(e,"accessRulesContext")>we.AGENT_REQUEST_LIMITS.accessRulesContextChars&&Je(`accessRulesContext exceeds ${we.AGENT_REQUEST_LIMITS.accessRulesContextChars} characters`),e}function UM(t){if(t!==void 0)return(typeof t!="string"||!qo.AGENT_APPROVAL_MODES.includes(t))&&Je(`request.approvalMode must be one of: ${qo.AGENT_APPROVAL_MODES.join(", ")}`),t}function xM(t,e){let r=po(t,e),n=Pa(r.toolCallId,`${e}.toolCallId`);return(typeof r.action!="string"||!we.AGENT_TOOL_CONTINUATION_ACTIONS.includes(r.action))&&Je(`${e}.action must be one of: ${we.AGENT_TOOL_CONTINUATION_ACTIONS.join(", ")}`),r.input!==void 0&&Gb(r.input,`${e}.input`)>we.AGENT_REQUEST_LIMITS.continuationInputChars&&Je(`${e}.input exceeds ${we.AGENT_REQUEST_LIMITS.continuationInputChars} characters`),{toolCallId:n,action:r.action,...r.input!==void 0?{input:r.input}:{}}}function Mpe(t){if(t===void 0)return;(!Array.isArray(t)||t.length===0)&&Je("request.toolContinuations must be a non-empty array"),t.length>we.AGENT_REQUEST_LIMITS.toolContinuations&&Je(`request.toolContinuations exceeds ${we.AGENT_REQUEST_LIMITS.toolContinuations} entries`);let e=t.map((r,n)=>xM(r,`request.toolContinuations[${n}]`));return new Set(e.map(({toolCallId:r})=>r)).size!==e.length&&Je("request.toolContinuations must not contain duplicate toolCallId values"),e}function NM(t,e){if(t===void 0)return;(typeof t!="string"||!t.trim())&&Je(`${e} must be a non-empty string`);let r=t.trim();return r.length>we.AGENT_REQUEST_LIMITS.messageContentChars&&Je(`${e} exceeds ${we.AGENT_REQUEST_LIMITS.messageContentChars} characters`),r}var Lpe=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Ppe(t){let e=RM({value:t.message,label:"request.message"}),r=NM(t.title,"request.title"),n=NM(t.titleInput,"request.titleInput"),i=t.hiddenSteeringMessage===void 0?void 0:RM({value:t.hiddenSteeringMessage,label:"request.hiddenSteeringMessage",requireHidden:!0});i&&i.id===e.id&&Je("request.hiddenSteeringMessage.id must differ from request.message.id");let o=Mpe(t.toolContinuations),s=UM(t.approvalMode),a=kM(t.frontendDrafts),c=OM(t.accessRulesContext);return t.nextStepId!==void 0&&(typeof t.nextStepId!="string"||!Lpe.test(t.nextStepId))&&Je("request.nextStepId must be a UUID"),{kind:"message",message:e,...t.nextStepId?{nextStepId:t.nextStepId}:{},...i?{hiddenSteeringMessage:i}:{},...r?{title:r}:{},...n?{titleInput:n}:{},...o?{toolContinuations:o}:{},...s?{approvalMode:s}:{},...a?{frontendDrafts:a}:{},...c?{accessRulesContext:c}:{}}}function $pe(t){let e=xM(t,"request"),r=UM(t.approvalMode),n=kM(t.frontendDrafts),i=OM(t.accessRulesContext);return{kind:"tool_continuation",...e,...r?{approvalMode:r}:{},...n?{frontendDrafts:n}:{},...i?{accessRulesContext:i}:{}}}function MM(t){let e=po(t,"request");return e.kind==="message"?Ppe(e):e.kind==="tool_continuation"?$pe(e):Je('request.kind must be "message" or "tool_continuation"')}function LM(t,e){let r=po(t,e);return(typeof r.kind!="string"||!qo.AGENT_SESSION_RESOURCE_KINDS.includes(r.kind))&&Je(`${e}.kind must be one of: ${qo.AGENT_SESSION_RESOURCE_KINDS.join(", ")}`),{kind:r.kind,id:Pa(r.id,`${e}.id`)}}we.SERVER_OWNED_SESSION_RESOURCE_KINDS=["briefing"];function PM(t,e){let r=LM(t,e);return we.SERVER_OWNED_SESSION_RESOURCE_KINDS.includes(r.kind)&&Je(`${e}.kind "${r.kind}" is assigned by the server`),r}function $M(t,e="session.createIfMissing"){let r=po(t,e),n=r.projectId===void 0?void 0:Pa(r.projectId,`${e}.projectId`),i=r.taskId===void 0?void 0:Pa(r.taskId,`${e}.taskId`);i&&!n&&Je(`${e}.taskId requires ${e}.projectId`);let o=Object.values(qo.AgentType);(typeof r.agentId!="string"||!o.includes(r.agentId))&&Je(`${e}.agentId must be one of: ${o.join(", ")}`);let s=r.resourceBinding===void 0?void 0:PM(r.resourceBinding,`${e}.resourceBinding`);return{agentId:r.agentId,...n?{projectId:n}:{},...i?{taskId:i}:{},...s?{resourceBinding:s}:{}}}function FM(t){let e=po(t,"session"),r=e.createIfMissing===void 0?void 0:$M(e.createIfMissing);return{id:Pa(e.id,"session.id"),...r?{createIfMissing:r}:{}}}function Fpe(t){let e=po(t,"body");return{session:FM(e.session),request:MM(e.request)}}function jpe(t){return t.kind==="message"}function zpe(t){return t.kind==="tool_continuation"}});var HM=m(Re=>{"use strict";Object.defineProperty(Re,"__esModule",{value:!0});Re.ARTIFACT_EXPORT_FORMATS=Re.ARTIFACT_RESPONSE_RESERVED_FIELD_NAMES=Re.ARTIFACT_RESPONSE_PATCH_DEBOUNCE_MS=Re.MAX_SPREADSHEET_ARTIFACT_BYTES=Re.MAX_HTML_ARTIFACT_IMAGE_BYTES=Re.MAX_HTML_ARTIFACT_BYTES=Re.MAX_SPREADSHEET_CELL_TEXT_LENGTH=Re.MAX_SPREADSHEET_SHEET_NAME_LENGTH=Re.MAX_SPREADSHEET_GRID_CELLS=Re.MAX_SPREADSHEET_SHEETS=Re.SPREADSHEET_CELL_TYPES=Re.XLSX_CONTENT_TYPE=Re.HTML_CONTENT_TYPE=void 0;Re.brainFileDisplayTitle=Hpe;Re.brainFileKind=qpe;Re.isValidSpreadsheetCell=Vpe;Re.isArtifactExportFormat=Jpe;Re.isArtifactExportFormatForKind=Wpe;var zM=Ia();Re.HTML_CONTENT_TYPE="text/html";Re.XLSX_CONTENT_TYPE="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";function Hpe(t){return t.replace(/\.[a-z][a-z0-9]{0,7}$/i,"")||t}function qpe({fileName:t,contentType:e}){let r=e?.split(";")[0].trim().toLowerCase(),n=t.toLowerCase().match(/\.([a-z0-9]+)$/)?.[1];return r===Re.HTML_CONTENT_TYPE||n==="html"||n==="htm"?"html":r===Re.XLSX_CONTENT_TYPE||n==="xlsx"?"spreadsheet":"file"}Re.SPREADSHEET_CELL_TYPES=["text","integer","number","percent","currency","boolean","date","datetime"];Re.MAX_SPREADSHEET_SHEETS=20;Re.MAX_SPREADSHEET_GRID_CELLS=1e6;Re.MAX_SPREADSHEET_SHEET_NAME_LENGTH=31;Re.MAX_SPREADSHEET_CELL_TEXT_LENGTH=32767;var Gpe=zM.z.iso.date(),Ype=zM.z.iso.datetime({offset:!0});function Vpe(t,e){return t===null?!0:e==="text"?typeof t=="string"&&t.length<=Re.MAX_SPREADSHEET_CELL_TEXT_LENGTH:e==="boolean"?typeof t=="boolean":["integer","number","percent","currency"].includes(e)?typeof t=="number"&&Number.isFinite(t)&&(e!=="integer"||Number.isInteger(t)):typeof t!="string"?!1:(e==="datetime"?Ype:Gpe).safeParse(t).success}Re.MAX_HTML_ARTIFACT_BYTES=1024*1024;Re.MAX_HTML_ARTIFACT_IMAGE_BYTES=12*1024*1024;Re.MAX_SPREADSHEET_ARTIFACT_BYTES=10*1024*1024;Re.ARTIFACT_RESPONSE_PATCH_DEBOUNCE_MS=300;Re.ARTIFACT_RESPONSE_RESERVED_FIELD_NAMES=new Set(["__proto__","constructor","prototype"]);Re.ARTIFACT_EXPORT_FORMATS=["pdf","docx","xlsx","pptx"];function Jpe(t){return Re.ARTIFACT_EXPORT_FORMATS.some(e=>e===t)}function Wpe(t,e,r=!1){return t==="spreadsheet"?e==="xlsx":r?e==="pdf"||e==="pptx":e!=="pptx"}});var JM=m(He=>{"use strict";Object.defineProperty(He,"__esModule",{value:!0});He.API_KEY_ACTION_LABELS=He.API_KEY_SURFACE_LABELS=He.API_KEY_SCOPES=He.API_KEY_SURFACE_ACTIONS=He.API_KEY_ACTIONS=He.API_KEY_SURFACES=void 0;He.getApiKeySurface=GM;He.getApiKeyAction=YM;He.getApiKeySurfaceActions=Yb;He.parseApiKeyScopes=VM;He.validateApiKeyScopesInput=efe;He.isApiKeyScopeAllowed=tfe;He.formatApiKeyScopes=rfe;He.API_KEY_SURFACES=["api","mcp"];He.API_KEY_ACTIONS=["read","write","execute"];He.API_KEY_SURFACE_ACTIONS={api:He.API_KEY_ACTIONS,mcp:["execute"]};He.API_KEY_SCOPES=He.API_KEY_SURFACES.flatMap(t=>He.API_KEY_SURFACE_ACTIONS[t].map(e=>`${t}:${e}`));He.API_KEY_SURFACE_LABELS={api:"API & CLI",mcp:"MCP"};He.API_KEY_ACTION_LABELS={read:"Read",write:"Write",execute:"Execute"};var qM=new Set(He.API_KEY_SCOPES),Zpe={"/v1/tools":["read"],"/v1/tools/:toolId/run":["execute"],"/v1/authenticate":["write"],"/v1/memory-notes":["read","write"]},Kpe=new Set(["/v1/api-keys","/v1/api-keys/:id","/v1/api-keys/:id/reveal"]),Xpe=new Set(["/v1/me"]);function GM(t){let e=t.split("?")[0];return e==="/mcp"||e.startsWith("/mcp/")?"mcp":"api"}function YM(t){return t==="read"?"read":t==="execute"?"execute":"write"}function Yb(t,e){return He.API_KEY_SURFACE_ACTIONS[e].filter(r=>(t||[]).includes(`${e}:${r}`))}function VM(t){if(!Array.isArray(t))return null;let e=[...new Set(t.filter(r=>qM.has(r)))];return e.length>0?e:null}function efe(t){if(t==null)return{scopes:null};let e=`Valid scopes: ${He.API_KEY_SCOPES.join(", ")}. Use null for full access.`;if(!Array.isArray(t)||t.length===0)return{error:`scopes must be a non-empty array of API key scopes. ${e}`};let r=t.filter(n=>!qM.has(n));return r.length>0?{error:`Unknown API key scope(s): ${r.map(String).join(", ")}. ${e}`}:{scopes:VM(t)}}function tfe({scopes:t,path:e,type:r}){if(!t||t.length===0)return!0;let n=e.split("?")[0];if(Kpe.has(n))return!1;if(Xpe.has(n))return!0;let i=YM(r),o=GM(n);return o==="api"&&Zpe[n]?.some(s=>s===r)&&Yb(t,"mcp").length>0?!0:t.includes(`${o}:${i}`)}function rfe(t){return!t||t.length===0?"Full access":He.API_KEY_SURFACES.map(e=>({surface:e,actions:Yb(t,e)})).filter(e=>e.actions.length>0).map(e=>He.API_KEY_SURFACE_ACTIONS[e.surface].length===1?He.API_KEY_SURFACE_LABELS[e.surface]:`${He.API_KEY_SURFACE_LABELS[e.surface]} ${e.actions.join("/")}`).join(", ")}});var WM=m(Vb=>{"use strict";Object.defineProperty(Vb,"__esModule",{value:!0});Vb.isValidEmail=nfe;function nfe(t){return/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)*\.[a-zA-Z]{1,}$/.test(t)}});var KM=m(It=>{"use strict";Object.defineProperty(It,"__esModule",{value:!0});It.GATEWAY_UNINSTALL_COMMANDS=It.GATEWAY_API_KEY_NAME_PREFIX=It.GATEWAY_TARGET_NAME_PATTERN=It.GATEWAY_SETUP_GUIDE_URL=It.GATEWAY_DOWNLOAD_BASE_URL=It.GATEWAY_INSTALL_TOKEN_PREFIX=void 0;It.getGatewayServerUrl=ZM;It.buildGatewayInstallToken=ofe;It.buildGatewayInstallCommand=sfe;It.getGatewayApiKeyName=afe;It.GATEWAY_INSTALL_TOKEN_PREFIX="sgi1.";It.GATEWAY_DOWNLOAD_BASE_URL="https://downloads.superglue.cloud";It.GATEWAY_SETUP_GUIDE_URL="https://superglue.ai/docs/guides/secure-gateway/";It.GATEWAY_TARGET_NAME_PATTERN=/^[a-z0-9]([a-z0-9_-]{0,61}[a-z0-9])?$/;function ZM(t){let e=new URL(t);return e.protocol=e.protocol==="http:"?"ws:":"wss:",e.pathname=`${e.pathname.replace(/\/+$/,"")}/ws/tunnels`,e.search="",e.hash="",e.toString()}function ife(t){let e=new TextEncoder().encode(t),r="";for(let n of e)r+=String.fromCharCode(n);return btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function ofe(t){let e={v:1,serverUrl:ZM(t.apiEndpoint),tunnelId:t.tunnelId,apiKey:t.apiKey,targets:t.targets,enableScriptRunner:t.enableScriptRunner};return It.GATEWAY_INSTALL_TOKEN_PREFIX+ife(JSON.stringify(e))}function sfe(t,e){return t==="windows"?[`$install = { ${["$ErrorActionPreference = 'Stop'","[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072","$ProgressPreference = 'SilentlyContinue'","$gateway = Join-Path $env:TEMP 'superglue-gateway.exe'","Remove-Item $gateway -Force -ErrorAction SilentlyContinue",`Invoke-WebRequest -UseBasicParsing '${It.GATEWAY_DOWNLOAD_BASE_URL}/superglue-gateway-windows.exe' -OutFile $gateway`,`'${e}' | & $gateway install -`].join("; ")} }`,`if (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { & $install } else { Start-Process powershell -Verb RunAs -ErrorAction Stop -ArgumentList "-NoExit -Command & {$install}"; 'Continue in the administrator PowerShell window.' }`].join("; "):["d=$(mktemp -d)",`u="${It.GATEWAY_DOWNLOAD_BASE_URL}/superglue-gateway-linux-$(uname -m | sed 's/aarch64/arm64/')"`,'s=$([ "$(id -u)" -eq 0 ] || echo sudo)','{ if command -v curl >/dev/null; then curl -fsSL -o "$d/superglue-gateway" "$u"; else wget -qO "$d/superglue-gateway" "$u"; fi; }','$s install -m 0755 "$d/superglue-gateway" /usr/local/bin/superglue-gateway',`echo '${e}' | $s /usr/local/bin/superglue-gateway install -`].join(" && ")}It.GATEWAY_API_KEY_NAME_PREFIX="Gateway: ";function afe(t){return It.GATEWAY_API_KEY_NAME_PREFIX+t}It.GATEWAY_UNINSTALL_COMMANDS={windows:'& "C:\\Program Files\\superglue Gateway\\superglue-gateway.exe" uninstall',linux:"sudo /usr/local/bin/superglue-gateway uninstall"}});var vg=m(he=>{"use strict";Object.defineProperty(he,"__esModule",{value:!0});he.OAUTH_TOKEN_CREDENTIAL_KEYS=he.OAUTH_CONFIG_CREDENTIAL_KEYS=void 0;he.hasMeaningfulValue=Ct;he.stringValue=Gt;he.validateOAuthConnection=yfe;he.formatOAuthConnectionDisabledReason=Ife;he.objectValue=Yo;he.parseScopes=Hd;he.normalizeGrantType=qd;he.normalizeOAuthClientMode=Zb;he.normalizeSystemAuthentication=fr;he.resolveOAuthClientMode=bfe;he.flattenSystemAuthentication=nL;he.maskedFlatSystemAuthentication=Sfe;he.isMaskedSecretValue=iL;he.pickAgentAuthInputFields=wfe;he.maskSystemAuthenticationForResponse=Bfe;he.restoreMaskedClientSecret=_fe;he.mapAgentAuthInput=oL;he.mergeAgentAuthInput=xfe;he.getAuthenticationConfigCredentialKeys=sL;he.buildAuthenticationEditorModel=Mfe;he.getCredentialRequirements=Lfe;he.isCredentialRequirementSatisfied=aL;he.hasUnsatisfiedCredentialRequirements=Pfe;he.updateAuthenticationEditorField=$fe;he.validateOAuthAuthenticationConfigPlacement=cL;he.authenticationToLegacyCredentials=uL;he.isRuntimeCredentialMetadataKey=Ffe;he.resolveCredentialAuthentication=jfe;he.buildRuntimeCredentialsFromAuthentication=zfe;he.resolveOAuthConfigFromAuthentication=Hfe;he.toCredentialInputValue=Kb;he.getCredentialEntries=qfe;he.getCredentialInputValues=Gfe;he.getCredentialDisplayHiddenKeys=Yfe;he.hasOAuthTokenCredentials=Vfe;he.getOAuthExpiryText=Jfe;he.hasRuntimeCredentialValues=Wfe;he.validateCredentialObjectKeys=Zfe;he.validateCredentialKeyList=Kfe;he.mapOAuthMissingFieldsForAgent=Xfe;he.validateOAuthAuthenticationAndCredentialInputs=ehe;var Rt=Rn(),cfe=fu();he.OAUTH_CONFIG_CREDENTIAL_KEYS=["auth_url","authUrl","token_url","tokenUrl","token_uri","scopes","scope","grant_type","grantType","oauthClientMode","client_id","clientId","client_secret","clientSecret","tokenAuthMethod","tokenContentType","usePKCE","extraHeaders","extraBodyParams"];var _g=["host","port","database","path","homeDirectory"],rL=["type","oauthClientMode","grantType","authUrl","tokenUrl","scopes","clientId","clientSecret","tokenAuthMethod","tokenContentType","usePKCE","extraHeaders","extraBodyParams","resource","protocol",..._g],ufe=new Set(rL),lfe="type, oauthClientMode, grantType, authUrl, tokenUrl, scopes, clientId, clientSecret, tokenAuthMethod, tokenContentType, usePKCE, extraHeaders, extraBodyParams, resource, protocol, host, port, database, path, homeDirectory",dfe=["grantType","authUrl","tokenUrl","scopes","clientId","clientSecret"],Afe={grantType:["grantType","grant_type"],authUrl:["authUrl","auth_url"],tokenUrl:["tokenUrl","token_url","token_uri"],scopes:["scopes","scope"],clientId:["clientId","client_id"],clientSecret:["clientSecret","client_secret"]},zd=["tokenAuthMethod","tokenContentType","usePKCE","extraHeaders","extraBodyParams","resource"],pfe=new Set(dfe);he.OAUTH_TOKEN_CREDENTIAL_KEYS=["access_token","accessToken","refresh_token","refreshToken","expires_at","expiresAt","expires_in","expiresIn","expiry","token_type","tokenType"];var ffe=new Set(he.OAUTH_TOKEN_CREDENTIAL_KEYS),hfe=["access_token","refresh_token","api_key","bearer_token","token","client_id","client_secret","auth_url","token_url","scopes","grant_type","token_type","expires_at","expiry","expires_in","host","hostname","port","database","dbname","db","username","password"],XM=new Map(hfe.map((t,e)=>[(0,Rt.normalizeCredentialKey)(t),e]));function $a(t){return Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0))}function Jb({config:t,key:e,value:r}){let n={...t||{}};return Ct(r)?n[e]=r:delete n[e],Object.keys(n).length>0?n:void 0}function Ct(t){return(0,Rt.hasCredentialValue)(t)}function Gt(t){if(Ct(t))return typeof t=="string"?t:String(t)}var gfe={"grant_type authorization_code or client_credentials":"authorization_code or client_credentials",client_id:"client ID",token_url:"token URL",auth_url:"authorization URL","client_secret or usePKCE":"client secret or PKCE","client_secret or oauth_cert + oauth_key":"client secret or OAuth certificate and key"};function Go(...t){return t.find(e=>Ct(e))}function mfe(t){return t===!0||t==="true"}function yfe(t){let e=t||{},r=Gt(Go(e.grant_type,e.grantType)),n=r==="client_credentials"?"client_credentials":"authorization_code",i=r&&r!=="authorization_code"&&r!=="client_credentials",o=Go(e.client_id,e.clientId),s=Go(e.client_secret,e.clientSecret),a=Go(e.auth_url,e.authUrl),c=Go(e.token_url,e.tokenUrl,e.token_uri),u=Go(e.oauth_cert,e.oauthCert),l=Go(e.oauth_key,e.oauthKey),d=Ct(u)&&Ct(l)||e.hasServerSideCertificateCredentials===!0,A=e.hasServerSideClientSecret===!0,p=Ct(s)||A,h=mfe(Go(e.usePKCE,e.usePkce)),g=[];return i&&g.push("grant_type authorization_code or client_credentials"),Ct(o)||g.push("client_id"),Ct(c)||g.push("token_url"),n==="client_credentials"?!p&&!d&&g.push("client_secret or oauth_cert + oauth_key"):(Ct(a)||g.push("auth_url"),!p&&!h&&g.push("client_secret or usePKCE")),{grantType:n,hasAccessToken:Ct(Go(e.access_token,e.accessToken)),hasCertificateCredentials:d,isReadyToConnect:g.length===0,missingFields:g,usePKCE:h}}function Efe(t){return t.length<=1?t[0]||"":t.length===2?`${t[0]} and ${t[1]}`:`${t.slice(0,-1).join(", ")}, and ${t[t.length-1]}`}function Ife(t){if(!t||t.isReadyToConnect)return null;let e=t.missingFields.map(r=>gfe[r]||r);return`OAuth connection is disabled because ${Efe(e)} ${e.length===1?"is":"are"} missing.`}function Yo(t){if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function fo(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function Hd(t){if(Array.isArray(t))return t.map(String).filter(Boolean);if(Ct(t)){if(typeof t=="string"){let e=t.trim().split(/[,\s]+/).map(r=>r.trim()).filter(Boolean);return e.length>0?e:void 0}return[String(t)]}}function qd(t){let e=Gt(t);if(e==="authorization_code"||e==="client_credentials"||e==="password"||e==="service_account"||e==="custom")return e;if(e)return"custom"}function Zb(t){return t==="managed"||t==="dynamic"||t==="custom"?t:void 0}function Cfe(t){let e=Object.entries(t).filter(([r])=>!pfe.has(r));return e.length>0?Object.fromEntries(e):void 0}function Eu(t,e,r){for(let i of Afe[r])if(r==="scopes"&&Array.isArray(t[i])||Ct(t[i]))return t[i];let n=Yo(t.client);return r==="clientId"&&Ct(n?.id)?n.id:r==="clientSecret"&&Ct(n?.secret)?n.secret:e[r]}function fr(t){if(!t)return;let e=t;if(e.type==="oauth2"){let r=Yo(e.config)||{},n=Cfe(r)||{};return $a({type:"oauth2",oauthClientMode:Zb(e.oauthClientMode),grantType:qd(Eu(e,r,"grantType")),authUrl:Gt(Eu(e,r,"authUrl")),tokenUrl:Gt(Eu(e,r,"tokenUrl")),scopes:Hd(Eu(e,r,"scopes")),oauthAppId:Gt(e.oauthAppId),clientId:Gt(Eu(e,r,"clientId")),clientSecret:Gt(Eu(e,r,"clientSecret")),config:Object.keys(n).length>0?n:void 0})}return e.type==="connection_string"?$a({type:"connection_string",protocol:e.protocol,config:Yo(e.config??e.components)}):e.type==="api_key"||e.type==="basic_auth"||e.type==="none"?$a({type:e.type,config:Yo(e.config)}):{type:"none"}}function bfe({authentication:t,templateManaged:e,templateRegistrationUrl:r}){let n=fr(t);return n?.type!=="oauth2"?"custom":n.oauthAppId?.startsWith("managed:")?"managed":n.oauthClientMode?n.oauthClientMode==="managed"&&!e?"custom":n.oauthClientMode:r?"dynamic":e&&!n.clientSecret?"managed":"custom"}function nL(t){let e=fr(t);if(!e)return;let{config:r,scopes:n,oauthAppId:i,...o}=e,s={};return r&&typeof r=="object"&&Object.assign(s,r),Object.assign(s,o),Array.isArray(n)?s.scopes=n.join(" "):n!==void 0&&(s.scopes=n),s}function Wb(t,e=""){return t==null?t:Array.isArray(t)?t.map(r=>Wb(r)):typeof t=="object"?Object.fromEntries(Object.entries(t).map(([r,n])=>[r,Wb(n,r)])):e&&(0,Rt.isSensitiveCredentialKey)(e)?(0,Rt.maskCredentialValue)(e,t):t}function Sfe(t){let e=nL(t);if(e)return Wb(e)}function iL(t){return(0,Rt.isMaskedValue)(t)||(0,Rt.isFullyMaskedCredentialValue)(t)}function wfe(t){let e=Yo(t);if(!e)return;let r={};for(let n of rL){if(!fo(e,n))continue;let i=e[n];i!==void 0&&(r[n]=i)}return r}function Bfe(t){return!t||t.type!=="oauth2"||!Ct(t.clientSecret)?t:{...t,clientSecret:Rt.FULLY_MASKED_CREDENTIAL_VALUE}}function _fe({incoming:t,existing:e}){if(!t||t.type!=="oauth2"||!iL(t.clientSecret))return t;let r=e?.type==="oauth2"?e.clientSecret:void 0;return{...t,clientSecret:r}}function vfe(t){if(t==="none"||t==="api_key"||t==="basic_auth"||t==="oauth2"||t==="connection_string")return t}function Qfe(t){let e=_g.flatMap(r=>{if(!fo(t,r))return[];let n=t[r];return Ct(n)?[[r,n]]:[]});return e.length>0?Object.fromEntries(e):void 0}function Tfe(t){return _g.filter(e=>fo(t,e))}function Dfe(t){let e=_g.flatMap(r=>fo(t,r)?[[r,t[r]]]:[]);return e.length>0?Object.fromEntries(e):void 0}function Rfe(t){let e=new Set(["oauthClientMode","grantType","authUrl","tokenUrl","scopes","clientId","clientSecret",...zd]);return Object.keys(t).filter(r=>e.has(r))}function oL(t){if(t==null)return{};let e=Yo(t);if(!e)return{error:"auth must be an object."};let r=vfe(e.type);if(!r)return{error:"auth.type is required."};let n=Object.keys(e).filter(a=>!ufe.has(a));if(n.length>0)return{error:`Unknown auth field(s): ${n.join(", ")}. Accepted: ${lfe}.`};let i=Tfe(e);if(r!=="connection_string"&&i.length>0)return{error:`Connection auth field(s) require auth.type 'connection_string': ${i.join(", ")}.`};let o=Rfe(e);if(r!=="oauth2"&&o.length>0)return{error:`OAuth auth field(s) require auth.type 'oauth2': ${o.join(", ")}.`};if(r!=="oauth2"){let a=Qfe(e);return{authentication:$a({type:r,protocol:r==="connection_string"?e.protocol:void 0,config:a})}}let s={...Object.fromEntries(zd.flatMap(a=>{if(!fo(e,a))return[];let c=e[a];return Ct(c)?[[a,c]]:[]}))};return{authentication:$a({type:"oauth2",oauthClientMode:Zb(e.oauthClientMode),grantType:qd(e.grantType),authUrl:Gt(e.authUrl),tokenUrl:Gt(e.tokenUrl),scopes:Hd(e.scopes),clientId:Gt(e.clientId),clientSecret:Gt(e.clientSecret),config:Object.keys(s).length>0?s:void 0})}}function Fa(t){return t===""||t===null||t===void 0}function jd(t,e,r,n){if(fo(e,r)){if(Fa(e[r])){delete t[n];return}t[n]=Gt(e[r])}}function Nfe(t,e){if(fo(e,"scopes")){if(Fa(e.scopes)){delete t.scopes;return}t.scopes=Hd(e.scopes)}}function kfe(t,e){if(fo(e,"grantType")){if(Fa(e.grantType)){delete t.grantType;return}t.grantType=qd(e.grantType)}}function Ofe(t,e,r){if(fo(e,r)){if(Fa(e[r])){delete t[r];return}t[r]=e[r]}}function Ufe(t,e){if(Fa(e))return;let r=Yo(e);if(!r)return t;let n={...t||{}};for(let[i,o]of Object.entries(r))Fa(o)?delete n[i]:n[i]=o;return Object.keys(n).length>0?n:void 0}function xfe(t,e){let r=oL(e);if(r.error)return fr(t)||{type:"none"};let n=r.authentication||{type:"none"},i=Yo(e)||{},o=fr(t),s=o?.type===n.type;if(n.type!=="oauth2"){let d=Dfe(i),A=s&&o?{...o}:{type:n.type};return n.type==="connection_string"&&fo(i,"protocol")&&(Fa(i.protocol)?delete A.protocol:A.protocol=i.protocol),d&&(A.config=Ufe(o?.config,d)),fr(A)||{type:n.type}}let c={...s&&o?.type==="oauth2"?{...o,config:{...o.config||{}}}:{type:"oauth2",config:{}}};jd(c,i,"oauthClientMode","oauthClientMode"),kfe(c,i),jd(c,i,"authUrl","authUrl"),jd(c,i,"tokenUrl","tokenUrl"),Nfe(c,i),jd(c,i,"clientId","clientId"),jd(c,i,"clientSecret","clientSecret");let l={...c.config||{}};for(let d of zd)Ofe(l,i,d);return c.config=Object.keys(l).length>0?l:void 0,fr(c)||{type:"oauth2"}}function sL(t){let e=fr(t);if(!e)return[];let r=new Set;for(let n of Object.keys(e.config||{}))r.add(n);return e.type==="oauth2"&&(e.grantType&&(r.add("grant_type"),r.add("grantType")),e.authUrl&&(r.add("auth_url"),r.add("authUrl")),e.tokenUrl&&(r.add("token_url"),r.add("tokenUrl"),r.add("token_uri")),e.scopes&&(r.add("scopes"),r.add("scope")),e.clientId&&(r.add("client_id"),r.add("clientId")),e.clientSecret&&(r.add("client_secret"),r.add("clientSecret"))),[...r]}function eL(t,e,r){if(r)for(let[n,i]of Object.entries(r))t.push({path:`${e}.${n}`,label:n,value:i})}function Mfe({authentication:t}){let e=fr(t)||{type:"none"},r=[];if(e.type==="oauth2"){r.push({path:"oauth2.clientId",label:"clientId",value:e.clientId},{path:"oauth2.clientSecret",label:"clientSecret",value:e.clientSecret},{path:"oauth2.grantType",label:"grantType",value:e.grantType||"authorization_code"},{path:"oauth2.authUrl",label:"authUrl",value:e.authUrl},{path:"oauth2.tokenUrl",label:"tokenUrl",value:e.tokenUrl},{path:"oauth2.scopes",label:"scopes",value:e.scopes?.join(" ")});for(let n of zd)r.push({path:`oauth2.config.${n}`,label:n,value:e.config?.[n]});for(let[n,i]of Object.entries(e.config||{}))zd.includes(n)||r.push({path:`oauth2.config.${n}`,label:n,value:i})}else e.type==="connection_string"?(e.protocol&&r.push({path:"connection.protocol",label:"protocol",value:e.protocol}),eL(r,"connection.config",e.config)):eL(r,`${e.type}.config`,e.config);return{type:e.type,authentication:e,configFields:r,hiddenCredentialKeys:sL(e)}}function Lfe(t){let e=fr(t);if(!e||e.type!=="connection_string")return[];let r={type:"field",field:{key:"username",aliases:["user"]}},n={type:"field",field:{key:"password"}};switch(e.protocol){case"sftp":return[r,{type:"oneOf",fields:[{key:"password"},{key:"privateKey"}]},{type:"field",field:{key:"passphrase"},optional:!0}];case"smb":return[r,n,{type:"field",field:{key:"domain"},optional:!0}];case"sqlserver":return[{type:"field",field:{key:"user",aliases:["username"]}},n];default:return[r,n]}}function tL(t,e){return(0,Rt.hasCredentialValue)(e[t.key])?!0:(t.aliases??[]).some(r=>(0,Rt.hasCredentialValue)(e[r]))}function aL(t,e){return t.optional?!0:t.type==="field"?tL(t.field,e):t.fields.some(r=>tL(r,e))}function Pfe(t,e){let r=e||{};return t.some(n=>!aL(n,r))}function $fe({authentication:t,path:e,value:r}){let n=fr(t)||{type:"none"};if(n.type==="oauth2"){if(e==="oauth2.grantType")return{...n,grantType:qd(r)};if(e==="oauth2.authUrl")return{...n,authUrl:Gt(r)};if(e==="oauth2.tokenUrl")return{...n,tokenUrl:Gt(r)};if(e==="oauth2.scopes")return{...n,scopes:Hd(r)??[]};if(e==="oauth2.clientId")return{...n,clientId:Gt(r)};if(e==="oauth2.clientSecret")return{...n,clientSecret:Gt(r)};if(e.startsWith("oauth2.config.")){let o=e.slice(14);return{...n,config:Jb({config:n.config,key:o,value:r})}}}if(n.type==="connection_string"){if(e==="connection.protocol")return{...n,protocol:Gt(r)};if(e.startsWith("connection.config.")){let o=e.slice(18);return{...n,config:Jb({config:n.config,key:o,value:r})}}}let i=`${n.type}.config.`;if(e.startsWith(i)){let o=e.slice(i.length);return{...n,config:Jb({config:n.config,key:o,value:r})}}return n}function cL({authentication:t,credentials:e}){if(fr(t)?.type!=="oauth2"||!e||typeof e!="object"||Array.isArray(e))return null;let n=Object.keys(e).filter(i=>he.OAUTH_CONFIG_CREDENTIAL_KEYS.includes(i));return n.length===0?null:`OAuth configuration keys belong in auth, not credentials: ${n.join(", ")}. Move OAuth client ID to auth.clientId, client secret to auth.clientSecret, auth URL to auth.authUrl, token URL to auth.tokenUrl, scopes to auth.scopes, grant type to auth.grantType, and token request settings to auth fields such as tokenAuthMethod/usePKCE/extraHeaders. Runtime OAuth access and refresh tokens are created by connect OAuth authorization.`}function uL(t){let e=fr(t);return e?e.type==="oauth2"?$a({...e.config||{},grant_type:e.grantType,auth_url:e.authUrl,token_url:e.tokenUrl,scopes:e.scopes?.join(" "),client_id:e.clientId,client_secret:e.clientSecret}):e.type==="connection_string"?e.config||{}:e.config||{}:{}}function Ffe(t){return ffe.has(t.trim())}function jfe({credential:t,system:e}){return t?.authentication??e?.authentication??void 0}function zfe({authentication:t,credentials:e}){let r=uL(t);return fr(t)?.type==="oauth2"?{...e||{},...r}:{...r,...e||{}}}function Hfe({input:t,authentication:e,templateOAuth:r}){let n=fr(e),i=n?.type==="oauth2"?n:void 0,o=i?.config||{},s=t||{},a=(...c)=>c.find(u=>u!=null);return $a({grant_type:a(s.grantType,s.grant_type,i?.grantType,r?.grant_type)||"authorization_code",scopes:a(s.scopes,i?.scopes?.join(" "),r?.scopes),client_id:a(s.clientId,s.client_id,i?.clientId),client_secret:a(s.clientSecret,s.client_secret,i?.clientSecret),auth_url:a(s.authUrl,s.auth_url,i?.authUrl,r?.authUrl),token_url:a(s.tokenUrl,s.token_url,i?.tokenUrl,r?.tokenUrl),resource:a(s.resource,o.resource,r?.resource),tokenAuthMethod:a(s.tokenAuthMethod,o.tokenAuthMethod,r?.tokenAuthMethod),tokenContentType:a(s.tokenContentType,o.tokenContentType,r?.tokenContentType),usePKCE:a(s.usePKCE,o.usePKCE,r?.usePKCE),extraHeaders:a(s.extraHeaders,o.extraHeaders,r?.extraHeaders),extraBodyParams:a(s.extraBodyParams,o.extraBodyParams,r?.extraBodyParams)})}function Kb(t){if(t==null)return"";if(typeof t=="string")return t;let e=JSON.stringify(t);return e===void 0?String(t):e}function qfe(t,e={}){let r=new Set((e.hiddenKeys||[]).map(Rt.normalizeCredentialKey));return Object.entries(t).filter(([n])=>!r.has((0,Rt.normalizeCredentialKey)(n))).sort(([n],[i])=>{let o=XM.get((0,Rt.normalizeCredentialKey)(n))??Number.MAX_SAFE_INTEGER,s=XM.get((0,Rt.normalizeCredentialKey)(i))??Number.MAX_SAFE_INTEGER;if(o!==s)return o-s;let a=(0,Rt.isSensitiveCredentialKey)(n),c=(0,Rt.isSensitiveCredentialKey)(i);return a!==c?a?-1:1:n.localeCompare(i)}).map(([n,i])=>({key:n,value:Kb(i),isReservedMasked:e.maskAll||(0,Rt.isSensitiveCredentialKey)(n)}))}function Gfe(t){return Object.fromEntries(Object.entries(t).map(([e,r])=>[e,Kb(r)]))}function Yfe({hideOAuthFiles:t=!1,configKeys:e=[]}){return[...e,...t?["oauth_cert","oauth_key"]:[]]}function Vfe(t){return Ct(t.access_token)||Ct(t.refresh_token)}function Jfe(t){let e=t.expires_at??t.expiry;if(e){let n=(0,cfe.parseUTCDate)(e);if(n)return`Expires ${n.toLocaleString()}`}let r=t.expires_in;return Ct(r)?`Expires in ${r} seconds`:null}function Wfe(t){return!!(t&&typeof t=="object"&&!Array.isArray(t)&&Object.values(t).some(e=>Ct(e)))}function Zfe(t){if(!t||typeof t!="object"||Array.isArray(t))return null;let e=(0,Rt.getInvalidCredentialKeyNames)(Object.keys(t));return e.length===0?null:`${Rt.CREDENTIAL_KEY_VALIDATION_DESCRIPTION} Invalid keys: ${e.join(", ")}`}function Kfe(t){let e=(0,Rt.getInvalidCredentialKeyNames)(t);return e.length===0?null:`${Rt.CREDENTIAL_KEY_VALIDATION_DESCRIPTION} Invalid keys: ${e.join(", ")}`}function Xfe(t){let e={"grant_type authorization_code or client_credentials":"grantType authorization_code or client_credentials",client_id:"clientId",token_url:"tokenUrl",auth_url:"authUrl","client_secret or usePKCE":"clientSecret or usePKCE","client_secret or oauth_cert + oauth_key":"clientSecret or oauth_cert + oauth_key"};return t.map(r=>e[r]||r)}function ehe({authentication:t,credentials:e}){return cL({authentication:t,credentials:e})}});var TL=m(ho=>{"use strict";Object.defineProperty(ho,"__esModule",{value:!0});ho.bundles=void 0;ho.buildBundleAgentLaunch=Ahe;ho.getBundle=phe;ho.listBundles=fhe;var the="https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap",rhe="<<(p) => { const value = p['sage_intacct_entity_id']; if (!value) return ''; const escaped = String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('\"', '&quot;').replaceAll(\"'\", '&apos;'); return `<locationid>${escaped}</locationid>`; }>>",lL="<<() => crypto.randomUUID()>>";function bt(t){return`<?xml version="1.0" encoding="UTF-8"?><request><control><senderid><<sage_intacct_sender_id>></senderid><password><<sage_intacct_sender_password>></password><controlid>${lL}</controlid><uniqueid>false</uniqueid><dtdversion>3.0</dtdversion></control><operation><authentication><login><userid><<sage_intacct_user_id>></userid><companyid><<sage_intacct_company_id>></companyid><password><<sage_intacct_user_password>></password>${rhe}</login></authentication><content><function controlid="${lL}">${t}</function></content></operation></request>`}function Ts({stepId:t,objectNameExpression:e,collectionName:r,mapExpression:n,includeTotalCount:i=!1}){let o=i?"Number(data && data.TOTALCOUNT ? data.TOTALCOUNT : rows.length)":"rows.length",s=n?`rows.map(${n})`:"rows";return`(sourceData) => { const response = sourceData.${t} && sourceData.${t}.data ? sourceData.${t}.data.RESPONSE : undefined; const control = response ? response.CONTROL : undefined; const operation = response ? response.OPERATION : undefined; const authentication = operation ? operation.AUTHENTICATION : undefined; const result = operation ? operation.RESULT : undefined; const statuses = [control && control.STATUS, authentication && authentication.STATUS, result && result.STATUS].filter(Boolean).map((value) => String(value).toLowerCase()); if (statuses.includes('failure')) { const message = (result && result.ERRORMESSAGE) || (authentication && authentication.ERR ? authentication.ERR.ERRORMESSAGE : undefined) || (control && control.ERR ? control.ERR.ERRORMESSAGE : undefined); const rawErrors = message ? message.ERROR : undefined; const errors = Array.isArray(rawErrors) ? rawErrors : (rawErrors ? [rawErrors] : []); const details = errors.map((error) => [error.ERRORNO, error.DESCRIPTION2 || error.DESCRIPTION, error.CORRECTION].filter(Boolean).join(' - ')).filter(Boolean); const supportIds = errors.map((error) => error.SUPPORTID).filter(Boolean); const suffix = supportIds.length ? \` Sage support ID: \${supportIds.join(', ')}.\` : ''; throw new Error(\`Sage Intacct request failed\${details.length ? \`: \${details.join('; ')}\` : '.'}\${suffix}\`); } const data = result ? result.DATA : undefined; const objectName = ${e}; const raw = data ? data[objectName] : undefined; const rows = (Array.isArray(raw) ? raw : (raw ? [raw] : [])).slice(0, (sourceData && sourceData.maxResults) ?? ${i?"1000":"200"}); return { total: ${o}, ${r}: ${s} }; }`}var Ds=`const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&apos;');`,dL="const toIntacctDate = (value) => { const match = String(value).match(/^(\\d{4})-(\\d{2})-(\\d{2})/); if (!match) throw new Error('Dates must be in YYYY-MM-DD format.'); return match[2] + '/' + match[3] + '/' + match[1]; };",AL="const assertBalanced = (lines) => { const balance = lines.reduce((sum, line) => sum + (line.type === 'credit' ? -1 : 1) * Math.abs(Number(line.amount)), 0); if (Math.abs(balance) > 0.005) throw new Error('Journal lines must balance: debits minus credits is ' + balance.toFixed(2) + '.'); };",pL=`const lineXml = (line) => { const amount = Number(line.amount); if (!Number.isFinite(amount) || amount <= 0) throw new Error('Every journal line needs a positive amount.'); const type = line.type === 'credit' ? -1 : line.type === 'debit' ? 1 : null; if (type === null) throw new Error("Every journal line needs type 'debit' or 'credit'."); if (!line.accountNo) throw new Error('Every journal line needs accountNo.'); let xml = '<GLENTRY><ACCOUNTNO>' + esc(line.accountNo) + '</ACCOUNTNO><TR_TYPE>' + type + '</TR_TYPE><TRX_AMOUNT>' + amount + '</TRX_AMOUNT>'; if (line.department) xml += '<DEPARTMENT>' + esc(line.department) + '</DEPARTMENT>'; if (line.location) xml += '<LOCATION>' + esc(line.location) + '</LOCATION>'; if (line.memo) xml += '<DESCRIPTION>' + esc(line.memo) + '</DESCRIPTION>'; return xml + '</GLENTRY>'; };`;function Iu({stepId:t,objectName:e}){return`(sourceData) => { const response = sourceData.${t} && sourceData.${t}.data ? sourceData.${t}.data.RESPONSE : undefined; const control = response ? response.CONTROL : undefined; const operation = response ? response.OPERATION : undefined; const authentication = operation ? operation.AUTHENTICATION : undefined; const result = operation ? operation.RESULT : undefined; const statuses = [control && control.STATUS, authentication && authentication.STATUS, result && result.STATUS].filter(Boolean).map((value) => String(value).toLowerCase()); if (statuses.includes('failure')) { const message = (result && result.ERRORMESSAGE) || (authentication && authentication.ERR ? authentication.ERR.ERRORMESSAGE : undefined) || (control && control.ERR ? control.ERR.ERRORMESSAGE : undefined); const rawErrors = message ? message.ERROR : undefined; const errors = Array.isArray(rawErrors) ? rawErrors : (rawErrors ? [rawErrors] : []); const details = errors.map((error) => [error.ERRORNO, error.DESCRIPTION2 || error.DESCRIPTION, error.CORRECTION].filter(Boolean).join(' - ')).filter(Boolean); const supportIds = errors.map((error) => error.SUPPORTID).filter(Boolean); const suffix = supportIds.length ? \` Sage support ID: \${supportIds.join(', ')}.\` : ''; throw new Error(\`Sage Intacct request failed\${details.length ? \`: \${details.join('; ')}\` : '.'}\${suffix}\`); } const data = result ? result.DATA : undefined; const raw = data ? (data.${e} || data.${e.toLowerCase()}) : undefined; const record = Array.isArray(raw) ? raw[0] : raw; return { recordNo: record && record.RECORDNO ? Number(record.RECORDNO) : undefined, record }; }`}var Jd="netsuite",tS=100,Vd=1e4,Og=String.raw`<<(p) => { const url = String(p['netsuite_url'] || ''); if (!url || url.includes('{accountId}')) throw new Error('NetSuite is not connected yet: set the account ID so the system URL is https://<account>.suitetalk.api.netsuite.com/services/rest'); return url.replace(/\/+$/, ''); }>>`,Ug={Authorization:"Bearer <<netsuite_access_token>>",Accept:"application/json"},rS=String.raw`const has = (value) => value !== undefined && value !== null && value !== ''; const nsId = (value, name) => { const text = String(value ?? '').trim(); if (!/^-?\d+$/.test(text)) throw new Error(name + ' must be a NetSuite internal ID.'); return text; }; const nsDate = (value, name) => { const text = String(value ?? '').trim(); if (!/^\d{4}-\d{2}-\d{2}$/.test(text)) throw new Error(name + ' must be a date in YYYY-MM-DD format.'); return text; }; const ref = (value, name) => ({ id: nsId(value, name) });`,nhe=String.raw`const str = (value) => (value === undefined || value === null || value === '' ? null : String(value)); const num = (value) => (value === undefined || value === null || value === '' ? null : Number(value)); const bool = (value) => value === 'T' || value === true; const ids = (value) => (value === undefined || value === null || value === '' ? [] : String(value).split(',').map((part) => part.trim()).filter(Boolean)); const status = (value) => (value ? String(value).replace(/^[^:]*:\s*/, '') : null);`,fL=String.raw`const stripLinks = (value) => { if (Array.isArray(value)) return value.map(stripLinks); if (value && typeof value === 'object') { const result = {}; for (const [key, entry] of Object.entries(value)) { if (key !== 'links') result[key] = stripLinks(entry); } return result; } return value; };`,ihe={type:"integer",minimum:1,maximum:Vd,description:`Maximum number of records to return (max ${Vd}). Defaults to ${tS}. The result always reports the full match count in total, so use maxResults 1 to count. Prefer filters over large values: big results can exceed an AI client's tool output limit.`},ohe={type:"boolean",description:"Only return active records. Defaults to false (inactive records are included)."},she={type:"string",description:"Optional subsidiary internal ID to filter by."},ahe={type:"string",description:"Optional earliest transaction date as YYYY-MM-DD."},che={type:"string",description:"Optional latest transaction date as YYYY-MM-DD."},uhe={type:"object",description:"Optional extra NetSuite REST field values merged into the record body as-is, e.g. custom fields like { custentity_region: 'EMEA' } or references like { terms: { id: '2' } }. Fields that this tool's own inputs set are rejected; use those inputs instead.",properties:{},additionalProperties:!0},Gd=t=>({input:"activeOnly",kind:"flag",clause:`${t}.isinactive = 'F'`,schema:ohe}),Yd=t=>({input:"subsidiaryId",kind:"id",clause:`${t}.subsidiary = $`,schema:she}),Xb=[{input:"fromDate",kind:"date",clause:"t.trandate >= TO_DATE('$', 'YYYY-MM-DD')",schema:ahe},{input:"toDate",kind:"date",clause:"t.trandate <= TO_DATE('$', 'YYYY-MM-DD')",schema:che}];function lhe(t){let e=`p[${JSON.stringify(t.input)}]`;if(t.kind==="flag")return`if (${e} === true || ${e} === 'true') where.push(${JSON.stringify(t.clause)});`;let[r,n]=t.clause.split("$");if(t.kind==="enum")return`if (has(${e})) { const allowed = ${JSON.stringify(t.values)}; if (!allowed.includes(String(${e}))) throw new Error(${JSON.stringify(`${t.input} must be one of: ${t.values.join(", ")}.`)}); where.push(${JSON.stringify(r)} + String(${e}) + ${JSON.stringify(n)}); }`;if(t.kind==="prefix")return`if (has(${e})) { const text = String(${e}).trim(); if (!/^[A-Za-z0-9._-]{1,40}$/.test(text)) throw new Error(${JSON.stringify(`${t.input} may only contain letters, digits, dots, underscores and hyphens.`)}); where.push(${JSON.stringify(r)} + text + ${JSON.stringify(n)}); }`;let i=t.kind==="id"?"nsId":"nsDate";return`if (has(${e})) where.push(${JSON.stringify(r)} + ${i}(${e}, ${JSON.stringify(t.input)}) + ${JSON.stringify(n)});`}function Rs({id:t,name:e,shortName:r,instruction:n,stepId:i,collection:o,select:s,baseWhere:a=[],orderBy:c,filters:u=[],properties:l={},required:d=[],mapRow:A}){let p=typeof s=="string"?JSON.stringify(s):s.js,h=`<<(p) => { ${rS} const where = ${JSON.stringify(a)}; ${u.map(lhe).join(" ")} return JSON.stringify({ q: ${p} + (where.length ? ' WHERE ' + where.join(' AND ') : '') + ${JSON.stringify(` ORDER BY ${c}`)} }); }>>`;return{id:t,name:e,shortName:r,instruction:`${n} Rows are ordered by internal ID. If more than ${Vd} rows match, narrow with the filters or page with the SuiteQL query tool (ORDER BY id, WHERE id > last id).`,inputSchema:{type:"object",properties:{...l,maxResults:ihe,...Object.fromEntries(u.map(g=>[g.input,g.schema]))},...d.length>0?{required:d}:{},additionalProperties:!1},steps:[{id:i,instruction:"Run the SuiteQL query page by page.",config:{type:"request",systemId:Jd,url:`${Og}/query/v1/suiteql`,method:"POST",headers:{...Ug,"Content-Type":"application/json",Prefer:"transient"},queryParams:{limit:"1000",offset:"<<offset>>"},body:h,pagination:{type:"offsetBased",pageSize:"1000",stopCondition:`(response, pageInfo, sourceData) => { if (sourceData && ["offset", "limit", "page"].some((key) => sourceData[key] !== undefined)) throw new Error("offset, limit and page are not inputs of this tool: use maxResults and the filters."); const page = response && response.data ? response.data : {}; const merged = pageInfo && pageInfo.mergedResult && Array.isArray(pageInfo.mergedResult.items) ? pageInfo.mergedResult.items.length : 0; const max = Math.min(Math.max(Math.floor(Number(sourceData && sourceData.maxResults)) || ${tS}, 1), ${Vd}); return page.hasMore !== true || merged >= max; }`}}}],outputTransform:`(sourceData) => { ${nhe} const raw = sourceData.${i} ? sourceData.${i}.data : undefined; const pages = Array.isArray(raw) ? raw : (raw ? [raw] : []); const items = pages.flatMap((page) => (page && Array.isArray(page.items) ? page.items : [])); const last = pages.length ? pages[pages.length - 1] : {}; const max = Math.min(Math.max(Math.floor(Number(sourceData.maxResults)) || ${tS}, 1), ${Vd}); const rows = items.slice(0, max).map(${A}).map((row) => Object.fromEntries(Object.entries(row).filter((entry) => entry[1] !== null))); const total = last && last.totalResults !== undefined ? Number(last.totalResults) : items.length; return { total, returned: rows.length, hasMore: total > rows.length, ${o}: rows }; }`}}function vr({id:t,name:e,shortName:r,instruction:n,stepId:i,recordType:o,mode:s,properties:a,required:c,body:u,replaceSublist:l}){let d=[...new Set(Array.from(u.matchAll(/record\.([A-Za-z0-9_]+)\s*=/g)).map(p=>p[1]))],A=s==="create"?`/record/v1/${o}`:`/record/v1/${o}/<<(p) => { ${rS} return nsId(p.internalId, 'internalId'); }>>`;return{id:t,name:e,shortName:r,instruction:n,inputSchema:{type:"object",properties:{...s==="update"?{internalId:{type:"string",description:`Internal ID of the ${o} to update.`}}:{},...a,fields:uhe},required:s==="update"?["internalId",...c]:c,additionalProperties:!1},steps:[{id:i,instruction:`${s==="create"?"Create":"Update"} the ${o} record.`,modify:!0,config:{type:"request",systemId:Jd,url:`${Og}${A}`,method:s==="create"?"POST":"PATCH",headers:{...Ug,"Content-Type":"application/json","X-NetSuite-idempotency-key":"<<() => crypto.randomUUID()>>"},...l?{queryParams:{replace:`<<(p) => (Array.isArray(p[${JSON.stringify(l.input)}]) && p[${JSON.stringify(l.input)}].length > 0 ? ${JSON.stringify(l.sublist)} : undefined)>>`}}:{},body:`<<(p) => { ${rS} const record = {}; ${u} if (p.fields && typeof p.fields === 'object' && !Array.isArray(p.fields)) { const managed = ${JSON.stringify(d)}; const reserved = Object.keys(p.fields).filter((key) => managed.includes(key)); if (reserved.length > 0) throw new Error('fields may not set ' + reserved.join(', ') + ': use this tool\\'s own inputs for them.'); Object.assign(record, p.fields); } if (Object.keys(record).length === 0) throw new Error('Provide at least one field to ${s}.'); return JSON.stringify(record); }>>`,captureHttpResponse:!0}}],outputTransform:s==="create"?`(sourceData) => { const step = sourceData.${i} || {}; const location = step.http && step.http.headers ? String(step.http.headers.location || '') : ''; const match = location.match(/\\/record\\/v1\\/[^/]+\\/([^/?#]+)/); if (!match) throw new Error('NetSuite did not return the location of the new ${o}.'); return { id: decodeURIComponent(match[1]), recordType: '${o}' }; }`:`(sourceData) => ({ id: String(sourceData.internalId).trim(), recordType: '${o}', updated: true })`}}var hL=String.raw`const lines = Array.isArray(p.lines) ? p.lines : []; let balance = 0; const items = lines.map((line, index) => { const amount = Number(line && line.amount); if (!Number.isFinite(amount) || amount <= 0) throw new Error('lines[' + index + '].amount must be a positive number.'); if (line.type !== 'debit' && line.type !== 'credit') throw new Error("lines[" + index + "].type must be 'debit' or 'credit'."); balance += line.type === 'debit' ? amount : -amount; const item = { account: ref(line.accountId, 'lines[' + index + '].accountId') }; item[line.type] = amount; if (has(line.memo)) item.memo = String(line.memo); if (has(line.departmentId)) item.department = ref(line.departmentId, 'lines[' + index + '].departmentId'); if (has(line.classId)) item.class = ref(line.classId, 'lines[' + index + '].classId'); if (has(line.locationId)) item.location = ref(line.locationId, 'lines[' + index + '].locationId'); if (has(line.entityId)) item.entity = ref(line.entityId, 'lines[' + index + '].entityId'); return item; }); if (lines.length > 0 && Math.abs(balance) > 0.005) throw new Error('Journal lines must balance: debits minus credits is ' + balance.toFixed(2) + '.'); if (items.length > 0) record.line = { items };`,gL=String.raw`if (has(p.subsidiaryId)) record.subsidiary = ref(p.subsidiaryId, 'subsidiaryId'); if (has(p.date)) record.tranDate = nsDate(p.date, 'date'); if (has(p.memo)) record.memo = String(p.memo); if (has(p.currencyId)) record.currency = ref(p.currencyId, 'currencyId'); if (has(p.externalId)) record.externalId = String(p.externalId);`,mL={type:"object",properties:{accountId:{type:"string",description:"GL account internal ID."},type:{type:"string",enum:["debit","credit"]},amount:{type:"number",description:"Positive amount."},memo:{type:"string",description:"Optional line memo."},departmentId:{type:"string",description:"Optional department internal ID."},classId:{type:"string",description:"Optional class internal ID."},locationId:{type:"string",description:"Optional location internal ID."},entityId:{type:"string",description:"Optional customer, vendor or employee internal ID for the line."}},required:["accountId","type","amount"],additionalProperties:!1},yL=t=>({subsidiaryId:{type:"string",description:t==="create"?"Subsidiary internal ID. Required in OneWorld accounts.":"Optional new subsidiary internal ID."},date:{type:"string",description:t==="create"?"Transaction date as YYYY-MM-DD.":"Optional new transaction date as YYYY-MM-DD."},memo:{type:"string",description:"Journal entry memo."},currencyId:{type:"string",description:"Optional currency internal ID."},externalId:{type:"string",description:"Optional external ID."}}),Qg=String.raw`if (p.isPerson === true || p.isPerson === 'true') record.isPerson = true; if (p.isPerson === false || p.isPerson === 'false') record.isPerson = false; if (has(p.entityId)) record.entityId = String(p.entityId); if (has(p.companyName)) record.companyName = String(p.companyName); if (has(p.firstName)) record.firstName = String(p.firstName); if (has(p.lastName)) record.lastName = String(p.lastName); if (has(p.subsidiaryId)) record.subsidiary = ref(p.subsidiaryId, 'subsidiaryId'); if (has(p.email)) record.email = String(p.email); if (has(p.phone)) record.phone = String(p.phone); if (has(p.currencyId)) record.currency = ref(p.currencyId, 'currencyId'); if (has(p.externalId)) record.externalId = String(p.externalId); if (p.isInactive === true || p.isInactive === 'true') record.isInactive = true; if (p.isInactive === false || p.isInactive === 'false') record.isInactive = false;`;function Tg(t){return{companyName:{type:"string",description:`Company name of the ${t}.`},isPerson:{type:"boolean",description:`True when the ${t} is an individual; then set firstName and lastName.`},firstName:{type:"string",description:"First name for an individual."},lastName:{type:"string",description:"Last name for an individual."},entityId:{type:"string",description:`${t==="customer"?"Customer":"Vendor"} ID. Omit when auto-numbering assigns it.`},subsidiaryId:{type:"string",description:"Primary subsidiary internal ID. Required on create in OneWorld accounts."},email:{type:"string",description:"Email address."},phone:{type:"string",description:"Phone number."},currencyId:{type:"string",description:"Primary currency internal ID."},externalId:{type:"string",description:"Optional external ID."}}}var Dg={isInactive:{type:"boolean",description:"Set true to inactivate, false to reactivate."}},Rg=String.raw`if (Array.isArray(p.subsidiaryIds) && p.subsidiaryIds.length > 0) record.subsidiary = { items: p.subsidiaryIds.map((value, index) => ref(value, 'subsidiaryIds[' + index + ']')) }; if (p.includeChildren === true || p.includeChildren === 'true') record.includeChildren = true; if (p.includeChildren === false || p.includeChildren === 'false') record.includeChildren = false;`,vL={subsidiaryIds:{type:"array",items:{type:"string"},description:"Subsidiary internal IDs the record is available in. On update the list replaces the current subsidiaries."},includeChildren:{type:"boolean",description:"Also make the record available to child subsidiaries."}},nS=["AcctPay","AcctRec","Bank","COGS","CredCard","DeferExpense","DeferRevenue","Equity","Expense","FixedAsset","Income","LongTermLiab","NonPosting","OthAsset","OthCurrAsset","OthCurrLiab","OthExpense","OthIncome","Stat","UnbilledRec"],EL=String.raw`if (has(p.acctNumber)) record.acctNumber = String(p.acctNumber); if (has(p.acctName)) record.acctName = String(p.acctName); if (has(p.acctType)) record.acctType = { id: String(p.acctType) }; if (has(p.parentId)) record.parent = ref(p.parentId, 'parentId'); if (has(p.description)) record.description = String(p.description); if (has(p.currencyId)) record.currency = ref(p.currencyId, 'currencyId'); if (has(p.externalId)) record.externalId = String(p.externalId); if (p.isInactive === true || p.isInactive === 'true') record.isInactive = true; if (p.isInactive === false || p.isInactive === 'false') record.isInactive = false;`,IL={acctNumber:{type:"string",description:"Account number."},acctName:{type:"string",description:"Account name."},acctType:{type:"string",enum:nS,description:"NetSuite account type."},parentId:{type:"string",description:"Optional parent account internal ID."},description:{type:"string",description:"Optional description."},currencyId:{type:"string",description:"Optional currency internal ID (bank and credit card accounts)."},externalId:{type:"string",description:"Optional external ID."},...vL},CL=String.raw`if (has(p.name)) record.name = String(p.name); if (has(p.parentId)) record.parent = ref(p.parentId, 'parentId'); if (has(p.externalId)) record.externalId = String(p.externalId); if (p.isInactive === true || p.isInactive === 'true') record.isInactive = true; if (p.isInactive === false || p.isInactive === 'false') record.isInactive = false;`,bL={name:{type:"string",description:"Department name."},parentId:{type:"string",description:"Optional parent department internal ID."},externalId:{type:"string",description:"Optional external ID."},...vL},Ng=t=>String.raw`if (has(p.${t})) record.entity = ref(p.${t}, '${t}'); if (has(p.subsidiaryId)) record.subsidiary = ref(p.subsidiaryId, 'subsidiaryId'); if (has(p.date)) record.tranDate = nsDate(p.date, 'date'); if (has(p.dueDate)) record.dueDate = nsDate(p.dueDate, 'dueDate'); if (has(p.memo)) record.memo = String(p.memo); if (has(p.currencyId)) record.currency = ref(p.currencyId, 'currencyId'); if (has(p.termsId)) record.terms = ref(p.termsId, 'termsId'); if (has(p.departmentId)) record.department = ref(p.departmentId, 'departmentId'); if (has(p.classId)) record.class = ref(p.classId, 'classId'); if (has(p.locationId)) record.location = ref(p.locationId, 'locationId'); if (has(p.externalId)) record.externalId = String(p.externalId);`,kg=t=>({subsidiaryId:{type:"string",description:t==="create"?"Optional subsidiary internal ID; defaults to the entity's subsidiary.":"Optional new subsidiary internal ID."},date:{type:"string",description:t==="create"?"Transaction date as YYYY-MM-DD.":"Optional new transaction date as YYYY-MM-DD."},dueDate:{type:"string",description:"Optional due date as YYYY-MM-DD."},memo:{type:"string",description:"Optional memo."},currencyId:{type:"string",description:"Optional currency internal ID."},termsId:{type:"string",description:"Optional payment terms internal ID."},departmentId:{type:"string",description:"Optional header department internal ID."},classId:{type:"string",description:"Optional header class internal ID."},locationId:{type:"string",description:"Optional header location internal ID."},externalId:{type:"string",description:"Optional external ID."}}),QL=String.raw`if (has(line.departmentId)) item.department = ref(line.departmentId, 'lines[' + index + '].departmentId'); if (has(line.classId)) item.class = ref(line.classId, 'lines[' + index + '].classId'); if (has(line.locationId)) item.location = ref(line.locationId, 'lines[' + index + '].locationId');`,SL=String.raw`if (Array.isArray(p.lines) && p.lines.length > 0) record.item = { items: p.lines.map((line, index) => { const item = { item: ref(line && line.itemId, 'lines[' + index + '].itemId') }; if (has(line.quantity)) { const quantity = Number(line.quantity); if (!Number.isFinite(quantity)) throw new Error('lines[' + index + '].quantity must be a number.'); item.quantity = quantity; } if (has(line.rate)) { const rate = Number(line.rate); if (!Number.isFinite(rate)) throw new Error('lines[' + index + '].rate must be a number.'); item.rate = rate; } if (has(line.amount)) { const amount = Number(line.amount); if (!Number.isFinite(amount)) throw new Error('lines[' + index + '].amount must be a number.'); item.amount = amount; } if (has(line.description)) item.description = String(line.description); if (has(line.taxCodeId)) item.taxCode = ref(line.taxCodeId, 'lines[' + index + '].taxCodeId'); ${QL} return item; }) };`,wL={type:"object",properties:{itemId:{type:"string",description:"Item internal ID."},quantity:{type:"number",description:"Optional quantity. Defaults to 1."},rate:{type:"number",description:"Optional unit price; defaults to the item price."},amount:{type:"number",description:"Optional line amount."},description:{type:"string",description:"Optional line description."},taxCodeId:{type:"string",description:"Optional tax code internal ID."},departmentId:{type:"string",description:"Optional department internal ID."},classId:{type:"string",description:"Optional class internal ID. Some accounts ignore line classes on invoices; check the saved record."},locationId:{type:"string",description:"Optional location internal ID."}},required:["itemId"],additionalProperties:!1},BL=String.raw`if (Array.isArray(p.lines) && p.lines.length > 0) record.expense = { items: p.lines.map((line, index) => { const amount = Number(line && line.amount); if (!Number.isFinite(amount) || amount <= 0) throw new Error('lines[' + index + '].amount must be a positive number.'); const item = { account: ref(line.accountId, 'lines[' + index + '].accountId'), amount }; if (has(line.memo)) item.memo = String(line.memo); ${QL} return item; }) };`,_L={type:"object",properties:{accountId:{type:"string",description:"Expense account internal ID."},amount:{type:"number",description:"Positive amount."},memo:{type:"string",description:"Optional line memo."},departmentId:{type:"string",description:"Optional department internal ID."},classId:{type:"string",description:"Optional class internal ID."},locationId:{type:"string",description:"Optional location internal ID."}},required:["accountId","amount"],additionalProperties:!1},ja="Re-running this tool creates another record; it is not idempotent.",dhe=[Rs({id:"netsuite-list-accounts",name:"List NetSuite chart of accounts",shortName:"Chart of accounts",instruction:"Lists general ledger accounts (the chart of accounts) from NetSuite with number, name, type, parent and subsidiaries. Useful for validating an imported chart of accounts.",stepId:"queryAccounts",collection:"accounts",select:"SELECT a.id, a.acctnumber, a.accountsearchdisplaynamecopy AS name, a.fullname, a.accttype, a.parent, a.subsidiary, cur.symbol AS currency, a.description, a.issummary, a.isinactive FROM account a LEFT JOIN currency cur ON cur.id = a.currency",orderBy:"a.id",filters:[Gd("a"),{input:"accountType",kind:"enum",values:nS,clause:"a.accttype = '$'",schema:{type:"string",enum:nS,description:"Only accounts of this NetSuite account type, e.g. Bank or Expense."}},{input:"numberPrefix",kind:"prefix",clause:"a.acctnumber LIKE '$%'",schema:{type:"string",description:"Only accounts whose number starts with this value, e.g. 1000 or 60."}}],mapRow:"(row) => ({ id: row.id, number: str(row.acctnumber), name: str(row.name), fullName: str(row.fullname), type: str(row.accttype), parentId: str(row.parent), subsidiaryIds: ids(row.subsidiary), currency: str(row.currency), description: str(row.description), isSummary: bool(row.issummary), isInactive: bool(row.isinactive) })"}),Rs({id:"netsuite-list-customers",name:"List NetSuite customers",shortName:"Customers",instruction:"Lists customer records from NetSuite with subsidiary, currency and open balance. Useful for verifying migrated AR master data.",stepId:"queryCustomers",collection:"customers",select:"SELECT c.id, c.entityid, c.companyname, c.isperson, c.firstname, c.lastname, c.email, c.phone, c.subsidiary, BUILTIN.DF(c.subsidiary) AS subsidiaryname, cur.symbol AS currency, c.balancesearch, c.overduebalancesearch, c.isinactive, TO_CHAR(c.datecreated, 'YYYY-MM-DD') AS datecreated, TO_CHAR(c.lastmodifieddate, 'YYYY-MM-DD') AS lastmodified FROM customer c LEFT JOIN currency cur ON cur.id = c.currency",orderBy:"c.id",filters:[Gd("c"),Yd("c")],mapRow:"(row) => ({ id: row.id, entityId: str(row.entityid), companyName: str(row.companyname), isPerson: bool(row.isperson), firstName: str(row.firstname), lastName: str(row.lastname), email: str(row.email), phone: str(row.phone), subsidiaryId: str(row.subsidiary), subsidiary: str(row.subsidiaryname), currency: str(row.currency), balance: num(row.balancesearch), overdueBalance: num(row.overduebalancesearch), isInactive: bool(row.isinactive), createdOn: str(row.datecreated), modifiedOn: str(row.lastmodified) })"}),Rs({id:"netsuite-list-vendors",name:"List NetSuite vendors",shortName:"Vendors",instruction:"Lists vendor records from NetSuite with subsidiary, currency and balance. Useful for verifying migrated AP master data.",stepId:"queryVendors",collection:"vendors",select:"SELECT v.id, v.entityid, v.companyname, v.isperson, v.firstname, v.lastname, v.email, v.phone, v.subsidiary, BUILTIN.DF(v.subsidiary) AS subsidiaryname, cur.symbol AS currency, v.balance, v.isinactive, TO_CHAR(v.datecreated, 'YYYY-MM-DD') AS datecreated, TO_CHAR(v.lastmodifieddate, 'YYYY-MM-DD') AS lastmodified FROM vendor v LEFT JOIN currency cur ON cur.id = v.currency",orderBy:"v.id",filters:[Gd("v"),Yd("v")],mapRow:"(row) => ({ id: row.id, entityId: str(row.entityid), companyName: str(row.companyname), isPerson: bool(row.isperson), firstName: str(row.firstname), lastName: str(row.lastname), email: str(row.email), phone: str(row.phone), subsidiaryId: str(row.subsidiary), subsidiary: str(row.subsidiaryname), currency: str(row.currency), balance: num(row.balance), isInactive: bool(row.isinactive), createdOn: str(row.datecreated), modifiedOn: str(row.lastmodified) })"}),Rs({id:"netsuite-list-journal-entries",name:"List NetSuite journal entries",shortName:"Journal entries",instruction:"Lists journal entry lines from NetSuite, one row per GL line and accounting book with journal, date, period, account, debit, credit and dimensions. Useful for verifying opening balances and postings at cutover.",stepId:"queryJournalLines",collection:"journalLines",select:"SELECT t.id AS journalid, t.tranid, TO_CHAR(t.trandate, 'YYYY-MM-DD') AS trandate, BUILTIN.DF(t.postingperiod) AS period, t.subsidiary, BUILTIN.DF(t.status) AS status, t.posting, t.memo AS journalmemo, cur.symbol AS currency, tl.id AS lineid, tal.accountingbook, tal.account, a.acctnumber, a.accountsearchdisplaynamecopy AS accountname, tal.debit, tal.credit, tl.memo, tl.department, tl.class, tl.location, tl.entity FROM transaction t JOIN transactionline tl ON tl.transaction = t.id JOIN transactionaccountingline tal ON tal.transaction = tl.transaction AND tal.transactionline = tl.id JOIN account a ON a.id = tal.account LEFT JOIN currency cur ON cur.id = t.currency",baseWhere:["t.type = 'Journal'"],orderBy:"t.id, tl.id, tal.accountingbook",filters:[...Xb,Yd("t")],mapRow:"(row) => ({ journalId: row.journalid, tranId: str(row.tranid), date: str(row.trandate), period: str(row.period), subsidiaryId: str(row.subsidiary), status: status(row.status), posting: bool(row.posting), journalMemo: str(row.journalmemo), currency: str(row.currency), line: num(row.lineid), accountingBookId: str(row.accountingbook), accountId: str(row.account), accountNumber: str(row.acctnumber), accountName: str(row.accountname), debit: num(row.debit), credit: num(row.credit), memo: str(row.memo), departmentId: str(row.department), classId: str(row.class), locationId: str(row.location), entityId: str(row.entity) })"}),Rs({id:"netsuite-list-invoices",name:"List NetSuite invoices",shortName:"Invoices",instruction:"Lists customer invoices from NetSuite with customer, dates, status, total and amount due. Useful for verifying migrated open AR at go-live.",stepId:"queryInvoices",collection:"invoices",select:"SELECT t.id, t.tranid, t.entity, BUILTIN.DF(t.entity) AS customername, TO_CHAR(t.trandate, 'YYYY-MM-DD') AS trandate, TO_CHAR(t.duedate, 'YYYY-MM-DD') AS duedate, BUILTIN.DF(t.status) AS status, cur.symbol AS currency, t.foreigntotal, t.foreignamountunpaid, t.subsidiary, t.memo FROM transaction t LEFT JOIN currency cur ON cur.id = t.currency",baseWhere:["t.type = 'CustInvc'"],orderBy:"t.id",filters:[...Xb,Yd("t"),{input:"openOnly",kind:"flag",clause:"t.status = 'A'",schema:{type:"boolean",description:"Only return open (unpaid) invoices."}}],mapRow:"(row) => ({ id: row.id, tranId: str(row.tranid), customerId: str(row.entity), customer: str(row.customername), date: str(row.trandate), dueDate: str(row.duedate), status: status(row.status), currency: str(row.currency), total: num(row.foreigntotal), amountDue: num(row.foreignamountunpaid), subsidiaryId: str(row.subsidiary), memo: str(row.memo) })"}),Rs({id:"netsuite-list-vendor-bills",name:"List NetSuite vendor bills",shortName:"Vendor bills",instruction:"Lists vendor bills from NetSuite with vendor, dates, status, approval status, total and amount due. Useful for verifying migrated open AP at go-live.",stepId:"queryBills",collection:"bills",select:"SELECT t.id, t.tranid, t.entity, BUILTIN.DF(t.entity) AS vendorname, TO_CHAR(t.trandate, 'YYYY-MM-DD') AS trandate, TO_CHAR(t.duedate, 'YYYY-MM-DD') AS duedate, BUILTIN.DF(t.status) AS status, BUILTIN.DF(t.approvalstatus) AS approvalstatus, cur.symbol AS currency, t.foreigntotal, t.foreignamountunpaid, t.subsidiary, t.memo FROM transaction t LEFT JOIN currency cur ON cur.id = t.currency",baseWhere:["t.type = 'VendBill'"],orderBy:"t.id",filters:[...Xb,Yd("t"),{input:"openOnly",kind:"flag",clause:"t.status = 'A'",schema:{type:"boolean",description:"Only return open bills (approved and not fully paid)."}}],mapRow:"(row) => ({ id: row.id, referenceNo: str(row.tranid), vendorId: str(row.entity), vendor: str(row.vendorname), date: str(row.trandate), dueDate: str(row.duedate), status: status(row.status), approvalStatus: str(row.approvalstatus), currency: str(row.currency), total: row.foreigntotal === undefined ? null : Math.abs(Number(row.foreigntotal)), amountDue: num(row.foreignamountunpaid), subsidiaryId: str(row.subsidiary), memo: str(row.memo) })"}),Rs({id:"netsuite-list-dimensions",name:"List NetSuite departments, classes or locations",shortName:"Departments, classes, locations",instruction:"Lists department, class or location records from NetSuite with hierarchy and subsidiaries. Useful for validating the dimension setup after an implementation and for finding the internal IDs the write tools need.",stepId:"queryDimensions",collection:"records",properties:{dimension:{type:"string",enum:["department","class","location"],description:"Which dimension to list."}},required:["dimension"],select:{js:String.raw`'SELECT d.id, d.name, d.fullname, d.parent, d.subsidiary, d.includechildren, d.isinactive FROM ' + (() => { const table = { department: 'department', class: 'classification', location: 'location' }[String(p.dimension || '')]; if (!table) throw new Error("dimension must be 'department', 'class' or 'location'."); return table; })() + ' d'`},orderBy:"d.id",filters:[Gd("d")],mapRow:"(row) => ({ id: row.id, name: str(row.name), fullName: str(row.fullname), parentId: str(row.parent), subsidiaryIds: ids(row.subsidiary), includeChildren: bool(row.includechildren), isInactive: bool(row.isinactive) })"}),Rs({id:"netsuite-list-subsidiaries",name:"List NetSuite subsidiaries",shortName:"Subsidiaries",instruction:"Lists subsidiaries from NetSuite with hierarchy, country, base currency and elimination flag. Most create tools need a subsidiary ID from this list in OneWorld accounts.",stepId:"querySubsidiaries",collection:"subsidiaries",select:"SELECT s.id, s.name, s.fullname, s.parent, s.country, cur.symbol AS currency, s.iselimination, s.isinactive FROM subsidiary s LEFT JOIN currency cur ON cur.id = s.currency",orderBy:"s.id",filters:[Gd("s")],mapRow:"(row) => ({ id: row.id, name: str(row.name), fullName: str(row.fullname), parentId: str(row.parent), country: str(row.country), currency: str(row.currency), isElimination: bool(row.iselimination), isInactive: bool(row.isinactive) })"}),{id:"netsuite-suiteql-query",name:"Run a NetSuite SuiteQL query",shortName:"SuiteQL query",instruction:"Runs a read-only SuiteQL SELECT query against NetSuite, for any record type, join or aggregate outside the prebuilt lists (for example items, employees, transaction lines or custom records). The workhorse tool for migration validation. Returns up to 1000 rows in one call with the total row count and hasMore; values are strings as NetSuite returns them.",inputSchema:{type:"object",properties:{query:{type:"string",description:`SuiteQL SELECT statement, e.g. "SELECT id, itemid, displayname FROM item WHERE isinactive = 'F' ORDER BY id". Dates come back in the user's date format; use TO_CHAR(field, 'YYYY-MM-DD') for ISO dates and BUILTIN.DF(field) for display names. For more than 1000 rows, page by key: ORDER BY id and add WHERE id > <last id>. Common columns: account (id, acctnumber, accountsearchdisplaynamecopy as the name, fullname, accttype, isinactive; there is no acctname column), customer (id, entityid, companyname, email, subsidiary, balancesearch, isinactive), vendor (id, entityid, companyname, email, subsidiary, balance, isinactive), transaction (id, tranid, type, trandate, entity, status, foreigntotal, foreignamountunpaid, subsidiary). Alias tables and qualify columns: FROM transaction t ... t.subsidiary works, an unqualified subsidiary fails.`},maxResults:{type:"integer",minimum:1,maximum:1e3,description:"Maximum number of rows to return (max 1000). Defaults to 100."}},required:["query"],additionalProperties:!1},steps:[{id:"runSuiteQl",instruction:"Run the SuiteQL query.",config:{type:"request",systemId:Jd,url:`${Og}/query/v1/suiteql`,method:"POST",headers:{...Ug,"Content-Type":"application/json",Prefer:"transient"},queryParams:{limit:"<<(p) => Math.min(Math.max(Math.floor(Number(p.maxResults)) || 100, 2), 1000)>>",offset:"0"},body:String.raw`<<(p) => { const query = String(p.query || '').trim(); if (!/^(select|with)\b/i.test(query)) throw new Error('query must be a SuiteQL SELECT statement.'); return JSON.stringify({ q: query }); }>>`}}],outputTransform:`(sourceData) => { ${fL} const data = sourceData.runSuiteQl && sourceData.runSuiteQl.data ? sourceData.runSuiteQl.data : {}; const items = Array.isArray(data.items) ? data.items : []; const max = Math.min(Math.max(Math.floor(Number(sourceData.maxResults)) || 100, 1), 1000); const records = stripLinks(items.slice(0, max)); const total = data.totalResults !== undefined ? Number(data.totalResults) : items.length; return { total, returned: records.length, hasMore: total > records.length, records }; }`},{id:"netsuite-get-record",name:"Get a NetSuite record",shortName:"Get record",instruction:"Fetches one NetSuite record of any type by internal ID or external ID through the REST record API, including its sublists such as transaction lines. Useful for inspecting a record in full before or after a write.",inputSchema:{type:"object",properties:{recordType:{type:"string",description:'REST record type, e.g. "customer", "vendor", "invoice", "vendorbill", "journalentry", "account", "department" or a custom record like "customrecord_x".'},internalId:{type:"string",description:"Internal ID of the record."},externalId:{type:"string",description:"External ID of the record, used when internalId is not set."},expandSubResources:{type:"boolean",description:"Include sublists and subrecords inline. Defaults to true."}},required:["recordType"],additionalProperties:!1},steps:[{id:"getRecord",instruction:"Fetch the record from the REST record API.",config:{type:"request",systemId:Jd,url:`${Og}/record/v1/<<(p) => { const type = String(p.recordType || '').trim().toLowerCase(); if (!/^[a-z][a-z0-9_]*$/.test(type)) throw new Error('recordType must contain only letters, numbers and underscores.'); return type; }>>/<<(p) => { if (p.internalId !== undefined && p.internalId !== null && p.internalId !== '') { const id = String(p.internalId).trim(); if (!/^-?\\d+$/.test(id)) throw new Error('internalId must be a NetSuite internal ID.'); return id; } if (p.externalId !== undefined && p.externalId !== null && p.externalId !== '') return 'eid:' + encodeURIComponent(String(p.externalId)); throw new Error('Provide internalId or externalId.'); }>>`,method:"GET",headers:Ug,queryParams:{expandSubResources:"<<(p) => (p.expandSubResources === false || p.expandSubResources === 'false' ? 'false' : 'true')>>"}}}],outputTransform:`(sourceData) => { ${fL} const record = sourceData.getRecord ? sourceData.getRecord.data : undefined; if (!record || typeof record !== 'object') throw new Error('NetSuite returned no record.'); return { record: stripLinks(record) }; }`},vr({id:"netsuite-create-journal-entry",name:"Create NetSuite journal entry",shortName:"Create journal entry",instruction:`Creates a journal entry in NetSuite through the REST record API. Debit and credit lines must balance. Returns the new internal ID. ${ja}`,stepId:"createJournalEntry",recordType:"journalentry",mode:"create",properties:{...yL("create"),lines:{type:"array",description:"Journal lines. Debit and credit totals must balance.",items:mL}},required:["date","lines"],body:`${gL} if (!Array.isArray(p.lines) || p.lines.length < 2) throw new Error('lines must contain at least two journal lines.'); ${hL}`}),vr({id:"netsuite-update-journal-entry",name:"Update NetSuite journal entry",shortName:"Update journal entry",instruction:"Updates an existing NetSuite journal entry by internal ID. Only the provided fields change. When lines are provided they replace all existing lines and must balance. Entries in closed periods refuse updates.",stepId:"updateJournalEntry",recordType:"journalentry",mode:"update",properties:{...yL("update"),lines:{type:"array",description:"Optional replacement lines. When set, they replace every existing line and must balance.",items:mL}},required:[],body:`${gL} if (Array.isArray(p.lines) && p.lines.length < 2) throw new Error('lines must contain at least two journal lines; omit lines to keep the current ones.'); ${hL}`,replaceSublist:{input:"lines",sublist:"line"}}),vr({id:"netsuite-create-vendor",name:"Create NetSuite vendor",shortName:"Create vendor",instruction:`Creates a vendor record in NetSuite. OneWorld accounts need a subsidiaryId. Omit entityId when auto-numbering assigns it. ${ja}`,stepId:"createVendor",recordType:"vendor",mode:"create",properties:Tg("vendor"),required:[],body:`if (!has(p.companyName) && !((p.isPerson === true || p.isPerson === 'true') && has(p.lastName))) throw new Error('Provide companyName, or isPerson with lastName.'); ${Qg}`}),vr({id:"netsuite-update-vendor",name:"Update NetSuite vendor",shortName:"Update vendor",instruction:"Updates an existing NetSuite vendor by internal ID. Only the provided fields change; set isInactive to inactivate or reactivate it.",stepId:"updateVendor",recordType:"vendor",mode:"update",properties:{...Tg("vendor"),...Dg},required:[],body:Qg}),vr({id:"netsuite-create-customer",name:"Create NetSuite customer",shortName:"Create customer",instruction:`Creates a customer record in NetSuite. OneWorld accounts need a subsidiaryId. Omit entityId when auto-numbering assigns it. ${ja}`,stepId:"createCustomer",recordType:"customer",mode:"create",properties:Tg("customer"),required:[],body:`if (!has(p.companyName) && !((p.isPerson === true || p.isPerson === 'true') && has(p.lastName))) throw new Error('Provide companyName, or isPerson with lastName.'); ${Qg}`}),vr({id:"netsuite-update-customer",name:"Update NetSuite customer",shortName:"Update customer",instruction:"Updates an existing NetSuite customer by internal ID. Only the provided fields change; set isInactive to inactivate or reactivate it.",stepId:"updateCustomer",recordType:"customer",mode:"update",properties:{...Tg("customer"),...Dg},required:[],body:Qg}),vr({id:"netsuite-create-account",name:"Create NetSuite GL account",shortName:"Create GL account",instruction:`Creates a general ledger account in NetSuite's chart of accounts. ${ja}`,stepId:"createAccount",recordType:"account",mode:"create",properties:IL,required:["acctName","acctType"],body:`if (!has(p.acctName) || !has(p.acctType)) throw new Error('acctName and acctType are required.'); ${EL} ${Rg}`}),vr({id:"netsuite-update-account",name:"Update NetSuite GL account",shortName:"Update GL account",instruction:"Updates an existing NetSuite GL account by internal ID. Only the provided fields change; set isInactive to inactivate or reactivate it. Accounts with transactions may refuse a type change.",stepId:"updateAccount",recordType:"account",mode:"update",properties:{...IL,...Dg},required:[],body:`${EL} ${Rg}`}),vr({id:"netsuite-create-invoice",name:"Create NetSuite invoice",shortName:"Create invoice",instruction:`Creates a customer invoice in NetSuite with item lines. Item, tax and posting rules of the account apply. ${ja}`,stepId:"createInvoice",recordType:"invoice",mode:"create",properties:{customerId:{type:"string",description:"Customer internal ID."},...kg("create"),lines:{type:"array",description:"Item lines.",items:wL}},required:["customerId","lines"],body:`if (!Array.isArray(p.lines) || p.lines.length === 0) throw new Error('lines must contain at least one item line.'); ${Ng("customerId")} ${SL}`}),vr({id:"netsuite-update-invoice",name:"Update NetSuite invoice",shortName:"Update invoice",instruction:"Updates an existing NetSuite invoice by internal ID. Only the provided fields change. When lines are provided they replace all existing item lines. Paid invoices and closed periods may refuse updates.",stepId:"updateInvoice",recordType:"invoice",mode:"update",properties:{customerId:{type:"string",description:"Optional new customer internal ID."},...kg("update"),lines:{type:"array",description:"Optional replacement item lines; they replace every existing item line.",items:wL}},required:[],body:`if (Array.isArray(p.lines) && p.lines.length === 0) throw new Error('lines must contain at least one item line; omit lines to keep the current ones.'); ${Ng("customerId")} ${SL}`,replaceSublist:{input:"lines",sublist:"item"}}),vr({id:"netsuite-create-vendor-bill",name:"Create NetSuite vendor bill",shortName:"Create vendor bill",instruction:`Creates a vendor bill in NetSuite with expense lines. Approval routing of the account applies. ${ja}`,stepId:"createVendorBill",recordType:"vendorbill",mode:"create",properties:{vendorId:{type:"string",description:"Vendor internal ID."},referenceNo:{type:"string",description:"Optional vendor invoice reference number."},...kg("create"),lines:{type:"array",description:"Expense lines.",items:_L}},required:["vendorId","lines"],body:`if (!Array.isArray(p.lines) || p.lines.length === 0) throw new Error('lines must contain at least one expense line.'); ${Ng("vendorId")} if (has(p.referenceNo)) record.tranId = String(p.referenceNo); ${BL}`}),vr({id:"netsuite-update-vendor-bill",name:"Update NetSuite vendor bill",shortName:"Update vendor bill",instruction:"Updates an existing NetSuite vendor bill by internal ID. Only the provided fields change. When lines are provided they replace all existing expense lines. Paid bills and closed periods may refuse updates.",stepId:"updateVendorBill",recordType:"vendorbill",mode:"update",properties:{vendorId:{type:"string",description:"Optional new vendor internal ID."},referenceNo:{type:"string",description:"Optional vendor invoice reference number."},...kg("update"),lines:{type:"array",description:"Optional replacement expense lines; they replace every existing expense line.",items:_L}},required:[],body:`if (Array.isArray(p.lines) && p.lines.length === 0) throw new Error('lines must contain at least one expense line; omit lines to keep the current ones.'); ${Ng("vendorId")} if (has(p.referenceNo)) record.tranId = String(p.referenceNo); ${BL}`,replaceSublist:{input:"lines",sublist:"expense"}}),vr({id:"netsuite-create-department",name:"Create NetSuite department",shortName:"Create department",instruction:`Creates a department in NetSuite. Without subsidiaryIds NetSuite assigns the parent subsidiary. ${ja}`,stepId:"createDepartment",recordType:"department",mode:"create",properties:bL,required:["name"],body:`if (!has(p.name)) throw new Error('name is required.'); ${CL} ${Rg}`}),vr({id:"netsuite-update-department",name:"Update NetSuite department",shortName:"Update department",instruction:"Updates an existing NetSuite department by internal ID. Only the provided fields change; set isInactive to inactivate or reactivate it.",stepId:"updateDepartment",recordType:"department",mode:"update",properties:{...bL,...Dg},required:[],body:`${CL} ${Rg}`})],eS={sap_s4hana:{bundleId:"sap_s4hana",templateId:"sap_s4hana",systemId:"sap_s4hana",displayName:"SAP S/4HANA",description:"Read business partners, sales orders, products and purchase orders from SAP.",systemUrl:the,credentialHint:"Works instantly with SAP's demo data. Add your own key later for your live system.",requiredCredentialKeys:["api_key"],demoCredentials:{api_key:"K8reTgiKCCaqvAPWC4cOjqqiLdLE8dqz"},mcpServer:{name:"sap",displayName:"SAP S/4HANA",description:"Business partners, sales orders, products and purchase orders from SAP."},installMcpServer:!0,agentLaunch:{userPrompt:"I just installed the SAP S/4HANA bundle. What can I do with it?",nextSteps:"Your first reply must be short: SAP is connected to free demo data and works right now, so offer to run one tool immediately as proof. No credential collection is needed to start. If they want their own data: their own free key comes from https://api.sap.com (SAP Business Accelerator Hub), collected and saved directly with a connect field, never via the Connections page; the system URL can then be switched to their own SAP host. Do not list the installed tools, do not add tips or explain SAP concepts unless asked."},tools:[{id:"sap-list-business-partners",name:"List SAP business partners",shortName:"Business partners",instruction:"Lists business partners (customers, suppliers, contacts) from SAP S/4HANA. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "BusinessPartnerCategory eq '2'" for organizations.`},maxResults:{type:"integer",description:"Maximum number of business partners to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchBusinessPartners",instruction:"Fetch business partners, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_BUSINESS_PARTNER/A_BusinessPartner",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:"<<filter>>",$select:"BusinessPartner,BusinessPartnerFullName,BusinessPartnerCategory,BusinessPartnerGrouping,CreationDate"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const d = (v) => { if (typeof v !== 'string' || !v.startsWith('/Date(')) return v; const n = parseInt(v.slice(6), 10); return Number.isFinite(n) ? new Date(n).toISOString().slice(0, 10) : v; }; const rows = (sourceData.fetchBusinessPartners?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, businessPartners: rows.map((r) => ({ id: r.BusinessPartner, name: r.BusinessPartnerFullName, category: r.BusinessPartnerCategory, grouping: r.BusinessPartnerGrouping, createdOn: d(r.CreationDate) })) }; }"},{id:"sap-list-sales-orders",name:"List SAP sales orders",shortName:"Sales orders",instruction:"Lists sales orders from SAP S/4HANA with their net amount, currency and sold-to party. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "SalesOrderType eq 'OR'" or "TotalNetAmount gt 1000".`},maxResults:{type:"integer",description:"Maximum number of sales orders to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchSalesOrders",instruction:"Fetch sales orders, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_SALES_ORDER_SRV/A_SalesOrder",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:"<<filter>>",$select:"SalesOrder,SalesOrderType,SoldToParty,TotalNetAmount,TransactionCurrency,SalesOrderDate,OverallSDProcessStatus"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const d = (v) => { if (typeof v !== 'string' || !v.startsWith('/Date(')) return v; const n = parseInt(v.slice(6), 10); return Number.isFinite(n) ? new Date(n).toISOString().slice(0, 10) : v; }; const rows = (sourceData.fetchSalesOrders?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, salesOrders: rows.map((r) => ({ id: r.SalesOrder, type: r.SalesOrderType, soldToParty: r.SoldToParty, netAmount: Number(r.TotalNetAmount), currency: r.TransactionCurrency, orderDate: d(r.SalesOrderDate), status: r.OverallSDProcessStatus })) }; }"},{id:"sap-list-products",name:"List SAP products",shortName:"Products",instruction:"Lists products (materials) from SAP S/4HANA with their type, group and base unit. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "ProductType eq 'FERT'" for finished goods.`},maxResults:{type:"integer",description:"Maximum number of products to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchProducts",instruction:"Fetch products, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_PRODUCT_SRV/A_Product",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:"<<filter>>",$expand:"to_Description",$select:"Product,ProductType,ProductGroup,BaseUnit,GrossWeight,WeightUnit,CreationDate,to_Description/Language,to_Description/ProductDescription"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const d = (v) => { if (typeof v !== 'string' || !v.startsWith('/Date(')) return v; const n = parseInt(v.slice(6), 10); return Number.isFinite(n) ? new Date(n).toISOString().slice(0, 10) : v; }; const nameOf = (r) => { const list = r.to_Description?.results ?? []; const hit = list.find((x) => x.Language === 'EN') ?? list[0]; return hit?.ProductDescription; }; const rows = (sourceData.fetchProducts?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, products: rows.map((r) => ({ id: r.Product, name: nameOf(r), type: r.ProductType, group: r.ProductGroup, baseUnit: r.BaseUnit, grossWeight: Number(r.GrossWeight), weightUnit: r.WeightUnit, createdOn: d(r.CreationDate) })) }; }"},{id:"sap-list-purchase-orders",name:"List SAP purchase orders",shortName:"Purchase orders",instruction:"Lists purchase orders from SAP S/4HANA with their supplier, currency and creation date. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "PurchaseOrderType eq 'NB'" for standard orders.`},maxResults:{type:"integer",description:"Maximum number of purchase orders to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchPurchaseOrders",instruction:"Fetch purchase orders, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_PURCHASEORDER_PROCESS_SRV/A_PurchaseOrder",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:"<<filter>>",$select:"PurchaseOrder,PurchaseOrderType,Supplier,PurchaseOrderDate,DocumentCurrency,CreatedByUser"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const d = (v) => { if (typeof v !== 'string' || !v.startsWith('/Date(')) return v; const n = parseInt(v.slice(6), 10); return Number.isFinite(n) ? new Date(n).toISOString().slice(0, 10) : v; }; const rows = (sourceData.fetchPurchaseOrders?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, purchaseOrders: rows.map((r) => ({ id: r.PurchaseOrder, type: r.PurchaseOrderType, supplier: r.Supplier, orderDate: d(r.PurchaseOrderDate), currency: r.DocumentCurrency, createdBy: r.CreatedByUser })) }; }"},{id:"sap-list-gl-accounts",name:"List SAP chart of accounts",shortName:"Chart of accounts",instruction:"Lists general ledger accounts (the chart of accounts) from SAP S/4HANA. Supports an optional OData $filter, e.g. by ChartOfAccounts.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "ChartOfAccounts eq 'YCOA'" or "GLAccountType eq 'X'".`},maxResults:{type:"integer",description:"Maximum number of accounts to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchGLAccounts",instruction:"Fetch GL accounts, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_GLACCOUNTINCHARTOFACCOUNTS_SRV/A_GLAccountInChartOfAccounts",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:`<<(p) => p.filter ? "ChartOfAccounts ne '' and (" + p.filter + ")" : "ChartOfAccounts ne ''">>`,$expand:"to_Text",$select:"GLAccount,ChartOfAccounts,GLAccountType,GLAccountGroup,IsBalanceSheetAccount,AccountIsBlockedForPosting,to_Text/Language,to_Text/GLAccountName"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const nameOf = (r) => { const list = r.to_Text?.results ?? []; const hit = list.find((x) => x.Language === 'EN') ?? list[0]; return hit?.GLAccountName; }; const rows = (sourceData.fetchGLAccounts?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, accounts: rows.map((r) => ({ account: r.GLAccount, name: nameOf(r), chartOfAccounts: r.ChartOfAccounts, type: r.GLAccountType, group: r.GLAccountGroup, isBalanceSheet: r.IsBalanceSheetAccount, blockedForPosting: r.AccountIsBlockedForPosting })) }; }"},{id:"sap-list-billing-documents",name:"List SAP billing documents",shortName:"Billing documents",instruction:"Lists billing documents (invoices, credit memos) from SAP S/4HANA with amount, currency and sold-to party. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "BillingDocumentType eq 'F2'" or "TotalNetAmount gt 1000".`},maxResults:{type:"integer",description:"Maximum number of billing documents to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchBillingDocuments",instruction:"Fetch billing documents, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_BILLING_DOCUMENT_SRV/A_BillingDocument",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:"<<filter>>",$select:"BillingDocument,BillingDocumentType,SoldToParty,TotalNetAmount,TransactionCurrency,BillingDocumentDate"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const d = (v) => { if (typeof v !== 'string' || !v.startsWith('/Date(')) return v; const n = parseInt(v.slice(6), 10); return Number.isFinite(n) ? new Date(n).toISOString().slice(0, 10) : v; }; const rows = (sourceData.fetchBillingDocuments?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, billingDocuments: rows.map((r) => ({ id: r.BillingDocument, type: r.BillingDocumentType, soldToParty: r.SoldToParty, netAmount: Number(r.TotalNetAmount), currency: r.TransactionCurrency, date: d(r.BillingDocumentDate) })) }; }"},{id:"sap-list-journal-entry-items",name:"List SAP journal entry line items",shortName:"Journal entries",instruction:"Lists journal entry line items (accounting document items) from SAP S/4HANA with company code, GL account, amount and posting date. Filter by CompanyCode, FiscalYear or PostingDate to keep results focused. Useful for verifying opening balances at cutover.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "CompanyCode eq '1010' and FiscalYear eq '2026'".`},maxResults:{type:"integer",description:"Maximum number of line items to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"fetchJournalItems",instruction:"Fetch accounting document line items, paging through results with $skip.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/API_OPLACCTGDOCITEMCUBE_SRV/A_OperationalAcctgDocItemCube",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$top:"<<pageSize>>",$skip:"<<offset>>",$filter:"<<filter>>",$select:"AccountingDocument,CompanyCode,FiscalYear,GLAccount,AmountInCompanyCodeCurrency,PostingDate"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const d = (v) => { if (typeof v !== 'string' || !v.startsWith('/Date(')) return v; const n = parseInt(v.slice(6), 10); return Number.isFinite(n) ? new Date(n).toISOString().slice(0, 10) : v; }; const rows = (sourceData.fetchJournalItems?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 200); return { total: rows.length, journalItems: rows.map((r) => ({ document: r.AccountingDocument, companyCode: r.CompanyCode, fiscalYear: r.FiscalYear, account: r.GLAccount, amount: Number(r.AmountInCompanyCodeCurrency), postingDate: d(r.PostingDate) })) }; }"},{id:"sap-query-odata",name:"Query any SAP OData service",shortName:"Query any service",instruction:"Queries any SAP S/4HANA OData service and entity set (for example API_PRODUCT_SRV/A_ProductDescription or API_SALES_ORDER_SRV/A_SalesOrderItem) with optional $select and $filter. The workhorse tool for data checks beyond the prebuilt lists.",inputSchema:{type:"object",properties:{servicePath:{type:"string",description:'Service and entity set in SERVICE/EntitySet form, e.g. "API_SALES_ORDER_SRV/A_SalesOrderItem".'},select:{type:"string",description:"Comma-separated OData $select field list. Omit for all fields."},filter:{type:"string",description:"Optional OData $filter expression."},maxResults:{type:"integer",description:"Maximum number of records to return. Defaults to 100."}},required:["servicePath"],additionalProperties:!0},steps:[{id:"queryService",instruction:"Query the requested OData service and entity set.",config:{type:"request",systemId:"sap_s4hana",url:"<<sap_s4hana_url>>/<<servicePath>>",method:"GET",headers:{APIKey:"<<sap_s4hana_api_key>>",Accept:"application/json"},queryParams:{$format:"json",$select:"<<select>>",$filter:"<<filter>>",$top:"<<pageSize>>",$skip:"<<offset>>"},pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const rows = response?.data?.d?.results ?? []; const fetched = pageInfo?.mergedResult?.d?.results?.length ?? 0; const max = sourceData?.maxResults ?? 100; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:"(sourceData) => { const rows = (sourceData.queryService?.data?.d?.results ?? []).slice(0, sourceData.maxResults ?? 100); return { total: rows.length, records: rows.map((r) => { const { __metadata, ...rest } = r; return rest; }) }; }"}]},sage100:{bundleId:"sage100",templateId:"sage100",systemId:"sage100",displayName:"Sage 100",description:"Connect on-premises Sage 100 through the superglue Secure Gateway, with a guided setup playbook and a connection test against the Business Object Interface.",systemUrl:"script://runner/vbs32",credentialHint:"Your assistant first helps you connect a Secure Gateway on your Sage 100 server, then collects your Sage company and user details.",requiredCredentialKeys:["sage_home","sage_company","sage_user","sage_password"],mcpServer:{name:"sage-100",displayName:"Sage 100",description:"Sage 100 Business Object Interface access through the Secure Gateway."},installMcpServer:!1,playbook:{id:"sage100-native-integration",name:"Sage 100 Native Integration (BOI)",whenToRun:"Use when connecting a Sage 100 installation to superglue, testing that connection, or building tools that read or write Sage 100 data through the Business Object Interface.",inputs:"A Sage 100 installation on a Windows machine the user can access; a superglue API key for the gateway; the Sage company code, a Sage user with module access, and the path to the MAS90\\Home directory; the business outcome once connected.",instructions:"First check /org/tunnels for a connected gateway with a runner target. If none is connected, guide the user step by step: download the Windows gateway from https://downloads.superglue.cloud/superglue-gateway-windows.exe onto the machine where Sage 100 and Workstation Setup are installed (the gateway must run there, ProvideX.Script is a local 32-bit COM class), create a config.yaml next to it with a tunnel_id, the server_url ending in /ws/tunnels (wss://api.superglue.cloud/ws/tunnels for hosted superglue), an API key from the API Keys page, and the line enable_script_runner: true, then run the executable. That flag is required: it opts the gateway into running Sage scripts (it is code execution on their machine, so it is off by default), and it is what registers the built-in runner target. No targets section is needed. If a tunnel is connected but has no runner target, the gateway is either missing enable_script_runner: true or is an outdated build; have the user add the flag and restart, or download the current gateway from the same URL. When the tunnel with the runner target appears, attach it to the Sage 100 connection with tools.writeConnection (tunnel with that tunnelId) and keep the URL script://runner/vbs32. Collect sage_home (full path to the MAS90\\Home directory, for example C:\\Sage\\Sage100\\MAS90\\Home, not the MAS90 directory itself), sage_company, sage_user and sage_password through the secure credential form. Then run the Test Sage 100 connection tool once and interpret the result: retVal 0 failures carry the Sage reason in sLastErrorMsg (wrong credentials, missing role access, wrong company code); COM error 0x80040154 means the gateway is not running on a machine with Sage 100 Workstation Setup; a no-license message means all Sage user seats are in use. For new capabilities, build tools whose steps use the script protocol with VBScript in the body: log on with SY_Session, set module context before touching data (nSetDate with YYYYMMDD dates, nSetModule, nLookupTask, nSetProgram), use _svc service objects for reads and _bus business objects for writes, and always release the session with nCleanup and DropObject so the license seat frees up. For reads, set each key segment with nSetKeyValue then nFind for a single record, or browse with nMoveFirst and nMoveNext, and read each field with nGetValue passing a variable that receives the value. To write a document that has lines, such as a sales order, get the header _bus object, set the header fields, get its oLines object, call nAddLine, set the line fields, then call nWrite on the header to commit the header and its lines together. A write fails with a lock error if the record is open in the Sage desktop or held by another session, so report the lock message instead of retrying. Each running script briefly consumes a Sage user seat. Ask for explicit approval before any script that writes to Sage, and warn that records open in the Sage desktop UI cause lock errors.",completionCriteria:"The gateway is connected, the installed Sage 100 system has the tunnel attached and credentials saved, and the connection test returned company data from Sage 100. Any additional requested capability works end to end, with writes explicitly approved before they ran."},agentLaunch:{userPrompt:"I just installed the Sage 100 integration. Help me connect my Sage 100 server.",nextSteps:"Your first reply must be short: one line confirming the Sage 100 integration and setup playbook are installed, then start the connection flow. Check /org/tunnels for a connected gateway with a runner target first. If none exists, walk the user through it one step at a time: download https://downloads.superglue.cloud/superglue-gateway-windows.exe onto the Windows machine where Sage 100 is installed and Workstation Setup has run, create a config.yaml next to it with tunnel_id, server_url (wss://api.superglue.cloud/ws/tunnels for hosted superglue), an API key from the API Keys page, and the line enable_script_runner: true, then run it. That flag is required: it opts the gateway into running scripts on their machine (off by default because it is code execution) and is what registers the runner target. No targets are needed in the config. If a tunnel is connected but has no runner target, the gateway is missing enable_script_runner: true or is an outdated build: have the user add the flag and restart, or download the current one from the same URL. Wait for the user to confirm, then verify the tunnel appears and attach it to the Sage 100 connection with tools.writeConnection tunnel, keeping the URL script://runner/vbs32. Use connect with the connection id and fields to save sage_home (full path to the MAS90\\Home directory, for example C:\\Sage\\Sage100\\MAS90\\Home, not MAS90 itself), sage_company (for example ABC for the demo company), sage_user and sage_password. Never send the user to the Connections page. Then run the Test Sage 100 connection tool once. If it fails, explain the specific cause in plain language before retrying. Mention that each test briefly uses one Sage user license seat. Do not list tools or add tips unless asked."},tools:[{id:"sage100-test-connection",name:"Test Sage 100 connection",shortName:"Connection test",instruction:"Logs on to Sage 100 through the Secure Gateway, opens the configured company, and reads the first customer record to verify the Business Object Interface end to end. Briefly consumes one Sage user license seat.",steps:[{id:"testConnection",instruction:"Run a VBScript through the gateway script runner that logs on via SY_Session, sets A/R module context, and reads the first customer.",config:{type:"request",systemId:"sage100",url:"<<sage100_url>>",method:"POST",body:["Option Explicit","On Error Resume Next","Dim oScript, oSS, oCust, retVal, custNo, custName, today",'Set oScript = CreateObject("ProvideX.Script")','FailOnErr "CREATE", " (Sage 100 Workstation Setup has not registered ProvideX.Script on this machine; the gateway must run on a prepared Sage 100 machine)"','oScript.Init "<<sage100_sage_home>>"','FailOnErr "INIT", " (sage_home must be the full path to the MAS90\\Home directory, not MAS90 itself)"','Set oSS = oScript.NewObject("SY_Session")','FailOnErr "SESSION", ""','retVal = oSS.nSetUser("<<sage100_sage_user>>", "<<sage100_sage_password>>")','FailOnErr "LOGON", ""',"If retVal = 0 Then",' WScript.Echo "LOGON FAILED: " & oSS.sLastErrorMsg'," WScript.Quit 1","End If",'retVal = oSS.nSetCompany("<<sage100_sage_company>>")','FailOnErr "COMPANY", ""',"If retVal = 0 Then",' WScript.Echo "COMPANY FAILED: " & oSS.sLastErrorMsg'," oSS.nCleanup"," oSS.DropObject"," WScript.Quit 1","End If",'today = Year(Date) & Right("0" & Month(Date), 2) & Right("0" & Day(Date), 2)','retVal = oSS.nSetDate("A/R", today)','FailOnErr "DATE", ""','retVal = oSS.nSetModule("A/R")','FailOnErr "MODULE", ""','retVal = oSS.nSetProgram(oSS.nLookupTask("AR_Customer_ui"))','FailOnErr "TASK", ""',"If retVal = 0 Then",' WScript.Echo "TASK FAILED: " & oSS.sLastErrorMsg'," oSS.nCleanup"," oSS.DropObject"," WScript.Quit 1","End If",'Set oCust = oScript.NewObject("AR_Customer_svc", oSS)','FailOnErr "CUSTOMER OBJECT", ""',"retVal = oCust.nMoveFirst()",'FailOnErr "READ", ""',"If retVal = 0 Then",' WScript.Echo "READ FAILED: " & oCust.sLastErrorMsg',"Else",' custNo = "" : custName = ""',' retVal = oCust.nGetValue("CustomerNo$", custNo)',' retVal = oCust.nGetValue("CustomerName$", custName)',' FailOnErr "READ VALUE", " (ByRef value marshalling failed)"',' WScript.Echo "CONNECTED - company <<sage100_sage_company>>, first customer: " & custNo & " / " & custName',"End If","oCust.DropObject","oSS.nCleanup","oSS.DropObject","If retVal = 0 Then WScript.Quit 1","","Sub FailOnErr(stage, hint)"," If Err.Number <> 0 Then",' WScript.Echo stage & " FAILED: [0x" & Hex(Err.Number) & "] " & Err.Description & hint'," WScript.Quit 1"," End If","End Sub"].join(`
113
113
  `)}}]}]},sage_intacct:{bundleId:"sage_intacct",templateId:"sage_intacct",systemId:"sage_intacct",displayName:"Sage Intacct",description:"Install a Sage Intacct system, eight read/query tools, fourteen write tools and a native integration playbook.",systemUrl:"https://api.intacct.com/ia/xml/xmlgw.phtml",credentialHint:"Works instantly with a Sage Intacct demo company. Enter your company ID and API user credentials to use your own company. Web Services sender credentials are preconfigured.",requiredCredentialKeys:["sender_id","sender_password","user_id","user_password","company_id"],demoCredentials:{company_id:"IndexCommerceMPP-DEV",user_id:"superglue",user_password:"Linux123___"},mcpServer:{name:"sage-intacct",displayName:"Sage Intacct",description:"Chart of accounts, customers, vendors, journal entries and ad-hoc object queries from Sage Intacct, plus create and update tools for GL accounts, journal entries, invoices, bills, departments, vendors and customers."},installMcpServer:!1,playbook:{id:"sage-intacct-native-integration",name:"Sage Intacct Native Integration",whenToRun:"Use when connecting, validating, querying or extending a Sage Intacct integration through XML Web Services.",inputs:"A configured Sage Intacct system; the object or business process to work with; optional Location/Entity ID for multi-entity companies; validation criteria and desired output.",instructions:"Use the installed read-only tools for chart of accounts, customers, vendors, journal entries, invoices, bills and departments. Use Query any Sage Intacct object for supported objects outside the named library. Use the installed create and update tools for GL accounts, journal entries, invoices, bills, departments, vendors and customers only after the user explicitly confirms the exact records to write; the create tools are not idempotent and re-running them duplicates records. Apply the configured Location/Entity ID when present. Verify every XML Web Services response at control, authentication and function-result level, and preserve Sage support IDs in failures. For other objects or operations, inspect Sage object documentation, create separate least-privilege tools, validate them in a development company and require explicit user confirmation before modifying Sage data.",completionCriteria:"The requested Sage data, write result or validation result is returned; entity scope is correct; Sage XML failures are surfaced as failures with support IDs; no Sage data is modified unless the user explicitly requested and confirmed the write."},agentLaunch:{userPrompt:"I just installed the Sage Intacct integration. What can I do with it?",nextSteps:"Your first reply must be short: one line confirming the Sage Intacct integration and native integration playbook are installed, then collect credentials. The Web Services sender credentials are already configured. Use connect with this system's connection id and fields to save user_id, user_password and company_id, plus optional entity_id when the user wants to target one entity in a multi-entity company. Never send the user to the Connections page. The user id and password are an API user login in the company; company id is the Intacct company id. Once saved, offer one read-only test run. Do not list the installed tools or add tips unless asked. The query tool accepts other supported Intacct object names, and additional read or write tools can be built beyond the default library. The installed create and update tools modify Sage data; run them only after the user confirms the exact records to write."},tools:[{id:"sage-intacct-list-accounts",name:"List Sage Intacct chart of accounts",shortName:"Chart of accounts",instruction:"Lists general ledger accounts (the chart of accounts) from Sage Intacct via the XML Web Services API. Useful for validating an imported chart of accounts after a migration.",inputSchema:{type:"object",properties:{maxResults:{type:"integer",description:"Maximum number of records to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"queryAccounts",instruction:"Query GLACCOUNT records via readByQuery-style paging.",config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt("<query><object>GLACCOUNT</object><select><field>RECORDNO</field><field>ACCOUNTNO</field><field>TITLE</field><field>ACCOUNTTYPE</field><field>NORMALBALANCE</field><field>STATUS</field></select><pagesize><<pageSize>></pagesize><offset><<offset>></offset></query>"),pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const dig = (o) => o && o.RESPONSE && o.RESPONSE.OPERATION && o.RESPONSE.OPERATION.RESULT ? o.RESPONSE.OPERATION.RESULT.DATA : undefined; const cur = dig(response && response.data); const cr = cur ? cur.GLACCOUNT : undefined; const rows = Array.isArray(cr) ? cr : (cr ? [cr] : []); const mr = dig(pageInfo && pageInfo.mergedResult); const mraw = mr ? mr.GLACCOUNT : undefined; const fetched = Array.isArray(mraw) ? mraw.length : (mraw ? 1 : 0); const max = (sourceData && sourceData.maxResults) ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:Ts({stepId:"queryAccounts",objectNameExpression:"'GLACCOUNT'",collectionName:"accounts",mapExpression:"(record) => ({ recordNo: record.RECORDNO, account: record.ACCOUNTNO, name: record.TITLE, type: record.ACCOUNTTYPE, normalBalance: record.NORMALBALANCE, status: record.STATUS })"})},{id:"sage-intacct-list-customers",name:"List Sage Intacct customers",shortName:"Customers",instruction:"Lists customer master records from Sage Intacct accounts receivable. Useful for verifying migrated AR master data.",inputSchema:{type:"object",properties:{maxResults:{type:"integer",description:"Maximum number of records to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"queryCustomers",instruction:"Query CUSTOMER records.",config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt("<query><object>CUSTOMER</object><select><field>RECORDNO</field><field>CUSTOMERID</field><field>NAME</field><field>STATUS</field><field>WHENCREATED</field></select><pagesize><<pageSize>></pagesize><offset><<offset>></offset></query>"),pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const dig = (o) => o && o.RESPONSE && o.RESPONSE.OPERATION && o.RESPONSE.OPERATION.RESULT ? o.RESPONSE.OPERATION.RESULT.DATA : undefined; const cur = dig(response && response.data); const cr = cur ? cur.CUSTOMER : undefined; const rows = Array.isArray(cr) ? cr : (cr ? [cr] : []); const mr = dig(pageInfo && pageInfo.mergedResult); const mraw = mr ? mr.CUSTOMER : undefined; const fetched = Array.isArray(mraw) ? mraw.length : (mraw ? 1 : 0); const max = (sourceData && sourceData.maxResults) ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:Ts({stepId:"queryCustomers",objectNameExpression:"'CUSTOMER'",collectionName:"customers",mapExpression:"(record) => ({ recordNo: record.RECORDNO, customerId: record.CUSTOMERID, name: record.NAME, status: record.STATUS, createdOn: record.WHENCREATED })"})},{id:"sage-intacct-list-vendors",name:"List Sage Intacct vendors",shortName:"Vendors",instruction:"Lists vendor master records from Sage Intacct accounts payable. Useful for verifying migrated AP master data.",inputSchema:{type:"object",properties:{maxResults:{type:"integer",description:"Maximum number of records to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"queryVendors",instruction:"Query VENDOR records.",config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt("<query><object>VENDOR</object><select><field>RECORDNO</field><field>VENDORID</field><field>NAME</field><field>STATUS</field><field>WHENCREATED</field></select><pagesize><<pageSize>></pagesize><offset><<offset>></offset></query>"),pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const dig = (o) => o && o.RESPONSE && o.RESPONSE.OPERATION && o.RESPONSE.OPERATION.RESULT ? o.RESPONSE.OPERATION.RESULT.DATA : undefined; const cur = dig(response && response.data); const cr = cur ? cur.VENDOR : undefined; const rows = Array.isArray(cr) ? cr : (cr ? [cr] : []); const mr = dig(pageInfo && pageInfo.mergedResult); const mraw = mr ? mr.VENDOR : undefined; const fetched = Array.isArray(mraw) ? mraw.length : (mraw ? 1 : 0); const max = (sourceData && sourceData.maxResults) ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:Ts({stepId:"queryVendors",objectNameExpression:"'VENDOR'",collectionName:"vendors",mapExpression:"(record) => ({ recordNo: record.RECORDNO, vendorId: record.VENDORID, name: record.NAME, status: record.STATUS, createdOn: record.WHENCREATED })"})},{id:"sage-intacct-list-journal-entries",name:"List Sage Intacct journal entries",shortName:"Journal entries",instruction:"Lists general ledger entries from Sage Intacct with account, type and amount. Useful for verifying opening balances and postings at cutover.",inputSchema:{type:"object",properties:{maxResults:{type:"integer",description:"Maximum number of records to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"queryJournalEntries",instruction:"Query GLENTRY records.",config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt("<query><object>GLENTRY</object><select><field>RECORDNO</field><field>BATCHNO</field><field>ACCOUNTNO</field><field>TR_TYPE</field><field>AMOUNT</field><field>ENTRY_DATE</field></select><pagesize><<pageSize>></pagesize><offset><<offset>></offset></query>"),pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const dig = (o) => o && o.RESPONSE && o.RESPONSE.OPERATION && o.RESPONSE.OPERATION.RESULT ? o.RESPONSE.OPERATION.RESULT.DATA : undefined; const cur = dig(response && response.data); const cr = cur ? cur.GLENTRY : undefined; const rows = Array.isArray(cr) ? cr : (cr ? [cr] : []); const mr = dig(pageInfo && pageInfo.mergedResult); const mraw = mr ? mr.GLENTRY : undefined; const fetched = Array.isArray(mraw) ? mraw.length : (mraw ? 1 : 0); const max = (sourceData && sourceData.maxResults) ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:Ts({stepId:"queryJournalEntries",objectNameExpression:"'GLENTRY'",collectionName:"journalEntries",mapExpression:"(record) => ({ recordNo: record.RECORDNO, batch: record.BATCHNO, account: record.ACCOUNTNO, type: record.TR_TYPE, amount: Number(record.AMOUNT), date: record.ENTRY_DATE })"})},{id:"sage-intacct-list-invoices",name:"List Sage Intacct invoices",shortName:"Invoices",instruction:"Lists accounts receivable invoices from Sage Intacct. Useful for verifying migrated open AR at go-live.",inputSchema:{type:"object",properties:{maxResults:{type:"integer",description:"Maximum number of records to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"queryInvoices",instruction:"Query ARINVOICE records.",config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt("<query><object>ARINVOICE</object><select><field>RECORDNO</field><field>RECORDID</field><field>CUSTOMERID</field><field>TOTALDUE</field><field>WHENCREATED</field><field>STATE</field></select><pagesize><<pageSize>></pagesize><offset><<offset>></offset></query>"),pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const dig = (o) => o && o.RESPONSE && o.RESPONSE.OPERATION && o.RESPONSE.OPERATION.RESULT ? o.RESPONSE.OPERATION.RESULT.DATA : undefined; const cur = dig(response && response.data); const cr = cur ? cur.ARINVOICE : undefined; const rows = Array.isArray(cr) ? cr : (cr ? [cr] : []); const mr = dig(pageInfo && pageInfo.mergedResult); const mraw = mr ? mr.ARINVOICE : undefined; const fetched = Array.isArray(mraw) ? mraw.length : (mraw ? 1 : 0); const max = (sourceData && sourceData.maxResults) ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:Ts({stepId:"queryInvoices",objectNameExpression:"'ARINVOICE'",collectionName:"invoices",mapExpression:"(record) => ({ recordNo: record.RECORDNO, invoiceId: record.RECORDID, customerId: record.CUSTOMERID, totalDue: Number(record.TOTALDUE), createdOn: record.WHENCREATED, state: record.STATE })"})},{id:"sage-intacct-list-bills",name:"List Sage Intacct bills",shortName:"Bills",instruction:"Lists accounts payable bills from Sage Intacct. Useful for verifying migrated open AP at go-live.",inputSchema:{type:"object",properties:{maxResults:{type:"integer",description:"Maximum number of records to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"queryBills",instruction:"Query APBILL records.",config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt("<query><object>APBILL</object><select><field>RECORDNO</field><field>RECORDID</field><field>VENDORID</field><field>TOTALDUE</field><field>WHENCREATED</field><field>STATE</field></select><pagesize><<pageSize>></pagesize><offset><<offset>></offset></query>"),pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const dig = (o) => o && o.RESPONSE && o.RESPONSE.OPERATION && o.RESPONSE.OPERATION.RESULT ? o.RESPONSE.OPERATION.RESULT.DATA : undefined; const cur = dig(response && response.data); const cr = cur ? cur.APBILL : undefined; const rows = Array.isArray(cr) ? cr : (cr ? [cr] : []); const mr = dig(pageInfo && pageInfo.mergedResult); const mraw = mr ? mr.APBILL : undefined; const fetched = Array.isArray(mraw) ? mraw.length : (mraw ? 1 : 0); const max = (sourceData && sourceData.maxResults) ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:Ts({stepId:"queryBills",objectNameExpression:"'APBILL'",collectionName:"bills",mapExpression:"(record) => ({ recordNo: record.RECORDNO, billId: record.RECORDID, vendorId: record.VENDORID, totalDue: Number(record.TOTALDUE), createdOn: record.WHENCREATED, state: record.STATE })"})},{id:"sage-intacct-list-departments",name:"List Sage Intacct departments",shortName:"Departments",instruction:"Lists department dimensions from Sage Intacct. Useful for validating the dimension setup after an implementation.",inputSchema:{type:"object",properties:{maxResults:{type:"integer",description:"Maximum number of records to return. Defaults to 200."}},additionalProperties:!0},steps:[{id:"queryDepartments",instruction:"Query DEPARTMENT records.",config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt("<query><object>DEPARTMENT</object><select><field>RECORDNO</field><field>DEPARTMENTID</field><field>TITLE</field><field>STATUS</field></select><pagesize><<pageSize>></pagesize><offset><<offset>></offset></query>"),pagination:{type:"offsetBased",pageSize:"100",stopCondition:"(response, pageInfo, sourceData) => { const dig = (o) => o && o.RESPONSE && o.RESPONSE.OPERATION && o.RESPONSE.OPERATION.RESULT ? o.RESPONSE.OPERATION.RESULT.DATA : undefined; const cur = dig(response && response.data); const cr = cur ? cur.DEPARTMENT : undefined; const rows = Array.isArray(cr) ? cr : (cr ? [cr] : []); const mr = dig(pageInfo && pageInfo.mergedResult); const mraw = mr ? mr.DEPARTMENT : undefined; const fetched = Array.isArray(mraw) ? mraw.length : (mraw ? 1 : 0); const max = (sourceData && sourceData.maxResults) ?? 200; return rows.length === 0 || fetched >= max; }"}}}],outputTransform:Ts({stepId:"queryDepartments",objectNameExpression:"'DEPARTMENT'",collectionName:"departments",mapExpression:"(record) => ({ recordNo: record.RECORDNO, departmentId: record.DEPARTMENTID, name: record.TITLE, status: record.STATUS })"})},{id:"sage-intacct-query-object",name:"Query any Sage Intacct object",shortName:"Query any object",instruction:"Queries any Sage Intacct object by name (for example GLACCOUNT, PROJECT, GLENTRY, ARINVOICE) using the XML Web Services readByQuery, with an optional Intacct query filter. The workhorse tool for migration validation beyond the prebuilt lists. Returns up to 1000 records in one call.",inputSchema:{type:"object",properties:{object:{type:"string",description:'Intacct object name, e.g. "GLACCOUNT", "PROJECT", "GLENTRY", "ARINVOICE".'},query:{type:"string",description:`Optional Intacct query filter, e.g. "STATUS = 'active'". Leave empty to return all records.`},maxResults:{type:"integer",description:"Maximum number of records to return (max 1000). Defaults to 100."}},required:["object"],additionalProperties:!0},steps:[{id:"queryObject",instruction:"Run readByQuery for the requested object.",config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt("<readByQuery><object><<(p) => { const value = String(p.object || '').toUpperCase(); if (!/^[A-Z][A-Z0-9_]*$/.test(value)) throw new Error('Sage Intacct object must contain only letters, numbers, and underscores.'); return value; }>></object><fields>*</fields><query><<(p) => String(p.query || '').replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;')>></query><pagesize><<(p) => Math.min(Math.max(Number(p.maxResults) || 100, 1), 1000)>></pagesize></readByQuery>")}}],outputTransform:Ts({stepId:"queryObject",objectNameExpression:"(sourceData && sourceData.object ? String(sourceData.object) : '').toUpperCase()",collectionName:"records",includeTotalCount:!0})},{id:"sage-intacct-create-journal-entry",name:"Create Sage Intacct journal entry",shortName:"Create journal entry",instruction:"Creates a journal entry (GLBATCH with GLENTRY lines) in Sage Intacct via the XML Web Services API. Debits and credits must balance. Re-running this tool creates another journal entry; it is not idempotent.",inputSchema:{type:"object",properties:{journal:{type:"string",description:'Journal symbol, e.g. "GJ". Defaults to GJ.'},date:{type:"string",description:"Posting date as YYYY-MM-DD."},title:{type:"string",description:"Journal entry description."},lines:{type:"array",description:"Journal lines. Debit and credit totals must balance.",items:{type:"object",properties:{accountNo:{type:"string",description:"GL account number."},type:{type:"string",enum:["debit","credit"]},amount:{type:"number",description:"Positive amount."},department:{type:"string",description:"Optional department ID."},location:{type:"string",description:"Optional location ID."},memo:{type:"string",description:"Optional line description."}},required:["accountNo","type","amount"],additionalProperties:!0}}},required:["date","title","lines"],additionalProperties:!0},steps:[{id:"createJournalEntry",instruction:"Create the GLBATCH record.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt(`<create><GLBATCH><JOURNAL><<(sourceData) => { ${Ds} return esc(sourceData.journal || 'GJ'); }>></JOURNAL><BATCH_DATE><<(sourceData) => { ${dL} return toIntacctDate(sourceData.date); }>></BATCH_DATE><BATCH_TITLE><<(sourceData) => { ${Ds} return esc(sourceData.title); }>></BATCH_TITLE><ENTRIES><<(sourceData) => { ${Ds} ${pL} ${AL} const lines = Array.isArray(sourceData.lines) ? sourceData.lines : []; if (lines.length === 0) throw new Error('lines must contain at least one journal line.'); assertBalanced(lines); return lines.map(lineXml).join(''); }>></ENTRIES></GLBATCH></create>`)}}],outputTransform:Iu({stepId:"createJournalEntry",objectName:"GLBATCH"})},{id:"sage-intacct-update-journal-entry",name:"Update Sage Intacct journal entry",shortName:"Update journal entry",instruction:"Updates an existing journal entry (GLBATCH) in Sage Intacct by record number. Posted or locked entries may refuse updates. When lines are provided they replace all existing lines of the entry.",inputSchema:{type:"object",properties:{recordNo:{type:"integer",description:"RECORDNO of the journal entry to update."},journal:{type:"string",description:"Optional new journal symbol."},date:{type:"string",description:"Optional new posting date as YYYY-MM-DD."},title:{type:"string",description:"Optional new description."},lines:{type:"array",description:"Optional replacement lines. When set, they replace every existing line and must balance.",items:{type:"object",properties:{accountNo:{type:"string",description:"GL account number."},type:{type:"string",enum:["debit","credit"]},amount:{type:"number",description:"Positive amount."},department:{type:"string",description:"Optional department ID."},location:{type:"string",description:"Optional location ID."},memo:{type:"string",description:"Optional line description."}},required:["accountNo","type","amount"],additionalProperties:!0}}},required:["recordNo"],additionalProperties:!0},steps:[{id:"updateJournalEntry",instruction:"Update the GLBATCH record.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt(`<update><GLBATCH><RECORDNO><<(sourceData) => { const recordNo = Number(sourceData.recordNo); if (!Number.isInteger(recordNo) || recordNo <= 0) throw new Error('recordNo must be a positive integer.'); return recordNo; }>></RECORDNO><<(sourceData) => { ${Ds} ${dL} ${pL} ${AL} let xml = ''; if (sourceData.journal) xml += '<JOURNAL>' + esc(sourceData.journal) + '</JOURNAL>'; if (sourceData.date) xml += '<BATCH_DATE>' + toIntacctDate(sourceData.date) + '</BATCH_DATE>'; if (sourceData.title) xml += '<BATCH_TITLE>' + esc(sourceData.title) + '</BATCH_TITLE>'; if (Array.isArray(sourceData.lines) && sourceData.lines.length > 0) { assertBalanced(sourceData.lines); xml += '<ENTRIES>' + sourceData.lines.map(lineXml).join('') + '</ENTRIES>'; } if (!xml) throw new Error('Provide at least one field to update.'); return xml; }>></GLBATCH></update>`)}}],outputTransform:Iu({stepId:"updateJournalEntry",objectName:"GLBATCH"})},{id:"sage-intacct-create-vendor",name:"Create Sage Intacct vendor",shortName:"Create vendor",instruction:"Creates a vendor master record in Sage Intacct via the XML Web Services API. Omit vendorId when the company uses vendor auto-numbering. Re-running this tool creates another vendor; it is not idempotent.",inputSchema:{type:"object",properties:{vendorId:{type:"string",description:"Vendor ID. Omit when auto-numbering assigns it."},name:{type:"string",description:"Vendor name."},taxId:{type:"string",description:"Optional tax ID."}},required:["name"],additionalProperties:!0},steps:[{id:"createVendor",instruction:"Create the VENDOR record.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt(`<create><VENDOR><<(sourceData) => { ${Ds} if (!sourceData.name) throw new Error('name is required.'); let xml = ''; if (sourceData.vendorId) xml += '<VENDORID>' + esc(sourceData.vendorId) + '</VENDORID>'; xml += '<NAME>' + esc(sourceData.name) + '</NAME>'; if (sourceData.taxId) xml += '<TAXID>' + esc(sourceData.taxId) + '</TAXID>'; return xml; }>></VENDOR></create>`)}}],outputTransform:Iu({stepId:"createVendor",objectName:"VENDOR"})},{id:"sage-intacct-update-vendor",name:"Update Sage Intacct vendor",shortName:"Update vendor",instruction:"Updates an existing vendor master record in Sage Intacct by record number. Only the provided fields change.",inputSchema:{type:"object",properties:{recordNo:{type:"integer",description:"RECORDNO of the vendor to update."},name:{type:"string",description:"Optional new vendor name."},status:{type:"string",enum:["active","inactive"]},taxId:{type:"string",description:"Optional new tax ID."}},required:["recordNo"],additionalProperties:!0},steps:[{id:"updateVendor",instruction:"Update the VENDOR record.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt(`<update><VENDOR><RECORDNO><<(sourceData) => { const recordNo = Number(sourceData.recordNo); if (!Number.isInteger(recordNo) || recordNo <= 0) throw new Error('recordNo must be a positive integer.'); return recordNo; }>></RECORDNO><<(sourceData) => { ${Ds} let xml = ''; if (sourceData.name) xml += '<NAME>' + esc(sourceData.name) + '</NAME>'; if (sourceData.status) xml += '<STATUS>' + esc(sourceData.status) + '</STATUS>'; if (sourceData.taxId) xml += '<TAXID>' + esc(sourceData.taxId) + '</TAXID>'; if (!xml) throw new Error('Provide at least one field to update.'); return xml; }>></VENDOR></update>`)}}],outputTransform:Iu({stepId:"updateVendor",objectName:"VENDOR"})},{id:"sage-intacct-create-customer",name:"Create Sage Intacct customer",shortName:"Create customer",instruction:"Creates a customer master record in Sage Intacct via the XML Web Services API. Omit customerId when the company uses customer auto-numbering. Re-running this tool creates another customer; it is not idempotent.",inputSchema:{type:"object",properties:{customerId:{type:"string",description:"Customer ID. Omit when auto-numbering assigns it."},name:{type:"string",description:"Customer name."},taxId:{type:"string",description:"Optional tax ID."}},required:["name"],additionalProperties:!0},steps:[{id:"createCustomer",instruction:"Create the CUSTOMER record.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt(`<create><CUSTOMER><<(sourceData) => { ${Ds} if (!sourceData.name) throw new Error('name is required.'); let xml = ''; if (sourceData.customerId) xml += '<CUSTOMERID>' + esc(sourceData.customerId) + '</CUSTOMERID>'; xml += '<NAME>' + esc(sourceData.name) + '</NAME>'; if (sourceData.taxId) xml += '<TAXID>' + esc(sourceData.taxId) + '</TAXID>'; return xml; }>></CUSTOMER></create>`)}}],outputTransform:Iu({stepId:"createCustomer",objectName:"CUSTOMER"})},{id:"sage-intacct-update-customer",name:"Update Sage Intacct customer",shortName:"Update customer",instruction:"Updates an existing customer master record in Sage Intacct by record number. Only the provided fields change.",inputSchema:{type:"object",properties:{recordNo:{type:"integer",description:"RECORDNO of the customer to update."},name:{type:"string",description:"Optional new customer name."},status:{type:"string",enum:["active","inactive"]},taxId:{type:"string",description:"Optional new tax ID."}},required:["recordNo"],additionalProperties:!0},steps:[{id:"updateCustomer",instruction:"Update the CUSTOMER record.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt(`<update><CUSTOMER><RECORDNO><<(sourceData) => { const recordNo = Number(sourceData.recordNo); if (!Number.isInteger(recordNo) || recordNo <= 0) throw new Error('recordNo must be a positive integer.'); return recordNo; }>></RECORDNO><<(sourceData) => { ${Ds} let xml = ''; if (sourceData.name) xml += '<NAME>' + esc(sourceData.name) + '</NAME>'; if (sourceData.status) xml += '<STATUS>' + esc(sourceData.status) + '</STATUS>'; if (sourceData.taxId) xml += '<TAXID>' + esc(sourceData.taxId) + '</TAXID>'; if (!xml) throw new Error('Provide at least one field to update.'); return xml; }>></CUSTOMER></update>`)}}],outputTransform:Iu({stepId:"updateCustomer",objectName:"CUSTOMER"})},{id:"sage-intacct-create-account",name:"Create Sage Intacct GL account",shortName:"Create GL account",instruction:"Creates a general ledger account in Sage Intacct via the XML Web Services API. Re-running this tool creates another account; it is not idempotent.",inputSchema:{type:"object",required:["accountNo","title","normalBalance","accountType"],properties:{title:{type:"string"},accountNo:{type:"string"},accountType:{type:"string",enum:["balancesheet","incomestatement"]},normalBalance:{type:"string",enum:["debit","credit"]},closingType:{type:"string",enum:["non-closing account","closing account"],description:"Period-end closing type. Defaults to non-closing account."},closingAccountNo:{type:"string",description:"Account to close into. Sage requires it when closingType is closing account."}}},steps:[{id:"createAccount",instruction:"Create the GLACCOUNT record via the Sage Intacct XML API.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt(`<create><GLACCOUNT><<(sourceData) => { const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&apos;'); if (!sourceData.accountNo) throw new Error('accountNo is required.'); if (!sourceData.title) throw new Error('title is required.'); let xml = '<ACCOUNTNO>' + esc(sourceData.accountNo) + '</ACCOUNTNO>'; xml += '<TITLE>' + esc(sourceData.title) + '</TITLE>'; xml += '<NORMALBALANCE>' + esc(sourceData.normalBalance || 'debit') + '</NORMALBALANCE>'; xml += '<ACCOUNTTYPE>' + esc(sourceData.accountType || 'balancesheet') + '</ACCOUNTTYPE>'; xml += '<CLOSINGTYPE>' + esc(sourceData.closingType || 'non-closing account') + '</CLOSINGTYPE>'; if (sourceData.closingAccountNo) xml += '<CLOSINGACCOUNTNO>' + esc(sourceData.closingAccountNo) + '</CLOSINGACCOUNTNO>'; return xml; }>></GLACCOUNT></create>`)}}],outputTransform:"(sourceData) => { const response = sourceData.createAccount && sourceData.createAccount.data ? sourceData.createAccount.data.RESPONSE : undefined; const control = response ? response.CONTROL : undefined; const operation = response ? response.OPERATION : undefined; const authentication = operation ? operation.AUTHENTICATION : undefined; const result = operation ? operation.RESULT : undefined; const statuses = [control && control.STATUS, authentication && authentication.STATUS, result && result.STATUS].filter(Boolean).map((value) => String(value).toLowerCase()); if (statuses.includes('failure')) { const message = (result && result.ERRORMESSAGE) || (authentication && authentication.ERR ? authentication.ERR.ERRORMESSAGE : undefined) || (control && control.ERR ? control.ERR.ERRORMESSAGE : undefined); const rawErrors = message ? message.ERROR : undefined; const errors = Array.isArray(rawErrors) ? rawErrors : (rawErrors ? [rawErrors] : []); const details = errors.map((error) => [error.ERRORNO, error.DESCRIPTION2 || error.DESCRIPTION, error.CORRECTION].filter(Boolean).join(' - ')).filter(Boolean); const supportIds = errors.map((error) => error.SUPPORTID).filter(Boolean); const suffix = supportIds.length ? ` Sage support ID: ${supportIds.join(', ')}.` : ''; throw new Error(`Sage Intacct request failed${details.length ? `: ${details.join('; ')}` : '.'}${suffix}`); } const data = result ? result.DATA : undefined; const raw = data ? (data.GLACCOUNT || data.glaccount) : undefined; const record = Array.isArray(raw) ? raw[0] : raw; return { recordNo: record && record.RECORDNO ? Number(record.RECORDNO) : undefined, record }; }"},{id:"sage-intacct-update-account",name:"Update Sage Intacct GL account",shortName:"Update GL account",instruction:"Updates an existing general ledger account in Sage Intacct by account number. Only the provided fields change.",inputSchema:{type:"object",required:["accountNo"],properties:{title:{type:"string"},accountNo:{type:"string"},accountType:{type:"string",enum:["balancesheet","incomestatement"]},normalBalance:{type:"string",enum:["debit","credit"]},status:{type:"string",enum:["active","inactive"]}}},steps:[{id:"updateAccount",instruction:"Update the GLACCOUNT record by account number.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt(`<update><GLACCOUNT><ACCOUNTNO><<(sourceData) => { const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&apos;'); if (!sourceData.accountNo) throw new Error('accountNo is required.'); return esc(sourceData.accountNo); }>></ACCOUNTNO><<(sourceData) => { const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&apos;'); let xml = ''; if (sourceData.title) xml += '<TITLE>' + esc(sourceData.title) + '</TITLE>'; if (sourceData.normalBalance) xml += '<NORMALBALANCE>' + esc(sourceData.normalBalance) + '</NORMALBALANCE>'; if (sourceData.accountType) xml += '<ACCOUNTTYPE>' + esc(sourceData.accountType) + '</ACCOUNTTYPE>'; if (sourceData.status) xml += '<STATUS>' + esc(sourceData.status) + '</STATUS>'; if (!xml) throw new Error('Provide at least one field to update.'); return xml; }>></GLACCOUNT></update>`)}}],outputTransform:"(sourceData) => { const response = sourceData.updateAccount && sourceData.updateAccount.data ? sourceData.updateAccount.data.RESPONSE : undefined; const control = response ? response.CONTROL : undefined; const operation = response ? response.OPERATION : undefined; const authentication = operation ? operation.AUTHENTICATION : undefined; const result = operation ? operation.RESULT : undefined; const statuses = [control && control.STATUS, authentication && authentication.STATUS, result && result.STATUS].filter(Boolean).map((value) => String(value).toLowerCase()); if (statuses.includes('failure')) { const message = (result && result.ERRORMESSAGE) || (authentication && authentication.ERR ? authentication.ERR.ERRORMESSAGE : undefined) || (control && control.ERR ? control.ERR.ERRORMESSAGE : undefined); const rawErrors = message ? message.ERROR : undefined; const errors = Array.isArray(rawErrors) ? rawErrors : (rawErrors ? [rawErrors] : []); const details = errors.map((error) => [error.ERRORNO, error.DESCRIPTION2 || error.DESCRIPTION, error.CORRECTION].filter(Boolean).join(' - ')).filter(Boolean); const supportIds = errors.map((error) => error.SUPPORTID).filter(Boolean); const suffix = supportIds.length ? ` Sage support ID: ${supportIds.join(', ')}.` : ''; throw new Error(`Sage Intacct request failed${details.length ? `: ${details.join('; ')}` : '.'}${suffix}`); } const data = result ? result.DATA : undefined; const raw = data ? (data.GLACCOUNT || data.glaccount) : undefined; const record = Array.isArray(raw) ? raw[0] : raw; return { accountNo: sourceData.accountNo, record }; }"},{id:"sage-intacct-create-invoice",name:"Create Sage Intacct AR invoice",shortName:"Create invoice",instruction:"Creates an AR invoice in Sage Intacct via the XML Web Services API. Requires a customer ID, transaction date, and at least one line item with a GL account and amount. Re-running creates another invoice; it is not idempotent.",inputSchema:{type:"object",required:["customerId","dateCreated","dateDue","lines"],properties:{lines:{type:"array",items:{type:"object",required:["glAccountNo","amount"],properties:{memo:{type:"string"},amount:{type:"number"},glAccountNo:{type:"string"},departmentId:{type:"string"},locationId:{type:"string"},vendorId:{type:"string"},customerId:{type:"string"},projectId:{type:"string"}}}},dateDue:{type:"string"},customerId:{type:"string"},dateCreated:{type:"string"},datePosted:{type:"string"},termName:{type:"string"},description:{type:"string"}}},steps:[{id:"createInvoice",instruction:"Create the ARINVOICE record with line items.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt("<create><ARINVOICE><<(sourceData) => { const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('\"', '&quot;').replaceAll(\"'\", '&apos;'); if (!sourceData.customerId) throw new Error('customerId is required.'); if (!sourceData.dateCreated) throw new Error('dateCreated is required (YYYY-MM-DD).'); const lines = Array.isArray(sourceData.lines) ? sourceData.lines : []; if (lines.length === 0) throw new Error('lines must contain at least one invoice line.'); const match = String(sourceData.dateCreated).match(/^(\\d{4})-(\\d{2})-(\\d{2})/); const dateXml = match ? `<WHENCREATED><YEAR>${match[1]}</YEAR><MONTH>${match[2]}</MONTH><DAY>${match[3]}</DAY></WHENCREATED>` : `<WHENCREATED>${esc(sourceData.dateCreated)}</WHENCREATED>`; let xml = '<CUSTOMERID>' + esc(sourceData.customerId) + '</CUSTOMERID>'; xml += dateXml; if (sourceData.datePosted) { const mp = String(sourceData.datePosted).match(/^(\\d{4})-(\\d{2})-(\\d{2})/); if (mp) xml += `<WHENPOSTED><YEAR>${mp[1]}</YEAR><MONTH>${mp[2]}</MONTH><DAY>${mp[3]}</DAY></WHENPOSTED>`; } if (sourceData.dateDue) { const md = String(sourceData.dateDue).match(/^(\\d{4})-(\\d{2})-(\\d{2})/); if (md) xml += `<WHENDUE><YEAR>${md[1]}</YEAR><MONTH>${md[2]}</MONTH><DAY>${md[3]}</DAY></WHENDUE>`; } else if (sourceData.termName) { xml += '<TERMNAME>' + esc(sourceData.termName) + '</TERMNAME>'; } if (sourceData.description) xml += '<DESCRIPTION>' + esc(sourceData.description) + '</DESCRIPTION>'; xml += '<ARINVOICEITEMS>'; lines.forEach((line) => { if (!line.glAccountNo) throw new Error('Each line requires glAccountNo.'); if (line.amount == null) throw new Error('Each line requires amount.'); xml += '<ARINVOICEITEM>'; xml += '<ACCOUNTNO>' + esc(line.glAccountNo) + '</ACCOUNTNO>'; xml += '<AMOUNT>' + Number(line.amount) + '</AMOUNT>'; if (line.memo) xml += '<MEMO>' + esc(line.memo) + '</MEMO>'; if (line.departmentId) xml += '<DEPARTMENTID>' + esc(line.departmentId) + '</DEPARTMENTID>'; if (line.locationId) xml += '<LOCATIONID>' + esc(line.locationId) + '</LOCATIONID>'; if (line.vendorId) xml += '<VENDORID>' + esc(line.vendorId) + '</VENDORID>'; if (line.customerId) xml += '<CUSTOMERID>' + esc(line.customerId) + '</CUSTOMERID>'; if (line.projectId) xml += '<PROJECTID>' + esc(line.projectId) + '</PROJECTID>'; xml += '</ARINVOICEITEM>'; }); xml += '</ARINVOICEITEMS>'; return xml; }>></ARINVOICE></create>")}}],outputTransform:"(sourceData) => { const response = sourceData.createInvoice && sourceData.createInvoice.data ? sourceData.createInvoice.data.RESPONSE : undefined; const control = response ? response.CONTROL : undefined; const operation = response ? response.OPERATION : undefined; const authentication = operation ? operation.AUTHENTICATION : undefined; const result = operation ? operation.RESULT : undefined; const statuses = [control && control.STATUS, authentication && authentication.STATUS, result && result.STATUS].filter(Boolean).map((value) => String(value).toLowerCase()); if (statuses.includes('failure')) { const message = (result && result.ERRORMESSAGE) || (authentication && authentication.ERR ? authentication.ERR.ERRORMESSAGE : undefined) || (control && control.ERR ? control.ERR.ERRORMESSAGE : undefined); const rawErrors = message ? message.ERROR : undefined; const errors = Array.isArray(rawErrors) ? rawErrors : (rawErrors ? [rawErrors] : []); const details = errors.map((error) => [error.ERRORNO, error.DESCRIPTION2 || error.DESCRIPTION, error.CORRECTION].filter(Boolean).join(' - ')).filter(Boolean); const supportIds = errors.map((error) => error.SUPPORTID).filter(Boolean); const suffix = supportIds.length ? ` Sage support ID: ${supportIds.join(', ')}.` : ''; throw new Error(`Sage Intacct request failed${details.length ? `: ${details.join('; ')}` : '.'}${suffix}`); } const data = result ? result.DATA : undefined; const raw = data ? (data.ARINVOICE || data.arinvoice) : undefined; const record = Array.isArray(raw) ? raw[0] : raw; return { recordNo: record && record.RECORDNO ? Number(record.RECORDNO) : undefined, record }; }"},{id:"sage-intacct-update-invoice",name:"Update Sage Intacct AR invoice",shortName:"Update invoice",instruction:"Updates an existing AR invoice in Sage Intacct by record number. Only the provided fields change. Line items can be added or updated by line number.",inputSchema:{type:"object",required:["recordNo"],properties:{recordNo:{type:"integer"},description:{type:"string"},customerId:{type:"string"},dateCreated:{type:"string"},dateDue:{type:"string"},termName:{type:"string"},lines:{type:"array",items:{type:"object",properties:{lineNo:{type:"integer"},memo:{type:"string"},amount:{type:"number"},glAccountNo:{type:"string"},departmentId:{type:"string"},locationId:{type:"string"},vendorId:{type:"string"},customerId:{type:"string"},projectId:{type:"string"}}}}}},steps:[{id:"updateInvoice",instruction:"Update the ARINVOICE record by RECORDNO.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt("<update><ARINVOICE><RECORDNO><<(sourceData) => { const recordNo = Number(sourceData.recordNo); if (!Number.isInteger(recordNo) || recordNo <= 0) throw new Error('recordNo must be a positive integer.'); return recordNo; }>></RECORDNO><<(sourceData) => { const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('\"', '&quot;').replaceAll(\"'\", '&apos;'); let xml = ''; if (sourceData.customerId) xml += '<CUSTOMERID>' + esc(sourceData.customerId) + '</CUSTOMERID>'; if (sourceData.dateCreated) { const match = String(sourceData.dateCreated).match(/^(\\d{4})-(\\d{2})-(\\d{2})/); if (match) xml += `<WHENCREATED><YEAR>${match[1]}</YEAR><MONTH>${match[2]}</MONTH><DAY>${match[3]}</DAY></WHENCREATED>`; } if (sourceData.dateDue) { const md = String(sourceData.dateDue).match(/^(\\d{4})-(\\d{2})-(\\d{2})/); if (md) xml += `<WHENDUE><YEAR>${md[1]}</YEAR><MONTH>${md[2]}</MONTH><DAY>${md[3]}</DAY></WHENDUE>`; } if (sourceData.termName) xml += '<TERMNAME>' + esc(sourceData.termName) + '</TERMNAME>'; if (sourceData.description) xml += '<DESCRIPTION>' + esc(sourceData.description) + '</DESCRIPTION>'; const lines = Array.isArray(sourceData.lines) ? sourceData.lines : []; if (lines.length > 0) { xml += '<ARINVOICEITEMS>'; lines.forEach((line) => { xml += '<ARINVOICEITEM>'; if (line.lineNo) xml += '<LINE_NO>' + Number(line.lineNo) + '</LINE_NO>'; if (line.glAccountNo) xml += '<ACCOUNTNO>' + esc(line.glAccountNo) + '</ACCOUNTNO>'; if (line.amount != null) xml += '<AMOUNT>' + Number(line.amount) + '</AMOUNT>'; if (line.memo) xml += '<MEMO>' + esc(line.memo) + '</MEMO>'; if (line.departmentId) xml += '<DEPARTMENTID>' + esc(line.departmentId) + '</DEPARTMENTID>'; if (line.locationId) xml += '<LOCATIONID>' + esc(line.locationId) + '</LOCATIONID>'; if (line.vendorId) xml += '<VENDORID>' + esc(line.vendorId) + '</VENDORID>'; if (line.customerId) xml += '<CUSTOMERID>' + esc(line.customerId) + '</CUSTOMERID>'; if (line.projectId) xml += '<PROJECTID>' + esc(line.projectId) + '</PROJECTID>'; xml += '</ARINVOICEITEM>'; }); xml += '</ARINVOICEITEMS>'; } if (!xml && lines.length === 0) throw new Error('Provide at least one field to update.'); return xml; }>></ARINVOICE></update>")}}],outputTransform:"(sourceData) => { const response = sourceData.updateInvoice && sourceData.updateInvoice.data ? sourceData.updateInvoice.data.RESPONSE : undefined; const control = response ? response.CONTROL : undefined; const operation = response ? response.OPERATION : undefined; const authentication = operation ? operation.AUTHENTICATION : undefined; const result = operation ? operation.RESULT : undefined; const statuses = [control && control.STATUS, authentication && authentication.STATUS, result && result.STATUS].filter(Boolean).map((value) => String(value).toLowerCase()); if (statuses.includes('failure')) { const message = (result && result.ERRORMESSAGE) || (authentication && authentication.ERR ? authentication.ERR.ERRORMESSAGE : undefined) || (control && control.ERR ? control.ERR.ERRORMESSAGE : undefined); const rawErrors = message ? message.ERROR : undefined; const errors = Array.isArray(rawErrors) ? rawErrors : (rawErrors ? [rawErrors] : []); const details = errors.map((error) => [error.ERRORNO, error.DESCRIPTION2 || error.DESCRIPTION, error.CORRECTION].filter(Boolean).join(' - ')).filter(Boolean); const supportIds = errors.map((error) => error.SUPPORTID).filter(Boolean); const suffix = supportIds.length ? ` Sage support ID: ${supportIds.join(', ')}.` : ''; throw new Error(`Sage Intacct request failed${details.length ? `: ${details.join('; ')}` : '.'}${suffix}`); } const data = result ? result.DATA : undefined; const raw = data ? (data.ARINVOICE || data.arinvoice) : undefined; const record = Array.isArray(raw) ? raw[0] : raw; return { recordNo: sourceData.recordNo, record }; }"},{id:"sage-intacct-create-bill",name:"Create Sage Intacct AP bill",shortName:"Create bill",instruction:"Creates an AP bill in Sage Intacct via the XML Web Services API. Requires a vendor ID, transaction date, and at least one line item with a GL account and amount. Re-running creates another bill; it is not idempotent.",inputSchema:{type:"object",required:["lines","dateDue","vendorId","dateCreated"],properties:{lines:{type:"array",items:{type:"object",required:["glAccountNo","amount"],properties:{memo:{type:"string"},amount:{type:"number"},glAccountNo:{type:"string"},departmentId:{type:"string"},locationId:{type:"string"},vendorId:{type:"string"},customerId:{type:"string"},projectId:{type:"string"}}}},dateDue:{type:"string"},vendorId:{type:"string"},dateCreated:{type:"string"},datePosted:{type:"string"},termName:{type:"string"},description:{type:"string"}}},steps:[{id:"createBill",instruction:"Create the APBILL record with line items.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt(`<create><APBILL><<(sourceData) => { const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&apos;'); if (!sourceData.vendorId) throw new Error('vendorId is required.'); if (!sourceData.dateCreated) throw new Error('dateCreated is required (YYYY-MM-DD).'); const lines = Array.isArray(sourceData.lines) ? sourceData.lines : []; if (lines.length === 0) throw new Error('lines must contain at least one bill line.'); const match = String(sourceData.dateCreated).match(/^(\\d{4})-(\\d{2})-(\\d{2})/); const dateStr = match ? match[2] + '/' + match[3] + '/' + match[1] : sourceData.dateCreated; let xml = '<VENDORID>' + esc(sourceData.vendorId) + '</VENDORID>'; xml += '<WHENCREATED>' + esc(dateStr) + '</WHENCREATED>'; if (sourceData.datePosted) { const mp = String(sourceData.datePosted).match(/^(\\d{4})-(\\d{2})-(\\d{2})/); xml += '<WHENPOSTED>' + esc(mp ? mp[2] + '/' + mp[3] + '/' + mp[1] : sourceData.datePosted) + '</WHENPOSTED>'; } if (sourceData.dateDue) { const md = String(sourceData.dateDue).match(/^(\\d{4})-(\\d{2})-(\\d{2})/); xml += '<WHENDUE>' + esc(md ? md[2] + '/' + md[3] + '/' + md[1] : sourceData.dateDue) + '</WHENDUE>'; } else if (sourceData.termName) { xml += '<TERMNAME>' + esc(sourceData.termName) + '</TERMNAME>'; } if (sourceData.description) xml += '<DESCRIPTION>' + esc(sourceData.description) + '</DESCRIPTION>'; xml += '<APBILLITEMS>'; lines.forEach((line) => { if (!line.glAccountNo) throw new Error('Each line requires glAccountNo.'); if (line.amount == null) throw new Error('Each line requires amount.'); xml += '<APBILLITEM>'; xml += '<ACCOUNTNO>' + esc(line.glAccountNo) + '</ACCOUNTNO>'; xml += '<AMOUNT>' + Number(line.amount) + '</AMOUNT>'; if (line.memo) xml += '<MEMO>' + esc(line.memo) + '</MEMO>'; if (line.departmentId) xml += '<DEPARTMENTID>' + esc(line.departmentId) + '</DEPARTMENTID>'; if (line.locationId) xml += '<LOCATIONID>' + esc(line.locationId) + '</LOCATIONID>'; if (line.vendorId) xml += '<VENDORID>' + esc(line.vendorId) + '</VENDORID>'; if (line.customerId) xml += '<CUSTOMERID>' + esc(line.customerId) + '</CUSTOMERID>'; if (line.projectId) xml += '<PROJECTID>' + esc(line.projectId) + '</PROJECTID>'; xml += '</APBILLITEM>'; }); xml += '</APBILLITEMS>'; return xml; }>></APBILL></create>`)}}],outputTransform:"(sourceData) => { const response = sourceData.createBill && sourceData.createBill.data ? sourceData.createBill.data.RESPONSE : undefined; const control = response ? response.CONTROL : undefined; const operation = response ? response.OPERATION : undefined; const authentication = operation ? operation.AUTHENTICATION : undefined; const result = operation ? operation.RESULT : undefined; const statuses = [control && control.STATUS, authentication && authentication.STATUS, result && result.STATUS].filter(Boolean).map((value) => String(value).toLowerCase()); if (statuses.includes('failure')) { const message = (result && result.ERRORMESSAGE) || (authentication && authentication.ERR ? authentication.ERR.ERRORMESSAGE : undefined) || (control && control.ERR ? control.ERR.ERRORMESSAGE : undefined); const rawErrors = message ? message.ERROR : undefined; const errors = Array.isArray(rawErrors) ? rawErrors : (rawErrors ? [rawErrors] : []); const details = errors.map((error) => [error.ERRORNO, error.DESCRIPTION2 || error.DESCRIPTION, error.CORRECTION].filter(Boolean).join(' - ')).filter(Boolean); const supportIds = errors.map((error) => error.SUPPORTID).filter(Boolean); const suffix = supportIds.length ? ` Sage support ID: ${supportIds.join(', ')}.` : ''; throw new Error(`Sage Intacct request failed${details.length ? `: ${details.join('; ')}` : '.'}${suffix}`); } const data = result ? result.DATA : undefined; const raw = data ? (data.APBILL || data.apbill) : undefined; const record = Array.isArray(raw) ? raw[0] : raw; return { recordNo: record && record.RECORDNO ? Number(record.RECORDNO) : undefined, record }; }"},{id:"sage-intacct-update-bill",name:"Update Sage Intacct AP bill",shortName:"Update bill",instruction:"Updates an existing AP bill in Sage Intacct by record number. Only the provided fields change. Line items can be added or updated by line number.",inputSchema:{type:"object",required:["recordNo"],properties:{recordNo:{type:"integer"},description:{type:"string"},vendorId:{type:"string"},dateCreated:{type:"string"},dateDue:{type:"string"},termName:{type:"string"},lines:{type:"array",items:{type:"object",properties:{lineNo:{type:"integer"},memo:{type:"string"},amount:{type:"number"},glAccountNo:{type:"string"},departmentId:{type:"string"},locationId:{type:"string"},vendorId:{type:"string"},customerId:{type:"string"},projectId:{type:"string"}}}}}},steps:[{id:"updateBill",instruction:"Update the APBILL record by RECORDNO.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt(`<update><APBILL><RECORDNO><<(sourceData) => { const recordNo = Number(sourceData.recordNo); if (!Number.isInteger(recordNo) || recordNo <= 0) throw new Error('recordNo must be a positive integer.'); return recordNo; }>></RECORDNO><<(sourceData) => { const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&apos;'); let xml = ''; if (sourceData.vendorId) xml += '<VENDORID>' + esc(sourceData.vendorId) + '</VENDORID>'; if (sourceData.dateCreated) { const match = String(sourceData.dateCreated).match(/^(\\d{4})-(\\d{2})-(\\d{2})/); xml += '<WHENCREATED>' + esc(match ? match[2] + '/' + match[3] + '/' + match[1] : sourceData.dateCreated) + '</WHENCREATED>'; } if (sourceData.dateDue) { const md = String(sourceData.dateDue).match(/^(\\d{4})-(\\d{2})-(\\d{2})/); xml += '<WHENDUE>' + esc(md ? md[2] + '/' + md[3] + '/' + md[1] : sourceData.dateDue) + '</WHENDUE>'; } if (sourceData.termName) xml += '<TERMNAME>' + esc(sourceData.termName) + '</TERMNAME>'; if (sourceData.description) xml += '<DESCRIPTION>' + esc(sourceData.description) + '</DESCRIPTION>'; const lines = Array.isArray(sourceData.lines) ? sourceData.lines : []; if (lines.length > 0) { xml += '<APBILLITEMS>'; lines.forEach((line) => { xml += '<APBILLITEM>'; if (line.lineNo) xml += '<LINE_NO>' + Number(line.lineNo) + '</LINE_NO>'; if (line.glAccountNo) xml += '<ACCOUNTNO>' + esc(line.glAccountNo) + '</ACCOUNTNO>'; if (line.amount != null) xml += '<AMOUNT>' + Number(line.amount) + '</AMOUNT>'; if (line.memo) xml += '<MEMO>' + esc(line.memo) + '</MEMO>'; if (line.departmentId) xml += '<DEPARTMENTID>' + esc(line.departmentId) + '</DEPARTMENTID>'; if (line.locationId) xml += '<LOCATIONID>' + esc(line.locationId) + '</LOCATIONID>'; if (line.vendorId) xml += '<VENDORID>' + esc(line.vendorId) + '</VENDORID>'; if (line.customerId) xml += '<CUSTOMERID>' + esc(line.customerId) + '</CUSTOMERID>'; if (line.projectId) xml += '<PROJECTID>' + esc(line.projectId) + '</PROJECTID>'; xml += '</APBILLITEM>'; }); xml += '</APBILLITEMS>'; } if (!xml && lines.length === 0) throw new Error('Provide at least one field to update.'); return xml; }>></APBILL></update>`)}}],outputTransform:"(sourceData) => { const response = sourceData.updateBill && sourceData.updateBill.data ? sourceData.updateBill.data.RESPONSE : undefined; const control = response ? response.CONTROL : undefined; const operation = response ? response.OPERATION : undefined; const authentication = operation ? operation.AUTHENTICATION : undefined; const result = operation ? operation.RESULT : undefined; const statuses = [control && control.STATUS, authentication && authentication.STATUS, result && result.STATUS].filter(Boolean).map((value) => String(value).toLowerCase()); if (statuses.includes('failure')) { const message = (result && result.ERRORMESSAGE) || (authentication && authentication.ERR ? authentication.ERR.ERRORMESSAGE : undefined) || (control && control.ERR ? control.ERR.ERRORMESSAGE : undefined); const rawErrors = message ? message.ERROR : undefined; const errors = Array.isArray(rawErrors) ? rawErrors : (rawErrors ? [rawErrors] : []); const details = errors.map((error) => [error.ERRORNO, error.DESCRIPTION2 || error.DESCRIPTION, error.CORRECTION].filter(Boolean).join(' - ')).filter(Boolean); const supportIds = errors.map((error) => error.SUPPORTID).filter(Boolean); const suffix = supportIds.length ? ` Sage support ID: ${supportIds.join(', ')}.` : ''; throw new Error(`Sage Intacct request failed${details.length ? `: ${details.join('; ')}` : '.'}${suffix}`); } const data = result ? result.DATA : undefined; const raw = data ? (data.APBILL || data.apbill) : undefined; const record = Array.isArray(raw) ? raw[0] : raw; return { recordNo: sourceData.recordNo, record }; }"},{id:"sage-intacct-create-department",name:"Create Sage Intacct department",shortName:"Create department",instruction:"Creates a department in Sage Intacct via the XML Web Services API. Requires a department ID and title. Re-running creates another department; it is not idempotent.",inputSchema:{type:"object",required:["departmentId","title"],properties:{title:{type:"string"},departmentId:{type:"string"}}},steps:[{id:"createDepartment",instruction:"Create the DEPARTMENT record.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt(`<create><DEPARTMENT><<(sourceData) => { const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&apos;'); if (!sourceData.departmentId) throw new Error('departmentId is required.'); if (!sourceData.title) throw new Error('title is required.'); let xml = '<DEPARTMENTID>' + esc(sourceData.departmentId) + '</DEPARTMENTID>'; xml += '<TITLE>' + esc(sourceData.title) + '</TITLE>'; if (sourceData.parentId) xml += '<PARENTID>' + esc(sourceData.parentId) + '</PARENTID>'; if (sourceData.status) xml += '<STATUS>' + esc(sourceData.status) + '</STATUS>'; return xml; }>></DEPARTMENT></create>`)}}],outputTransform:"(sourceData) => { const response = sourceData.createDepartment && sourceData.createDepartment.data ? sourceData.createDepartment.data.RESPONSE : undefined; const control = response ? response.CONTROL : undefined; const operation = response ? response.OPERATION : undefined; const authentication = operation ? operation.AUTHENTICATION : undefined; const result = operation ? operation.RESULT : undefined; const statuses = [control && control.STATUS, authentication && authentication.STATUS, result && result.STATUS].filter(Boolean).map((value) => String(value).toLowerCase()); if (statuses.includes('failure')) { const message = (result && result.ERRORMESSAGE) || (authentication && authentication.ERR ? authentication.ERR.ERRORMESSAGE : undefined) || (control && control.ERR ? control.ERR.ERRORMESSAGE : undefined); const rawErrors = message ? message.ERROR : undefined; const errors = Array.isArray(rawErrors) ? rawErrors : (rawErrors ? [rawErrors] : []); const details = errors.map((error) => [error.ERRORNO, error.DESCRIPTION2 || error.DESCRIPTION, error.CORRECTION].filter(Boolean).join(' - ')).filter(Boolean); const supportIds = errors.map((error) => error.SUPPORTID).filter(Boolean); const suffix = supportIds.length ? ` Sage support ID: ${supportIds.join(', ')}.` : ''; throw new Error(`Sage Intacct request failed${details.length ? `: ${details.join('; ')}` : '.'}${suffix}`); } const data = result ? result.DATA : undefined; const raw = data ? (data.DEPARTMENT || data.department) : undefined; const record = Array.isArray(raw) ? raw[0] : raw; return { recordNo: record && record.RECORDNO ? Number(record.RECORDNO) : undefined, record }; }"},{id:"sage-intacct-update-department",name:"Update Sage Intacct department",shortName:"Update department",instruction:"Updates an existing department in Sage Intacct by record number. Only the provided fields change.",inputSchema:{type:"object",required:["recordNo"],properties:{title:{type:"string"},recordNo:{type:"integer"},parentId:{type:"string"},status:{type:"string",enum:["active","inactive"]}}},steps:[{id:"updateDepartment",instruction:"Update the DEPARTMENT record by RECORDNO.",modify:!0,config:{type:"request",systemId:"sage_intacct",url:"<<sage_intacct_url>>",method:"POST",headers:{"Content-Type":"application/xml",Accept:"application/xml"},body:bt(`<update><DEPARTMENT><RECORDNO><<(sourceData) => { const recordNo = Number(sourceData.recordNo); if (!Number.isInteger(recordNo) || recordNo <= 0) throw new Error('recordNo must be a positive integer.'); return recordNo; }>></RECORDNO><<(sourceData) => { const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&apos;'); let xml = ''; if (sourceData.title) xml += '<TITLE>' + esc(sourceData.title) + '</TITLE>'; if (sourceData.parentId) xml += '<PARENTID>' + esc(sourceData.parentId) + '</PARENTID>'; if (sourceData.status) xml += '<STATUS>' + esc(sourceData.status) + '</STATUS>'; if (!xml) throw new Error('Provide at least one field to update.'); return xml; }>></DEPARTMENT></update>`)}}],outputTransform:"(sourceData) => { const response = sourceData.updateDepartment && sourceData.updateDepartment.data ? sourceData.updateDepartment.data.RESPONSE : undefined; const control = response ? response.CONTROL : undefined; const operation = response ? response.OPERATION : undefined; const authentication = operation ? operation.AUTHENTICATION : undefined; const result = operation ? operation.RESULT : undefined; const statuses = [control && control.STATUS, authentication && authentication.STATUS, result && result.STATUS].filter(Boolean).map((value) => String(value).toLowerCase()); if (statuses.includes('failure')) { const message = (result && result.ERRORMESSAGE) || (authentication && authentication.ERR ? authentication.ERR.ERRORMESSAGE : undefined) || (control && control.ERR ? control.ERR.ERRORMESSAGE : undefined); const rawErrors = message ? message.ERROR : undefined; const errors = Array.isArray(rawErrors) ? rawErrors : (rawErrors ? [rawErrors] : []); const details = errors.map((error) => [error.ERRORNO, error.DESCRIPTION2 || error.DESCRIPTION, error.CORRECTION].filter(Boolean).join(' - ')).filter(Boolean); const supportIds = errors.map((error) => error.SUPPORTID).filter(Boolean); const suffix = supportIds.length ? ` Sage support ID: ${supportIds.join(', ')}.` : ''; throw new Error(`Sage Intacct request failed${details.length ? `: ${details.join('; ')}` : '.'}${suffix}`); } const data = result ? result.DATA : undefined; const raw = data ? (data.DEPARTMENT || data.department) : undefined; const record = Array.isArray(raw) ? raw[0] : raw; return { recordNo: sourceData.recordNo, record }; }"}]},dynamics365_sales:{bundleId:"dynamics365_sales",templateId:"dynamics365_sales",systemId:"dynamics365_sales",displayName:"Dynamics 365 Sales",description:"Read accounts, contacts and the sales pipeline from Dynamics 365 Sales.",systemUrl:"https://<<api_host>>/api/data/v9.2",credentialHint:"Set api_host to your environment host, then connect with Microsoft OAuth. Your assistant walks you through it.",requiredCredentialKeys:["api_host","access_token"],mcpServer:{name:"dynamics-sales",displayName:"Dynamics 365 Sales",description:"Accounts, contacts, opportunity pipeline and ad-hoc Dataverse queries from Dynamics 365 Sales."},installMcpServer:!0,agentLaunch:{userPrompt:"I just installed the Dynamics 365 Sales bundle. What can I do with it?",nextSteps:'Your first reply must be short: one line confirming the Dynamics MCP server is installed, then ask for their environment host in chat (like contoso.crm.dynamics.com \u2014 it is not a secret, so never collect it through a secure form; form values are redacted and you cannot read them back). When they reply, save it with tools.writeConnection passing secrets: { api_host: "<their host>" } directly, without asking for secure inputs. Then start Microsoft OAuth with connect and substitute the same host into the scopes yourself \u2014 set auth.scopes to "https://<host>/user_impersonation offline_access", never the <<api_host>> placeholder, which Microsoft rejects. OAuth fills access_token automatically; never send the user to the Connections page and never suggest the az CLI. Once connected, the MCP server is ready; offer one test run. Do not list the installed tools, do not add tips unless asked. If asked later: OAuth refresh is automatic, the query tool accepts any Dataverse entity set, and record totals above 5000 are reported as capped by Dataverse rather than exact.'},tools:[{id:"dynamics-list-accounts",name:"List Dynamics 365 accounts",shortName:"Accounts",instruction:"Lists account records from Dynamics 365 with name, account number and creation date. Supports an optional OData $filter. Useful for validating migrated accounts.",inputSchema:{type:"object",properties:{filter:{type:"string",description:`Optional OData $filter expression, e.g. "createdon gt 2026-01-01T00:00:00Z" or "contains(name,'GmbH')".`},maxResults:{type:"integer",description:"Maximum number of accounts to return in one call. Defaults to 100."}},additionalProperties:!0},steps:[{id:"fetchAccounts",instruction:"Fetch accounts from the Dataverse Web API.",config:{type:"request",systemId:"dynamics365_sales",url:"https://<<dynamics365_sales_api_host>>/api/data/v9.2/accounts",method:"GET",headers:{Authorization:"Bearer <<dynamics365_sales_access_token>>",Accept:"application/json","OData-MaxVersion":"4.0","OData-Version":"4.0","If-None-Match":"null"},queryParams:{$select:"name,accountnumber,telephone1,websiteurl,createdon,modifiedon",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchAccounts?.data ?? {}; const rows = data.value ?? []; const capped = data["@Microsoft.Dynamics.CRM.totalrecordcountlimitexceeded"] === true; return { total: capped ? null : (data["@odata.count"] ?? rows.length), totalCapped: capped, returned: rows.length, accounts: rows.map((r) => ({ id: r.accountid, name: r.name, accountNumber: r.accountnumber, phone: r.telephone1, website: r.websiteurl, createdOn: r.createdon, modifiedOn: r.modifiedon })) }; }'},{id:"dynamics-list-contacts",name:"List Dynamics 365 contacts",shortName:"Contacts",instruction:"Lists contact records from Dynamics 365 with name, email and creation date. Supports an optional OData $filter. Useful for validating migrated contacts.",inputSchema:{type:"object",properties:{filter:{type:"string",description:'Optional OData $filter expression, e.g. "emailaddress1 eq null" to find contacts missing an email.'},maxResults:{type:"integer",description:"Maximum number of contacts to return in one call. Defaults to 100."}},additionalProperties:!0},steps:[{id:"fetchContacts",instruction:"Fetch contacts from the Dataverse Web API.",config:{type:"request",systemId:"dynamics365_sales",url:"https://<<dynamics365_sales_api_host>>/api/data/v9.2/contacts",method:"GET",headers:{Authorization:"Bearer <<dynamics365_sales_access_token>>",Accept:"application/json","OData-MaxVersion":"4.0","OData-Version":"4.0","If-None-Match":"null"},queryParams:{$select:"fullname,emailaddress1,telephone1,jobtitle,createdon,modifiedon",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchContacts?.data ?? {}; const rows = data.value ?? []; const capped = data["@Microsoft.Dynamics.CRM.totalrecordcountlimitexceeded"] === true; return { total: capped ? null : (data["@odata.count"] ?? rows.length), totalCapped: capped, returned: rows.length, contacts: rows.map((r) => ({ id: r.contactid, name: r.fullname, email: r.emailaddress1, phone: r.telephone1, jobTitle: r.jobtitle, createdOn: r.createdon, modifiedOn: r.modifiedon })) }; }'},{id:"dynamics-open-opportunities",name:"List Dynamics 365 open opportunities",shortName:"Open opportunities",instruction:"Lists open opportunities from Dynamics 365 with estimated value and close date. Supports an optional additional OData $filter. Useful for pipeline verification during UAT.",inputSchema:{type:"object",properties:{filter:{type:"string",description:'Optional additional OData $filter combined with the open-state filter, e.g. "estimatedvalue gt 10000".'},maxResults:{type:"integer",description:"Maximum number of opportunities to return in one call. Defaults to 100."}},additionalProperties:!0},steps:[{id:"fetchOpportunities",instruction:"Fetch open opportunities from the Dataverse Web API.",config:{type:"request",systemId:"dynamics365_sales",url:"https://<<dynamics365_sales_api_host>>/api/data/v9.2/opportunities",method:"GET",headers:{Authorization:"Bearer <<dynamics365_sales_access_token>>",Accept:"application/json","OData-MaxVersion":"4.0","OData-Version":"4.0","If-None-Match":"null"},queryParams:{$select:"name,estimatedvalue,estimatedclosedate,createdon,statecode,_parentaccountid_value",$filter:'<<(p) => p.filter ? "statecode eq 0 and (" + p.filter + ")" : "statecode eq 0">>',$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchOpportunities?.data ?? {}; const rows = data.value ?? []; const capped = data["@Microsoft.Dynamics.CRM.totalrecordcountlimitexceeded"] === true; return { total: capped ? null : (data["@odata.count"] ?? rows.length), totalCapped: capped, returned: rows.length, opportunities: rows.map((r) => ({ id: r.opportunityid, name: r.name, estimatedValue: r.estimatedvalue, estimatedCloseDate: r.estimatedclosedate, accountId: r._parentaccountid_value, createdOn: r.createdon })) }; }'},{id:"dynamics-list-leads",name:"List Dynamics 365 leads",shortName:"Leads",instruction:"Lists lead records from Dynamics 365 with subject, name and company. Supports an optional OData $filter. Useful for validating migrated leads.",inputSchema:{type:"object",properties:{filter:{type:"string",description:'Optional OData $filter expression, e.g. "statecode eq 0" for open leads.'},maxResults:{type:"integer",description:"Maximum number of records to return in one call. Defaults to 100."}},additionalProperties:!0},steps:[{id:"fetchLeads",instruction:"Fetch leads from the Dataverse Web API.",config:{type:"request",systemId:"dynamics365_sales",url:"https://<<dynamics365_sales_api_host>>/api/data/v9.2/leads",method:"GET",headers:{Authorization:"Bearer <<dynamics365_sales_access_token>>",Accept:"application/json","OData-MaxVersion":"4.0","OData-Version":"4.0","If-None-Match":"null"},queryParams:{$select:"subject,fullname,companyname,statecode,createdon,modifiedon",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchLeads?.data ?? {}; const rows = data.value ?? []; const capped = data["@Microsoft.Dynamics.CRM.totalrecordcountlimitexceeded"] === true; return { total: capped ? null : (data["@odata.count"] ?? rows.length), totalCapped: capped, returned: rows.length, records: rows.map((r) => ({ id: r.leadid, subject: r.subject, name: r.fullname, company: r.companyname, state: r.statecode, createdOn: r.createdon, modifiedOn: r.modifiedon })) }; }'},{id:"dynamics-list-cases",name:"List Dynamics 365 cases",shortName:"Cases",instruction:"Lists case (incident) records from Dynamics 365 with title, ticket number and status. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{filter:{type:"string",description:'Optional OData $filter expression, e.g. "statecode eq 0" for active cases.'},maxResults:{type:"integer",description:"Maximum number of records to return in one call. Defaults to 100."}},additionalProperties:!0},steps:[{id:"fetchCases",instruction:"Fetch incidents from the Dataverse Web API.",config:{type:"request",systemId:"dynamics365_sales",url:"https://<<dynamics365_sales_api_host>>/api/data/v9.2/incidents",method:"GET",headers:{Authorization:"Bearer <<dynamics365_sales_access_token>>",Accept:"application/json","OData-MaxVersion":"4.0","OData-Version":"4.0","If-None-Match":"null"},queryParams:{$select:"title,ticketnumber,statecode,createdon,_customerid_value",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchCases?.data ?? {}; const rows = data.value ?? []; const capped = data["@Microsoft.Dynamics.CRM.totalrecordcountlimitexceeded"] === true; return { total: capped ? null : (data["@odata.count"] ?? rows.length), totalCapped: capped, returned: rows.length, records: rows.map((r) => ({ id: r.incidentid, title: r.title, ticketNumber: r.ticketnumber, state: r.statecode, customerId: r._customerid_value, createdOn: r.createdon })) }; }'},{id:"dynamics-list-users",name:"List Dynamics 365 users",shortName:"Users",instruction:"Lists system users from Dynamics 365 with name, email and disabled state. Useful for owner-mapping checks during migrations.",inputSchema:{type:"object",properties:{filter:{type:"string",description:'Optional OData $filter expression, e.g. "isdisabled eq false" for active users.'},maxResults:{type:"integer",description:"Maximum number of records to return in one call. Defaults to 100."}},additionalProperties:!0},steps:[{id:"fetchUsers",instruction:"Fetch systemusers from the Dataverse Web API.",config:{type:"request",systemId:"dynamics365_sales",url:"https://<<dynamics365_sales_api_host>>/api/data/v9.2/systemusers",method:"GET",headers:{Authorization:"Bearer <<dynamics365_sales_access_token>>",Accept:"application/json","OData-MaxVersion":"4.0","OData-Version":"4.0","If-None-Match":"null"},queryParams:{$select:"fullname,internalemailaddress,isdisabled,createdon",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchUsers?.data ?? {}; const rows = data.value ?? []; const capped = data["@Microsoft.Dynamics.CRM.totalrecordcountlimitexceeded"] === true; return { total: capped ? null : (data["@odata.count"] ?? rows.length), totalCapped: capped, returned: rows.length, records: rows.map((r) => ({ id: r.systemuserid, name: r.fullname, email: r.internalemailaddress, disabled: r.isdisabled, createdOn: r.createdon })) }; }'},{id:"dynamics-list-products",name:"List Dynamics 365 products",shortName:"Products",instruction:"Lists product catalog records from Dynamics 365 with name, number and state. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{filter:{type:"string",description:'Optional OData $filter expression, e.g. "statecode eq 0" for active products.'},maxResults:{type:"integer",description:"Maximum number of records to return in one call. Defaults to 100."}},additionalProperties:!0},steps:[{id:"fetchProducts",instruction:"Fetch products from the Dataverse Web API.",config:{type:"request",systemId:"dynamics365_sales",url:"https://<<dynamics365_sales_api_host>>/api/data/v9.2/products",method:"GET",headers:{Authorization:"Bearer <<dynamics365_sales_access_token>>",Accept:"application/json","OData-MaxVersion":"4.0","OData-Version":"4.0","If-None-Match":"null"},queryParams:{$select:"name,productnumber,statecode,createdon",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchProducts?.data ?? {}; const rows = data.value ?? []; const capped = data["@Microsoft.Dynamics.CRM.totalrecordcountlimitexceeded"] === true; return { total: capped ? null : (data["@odata.count"] ?? rows.length), totalCapped: capped, returned: rows.length, records: rows.map((r) => ({ id: r.productid, name: r.name, number: r.productnumber, state: r.statecode, createdOn: r.createdon })) }; }'},{id:"dynamics-query-dataverse",name:"Query any Dynamics 365 entity",shortName:"Query any entity",instruction:'Queries any Dataverse entity set. Required input: entitySet \u2014 the plural entity set name, e.g. "leads", "systemusers", "incidents". Optional inputs: select (OData $select field list), filter (OData $filter expression), maxResults (record cap, default 100). The workhorse tool for CRM migration validation and data quality checks beyond the prebuilt lists.',inputSchema:{type:"object",properties:{entitySet:{type:"string",description:'Dataverse entity set name (plural), e.g. "leads", "systemusers", "incidents".'},select:{type:"string",description:'Comma-separated OData $select field list, e.g. "subject,createdon". Omit for all fields.'},filter:{type:"string",description:"Optional OData $filter expression."},maxResults:{type:"integer",description:"Maximum number of records to return in one call. Defaults to 100."}},required:["entitySet"],additionalProperties:!0},steps:[{id:"queryEntity",instruction:"Query the requested Dataverse entity set.",config:{type:"request",systemId:"dynamics365_sales",url:"https://<<dynamics365_sales_api_host>>/api/data/v9.2/<<entitySet>>",method:"GET",headers:{Authorization:"Bearer <<dynamics365_sales_access_token>>",Accept:"application/json","OData-MaxVersion":"4.0","OData-Version":"4.0","If-None-Match":"null"},queryParams:{$select:"<<select>>",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.queryEntity?.data ?? {}; const rows = data.value ?? []; const capped = data["@Microsoft.Dynamics.CRM.totalrecordcountlimitexceeded"] === true; return { total: capped ? null : (data["@odata.count"] ?? rows.length), totalCapped: capped, returned: rows.length, records: rows }; }'}]},dynamics365_business_central:{bundleId:"dynamics365_business_central",templateId:"dynamics365_business_central",systemId:"dynamics365_business_central",displayName:"Dynamics 365 Business Central",description:"Read companies, customers, vendors and the chart of accounts from Business Central.",systemUrl:"https://api.businesscentral.dynamics.com/v2.0/<<environment>>/api/v2.0",credentialHint:"Connect your Business Central environment. Your assistant walks you through it.",requiredCredentialKeys:["environment","access_token"],oauthSignIn:!0,mcpServer:{name:"business-central",displayName:"Dynamics 365 Business Central",description:"Companies, customers, vendors, chart of accounts and ad-hoc entity queries from Business Central."},installMcpServer:!0,agentLaunch:{userPrompt:"I just installed the Dynamics 365 Business Central bundle. What can I do with it?",nextSteps:"Your first reply must be short: one line confirming the Business Central MCP server is installed, then collect the credentials. Use connect with this system's connection id and fields to save environment (their BC environment name, usually production or sandbox) and access_token; never send the user to the Connections page. Fastest token: az account get-access-token --resource https://api.businesscentral.dynamics.com. Once saved, the MCP server is ready; run the companies tool as the test, because its result contains the company id every other tool needs. Do not list the installed tools, do not add tips unless asked. If asked later: tokens expire after about an hour, so a 401 means refresh access_token; the query tool accepts any Business Central entity set like items or salesInvoices."},tools:[{id:"business-central-list-companies",name:"List Business Central companies",shortName:"Companies",instruction:"Lists the companies in the Business Central environment. Run this first: every other Business Central tool needs a companyId from this list.",inputSchema:{type:"object",properties:{},additionalProperties:!0},steps:[{id:"fetchCompanies",instruction:"Fetch the companies in this environment.",config:{type:"request",systemId:"dynamics365_business_central",url:"https://api.businesscentral.dynamics.com/v2.0/<<dynamics365_business_central_environment>>/api/v2.0/companies",method:"GET",headers:{Authorization:"Bearer <<dynamics365_business_central_access_token>>",Accept:"application/json","Data-Access-Intent":"ReadOnly"}}}],outputTransform:"(sourceData) => { const rows = sourceData.fetchCompanies?.data?.value ?? []; return { total: rows.length, companies: rows.map((r) => ({ companyId: r.id, name: r.name, displayName: r.displayName })) }; }"},{id:"business-central-list-customers",name:"List Business Central customers",shortName:"Customers",instruction:"Lists customer master records from a Business Central company. Requires a companyId from the companies tool. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{companyId:{type:"string",description:"Company id (GUID) from the companies tool."},filter:{type:"string",description:`Optional OData $filter expression, e.g. "blocked ne ''" or "contains(displayName,'GmbH')".`},maxResults:{type:"integer",description:"Maximum number of customers to return in one call. Defaults to 100."}},required:["companyId"],additionalProperties:!0},steps:[{id:"fetchCustomers",instruction:"Fetch customers for the given company.",config:{type:"request",systemId:"dynamics365_business_central",url:"https://api.businesscentral.dynamics.com/v2.0/<<dynamics365_business_central_environment>>/api/v2.0/companies(<<companyId>>)/customers",method:"GET",headers:{Authorization:"Bearer <<dynamics365_business_central_access_token>>",Accept:"application/json","Data-Access-Intent":"ReadOnly"},queryParams:{$select:"id,number,displayName,email,phoneNumber,blocked,lastModifiedDateTime",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchCustomers?.data ?? {}; const rows = data.value ?? []; return { total: data["@odata.count"] ?? rows.length, customers: rows.map((r) => ({ id: r.id, number: r.number, name: r.displayName, email: r.email, phone: r.phoneNumber, blocked: r.blocked, lastModified: r.lastModifiedDateTime })) }; }'},{id:"business-central-list-vendors",name:"List Business Central vendors",shortName:"Vendors",instruction:"Lists vendor master records from a Business Central company. Requires a companyId from the companies tool. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{companyId:{type:"string",description:"Company id (GUID) from the companies tool."},filter:{type:"string",description:"Optional OData $filter expression."},maxResults:{type:"integer",description:"Maximum number of vendors to return in one call. Defaults to 100."}},required:["companyId"],additionalProperties:!0},steps:[{id:"fetchVendors",instruction:"Fetch vendors for the given company.",config:{type:"request",systemId:"dynamics365_business_central",url:"https://api.businesscentral.dynamics.com/v2.0/<<dynamics365_business_central_environment>>/api/v2.0/companies(<<companyId>>)/vendors",method:"GET",headers:{Authorization:"Bearer <<dynamics365_business_central_access_token>>",Accept:"application/json","Data-Access-Intent":"ReadOnly"},queryParams:{$select:"id,number,displayName,email,phoneNumber,blocked,lastModifiedDateTime",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchVendors?.data ?? {}; const rows = data.value ?? []; return { total: data["@odata.count"] ?? rows.length, vendors: rows.map((r) => ({ id: r.id, number: r.number, name: r.displayName, email: r.email, phone: r.phoneNumber, blocked: r.blocked, lastModified: r.lastModifiedDateTime })) }; }'},{id:"business-central-list-accounts",name:"List Business Central chart of accounts",shortName:"Chart of accounts",instruction:"Lists general ledger accounts (the chart of accounts) from a Business Central company. Requires a companyId from the companies tool. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{companyId:{type:"string",description:"Company id (GUID) from the companies tool."},filter:{type:"string",description:`Optional OData $filter expression, e.g. "category eq 'Assets'".`},maxResults:{type:"integer",description:"Maximum number of accounts to return in one call. Defaults to 200."}},required:["companyId"],additionalProperties:!0},steps:[{id:"fetchAccounts",instruction:"Fetch general ledger accounts for the given company.",config:{type:"request",systemId:"dynamics365_business_central",url:"https://api.businesscentral.dynamics.com/v2.0/<<dynamics365_business_central_environment>>/api/v2.0/companies(<<companyId>>)/accounts",method:"GET",headers:{Authorization:"Bearer <<dynamics365_business_central_access_token>>",Accept:"application/json","Data-Access-Intent":"ReadOnly"},queryParams:{$select:"id,number,displayName,category,subCategory,blocked,accountType",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 200>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchAccounts?.data ?? {}; const rows = data.value ?? []; return { total: data["@odata.count"] ?? rows.length, accounts: rows.map((r) => ({ id: r.id, number: r.number, name: r.displayName, category: r.category, subCategory: r.subCategory, type: r.accountType, blocked: r.blocked })) }; }'},{id:"business-central-list-items",name:"List Business Central items",shortName:"Items",instruction:"Lists item (product) master records from a Business Central company. Requires a companyId from the companies tool. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{companyId:{type:"string",description:"Company id (GUID) from the companies tool."},filter:{type:"string",description:`Optional OData $filter expression, e.g. "type eq 'Inventory'".`},maxResults:{type:"integer",description:"Maximum number of items to return in one call. Defaults to 100."}},required:["companyId"],additionalProperties:!0},steps:[{id:"fetchItems",instruction:"Fetch items for the given company.",config:{type:"request",systemId:"dynamics365_business_central",url:"https://api.businesscentral.dynamics.com/v2.0/<<dynamics365_business_central_environment>>/api/v2.0/companies(<<companyId>>)/items",method:"GET",headers:{Authorization:"Bearer <<dynamics365_business_central_access_token>>",Accept:"application/json","Data-Access-Intent":"ReadOnly"},queryParams:{$select:"id,number,displayName,type,unitPrice,inventory,blocked,lastModifiedDateTime",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchItems?.data ?? {}; const rows = data.value ?? []; return { total: data["@odata.count"] ?? rows.length, items: rows.map((r) => ({ id: r.id, number: r.number, name: r.displayName, type: r.type, unitPrice: r.unitPrice, inventory: r.inventory, blocked: r.blocked })) }; }'},{id:"business-central-list-sales-invoices",name:"List Business Central sales invoices",shortName:"Sales invoices",instruction:"Lists sales invoices from a Business Central company with customer, total and status. Requires a companyId from the companies tool. Supports an optional OData $filter.",inputSchema:{type:"object",properties:{companyId:{type:"string",description:"Company id (GUID) from the companies tool."},filter:{type:"string",description:`Optional OData $filter expression, e.g. "status eq 'Open'".`},maxResults:{type:"integer",description:"Maximum number of invoices to return in one call. Defaults to 100."}},required:["companyId"],additionalProperties:!0},steps:[{id:"fetchSalesInvoices",instruction:"Fetch sales invoices for the given company.",config:{type:"request",systemId:"dynamics365_business_central",url:"https://api.businesscentral.dynamics.com/v2.0/<<dynamics365_business_central_environment>>/api/v2.0/companies(<<companyId>>)/salesInvoices",method:"GET",headers:{Authorization:"Bearer <<dynamics365_business_central_access_token>>",Accept:"application/json","Data-Access-Intent":"ReadOnly"},queryParams:{$select:"id,number,customerName,invoiceDate,totalAmountIncludingTax,currencyCode,status",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchSalesInvoices?.data ?? {}; const rows = data.value ?? []; return { total: data["@odata.count"] ?? rows.length, invoices: rows.map((r) => ({ id: r.id, number: r.number, customer: r.customerName, date: r.invoiceDate, total: r.totalAmountIncludingTax, currency: r.currencyCode, status: r.status })) }; }'},{id:"business-central-list-gl-entries",name:"List Business Central general ledger entries",shortName:"GL entries",instruction:"Lists general ledger entries from a Business Central company with account, amounts and posting date. Requires a companyId from the companies tool. Filter by postingDate to verify opening balances at cutover.",inputSchema:{type:"object",properties:{companyId:{type:"string",description:"Company id (GUID) from the companies tool."},filter:{type:"string",description:'Optional OData $filter expression, e.g. "postingDate ge 2026-01-01".'},maxResults:{type:"integer",description:"Maximum number of entries to return in one call. Defaults to 200."}},required:["companyId"],additionalProperties:!0},steps:[{id:"fetchGLEntries",instruction:"Fetch general ledger entries for the given company.",config:{type:"request",systemId:"dynamics365_business_central",url:"https://api.businesscentral.dynamics.com/v2.0/<<dynamics365_business_central_environment>>/api/v2.0/companies(<<companyId>>)/generalLedgerEntries",method:"GET",headers:{Authorization:"Bearer <<dynamics365_business_central_access_token>>",Accept:"application/json","Data-Access-Intent":"ReadOnly"},queryParams:{$select:"id,entryNumber,postingDate,documentNumber,accountNumber,description,debitAmount,creditAmount",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 200>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.fetchGLEntries?.data ?? {}; const rows = data.value ?? []; return { total: data["@odata.count"] ?? rows.length, entries: rows.map((r) => ({ entryNumber: r.entryNumber, postingDate: r.postingDate, document: r.documentNumber, account: r.accountNumber, description: r.description, debit: r.debitAmount, credit: r.creditAmount })) }; }'},{id:"business-central-query-entity",name:"Query any Business Central entity",shortName:"Query any entity",instruction:"Queries any Business Central entity set by name (for example items, salesInvoices, generalLedgerEntries) within a company, with optional OData $select and $filter. The workhorse tool for migration validation beyond the prebuilt lists.",inputSchema:{type:"object",properties:{companyId:{type:"string",description:"Company id (GUID) from the companies tool."},entitySet:{type:"string",description:'Business Central entity set name, e.g. "items", "salesInvoices", "generalLedgerEntries".'},select:{type:"string",description:"Comma-separated OData $select field list. Omit for all fields."},filter:{type:"string",description:"Optional OData $filter expression."},maxResults:{type:"integer",description:"Maximum number of records to return in one call. Defaults to 100."}},required:["companyId","entitySet"],additionalProperties:!0},steps:[{id:"queryEntity",instruction:"Query the requested entity set for the given company.",config:{type:"request",systemId:"dynamics365_business_central",url:"https://api.businesscentral.dynamics.com/v2.0/<<dynamics365_business_central_environment>>/api/v2.0/companies(<<companyId>>)/<<entitySet>>",method:"GET",headers:{Authorization:"Bearer <<dynamics365_business_central_access_token>>",Accept:"application/json","Data-Access-Intent":"ReadOnly"},queryParams:{$select:"<<select>>",$filter:"<<filter>>",$top:"<<(p) => p.maxResults ?? 100>>",$count:"true"}}}],outputTransform:'(sourceData) => { const data = sourceData.queryEntity?.data ?? {}; const rows = data.value ?? []; return { total: data["@odata.count"] ?? rows.length, records: rows }; }'}]},netsuite:{bundleId:"netsuite",templateId:"netsuite",systemId:Jd,displayName:"NetSuite",description:"Install a NetSuite system, ten read/query tools, fourteen write tools and a native integration playbook.",systemUrl:"https://{accountId}.suitetalk.api.netsuite.com/services/rest",credentialHint:"Connects through your own NetSuite integration record with OAuth 2.0. Your assistant asks for the account ID and the integration record's client ID and secret, then opens the NetSuite sign-in.",requiredCredentialKeys:["access_token"],oauthSignIn:!0,mcpServer:{name:"netsuite",displayName:"NetSuite",description:"Chart of accounts, customers, vendors, journal entries, invoices, vendor bills, subsidiaries and dimensions from NetSuite, SuiteQL queries and record lookups, plus create and update tools for journal entries, vendors, customers, GL accounts, invoices, vendor bills and departments."},installMcpServer:!1,playbook:{id:"netsuite-native-integration",name:"NetSuite Native Integration",whenToRun:"Use when connecting, validating, querying or extending a NetSuite integration through REST Web Services and SuiteQL.",inputs:"A NetSuite connection with an OAuth sign-in; the record type or business process to work with; subsidiary scope for OneWorld accounts; validation criteria and desired output.",instructions:"Use the installed read-only tools for the chart of accounts, customers, vendors, journal entry lines, invoices, vendor bills, departments, subsidiaries, classes and locations. Use the SuiteQL query tool for any other record type, join or aggregate, and the get-record tool to inspect one record in full. Use the installed create and update tools for journal entries, vendors, customers, GL accounts, invoices, vendor bills and departments only after the user explicitly confirms the exact records to write; the create tools are not idempotent and re-running them duplicates records. Reference other records by internal ID from the list tools, and pass a subsidiary on OneWorld accounts. Surface NetSuite error details (o:errorDetails) as failures. For other record types or operations, inspect the account's metadata catalog, create separate least-privilege tools, validate them in a sandbox account and require explicit user confirmation before modifying NetSuite data.",completionCriteria:"The requested NetSuite data, write result or validation result is returned; subsidiary scope is correct; NetSuite errors are surfaced as failures with their details; no NetSuite data is modified unless the user explicitly requested and confirmed the write."},agentLaunch:{userPrompt:"I just installed the NetSuite integration. What can I do with it?",nextSteps:`Your first reply must be short: one line confirming the NetSuite integration and native integration playbook are installed. If the user already has a NetSuite connection with an OAuth sign-in under this system id, offer one read-only test run and stop. Otherwise connect it in this order. 1) Ask in chat for the NetSuite account ID (Setup > Company > Company Information, like 1234567 or 1234567_SB1 for a sandbox; it is not a secret). 2) Build the host from it in lowercase with "_" replaced by "-" (1234567_SB1 becomes 1234567-sb1). 3) Call connect with this system id, the user's existing NetSuite connection id if one exists, url https://<host>.suitetalk.api.netsuite.com/services/rest, and auth type oauth2 with oauthClientMode custom, authUrl https://<host>.app.netsuite.com/app/login/oauth2/authorize.nl and tokenUrl https://<host>.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token. Confirm no {accountId} remains in url, authUrl, or tokenUrl before calling it. If /org/oauth-apps/ lists an app for this NetSuite account, pass its oauthAppId; otherwise the card collects the client ID and client secret of their NetSuite integration record and then runs the OAuth sign-in. If they have no integration record yet, explain before calling connect: Setup > Integration > Manage Integrations > New, enable Authorization Code Grant with the REST Web Services and RESTlets scopes, set the redirect URI to the superglue OAuth callback URL exactly, and copy the client ID and secret shown once after saving; the NetSuite role needs REST Web Services and Log in using OAuth 2.0 Access Tokens permissions. Once connected, the integration is ready; offer one read-only test run. Do not list the installed tools or add tips unless asked. If asked later: the sign-in lasts seven days and a 401 means signing in again through connect with the connection id; the SuiteQL tool reads any record type; the installed create and update tools modify NetSuite data, so run them only after the user confirms the exact records to write.`},tools:dhe}};ho.bundles={...eS,sage_intacct_mcp:{...eS.sage_intacct,bundleId:"sage_intacct_mcp",description:"Install the Sage Intacct integration and an OAuth-protected MCP server for its read/query and write tools.",installMcpServer:!0},netsuite_mcp:{...eS.netsuite,bundleId:"netsuite_mcp",description:"Install the NetSuite integration and an OAuth-protected MCP server for its read/query and write tools.",installMcpServer:!0}};function Ahe({bundle:t,install:e}){let r=e.tools.map(s=>` - ${s.id}${s.name?` (${s.name})`:""}`).join(`
114
114
  `),n=e.system.requiredCredentialKeys.join(", "),i=e.mcpServer?[` - MCP server: ${e.mcpServer.name} (id: ${e.mcpServer.id})`,"","Silently load the connections and tool-deployment skills before replying. Do not narrate the skill loads.","","The MCP server card is already visible in this conversation with the server URL, its tools, and the client export options for Claude, Cursor, Langdock and curl. Do not describe or reproduce client setup in prose; point at the card."]:["","Silently load the connections skill before replying. Do not narrate the skill load."],o=[`The user just installed the "${t.displayName}" ${e.mcpServer?"MCP server and integration":"integration"} from the superglue website. Everything below already exists. Do not create, rebuild or duplicate any of it.`,"","Installed:",` - System ID: ${e.system.id} (${e.system.name}) at ${t.systemUrl}`," - Tools:",r,e.playbook?` - Playbook: ${e.playbook.name} (id: ${e.playbook.id})`:void 0,...i,"",e.system.hasUserCredentials?t.demoCredentials?"The connection is preloaded with shared demo secrets, so every tool works right now without any setup.":"The user already has a connection with every required secret.":`The user has no connection with every required secret yet, so no tool will run until the user adds the missing values. Required secret names: ${n}. ${t.credentialHint}`,t.agentLaunch.nextSteps,"","The user already saw this inventory on the install screen. Do not repeat it back to them."];return{userPrompt:t.agentLaunch.userPrompt,hiddenStarterMessage:o.filter(s=>s!==void 0).join(`
115
115
  `)}}function phe(t){return typeof t!="string"||!Object.prototype.hasOwnProperty.call(ho.bundles,t)?null:ho.bundles[t]}function fhe(){return Object.values(ho.bundles)}});var OL=m(Pg=>{"use strict";Object.defineProperty(Pg,"__esModule",{value:!0});Pg.chatVisualArtifactTitle=kL;Pg.chatVisualToArtifactHtml=whe;var Vr=eh(),DL=120,hhe={stats:"Key numbers",chart:"Chart",flow:"Flow",steps:"Steps",table:"Table",mapping:"Field mapping",migration:"Migration status",reconcile:"Reconciliation",timeline:"Timeline",cards:"Overview",diagram:"Diagram",image:"Images",callout:"Note",custom:"Visual",lesson:"Lesson"},ghe={success:"sg-success",failed:"sg-error",warning:"sg-warning",running:"sg-info"},mhe={positive:"sg-success",negative:"sg-error",warning:"sg-warning",neutral:""},yhe={info:"",success:"sg-success",warning:"sg-warning",error:"sg-error"},Ehe=["main{max-width:960px;margin:0 auto;padding:32px 24px}","h1{margin:0 0 6px}","h2{margin:28px 0 10px}",".sg-visual-caption{margin:0 0 24px}",".sg-visual-body{overflow-wrap:break-word}",".sg-visual-body pre{white-space:pre-wrap;background:var(--sg-surface);border:1px solid var(--sg-line);border-radius:var(--sg-radius);padding:12px 14px}",".sg-card h3{margin:0 0 4px;font-size:1rem}",".sg-card p{margin:4px 0 0}"].join("");function se(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function xg(t){return se(t).replace(/`([^`]+)`/g,"<code>$1</code>").replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>").replace(/(^|[^*\w])\*([^*\s][^*]*)\*/g,"$1<em>$2</em>").replace(/\[([^\]]+)\]\((https:\/\/[^\s)]+)\)/g,'<a href="$2">$1</a>')}function Lg(t){return t.trim().split(/\n\s*\n/).map(e=>{let r=e.split(`
@@ -1073,7 +1073,7 @@ ${u.map(l=>`- \`${l}\``).join(`
1073
1073
 
1074
1074
  post({ type: "ready" });
1075
1075
  })();`});var WP=m(de=>{"use strict";Object.defineProperty(de,"__esModule",{value:!0});de.RESERVED_ROLE_NAMES=de.RESERVED_ROLE_IDS=de.PREDEFINED_ROLE_IDS=void 0;de.toResourceRef=tA;de.toWildcardResourceRef=rA;de.getDefaultMemberResourceGrants=Tye;de.parseResourceRef=nA;de.getWildcardResourceRef=xS;de.normalizeResourcePermissions=Ps;de.permissionSatisfies=em;de.highestResourcePermission=tm;de.grantHasPermission=rm;de.grantMatchesResource=_u;de.getEffectiveResourcePermissions=MS;de.hasResourcePermission=Dye;de.getRoleResourceGrants=nm;de.hasImplicitAdminResourceAccess=LS;de.getAllowedResourceIds=jP;de.getAllowedResourceIdsForRoles=PS;de.getEffectiveResourcePermissionsForRoles=iA;de.getAllowedToolIds=zP;de.pickLongestHeldResource=Nye;de.getAllowedCredentialsIds=kye;de.getEffectiveCredentialsPermissions=Oye;de.getEffectiveToolPermissions=Uye;de.checkResourcePermission=$S;de.isToolAllowed=xye;de.isPlaybookVisible=Mye;de.hasAllTools=Lye;de.getResourceGrantSources=HP;de.getSharePermissionForResource=qP;de.getAccessRulePermissionForResource=FS;de.getAccessRuleScopeForResource=GP;de.hasAdminBaseRole=jS;de.resolveResourceAccessForRoles=Pye;de.normalizeResourceGrantInput=YP;de.normalizeRoleResourceGrantInput=$ye;de.isPredefinedRole=Fye;de.isReservedRoleId=jye;de.isReservedRoleName=zye;de.hasRole=Hye;de.getRoleIds=qye;de.getBaseRole=VP;de.getBaseRoleId=Gye;de.getPersonalRole=JP;de.getPersonalRoleId=Yye;var Kg=wg(),Xg="*";function tA(t,e){if(!e||e===Xg)throw new Error("Resource id is required");return`${t}:${encodeURIComponent(e)}`}function rA(t){return`${t}:${Xg}`}function Tye(){return Kg.RESOURCE_KINDS.flatMap(t=>{let e=(0,Kg.getResourceDefinition)(t).memberDefaultPermission;return e?[{resourceRef:rA(t),permissions:[e]}]:[]})}function nA(t){let e=t.indexOf(":");if(e<=0)return null;let r=t.slice(0,e);if(!(0,Kg.isResourceKind)(r))return null;let n=t.slice(e+1);if(!n)return null;if(n===Xg)return{kind:r,id:Xg,isWildcard:!0};try{return{kind:r,id:decodeURIComponent(n),isWildcard:!1}}catch{return null}}function xS(t){let e=nA(t);return e?rA(e.kind):null}function Ps(t){let e=new Set;for(let r of t||[])(r==="viewer"||r==="editor")&&e.add(r);return e.has("editor")&&e.add("viewer"),Array.from(e)}function em(t,e){return t===e||t==="editor"&&e==="viewer"}function tm(t){let e=Ps(t);if(e.includes("editor"))return"editor";if(e.includes("viewer"))return"viewer"}function rm(t,e){return t.revokedAt?!1:Ps(t.permissions).some(r=>em(r,e))}function _u(t,e){return t.revokedAt?!1:t.resourceRef===e||t.resourceRef===xS(e)}function MS(t,e){let r=new Set;for(let n of t)if(_u(n,e))for(let i of Ps(n.permissions))r.add(i);return Array.from(r)}function Dye(t,e,r){return MS(t,e).some(n=>em(n,r))}function nm(t){return t.flatMap(e=>jS([e])?(e.resourceGrants||[]).filter(r=>nA(r.resourceRef)?.kind==="credential"):e.resourceGrants||[])}function LS(t,e){return e!=="credential"&&jS(t)}function jP(t,e,r){let n=rA(e),i=new Set;for(let o of t){if(!rm(o,r))continue;if(o.resourceRef===n)return;let s=nA(o.resourceRef);s?.kind===e&&!s.isWildcard&&i.add(s.id)}return Array.from(i)}function PS(t,e,r){if(!LS(t,e))return jP(nm(t),e,r)}function iA(t,e,r){return LS(t,e)?["editor","viewer"]:MS(nm(t),tA(e,r))}function Rye(t){return(0,Kg.getResourceDefinition)(t).label}function zP(t,e="viewer"){return PS(t,"tool",e)}var US=Number.MAX_SAFE_INTEGER;function OS(t){if(!t)return US;let e=new Date(t).getTime();return Number.isNaN(e)?US:e}function Nye(t,e,r){if(t.length<=1)return t[0];let n=i=>{let o=tA(r,i.id),s=US;for(let a of e)_u(a,o)&&(s=Math.min(s,OS(a.createdAt)));return s};return[...t].sort((i,o)=>{let s=n(i)-n(o);return s!==0?s:OS(i.createdAt)-OS(o.createdAt)})[0]}function kye(t,e="viewer"){return PS(t,"credential",e)}function Oye(t,e){return iA(t,"credential",e)}function Uye(t,e){return iA(t,"tool",e)}function $S(t,e,r,n){return iA(t,e,r).some(o=>em(o,n))?{allowed:!0}:{allowed:!1,error:`${Rye(e)} '${r}' requires a '${n}' grant`}}function xye(t,e,r="viewer"){return $S(t,"tool",e,r)}function Mye(t,e,r="viewer"){return $S(t,"playbook",e,r)}function Lye(t,e="viewer"){return zP(t,e)===void 0}function HP(t,e,r="viewer"){let n=new Set;for(let i of t)_u(i,e)&&rm(i,r)&&n.add(i.source);return Array.from(n)}function qP(t,e){let r=t.filter(n=>n.source==="share"&&_u(n,e)).flatMap(n=>Ps(n.permissions));return tm(r)}function FS(t,e){let r=t.filter(n=>n.source==="access_rule"&&_u(n,e)).flatMap(n=>Ps(n.permissions));return tm(r)}function GP(t,e){let r=FS(t,e);return r?t.some(i=>i.source==="access_rule"&&i.resourceRef===xS(e)&&rm(i,r))?"all":"resource":void 0}function jS(t){return t.some(e=>e.isBaseRole&&e.id==="admin")}function Pye({roles:t,resource:e,userId:r}){let n=tA(e.kind,e.id),i=nm(t),o=new Set(iA(t,e.kind,e.id)),s=new Set(HP(i,n));e.ownerUserId&&e.ownerUserId===r&&(o.add("editor"),o.add("viewer"),s.add("ownership"));let a=Ps(Array.from(o));return{permissions:a,sources:Array.from(s),sharePermission:qP(i,n),accessRulePermission:FS(i,n),accessRuleScope:GP(i,n),maxPermission:tm(a)}}function YP(t){let e=nA(t.resourceRef);if(!e)throw new Error(`Invalid resource ref '${t.resourceRef}'`);return{...t,resourceRef:e.isWildcard?rA(e.kind):tA(e.kind,e.id),permissions:Ps(t.permissions||["viewer"]),source:t.source||"access_rule"}}function $ye(t){let e=YP({resourceRef:t.resourceRef,permissions:t.permissions,source:"access_rule"});return{resourceRef:e.resourceRef,permissions:e.permissions,source:"access_rule"}}de.PREDEFINED_ROLE_IDS=["admin","member","service_account"];de.RESERVED_ROLE_IDS=["admin","member","service_account"];de.RESERVED_ROLE_NAMES=["member","admin","service account"];function Fye(t){return de.PREDEFINED_ROLE_IDS.includes(t)}function jye(t){return de.RESERVED_ROLE_IDS.includes(t)}function zye(t){return de.RESERVED_ROLE_NAMES.includes(t.toLowerCase().trim())}function Hye(t,e){return t.some(r=>r.id===e)}function qye(t){return t.map(e=>e.id)}function VP(t){let e=t.filter(r=>r.isBaseRole);return e.length===1?e[0]:null}function Gye(t){let e=VP(t);return e?e.id:null}function JP(t){return t.find(e=>e.isPersonalRole)||null}function Yye(t){let e=JP(t);return e?e.id:null}});var KP=m(Kr=>{"use strict";Object.defineProperty(Kr,"__esModule",{value:!0});Kr.NOTIFICATION_EXCLUDED_REQUEST_SOURCES=Kr.CLIENT_REQUEST_SOURCES=Kr.REQUEST_SOURCES=void 0;Kr.isRequestSource=ZP;Kr.isClientRequestSource=Wye;Kr.parseRequestSource=Zye;var hr=Lr();Kr.REQUEST_SOURCES=[hr.RequestSource.API,hr.RequestSource.FRONTEND,hr.RequestSource.AGENT,hr.RequestSource.SCHEDULER,hr.RequestSource.MCP,hr.RequestSource.TOOL_CHAIN,hr.RequestSource.WEBHOOK,hr.RequestSource.CLI];Kr.CLIENT_REQUEST_SOURCES=[hr.RequestSource.FRONTEND,hr.RequestSource.AGENT,hr.RequestSource.MCP,hr.RequestSource.CLI];Kr.NOTIFICATION_EXCLUDED_REQUEST_SOURCES=[hr.RequestSource.FRONTEND,hr.RequestSource.AGENT,hr.RequestSource.MCP];var Vye=new Set(Kr.REQUEST_SOURCES),Jye=new Set(Kr.CLIENT_REQUEST_SOURCES);function ZP(t){return Vye.has(t)}function Wye(t){return Jye.has(t)}function Zye(t){let e=t.toLowerCase();return ZP(e)?e:void 0}});var i$=m(zS=>{"use strict";Object.defineProperty(zS,"__esModule",{value:!0});zS.readOnlyRequestRejection=pEe;var im=Rn(),wt="Nothing ran. Put the call in your plan instead.",XP=new Set(["GET","HEAD","OPTIONS"]),e$=new Set(["select","with","show","explain","describe","desc","table","values"]),Kye=/\b(insert|update|delete|merge|upsert|drop|create|alter|truncate|grant|revoke|copy|call|exec|execute|lock|vacuum|analyze|reindex|refresh|set|into|do|comment|prepare|deallocate|listen|notify|unlisten|discard|cluster|import|load|attach|detach|pragma|backup|restore|bulk)\b|\b(sp_|xp_)\w+/,Xye=new Set(["BITCOUNT","BITPOS","DBSIZE","ECHO","EXISTS","GEODIST","GEOPOS","GEOSEARCH","GET","GETBIT","GETRANGE","HEXISTS","HGET","HGETALL","HKEYS","HLEN","HMGET","HRANDFIELD","HSCAN","HSTRLEN","HVALS","INFO","JSON.GET","JSON.MGET","JSON.OBJKEYS","JSON.TYPE","KEYS","LINDEX","LLEN","LPOS","LRANGE","MEMORY","MGET","OBJECT","PFCOUNT","PING","PTTL","RANDOMKEY","SCAN","SCARD","SDIFF","SINTER","SINTERCARD","SISMEMBER","SMEMBERS","SMISMEMBER","SRANDMEMBER","SSCAN","STRLEN","SUNION","TIME","TTL","TYPE","XINFO","XLEN","XRANGE","XREVRANGE","ZCARD","ZCOUNT","ZDIFF","ZINTER","ZINTERCARD","ZLEXCOUNT","ZMSCORE","ZRANDMEMBER","ZRANGE","ZRANGEBYLEX","ZRANGEBYSCORE","ZRANK","ZREVRANGE","ZREVRANGEBYLEX","ZREVRANGEBYSCORE","ZREVRANK","ZSCAN","ZSCORE","ZUNION"]),eEe=new Set(["aggregate","countDocuments","distinct","estimatedDocumentCount","find","findOne","listCollections"]),tEe=new Set(["$out","$merge"]),t$=new Set(["list","get","exists","stat"]);function sm(t){if(!(!t||!t.trim()))try{return JSON.parse(t)}catch{return}}function om(t){return Array.isArray(t)?t:[t]}var rEe=/\b(nextval|setval|pg_advisory_\w*|pg_try_advisory_\w*|lo_\w+|dblink\w*|pg_terminate_backend|pg_cancel_backend|pg_reload_conf|pg_rotate_logfile|set_config|pg_notify|pg_sleep\w*|txid_current)\s*\(/;function nEe(t){let e=[],r="",n=0;for(;n<t.length;){let i=t[n],o=t[n+1];if(i==="-"&&o==="-"){let s=t.indexOf(`
1076
- `,n);n=s===-1?t.length:s,r+=" ";continue}if(i==="/"&&o==="*"){let s=t.indexOf("*/",n+2);if(s===-1)return{statements:e,unterminated:!0};n=s+2,r+=" ";continue}if(i==="'"||i==='"'||i==="`"||i==="["){let s=i==="["?"]":i,a=n+1;for(;a<t.length;){if(t[a]===s){if(t[a+1]===s&&s!=="]"){a+=2;continue}break}a+=1}if(a>=t.length)return{statements:e,unterminated:!0};r+=i==="'"?"''":'""',n=a+1;continue}if(i==="$"){let s=t.slice(n).match(/^\$[A-Za-z_]*\$/)?.[0];if(s){let a=t.indexOf(s,n+s.length);if(a===-1)return{statements:e,unterminated:!0};r+="''",n=a+s.length;continue}}if(i===";"){e.push(r),r="",n+=1;continue}r+=i,n+=1}return e.push(r),{statements:e.map(i=>i.replace(/\s+/g," ").trim()).filter(Boolean),unterminated:!1}}function iEe(t){let e=sm(t),r=typeof e?.query=="string"?e.query:void 0;if(!r)return`This read-only run cannot send a query it cannot read. Send the statement as {"query": "SELECT ..."}. ${wt}`;let{statements:n,unterminated:i}=nEe(r);if(i)return`This read-only run cannot check a statement with an unterminated quote or comment. ${wt}`;if(n.length>1)return`This read-only run allows one statement per call. ${wt}`;let s=(n[0]??"").toLowerCase(),a=s.replace(/^[(\s]+/,"").split(/[\s(]/)[0]??"";if(!e$.has(a))return`This read-only run allows only ${[...e$].join(", ").toUpperCase()} statements, not ${a.toUpperCase()||"this statement"}. ${wt}`;let c=s.match(Kye)??s.match(rEe);return c?`This read-only run refuses the statement because of "${c[0].replace(/\s*\($/,"").toUpperCase()}". ${wt}`:null}function oEe(t){let e=om(sm(t));for(let r of e){let n=typeof r?.command=="string"?r.command.trim():"";if(!n)return`This read-only run cannot send a command it cannot read. Send {"command": "GET", "args": [...]}. ${wt}`;if(!Xye.has(n.toUpperCase()))return`This read-only run refuses the Redis command ${n.toUpperCase()}, which is not a known read command. ${wt}`}return null}function sEe(t){let e=om(sm(t));for(let r of e){let n=typeof r?.operation=="string"?r.operation.trim():"";if(!n)return`This read-only run cannot send an operation it cannot read. Send {"operation": "find", ...}. ${wt}`;if(!eEe.has(n))return`This read-only run refuses the MongoDB operation ${n}, which writes. ${wt}`;for(let i of om(r?.pipeline))for(let o of Object.keys(i??{}))if(tEe.has(o))return`This read-only run refuses an aggregation with ${o}, which writes. ${wt}`}return null}function aEe(t,e){let r=om(sm(e));for(let n of r){let i=typeof n?.operation=="string"?n.operation.trim():"";if(!i)return`This read-only run cannot send an operation it cannot read. Send {"operation": "list", ...}. ${wt}`;if(!t$.has(i))return`This read-only run allows only ${[...t$].join(", ")} on ${t}, not ${i}. ${wt}`}return null}function cEe(t){let e=[t.url,t.body??"",...Object.entries(t.headers??{}).flatMap(([n,i])=>[n,i])],r=[];for(let n of e)for(let i of n.matchAll(/<<([\s\S]*?)>>/g)){let o=i[1].trim();o&&r.push(o)}return r}var uEe=new Set(["x-http-method-override","x-http-method","x-method-override"]);function n$(t){let e=t.match(/^([a-z][a-z0-9+.-]*):\/\/([^/?#]*)/i);if(!e)return null;let r=e[2];return{scheme:e[1].toLowerCase(),host:r.slice(r.lastIndexOf("@")+1).toLowerCase()}}function r$(t,e){return t.split(`<<${e.toLowerCase()}_`).join("<<")}function lEe(t){return t.systemId&&t.systemUrl?t.url.split(`<<${t.systemId}_url>>`).join(t.systemUrl):t.url}function dEe(t,e){let r=cEe(t);if(r.length===0)return null;let n=r.find(o=>o.startsWith("sg_auth"));if(n)return`This read-only run cannot send your identity token <<${n}>>. ${wt}`;let i=t.systemUrl?n$(t.systemUrl):null;return!t.systemId||!i||i.scheme!==e.scheme||r$(e.host,t.systemId)!==r$(i.host,t.systemId)?`This read-only run sends secrets only to the address of the system they belong to. Use <<${t.systemId??"systemId"}_url>> as the start of the URL. ${wt}`:null}function AEe(t){let e=Object.keys(t.headers??{}).find(n=>uEe.has(n.toLowerCase())),r=/[?&](_method|x-http-method-override)=/i.test(t.url);return e||r?`This read-only run cannot override the HTTP method. ${wt}`:null}function pEe(t){let e=lEe(t),r=n$(e);if(!r)return`This read-only run cannot check a URL whose address is not known before secrets are resolved. Start the URL with a scheme and host, or with <<systemId_url>>. ${wt}`;let n=(0,im.inferProtocolFromUrl)(e);if(t.protocol&&t.protocol!==n)return`This read-only run refuses protocol ${t.protocol} for a ${n} URL. ${wt}`;if(n==="http"&&r.scheme!=="http"&&r.scheme!=="https")return`This read-only run cannot use the ${r.scheme} scheme. ${wt}`;let i=dEe(t,r);if(i)return i;switch(n){case"http":{if((0,im.isNetSuiteRestletUrl)(e))return`This read-only run cannot call a NetSuite RESTlet, because RESTlet code can change the account on any method. ${wt}`;let o=(t.method||"GET").toUpperCase();return XP.has(o)?AEe(t):`This read-only run allows only ${[...XP].join(", ")} requests, not ${o}. ${wt}`}case"postgres":case"mssql":case"odbc":return iEe(t.body);case"redis":return oEe(t.body);case"mongodb":return sEe(t.body);case"sftp":case"smb":return aEe(n,t.body);case"suitecloud":return(0,im.isSuiteCloudWrite)({url:e,body:t.body})?`This read-only run allows only SuiteCloud listObjects, importObjects, listFiles, importFiles, validate, and preview, not ${(0,im.getSuiteCloudOperation)(t.body)??"an unknown operation"}. ${wt}`:null;default:return`This read-only run cannot use the ${n} protocol. ${wt}`}}});var o$=m(vu=>{"use strict";Object.defineProperty(vu,"__esModule",{value:!0});vu.PREPARABLE_TASK_STATUSES=vu.TASK_PREPARATION_STATES=void 0;vu.TASK_PREPARATION_STATES=["queued","preparing","ready","failed","started"];vu.PREPARABLE_TASK_STATUSES=["not_started","waiting"]});var s$=m(am=>{"use strict";Object.defineProperty(am,"__esModule",{value:!0});am.contextSourceTemplates=void 0;var fEe={slack:{category:"workspace",systemId:"slack",onboardingOrder:7,onboardingDescription:"Connect joined public channels so superglue can use relevant workspace context."},gmail:{category:"email",systemId:"gmail",onboardingOrder:9,onboardingDescription:"Let superglue access your gmail inbox. superglue will never send emails on your behalf."},fathomMcp:{category:"meetings",systemId:"fathomMcp",onboardingOrder:4,onboardingDescription:"Let superglue use meeting notes and transcripts. superglue will never join or record meetings."},granolaMcp:{category:"meetings",systemId:"granolaMcp",onboardingOrder:2,onboardingDescription:"Let superglue use notes and transcripts. superglue will never join or record meetings."},readAiMcp:{category:"meetings",systemId:"read-ai",onboardingOrder:6,onboardingDescription:"Let superglue use meeting summaries and transcripts. superglue will never join or record meetings."},otterMcp:{category:"meetings",systemId:"otter",onboardingOrder:7,onboardingDescription:"Let superglue use meeting notes and transcripts. superglue will never join or record meetings."},googleDrive:{category:"workspace",systemId:"google-drive",onboardingOrder:9,onboardingDescription:"Connect accessible Drive files for relevant workspace context."},box:{category:"workspace",systemId:"box",onboardingOrder:11,onboardingDescription:"Connect accessible Box files for relevant workspace context."},dropbox:{category:"workspace",systemId:"dropbox",onboardingOrder:12,onboardingDescription:"Connect accessible Dropbox files for relevant workspace context."},jira:{category:"workspace",systemId:"jira",onboardingOrder:13,onboardingDescription:"Connect Jira projects, issues, and comments for relevant workspace context."},rocketlaneMcp:{category:"workspace",systemId:"rocketlane",onboardingOrder:14,onboardingDescription:"Connect Rocketlane projects, tasks, and status for relevant workspace context."},zoho_crm:{category:"workspace",systemId:"zoho-crm",onboardingOrder:15,onboardingDescription:"Connect Zoho CRM accounts, contacts, deals, and notes. superglue will never edit records on its own.",regions:{US:"zoho_crm",EU:"zoho_crm_eu",UK:"zoho_crm_uk"}},zoho_projects:{category:"workspace",systemId:"zoho-projects",onboardingOrder:16,onboardingDescription:"Connect Zoho Projects projects, tasks, and milestones for relevant workspace context.",regions:{US:"zoho_projects",EU:"zoho_projects_eu",UK:"zoho_projects_uk"}},clickup:{category:"workspace",systemId:"clickup",onboardingOrder:17,onboardingDescription:"Connect ClickUp spaces, lists, tasks, and comments for relevant workspace context."},notion:{category:"workspace",systemId:"notion",onboardingOrder:8,onboardingDescription:"Connect selected Notion pages for relevant workspace context."},sharepoint:{category:"workspace",systemId:"sharepoint",onboardingOrder:10,onboardingDescription:"Connect accessible SharePoint sites and files for workspace context."},microsoftTeams:{category:"workspace",systemId:"microsoft-teams",onboardingOrder:6,onboardingDescription:"Connect Microsoft Teams channels and meetings for workspace context."},outlookMail:{category:"email",systemId:"outlook-mail",onboardingOrder:8,onboardingDescription:"Let superglue access your outlook inbox and calendar. superglue will never send emails on your behalf."},circleback:{category:"meetings",systemId:"circleback",onboardingOrder:1,onboardingDescription:"Let superglue use notes and transcripts. superglue will never join or record meetings.",endpointAliases:["https://app.circleback.ai/api/mcp"]},fireflies:{category:"meetings",systemId:"fireflies",onboardingOrder:3,onboardingDescription:"Let superglue use transcripts and summaries. superglue will never join or record meetings."},fellowMcp:{category:"meetings",systemId:"fellow",onboardingOrder:5,onboardingDescription:"Let superglue use meeting notes and transcripts. superglue will never join or record meetings."}};am.contextSourceTemplates=fEe});var YS=m(Oe=>{"use strict";Object.defineProperty(Oe,"__esModule",{value:!0});Oe.systemOptions=Oe.systems=void 0;Oe.hasManagedOAuthApp=yEe;Oe.formatMissingManagedOAuthAppError=EEe;Oe.getSystemTemplateOAuthClientMode=IEe;Oe.getSystemTemplateAuthentication=c$;Oe.mergeSystemTemplateAuthentication=u$;Oe.resolveSystemAuthentication=GS;Oe.getContextSourceTemplates=d$;Oe.findOwnedOAuthCredentials=A$;Oe.resolveContextSourceSetup=vEe;Oe.getUnresolvedTemplatePlaceholderError=DEe;Oe.getSystemLabel=REe;Oe.findTemplateForSystem=oA;Oe.uniqueKeywords=NEe;Oe.getOAuthConfig=kEe;Oe.getOAuthTokenExchangeConfig=OEe;Oe.getOAuthTokenUrl=UEe;var hEe=vg(),gEe=s$(),mEe=Rn(),cm=Gg();function yEe({templateId:t,managedOAuthTemplateIds:e}){return!!(t&&Oe.systems[t]?.oauth?.managed&&e.includes(t))}function EEe(t){return`This deployment has no superglue-managed OAuth app for ${t}. Configure the client ID and secret of your own OAuth app.`}function IEe({template:t,managedOAuthAvailable:e}){let r=t?.oauth;if(r)return r.registrationUrl?"dynamic":r.managed&&e?"managed":"custom"}function CEe(t){let e=t?.split(/[,\s]+/).filter(Boolean);return e?.length?e:void 0}function c$(t){if(!t)return;if(t.preferredAuthType!=="oauth2")return{type:t.preferredAuthType};let e=t.oauth;if(!e)return{type:"oauth2"};let r={};e.tokenAuthMethod&&(r.tokenAuthMethod=e.tokenAuthMethod),e.tokenContentType&&(r.tokenContentType=e.tokenContentType),e.extraHeaders&&(r.extraHeaders=e.extraHeaders),e.extraBodyParams&&(r.extraBodyParams=e.extraBodyParams),e.usePKCE!==void 0&&(r.usePKCE=e.usePKCE),e.resource&&(r.resource=e.resource);let n=CEe(e.scopes);return{type:"oauth2",...e.registrationUrl?{oauthClientMode:"dynamic"}:{},...e.authUrl?{authUrl:e.authUrl}:{},...e.tokenUrl?{tokenUrl:e.tokenUrl}:{},...e.grant_type?{grantType:e.grant_type}:{},...n?{scopes:n}:{},...Object.keys(r).length?{config:r}:{}}}function bEe(t,e){let r={...t||{},...e||{}};return Object.keys(r).length>0?r:void 0}function SEe(t,e){if(e)return{...t,config:e};let{config:r,...n}=t;return n}function u$({authentication:t,template:e}){let r=c$(e),n=(0,hEe.normalizeSystemAuthentication)(t);return n?!r||n.type!==r.type?n:SEe({...r,...n},bEe(r.config,n.config)):r}function GS(t){return u$({authentication:t.authentication,template:oA(t)?.template})||{type:"none"}}var l$="access_type=offline&prompt=consent&scope=";function HS(t){return{name:t==="com"?"zoho_crm":`zoho_crm_${t}`,label:t==="com"?"Zoho CRM":`Zoho CRM (${t.toUpperCase()})`,apiUrl:`https://www.zohoapis.${t}/crm/v8`,regex:t==="com"?"^.*(zoho.*crm|crm\\.zoho).*$":`^.*(zohoapis|crm\\.zoho)\\.${t}.*$`,icon:"simpleicons:zoho",docsUrl:"https://www.zoho.com/crm/developer/docs/api/v8/",openApiUrl:"https://raw.githubusercontent.com/zoho/crm-oas/main/v8.0/record/record.yaml",preferredAuthType:"oauth2",oauth:{authUrl:`https://accounts.zoho.${t}/oauth/v2/auth?${l$}ZohoCRM.modules.ALL,ZohoCRM.settings.ALL,ZohoCRM.users.READ,ZohoCRM.org.READ,ZohoCRM.coql.READ`,tokenUrl:`https://accounts.zoho.${t}/oauth/v2/token`,scopes:"",managed:!0},systemSpecificInstructions:`Send Authorization: Zoho-oauthtoken <<{systemId}_access_token>> on every call, with {systemId} replaced by the connected system id. Zoho CRM rejects the Bearer prefix even though the token response says token_type Bearer.
1076
+ `,n);n=s===-1?t.length:s,r+=" ";continue}if(i==="/"&&o==="*"){let s=t.indexOf("*/",n+2);if(s===-1)return{statements:e,unterminated:!0};n=s+2,r+=" ";continue}if(i==="'"||i==='"'||i==="`"||i==="["){let s=i==="["?"]":i,a=n+1;for(;a<t.length;){if(t[a]===s){if(t[a+1]===s&&s!=="]"){a+=2;continue}break}a+=1}if(a>=t.length)return{statements:e,unterminated:!0};r+=i==="'"?"''":'""',n=a+1;continue}if(i==="$"){let s=t.slice(n).match(/^\$[A-Za-z_]*\$/)?.[0];if(s){let a=t.indexOf(s,n+s.length);if(a===-1)return{statements:e,unterminated:!0};r+="''",n=a+s.length;continue}}if(i===";"){e.push(r),r="",n+=1;continue}r+=i,n+=1}return e.push(r),{statements:e.map(i=>i.replace(/\s+/g," ").trim()).filter(Boolean),unterminated:!1}}function iEe(t){let e=sm(t),r=typeof e?.query=="string"?e.query:void 0;if(!r)return`This read-only run cannot send a query it cannot read. Send the statement as {"query": "SELECT ..."}. ${wt}`;let{statements:n,unterminated:i}=nEe(r);if(i)return`This read-only run cannot check a statement with an unterminated quote or comment. ${wt}`;if(n.length>1)return`This read-only run allows one statement per call. ${wt}`;let s=(n[0]??"").toLowerCase(),a=s.replace(/^[(\s]+/,"").split(/[\s(]/)[0]??"";if(!e$.has(a))return`This read-only run allows only ${[...e$].join(", ").toUpperCase()} statements, not ${a.toUpperCase()||"this statement"}. ${wt}`;let c=s.match(Kye)??s.match(rEe);return c?`This read-only run refuses the statement because of "${c[0].replace(/\s*\($/,"").toUpperCase()}". ${wt}`:null}function oEe(t){let e=om(sm(t));for(let r of e){let n=typeof r?.command=="string"?r.command.trim():"";if(!n)return`This read-only run cannot send a command it cannot read. Send {"command": "GET", "args": [...]}. ${wt}`;if(!Xye.has(n.toUpperCase()))return`This read-only run refuses the Redis command ${n.toUpperCase()}, which is not a known read command. ${wt}`}return null}function sEe(t){let e=om(sm(t));for(let r of e){let n=typeof r?.operation=="string"?r.operation.trim():"";if(!n)return`This read-only run cannot send an operation it cannot read. Send {"operation": "find", ...}. ${wt}`;if(!eEe.has(n))return`This read-only run refuses the MongoDB operation ${n}, which writes. ${wt}`;for(let i of om(r?.pipeline))for(let o of Object.keys(i??{}))if(tEe.has(o))return`This read-only run refuses an aggregation with ${o}, which writes. ${wt}`}return null}function aEe(t,e){let r=om(sm(e));for(let n of r){let i=typeof n?.operation=="string"?n.operation.trim():"";if(!i)return`This read-only run cannot send an operation it cannot read. Send {"operation": "list", ...}. ${wt}`;if(!t$.has(i))return`This read-only run allows only ${[...t$].join(", ")} on ${t}, not ${i}. ${wt}`}return null}function cEe(t){let e=[t.url,t.body??"",...Object.entries(t.headers??{}).flatMap(([n,i])=>[n,i])],r=[];for(let n of e)for(let i of n.matchAll(/<<([\s\S]*?)>>/g)){let o=i[1].trim();o&&r.push(o)}return r}var uEe=new Set(["x-http-method-override","x-http-method","x-method-override"]);function n$(t){let e=t.match(/^([a-z][a-z0-9+.-]*):\/\/([^/?#]*)/i);if(!e)return null;let r=e[2];return{scheme:e[1].toLowerCase(),host:r.slice(r.lastIndexOf("@")+1).toLowerCase()}}function r$(t,e){return t.split(`<<${e.toLowerCase()}_`).join("<<")}function lEe(t){return t.systemId&&t.systemUrl?t.url.split(`<<${t.systemId}_url>>`).join(t.systemUrl):t.url}function dEe(t,e){let r=cEe(t);if(r.length===0)return null;let n=r.find(o=>o.startsWith("sg_auth"));if(n)return`This read-only run cannot send your identity token <<${n}>>. ${wt}`;let i=t.systemUrl?n$(t.systemUrl):null;return!t.systemId||!i||i.scheme!==e.scheme||r$(e.host,t.systemId)!==r$(i.host,t.systemId)?`This read-only run sends secrets only to the address of the system they belong to. Use <<${t.systemId??"systemId"}_url>> as the start of the URL. ${wt}`:null}function AEe(t){let e=Object.keys(t.headers??{}).find(n=>uEe.has(n.toLowerCase())),r=/[?&](_method|x-http-method-override)=/i.test(t.url);return e||r?`This read-only run cannot override the HTTP method. ${wt}`:null}function pEe(t){let e=lEe(t),r=n$(e);if(!r)return`This read-only run cannot check a URL whose address is not known before secrets are resolved. Start the URL with a scheme and host, or with <<systemId_url>>. ${wt}`;let n=(0,im.inferProtocolFromUrl)(e);if(t.protocol&&t.protocol!==n)return`This read-only run refuses protocol ${t.protocol} for a ${n} URL. ${wt}`;if(n==="http"&&r.scheme!=="http"&&r.scheme!=="https")return`This read-only run cannot use the ${r.scheme} scheme. ${wt}`;let i=dEe(t,r);if(i)return i;switch(n){case"http":{if((0,im.isNetSuiteRestletUrl)(e))return`This read-only run cannot call a NetSuite RESTlet, because RESTlet code can change the account on any method. ${wt}`;let o=(t.method||"GET").toUpperCase();return XP.has(o)?AEe(t):`This read-only run allows only ${[...XP].join(", ")} requests, not ${o}. ${wt}`}case"postgres":case"mssql":case"odbc":return iEe(t.body);case"redis":return oEe(t.body);case"mongodb":return sEe(t.body);case"sftp":case"smb":return aEe(n,t.body);case"suitecloud":return(0,im.isSuiteCloudWrite)({url:e,body:t.body})?`This read-only run allows only SuiteCloud listObjects, importObjects, listFiles, importFiles, validate, and preview, not ${(0,im.getSuiteCloudOperation)(t.body)??"an unknown operation"}. ${wt}`:null;default:return`This read-only run cannot use the ${n} protocol. ${wt}`}}});var o$=m(vu=>{"use strict";Object.defineProperty(vu,"__esModule",{value:!0});vu.PREPARABLE_TASK_STATUSES=vu.TASK_PREPARATION_STATES=void 0;vu.TASK_PREPARATION_STATES=["queued","preparing","ready","failed","started"];vu.PREPARABLE_TASK_STATUSES=["not_started","waiting"]});var s$=m(am=>{"use strict";Object.defineProperty(am,"__esModule",{value:!0});am.contextSourceTemplates=void 0;var fEe={slack:{category:"workspace",systemId:"slack",onboardingOrder:7,onboardingDescription:"Connect joined public channels so superglue can use relevant workspace context."},gmail:{category:"email",systemId:"gmail",onboardingOrder:9,onboardingDescription:"Let superglue access your gmail inbox. superglue will never send emails on your behalf."},fathomMcp:{category:"meetings",systemId:"fathomMcp",onboardingOrder:4,onboardingDescription:"Let superglue use meeting notes and transcripts. superglue will never join or record meetings."},granolaMcp:{category:"meetings",systemId:"granolaMcp",onboardingOrder:2,onboardingDescription:"Let superglue use notes and transcripts. superglue will never join or record meetings."},readAiMcp:{category:"meetings",systemId:"read-ai",onboardingOrder:6,onboardingDescription:"Let superglue use meeting summaries and transcripts. superglue will never join or record meetings."},otterMcp:{category:"meetings",systemId:"otter",onboardingOrder:7,onboardingDescription:"Let superglue use meeting notes and transcripts. superglue will never join or record meetings."},googleDrive:{category:"workspace",systemId:"google-drive",onboardingOrder:9,onboardingDescription:"Connect accessible Drive files for relevant workspace context."},box:{category:"workspace",systemId:"box",onboardingOrder:11,onboardingDescription:"Connect accessible Box files for relevant workspace context."},dropbox:{category:"workspace",systemId:"dropbox",onboardingOrder:12,onboardingDescription:"Connect accessible Dropbox files for relevant workspace context."},jira:{category:"workspace",systemId:"jira",onboardingOrder:13,onboardingDescription:"Connect Jira projects, issues, and comments for relevant workspace context."},rocketlaneMcp:{category:"workspace",systemId:"rocketlane",onboardingOrder:14,onboardingDescription:"Connect Rocketlane projects, tasks, and status for relevant workspace context."},zoho_crm:{category:"workspace",systemId:"zoho-crm",onboardingOrder:15,onboardingDescription:"Connect Zoho CRM accounts, contacts, deals, and notes. superglue will never edit records on its own.",regions:{US:"zoho_crm",EU:"zoho_crm_eu",UK:"zoho_crm_uk"}},zoho_projects:{category:"workspace",systemId:"zoho-projects",onboardingOrder:16,onboardingDescription:"Connect Zoho Projects projects, tasks, and milestones for relevant workspace context.",regions:{US:"zoho_projects",EU:"zoho_projects_eu",UK:"zoho_projects_uk"}},clickup:{category:"workspace",systemId:"clickup",onboardingOrder:17,onboardingDescription:"Connect ClickUp spaces, lists, tasks, and comments for relevant workspace context."},smartsheet:{category:"workspace",systemId:"smartsheet",onboardingOrder:18,onboardingDescription:"Connect Smartsheet sheets, reports, and dashboards for relevant workspace context."},notion:{category:"workspace",systemId:"notion",onboardingOrder:8,onboardingDescription:"Connect selected Notion pages for relevant workspace context."},sharepoint:{category:"workspace",systemId:"sharepoint",onboardingOrder:10,onboardingDescription:"Connect accessible SharePoint sites and files for workspace context."},microsoftTeams:{category:"workspace",systemId:"microsoft-teams",onboardingOrder:6,onboardingDescription:"Connect Microsoft Teams channels and meetings for workspace context."},outlookMail:{category:"email",systemId:"outlook-mail",onboardingOrder:8,onboardingDescription:"Let superglue access your outlook inbox and calendar. superglue will never send emails on your behalf."},circleback:{category:"meetings",systemId:"circleback",onboardingOrder:1,onboardingDescription:"Let superglue use notes and transcripts. superglue will never join or record meetings.",endpointAliases:["https://app.circleback.ai/api/mcp"]},fireflies:{category:"meetings",systemId:"fireflies",onboardingOrder:3,onboardingDescription:"Let superglue use transcripts and summaries. superglue will never join or record meetings."},fellowMcp:{category:"meetings",systemId:"fellow",onboardingOrder:5,onboardingDescription:"Let superglue use meeting notes and transcripts. superglue will never join or record meetings."}};am.contextSourceTemplates=fEe});var YS=m(Oe=>{"use strict";Object.defineProperty(Oe,"__esModule",{value:!0});Oe.systemOptions=Oe.systems=void 0;Oe.hasManagedOAuthApp=yEe;Oe.formatMissingManagedOAuthAppError=EEe;Oe.getSystemTemplateOAuthClientMode=IEe;Oe.getSystemTemplateAuthentication=c$;Oe.mergeSystemTemplateAuthentication=u$;Oe.resolveSystemAuthentication=GS;Oe.getContextSourceTemplates=d$;Oe.findOwnedOAuthCredentials=A$;Oe.resolveContextSourceSetup=vEe;Oe.getUnresolvedTemplatePlaceholderError=DEe;Oe.getSystemLabel=REe;Oe.findTemplateForSystem=oA;Oe.uniqueKeywords=NEe;Oe.getOAuthConfig=kEe;Oe.getOAuthTokenExchangeConfig=OEe;Oe.getOAuthTokenUrl=UEe;var hEe=vg(),gEe=s$(),mEe=Rn(),cm=Gg();function yEe({templateId:t,managedOAuthTemplateIds:e}){return!!(t&&Oe.systems[t]?.oauth?.managed&&e.includes(t))}function EEe(t){return`This deployment has no superglue-managed OAuth app for ${t}. Configure the client ID and secret of your own OAuth app.`}function IEe({template:t,managedOAuthAvailable:e}){let r=t?.oauth;if(r)return r.registrationUrl?"dynamic":r.managed&&e?"managed":"custom"}function CEe(t){let e=t?.split(/[,\s]+/).filter(Boolean);return e?.length?e:void 0}function c$(t){if(!t)return;if(t.preferredAuthType!=="oauth2")return{type:t.preferredAuthType};let e=t.oauth;if(!e)return{type:"oauth2"};let r={};e.tokenAuthMethod&&(r.tokenAuthMethod=e.tokenAuthMethod),e.tokenContentType&&(r.tokenContentType=e.tokenContentType),e.extraHeaders&&(r.extraHeaders=e.extraHeaders),e.extraBodyParams&&(r.extraBodyParams=e.extraBodyParams),e.usePKCE!==void 0&&(r.usePKCE=e.usePKCE),e.resource&&(r.resource=e.resource);let n=CEe(e.scopes);return{type:"oauth2",...e.registrationUrl?{oauthClientMode:"dynamic"}:{},...e.authUrl?{authUrl:e.authUrl}:{},...e.tokenUrl?{tokenUrl:e.tokenUrl}:{},...e.grant_type?{grantType:e.grant_type}:{},...n?{scopes:n}:{},...Object.keys(r).length?{config:r}:{}}}function bEe(t,e){let r={...t||{},...e||{}};return Object.keys(r).length>0?r:void 0}function SEe(t,e){if(e)return{...t,config:e};let{config:r,...n}=t;return n}function u$({authentication:t,template:e}){let r=c$(e),n=(0,hEe.normalizeSystemAuthentication)(t);return n?!r||n.type!==r.type?n:SEe({...r,...n},bEe(r.config,n.config)):r}function GS(t){return u$({authentication:t.authentication,template:oA(t)?.template})||{type:"none"}}var l$="access_type=offline&prompt=consent&scope=";function HS(t){return{name:t==="com"?"zoho_crm":`zoho_crm_${t}`,label:t==="com"?"Zoho CRM":`Zoho CRM (${t.toUpperCase()})`,apiUrl:`https://www.zohoapis.${t}/crm/v8`,regex:t==="com"?"^.*(zoho.*crm|crm\\.zoho).*$":`^.*(zohoapis|crm\\.zoho)\\.${t}.*$`,icon:"simpleicons:zoho",docsUrl:"https://www.zoho.com/crm/developer/docs/api/v8/",openApiUrl:"https://raw.githubusercontent.com/zoho/crm-oas/main/v8.0/record/record.yaml",preferredAuthType:"oauth2",oauth:{authUrl:`https://accounts.zoho.${t}/oauth/v2/auth?${l$}ZohoCRM.modules.ALL,ZohoCRM.settings.ALL,ZohoCRM.users.READ,ZohoCRM.org.READ,ZohoCRM.coql.READ`,tokenUrl:`https://accounts.zoho.${t}/oauth/v2/token`,scopes:"",managed:!0},systemSpecificInstructions:`Send Authorization: Zoho-oauthtoken <<{systemId}_access_token>> on every call, with {systemId} replaced by the connected system id. Zoho CRM rejects the Bearer prefix even though the token response says token_type Bearer.
1077
1077
  Data centers: accounts, tokens, and API calls must all use the user's Zoho data center. This template uses accounts.zoho.${t} and www.zohoapis.${t}; the US, EU, and UK data centers have separate templates. INVALID_TOKEN, INVALID_OAUTHTOKEN, or AUTHENTICATION_FAILURE on a fresh token means the account is in another data center; connect the matching template. Sandbox orgs use sandbox.zohoapis.<dc>; developer orgs use developer.zohoapis.<dc>.
1078
1078
  Setup: create a Server-based Application in the Zoho API Console (https://api-console.zoho.com) with the superglue OAuth callback URL as the redirect URI. If users outside the client's home data center will connect, enable Multi-DC in the client's Settings tab. The authorize URL carries access_type=offline&prompt=consent so Zoho issues a refresh token. Scopes are embedded there comma-separated because Zoho rejects space-separated scopes; change the scope parameter in the authorize URL and leave the scopes field empty.
1079
1079
  API: records live under /{module_api_name} (Leads, Contacts, Accounts, Deals, Tasks, or custom modules). Listing records requires a fields parameter with up to 50 field API names. per_page is at most 200 and page reaches 2,000 records; beyond that, pass page_token from info.next_page_token. Use POST /coql for SQL-like queries.`,keywords:["leads","contacts","accounts","deals","tasks","calls","meetings","notes","products","quotes","modules","coql","users"]}}function qS(t){return{name:t==="com"?"zoho_projects":`zoho_projects_${t}`,label:t==="com"?"Zoho Projects":`Zoho Projects (${t.toUpperCase()})`,apiUrl:`https://projectsapi.zoho.${t}/api/v3`,regex:t==="com"?"^.*(zoho.*projects|projects(api)?\\.zoho).*$":`^.*(projects(api)?\\.zoho\\.${t}|zoho\\.${t}/.*projects).*$`,icon:"simpleicons:zoho",docsUrl:"https://projects.zoho.com/api-docs",preferredAuthType:"oauth2",oauth:{authUrl:`https://accounts.zoho.${t}/oauth/v2/auth?${l$}ZohoProjects.portals.READ,ZohoProjects.projects.READ,ZohoProjects.projects.CREATE,ZohoProjects.tasks.READ,ZohoProjects.tasks.CREATE,ZohoProjects.tasklists.READ,ZohoProjects.milestones.READ,ZohoProjects.timesheets.READ,ZohoProjects.users.READ`,tokenUrl:`https://accounts.zoho.${t}/oauth/v2/token`,scopes:"",managed:!0},systemSpecificInstructions:`Send Authorization: Zoho-oauthtoken <<{systemId}_access_token>> on every call, with {systemId} replaced by the connected system id. Zoho rejects the Bearer prefix.
@@ -1114,7 +1114,7 @@ Authentication is not sent as Authorization: Bearer. First call POST /openapi/v1
1114
1114
 
1115
1115
  API keys are generated by a Jisr Admin in Settings > Webhook & API Keys > API Keys. Enabled API and lookup permissions control which endpoints and fields are accessible, the secret can only be copied once, and employee financial fields require the "Get Employee Financial Info" permission.
1116
1116
 
1117
- Most list endpoints paginate with page plus rpp or limit, capped at 100 records per page. Payroll and accrual endpoints often require specific type values, paygroup filters, and pay period dates set to the first day of a confirmed month. Some payroll endpoints, including employee monthly payables and payroll transaction deletion, are available only for whitelisted organizations.`},attio:{name:"attio",apiUrl:"https://api.attio.com/v2/",regex:"^.*attio.*$",icon:"/logos/attio.svg",docsUrl:"https://docs.attio.com/rest-api/overview",openApiUrl:"https://api.attio.com/openapi/api",preferredAuthType:"api_key",keywords:["people","objects","records","lists","entries","workspace_members","notes","tasks","threads","comments","sorts","api_slug","attribute_type","record_id","workspace_id","object_id"]},twilio:{name:"twilio",apiUrl:"https://api.twilio.com",regex:"^.*twilio.*$",icon:"/logos/twilio.svg",docsUrl:"https://www.twilio.com/docs/api",openApiUrl:"https://raw.githubusercontent.com/twilio/twilio-oai/refs/heads/main/spec/json/twilio_api_v2010.json",preferredAuthType:"api_key",keywords:["Messages","Media","MessageFeedback","Calls","Accounts","APIKeys","Addresses","UsageRecords","CallFeedback","CredentialsList","TaskRouter_Workspaces","TaskRouter_Tasks","TaskRouter_Workers","TaskRouter_Activities","MessagingServices"]},sendgrid:{name:"sendgrid",apiUrl:"https://api.sendgrid.com",regex:"^.*sendgrid.*$",icon:"/logos/sendgrid.svg",docsUrl:"https://www.twilio.com/docs/sendgrid/api-reference",openApiUrl:"https://raw.githubusercontent.com/sendgrid/sendgrid-oai/main/oai.json",preferredAuthType:"api_key",keywords:["mail_send","templates","campaigns","marketing_contacts","marketing_lists","suppression_groups","global_suppressions","asm_suppressions","subusers","stats","categories","whitelabel","ips","access_settings"]},github:{name:"github",apiUrl:"https://api.github.com",regex:"^.*github.*$",icon:"github",docsUrl:"https://docs.github.com/en/rest",openApiUrl:"https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json",preferredAuthType:"api_key",oauth:{authUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",scopes:"repo user admin:org workflow gist notifications delete_repo write:packages read:packages"},keywords:["repositories","issues","pull_requests","commits","branches","tags","releases","deployments","check_runs","actions_artifacts","organizations","packages","collaborators","gists","milestones"]},gitlab:{name:"gitlab",apiUrl:"https://api.gitlab.com",regex:"^.*gitlab.*$",icon:"gitlab",docsUrl:"https://docs.gitlab.com/api/rest/",openApiUrl:"https://gitlab.com/gitlab-org/gitlab/-/raw/master/doc/api/openapi/openapi.yaml",preferredAuthType:"api_key",oauth:{authUrl:"https://gitlab.com/oauth/authorize",tokenUrl:"https://gitlab.com/oauth/token",scopes:"api"},keywords:["projects","repositories","issues","pull_requests","commits","branches","tags","releases","deployments","check_runs","actions_artifacts","organizations","packages","collaborators","gists","milestones"]},bitbucket:{name:"bitbucket",apiUrl:"https://api.bitbucket.org",regex:"^.*bitbucket.*$",icon:"bitbucket",docsUrl:"https://developer.atlassian.com/cloud/bitbucket/rest",openApiUrl:"https://api.bitbucket.org/swagger.json",preferredAuthType:"oauth2",oauth:{authUrl:"https://bitbucket.org/site/oauth2/authorize",tokenUrl:"https://bitbucket.org/site/oauth2/access_token",scopes:"repository:admin account:write team:write webhook"},keywords:["repositories","projects","commits","branches","pullrequests","downloads","issues","pipelines","branchRestrictions","components","milestones","refs","hooks","forks","user"]},slack:{name:"slack",label:"Slack",apiUrl:"https://slack.com/api",extraApiUrls:["https://files.slack.com"],regex:"^.*slack.*$",icon:"slack",docsUrl:"https://docs.slack.dev/apis/web-api/",openApiUrl:"https://raw.githubusercontent.com/slackapi/slack-api-specs/master/web-api/slack_web_openapi_v2.json",preferredAuthType:"oauth2",oauth:{grant_type:"authorization_code",authUrl:"https://slack.com/oauth/v2/authorize",tokenUrl:"https://slack.com/api/oauth.v2.access",scopes:"channels:history channels:join channels:read files:read users:read users:read.email",managed:!0},keywords:["channel","conversation","user","file","event","message","workflow_step","workflow_published","workflow_step_execute","usergroup","im","mpim","group","check_run","apps_permissions_resource"],systemSpecificInstructions:"Slack OAuth returns a bot token. Bot access depends on its granted scopes and channel membership."},airtable:{name:"airtable",apiUrl:"https://api.airtable.com",regex:"^.*airtable.*$",icon:"airtable",docsUrl:"https://airtable.com/developers/web/api",preferredAuthType:"oauth2",oauth:{authUrl:"https://airtable.com/oauth2/v1/authorize",tokenUrl:"https://airtable.com/oauth2/v1/token",scopes:"data.recordComments:read data.recordComments:write data.records:read data.records:write schema.bases:read schema.bases:write user.email:read enterprise.groups:read data.records:manage enterprise.account:read enterprise.account:write enterprise.auditLogs:read enterprise.changeEvents:read enterprise.exports:manage enterprise.groups:manage enterprise.scim.usersAndGroups:manage enterprise.user:read enterprise.user:write webhook:manage",managed:!0,usePKCE:!0,tokenAuthMethod:"basic_auth",tokenContentType:"form"},keywords:["bases","tables","records","fields","views","formulas","attachments","comments","collaborators","metadata","schemas","api key","key"]},gmail:{name:"gmail",label:"Gmail",apiUrl:"https://gmail.googleapis.com/gmail/v1",extraApiUrls:["https://gmail.googleapis.com/batch/gmail/v1","https://gmail.googleapis.com/upload/gmail/v1"],regex:"^.*(gmail\\.googleapis|developers\\.google\\.com/gmail|mail\\.google).*$",icon:"gmail",docsUrl:"https://developers.google.com/gmail/api/reference/rest",openApiUrl:"https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/gmail.modify",managed:!0},keywords:["messages","threads","labels","drafts","send","attachments","history","filters","settings","forwarding","inbox","profile","oauth"]},googleWorkspace:{name:"googleWorkspace",label:"Google Workspace",apiUrl:"https://www.googleapis.com",extraApiUrls:["https://gmail.googleapis.com","https://people.googleapis.com","https://docs.googleapis.com","https://sheets.googleapis.com","https://slides.googleapis.com","https://forms.googleapis.com","https://tasks.googleapis.com"],regex:"^.*(workspace\\.google\\.com|developers\\.google\\.com/workspace(?!/tasks)).*$",icon:"/logos/google.svg",docsUrl:"https://developers.google.com/workspace",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:["openid","https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile","https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.settings.readonly","https://www.googleapis.com/auth/documents","https://www.googleapis.com/auth/spreadsheets","https://www.googleapis.com/auth/presentations","https://www.googleapis.com/auth/forms.body","https://www.googleapis.com/auth/forms.responses.readonly","https://www.googleapis.com/auth/gmail.modify","https://www.googleapis.com/auth/contacts","https://www.googleapis.com/auth/contacts.other.readonly","https://www.googleapis.com/auth/directory.readonly","https://www.googleapis.com/auth/tasks","https://www.googleapis.com/auth/drive.readonly","https://www.googleapis.com/auth/drive.file","https://www.googleapis.com/auth/drive.appdata"].join(" "),managed:!0},systemSpecificInstructions:"superglue provides a managed Google Workspace OAuth app; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. The System URL is the shared Google API host; address each product by its own path prefix or host: Calendar /calendar/v3, Docs https://docs.googleapis.com/v1, Sheets https://sheets.googleapis.com/v4, Slides https://slides.googleapis.com/v1, Forms https://forms.googleapis.com/v1, Gmail https://gmail.googleapis.com/gmail/v1 (read, search, and drafts; send via POST /users/me/messages/send with a base64url RFC 5322 message only when the user explicitly asks to send), People https://people.googleapis.com/v1 (contacts, otherContacts, and people:searchDirectoryPeople for the Workspace directory; directory search requires a Google Workspace account), Tasks https://tasks.googleapis.com/tasks/v1, Drive https://www.googleapis.com/drive/v3 (drive.readonly lists and reads any file the user can access; drive.file grants write access to files created or opened through this app). Send OAuth tokens as Authorization: Bearer <<access_token>>.",keywords:["workspace","calendar","events","docs","documents","sheets","spreadsheets","slides","presentations","forms","responses","gmail","send email","contacts","people","directory","tasks","oauth"]},granola:{name:"granola",label:"Granola API",apiUrl:"https://public-api.granola.ai",regex:"^.*granola.*$",icon:"/logos/granola.svg",docsUrl:"https://docs.granola.ai",preferredAuthType:"api_key",keywords:["meeting","notes","transcript","summary","ai","recording"]},fathom:{name:"fathom",apiUrl:"https://api.fathom.ai/external/v1",regex:"^.*(fathom\\.ai|fathom\\.video).*$",icon:"/logos/fathom.png",docsUrl:"https://developers.fathom.ai",openApiUrl:"https://developers.fathom.ai/api-reference/openapi.yaml",preferredAuthType:"oauth2",oauth:{grant_type:"authorization_code",authUrl:"https://fathom.video/external/v1/oauth2/authorize",tokenUrl:"https://api.fathom.ai/external/v1/oauth2/token",scopes:"public_api",managed:!0},keywords:["meeting","meetings","notetaker","transcript","transcription","recording","summary","action items","webhook","oauth"],systemSpecificInstructions:"Fathom is an AI meeting notetaker. superglue provides a managed Fathom OAuth app, so no app registration is needed \u2014 authenticate directly via OAuth (authorization code with refresh tokens; the only scope is public_api). Alternatively, an API key created in Fathom settings works via an X-Api-Key header. Send OAuth tokens as Authorization: Bearer <<access_token>>. Webhooks must set at least one of include_transcript, include_summary, include_action_items, or include_crm_matches. Rate limits: 60 requests per 60 seconds overall, 30 per 60 seconds for transcript, summary, and content-heavy meeting requests (5 per 60 seconds under high load)."},fathomMcp:{name:"fathomMcp",label:"Fathom",apiUrl:"https://api.fathom.ai/mcp",regex:"^https://api\\.fathom\\.ai/mcp/?(?:\\?.*)?$",icon:"/logos/fathom.png",docsUrl:"https://developers.fathom.ai/mcp-docs",preferredAuthType:"oauth2",oauth:{authUrl:"https://fathom.video/mcp/oauth/authorize",tokenUrl:"https://api.fathom.ai/mcp/oauth/token",registrationUrl:"https://api.fathom.ai/mcp/oauth/register",scopes:"mcp",resource:"https://api.fathom.ai/mcp",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Fathom is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Discover the current read tools before use, search narrowly, and retrieve transcript content only when relevant. Never join, record, edit, or otherwise mutate meetings through this integration. Use the separate Fathom API template only when deterministic REST access is required.",keywords:["meetings","notes","transcripts","summaries","action_items","attendees","recordings","decisions"]},granolaMcp:{name:"granolaMcp",label:"Granola",apiUrl:"https://mcp.granola.ai/mcp",regex:"^https://mcp\\.granola\\.ai/mcp/?(?:\\?.*)?$",icon:"/logos/granola.svg",docsUrl:"https://docs.granola.ai/help-center/sharing/integrations/mcp",preferredAuthType:"oauth2",oauth:{authUrl:"https://mcp-auth.granola.ai/oauth2/authorize",tokenUrl:"https://mcp-auth.granola.ai/oauth2/token",registrationUrl:"https://mcp-auth.granola.ai/oauth2/register",scopes:"mcp",resource:"https://mcp.granola.ai/mcp",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Granola is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Search narrowly and retrieve transcript content only when relevant. Never edit meeting data through this integration.",keywords:["meetings","notes","transcripts","summaries","action_items","attendees","folders","decisions"]},readAiMcp:{name:"readAiMcp",label:"Read AI",apiUrl:"https://api.read.ai/mcp",regex:"^https://api\\.read\\.ai/mcp/?(?:\\?.*)?$",icon:"/logos/read-ai.png",docsUrl:"https://support.read.ai/hc/en-us/articles/49381158409491-MCP-Server",preferredAuthType:"oauth2",oauth:{authUrl:"https://authn.read.ai/oauth2/auth",tokenUrl:"https://authn.read.ai/oauth2/token",registrationUrl:"https://api.read.ai/oauth/register",scopes:"mcp:execute meeting:read offline_access",resource:"https://api.read.ai/mcp",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Read AI is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Request read-only scopes only. Discover the current tools before use, search narrowly, and retrieve transcript content only when relevant. Never join, record, edit, or otherwise mutate meetings through this integration.",keywords:["meetings","transcripts","summaries","action_items","topics","participants","metrics"]},otterMcp:{name:"otterMcp",label:"Otter",apiUrl:"https://mcp.otter.ai/mcp",regex:"^https://mcp\\.otter\\.ai/mcp/?(?:\\?.*)?$",icon:"/logos/otter.png",docsUrl:"https://help.otter.ai/hc/en-us/articles/35287607569687-Otter-MCP-Server",preferredAuthType:"oauth2",oauth:{authUrl:"https://otter.ai/oauth2/authorize",tokenUrl:"https://otter.ai/oauth/token",registrationUrl:"https://otter.ai/oauth/register",scopes:"profile:read conversations:read",resource:"https://mcp.otter.ai/",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Otter is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Request read-only scopes only. Discover the current tools before use, search narrowly, and retrieve transcript content only when relevant. Never join, record, edit, or otherwise mutate meetings through this integration.",keywords:["meetings","conversations","transcripts"]},rocketlaneMcp:{name:"rocketlaneMcp",label:"Rocketlane",apiUrl:"https://mcp.rocketlane.com/mcp",regex:"^https://mcp\\.rocketlane\\.com/mcp/?(?:\\?.*)?$",icon:"/logos/rocketlane.svg",docsUrl:"https://help.rocketlane.com/support/solutions/articles/67000754219-connect-rocketlane-mcp-to-claude-code",preferredAuthType:"oauth2",oauth:{authUrl:"https://rocketlane.scalekit.com/resources/res_121247790507492638/oauth/authorize",tokenUrl:"https://rocketlane.scalekit.com/resources/res_121247790507492638/oauth/token",registrationUrl:"https://rocketlane.scalekit.com/api/v1/resources/res_121247790507492638/clients:register",scopes:"openid email profile",resource:"https://mcp.rocketlane.com/mcp",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Rocketlane is a brain context source (workspace) backed by remote MCP. Load the workspace-apps skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Discover the current tools before use, search narrowly, and retrieve project detail only when relevant.",keywords:["projects","tasks","phases","time_entries","customers","status"]},zoominfoMcp:{name:"zoominfoMcp",label:"ZoomInfo",apiUrl:"https://mcp.zoominfo.com/mcp",regex:"^https://mcp\\.zoominfo\\.com/mcp/?(?:\\?.*)?$",icon:"/logos/zoominfo.svg",docsUrl:"https://docs.gtm.ai/docs/connect-to-zoominfo-mcp",preferredAuthType:"oauth2",oauth:{authUrl:"https://mcp.zoominfo.com/oauth/authorize",tokenUrl:"https://okta-login.zoominfo.com/oauth2/default/v1/token",scopes:"openid profile email offline_access",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"ZoomInfo is a B2B prospect research System backed by remote MCP. Keep the MCP endpoint unchanged. ZoomInfo accepts dynamic client registration only from approved vendors, so each organization supplies its own OAuth client: a ZoomInfo admin assigns the DevPortal subscription, creates an MCP App at developer.zoominfo.com with the current superglue origin plus /api/auth/callback as the redirect URI, and pastes the client ID and secret into the System. A ZoomInfo admin must also enable API Access for each user under Admin Portal > Users > User Management. Store tokens in the current user's credential. Discover the current tools with tools/list before use. Resolve a company with search_companies before enrich_companies, enrich_company_signals, or account_research, and resolve attendees with search_contacts before enrich_contacts or contact_research. Every search and enrichment consumes the customer's ZoomInfo credits; fetch only the companies and contacts the task needs. ZoomInfo terms restrict storing its data: use results in the current answer and never copy them into brain files, playbooks, or other persistent context.",keywords:["prospects","companies","contacts","enrichment","intent","scoops","sales","meeting_prep"]},googleDrive:{name:"googleDrive",label:"Google Drive",apiUrl:"https://www.googleapis.com/drive/v3",extraApiUrls:["https://www.googleapis.com/upload/drive/v3"],regex:"^.*(googleapis\\.com/drive|developers\\.google\\.com/drive|drive\\.google).*$",icon:"googledrive",docsUrl:"https://developers.google.com/drive/api/v3/reference",openApiUrl:"https://www.googleapis.com/discovery/v1/apis/drive/v3/rest",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/drive.readonly",managed:!0},keywords:["files","folders","permissions","sharing","comments","revisions","changes","uploads","downloads","metadata","teamdrives","export","copy","move","oauth"],systemSpecificInstructions:"Use Drive API v3. Export Google Workspace files and use media download for stored files."},googleCalendar:{name:"googleCalendar",apiUrl:"https://www.googleapis.com/calendar/v3",regex:"^.*(googleapis\\.com/calendar|developers\\.google\\.com/calendar|calendar\\.google).*$",icon:"googlecalendar",docsUrl:"https://developers.google.com/calendar/api/v3/reference",openApiUrl:"https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.settings.readonly",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Calendar; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>.",keywords:["events","calendars","attendees","reminders","recurring","availability","free busy","settings","acl","colors","notifications","timezone","quick add","oauth"]},googleSheets:{name:"googleSheets",apiUrl:"https://sheets.googleapis.com/v4",regex:"^.*(sheets\\.googleapis|developers\\.google\\.com/sheets|sheets\\.google).*$",icon:"googlesheets",docsUrl:"https://developers.google.com/sheets/api/reference/rest",openApiUrl:"https://www.googleapis.com/discovery/v1/apis/sheets/v4/rest",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/drive.file",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Sheets; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>. The drive.file scope only lists files created or opened through this app; open any existing spreadsheet directly by its ID with the spreadsheets scope.",keywords:["spreadsheets","sheets","cells","ranges","values","formulas","formatting","charts","pivot tables","named ranges","protected ranges","batch update","append","oauth"]},googleDocs:{name:"googleDocs",label:"Google Docs",apiUrl:"https://docs.googleapis.com/v1",regex:"^.*(docs\\.googleapis|developers\\.google\\.com/docs|docs\\.google\\.com/document).*$",icon:"googledocs",docsUrl:"https://developers.google.com/docs/api/reference/rest",openApiUrl:"https://docs.googleapis.com/$discovery/rest?version=v1",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/drive.file",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Docs; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>. Create a document with POST /documents and edit it with POST /documents/{documentId}:batchUpdate.",keywords:["documents","docs","text","paragraphs","headings","tables","images","batch update","insert text","replace text","named ranges","oauth"]},googleSlides:{name:"googleSlides",label:"Google Slides",apiUrl:"https://slides.googleapis.com/v1",regex:"^.*(slides\\.googleapis|developers\\.google\\.com/slides|docs\\.google\\.com/presentation).*$",icon:"googleslides",docsUrl:"https://developers.google.com/slides/api/reference/rest",openApiUrl:"https://slides.googleapis.com/$discovery/rest?version=v1",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/presentations https://www.googleapis.com/auth/drive.file",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Slides; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>. Create a presentation with POST /presentations and edit it with POST /presentations/{presentationId}:batchUpdate.",keywords:["presentations","slides","decks","shapes","text boxes","images","layouts","batch update","thumbnails","oauth"]},googleForms:{name:"googleForms",label:"Google Forms",apiUrl:"https://forms.googleapis.com/v1",regex:"^.*(forms\\.googleapis|developers\\.google\\.com/forms|docs\\.google\\.com/forms).*$",icon:"googleforms",docsUrl:"https://developers.google.com/forms/api/reference/rest",openApiUrl:"https://forms.googleapis.com/$discovery/rest?version=v1",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/forms.body https://www.googleapis.com/auth/forms.responses.readonly https://www.googleapis.com/auth/drive.file",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Forms; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>. Create a form with POST /forms (title only), add questions with POST /forms/{formId}:batchUpdate, and read submissions with GET /forms/{formId}/responses.",keywords:["forms","questions","responses","submissions","surveys","quizzes","batch update","items","oauth"]},googleContacts:{name:"googleContacts",label:"Google Contacts",apiUrl:"https://people.googleapis.com/v1",regex:"^.*(people\\.googleapis|developers\\.google\\.com/people|contacts\\.google\\.com).*$",icon:"/logos/google.svg",docsUrl:"https://developers.google.com/people/api/rest",openApiUrl:"https://people.googleapis.com/$discovery/rest?version=v1",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/contacts https://www.googleapis.com/auth/contacts.other.readonly https://www.googleapis.com/auth/directory.readonly",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Contacts; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>. Use /people/me/connections and /people:createContact for saved contacts, /otherContacts for automatically saved contacts, and /people:searchDirectoryPeople for the Google Workspace directory (requires a Workspace account). Every request needs personFields or readMask.",keywords:["contacts","people","directory","other contacts","connections","emails","phone numbers","organizations","search","oauth"]},googleTasks:{name:"googleTasks",label:"Google Tasks",apiUrl:"https://tasks.googleapis.com/tasks/v1",regex:"^.*(tasks\\.googleapis|developers\\.google\\.com/(workspace/)?tasks|tasks\\.google\\.com).*$",icon:"googletasks",docsUrl:"https://developers.google.com/tasks/reference/rest",openApiUrl:"https://tasks.googleapis.com/$discovery/rest?version=v1",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/tasks",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Tasks; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>. List task lists with GET /users/@me/lists and create tasks with POST /lists/{tasklist}/tasks.",keywords:["tasks","task lists","to-do","due dates","completed","subtasks","oauth"]},googleAnalytics:{name:"googleAnalytics",apiUrl:"https://analytics.google.com",regex:"^.*(analytics|analyticsdata).*$",icon:"googleAnalytics",docsUrl:"https://developers.google.com/analytics/devguides/reporting/data/v1",openApiUrl:"https://analyticsdata.googleapis.com/$discovery/rest?version=v1beta",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/analytics.edit"},keywords:["properties","dimensions","metrics","reports","audiences","conversions","events","goals","segments","real time","user activity","attribution","funnels","cohorts","oauth"]},youtube:{name:"youtube",apiUrl:"https://youtube.googleapis.com",regex:"^.*youtube.*$",icon:"youtube",docsUrl:"https://developers.google.com/youtube/v3/docs",openApiUrl:"https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/youtube"},keywords:["videos","channels","playlists","comments","captions","live streams","analytics","thumbnails","subscriptions","activities","ratings","uploads","members","oauth"]},AWS:{name:"AWS",apiUrl:"https://amazonaws.com",regex:"^.*(aws|amazonaws).*$",icon:"/logos/aws.svg",docsUrl:"https://docs.aws.amazon.com/index.html",preferredAuthType:"api_key",keywords:["ec2","s3","lambda","rds","dynamodb","sqs","sns","cloudformation","iam","cloudwatch","vpc","instances","buckets","functions","api key"]},amazon_sp_api:{name:"amazon_sp_api",apiUrl:"https://sellingpartnerapi-na.amazon.com",regex:"^.*(sellingpartnerapi[-\\w]*\\.amazon\\.com).*$",icon:"/logos/amazon.svg",docsUrl:"https://developer-docs.amazon.com/sp-api/docs",preferredAuthType:"oauth2",oauth:{authUrl:"https://sellercentral.amazon.com/apps/authorize/consent",tokenUrl:"https://api.amazon.com/auth/o2/token",grant_type:"authorization_code",tokenAuthMethod:"body",tokenContentType:"form"},keywords:["orders","catalog items","listings","feeds","reports","fba inbound","fulfillment","inventory","pricing","seller central","marketplace"],systemSpecificInstructions:`Base host is region-specific: sellingpartnerapi-na.amazon.com (US/CA/MX/BR), sellingpartnerapi-eu.amazon.com (EU/UK/IN/ME/AF), sellingpartnerapi-fe.amazon.com (Singapore/AU/JP) \u2014 swap the region segment to match the seller's marketplace; sandbox testing uses sandbox.sellingpartnerapi-<region>.amazon.com. Requires registering an app in Seller Central > Develop Apps first. Third-party apps redirect sellers to https://sellercentral.amazon.com/apps/authorize/consent?application_id=<APP_ID>&state=<STATE> (add &version=beta only while the app is in Draft state, remove once Published); private/single-account developers can skip this by generating a refresh token directly via Seller Central > Develop Apps > "Authorize new developer" (self-authorization). Access tokens require header x-amz-access-token in addition to Authorization; some operations (e.g. FBA/notifications) use a separate grantless client_credentials flow instead of the refresh-token flow.`},googleCloud:{name:"googleCloud",apiUrl:"https://cloud.google.com",regex:"^.*(cloud\\.google|gcp|googlecloud).*$",icon:"googleCloud",docsUrl:"https://cloud.google.com/apis/docs/overview",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/cloud-platform"},keywords:["compute","storage","pubsub","cloud run","kubernetes","iam","vpc","cloud sql","bigtable","dataflow","logging","monitoring","oauth"]},bigquery:{name:"bigquery",apiUrl:"https://bigquery.googleapis.com/bigquery/v2",regex:"^.*(bigquery|bq\\.googleapis).*$",icon:"googleCloud",docsUrl:"https://cloud.google.com/bigquery/docs/reference/rest",openApiUrl:"https://bigquery.googleapis.com/$discovery/rest?version=v2",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/bigquery"},systemSpecificInstructions:`BigQuery REST API - Authentication Options:
1117
+ Most list endpoints paginate with page plus rpp or limit, capped at 100 records per page. Payroll and accrual endpoints often require specific type values, paygroup filters, and pay period dates set to the first day of a confirmed month. Some payroll endpoints, including employee monthly payables and payroll transaction deletion, are available only for whitelisted organizations.`},attio:{name:"attio",apiUrl:"https://api.attio.com/v2/",regex:"^.*attio.*$",icon:"/logos/attio.svg",docsUrl:"https://docs.attio.com/rest-api/overview",openApiUrl:"https://api.attio.com/openapi/api",preferredAuthType:"api_key",keywords:["people","objects","records","lists","entries","workspace_members","notes","tasks","threads","comments","sorts","api_slug","attribute_type","record_id","workspace_id","object_id"]},twilio:{name:"twilio",apiUrl:"https://api.twilio.com",regex:"^.*twilio.*$",icon:"/logos/twilio.svg",docsUrl:"https://www.twilio.com/docs/api",openApiUrl:"https://raw.githubusercontent.com/twilio/twilio-oai/refs/heads/main/spec/json/twilio_api_v2010.json",preferredAuthType:"api_key",keywords:["Messages","Media","MessageFeedback","Calls","Accounts","APIKeys","Addresses","UsageRecords","CallFeedback","CredentialsList","TaskRouter_Workspaces","TaskRouter_Tasks","TaskRouter_Workers","TaskRouter_Activities","MessagingServices"]},sendgrid:{name:"sendgrid",apiUrl:"https://api.sendgrid.com",regex:"^.*sendgrid.*$",icon:"/logos/sendgrid.svg",docsUrl:"https://www.twilio.com/docs/sendgrid/api-reference",openApiUrl:"https://raw.githubusercontent.com/sendgrid/sendgrid-oai/main/oai.json",preferredAuthType:"api_key",keywords:["mail_send","templates","campaigns","marketing_contacts","marketing_lists","suppression_groups","global_suppressions","asm_suppressions","subusers","stats","categories","whitelabel","ips","access_settings"]},github:{name:"github",apiUrl:"https://api.github.com",regex:"^.*github.*$",icon:"github",docsUrl:"https://docs.github.com/en/rest",openApiUrl:"https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json",preferredAuthType:"api_key",oauth:{authUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",scopes:"repo user admin:org workflow gist notifications delete_repo write:packages read:packages"},keywords:["repositories","issues","pull_requests","commits","branches","tags","releases","deployments","check_runs","actions_artifacts","organizations","packages","collaborators","gists","milestones"]},gitlab:{name:"gitlab",apiUrl:"https://api.gitlab.com",regex:"^.*gitlab.*$",icon:"gitlab",docsUrl:"https://docs.gitlab.com/api/rest/",openApiUrl:"https://gitlab.com/gitlab-org/gitlab/-/raw/master/doc/api/openapi/openapi.yaml",preferredAuthType:"api_key",oauth:{authUrl:"https://gitlab.com/oauth/authorize",tokenUrl:"https://gitlab.com/oauth/token",scopes:"api"},keywords:["projects","repositories","issues","pull_requests","commits","branches","tags","releases","deployments","check_runs","actions_artifacts","organizations","packages","collaborators","gists","milestones"]},bitbucket:{name:"bitbucket",apiUrl:"https://api.bitbucket.org",regex:"^.*bitbucket.*$",icon:"bitbucket",docsUrl:"https://developer.atlassian.com/cloud/bitbucket/rest",openApiUrl:"https://api.bitbucket.org/swagger.json",preferredAuthType:"oauth2",oauth:{authUrl:"https://bitbucket.org/site/oauth2/authorize",tokenUrl:"https://bitbucket.org/site/oauth2/access_token",scopes:"repository:admin account:write team:write webhook"},keywords:["repositories","projects","commits","branches","pullrequests","downloads","issues","pipelines","branchRestrictions","components","milestones","refs","hooks","forks","user"]},slack:{name:"slack",label:"Slack",apiUrl:"https://slack.com/api",extraApiUrls:["https://files.slack.com"],regex:"^.*slack.*$",icon:"slack",docsUrl:"https://docs.slack.dev/apis/web-api/",openApiUrl:"https://raw.githubusercontent.com/slackapi/slack-api-specs/master/web-api/slack_web_openapi_v2.json",preferredAuthType:"oauth2",oauth:{grant_type:"authorization_code",authUrl:"https://slack.com/oauth/v2/authorize",tokenUrl:"https://slack.com/api/oauth.v2.access",scopes:"channels:history channels:join channels:read files:read users:read users:read.email",managed:!0},keywords:["channel","conversation","user","file","event","message","workflow_step","workflow_published","workflow_step_execute","usergroup","im","mpim","group","check_run","apps_permissions_resource"],systemSpecificInstructions:"Slack OAuth returns a bot token. Bot access depends on its granted scopes and channel membership."},airtable:{name:"airtable",apiUrl:"https://api.airtable.com",regex:"^.*airtable.*$",icon:"airtable",docsUrl:"https://airtable.com/developers/web/api",preferredAuthType:"oauth2",oauth:{authUrl:"https://airtable.com/oauth2/v1/authorize",tokenUrl:"https://airtable.com/oauth2/v1/token",scopes:"data.recordComments:read data.recordComments:write data.records:read data.records:write schema.bases:read schema.bases:write user.email:read enterprise.groups:read data.records:manage enterprise.account:read enterprise.account:write enterprise.auditLogs:read enterprise.changeEvents:read enterprise.exports:manage enterprise.groups:manage enterprise.scim.usersAndGroups:manage enterprise.user:read enterprise.user:write webhook:manage",managed:!0,usePKCE:!0,tokenAuthMethod:"basic_auth",tokenContentType:"form"},keywords:["bases","tables","records","fields","views","formulas","attachments","comments","collaborators","metadata","schemas","api key","key"]},gmail:{name:"gmail",label:"Gmail",apiUrl:"https://gmail.googleapis.com/gmail/v1",extraApiUrls:["https://gmail.googleapis.com/batch/gmail/v1","https://gmail.googleapis.com/upload/gmail/v1"],regex:"^.*(gmail\\.googleapis|developers\\.google\\.com/gmail|mail\\.google).*$",icon:"gmail",docsUrl:"https://developers.google.com/gmail/api/reference/rest",openApiUrl:"https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/gmail.modify",managed:!0},keywords:["messages","threads","labels","drafts","send","attachments","history","filters","settings","forwarding","inbox","profile","oauth"]},googleWorkspace:{name:"googleWorkspace",label:"Google Workspace",apiUrl:"https://www.googleapis.com",extraApiUrls:["https://gmail.googleapis.com","https://people.googleapis.com","https://docs.googleapis.com","https://sheets.googleapis.com","https://slides.googleapis.com","https://forms.googleapis.com","https://tasks.googleapis.com"],regex:"^.*(workspace\\.google\\.com|developers\\.google\\.com/workspace(?!/tasks)).*$",icon:"/logos/google.svg",docsUrl:"https://developers.google.com/workspace",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:["openid","https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile","https://www.googleapis.com/auth/calendar","https://www.googleapis.com/auth/calendar.settings.readonly","https://www.googleapis.com/auth/documents","https://www.googleapis.com/auth/spreadsheets","https://www.googleapis.com/auth/presentations","https://www.googleapis.com/auth/forms.body","https://www.googleapis.com/auth/forms.responses.readonly","https://www.googleapis.com/auth/gmail.modify","https://www.googleapis.com/auth/contacts","https://www.googleapis.com/auth/contacts.other.readonly","https://www.googleapis.com/auth/directory.readonly","https://www.googleapis.com/auth/tasks","https://www.googleapis.com/auth/drive.readonly","https://www.googleapis.com/auth/drive.file","https://www.googleapis.com/auth/drive.appdata"].join(" "),managed:!0},systemSpecificInstructions:"superglue provides a managed Google Workspace OAuth app; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. The System URL is the shared Google API host; address each product by its own path prefix or host: Calendar /calendar/v3, Docs https://docs.googleapis.com/v1, Sheets https://sheets.googleapis.com/v4, Slides https://slides.googleapis.com/v1, Forms https://forms.googleapis.com/v1, Gmail https://gmail.googleapis.com/gmail/v1 (read, search, and drafts; send via POST /users/me/messages/send with a base64url RFC 5322 message only when the user explicitly asks to send), People https://people.googleapis.com/v1 (contacts, otherContacts, and people:searchDirectoryPeople for the Workspace directory; directory search requires a Google Workspace account), Tasks https://tasks.googleapis.com/tasks/v1, Drive https://www.googleapis.com/drive/v3 (drive.readonly lists and reads any file the user can access; drive.file grants write access to files created or opened through this app). Send OAuth tokens as Authorization: Bearer <<access_token>>.",keywords:["workspace","calendar","events","docs","documents","sheets","spreadsheets","slides","presentations","forms","responses","gmail","send email","contacts","people","directory","tasks","oauth"]},granola:{name:"granola",label:"Granola API",apiUrl:"https://public-api.granola.ai",regex:"^.*granola.*$",icon:"/logos/granola.svg",docsUrl:"https://docs.granola.ai",preferredAuthType:"api_key",keywords:["meeting","notes","transcript","summary","ai","recording"]},fathom:{name:"fathom",apiUrl:"https://api.fathom.ai/external/v1",regex:"^.*(fathom\\.ai|fathom\\.video).*$",icon:"/logos/fathom.png",docsUrl:"https://developers.fathom.ai",openApiUrl:"https://developers.fathom.ai/api-reference/openapi.yaml",preferredAuthType:"oauth2",oauth:{grant_type:"authorization_code",authUrl:"https://fathom.video/external/v1/oauth2/authorize",tokenUrl:"https://api.fathom.ai/external/v1/oauth2/token",scopes:"public_api",managed:!0},keywords:["meeting","meetings","notetaker","transcript","transcription","recording","summary","action items","webhook","oauth"],systemSpecificInstructions:"Fathom is an AI meeting notetaker. superglue provides a managed Fathom OAuth app, so no app registration is needed \u2014 authenticate directly via OAuth (authorization code with refresh tokens; the only scope is public_api). Alternatively, an API key created in Fathom settings works via an X-Api-Key header. Send OAuth tokens as Authorization: Bearer <<access_token>>. Webhooks must set at least one of include_transcript, include_summary, include_action_items, or include_crm_matches. Rate limits: 60 requests per 60 seconds overall, 30 per 60 seconds for transcript, summary, and content-heavy meeting requests (5 per 60 seconds under high load)."},fathomMcp:{name:"fathomMcp",mcp:!0,label:"Fathom",apiUrl:"https://api.fathom.ai/mcp",regex:"^https://api\\.fathom\\.ai/mcp/?(?:\\?.*)?$",icon:"/logos/fathom.png",docsUrl:"https://developers.fathom.ai/mcp-docs",preferredAuthType:"oauth2",oauth:{authUrl:"https://fathom.video/mcp/oauth/authorize",tokenUrl:"https://api.fathom.ai/mcp/oauth/token",registrationUrl:"https://api.fathom.ai/mcp/oauth/register",scopes:"mcp",resource:"https://api.fathom.ai/mcp",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Fathom is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Discover the current read tools before use, search narrowly, and retrieve transcript content only when relevant. Never join, record, edit, or otherwise mutate meetings through this integration. Use the separate Fathom API template only when deterministic REST access is required.",keywords:["meetings","notes","transcripts","summaries","action_items","attendees","recordings","decisions"]},granolaMcp:{name:"granolaMcp",mcp:!0,label:"Granola",apiUrl:"https://mcp.granola.ai/mcp",regex:"^https://mcp\\.granola\\.ai/mcp/?(?:\\?.*)?$",icon:"/logos/granola.svg",docsUrl:"https://docs.granola.ai/help-center/sharing/integrations/mcp",preferredAuthType:"oauth2",oauth:{authUrl:"https://mcp-auth.granola.ai/oauth2/authorize",tokenUrl:"https://mcp-auth.granola.ai/oauth2/token",registrationUrl:"https://mcp-auth.granola.ai/oauth2/register",scopes:"mcp",resource:"https://mcp.granola.ai/mcp",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Granola is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Search narrowly and retrieve transcript content only when relevant. Never edit meeting data through this integration.",keywords:["meetings","notes","transcripts","summaries","action_items","attendees","folders","decisions"]},readAiMcp:{name:"readAiMcp",mcp:!0,label:"Read AI",apiUrl:"https://api.read.ai/mcp",regex:"^https://api\\.read\\.ai/mcp/?(?:\\?.*)?$",icon:"/logos/read-ai.png",docsUrl:"https://support.read.ai/hc/en-us/articles/49381158409491-MCP-Server",preferredAuthType:"oauth2",oauth:{authUrl:"https://authn.read.ai/oauth2/auth",tokenUrl:"https://authn.read.ai/oauth2/token",registrationUrl:"https://api.read.ai/oauth/register",scopes:"mcp:execute meeting:read offline_access",resource:"https://api.read.ai/mcp",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Read AI is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Request read-only scopes only. Discover the current tools before use, search narrowly, and retrieve transcript content only when relevant. Never join, record, edit, or otherwise mutate meetings through this integration.",keywords:["meetings","transcripts","summaries","action_items","topics","participants","metrics"]},otterMcp:{name:"otterMcp",mcp:!0,label:"Otter",apiUrl:"https://mcp.otter.ai/mcp",regex:"^https://mcp\\.otter\\.ai/mcp/?(?:\\?.*)?$",icon:"/logos/otter.png",docsUrl:"https://help.otter.ai/hc/en-us/articles/35287607569687-Otter-MCP-Server",preferredAuthType:"oauth2",oauth:{authUrl:"https://otter.ai/oauth2/authorize",tokenUrl:"https://otter.ai/oauth/token",registrationUrl:"https://otter.ai/oauth/register",scopes:"profile:read conversations:read",resource:"https://mcp.otter.ai/",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Otter is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Request read-only scopes only. Discover the current tools before use, search narrowly, and retrieve transcript content only when relevant. Never join, record, edit, or otherwise mutate meetings through this integration.",keywords:["meetings","conversations","transcripts"]},rocketlaneMcp:{name:"rocketlaneMcp",mcp:!0,label:"Rocketlane",apiUrl:"https://mcp.rocketlane.com/mcp",regex:"^https://mcp\\.rocketlane\\.com/mcp/?(?:\\?.*)?$",icon:"/logos/rocketlane.svg",docsUrl:"https://help.rocketlane.com/support/solutions/articles/67000754219-connect-rocketlane-mcp-to-claude-code",preferredAuthType:"oauth2",oauth:{authUrl:"https://rocketlane.scalekit.com/resources/res_121247790507492638/oauth/authorize",tokenUrl:"https://rocketlane.scalekit.com/resources/res_121247790507492638/oauth/token",registrationUrl:"https://rocketlane.scalekit.com/api/v1/resources/res_121247790507492638/clients:register",scopes:"openid email profile",resource:"https://mcp.rocketlane.com/mcp",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Rocketlane is a brain context source (workspace) backed by remote MCP. Load the workspace-apps skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Discover the current tools before use, search narrowly, and retrieve project detail only when relevant.",keywords:["projects","tasks","phases","time_entries","customers","status"]},zoominfoMcp:{name:"zoominfoMcp",mcp:!0,label:"ZoomInfo",apiUrl:"https://mcp.zoominfo.com/mcp",regex:"^https://mcp\\.zoominfo\\.com/mcp/?(?:\\?.*)?$",icon:"/logos/zoominfo.svg",docsUrl:"https://docs.gtm.ai/docs/connect-to-zoominfo-mcp",preferredAuthType:"oauth2",oauth:{authUrl:"https://mcp.zoominfo.com/oauth/authorize",tokenUrl:"https://okta-login.zoominfo.com/oauth2/default/v1/token",scopes:"openid profile email offline_access",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"ZoomInfo is a B2B prospect research System backed by remote MCP. Keep the MCP endpoint unchanged. ZoomInfo accepts dynamic client registration only from approved vendors, so each organization supplies its own OAuth client: a ZoomInfo admin assigns the DevPortal subscription, creates an MCP App at developer.zoominfo.com with the current superglue origin plus /api/auth/callback as the redirect URI, and pastes the client ID and secret into the System. A ZoomInfo admin must also enable API Access for each user under Admin Portal > Users > User Management. Store tokens in the current user's credential. Discover the current tools with tools/list before use. Resolve a company with search_companies before enrich_companies, enrich_company_signals, or account_research, and resolve attendees with search_contacts before enrich_contacts or contact_research. Every search and enrichment consumes the customer's ZoomInfo credits; fetch only the companies and contacts the task needs. ZoomInfo terms restrict storing its data: use results in the current answer and never copy them into brain files, playbooks, or other persistent context.",keywords:["prospects","companies","contacts","enrichment","intent","scoops","sales","meeting_prep"]},googleDrive:{name:"googleDrive",label:"Google Drive",apiUrl:"https://www.googleapis.com/drive/v3",extraApiUrls:["https://www.googleapis.com/upload/drive/v3"],regex:"^.*(googleapis\\.com/drive|developers\\.google\\.com/drive|drive\\.google).*$",icon:"googledrive",docsUrl:"https://developers.google.com/drive/api/v3/reference",openApiUrl:"https://www.googleapis.com/discovery/v1/apis/drive/v3/rest",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/drive.readonly",managed:!0},keywords:["files","folders","permissions","sharing","comments","revisions","changes","uploads","downloads","metadata","teamdrives","export","copy","move","oauth"],systemSpecificInstructions:"Use Drive API v3. Export Google Workspace files and use media download for stored files."},googleCalendar:{name:"googleCalendar",apiUrl:"https://www.googleapis.com/calendar/v3",regex:"^.*(googleapis\\.com/calendar|developers\\.google\\.com/calendar|calendar\\.google).*$",icon:"googlecalendar",docsUrl:"https://developers.google.com/calendar/api/v3/reference",openApiUrl:"https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.settings.readonly",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Calendar; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>.",keywords:["events","calendars","attendees","reminders","recurring","availability","free busy","settings","acl","colors","notifications","timezone","quick add","oauth"]},googleSheets:{name:"googleSheets",apiUrl:"https://sheets.googleapis.com/v4",regex:"^.*(sheets\\.googleapis|developers\\.google\\.com/sheets|sheets\\.google).*$",icon:"googlesheets",docsUrl:"https://developers.google.com/sheets/api/reference/rest",openApiUrl:"https://www.googleapis.com/discovery/v1/apis/sheets/v4/rest",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/drive.file",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Sheets; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>. The drive.file scope only lists files created or opened through this app; open any existing spreadsheet directly by its ID with the spreadsheets scope.",keywords:["spreadsheets","sheets","cells","ranges","values","formulas","formatting","charts","pivot tables","named ranges","protected ranges","batch update","append","oauth"]},googleDocs:{name:"googleDocs",label:"Google Docs",apiUrl:"https://docs.googleapis.com/v1",regex:"^.*(docs\\.googleapis|developers\\.google\\.com/docs|docs\\.google\\.com/document).*$",icon:"googledocs",docsUrl:"https://developers.google.com/docs/api/reference/rest",openApiUrl:"https://docs.googleapis.com/$discovery/rest?version=v1",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/drive.file",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Docs; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>. Create a document with POST /documents and edit it with POST /documents/{documentId}:batchUpdate.",keywords:["documents","docs","text","paragraphs","headings","tables","images","batch update","insert text","replace text","named ranges","oauth"]},googleSlides:{name:"googleSlides",label:"Google Slides",apiUrl:"https://slides.googleapis.com/v1",regex:"^.*(slides\\.googleapis|developers\\.google\\.com/slides|docs\\.google\\.com/presentation).*$",icon:"googleslides",docsUrl:"https://developers.google.com/slides/api/reference/rest",openApiUrl:"https://slides.googleapis.com/$discovery/rest?version=v1",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/presentations https://www.googleapis.com/auth/drive.file",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Slides; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>. Create a presentation with POST /presentations and edit it with POST /presentations/{presentationId}:batchUpdate.",keywords:["presentations","slides","decks","shapes","text boxes","images","layouts","batch update","thumbnails","oauth"]},googleForms:{name:"googleForms",label:"Google Forms",apiUrl:"https://forms.googleapis.com/v1",regex:"^.*(forms\\.googleapis|developers\\.google\\.com/forms|docs\\.google\\.com/forms).*$",icon:"googleforms",docsUrl:"https://developers.google.com/forms/api/reference/rest",openApiUrl:"https://forms.googleapis.com/$discovery/rest?version=v1",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/forms.body https://www.googleapis.com/auth/forms.responses.readonly https://www.googleapis.com/auth/drive.file",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Forms; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>. Create a form with POST /forms (title only), add questions with POST /forms/{formId}:batchUpdate, and read submissions with GET /forms/{formId}/responses.",keywords:["forms","questions","responses","submissions","surveys","quizzes","batch update","items","oauth"]},googleContacts:{name:"googleContacts",label:"Google Contacts",apiUrl:"https://people.googleapis.com/v1",regex:"^.*(people\\.googleapis|developers\\.google\\.com/people|contacts\\.google\\.com).*$",icon:"/logos/google.svg",docsUrl:"https://developers.google.com/people/api/rest",openApiUrl:"https://people.googleapis.com/$discovery/rest?version=v1",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/contacts https://www.googleapis.com/auth/contacts.other.readonly https://www.googleapis.com/auth/directory.readonly",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Contacts; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>. Use /people/me/connections and /people:createContact for saved contacts, /otherContacts for automatically saved contacts, and /people:searchDirectoryPeople for the Google Workspace directory (requires a Workspace account). Every request needs personFields or readMask.",keywords:["contacts","people","directory","other contacts","connections","emails","phone numbers","organizations","search","oauth"]},googleTasks:{name:"googleTasks",label:"Google Tasks",apiUrl:"https://tasks.googleapis.com/tasks/v1",regex:"^.*(tasks\\.googleapis|developers\\.google\\.com/(workspace/)?tasks|tasks\\.google\\.com).*$",icon:"googletasks",docsUrl:"https://developers.google.com/tasks/reference/rest",openApiUrl:"https://tasks.googleapis.com/$discovery/rest?version=v1",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/tasks",managed:!0},systemSpecificInstructions:"superglue provides a managed Google OAuth app for Google Tasks; users connect with their Google login and never need to create a Google Cloud project or supply a client ID or secret. Send OAuth tokens as Authorization: Bearer <<access_token>>. List task lists with GET /users/@me/lists and create tasks with POST /lists/{tasklist}/tasks.",keywords:["tasks","task lists","to-do","due dates","completed","subtasks","oauth"]},googleAnalytics:{name:"googleAnalytics",apiUrl:"https://analytics.google.com",regex:"^.*(analytics|analyticsdata).*$",icon:"googleAnalytics",docsUrl:"https://developers.google.com/analytics/devguides/reporting/data/v1",openApiUrl:"https://analyticsdata.googleapis.com/$discovery/rest?version=v1beta",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/analytics.edit"},keywords:["properties","dimensions","metrics","reports","audiences","conversions","events","goals","segments","real time","user activity","attribution","funnels","cohorts","oauth"]},youtube:{name:"youtube",apiUrl:"https://youtube.googleapis.com",regex:"^.*youtube.*$",icon:"youtube",docsUrl:"https://developers.google.com/youtube/v3/docs",openApiUrl:"https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/youtube"},keywords:["videos","channels","playlists","comments","captions","live streams","analytics","thumbnails","subscriptions","activities","ratings","uploads","members","oauth"]},AWS:{name:"AWS",apiUrl:"https://amazonaws.com",regex:"^.*(aws|amazonaws).*$",icon:"/logos/aws.svg",docsUrl:"https://docs.aws.amazon.com/index.html",preferredAuthType:"api_key",keywords:["ec2","s3","lambda","rds","dynamodb","sqs","sns","cloudformation","iam","cloudwatch","vpc","instances","buckets","functions","api key"]},amazon_sp_api:{name:"amazon_sp_api",apiUrl:"https://sellingpartnerapi-na.amazon.com",regex:"^.*(sellingpartnerapi[-\\w]*\\.amazon\\.com).*$",icon:"/logos/amazon.svg",docsUrl:"https://developer-docs.amazon.com/sp-api/docs",preferredAuthType:"oauth2",oauth:{authUrl:"https://sellercentral.amazon.com/apps/authorize/consent",tokenUrl:"https://api.amazon.com/auth/o2/token",grant_type:"authorization_code",tokenAuthMethod:"body",tokenContentType:"form"},keywords:["orders","catalog items","listings","feeds","reports","fba inbound","fulfillment","inventory","pricing","seller central","marketplace"],systemSpecificInstructions:`Base host is region-specific: sellingpartnerapi-na.amazon.com (US/CA/MX/BR), sellingpartnerapi-eu.amazon.com (EU/UK/IN/ME/AF), sellingpartnerapi-fe.amazon.com (Singapore/AU/JP) \u2014 swap the region segment to match the seller's marketplace; sandbox testing uses sandbox.sellingpartnerapi-<region>.amazon.com. Requires registering an app in Seller Central > Develop Apps first. Third-party apps redirect sellers to https://sellercentral.amazon.com/apps/authorize/consent?application_id=<APP_ID>&state=<STATE> (add &version=beta only while the app is in Draft state, remove once Published); private/single-account developers can skip this by generating a refresh token directly via Seller Central > Develop Apps > "Authorize new developer" (self-authorization). Access tokens require header x-amz-access-token in addition to Authorization; some operations (e.g. FBA/notifications) use a separate grantless client_credentials flow instead of the refresh-token flow.`},googleCloud:{name:"googleCloud",apiUrl:"https://cloud.google.com",regex:"^.*(cloud\\.google|gcp|googlecloud).*$",icon:"googleCloud",docsUrl:"https://cloud.google.com/apis/docs/overview",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/cloud-platform"},keywords:["compute","storage","pubsub","cloud run","kubernetes","iam","vpc","cloud sql","bigtable","dataflow","logging","monitoring","oauth"]},bigquery:{name:"bigquery",apiUrl:"https://bigquery.googleapis.com/bigquery/v2",regex:"^.*(bigquery|bq\\.googleapis).*$",icon:"googleCloud",docsUrl:"https://cloud.google.com/bigquery/docs/reference/rest",openApiUrl:"https://bigquery.googleapis.com/$discovery/rest?version=v2",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/bigquery"},systemSpecificInstructions:`BigQuery REST API - Authentication Options:
1118
1118
 
1119
1119
  OPTION 1: OAuth App (Recommended)
1120
1120
  If the user has or creates an OAuth app in their Google Cloud project:
@@ -1151,7 +1151,7 @@ Create the developer app from the Ramp dashboard's Developer area with an Admin
1151
1151
 
1152
1152
  Token exchange is POST /developer/v1/token with form content, grant_type=client_credentials, and HTTP Basic auth using client_id:client_secret. Subsequent API calls use Authorization: Bearer <<access_token>>. Tokens are environment-bound and scope-bound; client-credentials tokens last 10 days.
1153
1153
 
1154
- For third-party or public multi-customer apps, use Ramp's authorization-code flow instead of Client Credentials: authorization endpoint https://api.ramp.com/v1/authorize and token endpoint https://api.ramp.com/developer/v1/token. Only users with Developer API authorization permissions, typically Admin or Business Owner users, can authorize apps. Sensitive scopes such as cards:read_vault require additional security review.`},remote:{name:"remote",apiUrl:"https://gateway.remote.com",regex:"^https?:\\/\\/(?:[^/]+\\.)*remote(?:-sandbox)?\\.com(?:[:/?#].*)?$",icon:"/logos/remote.svg",docsUrl:"https://developer.remote.com/docs/getting-started-with-remote",preferredAuthType:"api_key",keywords:["companies","employments","employees","contractors","countries","legal entities","expenses","payroll","onboarding","eligibility"],systemSpecificInstructions:"Remote customer API tokens are environment-specific: ra_live_ tokens work only with https://gateway.remote.com, while ra_test_ tokens work only with https://gateway.remote-sandbox.com. Company admins and owners generate tokens in Company Settings > Integrations & APIs > Integrations > Remote API. Send the token as Authorization: Bearer <token>; API routes begin with /v1/. This template targets customer API tokens; Remote partners may instead use OAuth flows."},xero:{name:"xero",apiUrl:"https://api.xero.com",regex:"^.*xero.*$",icon:"xero",docsUrl:"https://developer.xero.com/documentation/api/api-overview",openApiUrl:"https://raw.githubusercontent.com/XeroAPI/Xero-OpenAPI/master/xero_accounting.yaml",preferredAuthType:"oauth2",oauth:{authUrl:"https://login.xero.com/identity/connect/authorize",tokenUrl:"https://identity.xero.com/connect/token",scopes:"accounting.transactions accounting.transactions.read accounting.reports.read accounting.journals.read accounting.settings accounting.settings.read accounting.contacts accounting.contacts.read accounting.attachments accounting.attachments.read payroll.employees payroll.payruns payroll.payslip payroll.timesheets payroll.settings"},keywords:["accounts","invoices","contacts","bills","credit notes","bank transactions","payments","receipts","journals","purchase orders","quotes","reports","tax rates","tracking categories","payroll","oauth"]},myob:{name:"myob",apiUrl:"https://api.myob.com/accountright",regex:"^.*myob.*$",icon:"simpleicons:myob",docsUrl:"https://developer.myob.com/api/myob-business-api/api-overview/",preferredAuthType:"oauth2",oauth:{authUrl:"https://secure.myob.com/oauth2/account/authorize",tokenUrl:"https://secure.myob.com/oauth2/v1/authorize",scopes:"sme-general-ledger sme-sales sme-timebilling sme-inventory sme-contacts-customer sme-contacts-supplier sme-contacts-personal sme-contacts-employee sme-banking sme-purchases sme-payroll sme-company-settings sme-company-file",tokenAuthMethod:"body",tokenContentType:"form"},keywords:["invoices","contacts","accounts","bank transactions","items","purchase orders","sale orders","payroll","employees","company files","general ledger","tax codes"],systemSpecificInstructions:"Every request needs three headers beyond the bearer token: x-myobapi-key (app's API key), x-myobapi-version: v2, and x-myobapi-cftoken (Base64 of company-file username:password, required even with OAuth \u2014 desktop AccountRight files have no OAuth and use only this header). After OAuth redirect, the businessId returned is the cf_uri (company file UID) that must prefix every subsequent request path under the accountright base. Register the app and get the API key/secret from the Developer tab at my.MYOB.com, not from api.myob.com itself."},docusign:{name:"docusign",apiUrl:"https://api.docusign.com",regex:"^.*docusign.*$",icon:"/logos/docusign.svg",docsUrl:"https://developers.docusign.com/docs/esign-rest-api",openApiUrl:"https://raw.githubusercontent.com/docusign/OpenAPI-Specifications/refs/heads/master/esignature.rest.swagger-v2.1.json",preferredAuthType:"oauth2",oauth:{authUrl:"https://account.docusign.com/oauth/auth",tokenUrl:"https://account.docusign.com/oauth/token",scopes:"signature extended impersonation organization_read group_read permission_read user_read user_write account_read domain_read identity_provider_read user_data_redact asset_group_account_read asset_group_account_clone_write asset_group_account_clone_read"},keywords:["envelopes","documents","recipients","templates","signatures","tabs","brands","accounts","users","groups","powerforms","bulk send","connect","custom fields","oauth"]},deribit:{name:"deribit",apiUrl:"https://www.deribit.com/api/v2",regex:"^.*deribit.*$",icon:"deribit",docsUrl:"https://docs.deribit.com",preferredAuthType:"oauth2",oauth:{tokenUrl:"https://www.deribit.com/api/v2/public/auth",grant_type:"client_credentials",tokenContentType:"json"},keywords:["instruments","order_book","trades","orders","positions","accounts","wallet","deposits","withdrawals","market_data","options","futures","perpetuals"],systemSpecificInstructions:'Deribit uses a JSON-RPC 2.0 API over HTTPS. The token endpoint is /api/v2/public/auth \u2014 send client_id and client_secret as JSON body with grant_type: "client_credentials". Access tokens are Bearer tokens with a 900-second TTL; use /api/v2/public/auth with grant_type: "refresh_token" to renew. Deribit provides a testnet at https://test.deribit.com/api/v2 with separate credentials \u2014 register at test.deribit.com for a demo account.'},intercom:{name:"intercom",apiUrl:"https://api.intercom.io",regex:"^.*intercom.*$",icon:"intercom",docsUrl:"https://developers.intercom.com/intercom-api-reference",openApiUrl:"https://raw.githubusercontent.com/intercom/Intercom-OpenAPI/refs/heads/main/descriptions/2.9/api.intercom.io.yaml",preferredAuthType:"api_key",oauth:{authUrl:"https://app.intercom.com/oauth",tokenUrl:"https://api.intercom.io/auth/eagle/token",scopes:"inbox:read inbox:write users:read users:write companies:read companies:write contacts:read contacts:write conversations:read conversations:write help_center:read help_center:write teams:read teams:write tags:read tags:write segments:read events:write counts:read"},keywords:["contacts","conversations","messages","users","companies","events","tags","segments","articles","help center","teams","admins","inbox","notes","custom attributes","query","api key"]},asana:{name:"asana",apiUrl:"https://app.asana.com/api",regex:"^.*asana.*$",icon:"asana",docsUrl:"https://developers.asana.com/docs",openApiUrl:"https://raw.githubusercontent.com/Asana/openapi/master/defs/asana_oas.yaml",preferredAuthType:"api_key",oauth:{authUrl:"https://app.asana.com/-/oauth_authorize",tokenUrl:"https://app.asana.com/-/oauth_token",scopes:"default openid email profile",grant_type:"authorization_code",managed:!0},keywords:["tasks","projects","workspaces","teams","portfolios","goals","sections","tags","custom fields","stories","attachments","followers","assignee","due dates","query","search","api key"]},trello:{name:"trello",apiUrl:"https://api.trello.com",regex:"^.*trello.*$",icon:"trello",docsUrl:"https://developer.atlassian.com/cloud/trello/rest",openApiUrl:"https://developer.atlassian.com/cloud/trello/swagger.v3.json",preferredAuthType:"api_key",keywords:["boards","lists","cards","members","labels","checklists","attachments","comments","actions","organizations","teams","power-ups","custom fields","stickers","api key"]},notion:{name:"notion",label:"Notion",apiUrl:"https://api.notion.com",regex:"^.*notion.*$",icon:"notion",docsUrl:"https://developers.notion.com",openApiUrl:"https://raw.githubusercontent.com/cameronking4/notion-openapi-chatgpt-action/refs/heads/main/public/notion-openapi.json",preferredAuthType:"oauth2",oauth:{authUrl:"https://api.notion.com/v1/oauth/authorize?owner=user",tokenUrl:"https://api.notion.com/v1/oauth/token",scopes:"read_content read_comments read_user",managed:!0,tokenAuthMethod:"basic_auth",tokenContentType:"json",extraHeaders:{"Notion-Version":"2022-06-28"}},systemSpecificInstructions:"Notion OAuth exposes only pages selected for the connection and their accessible children.",keywords:["pages","databases","blocks","users","workspaces","properties","rich text","search","comments","parent","children","query","filter","sort","api key"]},digitalocean:{name:"digitalocean",apiUrl:"https://api.digitalocean.com",regex:"^.*digitalocean.*$",icon:"digitalocean",docsUrl:"https://docs.digitalocean.com/reference/api",openApiUrl:"https://raw.githubusercontent.com/digitalocean/openapi/refs/heads/main/specification/DigitalOcean-public.v2.yaml",preferredAuthType:"api_key",oauth:{authUrl:"https://cloud.digitalocean.com/v1/oauth/authorize",tokenUrl:"https://cloud.digitalocean.com/v1/oauth/token",scopes:"read write admin"},keywords:["droplets","volumes","images","snapshots","regions","sizes","ssh_keys","domains","domain_records","certificates","firewalls","load_balancers","projects","tags","vpcs","api key"]},heroku:{name:"heroku",apiUrl:"https://api.heroku.com",regex:"^.*heroku.*$",icon:"/logos/heroku.svg",docsUrl:"https://devcenter.heroku.com/categories/platform-api",preferredAuthType:"api_key",oauth:{authUrl:"https://id.heroku.com/oauth/authorize",tokenUrl:"https://id.heroku.com/oauth/token",scopes:"global read write read-protected write-protected"},keywords:["apps","addons","builds","releases","config_vars","formations","dynos","buildpacks","domains","collaborators","keys","account","apps/~/addons","spaces","pipelines","api key"]},huggingface:{name:"huggingface",apiUrl:"https://huggingface.co",regex:"^.*huggingface.*$",icon:"huggingface",docsUrl:"https://huggingface.co/docs/hub/en/api",preferredAuthType:"api_key",keywords:["models","datasets","spaces","parameters","inference","fine-tuning","files","spaces","accounts","groups","api key"]},circleci:{name:"circleci",apiUrl:"https://circleci.com/api",regex:"^.*circleci.*$",icon:"circleci",docsUrl:"https://circleci.com/docs/api",openApiUrl:"https://circleci.com/api/v2/openapi.json",preferredAuthType:"api_key",keywords:["pipelines","workflows","jobs","projects","builds","artifacts","environment_variables","contexts","orbs","insights","schedules","checkouts","api key"]},travisci:{name:"travisci",apiUrl:"https://api.travis-ci.com",regex:"^.*(travis|travis-ci).*$",icon:"travisCI",docsUrl:"https://docs.travis-ci.com/api",preferredAuthType:"api_key",keywords:["builds","jobs","repositories","branches","requests","caches","env_vars","settings","logs","stages","beta_features","api key"]},wordpress:{name:"wordpress",apiUrl:"https://{your-site.com}/wp-json/wp/v2",regex:"^.*wordpress.*$",icon:"wordpress",docsUrl:"https://developer.wordpress.org/rest-api",openApiUrl:"https://developer.wordpress.com/docs/api/",preferredAuthType:"api_key",keywords:["posts","pages","media","users","categories","tags","comments","taxonomies","types","statuses","settings","themes","plugins","api key"]},cloudflare:{name:"cloudflare",apiUrl:"https://api.cloudflare.com",regex:"^.*cloudflare.*$",icon:"cloudflare",docsUrl:"https://developers.cloudflare.com/api",openApiUrl:"https://raw.githubusercontent.com/cloudflare/api-schemas/refs/heads/main/openapi.json",preferredAuthType:"api_key",keywords:["zones","dns_records","firewall_rules","page_rules","workers","certificates","load_balancers","rate_limits","waf","analytics","cache","ssl","api key"]},bigcommerce:{name:"bigcommerce",apiUrl:"https://api.bigcommerce.com",regex:"^.*bigcommerce.*$",icon:"bigcommerce",docsUrl:"https://developer.bigcommerce.com/docs/rest-management",preferredAuthType:"api_key",keywords:["products","categories","brands","orders","customers","carts","checkouts","coupons","price_lists","customer_groups","shipping","store_content","themes","api key"]},woocommerce:{name:"woocommerce",apiUrl:"https://{yourstore.com}/wp-json/wc/v3",regex:"^.*woocommerce.*$",icon:"woocommerce",docsUrl:"https://woocommerce.github.io/woocommerce-rest-api-docs",preferredAuthType:"api_key",keywords:["products","orders","customers","coupons","categories","shipping_classes","tax_classes","payment_gateways","shipping_zones","shipping_methods","product_variations","refunds","reports","api key"]},prestashop:{name:"prestashop",apiUrl:"https://{yourstore.com}/api",regex:"^.*prestashop.*$",icon:"prestashop",docsUrl:"https://devdocs.prestashop-project.org/8/webservice",preferredAuthType:"api_key",keywords:["products","categories","customers","addresses","carts","orders","carriers","countries","currencies","languages","manufacturers","suppliers","stocks","api key"]},squarespace:{name:"squarespace",apiUrl:"https://api.squarespace.com",regex:"^.*squarespace.*$",icon:"squarespace",docsUrl:"https://developers.squarespace.com/commerce-apis",preferredAuthType:"oauth2",oauth:{authUrl:"https://login.squarespace.com/api/1/login/oauth/provider/authorize",tokenUrl:"https://login.squarespace.com/api/1/login/oauth/provider/tokens",scopes:"website.products.read website.products.write website.orders.read website.orders.write website.inventory.read website.transactions.read website.store_settings.read email.campaigns.read email.campaigns.send"},keywords:["products","orders","inventory","transactions","profiles","store_pages","categories","discounts","gift_cards","abandoned_carts","webhooks","oauth"]},monday:{name:"monday",apiUrl:"https://api.monday.com/v2",regex:"^.*monday.*$",icon:"/logos/monday.svg",docsUrl:"https://developer.monday.com/api-reference/docs",preferredAuthType:"api_key",oauth:{authUrl:"https://auth.monday.com/oauth2/authorize",tokenUrl:"https://auth.monday.com/oauth2/token",scopes:"me:read users:read boards:read boards:write workspaces:read workspaces:write webhooks:write updates:read updates:write assets:read assets:write tags:read teams:read"},keywords:["boards","items","groups","columns","updates","users","workspaces","tags","files","activities","teams","subitems","graphql","mutations","query","api key"]},clickup:{name:"clickup",label:"ClickUp",apiUrl:"https://api.clickup.com/api/v2",regex:"^.*clickup.*$",icon:"clickup",docsUrl:"https://clickup.com/api",openApiUrl:"https://developer.clickup.com/openapi/clickup-api-v2-reference.json",preferredAuthType:"oauth2",oauth:{grant_type:"authorization_code",authUrl:"https://app.clickup.com/api",tokenUrl:"https://api.clickup.com/api/v2/oauth/token",managed:!0},keywords:["tasks","lists","folders","spaces","teams","goals","views","statuses","priorities","tags","custom fields","time tracking","comments","checklists","dependencies","api key","oauth"],systemSpecificInstructions:"superglue provides a managed ClickUp OAuth app; users connect with their ClickUp login and pick the Workspaces to authorize on the consent screen. ClickUp OAuth has no scopes and issues no refresh token; access tokens currently do not expire. Send OAuth tokens as Authorization: Bearer <<access_token>>. Alternatively, a personal API token (pk_...) works as Authorization: <<api_key>> without the Bearer prefix. GET /team lists the authorized Workspaces (called teams in API v2)."},typeform:{name:"typeform",apiUrl:"https://api.typeform.com",regex:"^.*typeform.*$",icon:"typeform",docsUrl:"https://developer.typeform.com",preferredAuthType:"oauth2",oauth:{authUrl:"https://api.typeform.com/oauth/authorize",tokenUrl:"https://api.typeform.com/oauth/token",scopes:"forms:read forms:write responses:read responses:write themes:read themes:write images:read images:write workspaces:read workspaces:write webhooks:read webhooks:write accounts:read offline"},keywords:["forms","responses","questions","fields","themes","images","workspaces","logic jumps","hidden fields","variables","calculations","insights","reports","oauth"]},figma:{name:"figma",apiUrl:"https://api.figma.com",regex:"^(.*\\.)?figma\\.com(/.*)?$",icon:"figma",docsUrl:"https://www.figma.com/developers/api",openApiUrl:"https://raw.githubusercontent.com/figma/rest-api-spec/refs/heads/main/openapi/openapi.yaml",preferredAuthType:"oauth2",oauth:{authUrl:"https://www.figma.com/oauth",tokenUrl:"https://www.figma.com/api/oauth/token",scopes:"file_read file_write file_dev_resources:read file_dev_resources:write webhooks:write"},keywords:["files","projects","teams","components","styles","nodes","frames","pages","images","comments","versions","branches","libraries","plugins","oauth"]},contentful:{name:"contentful",apiUrl:"https://api.contentful.com",regex:"^(.*\\.)?contentful\\.com(/.*)?$",icon:"contentful",docsUrl:"https://www.contentful.com/developers/docs/references/content-management-api",preferredAuthType:"api_key",keywords:["spaces","environments","content types","entries","assets","locales","tags","webhooks","roles","api keys","content model","publishing","preview","api key"]},creatio:{name:"creatio",apiUrl:"https://<<instance>>.creatio.com/0/odata",regex:"^(.*\\.)?creatio\\.com(/.*)?$",icon:"/logos/creatio.ico",docsUrl:"https://academy.creatio.com/docs/developer/integrations_and_api/data_services/odata/overview",preferredAuthType:"oauth2",oauth:{authUrl:"https://<<instance>>.creatio.com/0/connect/authorize",tokenUrl:"https://<<instance>>.creatio.com/0/connect/token",scopes:"offline_access",grant_type:"authorization_code"},systemSpecificInstructions:`Creatio uses OIDC-compliant OAuth endpoints. The standard /ServiceModel/AuthService.svc/Authorize and /rest/oauth/token endpoints are behind IIS session auth and will NOT work for OAuth flows \u2014 you MUST use the /0/connect/* OIDC endpoints instead.
1154
+ For third-party or public multi-customer apps, use Ramp's authorization-code flow instead of Client Credentials: authorization endpoint https://api.ramp.com/v1/authorize and token endpoint https://api.ramp.com/developer/v1/token. Only users with Developer API authorization permissions, typically Admin or Business Owner users, can authorize apps. Sensitive scopes such as cards:read_vault require additional security review.`},remote:{name:"remote",apiUrl:"https://gateway.remote.com",regex:"^https?:\\/\\/(?:[^/]+\\.)*remote(?:-sandbox)?\\.com(?:[:/?#].*)?$",icon:"/logos/remote.svg",docsUrl:"https://developer.remote.com/docs/getting-started-with-remote",preferredAuthType:"api_key",keywords:["companies","employments","employees","contractors","countries","legal entities","expenses","payroll","onboarding","eligibility"],systemSpecificInstructions:"Remote customer API tokens are environment-specific: ra_live_ tokens work only with https://gateway.remote.com, while ra_test_ tokens work only with https://gateway.remote-sandbox.com. Company admins and owners generate tokens in Company Settings > Integrations & APIs > Integrations > Remote API. Send the token as Authorization: Bearer <token>; API routes begin with /v1/. This template targets customer API tokens; Remote partners may instead use OAuth flows."},xero:{name:"xero",apiUrl:"https://api.xero.com",regex:"^.*xero.*$",icon:"xero",docsUrl:"https://developer.xero.com/documentation/api/api-overview",openApiUrl:"https://raw.githubusercontent.com/XeroAPI/Xero-OpenAPI/master/xero_accounting.yaml",preferredAuthType:"oauth2",oauth:{authUrl:"https://login.xero.com/identity/connect/authorize",tokenUrl:"https://identity.xero.com/connect/token",scopes:"accounting.transactions accounting.transactions.read accounting.reports.read accounting.journals.read accounting.settings accounting.settings.read accounting.contacts accounting.contacts.read accounting.attachments accounting.attachments.read payroll.employees payroll.payruns payroll.payslip payroll.timesheets payroll.settings"},keywords:["accounts","invoices","contacts","bills","credit notes","bank transactions","payments","receipts","journals","purchase orders","quotes","reports","tax rates","tracking categories","payroll","oauth"]},myob:{name:"myob",apiUrl:"https://api.myob.com/accountright",regex:"^.*myob.*$",icon:"simpleicons:myob",docsUrl:"https://developer.myob.com/api/myob-business-api/api-overview/",preferredAuthType:"oauth2",oauth:{authUrl:"https://secure.myob.com/oauth2/account/authorize",tokenUrl:"https://secure.myob.com/oauth2/v1/authorize",scopes:"sme-general-ledger sme-sales sme-timebilling sme-inventory sme-contacts-customer sme-contacts-supplier sme-contacts-personal sme-contacts-employee sme-banking sme-purchases sme-payroll sme-company-settings sme-company-file",tokenAuthMethod:"body",tokenContentType:"form"},keywords:["invoices","contacts","accounts","bank transactions","items","purchase orders","sale orders","payroll","employees","company files","general ledger","tax codes"],systemSpecificInstructions:"Every request needs three headers beyond the bearer token: x-myobapi-key (app's API key), x-myobapi-version: v2, and x-myobapi-cftoken (Base64 of company-file username:password, required even with OAuth \u2014 desktop AccountRight files have no OAuth and use only this header). After OAuth redirect, the businessId returned is the cf_uri (company file UID) that must prefix every subsequent request path under the accountright base. Register the app and get the API key/secret from the Developer tab at my.MYOB.com, not from api.myob.com itself."},docusign:{name:"docusign",apiUrl:"https://api.docusign.com",regex:"^.*docusign.*$",icon:"/logos/docusign.svg",docsUrl:"https://developers.docusign.com/docs/esign-rest-api",openApiUrl:"https://raw.githubusercontent.com/docusign/OpenAPI-Specifications/refs/heads/master/esignature.rest.swagger-v2.1.json",preferredAuthType:"oauth2",oauth:{authUrl:"https://account.docusign.com/oauth/auth",tokenUrl:"https://account.docusign.com/oauth/token",scopes:"signature extended impersonation organization_read group_read permission_read user_read user_write account_read domain_read identity_provider_read user_data_redact asset_group_account_read asset_group_account_clone_write asset_group_account_clone_read"},keywords:["envelopes","documents","recipients","templates","signatures","tabs","brands","accounts","users","groups","powerforms","bulk send","connect","custom fields","oauth"]},deribit:{name:"deribit",apiUrl:"https://www.deribit.com/api/v2",regex:"^.*deribit.*$",icon:"deribit",docsUrl:"https://docs.deribit.com",preferredAuthType:"oauth2",oauth:{tokenUrl:"https://www.deribit.com/api/v2/public/auth",grant_type:"client_credentials",tokenContentType:"json"},keywords:["instruments","order_book","trades","orders","positions","accounts","wallet","deposits","withdrawals","market_data","options","futures","perpetuals"],systemSpecificInstructions:'Deribit uses a JSON-RPC 2.0 API over HTTPS. The token endpoint is /api/v2/public/auth \u2014 send client_id and client_secret as JSON body with grant_type: "client_credentials". Access tokens are Bearer tokens with a 900-second TTL; use /api/v2/public/auth with grant_type: "refresh_token" to renew. Deribit provides a testnet at https://test.deribit.com/api/v2 with separate credentials \u2014 register at test.deribit.com for a demo account.'},intercom:{name:"intercom",apiUrl:"https://api.intercom.io",regex:"^.*intercom.*$",icon:"intercom",docsUrl:"https://developers.intercom.com/intercom-api-reference",openApiUrl:"https://raw.githubusercontent.com/intercom/Intercom-OpenAPI/refs/heads/main/descriptions/2.9/api.intercom.io.yaml",preferredAuthType:"api_key",oauth:{authUrl:"https://app.intercom.com/oauth",tokenUrl:"https://api.intercom.io/auth/eagle/token",scopes:"inbox:read inbox:write users:read users:write companies:read companies:write contacts:read contacts:write conversations:read conversations:write help_center:read help_center:write teams:read teams:write tags:read tags:write segments:read events:write counts:read"},keywords:["contacts","conversations","messages","users","companies","events","tags","segments","articles","help center","teams","admins","inbox","notes","custom attributes","query","api key"]},asana:{name:"asana",apiUrl:"https://app.asana.com/api",regex:"^.*asana.*$",icon:"asana",docsUrl:"https://developers.asana.com/docs",openApiUrl:"https://raw.githubusercontent.com/Asana/openapi/master/defs/asana_oas.yaml",preferredAuthType:"api_key",oauth:{authUrl:"https://app.asana.com/-/oauth_authorize",tokenUrl:"https://app.asana.com/-/oauth_token",scopes:"default openid email profile",grant_type:"authorization_code",managed:!0},keywords:["tasks","projects","workspaces","teams","portfolios","goals","sections","tags","custom fields","stories","attachments","followers","assignee","due dates","query","search","api key"]},trello:{name:"trello",apiUrl:"https://api.trello.com",regex:"^.*trello.*$",icon:"trello",docsUrl:"https://developer.atlassian.com/cloud/trello/rest",openApiUrl:"https://developer.atlassian.com/cloud/trello/swagger.v3.json",preferredAuthType:"api_key",keywords:["boards","lists","cards","members","labels","checklists","attachments","comments","actions","organizations","teams","power-ups","custom fields","stickers","api key"]},notion:{name:"notion",label:"Notion",apiUrl:"https://api.notion.com",regex:"^.*notion.*$",icon:"notion",docsUrl:"https://developers.notion.com",openApiUrl:"https://raw.githubusercontent.com/cameronking4/notion-openapi-chatgpt-action/refs/heads/main/public/notion-openapi.json",preferredAuthType:"oauth2",oauth:{authUrl:"https://api.notion.com/v1/oauth/authorize?owner=user",tokenUrl:"https://api.notion.com/v1/oauth/token",scopes:"read_content read_comments read_user",managed:!0,tokenAuthMethod:"basic_auth",tokenContentType:"json",extraHeaders:{"Notion-Version":"2022-06-28"}},systemSpecificInstructions:"Notion OAuth exposes only pages selected for the connection and their accessible children.",keywords:["pages","databases","blocks","users","workspaces","properties","rich text","search","comments","parent","children","query","filter","sort","api key"]},digitalocean:{name:"digitalocean",apiUrl:"https://api.digitalocean.com",regex:"^.*digitalocean.*$",icon:"digitalocean",docsUrl:"https://docs.digitalocean.com/reference/api",openApiUrl:"https://raw.githubusercontent.com/digitalocean/openapi/refs/heads/main/specification/DigitalOcean-public.v2.yaml",preferredAuthType:"api_key",oauth:{authUrl:"https://cloud.digitalocean.com/v1/oauth/authorize",tokenUrl:"https://cloud.digitalocean.com/v1/oauth/token",scopes:"read write admin"},keywords:["droplets","volumes","images","snapshots","regions","sizes","ssh_keys","domains","domain_records","certificates","firewalls","load_balancers","projects","tags","vpcs","api key"]},heroku:{name:"heroku",apiUrl:"https://api.heroku.com",regex:"^.*heroku.*$",icon:"/logos/heroku.svg",docsUrl:"https://devcenter.heroku.com/categories/platform-api",preferredAuthType:"api_key",oauth:{authUrl:"https://id.heroku.com/oauth/authorize",tokenUrl:"https://id.heroku.com/oauth/token",scopes:"global read write read-protected write-protected"},keywords:["apps","addons","builds","releases","config_vars","formations","dynos","buildpacks","domains","collaborators","keys","account","apps/~/addons","spaces","pipelines","api key"]},huggingface:{name:"huggingface",apiUrl:"https://huggingface.co",regex:"^.*huggingface.*$",icon:"huggingface",docsUrl:"https://huggingface.co/docs/hub/en/api",preferredAuthType:"api_key",keywords:["models","datasets","spaces","parameters","inference","fine-tuning","files","spaces","accounts","groups","api key"]},circleci:{name:"circleci",apiUrl:"https://circleci.com/api",regex:"^.*circleci.*$",icon:"circleci",docsUrl:"https://circleci.com/docs/api",openApiUrl:"https://circleci.com/api/v2/openapi.json",preferredAuthType:"api_key",keywords:["pipelines","workflows","jobs","projects","builds","artifacts","environment_variables","contexts","orbs","insights","schedules","checkouts","api key"]},travisci:{name:"travisci",apiUrl:"https://api.travis-ci.com",regex:"^.*(travis|travis-ci).*$",icon:"travisCI",docsUrl:"https://docs.travis-ci.com/api",preferredAuthType:"api_key",keywords:["builds","jobs","repositories","branches","requests","caches","env_vars","settings","logs","stages","beta_features","api key"]},wordpress:{name:"wordpress",apiUrl:"https://{your-site.com}/wp-json/wp/v2",regex:"^.*wordpress.*$",icon:"wordpress",docsUrl:"https://developer.wordpress.org/rest-api",openApiUrl:"https://developer.wordpress.com/docs/api/",preferredAuthType:"api_key",keywords:["posts","pages","media","users","categories","tags","comments","taxonomies","types","statuses","settings","themes","plugins","api key"]},cloudflare:{name:"cloudflare",apiUrl:"https://api.cloudflare.com",regex:"^.*cloudflare.*$",icon:"cloudflare",docsUrl:"https://developers.cloudflare.com/api",openApiUrl:"https://raw.githubusercontent.com/cloudflare/api-schemas/refs/heads/main/openapi.json",preferredAuthType:"api_key",keywords:["zones","dns_records","firewall_rules","page_rules","workers","certificates","load_balancers","rate_limits","waf","analytics","cache","ssl","api key"]},bigcommerce:{name:"bigcommerce",apiUrl:"https://api.bigcommerce.com",regex:"^.*bigcommerce.*$",icon:"bigcommerce",docsUrl:"https://developer.bigcommerce.com/docs/rest-management",preferredAuthType:"api_key",keywords:["products","categories","brands","orders","customers","carts","checkouts","coupons","price_lists","customer_groups","shipping","store_content","themes","api key"]},woocommerce:{name:"woocommerce",apiUrl:"https://{yourstore.com}/wp-json/wc/v3",regex:"^.*woocommerce.*$",icon:"woocommerce",docsUrl:"https://woocommerce.github.io/woocommerce-rest-api-docs",preferredAuthType:"api_key",keywords:["products","orders","customers","coupons","categories","shipping_classes","tax_classes","payment_gateways","shipping_zones","shipping_methods","product_variations","refunds","reports","api key"]},prestashop:{name:"prestashop",apiUrl:"https://{yourstore.com}/api",regex:"^.*prestashop.*$",icon:"prestashop",docsUrl:"https://devdocs.prestashop-project.org/8/webservice",preferredAuthType:"api_key",keywords:["products","categories","customers","addresses","carts","orders","carriers","countries","currencies","languages","manufacturers","suppliers","stocks","api key"]},squarespace:{name:"squarespace",apiUrl:"https://api.squarespace.com",regex:"^.*squarespace.*$",icon:"squarespace",docsUrl:"https://developers.squarespace.com/commerce-apis",preferredAuthType:"oauth2",oauth:{authUrl:"https://login.squarespace.com/api/1/login/oauth/provider/authorize",tokenUrl:"https://login.squarespace.com/api/1/login/oauth/provider/tokens",scopes:"website.products.read website.products.write website.orders.read website.orders.write website.inventory.read website.transactions.read website.store_settings.read email.campaigns.read email.campaigns.send"},keywords:["products","orders","inventory","transactions","profiles","store_pages","categories","discounts","gift_cards","abandoned_carts","webhooks","oauth"]},monday:{name:"monday",apiUrl:"https://api.monday.com/v2",regex:"^.*monday.*$",icon:"/logos/monday.svg",docsUrl:"https://developer.monday.com/api-reference/docs",preferredAuthType:"api_key",oauth:{authUrl:"https://auth.monday.com/oauth2/authorize",tokenUrl:"https://auth.monday.com/oauth2/token",scopes:"me:read users:read boards:read boards:write workspaces:read workspaces:write webhooks:write updates:read updates:write assets:read assets:write tags:read teams:read"},keywords:["boards","items","groups","columns","updates","users","workspaces","tags","files","activities","teams","subitems","graphql","mutations","query","api key"]},clickup:{name:"clickup",label:"ClickUp",apiUrl:"https://api.clickup.com/api/v2",regex:"^.*clickup.*$",icon:"clickup",docsUrl:"https://clickup.com/api",openApiUrl:"https://developer.clickup.com/openapi/clickup-api-v2-reference.json",preferredAuthType:"oauth2",oauth:{grant_type:"authorization_code",authUrl:"https://app.clickup.com/api",tokenUrl:"https://api.clickup.com/api/v2/oauth/token",managed:!0},keywords:["tasks","lists","folders","spaces","teams","goals","views","statuses","priorities","tags","custom fields","time tracking","comments","checklists","dependencies","api key","oauth"],systemSpecificInstructions:"superglue provides a managed ClickUp OAuth app; users connect with their ClickUp login and pick the Workspaces to authorize on the consent screen. ClickUp OAuth has no scopes and issues no refresh token; access tokens currently do not expire. Send OAuth tokens as Authorization: Bearer <<access_token>>. Alternatively, a personal API token (pk_...) works as Authorization: <<api_key>> without the Bearer prefix. GET /team lists the authorized Workspaces (called teams in API v2)."},smartsheet:{name:"smartsheet",label:"Smartsheet",apiUrl:"https://api.smartsheet.com/2.0",regex:"^https?:\\/\\/(?:[^/]+\\.)*smartsheet\\.com(?:[:/?#].*)?$",icon:"/logos/smartsheet.png",docsUrl:"https://developers.smartsheet.com/api/smartsheet/openapi",preferredAuthType:"oauth2",oauth:{authUrl:"https://app.smartsheet.com/b/authorize",tokenUrl:"https://api.smartsheet.com/2.0/token",scopes:"READ_SHEETS WRITE_SHEETS CREATE_SHEETS READ_SIGHTS READ_USERS",managed:!0,tokenAuthMethod:"body",tokenContentType:"form"},keywords:["sheets","rows","columns","cells","reports","dashboards","sights","workspaces","folders","attachments","discussions","projects","gantt","api key","oauth"],systemSpecificInstructions:"Smartsheet API 2.0 on the US region. Send OAuth access tokens as Authorization: Bearer <<access_token>>; a personal API access token works the same way. Access tokens expire after 7 days and each refresh returns a new refresh token. Smartsheet Regions Europe (api.smartsheet.eu), Smartsheet Regions Australia (api.smartsheet.au), and Smartsheet Gov are separate accounts with separate tokens and do not accept US tokens. Dashboards are called sights in the API. Most list endpoints page with page and pageSize, or includeAll=true; GET /workspaces uses token pagination with maxItems and lastKey."},typeform:{name:"typeform",apiUrl:"https://api.typeform.com",regex:"^.*typeform.*$",icon:"typeform",docsUrl:"https://developer.typeform.com",preferredAuthType:"oauth2",oauth:{authUrl:"https://api.typeform.com/oauth/authorize",tokenUrl:"https://api.typeform.com/oauth/token",scopes:"forms:read forms:write responses:read responses:write themes:read themes:write images:read images:write workspaces:read workspaces:write webhooks:read webhooks:write accounts:read offline"},keywords:["forms","responses","questions","fields","themes","images","workspaces","logic jumps","hidden fields","variables","calculations","insights","reports","oauth"]},figma:{name:"figma",apiUrl:"https://api.figma.com",regex:"^(.*\\.)?figma\\.com(/.*)?$",icon:"figma",docsUrl:"https://www.figma.com/developers/api",openApiUrl:"https://raw.githubusercontent.com/figma/rest-api-spec/refs/heads/main/openapi/openapi.yaml",preferredAuthType:"oauth2",oauth:{authUrl:"https://www.figma.com/oauth",tokenUrl:"https://www.figma.com/api/oauth/token",scopes:"file_read file_write file_dev_resources:read file_dev_resources:write webhooks:write"},keywords:["files","projects","teams","components","styles","nodes","frames","pages","images","comments","versions","branches","libraries","plugins","oauth"]},contentful:{name:"contentful",apiUrl:"https://api.contentful.com",regex:"^(.*\\.)?contentful\\.com(/.*)?$",icon:"contentful",docsUrl:"https://www.contentful.com/developers/docs/references/content-management-api",preferredAuthType:"api_key",keywords:["spaces","environments","content types","entries","assets","locales","tags","webhooks","roles","api keys","content model","publishing","preview","api key"]},creatio:{name:"creatio",apiUrl:"https://<<instance>>.creatio.com/0/odata",regex:"^(.*\\.)?creatio\\.com(/.*)?$",icon:"/logos/creatio.ico",docsUrl:"https://academy.creatio.com/docs/developer/integrations_and_api/data_services/odata/overview",preferredAuthType:"oauth2",oauth:{authUrl:"https://<<instance>>.creatio.com/0/connect/authorize",tokenUrl:"https://<<instance>>.creatio.com/0/connect/token",scopes:"offline_access",grant_type:"authorization_code"},systemSpecificInstructions:`Creatio uses OIDC-compliant OAuth endpoints. The standard /ServiceModel/AuthService.svc/Authorize and /rest/oauth/token endpoints are behind IIS session auth and will NOT work for OAuth flows \u2014 you MUST use the /0/connect/* OIDC endpoints instead.
1155
1155
 
1156
1156
  To discover the correct endpoints for any Creatio instance, fetch: https://<instance>.creatio.com/0/.well-known/openid-configuration
1157
1157
 
@@ -1330,7 +1330,7 @@ SETUP: User needs a Google Ads Manager account, a Google Cloud project with OAut
1330
1330
  QUERYING (GAQL): Use Google Ads Query Language via:
1331
1331
  - POST /v23/customers/{customerId}/googleAds:searchStream (streaming, recommended)
1332
1332
  - POST /v23/customers/{customerId}/googleAds:search (paginated)
1333
- Example: SELECT campaign.name, metrics.impressions FROM campaign WHERE segments.date DURING LAST_30_DAYS`,keywords:["campaigns","ad_groups","ads","keywords","GAQL","budgets","bidding","conversions","audiences","extensions","reports","accounts","billing","targeting","search_terms","metrics","segments","oauth"]},google:{name:"google",apiUrl:"https://googleapis.com",regex:"^(?!.*(?:merchantapi\\.googleapis\\.com|content\\.googleapis\\.com/content|(?:gmail|sheets|docs|slides|forms|people|tasks)\\.googleapis\\.com)).*(googleapis\\.com(?!/(?:gmail|drive|calendar|sheets|googleads))|developers\\.google\\.com(?!/(?:gmail|drive|calendar|sheets|google-ads))).*$",icon:"google",docsUrl:"https://developers.google.com/apis-explorer",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile openid"},keywords:["apis","services","resources","GAQL","methods","scopes","projects","quotas","usage","oauth"]},posthog:{name:"posthog",apiUrl:"https://us.posthog.com/api",regex:"^.*posthog.*$",icon:"posthog",docsUrl:"https://posthog.com/docs/api",openApiUrl:"https://app.posthog.com/api/schema/",preferredAuthType:"api_key",keywords:["events","users","products","dashboard","properties","cohorts","funnels","retention","insights","engage","import","export","jql","query","segmentation","track","api key"]},circlebackApi:{name:"circlebackApi",label:"Circleback API",apiUrl:"https://circleback.ai/api",regex:"^https://circleback\\.ai/api/?(?:\\?.*)?$",icon:"/logos/circleback.png",docsUrl:"https://circleback.ai/docs/api",openApiUrl:"https://circleback.ai/docs/api/openapi.json",preferredAuthType:"api_key",systemSpecificInstructions:`Circleback's REST API provides deterministic access to meetings, notes, transcripts, action items, calendar events, people, companies, and tags. Load the meetings skill for meeting-context work. Create a personal API key in Circleback under Settings \u2192 API keys; it is shown once. Store it as api_key and send the current System's api_key credential placeholder as an Authorization Bearer token. Start with GET /search or GET /meetings, then use GET /meeting/{meetingId} and GET /meeting/{meetingId}/transcript only when needed. List endpoints paginate through the RFC 8288 Link response header with rel="next". The API also exposes meeting, action-item, and tag mutations; keep brain context use read-only and require explicit user direction before any mutation. Prefer the Circleback MCP template for context-source onboarding and OAuth-based contextual retrieval. Do not change an MCP System's endpoint to this REST base URL.`,keywords:["meetings","transcripts","notes","action items","calendar events","attendees","recordings","people","companies","tags","api key","rest"]},circleback:{name:"circleback",label:"Circleback",apiUrl:"https://circleback.ai/api/mcp",regex:"^https://(?:app\\.)?circleback\\.ai/api/mcp/?(?:\\?.*)?$",icon:"/logos/circleback.png",docsUrl:"https://support.circleback.ai/en/articles/13249081-circleback-mcp",preferredAuthType:"oauth2",oauth:{authUrl:"https://circleback.ai/api/oauth/authorize",tokenUrl:"https://circleback.ai/api/oauth/access-token",registrationUrl:"https://circleback.ai/api/oauth/register",scopes:"user",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Circleback is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Search narrowly and retrieve transcript content only when relevant. Prefer this MCP System for context-source onboarding and OAuth-based contextual retrieval. Use the separate Circleback API template only when deterministic REST access is required. Never join, record, or mutate meetings through this integration.",keywords:["meetings","transcripts","notes","action_items","calendar_events","attendees","summaries","people","companies","emails"]},fireflies:{name:"fireflies",label:"Fireflies",apiUrl:"https://api.fireflies.ai/mcp",regex:"^https://api\\.fireflies\\.ai/mcp/?(?:\\?.*)?$",icon:"/logos/fireflies.svg",docsUrl:"https://docs.fireflies.ai/getting-started/mcp-configuration",preferredAuthType:"oauth2",oauth:{authUrl:"https://api.fireflies.ai/authorize",tokenUrl:"https://api.fireflies.ai/token",registrationUrl:"https://api.fireflies.ai/register",scopes:"email profile",resource:"https://api.fireflies.ai/mcp",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Fireflies is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Use read-only transcript, summary, and search tools. Never share meetings, revoke access, rename or move meetings, create soundbites, or perform another provider mutation.",keywords:["meetings","transcripts","summaries","action_items","speakers","attendees","analytics","soundbites"]},fellowMcp:{name:"fellowMcp",label:"Fellow",apiUrl:"https://fellow.app/mcp",regex:"^https://fellow\\.app/mcp/?(?:\\?.*)?$",icon:"/logos/fellow.png",docsUrl:"https://developers.fellow.ai/reference/mcp-server",preferredAuthType:"oauth2",oauth:{authUrl:"https://fellow.app/mcp/authorize",tokenUrl:"https://fellow.app/mcp/token",registrationUrl:"https://fellow.app/mcp/register",scopes:"read_calendar read_meeting_content read_action_items read_channels",resource:"https://fellow.app/mcp",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Fellow is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. A Fellow workspace admin must enable Allow users to create MCP connections under Workspace Settings \u2192 Security. Request read-only scopes only; never request write_meeting_agenda. Discover the current tools before use and never edit agendas or meeting data through this integration.",keywords:["meetings","notes","transcripts","summaries","action_items","participants","calendar","channels"]},firecrawl:{name:"firecrawl",apiUrl:"https://api.firecrawl.dev/v1",regex:"^.*firecrawl.*$",icon:"/logos/firecrawl.png",docsUrl:"https://docs.firecrawl.dev/api-reference/introduction",preferredAuthType:"api_key",keywords:["crawl","scrape","extract","search","pdf","web","html","markdown","api key"]},crawlbase:{name:"crawlbase",apiUrl:"https://api.crawlbase.com",regex:"^.*crawlbase.*$",icon:"/logos/crawlbase.png",docsUrl:"https://crawlbase.com/docs/crawling-api/",preferredAuthType:"api_key",keywords:["crawl","scrape","extract","search","pdf","web","html","markdown","api key"]},procore:{name:"procore",apiUrl:"https://api.procore.com/rest/",regex:"^.*procore.*$",icon:"procore",docsUrl:"https://developers.procore.com/reference/rest/docs/rest-api-overview",openApiUrl:"https://raw.githubusercontent.com/procore/open-api-spec/refs/heads/master/pub-api.swagger.json",preferredAuthType:"oauth2",oauth:{authUrl:"https://login.procore.com/oauth/authorize",tokenUrl:"https://login.procore.com/oauth/token",scopes:""},systemSpecificInstructions:`IMPORTANT: Sandbox and production use completely separate credentials and base URLs \u2014 never mix them.
1333
+ Example: SELECT campaign.name, metrics.impressions FROM campaign WHERE segments.date DURING LAST_30_DAYS`,keywords:["campaigns","ad_groups","ads","keywords","GAQL","budgets","bidding","conversions","audiences","extensions","reports","accounts","billing","targeting","search_terms","metrics","segments","oauth"]},google:{name:"google",apiUrl:"https://googleapis.com",regex:"^(?!.*(?:merchantapi\\.googleapis\\.com|content\\.googleapis\\.com/content|(?:gmail|sheets|docs|slides|forms|people|tasks)\\.googleapis\\.com)).*(googleapis\\.com(?!/(?:gmail|drive|calendar|sheets|googleads))|developers\\.google\\.com(?!/(?:gmail|drive|calendar|sheets|google-ads))).*$",icon:"google",docsUrl:"https://developers.google.com/apis-explorer",preferredAuthType:"oauth2",oauth:{authUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",scopes:"https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile openid"},keywords:["apis","services","resources","GAQL","methods","scopes","projects","quotas","usage","oauth"]},posthog:{name:"posthog",apiUrl:"https://us.posthog.com/api",regex:"^.*posthog.*$",icon:"posthog",docsUrl:"https://posthog.com/docs/api",openApiUrl:"https://app.posthog.com/api/schema/",preferredAuthType:"api_key",keywords:["events","users","products","dashboard","properties","cohorts","funnels","retention","insights","engage","import","export","jql","query","segmentation","track","api key"]},circlebackApi:{name:"circlebackApi",label:"Circleback API",apiUrl:"https://circleback.ai/api",regex:"^https://circleback\\.ai/api/?(?:\\?.*)?$",icon:"/logos/circleback.png",docsUrl:"https://circleback.ai/docs/api",openApiUrl:"https://circleback.ai/docs/api/openapi.json",preferredAuthType:"api_key",systemSpecificInstructions:`Circleback's REST API provides deterministic access to meetings, notes, transcripts, action items, calendar events, people, companies, and tags. Load the meetings skill for meeting-context work. Create a personal API key in Circleback under Settings \u2192 API keys; it is shown once. Store it as api_key and send the current System's api_key secret placeholder as an Authorization Bearer token. Start with GET /search or GET /meetings, then use GET /meeting/{meetingId} and GET /meeting/{meetingId}/transcript only when needed. List endpoints paginate through the RFC 8288 Link response header with rel="next". The API also exposes meeting, action-item, and tag mutations; keep brain context use read-only and require explicit user direction before any mutation. Prefer the Circleback MCP template for context-source onboarding and OAuth-based contextual retrieval. Do not change an MCP System's endpoint to this REST base URL.`,keywords:["meetings","transcripts","notes","action items","calendar events","attendees","recordings","people","companies","tags","api key","rest"]},circleback:{name:"circleback",mcp:!0,label:"Circleback",apiUrl:"https://circleback.ai/api/mcp",regex:"^https://(?:app\\.)?circleback\\.ai/api/mcp/?(?:\\?.*)?$",icon:"/logos/circleback.png",docsUrl:"https://support.circleback.ai/en/articles/13249081-circleback-mcp",preferredAuthType:"oauth2",oauth:{authUrl:"https://circleback.ai/api/oauth/authorize",tokenUrl:"https://circleback.ai/api/oauth/access-token",registrationUrl:"https://circleback.ai/api/oauth/register",scopes:"user",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Circleback is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Search narrowly and retrieve transcript content only when relevant. Prefer this MCP System for context-source onboarding and OAuth-based contextual retrieval. Use the separate Circleback API template only when deterministic REST access is required. Never join, record, or mutate meetings through this integration.",keywords:["meetings","transcripts","notes","action_items","calendar_events","attendees","summaries","people","companies","emails"]},fireflies:{name:"fireflies",mcp:!0,label:"Fireflies",apiUrl:"https://api.fireflies.ai/mcp",regex:"^https://api\\.fireflies\\.ai/mcp/?(?:\\?.*)?$",icon:"/logos/fireflies.svg",docsUrl:"https://docs.fireflies.ai/getting-started/mcp-configuration",preferredAuthType:"oauth2",oauth:{authUrl:"https://api.fireflies.ai/authorize",tokenUrl:"https://api.fireflies.ai/token",registrationUrl:"https://api.fireflies.ai/register",scopes:"email profile",resource:"https://api.fireflies.ai/mcp",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Fireflies is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. Use read-only transcript, summary, and search tools. Never share meetings, revoke access, rename or move meetings, create soundbites, or perform another provider mutation.",keywords:["meetings","transcripts","summaries","action_items","speakers","attendees","analytics","soundbites"]},fellowMcp:{name:"fellowMcp",mcp:!0,label:"Fellow",apiUrl:"https://fellow.app/mcp",regex:"^https://fellow\\.app/mcp/?(?:\\?.*)?$",icon:"/logos/fellow.png",docsUrl:"https://developers.fellow.ai/reference/mcp-server",preferredAuthType:"oauth2",oauth:{authUrl:"https://fellow.app/mcp/authorize",tokenUrl:"https://fellow.app/mcp/token",registrationUrl:"https://fellow.app/mcp/register",scopes:"read_calendar read_meeting_content read_action_items read_channels",resource:"https://fellow.app/mcp",tokenAuthMethod:"body",usePKCE:!0},systemSpecificInstructions:"Fellow is a brain context source (meetings) backed by remote MCP. Load the meetings skill before using it. Keep the MCP endpoint unchanged. Authentication uses OAuth dynamic client registration with PKCE. Store the registered client configuration on the shared System and tokens in the current user's credential. A Fellow workspace admin must enable Allow users to create MCP connections under Workspace Settings \u2192 Security. Request read-only scopes only; never request write_meeting_agenda. Discover the current tools before use and never edit agendas or meeting data through this integration.",keywords:["meetings","notes","transcripts","summaries","action_items","participants","calendar","channels"]},firecrawl:{name:"firecrawl",apiUrl:"https://api.firecrawl.dev/v1",regex:"^.*firecrawl.*$",icon:"/logos/firecrawl.png",docsUrl:"https://docs.firecrawl.dev/api-reference/introduction",preferredAuthType:"api_key",keywords:["crawl","scrape","extract","search","pdf","web","html","markdown","api key"]},crawlbase:{name:"crawlbase",apiUrl:"https://api.crawlbase.com",regex:"^.*crawlbase.*$",icon:"/logos/crawlbase.png",docsUrl:"https://crawlbase.com/docs/crawling-api/",preferredAuthType:"api_key",keywords:["crawl","scrape","extract","search","pdf","web","html","markdown","api key"]},procore:{name:"procore",apiUrl:"https://api.procore.com/rest/",regex:"^.*procore.*$",icon:"procore",docsUrl:"https://developers.procore.com/reference/rest/docs/rest-api-overview",openApiUrl:"https://raw.githubusercontent.com/procore/open-api-spec/refs/heads/master/pub-api.swagger.json",preferredAuthType:"oauth2",oauth:{authUrl:"https://login.procore.com/oauth/authorize",tokenUrl:"https://login.procore.com/oauth/token",scopes:""},systemSpecificInstructions:`IMPORTANT: Sandbox and production use completely separate credentials and base URLs \u2014 never mix them.
1334
1334
  Setup:
1335
1335
  1) Create app at developers.procore.com \u2192 My Apps \u2192 Create New App.
1336
1336
  2) Add a "Data Connector Component" with User-level Authentication, then create a version.
@@ -2173,9 +2173,9 @@ ${e.format(r)}`.trim())}};dH.exports=gv});var yv=m((YFe,hH)=>{"use strict";var{I
2173
2173
  ${s}`;return}if(cE(e,i,KOe)){XOe(e,o)&&(r.retry=e.toString("utf8",o));return}if(cE(e,i,ZOe)){eUe(e,o)&&(r.id=e.toString("utf8",o));return}if(cE(e,i,WOe)){let s=e.toString("utf8",o);s.length>0&&(r.event=s)}}processEvent(e){e.retry&&qOe(e.retry)&&(this.state.reconnectionTime=parseInt(e.retry,10)),e.id!==void 0&&GOe(e.id)&&(this.state.lastEventId=e.id),e.data!==void 0&&this.push({type:e.event||"message",options:{data:e.data,lastEventId:this.state.lastEventId,origin:this.state.origin}})}clearEvent(){this.event.data=void 0,this.event.event=void 0,this.event.id=void 0,this.event.retry=void 0}hasPendingEvent(){return this.event.data!==void 0||this.event.event!==void 0||this.event.id!==void 0||this.event.retry!==void 0}hasCurrentByte(){return this.chunkIndex<this.chunks.length&&this.pos<this.chunks[this.chunkIndex].length}currentByte(){return this.chunks[this.chunkIndex][this.pos]}consumeCurrentByte(){this.advanceCursor(),this.syncLineStartToCursor()}advanceCursor(){for(this.pos++;this.chunkIndex<this.chunks.length&&this.pos>=this.chunks[this.chunkIndex].length;)this.chunkIndex++,this.pos=0}syncLineStartToCursor(){this.lineChunkIndex=this.chunkIndex,this.linePos=this.pos,this.dropConsumedChunks()}dropConsumedChunks(){for(;this.lineChunkIndex>0;)this.chunks.shift(),this.lineChunkIndex--,this.chunkIndex--;this.chunkIndex===this.chunks.length&&(this.chunks.length=0,this.chunkIndex=0,this.pos=0,this.lineChunkIndex=0,this.linePos=0)}readLine(){if(this.lineChunkIndex===this.chunkIndex)return this.chunks[this.chunkIndex].subarray(this.linePos,this.pos);let e=[],r=0;for(let n=this.lineChunkIndex;n<=this.chunkIndex;n++){let i=this.chunks[n],o=n===this.lineChunkIndex?this.linePos:0,s=n===this.chunkIndex?this.pos:i.length,a=i.subarray(o,s);r+=a.length,e.push(a)}return Buffer.concat(e,r)}peekBufferedByte(e){let r=this.lineChunkIndex,n=this.linePos;for(;r<this.chunks.length;){let i=this.chunks[r],o=i.length-n;if(e<o)return i[n+e];e-=o,r++,n=0}}discardLeadingBytes(e){for(;e>0&&this.lineChunkIndex<this.chunks.length;){let n=this.chunks[this.lineChunkIndex].length-this.linePos;e<n?(this.linePos+=e,e=0):(e-=n,this.lineChunkIndex++,this.linePos=0)}this.chunkIndex=this.lineChunkIndex,this.pos=this.linePos,this.dropConsumedChunks()}handleBOM(){let e=this.peekBufferedByte(0),r=this.peekBufferedByte(1),n=this.peekBufferedByte(2);return r===void 0?(e===gl[0]||(this.checkBOM=!1),!0):n===void 0?e===gl[0]&&r===gl[1]?!0:(this.checkBOM=!1,!1):(e===gl[0]&&r===gl[1]&&n===gl[2]&&this.discardLeadingBytes(3),this.checkBOM=!1,!this.hasCurrentByte())}};XY.exports={EventSourceStream:PQ}});var cV=m((F1e,aV)=>{"use strict";var{pipeline:tUe}=require("stream"),{fetching:rUe}=cp(),{makeRequest:nUe}=sl(),{webidl:Er}=Zt(),{EventSourceStream:iUe}=eV(),{parseMIMEType:oUe}=xn(),{createFastMessageEvent:sUe}=Wy(),{isNetworkError:tV}=op(),{kEnumerableProperty:Nc}=Se(),{environmentSettingsObject:rV}=tn(),nV=!1,iV=3e3,hp=0,oV=1,gp=2,aUe="anonymous",cUe="use-credentials",ml=class t extends EventTarget{#e={open:null,error:null,message:null};#t;#n=!1;#i=hp;#o=null;#r=null;#c;#s;constructor(e,r={}){super(),Er.util.markAsUncloneable(this);let n="EventSource constructor";Er.argumentLengthCheck(arguments,1,n),nV||(nV=!0,process.emitWarning("EventSource is experimental, expect them to change at any time.",{code:"UNDICI-ES"})),e=Er.converters.USVString(e),r=Er.converters.EventSourceInitDict(r,n,"eventSourceInitDict"),this.#c=r.node.dispatcher||r.dispatcher,this.#s={lastEventId:"",reconnectionTime:r.node.reconnectionTime};let i=rV,o;try{o=new URL(e,i.settingsObject.baseUrl),this.#s.origin=o.origin}catch(c){throw new DOMException(c,"SyntaxError")}this.#t=o.href;let s=aUe;r.withCredentials===!0&&(s=cUe,this.#n=!0);let a={redirect:"follow",keepalive:!0,mode:"cors",credentials:s==="anonymous"?"same-origin":"omit",referrer:"no-referrer"};a.client=rV.settingsObject,a.headersList=[["accept",{name:"accept",value:"text/event-stream"}]],a.cache="no-store",a.initiator="other",a.urlList=[new URL(this.#t)],this.#o=nUe(a),this.#a()}get readyState(){return this.#i}get url(){return this.#t}get withCredentials(){return this.#n}#a(){if(this.#i===gp)return;this.#i=hp;let e={request:this.#o,dispatcher:this.#c},r=n=>{if(!tV(n))return this.#u()};e.processResponseEndOfBody=r,e.processResponse=n=>{if(tV(n))if(n.aborted){this.close(),this.dispatchEvent(new Event("error"));return}else{this.#u();return}let i=n.headersList.get("content-type",!0),o=i!==null?oUe(i):"failure",s=o!=="failure"&&o.essence==="text/event-stream";if(n.status!==200||s===!1){this.close(),this.dispatchEvent(new Event("error"));return}this.#i=oV,this.dispatchEvent(new Event("open")),this.#s.origin=n.urlList[n.urlList.length-1].origin;let a=new iUe({eventSourceSettings:this.#s,push:c=>{this.dispatchEvent(sUe(c.type,c.options))}});tUe(n.body.stream,a,c=>{c?.aborted===!1&&(this.close(),this.dispatchEvent(new Event("error")))})},this.#r=rUe(e)}#u(){this.#i!==gp&&(this.#i=hp,this.dispatchEvent(new Event("error")),setTimeout(()=>{this.#i===hp&&(this.#s.lastEventId.length&&this.#o.headersList.set("last-event-id",this.#s.lastEventId,!0),this.#a())},this.#s.reconnectionTime)?.unref())}close(){Er.brandCheck(this,t),this.#i!==gp&&(this.#i=gp,this.#r.abort(),this.#o=null)}get onopen(){return this.#e.open}set onopen(e){this.#e.open&&this.removeEventListener("open",this.#e.open);let r=Er.converters.EventHandlerNonNull(e);r!==null?(this.addEventListener("open",r),this.#e.open=e):this.#e.open=null}get onmessage(){return this.#e.message}set onmessage(e){this.#e.message&&this.removeEventListener("message",this.#e.message);let r=Er.converters.EventHandlerNonNull(e);r!==null?(this.addEventListener("message",r),this.#e.message=e):this.#e.message=null}get onerror(){return this.#e.error}set onerror(e){this.#e.error&&this.removeEventListener("error",this.#e.error);let r=Er.converters.EventHandlerNonNull(e);r!==null?(this.addEventListener("error",r),this.#e.error=e):this.#e.error=null}},sV={CONNECTING:{__proto__:null,configurable:!1,enumerable:!0,value:hp,writable:!1},OPEN:{__proto__:null,configurable:!1,enumerable:!0,value:oV,writable:!1},CLOSED:{__proto__:null,configurable:!1,enumerable:!0,value:gp,writable:!1}};Object.defineProperties(ml,sV);Object.defineProperties(ml.prototype,sV);Object.defineProperties(ml.prototype,{close:Nc,onerror:Nc,onmessage:Nc,onopen:Nc,readyState:Nc,url:Nc,withCredentials:Nc});Er.converters.EventSourceInitDict=Er.dictionaryConverter([{key:"withCredentials",converter:Er.converters.boolean,defaultValue:()=>!1},{key:"dispatcher",converter:Er.converters.any},{key:"node",converter:Er.dictionaryConverter([{key:"reconnectionTime",converter:Er.converters["unsigned long"],defaultValue:()=>iV},{key:"dispatcher",converter:Er.converters.any}]),defaultValue:()=>({})}]);aV.exports={EventSource:ml,defaultReconnectionTime:iV}});var fV=m((j1e,K)=>{"use strict";var uUe=Js(),lV=pA(),lUe=oc(),dUe=Vj(),AUe=Kj(),pUe=cc(),fUe=E_(),hUe=h_(),gUe=M2(),mUe=H2(),yUe=Y2(),dV=ye(),lE=Se(),{InvalidArgumentError:uE}=dV,yl=Qz(),EUe=Va(),IUe=ov(),{MockCallHistory:CUe,MockCallHistoryLog:bUe}=cv(),SUe=mv(),wUe=Av(),BUe=vH(),_Ue=j_(),vUe=ny(),{getGlobalDispatcher:AV,setGlobalDispatcher:QUe}=yy(),TUe=el(),DUe=Bv();Object.assign(lV.prototype,yl);K.exports.Dispatcher=lV;K.exports.Client=uUe;K.exports.Pool=lUe;K.exports.BalancedPool=dUe;K.exports.RoundRobinPool=AUe;K.exports.Agent=pUe;K.exports.ProxyAgent=fUe;K.exports.Socks5ProxyAgent=hUe;K.exports.EnvHttpProxyAgent=gUe;K.exports.RetryAgent=mUe;K.exports.H2CClient=yUe;K.exports.RetryHandler=vUe;K.exports.DecoratorHandler=TUe;K.exports.RedirectHandler=DUe;K.exports.interceptors={redirect:LH(),responseError:$H(),retry:jH(),dump:qH(),dns:JH(),cache:vq(),decompress:kq(),deduplicate:Lq()};K.exports.cacheStores={MemoryCacheStore:Pv()};var RUe=Fq();K.exports.cacheStores.SqliteCacheStore=RUe;K.exports.buildConnector=EUe;K.exports.errors=dV;K.exports.util={parseHeaders:lE.parseHeaders,headerNameToString:lE.headerNameToString};function mp(t){return(e,r,n)=>{if(typeof r=="function"&&(n=r,r=null),!e||typeof e!="string"&&typeof e!="object"&&!(e instanceof URL))throw new uE("invalid url");if(r!=null&&typeof r!="object")throw new uE("invalid opts");if(r&&r.path!=null){if(typeof r.path!="string")throw new uE("invalid opts.path");let s=r.path;r.path.startsWith("/")||(s=`/${s}`),e=new URL(lE.parseOrigin(e).origin+s)}else r||(r=typeof e=="object"?e:{}),e=lE.parseURL(e);let{agent:i,dispatcher:o=AV()}=r;if(i)throw new uE("unsupported opts.agent. Did you mean opts.client?");return t.call(o,{...r,origin:e.origin,path:e.search?`${e.pathname}${e.search}`:e.pathname,method:r.method||(r.body?"PUT":"GET")},n)}}K.exports.setGlobalDispatcher=QUe;K.exports.getGlobalDispatcher=AV;var NUe=cp().fetch,uV=typeof __filename<"u"?__filename:void 0;function pV(t,e){if(!t||typeof t!="object")return;let r=typeof t.stack=="string"?t.stack:"",n=e.replace(/\\/g,"/");if(r&&(r.includes(e)||r.includes(n)))return;let i={};if(Error.captureStackTrace(i,pV),!i.stack)return;let o=i.stack.split(`
2174
2174
  `).slice(1).join(`
2175
2175
  `);t.stack=r?`${r}
2176
- ${o}`:i.stack}K.exports.fetch=function(e,r=void 0){return NUe(e,r).catch(n=>{throw uV?pV(n,uV):n&&typeof n=="object"&&Error.captureStackTrace(n,K.exports.fetch),n})};K.exports.Headers=wc().Headers;K.exports.Response=op().Response;K.exports.Request=sl().Request;K.exports.FormData=Rm().FormData;var{setGlobalOrigin:kUe,getGlobalOrigin:OUe}=eB();K.exports.setGlobalOrigin=kUe;K.exports.getGlobalOrigin=OUe;var{CacheStorage:UUe}=ZG(),{kConstruct:xUe}=We();K.exports.caches=new UUe(xUe);var{deleteCookie:MUe,getCookies:LUe,getSetCookies:PUe,setCookie:$Ue,parseCookie:FUe}=uY();K.exports.deleteCookie=MUe;K.exports.getCookies=LUe;K.exports.getSetCookies=PUe;K.exports.setCookie=$Ue;K.exports.parseCookie=FUe;var{parseMIMEType:jUe,serializeAMimeType:zUe}=xn();K.exports.parseMIMEType=jUe;K.exports.serializeAMimeType=zUe;var{CloseEvent:HUe,ErrorEvent:qUe,MessageEvent:GUe}=Wy(),{WebSocket:YUe,ping:VUe}=jY();K.exports.WebSocket=YUe;K.exports.CloseEvent=HUe;K.exports.ErrorEvent=qUe;K.exports.MessageEvent=GUe;K.exports.ping=VUe;K.exports.WebSocketStream=WY().WebSocketStream;K.exports.WebSocketError=OQ().WebSocketError;K.exports.request=mp(yl.request);K.exports.stream=mp(yl.stream);K.exports.pipeline=mp(yl.pipeline);K.exports.connect=mp(yl.connect);K.exports.upgrade=mp(yl.upgrade);K.exports.MockClient=IUe;K.exports.MockCallHistory=CUe;K.exports.MockCallHistoryLog=bUe;K.exports.MockPool=wUe;K.exports.MockAgent=SUe;K.exports.SnapshotAgent=BUe;K.exports.mockErrors=_Ue;var{EventSource:JUe}=cV();K.exports.EventSource=JUe;function WUe(){globalThis.fetch=K.exports.fetch,globalThis.Headers=K.exports.Headers,globalThis.Response=K.exports.Response,globalThis.Request=K.exports.Request,globalThis.FormData=K.exports.FormData,globalThis.WebSocket=K.exports.WebSocket,globalThis.CloseEvent=K.exports.CloseEvent,globalThis.ErrorEvent=K.exports.ErrorEvent,globalThis.MessageEvent=K.exports.MessageEvent,globalThis.EventSource=K.exports.EventSource}K.exports.install=WUe});var gV=m(Il=>{"use strict";Object.defineProperty(Il,"__esModule",{value:!0});Il.SuperglueClient=Il.SuperglueHttpError=void 0;var El=Lr(),Ur=aS(),ZUe=WS(),KUe=v$(),XUe=Rn(),As=fu(),exe=$d(),Ep=14400*1e3,yp;if(typeof globalThis.process<"u"&&globalThis.process.versions?.node)try{let{Agent:t}=fV();yp=new t({headersTimeout:Ep,bodyTimeout:Ep})}catch{}function hV(t){if(t?.aborted)throw t.reason??new DOMException("Aborted","AbortError")}var dE=class extends Error{constructor(e,r,n,i){super(e),this.status=r,this.code=n,this.details=i,this.name="SuperglueHttpError"}};Il.SuperglueHttpError=dE;var $Q=class{constructor({apiKey:e,apiEndpoint:r,onInfrastructureError:n,refreshToken:i,sseTokenProvider:o,tokenProvider:s}){if(!e&&!s)throw new Error("SuperglueClient requires either apiKey or tokenProvider");this.tokenProvider=s??(async()=>e),this.apiEndpoint=r??"https://api.superglue.cloud",this.sseManager=new ZUe.SSELogSubscriptionManager(this.apiEndpoint,o??this.tokenProvider,i),this.onInfrastructureError=n,this.refreshToken=i}async getApiKey(){return this.tokenProvider()}async fetchWithAuthRetry(e,r){let n=await this.getApiKey(),i=await e(n);if(i.status!==401||!this.refreshToken)return i;hV(r);let o=await this.refreshToken();return hV(r),!o||o===n?i:(i.body?.cancel(),e(o))}isInfrastructureError(e){return(0,XUe.isAbortError)(e)?!1:!!(e instanceof TypeError&&e.message.toLowerCase().includes("fetch")||e instanceof Error&&e.name==="TimeoutError")}async restRequest(e,r,n,i,o){let a=await(await this.restResponse({method:e,path:r,body:n,extraHeaders:i,requestInit:o})).text();if(a)return JSON.parse(a)}async restData(...e){return(await this.restRequest(...e)).data}async restResponse({method:e,path:r,body:n,extraHeaders:i,requestInit:o}){let s=`${this.apiEndpoint.replace(/\/$/,"")}${r}`,a=n!=null,c=typeof FormData<"u"&&n instanceof FormData,u=l=>{let d={Authorization:`Bearer ${l}`,...i};return a&&!c&&e!=="GET"&&(d["Content-Type"]="application/json"),fetch(s,{...o,method:e,headers:d,body:a?c?n:JSON.stringify(n):void 0,signal:o?.signal??AbortSignal.timeout(Ep),...yp?{dispatcher:yp}:{}})};return this.sendAuthorized(u,o?.signal)}async sendAuthorized(e,r){let n;try{n=await this.fetchWithAuthRetry(e,r)}catch(i){throw this.isInfrastructureError(i)&&this.onInfrastructureError?.(),i}if(!n.ok)throw await this.buildHttpError(n);return n}async uploadFiles(e,r){if(typeof r?.process!="boolean")throw new Error("process must be a boolean");if(e.length===0)return[];let n=e.map(l=>({...l,contentLength:l.contentLength??this.getUploadContentLength(l.content)})),o=(await this.restRequest("POST","/v1/files/uploads",{process:r.process,...r.allowUnprocessed?{allowUnprocessed:!0}:{},files:n.map(({fileName:l,contentType:d,contentLength:A})=>({fileName:l,contentLength:A,...d?{contentType:d}:{}}))})).data.files;if(o.length!==n.length)throw await Promise.all(o.map(l=>this.deleteFileUpload(l.id).catch(()=>{}))),new Error("Upload response did not match the selected files");let s=await Promise.allSettled(o.map(async(l,d)=>{let A=n[d],p=await fetch(l.uploadUrl,{method:"PUT",body:A.content,headers:{...l.uploadHeaders,...A.contentType?{"Content-Type":A.contentType}:{}},signal:AbortSignal.timeout(Math.min(Ep,l.expiresIn*1e3))});if(!p.ok)throw new Error(`Upload failed for ${A.fileName}: ${p.status} ${p.statusText}`);return l.id})),a=s.flatMap(l=>l.status==="fulfilled"?[l.value]:[]),c=new Map;if(a.length>0)try{let l=await this.restRequest("POST","/v1/files/uploads/complete",{fileIds:a});c=new Map(l.data.files.map(d=>[d.id,d]))}catch(l){c=new Map(a.map(d=>[d,{id:d,fileName:n[o.findIndex(A=>A.id===d)]?.fileName||d,contentLength:n[o.findIndex(A=>A.id===d)]?.contentLength||0,status:"failed",error:l instanceof Error?l.message:String(l)}]))}let u=o.map((l,d)=>{let A=s[d],p=n[d];return A.status==="rejected"?{id:l.id,fileName:p.fileName,contentLength:p.contentLength,status:"failed",error:A.reason instanceof Error?A.reason.message:String(A.reason)}:c.get(l.id)||{id:l.id,fileName:p.fileName,contentLength:p.contentLength,status:"failed",error:"Upload completion returned no result"}});return await Promise.all(u.filter(l=>l.status==="failed").map(l=>this.deleteFileUpload(l.id).catch(()=>{}))),u}async deleteFileUpload(e){await this.restRequest("DELETE",`/v1/files/uploads/${encodeURIComponent(e)}`)}getUploadContentLength(e){return typeof e=="string"?new TextEncoder().encode(e).byteLength:e instanceof Uint8Array?e.byteLength:e.size}async buildHttpError(e){e.status>=500&&this.onInfrastructureError?.();let r=await e.text(),n=`HTTP ${e.status}: ${r}`,i,o;try{let s=JSON.parse(r);s&&typeof s=="object"&&!Array.isArray(s)&&(o=s),typeof s?.code=="string"&&(i=s.code);let a=s.error;typeof a=="string"?n=a:a&&typeof a=="object"&&(n=a.message||JSON.stringify(a))}catch{}return new dE(n,e.status,i,o)}async streamRequest(e,r,n){let i=e.includes("?")?"&":"?",o=`${this.apiEndpoint.replace(/\/$/,"")}${e}${i}stream=true`,s=u=>fetch(o,{method:"POST",headers:{Authorization:`Bearer ${u}`,Accept:"text/event-stream","Content-Type":"application/json"},body:JSON.stringify(r),signal:n??AbortSignal.timeout(Ep),...yp?{dispatcher:yp}:{}}),a;try{a=await this.fetchWithAuthRetry(s,n)}catch(u){throw this.isInfrastructureError(u)&&this.onInfrastructureError?.(),u}if(!a.ok)throw await this.buildHttpError(a);if(!(a.headers.get("content-type")||"").includes("text/event-stream")){let u=await a.text();return u?JSON.parse(u):void 0}try{return await(0,KUe.consumeEventStreamResult)(a)}catch(u){throw this.isInfrastructureError(u)&&this.onInfrastructureError?.(),u}}async subscribeToLogsSSE(e={}){return this.sseManager.subscribeToLogs(e)}async disconnect(){await this.sseManager.disconnect()}async listMemoryNotes(e={}){let r=new URLSearchParams;e.scope&&r.set("scope",e.scope),e.query&&r.set("query",e.query);let n=r.toString();return this.restData("GET",`/v1/memory-notes${n?`?${n}`:""}`)}async createMemoryNote(e){return this.restData("POST","/v1/memory-notes",e)}async updateMemoryNote(e,r){return this.restData("PATCH",`/v1/memory-notes/${encodeURIComponent(e)}`,r)}async deleteMemoryNote(e){await this.restRequest("DELETE",`/v1/memory-notes/${encodeURIComponent(e)}`)}async clearMemoryNotes(e){return(await this.restRequest("DELETE",`/v1/memory-notes?scope=${e}`)).data.deleted}async getMe(){return this.restRequest("GET","/v1/me")}async completeOnboarding(){return this.restRequest("POST","/v1/me/onboarding/complete")}async runTool(e){let r=await this.restRequest("POST",`/v1/tools/${encodeURIComponent(e.toolId)}/run`,{inputs:e.payload,files:e.files,credentials:e.credentials,includeStepResultData:e.includeStepResultData,options:e.options,runId:e.runId,stateFixture:e.stateFixture},void 0,e.signal?{signal:e.signal}:void 0);return{success:r.status==="success",data:r.data,error:r.error,tool:r.tool,stepResults:r.stepResults?.map(n=>({...n}))||[],...r.fileArtifacts&&r.fileArtifacts.length>0?{fileArtifacts:r.fileArtifacts}:{},...r.metadata?.warnings?.length?{warnings:r.metadata.warnings}:{}}}async runToolConfig(e){let r=e.createRun?"/v1/tools/run?createRun=true":"/v1/tools/run",n=await this.restRequest("POST",r,{tool:e.tool,payload:e.payload,files:e.files,credentials:e.credentials,includeStepResultData:e.includeStepResultData,options:e.options,runId:e.runId,stateFixture:e.stateFixture,executionKind:e.executionKind,parentToolId:e.parentToolId,draftId:e.draftId},e.traceId?{"X-Trace-Id":e.traceId}:void 0,e.signal?{signal:e.signal}:void 0);return{success:n.status?n.status==="success":n.success??!1,data:n.data,error:n.error,tool:n.tool||e.tool,stepResults:n.stepResults?.map(o=>({...o}))||[],...n.fileArtifacts&&n.fileArtifacts.length>0?{fileArtifacts:n.fileArtifacts}:{},...n.metadata?.warnings?.length?{warnings:n.metadata.warnings}:{}}}async abortToolExecution(e){return{success:!0,runId:(await this.restRequest("POST",`/v1/runs/${encodeURIComponent(e)}/cancel`)).runId}}async executeStep({step:e,payload:r,files:n,previousResults:i,credentials:o,credentialsList:s,options:a,runId:c,systemIds:u,credentialId:l,systemAuth:d,createRun:A,parentToolId:p,stepIndex:h,stepId:g,signal:S,stream:B}){let _={step:e,payload:r,files:n,previousResults:i,credentials:o,credentialsList:s,options:a,runId:c,systemIds:u,credentialId:l,systemAuth:d,createRun:A,parentToolId:p,stepIndex:h,stepId:g};return B?this.streamRequest("/v1/tools/step/run",_,S):this.restRequest("POST","/v1/tools/step/run",_,void 0,S?{signal:S}:void 0)}async abortStep(e){return this.restRequest("POST","/v1/tools/step/abort",{runId:e})}async executeTransformOnly({outputTransform:e,outputSchema:r,inputSchema:n,payload:i,files:o,stepResults:s,options:a,runId:c,createRun:u,parentToolId:l,stepId:d,signal:A,stream:p}){let h={outputTransform:e,outputSchema:r,inputSchema:n,payload:i,files:o,stepResults:s,options:a,runId:c,createRun:u,parentToolId:l,stepId:d};return p?this.streamRequest("/v1/tools/transform/run",h,A):this.restRequest("POST","/v1/tools/transform/run",h,void 0,A?{signal:A}:void 0)}async createRun({toolId:e,toolConfig:r,toolResult:n,stepResults:i,toolPayload:o,status:s,error:a,startedAt:c,completedAt:u,executionKind:l,parentToolId:d,draftId:A}){return this.restRequest("POST","/v1/runs",{toolId:e,toolConfig:r,toolResult:n,stepResults:i,toolPayload:o,status:s,error:a,startedAt:(0,As.toUTCISOString)(c,"run.startedAt"),completedAt:(0,As.toUTCISOString)(u,"run.completedAt"),executionKind:l,parentToolId:d,draftId:A})}async checkRunLimit(){return this.restData("POST","/v1/runs/check-limit")}async extract({file:e,envelope:r}){if(!e)throw new Error("File must be provided for extract.");let n=new FormData;n.append("file",e);let i=r?"/v1/extract?envelope=true":"/v1/extract";return this.restRequest("POST",i,n)}mapOpenAPIRunToRun(e){let r={running:El.RunStatus.RUNNING,success:El.RunStatus.SUCCESS,failed:El.RunStatus.FAILED,aborted:El.RunStatus.ABORTED};return{runId:e.runId??e.id,toolId:e.toolId,tool:e.tool,systemIds:e.systemIds,status:r[e.status]??El.RunStatus.FAILED,toolPayload:e.toolPayload,data:e.data,toolResult:e.data,error:e.error,stepResults:e.stepResults,options:e.options,requestSource:e.requestSource,traceId:e.traceId,resultStorageUri:e.resultStorageUri,userId:e.userId,userEmail:e.userEmail,userName:e.userName,metadata:{...e.metadata,executionKind:e.metadata?.executionKind??El.RunExecutionKind.FULL},fileArtifacts:e.fileArtifacts}}mapOpenAPIScheduleToToolSchedule(e){return{...e,lastRunAt:e.lastRunAt?(0,As.requireUTCDate)(e.lastRunAt,"schedule.lastRunAt"):void 0,nextRunAt:(0,As.requireUTCDate)(e.nextRunAt,"schedule.nextRunAt"),createdAt:(0,As.requireUTCDate)(e.createdAt,"schedule.createdAt"),updatedAt:(0,As.requireUTCDate)(e.updatedAt,"schedule.updatedAt")}}async listRuns(e={}){let r=(0,Ur.createSearchListQueryParams)(e);e.toolId!==void 0&&r.set("toolId",e.toolId),e.searchUserIds?.length&&r.set("searchUserIds",e.searchUserIds.join(",")),e.includeTotal!==void 0&&r.set("includeTotal",String(e.includeTotal)),e.startedAfter!==void 0&&r.set("startedAfter",e.startedAfter instanceof Date?(0,As.toUTCISOString)(e.startedAfter,"run.startedAfter"):e.startedAfter),e.statuses!==void 0?r.set("status",e.statuses.join(",")):e.status!==void 0&&r.set("status",e.status),e.requestSources!==void 0&&r.set("requestSources",e.requestSources.join(",")),e.executionKinds!==void 0&&r.set("executionKinds",e.executionKinds.join(",")),e.userId!==void 0&&r.set("userId",e.userId),e.systemId!==void 0&&r.set("systemId",e.systemId),e.systemIds!==void 0&&r.set("systemIds",e.systemIds.join(","));let n=r.size>0?`?${r.toString()}`:"",i=await this.restRequest("GET",`/v1/runs${n}`,void 0,void 0,{signal:e.signal});return{data:i.data.map(o=>this.mapOpenAPIRunToRun(o)),total:i.total,page:i.page,limit:i.limit,hasMore:i.hasMore}}async getActivityCounts(e){let r=new URLSearchParams;e?.from&&r.set("from",e.from instanceof Date?(0,As.toUTCISOString)(e.from,"activity.from"):e.from),e?.to&&r.set("to",e.to instanceof Date?(0,As.toUTCISOString)(e.to,"activity.to"):e.to);let n=r.toString();return(await this.restRequest("GET",`/v1/activity/counts${n?`?${n}`:""}`,void 0,void 0,{signal:e?.signal})).counts}async getRun(e){try{let r=await this.restRequest("GET",`/v1/runs/${encodeURIComponent(e)}`);return this.mapOpenAPIRunToRun(r)}catch(r){if(r.message?.includes("404")||r.message?.includes("not found"))return null;throw r}}async getTool(e){try{return await this.restRequest("GET",`/v1/tools/${encodeURIComponent(e)}`)}catch(r){if(r.message?.includes("404")||r.message?.includes("not found")||r.message?.includes("403")||r.message?.includes("not allowed"))return null;throw r}}async getToolState(e){return(await this.restRequest("GET",`/v1/tools/${encodeURIComponent(e)}/state`)).state}async setToolState(e,r){await this.restRequest("PUT",`/v1/tools/${encodeURIComponent(e)}/state`,{state:r})}async deleteToolState(e){return(await this.restRequest("DELETE",`/v1/tools/${encodeURIComponent(e)}/state`)).deletedKeys}async archiveTool(e,r=!0){return this.updateTool(e,{archived:r})}async bulkArchiveTools(e,r=!0){return this.restRequest("POST","/v1/tools/bulk/archive",{ids:e,archived:r})}async bulkDeleteTools(e){return this.restRequest("POST","/v1/tools/bulk/delete",{ids:e})}async listTools(e={}){let r=(0,Ur.createListQueryParams)(e);e.includeArchived!==void 0&&r.set("includeArchived",String(e.includeArchived));let n=r.size>0?`?${r.toString()}`:"";return this.restRequest("GET",`/v1/tools${n}`)}async listAllTools(e={}){return(0,Ur.listAllPages)((r,n)=>this.listTools({...e,page:r,limit:n}))}async createTool(e,r){return this.restRequest("POST","/v1/tools",{...r,id:e})}async updateTool(e,r){return this.restRequest("PUT",`/v1/tools/${encodeURIComponent(e)}`,r)}async deleteTool(e){try{return await this.restRequest("DELETE",`/v1/tools/${encodeURIComponent(e)}`),!0}catch(r){if(r.message?.includes("404"))return!1;throw r}}async renameTool(e,r){return this.restRequest("POST",`/v1/tools/${encodeURIComponent(e)}/rename`,{newId:r})}async getWorkflow(e){return this.getTool(e)}async archiveWorkflow(e,r=!0){return this.upsertWorkflow(e,{archived:r})}async createWorkflow(e,r){return this.createTool(e,r)}async updateWorkflow(e,r){return this.updateTool(e,r)}async upsertWorkflow(e,r){return await this.getTool(e)?this.updateTool(e,r):this.createTool(e,r)}async deleteWorkflow(e){return this.deleteTool(e)}async renameWorkflow(e,r){return this.renameTool(e,r)}async listProjectSummaries(e={}){let r=(0,Ur.createSearchListQueryParams)(e);return r.set("includeResources","false"),e.includeArchived!==void 0&&r.set("includeArchived",String(e.includeArchived)),this.restRequest("GET",`/v1/projects?${r.toString()}`)}async listAllProjectSummaries({includeArchived:e}={}){return(0,Ur.listAllPages)((r,n)=>this.listProjectSummaries({page:r,limit:n,...e!==void 0?{includeArchived:e}:{}}))}async listAllProjectTasks(e){return(0,Ur.listAllPages)((r,n)=>this.restRequest("GET",`/v1/projects/${encodeURIComponent(e)}/tasks?page=${r}&limit=${n}`))}async saveProjectTask({projectId:e,taskId:r,input:n}){let i=`/v1/projects/${encodeURIComponent(e)}/tasks${r?`/${encodeURIComponent(r)}`:""}`;return this.restData(r?"PATCH":"POST",i,n)}async listAllProjectLabels(e){return(0,Ur.listAllPages)((r,n)=>this.restRequest("GET",`/v1/projects/${encodeURIComponent(e)}/labels?page=${r}&limit=${n}`))}async saveProjectLabel({projectId:e,labelId:r,input:n}){let i=`/v1/projects/${encodeURIComponent(e)}/labels${r?`/${encodeURIComponent(r)}`:""}`;return this.restData(r?"PATCH":"POST",i,n)}async deleteProjectLabel({projectId:e,labelId:r}){await this.restRequest("DELETE",`/v1/projects/${encodeURIComponent(e)}/labels/${encodeURIComponent(r)}`)}async listSchedules(e={}){let r=(0,Ur.createListQueryParams)(e),n=r.size>0?`?${r.toString()}`:"",i=e.toolId?`/v1/tools/${encodeURIComponent(e.toolId)}/schedules${n}`:`/v1/schedules${n}`,o=await this.restRequest("GET",i);return{...o,data:o.data.map(s=>this.mapOpenAPIScheduleToToolSchedule(s))}}async listAllSchedules(e={}){return(0,Ur.listAllPages)((r,n)=>this.listSchedules({...e,page:r,limit:n}))}async getToolSchedule(e,r){try{let n=await this.restRequest("GET",`/v1/tools/${encodeURIComponent(e)}/schedules/${encodeURIComponent(r)}`);return this.mapOpenAPIScheduleToToolSchedule(n)}catch(n){if(n.message?.includes("404")||n.message?.includes("not found"))return null;throw n}}async createToolSchedule(e,r){let n=await this.restRequest("POST",`/v1/tools/${encodeURIComponent(e)}/schedules`,{...r,timezone:r.timezone||(0,exe.getRuntimeTimezone)()});return this.mapOpenAPIScheduleToToolSchedule(n)}async updateToolSchedule(e,r,n){let i=await this.restRequest("PUT",`/v1/tools/${encodeURIComponent(e)}/schedules/${encodeURIComponent(r)}`,n);return this.mapOpenAPIScheduleToToolSchedule(i)}async deleteToolSchedule(e,r){return await this.restRequest("DELETE",`/v1/tools/${encodeURIComponent(e)}/schedules/${encodeURIComponent(r)}`),!0}async bulkSetSchedulesEnabled(e,r){return this.restRequest("POST","/v1/schedules/bulk/enable",{ids:e,enabled:r})}async bulkDeleteSchedules(e){return this.restRequest("POST","/v1/schedules/bulk/delete",{ids:e})}async listConnections(e={}){let r=(0,Ur.createListQueryParams)(e);e.systemId!==void 0&&r.set("systemId",e.systemId);let n=r.size>0?`?${r.toString()}`:"";return this.restRequest("GET",`/v1/connections${n}`)}async listAllConnections(e={}){return(0,Ur.listAllPages)((r,n)=>this.listConnections({...e,page:r,limit:n}))}async createOAuthApp(e){return this.restData("POST","/v1/oauth-apps",e)}async updateOAuthApp(e,r){return this.restData("PUT",`/v1/oauth-apps/${encodeURIComponent(e)}`,r)}async deleteOAuthApp(e){await this.restRequest("DELETE",`/v1/oauth-apps/${encodeURIComponent(e)}`)}async listOAuthApps({systemId:e}={}){return(0,Ur.listAllPages)(async(r,n)=>{let i=new URLSearchParams({page:String(r),limit:String(n),...e?{systemId:e}:{}});return this.restRequest("GET",`/v1/oauth-apps?${i}`)})}async getConnectionSetup(e){return this.restData("GET",`/v1/connections/setup/${encodeURIComponent(e)}`)}async createConnection(e){return this.restData("POST","/v1/connections",e)}async replaceConnection(e,r){return this.restData("PUT",`/v1/connections/${encodeURIComponent(e)}`,{credentials:r})}async updateConnection(e,r){return this.restData("PATCH",`/v1/connections/${encodeURIComponent(e)}`,r)}async deleteConnection(e){await this.restRequest("DELETE",`/v1/connections/${encodeURIComponent(e)}`)}async setDefaultConnection(e){await this.restRequest("POST",`/v1/connections/${encodeURIComponent(e)}/default`)}async listSystems(e={}){let r=(0,Ur.createListQueryParams)(e),n=r.size>0?`?${r.toString()}`:"";return this.restRequest("GET",`/v1/systems${n}`)}async listAllSystems(e={}){return(0,Ur.listAllPages)((r,n)=>this.listSystems({...e,page:r,limit:n}))}async createOAuthExchange(e){return(await this.restRequest("POST","/v1/oauth/exchanges",e)).data}async completeOAuthExchange(e,r){return(await this.restRequest("POST",`/v1/oauth/exchanges/${encodeURIComponent(e)}/complete`,r)).data}async describeOAuthProviderPage(e){return(await this.restRequest("POST",`/v1/oauth/exchanges/${encodeURIComponent(e)}/provider-page`)).data}async generateCredentialsLink(e){try{return{success:!0,credentialsUrl:(await this.restRequest("POST","/v1/authenticate",e||{})).data.credentialsUrl}}catch(r){return{success:!1,error:r.message}}}};Il.SuperglueClient=$Q});var yV=m(ht=>{"use strict";Object.defineProperty(ht,"__esModule",{value:!0});ht.UnquotedKeyStrategy=ht.TripleQuoteStrategy=ht.TrailingCommaStrategy=ht.SingleQuoteStrategy=ht.PythonLiteralStrategy=ht.CommentStrategy=ht.ResilientJsonParser=ht.RepairStrategy=void 0;ht.parseJsonResilient=txe;ht.parseJSON=rxe;ht.isValidJson=nxe;ht.prettyPrintJson=ixe;ht.minifyJson=oxe;var ci=class{validate(e){try{return JSON.parse(e),!0}catch{return!1}}};ht.RepairStrategy=ci;var AE=class extends ci{constructor(){super(...arguments),this.name="TripleQuoteRepair",this.description="Converts triple-quoted strings to proper JSON, parsing nested JSON content"}canApply(e){return/"""/.test(e)}apply(e){return e.replace(/"""([\s\S]*?)"""/g,(r,n)=>{let i=n.trim();if(i.startsWith("{")&&i.endsWith("}")||i.startsWith("[")&&i.endsWith("]"))try{let s=JSON.parse(i);return JSON.stringify(s)}catch{return`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}"`}return`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}"`})}};ht.TripleQuoteStrategy=AE;var pE=class extends ci{constructor(){super(...arguments),this.name="PythonLiteralRepair",this.description="Converts Python literals to JavaScript equivalents"}canApply(e){return/\b(None|True|False)\b/.test(e)}apply(e){return e.replace(/\bNone\b/g,"null").replace(/\bTrue\b/g,"true").replace(/\bFalse\b/g,"false")}};ht.PythonLiteralStrategy=pE;var fE=class extends ci{constructor(){super(...arguments),this.name="TrailingCommaRepair",this.description="Removes trailing commas from objects and arrays"}canApply(e){return/,\s*[}\]]/.test(e)}apply(e){return e.replace(/,(\s*[}\]])/g,"$1")}};ht.TrailingCommaStrategy=fE;var hE=class extends ci{constructor(){super(...arguments),this.name="SingleQuoteRepair",this.description="Converts single quotes to double quotes"}canApply(e){return/[{,]\s*'[^']*'\s*:/.test(e)||/:\s*'[^']*'/.test(e)}apply(e){let r=e.replace(/([{,]\s*)'([^']+)'(\s*:)/g,'$1"$2"$3');return r=r.replace(/(:\s*)'([^']+)'(\s*[,}])/g,'$1"$2"$3'),r}};ht.SingleQuoteStrategy=hE;var gE=class extends ci{constructor(){super(...arguments),this.name="UnquotedKeyRepair",this.description="Adds quotes to unquoted object keys"}canApply(e){return/[{,]\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*:/.test(e)}apply(e){return e.replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)(\s*:)/g,'$1"$2"$3')}};ht.UnquotedKeyStrategy=gE;var mE=class extends ci{constructor(){super(...arguments),this.name="CommentRemoval",this.description="Removes JavaScript-style comments"}canApply(e){return/\/\/.*$|\/\*[\s\S]*?\*\//m.test(e)}apply(e){let r=e.replace(/\/\/.*$/gm,"");return r=r.replace(/\/\*[\s\S]*?\*\//g,""),r}};ht.CommentStrategy=mE;var FQ=class extends ci{constructor(){super(...arguments),this.name="UnescapedControlCharactersRepair",this.description="Escapes unescaped control characters (newlines, tabs, etc.) in JSON strings"}canApply(e){try{return JSON.parse(e),!1}catch(r){let n=r.message||"";return n.includes("control character")||n.includes("Bad control")||n.includes("Unexpected token")&&/[\n\r\t]/.test(e)}}apply(e){let r="",n=!1,i=!1;for(let o=0;o<e.length;o++){let s=e[o],a=o>0?e[o-1]:"";if(i){r+=s,i=!1;continue}if(s==="\\"&&n){r+=s,i=!0;continue}if(s==='"'&&a!=="\\"){n=!n,r+=s;continue}if(n)switch(s){case`
2176
+ ${o}`:i.stack}K.exports.fetch=function(e,r=void 0){return NUe(e,r).catch(n=>{throw uV?pV(n,uV):n&&typeof n=="object"&&Error.captureStackTrace(n,K.exports.fetch),n})};K.exports.Headers=wc().Headers;K.exports.Response=op().Response;K.exports.Request=sl().Request;K.exports.FormData=Rm().FormData;var{setGlobalOrigin:kUe,getGlobalOrigin:OUe}=eB();K.exports.setGlobalOrigin=kUe;K.exports.getGlobalOrigin=OUe;var{CacheStorage:UUe}=ZG(),{kConstruct:xUe}=We();K.exports.caches=new UUe(xUe);var{deleteCookie:MUe,getCookies:LUe,getSetCookies:PUe,setCookie:$Ue,parseCookie:FUe}=uY();K.exports.deleteCookie=MUe;K.exports.getCookies=LUe;K.exports.getSetCookies=PUe;K.exports.setCookie=$Ue;K.exports.parseCookie=FUe;var{parseMIMEType:jUe,serializeAMimeType:zUe}=xn();K.exports.parseMIMEType=jUe;K.exports.serializeAMimeType=zUe;var{CloseEvent:HUe,ErrorEvent:qUe,MessageEvent:GUe}=Wy(),{WebSocket:YUe,ping:VUe}=jY();K.exports.WebSocket=YUe;K.exports.CloseEvent=HUe;K.exports.ErrorEvent=qUe;K.exports.MessageEvent=GUe;K.exports.ping=VUe;K.exports.WebSocketStream=WY().WebSocketStream;K.exports.WebSocketError=OQ().WebSocketError;K.exports.request=mp(yl.request);K.exports.stream=mp(yl.stream);K.exports.pipeline=mp(yl.pipeline);K.exports.connect=mp(yl.connect);K.exports.upgrade=mp(yl.upgrade);K.exports.MockClient=IUe;K.exports.MockCallHistory=CUe;K.exports.MockCallHistoryLog=bUe;K.exports.MockPool=wUe;K.exports.MockAgent=SUe;K.exports.SnapshotAgent=BUe;K.exports.mockErrors=_Ue;var{EventSource:JUe}=cV();K.exports.EventSource=JUe;function WUe(){globalThis.fetch=K.exports.fetch,globalThis.Headers=K.exports.Headers,globalThis.Response=K.exports.Response,globalThis.Request=K.exports.Request,globalThis.FormData=K.exports.FormData,globalThis.WebSocket=K.exports.WebSocket,globalThis.CloseEvent=K.exports.CloseEvent,globalThis.ErrorEvent=K.exports.ErrorEvent,globalThis.MessageEvent=K.exports.MessageEvent,globalThis.EventSource=K.exports.EventSource}K.exports.install=WUe});var gV=m(Il=>{"use strict";Object.defineProperty(Il,"__esModule",{value:!0});Il.SuperglueClient=Il.SuperglueHttpError=void 0;var El=Lr(),Ur=aS(),ZUe=WS(),KUe=v$(),XUe=Rn(),As=fu(),exe=$d(),Ep=14400*1e3,yp;if(typeof globalThis.process<"u"&&globalThis.process.versions?.node)try{let{Agent:t}=fV();yp=new t({headersTimeout:Ep,bodyTimeout:Ep})}catch{}function hV(t){if(t?.aborted)throw t.reason??new DOMException("Aborted","AbortError")}var dE=class extends Error{constructor(e,r,n,i){super(e),this.status=r,this.code=n,this.details=i,this.name="SuperglueHttpError"}};Il.SuperglueHttpError=dE;var $Q=class{constructor({apiKey:e,apiEndpoint:r,onInfrastructureError:n,refreshToken:i,sseTokenProvider:o,tokenProvider:s}){if(!e&&!s)throw new Error("SuperglueClient requires either apiKey or tokenProvider");this.tokenProvider=s??(async()=>e),this.apiEndpoint=r??"https://api.superglue.cloud",this.sseManager=new ZUe.SSELogSubscriptionManager(this.apiEndpoint,o??this.tokenProvider,i),this.onInfrastructureError=n,this.refreshToken=i}async getApiKey(){return this.tokenProvider()}async fetchWithAuthRetry(e,r){let n=await this.getApiKey(),i=await e(n);if(i.status!==401||!this.refreshToken)return i;hV(r);let o=await this.refreshToken();return hV(r),!o||o===n?i:(i.body?.cancel(),e(o))}isInfrastructureError(e){return(0,XUe.isAbortError)(e)?!1:!!(e instanceof TypeError&&e.message.toLowerCase().includes("fetch")||e instanceof Error&&e.name==="TimeoutError")}async restRequest(e,r,n,i,o){let a=await(await this.restResponse({method:e,path:r,body:n,extraHeaders:i,requestInit:o})).text();if(a)return JSON.parse(a)}async restData(...e){return(await this.restRequest(...e)).data}async restResponse({method:e,path:r,body:n,extraHeaders:i,requestInit:o}){let s=`${this.apiEndpoint.replace(/\/$/,"")}${r}`,a=n!=null,c=typeof FormData<"u"&&n instanceof FormData,u=l=>{let d={Authorization:`Bearer ${l}`,...i};return a&&!c&&e!=="GET"&&(d["Content-Type"]="application/json"),fetch(s,{...o,method:e,headers:d,body:a?c?n:JSON.stringify(n):void 0,signal:o?.signal??AbortSignal.timeout(Ep),...yp?{dispatcher:yp}:{}})};return this.sendAuthorized(u,o?.signal)}async sendAuthorized(e,r){let n;try{n=await this.fetchWithAuthRetry(e,r)}catch(i){throw this.isInfrastructureError(i)&&this.onInfrastructureError?.(),i}if(!n.ok)throw await this.buildHttpError(n);return n}async uploadFiles(e,r){if(typeof r?.process!="boolean")throw new Error("process must be a boolean");if(e.length===0)return[];let n=e.map(l=>({...l,contentLength:l.contentLength??this.getUploadContentLength(l.content)})),o=(await this.restRequest("POST","/v1/files/uploads",{process:r.process,...r.allowUnprocessed?{allowUnprocessed:!0}:{},files:n.map(({fileName:l,contentType:d,contentLength:A})=>({fileName:l,contentLength:A,...d?{contentType:d}:{}}))})).data.files;if(o.length!==n.length)throw await Promise.all(o.map(l=>this.deleteFileUpload(l.id).catch(()=>{}))),new Error("Upload response did not match the selected files");let s=await Promise.allSettled(o.map(async(l,d)=>{let A=n[d],p=await fetch(l.uploadUrl,{method:"PUT",body:A.content,headers:{...l.uploadHeaders,...A.contentType?{"Content-Type":A.contentType}:{}},signal:AbortSignal.timeout(Math.min(Ep,l.expiresIn*1e3))});if(!p.ok)throw new Error(`Upload failed for ${A.fileName}: ${p.status} ${p.statusText}`);return l.id})),a=s.flatMap(l=>l.status==="fulfilled"?[l.value]:[]),c=new Map;if(a.length>0)try{let l=await this.restRequest("POST","/v1/files/uploads/complete",{fileIds:a});c=new Map(l.data.files.map(d=>[d.id,d]))}catch(l){c=new Map(a.map(d=>[d,{id:d,fileName:n[o.findIndex(A=>A.id===d)]?.fileName||d,contentLength:n[o.findIndex(A=>A.id===d)]?.contentLength||0,status:"failed",error:l instanceof Error?l.message:String(l)}]))}let u=o.map((l,d)=>{let A=s[d],p=n[d];return A.status==="rejected"?{id:l.id,fileName:p.fileName,contentLength:p.contentLength,status:"failed",error:A.reason instanceof Error?A.reason.message:String(A.reason)}:c.get(l.id)||{id:l.id,fileName:p.fileName,contentLength:p.contentLength,status:"failed",error:"Upload completion returned no result"}});return await Promise.all(u.filter(l=>l.status==="failed").map(l=>this.deleteFileUpload(l.id).catch(()=>{}))),u}async deleteFileUpload(e){await this.restRequest("DELETE",`/v1/files/uploads/${encodeURIComponent(e)}`)}getUploadContentLength(e){return typeof e=="string"?new TextEncoder().encode(e).byteLength:e instanceof Uint8Array?e.byteLength:e.size}async buildHttpError(e){e.status>=500&&this.onInfrastructureError?.();let r=await e.text(),n=`HTTP ${e.status}: ${r}`,i,o;try{let s=JSON.parse(r);s&&typeof s=="object"&&!Array.isArray(s)&&(o=s),typeof s?.code=="string"&&(i=s.code);let a=s.error;typeof a=="string"?n=a:a&&typeof a=="object"&&(n=a.message||JSON.stringify(a))}catch{}return new dE(n,e.status,i,o)}async streamRequest(e,r,n){let i=e.includes("?")?"&":"?",o=`${this.apiEndpoint.replace(/\/$/,"")}${e}${i}stream=true`,s=u=>fetch(o,{method:"POST",headers:{Authorization:`Bearer ${u}`,Accept:"text/event-stream","Content-Type":"application/json"},body:JSON.stringify(r),signal:n??AbortSignal.timeout(Ep),...yp?{dispatcher:yp}:{}}),a;try{a=await this.fetchWithAuthRetry(s,n)}catch(u){throw this.isInfrastructureError(u)&&this.onInfrastructureError?.(),u}if(!a.ok)throw await this.buildHttpError(a);if(!(a.headers.get("content-type")||"").includes("text/event-stream")){let u=await a.text();return u?JSON.parse(u):void 0}try{return await(0,KUe.consumeEventStreamResult)(a)}catch(u){throw this.isInfrastructureError(u)&&this.onInfrastructureError?.(),u}}async subscribeToLogsSSE(e={}){return this.sseManager.subscribeToLogs(e)}async disconnect(){await this.sseManager.disconnect()}async listMemoryNotes(e={}){let r=new URLSearchParams;e.scope&&r.set("scope",e.scope),e.query&&r.set("query",e.query);let n=r.toString();return this.restData("GET",`/v1/memory-notes${n?`?${n}`:""}`)}async createMemoryNote(e){return this.restData("POST","/v1/memory-notes",e)}async updateMemoryNote(e,r){return this.restData("PATCH",`/v1/memory-notes/${encodeURIComponent(e)}`,r)}async deleteMemoryNote(e){await this.restRequest("DELETE",`/v1/memory-notes/${encodeURIComponent(e)}`)}async clearMemoryNotes(e){return(await this.restRequest("DELETE",`/v1/memory-notes?scope=${e}`)).data.deleted}async getMe(){return this.restRequest("GET","/v1/me")}async completeOnboarding(){return this.restRequest("POST","/v1/me/onboarding/complete")}async runTool(e){let r=await this.restRequest("POST",`/v1/tools/${encodeURIComponent(e.toolId)}/run`,{inputs:e.payload,files:e.files,credentials:e.credentials,includeStepResultData:e.includeStepResultData,options:e.options,runId:e.runId,stateFixture:e.stateFixture},void 0,e.signal?{signal:e.signal}:void 0);return{success:r.status==="success",data:r.data,error:r.error,tool:r.tool,stepResults:r.stepResults?.map(n=>({...n}))||[],...r.fileArtifacts&&r.fileArtifacts.length>0?{fileArtifacts:r.fileArtifacts}:{},...r.metadata?.warnings?.length?{warnings:r.metadata.warnings}:{}}}async runToolConfig(e){let r=e.createRun?"/v1/tools/run?createRun=true":"/v1/tools/run",n=await this.restRequest("POST",r,{tool:e.tool,payload:e.payload,files:e.files,credentials:e.credentials,includeStepResultData:e.includeStepResultData,options:e.options,runId:e.runId,stateFixture:e.stateFixture,executionKind:e.executionKind,parentToolId:e.parentToolId,draftId:e.draftId},e.traceId?{"X-Trace-Id":e.traceId}:void 0,e.signal?{signal:e.signal}:void 0);return{success:n.status?n.status==="success":n.success??!1,data:n.data,error:n.error,tool:n.tool||e.tool,stepResults:n.stepResults?.map(o=>({...o}))||[],...n.fileArtifacts&&n.fileArtifacts.length>0?{fileArtifacts:n.fileArtifacts}:{},...n.metadata?.warnings?.length?{warnings:n.metadata.warnings}:{}}}async abortToolExecution(e){return{success:!0,runId:(await this.restRequest("POST",`/v1/runs/${encodeURIComponent(e)}/cancel`)).runId}}async executeStep({step:e,payload:r,files:n,previousResults:i,credentials:o,credentialsList:s,options:a,runId:c,systemIds:u,connectionId:l,systemAuth:d,createRun:A,parentToolId:p,stepIndex:h,stepId:g,signal:S,stream:B}){let _={step:e,payload:r,files:n,previousResults:i,credentials:o,credentialsList:s,options:a,runId:c,systemIds:u,connectionId:l,systemAuth:d,createRun:A,parentToolId:p,stepIndex:h,stepId:g};return B?this.streamRequest("/v1/tools/step/run",_,S):this.restRequest("POST","/v1/tools/step/run",_,void 0,S?{signal:S}:void 0)}async abortStep(e){return this.restRequest("POST","/v1/tools/step/abort",{runId:e})}async executeTransformOnly({outputTransform:e,outputSchema:r,inputSchema:n,payload:i,files:o,stepResults:s,options:a,runId:c,createRun:u,parentToolId:l,stepId:d,signal:A,stream:p}){let h={outputTransform:e,outputSchema:r,inputSchema:n,payload:i,files:o,stepResults:s,options:a,runId:c,createRun:u,parentToolId:l,stepId:d};return p?this.streamRequest("/v1/tools/transform/run",h,A):this.restRequest("POST","/v1/tools/transform/run",h,void 0,A?{signal:A}:void 0)}async createRun({toolId:e,toolConfig:r,toolResult:n,stepResults:i,toolPayload:o,status:s,error:a,startedAt:c,completedAt:u,executionKind:l,parentToolId:d,draftId:A}){return this.restRequest("POST","/v1/runs",{toolId:e,toolConfig:r,toolResult:n,stepResults:i,toolPayload:o,status:s,error:a,startedAt:(0,As.toUTCISOString)(c,"run.startedAt"),completedAt:(0,As.toUTCISOString)(u,"run.completedAt"),executionKind:l,parentToolId:d,draftId:A})}async checkRunLimit(){return this.restData("POST","/v1/runs/check-limit")}async extract({file:e,envelope:r}){if(!e)throw new Error("File must be provided for extract.");let n=new FormData;n.append("file",e);let i=r?"/v1/extract?envelope=true":"/v1/extract";return this.restRequest("POST",i,n)}mapOpenAPIRunToRun(e){let r={running:El.RunStatus.RUNNING,success:El.RunStatus.SUCCESS,failed:El.RunStatus.FAILED,aborted:El.RunStatus.ABORTED};return{runId:e.runId??e.id,toolId:e.toolId,tool:e.tool,systemIds:e.systemIds,status:r[e.status]??El.RunStatus.FAILED,toolPayload:e.toolPayload,data:e.data,toolResult:e.data,error:e.error,stepResults:e.stepResults,options:e.options,requestSource:e.requestSource,traceId:e.traceId,resultStorageUri:e.resultStorageUri,userId:e.userId,userEmail:e.userEmail,userName:e.userName,metadata:{...e.metadata,executionKind:e.metadata?.executionKind??El.RunExecutionKind.FULL},fileArtifacts:e.fileArtifacts}}mapOpenAPIScheduleToToolSchedule(e){return{...e,lastRunAt:e.lastRunAt?(0,As.requireUTCDate)(e.lastRunAt,"schedule.lastRunAt"):void 0,nextRunAt:(0,As.requireUTCDate)(e.nextRunAt,"schedule.nextRunAt"),createdAt:(0,As.requireUTCDate)(e.createdAt,"schedule.createdAt"),updatedAt:(0,As.requireUTCDate)(e.updatedAt,"schedule.updatedAt")}}async listRuns(e={}){let r=(0,Ur.createSearchListQueryParams)(e);e.toolId!==void 0&&r.set("toolId",e.toolId),e.searchUserIds?.length&&r.set("searchUserIds",e.searchUserIds.join(",")),e.includeTotal!==void 0&&r.set("includeTotal",String(e.includeTotal)),e.startedAfter!==void 0&&r.set("startedAfter",e.startedAfter instanceof Date?(0,As.toUTCISOString)(e.startedAfter,"run.startedAfter"):e.startedAfter),e.statuses!==void 0?r.set("status",e.statuses.join(",")):e.status!==void 0&&r.set("status",e.status),e.requestSources!==void 0&&r.set("requestSources",e.requestSources.join(",")),e.executionKinds!==void 0&&r.set("executionKinds",e.executionKinds.join(",")),e.userId!==void 0&&r.set("userId",e.userId),e.systemId!==void 0&&r.set("systemId",e.systemId),e.systemIds!==void 0&&r.set("systemIds",e.systemIds.join(","));let n=r.size>0?`?${r.toString()}`:"",i=await this.restRequest("GET",`/v1/runs${n}`,void 0,void 0,{signal:e.signal});return{data:i.data.map(o=>this.mapOpenAPIRunToRun(o)),total:i.total,page:i.page,limit:i.limit,hasMore:i.hasMore}}async getActivityCounts(e){let r=new URLSearchParams;e?.from&&r.set("from",e.from instanceof Date?(0,As.toUTCISOString)(e.from,"activity.from"):e.from),e?.to&&r.set("to",e.to instanceof Date?(0,As.toUTCISOString)(e.to,"activity.to"):e.to);let n=r.toString();return(await this.restRequest("GET",`/v1/activity/counts${n?`?${n}`:""}`,void 0,void 0,{signal:e?.signal})).counts}async getRun(e){try{let r=await this.restRequest("GET",`/v1/runs/${encodeURIComponent(e)}`);return this.mapOpenAPIRunToRun(r)}catch(r){if(r.message?.includes("404")||r.message?.includes("not found"))return null;throw r}}async getTool(e){try{return await this.restRequest("GET",`/v1/tools/${encodeURIComponent(e)}`)}catch(r){if(r.message?.includes("404")||r.message?.includes("not found")||r.message?.includes("403")||r.message?.includes("not allowed"))return null;throw r}}async getToolState(e){return(await this.restRequest("GET",`/v1/tools/${encodeURIComponent(e)}/state`)).state}async setToolState(e,r){await this.restRequest("PUT",`/v1/tools/${encodeURIComponent(e)}/state`,{state:r})}async deleteToolState(e){return(await this.restRequest("DELETE",`/v1/tools/${encodeURIComponent(e)}/state`)).deletedKeys}async archiveTool(e,r=!0){return this.updateTool(e,{archived:r})}async bulkArchiveTools(e,r=!0){return this.restRequest("POST","/v1/tools/bulk/archive",{ids:e,archived:r})}async bulkDeleteTools(e){return this.restRequest("POST","/v1/tools/bulk/delete",{ids:e})}async listTools(e={}){let r=(0,Ur.createListQueryParams)(e);e.includeArchived!==void 0&&r.set("includeArchived",String(e.includeArchived));let n=r.size>0?`?${r.toString()}`:"";return this.restRequest("GET",`/v1/tools${n}`)}async listAllTools(e={}){return(0,Ur.listAllPages)((r,n)=>this.listTools({...e,page:r,limit:n}))}async createTool(e,r){return this.restRequest("POST","/v1/tools",{...r,id:e})}async updateTool(e,r){return this.restRequest("PUT",`/v1/tools/${encodeURIComponent(e)}`,r)}async deleteTool(e){try{return await this.restRequest("DELETE",`/v1/tools/${encodeURIComponent(e)}`),!0}catch(r){if(r.message?.includes("404"))return!1;throw r}}async renameTool(e,r){return this.restRequest("POST",`/v1/tools/${encodeURIComponent(e)}/rename`,{newId:r})}async getWorkflow(e){return this.getTool(e)}async archiveWorkflow(e,r=!0){return this.upsertWorkflow(e,{archived:r})}async createWorkflow(e,r){return this.createTool(e,r)}async updateWorkflow(e,r){return this.updateTool(e,r)}async upsertWorkflow(e,r){return await this.getTool(e)?this.updateTool(e,r):this.createTool(e,r)}async deleteWorkflow(e){return this.deleteTool(e)}async renameWorkflow(e,r){return this.renameTool(e,r)}async listProjectSummaries(e={}){let r=(0,Ur.createSearchListQueryParams)(e);return r.set("includeResources","false"),e.includeArchived!==void 0&&r.set("includeArchived",String(e.includeArchived)),this.restRequest("GET",`/v1/projects?${r.toString()}`)}async listAllProjectSummaries({includeArchived:e}={}){return(0,Ur.listAllPages)((r,n)=>this.listProjectSummaries({page:r,limit:n,...e!==void 0?{includeArchived:e}:{}}))}async listAllProjectTasks(e){return(0,Ur.listAllPages)((r,n)=>this.restRequest("GET",`/v1/projects/${encodeURIComponent(e)}/tasks?page=${r}&limit=${n}`))}async saveProjectTask({projectId:e,taskId:r,input:n}){let i=`/v1/projects/${encodeURIComponent(e)}/tasks${r?`/${encodeURIComponent(r)}`:""}`;return this.restData(r?"PATCH":"POST",i,n)}async listAllProjectLabels(e){return(0,Ur.listAllPages)((r,n)=>this.restRequest("GET",`/v1/projects/${encodeURIComponent(e)}/labels?page=${r}&limit=${n}`))}async saveProjectLabel({projectId:e,labelId:r,input:n}){let i=`/v1/projects/${encodeURIComponent(e)}/labels${r?`/${encodeURIComponent(r)}`:""}`;return this.restData(r?"PATCH":"POST",i,n)}async deleteProjectLabel({projectId:e,labelId:r}){await this.restRequest("DELETE",`/v1/projects/${encodeURIComponent(e)}/labels/${encodeURIComponent(r)}`)}async listSchedules(e={}){let r=(0,Ur.createListQueryParams)(e),n=r.size>0?`?${r.toString()}`:"",i=e.toolId?`/v1/tools/${encodeURIComponent(e.toolId)}/schedules${n}`:`/v1/schedules${n}`,o=await this.restRequest("GET",i);return{...o,data:o.data.map(s=>this.mapOpenAPIScheduleToToolSchedule(s))}}async listAllSchedules(e={}){return(0,Ur.listAllPages)((r,n)=>this.listSchedules({...e,page:r,limit:n}))}async getToolSchedule(e,r){try{let n=await this.restRequest("GET",`/v1/tools/${encodeURIComponent(e)}/schedules/${encodeURIComponent(r)}`);return this.mapOpenAPIScheduleToToolSchedule(n)}catch(n){if(n.message?.includes("404")||n.message?.includes("not found"))return null;throw n}}async createToolSchedule(e,r){let n=await this.restRequest("POST",`/v1/tools/${encodeURIComponent(e)}/schedules`,{...r,timezone:r.timezone||(0,exe.getRuntimeTimezone)()});return this.mapOpenAPIScheduleToToolSchedule(n)}async updateToolSchedule(e,r,n){let i=await this.restRequest("PUT",`/v1/tools/${encodeURIComponent(e)}/schedules/${encodeURIComponent(r)}`,n);return this.mapOpenAPIScheduleToToolSchedule(i)}async deleteToolSchedule(e,r){return await this.restRequest("DELETE",`/v1/tools/${encodeURIComponent(e)}/schedules/${encodeURIComponent(r)}`),!0}async bulkSetSchedulesEnabled(e,r){return this.restRequest("POST","/v1/schedules/bulk/enable",{ids:e,enabled:r})}async bulkDeleteSchedules(e){return this.restRequest("POST","/v1/schedules/bulk/delete",{ids:e})}async listConnections(e={}){let r=(0,Ur.createListQueryParams)(e);e.systemId!==void 0&&r.set("systemId",e.systemId);let n=r.size>0?`?${r.toString()}`:"";return this.restRequest("GET",`/v1/connections${n}`)}async listAllConnections(e={}){return(0,Ur.listAllPages)((r,n)=>this.listConnections({...e,page:r,limit:n}))}async createOAuthApp(e){return this.restData("POST","/v1/oauth-apps",e)}async updateOAuthApp(e,r){return this.restData("PUT",`/v1/oauth-apps/${encodeURIComponent(e)}`,r)}async deleteOAuthApp(e){await this.restRequest("DELETE",`/v1/oauth-apps/${encodeURIComponent(e)}`)}async listOAuthApps({systemId:e}={}){return(0,Ur.listAllPages)(async(r,n)=>{let i=new URLSearchParams({page:String(r),limit:String(n),...e?{systemId:e}:{}});return this.restRequest("GET",`/v1/oauth-apps?${i}`)})}async getConnectionSetup(e){return this.restData("GET",`/v1/connections/setup/${encodeURIComponent(e)}`)}async createConnection(e){return this.restData("POST","/v1/connections",e)}async replaceConnection(e,r){return this.restData("PUT",`/v1/connections/${encodeURIComponent(e)}`,{credentials:r})}async updateConnection(e,r){return this.restData("PATCH",`/v1/connections/${encodeURIComponent(e)}`,r)}async deleteConnection(e){await this.restRequest("DELETE",`/v1/connections/${encodeURIComponent(e)}`)}async setDefaultConnection(e){await this.restRequest("POST",`/v1/connections/${encodeURIComponent(e)}/default`)}async listSystems(e={}){let r=(0,Ur.createListQueryParams)(e),n=r.size>0?`?${r.toString()}`:"";return this.restRequest("GET",`/v1/systems${n}`)}async listAllSystems(e={}){return(0,Ur.listAllPages)((r,n)=>this.listSystems({...e,page:r,limit:n}))}async createOAuthExchange(e){return(await this.restRequest("POST","/v1/oauth/exchanges",e)).data}async completeOAuthExchange(e,r){return(await this.restRequest("POST",`/v1/oauth/exchanges/${encodeURIComponent(e)}/complete`,r)).data}async describeOAuthProviderPage(e){return(await this.restRequest("POST",`/v1/oauth/exchanges/${encodeURIComponent(e)}/provider-page`)).data}async generateCredentialsLink(e){try{return{success:!0,credentialsUrl:(await this.restRequest("POST","/v1/authenticate",e||{})).data.credentialsUrl}}catch(r){return{success:!1,error:r.message}}}};Il.SuperglueClient=$Q});var yV=m(ht=>{"use strict";Object.defineProperty(ht,"__esModule",{value:!0});ht.UnquotedKeyStrategy=ht.TripleQuoteStrategy=ht.TrailingCommaStrategy=ht.SingleQuoteStrategy=ht.PythonLiteralStrategy=ht.CommentStrategy=ht.ResilientJsonParser=ht.RepairStrategy=void 0;ht.parseJsonResilient=txe;ht.parseJSON=rxe;ht.isValidJson=nxe;ht.prettyPrintJson=ixe;ht.minifyJson=oxe;var ci=class{validate(e){try{return JSON.parse(e),!0}catch{return!1}}};ht.RepairStrategy=ci;var AE=class extends ci{constructor(){super(...arguments),this.name="TripleQuoteRepair",this.description="Converts triple-quoted strings to proper JSON, parsing nested JSON content"}canApply(e){return/"""/.test(e)}apply(e){return e.replace(/"""([\s\S]*?)"""/g,(r,n)=>{let i=n.trim();if(i.startsWith("{")&&i.endsWith("}")||i.startsWith("[")&&i.endsWith("]"))try{let s=JSON.parse(i);return JSON.stringify(s)}catch{return`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}"`}return`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}"`})}};ht.TripleQuoteStrategy=AE;var pE=class extends ci{constructor(){super(...arguments),this.name="PythonLiteralRepair",this.description="Converts Python literals to JavaScript equivalents"}canApply(e){return/\b(None|True|False)\b/.test(e)}apply(e){return e.replace(/\bNone\b/g,"null").replace(/\bTrue\b/g,"true").replace(/\bFalse\b/g,"false")}};ht.PythonLiteralStrategy=pE;var fE=class extends ci{constructor(){super(...arguments),this.name="TrailingCommaRepair",this.description="Removes trailing commas from objects and arrays"}canApply(e){return/,\s*[}\]]/.test(e)}apply(e){return e.replace(/,(\s*[}\]])/g,"$1")}};ht.TrailingCommaStrategy=fE;var hE=class extends ci{constructor(){super(...arguments),this.name="SingleQuoteRepair",this.description="Converts single quotes to double quotes"}canApply(e){return/[{,]\s*'[^']*'\s*:/.test(e)||/:\s*'[^']*'/.test(e)}apply(e){let r=e.replace(/([{,]\s*)'([^']+)'(\s*:)/g,'$1"$2"$3');return r=r.replace(/(:\s*)'([^']+)'(\s*[,}])/g,'$1"$2"$3'),r}};ht.SingleQuoteStrategy=hE;var gE=class extends ci{constructor(){super(...arguments),this.name="UnquotedKeyRepair",this.description="Adds quotes to unquoted object keys"}canApply(e){return/[{,]\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*:/.test(e)}apply(e){return e.replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)(\s*:)/g,'$1"$2"$3')}};ht.UnquotedKeyStrategy=gE;var mE=class extends ci{constructor(){super(...arguments),this.name="CommentRemoval",this.description="Removes JavaScript-style comments"}canApply(e){return/\/\/.*$|\/\*[\s\S]*?\*\//m.test(e)}apply(e){let r=e.replace(/\/\/.*$/gm,"");return r=r.replace(/\/\*[\s\S]*?\*\//g,""),r}};ht.CommentStrategy=mE;var FQ=class extends ci{constructor(){super(...arguments),this.name="UnescapedControlCharactersRepair",this.description="Escapes unescaped control characters (newlines, tabs, etc.) in JSON strings"}canApply(e){try{return JSON.parse(e),!1}catch(r){let n=r.message||"";return n.includes("control character")||n.includes("Bad control")||n.includes("Unexpected token")&&/[\n\r\t]/.test(e)}}apply(e){let r="",n=!1,i=!1;for(let o=0;o<e.length;o++){let s=e[o],a=o>0?e[o-1]:"";if(i){r+=s,i=!1;continue}if(s==="\\"&&n){r+=s,i=!0;continue}if(s==='"'&&a!=="\\"){n=!n,r+=s;continue}if(n)switch(s){case`
2177
2177
  `:r+="\\n";break;case"\r":r+="\\r";break;case" ":r+="\\t";break;case"\b":r+="\\b";break;case"\f":r+="\\f";break;default:let c=s.charCodeAt(0);c<32?r+="\\u"+("0000"+c.toString(16)).slice(-4):r+=s}else r+=s}return r}},jQ=class extends ci{constructor(){super(...arguments),this.name="TrailingCharactersRepair",this.description="Removes trailing characters after valid JSON structure"}canApply(e){let r=e.trim();if(!r.startsWith("{")&&!r.startsWith("["))return!1;let n=0,i=0,o=!1,s=!1;for(let a=0;a<r.length;a++){let c=r[a];if(o)s?s=!1:c==="\\"?s=!0:c==='"'&&(o=!1);else if(c==='"')o=!0;else if(c==="{")n++;else if(c==="}"){if(n--,n===0&&i===0&&a>0&&a<r.length-1)return!0}else if(c==="[")i++;else if(c==="]"&&(i--,i===0&&n===0&&a>0&&a<r.length-1))return!0}return!1}apply(e){let r=e.trim(),n=0,i=0,o=!1,s=!1,a=-1;for(let c=0;c<r.length;c++){let u=r[c];if(o)s?s=!1:u==="\\"?s=!0:u==='"'&&(o=!1);else if(u==='"')o=!0;else if(u==="{")n++;else if(u==="}"){if(n--,n===0&&i===0&&c>0){a=c;break}}else if(u==="[")i++;else if(u==="]"&&(i--,i===0&&n===0&&c>0)){a=c;break}}return a>0&&a<r.length-1?r.substring(0,a+1):e}},Cl=class{constructor(e={}){this.strategies=[],this.repairLog=[],this.options={attemptRepair:!0,maxDepth:10,preserveStringsOnFailure:!1,logRepairs:!1,...e},this.initializeDefaultStrategies(),e.customStrategies&&this.strategies.push(...e.customStrategies)}initializeDefaultStrategies(){this.strategies=[new AE,new hE,new FQ,new jQ,new pE,new fE,new gE,new mE]}parse(e){let r=Date.now();this.repairLog=[];let n=e instanceof Buffer?e.toString("utf8"):String(e);try{return{success:!0,data:JSON.parse(n),metadata:{parseTime:Date.now()-r,strategiesApplied:[]}}}catch(s){if(!this.options.attemptRepair)return{success:!1,error:`JSON parse error: ${s}`,metadata:{parseTime:Date.now()-r}}}let i=n,o=[];for(let s of this.strategies)if(s.canApply(i)){let a=i;if(i=s.apply(i),a!==i){o.push(s.name),this.repairLog.push(s.description),this.options.logRepairs&&console.log(`Applied ${s.name}: ${s.description}`);try{return{success:!0,data:JSON.parse(i),repairs:this.repairLog,metadata:{parseTime:Date.now()-r,strategiesApplied:o}}}catch{}}}try{return{success:!0,data:JSON.parse(i),repairs:this.repairLog,metadata:{parseTime:Date.now()-r,strategiesApplied:o}}}catch(s){let a=this.aggressiveFallback(i);return a.success?{...a,repairs:[...this.repairLog,"Applied aggressive fallback"],metadata:{parseTime:Date.now()-r,strategiesApplied:[...o,"AggressiveFallback"]}}:{success:!1,error:`Failed to parse JSON after applying ${o.length} strategies: ${s}`,repairs:this.repairLog,metadata:{parseTime:Date.now()-r,strategiesApplied:o}}}}aggressiveFallback(e){try{let r=e.indexOf("{"),n=e.indexOf("[");if(r===-1&&n===-1)return{success:!1,error:"No JSON-like structure found"};let i=r===-1?n:n===-1?r:Math.min(r,n),o=e.substring(i);for(let a of this.strategies)a.canApply(o)&&(o=a.apply(o));return{success:!0,data:JSON.parse(o)}}catch(r){return{success:!1,error:`Aggressive fallback failed: ${r}`}}}addStrategy(e){this.strategies.push(e)}removeStrategy(e){this.strategies=this.strategies.filter(r=>r.name!==e)}getStrategies(){return this.strategies.map(e=>e.name)}};ht.ResilientJsonParser=Cl;var mV=new Cl;function txe(t,e){return(e?new Cl(e):mV).parse(t)}function rxe(t){let e=mV.parse(t);if(e.success)return e.repairs&&e.repairs.length>0&&console.log("JSON parsed with repairs:",e.repairs),e.data;throw new Error(`Failed to parse JSON: ${e.error}`)}function nxe(t){try{return JSON.parse(t),!0}catch{return!1}}function ixe(t,e=2){return JSON.stringify(t,null,e)}function oxe(t){let r=new Cl().parse(t);if(r.success)return JSON.stringify(r.data);throw new Error("Cannot minify invalid JSON")}});var IV=m(Xt=>{"use strict";Object.defineProperty(Xt,"__esModule",{value:!0});Xt.MANAGED_OAUTH_APP_PREFIX=void 0;Xt.projectOAuthAppAuthentication=cxe;Xt.withoutOAuthAppOwnedFields=uxe;Xt.hasOAuthClientChanged=lxe;Xt.isDynamicOAuthConfiguration=dxe;Xt.isReusableOAuthAppForTemplate=Axe;Xt.getManagedOAuthTemplateId=EV;Xt.getOAuthAppSharedConfiguration=pxe;Xt.copyOAuthAppConfiguration=fxe;Xt.encryptConnectionAuthentication=hxe;Xt.decryptConnectionAuthentication=gxe;Xt.isManagedOAuthEndpointAllowed=mxe;var sxe=YS(),axe=Rn();function cxe(t){let{clientSecret:e,config:r,...n}=t,{extraHeaders:i,extraBodyParams:o,...s}=r??{};return{...n,...r?{config:s}:{}}}function uxe(t){if(!t.oauthAppId)return t;let{clientId:e,clientSecret:r,tokenUrl:n,...i}=t;return EV(t)&&n?{...i,tokenUrl:n}:i}function lxe(t,e){return t.type!=="oauth2"?!1:e.type!=="oauth2"?!0:t.oauthAppId||e.oauthAppId?t.oauthAppId!==e.oauthAppId:t.clientId!==e.clientId}Xt.MANAGED_OAUTH_APP_PREFIX="managed:";function dxe({authentication:t,template:e}){return t.oauthClientMode==="dynamic"||!!e?.oauth?.registrationUrl&&!t.clientSecret}function Axe({app:t,template:e}){return!e?.oauth?.registrationUrl||!!t.clientSecretHash}function EV(t){if(t?.type==="oauth2")return t.oauthAppId?.startsWith(Xt.MANAGED_OAUTH_APP_PREFIX)?t.oauthAppId.slice(Xt.MANAGED_OAUTH_APP_PREFIX.length):void 0}function pxe(t){let{grantType:e,scopes:r,oauthAppId:n,...i}=t;return i}function fxe({appAuthentication:t,authentication:e}){if(e?.type!=="oauth2")return{...t};let r=Object.fromEntries(Object.entries(e).filter(([,n])=>n!==void 0));return{...t,...r,config:{...t.config,...e.config}}}function hxe({authentication:t,encrypt:e}){if(t.type!=="oauth2")return t;let r={...t,config:{...t.config}};t.clientSecret!==void 0&&(r.clientSecret=e({value:t.clientSecret}).value);for(let n of["extraHeaders","extraBodyParams"]){let i=t.config?.[n];i!==void 0&&(r.config[n]=e({value:(0,axe.safeStringify)(i)}).value)}return r}function gxe({authentication:t,decrypt:e}){if(t.type!=="oauth2")return t;let r={...t,config:{...t.config}};t.clientSecret!==void 0&&(r.clientSecret=e({value:t.clientSecret}).value);for(let n of["extraHeaders","extraBodyParams"]){let i=t.config?.[n];typeof i=="string"&&(r.config[n]=JSON.parse(e({value:i}).value))}return r}function mxe({templateId:t,endpoint:e,url:r}){let n=sxe.systems[t]?.oauth,i=n?.[e];if(!n?.managed||!i)return!1;try{let o=new URL(r),s=new URL(i);return o.protocol!=="https:"||o.port||o.username||o.password||o.hash||o.pathname!==s.pathname?!1:o.hostname===s.hostname||(n.managedEndpointHosts??[]).some(a=>a.startsWith("*.")?o.hostname.endsWith(a.slice(1)):o.hostname===a)}catch{return!1}}});var bV=m(CV=>{"use strict";Object.defineProperty(CV,"__esModule",{value:!0})});var Ir=m(V=>{"use strict";var yxe=V&&V.__createBinding||(Object.create?(function(t,e,r,n){n===void 0&&(n=r);var i=Object.getOwnPropertyDescriptor(e,r);(!i||("get"in i?!e.__esModule:i.writable||i.configurable))&&(i={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,n,i)}):(function(t,e,r,n){n===void 0&&(n=r),t[n]=e[r]})),te=V&&V.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&yxe(e,t,r)};Object.defineProperty(V,"__esModule",{value:!0});V.SSELogSubscriptionManager=V.SuperglueHttpError=V.SuperglueClient=void 0;te(wM(),V);te(DM(),V);te(jM(),V);te(HM(),V);te(JM(),V);te(WM(),V);te(KM(),V);te(vg(),V);te(TL(),V);te(eh(),V);te(OL(),V);te(UL(),V);te(xL(),V);te(ML(),V);te(LL(),V);te(aS(),V);te($L(),V);te(zL(),V);te(Zd(),V);te(WL(),V);te(cS(),V);te(lS(),V);te(fS(),V);te(KL(),V);te(XL(),V);te(tP(),V);te(ph(),V);te(nP(),V);te(iP(),V);te(sP(),V);te(aP(),V);te(lP(),V);te(_P(),V);te(BS(),V);te(Fg(),V);te(wS(),V);te(RP(),V);te(kP(),V);te(kS(),V);te(FP(),V);te(Sg(),V);te(WP(),V);te(KP(),V);te(wg(),V);te(IS(),V);te(i$(),V);te(o$(),V);te(YS(),V);te(g$(),V);te(m$(),V);te(y$(),V);te(b$(),V);te(w$(),V);te(Lr(),V);te(Rn(),V);te(B$(),V);te(_$(),V);te(Gg(),V);te(fu(),V);te($d(),V);var SV=gV();Object.defineProperty(V,"SuperglueClient",{enumerable:!0,get:function(){return SV.SuperglueClient}});Object.defineProperty(V,"SuperglueHttpError",{enumerable:!0,get:function(){return SV.SuperglueHttpError}});var Exe=WS();Object.defineProperty(V,"SSELogSubscriptionManager",{enumerable:!0,get:function(){return Exe.SSELogSubscriptionManager}});te(yV(),V);te(IV(),V);te(bV(),V)});var tI=require("commander");var xr=Ee(require("fs")),_V=Ee(require("os")),ps=Ee(require("path")),Ip=Ee(Ir()),wV=new Set(["runner","builder","admin"]),BV={output:{mode:"stdout",directory:".superglue/output"},preset:"admin"};function fs(t){let e=ps.join(process.cwd(),".superglue"),r=_V.homedir();if(!r)return e;let n=ps.join(r,".superglue");return t===!0?e:t===!1?n:xr.existsSync(ps.join(e,"config.json"))?e:n}function zQ(t){return ps.join(fs(t),"config.json")}function yE(t){let e=zQ(t);if(!xr.existsSync(e))return{};try{return JSON.parse(xr.readFileSync(e,"utf-8"))}catch{return{}}}function bl(t){let e=yE(),r=t.apiKey||(0,Ip.readProcessEnvironmentValue)("SUPERGLUE_API_KEY")||e.apiKey||"",n=t.endpoint||(0,Ip.readProcessEnvironmentValue)("SUPERGLUE_API_ENDPOINT")||e.endpoint||"https://api.superglue.cloud",i=(0,Ip.readProcessEnvironmentValue)("SUPERGLUE_WEB_ENDPOINT")||e.webEndpoint||n.replace(/:3002\b/,":3001").replace(/api\.superglue/,"app.superglue"),o=(0,Ip.readProcessEnvironmentValue)("SUPERGLUE_CLI_PRESET"),s=o&&wV.has(o)?o:e.preset&&wV.has(e.preset)?e.preset:"admin";return{...BV,...e,apiKey:r,endpoint:n,webEndpoint:i,preset:s,output:{...BV.output,...e.output}}}function EE(t,e){let r=fs(e);xr.existsSync(r)||xr.mkdirSync(r,{recursive:!0}),xr.writeFileSync(ps.join(r,"config.json"),JSON.stringify(t,null,2)+`
2178
- `,{mode:384})}function IE(t,e){let r=ps.join(fs(e),"drafts");if(xr.existsSync(r)||xr.mkdirSync(r,{recursive:!0}),t.output.mode==="stdout+file"){let n=ps.resolve(t.output.directory);xr.existsSync(n)||xr.mkdirSync(n,{recursive:!0})}}var WQ=Ee(Ir());var HQ=Ee(require("readline"));var TV=require("child_process"),DV=require("util");var vV={name:"@superglue/cli",version:"1.1.230",bin:{sg:"./dist/cli.js"},files:[".claude-plugin/","dist/","skills/","LICENSE"],dependencies:{commander:"15.0.0-0","fast-json-patch":"3.1.1"},devDependencies:{"@superglue/shared":"file:../shared","@types/node":"25.5.0",tsup:"8.5.1",typescript:"5.8.3"},scripts:{build:"tsup && (cp -r skills dist/ 2>/dev/null || true)",dev:"tsup --watch","type-check":"tsc --noEmit",prepublishOnly:"npm run build"},publishConfig:{access:"public"}};var Cxe=(0,DV.promisify)(TV.exec),Cr=vV.version;function QV(t){let e=t.match(/^(\d+)(?:-(.+))?$/);return e?{numeric:parseInt(e[1],10),prerelease:e[2]||null}:{numeric:0,prerelease:t}}function bE(t,e){let r=t.split("."),n=e.split("."),i=Math.max(r.length,n.length);for(let o=0;o<i;o++){let s=QV(r[o]||"0"),a=QV(n[o]||"0");if(s.numeric<a.numeric)return-1;if(s.numeric>a.numeric||s.prerelease===null&&a.prerelease!==null)return 1;if(s.prerelease!==null&&a.prerelease===null)return-1;if(s.prerelease!==null&&a.prerelease!==null){if(s.prerelease<a.prerelease)return-1;if(s.prerelease>a.prerelease)return 1}}return 0}async function SE(){try{let t=await fetch("https://registry.npmjs.org/@superglue/cli/latest",{signal:AbortSignal.timeout(5e3)});return t.ok&&(await t.json()).version||null}catch{return null}}var CE=null;function RV(){le()&&(CE=SE())}async function NV(){if(!(!le()||!CE)){try{let t=new Promise(r=>{setTimeout(()=>r(null),2e3).unref()}),e=await Promise.race([CE,t]);e&&bE(Cr,e)<0&&(console.error(""),console.error(`${I.cyan}${I.bold} Update available: ${Cr} \u2192 ${e}${I.reset}`),console.error(`${I.cyan} Run ${I.bold}sg update${I.reset}${I.cyan} to upgrade${I.reset}`),console.error(""))}catch{}CE=null}}async function kV(){let t=await SE();if(!t)return{success:!1,message:"Could not fetch latest version from npm"};if(bE(Cr,t)>=0)return{success:!0,message:`Already on latest version (${Cr})`};try{return await Cxe("npm install -g @superglue/cli@latest"),{success:!0,message:`Updated from ${Cr} to ${t}`}}catch(e){return{success:!1,message:`Update failed: ${e.message}. Try manually: npm install -g @superglue/cli@latest`}}}var le=()=>process.argv.includes("--table")&&process.stdout.isTTY,qn=()=>process.argv.includes("--full"),I={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",italic:"\x1B[3m",underline:"\x1B[4m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m",gray:"\x1B[90m",bgRed:"\x1B[41m",bgGreen:"\x1B[42m",bgYellow:"\x1B[43m",bgBlue:"\x1B[44m",bgMagenta:"\x1B[45m",bgCyan:"\x1B[46m"};function OV(t,e){let r=e||t;return`\x1B]8;;${t}\x07${I.underline}${I.cyan}${r}${I.reset}\x1B]8;;\x07`}function UV(){if(!le())return;let t=I.reset,e=I.dim,r="\x1B[47;30m",n=[" #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@- "," =@@@- @@@@ "," @@@ @@% "," -@@ @@@@= @@@ @@@ @@@@@#@ @@@@@@@ @@@@@@@ @@@@@@ @@@ @@@ @@@ @@@@@@* %@@ "," @@ @@@ *@ @@@ @@@ @@@ :@@ @@@ @@@ -@@ @@@ @% @@@ @@@ @@@ @@* @@# "," #@@ @@@# @@@ @@@ @@@ :@@ @@@ @@@ -@@ @@@ @@@ @@@ @@@ @@* @@ "," @@- @@@@= @@@ @@@ @@@@@@@ @@@@@@ @@@@@@@ @@@ @@% @@@ @@@ @@@ @@@@@. @@."," #@% .@@@@ @@@ @@@ @@@ @@@ @@@ -@@ @@@ @@% @@@ @@@ @@@ @@* @@ "," @@ @ @@@ @@@ @@@ @@@ @@@ @@@ -@@ @@@ @@% @@@ @@@ @@@ @@* *@@ "," -@@ @@@@= @@@@@@ @@@ @@@@@@@ @@@ -@@ @@@@@@ @@@@@@% @@@@@@. @@@@@@* #@@ "," :@@* @@@ "," %@@@ =@@@. "," :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% "];console.log(""),n.forEach(i=>{let o=i.search(/\S/),s=i.length-[...i].reverse().join("").search(/\S/)-1;if(o===-1)return console.log(" "+i);let a=i.slice(0,o),c=i.slice(o,s+1).split("").map(l=>l===" "?" ":"\u2588").join(""),u=i.slice(s+1);console.log(` ${a}${r}${c}${t}${u}`)}),console.log(` ${e} CLI v${Cr}${t}`),console.log("")}function Ut(t){if(!le())return{stop:()=>{},update:()=>{},log:()=>{}};let e=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],r=0,n=t,i=()=>process.stdout.write("\r\x1B[2K"),o=()=>{process.stdout.write(`\r ${I.cyan}${e[r++%e.length]}${I.reset} ${n}`)},s=setInterval(o,80);return{update:a=>{n=a},log:a=>{i(),console.log(` ${I.dim}\u2502${I.reset} ${a}`),o()},stop:a=>{clearInterval(s),i(),a&&console.log(` ${a}`)}}}function re(t){le()?wE(t):console.log(JSON.stringify(t,null,2))}function Te(t,e){le()?(console.log(` ${I.green}\u2713${I.reset} ${t}`),e&&wE(e,4)):console.log(JSON.stringify({success:!0,message:t,...e&&typeof e=="object"?e:{data:e}}))}function Q(t,e){le()?(console.error(` ${I.red}\u2717${I.reset} ${t}`),e&&wE(e,4)):console.error(JSON.stringify({success:!1,error:t,details:e}))}function dn(t){le()&&console.log(` ${I.dim}${t}${I.reset}`)}function kc(t){le()&&(console.log(`
2178
+ `,{mode:384})}function IE(t,e){let r=ps.join(fs(e),"drafts");if(xr.existsSync(r)||xr.mkdirSync(r,{recursive:!0}),t.output.mode==="stdout+file"){let n=ps.resolve(t.output.directory);xr.existsSync(n)||xr.mkdirSync(n,{recursive:!0})}}var WQ=Ee(Ir());var HQ=Ee(require("readline"));var TV=require("child_process"),DV=require("util");var vV={name:"@superglue/cli",version:"1.1.231",bin:{sg:"./dist/cli.js"},files:[".claude-plugin/","dist/","skills/","LICENSE"],dependencies:{commander:"15.0.0-0","fast-json-patch":"3.1.1"},devDependencies:{"@superglue/shared":"file:../shared","@types/node":"25.5.0",tsup:"8.5.1",typescript:"5.8.3"},scripts:{build:"tsup && (cp -r skills dist/ 2>/dev/null || true)",dev:"tsup --watch","type-check":"tsc --noEmit",prepublishOnly:"npm run build"},publishConfig:{access:"public"}};var Cxe=(0,DV.promisify)(TV.exec),Cr=vV.version;function QV(t){let e=t.match(/^(\d+)(?:-(.+))?$/);return e?{numeric:parseInt(e[1],10),prerelease:e[2]||null}:{numeric:0,prerelease:t}}function bE(t,e){let r=t.split("."),n=e.split("."),i=Math.max(r.length,n.length);for(let o=0;o<i;o++){let s=QV(r[o]||"0"),a=QV(n[o]||"0");if(s.numeric<a.numeric)return-1;if(s.numeric>a.numeric||s.prerelease===null&&a.prerelease!==null)return 1;if(s.prerelease!==null&&a.prerelease===null)return-1;if(s.prerelease!==null&&a.prerelease!==null){if(s.prerelease<a.prerelease)return-1;if(s.prerelease>a.prerelease)return 1}}return 0}async function SE(){try{let t=await fetch("https://registry.npmjs.org/@superglue/cli/latest",{signal:AbortSignal.timeout(5e3)});return t.ok&&(await t.json()).version||null}catch{return null}}var CE=null;function RV(){le()&&(CE=SE())}async function NV(){if(!(!le()||!CE)){try{let t=new Promise(r=>{setTimeout(()=>r(null),2e3).unref()}),e=await Promise.race([CE,t]);e&&bE(Cr,e)<0&&(console.error(""),console.error(`${I.cyan}${I.bold} Update available: ${Cr} \u2192 ${e}${I.reset}`),console.error(`${I.cyan} Run ${I.bold}sg update${I.reset}${I.cyan} to upgrade${I.reset}`),console.error(""))}catch{}CE=null}}async function kV(){let t=await SE();if(!t)return{success:!1,message:"Could not fetch latest version from npm"};if(bE(Cr,t)>=0)return{success:!0,message:`Already on latest version (${Cr})`};try{return await Cxe("npm install -g @superglue/cli@latest"),{success:!0,message:`Updated from ${Cr} to ${t}`}}catch(e){return{success:!1,message:`Update failed: ${e.message}. Try manually: npm install -g @superglue/cli@latest`}}}var le=()=>process.argv.includes("--table")&&process.stdout.isTTY,qn=()=>process.argv.includes("--full"),I={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",italic:"\x1B[3m",underline:"\x1B[4m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m",gray:"\x1B[90m",bgRed:"\x1B[41m",bgGreen:"\x1B[42m",bgYellow:"\x1B[43m",bgBlue:"\x1B[44m",bgMagenta:"\x1B[45m",bgCyan:"\x1B[46m"};function OV(t,e){let r=e||t;return`\x1B]8;;${t}\x07${I.underline}${I.cyan}${r}${I.reset}\x1B]8;;\x07`}function UV(){if(!le())return;let t=I.reset,e=I.dim,r="\x1B[47;30m",n=[" #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@- "," =@@@- @@@@ "," @@@ @@% "," -@@ @@@@= @@@ @@@ @@@@@#@ @@@@@@@ @@@@@@@ @@@@@@ @@@ @@@ @@@ @@@@@@* %@@ "," @@ @@@ *@ @@@ @@@ @@@ :@@ @@@ @@@ -@@ @@@ @% @@@ @@@ @@@ @@* @@# "," #@@ @@@# @@@ @@@ @@@ :@@ @@@ @@@ -@@ @@@ @@@ @@@ @@@ @@* @@ "," @@- @@@@= @@@ @@@ @@@@@@@ @@@@@@ @@@@@@@ @@@ @@% @@@ @@@ @@@ @@@@@. @@."," #@% .@@@@ @@@ @@@ @@@ @@@ @@@ -@@ @@@ @@% @@@ @@@ @@@ @@* @@ "," @@ @ @@@ @@@ @@@ @@@ @@@ @@@ -@@ @@@ @@% @@@ @@@ @@@ @@* *@@ "," -@@ @@@@= @@@@@@ @@@ @@@@@@@ @@@ -@@ @@@@@@ @@@@@@% @@@@@@. @@@@@@* #@@ "," :@@* @@@ "," %@@@ =@@@. "," :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% "];console.log(""),n.forEach(i=>{let o=i.search(/\S/),s=i.length-[...i].reverse().join("").search(/\S/)-1;if(o===-1)return console.log(" "+i);let a=i.slice(0,o),c=i.slice(o,s+1).split("").map(l=>l===" "?" ":"\u2588").join(""),u=i.slice(s+1);console.log(` ${a}${r}${c}${t}${u}`)}),console.log(` ${e} CLI v${Cr}${t}`),console.log("")}function Ut(t){if(!le())return{stop:()=>{},update:()=>{},log:()=>{}};let e=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],r=0,n=t,i=()=>process.stdout.write("\r\x1B[2K"),o=()=>{process.stdout.write(`\r ${I.cyan}${e[r++%e.length]}${I.reset} ${n}`)},s=setInterval(o,80);return{update:a=>{n=a},log:a=>{i(),console.log(` ${I.dim}\u2502${I.reset} ${a}`),o()},stop:a=>{clearInterval(s),i(),a&&console.log(` ${a}`)}}}function re(t){le()?wE(t):console.log(JSON.stringify(t,null,2))}function Te(t,e){le()?(console.log(` ${I.green}\u2713${I.reset} ${t}`),e&&wE(e,4)):console.log(JSON.stringify({success:!0,message:t,...e&&typeof e=="object"?e:{data:e}}))}function Q(t,e){le()?(console.error(` ${I.red}\u2717${I.reset} ${t}`),e&&wE(e,4)):console.error(JSON.stringify({success:!1,error:t,details:e}))}function dn(t){le()&&console.log(` ${I.dim}${t}${I.reset}`)}function kc(t){le()&&(console.log(`
2179
2179
  ${I.bold}${I.cyan}${t}${I.reset}`),console.log(` ${I.dim}${"\u2500".repeat(t.length)}${I.reset}`))}function $t(t,e,r){if(!le()){console.log(JSON.stringify({success:!0,total:r?.total??t.length,items:t}));return}if(t.length===0){console.log(`
2180
2180
  ${I.dim}0 results${I.reset}
2181
2181
  `);return}let n=e||Object.keys(t[0]),i=qn()?1/0:60,o=n.map(l=>Math.min(i,Math.max(l.length,...t.map(d=>String(d[l]??"").replace(/[\n\r]+/g," ").trim().length))));console.log("");let s=n.map((l,d)=>`${I.bold}${I.cyan}${l.toUpperCase().padEnd(o[d])}${I.reset}`).join(" ");console.log(` ${s}`);let a=o.map(l=>`${I.dim}${"\u2500".repeat(l)}${I.reset}`).join(`${I.dim}\u2500\u2500${I.reset}`);console.log(` ${a}`);for(let l of t){let d=n.map((A,p)=>{let h=String(l[A]??"").replace(/[\n\r]+/g," ").trim();if(h.length>i){let S=`\u2026 (${h.length})`;h=h.slice(0,Math.max(0,i-S.length))+`${I.dim}${S}${I.reset}`}return A==="status"?`${{success:I.green,running:I.yellow,failed:I.red,aborted:I.red,error:I.red,pending:I.dim}[h.toLowerCase()]||""}${h.padEnd(o[p])}${I.reset}`:h.padEnd(o[p])}).join(" ");console.log(` ${d}`)}let c=r?.total??t.length,u=c===t.length?`${t.length} result${t.length===1?"":"s"}`:`${t.length} of ${c} result${c===1?"":"s"}`;console.log(`
@@ -2281,7 +2281,7 @@ ${I.bold}Examples:${I.reset}
2281
2281
 
2282
2282
  ${I.bold}Supported Protocols:${I.reset}
2283
2283
  HTTP/HTTPS, PostgreSQL, MSSQL/SQL Server, Redis, MongoDB, SFTP/FTP/FTPS, SMB
2284
- `).action(async r=>{r.url||(Q("Missing required option --url. Pass the absolute URL or <<systemId_url>> plus the path. Run 'sg skill <protocol>' (e.g. 'sg skill odbc') for URL formats and usage."),process.exit(1)),r.auth!=="auto"&&r.auth!=="none"&&(Q("--auth must be auto or none"),process.exit(1));let{client:n}=e(),i=r.method||"GET",o=await vl(r.file,n),s=r.body;if(s&&Object.keys(o).length>0)try{let l=JSON.parse(s),d=A=>{if(typeof A=="string"&&A.startsWith("file::")){let p=A.slice(6);if(p in o)return o[p];Q(`Unresolved file reference: file::${p}. Available: ${Object.keys(o).join(", ")||"(none)"}`),process.exit(1)}if(Array.isArray(A))return A.map(d);if(A&&typeof A=="object"){let p={};for(let[h,g]of Object.entries(A))p[h]=d(g);return p}return A};l=d(l),s=JSON.stringify(l)}catch(l){if(l.message?.startsWith("Unresolved file reference"))throw l}let a;if(r.headers)try{a=JSON.parse(r.headers)}catch(l){Q(`Invalid --headers JSON: ${l.message}`),process.exit(1)}let c;if(r.timeout!==void 0){let l=Number(r.timeout);(!Number.isInteger(l)||l<1e3)&&(Q("--timeout must be an integer of at least 1000 (milliseconds)"),process.exit(1)),c=l}let u={id:`call_system_${Date.now()}`,failureBehavior:r.continueOnError?"continue":"fail",config:{url:r.url,method:i,headers:a,body:s,systemId:r.systemId}};if(r.systemId||!r.connectionId){let l=(0,zE.getUnscopedCallPlaceholderError)({config:u.config,systemId:r.systemId});l&&(Q(l),process.exit(1))}try{let l=await n.executeStep({step:u,payload:{},credentialId:r.connectionId,systemAuth:r.auth,...c!==void 0?{options:{timeout:c}}:{}}),d=l.data,A=qxe(d)?d:void 0,p=A?A.data:d,h=l.stepFileKeys??A?.stepFileKeys,g=A?.success===!1,S=l.success&&(r.continueOnError||!g);re({success:S,protocol:(0,zE.inferProtocolFromUrl)(r.url),data:p,...l.credential?{credential:l.credential}:{},...l.auth?{auth:l.auth}:{},...h&&h.length>0?{stepFileKeys:h}:{},...l.error||A?.error?{error:l.error||A?.error}:{}}),S||process.exit(1)}catch(l){Q(l.message),process.exit(1)}})}function yJ(t,e){let r=JSON.parse(t);if(!r||typeof r!="object"||Array.isArray(r))throw new Error(`${e} must be a JSON object`);return r}function r0({systemId:t,set:e}){let r=e?.credentialKeys||[];return{systemId:t,...e?{connectionId:e.id,connectionName:e.name}:{},...e?.url?{url:e.url}:{},credentialKeys:r.map(n=>({...n,placeholder:`<<${t}_${n.key}>>`}))}}function Dl(t){let e=typeof t=="string"?t.trim():"";return e||(Q("--system-id must not be blank"),process.exit(1)),e}function Gxe(t){return t.map(e=>e.hasValue?e.key:`${e.key} (empty)`).join(", ")}function EJ(t,e){let r=t.command("connection").description("Manage your connection for a system ID").addHelpText("after",`
2284
+ `).action(async r=>{r.url||(Q("Missing required option --url. Pass the absolute URL or <<systemId_url>> plus the path. Run 'sg skill <protocol>' (e.g. 'sg skill odbc') for URL formats and usage."),process.exit(1)),r.auth!=="auto"&&r.auth!=="none"&&(Q("--auth must be auto or none"),process.exit(1));let{client:n}=e(),i=r.method||"GET",o=await vl(r.file,n),s=r.body;if(s&&Object.keys(o).length>0)try{let l=JSON.parse(s),d=A=>{if(typeof A=="string"&&A.startsWith("file::")){let p=A.slice(6);if(p in o)return o[p];Q(`Unresolved file reference: file::${p}. Available: ${Object.keys(o).join(", ")||"(none)"}`),process.exit(1)}if(Array.isArray(A))return A.map(d);if(A&&typeof A=="object"){let p={};for(let[h,g]of Object.entries(A))p[h]=d(g);return p}return A};l=d(l),s=JSON.stringify(l)}catch(l){if(l.message?.startsWith("Unresolved file reference"))throw l}let a;if(r.headers)try{a=JSON.parse(r.headers)}catch(l){Q(`Invalid --headers JSON: ${l.message}`),process.exit(1)}let c;if(r.timeout!==void 0){let l=Number(r.timeout);(!Number.isInteger(l)||l<1e3)&&(Q("--timeout must be an integer of at least 1000 (milliseconds)"),process.exit(1)),c=l}let u={id:`call_system_${Date.now()}`,failureBehavior:r.continueOnError?"continue":"fail",config:{url:r.url,method:i,headers:a,body:s,systemId:r.systemId}};if(r.systemId||!r.connectionId){let l=(0,zE.getUnscopedCallPlaceholderError)({config:u.config,systemId:r.systemId});l&&(Q(l),process.exit(1))}try{let l=await n.executeStep({step:u,payload:{},connectionId:r.connectionId,systemAuth:r.auth,...c!==void 0?{options:{timeout:c}}:{}}),d=l.data,A=qxe(d)?d:void 0,p=A?A.data:d,h=l.stepFileKeys??A?.stepFileKeys,g=A?.success===!1,S=l.success&&(r.continueOnError||!g);re({success:S,protocol:(0,zE.inferProtocolFromUrl)(r.url),data:p,...l.connection?{connection:l.connection}:{},...l.auth?{auth:l.auth}:{},...h&&h.length>0?{stepFileKeys:h}:{},...l.error||A?.error?{error:l.error||A?.error}:{}}),S||process.exit(1)}catch(l){Q(l.message),process.exit(1)}})}function yJ(t,e){let r=JSON.parse(t);if(!r||typeof r!="object"||Array.isArray(r))throw new Error(`${e} must be a JSON object`);return r}function r0({systemId:t,set:e}){let r=e?.credentialKeys||[];return{systemId:t,...e?{connectionId:e.id,connectionName:e.name}:{},...e?.url?{url:e.url}:{},credentialKeys:r.map(n=>({...n,placeholder:`<<${t}_${n.key}>>`}))}}function Dl(t){let e=typeof t=="string"?t.trim():"";return e||(Q("--system-id must not be blank"),process.exit(1)),e}function Gxe(t){return t.map(e=>e.hasValue?e.key:`${e.key} (empty)`).join(", ")}function EJ(t,e){let r=t.command("connection").description("Manage your connection for a system ID").addHelpText("after",`
2285
2285
  Examples:
2286
2286
  sg system connection list --system-id salesforce
2287
2287
  sg system connection get --system-id salesforce
@@ -2478,7 +2478,7 @@ All Commands:
2478
2478
 
2479
2479
  sg system list List systems (derived from connections and tools)
2480
2480
  sg system find [query] Search systems by keyword
2481
- sg system find --id <id> Get one system with your credential placeholders
2481
+ sg system find --id <id> Get one system with your secret placeholders
2482
2482
  sg system oauth-apps [--system-id <id>] List reusable OAuth apps
2483
2483
  sg system connection get --system-id <id> Get your connection for a system ID
2484
2484
  sg system connection set --system-id <id> Create or update your connection