@vibecontrols/agent 2026.531.12 → 2026.531.13

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.

Potentially problematic release.


This version of @vibecontrols/agent might be problematic. Click here for more details.

@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{CliContributorRegistry,createIframeBridge}from"./index-1atc02se.js";import{PluginManager,ServiceRegistry}from"./index-7qj1swrk.js";import{getOsAdapter}from"./index-srbb2214.js";import{mountProfileRoutes}from"./index-brtw3j8x.js";import{getAgentApiKey}from"./index-b4wy3jrt.js";import{readAgentConfigWithSecrets,writeAgentConfig}from"./index-2pqv0bya.js";import{assertAllowedGatewayUrl,gatewayClient,getDaemonProfile,getOrCreateProfile,profileRegistry,sanitizeOperatorTunnelUrl,sanitizeTunnelUrl}from"./index-7pdmqbj8.js";import{getVibecontrolsProductDir,validateAgentName}from"./index-bysm7taq.js";import{__require}from"./index-e9rt4m94.js";var RETRY_BACKOFFS_MS=[0,5000,15000,30000,60000],RATE_LIMIT_BUFFER_MS=2000,RATE_LIMIT_MIN_WAIT_MS=5000,RATE_LIMIT_MAX_WAIT_MS=120000,RATE_LIMIT_MAX_RETRIES=10,MAX_GATEWAY_RESPONSE_BYTES=1048576;class RateLimitError extends Error{resetAt;resource;constructor(message,resource,resetAt){super(message);this.name="RateLimitError",this.resource=resource,this.resetAt=resetAt}}function detectRateLimit(errors,resource){if(!errors?.length)return null;let hit=errors.find((e)=>e.extensions?.code==="RATE_LIMITED");if(!hit)return null;let resetRaw=hit.extensions?.resetAt,resetAt=null;if(resetRaw){let parsed=new Date(resetRaw);if(!Number.isNaN(parsed.getTime()))resetAt=parsed}return new RateLimitError(`${resource} rate limited${resetAt?` until ${resetAt.toISOString()}`:""}`,resource,resetAt)}function computeRateLimitDelay(err){if(!err.resetAt)return 60000;let waitMs=err.resetAt.getTime()-Date.now()+RATE_LIMIT_BUFFER_MS;return Math.min(Math.max(waitMs,RATE_LIMIT_MIN_WAIT_MS),RATE_LIMIT_MAX_WAIT_MS)}async function readResponseTextCapped(response,maxBytes){let contentLength=response.headers.get("content-length");if(contentLength){let parsed=Number.parseInt(contentLength,10);if(Number.isInteger(parsed)&&parsed>maxBytes)throw Error(`Gateway response is too large (${parsed} bytes)`)}if(!response.body)return"";let reader=response.body.getReader(),chunks=[],total=0;try{while(!0){let{done,value}=await reader.read();if(done)break;if(!value)continue;if(total+=value.byteLength,total>maxBytes)throw await reader.cancel().catch(()=>{return}),Error(`Gateway response exceeds ${maxBytes} bytes`);chunks.push(value)}}finally{reader.releaseLock()}let merged=new Uint8Array(total),offset=0;for(let chunk of chunks)merged.set(chunk,offset),offset+=chunk.byteLength;return new TextDecoder().decode(merged)}async function readGraphqlJson(response,resource){let raw=await readResponseTextCapped(response,MAX_GATEWAY_RESPONSE_BYTES),data;try{data=raw?JSON.parse(raw):{}}catch(err){let preview=raw.slice(0,240).replace(/\s+/g," ");throw Error(`${resource} returned non-JSON response (${response.status} ${response.statusText})${preview?`: ${preview}`:""}`,{cause:err})}if(!response.ok){let preview=raw.slice(0,240).replace(/\s+/g," ");throw Error(`${resource} failed (${response.status} ${response.statusText})${preview?`: ${preview}`:""}`)}return data}function ensureGraphqlSuffix(url){return url.endsWith("/graphql")?url:`${url}/graphql`}function isLocalDevGatewayHost(url){let host;try{host=new URL(url).hostname.toLowerCase().replace(/^\[|\]$/g,"")}catch{return!1}if(host==="localhost"||host==="127.0.0.1"||host==="::1"||host==="0.0.0.0"||host==="host.docker.internal")return!0;return host.endsWith(".localhost")||host.endsWith(".local")||host.endsWith(".local.burdenoff.com")}function devTlsFetchInit(url){if(!(process.env.VIBE_DEV_INSECURE_TLS==="1"||process.env.NODE_TLS_REJECT_UNAUTHORIZED==="0")&&!isLocalDevGatewayHost(url))return{};return{tls:{rejectUnauthorized:!1}}}async function authenticateApp(globalGatewayUrl,clientId,clientSecret){let res=await fetch(ensureGraphqlSuffix(globalGatewayUrl),{method:"POST",...devTlsFetchInit(globalGatewayUrl),headers:{"Content-Type":"application/json"},body:JSON.stringify({query:`mutation AuthenticateApp($input: AuthenticateAppInput!) {
2
+ import{CliContributorRegistry,createIframeBridge}from"./index-ttafzcs7.js";import{PluginManager,ServiceRegistry,getAgentVersion}from"./index-1x89a7r1.js";import{getOsAdapter}from"./index-srbb2214.js";import{mountProfileRoutes}from"./index-brtw3j8x.js";import{getAgentApiKey}from"./index-b4wy3jrt.js";import{readAgentConfigWithSecrets,writeAgentConfig}from"./index-2pqv0bya.js";import{assertAllowedGatewayUrl,gatewayClient,getDaemonProfile,getOrCreateProfile,profileRegistry,sanitizeOperatorTunnelUrl,sanitizeTunnelUrl}from"./index-7pdmqbj8.js";import{getVibecontrolsProductDir,validateAgentName}from"./index-bysm7taq.js";import{__require}from"./index-e9rt4m94.js";var RETRY_BACKOFFS_MS=[0,5000,15000,30000,60000],RATE_LIMIT_BUFFER_MS=2000,RATE_LIMIT_MIN_WAIT_MS=5000,RATE_LIMIT_MAX_WAIT_MS=120000,RATE_LIMIT_MAX_RETRIES=10,MAX_GATEWAY_RESPONSE_BYTES=1048576;class RateLimitError extends Error{resetAt;resource;constructor(message,resource,resetAt){super(message);this.name="RateLimitError",this.resource=resource,this.resetAt=resetAt}}function detectRateLimit(errors,resource){if(!errors?.length)return null;let hit=errors.find((e)=>e.extensions?.code==="RATE_LIMITED");if(!hit)return null;let resetRaw=hit.extensions?.resetAt,resetAt=null;if(resetRaw){let parsed=new Date(resetRaw);if(!Number.isNaN(parsed.getTime()))resetAt=parsed}return new RateLimitError(`${resource} rate limited${resetAt?` until ${resetAt.toISOString()}`:""}`,resource,resetAt)}function computeRateLimitDelay(err){if(!err.resetAt)return 60000;let waitMs=err.resetAt.getTime()-Date.now()+RATE_LIMIT_BUFFER_MS;return Math.min(Math.max(waitMs,RATE_LIMIT_MIN_WAIT_MS),RATE_LIMIT_MAX_WAIT_MS)}async function readResponseTextCapped(response,maxBytes){let contentLength=response.headers.get("content-length");if(contentLength){let parsed=Number.parseInt(contentLength,10);if(Number.isInteger(parsed)&&parsed>maxBytes)throw Error(`Gateway response is too large (${parsed} bytes)`)}if(!response.body)return"";let reader=response.body.getReader(),chunks=[],total=0;try{while(!0){let{done,value}=await reader.read();if(done)break;if(!value)continue;if(total+=value.byteLength,total>maxBytes)throw await reader.cancel().catch(()=>{return}),Error(`Gateway response exceeds ${maxBytes} bytes`);chunks.push(value)}}finally{reader.releaseLock()}let merged=new Uint8Array(total),offset=0;for(let chunk of chunks)merged.set(chunk,offset),offset+=chunk.byteLength;return new TextDecoder().decode(merged)}async function readGraphqlJson(response,resource){let raw=await readResponseTextCapped(response,MAX_GATEWAY_RESPONSE_BYTES),data;try{data=raw?JSON.parse(raw):{}}catch(err){let preview=raw.slice(0,240).replace(/\s+/g," ");throw Error(`${resource} returned non-JSON response (${response.status} ${response.statusText})${preview?`: ${preview}`:""}`,{cause:err})}if(!response.ok){let preview=raw.slice(0,240).replace(/\s+/g," ");throw Error(`${resource} failed (${response.status} ${response.statusText})${preview?`: ${preview}`:""}`)}return data}function ensureGraphqlSuffix(url){return url.endsWith("/graphql")?url:`${url}/graphql`}function isLocalDevGatewayHost(url){let host;try{host=new URL(url).hostname.toLowerCase().replace(/^\[|\]$/g,"")}catch{return!1}if(host==="localhost"||host==="127.0.0.1"||host==="::1"||host==="0.0.0.0"||host==="host.docker.internal")return!0;return host.endsWith(".localhost")||host.endsWith(".local")||host.endsWith(".local.burdenoff.com")}function devTlsFetchInit(url){if(!(process.env.VIBE_DEV_INSECURE_TLS==="1"||process.env.NODE_TLS_REJECT_UNAUTHORIZED==="0")&&!isLocalDevGatewayHost(url))return{};return{tls:{rejectUnauthorized:!1}}}async function authenticateApp(globalGatewayUrl,clientId,clientSecret){let res=await fetch(ensureGraphqlSuffix(globalGatewayUrl),{method:"POST",...devTlsFetchInit(globalGatewayUrl),headers:{"Content-Type":"application/json"},body:JSON.stringify({query:`mutation AuthenticateApp($input: AuthenticateAppInput!) {
3
3
  authenticateApp(input: $input) { accessToken expiresIn }
4
4
  }`,variables:{input:{clientId,clientSecret,scopes:[]}}}),signal:AbortSignal.timeout(15000)}),data=await readGraphqlJson(res,"authenticateApp"),rl=detectRateLimit(data.errors,"authenticateApp");if(rl)throw rl;if(data.errors?.length){let codes=data.errors.map((e)=>e.extensions?.code??"UNKNOWN").join(",");throw Error(`authenticateApp errors [${codes}]: ${data.errors.map((e)=>e.message).join("; ")}`)}let token=data.data?.authenticateApp?.accessToken;if(!token)throw Error("authenticateApp returned no token");return token}async function issueWorkspaceToken(workspaceGatewayUrl,appToken,workspaceId,organizationId){let res=await fetch(ensureGraphqlSuffix(workspaceGatewayUrl),{method:"POST",...devTlsFetchInit(workspaceGatewayUrl),headers:{"Content-Type":"application/json",Authorization:`Bearer ${appToken}`},body:JSON.stringify({query:`mutation IssueAgentWorkspaceToken($input: IssueWorkspaceTokenInput!) {
5
5
  issueWorkspaceToken(input: $input) {
@@ -114,7 +114,7 @@ data: /message
114
114
 
115
115
  `),this._clients.add(res),req.on("close",()=>{this._clients.delete(res)})}async _handleMessage(req,res){let body="";req.setEncoding("utf8"),req.on("data",(c)=>{if(body+=c,body.length>this._maxBodySize)req.destroy(),res.writeHead(413,{"Content-Type":"application/json"}),res.end(JSON.stringify({error:"Request body too large"}))}),req.on("end",async()=>{res.writeHead(202,{"Content-Type":"application/json"}),res.end("{}");let msg;try{msg=JSON.parse(body)}catch(_){this.send(error222(null,PARSE_ERROR222,"Parse error"));return}if(this._onMessage)await this._onMessage(msg).catch(()=>{})})}get port(){return this._port}get host(){return this._host}get url(){return`http://${this._host}:${this._port}`}get sseUrl(){return`${this.url}/sse`}}class StdioTransport222{constructor(){this._onMessage=null,this._buffer="",this._started=!1}onMessage(fn){this._onMessage=fn}send(msg){process.stdout.write(JSON.stringify(msg)+`
116
116
  `)}start(){if(this._started)return;this._started=!0,process.stdin.setEncoding("utf8"),process.stdin.on("data",(chunk)=>{this._buffer+=chunk;let idx;while((idx=this._buffer.indexOf(`
117
- `))!==-1){let line=this._buffer.slice(0,idx).trim();if(this._buffer=this._buffer.slice(idx+1),line&&this._onMessage){let msg;try{msg=JSON.parse(line)}catch(_){this.send(error222(null,PARSE_ERROR222,"Parse error"));continue}this._onMessage(msg).catch(()=>{})}}}),process.stdin.on("end",()=>{process.exit(0)})}stop(){process.stdin.removeAllListeners("data"),process.stdin.removeAllListeners("end"),this._started=!1}}var SERVER_INFO222={name:"skalex",version:"4.0.0-alpha"},PROTOCOL_VERSION222="2024-11-05";class SkalexMCPServer222{constructor(db,opts={}){this._db=db,this._transport=opts.transport||"stdio",this._port=opts.port||3000,this._host=opts.host||"127.0.0.1",this._allowedOrigin=opts.allowedOrigin??null,this._maxBodySize=opts.maxBodySize??1048576,this._scopes=opts.scopes||{"*":["read"]},this._t=null}async listen(){if(this._transport==="http")this._t=new HttpTransport222({port:this._port,host:this._host,allowedOrigin:this._allowedOrigin,maxBodySize:this._maxBodySize});else this._t=new StdioTransport222;this._t.onMessage((msg)=>this._handleMessage(msg)),await this._t.start()}async connect(transport){if(this._t=transport,this._t.onMessage((msg)=>this._handleMessage(msg)),typeof this._t.start==="function")await this._t.start()}async close(){if(this._t&&typeof this._t.stop==="function")await this._t.stop();this._t=null}get transport(){return this._transport}get url(){return this._t?.url}async _handleMessage(raw){let{msg,parseError}=typeof raw==="string"?parse222(raw):{msg:raw};if(parseError){this._send(parseError);return}let{id,method,params}=msg;if(id===void 0){if(method==="notifications/initialized")return;return}try{switch(method){case"initialize":this._send(ok222(id,{protocolVersion:PROTOCOL_VERSION222,capabilities:{tools:{}},serverInfo:SERVER_INFO222}));break;case"tools/list":this._send(ok222(id,{tools:this._visibleTools()}));break;case"tools/call":await this._handleToolCall(id,params);break;case"ping":this._send(ok222(id,{}));break;default:this._send(error222(id,METHOD_NOT_FOUND222,`Method not found: ${method}`))}}catch(err){this._send(error222(id,INTERNAL_ERROR222,err.message||"Internal error"))}}async _handleToolCall(id,params){let name=params?.name,args=params?.arguments??{};if(!name){this._send(error222(id,INVALID_PARAMS222,"tools/call requires params.name"));return}let def=TOOL_DEFS222.find((t)=>t.name===name);if(!def){this._send(error222(id,METHOD_NOT_FOUND222,`Unknown tool: ${name}`));return}let collection=args.collection||args.collection_name||null;if(!this._hasScope(collection,def.scope)){this._send(ok222(id,toolError222(`Access denied: "${name}" requires "${def.scope}" scope on collection "${collection}".`)));return}try{let result=await callTool222(name,args,this._db);this._send(ok222(id,toolResult222(JSON.stringify(result,null,2))))}catch(err){this._send(ok222(id,toolError222(err.message||String(err))))}}_visibleTools(){return TOOL_DEFS222.filter((def)=>{let global=this._scopes["*"];if(global&&(global.includes(def.scope)||global.includes("admin")))return!0;for(let[,perms]of Object.entries(this._scopes))if(perms.includes(def.scope)||perms.includes("admin"))return!0;return!1})}_hasScope(collection,scope){let check=(perms)=>perms.includes("admin")||perms.includes(scope);if(collection&&this._scopes[collection])return check(this._scopes[collection]);if(this._scopes["*"])return check(this._scopes["*"]);return!1}_send(msg){this._t?.send(msg)}}var META_KEY222="migrations",_serialize222=(value)=>JSON.stringify(value,function(key,v){let raw=this[key];if(raw instanceof Date)return{__skalex_date__:raw.toISOString()};if(typeof v==="bigint")return{__skalex_bigint__:v.toString()};return v}),_deserialize222=(text)=>JSON.parse(text,(_,v)=>{if(v&&typeof v==="object"){if("__skalex_bigint__"in v)return BigInt(v.__skalex_bigint__);if("__skalex_date__"in v)return new Date(v.__skalex_date__)}return v});class Skalex222{constructor({path="./.db",format="gz",debug=!1,adapter,ai,encrypt,slowQueryLog,queryCache,memory,logger:logger$1,plugins,llmAdapter,embeddingAdapter,regexMaxLength,idGenerator,serializer,deserializer,autoSave,ttlSweepInterval,lenientLoad}={}){if(this.dataDirectory=path,this.dataFormat=format,this.debug=debug,!Skalex222._errorsAttached)Skalex222.SkalexError=SkalexError222,Skalex222.ValidationError=ValidationError222,Skalex222.UniqueConstraintError=UniqueConstraintError222,Skalex222.TransactionError=TransactionError222,Skalex222.PersistenceError=PersistenceError222,Skalex222.AdapterError=AdapterError222,Skalex222.QueryError=QueryError222,Skalex222._errorsAttached=!0;this._adapterConfig=adapter??null;let fs=adapter||new FsAdapter222({dir:path,format});if(encrypt)fs=new EncryptedAdapter222(fs,encrypt.key);if(this.fs=fs,this._registry=new CollectionRegistry222(Collection222),this.collections=this._registry.stores,this._collectionInstances=this._registry._instances,this._migrations=new MigrationEngine222,this._connectPromise=null,this.isConnected=!1,this._aiConfig=ai||null,this._encryptConfig=encrypt||null,this._pluginsConfig=Array.isArray(plugins)?plugins:null,this._memoryConfig=memory||null,this._regexMaxLength=regexMaxLength??500,this._idGenerator=idGenerator??null,this._serializer=serializer??_serialize222,this._deserializer=deserializer??_deserialize222,this._autoSave=autoSave??!1,this._txManager=new TransactionManager222,this._ttlSweepInterval=ttlSweepInterval??0,this._ttlTimer=null,this._logger=logger$1??logger222,this._embeddingAdapter=embeddingAdapter??(ai?createEmbeddingAdapter222(ai):null),this._aiAdapter=llmAdapter??(ai?createLLMAdapter222(ai):null),this._persistence=new PersistenceManager222({adapter:this.fs,serializer:this._serializer,deserializer:this._deserializer,logger:this._logger,debug:this.debug,lenientLoad:lenientLoad??!1}),this._changeLog=new ChangeLog222(this),this._queryCache=new QueryCache222(queryCache||{}),this._eventBus=new EventBus222,this._queryLog=slowQueryLog?new QueryLog222(slowQueryLog):null,this._sessionStats=new SessionStats222,this._plugins=new PluginEngine222,Array.isArray(plugins))for(let p of plugins)this._plugins.register(p)}async connect(){if(this._connectPromise)return this._connectPromise;return this._connectPromise=this._doConnect(),this._connectPromise}async _doConnect(){try{await this.loadData();let meta=this._getMeta();if(meta.queryCache)this._queryCache.fromJSON(meta.queryCache);if(this._migrations._migrations.length>0){let applied=meta.appliedVersions||[],newApplied=await this._migrations.run((version)=>this.useCollection(`_migration_${version}`),applied);this._saveMeta({appliedVersions:newApplied})}if(this._sweepTtl(),this._ttlSweepInterval>0){if(this._ttlTimer=setInterval(()=>this._sweepTtl(),this._ttlSweepInterval),this._ttlTimer?.unref)this._ttlTimer.unref()}this.isConnected=!0,this._log("> - Connected to the database (\u221A)")}catch(error2222){throw this._logger(`Error connecting to the database: ${error2222}`,"error"),error2222}}async disconnect(){try{if(this._ttlTimer)clearInterval(this._ttlTimer),this._ttlTimer=null;await this.saveData(),this._registry.clear(),this.collections=this._registry.stores,this._collectionInstances=this._registry._instances,this._connectPromise=null,this.isConnected=!1,this._log("> - Disconnected from the database (\u221A)")}catch(error2222){throw this._logger(`Error disconnecting from the database: ${error2222}`,"error"),error2222}}async _ensureConnected(){if(this.isConnected)return;return this.connect()}useCollection(collectionName){return this._registry.get(collectionName,this)}createCollection(collectionName,options={}){return this._registry.create(collectionName,options,this)}_createCollectionStore(collectionName,options={}){this._registry.createStore(collectionName,options)}async renameCollection(from,to){this._registry.rename(from,to),await this.saveData(to),await this.fs.delete(from)}async loadData(){await this._persistence.loadAll(this.collections,{parseSchema:parseSchema222,buildIndex:this._registry.buildIndex,IndexEngine:IndexEngine222});for(let name in this._collectionInstances){let store=this.collections[name];if(store&&this._collectionInstances[name]._store!==store)this._collectionInstances[name]._store=store}}async saveData(collectionName){await this._persistence.save(this.collections,collectionName)}buildIndex(data,keyField){return this._registry.buildIndex(data,keyField)}addMigration(migration){this._migrations.add(migration)}migrationStatus(){let meta=this._getMeta();return this._migrations.status(meta.appliedVersions||[])}namespace(id){if(this._adapterConfig)throw new AdapterError222("ERR_SKALEX_ADAPTER_NAMESPACE_REQUIRES_FS","namespace() requires the default FsAdapter. When a custom storage adapter is configured, create a separate Skalex instance with your adapter instead.");let safeId=String(id).replace(/[^a-zA-Z0-9_-]/g,"_");if(!safeId)throw new ValidationError222("ERR_SKALEX_VALIDATION_NAMESPACE_ID","namespace: id must contain at least one alphanumeric character",{id});return new Skalex222({path:`${this.dataDirectory}/${safeId}`,format:this.dataFormat,debug:this.debug,ai:this._aiConfig||void 0,encrypt:this._encryptConfig||void 0,slowQueryLog:this._queryLog?{threshold:this._queryLog._threshold,maxEntries:this._queryLog._maxEntries}:void 0,queryCache:this._queryCache?{maxSize:this._queryCache._maxSize,ttl:this._queryCache._ttl}:void 0,plugins:this._pluginsConfig||void 0,memory:this._memoryConfig||void 0,logger:this._logger!==logger222?this._logger:void 0,llmAdapter:this._aiAdapter&&!this._aiConfig?this._aiAdapter:void 0,embeddingAdapter:this._embeddingAdapter&&!this._aiConfig?this._embeddingAdapter:void 0,regexMaxLength:this._regexMaxLength!==500?this._regexMaxLength:void 0,idGenerator:this._idGenerator||void 0,serializer:this._serializer!==_serialize222?this._serializer:void 0,deserializer:this._deserializer!==_deserialize222?this._deserializer:void 0,autoSave:this._autoSave||void 0,ttlSweepInterval:this._ttlSweepInterval||void 0})}use(plugin){this._plugins.register(plugin)}watch(callback){return this._eventBus.on("*",callback)}sessionStats(sessionId){if(sessionId!==void 0)return this._sessionStats.get(sessionId);return this._sessionStats.all()}get _inTransaction(){return this._txManager.active}_emitEvent(collectionName,data){if(!this._txManager.defer(()=>this._eventBus.emit(collectionName,data)))this._eventBus.emit(collectionName,data)}async _runAfterHook(hook,data){if(!this._txManager.defer(()=>this._plugins.run(hook,data)))await this._plugins.run(hook,data)}async _logChange(op,collectionName,doc,prev,session){if(!this._txManager.defer(()=>this._changeLog.log(op,collectionName,doc,prev,session)))await this._changeLog.log(op,collectionName,doc,prev,session)}async transaction(fn,opts={}){return this._txManager.run(fn,this,opts)}async seed(fixtures,{reset=!1}={}){for(let[name,docs]of Object.entries(fixtures)){if(reset&&this.collections[name])this._applySnapshot(name,{data:[],index:new Map}),delete this._collectionInstances[name];await this.useCollection(name).insertMany(docs)}await this.saveData()}dump(){return this._registry.dump()}inspect(collectionName){return this._registry.inspect(collectionName)}async import(filePath){let content=await this.fs.readRaw(filePath),docs;try{docs=JSON.parse(content)}catch{throw new PersistenceError222("ERR_SKALEX_PERSISTENCE_INVALID_JSON",`import: invalid JSON in file "${filePath}"`,{filePath})}let name=filePath.split("/").pop().replace(/\.[^.]+$/,"");return this.useCollection(name).insertMany(Array.isArray(docs)?docs:[docs],{save:!0})}async embed(text){if(!this._embeddingAdapter)throw new AdapterError222("ERR_SKALEX_ADAPTER_EMBEDDING_REQUIRED","db.embed() requires an AI adapter. Pass { ai: { provider, apiKey } } to the Skalex constructor.");return this._embeddingAdapter.embed(text)}async ask(collectionName,nlQuery,{limit=20}={}){if(!this._aiAdapter)throw new AdapterError222("ERR_SKALEX_ADAPTER_LLM_REQUIRED",'db.ask() requires a language model adapter. Configure { ai: { provider, model: "..." } }.');let col=this.useCollection(collectionName),schema=this.schema(collectionName),filter=this._queryCache.get(collectionName,schema,nlQuery);if(!filter){filter=await this._aiAdapter.generate(schema,nlQuery);let warnings=validateLLMFilter222(filter,schema);if(warnings.length)warnings.forEach((w)=>this._log(`[ask] ${w}`));this._queryCache.set(collectionName,schema,nlQuery,filter),this._saveMeta({queryCache:this._queryCache.toJSON()})}return col.find(processLLMFilter222(filter,{regexMaxLength:this._regexMaxLength}),{limit})}schema(collectionName){return this._registry.schema(collectionName)}useMemory(sessionId){return new Memory222(sessionId,this)}changelog(){return this._changeLog}async restore(collectionName,timestamp,opts={}){return this._changeLog.restore(collectionName,timestamp,opts)}stats(collectionName){return this._registry.stats(collectionName)}slowQueries(opts={}){if(!this._queryLog)return[];return this._queryLog.entries(opts)}slowQueryCount(){return this._queryLog?this._queryLog.size:0}clearSlowQueries(){this._queryLog?.clear()}mcp(opts={}){return new SkalexMCPServer222(this,opts)}_getMeta(){let metaCol=this.collections._meta;if(!metaCol)return{};return metaCol.index.get(META_KEY222)||{}}_saveMeta(data){if(!this.collections._meta)this._createCollectionStore("_meta");let col=this.collections._meta,existing=col.index.get(META_KEY222);if(existing)Object.assign(existing,data);else{let doc={_id:META_KEY222,...data};col.data.push(doc),col.index.set(META_KEY222,doc)}this._persistence.markDirty(this.collections,"_meta")}_sweepTtl(){for(let name in this.collections){let col=this.collections[name],removed=sweep222(col.data,col.index,col.fieldIndex?(doc)=>col.fieldIndex.remove(doc):null);if(removed>0)this._persistence.markDirty(this.collections,name),this._log(`TTL sweep: removed ${removed} expired docs from "${name}"`)}}_buildCollectionContext(){let db=this;return{ensureConnected:()=>db._ensureConnected(),get txManager(){return db._txManager},get plugins(){return db._plugins},get eventBus(){return db._eventBus},get sessionStats(){return db._sessionStats},get queryLog(){return db._queryLog},get logger(){return db._logger},get persistence(){return db._persistence},get collections(){return db.collections},embed:(text)=>db.embed(text),get idGenerator(){return db._idGenerator},get autoSave(){return db._autoSave},saveCollection:(name)=>db.saveData(name),snapshotCollection:(col)=>db._snapshotCollection(col),getCollection:(name)=>db.useCollection(name),emitEvent:(name,data)=>db._emitEvent(name,data),runAfterHook:(hook,data)=>db._runAfterHook(hook,data),logChange:(op,col,doc,prev,session)=>db._logChange(op,col,doc,prev,session),get fs(){return db.fs},get dataDirectory(){return db.dataDirectory}}}_log(msg){if(this.debug)this._logger(msg,"info")}_snapshotCollection(col){return{data:structuredClone(col.data)}}_applySnapshot(name,snap){let col=this.collections[name];if(!col)return;if(col.data=snap.data,col.index=this.buildIndex(snap.data,"_id"),col.fieldIndex)col.fieldIndex.buildFromData(snap.data)}}class AgentDatabase{}var registry=new Map;function registerAdapter(name,factory){registry.set(name,factory)}var nowIso=()=>new Date().toISOString();function cleanDoc(doc){if(!doc)return doc;let{_id:_ignoredId,createdAt:rawCreatedAt,updatedAt:rawUpdatedAt,_version:_ignoredVersion,_expiresAt:_ignoredExpires,...rest}=doc,out={...rest};if(out.createdAt==null&&rawCreatedAt!=null)out.createdAt=rawCreatedAt instanceof Date?rawCreatedAt.toISOString():String(rawCreatedAt);if(out.updatedAt==null&&rawUpdatedAt!=null)out.updatedAt=rawUpdatedAt instanceof Date?rawUpdatedAt.toISOString():String(rawUpdatedAt);return out}class SkalexAgentDatabase extends AgentDatabase{dataDir;encryptionKey;lockPath;lockFd=null;db;tasks;config;gitRepos;bookmarks;notifications;pluginState;constructor(opts){super();this.dataDir=opts.dataDir,this.encryptionKey=opts.encryptionKey,this.lockPath=join(opts.dataDir,".agent-db.lock")}static async create(opts){if(!existsSync(opts.dataDir))mkdirSync(opts.dataDir,{recursive:!0});let instance=new SkalexAgentDatabase(opts);instance.acquireLock();try{await instance.init()}catch(err){throw instance.releaseLock(),err}return instance}acquireLock(){try{this.lockFd=openSync(this.lockPath,"wx",384),writeFileSync(this.lockFd,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()}));return}catch(err){if(err.code!=="EEXIST")throw err}let stale=!1;try{let raw=JSON.parse(readFileSync(this.lockPath,"utf8"));if(!raw.pid)stale=!0;else try{process.kill(raw.pid,0)}catch{stale=!0}}catch{stale=!0}if(stale){try{unlinkSync(this.lockPath)}catch{}this.acquireLock();return}throw Error(`Agent database is already open by another process (${this.lockPath})`)}releaseLock(){if(this.lockFd!==null){try{closeSync(this.lockFd)}catch{}this.lockFd=null}try{unlinkSync(this.lockPath)}catch{}}async init(){this.db=new Skalex222({path:this.dataDir,encrypt:{key:this.encryptionKey},autoSave:!0,format:"gz",lenientLoad:!0}),this.tasks=this.db.createCollection("tasks",{schema:{id:{type:"string",required:!0,unique:!0},type:{type:"string",required:!0,enum:["command","script","file_operation"]},status:{type:"string",required:!0,enum:["pending","running","completed","failed"]},payload:{type:"string",required:!0},result:{type:"string"},error:{type:"string"},calendarTaskId:{type:"string"},exitCode:{type:"number"},timeout:{type:"number"}},indexes:["status","type"]}),this.config=this.db.createCollection("agent_config",{schema:{key:{type:"string",required:!0,unique:!0},value:{type:"string",required:!0}}}),this.gitRepos=this.db.createCollection("git_repositories",{schema:{id:{type:"string",required:!0,unique:!0},path:{type:"string",required:!0,unique:!0},name:{type:"string",required:!0},parentPath:{type:"string"},isSubmodule:{type:"boolean"},projectType:{type:"string"},vitePort:{type:"number"},lastScanned:{type:"string"}},indexes:["parentPath"]}),this.bookmarks=this.db.createCollection("bookmarked_commands",{schema:{id:{type:"string",required:!0,unique:!0},projectId:{type:"string"},command:{type:"string",required:!0},description:{type:"string"},category:{type:"string"}},indexes:["projectId","category"]}),this.notifications=this.db.createCollection("notifications",{schema:{id:{type:"string",required:!0,unique:!0},sessionName:{type:"string"},projectId:{type:"string"},type:{type:"string",required:!0,enum:["info","success","warning","error"]},title:{type:"string",required:!0},message:{type:"string",required:!0},status:{type:"string",required:!0,enum:["unread","read"]}},indexes:["status","projectId"]}),this.pluginState=this.db.createCollection("plugin_state",{schema:{pluginName:{type:"string",required:!0},key:{type:"string",required:!0},value:{type:"string",required:!0}},indexes:["pluginName"]}),await this.db.connect()}async close(){if(this.db?.isConnected)await this.db.disconnect();this.releaseLock()}getDbPath(){return this.dataDir}async createTask(task){let doc={id:task.id,type:task.type,status:task.status,payload:task.payload};if(task.result!=null)doc.result=task.result;if(task.error!=null)doc.error=task.error;if(task.calendarTaskId!=null)doc.calendarTaskId=task.calendarTaskId;if(task.exitCode!=null)doc.exitCode=task.exitCode;if(task.timeout!=null)doc.timeout=task.timeout;let inserted=await this.tasks.insertOne(doc);return cleanDoc(inserted)}async getTask(id){let doc=await this.tasks.findOne({id});return doc?cleanDoc(doc):void 0}async getAllTasks(){return(await this.tasks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async getPendingTasks(){return(await this.tasks.find({status:"pending"},{sort:{createdAt:1}})).docs.map((d)=>cleanDoc(d))}async updateTask(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.tasks.updateOne({id},patch)}async cancelTask(id){let existing=await this.tasks.findOne({id});if(!existing||existing.status!=="pending"&&existing.status!=="running")return!1;return await this.tasks.updateOne({id},{status:"failed",error:"Cancelled"}),!0}async getConfig(key){return(await this.config.findOne({key}))?.value}async setConfig(key,value){await this.config.upsert({key},{key,value})}async deleteConfig(key){return await this.config.deleteOne({key})!==null}async getAllConfig(){let res=await this.config.find(),out={};for(let doc of res.docs)out[doc.key]=doc.value;return out}async bulkSetConfig(entries){for(let[key,value]of Object.entries(entries))await this.config.upsert({key},{key,value})}async getConfigStatus(){let res=await this.config.find(),latest=null;for(let doc of res.docs){let raw=doc.updatedAt,iso=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:null;if(iso&&(!latest||iso>latest))latest=iso}return{totalKeys:res.docs.length,lastUpdated:latest}}async createGitRepository(repo){let doc={id:repo.id,path:repo.path,name:repo.name,isSubmodule:Boolean(repo.isSubmodule),lastScanned:nowIso()};if(repo.parentPath!=null)doc.parentPath=repo.parentPath;if(repo.projectType!=null)doc.projectType=repo.projectType;if(repo.vitePort!=null)doc.vitePort=repo.vitePort;let inserted=await this.gitRepos.insertOne(doc);return cleanDoc(inserted)}async getGitRepository(id){let doc=await this.gitRepos.findOne({id});return doc?cleanDoc(doc):void 0}async getGitRepositoryByPath(path){let doc=await this.gitRepos.findOne({path});return doc?cleanDoc(doc):void 0}async getAllGitRepositories(){return(await this.gitRepos.find(void 0,{sort:{path:1}})).docs.map((d)=>cleanDoc(d))}async updateGitRepository(id,updates){let patch={lastScanned:nowIso()};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;if(k==="isSubmodule"){patch[k]=Boolean(v);continue}patch[k]=v??null}await this.gitRepos.updateOne({id},patch)}async deleteGitRepository(id){return await this.gitRepos.deleteOne({id})!==null}async fixGitHierarchy(){let repos=await this.getAllGitRepositories(),fixed=0;for(let repo of repos){if(repo.isSubmodule)continue;let parent=repos.find((r)=>r.id!==repo.id&&repo.path.startsWith(`${r.path}/`)&&!r.isSubmodule);if(parent&&repo.parentPath!==parent.path)await this.updateGitRepository(repo.id,{parentPath:parent.path}),fixed++}return{fixed}}async createBookmarkedCommand(cmd){let doc={id:cmd.id,command:cmd.command};if(cmd.projectId!=null)doc.projectId=cmd.projectId;if(cmd.description!=null)doc.description=cmd.description;if(cmd.category!=null)doc.category=cmd.category;let inserted=await this.bookmarks.insertOne(doc);return cleanDoc(inserted)}async getBookmarkedCommand(id){let doc=await this.bookmarks.findOne({id});return doc?cleanDoc(doc):void 0}async getAllBookmarkedCommands(){return(await this.bookmarks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async getBookmarkedCommandsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.bookmarks.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async getBookmarkedCommandsByCategory(category){return(await this.bookmarks.find({category},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async updateBookmarkedCommand(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.bookmarks.updateOne({id},patch)}async deleteBookmarkedCommand(id){return await this.bookmarks.deleteOne({id})!==null}async executeBookmarkedCommand(id){return this.getBookmarkedCommand(id)}async createNotification(notification){let doc={id:notification.id,type:notification.type,title:notification.title,message:notification.message,status:notification.status};if(notification.sessionName!=null)doc.sessionName=notification.sessionName;if(notification.projectId!=null)doc.projectId=notification.projectId;let inserted=await this.notifications.insertOne(doc);return cleanDoc(inserted)}async getNotification(id){let doc=await this.notifications.findOne({id});return doc?cleanDoc(doc):void 0}async getAllNotifications(){return(await this.notifications.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async getNotificationsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.notifications.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async getGlobalNotifications(){return this.getNotificationsByProject(null)}async getUnreadNotifications(){return(await this.notifications.find({status:"unread"},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async updateNotificationStatus(id,status){await this.notifications.updateOne({id},{status})}async markAllNotificationsRead(){return(await this.notifications.updateMany({status:"unread"},{status:"read"})).length}async deleteNotification(id){return await this.notifications.deleteOne({id})!==null}async clearOldNotifications(olderThanDays=30){let cutoff=new Date(Date.now()-olderThanDays*24*60*60*1000);return(await this.notifications.deleteMany({createdAt:{$fn:(v)=>v instanceof Date&&v<cutoff}})).length}async getPluginState(pluginName,key){return(await this.pluginState.findOne({$and:[{pluginName},{key}]}))?.value}async setPluginState(pluginName,key,value){await this.pluginState.upsert({$and:[{pluginName},{key}]},{pluginName,key,value})}async deletePluginState(pluginName,key){return await this.pluginState.deleteOne({$and:[{pluginName},{key}]})!==null}async getAllPluginState(pluginName){return(await this.pluginState.find({pluginName},{sort:{key:1}})).docs.map((doc)=>{let raw=doc.updatedAt,updatedAt=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:void 0;return{key:doc.key,value:doc.value,updatedAt}})}async deleteAllPluginState(pluginName){return(await this.pluginState.deleteMany({pluginName})).length}}var createSkalexAgentDatabase=(opts)=>SkalexAgentDatabase.create(opts);registerAdapter("skalex",createSkalexAgentDatabase);var registry2=new Map;function registerAdapter2(name,factory){registry2.set(name,factory)}class AgentDatabase2{}registerAdapter2("skalex",createSkalexAgentDatabase);var nowIso2=()=>new Date().toISOString();function cleanDoc2(doc){if(!doc)return doc;let{_id:_ignoredId,createdAt:rawCreatedAt,updatedAt:rawUpdatedAt,_version:_ignoredVersion,_expiresAt:_ignoredExpires,...rest}=doc,out={...rest};if(out.createdAt==null&&rawCreatedAt!=null)out.createdAt=rawCreatedAt instanceof Date?rawCreatedAt.toISOString():String(rawCreatedAt);if(out.updatedAt==null&&rawUpdatedAt!=null)out.updatedAt=rawUpdatedAt instanceof Date?rawUpdatedAt.toISOString():String(rawUpdatedAt);return out}class SkalexAgentDatabase2 extends AgentDatabase2{dataDir;encryptionKey;lockPath;lockFd=null;db;tasks;config;gitRepos;bookmarks;notifications;pluginState;constructor(opts){super();this.dataDir=opts.dataDir,this.encryptionKey=opts.encryptionKey,this.lockPath=join2(opts.dataDir,".agent-db.lock")}static async create(opts){if(!existsSync2(opts.dataDir))mkdirSync2(opts.dataDir,{recursive:!0});let instance=new SkalexAgentDatabase2(opts);instance.acquireLock();try{await instance.init()}catch(err){throw instance.releaseLock(),err}return instance}acquireLock(){try{this.lockFd=openSync2(this.lockPath,"wx",384),writeFileSync2(this.lockFd,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()}));return}catch(err){if(err.code!=="EEXIST")throw err}let stale=!1;try{let raw=JSON.parse(readFileSync2(this.lockPath,"utf8"));if(!raw.pid)stale=!0;else try{process.kill(raw.pid,0)}catch{stale=!0}}catch{stale=!0}if(stale){try{unlinkSync2(this.lockPath)}catch{}this.acquireLock();return}throw Error(`Agent database is already open by another process (${this.lockPath})`)}releaseLock(){if(this.lockFd!==null){try{closeSync2(this.lockFd)}catch{}this.lockFd=null}try{unlinkSync2(this.lockPath)}catch{}}async init(){this.db=new Skalex22({path:this.dataDir,encrypt:{key:this.encryptionKey},autoSave:!0,format:"gz",lenientLoad:!0}),this.tasks=this.db.createCollection("tasks",{schema:{id:{type:"string",required:!0,unique:!0},type:{type:"string",required:!0,enum:["command","script","file_operation"]},status:{type:"string",required:!0,enum:["pending","running","completed","failed"]},payload:{type:"string",required:!0},result:{type:"string"},error:{type:"string"},calendarTaskId:{type:"string"},exitCode:{type:"number"},timeout:{type:"number"}},indexes:["status","type"]}),this.config=this.db.createCollection("agent_config",{schema:{key:{type:"string",required:!0,unique:!0},value:{type:"string",required:!0}}}),this.gitRepos=this.db.createCollection("git_repositories",{schema:{id:{type:"string",required:!0,unique:!0},path:{type:"string",required:!0,unique:!0},name:{type:"string",required:!0},parentPath:{type:"string"},isSubmodule:{type:"boolean"},projectType:{type:"string"},vitePort:{type:"number"},lastScanned:{type:"string"}},indexes:["parentPath"]}),this.bookmarks=this.db.createCollection("bookmarked_commands",{schema:{id:{type:"string",required:!0,unique:!0},projectId:{type:"string"},command:{type:"string",required:!0},description:{type:"string"},category:{type:"string"}},indexes:["projectId","category"]}),this.notifications=this.db.createCollection("notifications",{schema:{id:{type:"string",required:!0,unique:!0},sessionName:{type:"string"},projectId:{type:"string"},type:{type:"string",required:!0,enum:["info","success","warning","error"]},title:{type:"string",required:!0},message:{type:"string",required:!0},status:{type:"string",required:!0,enum:["unread","read"]}},indexes:["status","projectId"]}),this.pluginState=this.db.createCollection("plugin_state",{schema:{pluginName:{type:"string",required:!0},key:{type:"string",required:!0},value:{type:"string",required:!0}},indexes:["pluginName"]}),await this.db.connect()}async close(){if(this.db?.isConnected)await this.db.disconnect();this.releaseLock()}getDbPath(){return this.dataDir}async createTask(task){let doc={id:task.id,type:task.type,status:task.status,payload:task.payload};if(task.result!=null)doc.result=task.result;if(task.error!=null)doc.error=task.error;if(task.calendarTaskId!=null)doc.calendarTaskId=task.calendarTaskId;if(task.exitCode!=null)doc.exitCode=task.exitCode;if(task.timeout!=null)doc.timeout=task.timeout;let inserted=await this.tasks.insertOne(doc);return cleanDoc2(inserted)}async getTask(id){let doc=await this.tasks.findOne({id});return doc?cleanDoc2(doc):void 0}async getAllTasks(){return(await this.tasks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async getPendingTasks(){return(await this.tasks.find({status:"pending"},{sort:{createdAt:1}})).docs.map((d)=>cleanDoc2(d))}async updateTask(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.tasks.updateOne({id},patch)}async cancelTask(id){let existing=await this.tasks.findOne({id});if(!existing||existing.status!=="pending"&&existing.status!=="running")return!1;return await this.tasks.updateOne({id},{status:"failed",error:"Cancelled"}),!0}async getConfig(key){return(await this.config.findOne({key}))?.value}async setConfig(key,value){await this.config.upsert({key},{key,value})}async deleteConfig(key){return await this.config.deleteOne({key})!==null}async getAllConfig(){let res=await this.config.find(),out={};for(let doc of res.docs)out[doc.key]=doc.value;return out}async bulkSetConfig(entries){for(let[key,value]of Object.entries(entries))await this.config.upsert({key},{key,value})}async getConfigStatus(){let res=await this.config.find(),latest=null;for(let doc of res.docs){let raw=doc.updatedAt,iso=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:null;if(iso&&(!latest||iso>latest))latest=iso}return{totalKeys:res.docs.length,lastUpdated:latest}}async createGitRepository(repo){let doc={id:repo.id,path:repo.path,name:repo.name,isSubmodule:Boolean(repo.isSubmodule),lastScanned:nowIso2()};if(repo.parentPath!=null)doc.parentPath=repo.parentPath;if(repo.projectType!=null)doc.projectType=repo.projectType;if(repo.vitePort!=null)doc.vitePort=repo.vitePort;let inserted=await this.gitRepos.insertOne(doc);return cleanDoc2(inserted)}async getGitRepository(id){let doc=await this.gitRepos.findOne({id});return doc?cleanDoc2(doc):void 0}async getGitRepositoryByPath(path){let doc=await this.gitRepos.findOne({path});return doc?cleanDoc2(doc):void 0}async getAllGitRepositories(){return(await this.gitRepos.find(void 0,{sort:{path:1}})).docs.map((d)=>cleanDoc2(d))}async updateGitRepository(id,updates){let patch={lastScanned:nowIso2()};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;if(k==="isSubmodule"){patch[k]=Boolean(v);continue}patch[k]=v??null}await this.gitRepos.updateOne({id},patch)}async deleteGitRepository(id){return await this.gitRepos.deleteOne({id})!==null}async fixGitHierarchy(){let repos=await this.getAllGitRepositories(),fixed=0;for(let repo of repos){if(repo.isSubmodule)continue;let parent=repos.find((r)=>r.id!==repo.id&&repo.path.startsWith(`${r.path}/`)&&!r.isSubmodule);if(parent&&repo.parentPath!==parent.path)await this.updateGitRepository(repo.id,{parentPath:parent.path}),fixed++}return{fixed}}async createBookmarkedCommand(cmd){let doc={id:cmd.id,command:cmd.command};if(cmd.projectId!=null)doc.projectId=cmd.projectId;if(cmd.description!=null)doc.description=cmd.description;if(cmd.category!=null)doc.category=cmd.category;let inserted=await this.bookmarks.insertOne(doc);return cleanDoc2(inserted)}async getBookmarkedCommand(id){let doc=await this.bookmarks.findOne({id});return doc?cleanDoc2(doc):void 0}async getAllBookmarkedCommands(){return(await this.bookmarks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async getBookmarkedCommandsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.bookmarks.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async getBookmarkedCommandsByCategory(category){return(await this.bookmarks.find({category},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async updateBookmarkedCommand(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.bookmarks.updateOne({id},patch)}async deleteBookmarkedCommand(id){return await this.bookmarks.deleteOne({id})!==null}async executeBookmarkedCommand(id){return this.getBookmarkedCommand(id)}async createNotification(notification){let doc={id:notification.id,type:notification.type,title:notification.title,message:notification.message,status:notification.status};if(notification.sessionName!=null)doc.sessionName=notification.sessionName;if(notification.projectId!=null)doc.projectId=notification.projectId;let inserted=await this.notifications.insertOne(doc);return cleanDoc2(inserted)}async getNotification(id){let doc=await this.notifications.findOne({id});return doc?cleanDoc2(doc):void 0}async getAllNotifications(){return(await this.notifications.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async getNotificationsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.notifications.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async getGlobalNotifications(){return this.getNotificationsByProject(null)}async getUnreadNotifications(){return(await this.notifications.find({status:"unread"},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async updateNotificationStatus(id,status){await this.notifications.updateOne({id},{status})}async markAllNotificationsRead(){return(await this.notifications.updateMany({status:"unread"},{status:"read"})).length}async deleteNotification(id){return await this.notifications.deleteOne({id})!==null}async clearOldNotifications(olderThanDays=30){let cutoff=new Date(Date.now()-olderThanDays*24*60*60*1000);return(await this.notifications.deleteMany({createdAt:{$fn:(v)=>v instanceof Date&&v<cutoff}})).length}async getPluginState(pluginName,key){return(await this.pluginState.findOne({$and:[{pluginName},{key}]}))?.value}async setPluginState(pluginName,key,value){await this.pluginState.upsert({$and:[{pluginName},{key}]},{pluginName,key,value})}async deletePluginState(pluginName,key){return await this.pluginState.deleteOne({$and:[{pluginName},{key}]})!==null}async getAllPluginState(pluginName){return(await this.pluginState.find({pluginName},{sort:{key:1}})).docs.map((doc)=>{let raw=doc.updatedAt,updatedAt=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:void 0;return{key:doc.key,value:doc.value,updatedAt}})}async deleteAllPluginState(pluginName){return(await this.pluginState.deleteMany({pluginName})).length}}var createSkalexAgentDatabase2=(opts)=>SkalexAgentDatabase2.create(opts);registerAdapter2("skalex",createSkalexAgentDatabase2);var registry3=new Map;function registerAdapter3(name,factory){registry3.set(name,factory)}class AgentDatabase3{}registerAdapter3("skalex",createSkalexAgentDatabase2);var nowIso3=()=>new Date().toISOString();function cleanDoc3(doc){if(!doc)return doc;let{_id:_ignoredId,createdAt:rawCreatedAt,updatedAt:rawUpdatedAt,_version:_ignoredVersion,_expiresAt:_ignoredExpires,...rest}=doc,out={...rest};if(out.createdAt==null&&rawCreatedAt!=null)out.createdAt=rawCreatedAt instanceof Date?rawCreatedAt.toISOString():String(rawCreatedAt);if(out.updatedAt==null&&rawUpdatedAt!=null)out.updatedAt=rawUpdatedAt instanceof Date?rawUpdatedAt.toISOString():String(rawUpdatedAt);return out}class SkalexAgentDatabase3 extends AgentDatabase3{dataDir;encryptionKey;lockPath;lockFd=null;db;tasks;config;gitRepos;bookmarks;notifications;pluginState;constructor(opts){super();this.dataDir=opts.dataDir,this.encryptionKey=opts.encryptionKey,this.lockPath=join3(opts.dataDir,".agent-db.lock")}static async create(opts){if(!existsSync3(opts.dataDir))mkdirSync3(opts.dataDir,{recursive:!0});let instance=new SkalexAgentDatabase3(opts);instance.acquireLock();try{await instance.init()}catch(err){throw instance.releaseLock(),err}return instance}acquireLock(){try{this.lockFd=openSync3(this.lockPath,"wx",384),writeFileSync3(this.lockFd,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()}));return}catch(err){if(err.code!=="EEXIST")throw err}let stale=!1;try{let raw=JSON.parse(readFileSync3(this.lockPath,"utf8"));if(!raw.pid)stale=!0;else try{process.kill(raw.pid,0)}catch{stale=!0}}catch{stale=!0}if(stale){try{unlinkSync3(this.lockPath)}catch{}this.acquireLock();return}throw Error(`Agent database is already open by another process (${this.lockPath})`)}releaseLock(){if(this.lockFd!==null){try{closeSync3(this.lockFd)}catch{}this.lockFd=null}try{unlinkSync3(this.lockPath)}catch{}}async init(){this.db=new Skalex2({path:this.dataDir,encrypt:{key:this.encryptionKey},autoSave:!0,format:"gz",lenientLoad:!0}),this.tasks=this.db.createCollection("tasks",{schema:{id:{type:"string",required:!0,unique:!0},type:{type:"string",required:!0,enum:["command","script","file_operation"]},status:{type:"string",required:!0,enum:["pending","running","completed","failed"]},payload:{type:"string",required:!0},result:{type:"string"},error:{type:"string"},calendarTaskId:{type:"string"},exitCode:{type:"number"},timeout:{type:"number"}},indexes:["status","type"]}),this.config=this.db.createCollection("agent_config",{schema:{key:{type:"string",required:!0,unique:!0},value:{type:"string",required:!0}}}),this.gitRepos=this.db.createCollection("git_repositories",{schema:{id:{type:"string",required:!0,unique:!0},path:{type:"string",required:!0,unique:!0},name:{type:"string",required:!0},parentPath:{type:"string"},isSubmodule:{type:"boolean"},projectType:{type:"string"},vitePort:{type:"number"},lastScanned:{type:"string"}},indexes:["parentPath"]}),this.bookmarks=this.db.createCollection("bookmarked_commands",{schema:{id:{type:"string",required:!0,unique:!0},projectId:{type:"string"},command:{type:"string",required:!0},description:{type:"string"},category:{type:"string"}},indexes:["projectId","category"]}),this.notifications=this.db.createCollection("notifications",{schema:{id:{type:"string",required:!0,unique:!0},sessionName:{type:"string"},projectId:{type:"string"},type:{type:"string",required:!0,enum:["info","success","warning","error"]},title:{type:"string",required:!0},message:{type:"string",required:!0},status:{type:"string",required:!0,enum:["unread","read"]}},indexes:["status","projectId"]}),this.pluginState=this.db.createCollection("plugin_state",{schema:{pluginName:{type:"string",required:!0},key:{type:"string",required:!0},value:{type:"string",required:!0}},indexes:["pluginName"]}),await this.db.connect()}async close(){if(this.db?.isConnected)await this.db.disconnect();this.releaseLock()}getDbPath(){return this.dataDir}async createTask(task){let doc={id:task.id,type:task.type,status:task.status,payload:task.payload};if(task.result!=null)doc.result=task.result;if(task.error!=null)doc.error=task.error;if(task.calendarTaskId!=null)doc.calendarTaskId=task.calendarTaskId;if(task.exitCode!=null)doc.exitCode=task.exitCode;if(task.timeout!=null)doc.timeout=task.timeout;let inserted=await this.tasks.insertOne(doc);return cleanDoc3(inserted)}async getTask(id){let doc=await this.tasks.findOne({id});return doc?cleanDoc3(doc):void 0}async getAllTasks(){return(await this.tasks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async getPendingTasks(){return(await this.tasks.find({status:"pending"},{sort:{createdAt:1}})).docs.map((d)=>cleanDoc3(d))}async updateTask(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.tasks.updateOne({id},patch)}async cancelTask(id){let existing=await this.tasks.findOne({id});if(!existing||existing.status!=="pending"&&existing.status!=="running")return!1;return await this.tasks.updateOne({id},{status:"failed",error:"Cancelled"}),!0}async getConfig(key){return(await this.config.findOne({key}))?.value}async setConfig(key,value){await this.config.upsert({key},{key,value})}async deleteConfig(key){return await this.config.deleteOne({key})!==null}async getAllConfig(){let res=await this.config.find(),out={};for(let doc of res.docs)out[doc.key]=doc.value;return out}async bulkSetConfig(entries){for(let[key,value]of Object.entries(entries))await this.config.upsert({key},{key,value})}async getConfigStatus(){let res=await this.config.find(),latest=null;for(let doc of res.docs){let raw=doc.updatedAt,iso=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:null;if(iso&&(!latest||iso>latest))latest=iso}return{totalKeys:res.docs.length,lastUpdated:latest}}async createGitRepository(repo){let doc={id:repo.id,path:repo.path,name:repo.name,isSubmodule:Boolean(repo.isSubmodule),lastScanned:nowIso3()};if(repo.parentPath!=null)doc.parentPath=repo.parentPath;if(repo.projectType!=null)doc.projectType=repo.projectType;if(repo.vitePort!=null)doc.vitePort=repo.vitePort;let inserted=await this.gitRepos.insertOne(doc);return cleanDoc3(inserted)}async getGitRepository(id){let doc=await this.gitRepos.findOne({id});return doc?cleanDoc3(doc):void 0}async getGitRepositoryByPath(path){let doc=await this.gitRepos.findOne({path});return doc?cleanDoc3(doc):void 0}async getAllGitRepositories(){return(await this.gitRepos.find(void 0,{sort:{path:1}})).docs.map((d)=>cleanDoc3(d))}async updateGitRepository(id,updates){let patch={lastScanned:nowIso3()};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;if(k==="isSubmodule"){patch[k]=Boolean(v);continue}patch[k]=v??null}await this.gitRepos.updateOne({id},patch)}async deleteGitRepository(id){return await this.gitRepos.deleteOne({id})!==null}async fixGitHierarchy(){let repos=await this.getAllGitRepositories(),fixed=0;for(let repo of repos){if(repo.isSubmodule)continue;let parent=repos.find((r)=>r.id!==repo.id&&repo.path.startsWith(`${r.path}/`)&&!r.isSubmodule);if(parent&&repo.parentPath!==parent.path)await this.updateGitRepository(repo.id,{parentPath:parent.path}),fixed++}return{fixed}}async createBookmarkedCommand(cmd){let doc={id:cmd.id,command:cmd.command};if(cmd.projectId!=null)doc.projectId=cmd.projectId;if(cmd.description!=null)doc.description=cmd.description;if(cmd.category!=null)doc.category=cmd.category;let inserted=await this.bookmarks.insertOne(doc);return cleanDoc3(inserted)}async getBookmarkedCommand(id){let doc=await this.bookmarks.findOne({id});return doc?cleanDoc3(doc):void 0}async getAllBookmarkedCommands(){return(await this.bookmarks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async getBookmarkedCommandsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.bookmarks.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async getBookmarkedCommandsByCategory(category){return(await this.bookmarks.find({category},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async updateBookmarkedCommand(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.bookmarks.updateOne({id},patch)}async deleteBookmarkedCommand(id){return await this.bookmarks.deleteOne({id})!==null}async executeBookmarkedCommand(id){return this.getBookmarkedCommand(id)}async createNotification(notification){let doc={id:notification.id,type:notification.type,title:notification.title,message:notification.message,status:notification.status};if(notification.sessionName!=null)doc.sessionName=notification.sessionName;if(notification.projectId!=null)doc.projectId=notification.projectId;let inserted=await this.notifications.insertOne(doc);return cleanDoc3(inserted)}async getNotification(id){let doc=await this.notifications.findOne({id});return doc?cleanDoc3(doc):void 0}async getAllNotifications(){return(await this.notifications.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async getNotificationsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.notifications.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async getGlobalNotifications(){return this.getNotificationsByProject(null)}async getUnreadNotifications(){return(await this.notifications.find({status:"unread"},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async updateNotificationStatus(id,status){await this.notifications.updateOne({id},{status})}async markAllNotificationsRead(){return(await this.notifications.updateMany({status:"unread"},{status:"read"})).length}async deleteNotification(id){return await this.notifications.deleteOne({id})!==null}async clearOldNotifications(olderThanDays=30){let cutoff=new Date(Date.now()-olderThanDays*24*60*60*1000);return(await this.notifications.deleteMany({createdAt:{$fn:(v)=>v instanceof Date&&v<cutoff}})).length}async getPluginState(pluginName,key){return(await this.pluginState.findOne({$and:[{pluginName},{key}]}))?.value}async setPluginState(pluginName,key,value){await this.pluginState.upsert({$and:[{pluginName},{key}]},{pluginName,key,value})}async deletePluginState(pluginName,key){return await this.pluginState.deleteOne({$and:[{pluginName},{key}]})!==null}async getAllPluginState(pluginName){return(await this.pluginState.find({pluginName},{sort:{key:1}})).docs.map((doc)=>{let raw=doc.updatedAt,updatedAt=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:void 0;return{key:doc.key,value:doc.value,updatedAt}})}async deleteAllPluginState(pluginName){return(await this.pluginState.deleteMany({pluginName})).length}}var createSkalexAgentDatabase3=(opts)=>SkalexAgentDatabase3.create(opts);registerAdapter3("skalex",createSkalexAgentDatabase3);var registry4=new Map;function registerAdapter4(name,factory){registry4.set(name,factory)}class AgentDatabase4{}registerAdapter4("skalex",createSkalexAgentDatabase3);var nowIso4=()=>new Date().toISOString();function cleanDoc4(doc){if(!doc)return doc;let{_id:_ignoredId,createdAt:rawCreatedAt,updatedAt:rawUpdatedAt,_version:_ignoredVersion,_expiresAt:_ignoredExpires,...rest}=doc,out={...rest};if(out.createdAt==null&&rawCreatedAt!=null)out.createdAt=rawCreatedAt instanceof Date?rawCreatedAt.toISOString():String(rawCreatedAt);if(out.updatedAt==null&&rawUpdatedAt!=null)out.updatedAt=rawUpdatedAt instanceof Date?rawUpdatedAt.toISOString():String(rawUpdatedAt);return out}class SkalexAgentDatabase4 extends AgentDatabase4{dataDir;encryptionKey;lockPath;lockFd=null;db;tasks;config;gitRepos;bookmarks;notifications;pluginState;constructor(opts){super();this.dataDir=opts.dataDir,this.encryptionKey=opts.encryptionKey,this.lockPath=join4(opts.dataDir,".agent-db.lock")}static async create(opts){if(!existsSync4(opts.dataDir))mkdirSync4(opts.dataDir,{recursive:!0});let instance=new SkalexAgentDatabase4(opts);instance.acquireLock();try{await instance.init()}catch(err){throw instance.releaseLock(),err}return instance}acquireLock(){try{this.lockFd=openSync4(this.lockPath,"wx",384),writeFileSync4(this.lockFd,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()}));return}catch(err){if(err.code!=="EEXIST")throw err}let stale=!1;try{let raw=JSON.parse(readFileSync4(this.lockPath,"utf8"));if(!raw.pid)stale=!0;else try{process.kill(raw.pid,0)}catch{stale=!0}}catch{stale=!0}if(stale){try{unlinkSync4(this.lockPath)}catch{}this.acquireLock();return}throw Error(`Agent database is already open by another process (${this.lockPath})`)}releaseLock(){if(this.lockFd!==null){try{closeSync4(this.lockFd)}catch{}this.lockFd=null}try{unlinkSync4(this.lockPath)}catch{}}async init(){this.db=new Skalex({path:this.dataDir,encrypt:{key:this.encryptionKey},autoSave:!0,format:"gz",lenientLoad:!0}),this.tasks=this.db.createCollection("tasks",{schema:{id:{type:"string",required:!0,unique:!0},type:{type:"string",required:!0,enum:["command","script","file_operation"]},status:{type:"string",required:!0,enum:["pending","running","completed","failed"]},payload:{type:"string",required:!0},result:{type:"string"},error:{type:"string"},calendarTaskId:{type:"string"},exitCode:{type:"number"},timeout:{type:"number"}},indexes:["status","type"]}),this.config=this.db.createCollection("agent_config",{schema:{key:{type:"string",required:!0,unique:!0},value:{type:"string",required:!0}}}),this.gitRepos=this.db.createCollection("git_repositories",{schema:{id:{type:"string",required:!0,unique:!0},path:{type:"string",required:!0,unique:!0},name:{type:"string",required:!0},parentPath:{type:"string"},isSubmodule:{type:"boolean"},projectType:{type:"string"},vitePort:{type:"number"},lastScanned:{type:"string"}},indexes:["parentPath"]}),this.bookmarks=this.db.createCollection("bookmarked_commands",{schema:{id:{type:"string",required:!0,unique:!0},projectId:{type:"string"},command:{type:"string",required:!0},description:{type:"string"},category:{type:"string"}},indexes:["projectId","category"]}),this.notifications=this.db.createCollection("notifications",{schema:{id:{type:"string",required:!0,unique:!0},sessionName:{type:"string"},projectId:{type:"string"},type:{type:"string",required:!0,enum:["info","success","warning","error"]},title:{type:"string",required:!0},message:{type:"string",required:!0},status:{type:"string",required:!0,enum:["unread","read"]}},indexes:["status","projectId"]}),this.pluginState=this.db.createCollection("plugin_state",{schema:{pluginName:{type:"string",required:!0},key:{type:"string",required:!0},value:{type:"string",required:!0}},indexes:["pluginName"]}),await this.db.connect()}async close(){if(this.db?.isConnected)await this.db.disconnect();this.releaseLock()}getDbPath(){return this.dataDir}async createTask(task){let doc={id:task.id,type:task.type,status:task.status,payload:task.payload};if(task.result!=null)doc.result=task.result;if(task.error!=null)doc.error=task.error;if(task.calendarTaskId!=null)doc.calendarTaskId=task.calendarTaskId;if(task.exitCode!=null)doc.exitCode=task.exitCode;if(task.timeout!=null)doc.timeout=task.timeout;let inserted=await this.tasks.insertOne(doc);return cleanDoc4(inserted)}async getTask(id){let doc=await this.tasks.findOne({id});return doc?cleanDoc4(doc):void 0}async getAllTasks(){return(await this.tasks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async getPendingTasks(){return(await this.tasks.find({status:"pending"},{sort:{createdAt:1}})).docs.map((d)=>cleanDoc4(d))}async updateTask(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.tasks.updateOne({id},patch)}async cancelTask(id){let existing=await this.tasks.findOne({id});if(!existing||existing.status!=="pending"&&existing.status!=="running")return!1;return await this.tasks.updateOne({id},{status:"failed",error:"Cancelled"}),!0}async getConfig(key){return(await this.config.findOne({key}))?.value}async setConfig(key,value){await this.config.upsert({key},{key,value})}async deleteConfig(key){return await this.config.deleteOne({key})!==null}async getAllConfig(){let res=await this.config.find(),out={};for(let doc of res.docs)out[doc.key]=doc.value;return out}async bulkSetConfig(entries){for(let[key,value]of Object.entries(entries))await this.config.upsert({key},{key,value})}async getConfigStatus(){let res=await this.config.find(),latest=null;for(let doc of res.docs){let raw=doc.updatedAt,iso=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:null;if(iso&&(!latest||iso>latest))latest=iso}return{totalKeys:res.docs.length,lastUpdated:latest}}async createGitRepository(repo){let doc={id:repo.id,path:repo.path,name:repo.name,isSubmodule:Boolean(repo.isSubmodule),lastScanned:nowIso4()};if(repo.parentPath!=null)doc.parentPath=repo.parentPath;if(repo.projectType!=null)doc.projectType=repo.projectType;if(repo.vitePort!=null)doc.vitePort=repo.vitePort;let inserted=await this.gitRepos.insertOne(doc);return cleanDoc4(inserted)}async getGitRepository(id){let doc=await this.gitRepos.findOne({id});return doc?cleanDoc4(doc):void 0}async getGitRepositoryByPath(path){let doc=await this.gitRepos.findOne({path});return doc?cleanDoc4(doc):void 0}async getAllGitRepositories(){return(await this.gitRepos.find(void 0,{sort:{path:1}})).docs.map((d)=>cleanDoc4(d))}async updateGitRepository(id,updates){let patch={lastScanned:nowIso4()};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;if(k==="isSubmodule"){patch[k]=Boolean(v);continue}patch[k]=v??null}await this.gitRepos.updateOne({id},patch)}async deleteGitRepository(id){return await this.gitRepos.deleteOne({id})!==null}async fixGitHierarchy(){let repos=await this.getAllGitRepositories(),fixed=0;for(let repo of repos){if(repo.isSubmodule)continue;let parent=repos.find((r)=>r.id!==repo.id&&repo.path.startsWith(`${r.path}/`)&&!r.isSubmodule);if(parent&&repo.parentPath!==parent.path)await this.updateGitRepository(repo.id,{parentPath:parent.path}),fixed++}return{fixed}}async createBookmarkedCommand(cmd){let doc={id:cmd.id,command:cmd.command};if(cmd.projectId!=null)doc.projectId=cmd.projectId;if(cmd.description!=null)doc.description=cmd.description;if(cmd.category!=null)doc.category=cmd.category;let inserted=await this.bookmarks.insertOne(doc);return cleanDoc4(inserted)}async getBookmarkedCommand(id){let doc=await this.bookmarks.findOne({id});return doc?cleanDoc4(doc):void 0}async getAllBookmarkedCommands(){return(await this.bookmarks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async getBookmarkedCommandsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.bookmarks.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async getBookmarkedCommandsByCategory(category){return(await this.bookmarks.find({category},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async updateBookmarkedCommand(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.bookmarks.updateOne({id},patch)}async deleteBookmarkedCommand(id){return await this.bookmarks.deleteOne({id})!==null}async executeBookmarkedCommand(id){return this.getBookmarkedCommand(id)}async createNotification(notification){let doc={id:notification.id,type:notification.type,title:notification.title,message:notification.message,status:notification.status};if(notification.sessionName!=null)doc.sessionName=notification.sessionName;if(notification.projectId!=null)doc.projectId=notification.projectId;let inserted=await this.notifications.insertOne(doc);return cleanDoc4(inserted)}async getNotification(id){let doc=await this.notifications.findOne({id});return doc?cleanDoc4(doc):void 0}async getAllNotifications(){return(await this.notifications.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async getNotificationsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.notifications.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async getGlobalNotifications(){return this.getNotificationsByProject(null)}async getUnreadNotifications(){return(await this.notifications.find({status:"unread"},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async updateNotificationStatus(id,status){await this.notifications.updateOne({id},{status})}async markAllNotificationsRead(){return(await this.notifications.updateMany({status:"unread"},{status:"read"})).length}async deleteNotification(id){return await this.notifications.deleteOne({id})!==null}async clearOldNotifications(olderThanDays=30){let cutoff=new Date(Date.now()-olderThanDays*24*60*60*1000);return(await this.notifications.deleteMany({createdAt:{$fn:(v)=>v instanceof Date&&v<cutoff}})).length}async getPluginState(pluginName,key){return(await this.pluginState.findOne({$and:[{pluginName},{key}]}))?.value}async setPluginState(pluginName,key,value){await this.pluginState.upsert({$and:[{pluginName},{key}]},{pluginName,key,value})}async deletePluginState(pluginName,key){return await this.pluginState.deleteOne({$and:[{pluginName},{key}]})!==null}async getAllPluginState(pluginName){return(await this.pluginState.find({pluginName},{sort:{key:1}})).docs.map((doc)=>{let raw=doc.updatedAt,updatedAt=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:void 0;return{key:doc.key,value:doc.value,updatedAt}})}async deleteAllPluginState(pluginName){return(await this.pluginState.deleteMany({pluginName})).length}}var createSkalexAgentDatabase4=(opts)=>SkalexAgentDatabase4.create(opts);registerAdapter4("skalex",createSkalexAgentDatabase4);var registry5=new Map;function registerAdapter5(name,factory){registry5.set(name,factory)}function getAdapter(name){return registry5.get(name)}function listAdapters(){return Array.from(registry5.keys())}async function resolveFactory(options){if(options.adapterFactory)return options.adapterFactory;let name=options.adapterName??process.env.VIBE_STORAGE_ADAPTER??"skalex";if(name.startsWith("custom:")){let modPath=name.slice(7);if(!modPath)throw Error("VIBE_STORAGE_ADAPTER=custom: requires a module path after the colon");let mod=await import(modPath),factory2=mod.default??mod.createAdapter;if(typeof factory2!=="function")throw Error(`Custom storage adapter at ${modPath} must export a default function (or \`createAdapter\`) of type AgentStorageAdapterFactory`);return factory2}let factory=getAdapter(name);if(!factory){let candidate={skalex:"@vibecontrols/vibe-plugin-storage-skalex",postgres:"@vibecontrols/vibe-plugin-storage-postgres",postgresql:"@vibecontrols/vibe-plugin-storage-postgres"}[name];if(candidate)try{await import(candidate),factory=getAdapter(name)}catch{}}if(!factory)throw Error(`Unknown storage adapter: "${name}". Registered adapters: ${listAdapters().join(", ")||`(none \u2014 did you install @vibecontrols/vibe-plugin-storage-${name})?`}`);return factory}async function createAgentDatabase(options){if(!options.encryptionKey)throw Error("createAgentDatabase(): encryptionKey is required. Storage is always encrypted at rest.");if(!options.dbPath)throw Error("createAgentDatabase(): dbPath is required.");return(await resolveFactory(options))({dataDir:options.dbPath,encryptionKey:options.encryptionKey,adapterOptions:options.adapterOptions})}registerAdapter5("skalex",createSkalexAgentDatabase4);import os from"os";import{readFileSync as readFileSync5}from"fs";import{join as join7,dirname}from"path";import{fileURLToPath}from"url";import{mkdirSync as mkdirSync5}from"fs";import{join as join5}from"path";var LOG_SOURCE="profile-reconciler",DEFAULT_INTERVAL_MS=60000,MIN_INTERVAL_MS=5000,ATTACH_TIMEOUT_MS=30000,SECRET_WAIT_ATTEMPTS=15,SECRET_WAIT_DELAY_MS=200,DESIRED_PROFILES_QUERY=`
117
+ `))!==-1){let line=this._buffer.slice(0,idx).trim();if(this._buffer=this._buffer.slice(idx+1),line&&this._onMessage){let msg;try{msg=JSON.parse(line)}catch(_){this.send(error222(null,PARSE_ERROR222,"Parse error"));continue}this._onMessage(msg).catch(()=>{})}}}),process.stdin.on("end",()=>{process.exit(0)})}stop(){process.stdin.removeAllListeners("data"),process.stdin.removeAllListeners("end"),this._started=!1}}var SERVER_INFO222={name:"skalex",version:"4.0.0-alpha"},PROTOCOL_VERSION222="2024-11-05";class SkalexMCPServer222{constructor(db,opts={}){this._db=db,this._transport=opts.transport||"stdio",this._port=opts.port||3000,this._host=opts.host||"127.0.0.1",this._allowedOrigin=opts.allowedOrigin??null,this._maxBodySize=opts.maxBodySize??1048576,this._scopes=opts.scopes||{"*":["read"]},this._t=null}async listen(){if(this._transport==="http")this._t=new HttpTransport222({port:this._port,host:this._host,allowedOrigin:this._allowedOrigin,maxBodySize:this._maxBodySize});else this._t=new StdioTransport222;this._t.onMessage((msg)=>this._handleMessage(msg)),await this._t.start()}async connect(transport){if(this._t=transport,this._t.onMessage((msg)=>this._handleMessage(msg)),typeof this._t.start==="function")await this._t.start()}async close(){if(this._t&&typeof this._t.stop==="function")await this._t.stop();this._t=null}get transport(){return this._transport}get url(){return this._t?.url}async _handleMessage(raw){let{msg,parseError}=typeof raw==="string"?parse222(raw):{msg:raw};if(parseError){this._send(parseError);return}let{id,method,params}=msg;if(id===void 0){if(method==="notifications/initialized")return;return}try{switch(method){case"initialize":this._send(ok222(id,{protocolVersion:PROTOCOL_VERSION222,capabilities:{tools:{}},serverInfo:SERVER_INFO222}));break;case"tools/list":this._send(ok222(id,{tools:this._visibleTools()}));break;case"tools/call":await this._handleToolCall(id,params);break;case"ping":this._send(ok222(id,{}));break;default:this._send(error222(id,METHOD_NOT_FOUND222,`Method not found: ${method}`))}}catch(err){this._send(error222(id,INTERNAL_ERROR222,err.message||"Internal error"))}}async _handleToolCall(id,params){let name=params?.name,args=params?.arguments??{};if(!name){this._send(error222(id,INVALID_PARAMS222,"tools/call requires params.name"));return}let def=TOOL_DEFS222.find((t)=>t.name===name);if(!def){this._send(error222(id,METHOD_NOT_FOUND222,`Unknown tool: ${name}`));return}let collection=args.collection||args.collection_name||null;if(!this._hasScope(collection,def.scope)){this._send(ok222(id,toolError222(`Access denied: "${name}" requires "${def.scope}" scope on collection "${collection}".`)));return}try{let result=await callTool222(name,args,this._db);this._send(ok222(id,toolResult222(JSON.stringify(result,null,2))))}catch(err){this._send(ok222(id,toolError222(err.message||String(err))))}}_visibleTools(){return TOOL_DEFS222.filter((def)=>{let global=this._scopes["*"];if(global&&(global.includes(def.scope)||global.includes("admin")))return!0;for(let[,perms]of Object.entries(this._scopes))if(perms.includes(def.scope)||perms.includes("admin"))return!0;return!1})}_hasScope(collection,scope){let check=(perms)=>perms.includes("admin")||perms.includes(scope);if(collection&&this._scopes[collection])return check(this._scopes[collection]);if(this._scopes["*"])return check(this._scopes["*"]);return!1}_send(msg){this._t?.send(msg)}}var META_KEY222="migrations",_serialize222=(value)=>JSON.stringify(value,function(key,v){let raw=this[key];if(raw instanceof Date)return{__skalex_date__:raw.toISOString()};if(typeof v==="bigint")return{__skalex_bigint__:v.toString()};return v}),_deserialize222=(text)=>JSON.parse(text,(_,v)=>{if(v&&typeof v==="object"){if("__skalex_bigint__"in v)return BigInt(v.__skalex_bigint__);if("__skalex_date__"in v)return new Date(v.__skalex_date__)}return v});class Skalex222{constructor({path="./.db",format="gz",debug=!1,adapter,ai,encrypt,slowQueryLog,queryCache,memory,logger:logger$1,plugins,llmAdapter,embeddingAdapter,regexMaxLength,idGenerator,serializer,deserializer,autoSave,ttlSweepInterval,lenientLoad}={}){if(this.dataDirectory=path,this.dataFormat=format,this.debug=debug,!Skalex222._errorsAttached)Skalex222.SkalexError=SkalexError222,Skalex222.ValidationError=ValidationError222,Skalex222.UniqueConstraintError=UniqueConstraintError222,Skalex222.TransactionError=TransactionError222,Skalex222.PersistenceError=PersistenceError222,Skalex222.AdapterError=AdapterError222,Skalex222.QueryError=QueryError222,Skalex222._errorsAttached=!0;this._adapterConfig=adapter??null;let fs=adapter||new FsAdapter222({dir:path,format});if(encrypt)fs=new EncryptedAdapter222(fs,encrypt.key);if(this.fs=fs,this._registry=new CollectionRegistry222(Collection222),this.collections=this._registry.stores,this._collectionInstances=this._registry._instances,this._migrations=new MigrationEngine222,this._connectPromise=null,this.isConnected=!1,this._aiConfig=ai||null,this._encryptConfig=encrypt||null,this._pluginsConfig=Array.isArray(plugins)?plugins:null,this._memoryConfig=memory||null,this._regexMaxLength=regexMaxLength??500,this._idGenerator=idGenerator??null,this._serializer=serializer??_serialize222,this._deserializer=deserializer??_deserialize222,this._autoSave=autoSave??!1,this._txManager=new TransactionManager222,this._ttlSweepInterval=ttlSweepInterval??0,this._ttlTimer=null,this._logger=logger$1??logger222,this._embeddingAdapter=embeddingAdapter??(ai?createEmbeddingAdapter222(ai):null),this._aiAdapter=llmAdapter??(ai?createLLMAdapter222(ai):null),this._persistence=new PersistenceManager222({adapter:this.fs,serializer:this._serializer,deserializer:this._deserializer,logger:this._logger,debug:this.debug,lenientLoad:lenientLoad??!1}),this._changeLog=new ChangeLog222(this),this._queryCache=new QueryCache222(queryCache||{}),this._eventBus=new EventBus222,this._queryLog=slowQueryLog?new QueryLog222(slowQueryLog):null,this._sessionStats=new SessionStats222,this._plugins=new PluginEngine222,Array.isArray(plugins))for(let p of plugins)this._plugins.register(p)}async connect(){if(this._connectPromise)return this._connectPromise;return this._connectPromise=this._doConnect(),this._connectPromise}async _doConnect(){try{await this.loadData();let meta=this._getMeta();if(meta.queryCache)this._queryCache.fromJSON(meta.queryCache);if(this._migrations._migrations.length>0){let applied=meta.appliedVersions||[],newApplied=await this._migrations.run((version)=>this.useCollection(`_migration_${version}`),applied);this._saveMeta({appliedVersions:newApplied})}if(this._sweepTtl(),this._ttlSweepInterval>0){if(this._ttlTimer=setInterval(()=>this._sweepTtl(),this._ttlSweepInterval),this._ttlTimer?.unref)this._ttlTimer.unref()}this.isConnected=!0,this._log("> - Connected to the database (\u221A)")}catch(error2222){throw this._logger(`Error connecting to the database: ${error2222}`,"error"),error2222}}async disconnect(){try{if(this._ttlTimer)clearInterval(this._ttlTimer),this._ttlTimer=null;await this.saveData(),this._registry.clear(),this.collections=this._registry.stores,this._collectionInstances=this._registry._instances,this._connectPromise=null,this.isConnected=!1,this._log("> - Disconnected from the database (\u221A)")}catch(error2222){throw this._logger(`Error disconnecting from the database: ${error2222}`,"error"),error2222}}async _ensureConnected(){if(this.isConnected)return;return this.connect()}useCollection(collectionName){return this._registry.get(collectionName,this)}createCollection(collectionName,options={}){return this._registry.create(collectionName,options,this)}_createCollectionStore(collectionName,options={}){this._registry.createStore(collectionName,options)}async renameCollection(from,to){this._registry.rename(from,to),await this.saveData(to),await this.fs.delete(from)}async loadData(){await this._persistence.loadAll(this.collections,{parseSchema:parseSchema222,buildIndex:this._registry.buildIndex,IndexEngine:IndexEngine222});for(let name in this._collectionInstances){let store=this.collections[name];if(store&&this._collectionInstances[name]._store!==store)this._collectionInstances[name]._store=store}}async saveData(collectionName){await this._persistence.save(this.collections,collectionName)}buildIndex(data,keyField){return this._registry.buildIndex(data,keyField)}addMigration(migration){this._migrations.add(migration)}migrationStatus(){let meta=this._getMeta();return this._migrations.status(meta.appliedVersions||[])}namespace(id){if(this._adapterConfig)throw new AdapterError222("ERR_SKALEX_ADAPTER_NAMESPACE_REQUIRES_FS","namespace() requires the default FsAdapter. When a custom storage adapter is configured, create a separate Skalex instance with your adapter instead.");let safeId=String(id).replace(/[^a-zA-Z0-9_-]/g,"_");if(!safeId)throw new ValidationError222("ERR_SKALEX_VALIDATION_NAMESPACE_ID","namespace: id must contain at least one alphanumeric character",{id});return new Skalex222({path:`${this.dataDirectory}/${safeId}`,format:this.dataFormat,debug:this.debug,ai:this._aiConfig||void 0,encrypt:this._encryptConfig||void 0,slowQueryLog:this._queryLog?{threshold:this._queryLog._threshold,maxEntries:this._queryLog._maxEntries}:void 0,queryCache:this._queryCache?{maxSize:this._queryCache._maxSize,ttl:this._queryCache._ttl}:void 0,plugins:this._pluginsConfig||void 0,memory:this._memoryConfig||void 0,logger:this._logger!==logger222?this._logger:void 0,llmAdapter:this._aiAdapter&&!this._aiConfig?this._aiAdapter:void 0,embeddingAdapter:this._embeddingAdapter&&!this._aiConfig?this._embeddingAdapter:void 0,regexMaxLength:this._regexMaxLength!==500?this._regexMaxLength:void 0,idGenerator:this._idGenerator||void 0,serializer:this._serializer!==_serialize222?this._serializer:void 0,deserializer:this._deserializer!==_deserialize222?this._deserializer:void 0,autoSave:this._autoSave||void 0,ttlSweepInterval:this._ttlSweepInterval||void 0})}use(plugin){this._plugins.register(plugin)}watch(callback){return this._eventBus.on("*",callback)}sessionStats(sessionId){if(sessionId!==void 0)return this._sessionStats.get(sessionId);return this._sessionStats.all()}get _inTransaction(){return this._txManager.active}_emitEvent(collectionName,data){if(!this._txManager.defer(()=>this._eventBus.emit(collectionName,data)))this._eventBus.emit(collectionName,data)}async _runAfterHook(hook,data){if(!this._txManager.defer(()=>this._plugins.run(hook,data)))await this._plugins.run(hook,data)}async _logChange(op,collectionName,doc,prev,session){if(!this._txManager.defer(()=>this._changeLog.log(op,collectionName,doc,prev,session)))await this._changeLog.log(op,collectionName,doc,prev,session)}async transaction(fn,opts={}){return this._txManager.run(fn,this,opts)}async seed(fixtures,{reset=!1}={}){for(let[name,docs]of Object.entries(fixtures)){if(reset&&this.collections[name])this._applySnapshot(name,{data:[],index:new Map}),delete this._collectionInstances[name];await this.useCollection(name).insertMany(docs)}await this.saveData()}dump(){return this._registry.dump()}inspect(collectionName){return this._registry.inspect(collectionName)}async import(filePath){let content=await this.fs.readRaw(filePath),docs;try{docs=JSON.parse(content)}catch{throw new PersistenceError222("ERR_SKALEX_PERSISTENCE_INVALID_JSON",`import: invalid JSON in file "${filePath}"`,{filePath})}let name=filePath.split("/").pop().replace(/\.[^.]+$/,"");return this.useCollection(name).insertMany(Array.isArray(docs)?docs:[docs],{save:!0})}async embed(text){if(!this._embeddingAdapter)throw new AdapterError222("ERR_SKALEX_ADAPTER_EMBEDDING_REQUIRED","db.embed() requires an AI adapter. Pass { ai: { provider, apiKey } } to the Skalex constructor.");return this._embeddingAdapter.embed(text)}async ask(collectionName,nlQuery,{limit=20}={}){if(!this._aiAdapter)throw new AdapterError222("ERR_SKALEX_ADAPTER_LLM_REQUIRED",'db.ask() requires a language model adapter. Configure { ai: { provider, model: "..." } }.');let col=this.useCollection(collectionName),schema=this.schema(collectionName),filter=this._queryCache.get(collectionName,schema,nlQuery);if(!filter){filter=await this._aiAdapter.generate(schema,nlQuery);let warnings=validateLLMFilter222(filter,schema);if(warnings.length)warnings.forEach((w)=>this._log(`[ask] ${w}`));this._queryCache.set(collectionName,schema,nlQuery,filter),this._saveMeta({queryCache:this._queryCache.toJSON()})}return col.find(processLLMFilter222(filter,{regexMaxLength:this._regexMaxLength}),{limit})}schema(collectionName){return this._registry.schema(collectionName)}useMemory(sessionId){return new Memory222(sessionId,this)}changelog(){return this._changeLog}async restore(collectionName,timestamp,opts={}){return this._changeLog.restore(collectionName,timestamp,opts)}stats(collectionName){return this._registry.stats(collectionName)}slowQueries(opts={}){if(!this._queryLog)return[];return this._queryLog.entries(opts)}slowQueryCount(){return this._queryLog?this._queryLog.size:0}clearSlowQueries(){this._queryLog?.clear()}mcp(opts={}){return new SkalexMCPServer222(this,opts)}_getMeta(){let metaCol=this.collections._meta;if(!metaCol)return{};return metaCol.index.get(META_KEY222)||{}}_saveMeta(data){if(!this.collections._meta)this._createCollectionStore("_meta");let col=this.collections._meta,existing=col.index.get(META_KEY222);if(existing)Object.assign(existing,data);else{let doc={_id:META_KEY222,...data};col.data.push(doc),col.index.set(META_KEY222,doc)}this._persistence.markDirty(this.collections,"_meta")}_sweepTtl(){for(let name in this.collections){let col=this.collections[name],removed=sweep222(col.data,col.index,col.fieldIndex?(doc)=>col.fieldIndex.remove(doc):null);if(removed>0)this._persistence.markDirty(this.collections,name),this._log(`TTL sweep: removed ${removed} expired docs from "${name}"`)}}_buildCollectionContext(){let db=this;return{ensureConnected:()=>db._ensureConnected(),get txManager(){return db._txManager},get plugins(){return db._plugins},get eventBus(){return db._eventBus},get sessionStats(){return db._sessionStats},get queryLog(){return db._queryLog},get logger(){return db._logger},get persistence(){return db._persistence},get collections(){return db.collections},embed:(text)=>db.embed(text),get idGenerator(){return db._idGenerator},get autoSave(){return db._autoSave},saveCollection:(name)=>db.saveData(name),snapshotCollection:(col)=>db._snapshotCollection(col),getCollection:(name)=>db.useCollection(name),emitEvent:(name,data)=>db._emitEvent(name,data),runAfterHook:(hook,data)=>db._runAfterHook(hook,data),logChange:(op,col,doc,prev,session)=>db._logChange(op,col,doc,prev,session),get fs(){return db.fs},get dataDirectory(){return db.dataDirectory}}}_log(msg){if(this.debug)this._logger(msg,"info")}_snapshotCollection(col){return{data:structuredClone(col.data)}}_applySnapshot(name,snap){let col=this.collections[name];if(!col)return;if(col.data=snap.data,col.index=this.buildIndex(snap.data,"_id"),col.fieldIndex)col.fieldIndex.buildFromData(snap.data)}}class AgentDatabase{}var registry=new Map;function registerAdapter(name,factory){registry.set(name,factory)}var nowIso=()=>new Date().toISOString();function cleanDoc(doc){if(!doc)return doc;let{_id:_ignoredId,createdAt:rawCreatedAt,updatedAt:rawUpdatedAt,_version:_ignoredVersion,_expiresAt:_ignoredExpires,...rest}=doc,out={...rest};if(out.createdAt==null&&rawCreatedAt!=null)out.createdAt=rawCreatedAt instanceof Date?rawCreatedAt.toISOString():String(rawCreatedAt);if(out.updatedAt==null&&rawUpdatedAt!=null)out.updatedAt=rawUpdatedAt instanceof Date?rawUpdatedAt.toISOString():String(rawUpdatedAt);return out}class SkalexAgentDatabase extends AgentDatabase{dataDir;encryptionKey;lockPath;lockFd=null;db;tasks;config;gitRepos;bookmarks;notifications;pluginState;constructor(opts){super();this.dataDir=opts.dataDir,this.encryptionKey=opts.encryptionKey,this.lockPath=join(opts.dataDir,".agent-db.lock")}static async create(opts){if(!existsSync(opts.dataDir))mkdirSync(opts.dataDir,{recursive:!0});let instance=new SkalexAgentDatabase(opts);instance.acquireLock();try{await instance.init()}catch(err){throw instance.releaseLock(),err}return instance}acquireLock(){try{this.lockFd=openSync(this.lockPath,"wx",384),writeFileSync(this.lockFd,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()}));return}catch(err){if(err.code!=="EEXIST")throw err}let stale=!1;try{let raw=JSON.parse(readFileSync(this.lockPath,"utf8"));if(!raw.pid)stale=!0;else try{process.kill(raw.pid,0)}catch{stale=!0}}catch{stale=!0}if(stale){try{unlinkSync(this.lockPath)}catch{}this.acquireLock();return}throw Error(`Agent database is already open by another process (${this.lockPath})`)}releaseLock(){if(this.lockFd!==null){try{closeSync(this.lockFd)}catch{}this.lockFd=null}try{unlinkSync(this.lockPath)}catch{}}async init(){this.db=new Skalex222({path:this.dataDir,encrypt:{key:this.encryptionKey},autoSave:!0,format:"gz",lenientLoad:!0}),this.tasks=this.db.createCollection("tasks",{schema:{id:{type:"string",required:!0,unique:!0},type:{type:"string",required:!0,enum:["command","script","file_operation"]},status:{type:"string",required:!0,enum:["pending","running","completed","failed"]},payload:{type:"string",required:!0},result:{type:"string"},error:{type:"string"},calendarTaskId:{type:"string"},exitCode:{type:"number"},timeout:{type:"number"}},indexes:["status","type"]}),this.config=this.db.createCollection("agent_config",{schema:{key:{type:"string",required:!0,unique:!0},value:{type:"string",required:!0}}}),this.gitRepos=this.db.createCollection("git_repositories",{schema:{id:{type:"string",required:!0,unique:!0},path:{type:"string",required:!0,unique:!0},name:{type:"string",required:!0},parentPath:{type:"string"},isSubmodule:{type:"boolean"},projectType:{type:"string"},vitePort:{type:"number"},lastScanned:{type:"string"}},indexes:["parentPath"]}),this.bookmarks=this.db.createCollection("bookmarked_commands",{schema:{id:{type:"string",required:!0,unique:!0},projectId:{type:"string"},command:{type:"string",required:!0},description:{type:"string"},category:{type:"string"}},indexes:["projectId","category"]}),this.notifications=this.db.createCollection("notifications",{schema:{id:{type:"string",required:!0,unique:!0},sessionName:{type:"string"},projectId:{type:"string"},type:{type:"string",required:!0,enum:["info","success","warning","error"]},title:{type:"string",required:!0},message:{type:"string",required:!0},status:{type:"string",required:!0,enum:["unread","read"]}},indexes:["status","projectId"]}),this.pluginState=this.db.createCollection("plugin_state",{schema:{pluginName:{type:"string",required:!0},key:{type:"string",required:!0},value:{type:"string",required:!0}},indexes:["pluginName"]}),await this.db.connect()}async close(){if(this.db?.isConnected)await this.db.disconnect();this.releaseLock()}getDbPath(){return this.dataDir}async createTask(task){let doc={id:task.id,type:task.type,status:task.status,payload:task.payload};if(task.result!=null)doc.result=task.result;if(task.error!=null)doc.error=task.error;if(task.calendarTaskId!=null)doc.calendarTaskId=task.calendarTaskId;if(task.exitCode!=null)doc.exitCode=task.exitCode;if(task.timeout!=null)doc.timeout=task.timeout;let inserted=await this.tasks.insertOne(doc);return cleanDoc(inserted)}async getTask(id){let doc=await this.tasks.findOne({id});return doc?cleanDoc(doc):void 0}async getAllTasks(){return(await this.tasks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async getPendingTasks(){return(await this.tasks.find({status:"pending"},{sort:{createdAt:1}})).docs.map((d)=>cleanDoc(d))}async updateTask(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.tasks.updateOne({id},patch)}async cancelTask(id){let existing=await this.tasks.findOne({id});if(!existing||existing.status!=="pending"&&existing.status!=="running")return!1;return await this.tasks.updateOne({id},{status:"failed",error:"Cancelled"}),!0}async getConfig(key){return(await this.config.findOne({key}))?.value}async setConfig(key,value){await this.config.upsert({key},{key,value})}async deleteConfig(key){return await this.config.deleteOne({key})!==null}async getAllConfig(){let res=await this.config.find(),out={};for(let doc of res.docs)out[doc.key]=doc.value;return out}async bulkSetConfig(entries){for(let[key,value]of Object.entries(entries))await this.config.upsert({key},{key,value})}async getConfigStatus(){let res=await this.config.find(),latest=null;for(let doc of res.docs){let raw=doc.updatedAt,iso=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:null;if(iso&&(!latest||iso>latest))latest=iso}return{totalKeys:res.docs.length,lastUpdated:latest}}async createGitRepository(repo){let doc={id:repo.id,path:repo.path,name:repo.name,isSubmodule:Boolean(repo.isSubmodule),lastScanned:nowIso()};if(repo.parentPath!=null)doc.parentPath=repo.parentPath;if(repo.projectType!=null)doc.projectType=repo.projectType;if(repo.vitePort!=null)doc.vitePort=repo.vitePort;let inserted=await this.gitRepos.insertOne(doc);return cleanDoc(inserted)}async getGitRepository(id){let doc=await this.gitRepos.findOne({id});return doc?cleanDoc(doc):void 0}async getGitRepositoryByPath(path){let doc=await this.gitRepos.findOne({path});return doc?cleanDoc(doc):void 0}async getAllGitRepositories(){return(await this.gitRepos.find(void 0,{sort:{path:1}})).docs.map((d)=>cleanDoc(d))}async updateGitRepository(id,updates){let patch={lastScanned:nowIso()};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;if(k==="isSubmodule"){patch[k]=Boolean(v);continue}patch[k]=v??null}await this.gitRepos.updateOne({id},patch)}async deleteGitRepository(id){return await this.gitRepos.deleteOne({id})!==null}async fixGitHierarchy(){let repos=await this.getAllGitRepositories(),fixed=0;for(let repo of repos){if(repo.isSubmodule)continue;let parent=repos.find((r)=>r.id!==repo.id&&repo.path.startsWith(`${r.path}/`)&&!r.isSubmodule);if(parent&&repo.parentPath!==parent.path)await this.updateGitRepository(repo.id,{parentPath:parent.path}),fixed++}return{fixed}}async createBookmarkedCommand(cmd){let doc={id:cmd.id,command:cmd.command};if(cmd.projectId!=null)doc.projectId=cmd.projectId;if(cmd.description!=null)doc.description=cmd.description;if(cmd.category!=null)doc.category=cmd.category;let inserted=await this.bookmarks.insertOne(doc);return cleanDoc(inserted)}async getBookmarkedCommand(id){let doc=await this.bookmarks.findOne({id});return doc?cleanDoc(doc):void 0}async getAllBookmarkedCommands(){return(await this.bookmarks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async getBookmarkedCommandsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.bookmarks.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async getBookmarkedCommandsByCategory(category){return(await this.bookmarks.find({category},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async updateBookmarkedCommand(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.bookmarks.updateOne({id},patch)}async deleteBookmarkedCommand(id){return await this.bookmarks.deleteOne({id})!==null}async executeBookmarkedCommand(id){return this.getBookmarkedCommand(id)}async createNotification(notification){let doc={id:notification.id,type:notification.type,title:notification.title,message:notification.message,status:notification.status};if(notification.sessionName!=null)doc.sessionName=notification.sessionName;if(notification.projectId!=null)doc.projectId=notification.projectId;let inserted=await this.notifications.insertOne(doc);return cleanDoc(inserted)}async getNotification(id){let doc=await this.notifications.findOne({id});return doc?cleanDoc(doc):void 0}async getAllNotifications(){return(await this.notifications.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async getNotificationsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.notifications.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async getGlobalNotifications(){return this.getNotificationsByProject(null)}async getUnreadNotifications(){return(await this.notifications.find({status:"unread"},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc(d))}async updateNotificationStatus(id,status){await this.notifications.updateOne({id},{status})}async markAllNotificationsRead(){return(await this.notifications.updateMany({status:"unread"},{status:"read"})).length}async deleteNotification(id){return await this.notifications.deleteOne({id})!==null}async clearOldNotifications(olderThanDays=30){let cutoff=new Date(Date.now()-olderThanDays*24*60*60*1000);return(await this.notifications.deleteMany({createdAt:{$fn:(v)=>v instanceof Date&&v<cutoff}})).length}async getPluginState(pluginName,key){return(await this.pluginState.findOne({$and:[{pluginName},{key}]}))?.value}async setPluginState(pluginName,key,value){await this.pluginState.upsert({$and:[{pluginName},{key}]},{pluginName,key,value})}async deletePluginState(pluginName,key){return await this.pluginState.deleteOne({$and:[{pluginName},{key}]})!==null}async getAllPluginState(pluginName){return(await this.pluginState.find({pluginName},{sort:{key:1}})).docs.map((doc)=>{let raw=doc.updatedAt,updatedAt=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:void 0;return{key:doc.key,value:doc.value,updatedAt}})}async deleteAllPluginState(pluginName){return(await this.pluginState.deleteMany({pluginName})).length}}var createSkalexAgentDatabase=(opts)=>SkalexAgentDatabase.create(opts);registerAdapter("skalex",createSkalexAgentDatabase);var registry2=new Map;function registerAdapter2(name,factory){registry2.set(name,factory)}class AgentDatabase2{}registerAdapter2("skalex",createSkalexAgentDatabase);var nowIso2=()=>new Date().toISOString();function cleanDoc2(doc){if(!doc)return doc;let{_id:_ignoredId,createdAt:rawCreatedAt,updatedAt:rawUpdatedAt,_version:_ignoredVersion,_expiresAt:_ignoredExpires,...rest}=doc,out={...rest};if(out.createdAt==null&&rawCreatedAt!=null)out.createdAt=rawCreatedAt instanceof Date?rawCreatedAt.toISOString():String(rawCreatedAt);if(out.updatedAt==null&&rawUpdatedAt!=null)out.updatedAt=rawUpdatedAt instanceof Date?rawUpdatedAt.toISOString():String(rawUpdatedAt);return out}class SkalexAgentDatabase2 extends AgentDatabase2{dataDir;encryptionKey;lockPath;lockFd=null;db;tasks;config;gitRepos;bookmarks;notifications;pluginState;constructor(opts){super();this.dataDir=opts.dataDir,this.encryptionKey=opts.encryptionKey,this.lockPath=join2(opts.dataDir,".agent-db.lock")}static async create(opts){if(!existsSync2(opts.dataDir))mkdirSync2(opts.dataDir,{recursive:!0});let instance=new SkalexAgentDatabase2(opts);instance.acquireLock();try{await instance.init()}catch(err){throw instance.releaseLock(),err}return instance}acquireLock(){try{this.lockFd=openSync2(this.lockPath,"wx",384),writeFileSync2(this.lockFd,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()}));return}catch(err){if(err.code!=="EEXIST")throw err}let stale=!1;try{let raw=JSON.parse(readFileSync2(this.lockPath,"utf8"));if(!raw.pid)stale=!0;else try{process.kill(raw.pid,0)}catch{stale=!0}}catch{stale=!0}if(stale){try{unlinkSync2(this.lockPath)}catch{}this.acquireLock();return}throw Error(`Agent database is already open by another process (${this.lockPath})`)}releaseLock(){if(this.lockFd!==null){try{closeSync2(this.lockFd)}catch{}this.lockFd=null}try{unlinkSync2(this.lockPath)}catch{}}async init(){this.db=new Skalex22({path:this.dataDir,encrypt:{key:this.encryptionKey},autoSave:!0,format:"gz",lenientLoad:!0}),this.tasks=this.db.createCollection("tasks",{schema:{id:{type:"string",required:!0,unique:!0},type:{type:"string",required:!0,enum:["command","script","file_operation"]},status:{type:"string",required:!0,enum:["pending","running","completed","failed"]},payload:{type:"string",required:!0},result:{type:"string"},error:{type:"string"},calendarTaskId:{type:"string"},exitCode:{type:"number"},timeout:{type:"number"}},indexes:["status","type"]}),this.config=this.db.createCollection("agent_config",{schema:{key:{type:"string",required:!0,unique:!0},value:{type:"string",required:!0}}}),this.gitRepos=this.db.createCollection("git_repositories",{schema:{id:{type:"string",required:!0,unique:!0},path:{type:"string",required:!0,unique:!0},name:{type:"string",required:!0},parentPath:{type:"string"},isSubmodule:{type:"boolean"},projectType:{type:"string"},vitePort:{type:"number"},lastScanned:{type:"string"}},indexes:["parentPath"]}),this.bookmarks=this.db.createCollection("bookmarked_commands",{schema:{id:{type:"string",required:!0,unique:!0},projectId:{type:"string"},command:{type:"string",required:!0},description:{type:"string"},category:{type:"string"}},indexes:["projectId","category"]}),this.notifications=this.db.createCollection("notifications",{schema:{id:{type:"string",required:!0,unique:!0},sessionName:{type:"string"},projectId:{type:"string"},type:{type:"string",required:!0,enum:["info","success","warning","error"]},title:{type:"string",required:!0},message:{type:"string",required:!0},status:{type:"string",required:!0,enum:["unread","read"]}},indexes:["status","projectId"]}),this.pluginState=this.db.createCollection("plugin_state",{schema:{pluginName:{type:"string",required:!0},key:{type:"string",required:!0},value:{type:"string",required:!0}},indexes:["pluginName"]}),await this.db.connect()}async close(){if(this.db?.isConnected)await this.db.disconnect();this.releaseLock()}getDbPath(){return this.dataDir}async createTask(task){let doc={id:task.id,type:task.type,status:task.status,payload:task.payload};if(task.result!=null)doc.result=task.result;if(task.error!=null)doc.error=task.error;if(task.calendarTaskId!=null)doc.calendarTaskId=task.calendarTaskId;if(task.exitCode!=null)doc.exitCode=task.exitCode;if(task.timeout!=null)doc.timeout=task.timeout;let inserted=await this.tasks.insertOne(doc);return cleanDoc2(inserted)}async getTask(id){let doc=await this.tasks.findOne({id});return doc?cleanDoc2(doc):void 0}async getAllTasks(){return(await this.tasks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async getPendingTasks(){return(await this.tasks.find({status:"pending"},{sort:{createdAt:1}})).docs.map((d)=>cleanDoc2(d))}async updateTask(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.tasks.updateOne({id},patch)}async cancelTask(id){let existing=await this.tasks.findOne({id});if(!existing||existing.status!=="pending"&&existing.status!=="running")return!1;return await this.tasks.updateOne({id},{status:"failed",error:"Cancelled"}),!0}async getConfig(key){return(await this.config.findOne({key}))?.value}async setConfig(key,value){await this.config.upsert({key},{key,value})}async deleteConfig(key){return await this.config.deleteOne({key})!==null}async getAllConfig(){let res=await this.config.find(),out={};for(let doc of res.docs)out[doc.key]=doc.value;return out}async bulkSetConfig(entries){for(let[key,value]of Object.entries(entries))await this.config.upsert({key},{key,value})}async getConfigStatus(){let res=await this.config.find(),latest=null;for(let doc of res.docs){let raw=doc.updatedAt,iso=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:null;if(iso&&(!latest||iso>latest))latest=iso}return{totalKeys:res.docs.length,lastUpdated:latest}}async createGitRepository(repo){let doc={id:repo.id,path:repo.path,name:repo.name,isSubmodule:Boolean(repo.isSubmodule),lastScanned:nowIso2()};if(repo.parentPath!=null)doc.parentPath=repo.parentPath;if(repo.projectType!=null)doc.projectType=repo.projectType;if(repo.vitePort!=null)doc.vitePort=repo.vitePort;let inserted=await this.gitRepos.insertOne(doc);return cleanDoc2(inserted)}async getGitRepository(id){let doc=await this.gitRepos.findOne({id});return doc?cleanDoc2(doc):void 0}async getGitRepositoryByPath(path){let doc=await this.gitRepos.findOne({path});return doc?cleanDoc2(doc):void 0}async getAllGitRepositories(){return(await this.gitRepos.find(void 0,{sort:{path:1}})).docs.map((d)=>cleanDoc2(d))}async updateGitRepository(id,updates){let patch={lastScanned:nowIso2()};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;if(k==="isSubmodule"){patch[k]=Boolean(v);continue}patch[k]=v??null}await this.gitRepos.updateOne({id},patch)}async deleteGitRepository(id){return await this.gitRepos.deleteOne({id})!==null}async fixGitHierarchy(){let repos=await this.getAllGitRepositories(),fixed=0;for(let repo of repos){if(repo.isSubmodule)continue;let parent=repos.find((r)=>r.id!==repo.id&&repo.path.startsWith(`${r.path}/`)&&!r.isSubmodule);if(parent&&repo.parentPath!==parent.path)await this.updateGitRepository(repo.id,{parentPath:parent.path}),fixed++}return{fixed}}async createBookmarkedCommand(cmd){let doc={id:cmd.id,command:cmd.command};if(cmd.projectId!=null)doc.projectId=cmd.projectId;if(cmd.description!=null)doc.description=cmd.description;if(cmd.category!=null)doc.category=cmd.category;let inserted=await this.bookmarks.insertOne(doc);return cleanDoc2(inserted)}async getBookmarkedCommand(id){let doc=await this.bookmarks.findOne({id});return doc?cleanDoc2(doc):void 0}async getAllBookmarkedCommands(){return(await this.bookmarks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async getBookmarkedCommandsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.bookmarks.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async getBookmarkedCommandsByCategory(category){return(await this.bookmarks.find({category},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async updateBookmarkedCommand(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.bookmarks.updateOne({id},patch)}async deleteBookmarkedCommand(id){return await this.bookmarks.deleteOne({id})!==null}async executeBookmarkedCommand(id){return this.getBookmarkedCommand(id)}async createNotification(notification){let doc={id:notification.id,type:notification.type,title:notification.title,message:notification.message,status:notification.status};if(notification.sessionName!=null)doc.sessionName=notification.sessionName;if(notification.projectId!=null)doc.projectId=notification.projectId;let inserted=await this.notifications.insertOne(doc);return cleanDoc2(inserted)}async getNotification(id){let doc=await this.notifications.findOne({id});return doc?cleanDoc2(doc):void 0}async getAllNotifications(){return(await this.notifications.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async getNotificationsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.notifications.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async getGlobalNotifications(){return this.getNotificationsByProject(null)}async getUnreadNotifications(){return(await this.notifications.find({status:"unread"},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc2(d))}async updateNotificationStatus(id,status){await this.notifications.updateOne({id},{status})}async markAllNotificationsRead(){return(await this.notifications.updateMany({status:"unread"},{status:"read"})).length}async deleteNotification(id){return await this.notifications.deleteOne({id})!==null}async clearOldNotifications(olderThanDays=30){let cutoff=new Date(Date.now()-olderThanDays*24*60*60*1000);return(await this.notifications.deleteMany({createdAt:{$fn:(v)=>v instanceof Date&&v<cutoff}})).length}async getPluginState(pluginName,key){return(await this.pluginState.findOne({$and:[{pluginName},{key}]}))?.value}async setPluginState(pluginName,key,value){await this.pluginState.upsert({$and:[{pluginName},{key}]},{pluginName,key,value})}async deletePluginState(pluginName,key){return await this.pluginState.deleteOne({$and:[{pluginName},{key}]})!==null}async getAllPluginState(pluginName){return(await this.pluginState.find({pluginName},{sort:{key:1}})).docs.map((doc)=>{let raw=doc.updatedAt,updatedAt=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:void 0;return{key:doc.key,value:doc.value,updatedAt}})}async deleteAllPluginState(pluginName){return(await this.pluginState.deleteMany({pluginName})).length}}var createSkalexAgentDatabase2=(opts)=>SkalexAgentDatabase2.create(opts);registerAdapter2("skalex",createSkalexAgentDatabase2);var registry3=new Map;function registerAdapter3(name,factory){registry3.set(name,factory)}class AgentDatabase3{}registerAdapter3("skalex",createSkalexAgentDatabase2);var nowIso3=()=>new Date().toISOString();function cleanDoc3(doc){if(!doc)return doc;let{_id:_ignoredId,createdAt:rawCreatedAt,updatedAt:rawUpdatedAt,_version:_ignoredVersion,_expiresAt:_ignoredExpires,...rest}=doc,out={...rest};if(out.createdAt==null&&rawCreatedAt!=null)out.createdAt=rawCreatedAt instanceof Date?rawCreatedAt.toISOString():String(rawCreatedAt);if(out.updatedAt==null&&rawUpdatedAt!=null)out.updatedAt=rawUpdatedAt instanceof Date?rawUpdatedAt.toISOString():String(rawUpdatedAt);return out}class SkalexAgentDatabase3 extends AgentDatabase3{dataDir;encryptionKey;lockPath;lockFd=null;db;tasks;config;gitRepos;bookmarks;notifications;pluginState;constructor(opts){super();this.dataDir=opts.dataDir,this.encryptionKey=opts.encryptionKey,this.lockPath=join3(opts.dataDir,".agent-db.lock")}static async create(opts){if(!existsSync3(opts.dataDir))mkdirSync3(opts.dataDir,{recursive:!0});let instance=new SkalexAgentDatabase3(opts);instance.acquireLock();try{await instance.init()}catch(err){throw instance.releaseLock(),err}return instance}acquireLock(){try{this.lockFd=openSync3(this.lockPath,"wx",384),writeFileSync3(this.lockFd,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()}));return}catch(err){if(err.code!=="EEXIST")throw err}let stale=!1;try{let raw=JSON.parse(readFileSync3(this.lockPath,"utf8"));if(!raw.pid)stale=!0;else try{process.kill(raw.pid,0)}catch{stale=!0}}catch{stale=!0}if(stale){try{unlinkSync3(this.lockPath)}catch{}this.acquireLock();return}throw Error(`Agent database is already open by another process (${this.lockPath})`)}releaseLock(){if(this.lockFd!==null){try{closeSync3(this.lockFd)}catch{}this.lockFd=null}try{unlinkSync3(this.lockPath)}catch{}}async init(){this.db=new Skalex2({path:this.dataDir,encrypt:{key:this.encryptionKey},autoSave:!0,format:"gz",lenientLoad:!0}),this.tasks=this.db.createCollection("tasks",{schema:{id:{type:"string",required:!0,unique:!0},type:{type:"string",required:!0,enum:["command","script","file_operation"]},status:{type:"string",required:!0,enum:["pending","running","completed","failed"]},payload:{type:"string",required:!0},result:{type:"string"},error:{type:"string"},calendarTaskId:{type:"string"},exitCode:{type:"number"},timeout:{type:"number"}},indexes:["status","type"]}),this.config=this.db.createCollection("agent_config",{schema:{key:{type:"string",required:!0,unique:!0},value:{type:"string",required:!0}}}),this.gitRepos=this.db.createCollection("git_repositories",{schema:{id:{type:"string",required:!0,unique:!0},path:{type:"string",required:!0,unique:!0},name:{type:"string",required:!0},parentPath:{type:"string"},isSubmodule:{type:"boolean"},projectType:{type:"string"},vitePort:{type:"number"},lastScanned:{type:"string"}},indexes:["parentPath"]}),this.bookmarks=this.db.createCollection("bookmarked_commands",{schema:{id:{type:"string",required:!0,unique:!0},projectId:{type:"string"},command:{type:"string",required:!0},description:{type:"string"},category:{type:"string"}},indexes:["projectId","category"]}),this.notifications=this.db.createCollection("notifications",{schema:{id:{type:"string",required:!0,unique:!0},sessionName:{type:"string"},projectId:{type:"string"},type:{type:"string",required:!0,enum:["info","success","warning","error"]},title:{type:"string",required:!0},message:{type:"string",required:!0},status:{type:"string",required:!0,enum:["unread","read"]}},indexes:["status","projectId"]}),this.pluginState=this.db.createCollection("plugin_state",{schema:{pluginName:{type:"string",required:!0},key:{type:"string",required:!0},value:{type:"string",required:!0}},indexes:["pluginName"]}),await this.db.connect()}async close(){if(this.db?.isConnected)await this.db.disconnect();this.releaseLock()}getDbPath(){return this.dataDir}async createTask(task){let doc={id:task.id,type:task.type,status:task.status,payload:task.payload};if(task.result!=null)doc.result=task.result;if(task.error!=null)doc.error=task.error;if(task.calendarTaskId!=null)doc.calendarTaskId=task.calendarTaskId;if(task.exitCode!=null)doc.exitCode=task.exitCode;if(task.timeout!=null)doc.timeout=task.timeout;let inserted=await this.tasks.insertOne(doc);return cleanDoc3(inserted)}async getTask(id){let doc=await this.tasks.findOne({id});return doc?cleanDoc3(doc):void 0}async getAllTasks(){return(await this.tasks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async getPendingTasks(){return(await this.tasks.find({status:"pending"},{sort:{createdAt:1}})).docs.map((d)=>cleanDoc3(d))}async updateTask(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.tasks.updateOne({id},patch)}async cancelTask(id){let existing=await this.tasks.findOne({id});if(!existing||existing.status!=="pending"&&existing.status!=="running")return!1;return await this.tasks.updateOne({id},{status:"failed",error:"Cancelled"}),!0}async getConfig(key){return(await this.config.findOne({key}))?.value}async setConfig(key,value){await this.config.upsert({key},{key,value})}async deleteConfig(key){return await this.config.deleteOne({key})!==null}async getAllConfig(){let res=await this.config.find(),out={};for(let doc of res.docs)out[doc.key]=doc.value;return out}async bulkSetConfig(entries){for(let[key,value]of Object.entries(entries))await this.config.upsert({key},{key,value})}async getConfigStatus(){let res=await this.config.find(),latest=null;for(let doc of res.docs){let raw=doc.updatedAt,iso=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:null;if(iso&&(!latest||iso>latest))latest=iso}return{totalKeys:res.docs.length,lastUpdated:latest}}async createGitRepository(repo){let doc={id:repo.id,path:repo.path,name:repo.name,isSubmodule:Boolean(repo.isSubmodule),lastScanned:nowIso3()};if(repo.parentPath!=null)doc.parentPath=repo.parentPath;if(repo.projectType!=null)doc.projectType=repo.projectType;if(repo.vitePort!=null)doc.vitePort=repo.vitePort;let inserted=await this.gitRepos.insertOne(doc);return cleanDoc3(inserted)}async getGitRepository(id){let doc=await this.gitRepos.findOne({id});return doc?cleanDoc3(doc):void 0}async getGitRepositoryByPath(path){let doc=await this.gitRepos.findOne({path});return doc?cleanDoc3(doc):void 0}async getAllGitRepositories(){return(await this.gitRepos.find(void 0,{sort:{path:1}})).docs.map((d)=>cleanDoc3(d))}async updateGitRepository(id,updates){let patch={lastScanned:nowIso3()};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;if(k==="isSubmodule"){patch[k]=Boolean(v);continue}patch[k]=v??null}await this.gitRepos.updateOne({id},patch)}async deleteGitRepository(id){return await this.gitRepos.deleteOne({id})!==null}async fixGitHierarchy(){let repos=await this.getAllGitRepositories(),fixed=0;for(let repo of repos){if(repo.isSubmodule)continue;let parent=repos.find((r)=>r.id!==repo.id&&repo.path.startsWith(`${r.path}/`)&&!r.isSubmodule);if(parent&&repo.parentPath!==parent.path)await this.updateGitRepository(repo.id,{parentPath:parent.path}),fixed++}return{fixed}}async createBookmarkedCommand(cmd){let doc={id:cmd.id,command:cmd.command};if(cmd.projectId!=null)doc.projectId=cmd.projectId;if(cmd.description!=null)doc.description=cmd.description;if(cmd.category!=null)doc.category=cmd.category;let inserted=await this.bookmarks.insertOne(doc);return cleanDoc3(inserted)}async getBookmarkedCommand(id){let doc=await this.bookmarks.findOne({id});return doc?cleanDoc3(doc):void 0}async getAllBookmarkedCommands(){return(await this.bookmarks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async getBookmarkedCommandsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.bookmarks.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async getBookmarkedCommandsByCategory(category){return(await this.bookmarks.find({category},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async updateBookmarkedCommand(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.bookmarks.updateOne({id},patch)}async deleteBookmarkedCommand(id){return await this.bookmarks.deleteOne({id})!==null}async executeBookmarkedCommand(id){return this.getBookmarkedCommand(id)}async createNotification(notification){let doc={id:notification.id,type:notification.type,title:notification.title,message:notification.message,status:notification.status};if(notification.sessionName!=null)doc.sessionName=notification.sessionName;if(notification.projectId!=null)doc.projectId=notification.projectId;let inserted=await this.notifications.insertOne(doc);return cleanDoc3(inserted)}async getNotification(id){let doc=await this.notifications.findOne({id});return doc?cleanDoc3(doc):void 0}async getAllNotifications(){return(await this.notifications.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async getNotificationsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.notifications.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async getGlobalNotifications(){return this.getNotificationsByProject(null)}async getUnreadNotifications(){return(await this.notifications.find({status:"unread"},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc3(d))}async updateNotificationStatus(id,status){await this.notifications.updateOne({id},{status})}async markAllNotificationsRead(){return(await this.notifications.updateMany({status:"unread"},{status:"read"})).length}async deleteNotification(id){return await this.notifications.deleteOne({id})!==null}async clearOldNotifications(olderThanDays=30){let cutoff=new Date(Date.now()-olderThanDays*24*60*60*1000);return(await this.notifications.deleteMany({createdAt:{$fn:(v)=>v instanceof Date&&v<cutoff}})).length}async getPluginState(pluginName,key){return(await this.pluginState.findOne({$and:[{pluginName},{key}]}))?.value}async setPluginState(pluginName,key,value){await this.pluginState.upsert({$and:[{pluginName},{key}]},{pluginName,key,value})}async deletePluginState(pluginName,key){return await this.pluginState.deleteOne({$and:[{pluginName},{key}]})!==null}async getAllPluginState(pluginName){return(await this.pluginState.find({pluginName},{sort:{key:1}})).docs.map((doc)=>{let raw=doc.updatedAt,updatedAt=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:void 0;return{key:doc.key,value:doc.value,updatedAt}})}async deleteAllPluginState(pluginName){return(await this.pluginState.deleteMany({pluginName})).length}}var createSkalexAgentDatabase3=(opts)=>SkalexAgentDatabase3.create(opts);registerAdapter3("skalex",createSkalexAgentDatabase3);var registry4=new Map;function registerAdapter4(name,factory){registry4.set(name,factory)}class AgentDatabase4{}registerAdapter4("skalex",createSkalexAgentDatabase3);var nowIso4=()=>new Date().toISOString();function cleanDoc4(doc){if(!doc)return doc;let{_id:_ignoredId,createdAt:rawCreatedAt,updatedAt:rawUpdatedAt,_version:_ignoredVersion,_expiresAt:_ignoredExpires,...rest}=doc,out={...rest};if(out.createdAt==null&&rawCreatedAt!=null)out.createdAt=rawCreatedAt instanceof Date?rawCreatedAt.toISOString():String(rawCreatedAt);if(out.updatedAt==null&&rawUpdatedAt!=null)out.updatedAt=rawUpdatedAt instanceof Date?rawUpdatedAt.toISOString():String(rawUpdatedAt);return out}class SkalexAgentDatabase4 extends AgentDatabase4{dataDir;encryptionKey;lockPath;lockFd=null;db;tasks;config;gitRepos;bookmarks;notifications;pluginState;constructor(opts){super();this.dataDir=opts.dataDir,this.encryptionKey=opts.encryptionKey,this.lockPath=join4(opts.dataDir,".agent-db.lock")}static async create(opts){if(!existsSync4(opts.dataDir))mkdirSync4(opts.dataDir,{recursive:!0});let instance=new SkalexAgentDatabase4(opts);instance.acquireLock();try{await instance.init()}catch(err){throw instance.releaseLock(),err}return instance}acquireLock(){try{this.lockFd=openSync4(this.lockPath,"wx",384),writeFileSync4(this.lockFd,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()}));return}catch(err){if(err.code!=="EEXIST")throw err}let stale=!1;try{let raw=JSON.parse(readFileSync4(this.lockPath,"utf8"));if(!raw.pid)stale=!0;else try{process.kill(raw.pid,0)}catch{stale=!0}}catch{stale=!0}if(stale){try{unlinkSync4(this.lockPath)}catch{}this.acquireLock();return}throw Error(`Agent database is already open by another process (${this.lockPath})`)}releaseLock(){if(this.lockFd!==null){try{closeSync4(this.lockFd)}catch{}this.lockFd=null}try{unlinkSync4(this.lockPath)}catch{}}async init(){this.db=new Skalex({path:this.dataDir,encrypt:{key:this.encryptionKey},autoSave:!0,format:"gz",lenientLoad:!0}),this.tasks=this.db.createCollection("tasks",{schema:{id:{type:"string",required:!0,unique:!0},type:{type:"string",required:!0,enum:["command","script","file_operation"]},status:{type:"string",required:!0,enum:["pending","running","completed","failed"]},payload:{type:"string",required:!0},result:{type:"string"},error:{type:"string"},calendarTaskId:{type:"string"},exitCode:{type:"number"},timeout:{type:"number"}},indexes:["status","type"]}),this.config=this.db.createCollection("agent_config",{schema:{key:{type:"string",required:!0,unique:!0},value:{type:"string",required:!0}}}),this.gitRepos=this.db.createCollection("git_repositories",{schema:{id:{type:"string",required:!0,unique:!0},path:{type:"string",required:!0,unique:!0},name:{type:"string",required:!0},parentPath:{type:"string"},isSubmodule:{type:"boolean"},projectType:{type:"string"},vitePort:{type:"number"},lastScanned:{type:"string"}},indexes:["parentPath"]}),this.bookmarks=this.db.createCollection("bookmarked_commands",{schema:{id:{type:"string",required:!0,unique:!0},projectId:{type:"string"},command:{type:"string",required:!0},description:{type:"string"},category:{type:"string"}},indexes:["projectId","category"]}),this.notifications=this.db.createCollection("notifications",{schema:{id:{type:"string",required:!0,unique:!0},sessionName:{type:"string"},projectId:{type:"string"},type:{type:"string",required:!0,enum:["info","success","warning","error"]},title:{type:"string",required:!0},message:{type:"string",required:!0},status:{type:"string",required:!0,enum:["unread","read"]}},indexes:["status","projectId"]}),this.pluginState=this.db.createCollection("plugin_state",{schema:{pluginName:{type:"string",required:!0},key:{type:"string",required:!0},value:{type:"string",required:!0}},indexes:["pluginName"]}),await this.db.connect()}async close(){if(this.db?.isConnected)await this.db.disconnect();this.releaseLock()}getDbPath(){return this.dataDir}async createTask(task){let doc={id:task.id,type:task.type,status:task.status,payload:task.payload};if(task.result!=null)doc.result=task.result;if(task.error!=null)doc.error=task.error;if(task.calendarTaskId!=null)doc.calendarTaskId=task.calendarTaskId;if(task.exitCode!=null)doc.exitCode=task.exitCode;if(task.timeout!=null)doc.timeout=task.timeout;let inserted=await this.tasks.insertOne(doc);return cleanDoc4(inserted)}async getTask(id){let doc=await this.tasks.findOne({id});return doc?cleanDoc4(doc):void 0}async getAllTasks(){return(await this.tasks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async getPendingTasks(){return(await this.tasks.find({status:"pending"},{sort:{createdAt:1}})).docs.map((d)=>cleanDoc4(d))}async updateTask(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.tasks.updateOne({id},patch)}async cancelTask(id){let existing=await this.tasks.findOne({id});if(!existing||existing.status!=="pending"&&existing.status!=="running")return!1;return await this.tasks.updateOne({id},{status:"failed",error:"Cancelled"}),!0}async getConfig(key){return(await this.config.findOne({key}))?.value}async setConfig(key,value){await this.config.upsert({key},{key,value})}async deleteConfig(key){return await this.config.deleteOne({key})!==null}async getAllConfig(){let res=await this.config.find(),out={};for(let doc of res.docs)out[doc.key]=doc.value;return out}async bulkSetConfig(entries){for(let[key,value]of Object.entries(entries))await this.config.upsert({key},{key,value})}async getConfigStatus(){let res=await this.config.find(),latest=null;for(let doc of res.docs){let raw=doc.updatedAt,iso=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:null;if(iso&&(!latest||iso>latest))latest=iso}return{totalKeys:res.docs.length,lastUpdated:latest}}async createGitRepository(repo){let doc={id:repo.id,path:repo.path,name:repo.name,isSubmodule:Boolean(repo.isSubmodule),lastScanned:nowIso4()};if(repo.parentPath!=null)doc.parentPath=repo.parentPath;if(repo.projectType!=null)doc.projectType=repo.projectType;if(repo.vitePort!=null)doc.vitePort=repo.vitePort;let inserted=await this.gitRepos.insertOne(doc);return cleanDoc4(inserted)}async getGitRepository(id){let doc=await this.gitRepos.findOne({id});return doc?cleanDoc4(doc):void 0}async getGitRepositoryByPath(path){let doc=await this.gitRepos.findOne({path});return doc?cleanDoc4(doc):void 0}async getAllGitRepositories(){return(await this.gitRepos.find(void 0,{sort:{path:1}})).docs.map((d)=>cleanDoc4(d))}async updateGitRepository(id,updates){let patch={lastScanned:nowIso4()};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;if(k==="isSubmodule"){patch[k]=Boolean(v);continue}patch[k]=v??null}await this.gitRepos.updateOne({id},patch)}async deleteGitRepository(id){return await this.gitRepos.deleteOne({id})!==null}async fixGitHierarchy(){let repos=await this.getAllGitRepositories(),fixed=0;for(let repo of repos){if(repo.isSubmodule)continue;let parent=repos.find((r)=>r.id!==repo.id&&repo.path.startsWith(`${r.path}/`)&&!r.isSubmodule);if(parent&&repo.parentPath!==parent.path)await this.updateGitRepository(repo.id,{parentPath:parent.path}),fixed++}return{fixed}}async createBookmarkedCommand(cmd){let doc={id:cmd.id,command:cmd.command};if(cmd.projectId!=null)doc.projectId=cmd.projectId;if(cmd.description!=null)doc.description=cmd.description;if(cmd.category!=null)doc.category=cmd.category;let inserted=await this.bookmarks.insertOne(doc);return cleanDoc4(inserted)}async getBookmarkedCommand(id){let doc=await this.bookmarks.findOne({id});return doc?cleanDoc4(doc):void 0}async getAllBookmarkedCommands(){return(await this.bookmarks.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async getBookmarkedCommandsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.bookmarks.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async getBookmarkedCommandsByCategory(category){return(await this.bookmarks.find({category},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async updateBookmarkedCommand(id,updates){let patch={};for(let[k,v]of Object.entries(updates)){if(k==="id"||k==="createdAt"||k==="updatedAt")continue;patch[k]=v??null}if(Object.keys(patch).length===0)return;await this.bookmarks.updateOne({id},patch)}async deleteBookmarkedCommand(id){return await this.bookmarks.deleteOne({id})!==null}async executeBookmarkedCommand(id){return this.getBookmarkedCommand(id)}async createNotification(notification){let doc={id:notification.id,type:notification.type,title:notification.title,message:notification.message,status:notification.status};if(notification.sessionName!=null)doc.sessionName=notification.sessionName;if(notification.projectId!=null)doc.projectId=notification.projectId;let inserted=await this.notifications.insertOne(doc);return cleanDoc4(inserted)}async getNotification(id){let doc=await this.notifications.findOne({id});return doc?cleanDoc4(doc):void 0}async getAllNotifications(){return(await this.notifications.find(void 0,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async getNotificationsByProject(projectId){let filter=projectId===null?{projectId:{$fn:(v)=>v==null}}:{projectId};return(await this.notifications.find(filter,{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async getGlobalNotifications(){return this.getNotificationsByProject(null)}async getUnreadNotifications(){return(await this.notifications.find({status:"unread"},{sort:{createdAt:-1}})).docs.map((d)=>cleanDoc4(d))}async updateNotificationStatus(id,status){await this.notifications.updateOne({id},{status})}async markAllNotificationsRead(){return(await this.notifications.updateMany({status:"unread"},{status:"read"})).length}async deleteNotification(id){return await this.notifications.deleteOne({id})!==null}async clearOldNotifications(olderThanDays=30){let cutoff=new Date(Date.now()-olderThanDays*24*60*60*1000);return(await this.notifications.deleteMany({createdAt:{$fn:(v)=>v instanceof Date&&v<cutoff}})).length}async getPluginState(pluginName,key){return(await this.pluginState.findOne({$and:[{pluginName},{key}]}))?.value}async setPluginState(pluginName,key,value){await this.pluginState.upsert({$and:[{pluginName},{key}]},{pluginName,key,value})}async deletePluginState(pluginName,key){return await this.pluginState.deleteOne({$and:[{pluginName},{key}]})!==null}async getAllPluginState(pluginName){return(await this.pluginState.find({pluginName},{sort:{key:1}})).docs.map((doc)=>{let raw=doc.updatedAt,updatedAt=raw instanceof Date?raw.toISOString():typeof raw==="string"?raw:void 0;return{key:doc.key,value:doc.value,updatedAt}})}async deleteAllPluginState(pluginName){return(await this.pluginState.deleteMany({pluginName})).length}}var createSkalexAgentDatabase4=(opts)=>SkalexAgentDatabase4.create(opts);registerAdapter4("skalex",createSkalexAgentDatabase4);var registry5=new Map;function registerAdapter5(name,factory){registry5.set(name,factory)}function getAdapter(name){return registry5.get(name)}function listAdapters(){return Array.from(registry5.keys())}async function resolveFactory(options){if(options.adapterFactory)return options.adapterFactory;let name=options.adapterName??process.env.VIBE_STORAGE_ADAPTER??"skalex";if(name.startsWith("custom:")){let modPath=name.slice(7);if(!modPath)throw Error("VIBE_STORAGE_ADAPTER=custom: requires a module path after the colon");let mod=await import(modPath),factory2=mod.default??mod.createAdapter;if(typeof factory2!=="function")throw Error(`Custom storage adapter at ${modPath} must export a default function (or \`createAdapter\`) of type AgentStorageAdapterFactory`);return factory2}let factory=getAdapter(name);if(!factory){let candidate={skalex:"@vibecontrols/vibe-plugin-storage-skalex",postgres:"@vibecontrols/vibe-plugin-storage-postgres",postgresql:"@vibecontrols/vibe-plugin-storage-postgres"}[name];if(candidate)try{await import(candidate),factory=getAdapter(name)}catch{}}if(!factory)throw Error(`Unknown storage adapter: "${name}". Registered adapters: ${listAdapters().join(", ")||`(none \u2014 did you install @vibecontrols/vibe-plugin-storage-${name})?`}`);return factory}async function createAgentDatabase(options){if(!options.encryptionKey)throw Error("createAgentDatabase(): encryptionKey is required. Storage is always encrypted at rest.");if(!options.dbPath)throw Error("createAgentDatabase(): dbPath is required.");return(await resolveFactory(options))({dataDir:options.dbPath,encryptionKey:options.encryptionKey,adapterOptions:options.adapterOptions})}registerAdapter5("skalex",createSkalexAgentDatabase4);import os from"os";import{mkdirSync as mkdirSync5}from"fs";import{join as join5}from"path";var LOG_SOURCE="profile-reconciler",DEFAULT_INTERVAL_MS=60000,MIN_INTERVAL_MS=5000,ATTACH_TIMEOUT_MS=30000,SECRET_WAIT_ATTEMPTS=15,SECRET_WAIT_DELAY_MS=200,DESIRED_PROFILES_QUERY=`
118
118
  query VibecontrolsAgentProfiles($agentId: ID!) {
119
119
  vibecontrolsAgentProfiles(agentId: $agentId) {
120
120
  id
@@ -170,7 +170,7 @@ data: /message
170
170
  isActive
171
171
  }
172
172
  }
173
- `;function getAgentVersion(){try{let __dirname2=dirname(fileURLToPath(import.meta.url)),pkgPath=join7(__dirname2,"..","..","..","package.json");return JSON.parse(readFileSync5(pkgPath,"utf8")).version||"0.0.0"}catch{return"0.0.0"}}async function waitForTunnelUrl(serviceRegistry){if(process.env.AGENT_TUNNEL_URL){let safeUrl=sanitizeOperatorTunnelUrl(process.env.AGENT_TUNNEL_URL);if(!safeUrl)return getDaemonProfile().logger.warn(LOG_SOURCE2,"Ignoring invalid AGENT_TUNNEL_URL"),null;return getDaemonProfile().logger.debug(LOG_SOURCE2,`Using AGENT_TUNNEL_URL from environment: ${safeUrl}`),safeUrl}for(let attempt=1;attempt<=MAX_RETRIES;attempt++){let providers=[],defaultProvider=serviceRegistry.getProvider("tunnel");if(defaultProvider)providers.push(defaultProvider);for(let entry of serviceRegistry.listProvidersForType("tunnel")){let provider=serviceRegistry.getProviderByName("tunnel",entry.pluginName);if(provider&&!providers.includes(provider))providers.push(provider)}for(let tunnelProvider of providers){if(!tunnelProvider.getActiveTunnelUrl)continue;let url=await tunnelProvider.getActiveTunnelUrl(),safeUrl=sanitizeTunnelUrl(url);if(safeUrl)return getDaemonProfile().logger.debug(LOG_SOURCE2,`Tunnel URL available on attempt ${attempt}: ${safeUrl}`),safeUrl;if(url)getDaemonProfile().logger.warn(LOG_SOURCE2,"Tunnel provider returned invalid URL",{url})}if(attempt<MAX_RETRIES)getDaemonProfile().logger.debug(LOG_SOURCE2,`Tunnel URL not ready, retrying in ${RETRY_INTERVAL_MS/1000}s (attempt ${attempt}/${MAX_RETRIES})`),await new Promise((resolve)=>setTimeout(resolve,RETRY_INTERVAL_MS))}return getDaemonProfile().logger.warn(LOG_SOURCE2,`Tunnel URL not available after ${MAX_RETRIES} attempts`),null}async function getOrDiscoverAgentRecordId(db,hostname){let cachedAgentRecordId=await db.getConfig("gateway-auth:agentRecordId");if(cachedAgentRecordId)return cachedAgentRecordId;let workspaceId=await db.getConfig("gateway-auth:workspaceId");if(!workspaceId)return null;let result=await gatewayClient.workspaceQuery(FIND_EXISTING_AGENT_QUERY,{workspaceId});if(result.errors?.length)return getDaemonProfile().logger.warn(LOG_SOURCE2,"Failed to discover existing agent record",{errors:result.errors.map((error3)=>error3.message)}),null;let normalizedHostname=hostname.toLowerCase(),match=result.data?.vibecontrolsAgents?.find((agent)=>agent.hostname.toLowerCase()===normalizedHostname);if(!match)return null;return await db.setConfig("gateway-auth:agentRecordId",match.id),getDaemonProfile().logger.info(LOG_SOURCE2,"Recovered existing agent record ID",{agentRecordId:match.id,hostname}),match.id}async function agentRecordExists(workspaceId,agentRecordId){try{let result=await gatewayClient.workspaceQuery(FIND_EXISTING_AGENT_QUERY,{workspaceId});if(result.errors?.length)return!0;let agents=result.data?.vibecontrolsAgents;if(!agents)return!0;return agents.some((a)=>a.id===agentRecordId)}catch{return!0}}async function reportLifecycleState(db,state){if(!gatewayClient.isConfigured())return;let agentRecordId=await getOrDiscoverAgentRecordId(db,process.env.VIBE_AGENT_NAME||os.hostname());if(!agentRecordId)return;if(state!=="killed"){getDaemonProfile().logger.debug(LOG_SOURCE2,`Skipping '${state}' lifecycle sync \u2014 startup auto-report already refreshes the live agent record and the current backend schema has no dedicated lifecycle field.`);return}let result=await gatewayClient.workspaceQuery(DEACTIVATE_AGENT_MUTATION,{id:agentRecordId});if(result.errors?.length)getDaemonProfile().logger.warn(LOG_SOURCE2,`Failed to report lifecycle state '${state}'`,{errors:result.errors.map((e)=>e.message)});else getDaemonProfile().logger.info(LOG_SOURCE2,`Reported lifecycle state: ${state}`)}async function verifyAndRetryUpdate(agentRecordId,tunnelUrl,apiKey,workspaceId){let wsId=workspaceId||gatewayClient.getConfig()?.workspaceId||"";for(let attempt=1;attempt<=3;attempt++){await new Promise((r)=>setTimeout(r,1500));let backendUrl=(await gatewayClient.workspaceQuery(FIND_EXISTING_AGENT_QUERY,{workspaceId:wsId})).data?.vibecontrolsAgents?.find((a)=>a.id===agentRecordId)?.tunnelUrl??null;if(backendUrl===tunnelUrl)return getDaemonProfile().logger.info(LOG_SOURCE2,`Verified: backend tunnelUrl matches (attempt ${attempt})`),!0;getDaemonProfile().logger.warn(LOG_SOURCE2,`Verification failed (attempt ${attempt}/3): backend has '${backendUrl}', expected '${tunnelUrl}' \u2014 retrying update`),await gatewayClient.workspaceQuery(UPDATE_AGENT_MUTATION,{id:agentRecordId,input:{tunnelUrl:tunnelUrl||null,tunnelStatus:tunnelUrl?"CONNECTED":"DISCONNECTED",agentApiKey:apiKey}})}return getDaemonProfile().logger.error(LOG_SOURCE2,"Failed to verify tunnel URL update after 3 attempts"),!1}async function sendHeartbeat(agentRecordId){try{let result=await gatewayClient.workspaceQuery(HEARTBEAT_MUTATION,{id:agentRecordId});if(result.errors?.length)getDaemonProfile().logger.debug(LOG_SOURCE2,"Heartbeat returned errors",{errors:result.errors.map((e)=>e.message)});else getDaemonProfile().logger.debug(LOG_SOURCE2,"Heartbeat sent successfully")}catch(err){getDaemonProfile().logger.debug(LOG_SOURCE2,`Heartbeat failed: ${err instanceof Error?err.message:String(err)}`)}}var NOTIFY_PLUGIN_CHANGE_MUTATION=`
173
+ `;async function waitForTunnelUrl(serviceRegistry){if(process.env.AGENT_TUNNEL_URL){let safeUrl=sanitizeOperatorTunnelUrl(process.env.AGENT_TUNNEL_URL);if(!safeUrl)return getDaemonProfile().logger.warn(LOG_SOURCE2,"Ignoring invalid AGENT_TUNNEL_URL"),null;return getDaemonProfile().logger.debug(LOG_SOURCE2,`Using AGENT_TUNNEL_URL from environment: ${safeUrl}`),safeUrl}for(let attempt=1;attempt<=MAX_RETRIES;attempt++){let providers=[],defaultProvider=serviceRegistry.getProvider("tunnel");if(defaultProvider)providers.push(defaultProvider);for(let entry of serviceRegistry.listProvidersForType("tunnel")){let provider=serviceRegistry.getProviderByName("tunnel",entry.pluginName);if(provider&&!providers.includes(provider))providers.push(provider)}for(let tunnelProvider of providers){if(!tunnelProvider.getActiveTunnelUrl)continue;let url=await tunnelProvider.getActiveTunnelUrl(),safeUrl=sanitizeTunnelUrl(url);if(safeUrl)return getDaemonProfile().logger.debug(LOG_SOURCE2,`Tunnel URL available on attempt ${attempt}: ${safeUrl}`),safeUrl;if(url)getDaemonProfile().logger.warn(LOG_SOURCE2,"Tunnel provider returned invalid URL",{url})}if(attempt<MAX_RETRIES)getDaemonProfile().logger.debug(LOG_SOURCE2,`Tunnel URL not ready, retrying in ${RETRY_INTERVAL_MS/1000}s (attempt ${attempt}/${MAX_RETRIES})`),await new Promise((resolve)=>setTimeout(resolve,RETRY_INTERVAL_MS))}return getDaemonProfile().logger.warn(LOG_SOURCE2,`Tunnel URL not available after ${MAX_RETRIES} attempts`),null}async function getOrDiscoverAgentRecordId(db,hostname){let cachedAgentRecordId=await db.getConfig("gateway-auth:agentRecordId");if(cachedAgentRecordId)return cachedAgentRecordId;let workspaceId=await db.getConfig("gateway-auth:workspaceId");if(!workspaceId)return null;let result=await gatewayClient.workspaceQuery(FIND_EXISTING_AGENT_QUERY,{workspaceId});if(result.errors?.length)return getDaemonProfile().logger.warn(LOG_SOURCE2,"Failed to discover existing agent record",{errors:result.errors.map((error3)=>error3.message)}),null;let normalizedHostname=hostname.toLowerCase(),match=result.data?.vibecontrolsAgents?.find((agent)=>agent.hostname.toLowerCase()===normalizedHostname);if(!match)return null;return await db.setConfig("gateway-auth:agentRecordId",match.id),getDaemonProfile().logger.info(LOG_SOURCE2,"Recovered existing agent record ID",{agentRecordId:match.id,hostname}),match.id}async function agentRecordExists(workspaceId,agentRecordId){try{let result=await gatewayClient.workspaceQuery(FIND_EXISTING_AGENT_QUERY,{workspaceId});if(result.errors?.length)return!0;let agents=result.data?.vibecontrolsAgents;if(!agents)return!0;return agents.some((a)=>a.id===agentRecordId)}catch{return!0}}async function reportLifecycleState(db,state){if(!gatewayClient.isConfigured())return;let agentRecordId=await getOrDiscoverAgentRecordId(db,process.env.VIBE_AGENT_NAME||os.hostname());if(!agentRecordId)return;if(state!=="killed"){getDaemonProfile().logger.debug(LOG_SOURCE2,`Skipping '${state}' lifecycle sync \u2014 startup auto-report already refreshes the live agent record and the current backend schema has no dedicated lifecycle field.`);return}let result=await gatewayClient.workspaceQuery(DEACTIVATE_AGENT_MUTATION,{id:agentRecordId});if(result.errors?.length)getDaemonProfile().logger.warn(LOG_SOURCE2,`Failed to report lifecycle state '${state}'`,{errors:result.errors.map((e)=>e.message)});else getDaemonProfile().logger.info(LOG_SOURCE2,`Reported lifecycle state: ${state}`)}async function verifyAndRetryUpdate(agentRecordId,tunnelUrl,apiKey,workspaceId){let wsId=workspaceId||gatewayClient.getConfig()?.workspaceId||"";for(let attempt=1;attempt<=3;attempt++){await new Promise((r)=>setTimeout(r,1500));let backendUrl=(await gatewayClient.workspaceQuery(FIND_EXISTING_AGENT_QUERY,{workspaceId:wsId})).data?.vibecontrolsAgents?.find((a)=>a.id===agentRecordId)?.tunnelUrl??null;if(backendUrl===tunnelUrl)return getDaemonProfile().logger.info(LOG_SOURCE2,`Verified: backend tunnelUrl matches (attempt ${attempt})`),!0;getDaemonProfile().logger.warn(LOG_SOURCE2,`Verification failed (attempt ${attempt}/3): backend has '${backendUrl}', expected '${tunnelUrl}' \u2014 retrying update`),await gatewayClient.workspaceQuery(UPDATE_AGENT_MUTATION,{id:agentRecordId,input:{tunnelUrl:tunnelUrl||null,tunnelStatus:tunnelUrl?"CONNECTED":"DISCONNECTED",agentApiKey:apiKey}})}return getDaemonProfile().logger.error(LOG_SOURCE2,"Failed to verify tunnel URL update after 3 attempts"),!1}async function sendHeartbeat(agentRecordId){try{let result=await gatewayClient.workspaceQuery(HEARTBEAT_MUTATION,{id:agentRecordId});if(result.errors?.length)getDaemonProfile().logger.debug(LOG_SOURCE2,"Heartbeat returned errors",{errors:result.errors.map((e)=>e.message)});else getDaemonProfile().logger.debug(LOG_SOURCE2,"Heartbeat sent successfully")}catch(err){getDaemonProfile().logger.debug(LOG_SOURCE2,`Heartbeat failed: ${err instanceof Error?err.message:String(err)}`)}}var NOTIFY_PLUGIN_CHANGE_MUTATION=`
174
174
  mutation NotifyVibecontrolsAgentPluginChange($agentId: ID!) {
175
175
  notifyVibecontrolsAgentPluginChange(agentId: $agentId)
176
176
  }
@@ -1,6 +1,6 @@
1
1
  // @bun
2
- import{readPrereqState,runPluginPrereqs}from"./index-9nn2kpyg.js";import{notifyBackendPluginChange}from"./index-8xr7ewxg.js";import"./index-23rdsqea.js";import"./index-1atc02se.js";import{AVAILABLE_PLUGINS,getCatalogEntry,isCriticalPlugin,isTrustedPackage,validatePluginPackageName}from"./index-7qj1swrk.js";import"./index-srbb2214.js";import"./index-brtw3j8x.js";import"./index-b4wy3jrt.js";import{INTERNAL_DISPATCH_HEADER,getInternalDispatchToken}from"./index-d3mz9vws.js";import{Elysia,t}from"./index-rnk0kny8.js";import{apiGet,apiPost,getAgentUrl,maybePrintJson,pickOutputMode,resolveProfileName,runMultimode}from"./index-wvabz3xh.js";import{colors,errMsg,fail,formatTable,header,info,kv,success,warn}from"./index-r0qezdp7.js";import{interactiveDetail,interactiveTable}from"./index-campp0wv.js";import"./index-2pqv0bya.js";import{getDaemonProfile}from"./index-7pdmqbj8.js";import"./index-bysm7taq.js";import"./index-zs58d1hc.js";import{__require}from"./index-e9rt4m94.js";import{timingSafeEqual}from"crypto";async function getRegistryIntegrity(pkg,version){try{let proc=Bun.spawn({cmd:["npm","view",`${pkg}@${version}`,"dist.integrity","--json"],stdout:"pipe",stderr:"pipe"});if(await proc.exited!==0)return null;let trimmed=(await new Response(proc.stdout).text()).trim();if(!trimmed)return null;if(trimmed.startsWith('"'))try{let parsed=JSON.parse(trimmed);return typeof parsed==="string"?parsed:null}catch{return null}return trimmed}catch{return null}}function compareIntegrity(expected,actual){let a=Buffer.from(expected),b=Buffer.from(actual);if(a.length!==b.length)return!1;try{return timingSafeEqual(a,b)}catch{return!1}}var AVAILABLE_PLUGINS2=AVAILABLE_PLUGINS.map((p)=>({packageName:p.packageName,name:p.pluginName,description:p.description,cliCommand:p.cliCommand,apiPrefix:p.apiPrefix,installed:!1,category:p.category})),lifecycleLocks=new Map;function withPluginLifecycleLock(packageName,fn){let run=(lifecycleLocks.get(packageName)??Promise.resolve()).then(fn,fn),stored=run.then(()=>{return},()=>{return});return lifecycleLocks.set(packageName,stored),stored.finally(()=>{if(lifecycleLocks.get(packageName)===stored)lifecycleLocks.delete(packageName)}),run}function isPackageInstallInFlight(packageName){return lifecycleLocks.has(packageName)}function availablePluginsPayload(pluginManager){let installed=pluginManager.getPluginDetails(),installedNames=new Set(installed.map((p)=>p.packageName));return{plugins:AVAILABLE_PLUGINS2.map((p)=>({...p,installed:installedNames.has(p.packageName)}))}}function createRoutes(deps){let{pluginManager}=deps;return new Elysia().get("/",()=>{let plugins=pluginManager.getPluginDetails();return{plugins,count:plugins.length}}).get("/available",()=>availablePluginsPayload(pluginManager)).get("/catalog",()=>availablePluginsPayload(pluginManager)).get("/contributions",({query})=>{let wantedMount=typeof query?.mountPoint==="string"&&query.mountPoint?query.mountPoint:null,items=[],packageNameByPluginName=new Map;for(let detail of pluginManager.getPluginDetails())packageNameByPluginName.set(detail.pluginName,detail.packageName);for(let plugin of pluginManager.getAllPlugins()){let ui=plugin.ui;if(!ui||!ui.contributions||ui.contributions.length===0)continue;let fallbackCaps=ui.capabilities??{restPaths:[],wsTopics:[],rpcMethods:[]};for(let contribution of ui.contributions){if(wantedMount&&contribution.mountPoint!==wantedMount)continue;let meta=contribution.meta,rawOverride=meta&&typeof meta.url==="string"?meta.url:null,overrideUrl=rawOverride&&rawOverride.startsWith("/")&&!rawOverride.startsWith("//")&&!rawOverride.includes("\x00")&&!rawOverride.includes("..")?rawOverride:null;items.push({pluginKey:plugin.name,pluginPackageName:packageNameByPluginName.get(plugin.name),contribution,capabilities:contribution.capabilities??fallbackCaps,url:overrideUrl??`/ui/${encodeURIComponent(plugin.name)}`})}}return{contributions:items,count:items.length}}).post("/install",async({body,set})=>{if(!body.packageName||typeof body.packageName!=="string")return set.status=400,{error:"Missing required field: packageName"};if(body.packageName.startsWith("@burdenoff/"))body.packageName=body.packageName.replace(/^@burdenoff\//,"@vibecontrols/");if(!isTrustedPackage(body.packageName))return set.status=403,{error:"Plugin package is not in the trusted VibeControls catalog"};try{let packageName=validatePluginPackageName(body.packageName);if(isPackageInstallInFlight(packageName)){let slug=packageName.split("/").pop()?.replace("vibe-plugin-","");if(pluginManager.getAllPlugins().some((p)=>p.name===slug))return{success:!0,message:`Plugin ${packageName} is already installed`,packageName,alreadyInstalled:!0};return set.status=409,{error:"Install for this package is already in progress. Wait for it to finish.",packageName}}return await withPluginLifecycleLock(packageName,async()=>{let pluginName=packageName.split("/").pop()?.replace("vibe-plugin-",""),legacyAiProviderName=pluginName?.startsWith("ai-")?pluginName.slice(3):void 0,existingPlugin=pluginManager.getAllPlugins().find((p)=>p.name===pluginName||p.name===legacyAiProviderName),alreadyRunning=!!existingPlugin,installedEntry=await pluginManager.install(packageName),catalogEntry=getCatalogEntry(packageName);if(catalogEntry?.integrity){let actualIntegrity=await getRegistryIntegrity(packageName,installedEntry.version);if(!actualIntegrity||!compareIntegrity(catalogEntry.integrity,actualIntegrity)){try{await pluginManager.remove(packageName,deps.hostServices)}catch(rollbackErr){console.warn(`[plugin-mgr] integrity rollback uninstall failed for ${packageName}:`,rollbackErr)}return getDaemonProfile().audit.emit("agent","plugin.install.rejected",{packageName,version:installedEntry.version,reason:"integrity_mismatch",expected:catalogEntry.integrity,actual:actualIntegrity}),set.status=400,{error:"integrity mismatch",expected:catalogEntry.integrity,actual:actualIntegrity}}}else console.warn(`[plugin-mgr] plugin ${packageName} has no pinned integrity \u2014 accepting npm registry's hash`);let newPlugin=pluginManager.getAllPlugins().find((p)=>p.name===installedEntry.pluginName);if(newPlugin){let lifecycleErrors=[];if(deps.mountPlugin)deps.mountPlugin(newPlugin);if(deps.hostServices){if(alreadyRunning&&existingPlugin?.onServerStop)try{await existingPlugin.onServerStop()}catch(err){lifecycleErrors.push(`onServerStop failed: ${err instanceof Error?err.message:String(err)}`)}if(pluginManager.registerProviders(newPlugin,deps.hostServices),newPlugin.onServerStart&&deps.app)try{await newPlugin.onServerStart(deps.app,deps.hostServices),pluginManager.registerProviders(newPlugin,deps.hostServices)}catch(err){lifecycleErrors.push(`onServerStart failed: ${err instanceof Error?err.message:String(err)}`)}if(newPlugin.onServerReady&&deps.app)try{await newPlugin.onServerReady(deps.app,deps.hostServices)}catch(err){lifecycleErrors.push(`onServerReady failed: ${err instanceof Error?err.message:String(err)}`)}}if(deps.rebuildPluginSurfaces?.(),lifecycleErrors.length>0)return set.status=500,{success:!1,message:`Plugin ${packageName} installed but failed to start`,lifecycleErrors,restartRequired:!0}}let prereqs;if(newPlugin&&deps.app)try{prereqs=await runPluginPrereqs(newPlugin,packageName,deps.app,deps.db,{skipInstall:!!body.skipPrereqs})}catch(err){prereqs=void 0,console.warn(`[plugin-mgr] prereq run failed for ${packageName}:`,err)}return notifyBackendPluginChange(deps.db),getDaemonProfile().audit.emit("agent","plugin.installed",{packageName,version:installedEntry.version,pluginName:installedEntry.pluginName,wasRunning:alreadyRunning}),{success:!0,message:`Plugin ${packageName} installed and loaded successfully`,prereqs:prereqs?{satisfied:prereqs.satisfied,missing:prereqs.status?.missing??[],pendingSudo:prereqs.pendingSudo,skipped:!!body.skipPrereqs}:void 0}})}catch(err){return set.status=500,{error:"Failed to install plugin",details:String(err)}}},{body:t.Object({packageName:t.String(),skipPrereqs:t.Optional(t.Boolean())})}).post("/prereqs/status",async({body,set})=>{if(!body.packageName)return set.status=400,{error:"Missing packageName"};let pkg=body.packageName,plugin=pluginManager.getAllPlugins().find((p)=>p.name===pkg||pluginManager.getLoaded(pkg)?.name===p.name);if(!plugin||!deps.app)return await readPrereqState(deps.db,pkg)??{satisfied:!0,missing:[]};try{let r=await runPluginPrereqs(plugin,pkg,deps.app,deps.db,{skipInstall:!0});return{satisfied:r.satisfied,missing:r.status?.missing??[],noProtocol:r.noProtocol}}catch(err){return set.status=500,{error:String(err)}}},{body:t.Object({packageName:t.String()})}).post("/prereqs/install",async({body,set})=>{if(!body.packageName)return set.status=400,{error:"Missing packageName"};let pkg=body.packageName,plugin=pluginManager.getAllPlugins().find((p)=>p.name===pkg||pluginManager.getLoaded(pkg)?.name===p.name);if(!plugin||!deps.app)return set.status=404,{error:"Plugin not loaded"};try{let r=await runPluginPrereqs(plugin,pkg,deps.app,deps.db,{skipInstall:!1});return{satisfied:r.satisfied,installed:r.install?.installed??[],pendingSudo:r.pendingSudo,errors:r.install?.errors??[],noProtocol:r.noProtocol}}catch(err){return set.status=500,{error:String(err)}}},{body:t.Object({packageName:t.String(),approveSudo:t.Optional(t.Boolean())})}).post("/prereqs/uninstall",async({body,set})=>{if(!body.packageName)return set.status=400,{error:"Missing packageName"};let pkg=body.packageName,plugin=pluginManager.getAllPlugins().find((p)=>p.name===pkg);if(!plugin||!plugin.apiPrefix||!deps.app)return set.status=404,{error:"Plugin not loaded"};let handle=deps.app.handle;if(typeof handle!=="function")return set.status=500,{error:"App handle unavailable"};let path=`${plugin.apiPrefix.replace(/\/+$/,"")}/prereqs/uninstall`,res=await handle.call(deps.app,new Request(`http://agent.local${path}`,{method:"POST",headers:{"x-vc-profile-rewrite":"1",[INTERNAL_DISPATCH_HEADER]:getInternalDispatchToken()}}));if(res.status===404)return set.status=404,{error:"Plugin has no prereqs/uninstall endpoint"};return res.json()},{body:t.Object({packageName:t.String()})}).post("/nuke",async({body,set})=>{if(!deps.hostServices)return set.status=503,{error:"hostServices unavailable"};let agentDir=deps.hostServices.getDataDir?.();return{ok:!0,...await pluginManager.runPluginNuke(body.packageName,deps.hostServices,{agentDir,dryRun:!!body.dryRun})}},{body:t.Object({packageName:t.Optional(t.String()),dryRun:t.Optional(t.Boolean())})}).post("/remove",async({body,set})=>{if(!body.packageName||typeof body.packageName!=="string")return set.status=400,{error:"Missing required field: packageName"};if(body.packageName.startsWith("@burdenoff/"))body.packageName=body.packageName.replace(/^@burdenoff\//,"@vibecontrols/");if(isCriticalPlugin(body.packageName))return{success:!0,message:`Plugin ${body.packageName} is critical and cannot be removed; treating remove as a no-op.`,skipped:!0};try{let packageName=validatePluginPackageName(body.packageName);return await withPluginLifecycleLock(packageName,async()=>{return await pluginManager.remove(packageName,deps.hostServices),deps.rebuildPluginSurfaces?.(),notifyBackendPluginChange(deps.db),getDaemonProfile().audit.emit("agent","plugin.removed",{packageName}),{success:!0,message:`Plugin ${packageName} removed successfully`}})}catch(err){return set.status=500,{error:"Failed to remove plugin",details:String(err)}}},{body:t.Object({packageName:t.String()})}).post("/update",async({body,set})=>{if(!body.packageName||typeof body.packageName!=="string")return set.status=400,{error:"Missing required field: packageName"};try{let packageName=validatePluginPackageName(body.packageName);return await withPluginLifecycleLock(packageName,async()=>{let existingPlugin=pluginManager.getLoaded(packageName);if(existingPlugin?.onServerStop)await existingPlugin.onServerStop({reason:"reload"});if(existingPlugin&&deps.hostServices)deps.hostServices.serviceRegistry.unregisterPlugin(existingPlugin.name);let entry=await pluginManager.update(packageName),updatedPlugin=pluginManager.getLoaded(packageName);if(updatedPlugin&&deps.hostServices){if(pluginManager.registerProviders(updatedPlugin,deps.hostServices),updatedPlugin.onServerStart&&deps.app)await updatedPlugin.onServerStart(deps.app,deps.hostServices),pluginManager.registerProviders(updatedPlugin,deps.hostServices);if(updatedPlugin.onServerReady&&deps.app)await updatedPlugin.onServerReady(deps.app,deps.hostServices)}return deps.rebuildPluginSurfaces?.(),notifyBackendPluginChange(deps.db),{success:!0,message:`Plugin ${packageName} updated to v${entry.version}`,version:entry.version}})}catch(err){return set.status=500,{error:"Failed to update plugin",details:String(err)}}},{body:t.Object({packageName:t.String()})}).post("/update-all",async({set})=>{try{let results=await withPluginLifecycleLock("*",()=>pluginManager.updateAll());return{success:!0,results,message:`Updated ${results.filter((r)=>r.success).length}/${results.length} plugin(s)`}}catch(err){return set.status=500,{error:"Failed to update all plugins",details:String(err)}}}).post("/remove-all",async({set})=>{try{let results=await withPluginLifecycleLock("*",async()=>{let removed=await pluginManager.removeAll(deps.hostServices);return deps.rebuildPluginSurfaces?.(),removed});return{success:!0,results,message:`Removed ${results.filter((r)=>r.success).length}/${results.length} plugin(s)`}}catch(err){return set.status=500,{error:"Failed to remove all plugins",details:String(err)}}}).post("/reload",async({set})=>{try{if(!deps.app||!deps.hostServices)return set.status=503,{error:"Plugin lifecycle services are not ready"};let plugins=await withPluginLifecycleLock("*",async()=>{return await pluginManager.reloadAll(deps.app,deps.hostServices),deps.rebuildPluginSurfaces?.(),pluginManager.getPluginDetails()});return{success:!0,plugins,message:`Reloaded ${plugins.length} plugin(s)`}}catch(err){return set.status=500,{error:"Failed to reload plugins",details:String(err)}}}).post("/:name/reload",async({params,set})=>{if(!deps.app||!deps.hostServices)return set.status=503,{error:"Plugin lifecycle services are not ready"};let target=params.name,plugin=pluginManager.getAllPlugins().find((p)=>p.name===target);if(!plugin)return set.status=404,{error:`Plugin "${target}" not found`};let packageName=pluginManager.getPluginDetails().find((d)=>d.pluginName===target)?.packageName??`core:${target}`;if(isPackageInstallInFlight(packageName))return set.status=409,{error:"Plugin lifecycle in progress; try again shortly",packageName};try{return await withPluginLifecycleLock(packageName,async()=>{if(plugin.onServerStop)try{await plugin.onServerStop({reason:"reload"})}catch(err){console.warn(`[plugin-mgr] onServerStop during reload of ${target}:`,err)}if(deps.hostServices)deps.hostServices.serviceRegistry.unregisterPlugin(plugin.name);if(pluginManager.registerProviders(plugin,deps.hostServices),plugin.onServerStart)await plugin.onServerStart(deps.app,deps.hostServices),pluginManager.registerProviders(plugin,deps.hostServices);if(plugin.onServerReady)await plugin.onServerReady(deps.app,deps.hostServices);return deps.rebuildPluginSurfaces?.(),{success:!0,message:`Plugin ${target} reloaded`,version:plugin.version}})}catch(err){return set.status=500,{error:"Failed to reload plugin",details:String(err)}}},{params:t.Object({name:t.String()})})}import{mkdirSync,writeFileSync,existsSync}from"fs";import{isAbsolute,join,relative,resolve}from"path";var DEFAULT_AGENT_URL="http://localhost:3005",PLUGIN_BASENAME_RE=/^[a-z0-9][a-z0-9-]{0,63}$/,ALLOWED_TAGS=new Set(["backend","frontend","cli","provider","adapter","integration"]);function assertInside(parent,child){let rel=relative(parent,child);if(rel.startsWith("..")||isAbsolute(rel))throw Error("Plugin scaffold path escapes the selected directory.")}function toLiteral(value){return JSON.stringify(value)}function register(program){let cmd=program.command("plugin").description("Manage plugins");cmd.command("list").description("List installed plugins").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON").option("--plain","Force plain text output").action(async(options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged)),fetchData=async()=>{try{return(await apiGet(url,`/api/profiles/${profile}/plugins`)).plugins||[]}catch{warn("Agent not reachable. Attempting local plugin registry...");let{PluginManager}=await import("./plugin-system-afa49gcv.js");return new PluginManager().getPluginDetails()||[]}},statusOf=(p)=>p.status??(p.loaded===!0||p.enabled===!0?"enabled":"disabled"),nameOf=(p)=>p.pluginName||p.name||p.packageName||p.package||"-";await runMultimode({mode:pickOutputMode(merged),fetchData,plain:(list)=>{if(!list.length){info("No plugins installed.");return}header("Installed Plugins"),formatTable(list.map((p)=>({Name:nameOf(p),Version:p.version||"-",Status:statusOf(p),Description:p.description||"-"})))},interactive:async(list)=>{if(!list.length){header("Installed Plugins"),info("No plugins installed.");return}let rows=list.map((p)=>{let name=nameOf(p),status=statusOf(p),detailLines=[`${colors.bold(name)} ${status==="enabled"?colors.green(status):colors.dim(status)}`,"",` Version: ${p.version||"-"}`,` Description: ${p.description||"-"}`];if(p.tags&&Array.isArray(p.tags))detailLines.push(` Tags: ${p.tags.join(", ")}`);if(p.cliCommand)detailLines.push(` CLI command: vibe ${p.cliCommand}`);return{id:name,label:name,hint:status,detail:detailLines.join(`
3
- `)}});await interactiveTable({title:`vibe plugin \u2014 ${list.length} installed`,rows,footer:"\u2191/\u2193 navigate \xB7 q to quit"})},json:(list)=>list.map((p)=>({name:nameOf(p),version:p.version??null,status:statusOf(p),description:p.description??null,tags:p.tags??null,cliCommand:p.cliCommand??null}))})}catch(err){fail(errMsg(err))}}),cmd.command("install").description("Install a plugin").argument("<package>","NPM package name to install").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--skip-prereqs","Skip running the plugin's prereqs/install",!1).option("--json","Emit JSON result").action(async(packageName,options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged));try{let result=await apiPost(url,`/api/profiles/${profile}/plugins/install`,{packageName,skipPrereqs:!!options.skipPrereqs});if(maybePrintJson(merged,{ok:!0,action:"install",package:packageName,version:result?.version??null,prereqs:result?.prereqs??null}))return;if(success(`Plugin "${packageName}" installed.`),result?.version)kv("Version",result.version);if(result?.prereqs){let p=result.prereqs;if(p.skipped)warn(`Prerequisite install skipped. Run \`vibe plugin prereqs ${packageName} install\` later.`);else if(!p.satisfied)warn(`Prerequisites not yet satisfied: ${(p.missing||[]).map((m)=>m.name).join(", ")||"(unknown)"}`);if((p.pendingSudo||[]).length>0){warn(`${p.pendingSudo.length} command(s) need sudo. Run them and re-check with \`vibe plugin prereqs ${packageName} status\`:`);for(let ps of p.pendingSudo)kv(` ${ps.name}`,ps.command)}}}catch{warn("Agent not reachable. Attempting local install...");try{let{PluginManager}=await import("./plugin-system-afa49gcv.js");if(await new PluginManager().install(packageName),maybePrintJson(merged,{ok:!0,action:"install",package:packageName,local:!0}))return;success(`Plugin "${packageName}" installed locally.`)}catch(localErr){fail(`Could not install plugin via agent or locally: ${errMsg(localErr)}`)}}}catch(err){fail(errMsg(err))}}),cmd.command("remove").description("Remove a plugin").argument("<package>","NPM package name to remove").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON result").action(async(packageName,options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged));try{if(await apiPost(url,`/api/profiles/${profile}/plugins/remove`,{packageName}),maybePrintJson(merged,{ok:!0,action:"remove",package:packageName}))return;success(`Plugin "${packageName}" removed.`)}catch{warn("Agent not reachable. Attempting local removal...");try{let{PluginManager}=await import("./plugin-system-afa49gcv.js");if(await new PluginManager().remove(packageName),maybePrintJson(merged,{ok:!0,action:"remove",package:packageName,local:!0}))return;success(`Plugin "${packageName}" removed locally.`)}catch(localErr){fail(`Could not remove plugin via agent or locally: ${errMsg(localErr)}`)}}}catch(err){fail(errMsg(err))}}),cmd.command("update").description("Update a plugin (or all plugins with --all)").argument("[package]","NPM package name to update").option("--all","Update all installed plugins",!1).option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON result").action(async(packageName,options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged));if(options.all){info("Updating all plugins...");try{let result=await apiPost(url,`/api/profiles/${profile}/plugins/update-all`,{}),results=result?.results||[];if(maybePrintJson(merged,{ok:!0,action:"update-all",results}))return;for(let r of results)if(r.success)success(`Updated ${r.packageName}${r.version?` to v${r.version}`:""}`);else warn(`Failed to update ${r.packageName}: ${r.error}`);success(result?.message||"Done.")}catch{warn("Agent not reachable. Attempting local update...");try{let{PluginManager}=await import("./plugin-system-afa49gcv.js"),results=await new PluginManager().updateAll();if(maybePrintJson(merged,{ok:!0,action:"update-all",results,local:!0}))return;for(let r of results)if(r.success)success(`Updated ${r.packageName}${r.version?` to v${r.version}`:""}`);else warn(`Failed to update ${r.packageName}: ${r.error}`)}catch(localErr){fail(`Could not update plugins: ${errMsg(localErr)}`)}}}else if(packageName){info(`Updating ${packageName}...`);try{let result=await apiPost(url,`/api/profiles/${profile}/plugins/update`,{packageName});if(maybePrintJson(merged,{ok:!0,action:"update",package:packageName,version:result?.version??null,message:result?.message??null}))return;success(result?.message||`Plugin "${packageName}" updated.`)}catch{warn("Agent not reachable. Attempting local update...");try{let{PluginManager}=await import("./plugin-system-afa49gcv.js"),entry=await new PluginManager().update(packageName);if(maybePrintJson(merged,{ok:!0,action:"update",package:packageName,version:entry.version,local:!0}))return;success(`Plugin "${packageName}" updated to v${entry.version}.`)}catch(localErr){fail(`Could not update plugin: ${errMsg(localErr)}`)}}}else fail("Provide a package name to update, or use --all to update all plugins.")}catch(err){fail(errMsg(err))}}),cmd.command("uninstall").description("Uninstall a plugin (or all plugins with --all)").argument("[package]","NPM package name to uninstall").option("--all","Uninstall all external plugins",!1).option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON result").action(async(packageName,options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged));if(options.all){info("Uninstalling all plugins...");try{let result=await apiPost(url,`/api/profiles/${profile}/plugins/remove-all`,{}),results=result?.results||[];if(maybePrintJson(merged,{ok:!0,action:"uninstall-all",results}))return;for(let r of results)if(r.success)success(`Removed ${r.packageName}`);else warn(`Failed to remove ${r.packageName}: ${r.error}`);success(result?.message||"Done.")}catch{warn("Agent not reachable. Attempting local removal...");try{let{PluginManager}=await import("./plugin-system-afa49gcv.js"),results=await new PluginManager().removeAll();if(maybePrintJson(merged,{ok:!0,action:"uninstall-all",results,local:!0}))return;for(let r of results)if(r.success)success(`Removed ${r.packageName}`);else warn(`Failed to remove ${r.packageName}: ${r.error}`)}catch(localErr){fail(`Could not uninstall plugins: ${errMsg(localErr)}`)}}}else if(packageName)try{if(await apiPost(url,`/api/profiles/${profile}/plugins/remove`,{packageName}),maybePrintJson(merged,{ok:!0,action:"uninstall",package:packageName}))return;success(`Plugin "${packageName}" uninstalled.`)}catch{warn("Agent not reachable. Attempting local removal...");try{let{PluginManager}=await import("./plugin-system-afa49gcv.js");if(await new PluginManager().remove(packageName),maybePrintJson(merged,{ok:!0,action:"uninstall",package:packageName,local:!0}))return;success(`Plugin "${packageName}" uninstalled locally.`)}catch(localErr){fail(`Could not uninstall plugin: ${errMsg(localErr)}`)}}else fail("Provide a package name to uninstall, or use --all to uninstall all plugins.")}catch(err){fail(errMsg(err))}}),cmd.command("reload").description("Reload all plugins").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON result").action(async(options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged));if(await apiPost(url,`/api/profiles/${profile}/plugins/reload`,{}),maybePrintJson(merged,{ok:!0,action:"reload"}))return;success("Plugins reloaded.")}catch(err){fail(errMsg(err))}}),cmd.command("available").description("Show available plugins").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON").option("--plain","Force plain text output").action(async(options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged)),fetchData=async()=>{return(await apiGet(url,`/api/profiles/${profile}/plugins/available`)).plugins||[]},nameOf=(p)=>p.name||p.package||"-",versionOf=(p)=>p.version||p.latestVersion||"-";await runMultimode({mode:pickOutputMode(merged),fetchData,plain:(plugins)=>{if(!plugins||plugins.length===0){info("No available plugins found.");return}header("Available Plugins"),formatTable(plugins.map((p)=>({Name:nameOf(p),Version:versionOf(p),Description:p.description||"-"})))},interactive:async(plugins)=>{if(!plugins||plugins.length===0){header("Available Plugins"),info("No available plugins found.");return}let rows=plugins.map((p)=>{let name=nameOf(p),lines=[colors.bold(name),"",` Version: ${versionOf(p)}`,` Description: ${p.description||"-"}`];return{id:name,label:name,hint:versionOf(p),detail:lines.join(`
2
+ import{readPrereqState,runPluginPrereqs}from"./index-9nn2kpyg.js";import{notifyBackendPluginChange}from"./index-q96eskyn.js";import"./index-23rdsqea.js";import"./index-ttafzcs7.js";import{AVAILABLE_PLUGINS,getCatalogEntry,isCriticalPlugin,isTrustedPackage,validatePluginPackageName}from"./index-1x89a7r1.js";import"./index-srbb2214.js";import"./index-brtw3j8x.js";import"./index-b4wy3jrt.js";import{INTERNAL_DISPATCH_HEADER,getInternalDispatchToken}from"./index-d3mz9vws.js";import{Elysia,t}from"./index-rnk0kny8.js";import{apiGet,apiPost,getAgentUrl,maybePrintJson,pickOutputMode,resolveProfileName,runMultimode}from"./index-wvabz3xh.js";import{colors,errMsg,fail,formatTable,header,info,kv,success,warn}from"./index-r0qezdp7.js";import{interactiveDetail,interactiveTable}from"./index-campp0wv.js";import"./index-2pqv0bya.js";import{getDaemonProfile}from"./index-7pdmqbj8.js";import"./index-bysm7taq.js";import"./index-zs58d1hc.js";import{__require}from"./index-e9rt4m94.js";import{timingSafeEqual}from"crypto";async function getRegistryIntegrity(pkg,version){try{let proc=Bun.spawn({cmd:["npm","view",`${pkg}@${version}`,"dist.integrity","--json"],stdout:"pipe",stderr:"pipe"});if(await proc.exited!==0)return null;let trimmed=(await new Response(proc.stdout).text()).trim();if(!trimmed)return null;if(trimmed.startsWith('"'))try{let parsed=JSON.parse(trimmed);return typeof parsed==="string"?parsed:null}catch{return null}return trimmed}catch{return null}}function compareIntegrity(expected,actual){let a=Buffer.from(expected),b=Buffer.from(actual);if(a.length!==b.length)return!1;try{return timingSafeEqual(a,b)}catch{return!1}}var AVAILABLE_PLUGINS2=AVAILABLE_PLUGINS.map((p)=>({packageName:p.packageName,name:p.pluginName,description:p.description,cliCommand:p.cliCommand,apiPrefix:p.apiPrefix,installed:!1,category:p.category})),lifecycleLocks=new Map;function withPluginLifecycleLock(packageName,fn){let run=(lifecycleLocks.get(packageName)??Promise.resolve()).then(fn,fn),stored=run.then(()=>{return},()=>{return});return lifecycleLocks.set(packageName,stored),stored.finally(()=>{if(lifecycleLocks.get(packageName)===stored)lifecycleLocks.delete(packageName)}),run}function isPackageInstallInFlight(packageName){return lifecycleLocks.has(packageName)}function availablePluginsPayload(pluginManager){let installed=pluginManager.getPluginDetails(),installedNames=new Set(installed.map((p)=>p.packageName));return{plugins:AVAILABLE_PLUGINS2.map((p)=>({...p,installed:installedNames.has(p.packageName)}))}}function createRoutes(deps){let{pluginManager}=deps;return new Elysia().get("/",()=>{let plugins=pluginManager.getPluginDetails();return{plugins,count:plugins.length}}).get("/available",()=>availablePluginsPayload(pluginManager)).get("/catalog",()=>availablePluginsPayload(pluginManager)).get("/contributions",({query})=>{let wantedMount=typeof query?.mountPoint==="string"&&query.mountPoint?query.mountPoint:null,items=[],packageNameByPluginName=new Map;for(let detail of pluginManager.getPluginDetails())packageNameByPluginName.set(detail.pluginName,detail.packageName);for(let plugin of pluginManager.getAllPlugins()){let ui=plugin.ui;if(!ui||!ui.contributions||ui.contributions.length===0)continue;let fallbackCaps=ui.capabilities??{restPaths:[],wsTopics:[],rpcMethods:[]};for(let contribution of ui.contributions){if(wantedMount&&contribution.mountPoint!==wantedMount)continue;let meta=contribution.meta,rawOverride=meta&&typeof meta.url==="string"?meta.url:null,overrideUrl=rawOverride&&rawOverride.startsWith("/")&&!rawOverride.startsWith("//")&&!rawOverride.includes("\x00")&&!rawOverride.includes("..")?rawOverride:null;items.push({pluginKey:plugin.name,pluginPackageName:packageNameByPluginName.get(plugin.name),contribution,capabilities:contribution.capabilities??fallbackCaps,url:overrideUrl??`/ui/${encodeURIComponent(plugin.name)}`})}}return{contributions:items,count:items.length}}).post("/install",async({body,set})=>{if(!body.packageName||typeof body.packageName!=="string")return set.status=400,{error:"Missing required field: packageName"};if(body.packageName.startsWith("@burdenoff/"))body.packageName=body.packageName.replace(/^@burdenoff\//,"@vibecontrols/");if(!isTrustedPackage(body.packageName))return set.status=403,{error:"Plugin package is not in the trusted VibeControls catalog"};try{let packageName=validatePluginPackageName(body.packageName);if(isPackageInstallInFlight(packageName)){let slug=packageName.split("/").pop()?.replace("vibe-plugin-","");if(pluginManager.getAllPlugins().some((p)=>p.name===slug))return{success:!0,message:`Plugin ${packageName} is already installed`,packageName,alreadyInstalled:!0};return set.status=409,{error:"Install for this package is already in progress. Wait for it to finish.",packageName}}return await withPluginLifecycleLock(packageName,async()=>{let pluginName=packageName.split("/").pop()?.replace("vibe-plugin-",""),legacyAiProviderName=pluginName?.startsWith("ai-")?pluginName.slice(3):void 0,existingPlugin=pluginManager.getAllPlugins().find((p)=>p.name===pluginName||p.name===legacyAiProviderName),alreadyRunning=!!existingPlugin,installedEntry=await pluginManager.install(packageName),catalogEntry=getCatalogEntry(packageName);if(catalogEntry?.integrity){let actualIntegrity=await getRegistryIntegrity(packageName,installedEntry.version);if(!actualIntegrity||!compareIntegrity(catalogEntry.integrity,actualIntegrity)){try{await pluginManager.remove(packageName,deps.hostServices)}catch(rollbackErr){console.warn(`[plugin-mgr] integrity rollback uninstall failed for ${packageName}:`,rollbackErr)}return getDaemonProfile().audit.emit("agent","plugin.install.rejected",{packageName,version:installedEntry.version,reason:"integrity_mismatch",expected:catalogEntry.integrity,actual:actualIntegrity}),set.status=400,{error:"integrity mismatch",expected:catalogEntry.integrity,actual:actualIntegrity}}}else console.warn(`[plugin-mgr] plugin ${packageName} has no pinned integrity \u2014 accepting npm registry's hash`);let newPlugin=pluginManager.getAllPlugins().find((p)=>p.name===installedEntry.pluginName);if(newPlugin){let lifecycleErrors=[];if(deps.mountPlugin)deps.mountPlugin(newPlugin);if(deps.hostServices){if(alreadyRunning&&existingPlugin?.onServerStop)try{await existingPlugin.onServerStop()}catch(err){lifecycleErrors.push(`onServerStop failed: ${err instanceof Error?err.message:String(err)}`)}if(pluginManager.registerProviders(newPlugin,deps.hostServices),newPlugin.onServerStart&&deps.app)try{await newPlugin.onServerStart(deps.app,deps.hostServices),pluginManager.registerProviders(newPlugin,deps.hostServices)}catch(err){lifecycleErrors.push(`onServerStart failed: ${err instanceof Error?err.message:String(err)}`)}if(newPlugin.onServerReady&&deps.app)try{await newPlugin.onServerReady(deps.app,deps.hostServices)}catch(err){lifecycleErrors.push(`onServerReady failed: ${err instanceof Error?err.message:String(err)}`)}}if(deps.rebuildPluginSurfaces?.(),lifecycleErrors.length>0)return set.status=500,{success:!1,message:`Plugin ${packageName} installed but failed to start`,lifecycleErrors,restartRequired:!0}}let prereqs;if(newPlugin&&deps.app)try{prereqs=await runPluginPrereqs(newPlugin,packageName,deps.app,deps.db,{skipInstall:!!body.skipPrereqs})}catch(err){prereqs=void 0,console.warn(`[plugin-mgr] prereq run failed for ${packageName}:`,err)}return notifyBackendPluginChange(deps.db),getDaemonProfile().audit.emit("agent","plugin.installed",{packageName,version:installedEntry.version,pluginName:installedEntry.pluginName,wasRunning:alreadyRunning}),{success:!0,message:`Plugin ${packageName} installed and loaded successfully`,prereqs:prereqs?{satisfied:prereqs.satisfied,missing:prereqs.status?.missing??[],pendingSudo:prereqs.pendingSudo,skipped:!!body.skipPrereqs}:void 0}})}catch(err){return set.status=500,{error:"Failed to install plugin",details:String(err)}}},{body:t.Object({packageName:t.String(),skipPrereqs:t.Optional(t.Boolean())})}).post("/prereqs/status",async({body,set})=>{if(!body.packageName)return set.status=400,{error:"Missing packageName"};let pkg=body.packageName,plugin=pluginManager.getAllPlugins().find((p)=>p.name===pkg||pluginManager.getLoaded(pkg)?.name===p.name);if(!plugin||!deps.app)return await readPrereqState(deps.db,pkg)??{satisfied:!0,missing:[]};try{let r=await runPluginPrereqs(plugin,pkg,deps.app,deps.db,{skipInstall:!0});return{satisfied:r.satisfied,missing:r.status?.missing??[],noProtocol:r.noProtocol}}catch(err){return set.status=500,{error:String(err)}}},{body:t.Object({packageName:t.String()})}).post("/prereqs/install",async({body,set})=>{if(!body.packageName)return set.status=400,{error:"Missing packageName"};let pkg=body.packageName,plugin=pluginManager.getAllPlugins().find((p)=>p.name===pkg||pluginManager.getLoaded(pkg)?.name===p.name);if(!plugin||!deps.app)return set.status=404,{error:"Plugin not loaded"};try{let r=await runPluginPrereqs(plugin,pkg,deps.app,deps.db,{skipInstall:!1});return{satisfied:r.satisfied,installed:r.install?.installed??[],pendingSudo:r.pendingSudo,errors:r.install?.errors??[],noProtocol:r.noProtocol}}catch(err){return set.status=500,{error:String(err)}}},{body:t.Object({packageName:t.String(),approveSudo:t.Optional(t.Boolean())})}).post("/prereqs/uninstall",async({body,set})=>{if(!body.packageName)return set.status=400,{error:"Missing packageName"};let pkg=body.packageName,plugin=pluginManager.getAllPlugins().find((p)=>p.name===pkg);if(!plugin||!plugin.apiPrefix||!deps.app)return set.status=404,{error:"Plugin not loaded"};let handle=deps.app.handle;if(typeof handle!=="function")return set.status=500,{error:"App handle unavailable"};let path=`${plugin.apiPrefix.replace(/\/+$/,"")}/prereqs/uninstall`,res=await handle.call(deps.app,new Request(`http://agent.local${path}`,{method:"POST",headers:{"x-vc-profile-rewrite":"1",[INTERNAL_DISPATCH_HEADER]:getInternalDispatchToken()}}));if(res.status===404)return set.status=404,{error:"Plugin has no prereqs/uninstall endpoint"};return res.json()},{body:t.Object({packageName:t.String()})}).post("/nuke",async({body,set})=>{if(!deps.hostServices)return set.status=503,{error:"hostServices unavailable"};let agentDir=deps.hostServices.getDataDir?.();return{ok:!0,...await pluginManager.runPluginNuke(body.packageName,deps.hostServices,{agentDir,dryRun:!!body.dryRun})}},{body:t.Object({packageName:t.Optional(t.String()),dryRun:t.Optional(t.Boolean())})}).post("/remove",async({body,set})=>{if(!body.packageName||typeof body.packageName!=="string")return set.status=400,{error:"Missing required field: packageName"};if(body.packageName.startsWith("@burdenoff/"))body.packageName=body.packageName.replace(/^@burdenoff\//,"@vibecontrols/");if(isCriticalPlugin(body.packageName))return{success:!0,message:`Plugin ${body.packageName} is critical and cannot be removed; treating remove as a no-op.`,skipped:!0};try{let packageName=validatePluginPackageName(body.packageName);return await withPluginLifecycleLock(packageName,async()=>{return await pluginManager.remove(packageName,deps.hostServices),deps.rebuildPluginSurfaces?.(),notifyBackendPluginChange(deps.db),getDaemonProfile().audit.emit("agent","plugin.removed",{packageName}),{success:!0,message:`Plugin ${packageName} removed successfully`}})}catch(err){return set.status=500,{error:"Failed to remove plugin",details:String(err)}}},{body:t.Object({packageName:t.String()})}).post("/update",async({body,set})=>{if(!body.packageName||typeof body.packageName!=="string")return set.status=400,{error:"Missing required field: packageName"};try{let packageName=validatePluginPackageName(body.packageName);return await withPluginLifecycleLock(packageName,async()=>{let existingPlugin=pluginManager.getLoaded(packageName);if(existingPlugin?.onServerStop)await existingPlugin.onServerStop({reason:"reload"});if(existingPlugin&&deps.hostServices)deps.hostServices.serviceRegistry.unregisterPlugin(existingPlugin.name);let entry=await pluginManager.update(packageName),updatedPlugin=pluginManager.getLoaded(packageName);if(updatedPlugin&&deps.hostServices){if(pluginManager.registerProviders(updatedPlugin,deps.hostServices),updatedPlugin.onServerStart&&deps.app)await updatedPlugin.onServerStart(deps.app,deps.hostServices),pluginManager.registerProviders(updatedPlugin,deps.hostServices);if(updatedPlugin.onServerReady&&deps.app)await updatedPlugin.onServerReady(deps.app,deps.hostServices)}return deps.rebuildPluginSurfaces?.(),notifyBackendPluginChange(deps.db),{success:!0,message:`Plugin ${packageName} updated to v${entry.version}`,version:entry.version}})}catch(err){return set.status=500,{error:"Failed to update plugin",details:String(err)}}},{body:t.Object({packageName:t.String()})}).post("/update-all",async({set})=>{try{let results=await withPluginLifecycleLock("*",()=>pluginManager.updateAll());return{success:!0,results,message:`Updated ${results.filter((r)=>r.success).length}/${results.length} plugin(s)`}}catch(err){return set.status=500,{error:"Failed to update all plugins",details:String(err)}}}).post("/remove-all",async({set})=>{try{let results=await withPluginLifecycleLock("*",async()=>{let removed=await pluginManager.removeAll(deps.hostServices);return deps.rebuildPluginSurfaces?.(),removed});return{success:!0,results,message:`Removed ${results.filter((r)=>r.success).length}/${results.length} plugin(s)`}}catch(err){return set.status=500,{error:"Failed to remove all plugins",details:String(err)}}}).post("/reload",async({set})=>{try{if(!deps.app||!deps.hostServices)return set.status=503,{error:"Plugin lifecycle services are not ready"};let plugins=await withPluginLifecycleLock("*",async()=>{return await pluginManager.reloadAll(deps.app,deps.hostServices),deps.rebuildPluginSurfaces?.(),pluginManager.getPluginDetails()});return{success:!0,plugins,message:`Reloaded ${plugins.length} plugin(s)`}}catch(err){return set.status=500,{error:"Failed to reload plugins",details:String(err)}}}).post("/:name/reload",async({params,set})=>{if(!deps.app||!deps.hostServices)return set.status=503,{error:"Plugin lifecycle services are not ready"};let target=params.name,plugin=pluginManager.getAllPlugins().find((p)=>p.name===target);if(!plugin)return set.status=404,{error:`Plugin "${target}" not found`};let packageName=pluginManager.getPluginDetails().find((d)=>d.pluginName===target)?.packageName??`core:${target}`;if(isPackageInstallInFlight(packageName))return set.status=409,{error:"Plugin lifecycle in progress; try again shortly",packageName};try{return await withPluginLifecycleLock(packageName,async()=>{if(plugin.onServerStop)try{await plugin.onServerStop({reason:"reload"})}catch(err){console.warn(`[plugin-mgr] onServerStop during reload of ${target}:`,err)}if(deps.hostServices)deps.hostServices.serviceRegistry.unregisterPlugin(plugin.name);if(pluginManager.registerProviders(plugin,deps.hostServices),plugin.onServerStart)await plugin.onServerStart(deps.app,deps.hostServices),pluginManager.registerProviders(plugin,deps.hostServices);if(plugin.onServerReady)await plugin.onServerReady(deps.app,deps.hostServices);return deps.rebuildPluginSurfaces?.(),{success:!0,message:`Plugin ${target} reloaded`,version:plugin.version}})}catch(err){return set.status=500,{error:"Failed to reload plugin",details:String(err)}}},{params:t.Object({name:t.String()})})}import{mkdirSync,writeFileSync,existsSync}from"fs";import{isAbsolute,join,relative,resolve}from"path";var DEFAULT_AGENT_URL="http://localhost:3005",PLUGIN_BASENAME_RE=/^[a-z0-9][a-z0-9-]{0,63}$/,ALLOWED_TAGS=new Set(["backend","frontend","cli","provider","adapter","integration"]);function assertInside(parent,child){let rel=relative(parent,child);if(rel.startsWith("..")||isAbsolute(rel))throw Error("Plugin scaffold path escapes the selected directory.")}function toLiteral(value){return JSON.stringify(value)}function register(program){let cmd=program.command("plugin").description("Manage plugins");cmd.command("list").description("List installed plugins").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON").option("--plain","Force plain text output").action(async(options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged)),fetchData=async()=>{try{return(await apiGet(url,`/api/profiles/${profile}/plugins`)).plugins||[]}catch{warn("Agent not reachable. Attempting local plugin registry...");let{PluginManager}=await import("./plugin-system-3z2smf2a.js");return new PluginManager().getPluginDetails()||[]}},statusOf=(p)=>p.status??(p.loaded===!0||p.enabled===!0?"enabled":"disabled"),nameOf=(p)=>p.pluginName||p.name||p.packageName||p.package||"-";await runMultimode({mode:pickOutputMode(merged),fetchData,plain:(list)=>{if(!list.length){info("No plugins installed.");return}header("Installed Plugins"),formatTable(list.map((p)=>({Name:nameOf(p),Version:p.version||"-",Status:statusOf(p),Description:p.description||"-"})))},interactive:async(list)=>{if(!list.length){header("Installed Plugins"),info("No plugins installed.");return}let rows=list.map((p)=>{let name=nameOf(p),status=statusOf(p),detailLines=[`${colors.bold(name)} ${status==="enabled"?colors.green(status):colors.dim(status)}`,"",` Version: ${p.version||"-"}`,` Description: ${p.description||"-"}`];if(p.tags&&Array.isArray(p.tags))detailLines.push(` Tags: ${p.tags.join(", ")}`);if(p.cliCommand)detailLines.push(` CLI command: vibe ${p.cliCommand}`);return{id:name,label:name,hint:status,detail:detailLines.join(`
3
+ `)}});await interactiveTable({title:`vibe plugin \u2014 ${list.length} installed`,rows,footer:"\u2191/\u2193 navigate \xB7 q to quit"})},json:(list)=>list.map((p)=>({name:nameOf(p),version:p.version??null,status:statusOf(p),description:p.description??null,tags:p.tags??null,cliCommand:p.cliCommand??null}))})}catch(err){fail(errMsg(err))}}),cmd.command("install").description("Install a plugin").argument("<package>","NPM package name to install").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--skip-prereqs","Skip running the plugin's prereqs/install",!1).option("--json","Emit JSON result").action(async(packageName,options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged));try{let result=await apiPost(url,`/api/profiles/${profile}/plugins/install`,{packageName,skipPrereqs:!!options.skipPrereqs});if(maybePrintJson(merged,{ok:!0,action:"install",package:packageName,version:result?.version??null,prereqs:result?.prereqs??null}))return;if(success(`Plugin "${packageName}" installed.`),result?.version)kv("Version",result.version);if(result?.prereqs){let p=result.prereqs;if(p.skipped)warn(`Prerequisite install skipped. Run \`vibe plugin prereqs ${packageName} install\` later.`);else if(!p.satisfied)warn(`Prerequisites not yet satisfied: ${(p.missing||[]).map((m)=>m.name).join(", ")||"(unknown)"}`);if((p.pendingSudo||[]).length>0){warn(`${p.pendingSudo.length} command(s) need sudo. Run them and re-check with \`vibe plugin prereqs ${packageName} status\`:`);for(let ps of p.pendingSudo)kv(` ${ps.name}`,ps.command)}}}catch{warn("Agent not reachable. Attempting local install...");try{let{PluginManager}=await import("./plugin-system-3z2smf2a.js");if(await new PluginManager().install(packageName),maybePrintJson(merged,{ok:!0,action:"install",package:packageName,local:!0}))return;success(`Plugin "${packageName}" installed locally.`)}catch(localErr){fail(`Could not install plugin via agent or locally: ${errMsg(localErr)}`)}}}catch(err){fail(errMsg(err))}}),cmd.command("remove").description("Remove a plugin").argument("<package>","NPM package name to remove").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON result").action(async(packageName,options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged));try{if(await apiPost(url,`/api/profiles/${profile}/plugins/remove`,{packageName}),maybePrintJson(merged,{ok:!0,action:"remove",package:packageName}))return;success(`Plugin "${packageName}" removed.`)}catch{warn("Agent not reachable. Attempting local removal...");try{let{PluginManager}=await import("./plugin-system-3z2smf2a.js");if(await new PluginManager().remove(packageName),maybePrintJson(merged,{ok:!0,action:"remove",package:packageName,local:!0}))return;success(`Plugin "${packageName}" removed locally.`)}catch(localErr){fail(`Could not remove plugin via agent or locally: ${errMsg(localErr)}`)}}}catch(err){fail(errMsg(err))}}),cmd.command("update").description("Update a plugin (or all plugins with --all)").argument("[package]","NPM package name to update").option("--all","Update all installed plugins",!1).option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON result").action(async(packageName,options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged));if(options.all){info("Updating all plugins...");try{let result=await apiPost(url,`/api/profiles/${profile}/plugins/update-all`,{}),results=result?.results||[];if(maybePrintJson(merged,{ok:!0,action:"update-all",results}))return;for(let r of results)if(r.success)success(`Updated ${r.packageName}${r.version?` to v${r.version}`:""}`);else warn(`Failed to update ${r.packageName}: ${r.error}`);success(result?.message||"Done.")}catch{warn("Agent not reachable. Attempting local update...");try{let{PluginManager}=await import("./plugin-system-3z2smf2a.js"),results=await new PluginManager().updateAll();if(maybePrintJson(merged,{ok:!0,action:"update-all",results,local:!0}))return;for(let r of results)if(r.success)success(`Updated ${r.packageName}${r.version?` to v${r.version}`:""}`);else warn(`Failed to update ${r.packageName}: ${r.error}`)}catch(localErr){fail(`Could not update plugins: ${errMsg(localErr)}`)}}}else if(packageName){info(`Updating ${packageName}...`);try{let result=await apiPost(url,`/api/profiles/${profile}/plugins/update`,{packageName});if(maybePrintJson(merged,{ok:!0,action:"update",package:packageName,version:result?.version??null,message:result?.message??null}))return;success(result?.message||`Plugin "${packageName}" updated.`)}catch{warn("Agent not reachable. Attempting local update...");try{let{PluginManager}=await import("./plugin-system-3z2smf2a.js"),entry=await new PluginManager().update(packageName);if(maybePrintJson(merged,{ok:!0,action:"update",package:packageName,version:entry.version,local:!0}))return;success(`Plugin "${packageName}" updated to v${entry.version}.`)}catch(localErr){fail(`Could not update plugin: ${errMsg(localErr)}`)}}}else fail("Provide a package name to update, or use --all to update all plugins.")}catch(err){fail(errMsg(err))}}),cmd.command("uninstall").description("Uninstall a plugin (or all plugins with --all)").argument("[package]","NPM package name to uninstall").option("--all","Uninstall all external plugins",!1).option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON result").action(async(packageName,options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged));if(options.all){info("Uninstalling all plugins...");try{let result=await apiPost(url,`/api/profiles/${profile}/plugins/remove-all`,{}),results=result?.results||[];if(maybePrintJson(merged,{ok:!0,action:"uninstall-all",results}))return;for(let r of results)if(r.success)success(`Removed ${r.packageName}`);else warn(`Failed to remove ${r.packageName}: ${r.error}`);success(result?.message||"Done.")}catch{warn("Agent not reachable. Attempting local removal...");try{let{PluginManager}=await import("./plugin-system-3z2smf2a.js"),results=await new PluginManager().removeAll();if(maybePrintJson(merged,{ok:!0,action:"uninstall-all",results,local:!0}))return;for(let r of results)if(r.success)success(`Removed ${r.packageName}`);else warn(`Failed to remove ${r.packageName}: ${r.error}`)}catch(localErr){fail(`Could not uninstall plugins: ${errMsg(localErr)}`)}}}else if(packageName)try{if(await apiPost(url,`/api/profiles/${profile}/plugins/remove`,{packageName}),maybePrintJson(merged,{ok:!0,action:"uninstall",package:packageName}))return;success(`Plugin "${packageName}" uninstalled.`)}catch{warn("Agent not reachable. Attempting local removal...");try{let{PluginManager}=await import("./plugin-system-3z2smf2a.js");if(await new PluginManager().remove(packageName),maybePrintJson(merged,{ok:!0,action:"uninstall",package:packageName,local:!0}))return;success(`Plugin "${packageName}" uninstalled locally.`)}catch(localErr){fail(`Could not uninstall plugin: ${errMsg(localErr)}`)}}else fail("Provide a package name to uninstall, or use --all to uninstall all plugins.")}catch(err){fail(errMsg(err))}}),cmd.command("reload").description("Reload all plugins").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON result").action(async(options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged));if(await apiPost(url,`/api/profiles/${profile}/plugins/reload`,{}),maybePrintJson(merged,{ok:!0,action:"reload"}))return;success("Plugins reloaded.")}catch(err){fail(errMsg(err))}}),cmd.command("available").description("Show available plugins").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON").option("--plain","Force plain text output").action(async(options)=>{try{let merged={...program.opts(),...options},url=getAgentUrl(options),profile=encodeURIComponent(resolveProfileName(merged)),fetchData=async()=>{return(await apiGet(url,`/api/profiles/${profile}/plugins/available`)).plugins||[]},nameOf=(p)=>p.name||p.package||"-",versionOf=(p)=>p.version||p.latestVersion||"-";await runMultimode({mode:pickOutputMode(merged),fetchData,plain:(plugins)=>{if(!plugins||plugins.length===0){info("No available plugins found.");return}header("Available Plugins"),formatTable(plugins.map((p)=>({Name:nameOf(p),Version:versionOf(p),Description:p.description||"-"})))},interactive:async(plugins)=>{if(!plugins||plugins.length===0){header("Available Plugins"),info("No available plugins found.");return}let rows=plugins.map((p)=>{let name=nameOf(p),lines=[colors.bold(name),"",` Version: ${versionOf(p)}`,` Description: ${p.description||"-"}`];return{id:name,label:name,hint:versionOf(p),detail:lines.join(`
4
4
  `)}});await interactiveTable({title:`vibe plugin available \u2014 ${plugins.length} plugin(s)`,rows,footer:"\u2191/\u2193 navigate \xB7 q to quit"})},json:(plugins)=>plugins.map((p)=>({name:nameOf(p),version:versionOf(p),description:p.description??null}))})}catch(err){fail(errMsg(err))}});let prereqsCmd=cmd.command("prereqs").description("Inspect or run a plugin's prerequisite-install protocol").argument("<package>","NPM package name (or short plugin name)");prereqsCmd.command("status",{isDefault:!0}).description("Show the plugin's prereq status").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON").option("--plain","Force plain text output").action(async(options,cmdRef)=>{let pkg=cmdRef.parent?.args?.[0];if(!pkg){fail("Missing plugin package argument.");return}try{let merged={...program.opts(),...options},url=getAgentUrl(options),fetchData=async()=>apiPost(url,"/api/plugins/prereqs/status",{packageName:pkg});await runMultimode({mode:pickOutputMode(merged),fetchData,plain:(r)=>{if(kv("Plugin",pkg),kv("Satisfied",r?.satisfied?"yes":"no"),Array.isArray(r?.missing)&&r.missing.length>0)kv("Missing",r.missing.map((m)=>m.name).join(", "))},interactive:async(r)=>{let lines=[`Plugin: ${pkg}`,`Satisfied: ${r?.satisfied?"yes":"no"}`];if(Array.isArray(r?.missing)&&r.missing.length>0)lines.push(`Missing: ${r.missing.map((m)=>m.name).join(", ")}`);await interactiveDetail({title:`Prereqs: ${pkg}`,body:lines.join(`
5
5
  `),footer:"q / Esc to quit"})},json:(r)=>({plugin:pkg,satisfied:!!r?.satisfied,missing:Array.isArray(r?.missing)?r.missing:[],pendingSudo:Array.isArray(r?.pendingSudo)?r.pendingSudo:[]})})}catch(err){fail(`Could not read prereq status: ${errMsg(err)}`)}}),prereqsCmd.command("install").description("Run the plugin's prerequisite install endpoint").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--approve-sudo","Auto-approve sudo commands the plugin returns",!1).option("--json","Emit JSON result").action(async(options,cmdRef)=>{let pkg=cmdRef.parent?.args?.[0];if(!pkg){fail("Missing plugin package argument.");return}try{let merged={...program.opts(),...options},url=getAgentUrl(options),r=await apiPost(url,"/api/plugins/prereqs/install",{packageName:pkg,approveSudo:!!options.approveSudo});if(maybePrintJson(merged,{ok:!0,action:"prereqs-install",plugin:pkg,satisfied:!!r?.satisfied,pendingSudo:r?.pendingSudo??[]}))return;if(r?.satisfied)success(`Prerequisites satisfied for ${pkg}.`);else warn(`Prerequisites still missing for ${pkg}.`);if(Array.isArray(r?.pendingSudo)&&r.pendingSudo.length>0){warn(`${r.pendingSudo.length} command(s) require sudo:`);for(let ps of r.pendingSudo)kv(` ${ps.name}`,ps.command)}}catch(err){fail(`Prereq install failed: ${errMsg(err)}`)}}),prereqsCmd.command("uninstall").description("Run the plugin's prerequisite uninstall endpoint (if supported)").option("--agent-url <url>","Agent URL",DEFAULT_AGENT_URL).option("--profile <name>","Target a specific profile by name").option("--json","Emit JSON result").action(async(options,cmdRef)=>{let pkg=cmdRef.parent?.args?.[0];if(!pkg){fail("Missing plugin package argument.");return}try{let merged={...program.opts(),...options},url=getAgentUrl(options);if(await apiPost(url,"/api/plugins/prereqs/uninstall",{packageName:pkg}),maybePrintJson(merged,{ok:!0,action:"prereqs-uninstall",plugin:pkg}))return;success(`Prereq uninstall completed for ${pkg}.`)}catch(err){warn(`Prereq uninstall not supported or failed: ${errMsg(err)}`)}}),cmd.command("create").description("Scaffold a new plugin project").argument("<name>",'Plugin name (e.g. "docker" \u2192 vibe-plugin-docker)').option("-d, --dir <directory>","Parent directory",".").option("--tag <tag>","Plugin tag (backend, frontend, cli, provider, adapter, integration)","backend").option("--with-ui","Include a companion UI plugin scaffold",!1).option("--json","Emit JSON result").action(async(name,options)=>{try{let merged={...program.opts(),...options},baseName=name.startsWith("vibe-plugin-")?name.slice(12):name;if(!PLUGIN_BASENAME_RE.test(baseName)){fail("Plugin name must use lowercase letters, numbers, and dashes only.");return}let tag=options.tag;if(!ALLOWED_TAGS.has(tag)){fail("Invalid plugin tag.");return}let pluginName=`vibe-plugin-${baseName}`,parentDir=resolve(options.dir),dir=resolve(parentDir,pluginName);if(assertInside(parentDir,dir),existsSync(dir)){fail(`Directory "${dir}" already exists.`);return}info(`Scaffolding ${pluginName}...`),mkdirSync(join(dir,"src"),{recursive:!0}),mkdirSync(join(dir,"dist"),{recursive:!0});let description=`VibeControls plugin: ${baseName}`,packageJson={name:`@vibecontrols/${pluginName}`,version:"0.1.0",main:"./dist/index.js",type:"module",engines:{bun:">=1.3.0"},scripts:{build:"bun build ./src/index.ts --outdir ./dist --target bun",lint:"eslint ./src",format:"bunx prettier . --write","format:check":"bunx prettier . --check","type:check":"tsc --noEmit",clean:"rimraf dist",prebuild:"bun run clean",prepublishOnly:"bun run build",sanity:"bun run format:check && bun run lint && bun run type:check && bun run build"},keywords:["vibecontrols","vibe","vibe-plugin",baseName,"bun"],author:{name:"Your Name",email:"you@example.com"},license:"SEE LICENSE IN LICENSE",description,devDependencies:{"@types/bun":"^1.2.16","bun-types":"^1.3.9",commander:"^14.0.3",eslint:"^9.30.1",prettier:"^3.6.2",rimraf:"^6.0.1",typescript:"^5.8.3","typescript-eslint":"^8.56.0"},peerDependencies:{"@vibecontrols/agent":">=2.0.0"},peerDependenciesMeta:{"@vibecontrols/agent":{optional:!0}},publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},files:["dist/**/*","README.md","LICENSE"]};writeFileSync(join(dir,"package.json"),JSON.stringify(packageJson,null,2)+`
6
6
  `);let tsconfig={compilerOptions:{target:"ES2022",module:"ES2022",moduleResolution:"bundler",types:["bun-types"],strict:!0,esModuleInterop:!0,skipLibCheck:!0,outDir:"./dist",rootDir:"./src",declaration:!0,sourceMap:!0},include:["src/**/*.ts"],exclude:["node_modules","dist"]};writeFileSync(join(dir,"tsconfig.json"),JSON.stringify(tsconfig,null,2)+`
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- import{getPluginPackageRoot}from"./index-7qj1swrk.js";import{getAgentApiKey,getIframeTokenFromRequest,getUiCookieFromRequest,isValidUiPluginName,issueUiCookieToken,verifyIframeToken,verifyUiCookieToken}from"./index-b4wy3jrt.js";import{Elysia}from"./index-rnk0kny8.js";class CliContributorRegistry{statusSections=[];doctorChecks=[];addStatusSection(section){this.statusSections.push(section)}addDoctorCheck(check){this.doctorChecks.push(check)}getStatusSections(){return this.statusSections}getDoctorChecks(){return this.doctorChecks}}var activeRegistry=null;function setActiveContributorRegistry(registry){activeRegistry=registry}function getActiveContributorRegistry(){if(!activeRegistry)activeRegistry=new CliContributorRegistry;return activeRegistry}import{extname,relative,resolve}from"path";import{realpath}from"fs/promises";var DEFAULT_FRAME_ANCESTORS=["'self'","http://localhost:*","http://127.0.0.1:*","https://localhost:*","https://127.0.0.1:*","https://*.local.burdenoff.com","https://vibecontrols.com","https://*.vibecontrols.com","https://burdenoff.com","https://app.burdenoff.com","https://alphaapp.burdenoff.com"],warnedAboutUnsafeOverride=!1;function frameAncestorsCsp(){let override=process.env.VIBE_UI_FRAME_ANCESTORS?.trim(),sources=override?override.split(/[\s,]+/).filter(Boolean):DEFAULT_FRAME_ANCESTORS;if(override&&!warnedAboutUnsafeOverride&&(sources.includes("*")||!sources.includes("'self'")))warnedAboutUnsafeOverride=!0,console.warn(`[ui-server] VIBE_UI_FRAME_ANCESTORS override does not include "'self'" or contains "*". This significantly weakens CSP frame-ancestors and is almost never intended. Override: ${override}`);return`frame-ancestors ${sources.join(" ")}`}var MIME_TYPES={".html":"text/html",".js":"application/javascript",".mjs":"application/javascript",".css":"text/css",".json":"application/json",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".map":"application/json",".wasm":"application/wasm"};function getMimeType(filePath){return MIME_TYPES[extname(filePath).toLowerCase()]||"application/octet-stream"}var AUTH_BRIDGE_SCRIPT=`<script>
2
+ import{getPluginPackageRoot}from"./index-1x89a7r1.js";import{getAgentApiKey,getIframeTokenFromRequest,getUiCookieFromRequest,isValidUiPluginName,issueUiCookieToken,verifyIframeToken,verifyUiCookieToken}from"./index-b4wy3jrt.js";import{Elysia}from"./index-rnk0kny8.js";class CliContributorRegistry{statusSections=[];doctorChecks=[];addStatusSection(section){this.statusSections.push(section)}addDoctorCheck(check){this.doctorChecks.push(check)}getStatusSections(){return this.statusSections}getDoctorChecks(){return this.doctorChecks}}var activeRegistry=null;function setActiveContributorRegistry(registry){activeRegistry=registry}function getActiveContributorRegistry(){if(!activeRegistry)activeRegistry=new CliContributorRegistry;return activeRegistry}import{extname,relative,resolve}from"path";import{realpath}from"fs/promises";var DEFAULT_FRAME_ANCESTORS=["'self'","http://localhost:*","http://127.0.0.1:*","https://localhost:*","https://127.0.0.1:*","https://*.local.burdenoff.com","https://vibecontrols.com","https://*.vibecontrols.com","https://burdenoff.com","https://app.burdenoff.com","https://alphaapp.burdenoff.com"],warnedAboutUnsafeOverride=!1;function frameAncestorsCsp(){let override=process.env.VIBE_UI_FRAME_ANCESTORS?.trim(),sources=override?override.split(/[\s,]+/).filter(Boolean):DEFAULT_FRAME_ANCESTORS;if(override&&!warnedAboutUnsafeOverride&&(sources.includes("*")||!sources.includes("'self'")))warnedAboutUnsafeOverride=!0,console.warn(`[ui-server] VIBE_UI_FRAME_ANCESTORS override does not include "'self'" or contains "*". This significantly weakens CSP frame-ancestors and is almost never intended. Override: ${override}`);return`frame-ancestors ${sources.join(" ")}`}var MIME_TYPES={".html":"text/html",".js":"application/javascript",".mjs":"application/javascript",".css":"text/css",".json":"application/json",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".map":"application/json",".wasm":"application/wasm"};function getMimeType(filePath){return MIME_TYPES[extname(filePath).toLowerCase()]||"application/octet-stream"}var AUTH_BRIDGE_SCRIPT=`<script>
3
3
  window.__VIBE_AUTH__={apiKey:null};
4
4
  (function(){
5
5
  var p=new URLSearchParams(window.location.search);