@task-shepherd/agent 1.0.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/README.md +297 -0
- package/dist/cli/index.js +154 -0
- package/dist/graphql/introspection.json +44158 -0
- package/dist/index.js +1 -0
- package/dist/meta.json +2823 -0
- package/mcp-agent/dist/index.d.ts +2 -0
- package/mcp-agent/dist/index.js +916 -0
- package/mcp-agent/dist/test-schema.d.ts +6 -0
- package/mcp-agent/dist/test-schema.js +95 -0
- package/mcp-agent/dist/types.d.ts +1893 -0
- package/mcp-agent/dist/types.js +139 -0
- package/package.json +125 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";var $t=Object.create;var ue=Object.defineProperty;var Vt=Object.getOwnPropertyDescriptor;var Kt=Object.getOwnPropertyNames;var zt=Object.getPrototypeOf,qt=Object.prototype.hasOwnProperty;var A=(a,t)=>()=>(a&&(t=a(a=0)),t);var Bt=(a,t)=>()=>(t||a((t={exports:{}}).exports,t),t.exports),Q=(a,t)=>{for(var e in t)ue(a,e,{get:t[e],enumerable:!0})},it=(a,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Kt(t))!qt.call(a,s)&&s!==e&&ue(a,s,{get:()=>t[s],enumerable:!(r=Vt(t,s))||r.enumerable});return a};var h=(a,t,e)=>(e=a!=null?$t(zt(a)):{},it(t||!a||!a.__esModule?ue(e,"default",{value:a,enumerable:!0}):e,a)),ot=a=>it(ue({},"__esModule",{value:!0}),a);var g,Gt,at,Jt,Yt,Qt,Xt,Zt,er,tr,rr,sr,nr,ir,or,ar,cr,ct,Oe,Le=A(()=>{"use strict";g=require("zod"),Gt=g.z.enum(["development","staging","production","test"]),at=g.z.enum(["error","warn","info","debug","verbose"]),Jt=g.z.object({port:g.z.number().int().min(1).max(65535).default(8547),host:g.z.string().default("localhost"),environment:Gt.default("development"),logLevel:at.default("info"),requestTimeout:g.z.number().int().min(1e3).max(6e5).default(3e4),maxRequestSize:g.z.string().default("10mb"),enableCors:g.z.boolean().default(!0),enableHelmet:g.z.boolean().default(!0),enableCompression:g.z.boolean().default(!0)}),Yt=g.z.object({apiUrl:g.z.string().url(),apiKey:g.z.string().optional(),timeout:g.z.number().int().min(1e3).max(6e4).default(3e4),retries:g.z.number().int().min(0).max(10).default(3),retryDelay:g.z.number().int().min(100).max(1e4).default(1e3)}),Qt=g.z.object({url:g.z.string().default("redis://localhost:6379"),host:g.z.string().optional(),port:g.z.number().int().min(1).max(65535).optional(),password:g.z.string().optional(),database:g.z.number().int().min(0).max(15).default(0),keyPrefix:g.z.string().default("ai-agent:"),connectTimeout:g.z.number().int().min(1e3).max(3e4).default(1e4),maxRetriesPerRequest:g.z.number().int().min(0).max(10).default(3)}),Xt=g.z.object({apiKey:g.z.string().optional(),baseUrl:g.z.string().url().optional(),model:g.z.string().default("claude-3-5-sonnet-20241022"),maxRetries:g.z.number().int().min(0).max(10).default(3),timeoutMs:g.z.number().int().min(1e3).max(3e5).default(6e4),maxTokens:g.z.number().int().min(100).max(8192).default(4096),temperature:g.z.number().min(0).max(1).default(.7),commandPath:g.z.string().default("claude")}),Zt=g.z.object({tokenLimit:g.z.number().int().min(1e3).max(1e6).default(1e4),requestsPerMinute:g.z.number().int().min(1).max(1e3).default(60),requestsPerHour:g.z.number().int().min(1).max(1e4).default(1e3),burstLimit:g.z.number().int().min(1).max(100).default(10),windowSizeMs:g.z.number().int().min(1e3).max(36e5).default(6e4)}),er=g.z.enum(["project_review","implementation_plan","story_implementation","task_completion","code_review","review_application"]),tr=g.z.object({maxConcurrentJobs:g.z.number().int().min(1).max(10).default(3),jobTimeout:g.z.number().int().min(3e4).max(18e5).default(3e5),retryAttempts:g.z.number().int().min(0).max(5).default(2),retryDelay:g.z.number().int().min(1e3).max(6e4).default(5e3),healthCheckInterval:g.z.number().int().min(5e3).max(3e5).default(3e4),enabledCapabilities:g.z.array(er).default(["project_review","implementation_plan","story_implementation","task_completion","code_review","review_application"])}),rr=g.z.object({path:g.z.string().default("./data/ai-agent.db"),backupEnabled:g.z.boolean().default(!0),backupInterval:g.z.number().int().min(36e5).max(864e5).default(36e5),maxBackups:g.z.number().int().min(1).max(30).default(7),vacuumInterval:g.z.number().int().min(864e5).max(6048e5).default(864e5)}),sr=g.z.object({enableApiKeyAuth:g.z.boolean().default(!1),apiKeys:g.z.array(g.z.string()).default([]),allowedOrigins:g.z.array(g.z.string()).default(["http://localhost:3000","http://localhost:5173"]),enableHttps:g.z.boolean().default(!1),httpsOptions:g.z.object({keyPath:g.z.string().optional(),certPath:g.z.string().optional()}).optional(),sessionSecret:g.z.string().min(32).optional()}),nr=g.z.object({enableMetrics:g.z.boolean().default(!0),metricsPort:g.z.number().int().min(1).max(65535).default(9090),enableHealthChecks:g.z.boolean().default(!0),healthCheckPath:g.z.string().default("/health"),enableProfiling:g.z.boolean().default(!1)}),ir=g.z.object({level:at.default("info"),enableConsole:g.z.boolean().default(!0),enableFile:g.z.boolean().default(!0),logDirectory:g.z.string().default("./logs"),maxFileSize:g.z.string().default("100MB"),maxFiles:g.z.number().int().min(1).max(100).default(10),datePattern:g.z.string().default("YYYY-MM-DD"),enableRotation:g.z.boolean().default(!0),enableJson:g.z.boolean().default(!1)}),or=g.z.object({enableWebInterface:g.z.boolean().default(!0),enableApiDocumentation:g.z.boolean().default(!0),enableMetricsApi:g.z.boolean().default(!0),enableWorkspaceAnalysis:g.z.boolean().default(!0),enableMultiWorkspace:g.z.boolean().default(!0),enableClaudeApiIntegration:g.z.boolean().default(!0),enableExperimentalFeatures:g.z.boolean().default(!1)}),ar=g.z.object({id:g.z.string().min(1),name:g.z.string().min(1),domain:g.z.string().optional(),apiUrl:g.z.string().url(),wsUrl:g.z.string().url().optional(),apiKey:g.z.string().min(1),enabled:g.z.boolean().default(!0),metadata:g.z.object({description:g.z.string().optional(),color:g.z.string().optional(),logo:g.z.string().url().optional(),addedAt:g.z.string().optional()}).optional()}),cr=g.z.object({setupCompleted:g.z.boolean().default(!1),defaultOrganization:g.z.string().optional(),organizations:g.z.record(g.z.string(),ar).default({})}),ct=g.z.object({server:Jt,taskShepherd:Yt,redis:Qt,claude:Xt,rateLimit:Zt,worker:tr,database:rr,security:sr,monitoring:nr,logging:ir,features:or,multiOrg:cr.default({})}),Oe={server:{port:8547,host:"localhost",environment:"development",logLevel:"info",requestTimeout:3e4,maxRequestSize:"10mb",enableCors:!0,enableHelmet:!0,enableCompression:!0},taskShepherd:{apiUrl:"",timeout:3e4,retries:3,retryDelay:1e3},redis:{url:"redis://localhost:6379",database:0,keyPrefix:"ai-agent:",connectTimeout:1e4,maxRetriesPerRequest:3},claude:{model:"claude-3-5-sonnet-20241022",maxRetries:3,timeoutMs:6e4,maxTokens:4096,temperature:.7,commandPath:"claude"},rateLimit:{tokenLimit:1e4,requestsPerMinute:60,requestsPerHour:1e3,burstLimit:10,windowSizeMs:6e4},worker:{maxConcurrentJobs:3,jobTimeout:3e5,retryAttempts:2,retryDelay:5e3,healthCheckInterval:3e4,enabledCapabilities:["project_review","implementation_plan","story_implementation","task_completion","code_review","review_application"]},database:{path:"./data/ai-agent.db",backupEnabled:!0,backupInterval:36e5,maxBackups:7,vacuumInterval:864e5},security:{enableApiKeyAuth:!1,apiKeys:[],allowedOrigins:["http://localhost:3000","http://localhost:5173"],enableHttps:!1},monitoring:{enableMetrics:!0,metricsPort:9090,enableHealthChecks:!0,healthCheckPath:"/health",enableProfiling:!1},logging:{level:"info",enableConsole:!0,enableFile:!0,logDirectory:"./logs",maxFileSize:"100MB",maxFiles:10,datePattern:"YYYY-MM-DD",enableRotation:!0,enableJson:!1},features:{enableWebInterface:!0,enableApiDocumentation:!0,enableMetricsApi:!0,enableWorkspaceAnalysis:!0,enableMultiWorkspace:!0,enableClaudeApiIntegration:!0,enableExperimentalFeatures:!1},multiOrg:{setupCompleted:!1,organizations:{}}}});function He(a){return Fe||(Fe=new Me(a)),Fe}function ge(){return He().getConfig()}var q,$,lt,Me,Fe,me=A(()=>{"use strict";q=h(require("fs")),$=h(require("path")),lt=require("events");Le();Me=class extends lt.EventEmitter{constructor(e={}){super();this.watchers=new Map;this.lastValidation=null;this.options={configDir:$.resolve(process.cwd(),"config"),environment:e.environment||"production",enableHotReload:!1,hotReloadInterval:1e3,additionalConfigFiles:[],strictValidation:!1,...e},this.config={...Oe},this.configMetadata={config:this.config,sources:{},validatedAt:new Date,environment:this.options.environment},this.loadConfiguration()}getConfig(){return{...this.config}}getConfigWithMetadata(){return{...this.configMetadata}}get(e){return this.config[e]}getLastValidation(){return this.lastValidation}async reloadConfiguration(){return this.loadConfiguration()}validateConfiguration(){return this.validateConfig(this.config)}loadConfiguration(){try{let e={},r={...Oe};this.trackConfigSources(r,e,"default","built-in defaults",0);let s=this.loadConfigFile("config.json",e,1);s&&(r=this.mergeConfig(r,s));let n=this.loadConfigFile(`config.${this.options.environment}.json`,e,2);n&&(r=this.mergeConfig(r,n)),this.options.additionalConfigFiles.forEach((l,u)=>{let m=this.loadConfigFile(l,e,3+u);m&&(r=this.mergeConfig(r,m))});let i=this.loadEnvironmentOverrides();Object.keys(i).length>0&&(r=this.mergeConfig(r,i),this.trackConfigSources(i,e,"environment","environment variables",100));let o=this.validateConfig(r);if(o.success&&o.data){let l={...this.config};this.config=o.data,this.configMetadata={config:this.config,sources:e,validatedAt:new Date,environment:this.options.environment},JSON.stringify(l)!==JSON.stringify(this.config)&&this.emit("configurationChanged",{oldConfig:l,newConfig:this.config,sources:e})}return this.lastValidation=o,this.options.enableHotReload&&this.setupHotReloading(),o}catch(e){return console.error("Critical error in configuration loading:",e),{success:!1,errors:[{path:"configuration",message:`Configuration loading failed: ${e instanceof Error?e.message:"Unknown error"}`,code:"CONFIG_LOAD_ERROR"}],warnings:[]}}}loadConfigFile(e,r,s){let n=$.isAbsolute(e)?e:$.join(this.options.configDir,e);try{if(!q.existsSync(n))return null;let i=q.readFileSync(n,"utf-8"),o=JSON.parse(i);return this.trackConfigSources(o,r,"file",n,s),o}catch(i){return console.warn(`Failed to load configuration file ${n}:`,i),null}}loadEnvironmentOverrides(){let e={};if(process.env.PORT&&(e.server={...e.server,port:parseInt(process.env.PORT)}),process.env.HOST&&(e.server={...e.server,host:process.env.HOST}),process.env.LOG_LEVEL&&(e.server={...e.server,logLevel:process.env.LOG_LEVEL}),e.server={...e.server,environment:"production"},process.env.TASK_SHEPHERD_API_URL&&(e.taskShepherd={...e.taskShepherd,apiUrl:process.env.TASK_SHEPHERD_API_URL}),process.env.TASK_SHEPHERD_API_KEY&&(e.taskShepherd={...e.taskShepherd,apiKey:process.env.TASK_SHEPHERD_API_KEY}),process.env.TASK_SHEPHERD_WS_URL&&(e.taskShepherd={...e.taskShepherd,wsUrl:process.env.TASK_SHEPHERD_WS_URL}),process.env.TASK_SHEPHERD_ENABLE_WEBSOCKET!==void 0&&(e.taskShepherd={...e.taskShepherd,enableWebSocket:process.env.TASK_SHEPHERD_ENABLE_WEBSOCKET==="true"}),process.env.REDIS_URL&&(e.redis={...e.redis,url:process.env.REDIS_URL}),process.env.REDIS_HOST&&(e.redis={...e.redis,host:process.env.REDIS_HOST}),process.env.REDIS_PORT&&(e.redis={...e.redis,port:parseInt(process.env.REDIS_PORT)}),process.env.REDIS_PASSWORD&&(e.redis={...e.redis,password:process.env.REDIS_PASSWORD}),process.env.ANTHROPIC_API_KEY&&(e.claude={...e.claude,apiKey:process.env.ANTHROPIC_API_KEY}),process.env.ANTHROPIC_BASE_URL&&(e.claude={...e.claude,baseUrl:process.env.ANTHROPIC_BASE_URL}),process.env.CLAUDE_MODEL&&(e.claude={...e.claude,model:process.env.CLAUDE_MODEL}),process.env.CLAUDE_COMMAND_PATH&&(e.claude={...e.claude,commandPath:process.env.CLAUDE_COMMAND_PATH}),process.env.MAX_CONCURRENT_JOBS&&(e.worker={...e.worker,maxConcurrentJobs:parseInt(process.env.MAX_CONCURRENT_JOBS)}),process.env.JOB_TIMEOUT&&(e.worker={...e.worker,jobTimeout:parseInt(process.env.JOB_TIMEOUT)}),process.env.CAPABILITIES||process.env.AGENT_CAPABILITIES){let r=(process.env.CAPABILITIES||process.env.AGENT_CAPABILITIES||"").split(",").map(s=>s.trim());e.worker={...e.worker,enabledCapabilities:r}}if(process.env.TOKEN_RATE_LIMIT&&(e.rateLimit={...e.rateLimit,tokenLimit:parseInt(process.env.TOKEN_RATE_LIMIT)}),process.env.DB_PATH&&(e.database={...e.database,path:process.env.DB_PATH}),process.env.API_KEYS){let r=process.env.API_KEYS.split(",").map(s=>s.trim());e.security={...e.security,apiKeys:r,enableApiKeyAuth:!0}}return e}trackConfigSources(e,r,s,n,i){let o=(l,u="")=>{for(let[m,p]of Object.entries(l)){let f=u?`${u}.${m}`:m;p&&typeof p=="object"&&!Array.isArray(p)?o(p,f):r[f]={type:s,source:n,priority:i}}};o(e)}mergeConfig(e,r){let s={...e};for(let[n,i]of Object.entries(r))i&&typeof i=="object"&&!Array.isArray(i)?s[n]=this.mergeConfig(e[n]||{},i):s[n]=i;return s}validateConfig(e){let r=ct.safeParse(e);return r.success?{success:!0,data:r.data,errors:[],warnings:this.generateWarnings(r.data)}:{success:!1,errors:r.error.issues.map(s=>({path:s.path.join("."),message:s.message,code:s.code})),warnings:[]}}generateWarnings(e){let r=[];return e.server.environment==="development"&&(!e.claude.apiKey&&!e.claude.commandPath&&r.push({path:"claude.apiKey",message:"No Claude API key or command path configured",suggestion:"Set ANTHROPIC_API_KEY environment variable or ensure Claude CLI is installed"}),e.security.enableHttps&&r.push({path:"security.enableHttps",message:"HTTPS enabled in development mode",suggestion:"Consider disabling HTTPS for local development"})),e.server.environment==="production"&&(e.security.enableHttps||r.push({path:"security.enableHttps",message:"HTTPS disabled in production",suggestion:"Enable HTTPS for production deployment"}),e.security.enableApiKeyAuth||r.push({path:"security.enableApiKeyAuth",message:"API key authentication disabled in production",suggestion:"Enable API key authentication for production security"}),(e.server.logLevel==="debug"||e.server.logLevel==="verbose")&&r.push({path:"server.logLevel",message:"Debug logging enabled in production",suggestion:'Use "info" or "warn" log level for production'})),r}setupHotReloading(){this.watchers.forEach(r=>r.close()),this.watchers.clear(),[$.join(this.options.configDir,"config.json"),$.join(this.options.configDir,`config.${this.options.environment}.json`),...this.options.additionalConfigFiles].forEach(r=>{if(q.existsSync(r)){let s=q.watch(r,n=>{n==="change"&&setTimeout(()=>{console.log(`Configuration file changed: ${r}`);let i=this.loadConfiguration();i.success?(console.log("Configuration reloaded successfully"),this.emit("configurationReloaded",this.config)):(console.error("Configuration reload failed:",i.errors),this.emit("configurationError",i.errors))},this.options.hotReloadInterval)});this.watchers.set(r,s)}})}destroy(){this.watchers.forEach(e=>e.close()),this.watchers.clear(),this.removeAllListeners()}},Fe=null});var pt={};Q(pt,{detectClaude:()=>lr,detectClaudeSync:()=>Ue,getClaudeCommandPath:()=>pr});function lr(a="claude"){return Ue(a)}function Ue(a="claude"){if(ie(a))return{available:!0,path:a,method:"direct"};if(a==="claude"){let t=[process.env.HOME+"/.claude/local/claude","/usr/local/bin/claude","/opt/homebrew/bin/claude"].filter(e=>e);for(let e of t)if(ie(e))return{available:!0,path:e,method:"direct"};try{let e=(0,he.execSync)('bash -c "which claude"',{encoding:"utf8",stdio:"pipe"}).trim();if(e&&!e.includes("aliased to")&&ie(e))return{available:!0,path:e,method:"which"};if(e.includes("aliased to ")){let r=e.split("aliased to ")[1];if(r&&ie(r))return{available:!0,path:r,method:"which"}}}catch{}try{let r=(0,he.execSync)("where claude",{encoding:"utf8",stdio:"pipe"}).trim().split(`
|
|
3
|
+
`)[0];if(r&&ie(r))return{available:!0,path:r,method:"where"}}catch{}}return{available:!1,method:"none"}}function ie(a){try{return(0,he.execSync)(`"${a}" --version`,{stdio:"pipe"}),!0}catch{return!1}}function pr(a="claude"){return Ue(a).path||a}var he,dt=A(()=>{"use strict";he=require("child_process")});function gt(a){return $e.validateConfiguration(a)}var V,ut,$e,Ve=A(()=>{"use strict";V=h(require("fs")),ut=h(require("path")),$e=class{static validateConfiguration(t){let e=[],r=[];return this.isMultiOrgMode()?{valid:!0,errors:[],warnings:[]}:(this.validateServerConfig(t,e,r),this.validateTaskShepherdConfig(t,e,r),this.validateRedisConfig(t,e,r),this.validateClaudeConfig(t,e,r),this.validateDatabaseConfig(t,e,r),this.validateSecurityConfig(t,e,r),this.validateLoggingConfig(t,e,r),this.validateConfigurationDependencies(t,e,r),{valid:e.length===0,errors:e,warnings:r})}static isMultiOrgMode(){let t=require("fs"),e=require("path"),r=require("os"),s=e.join(r.homedir(),".task-shepherd-agent","config.json");return t.existsSync(s)}static validateServerConfig(t,e,r){let{server:s}=t;s.port<1024&&typeof process.getuid=="function"&&process.getuid()!==0&&r.push({path:"server.port",message:`Port ${s.port} requires root privileges`,code:"PRIVILEGED_PORT",severity:"warning",suggestion:"Use a port number above 1024 for non-root users"}),s.environment==="production"&&(s.logLevel==="debug"||s.logLevel==="verbose")&&r.push({path:"server.logLevel",message:"Debug logging enabled in production",code:"PRODUCTION_DEBUG_LOG",severity:"warning",suggestion:'Use "info" or "warn" log level for production'}),s.requestTimeout<5e3&&r.push({path:"server.requestTimeout",message:"Request timeout is very low",code:"LOW_REQUEST_TIMEOUT",severity:"warning",suggestion:"Consider increasing timeout for AI operations"})}static validateTaskShepherdConfig(t,e,r){let{taskShepherd:s}=t;if(s){try{new URL(s.apiUrl)}catch{e.push({path:"taskShepherd.apiUrl",message:"Invalid Task Shepherd API URL format",code:"INVALID_URL",severity:"error",suggestion:"Provide a valid HTTP/HTTPS URL"})}t.server.environment==="production"&&!s.apiKey&&r.push({path:"taskShepherd.apiKey",message:"No API key configured for production",code:"MISSING_API_KEY",severity:"warning",suggestion:"Set TASK_SHEPHERD_API_KEY environment variable"}),s.timeout>6e4&&r.push({path:"taskShepherd.timeout",message:"Task Shepherd API timeout is very high",code:"HIGH_TIMEOUT",severity:"warning",suggestion:"Consider reducing timeout to improve responsiveness"})}}static validateRedisConfig(t,e,r){let{redis:s}=t;if(!s){e.push({path:"redis",message:"Redis configuration is missing",code:"MISSING_REDIS_CONFIG",severity:"error"});return}s.url&&!s.url.startsWith("redis://")&&!s.url.startsWith("rediss://")&&e.push({path:"redis.url",message:"Invalid Redis URL format",code:"INVALID_REDIS_URL",severity:"error",suggestion:"Use redis:// or rediss:// protocol"}),(s.database<0||s.database>15)&&e.push({path:"redis.database",message:"Redis database number must be between 0 and 15",code:"INVALID_DB_NUMBER",severity:"error"}),s.connectTimeout<1e3&&r.push({path:"redis.connectTimeout",message:"Redis connection timeout is very low",code:"LOW_CONNECT_TIMEOUT",severity:"warning",suggestion:"Consider increasing timeout for reliable connections"})}static validateClaudeConfig(t,e,r){let{claude:s}=t;if(!s.apiKey&&!this.isClaudeCliAvailable(s.commandPath)&&e.push({path:"claude.apiKey",message:"No Claude API key configured and CLI not available",code:"MISSING_CLAUDE_AUTH",severity:"error",suggestion:"Set ANTHROPIC_API_KEY or install Claude CLI"}),s.baseUrl)try{new URL(s.baseUrl)}catch{e.push({path:"claude.baseUrl",message:"Invalid Claude base URL format",code:"INVALID_BASE_URL",severity:"error"})}let n=["claude-3-5-sonnet-20241022","claude-3-haiku-20240307","claude-3-opus-20240229"];s.model&&!n.includes(s.model)&&r.push({path:"claude.model",message:"Unknown Claude model specified",code:"UNKNOWN_MODEL",severity:"warning",suggestion:`Use one of: ${n.join(", ")}`}),s.timeoutMs<3e4&&r.push({path:"claude.timeoutMs",message:"Claude timeout is very low for AI operations",code:"LOW_AI_TIMEOUT",severity:"warning",suggestion:"Consider at least 30 seconds for AI operations"}),(s.temperature<0||s.temperature>1)&&e.push({path:"claude.temperature",message:"Claude temperature must be between 0 and 1",code:"INVALID_TEMPERATURE",severity:"error"})}static validateDatabaseConfig(t,e,r){let{database:s}=t;if(!s){e.push({path:"database",message:"Database configuration is missing",code:"MISSING_DATABASE_CONFIG",severity:"error"});return}let n=ut.dirname(s.path);try{V.existsSync(n)||V.mkdirSync(n,{recursive:!0})}catch{e.push({path:"database.path",message:`Cannot create database directory: ${n}`,code:"INVALID_DB_PATH",severity:"error",suggestion:"Ensure the directory is writable"})}s.backupEnabled&&s.maxBackups<1&&e.push({path:"database.maxBackups",message:"Maximum backups must be at least 1 when backup is enabled",code:"INVALID_BACKUP_COUNT",severity:"error"}),s.backupEnabled&&s.backupInterval<6e4&&r.push({path:"database.backupInterval",message:"Backup interval is very frequent",code:"FREQUENT_BACKUP",severity:"warning",suggestion:"Consider longer intervals to reduce I/O overhead"})}static validateSecurityConfig(t,e,r){let{security:s}=t;if(!s){e.push({path:"security",message:"Security configuration is missing",code:"MISSING_SECURITY_CONFIG",severity:"error"});return}if(t.server.environment==="production"&&(s.enableHttps||r.push({path:"security.enableHttps",message:"HTTPS disabled in production",code:"PRODUCTION_HTTP",severity:"warning",suggestion:"Enable HTTPS for production deployment"}),s.enableApiKeyAuth||r.push({path:"security.enableApiKeyAuth",message:"API key authentication disabled in production",code:"PRODUCTION_NO_AUTH",severity:"warning",suggestion:"Enable API key authentication for security"})),s.enableHttps&&s.httpsOptions){let{keyPath:n,certPath:i}=s.httpsOptions;n&&!V.existsSync(n)&&e.push({path:"security.httpsOptions.keyPath",message:"SSL private key file not found",code:"MISSING_SSL_KEY",severity:"error"}),i&&!V.existsSync(i)&&e.push({path:"security.httpsOptions.certPath",message:"SSL certificate file not found",code:"MISSING_SSL_CERT",severity:"error"})}s.enableApiKeyAuth&&s.apiKeys.length===0&&e.push({path:"security.apiKeys",message:"API key authentication enabled but no keys configured",code:"NO_API_KEYS",severity:"error",suggestion:"Configure API keys or disable authentication"}),s.sessionSecret&&s.sessionSecret.length<32&&r.push({path:"security.sessionSecret",message:"Session secret should be at least 32 characters",code:"WEAK_SESSION_SECRET",severity:"warning",suggestion:"Use a longer, randomly generated secret"})}static validateLoggingConfig(t,e,r){let{logging:s}=t;if(s.enableFile)try{V.existsSync(s.logDirectory)||V.mkdirSync(s.logDirectory,{recursive:!0})}catch{e.push({path:"logging.logDirectory",message:`Cannot create log directory: ${s.logDirectory}`,code:"INVALID_LOG_DIR",severity:"error",suggestion:"Ensure the directory is writable"})}s.maxFiles<1&&e.push({path:"logging.maxFiles",message:"Maximum log files must be at least 1",code:"INVALID_MAX_FILES",severity:"error"}),/^(\d+)(KB|MB|GB)$/i.test(s.maxFileSize)||e.push({path:"logging.maxFileSize",message:"Invalid log file size format",code:"INVALID_FILE_SIZE",severity:"error",suggestion:'Use format like "100MB", "1GB", etc.'})}static validateConfigurationDependencies(t,e,r){let s=t.worker.maxConcurrentJobs,n=t.rateLimit.requestsPerMinute;s*10>n&&r.push({path:"rateLimit.requestsPerMinute",message:"Rate limit may be too low for configured concurrent jobs",code:"RATE_LIMIT_TOO_LOW",severity:"warning",suggestion:"Increase rate limit or reduce concurrent jobs"}),t.monitoring.metricsPort===t.server.port&&e.push({path:"monitoring.metricsPort",message:"Metrics port conflicts with server port",code:"PORT_CONFLICT",severity:"error",suggestion:"Use different ports for metrics and main server"}),t.features.enableMetricsApi&&!t.monitoring.enableMetrics&&r.push({path:"features.enableMetricsApi",message:"Metrics API enabled but metrics collection disabled",code:"METRICS_DEPENDENCY",severity:"warning",suggestion:"Enable metrics collection or disable metrics API"})}static isClaudeCliAvailable(t){let{detectClaudeSync:e}=(dt(),ot(pt));return e(t).available}}});function dr(){let a=ge();return{port:a.server.port,nodeEnv:a.server.environment,taskShepherdApiUrl:a.taskShepherd.apiUrl,taskShepherdApiKey:a.taskShepherd.apiKey,redisUrl:a.redis.url,claudeCommandPath:a.claude.commandPath,claudeApiKey:a.claude.apiKey,claudeBaseUrl:a.claude.baseUrl,claudeModel:a.claude.model,claudeMaxRetries:a.claude.maxRetries,claudeTimeoutMs:a.claude.timeoutMs,maxConcurrentJobs:a.worker.maxConcurrentJobs,tokenRateLimit:a.rateLimit.tokenLimit,logLevel:a.server.logLevel}}var Ke,ur,X,mt=A(()=>{"use strict";Le();me();Ve();me();Ve();Ke=dr(),ur=He(),X={warnings:[]};if(X=gt(ur.getConfig()),!X.valid&&(console.error("Configuration validation failed:"),X.errors.forEach(a=>{console.error(` - ${a.path}: ${a.message}`)}),X.errors.some(a=>a.severity==="error")))throw new Error("Configuration contains critical errors. Please fix them before starting the service.");X.warnings.length>0&&(console.warn("Configuration warnings:"),X.warnings.forEach(a=>{console.warn(` - ${a.path}: ${a.message}`),a.suggestion&&console.warn(` Suggestion: ${a.suggestion}`)}))});var L,c,R=A(()=>{"use strict";L=h(require("winston"));mt();c=L.default.createLogger({level:Ke.nodeEnv==="development"?"debug":"info",format:L.default.format.combine(L.default.format.timestamp(),L.default.format.errors({stack:!0}),L.default.format.json()),defaultMeta:{service:"agent"},transports:[new L.default.transports.File({filename:"logs/error.log",level:"error",maxsize:100*1024*1024,maxFiles:5,tailable:!0}),new L.default.transports.File({filename:"logs/combined.log",maxsize:100*1024*1024,maxFiles:5,tailable:!0})]});Ke.nodeEnv!=="production"&&c.add(new L.default.transports.Console({format:L.default.format.combine(L.default.format.colorize(),L.default.format.simple())}))});var vt=Bt((cs,gr)=>{gr.exports={name:"@task-shepherd/agent",version:"1.0.2",description:"Simplified AI agent service for Task Shepherd project analysis",main:"dist/index.js",bin:{"task-shepherd-agent":"dist/cli/index.js"},files:["dist","mcp-agent","README.md","LICENSE.md"],engines:{node:">=18.0.0"},scripts:{dev:"ts-node-dev --respawn --transpile-only src/index.ts",build:"node build.js","build:dev":"node build-dev.js","build:tsc":"tsc","build:prod":"npm run build && npm run build:web",start:"node dist/index.js","type-check":"tsc --noEmit",lint:"eslint src/**/*.ts --fix",kill:"(lsof -ti:8547,8548 | xargs kill -9 2>/dev/null) || pkill -f 'node.*agent|ts-node-dev.*agent' || echo 'AI agent service stopped'",test:"jest",prepublishOnly:"npm run build","test:workqueue":"jest --config jest.workqueue.config.js","test:workqueue:watch":"jest --config jest.workqueue.config.js --watch","test:workqueue:coverage":"jest --config jest.workqueue.config.js --coverage","dev:web":"cd web && npm run dev","build:web":"cd web && npm run build","dev:all":'concurrently "npm run dev" "npm run dev:web"',codegen:"graphql-codegen --config codegen.yml","agent:init":"ts-node src/cli/index.ts init","agent:status":"ts-node src/cli/index.ts status","reset:config":"node reset-org-config.js","agent:identity:show":"ts-node src/cli/index.ts identity show","agent:identity:reset":"ts-node src/cli/index.ts identity reset","agent:identity:strategies":"ts-node src/cli/index.ts identity strategies","agent:heartbeat:test":"ts-node src/cli/index.ts heartbeat test","agent:config:validate":"ts-node src/cli/index.ts config validate","agent:config:show":"ts-node src/cli/index.ts config show","agent:cli:help":"ts-node src/cli/index.ts --help"},dependencies:{"@anthropic-ai/sdk":"^0.56.0","@graphql-typed-document-node/core":"^3.2.0","@task-shepherd/shared":"*",chalk:"^4.1.2",commander:"^11.0.0",compression:"^1.7.4",cors:"^2.8.5",dotenv:"^16.3.1",express:"^4.18.2",glob:"^11.0.3",graphql:"^16.8.0","graphql-request":"^6.1.0","graphql-ws":"^6.0.5",helmet:"^7.0.0",joi:"^17.9.2",prompts:"^2.4.2",semver:"^7.5.4",sqlite3:"^5.1.6",uuid:"^11.1.0",winston:"^3.10.0",ws:"^8.14.2",zod:"^3.22.4"},devDependencies:{"@graphql-codegen/cli":"^5.0.0","@graphql-codegen/client-preset":"^4.1.0","@graphql-codegen/introspection":"^4.0.0","@graphql-codegen/typed-document-node":"^5.0.1","@graphql-codegen/typescript":"^4.0.1","@graphql-codegen/typescript-operations":"^4.0.1","@types/compression":"^1.7.2","@types/cors":"^2.8.13","@types/express":"^4.17.17","@types/glob":"^8.1.0","@types/jest":"^30.0.0","@types/nock":"^10.0.3","@types/node":"^20.4.5","@types/prompts":"^2.4.9","@types/semver":"^7.5.4","@types/uuid":"^9.0.8","@types/ws":"^8.5.8","@typescript-eslint/eslint-plugin":"^6.2.0","@typescript-eslint/parser":"^6.2.0",concurrently:"^8.2.0",esbuild:"^0.19.0",eslint:"^8.45.0","javascript-obfuscator":"^4.1.1",jest:"^29.6.1",nock:"^14.0.7","ts-jest":"^29.1.1","ts-node-dev":"^2.0.0",typescript:"^5.1.6"},keywords:["ai","project-analysis","claude","task-management","ai-agent","project-management","code-analysis"],author:"Task Shepherd Team",license:"SEE LICENSE IN LICENSE.md",repository:{type:"git",url:"https://github.com/taskshepherd/task-shepherd.git",directory:"packages/agent"},bugs:{url:"https://github.com/taskshepherd/task-shepherd/issues"},homepage:"https://taskshepherd.com",publishConfig:{access:"public"}}});function kt(){return Be||(Be=new Ge),Be}var mr,j,Ge,Be,bt=A(()=>{"use strict";R();mr=vt(),j={version:mr.version||"1.0.0",buildTimestamp:process.env.BUILD_TIMESTAMP||new Date().toISOString(),commitHash:process.env.GIT_COMMIT_HASH||"dev",compatibility:{minBackendVersion:"1.0.0",maxBackendVersion:"3.0.0",supportedBackendMajors:[1,2]},features:{workspaceAutoDiscovery:!0,realTimeUpdates:!0,multiProjectAnalysis:!1,advancedReporting:!0},releaseChannel:process.env.RELEASE_CHANNEL||"stable",releaseNotes:"See CHANGELOG.md for detailed release notes",deprecationWarnings:[]},Ge=class{getVersionMetadata(){return{...j}}getVersion(){return j.version}getBuildInfo(){return{version:j.version,buildTimestamp:j.buildTimestamp,commitHash:j.commitHash,releaseChannel:j.releaseChannel}}getCompatibilityRequirements(){return{...j.compatibility}}getFeatureCapabilities(){return{...j.features}}logVersionInfo(){c.info("Agent version information",{version:j.version,buildTimestamp:j.buildTimestamp,commitHash:j.commitHash,releaseChannel:j.releaseChannel,compatibilityRequirements:j.compatibility,features:j.features})}},Be=null});function te(a){return c.debug("getGraphQLHttpClient called",{hasExistingClient:!!ae,hasOptions:!!a,optionsProvided:a?JSON.stringify(a,null,2):"none"}),ae||(c.info("Creating new HTTP client singleton via getGraphQLHttpClient"),ae=new ce(a)),c.debug("Returning HTTP client",{clientExists:!!ae}),ae}var St,ce,ae,ke=A(()=>{"use strict";St=require("events");R();me();bt();ce=class extends St.EventEmitter{constructor(e={}){super();this.healthCheckTimer=null;this.isHealthy=!1;this.circuitBreakerOpen=!1;this.failureCount=0;this.lastHealthCheck=0;let r=ge();c.info("GraphQL HTTP Client constructor called",{providedOptionsApiKey:e.apiKey?e.apiKey.substring(0,12)+"...":"none",configApiKey:r.taskShepherd.apiKey?r.taskShepherd.apiKey.substring(0,12)+"...":"none",configApiUrl:r.taskShepherd.apiUrl});let s=e.apiKey||r.taskShepherd.apiKey;s||c.error("CRITICAL: No API key available for GraphQL HTTP Client",{providedOptionsApiKey:e.apiKey?e.apiKey.substring(0,12)+"...":"none",configApiKey:r.taskShepherd.apiKey?r.taskShepherd.apiKey.substring(0,12)+"...":"none",configKeys:Object.keys(r.taskShepherd||{})});let n=r.taskShepherd.apiUrl,o={maxRetries:5,baseDelay:1e3,maxDelay:3e4,timeout:6e4,healthCheckInterval:3e4,enableCircuitBreaker:!0,baseUrl:e.baseUrl||n||"http://localhost:4002/api/graphql"};this.options={...o,...e,apiKey:e.apiKey!==void 0?e.apiKey:s},c.info("GraphQL HTTP Client initialized with options",{hasApiKey:!!this.options.apiKey,apiKeyLength:this.options.apiKey?.length||0,apiKeyPrefix:this.options.apiKey?this.options.apiKey.substring(0,12)+"...":"none",baseUrl:this.options.baseUrl,optionsKeys:Object.keys(this.options)}),this.startHealthChecking()}async query(e){if(this.circuitBreakerOpen)throw new Error("Circuit breaker is open - backend is unavailable");let r=null;for(let s=1;s<=this.options.maxRetries;s++)try{let n=await this.executeRequest(e,s);return this.failureCount=0,this.circuitBreakerOpen&&(this.circuitBreakerOpen=!1,c.info("Circuit breaker closed - backend is healthy again"),this.emit("circuitBreakerClosed")),n}catch(n){if(r=n instanceof Error?n:new Error(String(n)),c.warn(`GraphQL request attempt ${s}/${this.options.maxRetries} failed`,{error:r.message,operationName:e.operationName,willRetry:s<this.options.maxRetries}),s<this.options.maxRetries){let i=this.calculateRetryDelay(s);await this.sleep(i)}}throw this.failureCount++,this.options.enableCircuitBreaker&&this.failureCount>=5&&!this.circuitBreakerOpen&&(this.circuitBreakerOpen=!0,c.error("Circuit breaker opened - too many backend failures"),this.emit("circuitBreakerOpened"),setTimeout(()=>{this.circuitBreakerOpen=!1,this.failureCount=0,c.info("Circuit breaker half-open - testing backend"),this.emit("circuitBreakerHalfOpen")},6e4)),r||new Error("All GraphQL request attempts failed")}async mutate(e){return this.query(e)}async post(e){return this.query(e)}async registerWorkspace(e){let s=await this.mutate({query:`
|
|
4
|
+
mutation RegisterWorkspace($input: WorkspaceRegistrationInput!) {
|
|
5
|
+
registerWorkspace(input: $input) {
|
|
6
|
+
id
|
|
7
|
+
workspaceId
|
|
8
|
+
name
|
|
9
|
+
path
|
|
10
|
+
pattern
|
|
11
|
+
services {
|
|
12
|
+
id
|
|
13
|
+
serviceId
|
|
14
|
+
name
|
|
15
|
+
technology
|
|
16
|
+
isActive
|
|
17
|
+
}
|
|
18
|
+
isActive
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
`,variables:{input:e},operationName:"RegisterWorkspace"});if(!s.data?.registerWorkspace)throw new Error("Failed to register workspace");return s.data.registerWorkspace}async getAvailableWorkspaces(){let r=await this.query({query:`
|
|
22
|
+
query AvailableWorkspaces {
|
|
23
|
+
availableWorkspaces {
|
|
24
|
+
id
|
|
25
|
+
workspaceId
|
|
26
|
+
name
|
|
27
|
+
description
|
|
28
|
+
path
|
|
29
|
+
pattern
|
|
30
|
+
isActive
|
|
31
|
+
services {
|
|
32
|
+
id
|
|
33
|
+
serviceId
|
|
34
|
+
name
|
|
35
|
+
technology
|
|
36
|
+
isActive
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
`,operationName:"AvailableWorkspaces"});if(!r.data?.availableWorkspaces)throw new Error("Failed to fetch available workspaces");return r.data.availableWorkspaces}async exchangeApiKeyForJWT(e){c.debug("GraphQL HTTP Client exchangeApiKeyForJWT called",{providedApiKey:e?e.substring(0,12)+"...":"none",providedApiKeyLength:e?.length||0,clientOptionsApiKey:this.options.apiKey?this.options.apiKey.substring(0,12)+"...":"none",clientOptionsApiKeyLength:this.options.apiKey?.length||0});let s=await this.mutate({query:`
|
|
41
|
+
mutation ExchangeApiKeyForToken($apiKey: String!) {
|
|
42
|
+
exchangeApiKeyForToken(apiKey: $apiKey) {
|
|
43
|
+
token
|
|
44
|
+
refreshToken
|
|
45
|
+
expiresIn
|
|
46
|
+
tokenType
|
|
47
|
+
user {
|
|
48
|
+
id
|
|
49
|
+
email
|
|
50
|
+
role
|
|
51
|
+
status
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
`,variables:{apiKey:e},operationName:"ExchangeApiKeyForToken"});if(!s.data?.exchangeApiKeyForToken)throw new Error("Failed to exchange API key for JWT token");return s.data.exchangeApiKeyForToken}async checkHealth(){try{let e=await this.query({query:`
|
|
56
|
+
query {
|
|
57
|
+
me {
|
|
58
|
+
id
|
|
59
|
+
email
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
`}),r=this.isHealthy;return this.isHealthy=!!e?.data?.me?.id,!r&&this.isHealthy?(c.info("Backend health recovered - authentication verified"),this.emit("healthRecovered")):r&&!this.isHealthy&&(c.warn("Backend health degraded - authentication failed"),this.emit("healthDegraded")),this.lastHealthCheck=Date.now(),this.isHealthy}catch(e){let r=this.isHealthy;return this.isHealthy=!1,r&&(c.warn("Backend health check failed",{error:e instanceof Error?e.message:String(e)}),this.emit("healthDegraded")),!1}}get healthy(){let e=Date.now()-this.lastHealthCheck>12e4;return this.isHealthy&&!e}destroy(){this.healthCheckTimer&&(clearInterval(this.healthCheckTimer),this.healthCheckTimer=null),this.removeAllListeners()}async executeRequest(e,r){let{query:s,variables:n,operationName:i}=e,l=kt().getBuildInfo(),u={"Content-Type":"application/json","X-Agent-Version":l.version,"X-Client-Type":"task-shepherd-agent","X-Agent-Build":l.buildTimestamp,"X-Agent-Commit":l.commitHash,"X-Agent-Channel":l.releaseChannel};c.debug("HTTP Client state before request",{operationName:i,attempt:r,hasApiKeyInOptions:!!this.options.apiKey,apiKeyLength:this.options.apiKey?.length||0,optionsKeys:Object.keys(this.options)}),this.options.apiKey?(u["X-API-Key"]=this.options.apiKey,c.info("Adding API key to request headers",{operationName:i,apiKeyPrefix:this.options.apiKey.substring(0,12)+"...",headerName:"X-API-Key"})):c.error("NO API KEY AVAILABLE for GraphQL request",{operationName:i,attempt:r,optionsApiKey:this.options.apiKey,optionsKeys:Object.keys(this.options),allOptions:JSON.stringify(this.options,null,2)}),c.debug("Executing GraphQL request",{operationName:i,attempt:r,hasAuth:!!this.options.apiKey,url:this.options.baseUrl});let m=await fetch(this.options.baseUrl,{method:"POST",headers:u,body:JSON.stringify({query:s,variables:n,operationName:i}),signal:AbortSignal.timeout(this.options.timeout)});if(!m.ok)throw new Error(`HTTP ${m.status}: ${m.statusText}`);let p=await m.json();if(p.errors&&p.errors.length>0){let f=p.errors.map(S=>S.message).join(", ");throw new Error(`GraphQL errors: ${f}`)}return p}calculateRetryDelay(e){let r=this.options.baseDelay*Math.pow(2,e-1),s=Math.random()*1e3;return Math.min(r+s,this.options.maxDelay)}sleep(e){return new Promise(r=>setTimeout(r,e))}startHealthChecking(){this.checkHealth().catch(()=>{}),this.healthCheckTimer=setInterval(()=>{this.checkHealth().catch(()=>{})},this.options.healthCheckInterval)}},ae=null});var Je,wt=A(()=>{"use strict";Je="1.0.0"});var Se,It=A(()=>{"use strict";wt();Se=class{validate(t){let e=[],r=[];return this.validateRequiredStructure(t,e),this.validateWorkspaceMetadata(t.workspace,e,r),this.validateServicesConfig(t.services,e,r),this.validateAIConfig(t.ai,e,r),this.validatePathsConfig(t.paths,e,r),this.validateDevelopmentConfig(t.development,e,r),this.validateSecurityConfig(t.security,e,r),t.git&&this.validateGitConfig(t.git,e,r),t.integrations&&this.validateIntegrationsConfig(t.integrations,e,r),{valid:e.length===0,errors:e,warnings:r}}validateRequiredStructure(t,e){let r=["workspace","services","ai","paths","development","security"];for(let s of r)t[s]||e.push({path:s,message:`Required field '${s}' is missing`,code:"MISSING_REQUIRED_FIELD",severity:"error"})}validateWorkspaceMetadata(t,e,r){t&&(t.id||e.push({path:"workspace.id",message:"Workspace ID is required",code:"MISSING_WORKSPACE_ID",severity:"error"}),t.name||e.push({path:"workspace.name",message:"Workspace name is required",code:"MISSING_WORKSPACE_NAME",severity:"error"}),t.version?t.version!==Je&&r.push({path:"workspace.version",message:`Workspace version ${t.version} may not be compatible with current version ${Je}`,code:"VERSION_MISMATCH",severity:"warning"}):e.push({path:"workspace.version",message:"Workspace version is required",code:"MISSING_VERSION",severity:"error"}),t.id&&!/^[a-zA-Z0-9_-]+$/.test(t.id)&&e.push({path:"workspace.id",message:"Workspace ID must contain only alphanumeric characters, hyphens, and underscores",code:"INVALID_WORKSPACE_ID",severity:"error"}),t.name&&(t.name.length<1||t.name.length>100)&&e.push({path:"workspace.name",message:"Workspace name must be between 1 and 100 characters",code:"INVALID_WORKSPACE_NAME_LENGTH",severity:"error"}))}validateServicesConfig(t,e,r){if(!t)return;let s=Object.keys(t);for(let n of s){let i=t[n];i&&typeof i=="object"&&this.validateServiceEndpoint(i,`services.${n}`,e,r)}s.length===0&&r.push({path:"services",message:"No services are configured",code:"NO_SERVICES_CONFIGURED",severity:"warning"})}validateServiceEndpoint(t,e,r,s){t.name||r.push({path:`${e}.name`,message:"Service name is required",code:"MISSING_SERVICE_NAME",severity:"error"});let n=e.split(".").pop()||"",o=["mcp","shared","cli","tasqhubmcp"].includes(n)||t.port===0;!t.url&&!o&&r.push({path:`${e}.url`,message:"Service URL is required",code:"MISSING_SERVICE_URL",severity:"error"});let u=["mcp","shared","cli","tasqhubmcp"].includes(n)||t.port===0;!t.port&&!u&&r.push({path:`${e}.port`,message:"Service port is required",code:"MISSING_SERVICE_PORT",severity:"error"}),t.protocol||r.push({path:`${e}.protocol`,message:"Service protocol is required",code:"MISSING_SERVICE_PROTOCOL",severity:"error"}),t.port&&(typeof t.port!="number"||t.port<1||t.port>65535)&&r.push({path:`${e}.port`,message:"Service port must be a number between 1 and 65535",code:"INVALID_SERVICE_PORT",severity:"error"});let m=["http","https","ws","wss","tcp","udp","postgresql","redis","mongodb"];t.protocol&&!m.includes(t.protocol)&&r.push({path:`${e}.protocol`,message:`Service protocol must be one of: ${m.join(", ")}`,code:"INVALID_SERVICE_PROTOCOL",severity:"error"}),t.environment&&!["development","staging","production"].includes(t.environment)&&r.push({path:`${e}.environment`,message:"Service environment must be one of: development, staging, production",code:"INVALID_SERVICE_ENVIRONMENT",severity:"error"})}validateAIConfig(t,e,r){t&&(t.provider?["claude","openai","custom"].includes(t.provider)||e.push({path:"ai.provider",message:"AI provider must be one of: claude, openai, custom",code:"INVALID_AI_PROVIDER",severity:"error"}):e.push({path:"ai.provider",message:"AI provider is required",code:"MISSING_AI_PROVIDER",severity:"error"}),t.models?this.validateAIModels(t.models,t.provider,e,r):e.push({path:"ai.models",message:"AI models configuration is required",code:"MISSING_AI_MODELS",severity:"error"}),t.capabilities?this.validateAICapabilities(t.capabilities,e,r):e.push({path:"ai.capabilities",message:"AI capabilities configuration is required",code:"MISSING_AI_CAPABILITIES",severity:"error"}))}validateAIModels(t,e,r,s){e==="claude"&&!t.claude&&r.push({path:"ai.models.claude",message:"Claude model configuration is required when provider is claude",code:"MISSING_CLAUDE_CONFIG",severity:"error"}),e==="openai"&&!t.openai&&r.push({path:"ai.models.openai",message:"OpenAI model configuration is required when provider is openai",code:"MISSING_OPENAI_CONFIG",severity:"error"}),t.claude&&(t.claude.apiKey||r.push({path:"ai.models.claude.apiKey",message:"Claude API key is required",code:"MISSING_CLAUDE_API_KEY",severity:"error"}),t.claude.defaultModel||r.push({path:"ai.models.claude.defaultModel",message:"Claude default model is required",code:"MISSING_CLAUDE_DEFAULT_MODEL",severity:"error"})),t.openai&&(t.openai.apiKey||r.push({path:"ai.models.openai.apiKey",message:"OpenAI API key is required",code:"MISSING_OPENAI_API_KEY",severity:"error"}),t.openai.defaultModel||r.push({path:"ai.models.openai.defaultModel",message:"OpenAI default model is required",code:"MISSING_OPENAI_DEFAULT_MODEL",severity:"error"}))}validateAICapabilities(t,e,r){t.maxConcurrentOperations===void 0?e.push({path:"ai.capabilities.maxConcurrentOperations",message:"Maximum concurrent operations is required",code:"MISSING_MAX_CONCURRENT_OPERATIONS",severity:"error"}):(typeof t.maxConcurrentOperations!="number"||t.maxConcurrentOperations<1||t.maxConcurrentOperations>100)&&e.push({path:"ai.capabilities.maxConcurrentOperations",message:"Maximum concurrent operations must be a number between 1 and 100",code:"INVALID_MAX_CONCURRENT_OPERATIONS",severity:"error"}),t.supportedAnalysisTypes?Array.isArray(t.supportedAnalysisTypes)||e.push({path:"ai.capabilities.supportedAnalysisTypes",message:"Supported analysis types must be an array",code:"INVALID_SUPPORTED_ANALYSIS_TYPES",severity:"error"}):e.push({path:"ai.capabilities.supportedAnalysisTypes",message:"Supported analysis types are required",code:"MISSING_SUPPORTED_ANALYSIS_TYPES",severity:"error"}),t.isolationLevel?["strict","moderate","relaxed"].includes(t.isolationLevel)||e.push({path:"ai.capabilities.isolationLevel",message:"Isolation level must be one of: strict, moderate, relaxed",code:"INVALID_ISOLATION_LEVEL",severity:"error"}):r.push({path:"ai.capabilities.isolationLevel",message:"Isolation level not specified, defaulting to moderate",code:"MISSING_ISOLATION_LEVEL",severity:"warning"})}validatePathsConfig(t,e,r){if(!t)return;t.root||e.push({path:"paths.root",message:"Root path is required",code:"MISSING_ROOT_PATH",severity:"error"});let s=["src","tests","docs","config","build","temp","logs","excluded"];for(let n of s)t[n]&&!Array.isArray(t[n])&&e.push({path:`paths.${n}`,message:`${n} must be an array of paths`,code:"INVALID_PATH_ARRAY",severity:"error"});(!t.src||t.src.length===0)&&r.push({path:"paths.src",message:"No source paths specified",code:"NO_SOURCE_PATHS",severity:"warning"})}validateDevelopmentConfig(t,e,r){t&&(t.packageManager?["npm","yarn","pnpm"].includes(t.packageManager)||e.push({path:"development.packageManager",message:"Package manager must be one of: npm, yarn, pnpm",code:"INVALID_PACKAGE_MANAGER",severity:"error"}):e.push({path:"development.packageManager",message:"Package manager is required",code:"MISSING_PACKAGE_MANAGER",severity:"error"}),t.nodeVersion&&!/^\d+\.\d+\.\d+$/.test(t.nodeVersion)&&r.push({path:"development.nodeVersion",message:"Node.js version should be in format x.y.z",code:"INVALID_NODE_VERSION_FORMAT",severity:"warning"}))}validateSecurityConfig(t,e,r){t&&(t.filePermissions?this.validateFilePermissions(t.filePermissions,e,r):e.push({path:"security.filePermissions",message:"File permissions configuration is required",code:"MISSING_FILE_PERMISSIONS",severity:"error"}),t.networkPermissions?this.validateNetworkPermissions(t.networkPermissions,e,r):e.push({path:"security.networkPermissions",message:"Network permissions configuration is required",code:"MISSING_NETWORK_PERMISSIONS",severity:"error"}))}validateFilePermissions(t,e,r){let s=["read","write","execute"];for(let n of s)typeof t[n]!="boolean"&&e.push({path:`security.filePermissions.${n}`,message:`${n} permission must be a boolean`,code:"INVALID_FILE_PERMISSION",severity:"error"});t.restricted&&!Array.isArray(t.restricted)&&e.push({path:"security.filePermissions.restricted",message:"Restricted paths must be an array",code:"INVALID_RESTRICTED_PATHS",severity:"error"}),t.write&&t.execute&&r.push({path:"security.filePermissions",message:"Both write and execute permissions are enabled, this may pose security risks",code:"SECURITY_RISK_WRITE_EXECUTE",severity:"warning"})}validateNetworkPermissions(t,e,r){let s=["http","https"];for(let i of s)typeof t[i]!="boolean"&&e.push({path:`security.networkPermissions.${i}`,message:`${i} permission must be a boolean`,code:"INVALID_NETWORK_PERMISSION",severity:"error"});let n=["allowedDomains","blockedDomains"];for(let i of n)t[i]&&!Array.isArray(t[i])&&e.push({path:`security.networkPermissions.${i}`,message:`${i} must be an array`,code:"INVALID_DOMAIN_ARRAY",severity:"error"});t.http&&!t.https&&r.push({path:"security.networkPermissions",message:"HTTP is enabled but HTTPS is not, consider enabling HTTPS for better security",code:"SECURITY_RISK_HTTP_ONLY",severity:"warning"})}validateGitConfig(t,e,r){t.repositoryUrl&&!this.isValidUrl(t.repositoryUrl)&&e.push({path:"git.repositoryUrl",message:"Repository URL must be a valid URL",code:"INVALID_REPOSITORY_URL",severity:"error"}),t.defaultBranch&&!/^[a-zA-Z0-9/_-]+$/.test(t.defaultBranch)&&e.push({path:"git.defaultBranch",message:"Default branch name contains invalid characters",code:"INVALID_BRANCH_NAME",severity:"error"}),t.remoteName&&!/^[a-zA-Z0-9_-]+$/.test(t.remoteName)&&e.push({path:"git.remoteName",message:"Remote name contains invalid characters",code:"INVALID_REMOTE_NAME",severity:"error"})}validateIntegrationsConfig(t,e,r){t.taskShepherd&&(t.taskShepherd.apiUrl?this.isValidUrl(t.taskShepherd.apiUrl)||e.push({path:"integrations.taskShepherd.apiUrl",message:"Task Shepherd API URL must be a valid URL",code:"INVALID_TASK_SHEPHERD_API_URL",severity:"error"}):e.push({path:"integrations.taskShepherd.apiUrl",message:"Task Shepherd API URL is required",code:"MISSING_TASK_SHEPHERD_API_URL",severity:"error"}),t.taskShepherd.apiKey||e.push({path:"integrations.taskShepherd.apiKey",message:"Task Shepherd API key is required",code:"MISSING_TASK_SHEPHERD_API_KEY",severity:"error"}))}isValidUrl(t){try{return new URL(t),!0}catch{return!1}}}});var pe={};Q(pe,{WorkspaceRegistryService:()=>Ie,getWorkspaceRegistry:()=>z});function z(){return Ye||(Ye=new Ie),Ye}var we,le,Ie,Ye,B=A(()=>{"use strict";we=require("fs"),le=h(require("path"));R();Ie=class{constructor(){this.registry=new Map;let t=le.join(process.env.HOME||process.env.USERPROFILE||"",".task-shepherd-agent");this.registryPath=le.join(t,"workspace-registry.json")}async initialize(){try{await this.ensureDataDirectory(),await this.loadRegistry(),c.info("Workspace registry initialized",{registryPath:this.registryPath,workspaceCount:this.registry.size})}catch(t){c.error("Failed to initialize workspace registry",{error:t instanceof Error?t.message:String(t)})}}async ensureDataDirectory(){let t=le.dirname(this.registryPath);try{await we.promises.mkdir(t,{recursive:!0})}catch(e){c.error("Failed to create data directory",{dataDir:t,error:e instanceof Error?e.message:String(e)})}}async loadRegistry(){try{let t=await we.promises.readFile(this.registryPath,"utf-8"),e=JSON.parse(t);this.registry.clear();for(let r of e)this.registry.set(r.workspace.workspaceId,r);c.info("Loaded workspace registry from disk",{workspaceCount:this.registry.size})}catch(t){t.code==="ENOENT"?c.info("No existing workspace registry found, starting fresh"):c.error("Failed to load workspace registry",{error:t instanceof Error?t.message:String(t)})}}async saveRegistry(){try{let t=Array.from(this.registry.values());await we.promises.writeFile(this.registryPath,JSON.stringify(t,null,2),"utf-8"),c.debug("Saved workspace registry to disk",{workspaceCount:t.length})}catch(t){c.error("Failed to save workspace registry",{error:t instanceof Error?t.message:String(t)})}}async addWorkspace(t){let e={workspace:t,discoveredAt:new Date().toISOString(),syncStatus:"pending"},r=this.registry.get(t.workspaceId);r&&(e.lastSyncedAt=r.lastSyncedAt,e.syncStatus=r.syncStatus,e.syncError=r.syncError),this.registry.set(t.workspaceId,e),await this.saveRegistry(),c.info("Added workspace to local registry",{workspaceId:t.workspaceId,name:t.name,syncStatus:e.syncStatus})}async addWorkspaces(t){for(let e of t)await this.addWorkspace(e)}getAllWorkspaces(){return Array.from(this.registry.values())}getWorkspacesBySyncStatus(t){return Array.from(this.registry.values()).filter(e=>e.syncStatus===t)}getWorkspace(t){return this.registry.get(t)}async removeWorkspace(t){this.registry.delete(t)&&(await this.saveRegistry(),c.info("Removed workspace from registry",{workspaceId:t}))}async markWorkspaceSynced(t){let e=this.registry.get(t);e&&(e.syncStatus="synced",e.lastSyncedAt=new Date().toISOString(),e.syncError=void 0,this.registry.set(t,e),await this.saveRegistry(),c.info("Marked workspace as synced",{workspaceId:t,lastSyncedAt:e.lastSyncedAt}))}async markWorkspaceSyncFailed(t,e){let r=this.registry.get(t);r&&(r.syncStatus="failed",r.syncError=e,this.registry.set(t,r),await this.saveRegistry(),c.warn("Marked workspace sync as failed",{workspaceId:t,error:e}))}getSyncStats(){let t=Array.from(this.registry.values());return{total:t.length,synced:t.filter(e=>e.syncStatus==="synced").length,pending:t.filter(e=>e.syncStatus==="pending").length,failed:t.filter(e=>e.syncStatus==="failed").length}}async clearRegistry(){this.registry.clear(),await this.saveRegistry(),c.info("Cleared workspace registry")}},Ye=null});var G,re,Ee,Et=A(()=>{"use strict";G=require("fs"),re=h(require("path"));It();R();B();Ee=class{constructor(){this.validator=new Se}async discoverWorkspaces(t){try{if(c.info("Starting workspace discovery",{rootPath:t}),!(await G.promises.stat(t)).isDirectory())throw new Error(`Path ${t} is not a directory`);let r=await this.detectTaskShepherdMonorepo(t),s;return r?s=await this.discoverTaskShepherdWorkspaces(t):s=await this.discoverGenericWorkspaces(t),await this.saveDiscoveredWorkspaces(s),s}catch(e){return c.error("Workspace discovery failed",{rootPath:t,error:e instanceof Error?e.message:e}),[{workspaceId:"error",name:"Discovery Error",path:t,pattern:"monorepo",services:[],config:{},errors:[e instanceof Error?e.message:"Unknown error occurred"]}]}}async detectTaskShepherdMonorepo(t){try{let e=re.join(t,"package.json"),r=await G.promises.readFile(e,"utf-8"),s=JSON.parse(r),n=s.name==="task-shepherd"||s.workspaces&&Array.isArray(s.workspaces)&&s.workspaces.includes("packages/*"),i=["packages/frontend","packages/backend","packages/agent"],o=await Promise.all(i.map(async l=>{try{let u=re.join(t,l);return(await G.promises.stat(u)).isDirectory()}catch{return!1}}));return n&&o.some(l=>l)}catch{return!1}}async discoverTaskShepherdWorkspaces(t){let e=[],r=[{path:"packages/frontend",name:"Frontend App",technology:"react",port:5173},{path:"packages/backend",name:"GraphQL Backend",technology:"nodejs",port:4002},{path:"packages/agent",name:"AI Agent Service",technology:"nodejs",port:8547},{path:"packages/mcp",name:"MCP Server",technology:"nodejs",port:3001},{path:"packages/shared",name:"Shared Types",technology:"other"}];for(let s of r){let n=re.join(t,s.path);try{if((await G.promises.stat(n)).isDirectory()){let o=re.join(n,"package.json");try{await G.promises.access(o),e.push({id:s.path.replace("packages/",""),name:s.name,path:n,relativePath:s.path,technology:s.technology,port:s.port})}catch{c.warn("Package directory found but no package.json",{path:n})}}}catch{c.debug("Package not found",{path:n})}}return[{workspaceId:"task-shepherd-monorepo",name:"Task Shepherd Monorepo",path:t,pattern:"monorepo",services:e,config:{},errors:[]}]}async discoverGenericWorkspaces(t){let e=[];try{let r=re.join(t,"package.json");try{let s=await G.promises.readFile(r,"utf-8"),n=JSON.parse(s);if(n.name){let i=[],o={...n.dependencies,...n.devDependencies};(o.react||o["@types/react"])&&i.push({id:"frontend",name:"React Frontend",path:t,technology:"react"}),(o.express||o.fastify||o.koa)&&i.push({id:"backend",name:"Node.js Backend",path:t,technology:"nodejs"}),o.next&&i.push({id:"nextjs",name:"Next.js App",path:t,technology:"other"}),(i.length>0||n.scripts)&&e.push({workspaceId:`generic-${n.name.replace(/[^a-zA-Z0-9]/g,"-")}`,name:n.name,path:t,pattern:"monorepo",services:i,config:{},errors:[]})}}catch(s){c.debug("No package.json found or invalid",{rootPath:t,error:s instanceof Error?s.message:s})}return e}catch(r){return c.warn("Generic workspace discovery failed",{rootPath:t,error:r instanceof Error?r.message:r}),[]}}async discoverWorkspacesFromPaths(t){let e=[];for(let r of t)try{c.info("Scanning directory for workspaces",{searchPath:r});let n=(await this.discoverWorkspaces(r)).filter(i=>i.errors.length===0);e.push(...n),c.info("Directory scan completed",{searchPath:r,foundWorkspaces:n.length,totalWorkspaces:e.length})}catch(s){c.warn("Failed to scan directory for workspaces",{searchPath:r,error:s instanceof Error?s.message:String(s)})}return e}async generateWorkspaceConfig(t){return c.info("Generating workspace configuration",{workspaceId:t.workspaceId}),{workspace:{id:t.workspaceId,name:t.name,pattern:t.pattern,rootPath:t.path},services:t.services.reduce((e,r)=>(e[r.id]={name:r.name,path:r.path,technology:r.technology,port:r.port,enabled:!0},e),{}),ai:{models:{claude:{provider:"anthropic",model:"claude-3-sonnet",enabled:!0}},defaultModel:"claude",capabilities:{codeGeneration:!0,codeReview:!0,projectAnalysis:!0}},development:{hotReload:!0,debugMode:!0,testRunner:"jest"},integrations:{github:{enabled:!1},slack:{enabled:!1}}}}async saveDiscoveredWorkspaces(t){let e=z();await e.initialize();for(let r of t){if(r.errors.length>0){c.warn("Skipping workspace due to errors",{workspaceId:r.workspaceId,errors:r.errors});continue}try{c.info("Saving workspace to local registry",{workspaceId:r.workspaceId,servicesCount:r.services.length,note:"Will be synced with backend when connected"}),await e.addWorkspace(r),c.info("Successfully saved workspace to local registry",{workspaceId:r.workspaceId,capabilities:r.services.map(s=>`${s.name} (${s.technology})`).join(", ")})}catch(s){c.error("Failed to save workspace to local registry",{workspaceId:r.workspaceId,error:s instanceof Error?s.message:String(s)})}}}async validateWorkspaceConfig(t){try{let e=this.validator.validate(t);return{isValid:e.valid,errors:e.errors?.map(r=>r.message)||[]}}catch(e){return{isValid:!1,errors:[e instanceof Error?e.message:"Validation failed"]}}}}});var H,x,Ce,Ct=A(()=>{"use strict";H=h(require("fs")),x=h(require("path"));R();Ce=class{async detect(t){try{if(c.info("Starting .NET workspace detection",{workspacePath:t}),!await this.hasDotNetIndicators(t))return null;let r=await this.detectSolutions(t),s=await this.detectStandaloneProjects(t,r),n=this.identifySharedProjects(r),i=H.existsSync(x.join(t,"global.json")),o=this.findNuGetConfig(t),l=await this.detectDockerFiles(t),u;return r.length>1?u="dotnet-multi-solution":r.length===1?u="dotnet-single-solution":u="dotnet-project-only",{pattern:u,solutions:r,standaloneProjects:s,sharedProjects:n,globalJsonExists:i,nugetConfig:o,dockerFiles:l}}catch(e){return c.error("Failed to detect .NET workspace",{error:e,workspacePath:t}),null}}async hasDotNetIndicators(t){let e=["**/*.sln","**/*.csproj","**/*.fsproj","**/*.vbproj","global.json","nuget.config","Directory.Build.props","Directory.Build.targets"];for(let r of e){let{glob:s}=await import("glob");if((await s(r,{cwd:t})).length>0)return!0}return!1}async detectSolutions(t){let{glob:e}=await import("glob"),r=await e("**/*.sln",{cwd:t}),s=[];for(let n of r)try{let i=x.join(t,n),o=H.readFileSync(i,"utf8"),l=await this.parseSolutionProjects(i,o),u=this.parseSolutionConfigurations(o);s.push({name:x.basename(n,".sln"),file:n,path:x.dirname(i),projects:l,configurations:u})}catch(i){c.warn("Failed to parse solution file",{error:i,file:n})}return s}async parseSolutionProjects(t,e){let r=[],s=x.dirname(t),n=/Project\("[^"]+"\)\s*=\s*"([^"]+)",\s*"([^"]+)",\s*"[^"]+"/g,i;for(;(i=n.exec(e))!==null;){let o=i[1],l=i[2];if(l.endsWith(".sln"))continue;let u=x.resolve(s,l);if(H.existsSync(u))try{let m=await this.analyzeProject(u);m&&r.push({...m,name:o})}catch(m){c.warn("Failed to analyze project",{error:m,projectPath:u})}}return r}parseSolutionConfigurations(t){let e=[],r=/^\s*([^|]+)\|([^=]+)\s*=/gm,s;for(;(s=r.exec(t))!==null;){let n=`${s[1].trim()}|${s[2].trim()}`;e.includes(n)||e.push(n)}return e}async detectStandaloneProjects(t,e){let{glob:r}=await import("glob"),s=await r("**/*.csproj",{cwd:t}),n=new Set;e.forEach(o=>{o.projects.forEach(l=>{n.add(x.resolve(l.path,l.file))})});let i=[];for(let o of s){let l=x.resolve(t,o);if(!n.has(l))try{let u=await this.analyzeProject(l);u&&i.push(u)}catch(u){c.warn("Failed to analyze standalone project",{error:u,projectFile:o})}}return i}async analyzeProject(t){try{let e=H.readFileSync(t,"utf8"),r=x.dirname(t),s=x.basename(t,".csproj"),n=this.extractTargetFrameworks(e),i=this.extractPackageReferences(e),o=this.determineProjectType(e,i),l=this.isTestProject(e,i),u=await this.extractPort(r,o);return{name:s,file:x.basename(t),path:r,type:o,frameworks:n,port:u,packageReferences:i,isShared:!1,isTest:l}}catch(e){return c.error("Failed to analyze project file",{error:e,projectPath:t}),null}}extractTargetFrameworks(t){let e=[],r=t.match(/<TargetFramework>([^<]+)<\/TargetFramework>/);r&&e.push(r[1]);let s=t.match(/<TargetFrameworks>([^<]+)<\/TargetFrameworks>/);return s&&e.push(...s[1].split(";").map(n=>n.trim())),e}extractPackageReferences(t){let e=[],r=/<PackageReference\s+Include="([^"]+)"/g,s;for(;(s=r.exec(t))!==null;)e.push(s[1]);return e}determineProjectType(t,e){if(t.includes("Microsoft.NET.Sdk.Web"))return e.some(r=>r.includes("Blazor"))?"blazor":e.some(r=>r.includes("Mvc"))||t.includes("Microsoft.AspNetCore.Mvc")?"mvc":"aspnetcore";if(t.includes("Microsoft.NET.Sdk")){if(e.some(s=>["xunit","NUnit","MSTest"].some(n=>s.includes(n)))){if(e.some(s=>s.includes("xunit")))return"xunit";if(e.some(s=>s.includes("NUnit")))return"nunit";if(e.some(s=>s.includes("MSTest")))return"mstest"}let r=t.match(/<OutputType>([^<]+)<\/OutputType>/);return r&&r[1].toLowerCase()==="exe"?"console":"classlib"}return"unknown"}isTestProject(t,e){return e.some(r=>["xunit","nunit","mstest","Microsoft.NET.Test.Sdk"].some(s=>r.toLowerCase().includes(s.toLowerCase())))||t.toLowerCase().includes("test")}async extractPort(t,e){if(!["aspnetcore","mvc","webapi","blazor"].includes(e))return;let r=x.join(t,"Properties","launchSettings.json");if(H.existsSync(r))try{let n=JSON.parse(H.readFileSync(r,"utf8"));for(let i of Object.values(n.profiles||{})){let o=i;if(o.applicationUrl){let l=o.applicationUrl.match(/:(\d+)/);if(l)return parseInt(l[1])}}}catch(n){c.warn("Failed to parse launchSettings.json",{error:n,path:r})}return{aspnetcore:5e3,mvc:5e3,webapi:5001,blazor:5002}[e]}identifySharedProjects(t){if(t.length<2)return[];let e=new Map;t.forEach(s=>{s.projects.forEach(n=>{let i=x.resolve(n.path,n.file);e.has(i)?e.get(i).count++:e.set(i,{project:n,count:1})})});let r=[];for(let[,{project:s,count:n}]of e)n>1&&(s.isShared=!0,r.push(s));return r}findNuGetConfig(t){let e=["nuget.config","NuGet.config","NuGet.Config"];for(let r of e){let s=x.join(t,r);if(H.existsSync(s))return r}}async detectDockerFiles(t){let{glob:e}=await import("glob");return await e("**/Dockerfile*",{cwd:t})}}});var b,v,Ae,At=A(()=>{"use strict";b=h(require("fs")),v=h(require("path"));R();Ae=class{async detect(t){try{if(c.info("Starting Python workspace detection",{workspacePath:t}),!await this.hasPythonIndicators(t))return null;let r=await this.detectVirtualEnvironments(t),s=await this.detectPythonProjects(t),n=await this.detectGlobalPythonVersion(t),i=b.existsSync(v.join(t,"pyproject.toml"))&&b.readFileSync(v.join(t,"pyproject.toml"),"utf8").includes("[tool.poetry]"),o=b.existsSync(v.join(t,"Pipfile")),l=b.existsSync(v.join(t,"environment.yml"))||b.existsSync(v.join(t,"conda-env.yml")),u=await this.detectDockerFiles(t),m=await this.detectJupyterNotebooks(t),p;return s.length>1?p="python-monorepo":s.length===1&&s[0].apps.length>1?p="python-multi-app":p="python-single-project",{pattern:p,projects:s,virtualEnvironments:r,globalPythonVersion:n,hasPoetry:i,hasPipenv:o,hasCondaEnv:l,dockerFiles:u,jupyterNotebooks:m}}catch(e){return c.error("Failed to detect Python workspace",{error:e,workspacePath:t}),null}}async hasPythonIndicators(t){let e=["**/*.py","requirements.txt","requirements/**/*.txt","pyproject.toml","setup.py","setup.cfg","Pipfile","environment.yml","conda-env.yml","manage.py","app.py","main.py","**/__init__.py"];for(let r of e){let{glob:s}=await import("glob");if((await s(r,{cwd:t,maxDepth:3})).length>0)return!0}return!1}async detectVirtualEnvironments(t){let e=["venv","env",".venv",".env","virtualenv"],r=[];for(let s of e){let n=v.join(t,s);if(b.existsSync(n)&&b.statSync(n).isDirectory()){let i=process.platform==="win32"?"Scripts/python.exe":"bin/python";b.existsSync(v.join(n,i))&&r.push(s)}}return r}async detectPythonProjects(t){let e=[];if(b.existsSync(v.join(t,"manage.py"))){let r=await this.analyzeDjangoProject(t);r&&e.push(r)}else{let r=await this.findPythonProjectDirectories(t);for(let s of r){let n=await this.analyzePythonProject(s);n&&e.push(n)}}return e}async findPythonProjectDirectories(t){let e=[t],{glob:r}=await import("glob"),s=await r("**/setup.py",{cwd:t,maxDepth:2}),n=await r("**/pyproject.toml",{cwd:t,maxDepth:2}),i=await r("**/app.py",{cwd:t,maxDepth:2}),o=await r("**/main.py",{cwd:t,maxDepth:2});return[...s,...n,...i,...o].forEach(l=>{let u=v.dirname(v.resolve(t,l));e.includes(u)||e.push(u)}),e}async analyzeDjangoProject(t){try{let e=v.basename(t),r=await this.detectDjangoApps(t),{dependencies:s,devDependencies:n}=await this.analyzeDependencies(t),i=b.existsSync(v.join(t,"manage.py"));return{name:e,path:t,type:"django-project",framework:"django",apps:r,dependencies:s,devDependencies:n,virtualEnv:await this.findVirtualEnv(t),hasDockerfile:b.existsSync(v.join(t,"Dockerfile")),hasRequirements:await this.hasRequirementsFiles(t),hasPyprojectToml:b.existsSync(v.join(t,"pyproject.toml")),hasSetupPy:b.existsSync(v.join(t,"setup.py")),hasManagePy:i,testFramework:await this.detectTestFramework(t,s)}}catch(e){return c.error("Failed to analyze Django project",{error:e,projectPath:t}),null}}async detectDjangoApps(t){let e=[];try{let{glob:r}=await import("glob"),s=await r("**/apps.py",{cwd:t,maxDepth:3});for(let n of s){let i=v.dirname(v.resolve(t,n)),o=v.basename(i);if(o===v.basename(t))continue;let l=await this.analyzeDjangoApp(i,o);l&&e.push(l)}if(e.length===0){let n=await r("**/models.py",{cwd:t,maxDepth:2}),i=await r("**/views.py",{cwd:t,maxDepth:2}),o=new Set;[...n,...i].forEach(l=>{let u=v.dirname(v.resolve(t,l));v.basename(u)!==v.basename(t)&&o.add(u)});for(let l of o){let u=v.basename(l),m=await this.analyzeDjangoApp(l,u);m&&e.push(m)}}}catch(r){c.warn("Failed to detect Django apps",{error:r,projectPath:t})}return e}async analyzeDjangoApp(t,e){try{let r=b.existsSync(v.join(t,"models.py"))?await this.extractDjangoModels(v.join(t,"models.py")):[],s=b.existsSync(v.join(t,"urls.py"))?[e]:[],n=await this.findManagementCommands(t),i=b.existsSync(v.join(t,"tests.py"))||b.existsSync(v.join(t,"tests"));return{name:e,path:t,type:"django",models:r,urls:s,managementCommands:n,hasTests:i,isPackage:b.existsSync(v.join(t,"__init__.py"))}}catch(r){return c.warn("Failed to analyze Django app",{error:r,appPath:t,appName:e}),null}}async analyzePythonProject(t){try{let e=v.basename(t),{dependencies:r,devDependencies:s}=await this.analyzeDependencies(t),n="unknown",i;r.some(l=>l.includes("flask"))?(n="flask-app",i="flask"):r.some(l=>l.includes("fastapi"))?(n="fastapi-app",i="fastapi"):(b.existsSync(v.join(t,"setup.py"))||b.existsSync(v.join(t,"pyproject.toml")))&&(n="package");let o=await this.detectPythonApps(t,n);return{name:e,path:t,type:n,framework:i,apps:o,dependencies:r,devDependencies:s,virtualEnv:await this.findVirtualEnv(t),hasDockerfile:b.existsSync(v.join(t,"Dockerfile")),hasRequirements:await this.hasRequirementsFiles(t),hasPyprojectToml:b.existsSync(v.join(t,"pyproject.toml")),hasSetupPy:b.existsSync(v.join(t,"setup.py")),hasManagePy:b.existsSync(v.join(t,"manage.py")),testFramework:await this.detectTestFramework(t,r)}}catch(e){return c.error("Failed to analyze Python project",{error:e,projectPath:t}),null}}async detectPythonApps(t,e){let r=[];if(e==="flask-app"||e==="fastapi-app"){let s=["app.py","main.py","server.py","api.py"];for(let n of s){let i=v.join(t,n);if(b.existsSync(i)){let o=await this.extractPortFromPythonFile(i);r.push({name:v.basename(n,".py"),path:t,type:e==="flask-app"?"flask":"fastapi",port:o,hasTests:await this.hasTestFiles(t),isPackage:b.existsSync(v.join(t,"__init__.py"))});break}}}return r}async analyzeDependencies(t){let e=[],r=[],s=v.join(t,"requirements.txt");if(b.existsSync(s)){let l=b.readFileSync(s,"utf8");e.push(...this.parseRequirements(l))}let n=v.join(t,"requirements-dev.txt");if(b.existsSync(n)){let l=b.readFileSync(n,"utf8");r.push(...this.parseRequirements(l))}let i=v.join(t,"pyproject.toml");if(b.existsSync(i)){let l=b.readFileSync(i,"utf8"),{deps:u,devDeps:m}=this.parsePyprojectToml(l);e.push(...u),r.push(...m)}let o=v.join(t,"Pipfile");if(b.existsSync(o)){let l=b.readFileSync(o,"utf8"),{deps:u,devDeps:m}=this.parsePipfile(l);e.push(...u),r.push(...m)}return{dependencies:e,devDependencies:r}}parseRequirements(t){return t.split(`
|
|
63
|
+
`).map(e=>e.trim()).filter(e=>e&&!e.startsWith("#")&&!e.startsWith("-")).map(e=>e.split("==")[0].split(">=")[0].split("<=")[0].split("~=")[0].trim())}parsePyprojectToml(t){let e=[],r=[],s=t.match(/\[tool\.poetry\.dependencies\]([\s\S]*?)(\[|$)/);if(s){let o=s[1].match(/^([a-zA-Z0-9-_]+)\s*=/gm);o&&e.push(...o.map(l=>l.split("=")[0].trim()))}let n=t.match(/\[tool\.poetry\.group\.dev\.dependencies\]([\s\S]*?)(\[|$)/);if(n){let o=n[1].match(/^([a-zA-Z0-9-_]+)\s*=/gm);o&&r.push(...o.map(l=>l.split("=")[0].trim()))}return{deps:e,devDeps:r}}parsePipfile(t){let e=[],r=[],s=t.match(/\[packages\]([\s\S]*?)(\[|$)/);if(s){let o=s[1].match(/^([a-zA-Z0-9-_]+)\s*=/gm);o&&e.push(...o.map(l=>l.split("=")[0].trim()))}let n=t.match(/\[dev-packages\]([\s\S]*?)(\[|$)/);if(n){let o=n[1].match(/^([a-zA-Z0-9-_]+)\s*=/gm);o&&r.push(...o.map(l=>l.split("=")[0].trim()))}return{deps:e,devDeps:r}}async extractPortFromPythonFile(t){try{let e=b.readFileSync(t,"utf8"),r=[/\.run\([^)]*port\s*=\s*(\d+)/,/uvicorn\.run\([^)]*port\s*=\s*(\d+)/,/app\.run\([^)]*port\s*=\s*(\d+)/,/PORT\s*=\s*(\d+)/,/port\s*=\s*(\d+)/];for(let s of r){let n=e.match(s);if(n)return parseInt(n[1])}}catch(e){c.warn("Failed to extract port from Python file",{error:e,filePath:t})}}async extractDjangoModels(t){try{return(b.readFileSync(t,"utf8").match(/class\s+(\w+)\s*\([^)]*Model[^)]*\)/g)||[]).map(s=>{let n=s.match(/class\s+(\w+)/);return n?n[1]:""}).filter(s=>s)}catch{return[]}}async findManagementCommands(t){let e=v.join(t,"management","commands");if(!b.existsSync(e))return[];try{return b.readdirSync(e).filter(s=>s.endsWith(".py")&&s!=="__init__.py").map(s=>v.basename(s,".py"))}catch{return[]}}async findVirtualEnv(t){let e=["venv","env",".venv",".env"];for(let r of e){let s=v.join(t,r);if(b.existsSync(s))return r}}async hasRequirementsFiles(t){let e=["requirements.txt","requirements-dev.txt","requirements"];for(let s of e)if(b.existsSync(v.join(t,s)))return!0;let r=v.join(t,"requirements");return!!(b.existsSync(r)&&b.statSync(r).isDirectory())}async hasTestFiles(t){let{glob:e}=await import("glob");return(await e("**/test*.py",{cwd:t,maxDepth:2})).length>0}async detectTestFramework(t,e){if(e.some(n=>n.includes("pytest")))return"pytest";if(e.some(n=>n.includes("nose")))return"nose";if(e.some(n=>n.includes("tox")))return"tox";let{glob:r}=await import("glob"),s=await r("**/test*.py",{cwd:t,maxDepth:2});for(let n of s)try{let i=b.readFileSync(v.join(t,n),"utf8");if(i.includes("import unittest")||i.includes("from unittest"))return"unittest"}catch{}}async detectGlobalPythonVersion(t){let e=v.join(t,".python-version");if(b.existsSync(e))try{return b.readFileSync(e,"utf8").trim()}catch{}let r=v.join(t,"runtime.txt");if(b.existsSync(r))try{let n=b.readFileSync(r,"utf8").trim().match(/python-(\d+\.\d+(?:\.\d+)?)/);if(n)return n[1]}catch{}}async detectDockerFiles(t){let{glob:e}=await import("glob");return await e("**/Dockerfile*",{cwd:t,maxDepth:2})}async detectJupyterNotebooks(t){let{glob:e}=await import("glob");return await e("**/*.ipynb",{cwd:t,maxDepth:3})}}});var O,P,Te,Tt=A(()=>{"use strict";O=h(require("fs")),P=h(require("path"));R();Te=class{async detect(t){try{if(c.info("Starting Serverless Framework workspace detection",{workspacePath:t}),!await this.hasServerlessIndicators(t))return null;let r=await this.detectServerlessServices(t);if(r.length===0)return null;let s=await this.detectSharedResources(t),n=await this.detectGlobalPlugins(t),i=O.existsSync(P.join(t,"package.json")),o=O.existsSync(P.join(t,"lerna.json")),l=O.existsSync(P.join(t,"serverless.yml"))||O.existsSync(P.join(t,"serverless.yaml")),u=await this.detectFrameworkVersion(t),m=this.extractDeploymentBuckets(r),p=this.extractCustomDomains(r),f;return r.length>1?f=i||o?"serverless-monorepo":"serverless-multi-service":f="serverless-single-service",{pattern:f,services:r,sharedResources:s,globalPlugins:n,hasCommonPackageJson:i,hasLernaConfig:o,hasWorkspaceConfig:l,frameworkVersion:u,deploymentBuckets:m,customDomains:p}}catch(e){return c.error("Failed to detect Serverless workspace",{error:e,workspacePath:t}),null}}async hasServerlessIndicators(t){let e=["serverless.yml","serverless.yaml","serverless.json","**/serverless.yml","**/serverless.yaml","sls.yml","sls.yaml"];for(let r of e){let{glob:s}=await import("glob");if((await s(r,{cwd:t,maxDepth:3})).length>0)return!0}return!1}async detectServerlessServices(t){let{glob:e}=await import("glob"),r=await e("**/serverless.{yml,yaml,json}",{cwd:t,maxDepth:3}),s=[];for(let n of r)try{let i=P.dirname(P.resolve(t,n)),o=await this.analyzeServerlessService(i,n);o&&s.push(o)}catch(i){c.warn("Failed to analyze Serverless service",{error:i,configFile:n})}return s}async analyzeServerlessService(t,e){try{let r=P.resolve(t,P.basename(e)),s;if(e.endsWith(".json"))s=JSON.parse(O.readFileSync(r,"utf8"));else{let ne=O.readFileSync(r,"utf8");s=await this.parseServerlessYaml(ne)}let n=s.service||P.basename(t),i=this.normalizeProvider(s.provider?.name||s.provider||"aws"),o=s.provider?.runtime||"nodejs18.x",l=s.provider?.region,u=s.provider?.stage,m=await this.parseFunctions(s.functions||{},t),p=await this.parseResources(s.resources||{}),f=await this.parseStages(s),S=s.plugins||[],U=s.custom||{},se=this.analyzeServiceCapabilities(s,m,p);return{name:n,path:t,provider:i,runtime:o,region:l,stage:u,functions:m,resources:p,stages:f,plugins:S,customVariables:U,...se}}catch(r){return c.error("Failed to analyze Serverless service",{error:r,servicePath:t,configFile:e}),null}}async parseServerlessYaml(t){let e=t.split(`
|
|
64
|
+
`),r={},s="";for(let n of e){let i=n.trim();if(!i||i.startsWith("#"))continue;let o=n.length-n.trimStart().length;if(i.includes(":")){let[l,u]=i.split(":",2),m=l.trim(),p=u?.trim()||"";o===0?(s=m,r[m]=p||{}):s&&((!r[s]||typeof r[s]!="object")&&(r[s]={}),r[s][m]=p||{})}}return r}normalizeProvider(t){switch(t.toLowerCase()){case"aws":case"amazon":return"aws";case"azure":case"microsoft":return"azure";case"gcp":case"google":case"google-cloud":return"gcp";case"cloudflare":return"cloudflare";case"knative":return"knative";case"openwhisk":return"openwhisk";default:return"unknown"}}async parseFunctions(t,e){let r=[];for(let[s,n]of Object.entries(t))if(typeof n=="object"&&n!==null){let i=n,o={name:s,handler:i.handler||`${s}.handler`,runtime:i.runtime,events:this.parseEvents(i.events||[]),environment:i.environment,layers:i.layers,timeout:i.timeout,memorySize:i.memorySize,path:await this.findFunctionPath(e,s,i.handler)};r.push(o)}return r}parseEvents(t){let e=[];for(let r of t)if(typeof r=="object"){let s=Object.keys(r)[0];s&&e.push(s)}else typeof r=="string"&&e.push(r);return e}async parseResources(t){let e=[];if(t.Resources){for(let[r,s]of Object.entries(t.Resources))if(typeof s=="object"&&s!==null){let n=s;e.push({type:n.Type||"Unknown",name:r,properties:n.Properties||{}})}}return e}async parseStages(t){let e=[];if(t.provider?.stage&&e.push({name:t.provider.stage,region:t.provider.region,environment:t.provider.environment}),t.custom?.stages){for(let[r,s]of Object.entries(t.custom.stages))if(typeof s=="object"){let n=s;e.push({name:r,region:n.region,environment:n.environment,customDomain:n.customDomain})}}return e}analyzeServiceCapabilities(t,e,r){let s=r.length>0,n=r.some(p=>p.type.includes("StepFunctions"))||t.stepFunctions!==void 0,i=e.some(p=>p.events.includes("http")||p.events.includes("httpApi"))||r.some(p=>p.type.includes("ApiGateway")),o=e.some(p=>p.events.includes("eventBridge"))||r.some(p=>p.type.includes("Events")),l=r.some(p=>p.type.includes("DynamoDB"))||e.some(p=>p.environment&&Object.values(p.environment).some(f=>typeof f=="string"&&f.includes("dynamodb"))),u=e.some(p=>p.events.includes("s3"))||r.some(p=>p.type.includes("S3")),m=e.some(p=>p.layers&&p.layers.length>0);return{hasCustomResources:s,hasStepFunctions:n,hasApiGateway:i,hasEventBridge:o,hasDynamoDB:l,hasS3:u,hasLambdaLayers:m}}async findFunctionPath(t,e,r){let s=r.split(".");if(s.length<2)return;let n=s[0],i=[".js",".ts",".py",".cs",".java",".go"];for(let o of i){let l=P.join(t,n+o);if(O.existsSync(l))return P.relative(t,l)}}async detectSharedResources(t){let e=[],r=["shared/**/*.yml","shared/**/*.yaml","resources/**/*.yml","resources/**/*.yaml","common/**/*.yml","common/**/*.yaml"];for(let s of r){let{glob:n}=await import("glob"),i=await n(s,{cwd:t,maxDepth:3});e.push(...i)}return e}async detectGlobalPlugins(t){let e=[],r=P.join(t,"package.json");if(O.existsSync(r))try{let s=JSON.parse(O.readFileSync(r,"utf8")),n={...s.dependencies,...s.devDependencies};for(let i of Object.keys(n))(i.startsWith("serverless-")||i.includes("serverless"))&&e.push(i)}catch(s){c.warn("Failed to parse root package.json",{error:s})}return e}async detectFrameworkVersion(t){let e=P.join(t,"package.json");if(O.existsSync(e))try{let r=JSON.parse(O.readFileSync(e,"utf8")),s={...r.dependencies,...r.devDependencies};if(s.serverless)return s.serverless.replace(/[\^~]/,"")}catch(r){c.warn("Failed to detect Serverless Framework version",{error:r})}}extractDeploymentBuckets(t){let e=[];for(let r of t){r.customVariables.deploymentBucket&&e.push(r.customVariables.deploymentBucket);for(let s of r.resources)s.type.includes("S3")&&s.properties.BucketName&&e.push(s.properties.BucketName)}return[...new Set(e)]}extractCustomDomains(t){let e=[];for(let r of t){if(r.customVariables.customDomain){let s=r.customVariables.customDomain;typeof s=="object"&&s.domainName?e.push(s.domainName):typeof s=="string"&&e.push(s)}for(let s of r.stages)s.customDomain&&e.push(s.customDomain)}return[...new Set(e)]}}});var _,W,xe,xt=A(()=>{"use strict";_=h(require("fs")),W=h(require("path"));R();xe=class{async detect(t){try{if(c.info("Starting AWS SAM workspace detection",{workspacePath:t}),!await this.hasSamIndicators(t))return null;let r=await this.detectSamApplications(t);if(r.length===0)return null;let s=await this.detectSharedLayers(t),n=await this.detectSharedTemplates(t),i=await this.detectSamCliVersion(t),o=await this.detectAwsRegion(t),l=await this.detectDeploymentBucket(t),u=this.analyzeWorkspaceCapabilities(r),m;return r.some(f=>f.nestedApplications.length>0)?m="sam-nested-apps":r.length>1?m="sam-multi-app":m="sam-single-app",{pattern:m,applications:r,sharedLayers:s,sharedTemplates:n,samCliVersion:i,awsRegion:o,deploymentBucket:l,...u}}catch(e){return c.error("Failed to detect AWS SAM workspace",{error:e,workspacePath:t}),null}}async hasSamIndicators(t){let e=["template.yaml","template.yml","sam.yaml","sam.yml","**/template.yaml","**/template.yml","samconfig.toml",".aws-sam/**"];for(let r of e){let{glob:s}=await import("glob");if((await s(r,{cwd:t,maxDepth:3})).length>0)return!0}return!1}async detectSamApplications(t){let{glob:e}=await import("glob"),r=await e("**/template.{yaml,yml}",{cwd:t,maxDepth:3}),s=[];for(let n of r)try{let i=W.dirname(W.resolve(t,n)),o=await this.analyzeSamApplication(i,n);o&&s.push(o)}catch(i){c.warn("Failed to analyze SAM application",{error:i,templateFile:n})}return s}async analyzeSamApplication(t,e){try{let r=W.resolve(t,W.basename(e)),s=_.readFileSync(r,"utf8"),n=await this.parseSamTemplate(s);if(!this.isSamTemplate(n))return null;let i=n.Parameters?.ApplicationName?.Default||W.basename(t),o=await this.parseSamFunctions(n.Resources||{},t),l=await this.parseSamApis(n.Resources||{},o),u=await this.parseSamTables(n.Resources||{}),m=await this.parseSamLayers(n.Resources||{},t),p=await this.findNestedApplications(n.Resources||{}),f=await this.hasLocalTesting(t),S=await this.hasIntegrationTests(t),U=await this.hasPipeline(t);return{name:i,path:t,templatePath:r,samVersion:n.AWSTemplateFormatVersion||"2010-09-09",transform:n.Transform||"AWS::Serverless-2016-10-31",description:n.Description,globals:n.Globals,parameters:n.Parameters,mappings:n.Mappings,conditions:n.Conditions,functions:o,apis:l,tables:u,layers:m,nestedApplications:p,outputs:n.Outputs,hasLocalTesting:f,hasIntegrationTests:S,hasPipeline:U}}catch(r){return c.error("Failed to analyze SAM application",{error:r,appPath:t,templateFile:e}),null}}async parseSamTemplate(t){let e=t.split(`
|
|
65
|
+
`),r={},s="",n="",i=0;for(let o of e){let l=o.trim();if(!l||l.startsWith("#"))continue;let u=o.length-o.trimStart().length;if(l.includes(":")){let[m,p]=l.split(":",2),f=m.trim(),S=p?.trim()||"";u===0?(s=f,r[f]=S||{},i=0):u===2&&s?(n=f,(!r[s]||typeof r[s]!="object")&&(r[s]={}),r[s][f]=S||{},i=2):u>i&&s&&n&&((!r[s][n]||typeof r[s][n]!="object")&&(r[s][n]={}),r[s][n][f]=S||{})}}return r}isSamTemplate(t){return t.Transform==="AWS::Serverless-2016-10-31"||t.Resources&&Object.values(t.Resources).some(e=>e.Type&&e.Type.startsWith("AWS::Serverless::"))}async parseSamFunctions(t,e){let r=[];for(let[s,n]of Object.entries(t)){let i=n;if(i.Type==="AWS::Serverless::Function"){let o=i.Properties||{},l={name:s,handler:o.Handler||"index.handler",runtime:o.Runtime||"nodejs18.x",codeUri:o.CodeUri||".",events:await this.parseSamEvents(o.Events||{}),environment:o.Environment?.Variables,layers:o.Layers,timeout:o.Timeout,memorySize:o.MemorySize,reservedConcurrency:o.ReservedConcurrencyLimit,policies:o.Policies};r.push(l)}}return r}async parseSamEvents(t){let e=[];for(let[r,s]of Object.entries(t)){let n=s,i=n.Type||"Unknown";e.push({type:this.normalizeSamEventType(i),properties:n.Properties||{}})}return e}normalizeSamEventType(t){switch(t){case"Api":return"Api";case"HttpApi":return"HttpApi";case"S3":return"S3";case"DynamoDB":return"DynamoDB";case"SQS":return"SQS";case"SNS":return"SNS";case"EventBridge":case"EventBridgeRule":return"EventBridge";case"Schedule":return"Schedule";case"CloudWatchEvent":return"CloudWatchEvent";default:return"Unknown"}}async parseSamApis(t,e){let r=[];for(let[s,n]of Object.entries(t)){let i=n;if(i.Type==="AWS::Serverless::Api"||i.Type==="AWS::Serverless::HttpApi"){let o=i.Properties||{},l={name:s,type:i.Type==="AWS::Serverless::HttpApi"?"HttpApi":"Api",stageName:o.StageName,cors:o.Cors!==void 0,auth:o.Auth,domain:o.Domain?.DomainName,endpoints:[]};for(let u of e)for(let m of u.events)(m.type==="Api"||m.type==="HttpApi")&&(m.properties.RestApiId===s||!m.properties.RestApiId)&&l.endpoints.push({method:m.properties.Method||"ANY",path:m.properties.Path||"/",functionName:u.name});r.push(l)}}if(r.length===0){let s=[],n=[];for(let i of e)for(let o of i.events)o.type==="Api"?s.push({method:o.properties.Method||"ANY",path:o.properties.Path||"/",functionName:i.name}):o.type==="HttpApi"&&n.push({method:o.properties.Method||"ANY",path:o.properties.Path||"/",functionName:i.name});s.length>0&&r.push({name:"ImplicitApi",type:"Api",endpoints:s}),n.length>0&&r.push({name:"ImplicitHttpApi",type:"HttpApi",endpoints:n})}return r}async parseSamTables(t){let e=[];for(let[r,s]of Object.entries(t)){let n=s;if(n.Type==="AWS::Serverless::SimpleTable"||n.Type==="AWS::DynamoDB::Table"){let i=n.Properties||{};e.push({name:r,attributeDefinitions:i.AttributeDefinitions||[],keySchema:i.KeySchema||[],billingMode:i.BillingMode,streamSpecification:i.StreamSpecification})}}return e}async parseSamLayers(t,e){let r=[];for(let[s,n]of Object.entries(t)){let i=n;if(i.Type==="AWS::Serverless::LayerVersion"){let o=i.Properties||{};r.push({name:s,contentUri:o.ContentUri||"layers/",compatibleRuntimes:o.CompatibleRuntimes||[],description:o.Description})}}return r}async findNestedApplications(t){let e=[];for(let[r,s]of Object.entries(t))s.Type==="AWS::Serverless::Application"&&e.push(r);return e}async hasLocalTesting(t){let e=["tests/**","test/**","**/test_*.py","**/test_*.js","**/test_*.ts","**/spec_*.js","**/spec_*.ts","pytest.ini","jest.config.js","jest.config.ts"];for(let r of e){let{glob:s}=await import("glob");if((await s(r,{cwd:t,maxDepth:2})).length>0)return!0}return!1}async hasIntegrationTests(t){let e=["integration/**","integration-tests/**","e2e/**","end-to-end/**","**/integration_*.py","**/integration_*.js","**/integration_*.ts","**/e2e_*.js","**/e2e_*.ts"];for(let r of e){let{glob:s}=await import("glob");if((await s(r,{cwd:t,maxDepth:2})).length>0)return!0}return!1}async hasPipeline(t){let e=["pipeline.yaml","pipeline.yml","buildspec.yml","buildspec.yaml",".github/workflows/**",".gitlab-ci.yml","Jenkinsfile","azure-pipelines.yml","codepipeline/**"];for(let r of e){let{glob:s}=await import("glob");if((await s(r,{cwd:t,maxDepth:2})).length>0)return!0}return!1}async detectSharedLayers(t){let e=[],r=W.join(t,"layers");if(_.existsSync(r)&&_.statSync(r).isDirectory()){let s=_.readdirSync(r).filter(n=>_.statSync(W.join(r,n)).isDirectory());for(let n of s)e.push({name:n,contentUri:`layers/${n}`,compatibleRuntimes:[],description:`Shared layer: ${n}`})}return e}async detectSharedTemplates(t){let{glob:e}=await import("glob"),r=["shared/**/*.{yaml,yml}","templates/**/*.{yaml,yml}","common/**/*.{yaml,yml}"],s=[];for(let n of r){let i=await e(n,{cwd:t,maxDepth:2});s.push(...i)}return s}async detectSamCliVersion(t){let e=W.join(t,"samconfig.toml");if(_.existsSync(e))try{let s=_.readFileSync(e,"utf8").match(/version\s*=\s*["']([^"']+)["']/);if(s)return s[1]}catch(r){c.warn("Failed to parse samconfig.toml",{error:r})}}async detectAwsRegion(t){let e=W.join(t,"samconfig.toml");if(_.existsSync(e))try{let s=_.readFileSync(e,"utf8").match(/region\s*=\s*["']([^"']+)["']/);if(s)return s[1]}catch(r){c.warn("Failed to parse region from samconfig.toml",{error:r})}}async detectDeploymentBucket(t){let e=W.join(t,"samconfig.toml");if(_.existsSync(e))try{let s=_.readFileSync(e,"utf8").match(/s3_bucket\s*=\s*["']([^"']+)["']/);if(s)return s[1]}catch(r){c.warn("Failed to parse deployment bucket from samconfig.toml",{error:r})}}analyzeWorkspaceCapabilities(t){let e=t.some(p=>p.layers.length>0),r=t.some(p=>p.hasPipeline),s=t.some(p=>p.hasLocalTesting),n=t.some(p=>p.apis.length>0),i=t.some(p=>p.tables.length>0),o=!1,l=!1,u=!1,m=!1;for(let p of t)for(let f of p.functions)for(let S of f.events)switch(S.type){case"S3":o=!0;break;case"EventBridge":l=!0;break;case"SQS":u=!0;break;case"SNS":m=!0;break}return{hasSharedResources:e,hasPipeline:r,hasLocalInvoke:s,hasApiGateway:n,hasDynamoDB:i,hasS3:o,hasEventBridge:l,hasSQS:u,hasSNS:m}}}});var w,I,Pe,Pt=A(()=>{"use strict";w=h(require("fs")),I=h(require("path"));R();Pe=class{async detect(t){try{if(c.info("Starting JavaScript/TypeScript workspace detection",{workspacePath:t}),!await this.hasJavaScriptIndicators(t))return null;let r=await this.detectPackageManager(t),s=await this.detectWorkspaceManager(t),n=await this.detectJavaScriptPackages(t,s);if(n.length===0)return null;let i=await this.detectNodeVersion(t),o=w.existsSync(I.join(t,"docker-compose.yml"))||w.existsSync(I.join(t,"docker-compose.yaml")),l=await this.hasCI(t),u=await this.hasHusky(t),m=await this.hasCommitizen(t),p=await this.hasRenovate(t),f=await this.hasSemanticRelease(t),S=await this.hasTurbo(t),U=await this.hasNx(t),se=await this.hasLerna(t),ne=await this.detectSharedConfigs(t),We=await this.detectGlobalDependencies(t),Y;return this.hasFullstackPattern(n)?Y="js-fullstack":s||n.length>1?Y=s?"js-monorepo":"js-multi-package":Y="js-single-package",{pattern:Y,packages:n,workspaceManager:s,nodeVersion:i,packageManager:r,hasDockerCompose:o,hasCI:l,hasHusky:u,hasCommitizen:m,hasRenovate:p,hasSemanticRelease:f,hasTurbo:S,hasNx:U,hasLerna:se,sharedConfigs:ne,globalDependencies:We}}catch(e){return c.error("Failed to detect JavaScript workspace",{error:e,workspacePath:t}),null}}async hasJavaScriptIndicators(t){let e=["package.json","**/*.js","**/*.ts","**/*.jsx","**/*.tsx","**/*.vue","node_modules/","yarn.lock","package-lock.json","pnpm-lock.yaml","bun.lockb"];for(let r of e){let{glob:s}=await import("glob");if((await s(r,{cwd:t,maxDepth:2})).length>0)return!0}return!1}async detectPackageManager(t){return w.existsSync(I.join(t,"bun.lockb"))?"bun":w.existsSync(I.join(t,"pnpm-lock.yaml"))?"pnpm":w.existsSync(I.join(t,"yarn.lock"))?"yarn":"npm"}async detectWorkspaceManager(t){if(w.existsSync(I.join(t,"nx.json")))return"nx";if(w.existsSync(I.join(t,"lerna.json")))return"lerna";if(w.existsSync(I.join(t,"rush.json")))return"rush";let e=I.join(t,"package.json");if(w.existsSync(e))try{if(JSON.parse(w.readFileSync(e,"utf8")).workspaces)switch(await this.detectPackageManager(t)){case"yarn":return"yarn-workspaces";case"npm":return"npm-workspaces";case"pnpm":return"pnpm-workspaces"}}catch(r){c.warn("Failed to parse root package.json",{error:r})}}async detectJavaScriptPackages(t,e){let r=[],{glob:s}=await import("glob"),n=await s("**/package.json",{cwd:t,maxDepth:3,ignore:["**/node_modules/**"]});for(let i of n)try{let o=I.dirname(I.resolve(t,i)),l=await this.analyzeJavaScriptPackage(o);l&&r.push(l)}catch(o){c.warn("Failed to analyze JavaScript package",{error:o,packageJsonFile:i})}return r}async analyzeJavaScriptPackage(t){try{let e=I.join(t,"package.json"),r=JSON.parse(w.readFileSync(e,"utf8")),s=Object.keys(r.dependencies||{}),n=Object.keys(r.devDependencies||{}),i=[...s,...n],o=this.detectFramework(i,t),l=this.detectBuildTool(i,t),u=await this.detectPackageManager(t),m=this.detectRuntime(o,i),p=await this.detectLanguage(t,i),f=this.detectPackageType(r,o,i),S=await this.extractPort(t,r.scripts||{}),U=this.detectTestFramework(i),se=await this.hasTestFiles(t)||U!==void 0,ne=this.hasLinting(i,t),We=p!=="javascript"||i.includes("typescript"),Y=w.existsSync(I.join(t,"Dockerfile")),nt=!!(r.workspaces||r.nx),Ut=this.extractWorkspacePackages(r);return{name:r.name||I.basename(t),path:t,type:f,framework:o,buildTool:l,packageManager:u,runtime:m,language:p,port:S,scripts:r.scripts||{},dependencies:s,devDependencies:n,hasTests:se,testFramework:U,hasLinting:ne,hasTypeChecking:We,hasDockerfile:Y,isWorkspaceRoot:nt,workspacePackages:Ut}}catch(e){return c.error("Failed to analyze JavaScript package",{error:e,packagePath:t}),null}}detectFramework(t,e){return t.includes("react")?t.includes("next")?"next":"react":t.some(r=>r.startsWith("@angular/"))||w.existsSync(I.join(e,"angular.json"))?"angular":t.includes("vue")?t.includes("nuxt")?"nuxt":"vue":t.includes("svelte")?"svelte":t.includes("@nestjs/core")?"nest":t.includes("fastify")?"fastify":t.includes("express")?"express":t.some(r=>["node","nodemon","@types/node"].includes(r))?"node":"none"}detectBuildTool(t,e){return t.includes("@angular/cli")||w.existsSync(I.join(e,"angular.json"))?"angular-cli":t.includes("turbo")?"turbo":t.includes("vite")?"vite":t.includes("webpack")?"webpack":t.includes("rollup")?"rollup":t.includes("parcel")?"parcel":t.includes("esbuild")?"esbuild":"none"}detectRuntime(t,e){return["react","angular","vue","svelte"].includes(t)?"browser":["next","nuxt"].includes(t)?"both":["express","fastify","nest","node"].includes(t)||e.some(r=>["express","fastify","@nestjs/core","http-server"].includes(r))?"node":e.some(r=>["react-dom","@angular/platform-browser","vue"].includes(r))?"browser":"node"}async detectLanguage(t,e){let r=e.includes("typescript")||w.existsSync(I.join(t,"tsconfig.json")),{glob:s}=await import("glob"),n=await s("**/*.{js,jsx}",{cwd:t,maxDepth:2,ignore:["**/node_modules/**"]}),i=await s("**/*.{ts,tsx}",{cwd:t,maxDepth:2,ignore:["**/node_modules/**"]});return i.length===0&&n.length>0?"javascript":n.length===0&&i.length>0?"typescript":n.length>0&&i.length>0?"mixed":r?"typescript":"javascript"}detectPackageType(t,e,r){return t.private===!1||t.publishConfig?"library":["react","angular","vue","svelte","next","nuxt"].includes(e)||["express","fastify","nest","node"].includes(e)?"app":t.name?.includes("config")||t.name?.includes("eslint")?"config":r.some(s=>["storybook","@storybook/react","@storybook/angular"].includes(s))?"component":t.bin||r.some(s=>["commander","yargs","inquirer"].includes(s))?"tool":"app"}async extractPort(t,e){for(let[s,n]of Object.entries(e))if(["start","dev","serve"].includes(s)){let i=n.match(/--port[=\s]+(\d+)|-p[=\s]+(\d+)|PORT[=\s]+(\d+)/);if(i)return parseInt(i[1]||i[2]||i[3])}let r=["vite.config.js","vite.config.ts","vue.config.js","angular.json",".env",".env.local"];for(let s of r){let n=I.join(t,s);if(w.existsSync(n))try{let i=w.readFileSync(n,"utf8");if(s==="angular.json"){let o=JSON.parse(i),u=Object.values(o.projects||{})[0]?.architect?.serve?.options?.port;if(u)return u}else{let o=i.match(/port[:\s=]+(\d+)/i);if(o)return parseInt(o[1])}}catch{}}}detectTestFramework(t){if(t.includes("jest"))return"jest";if(t.includes("vitest"))return"vitest";if(t.includes("mocha"))return"mocha";if(t.includes("cypress"))return"cypress";if(t.includes("playwright")||t.includes("@playwright/test"))return"playwright";if(t.includes("jasmine"))return"jasmine";if(t.includes("karma"))return"karma"}async hasTestFiles(t){let{glob:e}=await import("glob"),r=["**/*.test.{js,ts,jsx,tsx}","**/*.spec.{js,ts,jsx,tsx}","**/test/**/*.{js,ts,jsx,tsx}","**/tests/**/*.{js,ts,jsx,tsx}","**/__tests__/**/*.{js,ts,jsx,tsx}"];for(let s of r)if((await e(s,{cwd:t,maxDepth:3,ignore:["**/node_modules/**"]})).length>0)return!0;return!1}hasLinting(t,e){return t.some(r=>r.includes("eslint"))||w.existsSync(I.join(e,".eslintrc.js"))||w.existsSync(I.join(e,".eslintrc.json"))||w.existsSync(I.join(e,"eslint.config.js"))}extractWorkspacePackages(t){if(t.workspaces){if(Array.isArray(t.workspaces))return t.workspaces;if(t.workspaces.packages)return t.workspaces.packages}}hasFullstackPattern(t){let e=["react","angular","vue","svelte"],r=["express","fastify","nest","node"],s=t.some(i=>e.includes(i.framework)),n=t.some(i=>r.includes(i.framework));return s&&n}async detectNodeVersion(t){let e=I.join(t,".nvmrc");if(w.existsSync(e))try{return w.readFileSync(e,"utf8").trim()}catch{}let r=I.join(t,"package.json");if(w.existsSync(r))try{let s=JSON.parse(w.readFileSync(r,"utf8"));if(s.engines?.node)return s.engines.node}catch{}}async hasCI(t){let e=[".github/workflows",".gitlab-ci.yml","azure-pipelines.yml","Jenkinsfile",".circleci/config.yml",".travis.yml"];for(let r of e)if(w.existsSync(I.join(t,r)))return!0;return!1}async hasHusky(t){return w.existsSync(I.join(t,".husky"))||await this.packageHasDependency(t,"husky")}async hasCommitizen(t){return await this.packageHasDependency(t,"commitizen")||await this.packageHasDependency(t,"cz-conventional-changelog")}async hasRenovate(t){return w.existsSync(I.join(t,"renovate.json"))||w.existsSync(I.join(t,".renovaterc"))}async hasSemanticRelease(t){return await this.packageHasDependency(t,"semantic-release")}async hasTurbo(t){return w.existsSync(I.join(t,"turbo.json"))||await this.packageHasDependency(t,"turbo")}async hasNx(t){return w.existsSync(I.join(t,"nx.json"))}async hasLerna(t){return w.existsSync(I.join(t,"lerna.json"))}async packageHasDependency(t,e){let r=I.join(t,"package.json");if(!w.existsSync(r))return!1;try{let s=JSON.parse(w.readFileSync(r,"utf8")),n={...s.dependencies,...s.devDependencies};return e in n}catch{return!1}}async detectSharedConfigs(t){let e=[".eslintrc.js",".eslintrc.json","eslint.config.js","prettier.config.js",".prettierrc","jest.config.js","vitest.config.js","tsconfig.json","tsconfig.base.json","babel.config.js",".babelrc","webpack.config.js","vite.config.js","tailwind.config.js",".editorconfig",".gitignore"],r=[];for(let s of e)w.existsSync(I.join(t,s))&&r.push(s);return r}async detectGlobalDependencies(t){let e=I.join(t,"package.json");if(!w.existsSync(e))return[];try{let r=JSON.parse(w.readFileSync(e,"utf8"));return Object.keys({...r.dependencies,...r.devDependencies})}catch{return[]}}}});var Rt={};Q(Rt,{WorkspaceRegistrationWizard:()=>Qe});var M,k,D,C,Qe,Dt=A(()=>{"use strict";M=h(require("prompts")),k=h(require("chalk")),D=h(require("fs")),C=h(require("path"));Et();R();Ct();At();Tt();xt();Pt();Qe=class{constructor(){this.configService=new Ee,this.dotNetDetector=new Ce,this.pythonDetector=new Ae,this.serverlessDetector=new Te,this.awsSamDetector=new xe,this.jsDetector=new Pe}async run(t){try{console.log(k.default.blue.bold(`
|
|
66
|
+
\u{1F680} Task Shepherd Workspace Registration`)),console.log(k.default.gray("\u2550".repeat(50))),console.log(k.default.gray(`Registering workspace at: ${t}`)),console.log();let e=C.join(t,"task-shepherd-workspace.json"),r=D.existsSync(e);if(r){console.log(k.default.yellow("\u26A0\uFE0F Existing workspace configuration found"));let i=await(0,M.default)({type:"select",name:"action",message:"What would you like to do?",choices:[{title:"Register workspace with existing configuration",value:"register"},{title:"Edit configuration and register",value:"edit"},{title:"Cancel",value:"cancel"}],initial:0});if(i.action==="cancel"){console.log(k.default.yellow("Registration cancelled"));return}if(i.action==="register"){await this.registerExistingConfig(t,e);return}}console.log(k.default.blue("\u{1F50D} Analyzing workspace..."));let s=await this.analyzeWorkspace(t);if(r)try{let i=D.readFileSync(e,"utf8"),o=JSON.parse(i);s=this.mergeWithExistingConfig(s,o.workspace)}catch(i){c.warn("Could not load existing config for editing",{error:i})}let n=await this.collectWorkspaceInfo(s);await this.saveWorkspaceConfig(t,n),this.displaySummary(t,n)}catch(e){throw c.error("Workspace registration failed",{error:e,workspacePath:t}),e}}async registerExistingConfig(t,e){try{let r=D.readFileSync(e,"utf8"),s=JSON.parse(r);console.log(k.default.blue(`
|
|
67
|
+
\u{1F4CB} Existing Configuration`)),console.log(k.default.gray("\u2550".repeat(30)));let n=s.workspace;if(console.log(k.default.cyan("Workspace:")),console.log(` Name: ${k.default.white(n.name)}`),n.description&&console.log(` Description: ${k.default.white(n.description)}`),console.log(` Pattern: ${k.default.white(n.pattern)}`),n.services&&n.services.length>0&&(console.log(k.default.cyan(`
|
|
68
|
+
Services:`)),n.services.forEach(o=>{console.log(` \u2022 ${k.default.white(o.name)} (${o.technology})`)})),!(await(0,M.default)({type:"confirm",name:"proceed",message:"Register this workspace with the backend?",initial:!0})).proceed){console.log(k.default.yellow("Registration cancelled"));return}console.log(k.default.green(`
|
|
69
|
+
\u2705 Workspace registered successfully with existing configuration`)),console.log(k.default.gray("Run `task-shepherd-agent workspace sync` to sync with backend"))}catch(r){throw c.error("Failed to load existing configuration",{error:r,configPath:e}),new Error(`Failed to load existing configuration: ${r instanceof Error?r.message:r}`)}}mergeWithExistingConfig(t,e){return{name:e.name||t.name,description:e.description||t.description,pattern:e.pattern||t.pattern,detectedTechnologies:t.detectedTechnologies,services:e.services||t.services,capabilities:e.capabilities||t.capabilities,tags:e.tags||t.tags}}async analyzeWorkspace(t){let e={};try{console.log(k.default.gray(" Detecting workspace technologies..."));let[r,s,n,i,o]=await Promise.all([this.dotNetDetector.detect(t).catch(()=>null),this.pythonDetector.detect(t).catch(()=>null),this.serverlessDetector.detect(t).catch(()=>null),this.awsSamDetector.detect(t).catch(()=>null),this.jsDetector.detect(t).catch(()=>null)]),l=[],u=[],m="multi-repo";if(r&&(console.log(k.default.gray(` \u2713 Detected .NET workspace (${r.pattern})`)),u.push("dotnet","csharp"),r.solutions.forEach(p=>{l.push({name:p.name,technology:"dotnet-solution",framework:"dotnet",path:C.relative(t,p.path)||"."})}),[...r.standaloneProjects,...r.sharedProjects].forEach(p=>{l.push({name:p.name,technology:p.type,framework:"dotnet",port:p.port,path:C.relative(t,p.path)||"."})}),r.solutions.length>1&&(m="monorepo")),s&&(console.log(k.default.gray(` \u2713 Detected Python workspace (${s.pattern})`)),u.push("python"),s.projects.forEach(p=>{u.push(p.framework||"python"),p.apps.forEach(f=>{l.push({name:f.name,technology:f.type,framework:p.framework,runtime:"python",port:f.port,path:C.relative(t,f.path)||"."})})}),s.pattern==="python-monorepo"&&(m="monorepo")),n&&(console.log(k.default.gray(` \u2713 Detected Serverless workspace (${n.pattern})`)),u.push("serverless"),n.services.forEach(p=>{l.push({name:p.name,technology:"serverless",framework:"serverless-framework",runtime:p.runtime,path:C.relative(t,p.path)||"."})}),n.pattern==="serverless-monorepo"&&(m="monorepo")),i&&(console.log(k.default.gray(` \u2713 Detected AWS SAM workspace (${i.pattern})`)),u.push("aws-sam","serverless"),i.applications.forEach(p=>{l.push({name:p.name,technology:"aws-sam",framework:"aws-sam",runtime:"serverless",path:C.relative(t,p.path)||"."})}),i.pattern==="sam-multi-app"&&(m="monorepo")),o&&(console.log(k.default.gray(` \u2713 Detected JavaScript/TypeScript workspace (${o.pattern})`)),u.push("javascript","typescript","nodejs"),o.packages.forEach(p=>{p.framework!=="none"&&u.push(p.framework),l.push({name:p.name,technology:p.type,framework:p.framework,runtime:p.runtime,port:p.port,path:C.relative(t,p.path)||"."})}),o.pattern==="js-monorepo"&&(m="monorepo")),l.length===0){console.log(k.default.gray(" Using generic workspace detection..."));let p=await this.configService.discoverWorkspaces(t);if(p.length>0){let f=p[0];e.name=f.name,e.pattern=f.pattern,e.services=f.services.map(S=>({name:S.name,technology:S.technology,port:S.port,path:C.relative(t,S.path)||"."}))}}else e.name=C.basename(t),e.pattern=m,e.detectedTechnologies=[...new Set(u)],e.services=l;e.capabilities=await this.detectCapabilities(t,e.detectedTechnologies),e.tags=await this.suggestTags(t,e),e.detectedTechnologies&&e.detectedTechnologies.length>0&&console.log(k.default.gray(` Technologies: ${e.detectedTechnologies.join(", ")}`))}catch(r){c.warn("Failed to analyze workspace, will use defaults",{error:r,workspacePath:t}),e.name=C.basename(t),e.pattern="multi-repo",e.services=[],e.capabilities=[],e.tags=[]}return e}async collectWorkspaceInfo(t){console.log(k.default.blue(`
|
|
70
|
+
\u{1F4CB} Workspace Configuration`)),console.log(k.default.gray(`Press Enter to accept suggested values
|
|
71
|
+
`)),t.detectedTechnologies&&t.detectedTechnologies.length>0&&(console.log(k.default.cyan("Detected Technologies:")),console.log(` ${t.detectedTechnologies.map(i=>k.default.white(i)).join(", ")}`),console.log());let e=await(0,M.default)([{type:"text",name:"name",message:"Workspace name:",initial:t.name||C.basename(process.cwd()),validate:i=>i.trim().length>0?!0:"Name is required"},{type:"text",name:"description",message:"Description (optional):",initial:this.generateDescription(t)},{type:"select",name:"pattern",message:"Workspace pattern:",choices:[{title:"Monorepo - Single repository with multiple services",value:"monorepo"},{title:"Multi-repo - Multiple related repositories",value:"multi-repo"},{title:"Hybrid - Mix of monorepo and multi-repo patterns",value:"hybrid"}],initial:t.pattern==="monorepo"?0:t.pattern==="hybrid"?2:1}]);if(!e.name)throw new Error("Workspace registration cancelled");let r=await this.collectServicesInfo(t.services||[]);if((await(0,M.default)({type:"confirm",name:"manual",message:"Add services manually (if auto-detection missed anything)?",initial:!1})).manual){let i=await this.collectManualServices();r.push(...i)}let n=await(0,M.default)([{type:"list",name:"capabilities",message:"Capabilities (comma-separated):",initial:(t.capabilities||[]).join(", "),separator:","},{type:"list",name:"tags",message:"Tags (comma-separated):",initial:(t.tags||[]).join(", "),separator:","}]);return{name:e.name,description:e.description||void 0,pattern:e.pattern,detectedTechnologies:t.detectedTechnologies,services:r,capabilities:n.capabilities?.filter(i=>i.trim())||[],tags:n.tags?.filter(i=>i.trim())||[]}}async collectServicesInfo(t){console.log(k.default.blue(`
|
|
72
|
+
\u2699\uFE0F Services Configuration`));let e=[];if(t.length===0)return console.log(k.default.gray(" No services were automatically detected")),e;console.log(k.default.gray(` Found ${t.length} potential service(s)
|
|
73
|
+
`));for(let r of t){let s=this.formatServiceDescription(r);if((await(0,M.default)({type:"confirm",name:"include",message:`Include detected service: ${s}?`,initial:!0})).include){let i=await(0,M.default)([{type:"text",name:"name",message:"Service name:",initial:r.name,validate:o=>o.trim().length>0?!0:"Name is required"},{type:"text",name:"technology",message:"Technology/Framework:",initial:r.technology},{type:"number",name:"port",message:"Port (optional):",initial:r.port,min:1,max:65535},{type:"text",name:"path",message:"Relative path:",initial:r.path||"."}]);i.name&&e.push({name:i.name,technology:i.technology||"unknown",framework:r.framework,runtime:r.runtime,port:i.port||void 0,path:i.path||"."})}}return e}async detectCapabilities(t,e){let r=[];try{e&&((e.includes("dotnet")||e.includes("csharp"))&&r.push("dotnet-development","enterprise-development"),e.includes("python")&&r.push("python-development"),e.includes("django")&&r.push("web-development","orm-development"),(e.includes("flask")||e.includes("fastapi"))&&r.push("api-development","microservices"),(e.includes("serverless")||e.includes("aws-sam"))&&r.push("serverless-development","cloud-native"),e.includes("react")&&r.push("frontend-development","spa-development"),e.includes("angular")&&r.push("frontend-development","enterprise-frontend"),e.includes("nodejs")&&r.push("backend-development","javascript-development"),e.includes("typescript")&&r.push("type-safe-development"));let s=C.join(t,"package.json");if(D.existsSync(s)){r.push("nodejs-development");let n=JSON.parse(D.readFileSync(s,"utf8")),i={...n.dependencies,...n.devDependencies};i.react&&r.push("react-development"),i.typescript&&r.push("typescript-development"),i.graphql&&r.push("graphql-api"),i.express&&r.push("rest-api"),(i.jest||i.vitest)&&r.push("automated-testing"),i.docker&&r.push("containerization")}(D.existsSync(C.join(t,"requirements.txt"))||D.existsSync(C.join(t,"pyproject.toml")))&&r.push("python-development"),D.existsSync(C.join(t,"global.json"))&&r.push("dotnet-development"),D.existsSync(C.join(t,"Dockerfile"))&&r.push("containerization"),D.existsSync(C.join(t,".github"))&&r.push("ci-cd"),D.existsSync(C.join(t,"docker-compose.yml"))&&r.push("multi-service-orchestration"),D.existsSync(C.join(t,"serverless.yml"))&&r.push("serverless-development"),D.existsSync(C.join(t,"template.yaml"))&&r.push("aws-sam-development")}catch(s){c.warn("Failed to detect capabilities",{error:s,workspacePath:t})}return[...new Set(r)]}async suggestTags(t,e){let r=[];e.pattern&&r.push(e.pattern),e.services?.forEach(n=>{n.technology&&!r.includes(n.technology)&&r.push(n.technology)});let s=e.name?.toLowerCase()||"";return s.includes("api")&&r.push("api"),s.includes("web")&&r.push("web"),s.includes("mobile")&&r.push("mobile"),s.includes("admin")&&r.push("admin"),s.includes("dashboard")&&r.push("dashboard"),r}async saveWorkspaceConfig(t,e){let r=C.join(t,"task-shepherd-workspace.json"),s={version:"1.0",workspace:{name:e.name,description:e.description,pattern:e.pattern,services:e.services.map(n=>({name:n.name,technology:n.technology,port:n.port,path:n.path})),capabilities:e.capabilities,tags:e.tags},metadata:{createdAt:new Date().toISOString(),updatedAt:new Date().toISOString(),configVersion:"1.0"}};try{await D.promises.writeFile(r,JSON.stringify(s,null,2)+`
|
|
74
|
+
`,"utf8"),console.log(k.default.green(`
|
|
75
|
+
\u2705 Workspace configuration saved to ${k.default.bold("task-shepherd-workspace.json")}`))}catch(n){throw c.error("Failed to save workspace configuration",{error:n,configPath:r}),new Error(`Failed to save configuration: ${n instanceof Error?n.message:n}`)}}displaySummary(t,e){console.log(k.default.blue.bold(`
|
|
76
|
+
\u{1F4CB} Registration Summary`)),console.log(k.default.gray("\u2550".repeat(40))),console.log(k.default.cyan("Workspace:")),console.log(` Name: ${k.default.white(e.name)}`),e.description&&console.log(` Description: ${k.default.white(e.description)}`),console.log(` Pattern: ${k.default.white(e.pattern)}`),e.services.length>0&&(console.log(k.default.cyan(`
|
|
77
|
+
Services:`)),e.services.forEach(r=>{let s=r.framework?`${r.technology}/${r.framework}`:r.technology;console.log(` \u2022 ${k.default.white(r.name)} (${s})`),r.runtime&&r.runtime!==r.framework&&console.log(` Runtime: ${r.runtime}`),r.port&&console.log(` Port: ${r.port}`),r.path&&r.path!=="."&&console.log(` Path: ${r.path}`)})),e.capabilities&&e.capabilities.length>0&&(console.log(k.default.cyan(`
|
|
78
|
+
Capabilities:`)),console.log(` ${e.capabilities.map(r=>k.default.white(r)).join(", ")}`)),e.tags&&e.tags.length>0&&(console.log(k.default.cyan(`
|
|
79
|
+
Tags:`)),console.log(` ${e.tags.map(r=>k.default.white(r)).join(", ")}`)),console.log(k.default.cyan(`
|
|
80
|
+
Next Steps:`)),console.log(` \u2022 Configuration saved to ${k.default.bold("task-shepherd-workspace.json")}`),console.log(" \u2022 Commit this file to version control"),console.log(` \u2022 Run ${k.default.bold("task-shepherd-agent workspace sync")} to sync with backend`),console.log()}generateDescription(t){if(!t.detectedTechnologies||t.detectedTechnologies.length===0)return"";let e=t.detectedTechnologies,r=[];return(e.includes("react")||e.includes("angular")||e.includes("vue"))&&r.push("frontend application"),e.includes("nodejs")&&(e.includes("express")||e.includes("fastify"))&&r.push("backend API"),e.includes("dotnet")&&r.push(".NET application"),e.includes("python")&&(e.includes("django")?r.push("Django web application"):e.includes("flask")||e.includes("fastapi")?r.push("Python API"):r.push("Python application")),(e.includes("serverless")||e.includes("aws-sam"))&&r.push("serverless application"),r.length===0?`Application built with ${e.slice(0,3).join(", ")}`:r.join(" and ")}formatServiceDescription(t){let e=`${k.default.cyan(t.name)}`;return t.framework&&t.framework!=="none"?e+=` (${t.framework})`:e+=` (${t.technology})`,t.port&&(e+=` on port ${t.port}`),t.path&&t.path!=="."&&(e+=` at ${t.path}`),e}async collectManualServices(){console.log(k.default.blue(`
|
|
81
|
+
\u2795 Manual Service Entry`));let t=[],e=!0;for(;e;){let r=await(0,M.default)([{type:"text",name:"name",message:"Service name:",validate:n=>n.trim().length>0?!0:"Name is required"},{type:"select",name:"technology",message:"Technology/Framework:",choices:[{title:"Node.js/Express",value:"nodejs-express"},{title:"React",value:"react"},{title:"Angular",value:"angular"},{title:"Vue.js",value:"vue"},{title:".NET Core API",value:"dotnet-webapi"},{title:".NET Core MVC",value:"dotnet-mvc"},{title:"Python/Django",value:"python-django"},{title:"Python/Flask",value:"python-flask"},{title:"Python/FastAPI",value:"python-fastapi"},{title:"AWS Lambda",value:"aws-lambda"},{title:"Serverless Function",value:"serverless-function"},{title:"Database",value:"database"},{title:"Other",value:"other"}]},{type:"text",name:"framework",message:"Framework (if different from technology):",initial:""},{type:"number",name:"port",message:"Port (optional):",min:1,max:65535},{type:"text",name:"path",message:"Relative path:",initial:"."}]);r.name&&t.push({name:r.name,technology:r.technology,framework:r.framework||void 0,port:r.port||void 0,path:r.path||"."}),e=(await(0,M.default)({type:"confirm",name:"continue",message:"Add another service?",initial:!1})).continue}return t}}});var Ze={};Q(Ze,{WorkspaceSyncService:()=>Re,getWorkspaceSyncService:()=>hr});function hr(){return Xe||(Xe=new Re),Xe}var _t,Re,Xe,et=A(()=>{"use strict";R();B();ke();_t=require("events"),Re=class extends _t.EventEmitter{constructor(e=3e4){super();this.syncIntervalMs=e;this.syncInProgress=!1;this.syncTimer=null;this.isConnected=!1}startPeriodicSync(){this.syncTimer||(c.info("Starting periodic workspace sync",{intervalMs:this.syncIntervalMs}),this.syncWorkspaces(),this.syncTimer=setInterval(()=>{this.syncWorkspaces()},this.syncIntervalMs))}stopPeriodicSync(){this.syncTimer&&(clearInterval(this.syncTimer),this.syncTimer=null,c.info("Stopped periodic workspace sync"))}setConnectionStatus(e,r=!0){this.isConnected=e,e&&r?(c.info("Backend connection established, triggering workspace sync"),this.syncWorkspaces()):e?c.info("Backend connection enabled"):c.warn("Backend connection lost, workspace sync will pause")}async forceSyncAllWorkspaces(){if(this.syncInProgress){c.debug("Workspace sync already in progress, skipping");return}if(!this.isConnected){c.debug("Backend not connected, skipping workspace sync");return}this.syncInProgress=!0,this.emit("syncStarted");try{let e=z(),r=e.getAllWorkspaces();if(r.length===0){c.debug("No workspaces to sync"),this.emit("syncCompleted",{synced:0,failed:0}),this.syncInProgress=!1;return}c.info("Force syncing ALL workspaces",{totalCount:r.length});let s=te(),n=0,i=0;for(let o of r)try{c.debug("Force syncing workspace",{workspaceId:o.workspace.workspaceId,name:o.workspace.name,currentStatus:o.syncStatus}),await s.registerWorkspace({workspaceId:o.workspace.workspaceId,name:o.workspace.name,path:o.workspace.path,pattern:o.workspace.pattern,description:`${o.workspace.pattern} workspace with ${o.workspace.services.length} services`,services:o.workspace.services.map(l=>({serviceId:l.id,name:l.name,path:l.relativePath||l.path,technology:l.technology,port:l.port}))}),await e.markWorkspaceSynced(o.workspace.workspaceId),n++,this.emit("workspaceSynced",o.workspace)}catch(l){c.error("Failed to force sync workspace",{workspaceId:o.workspace.workspaceId,error:l instanceof Error?l.message:String(l)}),await e.markWorkspaceSyncFailed(o.workspace.workspaceId,l instanceof Error?l.message:"Unknown error"),i++,this.emit("workspaceSyncFailed",o.workspace,l)}c.info("Force workspace sync completed",{total:r.length,synced:n,failed:i}),this.emit("syncCompleted",{synced:n,failed:i})}catch(e){c.error("Force workspace sync failed:",e),this.emit("syncFailed",e)}finally{this.syncInProgress=!1}}async syncWorkspaces(){if(this.syncInProgress){c.debug("Workspace sync already in progress, skipping");return}if(!this.isConnected){c.debug("Backend not connected, skipping workspace sync");return}this.syncInProgress=!0,this.emit("syncStarted");try{let e=z(),r=e.getWorkspacesBySyncStatus("pending"),s=e.getWorkspacesBySyncStatus("failed"),n=[...r,...s];if(n.length===0){c.debug("No workspaces to sync"),this.emit("syncCompleted",{synced:0,failed:0}),this.syncInProgress=!1;return}c.info("Starting workspace sync",{pendingCount:r.length,failedRetryCount:s.length});let i=te(),o=0,l=0;for(let u of n)try{c.debug("Syncing workspace",{workspaceId:u.workspace.workspaceId,name:u.workspace.name}),await i.registerWorkspace({workspaceId:u.workspace.workspaceId,name:u.workspace.name,path:u.workspace.path,pattern:u.workspace.pattern,description:`${u.workspace.pattern} workspace with ${u.workspace.services.length} services`,services:u.workspace.services.map(m=>({serviceId:m.id,name:m.name,path:m.relativePath||m.path,technology:m.technology,port:m.port}))}),await e.markWorkspaceSynced(u.workspace.workspaceId),o++,this.emit("workspaceSynced",u.workspace)}catch(m){c.error("Failed to sync workspace",{workspaceId:u.workspace.workspaceId,error:m instanceof Error?m.message:String(m)}),await e.markWorkspaceSyncFailed(u.workspace.workspaceId,m instanceof Error?m.message:"Unknown error"),l++,this.emit("workspaceSyncFailed",u.workspace,m)}c.info("Workspace sync completed",{synced:o,failed:l}),this.emit("syncCompleted",{synced:o,failed:l})}catch(e){c.error("Workspace sync failed",{error:e instanceof Error?e.message:String(e)}),this.emit("syncError",e)}finally{this.syncInProgress=!1}}async syncWorkspace(e){let r=z(),s=r.getWorkspace(e);if(!s)throw new Error(`Workspace not found: ${e}`);try{await te().registerWorkspace({workspaceId:s.workspace.workspaceId,name:s.workspace.name,path:s.workspace.path,pattern:s.workspace.pattern,description:`${s.workspace.pattern} workspace with ${s.workspace.services.length} services`,services:s.workspace.services.map(i=>({serviceId:i.id,name:i.name,technology:i.technology,port:i.port}))}),await r.markWorkspaceSynced(s.workspace.workspaceId),this.emit("workspaceSynced",s.workspace)}catch(n){throw await r.markWorkspaceSyncFailed(s.workspace.workspaceId,n instanceof Error?n.message:"Unknown error"),n}}getSyncStatus(){let e=z();return{isConnected:this.isConnected,syncInProgress:this.syncInProgress,stats:e.getSyncStats()}}},Xe=null});var tt=A(()=>{"use strict"});function De(){if(!Nt)throw new Error("WorkItemErrorTracker not initialized. Call initializeWorkItemErrorTracker first.");return Nt}var Nt,jt=A(()=>{"use strict";R();tt();Nt=null});var _e={};Q(_e,{createDebugWorkItemCommand:()=>yr});function yr(){let a=new Wt.Command("debug");return a.description("Debug work items and analyze error patterns").option("-i, --work-item-id <id>","Debug specific work item by ID").option("-t, --work-type <type>","Analyze error patterns for work type").option("-v, --verbose","Show detailed information").option("--timeline","Show execution timeline").option("--suggestions","Show fix suggestions").option("--export <format>","Export debug data (json|csv)").action(async t=>{try{t.workItemId?await vr(t.workItemId,t):t.workType?await kr(t.workType,t):await br(t)}catch(e){console.error(E.default.red("\u274C Debug command failed:"),e instanceof Error?e.message:e),process.exit(1)}}),a}async function vr(a,t){console.log(E.default.blue(`\u{1F50D} Debugging work item: ${a}
|
|
82
|
+
`));try{let e=De(),r=e.getErrorHistory(a),s=e.getLogHistory(a);if(r.length===0&&s.length===0){console.log(E.default.yellow("\u26A0\uFE0F No debug data found for this work item")),console.log(E.default.gray("This could mean:")),console.log(E.default.gray(" \u2022 Work item hasn't been processed yet")),console.log(E.default.gray(" \u2022 Work item ID is incorrect")),console.log(E.default.gray(" \u2022 Error tracking wasn't enabled when processed"));return}if(s.length>0){let n=s[0];console.log(E.default.green("\u{1F4CB} Work Item Information:")),console.log(` Work Type: ${n.workType}`),console.log(` Status: ${Ot(n.status)} ${n.status}`),console.log(` Worker ID: ${n.metadata.workerId}`),n.metadata.projectId&&console.log(` Project ID: ${n.metadata.projectId}`),console.log()}t.timeline&&s.length>0&&Sr(s),r.length>0?wr(r,t.verbose||!1):console.log(E.default.green("\u2705 No errors found for this work item")),t.suggestions&&r.length>0&&Ir(r),t.export&&await Er(a,{errors:r,logs:s},t.export)}catch(e){console.error(E.default.red("\u274C Failed to debug work item:"),e instanceof Error?e.message:e)}}async function kr(a,t){console.log(E.default.blue(`\u{1F4CA} Analyzing error patterns for work type: ${a}
|
|
83
|
+
`));try{let r=De().getFailurePattern(a);if(!r||r.frequency===0){console.log(E.default.yellow("\u26A0\uFE0F No error data found for this work type"));return}console.log(E.default.green("\u{1F4C8} Error Pattern Analysis:")),console.log(` Most Common Error: ${r.errorType}`),console.log(` Frequency: ${r.frequency} occurrences`),console.log(` Average Retry Count: ${r.averageRetryCount.toFixed(1)}`),console.log(` Success Rate After Retry: ${r.successRateAfterRetry.toFixed(1)}%`),console.log(),Object.keys(r.commonContext).length>0&&(console.log(E.default.cyan("\u{1F50D} Common Context Patterns:")),Object.entries(r.commonContext).forEach(([s,n])=>{console.log(` ${s}: ${n}`)}),console.log()),r.suggestedFixes.length>0&&(console.log(E.default.yellow("\u{1F4A1} Suggested Fixes:")),r.suggestedFixes.forEach((s,n)=>{console.log(` ${n+1}. ${s}`)}),console.log()),t.export&&await Cr(a,r,t.export)}catch(e){console.error(E.default.red("\u274C Failed to analyze work type:"),e instanceof Error?e.message:e)}}async function br(a){console.log(E.default.blue(`\u{1F3E5} Work Item Health Overview
|
|
84
|
+
`));try{let e=await De().getHealthStatus();console.log(E.default.green("\u{1F4CA} Current Status:")),console.log(` Active Work Items: ${e.activeWorkItems}`),console.log(` Failed (24h): ${e.failedInLast24Hours}`),console.log(` Success Rate: ${e.successRate.toFixed(1)}%`),console.log(` Avg Processing Time: ${e.averageProcessingTime}ms`),console.log(),e.topErrors.length>0&&(console.log(E.default.red("\u{1F6A8} Top Errors (24h):")),e.topErrors.slice(0,5).forEach((r,s)=>{let n=Lt(r.lastOccurrence);console.log(` ${s+1}. ${r.type} (${r.count}x) - ${n}`)}),console.log()),console.log(E.default.cyan("\u{1F4BB} System Resources:")),console.log(` Memory Usage: ${e.systemResources.memoryUsage}MB`),console.log(` CPU Usage: ${e.systemResources.cpuUsage}%`),console.log(` Disk Space: ${e.systemResources.diskSpace}MB`),console.log(),console.log(E.default.magenta("\u{1F310} External Services:")),Object.entries(e.externalServices).forEach(([r,s])=>{console.log(` ${r}: ${s==="healthy"?"\u2705":s==="degraded"?"\u26A0\uFE0F":"\u274C"} ${s}`)}),console.log(),a.export&&await Ar(e,a.export)}catch(t){console.error(E.default.red("\u274C Failed to get health overview:"),t instanceof Error?t.message:t)}}function Sr(a){console.log(E.default.cyan("\u23F1\uFE0F Execution Timeline:"));let t=a.sort((e,r)=>e.timestamp.getTime()-r.timestamp.getTime());t.forEach((e,r)=>{let s=e.timestamp.toLocaleTimeString(),n=e.duration?` (${Math.round(e.duration/1e3)}s)`:"",i=e.progress?.percentage?` - ${e.progress.percentage}%`:"";console.log(` ${s} ${Ot(e.status)} ${e.stage}${i}${n}`),e.errorData&&r<t.length-1&&console.log(E.default.red(` \u274C ${e.errorData.message}`))}),console.log()}function wr(a,t){console.log(E.default.red(`\u{1F6A8} Errors Found (${a.length}):`)),a.slice(0,t?a.length:5).forEach((e,r)=>{let s=Lt(e.context.timestamp);console.log(`
|
|
85
|
+
${r+1}. ${e.errorType} (${e.metadata.severity})`),console.log(` Message: ${e.message}`),console.log(` Stage: ${e.stage}`),console.log(` Occurred: ${s}`),console.log(` Retryable: ${e.metadata.retryable?"\u2705":"\u274C"}`),t&&e.stack&&console.log(E.default.gray(` Stack: ${e.stack.split(`
|
|
86
|
+
`)[0]}`)),e.metadata.tags.length>0&&console.log(` Tags: ${e.metadata.tags.join(", ")}`)}),!t&&a.length>5&&console.log(E.default.gray(`
|
|
87
|
+
... and ${a.length-5} more errors (use --verbose to see all)`)),console.log()}function Ir(a){let t=a[0];if(!t)return;console.log(E.default.yellow("\u{1F4A1} Suggested Fixes:")),Tr(t.errorType,t.metadata.category).forEach((r,s)=>{console.log(` ${s+1}. ${r}`)}),console.log()}async function Er(a,t,e){let r=new Date().toISOString().replace(/[:.]/g,"-"),s=`work-item-debug-${a}-${r}.${e}`;try{let n=await import("fs/promises");if(e==="json")await n.writeFile(s,JSON.stringify(t,null,2));else if(e==="csv"){let i=t.errors.map(l=>`"${l.id}","${l.errorType}","${l.stage}","${l.message}","${l.context.timestamp}"`).join(`
|
|
88
|
+
`);await n.writeFile(s,`ID,Error Type,Stage,Message,Timestamp
|
|
89
|
+
`+i)}console.log(E.default.green(`\u2705 Debug data exported to: ${s}`))}catch(n){console.error(E.default.red("\u274C Failed to export debug data:"),n instanceof Error?n.message:n)}}async function Cr(a,t,e){let r=new Date().toISOString().replace(/[:.]/g,"-"),s=`work-type-analysis-${a}-${r}.${e}`;try{let n=await import("fs/promises");e==="json"&&await n.writeFile(s,JSON.stringify(t,null,2)),console.log(E.default.green(`\u2705 Pattern data exported to: ${s}`))}catch(n){console.error(E.default.red("\u274C Failed to export pattern data:"),n instanceof Error?n.message:n)}}async function Ar(a,t){let r=`health-overview-${new Date().toISOString().replace(/[:.]/g,"-")}.${t}`;try{let s=await import("fs/promises");t==="json"&&await s.writeFile(r,JSON.stringify(a,null,2)),console.log(E.default.green(`\u2705 Health data exported to: ${r}`))}catch(s){console.error(E.default.red("\u274C Failed to export health data:"),s instanceof Error?s.message:s)}}function Ot(a){switch(a){case"ASSIGNED":return"\u{1F4CB}";case"PROCESSING":return"\u2699\uFE0F";case"COMPLETED":return"\u2705";case"FAILED":return"\u274C";case"RETRYING":return"\u{1F504}";default:return"\u2753"}}function Lt(a){let e=new Date().getTime()-a.getTime(),r=Math.floor(e/(1e3*60)),s=Math.floor(r/60),n=Math.floor(s/24);return r<1?"just now":r<60?`${r}m ago`:s<24?`${s}h ago`:`${n}d ago`}function Tr(a,t){let e=[];switch(a){case"network_error":e.push("Check network connectivity"),e.push("Verify API endpoint URLs"),e.push("Increase request timeout");break;case"authentication_error":e.push("Refresh authentication token"),e.push("Verify API key is valid"),e.push("Check user permissions");break;case"claude_api_error":e.push("Check Claude API key"),e.push("Verify Claude CLI installation"),e.push("Check token usage limits");break;case"missing_project":e.push("Verify project ID exists in database"),e.push("Check project access permissions"),e.push("Refresh project data cache");break;case"timeout_error":e.push("Increase operation timeout"),e.push("Break down large operations"),e.push("Check system resource usage");break;default:e.push("Check logs for detailed error information"),e.push("Verify system configuration"),e.push("Contact system administrator")}return e}var Wt,E,Ne=A(()=>{"use strict";Wt=require("commander"),E=h(require("chalk"));jt();tt()});var xr={};Q(xr,{program:()=>F});module.exports=ot(xr);var Ft=require("commander"),d=h(require("chalk"));var ht=h(require("readline")),y=h(require("chalk"));var Z=require("fs"),ze=h(require("path")),T=h(require("os")),fe=h(require("crypto"));R();var N=class{constructor(t){this.configDir=t||ze.default.join(T.default.homedir(),".task-shepherd-agent"),this.identityFile=ze.default.join(this.configDir,"agent-identity.json")}async initializeIdentity(t){let e=await this.loadExistingIdentity();if(e&&t.persistent!==!1)return e.lastUsed=new Date().toISOString(),await this.saveIdentity(e),c.info("Using existing agent identity",{agentId:e.agentId,agentName:e.agentName,service:"identity"}),this.currentIdentity=e,e;let r=await this.generateNewIdentity(t);return t.persistent!==!1&&await this.saveIdentity(r),this.currentIdentity=r,c.info("Generated new agent identity",{agentId:r.agentId,agentName:r.agentName,strategy:t.strategy,service:"identity"}),r}async generateNewIdentity(t){let e=T.default.hostname(),r=T.default.platform(),s=T.default.userInfo().username,n="production",i,o;switch(t.strategy){case"hostname":i=await this.generateHostnameBasedId(t),o=t.customName||`AI Agent (${e})`;break;case"user-configured":i=await this.generateUserConfiguredId(t),o=t.customName||`AI Agent (${i})`;break;case"machine-fingerprint":i=await this.generateMachineFingerprintId(t),o=t.customName||`AI Agent (${e})`;break;case"hybrid":i=await this.generateHybridId(t),o=t.customName||`AI Agent (${this.extractReadablePart(i)})`;break;default:throw new Error(`Unknown identity strategy: ${t.strategy}`)}return{agentId:i,agentName:o,hostname:e,platform:r,userId:s,environment:n,createdAt:new Date().toISOString(),lastUsed:new Date().toISOString(),version:process.env.npm_package_version||"1.0.0"}}async generateHostnameBasedId(t){let e=T.default.hostname(),r=[];t.prefix&&r.push(t.prefix);let s=e.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").substring(0,20);if(r.push(s),t.includeUser){let n=T.default.userInfo().username.toLowerCase().replace(/[^a-z0-9]/g,"").substring(0,10);r.push(n)}if(t.includeEnvironment){let n="production".substring(0,4);r.push(n)}return t.suffix&&r.push(t.suffix),r.join("-")}async generateUserConfiguredId(t){if(t.customName){let r=[t.customName.toLowerCase().replace(/[^a-z0-9-\s]/g,"").replace(/\s+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").substring(0,30)];if(t.includeEnvironment){let n="production".substring(0,4);r.push(n)}let s=fe.default.createHash("md5").update(T.default.hostname()+T.default.userInfo().username).digest("hex").substring(0,4);return r.push(s),r.join("-")}return this.generateInteractiveId(t)}async generateMachineFingerprintId(t){let e=this.getMachineFingerprint(),r=fe.default.createHash("sha256").update(e).digest("hex").substring(0,12),s=[];return t.prefix&&s.push(t.prefix),s.push("agent"),s.push(r),t.suffix&&s.push(t.suffix),s.join("-")}async generateHybridId(t){let e=T.default.hostname(),r=T.default.userInfo().username,s=e.toLowerCase().replace(/[^a-z0-9]/g,"").substring(0,8),n=fe.default.createHash("md5").update(`${e}-${r}-${T.default.platform()}`).digest("hex").substring(0,6),i=[];if(t.prefix&&i.push(t.prefix),i.push(s),i.push(n),t.includeEnvironment){let o="production".substring(0,3);i.push(o)}return t.suffix&&i.push(t.suffix),i.join("-")}async generateInteractiveId(t){let r=`ai-agent-${T.default.hostname().toLowerCase().substring(0,8)}`;return c.info("Using default agent ID (interactive mode not available)",{defaultId:r,service:"identity"}),r}getMachineFingerprint(){return[T.default.hostname(),T.default.platform(),T.default.arch(),T.default.userInfo().username,JSON.stringify(Object.keys(T.default.networkInterfaces()).sort())].join("|")}extractReadablePart(t){let e=t.split("-");return e.length>1?e[1]:t}async loadExistingIdentity(){try{let t=await Z.promises.readFile(this.identityFile,"utf8"),e=JSON.parse(t);return e.agentId&&e.agentName&&e.createdAt?e:(c.warn("Invalid identity file format, will regenerate",{service:"identity"}),null)}catch(t){return t.code!=="ENOENT"&&c.warn("Failed to load existing identity",{error:t instanceof Error?t.message:String(t),service:"identity"}),null}}async saveIdentity(t){try{await Z.promises.mkdir(this.configDir,{recursive:!0}),await Z.promises.writeFile(this.identityFile,JSON.stringify(t,null,2),"utf8"),c.info("Agent identity saved",{agentId:t.agentId,configDir:this.configDir,service:"identity"})}catch(e){throw c.error("Failed to save agent identity",{error:e instanceof Error?e.message:String(e),configDir:this.configDir,service:"identity"}),e}}getCurrentIdentity(){return this.currentIdentity||null}async updateIdentity(t){if(!this.currentIdentity)throw new Error("No current identity to update");let e={...this.currentIdentity,...t,lastUsed:new Date().toISOString()};return await this.saveIdentity(e),this.currentIdentity=e,c.info("Agent identity updated",{agentId:e.agentId,updates:Object.keys(t),service:"identity"}),e}async resetIdentity(){try{await Z.promises.unlink(this.identityFile),this.currentIdentity=void 0,c.info("Agent identity reset",{service:"identity"})}catch(t){if(t.code!=="ENOENT")throw c.error("Failed to reset agent identity",{error:t instanceof Error?t.message:String(t),service:"identity"}),t}}getAvailableStrategies(){return[{strategy:"hostname",description:"Use machine hostname as base (most readable)",example:"macbook-pro-dev"},{strategy:"user-configured",description:"User provides custom name with uniqueness suffix",example:"my-ai-assistant-a4f2"},{strategy:"machine-fingerprint",description:"Generate from machine characteristics (most stable)",example:"agent-7f4e2a8b9c1d"},{strategy:"hybrid",description:"Combine readable hostname with unique suffix (balanced)",example:"macbook-7f4e2a-dev"}]}validateAgentId(t){let e=[];return t.length<3&&e.push("Agent ID must be at least 3 characters long"),t.length>50&&e.push("Agent ID must be no more than 50 characters long"),/^[a-z0-9-]+$/i.test(t)||e.push("Agent ID can only contain letters, numbers, and hyphens"),(t.startsWith("-")||t.endsWith("-"))&&e.push("Agent ID cannot start or end with a hyphen"),t.includes("--")&&e.push("Agent ID cannot contain consecutive hyphens"),{valid:e.length===0,errors:e}}getIdentityFilePath(){return this.identityFile}async identityExists(){try{return await Z.promises.access(this.identityFile),!0}catch{return!1}}};var oe=class{constructor(){this.rl=ht.default.createInterface({input:process.stdin,output:process.stdout}),this.identityService=new N}async run(){try{if(console.log(y.default.blue.bold(`
|
|
90
|
+
\u{1F916} Task Shepherd AI Agent Setup Wizard`)),console.log(y.default.gray(`Let's configure your AI agent for optimal performance
|
|
91
|
+
`)),!await this.checkExistingConfiguration())return;let e=await this.gatherConfiguration(),r=await this.identityService.initializeIdentity(e.identity);await this.saveConfiguration(e,r.agentId),this.showSummary(r,e),console.log(y.default.green.bold(`
|
|
92
|
+
\u2705 Agent setup complete!`)),console.log(y.default.gray(`You can now start your agent with: npm run dev
|
|
93
|
+
`))}catch(t){console.error(y.default.red(`
|
|
94
|
+
\u274C Setup failed:`),t instanceof Error?t.message:t),process.exit(1)}finally{this.rl.close()}}async checkExistingConfiguration(){if(await this.identityService.identityExists()){let e=await this.ask(y.default.yellow("\u26A0\uFE0F An agent identity already exists. Do you want to reconfigure? (y/N): "));if(e.toLowerCase()!=="y"&&e.toLowerCase()!=="yes")return console.log(y.default.gray("Setup cancelled. Existing configuration preserved.")),!1;await this.identityService.resetIdentity()}return!0}async gatherConfiguration(){let t={identity:{strategy:"hostname",persistent:!0},backend:{apiUrl:"http://localhost:4002/graphql"},capabilities:[],features:{enableHeartbeat:!0,enableMetrics:!0,enableWebUI:!0},advanced:{heartbeatInterval:3e4,logLevel:"info",webPort:8548}};return await this.configureIdentity(t),await this.configureBackend(t),await this.configureCapabilities(t),await this.configureFeatures(t),await this.askBoolean("Configure advanced settings? (heartbeat interval, logging, etc.)",!1)&&await this.configureAdvanced(t),t}async configureIdentity(t){console.log(y.default.blue.bold(`
|
|
95
|
+
\u{1F4DD} Step 1: Agent Identity`)),console.log(y.default.gray(`Choose how your agent will be identified in the system
|
|
96
|
+
`));let e=this.identityService.getAvailableStrategies();console.log("Available identity strategies:"),e.forEach((i,o)=>{console.log(y.default.cyan(`${o+1}. ${i.strategy}`)+y.default.gray(` - ${i.description}`)),console.log(y.default.gray(` Example: ${i.example}
|
|
97
|
+
`))});let r=await this.askChoice("Select identity strategy",e.map(i=>i.strategy),"hostname");if(t.identity.strategy=r,r==="user-configured"){let i=await this.ask("Enter a custom name for your agent: ");i.trim()&&(t.identity.customName=i.trim())}let s=await this.askBoolean("Include environment in agent ID? (dev, prod, etc.)",!0);if(t.identity.includeEnvironment=s,r==="hostname"||r==="hybrid"){let i=await this.askBoolean("Include username in agent ID?",!1);t.identity.includeUser=i}if(await this.askBoolean("Add prefix to agent ID?",!1)){let i=await this.ask("Enter prefix: ");i.trim()&&(t.identity.prefix=i.trim().toLowerCase().replace(/[^a-z0-9]/g,""))}console.log(y.default.green("\u2713 Identity configuration complete"))}async configureBackend(t){console.log(y.default.blue.bold(`
|
|
98
|
+
\u{1F517} Step 2: Backend Connection`)),console.log(y.default.gray(`Configure connection to Task Shepherd backend
|
|
99
|
+
`));let e="http://localhost:4002/graphql",r=await this.ask(`Backend GraphQL URL (${e}): `);if(t.backend.apiUrl=r.trim()||e,console.log(y.default.yellow(`
|
|
100
|
+
\u{1F511} API Key Setup`)),console.log(y.default.gray("You need an API key to authenticate with the backend.")),console.log(y.default.gray("You can generate one in the Task Shepherd admin panel.")),await this.askBoolean("Do you have an API key?",!1)){let n=await this.askPassword("Enter API key: ");n.trim()&&(t.backend.apiKey=n.trim())}else console.log(y.default.yellow("\u26A0\uFE0F You can add an API key later in the configuration file."));console.log(y.default.green("\u2713 Backend configuration complete"))}async configureCapabilities(t){console.log(y.default.blue.bold(`
|
|
101
|
+
\u26A1 Step 3: Agent Capabilities`)),console.log(y.default.gray(`Select what your agent can do
|
|
102
|
+
`));let e=[{key:"project_review",name:"Project Review",description:"Analyze and review project requirements"},{key:"code_review",name:"Code Review",description:"Review code for quality and best practices"},{key:"development_planning",name:"Development Planning",description:"Create development plans and estimates"},{key:"story_implementation",name:"Story Implementation",description:"Implement user stories and features"},{key:"documentation",name:"Documentation",description:"Generate and maintain documentation"},{key:"testing",name:"Testing",description:"Create and execute tests"}];console.log("Available capabilities:"),e.forEach((s,n)=>{console.log(y.default.cyan(`${n+1}. ${s.name}`)+y.default.gray(` - ${s.description}`))}),console.log(y.default.gray(`
|
|
103
|
+
Enter capability numbers separated by commas (e.g., 1,2,3):`));let r=await this.ask("Select capabilities: ");if(r.trim()){let s=r.split(",").map(n=>parseInt(n.trim())-1).filter(n=>n>=0&&n<e.length);t.capabilities=s.map(n=>e[n].key)}t.capabilities.length===0&&(console.log(y.default.yellow("\u26A0\uFE0F No capabilities selected. Adding default project_review capability.")),t.capabilities=["project_review"]),console.log(y.default.green(`\u2713 Selected capabilities: ${t.capabilities.join(", ")}`))}async configureFeatures(t){console.log(y.default.blue.bold(`
|
|
104
|
+
\u{1F6E0}\uFE0F Step 4: Features`)),console.log(y.default.gray(`Enable/disable agent features
|
|
105
|
+
`)),t.features.enableHeartbeat=await this.askBoolean("Enable heartbeat monitoring?",!0),t.features.enableMetrics=await this.askBoolean("Enable performance metrics collection?",!0),t.features.enableWebUI=await this.askBoolean("Enable web dashboard?",!0),console.log(y.default.green("\u2713 Features configured"))}async configureAdvanced(t){if(console.log(y.default.blue.bold(`
|
|
106
|
+
\u{1F527} Step 5: Advanced Settings`)),console.log(y.default.gray(`Fine-tune agent behavior
|
|
107
|
+
`)),t.features.enableHeartbeat){let r=await this.askNumber("Heartbeat interval (seconds)",30);t.advanced.heartbeatInterval=r*1e3}let e=await this.askChoice("Log level",["error","warn","info","debug"],"info");if(t.advanced.logLevel=e,t.features.enableWebUI){let r=await this.askNumber("Web dashboard port",8548);t.advanced.webPort=r}console.log(y.default.green("\u2713 Advanced settings configured"))}async saveConfiguration(t,e){console.log(y.default.blue.bold(`
|
|
108
|
+
\u{1F4BE} Saving Configuration...`));let r=this.generateEnvContent(t,e),s=".env";require("fs").writeFileSync(s,r),console.log(y.default.green(`\u2713 Configuration saved to ${s}`))}generateEnvContent(t,e){let r=["# AI Worker Service Configuration",`AGENT_ID=${e}`,`AGENT_NAME=${t.identity.customName||"AI Agent"}`,"PORT=8547","NODE_ENV=production","","# Task Shepherd API Configuration",`TASK_SHEPHERD_API_URL=${t.backend.apiUrl}`];return t.backend.apiKey?r.push(`TASK_SHEPHERD_API_KEY=${t.backend.apiKey}`):r.push("# TASK_SHEPHERD_API_KEY=your-api-key-here"),r.push("","# Agent Features",`ENABLE_HEARTBEAT=${t.features.enableHeartbeat}`,`ENABLE_METRICS=${t.features.enableMetrics}`,`ENABLE_WEB_UI=${t.features.enableWebUI}`,"","# Agent Capabilities",`AGENT_CAPABILITIES=${t.capabilities.join(",")}`,"","# Advanced Settings",`HEARTBEAT_INTERVAL=${t.advanced.heartbeatInterval}`,`LOG_LEVEL=${t.advanced.logLevel}`,`WEB_PORT=${t.advanced.webPort}`,"","# Redis Configuration","REDIS_URL=redis://localhost:6379","","# Claude CLI Configuration (Primary Method)","CLAUDE_COMMAND_PATH=/Users/$USER/.claude/local/claude","","# Claude API Configuration (Optional - Enables Enhanced Features)","# ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}","# ANTHROPIC_BASE_URL=https://api.anthropic.com","# CLAUDE_MODEL=claude-3-5-sonnet-20241022","# CLAUDE_MAX_RETRIES=3","# CLAUDE_TIMEOUT_MS=60000","","# Service Configuration","MAX_CONCURRENT_JOBS=3","TOKEN_RATE_LIMIT=10000",""),r.join(`
|
|
109
|
+
`)}showSummary(t,e){console.log(y.default.blue.bold(`
|
|
110
|
+
\u{1F4CB} Configuration Summary`)),console.log(y.default.gray("\u2550".repeat(50))),console.log(y.default.cyan("Agent Identity:")),console.log(` ID: ${y.default.white(t.agentId)}`),console.log(` Name: ${y.default.white(t.agentName)}`),console.log(` Strategy: ${y.default.white(e.identity.strategy)}`),console.log(y.default.cyan(`
|
|
111
|
+
Backend Connection:`)),console.log(` URL: ${y.default.white(e.backend.apiUrl)}`),console.log(` API Key: ${e.backend.apiKey?y.default.green("\u2713 Configured"):y.default.yellow("\u26A0\uFE0F Not set")}`),console.log(y.default.cyan(`
|
|
112
|
+
Capabilities:`)),e.capabilities.forEach(r=>{console.log(` \u2022 ${y.default.white(r)}`)}),console.log(y.default.cyan(`
|
|
113
|
+
Features:`)),console.log(` Heartbeat: ${e.features.enableHeartbeat?y.default.green("\u2713"):y.default.red("\u2717")}`),console.log(` Metrics: ${e.features.enableMetrics?y.default.green("\u2713"):y.default.red("\u2717")}`),console.log(` Web UI: ${e.features.enableWebUI?y.default.green("\u2713"):y.default.red("\u2717")}`),e.features.enableWebUI&&(console.log(y.default.cyan(`
|
|
114
|
+
Web Dashboard:`)),console.log(` URL: ${y.default.white(`http://localhost:${e.advanced.webPort}`)}`))}ask(t){return new Promise(e=>{this.rl.question(t,e)})}async askPassword(t){return this.ask(t)}async askBoolean(t,e=!1){let r=e?"Y/n":"y/N",s=await this.ask(`${t} (${r}): `);return s.trim()?s.toLowerCase().startsWith("y"):e}async askNumber(t,e){let r=await this.ask(`${t} (${e}): `);if(!r.trim())return e;let s=parseInt(r);return isNaN(s)?e:s}async askChoice(t,e,r){let s=e.map((u,m)=>`${m+1}. ${u}`).join(", "),n=r?` (default: ${r})`:"",i=await this.ask(`${t} [${s}]${n}: `);if(!i.trim()&&r)return r;let o=parseInt(i)-1;if(o>=0&&o<e.length)return e[o];let l=e.find(u=>u.toLowerCase()===i.toLowerCase());return l||r||e[0]}};require.main===module&&new oe().run().catch(t=>{console.error(y.default.red("Wizard failed:"),t),process.exit(1)});var yt=require("events");var ft=require("events");R();var ee=h(require("os")),K=h(require("process")),ye=class extends ft.EventEmitter{constructor(e,r,s,n={}){super();this.responseTimes=[];this.maxResponseTimeHistory=50;this.metricsProviders=new Map;this.workerId=e,this.tokenTracker=r,this.httpClient=s,this.options={interval:3e4,timeout:1e4,retryAttempts:3,retryDelay:5e3,enableMetrics:!0,preferWebSocket:!0,fallbackToHttp:!0,...n},this.metrics=this.getInitialMetrics(),this.status={isRunning:!1,consecutiveFailures:0,totalSent:0,totalSuccessful:0,totalFailed:0,averageResponseTime:0,currentStatus:"offline"},this.setupDefaultMetricsProviders()}start(){if(this.intervalId){c.warn("Heartbeat service is already running",{workerId:this.workerId,service:"heartbeat"});return}c.info("Starting heartbeat service",{workerId:this.workerId,interval:this.options.interval,service:"heartbeat"}),this.status.isRunning=!0,this.status.currentStatus="healthy",this.sendHeartbeat(),this.intervalId=setInterval(()=>{this.sendHeartbeat()},this.options.interval),this.emit("started",{workerId:this.workerId})}stop(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=void 0),this.status.isRunning=!1,this.status.currentStatus="offline",c.info("Heartbeat service stopped",{workerId:this.workerId,service:"heartbeat"}),this.emit("stopped",{workerId:this.workerId})}async sendHeartbeat(){let e=Date.now();try{await this.collectMetrics();let r={workerId:this.workerId,timestamp:new Date().toISOString(),isHealthy:this.isAgentHealthy(),metrics:this.options.enableMetrics?this.metrics:void 0,status:this.determineAgentStatus(),version:K.default.env.npm_package_version||"1.0.0",localWorkState:await this.collectLocalWorkState()},s=await this.sendHeartbeatMessage(r),n=Date.now()-e;return this.updateResponseTimeHistory(n),s?(this.handleHeartbeatSuccess(),this.emit("heartbeat_sent",{workerId:this.workerId,responseTime:n,metrics:this.metrics})):(this.handleHeartbeatFailure(),this.emit("heartbeat_failed",{workerId:this.workerId,consecutiveFailures:this.status.consecutiveFailures})),s}catch(r){let s=Date.now()-e;return this.updateResponseTimeHistory(s),this.handleHeartbeatFailure(),c.error("Heartbeat error",{workerId:this.workerId,error:r instanceof Error?r.message:String(r),responseTime:s,service:"heartbeat"}),this.emit("heartbeat_error",{workerId:this.workerId,error:r,consecutiveFailures:this.status.consecutiveFailures}),!1}}async sendHeartbeatMessage(e){if(this.httpClient)return this.sendHttpHeartbeat(e);throw new Error("No available heartbeat transport (WebSocket failed and HTTP not configured)")}async sendHttpHeartbeat(e){c.debug("Sending heartbeat via HTTP GraphQL",{workerId:this.workerId,service:"heartbeat"});let r=0;for(;r<this.options.retryAttempts;)try{let s=`
|
|
115
|
+
mutation UpdateWorkerHeartbeat($input: WorkerHeartbeatInput!) {
|
|
116
|
+
updateWorkerHeartbeat(input: $input)
|
|
117
|
+
}
|
|
118
|
+
`,n={input:{workerId:e.workerId,isHealthy:e.isHealthy,cpuUsage:e.metrics?.cpuUsage,memoryUsage:e.metrics?.memoryUsage,responseTime:this.status.averageResponseTime||void 0,errorRate:this.getErrorRate(),localWorkState:e.localWorkState||void 0}};if((await this.httpClient?.mutate({query:s,variables:n}))?.data?.updateAIWorkerHeartbeat?.success)return c.debug("AI Worker heartbeat sent successfully",{workerId:this.workerId,service:"heartbeat"}),!0;throw new Error("AI Worker heartbeat failed")}catch(s){if(r++,r<this.options.retryAttempts)c.warn(`HTTP heartbeat attempt ${r} failed, retrying in ${this.options.retryDelay}ms`,{workerId:this.workerId,error:s instanceof Error?s.message:String(s),service:"heartbeat"}),await this.sleep(this.options.retryDelay);else throw s}return!1}async collectMetrics(){try{let e=K.default.memoryUsage(),r=ee.default.freemem(),s=await this.getCPUUsage();this.metrics={cpuUsage:s,memoryUsage:Math.round(e.heapUsed/1024/1024),freeMemory:Math.round(r/1024/1024),uptime:Math.round(K.default.uptime()),activeConnections:this.getActiveConnectionsCount(),queueSize:this.getQueueSize(),completedTasks:this.getCompletedTasksCount(),failedTasks:this.getFailedTasksCount(),lastActivity:this.getLastActivityTimestamp(),customMetrics:await this.collectCustomMetrics()}}catch(e){c.warn("Failed to collect metrics",{workerId:this.workerId,error:e instanceof Error?e.message:String(e),service:"heartbeat"}),this.metrics=this.getInitialMetrics()}}async getCPUUsage(){return new Promise(e=>{let r=K.default.cpuUsage();setTimeout(()=>{let s=K.default.cpuUsage(r),i=(s.user+s.system)/1e6/.1*100;e(Math.min(100,Math.max(0,i)))},100)})}setupDefaultMetricsProviders(){this.metricsProviders.set("tokenUsage",async()=>{let e=this.tokenTracker.getDailyUsage();return{totalTokens:e.totalTokens,totalCost:e.totalCost,requestsToday:e.operationCount}}),this.metricsProviders.set("systemLoad",async()=>{let e=ee.default.loadavg();return{load1m:e[0],load5m:e[1],load15m:e[2],platform:ee.default.platform(),arch:ee.default.arch()}})}async collectCustomMetrics(){let e={};for(let[r,s]of this.metricsProviders.entries())try{e[r]=await s()}catch(n){c.warn(`Failed to collect custom metric: ${r}`,{workerId:this.workerId,error:n instanceof Error?n.message:String(n),service:"heartbeat"})}return e}addMetricsProvider(e,r){this.metricsProviders.set(e,r),c.info(`Added custom metrics provider: ${e}`,{workerId:this.workerId,service:"heartbeat"})}removeMetricsProvider(e){this.metricsProviders.delete(e),c.info(`Removed custom metrics provider: ${e}`,{workerId:this.workerId,service:"heartbeat"})}isAgentHealthy(){let e=K.default.memoryUsage(),r=e.heapUsed/1024/1024,s=e.heapTotal*1.5/1024/1024;return!(r>s||this.getQueueSize()>100||this.status.consecutiveFailures>=5)}determineAgentStatus(){return this.isAgentHealthy()?this.getQueueSize()>0?"WORKING":Date.now()-(this.getLastActivityTime()||0)<3e5?"ACTIVE":"IDLE":"UNHEALTHY"}handleHeartbeatSuccess(){this.status.lastHeartbeat=new Date,this.status.lastSuccessfulHeartbeat=new Date,this.status.consecutiveFailures=0,this.status.totalSent++,this.status.totalSuccessful++,this.status.currentStatus="healthy"}handleHeartbeatFailure(){this.status.lastHeartbeat=new Date,this.status.consecutiveFailures++,this.status.totalSent++,this.status.totalFailed++,this.status.consecutiveFailures>=5?this.status.currentStatus="critical":this.status.consecutiveFailures>=3&&(this.status.currentStatus="warning")}updateResponseTimeHistory(e){this.responseTimes.push(e),this.responseTimes.length>this.maxResponseTimeHistory&&this.responseTimes.shift(),this.status.averageResponseTime=this.responseTimes.reduce((r,s)=>r+s,0)/this.responseTimes.length}getStatus(){return{...this.status}}getMetrics(){return{...this.metrics}}updateOptions(e){let r=this.status.isRunning;r&&this.stop(),this.options={...this.options,...e},r&&this.start(),c.info("Heartbeat options updated",{workerId:this.workerId,options:this.options,service:"heartbeat"})}async forceHealthCheck(){return await this.collectMetrics(),this.getMetrics()}getInitialMetrics(){return{cpuUsage:0,memoryUsage:0,freeMemory:Math.round(ee.default.freemem()/1024/1024),uptime:Math.round(K.default.uptime()),activeConnections:0,queueSize:0,completedTasks:0,failedTasks:0}}getActiveConnectionsCount(){return 1}getQueueSize(){return 0}getCompletedTasksCount(){return 0}getFailedTasksCount(){return 0}getLastActivityTimestamp(){return new Date().toISOString()}getLastActivityTime(){return Date.now()}sleep(e){return new Promise(r=>setTimeout(r,e))}getErrorRate(){return this.status.totalSent===0?0:this.status.totalFailed/this.status.totalSent}setSubscriptionHandler(e){this.subscriptionHandler=e}setCompletedWorkService(e){this.completedWorkService=e}async collectLocalWorkState(){let e=[];try{if(this.subscriptionHandler&&typeof this.subscriptionHandler.getActiveAssignments=="function"){let r=this.subscriptionHandler.getActiveAssignments();for(let s of r)e.push({workItemId:s.workItemId,status:s.status==="in_progress"?"in_progress":s.status,startedAt:s.startedAt?.toISOString(),completedAt:s.completedAt?.toISOString(),lastUpdate:new Date().toISOString()})}if(this.completedWorkService&&typeof this.completedWorkService.getCompletedItems=="function"){let r=this.completedWorkService.getCompletedItems(5,0);if(r&&r.items)for(let s of r.items){let n=new Date(s.completedAt).getTime(),i=Date.now()-30*60*1e3;n>i&&e.push({workItemId:s.id,status:s.status==="completed"?"completed":"failed",startedAt:s.startedAt,completedAt:s.completedAt,lastUpdate:new Date().toISOString()})}}return e}catch(r){return c.warn("Failed to collect local work state for heartbeat",{workerId:this.workerId,error:r instanceof Error?r.message:String(r),service:"heartbeat"}),[]}}};R();var qe=h(require("os")),ve=class extends yt.EventEmitter{constructor(e,r,s){super();this.registered=!1;this.httpClient=e,this.tokenTracker=r,this.identityService=s||new N}async initializeAndRegister(e){let r=await this.ensureAgentIdentity();return this.registerWorker(r,e)}async registerWorker(e,r){this.currentIdentity=e,c.info("Registering AI Agent with Task Shepherd backend",{workerId:e.agentId,workerName:e.agentName,capabilities:r.capabilities,scope:r.scope||"USER",service:"worker-registration"});let s=r.scopeId,n=r.scope||"USER";if(n==="USER"&&!s){let l=0,u=3;for(;l<u;){try{c.debug("Attempting to retrieve authenticated user ID",{attempt:l+1,maxRetries:u});let p=await this.httpClient.query({query:"query { me { id email } }",variables:{}});if(p.data?.me?.id){s=p.data.me.id,c.debug("Retrieved authenticated user ID for worker registration",{userId:s,userEmail:p.data.me.email});break}else if(c.warn("Received empty user response, retrying",{response:p,attempt:l+1}),l===u-1)return c.error("Failed to retrieve authenticated user ID after all retries",{response:p}),{success:!1,message:"Failed to retrieve authenticated user ID for registration - user may not be authenticated"}}catch(m){let p=m instanceof Error?m.message:String(m);if(c.warn("Failed to query authenticated user",{error:p,attempt:l+1,maxRetries:u}),p.toLowerCase().includes("unauthorized")||p.toLowerCase().includes("401")||p.toLowerCase().includes("authentication"))return c.error("Authentication failed - invalid API key or token",{error:p}),{success:!1,message:"Authentication failed - please check API key configuration"};if(l===u-1)return c.error("Failed to authenticate with backend after all retries",{error:p}),{success:!1,message:`Failed to authenticate with backend: ${p}`}}if(l++,l<u){let m=Math.min(1e3*Math.pow(2,l),5e3);c.debug("Waiting before retry",{delay:m,nextAttempt:l+1}),await new Promise(p=>setTimeout(p,m))}}}let i=`
|
|
119
|
+
mutation RegisterWorker($input: WorkerRegistrationInput!) {
|
|
120
|
+
registerWorker(input: $input)
|
|
121
|
+
}
|
|
122
|
+
`,o={input:{workerId:e.agentId,workerName:e.agentName,capabilities:this.mapCapabilities(r.capabilities),scope:n,scopeId:s||"",maxConcurrentTasks:r.maxConcurrentTasks,metadata:{hostname:e.hostname,platform:e.platform,environment:e.environment,version:e.version,userId:e.userId,createdAt:e.createdAt}}};try{if((await this.httpClient.mutate({query:i,variables:o})).data?.registerWorker)return this.registered=!0,c.info("AI Agent registered successfully",{workerId:e.agentId,status:"ACTIVE",service:"worker-registration"}),r.enableHeartbeat!==!1&&await this.initializeHeartbeat(e,r),await this.identityService.updateIdentity({lastUsed:new Date().toISOString()}),this.emit("registered",{workerId:e.agentId,identity:e}),{success:!0,message:"Worker registered successfully",workerId:e.agentId,identity:e};{let u="Registration failed";return c.error("Worker registration failed",{error:u}),{success:!1,message:u}}}catch(l){return c.error("Worker registration error",{error:l instanceof Error?l.message:String(l),workerId:e.agentId,service:"worker-registration"}),{success:!1,message:l instanceof Error?l.message:"Registration request failed"}}}async ensureAgentIdentity(){let e=process.env.AGENT_ID,r=process.env.AGENT_NAME;if(e&&r){let i={agentId:e,agentName:r,hostname:qe.default.hostname(),platform:qe.default.platform(),environment:"production",createdAt:new Date().toISOString(),lastUsed:new Date().toISOString(),version:process.env.npm_package_version||"1.0.0"};return c.info("Using environment-configured agent identity",{agentId:i.agentId,agentName:i.agentName,service:"worker-registration"}),i}let s=this.identityService.getCurrentIdentity();return s?(c.info("Using existing agent identity",{agentId:s.agentId,agentName:s.agentName,service:"worker-registration"}),s):(c.info("Generating new agent identity with default configuration",{service:"worker-registration"}),await this.identityService.initializeIdentity({strategy:"hybrid",includeEnvironment:!0,persistent:!0}))}async initializeHeartbeat(e,r){this.heartbeatService&&this.heartbeatService.stop(),this.heartbeatService=new ye(e.agentId,this.tokenTracker,this.httpClient,{interval:r.heartbeatInterval||3e4,enableMetrics:!0,retryAttempts:3,timeout:1e4,retryDelay:5e3,preferWebSocket:!0,fallbackToHttp:!0}),this.heartbeatService.on("heartbeat_sent",s=>{c.debug("Heartbeat sent successfully",{workerId:s.workerId,responseTime:s.responseTime,service:"worker-registration"})}),this.heartbeatService.on("heartbeat_failed",s=>{c.warn("Heartbeat failed",{workerId:s.workerId,consecutiveFailures:s.consecutiveFailures,service:"worker-registration"}),s.consecutiveFailures>=5&&this.emit("heartbeatCritical",s)}),this.heartbeatService.on("heartbeat_error",s=>{c.error("Heartbeat error",{workerId:s.workerId,error:s.error instanceof Error?s.error.message:String(s.error),service:"worker-registration"})}),this.heartbeatService.start(),c.info("Heartbeat service initialized and started",{workerId:e.agentId,interval:r.heartbeatInterval||3e4,service:"worker-registration"})}async unregisterWorker(){if(!this.registered||!this.currentIdentity)return;let e=this.currentIdentity.agentId;c.info("Unregistering AI Agent",{workerId:e,service:"worker-registration"});let r=`
|
|
123
|
+
mutation UnregisterWorker($workerId: String!) {
|
|
124
|
+
unregisterWorker(workerId: $workerId)
|
|
125
|
+
}
|
|
126
|
+
`;try{await this.httpClient.mutate({query:r,variables:{workerId:e}}),this.registered=!1,this.heartbeatService&&(this.heartbeatService.stop(),this.heartbeatService=void 0),c.info("AI Agent unregistered successfully",{workerId:e,service:"worker-registration"}),this.emit("unregistered",{workerId:e,identity:this.currentIdentity}),this.currentIdentity=void 0}catch(s){c.error("Worker unregistration failed",{error:s instanceof Error?s.message:String(s),workerId:e,service:"worker-registration"})}}getCurrentIdentity(){return this.currentIdentity||null}getRegistrationInfo(){return!this.registered||!this.currentIdentity?null:{workerId:this.currentIdentity.agentId,workerName:this.currentIdentity.agentName,capabilities:["project_review","code_review","development_planning"],registeredAt:new Date,hostname:this.currentIdentity.hostname,platform:this.currentIdentity.platform,environment:this.currentIdentity.environment}}getHeartbeatStatus(){return this.heartbeatService?.getStatus()||null}getHeartbeatMetrics(){return this.heartbeatService?.getMetrics()||null}async forceHeartbeat(){return this.heartbeatService?await this.heartbeatService.sendHeartbeat():!1}addMetricsProvider(e,r){this.heartbeatService&&this.heartbeatService.addMetricsProvider(e,r)}mapCapabilities(e){let r={project_review:"PROJECT_REVIEW",development_planning:"DEVELOPMENT_PLANNING",story_implementation:"STORY_IMPLEMENTATION",code_review:"CODE_REVIEW",testing:"TESTING",documentation:"DOCUMENTATION","project-reviewer":"PROJECT_REVIEW","development-planner":"DEVELOPMENT_PLANNING","code-reviewer":"CODE_REVIEW"};return e.map(s=>r[s]||s.toUpperCase())}isRegistered(){return this.registered}async updateWorkProgress(e,r){if(!this.registered||!this.currentIdentity){c.warn("Cannot update work progress - worker not registered",{workItemId:e});return}let s=`
|
|
127
|
+
mutation UpdateWorkerHeartbeat($input: WorkerHeartbeatInput!) {
|
|
128
|
+
updateWorkerHeartbeat(input: $input)
|
|
129
|
+
}
|
|
130
|
+
`,n={input:{workerId:this.currentIdentity.agentId,isHealthy:!0,workProgress:[{workItemId:e,percentage:r.percentage,currentStep:r.currentStep,completedSteps:r.completedSteps||[],estimatedTimeRemaining:r.estimatedTimeRemaining,lastError:r.lastError}]}};try{(await this.httpClient.mutate({query:s,variables:n})).data?.updateWorkerHeartbeat?c.debug("Work progress updated successfully",{workItemId:e,percentage:r.percentage,currentStep:r.currentStep,workerId:this.currentIdentity.agentId}):c.warn("Work progress update failed",{workItemId:e,message:"Work progress update failed",workerId:this.currentIdentity.agentId})}catch(i){c.error("Error updating work progress",{workItemId:e,error:i instanceof Error?i.message:String(i),workerId:this.currentIdentity.agentId,service:"worker-registration"})}}connectSubscriptionHandler(e){this.heartbeatService?(this.heartbeatService.setSubscriptionHandler(e),c.info("Subscription handler connected to heartbeat service",{workerId:this.currentIdentity?.agentId,service:"worker-registration"})):c.warn("Cannot connect subscription handler - heartbeat service not initialized",{service:"worker-registration"})}connectCompletedWorkService(e){this.heartbeatService?(this.heartbeatService.setCompletedWorkService(e),c.info("Completed work service connected to heartbeat service",{workerId:this.currentIdentity?.agentId,service:"worker-registration"})):c.warn("Cannot connect completed work service - heartbeat service not initialized",{service:"worker-registration"})}getHeartbeatService(){return this.heartbeatService}destroy(){this.heartbeatService&&(this.heartbeatService.stop(),this.heartbeatService=void 0),this.removeAllListeners(),this.registered=!1,this.currentIdentity=void 0}};ke();R();ke();var be=class{constructor(){this.usageHistory=[];this.COST_PER_1K_INPUT_TOKENS=.003;this.COST_PER_1K_OUTPUT_TOKENS=.015;this.MAX_HISTORY_SIZE=1e4}async trackUsage(t){t.cost||(t.cost=this.calculateCost(t.inputTokens,t.outputTokens)),this.usageHistory.push(t),this.usageHistory.length>this.MAX_HISTORY_SIZE&&(this.usageHistory=this.usageHistory.slice(-this.MAX_HISTORY_SIZE)),c.info("Token usage tracked",{sessionId:t.sessionId,inputTokens:t.inputTokens,outputTokens:t.outputTokens,totalTokens:t.totalTokens,cost:t.cost,analysisType:t.analysisType});try{await this.persistUsage(t)}catch(e){c.error("Failed to persist usage to backend",{sessionId:t.sessionId,error:e instanceof Error?e.message:String(e)})}}getUsageStats(t){let e=this.usageHistory;t&&(e=this.usageHistory.filter(f=>f.timestamp>=t.start&&f.timestamp<=t.end));let r=e.length,s=e.reduce((f,S)=>f+S.inputTokens,0),n=e.reduce((f,S)=>f+S.outputTokens,0),i=e.reduce((f,S)=>f+S.totalTokens,0),o=e.reduce((f,S)=>f+S.cost,0),l=r>0?s/r:0,u=r>0?n/r:0,m=r>0?o/r:0,p=e.reduce((f,S)=>(f[S.analysisType]||(f[S.analysisType]={sessions:0,inputTokens:0,outputTokens:0,totalTokens:0,cost:0}),f[S.analysisType].sessions++,f[S.analysisType].inputTokens+=S.inputTokens,f[S.analysisType].outputTokens+=S.outputTokens,f[S.analysisType].totalTokens+=S.totalTokens,f[S.analysisType].cost+=S.cost,f),{});return{summary:{totalSessions:r,totalInputTokens:s,totalOutputTokens:n,totalTokens:i,totalCost:o,avgInputTokens:l,avgOutputTokens:u,avgCost:m},byAnalysisType:p,recentUsage:e.slice(-10)}}getUsageHistory(t=100){return this.usageHistory.slice(-t)}getTotalTokens(){return this.usageHistory.reduce((t,e)=>t+e.totalTokens,0)}getApiCallCount(){return this.usageHistory.length}getEstimatedCost(){return this.usageHistory.reduce((t,e)=>t+e.cost,0)}getDailyUsage(){let t=new Date,e=new Date(t.getFullYear(),t.getMonth(),t.getDate()),r=this.usageHistory.filter(o=>o.timestamp>=e),s=r.reduce((o,l)=>o+l.totalTokens,0),n=r.reduce((o,l)=>o+l.cost,0),i=r.length;return{totalTokens:s,totalCost:n,operationCount:i}}getCurrentRateLimit(){let t=new Date,e=new Date(t.getTime()-60*60*1e3),s=this.usageHistory.filter(i=>i.timestamp>=e).reduce((i,o)=>i+o.totalTokens,0),n=new Date(Math.ceil(t.getTime()/(60*60*1e3))*(60*60*1e3));return{used:s,limit:1e4,resetTime:n}}calculateCost(t,e){let r=t/1e3*this.COST_PER_1K_INPUT_TOKENS,s=e/1e3*this.COST_PER_1K_OUTPUT_TOKENS;return Number((r+s).toFixed(6))}async persistUsage(t){try{let e=te(),r=`
|
|
131
|
+
mutation CreateClaudeUsageSession($input: CreateClaudeUsageSessionInput!) {
|
|
132
|
+
createClaudeUsageSession(input: $input) {
|
|
133
|
+
id
|
|
134
|
+
sessionId
|
|
135
|
+
type
|
|
136
|
+
isError
|
|
137
|
+
totalCostUsd
|
|
138
|
+
createdAt
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
`,s=this.mapAnalysisTypeToSessionType(t.analysisType),n=this.mapAnalysisTypeToSessionSubtype(t.analysisType),i={sessionId:t.sessionId,type:s,subtype:n,organizationId:process.env.TASK_SHEPHERD_ORGANIZATION_ID||"default-org",isError:!1,durationMs:0,durationApiMs:0,numTurns:1,totalCostUsd:t.cost,usage:{inputTokens:t.inputTokens,outputTokens:t.outputTokens,cacheCreationInputTokens:0,cacheReadInputTokens:0,totalTokens:t.totalTokens},startedAt:t.timestamp,completedAt:t.timestamp},o=await e.mutate({query:r,variables:{input:i},operationName:"CreateClaudeUsageSession"});if(!o.data?.createClaudeUsageSession)throw new Error("Failed to create usage session in backend");c.debug("Usage session persisted to backend",{sessionId:t.sessionId,backendId:o.data.createClaudeUsageSession.id})}catch(e){throw c.warn("Failed to persist usage to backend",{sessionId:t.sessionId,error:e instanceof Error?e.message:String(e)}),e}}mapAnalysisTypeToSessionType(t){switch(t.toLowerCase()){case"project_review":return"PROJECT_REVIEW";case"development_plan":return"DEVELOPMENT_PLAN";case"story_implementation":return"STORY_IMPLEMENTATION";case"task_implementation":return"TASK_IMPLEMENTATION";case"code_review":return"CODE_REVIEW";default:return"OTHER"}}mapAnalysisTypeToSessionSubtype(t){switch(t.toLowerCase()){case"project_review":return"ANALYSIS";case"development_plan":return"PLANNING";case"story_implementation":case"task_implementation":return"IMPLEMENTATION";case"code_review":return"REVIEW";default:return"OTHER"}}};var J=h(require("path")),je=h(require("fs")),F=new Ft.Command;F.name("task-shepherd-agent").description("Task Shepherd AI Agent CLI").version(process.env.npm_package_version||"1.0.0");F.command("init").description("Initialize agent configuration with interactive wizard").option("-f, --force","Force re-initialization even if agent is already configured").action(async a=>{try{let t=new oe;a.force&&console.log(d.default.yellow("\u26A0\uFE0F Force mode enabled - existing configuration will be overwritten")),await t.run()}catch(t){console.error(d.default.red("\u274C Initialization failed:"),t instanceof Error?t.message:t),process.exit(1)}});F.command("status").description("Show current agent configuration and status").option("-j, --json","Output in JSON format").action(async a=>{try{let t=new N,e=t.getCurrentIdentity();if(!e){console.log(d.default.yellow('\u26A0\uFE0F No agent identity found. Run "init" to set up the agent.'));return}if(a.json)console.log(JSON.stringify({identity:e,configPath:t.getIdentityFilePath(),envPath:J.default.join(process.cwd(),".env")},null,2));else{console.log(d.default.blue.bold(`
|
|
142
|
+
\u{1F916} Agent Status`)),console.log(d.default.gray("\u2550".repeat(40))),console.log(d.default.cyan("Identity:")),console.log(` ID: ${d.default.white(e.agentId)}`),console.log(` Name: ${d.default.white(e.agentName)}`),console.log(` Hostname: ${d.default.white(e.hostname)}`),console.log(` Platform: ${d.default.white(e.platform)}`),console.log(` Environment: ${d.default.white(e.environment)}`),console.log(d.default.cyan(`
|
|
143
|
+
Timing:`)),console.log(` Created: ${d.default.white(new Date(e.createdAt).toLocaleString())}`),console.log(` Last Used: ${d.default.white(new Date(e.lastUsed).toLocaleString())}`),console.log(d.default.cyan(`
|
|
144
|
+
Configuration:`)),console.log(` Identity File: ${d.default.gray(t.getIdentityFilePath())}`),console.log(` Environment File: ${d.default.gray(J.default.join(process.cwd(),".env"))}`);let r=je.default.existsSync(".env");console.log(` Environment Status: ${r?d.default.green("\u2713 Found"):d.default.red("\u2717 Missing")}`)}}catch(t){console.error(d.default.red("\u274C Failed to get agent status:"),t instanceof Error?t.message:t),process.exit(1)}});var rt=F.command("identity").description("Manage agent identity");rt.command("show").description("Show current agent identity").action(async()=>{try{let t=new N().getCurrentIdentity();if(!t){console.log(d.default.yellow("\u26A0\uFE0F No agent identity found."));return}console.log(d.default.blue.bold(`
|
|
145
|
+
\u{1F4CB} Agent Identity`)),console.log(d.default.gray("\u2550".repeat(30))),console.log(JSON.stringify(t,null,2))}catch(a){console.error(d.default.red("\u274C Failed to show identity:"),a instanceof Error?a.message:a),process.exit(1)}});rt.command("reset").description("Reset agent identity (will require re-initialization)").option("-y, --yes","Skip confirmation prompt").action(async a=>{try{if(!a.yes){let r=require("readline").createInterface({input:process.stdin,output:process.stdout}),s=await new Promise(n=>{r.question(d.default.yellow("\u26A0\uFE0F This will delete your agent identity. Continue? (y/N): "),n)});if(r.close(),s.toLowerCase()!=="y"&&s.toLowerCase()!=="yes"){console.log(d.default.gray("Operation cancelled."));return}}await new N().resetIdentity(),console.log(d.default.green("\u2705 Agent identity reset successfully")),console.log(d.default.gray('Run "init" to create a new identity'))}catch(t){console.error(d.default.red("\u274C Failed to reset identity:"),t instanceof Error?t.message:t),process.exit(1)}});rt.command("strategies").description("List available identity generation strategies").action(()=>{let t=new N().getAvailableStrategies();console.log(d.default.blue.bold(`
|
|
146
|
+
\u{1F527} Available Identity Strategies`)),console.log(d.default.gray("\u2550".repeat(50))),t.forEach((e,r)=>{console.log(d.default.cyan(`${r+1}. ${e.strategy}`)),console.log(d.default.gray(` ${e.description}`)),console.log(d.default.gray(` Example: ${e.example}
|
|
147
|
+
`))})});var Mt=F.command("heartbeat").description("Heartbeat and health monitoring commands");Mt.command("test").description("Test heartbeat connection to backend").option("-u, --url <url>","Backend GraphQL URL").option("-k, --api-key <key>","API key for authentication").action(async a=>{try{console.log(d.default.blue("\u{1F504} Testing heartbeat connection..."));let t=a.apiKey||process.env.TASK_SHEPHERD_API_KEY;t||(console.error(d.default.red("\u274C No API key provided. Use --api-key or set TASK_SHEPHERD_API_KEY")),process.exit(1));let e=new ce({baseUrl:a.url,apiKey:t}),r=new be,s=new N;await s.initializeIdentity({strategy:"hostname",persistent:!1}),await new ve(e,r,s).forceHeartbeat()?console.log(d.default.green("\u2705 Heartbeat test successful")):(console.log(d.default.red("\u274C Heartbeat test failed")),process.exit(1))}catch(t){console.error(d.default.red("\u274C Heartbeat test failed:"),t instanceof Error?t.message:t),process.exit(1)}});Mt.command("metrics").description("Show current heartbeat metrics").action(async()=>{try{console.log(d.default.yellow("\u26A0\uFE0F Heartbeat metrics are only available when the agent is running")),console.log(d.default.gray("Use the web dashboard at http://localhost:8548 to view live metrics"))}catch(a){console.error(d.default.red("\u274C Failed to get heartbeat metrics:"),a instanceof Error?a.message:a),process.exit(1)}});var de=F.command("workspace").description("Workspace discovery and management commands");de.command("register").description("Register current directory as a Task Shepherd workspace").option("-p, --path <path>","Path to register as workspace",process.cwd()).action(async a=>{try{console.log(d.default.blue("\u{1F4DD} Registering workspace..."));let{WorkspaceRegistrationWizard:t}=await Promise.resolve().then(()=>(Dt(),Rt));await new t().run(a.path)}catch(t){console.error(d.default.red("\u274C Workspace registration failed:"),t instanceof Error?t.message:t),process.exit(1)}});de.command("list").description("List workspaces from local registry").option("-j, --json","Output in JSON format").option("-s, --sync-status","Show sync status for each workspace").action(async a=>{try{console.log(d.default.blue("\u{1F4CB} Listing local workspace registry..."));let{getWorkspaceRegistry:t}=await Promise.resolve().then(()=>(B(),pe)),e=t();await e.initialize();let r=e.getAllWorkspaces();if(a.json)console.log(JSON.stringify(r,null,2));else if(r.length===0)console.log(d.default.yellow("\u26A0\uFE0F No workspaces in local registry")),console.log(d.default.gray('Run "workspace discover" to find and register workspaces'));else{let s=e.getSyncStats();console.log(d.default.green(`\u2705 Found ${r.length} workspace(s) in local registry:`)),a.syncStatus&&console.log(d.default.gray(` Synced: ${s.synced}, Pending: ${s.pending}, Failed: ${s.failed}`)),console.log();for(let n of r){let i=n.workspace;if(console.log(d.default.white.bold(`${i.name} (${i.workspaceId})`)),console.log(d.default.gray(` Path: ${i.path}`)),console.log(d.default.gray(` Pattern: ${i.pattern}`)),console.log(d.default.gray(` Discovered: ${new Date(n.discoveredAt).toLocaleString()}`)),a.syncStatus){let o={synced:"\u2705",pending:"\u23F3",failed:"\u274C"}[n.syncStatus];console.log(d.default.gray(` Sync Status: ${o} ${n.syncStatus}`)),n.lastSyncedAt&&console.log(d.default.gray(` Last Synced: ${new Date(n.lastSyncedAt).toLocaleString()}`)),n.syncError&&console.log(d.default.red(` Sync Error: ${n.syncError}`))}i.services&&i.services.length>0&&console.log(d.default.gray(` Services: ${i.services.map(o=>`${o.name} (${o.technology})`).join(", ")}`)),console.log()}}process.exit(0)}catch(t){console.error(d.default.red("\u274C Failed to list workspaces:"),t instanceof Error?t.message:t),process.exit(1)}});de.command("remove").description("Remove workspace from local registry").option("-i, --id <id>","Workspace ID to remove").option("-p, --path <path>","Remove workspace by path").option("-y, --yes","Skip confirmation prompt").action(async a=>{try{!a.id&&!a.path&&(console.error(d.default.red("\u274C Must specify either --id or --path")),process.exit(1));let{getWorkspaceRegistry:t}=await Promise.resolve().then(()=>(B(),pe)),e=t();await e.initialize();let r=e.getAllWorkspaces(),s=null;if(a.id)s=r.find(n=>n.workspace.workspaceId===a.id);else if(a.path){let n=J.default.resolve(a.path);s=r.find(i=>J.default.resolve(i.workspace.path)===n)}if(s||(console.error(d.default.red(`\u274C Workspace not found: ${a.id||a.path}`)),process.exit(1)),!a.yes){let i=require("readline").createInterface({input:process.stdin,output:process.stdout}),o=await new Promise(l=>{i.question(d.default.yellow(`\u26A0\uFE0F Remove workspace "${s.workspace.name}" (${s.workspace.workspaceId})? (y/N): `),l)});if(i.close(),o.toLowerCase()!=="y"&&o.toLowerCase()!=="yes"){console.log(d.default.gray("Operation cancelled."));return}}await e.removeWorkspace(s.workspace.workspaceId),console.log(d.default.green(`\u2705 Workspace "${s.workspace.name}" removed from local registry`)),console.log(d.default.gray(` ID: ${s.workspace.workspaceId}`)),console.log(d.default.gray(` Path: ${s.workspace.path}`)),process.exit(0)}catch(t){console.error(d.default.red("\u274C Failed to remove workspace:"),t instanceof Error?t.message:t),process.exit(1)}});de.command("sync").description("Sync local workspace registry with backend").option("-w, --workspace <id>","Sync specific workspace by ID").action(async a=>{try{console.log(d.default.blue("\u{1F504} Syncing workspaces with backend..."));let{getWorkspaceSyncService:t}=await Promise.resolve().then(()=>(et(),Ze)),{getWorkspaceRegistry:e}=await Promise.resolve().then(()=>(B(),pe)),r=t(),s=e();if(await s.initialize(),process.env.TASK_SHEPHERD_API_KEY||(console.error(d.default.red("\u274C No API key found. Set TASK_SHEPHERD_API_KEY environment variable.")),process.exit(1)),r.setConnectionStatus(!0,!1),a.workspace)try{await r.syncWorkspace(a.workspace),console.log(d.default.green(`\u2705 Successfully synced workspace: ${a.workspace}`))}catch(i){console.error(d.default.red(`\u274C Failed to sync workspace: ${i instanceof Error?i.message:i}`)),process.exit(1)}else{let i=s.getSyncStats();console.log(d.default.gray(`Found ${i.total} workspace(s): ${i.pending} pending, ${i.failed} failed`)),await r.syncWorkspaces();let o=s.getSyncStats();console.log(d.default.green(`\u2705 Sync complete: ${o.synced} synced, ${o.failed} failed`))}process.exit(0)}catch(t){console.error(d.default.red("\u274C Workspace sync failed:"),t instanceof Error?t.message:t),process.exit(1)}});de.command("status").description("Show workspace registry and sync status").action(async()=>{try{let{getWorkspaceRegistry:a}=await Promise.resolve().then(()=>(B(),pe)),{getWorkspaceSyncService:t}=await Promise.resolve().then(()=>(et(),Ze)),e=a();await e.initialize();let s=t().getSyncStatus(),n=e.getSyncStats();console.log(d.default.blue.bold(`
|
|
148
|
+
\u{1F4CA} Workspace Registry Status`)),console.log(d.default.gray("\u2550".repeat(40))),console.log(d.default.cyan("Registry Statistics:")),console.log(` Total Workspaces: ${d.default.white(n.total)}`),console.log(` Synced: ${d.default.green(n.synced)}`),console.log(` Pending: ${d.default.yellow(n.pending)}`),console.log(` Failed: ${d.default.red(n.failed)}`),console.log(d.default.cyan(`
|
|
149
|
+
Sync Status:`)),console.log(` Backend Connected: ${s.isConnected?d.default.green("\u2713"):d.default.red("\u2717")}`),console.log(` Sync In Progress: ${s.syncInProgress?d.default.yellow("Yes"):d.default.gray("No")}`);let i=J.default.join(process.env.HOME||process.env.USERPROFILE||"",".task-shepherd-agent","workspace-registry.json");console.log(d.default.cyan(`
|
|
150
|
+
Registry Location:`)),console.log(` ${d.default.gray(i)}`),process.exit(0)}catch(a){console.error(d.default.red("\u274C Failed to get status:"),a instanceof Error?a.message:a),process.exit(1)}});var Ht=F.command("config").description("Configuration management commands");Ht.command("validate").description("Validate current configuration").action(async()=>{try{console.log(d.default.blue("\u{1F50D} Validating configuration..."));let a=[],t=[],e=new N,r=e.getCurrentIdentity();if(!r)a.push("No agent identity found");else{let s=e.validateAgentId(r.agentId);s.valid||a.push(`Invalid agent ID: ${s.errors.join(", ")}`)}if(!je.default.existsSync(".env"))t.push(".env file not found");else{let s=je.default.readFileSync(".env","utf8"),n=["TASK_SHEPHERD_API_URL","AGENT_ID"],i=["TASK_SHEPHERD_API_KEY","AGENT_NAME"];for(let o of n)s.includes(o)||a.push(`Missing required environment variable: ${o}`);for(let o of i)s.includes(o)||t.push(`Missing optional environment variable: ${o}`)}console.log(d.default.blue.bold(`
|
|
151
|
+
\u{1F4CB} Configuration Validation`)),console.log(d.default.gray("\u2550".repeat(40))),a.length===0?console.log(d.default.green("\u2705 Configuration is valid")):(console.log(d.default.red(`\u274C Found ${a.length} error(s):`)),a.forEach(s=>{console.log(d.default.red(` \u2022 ${s}`))})),t.length>0&&(console.log(d.default.yellow(`\u26A0\uFE0F Found ${t.length} warning(s):`)),t.forEach(s=>{console.log(d.default.yellow(` \u2022 ${s}`))})),a.length>0&&(console.log(d.default.gray(`
|
|
152
|
+
Run "init" to fix configuration issues`)),process.exit(1))}catch(a){console.error(d.default.red("\u274C Configuration validation failed:"),a instanceof Error?a.message:a),process.exit(1)}});Ht.command("show").description("Show current configuration").action(()=>{try{console.log(d.default.blue.bold(`
|
|
153
|
+
\u2699\uFE0F Current Configuration`)),console.log(d.default.gray("\u2550".repeat(40)));let a=["AGENT_ID","AGENT_NAME","PORT","NODE_ENV","TASK_SHEPHERD_API_URL","TASK_SHEPHERD_API_KEY","ENABLE_HEARTBEAT","ENABLE_METRICS","ENABLE_WEB_UI","HEARTBEAT_INTERVAL","LOG_LEVEL","WEB_PORT"];console.log(d.default.cyan("Environment Variables:")),a.forEach(e=>{let r=process.env[e];if(r){let s=e.includes("KEY")?"***HIDDEN***":r;console.log(` ${e}: ${d.default.white(s)}`)}else console.log(` ${e}: ${d.default.gray("(not set)")}`)});let t=new N;console.log(d.default.cyan(`
|
|
154
|
+
File Locations:`)),console.log(` Identity: ${d.default.gray(t.getIdentityFilePath())}`),console.log(` Environment: ${d.default.gray(J.default.join(process.cwd(),".env"))}`),console.log(` Working Directory: ${d.default.gray(process.cwd())}`)}catch(a){console.error(d.default.red("\u274C Failed to show configuration:"),a instanceof Error?a.message:a),process.exit(1)}});var st=F.command("debug").description("Debug work items and analyze error patterns");st.command("work-item <workItemId>").description("Debug specific work item by ID").option("-v, --verbose","Show detailed information").option("--timeline","Show execution timeline").option("--suggestions","Show fix suggestions").option("--export <format>","Export debug data (json|csv)").action(async(a,t)=>{try{let{createDebugWorkItemCommand:e}=await Promise.resolve().then(()=>(Ne(),_e));await e().parseAsync(["node","debug","--work-item-id",a,...process.argv.slice(4)])}catch(e){console.error(d.default.red("\u274C Debug command failed:"),e instanceof Error?e.message:e),process.exit(1)}});st.command("work-type <workType>").description("Analyze error patterns for work type").option("--export <format>","Export pattern data (json)").action(async(a,t)=>{try{let{createDebugWorkItemCommand:e}=await Promise.resolve().then(()=>(Ne(),_e));await e().parseAsync(["node","debug","--work-type",a,...process.argv.slice(4)])}catch(e){console.error(d.default.red("\u274C Debug command failed:"),e instanceof Error?e.message:e),process.exit(1)}});st.command("health").description("Show work item health overview").option("--export <format>","Export health data (json)").action(async a=>{try{let{createDebugWorkItemCommand:t}=await Promise.resolve().then(()=>(Ne(),_e));await t().parseAsync(["node","debug",...process.argv.slice(3)])}catch(t){console.error(d.default.red("\u274C Debug command failed:"),t instanceof Error?t.message:t),process.exit(1)}});F.configureHelp({sortSubcommands:!0});F.on("command:*",a=>{console.error(d.default.red(`\u274C Unknown command: ${a[0]}`)),console.log(d.default.gray("Run --help to see available commands")),process.exit(1)});require.main===module&&F.parse();0&&(module.exports={program});
|