@task-shepherd/agent 1.0.12 → 1.0.14
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/dist/cli/index.js +1 -1
- package/dist/index.js +1045 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";var Xd=Object.create;var Oa=Object.defineProperty;var Zd=Object.getOwnPropertyDescriptor;var el=Object.getOwnPropertyNames;var tl=Object.getPrototypeOf,al=Object.prototype.hasOwnProperty;var D=(n,t)=>()=>(n&&(t=n(n=0)),t);var K=(n,t)=>()=>(t||n((t={exports:{}}).exports,t),t.exports),nt=(n,t)=>{for(var e in t)Oa(n,e,{get:t[e],enumerable:!0})},ps=(n,t,e,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of el(t))!al.call(n,r)&&r!==e&&Oa(n,r,{get:()=>t[r],enumerable:!(a=Zd(t,r))||a.enumerable});return n};var T=(n,t,e)=>(e=n!=null?Xd(tl(n)):{},ps(t||!n||!n.__esModule?Oa(e,"default",{value:n,enumerable:!0}):e,n)),ds=n=>ps(Oa({},"__esModule",{value:!0}),n);var b,rl,ls,il,nl,sl,ol,pl,dl,ll,cl,ul,ml,gl,hl,yl,fl,cs,ei,ti=D(()=>{"use strict";b=require("zod"),rl=b.z.enum(["development","staging","production","test"]),ls=b.z.enum(["error","warn","info","debug","verbose"]),il=b.z.object({port:b.z.number().int().min(1).max(65535).default(8547),host:b.z.string().default("localhost"),environment:rl.default("development"),logLevel:ls.default("info"),requestTimeout:b.z.number().int().min(1e3).max(6e5).default(3e4),maxRequestSize:b.z.string().default("10mb"),enableCors:b.z.boolean().default(!0),enableHelmet:b.z.boolean().default(!0),enableCompression:b.z.boolean().default(!0)}),nl=b.z.object({apiUrl:b.z.string().url(),apiKey:b.z.string().optional(),timeout:b.z.number().int().min(1e3).max(6e4).default(3e4),retries:b.z.number().int().min(0).max(10).default(3),retryDelay:b.z.number().int().min(100).max(1e4).default(1e3)}),sl=b.z.object({url:b.z.string().default("redis://localhost:6379"),host:b.z.string().optional(),port:b.z.number().int().min(1).max(65535).optional(),password:b.z.string().optional(),database:b.z.number().int().min(0).max(15).default(0),keyPrefix:b.z.string().default("ai-agent:"),connectTimeout:b.z.number().int().min(1e3).max(3e4).default(1e4),maxRetriesPerRequest:b.z.number().int().min(0).max(10).default(3)}),ol=b.z.object({apiKey:b.z.string().optional(),baseUrl:b.z.string().url().optional(),model:b.z.string().default("claude-3-5-sonnet-20241022"),maxRetries:b.z.number().int().min(0).max(10).default(3),timeoutMs:b.z.number().int().min(1e3).max(3e5).default(6e4),maxTokens:b.z.number().int().min(100).max(8192).default(4096),temperature:b.z.number().min(0).max(1).default(.7),commandPath:b.z.string().default("claude")}),pl=b.z.object({tokenLimit:b.z.number().int().min(1e3).max(1e6).default(1e4),requestsPerMinute:b.z.number().int().min(1).max(1e3).default(60),requestsPerHour:b.z.number().int().min(1).max(1e4).default(1e3),burstLimit:b.z.number().int().min(1).max(100).default(10),windowSizeMs:b.z.number().int().min(1e3).max(36e5).default(6e4)}),dl=b.z.enum(["project_review","implementation_plan","story_implementation","task_completion","code_review","review_application"]),ll=b.z.object({maxConcurrentJobs:b.z.number().int().min(1).max(10).default(3),jobTimeout:b.z.number().int().min(3e4).max(18e5).default(3e5),retryAttempts:b.z.number().int().min(0).max(5).default(2),retryDelay:b.z.number().int().min(1e3).max(6e4).default(5e3),healthCheckInterval:b.z.number().int().min(5e3).max(3e5).default(3e4),enabledCapabilities:b.z.array(dl).default(["project_review","implementation_plan","story_implementation","task_completion","code_review","review_application"])}),cl=b.z.object({path:b.z.string().default("./data/ai-agent.db"),backupEnabled:b.z.boolean().default(!0),backupInterval:b.z.number().int().min(36e5).max(864e5).default(36e5),maxBackups:b.z.number().int().min(1).max(30).default(7),vacuumInterval:b.z.number().int().min(864e5).max(6048e5).default(864e5)}),ul=b.z.object({enableApiKeyAuth:b.z.boolean().default(!1),apiKeys:b.z.array(b.z.string()).default([]),allowedOrigins:b.z.array(b.z.string()).default(["http://localhost:3000","http://localhost:5173"]),enableHttps:b.z.boolean().default(!1),httpsOptions:b.z.object({keyPath:b.z.string().optional(),certPath:b.z.string().optional()}).optional(),sessionSecret:b.z.string().min(32).optional()}),ml=b.z.object({enableMetrics:b.z.boolean().default(!0),metricsPort:b.z.number().int().min(1).max(65535).default(9090),enableHealthChecks:b.z.boolean().default(!0),healthCheckPath:b.z.string().default("/health"),enableProfiling:b.z.boolean().default(!1)}),gl=b.z.object({level:ls.default("info"),enableConsole:b.z.boolean().default(!0),enableFile:b.z.boolean().default(!0),logDirectory:b.z.string().default("./logs"),maxFileSize:b.z.string().default("100MB"),maxFiles:b.z.number().int().min(1).max(100).default(10),datePattern:b.z.string().default("YYYY-MM-DD"),enableRotation:b.z.boolean().default(!0),enableJson:b.z.boolean().default(!1)}),hl=b.z.object({enableWebInterface:b.z.boolean().default(!0),enableApiDocumentation:b.z.boolean().default(!0),enableMetricsApi:b.z.boolean().default(!0),enableWorkspaceAnalysis:b.z.boolean().default(!0),enableMultiWorkspace:b.z.boolean().default(!0),enableClaudeApiIntegration:b.z.boolean().default(!0),enableExperimentalFeatures:b.z.boolean().default(!1)}),yl=b.z.object({id:b.z.string().min(1),name:b.z.string().min(1),domain:b.z.string().optional(),apiUrl:b.z.string().url(),wsUrl:b.z.string().url().optional(),apiKey:b.z.string().min(1),enabled:b.z.boolean().default(!0),metadata:b.z.object({description:b.z.string().optional(),color:b.z.string().optional(),logo:b.z.string().url().optional(),addedAt:b.z.string().optional()}).optional()}),fl=b.z.object({setupCompleted:b.z.boolean().default(!1),defaultOrganization:b.z.string().optional(),organizations:b.z.record(b.z.string(),yl).default({})}),cs=b.z.object({server:il,taskShepherd:nl,redis:sl,claude:ol,rateLimit:pl,worker:ll,database:cl,security:ul,monitoring:ml,logging:gl,features:hl,multiOrg:fl.default({})}),ei={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 ii(n){return ai||(ai=new ri(n)),ai}function Wa(){return ii().getConfig()}var kt,st,us,ri,ai,Fa=D(()=>{"use strict";kt=T(require("fs")),st=T(require("path")),us=require("events");ti();ri=class extends us.EventEmitter{constructor(e={}){super();this.watchers=new Map;this.lastValidation=null;this.options={configDir:st.resolve(process.cwd(),"config"),environment:e.environment||"production",enableHotReload:!1,hotReloadInterval:1e3,additionalConfigFiles:[],strictValidation:!1,...e},this.config={...ei},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={},a={...ei};this.trackConfigSources(a,e,"default","built-in defaults",0);let r=this.loadConfigFile("config.json",e,1);r&&(a=this.mergeConfig(a,r));let i=this.loadConfigFile(`config.${this.options.environment}.json`,e,2);i&&(a=this.mergeConfig(a,i)),this.options.additionalConfigFiles.forEach((d,c)=>{let l=this.loadConfigFile(d,e,3+c);l&&(a=this.mergeConfig(a,l))});let s=this.loadEnvironmentOverrides();Object.keys(s).length>0&&(a=this.mergeConfig(a,s),this.trackConfigSources(s,e,"environment","environment variables",100));let o=this.validateConfig(a);if(o.success&&o.data){let d={...this.config};this.config=o.data,this.configMetadata={config:this.config,sources:e,validatedAt:new Date,environment:this.options.environment},JSON.stringify(d)!==JSON.stringify(this.config)&&this.emit("configurationChanged",{oldConfig:d,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,a,r){let i=st.isAbsolute(e)?e:st.join(this.options.configDir,e);try{if(!kt.existsSync(i))return null;let s=kt.readFileSync(i,"utf-8"),o=JSON.parse(s);return this.trackConfigSources(o,a,"file",i,r),o}catch(s){return console.warn(`Failed to load configuration file ${i}:`,s),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 a=(process.env.CAPABILITIES||process.env.AGENT_CAPABILITIES||"").split(",").map(r=>r.trim());e.worker={...e.worker,enabledCapabilities:a}}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 a=process.env.API_KEYS.split(",").map(r=>r.trim());e.security={...e.security,apiKeys:a,enableApiKeyAuth:!0}}return e}trackConfigSources(e,a,r,i,s){let o=(d,c="")=>{for(let[l,u]of Object.entries(d)){let y=c?`${c}.${l}`:l;u&&typeof u=="object"&&!Array.isArray(u)?o(u,y):a[y]={type:r,source:i,priority:s}}};o(e)}mergeConfig(e,a){let r={...e};for(let[i,s]of Object.entries(a))s&&typeof s=="object"&&!Array.isArray(s)?r[i]=this.mergeConfig(e[i]||{},s):r[i]=s;return r}validateConfig(e){let a=cs.safeParse(e);return a.success?{success:!0,data:a.data,errors:[],warnings:this.generateWarnings(a.data)}:{success:!1,errors:a.error.issues.map(r=>({path:r.path.join("."),message:r.message,code:r.code})),warnings:[]}}generateWarnings(e){let a=[];return e.server.environment==="development"&&(!e.claude.apiKey&&!e.claude.commandPath&&a.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&&a.push({path:"security.enableHttps",message:"HTTPS enabled in development mode",suggestion:"Consider disabling HTTPS for local development"})),e.server.environment==="production"&&(e.security.enableHttps||a.push({path:"security.enableHttps",message:"HTTPS disabled in production",suggestion:"Enable HTTPS for production deployment"}),e.security.enableApiKeyAuth||a.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")&&a.push({path:"server.logLevel",message:"Debug logging enabled in production",suggestion:'Use "info" or "warn" log level for production'})),a}setupHotReloading(){this.watchers.forEach(a=>a.close()),this.watchers.clear(),[st.join(this.options.configDir,"config.json"),st.join(this.options.configDir,`config.${this.options.environment}.json`),...this.options.additionalConfigFiles].forEach(a=>{if(kt.existsSync(a)){let r=kt.watch(a,i=>{i==="change"&&setTimeout(()=>{console.log(`Configuration file changed: ${a}`);let s=this.loadConfiguration();s.success?(console.log("Configuration reloaded successfully"),this.emit("configurationReloaded",this.config)):(console.error("Configuration reload failed:",s.errors),this.emit("configurationError",s.errors))},this.options.hotReloadInterval)});this.watchers.set(a,r)}})}destroy(){this.watchers.forEach(e=>e.close()),this.watchers.clear(),this.removeAllListeners()}},ai=null});var ms={};nt(ms,{detectClaude:()=>vl,detectClaudeSync:()=>ni,getClaudeCommandPath:()=>si});function vl(n="claude"){return ni(n)}function ni(n="claude"){if(pa(n))return{available:!0,path:n,method:"direct"};if(n==="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(pa(e))return{available:!0,path:e,method:"direct"};try{let e=(0,ja.execSync)('bash -c "which claude"',{encoding:"utf8",stdio:"pipe"}).trim();if(e&&!e.includes("aliased to")&&pa(e))return{available:!0,path:e,method:"which"};if(e.includes("aliased to ")){let a=e.split("aliased to ")[1];if(a&&pa(a))return{available:!0,path:a,method:"which"}}}catch{}try{let a=(0,ja.execSync)("where claude",{encoding:"utf8",stdio:"pipe"}).trim().split(`
|
|
3
|
-
`)[0];if(a&&pa(a))return{available:!0,path:a,method:"where"}}catch{}}return{available:!1,method:"none"}}function pa(n){try{return(0,ja.execSync)(`"${n}" --version`,{stdio:"pipe"}),!0}catch{return!1}}function si(n="claude"){return ni(n).path||n}var ja,oi=D(()=>{"use strict";ja=require("child_process")});function hs(n){return pi.validateConfiguration(n)}var ot,gs,pi,di=D(()=>{"use strict";ot=T(require("fs")),gs=T(require("path")),pi=class{static validateConfiguration(t){let e=[],a=[];return this.isMultiOrgMode()?{valid:!0,errors:[],warnings:[]}:(this.validateServerConfig(t,e,a),this.validateTaskShepherdConfig(t,e,a),this.validateRedisConfig(t,e,a),this.validateClaudeConfig(t,e,a),this.validateDatabaseConfig(t,e,a),this.validateSecurityConfig(t,e,a),this.validateLoggingConfig(t,e,a),this.validateConfigurationDependencies(t,e,a),{valid:e.length===0,errors:e,warnings:a})}static isMultiOrgMode(){let t=require("fs"),e=require("path"),a=require("os"),r=e.join(a.homedir(),".task-shepherd-agent","config.json");return t.existsSync(r)}static validateServerConfig(t,e,a){let{server:r}=t;r.port<1024&&typeof process.getuid=="function"&&process.getuid()!==0&&a.push({path:"server.port",message:`Port ${r.port} requires root privileges`,code:"PRIVILEGED_PORT",severity:"warning",suggestion:"Use a port number above 1024 for non-root users"}),r.environment==="production"&&(r.logLevel==="debug"||r.logLevel==="verbose")&&a.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'}),r.requestTimeout<5e3&&a.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,a){let{taskShepherd:r}=t;if(r){try{new URL(r.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"&&!r.apiKey&&a.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"}),r.timeout>6e4&&a.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,a){let{redis:r}=t;if(!r){e.push({path:"redis",message:"Redis configuration is missing",code:"MISSING_REDIS_CONFIG",severity:"error"});return}r.url&&!r.url.startsWith("redis://")&&!r.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"}),(r.database<0||r.database>15)&&e.push({path:"redis.database",message:"Redis database number must be between 0 and 15",code:"INVALID_DB_NUMBER",severity:"error"}),r.connectTimeout<1e3&&a.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,a){let{claude:r}=t;if(!r.apiKey&&!this.isClaudeCliAvailable(r.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"}),r.baseUrl)try{new URL(r.baseUrl)}catch{e.push({path:"claude.baseUrl",message:"Invalid Claude base URL format",code:"INVALID_BASE_URL",severity:"error"})}let i=["claude-3-5-sonnet-20241022","claude-3-haiku-20240307","claude-3-opus-20240229"];r.model&&!i.includes(r.model)&&a.push({path:"claude.model",message:"Unknown Claude model specified",code:"UNKNOWN_MODEL",severity:"warning",suggestion:`Use one of: ${i.join(", ")}`}),r.timeoutMs<3e4&&a.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"}),(r.temperature<0||r.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,a){let{database:r}=t;if(!r){e.push({path:"database",message:"Database configuration is missing",code:"MISSING_DATABASE_CONFIG",severity:"error"});return}let i=gs.dirname(r.path);try{ot.existsSync(i)||ot.mkdirSync(i,{recursive:!0})}catch{e.push({path:"database.path",message:`Cannot create database directory: ${i}`,code:"INVALID_DB_PATH",severity:"error",suggestion:"Ensure the directory is writable"})}r.backupEnabled&&r.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"}),r.backupEnabled&&r.backupInterval<6e4&&a.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,a){let{security:r}=t;if(!r){e.push({path:"security",message:"Security configuration is missing",code:"MISSING_SECURITY_CONFIG",severity:"error"});return}if(t.server.environment==="production"&&(r.enableHttps||a.push({path:"security.enableHttps",message:"HTTPS disabled in production",code:"PRODUCTION_HTTP",severity:"warning",suggestion:"Enable HTTPS for production deployment"}),r.enableApiKeyAuth||a.push({path:"security.enableApiKeyAuth",message:"API key authentication disabled in production",code:"PRODUCTION_NO_AUTH",severity:"warning",suggestion:"Enable API key authentication for security"})),r.enableHttps&&r.httpsOptions){let{keyPath:i,certPath:s}=r.httpsOptions;i&&!ot.existsSync(i)&&e.push({path:"security.httpsOptions.keyPath",message:"SSL private key file not found",code:"MISSING_SSL_KEY",severity:"error"}),s&&!ot.existsSync(s)&&e.push({path:"security.httpsOptions.certPath",message:"SSL certificate file not found",code:"MISSING_SSL_CERT",severity:"error"})}r.enableApiKeyAuth&&r.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"}),r.sessionSecret&&r.sessionSecret.length<32&&a.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,a){let{logging:r}=t;if(r.enableFile)try{ot.existsSync(r.logDirectory)||ot.mkdirSync(r.logDirectory,{recursive:!0})}catch{e.push({path:"logging.logDirectory",message:`Cannot create log directory: ${r.logDirectory}`,code:"INVALID_LOG_DIR",severity:"error",suggestion:"Ensure the directory is writable"})}r.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(r.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,a){let r=t.worker.maxConcurrentJobs,i=t.rateLimit.requestsPerMinute;r*10>i&&a.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&&a.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}=(oi(),ds(ms));return e(t).available}}});function Sl(){let n=Wa();return{port:n.server.port,nodeEnv:n.server.environment,taskShepherdApiUrl:n.taskShepherd.apiUrl,taskShepherdApiKey:n.taskShepherd.apiKey,redisUrl:n.redis.url,claudeCommandPath:n.claude.commandPath,claudeApiKey:n.claude.apiKey,claudeBaseUrl:n.claude.baseUrl,claudeModel:n.claude.model,claudeMaxRetries:n.claude.maxRetries,claudeTimeoutMs:n.claude.timeoutMs,maxConcurrentJobs:n.worker.maxConcurrentJobs,tokenRateLimit:n.rateLimit.tokenLimit,logLevel:n.server.logLevel}}var li,wl,Ot,ys=D(()=>{"use strict";ti();Fa();di();Fa();di();li=Sl(),wl=ii(),Ot={warnings:[]};if(Ot=hs(wl.getConfig()),!Ot.valid&&(console.error("Configuration validation failed:"),Ot.errors.forEach(n=>{console.error(` - ${n.path}: ${n.message}`)}),Ot.errors.some(n=>n.severity==="error")))throw new Error("Configuration contains critical errors. Please fix them before starting the service.");Ot.warnings.length>0&&(console.warn("Configuration warnings:"),Ot.warnings.forEach(n=>{console.warn(` - ${n.path}: ${n.message}`),n.suggestion&&console.warn(` Suggestion: ${n.suggestion}`)}))});var Te,p,U=D(()=>{"use strict";Te=T(require("winston"));ys();p=Te.default.createLogger({level:li.nodeEnv==="development"?"debug":"info",format:Te.default.format.combine(Te.default.format.timestamp(),Te.default.format.errors({stack:!0}),Te.default.format.json()),defaultMeta:{service:"agent"},transports:[new Te.default.transports.File({filename:"logs/error.log",level:"error",maxsize:100*1024*1024,maxFiles:5,tailable:!0}),new Te.default.transports.File({filename:"logs/combined.log",maxsize:100*1024*1024,maxFiles:5,tailable:!0})]});li.nodeEnv!=="production"&&p.add(new Te.default.transports.Console({format:Te.default.format.combine(Te.default.format.colorize(),Te.default.format.simple())}))});var Wt,ci,oe,La,ue,da=D(()=>{"use strict";Wt=require("fs"),ci=T(require("path")),oe=T(require("os")),La=T(require("crypto"));U();ue=class{constructor(t){this.configDir=t||ci.default.join(oe.default.homedir(),".task-shepherd-agent"),this.identityFile=ci.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),p.info("Using existing agent identity",{agentId:e.agentId,agentName:e.agentName,service:"identity"}),this.currentIdentity=e,e;let a=await this.generateNewIdentity(t);return t.persistent!==!1&&await this.saveIdentity(a),this.currentIdentity=a,p.info("Generated new agent identity",{agentId:a.agentId,agentName:a.agentName,strategy:t.strategy,service:"identity"}),a}async generateNewIdentity(t){let e=oe.default.hostname(),a=oe.default.platform(),r=oe.default.userInfo().username,i="production",s,o;switch(t.strategy){case"hostname":s=await this.generateHostnameBasedId(t),o=t.customName||`AI Agent (${e})`;break;case"user-configured":s=await this.generateUserConfiguredId(t),o=t.customName||`AI Agent (${s})`;break;case"machine-fingerprint":s=await this.generateMachineFingerprintId(t),o=t.customName||`AI Agent (${e})`;break;case"hybrid":s=await this.generateHybridId(t),o=t.customName||`AI Agent (${this.extractReadablePart(s)})`;break;default:throw new Error(`Unknown identity strategy: ${t.strategy}`)}return{agentId:s,agentName:o,hostname:e,platform:a,userId:r,environment:i,createdAt:new Date().toISOString(),lastUsed:new Date().toISOString(),version:process.env.npm_package_version||"1.0.0"}}async generateHostnameBasedId(t){let e=oe.default.hostname(),a=[];t.prefix&&a.push(t.prefix);let r=e.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").substring(0,20);if(a.push(r),t.includeUser){let i=oe.default.userInfo().username.toLowerCase().replace(/[^a-z0-9]/g,"").substring(0,10);a.push(i)}if(t.includeEnvironment){let i="production".substring(0,4);a.push(i)}return t.suffix&&a.push(t.suffix),a.join("-")}async generateUserConfiguredId(t){if(t.customName){let a=[t.customName.toLowerCase().replace(/[^a-z0-9-\s]/g,"").replace(/\s+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").substring(0,30)];if(t.includeEnvironment){let i="production".substring(0,4);a.push(i)}let r=La.default.createHash("md5").update(oe.default.hostname()+oe.default.userInfo().username).digest("hex").substring(0,4);return a.push(r),a.join("-")}return this.generateInteractiveId(t)}async generateMachineFingerprintId(t){let e=this.getMachineFingerprint(),a=La.default.createHash("sha256").update(e).digest("hex").substring(0,12),r=[];return t.prefix&&r.push(t.prefix),r.push("agent"),r.push(a),t.suffix&&r.push(t.suffix),r.join("-")}async generateHybridId(t){let e=oe.default.hostname(),a=oe.default.userInfo().username,r=e.toLowerCase().replace(/[^a-z0-9]/g,"").substring(0,8),i=La.default.createHash("md5").update(`${e}-${a}-${oe.default.platform()}`).digest("hex").substring(0,6),s=[];if(t.prefix&&s.push(t.prefix),s.push(r),s.push(i),t.includeEnvironment){let o="production".substring(0,3);s.push(o)}return t.suffix&&s.push(t.suffix),s.join("-")}async generateInteractiveId(t){let a=`ai-agent-${oe.default.hostname().toLowerCase().substring(0,8)}`;return p.info("Using default agent ID (interactive mode not available)",{defaultId:a,service:"identity"}),a}getMachineFingerprint(){return[oe.default.hostname(),oe.default.platform(),oe.default.arch(),oe.default.userInfo().username,JSON.stringify(Object.keys(oe.default.networkInterfaces()).sort())].join("|")}extractReadablePart(t){let e=t.split("-");return e.length>1?e[1]:t}async loadExistingIdentity(){try{let t=await Wt.promises.readFile(this.identityFile,"utf8"),e=JSON.parse(t);return e.agentId&&e.agentName&&e.createdAt?e:(p.warn("Invalid identity file format, will regenerate",{service:"identity"}),null)}catch(t){return t.code!=="ENOENT"&&p.warn("Failed to load existing identity",{error:t instanceof Error?t.message:String(t),service:"identity"}),null}}async saveIdentity(t){try{await Wt.promises.mkdir(this.configDir,{recursive:!0}),await Wt.promises.writeFile(this.identityFile,JSON.stringify(t,null,2),"utf8"),p.info("Agent identity saved",{agentId:t.agentId,configDir:this.configDir,service:"identity"})}catch(e){throw p.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,p.info("Agent identity updated",{agentId:e.agentId,updates:Object.keys(t),service:"identity"}),e}async resetIdentity(){try{await Wt.promises.unlink(this.identityFile),this.currentIdentity=void 0,p.info("Agent identity reset",{service:"identity"})}catch(t){if(t.code!=="ENOENT")throw p.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 Wt.promises.access(this.identityFile),!0}catch{return!1}}}});var ws=K((lu,kl)=>{kl.exports={name:"@task-shepherd/agent",version:"1.0.12",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","web/dist","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",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 za(){return mi||(mi=new gi),mi}var Il,ve,gi,mi,hi=D(()=>{"use strict";U();Il=ws(),ve={version:Il.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:[]},gi=class{getVersionMetadata(){return{...ve}}getVersion(){return ve.version}getBuildInfo(){return{version:ve.version,buildTimestamp:ve.buildTimestamp,commitHash:ve.commitHash,releaseChannel:ve.releaseChannel}}getCompatibilityRequirements(){return{...ve.compatibility}}getFeatureCapabilities(){return{...ve.features}}logVersionInfo(){p.info("Agent version information",{version:ve.version,buildTimestamp:ve.buildTimestamp,commitHash:ve.commitHash,releaseChannel:ve.releaseChannel,compatibilityRequirements:ve.compatibility,features:ve.features})}},mi=null});var Is={};nt(Is,{GraphQLHttpClient:()=>Ue,getGraphQLHttpClient:()=>It,initializeGraphQLHttpClient:()=>bl});function It(n){return p.debug("getGraphQLHttpClient called",{hasExistingClient:!!Me,hasOptions:!!n,optionsProvided:n?JSON.stringify(n,null,2):"none"}),Me||(p.info("Creating new HTTP client singleton via getGraphQLHttpClient"),Me=new Ue(n)),p.debug("Returning HTTP client",{clientExists:!!Me}),Me}function bl(n){return p.info("initializeGraphQLHttpClient called",{providedOptions:JSON.stringify(n,null,2),hasExistingClient:!!Me}),Me&&(p.info("Destroying existing HTTP client"),Me.destroy()),Me=new Ue(n),p.info("New HTTP client singleton created",{clientExists:!!Me}),Me}var ks,Ue,Me,jt=D(()=>{"use strict";ks=require("events");U();Fa();hi();Ue=class extends ks.EventEmitter{constructor(e={}){super();this.healthCheckTimer=null;this.isHealthy=!1;this.circuitBreakerOpen=!1;this.failureCount=0;this.lastHealthCheck=0;let a=Wa();p.info("GraphQL HTTP Client constructor called",{providedOptionsApiKey:e.apiKey?e.apiKey.substring(0,12)+"...":"none",configApiKey:a.taskShepherd.apiKey?a.taskShepherd.apiKey.substring(0,12)+"...":"none",configApiUrl:a.taskShepherd.apiUrl});let r=e.apiKey||a.taskShepherd.apiKey;r||p.error("CRITICAL: No API key available for GraphQL HTTP Client",{providedOptionsApiKey:e.apiKey?e.apiKey.substring(0,12)+"...":"none",configApiKey:a.taskShepherd.apiKey?a.taskShepherd.apiKey.substring(0,12)+"...":"none",configKeys:Object.keys(a.taskShepherd||{})});let i=a.taskShepherd.apiUrl,o={maxRetries:5,baseDelay:1e3,maxDelay:3e4,timeout:6e4,healthCheckInterval:3e4,enableCircuitBreaker:!0,baseUrl:e.baseUrl||i||"http://localhost:4002/api/graphql"};this.options={...o,...e,apiKey:e.apiKey!==void 0?e.apiKey:r},p.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 a=null;for(let r=1;r<=this.options.maxRetries;r++)try{let i=await this.executeRequest(e,r);return this.failureCount=0,this.circuitBreakerOpen&&(this.circuitBreakerOpen=!1,p.info("Circuit breaker closed - backend is healthy again"),this.emit("circuitBreakerClosed")),i}catch(i){if(a=i instanceof Error?i:new Error(String(i)),p.warn(`GraphQL request attempt ${r}/${this.options.maxRetries} failed`,{error:a.message,operationName:e.operationName,willRetry:r<this.options.maxRetries}),r<this.options.maxRetries){let s=this.calculateRetryDelay(r);await this.sleep(s)}}throw this.failureCount++,this.options.enableCircuitBreaker&&this.failureCount>=5&&!this.circuitBreakerOpen&&(this.circuitBreakerOpen=!0,p.error("Circuit breaker opened - too many backend failures"),this.emit("circuitBreakerOpened"),setTimeout(()=>{this.circuitBreakerOpen=!1,this.failureCount=0,p.info("Circuit breaker half-open - testing backend"),this.emit("circuitBreakerHalfOpen")},6e4)),a||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 r=await this.mutate({query:`
|
|
3
|
+
`)[0];if(a&&pa(a))return{available:!0,path:a,method:"where"}}catch{}}return{available:!1,method:"none"}}function pa(n){try{return(0,ja.execSync)(`"${n}" --version`,{stdio:"pipe"}),!0}catch{return!1}}function si(n="claude"){return ni(n).path||n}var ja,oi=D(()=>{"use strict";ja=require("child_process")});function hs(n){return pi.validateConfiguration(n)}var ot,gs,pi,di=D(()=>{"use strict";ot=T(require("fs")),gs=T(require("path")),pi=class{static validateConfiguration(t){let e=[],a=[];return this.isMultiOrgMode()?{valid:!0,errors:[],warnings:[]}:(this.validateServerConfig(t,e,a),this.validateTaskShepherdConfig(t,e,a),this.validateRedisConfig(t,e,a),this.validateClaudeConfig(t,e,a),this.validateDatabaseConfig(t,e,a),this.validateSecurityConfig(t,e,a),this.validateLoggingConfig(t,e,a),this.validateConfigurationDependencies(t,e,a),{valid:e.length===0,errors:e,warnings:a})}static isMultiOrgMode(){let t=require("fs"),e=require("path"),a=require("os"),r=e.join(a.homedir(),".task-shepherd-agent","config.json");return t.existsSync(r)}static validateServerConfig(t,e,a){let{server:r}=t;r.port<1024&&typeof process.getuid=="function"&&process.getuid()!==0&&a.push({path:"server.port",message:`Port ${r.port} requires root privileges`,code:"PRIVILEGED_PORT",severity:"warning",suggestion:"Use a port number above 1024 for non-root users"}),r.environment==="production"&&(r.logLevel==="debug"||r.logLevel==="verbose")&&a.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'}),r.requestTimeout<5e3&&a.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,a){let{taskShepherd:r}=t;if(r){try{new URL(r.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"&&!r.apiKey&&a.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"}),r.timeout>6e4&&a.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,a){let{redis:r}=t;if(!r){e.push({path:"redis",message:"Redis configuration is missing",code:"MISSING_REDIS_CONFIG",severity:"error"});return}r.url&&!r.url.startsWith("redis://")&&!r.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"}),(r.database<0||r.database>15)&&e.push({path:"redis.database",message:"Redis database number must be between 0 and 15",code:"INVALID_DB_NUMBER",severity:"error"}),r.connectTimeout<1e3&&a.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,a){let{claude:r}=t;if(!r.apiKey&&!this.isClaudeCliAvailable(r.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"}),r.baseUrl)try{new URL(r.baseUrl)}catch{e.push({path:"claude.baseUrl",message:"Invalid Claude base URL format",code:"INVALID_BASE_URL",severity:"error"})}let i=["claude-3-5-sonnet-20241022","claude-3-haiku-20240307","claude-3-opus-20240229"];r.model&&!i.includes(r.model)&&a.push({path:"claude.model",message:"Unknown Claude model specified",code:"UNKNOWN_MODEL",severity:"warning",suggestion:`Use one of: ${i.join(", ")}`}),r.timeoutMs<3e4&&a.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"}),(r.temperature<0||r.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,a){let{database:r}=t;if(!r){e.push({path:"database",message:"Database configuration is missing",code:"MISSING_DATABASE_CONFIG",severity:"error"});return}let i=gs.dirname(r.path);try{ot.existsSync(i)||ot.mkdirSync(i,{recursive:!0})}catch{e.push({path:"database.path",message:`Cannot create database directory: ${i}`,code:"INVALID_DB_PATH",severity:"error",suggestion:"Ensure the directory is writable"})}r.backupEnabled&&r.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"}),r.backupEnabled&&r.backupInterval<6e4&&a.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,a){let{security:r}=t;if(!r){e.push({path:"security",message:"Security configuration is missing",code:"MISSING_SECURITY_CONFIG",severity:"error"});return}if(t.server.environment==="production"&&(r.enableHttps||a.push({path:"security.enableHttps",message:"HTTPS disabled in production",code:"PRODUCTION_HTTP",severity:"warning",suggestion:"Enable HTTPS for production deployment"}),r.enableApiKeyAuth||a.push({path:"security.enableApiKeyAuth",message:"API key authentication disabled in production",code:"PRODUCTION_NO_AUTH",severity:"warning",suggestion:"Enable API key authentication for security"})),r.enableHttps&&r.httpsOptions){let{keyPath:i,certPath:s}=r.httpsOptions;i&&!ot.existsSync(i)&&e.push({path:"security.httpsOptions.keyPath",message:"SSL private key file not found",code:"MISSING_SSL_KEY",severity:"error"}),s&&!ot.existsSync(s)&&e.push({path:"security.httpsOptions.certPath",message:"SSL certificate file not found",code:"MISSING_SSL_CERT",severity:"error"})}r.enableApiKeyAuth&&r.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"}),r.sessionSecret&&r.sessionSecret.length<32&&a.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,a){let{logging:r}=t;if(r.enableFile)try{ot.existsSync(r.logDirectory)||ot.mkdirSync(r.logDirectory,{recursive:!0})}catch{e.push({path:"logging.logDirectory",message:`Cannot create log directory: ${r.logDirectory}`,code:"INVALID_LOG_DIR",severity:"error",suggestion:"Ensure the directory is writable"})}r.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(r.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,a){let r=t.worker.maxConcurrentJobs,i=t.rateLimit.requestsPerMinute;r*10>i&&a.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&&a.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}=(oi(),ds(ms));return e(t).available}}});function Sl(){let n=Wa();return{port:n.server.port,nodeEnv:n.server.environment,taskShepherdApiUrl:n.taskShepherd.apiUrl,taskShepherdApiKey:n.taskShepherd.apiKey,redisUrl:n.redis.url,claudeCommandPath:n.claude.commandPath,claudeApiKey:n.claude.apiKey,claudeBaseUrl:n.claude.baseUrl,claudeModel:n.claude.model,claudeMaxRetries:n.claude.maxRetries,claudeTimeoutMs:n.claude.timeoutMs,maxConcurrentJobs:n.worker.maxConcurrentJobs,tokenRateLimit:n.rateLimit.tokenLimit,logLevel:n.server.logLevel}}var li,wl,Ot,ys=D(()=>{"use strict";ti();Fa();di();Fa();di();li=Sl(),wl=ii(),Ot={warnings:[]};if(Ot=hs(wl.getConfig()),!Ot.valid&&(console.error("Configuration validation failed:"),Ot.errors.forEach(n=>{console.error(` - ${n.path}: ${n.message}`)}),Ot.errors.some(n=>n.severity==="error")))throw new Error("Configuration contains critical errors. Please fix them before starting the service.");Ot.warnings.length>0&&(console.warn("Configuration warnings:"),Ot.warnings.forEach(n=>{console.warn(` - ${n.path}: ${n.message}`),n.suggestion&&console.warn(` Suggestion: ${n.suggestion}`)}))});var Te,p,U=D(()=>{"use strict";Te=T(require("winston"));ys();p=Te.default.createLogger({level:li.nodeEnv==="development"?"debug":"info",format:Te.default.format.combine(Te.default.format.timestamp(),Te.default.format.errors({stack:!0}),Te.default.format.json()),defaultMeta:{service:"agent"},transports:[new Te.default.transports.File({filename:"logs/error.log",level:"error",maxsize:100*1024*1024,maxFiles:5,tailable:!0}),new Te.default.transports.File({filename:"logs/combined.log",maxsize:100*1024*1024,maxFiles:5,tailable:!0})]});li.nodeEnv!=="production"&&p.add(new Te.default.transports.Console({format:Te.default.format.combine(Te.default.format.colorize(),Te.default.format.simple())}))});var Wt,ci,oe,La,ue,da=D(()=>{"use strict";Wt=require("fs"),ci=T(require("path")),oe=T(require("os")),La=T(require("crypto"));U();ue=class{constructor(t){this.configDir=t||ci.default.join(oe.default.homedir(),".task-shepherd-agent"),this.identityFile=ci.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),p.info("Using existing agent identity",{agentId:e.agentId,agentName:e.agentName,service:"identity"}),this.currentIdentity=e,e;let a=await this.generateNewIdentity(t);return t.persistent!==!1&&await this.saveIdentity(a),this.currentIdentity=a,p.info("Generated new agent identity",{agentId:a.agentId,agentName:a.agentName,strategy:t.strategy,service:"identity"}),a}async generateNewIdentity(t){let e=oe.default.hostname(),a=oe.default.platform(),r=oe.default.userInfo().username,i="production",s,o;switch(t.strategy){case"hostname":s=await this.generateHostnameBasedId(t),o=t.customName||`AI Agent (${e})`;break;case"user-configured":s=await this.generateUserConfiguredId(t),o=t.customName||`AI Agent (${s})`;break;case"machine-fingerprint":s=await this.generateMachineFingerprintId(t),o=t.customName||`AI Agent (${e})`;break;case"hybrid":s=await this.generateHybridId(t),o=t.customName||`AI Agent (${this.extractReadablePart(s)})`;break;default:throw new Error(`Unknown identity strategy: ${t.strategy}`)}return{agentId:s,agentName:o,hostname:e,platform:a,userId:r,environment:i,createdAt:new Date().toISOString(),lastUsed:new Date().toISOString(),version:process.env.npm_package_version||"1.0.0"}}async generateHostnameBasedId(t){let e=oe.default.hostname(),a=[];t.prefix&&a.push(t.prefix);let r=e.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").substring(0,20);if(a.push(r),t.includeUser){let i=oe.default.userInfo().username.toLowerCase().replace(/[^a-z0-9]/g,"").substring(0,10);a.push(i)}if(t.includeEnvironment){let i="production".substring(0,4);a.push(i)}return t.suffix&&a.push(t.suffix),a.join("-")}async generateUserConfiguredId(t){if(t.customName){let a=[t.customName.toLowerCase().replace(/[^a-z0-9-\s]/g,"").replace(/\s+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").substring(0,30)];if(t.includeEnvironment){let i="production".substring(0,4);a.push(i)}let r=La.default.createHash("md5").update(oe.default.hostname()+oe.default.userInfo().username).digest("hex").substring(0,4);return a.push(r),a.join("-")}return this.generateInteractiveId(t)}async generateMachineFingerprintId(t){let e=this.getMachineFingerprint(),a=La.default.createHash("sha256").update(e).digest("hex").substring(0,12),r=[];return t.prefix&&r.push(t.prefix),r.push("agent"),r.push(a),t.suffix&&r.push(t.suffix),r.join("-")}async generateHybridId(t){let e=oe.default.hostname(),a=oe.default.userInfo().username,r=e.toLowerCase().replace(/[^a-z0-9]/g,"").substring(0,8),i=La.default.createHash("md5").update(`${e}-${a}-${oe.default.platform()}`).digest("hex").substring(0,6),s=[];if(t.prefix&&s.push(t.prefix),s.push(r),s.push(i),t.includeEnvironment){let o="production".substring(0,3);s.push(o)}return t.suffix&&s.push(t.suffix),s.join("-")}async generateInteractiveId(t){let a=`ai-agent-${oe.default.hostname().toLowerCase().substring(0,8)}`;return p.info("Using default agent ID (interactive mode not available)",{defaultId:a,service:"identity"}),a}getMachineFingerprint(){return[oe.default.hostname(),oe.default.platform(),oe.default.arch(),oe.default.userInfo().username,JSON.stringify(Object.keys(oe.default.networkInterfaces()).sort())].join("|")}extractReadablePart(t){let e=t.split("-");return e.length>1?e[1]:t}async loadExistingIdentity(){try{let t=await Wt.promises.readFile(this.identityFile,"utf8"),e=JSON.parse(t);return e.agentId&&e.agentName&&e.createdAt?e:(p.warn("Invalid identity file format, will regenerate",{service:"identity"}),null)}catch(t){return t.code!=="ENOENT"&&p.warn("Failed to load existing identity",{error:t instanceof Error?t.message:String(t),service:"identity"}),null}}async saveIdentity(t){try{await Wt.promises.mkdir(this.configDir,{recursive:!0}),await Wt.promises.writeFile(this.identityFile,JSON.stringify(t,null,2),"utf8"),p.info("Agent identity saved",{agentId:t.agentId,configDir:this.configDir,service:"identity"})}catch(e){throw p.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,p.info("Agent identity updated",{agentId:e.agentId,updates:Object.keys(t),service:"identity"}),e}async resetIdentity(){try{await Wt.promises.unlink(this.identityFile),this.currentIdentity=void 0,p.info("Agent identity reset",{service:"identity"})}catch(t){if(t.code!=="ENOENT")throw p.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 Wt.promises.access(this.identityFile),!0}catch{return!1}}}});var ws=K((lu,kl)=>{kl.exports={name:"@task-shepherd/agent",version:"1.0.14",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","web/dist","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",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 za(){return mi||(mi=new gi),mi}var Il,ve,gi,mi,hi=D(()=>{"use strict";U();Il=ws(),ve={version:Il.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:[]},gi=class{getVersionMetadata(){return{...ve}}getVersion(){return ve.version}getBuildInfo(){return{version:ve.version,buildTimestamp:ve.buildTimestamp,commitHash:ve.commitHash,releaseChannel:ve.releaseChannel}}getCompatibilityRequirements(){return{...ve.compatibility}}getFeatureCapabilities(){return{...ve.features}}logVersionInfo(){p.info("Agent version information",{version:ve.version,buildTimestamp:ve.buildTimestamp,commitHash:ve.commitHash,releaseChannel:ve.releaseChannel,compatibilityRequirements:ve.compatibility,features:ve.features})}},mi=null});var Is={};nt(Is,{GraphQLHttpClient:()=>Ue,getGraphQLHttpClient:()=>It,initializeGraphQLHttpClient:()=>bl});function It(n){return p.debug("getGraphQLHttpClient called",{hasExistingClient:!!Me,hasOptions:!!n,optionsProvided:n?JSON.stringify(n,null,2):"none"}),Me||(p.info("Creating new HTTP client singleton via getGraphQLHttpClient"),Me=new Ue(n)),p.debug("Returning HTTP client",{clientExists:!!Me}),Me}function bl(n){return p.info("initializeGraphQLHttpClient called",{providedOptions:JSON.stringify(n,null,2),hasExistingClient:!!Me}),Me&&(p.info("Destroying existing HTTP client"),Me.destroy()),Me=new Ue(n),p.info("New HTTP client singleton created",{clientExists:!!Me}),Me}var ks,Ue,Me,jt=D(()=>{"use strict";ks=require("events");U();Fa();hi();Ue=class extends ks.EventEmitter{constructor(e={}){super();this.healthCheckTimer=null;this.isHealthy=!1;this.circuitBreakerOpen=!1;this.failureCount=0;this.lastHealthCheck=0;let a=Wa();p.info("GraphQL HTTP Client constructor called",{providedOptionsApiKey:e.apiKey?e.apiKey.substring(0,12)+"...":"none",configApiKey:a.taskShepherd.apiKey?a.taskShepherd.apiKey.substring(0,12)+"...":"none",configApiUrl:a.taskShepherd.apiUrl});let r=e.apiKey||a.taskShepherd.apiKey;r||p.error("CRITICAL: No API key available for GraphQL HTTP Client",{providedOptionsApiKey:e.apiKey?e.apiKey.substring(0,12)+"...":"none",configApiKey:a.taskShepherd.apiKey?a.taskShepherd.apiKey.substring(0,12)+"...":"none",configKeys:Object.keys(a.taskShepherd||{})});let i=a.taskShepherd.apiUrl,o={maxRetries:5,baseDelay:1e3,maxDelay:3e4,timeout:6e4,healthCheckInterval:3e4,enableCircuitBreaker:!0,baseUrl:e.baseUrl||i||"http://localhost:4002/api/graphql"};this.options={...o,...e,apiKey:e.apiKey!==void 0?e.apiKey:r},p.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 a=null;for(let r=1;r<=this.options.maxRetries;r++)try{let i=await this.executeRequest(e,r);return this.failureCount=0,this.circuitBreakerOpen&&(this.circuitBreakerOpen=!1,p.info("Circuit breaker closed - backend is healthy again"),this.emit("circuitBreakerClosed")),i}catch(i){if(a=i instanceof Error?i:new Error(String(i)),p.warn(`GraphQL request attempt ${r}/${this.options.maxRetries} failed`,{error:a.message,operationName:e.operationName,willRetry:r<this.options.maxRetries}),r<this.options.maxRetries){let s=this.calculateRetryDelay(r);await this.sleep(s)}}throw this.failureCount++,this.options.enableCircuitBreaker&&this.failureCount>=5&&!this.circuitBreakerOpen&&(this.circuitBreakerOpen=!0,p.error("Circuit breaker opened - too many backend failures"),this.emit("circuitBreakerOpened"),setTimeout(()=>{this.circuitBreakerOpen=!1,this.failureCount=0,p.info("Circuit breaker half-open - testing backend"),this.emit("circuitBreakerHalfOpen")},6e4)),a||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 r=await this.mutate({query:`
|
|
4
4
|
mutation RegisterWorkspace($input: WorkspaceRegistrationInput!) {
|
|
5
5
|
registerWorkspace(input: $input) {
|
|
6
6
|
id
|