@beepflow/mcp 2026.9.0 → 2026.9.1

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 +2 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -43,10 +43,10 @@ function print() { __p += __j.call(arguments, '') }
43
43
  saved_at_ms integer not null,
44
44
  primary key (scope, resource, key)
45
45
  )
46
- `),this.database)}};function Ny(e){let t=e??"unknown-user";return SB.createHash("sha256").update(t).digest("hex")}function Fy(e,t,n){let r=e.replace(/^http/,"ws"),i=encodeURIComponent(t),o=encodeURIComponent(n);return`${r}/base/${i}/${o}`}var vp=class{websocket;sessionId=Ic();backendUrl;accessToken;channelListeners=new Map;disconnectListeners=new Set;ackWaiters=new Map;intentionallyClosed=!1;constructor(t,n){this.backendUrl=t,this.accessToken=n}async connect(t){this.intentionallyClosed=!1,this.sessionId=Ic();let n=Fy(this.backendUrl,this.accessToken,this.sessionId),r=new WebSocket(n,"echo");this.websocket=r,await new Promise((i,o)=>{let s=setTimeout(()=>o(new Error("websocket open timeout")),t);r.onopen=()=>{clearTimeout(s),i()},r.onerror=()=>{clearTimeout(s),o(new Error("websocket open failed"))}}),r.onmessage=i=>this.processMessage(i.data),r.onclose=()=>this.processClose(),r.onerror=()=>this.processClose()}getSessionId(){return this.sessionId}send(t,n){if(!this.websocket||this.websocket.readyState!==WebSocket.OPEN)throw new Error("gateway websocket not connected");this.websocket.send(`${t};${JSON.stringify(n)}`)}sendWithAck(t,n,r=15e3){let i=Ic(),o={...n,eventId:i};return new Promise(s=>{let c=setTimeout(()=>{this.ackWaiters.delete(i),s({ok:!1,reason:"timeout"})},r);this.ackWaiters.set(i,{resolve:s,timeout:c}),this.send(t,o)})}onChannel(t,n){return this.channelListeners.has(t)||this.channelListeners.set(t,new Set),this.channelListeners.get(t).add(n),()=>this.channelListeners.get(t)?.delete(n)}onDisconnected(t){return this.disconnectListeners.add(t),()=>this.disconnectListeners.delete(t)}waitForChannelEvent(t,n,r,i){return new Promise((o,s)=>{let c=setTimeout(()=>{h(),i?.removeEventListener("abort",f),s(new Error(`channel event timeout: ${t}`))},r),f=()=>{clearTimeout(c),h(),s(new Error(`channel event aborted: ${t}`))},h=this.onChannel(t,g=>{n(g)&&(clearTimeout(c),h(),i?.removeEventListener("abort",f),o(g))});i?.aborted?f():i?.addEventListener("abort",f,{once:!0})})}collectChannelEvents(t,n,r,i){return new Promise((o,s)=>{let c=[],f,h=setTimeout(()=>{_(),f&&clearTimeout(f),s(new Error(`channel event timeout: ${t}`))},r),g=()=>{clearTimeout(h),_(),o(c)},_=this.onChannel(t,S=>{n(S)&&(c.push(S),f&&clearTimeout(f),f=setTimeout(g,i))})})}close(){this.intentionallyClosed=!0,this.websocket?.close(),this.websocket=void 0;for(let t of this.ackWaiters.values())clearTimeout(t.timeout),t.resolve({ok:!1,reason:"closed"});this.ackWaiters.clear()}processMessage(t){let n=typeof t=="string"?t:"",r=n.indexOf(";");if(r===-1)return;let i=n.slice(0,r),o=n.slice(r+1),s;try{s=JSON.parse(o)}catch{return}if(i.startsWith("ack:")){this.resolveAck(i.slice(4),s);return}s=AB(s);let c=this.channelListeners.get(i);if(c)for(let f of c)f(s)}resolveAck(t,n){let r=this.ackWaiters.get(t);r&&(this.ackWaiters.delete(t),clearTimeout(r.timeout),r.resolve(n.value??{ok:!1}))}processClose(){if(!this.intentionallyClosed)for(let t of this.disconnectListeners)t()}};function AB(e){if(e.resource!=="connections")return e;switch(e.action){case"snapshot":return{...e,value:wB(e.value)};case"delta":return{...e,value:RB(e.value)};default:return e}}function wB(e){if(!q0(e))return e;let t={};for(let n in e)t[n]=My(e[n]);return t}function RB(e){return q0(e)?{...e,pre:Ly(e.pre),post:Ly(e.post)}:e}function Ly(e){return e===null?null:My(e)}function My(e){if(!q0(e))return e;let t={...e};return delete t.config,t}function q0(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}var z0="beepflow://resource-schemas/",wt={type:"number",description:"Nanoseconds since Unix epoch. Omit updatedAt on creates and manual edits unless preserving an existing value; replicated state updates it after accepted writes."},ie={type:"string"},ji={type:"number"},By={type:"integer"},Ii={type:"boolean"};var Sp={type:"object",additionalProperties:ie},W0={type:"object",additionalProperties:Ii},yp={type:"object",additionalProperties:{type:"object",additionalProperties:Ii,properties:{list:Ii,detail:Ii,create:Ii,edit:Ii,delete:Ii,authorize:Ii}}},xu=["boolean","string","number","datetime","map","binary","wildcard","list of boolean","list of string","list of number","list of datetime","list of map","list of binary","list of wildcard"],Uy=["ManualTick","AerospikeSet","ApacheKafkaTopic","MQTTTopic","KaggleFile","RabbitMQQueue","RabbitMQStream","QdrantCollection","BaseVectorCollection","BaseEventCollection","BaseLookupCollection","GorgiasTicketsView","GoogleDriveFile"],Ou={anyOf:[Ii,{type:"null"}]},DB=["Use resource_query first when editing existing items; upsert sends whole item state, not a JSON patch. Preserve unchanged fields.","Omit updatedAt on creates and manual edits unless preserving an existing value; replicated state updates it after accepted writes."];function Mt(e,t,n){let r=`${z0}${e}`;return{resource:e,uri:r,sourceType:t,notes:DB,itemSchema:{$schema:"https://json-schema.org/draft/2020-12/schema",title:`Beepflow ${e} item`,type:"object",additionalProperties:!1,required:n.required,properties:n.properties,...n.defs?{$defs:n.defs}:{}}}}var Vy=Mt("note-runner-destinations","frontend/src/spaces/types.ts:NoteRunnerDestination",{required:["id","ownerEmail","name","computer","agent"],properties:{id:ie,updatedAt:wt,ownerEmail:ie,name:ie,computer:ie,agent:{type:"string",enum:["codex","claude"]},lastSeen:wt,activeExecutionId:ie}});var qy=Mt("page-note-executions","frontend/src/tabs/types.ts:PageNoteExecution",{required:["id","ownerEmail","destinationId","spaceId","state","notes"],properties:{id:ie,updatedAt:wt,createdAt:wt,ownerEmail:ie,destinationId:ie,spaceId:ie,spaceName:ie,agent:{type:"string",enum:["codex","claude"]},state:{type:"string",enum:["preparing","unclaimed","claimed","running","unknown","completed","failed"]},notes:{type:"array",items:{type:"object",additionalProperties:!1,required:["pageId","noteId","revision"],properties:{pageId:ie,noteId:ie,revision:ie,createdAt:wt}}},sessionId:ie,result:ie,error:ie}});var K0={$ref:"#/$defs/operatorType"},CB={type:"object",additionalProperties:!1,required:["value"],properties:{value:{description:"Raw option value written to node input literal when selected."},label:{...ie,description:"Optional label shown in operator input dropdowns."}}},xB={type:"object",additionalProperties:!1,required:["type"],properties:{type:{type:"string",enum:xu,description:'Blueprint value type name. Use "list of X" for lists, never "list".'},options:{anyOf:[{type:"array",items:CB},{type:"null"}],description:"Allowed literal values for dropdown-style widgets."},isArray:{type:"boolean",description:"Whether this pin accepts multiple values."},allowedTypes:{anyOf:[{type:"array",items:K0},{type:"null"}],description:"Allowed concrete types for wildcard pins."},linkType:{...ie,description:"Type-linking group used to propagate wildcard types across pins."},widgetType:{...ie,description:'Frontend input widget id. Supports built-in widgets, integration selectors, and "<IntegrationType>-connection" connection dropdowns.'},defaultValue:{description:"Default literal value used when node input omits a value."},defaultValueForArrayElement:{description:"Default literal value for newly added array input elements."}}},OB={type:"object",additionalProperties:!1,required:["name","doc","type"],properties:{name:{...ie,description:"Output pin name."},doc:{...ie,description:"Operator output documentation shown to users."},type:K0}},kB={type:"object",additionalProperties:!1,required:["name","doc","type"],properties:{name:{...ie,description:"Input pin name; node inputs are keyed by this value."},doc:{...ie,description:"Operator input documentation shown to users."},type:K0,isLiteral:{...Ii,description:"Whether this input must be edited as literal value instead of upstream connection."}}},zy=Mt("blueprint-operators","frontend/src/tabs/blueprint/types.ts:Operator",{required:["id","type","name","doc","categoryPath","inputs"],properties:{id:{...ie,description:"Stable registered operator id referenced by blueprint nodes."},type:{...ie,description:"Operator kind, usually function, variable, or localVariable."},name:{...ie,description:"Display name used in operator search and node labels."},aliases:{type:"array",items:ie,description:"Additional search terms for this operator."},doc:{...ie,description:"Operator documentation shown to users."},categoryPath:{type:"array",items:ie,description:"Menu category path segments."},inputs:{type:"array",items:kB,description:"Input pins in display order."},output:{anyOf:[OB,{type:"null"}],description:"Output pin definition, or null for side-effect-only operators."},isDeprecated:{...Ii,description:"Whether operator is deprecated and hidden from default search."},hidden:{...Ii,description:"Whether operator is hidden from menus and search."},canMock:{...Ii,description:"Whether test mode can mock this operator."},updatedAt:wt},defs:{operatorType:xB}});var IB={type:"object",additionalProperties:!1,properties:{x:{...ji,description:"Optional node world x coordinate in blueprint editor. For new nodes, never specify style.x; omit it so the frontend can place nodes after measuring dimensions."},y:{...ji,description:"Optional node world y coordinate in blueprint editor. For new nodes, never specify style.y; omit it so the frontend can place nodes after measuring dimensions."},title:{...ie,description:"Optional display title shown on node."},comment:{...ie,description:"Optional user-authored node comment."}}},PB={type:"object",additionalProperties:!0,description:"Blueprint view node. For new nodes, never specify style.x or style.y; omit coordinates so the frontend can place nodes after measuring dimensions. Known visualization blocks are intentionally accepted as additional properties.",required:["id"],properties:{id:{...ie,description:"Node id; must match key in blueprint view nodes record."},style:IB}},Wy=Mt("blueprint-views","frontend/src/tabs/blueprint/types.ts:BlueprintView",{required:["id","nodes"],properties:{id:{...ie,description:"Blueprint tab id; must match tabs and blueprints resource id."},updatedAt:wt,nodes:{type:"object",additionalProperties:PB,description:"Editor view state keyed by node id."}}});var Ky={type:"object",properties:{name:ie,type:ie,value:ie},description:"DNS record the domain owner publishes in their own zone."},Gy=Mt("domains","frontend/src/domains/types.ts:Domain",{required:["id","spaceId"],properties:{id:{...ie,description:"Hostname serving a site, such as www.acme.com, or a single label under beepflow.app such as acme.beepflow.app. Lowercase, no port and no trailing dot, at least two labels, and never beepflow.com, cname-beepflow.app or a host under either. A beepflow.app subdomain is covered by the certificate Beepflow already holds and serves as soon as it is registered; reserved labels such as www and api, and any label starting with space-, are rejected. Registering a hostname is exclusive across every space. Pages served here must keep tokens in localStorage, never in cookies: beepflow.app is a shared parent domain, so a cookie scoped to it is readable by every other site published under it."},updatedAt:wt,spaceId:{...ie,description:"Space owning the domain. Cannot change after create, and a space holds at most 10 of each kind, counted separately for beepflow.app subdomains and for domains the space owns."},siteId:{...ie,description:"Site whose routes this domain serves, which must belong to the same space. Empty while the domain is registered but serves no site, which holds the hostname and answers 404. A site being deleted empties this rather than releasing the domain."},mcpServerId:{...ie,description:"MCP server of the same space answering on this domain at /mcp; every other path stays with the site. Empty while the domain serves no MCP server."},openAIAppsChallenge:{...ie,description:"Exact plain-text token served at /.well-known/openai-apps-challenge for OpenAI plugin domain verification. Empty disables the response."},status:{...ie,description:'Read only: pending-dns, verifying, active or failed. A beepflow.app subdomain is active from the moment it is registered. Written by the backend as it settles the domain against Cloudflare, and only an active domain attached to a site is served. Writing a value of your own here, or in any field below, is rejected. A create must still carry every one of them at its zero value ("" for strings, 0 for checkedAt, and a record of empty strings), because an item that does not match the stored one fails the precondition of every delta the backend later sends for it.'},statusChangedAt:{type:"number",description:"Read only: milliseconds since Unix epoch of the last status transition."},cloudflareHostnameId:{...ie,description:"Read only: custom hostname backing this domain at the edge."},ownershipRecord:{...Ky,description:"Read only: record proving the claim on the domain."},certificateRecord:{...Ky,description:"Read only: CNAME delegating the certificate challenge to Cloudflare, which writes the challenge that changes at the delegated name so the owner publishes this one once and never again."},hostnameVerified:{type:"boolean",description:"Read only: whether the edge took the hostname into its zone, read from the edge rather than from DNS, so it lags a record that is already published and says nothing about which record it is waiting on."},siteRecordPublished:{type:"boolean",description:"Read only: whether the CNAME onto the serving zone resolves, read from DNS. A provider that answers the record as a proxy, which an apex on Cloudflare always does because it flattens the canonical name away, hides it from any reader; there it counts as published once the edge has taken the hostname, or once the ownership and certificate records both resolve."},ownershipRecordPublished:{type:"boolean",description:"Read only: whether the TXT record proving the claim resolves with the value the edge asked for, read from DNS. True as well once the edge stops naming the record, which is how it reports a claim it has already read."},challengeDelegated:{type:"boolean",description:"Read only: whether the certificate record resolves to the delegated name, read from DNS rather than from the edge."},challengeRecordProxied:{type:"boolean",description:"Read only: whether the certificate record is proxied instead of resolving directly to the delegated name, which blocks certificate issuance."},verificationMessage:{...ie,description:"Read only: what the edge is waiting on, or why it stopped. Present while a domain is healthy and still pending, so it does not by itself mean failure."},checkedAt:{type:"number",description:"Read only: milliseconds since Unix epoch of the last check against the edge."}}});var Hy=Mt("email-domains","frontend/src/email-domains/types.ts:EmailDomain",{required:["id","spaceId"],properties:{id:{...ie,description:"Domain blueprints send mail from, such as acme.com or mail.acme.com. Lowercase, no port and no trailing dot, at least two labels, and never beepflow.com, beepflow.app, cname-beepflow.app or a host under any of them. Registering one is exclusive across every space, and the workspace holds at most 10. This is separate from the domains resource: registering a domain here signs mail, and says nothing about serving pages."},updatedAt:wt,spaceId:{...ie,description:"Space the domain is filed under, which says who may see, register and release it, the way the space on a connection does. It never says which blueprints may send from it: a blueprint of any space sends from this domain as long as whoever started it can see this space. Unlike a served domain this can change after create, because a domain moves between spaces without anything at SES changing; the write is refused unless the caller holds both the space it leaves and the space it joins."},status:{...ie,description:'Read only: pending-dns, verifying, active or failed. Only an active domain can be sent from. Written by the backend as it settles the domain against SES, and writing a value of your own here, or in any field below, is rejected. A create must still carry every one of them at its zero value ("" for strings, 0 for numbers, {} for dkimRecords), because an item that does not match the stored one fails the precondition of every delta the backend later sends for it.'},statusChangedAt:{type:"number",description:"Read only: milliseconds since Unix epoch of the last status transition."},dkimRecords:{type:"object",additionalProperties:ie,description:"Read only: the CNAME records the owner publishes to prove the domain and sign its mail, keyed by the name each is published at, with the value each resolves to. Three of them, named <token>._domainkey.<domain>. Releasing the domain and registering it again mints new ones."},dkimRecordsPublished:{type:"boolean",description:"Read only: whether every DKIM record resolves, read from DNS rather than from SES, so it moves as soon as the owner publishes them rather than when SES next looks."},verificationMessage:{...ie,description:"Read only: why the domain stopped, such as records SES could not find in time, or a domain already sending from this account outside Beepflow."},checkedAt:{type:"number",description:"Read only: milliseconds since Unix epoch of the last check against SES."},bounceCount:{type:"number",description:'Read only: bounces received for mail sent from this domain. Written from the events SES publishes, which are also written into the email-bounces collection of the space BaseEvent connection named "Email Events".'},complaintCount:{type:"number",description:"Read only: complaints received for mail sent from this domain, written alongside the email-complaints collection of the same connection."},lastBounceAt:{type:"number",description:"Read only: milliseconds since Unix epoch of the most recent bounce."},lastComplaintAt:{type:"number",description:"Read only: milliseconds since Unix epoch of the most recent complaint."}}});var Tp={type:"string",description:"Integration resource type processed by this blueprint, such as ApacheKafkaTopic or QdrantCollection. Call integration_blueprint_contexts_list first; use only resource types returned by that tool. The returned executionKind determines trigger choice: managed resources use executor, finite resources choose event-first among blueprint, webhook, and manual, and fall back to cron or loop only when no event exists to react to."},Ap={type:"object",additionalProperties:!0,description:"Integration-specific config for context.type. Start from contextTemplate.config returned by integration_blueprint_contexts_list, fill every configFields item where required=true, and preserve optional defaults such as consumerGroupId, clientId, parser, offsetResetStrategy, orderBy, or webhook topic maps when provided."},wp={type:"object",additionalProperties:!1,required:["enabled"],properties:{enabled:{type:"boolean",description:"Must be true. Backend ignores this trigger branch when enabled is false."}}},G0={...wp.properties.enabled,enum:[!0]},NB=["auto","application/json","text/plain","text/html","application/xml","application/x-www-form-urlencoded","multipart/form-data","application/octet-stream"],FB={type:"object",additionalProperties:!1,required:["count"],description:"Run immediately when explore runtime starts or restarts. Use for finite resource sampling, one-shot imports, and ad hoc reads.",properties:{count:{type:"integer",minimum:1,description:"Number of executions to run back-to-back. Frontend default is 1; backend coerces values below 1 to 1."}}},LB={type:"object",additionalProperties:!1,required:["expression"],description:"Run on a seconds-field cron schedule while explore runtime is active. Use only when no event exists to react to, such as an external finite source with no stream, webhook, or upstream blueprint. Do not use cron to keep derived collections in sync with records another blueprint produces; consume the event instead.",properties:{expression:{type:"string",description:"Cron expression with six fields including seconds, parsed by robfig/cron. Example: 0 */5 * * * * runs every five minutes."},timezone:{type:"string",description:"Optional IANA timezone name such as UTC or America/New_York. Backend uses UTC when omitted or empty."}}},MB={type:"object",additionalProperties:!1,required:["delayMs"],description:"Run immediately, then wait delayMs before repeating while explore runtime is active. Use only for deliberate fixed-delay polling, when the source offers no stream, webhook, or upstream blueprint.",properties:{delayMs:{type:"integer",minimum:1,description:"Delay between executions in milliseconds. Must be positive to avoid a hot loop."}}},$y={...wp,description:"Wait while active until another blueprint or Trigger Self operator invokes this blueprint. Trigger argument is available through Get Trigger Argument. Directed invocation only: the trigger topic is created on start seeking to its end and deleted on stop, so invocations sent while this blueprint is inactive are lost. For durable fan-out, publish into a BaseEvent collection and consume it with an executor trigger."},BB={type:"object",additionalProperties:!1,required:["mode"],description:"Who may call this webhook. The gateway enforces it before the blueprint runs, and a webhook without auth is rejected.",properties:{mode:{type:"string",enum:["public","workspace","space-token"],description:"workspace requires a Beepflow access token whose user can read this blueprint tab; use it for webhooks a Beepflow page or the dashboard calls, and it is the default for new webhooks. space-token requires a token minted by another blueprint in this space through the Issue Token operator; use it for pages serving the customer's own end users, and read the identity from trigger auth.claims. public accepts any caller; use it only when an outside provider posts to this URL and cannot send a token."},allowedOrigins:{type:"array",items:{type:"string"},description:"Extra browser origins allowed to call this webhook, such as https://app.partner.com. Beepflow pages of the owning space are always allowed, so omit this unless a site outside Beepflow calls the webhook from a browser."}}},H0={type:"object",additionalProperties:!1,required:["enabled","auth"],description:"Wait while active for generic GET/POST /:tabId/trigger HTTP calls. Request method, URL, parsed body, headers, auth, and timestamp become trigger argument. Webhook URL is `${status.backendUrl}/${encodeURIComponent(blueprint.id)}/trigger` and runs only while blueprint is active in explore mode. Call it with blueprint_webhook_call, which sends the MCP credential.",properties:{enabled:wp.properties.enabled,auth:BB,timeoutMs:{type:"integer",minimum:1,description:"Maximum synchronous webhook execution time in milliseconds. Backend uses 30000 when omitted or below 1."},contentType:{type:"string",enum:NB,description:"Request body parser. Omit or use auto to infer from incoming Content-Type, then fall back to JSON sniffing, UTF-8 text, then binary. Not for provider webhook resources managed through BaseEvent; use BaseEventCollection."},description:{type:"string",description:"What this webhook does, shown to callers that discover it: an mcp-servers item listing this blueprint as a tool serves it as the tool description."},annotations:{type:"object",additionalProperties:!1,required:["readOnlyHint","destructiveHint","openWorldHint"],description:"MCP safety hints describing whether this webhook only reads, can cause irreversible changes, or changes external systems.",properties:{readOnlyHint:{type:"boolean"},destructiveHint:{type:"boolean"},openWorldHint:{type:"boolean"}}},inputSchema:{type:"object",additionalProperties:!0,description:"JSON Schema (draft 7 default) the gateway validates the JSON request body against before the blueprint runs; violating requests are rejected with the violations and never reach the blueprint. Also served as the tool inputSchema when an mcp-servers item lists this blueprint. Only meaningful for JSON bodies; leave unset for other content types."},outputSchema:{type:"object",additionalProperties:!0,description:"JSON Schema describing the JSON body the webhook response node returns. Not enforced; served as the tool outputSchema when an mcp-servers item lists this blueprint."}}},Xy={...wp,description:"Use for managed integration resources where runtime owns stream, event, webhook, or poll lifecycle, such as ApacheKafkaTopic, RabbitMQStream, BaseEventCollection, and MQTTTopic. Also use it for internal blueprint-to-blueprint events published into a BaseEvent collection, which is the durable, decoupled default for derived and fan-out work."},Ep={type:"object",additionalProperties:!1,minProperties:1,maxProperties:1,description:"Exactly one trigger branch, chosen event-first: executor for executionKind=managed resources and for BaseEvent collections carrying internal events, blueprint for directed invocation by a known caller, webhook for generic GET/POST /:tabId/trigger HTTP calls, manual for ad hoc/sample/start-once runs and one-shot backfills, and cron or loop last, only when no event exists to react to.",properties:{manual:FB,cron:LB,loop:MB,blueprint:$y,webhook:H0,executor:Xy},oneOf:[{required:["manual"]},{required:["cron"]},{required:["loop"]},{required:["blueprint"]},{required:["webhook"]},{required:["executor"]}]},Yy={...Ep,properties:{...Ep.properties,blueprint:{...$y,properties:{enabled:G0}},webhook:{...H0,properties:{...H0.properties,enabled:G0}},executor:{...Xy,properties:{enabled:G0}}}};var UB={type:"object",additionalProperties:!1,required:["literal"],properties:{literal:{description:"Literal JSON value for this input element; null is valid when connected upstream."},nodeId:{...ie,description:"Upstream node id when this value is connected to another node output."},operatorInputId:{...ie,description:"Upstream output pin name used by this connection."},nodeInputIndex:{...ie,description:'CRDT list index of upstream output value. Use "0.5" for any connected node output.'}}},VB={type:"object",additionalProperties:!1,required:["values"],properties:{isArray:{...Ou,description:"Whether input accepts multiple values for one operator input."},values:{type:"object",additionalProperties:UB,description:"Input values keyed by CRDT list index strings."},type:{type:"string",enum:xu,description:"Resolved input type override."},forceZipping:{...Ou,description:"Force list zipping behavior for multiple upstream values."},listInputMode:{type:"string",enum:["list","items"],description:"Whether this input receives one whole list value or assembles a list from item values."}}},qB={type:"object",additionalProperties:!1,required:["id","operatorId","inputs"],properties:{id:{...ie,description:"Stable node id; must match key in blueprint nodes record."},operatorId:{...ie,description:"Id of registered blueprint operator this node executes."},inputs:{type:"object",additionalProperties:VB,description:"Node inputs keyed by operator input name."},mockNever:{...Ou,description:"Disable mocking for this node."},skipBehavior:{type:"string",enum:["skip","null"],description:"Behavior when upstream value is skipped."},disabled:{...Ou,description:"Whether this node and downstream dependent nodes are disabled."},outputType:{type:"string",enum:xu,description:"Resolved output type for wildcard operators."}}},zB={type:"object",additionalProperties:!1,required:["type","trigger"],properties:{type:Tp,trigger:Yy,config:Ap}},jy=Mt("blueprints","frontend/src/tabs/blueprint/types.ts:Blueprint",{required:["id","mode","nodes","context"],properties:{id:{...ie,description:"Blueprint tab id; must match tabs resource id."},updatedAt:wt,mode:{type:"string",enum:["test","explore"],description:'Execution mode; result id is blueprint id plus "-test" or "-explore".'},nodes:{type:"object",additionalProperties:qB,description:"Blueprint nodes keyed by node id."},context:zB,testRecordsAmount:{...By,description:"Target number of test records to keep for test mode."},recomputeOnChange:{type:"string",enum:["always","manual"],description:"Whether edits automatically restart execution."},mockNever:{...Ii,description:"Global flag to disable node mocking."},desiredState:{type:"string",enum:["active","inactive"],description:"Requested runtime state for test or explore mode."},runtimeActionId:{...ie,description:"Backend-owned id for latest explicit start or stop request; preserve on unrelated edits."},updatedBy:{...ie,description:"Backend-owned email of whoever last changed this blueprint; attribution only."},startedBy:{...ie,description:"Backend-owned email of whoever last started this blueprint; its executions act as that person."}}});var WB=["Aerospike","ApacheKafka","MQTT","Kaggle","FacebookAds","RabbitMQ","Shopify","ShopifyApp","YouTube","Webshare","Playwright","AWS","Qdrant","OpenAI","BaseVector","BaseEvent","BaseLookup","Gorgias","LMStudio","OpenRouter","VoyageAI","GoogleDrive","GoogleSheets","Gmail","DiscordChannelWebhook"],Qy=Mt("connections","frontend/src/integrations/types.ts:Connection",{required:["id","label","type","spaceId"],properties:{id:ie,updatedAt:wt,label:ie,type:{type:"string",enum:WB},spaceId:ie}});var Jy=Mt("roles","frontend/src/auth/roles/types.ts:Role",{required:["id","label","authorizations"],properties:{id:ie,updatedAt:wt,label:ie,authorizations:yp}});var Zy=Mt("pages","frontend/src/tabs/types.ts:Page",{required:["id","sourceUrl","distUrl"],properties:{id:{...ie,description:"Page tab id; must match tabs resource id."},updatedAt:wt,sourceUrl:{...ie,description:"File-service URL for raw source HTML."},distUrl:{...ie,description:"File-service URL for optimized HTML rendered in a sandbox iframe."}}});var KB={type:"object",additionalProperties:!1,required:["selector","tagName"],properties:{selector:{...ie,description:"CSS selector the element answered to in the rendered page."},tagName:ie,attributes:{anyOf:[Sp,{type:"null"}],description:"id, class, name, role, aria-label, href, src, alt and every data-* of the element. A page builds most of its dom from script, so search the source html by these before trusting the selector."},ancestorChain:{anyOf:[{type:"array",items:ie},{type:"null"}],description:"tag#id.class of the ancestors, outermost first."},textSnippet:{...ie,description:"Start of the element text as the viewer saw it."},htmlSnippet:{...ie,description:"Start of the element outerHTML as rendered."},pageQuery:{...ie,description:"Page url query the note was placed under."},viewportWidth:ji,viewportHeight:ji,viewportMode:{type:"string",enum:["desktop","mobile"],description:"Dashboard preview mode the note was taken in; reproduce the page at this viewport when addressing the note. Absent on notes older than the toggle."},rect:{type:"object",additionalProperties:!1,properties:{x:ji,y:ji,width:ji,height:ji}}}},GB={type:"object",additionalProperties:!1,required:["id","note","status","target"],properties:{autoRun:{type:"boolean"},revision:ie,resolvedRevision:ie,id:ie,note:{...ie,description:"What the viewer asked for at this element."},status:{type:"string",enum:["open","resolved"]},createdAt:wt,createdByEmail:ie,resolvedAt:wt,resolvedByEmail:ie,target:KB}},eE=Mt("page-annotations","frontend/src/tabs/types.ts:PageAnnotation",{required:["id","notesById"],properties:{id:{...ie,description:"Page tab id; must match tabs resource id."},updatedAt:wt,notesById:{type:"object",additionalProperties:GB,description:"Notes viewers placed on elements of this page, keyed by note id."}}});var tE=Mt("sites","frontend/src/sites/types.ts:Site",{required:["id","name","spaceId","pageTabIdByPath"],properties:{id:{...ie,description:"Site id, opaque and generated at create. It names nothing outside the workspace: the hostnames a site answers on are the domains registered against it in the domains resource, so a site created here is reachable only once a domain names it."},name:{...ie,description:"What the site is called, up to 100 characters. Two sites of one space may share a name, because the id is what tells them apart."},updatedAt:wt,spaceId:{...ie,description:"Space owning the site. Every routed page tab must belong to this space, and the value cannot change after create."},pageTabIdByPath:{type:"object",additionalProperties:ie,description:'Page tab id by request path, at most 100 entries. Paths start with "/", carry no query or fragment, and have no trailing slash except the root path "/".'}}});var nE=Mt("mcp-servers","frontend/src/mcp-servers/types.ts:McpServer",{required:["id","name","spaceId","toolTabIdByName"],properties:{id:{...ie,description:'Server id, 1-64 characters of [a-zA-Z0-9_-], never "oauth". It is the last path segment of the endpoint POST ${backendUrl}/mcp/<id>, reachable on the app host and on every domain of the workspace, and cannot change after create.'},name:{...ie,description:"What the server calls itself in the MCP initialize response, up to 100 characters."},updatedAt:wt,spaceId:{...ie,description:"Space owning the server. Every tool blueprint and OAuth access token must belong to this space, and the value cannot change after create."},auth:{type:"object",additionalProperties:!1,required:["mode"],description:"Who may call this server. The gateway enforces it before any tool runs, and a server without auth rejects every call. The caller identity reaches each tool blueprint as trigger auth, in the same shape webhook triggers receive.",properties:{mode:{type:"string",enum:["public","workspace","space-token"],description:"space-token uses OAuth when authorizeUrl is set, exchanging a token minted by the space's login blueprint for an MCP access token bound to this server; without authorizeUrl, callers provide the end-user token directly. Tools read the identity from trigger auth.claims. workspace requires a Beepflow access token whose user can read this server. public accepts any caller."},allowedOrigins:{type:"array",items:{type:"string"},description:"Extra browser origins allowed to call this server. Beepflow pages of the owning space are always allowed."},authorizeUrl:{...ie,description:"Absolute URL of the login page remote OAuth clients such as claude.ai are sent to, usually a page published on a site of this space. The page receives the pending request in its mcp_authorize query parameter, signs the end user in through its own login blueprint, posts {authorizeRequest, token} to /api/mcp/oauth/complete, and navigates to the returned redirectUrl. Only meaningful with mode space-token; without it the server offers no OAuth."}}},toolTabIdByName:{type:"object",additionalProperties:ie,description:"Webhook blueprint tab id by tool name, at most 100 entries. Names are 1-128 characters of [a-zA-Z0-9_-]. Each tab must be a blueprint of the same space with a webhook trigger; its tab name, trigger description, schemas and annotations describe the listed tool, and tools/call runs it like a POST webhook call. A tool answers only while its blueprint is active."}}});var rE=Mt("schemas","frontend/src/integrations/types.ts:Schema",{required:["id","type","connectionId","path","schema"],properties:{id:ie,updatedAt:wt,type:{type:"string",enum:Uy},connectionId:ie,path:Sp,schema:{type:"object",additionalProperties:{type:"string",enum:xu}},keySerdeType:{type:"string"},valueSerdeType:{type:"string"}}});var iE=Mt("space-join-requests","frontend/src/spaces/space-join-requests/types.ts:SpaceJoinRequest",{required:["id","createdAt","requestedBy","kind","status","spaceId","userId"],properties:{id:ie,createdAt:{type:"number",description:"Nanoseconds since Unix epoch."},updatedAt:wt,requestedBy:ie,kind:{type:"string",enum:["invite","request"]},status:{type:"string",enum:["pending","granted","denied"]},spaceId:ie,userId:ie}});var oE=Mt("spaces","frontend/src/spaces/types.ts:Space",{required:["id","label"],properties:{id:ie,updatedAt:wt,label:ie,noteRunnerDestinationId:ie,activeNoteExecutionId:{...ie,readOnly:!0},thumbnailUrl:ie,description:ie,isUserSpace:Ou}});var aE=Mt("tabs","frontend/src/tabs/types.ts:Tab",{required:["id","name","order","type","parent","spaceId"],properties:{id:{...ie,description:"Stable tab id. Blueprint and page tabs normally have matching records keyed by this id."},updatedAt:wt,name:ie,order:ji,type:{type:"string",enum:["blueprint","folder","page"],description:"Navigation item kind; blueprint and page tabs normally have matching records."},parent:ie,spaceId:ie}});var sE=Mt("user-locations","frontend/src/workspace/user-location/types.ts:UserLocation",{required:["id"],properties:{id:ie,updatedAt:wt,tab:{type:"object",additionalProperties:!1,required:["id"],properties:{id:ie}},blueprint:{type:"object",additionalProperties:!1,required:["id"],properties:{id:ie,worldPosition:{type:"object",additionalProperties:!1,required:["x","y"],properties:{x:ji,y:ji}}}}}});var uE=Mt("users","frontend/src/auth/users/types.ts:User",{required:["id","displayName","roleIds","authorizations","spaces"],properties:{id:ie,updatedAt:wt,displayName:ie,avatarUrl:ie,roleIds:W0,authorizations:yp,spaces:W0}});var Rp=[uE,Jy,oE,aE,Zy,eE,Vy,qy,tE,Qy,rE,jy,Wy,Gy,Hy,nE,zy,sE,iE];function Dp(e){return Rp.find(t=>t.resource===e)}var $0=[Xr("users","Workspace users and authorizations.",!0),Xr("roles","Workspace roles and resource authorizations.",!0),Xr("spaces","Workspace spaces.",!0),Xr("tabs","Tabs and folders visible to authorized user; blueprint and page tabs normally share ids with matching records.",!0),Xr("pages","Untrusted single-page HTML source and optimized file URLs keyed by matching page tab id.",!0),Xr("page-annotations","Notes viewers placed on elements of a page in the dashboard, keyed by matching page tab id.",!0),Xr("note-runner-destinations","Installed note runner destinations owned by the signed-in user. Registration and active execution fields are maintained by the backend.",!1),Xr("page-note-executions","Claimed page-note batches and their session outcomes. Execution state is maintained by the backend; open notes remain the source of pending work.",!1),Xr("sites","Public sites keyed by id; each maps request paths of one space to page tab ids and carries no hostname of its own, so it is served without sign in on whichever domains are registered against it.",!0),Xr("domains","Hostnames a space registered, keyed by hostname; every host a site or MCP server is served on is one of these, whether a beepflow.app subdomain or a domain the space owns. An active domain can serve a site's pages, an MCP endpoint and an OpenAI verification challenge. Reconciliation status and DNS fields are read-only.",!0),Xr("email-domains","Domains the workspace proved it holds so blueprints can send mail from them, keyed by the domain. Registering one hands back three DKIM CNAME records to publish; once they resolve the domain signs mail and the Send Email from Your Domain operator accepts a From address under it. The space on the row says who may see, register and release the domain, the way it does on a connection, and never which blueprints may send from it: a blueprint of any space sends from any verified domain whoever started it may see. Separate from the domains resource, which serves pages instead. Only id and spaceId are writable, and spaceId can change so a domain moves between spaces.",!0),Xr("mcp-servers","HTTP MCP servers keyed by id; each publishes webhook blueprints of one space as MCP tools at POST ${backendUrl}/mcp/<id>. toolTabIdByName maps each tool name to a webhook blueprint tab; the tool's description, schemas and annotations live on that blueprint's webhook trigger, so the server holds only naming, auth and grouping. A space-token server with authorizeUrl exchanges the site's end-user login token for an MCP access token bound to the requested server and resource.",!0),Xr("connections","Read-only integration connections without secret-bearing config; config is redacted and cannot be read through MCP.",!1),Xr("schemas","Integration schema metadata.",!0),Xr("blueprints","Blueprint definitions keyed by matching blueprint tab id.",!0),Xr("blueprint-views","Blueprint editor view state keyed by matching blueprint tab id.",!0),Xr("blueprint-operators","Registered blueprint operator definitions.",!1),Xr("user-locations","Live user location records.",!0),Xr("space-join-requests","Space invitation and join requests.",!0)],HB=["tabs","pages","page-annotations","blueprints","blueprint-views"],X0=new Set(HB),ku=$0.filter(e=>!X0.has(e.name)),rf=ku.map(e=>e.name),cE=$0.map(e=>e.name);function $B(e){return $0.find(t=>t.name===e)}function lE(e){return ku.find(t=>t.name===e)}function fE(e){if($B(e))return e;throw new Error(`unsupported resource: ${e}`)}function Y0(e){if(X0.has(e))throw new Error(`dedicated resource ${e}: use tab and blueprint intent tools instead of generic resource_* tools`);if(lE(e))return e;throw new Error(`unsupported resource: ${e}`)}function j0(e){let t=lE(e);if(X0.has(e))throw new Error(`dedicated resource ${e}: use tab and blueprint intent tools instead of generic resource_* tools`);if(!t)throw new Error(`unsupported resource: ${e}`);if(!t.writable)throw new Error(`resource is read-only: ${e}`);return t.name}function Xr(e,t,n){return{name:e,description:t,writable:n,schemaUri:`${z0}${e}`}}function Yr(){return Date.now()*1e6}function of(e,t){if(e===null&&t===null)return{pre:null,post:null};if(e===null&&t!==null)return{pre:null,post:t};if(e!==null&&t===null)return{pre:e,post:null};if(typeof e!="object"||typeof t!="object")return e!==t?{pre:e,post:t}:{pre:null,post:null};if(Array.isArray(e)||Array.isArray(t))return{pre:null,post:null};let{pre:n,post:r}=dE(e,t);return n===null&&r===null?{pre:null,post:null}:{pre:n,post:r}}function dE(e,t){let n={},r={},i=!1,o=new Set([...Ka(e),...Ka(t)]);for(let s of o){if(s==="updatedAt")continue;let c=e[s],f=t[s];if(Array.isArray(c)||Array.isArray(f)){(Array.isArray(c)!==Array.isArray(f)||!Cp(c,f))&&(n[s]=c===void 0?null:c,r[s]=f===void 0?null:f,i=!0);continue}let h=Bs(c),g=Bs(f);if(!(s in t))h||(n[s]=c,r[s]=null,i=!0);else if(!(s in e))g||(n[s]=null,r[s]=f,i=!0);else{if(h&&g)continue;if(h&&!g)n[s]=null,r[s]=f,i=!0;else if(!h&&g)n[s]=c,r[s]=null,i=!0;else{let{pre:_,post:S}=XB(c,f);(_!==void 0||S!==void 0)&&(_!==void 0&&(n[s]=Q0(_)),S!==void 0&&(r[s]=Q0(S)),i=!0)}}}return i?Ka(n).length===0&&Ka(r).length===0?{pre:null,post:null}:Ka(n).length===0?{pre:null,post:r}:Ka(r).length===0?{pre:n,post:null}:{pre:n,post:r}:{pre:null,post:null}}function XB(e,t){if(YB(e,t))return{pre:void 0,post:void 0};let n=Bs(e),r=Bs(t);if(n&&r)return{pre:void 0,post:void 0};if(n)return{pre:null,post:t};if(r)return{pre:e,post:null};if(Array.isArray(e)||Array.isArray(t))return{pre:void 0,post:void 0};if(typeof e!=typeof t)return{pre:e,post:t};if(typeof e=="object"&&e!==null&&typeof t=="object"&&t!==null){let{pre:i,post:o}=dE(e,t);return i===null&&o===null?{pre:void 0,post:void 0}:{pre:i===null?void 0:i,post:o===null?void 0:o}}return{pre:e,post:t}}function Bs(e){return e==null?!0:typeof e=="object"&&e!==null?Array.isArray(e)?e.length===0:Ka(e).length===0:!1}function YB(e,t){return Bs(e)&&Bs(t)?!0:Cp(e,t)}function Cp(e,t){if(e===t)return!0;if(e==null||t==null||typeof e!="object"||typeof t!="object")return!1;let n=Ka(e),r=Ka(t);if(n.length!==r.length)return!1;for(let i of n)if(!(i in t)||!Cp(e[i],t[i]))return!1;return!0}function xp(e,t){return t.pre===null?e===null:e===null||typeof e!="object"||Array.isArray(e)?!1:pE(e,t.pre)}function pE(e,t){for(let n in t)if(n!=="updatedAt"&&!jB(e[n],t[n]))return!1;return!0}function jB(e,t){return t===null||QB(t)?Bs(e):e===void 0?!1:typeof t=="object"&&t!==null&&!Array.isArray(t)&&typeof e=="object"&&e!==null&&!Array.isArray(e)?pE(e,t):Cp(e,t)}function QB(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Ka(e).length===0}function Q0(e){if(e==null)return null;if(typeof e=="object"&&e!==null){if(Array.isArray(e)&&e.length===0)return null;if(!Array.isArray(e)){let t={},n=!1;for(let r in e)t[r]=Q0(e[r]),t[r]!==void 0&&(n=!0);return n?t:null}}return e}function J0(e,t){let n=Z0(e,t);return n!==null&&typeof n=="object"&&!Array.isArray(n)&&(n.updatedAt=t.updatedAt),n}function Z0(e,t){return t.post===null?null:e===null?t.post:typeof e!="object"||Array.isArray(e)?t.post:mE(e,t.post)}function mE(e,t){let n={};for(let r in e)if(r in t){let i=t[r];if(i===null)continue;typeof i=="object"&&!Array.isArray(i)&&typeof e[r]=="object"&&!Array.isArray(e[r])&&e[r]!==null?n[r]=mE(e[r],i):n[r]=i}else n[r]=e[r];for(let r in t)!(r in e)&&t[r]!==null&&(n[r]=t[r]);return n}function Ka(e){let t=[];for(let n in e)t.push(n);return t}var hE="replicated-state",Op=class{ackedResources={};dirtyResources={};unauthorizedKeys={};loadingResources={};loadingPromises=new Map;loadedResources=new Set;registeredResources=new Set;resourceChangeListeners=new Set;snapshotWaiters=new Map;storage;socketSession;logger;inflightItems=new Map;constructor(t,n,r){this.storage=t,this.socketSession=n,this.logger=r}onResourceChange(t){return this.resourceChangeListeners.add(t),()=>this.resourceChangeListeners.delete(t)}registerResource(t){this.registeredResources.add(t),this.initializeResource(t)}isResourceRegistered(t){return this.registeredResources.has(t)}getRegisteredResources(){return Array.from(this.registeredResources)}setDirtyItems(t,n){this.registerResource(t),this.dirtyResources[t]=Qi(n)}setDirtyItem(t,n,r){if(this.registerResource(t),r===void 0){delete this.dirtyResources[t][n];return}this.dirtyResources[t][n]=Qi(r)}clearSessionState(){this.ackedResources={},this.loadingResources={},this.loadingPromises.clear(),this.loadedResources.clear(),this.inflightItems.clear();for(let t of this.registeredResources)this.dirtyResources[t]={},this.unauthorizedKeys[t]={},this.loadingResources[t]=!0,this.emitResourceChange(t)}async loadRegisteredResourcesFromStorage(){await Promise.all(Array.from(this.registeredResources,t=>this.loadResourceFromStorage(t)))}async hydrate(t,n){this.registerResource(t),await this.loadResourceFromStorage(t),this.logger.info(`Calculating lastUpdatedAtSeen from ${_E(this.ackedResources[t])} items`);let r=this.prepareSnapshotQuery(t,n);this.logger.info(`\u{1F4F8} ${t} requested with query:`,r),this.socketSession.send(hE,{resource:t,action:"snapshot",value:r})}hydrateAll(t){return this.hydrate(t,{all:!0})}async waitForSnapshot(t,n){await new Promise((r,i)=>{let o,s=()=>{clearTimeout(o),r()};o=setTimeout(()=>{this.snapshotWaiters.get(t)?.delete(s),i(new Error(`snapshot timeout for ${t}`))},n),this.snapshotWaiters.has(t)||this.snapshotWaiters.set(t,new Set),this.snapshotWaiters.get(t).add(s)})}processSocketEvent(t){switch(t.action){case"snapshot":this.applySnapshot(t.resource,t.value??{});break;case"delta":this.applyRemoteDelta(t);break}}async upsertItem(t,n){this.registerResource(t);let r=this.getAckedValue(t,n.id),i=of(r,n);return i.pre===null&&i.post===null?!0:this.sendDelta(t,n.id,i,n)}async deleteItem(t,n){this.registerResource(t);let r=this.getAckedValue(t,n),i=of(r,null);return i.pre===null&&i.post===null?!0:this.sendDelta(t,n,i,null)}isItemInflight(t,n){return this.inflightItems.get(t)?.has(n)===!0}async sendDelta(t,n,r,i){this.registerResource(t),this.inflightItems.has(t)||this.inflightItems.set(t,new Set);let o=this.inflightItems.get(t);if(o.has(n))return!1;let s=this.getDirtyValue(t,n);xp(s,r)&&(arguments.length>=4?this.setDirtyValue(t,n,Qi(i)):this.setDirtyValue(t,n,Z0(s,Qi(r))),this.emitResourceChange(t)),o.add(n);let c;try{c=await this.socketSession.sendWithAck(hE,{resource:t,action:"delta",key:n,value:r})}catch(f){c={ok:!1,reason:f instanceof Error?f.message:"error"}}return o.delete(n),c.ok?!0:(this.revertDirtyToAckedValue(t,n),this.emitResourceChange(t),this.logger.error(`!ack[${t}] Reverting to acked state for ${t}:${n}`,c.reason),!1)}getAckedValue(t,n){return this.initializeResource(t),this.ackedResources[t][n]??null}getDirtyValue(t,n){return this.initializeResource(t),this.dirtyResources[t][n]??null}getVisibleItems(t){this.initializeResource(t);let n={};for(let r in this.dirtyResources[t]){let i=this.dirtyResources[t][r];i!=null&&(n[r]=i)}return n}getRawItems(t){return this.initializeResource(t),Qi(this.dirtyResources[t])}getAckedItems(t){return this.initializeResource(t),Qi(this.ackedResources[t])}getUnauthorizedKeys(t){return this.initializeResource(t),Qi(this.unauthorizedKeys[t])}isResourceLoading(t){return this.initializeResource(t),this.loadingResources[t]}initializeResource(t){this.ackedResources[t]===void 0&&(this.ackedResources[t]={}),this.dirtyResources[t]===void 0&&(this.dirtyResources[t]={}),this.unauthorizedKeys[t]===void 0&&(this.unauthorizedKeys[t]={}),this.loadingResources[t]===void 0&&(this.loadingResources[t]=!0)}prepareSnapshotQuery(t,n){this.initializeResource(t);let r=Qi(n);if(r.lastUpdatedAtSeen!==void 0)return r;let i=this.buildLastUpdatedAtSeen(t,r);return gE(i)||(r.lastUpdatedAtSeen=i),r}async loadResourceFromStorage(t){if(this.initializeResource(t),this.loadedResources.has(t))return;if(this.loadingPromises.has(t))return this.loadingPromises.get(t);let n=this.loadResourceItemsFromStorage(t);this.loadingPromises.set(t,n);try{await n}finally{this.loadingPromises.delete(t),this.loadedResources.add(t)}}async loadResourceItemsFromStorage(t){let n=!1,r=0;try{let i=await this.storage.loadItems(t);if(i&&gE(this.ackedResources[t])){n=!0;for(let o in i)this.applyCachedItem(t,o,i[o])&&(r+=1)}}catch(i){this.logger.warn(`Failed to load cached ${t}: ${String(i)}`)}finally{this.loadingResources[t]=!1,this.emitResourceChange(t),n?this.logger.info(`\u{1F4C2} ${r}x ${t} from cache`):this.logger.info(`\u{1F4C2} no cached data for ${t}`)}}applyCachedItem(t,n,r){return r===null?(this.ackedResources[t][n]=null,this.dirtyResources[t][n]=null,!0):r==="unauthorized"?(this.unauthorizedKeys[t][n]=!0,!1):(this.ackedResources[t][n]=Qi(r),this.dirtyResources[t][n]=Qi(r),!0)}applySnapshot(t,n){this.initializeResource(t);for(let r in n){let i=n[r];i===null?(this.ackedResources[t][r]=null,(!this.isItemInflight(t,r)||this.getDirtyValue(t,r)==null)&&(this.dirtyResources[t][r]=null),delete this.unauthorizedKeys[t][r]):i==="unauthorized"?(delete this.ackedResources[t][r],delete this.dirtyResources[t][r],this.unauthorizedKeys[t][r]=!0):(this.ackedResources[t][r]=Qi(i),this.dirtyResources[t][r]=Qi(i),delete this.unauthorizedKeys[t][r]),this.storage.persistItem(t,r,i).catch(o=>{this.logger.warn(`Failed to persist ${t}:${r}: ${String(o)}`)})}this.loadingResources[t]=!1,this.emitResourceChange(t),this.logger.info(`\u{1F4F8} ${_E(n)}x ${t} `),this.resolveSnapshotWaiters(t)}applyRemoteDelta(t){let n=t.resource,r=t.key;if(!r)return;this.initializeResource(n);let i=t.value,o={pre:i.pre,post:i.post},s=this.getAckedValue(n,r);if(!xp(s,o))this.logger.error(`\u{1D6AB}S precondition invalid on last acked for ${n}:${r}`,{pre:o.pre,post:o.post,current:s});else{let f=J0(s,Qi(i));this.ackedResources[n][r]=f,this.storage.persistItem(n,r,f).catch(h=>{this.logger.warn(`Failed to persist ${n}:${r}: ${String(h)}`)}),this.logger.info(eg(`\u{1D6AB}S[${n}] acked`,o))}let c=this.getDirtyValue(n,r);t.by!==this.socketSession.getSessionId()?xp(c,o)?o.post===null?(this.dirtyResources[n][r]=null,this.logger.info(eg(`\u{1D6AB}S[${n}] dirty`,o))):(this.dirtyResources[n][r]=J0(c,Qi(i)),this.logger.info(eg(`\u{1D6AB}S[${n}] dirty`,o))):(this.logger.warn(`Skip delta on dirty for ${n}:${r}`,{pre:o.pre,post:o.post,current:s}),this.revertDirtyToAckedValue(n,r)):o.post!=null&&c!=null&&typeof c=="object"&&(c.updatedAt=i.updatedAt,this.dirtyResources[n][r]=c,this.logger.info(`\u{1D6AB}S[${n}] dirty updatedAt for ${r}`)),this.emitResourceChange(n)}buildLastUpdatedAtSeen(t,n){let r=this.ackedResources[t],i={};if(n.all){for(let o in r)this.copyItemUpdatedAt(r[o],o,i);return i}if(n.keys&&n.keys.length>0)for(let o of n.keys)this.copyItemUpdatedAt(r[o],o,i);return i}copyItemUpdatedAt(t,n,r){t&&typeof t=="object"&&typeof t.updatedAt=="number"&&(r[n]=t.updatedAt)}setDirtyValue(t,n,r){if(r===null){this.dirtyResources[t][n]=null;return}this.dirtyResources[t][n]=r}revertDirtyToAckedValue(t,n){let r=this.ackedResources[t][n];if(r===void 0){delete this.dirtyResources[t][n];return}if(r===null){this.dirtyResources[t][n]=null;return}this.dirtyResources[t][n]=Qi(r)}emitResourceChange(t){let n={resource:t,acked:this.getAckedItems(t),dirty:this.getRawItems(t),unauthorized:this.getUnauthorizedKeys(t),loading:this.loadingResources[t]};for(let r of this.resourceChangeListeners)r(n)}resolveSnapshotWaiters(t){let n=this.snapshotWaiters.get(t);if(n){this.snapshotWaiters.delete(t);for(let r of n)r()}}};function Qi(e){if(e===void 0)return e;if(typeof structuredClone=="function")try{return structuredClone(e)}catch{}try{return JSON.parse(JSON.stringify(e))}catch{return e}}function gE(e){for(let t in e)return!1;return!0}function _E(e){let t=0;for(let n in e)t+=1;return t}function eg(e,t){return`${e}
46
+ `),this.database)}};function Ny(e){let t=e??"unknown-user";return SB.createHash("sha256").update(t).digest("hex")}function Fy(e,t,n){let r=e.replace(/^http/,"ws"),i=encodeURIComponent(t),o=encodeURIComponent(n);return`${r}/base/${i}/${o}`}var vp=class{websocket;sessionId=Ic();backendUrl;accessToken;channelListeners=new Map;disconnectListeners=new Set;ackWaiters=new Map;intentionallyClosed=!1;constructor(t,n){this.backendUrl=t,this.accessToken=n}async connect(t){this.intentionallyClosed=!1,this.sessionId=Ic();let n=Fy(this.backendUrl,this.accessToken,this.sessionId),r=new WebSocket(n,"echo");this.websocket=r,await new Promise((i,o)=>{let s=setTimeout(()=>o(new Error("websocket open timeout")),t);r.onopen=()=>{clearTimeout(s),i()},r.onerror=()=>{clearTimeout(s),o(new Error("websocket open failed"))}}),r.onmessage=i=>this.processMessage(i.data),r.onclose=()=>this.processClose(),r.onerror=()=>this.processClose()}getSessionId(){return this.sessionId}send(t,n){if(!this.websocket||this.websocket.readyState!==WebSocket.OPEN)throw new Error("gateway websocket not connected");this.websocket.send(`${t};${JSON.stringify(n)}`)}sendWithAck(t,n,r=15e3){let i=Ic(),o={...n,eventId:i};return new Promise(s=>{let c=setTimeout(()=>{this.ackWaiters.delete(i),s({ok:!1,reason:"timeout"})},r);this.ackWaiters.set(i,{resolve:s,timeout:c}),this.send(t,o)})}onChannel(t,n){return this.channelListeners.has(t)||this.channelListeners.set(t,new Set),this.channelListeners.get(t).add(n),()=>this.channelListeners.get(t)?.delete(n)}onDisconnected(t){return this.disconnectListeners.add(t),()=>this.disconnectListeners.delete(t)}waitForChannelEvent(t,n,r,i){return new Promise((o,s)=>{let c=setTimeout(()=>{h(),i?.removeEventListener("abort",f),s(new Error(`channel event timeout: ${t}`))},r),f=()=>{clearTimeout(c),h(),s(new Error(`channel event aborted: ${t}`))},h=this.onChannel(t,g=>{n(g)&&(clearTimeout(c),h(),i?.removeEventListener("abort",f),o(g))});i?.aborted?f():i?.addEventListener("abort",f,{once:!0})})}collectChannelEvents(t,n,r,i){return new Promise((o,s)=>{let c=[],f,h=setTimeout(()=>{_(),f&&clearTimeout(f),s(new Error(`channel event timeout: ${t}`))},r),g=()=>{clearTimeout(h),_(),o(c)},_=this.onChannel(t,S=>{n(S)&&(c.push(S),f&&clearTimeout(f),f=setTimeout(g,i))})})}close(){this.intentionallyClosed=!0,this.websocket?.close(),this.websocket=void 0;for(let t of this.ackWaiters.values())clearTimeout(t.timeout),t.resolve({ok:!1,reason:"closed"});this.ackWaiters.clear()}processMessage(t){let n=typeof t=="string"?t:"",r=n.indexOf(";");if(r===-1)return;let i=n.slice(0,r),o=n.slice(r+1),s;try{s=JSON.parse(o)}catch{return}if(i.startsWith("ack:")){this.resolveAck(i.slice(4),s);return}s=AB(s);let c=this.channelListeners.get(i);if(c)for(let f of c)f(s)}resolveAck(t,n){let r=this.ackWaiters.get(t);r&&(this.ackWaiters.delete(t),clearTimeout(r.timeout),r.resolve(n.value??{ok:!1}))}processClose(){if(!this.intentionallyClosed)for(let t of this.disconnectListeners)t()}};function AB(e){if(e.resource!=="connections")return e;switch(e.action){case"snapshot":return{...e,value:wB(e.value)};case"delta":return{...e,value:RB(e.value)};default:return e}}function wB(e){if(!q0(e))return e;let t={};for(let n in e)t[n]=My(e[n]);return t}function RB(e){return q0(e)?{...e,pre:Ly(e.pre),post:Ly(e.post)}:e}function Ly(e){return e===null?null:My(e)}function My(e){if(!q0(e))return e;let t={...e};return delete t.config,t}function q0(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}var z0="beepflow://resource-schemas/",wt={type:"number",description:"Nanoseconds since Unix epoch. Omit updatedAt on creates and manual edits unless preserving an existing value; replicated state updates it after accepted writes."},ie={type:"string"},ji={type:"number"},By={type:"integer"},Ii={type:"boolean"};var Sp={type:"object",additionalProperties:ie},W0={type:"object",additionalProperties:Ii},yp={type:"object",additionalProperties:{type:"object",additionalProperties:Ii,properties:{list:Ii,detail:Ii,create:Ii,edit:Ii,delete:Ii,authorize:Ii}}},xu=["boolean","string","number","datetime","map","binary","wildcard","list of boolean","list of string","list of number","list of datetime","list of map","list of binary","list of wildcard"],Uy=["ManualTick","AerospikeSet","ApacheKafkaTopic","MQTTTopic","KaggleFile","RabbitMQQueue","RabbitMQStream","QdrantCollection","BaseVectorCollection","BaseEventCollection","BaseLookupCollection","GorgiasTicketsView","GoogleDriveFile"],Ou={anyOf:[Ii,{type:"null"}]},DB=["Use resource_query first when editing existing items; upsert sends whole item state, not a JSON patch. Preserve unchanged fields.","Omit updatedAt on creates and manual edits unless preserving an existing value; replicated state updates it after accepted writes."];function Mt(e,t,n){let r=`${z0}${e}`;return{resource:e,uri:r,sourceType:t,notes:DB,itemSchema:{$schema:"https://json-schema.org/draft/2020-12/schema",title:`Beepflow ${e} item`,type:"object",additionalProperties:!1,required:n.required,properties:n.properties,...n.defs?{$defs:n.defs}:{}}}}var Vy=Mt("note-runner-destinations","frontend/src/spaces/types.ts:NoteRunnerDestination",{required:["id","ownerEmail","name","computer","agent"],properties:{id:ie,updatedAt:wt,ownerEmail:ie,name:ie,computer:ie,agent:{type:"string",enum:["codex","claude"]},lastSeen:wt,activeExecutionId:ie}});var qy=Mt("page-note-executions","frontend/src/tabs/types.ts:PageNoteExecution",{required:["id","ownerEmail","destinationId","spaceId","state","notes"],properties:{id:ie,updatedAt:wt,createdAt:wt,ownerEmail:ie,destinationId:ie,spaceId:ie,spaceName:ie,agent:{type:"string",enum:["codex","claude"]},state:{type:"string",enum:["preparing","unclaimed","claimed","running","unknown","completed","failed"]},notes:{type:"array",items:{type:"object",additionalProperties:!1,required:["pageId","noteId","revision"],properties:{pageId:ie,noteId:ie,revision:ie,createdAt:wt}}},sessionId:ie,result:ie,error:ie}});var K0={$ref:"#/$defs/operatorType"},CB={type:"object",additionalProperties:!1,required:["value"],properties:{value:{description:"Raw option value written to node input literal when selected."},label:{...ie,description:"Optional label shown in operator input dropdowns."}}},xB={type:"object",additionalProperties:!1,required:["type"],properties:{type:{type:"string",enum:xu,description:'Blueprint value type name. Use "list of X" for lists, never "list".'},options:{anyOf:[{type:"array",items:CB},{type:"null"}],description:"Allowed literal values for dropdown-style widgets."},isArray:{type:"boolean",description:"Whether this pin accepts multiple values."},allowedTypes:{anyOf:[{type:"array",items:K0},{type:"null"}],description:"Allowed concrete types for wildcard pins."},linkType:{...ie,description:"Type-linking group used to propagate wildcard types across pins."},widgetType:{...ie,description:'Frontend input widget id. Supports built-in widgets, integration selectors, and "<IntegrationType>-connection" connection dropdowns.'},defaultValue:{description:"Default literal value used when node input omits a value."},defaultValueForArrayElement:{description:"Default literal value for newly added array input elements."}}},OB={type:"object",additionalProperties:!1,required:["name","doc","type"],properties:{name:{...ie,description:"Output pin name."},doc:{...ie,description:"Operator output documentation shown to users."},type:K0}},kB={type:"object",additionalProperties:!1,required:["name","doc","type"],properties:{name:{...ie,description:"Input pin name; node inputs are keyed by this value."},doc:{...ie,description:"Operator input documentation shown to users."},type:K0,isLiteral:{...Ii,description:"Whether this input must be edited as literal value instead of upstream connection."}}},zy=Mt("blueprint-operators","frontend/src/tabs/blueprint/types.ts:Operator",{required:["id","type","name","doc","categoryPath","inputs"],properties:{id:{...ie,description:"Stable registered operator id referenced by blueprint nodes."},type:{...ie,description:"Operator kind, usually function, variable, or localVariable."},name:{...ie,description:"Display name used in operator search and node labels."},aliases:{type:"array",items:ie,description:"Additional search terms for this operator."},doc:{...ie,description:"Operator documentation shown to users."},categoryPath:{type:"array",items:ie,description:"Menu category path segments."},inputs:{type:"array",items:kB,description:"Input pins in display order."},output:{anyOf:[OB,{type:"null"}],description:"Output pin definition, or null for side-effect-only operators."},isDeprecated:{...Ii,description:"Whether operator is deprecated and hidden from default search."},hidden:{...Ii,description:"Whether operator is hidden from menus and search."},canMock:{...Ii,description:"Whether test mode can mock this operator."},updatedAt:wt},defs:{operatorType:xB}});var IB={type:"object",additionalProperties:!1,properties:{x:{...ji,description:"Optional node world x coordinate in blueprint editor. For new nodes, never specify style.x; omit it so the frontend can place nodes after measuring dimensions."},y:{...ji,description:"Optional node world y coordinate in blueprint editor. For new nodes, never specify style.y; omit it so the frontend can place nodes after measuring dimensions."},title:{...ie,description:"Optional display title shown on node."},comment:{...ie,description:"Optional user-authored node comment."}}},PB={type:"object",additionalProperties:!0,description:"Blueprint view node. For new nodes, never specify style.x or style.y; omit coordinates so the frontend can place nodes after measuring dimensions. Known visualization blocks are intentionally accepted as additional properties.",required:["id"],properties:{id:{...ie,description:"Node id; must match key in blueprint view nodes record."},style:IB}},Wy=Mt("blueprint-views","frontend/src/tabs/blueprint/types.ts:BlueprintView",{required:["id","nodes"],properties:{id:{...ie,description:"Blueprint tab id; must match tabs and blueprints resource id."},updatedAt:wt,nodes:{type:"object",additionalProperties:PB,description:"Editor view state keyed by node id."}}});var Ky={type:"object",properties:{name:ie,type:ie,value:ie},description:"DNS record the domain owner publishes in their own zone."},Gy=Mt("domains","frontend/src/domains/types.ts:Domain",{required:["id","spaceId"],properties:{id:{...ie,description:"Hostname serving a site, such as www.acme.com, or a single label under beepflow.app such as acme.beepflow.app. Lowercase, no port and no trailing dot, at least two labels, and never beepflow.com, cname-beepflow.app or a host under either. A beepflow.app subdomain is covered by the certificate Beepflow already holds and serves as soon as it is registered; reserved labels such as www and api, and any label starting with space-, are rejected. Registering a hostname is exclusive across every space. Pages served here must keep tokens in localStorage, never in cookies: beepflow.app is a shared parent domain, so a cookie scoped to it is readable by every other site published under it."},updatedAt:wt,spaceId:{...ie,description:"Space owning the domain. Cannot change after create, and a space holds at most 10 of each kind, counted separately for beepflow.app subdomains and for domains the space owns."},siteId:{...ie,description:"Site whose routes this domain serves, which must belong to the same space. Empty while the domain is registered but serves no site, which holds the hostname and answers 404. A site being deleted empties this rather than releasing the domain."},mcpServerId:{...ie,description:"MCP server of the same space answering on this domain at /mcp; every other path stays with the site. Empty while the domain serves no MCP server."},openAIAppsChallenge:{...ie,description:"Exact plain-text token served at /.well-known/openai-apps-challenge for OpenAI plugin domain verification. Empty disables the response."},status:{...ie,description:'Read only: pending-dns, verifying, active or failed. A beepflow.app subdomain is active from the moment it is registered. Written by the backend as it settles the domain against Cloudflare, and only an active domain attached to a site is served. Writing a value of your own here, or in any field below, is rejected. A create must still carry every one of them at its zero value ("" for strings, 0 for checkedAt, and a record of empty strings), because an item that does not match the stored one fails the precondition of every delta the backend later sends for it.'},statusChangedAt:{type:"number",description:"Read only: milliseconds since Unix epoch of the last status transition."},cloudflareHostnameId:{...ie,description:"Read only: custom hostname backing this domain at the edge."},ownershipRecord:{...Ky,description:"Read only: record proving the claim on the domain."},certificateRecord:{...Ky,description:"Read only: CNAME delegating the certificate challenge to Cloudflare, which writes the challenge that changes at the delegated name so the owner publishes this one once and never again."},hostnameVerified:{type:"boolean",description:"Read only: whether the edge took the hostname into its zone, read from the edge rather than from DNS, so it lags a record that is already published and says nothing about which record it is waiting on."},siteRecordPublished:{type:"boolean",description:"Read only: whether the CNAME onto the serving zone resolves, read from DNS. A provider that answers the record as a proxy, which an apex on Cloudflare always does because it flattens the canonical name away, hides it from any reader; there it counts as published once the edge has taken the hostname, or once the ownership and certificate records both resolve."},ownershipRecordPublished:{type:"boolean",description:"Read only: whether the TXT record proving the claim resolves with the value the edge asked for, read from DNS. True as well once the edge stops naming the record, which is how it reports a claim it has already read."},challengeDelegated:{type:"boolean",description:"Read only: whether the certificate record resolves to the delegated name, read from DNS rather than from the edge."},challengeRecordProxied:{type:"boolean",description:"Read only: whether the certificate record is proxied instead of resolving directly to the delegated name, which blocks certificate issuance."},verificationMessage:{...ie,description:"Read only: what the edge is waiting on, or why it stopped. Present while a domain is healthy and still pending, so it does not by itself mean failure."},checkedAt:{type:"number",description:"Read only: milliseconds since Unix epoch of the last check against the edge."}}});var Hy=Mt("email-domains","frontend/src/email-domains/types.ts:EmailDomain",{required:["id","spaceId"],properties:{id:{...ie,description:"Domain blueprints send mail from, such as acme.com or mail.acme.com. Lowercase, no port and no trailing dot, at least two labels, and never beepflow.com, beepflow.app, cname-beepflow.app or a host under any of them. Registering one is exclusive across every space, and the workspace holds at most 10. This is separate from the domains resource: registering a domain here signs mail, and says nothing about serving pages."},updatedAt:wt,spaceId:{...ie,description:"Space the domain is filed under, which says who may see, register and release it, the way the space on a connection does. It never says which blueprints may send from it: a blueprint of any space sends from this domain as long as whoever started it can see this space. Unlike a served domain this can change after create, because a domain moves between spaces without anything at SES changing; the write is refused unless the caller holds both the space it leaves and the space it joins."},status:{...ie,description:'Read only: pending-dns, verifying, active or failed. Only an active domain can be sent from. Written by the backend as it settles the domain against SES, and writing a value of your own here, or in any field below, is rejected. A create must still carry every one of them at its zero value ("" for strings, 0 for numbers, {} for dkimRecords), because an item that does not match the stored one fails the precondition of every delta the backend later sends for it.'},statusChangedAt:{type:"number",description:"Read only: milliseconds since Unix epoch of the last status transition."},dkimRecords:{type:"object",additionalProperties:ie,description:"Read only: the CNAME records the owner publishes to prove the domain and sign its mail, keyed by the name each is published at, with the value each resolves to. Three of them, named <token>._domainkey.<domain>. Releasing the domain and registering it again mints new ones."},dkimRecordsPublished:{type:"boolean",description:"Read only: whether every DKIM record resolves, read from DNS rather than from SES, so it moves as soon as the owner publishes them rather than when SES next looks."},verificationMessage:{...ie,description:"Read only: why the domain stopped, such as records SES could not find in time, or a domain already sending from this account outside Beepflow."},checkedAt:{type:"number",description:"Read only: milliseconds since Unix epoch of the last check against SES."},bounceCount:{type:"number",description:'Read only: bounces received for mail sent from this domain. Written from the events SES publishes, which are also written into the email-bounces collection of the space BaseEvent connection named "Email Events".'},complaintCount:{type:"number",description:"Read only: complaints received for mail sent from this domain, written alongside the email-complaints collection of the same connection."},lastBounceAt:{type:"number",description:"Read only: milliseconds since Unix epoch of the most recent bounce."},lastComplaintAt:{type:"number",description:"Read only: milliseconds since Unix epoch of the most recent complaint."}}});var Tp={type:"string",description:"Integration resource type processed by this blueprint, such as ApacheKafkaTopic or QdrantCollection. Call integration_blueprint_contexts_list first; use only resource types returned by that tool. The returned executionKind determines trigger choice: managed resources use executor, finite resources choose event-first among blueprint, webhook, and manual, and fall back to cron or loop only when no event exists to react to."},Ap={type:"object",additionalProperties:!0,description:"Integration-specific config for context.type. Start from contextTemplate.config returned by integration_blueprint_contexts_list, fill every configFields item where required=true, and preserve optional defaults such as consumerGroupId, clientId, parser, offsetResetStrategy, orderBy, or webhook topic maps when provided."},wp={type:"object",additionalProperties:!1,required:["enabled"],properties:{enabled:{type:"boolean",description:"Must be true. Backend ignores this trigger branch when enabled is false."}}},G0={...wp.properties.enabled,enum:[!0]},NB=["auto","application/json","text/plain","text/html","application/xml","application/x-www-form-urlencoded","multipart/form-data","application/octet-stream"],FB={type:"object",additionalProperties:!1,required:["count"],description:"Run immediately when explore runtime starts or restarts. Use for finite resource sampling, one-shot imports, and ad hoc reads.",properties:{count:{type:"integer",minimum:1,description:"Number of executions to run back-to-back. Frontend default is 1; backend coerces values below 1 to 1."}}},LB={type:"object",additionalProperties:!1,required:["expression"],description:"Run on a seconds-field cron schedule while explore runtime is active. Use only when no event exists to react to, such as an external finite source with no stream, webhook, or upstream blueprint. Do not use cron to keep derived collections in sync with records another blueprint produces; consume the event instead.",properties:{expression:{type:"string",description:"Cron expression with six fields including seconds, parsed by robfig/cron. Example: 0 */5 * * * * runs every five minutes."},timezone:{type:"string",description:"Optional IANA timezone name such as UTC or America/New_York. Backend uses UTC when omitted or empty."}}},MB={type:"object",additionalProperties:!1,required:["delayMs"],description:"Run immediately, then wait delayMs before repeating while explore runtime is active. Use only for deliberate fixed-delay polling, when the source offers no stream, webhook, or upstream blueprint.",properties:{delayMs:{type:"integer",minimum:1,description:"Delay between executions in milliseconds. Must be positive to avoid a hot loop."}}},$y={...wp,description:"Wait while active until another blueprint or Trigger Self operator invokes this blueprint. Trigger argument is available through Get Trigger Argument. Directed invocation only: the trigger topic is created on start seeking to its end and deleted on stop, so invocations sent while this blueprint is inactive are lost. For durable fan-out, publish into a BaseEvent collection and consume it with an executor trigger."},BB={type:"object",additionalProperties:!1,required:["mode"],description:"Who may call this webhook. The gateway enforces it before the blueprint runs, and a webhook without auth is rejected.",properties:{mode:{type:"string",enum:["public","workspace","space-token"],description:"workspace requires a Beepflow access token whose user can read this blueprint tab; use it for webhooks a Beepflow page or the dashboard calls, and it is the default for new webhooks. space-token requires a token minted by another blueprint in this space through the Issue Token operator; use it for pages serving the customer's own end users, and read the identity from trigger auth.claims. public accepts any caller; use it only when an outside provider posts to this URL and cannot send a token."},allowedOrigins:{type:"array",items:{type:"string"},description:"Extra browser origins allowed to call this webhook, such as https://app.partner.com. Beepflow pages of the owning space are always allowed, so omit this unless a site outside Beepflow calls the webhook from a browser."}}},H0={type:"object",additionalProperties:!1,required:["enabled","auth"],description:"Wait while active for generic GET/POST /:tabId/trigger HTTP calls. Request method, URL, parsed body, headers, auth, and timestamp become trigger argument. Webhook URL is `${status.backendUrl}/${encodeURIComponent(blueprint.id)}/trigger` and runs only while blueprint is active in explore mode. Call it with blueprint_webhook_call, which sends the MCP credential.",properties:{enabled:wp.properties.enabled,auth:BB,timeoutMs:{type:"integer",minimum:0,description:"Maximum synchronous webhook execution time in milliseconds. Backend uses 30000 when omitted or below 1."},contentType:{type:"string",enum:["",...NB],description:"Request body parser. Omit, leave empty, or use auto to infer from incoming Content-Type, then fall back to JSON sniffing, UTF-8 text, then binary. Not for provider webhook resources managed through BaseEvent; use BaseEventCollection."},description:{type:"string",description:"What this webhook does, shown to callers that discover it: an mcp-servers item listing this blueprint as a tool serves it as the tool description."},annotations:{type:"object",additionalProperties:!1,required:["readOnlyHint","destructiveHint","openWorldHint"],description:"MCP safety hints describing whether this webhook only reads, can cause irreversible changes, or changes external systems.",properties:{readOnlyHint:{type:"boolean"},destructiveHint:{type:"boolean"},openWorldHint:{type:"boolean"}}},inputSchema:{type:"object",additionalProperties:!0,description:"JSON Schema (draft 7 default) the gateway validates the JSON request body against before the blueprint runs; violating requests are rejected with the violations and never reach the blueprint. Also served as the tool inputSchema when an mcp-servers item lists this blueprint. Only meaningful for JSON bodies; leave unset for other content types."},outputSchema:{type:"object",additionalProperties:!0,description:"JSON Schema describing the JSON body the webhook response node returns. Not enforced; served as the tool outputSchema when an mcp-servers item lists this blueprint."}}},Xy={...wp,description:"Use for managed integration resources where runtime owns stream, event, webhook, or poll lifecycle, such as ApacheKafkaTopic, RabbitMQStream, BaseEventCollection, and MQTTTopic. Also use it for internal blueprint-to-blueprint events published into a BaseEvent collection, which is the durable, decoupled default for derived and fan-out work."},Ep={type:"object",additionalProperties:!1,minProperties:1,maxProperties:1,description:"Exactly one trigger branch, chosen event-first: executor for executionKind=managed resources and for BaseEvent collections carrying internal events, blueprint for directed invocation by a known caller, webhook for generic GET/POST /:tabId/trigger HTTP calls, manual for ad hoc/sample/start-once runs and one-shot backfills, and cron or loop last, only when no event exists to react to.",properties:{manual:FB,cron:LB,loop:MB,blueprint:$y,webhook:H0,executor:Xy},oneOf:[{required:["manual"]},{required:["cron"]},{required:["loop"]},{required:["blueprint"]},{required:["webhook"]},{required:["executor"]}]},Yy={...Ep,properties:{...Ep.properties,blueprint:{...$y,properties:{enabled:G0}},webhook:{...H0,properties:{...H0.properties,enabled:G0}},executor:{...Xy,properties:{enabled:G0}}}};var UB={type:"object",additionalProperties:!1,required:["literal"],properties:{literal:{description:"Literal JSON value for this input element; null is valid when connected upstream."},nodeId:{...ie,description:"Upstream node id when this value is connected to another node output."},operatorInputId:{...ie,description:"Upstream output pin name used by this connection."},nodeInputIndex:{...ie,description:'CRDT list index of upstream output value. Use "0.5" for any connected node output.'}}},VB={type:"object",additionalProperties:!1,required:["values"],properties:{isArray:{...Ou,description:"Whether input accepts multiple values for one operator input."},values:{type:"object",additionalProperties:UB,description:"Input values keyed by CRDT list index strings."},type:{type:"string",enum:xu,description:"Resolved input type override."},forceZipping:{...Ou,description:"Force list zipping behavior for multiple upstream values."},listInputMode:{type:"string",enum:["list","items"],description:"Whether this input receives one whole list value or assembles a list from item values."}}},qB={type:"object",additionalProperties:!1,required:["id","operatorId","inputs"],properties:{id:{...ie,description:"Stable node id; must match key in blueprint nodes record."},operatorId:{...ie,description:"Id of registered blueprint operator this node executes."},inputs:{type:"object",additionalProperties:VB,description:"Node inputs keyed by operator input name."},mockNever:{...Ou,description:"Disable mocking for this node."},skipBehavior:{type:"string",enum:["skip","null"],description:"Behavior when upstream value is skipped."},disabled:{...Ou,description:"Whether this node and downstream dependent nodes are disabled."},outputType:{type:"string",enum:xu,description:"Resolved output type for wildcard operators."}}},zB={type:"object",additionalProperties:!1,required:["type","trigger"],properties:{type:Tp,trigger:Yy,config:Ap}},jy=Mt("blueprints","frontend/src/tabs/blueprint/types.ts:Blueprint",{required:["id","mode","nodes","context"],properties:{id:{...ie,description:"Blueprint tab id; must match tabs resource id."},updatedAt:wt,mode:{type:"string",enum:["test","explore"],description:'Execution mode; result id is blueprint id plus "-test" or "-explore".'},nodes:{type:"object",additionalProperties:qB,description:"Blueprint nodes keyed by node id."},context:zB,testRecordsAmount:{...By,description:"Target number of test records to keep for test mode."},recomputeOnChange:{type:"string",enum:["always","manual"],description:"Whether edits automatically restart execution."},mockNever:{...Ii,description:"Global flag to disable node mocking."},desiredState:{type:"string",enum:["active","inactive"],description:"Requested runtime state for test or explore mode."},runtimeActionId:{...ie,description:"Backend-owned id for latest explicit start or stop request; preserve on unrelated edits."},updatedBy:{...ie,description:"Backend-owned email of whoever last changed this blueprint; attribution only."},startedBy:{...ie,description:"Backend-owned email of whoever last started this blueprint; its executions act as that person."}}});var WB=["Aerospike","ApacheKafka","MQTT","Kaggle","FacebookAds","RabbitMQ","Shopify","ShopifyApp","YouTube","Webshare","Playwright","AWS","Qdrant","OpenAI","BaseVector","BaseEvent","BaseLookup","Gorgias","LMStudio","OpenRouter","VoyageAI","GoogleDrive","GoogleSheets","Gmail","DiscordChannelWebhook"],Qy=Mt("connections","frontend/src/integrations/types.ts:Connection",{required:["id","label","type","spaceId"],properties:{id:ie,updatedAt:wt,label:ie,type:{type:"string",enum:WB},spaceId:ie}});var Jy=Mt("roles","frontend/src/auth/roles/types.ts:Role",{required:["id","label","authorizations"],properties:{id:ie,updatedAt:wt,label:ie,authorizations:yp}});var Zy=Mt("pages","frontend/src/tabs/types.ts:Page",{required:["id","sourceUrl","distUrl"],properties:{id:{...ie,description:"Page tab id; must match tabs resource id."},updatedAt:wt,sourceUrl:{...ie,description:"File-service URL for raw source HTML."},distUrl:{...ie,description:"File-service URL for optimized HTML rendered in a sandbox iframe."}}});var KB={type:"object",additionalProperties:!1,required:["selector","tagName"],properties:{selector:{...ie,description:"CSS selector the element answered to in the rendered page."},tagName:ie,attributes:{anyOf:[Sp,{type:"null"}],description:"id, class, name, role, aria-label, href, src, alt and every data-* of the element. A page builds most of its dom from script, so search the source html by these before trusting the selector."},ancestorChain:{anyOf:[{type:"array",items:ie},{type:"null"}],description:"tag#id.class of the ancestors, outermost first."},textSnippet:{...ie,description:"Start of the element text as the viewer saw it."},htmlSnippet:{...ie,description:"Start of the element outerHTML as rendered."},pageQuery:{...ie,description:"Page url query the note was placed under."},viewportWidth:ji,viewportHeight:ji,viewportMode:{type:"string",enum:["","desktop","mobile"],description:"Dashboard preview mode the note was taken in; reproduce the page at this viewport when addressing the note. Empty on notes older than the toggle."},rect:{type:"object",additionalProperties:!1,properties:{x:ji,y:ji,width:ji,height:ji}}}},GB={type:"object",additionalProperties:!1,required:["id","note","status","target"],properties:{autoRun:{type:"boolean"},revision:ie,resolvedRevision:ie,id:ie,note:{...ie,description:"What the viewer asked for at this element."},status:{type:"string",enum:["open","resolved"]},createdAt:wt,createdByEmail:ie,resolvedAt:wt,resolvedByEmail:ie,target:KB}},eE=Mt("page-annotations","frontend/src/tabs/types.ts:PageAnnotation",{required:["id","notesById"],properties:{id:{...ie,description:"Page tab id; must match tabs resource id."},updatedAt:wt,notesById:{type:"object",additionalProperties:GB,description:"Notes viewers placed on elements of this page, keyed by note id."}}});var tE=Mt("sites","frontend/src/sites/types.ts:Site",{required:["id","name","spaceId","pageTabIdByPath"],properties:{id:{...ie,description:"Site id, opaque and generated at create. It names nothing outside the workspace: the hostnames a site answers on are the domains registered against it in the domains resource, so a site created here is reachable only once a domain names it."},name:{...ie,description:"What the site is called, up to 100 characters. Two sites of one space may share a name, because the id is what tells them apart."},updatedAt:wt,spaceId:{...ie,description:"Space owning the site. Every routed page tab must belong to this space, and the value cannot change after create."},pageTabIdByPath:{type:"object",additionalProperties:ie,description:'Page tab id by request path, at most 100 entries. Paths start with "/", carry no query or fragment, and have no trailing slash except the root path "/".'}}});var nE=Mt("mcp-servers","frontend/src/mcp-servers/types.ts:McpServer",{required:["id","name","spaceId","toolTabIdByName"],properties:{id:{...ie,description:'Server id, 1-64 characters of [a-zA-Z0-9_-], never "oauth". It is the last path segment of the endpoint POST ${backendUrl}/mcp/<id>, reachable on the app host and on every domain of the workspace, and cannot change after create.'},name:{...ie,description:"What the server calls itself in the MCP initialize response, up to 100 characters."},updatedAt:wt,spaceId:{...ie,description:"Space owning the server. Every tool blueprint and OAuth access token must belong to this space, and the value cannot change after create."},auth:{type:"object",additionalProperties:!1,required:["mode"],description:"Who may call this server. The gateway enforces it before any tool runs, and a server without auth rejects every call. The caller identity reaches each tool blueprint as trigger auth, in the same shape webhook triggers receive.",properties:{mode:{type:"string",enum:["public","workspace","space-token"],description:"space-token uses OAuth when authorizeUrl is set, exchanging a token minted by the space's login blueprint for an MCP access token bound to this server; without authorizeUrl, callers provide the end-user token directly. Tools read the identity from trigger auth.claims. workspace requires a Beepflow access token whose user can read this server. public accepts any caller."},allowedOrigins:{type:"array",items:{type:"string"},description:"Extra browser origins allowed to call this server. Beepflow pages of the owning space are always allowed."},authorizeUrl:{...ie,description:"Absolute URL of the login page remote OAuth clients such as claude.ai are sent to, usually a page published on a site of this space. The page receives the pending request in its mcp_authorize query parameter, signs the end user in through its own login blueprint, posts {authorizeRequest, token} to /api/mcp/oauth/complete, and navigates to the returned redirectUrl. Only meaningful with mode space-token; without it the server offers no OAuth."}}},toolTabIdByName:{type:"object",additionalProperties:ie,description:"Webhook blueprint tab id by tool name, at most 100 entries. Names are 1-128 characters of [a-zA-Z0-9_-]. Each tab must be a blueprint of the same space with a webhook trigger; its tab name, trigger description, schemas and annotations describe the listed tool, and tools/call runs it like a POST webhook call. A tool answers only while its blueprint is active."}}});var rE=Mt("schemas","frontend/src/integrations/types.ts:Schema",{required:["id","type","connectionId","path","schema"],properties:{id:ie,updatedAt:wt,type:{type:"string",enum:Uy},connectionId:ie,path:Sp,schema:{type:"object",additionalProperties:{type:"string",enum:xu}},keySerdeType:{type:"string"},valueSerdeType:{type:"string"}}});var iE=Mt("space-join-requests","frontend/src/spaces/space-join-requests/types.ts:SpaceJoinRequest",{required:["id","createdAt","requestedBy","kind","status","spaceId","userId"],properties:{id:ie,createdAt:{type:"number",description:"Nanoseconds since Unix epoch."},updatedAt:wt,requestedBy:ie,kind:{type:"string",enum:["invite","request"]},status:{type:"string",enum:["pending","granted","denied"]},spaceId:ie,userId:ie}});var oE=Mt("spaces","frontend/src/spaces/types.ts:Space",{required:["id","label"],properties:{id:ie,updatedAt:wt,label:ie,noteRunnerDestinationId:ie,activeNoteExecutionId:{...ie,readOnly:!0},thumbnailUrl:ie,description:ie,isUserSpace:Ou}});var aE=Mt("tabs","frontend/src/tabs/types.ts:Tab",{required:["id","name","order","type","parent","spaceId"],properties:{id:{...ie,description:"Stable tab id. Blueprint and page tabs normally have matching records keyed by this id."},updatedAt:wt,name:ie,order:ji,type:{type:"string",enum:["blueprint","folder","page"],description:"Navigation item kind; blueprint and page tabs normally have matching records."},parent:ie,spaceId:ie}});var sE=Mt("user-locations","frontend/src/workspace/user-location/types.ts:UserLocation",{required:["id"],properties:{id:ie,updatedAt:wt,tab:{type:"object",additionalProperties:!1,required:["id"],properties:{id:ie}},blueprint:{type:"object",additionalProperties:!1,required:["id"],properties:{id:ie,worldPosition:{type:"object",additionalProperties:!1,required:["x","y"],properties:{x:ji,y:ji}}}}}});var uE=Mt("users","frontend/src/auth/users/types.ts:User",{required:["id","displayName","roleIds","authorizations","spaces"],properties:{id:ie,updatedAt:wt,displayName:ie,avatarUrl:ie,roleIds:W0,authorizations:yp,spaces:W0}});var Rp=[uE,Jy,oE,aE,Zy,eE,Vy,qy,tE,Qy,rE,jy,Wy,Gy,Hy,nE,zy,sE,iE];function Dp(e){return Rp.find(t=>t.resource===e)}var $0=[Xr("users","Workspace users and authorizations.",!0),Xr("roles","Workspace roles and resource authorizations.",!0),Xr("spaces","Workspace spaces.",!0),Xr("tabs","Tabs and folders visible to authorized user; blueprint and page tabs normally share ids with matching records.",!0),Xr("pages","Untrusted single-page HTML source and optimized file URLs keyed by matching page tab id.",!0),Xr("page-annotations","Notes viewers placed on elements of a page in the dashboard, keyed by matching page tab id.",!0),Xr("note-runner-destinations","Installed note runner destinations owned by the signed-in user. Registration and active execution fields are maintained by the backend.",!1),Xr("page-note-executions","Claimed page-note batches and their session outcomes. Execution state is maintained by the backend; open notes remain the source of pending work.",!1),Xr("sites","Public sites keyed by id; each maps request paths of one space to page tab ids and carries no hostname of its own, so it is served without sign in on whichever domains are registered against it.",!0),Xr("domains","Hostnames a space registered, keyed by hostname; every host a site or MCP server is served on is one of these, whether a beepflow.app subdomain or a domain the space owns. An active domain can serve a site's pages, an MCP endpoint and an OpenAI verification challenge. Reconciliation status and DNS fields are read-only.",!0),Xr("email-domains","Domains the workspace proved it holds so blueprints can send mail from them, keyed by the domain. Registering one hands back three DKIM CNAME records to publish; once they resolve the domain signs mail and the Send Email from Your Domain operator accepts a From address under it. The space on the row says who may see, register and release the domain, the way it does on a connection, and never which blueprints may send from it: a blueprint of any space sends from any verified domain whoever started it may see. Separate from the domains resource, which serves pages instead. Only id and spaceId are writable, and spaceId can change so a domain moves between spaces.",!0),Xr("mcp-servers","HTTP MCP servers keyed by id; each publishes webhook blueprints of one space as MCP tools at POST ${backendUrl}/mcp/<id>. toolTabIdByName maps each tool name to a webhook blueprint tab; the tool's description, schemas and annotations live on that blueprint's webhook trigger, so the server holds only naming, auth and grouping. A space-token server with authorizeUrl exchanges the site's end-user login token for an MCP access token bound to the requested server and resource.",!0),Xr("connections","Read-only integration connections without secret-bearing config; config is redacted and cannot be read through MCP.",!1),Xr("schemas","Integration schema metadata.",!0),Xr("blueprints","Blueprint definitions keyed by matching blueprint tab id.",!0),Xr("blueprint-views","Blueprint editor view state keyed by matching blueprint tab id.",!0),Xr("blueprint-operators","Registered blueprint operator definitions.",!1),Xr("user-locations","Live user location records.",!0),Xr("space-join-requests","Space invitation and join requests.",!0)],HB=["tabs","pages","page-annotations","blueprints","blueprint-views"],X0=new Set(HB),ku=$0.filter(e=>!X0.has(e.name)),rf=ku.map(e=>e.name),cE=$0.map(e=>e.name);function $B(e){return $0.find(t=>t.name===e)}function lE(e){return ku.find(t=>t.name===e)}function fE(e){if($B(e))return e;throw new Error(`unsupported resource: ${e}`)}function Y0(e){if(X0.has(e))throw new Error(`dedicated resource ${e}: use tab and blueprint intent tools instead of generic resource_* tools`);if(lE(e))return e;throw new Error(`unsupported resource: ${e}`)}function j0(e){let t=lE(e);if(X0.has(e))throw new Error(`dedicated resource ${e}: use tab and blueprint intent tools instead of generic resource_* tools`);if(!t)throw new Error(`unsupported resource: ${e}`);if(!t.writable)throw new Error(`resource is read-only: ${e}`);return t.name}function Xr(e,t,n){return{name:e,description:t,writable:n,schemaUri:`${z0}${e}`}}function Yr(){return Date.now()*1e6}function of(e,t){if(e===null&&t===null)return{pre:null,post:null};if(e===null&&t!==null)return{pre:null,post:t};if(e!==null&&t===null)return{pre:e,post:null};if(typeof e!="object"||typeof t!="object")return e!==t?{pre:e,post:t}:{pre:null,post:null};if(Array.isArray(e)||Array.isArray(t))return{pre:null,post:null};let{pre:n,post:r}=dE(e,t);return n===null&&r===null?{pre:null,post:null}:{pre:n,post:r}}function dE(e,t){let n={},r={},i=!1,o=new Set([...Ka(e),...Ka(t)]);for(let s of o){if(s==="updatedAt")continue;let c=e[s],f=t[s];if(Array.isArray(c)||Array.isArray(f)){(Array.isArray(c)!==Array.isArray(f)||!Cp(c,f))&&(n[s]=c===void 0?null:c,r[s]=f===void 0?null:f,i=!0);continue}let h=Bs(c),g=Bs(f);if(!(s in t))h||(n[s]=c,r[s]=null,i=!0);else if(!(s in e))g||(n[s]=null,r[s]=f,i=!0);else{if(h&&g)continue;if(h&&!g)n[s]=null,r[s]=f,i=!0;else if(!h&&g)n[s]=c,r[s]=null,i=!0;else{let{pre:_,post:S}=XB(c,f);(_!==void 0||S!==void 0)&&(_!==void 0&&(n[s]=Q0(_)),S!==void 0&&(r[s]=Q0(S)),i=!0)}}}return i?Ka(n).length===0&&Ka(r).length===0?{pre:null,post:null}:Ka(n).length===0?{pre:null,post:r}:Ka(r).length===0?{pre:n,post:null}:{pre:n,post:r}:{pre:null,post:null}}function XB(e,t){if(YB(e,t))return{pre:void 0,post:void 0};let n=Bs(e),r=Bs(t);if(n&&r)return{pre:void 0,post:void 0};if(n)return{pre:null,post:t};if(r)return{pre:e,post:null};if(Array.isArray(e)||Array.isArray(t))return{pre:void 0,post:void 0};if(typeof e!=typeof t)return{pre:e,post:t};if(typeof e=="object"&&e!==null&&typeof t=="object"&&t!==null){let{pre:i,post:o}=dE(e,t);return i===null&&o===null?{pre:void 0,post:void 0}:{pre:i===null?void 0:i,post:o===null?void 0:o}}return{pre:e,post:t}}function Bs(e){return e==null?!0:typeof e=="object"&&e!==null?Array.isArray(e)?e.length===0:Ka(e).length===0:!1}function YB(e,t){return Bs(e)&&Bs(t)?!0:Cp(e,t)}function Cp(e,t){if(e===t)return!0;if(e==null||t==null||typeof e!="object"||typeof t!="object")return!1;let n=Ka(e),r=Ka(t);if(n.length!==r.length)return!1;for(let i of n)if(!(i in t)||!Cp(e[i],t[i]))return!1;return!0}function xp(e,t){return t.pre===null?e===null:e===null||typeof e!="object"||Array.isArray(e)?!1:pE(e,t.pre)}function pE(e,t){for(let n in t)if(n!=="updatedAt"&&!jB(e[n],t[n]))return!1;return!0}function jB(e,t){return t===null||QB(t)?Bs(e):e===void 0?!1:typeof t=="object"&&t!==null&&!Array.isArray(t)&&typeof e=="object"&&e!==null&&!Array.isArray(e)?pE(e,t):Cp(e,t)}function QB(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Ka(e).length===0}function Q0(e){if(e==null)return null;if(typeof e=="object"&&e!==null){if(Array.isArray(e)&&e.length===0)return null;if(!Array.isArray(e)){let t={},n=!1;for(let r in e)t[r]=Q0(e[r]),t[r]!==void 0&&(n=!0);return n?t:null}}return e}function J0(e,t){let n=Z0(e,t);return n!==null&&typeof n=="object"&&!Array.isArray(n)&&(n.updatedAt=t.updatedAt),n}function Z0(e,t){return t.post===null?null:e===null?t.post:typeof e!="object"||Array.isArray(e)?t.post:mE(e,t.post)}function mE(e,t){let n={};for(let r in e)if(r in t){let i=t[r];if(i===null)continue;typeof i=="object"&&!Array.isArray(i)&&typeof e[r]=="object"&&!Array.isArray(e[r])&&e[r]!==null?n[r]=mE(e[r],i):n[r]=i}else n[r]=e[r];for(let r in t)!(r in e)&&t[r]!==null&&(n[r]=t[r]);return n}function Ka(e){let t=[];for(let n in e)t.push(n);return t}var hE="replicated-state",Op=class{ackedResources={};dirtyResources={};unauthorizedKeys={};loadingResources={};loadingPromises=new Map;loadedResources=new Set;registeredResources=new Set;resourceChangeListeners=new Set;snapshotWaiters=new Map;storage;socketSession;logger;inflightItems=new Map;constructor(t,n,r){this.storage=t,this.socketSession=n,this.logger=r}onResourceChange(t){return this.resourceChangeListeners.add(t),()=>this.resourceChangeListeners.delete(t)}registerResource(t){this.registeredResources.add(t),this.initializeResource(t)}isResourceRegistered(t){return this.registeredResources.has(t)}getRegisteredResources(){return Array.from(this.registeredResources)}setDirtyItems(t,n){this.registerResource(t),this.dirtyResources[t]=Qi(n)}setDirtyItem(t,n,r){if(this.registerResource(t),r===void 0){delete this.dirtyResources[t][n];return}this.dirtyResources[t][n]=Qi(r)}clearSessionState(){this.ackedResources={},this.loadingResources={},this.loadingPromises.clear(),this.loadedResources.clear(),this.inflightItems.clear();for(let t of this.registeredResources)this.dirtyResources[t]={},this.unauthorizedKeys[t]={},this.loadingResources[t]=!0,this.emitResourceChange(t)}async loadRegisteredResourcesFromStorage(){await Promise.all(Array.from(this.registeredResources,t=>this.loadResourceFromStorage(t)))}async hydrate(t,n){this.registerResource(t),await this.loadResourceFromStorage(t),this.logger.info(`Calculating lastUpdatedAtSeen from ${_E(this.ackedResources[t])} items`);let r=this.prepareSnapshotQuery(t,n);this.logger.info(`\u{1F4F8} ${t} requested with query:`,r),this.socketSession.send(hE,{resource:t,action:"snapshot",value:r})}hydrateAll(t){return this.hydrate(t,{all:!0})}async waitForSnapshot(t,n){await new Promise((r,i)=>{let o,s=()=>{clearTimeout(o),r()};o=setTimeout(()=>{this.snapshotWaiters.get(t)?.delete(s),i(new Error(`snapshot timeout for ${t}`))},n),this.snapshotWaiters.has(t)||this.snapshotWaiters.set(t,new Set),this.snapshotWaiters.get(t).add(s)})}processSocketEvent(t){switch(t.action){case"snapshot":this.applySnapshot(t.resource,t.value??{});break;case"delta":this.applyRemoteDelta(t);break}}async upsertItem(t,n){this.registerResource(t);let r=this.getAckedValue(t,n.id),i=of(r,n);return i.pre===null&&i.post===null?!0:this.sendDelta(t,n.id,i,n)}async deleteItem(t,n){this.registerResource(t);let r=this.getAckedValue(t,n),i=of(r,null);return i.pre===null&&i.post===null?!0:this.sendDelta(t,n,i,null)}isItemInflight(t,n){return this.inflightItems.get(t)?.has(n)===!0}async sendDelta(t,n,r,i){this.registerResource(t),this.inflightItems.has(t)||this.inflightItems.set(t,new Set);let o=this.inflightItems.get(t);if(o.has(n))return!1;let s=this.getDirtyValue(t,n);xp(s,r)&&(arguments.length>=4?this.setDirtyValue(t,n,Qi(i)):this.setDirtyValue(t,n,Z0(s,Qi(r))),this.emitResourceChange(t)),o.add(n);let c;try{c=await this.socketSession.sendWithAck(hE,{resource:t,action:"delta",key:n,value:r})}catch(f){c={ok:!1,reason:f instanceof Error?f.message:"error"}}return o.delete(n),c.ok?!0:(this.revertDirtyToAckedValue(t,n),this.emitResourceChange(t),this.logger.error(`!ack[${t}] Reverting to acked state for ${t}:${n}`,c.reason),!1)}getAckedValue(t,n){return this.initializeResource(t),this.ackedResources[t][n]??null}getDirtyValue(t,n){return this.initializeResource(t),this.dirtyResources[t][n]??null}getVisibleItems(t){this.initializeResource(t);let n={};for(let r in this.dirtyResources[t]){let i=this.dirtyResources[t][r];i!=null&&(n[r]=i)}return n}getRawItems(t){return this.initializeResource(t),Qi(this.dirtyResources[t])}getAckedItems(t){return this.initializeResource(t),Qi(this.ackedResources[t])}getUnauthorizedKeys(t){return this.initializeResource(t),Qi(this.unauthorizedKeys[t])}isResourceLoading(t){return this.initializeResource(t),this.loadingResources[t]}initializeResource(t){this.ackedResources[t]===void 0&&(this.ackedResources[t]={}),this.dirtyResources[t]===void 0&&(this.dirtyResources[t]={}),this.unauthorizedKeys[t]===void 0&&(this.unauthorizedKeys[t]={}),this.loadingResources[t]===void 0&&(this.loadingResources[t]=!0)}prepareSnapshotQuery(t,n){this.initializeResource(t);let r=Qi(n);if(r.lastUpdatedAtSeen!==void 0)return r;let i=this.buildLastUpdatedAtSeen(t,r);return gE(i)||(r.lastUpdatedAtSeen=i),r}async loadResourceFromStorage(t){if(this.initializeResource(t),this.loadedResources.has(t))return;if(this.loadingPromises.has(t))return this.loadingPromises.get(t);let n=this.loadResourceItemsFromStorage(t);this.loadingPromises.set(t,n);try{await n}finally{this.loadingPromises.delete(t),this.loadedResources.add(t)}}async loadResourceItemsFromStorage(t){let n=!1,r=0;try{let i=await this.storage.loadItems(t);if(i&&gE(this.ackedResources[t])){n=!0;for(let o in i)this.applyCachedItem(t,o,i[o])&&(r+=1)}}catch(i){this.logger.warn(`Failed to load cached ${t}: ${String(i)}`)}finally{this.loadingResources[t]=!1,this.emitResourceChange(t),n?this.logger.info(`\u{1F4C2} ${r}x ${t} from cache`):this.logger.info(`\u{1F4C2} no cached data for ${t}`)}}applyCachedItem(t,n,r){return r===null?(this.ackedResources[t][n]=null,this.dirtyResources[t][n]=null,!0):r==="unauthorized"?(this.unauthorizedKeys[t][n]=!0,!1):(this.ackedResources[t][n]=Qi(r),this.dirtyResources[t][n]=Qi(r),!0)}applySnapshot(t,n){this.initializeResource(t);for(let r in n){let i=n[r];i===null?(this.ackedResources[t][r]=null,(!this.isItemInflight(t,r)||this.getDirtyValue(t,r)==null)&&(this.dirtyResources[t][r]=null),delete this.unauthorizedKeys[t][r]):i==="unauthorized"?(delete this.ackedResources[t][r],delete this.dirtyResources[t][r],this.unauthorizedKeys[t][r]=!0):(this.ackedResources[t][r]=Qi(i),this.dirtyResources[t][r]=Qi(i),delete this.unauthorizedKeys[t][r]),this.storage.persistItem(t,r,i).catch(o=>{this.logger.warn(`Failed to persist ${t}:${r}: ${String(o)}`)})}this.loadingResources[t]=!1,this.emitResourceChange(t),this.logger.info(`\u{1F4F8} ${_E(n)}x ${t} `),this.resolveSnapshotWaiters(t)}applyRemoteDelta(t){let n=t.resource,r=t.key;if(!r)return;this.initializeResource(n);let i=t.value,o={pre:i.pre,post:i.post},s=this.getAckedValue(n,r);if(!xp(s,o))this.logger.error(`\u{1D6AB}S precondition invalid on last acked for ${n}:${r}`,{pre:o.pre,post:o.post,current:s});else{let f=J0(s,Qi(i));this.ackedResources[n][r]=f,this.storage.persistItem(n,r,f).catch(h=>{this.logger.warn(`Failed to persist ${n}:${r}: ${String(h)}`)}),this.logger.info(eg(`\u{1D6AB}S[${n}] acked`,o))}let c=this.getDirtyValue(n,r);t.by!==this.socketSession.getSessionId()?xp(c,o)?o.post===null?(this.dirtyResources[n][r]=null,this.logger.info(eg(`\u{1D6AB}S[${n}] dirty`,o))):(this.dirtyResources[n][r]=J0(c,Qi(i)),this.logger.info(eg(`\u{1D6AB}S[${n}] dirty`,o))):(this.logger.warn(`Skip delta on dirty for ${n}:${r}`,{pre:o.pre,post:o.post,current:s}),this.revertDirtyToAckedValue(n,r)):o.post!=null&&c!=null&&typeof c=="object"&&(c.updatedAt=i.updatedAt,this.dirtyResources[n][r]=c,this.logger.info(`\u{1D6AB}S[${n}] dirty updatedAt for ${r}`)),this.emitResourceChange(n)}buildLastUpdatedAtSeen(t,n){let r=this.ackedResources[t],i={};if(n.all){for(let o in r)this.copyItemUpdatedAt(r[o],o,i);return i}if(n.keys&&n.keys.length>0)for(let o of n.keys)this.copyItemUpdatedAt(r[o],o,i);return i}copyItemUpdatedAt(t,n,r){t&&typeof t=="object"&&typeof t.updatedAt=="number"&&(r[n]=t.updatedAt)}setDirtyValue(t,n,r){if(r===null){this.dirtyResources[t][n]=null;return}this.dirtyResources[t][n]=r}revertDirtyToAckedValue(t,n){let r=this.ackedResources[t][n];if(r===void 0){delete this.dirtyResources[t][n];return}if(r===null){this.dirtyResources[t][n]=null;return}this.dirtyResources[t][n]=Qi(r)}emitResourceChange(t){let n={resource:t,acked:this.getAckedItems(t),dirty:this.getRawItems(t),unauthorized:this.getUnauthorizedKeys(t),loading:this.loadingResources[t]};for(let r of this.resourceChangeListeners)r(n)}resolveSnapshotWaiters(t){let n=this.snapshotWaiters.get(t);if(n){this.snapshotWaiters.delete(t);for(let r of n)r()}}};function Qi(e){if(e===void 0)return e;if(typeof structuredClone=="function")try{return structuredClone(e)}catch{}try{return JSON.parse(JSON.stringify(e))}catch{return e}}function gE(e){for(let t in e)return!1;return!0}function _E(e){let t=0;for(let n in e)t+=1;return t}function eg(e,t){return`${e}
47
47
  delta.pre: ${JSON.stringify(t.pre)}
48
48
  delta.post: ${JSON.stringify(t.post)}`}var kp=15e3,ZB=2e3,rg=class{replicatedState;recordStorage;gatewaySocketSession;startPromise;reconnectTimer;registeredResources=new Set(cE);closed=!1;start(){return this.startPromise?this.startPromise:(this.closed=!1,this.startPromise=this.connectAndHydrate().catch(t=>{throw this.startPromise=void 0,t}),this.startPromise)}async hydrateResource(t,n={all:!0}){this.registerResource(t),await this.start(),await this.hydrateConnectedResource(t,n)}async readResourceItems(t,n={all:!0}){return this.registerResource(t),await this.start(),this.filterVisibleItems(t,n)}async readResourceItem(t,n){this.registerResource(t),await this.start();let r=this.replicatedState?.getVisibleItems(t)[n]??null;return bE(t,r)}async upsertResourceItem(t,n){if(this.registerResource(t),await this.start(),!this.replicatedState)throw new Error("replicated state not initialized");return this.replicatedState.upsertItem(t,n)}async applyResourceDelta(t,n,r){if(this.registerResource(t),await this.start(),!this.replicatedState)throw new Error("replicated state not initialized");return this.replicatedState.sendDelta(t,n,r)}async deleteResourceItem(t,n){if(this.registerResource(t),await this.start(),!this.replicatedState)throw new Error("replicated state not initialized");return this.replicatedState.deleteItem(t,n)}waitForChannelEvent(t,n,r=kp,i){if(!this.gatewaySocketSession)throw new Error("gateway websocket not connected");return this.gatewaySocketSession.waitForChannelEvent(t,o=>n(o),r,i)}collectChannelEvents(t,n,r=kp,i=250){if(!this.gatewaySocketSession)throw new Error("gateway websocket not connected");return this.gatewaySocketSession.collectChannelEvents(t,o=>n(o),r,i)}sendChannelEvent(t,n){if(!this.gatewaySocketSession)throw new Error("gateway websocket not connected");this.gatewaySocketSession.send(t,n)}close(){this.closed=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.startPromise=void 0,this.gatewaySocketSession?.close(),this.recordStorage?.close(),this.gatewaySocketSession=void 0,this.recordStorage=void 0,this.replicatedState=void 0}registerResource(t){fE(t),this.registeredResources.add(t),this.replicatedState?.registerResource(t)}async connectAndHydrate(){let t=await Do();if(!t)throw new Error("missing jwt: set BEEPFLOW_JWT or run auth tool to persist token");let n=await ga(t);await Py(n);let r=Wn(),i=ha(n),o=Ny(i.email);this.gatewaySocketSession?.close(),this.recordStorage?.close(),this.recordStorage=new bp(r.replicatedStateDatabasePath,o),this.gatewaySocketSession=new vp(r.backendUrl,n),this.replicatedState=new Op(this.recordStorage,this.gatewaySocketSession,vE),this.gatewaySocketSession.onChannel("replicated-state",s=>this.replicatedState?.processSocketEvent(s)),this.gatewaySocketSession.onDisconnected(()=>this.scheduleReconnect());for(let s of this.registeredResources)this.replicatedState.registerResource(s);await this.gatewaySocketSession.connect(kp),await this.replicatedState.loadRegisteredResourcesFromStorage(),await this.hydrateRegisteredResources()}async hydrateRegisteredResources(){let t=await Promise.allSettled(Array.from(this.registeredResources,n=>this.hydrateConnectedResource(n,{all:!0})));for(let n of t)n.status==="rejected"&&vE.warn(String(n.reason))}async hydrateConnectedResource(t,n){if(!this.replicatedState)throw new Error("replicated state not initialized");let r=this.replicatedState.waitForSnapshot(t,kp);await this.replicatedState.hydrate(t,n),await r}filterVisibleItems(t,n){let r=this.replicatedState?.getVisibleItems(t)??{},i={};for(let o in r)e6(o,r[o],n)&&(i[o]=bE(t,r[o]));return i}scheduleReconnect(){this.closed||this.reconnectTimer||(this.startPromise=void 0,this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=void 0,this.start().catch(()=>this.scheduleReconnect())},ZB))}};function e6(e,t,n){return t6(e,t,n.lastUpdatedAtSeen)?!!(n.all||n.keys?.includes(e)||n6(t,n.fieldEqualTo)):!1}function bE(e,t){if(e!=="connections"||!t||typeof t!="object"||Array.isArray(t))return t;let n={...t};return delete n.config,n}function t6(e,t,n){let r=n?.[e];if(r===void 0||!t||typeof t!="object")return!0;let i=t.updatedAt;return typeof i!="number"||i>r}function n6(e,t){if(!t||!e||typeof e!="object")return!1;let n=e,r=!1;for(let i in t)if(r=!0,!JB(n[i],t[i]))return!1;return r}var vE={info(e,t){tg("info",e,t)},warn(e,t){tg("warn",e,t)},error(e,t){tg("error",e,t)}};function tg(e,t,n){let r=n===void 0?"":` ${JSON.stringify(n)}`;process.stderr.write(`[replicated-state:${e}] ${t}${r}
49
- `)}var ng;function Ip(){return ng||(ng=new rg),ng}import{isDeepStrictEqual as r6}from"node:util";function Nr(e,t){let n=Dp(e);if(!n)throw new Error(`missing schema for resource: ${e}`);let r={failures:[],rootSchema:n.itemSchema};if(Fc(n.itemSchema,t,"$",r),r.failures.length===0)return;let i=r.failures.slice(0,5).map(o=>`${o.path} ${o.message}`).join("; ");throw new Error(`item does not match ${e} schema: ${i}`)}function Fc(e,t,n,r){if(e===!0)return;if(e===!1)return Ga(r,n,"is not allowed");if(!m6(e))return;let i=e.$ref;if(typeof i=="string"){Fc(d6(i,r.rootSchema),t,n,r);return}i6(e,t,n,r)&&(o6(e,t,n,r),a6(e,t,n,r),s6(e,t,n,r),c6(e,t,n,r))}function i6(e,t,n,r){if(!Array.isArray(e.anyOf))return!0;for(let i of e.anyOf){let o={failures:[],rootSchema:r.rootSchema};if(Fc(i,t,n,o),o.failures.length===0)return!1}return Ga(r,n,"does not match any allowed schema"),!1}function o6(e,t,n,r){let i=e.enum;if(Array.isArray(i)){for(let o of i)if(r6(t,o))return;Ga(r,n,`must be one of ${i.map(String).join(", ")}`)}}function a6(e,t,n,r){let i=e.type;if(typeof i=="string"&&!SE(t,i)){Ga(r,n,`must be ${i}`);return}if(Array.isArray(i)){for(let o of i)if(typeof o=="string"&&SE(t,o))return;Ga(r,n,`must be ${i.map(String).join(" or ")}`)}}function s6(e,t,n,r){if(e.type!=="object"||!af(t))return;let i=af(e.properties)?e.properties:{};u6(e,t,n,r);for(let o of f6(e))(!(o in t)||t[o]===void 0)&&Ga(r,`${n}.${o}`,"is required");for(let o in t){if(t[o]===void 0){Ga(r,`${n}.${o}`,"must not be undefined");continue}if(o in i){Fc(i[o],t[o],`${n}.${o}`,r);continue}l6(e,t[o],`${n}.${o}`,r)}}function u6(e,t,n,r){let i=0;for(let c in t)Object.prototype.hasOwnProperty.call(t,c)&&i++;let o=e.minProperties;typeof o=="number"&&i<o&&Ga(r,n,`must have at least ${o} properties`);let s=e.maxProperties;typeof s=="number"&&i>s&&Ga(r,n,`must have at most ${s} properties`)}function c6(e,t,n,r){if(e.type!=="array"||!Array.isArray(t))return;let i=e.items;if(i!==void 0)for(let o=0;o<t.length;o++)Fc(i,t[o],`${n}[${o}]`,r)}function l6(e,t,n,r){let i=e.additionalProperties;if(i===!1){Ga(r,n,"is not allowed");return}i===void 0||i===!0||Fc(i,t,n,r)}function f6(e){return Array.isArray(e.required)?e.required.filter(t=>typeof t=="string"):[]}function d6(e,t){if(!e.startsWith("#/"))return!1;let n=t,r=e.slice(2).split("/").map(p6);for(let i of r){if(!af(n)||!(i in n))return!1;n=n[i]}return n}function p6(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function SE(e,t){switch(t){case"array":return Array.isArray(e);case"boolean":return typeof e=="boolean";case"integer":return Number.isInteger(e);case"null":return e===null;case"number":return typeof e=="number"&&Number.isFinite(e);case"object":return af(e);case"string":return typeof e=="string";default:return!0}}function m6(e){return af(e)}function af(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Ga(e,t,n){e.failures.push({path:t,message:n})}async function ig(e){return _6(await og(e))}async function EE(){return await _p("/integrations")}async function TE(e,t){return await _p(`/integrations/blueprint-contexts${h6(e,t)}`)}async function og(e){return g6(await _p(`/integrations/${encodeURIComponent(e)}/openapi`))}function h6(e,t){let n=new URLSearchParams;e&&n.set("integrationType",e),t&&n.set("resourceType",t);let r=n.toString();return r?`?${r}`:""}async function AE(e){let n=(await ig(e.integrationType)).find(i=>i.operationId===e.operationId);if(!n)throw new Error(`unsupported integration endpoint: ${e.operationId}`);A6(n,e.confirm);let r=w6(n,e.payload);if(n.requestMode==="none"&&r.body!==void 0)throw new Error(`integration endpoint ${n.operationId} has requestBody=null; remove body-only fields from payload`);return await ds({method:n.method,path:O6(n,r.path),query:r.query,headers:r.headers,body:r.body,requestMode:n.requestMode,responseMode:n.responseMode,files:r.files,outputFilePath:e.outputFilePath})}function g6(e){let t=sf(e,"paths");for(let n in t){let r=t[n];if(er(r))for(let i in r){let o=r[i];er(o)&&(o.payloadSchema=wE(o))}}return e}function _6(e){let t=sf(e,"paths"),n=[];for(let r in t){let i=t[r];if(er(i))for(let o in i){let s=i[o];er(s)&&n.push(b6(o.toUpperCase(),r,s))}}return n}function b6(e,t,n){let r=sf(n,"x-beepflow");return{operationId:Iu(n,"operationId"),integrationType:Iu(r,"integrationType"),resourceType:I6(r,"resourceType"),method:e,path:t,originalPath:Iu(r,"originalPath"),summary:Iu(n,"summary"),access:Iu(r,"access"),sideEffect:Iu(r,"sideEffect"),mcpExposure:Iu(r,"mcpExposure"),requestMode:CE(n),responseMode:E6(n),pathParameters:k6(t),parameters:DE(n),payloadSchema:wE(n),requestBody:Co(n,"requestBody"),responses:sf(n,"responses"),runtimeUse:"mcp-only",externalAppUse:"forbidden",externalAppAlternative:"Create/use a blueprint with webhook trigger and call /api/:tabId/trigger."}}function wE(e){let t=CE(e),n=y6(e,t),r={type:"object",additionalProperties:!1,properties:{}},i=r.properties,o=[];for(let s of DE(e))!er(s)||typeof s.name!="string"||!er(s.schema)||(i[s.name]=s.schema,s.required===!0&&o.push(s.name));return v6(r,i,o,n,t),o.length&&(r.required=o),r}function v6(e,t,n,r,i){if(!r)return;let o=Co(r,"properties");if(!o){e.additionalProperties=r.additionalProperties??!0;return}for(let c in o)t[c]=S6(o[c],i);r.additionalProperties!==void 0&&r.additionalProperties!==!1&&(e.additionalProperties=r.additionalProperties);let s=r.required;if(Array.isArray(s))for(let c of s)typeof c=="string"&&n.push(c)}function S6(e,t){return t!=="multipart"||!er(e)||e.format!=="binary"?e:{type:"object",additionalProperties:!1,description:"Multipart file input. Provide filePath or base64 content.",properties:{filePath:{type:"string",description:"Local file path to read and upload."},base64:{type:"string",description:"Base64-encoded file content."},fileName:{type:"string",description:"File name to send for base64 content."},contentType:{type:"string",description:"MIME type for uploaded content."}}}}function y6(e,t){let n=Co(e,"requestBody");if(!n)return null;let r=Co(n,"content");if(!r)return null;let i=RE(t),o=Co(r,i);return o?Co(o,"schema"):null}function RE(e){switch(e){case"multipart":return"multipart/form-data";case"form":return"application/x-www-form-urlencoded";default:return"application/json"}}function DE(e){let t=e.parameters;if(t==null)return[];if(!Array.isArray(t))throw new Error("invalid integration OpenAPI schema: parameters must be array");return t}function CE(e){let t=Co(e,"requestBody");if(!t)return"none";let n=Co(t,"content");return n?er(n["multipart/form-data"])?"multipart":er(n["application/x-www-form-urlencoded"])?"form":(er(n["application/json"]),"json"):"none"}function E6(e){let t=sf(e,"responses");for(let i in t)if(i.startsWith("3")&&er(t[i]))return"redirect";let n=T6(t);if(!n)return"empty";let r=Co(n,"content");return r?er(r["application/octet-stream"])?"binary":er(r["text/plain"])?"text":(er(r["application/json"]),"json"):"empty"}function T6(e){if(er(e[200]))return e[200];for(let t in e)if(t.startsWith("2")&&er(e[t]))return e[t];return null}function A6(e,t){if(!(e.mcpExposure==="safe"&&e.sideEffect!=="destructive")&&t!==!0)throw new Error(`integration endpoint requires confirm=true: ${e.operationId}`)}function w6(e,t){let n={path:{},query:{},headers:{}},r=t??{},i=x6(e);for(let o of e.parameters){if(!er(o)||typeof o.name!="string"||typeof o.in!="string")continue;let s=r[o.name];s!==void 0&&(o.in==="path"&&(n.path[o.name]=s),o.in==="query"&&(n.query[o.name]=s),o.in==="header"&&(n.headers[o.name]=s))}if(e.requestMode!=="none")R6(e,r,i,n);else for(let o in r)i.has(o)||(n.body={[o]:r[o]});return n}function R6(e,t,n,r){let i=C6(e),o=i?Co(i,"properties"):null,s={},c={};if(o){for(let f in o)D6(e,f,t[f],s,c);if(i?.additionalProperties!==void 0&&i.additionalProperties!==!1)for(let f in t)!n.has(f)&&o[f]===void 0&&(s[f]=t[f])}else if(i?.additionalProperties!==!1)for(let f in t)n.has(f)||(s[f]=t[f]);yE(s)&&(r.body=s),yE(c)&&(r.files=c)}function D6(e,t,n,r,i){if(n!==void 0){if(e.requestMode==="multipart"&&er(n)&&(typeof n.filePath=="string"||typeof n.base64=="string")){i[t]=n;return}r[t]=n}}function C6(e){if(!e.requestBody)return null;let t=Co(e.requestBody,"content"),n=t?Co(t,RE(e.requestMode)):null;return n?Co(n,"schema"):null}function x6(e){let t=new Set;for(let n of e.parameters)er(n)&&typeof n.name=="string"&&t.add(n.name);return t}function yE(e){for(let t in e)if(e[t]!==void 0)return!0;return!1}function O6(e,t){let n=e.path;for(let r of e.pathParameters){let i=t?.[r];if(typeof i!="string"&&typeof i!="number")throw new Error(`integration endpoint path parameter required: ${r}`);n=n.replace(`{${r}}`,encodeURIComponent(String(i)))}return n}function k6(e){let t=[];for(let n of e.matchAll(/\{([^}]+)\}/g))n[1]&&t.push(n[1]);return t}function sf(e,t){if(!er(e)||!er(e[t]))throw new Error(`invalid integration OpenAPI schema: ${t} must be object`);return e[t]}function Co(e,t){if(!er(e)||e[t]===void 0||e[t]===null)return null;if(!er(e[t]))throw new Error(`invalid integration OpenAPI schema: ${t} must be object`);return e[t]}function Iu(e,t){if(typeof e[t]!="string")throw new Error(`invalid integration OpenAPI schema: ${t} must be string`);return e[t]}function I6(e,t){if(e[t]===void 0||e[t]===null)return null;if(typeof e[t]!="string")throw new Error(`invalid integration OpenAPI schema: ${t} must be string`);return e[t]}function er(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}import OE from"node:fs";import ag from"node:path";import{fileURLToPath as N6}from"node:url";var xE={name:"@beepflow/mcp",version:"2026.9.0",type:"module",engines:{node:">=24.6.0"},license:"UNLICENSED",bin:{mcp:"./dist/index.js"},files:["dist/**","README.md","LICENSE"],scripts:{"start:src":"node --experimental-strip-types ./src/index.ts","test:src":'tsc -b ../shared/tsconfig.json && node --experimental-strip-types --test "./src/**/*.test.ts" "../shared/replicated-state/**/*.test.ts"',build:`node --input-type=module -e "import fs from 'node:fs'; fs.rmSync('dist', { recursive: true, force: true });" && tsc -b ../shared/tsconfig.json && tsc -p tsconfig.json --noEmit && esbuild src/index.ts --bundle --platform=node --format=esm --target=node24 --minify --banner:js='#!/usr/bin/env node
49
+ `)}var ng;function Ip(){return ng||(ng=new rg),ng}import{isDeepStrictEqual as r6}from"node:util";function Nr(e,t){let n=Dp(e);if(!n)throw new Error(`missing schema for resource: ${e}`);let r={failures:[],rootSchema:n.itemSchema};if(Fc(n.itemSchema,t,"$",r),r.failures.length===0)return;let i=r.failures.slice(0,5).map(o=>`${o.path} ${o.message}`).join("; ");throw new Error(`item does not match ${e} schema: ${i}`)}function Fc(e,t,n,r){if(e===!0)return;if(e===!1)return Ga(r,n,"is not allowed");if(!m6(e))return;let i=e.$ref;if(typeof i=="string"){Fc(d6(i,r.rootSchema),t,n,r);return}i6(e,t,n,r)&&(o6(e,t,n,r),a6(e,t,n,r),s6(e,t,n,r),c6(e,t,n,r))}function i6(e,t,n,r){if(!Array.isArray(e.anyOf))return!0;for(let i of e.anyOf){let o={failures:[],rootSchema:r.rootSchema};if(Fc(i,t,n,o),o.failures.length===0)return!1}return Ga(r,n,"does not match any allowed schema"),!1}function o6(e,t,n,r){let i=e.enum;if(Array.isArray(i)){for(let o of i)if(r6(t,o))return;Ga(r,n,`must be one of ${i.map(String).join(", ")}`)}}function a6(e,t,n,r){let i=e.type;if(typeof i=="string"&&!SE(t,i)){Ga(r,n,`must be ${i}`);return}if(Array.isArray(i)){for(let o of i)if(typeof o=="string"&&SE(t,o))return;Ga(r,n,`must be ${i.map(String).join(" or ")}`)}}function s6(e,t,n,r){if(e.type!=="object"||!af(t))return;let i=af(e.properties)?e.properties:{};u6(e,t,n,r);for(let o of f6(e))(!(o in t)||t[o]===void 0)&&Ga(r,`${n}.${o}`,"is required");for(let o in t){if(t[o]===void 0){Ga(r,`${n}.${o}`,"must not be undefined");continue}if(o in i){Fc(i[o],t[o],`${n}.${o}`,r);continue}l6(e,t[o],`${n}.${o}`,r)}}function u6(e,t,n,r){let i=0;for(let c in t)Object.prototype.hasOwnProperty.call(t,c)&&i++;let o=e.minProperties;typeof o=="number"&&i<o&&Ga(r,n,`must have at least ${o} properties`);let s=e.maxProperties;typeof s=="number"&&i>s&&Ga(r,n,`must have at most ${s} properties`)}function c6(e,t,n,r){if(e.type!=="array"||!Array.isArray(t))return;let i=e.items;if(i!==void 0)for(let o=0;o<t.length;o++)Fc(i,t[o],`${n}[${o}]`,r)}function l6(e,t,n,r){let i=e.additionalProperties;if(i===!1){Ga(r,n,"is not allowed");return}i===void 0||i===!0||Fc(i,t,n,r)}function f6(e){return Array.isArray(e.required)?e.required.filter(t=>typeof t=="string"):[]}function d6(e,t){if(!e.startsWith("#/"))return!1;let n=t,r=e.slice(2).split("/").map(p6);for(let i of r){if(!af(n)||!(i in n))return!1;n=n[i]}return n}function p6(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function SE(e,t){switch(t){case"array":return Array.isArray(e);case"boolean":return typeof e=="boolean";case"integer":return Number.isInteger(e);case"null":return e===null;case"number":return typeof e=="number"&&Number.isFinite(e);case"object":return af(e);case"string":return typeof e=="string";default:return!0}}function m6(e){return af(e)}function af(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Ga(e,t,n){e.failures.push({path:t,message:n})}async function ig(e){return _6(await og(e))}async function EE(){return await _p("/integrations")}async function TE(e,t){return await _p(`/integrations/blueprint-contexts${h6(e,t)}`)}async function og(e){return g6(await _p(`/integrations/${encodeURIComponent(e)}/openapi`))}function h6(e,t){let n=new URLSearchParams;e&&n.set("integrationType",e),t&&n.set("resourceType",t);let r=n.toString();return r?`?${r}`:""}async function AE(e){let n=(await ig(e.integrationType)).find(i=>i.operationId===e.operationId);if(!n)throw new Error(`unsupported integration endpoint: ${e.operationId}`);A6(n,e.confirm);let r=w6(n,e.payload);if(n.requestMode==="none"&&r.body!==void 0)throw new Error(`integration endpoint ${n.operationId} has requestBody=null; remove body-only fields from payload`);return await ds({method:n.method,path:O6(n,r.path),query:r.query,headers:r.headers,body:r.body,requestMode:n.requestMode,responseMode:n.responseMode,files:r.files,outputFilePath:e.outputFilePath})}function g6(e){let t=sf(e,"paths");for(let n in t){let r=t[n];if(er(r))for(let i in r){let o=r[i];er(o)&&(o.payloadSchema=wE(o))}}return e}function _6(e){let t=sf(e,"paths"),n=[];for(let r in t){let i=t[r];if(er(i))for(let o in i){let s=i[o];er(s)&&n.push(b6(o.toUpperCase(),r,s))}}return n}function b6(e,t,n){let r=sf(n,"x-beepflow");return{operationId:Iu(n,"operationId"),integrationType:Iu(r,"integrationType"),resourceType:I6(r,"resourceType"),method:e,path:t,originalPath:Iu(r,"originalPath"),summary:Iu(n,"summary"),access:Iu(r,"access"),sideEffect:Iu(r,"sideEffect"),mcpExposure:Iu(r,"mcpExposure"),requestMode:CE(n),responseMode:E6(n),pathParameters:k6(t),parameters:DE(n),payloadSchema:wE(n),requestBody:Co(n,"requestBody"),responses:sf(n,"responses"),runtimeUse:"mcp-only",externalAppUse:"forbidden",externalAppAlternative:"Create/use a blueprint with webhook trigger and call /api/:tabId/trigger."}}function wE(e){let t=CE(e),n=y6(e,t),r={type:"object",additionalProperties:!1,properties:{}},i=r.properties,o=[];for(let s of DE(e))!er(s)||typeof s.name!="string"||!er(s.schema)||(i[s.name]=s.schema,s.required===!0&&o.push(s.name));return v6(r,i,o,n,t),o.length&&(r.required=o),r}function v6(e,t,n,r,i){if(!r)return;let o=Co(r,"properties");if(!o){e.additionalProperties=r.additionalProperties??!0;return}for(let c in o)t[c]=S6(o[c],i);r.additionalProperties!==void 0&&r.additionalProperties!==!1&&(e.additionalProperties=r.additionalProperties);let s=r.required;if(Array.isArray(s))for(let c of s)typeof c=="string"&&n.push(c)}function S6(e,t){return t!=="multipart"||!er(e)||e.format!=="binary"?e:{type:"object",additionalProperties:!1,description:"Multipart file input. Provide filePath or base64 content.",properties:{filePath:{type:"string",description:"Local file path to read and upload."},base64:{type:"string",description:"Base64-encoded file content."},fileName:{type:"string",description:"File name to send for base64 content."},contentType:{type:"string",description:"MIME type for uploaded content."}}}}function y6(e,t){let n=Co(e,"requestBody");if(!n)return null;let r=Co(n,"content");if(!r)return null;let i=RE(t),o=Co(r,i);return o?Co(o,"schema"):null}function RE(e){switch(e){case"multipart":return"multipart/form-data";case"form":return"application/x-www-form-urlencoded";default:return"application/json"}}function DE(e){let t=e.parameters;if(t==null)return[];if(!Array.isArray(t))throw new Error("invalid integration OpenAPI schema: parameters must be array");return t}function CE(e){let t=Co(e,"requestBody");if(!t)return"none";let n=Co(t,"content");return n?er(n["multipart/form-data"])?"multipart":er(n["application/x-www-form-urlencoded"])?"form":(er(n["application/json"]),"json"):"none"}function E6(e){let t=sf(e,"responses");for(let i in t)if(i.startsWith("3")&&er(t[i]))return"redirect";let n=T6(t);if(!n)return"empty";let r=Co(n,"content");return r?er(r["application/octet-stream"])?"binary":er(r["text/plain"])?"text":(er(r["application/json"]),"json"):"empty"}function T6(e){if(er(e[200]))return e[200];for(let t in e)if(t.startsWith("2")&&er(e[t]))return e[t];return null}function A6(e,t){if(!(e.mcpExposure==="safe"&&e.sideEffect!=="destructive")&&t!==!0)throw new Error(`integration endpoint requires confirm=true: ${e.operationId}`)}function w6(e,t){let n={path:{},query:{},headers:{}},r=t??{},i=x6(e);for(let o of e.parameters){if(!er(o)||typeof o.name!="string"||typeof o.in!="string")continue;let s=r[o.name];s!==void 0&&(o.in==="path"&&(n.path[o.name]=s),o.in==="query"&&(n.query[o.name]=s),o.in==="header"&&(n.headers[o.name]=s))}if(e.requestMode!=="none")R6(e,r,i,n);else for(let o in r)i.has(o)||(n.body={[o]:r[o]});return n}function R6(e,t,n,r){let i=C6(e),o=i?Co(i,"properties"):null,s={},c={};if(o){for(let f in o)D6(e,f,t[f],s,c);if(i?.additionalProperties!==void 0&&i.additionalProperties!==!1)for(let f in t)!n.has(f)&&o[f]===void 0&&(s[f]=t[f])}else if(i?.additionalProperties!==!1)for(let f in t)n.has(f)||(s[f]=t[f]);yE(s)&&(r.body=s),yE(c)&&(r.files=c)}function D6(e,t,n,r,i){if(n!==void 0){if(e.requestMode==="multipart"&&er(n)&&(typeof n.filePath=="string"||typeof n.base64=="string")){i[t]=n;return}r[t]=n}}function C6(e){if(!e.requestBody)return null;let t=Co(e.requestBody,"content"),n=t?Co(t,RE(e.requestMode)):null;return n?Co(n,"schema"):null}function x6(e){let t=new Set;for(let n of e.parameters)er(n)&&typeof n.name=="string"&&t.add(n.name);return t}function yE(e){for(let t in e)if(e[t]!==void 0)return!0;return!1}function O6(e,t){let n=e.path;for(let r of e.pathParameters){let i=t?.[r];if(typeof i!="string"&&typeof i!="number")throw new Error(`integration endpoint path parameter required: ${r}`);n=n.replace(`{${r}}`,encodeURIComponent(String(i)))}return n}function k6(e){let t=[];for(let n of e.matchAll(/\{([^}]+)\}/g))n[1]&&t.push(n[1]);return t}function sf(e,t){if(!er(e)||!er(e[t]))throw new Error(`invalid integration OpenAPI schema: ${t} must be object`);return e[t]}function Co(e,t){if(!er(e)||e[t]===void 0||e[t]===null)return null;if(!er(e[t]))throw new Error(`invalid integration OpenAPI schema: ${t} must be object`);return e[t]}function Iu(e,t){if(typeof e[t]!="string")throw new Error(`invalid integration OpenAPI schema: ${t} must be string`);return e[t]}function I6(e,t){if(e[t]===void 0||e[t]===null)return null;if(typeof e[t]!="string")throw new Error(`invalid integration OpenAPI schema: ${t} must be string`);return e[t]}function er(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}import OE from"node:fs";import ag from"node:path";import{fileURLToPath as N6}from"node:url";var xE={name:"@beepflow/mcp",version:"2026.9.1",type:"module",engines:{node:">=24.6.0"},license:"UNLICENSED",bin:{mcp:"./dist/index.js"},files:["dist/**","README.md","LICENSE"],scripts:{"start:src":"node --experimental-strip-types ./src/index.ts","test:src":'tsc -b ../shared/tsconfig.json && node --experimental-strip-types --test "./src/**/*.test.ts" "../shared/replicated-state/**/*.test.ts"',build:`node --input-type=module -e "import fs from 'node:fs'; fs.rmSync('dist', { recursive: true, force: true });" && tsc -b ../shared/tsconfig.json && tsc -p tsconfig.json --noEmit && esbuild src/index.ts --bundle --platform=node --format=esm --target=node24 --minify --banner:js='#!/usr/bin/env node
50
50
  const require = (await import("node:module")).createRequire(import.meta.url);' --outfile=dist/index.js && node --input-type=module -e "import fs from 'node:fs'; fs.chmodSync('dist/index.js', 0o755);"`,start:"node ./dist/index.js",test:"yarn test:src && yarn build && node ./dist/index.js < /dev/null",prepack:"yarn build"},devDependencies:{"@types/html-minifier-terser":"^7.0.2","@types/lodash":"^4.17.20","@types/node":"^24.3.0",esbuild:"^0.25.9","html-minifier-terser":"^7.2.0",typescript:"~5.7.3"},dependencies:{lodash:"^4.17.21"}};var Us=xE.version,F6="https://registry.npmjs.org/@beepflow/mcp/latest",L6=6e5,M6=Date.now()-process.uptime()*1e3,kE=0,uf;async function IE(){if(U6()>M6)return{reason:"source-changed-since-start",runningVersion:Us,message:"Beepflow MCP source changed after this server started, so it runs outdated code. Ask the user to restart the Beepflow MCP server before continuing."};let e=await V6();if(!(e===void 0||!B6(e,Us)))return{reason:"newer-version-published",runningVersion:Us,latestVersion:e,message:`Beepflow MCP runs ${Us} while ${e} is published. Ask the user to restart the Beepflow MCP server before continuing.`}}function B6(e,t){let n=e.split(".").map(Number),r=t.split(".").map(Number);for(let i=0;i<Math.max(n.length,r.length);i+=1){let o=n[i]??0,s=r[i]??0;if(o!==s)return o>s}return!1}function U6(){let e=ag.dirname(N6(import.meta.url)),t=0;try{for(let n of[e,ag.join(e,"../../shared/replicated-state")])for(let r of OE.readdirSync(n,{recursive:!0,withFileTypes:!0}))!r.isFile()||!r.name.endsWith(".ts")||(t=Math.max(t,OE.statSync(ag.join(r.parentPath,r.name)).mtimeMs))}catch{return 0}return t}async function V6(){if(Date.now()-kE<L6)return uf;try{let e=await fetch(F6,{signal:AbortSignal.timeout(1500)}),t=e.ok?await e.json():void 0;uf=typeof t?.version=="string"?t.version:void 0}catch{uf=void 0}return uf!==void 0&&(kE=Date.now()),uf}var PE="For Beepflow tasks, call status first and follow the instructions field returned in the status response. Treat client-saved tool outputs as historical logs; verify resource ids with live MCP queries. Name resources as Label[id], not bare id.",NE=`
51
51
  Use Beepflow MCP to inspect authenticated workspace resources, blueprint context, live results, integration OpenAPI endpoints, and auth.
52
52
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beepflow/mcp",
3
- "version": "2026.9.0",
3
+ "version": "2026.9.1",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=24.6.0"