@superglue/cli 1.1.191 → 1.1.192

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
@@ -107,7 +107,7 @@ attempted value: ${s}
107
107
 
108
108
  `)}function Qb(t){return(t.parts||[]).flatMap(e=>e.type==="tool"&&e.tool?[e.tool]:[])}function GM(t){return Bb(t)?!0:Qb(t).length>0}function _b(t){return t.role==="assistant"&&!t.isStreaming&&!GM(t)}function Zde(t){return t.role==="system"||t.isHidden?!1:!_b(t)}function Kde(t){return t.filter(e=>!_b(e))}function Xde(t){return t.filter(e=>{let r=Bb(e),n=Qb(e).length>0;return(r||n)&&!(e.id==="1"&&!r)})}function eAe(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=bb(t);if(n.length<=e)return n;let i=jM(t,r),o=bb(i);return o.length<=e?o:o.slice(0,e)+"... [truncated]"}function tAe(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)}
109
109
  ... [${i} characters omitted] ...
110
- ${t.slice(t.length-n)}`}function rAe(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 nAe(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 iAe(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 oAe(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 sAe(t){return t.map(e=>YM(e))}function aAe(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}`}N.ALLOWED_PATCH_SYSTEM_FIELDS=["name","url","specificInstructions","icon","credentials","authentication","metadata","templateName","requiredCredentialKeys","documentationFiles","tunnel","tags"];var cAe=new Set(["data","stepResults","toolPayload","rawData","transformedData"]),uAe=8e4;function lAe(t,e=uAe){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(cAe.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,cde.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 dAe(t){if(!t.steps)return[];let e=new Set;for(let r of t.steps)r.config&&(0,DM.isRequestConfig)(r.config)&&r.config.systemId&&e.add(r.config.systemId);return Array.from(e)}function cg(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)cg(n,e,r);return}for(let n of Object.values(t))cg(n,e,r)}}function AAe(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 VM(t,e){let r=[];cg(t,r);let n=`${e}_`,i=new Set;for(let o of r)for(let s of AAe(o)){if(!s.startsWith(n))continue;let a=s.slice(n.length);!a||a==="url"||!N.CREDENTIAL_KEY_PATTERN.test(a)||i.add(a)}return[...i]}var pAe=/^\s*(async\s+)?(\([^)]*\)|[a-zA-Z_$][a-zA-Z0-9_$]*)\s*=>/,fAe=new Set(["sg_auth_email","sg_auth_jwt"]);function hAe({config:t,systemId:e}){let r=[];cg(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)||pAe.test(d)||fAe.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=>N.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 gAe(t){let e={};if(!t.steps)return e;for(let r of t.steps){if(!r.config||!(0,DM.isRequestConfig)(r.config)||!r.config.systemId)continue;let n=VM(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}});var XM=m(gt=>{"use strict";Object.defineProperty(gt,"__esModule",{value:!0});gt.AGENT_CONTEXT_MEMORY_MESSAGE_ID_PREFIX=void 0;gt.applyToolMutation=JM;gt.mutateToolCallInMessages=yAe;gt.buildStreamingAssistantMessage=WM;gt.parseToolOutput=ZM;gt.parseAgentStreamEventLine=IAe;gt.stopActiveTool=KM;gt.appendContentToMessage=vb;gt.updateMessageWithData=lu;gt.findAwaitingConfirmationToolCallIds=CAe;gt.declineAwaitingConfirmationTools=bAe;gt.findAndResumeMessageWithTool=SAe;gt.serializeMessageForPersistence=BAe;gt.isTurnContextBlockMessage=Db;gt.normalizeAgentSessionForkMessages=QAe;gt.normalizeAgentSessionImportMessages=_Ae;gt.createAgentTranscriptState=vAe;gt.applyAgentStreamChunk=DAe;var mAe=yr(),dg=wn();function JM(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 yAe(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:JM(s.tool,r)}));return i&&o?{...n,parts:o}:n})}function WM(t){return{id:t,content:"",role:"assistant",timestamp:new Date,parts:[{type:"content",content:"",id:"content-0"}],isStreaming:!0}}function EAe(){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 ZM(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 IAe(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 KM(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 vb(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 lu(t,e,r){if(t.id!==r.id)return t;switch(e.type){case"content":return vb(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"||typeof e.toolCallId!="string")return t;let i=o=>{if(o.id!==e.toolCallId)return o;let s=ZM(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:KM(i.tool)}:i);return{...t,isStreaming:!1,parts:n,content:""}}default:return t}}function CAe(t){let e=new Set;for(let r of t)for(let n of(0,dg.getMessageToolCalls)(r))n.status==="awaiting_confirmation"&&e.add(n.id);return[...e]}function bAe(t){let e=EAe();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 SAe(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 wAe(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 BAe(t){let{isStreaming:e,tools:r,...n}=t;return JSON.parse((0,dg.safeStringify)({...n,...t.parts?{parts:t.parts.map(i=>i.type==="tool"&&i.tool?{...i,tool:wAe(i.tool)}:i)}:{}},0))}gt.AGENT_CONTEXT_MEMORY_MESSAGE_ID_PREFIX="context-memory-";function Db(t){return mAe.TURN_CONTEXT_BLOCK_TYPES.includes(t.contextType??"")}function QAe(t){return t.filter(e=>e.role!=="system"&&e.contextType!=="memory_notes"&&!Db(e)&&!e.id.startsWith(gt.AGENT_CONTEXT_MEMORY_MESSAGE_ID_PREFIX)).map(e=>({...e,stale:void 0,isStreaming:void 0}))}function _Ae(t){return t.filter(e=>!e.stale&&!e.isStreaming&&e.contextType!=="memory_notes"&&!Db(e)&&!!e.id)}function vAe(t=[],e=null){return{messages:t,assistantMessageId:e,outcome:"streaming"}}function lg(t,e){return(0,dg.getMessageToolCalls)(t).some(r=>r.id===e)}function uu(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=WM(t.assistantMessageId??e.createAssistantMessageId());return{state:{...t,messages:[...t.messages,n],assistantMessageId:n.id},target:n}}function DAe(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,dg.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=uu(t,r);return{...n.state,messages:n.state.messages.map(i=>i.id===n.target.id?vb(i,e.content||""):i)}}case"error":{let n=uu(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=>lg(o,e.toolCall.id))??null,i=n?{state:t,target:n}:uu(t,r);return{...i.state,messages:i.state.messages.map(o=>lu(o,e,i.target))}}case"run_command_effect":{let n=e.toolCallId;if(!n)return t;let i=t.messages.find(o=>lg(o,n));return i?{...t,messages:t.messages.map(o=>lu(o,e,i))}:t}case"tool_call_input":{if(!e.toolCall)return t;let n=t.messages.find(i=>lg(i,e.toolCall.id));return n?{...t,messages:t.messages.map(i=>lu(i,e,n))}:t}case"tool_call_complete":{if(!e.toolCall)return t;let n=t.messages.find(o=>lg(o,e.toolCall.id)),i=n?{state:t,target:n}:uu(t,r);return{...i.state,messages:i.state.messages.map(o=>lu(o,e,i.target))}}case"paused":{let n=uu(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=uu(t,r);return{...n.state,outcome:t.outcome==="failed"?"failed":"completed",messages:n.state.messages.map(i=>lu(i,e,n.target))}}default:return t}}});var Tb=m(Lo=>{"use strict";Object.defineProperty(Lo,"__esModule",{value:!0});Lo.PROJECT_LIMITS=Lo.PROJECT_TASK_STATUSES=Lo.PROJECT_RESOURCE_TYPES=void 0;Lo.projectResourceKey=TAe;Lo.PROJECT_RESOURCE_TYPES=["system","playbook","artifact","file","tool"];Lo.PROJECT_TASK_STATUSES=["not_started","in_progress","waiting","done"];Lo.PROJECT_LIMITS={name:80,description:500,taskName:120,taskDescription:1e4,taskResources:100};function TAe(t){return`${t.type}:${t.id}`}});var Ag=m(zr=>{"use strict";Object.defineProperty(zr,"__esModule",{value:!0});zr.RESOURCE_KINDS=zr.RESOURCE_DEFINITIONS=void 0;zr.isResourceKind=RAe;zr.getResourceDefinition=kAe;zr.getResourceAppPath=NAe;zr.RESOURCE_DEFINITIONS={tool:{label:"Tool",pluralLabel:"Tools",collectionKey:"tools",appPath:"/tools",hasDetailPage:!0,memberDefaultPermission:"editor",pickerDefaultPermission:"editor"},system:{label:"System",pluralLabel:"Systems",collectionKey:"systems",appPath:"/systems",hasDetailPage:!0,memberDefaultPermission:"editor",pickerDefaultPermission:"editor"},credential:{label:"Credential",pluralLabel:"Credentials",collectionKey:"credentials",appPath:"/credentials",hasDetailPage:!1,pickerDefaultPermission:"viewer"},playbook:{label:"Playbook",pluralLabel:"Playbooks",collectionKey:"playbooks",appPath:"/playbooks",hasDetailPage:!0,pickerDefaultPermission:"editor"},artifact:{label:"Artifact",pluralLabel:"Artifacts",collectionKey:"artifacts",appPath:"/artifacts",hasDetailPage:!0,pickerDefaultPermission:"editor"},file:{label:"File",pluralLabel:"Files",collectionKey:"files",appPath:"/files",hasDetailPage:!1,pickerDefaultPermission:"viewer"},project:{label:"Project",pluralLabel:"Projects",collectionKey:"projects",appPath:"/projects",hasDetailPage:!0,pickerDefaultPermission:"viewer"}};zr.RESOURCE_KINDS=Object.keys(zr.RESOURCE_DEFINITIONS);function RAe(t){return typeof t=="string"&&Object.prototype.hasOwnProperty.call(zr.RESOURCE_DEFINITIONS,t)}function kAe(t){return zr.RESOURCE_DEFINITIONS[t]}function NAe(t,e){let r=zr.RESOURCE_DEFINITIONS[t];return r.hasDetailPage?`${r.appPath}/${encodeURIComponent(e)}`:r.appPath}});var nx=m(ka=>{"use strict";Object.defineProperty(ka,"__esModule",{value:!0});ka.SDK_ERROR_DETAILS_SCHEMA=ka.SDK_OUTPUT_CONTRACTS=void 0;ka.toSdkJsonSchema=xAe;var y=pa(),OAe=Tb(),UAe=Ag(),MAe=yr();function xAe({schema:t}){return y.z.toJSONSchema(t,{target:"draft-7",io:"output",unrepresentable:"any"})}var ex=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()}),tx=y.z.looseObject({vfsPath:y.z.string(),storedBytes:y.z.number(),originalOutputBytes:y.z.number(),storageTruncated:y.z.boolean()}),rx=y.z.object({action:y.z.enum(["approve","reject","oauth_success","oauth_failure"]),source:y.z.enum(["user","automatic"])});function Bn(t){return y.z.looseObject({toolCallId:y.z.string(),toolName:y.z.string(),outcome:y.z.literal("success"),confirmation:rx.optional(),data:t})}var Rb={http:ex.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()},LAe=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."),...Rb}),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."),...Rb}),y.z.looseObject({protocol:y.z.enum(MAe.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."),...Rb})]),PAe=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.")})]),FAe=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.")}),$Ae=y.z.looseObject({stepId:y.z.string(),success:y.z.boolean(),data:y.z.unknown().optional(),error:y.z.string().nullable().optional(),http:ex.optional(),stepFileKeys:y.z.array(y.z.string()).optional()}),jAe=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($Ae),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:tx.optional()}),zAe=Bn(y.z.looseObject({resource:y.z.looseObject({id:y.z.string(),name:y.z.string().optional(),version:y.z.union([y.z.number(),y.z.string()]).optional()}),created:y.z.boolean(),projectId:y.z.string().optional(),addedFiles:y.z.array(y.z.looseObject({id:y.z.string(),fileName: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(OAe.PROJECT_RESOURCE_TYPES),id:y.z.string()}),error:y.z.string().optional()}).optional()}));ka.SDK_OUTPUT_CONTRACTS={assignSessionToProject:{name:"SuperglueSessionProjectResult",schema:Bn(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:LAe,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:PAe,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."},systemFetch:{name:"SuperglueSystemFetchResult",schema:FAe,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:jAe,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:zAe,description:"Returns saved resource identity, creation status, and available project attribution or added files. Throws SuperglueError on failure."},installBundle:{name:"SuperglueBundleInstallResult",schema:Bn(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, tool, MCP server, and playbook identities, the secret names the user must supply, and whether the user has a complete credential. Throws SuperglueError on failure."},stopBackgroundJob:{name:"SuperglueStopBackgroundJobResult",schema:Bn(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:Bn(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:Bn(y.z.looseObject({resource:y.z.looseObject({kind:y.z.enum(UAe.RESOURCE_KINDS),id:y.z.string()})})),description:"Returns the shared resource identity. Throws SuperglueError on failure."},showVisual:{name:"SuperglueShowVisualResult",schema:Bn(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:Bn(y.z.looseObject({actionCount:y.z.number()})),description:"Returns the notification action count. Throws SuperglueError on failure."},writeOrgSettings:{name:"SuperglueOrgSettingsResult",schema:Bn(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:Bn(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:Bn(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:Bn(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."},previewArtifact:{name:"SuperglueArtifactPreviewResult",schema:y.z.looseObject({draftId:y.z.string(),bytes:y.z.number()}),description:"Returns the artifact draft identity and byte count. Throws SuperglueError on failure."}};var qAe=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()});ka.SDK_ERROR_DETAILS_SCHEMA=y.z.discriminatedUnion("kind",[y.z.looseObject({kind:y.z.literal("tool_result"),resultMetadata:tx.optional(),result:y.z.looseObject({toolCallId:y.z.string(),toolName:y.z.string(),outcome:y.z.enum(["success","failure","rejected","aborted"]),confirmation:rx.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(qAe),output:y.z.unknown().optional()})])});var hx=m(be=>{"use strict";Object.defineProperty(be,"__esModule",{value:!0});be.SERVER_OWNED_SESSION_RESOURCE_KINDS=be.AgentRequestValidationError=be.AGENT_TOOL_CONTINUATION_ACTION_BY_CONFIRMATION_STATE=be.AGENT_TOOL_CONTINUATION_ACTIONS=be.AGENT_IDENTIFIER_PATTERN=be.AGENT_REQUEST_LIMITS=void 0;be.validateAgentRequestPayload=lx;be.validateResourceBinding=dx;be.validateClientResourceBinding=Ax;be.validateAgentSessionIdentity=px;be.validateAgentSessionTarget=fx;be.validateAgentRequestSubmission=WAe;be.isAgentMessagePayload=ZAe;be.isAgentToolContinuationPayload=KAe;var Po=yr();be.AGENT_REQUEST_LIMITS={messageContentChars:5e4,identifierChars:256,attachedFiles:20,toolContinuations:20,continuationInputChars:1e5,frontendDraftsChars:2e6,accessRulesContextChars:2e6,pendingMessagesPerSession:10};be.AGENT_IDENTIFIER_PATTERN=/^[A-Za-z0-9._-]+$/;be.AGENT_TOOL_CONTINUATION_ACTIONS=["approve","reject","oauth_success","oauth_failure"];be.AGENT_TOOL_CONTINUATION_ACTION_BY_CONFIRMATION_STATE={[Po.ConfirmationAction.CONFIRMED]:"approve",[Po.ConfirmationAction.DECLINED]:"reject",[Po.ConfirmationAction.OAUTH_SUCCESS]:"oauth_success",[Po.ConfirmationAction.OAUTH_FAILURE]:"oauth_failure"};var pg=class extends Error{constructor(e){super(e),this.name="AgentRequestValidationError"}};be.AgentRequestValidationError=pg;function Ze(t){throw new pg(t)}function co(t,e){return(!t||typeof t!="object"||Array.isArray(t))&&Ze(`${e} must be an object`),t}function Na(t,e){(typeof t!="string"||!t.trim())&&Ze(`${e} must be a non-empty string`);let r=t.trim();return r.length>be.AGENT_REQUEST_LIMITS.identifierChars&&Ze(`${e} exceeds ${be.AGENT_REQUEST_LIMITS.identifierChars} characters`),be.AGENT_IDENTIFIER_PATTERN.test(r)||Ze(`${e} may only contain letters, numbers, dots, underscores, and hyphens`),r}function HAe(t,e){return typeof t!="boolean"&&Ze(`${e} must be a boolean`),t}function kb(t,e){try{return JSON.stringify(t).length}catch{return Ze(`${e} must be JSON-serializable`)}}function GAe(t,e){if(t!==void 0)return Array.isArray(t)||Ze(`${e} must be an array`),t.length>be.AGENT_REQUEST_LIMITS.attachedFiles&&Ze(`${e} exceeds ${be.AGENT_REQUEST_LIMITS.attachedFiles} entries`),t.map((r,n)=>{let i=co(r,`${e}[${n}]`);return{...i,key:Na(i.key,`${e}[${n}].key`)}})}function ix({value:t,label:e,requireHidden:r}){let n=co(t,e),i=Na(n.id,`${e}.id`);typeof n.content!="string"&&Ze(`${e}.content must be a string`);let o=n.content;o.length>be.AGENT_REQUEST_LIMITS.messageContentChars&&Ze(`${e}.content exceeds ${be.AGENT_REQUEST_LIMITS.messageContentChars} characters`);let s=HAe(n.isHidden,`${e}.isHidden`);r&&!s&&Ze(`${e}.isHidden must be true`);let a=GAe(n.attachedFiles,`${e}.attachedFiles`);return!o.trim()&&!a?.length&&Ze(`${e}.content may only be empty when an attachment is present`),{id:i,content:o,isHidden:s,...a?{attachedFiles:a}:{}}}function sx(t){if(t===void 0)return;let e=co(t,"frontendDrafts");return kb(e,"frontendDrafts")>be.AGENT_REQUEST_LIMITS.frontendDraftsChars&&Ze(`frontendDrafts exceeds ${be.AGENT_REQUEST_LIMITS.frontendDraftsChars} characters`),e}function ax(t){if(t===void 0)return;let e=co(t,"accessRulesContext");return kb(e,"accessRulesContext")>be.AGENT_REQUEST_LIMITS.accessRulesContextChars&&Ze(`accessRulesContext exceeds ${be.AGENT_REQUEST_LIMITS.accessRulesContextChars} characters`),e}function cx(t){if(t!==void 0)return(typeof t!="string"||!Po.AGENT_APPROVAL_MODES.includes(t))&&Ze(`request.approvalMode must be one of: ${Po.AGENT_APPROVAL_MODES.join(", ")}`),t}function ux(t,e){let r=co(t,e),n=Na(r.toolCallId,`${e}.toolCallId`);return(typeof r.action!="string"||!be.AGENT_TOOL_CONTINUATION_ACTIONS.includes(r.action))&&Ze(`${e}.action must be one of: ${be.AGENT_TOOL_CONTINUATION_ACTIONS.join(", ")}`),r.input!==void 0&&kb(r.input,`${e}.input`)>be.AGENT_REQUEST_LIMITS.continuationInputChars&&Ze(`${e}.input exceeds ${be.AGENT_REQUEST_LIMITS.continuationInputChars} characters`),{toolCallId:n,action:r.action,...r.input!==void 0?{input:r.input}:{}}}function YAe(t){if(t===void 0)return;(!Array.isArray(t)||t.length===0)&&Ze("request.toolContinuations must be a non-empty array"),t.length>be.AGENT_REQUEST_LIMITS.toolContinuations&&Ze(`request.toolContinuations exceeds ${be.AGENT_REQUEST_LIMITS.toolContinuations} entries`);let e=t.map((r,n)=>ux(r,`request.toolContinuations[${n}]`));return new Set(e.map(({toolCallId:r})=>r)).size!==e.length&&Ze("request.toolContinuations must not contain duplicate toolCallId values"),e}function ox(t,e){if(t===void 0)return;(typeof t!="string"||!t.trim())&&Ze(`${e} must be a non-empty string`);let r=t.trim();return r.length>be.AGENT_REQUEST_LIMITS.messageContentChars&&Ze(`${e} exceeds ${be.AGENT_REQUEST_LIMITS.messageContentChars} characters`),r}function VAe(t){let e=ix({value:t.message,label:"request.message"}),r=ox(t.title,"request.title"),n=ox(t.titleInput,"request.titleInput"),i=t.hiddenSteeringMessage===void 0?void 0:ix({value:t.hiddenSteeringMessage,label:"request.hiddenSteeringMessage",requireHidden:!0});i&&i.id===e.id&&Ze("request.hiddenSteeringMessage.id must differ from request.message.id");let o=YAe(t.toolContinuations),s=cx(t.approvalMode),a=sx(t.frontendDrafts),c=ax(t.accessRulesContext);return{kind:"message",message:e,...i?{hiddenSteeringMessage:i}:{},...r?{title:r}:{},...n?{titleInput:n}:{},...o?{toolContinuations:o}:{},...s?{approvalMode:s}:{},...a?{frontendDrafts:a}:{},...c?{accessRulesContext:c}:{}}}function JAe(t){let e=ux(t,"request"),r=cx(t.approvalMode),n=sx(t.frontendDrafts),i=ax(t.accessRulesContext);return{kind:"tool_continuation",...e,...r?{approvalMode:r}:{},...n?{frontendDrafts:n}:{},...i?{accessRulesContext:i}:{}}}function lx(t){let e=co(t,"request");return e.kind==="message"?VAe(e):e.kind==="tool_continuation"?JAe(e):Ze('request.kind must be "message" or "tool_continuation"')}function dx(t,e){let r=co(t,e);return(typeof r.kind!="string"||!Po.AGENT_SESSION_RESOURCE_KINDS.includes(r.kind))&&Ze(`${e}.kind must be one of: ${Po.AGENT_SESSION_RESOURCE_KINDS.join(", ")}`),{kind:r.kind,id:Na(r.id,`${e}.id`)}}be.SERVER_OWNED_SESSION_RESOURCE_KINDS=["briefing"];function Ax(t,e){let r=dx(t,e);return be.SERVER_OWNED_SESSION_RESOURCE_KINDS.includes(r.kind)&&Ze(`${e}.kind "${r.kind}" is assigned by the server`),r}function px(t,e="session.createIfMissing"){let r=co(t,e),n=r.projectId===void 0?void 0:Na(r.projectId,`${e}.projectId`),i=r.taskId===void 0?void 0:Na(r.taskId,`${e}.taskId`);i&&!n&&Ze(`${e}.taskId requires ${e}.projectId`);let o=Object.values(Po.AgentType);(typeof r.agentId!="string"||!o.includes(r.agentId))&&Ze(`${e}.agentId must be one of: ${o.join(", ")}`);let s=r.resourceBinding===void 0?void 0:Ax(r.resourceBinding,`${e}.resourceBinding`);return{agentId:r.agentId,...n?{projectId:n}:{},...i?{taskId:i}:{},...s?{resourceBinding:s}:{}}}function fx(t){let e=co(t,"session"),r=e.createIfMissing===void 0?void 0:px(e.createIfMissing);return{id:Na(e.id,"session.id"),...r?{createIfMissing:r}:{}}}function WAe(t){let e=co(t,"body");return{session:fx(e.session),request:lx(e.request)}}function ZAe(t){return t.kind==="message"}function KAe(t){return t.kind==="tool_continuation"}});var mx=m(He=>{"use strict";Object.defineProperty(He,"__esModule",{value:!0});He.ARTIFACT_EXPORT_FORMATS=He.ARTIFACT_RESPONSE_RESERVED_FIELD_NAMES=He.ARTIFACT_RESPONSE_PATCH_DEBOUNCE_MS=He.MAX_SPREADSHEET_ARTIFACT_BYTES=He.MAX_HTML_ARTIFACT_IMAGE_BYTES=He.MAX_HTML_ARTIFACT_BYTES=He.MAX_SPREADSHEET_CELL_TEXT_LENGTH=He.MAX_SPREADSHEET_SHEET_NAME_LENGTH=He.MAX_SPREADSHEET_GRID_CELLS=He.MAX_SPREADSHEET_SHEETS=He.SPREADSHEET_CELL_TYPES=void 0;He.isValidSpreadsheetCell=tpe;He.isArtifactExportFormat=rpe;He.isArtifactExportFormatForKind=npe;var gx=pa();He.SPREADSHEET_CELL_TYPES=["text","integer","number","percent","currency","boolean","date","datetime"];He.MAX_SPREADSHEET_SHEETS=20;He.MAX_SPREADSHEET_GRID_CELLS=1e6;He.MAX_SPREADSHEET_SHEET_NAME_LENGTH=31;He.MAX_SPREADSHEET_CELL_TEXT_LENGTH=32767;var XAe=gx.z.iso.date(),epe=gx.z.iso.datetime({offset:!0});function tpe(t,e){return t===null?!0:e==="text"?typeof t=="string"&&t.length<=He.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"?epe:XAe).safeParse(t).success}He.MAX_HTML_ARTIFACT_BYTES=1024*1024;He.MAX_HTML_ARTIFACT_IMAGE_BYTES=12*1024*1024;He.MAX_SPREADSHEET_ARTIFACT_BYTES=10*1024*1024;He.ARTIFACT_RESPONSE_PATCH_DEBOUNCE_MS=300;He.ARTIFACT_RESPONSE_RESERVED_FIELD_NAMES=new Set(["__proto__","constructor","prototype"]);He.ARTIFACT_EXPORT_FORMATS=["html","pdf","docx","xlsx","pptx"];function rpe(t){return He.ARTIFACT_EXPORT_FORMATS.some(e=>e===t)}function npe(t,e,r=!1){return t==="spreadsheet"?e==="xlsx":r?e==="html"||e==="pdf"||e==="pptx":e!=="pptx"}});var bx=m($e=>{"use strict";Object.defineProperty($e,"__esModule",{value:!0});$e.API_KEY_ACTION_LABELS=$e.API_KEY_SURFACE_LABELS=$e.API_KEY_SCOPES=$e.API_KEY_SURFACE_ACTIONS=$e.API_KEY_ACTIONS=$e.API_KEY_SURFACES=void 0;$e.getApiKeySurface=Ex;$e.getApiKeyAction=Ix;$e.getApiKeySurfaceActions=Nb;$e.parseApiKeyScopes=Cx;$e.validateApiKeyScopesInput=ape;$e.isApiKeyScopeAllowed=cpe;$e.formatApiKeyScopes=upe;$e.API_KEY_SURFACES=["api","mcp"];$e.API_KEY_ACTIONS=["read","write","execute"];$e.API_KEY_SURFACE_ACTIONS={api:$e.API_KEY_ACTIONS,mcp:["execute"]};$e.API_KEY_SCOPES=$e.API_KEY_SURFACES.flatMap(t=>$e.API_KEY_SURFACE_ACTIONS[t].map(e=>`${t}:${e}`));$e.API_KEY_SURFACE_LABELS={api:"API & CLI",mcp:"MCP"};$e.API_KEY_ACTION_LABELS={read:"Read",write:"Write",execute:"Execute"};var yx=new Set($e.API_KEY_SCOPES),ipe={"/v1/tools":["read"],"/v1/tools/:toolId/run":["execute"],"/v1/authenticate":["write"],"/v1/memory-notes":["read","write"]},ope=new Set(["/v1/api-keys","/v1/api-keys/:id","/v1/api-keys/:id/reveal"]),spe=new Set(["/v1/me"]);function Ex(t){let e=t.split("?")[0];return e==="/mcp"||e.startsWith("/mcp/")?"mcp":"api"}function Ix(t){return t==="read"?"read":t==="execute"?"execute":"write"}function Nb(t,e){return $e.API_KEY_SURFACE_ACTIONS[e].filter(r=>(t||[]).includes(`${e}:${r}`))}function Cx(t){if(!Array.isArray(t))return null;let e=[...new Set(t.filter(r=>yx.has(r)))];return e.length>0?e:null}function ape(t){if(t==null)return{scopes:null};let e=`Valid scopes: ${$e.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=>!yx.has(n));return r.length>0?{error:`Unknown API key scope(s): ${r.map(String).join(", ")}. ${e}`}:{scopes:Cx(t)}}function cpe({scopes:t,path:e,type:r}){if(!t||t.length===0)return!0;let n=e.split("?")[0];if(ope.has(n))return!1;if(spe.has(n))return!0;let i=Ix(r),o=Ex(n);return o==="api"&&ipe[n]?.some(s=>s===r)&&Nb(t,"mcp").length>0?!0:t.includes(`${o}:${i}`)}function upe(t){return!t||t.length===0?"Full access":$e.API_KEY_SURFACES.map(e=>({surface:e,actions:Nb(t,e)})).filter(e=>e.actions.length>0).map(e=>$e.API_KEY_SURFACE_ACTIONS[e.surface].length===1?$e.API_KEY_SURFACE_LABELS[e.surface]:`${$e.API_KEY_SURFACE_LABELS[e.surface]} ${e.actions.join("/")}`).join(", ")}});var Sx=m(Ob=>{"use strict";Object.defineProperty(Ob,"__esModule",{value:!0});Ob.isValidEmail=lpe;function lpe(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 Bx=m(mt=>{"use strict";Object.defineProperty(mt,"__esModule",{value:!0});mt.GATEWAY_UNINSTALL_COMMANDS=mt.GATEWAY_API_KEY_NAME_PREFIX=mt.GATEWAY_TARGET_NAME_PATTERN=mt.GATEWAY_SETUP_GUIDE_URL=mt.GATEWAY_DOWNLOAD_BASE_URL=mt.GATEWAY_INSTALL_TOKEN_PREFIX=void 0;mt.getGatewayServerUrl=wx;mt.buildGatewayInstallToken=Ape;mt.buildGatewayInstallCommand=ppe;mt.getGatewayApiKeyName=fpe;mt.GATEWAY_INSTALL_TOKEN_PREFIX="sgi1.";mt.GATEWAY_DOWNLOAD_BASE_URL="https://downloads.superglue.cloud";mt.GATEWAY_SETUP_GUIDE_URL="https://superglue.ai/docs/guides/secure-gateway/";mt.GATEWAY_TARGET_NAME_PATTERN=/^[a-z0-9]([a-z0-9_-]{0,61}[a-z0-9])?$/;function wx(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 dpe(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 Ape(t){let e={v:1,serverUrl:wx(t.apiEndpoint),tunnelId:t.tunnelId,apiKey:t.apiKey,targets:t.targets,enableScriptRunner:t.enableScriptRunner};return mt.GATEWAY_INSTALL_TOKEN_PREFIX+dpe(JSON.stringify(e))}function ppe(t,e){return t==="windows"?['$ErrorActionPreference = "Stop"',"[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072",'$ProgressPreference = "SilentlyContinue"','$gateway = "$env:TEMP\\superglue-gateway.exe"',"Remove-Item $gateway -Force -ErrorAction SilentlyContinue",`Invoke-WebRequest -UseBasicParsing "${mt.GATEWAY_DOWNLOAD_BASE_URL}/superglue-gateway-windows.exe" -OutFile $gateway`,`"${e}" | & $gateway install -`].join("; "):["d=$(mktemp -d)",`u="${mt.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(" && ")}mt.GATEWAY_API_KEY_NAME_PREFIX="Gateway: ";function fpe(t){return mt.GATEWAY_API_KEY_NAME_PREFIX+t}mt.GATEWAY_UNINSTALL_COMMANDS={windows:'& "C:\\Program Files\\superglue Gateway\\superglue-gateway.exe" uninstall',linux:"sudo /usr/local/bin/superglue-gateway uninstall"}});var Ld=m(fe=>{"use strict";Object.defineProperty(fe,"__esModule",{value:!0});fe.OAUTH_CONFIG_CREDENTIAL_KEYS=void 0;fe.hasMeaningfulValue=yt;fe.stringValue=Gt;fe.validateOAuthConnection=Bpe;fe.formatOAuthConnectionDisabledReason=_pe;fe.objectValue=$o;fe.parseScopes=Md;fe.normalizeGrantType=xd;fe.normalizeOAuthClientMode=xb;fe.normalizeSystemAuthentication=Xt;fe.resolveOAuthClientMode=Dpe;fe.flattenSystemAuthentication=Tx;fe.maskedFlatSystemAuthentication=Tpe;fe.isMaskedSecretValue=Rx;fe.pickAgentAuthInputFields=Rpe;fe.maskSystemAuthenticationForResponse=kpe;fe.restoreMaskedClientSecret=Npe;fe.mapAgentAuthInput=kx;fe.mergeAgentAuthInput=qpe;fe.getAuthenticationConfigCredentialKeys=Nx;fe.buildAuthenticationEditorModel=Hpe;fe.getCredentialRequirements=Gpe;fe.isCredentialRequirementSatisfied=Ox;fe.hasUnsatisfiedCredentialRequirements=Ype;fe.updateAuthenticationEditorField=Vpe;fe.validateOAuthAuthenticationConfigPlacement=Ux;fe.authenticationToLegacyCredentials=Mx;fe.isRuntimeCredentialMetadataKey=Jpe;fe.resolveCredentialAuthentication=Wpe;fe.getCredentialAuthenticationStorageError=Zpe;fe.buildRuntimeCredentialsFromAuthentication=Kpe;fe.resolveOAuthConfigFromAuthentication=Xpe;fe.toCredentialInputValue=Lb;fe.getCredentialEntries=efe;fe.getCredentialInputValues=tfe;fe.getCredentialDisplayHiddenKeys=rfe;fe.hasOAuthTokenCredentials=nfe;fe.getOAuthExpiryText=ife;fe.hasRuntimeCredentialValues=ofe;fe.validateCredentialObjectKeys=xx;fe.validateCredentialKeyList=Lx;fe.normalizeAskForUserInputs=Px;fe.validateSystemInputCollection=sfe;fe.mapOAuthMissingFieldsForAgent=afe;fe.validateOAuthAuthenticationAndCredentialInputs=cfe;var vt=wn(),hpe=su();fe.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 fg=["host","port","database","path","homeDirectory"],Dx=["type","oauthClientMode","grantType","authUrl","tokenUrl","scopes","clientId","clientSecret","tokenAuthMethod","tokenContentType","usePKCE","extraHeaders","extraBodyParams","protocol",...fg],gpe=new Set(Dx),mpe="type, oauthClientMode, grantType, authUrl, tokenUrl, scopes, clientId, clientSecret, tokenAuthMethod, tokenContentType, usePKCE, extraHeaders, extraBodyParams, protocol, host, port, database, path, homeDirectory",ype=["grantType","authUrl","tokenUrl","scopes","clientId","clientSecret"],Epe={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"]},Ud=["tokenAuthMethod","tokenContentType","usePKCE","extraHeaders","extraBodyParams"],Ipe=new Set(ype),Cpe=new Set(["access_token","accessToken","refresh_token","refreshToken","expires_at","expiresAt","expires_in","expiresIn","expiry","token_type","tokenType"]),bpe=["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"],Qx=new Map(bpe.map((t,e)=>[(0,vt.normalizeCredentialKey)(t),e]));function Oa(t){return Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0))}function Ub({config:t,key:e,value:r}){let n={...t||{}};return yt(r)?n[e]=r:delete n[e],Object.keys(n).length>0?n:void 0}function yt(t){return(0,vt.hasCredentialValue)(t)}function Gt(t){if(yt(t))return typeof t=="string"?t:String(t)}var Spe={"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 Fo(...t){return t.find(e=>yt(e))}function wpe(t){return t===!0||t==="true"}function Bpe(t){let e=t||{},r=Gt(Fo(e.grant_type,e.grantType)),n=r==="client_credentials"?"client_credentials":"authorization_code",i=r&&r!=="authorization_code"&&r!=="client_credentials",o=Fo(e.client_id,e.clientId),s=Fo(e.client_secret,e.clientSecret),a=Fo(e.auth_url,e.authUrl),c=Fo(e.token_url,e.tokenUrl,e.token_uri),u=Fo(e.oauth_cert,e.oauthCert),l=Fo(e.oauth_key,e.oauthKey),d=yt(u)&&yt(l)||e.hasServerSideCertificateCredentials===!0,A=e.hasServerSideClientSecret===!0,p=yt(s)||A,h=wpe(Fo(e.usePKCE,e.usePkce)),g=[];return i&&g.push("grant_type authorization_code or client_credentials"),yt(o)||g.push("client_id"),yt(c)||g.push("token_url"),n==="client_credentials"?!p&&!d&&g.push("client_secret or oauth_cert + oauth_key"):(yt(a)||g.push("auth_url"),!p&&!h&&g.push("client_secret or usePKCE")),{grantType:n,hasAccessToken:yt(Fo(e.access_token,e.accessToken)),hasCertificateCredentials:d,isReadyToConnect:g.length===0,missingFields:g,usePKCE:h}}function Qpe(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 _pe(t){if(!t||t.isReadyToConnect)return null;let e=t.missingFields.map(r=>Spe[r]||r);return`OAuth connection is disabled because ${Qpe(e)} ${e.length===1?"is":"are"} missing.`}function $o(t){if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function uo(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function Md(t){if(yt(t)){if(Array.isArray(t))return t.map(String).filter(Boolean);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 xd(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 xb(t){return t==="managed"||t==="dynamic"||t==="custom"?t:void 0}function vpe(t){let e=Object.entries(t).filter(([r])=>!Ipe.has(r));return e.length>0?Object.fromEntries(e):void 0}function du(t,e,r){for(let i of Epe[r])if(yt(t[i]))return t[i];let n=$o(t.client);return r==="clientId"&&yt(n?.id)?n.id:r==="clientSecret"&&yt(n?.secret)?n.secret:e[r]}function Xt(t){if(!t)return;let e=t;if(e.type==="oauth2"){let r=$o(e.config)||{},n=vpe(r)||{};return Oa({type:"oauth2",oauthClientMode:xb(e.oauthClientMode),grantType:xd(du(e,r,"grantType")),authUrl:Gt(du(e,r,"authUrl")),tokenUrl:Gt(du(e,r,"tokenUrl")),scopes:Md(du(e,r,"scopes")),clientId:Gt(du(e,r,"clientId")),clientSecret:Gt(du(e,r,"clientSecret")),config:Object.keys(n).length>0?n:void 0})}return e.type==="connection_string"?Oa({type:"connection_string",protocol:e.protocol,config:$o(e.config??e.components)}):e.type==="api_key"||e.type==="basic_auth"||e.type==="none"?Oa({type:e.type,config:$o(e.config)}):{type:"none"}}function Dpe({authentication:t,templateManaged:e,templateRegistrationUrl:r}){let n=Xt(t);if(n?.type!=="oauth2")return"custom";let i=n.oauthClientMode;return i?i==="managed"&&!e?"custom":i:r?"dynamic":e&&!n.clientSecret?"managed":"custom"}function Tx(t){let e=Xt(t);if(!e)return;let{config:r,scopes:n,...i}=e,o={};return r&&typeof r=="object"&&Object.assign(o,r),Object.assign(o,i),Array.isArray(n)?o.scopes=n.join(" "):n!==void 0&&(o.scopes=n),o}function Mb(t,e=""){return t==null?t:Array.isArray(t)?t.map(r=>Mb(r)):typeof t=="object"?Object.fromEntries(Object.entries(t).map(([r,n])=>[r,Mb(n,r)])):e&&(0,vt.isSensitiveCredentialKey)(e)?(0,vt.maskCredentialValue)(e,t):t}function Tpe(t){let e=Tx(t);if(e)return Mb(e)}function Rx(t){return(0,vt.isMaskedValue)(t)||(0,vt.isFullyMaskedCredentialValue)(t)}function Rpe(t){let e=$o(t);if(!e)return;let r={};for(let n of Dx){if(!uo(e,n))continue;let i=e[n];i!==void 0&&(r[n]=i)}return r}function kpe(t){return!t||t.type!=="oauth2"||!yt(t.clientSecret)?t:{...t,clientSecret:vt.FULLY_MASKED_CREDENTIAL_VALUE}}function Npe({incoming:t,existing:e}){if(!t||t.type!=="oauth2"||!Rx(t.clientSecret))return t;let r=e?.type==="oauth2"?e.clientSecret:void 0;return{...t,clientSecret:r}}function Ope(t){if(t==="none"||t==="api_key"||t==="basic_auth"||t==="oauth2"||t==="connection_string")return t}function Upe(t){return Object.entries(t||{})}function Mpe(t){let e=fg.flatMap(r=>{if(!uo(t,r))return[];let n=t[r];return yt(n)?[[r,n]]:[]});return e.length>0?Object.fromEntries(e):void 0}function xpe(t){return fg.filter(e=>uo(t,e))}function Lpe(t){let e=fg.flatMap(r=>uo(t,r)?[[r,t[r]]]:[]);return e.length>0?Object.fromEntries(e):void 0}function Ppe(t){let e=new Set(["oauthClientMode","grantType","authUrl","tokenUrl","scopes","clientId","clientSecret",...Ud]);return Object.keys(t).filter(r=>e.has(r))}function kx(t){if(t==null)return{};let e=$o(t);if(!e)return{error:"auth must be an object."};let r=Ope(e.type);if(!r)return{error:"auth.type is required."};let n=Object.keys(e).filter(a=>!gpe.has(a));if(n.length>0)return{error:`Unknown auth field(s): ${n.join(", ")}. Accepted: ${mpe}.`};let i=xpe(e);if(r!=="connection_string"&&i.length>0)return{error:`Connection auth field(s) require auth.type 'connection_string': ${i.join(", ")}.`};let o=Ppe(e);if(r!=="oauth2"&&o.length>0)return{error:`OAuth auth field(s) require auth.type 'oauth2': ${o.join(", ")}.`};if(r!=="oauth2"){let a=Mpe(e);return{authentication:Oa({type:r,protocol:r==="connection_string"?e.protocol:void 0,config:a})}}let s={...Object.fromEntries(Ud.flatMap(a=>{if(!uo(e,a))return[];let c=e[a];return yt(c)?[[a,c]]:[]}))};return{authentication:Oa({type:"oauth2",oauthClientMode:xb(e.oauthClientMode),grantType:xd(e.grantType),authUrl:Gt(e.authUrl),tokenUrl:Gt(e.tokenUrl),scopes:Md(e.scopes),clientId:Gt(e.clientId),clientSecret:Gt(e.clientSecret),config:Object.keys(s).length>0?s:void 0})}}function Ua(t){return t===""||t===null||t===void 0}function Od(t,e,r,n){if(uo(e,r)){if(Ua(e[r])){delete t[n];return}t[n]=Gt(e[r])}}function Fpe(t,e){if(uo(e,"scopes")){if(Ua(e.scopes)){delete t.scopes;return}t.scopes=Md(e.scopes)}}function $pe(t,e){if(uo(e,"grantType")){if(Ua(e.grantType)){delete t.grantType;return}t.grantType=xd(e.grantType)}}function jpe(t,e,r){if(uo(e,r)){if(Ua(e[r])){delete t[r];return}t[r]=e[r]}}function zpe(t,e){if(Ua(e))return;let r=$o(e);if(!r)return t;let n={...t||{}};for(let[i,o]of Object.entries(r))Ua(o)?delete n[i]:n[i]=o;return Object.keys(n).length>0?n:void 0}function qpe(t,e){let r=kx(e);if(r.error)return Xt(t)||{type:"none"};let n=r.authentication||{type:"none"},i=$o(e)||{},o=Xt(t),s=o?.type===n.type;if(n.type!=="oauth2"){let d=Lpe(i),A=s&&o?{...o}:{type:n.type};return n.type==="connection_string"&&uo(i,"protocol")&&(Ua(i.protocol)?delete A.protocol:A.protocol=i.protocol),d&&(A.config=zpe(o?.config,d)),Xt(A)||{type:n.type}}let c={...s&&o?.type==="oauth2"?{...o,config:{...o.config||{}}}:{type:"oauth2",config:{}}};Od(c,i,"oauthClientMode","oauthClientMode"),$pe(c,i),Od(c,i,"authUrl","authUrl"),Od(c,i,"tokenUrl","tokenUrl"),Fpe(c,i),Od(c,i,"clientId","clientId"),Od(c,i,"clientSecret","clientSecret");let l={...c.config||{}};for(let d of Ud)jpe(l,i,d);return c.config=Object.keys(l).length>0?l:void 0,Xt(c)||{type:"oauth2"}}function Nx(t){let e=Xt(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 _x(t,e,r){if(r)for(let[n,i]of Object.entries(r))t.push({path:`${e}.${n}`,label:n,value:i})}function Hpe({authentication:t}){let e=Xt(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 Ud)r.push({path:`oauth2.config.${n}`,label:n,value:e.config?.[n]});for(let[n,i]of Object.entries(e.config||{}))Ud.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}),_x(r,"connection.config",e.config)):_x(r,`${e.type}.config`,e.config);return{type:e.type,authentication:e,configFields:r,hiddenCredentialKeys:Nx(e)}}function Gpe(t){let e=Xt(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 vx(t,e){return(0,vt.hasCredentialValue)(e[t.key])?!0:(t.aliases??[]).some(r=>(0,vt.hasCredentialValue)(e[r]))}function Ox(t,e){return t.optional?!0:t.type==="field"?vx(t.field,e):t.fields.some(r=>vx(r,e))}function Ype(t,e){let r=e||{};return t.some(n=>!Ox(n,r))}function Vpe({authentication:t,path:e,value:r}){let n=Xt(t)||{type:"none"};if(n.type==="oauth2"){if(e==="oauth2.grantType")return{...n,grantType:xd(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:Md(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:Ub({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:Ub({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:Ub({config:n.config,key:o,value:r})}}return n}function Ux({authentication:t,credentials:e}){if(Xt(t)?.type!=="oauth2"||!e||typeof e!="object"||Array.isArray(e))return null;let n=Object.keys(e).filter(i=>fe.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 authenticate_oauth.`}function Mx(t){let e=Xt(t);return e?e.type==="oauth2"?Oa({...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 Jpe(t){return Cpe.has(t.trim())}function Wpe({credential:t,system:e}){return t?.authentication??e?.authentication??void 0}function Zpe(t){let e=Xt(t);return e?.type==="oauth2"&&e.oauthClientMode==="managed"&&e.clientSecret?"Managed OAuth client secrets cannot be stored on credentials":null}function Kpe({authentication:t,credentials:e}){let r=Mx(t);return Xt(t)?.type==="oauth2"?{...e||{},...r}:{...r,...e||{}}}function Xpe({input:t,authentication:e,templateOAuth:r}){let n=Xt(e),i=n?.type==="oauth2"?n:void 0,o=i?.config||{},s=t||{},a=(...c)=>c.find(u=>u!=null);return Oa({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 Lb(t){if(t==null)return"";if(typeof t=="string")return t;let e=JSON.stringify(t);return e===void 0?String(t):e}function efe(t,e={}){let r=new Set((e.hiddenKeys||[]).map(vt.normalizeCredentialKey));return Object.entries(t).filter(([n])=>!r.has((0,vt.normalizeCredentialKey)(n))).sort(([n],[i])=>{let o=Qx.get((0,vt.normalizeCredentialKey)(n))??Number.MAX_SAFE_INTEGER,s=Qx.get((0,vt.normalizeCredentialKey)(i))??Number.MAX_SAFE_INTEGER;if(o!==s)return o-s;let a=(0,vt.isSensitiveCredentialKey)(n),c=(0,vt.isSensitiveCredentialKey)(i);return a!==c?a?-1:1:n.localeCompare(i)}).map(([n,i])=>({key:n,value:Lb(i),isReservedMasked:e.maskAll||(0,vt.isSensitiveCredentialKey)(n)}))}function tfe(t){return Object.fromEntries(Object.entries(t).map(([e,r])=>[e,Lb(r)]))}function rfe({hideOAuthFiles:t=!1,configKeys:e=[]}){return[...e,...t?["oauth_cert","oauth_key"]:[]]}function nfe(t){return yt(t.access_token)||yt(t.refresh_token)}function ife(t){let e=t.expires_at??t.expiry;if(e){let n=(0,hpe.parseUTCDate)(e);if(n)return`Expires ${n.toLocaleString()}`}let r=t.expires_in;return yt(r)?`Expires in ${r} seconds`:null}function ofe(t){return!!(t&&typeof t=="object"&&!Array.isArray(t)&&Object.values(t).some(e=>yt(e)))}function xx(t){if(!t||typeof t!="object"||Array.isArray(t))return null;let e=(0,vt.getInvalidCredentialKeyNames)(Object.keys(t));return e.length===0?null:`${vt.CREDENTIAL_KEY_VALIDATION_DESCRIPTION} Invalid keys: ${e.join(", ")}`}function Lx(t){let e=(0,vt.getInvalidCredentialKeyNames)(t);return e.length===0?null:`${vt.CREDENTIAL_KEY_VALIDATION_DESCRIPTION} Invalid keys: ${e.join(", ")}`}function Px(t){return Array.isArray(t)?[...new Set(t.map(e=>String(e||"").trim()).filter(Boolean))]:[]}function sfe({credentials:t,askForUserInputs:e}){let r=xx(t);if(r)return r;let n=Px(e),i=Lx(n);if(i)return i;if(t&&typeof t=="object"&&!Array.isArray(t))for(let[o,s]of Upe(t)){if(s===""||s===null)return"Blank secret values are not allowed; list secret names to collect from the user in askForUserInputs.";if(n.includes(o))return`Secret name '${o}' cannot be in both credentials and askForUserInputs.`}return null}function afe(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 cfe({authentication:t,credentials:e}){return Ux({authentication:t,credentials:e})}});var oL=m(Wn=>{"use strict";Object.defineProperty(Wn,"__esModule",{value:!0});Wn.bundles=void 0;Wn.buildBundleAgentLaunch=Cfe;Wn.getBundle=bfe;Wn.listBundles=Sfe;Wn.rewriteBundleToolSystemId=wfe;var ufe=yr(),lfe="https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap",dfe="<<(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>`; }>>",Fx="<<() => crypto.randomUUID()>>";function Et(t){return`<?xml version="1.0" encoding="UTF-8"?><request><control><senderid><<sage_intacct_sender_id>></senderid><password><<sage_intacct_sender_password>></password><controlid>${Fx}</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>${dfe}</login></authentication><content><function controlid="${Fx}">${t}</function></content></operation></request>`}function Ss({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 ws=`const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&apos;');`,$x="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]; };",jx="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) + '.'); };",zx=`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 Au({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",$b=100,$d=1e4,Cg=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(/\/+$/, ''); }>>`,bg={Authorization:"Bearer <<netsuite_access_token>>",Accept:"application/json"},jb=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) });`,Afe=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);`,qx=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; };`,pfe={type:"integer",minimum:1,maximum:$d,description:`Maximum number of records to return (max ${$d}). Defaults to ${$b}. 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.`},ffe={type:"boolean",description:"Only return active records. Defaults to false (inactive records are included)."},hfe={type:"string",description:"Optional subsidiary internal ID to filter by."},gfe={type:"string",description:"Optional earliest transaction date as YYYY-MM-DD."},mfe={type:"string",description:"Optional latest transaction date as YYYY-MM-DD."},yfe={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},Pd=t=>({input:"activeOnly",kind:"flag",clause:`${t}.isinactive = 'F'`,schema:ffe}),Fd=t=>({input:"subsidiaryId",kind:"id",clause:`${t}.subsidiary = $`,schema:hfe}),Pb=[{input:"fromDate",kind:"date",clause:"t.trandate >= TO_DATE('$', 'YYYY-MM-DD')",schema:gfe},{input:"toDate",kind:"date",clause:"t.trandate <= TO_DATE('$', 'YYYY-MM-DD')",schema:mfe}];function Efe(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 Bs({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) => { ${jb} const where = ${JSON.stringify(a)}; ${u.map(Efe).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 ${$d} 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:pfe,...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:`${Cg}/query/v1/suiteql`,method:"POST",headers:{...bg,"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)) || ${$b}, 1), ${$d}); return page.hasMore !== true || merged >= max; }`}}}],outputTransform:`(sourceData) => { ${Afe} 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)) || ${$b}, 1), ${$d}); 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 wr({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) => { ${jb} 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:yfe},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:`${Cg}${A}`,method:s==="create"?"POST":"PATCH",headers:{...bg,"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) => { ${jb} 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 Hx=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 };`,Gx=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);`,Yx={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},Vx=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."}}),hg=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 gg(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 mg={isInactive:{type:"boolean",description:"Set true to inactivate, false to reactivate."}},yg=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;`,nL={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."}},zb=["AcctPay","AcctRec","Bank","COGS","CredCard","DeferExpense","DeferRevenue","Equity","Expense","FixedAsset","Income","LongTermLiab","NonPosting","OthAsset","OthCurrAsset","OthCurrLiab","OthExpense","OthIncome","Stat","UnbilledRec"],Jx=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;`,Wx={acctNumber:{type:"string",description:"Account number."},acctName:{type:"string",description:"Account name."},acctType:{type:"string",enum:zb,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."},...nL},Zx=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;`,Kx={name:{type:"string",description:"Department name."},parentId:{type:"string",description:"Optional parent department internal ID."},externalId:{type:"string",description:"Optional external ID."},...nL},Eg=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);`,Ig=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."}}),iL=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');`,Xx=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'); ${iL} return item; }) };`,eL={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},tL=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); ${iL} return item; }) };`,rL={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},Ma="Re-running this tool creates another record; it is not idempotent.",Ife=[Bs({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:[Pd("a"),{input:"accountType",kind:"enum",values:zb,clause:"a.accttype = '$'",schema:{type:"string",enum:zb,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) })"}),Bs({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:[Pd("c"),Fd("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) })"}),Bs({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:[Pd("v"),Fd("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) })"}),Bs({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:[...Pb,Fd("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) })"}),Bs({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:[...Pb,Fd("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) })"}),Bs({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:[...Pb,Fd("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) })"}),Bs({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:[Pd("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) })"}),Bs({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:[Pd("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:`${Cg}/query/v1/suiteql`,method:"POST",headers:{...bg,"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) => { ${qx} 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:`${Cg}/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:bg,queryParams:{expandSubResources:"<<(p) => (p.expandSubResources === false || p.expandSubResources === 'false' ? 'false' : 'true')>>"}}}],outputTransform:`(sourceData) => { ${qx} const record = sourceData.getRecord ? sourceData.getRecord.data : undefined; if (!record || typeof record !== 'object') throw new Error('NetSuite returned no record.'); return { record: stripLinks(record) }; }`},wr({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. ${Ma}`,stepId:"createJournalEntry",recordType:"journalentry",mode:"create",properties:{...Vx("create"),lines:{type:"array",description:"Journal lines. Debit and credit totals must balance.",items:Yx}},required:["date","lines"],body:`${Gx} if (!Array.isArray(p.lines) || p.lines.length < 2) throw new Error('lines must contain at least two journal lines.'); ${Hx}`}),wr({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:{...Vx("update"),lines:{type:"array",description:"Optional replacement lines. When set, they replace every existing line and must balance.",items:Yx}},required:[],body:`${Gx} 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.'); ${Hx}`,replaceSublist:{input:"lines",sublist:"line"}}),wr({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. ${Ma}`,stepId:"createVendor",recordType:"vendor",mode:"create",properties:gg("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.'); ${hg}`}),wr({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:{...gg("vendor"),...mg},required:[],body:hg}),wr({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. ${Ma}`,stepId:"createCustomer",recordType:"customer",mode:"create",properties:gg("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.'); ${hg}`}),wr({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:{...gg("customer"),...mg},required:[],body:hg}),wr({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. ${Ma}`,stepId:"createAccount",recordType:"account",mode:"create",properties:Wx,required:["acctName","acctType"],body:`if (!has(p.acctName) || !has(p.acctType)) throw new Error('acctName and acctType are required.'); ${Jx} ${yg}`}),wr({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:{...Wx,...mg},required:[],body:`${Jx} ${yg}`}),wr({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. ${Ma}`,stepId:"createInvoice",recordType:"invoice",mode:"create",properties:{customerId:{type:"string",description:"Customer internal ID."},...Ig("create"),lines:{type:"array",description:"Item lines.",items:eL}},required:["customerId","lines"],body:`if (!Array.isArray(p.lines) || p.lines.length === 0) throw new Error('lines must contain at least one item line.'); ${Eg("customerId")} ${Xx}`}),wr({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."},...Ig("update"),lines:{type:"array",description:"Optional replacement item lines; they replace every existing item line.",items:eL}},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.'); ${Eg("customerId")} ${Xx}`,replaceSublist:{input:"lines",sublist:"item"}}),wr({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. ${Ma}`,stepId:"createVendorBill",recordType:"vendorbill",mode:"create",properties:{vendorId:{type:"string",description:"Vendor internal ID."},referenceNo:{type:"string",description:"Optional vendor invoice reference number."},...Ig("create"),lines:{type:"array",description:"Expense lines.",items:rL}},required:["vendorId","lines"],body:`if (!Array.isArray(p.lines) || p.lines.length === 0) throw new Error('lines must contain at least one expense line.'); ${Eg("vendorId")} if (has(p.referenceNo)) record.tranId = String(p.referenceNo); ${tL}`}),wr({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."},...Ig("update"),lines:{type:"array",description:"Optional replacement expense lines; they replace every existing expense line.",items:rL}},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.'); ${Eg("vendorId")} if (has(p.referenceNo)) record.tranId = String(p.referenceNo); ${tL}`,replaceSublist:{input:"lines",sublist:"expense"}}),wr({id:"netsuite-create-department",name:"Create NetSuite department",shortName:"Create department",instruction:`Creates a department in NetSuite. Without subsidiaryIds NetSuite assigns the parent subsidiary. ${Ma}`,stepId:"createDepartment",recordType:"department",mode:"create",properties:Kx,required:["name"],body:`if (!has(p.name)) throw new Error('name is required.'); ${Zx} ${yg}`}),wr({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:{...Kx,...mg},required:[],body:`${Zx} ${yg}`})],Fb={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:lfe,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 with set_credentials, never as chat text and never via the Credentials 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, call setup_gateway with os windows and enableScriptRunner true (no targets are needed); the user runs the install command in PowerShell opened with 'Run as administrator' on the machine where Sage 100 and Workstation Setup are installed (the gateway must run there, ProvideX.Script is a local 32-bit COM class). The command installs the gateway as a Windows service and the call completes when it connects; never ask for the command or its key in chat. The same setup is in Systems \u2192 Connect system \u2192 Private System \u2192 Set up a gateway. The script runner option 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. Only if the user cannot use that page, fall back to the manual setup: download https://downloads.superglue.cloud/superglue-gateway-windows.exe, 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. If a tunnel is connected but has no runner target, the gateway was set up without the script runner or is an outdated build; have the user set up the gateway again with the option selected, or add the flag and restart. The service runs as the Windows system account: if Sage data is on a mapped drive or a network share that account cannot reach, the connection test fails with a path or access error. When the tunnel with the runner target appears, attach it to this Sage 100 system with tools.writeSystem from superglue/approved (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, never as chat text. 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, call setup_gateway with os windows and enableScriptRunner true (no targets are needed), and tell the user to run the install command in PowerShell opened with "Run as administrator" on the Windows machine where Sage 100 is installed and Workstation Setup has run. The call completes when the gateway connects; never ask for the command or its key in chat. The script runner option 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. If a tunnel is connected but has no runner target, the gateway was set up without the script runner or is an outdated build: have the user set up the gateway again with the option selected. When setup_gateway completes, check that the returned targets include runner, then attach that tunnel to this Sage 100 system with tools.writeSystem from superglue/approved, keeping the URL script://runner/vbs32. Use set_credentials to collect 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 Credentials page and never accept secrets as chat text. 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(`
110
+ ${t.slice(t.length-n)}`}function rAe(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 nAe(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 iAe(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 oAe(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 sAe(t){return t.map(e=>YM(e))}function aAe(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}`}N.ALLOWED_PATCH_SYSTEM_FIELDS=["name","url","specificInstructions","icon","credentials","authentication","metadata","templateName","requiredCredentialKeys","documentationFiles","tunnel","tags"];var cAe=new Set(["data","stepResults","toolPayload","rawData","transformedData"]),uAe=8e4;function lAe(t,e=uAe){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(cAe.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,cde.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 dAe(t){if(!t.steps)return[];let e=new Set;for(let r of t.steps)r.config&&(0,DM.isRequestConfig)(r.config)&&r.config.systemId&&e.add(r.config.systemId);return Array.from(e)}function cg(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)cg(n,e,r);return}for(let n of Object.values(t))cg(n,e,r)}}function AAe(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 VM(t,e){let r=[];cg(t,r);let n=`${e}_`,i=new Set;for(let o of r)for(let s of AAe(o)){if(!s.startsWith(n))continue;let a=s.slice(n.length);!a||a==="url"||!N.CREDENTIAL_KEY_PATTERN.test(a)||i.add(a)}return[...i]}var pAe=/^\s*(async\s+)?(\([^)]*\)|[a-zA-Z_$][a-zA-Z0-9_$]*)\s*=>/,fAe=new Set(["sg_auth_email","sg_auth_jwt"]);function hAe({config:t,systemId:e}){let r=[];cg(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)||pAe.test(d)||fAe.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=>N.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 gAe(t){let e={};if(!t.steps)return e;for(let r of t.steps){if(!r.config||!(0,DM.isRequestConfig)(r.config)||!r.config.systemId)continue;let n=VM(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}});var XM=m(gt=>{"use strict";Object.defineProperty(gt,"__esModule",{value:!0});gt.AGENT_CONTEXT_MEMORY_MESSAGE_ID_PREFIX=void 0;gt.applyToolMutation=JM;gt.mutateToolCallInMessages=yAe;gt.buildStreamingAssistantMessage=WM;gt.parseToolOutput=ZM;gt.parseAgentStreamEventLine=IAe;gt.stopActiveTool=KM;gt.appendContentToMessage=vb;gt.updateMessageWithData=lu;gt.findAwaitingConfirmationToolCallIds=CAe;gt.declineAwaitingConfirmationTools=bAe;gt.findAndResumeMessageWithTool=SAe;gt.serializeMessageForPersistence=BAe;gt.isTurnContextBlockMessage=Db;gt.normalizeAgentSessionForkMessages=QAe;gt.normalizeAgentSessionImportMessages=_Ae;gt.createAgentTranscriptState=vAe;gt.applyAgentStreamChunk=DAe;var mAe=yr(),dg=wn();function JM(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 yAe(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:JM(s.tool,r)}));return i&&o?{...n,parts:o}:n})}function WM(t){return{id:t,content:"",role:"assistant",timestamp:new Date,parts:[{type:"content",content:"",id:"content-0"}],isStreaming:!0}}function EAe(){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 ZM(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 IAe(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 KM(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 vb(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 lu(t,e,r){if(t.id!==r.id)return t;switch(e.type){case"content":return vb(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"||typeof e.toolCallId!="string")return t;let i=o=>{if(o.id!==e.toolCallId)return o;let s=ZM(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:KM(i.tool)}:i);return{...t,isStreaming:!1,parts:n,content:""}}default:return t}}function CAe(t){let e=new Set;for(let r of t)for(let n of(0,dg.getMessageToolCalls)(r))n.status==="awaiting_confirmation"&&e.add(n.id);return[...e]}function bAe(t){let e=EAe();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 SAe(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 wAe(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 BAe(t){let{isStreaming:e,tools:r,...n}=t;return JSON.parse((0,dg.safeStringify)({...n,...t.parts?{parts:t.parts.map(i=>i.type==="tool"&&i.tool?{...i,tool:wAe(i.tool)}:i)}:{}},0))}gt.AGENT_CONTEXT_MEMORY_MESSAGE_ID_PREFIX="context-memory-";function Db(t){return mAe.TURN_CONTEXT_BLOCK_TYPES.includes(t.contextType??"")}function QAe(t){return t.filter(e=>e.role!=="system"&&e.contextType!=="memory_notes"&&!Db(e)&&!e.id.startsWith(gt.AGENT_CONTEXT_MEMORY_MESSAGE_ID_PREFIX)).map(e=>({...e,stale:void 0,isStreaming:void 0}))}function _Ae(t){return t.filter(e=>!e.stale&&!e.isStreaming&&e.contextType!=="memory_notes"&&!Db(e)&&!!e.id)}function vAe(t=[],e=null){return{messages:t,assistantMessageId:e,outcome:"streaming"}}function lg(t,e){return(0,dg.getMessageToolCalls)(t).some(r=>r.id===e)}function uu(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=WM(t.assistantMessageId??e.createAssistantMessageId());return{state:{...t,messages:[...t.messages,n],assistantMessageId:n.id},target:n}}function DAe(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,dg.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=uu(t,r);return{...n.state,messages:n.state.messages.map(i=>i.id===n.target.id?vb(i,e.content||""):i)}}case"error":{let n=uu(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=>lg(o,e.toolCall.id))??null,i=n?{state:t,target:n}:uu(t,r);return{...i.state,messages:i.state.messages.map(o=>lu(o,e,i.target))}}case"run_command_effect":{let n=e.toolCallId;if(!n)return t;let i=t.messages.find(o=>lg(o,n));return i?{...t,messages:t.messages.map(o=>lu(o,e,i))}:t}case"tool_call_input":{if(!e.toolCall)return t;let n=t.messages.find(i=>lg(i,e.toolCall.id));return n?{...t,messages:t.messages.map(i=>lu(i,e,n))}:t}case"tool_call_complete":{if(!e.toolCall)return t;let n=t.messages.find(o=>lg(o,e.toolCall.id)),i=n?{state:t,target:n}:uu(t,r);return{...i.state,messages:i.state.messages.map(o=>lu(o,e,i.target))}}case"paused":{let n=uu(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=uu(t,r);return{...n.state,outcome:t.outcome==="failed"?"failed":"completed",messages:n.state.messages.map(i=>lu(i,e,n.target))}}default:return t}}});var Tb=m(Lo=>{"use strict";Object.defineProperty(Lo,"__esModule",{value:!0});Lo.PROJECT_LIMITS=Lo.PROJECT_TASK_STATUSES=Lo.PROJECT_RESOURCE_TYPES=void 0;Lo.projectResourceKey=TAe;Lo.PROJECT_RESOURCE_TYPES=["system","playbook","artifact","file","tool"];Lo.PROJECT_TASK_STATUSES=["not_started","in_progress","waiting","done"];Lo.PROJECT_LIMITS={name:80,description:500,taskName:120,taskDescription:1e4,taskResources:100};function TAe(t){return`${t.type}:${t.id}`}});var Ag=m(zr=>{"use strict";Object.defineProperty(zr,"__esModule",{value:!0});zr.RESOURCE_KINDS=zr.RESOURCE_DEFINITIONS=void 0;zr.isResourceKind=RAe;zr.getResourceDefinition=kAe;zr.getResourceAppPath=NAe;zr.RESOURCE_DEFINITIONS={tool:{label:"Tool",pluralLabel:"Tools",collectionKey:"tools",appPath:"/tools",hasDetailPage:!0,memberDefaultPermission:"editor",pickerDefaultPermission:"editor"},system:{label:"System",pluralLabel:"Systems",collectionKey:"systems",appPath:"/systems",hasDetailPage:!0,memberDefaultPermission:"editor",pickerDefaultPermission:"editor"},credential:{label:"Credential",pluralLabel:"Credentials",collectionKey:"credentials",appPath:"/credentials",hasDetailPage:!1,pickerDefaultPermission:"viewer"},playbook:{label:"Playbook",pluralLabel:"Playbooks",collectionKey:"playbooks",appPath:"/playbooks",hasDetailPage:!0,pickerDefaultPermission:"editor"},artifact:{label:"Artifact",pluralLabel:"Artifacts",collectionKey:"artifacts",appPath:"/artifacts",hasDetailPage:!0,pickerDefaultPermission:"editor"},file:{label:"File",pluralLabel:"Files",collectionKey:"files",appPath:"/files",hasDetailPage:!1,pickerDefaultPermission:"viewer"},project:{label:"Project",pluralLabel:"Projects",collectionKey:"projects",appPath:"/projects",hasDetailPage:!0,pickerDefaultPermission:"viewer"}};zr.RESOURCE_KINDS=Object.keys(zr.RESOURCE_DEFINITIONS);function RAe(t){return typeof t=="string"&&Object.prototype.hasOwnProperty.call(zr.RESOURCE_DEFINITIONS,t)}function kAe(t){return zr.RESOURCE_DEFINITIONS[t]}function NAe(t,e){let r=zr.RESOURCE_DEFINITIONS[t];return r.hasDetailPage?`${r.appPath}/${encodeURIComponent(e)}`:r.appPath}});var nx=m(ka=>{"use strict";Object.defineProperty(ka,"__esModule",{value:!0});ka.SDK_ERROR_DETAILS_SCHEMA=ka.SDK_OUTPUT_CONTRACTS=void 0;ka.toSdkJsonSchema=xAe;var y=pa(),OAe=Tb(),UAe=Ag(),MAe=yr();function xAe({schema:t}){return y.z.toJSONSchema(t,{target:"draft-7",io:"output",unrepresentable:"any"})}var ex=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()}),tx=y.z.looseObject({vfsPath:y.z.string(),storedBytes:y.z.number(),originalOutputBytes:y.z.number(),storageTruncated:y.z.boolean()}),rx=y.z.object({action:y.z.enum(["approve","reject","oauth_success","oauth_failure"]),source:y.z.enum(["user","automatic"])});function Bn(t){return y.z.looseObject({toolCallId:y.z.string(),toolName:y.z.string(),outcome:y.z.literal("success"),confirmation:rx.optional(),data:t})}var Rb={http:ex.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()},LAe=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."),...Rb}),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."),...Rb}),y.z.looseObject({protocol:y.z.enum(MAe.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."),...Rb})]),PAe=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.")})]),FAe=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.")}),$Ae=y.z.looseObject({stepId:y.z.string(),success:y.z.boolean(),data:y.z.unknown().optional(),error:y.z.string().nullable().optional(),http:ex.optional(),stepFileKeys:y.z.array(y.z.string()).optional()}),jAe=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($Ae),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:tx.optional()}),zAe=Bn(y.z.looseObject({resource:y.z.looseObject({id:y.z.string(),name:y.z.string().optional(),version:y.z.union([y.z.number(),y.z.string()]).optional()}),created:y.z.boolean(),projectId:y.z.string().optional(),addedFiles:y.z.array(y.z.looseObject({id:y.z.string(),fileName: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(OAe.PROJECT_RESOURCE_TYPES),id:y.z.string()}),error:y.z.string().optional()}).optional()}));ka.SDK_OUTPUT_CONTRACTS={assignSessionToProject:{name:"SuperglueSessionProjectResult",schema:Bn(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:LAe,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:PAe,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."},systemFetch:{name:"SuperglueSystemFetchResult",schema:FAe,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:jAe,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:zAe,description:"Returns saved resource identity, creation status, and available project attribution or added files. Throws SuperglueError on failure."},installBundle:{name:"SuperglueBundleInstallResult",schema:Bn(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, tool, MCP server, and playbook identities, the secret names the user must supply, and whether the user has a complete credential. Throws SuperglueError on failure."},stopBackgroundJob:{name:"SuperglueStopBackgroundJobResult",schema:Bn(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:Bn(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:Bn(y.z.looseObject({resource:y.z.looseObject({kind:y.z.enum(UAe.RESOURCE_KINDS),id:y.z.string()})})),description:"Returns the shared resource identity. Throws SuperglueError on failure."},showVisual:{name:"SuperglueShowVisualResult",schema:Bn(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:Bn(y.z.looseObject({actionCount:y.z.number()})),description:"Returns the notification action count. Throws SuperglueError on failure."},writeOrgSettings:{name:"SuperglueOrgSettingsResult",schema:Bn(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:Bn(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:Bn(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:Bn(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."},previewArtifact:{name:"SuperglueArtifactPreviewResult",schema:y.z.looseObject({draftId:y.z.string(),bytes:y.z.number()}),description:"Returns the artifact draft identity and byte count. Throws SuperglueError on failure."}};var qAe=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()});ka.SDK_ERROR_DETAILS_SCHEMA=y.z.discriminatedUnion("kind",[y.z.looseObject({kind:y.z.literal("tool_result"),resultMetadata:tx.optional(),result:y.z.looseObject({toolCallId:y.z.string(),toolName:y.z.string(),outcome:y.z.enum(["success","failure","rejected","aborted"]),confirmation:rx.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(qAe),output:y.z.unknown().optional()})])});var hx=m(be=>{"use strict";Object.defineProperty(be,"__esModule",{value:!0});be.SERVER_OWNED_SESSION_RESOURCE_KINDS=be.AgentRequestValidationError=be.AGENT_TOOL_CONTINUATION_ACTION_BY_CONFIRMATION_STATE=be.AGENT_TOOL_CONTINUATION_ACTIONS=be.AGENT_IDENTIFIER_PATTERN=be.AGENT_REQUEST_LIMITS=void 0;be.validateAgentRequestPayload=lx;be.validateResourceBinding=dx;be.validateClientResourceBinding=Ax;be.validateAgentSessionIdentity=px;be.validateAgentSessionTarget=fx;be.validateAgentRequestSubmission=WAe;be.isAgentMessagePayload=ZAe;be.isAgentToolContinuationPayload=KAe;var Po=yr();be.AGENT_REQUEST_LIMITS={messageContentChars:5e4,identifierChars:256,attachedFiles:20,toolContinuations:20,continuationInputChars:1e5,frontendDraftsChars:2e6,accessRulesContextChars:2e6,pendingMessagesPerSession:10};be.AGENT_IDENTIFIER_PATTERN=/^[A-Za-z0-9._-]+$/;be.AGENT_TOOL_CONTINUATION_ACTIONS=["approve","reject","oauth_success","oauth_failure"];be.AGENT_TOOL_CONTINUATION_ACTION_BY_CONFIRMATION_STATE={[Po.ConfirmationAction.CONFIRMED]:"approve",[Po.ConfirmationAction.DECLINED]:"reject",[Po.ConfirmationAction.OAUTH_SUCCESS]:"oauth_success",[Po.ConfirmationAction.OAUTH_FAILURE]:"oauth_failure"};var pg=class extends Error{constructor(e){super(e),this.name="AgentRequestValidationError"}};be.AgentRequestValidationError=pg;function Ze(t){throw new pg(t)}function co(t,e){return(!t||typeof t!="object"||Array.isArray(t))&&Ze(`${e} must be an object`),t}function Na(t,e){(typeof t!="string"||!t.trim())&&Ze(`${e} must be a non-empty string`);let r=t.trim();return r.length>be.AGENT_REQUEST_LIMITS.identifierChars&&Ze(`${e} exceeds ${be.AGENT_REQUEST_LIMITS.identifierChars} characters`),be.AGENT_IDENTIFIER_PATTERN.test(r)||Ze(`${e} may only contain letters, numbers, dots, underscores, and hyphens`),r}function HAe(t,e){return typeof t!="boolean"&&Ze(`${e} must be a boolean`),t}function kb(t,e){try{return JSON.stringify(t).length}catch{return Ze(`${e} must be JSON-serializable`)}}function GAe(t,e){if(t!==void 0)return Array.isArray(t)||Ze(`${e} must be an array`),t.length>be.AGENT_REQUEST_LIMITS.attachedFiles&&Ze(`${e} exceeds ${be.AGENT_REQUEST_LIMITS.attachedFiles} entries`),t.map((r,n)=>{let i=co(r,`${e}[${n}]`);return{...i,key:Na(i.key,`${e}[${n}].key`)}})}function ix({value:t,label:e,requireHidden:r}){let n=co(t,e),i=Na(n.id,`${e}.id`);typeof n.content!="string"&&Ze(`${e}.content must be a string`);let o=n.content;o.length>be.AGENT_REQUEST_LIMITS.messageContentChars&&Ze(`${e}.content exceeds ${be.AGENT_REQUEST_LIMITS.messageContentChars} characters`);let s=HAe(n.isHidden,`${e}.isHidden`);r&&!s&&Ze(`${e}.isHidden must be true`);let a=GAe(n.attachedFiles,`${e}.attachedFiles`);return!o.trim()&&!a?.length&&Ze(`${e}.content may only be empty when an attachment is present`),{id:i,content:o,isHidden:s,...a?{attachedFiles:a}:{}}}function sx(t){if(t===void 0)return;let e=co(t,"frontendDrafts");return kb(e,"frontendDrafts")>be.AGENT_REQUEST_LIMITS.frontendDraftsChars&&Ze(`frontendDrafts exceeds ${be.AGENT_REQUEST_LIMITS.frontendDraftsChars} characters`),e}function ax(t){if(t===void 0)return;let e=co(t,"accessRulesContext");return kb(e,"accessRulesContext")>be.AGENT_REQUEST_LIMITS.accessRulesContextChars&&Ze(`accessRulesContext exceeds ${be.AGENT_REQUEST_LIMITS.accessRulesContextChars} characters`),e}function cx(t){if(t!==void 0)return(typeof t!="string"||!Po.AGENT_APPROVAL_MODES.includes(t))&&Ze(`request.approvalMode must be one of: ${Po.AGENT_APPROVAL_MODES.join(", ")}`),t}function ux(t,e){let r=co(t,e),n=Na(r.toolCallId,`${e}.toolCallId`);return(typeof r.action!="string"||!be.AGENT_TOOL_CONTINUATION_ACTIONS.includes(r.action))&&Ze(`${e}.action must be one of: ${be.AGENT_TOOL_CONTINUATION_ACTIONS.join(", ")}`),r.input!==void 0&&kb(r.input,`${e}.input`)>be.AGENT_REQUEST_LIMITS.continuationInputChars&&Ze(`${e}.input exceeds ${be.AGENT_REQUEST_LIMITS.continuationInputChars} characters`),{toolCallId:n,action:r.action,...r.input!==void 0?{input:r.input}:{}}}function YAe(t){if(t===void 0)return;(!Array.isArray(t)||t.length===0)&&Ze("request.toolContinuations must be a non-empty array"),t.length>be.AGENT_REQUEST_LIMITS.toolContinuations&&Ze(`request.toolContinuations exceeds ${be.AGENT_REQUEST_LIMITS.toolContinuations} entries`);let e=t.map((r,n)=>ux(r,`request.toolContinuations[${n}]`));return new Set(e.map(({toolCallId:r})=>r)).size!==e.length&&Ze("request.toolContinuations must not contain duplicate toolCallId values"),e}function ox(t,e){if(t===void 0)return;(typeof t!="string"||!t.trim())&&Ze(`${e} must be a non-empty string`);let r=t.trim();return r.length>be.AGENT_REQUEST_LIMITS.messageContentChars&&Ze(`${e} exceeds ${be.AGENT_REQUEST_LIMITS.messageContentChars} characters`),r}function VAe(t){let e=ix({value:t.message,label:"request.message"}),r=ox(t.title,"request.title"),n=ox(t.titleInput,"request.titleInput"),i=t.hiddenSteeringMessage===void 0?void 0:ix({value:t.hiddenSteeringMessage,label:"request.hiddenSteeringMessage",requireHidden:!0});i&&i.id===e.id&&Ze("request.hiddenSteeringMessage.id must differ from request.message.id");let o=YAe(t.toolContinuations),s=cx(t.approvalMode),a=sx(t.frontendDrafts),c=ax(t.accessRulesContext);return{kind:"message",message:e,...i?{hiddenSteeringMessage:i}:{},...r?{title:r}:{},...n?{titleInput:n}:{},...o?{toolContinuations:o}:{},...s?{approvalMode:s}:{},...a?{frontendDrafts:a}:{},...c?{accessRulesContext:c}:{}}}function JAe(t){let e=ux(t,"request"),r=cx(t.approvalMode),n=sx(t.frontendDrafts),i=ax(t.accessRulesContext);return{kind:"tool_continuation",...e,...r?{approvalMode:r}:{},...n?{frontendDrafts:n}:{},...i?{accessRulesContext:i}:{}}}function lx(t){let e=co(t,"request");return e.kind==="message"?VAe(e):e.kind==="tool_continuation"?JAe(e):Ze('request.kind must be "message" or "tool_continuation"')}function dx(t,e){let r=co(t,e);return(typeof r.kind!="string"||!Po.AGENT_SESSION_RESOURCE_KINDS.includes(r.kind))&&Ze(`${e}.kind must be one of: ${Po.AGENT_SESSION_RESOURCE_KINDS.join(", ")}`),{kind:r.kind,id:Na(r.id,`${e}.id`)}}be.SERVER_OWNED_SESSION_RESOURCE_KINDS=["briefing"];function Ax(t,e){let r=dx(t,e);return be.SERVER_OWNED_SESSION_RESOURCE_KINDS.includes(r.kind)&&Ze(`${e}.kind "${r.kind}" is assigned by the server`),r}function px(t,e="session.createIfMissing"){let r=co(t,e),n=r.projectId===void 0?void 0:Na(r.projectId,`${e}.projectId`),i=r.taskId===void 0?void 0:Na(r.taskId,`${e}.taskId`);i&&!n&&Ze(`${e}.taskId requires ${e}.projectId`);let o=Object.values(Po.AgentType);(typeof r.agentId!="string"||!o.includes(r.agentId))&&Ze(`${e}.agentId must be one of: ${o.join(", ")}`);let s=r.resourceBinding===void 0?void 0:Ax(r.resourceBinding,`${e}.resourceBinding`);return{agentId:r.agentId,...n?{projectId:n}:{},...i?{taskId:i}:{},...s?{resourceBinding:s}:{}}}function fx(t){let e=co(t,"session"),r=e.createIfMissing===void 0?void 0:px(e.createIfMissing);return{id:Na(e.id,"session.id"),...r?{createIfMissing:r}:{}}}function WAe(t){let e=co(t,"body");return{session:fx(e.session),request:lx(e.request)}}function ZAe(t){return t.kind==="message"}function KAe(t){return t.kind==="tool_continuation"}});var mx=m(He=>{"use strict";Object.defineProperty(He,"__esModule",{value:!0});He.ARTIFACT_EXPORT_FORMATS=He.ARTIFACT_RESPONSE_RESERVED_FIELD_NAMES=He.ARTIFACT_RESPONSE_PATCH_DEBOUNCE_MS=He.MAX_SPREADSHEET_ARTIFACT_BYTES=He.MAX_HTML_ARTIFACT_IMAGE_BYTES=He.MAX_HTML_ARTIFACT_BYTES=He.MAX_SPREADSHEET_CELL_TEXT_LENGTH=He.MAX_SPREADSHEET_SHEET_NAME_LENGTH=He.MAX_SPREADSHEET_GRID_CELLS=He.MAX_SPREADSHEET_SHEETS=He.SPREADSHEET_CELL_TYPES=void 0;He.isValidSpreadsheetCell=tpe;He.isArtifactExportFormat=rpe;He.isArtifactExportFormatForKind=npe;var gx=pa();He.SPREADSHEET_CELL_TYPES=["text","integer","number","percent","currency","boolean","date","datetime"];He.MAX_SPREADSHEET_SHEETS=20;He.MAX_SPREADSHEET_GRID_CELLS=1e6;He.MAX_SPREADSHEET_SHEET_NAME_LENGTH=31;He.MAX_SPREADSHEET_CELL_TEXT_LENGTH=32767;var XAe=gx.z.iso.date(),epe=gx.z.iso.datetime({offset:!0});function tpe(t,e){return t===null?!0:e==="text"?typeof t=="string"&&t.length<=He.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"?epe:XAe).safeParse(t).success}He.MAX_HTML_ARTIFACT_BYTES=1024*1024;He.MAX_HTML_ARTIFACT_IMAGE_BYTES=12*1024*1024;He.MAX_SPREADSHEET_ARTIFACT_BYTES=10*1024*1024;He.ARTIFACT_RESPONSE_PATCH_DEBOUNCE_MS=300;He.ARTIFACT_RESPONSE_RESERVED_FIELD_NAMES=new Set(["__proto__","constructor","prototype"]);He.ARTIFACT_EXPORT_FORMATS=["html","pdf","docx","xlsx","pptx"];function rpe(t){return He.ARTIFACT_EXPORT_FORMATS.some(e=>e===t)}function npe(t,e,r=!1){return t==="spreadsheet"?e==="xlsx":r?e==="html"||e==="pdf"||e==="pptx":e!=="pptx"}});var bx=m($e=>{"use strict";Object.defineProperty($e,"__esModule",{value:!0});$e.API_KEY_ACTION_LABELS=$e.API_KEY_SURFACE_LABELS=$e.API_KEY_SCOPES=$e.API_KEY_SURFACE_ACTIONS=$e.API_KEY_ACTIONS=$e.API_KEY_SURFACES=void 0;$e.getApiKeySurface=Ex;$e.getApiKeyAction=Ix;$e.getApiKeySurfaceActions=Nb;$e.parseApiKeyScopes=Cx;$e.validateApiKeyScopesInput=ape;$e.isApiKeyScopeAllowed=cpe;$e.formatApiKeyScopes=upe;$e.API_KEY_SURFACES=["api","mcp"];$e.API_KEY_ACTIONS=["read","write","execute"];$e.API_KEY_SURFACE_ACTIONS={api:$e.API_KEY_ACTIONS,mcp:["execute"]};$e.API_KEY_SCOPES=$e.API_KEY_SURFACES.flatMap(t=>$e.API_KEY_SURFACE_ACTIONS[t].map(e=>`${t}:${e}`));$e.API_KEY_SURFACE_LABELS={api:"API & CLI",mcp:"MCP"};$e.API_KEY_ACTION_LABELS={read:"Read",write:"Write",execute:"Execute"};var yx=new Set($e.API_KEY_SCOPES),ipe={"/v1/tools":["read"],"/v1/tools/:toolId/run":["execute"],"/v1/authenticate":["write"],"/v1/memory-notes":["read","write"]},ope=new Set(["/v1/api-keys","/v1/api-keys/:id","/v1/api-keys/:id/reveal"]),spe=new Set(["/v1/me"]);function Ex(t){let e=t.split("?")[0];return e==="/mcp"||e.startsWith("/mcp/")?"mcp":"api"}function Ix(t){return t==="read"?"read":t==="execute"?"execute":"write"}function Nb(t,e){return $e.API_KEY_SURFACE_ACTIONS[e].filter(r=>(t||[]).includes(`${e}:${r}`))}function Cx(t){if(!Array.isArray(t))return null;let e=[...new Set(t.filter(r=>yx.has(r)))];return e.length>0?e:null}function ape(t){if(t==null)return{scopes:null};let e=`Valid scopes: ${$e.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=>!yx.has(n));return r.length>0?{error:`Unknown API key scope(s): ${r.map(String).join(", ")}. ${e}`}:{scopes:Cx(t)}}function cpe({scopes:t,path:e,type:r}){if(!t||t.length===0)return!0;let n=e.split("?")[0];if(ope.has(n))return!1;if(spe.has(n))return!0;let i=Ix(r),o=Ex(n);return o==="api"&&ipe[n]?.some(s=>s===r)&&Nb(t,"mcp").length>0?!0:t.includes(`${o}:${i}`)}function upe(t){return!t||t.length===0?"Full access":$e.API_KEY_SURFACES.map(e=>({surface:e,actions:Nb(t,e)})).filter(e=>e.actions.length>0).map(e=>$e.API_KEY_SURFACE_ACTIONS[e.surface].length===1?$e.API_KEY_SURFACE_LABELS[e.surface]:`${$e.API_KEY_SURFACE_LABELS[e.surface]} ${e.actions.join("/")}`).join(", ")}});var Sx=m(Ob=>{"use strict";Object.defineProperty(Ob,"__esModule",{value:!0});Ob.isValidEmail=lpe;function lpe(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 Bx=m(mt=>{"use strict";Object.defineProperty(mt,"__esModule",{value:!0});mt.GATEWAY_UNINSTALL_COMMANDS=mt.GATEWAY_API_KEY_NAME_PREFIX=mt.GATEWAY_TARGET_NAME_PATTERN=mt.GATEWAY_SETUP_GUIDE_URL=mt.GATEWAY_DOWNLOAD_BASE_URL=mt.GATEWAY_INSTALL_TOKEN_PREFIX=void 0;mt.getGatewayServerUrl=wx;mt.buildGatewayInstallToken=Ape;mt.buildGatewayInstallCommand=ppe;mt.getGatewayApiKeyName=fpe;mt.GATEWAY_INSTALL_TOKEN_PREFIX="sgi1.";mt.GATEWAY_DOWNLOAD_BASE_URL="https://downloads.superglue.cloud";mt.GATEWAY_SETUP_GUIDE_URL="https://superglue.ai/docs/guides/secure-gateway/";mt.GATEWAY_TARGET_NAME_PATTERN=/^[a-z0-9]([a-z0-9_-]{0,61}[a-z0-9])?$/;function wx(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 dpe(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 Ape(t){let e={v:1,serverUrl:wx(t.apiEndpoint),tunnelId:t.tunnelId,apiKey:t.apiKey,targets:t.targets,enableScriptRunner:t.enableScriptRunner};return mt.GATEWAY_INSTALL_TOKEN_PREFIX+dpe(JSON.stringify(e))}function ppe(t,e){return t==="windows"?['$ErrorActionPreference = "Stop"',"[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072",'$ProgressPreference = "SilentlyContinue"','$gateway = "$env:TEMP\\superglue-gateway.exe"',"Remove-Item $gateway -Force -ErrorAction SilentlyContinue",`Invoke-WebRequest -UseBasicParsing "${mt.GATEWAY_DOWNLOAD_BASE_URL}/superglue-gateway-windows.exe" -OutFile $gateway`,`"${e}" | & $gateway install -`].join("; "):["d=$(mktemp -d)",`u="${mt.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(" && ")}mt.GATEWAY_API_KEY_NAME_PREFIX="Gateway: ";function fpe(t){return mt.GATEWAY_API_KEY_NAME_PREFIX+t}mt.GATEWAY_UNINSTALL_COMMANDS={windows:'& "C:\\Program Files\\superglue Gateway\\superglue-gateway.exe" uninstall',linux:"sudo /usr/local/bin/superglue-gateway uninstall"}});var Ld=m(fe=>{"use strict";Object.defineProperty(fe,"__esModule",{value:!0});fe.OAUTH_CONFIG_CREDENTIAL_KEYS=void 0;fe.hasMeaningfulValue=yt;fe.stringValue=Gt;fe.validateOAuthConnection=Bpe;fe.formatOAuthConnectionDisabledReason=_pe;fe.objectValue=$o;fe.parseScopes=Md;fe.normalizeGrantType=xd;fe.normalizeOAuthClientMode=xb;fe.normalizeSystemAuthentication=Xt;fe.resolveOAuthClientMode=Dpe;fe.flattenSystemAuthentication=Tx;fe.maskedFlatSystemAuthentication=Tpe;fe.isMaskedSecretValue=Rx;fe.pickAgentAuthInputFields=Rpe;fe.maskSystemAuthenticationForResponse=kpe;fe.restoreMaskedClientSecret=Npe;fe.mapAgentAuthInput=kx;fe.mergeAgentAuthInput=qpe;fe.getAuthenticationConfigCredentialKeys=Nx;fe.buildAuthenticationEditorModel=Hpe;fe.getCredentialRequirements=Gpe;fe.isCredentialRequirementSatisfied=Ox;fe.hasUnsatisfiedCredentialRequirements=Ype;fe.updateAuthenticationEditorField=Vpe;fe.validateOAuthAuthenticationConfigPlacement=Ux;fe.authenticationToLegacyCredentials=Mx;fe.isRuntimeCredentialMetadataKey=Jpe;fe.resolveCredentialAuthentication=Wpe;fe.getCredentialAuthenticationStorageError=Zpe;fe.buildRuntimeCredentialsFromAuthentication=Kpe;fe.resolveOAuthConfigFromAuthentication=Xpe;fe.toCredentialInputValue=Lb;fe.getCredentialEntries=efe;fe.getCredentialInputValues=tfe;fe.getCredentialDisplayHiddenKeys=rfe;fe.hasOAuthTokenCredentials=nfe;fe.getOAuthExpiryText=ife;fe.hasRuntimeCredentialValues=ofe;fe.validateCredentialObjectKeys=xx;fe.validateCredentialKeyList=Lx;fe.normalizeAskForUserInputs=Px;fe.validateSystemInputCollection=sfe;fe.mapOAuthMissingFieldsForAgent=afe;fe.validateOAuthAuthenticationAndCredentialInputs=cfe;var vt=wn(),hpe=su();fe.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 fg=["host","port","database","path","homeDirectory"],Dx=["type","oauthClientMode","grantType","authUrl","tokenUrl","scopes","clientId","clientSecret","tokenAuthMethod","tokenContentType","usePKCE","extraHeaders","extraBodyParams","protocol",...fg],gpe=new Set(Dx),mpe="type, oauthClientMode, grantType, authUrl, tokenUrl, scopes, clientId, clientSecret, tokenAuthMethod, tokenContentType, usePKCE, extraHeaders, extraBodyParams, protocol, host, port, database, path, homeDirectory",ype=["grantType","authUrl","tokenUrl","scopes","clientId","clientSecret"],Epe={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"]},Ud=["tokenAuthMethod","tokenContentType","usePKCE","extraHeaders","extraBodyParams"],Ipe=new Set(ype),Cpe=new Set(["access_token","accessToken","refresh_token","refreshToken","expires_at","expiresAt","expires_in","expiresIn","expiry","token_type","tokenType"]),bpe=["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"],Qx=new Map(bpe.map((t,e)=>[(0,vt.normalizeCredentialKey)(t),e]));function Oa(t){return Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0))}function Ub({config:t,key:e,value:r}){let n={...t||{}};return yt(r)?n[e]=r:delete n[e],Object.keys(n).length>0?n:void 0}function yt(t){return(0,vt.hasCredentialValue)(t)}function Gt(t){if(yt(t))return typeof t=="string"?t:String(t)}var Spe={"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 Fo(...t){return t.find(e=>yt(e))}function wpe(t){return t===!0||t==="true"}function Bpe(t){let e=t||{},r=Gt(Fo(e.grant_type,e.grantType)),n=r==="client_credentials"?"client_credentials":"authorization_code",i=r&&r!=="authorization_code"&&r!=="client_credentials",o=Fo(e.client_id,e.clientId),s=Fo(e.client_secret,e.clientSecret),a=Fo(e.auth_url,e.authUrl),c=Fo(e.token_url,e.tokenUrl,e.token_uri),u=Fo(e.oauth_cert,e.oauthCert),l=Fo(e.oauth_key,e.oauthKey),d=yt(u)&&yt(l)||e.hasServerSideCertificateCredentials===!0,A=e.hasServerSideClientSecret===!0,p=yt(s)||A,h=wpe(Fo(e.usePKCE,e.usePkce)),g=[];return i&&g.push("grant_type authorization_code or client_credentials"),yt(o)||g.push("client_id"),yt(c)||g.push("token_url"),n==="client_credentials"?!p&&!d&&g.push("client_secret or oauth_cert + oauth_key"):(yt(a)||g.push("auth_url"),!p&&!h&&g.push("client_secret or usePKCE")),{grantType:n,hasAccessToken:yt(Fo(e.access_token,e.accessToken)),hasCertificateCredentials:d,isReadyToConnect:g.length===0,missingFields:g,usePKCE:h}}function Qpe(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 _pe(t){if(!t||t.isReadyToConnect)return null;let e=t.missingFields.map(r=>Spe[r]||r);return`OAuth connection is disabled because ${Qpe(e)} ${e.length===1?"is":"are"} missing.`}function $o(t){if(!(!t||typeof t!="object"||Array.isArray(t)))return t}function uo(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function Md(t){if(yt(t)){if(Array.isArray(t))return t.map(String).filter(Boolean);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 xd(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 xb(t){return t==="managed"||t==="dynamic"||t==="custom"?t:void 0}function vpe(t){let e=Object.entries(t).filter(([r])=>!Ipe.has(r));return e.length>0?Object.fromEntries(e):void 0}function du(t,e,r){for(let i of Epe[r])if(yt(t[i]))return t[i];let n=$o(t.client);return r==="clientId"&&yt(n?.id)?n.id:r==="clientSecret"&&yt(n?.secret)?n.secret:e[r]}function Xt(t){if(!t)return;let e=t;if(e.type==="oauth2"){let r=$o(e.config)||{},n=vpe(r)||{};return Oa({type:"oauth2",oauthClientMode:xb(e.oauthClientMode),grantType:xd(du(e,r,"grantType")),authUrl:Gt(du(e,r,"authUrl")),tokenUrl:Gt(du(e,r,"tokenUrl")),scopes:Md(du(e,r,"scopes")),clientId:Gt(du(e,r,"clientId")),clientSecret:Gt(du(e,r,"clientSecret")),config:Object.keys(n).length>0?n:void 0})}return e.type==="connection_string"?Oa({type:"connection_string",protocol:e.protocol,config:$o(e.config??e.components)}):e.type==="api_key"||e.type==="basic_auth"||e.type==="none"?Oa({type:e.type,config:$o(e.config)}):{type:"none"}}function Dpe({authentication:t,templateManaged:e,templateRegistrationUrl:r}){let n=Xt(t);if(n?.type!=="oauth2")return"custom";let i=n.oauthClientMode;return i?i==="managed"&&!e?"custom":i:r?"dynamic":e&&!n.clientSecret?"managed":"custom"}function Tx(t){let e=Xt(t);if(!e)return;let{config:r,scopes:n,...i}=e,o={};return r&&typeof r=="object"&&Object.assign(o,r),Object.assign(o,i),Array.isArray(n)?o.scopes=n.join(" "):n!==void 0&&(o.scopes=n),o}function Mb(t,e=""){return t==null?t:Array.isArray(t)?t.map(r=>Mb(r)):typeof t=="object"?Object.fromEntries(Object.entries(t).map(([r,n])=>[r,Mb(n,r)])):e&&(0,vt.isSensitiveCredentialKey)(e)?(0,vt.maskCredentialValue)(e,t):t}function Tpe(t){let e=Tx(t);if(e)return Mb(e)}function Rx(t){return(0,vt.isMaskedValue)(t)||(0,vt.isFullyMaskedCredentialValue)(t)}function Rpe(t){let e=$o(t);if(!e)return;let r={};for(let n of Dx){if(!uo(e,n))continue;let i=e[n];i!==void 0&&(r[n]=i)}return r}function kpe(t){return!t||t.type!=="oauth2"||!yt(t.clientSecret)?t:{...t,clientSecret:vt.FULLY_MASKED_CREDENTIAL_VALUE}}function Npe({incoming:t,existing:e}){if(!t||t.type!=="oauth2"||!Rx(t.clientSecret))return t;let r=e?.type==="oauth2"?e.clientSecret:void 0;return{...t,clientSecret:r}}function Ope(t){if(t==="none"||t==="api_key"||t==="basic_auth"||t==="oauth2"||t==="connection_string")return t}function Upe(t){return Object.entries(t||{})}function Mpe(t){let e=fg.flatMap(r=>{if(!uo(t,r))return[];let n=t[r];return yt(n)?[[r,n]]:[]});return e.length>0?Object.fromEntries(e):void 0}function xpe(t){return fg.filter(e=>uo(t,e))}function Lpe(t){let e=fg.flatMap(r=>uo(t,r)?[[r,t[r]]]:[]);return e.length>0?Object.fromEntries(e):void 0}function Ppe(t){let e=new Set(["oauthClientMode","grantType","authUrl","tokenUrl","scopes","clientId","clientSecret",...Ud]);return Object.keys(t).filter(r=>e.has(r))}function kx(t){if(t==null)return{};let e=$o(t);if(!e)return{error:"auth must be an object."};let r=Ope(e.type);if(!r)return{error:"auth.type is required."};let n=Object.keys(e).filter(a=>!gpe.has(a));if(n.length>0)return{error:`Unknown auth field(s): ${n.join(", ")}. Accepted: ${mpe}.`};let i=xpe(e);if(r!=="connection_string"&&i.length>0)return{error:`Connection auth field(s) require auth.type 'connection_string': ${i.join(", ")}.`};let o=Ppe(e);if(r!=="oauth2"&&o.length>0)return{error:`OAuth auth field(s) require auth.type 'oauth2': ${o.join(", ")}.`};if(r!=="oauth2"){let a=Mpe(e);return{authentication:Oa({type:r,protocol:r==="connection_string"?e.protocol:void 0,config:a})}}let s={...Object.fromEntries(Ud.flatMap(a=>{if(!uo(e,a))return[];let c=e[a];return yt(c)?[[a,c]]:[]}))};return{authentication:Oa({type:"oauth2",oauthClientMode:xb(e.oauthClientMode),grantType:xd(e.grantType),authUrl:Gt(e.authUrl),tokenUrl:Gt(e.tokenUrl),scopes:Md(e.scopes),clientId:Gt(e.clientId),clientSecret:Gt(e.clientSecret),config:Object.keys(s).length>0?s:void 0})}}function Ua(t){return t===""||t===null||t===void 0}function Od(t,e,r,n){if(uo(e,r)){if(Ua(e[r])){delete t[n];return}t[n]=Gt(e[r])}}function Fpe(t,e){if(uo(e,"scopes")){if(Ua(e.scopes)){delete t.scopes;return}t.scopes=Md(e.scopes)}}function $pe(t,e){if(uo(e,"grantType")){if(Ua(e.grantType)){delete t.grantType;return}t.grantType=xd(e.grantType)}}function jpe(t,e,r){if(uo(e,r)){if(Ua(e[r])){delete t[r];return}t[r]=e[r]}}function zpe(t,e){if(Ua(e))return;let r=$o(e);if(!r)return t;let n={...t||{}};for(let[i,o]of Object.entries(r))Ua(o)?delete n[i]:n[i]=o;return Object.keys(n).length>0?n:void 0}function qpe(t,e){let r=kx(e);if(r.error)return Xt(t)||{type:"none"};let n=r.authentication||{type:"none"},i=$o(e)||{},o=Xt(t),s=o?.type===n.type;if(n.type!=="oauth2"){let d=Lpe(i),A=s&&o?{...o}:{type:n.type};return n.type==="connection_string"&&uo(i,"protocol")&&(Ua(i.protocol)?delete A.protocol:A.protocol=i.protocol),d&&(A.config=zpe(o?.config,d)),Xt(A)||{type:n.type}}let c={...s&&o?.type==="oauth2"?{...o,config:{...o.config||{}}}:{type:"oauth2",config:{}}};Od(c,i,"oauthClientMode","oauthClientMode"),$pe(c,i),Od(c,i,"authUrl","authUrl"),Od(c,i,"tokenUrl","tokenUrl"),Fpe(c,i),Od(c,i,"clientId","clientId"),Od(c,i,"clientSecret","clientSecret");let l={...c.config||{}};for(let d of Ud)jpe(l,i,d);return c.config=Object.keys(l).length>0?l:void 0,Xt(c)||{type:"oauth2"}}function Nx(t){let e=Xt(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 _x(t,e,r){if(r)for(let[n,i]of Object.entries(r))t.push({path:`${e}.${n}`,label:n,value:i})}function Hpe({authentication:t}){let e=Xt(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 Ud)r.push({path:`oauth2.config.${n}`,label:n,value:e.config?.[n]});for(let[n,i]of Object.entries(e.config||{}))Ud.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}),_x(r,"connection.config",e.config)):_x(r,`${e.type}.config`,e.config);return{type:e.type,authentication:e,configFields:r,hiddenCredentialKeys:Nx(e)}}function Gpe(t){let e=Xt(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 vx(t,e){return(0,vt.hasCredentialValue)(e[t.key])?!0:(t.aliases??[]).some(r=>(0,vt.hasCredentialValue)(e[r]))}function Ox(t,e){return t.optional?!0:t.type==="field"?vx(t.field,e):t.fields.some(r=>vx(r,e))}function Ype(t,e){let r=e||{};return t.some(n=>!Ox(n,r))}function Vpe({authentication:t,path:e,value:r}){let n=Xt(t)||{type:"none"};if(n.type==="oauth2"){if(e==="oauth2.grantType")return{...n,grantType:xd(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:Md(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:Ub({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:Ub({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:Ub({config:n.config,key:o,value:r})}}return n}function Ux({authentication:t,credentials:e}){if(Xt(t)?.type!=="oauth2"||!e||typeof e!="object"||Array.isArray(e))return null;let n=Object.keys(e).filter(i=>fe.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 authenticate_oauth.`}function Mx(t){let e=Xt(t);return e?e.type==="oauth2"?Oa({...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 Jpe(t){return Cpe.has(t.trim())}function Wpe({credential:t,system:e}){return t?.authentication??e?.authentication??void 0}function Zpe(t){let e=Xt(t);return e?.type==="oauth2"&&e.oauthClientMode==="managed"&&e.clientSecret?"Managed OAuth client secrets cannot be stored on credentials":null}function Kpe({authentication:t,credentials:e}){let r=Mx(t);return Xt(t)?.type==="oauth2"?{...e||{},...r}:{...r,...e||{}}}function Xpe({input:t,authentication:e,templateOAuth:r}){let n=Xt(e),i=n?.type==="oauth2"?n:void 0,o=i?.config||{},s=t||{},a=(...c)=>c.find(u=>u!=null);return Oa({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 Lb(t){if(t==null)return"";if(typeof t=="string")return t;let e=JSON.stringify(t);return e===void 0?String(t):e}function efe(t,e={}){let r=new Set((e.hiddenKeys||[]).map(vt.normalizeCredentialKey));return Object.entries(t).filter(([n])=>!r.has((0,vt.normalizeCredentialKey)(n))).sort(([n],[i])=>{let o=Qx.get((0,vt.normalizeCredentialKey)(n))??Number.MAX_SAFE_INTEGER,s=Qx.get((0,vt.normalizeCredentialKey)(i))??Number.MAX_SAFE_INTEGER;if(o!==s)return o-s;let a=(0,vt.isSensitiveCredentialKey)(n),c=(0,vt.isSensitiveCredentialKey)(i);return a!==c?a?-1:1:n.localeCompare(i)}).map(([n,i])=>({key:n,value:Lb(i),isReservedMasked:e.maskAll||(0,vt.isSensitiveCredentialKey)(n)}))}function tfe(t){return Object.fromEntries(Object.entries(t).map(([e,r])=>[e,Lb(r)]))}function rfe({hideOAuthFiles:t=!1,configKeys:e=[]}){return[...e,...t?["oauth_cert","oauth_key"]:[]]}function nfe(t){return yt(t.access_token)||yt(t.refresh_token)}function ife(t){let e=t.expires_at??t.expiry;if(e){let n=(0,hpe.parseUTCDate)(e);if(n)return`Expires ${n.toLocaleString()}`}let r=t.expires_in;return yt(r)?`Expires in ${r} seconds`:null}function ofe(t){return!!(t&&typeof t=="object"&&!Array.isArray(t)&&Object.values(t).some(e=>yt(e)))}function xx(t){if(!t||typeof t!="object"||Array.isArray(t))return null;let e=(0,vt.getInvalidCredentialKeyNames)(Object.keys(t));return e.length===0?null:`${vt.CREDENTIAL_KEY_VALIDATION_DESCRIPTION} Invalid keys: ${e.join(", ")}`}function Lx(t){let e=(0,vt.getInvalidCredentialKeyNames)(t);return e.length===0?null:`${vt.CREDENTIAL_KEY_VALIDATION_DESCRIPTION} Invalid keys: ${e.join(", ")}`}function Px(t){return Array.isArray(t)?[...new Set(t.map(e=>String(e||"").trim()).filter(Boolean))]:[]}function sfe({credentials:t,askForUserInputs:e}){let r=xx(t);if(r)return r;let n=Px(e),i=Lx(n);if(i)return i;if(t&&typeof t=="object"&&!Array.isArray(t))for(let[o,s]of Upe(t)){if(s===""||s===null)return"Blank secret values are not allowed; list secret names to collect from the user in askForUserInputs.";if(n.includes(o))return`Secret name '${o}' cannot be in both credentials and askForUserInputs.`}return null}function afe(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 cfe({authentication:t,credentials:e}){return Ux({authentication:t,credentials:e})}});var oL=m(Wn=>{"use strict";Object.defineProperty(Wn,"__esModule",{value:!0});Wn.bundles=void 0;Wn.buildBundleAgentLaunch=Cfe;Wn.getBundle=bfe;Wn.listBundles=Sfe;Wn.rewriteBundleToolSystemId=wfe;var ufe=yr(),lfe="https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap",dfe="<<(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>`; }>>",Fx="<<() => crypto.randomUUID()>>";function Et(t){return`<?xml version="1.0" encoding="UTF-8"?><request><control><senderid><<sage_intacct_sender_id>></senderid><password><<sage_intacct_sender_password>></password><controlid>${Fx}</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>${dfe}</login></authentication><content><function controlid="${Fx}">${t}</function></content></operation></request>`}function Ss({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 ws=`const esc = (value) => String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&apos;');`,$x="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]; };",jx="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) + '.'); };",zx=`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 Au({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",$b=100,$d=1e4,Cg=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(/\/+$/, ''); }>>`,bg={Authorization:"Bearer <<netsuite_access_token>>",Accept:"application/json"},jb=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) });`,Afe=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);`,qx=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; };`,pfe={type:"integer",minimum:1,maximum:$d,description:`Maximum number of records to return (max ${$d}). Defaults to ${$b}. 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.`},ffe={type:"boolean",description:"Only return active records. Defaults to false (inactive records are included)."},hfe={type:"string",description:"Optional subsidiary internal ID to filter by."},gfe={type:"string",description:"Optional earliest transaction date as YYYY-MM-DD."},mfe={type:"string",description:"Optional latest transaction date as YYYY-MM-DD."},yfe={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},Pd=t=>({input:"activeOnly",kind:"flag",clause:`${t}.isinactive = 'F'`,schema:ffe}),Fd=t=>({input:"subsidiaryId",kind:"id",clause:`${t}.subsidiary = $`,schema:hfe}),Pb=[{input:"fromDate",kind:"date",clause:"t.trandate >= TO_DATE('$', 'YYYY-MM-DD')",schema:gfe},{input:"toDate",kind:"date",clause:"t.trandate <= TO_DATE('$', 'YYYY-MM-DD')",schema:mfe}];function Efe(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 Bs({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) => { ${jb} const where = ${JSON.stringify(a)}; ${u.map(Efe).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 ${$d} 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:pfe,...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:`${Cg}/query/v1/suiteql`,method:"POST",headers:{...bg,"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)) || ${$b}, 1), ${$d}); return page.hasMore !== true || merged >= max; }`}}}],outputTransform:`(sourceData) => { ${Afe} 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)) || ${$b}, 1), ${$d}); 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 wr({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) => { ${jb} 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:yfe},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:`${Cg}${A}`,method:s==="create"?"POST":"PATCH",headers:{...bg,"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) => { ${jb} 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 Hx=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 };`,Gx=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);`,Yx={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},Vx=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."}}),hg=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 gg(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 mg={isInactive:{type:"boolean",description:"Set true to inactivate, false to reactivate."}},yg=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;`,nL={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."}},zb=["AcctPay","AcctRec","Bank","COGS","CredCard","DeferExpense","DeferRevenue","Equity","Expense","FixedAsset","Income","LongTermLiab","NonPosting","OthAsset","OthCurrAsset","OthCurrLiab","OthExpense","OthIncome","Stat","UnbilledRec"],Jx=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;`,Wx={acctNumber:{type:"string",description:"Account number."},acctName:{type:"string",description:"Account name."},acctType:{type:"string",enum:zb,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."},...nL},Zx=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;`,Kx={name:{type:"string",description:"Department name."},parentId:{type:"string",description:"Optional parent department internal ID."},externalId:{type:"string",description:"Optional external ID."},...nL},Eg=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);`,Ig=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."}}),iL=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');`,Xx=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'); ${iL} return item; }) };`,eL={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},tL=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); ${iL} return item; }) };`,rL={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},Ma="Re-running this tool creates another record; it is not idempotent.",Ife=[Bs({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:[Pd("a"),{input:"accountType",kind:"enum",values:zb,clause:"a.accttype = '$'",schema:{type:"string",enum:zb,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) })"}),Bs({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:[Pd("c"),Fd("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) })"}),Bs({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:[Pd("v"),Fd("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) })"}),Bs({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:[...Pb,Fd("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) })"}),Bs({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:[...Pb,Fd("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) })"}),Bs({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:[...Pb,Fd("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) })"}),Bs({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:[Pd("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) })"}),Bs({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:[Pd("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:`${Cg}/query/v1/suiteql`,method:"POST",headers:{...bg,"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) => { ${qx} 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:`${Cg}/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:bg,queryParams:{expandSubResources:"<<(p) => (p.expandSubResources === false || p.expandSubResources === 'false' ? 'false' : 'true')>>"}}}],outputTransform:`(sourceData) => { ${qx} const record = sourceData.getRecord ? sourceData.getRecord.data : undefined; if (!record || typeof record !== 'object') throw new Error('NetSuite returned no record.'); return { record: stripLinks(record) }; }`},wr({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. ${Ma}`,stepId:"createJournalEntry",recordType:"journalentry",mode:"create",properties:{...Vx("create"),lines:{type:"array",description:"Journal lines. Debit and credit totals must balance.",items:Yx}},required:["date","lines"],body:`${Gx} if (!Array.isArray(p.lines) || p.lines.length < 2) throw new Error('lines must contain at least two journal lines.'); ${Hx}`}),wr({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:{...Vx("update"),lines:{type:"array",description:"Optional replacement lines. When set, they replace every existing line and must balance.",items:Yx}},required:[],body:`${Gx} 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.'); ${Hx}`,replaceSublist:{input:"lines",sublist:"line"}}),wr({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. ${Ma}`,stepId:"createVendor",recordType:"vendor",mode:"create",properties:gg("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.'); ${hg}`}),wr({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:{...gg("vendor"),...mg},required:[],body:hg}),wr({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. ${Ma}`,stepId:"createCustomer",recordType:"customer",mode:"create",properties:gg("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.'); ${hg}`}),wr({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:{...gg("customer"),...mg},required:[],body:hg}),wr({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. ${Ma}`,stepId:"createAccount",recordType:"account",mode:"create",properties:Wx,required:["acctName","acctType"],body:`if (!has(p.acctName) || !has(p.acctType)) throw new Error('acctName and acctType are required.'); ${Jx} ${yg}`}),wr({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:{...Wx,...mg},required:[],body:`${Jx} ${yg}`}),wr({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. ${Ma}`,stepId:"createInvoice",recordType:"invoice",mode:"create",properties:{customerId:{type:"string",description:"Customer internal ID."},...Ig("create"),lines:{type:"array",description:"Item lines.",items:eL}},required:["customerId","lines"],body:`if (!Array.isArray(p.lines) || p.lines.length === 0) throw new Error('lines must contain at least one item line.'); ${Eg("customerId")} ${Xx}`}),wr({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."},...Ig("update"),lines:{type:"array",description:"Optional replacement item lines; they replace every existing item line.",items:eL}},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.'); ${Eg("customerId")} ${Xx}`,replaceSublist:{input:"lines",sublist:"item"}}),wr({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. ${Ma}`,stepId:"createVendorBill",recordType:"vendorbill",mode:"create",properties:{vendorId:{type:"string",description:"Vendor internal ID."},referenceNo:{type:"string",description:"Optional vendor invoice reference number."},...Ig("create"),lines:{type:"array",description:"Expense lines.",items:rL}},required:["vendorId","lines"],body:`if (!Array.isArray(p.lines) || p.lines.length === 0) throw new Error('lines must contain at least one expense line.'); ${Eg("vendorId")} if (has(p.referenceNo)) record.tranId = String(p.referenceNo); ${tL}`}),wr({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."},...Ig("update"),lines:{type:"array",description:"Optional replacement expense lines; they replace every existing expense line.",items:rL}},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.'); ${Eg("vendorId")} if (has(p.referenceNo)) record.tranId = String(p.referenceNo); ${tL}`,replaceSublist:{input:"lines",sublist:"expense"}}),wr({id:"netsuite-create-department",name:"Create NetSuite department",shortName:"Create department",instruction:`Creates a department in NetSuite. Without subsidiaryIds NetSuite assigns the parent subsidiary. ${Ma}`,stepId:"createDepartment",recordType:"department",mode:"create",properties:Kx,required:["name"],body:`if (!has(p.name)) throw new Error('name is required.'); ${Zx} ${yg}`}),wr({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:{...Kx,...mg},required:[],body:`${Zx} ${yg}`})],Fb={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:lfe,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 with set_credentials, never as chat text and never via the Credentials 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, call setup_gateway with os windows and enableScriptRunner true (no targets are needed); the user runs the install command in PowerShell opened with 'Run as administrator' on the machine where Sage 100 and Workstation Setup are installed (the gateway must run there, ProvideX.Script is a local 32-bit COM class). The command installs the gateway as a Windows service and the call completes when it connects; never ask for the command or its key in chat. The same setup is in Systems \u2192 Connect system \u2192 Private System \u2192 Set up a gateway. The script runner option 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. Only if the user cannot use that page, fall back to the manual setup: download https://downloads.superglue.cloud/superglue-gateway-windows.exe, 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. If a tunnel is connected but has no runner target, the gateway was set up without the script runner or is an outdated build; have the user set up the gateway again with the option selected, or add the flag and restart. The service runs as the Windows system account: if Sage data is on a mapped drive or a network share that account cannot reach, the connection test fails with a path or access error. When the tunnel with the runner target appears, attach it to this Sage 100 system with tools.writeSystem from superglue (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, never as chat text. 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, call setup_gateway with os windows and enableScriptRunner true (no targets are needed), and tell the user to run the install command in PowerShell opened with "Run as administrator" on the Windows machine where Sage 100 is installed and Workstation Setup has run. The call completes when the gateway connects; never ask for the command or its key in chat. The script runner option 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. If a tunnel is connected but has no runner target, the gateway was set up without the script runner or is an outdated build: have the user set up the gateway again with the option selected. When setup_gateway completes, check that the returned targets include runner, then attach that tunnel to this Sage 100 system with tools.writeSystem from superglue, keeping the URL script://runner/vbs32. Use set_credentials to collect 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 Credentials page and never accept secrets as chat text. 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(`
111
111
  `)}}]}]},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 offer one read-only test run. If the user entered no company credentials during install, the system uses a shared Sage Intacct demo company and works right now. Other users share the demo company, so run create or update tools against it only when the user explicitly asks and confirms the exact records. For their own company, use set_credentials for this system to collect user_id, user_password and company_id, plus optional entity_id when the user wants to target one entity in a multi-entity company. The Web Services sender credentials are already configured. Never send the user to the Credentials page and never accept secrets as chat text. The user id and password are an API user login in the company; company id is the Intacct company id. 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:Et("<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:Ss({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:Et("<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:Ss({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:Et("<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:Ss({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:Et("<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:Ss({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:Et("<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:Ss({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:Et("<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:Ss({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:Et("<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:Ss({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:Et("<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:Ss({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:Et(`<create><GLBATCH><JOURNAL><<(sourceData) => { ${ws} return esc(sourceData.journal || 'GJ'); }>></JOURNAL><BATCH_DATE><<(sourceData) => { ${$x} return toIntacctDate(sourceData.date); }>></BATCH_DATE><BATCH_TITLE><<(sourceData) => { ${ws} return esc(sourceData.title); }>></BATCH_TITLE><ENTRIES><<(sourceData) => { ${ws} ${zx} ${jx} 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:Au({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:Et(`<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) => { ${ws} ${$x} ${zx} ${jx} 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:Au({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:Et(`<create><VENDOR><<(sourceData) => { ${ws} 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:Au({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:Et(`<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) => { ${ws} 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:Au({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:Et(`<create><CUSTOMER><<(sourceData) => { ${ws} 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:Au({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:Et(`<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) => { ${ws} 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:Au({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:Et(`<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:Et(`<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:Et("<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:Et("<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:Et(`<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:Et(`<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:Et(`<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:Et(`<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 set_credentials passing credentials: { api_host: "<their host>" } directly, without askForUserInputs. Then start Microsoft OAuth with authenticate_oauth and substitute the same host into the scopes yourself \u2014 send "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 Credentials page, never ask for a token as chat text, 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"],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 set_credentials for this system to collect environment (their BC environment name, usually production or sandbox) and access_token; never send the user to the Credentials page and never accept secrets as chat text. 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 configured NetSuite system 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 system already has a NetSuite sign-in for this user, 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) and edit the system: url https://<host>.suitetalk.api.netsuite.com/services/rest, authentication 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. Read the system back and confirm no {accountId} remains; never start OAuth while it does. 3) Ask for the client ID and client secret of their NetSuite integration record in chat and store them in the system authentication. If they have no integration record yet, explain: 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. 4) Run authenticate_oauth for this system. OAuth fills access_token; never ask for a token as chat text and never send the user to the Credentials page. 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: how long the sign-in lasts depends on the integration record, and a 401 means signing in again; 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:Ife}};Wn.bundles={...Fb,sage_intacct_mcp:{...Fb.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:{...Fb.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 Cfe({bundle:t,install:e}){let r=e.tools.map(s=>` - ${s.id}${s.name?` (${s.name})`:""}`).join(`
112
112
  `),n=e.system.requiredCredentialKeys.join(", "),i=e.mcpServer?[` - MCP server: ${e.mcpServer.name} (id: ${e.mcpServer.id})`,"","Silently load the systems 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 systems 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: ${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 system is preloaded with a shared demo credential, so every tool works right now without any setup.":"The system already has credentials for this user.":`The system does not have a complete credential set yet, so no tool will run until the user adds the missing values. Required credential keys: ${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(`
113
113
  `)}}function bfe(t){return typeof t!="string"||!Object.prototype.hasOwnProperty.call(Wn.bundles,t)?null:Wn.bundles[t]}function Sfe(){return Object.values(Wn.bundles)}function wfe({tool:t,fromSystemId:e,toSystemId:r}){if(e===r)return t;let n=i=>typeof i=="string"?i.split(`${e}_`).join(`${r}_`):Array.isArray(i)?i.map(n):i&&typeof i=="object"?Object.fromEntries(Object.entries(i).map(([o,s])=>[o,n(s)])):i;return{...t,steps:t.steps.map(i=>{let o=n(i.config);return(0,ufe.isRequestConfig)(o)&&o.systemId===e&&(o.systemId=r),{...i,config:o}}),outputTransform:n(t.outputTransform)}}});var cL=m(Qe=>{"use strict";Object.defineProperty(Qe,"__esModule",{value:!0});Qe.CHAT_VISUAL_FRAME_SOURCE=Qe.CHAT_VISUAL_HOST_SOURCE=Qe.chatVisualFrameMessageSchema=Qe.chatVisualDataRequestSchema=Qe.CHAT_VISUAL_RUN_STATUSES=Qe.CHAT_VISUAL_DATA_METHODS=Qe.CHAT_VISUAL_LIGHT_THEME=Qe.CHAT_VISUAL_THEME_KEYS=Qe.CHAT_VISUAL_CONTENT_SECURITY_POLICY=Qe.CHAT_VISUAL_ALLOWED_ORIGINS=Qe.CHAT_VISUAL_SCRIPT_SOURCES=void 0;Qe.isChatVisualAllowedUrl=Bfe;Qe.hslTripletToHex=Qfe;Qe.buildCustomVisualDocument=Rfe;Qe.detectChatVisualLibraries=Nfe;var ct=pa();Qe.CHAT_VISUAL_SCRIPT_SOURCES=["https://cdn.jsdelivr.net/npm/","https://cdnjs.cloudflare.com/ajax/libs/"];var sL=[...Qe.CHAT_VISUAL_SCRIPT_SOURCES,"https://fonts.googleapis.com/"],aL=[...Qe.CHAT_VISUAL_SCRIPT_SOURCES,"https://fonts.gstatic.com/"];Qe.CHAT_VISUAL_ALLOWED_ORIGINS=["https://cdn.jsdelivr.net","https://cdnjs.cloudflare.com","https://fonts.googleapis.com","https://fonts.gstatic.com"];function Bfe(t){return t.startsWith("data:")||t.startsWith("blob:")||t==="about:blank"?!0:[...sL,...aL].some(e=>t.startsWith(e))}Qe.CHAT_VISUAL_CONTENT_SECURITY_POLICY=["default-src 'none'",`script-src 'unsafe-inline' 'unsafe-eval' blob: ${Qe.CHAT_VISUAL_SCRIPT_SOURCES.join(" ")}`,`style-src 'unsafe-inline' ${sL.join(" ")}`,`font-src data: ${aL.join(" ")}`,`img-src data: blob: ${Qe.CHAT_VISUAL_SCRIPT_SOURCES.join(" ")}`,`connect-src ${Qe.CHAT_VISUAL_SCRIPT_SOURCES.join(" ")}`,"media-src data: blob:","worker-src blob:","frame-src 'none'","child-src 'none'","object-src 'none'","manifest-src 'none'","form-action 'none'","base-uri 'none'"].join("; ");Qe.CHAT_VISUAL_THEME_KEYS=["bg","surface","fg","muted","border","accent","positive","negative","warning","chart-1","chart-2","chart-3","chart-4","chart-5"];function Qfe(t){let e=t.trim().match(/^(-?[\d.]+)\s+([\d.]+)%\s+([\d.]+)%$/);if(!e)return null;let r=Number(e[1])/360,n=Number(e[2])/100,i=Number(e[3])/100,o=i<.5?i*(1+n):i+n-i*n,s=2*i-o,a=c=>{let u=r+c;u<0&&(u+=1),u>1&&(u-=1);let l=u<1/6?s+(o-s)*6*u:u<1/2?o:u<2/3?s+(o-s)*(2/3-u)*6:s;return Math.round(l*255).toString(16).padStart(2,"0")};return`#${a(1/3)}${a(0)}${a(-1/3)}`}Qe.CHAT_VISUAL_LIGHT_THEME={mode:"light",colors:{bg:"#ffffff",surface:"#fafafa",fg:"#18191b",muted:"#5f646d",border:"#e4e5e7",accent:"#007fff",positive:"#10b981",negative:"#dc2626",warning:"#d97706","chart-1":"#007fff","chart-2":"#22c3c3","chart-3":"#a542d7","chart-4":"#e2368c","chart-5":"#28bd73"}};Qe.CHAT_VISUAL_DATA_METHODS=["listRuns","getRun"];Qe.CHAT_VISUAL_RUN_STATUSES=["running","success","failed","aborted"];Qe.chatVisualDataRequestSchema=ct.z.discriminatedUnion("method",[ct.z.object({method:ct.z.literal("listRuns"),params:ct.z.object({toolId:ct.z.string().min(1).max(200).optional(),status:ct.z.enum(Qe.CHAT_VISUAL_RUN_STATUSES).optional(),limit:ct.z.number().int().min(1).max(200).optional(),since:ct.z.string().max(40).optional()}).strict().optional()}),ct.z.object({method:ct.z.literal("getRun"),params:ct.z.object({runId:ct.z.string().min(1).max(200)})})]);Qe.chatVisualFrameMessageSchema=ct.z.discriminatedUnion("type",[ct.z.object({type:ct.z.literal("request"),id:ct.z.number().int().positive(),method:ct.z.enum(Qe.CHAT_VISUAL_DATA_METHODS),params:ct.z.unknown().optional()}),ct.z.object({type:ct.z.literal("resize"),height:ct.z.number().nonnegative()}),ct.z.object({type:ct.z.literal("error"),message:ct.z.string().max(2e3)})]);Qe.CHAT_VISUAL_HOST_SOURCE="superglue-visual-host";Qe.CHAT_VISUAL_FRAME_SOURCE="superglue-visual";var _fe={listRuns:{runs:[],total:0},getRun:null};function vfe(t){return`:root{${Qe.CHAT_VISUAL_THEME_KEYS.map(r=>`--sg-${r}:${t.colors[r]};`).join("")}--sg-font:"Inter",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;--sg-mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace;--sg-radius:12px;color-scheme:${t.mode};}`}var Dfe="html,body{margin:0;padding:0;background:transparent;color:var(--sg-fg);font:14px/1.5 var(--sg-font);-webkit-font-smoothing:antialiased;}*,*::before,*::after{box-sizing:border-box;}";function Tfe(t){return`(function(){
@@ -1856,7 +1856,7 @@ ${s}`;return}if(Gy(e,i,QNe)){_Ne(e,o)&&(r.retry=e.toString("utf8",o));return}if(
1856
1856
  `);t.stack=r?`${r}
1857
1857
  ${o}`:i.stack}Z.exports.fetch=function(e,r=void 0){return sOe(e,r).catch(n=>{throw TY?OY(n,TY):n&&typeof n=="object"&&Error.captureStackTrace(n,Z.exports.fetch),n})};Z.exports.Headers=yc().Headers;Z.exports.Response=JA().Response;Z.exports.Request=Ku().Request;Z.exports.FormData=hm().FormData;var{setGlobalOrigin:aOe,getGlobalOrigin:cOe}=Ow();Z.exports.setGlobalOrigin=aOe;Z.exports.getGlobalOrigin=cOe;var{CacheStorage:uOe}=yG(),{kConstruct:lOe}=Ge();Z.exports.caches=new uOe(lOe);var{deleteCookie:dOe,getCookies:AOe,getSetCookies:pOe,setCookie:fOe,parseCookie:hOe}=TG();Z.exports.deleteCookie=dOe;Z.exports.getCookies=AOe;Z.exports.getSetCookies=pOe;Z.exports.setCookie=fOe;Z.exports.parseCookie=hOe;var{parseMIMEType:gOe,serializeAMimeType:mOe}=Tn();Z.exports.parseMIMEType=gOe;Z.exports.serializeAMimeType=mOe;var{CloseEvent:yOe,ErrorEvent:EOe,MessageEvent:IOe}=Oy(),{WebSocket:COe,ping:bOe}=uY();Z.exports.WebSocket=COe;Z.exports.CloseEvent=yOe;Z.exports.ErrorEvent=EOe;Z.exports.MessageEvent=IOe;Z.exports.ping=bOe;Z.exports.WebSocketStream=mY().WebSocketStream;Z.exports.WebSocketError=fv().WebSocketError;Z.exports.request=ap(ll.request);Z.exports.stream=ap(ll.stream);Z.exports.pipeline=ap(ll.pipeline);Z.exports.connect=ap(ll.connect);Z.exports.upgrade=ap(ll.upgrade);Z.exports.MockClient=VNe;Z.exports.MockCallHistory=JNe;Z.exports.MockCallHistoryLog=WNe;Z.exports.MockPool=KNe;Z.exports.MockAgent=ZNe;Z.exports.SnapshotAgent=XNe;Z.exports.mockErrors=eOe;var{EventSource:SOe}=DY();Z.exports.EventSource=SOe;function wOe(){globalThis.fetch=Z.exports.fetch,globalThis.Headers=Z.exports.Headers,globalThis.Response=Z.exports.Response,globalThis.Request=Z.exports.Request,globalThis.FormData=Z.exports.FormData,globalThis.WebSocket=Z.exports.WebSocket,globalThis.CloseEvent=Z.exports.CloseEvent,globalThis.ErrorEvent=Z.exports.ErrorEvent,globalThis.MessageEvent=Z.exports.MessageEvent,globalThis.EventSource=Z.exports.EventSource}Z.exports.install=wOe});var xY=m(Al=>{"use strict";Object.defineProperty(Al,"__esModule",{value:!0});Al.SuperglueClient=Al.SuperglueHttpError=void 0;var dl=yr(),Pn=Hb(),BOe=TS(),QOe=VP(),_Oe=wn(),is=su(),vOe=kd(),up=14400*1e3,cp;if(typeof globalThis.process<"u"&&globalThis.process.versions?.node)try{let{Agent:t}=UY();cp=new t({headersTimeout:up,bodyTimeout:up})}catch{}function MY(t){if(t?.aborted)throw t.reason??new DOMException("Aborted","AbortError")}var Jy=class extends Error{constructor(e,r,n,i){super(e),this.status=r,this.code=n,this.details=i,this.name="SuperglueHttpError"}};Al.SuperglueHttpError=Jy;var Iv=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 BOe.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;MY(r);let o=await this.refreshToken();return MY(r),!o||o===n?i:(i.body?.cancel(),e(o))}isInfrastructureError(e){return(0,_Oe.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 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=d=>{let A={Authorization:`Bearer ${d}`,...i};return a&&!c&&e!=="GET"&&(A["Content-Type"]="application/json"),fetch(s,{...o,method:e,headers:A,body:a?c?n:JSON.stringify(n):void 0,signal:o?.signal??AbortSignal.timeout(up),...cp?{dispatcher:cp}:{}})},l;try{l=await this.fetchWithAuthRetry(u,o?.signal)}catch(d){throw this.isInfrastructureError(d)&&this.onInfrastructureError?.(),d}if(!l.ok)throw await this.buildHttpError(l);return l}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:A.contentType?{"Content-Type":A.contentType}:void 0,signal:AbortSignal.timeout(Math.min(up,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 Jy(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(up),...cp?{dispatcher:cp}:{}}),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,QOe.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(await this.restRequest("GET",`/v1/memory-notes${n?`?${n}`:""}`)).data}async createMemoryNote(e){return(await this.restRequest("POST","/v1/memory-notes",e)).data}async updateMemoryNote(e,r){return(await this.restRequest("PATCH",`/v1/memory-notes/${encodeURIComponent(e)}`,r)).data}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,options:s,runId:a,systemIds:c,credentialId:u,systemAuth:l,createRun:d,parentToolId:A,stepIndex:p,stepId:h,signal:g,stream:S}){let B={step:e,payload:r,files:n,previousResults:i,credentials:o,options:s,runId:a,systemIds:c,credentialId:u,systemAuth:l,createRun:d,parentToolId:A,stepIndex:p,stepId:h};return S?this.streamRequest("/v1/tools/step/run",B,g):this.restRequest("POST","/v1/tools/step/run",B,void 0,g?{signal:g}: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,is.toUTCISOString)(c,"run.startedAt"),completedAt:(0,is.toUTCISOString)(u,"run.completedAt"),executionKind:l,parentToolId:d,draftId:A})}async checkRunLimit(){return(await this.restRequest("POST","/v1/runs/check-limit")).data}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:dl.RunStatus.RUNNING,success:dl.RunStatus.SUCCESS,failed:dl.RunStatus.FAILED,aborted:dl.RunStatus.ABORTED};return{runId:e.runId??e.id,toolId:e.toolId,tool:e.tool,systemIds:e.systemIds,status:r[e.status]??dl.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??dl.RunExecutionKind.FULL},fileArtifacts:e.fileArtifacts}}mapOpenAPIScheduleToToolSchedule(e){return{...e,lastRunAt:e.lastRunAt?(0,is.requireUTCDate)(e.lastRunAt,"schedule.lastRunAt"):void 0,nextRunAt:(0,is.requireUTCDate)(e.nextRunAt,"schedule.nextRunAt"),createdAt:(0,is.requireUTCDate)(e.createdAt,"schedule.createdAt"),updatedAt:(0,is.requireUTCDate)(e.updatedAt,"schedule.updatedAt")}}async listRuns(e={}){let r=(0,Pn.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,is.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,is.toUTCISOString)(e.from,"activity.from"):e.from),e?.to&&r.set("to",e.to instanceof Date?(0,is.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,Pn.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,Pn.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,Pn.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,Pn.listAllPages)((r,n)=>this.listProjectSummaries({page:r,limit:n,...e!==void 0?{includeArchived:e}:{}}))}async listAllProjectTasks(e){return(0,Pn.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(await this.restRequest(r?"PATCH":"POST",i,n)).data}async listSchedules(e={}){let r=(0,Pn.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,Pn.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,vOe.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 listCredentials(e={}){let r=(0,Pn.createListQueryParams)(e);e.systemId!==void 0&&r.set("systemId",e.systemId);let n=r.size>0?`?${r.toString()}`:"";return this.restRequest("GET",`/v1/credentials${n}`)}async listAllCredentials(e={}){return(0,Pn.listAllPages)((r,n)=>this.listCredentials({...e,page:r,limit:n}))}async createCredentials(e){return(await this.restRequest("POST","/v1/credentials",e)).data}async replaceCredentials(e,r){return(await this.restRequest("PUT",`/v1/credentials/${encodeURIComponent(e)}`,{credentials:r})).data}async updateCredentials(e,r){return(await this.restRequest("PATCH",`/v1/credentials/${encodeURIComponent(e)}`,r)).data}async deleteCredentials(e){await this.restRequest("DELETE",`/v1/credentials/${encodeURIComponent(e)}`)}async setDefaultCredentials(e){await this.restRequest("POST",`/v1/credentials/${encodeURIComponent(e)}/default`)}async listSystems(e={}){let r=(0,Pn.createListQueryParams)(e),n=r.size>0?`?${r.toString()}`:"";return this.restRequest("GET",`/v1/systems${n}`)}async listAllSystems(e={}){return(0,Pn.listAllPages)((r,n)=>this.listSystems({...e,page:r,limit:n}))}async getSystem(e){return(await this.restRequest("GET",`/v1/systems/${encodeURIComponent(e)}`)).data}async createSystem(e){return(await this.restRequest("POST","/v1/systems",e)).data}async updateSystem(e,r){return(await this.restRequest("PATCH",`/v1/systems/${encodeURIComponent(e)}`,r)).data}async deleteSystem(e){return await this.restRequest("DELETE",`/v1/systems/${encodeURIComponent(e)}`),!0}async bulkDeleteSystems(e){return this.restRequest("POST","/v1/systems/bulk/delete",{ids:e})}async listManagedOAuthTemplateIds(){return(await this.restRequest("GET","/v1/oauth2/managed-apps")).data.templateIds}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 searchSystemDocumentation(e,r){return(await this.restRequest("POST",`/v1/systems/${encodeURIComponent(e)}/documentation/search`,{keywords:r})).data}async triggerSystemDocumentationScrapeJob(e,r){return(await this.restRequest("POST",`/v1/systems/${encodeURIComponent(e)}/documentation/scrape`,r)).data}async fetchOpenApiSpec(e,r,n){return(await this.restRequest("POST",`/v1/systems/${encodeURIComponent(e)}/documentation/openapi`,{url:r,link:n?.link})).data}async uploadSystemDocumentationFiles(e,r,n){let i=await this.uploadFiles(r,{process:!0}),o=i.flatMap(s=>s.status==="uploaded"?[s.id]:[]);if(o.length>0)try{await this.restRequest("POST",`/v1/systems/${encodeURIComponent(e)}/documentation/files`,{fileIds:o,link:n?.link!==!1})}catch(s){throw await Promise.all(o.map(a=>this.deleteFileUpload(a).catch(()=>{}))),s}if(!n?.settle){let s=i.filter(a=>a.status==="failed");if(s.length>0)throw new Error(s.map(a=>a.error).join("; "))}return i}async listSystemDocumentationFiles(e,r){let n=new URLSearchParams;r?.length&&n.set("fileIds",r.join(","));let i=n.size>0?`?${n.toString()}`:"";return(await this.restRequest("GET",`/v1/systems/${encodeURIComponent(e)}/documentation/files${i}`)).data}async getSystemDocumentationFileContent(e,r,n){return(await this.restRequest("GET",`/v1/systems/${encodeURIComponent(e)}/documentation/files/${encodeURIComponent(r)}/content?processed=${n.processed}`)).data}async deleteSystemDocumentationFile(e,r){await this.restRequest("DELETE",`/v1/systems/${encodeURIComponent(e)}/documentation/files/${encodeURIComponent(r)}`)}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}}}};Al.SuperglueClient=Iv});var PY=m(pt=>{"use strict";Object.defineProperty(pt,"__esModule",{value:!0});pt.UnquotedKeyStrategy=pt.TripleQuoteStrategy=pt.TrailingCommaStrategy=pt.SingleQuoteStrategy=pt.PythonLiteralStrategy=pt.CommentStrategy=pt.ResilientJsonParser=pt.RepairStrategy=void 0;pt.parseJsonResilient=DOe;pt.parseJSON=TOe;pt.isValidJson=ROe;pt.prettyPrintJson=kOe;pt.minifyJson=NOe;var ii=class{validate(e){try{return JSON.parse(e),!0}catch{return!1}}};pt.RepairStrategy=ii;var Wy=class extends ii{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")}"`})}};pt.TripleQuoteStrategy=Wy;var Zy=class extends ii{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")}};pt.PythonLiteralStrategy=Zy;var Ky=class extends ii{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")}};pt.TrailingCommaStrategy=Ky;var Xy=class extends ii{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}};pt.SingleQuoteStrategy=Xy;var eE=class extends ii{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')}};pt.UnquotedKeyStrategy=eE;var tE=class extends ii{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}};pt.CommentStrategy=tE;var Cv=class extends ii{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`
1858
1858
  `: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}},bv=class extends ii{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}},pl=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 Wy,new Xy,new Cv,new bv,new Zy,new Ky,new eE,new tE]}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)}};pt.ResilientJsonParser=pl;var LY=new pl;function DOe(t,e){return(e?new pl(e):LY).parse(t)}function TOe(t){let e=LY.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 ROe(t){try{return JSON.parse(t),!0}catch{return!1}}function kOe(t,e=2){return JSON.stringify(t,null,e)}function NOe(t){let r=new pl().parse(t);if(r.success)return JSON.stringify(r.data);throw new Error("Cannot minify invalid JSON")}});var gr=m(K=>{"use strict";var OOe=K&&K.__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]})),ce=K&&K.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&OOe(e,t,r)};Object.defineProperty(K,"__esModule",{value:!0});K.SSELogSubscriptionManager=K.SuperglueHttpError=K.SuperglueClient=void 0;ce(XM(),K);ce(nx(),K);ce(hx(),K);ce(mx(),K);ce(bx(),K);ce(Sx(),K);ce(Bx(),K);ce(Ld(),K);ce(oL(),K);ce(SI(),K);ce(cL(),K);ce(uL(),K);ce(lL(),K);ce(dL(),K);ce(Hb(),K);ce(pL(),K);ce(gL(),K);ce(mL(),K);ce(yL(),K);ce(Vb(),K);ce(Kb(),K);ce(IL(),K);ce(CL(),K);ce(SL(),K);ce(rh(),K);ce(BL(),K);ce(QL(),K);ce(vL(),K);ce(DL(),K);ce(kL(),K);ce(YL(),K);ce(cS(),K);ce(zd(),K);ce(aS(),K);ce(KL(),K);ce(eP(),K);ce(rP(),K);ce(Tb(),K);ce(AP(),K);ce(fP(),K);ce(Ag(),K);ce(_P(),K);ce(NP(),K);ce(OP(),K);ce(QS(),K);ce(LP(),K);ce(PP(),K);ce(zP(),K);ce(HP(),K);ce(yr(),K);ce(wn(),K);ce(GP(),K);ce(YP(),K);ce(vg(),K);ce(su(),K);ce(kd(),K);var FY=xY();Object.defineProperty(K,"SuperglueClient",{enumerable:!0,get:function(){return FY.SuperglueClient}});Object.defineProperty(K,"SuperglueHttpError",{enumerable:!0,get:function(){return FY.SuperglueHttpError}});var UOe=TS();Object.defineProperty(K,"SSELogSubscriptionManager",{enumerable:!0,get:function(){return UOe.SSELogSubscriptionManager}});ce(PY(),K)});var PE=require("commander");var kr=ge(require("fs")),zY=ge(require("os")),os=ge(require("path")),lp=ge(gr()),$Y=new Set(["runner","builder","admin"]),jY={output:{mode:"stdout",directory:".superglue/output"},preset:"admin"};function ss(t){let e=os.join(process.cwd(),".superglue"),r=zY.homedir();if(!r)return e;let n=os.join(r,".superglue");return t===!0?e:t===!1?n:kr.existsSync(os.join(e,"config.json"))?e:n}function Sv(t){return os.join(ss(t),"config.json")}function rE(t){let e=Sv(t);if(!kr.existsSync(e))return{};try{return JSON.parse(kr.readFileSync(e,"utf-8"))}catch{return{}}}function fl(t){let e=rE(),r=t.apiKey||(0,lp.readProcessEnvironmentValue)("SUPERGLUE_API_KEY")||e.apiKey||"",n=t.endpoint||(0,lp.readProcessEnvironmentValue)("SUPERGLUE_API_ENDPOINT")||e.endpoint||"https://api.superglue.cloud",i=(0,lp.readProcessEnvironmentValue)("SUPERGLUE_WEB_ENDPOINT")||e.webEndpoint||n.replace(/:3002\b/,":3001").replace(/api\.superglue/,"app.superglue"),o=(0,lp.readProcessEnvironmentValue)("SUPERGLUE_CLI_PRESET"),s=o&&$Y.has(o)?o:e.preset&&$Y.has(e.preset)?e.preset:"admin";return{...jY,...e,apiKey:r,endpoint:n,webEndpoint:i,preset:s,output:{...jY.output,...e.output}}}function nE(t,e){let r=ss(e);kr.existsSync(r)||kr.mkdirSync(r,{recursive:!0}),kr.writeFileSync(os.join(r,"config.json"),JSON.stringify(t,null,2)+`
1859
- `,{mode:384})}function iE(t,e){let r=os.join(ss(e),"drafts");if(kr.existsSync(r)||kr.mkdirSync(r,{recursive:!0}),t.output.mode==="stdout+file"){let n=os.resolve(t.output.directory);kr.existsSync(n)||kr.mkdirSync(n,{recursive:!0})}}var Tv=ge(gr());var wv=ge(require("readline"));var GY=require("child_process"),YY=require("util");var qY={name:"@superglue/cli",version:"1.1.191",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 xOe=(0,YY.promisify)(GY.exec),mr=qY.version;function HY(t){let e=t.match(/^(\d+)(?:-(.+))?$/);return e?{numeric:parseInt(e[1],10),prerelease:e[2]||null}:{numeric:0,prerelease:t}}function sE(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=HY(r[o]||"0"),a=HY(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 aE(){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 oE=null;function VY(){se()&&(oE=aE())}async function JY(){if(!(!se()||!oE)){try{let t=new Promise(r=>{setTimeout(()=>r(null),2e3).unref()}),e=await Promise.race([oE,t]);e&&sE(mr,e)<0&&(console.error(""),console.error(`${E.cyan}${E.bold} Update available: ${mr} \u2192 ${e}${E.reset}`),console.error(`${E.cyan} Run ${E.bold}sg update${E.reset}${E.cyan} to upgrade${E.reset}`),console.error(""))}catch{}oE=null}}async function WY(){let t=await aE();if(!t)return{success:!1,message:"Could not fetch latest version from npm"};if(sE(mr,t)>=0)return{success:!0,message:`Already on latest version (${mr})`};try{return await xOe("npm install -g @superglue/cli@latest"),{success:!0,message:`Updated from ${mr} to ${t}`}}catch(e){return{success:!1,message:`Update failed: ${e.message}. Try manually: npm install -g @superglue/cli@latest`}}}var se=()=>process.argv.includes("--table")&&process.stdout.isTTY,Nr=()=>process.argv.includes("--full"),E={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 ZY(t,e){let r=e||t;return`\x1B]8;;${t}\x07${E.underline}${E.cyan}${r}${E.reset}\x1B]8;;\x07`}function KY(){if(!se())return;let t=E.reset,e=E.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${mr}${t}`),console.log("")}function lt(t){if(!se())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 ${E.cyan}${e[r++%e.length]}${E.reset} ${n}`)},s=setInterval(o,80);return{update:a=>{n=a},log:a=>{i(),console.log(` ${E.dim}\u2502${E.reset} ${a}`),o()},stop:a=>{clearInterval(s),i(),a&&console.log(` ${a}`)}}}function ee(t){se()?cE(t):console.log(JSON.stringify(t,null,2))}function ve(t,e){se()?(console.log(` ${E.green}\u2713${E.reset} ${t}`),e&&cE(e,4)):console.log(JSON.stringify({success:!0,message:t,...e&&typeof e=="object"?e:{data:e}}))}function D(t,e){se()?(console.error(` ${E.red}\u2717${E.reset} ${t}`),e&&cE(e,4)):console.error(JSON.stringify({success:!1,error:t,details:e}))}function XY(t){se()&&console.log(` ${E.yellow}\u26A0${E.reset} ${t}`)}function sr(t){se()&&console.log(` ${E.dim}${t}${E.reset}`)}function as(t){se()&&(console.log(`
1859
+ `,{mode:384})}function iE(t,e){let r=os.join(ss(e),"drafts");if(kr.existsSync(r)||kr.mkdirSync(r,{recursive:!0}),t.output.mode==="stdout+file"){let n=os.resolve(t.output.directory);kr.existsSync(n)||kr.mkdirSync(n,{recursive:!0})}}var Tv=ge(gr());var wv=ge(require("readline"));var GY=require("child_process"),YY=require("util");var qY={name:"@superglue/cli",version:"1.1.192",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 xOe=(0,YY.promisify)(GY.exec),mr=qY.version;function HY(t){let e=t.match(/^(\d+)(?:-(.+))?$/);return e?{numeric:parseInt(e[1],10),prerelease:e[2]||null}:{numeric:0,prerelease:t}}function sE(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=HY(r[o]||"0"),a=HY(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 aE(){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 oE=null;function VY(){se()&&(oE=aE())}async function JY(){if(!(!se()||!oE)){try{let t=new Promise(r=>{setTimeout(()=>r(null),2e3).unref()}),e=await Promise.race([oE,t]);e&&sE(mr,e)<0&&(console.error(""),console.error(`${E.cyan}${E.bold} Update available: ${mr} \u2192 ${e}${E.reset}`),console.error(`${E.cyan} Run ${E.bold}sg update${E.reset}${E.cyan} to upgrade${E.reset}`),console.error(""))}catch{}oE=null}}async function WY(){let t=await aE();if(!t)return{success:!1,message:"Could not fetch latest version from npm"};if(sE(mr,t)>=0)return{success:!0,message:`Already on latest version (${mr})`};try{return await xOe("npm install -g @superglue/cli@latest"),{success:!0,message:`Updated from ${mr} to ${t}`}}catch(e){return{success:!1,message:`Update failed: ${e.message}. Try manually: npm install -g @superglue/cli@latest`}}}var se=()=>process.argv.includes("--table")&&process.stdout.isTTY,Nr=()=>process.argv.includes("--full"),E={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 ZY(t,e){let r=e||t;return`\x1B]8;;${t}\x07${E.underline}${E.cyan}${r}${E.reset}\x1B]8;;\x07`}function KY(){if(!se())return;let t=E.reset,e=E.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${mr}${t}`),console.log("")}function lt(t){if(!se())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 ${E.cyan}${e[r++%e.length]}${E.reset} ${n}`)},s=setInterval(o,80);return{update:a=>{n=a},log:a=>{i(),console.log(` ${E.dim}\u2502${E.reset} ${a}`),o()},stop:a=>{clearInterval(s),i(),a&&console.log(` ${a}`)}}}function ee(t){se()?cE(t):console.log(JSON.stringify(t,null,2))}function ve(t,e){se()?(console.log(` ${E.green}\u2713${E.reset} ${t}`),e&&cE(e,4)):console.log(JSON.stringify({success:!0,message:t,...e&&typeof e=="object"?e:{data:e}}))}function D(t,e){se()?(console.error(` ${E.red}\u2717${E.reset} ${t}`),e&&cE(e,4)):console.error(JSON.stringify({success:!1,error:t,details:e}))}function XY(t){se()&&console.log(` ${E.yellow}\u26A0${E.reset} ${t}`)}function sr(t){se()&&console.log(` ${E.dim}${t}${E.reset}`)}function as(t){se()&&(console.log(`
1860
1860
  ${E.bold}${E.cyan}${t}${E.reset}`),console.log(` ${E.dim}${"\u2500".repeat(t.length)}${E.reset}`))}function Or(t,e,r){if(!se()){console.log(JSON.stringify({success:!0,total:r?.total??t.length,items:t}));return}if(t.length===0){console.log(`
1861
1861
  ${E.dim}0 results${E.reset}
1862
1862
  `);return}let n=e||Object.keys(t[0]),i=Nr()?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)=>`${E.bold}${E.cyan}${l.toUpperCase().padEnd(o[d])}${E.reset}`).join(" ");console.log(` ${s}`);let a=o.map(l=>`${E.dim}${"\u2500".repeat(l)}${E.reset}`).join(`${E.dim}\u2500\u2500${E.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))+`${E.dim}${S}${E.reset}`}return A==="status"?`${{success:E.green,running:E.yellow,failed:E.red,aborted:E.red,error:E.red,pending:E.dim}[h.toLowerCase()]||""}${h.padEnd(o[p])}${E.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(`