@membranehq/cli 1.4.5 → 1.4.7

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.
Files changed (2) hide show
  1. package/dist/index.js +31 -31
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,24 +1,24 @@
1
1
  #!/usr/bin/env node
2
- var xn=Object.defineProperty;var c=(r,e)=>xn(r,"name",{value:e,configurable:!0});import*as v from"node:fs";import{mkdirSync as In,writeFileSync as $n,readFileSync as kn}from"node:fs";import*as x from"node:path";import{join as Me,dirname as Rn}from"node:path";import{URL as Pn,fileURLToPath as An}from"node:url";import w from"chalk";import{Command as Dn}from"commander";import{WorkspaceElementType as T,MembraneConfigLoader as On,MembraneAxiosInstance as Nn,MembraneClient as xt,extractMembraneErrorData as J,WorkspaceElementSpecs as V,WorkspaceSyncEventType as Mn,ConnectorFileUpdateType as Fe,CONSOLE_ACCOUNT_API_TOKEN_PATH as Fn,NotFoundError as Ln,getMembraneElementPath as jn,parseMembraneElementPath as ie,CONNECTOR_VERSION_DEVELOPMENT as It,compareWorkspaceExports as Un,WorkspaceElementChangeType as Y,setValueAtLocator as Le,getDataCollectionCreateFields as je,excludeWriteOnlyFieldsFromSchema as $t,valueToSchema as xe,getRequiredFieldsFromSchema as Kn,getValueAtLocator as qn,walkSchema as kt,makeDataLocationPath as Rt,getDataCollectionUpdateFields as Ue}from"@membranehq/sdk";import Ke from"lodash/camelCase.js";import qe from"lodash/upperFirst.js";import Bn from"code-block-writer";import _n from"lodash/uniqBy.js";import se,{createContext as Be,useState as D,useEffect as he,useContext as _e,useId as Wn,useRef as We,useLayoutEffect as Ie,useMemo as Jn}from"react";import{Box as g,Text as y,useInput as ae,render as Je,Newline as Gn}from"ink";import{jsx as u,jsxs as b,Fragment as $e}from"react/jsx-runtime";import Pt from"swr/immutable";import At from"os";import I from"path";import Hn from"conf";import ge,{isAxiosError as zn}from"axios";import Ge from"jsonwebtoken";import{AsyncLocalStorage as Vn}from"async_hooks";import{toSentenceCase as Yn}from"js-convert-case";import Zn from"lodash/isEqual.js";import G from"js-yaml";import*as Xn from"node:crypto";import{createHash as Qn}from"node:crypto";import er from"chokidar";import tr from"yaml";import{EventEmitter as nr}from"events";import{EventSource as rr}from"eventsource";import P from"fs";import Dt from"archiver";import Ot from"form-data";import ke from"unzipper";import*as or from"node:os";import"node:events";import Nt from"ink-text-input";import{SWRConfig as ir}from"swr";import Re from"ink-spinner";import{TextInput as sr,Select as ar,Spinner as cr}from"@inkjs/ui";import{FastMCP as lr}from"fastmcp";import{z as A}from"zod";import Mt from"semver";import Ft from"ora";import Lt from"jszip";import{minimatch as ur}from"minimatch";import{exec as dr}from"node:child_process";import He from"lodash/merge.js";import hr from"@anthropic-ai/sdk";import{faker as ye}from"@faker-js/faker";import pr from"lodash/template.js";import fr from"lodash/templateSettings.js";function ce(r){if(r.type){if(Array.isArray(r.type))return{anyOf:r.type.map(t=>ce({...r,type:t}))};if(r.type==="array"){const t={type:"array",items:r.items?ce(r.items):{type:"object"}};return r.title&&(t.title=r.title),r.description&&(t.description=r.description),r.minItems!==void 0&&(t.minItems=r.minItems),r.maxItems!==void 0&&(t.maxItems=r.maxItems),r.uniqueItems!==void 0&&(t.uniqueItems=r.uniqueItems),t}}const e={};if(r.type&&!Array.isArray(r.type)&&(e.type=r.type),r.title&&(e.title=r.title),r.description&&(e.description=r.description),r.format&&(e.format=r.format),r.enum&&(e.enum=r.enum),r.default!==void 0&&(e.default=r.default),r.minimum!==void 0&&(e.minimum=r.minimum),r.maximum!==void 0&&(e.maximum=r.maximum),r.minLength!==void 0&&(e.minLength=r.minLength),r.maxLength!==void 0&&(e.maxLength=r.maxLength),r.maxItems!==void 0&&(e.maxItems=r.maxItems),r.readOnly!==void 0&&(e.readOnly=r.readOnly),r.writeOnly!==void 0&&(e.writeOnly=r.writeOnly),r.examples&&r.examples.length>0&&(e.example=r.examples[0]),r.properties){e.properties={};for(const[t,n]of Object.entries(r.properties))e.properties[t]=ce(n)}return r.anyOf&&(e.anyOf=r.anyOf.map(ce)),r.additionalProperties!==void 0&&(typeof r.additionalProperties=="boolean"?e.additionalProperties=r.additionalProperties:e.additionalProperties=ce(r.additionalProperties)),r.required&&(e.required=r.required),e}c(ce,"convertDataSchemaToOpenAPI");function mr(r){const{membraneInterfaces:{actions:e}}=r,t=gr(e);return JSON.stringify({openapi:"3.0.0",info:{title:"Membrane Actions API",version:"1.0.0",description:"Generated OpenAPI specification for Membrane actions"},paths:{},components:{schemas:t}},null,2)}c(mr,"generateOpenAPIContent");function gr(r){const e={};return r.forEach(t=>{const n=qe(Ke(t.key)),o={type:"object",properties:{id:{type:"string",description:"Request ID"},action:{type:"string",enum:[t.key]}},required:["id","action"]};if(t?.inputSchema){const a=ce(t.inputSchema);a.properties&&(o.properties={...o.properties,...a.properties}),a.required&&(o.required=[...o.required||[],...a.required])}e[`${n}Request`]=o;const i={type:"object",properties:{id:{type:"string",description:"Response ID"},success:{type:"boolean"},data:{type:"object"}},required:["id","success"]},s=t?.customOutputSchema||t?.outputSchema;if(s){const a=ce(s);i.properties={...i.properties,data:a}}e[`${n}Response`]=i}),e}c(gr,"generateOpenAPISchemas");function yr(r){const{membraneInterfaces:{actions:e}}=r,t=_n(e,"key"),n=new Bn({indentNumberOfSpaces:2,newLine:`
3
- `});return n.writeLine("// Generated TypeScript definitions for Membrane actions"),n.newLine(),n.writeLine("import type {"),n.writeLine(" ActionAccessor,"),n.writeLine(" ConnectionLevelActionAccessor,"),n.writeLine('} from "@membranehq/sdk";'),n.newLine(),wr(n,t),n.toString()}c(yr,"generateTypeScriptContent");function wr(r,e){r.writeLine('declare module "@membranehq/sdk" {'),r.indent(()=>{e.forEach(t=>{const n=Ve(t),o=t?.inputSchema;Pe(r,{interfaceName:n,properties:o?.properties,required:o?.required||[]});const i=Ye(t),s=t?.customOutputSchema||t?.outputSchema;Pe(r,{interfaceName:i,properties:s?.properties,required:s?.required||[],fallbackContent:"result: unknown"}),r.newLine()}),Pe(r,{interfaceName:"MembraneClient",methods:e.map(t=>{const n=Ve(t),o=Ye(t);return{name:"action",parameters:`selector: "${t.key}"`,returnType:`ActionAccessor<${n}, ${o}>`}})}),r.newLine(),Pe(r,{interfaceName:"ConnectionAccessor",methods:e.map(t=>{const n=Ve(t),o=Ye(t);return{name:"action",parameters:`selector: "${t.key}"`,returnType:`ConnectionLevelActionAccessor<${n}, ${o}>`}})})}),r.writeLine("}")}c(wr,"generateModuleAugmentation");function Pe(r,e){const{interfaceName:t,properties:n,required:o=[],methods:i,fallbackContent:s}=e;r.writeLine(`interface ${t} {`),r.indent(()=>{n&&Object.keys(n).length>0&&Cr(r,n,o),i&&i.length>0&&(n&&Object.keys(n).length>0&&r.newLine(),i.forEach((a,l)=>{r.writeLine(`${a.name}(${a.parameters}): ${a.returnType};`),l<i.length-1&&r.newLine()})),s&&(!n||Object.keys(n).length===0)&&(!i||i.length===0)&&r.writeLine(s)}),r.writeLine("}")}c(Pe,"generateTypeScriptInterface");function Cr(r,e,t){Object.entries(e).forEach(([n,o])=>{const s=t.includes(n)?"":"?",a=ze(o);r.writeLine(`readonly ${n}${s}: ${a}`)})}c(Cr,"generateTypeScriptProperties");function ze(r){return r.type==="string"?r.enum?r.enum.map(e=>`'${e}'`).join(" | "):"string":r.type==="number"||r.type==="integer"?"number":r.type==="boolean"?"boolean":r.type==="array"?`${r.items?ze(r.items):"unknown"}[]`:r.type==="object"?r.properties?`{ ${Object.entries(r.properties).map(([t,n])=>{const i=(r.required||[]).includes(t)?"":"?",s=ze(n);return`readonly ${t}${i}: ${s}`}).join("; ")} }`:"Record<string, unknown>":"unknown"}c(ze,"convertJsonSchemaToTypeScript");function Ve(r){return`${qe(Ke(r.key))}Input`}c(Ve,"getInputTypeName");function Ye(r){return`${qe(Ke(r.key))}Output`}c(Ye,"getOutputTypeName");async function Ze(r){const{out:e}=r;await v.promises.mkdir(e,{recursive:!0});const t=Sr(r);for(const[n,o]of Object.entries(t)){const i=x.join(e,n);await v.promises.writeFile(i,o,"utf-8")}}c(Ze,"generateCode");function Sr(r){switch(r.target){case"openapi":return{"openapi.json":mr(r)};case"typescript":return{"generated.d.ts":yr(r)};default:throw new Error(`Unsupported target: ${r.target}`)}}c(Sr,"generateContent");const Xe=c(()=>[w.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),w.yellow("\u2502 \u26A0\uFE0F EXPERIMENTAL FEATURE WARNING \u2502"),w.yellow("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),w.yellow("\u2502 The codegen command is experimental and subject to rapid changes.\u2502"),w.yellow("\u2502 Features, APIs, and file structures may change without notice. \u2502"),w.yellow("\u2502 Use in production environments is not recommended. \u2502"),w.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),""].join(`
4
- `),"createExperimentalWarning$2");function br(r,e){r.command("codegen").description("\u26A0\uFE0F EXPERIMENTAL: Generate code for easy integration within projects - This feature is experimental and will be changing rapidly. Use at your own risk.").requiredOption("--actions <actions>",'Comma-separated list of action names (e.g., "list-files,get-file-by-id")').requiredOption("--out <path>","Output directory for generated files").requiredOption("--target <type>","Target format: openapi or typescript").requiredOption("--schemasOnly","Generate only schemas without implementation").addHelpText("after",Xe()).addHelpText("after",["",w.bold("Examples:"),` ${w.gray("\u25B8")} ${w.cyan("membrane codegen --actions list-files,get-file-by-id --out src/generated --target openapi --schemasOnly")}`,` ${w.gray("\u25B8")} ${w.cyan("membrane install --actions delete-file --out src/generated --target typescript --schemasOnly")}`,"",Xe()].join(`
5
- `)).action(async t=>{try{console.warn(Xe()),console.error(w.cyan("\u{1F527} Membrane Codegen")),console.error("Status: Loading membrane interfaces...");const n=await vr(e,t),o={out:t.out,target:t.target,schemasOnly:t.schemasOnly,membraneInterfaces:n};console.error(`Output: ${o.out}`),console.error(`Target: ${o.target}`),console.error(`Schemas Only: ${o.schemasOnly?"Yes":"No"}`),console.error(`Loaded ${n.actions.length} membrane interfaces`),console.error("Status: Generating code..."),await Ze(o),console.error(w.green("\u2705 Code generation completed successfully!")),process.exit(0)}catch(n){console.error(w.red("\u274C Code generation failed:")),console.error(n instanceof Error?n.message:"Unknown error occurred"),process.exit(1)}})}c(br,"setupCodegenCommand");async function vr(r,e){return await r.fetchElements(),{actions:[...r.getSyncedElementsByType(T.Action).map(t=>t.data)].filter(t=>e.actions.includes(t.key||""))}}c(vr,"loadMembraneInterfaces");class me{static{c(this,"ConfigLoader")}static instance=null;sdkLoader;constructor(){this.sdkLoader=new On}static getInstance(){return me.instance||(me.instance=new me),me.instance}loadConfig(e){e&&e!==this.sdkLoader.getCwd()&&this.sdkLoader.setCwd(e);try{return this.sdkLoader.loadConfig({validate:!0})}catch(t){if(t.message?.includes("Failed to parse"))throw t;return null}}clearCache(){this.sdkLoader.clearCache()}updateConfig(e){return this.sdkLoader.updateConfig(e)}saveToFile(e){return this.sdkLoader.saveToFile(e)}isCacheDefined(){return this.sdkLoader.hasValidConfig()}}const le=me.getInstance();function we(r){return le.loadConfig(r)}c(we,"readProjectConfig");const Er="membrane",Tr="membrane.config.yml",Qe="https://api.getmembrane.com",xr="https://console.getmembrane.com";function et(r){const t=we()?.consoleUri||xr;return r?new Pn(r,t).toString():t}c(et,"getConsoleUrl");function tt(){const r=process.cwd(),e=x.join(r,Er),t=x.join(r,Tr),n=e,o=x.join(n,"workspace.yaml");return{membraneDirPath:e,configPath:t,payloadDirPath:n,workspaceDataFilePath:o}}c(tt,"getPaths");function jt(){return tt().membraneDirPath}c(jt,"getBasePath");const Ir={pat:{type:"string"},workspace:{type:"object"}},Ut=new Hn({schema:Ir,configName:"config",cwd:I.join(At.homedir(),".membrane")}),$r=c(r=>{Ut.set("pat",r)},"setPat"),Kt=c(()=>Ut.get("pat"),"getPat");class qt{static{c(this,"AccountApiClient")}constructor(e=Qe){this.apiBaseUrl=e}async request(e,t={}){const n=t.headers?t.headers instanceof Headers?new Headers(t.headers):new Headers(t.headers):new Headers;if(!n.has("Authorization")){const s=Kt();if(!s)throw new Error("Personal Access Token not found.");n.set("Authorization",`Bearer ${s}`)}t.body&&!n.has("Content-Type")&&n.set("Content-Type","application/json");const o=await fetch(`${this.apiBaseUrl}${e}`,{...t,headers:n});if(!o.ok){const s=await o.text();throw new Error(`API request failed: ${o.status} ${o.statusText} - ${s}`)}if(o.status===204)return{};const i=await o.text();return JSON.parse(i)}get(e){return this.request(e,{method:"GET"})}post(e,t){return this.request(e,{method:"POST",body:JSON.stringify(t)})}put(e,t){return this.request(e,{method:"PUT",body:JSON.stringify(t)})}patch(e,t){return this.request(e,{method:"PATCH",body:JSON.stringify(t)})}delete(e){return this.request(e,{method:"DELETE"})}}const kr=c(r=>{const e=new qt(Qe);return t=>e.get(t)},"createAccountApiFetcher"),Rr="membrane",Pr=["**/node_modules/**","**/.git/**","**/.DS_Store","**/Thumbs.db","**/*.tmp","**/*.swp","**/*.swo","**/*.log","**/*.lock","**/.cache/**","**/.next/**","**/.vscode/**","**/.idea/**","**/.logs/**"];function q(r){return x.join(r,Rr)}c(q,"getMembraneDir");const Bt=Me(q(process.cwd()),".logs");class Ar{static{c(this,"WorkspaceLogger")}_logs;verboseMode=!1;notificationHandler=null;constructor(){this._logs=[]}setNotificationHandler(e){this.notificationHandler=e}setVerboseMode(e){this.verboseMode=e}getVerboseMode(){return this.verboseMode}get logs(){return[...this._logs]}get latestLogs(){return this._logs.slice(this._logs.length-5)}log(e,t="info"){const n={timestamp:new Date().toISOString(),message:e,type:t};this._logs.push(n),this._logs=this._logs.slice(0,1e3),(t!=="debug"||this.verboseMode)&&this.notificationHandler&&this.notificationHandler.addLog(n)}info(e){this.log(e,"info")}success(e){this.log(e,"success")}warning(e){this.log(e,"warning")}error(e){this.log(e,"error")}debug(e){this.log(e,"debug")}clear(){this._logs=[]}saveLogsToFile(e){if(this._logs.length===0)return null;try{const t=new Date().toISOString().replace(/[:.]/g,"_"),n=e?`-${e}`:"",o=`${t}${n}.txt`;In(Bt,{recursive:!0});const i=Me(Bt,o),s=this._logs.map(a=>`[${a.timestamp}] ${a.type?.toUpperCase()||"INFO"}: ${a.message}`).join(`
6
- `);return $n(i,s,"utf-8"),i}catch(t){return console.error("Failed to save logs:",t),null}}}const m=new Ar,_t=new Vn;class Wt{static{c(this,"RequestLogger")}constructor(e=Nn){this.axiosInstance=e}interceptorsConfigured=!1;setup(){if(this.interceptorsConfigured)return;const e=c(t=>(this.logError(t),Promise.reject(t)),"errorHandler");this.axiosInstance.interceptors.request.use(t=>{const n=_t.getStore();t.metadata={startTime:Date.now(),skipErrorLog:n};const{method:o,url:i}=this.getRequestDetails(t);return m.debug(`[Request]: ${o} ${i}`),t},e),this.axiosInstance.interceptors.response.use(t=>{const{method:n,url:o}=this.getRequestDetails(t.config),i=this.getDuration(t.config),{status:s,statusText:a}=t;return m.debug(`[Response]: ${n} ${o} - ${s} ${a} (${i}ms)`),t},e),this.interceptorsConfigured=!0}static withSkipErrorLog(e){return _t.run(!0,e)}getRequestDetails(e){const t=e?.method?.toUpperCase()??"UNKNOWN";if(!e?.url)return{method:t,url:"unknown"};if(e.url.startsWith("http"))return{method:t,url:e.url};const o=`${e.baseURL??""}/${e.url}`.replace(/\/+/g,"/").replace(/:\//,"://");return{method:t,url:o}}getDuration(e){return Date.now()-(e?.metadata?.startTime??Date.now())}logError(e){if(e.config?.metadata?.skipErrorLog)return;const{method:t,url:n}=this.getRequestDetails(e.config),o=this.getDuration(e.config);if(e.response){const{status:i,statusText:s}=e.response;m.error(`[Response]: ${t} ${n} - ${i} ${s} (${o}ms)`),e.response.data&&m.error(`[Response Data]: ${JSON.stringify(e.response.data,null,2)}`)}}}function Dr(r,e){return new Proxy(r,{get(t,n){const o=t[n];return typeof o=="function"?(...i)=>(e.lastCall={method:String(n),args:i},o.apply(t,i)):o}})}c(Dr,"createTrackedClient");class Or{static{c(this,"MembraneAPIManager")}client=null;currentConfig=null;tokenExpiry=0;requestTimes=[];maxRequestsPerSecond=80;windowSizeMs=1e3;semaphore=0;maxConcurrentRequests;maxRetries;retryDelay;requestTimeout;enableJitter;semaphoreQueue=[];rateLimitMutex=Promise.resolve();requestLogger=null;constructor(e={}){this.init(e)}init(e={}){this.windowSizeMs=e.windowSizeMs??1e3,this.maxRequestsPerSecond=e.maxRequestsPerSecond??80,this.maxConcurrentRequests=e.maxConcurrentRequests??Math.max(1,Math.min(Math.floor(this.maxRequestsPerSecond/4),20)),this.maxRetries=e.maxRetries??3,this.retryDelay=e.retryDelay??1e3,this.requestTimeout=e.requestTimeout??12e4,this.enableJitter=e.enableJitter!==!1,this.requestLogger=new Wt,this.requestLogger.setup()}async withClient(e,t=!0,n=process.cwd()){const o={lastCall:null},i=c(async()=>{try{return await this.withRetry(async()=>{const s=await this.getClient(n),a=Dr(s,o);await this.acquireSemaphore();try{return await this.waitIfNeeded(),this.recordRequest(),await this.withTimeout(e(a),this.requestTimeout)}finally{this.releaseSemaphore()}},"API request")}catch(s){if(t){const a=o.lastCall?`Request: client.${o.lastCall.method}(${o.lastCall.args.map(l=>JSON.stringify(l)).join(", ")})`:null;throw s?.isMembraneError?(console.error(`
7
- Membrane API Error:`),a&&console.error(a),console.error(JSON.stringify(J(s),null,2))):zn(s)?(console.error(`
2
+ var In=Object.defineProperty;var c=(r,e)=>In(r,"name",{value:e,configurable:!0});import*as v from"node:fs";import{mkdirSync as $n,writeFileSync as kn,readFileSync as Rn}from"node:fs";import*as E from"node:path";import{join as Fe,dirname as Pn}from"node:path";import{URL as An,fileURLToPath as Dn}from"node:url";import C from"chalk";import{Command as On}from"commander";import{WorkspaceElementType as x,MembraneConfigLoader as Nn,MembraneAxiosInstance as Mn,MembraneClient as kt,extractMembraneErrorData as J,WorkspaceElementSpecs as V,WorkspaceSyncEventType as Fn,ConnectorFileUpdateType as Le,CONSOLE_ACCOUNT_API_TOKEN_PATH as Ln,NotFoundError as jn,getConnectorSpecPath as Un,getConnectorVersionPath as Rt,CONNECTOR_VERSION_DEVELOPMENT as je,getMembraneElementPath as Kn,parseMembraneElementPath as ie,compareWorkspaceExports as qn,WorkspaceElementChangeType as Y,setValueAtLocator as Ue,getDataCollectionCreateFields as Ke,excludeWriteOnlyFieldsFromSchema as Pt,valueToSchema as Ie,getRequiredFieldsFromSchema as Bn,getValueAtLocator as _n,walkSchema as At,makeDataLocationPath as Dt,getDataCollectionUpdateFields as qe}from"@membranehq/sdk";import Be from"lodash/camelCase.js";import _e from"lodash/upperFirst.js";import Wn from"code-block-writer";import Jn from"lodash/uniqBy.js";import se,{createContext as We,useState as D,useEffect as he,useContext as Je,useId as Gn,useRef as Ge,useLayoutEffect as $e,useMemo as Hn}from"react";import{Box as g,Text as y,useInput as ae,render as He,Newline as zn}from"ink";import{jsx as u,jsxs as b,Fragment as ke}from"react/jsx-runtime";import Ot from"swr/immutable";import Nt from"os";import $ from"path";import Vn from"conf";import ge,{isAxiosError as Yn}from"axios";import ze from"jsonwebtoken";import{AsyncLocalStorage as Zn}from"async_hooks";import{toSentenceCase as Xn}from"js-convert-case";import Qn from"lodash/isEqual.js";import G from"js-yaml";import*as er from"node:crypto";import{createHash as tr}from"node:crypto";import nr from"chokidar";import rr from"yaml";import{EventEmitter as or}from"events";import{EventSource as ir}from"eventsource";import P from"fs";import Ve from"archiver";import Mt from"form-data";import Re from"unzipper";import*as sr from"node:os";import"node:events";import Ft from"ink-text-input";import{SWRConfig as ar}from"swr";import Pe from"ink-spinner";import{TextInput as cr,Select as lr,Spinner as ur}from"@inkjs/ui";import{FastMCP as dr}from"fastmcp";import{z as A}from"zod";import ye from"semver";import Lt from"ora";import jt from"jszip";import{minimatch as hr}from"minimatch";import{exec as pr}from"node:child_process";import Ye from"lodash/merge.js";import fr from"@anthropic-ai/sdk";import{faker as we}from"@faker-js/faker";import mr from"lodash/template.js";import gr from"lodash/templateSettings.js";function ce(r){if(r.type){if(Array.isArray(r.type))return{anyOf:r.type.map(t=>ce({...r,type:t}))};if(r.type==="array"){const t={type:"array",items:r.items?ce(r.items):{type:"object"}};return r.title&&(t.title=r.title),r.description&&(t.description=r.description),r.minItems!==void 0&&(t.minItems=r.minItems),r.maxItems!==void 0&&(t.maxItems=r.maxItems),r.uniqueItems!==void 0&&(t.uniqueItems=r.uniqueItems),t}}const e={};if(r.type&&!Array.isArray(r.type)&&(e.type=r.type),r.title&&(e.title=r.title),r.description&&(e.description=r.description),r.format&&(e.format=r.format),r.enum&&(e.enum=r.enum),r.default!==void 0&&(e.default=r.default),r.minimum!==void 0&&(e.minimum=r.minimum),r.maximum!==void 0&&(e.maximum=r.maximum),r.minLength!==void 0&&(e.minLength=r.minLength),r.maxLength!==void 0&&(e.maxLength=r.maxLength),r.maxItems!==void 0&&(e.maxItems=r.maxItems),r.readOnly!==void 0&&(e.readOnly=r.readOnly),r.writeOnly!==void 0&&(e.writeOnly=r.writeOnly),r.examples&&r.examples.length>0&&(e.example=r.examples[0]),r.properties){e.properties={};for(const[t,n]of Object.entries(r.properties))e.properties[t]=ce(n)}return r.anyOf&&(e.anyOf=r.anyOf.map(ce)),r.additionalProperties!==void 0&&(typeof r.additionalProperties=="boolean"?e.additionalProperties=r.additionalProperties:e.additionalProperties=ce(r.additionalProperties)),r.required&&(e.required=r.required),e}c(ce,"convertDataSchemaToOpenAPI");function yr(r){const{membraneInterfaces:{actions:e}}=r,t=wr(e);return JSON.stringify({openapi:"3.0.0",info:{title:"Membrane Actions API",version:"1.0.0",description:"Generated OpenAPI specification for Membrane actions"},paths:{},components:{schemas:t}},null,2)}c(yr,"generateOpenAPIContent");function wr(r){const e={};return r.forEach(t=>{const n=_e(Be(t.key)),o={type:"object",properties:{id:{type:"string",description:"Request ID"},action:{type:"string",enum:[t.key]}},required:["id","action"]};if(t?.inputSchema){const a=ce(t.inputSchema);a.properties&&(o.properties={...o.properties,...a.properties}),a.required&&(o.required=[...o.required||[],...a.required])}e[`${n}Request`]=o;const i={type:"object",properties:{id:{type:"string",description:"Response ID"},success:{type:"boolean"},data:{type:"object"}},required:["id","success"]},s=t?.customOutputSchema||t?.outputSchema;if(s){const a=ce(s);i.properties={...i.properties,data:a}}e[`${n}Response`]=i}),e}c(wr,"generateOpenAPISchemas");function Cr(r){const{membraneInterfaces:{actions:e}}=r,t=Jn(e,"key"),n=new Wn({indentNumberOfSpaces:2,newLine:`
3
+ `});return n.writeLine("// Generated TypeScript definitions for Membrane actions"),n.newLine(),n.writeLine("import type {"),n.writeLine(" ActionAccessor,"),n.writeLine(" ConnectionLevelActionAccessor,"),n.writeLine('} from "@membranehq/sdk";'),n.newLine(),Sr(n,t),n.toString()}c(Cr,"generateTypeScriptContent");function Sr(r,e){r.writeLine('declare module "@membranehq/sdk" {'),r.indent(()=>{e.forEach(t=>{const n=Xe(t),o=t?.inputSchema;Ae(r,{interfaceName:n,properties:o?.properties,required:o?.required||[]});const i=Qe(t),s=t?.customOutputSchema||t?.outputSchema;Ae(r,{interfaceName:i,properties:s?.properties,required:s?.required||[],fallbackContent:"result: unknown"}),r.newLine()}),Ae(r,{interfaceName:"MembraneClient",methods:e.map(t=>{const n=Xe(t),o=Qe(t);return{name:"action",parameters:`selector: "${t.key}"`,returnType:`ActionAccessor<${n}, ${o}>`}})}),r.newLine(),Ae(r,{interfaceName:"ConnectionAccessor",methods:e.map(t=>{const n=Xe(t),o=Qe(t);return{name:"action",parameters:`selector: "${t.key}"`,returnType:`ConnectionLevelActionAccessor<${n}, ${o}>`}})})}),r.writeLine("}")}c(Sr,"generateModuleAugmentation");function Ae(r,e){const{interfaceName:t,properties:n,required:o=[],methods:i,fallbackContent:s}=e;r.writeLine(`interface ${t} {`),r.indent(()=>{n&&Object.keys(n).length>0&&br(r,n,o),i&&i.length>0&&(n&&Object.keys(n).length>0&&r.newLine(),i.forEach((a,l)=>{r.writeLine(`${a.name}(${a.parameters}): ${a.returnType};`),l<i.length-1&&r.newLine()})),s&&(!n||Object.keys(n).length===0)&&(!i||i.length===0)&&r.writeLine(s)}),r.writeLine("}")}c(Ae,"generateTypeScriptInterface");function br(r,e,t){Object.entries(e).forEach(([n,o])=>{const s=t.includes(n)?"":"?",a=Ze(o);r.writeLine(`readonly ${n}${s}: ${a}`)})}c(br,"generateTypeScriptProperties");function Ze(r){return r.type==="string"?r.enum?r.enum.map(e=>`'${e}'`).join(" | "):"string":r.type==="number"||r.type==="integer"?"number":r.type==="boolean"?"boolean":r.type==="array"?`${r.items?Ze(r.items):"unknown"}[]`:r.type==="object"?r.properties?`{ ${Object.entries(r.properties).map(([t,n])=>{const i=(r.required||[]).includes(t)?"":"?",s=Ze(n);return`readonly ${t}${i}: ${s}`}).join("; ")} }`:"Record<string, unknown>":"unknown"}c(Ze,"convertJsonSchemaToTypeScript");function Xe(r){return`${_e(Be(r.key))}Input`}c(Xe,"getInputTypeName");function Qe(r){return`${_e(Be(r.key))}Output`}c(Qe,"getOutputTypeName");async function et(r){const{out:e}=r;await v.promises.mkdir(e,{recursive:!0});const t=vr(r);for(const[n,o]of Object.entries(t)){const i=E.join(e,n);await v.promises.writeFile(i,o,"utf-8")}}c(et,"generateCode");function vr(r){switch(r.target){case"openapi":return{"openapi.json":yr(r)};case"typescript":return{"generated.d.ts":Cr(r)};default:throw new Error(`Unsupported target: ${r.target}`)}}c(vr,"generateContent");const tt=c(()=>[C.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),C.yellow("\u2502 \u26A0\uFE0F EXPERIMENTAL FEATURE WARNING \u2502"),C.yellow("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),C.yellow("\u2502 The codegen command is experimental and subject to rapid changes.\u2502"),C.yellow("\u2502 Features, APIs, and file structures may change without notice. \u2502"),C.yellow("\u2502 Use in production environments is not recommended. \u2502"),C.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),""].join(`
4
+ `),"createExperimentalWarning$2");function Er(r,e){r.command("codegen").description("\u26A0\uFE0F EXPERIMENTAL: Generate code for easy integration within projects - This feature is experimental and will be changing rapidly. Use at your own risk.").requiredOption("--actions <actions>",'Comma-separated list of action names (e.g., "list-files,get-file-by-id")').requiredOption("--out <path>","Output directory for generated files").requiredOption("--target <type>","Target format: openapi or typescript").requiredOption("--schemasOnly","Generate only schemas without implementation").addHelpText("after",tt()).addHelpText("after",["",C.bold("Examples:"),` ${C.gray("\u25B8")} ${C.cyan("membrane codegen --actions list-files,get-file-by-id --out src/generated --target openapi --schemasOnly")}`,` ${C.gray("\u25B8")} ${C.cyan("membrane install --actions delete-file --out src/generated --target typescript --schemasOnly")}`,"",tt()].join(`
5
+ `)).action(async t=>{try{console.warn(tt()),console.error(C.cyan("\u{1F527} Membrane Codegen")),console.error("Status: Loading membrane interfaces...");const n=await Tr(e,t),o={out:t.out,target:t.target,schemasOnly:t.schemasOnly,membraneInterfaces:n};console.error(`Output: ${o.out}`),console.error(`Target: ${o.target}`),console.error(`Schemas Only: ${o.schemasOnly?"Yes":"No"}`),console.error(`Loaded ${n.actions.length} membrane interfaces`),console.error("Status: Generating code..."),await et(o),console.error(C.green("\u2705 Code generation completed successfully!")),process.exit(0)}catch(n){console.error(C.red("\u274C Code generation failed:")),console.error(n instanceof Error?n.message:"Unknown error occurred"),process.exit(1)}})}c(Er,"setupCodegenCommand");async function Tr(r,e){return await r.fetchElements(),{actions:[...r.getSyncedElementsByType(x.Action).map(t=>t.data)].filter(t=>e.actions.includes(t.key||""))}}c(Tr,"loadMembraneInterfaces");class me{static{c(this,"ConfigLoader")}static instance=null;sdkLoader;constructor(){this.sdkLoader=new Nn}static getInstance(){return me.instance||(me.instance=new me),me.instance}loadConfig(e){e&&e!==this.sdkLoader.getCwd()&&this.sdkLoader.setCwd(e);try{return this.sdkLoader.loadConfig({validate:!0})}catch(t){if(t.message?.includes("Failed to parse"))throw t;return null}}clearCache(){this.sdkLoader.clearCache()}updateConfig(e){return this.sdkLoader.updateConfig(e)}saveToFile(e){return this.sdkLoader.saveToFile(e)}isCacheDefined(){return this.sdkLoader.hasValidConfig()}}const le=me.getInstance();function Ce(r){return le.loadConfig(r)}c(Ce,"readProjectConfig");const xr="membrane",Ir="membrane.config.yml",nt="https://api.getmembrane.com",$r="https://console.getmembrane.com";function rt(r){const t=Ce()?.consoleUri||$r;return r?new An(r,t).toString():t}c(rt,"getConsoleUrl");function ot(){const r=process.cwd(),e=E.join(r,xr),t=E.join(r,Ir),n=e,o=E.join(n,"workspace.yaml");return{membraneDirPath:e,configPath:t,payloadDirPath:n,workspaceDataFilePath:o}}c(ot,"getPaths");function Ut(){return ot().membraneDirPath}c(Ut,"getBasePath");const kr={pat:{type:"string"},workspace:{type:"object"}},Kt=new Vn({schema:kr,configName:"config",cwd:$.join(Nt.homedir(),".membrane")}),Rr=c(r=>{Kt.set("pat",r)},"setPat"),qt=c(()=>Kt.get("pat"),"getPat");class Bt{static{c(this,"AccountApiClient")}constructor(e=nt){this.apiBaseUrl=e}async request(e,t={}){const n=t.headers?t.headers instanceof Headers?new Headers(t.headers):new Headers(t.headers):new Headers;if(!n.has("Authorization")){const s=qt();if(!s)throw new Error("Personal Access Token not found.");n.set("Authorization",`Bearer ${s}`)}t.body&&!n.has("Content-Type")&&n.set("Content-Type","application/json");const o=await fetch(`${this.apiBaseUrl}${e}`,{...t,headers:n});if(!o.ok){const s=await o.text();throw new Error(`API request failed: ${o.status} ${o.statusText} - ${s}`)}if(o.status===204)return{};const i=await o.text();return JSON.parse(i)}get(e){return this.request(e,{method:"GET"})}post(e,t){return this.request(e,{method:"POST",body:JSON.stringify(t)})}put(e,t){return this.request(e,{method:"PUT",body:JSON.stringify(t)})}patch(e,t){return this.request(e,{method:"PATCH",body:JSON.stringify(t)})}delete(e){return this.request(e,{method:"DELETE"})}}const Pr=c(r=>{const e=new Bt(nt);return t=>e.get(t)},"createAccountApiFetcher"),Ar="membrane",Dr=["**/node_modules/**","**/.git/**","**/.DS_Store","**/Thumbs.db","**/*.tmp","**/*.swp","**/*.swo","**/*.log","**/*.lock","**/.cache/**","**/.next/**","**/.vscode/**","**/.idea/**","**/.logs/**"];function U(r){return E.join(r,Ar)}c(U,"getMembraneDir");const _t=Fe(U(process.cwd()),".logs");class Or{static{c(this,"WorkspaceLogger")}_logs;verboseMode=!1;notificationHandler=null;constructor(){this._logs=[]}setNotificationHandler(e){this.notificationHandler=e}setVerboseMode(e){this.verboseMode=e}getVerboseMode(){return this.verboseMode}get logs(){return[...this._logs]}get latestLogs(){return this._logs.slice(this._logs.length-5)}log(e,t="info"){const n={timestamp:new Date().toISOString(),message:e,type:t};this._logs.push(n),this._logs=this._logs.slice(0,1e3),(t!=="debug"||this.verboseMode)&&this.notificationHandler&&this.notificationHandler.addLog(n)}info(e){this.log(e,"info")}success(e){this.log(e,"success")}warning(e){this.log(e,"warning")}error(e){this.log(e,"error")}debug(e){this.log(e,"debug")}clear(){this._logs=[]}saveLogsToFile(e){if(this._logs.length===0)return null;try{const t=new Date().toISOString().replace(/[:.]/g,"_"),n=e?`-${e}`:"",o=`${t}${n}.txt`;$n(_t,{recursive:!0});const i=Fe(_t,o),s=this._logs.map(a=>`[${a.timestamp}] ${a.type?.toUpperCase()||"INFO"}: ${a.message}`).join(`
6
+ `);return kn(i,s,"utf-8"),i}catch(t){return console.error("Failed to save logs:",t),null}}}const f=new Or,Wt=new Zn;class Jt{static{c(this,"RequestLogger")}constructor(e=Mn){this.axiosInstance=e}interceptorsConfigured=!1;setup(){if(this.interceptorsConfigured)return;const e=c(t=>(this.logError(t),Promise.reject(t)),"errorHandler");this.axiosInstance.interceptors.request.use(t=>{const n=Wt.getStore();t.metadata={startTime:Date.now(),skipErrorLog:n};const{method:o,url:i}=this.getRequestDetails(t);return f.debug(`[Request]: ${o} ${i}`),t},e),this.axiosInstance.interceptors.response.use(t=>{const{method:n,url:o}=this.getRequestDetails(t.config),i=this.getDuration(t.config),{status:s,statusText:a}=t;return f.debug(`[Response]: ${n} ${o} - ${s} ${a} (${i}ms)`),t},e),this.interceptorsConfigured=!0}static withSkipErrorLog(e){return Wt.run(!0,e)}getRequestDetails(e){const t=e?.method?.toUpperCase()??"UNKNOWN";if(!e?.url)return{method:t,url:"unknown"};if(e.url.startsWith("http"))return{method:t,url:e.url};const o=`${e.baseURL??""}/${e.url}`.replace(/\/+/g,"/").replace(/:\//,"://");return{method:t,url:o}}getDuration(e){return Date.now()-(e?.metadata?.startTime??Date.now())}logError(e){if(e.config?.metadata?.skipErrorLog)return;const{method:t,url:n}=this.getRequestDetails(e.config),o=this.getDuration(e.config);if(e.response){const{status:i,statusText:s}=e.response;f.error(`[Response]: ${t} ${n} - ${i} ${s} (${o}ms)`),e.response.data&&f.error(`[Response Data]: ${JSON.stringify(e.response.data,null,2)}`)}}}function Nr(r,e){return new Proxy(r,{get(t,n){const o=t[n];return typeof o=="function"?(...i)=>(e.lastCall={method:String(n),args:i},o.apply(t,i)):o}})}c(Nr,"createTrackedClient");class Mr{static{c(this,"MembraneAPIManager")}client=null;currentConfig=null;tokenExpiry=0;requestTimes=[];maxRequestsPerSecond=80;windowSizeMs=1e3;semaphore=0;maxConcurrentRequests;maxRetries;retryDelay;requestTimeout;enableJitter;semaphoreQueue=[];rateLimitMutex=Promise.resolve();requestLogger=null;constructor(e={}){this.init(e)}init(e={}){this.windowSizeMs=e.windowSizeMs??1e3,this.maxRequestsPerSecond=e.maxRequestsPerSecond??80,this.maxConcurrentRequests=e.maxConcurrentRequests??Math.max(1,Math.min(Math.floor(this.maxRequestsPerSecond/4),20)),this.maxRetries=e.maxRetries??3,this.retryDelay=e.retryDelay??1e3,this.requestTimeout=e.requestTimeout??12e4,this.enableJitter=e.enableJitter!==!1,this.requestLogger=new Jt,this.requestLogger.setup()}async withClient(e,t=!0,n=process.cwd()){const o={lastCall:null},i=c(async()=>{try{return await this.withRetry(async()=>{const s=await this.getClient(n),a=Nr(s,o);await this.acquireSemaphore();try{return await this.waitIfNeeded(),this.recordRequest(),await this.withTimeout(e(a),this.requestTimeout)}finally{this.releaseSemaphore()}},"API request")}catch(s){if(t){const a=o.lastCall?`Request: client.${o.lastCall.method}(${o.lastCall.args.map(l=>JSON.stringify(l)).join(", ")})`:null;throw s?.isMembraneError?(console.error(`
7
+ Membrane API Error:`),a&&console.error(a),console.error(JSON.stringify(J(s),null,2))):Yn(s)?(console.error(`
8
8
  HTTP Error:`),a&&console.error(a),console.error(JSON.stringify({message:s.message,status:s.response?.status,statusText:s.response?.statusText,responseData:s.response?.data},null,2))):(console.error(`
9
- Unexpected Error:`),a&&console.error(a),console.error(s)),s}return}},"executeRequest");return t?i():Wt.withSkipErrorLog(i)}async generateAccessToken(e,t){return Ge.sign({name:"Membrane Agent",isAdmin:!0,exp:Math.floor(Date.now()/1e3)+3600,iss:e},t,{algorithm:"HS512"})}isTokenValid(){return Date.now()<this.tokenExpiry}getCurrentConfig(e){const t=we(e);return!t?.workspaceKey||!t?.workspaceSecret?null:{workspaceKey:t.workspaceKey,workspaceSecret:t.workspaceSecret,apiUri:t.apiUri}}async createClient(e){const t=await this.generateAccessToken(e.workspaceKey,e.workspaceSecret);return this.tokenExpiry=Date.now()+36e5,this.currentConfig=e,new xt({token:t,apiUri:e.apiUri})}async getClient(e=process.cwd()){const t=this.getCurrentConfig(e);if(!t)throw new Error("Unable to create MembraneClient: No workspace configuration found.");const n=!this.currentConfig||this.currentConfig.workspaceKey!==t.workspaceKey||this.currentConfig.workspaceSecret!==t.workspaceSecret||this.currentConfig.apiUri!==t.apiUri,o=!this.isTokenValid()||this.tokenExpiry-Date.now()<3e5;return(!this.client||n||o)&&(this.client=await this.createClient(t)),this.client}clearClient(){this.client=null,this.currentConfig=null,this.tokenExpiry=0,this.requestTimes=[],this.semaphore=0,this.semaphoreQueue=[],this.rateLimitMutex=Promise.resolve()}getCurrentConfigInfo(){return this.currentConfig}async waitIfNeeded(){this.rateLimitMutex=this.rateLimitMutex.then(async()=>{for(this.cleanOldRequests();this.requestTimes.length>=this.maxRequestsPerSecond;){const t=this.requestTimes[0]+this.windowSizeMs-Date.now()+10;if(t>0)await new Promise(n=>setTimeout(n,t)),this.cleanOldRequests();else break}}),await this.rateLimitMutex}recordRequest(){this.requestTimes.push(Date.now())}cleanOldRequests(){const e=Date.now()-this.windowSizeMs;this.requestTimes=this.requestTimes.filter(t=>t>e)}getRequestCount(){return this.cleanOldRequests(),this.requestTimes.length}async acquireSemaphore(){if(this.semaphore<this.maxConcurrentRequests){this.semaphore++;return}return new Promise(e=>{this.semaphoreQueue.push(e)})}releaseSemaphore(){if(this.semaphore--,this.semaphoreQueue.length>0){const e=this.semaphoreQueue.shift();this.semaphore++,e()}}async withRetry(e,t="operation"){let n;for(let o=0;o<=this.maxRetries;o++)try{return await e()}catch(i){if(n=i,!this.isRetryableError(i)||o===this.maxRetries)throw i;const s=new Date().toISOString(),a=o+2;m.debug(`[${s}] Retrying ${t} (attempt ${a}/${this.maxRetries+1})`);let l=this.retryDelay*Math.pow(2,o);if(this.enableJitter){const d=l*.25*(Math.random()*2-1);l=Math.max(0,l+d)}await new Promise(d=>setTimeout(d,l))}throw n||new Error("Unknown error occurred during retry attempts")}isRetryableError(e){if(!e)return!1;const t=(e.message||e.toString()||"").toLowerCase(),n=e.code;return n&&["econnrefused","enotfound","econnreset","etimedout","ehostunreach","enetunreach"].includes(n.toLowerCase())?!0:["econnrefused","connection refused","network error","timeout","socket hang up","request timeout","dns lookup failed"].some(s=>t.includes(s))}async withTimeout(e,t){let n;const o=new Promise((i,s)=>{n=setTimeout(()=>s(new Error(`Request timeout after ${t}ms`)),t)});try{const i=await Promise.race([e,o]);return n&&clearTimeout(n),i}catch(i){throw n&&clearTimeout(n),i}}async getVersion(){try{return(await this.withClient(t=>t.get("version"),!1))?.version??null}catch{return null}}}const $=new Or;async function Jt(r){const e=await $.withClient(t=>t.get("org-workspace-id"),!0,r);if(!e)throw new Error("Failed to get workspace ID");return e.id}c(Jt,"getWorkspaceId");const Z={UPDATE:"update",DELETE:"delete",CREATE:"create"},B={INCOMING:"incoming",OUTGOING:"outgoing"},z={[T.Integration]:{element:"integration",elements:"integrations",exportable:!1,exportCleanup:c(r=>({id:r.id,key:r.key,name:r.name,connectorId:r.connectorId,baseUri:r.baseUri,connectorVersion:r.connectorVersion}),"exportCleanup")},[T.Connector]:{element:"connector",elements:"connectors",exportable:!1},[T.Action]:{element:"action",elements:"actions",integrationSpecific:!0,exportCleanup:c(r=>(delete r.integration,r),"exportCleanup")},[T.AppDataSchema]:{element:"appDataSchema",elements:"appDataSchemas"},[T.AppEventType]:{element:"appEventType",elements:"appEventTypes"},[T.DataLinkTable]:{element:"dataLinkTable",elements:"dataLinkTables"},[T.DataSource]:{element:"dataSource",elements:"dataSources",parentKey:"universalDataSourceId",integrationSpecific:!0},[T.FieldMapping]:{element:"fieldMapping",elements:"fieldMappings",integrationSpecific:!0,parentKey:"universalFieldMappingId",exportCleanup:c(r=>(delete r.dataSourceId,r),"exportCleanup")},[T.Flow]:{element:"flow",elements:"flows",integrationSpecific:!0,parentKey:"universalFlowId"},[T.Package]:{element:"package",elements:"packages",integrationSpecific:!0}},Nr=["id","workspaceId","integrationId","createdAt","updatedAt","revision","archivedAt","baseUri","state","appliedToIntegrations","dependencies"],Gt=[T.Action,T.FieldMapping,T.Flow,T.DataSource,T.Package];class M{static{c(this,"Element")}type;key;integrationKey;data;constructor(e,t,n,o){if(!o)throw new Error("Element must always contain data");if(!t)throw new Error("Element must have a key");this.type=e,this.key=t,this.data=o,this.integrationKey=n||M.extractIntegrationKey(o)}get id(){return M.makeId(this.type,this.key,this.integrationKey)}get dirPath(){const e=V[this.type].apiPath;if(this.integrationKey){const t=V[T.Integration].apiPath;return x.join(t,this.integrationKey,e,this.key)}return x.join(e,this.key)}get path(){return x.join(this.dirPath,"spec.yaml")}get relativePath(){return x.relative(q(process.cwd()),this.path)}get absolutePath(){return x.resolve(x.join(q(process.cwd()),this.path))}isEqual(e){if(this.id!==e.id)return!1;const t=this.clean(),n=e.clean();return Zn(t,n)}hasParent(){if(this.data?.parentUuid)return!0;const e=this.getParentKey();return!!e&&!!this.data?.[e]}clean(){const e={...this.data};return Nr.forEach(t=>{delete e[t]}),Object.keys(e).forEach(t=>{t.match(/universal.*Revision/)&&delete e[t]}),e}getParentKey(){let e="parentId";return z?.[this.type]?.parentKey&&(e=z?.[this.type]?.parentKey),e}static new(e,t,n,o){return new M(e,t,n,o)}static fromData(e,t){if(!t?.key)throw new Error(`Element missing key: ${JSON.stringify(t)}`);const n=this.extractIntegrationKey(t);return new M(e,t.key,n,t)}static fromPathAndData(e,t){const n=M.parsePath(e);if(!t)return;const o=t?.key||n?.key;return n?M.new(n.type,o,n.integrationKey,t):void 0}static fromElement(e){return new M(e.type,e.key,e.integrationKey,{...e.data})}static idFromPath(e){const t=M.parsePath(e);if(t)return M.makeId(t.type,t.key,t.integrationKey)}static makeId(e,t,n){return e===T.Integration?`${e}:${t}`:M.isIntegrationSpecific(e)?`${n||"universal"}:${e}:${t}`:`${e}:${t}`}static parsePath(e){const t=this.getRelativePath(e);if(!this.isElementFile(t))return;const n=Object.values(V).map(l=>l.apiPath).join("|"),o=new RegExp(`^(?<elementType>${n})/(?<elementKey>[^/]+)/spec\\.ya?ml$`),i=t.match(o);if(i?.groups){const{elementType:l,elementKey:d}=i.groups,h=this.getElementTypeFromPath(l);if(h)return{type:h,key:d}}const s=new RegExp(`^integrations/(?<integrationKey>[^/]+)/(?<elementType>${n})/(?<elementKey>[^/]+)/spec\\.ya?ml$`),a=t.match(s);if(a?.groups){const{integrationKey:l,elementType:d,elementKey:h}=a.groups,f=this.getElementTypeFromPath(d);if(f)return{type:f,key:h,integrationKey:l}}}static extractIntegrationKey(e){return e?.integrationKey||e?.integration?.key||e?.integration_key||void 0}static isElementFile(e){return e.endsWith(".yml")||e.endsWith(".yaml")}static getElementTypeFromPath(e){return Object.values(T).find(t=>V[t].apiPath===e)}static getRelativePath(e){return x.relative(q(process.cwd()),e)}static isIntegrationSpecific(e){return Gt.includes(e)}static canBeIntegrationSpecific(e){return Gt.includes(e)}}class Ht{static{c(this,"BaseWorkspaceElementsRepository")}constructor(e){this.cache=e}connectorsMapping;sourceCache;setConnectorsMapping(e){this.connectorsMapping=e}setSourceCache(e){this.sourceCache=e}async getElements(){const e=[];try{const t=await this.getIntegrations();e.push(...t);const n=[T.Integration,T.Connector],o=Object.keys(z),i=await Promise.all(o.filter(s=>!n.includes(s)).map(async s=>this.getElementsByType(s,t)));for(const s of i)e.push(...s)}catch(t){throw m.error(`Failed to get elements: ${t}`),t}return e}async putElement(e){let t=this.cache.get(e.id);return t&&!e.data.id&&t.data.id&&(e.data.id=t.data.id),!t&&e.data.id&&(t=await this.getByInternalId(e.data.id,e.type,!1)),e.data.id&&t?t=await this.updateElement(e,t,{elements:this.cache.getAll(),connectorsMapping:this.connectorsMapping,sourceElements:this.sourceCache?.getAll()}):t=await this.createElement(e,{elements:this.cache.getAll(),connectorsMapping:this.connectorsMapping,sourceElements:this.sourceCache?.getAll()}),t}async getElementsByType(e,t){return[]}async createElement(e,t){return e}async updateElement(e,t,n){return t}async getElement(e){}async getIntegrations(){return[]}async getByInternalId(e,t,n=!0){}async deleteElement(e,t){}}function nt(r,e=!0){if(v.existsSync(r))try{const t=v.readFileSync(r,"utf8");return G.load(t)||void 0}catch(t){if(!e)return;if(t instanceof Error){const n=x.relative(process.cwd(),r);throw new Error(`Failed to parse YAML file "${n}": ${t.message}`)}throw t}}c(nt,"readYaml$1");function Mr(r,e,t){try{const n=G.dump(e,t);v.writeFileSync(r,n,"utf8")}catch(n){if(n instanceof Error){const o=x.relative(process.cwd(),r);throw new Error(`Failed to write YAML file "${o}": ${n.message}`)}throw n}}c(Mr,"writeYaml$1");class Fr extends Ht{static{c(this,"LocalWorkspaceElementsRepository")}basePath;constructor(e){super(e),this.basePath=q(process.cwd())}async getElementsByType(e,t){const n=[],o=x.join(this.basePath,V[e].apiPath),i=await this.readElementsInDir(o);n.push(...i);for(const s of t){const a=x.join(this.basePath,V[T.Integration].apiPath,s.key,V[e].apiPath),l=await this.readElementsInDir(a);n.push(...l)}return n.length>0&&m.debug(`[local] Fetched ${n.length} ${e}${n.length!==1?"s":""}`),n}async getElement(e){return this.readElement(e.path)}async createElement(e){return this.updateElement(e,e)}async updateElement(e,t){if(!e.data)throw new Error("Element must have data to write");const n=x.join(this.basePath,t.dirPath),o=x.join(this.basePath,t.path);return v.existsSync(n)||v.mkdirSync(n,{recursive:!0}),Mr(o,e.data),m.debug(`[local] Written ${t.relativePath}`),t}async deleteElement(e){const t=x.join(this.basePath,e.path),n=x.join(this.basePath,e.dirPath);v.existsSync(t)&&v.rmSync(t,{force:!0}),this.pruneEmptyDir(n),m.debug(`[local] Deleted ${e.relativePath}`)}async getIntegrations(){const e=x.join(this.basePath,V[T.Integration].apiPath);return this.readElementsInDir(e)}async readElement(e){const t=nt(e);if(t)return M.fromPathAndData(e,t)}async readElementsInDir(e){const t=[];if(!v.existsSync(e))return t;const n=v.readdirSync(e);if(n.length===0)return t;const o=n.map(async s=>{const a=x.join(e,s,"spec.yaml");return this.readElement(a)});return(await Promise.all(o)).filter(s=>s!=null)}pruneEmptyDir(e){try{if(!e.startsWith(this.basePath)||e===this.basePath||!v.existsSync(e)||v.readdirSync(e).length>0)return;v.rmdirSync(e),this.pruneEmptyDir(x.dirname(e))}catch(t){console.warn(`Failed to prune empty directory ${e}:`,t)}}}class Lr extends Ht{static{c(this,"RemoteWorkspaceElementsRepository")}async getElementsByType(e,t){const n=M.canBeIntegrationSpecific(e),o=await this.findAll(e,n?{layer:"universal"}:{});if(!M.canBeIntegrationSpecific(e))return o;for(const i of t){const s=i.key,a=i.data.id,l=await this.findAll(e,a?{integrationId:a}:{integrationKey:s},s);o.push(...l)}return o.length>0&&m.debug(`[remote] Fetched ${o.length} ${e}${o.length!==1?"s":""}`),o}async getElement(e){const t=await $.withClient(n=>n[z[e.type].element](e.data.id).get());return M.fromData(e.type,t)}async createElement(e,t){const n=e.clean();if(this.transformElementForCreate(e,n,t),e.hasParent()&&n.integrationId&&!n.isCustomized){const s=e.getParentKey(),a=new Set(["uuid","integrationId",s,"meta","integrationUuid","parentUuid"]);Object.keys(n).forEach(l=>{a.has(l)||delete n[l]})}const o=await $.withClient(s=>s[z[e.type].elements].create(n)),i=M.fromData(e.type,o);return m.debug(`[remote] Created ${i.id}`),i}async updateElement(e,t,n){if(!e.data.id)throw new Error("Element must have an id to update");t.data.archivedAt&&await $.withClient(a=>a[z[e.type].element](t.data.id).restore());const o=e.clean();if(this.transformElementForUpdate(e,o,n),e.hasParent()&&o.integrationId&&!o.isCustomized)return m.debug(`[remote] Skipped update for ${t.id} (non-customized)`),t;const i=await $.withClient(a=>a[z[e.type].element](t.data.id).put(o)),s=M.fromData(t.type,i);return m.debug(`[remote] Updated ${t.id}`),s}async deleteElement(e){if(!e.data.id)throw new Error("Element must have an id to delete");await $.withClient(t=>t[z[e.type].element](e.data.id).archive()),m.debug(`[remote] Deleted ${e.id}`)}async getIntegrations(){const e=await $.withClient(n=>n.integrations.findAll());if(!e)return[];const t=e.map(n=>M.fromData(T.Integration,n));return t.length>0&&m.debug(`[remote] Fetched ${t.length} integrations`),t}async getByInternalId(e,t){let n;if(n=await $.withClient(o=>o[z[t].element](e).get(),!1),!!n)return M.fromData(t,n)}transformElementForCreate(e,t,n){if(e.integrationKey){const o=n.elements.find(i=>i.type===T.Integration&&i.key===e.integrationKey);if(o)t.integrationId=o.data.id;else throw new Error(`Dependency integration ${e.integrationKey} not found for ${e.id}`)}if(e.type===T.Integration){const o=n.connectorsMapping?.[t.connectorId];o&&(t.connectorId=o)}this.transformPackageDependencies(e,t,n),this.transformParentDependency(e,t,n)}transformElementForUpdate(e,t,n){if(e.type===T.Integration){const o=n.connectorsMapping?.[t.connectorId];o&&(t.connectorId=o)}if(e.integrationKey){t.integrationKey=e.integrationKey;const o=n.elements.find(i=>i.type===T.Integration&&i.key===e.integrationKey);if(o)t.integrationId=o.data.id;else throw new Error(`Dependency integration ${e.integrationKey} not found for ${e.id}`)}this.transformPackageDependencies(e,t,n),this.transformParentDependency(e,t,n)}transformPackageDependencies(e,t,n){if(e.type!==T.Package||!t.elements)return;const o=t.elements.map(i=>{const a=(n.sourceElements||n.elements).find(d=>d.data.id===i.id&&d.type===i.type);if(!a)throw new Error(`Package element ${i.type} with id ${i.id} not found in source workspace for package ${e.id}`);const l=n.elements.find(d=>d.type===i.type&&d.key===a.key&&d.integrationKey===a.integrationKey);if(!l)throw new Error(`Package element ${i.type} with key ${a.key} not found in target workspace for package ${e.id}`);return{id:l.data.id,type:i.type}});t.elements=o}transformParentDependency(e,t,n){if(!e.hasParent())return;const o=e.getParentKey();if(!o)return;const i=n.elements.find(s=>s.type===e.type&&s.key===e.key&&!s.hasParent());if(i)t[o]=i.data.id;else throw new Error(`Parent ${e.getParentKey()} not found for ${e.id}`)}async findAll(e,t={},n){const o=await $.withClient(i=>i[z[e].elements].findAll(t));return o?o.filter(i=>i.key).map(i=>(n&&!i.integrationKey&&(i.integrationKey=n),M.fromData(e,i))):[]}}class rt extends nr{static{c(this,"TypedEventEmitter")}on(e,t){return super.on(e,t)}emit(e,...t){return super.emit(e,...t)}off(e,t){return super.off(e,t)}once(e,t){return super.once(e,t)}}const _={Updated:"updated",Deleted:"deleted",Stopped:"stopped"},jr={ignored:Pr,persistent:!0,ignoreInitial:!0,followSymlinks:!1,depth:20,awaitWriteFinish:{stabilityThreshold:500,pollInterval:100},ignorePermissionErrors:!0,atomic:!0,usePolling:!1,alwaysStat:!1,interval:1e3,binaryInterval:300};class Ur extends rt{static{c(this,"LocalElementWatcher")}constructor(e){super(),this.options=e,this.membraneDir=q(this.options.cwd),this.lockTimeoutMs=this.options.lockTimeoutMs??1e3}isWatching=!1;watcher;membraneDir;contentCache={};ignoredPaths=new Set;lockTimeoutMs;async start(){this.isWatching||(v.existsSync(this.membraneDir)||v.mkdirSync(this.membraneDir,{recursive:!0}),this.initializeContentCache(),this.watcher=er.watch(this.membraneDir,jr),this.watcher.on("add",e=>this.handleFileSystemEvent(_.Updated,e)).on("change",e=>this.handleFileSystemEvent(_.Updated,e)).on("unlink",e=>this.handleFileSystemEvent(_.Deleted,e)).on("ready",()=>this.isWatching=!0))}async stop(){!this.isWatching||!this.watcher||(await this.watcher.close(),this.isWatching=!1,this.watcher=void 0,this.clearCache(),this.clearAllLocks(),this.emit(_.Stopped))}getCwd(){return this.options.cwd}async executeWithPathLock(e,t){const n=x.resolve(e);this.ignoredPaths.add(n);try{await t()}finally{setTimeout(()=>{this.ignoredPaths.delete(n)},this.lockTimeoutMs)}}isPathLocked(e){const t=x.resolve(e);if(this.ignoredPaths.has(t))return!0;for(const n of this.ignoredPaths)if(t.startsWith(n+x.sep))return!0;return!1}clearAllLocks(){this.ignoredPaths.clear()}handleFileSystemEvent(e,t){const n=x.relative(this.membraneDir,t);if(this.isPathLocked(t))return;if(e===_.Deleted){this.removeFromCache(n);const a={filePath:t,relativePath:n,data:void 0};m.info(`[local] ${e}: ${a.relativePath}`),this.emit(e,a);return}const o=this.readFileContent(t);if(!this.hasContentChanged(n,o))return;const s=this.processFileEvent(t,o);this.updateCache(n,o),s&&(m.info(`[local] ${e}: ${s.relativePath}`),this.emit(e,s))}readFileContent(e){return v.readFileSync(e,"utf8")}processFileEvent(e,t){const n=x.relative(this.membraneDir,e);let o;try{o=t?tr.parse(t):void 0}catch{o=void 0}return{filePath:e,relativePath:n,data:o}}hasContentChanged(e,t){if(!t)return this.contentCache[e]!==void 0;const n=this.getContentHash(t);return this.contentCache[e]!==n}getContentHash(e){return Xn.createHash("sha256").update(e).digest("hex")}updateCache(e,t){if(!t){delete this.contentCache[e];return}this.contentCache[e]=this.getContentHash(t)}removeFromCache(e){delete this.contentCache[e]}clearCache(){Object.keys(this.contentCache).forEach(e=>{delete this.contentCache[e]})}initializeContentCache(){v.existsSync(this.membraneDir)&&this.scanDirectoryForCache(this.membraneDir)}scanDirectoryForCache(e){const t=v.readdirSync(e,{withFileTypes:!0});for(const n of t){const o=x.join(e,n.name);if(n.isDirectory())this.scanDirectoryForCache(o);else if(n.isFile())try{const i=v.readFileSync(o,"utf8"),s=x.relative(this.membraneDir,o);this.updateCache(s,i)}catch{}}}}var ot=(r=>(r.Updated="updated",r.ConnectorFileUpdated="connector-file-updated",r.Connected="connected",r.Disconnected="disconnected",r.Error="error",r))(ot||{});const Kr={debounceMs:2e3,reconnectIntervalMs:5e3,maxReconnectAttempts:1/0,maxBackoffMs:6e4,connectionTimeoutMs:3e5};class qr extends rt{static{c(this,"RemoteElementWatcher")}constructor(e=Kr){super(),this.config=e}eventSource;debounceTimeouts=new Map;reconnectAttempts=0;reconnectTimeout;connectionTimeout;isStarted=!1;isConnected=!1;async start(){this.isStarted||(this.isStarted=!0,await this.connect())}async stop(){this.isStarted&&(this.isStarted=!1,this.isConnected=!1,this.clearReconnectTimeout(),this.clearConnectionTimeout(),this.clearAllDebounceTimeouts(),this.eventSource&&(this.eventSource.close(),this.eventSource=void 0))}async connect(){try{m.debug("[remote-events] Connecting to server"),this.eventSource&&(this.eventSource.close(),this.eventSource=void 0);const e=await $.getClient(process.cwd()),t=await e.getToken();if(!t)throw new Error("No auth token available");const n=`${e.apiUri}/sse/workspace?token=${encodeURIComponent(t)}`;m.debug("[remote-events] Subscribing to workspace events"),this.eventSource=new rr(n),this.setupEventSourceHandlers()}catch(e){m.debug(`[remote-events] Failed to connect: ${e}`),this.emit("error",{error:e}),this.scheduleReconnect()}}setupEventSourceHandlers(){this.eventSource&&(this.eventSource.onopen=()=>{m.debug("[remote-events] Connected to server"),this.reconnectAttempts=0,this.isConnected=!0,this.resetConnectionTimeout(),this.emit("connected",{})},this.eventSource.onmessage=e=>{try{this.resetConnectionTimeout();const t=JSON.parse(e.data);this.handleElementUpdate(t)}catch(t){m.debug(`[remote-events] Failed to parse workspace event: ${t}`)}},this.eventSource.onerror=e=>{m.debug(`[remote-events] Connection error: ${JSON.stringify(e,null,2)}`),this.isConnected=!1,this.clearConnectionTimeout(),this.eventSource&&(this.eventSource.close(),this.eventSource=void 0),this.emit("disconnected",{}),this.isStarted&&this.scheduleReconnect()})}handleElementUpdate(e){if(e.type!==Mn.ElementUpdate)return;const{elementId:t,elementType:n,data:o={}}=e;if(!(!t||!n)){if(n===T.Connector){const{filePath:i,eventType:s,newPath:a}=o;return m.debug(`[remote-watcher] Received connector event - elementId: ${t}, filePath: ${i}, eventType: ${s}`),this.scheduleConnectorFileUpdate(t,i,s,a)}return this.scheduleElementUpdate(t,n)}}scheduleElementUpdate(e,t){const n=this.debounceTimeouts.get(e);n&&clearTimeout(n);const o=setTimeout(()=>{this.debounceTimeouts.delete(e),this.emit("updated",{elementId:e,elementType:t})},this.config.debounceMs);this.debounceTimeouts.set(e,o)}scheduleConnectorFileUpdate(e,t,n,o){const i=JSON.stringify({connectorId:e,filePath:t}),s=this.debounceTimeouts.get(i);s&&clearTimeout(s);const a=setTimeout(()=>{this.debounceTimeouts.delete(i),this.emit("connector-file-updated",{connectorId:e,filePath:t,eventType:n,newPath:o})},this.config.debounceMs);this.debounceTimeouts.set(i,a)}scheduleReconnect(){if(!this.isStarted||this.reconnectAttempts>=this.config.maxReconnectAttempts){this.reconnectAttempts>=this.config.maxReconnectAttempts&&(m.error("[remote-events] Max reconnection attempts reached. Connection will not be retried."),this.emit("error",{error:new Error("Max reconnection attempts reached")}));return}this.reconnectTimeout&&clearTimeout(this.reconnectTimeout),this.reconnectAttempts++;const e=this.config.reconnectIntervalMs*Math.pow(2,this.reconnectAttempts-1),t=Math.random()*.3*e,n=Math.min(e+t,this.config.maxBackoffMs);m.debug(`[remote-events] Reconnecting in ${Math.round(n)}ms (attempt ${this.reconnectAttempts})`),this.reconnectTimeout=setTimeout(()=>{this.connect()},n)}clearReconnectTimeout(){this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=void 0)}resetConnectionTimeout(){this.clearConnectionTimeout(),this.connectionTimeout=setTimeout(()=>{this.isConnected&&this.isStarted&&(m.debug("[remote-events] Connection timeout detected, reconnecting..."),this.isConnected=!1,this.eventSource&&(this.eventSource.close(),this.eventSource=void 0),this.scheduleReconnect())},this.config.connectionTimeoutMs)}clearConnectionTimeout(){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=void 0)}clearAllDebounceTimeouts(){this.debounceTimeouts.forEach(e=>clearTimeout(e)),this.debounceTimeouts.clear()}}class zt{static{c(this,"ElementsCache")}elements=new Map;typeIndex=new Map;internalIdIndex=new Map;constructor(e){e&&this.addAll(e)}add(e){const t=e.id;this.elements.set(t,e),this.typeIndex.has(e.type)||this.typeIndex.set(e.type,new Set),this.typeIndex.get(e.type).add(t),e.data?.id&&this.internalIdIndex.set(e.data.id,t)}remove(e){const t=e.id,n=this.elements.delete(t);if(n){const o=this.typeIndex.get(e.type);o&&(o.delete(t),o.size===0&&this.typeIndex.delete(e.type)),e.data?.id&&this.internalIdIndex.delete(e.data.id)}return n}put(e){this.elements.has(e.id)&&this.remove(e),this.add(e)}get(e){return this.elements.get(e)}getByInternalId(e){const t=this.internalIdIndex.get(e);if(t)return this.elements.get(t)}getElementsByType(e){const t=this.typeIndex.get(e);return t?Array.from(t).map(n=>this.elements.get(n)).filter(n=>n!==void 0):[]}getAll(){return Array.from(this.elements.values())??[]}getTypes(){return Array.from(this.typeIndex.keys())}addAll(e){for(const t of e)t&&this.add(t)}removeAll(e){for(const t of e)this.remove(t)}getElementIdsByType(e){return this.typeIndex.get(e)}clear(){this.elements.clear(),this.typeIndex.clear(),this.internalIdIndex.clear()}getAllIds(){return new Set(this.elements.keys())}}const pe="connectors",X="development",it={};async function Vt(r={}){const{onProgress:e}=r,t=new Set,o=(await $.withClient(d=>d.get("org-workspace-id"))).id,i={};m.info("[connectors] Loading custom connectors"),await $.withClient(d=>d.get(`/connectors?workspaceId=${o}`)),m.info("[connectors] Loading public connectors");const s=ee(),l=(P.existsSync(s)?P.readdirSync(s):[]).filter(d=>{if(d.startsWith("."))return!1;const h=I.join(s,d);try{return P.statSync(h).isDirectory()}catch{return!1}});for(const d of l){m.info(`[connectors] Loading connector from: ${d}`);const h=P.readdirSync(I.join(s,d)),f=await st(d);if(!f)continue;e?.("pushing",f.name),"baseUri"in f&&delete f.baseUri;let p;if(f.uuid&&(p=await $.withClient(E=>E.get(`/connectors/${f.uuid}`),!1)),p)i[f.id]=p.id,m.info(`[connectors] Matched ${f.name} uuid: ${f.uuid}`),p.isPublic||(p.archivedAt&&(m.info(`[connectors] Restoring archived connector ${f.name}`),await $.withClient(E=>E.post(`connectors/${p.id}/restore`))),m.info(`[connectors] Updating connector ${f.name}`),await $.withClient(E=>E.patch(`connectors/${p.id}`,{...f,workspaceId:o})));else if(!i[f.id]&&!p?.isPublic){let E=!1;try{const S=await at({connectorId:f.id});S&&S.isPublic&&(E=!0)}catch{}if(!E){m.info(`[connectors] Creating custom connector ${f.name} (${f.key})`);const S=await $.withClient(N=>N.post("connectors",{...f,workspaceId:o}));i[f.id]=S.id}}const C=h.filter(E=>P.statSync(I.join(s,d,E)).isDirectory());for(const E of C)await Wr({connector:f,version:E,connectorId:i[f.id]}),t.add(f.id);e?.("pushed",f.name)}return{connectorsMapping:i,pushedConnectors:Array.from(t)}}c(Vt,"pushConnectors");async function Yt({connectorId:r,connectorVersion:e,allConnectors:t,pulledConnectors:n,pulledConnectorVersions:o}){if(!r||o[r]?.has(e))return;const i=jt(),s=await at({connectorId:r});if(!s.isPublic||t){if(!s?.key){console.error(`[connectors] Connector ${r} has no key. Skipping..`),m.error(`[connectors] Connector ${r} has no key. Skipping..`);return}n.has(r)||(await Jr({basePath:i,connector:s}),n.add(r)),o[r]||(o[r]=new Set),o[r].has(e)||(await Gr({connector:s,connectorVersion:e,basePath:i}),o[r].add(e))}}c(Yt,"pullRemoteConnector");function ee(){const r=tt();return I.join(r.membraneDirPath,pe)}c(ee,"getConnectorsPath");async function st(r){const e=I.join(ee(),r,`${r}.yml`);return nt(e,!1)}c(st,"readConnector");async function Br(r,e){return m.info(`[connectors] Zipping ${r} into ${e}`),new Promise((t,n)=>{const o=P.createWriteStream(e),i=Dt("zip",{zlib:{level:9}});o.on("close",()=>{m.success(`[connectors] Successfully created ${e}`),t()}),o.on("end",()=>{m.info("[connectors] Data has been drained")}),i.on("warning",a=>{a.code==="ENOENT"?console.warn(a):n(a)}),i.on("error",a=>{n(a)}),i.pipe(o);const s=P.readdirSync(r);for(const a of s){const l=I.join(r,a),d=P.statSync(l);d.isFile()?i.file(l,{name:a}):d.isDirectory()&&i.directory(l,a)}i.finalize()})}c(Br,"createZipArchive");async function _r(r,e){return m.info(`[connectors] Unzipping into ${e}`),new Promise((t,n)=>{const o=ke.Parse();o.on("entry",i=>{const s=i.path;if(i.type==="Directory"){const l=I.join(e,s);P.mkdirSync(l,{recursive:!0}),i.autodrain()}else{const l=I.join(e,s),d=I.dirname(l);P.mkdirSync(d,{recursive:!0});const h=P.createWriteStream(l);i.pipe(h),h.on("finish",()=>{})}}),o.on("end",()=>{m.success(`[connectors] Successfully extracted to ${e}`),t()}),o.on("error",i=>{n(i)}),o.write(r),o.end()})}c(_r,"extractZipArchive");async function Wr({connector:r,version:e,connectorId:t}){const n=I.join(ee(),Q(r),Zt(e)),o=I.join(n,"src"),i=I.join(n,"src.zip"),s=P.existsSync(i);if(P.existsSync(o)&&(m.info(`[connectors] Archiving source code for ${r.name} version ${e}`),await Br(o,i)),!P.existsSync(i)){m.warning(`[connectors] No source code found for ${r.name} version ${e}`);return}try{const a=new Ot;if(a.append("file",P.createReadStream(i),"file.zip"),m.info(`[connectors] Pushing connector version ${e} for ${r.name}`),e==X)m.info(`[connectors] Uploading connector ${t}`),await $.withClient(l=>l.post(`connectors/${t}/upload`,a,{headers:{...a.getHeaders()}}));else{if(a.append("version",e),a.append("changelog","Imported Version"),(await $.withClient(d=>d.get(`/connectors/${t}/versions`))).find(d=>d.version==e)){m.info(`[connectors] Version ${e} already published`);return}m.info(`[connectors] Publishing version ${e} of connector ${t}`),await $.withClient(d=>d.post(`connectors/${t}/publish-version`,a,{headers:{...a.getHeaders()}}))}m.success(`Successfully pushed connector version ${e} for ${r.name}`)}catch(a){m.error(`Error pushing connector version ${e} for ${r.name}: ${a}`),console.error(`[connectors] Error pushing connector version ${e} for ${r.name}: ${a}`)}finally{!s&&P.existsSync(i)&&(m.info(`[connectors] Cleaning up temporary zip file for ${r.name} version ${e}`),P.unlinkSync(i))}}c(Wr,"pushConnectorVersion");async function at({connectorId:r}){if(r){if(it[r])return it[r];try{const e=await $.withClient(t=>t.get(`connectors/${r}`),!1);return it[r]=e,e}catch(e){return m.error(`[connectors] Failed to get connector ${r}: ${e}`),console.error(`[connectors] Failed to get connector ${r}: ${e}`),null}}}c(at,"getConnector");async function Jr({basePath:r,connector:e}){const t=Q(e),n=I.join(r,pe,t);P.mkdirSync(n,{recursive:!0});const o=I.join(n,`${Q(e)}.yml`);P.writeFileSync(o,G.dump(e)),m.info(`[connectors] Pulled connector ${e.name}`)}c(Jr,"pullConnector$1");async function Gr({connector:r,connectorVersion:e,basePath:t}){const n=Q(r),o=Zt(e),i=I.join(t,"connectors",n,o),s=await $.withClient(l=>l.get(`connectors/${r.id}/download`,{version:e},{responseType:"arraybuffer",headers:{Accept:"application/zip"},timeout:1e6}));P.mkdirSync(i,{recursive:!0});const a=I.join(i,"src.zip");if(P.writeFileSync(a,s),!e){const l=I.join(i,"src");P.mkdirSync(l,{recursive:!0}),await _r(s,l)}m.info(`[connectors] Pulled connector version: ${r.name} (${o})`)}c(Gr,"pullConnectorVersion");function Q(r){return r.key}c(Q,"getConnectorDirName");function Zt(r){return r??X}c(Zt,"getConnectorVersionDirName");function Hr(r){const e=jt(),t=Q(r);return I.join(e,pe,t)}c(Hr,"getConnectorDirPath");function zr(r){return r.match(`${pe}/[^/]+/${X}/src/.*`)!==null}c(zr,"isConnectorSourceFile");async function Vr(r){const e=r.match(`${pe}/([^/]+)/${X}/src/(.*)`);if(!e)return;const t=e[1],n=e[2],o=await st(t);if(!o){m.warning(`[connectors] Connector ${t} not found. Ignoring file change`);return}const i=o.id,s=P.readFileSync(r,"utf-8");await $.withClient(a=>a.put(`connectors/${i}/files/${n}`,s,{headers:{"Content-Type":"text/plain"}})),m.info(`[connectors] Pushed file ${n} for connector ${o.name}`)}c(Vr,"putConnectorFile");async function Yr(r){const e=r.match(`${pe}/([^/]+)/${X}/src/(.*)`);if(!e)return;const t=e[1],n=e[2],o=await st(t);if(!o){m.warning(`[connectors] Connector ${t} not found. Ignoring file change`);return}const i=o.id;await $.withClient(s=>s.delete(`connectors/${i}/files/${n}`)),m.info(`[connectors] Deleted file ${n} for connector ${o.name}`)}c(Yr,"deleteConnectorFile");async function Zr(r,e){try{const t=await $.withClient(s=>s.get(`connectors/${r}`));if(!t){m.warning(`[connectors] Connector ${r} not found`);return}const n=await $.withClient(s=>s.get(`connectors/${r}/files/${e}`)),o=Q(t),i=I.join(ee(),o,X,"src",e);P.mkdirSync(I.dirname(i),{recursive:!0}),n!=null?(P.writeFileSync(i,n),m.info(`[connectors] Pulled file ${e} for connector ${t.name}`)):P.existsSync(i)&&(P.unlinkSync(i),m.info(`[connectors] Deleted file ${e} for connector ${t.name}`))}catch(t){m.error(`[connectors] Failed to pull connector file ${e} for connector ${r}: ${t}`),console.error(`[connectors] Failed to pull connector file ${e} for connector ${r}: ${t}`)}}c(Zr,"pullConnectorFile");async function Xr(r,e){const t=await $.withClient(i=>i.get(`connectors/${r}`),!1);if(!t){m.warning(`[connectors] Connector ${r} not found`);return}const n=Q(t),o=I.join(ee(),n,X,"src",e);P.existsSync(o)&&(P.unlinkSync(o),m.info(`[connectors] Deleted file ${e} for connector ${n}`))}c(Xr,"deleteLocalConnectorFile");async function Qr(r,e,t){if(t&&e!==t)try{const n=await $.withClient(l=>l.get(`connectors/${r}`),!1);if(!n){m.warning(`[connectors] Connector ${r} not found`);return}const o=Q(n),i=I.join(ee(),o,X,"src"),s=I.join(i,e),a=I.join(i,t);P.existsSync(s)&&(P.mkdirSync(I.dirname(a),{recursive:!0}),P.renameSync(s,a),m.info(`[connectors] Renamed directory from ${e} to ${t} for connector ${o}`))}catch(n){m.error(`[connectors] Failed to rename directory ${e} to ${t} for connector ${r}: ${n}`)}}c(Qr,"renameLocalConnectorDirectory");async function eo(r,e){try{const t=await $.withClient(i=>i.get(`connectors/${r}`),!1);if(!t){m.warning(`[connectors] Connector ${r} not found`);return}const n=Q(t),o=I.join(ee(),n,X,"src",e);if(P.existsSync(o)){const i=I.resolve(ee());if(!I.resolve(o).startsWith(i))return;P.rmSync(o,{recursive:!0,force:!0}),m.info(`[connectors] Deleted directory ${e} for connector ${n}`)}}catch(t){m.error(`[connectors] Failed to delete directory ${e} for connector ${r}: ${t}`)}}c(eo,"deleteLocalConnectorDirectory");const F={LogAdded:"logAdded",StateChanged:"stateChanged",StatsChanged:"statsChanged",ConflictsChanged:"conflictsChanged",McpStatusChanged:"mcpStatusChanged",McpServersChanged:"mcpServersChanged",ConfigChanged:"configChanged"};class to extends rt{static{c(this,"WorkspaceNotifications")}constructor(e){super(),this.config=e,m.setNotificationHandler(this)}clientId;heartbeatInterval;isCleaningUp=!1;async connectToRemote(){await this.registerWithRemoteServer(),await this.startHeartbeatLoop()}async setState(e){this.emit(F.StateChanged,{state:e}),await this.emitRemote({status:e})}setConflicts(e){this.emit(F.ConflictsChanged,{conflicts:e})}setConfig(e){this.emit(F.ConfigChanged,{config:e})}setStats(e){this.emit(F.StatsChanged,{stats:e})}addLog(e){this.emit(F.LogAdded,{log:e})}setMcpStatus(e){this.emit(F.McpStatusChanged,{status:e})}async setMcpServers(e){this.emit(F.McpServersChanged,{servers:e}),await this.emitRemote({mcpServers:e.map(t=>({name:t.agentName,totalRequests:t.totalRequests}))})}async cleanup(){!this.clientId||this.isCleaningUp||(this.isCleaningUp=!0,this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=void 0),await this.withErrorHandling(async()=>{await $.withClient(e=>e.delete(`/local-clients/${this.clientId}`))}),this.clientId=void 0)}async registerWithRemoteServer(){if(this.clientId)return;const e=await this.withErrorHandling(async()=>await $.withClient(t=>t.post("/local-clients",{hostname:At.hostname(),workingDirectory:process.cwd()})));e?.id?this.clientId=e.id:this.addLog({timestamp:new Date().toISOString(),message:"Failed to register with remote server",type:"error"})}async startHeartbeatLoop(){this.heartbeatInterval=setInterval(async()=>{this.clientId&&await this.sendHeartbeat()},this.config.heartbeatIntervalMs)}async sendHeartbeat(){this.clientId&&await this.withErrorHandling(async()=>{await $.withClient(e=>e.post(`/local-clients/${this.clientId}/keep-alive`,{}))})}async emitRemote(e){this.clientId&&await this.withErrorHandling(async()=>{await $.withClient(t=>t.patch(`/local-clients/${this.clientId}`,e))})}async withErrorHandling(e){try{return await e()}catch(t){const n=t instanceof Error?t.message:String(t);return this.addLog({timestamp:new Date().toISOString(),message:`Failed to connect to remote: ${n}`,type:"error"}),null}}}const te=new to({heartbeatIntervalMs:15e3}),Xt=[T.AppDataSchema,T.AppEventType,T.DataLinkTable,T.DataSource,T.FieldMapping,T.Action,T.Flow,T.Package];class Ee{static{c(this,"ElementSyncService")}localWatcher=void 0;remoteWatcher=void 0;notifier;changes=[];localCache;remoteCache;localRepo;remoteRepo;pulledConnectors=new Set;pulledConnectorVersions={};constructor(){this.notifier=te,this.localCache=new zt,this.remoteCache=new zt,this.localRepo=new Fr(this.localCache),this.remoteRepo=new Lr(this.remoteCache)}clear(){this.changes=[]}needsForcedSync(){return this.changes.some(e=>e.isConflict)}needsSync(){return this.changes.length>0}async getStats(){const e=this.localCache.getAll(),t={};return e.forEach(n=>{t[n.type]=(t[n.type]||0)+1}),t}async fetchElements(){const e=await this.localRepo.getElements(),t=await this.remoteRepo.getElements();this.localCache.addAll(e),this.remoteCache.addAll(t)}async updateElement(e,t){const n=this.getHandler(t),o=this.getCache(t);try{const i=await n.putElement(e);o.put(i)}catch(i){throw m.error(`Failed to update element ${e.id}: ${i}`),i}}async deleteElement(e,t){const n=this.getHandler(t),o=this.getCache(t);try{await n.deleteElement(e,{elements:n.cache.getAll(),connectorsMapping:n.connectorsMapping}),o.remove(e)}catch(i){throw m.error(`Failed to delete element ${e.id}: ${i}`),i}}async pullConnectors(e=!1){const t=this.remoteCache.getElementsByType(T.Integration).map(n=>n.data);for(const n of t){const o=n.connectorId,i=n.connectorVersion;o&&await Yt({connectorId:o,connectorVersion:i,allConnectors:e,pulledConnectors:this.pulledConnectors,pulledConnectorVersions:this.pulledConnectorVersions})}}async pushConnectors(){const{connectorsMapping:e}=await Vt();this.remoteRepo.setConnectorsMapping(e)}getHandler(e){return e===B.INCOMING?this.localRepo:(this.remoteRepo.setSourceCache(this.localCache),this.remoteRepo)}getCache(e){return e===B.INCOMING?this.localCache:this.remoteCache}async startWatching(){this.localWatcher=new Ur({cwd:process.cwd(),lockTimeoutMs:1e3}),this.localWatcher.on(_.Updated,e=>this.handleLocalEvent(e,_.Updated)),this.localWatcher.on(_.Deleted,e=>this.handleLocalEvent(e,_.Deleted)),await this.localWatcher.start(),m.success("[local] Tracking changes.."),this.remoteWatcher=new qr,this.remoteWatcher.on(ot.Updated,({elementId:e,elementType:t})=>this.handleRemoteElementEvent(e,t)),this.remoteWatcher.on(ot.ConnectorFileUpdated,({connectorId:e,filePath:t,eventType:n,newPath:o})=>this.handleRemoteConnectorFileEvent(e,t,n,o)),await this.remoteWatcher.start(),m.success("[remote] Tracking changes..")}async stopWatching(){this.localWatcher&&(await this.localWatcher.stop(),this.localWatcher=void 0),this.remoteWatcher&&(await this.remoteWatcher.stop(),this.remoteWatcher=void 0)}async handleRemoteElementEvent(e,t){try{const n=await this.remoteRepo.getByInternalId(e,t),o=!!n?.data.archivedAt||!!n?.data.isDeactivated;if(!n||o){const s=n||this.remoteCache.getByInternalId(e);return s?(m.info(`[${this.getDirectionLabel(B.INCOMING)}] Deleted: ${s.id}`),this.localWatcher?.executeWithPathLock(s.absolutePath,()=>this.deleteElement(s,B.INCOMING))):void 0}if(m.info(`[${this.getDirectionLabel(B.INCOMING)}] Updated: ${n.id}`),await this.localWatcher?.executeWithPathLock(n.absolutePath,async()=>this.updateElement(n,B.INCOMING)),t===T.Integration){const s=n.data.connectorId,a=n.data.connectorVersion,l=await at({connectorId:s});if(!l?.key)return;const d=Hr(l);await this.localWatcher?.executeWithPathLock(d,async()=>Yt({connectorId:s,connectorVersion:a,allConnectors:!1,pulledConnectors:this.pulledConnectors,pulledConnectorVersions:this.pulledConnectorVersions}))}}catch(n){m.error(`[sync] Error handling remote event: ${n}`)}}async handleRemoteConnectorFileEvent(e,t,n,o){try{switch(n){case Fe.ConnectorFileDeleted:await Xr(e,t);break;case Fe.ConnectorDirectoryRenamed:await Qr(e,t,o);break;case Fe.ConnectorDirectoryDeleted:await eo(e,t);break;default:await Zr(e,t);break}}catch(i){m.error(`[sync] Error handling remote connector file event: ${i}`)}}async handleLocalEvent(e,t){try{if(zr(e.filePath))switch(t){case _.Updated:await Vr(e.filePath);break;case _.Deleted:await Yr(e.filePath);break}else{let n=M.fromPathAndData(e.filePath,e.data);if(!n){const o=M.idFromPath(e.filePath);if(!o||(n=this.remoteCache.get(o),!n))return}switch(m.info(`[${this.getDirectionLabel(B.OUTGOING)}] ${Yn(t)}: ${n.id}`),t){case _.Updated:await this.updateElement(n,B.OUTGOING);break;case _.Deleted:await this.deleteElement(n,B.OUTGOING);break}}}catch(n){m.error(`[sync] Error handling local event: ${n}`)}}detectIncomingChanges(){this.clearChanges();const e=Ee.getChanges(B.INCOMING,this.remoteCache,this.localCache);return this.updateChanges(e),e}detectOutgoingChanges(){this.clearChanges();const e=Ee.getChanges(B.OUTGOING,this.localCache,this.remoteCache);return this.updateChanges(e),e}async resolveChanges(){if(!this.needsSync())return;m.info("[resolver] Resolving changes.."),m.info("[resolver] Resolving integration elements");const e=this.changes.filter(o=>o.element.type===T.Integration);await Promise.all(e.map(async o=>this.resolveChange(o))),e.length>0&&(await this.fetchElements(),this.changes=this.changes.length>0&&this.changes[0]?.direction===B.INCOMING?this.detectIncomingChanges():this.detectOutgoingChanges(),this.changes=this.changes.filter(o=>o.element.type!==T.Integration)),m.info("[resolver] Resolving universal elements");const t=this.changes.filter(o=>!o.element.hasParent());for(const o of Xt){const i=t.filter(s=>s.element.type===o);m.info(`[resolver] Resolving ${o} elements`),await Promise.all(i.map(async s=>this.resolveChange(s)))}m.info("[resolver] Resolving integration level elements");const n=this.changes.filter(o=>o.element.hasParent());for(const o of Xt){const i=n.filter(s=>s.element.type===o);m.info(`[resolver] Resolving ${o} elements`),await Promise.all(i.map(async s=>this.resolveChange(s)))}m.success("[resolver] Resolved changes")}async resolveChange(e){switch(e.type){case Z.DELETE:return this.deleteElement(e.element,e.direction);case Z.CREATE:return this.updateElement(e.element,e.direction);case Z.UPDATE:return this.updateElement(e.element,e.direction)}}static getChanges(e,t,n){const o=t.getAllIds(),i=n.getAllIds(),s=new Set([...o,...i]),a=[];for(const l of s){const d=t.get(l),h=n.get(l),f=Ee.detectChangeForElement(d,h,e);f&&a.push(f)}return a}updateChanges(e){if(this.changes=e,this.needsForcedSync()){const t=e.filter(n=>n.isConflict);m.warning("[resolver] Conflicts detected"),this.notifier.setConflicts(t)}}clearChanges(){this.changes=[]}getDirectionLabel(e){switch(e){case B.INCOMING:return"local\u2190remote";case B.OUTGOING:return"local\u2192remote"}}static detectChangeForElement(e,t,n){return e&&!t?{type:Z.CREATE,element:e,direction:n,isConflict:!1}:!e&&t?{type:Z.DELETE,element:t,direction:n,isConflict:!0}:e&&t&&!e.isEqual(t)?{type:Z.UPDATE,element:e,direction:n,isConflict:!1}:null}}const ne=x.join(or.tmpdir(),"membrane-mcp-status"),Qt=3e4;class no{static{c(this,"McpStatusService")}constructor(e=2e3){this.pollIntervalMs=e}isRunning=!1;pollInterval;async start(){this.isRunning||(this.isRunning=!0,this.pollInterval=setInterval(async()=>await this.checkStatus(),this.pollIntervalMs),await this.checkStatus())}async stop(){this.pollInterval&&(clearInterval(this.pollInterval),this.pollInterval=void 0,this.isRunning=!1)}async checkStatus(){try{const e=process.cwd(),t=Ae(void 0,e),n=en(e);t&&te.setMcpStatus(t),await te.setMcpServers(n)}catch{m.error("Failed to check MCP status")}}}function Ae(r,e){try{const t=e||process.cwd();if(!r){const o=en(t);return o.length===0?null:o[0]}const n=ut(r,t);if(v.existsSync(n)){const o=v.statSync(n),i=new Date;if(i.getTime()-o.mtime.getTime()>Qt)return Ce(r,t),null;const a=v.readFileSync(n,"utf8"),l=JSON.parse(a);if(l.isRunning){const d=new Date(l.lastActivity).getTime();if(i.getTime()-d>Qt)return Ce(r,t),null}return l}}catch{r&&e&&Ce(r,e)}return null}c(Ae,"getMcpStatus");function en(r){try{const e=r||process.cwd(),t=lt(e);if(!v.existsSync(ne))return[];const n=v.readdirSync(ne),o=[];for(const i of n){const s=i.match(new RegExp(`^mcp-${t}-(\\d+)\\.json$`));if(s){const a=parseInt(s[1],10),l=Ae(a,e);l&&o.push(l)}}return o.sort((i,s)=>new Date(s.startTime).getTime()-new Date(i.startTime).getTime())}catch{return[]}}c(en,"getAllMcpStatusFiles");function ct(r){try{const t={...Ae(r.processId,r.cwd)||{isRunning:!1,startTime:new Date().toISOString(),lastActivity:new Date().toISOString(),toolsCount:0,totalRequests:0,processId:r.processId,cwd:r.cwd,agentName:process.env.AGENT_NAME||"Unnamed Agent"},...r};v.existsSync(ne)||v.mkdirSync(ne,{recursive:!0});const n=ut(r.processId,r.cwd);v.writeFileSync(n,JSON.stringify(t,null,2))}catch{}}c(ct,"updateMcpStatus");function Ce(r,e){try{const t=e||process.cwd();if(r){const n=ut(r,t);v.existsSync(n)&&v.unlinkSync(n)}else{const n=lt(t);if(v.existsSync(ne)){const o=v.readdirSync(ne);for(const i of o)i.match(new RegExp(`^mcp-${n}-\\d+\\.json$`))&&v.unlinkSync(x.join(ne,i))}}}catch{}}c(Ce,"clearMcpStatus");function ro(r,e){const t=Ae(r,e);t&&ct({processId:r,cwd:e,totalRequests:t.totalRequests+1,lastRequestTime:new Date().toISOString(),lastActivity:new Date().toISOString()})}c(ro,"trackToolExecution");function lt(r){return Qn("md5").update(r).digest("hex").slice(0,8)}c(lt,"getCwdHash");function ut(r,e){const t=lt(e);return x.join(ne,`mcp-${t}-${r}.json`)}c(ut,"getStatusFilePath");const De={Agent:"agent",Cli:"cli"},k={NOT_INITIALIZED:"not_initialized",SETTING_UP:"setting_up",INITIALIZED:"initialized",NOT_SYNCED:"not_synced",PULLING:"pulling",PUSHING:"pushing",RESOLVING:"resolving",CONFLICTS:"conflicts",SYNCED:"synced",WATCHING:"watching",ERROR:"error"};class oo{static{c(this,"MembraneCLIService")}constructor(e,t,n=()=>process.exit(0)){this.mode=e,this.cwd=t,this.onShutdown=n,this.notifier=te,this.mcpStatusService=new no,this.syncService=new Ee,this.setupProcessCleanup()}initialized=!1;notifier;mcpStatusService;syncService;isShuttingDown=!1;currentConfig=null;get config(){return this.currentConfig}getSyncedElements(){return this.syncService.localCache.getAll()}getSyncedElementsByType(e){return this.syncService.localCache.getElementsByType(e)}async fetchElements(){await this.syncService.fetchElements()}async pullWorkspace(e={}){let t=!1;try{if(m.setVerboseMode(!!e.verbose),e.rps!==void 0&&$.init({maxRequestsPerSecond:e.rps}),await this.notifier.setState(k.PULLING),await this.syncService.fetchElements(),this.syncService.detectIncomingChanges(),this.syncService.needsForcedSync()&&!e.force){await this.notifier.setState(k.CONFLICTS),e.watch||(t=!0);return}await this.syncService.pullConnectors(e.allConnectors),await this.syncWorkspaces(e)}catch(n){t=!0,m.error(`Failed to pull workspace: ${n}`),await this.notifier.setState(k.ERROR),m.saveLogsToFile("error")}finally{if(e.saveLogs&&m.saveLogsToFile(),t)process.exit(1);else return e?.onComplete?.()}}async pushWorkspace(e={}){let t=!1;try{if(m.setVerboseMode(!!e.verbose),e.rps!==void 0&&$.init({maxRequestsPerSecond:e.rps}),await this.notifier.setState(k.PUSHING),await this.syncService.fetchElements(),this.syncService.detectOutgoingChanges(),this.syncService.needsForcedSync()&&!e.force){await this.notifier.setState(k.CONFLICTS),e.watch||(t=!0);return}await this.syncService.pushConnectors(),await this.syncWorkspaces(e)}catch(n){t=!0,m.error(`Failed to push workspace: ${n}`),await this.notifier.setState(k.ERROR),m.saveLogsToFile("error")}finally{if(e.saveLogs&&m.saveLogsToFile(),t)process.exit(1);else return e?.onComplete?.()}}async syncWorkspaces(e={}){try{e.verbose!==void 0&&m.setVerboseMode(!!e.verbose),await this.notifier.setState(k.RESOLVING),this.syncService.needsSync()&&await this.syncService.resolveChanges();const t=await this.syncService.getStats();this.notifier.setStats(t),await this.notifier.setState(k.SYNCED),e.watch&&(await this.notifier.setState(k.WATCHING),await this.syncService.startWatching())}catch(t){m.error(`Failed to sync local and remote workspaces: ${t}`),await this.notifier.setState(k.ERROR),m.saveLogsToFile("error")}}async init({force:e=!1}={}){if(!(this.initialized&&!e)){await this.notifier.setState(k.NOT_INITIALIZED);try{await this.loadConfig(),le.isCacheDefined()?(await this.initServices(),this.initialized=!0,await this.notifier.setState(k.INITIALIZED)):(this.initialized=!1,await this.notifier.setState(k.SETTING_UP))}catch(t){m.error(`Failed to initialize services: ${t}`),await this.notifier.setState(k.ERROR),m.saveLogsToFile("error"),this.onShutdown()}}}async loadConfig(){this.currentConfig=le.loadConfig(this.cwd),this.notifier.setConfig(this.currentConfig)}async updateConfig(e){const t={...this.currentConfig,...e};if(!(JSON.stringify(t)!==JSON.stringify(this.currentConfig)))return;await this.stopServices();const o=le.updateConfig(t);this.currentConfig=o,await this.init({force:!0})}async shutdown(){!this.initialized||this.isShuttingDown||(this.isShuttingDown=!0,this.mode===De.Agent&&(await this.notifier.cleanup(),await this.mcpStatusService.stop()),this.initialized=!1,this.onShutdown())}async initServices(){this.mode===De.Agent&&(await this.notifier.connectToRemote(),await this.mcpStatusService.start()),this.syncService.clear()}async stopServices(){this.mode===De.Agent&&(await this.notifier.cleanup(),await this.mcpStatusService.stop())}setupProcessCleanup(){["SIGINT","SIGTERM","uncaughtException","unhandledRejection"].forEach(t=>process.on(t,()=>this.shutdown())),process.on("beforeExit",t=>{t===0&&this.shutdown()})}}const tn=Be(null);function io({children:r,membraneCLIService:e}){const{data:t}=Pt("/account"),[n,o]=D(k.NOT_INITIALIZED),[i,s]=D([]),[a,l]=D({}),[d,h]=D([]),[f,p]=D(null),E=t?.workspaces?.find(S=>S.workspaceKey===f?.workspaceKey)||null;return he(()=>{const S=c(({state:L})=>o(L),"handleStateChanged"),N=c(({stats:L})=>l(L),"handleStatsChanged"),O=c(({log:L})=>h(Te=>[...Te,L]),"handleLogAdded"),U=c(({conflicts:L})=>s(L),"handleConflictsUpdated"),K=c(({config:L})=>p(L),"handleConfigChanged");return e.notifier.on(F.StateChanged,S),e.notifier.on(F.StatsChanged,N),e.notifier.on(F.LogAdded,O),e.notifier.on(F.ConflictsChanged,U),e.notifier.on(F.ConfigChanged,K),e.init(),()=>{e.notifier.off(F.StateChanged,S),e.notifier.off(F.StatsChanged,N),e.notifier.off(F.LogAdded,O),e.notifier.off(F.ConflictsChanged,U),e.notifier.off(F.ConfigChanged,K)}},[]),u(tn.Provider,{value:{state:n,stats:a,logs:d,currentWorkspace:E,conflicts:i,config:f,updateConfig:c(S=>e.updateConfig(S),"updateConfig"),resolveConflicts:c(S=>e.syncWorkspaces(S),"resolveConflicts"),pull:c(S=>e.pullWorkspace(S),"pull"),push:c(S=>e.pushWorkspace(S),"push"),exit:c(()=>e.shutdown(),"exit"),fetchElements:c(()=>e.fetchElements(),"fetchElements"),getSyncedElementsByType:c(S=>e.getSyncedElementsByType(S),"getSyncedElementsByType")},children:r})}c(io,"MembraneCLIServiceProvider");function H(){const r=_e(tn);if(!r)throw new Error("useMembraneCLIService must be used within MembraneCLIServiceProvider");return r}c(H,"useMembraneCLIService");const dt=Be(null),nn=c(()=>{const r=_e(dt);if(!r)throw new Error("useTree must be used within TreeView");return r},"useTree"),so=c(r=>se.Children.count(r)>0,"hasChildren");function ao(r){const e=nn(),{label:t,value:n,isInitiallyExpanded:o}=r,i=Wn(),s=We(e.registerChildItem(t)).current,a=e.isActiveByRef(s),[l,d]=D(o??!1),h={props:r,ref:s,id:i,active:a,expanded:l,setExpanded:d,label:t,value:n,isInitiallyExpanded:o,isParent:!1},{children:f}=r,p=typeof f=="function"?f(h):f;return{...h,props:{...r,children:p},isParent:so(p)}}c(ao,"useTreeItem");function fe(r){const e=nn(),t=ao(r),{expanded:n,isParent:o,props:{children:i},setExpanded:s}=t,{renderValue:a=lo}=r,l=t.ref;Ie(()=>{function p(C){return r.onInput?.(C)?!0:C.active&&C.key.rightArrow&&!n?(s(!0),!0):C.active&&C.key.leftArrow&&n?(s(!1),!0):!1}c(p,"onInput"),l.onInput=p},[l,r.onInput,n,s]),l.firstChild??={parent:l,index:0};let d=l.firstChild;function h(p){const C=d;return C.nextSibling||(C.nextSibling={parent:l,prevSibling:C,index:C.index+1}),d=C.nextSibling,C.label=p,C}c(h,"registerChildItem");function f(){l.lastRenderedChild=d.prevSibling}return c(f,"commitChildren"),Ie(()=>{f()}),b($e,{children:[b(g,{marginLeft:e.depth*2,children:[u(g,{width:2,children:o&&u(y,{children:n?"\u25BC":"\u25B6"})}),co(t),a(t)]}),n&&u(dt.Provider,{value:{...e,depth:e.depth+1,registerChildItem:h},children:i})]})}c(fe,"TreeItem");function co({active:r,label:e}){return u(g,{width:32,children:u(y,{inverse:r,children:e})})}c(co,"defaultRenderLabel");function lo(r){return u(y,{})}c(lo,"defaultRenderValue");const ue=c(({label:r,onPress:e,hotkey:t})=>u(fe,{label:r,onInput:c(({input:n,key:o,active:i})=>i&&o.return||t&&t in o&&o[t]||n===t?(e(),!0):!1,"onInput"),renderValue:c(()=>u(g,{children:u(y,{children:`${t?` (${t})`:""}`})}),"renderValue")}),"ActionTreeItem"),rn=c(({label:r,value:e,onChange:t,disabled:n=!1,mask:o,...i})=>{const[s,a]=D(e),[l,d]=D(!1);return Ie(()=>{l||a(e)},[l,e]),u(fe,{label:r,value:e,onInput:c(({key:h,active:f})=>n?!1:l?(h.escape&&d(!1),h.return&&(t(s),d(!1)),!0):f&&h.return?(d(!0),a(e),!0):!1,"onInput"),renderValue:c(()=>{const h=s,f=o?o.repeat(h.length):h;return u(g,{children:n||!l?u(y,{dimColor:!0,children:f}):b($e,{children:[u(g,{width:f.length+1,children:u(Nt,{...i,focus:l,value:h,onChange:a})}),u(y,{dimColor:!0,children:" \u241B cancel"})]})})},"renderValue")})},"TreeTextField"),uo=c(r=>u(rn,{...r,mask:"*"}),"SecretField"),W=c(({children:r,showHelp:e=!1})=>{const t=We({parent:void 0,label:"<<ROOT>>",index:0}),[n,o]=D(t.current),i={depth:0,isActiveByRef:c(a=>n===a,"isActiveByRef"),registerChildItem:c(()=>t.current,"registerChildItem"),activeItemRef:n};Ie(()=>{o(a=>a.parent?a.parent.lastRenderedChild&&a.index>a.parent.lastRenderedChild.index?a.parent.lastRenderedChild:a:t.current.firstChild??t.current)});function*s(a){a&&(yield a,yield*s(a.firstChild),a.nextSibling&&a!==a.parent?.lastRenderedChild&&(yield*s(a.nextSibling)))}return c(s,"walkTree"),ae((a,l)=>{if(n.onInput?.({input:a,key:l,active:!0}))return;let d,h;for(const f of s(t.current))if(f.label!=null){if(d===n&&(h=f),f&&f.onInput?.({input:a,key:l,active:f===n}))return;d=f}l.upArrow?o(f=>f.prevSibling?.lastRenderedChild??f.prevSibling??f.parent??t.current):l.downArrow?o(f=>h??f):l.pageUp?o(()=>t.current.firstChild??t.current):l.pageDown?o(()=>t.current.lastRenderedChild??t.current):l.tab?console.debug({label:n.label,nextSibling:n.nextSibling?.label,prevSibling:n.prevSibling?.label,parent:n.parent?.label,firstChild:n.firstChild?.label,lastRenderedChild:n.lastRenderedChild?.label}):l.leftArrow?o(f=>f.parent??t.current):l.rightArrow&&o(f=>f.lastRenderedChild?f.firstChild:f)}),u(dt.Provider,{value:i,children:b(g,{flexDirection:"column",children:[u(fe,{isInitiallyExpanded:!0,label:"rootItem",children:r}),e&&u(g,{marginTop:1,flexDirection:"column",children:u(y,{dimColor:!0,children:"\u2191/\u2193 move \u2022 \u2190 collapse \u2022 \u2192 expand \u2022 Enter/Space select/edit \u2022 Esc exit"})})]})})},"TreeView");W.Item=fe,W.TextField=rn;function de({label:r,elementType:e,isActionExcluded:t,toggleAction:n,generateCode:o}){const[i,s]=D([]),{fetchElements:a,getSyncedElementsByType:l}=H();return he(()=>{c(async()=>{try{await a();const h=l(e);s(h.map(f=>f.data))}catch(h){console.error(String(h))}},"loadElements")()},[e,a,l,s]),u(fe,{label:r,children:i.map(d=>u(fe,{label:d.name,children:e===T.Action&&b($e,{children:[t&&n&&u(ue,{label:`Toggle ${t(d)?"":"(excluded)"}`,onPress:c(()=>{n(d)},"onPress")}),o&&u(ue,{label:"Generate code",onPress:c(()=>{o?.(d)},"onPress")})]})},d.id))})}c(de,"WorkspaceElementsTreeItem");function ho({onComplete:r}){const{config:e,updateConfig:t,fetchElements:n,getSyncedElementsByType:o}=H(),[i,s]=D(""),a=e,l=c(p=>{s(p),setTimeout(()=>s(""),2e3)},"setFlash"),d=c(async(p,C)=>{try{await t({[p]:C}),l("\u2705 Configuration updated!")}catch{l("\u274C Error updating configuration")}},"updateField"),h=c(async()=>{try{if(e){const p=le.saveToFile(e);l(p?"\u2705 Configuration saved successfully!":"\u274C Failed to save configuration"),await n();const C=o(T.Action);await Ze({out:a?.outputDir??"",target:a?.projectType??"typescript",schemasOnly:!1,membraneInterfaces:{actions:C.filter(E=>!a?.excludedActionKeys?.includes(E.key)).map(E=>E.data)}}),l("\u2705 Code generated successfully!")}}catch{l("\u274C Error saving configuration")}},"handleSaveConfig"),f=c(async()=>{try{const p=le.loadConfig();p?(await t(p),l("\u2705 Configuration reloaded successfully!")):l("\u274C No configuration found to reload")}catch{l("\u274C Error reloading configuration")}},"handleReloadConfig");return b(g,{flexDirection:"column",gap:1,children:[u(y,{bold:!0,color:"cyan",children:"\u2699\uFE0F Membrane Configuration Manager"}),u(g,{paddingX:2,children:b(W,{showHelp:!0,children:[b(W.Item,{label:"Configuration",isInitiallyExpanded:!0,children:[b(W.Item,{label:"Project",children:[u(W.TextField,{label:"Workspace Key",value:a?.workspaceKey??"",onChange:c(p=>d("workspaceKey",p),"onChange"),disabled:!0}),u(uo,{label:"Workspace Secret",value:a?.workspaceSecret??"",onChange:c(p=>d("workspaceSecret",p),"onChange"),disabled:!0}),u(W.TextField,{label:"API URI",value:a?.apiUri??"",onChange:c(p=>d("apiUri",p),"onChange")}),u(W.TextField,{label:"Test Customer ID",value:a?.testCustomerId??"",onChange:c(p=>d("testCustomerId",p),"onChange")})]}),b(W.Item,{label:"Code Generation",isInitiallyExpanded:!0,children:[b(W.Item,{label:"Project Type",isInitiallyExpanded:!0,value:a?.projectType,renderValue:c(({value:p})=>u(y,{children:p==="typescript"?"TypeScript":p==="openapi"?"OpenAPI":"(Not set)"}),"renderValue"),children:[u(ue,{label:"Update to TypeScript",onPress:c(()=>d("projectType","typescript"),"onPress")}),u(ue,{label:"Update to OpenAPI",onPress:c(()=>d("projectType","openapi"),"onPress")})]}),u(W.TextField,{label:"Project dir",value:a?.outputDir??"",onChange:c(p=>d("outputDir",p),"onChange")})]}),b(W.Item,{label:"Workspace Elements",children:[u(de,{label:"Actions",elementType:T.Action,isActionExcluded:c(p=>a?.excludedActionKeys?.includes(p.key)??!1,"isActionExcluded"),toggleAction:c(p=>d("excludedActionKeys",[...a?.excludedActionKeys??[],p.key]),"toggleAction"),generateCode:c(p=>{(async()=>{try{await Ze({out:a?.outputDir??"",target:a?.projectType??"typescript",schemasOnly:!1,membraneInterfaces:{actions:[p]}}),l("\u2705 Code generated successfully!")}catch{l("\u274C Error generating code")}})()},"generateCode")}),u(de,{label:"Flows",elementType:T.Flow}),u(de,{label:"Data Sources",elementType:T.DataSource}),u(de,{label:"Field Mappings",elementType:T.FieldMapping}),u(de,{label:"Packages",elementType:T.Package}),u(de,{label:"App Data Schemas",elementType:T.AppDataSchema}),u(de,{label:"App Event Types",elementType:T.AppEventType})]})]}),u(ue,{label:"Save Configuration",onPress:h,hotkey:"s"}),u(ue,{label:"Reload Configuration",onPress:f,hotkey:"r"}),u(ue,{label:"Exit",onPress:c(()=>r?.(),"onPress"),hotkey:"escape"})]})}),i&&u(g,{paddingX:2,children:u(y,{color:i.includes("\u2705")?"green":"red",children:i})})]})}c(ho,"ConfigManager");const on=Be(process.cwd());function po({cwd:r,children:e}){return u(on.Provider,{value:r,children:e})}c(po,"CwdProvider");function fo(){return _e(on)}c(fo,"useCwd");function ht({cwd:r,children:e,membraneCLIService:t}){const n=r||process.cwd();return u(po,{cwd:n,children:u(ir,{value:{fetcher:kr()},children:u(io,{membraneCLIService:t,children:e})})})}c(ht,"Layout");function mo(r,e){r.command("config").alias("install").description("\u26A0\uFE0F EXPERIMENTAL: Manage local membrane configuration with interactive UI").addHelpText("after",["","Examples:"," membrane config # Open interactive config manager",""].join(`
10
- `)).action(()=>{Je(se.createElement(ht,{membraneCLIService:e,children:se.createElement(ho,{onComplete:c(()=>process.exit(0),"onComplete")})}))})}c(mo,"setupConfigCommand");function go({currentPat:r,onSubmit:e}){const[t,n]=D(""),[o,i]=D(!1),[s,a]=D(null),l=et(`/w/0/${Fn}`);return b(g,{flexDirection:"column",borderStyle:"round",borderTop:!0,width:70,paddingX:1,children:[u(g,{marginTop:-1,marginBottom:1,children:u(y,{bold:!0,children:"\u{1F511} Enter your Personal Access Token"})}),u(y,{children:"Please provide your Personal Access Token. You can find it here:"}),u(g,{marginTop:1,marginBottom:1,children:u(y,{color:"yellow",children:l})}),r&&u(y,{dimColor:!0,children:"Press Enter to keep your current token or type a new one."}),u(Nt,{mask:"*",placeholder:`${r?"******":"Enter your token here..."}`,value:t,onChange:n,onSubmit:c(async h=>{a(null),i(!0);try{await e(h),n("")}catch{a("Invalid token. Please try again.")}finally{i(!1)}},"handleSubmit")}),o&&u(g,{marginTop:1,children:b(y,{children:[u(Re,{type:"dots"})," Validating token..."]})}),s&&u(y,{color:"red",children:s})]})}c(go,"PersonalAccessTokenInput");function sn({onExit:r,showEscOption:e=!0}){const[t,n]=D(""),{data:o,error:i,isLoading:s}=Pt("/account"),{updateConfig:a}=H(),l=o?.workspaces,d=s;if(ae((S,N)=>{N.escape&&r?.()}),d)return b(g,{children:[u(Re,{}),u(y,{children:" Fetching workspaces..."})]});if(i)return b(g,{flexDirection:"column",children:[b(y,{color:"red",children:["Error: ",i.message]}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"Press ESC to go back"})})]});const h=l?.filter(S=>S.name.toLowerCase().includes(t.toLowerCase()))??[],f=h.map(S=>({label:S.name,value:S.id})),p=f.length,C=l?.length??0;async function E(S){const N=h.find(K=>K.id===S);if(!N)return;const{key:O,secret:U}=N;!O||!U||(await a({workspaceKey:O,workspaceSecret:U}),r?.())}return c(E,"handleSelect"),b(g,{flexDirection:"column",borderStyle:"round",borderTop:!0,width:70,paddingX:1,children:[u(g,{marginTop:-1,children:u(y,{bold:!0,children:"\u{1F4C1} Select your workspace"})}),b(g,{marginTop:1,children:[u(y,{children:"Search: "}),u(sr,{placeholder:"Enter a search query...",onChange:n})]}),C>5&&b(y,{children:["Showing ",p," of ",C," workspaces."]}),u(g,{marginTop:1,children:u(ar,{options:f,onChange:c(S=>{S&&E(S)},"onChange")})}),e&&u(g,{marginTop:1,children:u(y,{color:"grey",children:"Press ESC to go back"})})]})}c(sn,"SelectWorkspace");var Se=(r=>(r[r.Authenticate=0]="Authenticate",r[r.ConnectWorkspace=1]="ConnectWorkspace",r))(Se||{});const yo={0:"Authenticate in Membrane",1:"Connect a Membrane Workspace"},pt=[Se.Authenticate,Se.ConnectWorkspace];function an({onComplete:r}){const{config:e}=H(),[t,n]=D(!1),[o,i]=D(0),s=!!(e?.workspaceKey&&e?.workspaceSecret),a=Kt(),l=pt[o],d=o+1,h=pt.length,f=pt.map((E,S)=>{let N="pending";return S<o?N="done":S===o&&(N="current"),{id:E,label:yo[E],status:N}});async function p(E){const S=a&&E===""?a:E,N=new qt;try{await N.request("/account",{headers:{Authorization:`Bearer ${S}`}}),$r(S),i(O=>O+1)}catch(O){console.error(O)}}c(p,"handlePatSubmit");function C(){n(!0),r&&r()}return c(C,"handleWorkspaceSelected"),ae((E,S)=>{s&&S.escape&&r&&r()}),t?u(g,{children:u(y,{children:"\u2705 Setup complete. You are ready to go!"})}):b(g,{flexDirection:"column",alignSelf:"flex-start",gap:1,children:[b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:70,children:[u(g,{marginTop:-1,marginBottom:1,children:b(y,{bold:!0,children:["\u{1F6E0}\uFE0F Setup \u2014"," ",b(y,{color:"cyan",children:["Step ",d," of ",h]}),s&&u(y,{color:"grey",children:" [esc: go back]"})]})}),u(g,{flexDirection:"column",paddingLeft:2,children:f.map(E=>u(wo,{status:E.status,label:E.label},E.id))})]}),l===Se.Authenticate&&u(go,{currentPat:a,onSubmit:p}),l===Se.ConnectWorkspace&&u(sn,{onExit:C,showEscOption:!1})]})}c(an,"Setup");function wo({status:r,label:e}){return b(g,{children:[b(g,{width:2,children:[r==="current"&&u(Re,{type:"dots"}),r==="done"&&u(y,{children:"\u2705"})]}),u(y,{dimColor:r!=="current",children:e})]})}c(wo,"StepDisplay");function Co(r,e){r.command("init").description("Run interactive setup for Membrane project").option("--key <key>","Workspace key for non-interactive setup").option("--secret <secret>","Workspace secret for non-interactive setup").addHelpText("after",["","Examples:"," membrane init # Run interactive setup"," membrane init --key KEY --secret SEC # Non-interactive setup with key and secret",""].join(`
11
- `)).action(t=>{t.key&&t.secret?le.saveToFile({workspaceKey:t.key,workspaceSecret:t.secret})?(console.error("\u2705 Configuration saved to membrane.config.yml"),process.exit(0)):(console.error("Error writing configuration file"),process.exit(1)):t.key||t.secret?(console.error("Error: Both --key and --secret must be provided for non-interactive mode"),process.exit(1)):Je(se.createElement(ht,{membraneCLIService:e,children:se.createElement(an,{onComplete:c(()=>process.exit(0),"onComplete")})}))})}c(Co,"setupInitCommand");const So=86400;async function bo(r,e,t,n){const o={iss:r,isAdmin:!0};return t&&(o.id=t),Ge.sign(o,e,{expiresIn:So})}c(bo,"generateMcpAccessToken");async function vo(r,e){return(await ge.get(`${r}/docs-json`,{headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"}})).data}c(vo,"fetchOpenApiSchema");function re(r,e=!0,t,n=new Set){if(!r)return e?A.string():A.string().optional();if(Object.keys(r).length===0)return e?A.any():A.any().optional();if(r.$ref){const i=r.$ref.replace("#/components/schemas/","");if(n.has(i))return A.any();if(n.add(i),t?.schemas?.[i]){const s=t.schemas[i];return re(s,e,t,n)}return A.any()}let o;if(r.type==="object"||r.properties){const i={};if(r.properties)for(const[s,a]of Object.entries(r.properties)){const l=r.required?.includes(s)??!1;i[s]=re(a,l,t,n)}if(Object.keys(i).length>0){if(o=A.object(i),r.additionalProperties)if(typeof r.additionalProperties=="object"){const s=re(r.additionalProperties,!1,t,n);o=o.catchall(s)}else r.additionalProperties===!0&&(o=o.passthrough())}else if(r.additionalProperties&&typeof r.additionalProperties=="object"){const s=re(r.additionalProperties,!1,t,n);o=A.record(A.string(),s)}else o=A.record(A.string(),A.any())}else if(r.type==="array"){const i=r.items?re(r.items,!0,t,n):A.any();o=A.array(i)}else if(r.anyOf)o=A.any();else{switch(r.type){case"integer":o=A.coerce.number().int();break;case"number":o=A.coerce.number();break;case"boolean":o=A.coerce.boolean();break;case"string":default:o=A.string();break}r.format==="uuid"?o=A.string().uuid():r.format==="email"?o=A.string().email():r.format==="date"?o=A.string().regex(/^\d{4}-\d{2}-\d{2}$/):r.format==="date-time"&&(o=A.string().datetime()),r.enum&&(o=A.enum(r.enum)),(r.type==="integer"||r.type==="number")&&(r.minimum!==void 0&&(o=o.min(r.minimum)),r.maximum!==void 0&&(o=o.max(r.maximum))),r.type==="string"&&(r.minLength!==void 0&&(o=o.min(r.minLength)),r.maxLength!==void 0&&(o=o.max(r.maxLength)))}return e?o:o.optional()}c(re,"convertOpenApiSchemaToZod");function cn(r){const e=r.match(/\{([^}]+)\}/g);return e?e.map(t=>t.slice(1,-1)):[]}c(cn,"extractPathParameters");function Eo(r,e,t,n,o,i){const s=r.operationId||`${t}_${e.replace(/[^a-zA-Z0-9]/g,"_")}`,a=r.description||r.summary||`${t.toUpperCase()} ${e}`,l={},d={},h={};if(r.parameters){for(const p of r.parameters)if(p.in==="path")d[p.name]=re(p.schema,!0,o).describe(p.description||`Path parameter: ${p.name}`);else if(p.in==="query"){const C=p.required===!0;h[p.name]=re(p.schema,C,o).describe(p.description||`Query parameter: ${p.name}`)}}if(Object.keys(d).length>0&&(l.params=A.object(d).describe("Path parameters")),Object.keys(h).length>0&&(l.query=A.object(h).describe("Query parameters")),r.requestBody&&r.requestBody.content){const p=r.requestBody.required===!0;if(r.requestBody.content["application/json"]){const C=r.requestBody.content["application/json"].schema;C?l.body=re(C,p,o).describe("Request body (JSON)"):l.body=A.any().describe("Request body (JSON)")}else r.requestBody.content["application/octet-stream"]||r.requestBody.content["text/plain"]?l.body=p?A.string().describe("Request body (binary/text)"):A.string().optional().describe("Request body (binary/text)"):l.body=A.any().describe("Request body")}const f=Object.keys(l).length>0?A.object(l):A.object({});return{name:s,description:a,parameters:f,async execute(p){try{const C=cn(e);if(C.length>0){if(!p.params)throw new Error(`Missing required path parameters: ${C.join(", ")}`);const K=C.filter(L=>!(L in p.params));if(K.length>0)throw new Error(`Missing required path parameters: ${K.join(", ")}`)}let E=`${n}${e}`;if(p.params)for(const[K,L]of Object.entries(p.params)){const Te=`{${K}}`;E.includes(Te)&&(E=E.replace(Te,String(L)))}const S=cn(E);if(S.length>0)throw new Error(`Unresolved path parameters: ${S.join(", ")}`);const N=new URLSearchParams;if(p.query)for(const[K,L]of Object.entries(p.query))L!=null&&N.append(K,String(L));N.toString()&&(E+=`?${N.toString()}`);const O={method:t.toUpperCase(),headers:{Authorization:`Bearer ${i}`}};p.body&&t.toLowerCase()!=="get"&&(r.requestBody?.content?.["application/json"]?(O.headers["Content-Type"]="application/json",O.data=p.body):r.requestBody?.content?.["application/octet-stream"]?(O.headers["Content-Type"]="application/octet-stream",O.data=p.body):r.requestBody?.content?.["text/plain"]?(O.headers["Content-Type"]="text/plain",O.data=p.body):(O.headers["Content-Type"]="application/json",O.data=p.body));const U=await ge.request({url:E,...O});return{content:[{type:"text",text:U.data===""?"":JSON.stringify(U.data,null,2)}]}}catch(C){return ge.isAxiosError(C)?{content:[{type:"text",text:`Error: ${C.response?.data?`HTTP ${C.response.status}: ${C.response.statusText} - ${JSON.stringify(C.response.data)}`:`HTTP ${C.response?.status||"unknown"}: ${C.message}`}`}],isError:!0}:C instanceof Error?{content:[{type:"text",text:`Error: API call failed: ${C.message}`}],isError:!0}:{content:[{type:"text",text:"Error: API call failed with unknown error"}],isError:!0}}}}}c(Eo,"createApiTool");function To(r,e,t){const n=[];if(!r.paths)return n;const o=r.components||{};for(const[i,s]of Object.entries(r.paths))if(typeof s=="object"&&s!==null){for(const[a,l]of Object.entries(s))if(["get","post","put","delete","patch"].includes(a)&&l&&typeof l=="object"){const d=Eo(l,i,a,e,o,t);n.push(d)}}return n}c(To,"convertOpenApiToTools");function xo(r){r.command("mcp").description("Launch MCP server with OpenAPI endpoints as tools (API URI is read from environment variables or membrane.config.yml)").addHelpText("after",["","Examples:"," membrane mcp # Launch MCP server using API URI from env vars or membrane.config.yml",""].join(`
12
- `)).action(async()=>{try{process.env.FASTMCP_SUPPRESS_WARNINGS="true";const e=we(),t=process.env.MEMBRANE_ACCESS_TOKEN||e?.accessToken,n=process.env.MEMBRANE_WORKSPACE_KEY||e?.workspaceKey,o=process.env.MEMBRANE_WORKSPACE_SECRET||e?.workspaceSecret,i=process.env.MEMBRANE_TEST_CUSTOMER_ID||e?.testCustomerId,s=process.env.MEMBRANE_API_URI||e?.apiUri||Qe;!t&&(!n||!o)&&(e||(console.error("No configuration found. Please set MEMBRANE_ACCESS_TOKEN, or MEMBRANE_WORKSPACE_KEY and MEMBRANE_WORKSPACE_SECRET environment variables, or run `membrane init` first to create a configuration file."),process.exit(1)),console.error("Missing credentials. Please provide MEMBRANE_ACCESS_TOKEN or workspace key/secret in the configuration file, command line, or environment variables."),process.exit(1));const a=t||await bo(n,o,i),l=await vo(s,a),d=To(l,s,a),h=new lr({name:"Membrane API",instructions:`This MCP server lets you interact with Membrane to configure, run, and troubleshoot integrations.
9
+ Unexpected Error:`),a&&console.error(a),console.error(s)),s}return}},"executeRequest");return t?i():Jt.withSkipErrorLog(i)}async generateAccessToken(e,t){return ze.sign({name:"Membrane Agent",isAdmin:!0,exp:Math.floor(Date.now()/1e3)+3600,iss:e},t,{algorithm:"HS512"})}isTokenValid(){return Date.now()<this.tokenExpiry}getCurrentConfig(e){const t=Ce(e);return!t?.workspaceKey||!t?.workspaceSecret?null:{workspaceKey:t.workspaceKey,workspaceSecret:t.workspaceSecret,apiUri:t.apiUri}}async createClient(e){const t=await this.generateAccessToken(e.workspaceKey,e.workspaceSecret);return this.tokenExpiry=Date.now()+36e5,this.currentConfig=e,new kt({token:t,apiUri:e.apiUri})}async getClient(e=process.cwd()){const t=this.getCurrentConfig(e);if(!t)throw new Error("Unable to create MembraneClient: No workspace configuration found.");const n=!this.currentConfig||this.currentConfig.workspaceKey!==t.workspaceKey||this.currentConfig.workspaceSecret!==t.workspaceSecret||this.currentConfig.apiUri!==t.apiUri,o=!this.isTokenValid()||this.tokenExpiry-Date.now()<3e5;return(!this.client||n||o)&&(this.client=await this.createClient(t)),this.client}clearClient(){this.client=null,this.currentConfig=null,this.tokenExpiry=0,this.requestTimes=[],this.semaphore=0,this.semaphoreQueue=[],this.rateLimitMutex=Promise.resolve()}getCurrentConfigInfo(){return this.currentConfig}async waitIfNeeded(){this.rateLimitMutex=this.rateLimitMutex.then(async()=>{for(this.cleanOldRequests();this.requestTimes.length>=this.maxRequestsPerSecond;){const t=this.requestTimes[0]+this.windowSizeMs-Date.now()+10;if(t>0)await new Promise(n=>setTimeout(n,t)),this.cleanOldRequests();else break}}),await this.rateLimitMutex}recordRequest(){this.requestTimes.push(Date.now())}cleanOldRequests(){const e=Date.now()-this.windowSizeMs;this.requestTimes=this.requestTimes.filter(t=>t>e)}getRequestCount(){return this.cleanOldRequests(),this.requestTimes.length}async acquireSemaphore(){if(this.semaphore<this.maxConcurrentRequests){this.semaphore++;return}return new Promise(e=>{this.semaphoreQueue.push(e)})}releaseSemaphore(){if(this.semaphore--,this.semaphoreQueue.length>0){const e=this.semaphoreQueue.shift();this.semaphore++,e()}}async withRetry(e,t="operation"){let n;for(let o=0;o<=this.maxRetries;o++)try{return await e()}catch(i){if(n=i,!this.isRetryableError(i)||o===this.maxRetries)throw i;const s=new Date().toISOString(),a=o+2;f.debug(`[${s}] Retrying ${t} (attempt ${a}/${this.maxRetries+1})`);let l=this.retryDelay*Math.pow(2,o);if(this.enableJitter){const d=l*.25*(Math.random()*2-1);l=Math.max(0,l+d)}await new Promise(d=>setTimeout(d,l))}throw n||new Error("Unknown error occurred during retry attempts")}isRetryableError(e){if(!e)return!1;const t=(e.message||e.toString()||"").toLowerCase(),n=e.code;return n&&["econnrefused","enotfound","econnreset","etimedout","ehostunreach","enetunreach"].includes(n.toLowerCase())?!0:["econnrefused","connection refused","network error","timeout","socket hang up","request timeout","dns lookup failed"].some(s=>t.includes(s))}async withTimeout(e,t){let n;const o=new Promise((i,s)=>{n=setTimeout(()=>s(new Error(`Request timeout after ${t}ms`)),t)});try{const i=await Promise.race([e,o]);return n&&clearTimeout(n),i}catch(i){throw n&&clearTimeout(n),i}}async getVersion(){try{return(await this.withClient(t=>t.get("version"),!1))?.version??null}catch{return null}}}const I=new Mr;async function Gt(r){const e=await I.withClient(t=>t.get("org-workspace-id"),!0,r);if(!e)throw new Error("Failed to get workspace ID");return e.id}c(Gt,"getWorkspaceId");const Z={UPDATE:"update",DELETE:"delete",CREATE:"create"},B={INCOMING:"incoming",OUTGOING:"outgoing"},z={[x.Integration]:{element:"integration",elements:"integrations",exportable:!1,exportCleanup:c(r=>({id:r.id,key:r.key,name:r.name,connectorId:r.connectorId,baseUri:r.baseUri,connectorVersion:r.connectorVersion}),"exportCleanup")},[x.Connector]:{element:"connector",elements:"connectors",exportable:!1},[x.Action]:{element:"action",elements:"actions",integrationSpecific:!0,exportCleanup:c(r=>(delete r.integration,r),"exportCleanup")},[x.AppDataSchema]:{element:"appDataSchema",elements:"appDataSchemas"},[x.AppEventType]:{element:"appEventType",elements:"appEventTypes"},[x.DataLinkTable]:{element:"dataLinkTable",elements:"dataLinkTables"},[x.DataSource]:{element:"dataSource",elements:"dataSources",parentKey:"universalDataSourceId",integrationSpecific:!0},[x.FieldMapping]:{element:"fieldMapping",elements:"fieldMappings",integrationSpecific:!0,parentKey:"universalFieldMappingId",exportCleanup:c(r=>(delete r.dataSourceId,r),"exportCleanup")},[x.Flow]:{element:"flow",elements:"flows",integrationSpecific:!0,parentKey:"universalFlowId"},[x.Package]:{element:"package",elements:"packages",integrationSpecific:!0}},Fr=["id","workspaceId","integrationId","createdAt","updatedAt","revision","archivedAt","baseUri","state","appliedToIntegrations","dependencies"],Ht=[x.Action,x.FieldMapping,x.Flow,x.DataSource,x.Package];class M{static{c(this,"Element")}type;key;integrationKey;data;constructor(e,t,n,o){if(!o)throw new Error("Element must always contain data");if(!t)throw new Error("Element must have a key");this.type=e,this.key=t,this.data=o,this.integrationKey=n||M.extractIntegrationKey(o)}get id(){return M.makeId(this.type,this.key,this.integrationKey)}get dirPath(){const e=V[this.type].apiPath;if(this.integrationKey){const t=V[x.Integration].apiPath;return E.join(t,this.integrationKey,e,this.key)}return E.join(e,this.key)}get path(){return E.join(this.dirPath,"spec.yaml")}get relativePath(){return E.relative(U(process.cwd()),this.path)}get absolutePath(){return E.resolve(E.join(U(process.cwd()),this.path))}isEqual(e){if(this.id!==e.id)return!1;const t=this.clean(),n=e.clean();return Qn(t,n)}hasParent(){if(this.data?.parentUuid)return!0;const e=this.getParentKey();return!!e&&!!this.data?.[e]}clean(){const e={...this.data};return Fr.forEach(t=>{delete e[t]}),Object.keys(e).forEach(t=>{t.match(/universal.*Revision/)&&delete e[t]}),e}getParentKey(){let e="parentId";return z?.[this.type]?.parentKey&&(e=z?.[this.type]?.parentKey),e}static new(e,t,n,o){return new M(e,t,n,o)}static fromData(e,t){if(!t?.key)throw new Error(`Element missing key: ${JSON.stringify(t)}`);const n=this.extractIntegrationKey(t);return new M(e,t.key,n,t)}static fromPathAndData(e,t){const n=M.parsePath(e);if(!t)return;const o=t?.key||n?.key;return n?M.new(n.type,o,n.integrationKey,t):void 0}static fromElement(e){return new M(e.type,e.key,e.integrationKey,{...e.data})}static idFromPath(e){const t=M.parsePath(e);if(t)return M.makeId(t.type,t.key,t.integrationKey)}static makeId(e,t,n){return e===x.Integration?`${e}:${t}`:M.isIntegrationSpecific(e)?`${n||"universal"}:${e}:${t}`:`${e}:${t}`}static parsePath(e){const t=this.getRelativePath(e);if(!this.isElementFile(t))return;const n=Object.values(V).map(l=>l.apiPath).join("|"),o=new RegExp(`^(?<elementType>${n})/(?<elementKey>[^/]+)/spec\\.ya?ml$`),i=t.match(o);if(i?.groups){const{elementType:l,elementKey:d}=i.groups,h=this.getElementTypeFromPath(l);if(h)return{type:h,key:d}}const s=new RegExp(`^integrations/(?<integrationKey>[^/]+)/(?<elementType>${n})/(?<elementKey>[^/]+)/spec\\.ya?ml$`),a=t.match(s);if(a?.groups){const{integrationKey:l,elementType:d,elementKey:h}=a.groups,m=this.getElementTypeFromPath(d);if(m)return{type:m,key:h,integrationKey:l}}}static extractIntegrationKey(e){return e?.integrationKey||e?.integration?.key||e?.integration_key||void 0}static isElementFile(e){return e.endsWith(".yml")||e.endsWith(".yaml")}static getElementTypeFromPath(e){return Object.values(x).find(t=>V[t].apiPath===e)}static getRelativePath(e){return E.relative(U(process.cwd()),e)}static isIntegrationSpecific(e){return Ht.includes(e)}static canBeIntegrationSpecific(e){return Ht.includes(e)}}class zt{static{c(this,"BaseWorkspaceElementsRepository")}constructor(e){this.cache=e}connectorsMapping;sourceCache;setConnectorsMapping(e){this.connectorsMapping=e}setSourceCache(e){this.sourceCache=e}async getElements(){const e=[];try{const t=await this.getIntegrations();e.push(...t);const n=[x.Integration,x.Connector],o=Object.keys(z),i=await Promise.all(o.filter(s=>!n.includes(s)).map(async s=>this.getElementsByType(s,t)));for(const s of i)e.push(...s)}catch(t){throw f.error(`Failed to get elements: ${t}`),t}return e}async putElement(e){let t=this.cache.get(e.id);return t&&!e.data.id&&t.data.id&&(e.data.id=t.data.id),!t&&e.data.id&&(t=await this.getByInternalId(e.data.id,e.type,!1)),e.data.id&&t?t=await this.updateElement(e,t,{elements:this.cache.getAll(),connectorsMapping:this.connectorsMapping,sourceElements:this.sourceCache?.getAll()}):t=await this.createElement(e,{elements:this.cache.getAll(),connectorsMapping:this.connectorsMapping,sourceElements:this.sourceCache?.getAll()}),t}async getElementsByType(e,t){return[]}async createElement(e,t){return e}async updateElement(e,t,n){return t}async getElement(e){}async getIntegrations(){return[]}async getByInternalId(e,t,n=!0){}async deleteElement(e,t){}}function it(r,e=!0){if(v.existsSync(r))try{const t=v.readFileSync(r,"utf8");return G.load(t)||void 0}catch(t){if(!e)return;if(t instanceof Error){const n=E.relative(process.cwd(),r);throw new Error(`Failed to parse YAML file "${n}": ${t.message}`)}throw t}}c(it,"readYaml$1");function Lr(r,e,t){try{const n=G.dump(e,t);v.writeFileSync(r,n,"utf8")}catch(n){if(n instanceof Error){const o=E.relative(process.cwd(),r);throw new Error(`Failed to write YAML file "${o}": ${n.message}`)}throw n}}c(Lr,"writeYaml$1");class jr extends zt{static{c(this,"LocalWorkspaceElementsRepository")}basePath;constructor(e){super(e),this.basePath=U(process.cwd())}async getElementsByType(e,t){const n=[],o=E.join(this.basePath,V[e].apiPath),i=await this.readElementsInDir(o);n.push(...i);for(const s of t){const a=E.join(this.basePath,V[x.Integration].apiPath,s.key,V[e].apiPath),l=await this.readElementsInDir(a);n.push(...l)}return n.length>0&&f.debug(`[local] Fetched ${n.length} ${e}${n.length!==1?"s":""}`),n}async getElement(e){return this.readElement(e.path)}async createElement(e){return this.updateElement(e,e)}async updateElement(e,t){if(!e.data)throw new Error("Element must have data to write");const n=E.join(this.basePath,t.dirPath),o=E.join(this.basePath,t.path);return v.existsSync(n)||v.mkdirSync(n,{recursive:!0}),Lr(o,e.data),f.debug(`[local] Written ${t.relativePath}`),t}async deleteElement(e){const t=E.join(this.basePath,e.path),n=E.join(this.basePath,e.dirPath);v.existsSync(t)&&v.rmSync(t,{force:!0}),this.pruneEmptyDir(n),f.debug(`[local] Deleted ${e.relativePath}`)}async getIntegrations(){const e=E.join(this.basePath,V[x.Integration].apiPath);return this.readElementsInDir(e)}async readElement(e){const t=it(e);if(t)return M.fromPathAndData(e,t)}async readElementsInDir(e){const t=[];if(!v.existsSync(e))return t;const n=v.readdirSync(e);if(n.length===0)return t;const o=n.map(async s=>{const a=E.join(e,s,"spec.yaml");return this.readElement(a)});return(await Promise.all(o)).filter(s=>s!=null)}pruneEmptyDir(e){try{if(!e.startsWith(this.basePath)||e===this.basePath||!v.existsSync(e)||v.readdirSync(e).length>0)return;v.rmdirSync(e),this.pruneEmptyDir(E.dirname(e))}catch(t){console.warn(`Failed to prune empty directory ${e}:`,t)}}}class Ur extends zt{static{c(this,"RemoteWorkspaceElementsRepository")}async getElementsByType(e,t){const n=M.canBeIntegrationSpecific(e),o=await this.findAll(e,n?{layer:"universal"}:{});if(!M.canBeIntegrationSpecific(e))return o;for(const i of t){const s=i.key,a=i.data.id,l=await this.findAll(e,a?{integrationId:a}:{integrationKey:s},s);o.push(...l)}return o.length>0&&f.debug(`[remote] Fetched ${o.length} ${e}${o.length!==1?"s":""}`),o}async getElement(e){const t=await I.withClient(n=>n[z[e.type].element](e.data.id).get());return M.fromData(e.type,t)}async createElement(e,t){const n=e.clean();if(this.transformElementForCreate(e,n,t),e.hasParent()&&n.integrationId&&!n.isCustomized){const s=e.getParentKey(),a=new Set(["uuid","integrationId",s,"meta","integrationUuid","parentUuid"]);Object.keys(n).forEach(l=>{a.has(l)||delete n[l]})}const o=await I.withClient(s=>s[z[e.type].elements].create(n)),i=M.fromData(e.type,o);return f.debug(`[remote] Created ${i.id}`),i}async updateElement(e,t,n){if(!e.data.id)throw new Error("Element must have an id to update");t.data.archivedAt&&await I.withClient(a=>a[z[e.type].element](t.data.id).restore());const o=e.clean();if(this.transformElementForUpdate(e,o,n),e.hasParent()&&o.integrationId&&!o.isCustomized)return f.debug(`[remote] Skipped update for ${t.id} (non-customized)`),t;const i=await I.withClient(a=>a[z[e.type].element](t.data.id).put(o)),s=M.fromData(t.type,i);return f.debug(`[remote] Updated ${t.id}`),s}async deleteElement(e){if(!e.data.id)throw new Error("Element must have an id to delete");await I.withClient(t=>t[z[e.type].element](e.data.id).archive()),f.debug(`[remote] Deleted ${e.id}`)}async getIntegrations(){const e=await I.withClient(n=>n.integrations.findAll());if(!e)return[];const t=e.map(n=>M.fromData(x.Integration,n));return t.length>0&&f.debug(`[remote] Fetched ${t.length} integrations`),t}async getByInternalId(e,t){let n;if(n=await I.withClient(o=>o[z[t].element](e).get(),!1),!!n)return M.fromData(t,n)}transformElementForCreate(e,t,n){if(e.integrationKey){const o=n.elements.find(i=>i.type===x.Integration&&i.key===e.integrationKey);if(o)t.integrationId=o.data.id;else throw new Error(`Dependency integration ${e.integrationKey} not found for ${e.id}`)}if(e.type===x.Integration){const o=n.connectorsMapping?.[t.connectorId];o&&(t.connectorId=o)}this.transformPackageDependencies(e,t,n),this.transformParentDependency(e,t,n)}transformElementForUpdate(e,t,n){if(e.type===x.Integration){const o=n.connectorsMapping?.[t.connectorId];o&&(t.connectorId=o)}if(e.integrationKey){t.integrationKey=e.integrationKey;const o=n.elements.find(i=>i.type===x.Integration&&i.key===e.integrationKey);if(o)t.integrationId=o.data.id;else throw new Error(`Dependency integration ${e.integrationKey} not found for ${e.id}`)}this.transformPackageDependencies(e,t,n),this.transformParentDependency(e,t,n)}transformPackageDependencies(e,t,n){if(e.type!==x.Package||!t.elements)return;const o=t.elements.map(i=>{const a=(n.sourceElements||n.elements).find(d=>d.data.id===i.id&&d.type===i.type);if(!a)throw new Error(`Package element ${i.type} with id ${i.id} not found in source workspace for package ${e.id}`);const l=n.elements.find(d=>d.type===i.type&&d.key===a.key&&d.integrationKey===a.integrationKey);if(!l)throw new Error(`Package element ${i.type} with key ${a.key} not found in target workspace for package ${e.id}`);return{id:l.data.id,type:i.type}});t.elements=o}transformParentDependency(e,t,n){if(!e.hasParent())return;const o=e.getParentKey();if(!o)return;const i=n.elements.find(s=>s.type===e.type&&s.key===e.key&&!s.hasParent());if(i)t[o]=i.data.id;else throw new Error(`Parent ${e.getParentKey()} not found for ${e.id}`)}async findAll(e,t={},n){const o=await I.withClient(i=>i[z[e].elements].findAll(t));return o?o.filter(i=>i.key).map(i=>(n&&!i.integrationKey&&(i.integrationKey=n),M.fromData(e,i))):[]}}class st extends or{static{c(this,"TypedEventEmitter")}on(e,t){return super.on(e,t)}emit(e,...t){return super.emit(e,...t)}off(e,t){return super.off(e,t)}once(e,t){return super.once(e,t)}}const _={Updated:"updated",Deleted:"deleted",Stopped:"stopped"},Kr={ignored:Dr,persistent:!0,ignoreInitial:!0,followSymlinks:!1,depth:20,awaitWriteFinish:{stabilityThreshold:500,pollInterval:100},ignorePermissionErrors:!0,atomic:!0,usePolling:!1,alwaysStat:!1,interval:1e3,binaryInterval:300};class qr extends st{static{c(this,"LocalElementWatcher")}constructor(e){super(),this.options=e,this.membraneDir=U(this.options.cwd),this.lockTimeoutMs=this.options.lockTimeoutMs??1e3}isWatching=!1;watcher;membraneDir;contentCache={};ignoredPaths=new Set;lockTimeoutMs;async start(){this.isWatching||(v.existsSync(this.membraneDir)||v.mkdirSync(this.membraneDir,{recursive:!0}),this.initializeContentCache(),this.watcher=nr.watch(this.membraneDir,Kr),this.watcher.on("add",e=>this.handleFileSystemEvent(_.Updated,e)).on("change",e=>this.handleFileSystemEvent(_.Updated,e)).on("unlink",e=>this.handleFileSystemEvent(_.Deleted,e)).on("ready",()=>this.isWatching=!0))}async stop(){!this.isWatching||!this.watcher||(await this.watcher.close(),this.isWatching=!1,this.watcher=void 0,this.clearCache(),this.clearAllLocks(),this.emit(_.Stopped))}getCwd(){return this.options.cwd}async executeWithPathLock(e,t){const n=E.resolve(e);this.ignoredPaths.add(n);try{await t()}finally{setTimeout(()=>{this.ignoredPaths.delete(n)},this.lockTimeoutMs)}}isPathLocked(e){const t=E.resolve(e);if(this.ignoredPaths.has(t))return!0;for(const n of this.ignoredPaths)if(t.startsWith(n+E.sep))return!0;return!1}clearAllLocks(){this.ignoredPaths.clear()}handleFileSystemEvent(e,t){const n=E.relative(this.membraneDir,t);if(this.isPathLocked(t))return;if(e===_.Deleted){this.removeFromCache(n);const a={filePath:t,relativePath:n,data:void 0};f.info(`[local] ${e}: ${a.relativePath}`),this.emit(e,a);return}const o=this.readFileContent(t);if(!this.hasContentChanged(n,o))return;const s=this.processFileEvent(t,o);this.updateCache(n,o),s&&(f.info(`[local] ${e}: ${s.relativePath}`),this.emit(e,s))}readFileContent(e){return v.readFileSync(e,"utf8")}processFileEvent(e,t){const n=E.relative(this.membraneDir,e);let o;try{o=t?rr.parse(t):void 0}catch{o=void 0}return{filePath:e,relativePath:n,data:o}}hasContentChanged(e,t){if(!t)return this.contentCache[e]!==void 0;const n=this.getContentHash(t);return this.contentCache[e]!==n}getContentHash(e){return er.createHash("sha256").update(e).digest("hex")}updateCache(e,t){if(!t){delete this.contentCache[e];return}this.contentCache[e]=this.getContentHash(t)}removeFromCache(e){delete this.contentCache[e]}clearCache(){Object.keys(this.contentCache).forEach(e=>{delete this.contentCache[e]})}initializeContentCache(){v.existsSync(this.membraneDir)&&this.scanDirectoryForCache(this.membraneDir)}scanDirectoryForCache(e){const t=v.readdirSync(e,{withFileTypes:!0});for(const n of t){const o=E.join(e,n.name);if(n.isDirectory())this.scanDirectoryForCache(o);else if(n.isFile())try{const i=v.readFileSync(o,"utf8"),s=E.relative(this.membraneDir,o);this.updateCache(s,i)}catch{}}}}var at=(r=>(r.Updated="updated",r.ConnectorFileUpdated="connector-file-updated",r.Connected="connected",r.Disconnected="disconnected",r.Error="error",r))(at||{});const Br={debounceMs:2e3,reconnectIntervalMs:5e3,maxReconnectAttempts:1/0,maxBackoffMs:6e4,connectionTimeoutMs:3e5};class _r extends st{static{c(this,"RemoteElementWatcher")}constructor(e=Br){super(),this.config=e}eventSource;debounceTimeouts=new Map;reconnectAttempts=0;reconnectTimeout;connectionTimeout;isStarted=!1;isConnected=!1;async start(){this.isStarted||(this.isStarted=!0,await this.connect())}async stop(){this.isStarted&&(this.isStarted=!1,this.isConnected=!1,this.clearReconnectTimeout(),this.clearConnectionTimeout(),this.clearAllDebounceTimeouts(),this.eventSource&&(this.eventSource.close(),this.eventSource=void 0))}async connect(){try{f.debug("[remote-events] Connecting to server"),this.eventSource&&(this.eventSource.close(),this.eventSource=void 0);const e=await I.getClient(process.cwd()),t=await e.getToken();if(!t)throw new Error("No auth token available");const n=`${e.apiUri}/sse/workspace?token=${encodeURIComponent(t)}`;f.debug("[remote-events] Subscribing to workspace events"),this.eventSource=new ir(n),this.setupEventSourceHandlers()}catch(e){f.debug(`[remote-events] Failed to connect: ${e}`),this.emit("error",{error:e}),this.scheduleReconnect()}}setupEventSourceHandlers(){this.eventSource&&(this.eventSource.onopen=()=>{f.debug("[remote-events] Connected to server"),this.reconnectAttempts=0,this.isConnected=!0,this.resetConnectionTimeout(),this.emit("connected",{})},this.eventSource.onmessage=e=>{try{this.resetConnectionTimeout();const t=JSON.parse(e.data);this.handleElementUpdate(t)}catch(t){f.debug(`[remote-events] Failed to parse workspace event: ${t}`)}},this.eventSource.onerror=e=>{f.debug(`[remote-events] Connection error: ${JSON.stringify(e,null,2)}`),this.isConnected=!1,this.clearConnectionTimeout(),this.eventSource&&(this.eventSource.close(),this.eventSource=void 0),this.emit("disconnected",{}),this.isStarted&&this.scheduleReconnect()})}handleElementUpdate(e){if(e.type!==Fn.ElementUpdate)return;const{elementId:t,elementType:n,data:o={}}=e;if(!(!t||!n)){if(n===x.Connector){const{filePath:i,eventType:s,newPath:a}=o;return f.debug(`[remote-watcher] Received connector event - elementId: ${t}, filePath: ${i}, eventType: ${s}`),this.scheduleConnectorFileUpdate(t,i,s,a)}return this.scheduleElementUpdate(t,n)}}scheduleElementUpdate(e,t){const n=this.debounceTimeouts.get(e);n&&clearTimeout(n);const o=setTimeout(()=>{this.debounceTimeouts.delete(e),this.emit("updated",{elementId:e,elementType:t})},this.config.debounceMs);this.debounceTimeouts.set(e,o)}scheduleConnectorFileUpdate(e,t,n,o){const i=JSON.stringify({connectorId:e,filePath:t}),s=this.debounceTimeouts.get(i);s&&clearTimeout(s);const a=setTimeout(()=>{this.debounceTimeouts.delete(i),this.emit("connector-file-updated",{connectorId:e,filePath:t,eventType:n,newPath:o})},this.config.debounceMs);this.debounceTimeouts.set(i,a)}scheduleReconnect(){if(!this.isStarted||this.reconnectAttempts>=this.config.maxReconnectAttempts){this.reconnectAttempts>=this.config.maxReconnectAttempts&&(f.error("[remote-events] Max reconnection attempts reached. Connection will not be retried."),this.emit("error",{error:new Error("Max reconnection attempts reached")}));return}this.reconnectTimeout&&clearTimeout(this.reconnectTimeout),this.reconnectAttempts++;const e=this.config.reconnectIntervalMs*Math.pow(2,this.reconnectAttempts-1),t=Math.random()*.3*e,n=Math.min(e+t,this.config.maxBackoffMs);f.debug(`[remote-events] Reconnecting in ${Math.round(n)}ms (attempt ${this.reconnectAttempts})`),this.reconnectTimeout=setTimeout(()=>{this.connect()},n)}clearReconnectTimeout(){this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=void 0)}resetConnectionTimeout(){this.clearConnectionTimeout(),this.connectionTimeout=setTimeout(()=>{this.isConnected&&this.isStarted&&(f.debug("[remote-events] Connection timeout detected, reconnecting..."),this.isConnected=!1,this.eventSource&&(this.eventSource.close(),this.eventSource=void 0),this.scheduleReconnect())},this.config.connectionTimeoutMs)}clearConnectionTimeout(){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=void 0)}clearAllDebounceTimeouts(){this.debounceTimeouts.forEach(e=>clearTimeout(e)),this.debounceTimeouts.clear()}}class Vt{static{c(this,"ElementsCache")}elements=new Map;typeIndex=new Map;internalIdIndex=new Map;constructor(e){e&&this.addAll(e)}add(e){const t=e.id;this.elements.set(t,e),this.typeIndex.has(e.type)||this.typeIndex.set(e.type,new Set),this.typeIndex.get(e.type).add(t),e.data?.id&&this.internalIdIndex.set(e.data.id,t)}remove(e){const t=e.id,n=this.elements.delete(t);if(n){const o=this.typeIndex.get(e.type);o&&(o.delete(t),o.size===0&&this.typeIndex.delete(e.type)),e.data?.id&&this.internalIdIndex.delete(e.data.id)}return n}put(e){this.elements.has(e.id)&&this.remove(e),this.add(e)}get(e){return this.elements.get(e)}getByInternalId(e){const t=this.internalIdIndex.get(e);if(t)return this.elements.get(t)}getElementsByType(e){const t=this.typeIndex.get(e);return t?Array.from(t).map(n=>this.elements.get(n)).filter(n=>n!==void 0):[]}getAll(){return Array.from(this.elements.values())??[]}getTypes(){return Array.from(this.typeIndex.keys())}addAll(e){for(const t of e)t&&this.add(t)}removeAll(e){for(const t of e)this.remove(t)}getElementIdsByType(e){return this.typeIndex.get(e)}clear(){this.elements.clear(),this.typeIndex.clear(),this.internalIdIndex.clear()}getAllIds(){return new Set(this.elements.keys())}}const pe="connectors",X="development",ct={};async function Yt(r={}){const{onProgress:e}=r,t=new Set,o=(await I.withClient(d=>d.get("org-workspace-id"))).id,i={};f.info("[connectors] Loading custom connectors"),await I.withClient(d=>d.get(`/connectors?workspaceId=${o}`)),f.info("[connectors] Loading public connectors");const s=ee(),l=(P.existsSync(s)?P.readdirSync(s):[]).filter(d=>{if(d.startsWith("."))return!1;const h=$.join(s,d);try{return P.statSync(h).isDirectory()}catch{return!1}});for(const d of l){f.info(`[connectors] Loading connector from: ${d}`);const h=P.readdirSync($.join(s,d)),m=await lt(d);if(!m)continue;e?.("pushing",m.name),"baseUri"in m&&delete m.baseUri;let p;m.uuid&&(p=await I.withClient(S=>S.get(`/connectors/${m.uuid}`),!1));const w=m.uuid;if(p)i[w]=p.id,f.info(`[connectors] Matched ${m.name} uuid: ${m.uuid}`),p.isPublic||(p.archivedAt&&(f.info(`[connectors] Restoring archived connector ${m.name}`),await I.withClient(S=>S.post(`connectors/${p.id}/restore`))),f.info(`[connectors] Updating connector ${m.name}`),await I.withClient(S=>S.patch(`connectors/${p.id}`,{...m,workspaceId:o})));else if(!i[w]&&!p?.isPublic){let S=!1;try{const O=await ut({connectorId:w});O&&O.isPublic&&(S=!0)}catch{}if(!S){f.info(`[connectors] Creating custom connector ${m.name} (${m.key})`);const O=await I.withClient(N=>N.post("connectors",{...m,workspaceId:o}));i[w]=O.id}}const T=h.filter(S=>P.statSync($.join(s,d,S)).isDirectory());for(const S of T)await Gr({connector:m,version:S,connectorId:i[w]}),t.add(w);e?.("pushed",m.name)}return{connectorsMapping:i,pushedConnectors:Array.from(t)}}c(Yt,"pushConnectors");async function Zt({connectorId:r,connectorVersion:e,allConnectors:t,pulledConnectors:n,pulledConnectorVersions:o}){if(!r||o[r]?.has(e))return;const i=Ut(),s=await ut({connectorId:r});if(!s.isPublic||t){if(!s?.key){console.error(`[connectors] Connector ${r} has no key. Skipping..`),f.error(`[connectors] Connector ${r} has no key. Skipping..`);return}n.has(r)||(await Hr({basePath:i,connector:s}),n.add(r)),o[r]||(o[r]=new Set),o[r].has(e)||(await zr({connector:s,connectorVersion:e,basePath:i}),o[r].add(e))}}c(Zt,"pullRemoteConnector");function ee(){const r=ot();return $.join(r.membraneDirPath,pe)}c(ee,"getConnectorsPath");async function lt(r){const e=$.join(ee(),r,`${r}.yml`);return it(e,!1)}c(lt,"readConnector");async function Wr(r,e){return f.info(`[connectors] Zipping ${r} into ${e}`),new Promise((t,n)=>{const o=P.createWriteStream(e),i=Ve("zip",{zlib:{level:9}});o.on("close",()=>{f.success(`[connectors] Successfully created ${e}`),t()}),o.on("end",()=>{f.info("[connectors] Data has been drained")}),i.on("warning",a=>{a.code==="ENOENT"?console.warn(a):n(a)}),i.on("error",a=>{n(a)}),i.pipe(o);const s=P.readdirSync(r);for(const a of s){const l=$.join(r,a),d=P.statSync(l);d.isFile()?i.file(l,{name:a}):d.isDirectory()&&i.directory(l,a)}i.finalize()})}c(Wr,"createZipArchive");async function Jr(r,e){return f.info(`[connectors] Unzipping into ${e}`),new Promise((t,n)=>{const o=Re.Parse();o.on("entry",i=>{const s=i.path;if(i.type==="Directory"){const l=$.join(e,s);P.mkdirSync(l,{recursive:!0}),i.autodrain()}else{const l=$.join(e,s),d=$.dirname(l);P.mkdirSync(d,{recursive:!0});const h=P.createWriteStream(l);i.pipe(h),h.on("finish",()=>{})}}),o.on("end",()=>{f.success(`[connectors] Successfully extracted to ${e}`),t()}),o.on("error",i=>{n(i)}),o.write(r),o.end()})}c(Jr,"extractZipArchive");async function Gr({connector:r,version:e,connectorId:t}){const n=$.join(ee(),Q(r),Xt(e)),o=$.join(n,"src"),i=$.join(n,"src.zip"),s=P.existsSync(i);if(P.existsSync(o)&&(f.info(`[connectors] Archiving source code for ${r.name} version ${e}`),await Wr(o,i)),!P.existsSync(i)){f.warning(`[connectors] No source code found for ${r.name} version ${e}`);return}try{const a=new Mt;if(a.append("file",P.createReadStream(i),"file.zip"),f.info(`[connectors] Pushing connector version ${e} for ${r.name}`),e==X)f.info(`[connectors] Uploading connector ${t}`),await I.withClient(l=>l.post(`connectors/${t}/upload`,a,{headers:{...a.getHeaders()}}));else{if(a.append("version",e),a.append("changelog","Imported Version"),(await I.withClient(d=>d.get(`/connectors/${t}/versions`))).find(d=>d.version==e)){f.info(`[connectors] Version ${e} already published`);return}f.info(`[connectors] Publishing version ${e} of connector ${t}`),await I.withClient(d=>d.post(`connectors/${t}/publish-version`,a,{headers:{...a.getHeaders()}}))}f.success(`Successfully pushed connector version ${e} for ${r.name}`)}catch(a){f.error(`Error pushing connector version ${e} for ${r.name}: ${a}`),console.error(`[connectors] Error pushing connector version ${e} for ${r.name}: ${a}`)}finally{!s&&P.existsSync(i)&&(f.info(`[connectors] Cleaning up temporary zip file for ${r.name} version ${e}`),P.unlinkSync(i))}}c(Gr,"pushConnectorVersion");async function ut({connectorId:r}){if(r){if(ct[r])return ct[r];try{const e=await I.withClient(t=>t.get(`connectors/${r}`),!1);return ct[r]=e,e}catch(e){return f.error(`[connectors] Failed to get connector ${r}: ${e}`),console.error(`[connectors] Failed to get connector ${r}: ${e}`),null}}}c(ut,"getConnector");async function Hr({basePath:r,connector:e}){const t=Q(e),n=$.join(r,pe,t);P.mkdirSync(n,{recursive:!0});const o=$.join(n,`${Q(e)}.yml`);P.writeFileSync(o,G.dump(e)),f.info(`[connectors] Pulled connector ${e.name}`)}c(Hr,"pullConnector$1");async function zr({connector:r,connectorVersion:e,basePath:t}){const n=Q(r),o=Xt(e),i=$.join(t,"connectors",n,o),s=await I.withClient(l=>l.get(`connectors/${r.id}/download`,{version:e},{responseType:"arraybuffer",headers:{Accept:"application/zip"},timeout:1e6}));P.mkdirSync(i,{recursive:!0});const a=$.join(i,"src.zip");if(P.writeFileSync(a,s),!e){const l=$.join(i,"src");P.mkdirSync(l,{recursive:!0}),await Jr(s,l)}f.info(`[connectors] Pulled connector version: ${r.name} (${o})`)}c(zr,"pullConnectorVersion");function Q(r){return r.key}c(Q,"getConnectorDirName");function Xt(r){return r??X}c(Xt,"getConnectorVersionDirName");function Vr(r){const e=Ut(),t=Q(r);return $.join(e,pe,t)}c(Vr,"getConnectorDirPath");function Yr(r){return r.match(`${pe}/[^/]+/${X}/src/.*`)!==null}c(Yr,"isConnectorSourceFile");async function Zr(r){const e=r.match(`${pe}/([^/]+)/${X}/src/(.*)`);if(!e)return;const t=e[1],n=e[2],o=await lt(t);if(!o){f.warning(`[connectors] Connector ${t} not found. Ignoring file change`);return}const i=o.id,s=P.readFileSync(r,"utf-8");await I.withClient(a=>a.put(`connectors/${i}/files/${n}`,s,{headers:{"Content-Type":"text/plain"}})),f.info(`[connectors] Pushed file ${n} for connector ${o.name}`)}c(Zr,"putConnectorFile");async function Xr(r){const e=r.match(`${pe}/([^/]+)/${X}/src/(.*)`);if(!e)return;const t=e[1],n=e[2],o=await lt(t);if(!o){f.warning(`[connectors] Connector ${t} not found. Ignoring file change`);return}const i=o.id;await I.withClient(s=>s.delete(`connectors/${i}/files/${n}`)),f.info(`[connectors] Deleted file ${n} for connector ${o.name}`)}c(Xr,"deleteConnectorFile");async function Qr(r,e){try{const t=await I.withClient(s=>s.get(`connectors/${r}`));if(!t){f.warning(`[connectors] Connector ${r} not found`);return}const n=await I.withClient(s=>s.get(`connectors/${r}/files/${e}`)),o=Q(t),i=$.join(ee(),o,X,"src",e);P.mkdirSync($.dirname(i),{recursive:!0}),n!=null?(P.writeFileSync(i,n),f.info(`[connectors] Pulled file ${e} for connector ${t.name}`)):P.existsSync(i)&&(P.unlinkSync(i),f.info(`[connectors] Deleted file ${e} for connector ${t.name}`))}catch(t){f.error(`[connectors] Failed to pull connector file ${e} for connector ${r}: ${t}`),console.error(`[connectors] Failed to pull connector file ${e} for connector ${r}: ${t}`)}}c(Qr,"pullConnectorFile");async function eo(r,e){const t=await I.withClient(i=>i.get(`connectors/${r}`),!1);if(!t){f.warning(`[connectors] Connector ${r} not found`);return}const n=Q(t),o=$.join(ee(),n,X,"src",e);P.existsSync(o)&&(P.unlinkSync(o),f.info(`[connectors] Deleted file ${e} for connector ${n}`))}c(eo,"deleteLocalConnectorFile");async function to(r,e,t){if(t&&e!==t)try{const n=await I.withClient(l=>l.get(`connectors/${r}`),!1);if(!n){f.warning(`[connectors] Connector ${r} not found`);return}const o=Q(n),i=$.join(ee(),o,X,"src"),s=$.join(i,e),a=$.join(i,t);P.existsSync(s)&&(P.mkdirSync($.dirname(a),{recursive:!0}),P.renameSync(s,a),f.info(`[connectors] Renamed directory from ${e} to ${t} for connector ${o}`))}catch(n){f.error(`[connectors] Failed to rename directory ${e} to ${t} for connector ${r}: ${n}`)}}c(to,"renameLocalConnectorDirectory");async function no(r,e){try{const t=await I.withClient(i=>i.get(`connectors/${r}`),!1);if(!t){f.warning(`[connectors] Connector ${r} not found`);return}const n=Q(t),o=$.join(ee(),n,X,"src",e);if(P.existsSync(o)){const i=$.resolve(ee());if(!$.resolve(o).startsWith(i))return;P.rmSync(o,{recursive:!0,force:!0}),f.info(`[connectors] Deleted directory ${e} for connector ${n}`)}}catch(t){f.error(`[connectors] Failed to delete directory ${e} for connector ${r}: ${t}`)}}c(no,"deleteLocalConnectorDirectory");const F={LogAdded:"logAdded",StateChanged:"stateChanged",StatsChanged:"statsChanged",ConflictsChanged:"conflictsChanged",McpStatusChanged:"mcpStatusChanged",McpServersChanged:"mcpServersChanged",ConfigChanged:"configChanged"};class ro extends st{static{c(this,"WorkspaceNotifications")}constructor(e){super(),this.config=e,f.setNotificationHandler(this)}clientId;heartbeatInterval;isCleaningUp=!1;async connectToRemote(){await this.registerWithRemoteServer(),await this.startHeartbeatLoop()}async setState(e){this.emit(F.StateChanged,{state:e}),await this.emitRemote({status:e})}setConflicts(e){this.emit(F.ConflictsChanged,{conflicts:e})}setConfig(e){this.emit(F.ConfigChanged,{config:e})}setStats(e){this.emit(F.StatsChanged,{stats:e})}addLog(e){this.emit(F.LogAdded,{log:e})}setMcpStatus(e){this.emit(F.McpStatusChanged,{status:e})}async setMcpServers(e){this.emit(F.McpServersChanged,{servers:e}),await this.emitRemote({mcpServers:e.map(t=>({name:t.agentName,totalRequests:t.totalRequests}))})}async cleanup(){!this.clientId||this.isCleaningUp||(this.isCleaningUp=!0,this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=void 0),await this.withErrorHandling(async()=>{await I.withClient(e=>e.delete(`/local-clients/${this.clientId}`))}),this.clientId=void 0)}async registerWithRemoteServer(){if(this.clientId)return;const e=await this.withErrorHandling(async()=>await I.withClient(t=>t.post("/local-clients",{hostname:Nt.hostname(),workingDirectory:process.cwd()})));e?.id?this.clientId=e.id:this.addLog({timestamp:new Date().toISOString(),message:"Failed to register with remote server",type:"error"})}async startHeartbeatLoop(){this.heartbeatInterval=setInterval(async()=>{this.clientId&&await this.sendHeartbeat()},this.config.heartbeatIntervalMs)}async sendHeartbeat(){this.clientId&&await this.withErrorHandling(async()=>{await I.withClient(e=>e.post(`/local-clients/${this.clientId}/keep-alive`,{}))})}async emitRemote(e){this.clientId&&await this.withErrorHandling(async()=>{await I.withClient(t=>t.patch(`/local-clients/${this.clientId}`,e))})}async withErrorHandling(e){try{return await e()}catch(t){const n=t instanceof Error?t.message:String(t);return this.addLog({timestamp:new Date().toISOString(),message:`Failed to connect to remote: ${n}`,type:"error"}),null}}}const te=new ro({heartbeatIntervalMs:15e3}),Qt=[x.AppDataSchema,x.AppEventType,x.DataLinkTable,x.DataSource,x.FieldMapping,x.Action,x.Flow,x.Package];class Te{static{c(this,"ElementSyncService")}localWatcher=void 0;remoteWatcher=void 0;notifier;changes=[];localCache;remoteCache;localRepo;remoteRepo;pulledConnectors=new Set;pulledConnectorVersions={};constructor(){this.notifier=te,this.localCache=new Vt,this.remoteCache=new Vt,this.localRepo=new jr(this.localCache),this.remoteRepo=new Ur(this.remoteCache)}clear(){this.changes=[]}needsForcedSync(){return this.changes.some(e=>e.isConflict)}needsSync(){return this.changes.length>0}async getStats(){const e=this.localCache.getAll(),t={};return e.forEach(n=>{t[n.type]=(t[n.type]||0)+1}),t}async fetchElements(){const e=await this.localRepo.getElements(),t=await this.remoteRepo.getElements();this.localCache.addAll(e),this.remoteCache.addAll(t)}async updateElement(e,t){const n=this.getHandler(t),o=this.getCache(t);try{const i=await n.putElement(e);o.put(i)}catch(i){throw f.error(`Failed to update element ${e.id}: ${i}`),i}}async deleteElement(e,t){const n=this.getHandler(t),o=this.getCache(t);try{await n.deleteElement(e,{elements:n.cache.getAll(),connectorsMapping:n.connectorsMapping}),o.remove(e)}catch(i){throw f.error(`Failed to delete element ${e.id}: ${i}`),i}}async pullConnectors(e=!1){const t=this.remoteCache.getElementsByType(x.Integration).map(n=>n.data);for(const n of t){const o=n.connectorId,i=n.connectorVersion;o&&await Zt({connectorId:o,connectorVersion:i,allConnectors:e,pulledConnectors:this.pulledConnectors,pulledConnectorVersions:this.pulledConnectorVersions})}}async pushConnectors(){const{connectorsMapping:e}=await Yt();this.remoteRepo.setConnectorsMapping(e)}getHandler(e){return e===B.INCOMING?this.localRepo:(this.remoteRepo.setSourceCache(this.localCache),this.remoteRepo)}getCache(e){return e===B.INCOMING?this.localCache:this.remoteCache}async startWatching(){this.localWatcher=new qr({cwd:process.cwd(),lockTimeoutMs:1e3}),this.localWatcher.on(_.Updated,e=>this.handleLocalEvent(e,_.Updated)),this.localWatcher.on(_.Deleted,e=>this.handleLocalEvent(e,_.Deleted)),await this.localWatcher.start(),f.success("[local] Tracking changes.."),this.remoteWatcher=new _r,this.remoteWatcher.on(at.Updated,({elementId:e,elementType:t})=>this.handleRemoteElementEvent(e,t)),this.remoteWatcher.on(at.ConnectorFileUpdated,({connectorId:e,filePath:t,eventType:n,newPath:o})=>this.handleRemoteConnectorFileEvent(e,t,n,o)),await this.remoteWatcher.start(),f.success("[remote] Tracking changes..")}async stopWatching(){this.localWatcher&&(await this.localWatcher.stop(),this.localWatcher=void 0),this.remoteWatcher&&(await this.remoteWatcher.stop(),this.remoteWatcher=void 0)}async handleRemoteElementEvent(e,t){try{const n=await this.remoteRepo.getByInternalId(e,t),o=!!n?.data.archivedAt||!!n?.data.isDeactivated;if(!n||o){const s=n||this.remoteCache.getByInternalId(e);return s?(f.info(`[${this.getDirectionLabel(B.INCOMING)}] Deleted: ${s.id}`),this.localWatcher?.executeWithPathLock(s.absolutePath,()=>this.deleteElement(s,B.INCOMING))):void 0}if(f.info(`[${this.getDirectionLabel(B.INCOMING)}] Updated: ${n.id}`),await this.localWatcher?.executeWithPathLock(n.absolutePath,async()=>this.updateElement(n,B.INCOMING)),t===x.Integration){const s=n.data.connectorId,a=n.data.connectorVersion,l=await ut({connectorId:s});if(!l?.key)return;const d=Vr(l);await this.localWatcher?.executeWithPathLock(d,async()=>Zt({connectorId:s,connectorVersion:a,allConnectors:!1,pulledConnectors:this.pulledConnectors,pulledConnectorVersions:this.pulledConnectorVersions}))}}catch(n){f.error(`[sync] Error handling remote event: ${n}`)}}async handleRemoteConnectorFileEvent(e,t,n,o){try{switch(n){case Le.ConnectorFileDeleted:await eo(e,t);break;case Le.ConnectorDirectoryRenamed:await to(e,t,o);break;case Le.ConnectorDirectoryDeleted:await no(e,t);break;default:await Qr(e,t);break}}catch(i){f.error(`[sync] Error handling remote connector file event: ${i}`)}}async handleLocalEvent(e,t){try{if(Yr(e.filePath))switch(t){case _.Updated:await Zr(e.filePath);break;case _.Deleted:await Xr(e.filePath);break}else{let n=M.fromPathAndData(e.filePath,e.data);if(!n){const o=M.idFromPath(e.filePath);if(!o||(n=this.remoteCache.get(o),!n))return}switch(f.info(`[${this.getDirectionLabel(B.OUTGOING)}] ${Xn(t)}: ${n.id}`),t){case _.Updated:await this.updateElement(n,B.OUTGOING);break;case _.Deleted:await this.deleteElement(n,B.OUTGOING);break}}}catch(n){f.error(`[sync] Error handling local event: ${n}`)}}detectIncomingChanges(){this.clearChanges();const e=Te.getChanges(B.INCOMING,this.remoteCache,this.localCache);return this.updateChanges(e),e}detectOutgoingChanges(){this.clearChanges();const e=Te.getChanges(B.OUTGOING,this.localCache,this.remoteCache);return this.updateChanges(e),e}async resolveChanges(){if(!this.needsSync())return;f.info("[resolver] Resolving changes.."),f.info("[resolver] Resolving integration elements");const e=this.changes.filter(o=>o.element.type===x.Integration);await Promise.all(e.map(async o=>this.resolveChange(o))),e.length>0&&(await this.fetchElements(),this.changes=this.changes.length>0&&this.changes[0]?.direction===B.INCOMING?this.detectIncomingChanges():this.detectOutgoingChanges(),this.changes=this.changes.filter(o=>o.element.type!==x.Integration)),f.info("[resolver] Resolving universal elements");const t=this.changes.filter(o=>!o.element.hasParent());for(const o of Qt){const i=t.filter(s=>s.element.type===o);f.info(`[resolver] Resolving ${o} elements`),await Promise.all(i.map(async s=>this.resolveChange(s)))}f.info("[resolver] Resolving integration level elements");const n=this.changes.filter(o=>o.element.hasParent());for(const o of Qt){const i=n.filter(s=>s.element.type===o);f.info(`[resolver] Resolving ${o} elements`),await Promise.all(i.map(async s=>this.resolveChange(s)))}f.success("[resolver] Resolved changes")}async resolveChange(e){switch(e.type){case Z.DELETE:return this.deleteElement(e.element,e.direction);case Z.CREATE:return this.updateElement(e.element,e.direction);case Z.UPDATE:return this.updateElement(e.element,e.direction)}}static getChanges(e,t,n){const o=t.getAllIds(),i=n.getAllIds(),s=new Set([...o,...i]),a=[];for(const l of s){const d=t.get(l),h=n.get(l),m=Te.detectChangeForElement(d,h,e);m&&a.push(m)}return a}updateChanges(e){if(this.changes=e,this.needsForcedSync()){const t=e.filter(n=>n.isConflict);f.warning("[resolver] Conflicts detected"),this.notifier.setConflicts(t)}}clearChanges(){this.changes=[]}getDirectionLabel(e){switch(e){case B.INCOMING:return"local\u2190remote";case B.OUTGOING:return"local\u2192remote"}}static detectChangeForElement(e,t,n){return e&&!t?{type:Z.CREATE,element:e,direction:n,isConflict:!1}:!e&&t?{type:Z.DELETE,element:t,direction:n,isConflict:!0}:e&&t&&!e.isEqual(t)?{type:Z.UPDATE,element:e,direction:n,isConflict:!1}:null}}const ne=E.join(sr.tmpdir(),"membrane-mcp-status"),en=3e4;class oo{static{c(this,"McpStatusService")}constructor(e=2e3){this.pollIntervalMs=e}isRunning=!1;pollInterval;async start(){this.isRunning||(this.isRunning=!0,this.pollInterval=setInterval(async()=>await this.checkStatus(),this.pollIntervalMs),await this.checkStatus())}async stop(){this.pollInterval&&(clearInterval(this.pollInterval),this.pollInterval=void 0,this.isRunning=!1)}async checkStatus(){try{const e=process.cwd(),t=De(void 0,e),n=tn(e);t&&te.setMcpStatus(t),await te.setMcpServers(n)}catch{f.error("Failed to check MCP status")}}}function De(r,e){try{const t=e||process.cwd();if(!r){const o=tn(t);return o.length===0?null:o[0]}const n=pt(r,t);if(v.existsSync(n)){const o=v.statSync(n),i=new Date;if(i.getTime()-o.mtime.getTime()>en)return Se(r,t),null;const a=v.readFileSync(n,"utf8"),l=JSON.parse(a);if(l.isRunning){const d=new Date(l.lastActivity).getTime();if(i.getTime()-d>en)return Se(r,t),null}return l}}catch{r&&e&&Se(r,e)}return null}c(De,"getMcpStatus");function tn(r){try{const e=r||process.cwd(),t=ht(e);if(!v.existsSync(ne))return[];const n=v.readdirSync(ne),o=[];for(const i of n){const s=i.match(new RegExp(`^mcp-${t}-(\\d+)\\.json$`));if(s){const a=parseInt(s[1],10),l=De(a,e);l&&o.push(l)}}return o.sort((i,s)=>new Date(s.startTime).getTime()-new Date(i.startTime).getTime())}catch{return[]}}c(tn,"getAllMcpStatusFiles");function dt(r){try{const t={...De(r.processId,r.cwd)||{isRunning:!1,startTime:new Date().toISOString(),lastActivity:new Date().toISOString(),toolsCount:0,totalRequests:0,processId:r.processId,cwd:r.cwd,agentName:process.env.AGENT_NAME||"Unnamed Agent"},...r};v.existsSync(ne)||v.mkdirSync(ne,{recursive:!0});const n=pt(r.processId,r.cwd);v.writeFileSync(n,JSON.stringify(t,null,2))}catch{}}c(dt,"updateMcpStatus");function Se(r,e){try{const t=e||process.cwd();if(r){const n=pt(r,t);v.existsSync(n)&&v.unlinkSync(n)}else{const n=ht(t);if(v.existsSync(ne)){const o=v.readdirSync(ne);for(const i of o)i.match(new RegExp(`^mcp-${n}-\\d+\\.json$`))&&v.unlinkSync(E.join(ne,i))}}}catch{}}c(Se,"clearMcpStatus");function io(r,e){const t=De(r,e);t&&dt({processId:r,cwd:e,totalRequests:t.totalRequests+1,lastRequestTime:new Date().toISOString(),lastActivity:new Date().toISOString()})}c(io,"trackToolExecution");function ht(r){return tr("md5").update(r).digest("hex").slice(0,8)}c(ht,"getCwdHash");function pt(r,e){const t=ht(e);return E.join(ne,`mcp-${t}-${r}.json`)}c(pt,"getStatusFilePath");const Oe={Agent:"agent",Cli:"cli"},k={NOT_INITIALIZED:"not_initialized",SETTING_UP:"setting_up",INITIALIZED:"initialized",NOT_SYNCED:"not_synced",PULLING:"pulling",PUSHING:"pushing",RESOLVING:"resolving",CONFLICTS:"conflicts",SYNCED:"synced",WATCHING:"watching",ERROR:"error"};class so{static{c(this,"MembraneCLIService")}constructor(e,t,n=()=>process.exit(0)){this.mode=e,this.cwd=t,this.onShutdown=n,this.notifier=te,this.mcpStatusService=new oo,this.syncService=new Te,this.setupProcessCleanup()}initialized=!1;notifier;mcpStatusService;syncService;isShuttingDown=!1;currentConfig=null;get config(){return this.currentConfig}getSyncedElements(){return this.syncService.localCache.getAll()}getSyncedElementsByType(e){return this.syncService.localCache.getElementsByType(e)}async fetchElements(){await this.syncService.fetchElements()}async pullWorkspace(e={}){let t=!1;try{if(f.setVerboseMode(!!e.verbose),e.rps!==void 0&&I.init({maxRequestsPerSecond:e.rps}),await this.notifier.setState(k.PULLING),await this.syncService.fetchElements(),this.syncService.detectIncomingChanges(),this.syncService.needsForcedSync()&&!e.force){await this.notifier.setState(k.CONFLICTS),e.watch||(t=!0);return}await this.syncService.pullConnectors(e.allConnectors),await this.syncWorkspaces(e)}catch(n){t=!0,f.error(`Failed to pull workspace: ${n}`),await this.notifier.setState(k.ERROR),f.saveLogsToFile("error")}finally{if(e.saveLogs&&f.saveLogsToFile(),t)process.exit(1);else return e?.onComplete?.()}}async pushWorkspace(e={}){let t=!1;try{if(f.setVerboseMode(!!e.verbose),e.rps!==void 0&&I.init({maxRequestsPerSecond:e.rps}),await this.notifier.setState(k.PUSHING),await this.syncService.fetchElements(),this.syncService.detectOutgoingChanges(),this.syncService.needsForcedSync()&&!e.force){await this.notifier.setState(k.CONFLICTS),e.watch||(t=!0);return}await this.syncService.pushConnectors(),await this.syncWorkspaces(e)}catch(n){t=!0,f.error(`Failed to push workspace: ${n}`),await this.notifier.setState(k.ERROR),f.saveLogsToFile("error")}finally{if(e.saveLogs&&f.saveLogsToFile(),t)process.exit(1);else return e?.onComplete?.()}}async syncWorkspaces(e={}){try{e.verbose!==void 0&&f.setVerboseMode(!!e.verbose),await this.notifier.setState(k.RESOLVING),this.syncService.needsSync()&&await this.syncService.resolveChanges();const t=await this.syncService.getStats();this.notifier.setStats(t),await this.notifier.setState(k.SYNCED),e.watch&&(await this.notifier.setState(k.WATCHING),await this.syncService.startWatching())}catch(t){f.error(`Failed to sync local and remote workspaces: ${t}`),await this.notifier.setState(k.ERROR),f.saveLogsToFile("error")}}async init({force:e=!1}={}){if(!(this.initialized&&!e)){await this.notifier.setState(k.NOT_INITIALIZED);try{await this.loadConfig(),le.isCacheDefined()?(await this.initServices(),this.initialized=!0,await this.notifier.setState(k.INITIALIZED)):(this.initialized=!1,await this.notifier.setState(k.SETTING_UP))}catch(t){f.error(`Failed to initialize services: ${t}`),await this.notifier.setState(k.ERROR),f.saveLogsToFile("error"),this.onShutdown()}}}async loadConfig(){this.currentConfig=le.loadConfig(this.cwd),this.notifier.setConfig(this.currentConfig)}async updateConfig(e){const t={...this.currentConfig,...e};if(!(JSON.stringify(t)!==JSON.stringify(this.currentConfig)))return;await this.stopServices();const o=le.updateConfig(t);this.currentConfig=o,await this.init({force:!0})}async shutdown(){!this.initialized||this.isShuttingDown||(this.isShuttingDown=!0,this.mode===Oe.Agent&&(await this.notifier.cleanup(),await this.mcpStatusService.stop()),this.initialized=!1,this.onShutdown())}async initServices(){this.mode===Oe.Agent&&(await this.notifier.connectToRemote(),await this.mcpStatusService.start()),this.syncService.clear()}async stopServices(){this.mode===Oe.Agent&&(await this.notifier.cleanup(),await this.mcpStatusService.stop())}setupProcessCleanup(){["SIGINT","SIGTERM","uncaughtException","unhandledRejection"].forEach(t=>process.on(t,()=>this.shutdown())),process.on("beforeExit",t=>{t===0&&this.shutdown()})}}const nn=We(null);function ao({children:r,membraneCLIService:e}){const{data:t}=Ot("/account"),[n,o]=D(k.NOT_INITIALIZED),[i,s]=D([]),[a,l]=D({}),[d,h]=D([]),[m,p]=D(null),T=t?.workspaces?.find(S=>S.workspaceKey===m?.workspaceKey)||null;return he(()=>{const S=c(({state:L})=>o(L),"handleStateChanged"),O=c(({stats:L})=>l(L),"handleStatsChanged"),N=c(({log:L})=>h(xe=>[...xe,L]),"handleLogAdded"),K=c(({conflicts:L})=>s(L),"handleConflictsUpdated"),q=c(({config:L})=>p(L),"handleConfigChanged");return e.notifier.on(F.StateChanged,S),e.notifier.on(F.StatsChanged,O),e.notifier.on(F.LogAdded,N),e.notifier.on(F.ConflictsChanged,K),e.notifier.on(F.ConfigChanged,q),e.init(),()=>{e.notifier.off(F.StateChanged,S),e.notifier.off(F.StatsChanged,O),e.notifier.off(F.LogAdded,N),e.notifier.off(F.ConflictsChanged,K),e.notifier.off(F.ConfigChanged,q)}},[]),u(nn.Provider,{value:{state:n,stats:a,logs:d,currentWorkspace:T,conflicts:i,config:m,updateConfig:c(S=>e.updateConfig(S),"updateConfig"),resolveConflicts:c(S=>e.syncWorkspaces(S),"resolveConflicts"),pull:c(S=>e.pullWorkspace(S),"pull"),push:c(S=>e.pushWorkspace(S),"push"),exit:c(()=>e.shutdown(),"exit"),fetchElements:c(()=>e.fetchElements(),"fetchElements"),getSyncedElementsByType:c(S=>e.getSyncedElementsByType(S),"getSyncedElementsByType")},children:r})}c(ao,"MembraneCLIServiceProvider");function H(){const r=Je(nn);if(!r)throw new Error("useMembraneCLIService must be used within MembraneCLIServiceProvider");return r}c(H,"useMembraneCLIService");const ft=We(null),rn=c(()=>{const r=Je(ft);if(!r)throw new Error("useTree must be used within TreeView");return r},"useTree"),co=c(r=>se.Children.count(r)>0,"hasChildren");function lo(r){const e=rn(),{label:t,value:n,isInitiallyExpanded:o}=r,i=Gn(),s=Ge(e.registerChildItem(t)).current,a=e.isActiveByRef(s),[l,d]=D(o??!1),h={props:r,ref:s,id:i,active:a,expanded:l,setExpanded:d,label:t,value:n,isInitiallyExpanded:o,isParent:!1},{children:m}=r,p=typeof m=="function"?m(h):m;return{...h,props:{...r,children:p},isParent:co(p)}}c(lo,"useTreeItem");function fe(r){const e=rn(),t=lo(r),{expanded:n,isParent:o,props:{children:i},setExpanded:s}=t,{renderValue:a=ho}=r,l=t.ref;$e(()=>{function p(w){return r.onInput?.(w)?!0:w.active&&w.key.rightArrow&&!n?(s(!0),!0):w.active&&w.key.leftArrow&&n?(s(!1),!0):!1}c(p,"onInput"),l.onInput=p},[l,r.onInput,n,s]),l.firstChild??={parent:l,index:0};let d=l.firstChild;function h(p){const w=d;return w.nextSibling||(w.nextSibling={parent:l,prevSibling:w,index:w.index+1}),d=w.nextSibling,w.label=p,w}c(h,"registerChildItem");function m(){l.lastRenderedChild=d.prevSibling}return c(m,"commitChildren"),$e(()=>{m()}),b(ke,{children:[b(g,{marginLeft:e.depth*2,children:[u(g,{width:2,children:o&&u(y,{children:n?"\u25BC":"\u25B6"})}),uo(t),a(t)]}),n&&u(ft.Provider,{value:{...e,depth:e.depth+1,registerChildItem:h},children:i})]})}c(fe,"TreeItem");function uo({active:r,label:e}){return u(g,{width:32,children:u(y,{inverse:r,children:e})})}c(uo,"defaultRenderLabel");function ho(r){return u(y,{})}c(ho,"defaultRenderValue");const ue=c(({label:r,onPress:e,hotkey:t})=>u(fe,{label:r,onInput:c(({input:n,key:o,active:i})=>i&&o.return||t&&t in o&&o[t]||n===t?(e(),!0):!1,"onInput"),renderValue:c(()=>u(g,{children:u(y,{children:`${t?` (${t})`:""}`})}),"renderValue")}),"ActionTreeItem"),on=c(({label:r,value:e,onChange:t,disabled:n=!1,mask:o,...i})=>{const[s,a]=D(e),[l,d]=D(!1);return $e(()=>{l||a(e)},[l,e]),u(fe,{label:r,value:e,onInput:c(({key:h,active:m})=>n?!1:l?(h.escape&&d(!1),h.return&&(t(s),d(!1)),!0):m&&h.return?(d(!0),a(e),!0):!1,"onInput"),renderValue:c(()=>{const h=s,m=o?o.repeat(h.length):h;return u(g,{children:n||!l?u(y,{dimColor:!0,children:m}):b(ke,{children:[u(g,{width:m.length+1,children:u(Ft,{...i,focus:l,value:h,onChange:a})}),u(y,{dimColor:!0,children:" \u241B cancel"})]})})},"renderValue")})},"TreeTextField"),po=c(r=>u(on,{...r,mask:"*"}),"SecretField"),W=c(({children:r,showHelp:e=!1})=>{const t=Ge({parent:void 0,label:"<<ROOT>>",index:0}),[n,o]=D(t.current),i={depth:0,isActiveByRef:c(a=>n===a,"isActiveByRef"),registerChildItem:c(()=>t.current,"registerChildItem"),activeItemRef:n};$e(()=>{o(a=>a.parent?a.parent.lastRenderedChild&&a.index>a.parent.lastRenderedChild.index?a.parent.lastRenderedChild:a:t.current.firstChild??t.current)});function*s(a){a&&(yield a,yield*s(a.firstChild),a.nextSibling&&a!==a.parent?.lastRenderedChild&&(yield*s(a.nextSibling)))}return c(s,"walkTree"),ae((a,l)=>{if(n.onInput?.({input:a,key:l,active:!0}))return;let d,h;for(const m of s(t.current))if(m.label!=null){if(d===n&&(h=m),m&&m.onInput?.({input:a,key:l,active:m===n}))return;d=m}l.upArrow?o(m=>m.prevSibling?.lastRenderedChild??m.prevSibling??m.parent??t.current):l.downArrow?o(m=>h??m):l.pageUp?o(()=>t.current.firstChild??t.current):l.pageDown?o(()=>t.current.lastRenderedChild??t.current):l.tab?console.debug({label:n.label,nextSibling:n.nextSibling?.label,prevSibling:n.prevSibling?.label,parent:n.parent?.label,firstChild:n.firstChild?.label,lastRenderedChild:n.lastRenderedChild?.label}):l.leftArrow?o(m=>m.parent??t.current):l.rightArrow&&o(m=>m.lastRenderedChild?m.firstChild:m)}),u(ft.Provider,{value:i,children:b(g,{flexDirection:"column",children:[u(fe,{isInitiallyExpanded:!0,label:"rootItem",children:r}),e&&u(g,{marginTop:1,flexDirection:"column",children:u(y,{dimColor:!0,children:"\u2191/\u2193 move \u2022 \u2190 collapse \u2022 \u2192 expand \u2022 Enter/Space select/edit \u2022 Esc exit"})})]})})},"TreeView");W.Item=fe,W.TextField=on;function de({label:r,elementType:e,isActionExcluded:t,toggleAction:n,generateCode:o}){const[i,s]=D([]),{fetchElements:a,getSyncedElementsByType:l}=H();return he(()=>{c(async()=>{try{await a();const h=l(e);s(h.map(m=>m.data))}catch(h){console.error(String(h))}},"loadElements")()},[e,a,l,s]),u(fe,{label:r,children:i.map(d=>u(fe,{label:d.name,children:e===x.Action&&b(ke,{children:[t&&n&&u(ue,{label:`Toggle ${t(d)?"":"(excluded)"}`,onPress:c(()=>{n(d)},"onPress")}),o&&u(ue,{label:"Generate code",onPress:c(()=>{o?.(d)},"onPress")})]})},d.id))})}c(de,"WorkspaceElementsTreeItem");function fo({onComplete:r}){const{config:e,updateConfig:t,fetchElements:n,getSyncedElementsByType:o}=H(),[i,s]=D(""),a=e,l=c(p=>{s(p),setTimeout(()=>s(""),2e3)},"setFlash"),d=c(async(p,w)=>{try{await t({[p]:w}),l("\u2705 Configuration updated!")}catch{l("\u274C Error updating configuration")}},"updateField"),h=c(async()=>{try{if(e){const p=le.saveToFile(e);l(p?"\u2705 Configuration saved successfully!":"\u274C Failed to save configuration"),await n();const w=o(x.Action);await et({out:a?.outputDir??"",target:a?.projectType??"typescript",schemasOnly:!1,membraneInterfaces:{actions:w.filter(T=>!a?.excludedActionKeys?.includes(T.key)).map(T=>T.data)}}),l("\u2705 Code generated successfully!")}}catch{l("\u274C Error saving configuration")}},"handleSaveConfig"),m=c(async()=>{try{const p=le.loadConfig();p?(await t(p),l("\u2705 Configuration reloaded successfully!")):l("\u274C No configuration found to reload")}catch{l("\u274C Error reloading configuration")}},"handleReloadConfig");return b(g,{flexDirection:"column",gap:1,children:[u(y,{bold:!0,color:"cyan",children:"\u2699\uFE0F Membrane Configuration Manager"}),u(g,{paddingX:2,children:b(W,{showHelp:!0,children:[b(W.Item,{label:"Configuration",isInitiallyExpanded:!0,children:[b(W.Item,{label:"Project",children:[u(W.TextField,{label:"Workspace Key",value:a?.workspaceKey??"",onChange:c(p=>d("workspaceKey",p),"onChange"),disabled:!0}),u(po,{label:"Workspace Secret",value:a?.workspaceSecret??"",onChange:c(p=>d("workspaceSecret",p),"onChange"),disabled:!0}),u(W.TextField,{label:"API URI",value:a?.apiUri??"",onChange:c(p=>d("apiUri",p),"onChange")}),u(W.TextField,{label:"Test Customer ID",value:a?.testCustomerId??"",onChange:c(p=>d("testCustomerId",p),"onChange")})]}),b(W.Item,{label:"Code Generation",isInitiallyExpanded:!0,children:[b(W.Item,{label:"Project Type",isInitiallyExpanded:!0,value:a?.projectType,renderValue:c(({value:p})=>u(y,{children:p==="typescript"?"TypeScript":p==="openapi"?"OpenAPI":"(Not set)"}),"renderValue"),children:[u(ue,{label:"Update to TypeScript",onPress:c(()=>d("projectType","typescript"),"onPress")}),u(ue,{label:"Update to OpenAPI",onPress:c(()=>d("projectType","openapi"),"onPress")})]}),u(W.TextField,{label:"Project dir",value:a?.outputDir??"",onChange:c(p=>d("outputDir",p),"onChange")})]}),b(W.Item,{label:"Workspace Elements",children:[u(de,{label:"Actions",elementType:x.Action,isActionExcluded:c(p=>a?.excludedActionKeys?.includes(p.key)??!1,"isActionExcluded"),toggleAction:c(p=>d("excludedActionKeys",[...a?.excludedActionKeys??[],p.key]),"toggleAction"),generateCode:c(p=>{(async()=>{try{await et({out:a?.outputDir??"",target:a?.projectType??"typescript",schemasOnly:!1,membraneInterfaces:{actions:[p]}}),l("\u2705 Code generated successfully!")}catch{l("\u274C Error generating code")}})()},"generateCode")}),u(de,{label:"Flows",elementType:x.Flow}),u(de,{label:"Data Sources",elementType:x.DataSource}),u(de,{label:"Field Mappings",elementType:x.FieldMapping}),u(de,{label:"Packages",elementType:x.Package}),u(de,{label:"App Data Schemas",elementType:x.AppDataSchema}),u(de,{label:"App Event Types",elementType:x.AppEventType})]})]}),u(ue,{label:"Save Configuration",onPress:h,hotkey:"s"}),u(ue,{label:"Reload Configuration",onPress:m,hotkey:"r"}),u(ue,{label:"Exit",onPress:c(()=>r?.(),"onPress"),hotkey:"escape"})]})}),i&&u(g,{paddingX:2,children:u(y,{color:i.includes("\u2705")?"green":"red",children:i})})]})}c(fo,"ConfigManager");const sn=We(process.cwd());function mo({cwd:r,children:e}){return u(sn.Provider,{value:r,children:e})}c(mo,"CwdProvider");function go(){return Je(sn)}c(go,"useCwd");function mt({cwd:r,children:e,membraneCLIService:t}){const n=r||process.cwd();return u(mo,{cwd:n,children:u(ar,{value:{fetcher:Pr()},children:u(ao,{membraneCLIService:t,children:e})})})}c(mt,"Layout");function yo(r,e){r.command("config").alias("install").description("\u26A0\uFE0F EXPERIMENTAL: Manage local membrane configuration with interactive UI").addHelpText("after",["","Examples:"," membrane config # Open interactive config manager",""].join(`
10
+ `)).action(()=>{He(se.createElement(mt,{membraneCLIService:e,children:se.createElement(fo,{onComplete:c(()=>process.exit(0),"onComplete")})}))})}c(yo,"setupConfigCommand");function wo({currentPat:r,onSubmit:e}){const[t,n]=D(""),[o,i]=D(!1),[s,a]=D(null),l=rt(`/w/0/${Ln}`);return b(g,{flexDirection:"column",borderStyle:"round",borderTop:!0,width:70,paddingX:1,children:[u(g,{marginTop:-1,marginBottom:1,children:u(y,{bold:!0,children:"\u{1F511} Enter your Personal Access Token"})}),u(y,{children:"Please provide your Personal Access Token. You can find it here:"}),u(g,{marginTop:1,marginBottom:1,children:u(y,{color:"yellow",children:l})}),r&&u(y,{dimColor:!0,children:"Press Enter to keep your current token or type a new one."}),u(Ft,{mask:"*",placeholder:`${r?"******":"Enter your token here..."}`,value:t,onChange:n,onSubmit:c(async h=>{a(null),i(!0);try{await e(h),n("")}catch{a("Invalid token. Please try again.")}finally{i(!1)}},"handleSubmit")}),o&&u(g,{marginTop:1,children:b(y,{children:[u(Pe,{type:"dots"})," Validating token..."]})}),s&&u(y,{color:"red",children:s})]})}c(wo,"PersonalAccessTokenInput");function an({onExit:r,showEscOption:e=!0}){const[t,n]=D(""),{data:o,error:i,isLoading:s}=Ot("/account"),{updateConfig:a}=H(),l=o?.workspaces,d=s;if(ae((S,O)=>{O.escape&&r?.()}),d)return b(g,{children:[u(Pe,{}),u(y,{children:" Fetching workspaces..."})]});if(i)return b(g,{flexDirection:"column",children:[b(y,{color:"red",children:["Error: ",i.message]}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"Press ESC to go back"})})]});const h=l?.filter(S=>S.name.toLowerCase().includes(t.toLowerCase()))??[],m=h.map(S=>({label:S.name,value:S.id})),p=m.length,w=l?.length??0;async function T(S){const O=h.find(q=>q.id===S);if(!O)return;const{key:N,secret:K}=O;!N||!K||(await a({workspaceKey:N,workspaceSecret:K}),r?.())}return c(T,"handleSelect"),b(g,{flexDirection:"column",borderStyle:"round",borderTop:!0,width:70,paddingX:1,children:[u(g,{marginTop:-1,children:u(y,{bold:!0,children:"\u{1F4C1} Select your workspace"})}),b(g,{marginTop:1,children:[u(y,{children:"Search: "}),u(cr,{placeholder:"Enter a search query...",onChange:n})]}),w>5&&b(y,{children:["Showing ",p," of ",w," workspaces."]}),u(g,{marginTop:1,children:u(lr,{options:m,onChange:c(S=>{S&&T(S)},"onChange")})}),e&&u(g,{marginTop:1,children:u(y,{color:"grey",children:"Press ESC to go back"})})]})}c(an,"SelectWorkspace");var be=(r=>(r[r.Authenticate=0]="Authenticate",r[r.ConnectWorkspace=1]="ConnectWorkspace",r))(be||{});const Co={0:"Authenticate in Membrane",1:"Connect a Membrane Workspace"},gt=[be.Authenticate,be.ConnectWorkspace];function cn({onComplete:r}){const{config:e}=H(),[t,n]=D(!1),[o,i]=D(0),s=!!(e?.workspaceKey&&e?.workspaceSecret),a=qt(),l=gt[o],d=o+1,h=gt.length,m=gt.map((T,S)=>{let O="pending";return S<o?O="done":S===o&&(O="current"),{id:T,label:Co[T],status:O}});async function p(T){const S=a&&T===""?a:T,O=new Bt;try{await O.request("/account",{headers:{Authorization:`Bearer ${S}`}}),Rr(S),i(N=>N+1)}catch(N){console.error(N)}}c(p,"handlePatSubmit");function w(){n(!0),r&&r()}return c(w,"handleWorkspaceSelected"),ae((T,S)=>{s&&S.escape&&r&&r()}),t?u(g,{children:u(y,{children:"\u2705 Setup complete. You are ready to go!"})}):b(g,{flexDirection:"column",alignSelf:"flex-start",gap:1,children:[b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:70,children:[u(g,{marginTop:-1,marginBottom:1,children:b(y,{bold:!0,children:["\u{1F6E0}\uFE0F Setup \u2014"," ",b(y,{color:"cyan",children:["Step ",d," of ",h]}),s&&u(y,{color:"grey",children:" [esc: go back]"})]})}),u(g,{flexDirection:"column",paddingLeft:2,children:m.map(T=>u(So,{status:T.status,label:T.label},T.id))})]}),l===be.Authenticate&&u(wo,{currentPat:a,onSubmit:p}),l===be.ConnectWorkspace&&u(an,{onExit:w,showEscOption:!1})]})}c(cn,"Setup");function So({status:r,label:e}){return b(g,{children:[b(g,{width:2,children:[r==="current"&&u(Pe,{type:"dots"}),r==="done"&&u(y,{children:"\u2705"})]}),u(y,{dimColor:r!=="current",children:e})]})}c(So,"StepDisplay");function bo(r,e){r.command("init").description("Run interactive setup for Membrane project").option("--key <key>","Workspace key for non-interactive setup").option("--secret <secret>","Workspace secret for non-interactive setup").addHelpText("after",["","Examples:"," membrane init # Run interactive setup"," membrane init --key KEY --secret SEC # Non-interactive setup with key and secret",""].join(`
11
+ `)).action(t=>{t.key&&t.secret?le.saveToFile({workspaceKey:t.key,workspaceSecret:t.secret})?(console.error("\u2705 Configuration saved to membrane.config.yml"),process.exit(0)):(console.error("Error writing configuration file"),process.exit(1)):t.key||t.secret?(console.error("Error: Both --key and --secret must be provided for non-interactive mode"),process.exit(1)):He(se.createElement(mt,{membraneCLIService:e,children:se.createElement(cn,{onComplete:c(()=>process.exit(0),"onComplete")})}))})}c(bo,"setupInitCommand");const vo=86400;async function Eo(r,e,t,n){const o={iss:r,isAdmin:!0};return t&&(o.id=t),ze.sign(o,e,{expiresIn:vo})}c(Eo,"generateMcpAccessToken");async function To(r,e){return(await ge.get(`${r}/docs-json`,{headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"}})).data}c(To,"fetchOpenApiSchema");function re(r,e=!0,t,n=new Set){if(!r)return e?A.string():A.string().optional();if(Object.keys(r).length===0)return e?A.any():A.any().optional();if(r.$ref){const i=r.$ref.replace("#/components/schemas/","");if(n.has(i))return A.any();if(n.add(i),t?.schemas?.[i]){const s=t.schemas[i];return re(s,e,t,n)}return A.any()}let o;if(r.type==="object"||r.properties){const i={};if(r.properties)for(const[s,a]of Object.entries(r.properties)){const l=r.required?.includes(s)??!1;i[s]=re(a,l,t,n)}if(Object.keys(i).length>0){if(o=A.object(i),r.additionalProperties)if(typeof r.additionalProperties=="object"){const s=re(r.additionalProperties,!1,t,n);o=o.catchall(s)}else r.additionalProperties===!0&&(o=o.passthrough())}else if(r.additionalProperties&&typeof r.additionalProperties=="object"){const s=re(r.additionalProperties,!1,t,n);o=A.record(A.string(),s)}else o=A.record(A.string(),A.any())}else if(r.type==="array"){const i=r.items?re(r.items,!0,t,n):A.any();o=A.array(i)}else if(r.anyOf)o=A.any();else{switch(r.type){case"integer":o=A.coerce.number().int();break;case"number":o=A.coerce.number();break;case"boolean":o=A.coerce.boolean();break;case"string":default:o=A.string();break}r.format==="uuid"?o=A.string().uuid():r.format==="email"?o=A.string().email():r.format==="date"?o=A.string().regex(/^\d{4}-\d{2}-\d{2}$/):r.format==="date-time"&&(o=A.string().datetime()),r.enum&&(o=A.enum(r.enum)),(r.type==="integer"||r.type==="number")&&(r.minimum!==void 0&&(o=o.min(r.minimum)),r.maximum!==void 0&&(o=o.max(r.maximum))),r.type==="string"&&(r.minLength!==void 0&&(o=o.min(r.minLength)),r.maxLength!==void 0&&(o=o.max(r.maxLength)))}return e?o:o.optional()}c(re,"convertOpenApiSchemaToZod");function ln(r){const e=r.match(/\{([^}]+)\}/g);return e?e.map(t=>t.slice(1,-1)):[]}c(ln,"extractPathParameters");function xo(r,e,t,n,o,i){const s=r.operationId||`${t}_${e.replace(/[^a-zA-Z0-9]/g,"_")}`,a=r.description||r.summary||`${t.toUpperCase()} ${e}`,l={},d={},h={};if(r.parameters){for(const p of r.parameters)if(p.in==="path")d[p.name]=re(p.schema,!0,o).describe(p.description||`Path parameter: ${p.name}`);else if(p.in==="query"){const w=p.required===!0;h[p.name]=re(p.schema,w,o).describe(p.description||`Query parameter: ${p.name}`)}}if(Object.keys(d).length>0&&(l.params=A.object(d).describe("Path parameters")),Object.keys(h).length>0&&(l.query=A.object(h).describe("Query parameters")),r.requestBody&&r.requestBody.content){const p=r.requestBody.required===!0;if(r.requestBody.content["application/json"]){const w=r.requestBody.content["application/json"].schema;w?l.body=re(w,p,o).describe("Request body (JSON)"):l.body=A.any().describe("Request body (JSON)")}else r.requestBody.content["application/octet-stream"]||r.requestBody.content["text/plain"]?l.body=p?A.string().describe("Request body (binary/text)"):A.string().optional().describe("Request body (binary/text)"):l.body=A.any().describe("Request body")}const m=Object.keys(l).length>0?A.object(l):A.object({});return{name:s,description:a,parameters:m,async execute(p){try{const w=ln(e);if(w.length>0){if(!p.params)throw new Error(`Missing required path parameters: ${w.join(", ")}`);const q=w.filter(L=>!(L in p.params));if(q.length>0)throw new Error(`Missing required path parameters: ${q.join(", ")}`)}let T=`${n}${e}`;if(p.params)for(const[q,L]of Object.entries(p.params)){const xe=`{${q}}`;T.includes(xe)&&(T=T.replace(xe,String(L)))}const S=ln(T);if(S.length>0)throw new Error(`Unresolved path parameters: ${S.join(", ")}`);const O=new URLSearchParams;if(p.query)for(const[q,L]of Object.entries(p.query))L!=null&&O.append(q,String(L));O.toString()&&(T+=`?${O.toString()}`);const N={method:t.toUpperCase(),headers:{Authorization:`Bearer ${i}`}};p.body&&t.toLowerCase()!=="get"&&(r.requestBody?.content?.["application/json"]?(N.headers["Content-Type"]="application/json",N.data=p.body):r.requestBody?.content?.["application/octet-stream"]?(N.headers["Content-Type"]="application/octet-stream",N.data=p.body):r.requestBody?.content?.["text/plain"]?(N.headers["Content-Type"]="text/plain",N.data=p.body):(N.headers["Content-Type"]="application/json",N.data=p.body));const K=await ge.request({url:T,...N});return{content:[{type:"text",text:K.data===""?"":JSON.stringify(K.data,null,2)}]}}catch(w){return ge.isAxiosError(w)?{content:[{type:"text",text:`Error: ${w.response?.data?`HTTP ${w.response.status}: ${w.response.statusText} - ${JSON.stringify(w.response.data)}`:`HTTP ${w.response?.status||"unknown"}: ${w.message}`}`}],isError:!0}:w instanceof Error?{content:[{type:"text",text:`Error: API call failed: ${w.message}`}],isError:!0}:{content:[{type:"text",text:"Error: API call failed with unknown error"}],isError:!0}}}}}c(xo,"createApiTool");function Io(r,e,t){const n=[];if(!r.paths)return n;const o=r.components||{};for(const[i,s]of Object.entries(r.paths))if(typeof s=="object"&&s!==null){for(const[a,l]of Object.entries(s))if(["get","post","put","delete","patch"].includes(a)&&l&&typeof l=="object"){const d=xo(l,i,a,e,o,t);n.push(d)}}return n}c(Io,"convertOpenApiToTools");function $o(r){r.command("mcp").description("Launch MCP server with OpenAPI endpoints as tools (API URI is read from environment variables or membrane.config.yml)").addHelpText("after",["","Examples:"," membrane mcp # Launch MCP server using API URI from env vars or membrane.config.yml",""].join(`
12
+ `)).action(async()=>{try{process.env.FASTMCP_SUPPRESS_WARNINGS="true";const e=Ce(),t=process.env.MEMBRANE_ACCESS_TOKEN||e?.accessToken,n=process.env.MEMBRANE_WORKSPACE_KEY||e?.workspaceKey,o=process.env.MEMBRANE_WORKSPACE_SECRET||e?.workspaceSecret,i=process.env.MEMBRANE_TEST_CUSTOMER_ID||e?.testCustomerId,s=process.env.MEMBRANE_API_URI||e?.apiUri||nt;!t&&(!n||!o)&&(e||(console.error("No configuration found. Please set MEMBRANE_ACCESS_TOKEN, or MEMBRANE_WORKSPACE_KEY and MEMBRANE_WORKSPACE_SECRET environment variables, or run `membrane init` first to create a configuration file."),process.exit(1)),console.error("Missing credentials. Please provide MEMBRANE_ACCESS_TOKEN or workspace key/secret in the configuration file, command line, or environment variables."),process.exit(1));const a=t||await Eo(n,o,i),l=await To(s,a),d=Io(l,s,a),h=new dr({name:"Membrane API",instructions:`This MCP server lets you interact with Membrane to configure, run, and troubleshoot integrations.
13
13
  Use it for anything related to Membrane or integrations.
14
- `,version:"1.0.0"});for(const C of d){const E=C.execute;C.execute=async S=>(ro(process.pid,process.cwd()),E(S)),h.addTool(C)}ct({isRunning:!0,startTime:new Date().toISOString(),toolsCount:d.length,lastActivity:new Date().toISOString(),processId:process.pid,cwd:process.cwd(),agentName:process.env.AGENT_NAME||"Unnamed Agent"});const f=setInterval(()=>{ct({processId:process.pid,cwd:process.cwd(),lastActivity:new Date().toISOString()})},5e3),p=c(async()=>{clearInterval(f),Ce(process.pid,process.cwd());try{await h.stop()}catch{}},"cleanup");await h.start({transportType:"stdio"}),process.on("SIGINT",async()=>{await p(),process.exit(0)}),process.on("SIGTERM",async()=>{await p(),process.exit(0)}),process.on("exit",()=>{Ce(process.pid,process.cwd())}),process.on("uncaughtException",async C=>{console.error("Uncaught exception:",C.message),await p(),process.exit(1)}),process.on("unhandledRejection",async C=>{console.error("Unhandled rejection:",C),await p(),process.exit(1)})}catch(e){e instanceof Error&&(console.error(e.message),process.exit(1)),console.error("An unknown error occurred"),process.exit(1)}})}c(xo,"setupMcpCommand");const Io={info:"\u{1F4DD}",success:"\u2728",warning:"\u26A0\uFE0F",error:"\u274C",debug:"\u{1F50D}"},$o={info:w.white,success:w.green,warning:w.yellow,error:w.red,debug:w.gray};class R{static{c(this,"Logger")}static formatMessage(e,t,n={icon:!1}){const o=n.timestamp?`${w.gray(new Date().toISOString())} `:"",i=n.prefix?`${w.gray(n.prefix)} `:"",s=n.suffix?` ${w.gray(n.suffix)}`:"",a=Io[t],l=$o[t];return`${o}${n.icon?a:""} ${i}${l(e)}${s}`}static info(e,t){let n=w.white;if(t?.color&&(n=w[t.color.toLowerCase()]||w.white),t?.timestamp){const o=new Date().toLocaleTimeString();console.debug(`${w.gray(`[${o}]`)} ${n(e)}`)}else console.debug(n(e))}static group(e,t){}static groupEnd(){}static newLine(){}static success(e,t){console.debug(this.formatMessage(e,"success",t))}static warning(e,t){console.debug(this.formatMessage(e,"warning",t))}static error(e,t){console.error(this.formatMessage(e,"error",t))}static debug(e,t){t?.prefix?console.debug(w.gray(`[${t.prefix}] ${e}`),t.error?`
15
- ${w.red(t.error)}`:""):console.debug(w.gray(e),t?.error?`
16
- ${w.red(t.error)}`:"")}static step(e,t){}static header(e){console.debug(),console.debug(w.bold.cyan(`\u25B6 ${e}`)),console.debug()}static table(e,t){if(e.length===0)return;const n=t||Object.keys(e[0]),o=e.map(i=>{const s={};return n.forEach(a=>{s[a]=i[a]}),s});console.table(o,n)}static divider(){}}function ko(r){r.command("open").description("Open the workspace in the browser").addHelpText("after",["","Examples:"," membrane open # Open workspace in browser",""].join(`
17
- `)).action(async()=>{try{R.header("Opening Workspace in Browser"),R.info("Loading configuration...");const e=we();if(!e)throw new Error("No configuration found. Please set MEMBRANE_WORKSPACE_KEY and MEMBRANE_WORKSPACE_SECRET environment variables, or run `membrane init` first.");if(!e.workspaceKey||!e.workspaceSecret)throw new Error("Missing workspace credentials");R.info("Retrieving workspace ID...");const t=await Jt(process.cwd()),n=et(`/w/${t}`);R.info(`Opening ${n}...`);const{default:o}=await import("open");await o(n),R.success("Browser opened successfully")}catch(e){e instanceof Error&&(R.error(e.message),process.exit(1)),R.error("An unknown error occurred"),process.exit(1)}})}c(ko,"setupOpenCommand");async function ft(r,e,t={}){const{jobId:n,accessKey:o}=await e(),i=`${n}:${o}`;m.debug(`[background-job] Started job ${n}`);const s=Date.now(),{pollIntervalMs:a=1e3,timeoutMs:l=3e5,maxRetries:d=3}=t;let h=0;for(;;){if(Date.now()-s>l)throw new Error(`Background job ${n} timed out after ${l}ms`);await new Promise(C=>setTimeout(C,a));let p;try{p=await r.get(`background-jobs/${i}`),h=0}catch(C){if(C instanceof Ln&&h<d){h++,m.debug(`[background-job] Job ${n} not found, retrying (${h}/${d})`);continue}throw C}if(p.status==="completed"){if(m.debug(`[background-job] Completed job ${n}`),!p.result)throw new Error(`Background job ${n} completed but returned no result`);return p.result}if(p.status==="failed"){const C=p.error?.message||"Unknown error";throw m.error(`[background-job] Failed job ${n}: ${C}`),p.error?.stack&&m.error(`Stacktrace: ${p.error.stack}`),new Error(`Background job ${n} failed: ${C}`)}m.debug(`[background-job] Polling job ${n} (status: ${p.status})`)}}c(ft,"pollBackgroundJob");function ln(r,e){be(x.dirname(r)),v.writeFileSync(r,e)}c(ln,"writeFile");function Ro(r){v.existsSync(r)&&v.rmSync(r)}c(Ro,"deleteFile");function mt(r){v.existsSync(r)&&v.rmSync(r,{recursive:!0,force:!0})}c(mt,"deleteDir");function Po(r,e=!0){if(v.existsSync(r))try{const t=v.readFileSync(r,"utf8");return G.load(t)||void 0}catch(t){if(!e)return;if(t instanceof Error){const n=x.relative(process.cwd(),r);throw new Error(`Failed to parse YAML file "${n}": ${t.message}`)}throw t}}c(Po,"readYaml");function un(r,e,t){try{be(x.dirname(r));const n=G.dump(e,t);v.writeFileSync(r,n,"utf8")}catch(n){if(n instanceof Error){const o=x.relative(process.cwd(),r);throw new Error(`Failed to write YAML file "${o}": ${n.message}`)}throw n}return e}c(un,"writeYaml");function be(r){v.existsSync(r)||v.mkdirSync(r,{recursive:!0})}c(be,"ensureDirExists");function dn(r,e=!0){if(!v.existsSync(r)||!v.statSync(r).isDirectory())return;let t=v.readdirSync(r);t.length>0&&(t.forEach(n=>dn(x.join(r,n),!1)),t=v.readdirSync(r)),t.length===0&&!e&&v.rmdirSync(r)}c(dn,"cleanupEmptyFolders");function Ao(r){const e=r.split(/[\\/]/).join("/");return e.endsWith("/")?e+"**":e}c(Ao,"normalizePattern");async function hn(r,e=[]){return new Promise(async(t,n)=>{const o=e.map(Ao),i=Dt("zip",{zlib:{level:9}}),s=[];i.on("data",l=>s.push(l)),i.on("end",()=>t(Buffer.concat(s))),i.on("error",l=>n(l));const a=new Map;for(const l of r[T.Integration]||[])a.set(l.uuid,l.key);for(const[l,d]of Object.entries(r))for(const h of d){const f=h.key,p=a.get(h.integrationUuid),C=jn(l,f,p);if(o.length>0&&!o.some(S=>ur(C,S)))continue;const E=G.dump(h);i.append(E,{name:C})}i.finalize()})}c(hn,"createMembraneZip");async function gt(r,e){const t=await Lt.loadAsync(r),n=[];for(const[o,i]of Object.entries(t.files)){if(i.dir)continue;const s=ie(o);if(!s)continue;const a=await i.async("string"),l=G.load(a);if(!l)continue;const d=await e(o,l,s);d!==void 0&&n.push(d)}return n}c(gt,"iterateZipItems");async function Do(r){const e=await Lt.loadAsync(r),t={};for(const[n,o]of Object.entries(e.files)){if(o.dir)continue;const i=ie(n);if(!i)continue;const s=await o.async("string"),a=G.load(s);t[i.type]||(t[i.type]=[]),t[i.type].push(a)}return t}c(Do,"readMembraneZip");async function pn(r=process.cwd()){const e=await fn(q(r)),t={};for(const{data:n,type:o}of e)t[o]||(t[o]=[]),t[o].push(n);return t}c(pn,"readMembraneDir");async function fn(r){const e=mn(r),t=[];for(const n of e){if(n.isDirectory())continue;const o=ie(n.path);if(!o)continue;const i=await n.readContent(),s=G.load(i),a=x.join(r,n.path);t.push({filePath:a,data:s,type:o.type})}return t}c(fn,"iterateMembraneFiles");function mn(r,e){const t=[];if(e||(e=r),!v.existsSync(e)||e.startsWith(x.join(r,"connectors")))return t;const n=v.readdirSync(e,{withFileTypes:!0});for(const o of n){const i=x.join(e,o.name),s=x.relative(r,i);o.isDirectory()?t.push(...mn(r,i)):o.isFile()&&ie(s)&&t.push({path:s,isDirectory:c(()=>!1,"isDirectory"),readContent:c(async()=>v.readFileSync(i,"utf8"),"readContent")})}return t}c(mn,"getMembraneFiles");function gn(){const r={},e=x.join(q(process.cwd()),"connectors");if(!v.existsSync(e))return r;const t=v.readdirSync(e);for(const n of t){const o=x.join(e,n);if(!v.statSync(o).isDirectory())continue;const i=x.join(o,`${n}.yml`),s=Po(i,!1);if(!s?.uuid)continue;const a=new Set,l=v.readdirSync(o);for(const d of l){if(d.endsWith(".yml"))continue;const h=x.join(o,d);v.statSync(h).isDirectory()&&a.add(d=="development"?"":d)}r[s.uuid]={key:n,id:s.id,versions:Array.from(a)}}return r}c(gn,"readConnectorsDir");function ve(r,e){const t=x.join(q(process.cwd()),"connectors",r);return e==""||e===It?x.join(t,"development"):e?x.join(t,e):t}c(ve,"getConnectorPath");const yn=1e3,wn=12e4;async function Oo(){const r=await $.withClient(async t=>ft(t,()=>t.get("export"),{pollIntervalMs:yn,timeoutMs:wn}));if(!r)throw new Error("Failed to export workspace");const e=await ge.get(r.downloadUrl,{responseType:"arraybuffer"});return Buffer.from(e.data)}c(Oo,"downloadWorkspaceExport");async function Cn(r,e={}){const t=new Ot;t.append("file",r,{filename:"membrane.zip",contentType:"application/zip"});const n=await $.withClient(async i=>{const s=`import?dryRun=${e.dryRun??!1}&partial=${e.partial??!1}`,{jobId:a,accessKey:l}=await i.post(s,t,{headers:t.getHeaders()});return ft(i,()=>Promise.resolve({jobId:a,accessKey:l}),{pollIntervalMs:1e3,timeoutMs:3e5})});if(!n)throw new Error("Failed to import workspace");const o={};for(const[i,s]of Object.entries(n))o[i]=new Set(s||[]);return o}c(Cn,"importWorkspace");async function No(r,e){const t=await $.withClient(async o=>ft(o,()=>o.get(`connectors/${r}/export-files`,{version:e}),{pollIntervalMs:yn,timeoutMs:wn}));if(!t)throw new Error("Failed to export connector version");const n=await ge.get(t.downloadUrl,{responseType:"arraybuffer"});return Buffer.from(n.data)}c(No,"exportConnector");const Sn=5;function Mo(r){r.command("pull").description("Pull workspace data from specified workspace").option("--force","Overwrite conflicts with remote data",!1).addHelpText("after",["","Examples:"," membrane pull # Pull from default workspace"," membrane pull --force # Overwrite conflicts with remote data",""].join(`
18
- `)).action(async e=>{const t=Ft({text:"Pulling workspace",color:"white"}).start();try{const n=await Fo(e,t);t.stop(),qo(n.workspaceExport,n.connectors)}catch(n){t.stop(),_o(n),process.exit(1)}})}c(Mo,"setupPullCommand");async function Fo(r,e){const t=await pn(),n=await hn(t),o=await Oo(),i=await Do(o),{comparison:s}=Un(t,i);s[Y.DELETE].size>0&&!r.force&&(await Bo(s,n),R.error("Use --force to delete local elements"),process.exit(1));const l=await fn(q(process.cwd()));for(const{filePath:p,data:C}of l)s[Y.DELETE].has(C.uuid)&&Ro(p);dn(q(process.cwd())),await gt(o,(p,C)=>{if(ie(p)&&(s[Y.CREATE].has(C.uuid)||s[Y.UPDATE].has(C.uuid))){const S=I.join(q(process.cwd()),p);un(S,C)}});const d=await $.getVersion(),h=d?Mt.coerce(d):null;return{connectors:h&&Mt.gte(h,"1.8.0")?await Lo(o,e):await Uo(i[T.Integration],e),workspaceExport:i}}c(Fo,"pullWorkspace");async function Lo(r,e){e.text="Extracting connectors",mt(I.join(q(process.cwd()),"connectors"));const t=new Set,n=await ke.Open.buffer(r);for(const o of n.files){if(!o.path.startsWith("connectors/")||o.type==="Directory")continue;const i=I.join(q(process.cwd()),o.path);be(I.dirname(i));const s=await o.buffer();if(ln(i,s),t.add(o.path.split("/")[1]),o.path.endsWith("/development/src.zip")){const a=I.join(I.dirname(i),"src");be(a),await(await ke.Open.buffer(s)).extract({path:a})}}return Array.from(t)}c(Lo,"extractConnectorsFromExport");async function jo(r,e,t){if(ln(I.join(ve(r,e),"src.zip"),t),!e||e===It){const n=I.join(ve(r,e),"src");be(n),await(await ke.Open.buffer(t)).extract({path:n})}}c(jo,"writeConnectorVersion");async function Uo(r,e){e.text="Pulling connectors";const t=new Map,{id:n}=await $.withClient(l=>l.get("org-workspace-id")),{items:o=[]}=await $.withClient(l=>l.get(`/connectors?workspaceId=${n}`));for(const l of o){const d=l.uuid??l.id;!l.isPublic&&d&&t.set(d,new Set([""]))}for(const l of r??[]){const{connectorUuid:d,connectorVersion:h}=l;d&&(t.has(d)||t.set(d,new Set),t.get(d).add(h??""))}const i=gn();for(const[l,{key:d,versions:h}]of Object.entries(i)){if(!t.has(l)){const p=ve(d);mt(p);continue}const f=t.get(l);for(const p of h)if(!f.has(p)){const C=ve(d,p);mt(C)}}const s=Array.from(t.entries()),a=c((l,d)=>{l==="pulling"?e.start(`Pulling connector ${d}...`):e.succeed(`Pulled connector ${d}`)},"onProgress");for(let l=0;l<s.length;l+=Sn){const d=s.slice(l,l+Sn);await Promise.all(d.map(([h,f])=>Ko(h,Array.from(f),a)))}return Array.from(t.keys())}c(Uo,"pullConnectorsLegacy");async function Ko(r,e,t){const n=await $.withClient(d=>d.get(`connectors/${r}/export-json`),!1),o=await $.withClient(d=>d.get(`connectors/${r}`),!1);if(!n||!o||!n.key||!o.key)return;const i=o.name||n.key;t?.("pulling",i);const s={...n,id:o.id,uuid:o.uuid},a=ve(n.key),l=I.join(a,`${n.key}.yml`);un(l,s);for(const d of e){const h=await No(r,d);await jo(n.key,d,h)}t?.("pulled",i)}c(Ko,"pullConnector");function qo(r,e=[]){const t=Object.values(r).reduce((n,o)=>n+(o?.length??0),0)+e.length;R.info(`\u25CF Pulled workspace elements \xB7 ${t}`);for(const n of Object.keys(r).sort()){const o=r[n];R.info(`\u2514\u2500\u2500 ${n}s \xB7 ${o?.length??0}`)}e.length>0&&R.info(`\u2514\u2500\u2500 connectors \xB7 ${e.length}`)}c(qo,"showStats$1");async function Bo(r,e){const t=r[Y.DELETE].size;R.info(`\u2299 Pull: conflicts detected \xB7 ${t}`),await gt(e,(n,o)=>{ie(n)&&r[Y.DELETE].has(o.uuid)&&R.info(`\u2514\u2500\u2500 ./membrane/${n} (deleted in remote)`)})}c(Bo,"showConflicts$1");async function _o(r){R.error("\u25A0 Error"),R.error(`\u2514\u2500\u2500 ${r.message}`),R.error(` ${r.stack}`)}c(_o,"showError$1");const j=[];for(let r=0;r<256;++r)j.push((r+256).toString(16).slice(1));function Wo(r,e=0){return(j[r[e+0]]+j[r[e+1]]+j[r[e+2]]+j[r[e+3]]+"-"+j[r[e+4]]+j[r[e+5]]+"-"+j[r[e+6]]+j[r[e+7]]+"-"+j[r[e+8]]+j[r[e+9]]+"-"+j[r[e+10]]+j[r[e+11]]+j[r[e+12]]+j[r[e+13]]+j[r[e+14]]+j[r[e+15]]).toLowerCase()}c(Wo,"unsafeStringify");let yt;const Jo=new Uint8Array(16);function Go(){if(!yt){if(typeof crypto>"u"||!crypto.getRandomValues)throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");yt=crypto.getRandomValues.bind(crypto)}return yt(Jo)}c(Go,"rng");const Ho=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto);var bn={randomUUID:Ho};function zo(r,e,t){if(bn.randomUUID&&!r)return bn.randomUUID();r=r||{};const n=r.random??r.rng?.()??Go();if(n.length<16)throw new Error("Random bytes length must be >= 16");return n[6]=n[6]&15|64,n[8]=n[8]&63|128,Wo(n)}c(zo,"v4");function Vo(r){r.command("push").description("Push workspace data to specified workspace").argument("[files...]","Files, directories, or glob patterns to push").option("--force","Overwrite conflicts with local data",!1).addHelpText("after",["","Examples:"," membrane push # Push all workspace elements"," membrane push data-sources/ # Push all data-sources"," membrane push actions/my-action/spec.yaml # Push specific action"," membrane push flows/*-test/spec.yaml # Push flows matching pattern"," membrane push --force # Overwrite conflicts with local data",""].join(`
19
- `)).action(async(e,t)=>{const n=Ft({text:"Pushing workspace",color:"white"}).start();try{await Yo(e,t,n)}catch(o){n.stop(),ni(o),process.exit(1)}})}c(Vo,"setupPushCommand");async function Yo(r,e,t){const n=r.length>0,o=await pn(),i=gn(),s=Zo(o,i),a=await hn(s,n?r:void 0);t.text="Comparing workspace";const l=await Cn(a,{dryRun:!0,partial:n});l[Y.DELETE].size>0&&!e.force&&(t.stop(),await ti(l,a),R.error("Use --force to delete remote elements"),process.exit(1));const{pushedConnectors:h=[]}=await Vt({onProgress:c((f,p)=>{f==="pushing"?t.start(`Pushing connector ${p}...`):t.succeed(`Pushed connector ${p}`)},"onProgress")});t.start("Pushing workspace..."),await Cn(a,{partial:n}),t.stop(),ei(s,h),process.exit(0)}c(Yo,"pushWorkspace");function Zo(r,e){const t=Xo(r),n=Qo(t,e),o={};for(const[i,s]of Object.entries(t)){const a=i,l=V[a]?.parentFieldKey||"parentId";o[a]=(s||[]).map(d=>{const h={...d};if(h.integrationId&&!h.integrationUuid&&(h.integrationUuid=n.get(h.integrationId.toString())||h.integrationId,delete h.integrationId),h.connectorId){if(!h.connectorUuid){const f=n.get(h.connectorId.toString());f&&(h.connectorUuid=f)}delete h.connectorId}if(h[l]){const f=h[l].toString(),p=n.get(f);p&&(h.parentUuid=p)}return a===T.Package&&h.elements&&(h.elements=h.elements.map(f=>{if(f.id&&!f.uuid){const p=n.get(f.id.toString());if(p)return{uuid:p,type:f.type}}return f})),delete h.id,h})}return o}c(Zo,"resolveLegacyIdReferences");function Xo(r){const e={};for(const[t,n]of Object.entries(r))e[t]=(n||[]).map(o=>o.uuid?o:{...o,uuid:zo()});return e}c(Xo,"generateMissingUuids");function Qo(r,e){const t=new Map;for(const n of Object.values(r))for(const o of n||[])o.id&&o.uuid&&t.set(o.id.toString(),o.uuid);for(const[n,o]of Object.entries(e))o.id&&t.set(o.id.toString(),n);return t}c(Qo,"buildIdToUuidLookup");function ei(r,e=[]){const t=Object.values(r).reduce((n,o)=>n+(o?.length??0),0)+e.length;R.info(`\u25CF Pushed workspace elements \xB7 ${t}`);for(const n of Object.keys(r).sort()){const o=r[n];R.info(`\u2514\u2500\u2500 ${n}s \xB7 ${o?.length??0}`)}e.length>0&&R.info(`\u2514\u2500\u2500 connectors \xB7 ${e.length}`)}c(ei,"showStats");async function ti(r,e){const t=r[Y.DELETE].size;R.info(`\u2299 Push: conflicts detected \xB7 ${t}`),await gt(e,(n,o)=>{ie(n)&&r[Y.DELETE].has(o.uuid)&&R.info(`\u2514\u2500\u2500 ./membrane/${n} (deleted locally)`)})}c(ti,"showConflicts");async function ni(r){R.error("\u25A0 Error"),R.error(`\u2514\u2500\u2500 ${r.message}`),R.error(` ${r.stack}`)}c(ni,"showError");const wt=[{id:"claude-code",name:"Claude Code",description:"Anthropic Claude Code agent",actionDescription:"Adding membrane MCP to .mcp.json in the current directory",addConfig:c(()=>{const r=x.join(process.cwd(),".mcp.json"),e={mcpServers:{membrane:{command:"membrane",args:["mcp"],env:{AGENT_NAME:"Claude Code"}}}};let t={};if(v.existsSync(r))try{t=JSON.parse(v.readFileSync(r,"utf8"))}catch{t={}}const n={...t,mcpServers:{...t.mcpServers,...e.mcpServers}};return v.writeFileSync(r,JSON.stringify(n,null,2)),`MCP server configuration added to ${r}`},"addConfig")},{id:"cursor",name:"Cursor",description:"Cursor AI editor",actionDescription:"Adding membrane MCP to .cursor/mcp.json in the current directory",addConfig:c(()=>{const r=x.join(process.cwd(),".cursor"),e=x.join(r,"mcp.json");v.existsSync(r)||v.mkdirSync(r);const t={mcpServers:{membrane:{command:"membrane",args:["mcp"],env:{AGENT_NAME:"Cursor"}}}};let n={};if(v.existsSync(e))try{n=JSON.parse(v.readFileSync(e,"utf8"))}catch{n={}}const o={...n,mcpServers:{...n.mcpServers,...t.mcpServers}};return v.writeFileSync(e,JSON.stringify(o,null,2)),`MCP server configuration added to ${e}`},"addConfig")}];function ri({onExit:r,onComplete:e}){const[t,n]=D(0),[o,i]=D(!1),[s,a]=D(null),[l,d]=D(""),[h,f]=D("");ae((E,S)=>{if(l||h){(S.escape||E==="q"||S.return)&&e();return}if(o)S.return||E===" "?p(s):S.escape&&(i(!1),a(null));else if(S.escape)r();else if(S.upArrow||E==="k")n(Math.max(0,t-1));else if(S.downArrow||E==="j")n(Math.min(wt.length-1,t+1));else if(S.return||E===" "){const N=wt[t];a(N),i(!0)}});const p=c(E=>{try{const S=E.addConfig();d(S)}catch(S){f(`Failed to write configuration: ${S.message||S}`)}},"addMcpConfiguration"),C=Math.min(80,process.stdout.columns||80);return l?b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:C,children:[u(g,{marginTop:-1,marginBottom:1,children:b(y,{bold:!0,children:["\u{1F517} Connect Agent \u2014 ",u(y,{color:"green",children:"Success"})]})}),b(g,{flexDirection:"column",paddingLeft:2,children:[u(y,{color:"green",children:l}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"The agent will now be able to use Membrane's integration capabilities."})})]}),u(g,{marginTop:1,paddingLeft:2,children:u(y,{color:"white",children:"[esc/q/enter: exit]"})})]}):h?b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:C,children:[u(g,{marginTop:-1,marginBottom:1,children:b(y,{bold:!0,children:["\u{1F517} Connect Agent \u2014 ",u(y,{color:"red",children:"Error"})]})}),u(g,{flexDirection:"column",paddingLeft:2,children:u(y,{color:"red",children:h})}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"[esc/q/enter: exit]"})})]}):o&&s?b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:C,children:[u(g,{marginTop:-1,marginBottom:1,children:b(y,{bold:!0,children:["\u{1F517} Connect Agent \u2014 ",u(y,{color:"cyan",children:"Confirmation"})]})}),b(g,{flexDirection:"column",paddingLeft:2,children:[b(y,{children:["Connect ",u(y,{bold:!0,children:s.name})," to Membrane via MCP?"]}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"This will add an MCP server configuration that allows the agent to use Membrane's integration capabilities."})}),u(g,{marginTop:1,children:u(y,{color:"yellow",bold:!0,children:s.actionDescription})}),u(g,{marginTop:2,marginBottom:1,children:b(y,{children:[u(y,{color:"white",bold:!0,children:"[Enter] Confirm"})," ",u(y,{color:"gray",children:"[Esc] Cancel"})]})})]})]}):b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:C,children:[u(g,{marginTop:-1,marginBottom:1,children:b(y,{bold:!0,children:["\u{1F517} Connect Agent \u2014 ",u(y,{color:"cyan",children:"Select Agent"})]})}),b(g,{flexDirection:"column",paddingLeft:2,children:[u(y,{color:"grey",children:"Choose an agent to connect to Membrane via MCP:"}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"This will add an MCP server configuration that allows the agent to use Membrane's integration capabilities."})}),u(g,{marginTop:1,flexDirection:"column",children:wt.map((E,S)=>b(g,{children:[b(y,{color:t===S?"cyan":"white",children:[t===S?"\u25B6 ":" ",E.name]}),b(y,{color:"grey",children:[" \u2014 ",E.description]})]},E.id))})]}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"[\u2191\u2193: select] [enter: choose] [esc: exit]"})})]})}c(ri,"AddMcpServerScreen");function oi(){const[r,e]=D(null),[t,n]=D([]),[o,i]=D(null);return he(()=>{const s=c(({status:l})=>{e(l),i(null)},"handleMcpStatusChanged"),a=c(({servers:l})=>{n(l),i(null)},"handleMcpServersChanged");return te.on(F.McpStatusChanged,s),te.on(F.McpServersChanged,a),()=>{te.off(F.McpStatusChanged,s),te.off(F.McpServersChanged,a)}},[]),{mcpStatus:r,allMcpServers:t,error:o,isRunning:r?.isRunning||!1,toolsCount:r?.toolsCount||0,totalRequests:r?.totalRequests||0,lastActivity:r?.lastActivity,processId:r?.processId,serverCount:t.length}}c(oi,"useMcpStatus");function ii(){const{error:r,serverCount:e,allMcpServers:t}=oi(),n=Math.min(100,process.stdout.columns||100);return b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:n,children:[u(g,{marginTop:-1,marginBottom:0,flexDirection:"column",children:b(y,{bold:!0,children:["\u{1F916} Connected AI Agents:"," ",r?u(y,{color:"red",children:"error reading status"}):e===0?u(y,{color:"yellow",children:"none"}):u(y,{color:"green",children:e})]})}),!r&&e===0&&u(g,{marginTop:1,children:b(y,{color:"grey",children:["Connect your AI agents to Membrane.",u(Gn,{}),"It will give them tools and context to build integrations."]})}),t.length>0&&u(g,{flexDirection:"column",paddingLeft:2,marginTop:1,children:t.map((o,i)=>u(g,{children:b(y,{color:"grey",children:["#",i+1," ",o.agentName,": ",o.totalRequests," calls"]})},o.processId))}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"[a: connect an agent]"})})]})}c(ii,"Agent");const vn=c(r=>{switch(r){case"error":return"red";case"success":return"green";case"warning":return"yellow";default:return}},"getLogColor");function En(r,e){return e<3?r.slice(0,Math.max(0,e)):r.length<=e?r:`${r.slice(0,e-3)}...`}c(En,"truncateText");function si({children:r}){const{state:e,logs:t}=H();return!e||e===k.NOT_INITIALIZED?b(g,{gap:1,flexDirection:"row",children:[u(cr,{type:"dots"}),u(y,{children:"Initializing..."})]}):e===k.SETTING_UP?u(g,{gap:1,flexDirection:"row",children:u(y,{children:"No workspace selected. Please run `membrane init` to select a workspace."})}):e===k.ERROR?u(g,{flexDirection:"column",children:t.slice().map((n,o)=>u(y,{color:vn(n.type),children:n.message},n.timestamp+o))}):r}c(si,"EnsureInitialized");function ai(){const{stats:r}=H(),e=Object.entries(r).filter(([t,n])=>n>0);return e.length===0?null:b(g,{flexDirection:"column",children:[u(g,{children:u(g,{width:12,children:u(y,{color:"grey",children:"Elements:"})})}),u(g,{flexDirection:"column",marginLeft:1,children:e.map(([t,n])=>b(g,{children:[u(g,{width:20,children:b(y,{children:[t,":"]})}),u(y,{color:"green",children:n})]},t))})]})}c(ai,"ElementStats");const Ct=5,ci=6;function li(){const{logs:r}=H(),[e,t]=D(0),n=Math.min(100,process.stdout.columns||100),o=Ct,i=Math.max(0,r.length-o-e),s=r.length-e,a=r.slice(i,s),l=n-ci,d=e<r.length-o,h=e>0;return ae((f,p)=>{if(r.length!==0)if(p.upArrow){const C=Math.max(0,r.length-o);t(E=>Math.min(C,E+1))}else p.downArrow?t(C=>Math.max(0,C-1)):(f==="G"||f==="g")&&t(0)}),b(g,{flexDirection:"column",paddingTop:1,children:[b(y,{color:"grey",children:["Recent Activity (",i+1,"-",s," of ",r.length,"):",r.length>Ct&&u(y,{color:"grey",children:" [arrows: scroll] [g: end]"})]}),a.map((f,p)=>u(g,{marginLeft:1,children:u(y,{color:vn(f.type),children:En(f.message,l)})},f.timestamp+p)),r.length>Ct&&b(g,{marginLeft:1,flexDirection:"row",children:[d&&u(y,{color:"grey",children:"\u2191 "}),h&&u(y,{color:"grey",children:"\u2193 "})]})]})}c(li,"Logs");const Oe=[{value:"sync",label:"Continue (overwrite/delete)",key:""},{value:"exit",label:"Cancel",key:""}];function ui(){const{state:r,resolveConflicts:e,exit:t}=H(),[n,o]=D(0),[i,s]=D(!1),[a,l]=D(!1);return ae((d,h)=>{if(!i){if(h.ctrl&&d.toLowerCase()==="r"){l(!a);return}h.upArrow?o(f=>f>0?f-1:Oe.length-1):h.downArrow?o(f=>f<Oe.length-1?f+1:0):d.toLowerCase()==="y"?o(0):d.toLowerCase()==="n"?o(1):(h.return||d===" ")&&(s(!0),Oe[n].value==="sync"?e({watch:!0}):t())}}),he(()=>{r!==k.CONFLICTS&&i&&s(!1)},[r,i]),b(g,{flexDirection:"column",paddingTop:1,children:[u(g,{children:u(g,{flexDirection:"row",gap:2,children:u(y,{bold:!0,color:"white",children:"Conflicts with remote"})})}),u(g,{children:u(y,{color:"grey",children:"The remote workspace has changes that aren't in your local workspace:"})}),u(g,{marginTop:1,marginLeft:2,children:u(hi,{isExpanded:a})}),b(g,{marginTop:2,flexDirection:"row",gap:1,children:[u(y,{color:"white",bold:!0,children:"What would you like to do?"}),u(y,{color:"grey",children:"[up/down, enter]"})]}),u(g,{children:i?b(g,{flexDirection:"row",gap:1,children:[u(Re,{type:"dots"}),u(y,{color:"blue",bold:!0,children:"Syncing with remote..."})]}):u(g,{flexDirection:"column",children:Oe.map((d,h)=>u(g,{flexDirection:"column",children:b(g,{flexDirection:"row",gap:1,children:[u(y,{color:n===h?"cyan":"grey",children:n===h?"\u25B6":" "}),u(y,{color:n===h?"cyan":"grey",bold:n===h,children:d.label})]})},d.value))})})]})}c(ui,"ResolveChangesUI");const di={[Z.UPDATE]:{incoming:{label:"Elements updated in remote",description:"(to be overwritten from remote)"},outgoing:{label:"Elements updated locally",description:"(to be pushed to remote)"}},[Z.DELETE]:{incoming:{label:"Elements not existing in remote",description:"(to be deleted locally)"},outgoing:{label:"Elements deleted locally",description:"(to be deleted from remote)"}},[Z.CREATE]:{incoming:{label:"Elements created in remote",description:"(to be created locally)"},outgoing:{label:"Elements created locally",description:"(to be created in remote)"}}};function hi({isExpanded:r,showControls:e=!0}){const{conflicts:t}=H(),n=5,o=Jn(()=>{const i={};return t.forEach(s=>{const a=`${s.type}-${s.direction}`;i[a]||(i[a]=[]),i[a].push(s)}),i},[t]);return u(g,{flexDirection:"column",children:Object.entries(o).map(([i,s])=>{if(s.length===0)return null;const[a,l]=i.split("-"),d=di[a][l];return b(g,{flexDirection:"column",children:[b(g,{flexDirection:"row",gap:1,children:[b(y,{color:"yellow",children:[d.label," (",s.length,")"]}),u(y,{color:"white",children:d.description})]}),(r?s:s.slice(0,n)).map(h=>u(g,{marginLeft:2,children:b(y,{color:"grey",children:["\u2022 ",h.element.id," (",h.element.relativePath,")"]})},h.element.id)),!r&&s.length>n&&u(g,{marginLeft:2,children:b(y,{color:"cyan",children:["... and ",s.length-n," more",e?" (press Ctrl+R to show all)":""]})}),r&&s.length>n&&e&&u(g,{marginLeft:2,children:u(y,{color:"cyan",children:"(press Ctrl+R to collapse)"})})]},i)})})}c(hi,"Conflicts");function pi(){const{config:r,state:e,logs:t,currentWorkspace:n,pull:o}=H(),i=n?.name,s=i?En(i,30):r?.workspaceKey,a=Math.min(100,process.stdout.columns||100);return he(()=>{o({watch:!0})},[]),b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:a,children:[u(g,{marginTop:-1,marginBottom:1,children:b(g,{flexDirection:"row",gap:1,children:[u(y,{bold:!0,children:"\u{1F504} Workspace"}),b(y,{color:mi(e),children:[" [",fi(e),"] "]})]})}),b(g,{children:[u(g,{width:12,children:u(y,{color:"grey",children:"Local:"})}),u(y,{color:"grey",children:process.cwd()})]}),b(g,{children:[u(g,{width:12,children:u(y,{color:"grey",children:"Remote:"})}),r?.workspaceKey?b(y,{color:"grey",children:[s," [o: open in console] [w: change]"]}):b(y,{children:[u(y,{color:"yellow",children:"not selected"})," [w: select]"]})]}),e===k.CONFLICTS?u(ui,{}):b($e,{children:[u(g,{paddingTop:1,children:u(ai,{})}),t.length>0&&u(li,{})]})]})}c(pi,"Workspace");function fi(r){switch(r){case k.PULLING:return"pulling";case k.PUSHING:return"pushing";case k.CONFLICTS:return"conflicts";case k.SYNCED:return"synced";case k.ERROR:return"error";case k.WATCHING:return"tracking changes";case k.RESOLVING:return"resolving";case k.NOT_SYNCED:return"not synced";case k.INITIALIZED:return"initialized";case k.SETTING_UP:return"setup required";default:return"unknown"}}c(fi,"getStatusDisplay");function mi(r){switch(r){case k.PULLING:return"yellow";case k.PUSHING:return"yellow";case k.CONFLICTS:return"red";case k.SYNCED:return"green";case k.ERROR:return"red";case k.WATCHING:return"green";case k.RESOLVING:return"yellow";case k.NOT_SYNCED:return"grey";case k.SETTING_UP:return"yellow";default:return"grey"}}c(mi,"getStatusColor");function gi(){const r=fo(),e=We(!0),{exit:t,state:n}=H(),[o,i]=D(null),s=o??(n===k.SETTING_UP?"setup":"main");ae(l=>{s==="main"&&(l==="w"&&i("workspace-selection"),l==="a"&&i("add-mcp-server"),l==="o"&&n===k.INITIALIZED&&a(),l==="s"&&i("setup"))});async function a(){try{const l=await Jt(r),d=et(`/w/${l}`),h=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";dr(`${h} "${d}"`)}catch(l){console.error("Failed to open workspace:",l),t()}}return c(a,"handleOpenWorkspace"),he(()=>(e.current=!0,()=>{e.current=!1}),[]),s==="workspace-selection"?u(sn,{onExit:c(()=>i(null),"onExit")}):s==="add-mcp-server"?u(ri,{onExit:c(()=>i(null),"onExit"),onComplete:c(()=>i(null),"onComplete")}):s==="setup"?u(an,{onComplete:c(()=>i(null),"onComplete")},Date.now()):u(si,{children:b(g,{flexDirection:"column",children:[u(g,{flexGrow:1,children:u(ii,{})}),u(pi,{}),u(g,{paddingLeft:2,children:u(y,{color:"grey",children:"[s: (re-)setup]"})})]})})}c(gi,"Main");const yi=c(()=>[w.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),w.yellow("\u2502 \u26A0\uFE0F EXPERIMENTAL FEATURE WARNING \u2502"),w.yellow("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),w.yellow("\u2502 Real-time agent mode is experimental and subject to changes. \u2502"),w.yellow("\u2502 Use in production environments is not recommended. \u2502"),w.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),""].join(`
20
- `),"createExperimentalWarning$1");function wi(r,e){r.command("sync").description("\u26A0\uFE0F EXPERIMENTAL: Sync workspace data in real-time - This feature is experimental and subject to changes. Use in production environments is not recommended.").option("--watch","Watch for changes and sync automatically",!1).option("--rps <number>","Maximum requests per second (default: 80)",t=>parseInt(t,10)).addHelpText("after",["","Examples:"," membrane sync --watch # Start real-time sync with watch mode"," membrane sync --watch --rps 5 # Limit to 5 requests per second",""].join(`
21
- `)).action(async t=>{if(t.watch||(console.error("Error: The sync command requires the --watch flag"),console.error("Usage: membrane sync --watch"),process.exit(1)),t.rps!==void 0){const n=t.rps;!isNaN(n)&&n>0&&n<=1e3?$.init({maxRequestsPerSecond:n}):(m.error(`Invalid RPS value: ${n}. Must be between 1 and 1000.`),process.exit(1))}console.warn(yi()),Je(se.createElement(ht,{cwd:process.cwd(),membraneCLIService:e,children:se.createElement(gi)}))})}c(wi,"setupSyncCommand");class Ci{static{c(this,"BaseRunner")}constructor(e={}){if(this.options=e,this.fsPaths=tt(),e&&typeof e=="object"){const t=e;"client"in t&&t.client&&(this.client=t.client),"workspace"in t&&(this.workspace=t.workspace)}}client;workspace;fsPaths}const Si="claude-sonnet-4-20250514";class Tt{static{c(this,"TestEnvironment")}client;connectionId;testsDir;testBasePath;options;llm;state={};constructor({connectionId:e,testsDir:t,testBasePath:n,client:o,options:i,llm:s}){this.client=o,this.connectionId=e,this.testsDir=t,this.testBasePath=n,this.llm=s,this.options=i}static async create({connectionId:e,testBasePath:t,options:n}){const o=we();if(!o)throw new Error("No configuration found. Please set MEMBRANE_WORKSPACE_KEY and MEMBRANE_WORKSPACE_SECRET environment variables, or run `membrane init` first.");if(!o.workspaceKey||!o.workspaceSecret)throw new Error("Missing workspace credentials");if(!o.anthropicApiKey)throw new Error("Anthropic API key not configured. Run `membrane init` to set up testing.");const i=new xt({token:await this.createMembraneToken(o),apiUri:o.apiUri}),s=new hr({apiKey:o.anthropicApiKey}),a={complete:c(async({prompt:l,maxTokens:d})=>{const h=await s.messages.create({model:Si,max_tokens:d,messages:[{role:"user",content:l}]});return h.content[0].type==="text"?h.content[0].text:""},"complete")};return new Tt({client:i,options:n,connectionId:e,testsDir:"src/testing/tests",testBasePath:t,llm:a})}async run(e){this.state={};const t={};for(const n of e)await n.run(),He(t,n.getResult());this.writeResults(t)}async readYaml(e){const t=I.join(this.testsDir,this.testBasePath,this.connectionId,e);return nt(t)}async writeYaml(e,t){const n=I.join(this.testsDir,this.testBasePath,this.connectionId,e);P.mkdirSync(I.dirname(n),{recursive:!0}),P.writeFileSync(n,G.dump(t,{noRefs:!0}))}writeResults(e){const t=I.join(this.testsDir,this.testBasePath,this.connectionId);P.mkdirSync(t,{recursive:!0});const n=I.join(t,"test-results.yaml");P.writeFileSync(n,G.dump(e,{noRefs:!0})),console.debug(`[TestRunner] Results written to: ${n}`)}static async createMembraneToken(e){const t=e.testCustomerId||"test-customer",n={id:t,name:t},o={issuer:e.workspaceKey,expiresIn:7200,algorithm:"HS512"};return Ge.sign(n,e.workspaceSecret,o)}}fr.interpolate=/{{([\s\S]+?)}}/g;function St(r,e){if(typeof r=="string"){const t=pr(r),n={state:e,random:{number:c(()=>ye.number.int(),"number"),alphaNumeric:c(i=>ye.string.alphanumeric(i),"alphaNumeric")},faker:{company:{name:c(()=>ye.company.name(),"name"),catchPhrase:c(()=>ye.company.catchPhrase(),"catchPhrase")},internet:{email:c(()=>ye.internet.email(),"email")}},entries:e["journal-entries"],orders:e["purchase-orders"]||e["sales-orders"],bills:e["vendor-bills"]},o=t(n);return r.includes("{{")&&r.includes("}}")&&(console.debug(`[TEMPLATE] Input: ${r}`),console.debug(`[TEMPLATE] Output: ${o}`)),o}return Array.isArray(r)?r.map(t=>St(t,e)):typeof r=="object"&&r!==null?Object.fromEntries(Object.entries(r).map(([t,n])=>[t,St(n,e)])):r}c(St,"processNode");function bi(r,e){return St(r,e)}c(bi,"handleTemplate");class vi{static{c(this,"BaseTestSuite")}result;environment;constructor({environment:e}){this.environment=e,this.result={}}async run(){}getResult(){return this.result}async runTest(e){console.debug(`${w.bold.cyan("[start]")} ${w.yellow(e.path)}`);let t=!1,n=!1,o={},i={},s;for(;!t;)try{i=await e.readTestCase(),i||(i=await e.generateConfig(),await this.environment.writeYaml(e.getTestCasePath(),i),console.debug(`${w.bold.yellow("[initialized]")} ${w.yellow(e.path)}`)),s=bi(i,this.environment.state),await e.run(s),console.debug(`${w.bold.green("[success]")} ${w.yellow(e.path)}`),t=!0,o=e.getResult(),Le(this.result,e.path,o)}catch(l){if(console.error(`${w.bold.red("[error]")} ${w.yellow(e.path)}: ${l}`),this.environment.options.fix&&!n){n=!0;try{await e.fix(l);continue}catch(d){console.error(`${w.bold.red("[fix fail]")} ${w.yellow(e.path)}: ${d}`)}}Le(this.result,e.path,{error:J(l)}),t=!0,o={error:J(l)}}const a={...s,result:o};await this.environment.writeYaml(e.getTestCasePath(),a)}async runTestSuite(e){await e.run(),He(this.result,e.getResult())}}class oe{static{c(this,"BaseTester")}environment;level;logs;assertions;resultsLocator;path;constructor({environment:e,path:t}){this.environment=e,this.logs=[],this.assertions=[],this.path=t,this.level=0,this.resultsLocator=""}async fix(e){const t=await this.readTestCase();if(!t)throw new Error(`No config found for test ${this.path}`);const n=await this.fixTestCase({config:t,error:e});console.debug(w.bold.yellow("[auto-fix]"),this.path),await this.environment.writeYaml(this.getTestCasePath(),n)}async readTestCase(){const e=this.getTestCasePath();return this.environment.readYaml(e)}async generateConfig(){return{}}async fixTestCase(e){throw new Error(`Auto-fix is not implemented for test ${this.path}`)}getResult(){return{logs:this.logs,assertions:this.assertions}}async assert(e,t,n){try{const o=await e();o?(this.logMsg(`\u2705 ${t}`),this.assertions.push({message:t,result:o})):(this.logMsg(`\u274C ${t}`),this.assertions.push({message:t,result:!1,details:n}))}catch(o){this.assertions.push({message:t,result:!1,details:J(o)}),this.logMsg(`\u274C ${t}: ${o.message}`)}}logMsg(e){console.debug(`${" ".repeat(this.level*2)}${e}`)}getTestCasePath(){return`${this.path}.test.yml`}}function bt(r,e){const t={};for(const n in e){if(!(n in r)){t[n]=e[n];continue}const o=r[n],i=e[n];if(o&&i&&typeof o=="object"&&typeof i=="object"){if(Array.isArray(o)&&Array.isArray(i)){const s=i.filter(a=>!o.some(l=>{if(typeof l=="object"&&typeof a=="object"&&l!==null&&a!==null&&!Array.isArray(l)&&!Array.isArray(a)){for(const d in a)if(!(d in l)||!vt(l[d],a[d]))return!1;return!0}else return JSON.stringify(l)===JSON.stringify(a)}));s.length>0&&(t[n]=s)}else if(!Array.isArray(o)&&!Array.isArray(i)){const s=bt(o,i);s!==null&&(t[n]=s)}else t[n]=i;continue}vt(o,i)||(t[n]=i)}return Object.keys(t).length===0?null:t}c(bt,"getNotMatchingSubFields");function vt(r,e){if(r==e||r?.toString?.()===e?.toString?.())return!0;const t=new Date(r),n=new Date(e);return!isNaN(t.getTime())&&!isNaN(n.getTime())?t.getTime()===n.getTime():!1}c(vt,"softCompare");class Ei extends oe{static{c(this,"DataCollectionCreateTester")}dataCollectionKey;dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/create`}),this.dataCollectionKey=t,this.dataCollection=n}async run(e){const t=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).create(e.input);await this.assert(()=>!!t.id,"Returned ID of a created record"),t.id&&(this.environment.state[this.dataCollectionKey]={createdRecordId:t.id});const n=je(this.dataCollection);if(this.dataCollection.findById){const i=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).findById({id:t.id});await this.assert(()=>!!i.record,"Record is returned from findById"),i.record&&(this.environment.state[this.dataCollectionKey]={createdRecordId:t.id,createdRecord:i.record.fields});const s=$t(n),a=xe(e.input.fields,s,{skipUnknownFields:!0}),l=xe(i.record.fields,s),d=bt(l,a);await this.assert(()=>!d,"Returned fields match created fields",{difference:d,sentFields:a,receivedFields:l})}const o=Kn(n??{});if(o.length>0){const i={};o.forEach(a=>{const l=qn(e.input.fields,a);typeof l<"u"&&Le(i,a,l)});const s=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).create({fields:i});await this.assert(()=>!!s.id,"Record can be created with schema-defined required fields only")}}async generateConfig(){const e=je(this.dataCollection);if(!e?.properties)throw new Error("No fields schema found for data collection");return{input:{fields:await this.generateFieldsWithLLM(e)}}}async fixTestCase({config:e,error:t}){const n=J(t),o=je(this.dataCollection),i=await this.getExampleRecordsForSchema(o),s=`I'm trying to create a data record in a data collection with the following fields schema:
14
+ `,version:"1.0.0"});for(const w of d){const T=w.execute;w.execute=async S=>(io(process.pid,process.cwd()),T(S)),h.addTool(w)}dt({isRunning:!0,startTime:new Date().toISOString(),toolsCount:d.length,lastActivity:new Date().toISOString(),processId:process.pid,cwd:process.cwd(),agentName:process.env.AGENT_NAME||"Unnamed Agent"});const m=setInterval(()=>{dt({processId:process.pid,cwd:process.cwd(),lastActivity:new Date().toISOString()})},5e3),p=c(async()=>{clearInterval(m),Se(process.pid,process.cwd());try{await h.stop()}catch{}},"cleanup");await h.start({transportType:"stdio"}),process.on("SIGINT",async()=>{await p(),process.exit(0)}),process.on("SIGTERM",async()=>{await p(),process.exit(0)}),process.on("exit",()=>{Se(process.pid,process.cwd())}),process.on("uncaughtException",async w=>{console.error("Uncaught exception:",w.message),await p(),process.exit(1)}),process.on("unhandledRejection",async w=>{console.error("Unhandled rejection:",w),await p(),process.exit(1)})}catch(e){e instanceof Error&&(console.error(e.message),process.exit(1)),console.error("An unknown error occurred"),process.exit(1)}})}c($o,"setupMcpCommand");const ko={info:"\u{1F4DD}",success:"\u2728",warning:"\u26A0\uFE0F",error:"\u274C",debug:"\u{1F50D}"},Ro={info:C.white,success:C.green,warning:C.yellow,error:C.red,debug:C.gray};class R{static{c(this,"Logger")}static formatMessage(e,t,n={icon:!1}){const o=n.timestamp?`${C.gray(new Date().toISOString())} `:"",i=n.prefix?`${C.gray(n.prefix)} `:"",s=n.suffix?` ${C.gray(n.suffix)}`:"",a=ko[t],l=Ro[t];return`${o}${n.icon?a:""} ${i}${l(e)}${s}`}static info(e,t){let n=C.white;if(t?.color&&(n=C[t.color.toLowerCase()]||C.white),t?.timestamp){const o=new Date().toLocaleTimeString();console.debug(`${C.gray(`[${o}]`)} ${n(e)}`)}else console.debug(n(e))}static group(e,t){}static groupEnd(){}static newLine(){}static success(e,t){console.debug(this.formatMessage(e,"success",t))}static warning(e,t){console.debug(this.formatMessage(e,"warning",t))}static error(e,t){console.error(this.formatMessage(e,"error",t))}static debug(e,t){t?.prefix?console.debug(C.gray(`[${t.prefix}] ${e}`),t.error?`
15
+ ${C.red(t.error)}`:""):console.debug(C.gray(e),t?.error?`
16
+ ${C.red(t.error)}`:"")}static step(e,t){}static header(e){console.debug(),console.debug(C.bold.cyan(`\u25B6 ${e}`)),console.debug()}static table(e,t){if(e.length===0)return;const n=t||Object.keys(e[0]),o=e.map(i=>{const s={};return n.forEach(a=>{s[a]=i[a]}),s});console.table(o,n)}static divider(){}}function Po(r){r.command("open").description("Open the workspace in the browser").addHelpText("after",["","Examples:"," membrane open # Open workspace in browser",""].join(`
17
+ `)).action(async()=>{try{R.header("Opening Workspace in Browser"),R.info("Loading configuration...");const e=Ce();if(!e)throw new Error("No configuration found. Please set MEMBRANE_WORKSPACE_KEY and MEMBRANE_WORKSPACE_SECRET environment variables, or run `membrane init` first.");if(!e.workspaceKey||!e.workspaceSecret)throw new Error("Missing workspace credentials");R.info("Retrieving workspace ID...");const t=await Gt(process.cwd()),n=rt(`/w/${t}`);R.info(`Opening ${n}...`);const{default:o}=await import("open");await o(n),R.success("Browser opened successfully")}catch(e){e instanceof Error&&(R.error(e.message),process.exit(1)),R.error("An unknown error occurred"),process.exit(1)}})}c(Po,"setupOpenCommand");async function yt(r,e,t={}){const{jobId:n,accessKey:o}=await e(),i=`${n}:${o}`;f.debug(`[background-job] Started job ${n}`);const s=Date.now(),{pollIntervalMs:a=1e3,timeoutMs:l=3e5,maxRetries:d=3}=t;let h=0;for(;;){if(Date.now()-s>l)throw new Error(`Background job ${n} timed out after ${l}ms`);await new Promise(w=>setTimeout(w,a));let p;try{p=await r.get(`background-jobs/${i}`),h=0}catch(w){if(w instanceof jn&&h<d){h++,f.debug(`[background-job] Job ${n} not found, retrying (${h}/${d})`);continue}throw w}if(p.status==="completed"){if(f.debug(`[background-job] Completed job ${n}`),!p.result)throw new Error(`Background job ${n} completed but returned no result`);return p.result}if(p.status==="failed"){const w=p.error?.message||"Unknown error";throw f.error(`[background-job] Failed job ${n}: ${w}`),p.error?.stack&&f.error(`Stacktrace: ${p.error.stack}`),new Error(`Background job ${n} failed: ${w}`)}f.debug(`[background-job] Polling job ${n} (status: ${p.status})`)}}c(yt,"pollBackgroundJob");function un(r,e){ve(E.dirname(r)),v.writeFileSync(r,e)}c(un,"writeFile");function Ao(r){v.existsSync(r)&&v.rmSync(r)}c(Ao,"deleteFile");function wt(r){v.existsSync(r)&&v.rmSync(r,{recursive:!0,force:!0})}c(wt,"deleteDir");function Do(r,e=!0){if(v.existsSync(r))try{const t=v.readFileSync(r,"utf8");return G.load(t)||void 0}catch(t){if(!e)return;if(t instanceof Error){const n=E.relative(process.cwd(),r);throw new Error(`Failed to parse YAML file "${n}": ${t.message}`)}throw t}}c(Do,"readYaml");function dn(r,e,t){try{ve(E.dirname(r));const n=G.dump(e,t);v.writeFileSync(r,n,"utf8")}catch(n){if(n instanceof Error){const o=E.relative(process.cwd(),r);throw new Error(`Failed to write YAML file "${o}": ${n.message}`)}throw n}return e}c(dn,"writeYaml");function ve(r){v.existsSync(r)||v.mkdirSync(r,{recursive:!0})}c(ve,"ensureDirExists");function hn(r,e=!0){if(!v.existsSync(r)||!v.statSync(r).isDirectory())return;let t=v.readdirSync(r);t.length>0&&(t.forEach(n=>hn(E.join(r,n),!1)),t=v.readdirSync(r)),t.length===0&&!e&&v.rmdirSync(r)}c(hn,"cleanupEmptyFolders");function Oo(r){const e=r.split(/[\\/]/).join("/");return e.endsWith("/")?e+"**":e}c(Oo,"normalizePattern");async function pn(r,e,t){const n=(e??[]).map(Oo),o=[];if(t){const i=E.join(U(process.cwd()),"connectors");for(const s of Object.values(t)){const a=s.key,l=E.join(i,a),d=E.join(l,`${a}.yml`);v.existsSync(d)&&o.push({name:Un(a),content:v.readFileSync(d,"utf-8")});const h=[...s.versions];v.existsSync(E.join(l,"development"))&&!h.includes("")&&h.push("");for(const m of h){const p=m===""?"development":m,w=E.join(l,p,"src"),T=E.join(l,p,"src.zip"),S=m===""?je:m;v.existsSync(w)?o.push({name:Rt(a,S),content:await No(w)}):v.existsSync(T)&&o.push({name:Rt(a,S),content:v.readFileSync(T)})}}}return new Promise((i,s)=>{const a=Ve("zip",{zlib:{level:9}}),l=[];a.on("data",h=>l.push(h)),a.on("end",()=>i(Buffer.concat(l))),a.on("error",h=>s(h));const d=new Map;for(const h of r[x.Integration]||[])d.set(h.uuid,h.key);for(const[h,m]of Object.entries(r))for(const p of m){const w=d.get(p.integrationUuid),T=Kn(h,p.key,w);n.length>0&&!n.some(S=>hr(T,S))||a.append(G.dump(p),{name:T})}for(const{name:h,content:m}of o)a.append(m,{name:h});a.finalize()})}c(pn,"createMembraneZip");async function No(r){return new Promise((e,t)=>{const n=Ve("zip",{zlib:{level:9}}),o=[];n.on("data",i=>o.push(i)),n.on("end",()=>e(Buffer.concat(o))),n.on("error",i=>t(i)),n.directory(r,!1),n.finalize()})}c(No,"createConnectorVersionZip");async function Ct(r,e){const t=await jt.loadAsync(r),n=[];for(const[o,i]of Object.entries(t.files)){if(i.dir)continue;const s=ie(o);if(!s)continue;const a=await i.async("string"),l=G.load(a);if(!l)continue;const d=await e(o,l,s);d!==void 0&&n.push(d)}return n}c(Ct,"iterateZipItems");async function Mo(r){const e=await jt.loadAsync(r),t={};for(const[n,o]of Object.entries(e.files)){if(o.dir)continue;const i=ie(n);if(!i)continue;const s=await o.async("string"),a=G.load(s);t[i.type]||(t[i.type]=[]),t[i.type].push(a)}return t}c(Mo,"readMembraneZip");async function fn(r=process.cwd()){const e=await mn(U(r)),t={};for(const{data:n,type:o}of e)t[o]||(t[o]=[]),t[o].push(n);return t}c(fn,"readMembraneDir");async function mn(r){const e=gn(r),t=[];for(const n of e){if(n.isDirectory())continue;const o=ie(n.path);if(!o)continue;const i=await n.readContent(),s=G.load(i),a=E.join(r,n.path);t.push({filePath:a,data:s,type:o.type})}return t}c(mn,"iterateMembraneFiles");function gn(r,e){const t=[];if(e||(e=r),!v.existsSync(e)||e.startsWith(E.join(r,"connectors")))return t;const n=v.readdirSync(e,{withFileTypes:!0});for(const o of n){const i=E.join(e,o.name),s=E.relative(r,i);o.isDirectory()?t.push(...gn(r,i)):o.isFile()&&ie(s)&&t.push({path:s,isDirectory:c(()=>!1,"isDirectory"),readContent:c(async()=>v.readFileSync(i,"utf8"),"readContent")})}return t}c(gn,"getMembraneFiles");function yn(){const r={},e=E.join(U(process.cwd()),"connectors");if(!v.existsSync(e))return r;const t=v.readdirSync(e);for(const n of t){const o=E.join(e,n);if(!v.statSync(o).isDirectory())continue;const i=E.join(o,`${n}.yml`),s=Do(i,!1);if(!s?.uuid)continue;const a=new Set,l=v.readdirSync(o);for(const d of l){if(d.endsWith(".yml"))continue;const h=E.join(o,d);v.statSync(h).isDirectory()&&a.add(d=="development"?"":d)}r[s.uuid]={key:n,id:s.id,versions:Array.from(a)}}return r}c(yn,"readConnectorsDir");function Ee(r,e){const t=E.join(U(process.cwd()),"connectors",r);return e==""||e===je?E.join(t,"development"):e?E.join(t,e):t}c(Ee,"getConnectorPath");const wn=1e3,Cn=12e4;async function Fo(){const r=await I.withClient(async t=>yt(t,()=>t.get("export"),{pollIntervalMs:wn,timeoutMs:Cn}));if(!r)throw new Error("Failed to export workspace");const e=await ge.get(r.downloadUrl,{responseType:"arraybuffer"});return Buffer.from(e.data)}c(Fo,"downloadWorkspaceExport");async function Sn(r,e={}){const t=new Mt;t.append("file",r,{filename:"membrane.zip",contentType:"application/zip"});const n=await I.withClient(async i=>{const s=`import?dryRun=${e.dryRun??!1}&partial=${e.partial??!1}`,{jobId:a,accessKey:l}=await i.post(s,t,{headers:t.getHeaders()});return yt(i,()=>Promise.resolve({jobId:a,accessKey:l}),{pollIntervalMs:1e3,timeoutMs:3e5})});if(!n)throw new Error("Failed to import workspace");const o={};for(const[i,s]of Object.entries(n))o[i]=new Set(s||[]);return o}c(Sn,"importWorkspace");async function Lo(r,e){const t=await I.withClient(async o=>yt(o,()=>o.get(`connectors/${r}/export-files`,{version:e}),{pollIntervalMs:wn,timeoutMs:Cn}));if(!t)throw new Error("Failed to export connector version");const n=await ge.get(t.downloadUrl,{responseType:"arraybuffer"});return Buffer.from(n.data)}c(Lo,"exportConnector");const bn=5;function jo(r){r.command("pull").description("Pull workspace data from specified workspace").option("--force","Overwrite conflicts with remote data",!1).addHelpText("after",["","Examples:"," membrane pull # Pull from default workspace"," membrane pull --force # Overwrite conflicts with remote data",""].join(`
18
+ `)).action(async e=>{const t=Lt({text:"Pulling workspace",color:"white"}).start();try{const n=await Uo(e,t);t.stop(),Wo(n.workspaceExport,n.connectors)}catch(n){t.stop(),Go(n),process.exit(1)}})}c(jo,"setupPullCommand");async function Uo(r,e){const t=await fn(),n=await pn(t),o=await Fo(),i=await Mo(o),{comparison:s}=qn(t,i);s[Y.DELETE].size>0&&!r.force&&(await Jo(s,n),R.error("Use --force to delete local elements"),process.exit(1));const l=await mn(U(process.cwd()));for(const{filePath:p,data:w}of l)s[Y.DELETE].has(w.uuid)&&Ao(p);hn(U(process.cwd())),await Ct(o,(p,w)=>{if(ie(p)&&(s[Y.CREATE].has(w.uuid)||s[Y.UPDATE].has(w.uuid))){const S=$.join(U(process.cwd()),p);dn(S,w)}});const d=await I.getVersion(),h=d?ye.coerce(d):null;return{connectors:h&&ye.gte(h,"1.8.0")?await Ko(o,e):await Bo(i[x.Integration],e),workspaceExport:i}}c(Uo,"pullWorkspace");async function Ko(r,e){e.text="Extracting connectors",wt($.join(U(process.cwd()),"connectors"));const t=new Set,n=await Re.Open.buffer(r);for(const o of n.files){if(!o.path.startsWith("connectors/")||o.type==="Directory")continue;const i=$.join(U(process.cwd()),o.path);ve($.dirname(i));const s=await o.buffer();if(un(i,s),t.add(o.path.split("/")[1]),o.path.endsWith("/development/src.zip")){const a=$.join($.dirname(i),"src");ve(a),await(await Re.Open.buffer(s)).extract({path:a})}}return Array.from(t)}c(Ko,"extractConnectorsFromExport");async function qo(r,e,t){if(un($.join(Ee(r,e),"src.zip"),t),!e||e===je){const n=$.join(Ee(r,e),"src");ve(n),await(await Re.Open.buffer(t)).extract({path:n})}}c(qo,"writeConnectorVersion");async function Bo(r,e){e.text="Pulling connectors";const t=new Map,{id:n}=await I.withClient(l=>l.get("org-workspace-id")),{items:o=[]}=await I.withClient(l=>l.get(`/connectors?workspaceId=${n}`));for(const l of o){const d=l.uuid??l.id;!l.isPublic&&d&&t.set(d,new Set([""]))}for(const l of r??[]){const{connectorUuid:d,connectorVersion:h}=l;d&&(t.has(d)||t.set(d,new Set),t.get(d).add(h??""))}const i=yn();for(const[l,{key:d,versions:h}]of Object.entries(i)){if(!t.has(l)){const p=Ee(d);wt(p);continue}const m=t.get(l);for(const p of h)if(!m.has(p)){const w=Ee(d,p);wt(w)}}const s=Array.from(t.entries()),a=c((l,d)=>{l==="pulling"?e.start(`Pulling connector ${d}...`):e.succeed(`Pulled connector ${d}`)},"onProgress");for(let l=0;l<s.length;l+=bn){const d=s.slice(l,l+bn);await Promise.all(d.map(([h,m])=>_o(h,Array.from(m),a)))}return Array.from(t.keys())}c(Bo,"pullConnectorsLegacy");async function _o(r,e,t){const n=await I.withClient(d=>d.get(`connectors/${r}/export-json`),!1),o=await I.withClient(d=>d.get(`connectors/${r}`),!1);if(!n||!o||!n.key||!o.key)return;const i=o.name||n.key;t?.("pulling",i);const s={...n,id:o.id,uuid:o.uuid},a=Ee(n.key),l=$.join(a,`${n.key}.yml`);dn(l,s);for(const d of e){const h=await Lo(r,d);await qo(n.key,d,h)}t?.("pulled",i)}c(_o,"pullConnector");function Wo(r,e=[]){const t=Object.values(r).reduce((n,o)=>n+(o?.length??0),0)+e.length;R.info(`\u25CF Pulled workspace elements \xB7 ${t}`);for(const n of Object.keys(r).sort()){const o=r[n];R.info(`\u2514\u2500\u2500 ${n}s \xB7 ${o?.length??0}`)}e.length>0&&R.info(`\u2514\u2500\u2500 connectors \xB7 ${e.length}`)}c(Wo,"showStats$1");async function Jo(r,e){const t=r[Y.DELETE].size;R.info(`\u2299 Pull: conflicts detected \xB7 ${t}`),await Ct(e,(n,o)=>{ie(n)&&r[Y.DELETE].has(o.uuid)&&R.info(`\u2514\u2500\u2500 ./membrane/${n} (deleted in remote)`)})}c(Jo,"showConflicts$1");async function Go(r){R.error("\u25A0 Error"),R.error(`\u2514\u2500\u2500 ${r.message}`),R.error(` ${r.stack}`)}c(Go,"showError$1");const j=[];for(let r=0;r<256;++r)j.push((r+256).toString(16).slice(1));function Ho(r,e=0){return(j[r[e+0]]+j[r[e+1]]+j[r[e+2]]+j[r[e+3]]+"-"+j[r[e+4]]+j[r[e+5]]+"-"+j[r[e+6]]+j[r[e+7]]+"-"+j[r[e+8]]+j[r[e+9]]+"-"+j[r[e+10]]+j[r[e+11]]+j[r[e+12]]+j[r[e+13]]+j[r[e+14]]+j[r[e+15]]).toLowerCase()}c(Ho,"unsafeStringify");let St;const zo=new Uint8Array(16);function Vo(){if(!St){if(typeof crypto>"u"||!crypto.getRandomValues)throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");St=crypto.getRandomValues.bind(crypto)}return St(zo)}c(Vo,"rng");const Yo=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto);var vn={randomUUID:Yo};function Zo(r,e,t){if(vn.randomUUID&&!r)return vn.randomUUID();r=r||{};const n=r.random??r.rng?.()??Vo();if(n.length<16)throw new Error("Random bytes length must be >= 16");return n[6]=n[6]&15|64,n[8]=n[8]&63|128,Ho(n)}c(Zo,"v4");const Xo="1.9";function Qo(r){r.command("push").description("Push workspace data to specified workspace").argument("[files...]","Files, directories, or glob patterns to push").option("--force","Overwrite conflicts with local data",!1).addHelpText("after",["","Examples:"," membrane push # Push all workspace elements"," membrane push data-sources/ # Push all data-sources"," membrane push actions/my-action/spec.yaml # Push specific action"," membrane push flows/*-test/spec.yaml # Push flows matching pattern"," membrane push --force # Overwrite conflicts with local data",""].join(`
19
+ `)).action(async(e,t)=>{const n=Lt({text:"Pushing workspace",color:"white"}).start();try{await ei(e,t,n)}catch(o){n.stop(),ui(o),process.exit(1)}})}c(Qo,"setupPushCommand");async function ei(r,e,t){const n=r.length>0,o=await fn(),i=yn(),s=oi(o,i),a=await ti(),l=await pn(s,n?r:void 0,a?i:void 0);e.force||(t.text="Comparing workspace",await ni(l,n)&&(t.stop(),process.exit(1)));const d=a?Object.keys(i):await ri(t);t.start("Pushing workspace..."),await Sn(l,{partial:n}),t.stop(),ci(s,d),process.exit(0)}c(ei,"pushWorkspace");async function ti(){const r=await I.getVersion(),e=r?ye.coerce(r):null,t=ye.coerce(Xo);return!!(e&&t&&ye.gte(e,t))}c(ti,"checkConnectorImportSupport");async function ni(r,e){const t=await Sn(r,{dryRun:!0,partial:e}),n=t[Y.DELETE].size>0;return n&&(await li(t,r),R.error("Use --force to delete remote elements")),n}c(ni,"checkForConflicts");async function ri(r){return(await Yt({onProgress:c((t,n)=>{t==="pushing"?r.start(`Pushing connector ${n}...`):r.succeed(`Pushed connector ${n}`)},"onProgress")})).pushedConnectors??[]}c(ri,"pushConnectorsLegacy");function oi(r,e){const t=si(r),n=ai(t,e),o={};for(const[i,s]of Object.entries(t)){const a=i;o[a]=(s||[]).map(l=>ii(l,a,n))}return o}c(oi,"resolveLegacyIdReferences");function ii(r,e,t){const n={...r},o=V[e]?.parentFieldKey||"parentId";if(n.integrationId&&!n.integrationUuid&&(n.integrationUuid=t.get(n.integrationId.toString())||n.integrationId,delete n.integrationId),n.connectorId){if(!n.connectorUuid){const i=t.get(n.connectorId.toString());i&&(n.connectorUuid=i)}delete n.connectorId}if(n[o]){const i=t.get(n[o].toString());i&&(n.parentUuid=i)}return e===x.Package&&n.elements&&(n.elements=n.elements.map(i=>{if(i.id&&!i.uuid){const s=t.get(i.id.toString());if(s)return{uuid:s,type:i.type}}return i})),delete n.id,n}c(ii,"resolveElementIds");function si(r){const e={};for(const[t,n]of Object.entries(r))e[t]=(n||[]).map(o=>o.uuid?o:{...o,uuid:Zo()});return e}c(si,"generateMissingUuids");function ai(r,e){const t=new Map;for(const n of Object.values(r))for(const o of n||[])o.id&&o.uuid&&t.set(o.id.toString(),o.uuid);for(const[n,o]of Object.entries(e))o.id&&t.set(o.id.toString(),n);return t}c(ai,"buildIdToUuidLookup");function ci(r,e=[]){const t=Object.values(r).reduce((n,o)=>n+(o?.length??0),0)+e.length;R.info(`\u25CF Pushed workspace elements \xB7 ${t}`);for(const n of Object.keys(r).sort()){const o=r[n];R.info(`\u2514\u2500\u2500 ${n}s \xB7 ${o?.length??0}`)}e.length>0&&R.info(`\u2514\u2500\u2500 connectors \xB7 ${e.length}`)}c(ci,"showStats");async function li(r,e){const t=r[Y.DELETE].size;R.info(`\u2299 Push: conflicts detected \xB7 ${t}`),await Ct(e,(n,o)=>{ie(n)&&r[Y.DELETE].has(o.uuid)&&R.info(`\u2514\u2500\u2500 ./membrane/${n} (deleted locally)`)})}c(li,"showConflicts");function ui(r){R.error("\u25A0 Error"),R.error(`\u2514\u2500\u2500 ${r.message}`),R.error(` ${r.stack}`)}c(ui,"showError");const bt=[{id:"claude-code",name:"Claude Code",description:"Anthropic Claude Code agent",actionDescription:"Adding membrane MCP to .mcp.json in the current directory",addConfig:c(()=>{const r=E.join(process.cwd(),".mcp.json"),e={mcpServers:{membrane:{command:"membrane",args:["mcp"],env:{AGENT_NAME:"Claude Code"}}}};let t={};if(v.existsSync(r))try{t=JSON.parse(v.readFileSync(r,"utf8"))}catch{t={}}const n={...t,mcpServers:{...t.mcpServers,...e.mcpServers}};return v.writeFileSync(r,JSON.stringify(n,null,2)),`MCP server configuration added to ${r}`},"addConfig")},{id:"cursor",name:"Cursor",description:"Cursor AI editor",actionDescription:"Adding membrane MCP to .cursor/mcp.json in the current directory",addConfig:c(()=>{const r=E.join(process.cwd(),".cursor"),e=E.join(r,"mcp.json");v.existsSync(r)||v.mkdirSync(r);const t={mcpServers:{membrane:{command:"membrane",args:["mcp"],env:{AGENT_NAME:"Cursor"}}}};let n={};if(v.existsSync(e))try{n=JSON.parse(v.readFileSync(e,"utf8"))}catch{n={}}const o={...n,mcpServers:{...n.mcpServers,...t.mcpServers}};return v.writeFileSync(e,JSON.stringify(o,null,2)),`MCP server configuration added to ${e}`},"addConfig")}];function di({onExit:r,onComplete:e}){const[t,n]=D(0),[o,i]=D(!1),[s,a]=D(null),[l,d]=D(""),[h,m]=D("");ae((T,S)=>{if(l||h){(S.escape||T==="q"||S.return)&&e();return}if(o)S.return||T===" "?p(s):S.escape&&(i(!1),a(null));else if(S.escape)r();else if(S.upArrow||T==="k")n(Math.max(0,t-1));else if(S.downArrow||T==="j")n(Math.min(bt.length-1,t+1));else if(S.return||T===" "){const O=bt[t];a(O),i(!0)}});const p=c(T=>{try{const S=T.addConfig();d(S)}catch(S){m(`Failed to write configuration: ${S.message||S}`)}},"addMcpConfiguration"),w=Math.min(80,process.stdout.columns||80);return l?b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:w,children:[u(g,{marginTop:-1,marginBottom:1,children:b(y,{bold:!0,children:["\u{1F517} Connect Agent \u2014 ",u(y,{color:"green",children:"Success"})]})}),b(g,{flexDirection:"column",paddingLeft:2,children:[u(y,{color:"green",children:l}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"The agent will now be able to use Membrane's integration capabilities."})})]}),u(g,{marginTop:1,paddingLeft:2,children:u(y,{color:"white",children:"[esc/q/enter: exit]"})})]}):h?b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:w,children:[u(g,{marginTop:-1,marginBottom:1,children:b(y,{bold:!0,children:["\u{1F517} Connect Agent \u2014 ",u(y,{color:"red",children:"Error"})]})}),u(g,{flexDirection:"column",paddingLeft:2,children:u(y,{color:"red",children:h})}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"[esc/q/enter: exit]"})})]}):o&&s?b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:w,children:[u(g,{marginTop:-1,marginBottom:1,children:b(y,{bold:!0,children:["\u{1F517} Connect Agent \u2014 ",u(y,{color:"cyan",children:"Confirmation"})]})}),b(g,{flexDirection:"column",paddingLeft:2,children:[b(y,{children:["Connect ",u(y,{bold:!0,children:s.name})," to Membrane via MCP?"]}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"This will add an MCP server configuration that allows the agent to use Membrane's integration capabilities."})}),u(g,{marginTop:1,children:u(y,{color:"yellow",bold:!0,children:s.actionDescription})}),u(g,{marginTop:2,marginBottom:1,children:b(y,{children:[u(y,{color:"white",bold:!0,children:"[Enter] Confirm"})," ",u(y,{color:"gray",children:"[Esc] Cancel"})]})})]})]}):b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:w,children:[u(g,{marginTop:-1,marginBottom:1,children:b(y,{bold:!0,children:["\u{1F517} Connect Agent \u2014 ",u(y,{color:"cyan",children:"Select Agent"})]})}),b(g,{flexDirection:"column",paddingLeft:2,children:[u(y,{color:"grey",children:"Choose an agent to connect to Membrane via MCP:"}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"This will add an MCP server configuration that allows the agent to use Membrane's integration capabilities."})}),u(g,{marginTop:1,flexDirection:"column",children:bt.map((T,S)=>b(g,{children:[b(y,{color:t===S?"cyan":"white",children:[t===S?"\u25B6 ":" ",T.name]}),b(y,{color:"grey",children:[" \u2014 ",T.description]})]},T.id))})]}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"[\u2191\u2193: select] [enter: choose] [esc: exit]"})})]})}c(di,"AddMcpServerScreen");function hi(){const[r,e]=D(null),[t,n]=D([]),[o,i]=D(null);return he(()=>{const s=c(({status:l})=>{e(l),i(null)},"handleMcpStatusChanged"),a=c(({servers:l})=>{n(l),i(null)},"handleMcpServersChanged");return te.on(F.McpStatusChanged,s),te.on(F.McpServersChanged,a),()=>{te.off(F.McpStatusChanged,s),te.off(F.McpServersChanged,a)}},[]),{mcpStatus:r,allMcpServers:t,error:o,isRunning:r?.isRunning||!1,toolsCount:r?.toolsCount||0,totalRequests:r?.totalRequests||0,lastActivity:r?.lastActivity,processId:r?.processId,serverCount:t.length}}c(hi,"useMcpStatus");function pi(){const{error:r,serverCount:e,allMcpServers:t}=hi(),n=Math.min(100,process.stdout.columns||100);return b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:n,children:[u(g,{marginTop:-1,marginBottom:0,flexDirection:"column",children:b(y,{bold:!0,children:["\u{1F916} Connected AI Agents:"," ",r?u(y,{color:"red",children:"error reading status"}):e===0?u(y,{color:"yellow",children:"none"}):u(y,{color:"green",children:e})]})}),!r&&e===0&&u(g,{marginTop:1,children:b(y,{color:"grey",children:["Connect your AI agents to Membrane.",u(zn,{}),"It will give them tools and context to build integrations."]})}),t.length>0&&u(g,{flexDirection:"column",paddingLeft:2,marginTop:1,children:t.map((o,i)=>u(g,{children:b(y,{color:"grey",children:["#",i+1," ",o.agentName,": ",o.totalRequests," calls"]})},o.processId))}),u(g,{marginTop:1,children:u(y,{color:"grey",children:"[a: connect an agent]"})})]})}c(pi,"Agent");const En=c(r=>{switch(r){case"error":return"red";case"success":return"green";case"warning":return"yellow";default:return}},"getLogColor");function Tn(r,e){return e<3?r.slice(0,Math.max(0,e)):r.length<=e?r:`${r.slice(0,e-3)}...`}c(Tn,"truncateText");function fi({children:r}){const{state:e,logs:t}=H();return!e||e===k.NOT_INITIALIZED?b(g,{gap:1,flexDirection:"row",children:[u(ur,{type:"dots"}),u(y,{children:"Initializing..."})]}):e===k.SETTING_UP?u(g,{gap:1,flexDirection:"row",children:u(y,{children:"No workspace selected. Please run `membrane init` to select a workspace."})}):e===k.ERROR?u(g,{flexDirection:"column",children:t.slice().map((n,o)=>u(y,{color:En(n.type),children:n.message},n.timestamp+o))}):r}c(fi,"EnsureInitialized");function mi(){const{stats:r}=H(),e=Object.entries(r).filter(([t,n])=>n>0);return e.length===0?null:b(g,{flexDirection:"column",children:[u(g,{children:u(g,{width:12,children:u(y,{color:"grey",children:"Elements:"})})}),u(g,{flexDirection:"column",marginLeft:1,children:e.map(([t,n])=>b(g,{children:[u(g,{width:20,children:b(y,{children:[t,":"]})}),u(y,{color:"green",children:n})]},t))})]})}c(mi,"ElementStats");const vt=5,gi=6;function yi(){const{logs:r}=H(),[e,t]=D(0),n=Math.min(100,process.stdout.columns||100),o=vt,i=Math.max(0,r.length-o-e),s=r.length-e,a=r.slice(i,s),l=n-gi,d=e<r.length-o,h=e>0;return ae((m,p)=>{if(r.length!==0)if(p.upArrow){const w=Math.max(0,r.length-o);t(T=>Math.min(w,T+1))}else p.downArrow?t(w=>Math.max(0,w-1)):(m==="G"||m==="g")&&t(0)}),b(g,{flexDirection:"column",paddingTop:1,children:[b(y,{color:"grey",children:["Recent Activity (",i+1,"-",s," of ",r.length,"):",r.length>vt&&u(y,{color:"grey",children:" [arrows: scroll] [g: end]"})]}),a.map((m,p)=>u(g,{marginLeft:1,children:u(y,{color:En(m.type),children:Tn(m.message,l)})},m.timestamp+p)),r.length>vt&&b(g,{marginLeft:1,flexDirection:"row",children:[d&&u(y,{color:"grey",children:"\u2191 "}),h&&u(y,{color:"grey",children:"\u2193 "})]})]})}c(yi,"Logs");const Ne=[{value:"sync",label:"Continue (overwrite/delete)",key:""},{value:"exit",label:"Cancel",key:""}];function wi(){const{state:r,resolveConflicts:e,exit:t}=H(),[n,o]=D(0),[i,s]=D(!1),[a,l]=D(!1);return ae((d,h)=>{if(!i){if(h.ctrl&&d.toLowerCase()==="r"){l(!a);return}h.upArrow?o(m=>m>0?m-1:Ne.length-1):h.downArrow?o(m=>m<Ne.length-1?m+1:0):d.toLowerCase()==="y"?o(0):d.toLowerCase()==="n"?o(1):(h.return||d===" ")&&(s(!0),Ne[n].value==="sync"?e({watch:!0}):t())}}),he(()=>{r!==k.CONFLICTS&&i&&s(!1)},[r,i]),b(g,{flexDirection:"column",paddingTop:1,children:[u(g,{children:u(g,{flexDirection:"row",gap:2,children:u(y,{bold:!0,color:"white",children:"Conflicts with remote"})})}),u(g,{children:u(y,{color:"grey",children:"The remote workspace has changes that aren't in your local workspace:"})}),u(g,{marginTop:1,marginLeft:2,children:u(Si,{isExpanded:a})}),b(g,{marginTop:2,flexDirection:"row",gap:1,children:[u(y,{color:"white",bold:!0,children:"What would you like to do?"}),u(y,{color:"grey",children:"[up/down, enter]"})]}),u(g,{children:i?b(g,{flexDirection:"row",gap:1,children:[u(Pe,{type:"dots"}),u(y,{color:"blue",bold:!0,children:"Syncing with remote..."})]}):u(g,{flexDirection:"column",children:Ne.map((d,h)=>u(g,{flexDirection:"column",children:b(g,{flexDirection:"row",gap:1,children:[u(y,{color:n===h?"cyan":"grey",children:n===h?"\u25B6":" "}),u(y,{color:n===h?"cyan":"grey",bold:n===h,children:d.label})]})},d.value))})})]})}c(wi,"ResolveChangesUI");const Ci={[Z.UPDATE]:{incoming:{label:"Elements updated in remote",description:"(to be overwritten from remote)"},outgoing:{label:"Elements updated locally",description:"(to be pushed to remote)"}},[Z.DELETE]:{incoming:{label:"Elements not existing in remote",description:"(to be deleted locally)"},outgoing:{label:"Elements deleted locally",description:"(to be deleted from remote)"}},[Z.CREATE]:{incoming:{label:"Elements created in remote",description:"(to be created locally)"},outgoing:{label:"Elements created locally",description:"(to be created in remote)"}}};function Si({isExpanded:r,showControls:e=!0}){const{conflicts:t}=H(),n=5,o=Hn(()=>{const i={};return t.forEach(s=>{const a=`${s.type}-${s.direction}`;i[a]||(i[a]=[]),i[a].push(s)}),i},[t]);return u(g,{flexDirection:"column",children:Object.entries(o).map(([i,s])=>{if(s.length===0)return null;const[a,l]=i.split("-"),d=Ci[a][l];return b(g,{flexDirection:"column",children:[b(g,{flexDirection:"row",gap:1,children:[b(y,{color:"yellow",children:[d.label," (",s.length,")"]}),u(y,{color:"white",children:d.description})]}),(r?s:s.slice(0,n)).map(h=>u(g,{marginLeft:2,children:b(y,{color:"grey",children:["\u2022 ",h.element.id," (",h.element.relativePath,")"]})},h.element.id)),!r&&s.length>n&&u(g,{marginLeft:2,children:b(y,{color:"cyan",children:["... and ",s.length-n," more",e?" (press Ctrl+R to show all)":""]})}),r&&s.length>n&&e&&u(g,{marginLeft:2,children:u(y,{color:"cyan",children:"(press Ctrl+R to collapse)"})})]},i)})})}c(Si,"Conflicts");function bi(){const{config:r,state:e,logs:t,currentWorkspace:n,pull:o}=H(),i=n?.name,s=i?Tn(i,30):r?.workspaceKey,a=Math.min(100,process.stdout.columns||100);return he(()=>{o({watch:!0})},[]),b(g,{flexDirection:"column",paddingX:1,borderStyle:"round",borderTop:!0,width:a,children:[u(g,{marginTop:-1,marginBottom:1,children:b(g,{flexDirection:"row",gap:1,children:[u(y,{bold:!0,children:"\u{1F504} Workspace"}),b(y,{color:Ei(e),children:[" [",vi(e),"] "]})]})}),b(g,{children:[u(g,{width:12,children:u(y,{color:"grey",children:"Local:"})}),u(y,{color:"grey",children:process.cwd()})]}),b(g,{children:[u(g,{width:12,children:u(y,{color:"grey",children:"Remote:"})}),r?.workspaceKey?b(y,{color:"grey",children:[s," [o: open in console] [w: change]"]}):b(y,{children:[u(y,{color:"yellow",children:"not selected"})," [w: select]"]})]}),e===k.CONFLICTS?u(wi,{}):b(ke,{children:[u(g,{paddingTop:1,children:u(mi,{})}),t.length>0&&u(yi,{})]})]})}c(bi,"Workspace");function vi(r){switch(r){case k.PULLING:return"pulling";case k.PUSHING:return"pushing";case k.CONFLICTS:return"conflicts";case k.SYNCED:return"synced";case k.ERROR:return"error";case k.WATCHING:return"tracking changes";case k.RESOLVING:return"resolving";case k.NOT_SYNCED:return"not synced";case k.INITIALIZED:return"initialized";case k.SETTING_UP:return"setup required";default:return"unknown"}}c(vi,"getStatusDisplay");function Ei(r){switch(r){case k.PULLING:return"yellow";case k.PUSHING:return"yellow";case k.CONFLICTS:return"red";case k.SYNCED:return"green";case k.ERROR:return"red";case k.WATCHING:return"green";case k.RESOLVING:return"yellow";case k.NOT_SYNCED:return"grey";case k.SETTING_UP:return"yellow";default:return"grey"}}c(Ei,"getStatusColor");function Ti(){const r=go(),e=Ge(!0),{exit:t,state:n}=H(),[o,i]=D(null),s=o??(n===k.SETTING_UP?"setup":"main");ae(l=>{s==="main"&&(l==="w"&&i("workspace-selection"),l==="a"&&i("add-mcp-server"),l==="o"&&n===k.INITIALIZED&&a(),l==="s"&&i("setup"))});async function a(){try{const l=await Gt(r),d=rt(`/w/${l}`),h=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";pr(`${h} "${d}"`)}catch(l){console.error("Failed to open workspace:",l),t()}}return c(a,"handleOpenWorkspace"),he(()=>(e.current=!0,()=>{e.current=!1}),[]),s==="workspace-selection"?u(an,{onExit:c(()=>i(null),"onExit")}):s==="add-mcp-server"?u(di,{onExit:c(()=>i(null),"onExit"),onComplete:c(()=>i(null),"onComplete")}):s==="setup"?u(cn,{onComplete:c(()=>i(null),"onComplete")},Date.now()):u(fi,{children:b(g,{flexDirection:"column",children:[u(g,{flexGrow:1,children:u(pi,{})}),u(bi,{}),u(g,{paddingLeft:2,children:u(y,{color:"grey",children:"[s: (re-)setup]"})})]})})}c(Ti,"Main");const xi=c(()=>[C.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),C.yellow("\u2502 \u26A0\uFE0F EXPERIMENTAL FEATURE WARNING \u2502"),C.yellow("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),C.yellow("\u2502 Real-time agent mode is experimental and subject to changes. \u2502"),C.yellow("\u2502 Use in production environments is not recommended. \u2502"),C.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),""].join(`
20
+ `),"createExperimentalWarning$1");function Ii(r,e){r.command("sync").description("\u26A0\uFE0F EXPERIMENTAL: Sync workspace data in real-time - This feature is experimental and subject to changes. Use in production environments is not recommended.").option("--watch","Watch for changes and sync automatically",!1).option("--rps <number>","Maximum requests per second (default: 80)",t=>parseInt(t,10)).addHelpText("after",["","Examples:"," membrane sync --watch # Start real-time sync with watch mode"," membrane sync --watch --rps 5 # Limit to 5 requests per second",""].join(`
21
+ `)).action(async t=>{if(t.watch||(console.error("Error: The sync command requires the --watch flag"),console.error("Usage: membrane sync --watch"),process.exit(1)),t.rps!==void 0){const n=t.rps;!isNaN(n)&&n>0&&n<=1e3?I.init({maxRequestsPerSecond:n}):(f.error(`Invalid RPS value: ${n}. Must be between 1 and 1000.`),process.exit(1))}console.warn(xi()),He(se.createElement(mt,{cwd:process.cwd(),membraneCLIService:e,children:se.createElement(Ti)}))})}c(Ii,"setupSyncCommand");class $i{static{c(this,"BaseRunner")}constructor(e={}){if(this.options=e,this.fsPaths=ot(),e&&typeof e=="object"){const t=e;"client"in t&&t.client&&(this.client=t.client),"workspace"in t&&(this.workspace=t.workspace)}}client;workspace;fsPaths}const ki="claude-sonnet-4-20250514";class $t{static{c(this,"TestEnvironment")}client;connectionId;testsDir;testBasePath;options;llm;state={};constructor({connectionId:e,testsDir:t,testBasePath:n,client:o,options:i,llm:s}){this.client=o,this.connectionId=e,this.testsDir=t,this.testBasePath=n,this.llm=s,this.options=i}static async create({connectionId:e,testBasePath:t,options:n}){const o=Ce();if(!o)throw new Error("No configuration found. Please set MEMBRANE_WORKSPACE_KEY and MEMBRANE_WORKSPACE_SECRET environment variables, or run `membrane init` first.");if(!o.workspaceKey||!o.workspaceSecret)throw new Error("Missing workspace credentials");if(!o.anthropicApiKey)throw new Error("Anthropic API key not configured. Run `membrane init` to set up testing.");const i=new kt({token:await this.createMembraneToken(o),apiUri:o.apiUri}),s=new fr({apiKey:o.anthropicApiKey}),a={complete:c(async({prompt:l,maxTokens:d})=>{const h=await s.messages.create({model:ki,max_tokens:d,messages:[{role:"user",content:l}]});return h.content[0].type==="text"?h.content[0].text:""},"complete")};return new $t({client:i,options:n,connectionId:e,testsDir:"src/testing/tests",testBasePath:t,llm:a})}async run(e){this.state={};const t={};for(const n of e)await n.run(),Ye(t,n.getResult());this.writeResults(t)}async readYaml(e){const t=$.join(this.testsDir,this.testBasePath,this.connectionId,e);return it(t)}async writeYaml(e,t){const n=$.join(this.testsDir,this.testBasePath,this.connectionId,e);P.mkdirSync($.dirname(n),{recursive:!0}),P.writeFileSync(n,G.dump(t,{noRefs:!0}))}writeResults(e){const t=$.join(this.testsDir,this.testBasePath,this.connectionId);P.mkdirSync(t,{recursive:!0});const n=$.join(t,"test-results.yaml");P.writeFileSync(n,G.dump(e,{noRefs:!0})),console.debug(`[TestRunner] Results written to: ${n}`)}static async createMembraneToken(e){const t=e.testCustomerId||"test-customer",n={id:t,name:t},o={issuer:e.workspaceKey,expiresIn:7200,algorithm:"HS512"};return ze.sign(n,e.workspaceSecret,o)}}gr.interpolate=/{{([\s\S]+?)}}/g;function Et(r,e){if(typeof r=="string"){const t=mr(r),n={state:e,random:{number:c(()=>we.number.int(),"number"),alphaNumeric:c(i=>we.string.alphanumeric(i),"alphaNumeric")},faker:{company:{name:c(()=>we.company.name(),"name"),catchPhrase:c(()=>we.company.catchPhrase(),"catchPhrase")},internet:{email:c(()=>we.internet.email(),"email")}},entries:e["journal-entries"],orders:e["purchase-orders"]||e["sales-orders"],bills:e["vendor-bills"]},o=t(n);return r.includes("{{")&&r.includes("}}")&&(console.debug(`[TEMPLATE] Input: ${r}`),console.debug(`[TEMPLATE] Output: ${o}`)),o}return Array.isArray(r)?r.map(t=>Et(t,e)):typeof r=="object"&&r!==null?Object.fromEntries(Object.entries(r).map(([t,n])=>[t,Et(n,e)])):r}c(Et,"processNode");function Ri(r,e){return Et(r,e)}c(Ri,"handleTemplate");class Pi{static{c(this,"BaseTestSuite")}result;environment;constructor({environment:e}){this.environment=e,this.result={}}async run(){}getResult(){return this.result}async runTest(e){console.debug(`${C.bold.cyan("[start]")} ${C.yellow(e.path)}`);let t=!1,n=!1,o={},i={},s;for(;!t;)try{i=await e.readTestCase(),i||(i=await e.generateConfig(),await this.environment.writeYaml(e.getTestCasePath(),i),console.debug(`${C.bold.yellow("[initialized]")} ${C.yellow(e.path)}`)),s=Ri(i,this.environment.state),await e.run(s),console.debug(`${C.bold.green("[success]")} ${C.yellow(e.path)}`),t=!0,o=e.getResult(),Ue(this.result,e.path,o)}catch(l){if(console.error(`${C.bold.red("[error]")} ${C.yellow(e.path)}: ${l}`),this.environment.options.fix&&!n){n=!0;try{await e.fix(l);continue}catch(d){console.error(`${C.bold.red("[fix fail]")} ${C.yellow(e.path)}: ${d}`)}}Ue(this.result,e.path,{error:J(l)}),t=!0,o={error:J(l)}}const a={...s,result:o};await this.environment.writeYaml(e.getTestCasePath(),a)}async runTestSuite(e){await e.run(),Ye(this.result,e.getResult())}}class oe{static{c(this,"BaseTester")}environment;level;logs;assertions;resultsLocator;path;constructor({environment:e,path:t}){this.environment=e,this.logs=[],this.assertions=[],this.path=t,this.level=0,this.resultsLocator=""}async fix(e){const t=await this.readTestCase();if(!t)throw new Error(`No config found for test ${this.path}`);const n=await this.fixTestCase({config:t,error:e});console.debug(C.bold.yellow("[auto-fix]"),this.path),await this.environment.writeYaml(this.getTestCasePath(),n)}async readTestCase(){const e=this.getTestCasePath();return this.environment.readYaml(e)}async generateConfig(){return{}}async fixTestCase(e){throw new Error(`Auto-fix is not implemented for test ${this.path}`)}getResult(){return{logs:this.logs,assertions:this.assertions}}async assert(e,t,n){try{const o=await e();o?(this.logMsg(`\u2705 ${t}`),this.assertions.push({message:t,result:o})):(this.logMsg(`\u274C ${t}`),this.assertions.push({message:t,result:!1,details:n}))}catch(o){this.assertions.push({message:t,result:!1,details:J(o)}),this.logMsg(`\u274C ${t}: ${o.message}`)}}logMsg(e){console.debug(`${" ".repeat(this.level*2)}${e}`)}getTestCasePath(){return`${this.path}.test.yml`}}function Tt(r,e){const t={};for(const n in e){if(!(n in r)){t[n]=e[n];continue}const o=r[n],i=e[n];if(o&&i&&typeof o=="object"&&typeof i=="object"){if(Array.isArray(o)&&Array.isArray(i)){const s=i.filter(a=>!o.some(l=>{if(typeof l=="object"&&typeof a=="object"&&l!==null&&a!==null&&!Array.isArray(l)&&!Array.isArray(a)){for(const d in a)if(!(d in l)||!xt(l[d],a[d]))return!1;return!0}else return JSON.stringify(l)===JSON.stringify(a)}));s.length>0&&(t[n]=s)}else if(!Array.isArray(o)&&!Array.isArray(i)){const s=Tt(o,i);s!==null&&(t[n]=s)}else t[n]=i;continue}xt(o,i)||(t[n]=i)}return Object.keys(t).length===0?null:t}c(Tt,"getNotMatchingSubFields");function xt(r,e){if(r==e||r?.toString?.()===e?.toString?.())return!0;const t=new Date(r),n=new Date(e);return!isNaN(t.getTime())&&!isNaN(n.getTime())?t.getTime()===n.getTime():!1}c(xt,"softCompare");class Ai extends oe{static{c(this,"DataCollectionCreateTester")}dataCollectionKey;dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/create`}),this.dataCollectionKey=t,this.dataCollection=n}async run(e){const t=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).create(e.input);await this.assert(()=>!!t.id,"Returned ID of a created record"),t.id&&(this.environment.state[this.dataCollectionKey]={createdRecordId:t.id});const n=Ke(this.dataCollection);if(this.dataCollection.findById){const i=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).findById({id:t.id});await this.assert(()=>!!i.record,"Record is returned from findById"),i.record&&(this.environment.state[this.dataCollectionKey]={createdRecordId:t.id,createdRecord:i.record.fields});const s=Pt(n),a=Ie(e.input.fields,s,{skipUnknownFields:!0}),l=Ie(i.record.fields,s),d=Tt(l,a);await this.assert(()=>!d,"Returned fields match created fields",{difference:d,sentFields:a,receivedFields:l})}const o=Bn(n??{});if(o.length>0){const i={};o.forEach(a=>{const l=_n(e.input.fields,a);typeof l<"u"&&Ue(i,a,l)});const s=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).create({fields:i});await this.assert(()=>!!s.id,"Record can be created with schema-defined required fields only")}}async generateConfig(){const e=Ke(this.dataCollection);if(!e?.properties)throw new Error("No fields schema found for data collection");return{input:{fields:await this.generateFieldsWithLLM(e)}}}async fixTestCase({config:e,error:t}){const n=J(t),o=Ke(this.dataCollection),i=await this.getExampleRecordsForSchema(o),s=`I'm trying to create a data record in a data collection with the following fields schema:
22
22
 
23
23
  ${JSON.stringify(o,null,2)}
24
24
 
@@ -42,7 +42,7 @@ Format your response as a JSON object with two fields:
42
42
  "fields": { ... fixed fields ... }
43
43
  }.
44
44
 
45
- Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,a=await this.environment.llm.complete({prompt:s,maxTokens:1e4}),l=JSON.parse(a.trim());return console.warn(w.bold.yellow("[auto-fix]"),`${this.path}:`,l.explanation),{input:{fields:l.fields}}}async generateFieldsWithLLM(e){const t=await this.getExampleRecordsForSchema(e),n=`Generate a valid JSON object that matches this JSONSchema. Return only the JSON object, no other text.
45
+ Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,a=await this.environment.llm.complete({prompt:s,maxTokens:1e4}),l=JSON.parse(a.trim());return console.warn(C.bold.yellow("[auto-fix]"),`${this.path}:`,l.explanation),{input:{fields:l.fields}}}async generateFieldsWithLLM(e){const t=await this.getExampleRecordsForSchema(e),n=`Generate a valid JSON object that matches this JSONSchema. Return only the JSON object, no other text.
46
46
 
47
47
  ${this.getExampleRecordsPrompt(t)}
48
48
 
@@ -58,7 +58,7 @@ ${JSON.stringify(o,null,2)}`).join(`
58
58
 
59
59
  `)}.
60
60
 
61
- If you don't have an example for a given collection, leave the field empty instead of coming up with a fake record id.`}async findReferenceCollections(e){const t=new Set,n=[];return kt(e,o=>{if(o.referenceCollection){const i=o.referenceCollection.key,s=o.referenceCollection.parameters,a=`${i}:${JSON.stringify(s||{})}`;t.has(a)||(t.add(a),n.push({key:i,parameters:s}))}return o}),n}async fetchExampleRecords(e){return(await this.environment.client.connection(this.environment.connectionId).dataCollection(e.key).list({parameters:e.parameters})).records.map(n=>({id:n.id,fields:n.fields??{}}))}async getExampleRecordsForSchema(e){const t=await this.findReferenceCollections(e),n={};for(const o of t){const i=Rt(o);n[i]=await this.fetchExampleRecords(o)}return n}}class Ti extends oe{static{c(this,"DataCollectionDeleteTester")}dataCollectionKey;dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/delete`}),this.dataCollectionKey=t,this.dataCollection=n}async run(e){const t=this.environment.state[this.dataCollectionKey]?.createdRecordId||e?.input?.id;if(!t)throw new Error(`No ID found in state or config for ${this.dataCollectionKey} delete`);try{await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).delete({id:t})}catch(n){throw n}if(this.dataCollection.findById)try{await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).findById({id:t})}catch(n){if(n?.data?.data?.response?.status===404){await this.assert(()=>!0,"Record is not found after deletion");return}throw n}else await this.assert(()=>!0,"No findById capability, skipping verification")}async generateConfig(){let e=this.environment.state[this.dataCollectionKey]?.createdRecordId;if(!e){if(!this.dataCollection.list)throw new Error(`Can't find a record to test delete operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`);const t=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).list({});if(!t?.records?.length)throw new Error(`No records found to test delete for ${this.dataCollectionKey}`);e=t.records[0].id}return{input:{id:e}}}async fixTestCase({config:e,error:t}){const n=J(t),o=`I'm trying to delete a record from a data collection.
61
+ If you don't have an example for a given collection, leave the field empty instead of coming up with a fake record id.`}async findReferenceCollections(e){const t=new Set,n=[];return At(e,o=>{if(o.referenceCollection){const i=o.referenceCollection.key,s=o.referenceCollection.parameters,a=`${i}:${JSON.stringify(s||{})}`;t.has(a)||(t.add(a),n.push({key:i,parameters:s}))}return o}),n}async fetchExampleRecords(e){return(await this.environment.client.connection(this.environment.connectionId).dataCollection(e.key).list({parameters:e.parameters})).records.map(n=>({id:n.id,fields:n.fields??{}}))}async getExampleRecordsForSchema(e){const t=await this.findReferenceCollections(e),n={};for(const o of t){const i=Dt(o);n[i]=await this.fetchExampleRecords(o)}return n}}class Di extends oe{static{c(this,"DataCollectionDeleteTester")}dataCollectionKey;dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/delete`}),this.dataCollectionKey=t,this.dataCollection=n}async run(e){const t=this.environment.state[this.dataCollectionKey]?.createdRecordId||e?.input?.id;if(!t)throw new Error(`No ID found in state or config for ${this.dataCollectionKey} delete`);try{await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).delete({id:t})}catch(n){throw n}if(this.dataCollection.findById)try{await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).findById({id:t})}catch(n){if(n?.data?.data?.response?.status===404){await this.assert(()=>!0,"Record is not found after deletion");return}throw n}else await this.assert(()=>!0,"No findById capability, skipping verification")}async generateConfig(){let e=this.environment.state[this.dataCollectionKey]?.createdRecordId;if(!e){if(!this.dataCollection.list)throw new Error(`Can't find a record to test delete operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`);const t=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).list({});if(!t?.records?.length)throw new Error(`No records found to test delete for ${this.dataCollectionKey}`);e=t.records[0].id}return{input:{id:e}}}async fixTestCase({config:e,error:t}){const n=J(t),o=`I'm trying to delete a record from a data collection.
62
62
 
63
63
  I tried to delete a record with this ID:
64
64
 
@@ -78,7 +78,7 @@ Format your response as a JSON object with two fields:
78
78
  "id": "fixed id"
79
79
  }.
80
80
 
81
- Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,i=await this.environment.llm.complete({prompt:o,maxTokens:1e3}),s=JSON.parse(i.trim());return console.warn(w.bold.yellow("[auto-fix]"),`${this.path}:`,s.explanation),{input:{id:s.id}}}}class xi extends oe{static{c(this,"DataCollectionFindByIdTester")}dataCollectionKey;dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/find-by-id`}),this.dataCollectionKey=t,this.dataCollection=n}async run(e){const t=this.environment.state[this.dataCollectionKey]?.createdRecordId||e?.input?.id;if(!t)throw new Error(`No ID found in state or config for ${this.dataCollectionKey} find-by-id`);const n=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).findById({id:t});await this.assert(()=>!!n.record,"Record is returned from findById"),await this.assert(()=>n.record.id===t,"Returned record ID matches requested ID")}async generateConfig(){let e=this.environment.state[this.dataCollectionKey]?.createdRecordId;if(!e){if(!this.dataCollection.list)throw new Error(`Can't find a record to test findById operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`);const t=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).list({});if(!t?.records?.length)throw new Error(`No records found to test findById for ${this.dataCollectionKey}`);e=t.records[0].id}return{input:{id:e}}}async fixTestCase({config:e,error:t}){const n=J(t),o=`I'm trying to find a record by ID in a data collection.
81
+ Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,i=await this.environment.llm.complete({prompt:o,maxTokens:1e3}),s=JSON.parse(i.trim());return console.warn(C.bold.yellow("[auto-fix]"),`${this.path}:`,s.explanation),{input:{id:s.id}}}}class Oi extends oe{static{c(this,"DataCollectionFindByIdTester")}dataCollectionKey;dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/find-by-id`}),this.dataCollectionKey=t,this.dataCollection=n}async run(e){const t=this.environment.state[this.dataCollectionKey]?.createdRecordId||e?.input?.id;if(!t)throw new Error(`No ID found in state or config for ${this.dataCollectionKey} find-by-id`);const n=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).findById({id:t});await this.assert(()=>!!n.record,"Record is returned from findById"),await this.assert(()=>n.record.id===t,"Returned record ID matches requested ID")}async generateConfig(){let e=this.environment.state[this.dataCollectionKey]?.createdRecordId;if(!e){if(!this.dataCollection.list)throw new Error(`Can't find a record to test findById operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`);const t=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).list({});if(!t?.records?.length)throw new Error(`No records found to test findById for ${this.dataCollectionKey}`);e=t.records[0].id}return{input:{id:e}}}async fixTestCase({config:e,error:t}){const n=J(t),o=`I'm trying to find a record by ID in a data collection.
82
82
 
83
83
  I tried to find a record with this ID:
84
84
 
@@ -98,7 +98,7 @@ Format your response as a JSON object with two fields:
98
98
  "id": "fixed id"
99
99
  }.
100
100
 
101
- Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,i=await this.environment.llm.complete({prompt:o,maxTokens:1e3}),s=JSON.parse(i.trim());return console.warn(w.bold.yellow("[auto-fix]"),`${this.path}:`,s.explanation),{input:{id:s.id}}}}class Ii extends oe{static{c(this,"DataCollectionListTester")}dataCollectionKey;constructor({environment:e,dataCollectionKey:t}){super({environment:e,path:`data/${t}/list`}),this.dataCollectionKey=t}async run(e){const t=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).list(e.input);if(await this.assert(()=>Array.isArray(t.records),"Response has records field as array"),e.input.sort){const{field:n,direction:o}=e.input.sort,i=t.records;if(i.length>1)for(let s=1;s<i.length;s++){const a=i[s-1].fields?.[n],l=i[s].fields?.[n];a==null||l==null||(o==="asc"?await this.assert(()=>a<=l,`Records are sorted by ${n} in ascending order`):await this.assert(()=>a>=l,`Records are sorted by ${n} in descending order`))}}}async generateConfig(){return{input:{}}}async fixTestCase({config:e,error:t}){const n=J(t),o=`I'm trying to list records from a data collection.
101
+ Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,i=await this.environment.llm.complete({prompt:o,maxTokens:1e3}),s=JSON.parse(i.trim());return console.warn(C.bold.yellow("[auto-fix]"),`${this.path}:`,s.explanation),{input:{id:s.id}}}}class Ni extends oe{static{c(this,"DataCollectionListTester")}dataCollectionKey;constructor({environment:e,dataCollectionKey:t}){super({environment:e,path:`data/${t}/list`}),this.dataCollectionKey=t}async run(e){const t=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).list(e.input);if(await this.assert(()=>Array.isArray(t.records),"Response has records field as array"),e.input.sort){const{field:n,direction:o}=e.input.sort,i=t.records;if(i.length>1)for(let s=1;s<i.length;s++){const a=i[s-1].fields?.[n],l=i[s].fields?.[n];a==null||l==null||(o==="asc"?await this.assert(()=>a<=l,`Records are sorted by ${n} in ascending order`):await this.assert(()=>a>=l,`Records are sorted by ${n} in descending order`))}}}async generateConfig(){return{input:{}}}async fixTestCase({config:e,error:t}){const n=J(t),o=`I'm trying to list records from a data collection.
102
102
 
103
103
  I tried to list records with these parameters:
104
104
 
@@ -118,7 +118,7 @@ Format your response as a JSON object with two fields:
118
118
  "input": { ... fixed parameters ... }
119
119
  }.
120
120
 
121
- Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,i=await this.environment.llm.complete({prompt:o,maxTokens:1e3}),s=JSON.parse(i.trim());return console.warn(w.bold.yellow("[auto-fix]"),`${this.path}:`,s.explanation),{input:s.input}}}class $i extends oe{static{c(this,"DataCollectionMatchTester")}dataCollectionKey;dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/match`}),this.dataCollectionKey=t,this.dataCollection=n}async run(e){const t=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).match(e.input);await this.assert(()=>!!t.record,"Response contains a record");const n=t.record,i=(await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).findById({id:n.id})).record;for(const[s,a]of Object.entries(e.input.query)){const l=i.fields?.[s];await this.assert(()=>vt(l,a),`Record field ${s} matches input value - expected ${JSON.stringify(a)} got ${JSON.stringify(l)}`)}}async generateConfig(){if(!this.dataCollection.list)throw new Error(`Can't find a record to test match operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`);const e=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).list({});if(!e?.records?.length)throw new Error("No records found to test match");const t=e.records[0];if(!t?.fields)throw new Error("First record has no fields to match against");const n={},o=t.fields||{},i=Object.entries(o).filter(([s,a])=>s!=="links"&&a!=null&&a!=="").slice(0,1);if(i.length===0)throw new Error("No usable fields found in record for matching");for(const[s,a]of i)n[s]=a;return{input:{query:n}}}async fixTestCase({config:e,error:t}){const n=J(t),o=`I'm trying to match a record in a data collection.
121
+ Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,i=await this.environment.llm.complete({prompt:o,maxTokens:1e3}),s=JSON.parse(i.trim());return console.warn(C.bold.yellow("[auto-fix]"),`${this.path}:`,s.explanation),{input:s.input}}}class Mi extends oe{static{c(this,"DataCollectionMatchTester")}dataCollectionKey;dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/match`}),this.dataCollectionKey=t,this.dataCollection=n}async run(e){const t=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).match(e.input);await this.assert(()=>!!t.record,"Response contains a record");const n=t.record,i=(await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).findById({id:n.id})).record;for(const[s,a]of Object.entries(e.input.query)){const l=i.fields?.[s];await this.assert(()=>xt(l,a),`Record field ${s} matches input value - expected ${JSON.stringify(a)} got ${JSON.stringify(l)}`)}}async generateConfig(){if(!this.dataCollection.list)throw new Error(`Can't find a record to test match operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`);const e=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).list({});if(!e?.records?.length)throw new Error("No records found to test match");const t=e.records[0];if(!t?.fields)throw new Error("First record has no fields to match against");const n={},o=t.fields||{},i=Object.entries(o).filter(([s,a])=>s!=="links"&&a!=null&&a!=="").slice(0,1);if(i.length===0)throw new Error("No usable fields found in record for matching");for(const[s,a]of i)n[s]=a;return{input:{query:n}}}async fixTestCase({config:e,error:t}){const n=J(t),o=`I'm trying to match a record in a data collection.
122
122
 
123
123
  I tried to match a record with this query:
124
124
 
@@ -138,7 +138,7 @@ Format your response as a JSON object with two fields:
138
138
  "query": { ... fixed query ... }
139
139
  }.
140
140
 
141
- Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,i=await this.environment.llm.complete({prompt:o,maxTokens:1e3}),s=JSON.parse(i.trim());return console.warn(w.bold.yellow("[auto-fix]"),`${this.path}:`,s.explanation),{input:{query:s.query}}}}class ki extends oe{static{c(this,"DataCollectionSearchTester")}dataCollectionKey;dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/search`}),this.dataCollectionKey=t,this.dataCollection=n}async run(e){const t=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).search(e.input);await this.assert(()=>Array.isArray(t.records),"Response has records field as array");const n=t.records.some(o=>o.id===e.expectedRecordId);n||console.debug(w.yellow(`Search query "${e.input.query}" did not return expected record`)),await this.assert(()=>n,"Search returns expected record")}async generateConfig(){if(!this.dataCollection.list)throw new Error(`Can't find a record to test search operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`);const e=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).list({});if(!e.records.length)throw new Error("No records found to test search");const t=e.records[0],n=await this.getSearchQueryWithLLM(t.fields||{});if(!n)throw new Error("Unable to generate search query. LLM could not identify a suitable field value from the record to use as the search query.");return{input:{query:n},expectedRecordId:t.id}}async getSearchQueryWithLLM(e){const t=`You are given the fields of a record from a data collection. Identify the BEST single field value that a user is MOST likely to type when searching for this record (e.g. name, title, email, external id). Ignore null, empty strings, technical IDs, HTML, and timestamps unless they are obviously human-searchable. Make sure the field value is as unique as possible for this record. RETURN ONLY the field value as a plain string. No additional text, no JSON, no quotes.
141
+ Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,i=await this.environment.llm.complete({prompt:o,maxTokens:1e3}),s=JSON.parse(i.trim());return console.warn(C.bold.yellow("[auto-fix]"),`${this.path}:`,s.explanation),{input:{query:s.query}}}}class Fi extends oe{static{c(this,"DataCollectionSearchTester")}dataCollectionKey;dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/search`}),this.dataCollectionKey=t,this.dataCollection=n}async run(e){const t=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).search(e.input);await this.assert(()=>Array.isArray(t.records),"Response has records field as array");const n=t.records.some(o=>o.id===e.expectedRecordId);n||console.debug(C.yellow(`Search query "${e.input.query}" did not return expected record`)),await this.assert(()=>n,"Search returns expected record")}async generateConfig(){if(!this.dataCollection.list)throw new Error(`Can't find a record to test search operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`);const e=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).list({});if(!e.records.length)throw new Error("No records found to test search");const t=e.records[0],n=await this.getSearchQueryWithLLM(t.fields||{});if(!n)throw new Error("Unable to generate search query. LLM could not identify a suitable field value from the record to use as the search query.");return{input:{query:n},expectedRecordId:t.id}}async getSearchQueryWithLLM(e){const t=`You are given the fields of a record from a data collection. Identify the BEST single field value that a user is MOST likely to type when searching for this record (e.g. name, title, email, external id). Ignore null, empty strings, technical IDs, HTML, and timestamps unless they are obviously human-searchable. Make sure the field value is as unique as possible for this record. RETURN ONLY the field value as a plain string. No additional text, no JSON, no quotes.
142
142
 
143
143
  Record fields:
144
144
  ${JSON.stringify(e,null,2)}
@@ -163,7 +163,7 @@ Format your response as a JSON object with two fields:
163
163
  "input": { ... fixed parameters ... }
164
164
  }.
165
165
 
166
- Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,i=await this.environment.llm.complete({prompt:o,maxTokens:1e3}),s=JSON.parse(i.trim());return console.warn(w.bold.yellow("[auto-fix]"),`${this.path}:`,s.explanation),{input:s.input,expectedRecordId:e.expectedRecordId}}}class Ri extends oe{static{c(this,"DataCollectionSpecTester")}dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/spec`}),this.dataCollection=n}async run(){const e=Object.keys(this.dataCollection.fieldsSchema||{}).length;await this.assert(()=>e>0,"Fields schema has field definitions")}}class Pi extends oe{static{c(this,"DataCollectionUpdateTester")}dataCollectionKey;dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/update`}),this.dataCollectionKey=t,this.dataCollection=n}async run(e){const t=this.environment.state[this.dataCollectionKey]?.createdRecordId||e?.input?.id;if(!t)throw new Error(`No ID found in state or config for ${this.dataCollectionKey} update`);const n=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).update({...e.input,id:t});if(await this.assert(()=>!!n.id,"Returned ID of updated record"),this.environment.state[this.dataCollectionKey]||(this.environment.state[this.dataCollectionKey]={}),this.environment.state[this.dataCollectionKey].createdRecordId=n.id,this.dataCollection.findById){const o=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).findById({id:n.id});await this.assert(()=>!!o.record,"Record is returned from findById");const i=Ue(this.dataCollection),s=$t(i),a=xe(e.input.fields,s,{skipUnknownFields:!0}),l=xe(o.record.fields,s),d=bt(l,a);await this.assert(()=>!d,"Returned fields match updated fields",{difference:d,sentFields:a,receivedFields:l})}}async generateConfig(){let e=this.environment.state[this.dataCollectionKey]?.createdRecordId;if(!e){if(!this.dataCollection.list)throw new Error(`Can't find a record to test update operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`);const o=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).list({});if(!o?.records?.length)throw new Error(`No records found to test update for ${this.dataCollectionKey}`);e=o.records[0].id}const t=Ue(this.dataCollection);if(!t?.properties)throw new Error("No fields schema found for data collection");const n=await this.generateFieldsWithLLM(t);return{input:{id:e,fields:n}}}async fixTestCase({config:e,error:t}){const n=J(t),o=Ue(this.dataCollection),i=await this.getExampleRecordsForSchema(o),s=`I'm trying to update a data record in a data collection with the following fields schema:
166
+ Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,i=await this.environment.llm.complete({prompt:o,maxTokens:1e3}),s=JSON.parse(i.trim());return console.warn(C.bold.yellow("[auto-fix]"),`${this.path}:`,s.explanation),{input:s.input,expectedRecordId:e.expectedRecordId}}}class Li extends oe{static{c(this,"DataCollectionSpecTester")}dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/spec`}),this.dataCollection=n}async run(){const e=Object.keys(this.dataCollection.fieldsSchema||{}).length;await this.assert(()=>e>0,"Fields schema has field definitions")}}class ji extends oe{static{c(this,"DataCollectionUpdateTester")}dataCollectionKey;dataCollection;constructor({environment:e,dataCollectionKey:t,dataCollection:n}){super({environment:e,path:`data/${t}/update`}),this.dataCollectionKey=t,this.dataCollection=n}async run(e){const t=this.environment.state[this.dataCollectionKey]?.createdRecordId||e?.input?.id;if(!t)throw new Error(`No ID found in state or config for ${this.dataCollectionKey} update`);const n=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).update({...e.input,id:t});if(await this.assert(()=>!!n.id,"Returned ID of updated record"),this.environment.state[this.dataCollectionKey]||(this.environment.state[this.dataCollectionKey]={}),this.environment.state[this.dataCollectionKey].createdRecordId=n.id,this.dataCollection.findById){const o=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).findById({id:n.id});await this.assert(()=>!!o.record,"Record is returned from findById");const i=qe(this.dataCollection),s=Pt(i),a=Ie(e.input.fields,s,{skipUnknownFields:!0}),l=Ie(o.record.fields,s),d=Tt(l,a);await this.assert(()=>!d,"Returned fields match updated fields",{difference:d,sentFields:a,receivedFields:l})}}async generateConfig(){let e=this.environment.state[this.dataCollectionKey]?.createdRecordId;if(!e){if(!this.dataCollection.list)throw new Error(`Can't find a record to test update operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`);const o=await this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).list({});if(!o?.records?.length)throw new Error(`No records found to test update for ${this.dataCollectionKey}`);e=o.records[0].id}const t=qe(this.dataCollection);if(!t?.properties)throw new Error("No fields schema found for data collection");const n=await this.generateFieldsWithLLM(t);return{input:{id:e,fields:n}}}async fixTestCase({config:e,error:t}){const n=J(t),o=qe(this.dataCollection),i=await this.getExampleRecordsForSchema(o),s=`I'm trying to update a data record in a data collection with the following fields schema:
167
167
 
168
168
  ${JSON.stringify(o,null,2)}
169
169
 
@@ -187,7 +187,7 @@ Format your response as a JSON object with two fields:
187
187
  "fields": { ... fixed fields ... }
188
188
  }.
189
189
 
190
- Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,a=await this.environment.llm.complete({prompt:s,maxTokens:1e4}),l=JSON.parse(a.trim());return console.warn(w.bold.yellow("[auto-fix]"),`${this.path}:`,l.explanation),{input:{id:e.input.id,fields:l.fields}}}async generateFieldsWithLLM(e){const t=await this.getExampleRecordsForSchema(e),n=`Generate a valid JSON object that matches this JSONSchema. Return only the JSON object, no other text.
190
+ Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`,a=await this.environment.llm.complete({prompt:s,maxTokens:1e4}),l=JSON.parse(a.trim());return console.warn(C.bold.yellow("[auto-fix]"),`${this.path}:`,l.explanation),{input:{id:e.input.id,fields:l.fields}}}async generateFieldsWithLLM(e){const t=await this.getExampleRecordsForSchema(e),n=`Generate a valid JSON object that matches this JSONSchema. Return only the JSON object, no other text.
191
191
 
192
192
  ${this.getExampleRecordsPrompt(t)}
193
193
 
@@ -203,9 +203,9 @@ ${JSON.stringify(o,null,2)}`).join(`
203
203
 
204
204
  `)}.
205
205
 
206
- If you don't have an example for a given collection, leave the field empty instead of coming up with a fake record id.`}async findReferenceCollections(e){const t=new Set,n=[];return kt(e,o=>{if(o.referenceCollection){const i=o.referenceCollection.key,s=o.referenceCollection.parameters,a=`${i}:${JSON.stringify(s||{})}`;t.has(a)||(t.add(a),n.push({key:i,parameters:s}))}return o}),n}async fetchExampleRecords(e){return(await this.environment.client.connection(this.environment.connectionId).dataCollection(e.key).list({parameters:e.parameters})).records.map(n=>({id:n.id,fields:n.fields||{}}))}async getExampleRecordsForSchema(e){const t=await this.findReferenceCollections(e),n={};for(const o of t){const i=Rt(o);n[i]=await this.fetchExampleRecords(o)}return n}}const Et={spec:{testerClass:Ri},create:{testerClass:Ei,operationKey:"create"},"find-by-id":{testerClass:xi,operationKey:"findById"},list:{testerClass:Ii,operationKey:"list"},match:{testerClass:$i,operationKey:"match"},search:{testerClass:ki,operationKey:"search"},update:{testerClass:Pi,operationKey:"update"},delete:{testerClass:Ti,operationKey:"delete"}};class Ai extends vi{static{c(this,"DataCollectionTestSuite")}dataCollectionKey;testMethod;constructor({environment:e,dataCollectionKey:t,testMethod:n}){super({environment:e}),this.dataCollectionKey=t,this.testMethod=n}async run(){const e=await this.fetchDataCollection(),t=this.testMethod?[this.createTester(this.testMethod,e)]:this.createAllAvailableTesters(e);R.info("\u{1F680} Running tests...");for(const n of t)await this.runTest(n);this.displayTestSummary(t.length)}async fetchDataCollection(){return this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).get()}isOperationAvailable(e,t){return t?!!e[t]:!0}createTester(e,t){const n=Et[e];if(!n)throw new Error(`Unknown test method "${e}". Available: ${this.getAvailableTestMethods(t).join(", ")}`);const o="operationKey"in n?n.operationKey:void 0;if(!this.isOperationAvailable(t,o))throw new Error(`${o} operation not available for data collection "${this.dataCollectionKey}"`);return this.instantiateTester(n,t)}createAllAvailableTesters(e){return Object.entries(Et).filter(([,t])=>{const n="operationKey"in t?t.operationKey:void 0;return this.isOperationAvailable(e,n)}).map(([,t])=>this.instantiateTester(t,e))}instantiateTester(e,t){const n={environment:this.environment,dataCollectionKey:this.dataCollectionKey,dataCollection:t};return new e.testerClass(n)}getAvailableTestMethods(e){return Object.entries(Et).filter(([,t])=>{const n="operationKey"in t?t.operationKey:void 0;return this.isOperationAvailable(e,n)}).map(([t])=>t)}displayTestSummary(e){R.info(`\u{1F4CA} ${e} test${e===1?"":"s"} executed`)}}class Di extends Ci{static{c(this,"TestRunner")}constructor(e){super(e)}async initialize(){R.debug("Initializing test runner",{prefix:"TestRunner"})}async run(){try{const{testPath:e,path:t,fix:n}=this.options,o=e.split("/");o.length<2&&(R.error("Invalid test path. Expected format: <type>/<name>[/additional/path][/method]"),process.exit(1));const[i,s,...a]=o;i!=="connectors"&&(R.error(`Test type "${i}" is not yet fully implemented. Currently only "connectors" is fully supported.`),R.error("Supported test types: connectors"),process.exit(1));const l=s,d=i,h=[...a,...t?t.split("/"):[]].join("/"),f=await Tt.create({connectionId:l,testBasePath:d,options:{fix:n}}),C=await f.client.get(`connections/${l}/data`),E=[],S=h?h.split("/"):[];if(S.length===0||S[0]==="data"){S[0]==="data"&&S.shift();let O,U;S.length>=1&&(U=S[0],S.length>=2&&S[1].trim()!==""&&(O=S[1]));for(const K of C){if(U&&U!==K.key)continue;const L=new Ai({environment:f,dataCollectionKey:K.key,testMethod:O});E.push(L)}}E.length===0&&(R.error(`No test suites found for path: ${e}${h?"/"+h:""}`),process.exit(1));const N={};for(const O of E){await O.run();const U=O.getResult();R.debug(`Suite ${O.constructor.name} result:`,{prefix:"TestRunner"}),He(N,U)}console.debug("[TestRunner] All results collected:",Object.keys(N)),f.writeResults(N)}catch(e){throw console.error("Error in TestRunner.run():",e),e}}}const Ne=c(()=>[w.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),w.yellow("\u2502 \u26A0\uFE0F EXPERIMENTAL FEATURE WARNING \u2502"),w.yellow("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),w.yellow("\u2502 The test command is experimental and subject to rapid changes. \u2502"),w.yellow("\u2502 Features, APIs, and file structures may change without notice. \u2502"),w.yellow("\u2502 Use in production environments is not recommended. \u2502"),w.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),""].join(`
207
- `),"createExperimentalWarning");function Oi(r){r.command("test").description("\u26A0\uFE0F EXPERIMENTAL: Test management commands - This feature is experimental and will be changing rapidly. Use at your own risk.").addHelpText("after",Ne()).action(async()=>{console.warn(Ne()),R.error("Please specify a subcommand. Use --help for available options."),process.exit(1)}).command("run").description("Run integration tests for various membrane components").argument("<testPath>",'Test path (e.g., "connectors/netsuite", "actions/create-contact", "connectors/hubspot/data/contacts", "connectors/netsuite/data/contacts/create")').option("-p, --path <path>","Additional path filter within the test scope").option("--fix","Enable auto-fix for test issues").addHelpText("after",["",w.bold("Examples:"),` ${w.gray("\u25B8")} ${w.cyan("membrane test run connectors/netsuite")} # Test all data collections for netsuite connector`,` ${w.gray("\u25B8")} ${w.cyan("membrane test run connectors/netsuite/data/contacts")} # Test specific data collection`,` ${w.gray("\u25B8")} ${w.cyan("membrane test run connectors/netsuite/data/contacts/create")} # Test specific method for data collection`,` ${w.gray("\u25B8")} ${w.cyan("membrane test run connectors/netsuite/data/contacts/delete")} # Test delete method for data collection`,` ${w.gray("\u25B8")} ${w.cyan("membrane test run actions/create-contact")} # Test specific action`,` ${w.gray("\u25B8")} ${w.cyan("membrane test run connectors/hubspot/events")} # Test events for hubspot`,` ${w.gray("\u25B8")} ${w.cyan("membrane test run connectors/salesforce --fix")} # Run tests with auto-fix enabled`,"",w.gray("For more information, visit:"),w.blue(" https://docs.getmembrane.com/docs/development-environment"),"",Ne()].join(`
208
- `)).action(async(t,n)=>{try{console.warn(Ne()),t||(R.error("Test path is required"),process.exit(1)),R.header(`Testing: ${t}`);const o=new Di({testPath:t,path:n.path,fix:n.fix});await o.initialize(),await o.run(),R.success("Tests completed")}catch(o){o instanceof Error&&(R.error(o.message),process.exit(1)),R.error("An unknown error occurred"),process.exit(1)}})}c(Oi,"setupTestCommand");const Ni=c(()=>{try{const r=An(import.meta.url),e=Rn(r),t=Me(e,"..","package.json");return JSON.parse(kn(t,"utf-8")).version}catch{return"1.0.0"}},"getPackageVersion"),Tn=Ni();function Mi(){process.on("SIGINT",()=>process.exit(130));const r=new Dn().name("membrane").description("Command-line interface for Membrane Agent").version(Tn,"-v, --version","Output the version number").option("--verbose","Enable verbose logging (shows debug messages)");r.configureHelp({sortSubcommands:!0,subcommandTerm:c(n=>w.cyan(n.name()),"subcommandTerm"),commandUsage:c(n=>n.name()==="membrane"?`${w.cyan(n.name())} ${w.gray("[options]")} ${w.cyan("[command]")}`:n.usage(),"commandUsage"),optionTerm:c(n=>{const o=n.flags;return`${w.gray("\u25B8")} ${w.cyan(o)}`},"optionTerm"),subcommandDescription:c(n=>w.gray(n.description()),"subcommandDescription"),optionDescription:c(n=>w.gray(n.description),"optionDescription"),commandDescription:c(n=>w.gray(n.description()),"commandDescription")}),r.addHelpText("beforeAll",`
209
- ${w.bold.cyan("Membrane Agent CLI")} ${w.gray(`v${Tn}`)}
206
+ If you don't have an example for a given collection, leave the field empty instead of coming up with a fake record id.`}async findReferenceCollections(e){const t=new Set,n=[];return At(e,o=>{if(o.referenceCollection){const i=o.referenceCollection.key,s=o.referenceCollection.parameters,a=`${i}:${JSON.stringify(s||{})}`;t.has(a)||(t.add(a),n.push({key:i,parameters:s}))}return o}),n}async fetchExampleRecords(e){return(await this.environment.client.connection(this.environment.connectionId).dataCollection(e.key).list({parameters:e.parameters})).records.map(n=>({id:n.id,fields:n.fields||{}}))}async getExampleRecordsForSchema(e){const t=await this.findReferenceCollections(e),n={};for(const o of t){const i=Dt(o);n[i]=await this.fetchExampleRecords(o)}return n}}const It={spec:{testerClass:Li},create:{testerClass:Ai,operationKey:"create"},"find-by-id":{testerClass:Oi,operationKey:"findById"},list:{testerClass:Ni,operationKey:"list"},match:{testerClass:Mi,operationKey:"match"},search:{testerClass:Fi,operationKey:"search"},update:{testerClass:ji,operationKey:"update"},delete:{testerClass:Di,operationKey:"delete"}};class Ui extends Pi{static{c(this,"DataCollectionTestSuite")}dataCollectionKey;testMethod;constructor({environment:e,dataCollectionKey:t,testMethod:n}){super({environment:e}),this.dataCollectionKey=t,this.testMethod=n}async run(){const e=await this.fetchDataCollection(),t=this.testMethod?[this.createTester(this.testMethod,e)]:this.createAllAvailableTesters(e);R.info("\u{1F680} Running tests...");for(const n of t)await this.runTest(n);this.displayTestSummary(t.length)}async fetchDataCollection(){return this.environment.client.connection(this.environment.connectionId).dataCollection(this.dataCollectionKey).get()}isOperationAvailable(e,t){return t?!!e[t]:!0}createTester(e,t){const n=It[e];if(!n)throw new Error(`Unknown test method "${e}". Available: ${this.getAvailableTestMethods(t).join(", ")}`);const o="operationKey"in n?n.operationKey:void 0;if(!this.isOperationAvailable(t,o))throw new Error(`${o} operation not available for data collection "${this.dataCollectionKey}"`);return this.instantiateTester(n,t)}createAllAvailableTesters(e){return Object.entries(It).filter(([,t])=>{const n="operationKey"in t?t.operationKey:void 0;return this.isOperationAvailable(e,n)}).map(([,t])=>this.instantiateTester(t,e))}instantiateTester(e,t){const n={environment:this.environment,dataCollectionKey:this.dataCollectionKey,dataCollection:t};return new e.testerClass(n)}getAvailableTestMethods(e){return Object.entries(It).filter(([,t])=>{const n="operationKey"in t?t.operationKey:void 0;return this.isOperationAvailable(e,n)}).map(([t])=>t)}displayTestSummary(e){R.info(`\u{1F4CA} ${e} test${e===1?"":"s"} executed`)}}class Ki extends $i{static{c(this,"TestRunner")}constructor(e){super(e)}async initialize(){R.debug("Initializing test runner",{prefix:"TestRunner"})}async run(){try{const{testPath:e,path:t,fix:n}=this.options,o=e.split("/");o.length<2&&(R.error("Invalid test path. Expected format: <type>/<name>[/additional/path][/method]"),process.exit(1));const[i,s,...a]=o;i!=="connectors"&&(R.error(`Test type "${i}" is not yet fully implemented. Currently only "connectors" is fully supported.`),R.error("Supported test types: connectors"),process.exit(1));const l=s,d=i,h=[...a,...t?t.split("/"):[]].join("/"),m=await $t.create({connectionId:l,testBasePath:d,options:{fix:n}}),w=await m.client.get(`connections/${l}/data`),T=[],S=h?h.split("/"):[];if(S.length===0||S[0]==="data"){S[0]==="data"&&S.shift();let N,K;S.length>=1&&(K=S[0],S.length>=2&&S[1].trim()!==""&&(N=S[1]));for(const q of w){if(K&&K!==q.key)continue;const L=new Ui({environment:m,dataCollectionKey:q.key,testMethod:N});T.push(L)}}T.length===0&&(R.error(`No test suites found for path: ${e}${h?"/"+h:""}`),process.exit(1));const O={};for(const N of T){await N.run();const K=N.getResult();R.debug(`Suite ${N.constructor.name} result:`,{prefix:"TestRunner"}),Ye(O,K)}console.debug("[TestRunner] All results collected:",Object.keys(O)),m.writeResults(O)}catch(e){throw console.error("Error in TestRunner.run():",e),e}}}const Me=c(()=>[C.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),C.yellow("\u2502 \u26A0\uFE0F EXPERIMENTAL FEATURE WARNING \u2502"),C.yellow("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),C.yellow("\u2502 The test command is experimental and subject to rapid changes. \u2502"),C.yellow("\u2502 Features, APIs, and file structures may change without notice. \u2502"),C.yellow("\u2502 Use in production environments is not recommended. \u2502"),C.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),""].join(`
207
+ `),"createExperimentalWarning");function qi(r){r.command("test").description("\u26A0\uFE0F EXPERIMENTAL: Test management commands - This feature is experimental and will be changing rapidly. Use at your own risk.").addHelpText("after",Me()).action(async()=>{console.warn(Me()),R.error("Please specify a subcommand. Use --help for available options."),process.exit(1)}).command("run").description("Run integration tests for various membrane components").argument("<testPath>",'Test path (e.g., "connectors/netsuite", "actions/create-contact", "connectors/hubspot/data/contacts", "connectors/netsuite/data/contacts/create")').option("-p, --path <path>","Additional path filter within the test scope").option("--fix","Enable auto-fix for test issues").addHelpText("after",["",C.bold("Examples:"),` ${C.gray("\u25B8")} ${C.cyan("membrane test run connectors/netsuite")} # Test all data collections for netsuite connector`,` ${C.gray("\u25B8")} ${C.cyan("membrane test run connectors/netsuite/data/contacts")} # Test specific data collection`,` ${C.gray("\u25B8")} ${C.cyan("membrane test run connectors/netsuite/data/contacts/create")} # Test specific method for data collection`,` ${C.gray("\u25B8")} ${C.cyan("membrane test run connectors/netsuite/data/contacts/delete")} # Test delete method for data collection`,` ${C.gray("\u25B8")} ${C.cyan("membrane test run actions/create-contact")} # Test specific action`,` ${C.gray("\u25B8")} ${C.cyan("membrane test run connectors/hubspot/events")} # Test events for hubspot`,` ${C.gray("\u25B8")} ${C.cyan("membrane test run connectors/salesforce --fix")} # Run tests with auto-fix enabled`,"",C.gray("For more information, visit:"),C.blue(" https://docs.getmembrane.com/docs/development-environment"),"",Me()].join(`
208
+ `)).action(async(t,n)=>{try{console.warn(Me()),t||(R.error("Test path is required"),process.exit(1)),R.header(`Testing: ${t}`);const o=new Ki({testPath:t,path:n.path,fix:n.fix});await o.initialize(),await o.run(),R.success("Tests completed")}catch(o){o instanceof Error&&(R.error(o.message),process.exit(1)),R.error("An unknown error occurred"),process.exit(1)}})}c(qi,"setupTestCommand");const Bi=c(()=>{try{const r=Dn(import.meta.url),e=Pn(r),t=Fe(e,"..","package.json");return JSON.parse(Rn(t,"utf-8")).version}catch{return"1.0.0"}},"getPackageVersion"),xn=Bi();function _i(){process.on("SIGINT",()=>process.exit(130));const r=new On().name("membrane").description("Command-line interface for Membrane Agent").version(xn,"-v, --version","Output the version number").option("--verbose","Enable verbose logging (shows debug messages)");r.configureHelp({sortSubcommands:!0,subcommandTerm:c(n=>C.cyan(n.name()),"subcommandTerm"),commandUsage:c(n=>n.name()==="membrane"?`${C.cyan(n.name())} ${C.gray("[options]")} ${C.cyan("[command]")}`:n.usage(),"commandUsage"),optionTerm:c(n=>{const o=n.flags;return`${C.gray("\u25B8")} ${C.cyan(o)}`},"optionTerm"),subcommandDescription:c(n=>C.gray(n.description()),"subcommandDescription"),optionDescription:c(n=>C.gray(n.description),"optionDescription"),commandDescription:c(n=>C.gray(n.description()),"commandDescription")}),r.addHelpText("beforeAll",`
209
+ ${C.bold.cyan("Membrane Agent CLI")} ${C.gray(`v${xn}`)}
210
210
 
211
- `);const e=new oo(De.Cli,process.cwd());Mo(r),Vo(r),ko(r),Oi(r),xo(r),wi(r,e),Co(r,e),br(r,e),mo(r,e),process.argv.length===2&&(r.outputHelp(),process.exit(0)),r.parse(),r.opts().verbose&&m.setVerboseMode(!0)}c(Mi,"runCLI"),Mi();
211
+ `);const e=new so(Oe.Cli,process.cwd());jo(r),Qo(r),Po(r),qi(r),$o(r),Ii(r,e),bo(r,e),Er(r,e),yo(r,e),process.argv.length===2&&(r.outputHelp(),process.exit(0)),r.parse(),r.opts().verbose&&f.setVerboseMode(!0)}c(_i,"runCLI"),_i();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@membranehq/cli",
3
- "version": "1.4.5",
3
+ "version": "1.4.7",
4
4
  "description": "",
5
5
  "keywords": [
6
6
  "cli",
@@ -30,7 +30,7 @@
30
30
  "@buildwithlayer/openapi-to-tools": "^1.3.3",
31
31
  "@faker-js/faker": "^9.8.0",
32
32
  "@inkjs/ui": "^2.0.0",
33
- "@membranehq/sdk": "^0.15.0",
33
+ "@membranehq/sdk": "^0.15.3",
34
34
  "@modelcontextprotocol/sdk": "^1.25.2",
35
35
  "@types/js-yaml": "^4.0.9",
36
36
  "@types/jsonwebtoken": "^9.0.10",