@whoz-oss/coday-server 0.118.1 → 0.118.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +3 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whoz-oss/coday-server",
3
- "version": "0.118.1",
3
+ "version": "0.118.2",
4
4
  "repository": "https://github.com/whoz-oss/coday",
5
5
  "type": "module",
6
6
  "main": "server/server.js",
package/server.js CHANGED
@@ -307,7 +307,7 @@ ${a}\r
307
307
 
308
308
  More details: https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md#removed-logprovider-and-loglevel-options
309
309
  `)),t}function vK(r){let e=r.logProvider&&r.logProvider();return e&&(r.logger=e),(0,I_t.getLogger)(r)}});var __e=k(bK=>{"use strict";Object.defineProperty(bK,"__esModule",{value:!0});bK.legacyCreateProxyMiddleware=N_t;var $_t=dK(),R_t=Ol(),j_t=x_e(),w_e=R_t.Debug.extend("legacy-create-proxy-middleware");function N_t(r,e){w_e("init");let t=(0,j_t.legacyOptionsAdapter)(r,e),n=(0,$_t.createProxyMiddleware)(t);return w_e("add marker for patching req.url (old behavior)"),n.__LEGACY_HTTP_PROXY_MIDDLEWARE__=!0,n}});var S_e=k(dI=>{"use strict";Object.defineProperty(dI,"__esModule",{value:!0});dI.legacyCreateProxyMiddleware=void 0;var F_t=__e();Object.defineProperty(dI,"legacyCreateProxyMiddleware",{enumerable:!0,get:function(){return F_t.legacyCreateProxyMiddleware}})});var k_e=k(C3=>{"use strict";var M_t=C3&&C3.__createBinding||(Object.create?(function(r,e,t,n){n===void 0&&(n=t);var i=Object.getOwnPropertyDescriptor(e,t);(!i||("get"in i?!e.__esModule:i.writable||i.configurable))&&(i={enumerable:!0,get:function(){return e[t]}}),Object.defineProperty(r,n,i)}):(function(r,e,t,n){n===void 0&&(n=t),r[n]=e[t]})),L_t=C3&&C3.__exportStar||function(r,e){for(var t in r)t!=="default"&&!Object.prototype.hasOwnProperty.call(e,t)&&M_t(e,r,t)};Object.defineProperty(C3,"__esModule",{value:!0});L_t(S_e(),C3)});var xK=k(xu=>{"use strict";var q_t=xu&&xu.__createBinding||(Object.create?(function(r,e,t,n){n===void 0&&(n=t);var i=Object.getOwnPropertyDescriptor(e,t);(!i||("get"in i?!e.__esModule:i.writable||i.configurable))&&(i={enumerable:!0,get:function(){return e[t]}}),Object.defineProperty(r,n,i)}):(function(r,e,t,n){n===void 0&&(n=t),r[n]=e[t]})),hI=xu&&xu.__exportStar||function(r,e){for(var t in r)t!=="default"&&!Object.prototype.hasOwnProperty.call(e,t)&&q_t(e,r,t)};Object.defineProperty(xu,"__esModule",{value:!0});hI(dK(),xu);hI(b_e(),xu);hI(qJ(),xu);hI(k_e(),xu)});var xI=lr(mne(),1);import Rl from"path";import mI from"fs";import*as _ye from"path";var Ne=class{commandWord;description;requiredIntegrations=[];isInternal=!1;constructor(e){this.commandWord=e.commandWord,this.description=e.description,this.requiredIntegrations=e.requiredIntegrations||[],this.isInternal=!!e?.isInternal}getSubCommand(e){return e.slice(this.commandWord.length).trim()}accept(e,t){return!!e&&e.toLowerCase().startsWith(this.commandWord)}};var goe=lr(wo(),1);function kj(r,e=80){if(r.length<=e)return r;try{if(r.trim().startsWith("{")||r.trim().startsWith("[")){let t=JSON.parse(r),n=JSON.stringify(t);return n.length<=e?n:n.substring(0,e)+`...(${n.length} chars)`}}catch{}return r.substring(0,e)+"..."}var ri=class{constructor(e,t){this.type=t;if(e.timestamp)this.timestamp=e.timestamp;else{let n=Math.random().toString(36).substring(2,7);this.timestamp=`${new Date().toISOString()}-${n}`}this.parentKey=e.parentKey,this.threadId=e.threadId,this.length=0}timestamp;parentKey;static type;length;threadId;get date(){let e=this.timestamp.lastIndexOf("-");if(e>0){let t=this.timestamp.substring(e+1);if(t.length===5&&/^[a-z0-9]+$/.test(t))return new Date(this.timestamp.substring(0,e))}return new Date(this.timestamp)}},ww=class extends ri{invite;constructor(e,t){super(e,t),this.invite=e.invite}buildAnswer(e){return new Sr({answer:e,parentKey:this.timestamp,invite:this.invite})}},H0=class r extends ri{static type="heartbeat";constructor(e){super(e,r.type)}},Fi=class r extends ww{defaultValue;static type="invite";constructor(e){super(e,r.type),this.defaultValue=e.defaultValue}},moe="InviteEventDefault",Sr=class r extends ri{answer;invite;name;static type="answer";constructor(e){super(e,r.type),this.answer=e.answer??"No answer",this.invite=e.invite,this.name=e.name}},ju=class r extends ri{speaker;text;static type="text";constructor(e){super(e,r.type),this.speaker=e.speaker,this.text=e.text}},m2=class r extends ri{chunk;static type="text_chunk";constructor(e){super(e,r.type),this.chunk=e.chunk,this.length=this.chunk.length}},W0=class r extends ri{warning;static type="warn";constructor(e){super(e,r.type),this.warning=e.warning}},Ha=class r extends ri{error;static type="error";constructor(e){super(e,r.type),this.error=e.error}},Mi=class r extends ww{options;optionalQuestion;allowFreeText;static type="choice";constructor(e){super(e,r.type),this.options=e.options,this.optionalQuestion=e.optionalQuestion,this.allowFreeText=e.allowFreeText??!1}},hn=class r extends ri{toolRequestId;name;args;static type="tool_request";constructor(e){super(e,r.type),this.toolRequestId=e.toolRequestId??this.timestamp,this.name=e.name,this.args=e.args,this.length=this.args.length+this.name.length+this.toolRequestId.length+20}buildResponse(e){return new Tn({output:e,toolRequestId:this.toolRequestId,parentKey:this.timestamp})}toSingleLineString(e=50){let t=kj(this.args,e);return`\u{1F527} ${this.name}(${t})`}},Tn=class r extends ri{toolRequestId;output;static type="tool_response";constructor(e){if(super(e,r.type),this.toolRequestId=e.toolRequestId||this.timestamp||new Date().toISOString(),this.output=e.output,typeof this.output=="string")this.length=this.output.length+this.toolRequestId.length+20;else if(this.output.type==="text")this.length=this.output.content.length+this.toolRequestId.length+20;else if(this.output.type==="image"){let t=(this.output.width??0)*(this.output.height??0)/750;this.length=(t?t*3.5:this.output.content.length)+this.toolRequestId.length+20}else this.length=this.toolRequestId.length+20}getTextOutput(){return typeof this.output=="string"?this.output:this.output.type==="text"?this.output.content:this.output.type==="image"?`[Image: ${this.output.mimeType}]`:""}toSingleLineString(e=50){let t=this.getTextOutput(),n=kj(t,e),i=typeof this.output!="string"&&this.output.type==="image"?" [image]":"";return`\u2B91 ${n}${i}`}},dp=class r extends ri{static type="thinking";static debounce=5e3;constructor(e){super(e,r.type)}},xa=class r extends ri{summary;static type="summary";constructor(e){super(e,r.type),this.summary=e.summary,this.length=this.summary.length}toSingleLineString(e=80){return`\u{1F4CB} Summary: ${kj(this.summary,e)}`}},jt=class r extends ri{role;name;content;static type="message";constructor(e){super(e,r.type),this.role=e.role,this.name=e.name,this.content=e.content,this.length=this.content.map(t=>{if(t.type==="text")return t.content.length;if(t.type==="image"){let n=(t.width||0)*(t.height||0)/750;return n?n*3.5:t.content.length}return 0}).reduce((t,n)=>t+n,0)}getTextContent(){return this.content.filter(e=>e.type==="text").map(e=>e.content).join(`
310
- `)}},Tc=class r extends ri{threadId;name;summary;users;static type="thread_update";constructor(e){super(e,r.type),this.threadId=e.threadId,this.name=e.name,this.summary=e.summary,this.users=e.users}},Pc=class r extends ri{filename;operation;size;mimeType;static type="file";constructor(e){super(e,r.type),this.filename=e.filename,this.operation=e.operation,this.size=e.size,this.mimeType=e.mimeType}toSingleLineString(){let e=this.operation==="created"?"\u{1F4C4}":this.operation==="updated"?"\u{1F4DD}":"\u{1F5D1}\uFE0F",t=this.size?` (${(this.size/1024).toFixed(1)} KB)`:"";return`${e} ${this.operation}: ${this.filename}${t}`}},Ic=class r extends ri{authUrl;state;integrationName;static type="oauth_request";constructor(e){super(e,r.type),this.authUrl=e.authUrl,this.state=e.state,this.integrationName=e.integrationName}},_o=class r extends ri{subThreadId;agentName;static type="delegation";constructor(e){super(e,r.type),this.subThreadId=e.subThreadId,this.agentName=e.agentName}},_w=class r extends ri{code;state;integrationName;error;errorDescription;static type="oauth_callback";constructor(e){super(e,r.type),this.code=e.code,this.state=e.state,this.integrationName=e.integrationName,this.error=e.error,this.errorDescription=e.errorDescription}},tKe={[jt.type]:jt,[Sr.type]:Sr,[Mi.type]:Mi,[_o.type]:_o,[Ha.type]:Ha,[H0.type]:H0,[Fi.type]:Fi,[hn.type]:hn,[Tn.type]:Tn,[ju.type]:ju,[m2.type]:m2,[dp.type]:dp,[W0.type]:W0,[Tc.type]:Tc,[xa.type]:xa,[Pc.type]:Pc,[Ic.type]:Ic,[_w.type]:_w};function Sw(r){let e=tKe[r.type];return e?new e(r):void 0}var kw=class{constructor(e,t,n,i=!1){this.aiClient=t;this.tools=n;this.internal=i;this.name=e.name,this.description=e.description,this.definition={...e}}name;description;definition;get systemInstructions(){return this.definition.instructions}getAiClient(){return this.aiClient}async run(e,t,n){let i=e.trim(),a=new Sr({answer:i,name:n??t.username});t.addAnswerEvent(a);let o=await this.aiClient.run(this,t),s=new goe.ReplaySubject;return o.subscribe(s),s.asObservable()}};var Ew={name:"Coday",description:"Default fallback agent with neutral character and access to all tools",instructions:`
310
+ `)}},Tc=class r extends ri{threadId;name;summary;users;static type="thread_update";constructor(e){super(e,r.type),this.threadId=e.threadId,this.name=e.name,this.summary=e.summary,this.users=e.users}},Pc=class r extends ri{filename;operation;size;mimeType;static type="file";constructor(e){super(e,r.type),this.filename=e.filename,this.operation=e.operation,this.size=e.size,this.mimeType=e.mimeType}toSingleLineString(){let e=this.operation==="created"?"\u{1F4C4}":this.operation==="updated"?"\u{1F4DD}":"\u{1F5D1}\uFE0F",t=this.size?` (${(this.size/1024).toFixed(1)} KB)`:"";return`${e} ${this.operation}: ${this.filename}${t}`}},Ic=class r extends ri{authUrl;state;integrationName;static type="oauth_request";constructor(e){super(e,r.type),this.authUrl=e.authUrl,this.state=e.state,this.integrationName=e.integrationName}},_o=class r extends ri{subThreadId;agentName;static type="delegation";constructor(e){super(e,r.type),this.subThreadId=e.subThreadId,this.agentName=e.agentName}},_w=class r extends ri{code;state;integrationName;error;errorDescription;static type="oauth_callback";constructor(e){super(e,r.type),this.code=e.code,this.state=e.state,this.integrationName=e.integrationName,this.error=e.error,this.errorDescription=e.errorDescription}},tKe={[jt.type]:jt,[Sr.type]:Sr,[Mi.type]:Mi,[_o.type]:_o,[Ha.type]:Ha,[H0.type]:H0,[Fi.type]:Fi,[hn.type]:hn,[Tn.type]:Tn,[ju.type]:ju,[m2.type]:m2,[dp.type]:dp,[W0.type]:W0,[Tc.type]:Tc,[xa.type]:xa,[Pc.type]:Pc,[Ic.type]:Ic,[_w.type]:_w};function Sw(r){let e=tKe[r.type];return e?new e(r):void 0}var kw=class{constructor(e,t,n,i=!1){this.aiClient=t;this.tools=n;this.internal=i;this.name=e.name,this.description=e.description,this.definition={...e}}name;description;definition;get systemInstructions(){return this.definition.instructions}getAiClient(){return this.aiClient}async run(e,t,n){if(!t)throw new Error(`[Agent:${this.name}] Cannot run: thread context is undefined. Ensure initThread() completed before agent execution.`);let i=e.trim(),a=new Sr({answer:i,name:n??t.username});t.addAnswerEvent(a);let o=await this.aiClient.run(this,t),s=new goe.ReplaySubject;return o.subscribe(s),s.asObservable()}};var Ew={name:"Coday",description:"Default fallback agent with neutral character and access to all tools",instructions:`
311
311
  You are Coday, an AI assistant designed for interactive usage by users through various chat-like interfaces.
312
312
 
313
313
  When other agents are available, you should redirect the user request to the appropriate agent, given the topic.
@@ -877,7 +877,7 @@ Are you sure you want to delete this MCP server configuration?
877
877
 
878
878
  Here are the information collected during previous chats:
879
879
  `),n.join(`
880
- `)):""}loadMemoriesFrom(e){this.memories=[],this.userMemoriesPath=this.readMemories(this.userMemoriesPath)?this.userMemoriesPath:void 0;let t=e?.configPath?Jk.join(e.configPath,EL):void 0;this.projectMemoriesPath=this.readMemories(t)?t:void 0,e&&this.checkInit()}readMemories(e){if(!e)return!1;try{if(!jot(e)){let n=Ype.stringify({memories:[]});Not(e,n)}let t=oa(e);return t?(this.memories.push(...t.memories),!0):!1}catch{return!1}}checkInit(){if(!this.userMemoriesPath||!this.projectMemoriesPath)throw new Error("user or project path not set for memory service")}saveMemories(){this.checkInit();let e=this.memories.filter(n=>n.level==="USER"),t=this.memories.filter(n=>n.level==="PROJECT");Un(this.userMemoriesPath,{memories:e}),Un(this.projectMemoriesPath,{memories:t})}};import*as ede from"crypto";import*as No from"node:fs/promises";import*as jo from"path";import{exec as Qpe}from"child_process";var zm=class r{constructor(e,t,n){this.repository=e;this.defaultProject=t;this.isForcedMode=n}maskingService=new af;listProjects(){let e=this.repository.listProjects();return this.isForcedMode&&this.defaultProject?e.filter(t=>t===this.defaultProject).map(t=>{let n=this.repository.getConfig(t);return{name:t,volatile:n?.volatile}}):e.map(t=>{let n=this.repository.getConfig(t);return{name:t,volatile:n?.volatile}})}getDefaultProject(){return this.defaultProject||null}getForcedMode(){return this.isForcedMode}getProject(e){this.checkAgainstForced(e);let t=this.repository.getConfig(e);if(t)return{name:e,config:t};if(!this.isForcedMode&&this.defaultProject){let n=process.cwd(),i=r.generateProjectId(n),a=jo.basename(n);if(e===a||e===i||e===this.defaultProject){console.log(`[PROJECT_SERVICE] Creating volatile project for '${e}' at ${n}`);let o=this.getOrCreateVolatileProject(n);if(t=this.repository.getConfig(o),t)return{name:o,config:t}}}return null}exists(e){return this.checkAgainstForced(e),this.repository.exists(e)}createProject(e,t){if(this.checkAgainstForced(e),!e||!t)throw new Error("Project name and path are required");if(!this.repository.createProject(e,t))throw new Error(`Project '${e}' already exists`)}updateProjectConfig(e,t){if(this.checkAgainstForced(e),!this.repository.exists(e))throw new Error(`Project '${e}' does not exist`);this.repository.saveConfig(e,t)}async deleteProject(e,t){if(this.checkAgainstForced(e),e.includes("__"))t?.removeGitWorktree&&await this.removeGitWorktree(e),await this.unregisterWorktreeProject(e);else if(!this.repository.deleteProject(e))throw new Error(`Project '${e}' does not exist`)}async removeGitWorktree(e){let t=e.lastIndexOf("__");if(t===-1)return;let n=e.substring(0,t),i=this.repository.getConfig(n);if(!i?.path){console.warn(`[PROJECT_SERVICE] Cannot remove git worktree: parent project '${n}' config not found`);return}let a=i.path,o=jo.dirname(a),s=jo.join(o,e);try{await No.access(s)}catch{console.warn(`[PROJECT_SERVICE] Worktree path does not exist, skipping git removal: ${s}`);return}Qpe(`git worktree remove "${s}" --force`,{cwd:a},c=>{if(c){console.error(`[PROJECT_SERVICE] Failed to remove git worktree: ${c.message}`);return}console.log(`[PROJECT_SERVICE] Removed git worktree: ${s}`),Qpe("git worktree prune",{cwd:a},u=>{u&&console.warn(`[PROJECT_SERVICE] git worktree prune failed: ${u.message}`)})})}getProjectConfigForClient(e){this.checkAgainstForced(e);let t=this.repository.getConfig(e);return t?this.maskingService.maskConfig(t):null}updateProjectConfigFromClient(e,t){this.checkAgainstForced(e);let n=this.repository.getConfig(e);if(!n)throw new Error(`Project '${e}' does not exist`);let i=this.maskingService.unmaskConfig(t,n);this.repository.saveConfig(e,i)}checkAgainstForced(e){if(this.isForcedMode&&this.defaultProject&&this.defaultProject!==e)throw Error(`Project selection outside of ${this.defaultProject} not allowed`)}getOrCreateVolatileProject(e){let t=r.generateProjectId(e);if(this.repository.exists(t))return t;this.repository.createProject(t,e);let n=this.repository.getConfig(t);return n&&(n.volatile=!0,n.createdAt=Date.now(),this.repository.saveConfig(t,n)),t}async registerWorktreeProject(e,t,n){let i=this.repository.getConfig(n),a=i?{...i,path:t,volatile:void 0,createdAt:void 0}:{version:1,path:t,integration:{},storage:{type:"file"},agents:[]};this.repository.createProject(e,t),this.repository.saveConfig(e,a);let o=this.repository.getProjectInfo(n);if(o){let s=this.repository.getProjectInfo(e);if(s)for(let c of["agents","prompts","schedulers","memories"]){let u=jo.join(o.configPath,c),l=jo.join(s.configPath,c);try{await No.access(u),await No.symlink(u,l)}catch{}}}}async unregisterWorktreeProject(e){let t=this.repository.getProjectInfo(e);if(!t)return;let n=e.lastIndexOf("__");if(n!==-1){let i=e.substring(0,n),a=this.repository.getProjectInfo(i);a&&await this.migrateThreadsToParent(t.configPath,a.configPath)}this.repository.deleteProject(e)}async migrateThreadsToParent(e,t){let n=jo.join(e,"threads"),i=jo.join(t,"threads");try{await No.access(n)}catch{return}await No.mkdir(i,{recursive:!0});let a=await No.readdir(n);for(let o of a){let s=jo.join(n,o),c=jo.join(i,o);try{await No.access(c)}catch{await No.rename(s,c)}}}static generateProjectId(e){let t=jo.basename(e),n=ede.createHash("sha256").update(e).digest("hex").substring(0,8);return`${t}_${n}`}};var nde=lr(wo(),1);import*as Bm from"node:path";import*as rde from"node:os";import{mkdirSync as Fot}from"fs";var Mot="projects",tde="project.yaml",Hm=class{constructor(e,t,n){this.interactor=e;this.projectService=t;let i=Bm.join(rde.userInfo().homedir,".coday");this.projectsConfigPath=Bm.join(n??i,Mot),Fot(this.projectsConfigPath,{recursive:!0}),this.projects=this.projectService.listProjects().map(a=>a.name)}projectsConfigPath;maskingService=new af;projects;selectedProjectBehaviorSubject=new nde.BehaviorSubject(null);selectedProject$=this.selectedProjectBehaviorSubject.asObservable();selectProject(e){let t=Bm.join(this.projectsConfigPath,e),n=Bm.join(t,tde),i=this.projectService.getProject(e)?.config;if(!i?.path){console.log(`[PROJECT_STATE_SERVICE] ERROR: No project path in config for '${e}'`),this.interactor.error("Invalid selection, project path needed \u{1F622}.");return}let o={name:e,config:i,configPath:t};console.log(`[PROJECT_STATE_SERVICE] Selected '${e}' \u2192 ${i.path}`),this.updateSelectedProject(o),this.interactor.displayText(`Project local configuration used: ${n}`)}updateSelectedProject(e){this.selectedProjectBehaviorSubject.next(e)}get selectedProject(){return this.selectedProjectBehaviorSubject.value}save(e){let t=this.selectedProjectBehaviorSubject.value;if(!t){this.interactor.error("No current project selected, save not possible");return}let n={...t.config,...e};Un(Bm.join(t.configPath,tde),n),t.config=n,this.updateSelectedProject(t)}getConfigForClient(){let e=this.selectedProjectBehaviorSubject.value;return e?this.maskingService.maskConfig(e.config):null}updateConfigFromClient(e){let t=this.selectedProjectBehaviorSubject.value;if(!t){this.interactor.error("No current project selected, update not possible");return}let n=this.maskingService.unmaskConfig(e,t.config);this.save(n)}};import*as al from"node:path";import*as ode from"node:os";import{randomUUID as qot}from"node:crypto";import{existsSync as sf,mkdirSync as Uot,readdirSync as ade,unlinkSync as zot}from"fs";import*as CL from"node:path";import*as ide from"node:os";function Lot(r){return r.replace(/[^a-zA-Z0-9]/g,"_")}function Wm(r,e){try{let t=CL.join(ide.userInfo().homedir,".coday"),n=Lot(r),i=CL.join(e??t,"users",n,"user.yaml"),a=oa(i);return a?a.groups?.includes("CODAY_ADMIN")??!1:!1}catch{return!1}}var Kk=class{codayConfigDir;projectService;nativeHandlerStubs=[];constructor(e,t){let n=al.join(ode.userInfo().homedir,".coday");this.codayConfigDir=e??n,this.projectService=t}getProjectPath(e){if(this.projectService)return this.projectService.getProject(e)?.config.path}async getOrCreatePromptsDir(e,t){let n;if(t==="local")n=al.join(this.codayConfigDir,"projects",e,"prompts");else{let i=this.getProjectPath(e);if(!i)throw new Error("Project path not configured, cannot access project prompts");let a=await C2({text:"coday.yaml",root:i});if(a.length===0)throw new Error(`coday.yaml not found in project path: ${i}`);let o=al.dirname(a[0]);n=al.join(i,o,"prompts")}return sf(n)||(Uot(n,{recursive:!0}),console.log(`[PROMPT] Created prompts directory: ${n}`)),n}async getOrCreatePromptFilePath(e,t,n){let i=await this.getOrCreatePromptsDir(e,n);return al.join(i,`${t}.yml`)}async findPromptSource(e,t){let n=await this.getOrCreatePromptFilePath(e,t,"local");if(sf(n))return"local";if(this.projectService)try{let i=await this.getOrCreatePromptFilePath(e,t,"project");if(sf(i))return"project"}catch{}return null}async findProjectForPrompt(e){let t=al.join(this.codayConfigDir,"projects");if(!sf(t))return null;let n=ade(t,{withFileTypes:!0}).filter(i=>i.isDirectory()).map(i=>i.name);for(let i of n){let a=al.join(this.codayConfigDir,"projects",i,"prompts",`${e}.yml`);if(sf(a))return i;if(this.projectService)try{let o=await this.getOrCreatePromptFilePath(i,e,"project");if(sf(o))return i}catch{}}return null}validatePlaceholders(e){let t=/\{\{(\w+)\}\}/g,n=[],i=/^[A-Za-z][A-Za-z0-9-]*$/;if(e.forEach(a=>{let o;for(;(o=t.exec(a))!==null;){let s=o[1];s&&s!=="PARAMETERS"&&!i.test(s)&&n.push(s)}}),n.length>0)throw new Error(`Invalid parameter keys: ${n.join(", ")}. Keys must start with a letter and contain only letters, digits, and hyphens.`)}async create(e,t,n="local"){try{this.validatePlaceholders(t.commands);let i=qot(),a={...t,id:i,source:n,createdAt:new Date().toISOString(),parameterFormat:this.getParameterFormat(t.commands)},o=await this.getOrCreatePromptFilePath(e,i,n);if(sf(o))throw new Error(`Prompt with ID ${i} already exists`);return Un(o,a),console.log(`[PROMPT] Created prompt ${i} in ${n} for project ${e}`),a}catch(i){throw new Error(`Failed to create prompt: ${i instanceof Error?i.message:"Unknown error"}`)}}async get(e,t){try{let n=await this.findPromptSource(e,t);if(!n)return null;let i=await this.getOrCreatePromptFilePath(e,t,n),a=oa(i);return a?(a.source||(a.source=n),a):null}catch(n){return console.error(`Failed to get prompt ${t}:`,n),null}}async getById(e){try{let t=await this.findProjectForPrompt(e);if(!t)return null;let n=await this.get(t,e);return n?{prompt:n,projectName:t}:null}catch(t){return console.error(`Failed to get prompt ${e}:`,t),null}}async update(e,t,n,i){try{let a=await this.get(e,t);if(!a)return null;if(n.webhookEnabled!==void 0&&n.webhookEnabled!==a.webhookEnabled&&!Wm(i,this.codayConfigDir))throw new Error("Only CODAY_ADMIN can enable/disable webhook for prompts");let{id:o,createdAt:s,source:c,...u}=n;n.commands&&this.validatePlaceholders(n.commands);let l={...a,...u,updatedAt:new Date().toISOString()};n.commands&&(l.parameterFormat=this.getParameterFormat(n.commands));let f=await this.getOrCreatePromptFilePath(e,t,a.source);return Un(f,l),console.log(`[PROMPT] Updated prompt ${t} (${a.source}) by user ${i}`),l}catch(a){throw console.error(`Failed to update prompt ${t}:`,a),a}}async delete(e,t){try{let n=await this.findPromptSource(e,t);if(!n)return!1;let i=await this.getOrCreatePromptFilePath(e,t,n);return zot(i),console.log(`[PROMPT] Deleted prompt ${t} from ${n}`),!0}catch(n){return console.error(`Failed to delete prompt ${t}:`,n),!1}}getParameterFormat(e){if(e.some(a=>/\{\{PARAMETERS\}\}/.test(a)))return"";let n=/\{\{(\w+)\}\}/g,i=new Set;return e.forEach(a=>{let o;for(;(o=n.exec(a))!==null;){let s=o[1];s&&s!=="PARAMETERS"&&i.add(s)}}),i.size===0?"":Array.from(i).map(a=>`${a}=""`).join(" ")}registerNativeHandler(e){this.nativeHandlerStubs.find(t=>t.id===e.id)||this.nativeHandlerStubs.push(e)}async list(e,t=[]){try{let n=[],i=["local"];this.projectService&&i.push("project");for(let a of i)try{let o=await this.getOrCreatePromptsDir(e,a);if(!sf(o))continue;let c=ade(o).filter(u=>u.endsWith(".yml"));for(let u of c){let l=u.replace(".yml",""),f=await this.get(e,l);f&&n.push({id:f.id,name:f.name,description:f.description,webhookEnabled:f.webhookEnabled,createdBy:f.createdBy,createdAt:f.createdAt,updatedAt:f.updatedAt,source:f.source||a,parameterFormat:f.parameterFormat})}}catch(o){console.log(`[PROMPT] Could not access ${a} prompts for ${e}:`,o)}return n.push(...V0),n.push(...this.nativeHandlerStubs),n.push(...t),n.sort((a,o)=>new Date(o.createdAt).getTime()-new Date(a.createdAt).getTime())}catch(n){return console.error(`Failed to list prompts for project ${e}:`,n),[]}}async enableWebhook(e,t,n){return this.update(e,t,{webhookEnabled:!0},n)}async disableWebhook(e,t,n){return this.update(e,t,{webhookEnabled:!1},n)}};var sde=lr(wo(),1),Yk=class{constructor(e){this.promptService=e}threadCodayManager;threadService;codayOptions;logger;initialize(e,t,n,i){this.threadCodayManager=e,this.threadService=t,this.codayOptions=n,this.logger=i}processCommands(e,t){let n;if(typeof t=="string"){let a=e.some(s=>/\{\{PARAMETERS\}\}/.test(s));if(e.some(s=>/\{\{(?!PARAMETERS\}\})\w+\}\}/.test(s)))throw new Error("Prompt contains structured placeholders ({{key}}). Use an object parameter instead of a string.");a?n=e.map(s=>s.replace(/\{\{PARAMETERS\}\}/g,t)):n=e.map((s,c)=>c===0?`${s} ${t}`.trim():s)}else typeof t=="object"&&t!==null?n=e.map(a=>{let o=a;return Object.entries(t).forEach(([s,c])=>{let u=`{{${s}}}`;o=o.replaceAll(u,String(c))}),o}):n=[...e];let i=new Set;if(n.forEach(a=>{let o=a.match(/\{\{(\w+)\}\}/g);o&&o.forEach(s=>i.add(s))}),i.size>0){let a=Array.from(i).map(o=>o.replace(/[{}]/g,"")).join(", ");throw new Error(`Missing required parameters: ${a}`)}return n}async executePrompt(e,t,n,i,a){if(!this.threadCodayManager||!this.threadService||!this.codayOptions||!this.logger)throw new Error("PromptExecutionService not initialized. Call initialize() first.");let{title:o,awaitFinalAnswer:s=!1,projectName:c}=a||{},u,l;if(c){if(l=c,u=await this.promptService.get(l,e),!u)throw new Error(`Prompt ${e} not found in project ${l}`)}else{let y=await this.promptService.getById(e);if(!y)throw new Error(`Prompt not found: ${e}`);u=y.prompt,l=y.projectName}if(i==="webhook"&&!u.webhookEnabled)throw new Error(`Prompt ${e} is not enabled for webhook execution`);if(!u.commands||u.commands.length===0)throw new Error("Prompt has no commands configured");let f=this.processCommands(u.commands,t);if(!n)throw new Error("Username is required");let d=(await this.threadService.createThread(l,n,o)).id;console.log(`[PROMPT_EXEC] Created new thread: ${d} for ${i} execution`);let m={...this.codayOptions,oneshot:!0,project:l,thread:d,prompts:f};console.log(`[PROMPT_EXEC] Creating instance for ${i} execution with ${f.length} prompts:`,f);let h=this.threadCodayManager.createWithoutConnection(d,l,n,m);h.prepareCoday();let g=h.coday.interactor,v={project:l,title:o??"Untitled",username:n,clientId:d,promptCount:f.length,awaitFinalAnswer:!!s,promptName:u.name,promptId:u.id,executionMode:i};if(i==="webhook"?this.logger.logWebhook(v):this.logger.logWebhook({...v,webhookName:u.name,webhookUuid:u.id}),s){let y=[],x=g.events.pipe((0,sde.filter)(_=>(console.log(`[PROMPT_EXEC] Received event type: ${_.type}, role: ${_ instanceof jt?_.role:"N/A"}`),_ instanceof jt&&_.role==="assistant"&&!!_.name))).subscribe(_=>{y.push(_)});try{await h.coday.run(),x.unsubscribe();let _=y[y.length-1];return await this.threadCodayManager.cleanup(d),{threadId:d,lastEvent:_}}catch(_){x.unsubscribe();let S=_ instanceof Error?_.message:"Unknown error";throw this.logger.logWebhookError({error:`Prompt execution failed: ${S}`,username:n,project:l,clientId:d}),console.error("[PROMPT_EXEC] Error waiting for prompt completion:",_),await this.threadCodayManager.cleanup(d),_}}else return h.coday.run().catch(y=>{console.error("[PROMPT_EXEC] Error during prompt Coday run:",y)}),setTimeout(()=>{this.threadCodayManager.cleanup(d).catch(y=>{console.error("[PROMPT_EXEC] Error cleaning up prompt thread after timeout:",y)})},300*1e3),{threadId:d}}};var Tg=lr(zc(),1);import*as ui from"fs";import*as Vm from"path";import{randomUUID as Bot}from"node:crypto";var Xk=class{constructor(e,t,n){this.logger=e;this.promptService=t;this.codayConfigDir=n}schedulers=new Map;checkInterval;CHECK_INTERVAL_MS=3e4;promptExecutionService;initializeExecution(e){this.promptExecutionService=e}async initialize(){console.log("[SCHEDULER] Initializing SchedulerService..."),await this.loadAllSchedulers(),this.startScheduler(),console.log(`[SCHEDULER] SchedulerService initialized with ${this.schedulers.size} schedulers`)}stop(){this.checkInterval&&(clearInterval(this.checkInterval),this.checkInterval=void 0,console.log("[SCHEDULER] SchedulerService stopped"))}async loadAllSchedulers(){this.schedulers.clear();let e=Vm.join(this.codayConfigDir,"projects");if(!ui.existsSync(e))return;let t=ui.readdirSync(e,{withFileTypes:!0}).filter(n=>n.isDirectory()).map(n=>n.name);for(let n of t)try{let i=await this.loadProjectSchedulers(n);for(let a of i)this.schedulers.set(a.id,a)}catch(i){console.error(`[SCHEDULER] Failed to load schedulers for project ${n}:`,i)}}async loadProjectSchedulers(e){let t=this.getSchedulersDir(e);if(!ui.existsSync(t))return[];let n=ui.readdirSync(t),i=[];for(let a of n)if(a.endsWith(".yml"))try{let o=Vm.join(t,a),s=ui.readFileSync(o,"utf-8"),c=Tg.parse(s),u=this.calculateNextRunSkippingMissed(c),l=u.occurrenceCount!==c.occurrenceCount;c.nextRun=u.nextRun,c.occurrenceCount=u.occurrenceCount,l&&await this.saveScheduler(c,e),i.push(c)}catch(o){console.error(`[SCHEDULER] Failed to load scheduler from ${a}:`,o)}return i}startScheduler(){this.checkInterval=setInterval(()=>{this.checkAndExecuteSchedulers()},this.CHECK_INTERVAL_MS),this.checkAndExecuteSchedulers()}async checkAndExecuteSchedulers(){for(let e of this.schedulers.values())e.enabled&&Bue(e.schedule,e.nextRun??null,e.occurrenceCount??0)&&this.executeScheduler(e).catch(t=>{console.error(`[SCHEDULER] Failed to execute scheduler ${e.id}:`,t)})}async executeSchedulerInternal(e,t,n){if(!this.promptExecutionService)throw new Error("PromptExecutionService not initialized");console.log(`[SCHEDULER] Executing scheduler "${e.name}" (${e.id}) [${n}]`);let i=e.parameters;e.parameters&&typeof e.parameters=="object"&&Object.keys(e.parameters).length===1&&"PARAMETERS"in e.parameters&&(i=String(e.parameters.PARAMETERS));let a=await this.promptExecutionService.executePrompt(e.promptId,i,e.createdBy,"scheduled",{title:n==="scheduled"?`Scheduled: ${e.name}`:`Manual: ${e.name}`,awaitFinalAnswer:!1,projectName:t});return console.log(`[SCHEDULER] Scheduler "${e.name}" executed successfully. Thread: ${a.threadId}`),a.threadId}async executeScheduler(e){let t=new Date().toISOString();console.log(`[SCHEDULER] Executing scheduler "${e.name}" (${e.id})`);let n=this.findProjectForScheduler(e.id);if(!n){console.error(`[SCHEDULER] Cannot find project for scheduler ${e.id}, skipping execution`);return}let i,a,o;e.lastRun=t,e.occurrenceCount=(e.occurrenceCount??0)+1,e.nextRun=Oh(e.schedule,new Date,e.occurrenceCount);try{await this.saveScheduler(e,n),console.log(`[SCHEDULER] Next execution for "${e.name}": ${e.nextRun}`),this.schedulers.set(e.id,e),a=await this.executeSchedulerInternal(e,n,"scheduled"),i=!0}catch(s){i=!1,o=s instanceof Error?s.message:String(s),console.error(`[SCHEDULER] Scheduler "${e.name}" failed:`,s)}this.logger.logTriggerExecution({triggerId:e.id,triggerName:e.name,webhookUuid:e.promptId,projectName:n,success:i,threadId:a,error:o})}validateSchedule(e){return zue(e)}calculateNextRunSkippingMissed(e){let t=new Date,n=e.occurrenceCount??0,i=e.nextRun;if(!i)return{nextRun:Oh(e.schedule,t,n),occurrenceCount:n};if(new Date(i)>=t)return{nextRun:i,occurrenceCount:n};let a=1e3,o=0,s=0;for(;o<a;){if(n++,s++,i=Oh(e.schedule,t,n),!i)return s>0&&console.log(`[SCHEDULER] Scheduler "${e.name}" (${e.id}) expired after skipping ${s} missed occurrence(s)`),{nextRun:null,occurrenceCount:n};if(new Date(i)>=t)return s>0&&console.log(`[SCHEDULER] Scheduler "${e.name}" (${e.id}) skipped ${s} missed occurrence(s), next run: ${i}`),{nextRun:i,occurrenceCount:n};o++}return console.warn(`[SCHEDULER] Could not find future nextRun for scheduler ${e.id} after ${a} iterations`),{nextRun:null,occurrenceCount:n}}getSchedulersDir(e){return Vm.join(this.codayConfigDir,"projects",e,"schedulers")}getSchedulerFilePath(e,t){return Vm.join(this.getSchedulersDir(e),`${t}.yml`)}findProjectForScheduler(e){let t=Vm.join(this.codayConfigDir,"projects");if(!ui.existsSync(t))return null;let n=ui.readdirSync(t,{withFileTypes:!0}).filter(i=>i.isDirectory()).map(i=>i.name);for(let i of n){let a=this.getSchedulerFilePath(i,e);if(ui.existsSync(a))return i}return null}canAccessScheduler(e,t){return e.createdBy===t?!0:Wm(t,this.codayConfigDir)}async listSchedulers(e,t){return(await this.loadProjectSchedulers(e)).filter(i=>this.canAccessScheduler(i,t)).map(i=>({id:i.id,name:i.name,enabled:i.enabled,promptId:i.promptId,schedule:i.schedule,parameters:i.parameters,lastRun:i.lastRun,nextRun:i.nextRun,createdBy:i.createdBy}))}async getScheduler(e,t,n){let i=this.getSchedulerFilePath(e,t);if(!ui.existsSync(i))return null;try{let a=ui.readFileSync(i,"utf-8"),o=Tg.parse(a),s=this.calculateNextRunSkippingMissed(o);return o.nextRun=s.nextRun,o.occurrenceCount=s.occurrenceCount,n&&!this.canAccessScheduler(o,n)?(console.log(`[SCHEDULER] Access denied for user ${n} to scheduler ${t}`),null):o}catch(a){return console.error(`[SCHEDULER] Failed to load scheduler ${t}:`,a),null}}async createScheduler(e,t,n){let i=this.validateSchedule(t.schedule);if(!i.valid)throw new Error(`Invalid schedule: ${i.error}`);if(!await this.promptService.getById(t.promptId))throw new Error(`Prompt not found: ${t.promptId}`);let o={id:Bot(),name:t.name,enabled:t.enabled??!0,promptId:t.promptId,schedule:t.schedule,parameters:t.parameters,createdBy:n,createdAt:new Date().toISOString(),nextRun:Oh(t.schedule,new Date,0),occurrenceCount:0};return await this.saveScheduler(o,e),this.schedulers.set(o.id,o),console.log(`[SCHEDULER] Created scheduler "${o.name}" (${o.id}) for project ${e}`),o}async updateScheduler(e,t,n,i){let a=await this.getScheduler(e,t,i);if(!a)throw new Error(`Scheduler not found or access denied: ${t}`);if(console.log(`[SCHEDULER] Updating scheduler ${t} by user ${i}`),n.name!==void 0&&(a.name=n.name),n.enabled!==void 0&&(a.enabled=n.enabled),n.parameters!==void 0&&(a.parameters=n.parameters),n.promptId!==void 0){if(!await this.promptService.getById(n.promptId))throw new Error(`Prompt not found: ${n.promptId}`);a.promptId=n.promptId}if(n.schedule!==void 0){let o=this.validateSchedule(n.schedule);if(!o.valid)throw new Error(`Invalid schedule: ${o.error}`);a.schedule=n.schedule,a.occurrenceCount=0,a.nextRun=Oh(n.schedule,new Date,0)}return await this.saveScheduler(a,e),this.schedulers.set(a.id,a),console.log(`[SCHEDULER] Updated scheduler "${a.name}" (${a.id})`),a}async deleteScheduler(e,t,n){if(!await this.getScheduler(e,t,n))return!1;let a=this.getSchedulerFilePath(e,t);return ui.unlinkSync(a),this.schedulers.delete(t),console.log(`[SCHEDULER] Deleted scheduler ${t} by user ${n}`),!0}async enableScheduler(e,t,n){return this.updateScheduler(e,t,{enabled:!0},n)}async disableScheduler(e,t,n){return this.updateScheduler(e,t,{enabled:!1},n)}async runSchedulerNow(e,t,n){let i=await this.getScheduler(e,t,n);if(!i)throw new Error(`Scheduler not found or access denied: ${t}`);let a=await this.executeSchedulerInternal(i,e,"manual");return i.lastRun=new Date().toISOString(),await this.saveScheduler(i,e),this.schedulers.set(i.id,i),this.logger.logTriggerExecution({triggerId:i.id,triggerName:i.name,webhookUuid:i.promptId,projectName:e,success:!0,threadId:a}),a}async saveScheduler(e,t){if(!t&&(t=this.findProjectForScheduler(e.id),!t))throw new Error(`Cannot find project for scheduler ${e.id}`);let n=this.getSchedulersDir(t);ui.mkdirSync(n,{recursive:!0});let i=this.getSchedulerFilePath(t,e.id),a=Tg.stringify(e);ui.writeFileSync(i,a,"utf-8")}};import*as fs from"node:path";import*as ude from"node:os";import{existsSync as cde,lstatSync as Hot,mkdirSync as AL,readdirSync as Wot,renameSync as Vot}from"fs";var Qk=class r{projectsConfigPath;static PROJECT_FILENAME="project.yaml";constructor(e){let t=fs.join(ude.userInfo().homedir,".coday");this.projectsConfigPath=fs.join(e??t,"projects"),AL(this.projectsConfigPath,{recursive:!0})}listProjects(){return Wot(this.projectsConfigPath).filter(t=>!t.startsWith(".")&&Hot(fs.join(this.projectsConfigPath,t)).isDirectory())}getProjectInfo(e){let t=fs.join(this.projectsConfigPath,e),n=fs.join(t,r.PROJECT_FILENAME);return cde(n)?{name:e,configPath:t}:null}exists(e){return this.getProjectInfo(e)!==null}getConfig(e){let t=this.getProjectInfo(e);if(!t)return console.log(`[PROJECT_REPO] No project info found for: '${e}'`),null;let n=fs.join(t.configPath,r.PROJECT_FILENAME),i=oa(n);if(!i)return console.log(`[PROJECT_REPO] Failed to load config for '${e}' from ${n}`),null;let a=Dh(i,Hue);return a!==i&&(console.log(`[PROJECT_REPO] Config migrated for '${e}', saving...`),Un(n,a)),a}saveConfig(e,t){let n=this.getProjectInfo(e);if(!n)throw new Error(`Project '${e}' does not exist`);let i=fs.join(n.configPath,r.PROJECT_FILENAME);Un(i,t)}createProject(e,t){let n=fs.join(this.projectsConfigPath,e),i=fs.join(n,r.PROJECT_FILENAME);return cde(i)?!1:(console.log(`[PROJECT_REPO] Creating project '${e}' with path: ${t}`),AL(n,{recursive:!0}),Un(i,{version:1,path:t,integration:{},storage:{type:"file"},agents:[]}),console.log(`[PROJECT_REPO] Project '${e}' created successfully`),!0)}deleteProject(e){let t=this.getProjectInfo(e);if(!t)return!1;let n=fs.join(this.projectsConfigPath,".deleted");AL(n,{recursive:!0});let i=new Date().toISOString().replace(/:/g,"-"),a=fs.join(n,`${e}__${i}`);return Vot(t.configPath,a),!0}};var TL=lr(zc(),1);import{promises as ol}from"fs";import ld from"path";var lde=async r=>{try{let e=await ol.readFile(r,"utf-8");return TL.default.parse(e)}catch{return null}},eE=class{constructor(e){this.projectsDir=e}getThreadsDir(e){return ld.join(this.projectsDir,e,"threads")}async ensureThreadsDir(e){let t=this.getThreadsDir(e);try{await ol.mkdir(t,{recursive:!0})}catch(n){throw new Nu(`Failed to initialize threads directory for project ${e}`,n)}}getThreadFileName(e){return`${e.id}.yml`}async findThreadFile(e,t){try{let n=this.getThreadsDir(e),i=`${t}.yml`;try{return await ol.access(ld.join(n,i)),i}catch{}return(await ol.readdir(n)).find(s=>s.endsWith(`-${t}.yml`))||null}catch(n){throw new Nu(`Error finding thread ${t} in project ${e}`,n)}}async getById(e,t){try{let n=await this.findThreadFile(e,t);if(!n)return null;let i=this.getThreadsDir(e),a=ld.join(i,n),o=await lde(a);if(!o)return null;let s=Dh(o,rF);return s.projectId||(s.projectId=e),s!==o&&Un(a,s),new Fu(s)}catch(n){throw new Nu(`Failed to read thread ${t} from project ${e}`,n)}}async save(e,t){await this.ensureThreadsDir(e);try{if(t.id||(t.id=crypto.randomUUID()),t.projectId||(t.projectId=e),t.projectId!==e)throw new Error(`Thread projectId mismatch: expected ${e}, got ${t.projectId}`);let n=this.getThreadsDir(e),i=this.getThreadFileName(t),a=ld.join(n,i),o=await this.findThreadFile(e,t.id);if(o&&o!==i){let u=ld.join(n,o);try{await ol.unlink(u),console.log(`[THREAD-REPO] Migrated/renamed thread file: ${o} \u2192 ${i}`)}catch(l){console.warn(`[THREAD-REPO] Could not delete old thread file: ${o}`,l)}}let s={...t.serialize(),version:rF.length+1},c=TL.default.stringify(s);return await ol.writeFile(a,c,"utf-8"),t}catch(n){throw new Nu(`Failed to save thread ${t.id} to project ${e}`,n)}}async listByProject(e){try{let t=this.getThreadsDir(e);try{await ol.access(t)}catch{return[]}let n=await ol.readdir(t);return(await Promise.all(n.filter(a=>a.endsWith(".yml")).map(async a=>{let o=await lde(ld.join(t,a));if(!o)return null;let s=o.projectId||e;return{id:o.id,username:o.username,projectId:s,name:o.name??"...",summary:o.summary??"",createdDate:o.createdDate??"",modifiedDate:o.modifiedDate??"",price:o.price??0,starring:o.starring??[],users:Array.isArray(o.users)?o.users.map(c=>typeof c=="string"?{userId:c}:c):o.username?[{userId:o.username}]:[],parentThreadId:o.parentThreadId,parentEventId:o.parentEventId,delegatedAgentName:o.delegatedAgentName,delegatedTask:o.delegatedTask}}))).filter(a=>!!a).sort((a,o)=>a.modifiedDate>o.modifiedDate?-1:1)}catch(t){throw new Nu(`Failed to list threads for project ${e}`,t)}}async delete(e,t){try{let n=await this.findThreadFile(e,t);if(!n)return!1;let i=this.getThreadsDir(e);return await ol.unlink(ld.join(i,n)),!0}catch(n){throw new Nu(`Failed to delete thread ${t} from project ${e}`,n)}}};var tE=class{constructor(e,t,n){this.projectRepository=e;this.projectsDir=t;this.threadFileService=n}repositoryCache=new Map;threadListCache=new Map;CACHE_TTL_MS=14400*1e3;loadingPromises=new Map;getThreadRepository(e){let t=this.repositoryCache.get(e);if(t)return t;if(!this.projectRepository.getProjectInfo(e))throw new Error(`Project '${e}' not found`);let i=new eE(this.projectsDir);return this.repositoryCache.set(e,i),i}clearCache(e){e?this.repositoryCache.delete(e):this.repositoryCache.clear()}async listThreads(e,t){let n=this.threadListCache.get(e);if(n&&Date.now()-n.timestamp<this.CACHE_TTL_MS)return n.data.filter(o=>on(o,t)).sort((o,s)=>o.modifiedDate>s.modifiedDate?-1:1);let i=this.loadingPromises.get(e);if(i)return await i,this.listThreads(e,t);let a=this.loadThreadListFromDisk(e);this.loadingPromises.set(e,a);try{return(await a).filter(s=>on(s,t)).sort((s,c)=>s.modifiedDate>c.modifiedDate?-1:1)}catch(o){throw this.threadListCache.delete(e),o}finally{this.loadingPromises.delete(e)}}async loadThreadListFromDisk(e){let n=await this.getThreadRepository(e).listByProject(e);return this.threadListCache.set(e,{data:n,timestamp:Date.now()}),n}toThreadSummary(e){return{id:e.id,username:e.username,projectId:e.projectId,name:e.name,summary:e.summary,createdDate:e.createdDate,modifiedDate:e.modifiedDate,price:e.price,starring:e.starring,users:e.users,parentThreadId:e.parentThreadId,parentEventId:e.parentEventId,delegatedAgentName:e.delegatedAgentName,delegatedTask:e.delegatedTask}}updateThreadInCache(e,t){let n=this.threadListCache.get(e);if(!n)return;let i=n.data.findIndex(a=>a.id===t.id);i!==-1?n.data[i]=t:n.data.push(t)}removeThreadFromCache(e,t){let n=this.threadListCache.get(e);n&&(n.data=n.data.filter(i=>i.id!==t))}async getThread(e,t){return await this.getThreadRepository(e).getById(e,t)}async createThread(e,t,n){let i=this.getThreadRepository(e),a=new Fu({id:crypto.randomUUID(),username:t,projectId:e,name:n||"",price:0}),o=await i.save(e,a);return this.updateThreadInCache(e,this.toThreadSummary(o)),o}async updateThread(e,t,n){let i=this.getThreadRepository(e),a=await i.getById(e,t);if(!a){let c=this.threadListCache.get(e)?.data.find(u=>u.id===t);if(c)a=new Fu({id:c.id,username:c.username,projectId:c.projectId,name:c.name,summary:c.summary,price:c.price,starring:c.starring,users:c.users,parentThreadId:c.parentThreadId,parentEventId:c.parentEventId,delegatedAgentName:c.delegatedAgentName,delegatedTask:c.delegatedTask});else throw new Error(`Thread '${t}' not found in project '${e}'`)}n.name!==void 0&&(a.name=n.name),n.summary!==void 0&&(a.summary=n.summary),n.users!==void 0&&(a.users=n.users);let o=await i.save(e,a);return this.updateThreadInCache(e,this.toThreadSummary(o)),o}async starThread(e,t,n){let i=this.getThreadRepository(e),a=await i.getById(e,t);if(!a)throw new Error(`Thread '${t}' not found in project '${e}'`);a.starring.includes(n)||a.starring.push(n);let o=await i.save(e,a);return this.updateThreadInCache(e,this.toThreadSummary(o)),o}async unstarThread(e,t,n){let i=this.getThreadRepository(e),a=await i.getById(e,t);if(!a)throw new Error(`Thread '${t}' not found in project '${e}'`);a.starring=a.starring.filter(s=>s!==n);let o=await i.save(e,a);return this.updateThreadInCache(e,this.toThreadSummary(o)),o}async deleteThread(e,t){let i=await this.getThreadRepository(e).delete(e,t);return i&&(await this.threadFileService.deleteThreadFiles(e,t),this.removeThreadFromCache(e,t)),i}async saveThread(e,t){let i=await this.getThreadRepository(e).save(e,t);return this.updateThreadInCache(e,this.toThreadSummary(i)),i}async listAllThreads(e){let t=this.threadListCache.get(e);if(t&&Date.now()-t.timestamp<this.CACHE_TTL_MS)return t.data.sort((a,o)=>a.modifiedDate>o.modifiedDate?-1:1);let n=this.loadingPromises.get(e);if(n)return await n,this.listAllThreads(e);let i=this.loadThreadListFromDisk(e);this.loadingPromises.set(e,i);try{return(await i).sort((o,s)=>o.modifiedDate>s.modifiedDate?-1:1)}catch(a){throw this.threadListCache.delete(e),a}finally{this.loadingPromises.delete(e)}}async exists(e,t){return await this.getThread(e,t)!==null}};var mde=lr(zc(),1);import*as Ca from"fs/promises";import*as Pg from"path";var fde=5,pde=24,dde=100,hde={SHORT_THREADS:7,LONG_THREADS:30},rE=class{constructor(e,t){this.projectsConfigPath=e;this.logger=t}cleanupTimer=null;initialTimer=null;isRunning=!1;async start(){if(this.isRunning){this.log("Thread cleanup service already running");return}this.isRunning=!0,this.log("Starting thread cleanup service with user message-based retention"),this.initialTimer=setTimeout(async()=>{await this.performCleanup(),this.cleanupTimer=setInterval(async()=>{await this.performCleanup()},pde*60*60*1e3),this.log(`Thread cleanup scheduled every ${pde} hours`)},fde*60*1e3),this.log(`Initial cleanup scheduled in ${fde} minutes`)}async stop(){this.initialTimer&&(clearTimeout(this.initialTimer),this.initialTimer=null),this.cleanupTimer&&(clearInterval(this.cleanupTimer),this.cleanupTimer=null),this.isRunning=!1,this.log("Thread cleanup service stopped (all timers cleared)")}async performCleanup(){let e=Date.now(),t=0,n=0,i=0;try{this.log("Starting thread cleanup...");let a=await Ca.readdir(this.projectsConfigPath);this.log(`Found ${a.length} projects to scan`);for(let s of a)try{let c=Pg.join(this.projectsConfigPath,s);if(!(await Ca.lstat(c)).isDirectory())continue;let l=Pg.join(c,"threads");try{await Ca.access(l)}catch{continue}let{scanned:f,deleted:p,errors:d}=await this.cleanupProjectThreads(s,l);t+=f,n+=p,i+=d}catch(c){this.logError(`Error processing project ${s}: ${c}`),i++}let o=Date.now()-e;this.log(`Cleanup completed: ${n}/${t} threads deleted across all projects in ${o}ms (${i} errors)`)}catch(a){let o=Date.now()-e;this.logError(`Cleanup failed after ${o}ms: ${a}`)}}async cleanupProjectThreads(e,t){let n=0,i=0,a=0;try{let s=(await Ca.readdir(t)).filter(c=>c.endsWith(".yml"));if(n=s.length,s.length===0)return{scanned:n,deleted:i,errors:a};this.log(`Scanning ${s.length} threads in project ${e}`);for(let c=0;c<s.length;c+=dde){let u=s.slice(c,c+dde),l=await this.processBatch(u,t,e);i+=l.deleted,a+=l.errors}i>0&&this.log(`Project ${e}: deleted ${i}/${n} expired threads`)}catch(o){this.logError(`Error scanning project ${e}: ${o}`),a++}return{scanned:n,deleted:i,errors:a}}async processBatch(e,t,n){let i=0,a=0;return await Promise.all(e.map(async o=>{let s=Pg.join(t,o),c;try{let u=await Ca.readFile(s,"utf-8");c=mde.parse(u)}catch(u){await Ca.unlink(s),this.logError(`Error processing file ${o} in project ${n}: ${u}`)}if(!(!c||!c.modifiedDate)&&!(c.starring&&Array.isArray(c.starring)&&c.starring.length>0)&&this.shouldDeleteThread(c)){let u=this.countUserMessages(c.messages||[]),l=this.getDaysSinceModified(c.modifiedDate),f=c.id||o.replace(".yml","");await Ca.unlink(s),await this.deleteThreadFiles(t,f),i++,this.logger.logThreadCleanup(n,o),console.log(`ThreadCleanup: Deleted thread ${f} and its files directory (${u} user messages, ${l} days old)`)}})),{deleted:i,errors:a}}shouldDeleteThread(e){if(!e||!e.modifiedDate)return!1;let n=this.countUserMessages(e.messages||[])<=3?hde.SHORT_THREADS:hde.LONG_THREADS;return this.getDaysSinceModified(e.modifiedDate)>n}countUserMessages(e){return e.filter(t=>t&&t.type==="message"&&t.role==="user").length}getDaysSinceModified(e){let t=new Date(e),i=new Date().getTime()-t.getTime();return Math.floor(i/(1e3*60*60*24))}async deleteThreadFiles(e,t){try{let n=Pg.join(e,`${t}-files`);try{await Ca.access(n),await Ca.rm(n,{recursive:!0,force:!0}),console.log(`ThreadCleanup: Deleted files directory ${n}`)}catch(i){if(i.code!=="ENOENT")throw i}}catch(n){console.error(`ThreadCleanup: Error deleting files for ${t}:`,n)}}log(e){let t=new Date().toISOString();console.log(`[${t}] ThreadCleanup: ${e}`)}logError(e){let t=new Date().toISOString();console.error(`[${t}] ThreadCleanup ERROR: ${e}`)}async forceCleanup(){this.log("Manual cleanup triggered"),await this.performCleanup()}};import*as Hi from"path";import*as fd from"fs";import*as Aa from"fs/promises";var nE=class{constructor(e){this.projectsDir=e}getThreadFilesDir(e,t){return Hi.join(this.projectsDir,e,"threads",`${t}-files`)}async ensureThreadFilesDir(e,t){let n=this.getThreadFilesDir(e,t);fd.existsSync(n)||await Aa.mkdir(n,{recursive:!0})}async listFiles(e,t){await this.ensureThreadFilesDir(e,t);let n=this.getThreadFilesDir(e,t),i=await Aa.readdir(n);return await Promise.all(i.map(async o=>{let s=Hi.join(n,o),c=await Aa.stat(s);return{filename:o,size:c.size,lastModified:c.mtime.toISOString()}}))}async saveFile(e,t,n,i){let a=this.getThreadFilesDir(e,t);await Aa.mkdir(a,{recursive:!0});let o=Hi.join(a,n);await Aa.writeFile(o,i)}async getFile(e,t,n){await this.ensureThreadFilesDir(e,t);let i=this.getThreadFilesDir(e,t),a=Hi.join(i,n),o=Hi.resolve(a),s=Hi.resolve(i);if(!o.startsWith(s))throw new Error("Access denied: invalid file path");if(!fd.existsSync(a))throw new Error(`File '${n}' not found`);return await Aa.readFile(a)}async getFilePath(e,t,n){await this.ensureThreadFilesDir(e,t);let i=this.getThreadFilesDir(e,t),a=Hi.join(i,n),o=Hi.resolve(a),s=Hi.resolve(i);if(!o.startsWith(s))throw new Error("Access denied: invalid file path");if(!fd.existsSync(a))throw new Error(`File '${n}' not found`);return a}fileExists(e,t,n){let i=this.getThreadFilesDir(e,t),a=Hi.join(i,n),o=Hi.resolve(a),s=Hi.resolve(i);return o.startsWith(s)?fd.existsSync(a):!1}async deleteFile(e,t,n){await this.ensureThreadFilesDir(e,t);let i=this.getThreadFilesDir(e,t),a=Hi.join(i,n),o=Hi.resolve(a),s=Hi.resolve(i);if(!o.startsWith(s))throw new Error("Access denied: invalid file path");if(!fd.existsSync(a))throw new Error(`File '${n}' not found`);await Aa.unlink(a)}async deleteThreadFiles(e,t){try{let n=this.getThreadFilesDir(e,t);fd.existsSync(n)&&(await Aa.rm(n,{recursive:!0,force:!0}),console.log(`Deleted thread files directory: ${n}`))}catch(n){console.error(`Error deleting thread files for ${t}:`,n)}}};var gde=lr(wo(),1);var iE=class{constructor(e,t,n,i){this.threadRepository=t;this.projectId=n;this.interactor=i;this.username=e.username}activeThread$=new gde.BehaviorSubject(null);isKilled=!1;activeThread=this.activeThread$.asObservable();username;async kill(){this.isKilled=!0,this.activeThread$.complete()}async create(e){let t=new Fu({id:"",username:this.username,name:e??"",price:0});return this.activeThread$.next(t),t}async select(e){let t=await this.threadRepository.getById(this.projectId,e);if(!t)throw new Error(`Thread ${e} not found`);return this.activeThread$.next(t),t}async save(e){let t=this.activeThread$.value;if(!t){console.error(`No thread existing when save attempt with name '${e}'`);return}e&&(t.name=e);let n=await this.threadRepository.save(this.projectId,t);this.activeThread$.next(n)}async autoSave(e){if(this.isKilled){console.log("Autosave skipped: service has been killed");return}let t=this.activeThread$.value;if(!t||t.messagesLength==0){console.log(`Autosave of an empty or falsy thread aborted, threadId: ${t?.id}, user: ${this.username}`);return}try{e&&(t.name=e),await this.threadRepository.save(this.projectId,t),this.interactor&&this.interactor.sendEvent(new Tc({threadId:t.id,name:t.name||void 0}))}catch(n){console.log("Autosave failed (service may have been killed):",n instanceof Error?n.message:n)}}async truncateAtUserMessage(e){let t=this.activeThread$.value;if(!t)return console.error("No active thread available for truncation"),!1;let n=t.truncateAtUserMessage(e);return n||this.interactor?.warn("Failed to truncate thread."),n}getCurrentThread(){return this.activeThread$.value}};async function vde(r,e){let t=e.project.selectedProject,n=e.user.getUserData(t.name),i=await Gk(t.config.path,r,n),a=new Z0({...i,root:t.config.path,name:t.name},e.user.username);return console.log(`[BUILD_CONTEXT] Context for '${a.project.name}' \u2192 root: ${a.project.root}, desc: ${a.project.description?.length||0} chars`),a}var aE=class extends Ne{constructor(t,n){super({commandWord:"select-project",description:"Select an existing project"});this.interactor=t;this.services=n}async handle(t,n){try{let i=this.getSubCommand(t);return await this.selectProject(i)??n}catch(i){return this.interactor.error(`Invalid project selection because: ${i.toString()}`),n}}async selectProject(t){return this.services.project.selectProject(t),this.services.project.selectedProject?vde(this.interactor,this.services):null}};var oE=class extends Ne{constructor(t,n,i){super({commandWord:"add",description:"Add a new integration configuration. User level is default, use --project/-p for project level."});this.interactor=t;this.service=n;this.editHandler=i}async handle(t,n){let a=!!Pt(this.getSubCommand(t),[{key:"project",alias:"p"}]).project,o=a?"project":"user",s=this.service.getMergedIntegrations(),c=Object.keys(s),u=hp.filter(h=>!c.includes(h));if(u.length===0)return this.interactor.displayText(`All available integrations (${hp.join(", ")}) are already configured.`),n;let l=await this.interactor.chooseOption(u.sort(),"Select integration to add:",`Available integrations to configure:
880
+ `)):""}loadMemoriesFrom(e){this.memories=[],this.userMemoriesPath=this.readMemories(this.userMemoriesPath)?this.userMemoriesPath:void 0;let t=e?.configPath?Jk.join(e.configPath,EL):void 0;this.projectMemoriesPath=this.readMemories(t)?t:void 0,e&&this.checkInit()}readMemories(e){if(!e)return!1;try{if(!jot(e)){let n=Ype.stringify({memories:[]});Not(e,n)}let t=oa(e);return t?(this.memories.push(...t.memories),!0):!1}catch{return!1}}checkInit(){if(!this.userMemoriesPath||!this.projectMemoriesPath)throw new Error("user or project path not set for memory service")}saveMemories(){this.checkInit();let e=this.memories.filter(n=>n.level==="USER"),t=this.memories.filter(n=>n.level==="PROJECT");Un(this.userMemoriesPath,{memories:e}),Un(this.projectMemoriesPath,{memories:t})}};import*as ede from"crypto";import*as No from"node:fs/promises";import*as jo from"path";import{exec as Qpe}from"child_process";var zm=class r{constructor(e,t,n){this.repository=e;this.defaultProject=t;this.isForcedMode=n}maskingService=new af;listProjects(){let e=this.repository.listProjects();return this.isForcedMode&&this.defaultProject?e.filter(t=>t===this.defaultProject).map(t=>{let n=this.repository.getConfig(t);return{name:t,volatile:n?.volatile}}):e.map(t=>{let n=this.repository.getConfig(t);return{name:t,volatile:n?.volatile}})}getDefaultProject(){return this.defaultProject||null}getForcedMode(){return this.isForcedMode}getProject(e){this.checkAgainstForced(e);let t=this.repository.getConfig(e);if(t)return{name:e,config:t};if(!this.isForcedMode&&this.defaultProject){let n=process.cwd(),i=r.generateProjectId(n),a=jo.basename(n);if(e===a||e===i||e===this.defaultProject){console.log(`[PROJECT_SERVICE] Creating volatile project for '${e}' at ${n}`);let o=this.getOrCreateVolatileProject(n);if(t=this.repository.getConfig(o),t)return{name:o,config:t}}}return null}exists(e){return this.checkAgainstForced(e),this.repository.exists(e)}createProject(e,t){if(this.checkAgainstForced(e),!e||!t)throw new Error("Project name and path are required");if(!this.repository.createProject(e,t))throw new Error(`Project '${e}' already exists`)}updateProjectConfig(e,t){if(this.checkAgainstForced(e),!this.repository.exists(e))throw new Error(`Project '${e}' does not exist`);this.repository.saveConfig(e,t)}async deleteProject(e,t){if(this.checkAgainstForced(e),e.includes("__"))t?.removeGitWorktree&&await this.removeGitWorktree(e),await this.unregisterWorktreeProject(e);else if(!this.repository.deleteProject(e))throw new Error(`Project '${e}' does not exist`)}async removeGitWorktree(e){let t=e.lastIndexOf("__");if(t===-1)return;let n=e.substring(0,t),i=this.repository.getConfig(n);if(!i?.path){console.warn(`[PROJECT_SERVICE] Cannot remove git worktree: parent project '${n}' config not found`);return}let a=i.path,o=jo.dirname(a),s=jo.join(o,e);try{await No.access(s)}catch{console.warn(`[PROJECT_SERVICE] Worktree path does not exist, skipping git removal: ${s}`);return}Qpe(`git worktree remove "${s}" --force`,{cwd:a},c=>{if(c){console.error(`[PROJECT_SERVICE] Failed to remove git worktree: ${c.message}`);return}console.log(`[PROJECT_SERVICE] Removed git worktree: ${s}`),Qpe("git worktree prune",{cwd:a},u=>{u&&console.warn(`[PROJECT_SERVICE] git worktree prune failed: ${u.message}`)})})}getProjectConfigForClient(e){this.checkAgainstForced(e);let t=this.repository.getConfig(e);return t?this.maskingService.maskConfig(t):null}updateProjectConfigFromClient(e,t){this.checkAgainstForced(e);let n=this.repository.getConfig(e);if(!n)throw new Error(`Project '${e}' does not exist`);let i=this.maskingService.unmaskConfig(t,n);this.repository.saveConfig(e,i)}checkAgainstForced(e){if(this.isForcedMode&&this.defaultProject&&this.defaultProject!==e)throw Error(`Project selection outside of ${this.defaultProject} not allowed`)}getOrCreateVolatileProject(e){let t=r.generateProjectId(e);if(this.repository.exists(t))return t;this.repository.createProject(t,e);let n=this.repository.getConfig(t);return n&&(n.volatile=!0,n.createdAt=Date.now(),this.repository.saveConfig(t,n)),t}async registerWorktreeProject(e,t,n){let i=this.repository.getConfig(n),a=i?{...i,path:t,volatile:void 0,createdAt:void 0}:{version:1,path:t,integration:{},storage:{type:"file"},agents:[]};this.repository.createProject(e,t),this.repository.saveConfig(e,a);let o=this.repository.getProjectInfo(n);if(o){let s=this.repository.getProjectInfo(e);if(s)for(let c of["agents","prompts","schedulers","memories"]){let u=jo.join(o.configPath,c),l=jo.join(s.configPath,c);try{await No.access(u),await No.symlink(u,l)}catch{}}}}async unregisterWorktreeProject(e){let t=this.repository.getProjectInfo(e);if(!t)return;let n=e.lastIndexOf("__");if(n!==-1){let i=e.substring(0,n),a=this.repository.getProjectInfo(i);a&&await this.migrateThreadsToParent(t.configPath,a.configPath)}this.repository.deleteProject(e)}async migrateThreadsToParent(e,t){let n=jo.join(e,"threads"),i=jo.join(t,"threads");try{await No.access(n)}catch{return}await No.mkdir(i,{recursive:!0});let a=await No.readdir(n);for(let o of a){let s=jo.join(n,o),c=jo.join(i,o);try{await No.access(c)}catch{await No.rename(s,c)}}}static generateProjectId(e){let t=jo.basename(e),n=ede.createHash("sha256").update(e).digest("hex").substring(0,8);return`${t}_${n}`}};var nde=lr(wo(),1);import*as Bm from"node:path";import*as rde from"node:os";import{mkdirSync as Fot}from"fs";var Mot="projects",tde="project.yaml",Hm=class{constructor(e,t,n){this.interactor=e;this.projectService=t;let i=Bm.join(rde.userInfo().homedir,".coday");this.projectsConfigPath=Bm.join(n??i,Mot),Fot(this.projectsConfigPath,{recursive:!0}),this.projects=this.projectService.listProjects().map(a=>a.name)}projectsConfigPath;maskingService=new af;projects;selectedProjectBehaviorSubject=new nde.BehaviorSubject(null);selectedProject$=this.selectedProjectBehaviorSubject.asObservable();selectProject(e){let t=Bm.join(this.projectsConfigPath,e),n=Bm.join(t,tde),i=this.projectService.getProject(e)?.config;if(!i?.path){console.log(`[PROJECT_STATE_SERVICE] ERROR: No project path in config for '${e}'`),this.interactor.error("Invalid selection, project path needed \u{1F622}.");return}let o={name:e,config:i,configPath:t};console.log(`[PROJECT_STATE_SERVICE] Selected '${e}' \u2192 ${i.path}`),this.updateSelectedProject(o),this.interactor.displayText(`Project local configuration used: ${n}`)}updateSelectedProject(e){this.selectedProjectBehaviorSubject.next(e)}get selectedProject(){return this.selectedProjectBehaviorSubject.value}save(e){let t=this.selectedProjectBehaviorSubject.value;if(!t){this.interactor.error("No current project selected, save not possible");return}let n={...t.config,...e};Un(Bm.join(t.configPath,tde),n),t.config=n,this.updateSelectedProject(t)}getConfigForClient(){let e=this.selectedProjectBehaviorSubject.value;return e?this.maskingService.maskConfig(e.config):null}updateConfigFromClient(e){let t=this.selectedProjectBehaviorSubject.value;if(!t){this.interactor.error("No current project selected, update not possible");return}let n=this.maskingService.unmaskConfig(e,t.config);this.save(n)}};import*as al from"node:path";import*as ode from"node:os";import{randomUUID as qot}from"node:crypto";import{existsSync as sf,mkdirSync as Uot,readdirSync as ade,unlinkSync as zot}from"fs";import*as CL from"node:path";import*as ide from"node:os";function Lot(r){return r.replace(/[^a-zA-Z0-9]/g,"_")}function Wm(r,e){try{let t=CL.join(ide.userInfo().homedir,".coday"),n=Lot(r),i=CL.join(e??t,"users",n,"user.yaml"),a=oa(i);return a?a.groups?.includes("CODAY_ADMIN")??!1:!1}catch{return!1}}var Kk=class{codayConfigDir;projectService;nativeHandlerStubs=[];constructor(e,t){let n=al.join(ode.userInfo().homedir,".coday");this.codayConfigDir=e??n,this.projectService=t}getProjectPath(e){if(this.projectService)return this.projectService.getProject(e)?.config.path}async getOrCreatePromptsDir(e,t){let n;if(t==="local")n=al.join(this.codayConfigDir,"projects",e,"prompts");else{let i=this.getProjectPath(e);if(!i)throw new Error("Project path not configured, cannot access project prompts");let a=await C2({text:"coday.yaml",root:i});if(a.length===0)throw new Error(`coday.yaml not found in project path: ${i}`);let o=al.dirname(a[0]);n=al.join(i,o,"prompts")}return sf(n)||(Uot(n,{recursive:!0}),console.log(`[PROMPT] Created prompts directory: ${n}`)),n}async getOrCreatePromptFilePath(e,t,n){let i=await this.getOrCreatePromptsDir(e,n);return al.join(i,`${t}.yml`)}async findPromptSource(e,t){let n=await this.getOrCreatePromptFilePath(e,t,"local");if(sf(n))return"local";if(this.projectService)try{let i=await this.getOrCreatePromptFilePath(e,t,"project");if(sf(i))return"project"}catch{}return null}async findProjectForPrompt(e){let t=al.join(this.codayConfigDir,"projects");if(!sf(t))return null;let n=ade(t,{withFileTypes:!0}).filter(i=>i.isDirectory()).map(i=>i.name);for(let i of n){let a=al.join(this.codayConfigDir,"projects",i,"prompts",`${e}.yml`);if(sf(a))return i;if(this.projectService)try{let o=await this.getOrCreatePromptFilePath(i,e,"project");if(sf(o))return i}catch{}}return null}validatePlaceholders(e){let t=/\{\{(\w+)\}\}/g,n=[],i=/^[A-Za-z][A-Za-z0-9-]*$/;if(e.forEach(a=>{let o;for(;(o=t.exec(a))!==null;){let s=o[1];s&&s!=="PARAMETERS"&&!i.test(s)&&n.push(s)}}),n.length>0)throw new Error(`Invalid parameter keys: ${n.join(", ")}. Keys must start with a letter and contain only letters, digits, and hyphens.`)}async create(e,t,n="local"){try{this.validatePlaceholders(t.commands);let i=qot(),a={...t,id:i,source:n,createdAt:new Date().toISOString(),parameterFormat:this.getParameterFormat(t.commands)},o=await this.getOrCreatePromptFilePath(e,i,n);if(sf(o))throw new Error(`Prompt with ID ${i} already exists`);return Un(o,a),console.log(`[PROMPT] Created prompt ${i} in ${n} for project ${e}`),a}catch(i){throw new Error(`Failed to create prompt: ${i instanceof Error?i.message:"Unknown error"}`)}}async get(e,t){try{let n=await this.findPromptSource(e,t);if(!n)return null;let i=await this.getOrCreatePromptFilePath(e,t,n),a=oa(i);return a?(a.source||(a.source=n),a):null}catch(n){return console.error(`Failed to get prompt ${t}:`,n),null}}async getById(e){try{let t=await this.findProjectForPrompt(e);if(!t)return null;let n=await this.get(t,e);return n?{prompt:n,projectName:t}:null}catch(t){return console.error(`Failed to get prompt ${e}:`,t),null}}async update(e,t,n,i){try{let a=await this.get(e,t);if(!a)return null;if(n.webhookEnabled!==void 0&&n.webhookEnabled!==a.webhookEnabled&&!Wm(i,this.codayConfigDir))throw new Error("Only CODAY_ADMIN can enable/disable webhook for prompts");let{id:o,createdAt:s,source:c,...u}=n;n.commands&&this.validatePlaceholders(n.commands);let l={...a,...u,updatedAt:new Date().toISOString()};n.commands&&(l.parameterFormat=this.getParameterFormat(n.commands));let f=await this.getOrCreatePromptFilePath(e,t,a.source);return Un(f,l),console.log(`[PROMPT] Updated prompt ${t} (${a.source}) by user ${i}`),l}catch(a){throw console.error(`Failed to update prompt ${t}:`,a),a}}async delete(e,t){try{let n=await this.findPromptSource(e,t);if(!n)return!1;let i=await this.getOrCreatePromptFilePath(e,t,n);return zot(i),console.log(`[PROMPT] Deleted prompt ${t} from ${n}`),!0}catch(n){return console.error(`Failed to delete prompt ${t}:`,n),!1}}getParameterFormat(e){if(e.some(a=>/\{\{PARAMETERS\}\}/.test(a)))return"";let n=/\{\{(\w+)\}\}/g,i=new Set;return e.forEach(a=>{let o;for(;(o=n.exec(a))!==null;){let s=o[1];s&&s!=="PARAMETERS"&&i.add(s)}}),i.size===0?"":Array.from(i).map(a=>`${a}=""`).join(" ")}registerNativeHandler(e){this.nativeHandlerStubs.find(t=>t.id===e.id)||this.nativeHandlerStubs.push(e)}async list(e,t=[]){try{let n=[],i=["local"];this.projectService&&i.push("project");for(let a of i)try{let o=await this.getOrCreatePromptsDir(e,a);if(!sf(o))continue;let c=ade(o).filter(u=>u.endsWith(".yml"));for(let u of c){let l=u.replace(".yml",""),f=await this.get(e,l);f&&n.push({id:f.id,name:f.name,description:f.description,webhookEnabled:f.webhookEnabled,createdBy:f.createdBy,createdAt:f.createdAt,updatedAt:f.updatedAt,source:f.source||a,parameterFormat:f.parameterFormat})}}catch(o){console.log(`[PROMPT] Could not access ${a} prompts for ${e}:`,o)}return n.push(...V0),n.push(...this.nativeHandlerStubs),n.push(...t),n.sort((a,o)=>new Date(o.createdAt).getTime()-new Date(a.createdAt).getTime())}catch(n){return console.error(`Failed to list prompts for project ${e}:`,n),[]}}async enableWebhook(e,t,n){return this.update(e,t,{webhookEnabled:!0},n)}async disableWebhook(e,t,n){return this.update(e,t,{webhookEnabled:!1},n)}};var sde=lr(wo(),1),Yk=class{constructor(e){this.promptService=e}threadCodayManager;threadService;codayOptions;logger;initialize(e,t,n,i){this.threadCodayManager=e,this.threadService=t,this.codayOptions=n,this.logger=i}processCommands(e,t){let n;if(typeof t=="string"){let a=e.some(s=>/\{\{PARAMETERS\}\}/.test(s));if(e.some(s=>/\{\{(?!PARAMETERS\}\})\w+\}\}/.test(s)))throw new Error("Prompt contains structured placeholders ({{key}}). Use an object parameter instead of a string.");a?n=e.map(s=>s.replace(/\{\{PARAMETERS\}\}/g,t)):n=e.map((s,c)=>c===0?`${s} ${t}`.trim():s)}else typeof t=="object"&&t!==null?n=e.map(a=>{let o=a;return Object.entries(t).forEach(([s,c])=>{let u=`{{${s}}}`;o=o.replaceAll(u,String(c))}),o}):n=[...e];let i=new Set;if(n.forEach(a=>{let o=a.match(/\{\{(\w+)\}\}/g);o&&o.forEach(s=>i.add(s))}),i.size>0){let a=Array.from(i).map(o=>o.replace(/[{}]/g,"")).join(", ");throw new Error(`Missing required parameters: ${a}`)}return n}async executePrompt(e,t,n,i,a){if(!this.threadCodayManager||!this.threadService||!this.codayOptions||!this.logger)throw new Error("PromptExecutionService not initialized. Call initialize() first.");let{title:o,awaitFinalAnswer:s=!1,projectName:c}=a||{},u,l;if(c){if(l=c,u=await this.promptService.get(l,e),!u)throw new Error(`Prompt ${e} not found in project ${l}`)}else{let y=await this.promptService.getById(e);if(!y)throw new Error(`Prompt not found: ${e}`);u=y.prompt,l=y.projectName}if(i==="webhook"&&!u.webhookEnabled)throw new Error(`Prompt ${e} is not enabled for webhook execution`);if(!u.commands||u.commands.length===0)throw new Error("Prompt has no commands configured");let f=this.processCommands(u.commands,t);if(!n)throw new Error("Username is required");let d=(await this.threadService.createThread(l,n,o)).id;console.log(`[PROMPT_EXEC] Created new thread: ${d} for ${i} execution`);let m={...this.codayOptions,oneshot:!0,project:l,thread:d,prompts:f};console.log(`[PROMPT_EXEC] Creating instance for ${i} execution with ${f.length} prompts:`,f);let h=this.threadCodayManager.createWithoutConnection(d,l,n,m);h.prepareCoday();let g=h.coday.interactor,v={project:l,title:o??"Untitled",username:n,clientId:d,promptCount:f.length,awaitFinalAnswer:!!s,promptName:u.name,promptId:u.id,executionMode:i};if(i==="webhook"?this.logger.logWebhook(v):this.logger.logWebhook({...v,webhookName:u.name,webhookUuid:u.id}),s){let y=[],x=g.events.pipe((0,sde.filter)(_=>(console.log(`[PROMPT_EXEC] Received event type: ${_.type}, role: ${_ instanceof jt?_.role:"N/A"}`),_ instanceof jt&&_.role==="assistant"&&!!_.name))).subscribe(_=>{y.push(_)});try{await h.coday.run(),x.unsubscribe();let _=y[y.length-1];return await this.threadCodayManager.cleanup(d),{threadId:d,lastEvent:_}}catch(_){x.unsubscribe();let S=_ instanceof Error?_.message:"Unknown error";throw this.logger.logWebhookError({error:`Prompt execution failed: ${S}`,username:n,project:l,clientId:d}),console.error("[PROMPT_EXEC] Error waiting for prompt completion:",_),await this.threadCodayManager.cleanup(d),_}}else return h.coday.run().catch(y=>{console.error("[PROMPT_EXEC] Error during prompt Coday run:",y)}).finally(()=>{this.threadCodayManager.cleanup(d).catch(y=>{console.error("[PROMPT_EXEC] Error cleaning up prompt thread after run:",y)})}),{threadId:d}}};var Tg=lr(zc(),1);import*as ui from"fs";import*as Vm from"path";import{randomUUID as Bot}from"node:crypto";var Xk=class{constructor(e,t,n){this.logger=e;this.promptService=t;this.codayConfigDir=n}schedulers=new Map;checkInterval;CHECK_INTERVAL_MS=3e4;promptExecutionService;initializeExecution(e){this.promptExecutionService=e}async initialize(){console.log("[SCHEDULER] Initializing SchedulerService..."),await this.loadAllSchedulers(),this.startScheduler(),console.log(`[SCHEDULER] SchedulerService initialized with ${this.schedulers.size} schedulers`)}stop(){this.checkInterval&&(clearInterval(this.checkInterval),this.checkInterval=void 0,console.log("[SCHEDULER] SchedulerService stopped"))}async loadAllSchedulers(){this.schedulers.clear();let e=Vm.join(this.codayConfigDir,"projects");if(!ui.existsSync(e))return;let t=ui.readdirSync(e,{withFileTypes:!0}).filter(n=>n.isDirectory()).map(n=>n.name);for(let n of t)try{let i=await this.loadProjectSchedulers(n);for(let a of i)this.schedulers.set(a.id,a)}catch(i){console.error(`[SCHEDULER] Failed to load schedulers for project ${n}:`,i)}}async loadProjectSchedulers(e){let t=this.getSchedulersDir(e);if(!ui.existsSync(t))return[];let n=ui.readdirSync(t),i=[];for(let a of n)if(a.endsWith(".yml"))try{let o=Vm.join(t,a),s=ui.readFileSync(o,"utf-8"),c=Tg.parse(s),u=this.calculateNextRunSkippingMissed(c),l=u.occurrenceCount!==c.occurrenceCount;c.nextRun=u.nextRun,c.occurrenceCount=u.occurrenceCount,l&&await this.saveScheduler(c,e),i.push(c)}catch(o){console.error(`[SCHEDULER] Failed to load scheduler from ${a}:`,o)}return i}startScheduler(){this.checkInterval=setInterval(()=>{this.checkAndExecuteSchedulers()},this.CHECK_INTERVAL_MS),this.checkAndExecuteSchedulers()}async checkAndExecuteSchedulers(){for(let e of this.schedulers.values())e.enabled&&Bue(e.schedule,e.nextRun??null,e.occurrenceCount??0)&&this.executeScheduler(e).catch(t=>{console.error(`[SCHEDULER] Failed to execute scheduler ${e.id}:`,t)})}async executeSchedulerInternal(e,t,n){if(!this.promptExecutionService)throw new Error("PromptExecutionService not initialized");console.log(`[SCHEDULER] Executing scheduler "${e.name}" (${e.id}) [${n}]`);let i=e.parameters;e.parameters&&typeof e.parameters=="object"&&Object.keys(e.parameters).length===1&&"PARAMETERS"in e.parameters&&(i=String(e.parameters.PARAMETERS));let a=await this.promptExecutionService.executePrompt(e.promptId,i,e.createdBy,"scheduled",{title:n==="scheduled"?`Scheduled: ${e.name}`:`Manual: ${e.name}`,awaitFinalAnswer:!1,projectName:t});return console.log(`[SCHEDULER] Scheduler "${e.name}" executed successfully. Thread: ${a.threadId}`),a.threadId}async executeScheduler(e){let t=new Date().toISOString();console.log(`[SCHEDULER] Executing scheduler "${e.name}" (${e.id})`);let n=this.findProjectForScheduler(e.id);if(!n){console.error(`[SCHEDULER] Cannot find project for scheduler ${e.id}, skipping execution`);return}let i,a,o;e.lastRun=t,e.occurrenceCount=(e.occurrenceCount??0)+1,e.nextRun=Oh(e.schedule,new Date,e.occurrenceCount);try{await this.saveScheduler(e,n),console.log(`[SCHEDULER] Next execution for "${e.name}": ${e.nextRun}`),this.schedulers.set(e.id,e),a=await this.executeSchedulerInternal(e,n,"scheduled"),i=!0}catch(s){i=!1,o=s instanceof Error?s.message:String(s),console.error(`[SCHEDULER] Scheduler "${e.name}" failed:`,s)}this.logger.logTriggerExecution({triggerId:e.id,triggerName:e.name,webhookUuid:e.promptId,projectName:n,success:i,threadId:a,error:o})}validateSchedule(e){return zue(e)}calculateNextRunSkippingMissed(e){let t=new Date,n=e.occurrenceCount??0,i=e.nextRun;if(!i)return{nextRun:Oh(e.schedule,t,n),occurrenceCount:n};if(new Date(i)>=t)return{nextRun:i,occurrenceCount:n};let a=1e3,o=0,s=0;for(;o<a;){if(n++,s++,i=Oh(e.schedule,t,n),!i)return s>0&&console.log(`[SCHEDULER] Scheduler "${e.name}" (${e.id}) expired after skipping ${s} missed occurrence(s)`),{nextRun:null,occurrenceCount:n};if(new Date(i)>=t)return s>0&&console.log(`[SCHEDULER] Scheduler "${e.name}" (${e.id}) skipped ${s} missed occurrence(s), next run: ${i}`),{nextRun:i,occurrenceCount:n};o++}return console.warn(`[SCHEDULER] Could not find future nextRun for scheduler ${e.id} after ${a} iterations`),{nextRun:null,occurrenceCount:n}}getSchedulersDir(e){return Vm.join(this.codayConfigDir,"projects",e,"schedulers")}getSchedulerFilePath(e,t){return Vm.join(this.getSchedulersDir(e),`${t}.yml`)}findProjectForScheduler(e){let t=Vm.join(this.codayConfigDir,"projects");if(!ui.existsSync(t))return null;let n=ui.readdirSync(t,{withFileTypes:!0}).filter(i=>i.isDirectory()).map(i=>i.name);for(let i of n){let a=this.getSchedulerFilePath(i,e);if(ui.existsSync(a))return i}return null}canAccessScheduler(e,t){return e.createdBy===t?!0:Wm(t,this.codayConfigDir)}async listSchedulers(e,t){return(await this.loadProjectSchedulers(e)).filter(i=>this.canAccessScheduler(i,t)).map(i=>({id:i.id,name:i.name,enabled:i.enabled,promptId:i.promptId,schedule:i.schedule,parameters:i.parameters,lastRun:i.lastRun,nextRun:i.nextRun,createdBy:i.createdBy}))}async getScheduler(e,t,n){let i=this.getSchedulerFilePath(e,t);if(!ui.existsSync(i))return null;try{let a=ui.readFileSync(i,"utf-8"),o=Tg.parse(a),s=this.calculateNextRunSkippingMissed(o);return o.nextRun=s.nextRun,o.occurrenceCount=s.occurrenceCount,n&&!this.canAccessScheduler(o,n)?(console.log(`[SCHEDULER] Access denied for user ${n} to scheduler ${t}`),null):o}catch(a){return console.error(`[SCHEDULER] Failed to load scheduler ${t}:`,a),null}}async createScheduler(e,t,n){let i=this.validateSchedule(t.schedule);if(!i.valid)throw new Error(`Invalid schedule: ${i.error}`);if(!await this.promptService.getById(t.promptId))throw new Error(`Prompt not found: ${t.promptId}`);let o={id:Bot(),name:t.name,enabled:t.enabled??!0,promptId:t.promptId,schedule:t.schedule,parameters:t.parameters,createdBy:n,createdAt:new Date().toISOString(),nextRun:Oh(t.schedule,new Date,0),occurrenceCount:0};return await this.saveScheduler(o,e),this.schedulers.set(o.id,o),console.log(`[SCHEDULER] Created scheduler "${o.name}" (${o.id}) for project ${e}`),o}async updateScheduler(e,t,n,i){let a=await this.getScheduler(e,t,i);if(!a)throw new Error(`Scheduler not found or access denied: ${t}`);if(console.log(`[SCHEDULER] Updating scheduler ${t} by user ${i}`),n.name!==void 0&&(a.name=n.name),n.enabled!==void 0&&(a.enabled=n.enabled),n.parameters!==void 0&&(a.parameters=n.parameters),n.promptId!==void 0){if(!await this.promptService.getById(n.promptId))throw new Error(`Prompt not found: ${n.promptId}`);a.promptId=n.promptId}if(n.schedule!==void 0){let o=this.validateSchedule(n.schedule);if(!o.valid)throw new Error(`Invalid schedule: ${o.error}`);a.schedule=n.schedule,a.occurrenceCount=0,a.nextRun=Oh(n.schedule,new Date,0)}return await this.saveScheduler(a,e),this.schedulers.set(a.id,a),console.log(`[SCHEDULER] Updated scheduler "${a.name}" (${a.id})`),a}async deleteScheduler(e,t,n){if(!await this.getScheduler(e,t,n))return!1;let a=this.getSchedulerFilePath(e,t);return ui.unlinkSync(a),this.schedulers.delete(t),console.log(`[SCHEDULER] Deleted scheduler ${t} by user ${n}`),!0}async enableScheduler(e,t,n){return this.updateScheduler(e,t,{enabled:!0},n)}async disableScheduler(e,t,n){return this.updateScheduler(e,t,{enabled:!1},n)}async runSchedulerNow(e,t,n){let i=await this.getScheduler(e,t,n);if(!i)throw new Error(`Scheduler not found or access denied: ${t}`);let a=await this.executeSchedulerInternal(i,e,"manual");return i.lastRun=new Date().toISOString(),await this.saveScheduler(i,e),this.schedulers.set(i.id,i),this.logger.logTriggerExecution({triggerId:i.id,triggerName:i.name,webhookUuid:i.promptId,projectName:e,success:!0,threadId:a}),a}async saveScheduler(e,t){if(!t&&(t=this.findProjectForScheduler(e.id),!t))throw new Error(`Cannot find project for scheduler ${e.id}`);let n=this.getSchedulersDir(t);ui.mkdirSync(n,{recursive:!0});let i=this.getSchedulerFilePath(t,e.id),a=Tg.stringify(e);ui.writeFileSync(i,a,"utf-8")}};import*as fs from"node:path";import*as ude from"node:os";import{existsSync as cde,lstatSync as Hot,mkdirSync as AL,readdirSync as Wot,renameSync as Vot}from"fs";var Qk=class r{projectsConfigPath;static PROJECT_FILENAME="project.yaml";constructor(e){let t=fs.join(ude.userInfo().homedir,".coday");this.projectsConfigPath=fs.join(e??t,"projects"),AL(this.projectsConfigPath,{recursive:!0})}listProjects(){return Wot(this.projectsConfigPath).filter(t=>!t.startsWith(".")&&Hot(fs.join(this.projectsConfigPath,t)).isDirectory())}getProjectInfo(e){let t=fs.join(this.projectsConfigPath,e),n=fs.join(t,r.PROJECT_FILENAME);return cde(n)?{name:e,configPath:t}:null}exists(e){return this.getProjectInfo(e)!==null}getConfig(e){let t=this.getProjectInfo(e);if(!t)return console.log(`[PROJECT_REPO] No project info found for: '${e}'`),null;let n=fs.join(t.configPath,r.PROJECT_FILENAME),i=oa(n);if(!i)return console.log(`[PROJECT_REPO] Failed to load config for '${e}' from ${n}`),null;let a=Dh(i,Hue);return a!==i&&(console.log(`[PROJECT_REPO] Config migrated for '${e}', saving...`),Un(n,a)),a}saveConfig(e,t){let n=this.getProjectInfo(e);if(!n)throw new Error(`Project '${e}' does not exist`);let i=fs.join(n.configPath,r.PROJECT_FILENAME);Un(i,t)}createProject(e,t){let n=fs.join(this.projectsConfigPath,e),i=fs.join(n,r.PROJECT_FILENAME);return cde(i)?!1:(console.log(`[PROJECT_REPO] Creating project '${e}' with path: ${t}`),AL(n,{recursive:!0}),Un(i,{version:1,path:t,integration:{},storage:{type:"file"},agents:[]}),console.log(`[PROJECT_REPO] Project '${e}' created successfully`),!0)}deleteProject(e){let t=this.getProjectInfo(e);if(!t)return!1;let n=fs.join(this.projectsConfigPath,".deleted");AL(n,{recursive:!0});let i=new Date().toISOString().replace(/:/g,"-"),a=fs.join(n,`${e}__${i}`);return Vot(t.configPath,a),!0}};var TL=lr(zc(),1);import{promises as ol}from"fs";import ld from"path";var lde=async r=>{try{let e=await ol.readFile(r,"utf-8");return TL.default.parse(e)}catch{return null}},eE=class{constructor(e){this.projectsDir=e}getThreadsDir(e){return ld.join(this.projectsDir,e,"threads")}async ensureThreadsDir(e){let t=this.getThreadsDir(e);try{await ol.mkdir(t,{recursive:!0})}catch(n){throw new Nu(`Failed to initialize threads directory for project ${e}`,n)}}getThreadFileName(e){return`${e.id}.yml`}async findThreadFile(e,t){try{let n=this.getThreadsDir(e),i=`${t}.yml`;try{return await ol.access(ld.join(n,i)),i}catch{}return(await ol.readdir(n)).find(s=>s.endsWith(`-${t}.yml`))||null}catch(n){throw new Nu(`Error finding thread ${t} in project ${e}`,n)}}async getById(e,t){try{let n=await this.findThreadFile(e,t);if(!n)return null;let i=this.getThreadsDir(e),a=ld.join(i,n),o=await lde(a);if(!o)return null;let s=Dh(o,rF);return s.projectId||(s.projectId=e),s!==o&&Un(a,s),new Fu(s)}catch(n){throw new Nu(`Failed to read thread ${t} from project ${e}`,n)}}async save(e,t){await this.ensureThreadsDir(e);try{if(t.id||(t.id=crypto.randomUUID()),t.projectId||(t.projectId=e),t.projectId!==e)throw new Error(`Thread projectId mismatch: expected ${e}, got ${t.projectId}`);let n=this.getThreadsDir(e),i=this.getThreadFileName(t),a=ld.join(n,i),o=await this.findThreadFile(e,t.id);if(o&&o!==i){let u=ld.join(n,o);try{await ol.unlink(u),console.log(`[THREAD-REPO] Migrated/renamed thread file: ${o} \u2192 ${i}`)}catch(l){console.warn(`[THREAD-REPO] Could not delete old thread file: ${o}`,l)}}let s={...t.serialize(),version:rF.length+1},c=TL.default.stringify(s);return await ol.writeFile(a,c,"utf-8"),t}catch(n){throw new Nu(`Failed to save thread ${t.id} to project ${e}`,n)}}async listByProject(e){try{let t=this.getThreadsDir(e);try{await ol.access(t)}catch{return[]}let n=await ol.readdir(t);return(await Promise.all(n.filter(a=>a.endsWith(".yml")).map(async a=>{let o=await lde(ld.join(t,a));if(!o)return null;let s=o.projectId||e;return{id:o.id,username:o.username,projectId:s,name:o.name??"...",summary:o.summary??"",createdDate:o.createdDate??"",modifiedDate:o.modifiedDate??"",price:o.price??0,starring:o.starring??[],users:Array.isArray(o.users)?o.users.map(c=>typeof c=="string"?{userId:c}:c):o.username?[{userId:o.username}]:[],parentThreadId:o.parentThreadId,parentEventId:o.parentEventId,delegatedAgentName:o.delegatedAgentName,delegatedTask:o.delegatedTask}}))).filter(a=>!!a).sort((a,o)=>a.modifiedDate>o.modifiedDate?-1:1)}catch(t){throw new Nu(`Failed to list threads for project ${e}`,t)}}async delete(e,t){try{let n=await this.findThreadFile(e,t);if(!n)return!1;let i=this.getThreadsDir(e);return await ol.unlink(ld.join(i,n)),!0}catch(n){throw new Nu(`Failed to delete thread ${t} from project ${e}`,n)}}};var tE=class{constructor(e,t,n){this.projectRepository=e;this.projectsDir=t;this.threadFileService=n}repositoryCache=new Map;threadListCache=new Map;CACHE_TTL_MS=14400*1e3;loadingPromises=new Map;getThreadRepository(e){let t=this.repositoryCache.get(e);if(t)return t;if(!this.projectRepository.getProjectInfo(e))throw new Error(`Project '${e}' not found`);let i=new eE(this.projectsDir);return this.repositoryCache.set(e,i),i}clearCache(e){e?this.repositoryCache.delete(e):this.repositoryCache.clear()}async listThreads(e,t){let n=this.threadListCache.get(e);if(n&&Date.now()-n.timestamp<this.CACHE_TTL_MS)return n.data.filter(o=>on(o,t)).sort((o,s)=>o.modifiedDate>s.modifiedDate?-1:1);let i=this.loadingPromises.get(e);if(i)return await i,this.listThreads(e,t);let a=this.loadThreadListFromDisk(e);this.loadingPromises.set(e,a);try{return(await a).filter(s=>on(s,t)).sort((s,c)=>s.modifiedDate>c.modifiedDate?-1:1)}catch(o){throw this.threadListCache.delete(e),o}finally{this.loadingPromises.delete(e)}}async loadThreadListFromDisk(e){let n=await this.getThreadRepository(e).listByProject(e);return this.threadListCache.set(e,{data:n,timestamp:Date.now()}),n}toThreadSummary(e){return{id:e.id,username:e.username,projectId:e.projectId,name:e.name,summary:e.summary,createdDate:e.createdDate,modifiedDate:e.modifiedDate,price:e.price,starring:e.starring,users:e.users,parentThreadId:e.parentThreadId,parentEventId:e.parentEventId,delegatedAgentName:e.delegatedAgentName,delegatedTask:e.delegatedTask}}updateThreadInCache(e,t){let n=this.threadListCache.get(e);if(!n)return;let i=n.data.findIndex(a=>a.id===t.id);i!==-1?n.data[i]=t:n.data.push(t)}removeThreadFromCache(e,t){let n=this.threadListCache.get(e);n&&(n.data=n.data.filter(i=>i.id!==t))}async getThread(e,t){return await this.getThreadRepository(e).getById(e,t)}async createThread(e,t,n){let i=this.getThreadRepository(e),a=new Fu({id:crypto.randomUUID(),username:t,projectId:e,name:n||"",price:0}),o=await i.save(e,a);return this.updateThreadInCache(e,this.toThreadSummary(o)),o}async updateThread(e,t,n){let i=this.getThreadRepository(e),a=await i.getById(e,t);if(!a){let c=this.threadListCache.get(e)?.data.find(u=>u.id===t);if(c)a=new Fu({id:c.id,username:c.username,projectId:c.projectId,name:c.name,summary:c.summary,price:c.price,starring:c.starring,users:c.users,parentThreadId:c.parentThreadId,parentEventId:c.parentEventId,delegatedAgentName:c.delegatedAgentName,delegatedTask:c.delegatedTask});else throw new Error(`Thread '${t}' not found in project '${e}'`)}n.name!==void 0&&(a.name=n.name),n.summary!==void 0&&(a.summary=n.summary),n.users!==void 0&&(a.users=n.users);let o=await i.save(e,a);return this.updateThreadInCache(e,this.toThreadSummary(o)),o}async starThread(e,t,n){let i=this.getThreadRepository(e),a=await i.getById(e,t);if(!a)throw new Error(`Thread '${t}' not found in project '${e}'`);a.starring.includes(n)||a.starring.push(n);let o=await i.save(e,a);return this.updateThreadInCache(e,this.toThreadSummary(o)),o}async unstarThread(e,t,n){let i=this.getThreadRepository(e),a=await i.getById(e,t);if(!a)throw new Error(`Thread '${t}' not found in project '${e}'`);a.starring=a.starring.filter(s=>s!==n);let o=await i.save(e,a);return this.updateThreadInCache(e,this.toThreadSummary(o)),o}async deleteThread(e,t){let i=await this.getThreadRepository(e).delete(e,t);return i&&(await this.threadFileService.deleteThreadFiles(e,t),this.removeThreadFromCache(e,t)),i}async saveThread(e,t){let i=await this.getThreadRepository(e).save(e,t);return this.updateThreadInCache(e,this.toThreadSummary(i)),i}async listAllThreads(e){let t=this.threadListCache.get(e);if(t&&Date.now()-t.timestamp<this.CACHE_TTL_MS)return t.data.sort((a,o)=>a.modifiedDate>o.modifiedDate?-1:1);let n=this.loadingPromises.get(e);if(n)return await n,this.listAllThreads(e);let i=this.loadThreadListFromDisk(e);this.loadingPromises.set(e,i);try{return(await i).sort((o,s)=>o.modifiedDate>s.modifiedDate?-1:1)}catch(a){throw this.threadListCache.delete(e),a}finally{this.loadingPromises.delete(e)}}async exists(e,t){return await this.getThread(e,t)!==null}};var mde=lr(zc(),1);import*as Ca from"fs/promises";import*as Pg from"path";var fde=5,pde=24,dde=100,hde={SHORT_THREADS:7,LONG_THREADS:30},rE=class{constructor(e,t){this.projectsConfigPath=e;this.logger=t}cleanupTimer=null;initialTimer=null;isRunning=!1;async start(){if(this.isRunning){this.log("Thread cleanup service already running");return}this.isRunning=!0,this.log("Starting thread cleanup service with user message-based retention"),this.initialTimer=setTimeout(async()=>{await this.performCleanup(),this.cleanupTimer=setInterval(async()=>{await this.performCleanup()},pde*60*60*1e3),this.log(`Thread cleanup scheduled every ${pde} hours`)},fde*60*1e3),this.log(`Initial cleanup scheduled in ${fde} minutes`)}async stop(){this.initialTimer&&(clearTimeout(this.initialTimer),this.initialTimer=null),this.cleanupTimer&&(clearInterval(this.cleanupTimer),this.cleanupTimer=null),this.isRunning=!1,this.log("Thread cleanup service stopped (all timers cleared)")}async performCleanup(){let e=Date.now(),t=0,n=0,i=0;try{this.log("Starting thread cleanup...");let a=await Ca.readdir(this.projectsConfigPath);this.log(`Found ${a.length} projects to scan`);for(let s of a)try{let c=Pg.join(this.projectsConfigPath,s);if(!(await Ca.lstat(c)).isDirectory())continue;let l=Pg.join(c,"threads");try{await Ca.access(l)}catch{continue}let{scanned:f,deleted:p,errors:d}=await this.cleanupProjectThreads(s,l);t+=f,n+=p,i+=d}catch(c){this.logError(`Error processing project ${s}: ${c}`),i++}let o=Date.now()-e;this.log(`Cleanup completed: ${n}/${t} threads deleted across all projects in ${o}ms (${i} errors)`)}catch(a){let o=Date.now()-e;this.logError(`Cleanup failed after ${o}ms: ${a}`)}}async cleanupProjectThreads(e,t){let n=0,i=0,a=0;try{let s=(await Ca.readdir(t)).filter(c=>c.endsWith(".yml"));if(n=s.length,s.length===0)return{scanned:n,deleted:i,errors:a};this.log(`Scanning ${s.length} threads in project ${e}`);for(let c=0;c<s.length;c+=dde){let u=s.slice(c,c+dde),l=await this.processBatch(u,t,e);i+=l.deleted,a+=l.errors}i>0&&this.log(`Project ${e}: deleted ${i}/${n} expired threads`)}catch(o){this.logError(`Error scanning project ${e}: ${o}`),a++}return{scanned:n,deleted:i,errors:a}}async processBatch(e,t,n){let i=0,a=0;return await Promise.all(e.map(async o=>{let s=Pg.join(t,o),c;try{let u=await Ca.readFile(s,"utf-8");c=mde.parse(u)}catch(u){await Ca.unlink(s),this.logError(`Error processing file ${o} in project ${n}: ${u}`)}if(!(!c||!c.modifiedDate)&&!(c.starring&&Array.isArray(c.starring)&&c.starring.length>0)&&this.shouldDeleteThread(c)){let u=this.countUserMessages(c.messages||[]),l=this.getDaysSinceModified(c.modifiedDate),f=c.id||o.replace(".yml","");await Ca.unlink(s),await this.deleteThreadFiles(t,f),i++,this.logger.logThreadCleanup(n,o),console.log(`ThreadCleanup: Deleted thread ${f} and its files directory (${u} user messages, ${l} days old)`)}})),{deleted:i,errors:a}}shouldDeleteThread(e){if(!e||!e.modifiedDate)return!1;let n=this.countUserMessages(e.messages||[])<=3?hde.SHORT_THREADS:hde.LONG_THREADS;return this.getDaysSinceModified(e.modifiedDate)>n}countUserMessages(e){return e.filter(t=>t&&t.type==="message"&&t.role==="user").length}getDaysSinceModified(e){let t=new Date(e),i=new Date().getTime()-t.getTime();return Math.floor(i/(1e3*60*60*24))}async deleteThreadFiles(e,t){try{let n=Pg.join(e,`${t}-files`);try{await Ca.access(n),await Ca.rm(n,{recursive:!0,force:!0}),console.log(`ThreadCleanup: Deleted files directory ${n}`)}catch(i){if(i.code!=="ENOENT")throw i}}catch(n){console.error(`ThreadCleanup: Error deleting files for ${t}:`,n)}}log(e){let t=new Date().toISOString();console.log(`[${t}] ThreadCleanup: ${e}`)}logError(e){let t=new Date().toISOString();console.error(`[${t}] ThreadCleanup ERROR: ${e}`)}async forceCleanup(){this.log("Manual cleanup triggered"),await this.performCleanup()}};import*as Hi from"path";import*as fd from"fs";import*as Aa from"fs/promises";var nE=class{constructor(e){this.projectsDir=e}getThreadFilesDir(e,t){return Hi.join(this.projectsDir,e,"threads",`${t}-files`)}async ensureThreadFilesDir(e,t){let n=this.getThreadFilesDir(e,t);fd.existsSync(n)||await Aa.mkdir(n,{recursive:!0})}async listFiles(e,t){await this.ensureThreadFilesDir(e,t);let n=this.getThreadFilesDir(e,t),i=await Aa.readdir(n);return await Promise.all(i.map(async o=>{let s=Hi.join(n,o),c=await Aa.stat(s);return{filename:o,size:c.size,lastModified:c.mtime.toISOString()}}))}async saveFile(e,t,n,i){let a=this.getThreadFilesDir(e,t);await Aa.mkdir(a,{recursive:!0});let o=Hi.join(a,n);await Aa.writeFile(o,i)}async getFile(e,t,n){await this.ensureThreadFilesDir(e,t);let i=this.getThreadFilesDir(e,t),a=Hi.join(i,n),o=Hi.resolve(a),s=Hi.resolve(i);if(!o.startsWith(s))throw new Error("Access denied: invalid file path");if(!fd.existsSync(a))throw new Error(`File '${n}' not found`);return await Aa.readFile(a)}async getFilePath(e,t,n){await this.ensureThreadFilesDir(e,t);let i=this.getThreadFilesDir(e,t),a=Hi.join(i,n),o=Hi.resolve(a),s=Hi.resolve(i);if(!o.startsWith(s))throw new Error("Access denied: invalid file path");if(!fd.existsSync(a))throw new Error(`File '${n}' not found`);return a}fileExists(e,t,n){let i=this.getThreadFilesDir(e,t),a=Hi.join(i,n),o=Hi.resolve(a),s=Hi.resolve(i);return o.startsWith(s)?fd.existsSync(a):!1}async deleteFile(e,t,n){await this.ensureThreadFilesDir(e,t);let i=this.getThreadFilesDir(e,t),a=Hi.join(i,n),o=Hi.resolve(a),s=Hi.resolve(i);if(!o.startsWith(s))throw new Error("Access denied: invalid file path");if(!fd.existsSync(a))throw new Error(`File '${n}' not found`);await Aa.unlink(a)}async deleteThreadFiles(e,t){try{let n=this.getThreadFilesDir(e,t);fd.existsSync(n)&&(await Aa.rm(n,{recursive:!0,force:!0}),console.log(`Deleted thread files directory: ${n}`))}catch(n){console.error(`Error deleting thread files for ${t}:`,n)}}};var gde=lr(wo(),1);var iE=class{constructor(e,t,n,i){this.threadRepository=t;this.projectId=n;this.interactor=i;this.username=e.username}activeThread$=new gde.BehaviorSubject(null);isKilled=!1;activeThread=this.activeThread$.asObservable();username;async kill(){this.isKilled=!0,this.activeThread$.complete()}async create(e){let t=new Fu({id:"",username:this.username,name:e??"",price:0});return this.activeThread$.next(t),t}async select(e){let t=await this.threadRepository.getById(this.projectId,e);if(!t)throw new Error(`Thread ${e} not found`);return this.activeThread$.next(t),t}async save(e){let t=this.activeThread$.value;if(!t){console.error(`No thread existing when save attempt with name '${e}'`);return}e&&(t.name=e);let n=await this.threadRepository.save(this.projectId,t);this.activeThread$.next(n)}async autoSave(e){if(this.isKilled){console.log("Autosave skipped: service has been killed");return}let t=this.activeThread$.value;if(!t||t.messagesLength==0){console.log(`Autosave of an empty or falsy thread aborted, threadId: ${t?.id}, user: ${this.username}`);return}try{e&&(t.name=e),await this.threadRepository.save(this.projectId,t),this.interactor&&this.interactor.sendEvent(new Tc({threadId:t.id,name:t.name||void 0}))}catch(n){console.log("Autosave failed (service may have been killed):",n instanceof Error?n.message:n)}}async truncateAtUserMessage(e){let t=this.activeThread$.value;if(!t)return console.error("No active thread available for truncation"),!1;let n=t.truncateAtUserMessage(e);return n||this.interactor?.warn("Failed to truncate thread."),n}getCurrentThread(){return this.activeThread$.value}};async function vde(r,e){let t=e.project.selectedProject,n=e.user.getUserData(t.name),i=await Gk(t.config.path,r,n),a=new Z0({...i,root:t.config.path,name:t.name},e.user.username);return console.log(`[BUILD_CONTEXT] Context for '${a.project.name}' \u2192 root: ${a.project.root}, desc: ${a.project.description?.length||0} chars`),a}var aE=class extends Ne{constructor(t,n){super({commandWord:"select-project",description:"Select an existing project"});this.interactor=t;this.services=n}async handle(t,n){try{let i=this.getSubCommand(t);return await this.selectProject(i)??n}catch(i){return this.interactor.error(`Invalid project selection because: ${i.toString()}`),n}}async selectProject(t){return this.services.project.selectProject(t),this.services.project.selectedProject?vde(this.interactor,this.services):null}};var oE=class extends Ne{constructor(t,n,i){super({commandWord:"add",description:"Add a new integration configuration. User level is default, use --project/-p for project level."});this.interactor=t;this.service=n;this.editHandler=i}async handle(t,n){let a=!!Pt(this.getSubCommand(t),[{key:"project",alias:"p"}]).project,o=a?"project":"user",s=this.service.getMergedIntegrations(),c=Object.keys(s),u=hp.filter(h=>!c.includes(h));if(u.length===0)return this.interactor.displayText(`All available integrations (${hp.join(", ")}) are already configured.`),n;let l=await this.interactor.chooseOption(u.sort(),"Select integration to add:",`Available integrations to configure:
881
881
 
882
882
  ${u.map(h=>`- **${h}**`).join(`
883
883
  `)}
@@ -1415,7 +1415,7 @@ ${this.services.memory.getFormattedMemories("PROJECT",n.name)}
1415
1415
 
1416
1416
  ${l}
1417
1417
 
1418
- `;let p=n.integrations?new Map(Object.entries(n.integrations).map(([x,_])=>{let S=_&&_.length>0?_:[];return[x,S]})):void 0;this.interactor.debug(`Agent '${n.name}' integrations: ${p?Array.from(p.keys()).join(", "):"ALL (undefined)"}`);let d=performance.now(),m=await this.toolbox.getTools({context:t,integrations:p,agentName:n.name}),h=performance.now()-d;this.interactor.debug(` \u{1F4E6} Tools available for '${n.name}': ${m.map(x=>x.function.name).join(", ")}`);let g=new Tw([...m]),v=new kw(n,o,g),y=performance.now()-i;return this.interactor.debug(`\u2728 Agent '${n.name}' created: ${y.toFixed(2)}ms (client: ${s.toFixed(2)}ms, docs: ${f.toFixed(2)}ms, tools: ${h.toFixed(2)}ms)`),v}catch(a){let o=`Failed to create agent ${n.name}`;console.error(`${o}:`,a),this.interactor.error(o);return}}};var pyt=100,vP=class{constructor(e,t,n){this.interactor=e;this.options=t;this.services=n;this.interactor.debugLevelEnabled=t.debug,this.interactor.debug("Coday started with debug"),this.configHandler=new hE(e,this.services),this.maxIterations=pyt,this.aiThreadService=new iE(n.user,n.thread.getThreadRepository(t.project),t.project,e),this.aiThreadService.activeThread.subscribe(i=>{!this.context||!i||(this.context.aiThread=i,this.replayThread(i))}),this.aiClientProvider=new Gm(this.interactor,this.services.user,this.services.project,this.services.logger),this.interactor.events.pipe((0,ZZ.filter)(i=>i instanceof Fi||i instanceof Mi||i instanceof Sr),(0,ZZ.filter)(()=>!this.isReplaying)).subscribe(i=>{i instanceof Fi||i instanceof Mi?this.pendingQuestionEvent=i:i instanceof Sr&&this.pendingQuestionEvent&&i.parentKey===this.pendingQuestionEvent.timestamp&&(this.pendingQuestionEvent=null)})}context=null;configHandler;handlerLooper;aiHandler;maxIterations;initialPrompts=[];aiThreadService;killed=!1;isReplaying=!1;pendingQuestionEvent=null;messageQueue=[];aiClientProvider;addUserMessage(e,t){if(this.pendingQuestionEvent){let n=this.pendingQuestionEvent.buildAnswer(t);n.name=e,this.interactor.sendEvent(n)}else{let n=new jt({role:"user",content:[{type:"text",content:t}],name:e});this.interactor.sendEvent(n),this.messageQueue.push({username:e,message:t})}}replay(){let e=this.aiThreadService.getCurrentThread();if(!e){console.log("No active thread to replay");return}this.replayThread(e),!this.options.oneshot&&e.runStatus!=="RUNNING"&&this.interactor.replayLastInvite()}upload(e){let t=this.aiThreadService.getCurrentThread();if(!t){this.interactor.error("No active thread available for upload");return}let n=this.services.user.username;e.forEach(a=>{t.addUserMessage(n,a)});let i=new jt({role:"user",content:e,name:n});this.interactor.sendEvent(i)}async run(){this.initialPrompts=this.options.prompts?[...this.options.prompts]:[],this.interactor.debug(`[CODAY] Starting run with ${this.initialPrompts.length} initial prompts`);try{do{if(this.killed)return;if(await this.initContext(),await this.initThread(),!this.context){this.interactor.error("Could not initialize context \u{1F62D}");break}let e=await this.initCommand();if(!e&&this.options.oneshot)break;let t=this.context?.aiThread;t&&(t.runStatus="RUNNING"),this.context?.addCommands(e),this.context=await this.handlerLooper?.handle(this.context)??null}while(!this.context?.oneshot)}finally{this.stop()}await this.cleanup()}stop(){let e=this.context?.aiThread;e&&(e.runStatus="STOPPED"),this.handlerLooper?.stop(),this.aiThreadService.autoSave()}async cleanup(){try{this.services.agent&&await this.services.agent.kill(),this.aiThreadService.kill(),this.aiClientProvider.cleanup(),this.context=null,this.handlerLooper=void 0,this.aiHandler=void 0,this.messageQueue=[],this.pendingQuestionEvent=null}catch(e){console.error("Error during agent cleanup:",e)}}async kill(){this.killed=!0,this.stop();try{await this.cleanup()}catch(e){console.error("Error during kill cleanup:",e)}this.handlerLooper?.kill(),this.interactor.kill()}async replayThread(e){this.isReplaying=!0;try{let t=(await e.getMessages(void 0,void 0)).messages;if(!t?.length)return;let n=[...t].sort((i,a)=>new Date(i.timestamp).getTime()-new Date(a.timestamp).getTime());for(let i of n)(i instanceof jt||i instanceof hn||i instanceof Tn||i instanceof Fi||i instanceof Mi||i instanceof Sr)&&this.interactor.sendEvent(i);this.interactor.displayText(`Selected thread '${e.name}'`)}finally{this.isReplaying=!1}}async initContext(){if(this.context){this.interactor.debug("[CODAY] Context already initialized, skipping");return}if(this.interactor.debug(`[CODAY] Initializing context for project: ${this.options.project}`),this.context=await this.configHandler.selectProjectHandler.selectProject(this.options.project),!this.context){console.log("[CODAY] ERROR: Failed to create context from selectProject");return}console.log(`[CODAY] Context initialized: '${this.context.project.name}' at ${this.context.project.root}`),this.context&&(this.context.oneshot=this.options.oneshot,this.context.fileReadOnly=this.options.fileReadOnly,this.options.thread&&this.options.project&&(this.context.threadFilesRoot=_ye.join(this.options.configDir,"projects",this.options.project,"threads",`${this.options.thread}-files`),this.interactor.debug(`[CODAY] Thread files root: ${this.context.threadFilesRoot}`)),this.services.aiConfig=new Wk(this.services.user,this.services.project),this.services.aiConfig.initialize(this.context),this.services.mcp.initialize(this.context),this.services.agent=new k4(this.interactor,this.aiClientProvider,this.services,this.context.project.root,this.options.agentFolders),this.aiHandler=new OE(this.interactor,this.services.agent,this.aiThreadService),this.handlerLooper=new DE(this.interactor,this.aiHandler,this.configHandler,this.services),this.aiClientProvider.init(this.context),await this.handlerLooper.init(this.context.project),console.log("[CODAY] Initializing services..."),await this.services.agent.initialize(this.context),console.log("[CODAY] Services initialized"))}async initThread(){if(!this.context?.aiThread){if(!this.options.thread)throw Error("No thread given, cannot start Coday instance");await this.aiThreadService.select(this.options.thread)}}async initCommand(){let e;if(this.interactor.debug(`[CODAY] initCommand: ${this.initialPrompts.length} prompts available, oneshot=${this.options.oneshot}`),this.initialPrompts.length)e=this.initialPrompts.shift(),this.interactor.debug(`[CODAY] Using initial prompt: ${e}`),this.initialPrompts.length&&(this.interactor.debug(`[CODAY] Adding ${this.initialPrompts.length} remaining prompts to queue`),this.context?.addCommands(...this.initialPrompts),this.initialPrompts=[]);else if(this.messageQueue.length>0){let t=this.messageQueue.shift();this.interactor.debug(`[CODAY] Consuming queued message from ${t.username}`),e=t.message,this.context&&(this.context.username=t.username)}else this.options.oneshot?this.interactor.debug("[CODAY] No initial prompts and oneshot mode, exiting"):(this.interactor.debug("[CODAY] No initial prompts, waiting for user input"),e=await this.interactor.promptText(moe),this.context&&this.interactor.lastAnswerName&&(this.context.username=this.interactor.lastAnswerName));return e}};function fe(r,...e){console.log(`${new Date().toISOString()} ${r}`,...e)}var dyt=4,yP=class{constructor(e,t){this.aiClient=e;this.threadService=t}process(e,t){this.run(e,t).catch(n=>fe("POST_PROCESSOR",`Unhandled error for thread ${e.id}:`,n))}async run(e,t){let n=e.getUserMessageCount();if(n<dyt){fe("POST_PROCESSOR",`Skipping thread ${e.id}: only ${n} user message(s)`);return}fe("POST_PROCESSOR",`Processing thread ${e.id} (${n} user messages)`);let{messages:i}=await e.getMessages(void 0,void 0),a=i.filter(f=>f instanceof jt).slice(-40).map(f=>{let p=f.role==="user"?"User":f.name||"Assistant",d=f.content.filter(m=>m.type==="text").map(m=>m.content).join(" ").slice(0,500);return`${p}: ${d}`});if(!a.length){fe("POST_PROCESSOR",`Skipping thread ${e.id}: no text messages`);return}let s=`You are given a conversation transcript. Reply ONLY with a valid JSON object (no markdown, no explanation) with two fields:
1418
+ `;let p=n.integrations?new Map(Object.entries(n.integrations).map(([x,_])=>{let S=_&&_.length>0?_:[];return[x,S]})):void 0;this.interactor.debug(`Agent '${n.name}' integrations: ${p?Array.from(p.keys()).join(", "):"ALL (undefined)"}`);let d=performance.now(),m=await this.toolbox.getTools({context:t,integrations:p,agentName:n.name}),h=performance.now()-d;this.interactor.debug(` \u{1F4E6} Tools available for '${n.name}': ${m.map(x=>x.function.name).join(", ")}`);let g=new Tw([...m]),v=new kw(n,o,g),y=performance.now()-i;return this.interactor.debug(`\u2728 Agent '${n.name}' created: ${y.toFixed(2)}ms (client: ${s.toFixed(2)}ms, docs: ${f.toFixed(2)}ms, tools: ${h.toFixed(2)}ms)`),v}catch(a){let o=`Failed to create agent ${n.name}`;console.error(`${o}:`,a),this.interactor.error(o);return}}};var pyt=100,vP=class{constructor(e,t,n){this.interactor=e;this.options=t;this.services=n;this.interactor.debugLevelEnabled=t.debug,this.interactor.debug("Coday started with debug"),this.configHandler=new hE(e,this.services),this.maxIterations=pyt,this.aiThreadService=new iE(n.user,n.thread.getThreadRepository(t.project),t.project,e),this.aiThreadService.activeThread.subscribe(i=>{!this.context||!i||(this.context.aiThread=i,this.replayThread(i))}),this.aiClientProvider=new Gm(this.interactor,this.services.user,this.services.project,this.services.logger),this.interactor.events.pipe((0,ZZ.filter)(i=>i instanceof Fi||i instanceof Mi||i instanceof Sr),(0,ZZ.filter)(()=>!this.isReplaying)).subscribe(i=>{i instanceof Fi||i instanceof Mi?this.pendingQuestionEvent=i:i instanceof Sr&&this.pendingQuestionEvent&&i.parentKey===this.pendingQuestionEvent.timestamp&&(this.pendingQuestionEvent=null)})}context=null;configHandler;handlerLooper;aiHandler;maxIterations;initialPrompts=[];aiThreadService;killed=!1;isReplaying=!1;pendingQuestionEvent=null;messageQueue=[];aiClientProvider;addUserMessage(e,t){if(this.pendingQuestionEvent){let n=this.pendingQuestionEvent.buildAnswer(t);n.name=e,this.interactor.sendEvent(n)}else{let n=new jt({role:"user",content:[{type:"text",content:t}],name:e});this.interactor.sendEvent(n),this.messageQueue.push({username:e,message:t})}}replay(){let e=this.aiThreadService.getCurrentThread();if(!e){console.log("No active thread to replay");return}this.replayThread(e),!this.options.oneshot&&e.runStatus!=="RUNNING"&&this.interactor.replayLastInvite()}upload(e){let t=this.aiThreadService.getCurrentThread();if(!t){this.interactor.error("No active thread available for upload");return}let n=this.services.user.username;e.forEach(a=>{t.addUserMessage(n,a)});let i=new jt({role:"user",content:e,name:n});this.interactor.sendEvent(i)}async run(){this.initialPrompts=this.options.prompts?[...this.options.prompts]:[],this.interactor.debug(`[CODAY] Starting run with ${this.initialPrompts.length} initial prompts`);try{do{if(this.killed)return;if(await this.initContext(),await this.initThread(),!this.context){this.interactor.error("Could not initialize context \u{1F62D}");break}let e=await this.initCommand();if(!e&&this.options.oneshot)break;let t=this.context?.aiThread;t&&(t.runStatus="RUNNING"),this.context?.addCommands(e),this.context=await this.handlerLooper?.handle(this.context)??null}while(!this.context?.oneshot)}finally{this.stop()}await this.cleanup()}stop(){let e=this.context?.aiThread;e&&(e.runStatus="STOPPED"),this.handlerLooper?.stop(),this.aiThreadService.autoSave()}async cleanup(){try{this.services.agent&&await this.services.agent.kill(),this.aiThreadService.kill(),this.aiClientProvider.cleanup(),this.context=null,this.handlerLooper=void 0,this.aiHandler=void 0,this.messageQueue=[],this.pendingQuestionEvent=null}catch(e){console.error("Error during agent cleanup:",e)}}async kill(){this.killed=!0,this.stop();try{await this.cleanup()}catch(e){console.error("Error during kill cleanup:",e)}this.handlerLooper?.kill(),this.interactor.kill()}async replayThread(e){this.isReplaying=!0;try{let t=(await e.getMessages(void 0,void 0)).messages;if(!t?.length)return;let n=[...t].sort((i,a)=>new Date(i.timestamp).getTime()-new Date(a.timestamp).getTime());for(let i of n)(i instanceof jt||i instanceof hn||i instanceof Tn||i instanceof Fi||i instanceof Mi||i instanceof Sr)&&this.interactor.sendEvent(i);this.interactor.displayText(`Selected thread '${e.name}'`)}finally{this.isReplaying=!1}}async initContext(){if(this.context){this.interactor.debug("[CODAY] Context already initialized, skipping");return}if(this.interactor.debug(`[CODAY] Initializing context for project: ${this.options.project}`),this.context=await this.configHandler.selectProjectHandler.selectProject(this.options.project),!this.context){console.log("[CODAY] ERROR: Failed to create context from selectProject");return}console.log(`[CODAY] Context initialized: '${this.context.project.name}' at ${this.context.project.root}`),this.context&&(this.context.oneshot=this.options.oneshot,this.context.fileReadOnly=this.options.fileReadOnly,this.options.thread&&this.options.project&&(this.context.threadFilesRoot=_ye.join(this.options.configDir,"projects",this.options.project,"threads",`${this.options.thread}-files`),this.interactor.debug(`[CODAY] Thread files root: ${this.context.threadFilesRoot}`)),this.services.aiConfig=new Wk(this.services.user,this.services.project),this.services.aiConfig.initialize(this.context),this.services.mcp.initialize(this.context),this.services.agent=new k4(this.interactor,this.aiClientProvider,this.services,this.context.project.root,this.options.agentFolders),this.aiHandler=new OE(this.interactor,this.services.agent,this.aiThreadService),this.handlerLooper=new DE(this.interactor,this.aiHandler,this.configHandler,this.services),this.aiClientProvider.init(this.context),await this.handlerLooper.init(this.context.project),console.log("[CODAY] Initializing services..."),await this.services.agent.initialize(this.context),console.log("[CODAY] Services initialized"))}async initThread(){if(this.context?.aiThread)return;if(!this.options.thread)throw Error("No thread given, cannot start Coday instance");let e=await this.aiThreadService.select(this.options.thread);this.context&&(this.context.aiThread=e)}async initCommand(){let e;if(this.interactor.debug(`[CODAY] initCommand: ${this.initialPrompts.length} prompts available, oneshot=${this.options.oneshot}`),this.initialPrompts.length)e=this.initialPrompts.shift(),this.interactor.debug(`[CODAY] Using initial prompt: ${e}`),this.initialPrompts.length&&(this.interactor.debug(`[CODAY] Adding ${this.initialPrompts.length} remaining prompts to queue`),this.context?.addCommands(...this.initialPrompts),this.initialPrompts=[]);else if(this.messageQueue.length>0){let t=this.messageQueue.shift();this.interactor.debug(`[CODAY] Consuming queued message from ${t.username}`),e=t.message,this.context&&(this.context.username=t.username)}else this.options.oneshot?this.interactor.debug("[CODAY] No initial prompts and oneshot mode, exiting"):(this.interactor.debug("[CODAY] No initial prompts, waiting for user input"),e=await this.interactor.promptText(moe),this.context&&this.interactor.lastAnswerName&&(this.context.username=this.interactor.lastAnswerName));return e}};function fe(r,...e){console.log(`${new Date().toISOString()} ${r}`,...e)}var dyt=4,yP=class{constructor(e,t){this.aiClient=e;this.threadService=t}process(e,t){this.run(e,t).catch(n=>fe("POST_PROCESSOR",`Unhandled error for thread ${e.id}:`,n))}async run(e,t){let n=e.getUserMessageCount();if(n<dyt){fe("POST_PROCESSOR",`Skipping thread ${e.id}: only ${n} user message(s)`);return}fe("POST_PROCESSOR",`Processing thread ${e.id} (${n} user messages)`);let{messages:i}=await e.getMessages(void 0,void 0),a=i.filter(f=>f instanceof jt).slice(-40).map(f=>{let p=f.role==="user"?"User":f.name||"Assistant",d=f.content.filter(m=>m.type==="text").map(m=>m.content).join(" ").slice(0,500);return`${p}: ${d}`});if(!a.length){fe("POST_PROCESSOR",`Skipping thread ${e.id}: no text messages`);return}let s=`You are given a conversation transcript. Reply ONLY with a valid JSON object (no markdown, no explanation) with two fields:
1419
1419
  - "name": a short title for the conversation (max 60 chars, no quotes)
1420
1420
  - "summary": 2-4 sentences summarising the main topics and outcomes
1421
1421