@whoz-oss/coday-server 0.121.1 → 0.121.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/server.js +1 -1
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -1206,7 +1206,7 @@ Actions:
|
|
|
1206
1206
|
- stop <session>: kill a session and its processes
|
|
1207
1207
|
|
|
1208
1208
|
Use clear, stable session names matching the application role, eg: "backend", "frontend", "agentos", "worker", "db".
|
|
1209
|
-
New sessions always start from the project root directory.`,parameters:{type:"object",properties:{action:{type:"string",enum:["list","status","start","logs","send","stop"],description:"The tmux action to perform."},session:{type:"string",description:"Session name (required for all actions except list)."},command:{type:"string",description:"Command to run (required for start and send actions)."}}},parse:JSON.parse,function:async({action:i,session:a,command:o})=>{try{if(a!==void 0){let s=s5t(a);if(s)return s}switch(i){case"list":try{let{stdout:s}=await Ud("tmux",["list-sessions"]);return s.trim()}catch{return"No tmux sessions running"}case"status":{if(!a)return"Error: session name is required for status";try{return await Ud("tmux",["has-session","-t",a]),"running"}catch{return"stopped"}}case"start":{if(!a)return"Error: session name is required for start";if(!o)return"Error: command is required for start";try{await Ud("tmux",["new-session","-d","-s",a,"-x","220","-y","50","-c",n])}catch{}return await Ud("tmux",["send-keys","-t",a,o,"Enter"]),`Session '${a}' started`}case"logs":{if(!a)return"Error: session name is required for logs";try{let{stdout:s}=await Ud("tmux",["capture-pane","-t",a,"-p","-S","-200"]);return s.trim()}catch{return`Session '${a}' not found`}}case"send":{if(!a)return"Error: session name is required for send";if(!o)return"Error: command is required for send";try{return await Ud("tmux",["send-keys","-t",a,o,"Enter"]),`Command sent to session '${a}'`}catch{return`Session '${a}' not found`}}case"stop":{if(!a)return"Error: session name is required for stop";try{return await Ud("tmux",["kill-session","-t",a]),`Session '${a}' killed`}catch{return`Session '${a}' not found`}}default:return`Unknown action: ${i}`}}catch(s){let c=`tmux error: ${s instanceof Error?s.message:String(s)}`;return this.interactor.error(c),c}}}}]}async kill(){}};var c5t=["push
|
|
1209
|
+
New sessions always start from the project root directory.`,parameters:{type:"object",properties:{action:{type:"string",enum:["list","status","start","logs","send","stop"],description:"The tmux action to perform."},session:{type:"string",description:"Session name (required for all actions except list)."},command:{type:"string",description:"Command to run (required for start and send actions)."}}},parse:JSON.parse,function:async({action:i,session:a,command:o})=>{try{if(a!==void 0){let s=s5t(a);if(s)return s}switch(i){case"list":try{let{stdout:s}=await Ud("tmux",["list-sessions"]);return s.trim()}catch{return"No tmux sessions running"}case"status":{if(!a)return"Error: session name is required for status";try{return await Ud("tmux",["has-session","-t",a]),"running"}catch{return"stopped"}}case"start":{if(!a)return"Error: session name is required for start";if(!o)return"Error: command is required for start";try{await Ud("tmux",["new-session","-d","-s",a,"-x","220","-y","50","-c",n])}catch{}return await Ud("tmux",["send-keys","-t",a,o,"Enter"]),`Session '${a}' started`}case"logs":{if(!a)return"Error: session name is required for logs";try{let{stdout:s}=await Ud("tmux",["capture-pane","-t",a,"-p","-S","-200"]);return s.trim()}catch{return`Session '${a}' not found`}}case"send":{if(!a)return"Error: session name is required for send";if(!o)return"Error: command is required for send";try{return await Ud("tmux",["send-keys","-t",a,o,"Enter"]),`Command sent to session '${a}'`}catch{return`Session '${a}' not found`}}case"stop":{if(!a)return"Error: session name is required for stop";try{return await Ud("tmux",["kill-session","-t",a]),`Session '${a}' killed`}catch{return`Session '${a}' not found`}}default:return`Unknown action: ${i}`}}catch(s){let c=`tmux error: ${s instanceof Error?s.message:String(s)}`;return this.interactor.error(c),c}}}}]}async kill(){}};var c5t=["push -f","push --force","push --tags","reset","&&","clean"],u5t=["list"],t6e=async({params:r,root:e,interactor:t})=>{let n=r.trimStart();if(n.startsWith("worktree ")){let o=n.slice(9).trimStart().split(/\s+/)[0]??"";if(!u5t.includes(o))return`Error: 'git worktree ${o}' is not allowed via the generic git tool. Use the dedicated worktree tools (list_worktrees, create_worktree, remove_worktree) instead.`}let i=`git ${r}`,a=c5t.some(o=>r.includes(o));return await Io({command:i,root:e,interactor:t,requireConfirmation:a})};var I9=class extends Zt{constructor(t,n,i,a){super(t,i,a);this.integrationService=n}static TYPE="GIT";async buildTools(t,n){let i=[];if(!this.integrationService.hasIntegration("GIT"))return i;let a=async({params:s})=>await t6e({params:s,root:t.project.root,interactor:this.interactor}),o={type:"function",function:{name:`${this.name}__git`,description:'Run git command and parameters. Note: worktree subcommands are blocked except "list" \u2014 use the dedicated worktree tools instead.',parameters:{type:"object",properties:{params:{type:"string",description:"Additional command (like add, log, diff, status) and parameters for git, will be composed as `git [params]`."}}},parse:JSON.parse,function:a}};return i.push(o),i}};import*as su from"node:path";import*as nc from"node:fs/promises";function r6e(r){return r.replace(/[^a-zA-Z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}async function l5t(r){let e=su.join(r,".git");try{return(await nc.lstat(e)).isFile()}catch{return!1}}function n6e(r,e){return`${r}__${e}`}function f5t(r,e){let t=`${r}__`;return e.startsWith(t)?e.slice(t.length):null}var D9=class extends Zt{constructor(t,n,i,a,o){super(t,i,a);this.integrationService=n;this.projectService=o}static TYPE="GIT_WORKTREE";async buildTools(t,n){let i=[];if(!this.integrationService.hasIntegration("GIT_WORKTREE"))return i;if(!this.projectService)return this.interactor.debug("[WORKTREE] ProjectService not available, worktree tools disabled"),i;let a=this.projectService,o=t.project.root,s=t.project.name,c=su.dirname(o),u=await l5t(o),l={type:"function",function:{name:`${this.name}__list_worktrees`,description:"Lists all git worktrees for the current repository, with their Coday project registration status.",parameters:{type:"object",properties:{}},parse:JSON.parse,function:async()=>{let p=await Io({command:"git worktree list --porcelain",root:o,interactor:this.interactor}),d=[];for(let h of p.split(/\n\n+/).filter(Boolean)){let g=h.trim().split(`
|
|
1210
1210
|
`),v=g.find(S=>S.startsWith("worktree ")),y=g.find(S=>S.startsWith("branch "));if(!v)continue;let x=v.replace("worktree ","").trim(),_=y?y.replace("branch refs/heads/","").trim():"(detached)";d.push({path:x,branch:_})}let m=d[0]?.path;return JSON.stringify(d.map(h=>{let g=h.path===m,v=su.basename(h.path),y=g?s:v;return{branch:h.branch,path:h.path,projectName:y,isMain:g}}),null,2)}}};if(i.push(l),!u){let p={type:"function",function:{name:`${this.name}__create_worktree`,description:"Creates a git worktree on the given branch (creates the branch if it does not exist) and registers it as a Coday sub-project. Returns projectName, worktreePath and branch.",parameters:{type:"object",properties:{branch:{type:"string",description:"Branch name to create or checkout (e.g., feat/my-feature)"}},required:["branch"]},parse:JSON.parse,function:async({branch:d})=>{if(!/^[a-zA-Z0-9._/-]+$/.test(d))return`Error: branch name contains invalid characters: ${d}`;let m=r6e(d),h=su.join(c,`${s}__${m}`),g=n6e(s,m);try{return await nc.access(h),`Error: worktree path already exists: ${h}`}catch{}let v=await Io({command:`git worktree add "${h}" -b "${d}"`,root:o,interactor:this.interactor});if(v.startsWith("Command failed:")){try{await nc.rmdir(h)}catch{}if(v=await Io({command:`git worktree add "${h}" "${d}"`,root:o,interactor:this.interactor}),v.startsWith("Command failed:"))return`Failed to create worktree:
|
|
1211
1211
|
${v}`}await a.registerWorktreeProject(g,h,s),this.interactor.debug(`[WORKTREE] Registered project '${g}' at ${h}`);let y=this.config?.postCreateScript;if(typeof y=="string"&&y.trim()){let x=su.resolve(o,y),_,S;try{await nc.access(x,nc.constants.X_OK);let C=await Io({command:`"${x}"`,root:h,interactor:this.interactor});C.startsWith("Command failed:")?(_=`postCreateScript failed: ${C}`,this.interactor.warn(`[WORKTREE] ${_}`)):(S=C,this.interactor.displayText(`[WORKTREE] postCreateScript completed:
|
|
1212
1212
|
${C}`))}catch{_=`postCreateScript not found or not executable: ${x}`,this.interactor.warn(`[WORKTREE] ${_}`)}return JSON.stringify({projectName:g,worktreePath:h,branch:d,..._?{warning:_}:{},...S?{postCreateScriptOutput:S}:{}})}return JSON.stringify({projectName:g,worktreePath:h,branch:d})}}};i.push(p)}let f={type:"function",function:{name:`${this.name}__remove_worktree`,description:"Removes a git worktree by branch name and cleans up the associated Coday project entry. Use force=true to remove even with uncommitted changes. Optionally provide projectName (from list_worktrees) to locate the actual directory when the path does not match the branch-derived name (e.g. legacy worktrees).",parameters:{type:"object",properties:{branch:{type:"string",description:"Branch whose worktree to remove"},projectName:{type:"string",description:"Optional. The Coday project name for the worktree (as shown by list_worktrees). When provided, the actual directory is resolved from this name instead of being derived from the branch name. Useful for legacy worktrees whose directory name does not match the current naming convention."},force:{type:"boolean",description:"Force removal even if the worktree has uncommitted changes"}},required:["branch"]},parse:JSON.parse,function:async({branch:p,projectName:d,force:m})=>{if(!/^[a-zA-Z0-9._/-]+$/.test(p))return`Error: branch name contains invalid characters: ${p}`;let h=r6e(p),g,v;if(d){let _=f5t(s,d);if(_===null)return`Error: projectName "${d}" does not start with the expected prefix "${s}__". Use list_worktrees to get the correct projectName.`;v=_,g=d}else v=h,g=n6e(s,h);let y=su.join(c,`${s}__${v}`);if(y===o)return"Error: cannot remove the main worktree";let x=!1;try{x=(await nc.stat(y)).isDirectory()}catch{}if(x){let _=await Io({command:`git worktree remove "${y}"${m?" --force":""}`,root:o,interactor:this.interactor});if(_.startsWith("Command failed:"))return`Failed to remove worktree:
|