@whoz-oss/coday-server 0.107.1 → 0.107.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/server.js +1 -1
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -861,7 +861,7 @@ Are you sure you want to delete this MCP server configuration?
|
|
|
861
861
|
**ID:** \`${l.id}\`
|
|
862
862
|
**Level:** ${f}
|
|
863
863
|
**Status:** Successfully removed from configuration
|
|
864
|
-
`;return this.interactor.displayText(m),n}};var KS=class extends Zn{constructor(e,t){super({commandWord:"mcp",description:"Configure MCP (Model Context Protocol) servers"},e);let n=new GS(e,t.mcp);this.handlers=[new VS(e,t.mcp),n,new ZS(e,t.mcp,n),new JS(e,t.mcp)]}};import*as Va from"node:path";import*as vfe from"node:os";import{existsSync as YS,mkdirSync as gfe,readdirSync as xM,unlinkSync as Lit,writeFileSync as qit}from"fs";var XS=class r{codayConfigDir;projectService;constructor(e,t){let n=Va.join(vfe.userInfo().homedir,".coday");this.codayConfigDir=e??n,this.projectService=t}getProjectPath(e){if(this.projectService)return this.projectService.getProject(e)?.config.path}async getOrCreateAgentsDir(e,t){let n;if(t==="project")n=Va.join(this.codayConfigDir,"projects",e,"agents");else{let i=this.getProjectPath(e);if(!i)throw new Error("Project path not configured, cannot access colocated agents");let a=await d2({text:"coday.yaml",root:i});if(a.length===0)throw new Error(`coday.yaml not found in project path: ${i}`);let o=Va.dirname(a[0]);n=Va.join(i,o,"agents")}return YS(n)||(gfe(n,{recursive:!0}),console.log(`[AGENT_CRUD] Created agents directory: ${n}`)),n}findAgentFile(e,t){if(!YS(e))return null;let n=t.toLowerCase(),a=xM(e).filter(o=>o.endsWith(".yml")||o.endsWith(".yaml")).find(o=>o.replace(/\.ya?ml$/,"").toLowerCase()===n);return a?Va.join(e,a):null}async findAgentAcrossLocations(e,t){let n=Va.join(this.codayConfigDir,"projects",e,"agents"),i=this.findAgentFile(n,t);if(i)return{location:"project",filePath:i};if(this.projectService)try{let a=await this.getOrCreateAgentsDir(e,"colocated"),o=this.findAgentFile(a,t);if(o)return{location:"colocated",filePath:o}}catch{}return null}static RESERVED_NAMES=new Set(["editable","documents"]);validateAgentName(e){if(!e||typeof e!="string")throw new Error("Agent name is required");if(!/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(e))throw new Error("Agent name must start with alphanumeric and contain only letters, digits, hyphens or underscores");if(r.RESERVED_NAMES.has(e.toLowerCase()))throw new Error(`Agent name '${e}' is reserved and cannot be used`)}async list(e){let t=[],n=["project"];this.projectService&&n.push("colocated");for(let i of n)try{let a=await this.getOrCreateAgentsDir(e,i);if(!YS(a))continue;let o=xM(a).filter(s=>s.endsWith(".yml")||s.endsWith(".yaml"));for(let s of o){let c=s.replace(/\.ya?ml$/,""),u=Va.join(a,s),l=ta(u);l&&t.push({name:l.name??c,description:l.description??"",source:i,editable:!0})}}catch(a){console.log(`[AGENT_CRUD] Could not access ${i} agents for ${e}:`,a)}return t.sort((i,a)=>i.name.toLowerCase().localeCompare(a.name.toLowerCase()))}async get(e,t){let n=await this.findAgentAcrossLocations(e,t);if(!n)return null;let i=ta(n.filePath);return i?{definition:i,source:n.location,filePath:n.filePath,editable:!0}:null}async create(e,t,n){if(this.validateAgentName(t.name),!t.description)throw new Error("Agent description is required");let i=await this.findAgentAcrossLocations(e,t.name);if(i)throw new Error(`Agent '${t.name}' already exists in ${i.location} location`);let a=await this.getOrCreateAgentsDir(e,n),o=Va.join(a,`${t.name}.yml`);return Mn(o,t),console.log(`[AGENT_CRUD] Created agent '${t.name}' in ${n} for project ${e}`),{definition:t,source:n,filePath:o,editable:!0}}async update(e,t,n){let i=await this.findAgentAcrossLocations(e,t);if(!i)return null;if(n.description!==void 0&&!n.description)throw new Error("Agent description cannot be empty");let a=ta(i.filePath);if(!a)return null;let o={name:a.name,description:n.description??a.description,instructions:n.instructions,aiProvider:n.aiProvider,modelName:n.modelName,temperature:n.temperature,maxOutputTokens:n.maxOutputTokens,openaiAssistantId:n.openaiAssistantId,integrations:n.integrations,mandatoryDocs:n.mandatoryDocs??a.mandatoryDocs,optionalDocs:n.optionalDocs??a.optionalDocs};return Object.keys(o).forEach(s=>{o[s]===void 0&&delete o[s]}),Mn(i.filePath,o),console.log(`[AGENT_CRUD] Updated agent '${t}' in ${i.location} for project ${e}`),{definition:o,source:i.location,filePath:i.filePath,editable:!0}}async getOrCreateDocumentsDir(e,t){let n=await this.getOrCreateAgentsDir(e,t),i=Va.join(n,"documents");return YS(i)||gfe(i,{recursive:!0}),i}async listDocuments(e,t){try{let n=await this.getOrCreateDocumentsDir(e,t);return xM(n).filter(i=>!i.startsWith(".")).sort()}catch{return[]}}async saveDocument(e,t,n,i){if(i.length>10485760)throw new Error(`File too large: ${(i.length/1024/1024).toFixed(2)} MB exceeds maximum of ${10485760/1024/1024} MB`);if(!Rx(n))throw new Error(`File type not allowed for: ${n}`);let a=Va.basename(n);if(!a||a!==n)throw new Error("Invalid filename");let o=await this.getOrCreateDocumentsDir(e,t),s=Va.join(o,a);return qit(s,i),console.log(`[AGENT_CRUD] Saved document '${a}' in ${t} for project ${e}`),`documents/${a}`}async delete(e,t){let n=await this.findAgentAcrossLocations(e,t);return n?(Lit(n.filePath),console.log(`[AGENT_CRUD] Deleted agent '${t}' from ${n.location} for project ${e}`),!0):!1}};var QS=class{constructor(e,t){this.userService=e;this.projectService=t}providerCache=new Map;mergedConfig=null;initialize(e){this.providerCache.clear(),this.mergedConfig=null,this.providerCache.set("coday",e.project.ai||[]),this.providerCache.set("project",this.projectService.selectedProject?.config?.ai||[]),this.providerCache.set("user",this.userService.config.ai||[])}getProviders(e){return this.providerCache.get(e)||[]}getProvider(e,t){return Ri.validate(t),this.getProviders(t).find(i=>i.name===e)}async saveProvider(e,t){Ri.validate(t);let n=this.getProviders(t),i=n.findIndex(a=>a.name===e.name);i>=0?n[i]=e:n.push(e),await this.saveProviders(n,t),this.mergedConfig=null}async deleteProvider(e,t){Ri.validate(t);let n=this.getProviders(t),i=n.filter(a=>a.name!==e);i.length!==n.length&&(await this.saveProviders(i,t),this.mergedConfig=null)}getModel(e,t,n){return Ri.validate(n),this.getProvider(e,n)?.models?.find(a=>a.name===t||a.alias===t)}async saveModel(e,t,n){Ri.validate(n);let i=this.getProvider(e,n);i||(i={name:e,models:[]},await this.saveProvider(i,n));let a=i.models||[],o=a.findIndex(s=>s.name===t.name||t.alias&&s.alias===t.alias);o>=0?a[o]=t:a.push(t),i.models=a,await this.saveProvider(i,n),this.mergedConfig=null}async deleteModel(e,t,n){Ri.validate(n);let i=this.getProvider(e,n);if(i?.models){let a=i.models.filter(o=>o.name!==t&&o.alias!==t);a.length!==i.models.length&&(i.models=a,await this.saveProvider(i,n),this.mergedConfig=null)}}getMergedConfiguration(){if(this.mergedConfig)return this.mergedConfig;let e=[],t=new Map;for(let n of["coday","project","user"]){let i=this.providerCache.get(n)||[];for(let a of i){let o=e.findIndex(s=>s.name===a.name);if(o>=0){let s=e[o];if(e[o]={...s,...a},a.models?.length){let c=s.models||[];for(let u of a.models){let l=c.findIndex(f=>f.name===u.name||u.alias&&f.alias===u.alias);l>=0?c[l]={...c[l],...u,price:{...c[l]?.price,...u.price}}:c.push(u),u.alias&&t.set(u.alias,{provider:a.name,model:u.name})}e[o].models=c}}else e.push({...a}),a.models?.forEach(s=>{s.alias&&t.set(s.alias,{provider:a.name,model:s.name})})}}return this.mergedConfig={providers:e,modelAliasMap:t},this.mergedConfig}resolveModelAlias(e){return this.getMergedConfiguration().modelAliasMap.get(e)}async saveProviders(e,t){switch(t){case"project":if(!this.projectService.selectedProject)throw new Error("No project selected");let n={...this.projectService.selectedProject.config,ai:e};this.projectService.save(n),this.providerCache.set(t,e);break;case"user":this.userService.config.ai=e,this.userService.save(),this.providerCache.set(t,e);break}}};var W2=class{MASK_PATTERN="****";SENSITIVE_FIELD_NAMES=["apikey","api_key","password","token","secret","auth","client_id"];isSensitiveField(e){let t=e.toLowerCase();return this.SENSITIVE_FIELD_NAMES.some(n=>t.includes(n))}maskValue(e){if(!e||e.length===0)return e;if(e.length<=8)return this.MASK_PATTERN;if(e.length<12){let i=e.substring(0,2),a=e.substring(e.length-2);return`${i}${this.MASK_PATTERN}${a}`}let t=e.substring(0,4),n=e.substring(e.length-4);return`${t}${this.MASK_PATTERN}${n}`}isMasked(e){return typeof e=="string"&&e.includes(this.MASK_PATTERN)}maskConfig(e){if(e==null||typeof e!="object")return e;if(Array.isArray(e))return e.map(n=>this.maskConfig(n));let t={};for(let[n,i]of Object.entries(e))this.isSensitiveField(n)&&typeof i=="string"?t[n]=this.maskValue(i):n==="env"&&typeof i=="object"&&i!==null&&!Array.isArray(i)?t[n]=this.maskEnvObject(i):typeof i=="object"&&i!==null?t[n]=this.maskConfig(i):t[n]=i;return t}maskEnvObject(e){let t={};for(let[n,i]of Object.entries(e))typeof i=="string"?t[n]=this.maskValue(i):t[n]=i;return t}unmaskConfig(e,t){if(e==null||t==null||typeof e!="object")return e;if(Array.isArray(e))return e.map((o,s)=>{let c=Array.isArray(t)?t[s]:void 0;return this.unmaskConfig(o,c)});let n={},i=e,a=t;for(let[o,s]of Object.entries(i)){let c=a[o];this.isSensitiveField(o)&&typeof s=="string"?this.isMasked(s)?n[o]=c:n[o]=s:o==="env"&&typeof s=="object"&&s!==null&&!Array.isArray(s)?n[o]=this.unmaskEnvObject(s,c):typeof s=="object"&&s!==null?n[o]=this.unmaskConfig(s,c):n[o]=s}if(!Array.isArray(e))for(let[o,s]of Object.entries(a))o in i||(n[o]=s);return n}unmaskEnvObject(e,t){if(!t||typeof t!="object")return e;let n={};for(let[i,a]of Object.entries(e))typeof a=="string"&&this.isMasked(a)?n[i]=t[i]:n[i]=a;for(let[i,a]of Object.entries(t))i in e||(n[i]=a);return n}};import*as mm from"node:path";import{existsSync as Uit,mkdirSync as zit}from"fs";import*as bfe from"node:os";var Bit="users",yfe="user.yaml",V2=class{constructor(e,t,n){this.username=t;this.interactor=n;this.sanitizedUsername=k6(t);let i=mm.join(bfe.userInfo().homedir,".coday"),a=mm.join(e??i,Bit);this.userConfigPath=mm.join(a,this.sanitizedUsername),zit(this.userConfigPath,{recursive:!0});let o=mm.join(this.userConfigPath,yfe);if(!Uit(o)){console.log(`[USER_SERVICE] Creating default config for user '${this.sanitizedUsername}' at ${o}`);let c={...Yie,version:1,username:t};Mn(o,c)}console.log(`[USER_SERVICE] Loading config for '${this.sanitizedUsername}' from ${o}`);let s=ta(o);if(!s)throw console.log(`[USER_SERVICE] ERROR: Failed to read user config at ${o}`),Error(`Could not read user config for username ${this.sanitizedUsername}`);this.config=fh(s,u2e),this.config!==s&&(console.log(`[USER_SERVICE] Config migrated for '${this.sanitizedUsername}' to version ${this.config?.version}`),Mn(o,this.config),this.interactor.displayText(`User configuration migrated to version ${this.config?.version}`))}userConfigPath;sanitizedUsername;config;maskingService=new W2;resolveProjectName(e){let t=e.lastIndexOf("__");return t!==-1?e.substring(0,t):e}save(){if(this.config){let e=mm.join(this.userConfigPath,yfe);Mn(e,this.config)}else console.error("No user configuration available to save.")}setProjectIntegration(e,t){let n=this.resolveProjectName(e);this.config.projects??={},this.config.projects[n]??={integration:{}},this.config.projects[n].integration={...this.config.projects[n].integration,...t},this.save()}setBio(e){this.config.bio=e?.trim()||void 0,this.save()}getBio(){return this.config.bio}setProjectBio(e,t){let n=this.resolveProjectName(e);this.config.projects??={},this.config.projects[n]??={integration:{}},this.config.projects[n].bio=t?.trim()||void 0,this.save()}getProjectBio(e){return this.config.projects?.[this.resolveProjectName(e)]?.bio}getCombinedBio(e){let t=this.getBio(),n=e?this.getProjectBio(e):void 0;return t&&n?`${t}
|
|
864
|
+
`;return this.interactor.displayText(m),n}};var KS=class extends Zn{constructor(e,t){super({commandWord:"mcp",description:"Configure MCP (Model Context Protocol) servers"},e);let n=new GS(e,t.mcp);this.handlers=[new VS(e,t.mcp),n,new ZS(e,t.mcp,n),new JS(e,t.mcp)]}};import*as Va from"node:path";import*as vfe from"node:os";import{existsSync as YS,mkdirSync as gfe,readdirSync as xM,unlinkSync as Lit,writeFileSync as qit}from"fs";var XS=class r{codayConfigDir;projectService;constructor(e,t){let n=Va.join(vfe.userInfo().homedir,".coday");this.codayConfigDir=e??n,this.projectService=t}getProjectPath(e){if(this.projectService)return this.projectService.getProject(e)?.config.path}async getOrCreateAgentsDir(e,t){let n;if(t==="project")n=Va.join(this.codayConfigDir,"projects",e,"agents");else{let i=this.getProjectPath(e);if(!i)throw new Error("Project path not configured, cannot access colocated agents");let a=await d2({text:"coday.yaml",root:i});if(a.length===0)throw new Error(`coday.yaml not found in project path: ${i}`);let o=Va.dirname(a[0]);n=Va.join(i,o,"agents")}return YS(n)||(gfe(n,{recursive:!0}),console.log(`[AGENT_CRUD] Created agents directory: ${n}`)),n}findAgentFile(e,t){if(!YS(e))return null;let n=t.toLowerCase(),a=xM(e).filter(o=>o.endsWith(".yml")||o.endsWith(".yaml")).find(o=>o.replace(/\.ya?ml$/,"").toLowerCase()===n);return a?Va.join(e,a):null}async findAgentAcrossLocations(e,t){let n=Va.join(this.codayConfigDir,"projects",e,"agents"),i=this.findAgentFile(n,t);if(i)return{location:"project",filePath:i};if(this.projectService)try{let a=await this.getOrCreateAgentsDir(e,"colocated"),o=this.findAgentFile(a,t);if(o)return{location:"colocated",filePath:o}}catch{}return null}static RESERVED_NAMES=new Set(["editable","documents"]);validateAgentName(e){if(!e||typeof e!="string")throw new Error("Agent name is required");if(!/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(e))throw new Error("Agent name must start with alphanumeric and contain only letters, digits, hyphens or underscores");if(r.RESERVED_NAMES.has(e.toLowerCase()))throw new Error(`Agent name '${e}' is reserved and cannot be used`)}async list(e){let t=[],n=["project"];this.projectService&&n.push("colocated");for(let i of n)try{let a=await this.getOrCreateAgentsDir(e,i);if(!YS(a))continue;let o=xM(a).filter(s=>s.endsWith(".yml")||s.endsWith(".yaml"));for(let s of o){let c=s.replace(/\.ya?ml$/,""),u=Va.join(a,s),l=ta(u);l&&t.push({name:l.name??c,description:l.description??"",source:i,editable:!0})}}catch(a){console.log(`[AGENT_CRUD] Could not access ${i} agents for ${e}:`,a)}return t.sort((i,a)=>i.name.toLowerCase().localeCompare(a.name.toLowerCase()))}async get(e,t){let n=await this.findAgentAcrossLocations(e,t);if(!n)return null;let i=ta(n.filePath);return i?{definition:i,source:n.location,filePath:n.filePath,editable:!0}:null}async create(e,t,n){if(this.validateAgentName(t.name),!t.description)throw new Error("Agent description is required");let i=await this.findAgentAcrossLocations(e,t.name);if(i)throw new Error(`Agent '${t.name}' already exists in ${i.location} location`);let a=await this.getOrCreateAgentsDir(e,n),o=Va.join(a,`${t.name}.yml`);return Mn(o,t),console.log(`[AGENT_CRUD] Created agent '${t.name}' in ${n} for project ${e}`),{definition:t,source:n,filePath:o,editable:!0}}async update(e,t,n){let i=await this.findAgentAcrossLocations(e,t);if(!i)return null;if(n.description!==void 0&&!n.description)throw new Error("Agent description cannot be empty");let a=ta(i.filePath);if(!a)return null;let o={name:a.name,description:n.description??a.description,instructions:n.instructions,aiProvider:n.aiProvider,modelName:n.modelName,temperature:n.temperature,maxOutputTokens:n.maxOutputTokens,openaiAssistantId:n.openaiAssistantId,integrations:n.integrations,mandatoryDocs:n.mandatoryDocs??a.mandatoryDocs,optionalDocs:n.optionalDocs??a.optionalDocs};return Object.keys(o).forEach(s=>{o[s]===void 0&&delete o[s]}),Mn(i.filePath,o),console.log(`[AGENT_CRUD] Updated agent '${t}' in ${i.location} for project ${e}`),{definition:o,source:i.location,filePath:i.filePath,editable:!0}}async getOrCreateDocumentsDir(e,t){let n=await this.getOrCreateAgentsDir(e,t),i=Va.join(n,"documents");return YS(i)||gfe(i,{recursive:!0}),i}async listDocuments(e,t){try{let n=await this.getOrCreateDocumentsDir(e,t);return xM(n).filter(i=>!i.startsWith(".")).sort()}catch{return[]}}async saveDocument(e,t,n,i){if(i.length>10485760)throw new Error(`File too large: ${(i.length/1024/1024).toFixed(2)} MB exceeds maximum of ${10485760/1024/1024} MB`);if(!Rx(n))throw new Error(`File type not allowed for: ${n}`);let a=Va.basename(n);if(!a||a!==n)throw new Error("Invalid filename");let o=await this.getOrCreateDocumentsDir(e,t),s=Va.join(o,a);return qit(s,i),console.log(`[AGENT_CRUD] Saved document '${a}' in ${t} for project ${e}`),`documents/${a}`}async delete(e,t){let n=await this.findAgentAcrossLocations(e,t);return n?(Lit(n.filePath),console.log(`[AGENT_CRUD] Deleted agent '${t}' from ${n.location} for project ${e}`),!0):!1}};var QS=class{constructor(e,t){this.userService=e;this.projectService=t}providerCache=new Map;mergedConfig=null;initialize(e){this.providerCache.clear(),this.mergedConfig=null,this.providerCache.set("coday",e.project.ai||[]),this.providerCache.set("project",this.projectService.selectedProject?.config?.ai||[]),this.providerCache.set("user",this.userService.config.ai||[])}getProviders(e){return this.providerCache.get(e)||[]}getProvider(e,t){return Ri.validate(t),this.getProviders(t).find(i=>i.name===e)}async saveProvider(e,t){Ri.validate(t);let n=this.getProviders(t),i=n.findIndex(a=>a.name===e.name);i>=0?n[i]=e:n.push(e),await this.saveProviders(n,t),this.mergedConfig=null}async deleteProvider(e,t){Ri.validate(t);let n=this.getProviders(t),i=n.filter(a=>a.name!==e);i.length!==n.length&&(await this.saveProviders(i,t),this.mergedConfig=null)}getModel(e,t,n){return Ri.validate(n),this.getProvider(e,n)?.models?.find(a=>a.name===t||a.alias===t)}async saveModel(e,t,n){Ri.validate(n);let i=this.getProvider(e,n);i||(i={name:e,models:[]},await this.saveProvider(i,n));let a=i.models||[],o=a.findIndex(s=>s.name===t.name||t.alias&&s.alias===t.alias);o>=0?a[o]=t:a.push(t),i.models=a,await this.saveProvider(i,n),this.mergedConfig=null}async deleteModel(e,t,n){Ri.validate(n);let i=this.getProvider(e,n);if(i?.models){let a=i.models.filter(o=>o.name!==t&&o.alias!==t);a.length!==i.models.length&&(i.models=a,await this.saveProvider(i,n),this.mergedConfig=null)}}getMergedConfiguration(){if(this.mergedConfig)return this.mergedConfig;let e=[],t=new Map;for(let n of["coday","project","user"]){let i=this.providerCache.get(n)||[];for(let a of i){let o=e.findIndex(s=>s.name===a.name);if(o>=0){let s=e[o];if(e[o]={...s,...a},a.models?.length){let c=s.models||[];for(let u of a.models){let l=c.findIndex(f=>f.name===u.name||u.alias&&f.alias===u.alias);l>=0?c[l]={...c[l],...u,price:{...c[l]?.price,...u.price}}:c.push(u),u.alias&&t.set(u.alias,{provider:a.name,model:u.name})}e[o].models=c}}else e.push({...a}),a.models?.forEach(s=>{s.alias&&t.set(s.alias,{provider:a.name,model:s.name})})}}return this.mergedConfig={providers:e,modelAliasMap:t},this.mergedConfig}resolveModelAlias(e){return this.getMergedConfiguration().modelAliasMap.get(e)}async saveProviders(e,t){switch(t){case"project":if(!this.projectService.selectedProject)throw new Error("No project selected");let n={...this.projectService.selectedProject.config,ai:e};this.projectService.save(n),this.providerCache.set(t,e);break;case"user":this.userService.config.ai=e,this.userService.save(),this.providerCache.set(t,e);break}}};var W2=class{MASK_PATTERN="****";SENSITIVE_FIELD_NAMES=["apikey","api_key","password","token","secret","auth","client_id"];isSensitiveField(e){let t=e.toLowerCase();return this.SENSITIVE_FIELD_NAMES.some(n=>t.includes(n))}maskValue(e){if(!e||e.length===0)return e;if(e.length<=8)return this.MASK_PATTERN;if(e.length<12){let i=e.substring(0,2),a=e.substring(e.length-2);return`${i}${this.MASK_PATTERN}${a}`}let t=e.substring(0,4),n=e.substring(e.length-4);return`${t}${this.MASK_PATTERN}${n}`}isMasked(e){return typeof e=="string"&&e.includes(this.MASK_PATTERN)}maskConfig(e){if(e==null||typeof e!="object")return e;if(Array.isArray(e))return e.map(n=>this.maskConfig(n));let t={};for(let[n,i]of Object.entries(e))this.isSensitiveField(n)&&typeof i=="string"?t[n]=this.maskValue(i):n==="env"&&typeof i=="object"&&i!==null&&!Array.isArray(i)?t[n]=this.maskEnvObject(i):typeof i=="object"&&i!==null?t[n]=this.maskConfig(i):t[n]=i;return t}maskEnvObject(e){let t={};for(let[n,i]of Object.entries(e))typeof i=="string"?t[n]=this.maskValue(i):t[n]=i;return t}unmaskConfig(e,t){if(e==null||t==null||typeof e!="object")return e;if(Array.isArray(e))return e.map((o,s)=>{let c=Array.isArray(t)?t[s]:void 0;return this.unmaskConfig(o,c)});let n={},i=e,a=t;for(let[o,s]of Object.entries(i)){let c=a[o];this.isSensitiveField(o)&&typeof s=="string"?this.isMasked(s)?n[o]=c:n[o]=s:o==="env"&&typeof s=="object"&&s!==null&&!Array.isArray(s)?n[o]=this.unmaskEnvObject(s,c):typeof s=="object"&&s!==null?n[o]=this.unmaskConfig(s,c):n[o]=s}if(!Array.isArray(e))for(let[o,s]of Object.entries(a))o in i||(n[o]=s);return n}unmaskEnvObject(e,t){if(!t||typeof t!="object")return e;let n={};for(let[i,a]of Object.entries(e))typeof a=="string"&&this.isMasked(a)?n[i]=t[i]:n[i]=a;for(let[i,a]of Object.entries(t))i in e||(n[i]=a);return n}};import*as mm from"node:path";import{existsSync as Uit,mkdirSync as zit}from"fs";import*as bfe from"node:os";var Bit="users",yfe="user.yaml",V2=class{constructor(e,t,n){this.username=t;this.interactor=n;this.sanitizedUsername=k6(t);let i=mm.join(bfe.userInfo().homedir,".coday"),a=mm.join(e??i,Bit);this.userConfigPath=mm.join(a,this.sanitizedUsername),zit(this.userConfigPath,{recursive:!0});let o=mm.join(this.userConfigPath,yfe);if(!Uit(o)){console.log(`[USER_SERVICE] Creating default config for user '${this.sanitizedUsername}' at ${o}`);let c={...Yie,version:1,username:t};Mn(o,c)}console.log(`[USER_SERVICE] Loading config for '${this.sanitizedUsername}' from ${o}`);let s=ta(o);if(!s)throw console.log(`[USER_SERVICE] ERROR: Failed to read user config at ${o}`),Error(`Could not read user config for username ${this.sanitizedUsername}`);this.config=fh(s,u2e),(this.config!==s||!this.config.username)&&(this.config!==s&&(console.log(`[USER_SERVICE] Config migrated for '${this.sanitizedUsername}' to version ${this.config?.version}`),this.interactor.displayText(`User configuration migrated to version ${this.config?.version}`)),this.config.username||(console.log(`[USER_SERVICE] Backfilling username for existing user '${this.sanitizedUsername}'`),this.interactor.displayText("User configuration updated: username backfilled"),this.config.username=t),Mn(o,this.config))}userConfigPath;sanitizedUsername;config;maskingService=new W2;resolveProjectName(e){let t=e.lastIndexOf("__");return t!==-1?e.substring(0,t):e}save(){if(this.config){let e=mm.join(this.userConfigPath,yfe);Mn(e,this.config)}else console.error("No user configuration available to save.")}setProjectIntegration(e,t){let n=this.resolveProjectName(e);this.config.projects??={},this.config.projects[n]??={integration:{}},this.config.projects[n].integration={...this.config.projects[n].integration,...t},this.save()}setBio(e){this.config.bio=e?.trim()||void 0,this.save()}getBio(){return this.config.bio}setProjectBio(e,t){let n=this.resolveProjectName(e);this.config.projects??={},this.config.projects[n]??={integration:{}},this.config.projects[n].bio=t?.trim()||void 0,this.save()}getProjectBio(e){return this.config.projects?.[this.resolveProjectName(e)]?.bio}getCombinedBio(e){let t=this.getBio(),n=e?this.getProjectBio(e):void 0;return t&&n?`${t}
|
|
865
865
|
|
|
866
866
|
Project context: ${n}`:n??t}getUserData(e){return{username:this.username,bio:this.getCombinedBio(e)}}getConfigForClient(){return this.maskingService.maskConfig(this.config)}updateConfigFromClient(e){this.config=this.maskingService.unmaskConfig(e,this.config),this.save()}};var eE=class{constructor(e,t){this.configDir=e;this.interactor=t}userServices=new Map;getUserService(e){let t=k6(e),n=this.userServices.get(t);return n||(n=new V2(this.configDir,e,this.interactor),this.userServices.set(t,n)),n}clearUserService(e){let t=k6(e);this.userServices.delete(t)}clearAll(){this.userServices.clear()}};var xfe={description:"Dummy description of the project, refer to docs for proper use.",mandatoryDocs:[],optionalDocs:[],scripts:{example:{description:"Dummy description of the example script so that the LLM can get a grasp of what it does (so to understand when to use it), refer to docs for proper use.",command:'echo "example script run with great success"',parametersDescription:"Dummy description of parameters, refer to docs for proper use."}}};var wfe="********",gm=class{constructor(e,t,n){this.userService=e;this.projectService=t;this.interactor=n}getIntegrations(e){if(Ri.validate(e),e==="coday")throw new Error("CODAY level not supported for integrations");let t={};if(e==="project"){let n=this.projectService.selectedProject;if(!n)return{};t=n.config.integration||{}}else if(e==="user"){let n=this.projectService.selectedProject;if(!n)return{};t=(this.userService.config.projects||{})[this.userService.resolveProjectName(n.name)]?.integration||{}}return this.maskApiKeys(t)}async saveIntegration(e,t,n){if(Ri.validate(n),n==="coday")throw new Error("CODAY level not supported for integrations");if(n==="project"){let i=this.projectService.selectedProject;if(!i)throw new Error("No project selected");let o={...i.config.integration||{},[e]:t};this.projectService.save({integration:o})}else if(n==="user"){let i=this.projectService.selectedProject;if(!i)throw new Error("No project selected");this.userService.setProjectIntegration(i.name,{[e]:t})}this.interactor.debug(`Integration '${e}' saved at ${n.toLowerCase()} level`)}async deleteIntegration(e,t){if(Ri.validate(t),t==="coday")throw new Error("CODAY level not supported for integrations");if(t==="project"){let n=this.projectService.selectedProject;if(!n)throw new Error("No project selected");let i=n.config.integration||{};if(!i[e])throw new Error(`Integration '${e}' not found at project level`);let a={...i};delete a[e],this.projectService.save({integration:a})}else if(t==="user"){let n=this.projectService.selectedProject;if(!n)throw new Error("No project selected");let i=this.userService.resolveProjectName(n.name),o=(this.userService.config.projects||{})[i]?.integration||{};if(!o[e])throw new Error(`Integration '${e}' not found at user level`);let s={...o};delete s[e],this.userService.config.projects||(this.userService.config.projects={}),this.userService.config.projects[i]||(this.userService.config.projects[i]={integration:{}}),this.userService.config.projects[i].integration=s,this.userService.save()}this.interactor.debug(`Integration '${e}' deleted from ${t.toLowerCase()} level`)}getMergedIntegrations(){let e=this.projectService.selectedProject;if(!e)return{};let t=e.config.integration||{},i=(this.userService.config.projects||{})[this.userService.resolveProjectName(e.name)]?.integration||{},a={...t};return Object.keys(i).forEach(o=>{let s=i[o],c=a[o];c?a[o]={...c,...s}:a[o]=s}),this.maskApiKeys(a)}maskApiKeys(e){let t={};return Object.keys(e).forEach(n=>{let i=e[n];t[n]={...i,...i.apiKey&&{apiKey:wfe}}}),t}isApiKeyMasked(e){return e===wfe}getUnmaskedIntegrationsAtLevel(e){if(Ri.validate(e),e==="coday")throw new Error("CODAY level not supported for integrations");if(e==="project"){let i=this.projectService.selectedProject;return i?{...i.config.integration??{}}:{}}let t=this.projectService.selectedProject;return t?{...(this.userService.config.projects??{})[this.userService.resolveProjectName(t.name)]?.integration??{}}:{}}getUnmaskedIntegration(e,t){if(Ri.validate(t),t==="coday")throw new Error("CODAY level not supported for integrations");if(t==="project"){let n=this.projectService.selectedProject;return n?(n.config.integration||{})[e]:void 0}else if(t==="user"){let n=this.projectService.selectedProject;return n?((this.userService.config.projects||{})[this.userService.resolveProjectName(n.name)]?.integration||{})[e]:void 0}}};var Hit="_API_KEY",vm=class{constructor(e,t,n){this.projectService=e;this.userService=t;this.interactor=n;e.selectedProject$.subscribe(i=>{if(!i){this.projectIntegrations={},this.userIntegrations={},this.integrations={};return}this.projectIntegrations=i.config.integration||{},this.userIntegrations=i.name&&this.userService.config.projects?this.userService.config.projects[this.userService.resolveProjectName(i.name)]?.integration||{}:{},this.integrations={...this.projectIntegrations},Object.keys(this.userIntegrations).forEach(a=>{let o=this.userIntegrations[a],s=this.integrations[a];if(!s)this.integrations[a]=o;else{let c={...s,...o};if(s.oauth2&&o.oauth2&&(c.oauth2={...s.oauth2,...o.oauth2}),s.http&&o.http){let u=s.http,l=o.http;if(c.http={...u,...l},u.endpoints?.length){let f=l.endpoints??[],p=new Map(f.map(d=>[d.name,d]));c.http.endpoints=[...u.endpoints.map(d=>({...d,...p.get(d.name)??{}})),...f.filter(d=>!u.endpoints.find(m=>m.name===d.name))]}}this.integrations[a]=c}})})}integrations={};projectIntegrations={};userIntegrations={};hasIntegration(e){let t=Fx[e];return t?t.length?t.some(n=>this.hasIntegration(n)):Object.keys(this.integrations).includes(e):!1}getIntegration(e){return this.integrations[e]}getApiKey(e){if(!tp.includes(e))return;let t=process.env[`${e}${Hit}`];return t?(this.interactor?.displayText(`Using environment variable for ${e} API key`),t):this.integrations[e]?.apiKey}setIntegration(e,t){this.integrations[e]=t,this.projectService.save({integration:this.integrations})}getApiUrl(e){return this.integrations[e]?.apiUrl}getUsername(e){return this.integrations[e]?.username}};var _fe=ur(Tc(),1);import{existsSync as Wit,readFileSync as Vit}from"fs";import*as Sfe from"node:path";var ym="coday.yaml",tE=async(r,e,t)=>{let n=await d2({text:ym,root:r}),i=null,a;if(n.length>1)throw console.log(`[LOAD_PROJECT_DESC] ERROR: Multiple ${ym} files found in ${r}`),new Error(`Multiple files found for ${ym}. Please ensure there is only one file with this name.`);n.length===1&&(i=Sfe.join(r,n[0]));try{if(i&&Wit(i)){let o=Vit(i,"utf-8");a=_fe.parse(o),console.log(`[LOAD_PROJECT_DESC] Loaded ${ym}: ${a.agents?.length||0} agents, ${a.description?.length||0} chars desc`),e.displayText?.(`Project configuration used: ${i}`)}}finally{if(!a){let s=`No ${ym} found in project folder: ${r}. Using default configuration (not written to disk).`;console.warn(s),e.warn?.(s),a={...xfe}}a.description+=await t_(a,e,r,ym);let o=`
|
|
867
867
|
|