shark-ai 0.0.1 β 0.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/dist/bin/shark.d.ts +2 -1
- package/dist/bin/shark.js +0 -1
- package/dist/bin/shark.js.map +1 -1
- package/package.json +2 -2
package/dist/bin/shark.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
export { }
|
package/dist/bin/shark.js
CHANGED
package/dist/bin/shark.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/error/crash-handler.ts","../../src/bin/shark.ts","../../src/commands/init.ts","../../src/core/workflow/workflow-manager.ts","../../src/core/workflow/shark-workflow.schema.ts","../../src/core/api/stackspot-client.ts","../../src/core/debug/file-logger.ts","../../src/core/api/sse-client.ts","../../src/core/agents/agent-response-parser.ts","../../src/core/workflow/conversation-manager.ts","../../src/core/auth/get-active-realm.ts","../../src/core/agents/business-analyst-agent.ts","../../src/core/agents/specification-agent.ts","../../src/core/agents/agent-tools.ts","../../src/commands/scan.ts","../../src/core/agents/scan-agent.ts","../../src/commands/dev.ts","../../src/core/agents/developer-agent.ts","../../src/commands/qa.ts","../../src/core/agents/qa-agent.ts"],"sourcesContent":["import fs from 'fs';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport { colors } from '../../ui/colors.js';\r\n\r\nexport class CrashHandler {\r\n private static instance: CrashHandler;\r\n private readonly logDir: string;\r\n\r\n private constructor() {\r\n this.logDir = path.join(os.homedir(), '.shark', 'logs');\r\n }\r\n\r\n public static getInstance(): CrashHandler {\r\n if (!CrashHandler.instance) {\r\n CrashHandler.instance = new CrashHandler();\r\n }\r\n return CrashHandler.instance;\r\n }\r\n\r\n public init(): void {\r\n process.on('uncaughtException', (error) => this.handleError(error, 'Uncaught Exception'));\r\n process.on('unhandledRejection', (reason) => this.handleError(reason, 'Unhandled Rejection'));\r\n }\r\n\r\n private handleError(error: any, type: string): void {\r\n // Prevent infinite loops if logging fails\r\n try {\r\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\r\n const logFile = path.join(this.logDir, `crash-${timestamp}.log`);\r\n\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n const stackTrace = error instanceof Error ? error.stack : 'No stack trace available';\r\n\r\n const logContent = `\r\n[${new Date().toISOString()}] ${type}\r\n--------------------------------------------------\r\nMessage: ${errorMessage}\r\nStack:\r\n${stackTrace}\r\n--------------------------------------------------\r\nSystem: ${os.platform()} ${os.release()} ${os.arch()}\r\nNode: ${process.version}\r\n`;\r\n\r\n // Ensure directory exists sync (we are crashing, async might not finish)\r\n if (!fs.existsSync(this.logDir)) {\r\n fs.mkdirSync(this.logDir, { recursive: true });\r\n }\r\n\r\n fs.writeFileSync(logFile, logContent, 'utf-8');\r\n\r\n console.error('\\n');\r\n console.error(colors.error('π₯ Whoops! Shark CLI crashed unexpectedly.'));\r\n console.error(colors.dim(` Details have been saved to: ${logFile}`));\r\n console.error(colors.dim(' Please report this issue so we can fix it.'));\r\n console.error(colors.error(` Error: ${errorMessage}`));\r\n console.error('\\n');\r\n\r\n } catch (filesysError) {\r\n console.error('Fatal Error: Failed to write crash log.', filesysError);\r\n console.error('Original Error:', error);\r\n } finally {\r\n process.exit(1);\r\n }\r\n }\r\n}\r\n\r\nexport const crashHandler = CrashHandler.getInstance();\r\n","#!/usr/bin/env node\r\nimport { crashHandler } from '../core/error/crash-handler.js';\r\n\r\n// Initialize Global Crash Handler\r\ncrashHandler.init();\r\n\r\nimport { Command } from 'commander';\r\nimport { loginCommand } from '../commands/login.js';\r\nimport { configCommand } from '../commands/config.js';\r\nimport { initCommand } from '../commands/init.js';\r\nimport { colors } from '../ui/colors.js';\r\nimport { interactiveBusinessAnalyst } from '../core/agents/business-analyst-agent.js';\r\nimport { interactiveSpecificationAgent } from '../core/agents/specification-agent.js';\r\nimport { scanCommand } from '../commands/scan.js';\r\nimport { devCommand } from '../commands/dev.js';\r\nimport { qaCommand } from '../commands/qa.js';\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('shark')\r\n .description('Shark CLI: AI-Native Collaborative Development Tool')\r\n .version('0.0.1');\r\n\r\nprogram.addCommand(loginCommand);\r\nprogram.addCommand(initCommand);\r\nprogram.addCommand(scanCommand);\r\nprogram.addCommand(devCommand);\r\nprogram.addCommand(qaCommand);\r\n\r\n// Command: ba\r\n// Description: Starts the Business Analyst Agent interactive session\r\nprogram\r\n .command('ba')\r\n .description('Start Business Analyst Agent interactive session')\r\n .option('--id <agent_id>', 'Override Agent ID')\r\n .action(async (options) => {\r\n try {\r\n await interactiveBusinessAnalyst();\r\n } catch (error: any) {\r\n console.error('Error:', error.message);\r\n process.exit(1);\r\n }\r\n });\r\n\r\n// Command: spec\r\n// Description: Starts the Specification Agent session\r\nprogram\r\n .command('spec')\r\n .description('Start Specification Agent interactive session')\r\n .option('--id <agent_id>', 'Override Agent ID')\r\n .option('--briefing <path>', 'Path to briefing file')\r\n .action(async (options) => {\r\n try {\r\n await interactiveSpecificationAgent({\r\n agentId: options.id,\r\n briefingPath: options.briefing\r\n });\r\n } catch (error: any) {\r\n console.error('Error:', error.message);\r\n process.exit(1);\r\n }\r\n });\r\n\r\nprogram\r\n .command('config')\r\n .description('Manage global configuration')\r\n .action(configCommand.action);\r\n\r\n// Global Error Handler for the CLI\r\nprocess.on('unhandledRejection', (err) => {\r\n console.error(colors.error('β Unhandled Error:'), err);\r\n process.exit(1);\r\n});\r\n\r\nprogram.parse(process.argv);\r\n","import { Command } from 'commander';\r\nimport { tui } from '../ui/tui.js';\r\nimport { workflowManager } from '../core/workflow/workflow-manager.js';\r\nimport { TechStackEnum } from '../core/workflow/shark-workflow.schema.js';\r\nimport { randomUUID } from 'crypto';\r\nimport { colors } from '../ui/colors.js';\r\n\r\nexport const initAction = async () => {\r\n tui.intro('Shark Project Initialization');\r\n\r\n // 1. Check if workflow already exists\r\n const existingState = await workflowManager.load();\r\n if (existingState) {\r\n // Smart Resume Context Card\r\n tui.log.info(colors.dim('----------------------------------------'));\r\n tui.log.info(`π¦ ${colors.primary('Welcome back to Shark CLI!')}`);\r\n tui.log.message(` Project: ${colors.white(existingState.projectName)}`);\r\n tui.log.message(` Stage: ${colors.secondary(existingState.currentStage)}`);\r\n tui.log.message(` Updated: ${colors.dim(new Date(existingState.lastUpdated).toLocaleString())}`);\r\n tui.log.info(colors.dim('----------------------------------------'));\r\n\r\n const action = await tui.select({\r\n message: 'An existing project was detected. What would you like to do?',\r\n options: [\r\n { value: 'resume', label: 'π Resume Work' },\r\n { value: 'overwrite', label: 'β οΈ Overwrite (Start Fresh)' },\r\n { value: 'exit', label: 'β Exit' }\r\n ]\r\n });\r\n\r\n if (tui.isCancel(action) || action === 'exit') {\r\n tui.outro('See you later! π');\r\n return;\r\n }\r\n\r\n if (action === 'resume') {\r\n tui.log.success(`Resuming work on ${colors.primary(existingState.projectName)}...`);\r\n // Future: Route to specific agent based on stage\r\n tui.outro(`To continue, run: \"shark agent\" (Context loaded)`);\r\n return;\r\n }\r\n\r\n // If overwrite, we just proceed to step 2...\r\n }\r\n\r\n // 2. Prompt for Project Name\r\n const projectName = await tui.text({\r\n message: 'What is the name of your project?',\r\n placeholder: 'e.g. My Awesome App',\r\n validate: (value) => {\r\n if (!value) return 'Project name is required';\r\n if (value.trim().length < 2) return 'Project name must be at least 2 characters';\r\n }\r\n });\r\n\r\n if (tui.isCancel(projectName)) {\r\n tui.outro('Initialization cancelled.');\r\n return;\r\n }\r\n\r\n // 3. Prompt for Tech Stack\r\n const techStackOptions = TechStackEnum.options.map(stack => ({\r\n value: stack,\r\n label: stack === 'node-ts' ? 'Node.js (TypeScript)' :\r\n stack === 'nextjs' ? 'Next.js' :\r\n stack.charAt(0).toUpperCase() + stack.slice(1)\r\n }));\r\n\r\n const techStack = await tui.select({\r\n message: 'Select your technology stack:',\r\n options: techStackOptions\r\n });\r\n\r\n if (tui.isCancel(techStack)) {\r\n tui.outro('Initialization cancelled.');\r\n return;\r\n }\r\n\r\n // 4. Create and Save State\r\n const spinner = tui.spinner();\r\n spinner.start('Initializing project workflow...');\r\n\r\n try {\r\n const newState = {\r\n projectId: randomUUID(),\r\n projectName: projectName as string,\r\n techStack: techStack as any,\r\n currentStage: 'business_analysis' as const,\r\n stageStatus: 'pending' as const,\r\n lastUpdated: new Date().toISOString(),\r\n artifacts: [],\r\n metadata: {\r\n initializedBy: 'shark-cli',\r\n version: '0.0.1'\r\n }\r\n };\r\n\r\n await workflowManager.save(newState);\r\n spinner.stop('Project workflow created!');\r\n\r\n tui.log.success(`Project ${colors.primary(projectName as string)} initialized successfully.`);\r\n tui.log.message(`Your Project ID: ${colors.dim(newState.projectId)}`);\r\n tui.outro('Ready to start! Run \"shark agent\" to begin analyzing requirements.'); // Placeholder hint\r\n } catch (error: any) {\r\n spinner.stop('Initialization failed.', 1);\r\n tui.log.error(error.message);\r\n process.exit(1);\r\n }\r\n};\r\n\r\nexport const initCommand = new Command('init')\r\n .description('Initialize a new Shark project')\r\n .action(initAction);\r\n","import fs from 'fs/promises';\r\nimport path from 'path';\r\nimport { WorkflowSchema, type WorkflowState } from './shark-workflow.schema.js';\r\nimport { colors } from '../../ui/colors.js';\r\n\r\nexport class WorkflowManager {\r\n private static instance: WorkflowManager;\r\n private readonly filename = 'shark-workflow.json';\r\n private readonly tmpFilename = '.shark-workflow.tmp';\r\n\r\n private constructor() { }\r\n\r\n public static getInstance(): WorkflowManager {\r\n if (!WorkflowManager.instance) {\r\n WorkflowManager.instance = new WorkflowManager();\r\n }\r\n return WorkflowManager.instance;\r\n }\r\n\r\n private getFilePath(): string {\r\n return path.join(process.cwd(), this.filename);\r\n }\r\n\r\n private getTmpFilePath(): string {\r\n return path.join(process.cwd(), this.tmpFilename);\r\n }\r\n\r\n public async save(state: WorkflowState): Promise<void> {\r\n // 1. Validate State\r\n const parsed = WorkflowSchema.safeParse(state);\r\n if (!parsed.success) {\r\n throw new Error(`Invalid workflow state: ${parsed.error.message}`);\r\n }\r\n\r\n const filePath = this.getFilePath();\r\n const tmpPath = this.getTmpFilePath();\r\n const data = JSON.stringify(parsed.data, null, 2);\r\n\r\n try {\r\n // 2. Write to TMP\r\n await fs.writeFile(tmpPath, data, 'utf-8');\r\n\r\n // 3. Rename TMP to Final (Atomic)\r\n await fs.rename(tmpPath, filePath);\r\n } catch (error: any) {\r\n throw new Error(`Failed to save workflow state atomically: ${error.message}`);\r\n }\r\n }\r\n\r\n public async load(): Promise<WorkflowState | null> {\r\n const filePath = this.getFilePath();\r\n\r\n try {\r\n // Check if file exists\r\n try {\r\n await fs.access(filePath);\r\n } catch {\r\n return null; // File doesn't exist, generic start\r\n }\r\n\r\n const content = await fs.readFile(filePath, 'utf-8');\r\n const json = JSON.parse(content);\r\n\r\n const parsed = WorkflowSchema.safeParse(json);\r\n if (parsed.success) {\r\n return parsed.data;\r\n } else {\r\n console.warn(colors.warning(`β οΈ Corrupted workflow file detected: ${parsed.error.message}`));\r\n return null;\r\n }\r\n\r\n } catch (error: any) {\r\n console.warn(colors.warning(`β οΈ Failed to load workflow state: ${error.message}`));\r\n return null;\r\n }\r\n }\r\n\r\n // Helper to get current state or default if none exists\r\n public async getOrInitState(): Promise<WorkflowState | null> {\r\n return await this.load();\r\n }\r\n}\r\n\r\nexport const workflowManager = WorkflowManager.getInstance();\r\n","import { z } from 'zod';\r\n\r\nexport enum ProjectParams {\r\n PROJECT_ID = 'projectId',\r\n PROJECT_NAME = 'projectName',\r\n TECH_STACK = 'techStack',\r\n}\r\n\r\nexport const TechStackEnum = z.enum([\r\n 'react',\r\n 'nextjs',\r\n 'angular',\r\n 'vue',\r\n 'node-ts',\r\n 'python',\r\n 'dotnet',\r\n 'java',\r\n 'unknown'\r\n]);\r\n\r\nexport type TechStack = z.infer<typeof TechStackEnum>;\r\n\r\nexport const WorkflowStageEnum = z.enum([\r\n 'business_analysis',\r\n 'specification',\r\n 'architecture',\r\n 'development',\r\n 'verification',\r\n 'deployment'\r\n]);\r\n\r\nexport type WorkflowStage = z.infer<typeof WorkflowStageEnum>;\r\n\r\nexport const StageStatusEnum = z.enum([\r\n 'pending',\r\n 'in_progress',\r\n 'completed',\r\n 'failed',\r\n 'skipped'\r\n]);\r\n\r\nexport type StageStatus = z.infer<typeof StageStatusEnum>;\r\n\r\nexport const WorkflowSchema = z.object({\r\n projectId: z.string().uuid(),\r\n projectName: z.string().min(1),\r\n techStack: TechStackEnum.default('unknown'),\r\n currentStage: WorkflowStageEnum.default('business_analysis'),\r\n stageStatus: StageStatusEnum.default('pending'),\r\n lastUpdated: z.string().datetime(), // ISO 8601\r\n conversationId: z.string().optional(),\r\n conversations: z.record(z.string(), z.string()).optional(), // agentType -> conversationId\r\n artifacts: z.array(z.string()).default([]),\r\n // Extensible metadata bag\r\n metadata: z.record(z.unknown()).optional(),\r\n});\r\n\r\nexport type WorkflowState = z.infer<typeof WorkflowSchema>;\r\n","import { tokenStorage } from '../auth/token-storage.js';\r\n\r\nexport class AuthError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = 'AuthError';\r\n }\r\n}\r\n\r\ninterface RequestOptions extends RequestInit {\r\n params?: Record<string, string>;\r\n}\r\n\r\n// API Base URLs\r\nexport const STACKSPOT_API_BASE = 'https://api.stackspot.com';\r\nexport const STACKSPOT_AGENT_API_BASE = 'https://genai-inference-app.stackspot.com';\r\n\r\nexport class StackSpotClient {\r\n private readonly MAX_RETRIES = 3;\r\n private readonly RETRY_DELAYS = [1000, 2000, 4000]; // 1s, 2s, 4s\r\n private debugMode = false;\r\n\r\n constructor(private realm: string) { }\r\n\r\n public enableDebug(): void {\r\n this.debugMode = true;\r\n }\r\n\r\n private async getHeaders(): Promise<Headers> {\r\n const token = await tokenStorage.getToken(this.realm);\r\n\r\n if (!token) {\r\n throw new AuthError(`Authentication required for realm '${this.realm}'.\\nPlease run 'shark login' to authenticate.`);\r\n }\r\n\r\n const headers = new Headers();\r\n headers.set('Authorization', `Bearer ${token}`);\r\n headers.set('Content-Type', 'application/json');\r\n return headers;\r\n }\r\n\r\n private shouldRetry(error: any, attempt: number): boolean {\r\n if (attempt >= this.MAX_RETRIES) return false;\r\n\r\n // Retry on network errors\r\n if (error.name === 'TypeError' || error.message?.includes('fetch')) return true;\r\n\r\n // Retry on 5xx server errors\r\n if (error.status && error.status >= 500) return true;\r\n\r\n return false;\r\n }\r\n\r\n private async sleep(ms: number): Promise<void> {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n }\r\n\r\n private async request<T>(url: string, options: RequestOptions = {}): Promise<T> {\r\n let lastError: any;\r\n\r\n for (let attempt = 0; attempt <= this.MAX_RETRIES; attempt++) {\r\n try {\r\n if (this.debugMode && attempt > 0) {\r\n console.log(`[StackSpotClient] Retry attempt ${attempt}/${this.MAX_RETRIES} for ${url}`);\r\n }\r\n\r\n const headers = await this.getHeaders();\r\n\r\n // Merge custom headers\r\n if (options.headers) {\r\n new Headers(options.headers).forEach((value, key) => headers.set(key, value));\r\n }\r\n\r\n // Add Query Params\r\n let finalUrl = url;\r\n if (options.params) {\r\n const query = new URLSearchParams(options.params).toString();\r\n finalUrl += `?${query}`;\r\n }\r\n\r\n if (this.debugMode) {\r\n console.log(`[StackSpotClient] ${options.method || 'GET'} ${finalUrl}`);\r\n }\r\n\r\n const response = await fetch(finalUrl, {\r\n ...options,\r\n headers,\r\n });\r\n\r\n if (response.status === 401) {\r\n throw new AuthError(\"Session expired or invalid credentials. Please run 'shark login' again.\");\r\n }\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n const error: any = new Error(`API Request failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n error.status = response.status;\r\n throw error;\r\n }\r\n\r\n // Return null for 204 No Content\r\n if (response.status === 204) {\r\n return null as T;\r\n }\r\n\r\n return (await response.json()) as T;\r\n\r\n } catch (error: any) {\r\n lastError = error;\r\n\r\n // Don't retry auth errors\r\n if (error instanceof AuthError) {\r\n throw error;\r\n }\r\n\r\n if (this.shouldRetry(error, attempt)) {\r\n const delay = this.RETRY_DELAYS[attempt] || this.RETRY_DELAYS[this.RETRY_DELAYS.length - 1];\r\n if (this.debugMode) {\r\n console.log(`[StackSpotClient] Retrying in ${delay}ms...`);\r\n }\r\n await this.sleep(delay);\r\n continue;\r\n }\r\n\r\n // No more retries\r\n throw error;\r\n }\r\n }\r\n\r\n throw lastError;\r\n }\r\n\r\n async get<T>(url: string, options?: RequestOptions): Promise<T> {\r\n return this.request<T>(url, { ...options, method: 'GET' });\r\n }\r\n\r\n async post<T>(url: string, body: any, options?: RequestOptions): Promise<T> {\r\n return this.request<T>(url, {\r\n ...options,\r\n method: 'POST',\r\n body: JSON.stringify(body)\r\n });\r\n }\r\n\r\n async put<T>(url: string, body: any, options?: RequestOptions): Promise<T> {\r\n return this.request<T>(url, {\r\n ...options,\r\n method: 'PUT',\r\n body: JSON.stringify(body)\r\n });\r\n }\r\n\r\n async delete<T>(url: string, options?: RequestOptions): Promise<T> {\r\n return this.request<T>(url, { ...options, method: 'DELETE' });\r\n }\r\n}\r\n\r\nexport function createAuthenticatedClient(realm: string): StackSpotClient {\r\n return new StackSpotClient(realm);\r\n}\r\n","import fs from 'node:fs';\r\nimport path from 'node:path';\r\n\r\nexport class FileLogger {\r\n private static logPath = path.resolve(process.cwd(), 'shark-debug.log');\r\n private static enabled = true; // Enabled by default for this debugging session\r\n\r\n static init() {\r\n try {\r\n fs.writeFileSync(this.logPath, `--- Shark CLI Debug Log Started at ${new Date().toISOString()} ---\\n`);\r\n } catch (e) {\r\n console.error('Failed to initialize debug log:', e);\r\n }\r\n }\r\n\r\n static log(category: string, message: string, data?: any) {\r\n if (!this.enabled) return;\r\n\r\n try {\r\n const timestamp = new Date().toISOString();\r\n let logEntry = `[${timestamp}] [${category.toUpperCase()}] ${message}\\n`;\r\n if (data !== undefined) {\r\n if (typeof data === 'object') {\r\n logEntry += JSON.stringify(data, null, 2) + '\\n';\r\n } else {\r\n logEntry += String(data) + '\\n';\r\n }\r\n }\r\n logEntry += '-'.repeat(40) + '\\n';\r\n\r\n fs.appendFileSync(this.logPath, logEntry);\r\n } catch (e) {\r\n // calculated risk: silence logging errors to not break app\r\n }\r\n }\r\n}\r\n","import { FileLogger } from '../debug/file-logger.js';\r\n\r\nexport interface SSECallbacks {\r\n onChunk?: (partialMessage: string) => void;\r\n onComplete?: (fullMessage: string, metadata?: any) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\nexport class SSEClient {\r\n /**\r\n * Streams agent response using Server-Sent Events.\r\n * \r\n * @param url - The SSE endpoint URL\r\n * @param requestPayload - The request payload to POST\r\n * @param headers - Request headers (including Authorization)\r\n * @param callbacks - Event callbacks for chunks, completion, and errors\r\n */\r\n async streamAgentResponse(\r\n url: string,\r\n requestPayload: unknown,\r\n headers: HeadersInit,\r\n callbacks: SSECallbacks = {}\r\n ): Promise<void> {\r\n const { onChunk, onComplete, onError } = callbacks;\r\n\r\n FileLogger.log('SSE', `Starting Request to ${url}`, {\r\n headers,\r\n payload: requestPayload\r\n });\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n ...headers,\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(requestPayload),\r\n });\r\n\r\n FileLogger.log('SSE', `Response Status: ${response.status} ${response.statusText}`);\r\n\r\n const responseHeaders: Record<string, string> = {};\r\n response.headers.forEach((value, key) => { responseHeaders[key] = value; });\r\n FileLogger.log('SSE', 'Response Headers', responseHeaders);\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n FileLogger.log('SSE', 'Response Error Body', errorText);\r\n throw new Error(`SSE request failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n if (!response.body) {\r\n throw new Error('Response body is null');\r\n }\r\n\r\n const reader = response.body.getReader();\r\n const decoder = new TextDecoder();\r\n let buffer = '';\r\n let fullMessage = '';\r\n let metadata: any = {};\r\n\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n\r\n if (done) {\r\n break;\r\n }\r\n\r\n // Decode chunk\r\n buffer += decoder.decode(value, { stream: true });\r\n\r\n // Process complete lines\r\n const lines = buffer.split('\\n');\r\n buffer = lines.pop() || ''; // Keep incomplete line in buffer\r\n\r\n for (const line of lines) {\r\n if (line.startsWith('data:')) {\r\n const data = line.slice(5).trim(); // Remove 'data:' prefix\r\n\r\n if (data === '[DONE]') {\r\n FileLogger.log('SSE', 'Stream Complete [DONE]', { fullMessage, metadata });\r\n // End of stream\r\n if (onComplete) {\r\n onComplete(fullMessage, metadata);\r\n }\r\n return;\r\n }\r\n\r\n try {\r\n const parsed = JSON.parse(data);\r\n const chunk = parsed.message || parsed.content || data;\r\n fullMessage += chunk;\r\n\r\n // Capture latest metadata (e.g. conversation_id)\r\n if (parsed.conversation_id) {\r\n metadata.conversation_id = parsed.conversation_id;\r\n }\r\n\r\n if (onChunk) {\r\n onChunk(chunk);\r\n }\r\n } catch (parseError) {\r\n // Not JSON, treat as plain text\r\n fullMessage += data;\r\n if (onChunk) {\r\n onChunk(data);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n FileLogger.log('SSE', 'Stream Ended Naturally', { fullMessage, metadata });\r\n\r\n // Stream ended without [DONE]\r\n if (onComplete) {\r\n onComplete(fullMessage, metadata);\r\n }\r\n\r\n } catch (error) {\r\n FileLogger.log('SSE', 'Stream Error', error);\r\n if (onError) {\r\n onError(error instanceof Error ? error : new Error(String(error)));\r\n } else {\r\n throw error;\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport const sseClient = new SSEClient();\r\n","import { z } from 'zod';\r\nimport { FileLogger } from '../debug/file-logger';\r\n\r\n// Action Schema\r\nexport const AgentActionSchema = z.object({\r\n type: z.enum(['create_file', 'modify_file', 'delete_file', 'talk_with_user', 'list_files', 'read_file', 'search_file', 'run_command', 'use_mcp_tool']),\r\n path: z.string().nullable().optional(), // Nullable for strict mode combatibility\r\n content: z.string().nullable().optional(),\r\n target_content: z.string().nullable().optional(),\r\n command: z.string().nullable().optional(),\r\n tool_name: z.string().nullable().optional(),\r\n tool_args: z.string().nullable().optional(), // JSON string argument\r\n});\r\n\r\nexport type AgentAction = z.infer<typeof AgentActionSchema>;\r\n\r\n// Command Schema (for future use)\r\nexport const AgentCommandSchema = z.object({\r\n command: z.string(),\r\n description: z.string(),\r\n critical: z.boolean(),\r\n});\r\n\r\n// Full Structured Response Schema\r\nexport const AgentResponseSchema = z.object({\r\n actions: z.array(AgentActionSchema),\r\n commands: z.array(AgentCommandSchema).optional(),\r\n summary: z.string().optional(),\r\n\r\n // Legacy fields handling for smooth transition/fallback\r\n message: z.string().optional(),\r\n conversation_id: z.string().optional(),\r\n});\r\n\r\nexport type AgentResponse = z.infer<typeof AgentResponseSchema>;\r\n\r\n/**\r\n * Parses raw agent response expecting a JSON string that matches our schema.\r\n */\r\nexport function parseAgentResponse(rawResponse: unknown): AgentResponse {\r\n FileLogger.log('PARSER', 'Parsing Agent Response', { rawType: typeof rawResponse });\r\n\r\n let parsedObj: any = {};\r\n let conversation_id: string | undefined;\r\n\r\n // 1. Handle string input (accumulated SSE or raw JSON string)\r\n if (typeof rawResponse === 'string') {\r\n FileLogger.log('PARSER', 'Type String', { length: rawResponse.length });\r\n try {\r\n parsedObj = extractFirstJson(rawResponse);\r\n } catch (e) {\r\n FileLogger.log('PARSER', 'String Parse Failed', { error: (e as Error).message });\r\n // Fallback: treat as simple message if not valid JSON\r\n return {\r\n actions: [{\r\n type: 'talk_with_user',\r\n content: rawResponse,\r\n path: ''\r\n }],\r\n message: rawResponse\r\n };\r\n }\r\n }\r\n // 2. Handle object input (direct API response)\r\n else if (typeof rawResponse === 'object' && rawResponse !== null) {\r\n const anyResp = rawResponse as any;\r\n conversation_id = anyResp.conversation_id;\r\n\r\n FileLogger.log('PARSER', 'Type Object', {\r\n hasContent: !!anyResp.content,\r\n hasMessage: !!anyResp.message,\r\n messageType: typeof anyResp.message\r\n });\r\n\r\n // Sometimes content is nested in 'content' or 'message'\r\n const stringContent = anyResp.content || anyResp.message;\r\n if (stringContent && typeof stringContent === 'string') {\r\n try {\r\n // Try to parse it as JSON actions\r\n const parsedInside = extractFirstJson(stringContent);\r\n // Only use it if it looks like an object (not just a primitive)\r\n if (typeof parsedInside === 'object' && parsedInside !== null) {\r\n parsedObj = parsedInside;\r\n FileLogger.log('PARSER', 'Inner JSON Parsed', { keys: Object.keys(parsedObj) });\r\n } else {\r\n // It was a string literal or number, treat as text\r\n parsedObj = rawResponse;\r\n FileLogger.log('PARSER', 'Inner JSON was primitive');\r\n }\r\n } catch (e) {\r\n // Not JSON, continue with rawResponse\r\n parsedObj = rawResponse;\r\n FileLogger.log('PARSER', 'Inner JSON Parse Error - treating as raw', { error: (e as Error).message });\r\n }\r\n } else {\r\n parsedObj = rawResponse;\r\n }\r\n\r\n // If we didn't successfully parse inner JSON actions, use the raw object\r\n if (!parsedObj.actions) {\r\n parsedObj = rawResponse;\r\n }\r\n }\r\n\r\n // 3. Normalize Actions\r\n // Ensure 'actions' array exists\r\n if (!parsedObj.actions) {\r\n FileLogger.log('PARSER', 'No Actions Found - Constructing Default');\r\n // If it looks like the legacy format or direct message\r\n return {\r\n conversation_id,\r\n actions: [{\r\n type: 'talk_with_user',\r\n content: parsedObj.message || JSON.stringify(parsedObj),\r\n path: ''\r\n }],\r\n message: parsedObj.message\r\n };\r\n }\r\n\r\n // 4. Validate against Schema\r\n // We construct the final object to match our schema structure\r\n const result = {\r\n actions: parsedObj.actions,\r\n commands: parsedObj.commands || [],\r\n summary: parsedObj.summary || '',\r\n conversation_id,\r\n message: parsedObj.summary || 'Agent Action' // Backward compatibility\r\n };\r\n\r\n\r\n FileLogger.log('PARSER', 'Final Result Constructed', { actionCount: result.actions.length });\r\n\r\n try {\r\n return AgentResponseSchema.parse(result);\r\n } catch (e) {\r\n FileLogger.log('PARSER', 'Schema Validation Failed', { error: (e as Error).message });\r\n throw e;\r\n }\r\n}\r\n\r\nfunction extractFirstJson(str: string): any {\r\n try {\r\n return JSON.parse(str);\r\n } catch (e) {\r\n // If simple parse fails, try to find the first balanced object\r\n const firstOpen = str.indexOf('{');\r\n if (firstOpen === -1) throw e;\r\n\r\n let balance = 0;\r\n let inString = false;\r\n let escape = false;\r\n\r\n for (let i = firstOpen; i < str.length; i++) {\r\n const char = str[i];\r\n\r\n if (escape) {\r\n escape = false;\r\n continue;\r\n }\r\n\r\n if (char === '\\\\') {\r\n escape = true;\r\n continue;\r\n }\r\n\r\n if (char === '\"') {\r\n inString = !inString;\r\n continue;\r\n }\r\n\r\n if (!inString) {\r\n if (char === '{') balance++;\r\n else if (char === '}') {\r\n balance--;\r\n if (balance === 0) {\r\n // Found the end of the first object\r\n const potentialJson = str.substring(firstOpen, i + 1);\r\n try {\r\n return JSON.parse(potentialJson);\r\n } catch (innerE) {\r\n // If this chunk failed, maybe our brace counting was off (e.g. comments?), throw original\r\n throw e;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n throw e;\r\n }\r\n}\r\n","import { workflowManager } from './workflow-manager.js';\r\n\r\n/**\r\n * Manages conversation IDs for agent interactions.\r\n * Stores conversation IDs in the workflow state to maintain context across sessions.\r\n */\r\nexport class ConversationManager {\r\n private static instance: ConversationManager;\r\n\r\n private constructor() { }\r\n\r\n public static getInstance(): ConversationManager {\r\n if (!ConversationManager.instance) {\r\n ConversationManager.instance = new ConversationManager();\r\n }\r\n return ConversationManager.instance;\r\n }\r\n\r\n /**\r\n * Saves a conversation ID for a specific agent type.\r\n * \r\n * @param agentType - The type of agent (e.g., 'business_analyst', 'architect')\r\n * @param conversationId - The conversation ID from the agent response\r\n */\r\n async saveConversationId(agentType: string, conversationId: string): Promise<void> {\r\n const state = await workflowManager.load();\r\n if (!state) {\r\n throw new Error('No workflow state found. Please run \"shark init\" first.');\r\n }\r\n\r\n // Initialize conversations object if it doesn't exist\r\n if (!state.conversations) {\r\n state.conversations = {};\r\n }\r\n\r\n state.conversations[agentType] = conversationId;\r\n await workflowManager.save(state);\r\n }\r\n\r\n /**\r\n * Retrieves the conversation ID for a specific agent type.\r\n * \r\n * @param agentType - The type of agent\r\n * @returns The conversation ID, or undefined if none exists\r\n */\r\n async getConversationId(agentType: string): Promise<string | undefined> {\r\n const state = await workflowManager.load();\r\n if (!state || !state.conversations) {\r\n return undefined;\r\n }\r\n\r\n return state.conversations[agentType];\r\n }\r\n\r\n /**\r\n * Clears the conversation ID for a specific agent type.\r\n * \r\n * @param agentType - The type of agent\r\n */\r\n async clearConversationId(agentType: string): Promise<void> {\r\n const state = await workflowManager.load();\r\n if (!state || !state.conversations) {\r\n return;\r\n }\r\n\r\n delete state.conversations[agentType];\r\n await workflowManager.save(state);\r\n }\r\n\r\n /**\r\n * Clears all conversation IDs.\r\n * Useful when transitioning to a new project or resetting state.\r\n */\r\n async clearAllConversations(): Promise<void> {\r\n const state = await workflowManager.load();\r\n if (!state) {\r\n return;\r\n }\r\n\r\n state.conversations = {};\r\n await workflowManager.save(state);\r\n }\r\n}\r\n\r\nexport const conversationManager = ConversationManager.getInstance();\r\n","import { ConfigManager } from '../config-manager.js';\r\n\r\n/**\r\n * Gets the currently active (logged-in) realm from config.\r\n * \r\n * @returns The active realm\r\n * @throws Error if no realm is active (user not logged in)\r\n */\r\nexport async function getActiveRealm(): Promise<string> {\r\n const configManager = ConfigManager.getInstance();\r\n const config = configManager.getConfig();\r\n const realm = config.activeRealm;\r\n\r\n if (!realm) {\r\n throw new Error(\r\n 'No active authentication found.\\n' +\r\n 'Please run \"shark login\" first to authenticate.'\r\n );\r\n }\r\n\r\n return realm;\r\n}\r\n","import { STACKSPOT_AGENT_API_BASE } from '../api/stackspot-client.js';\r\nimport { sseClient } from '../api/sse-client.js';\r\nimport { parseAgentResponse, AgentResponse } from './agent-response-parser.js';\r\nimport { conversationManager } from '../workflow/conversation-manager.js';\r\nimport { tokenStorage } from '../auth/token-storage.js';\r\nimport { getActiveRealm } from '../auth/get-active-realm.js';\r\nimport { tui } from '../../ui/tui.js';\r\nimport { colors } from '../../ui/colors.js';\r\n\r\nconst AGENT_TYPE = 'business_analyst';\r\n\r\n// TODO: Get this from config or environment variable\r\n// You get this ID when you create your custom agent in StackSpot Portal\r\nconst AGENT_ID = process.env.STACKSPOT_BA_AGENT_ID || '01KEJ95G304TNNAKGH5XNEEBVD';\r\n\r\nexport interface BAAgentOptions {\r\n agentId?: string; // Allow overriding agent ID\r\n onChunk?: (chunk: string) => void;\r\n onComplete?: (response: AgentResponse) => void;\r\n}\r\n\r\n/**\r\n * Orchestrates interaction with the Business Analyst agent.\r\n * Integrates all communication components into a complete flow.\r\n * Automatically uses the active realm from config (no need to pass it).\r\n * \r\n * @param prompt - User's project description\r\n * @param options - Configuration options (callbacks, optional agentId override)\r\n * @returns Complete agent response\r\n */\r\nexport async function runBusinessAnalystAgent(\r\n prompt: string,\r\n options: BAAgentOptions = {}\r\n): Promise<AgentResponse> {\r\n const { agentId, onChunk, onComplete } = options;\r\n\r\n // 1. Get active realm from config (auto-detect)\r\n const realm = await getActiveRealm();\r\n\r\n // 1. Get auth token\r\n const token = await tokenStorage.getToken(realm);\r\n if (!token) {\r\n throw new Error(`No authentication token found for realm '${realm}'. Please run 'shark login'.`);\r\n }\r\n\r\n // 2. Load existing conversation ID (if any)\r\n const existingConversationId = await conversationManager.getConversationId(AGENT_TYPE);\r\n\r\n // 3. Build request payload (StackSpot agent format)\r\n const requestPayload = {\r\n user_prompt: prompt,\r\n streaming: true,\r\n stackspot_knowledge: false, // Use agent's configured KS instead\r\n return_ks_in_response: true,\r\n deep_search_ks: false,\r\n conversation_id: existingConversationId,\r\n };\r\n\r\n // 4. Construct agent URL - CORRECT FORMAT\r\n const finalAgentId = agentId || AGENT_ID;\r\n const agentUrl = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${finalAgentId}/chat`;\r\n\r\n // 5. Prepare headers\r\n const headers = {\r\n 'Authorization': `Bearer ${token}`,\r\n 'Content-Type': 'application/json',\r\n };\r\n\r\n // 6. Stream agent response\r\n let fullMessage = '';\r\n let rawResponse: any = {};\r\n\r\n await sseClient.streamAgentResponse(\r\n agentUrl,\r\n requestPayload,\r\n headers,\r\n {\r\n onChunk: (chunk) => {\r\n fullMessage += chunk;\r\n if (onChunk) {\r\n onChunk(chunk);\r\n }\r\n },\r\n onComplete: async (message) => {\r\n // Build complete response object\r\n rawResponse = {\r\n message: message || fullMessage,\r\n conversation_id: existingConversationId, // Will be updated if new one provided\r\n };\r\n },\r\n onError: (error) => {\r\n throw error;\r\n },\r\n }\r\n );\r\n\r\n // 7. Parse response\r\n const parsedResponse = parseAgentResponse(rawResponse);\r\n\r\n // 8. Save new conversation ID (if provided)\r\n if (parsedResponse.conversation_id) {\r\n await conversationManager.saveConversationId(AGENT_TYPE, parsedResponse.conversation_id);\r\n }\r\n\r\n // 9. Call completion callback\r\n if (onComplete) {\r\n onComplete(parsedResponse);\r\n }\r\n\r\n return parsedResponse;\r\n}\r\n\r\n/**\r\n * Interactive Business Analyst session with TUI.\r\n * Prompts user for input and displays streamed response.\r\n * Automatically uses the active realm from config.\r\n */\r\nexport async function interactiveBusinessAnalyst(): Promise<void> {\r\n tui.intro('π― Business Analyst Agent');\r\n\r\n const prompt = await tui.text({\r\n message: 'Describe your project idea',\r\n placeholder: 'E.g., I want to build a task management app for teams...',\r\n validate: (value) => {\r\n if (!value || value.length < 10) return 'Please provide a detailed description (at least 10 characters)';\r\n },\r\n });\r\n\r\n if (tui.isCancel(prompt)) {\r\n tui.outro('Cancelled');\r\n return;\r\n }\r\n\r\n const spinner = tui.spinner();\r\n spinner.start('π¬ Business Analyst is thinking...');\r\n\r\n let responseText = '';\r\n\r\n try {\r\n await runBusinessAnalystAgent(prompt as string, {\r\n onChunk: (chunk) => {\r\n responseText += chunk;\r\n // Update spinner with preview (try to parse JSON if possible, otherwise raw)\r\n try {\r\n // Start of JSON?\r\n if (responseText.trim().startsWith('{')) {\r\n spinner.message(colors.dim('Receiving structured data...'));\r\n } else {\r\n spinner.message(colors.dim('Thinking...'));\r\n }\r\n } catch (e) {\r\n // ignore\r\n }\r\n },\r\n onComplete: async (response) => {\r\n spinner.stop('Response received');\r\n\r\n // Show summary if exists\r\n if (response.summary) {\r\n tui.log.info(colors.italic(response.summary));\r\n }\r\n\r\n // Handle Actions\r\n if (response.actions && response.actions.length > 0) {\r\n for (const action of response.actions) {\r\n\r\n // CASE 1: TALK WITH USER (Conventional Message)\r\n if (action.type === 'talk_with_user') {\r\n tui.log.info(colors.green('π€ BA Agent:'));\r\n console.log(action.content); // Print formatted markdown\r\n\r\n // We don't verify \"talk\", we just show it.\r\n // The flow will wait for next user input naturally at loop start?\r\n // Wait! We need a loop here?\r\n // runBusinessAnalystAgent is a ONE-OFF request.\r\n // The LOOP needs to be in interactiveBusinessAnalyst.\r\n }\r\n\r\n // CASE 2: FILE OPERATIONS (Autonomous Actions)\r\n else {\r\n tui.log.warning(`\\nπ€ Agent wants to ${action.type}: ${colors.bold(action.path || 'unknown')}`);\r\n\r\n // Show content preview\r\n if (action.content) {\r\n console.log(colors.dim('--- Content Preview ---'));\r\n console.log(action.content.substring(0, 300) + (action.content.length > 300 ? '...' : ''));\r\n console.log(colors.dim('-----------------------'));\r\n }\r\n\r\n const confirm = await tui.confirm({\r\n message: `Allow agent to ${action.type} '${action.path}'?`,\r\n active: 'Yes',\r\n inactive: 'No'\r\n });\r\n\r\n if (confirm) {\r\n // TODO: Add actual file system writing logic here\r\n // fs.writeFileSync(action.path!, action.content);\r\n tui.log.success(`β
Action executed: ${action.path} created.`);\r\n } else {\r\n tui.log.error('β Action denied.');\r\n }\r\n }\r\n }\r\n }\r\n if (response.tokens) {\r\n tui.log.info(`Tokens used: ${response.tokens.output || 0}`);\r\n }\r\n },\r\n });\r\n\r\n tui.outro('Session complete');\r\n } catch (error: any) {\r\n spinner.stop('β Error', 1);\r\n tui.log.error(error.message);\r\n throw error;\r\n }\r\n}\r\n","\r\nimport { STACKSPOT_AGENT_API_BASE } from '../api/stackspot-client.js';\r\nimport { sseClient } from '../api/sse-client.js';\r\nimport { parseAgentResponse, AgentResponse } from './agent-response-parser.js';\r\nimport { conversationManager } from '../workflow/conversation-manager.js';\r\nimport { tokenStorage } from '../auth/token-storage.js';\r\nimport { getActiveRealm } from '../auth/get-active-realm.js';\r\nimport { tui } from '../../ui/tui.js';\r\nimport { colors } from '../../ui/colors.js';\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport { FileLogger } from '../debug/file-logger.js';\r\nimport { handleListFiles, handleReadFile, handleSearchFile, startSmartReplace } from './agent-tools.js';\r\n\r\nconst AGENT_TYPE = 'specification_agent';\r\n\r\n// Placeholder ID - User must provide the real one via env or config\r\nconst AGENT_ID = process.env.STACKSPOT_SPEC_AGENT_ID || '01KEPXTX37FTB4N672TZST4SGP';\r\n\r\nexport interface SpecAgentOptions {\r\n agentId?: string;\r\n briefingPath?: string; // Path to the briefing file to read\r\n}\r\n\r\n/**\r\n * Interactive Specification Agent session.\r\n * Reads briefing, consults user, and generates tech-spec.md.\r\n */\r\nexport async function interactiveSpecificationAgent(options: SpecAgentOptions = {}): Promise<void> {\r\n FileLogger.init();\r\n tui.intro('ποΈ Specification Agent');\r\n\r\n // 1. Resolve Briefing File\r\n let briefingContent = '';\r\n let briefingPath = options.briefingPath;\r\n\r\n if (!briefingPath) {\r\n // Try to find a default briefing in current dir\r\n const files = fs.readdirSync(process.cwd());\r\n const defaultBriefing = files.find(f => f.endsWith('_briefing.md'));\r\n\r\n briefingPath = await tui.text({\r\n message: 'Path to Briefing file (Leave empty to skip)',\r\n initialValue: defaultBriefing || '',\r\n placeholder: 'e.g., todo-list_briefing.md',\r\n validate: (val) => {\r\n if (val && !fs.existsSync(val)) return 'File not found';\r\n }\r\n }) as string;\r\n }\r\n\r\n if (tui.isCancel(briefingPath)) return;\r\n\r\n if (briefingPath) {\r\n try {\r\n briefingContent = fs.readFileSync(briefingPath, 'utf-8');\r\n tui.log.info(`Loaded briefing: ${colors.bold(briefingPath)}`);\r\n } catch (e) {\r\n tui.log.error(`Failed to read briefing: ${e}`);\r\n return;\r\n }\r\n } else {\r\n tui.log.info('Skipping briefing file. Starting fresh or exploring existing project.');\r\n }\r\n\r\n // 2. Initial Prompt Construction\r\n const initialPrompt = briefingContent ? `\r\nTenho o seguinte Documento de Briefing de NegΓ³cio. \r\nPor favor, analise-o e inicie o processo de definiΓ§Γ£o da EspecificaΓ§Γ£o TΓ©cnica.\r\n\r\n---\r\n${briefingContent}\r\n---\r\n `.trim() : 'Gostaria de ajuda com uma especificaΓ§Γ£o tΓ©cnica ou explorar este projeto.';\r\n\r\n // 3. Start Conversation Loop\r\n await runSpecLoop(initialPrompt, options.agentId);\r\n}\r\n\r\n/**\r\n * Main Loop for Specification Agent\r\n */\r\nasync function runSpecLoop(initialMessage: string, overrideAgentId?: string) {\r\n let nextPrompt = initialMessage;\r\n let keepGoing = true;\r\n\r\n while (keepGoing) {\r\n const spinner = tui.spinner();\r\n spinner.start('ποΈ Specification Agent is thinking...');\r\n\r\n let responseText = '';\r\n let lastResponse: AgentResponse | null = null;\r\n\r\n try {\r\n // Call Agent\r\n lastResponse = await callSpecAgentApi(nextPrompt, (chunk) => {\r\n responseText += chunk;\r\n try {\r\n if (responseText.trim().startsWith('{')) {\r\n spinner.message(colors.dim('Receiving structured data...'));\r\n } else {\r\n spinner.message(colors.dim('Thinking...'));\r\n }\r\n } catch (e) { }\r\n }, overrideAgentId);\r\n\r\n spinner.stop('Response received');\r\n\r\n // Handle Response Actions\r\n if (lastResponse && lastResponse.actions) {\r\n // Reset next prompt, we will build it based on actions results\r\n let executionResults = \"\";\r\n let waitingForUser = false;\r\n\r\n for (const action of lastResponse.actions) {\r\n\r\n if (action.type === 'talk_with_user') {\r\n tui.log.info(colors.primary('π€ Architect:'));\r\n console.log(action.content);\r\n waitingForUser = true;\r\n }\r\n\r\n else if (action.type === 'list_files') {\r\n tui.log.info(`π List files in: ${colors.bold(action.path || '.')}`);\r\n const result = handleListFiles(action.path || '.');\r\n executionResults += `[Action list_files(${action.path}) Result]:\\n${result}\\n\\n`;\r\n tui.log.info(colors.dim(`Files listed.`));\r\n }\r\n\r\n else if (action.type === 'read_file') {\r\n tui.log.info(`π Read file: ${colors.bold(action.path || '')}`);\r\n const result = handleReadFile(action.path || '');\r\n executionResults += `[Action read_file(${action.path}) Result]:\\n${result}\\n\\n`;\r\n tui.log.info(colors.dim(`File read.`));\r\n }\r\n\r\n else if (action.type === 'search_file') {\r\n tui.log.info(`π Search file: ${colors.bold(action.path || '')}`);\r\n const result = handleSearchFile(action.path || '');\r\n executionResults += `[Action search_file(${action.path}) Result]:\\n${result}\\n\\n`;\r\n tui.log.info(colors.dim(`Files found.`));\r\n }\r\n\r\n else if (['create_file', 'modify_file', 'delete_file'].includes(action.type)) {\r\n tui.log.warning(`\\nπ€ Agent wants to ${action.type}: ${colors.bold(action.path || 'unknown')}`);\r\n\r\n // Preview\r\n if (action.content) {\r\n console.log(colors.dim('--- Content Preview ---'));\r\n console.log(action.content.substring(0, 300) + '...');\r\n console.log(colors.dim('-----------------------'));\r\n }\r\n\r\n const confirm = await tui.confirm({\r\n message: `Approve ${action.type}?`,\r\n active: 'Yes',\r\n inactive: 'No'\r\n });\r\n\r\n if (confirm) {\r\n if (action.path) {\r\n try {\r\n if (action.type === 'create_file') {\r\n fs.writeFileSync(action.path, action.content || '');\r\n tui.log.success(`β
Created: ${action.path}`);\r\n executionResults += `[Action create_file(${action.path})]: Success\\n\\n`;\r\n } else if (action.type === 'modify_file') {\r\n if (action.target_content) {\r\n const success = startSmartReplace(action.path, action.content || '', action.target_content, tui);\r\n executionResults += `[Action modify_file(${action.path})]: ${success ? 'Success' : 'Failed'}\\n\\n`;\r\n } else {\r\n fs.writeFileSync(action.path, action.content || '');\r\n tui.log.success(`β
Overwritten: ${action.path}`);\r\n executionResults += `[Action modify_file(${action.path})]: Success (Overwrite)\\n\\n`;\r\n }\r\n } else if (action.type === 'delete_file') {\r\n fs.unlinkSync(action.path);\r\n tui.log.success(`β
Deleted: ${action.path}`);\r\n executionResults += `[Action delete_file(${action.path})]: Success\\n\\n`;\r\n }\r\n } catch (e: any) {\r\n tui.log.error(`β Failed: ${e.message}`);\r\n executionResults += `[Action ${action.type}(${action.path})]: Error: ${e.message}\\n\\n`;\r\n }\r\n }\r\n } else {\r\n tui.log.error('β Action denied.');\r\n executionResults += `[Action ${action.type}]: User Denied\\n\\n`;\r\n }\r\n }\r\n }\r\n\r\n // Prepare next prompt\r\n if (executionResults) {\r\n // If actions produced output (like file list), send it back to agent automatically\r\n // But if the agent ALSO talked to user, we should give priority to user input??\r\n // Strategy: If agent asked something (talk_with_user), we MUST ask user.\r\n // The tool outputs are appended.\r\n\r\n if (waitingForUser) {\r\n const userReply = await tui.text({\r\n message: 'Your answer',\r\n placeholder: 'Type your answer...'\r\n });\r\n if (tui.isCancel(userReply)) {\r\n keepGoing = false;\r\n return;\r\n }\r\n nextPrompt = `${executionResults}\\n\\nUser Reply: ${userReply}`;\r\n tui.log.info(colors.dim('Auto-replying with tool results...'));\r\n } else {\r\n // Agent just did tools, let's auto-reply with results so it can continue\r\n nextPrompt = executionResults;\r\n FileLogger.log('SYSTEM', 'Auto-replying with Tool Results', { length: executionResults.length });\r\n tui.log.info(colors.dim('Auto-replying with tool results...'));\r\n }\r\n\r\n } else if (waitingForUser) {\r\n // Only talk, no tools\r\n const userReply = await tui.text({\r\n message: 'Your answer',\r\n placeholder: 'Type your answer...'\r\n });\r\n if (tui.isCancel(userReply)) {\r\n keepGoing = false;\r\n return;\r\n }\r\n nextPrompt = userReply as string;\r\n } else {\r\n // No actions? Weird.\r\n tui.log.warning('No actions taken.');\r\n keepGoing = false;\r\n }\r\n\r\n } else {\r\n tui.log.warning('No actions received from agent.');\r\n keepGoing = false;\r\n }\r\n\r\n } catch (error: any) {\r\n spinner.stop('Error');\r\n tui.log.error(error.message);\r\n keepGoing = false;\r\n }\r\n }\r\n}\r\n\r\n// --- Helper Functions in agent-tools.ts ---\r\n\r\n// --- API Wrapper ---\r\n\r\nasync function callSpecAgentApi(prompt: string, onChunk: (chunk: string) => void, agentId?: string): Promise<AgentResponse> {\r\n const realm = await getActiveRealm();\r\n const token = await tokenStorage.getToken(realm);\r\n if (!token) throw new Error('Not logged in');\r\n\r\n const conversationId = await conversationManager.getConversationId(AGENT_TYPE);\r\n\r\n const payload = {\r\n user_prompt: prompt,\r\n streaming: true,\r\n stackspot_knowledge: false,\r\n return_ks_in_response: true,\r\n use_conversation: true,\r\n conversation_id: conversationId\r\n };\r\n\r\n const finalId = agentId || AGENT_ID;\r\n const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${finalId}/chat`;\r\n\r\n let fullMsg = '';\r\n let raw: any = {};\r\n\r\n FileLogger.log('AGENT', 'Calling Agent API', {\r\n agentId: finalId,\r\n conversationId,\r\n prompt: prompt.substring(0, 500) // Log summary of prompt\r\n });\r\n\r\n await sseClient.streamAgentResponse(url, payload, { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, {\r\n onChunk: (c) => { fullMsg += c; onChunk(c); },\r\n onComplete: (msg, metadata) => {\r\n // Prefer conversation_id from metadata (server response), fallback to sent ID\r\n const returnedId = metadata?.conversation_id;\r\n\r\n FileLogger.log('AGENT', 'Response Complete', {\r\n conversationId,\r\n returnedId,\r\n messageLength: msg?.length\r\n });\r\n\r\n raw = {\r\n message: msg || fullMsg,\r\n conversation_id: returnedId || conversationId\r\n };\r\n },\r\n onError: (e) => { throw e; }\r\n });\r\n\r\n const parsed = parseAgentResponse(raw);\r\n if (parsed.conversation_id) {\r\n await conversationManager.saveConversationId(AGENT_TYPE, parsed.conversation_id);\r\n }\r\n\r\n return parsed;\r\n}\r\n","\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport fg from 'fast-glob';\r\nimport { colors } from '../../ui/colors.js';\r\nimport { tui } from '../../ui/tui.js';\r\n\r\n/**\r\n * Shared tools for Agent interaction (File System, etc.)\r\n */\r\n\r\nexport function handleListFiles(dirPath: string): string {\r\n try {\r\n const fullPath = path.resolve(process.cwd(), dirPath);\r\n if (!fs.existsSync(fullPath)) return `Error: Directory ${dirPath} does not exist.`;\r\n\r\n const items = fs.readdirSync(fullPath, { withFileTypes: true });\r\n return items.map(item => {\r\n return `${item.isDirectory() ? '[DIR]' : '[FILE]'} ${item.name}`;\r\n }).join('\\n');\r\n } catch (e: any) {\r\n return `Error listing files: ${e.message}`;\r\n }\r\n}\r\n\r\nexport function handleReadFile(filePath: string): string {\r\n try {\r\n const fullPath = path.resolve(process.cwd(), filePath);\r\n if (!fs.existsSync(fullPath)) return `Error: File ${filePath} does not exist.`;\r\n\r\n // Limit size?\r\n const stats = fs.statSync(fullPath);\r\n if (stats.size > 100 * 1024) return `Error: File too large to read (${stats.size} bytes). Limit is 100KB.`;\r\n\r\n return fs.readFileSync(fullPath, 'utf-8');\r\n } catch (e: any) {\r\n return `Error reading file: ${e.message}`;\r\n }\r\n}\r\n\r\nexport function handleSearchFile(pattern: string): string {\r\n try {\r\n // Limit scope to current directory for safety?\r\n // Patterns are relative to process.cwd()\r\n const entries = fg.sync(pattern, { dot: true });\r\n if (entries.length === 0) return 'No files found matching pattern.';\r\n return entries.slice(0, 50).join('\\n');\r\n } catch (e: any) {\r\n return `Error searching files: ${e.message}`;\r\n }\r\n}\r\n\r\nexport function startSmartReplace(filePath: string, newContent: string, targetContent: string, tui: any): boolean {\r\n if (!fs.existsSync(filePath)) {\r\n tui.log.error(`β File not found for modification: ${filePath}`);\r\n return false;\r\n }\r\n\r\n const currentFileContent = fs.readFileSync(filePath, 'utf-8');\r\n\r\n // 1. Validation: Does target exist?\r\n // Normalize line endings?\r\n if (!currentFileContent.includes(targetContent)) {\r\n tui.log.error(`β Target content not found in ${filePath}. Modification aborted.`);\r\n console.log(colors.dim('--- Target Content Expected ---'));\r\n console.log(targetContent.substring(0, 200) + '...');\r\n return false;\r\n }\r\n\r\n // 2. Validation: Is it unique?\r\n const occurrences = currentFileContent.split(targetContent).length - 1;\r\n if (occurrences > 1) {\r\n tui.log.error(`β Ambiguous target: Found ${occurrences} occurrences in ${filePath}. Modification aborted.`);\r\n return false;\r\n }\r\n\r\n // 3. Apply Replacement\r\n const updatedContent = currentFileContent.replace(targetContent, newContent);\r\n fs.writeFileSync(filePath, updatedContent);\r\n tui.log.success(`β
Smart Replace Applied: ${filePath}`);\r\n return true;\r\n}\r\n\r\nexport async function handleRunCommand(command: string): Promise<string> {\r\n const { spawn } = await import('node:child_process');\r\n try {\r\n tui.log.info(`π» Executing: ${colors.dim(command)}`);\r\n\r\n // Split command into cmd and args (naive split, use specific parser if needed for complex quotes)\r\n // For simplicity in Agent usage, we might act as a shell?\r\n // Let's use shell: true option for ease of piping/env usage.\r\n\r\n return new Promise((resolve) => {\r\n const child = spawn(command, {\r\n shell: true,\r\n stdio: ['ignore', 'pipe', 'pipe'],\r\n cwd: process.cwd()\r\n });\r\n\r\n let stdout = '';\r\n let stderr = '';\r\n\r\n // Timeout safety: 5 minutes\r\n const timer = setTimeout(() => {\r\n child.kill();\r\n resolve(`Error: Command timed out after 5 minutes.\\nOutput so far:\\n${stdout}\\n${stderr}`);\r\n }, 5 * 60 * 1000);\r\n\r\n child.stdout.on('data', (data) => {\r\n const chunk = data.toString();\r\n stdout += chunk;\r\n // Optional: Stream to TUI if verbose?\r\n });\r\n\r\n child.stderr.on('data', (data) => {\r\n stderr += data.toString();\r\n });\r\n\r\n child.on('close', (code) => {\r\n clearTimeout(timer);\r\n if (code === 0) {\r\n resolve(stdout.trim() || 'Command executed successfully (no output).');\r\n } else {\r\n resolve(`Command failed with exit code ${code}.\\nSTDERR:\\n${stderr}\\nSTDOUT:\\n${stdout}`);\r\n }\r\n });\r\n\r\n child.on('error', (err) => {\r\n clearTimeout(timer);\r\n resolve(`Error executing command: ${err.message}`);\r\n });\r\n });\r\n\r\n } catch (e: any) {\r\n return `Error launching command: ${e.message}`;\r\n }\r\n}\r\n","\r\nimport { Command } from 'commander';\r\nimport { interactiveScanAgent } from '../core/agents/scan-agent.js';\r\n\r\nexport const scanCommand = new Command('scan')\r\n .description('Analyze the project and generate context documentation')\r\n .option('-o, --output <path>', 'Output file path (default: _bmad/project-context/project-context.md)')\r\n .option('--depth <level>', 'Scan depth (quick, deep, exhaustive)', 'quick')\r\n .action(async (options) => {\r\n try {\r\n await interactiveScanAgent(options);\r\n } catch (error: any) {\r\n console.error('Error during scan:', error.message);\r\n process.exit(1);\r\n }\r\n });\r\n","\r\nimport { STACKSPOT_AGENT_API_BASE } from '../api/stackspot-client.js';\r\nimport { sseClient } from '../api/sse-client.js';\r\nimport { parseAgentResponse, AgentResponse } from './agent-response-parser.js';\r\nimport { conversationManager } from '../workflow/conversation-manager.js';\r\nimport { tokenStorage } from '../auth/token-storage.js';\r\nimport { getActiveRealm } from '../auth/get-active-realm.js';\r\nimport { tui } from '../../ui/tui.js';\r\nimport { colors } from '../../ui/colors.js';\r\nimport { FileLogger } from '../debug/file-logger.js';\r\nimport { handleListFiles, handleReadFile, handleSearchFile } from './agent-tools.js';\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\n\r\nconst AGENT_TYPE = 'scan_agent';\r\n// We can reuse the Specification Agent ID or a new one. Using env var or default.\r\n// Ideally, we'd have a specific ID for Scan Agent. For now, assume a placeholder or reuse.\r\nconst AGENT_ID = process.env.STACKSPOT_SCAN_AGENT_ID || '01KEQ9AHWB550J2244YBH3QATN'; // User provided Agent ID\r\n\r\n/**\r\n * Scan Agent implementation.\r\n * It autonomously explores the project and generates project-context.md\r\n */\r\nimport { ConfigManager } from '../config-manager.js';\r\n\r\n// ... (existing imports)\r\n\r\n/**\r\n * Scan Agent implementation.\r\n * It autonomously explores the project and generates project-context.md\r\n */\r\nexport async function interactiveScanAgent(options: { output?: string, depth?: string } = {}): Promise<void> {\r\n FileLogger.init();\r\n tui.intro('π΅οΈββοΈ Scan Agent');\r\n\r\n const config = ConfigManager.getInstance().getConfig();\r\n const language = config.language || 'English';\r\n\r\n const projectRoot = process.cwd();\r\n // Use options.output if provided, otherwise default to _sharkrc/project-context.md\r\n // If output option is provided, resolve it.\r\n // If not, use _sharkrc directory (create if needed).\r\n\r\n let outputFile: string;\r\n\r\n if (options.output) {\r\n outputFile = path.resolve(process.cwd(), options.output);\r\n } else {\r\n const outputDir = path.resolve(projectRoot, '_sharkrc');\r\n if (!fs.existsSync(outputDir)) {\r\n // Check if _sharkrc exists as a file (common config file name), if so, error or warn?\r\n // User requested \"pasta _sharkrc\".\r\n const stat = fs.existsSync(outputDir) ? fs.statSync(outputDir) : null;\r\n if (stat && stat.isFile()) {\r\n tui.log.warning(`Warning: '_sharkrc' exists as a file. Using '_bmad/project-context' instead to avoid overwrite.`);\r\n const fallbackDir = path.resolve(projectRoot, '_bmad/project-context');\r\n if (!fs.existsSync(fallbackDir)) fs.mkdirSync(fallbackDir, { recursive: true });\r\n outputFile = path.join(fallbackDir, 'project-context.md');\r\n } else {\r\n fs.mkdirSync(outputDir, { recursive: true });\r\n outputFile = path.join(outputDir, 'project-context.md');\r\n }\r\n } else {\r\n fs.mkdirSync(outputDir, { recursive: true });\r\n outputFile = path.join(outputDir, 'project-context.md');\r\n }\r\n }\r\n\r\n tui.log.info(`Scanning project at: ${colors.bold(projectRoot)}`);\r\n tui.log.info(`Output targeted at: ${colors.bold(outputFile)}`);\r\n tui.log.info(`Language: ${colors.bold(language)}`);\r\n\r\n const configFileRelative = path.relative(projectRoot, outputFile);\r\n\r\n // Construct the \"Super Prompt\"\r\n const superPrompt = `\r\nYou are the **Scan Agent**, an expert software architect and analyst.\r\nYour mission is to explore this project's codebase and generate a comprehensive context file that will be used by other AI agents (specifically a Developer Agent) to understand how to work on this project.\r\n\r\n**Goal**: Create a markdown file at: \\`${configFileRelative}\\`.\r\n\r\n**LANGUAGE INSTRUCTION**:\r\nYou MUST write the content of the \\`project-context.md\\` file in **${language}**.\r\nAlso, strictly interact with tools using the appropriate payload.\r\n\r\n**Instructions**:\r\n1. **Analyze Structure**: Use \\`list_files\\` to understand the root directory and key subdirectories (src, tools, config, etc.).\r\n2. **Identify Tech Stack**: Use \\`read_file\\` or \\`search_file\\` on key manifests (package.json, pom.xml, go.mod, Dockerfile, etc.) to determine languages, frameworks, and versions.\r\n3. **Map Architecture**: Infer the architectural pattern (Monolith? Microservices? Clean Architecture?) based on folder structure and key files.\r\n4. **Document Key Paths**: Identify where source code, tests, and configs live.\r\n\r\n**Output Format** (Markdown):\r\nThe final action MUST be \\`create_file\\` (or \\`modify_file\\`) for the target file with the following structure:\r\n\r\n# Project Context\r\n\r\n## Overview\r\n[Brief description of what this project seems to be]\r\n\r\n## Tech Stack\r\n- **Language**: [e.g. TypeScript]\r\n- **Framework**: [e.g. React, Express, NestJS]\r\n- **Build Tool**: [e.g. Vite, Webpack]\r\n- **Database**: [e.g. PostgreSQL, Prisma] (if detected)\r\n\r\n## Architecture\r\n[Description of the folder structure and architectural patterns detected]\r\n\r\n## Key Locations\r\n- **Source**: [path/to/src]\r\n- **Tests**: [path/to/tests]\r\n- **Config**: [path/to/config]\r\n\r\n## Commands\r\n[List of discovered npm scripts or makefile commands for dev, build, test]\r\n\r\n---\r\n\r\n**Rules**:\r\n- Do NOT guess. If you are unsure, check the file.\r\n- Be concise.\r\n- Focus on FACTS that a Developer Agent needs to know to write code correcty.\r\n- Start by listing the root directory.\r\n`.trim();\r\n\r\n await runScanLoop(superPrompt, outputFile);\r\n}\r\n\r\n// ... (rest of the file)\r\n\r\nasync function runScanLoop(initialPrompt: string, targetPath: string) {\r\n let nextPrompt = initialPrompt;\r\n let keepGoing = true;\r\n let stepCount = 0;\r\n const MAX_STEPS = 15; // Safety limit\r\n\r\n while (keepGoing && stepCount < MAX_STEPS) {\r\n stepCount++;\r\n const spinner = tui.spinner();\r\n spinner.start(`π΅οΈββοΈ Scan Agent analyzing (Step ${stepCount}/${MAX_STEPS})...`);\r\n\r\n let responseText = '';\r\n let lastResponse: AgentResponse | null = null;\r\n\r\n try {\r\n // Call Agent\r\n lastResponse = await callScanAgentApi(nextPrompt, (chunk) => {\r\n responseText += chunk;\r\n // Optional: Update spinner message based on chunk if needed\r\n });\r\n\r\n spinner.stop('Step complete');\r\n\r\n // Handle Response Actions\r\n if (lastResponse && lastResponse.actions) {\r\n let executionResults = \"\";\r\n let fileCreated = false;\r\n\r\n for (const action of lastResponse.actions) {\r\n if (action.type === 'list_files') {\r\n tui.log.info(`π Scanning dir: ${colors.bold(action.path || '.')}`);\r\n const result = handleListFiles(action.path || '.');\r\n executionResults += `[Action list_files(${action.path}) Result]:\\n${result}\\n\\n`;\r\n }\r\n else if (action.type === 'read_file') {\r\n tui.log.info(`π Reading file: ${colors.bold(action.path || '')}`);\r\n const result = handleReadFile(action.path || '');\r\n // Truncate if too long for context window? Agent Tools already limits size.\r\n executionResults += `[Action read_file(${action.path}) Result]:\\n${result}\\n\\n`;\r\n }\r\n else if (action.type === 'search_file') {\r\n tui.log.info(`π Searching: ${colors.bold(action.path || '')}`);\r\n const result = handleSearchFile(action.path || '');\r\n executionResults += `[Action search_file(${action.path}) Result]:\\n${result}\\n\\n`;\r\n }\r\n else if (action.type === 'create_file' || action.type === 'modify_file') {\r\n // Check if this is our target file\r\n // The agent might try to create other files, but we mainly care about the context file.\r\n // We will allow it to create the target file automatically without prompt if it matches.\r\n\r\n // For safety, let's just confirm. Or since this is \"Scan\", maybe we auto-accept?\r\n // Let's auto-accept if it is the target file, confirm otherwise.\r\n const resolvedActionPath = path.resolve(action.path || '');\r\n const resolvedTargetPath = path.resolve(targetPath);\r\n let isTarget = resolvedActionPath === resolvedTargetPath;\r\n\r\n // Fallback: If agent uses wrong directory but correct filename \"project-context.md\", allow it and force correct path.\r\n if (!isTarget && path.basename(action.path || '') === 'project-context.md') {\r\n tui.log.warning(`Agent targeted '${action.path}' but we enforce '${path.relative(process.cwd(), targetPath)}'. Redirecting write.`);\r\n isTarget = true;\r\n // Update action path for logging consistency (optional, but good for clarity)\r\n action.path = targetPath;\r\n }\r\n\r\n if (isTarget) {\r\n // Enforce writing to the correct targetPath regardless of what agent said\r\n const finalPath = targetPath;\r\n if (action.type === 'create_file') {\r\n fs.writeFileSync(finalPath, action.content || '');\r\n tui.log.success(`β
Generated Context: ${finalPath}`);\r\n fileCreated = true;\r\n } else {\r\n // Modify\r\n fs.writeFileSync(finalPath, action.content || ''); // Overwrite for now\r\n tui.log.success(`β
Updated Context: ${finalPath}`);\r\n fileCreated = true;\r\n }\r\n executionResults += `[Action ${action.type}]: Success. Task Completed.\\n`;\r\n } else {\r\n tui.log.warning(`Agent wants to write to unexpected file: ${action.path}`);\r\n // Skip for now to avoid side effects during scan, or ask user?\r\n // Let's just log it.\r\n executionResults += `[Action ${action.type}]: Skipped (Scan Agent only writes context file)\\n`;\r\n }\r\n }\r\n else if (action.type === 'talk_with_user') {\r\n tui.log.info(colors.primary('π€ Scan Agent asks:'));\r\n console.log(action.content);\r\n // We don't really want to chat during auto-scan, but if it asks, we should probably answer or stop.\r\n // For now, let's stop and ask user.\r\n const reply = await tui.text({ message: 'Agent needs input:', placeholder: 'Reply...' });\r\n executionResults += `[User Reply]: ${reply}\\n`;\r\n }\r\n }\r\n\r\n if (fileCreated) {\r\n tui.log.success('β¨ Scan completed successfully!');\r\n keepGoing = false;\r\n } else {\r\n // Feed results back\r\n nextPrompt = executionResults;\r\n FileLogger.log('SCAN', 'Auto-replying with results', { length: executionResults.length });\r\n }\r\n\r\n } else {\r\n // No actions?\r\n if (stepCount > 1) {\r\n tui.log.warning('Scan Agent stopped without actions.');\r\n keepGoing = false;\r\n } else {\r\n // First turn and no actions? problematic.\r\n }\r\n }\r\n\r\n } catch (error: any) {\r\n spinner.stop('Error');\r\n tui.log.error(error.message);\r\n keepGoing = false;\r\n }\r\n }\r\n}\r\n\r\n\r\nasync function callScanAgentApi(prompt: string, onChunk: (chunk: string) => void): Promise<AgentResponse> {\r\n const realm = await getActiveRealm();\r\n const token = await tokenStorage.getToken(realm);\r\n if (!token) throw new Error('Not logged in');\r\n\r\n // Generate a temporary conversation ID for this scan session\r\n // We might not need to persist it long-term, but we need one for the session.\r\n // Or we rely on the one returned.\r\n let conversationId = await conversationManager.getConversationId(AGENT_TYPE);\r\n\r\n // If no conversation exists, that's fine, API will create one.\r\n\r\n const payload = {\r\n user_prompt: prompt,\r\n streaming: true,\r\n stackspot_knowledge: false,\r\n return_ks_in_response: true,\r\n use_conversation: true,\r\n conversation_id: conversationId\r\n };\r\n\r\n const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${AGENT_ID}/chat`;\r\n let fullMsg = '';\r\n let raw: any = {};\r\n\r\n FileLogger.log('SCAN', 'Calling API', { promptLength: prompt.length });\r\n\r\n await sseClient.streamAgentResponse(url, payload, { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, {\r\n onChunk: (c) => { fullMsg += c; onChunk(c); },\r\n onComplete: (msg, metadata) => {\r\n const returnedId = metadata?.conversation_id;\r\n raw = {\r\n message: msg || fullMsg,\r\n conversation_id: returnedId || conversationId\r\n };\r\n },\r\n onError: (e) => { throw e; }\r\n });\r\n\r\n const parsed = parseAgentResponse(raw);\r\n if (parsed.conversation_id) {\r\n await conversationManager.saveConversationId(AGENT_TYPE, parsed.conversation_id);\r\n }\r\n return parsed;\r\n}\r\n","\r\nimport { Command } from 'commander';\r\nimport { interactiveDeveloperAgent } from '../core/agents/developer-agent.js';\r\n\r\nexport const devCommand = new Command('dev')\r\n .description('Starts the Shark Developer Agent (Shark Dev)')\r\n .option('-t, --task <type>', 'Initial task description')\r\n .option('-c, --context <path>', 'Path to custom context file')\r\n .action(async (options) => {\r\n await interactiveDeveloperAgent(options);\r\n });\r\n","\r\nimport { STACKSPOT_AGENT_API_BASE } from '../api/stackspot-client.js';\r\nimport { sseClient } from '../api/sse-client.js';\r\nimport { parseAgentResponse, AgentResponse, AgentAction } from './agent-response-parser.js';\r\nimport { conversationManager } from '../workflow/conversation-manager.js';\r\nimport { tokenStorage } from '../auth/token-storage.js';\r\nimport { getActiveRealm } from '../auth/get-active-realm.js';\r\nimport { tui } from '../../ui/tui.js';\r\nimport { colors } from '../../ui/colors.js';\r\nimport { ConfigManager } from '../config-manager.js';\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport { FileLogger } from '../debug/file-logger.js';\r\nimport {\r\n handleListFiles,\r\n handleReadFile,\r\n handleSearchFile,\r\n startSmartReplace,\r\n handleRunCommand\r\n} from './agent-tools.js';\r\n\r\nconst AGENT_TYPE = 'developer_agent';\r\n// Placeholder ID - User must provide the real one via env\r\nconst AGENT_ID = process.env.STACKSPOT_DEV_AGENT_ID || '01KEQCGJ65YENRA4QBXVN1YFFX'; // Default ID if not set in env\r\n\r\nexport async function interactiveDeveloperAgent(options: { task?: string, context?: string } = {}): Promise<void> {\r\n FileLogger.init();\r\n tui.intro('π¦ Shark Dev Agent');\r\n\r\n if (AGENT_ID === 'PENDING_CONFIGURATION') {\r\n tui.log.error('β STACKSPOT_DEV_AGENT_ID not configured in .env');\r\n return;\r\n }\r\n\r\n // 1. Load Context\r\n const projectRoot = process.cwd();\r\n let contextContent = '';\r\n const defaultContextPath = path.resolve(projectRoot, '_sharkrc', 'project-context.md');\r\n const specificContextPath = options.context ? path.resolve(projectRoot, options.context) : defaultContextPath;\r\n\r\n if (fs.existsSync(specificContextPath)) {\r\n try {\r\n contextContent = fs.readFileSync(specificContextPath, 'utf-8');\r\n tui.log.info(`π Context loaded from: ${colors.dim(path.relative(projectRoot, specificContextPath))}`);\r\n } catch (e) {\r\n tui.log.warning(`Failed to read context file: ${e}`);\r\n }\r\n } else {\r\n tui.log.warning(`β οΈ No context file found. Agent will run without pre-loaded context.`);\r\n }\r\n\r\n // 2. Prepare Initial Prompt\r\n let nextPrompt = options.task || \"I'm ready to help. What's the task?\";\r\n if (contextContent) {\r\n nextPrompt += `\\n\\n--- PROJECT CONTEXT ---\\n${contextContent}\\n-----------------------`;\r\n }\r\n\r\n // 3. Main Loop\r\n let keepGoing = true;\r\n const spinner = tui.spinner();\r\n\r\n while (keepGoing) {\r\n try {\r\n spinner.start('Waiting for Agent...');\r\n\r\n // Call API\r\n let lastResponse: AgentResponse | null = null;\r\n await callDevAgentApi(nextPrompt, (chunk) => {\r\n // Optional: Stream text to TUI if needed\r\n if (!lastResponse) {\r\n // Maybe show thinking dots?\r\n }\r\n }).then(resp => {\r\n lastResponse = resp;\r\n });\r\n\r\n spinner.stop('Response received');\r\n\r\n if (lastResponse && (lastResponse as AgentResponse).actions) {\r\n const response = lastResponse as AgentResponse;\r\n let executionResults = \"\";\r\n let waitingForUser = false;\r\n\r\n for (const action of response.actions) {\r\n\r\n if (action.type === 'talk_with_user') {\r\n tui.log.info(colors.primary('π€ Shark Dev:'));\r\n console.log(action.content);\r\n waitingForUser = true;\r\n }\r\n\r\n else if (action.type === 'list_files') {\r\n tui.log.info(`π Scanning dir: ${colors.dim(action.path || '.')}`);\r\n const result = handleListFiles(action.path || '.');\r\n executionResults += `[Action list_files(${action.path}) Result]:\\n${result}\\n\\n`;\r\n }\r\n\r\n else if (action.type === 'read_file') {\r\n tui.log.info(`π Reading: ${colors.dim(action.path || '')}`);\r\n const result = handleReadFile(action.path || '');\r\n executionResults += `[Action read_file(${action.path}) Result]:\\n${result}\\n\\n`;\r\n }\r\n\r\n else if (action.type === 'search_file') {\r\n tui.log.info(`π Searching: ${colors.dim(action.path || '')}`);\r\n const result = handleSearchFile(action.path || '');\r\n executionResults += `[Action search_file(${action.path}) Result]:\\n${result}\\n\\n`;\r\n }\r\n\r\n else if (action.type === 'run_command') {\r\n const cmd = action.command || '';\r\n tui.log.info(`π» Executing: ${colors.dim(cmd)}`);\r\n // Execute Command\r\n // Warning: Prompt user for non-safe commands? \r\n // For now, let's assume Shark Dev is trusted or ask for everything.\r\n // Let's ask for confirmation for consistency.\r\n const confirm = await tui.confirm({\r\n message: `Execute command: ${cmd}?`,\r\n active: 'Yes',\r\n inactive: 'No'\r\n });\r\n\r\n if (confirm) {\r\n const result = await handleRunCommand(cmd);\r\n executionResults += `[Action run_command(${cmd}) Result]:\\n${result}\\n\\n`;\r\n } else {\r\n executionResults += `[Action run_command]: User blocked execution.\\n\\n`;\r\n }\r\n }\r\n\r\n else if (['create_file', 'modify_file'].includes(action.type)) {\r\n const isCreate = action.type === 'create_file';\r\n const filePath = action.path || '';\r\n tui.log.warning(`\\nπ€ Agent wants to ${isCreate ? 'CREATE' : 'MODIFY'}: ${colors.bold(filePath)}`);\r\n\r\n // Preview content (maybe diff?)\r\n // For brevity, just log start\r\n if (action.content) {\r\n console.log(colors.dim('--- Content ---\\n') + action.content.substring(0, 200) + '...\\n' + colors.dim('---------------'));\r\n }\r\n\r\n const confirm = await tui.confirm({\r\n message: `Approve changes to ${filePath}?`,\r\n active: 'Yes',\r\n inactive: 'No'\r\n });\r\n\r\n if (confirm) {\r\n if (filePath) {\r\n const targetPath = path.resolve(projectRoot, filePath);\r\n const dir = path.dirname(targetPath);\r\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\r\n\r\n if (isCreate) {\r\n fs.writeFileSync(targetPath, action.content || '');\r\n tui.log.success(`β
Created: ${filePath}`);\r\n executionResults += `[Action create_file(${filePath})]: Success\\n\\n`;\r\n } else {\r\n // Modify\r\n if (action.target_content) {\r\n const success = startSmartReplace(filePath, action.content || '', action.target_content, tui);\r\n executionResults += `[Action modify_file(${filePath})]: ${success ? 'Success' : 'Failed'}\\n\\n`;\r\n } else {\r\n // Fallback overwrite if no target_content provided (should be rare given schema)\r\n // But for Dev Agent, schema requires new_content (mapped to content) and target_content.\r\n // If target_content missing, we might fail or overwrite.\r\n // Let's safe fail.\r\n tui.log.error('β Missing target_content for modification.');\r\n executionResults += `[Action modify_file]: Failed. Missing target_content.\\n\\n`;\r\n }\r\n }\r\n }\r\n } else {\r\n tui.log.error('β Denied.');\r\n executionResults += `[Action ${action.type}]: User Denied.\\n\\n`;\r\n }\r\n }\r\n }\r\n\r\n // Prepare next prompt\r\n if (executionResults) {\r\n if (waitingForUser) {\r\n const userReply = await tui.text({ message: 'Your answer:' });\r\n if (tui.isCancel(userReply)) { keepGoing = false; break; }\r\n nextPrompt = `${executionResults}\\n\\nUser Reply: ${userReply}`;\r\n } else {\r\n // Auto-continue\r\n nextPrompt = executionResults;\r\n tui.log.info(colors.dim('Sending tool results to agent...'));\r\n }\r\n } else if (waitingForUser) {\r\n const userReply = await tui.text({ message: 'Your answer:' });\r\n if (tui.isCancel(userReply)) { keepGoing = false; break; }\r\n nextPrompt = userReply as string;\r\n } else {\r\n // Fallback: If no actions but we have a message/summary, assume it's a talk\r\n if (response.message) {\r\n tui.log.info(colors.primary('π€ Shark Dev:'));\r\n console.log(response.message);\r\n const userReply = await tui.text({ message: 'Your answer:' });\r\n if (tui.isCancel(userReply)) {\r\n keepGoing = false;\r\n } else {\r\n nextPrompt = userReply as string;\r\n }\r\n } else {\r\n tui.log.warning('Agent took no actions.');\r\n keepGoing = false;\r\n }\r\n }\r\n\r\n } else {\r\n tui.log.warning('Invalid response from agent.');\r\n keepGoing = false;\r\n }\r\n\r\n } catch (e: any) {\r\n spinner.stop('Error');\r\n tui.log.error(e.message);\r\n keepGoing = false;\r\n }\r\n }\r\n\r\n tui.outro('π Shark Dev Session Ended');\r\n}\r\n\r\nasync function callDevAgentApi(prompt: string, onChunk: (chunk: string) => void): Promise<AgentResponse> {\r\n const realm = await getActiveRealm();\r\n const token = await tokenStorage.getToken(realm);\r\n if (!token) throw new Error('Not logged in. Run shark login.');\r\n\r\n const conversationId = await conversationManager.getConversationId(AGENT_TYPE);\r\n\r\n const payload = {\r\n user_prompt: prompt,\r\n streaming: true,\r\n use_conversation: true,\r\n conversation_id: conversationId,\r\n stackspot_knowledge: false // Dev Agent focuses on project context\r\n };\r\n\r\n const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${AGENT_ID}/chat`;\r\n let fullMsg = '';\r\n let raw: any = {};\r\n\r\n await sseClient.streamAgentResponse(url, payload, { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, {\r\n onChunk: (c) => { fullMsg += c; onChunk(c); },\r\n onComplete: (msg, metadata) => {\r\n const returnedId = metadata?.conversation_id;\r\n raw = {\r\n message: msg || fullMsg,\r\n conversation_id: returnedId || conversationId\r\n };\r\n },\r\n onError: (e) => { throw e; }\r\n });\r\n\r\n const parsed = parseAgentResponse(raw);\r\n if (parsed.conversation_id) {\r\n await conversationManager.saveConversationId(AGENT_TYPE, parsed.conversation_id);\r\n }\r\n return parsed;\r\n}\r\n","import { Command } from 'commander';\r\nimport { runQAAgent } from '../core/agents/qa-agent';\r\n\r\nexport const qaCommand = new Command('qa')\r\n .description('Start the Shark QA Agent to test web applications')\r\n .option('--url <url>', 'Initial URL to test')\r\n .option('--scenario <scenario>', 'Scenario description or test case to execute')\r\n .action(async (options) => {\r\n try {\r\n await runQAAgent({\r\n initialUrl: options.url,\r\n scenario: options.scenario\r\n });\r\n } catch (error: any) {\r\n console.error('Failed to run QA Agent:', error.message);\r\n process.exit(1);\r\n }\r\n });\r\n","import { tui } from '../../ui/tui';\r\nimport { colors } from '../../ui/colors';\r\nimport { getActiveRealm } from '../auth/get-active-realm';\r\nimport { tokenStorage } from '../auth/token-storage';\r\nimport { sseClient } from '../api/sse-client';\r\nimport { parseAgentResponse, AgentAction, AgentResponse } from './agent-response-parser';\r\nimport { conversationManager } from '../workflow/conversation-manager';\r\nimport { handleReadFile, handleListFiles, handleSearchFile, handleRunCommand } from './agent-tools';\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\r\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\r\n\r\nconst AGENT_TYPE = 'qa_agent';\r\n\r\n// Allow override via env var, otherwise use a default (placeholder for now)\r\nconst AGENT_ID = process.env.STACKSPOT_QA_AGENT_ID || '01KEQFJZ3Q3JER11NH22HEZX9X';\r\n\r\ninterface QAAgentOptions {\r\n initialUrl?: string;\r\n scenario?: string;\r\n}\r\n\r\n// MCP Client Wrapper\r\nclass ChromeDevToolsClient {\r\n private client: Client | null = null;\r\n private transport: StdioClientTransport | null = null;\r\n\r\n async connect() {\r\n if (this.client) return;\r\n\r\n try {\r\n this.transport = new StdioClientTransport({\r\n command: 'npx',\r\n args: ['-y', 'chrome-devtools-mcp@latest']\r\n });\r\n\r\n this.client = new Client({\r\n name: \"shark-qa-client\",\r\n version: \"1.0.0\"\r\n }, {\r\n capabilities: {}\r\n });\r\n\r\n await this.client.connect(this.transport);\r\n tui.log.success('π Connected to Chrome DevTools MCP');\r\n } catch (e: any) {\r\n tui.log.error(`Failed to connect to Chrome MCP: ${e.message}`);\r\n throw e;\r\n }\r\n }\r\n\r\n async callTool(name: string, args: any) {\r\n if (!this.client) await this.connect();\r\n try {\r\n const result = await this.client!.callTool({\r\n name,\r\n arguments: args\r\n });\r\n return result;\r\n } catch (e: any) {\r\n return { isError: true, content: [{ type: 'text', text: `MCP Error: ${e.message}` }] };\r\n }\r\n }\r\n\r\n async close() {\r\n if (this.transport) {\r\n await this.transport.close();\r\n }\r\n }\r\n}\r\n\r\nconst mcpClient = new ChromeDevToolsClient();\r\n\r\nexport async function runQAAgent(options: QAAgentOptions) {\r\n if (!AGENT_ID) {\r\n tui.log.error('β STACKSPOT_QA_AGENT_ID not configured.');\r\n tui.log.info('Please run: set STACKSPOT_QA_AGENT_ID=<your-id>');\r\n return;\r\n }\r\n\r\n // Connect to MCP at start\r\n await mcpClient.connect();\r\n\r\n tui.intro('π¦ Shark QA Agent');\r\n tui.log.info('Connecting to Chrome DevTools...');\r\n\r\n const realm = await getActiveRealm();\r\n const token = await tokenStorage.getToken(realm);\r\n\r\n if (!token) {\r\n tui.log.error('Authentication required. Run \"shark login\".');\r\n return;\r\n }\r\n\r\n // 1. Prepare Initial Context\r\n let projectContext = \"\";\r\n try {\r\n const contextPath = path.join(process.cwd(), '_sharkrc', 'project-context.md');\r\n if (fs.existsSync(contextPath)) {\r\n projectContext = fs.readFileSync(contextPath, 'utf-8');\r\n tui.log.info(`π Context loaded from: _sharkrc/project-context.md`);\r\n }\r\n } catch (e) {\r\n // Ignore if no context\r\n }\r\n\r\n let userMessage = `CONTEXTO DO PROJETO:\\n${projectContext}\\n\\n`;\r\n\r\n if (options.initialUrl) {\r\n userMessage += `URL ALVO: ${options.initialUrl}\\n`;\r\n }\r\n if (options.scenario) {\r\n userMessage += `CENΓRIO DE TESTE: ${options.scenario}\\n`;\r\n } else {\r\n userMessage += `Por favor, aguarde instruΓ§Γ΅es do usuΓ‘rio.`;\r\n }\r\n\r\n // 2. Interaction Loop\r\n let keepRunning = true;\r\n\r\n while (keepRunning) {\r\n const spinner = tui.spinner();\r\n spinner.start('π€ Shark QA is thinking...');\r\n\r\n let agentResponseText = \"\";\r\n let agentResponse: AgentResponse | null = null;\r\n\r\n try {\r\n // API Interaction (Manual Call until AgentManager is unified)\r\n const existingConversationId = await conversationManager.getConversationId(AGENT_TYPE);\r\n\r\n await sseClient.streamAgentResponse(\r\n `https://genai-inference-app.stackspot.com/v1/agent/${AGENT_ID}/chat`,\r\n {\r\n user_prompt: userMessage,\r\n streaming: true,\r\n use_conversation: true,\r\n conversation_id: existingConversationId\r\n },\r\n {\r\n 'Authorization': `Bearer ${token}`\r\n },\r\n {\r\n onChunk: (chunk) => {\r\n agentResponseText += chunk;\r\n if (agentResponseText.length > 10 && agentResponseText.trim().startsWith('{')) {\r\n spinner.message('Receiving structured plan...');\r\n }\r\n },\r\n onComplete: (fullText, metadata) => {\r\n try {\r\n if (metadata?.conversation_id) {\r\n conversationManager.saveConversationId(AGENT_TYPE, metadata.conversation_id);\r\n }\r\n agentResponse = parseAgentResponse(fullText || agentResponseText);\r\n } catch (e) {\r\n tui.log.error(`Parse Error: ${(e as Error).message}`);\r\n agentResponse = { actions: [], summary: \"Error parsing response\", message: fullText };\r\n }\r\n }\r\n }\r\n );\r\n\r\n spinner.stop('Response Received');\r\n\r\n } catch (error) {\r\n spinner.stop('Communication Error', 1);\r\n tui.log.error((error as Error).message);\r\n keepRunning = false;\r\n break;\r\n }\r\n\r\n if (!agentResponse) continue;\r\n\r\n // 3. Handle Actions\r\n if (agentResponse.summary) {\r\n tui.log.info(colors.primary(`π Plan: ${agentResponse.summary}`));\r\n }\r\n\r\n if (agentResponse.actions.length === 0) {\r\n // No actions usually means it's waiting for user or finished\r\n const reply = await tui.text({\r\n message: \"π€ Shark QA:\",\r\n placeholder: \"Your reply...\"\r\n });\r\n\r\n if (tui.isCancel(reply)) {\r\n keepRunning = false;\r\n } else {\r\n userMessage = reply as string;\r\n }\r\n continue;\r\n }\r\n\r\n for (const action of agentResponse.actions) {\r\n tui.log.info(colors.dim(`Executing: ${action.type}`));\r\n\r\n let result = \"\";\r\n\r\n try {\r\n switch (action.type) {\r\n case 'talk_with_user':\r\n const reply = await tui.text({\r\n message: `π€ ${action.content}`,\r\n });\r\n if (tui.isCancel(reply)) keepRunning = false;\r\n else result = reply as string;\r\n break;\r\n\r\n case 'use_mcp_tool':\r\n if (action.tool_name) {\r\n tui.log.info(`π§ MCP Tool: ${colors.bold(action.tool_name)}`);\r\n let args = {};\r\n try {\r\n args = typeof action.tool_args === 'string'\r\n ? JSON.parse(action.tool_args)\r\n : (action.tool_args || {});\r\n } catch (e) {\r\n tui.log.warning('Failed to parse tool_args, using empty object');\r\n }\r\n const mcpResult = await mcpClient.callTool(action.tool_name, args);\r\n result = JSON.stringify(mcpResult);\r\n // Brief preview\r\n tui.log.success(`Result: ${result.substring(0, 100)}...`);\r\n }\r\n break;\r\n\r\n case 'create_file':\r\n if (action.path && action.content) {\r\n const fullPath = path.resolve(process.cwd(), action.path);\r\n fs.writeFileSync(fullPath, action.content);\r\n tui.log.success(`File created: ${action.path}`);\r\n result = \"File created successfully.\";\r\n }\r\n break;\r\n\r\n case 'read_file':\r\n result = handleReadFile(action.path || '');\r\n break;\r\n\r\n case 'run_command':\r\n // Safety check?\r\n const confirm = await tui.confirm({ message: `Run command: ${action.command}?` });\r\n if (confirm && action.command) {\r\n result = await handleRunCommand(action.command);\r\n } else {\r\n result = \"Command execution denied by user.\";\r\n }\r\n break;\r\n\r\n default:\r\n result = `Action ${action.type} not fully implemented in local client.`;\r\n }\r\n } catch (e: any) {\r\n result = `Error executing ${action.type}: ${e.message}`;\r\n tui.log.error(result);\r\n }\r\n\r\n // Feed result back to agent\r\n userMessage = `[Action ${action.type} Result]:\\n${result}\\n\\n`;\r\n }\r\n }\r\n\r\n await mcpClient.close();\r\n tui.outro('π¦ Shark QA Session Ended');\r\n}\r\n"],"mappings":";;;;;;;;;;;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AAGR,IAAM,eAAN,MAAM,cAAa;AAAA,EACtB,OAAe;AAAA,EACE;AAAA,EAET,cAAc;AAClB,SAAK,SAAS,KAAK,KAAK,GAAG,QAAQ,GAAG,UAAU,MAAM;AAAA,EAC1D;AAAA,EAEA,OAAc,cAA4B;AACtC,QAAI,CAAC,cAAa,UAAU;AACxB,oBAAa,WAAW,IAAI,cAAa;AAAA,IAC7C;AACA,WAAO,cAAa;AAAA,EACxB;AAAA,EAEO,OAAa;AAChB,YAAQ,GAAG,qBAAqB,CAAC,UAAU,KAAK,YAAY,OAAO,oBAAoB,CAAC;AACxF,YAAQ,GAAG,sBAAsB,CAAC,WAAW,KAAK,YAAY,QAAQ,qBAAqB,CAAC;AAAA,EAChG;AAAA,EAEQ,YAAY,OAAY,MAAoB;AAEhD,QAAI;AACA,YAAM,aAAY,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG;AAC/D,YAAM,UAAU,KAAK,KAAK,KAAK,QAAQ,SAAS,SAAS,MAAM;AAE/D,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,YAAM,aAAa,iBAAiB,QAAQ,MAAM,QAAQ;AAE1D,YAAM,aAAa;AAAA,IAC5B,oBAAI,KAAK,GAAE,YAAY,CAAC,KAAK,IAAI;AAAA;AAAA,WAEzB,YAAY;AAAA;AAAA,EAErB,UAAU;AAAA;AAAA,UAEF,GAAG,SAAS,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,GAAG,KAAK,CAAC;AAAA,QAC5C,QAAQ,OAAO;AAAA;AAIX,UAAI,CAAC,GAAG,WAAW,KAAK,MAAM,GAAG;AAC7B,WAAG,UAAU,KAAK,QAAQ,EAAE,WAAW,KAAK,CAAC;AAAA,MACjD;AAEA,SAAG,cAAc,SAAS,YAAY,OAAO;AAE7C,cAAQ,MAAM,IAAI;AAClB,cAAQ,MAAM,OAAO,MAAM,oDAA6C,CAAC;AACzE,cAAQ,MAAM,OAAO,IAAI,kCAAkC,OAAO,EAAE,CAAC;AACrE,cAAQ,MAAM,OAAO,IAAI,+CAA+C,CAAC;AACzE,cAAQ,MAAM,OAAO,MAAM,aAAa,YAAY,EAAE,CAAC;AACvD,cAAQ,MAAM,IAAI;AAAA,IAEtB,SAAS,cAAc;AACnB,cAAQ,MAAM,2CAA2C,YAAY;AACrE,cAAQ,MAAM,mBAAmB,KAAK;AAAA,IAC1C,UAAE;AACE,cAAQ,KAAK,CAAC;AAAA,IAClB;AAAA,EACJ;AACJ;AAEO,IAAM,eAAe,aAAa,YAAY;;;AC9DrD,SAAS,WAAAA,gBAAe;;;ACNxB,SAAS,eAAe;;;ACAxB,OAAOC,SAAQ;AACf,OAAOC,WAAU;;;ACDjB,SAAS,SAAS;AAQX,IAAM,gBAAgB,EAAE,KAAK;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAIM,IAAM,oBAAoB,EAAE,KAAK;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAIM,IAAM,kBAAkB,EAAE,KAAK;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAIM,IAAM,iBAAiB,EAAE,OAAO;AAAA,EACnC,WAAW,EAAE,OAAO,EAAE,KAAK;AAAA,EAC3B,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC7B,WAAW,cAAc,QAAQ,SAAS;AAAA,EAC1C,cAAc,kBAAkB,QAAQ,mBAAmB;AAAA,EAC3D,aAAa,gBAAgB,QAAQ,SAAS;AAAA,EAC9C,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EACjC,gBAAgB,EAAE,OAAO,EAAE,SAAS;AAAA,EACpC,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA;AAAA,EACzD,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA;AAAA,EAEzC,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS;AAC7C,CAAC;;;ADlDM,IAAM,kBAAN,MAAM,iBAAgB;AAAA,EACzB,OAAe;AAAA,EACE,WAAW;AAAA,EACX,cAAc;AAAA,EAEvB,cAAc;AAAA,EAAE;AAAA,EAExB,OAAc,cAA+B;AACzC,QAAI,CAAC,iBAAgB,UAAU;AAC3B,uBAAgB,WAAW,IAAI,iBAAgB;AAAA,IACnD;AACA,WAAO,iBAAgB;AAAA,EAC3B;AAAA,EAEQ,cAAsB;AAC1B,WAAOC,MAAK,KAAK,QAAQ,IAAI,GAAG,KAAK,QAAQ;AAAA,EACjD;AAAA,EAEQ,iBAAyB;AAC7B,WAAOA,MAAK,KAAK,QAAQ,IAAI,GAAG,KAAK,WAAW;AAAA,EACpD;AAAA,EAEA,MAAa,KAAK,OAAqC;AAEnD,UAAM,SAAS,eAAe,UAAU,KAAK;AAC7C,QAAI,CAAC,OAAO,SAAS;AACjB,YAAM,IAAI,MAAM,2BAA2B,OAAO,MAAM,OAAO,EAAE;AAAA,IACrE;AAEA,UAAM,WAAW,KAAK,YAAY;AAClC,UAAM,UAAU,KAAK,eAAe;AACpC,UAAM,OAAO,KAAK,UAAU,OAAO,MAAM,MAAM,CAAC;AAEhD,QAAI;AAEA,YAAMC,IAAG,UAAU,SAAS,MAAM,OAAO;AAGzC,YAAMA,IAAG,OAAO,SAAS,QAAQ;AAAA,IACrC,SAAS,OAAY;AACjB,YAAM,IAAI,MAAM,6CAA6C,MAAM,OAAO,EAAE;AAAA,IAChF;AAAA,EACJ;AAAA,EAEA,MAAa,OAAsC;AAC/C,UAAM,WAAW,KAAK,YAAY;AAElC,QAAI;AAEA,UAAI;AACA,cAAMA,IAAG,OAAO,QAAQ;AAAA,MAC5B,QAAQ;AACJ,eAAO;AAAA,MACX;AAEA,YAAM,UAAU,MAAMA,IAAG,SAAS,UAAU,OAAO;AACnD,YAAM,OAAO,KAAK,MAAM,OAAO;AAE/B,YAAM,SAAS,eAAe,UAAU,IAAI;AAC5C,UAAI,OAAO,SAAS;AAChB,eAAO,OAAO;AAAA,MAClB,OAAO;AACH,gBAAQ,KAAK,OAAO,QAAQ,mDAAyC,OAAO,MAAM,OAAO,EAAE,CAAC;AAC5F,eAAO;AAAA,MACX;AAAA,IAEJ,SAAS,OAAY;AACjB,cAAQ,KAAK,OAAO,QAAQ,gDAAsC,MAAM,OAAO,EAAE,CAAC;AAClF,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA,EAGA,MAAa,iBAAgD;AACzD,WAAO,MAAM,KAAK,KAAK;AAAA,EAC3B;AACJ;AAEO,IAAM,kBAAkB,gBAAgB,YAAY;;;AD/E3D,SAAS,kBAAkB;AAGpB,IAAM,aAAa,YAAY;AAClC,MAAI,MAAM,8BAA8B;AAGxC,QAAM,gBAAgB,MAAM,gBAAgB,KAAK;AACjD,MAAI,eAAe;AAEf,QAAI,IAAI,KAAK,OAAO,IAAI,0CAA0C,CAAC;AACnE,QAAI,IAAI,KAAK,cAAO,OAAO,QAAQ,4BAA4B,CAAC,EAAE;AAClE,QAAI,IAAI,QAAQ,eAAe,OAAO,MAAM,cAAc,WAAW,CAAC,EAAE;AACxE,QAAI,IAAI,QAAQ,eAAe,OAAO,UAAU,cAAc,YAAY,CAAC,EAAE;AAC7E,QAAI,IAAI,QAAQ,eAAe,OAAO,IAAI,IAAI,KAAK,cAAc,WAAW,EAAE,eAAe,CAAC,CAAC,EAAE;AACjG,QAAI,IAAI,KAAK,OAAO,IAAI,0CAA0C,CAAC;AAEnE,UAAM,SAAS,MAAM,IAAI,OAAO;AAAA,MAC5B,SAAS;AAAA,MACT,SAAS;AAAA,QACL,EAAE,OAAO,UAAU,OAAO,wBAAiB;AAAA,QAC3C,EAAE,OAAO,aAAa,OAAO,wCAA8B;AAAA,QAC3D,EAAE,OAAO,QAAQ,OAAO,cAAS;AAAA,MACrC;AAAA,IACJ,CAAC;AAED,QAAI,IAAI,SAAS,MAAM,KAAK,WAAW,QAAQ;AAC3C,UAAI,MAAM,0BAAmB;AAC7B;AAAA,IACJ;AAEA,QAAI,WAAW,UAAU;AACrB,UAAI,IAAI,QAAQ,oBAAoB,OAAO,QAAQ,cAAc,WAAW,CAAC,KAAK;AAElF,UAAI,MAAM,kDAAkD;AAC5D;AAAA,IACJ;AAAA,EAGJ;AAGA,QAAM,cAAc,MAAM,IAAI,KAAK;AAAA,IAC/B,SAAS;AAAA,IACT,aAAa;AAAA,IACb,UAAU,CAAC,UAAU;AACjB,UAAI,CAAC,MAAO,QAAO;AACnB,UAAI,MAAM,KAAK,EAAE,SAAS,EAAG,QAAO;AAAA,IACxC;AAAA,EACJ,CAAC;AAED,MAAI,IAAI,SAAS,WAAW,GAAG;AAC3B,QAAI,MAAM,2BAA2B;AACrC;AAAA,EACJ;AAGA,QAAM,mBAAmB,cAAc,QAAQ,IAAI,YAAU;AAAA,IACzD,OAAO;AAAA,IACP,OAAO,UAAU,YAAY,yBACzB,UAAU,WAAW,YACjB,MAAM,OAAO,CAAC,EAAE,YAAY,IAAI,MAAM,MAAM,CAAC;AAAA,EACzD,EAAE;AAEF,QAAM,YAAY,MAAM,IAAI,OAAO;AAAA,IAC/B,SAAS;AAAA,IACT,SAAS;AAAA,EACb,CAAC;AAED,MAAI,IAAI,SAAS,SAAS,GAAG;AACzB,QAAI,MAAM,2BAA2B;AACrC;AAAA,EACJ;AAGA,QAAM,UAAU,IAAI,QAAQ;AAC5B,UAAQ,MAAM,kCAAkC;AAEhD,MAAI;AACA,UAAM,WAAW;AAAA,MACb,WAAW,WAAW;AAAA,MACtB;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,aAAa;AAAA,MACb,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC,WAAW,CAAC;AAAA,MACZ,UAAU;AAAA,QACN,eAAe;AAAA,QACf,SAAS;AAAA,MACb;AAAA,IACJ;AAEA,UAAM,gBAAgB,KAAK,QAAQ;AACnC,YAAQ,KAAK,2BAA2B;AAExC,QAAI,IAAI,QAAQ,WAAW,OAAO,QAAQ,WAAqB,CAAC,4BAA4B;AAC5F,QAAI,IAAI,QAAQ,oBAAoB,OAAO,IAAI,SAAS,SAAS,CAAC,EAAE;AACpE,QAAI,MAAM,oEAAoE;AAAA,EAClF,SAAS,OAAY;AACjB,YAAQ,KAAK,0BAA0B,CAAC;AACxC,QAAI,IAAI,MAAM,MAAM,OAAO;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAClB;AACJ;AAEO,IAAM,cAAc,IAAI,QAAQ,MAAM,EACxC,YAAY,gCAAgC,EAC5C,OAAO,UAAU;;;AGjGf,IAAM,2BAA2B;;;ACfxC,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAEV,IAAM,aAAN,MAAiB;AAAA,EACpB,OAAe,UAAUA,MAAK,QAAQ,QAAQ,IAAI,GAAG,iBAAiB;AAAA,EACtE,OAAe,UAAU;AAAA;AAAA,EAEzB,OAAO,OAAO;AACV,QAAI;AACA,MAAAD,IAAG,cAAc,KAAK,SAAS,uCAAsC,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,CAAQ;AAAA,IACzG,SAAS,GAAG;AACR,cAAQ,MAAM,mCAAmC,CAAC;AAAA,IACtD;AAAA,EACJ;AAAA,EAEA,OAAO,IAAI,UAAkB,SAAiB,MAAY;AACtD,QAAI,CAAC,KAAK,QAAS;AAEnB,QAAI;AACA,YAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AACzC,UAAI,WAAW,IAAI,SAAS,MAAM,SAAS,YAAY,CAAC,KAAK,OAAO;AAAA;AACpE,UAAI,SAAS,QAAW;AACpB,YAAI,OAAO,SAAS,UAAU;AAC1B,sBAAY,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI;AAAA,QAChD,OAAO;AACH,sBAAY,OAAO,IAAI,IAAI;AAAA,QAC/B;AAAA,MACJ;AACA,kBAAY,IAAI,OAAO,EAAE,IAAI;AAE7B,MAAAA,IAAG,eAAe,KAAK,SAAS,QAAQ;AAAA,IAC5C,SAAS,GAAG;AAAA,IAEZ;AAAA,EACJ;AACJ;;;AC3BO,IAAM,YAAN,MAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASnB,MAAM,oBACF,KACA,gBACA,SACA,YAA0B,CAAC,GACd;AACb,UAAM,EAAE,SAAS,YAAY,QAAQ,IAAI;AAEzC,eAAW,IAAI,OAAO,uBAAuB,GAAG,IAAI;AAAA,MAChD;AAAA,MACA,SAAS;AAAA,IACb,CAAC;AAED,QAAI;AACA,YAAM,WAAW,MAAM,MAAM,KAAK;AAAA,QAC9B,QAAQ;AAAA,QACR,SAAS;AAAA,UACL,GAAG;AAAA,UACH,gBAAgB;AAAA,QACpB;AAAA,QACA,MAAM,KAAK,UAAU,cAAc;AAAA,MACvC,CAAC;AAED,iBAAW,IAAI,OAAO,oBAAoB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAElF,YAAM,kBAA0C,CAAC;AACjD,eAAS,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAAE,wBAAgB,GAAG,IAAI;AAAA,MAAO,CAAC;AAC1E,iBAAW,IAAI,OAAO,oBAAoB,eAAe;AAEzD,UAAI,CAAC,SAAS,IAAI;AACd,cAAM,YAAY,MAAM,SAAS,KAAK;AACtC,mBAAW,IAAI,OAAO,uBAAuB,SAAS;AACtD,cAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,IAAI,SAAS,UAAU,MAAM,SAAS,EAAE;AAAA,MAClG;AAEA,UAAI,CAAC,SAAS,MAAM;AAChB,cAAM,IAAI,MAAM,uBAAuB;AAAA,MAC3C;AAEA,YAAM,SAAS,SAAS,KAAK,UAAU;AACvC,YAAM,UAAU,IAAI,YAAY;AAChC,UAAI,SAAS;AACb,UAAI,cAAc;AAClB,UAAI,WAAgB,CAAC;AAErB,aAAO,MAAM;AACT,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAE1C,YAAI,MAAM;AACN;AAAA,QACJ;AAGA,kBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAGhD,cAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,iBAAS,MAAM,IAAI,KAAK;AAExB,mBAAW,QAAQ,OAAO;AACtB,cAAI,KAAK,WAAW,OAAO,GAAG;AAC1B,kBAAM,OAAO,KAAK,MAAM,CAAC,EAAE,KAAK;AAEhC,gBAAI,SAAS,UAAU;AACnB,yBAAW,IAAI,OAAO,0BAA0B,EAAE,aAAa,SAAS,CAAC;AAEzE,kBAAI,YAAY;AACZ,2BAAW,aAAa,QAAQ;AAAA,cACpC;AACA;AAAA,YACJ;AAEA,gBAAI;AACA,oBAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,oBAAM,QAAQ,OAAO,WAAW,OAAO,WAAW;AAClD,6BAAe;AAGf,kBAAI,OAAO,iBAAiB;AACxB,yBAAS,kBAAkB,OAAO;AAAA,cACtC;AAEA,kBAAI,SAAS;AACT,wBAAQ,KAAK;AAAA,cACjB;AAAA,YACJ,SAAS,YAAY;AAEjB,6BAAe;AACf,kBAAI,SAAS;AACT,wBAAQ,IAAI;AAAA,cAChB;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAEA,iBAAW,IAAI,OAAO,0BAA0B,EAAE,aAAa,SAAS,CAAC;AAGzE,UAAI,YAAY;AACZ,mBAAW,aAAa,QAAQ;AAAA,MACpC;AAAA,IAEJ,SAAS,OAAO;AACZ,iBAAW,IAAI,OAAO,gBAAgB,KAAK;AAC3C,UAAI,SAAS;AACT,gBAAQ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,MACrE,OAAO;AACH,cAAM;AAAA,MACV;AAAA,IACJ;AAAA,EACJ;AACJ;AAEO,IAAM,YAAY,IAAI,UAAU;;;ACnIvC,SAAS,KAAAE,UAAS;AAIX,IAAM,oBAAoBC,GAAE,OAAO;AAAA,EACtC,MAAMA,GAAE,KAAK,CAAC,eAAe,eAAe,eAAe,kBAAkB,cAAc,aAAa,eAAe,eAAe,cAAc,CAAC;AAAA,EACrJ,MAAMA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA;AAAA,EACrC,SAASA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACxC,gBAAgBA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC/C,SAASA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACxC,WAAWA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC1C,WAAWA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA;AAC9C,CAAC;AAKM,IAAM,qBAAqBA,GAAE,OAAO;AAAA,EACvC,SAASA,GAAE,OAAO;AAAA,EAClB,aAAaA,GAAE,OAAO;AAAA,EACtB,UAAUA,GAAE,QAAQ;AACxB,CAAC;AAGM,IAAM,sBAAsBA,GAAE,OAAO;AAAA,EACxC,SAASA,GAAE,MAAM,iBAAiB;AAAA,EAClC,UAAUA,GAAE,MAAM,kBAAkB,EAAE,SAAS;AAAA,EAC/C,SAASA,GAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAG7B,SAASA,GAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,iBAAiBA,GAAE,OAAO,EAAE,SAAS;AACzC,CAAC;AAOM,SAAS,mBAAmB,aAAqC;AACpE,aAAW,IAAI,UAAU,0BAA0B,EAAE,SAAS,OAAO,YAAY,CAAC;AAElF,MAAI,YAAiB,CAAC;AACtB,MAAI;AAGJ,MAAI,OAAO,gBAAgB,UAAU;AACjC,eAAW,IAAI,UAAU,eAAe,EAAE,QAAQ,YAAY,OAAO,CAAC;AACtE,QAAI;AACA,kBAAY,iBAAiB,WAAW;AAAA,IAC5C,SAAS,GAAG;AACR,iBAAW,IAAI,UAAU,uBAAuB,EAAE,OAAQ,EAAY,QAAQ,CAAC;AAE/E,aAAO;AAAA,QACH,SAAS,CAAC;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,MAAM;AAAA,QACV,CAAC;AAAA,QACD,SAAS;AAAA,MACb;AAAA,IACJ;AAAA,EACJ,WAES,OAAO,gBAAgB,YAAY,gBAAgB,MAAM;AAC9D,UAAM,UAAU;AAChB,sBAAkB,QAAQ;AAE1B,eAAW,IAAI,UAAU,eAAe;AAAA,MACpC,YAAY,CAAC,CAAC,QAAQ;AAAA,MACtB,YAAY,CAAC,CAAC,QAAQ;AAAA,MACtB,aAAa,OAAO,QAAQ;AAAA,IAChC,CAAC;AAGD,UAAM,gBAAgB,QAAQ,WAAW,QAAQ;AACjD,QAAI,iBAAiB,OAAO,kBAAkB,UAAU;AACpD,UAAI;AAEA,cAAM,eAAe,iBAAiB,aAAa;AAEnD,YAAI,OAAO,iBAAiB,YAAY,iBAAiB,MAAM;AAC3D,sBAAY;AACZ,qBAAW,IAAI,UAAU,qBAAqB,EAAE,MAAM,OAAO,KAAK,SAAS,EAAE,CAAC;AAAA,QAClF,OAAO;AAEH,sBAAY;AACZ,qBAAW,IAAI,UAAU,0BAA0B;AAAA,QACvD;AAAA,MACJ,SAAS,GAAG;AAER,oBAAY;AACZ,mBAAW,IAAI,UAAU,4CAA4C,EAAE,OAAQ,EAAY,QAAQ,CAAC;AAAA,MACxG;AAAA,IACJ,OAAO;AACH,kBAAY;AAAA,IAChB;AAGA,QAAI,CAAC,UAAU,SAAS;AACpB,kBAAY;AAAA,IAChB;AAAA,EACJ;AAIA,MAAI,CAAC,UAAU,SAAS;AACpB,eAAW,IAAI,UAAU,yCAAyC;AAElE,WAAO;AAAA,MACH;AAAA,MACA,SAAS,CAAC;AAAA,QACN,MAAM;AAAA,QACN,SAAS,UAAU,WAAW,KAAK,UAAU,SAAS;AAAA,QACtD,MAAM;AAAA,MACV,CAAC;AAAA,MACD,SAAS,UAAU;AAAA,IACvB;AAAA,EACJ;AAIA,QAAM,SAAS;AAAA,IACX,SAAS,UAAU;AAAA,IACnB,UAAU,UAAU,YAAY,CAAC;AAAA,IACjC,SAAS,UAAU,WAAW;AAAA,IAC9B;AAAA,IACA,SAAS,UAAU,WAAW;AAAA;AAAA,EAClC;AAGA,aAAW,IAAI,UAAU,4BAA4B,EAAE,aAAa,OAAO,QAAQ,OAAO,CAAC;AAE3F,MAAI;AACA,WAAO,oBAAoB,MAAM,MAAM;AAAA,EAC3C,SAAS,GAAG;AACR,eAAW,IAAI,UAAU,4BAA4B,EAAE,OAAQ,EAAY,QAAQ,CAAC;AACpF,UAAM;AAAA,EACV;AACJ;AAEA,SAAS,iBAAiB,KAAkB;AACxC,MAAI;AACA,WAAO,KAAK,MAAM,GAAG;AAAA,EACzB,SAAS,GAAG;AAER,UAAM,YAAY,IAAI,QAAQ,GAAG;AACjC,QAAI,cAAc,GAAI,OAAM;AAE5B,QAAI,UAAU;AACd,QAAI,WAAW;AACf,QAAI,SAAS;AAEb,aAAS,IAAI,WAAW,IAAI,IAAI,QAAQ,KAAK;AACzC,YAAM,OAAO,IAAI,CAAC;AAElB,UAAI,QAAQ;AACR,iBAAS;AACT;AAAA,MACJ;AAEA,UAAI,SAAS,MAAM;AACf,iBAAS;AACT;AAAA,MACJ;AAEA,UAAI,SAAS,KAAK;AACd,mBAAW,CAAC;AACZ;AAAA,MACJ;AAEA,UAAI,CAAC,UAAU;AACX,YAAI,SAAS,IAAK;AAAA,iBACT,SAAS,KAAK;AACnB;AACA,cAAI,YAAY,GAAG;AAEf,kBAAM,gBAAgB,IAAI,UAAU,WAAW,IAAI,CAAC;AACpD,gBAAI;AACA,qBAAO,KAAK,MAAM,aAAa;AAAA,YACnC,SAAS,QAAQ;AAEb,oBAAM;AAAA,YACV;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AACA,UAAM;AAAA,EACV;AACJ;;;ACxLO,IAAM,sBAAN,MAAM,qBAAoB;AAAA,EAC7B,OAAe;AAAA,EAEP,cAAc;AAAA,EAAE;AAAA,EAExB,OAAc,cAAmC;AAC7C,QAAI,CAAC,qBAAoB,UAAU;AAC/B,2BAAoB,WAAW,IAAI,qBAAoB;AAAA,IAC3D;AACA,WAAO,qBAAoB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,mBAAmB,WAAmB,gBAAuC;AAC/E,UAAM,QAAQ,MAAM,gBAAgB,KAAK;AACzC,QAAI,CAAC,OAAO;AACR,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC7E;AAGA,QAAI,CAAC,MAAM,eAAe;AACtB,YAAM,gBAAgB,CAAC;AAAA,IAC3B;AAEA,UAAM,cAAc,SAAS,IAAI;AACjC,UAAM,gBAAgB,KAAK,KAAK;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAkB,WAAgD;AACpE,UAAM,QAAQ,MAAM,gBAAgB,KAAK;AACzC,QAAI,CAAC,SAAS,CAAC,MAAM,eAAe;AAChC,aAAO;AAAA,IACX;AAEA,WAAO,MAAM,cAAc,SAAS;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,oBAAoB,WAAkC;AACxD,UAAM,QAAQ,MAAM,gBAAgB,KAAK;AACzC,QAAI,CAAC,SAAS,CAAC,MAAM,eAAe;AAChC;AAAA,IACJ;AAEA,WAAO,MAAM,cAAc,SAAS;AACpC,UAAM,gBAAgB,KAAK,KAAK;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,wBAAuC;AACzC,UAAM,QAAQ,MAAM,gBAAgB,KAAK;AACzC,QAAI,CAAC,OAAO;AACR;AAAA,IACJ;AAEA,UAAM,gBAAgB,CAAC;AACvB,UAAM,gBAAgB,KAAK,KAAK;AAAA,EACpC;AACJ;AAEO,IAAM,sBAAsB,oBAAoB,YAAY;;;AC5EnE,eAAsB,iBAAkC;AACpD,QAAM,gBAAgB,cAAc,YAAY;AAChD,QAAM,SAAS,cAAc,UAAU;AACvC,QAAM,QAAQ,OAAO;AAErB,MAAI,CAAC,OAAO;AACR,UAAM,IAAI;AAAA,MACN;AAAA,IAEJ;AAAA,EACJ;AAEA,SAAO;AACX;;;ACZA,IAAM,aAAa;AAInB,IAAM,WAAW,QAAQ,IAAI,yBAAyB;AAiBtD,eAAsB,wBAClB,QACA,UAA0B,CAAC,GACL;AACtB,QAAM,EAAE,SAAS,SAAS,WAAW,IAAI;AAGzC,QAAM,QAAQ,MAAM,eAAe;AAGnC,QAAM,QAAQ,MAAM,aAAa,SAAS,KAAK;AAC/C,MAAI,CAAC,OAAO;AACR,UAAM,IAAI,MAAM,4CAA4C,KAAK,8BAA8B;AAAA,EACnG;AAGA,QAAM,yBAAyB,MAAM,oBAAoB,kBAAkB,UAAU;AAGrF,QAAM,iBAAiB;AAAA,IACnB,aAAa;AAAA,IACb,WAAW;AAAA,IACX,qBAAqB;AAAA;AAAA,IACrB,uBAAuB;AAAA,IACvB,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,EACrB;AAGA,QAAM,eAAe,WAAW;AAChC,QAAM,WAAW,GAAG,wBAAwB,aAAa,YAAY;AAGrE,QAAM,UAAU;AAAA,IACZ,iBAAiB,UAAU,KAAK;AAAA,IAChC,gBAAgB;AAAA,EACpB;AAGA,MAAI,cAAc;AAClB,MAAI,cAAmB,CAAC;AAExB,QAAM,UAAU;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACI,SAAS,CAAC,UAAU;AAChB,uBAAe;AACf,YAAI,SAAS;AACT,kBAAQ,KAAK;AAAA,QACjB;AAAA,MACJ;AAAA,MACA,YAAY,OAAO,YAAY;AAE3B,sBAAc;AAAA,UACV,SAAS,WAAW;AAAA,UACpB,iBAAiB;AAAA;AAAA,QACrB;AAAA,MACJ;AAAA,MACA,SAAS,CAAC,UAAU;AAChB,cAAM;AAAA,MACV;AAAA,IACJ;AAAA,EACJ;AAGA,QAAM,iBAAiB,mBAAmB,WAAW;AAGrD,MAAI,eAAe,iBAAiB;AAChC,UAAM,oBAAoB,mBAAmB,YAAY,eAAe,eAAe;AAAA,EAC3F;AAGA,MAAI,YAAY;AACZ,eAAW,cAAc;AAAA,EAC7B;AAEA,SAAO;AACX;AAOA,eAAsB,6BAA4C;AAC9D,MAAI,MAAM,kCAA2B;AAErC,QAAM,SAAS,MAAM,IAAI,KAAK;AAAA,IAC1B,SAAS;AAAA,IACT,aAAa;AAAA,IACb,UAAU,CAAC,UAAU;AACjB,UAAI,CAAC,SAAS,MAAM,SAAS,GAAI,QAAO;AAAA,IAC5C;AAAA,EACJ,CAAC;AAED,MAAI,IAAI,SAAS,MAAM,GAAG;AACtB,QAAI,MAAM,WAAW;AACrB;AAAA,EACJ;AAEA,QAAM,UAAU,IAAI,QAAQ;AAC5B,UAAQ,MAAM,2CAAoC;AAElD,MAAI,eAAe;AAEnB,MAAI;AACA,UAAM,wBAAwB,QAAkB;AAAA,MAC5C,SAAS,CAAC,UAAU;AAChB,wBAAgB;AAEhB,YAAI;AAEA,cAAI,aAAa,KAAK,EAAE,WAAW,GAAG,GAAG;AACrC,oBAAQ,QAAQ,OAAO,IAAI,8BAA8B,CAAC;AAAA,UAC9D,OAAO;AACH,oBAAQ,QAAQ,OAAO,IAAI,aAAa,CAAC;AAAA,UAC7C;AAAA,QACJ,SAAS,GAAG;AAAA,QAEZ;AAAA,MACJ;AAAA,MACA,YAAY,OAAO,aAAa;AAC5B,gBAAQ,KAAK,mBAAmB;AAGhC,YAAI,SAAS,SAAS;AAClB,cAAI,IAAI,KAAK,OAAO,OAAO,SAAS,OAAO,CAAC;AAAA,QAChD;AAGA,YAAI,SAAS,WAAW,SAAS,QAAQ,SAAS,GAAG;AACjD,qBAAW,UAAU,SAAS,SAAS;AAGnC,gBAAI,OAAO,SAAS,kBAAkB;AAClC,kBAAI,IAAI,KAAK,OAAO,MAAM,qBAAc,CAAC;AACzC,sBAAQ,IAAI,OAAO,OAAO;AAAA,YAO9B,OAGK;AACD,kBAAI,IAAI,QAAQ;AAAA,2BAAuB,OAAO,IAAI,KAAK,OAAO,KAAK,OAAO,QAAQ,SAAS,CAAC,EAAE;AAG9F,kBAAI,OAAO,SAAS;AAChB,wBAAQ,IAAI,OAAO,IAAI,yBAAyB,CAAC;AACjD,wBAAQ,IAAI,OAAO,QAAQ,UAAU,GAAG,GAAG,KAAK,OAAO,QAAQ,SAAS,MAAM,QAAQ,GAAG;AACzF,wBAAQ,IAAI,OAAO,IAAI,yBAAyB,CAAC;AAAA,cACrD;AAEA,oBAAM,UAAU,MAAM,IAAI,QAAQ;AAAA,gBAC9B,SAAS,kBAAkB,OAAO,IAAI,KAAK,OAAO,IAAI;AAAA,gBACtD,QAAQ;AAAA,gBACR,UAAU;AAAA,cACd,CAAC;AAED,kBAAI,SAAS;AAGT,oBAAI,IAAI,QAAQ,2BAAsB,OAAO,IAAI,WAAW;AAAA,cAChE,OAAO;AACH,oBAAI,IAAI,MAAM,uBAAkB;AAAA,cACpC;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AACA,YAAI,SAAS,QAAQ;AACjB,cAAI,IAAI,KAAK,gBAAgB,SAAS,OAAO,UAAU,CAAC,EAAE;AAAA,QAC9D;AAAA,MACJ;AAAA,IACJ,CAAC;AAED,QAAI,MAAM,kBAAkB;AAAA,EAChC,SAAS,OAAY;AACjB,YAAQ,KAAK,gBAAW,CAAC;AACzB,QAAI,IAAI,MAAM,MAAM,OAAO;AAC3B,UAAM;AAAA,EACV;AACJ;;;AChNA,OAAOC,SAAQ;;;ACRf,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAO,QAAQ;AAQR,SAAS,gBAAgB,SAAyB;AACrD,MAAI;AACA,UAAM,WAAWC,MAAK,QAAQ,QAAQ,IAAI,GAAG,OAAO;AACpD,QAAI,CAACC,IAAG,WAAW,QAAQ,EAAG,QAAO,oBAAoB,OAAO;AAEhE,UAAM,QAAQA,IAAG,YAAY,UAAU,EAAE,eAAe,KAAK,CAAC;AAC9D,WAAO,MAAM,IAAI,UAAQ;AACrB,aAAO,GAAG,KAAK,YAAY,IAAI,UAAU,QAAQ,IAAI,KAAK,IAAI;AAAA,IAClE,CAAC,EAAE,KAAK,IAAI;AAAA,EAChB,SAAS,GAAQ;AACb,WAAO,wBAAwB,EAAE,OAAO;AAAA,EAC5C;AACJ;AAEO,SAAS,eAAe,UAA0B;AACrD,MAAI;AACA,UAAM,WAAWD,MAAK,QAAQ,QAAQ,IAAI,GAAG,QAAQ;AACrD,QAAI,CAACC,IAAG,WAAW,QAAQ,EAAG,QAAO,eAAe,QAAQ;AAG5D,UAAM,QAAQA,IAAG,SAAS,QAAQ;AAClC,QAAI,MAAM,OAAO,MAAM,KAAM,QAAO,kCAAkC,MAAM,IAAI;AAEhF,WAAOA,IAAG,aAAa,UAAU,OAAO;AAAA,EAC5C,SAAS,GAAQ;AACb,WAAO,uBAAuB,EAAE,OAAO;AAAA,EAC3C;AACJ;AAEO,SAAS,iBAAiB,SAAyB;AACtD,MAAI;AAGA,UAAM,UAAU,GAAG,KAAK,SAAS,EAAE,KAAK,KAAK,CAAC;AAC9C,QAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,WAAO,QAAQ,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI;AAAA,EACzC,SAAS,GAAQ;AACb,WAAO,0BAA0B,EAAE,OAAO;AAAA,EAC9C;AACJ;AAEO,SAAS,kBAAkB,UAAkB,YAAoB,eAAuBC,MAAmB;AAC9G,MAAI,CAACD,IAAG,WAAW,QAAQ,GAAG;AAC1B,IAAAC,KAAI,IAAI,MAAM,2CAAsC,QAAQ,EAAE;AAC9D,WAAO;AAAA,EACX;AAEA,QAAM,qBAAqBD,IAAG,aAAa,UAAU,OAAO;AAI5D,MAAI,CAAC,mBAAmB,SAAS,aAAa,GAAG;AAC7C,IAAAC,KAAI,IAAI,MAAM,sCAAiC,QAAQ,yBAAyB;AAChF,YAAQ,IAAI,OAAO,IAAI,iCAAiC,CAAC;AACzD,YAAQ,IAAI,cAAc,UAAU,GAAG,GAAG,IAAI,KAAK;AACnD,WAAO;AAAA,EACX;AAGA,QAAM,cAAc,mBAAmB,MAAM,aAAa,EAAE,SAAS;AACrE,MAAI,cAAc,GAAG;AACjB,IAAAA,KAAI,IAAI,MAAM,kCAA6B,WAAW,mBAAmB,QAAQ,yBAAyB;AAC1G,WAAO;AAAA,EACX;AAGA,QAAM,iBAAiB,mBAAmB,QAAQ,eAAe,UAAU;AAC3E,EAAAD,IAAG,cAAc,UAAU,cAAc;AACzC,EAAAC,KAAI,IAAI,QAAQ,iCAA4B,QAAQ,EAAE;AACtD,SAAO;AACX;AAEA,eAAsB,iBAAiB,SAAkC;AACrE,QAAM,EAAE,MAAM,IAAI,MAAM,OAAO,eAAoB;AACnD,MAAI;AACA,QAAI,IAAI,KAAK,wBAAiB,OAAO,IAAI,OAAO,CAAC,EAAE;AAMnD,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC5B,YAAM,QAAQ,MAAM,SAAS;AAAA,QACzB,OAAO;AAAA,QACP,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,QAChC,KAAK,QAAQ,IAAI;AAAA,MACrB,CAAC;AAED,UAAI,SAAS;AACb,UAAI,SAAS;AAGb,YAAM,QAAQ,WAAW,MAAM;AAC3B,cAAM,KAAK;AACX,gBAAQ;AAAA;AAAA,EAA8D,MAAM;AAAA,EAAK,MAAM,EAAE;AAAA,MAC7F,GAAG,IAAI,KAAK,GAAI;AAEhB,YAAM,OAAO,GAAG,QAAQ,CAAC,SAAS;AAC9B,cAAM,QAAQ,KAAK,SAAS;AAC5B,kBAAU;AAAA,MAEd,CAAC;AAED,YAAM,OAAO,GAAG,QAAQ,CAAC,SAAS;AAC9B,kBAAU,KAAK,SAAS;AAAA,MAC5B,CAAC;AAED,YAAM,GAAG,SAAS,CAAC,SAAS;AACxB,qBAAa,KAAK;AAClB,YAAI,SAAS,GAAG;AACZ,kBAAQ,OAAO,KAAK,KAAK,4CAA4C;AAAA,QACzE,OAAO;AACH,kBAAQ,iCAAiC,IAAI;AAAA;AAAA,EAAe,MAAM;AAAA;AAAA,EAAc,MAAM,EAAE;AAAA,QAC5F;AAAA,MACJ,CAAC;AAED,YAAM,GAAG,SAAS,CAAC,QAAQ;AACvB,qBAAa,KAAK;AAClB,gBAAQ,4BAA4B,IAAI,OAAO,EAAE;AAAA,MACrD,CAAC;AAAA,IACL,CAAC;AAAA,EAEL,SAAS,GAAQ;AACb,WAAO,4BAA4B,EAAE,OAAO;AAAA,EAChD;AACJ;;;AD1HA,IAAMC,cAAa;AAGnB,IAAMC,YAAW,QAAQ,IAAI,2BAA2B;AAWxD,eAAsB,8BAA8B,UAA4B,CAAC,GAAkB;AAC/F,aAAW,KAAK;AAChB,MAAI,MAAM,sCAA0B;AAGpC,MAAI,kBAAkB;AACtB,MAAI,eAAe,QAAQ;AAE3B,MAAI,CAAC,cAAc;AAEf,UAAM,QAAQC,IAAG,YAAY,QAAQ,IAAI,CAAC;AAC1C,UAAM,kBAAkB,MAAM,KAAK,OAAK,EAAE,SAAS,cAAc,CAAC;AAElE,mBAAe,MAAM,IAAI,KAAK;AAAA,MAC1B,SAAS;AAAA,MACT,cAAc,mBAAmB;AAAA,MACjC,aAAa;AAAA,MACb,UAAU,CAAC,QAAQ;AACf,YAAI,OAAO,CAACA,IAAG,WAAW,GAAG,EAAG,QAAO;AAAA,MAC3C;AAAA,IACJ,CAAC;AAAA,EACL;AAEA,MAAI,IAAI,SAAS,YAAY,EAAG;AAEhC,MAAI,cAAc;AACd,QAAI;AACA,wBAAkBA,IAAG,aAAa,cAAc,OAAO;AACvD,UAAI,IAAI,KAAK,oBAAoB,OAAO,KAAK,YAAY,CAAC,EAAE;AAAA,IAChE,SAAS,GAAG;AACR,UAAI,IAAI,MAAM,4BAA4B,CAAC,EAAE;AAC7C;AAAA,IACJ;AAAA,EACJ,OAAO;AACH,QAAI,IAAI,KAAK,uEAAuE;AAAA,EACxF;AAGA,QAAM,gBAAgB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,EAK1C,eAAe;AAAA;AAAA,MAEX,KAAK,IAAI;AAGX,QAAM,YAAY,eAAe,QAAQ,OAAO;AACpD;AAKA,eAAe,YAAY,gBAAwB,iBAA0B;AACzE,MAAI,aAAa;AACjB,MAAI,YAAY;AAEhB,SAAO,WAAW;AACd,UAAM,UAAU,IAAI,QAAQ;AAC5B,YAAQ,MAAM,qDAAyC;AAEvD,QAAI,eAAe;AACnB,QAAI,eAAqC;AAEzC,QAAI;AAEA,qBAAe,MAAM,iBAAiB,YAAY,CAAC,UAAU;AACzD,wBAAgB;AAChB,YAAI;AACA,cAAI,aAAa,KAAK,EAAE,WAAW,GAAG,GAAG;AACrC,oBAAQ,QAAQ,OAAO,IAAI,8BAA8B,CAAC;AAAA,UAC9D,OAAO;AACH,oBAAQ,QAAQ,OAAO,IAAI,aAAa,CAAC;AAAA,UAC7C;AAAA,QACJ,SAAS,GAAG;AAAA,QAAE;AAAA,MAClB,GAAG,eAAe;AAElB,cAAQ,KAAK,mBAAmB;AAGhC,UAAI,gBAAgB,aAAa,SAAS;AAEtC,YAAI,mBAAmB;AACvB,YAAI,iBAAiB;AAErB,mBAAW,UAAU,aAAa,SAAS;AAEvC,cAAI,OAAO,SAAS,kBAAkB;AAClC,gBAAI,IAAI,KAAK,OAAO,QAAQ,sBAAe,CAAC;AAC5C,oBAAQ,IAAI,OAAO,OAAO;AAC1B,6BAAiB;AAAA,UACrB,WAES,OAAO,SAAS,cAAc;AACnC,gBAAI,IAAI,KAAK,4BAAqB,OAAO,KAAK,OAAO,QAAQ,GAAG,CAAC,EAAE;AACnE,kBAAM,SAAS,gBAAgB,OAAO,QAAQ,GAAG;AACjD,gCAAoB,sBAAsB,OAAO,IAAI;AAAA,EAAe,MAAM;AAAA;AAAA;AAC1E,gBAAI,IAAI,KAAK,OAAO,IAAI,eAAe,CAAC;AAAA,UAC5C,WAES,OAAO,SAAS,aAAa;AAClC,gBAAI,IAAI,KAAK,wBAAiB,OAAO,KAAK,OAAO,QAAQ,EAAE,CAAC,EAAE;AAC9D,kBAAM,SAAS,eAAe,OAAO,QAAQ,EAAE;AAC/C,gCAAoB,qBAAqB,OAAO,IAAI;AAAA,EAAe,MAAM;AAAA;AAAA;AACzE,gBAAI,IAAI,KAAK,OAAO,IAAI,YAAY,CAAC;AAAA,UACzC,WAES,OAAO,SAAS,eAAe;AACpC,gBAAI,IAAI,KAAK,0BAAmB,OAAO,KAAK,OAAO,QAAQ,EAAE,CAAC,EAAE;AAChE,kBAAM,SAAS,iBAAiB,OAAO,QAAQ,EAAE;AACjD,gCAAoB,uBAAuB,OAAO,IAAI;AAAA,EAAe,MAAM;AAAA;AAAA;AAC3E,gBAAI,IAAI,KAAK,OAAO,IAAI,cAAc,CAAC;AAAA,UAC3C,WAES,CAAC,eAAe,eAAe,aAAa,EAAE,SAAS,OAAO,IAAI,GAAG;AAC1E,gBAAI,IAAI,QAAQ;AAAA,2BAAuB,OAAO,IAAI,KAAK,OAAO,KAAK,OAAO,QAAQ,SAAS,CAAC,EAAE;AAG9F,gBAAI,OAAO,SAAS;AAChB,sBAAQ,IAAI,OAAO,IAAI,yBAAyB,CAAC;AACjD,sBAAQ,IAAI,OAAO,QAAQ,UAAU,GAAG,GAAG,IAAI,KAAK;AACpD,sBAAQ,IAAI,OAAO,IAAI,yBAAyB,CAAC;AAAA,YACrD;AAEA,kBAAM,UAAU,MAAM,IAAI,QAAQ;AAAA,cAC9B,SAAS,WAAW,OAAO,IAAI;AAAA,cAC/B,QAAQ;AAAA,cACR,UAAU;AAAA,YACd,CAAC;AAED,gBAAI,SAAS;AACT,kBAAI,OAAO,MAAM;AACb,oBAAI;AACA,sBAAI,OAAO,SAAS,eAAe;AAC/B,oBAAAA,IAAG,cAAc,OAAO,MAAM,OAAO,WAAW,EAAE;AAClD,wBAAI,IAAI,QAAQ,mBAAc,OAAO,IAAI,EAAE;AAC3C,wCAAoB,uBAAuB,OAAO,IAAI;AAAA;AAAA;AAAA,kBAC1D,WAAW,OAAO,SAAS,eAAe;AACtC,wBAAI,OAAO,gBAAgB;AACvB,4BAAM,UAAU,kBAAkB,OAAO,MAAM,OAAO,WAAW,IAAI,OAAO,gBAAgB,GAAG;AAC/F,0CAAoB,uBAAuB,OAAO,IAAI,OAAO,UAAU,YAAY,QAAQ;AAAA;AAAA;AAAA,oBAC/F,OAAO;AACH,sBAAAA,IAAG,cAAc,OAAO,MAAM,OAAO,WAAW,EAAE;AAClD,0BAAI,IAAI,QAAQ,uBAAkB,OAAO,IAAI,EAAE;AAC/C,0CAAoB,uBAAuB,OAAO,IAAI;AAAA;AAAA;AAAA,oBAC1D;AAAA,kBACJ,WAAW,OAAO,SAAS,eAAe;AACtC,oBAAAA,IAAG,WAAW,OAAO,IAAI;AACzB,wBAAI,IAAI,QAAQ,mBAAc,OAAO,IAAI,EAAE;AAC3C,wCAAoB,uBAAuB,OAAO,IAAI;AAAA;AAAA;AAAA,kBAC1D;AAAA,gBACJ,SAAS,GAAQ;AACb,sBAAI,IAAI,MAAM,kBAAa,EAAE,OAAO,EAAE;AACtC,sCAAoB,WAAW,OAAO,IAAI,IAAI,OAAO,IAAI,cAAc,EAAE,OAAO;AAAA;AAAA;AAAA,gBACpF;AAAA,cACJ;AAAA,YACJ,OAAO;AACH,kBAAI,IAAI,MAAM,uBAAkB;AAChC,kCAAoB,WAAW,OAAO,IAAI;AAAA;AAAA;AAAA,YAC9C;AAAA,UACJ;AAAA,QACJ;AAGA,YAAI,kBAAkB;AAMlB,cAAI,gBAAgB;AAChB,kBAAM,YAAY,MAAM,IAAI,KAAK;AAAA,cAC7B,SAAS;AAAA,cACT,aAAa;AAAA,YACjB,CAAC;AACD,gBAAI,IAAI,SAAS,SAAS,GAAG;AACzB,0BAAY;AACZ;AAAA,YACJ;AACA,yBAAa,GAAG,gBAAgB;AAAA;AAAA,cAAmB,SAAS;AAC5D,gBAAI,IAAI,KAAK,OAAO,IAAI,oCAAoC,CAAC;AAAA,UACjE,OAAO;AAEH,yBAAa;AACb,uBAAW,IAAI,UAAU,mCAAmC,EAAE,QAAQ,iBAAiB,OAAO,CAAC;AAC/F,gBAAI,IAAI,KAAK,OAAO,IAAI,oCAAoC,CAAC;AAAA,UACjE;AAAA,QAEJ,WAAW,gBAAgB;AAEvB,gBAAM,YAAY,MAAM,IAAI,KAAK;AAAA,YAC7B,SAAS;AAAA,YACT,aAAa;AAAA,UACjB,CAAC;AACD,cAAI,IAAI,SAAS,SAAS,GAAG;AACzB,wBAAY;AACZ;AAAA,UACJ;AACA,uBAAa;AAAA,QACjB,OAAO;AAEH,cAAI,IAAI,QAAQ,mBAAmB;AACnC,sBAAY;AAAA,QAChB;AAAA,MAEJ,OAAO;AACH,YAAI,IAAI,QAAQ,iCAAiC;AACjD,oBAAY;AAAA,MAChB;AAAA,IAEJ,SAAS,OAAY;AACjB,cAAQ,KAAK,OAAO;AACpB,UAAI,IAAI,MAAM,MAAM,OAAO;AAC3B,kBAAY;AAAA,IAChB;AAAA,EACJ;AACJ;AAMA,eAAe,iBAAiB,QAAgB,SAAkC,SAA0C;AACxH,QAAM,QAAQ,MAAM,eAAe;AACnC,QAAM,QAAQ,MAAM,aAAa,SAAS,KAAK;AAC/C,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,eAAe;AAE3C,QAAM,iBAAiB,MAAM,oBAAoB,kBAAkBF,WAAU;AAE7E,QAAM,UAAU;AAAA,IACZ,aAAa;AAAA,IACb,WAAW;AAAA,IACX,qBAAqB;AAAA,IACrB,uBAAuB;AAAA,IACvB,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,EACrB;AAEA,QAAM,UAAU,WAAWC;AAC3B,QAAM,MAAM,GAAG,wBAAwB,aAAa,OAAO;AAE3D,MAAI,UAAU;AACd,MAAI,MAAW,CAAC;AAEhB,aAAW,IAAI,SAAS,qBAAqB;AAAA,IACzC,SAAS;AAAA,IACT;AAAA,IACA,QAAQ,OAAO,UAAU,GAAG,GAAG;AAAA;AAAA,EACnC,CAAC;AAED,QAAM,UAAU,oBAAoB,KAAK,SAAS,EAAE,iBAAiB,UAAU,KAAK,IAAI,gBAAgB,mBAAmB,GAAG;AAAA,IAC1H,SAAS,CAAC,MAAM;AAAE,iBAAW;AAAG,cAAQ,CAAC;AAAA,IAAG;AAAA,IAC5C,YAAY,CAAC,KAAK,aAAa;AAE3B,YAAM,aAAa,UAAU;AAE7B,iBAAW,IAAI,SAAS,qBAAqB;AAAA,QACzC;AAAA,QACA;AAAA,QACA,eAAe,KAAK;AAAA,MACxB,CAAC;AAED,YAAM;AAAA,QACF,SAAS,OAAO;AAAA,QAChB,iBAAiB,cAAc;AAAA,MACnC;AAAA,IACJ;AAAA,IACA,SAAS,CAAC,MAAM;AAAE,YAAM;AAAA,IAAG;AAAA,EAC/B,CAAC;AAED,QAAM,SAAS,mBAAmB,GAAG;AACrC,MAAI,OAAO,iBAAiB;AACxB,UAAM,oBAAoB,mBAAmBD,aAAY,OAAO,eAAe;AAAA,EACnF;AAEA,SAAO;AACX;;;AEhTA,SAAS,WAAAG,gBAAe;;;ACUxB,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAEjB,IAAMC,cAAa;AAGnB,IAAMC,YAAW,QAAQ,IAAI,2BAA2B;AAcxD,eAAsB,qBAAqB,UAA+C,CAAC,GAAkB;AACzG,aAAW,KAAK;AAChB,MAAI,MAAM,+CAAoB;AAE9B,QAAM,SAAS,cAAc,YAAY,EAAE,UAAU;AACrD,QAAM,WAAW,OAAO,YAAY;AAEpC,QAAM,cAAc,QAAQ,IAAI;AAKhC,MAAI;AAEJ,MAAI,QAAQ,QAAQ;AAChB,iBAAaC,MAAK,QAAQ,QAAQ,IAAI,GAAG,QAAQ,MAAM;AAAA,EAC3D,OAAO;AACH,UAAM,YAAYA,MAAK,QAAQ,aAAa,UAAU;AACtD,QAAI,CAACC,IAAG,WAAW,SAAS,GAAG;AAG3B,YAAM,OAAOA,IAAG,WAAW,SAAS,IAAIA,IAAG,SAAS,SAAS,IAAI;AACjE,UAAI,QAAQ,KAAK,OAAO,GAAG;AACvB,YAAI,IAAI,QAAQ,iGAAiG;AACjH,cAAM,cAAcD,MAAK,QAAQ,aAAa,uBAAuB;AACrE,YAAI,CAACC,IAAG,WAAW,WAAW,EAAG,CAAAA,IAAG,UAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AAC9E,qBAAaD,MAAK,KAAK,aAAa,oBAAoB;AAAA,MAC5D,OAAO;AACH,QAAAC,IAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAC3C,qBAAaD,MAAK,KAAK,WAAW,oBAAoB;AAAA,MAC1D;AAAA,IACJ,OAAO;AACH,MAAAC,IAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAC3C,mBAAaD,MAAK,KAAK,WAAW,oBAAoB;AAAA,IAC1D;AAAA,EACJ;AAEA,MAAI,IAAI,KAAK,wBAAwB,OAAO,KAAK,WAAW,CAAC,EAAE;AAC/D,MAAI,IAAI,KAAK,uBAAuB,OAAO,KAAK,UAAU,CAAC,EAAE;AAC7D,MAAI,IAAI,KAAK,aAAa,OAAO,KAAK,QAAQ,CAAC,EAAE;AAEjD,QAAM,qBAAqBA,MAAK,SAAS,aAAa,UAAU;AAGhE,QAAM,cAAc;AAAA;AAAA;AAAA;AAAA,yCAIiB,kBAAkB;AAAA;AAAA;AAAA,qEAGU,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyC3E,KAAK;AAEH,QAAM,YAAY,aAAa,UAAU;AAC7C;AAIA,eAAe,YAAY,eAAuB,YAAoB;AAClE,MAAI,aAAa;AACjB,MAAI,YAAY;AAChB,MAAI,YAAY;AAChB,QAAM,YAAY;AAElB,SAAO,aAAa,YAAY,WAAW;AACvC;AACA,UAAM,UAAU,IAAI,QAAQ;AAC5B,YAAQ,MAAM,iEAAsC,SAAS,IAAI,SAAS,MAAM;AAEhF,QAAI,eAAe;AACnB,QAAI,eAAqC;AAEzC,QAAI;AAEA,qBAAe,MAAM,iBAAiB,YAAY,CAAC,UAAU;AACzD,wBAAgB;AAAA,MAEpB,CAAC;AAED,cAAQ,KAAK,eAAe;AAG5B,UAAI,gBAAgB,aAAa,SAAS;AACtC,YAAI,mBAAmB;AACvB,YAAI,cAAc;AAElB,mBAAW,UAAU,aAAa,SAAS;AACvC,cAAI,OAAO,SAAS,cAAc;AAC9B,gBAAI,IAAI,KAAK,2BAAoB,OAAO,KAAK,OAAO,QAAQ,GAAG,CAAC,EAAE;AAClE,kBAAM,SAAS,gBAAgB,OAAO,QAAQ,GAAG;AACjD,gCAAoB,sBAAsB,OAAO,IAAI;AAAA,EAAe,MAAM;AAAA;AAAA;AAAA,UAC9E,WACS,OAAO,SAAS,aAAa;AAClC,gBAAI,IAAI,KAAK,2BAAoB,OAAO,KAAK,OAAO,QAAQ,EAAE,CAAC,EAAE;AACjE,kBAAM,SAAS,eAAe,OAAO,QAAQ,EAAE;AAE/C,gCAAoB,qBAAqB,OAAO,IAAI;AAAA,EAAe,MAAM;AAAA;AAAA;AAAA,UAC7E,WACS,OAAO,SAAS,eAAe;AACpC,gBAAI,IAAI,KAAK,wBAAiB,OAAO,KAAK,OAAO,QAAQ,EAAE,CAAC,EAAE;AAC9D,kBAAM,SAAS,iBAAiB,OAAO,QAAQ,EAAE;AACjD,gCAAoB,uBAAuB,OAAO,IAAI;AAAA,EAAe,MAAM;AAAA;AAAA;AAAA,UAC/E,WACS,OAAO,SAAS,iBAAiB,OAAO,SAAS,eAAe;AAOrE,kBAAM,qBAAqBA,MAAK,QAAQ,OAAO,QAAQ,EAAE;AACzD,kBAAM,qBAAqBA,MAAK,QAAQ,UAAU;AAClD,gBAAI,WAAW,uBAAuB;AAGtC,gBAAI,CAAC,YAAYA,MAAK,SAAS,OAAO,QAAQ,EAAE,MAAM,sBAAsB;AACxE,kBAAI,IAAI,QAAQ,mBAAmB,OAAO,IAAI,qBAAqBA,MAAK,SAAS,QAAQ,IAAI,GAAG,UAAU,CAAC,uBAAuB;AAClI,yBAAW;AAEX,qBAAO,OAAO;AAAA,YAClB;AAEA,gBAAI,UAAU;AAEV,oBAAM,YAAY;AAClB,kBAAI,OAAO,SAAS,eAAe;AAC/B,gBAAAC,IAAG,cAAc,WAAW,OAAO,WAAW,EAAE;AAChD,oBAAI,IAAI,QAAQ,6BAAwB,SAAS,EAAE;AACnD,8BAAc;AAAA,cAClB,OAAO;AAEH,gBAAAA,IAAG,cAAc,WAAW,OAAO,WAAW,EAAE;AAChD,oBAAI,IAAI,QAAQ,2BAAsB,SAAS,EAAE;AACjD,8BAAc;AAAA,cAClB;AACA,kCAAoB,WAAW,OAAO,IAAI;AAAA;AAAA,YAC9C,OAAO;AACH,kBAAI,IAAI,QAAQ,4CAA4C,OAAO,IAAI,EAAE;AAGzE,kCAAoB,WAAW,OAAO,IAAI;AAAA;AAAA,YAC9C;AAAA,UACJ,WACS,OAAO,SAAS,kBAAkB;AACvC,gBAAI,IAAI,KAAK,OAAO,QAAQ,4BAAqB,CAAC;AAClD,oBAAQ,IAAI,OAAO,OAAO;AAG1B,kBAAM,QAAQ,MAAM,IAAI,KAAK,EAAE,SAAS,sBAAsB,aAAa,WAAW,CAAC;AACvF,gCAAoB,iBAAiB,KAAK;AAAA;AAAA,UAC9C;AAAA,QACJ;AAEA,YAAI,aAAa;AACb,cAAI,IAAI,QAAQ,qCAAgC;AAChD,sBAAY;AAAA,QAChB,OAAO;AAEH,uBAAa;AACb,qBAAW,IAAI,QAAQ,8BAA8B,EAAE,QAAQ,iBAAiB,OAAO,CAAC;AAAA,QAC5F;AAAA,MAEJ,OAAO;AAEH,YAAI,YAAY,GAAG;AACf,cAAI,IAAI,QAAQ,qCAAqC;AACrD,sBAAY;AAAA,QAChB,OAAO;AAAA,QAEP;AAAA,MACJ;AAAA,IAEJ,SAAS,OAAY;AACjB,cAAQ,KAAK,OAAO;AACpB,UAAI,IAAI,MAAM,MAAM,OAAO;AAC3B,kBAAY;AAAA,IAChB;AAAA,EACJ;AACJ;AAGA,eAAe,iBAAiB,QAAgB,SAA0D;AACtG,QAAM,QAAQ,MAAM,eAAe;AACnC,QAAM,QAAQ,MAAM,aAAa,SAAS,KAAK;AAC/C,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,eAAe;AAK3C,MAAI,iBAAiB,MAAM,oBAAoB,kBAAkBH,WAAU;AAI3E,QAAM,UAAU;AAAA,IACZ,aAAa;AAAA,IACb,WAAW;AAAA,IACX,qBAAqB;AAAA,IACrB,uBAAuB;AAAA,IACvB,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,EACrB;AAEA,QAAM,MAAM,GAAG,wBAAwB,aAAaC,SAAQ;AAC5D,MAAI,UAAU;AACd,MAAI,MAAW,CAAC;AAEhB,aAAW,IAAI,QAAQ,eAAe,EAAE,cAAc,OAAO,OAAO,CAAC;AAErE,QAAM,UAAU,oBAAoB,KAAK,SAAS,EAAE,iBAAiB,UAAU,KAAK,IAAI,gBAAgB,mBAAmB,GAAG;AAAA,IAC1H,SAAS,CAAC,MAAM;AAAE,iBAAW;AAAG,cAAQ,CAAC;AAAA,IAAG;AAAA,IAC5C,YAAY,CAAC,KAAK,aAAa;AAC3B,YAAM,aAAa,UAAU;AAC7B,YAAM;AAAA,QACF,SAAS,OAAO;AAAA,QAChB,iBAAiB,cAAc;AAAA,MACnC;AAAA,IACJ;AAAA,IACA,SAAS,CAAC,MAAM;AAAE,YAAM;AAAA,IAAG;AAAA,EAC/B,CAAC;AAED,QAAM,SAAS,mBAAmB,GAAG;AACrC,MAAI,OAAO,iBAAiB;AACxB,UAAM,oBAAoB,mBAAmBD,aAAY,OAAO,eAAe;AAAA,EACnF;AACA,SAAO;AACX;;;ADrSO,IAAM,cAAc,IAAII,SAAQ,MAAM,EACxC,YAAY,wDAAwD,EACpE,OAAO,uBAAuB,sEAAsE,EACpG,OAAO,mBAAmB,wCAAwC,OAAO,EACzE,OAAO,OAAO,YAAY;AACvB,MAAI;AACA,UAAM,qBAAqB,OAAO;AAAA,EACtC,SAAS,OAAY;AACjB,YAAQ,MAAM,sBAAsB,MAAM,OAAO;AACjD,YAAQ,KAAK,CAAC;AAAA,EAClB;AACJ,CAAC;;;AEdL,SAAS,WAAAC,gBAAe;;;ACSxB,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAUjB,IAAMC,cAAa;AAEnB,IAAMC,YAAW,QAAQ,IAAI,0BAA0B;AAEvD,eAAsB,0BAA0B,UAA+C,CAAC,GAAkB;AAC9G,aAAW,KAAK;AAChB,MAAI,MAAM,2BAAoB;AAE9B,MAAIA,cAAa,yBAAyB;AACtC,QAAI,IAAI,MAAM,sDAAiD;AAC/D;AAAA,EACJ;AAGA,QAAM,cAAc,QAAQ,IAAI;AAChC,MAAI,iBAAiB;AACrB,QAAM,qBAAqBC,MAAK,QAAQ,aAAa,YAAY,oBAAoB;AACrF,QAAM,sBAAsB,QAAQ,UAAUA,MAAK,QAAQ,aAAa,QAAQ,OAAO,IAAI;AAE3F,MAAIC,IAAG,WAAW,mBAAmB,GAAG;AACpC,QAAI;AACA,uBAAiBA,IAAG,aAAa,qBAAqB,OAAO;AAC7D,UAAI,IAAI,KAAK,kCAA2B,OAAO,IAAID,MAAK,SAAS,aAAa,mBAAmB,CAAC,CAAC,EAAE;AAAA,IACzG,SAAS,GAAG;AACR,UAAI,IAAI,QAAQ,gCAAgC,CAAC,EAAE;AAAA,IACvD;AAAA,EACJ,OAAO;AACH,QAAI,IAAI,QAAQ,gFAAsE;AAAA,EAC1F;AAGA,MAAI,aAAa,QAAQ,QAAQ;AACjC,MAAI,gBAAgB;AAChB,kBAAc;AAAA;AAAA;AAAA,EAAgC,cAAc;AAAA;AAAA,EAChE;AAGA,MAAI,YAAY;AAChB,QAAM,UAAU,IAAI,QAAQ;AAE5B,SAAO,WAAW;AACd,QAAI;AACA,cAAQ,MAAM,sBAAsB;AAGpC,UAAI,eAAqC;AACzC,YAAM,gBAAgB,YAAY,CAAC,UAAU;AAEzC,YAAI,CAAC,cAAc;AAAA,QAEnB;AAAA,MACJ,CAAC,EAAE,KAAK,UAAQ;AACZ,uBAAe;AAAA,MACnB,CAAC;AAED,cAAQ,KAAK,mBAAmB;AAEhC,UAAI,gBAAiB,aAA+B,SAAS;AACzD,cAAM,WAAW;AACjB,YAAI,mBAAmB;AACvB,YAAI,iBAAiB;AAErB,mBAAW,UAAU,SAAS,SAAS;AAEnC,cAAI,OAAO,SAAS,kBAAkB;AAClC,gBAAI,IAAI,KAAK,OAAO,QAAQ,sBAAe,CAAC;AAC5C,oBAAQ,IAAI,OAAO,OAAO;AAC1B,6BAAiB;AAAA,UACrB,WAES,OAAO,SAAS,cAAc;AACnC,gBAAI,IAAI,KAAK,2BAAoB,OAAO,IAAI,OAAO,QAAQ,GAAG,CAAC,EAAE;AACjE,kBAAM,SAAS,gBAAgB,OAAO,QAAQ,GAAG;AACjD,gCAAoB,sBAAsB,OAAO,IAAI;AAAA,EAAe,MAAM;AAAA;AAAA;AAAA,UAC9E,WAES,OAAO,SAAS,aAAa;AAClC,gBAAI,IAAI,KAAK,sBAAe,OAAO,IAAI,OAAO,QAAQ,EAAE,CAAC,EAAE;AAC3D,kBAAM,SAAS,eAAe,OAAO,QAAQ,EAAE;AAC/C,gCAAoB,qBAAqB,OAAO,IAAI;AAAA,EAAe,MAAM;AAAA;AAAA;AAAA,UAC7E,WAES,OAAO,SAAS,eAAe;AACpC,gBAAI,IAAI,KAAK,wBAAiB,OAAO,IAAI,OAAO,QAAQ,EAAE,CAAC,EAAE;AAC7D,kBAAM,SAAS,iBAAiB,OAAO,QAAQ,EAAE;AACjD,gCAAoB,uBAAuB,OAAO,IAAI;AAAA,EAAe,MAAM;AAAA;AAAA;AAAA,UAC/E,WAES,OAAO,SAAS,eAAe;AACpC,kBAAM,MAAM,OAAO,WAAW;AAC9B,gBAAI,IAAI,KAAK,wBAAiB,OAAO,IAAI,GAAG,CAAC,EAAE;AAK/C,kBAAM,UAAU,MAAM,IAAI,QAAQ;AAAA,cAC9B,SAAS,oBAAoB,GAAG;AAAA,cAChC,QAAQ;AAAA,cACR,UAAU;AAAA,YACd,CAAC;AAED,gBAAI,SAAS;AACT,oBAAM,SAAS,MAAM,iBAAiB,GAAG;AACzC,kCAAoB,uBAAuB,GAAG;AAAA,EAAe,MAAM;AAAA;AAAA;AAAA,YACvE,OAAO;AACH,kCAAoB;AAAA;AAAA;AAAA,YACxB;AAAA,UACJ,WAES,CAAC,eAAe,aAAa,EAAE,SAAS,OAAO,IAAI,GAAG;AAC3D,kBAAM,WAAW,OAAO,SAAS;AACjC,kBAAM,WAAW,OAAO,QAAQ;AAChC,gBAAI,IAAI,QAAQ;AAAA,2BAAuB,WAAW,WAAW,QAAQ,KAAK,OAAO,KAAK,QAAQ,CAAC,EAAE;AAIjG,gBAAI,OAAO,SAAS;AAChB,sBAAQ,IAAI,OAAO,IAAI,mBAAmB,IAAI,OAAO,QAAQ,UAAU,GAAG,GAAG,IAAI,UAAU,OAAO,IAAI,iBAAiB,CAAC;AAAA,YAC5H;AAEA,kBAAM,UAAU,MAAM,IAAI,QAAQ;AAAA,cAC9B,SAAS,sBAAsB,QAAQ;AAAA,cACvC,QAAQ;AAAA,cACR,UAAU;AAAA,YACd,CAAC;AAED,gBAAI,SAAS;AACT,kBAAI,UAAU;AACV,sBAAM,aAAaA,MAAK,QAAQ,aAAa,QAAQ;AACrD,sBAAM,MAAMA,MAAK,QAAQ,UAAU;AACnC,oBAAI,CAACC,IAAG,WAAW,GAAG,EAAG,CAAAA,IAAG,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAE9D,oBAAI,UAAU;AACV,kBAAAA,IAAG,cAAc,YAAY,OAAO,WAAW,EAAE;AACjD,sBAAI,IAAI,QAAQ,mBAAc,QAAQ,EAAE;AACxC,sCAAoB,uBAAuB,QAAQ;AAAA;AAAA;AAAA,gBACvD,OAAO;AAEH,sBAAI,OAAO,gBAAgB;AACvB,0BAAM,UAAU,kBAAkB,UAAU,OAAO,WAAW,IAAI,OAAO,gBAAgB,GAAG;AAC5F,wCAAoB,uBAAuB,QAAQ,OAAO,UAAU,YAAY,QAAQ;AAAA;AAAA;AAAA,kBAC5F,OAAO;AAKH,wBAAI,IAAI,MAAM,iDAA4C;AAC1D,wCAAoB;AAAA;AAAA;AAAA,kBACxB;AAAA,gBACJ;AAAA,cACJ;AAAA,YACJ,OAAO;AACH,kBAAI,IAAI,MAAM,gBAAW;AACzB,kCAAoB,WAAW,OAAO,IAAI;AAAA;AAAA;AAAA,YAC9C;AAAA,UACJ;AAAA,QACJ;AAGA,YAAI,kBAAkB;AAClB,cAAI,gBAAgB;AAChB,kBAAM,YAAY,MAAM,IAAI,KAAK,EAAE,SAAS,eAAe,CAAC;AAC5D,gBAAI,IAAI,SAAS,SAAS,GAAG;AAAE,0BAAY;AAAO;AAAA,YAAO;AACzD,yBAAa,GAAG,gBAAgB;AAAA;AAAA,cAAmB,SAAS;AAAA,UAChE,OAAO;AAEH,yBAAa;AACb,gBAAI,IAAI,KAAK,OAAO,IAAI,kCAAkC,CAAC;AAAA,UAC/D;AAAA,QACJ,WAAW,gBAAgB;AACvB,gBAAM,YAAY,MAAM,IAAI,KAAK,EAAE,SAAS,eAAe,CAAC;AAC5D,cAAI,IAAI,SAAS,SAAS,GAAG;AAAE,wBAAY;AAAO;AAAA,UAAO;AACzD,uBAAa;AAAA,QACjB,OAAO;AAEH,cAAI,SAAS,SAAS;AAClB,gBAAI,IAAI,KAAK,OAAO,QAAQ,sBAAe,CAAC;AAC5C,oBAAQ,IAAI,SAAS,OAAO;AAC5B,kBAAM,YAAY,MAAM,IAAI,KAAK,EAAE,SAAS,eAAe,CAAC;AAC5D,gBAAI,IAAI,SAAS,SAAS,GAAG;AACzB,0BAAY;AAAA,YAChB,OAAO;AACH,2BAAa;AAAA,YACjB;AAAA,UACJ,OAAO;AACH,gBAAI,IAAI,QAAQ,wBAAwB;AACxC,wBAAY;AAAA,UAChB;AAAA,QACJ;AAAA,MAEJ,OAAO;AACH,YAAI,IAAI,QAAQ,8BAA8B;AAC9C,oBAAY;AAAA,MAChB;AAAA,IAEJ,SAAS,GAAQ;AACb,cAAQ,KAAK,OAAO;AACpB,UAAI,IAAI,MAAM,EAAE,OAAO;AACvB,kBAAY;AAAA,IAChB;AAAA,EACJ;AAEA,MAAI,MAAM,mCAA4B;AAC1C;AAEA,eAAe,gBAAgB,QAAgB,SAA0D;AACrG,QAAM,QAAQ,MAAM,eAAe;AACnC,QAAM,QAAQ,MAAM,aAAa,SAAS,KAAK;AAC/C,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,iCAAiC;AAE7D,QAAM,iBAAiB,MAAM,oBAAoB,kBAAkBH,WAAU;AAE7E,QAAM,UAAU;AAAA,IACZ,aAAa;AAAA,IACb,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,qBAAqB;AAAA;AAAA,EACzB;AAEA,QAAM,MAAM,GAAG,wBAAwB,aAAaC,SAAQ;AAC5D,MAAI,UAAU;AACd,MAAI,MAAW,CAAC;AAEhB,QAAM,UAAU,oBAAoB,KAAK,SAAS,EAAE,iBAAiB,UAAU,KAAK,IAAI,gBAAgB,mBAAmB,GAAG;AAAA,IAC1H,SAAS,CAAC,MAAM;AAAE,iBAAW;AAAG,cAAQ,CAAC;AAAA,IAAG;AAAA,IAC5C,YAAY,CAAC,KAAK,aAAa;AAC3B,YAAM,aAAa,UAAU;AAC7B,YAAM;AAAA,QACF,SAAS,OAAO;AAAA,QAChB,iBAAiB,cAAc;AAAA,MACnC;AAAA,IACJ;AAAA,IACA,SAAS,CAAC,MAAM;AAAE,YAAM;AAAA,IAAG;AAAA,EAC/B,CAAC;AAED,QAAM,SAAS,mBAAmB,GAAG;AACrC,MAAI,OAAO,iBAAiB;AACxB,UAAM,oBAAoB,mBAAmBD,aAAY,OAAO,eAAe;AAAA,EACnF;AACA,SAAO;AACX;;;ADlQO,IAAM,aAAa,IAAII,SAAQ,KAAK,EACtC,YAAY,8CAA8C,EAC1D,OAAO,qBAAqB,0BAA0B,EACtD,OAAO,wBAAwB,6BAA6B,EAC5D,OAAO,OAAO,YAAY;AACvB,QAAM,0BAA0B,OAAO;AAC3C,CAAC;;;AEVL,SAAS,WAAAC,gBAAe;;;ACQxB,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,cAAc;AACvB,SAAS,4BAA4B;AAErC,IAAMC,cAAa;AAGnB,IAAMC,YAAW,QAAQ,IAAI,yBAAyB;AAQtD,IAAM,uBAAN,MAA2B;AAAA,EACf,SAAwB;AAAA,EACxB,YAAyC;AAAA,EAEjD,MAAM,UAAU;AACZ,QAAI,KAAK,OAAQ;AAEjB,QAAI;AACA,WAAK,YAAY,IAAI,qBAAqB;AAAA,QACtC,SAAS;AAAA,QACT,MAAM,CAAC,MAAM,4BAA4B;AAAA,MAC7C,CAAC;AAED,WAAK,SAAS,IAAI,OAAO;AAAA,QACrB,MAAM;AAAA,QACN,SAAS;AAAA,MACb,GAAG;AAAA,QACC,cAAc,CAAC;AAAA,MACnB,CAAC;AAED,YAAM,KAAK,OAAO,QAAQ,KAAK,SAAS;AACxC,UAAI,IAAI,QAAQ,4CAAqC;AAAA,IACzD,SAAS,GAAQ;AACb,UAAI,IAAI,MAAM,oCAAoC,EAAE,OAAO,EAAE;AAC7D,YAAM;AAAA,IACV;AAAA,EACJ;AAAA,EAEA,MAAM,SAAS,MAAc,MAAW;AACpC,QAAI,CAAC,KAAK,OAAQ,OAAM,KAAK,QAAQ;AACrC,QAAI;AACA,YAAM,SAAS,MAAM,KAAK,OAAQ,SAAS;AAAA,QACvC;AAAA,QACA,WAAW;AAAA,MACf,CAAC;AACD,aAAO;AAAA,IACX,SAAS,GAAQ;AACb,aAAO,EAAE,SAAS,MAAM,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,cAAc,EAAE,OAAO,GAAG,CAAC,EAAE;AAAA,IACzF;AAAA,EACJ;AAAA,EAEA,MAAM,QAAQ;AACV,QAAI,KAAK,WAAW;AAChB,YAAM,KAAK,UAAU,MAAM;AAAA,IAC/B;AAAA,EACJ;AACJ;AAEA,IAAM,YAAY,IAAI,qBAAqB;AAE3C,eAAsB,WAAW,SAAyB;AACtD,MAAI,CAACA,WAAU;AACX,QAAI,IAAI,MAAM,8CAAyC;AACvD,QAAI,IAAI,KAAK,iDAAiD;AAC9D;AAAA,EACJ;AAGA,QAAM,UAAU,QAAQ;AAExB,MAAI,MAAM,0BAAmB;AAC7B,MAAI,IAAI,KAAK,kCAAkC;AAE/C,QAAM,QAAQ,MAAM,eAAe;AACnC,QAAM,QAAQ,MAAM,aAAa,SAAS,KAAK;AAE/C,MAAI,CAAC,OAAO;AACR,QAAI,IAAI,MAAM,6CAA6C;AAC3D;AAAA,EACJ;AAGA,MAAI,iBAAiB;AACrB,MAAI;AACA,UAAM,cAAcF,MAAK,KAAK,QAAQ,IAAI,GAAG,YAAY,oBAAoB;AAC7E,QAAID,IAAG,WAAW,WAAW,GAAG;AAC5B,uBAAiBA,IAAG,aAAa,aAAa,OAAO;AACrD,UAAI,IAAI,KAAK,4DAAqD;AAAA,IACtE;AAAA,EACJ,SAAS,GAAG;AAAA,EAEZ;AAEA,MAAI,cAAc;AAAA,EAAyB,cAAc;AAAA;AAAA;AAEzD,MAAI,QAAQ,YAAY;AACpB,mBAAe,aAAa,QAAQ,UAAU;AAAA;AAAA,EAClD;AACA,MAAI,QAAQ,UAAU;AAClB,mBAAe,wBAAqB,QAAQ,QAAQ;AAAA;AAAA,EACxD,OAAO;AACH,mBAAe;AAAA,EACnB;AAGA,MAAI,cAAc;AAElB,SAAO,aAAa;AAChB,UAAM,UAAU,IAAI,QAAQ;AAC5B,YAAQ,MAAM,mCAA4B;AAE1C,QAAI,oBAAoB;AACxB,QAAI,gBAAsC;AAE1C,QAAI;AAEA,YAAM,yBAAyB,MAAM,oBAAoB,kBAAkBE,WAAU;AAErF,YAAM,UAAU;AAAA,QACZ,sDAAsDC,SAAQ;AAAA,QAC9D;AAAA,UACI,aAAa;AAAA,UACb,WAAW;AAAA,UACX,kBAAkB;AAAA,UAClB,iBAAiB;AAAA,QACrB;AAAA,QACA;AAAA,UACI,iBAAiB,UAAU,KAAK;AAAA,QACpC;AAAA,QACA;AAAA,UACI,SAAS,CAAC,UAAU;AAChB,iCAAqB;AACrB,gBAAI,kBAAkB,SAAS,MAAM,kBAAkB,KAAK,EAAE,WAAW,GAAG,GAAG;AAC3E,sBAAQ,QAAQ,8BAA8B;AAAA,YAClD;AAAA,UACJ;AAAA,UACA,YAAY,CAAC,UAAU,aAAa;AAChC,gBAAI;AACA,kBAAI,UAAU,iBAAiB;AAC3B,oCAAoB,mBAAmBD,aAAY,SAAS,eAAe;AAAA,cAC/E;AACA,8BAAgB,mBAAmB,YAAY,iBAAiB;AAAA,YACpE,SAAS,GAAG;AACR,kBAAI,IAAI,MAAM,gBAAiB,EAAY,OAAO,EAAE;AACpD,8BAAgB,EAAE,SAAS,CAAC,GAAG,SAAS,0BAA0B,SAAS,SAAS;AAAA,YACxF;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAEA,cAAQ,KAAK,mBAAmB;AAAA,IAEpC,SAAS,OAAO;AACZ,cAAQ,KAAK,uBAAuB,CAAC;AACrC,UAAI,IAAI,MAAO,MAAgB,OAAO;AACtC,oBAAc;AACd;AAAA,IACJ;AAEA,QAAI,CAAC,cAAe;AAGpB,QAAI,cAAc,SAAS;AACvB,UAAI,IAAI,KAAK,OAAO,QAAQ,mBAAY,cAAc,OAAO,EAAE,CAAC;AAAA,IACpE;AAEA,QAAI,cAAc,QAAQ,WAAW,GAAG;AAEpC,YAAM,QAAQ,MAAM,IAAI,KAAK;AAAA,QACzB,SAAS;AAAA,QACT,aAAa;AAAA,MACjB,CAAC;AAED,UAAI,IAAI,SAAS,KAAK,GAAG;AACrB,sBAAc;AAAA,MAClB,OAAO;AACH,sBAAc;AAAA,MAClB;AACA;AAAA,IACJ;AAEA,eAAW,UAAU,cAAc,SAAS;AACxC,UAAI,IAAI,KAAK,OAAO,IAAI,cAAc,OAAO,IAAI,EAAE,CAAC;AAEpD,UAAI,SAAS;AAEb,UAAI;AACA,gBAAQ,OAAO,MAAM;AAAA,UACjB,KAAK;AACD,kBAAM,QAAQ,MAAM,IAAI,KAAK;AAAA,cACzB,SAAS,aAAM,OAAO,OAAO;AAAA,YACjC,CAAC;AACD,gBAAI,IAAI,SAAS,KAAK,EAAG,eAAc;AAAA,gBAClC,UAAS;AACd;AAAA,UAEJ,KAAK;AACD,gBAAI,OAAO,WAAW;AAClB,kBAAI,IAAI,KAAK,uBAAgB,OAAO,KAAK,OAAO,SAAS,CAAC,EAAE;AAC5D,kBAAI,OAAO,CAAC;AACZ,kBAAI;AACA,uBAAO,OAAO,OAAO,cAAc,WAC7B,KAAK,MAAM,OAAO,SAAS,IAC1B,OAAO,aAAa,CAAC;AAAA,cAChC,SAAS,GAAG;AACR,oBAAI,IAAI,QAAQ,+CAA+C;AAAA,cACnE;AACA,oBAAM,YAAY,MAAM,UAAU,SAAS,OAAO,WAAW,IAAI;AACjE,uBAAS,KAAK,UAAU,SAAS;AAEjC,kBAAI,IAAI,QAAQ,WAAW,OAAO,UAAU,GAAG,GAAG,CAAC,KAAK;AAAA,YAC5D;AACA;AAAA,UAEJ,KAAK;AACD,gBAAI,OAAO,QAAQ,OAAO,SAAS;AAC/B,oBAAM,WAAWD,MAAK,QAAQ,QAAQ,IAAI,GAAG,OAAO,IAAI;AACxD,cAAAD,IAAG,cAAc,UAAU,OAAO,OAAO;AACzC,kBAAI,IAAI,QAAQ,iBAAiB,OAAO,IAAI,EAAE;AAC9C,uBAAS;AAAA,YACb;AACA;AAAA,UAEJ,KAAK;AACD,qBAAS,eAAe,OAAO,QAAQ,EAAE;AACzC;AAAA,UAEJ,KAAK;AAED,kBAAM,UAAU,MAAM,IAAI,QAAQ,EAAE,SAAS,gBAAgB,OAAO,OAAO,IAAI,CAAC;AAChF,gBAAI,WAAW,OAAO,SAAS;AAC3B,uBAAS,MAAM,iBAAiB,OAAO,OAAO;AAAA,YAClD,OAAO;AACH,uBAAS;AAAA,YACb;AACA;AAAA,UAEJ;AACI,qBAAS,UAAU,OAAO,IAAI;AAAA,QACtC;AAAA,MACJ,SAAS,GAAQ;AACb,iBAAS,mBAAmB,OAAO,IAAI,KAAK,EAAE,OAAO;AACrD,YAAI,IAAI,MAAM,MAAM;AAAA,MACxB;AAGA,oBAAc,WAAW,OAAO,IAAI;AAAA,EAAc,MAAM;AAAA;AAAA;AAAA,IAC5D;AAAA,EACJ;AAEA,QAAM,UAAU,MAAM;AACtB,MAAI,MAAM,kCAA2B;AACzC;;;ADvQO,IAAM,YAAY,IAAII,SAAQ,IAAI,EACpC,YAAY,mDAAmD,EAC/D,OAAO,eAAe,qBAAqB,EAC3C,OAAO,yBAAyB,8CAA8C,EAC9E,OAAO,OAAO,YAAY;AACvB,MAAI;AACA,UAAM,WAAW;AAAA,MACb,YAAY,QAAQ;AAAA,MACpB,UAAU,QAAQ;AAAA,IACtB,CAAC;AAAA,EACL,SAAS,OAAY;AACjB,YAAQ,MAAM,2BAA2B,MAAM,OAAO;AACtD,YAAQ,KAAK,CAAC;AAAA,EAClB;AACJ,CAAC;;;AjBbL,aAAa,KAAK;AAalB,IAAM,UAAU,IAAIC,SAAQ;AAE5B,QACK,KAAK,OAAO,EACZ,YAAY,qDAAqD,EACjE,QAAQ,OAAO;AAEpB,QAAQ,WAAW,YAAY;AAC/B,QAAQ,WAAW,WAAW;AAC9B,QAAQ,WAAW,WAAW;AAC9B,QAAQ,WAAW,UAAU;AAC7B,QAAQ,WAAW,SAAS;AAI5B,QACK,QAAQ,IAAI,EACZ,YAAY,kDAAkD,EAC9D,OAAO,mBAAmB,mBAAmB,EAC7C,OAAO,OAAO,YAAY;AACvB,MAAI;AACA,UAAM,2BAA2B;AAAA,EACrC,SAAS,OAAY;AACjB,YAAQ,MAAM,UAAU,MAAM,OAAO;AACrC,YAAQ,KAAK,CAAC;AAAA,EAClB;AACJ,CAAC;AAIL,QACK,QAAQ,MAAM,EACd,YAAY,+CAA+C,EAC3D,OAAO,mBAAmB,mBAAmB,EAC7C,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,OAAO,YAAY;AACvB,MAAI;AACA,UAAM,8BAA8B;AAAA,MAChC,SAAS,QAAQ;AAAA,MACjB,cAAc,QAAQ;AAAA,IAC1B,CAAC;AAAA,EACL,SAAS,OAAY;AACjB,YAAQ,MAAM,UAAU,MAAM,OAAO;AACrC,YAAQ,KAAK,CAAC;AAAA,EAClB;AACJ,CAAC;AAEL,QACK,QAAQ,QAAQ,EAChB,YAAY,6BAA6B,EACzC,OAAO,cAAc,MAAM;AAGhC,QAAQ,GAAG,sBAAsB,CAAC,QAAQ;AACtC,UAAQ,MAAM,OAAO,MAAM,yBAAoB,GAAG,GAAG;AACrD,UAAQ,KAAK,CAAC;AAClB,CAAC;AAED,QAAQ,MAAM,QAAQ,IAAI;","names":["Command","fs","path","path","fs","fs","path","z","z","fs","fs","path","path","fs","tui","AGENT_TYPE","AGENT_ID","fs","Command","fs","path","AGENT_TYPE","AGENT_ID","path","fs","Command","Command","fs","path","AGENT_TYPE","AGENT_ID","path","fs","Command","Command","fs","path","AGENT_TYPE","AGENT_ID","Command","Command"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/error/crash-handler.ts","../../src/bin/shark.ts","../../src/commands/init.ts","../../src/core/workflow/workflow-manager.ts","../../src/core/workflow/shark-workflow.schema.ts","../../src/core/api/stackspot-client.ts","../../src/core/debug/file-logger.ts","../../src/core/api/sse-client.ts","../../src/core/agents/agent-response-parser.ts","../../src/core/workflow/conversation-manager.ts","../../src/core/auth/get-active-realm.ts","../../src/core/agents/business-analyst-agent.ts","../../src/core/agents/specification-agent.ts","../../src/core/agents/agent-tools.ts","../../src/commands/scan.ts","../../src/core/agents/scan-agent.ts","../../src/commands/dev.ts","../../src/core/agents/developer-agent.ts","../../src/commands/qa.ts","../../src/core/agents/qa-agent.ts"],"sourcesContent":["import fs from 'fs';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport { colors } from '../../ui/colors.js';\r\n\r\nexport class CrashHandler {\r\n private static instance: CrashHandler;\r\n private readonly logDir: string;\r\n\r\n private constructor() {\r\n this.logDir = path.join(os.homedir(), '.shark', 'logs');\r\n }\r\n\r\n public static getInstance(): CrashHandler {\r\n if (!CrashHandler.instance) {\r\n CrashHandler.instance = new CrashHandler();\r\n }\r\n return CrashHandler.instance;\r\n }\r\n\r\n public init(): void {\r\n process.on('uncaughtException', (error) => this.handleError(error, 'Uncaught Exception'));\r\n process.on('unhandledRejection', (reason) => this.handleError(reason, 'Unhandled Rejection'));\r\n }\r\n\r\n private handleError(error: any, type: string): void {\r\n // Prevent infinite loops if logging fails\r\n try {\r\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\r\n const logFile = path.join(this.logDir, `crash-${timestamp}.log`);\r\n\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n const stackTrace = error instanceof Error ? error.stack : 'No stack trace available';\r\n\r\n const logContent = `\r\n[${new Date().toISOString()}] ${type}\r\n--------------------------------------------------\r\nMessage: ${errorMessage}\r\nStack:\r\n${stackTrace}\r\n--------------------------------------------------\r\nSystem: ${os.platform()} ${os.release()} ${os.arch()}\r\nNode: ${process.version}\r\n`;\r\n\r\n // Ensure directory exists sync (we are crashing, async might not finish)\r\n if (!fs.existsSync(this.logDir)) {\r\n fs.mkdirSync(this.logDir, { recursive: true });\r\n }\r\n\r\n fs.writeFileSync(logFile, logContent, 'utf-8');\r\n\r\n console.error('\\n');\r\n console.error(colors.error('π₯ Whoops! Shark CLI crashed unexpectedly.'));\r\n console.error(colors.dim(` Details have been saved to: ${logFile}`));\r\n console.error(colors.dim(' Please report this issue so we can fix it.'));\r\n console.error(colors.error(` Error: ${errorMessage}`));\r\n console.error('\\n');\r\n\r\n } catch (filesysError) {\r\n console.error('Fatal Error: Failed to write crash log.', filesysError);\r\n console.error('Original Error:', error);\r\n } finally {\r\n process.exit(1);\r\n }\r\n }\r\n}\r\n\r\nexport const crashHandler = CrashHandler.getInstance();\r\n","\r\nimport { crashHandler } from '../core/error/crash-handler.js';\r\n\r\n// Initialize Global Crash Handler\r\ncrashHandler.init();\r\n\r\nimport { Command } from 'commander';\r\nimport { loginCommand } from '../commands/login.js';\r\nimport { configCommand } from '../commands/config.js';\r\nimport { initCommand } from '../commands/init.js';\r\nimport { colors } from '../ui/colors.js';\r\nimport { interactiveBusinessAnalyst } from '../core/agents/business-analyst-agent.js';\r\nimport { interactiveSpecificationAgent } from '../core/agents/specification-agent.js';\r\nimport { scanCommand } from '../commands/scan.js';\r\nimport { devCommand } from '../commands/dev.js';\r\nimport { qaCommand } from '../commands/qa.js';\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('shark')\r\n .description('Shark CLI: AI-Native Collaborative Development Tool')\r\n .version('0.0.1');\r\n\r\nprogram.addCommand(loginCommand);\r\nprogram.addCommand(initCommand);\r\nprogram.addCommand(scanCommand);\r\nprogram.addCommand(devCommand);\r\nprogram.addCommand(qaCommand);\r\n\r\n// Command: ba\r\n// Description: Starts the Business Analyst Agent interactive session\r\nprogram\r\n .command('ba')\r\n .description('Start Business Analyst Agent interactive session')\r\n .option('--id <agent_id>', 'Override Agent ID')\r\n .action(async (options) => {\r\n try {\r\n await interactiveBusinessAnalyst();\r\n } catch (error: any) {\r\n console.error('Error:', error.message);\r\n process.exit(1);\r\n }\r\n });\r\n\r\n// Command: spec\r\n// Description: Starts the Specification Agent session\r\nprogram\r\n .command('spec')\r\n .description('Start Specification Agent interactive session')\r\n .option('--id <agent_id>', 'Override Agent ID')\r\n .option('--briefing <path>', 'Path to briefing file')\r\n .action(async (options) => {\r\n try {\r\n await interactiveSpecificationAgent({\r\n agentId: options.id,\r\n briefingPath: options.briefing\r\n });\r\n } catch (error: any) {\r\n console.error('Error:', error.message);\r\n process.exit(1);\r\n }\r\n });\r\n\r\nprogram\r\n .command('config')\r\n .description('Manage global configuration')\r\n .action(configCommand.action);\r\n\r\n// Global Error Handler for the CLI\r\nprocess.on('unhandledRejection', (err) => {\r\n console.error(colors.error('β Unhandled Error:'), err);\r\n process.exit(1);\r\n});\r\n\r\nprogram.parse(process.argv);\r\n","import { Command } from 'commander';\r\nimport { tui } from '../ui/tui.js';\r\nimport { workflowManager } from '../core/workflow/workflow-manager.js';\r\nimport { TechStackEnum } from '../core/workflow/shark-workflow.schema.js';\r\nimport { randomUUID } from 'crypto';\r\nimport { colors } from '../ui/colors.js';\r\n\r\nexport const initAction = async () => {\r\n tui.intro('Shark Project Initialization');\r\n\r\n // 1. Check if workflow already exists\r\n const existingState = await workflowManager.load();\r\n if (existingState) {\r\n // Smart Resume Context Card\r\n tui.log.info(colors.dim('----------------------------------------'));\r\n tui.log.info(`π¦ ${colors.primary('Welcome back to Shark CLI!')}`);\r\n tui.log.message(` Project: ${colors.white(existingState.projectName)}`);\r\n tui.log.message(` Stage: ${colors.secondary(existingState.currentStage)}`);\r\n tui.log.message(` Updated: ${colors.dim(new Date(existingState.lastUpdated).toLocaleString())}`);\r\n tui.log.info(colors.dim('----------------------------------------'));\r\n\r\n const action = await tui.select({\r\n message: 'An existing project was detected. What would you like to do?',\r\n options: [\r\n { value: 'resume', label: 'π Resume Work' },\r\n { value: 'overwrite', label: 'β οΈ Overwrite (Start Fresh)' },\r\n { value: 'exit', label: 'β Exit' }\r\n ]\r\n });\r\n\r\n if (tui.isCancel(action) || action === 'exit') {\r\n tui.outro('See you later! π');\r\n return;\r\n }\r\n\r\n if (action === 'resume') {\r\n tui.log.success(`Resuming work on ${colors.primary(existingState.projectName)}...`);\r\n // Future: Route to specific agent based on stage\r\n tui.outro(`To continue, run: \"shark agent\" (Context loaded)`);\r\n return;\r\n }\r\n\r\n // If overwrite, we just proceed to step 2...\r\n }\r\n\r\n // 2. Prompt for Project Name\r\n const projectName = await tui.text({\r\n message: 'What is the name of your project?',\r\n placeholder: 'e.g. My Awesome App',\r\n validate: (value) => {\r\n if (!value) return 'Project name is required';\r\n if (value.trim().length < 2) return 'Project name must be at least 2 characters';\r\n }\r\n });\r\n\r\n if (tui.isCancel(projectName)) {\r\n tui.outro('Initialization cancelled.');\r\n return;\r\n }\r\n\r\n // 3. Prompt for Tech Stack\r\n const techStackOptions = TechStackEnum.options.map(stack => ({\r\n value: stack,\r\n label: stack === 'node-ts' ? 'Node.js (TypeScript)' :\r\n stack === 'nextjs' ? 'Next.js' :\r\n stack.charAt(0).toUpperCase() + stack.slice(1)\r\n }));\r\n\r\n const techStack = await tui.select({\r\n message: 'Select your technology stack:',\r\n options: techStackOptions\r\n });\r\n\r\n if (tui.isCancel(techStack)) {\r\n tui.outro('Initialization cancelled.');\r\n return;\r\n }\r\n\r\n // 4. Create and Save State\r\n const spinner = tui.spinner();\r\n spinner.start('Initializing project workflow...');\r\n\r\n try {\r\n const newState = {\r\n projectId: randomUUID(),\r\n projectName: projectName as string,\r\n techStack: techStack as any,\r\n currentStage: 'business_analysis' as const,\r\n stageStatus: 'pending' as const,\r\n lastUpdated: new Date().toISOString(),\r\n artifacts: [],\r\n metadata: {\r\n initializedBy: 'shark-cli',\r\n version: '0.0.1'\r\n }\r\n };\r\n\r\n await workflowManager.save(newState);\r\n spinner.stop('Project workflow created!');\r\n\r\n tui.log.success(`Project ${colors.primary(projectName as string)} initialized successfully.`);\r\n tui.log.message(`Your Project ID: ${colors.dim(newState.projectId)}`);\r\n tui.outro('Ready to start! Run \"shark agent\" to begin analyzing requirements.'); // Placeholder hint\r\n } catch (error: any) {\r\n spinner.stop('Initialization failed.', 1);\r\n tui.log.error(error.message);\r\n process.exit(1);\r\n }\r\n};\r\n\r\nexport const initCommand = new Command('init')\r\n .description('Initialize a new Shark project')\r\n .action(initAction);\r\n","import fs from 'fs/promises';\r\nimport path from 'path';\r\nimport { WorkflowSchema, type WorkflowState } from './shark-workflow.schema.js';\r\nimport { colors } from '../../ui/colors.js';\r\n\r\nexport class WorkflowManager {\r\n private static instance: WorkflowManager;\r\n private readonly filename = 'shark-workflow.json';\r\n private readonly tmpFilename = '.shark-workflow.tmp';\r\n\r\n private constructor() { }\r\n\r\n public static getInstance(): WorkflowManager {\r\n if (!WorkflowManager.instance) {\r\n WorkflowManager.instance = new WorkflowManager();\r\n }\r\n return WorkflowManager.instance;\r\n }\r\n\r\n private getFilePath(): string {\r\n return path.join(process.cwd(), this.filename);\r\n }\r\n\r\n private getTmpFilePath(): string {\r\n return path.join(process.cwd(), this.tmpFilename);\r\n }\r\n\r\n public async save(state: WorkflowState): Promise<void> {\r\n // 1. Validate State\r\n const parsed = WorkflowSchema.safeParse(state);\r\n if (!parsed.success) {\r\n throw new Error(`Invalid workflow state: ${parsed.error.message}`);\r\n }\r\n\r\n const filePath = this.getFilePath();\r\n const tmpPath = this.getTmpFilePath();\r\n const data = JSON.stringify(parsed.data, null, 2);\r\n\r\n try {\r\n // 2. Write to TMP\r\n await fs.writeFile(tmpPath, data, 'utf-8');\r\n\r\n // 3. Rename TMP to Final (Atomic)\r\n await fs.rename(tmpPath, filePath);\r\n } catch (error: any) {\r\n throw new Error(`Failed to save workflow state atomically: ${error.message}`);\r\n }\r\n }\r\n\r\n public async load(): Promise<WorkflowState | null> {\r\n const filePath = this.getFilePath();\r\n\r\n try {\r\n // Check if file exists\r\n try {\r\n await fs.access(filePath);\r\n } catch {\r\n return null; // File doesn't exist, generic start\r\n }\r\n\r\n const content = await fs.readFile(filePath, 'utf-8');\r\n const json = JSON.parse(content);\r\n\r\n const parsed = WorkflowSchema.safeParse(json);\r\n if (parsed.success) {\r\n return parsed.data;\r\n } else {\r\n console.warn(colors.warning(`β οΈ Corrupted workflow file detected: ${parsed.error.message}`));\r\n return null;\r\n }\r\n\r\n } catch (error: any) {\r\n console.warn(colors.warning(`β οΈ Failed to load workflow state: ${error.message}`));\r\n return null;\r\n }\r\n }\r\n\r\n // Helper to get current state or default if none exists\r\n public async getOrInitState(): Promise<WorkflowState | null> {\r\n return await this.load();\r\n }\r\n}\r\n\r\nexport const workflowManager = WorkflowManager.getInstance();\r\n","import { z } from 'zod';\r\n\r\nexport enum ProjectParams {\r\n PROJECT_ID = 'projectId',\r\n PROJECT_NAME = 'projectName',\r\n TECH_STACK = 'techStack',\r\n}\r\n\r\nexport const TechStackEnum = z.enum([\r\n 'react',\r\n 'nextjs',\r\n 'angular',\r\n 'vue',\r\n 'node-ts',\r\n 'python',\r\n 'dotnet',\r\n 'java',\r\n 'unknown'\r\n]);\r\n\r\nexport type TechStack = z.infer<typeof TechStackEnum>;\r\n\r\nexport const WorkflowStageEnum = z.enum([\r\n 'business_analysis',\r\n 'specification',\r\n 'architecture',\r\n 'development',\r\n 'verification',\r\n 'deployment'\r\n]);\r\n\r\nexport type WorkflowStage = z.infer<typeof WorkflowStageEnum>;\r\n\r\nexport const StageStatusEnum = z.enum([\r\n 'pending',\r\n 'in_progress',\r\n 'completed',\r\n 'failed',\r\n 'skipped'\r\n]);\r\n\r\nexport type StageStatus = z.infer<typeof StageStatusEnum>;\r\n\r\nexport const WorkflowSchema = z.object({\r\n projectId: z.string().uuid(),\r\n projectName: z.string().min(1),\r\n techStack: TechStackEnum.default('unknown'),\r\n currentStage: WorkflowStageEnum.default('business_analysis'),\r\n stageStatus: StageStatusEnum.default('pending'),\r\n lastUpdated: z.string().datetime(), // ISO 8601\r\n conversationId: z.string().optional(),\r\n conversations: z.record(z.string(), z.string()).optional(), // agentType -> conversationId\r\n artifacts: z.array(z.string()).default([]),\r\n // Extensible metadata bag\r\n metadata: z.record(z.unknown()).optional(),\r\n});\r\n\r\nexport type WorkflowState = z.infer<typeof WorkflowSchema>;\r\n","import { tokenStorage } from '../auth/token-storage.js';\r\n\r\nexport class AuthError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = 'AuthError';\r\n }\r\n}\r\n\r\ninterface RequestOptions extends RequestInit {\r\n params?: Record<string, string>;\r\n}\r\n\r\n// API Base URLs\r\nexport const STACKSPOT_API_BASE = 'https://api.stackspot.com';\r\nexport const STACKSPOT_AGENT_API_BASE = 'https://genai-inference-app.stackspot.com';\r\n\r\nexport class StackSpotClient {\r\n private readonly MAX_RETRIES = 3;\r\n private readonly RETRY_DELAYS = [1000, 2000, 4000]; // 1s, 2s, 4s\r\n private debugMode = false;\r\n\r\n constructor(private realm: string) { }\r\n\r\n public enableDebug(): void {\r\n this.debugMode = true;\r\n }\r\n\r\n private async getHeaders(): Promise<Headers> {\r\n const token = await tokenStorage.getToken(this.realm);\r\n\r\n if (!token) {\r\n throw new AuthError(`Authentication required for realm '${this.realm}'.\\nPlease run 'shark login' to authenticate.`);\r\n }\r\n\r\n const headers = new Headers();\r\n headers.set('Authorization', `Bearer ${token}`);\r\n headers.set('Content-Type', 'application/json');\r\n return headers;\r\n }\r\n\r\n private shouldRetry(error: any, attempt: number): boolean {\r\n if (attempt >= this.MAX_RETRIES) return false;\r\n\r\n // Retry on network errors\r\n if (error.name === 'TypeError' || error.message?.includes('fetch')) return true;\r\n\r\n // Retry on 5xx server errors\r\n if (error.status && error.status >= 500) return true;\r\n\r\n return false;\r\n }\r\n\r\n private async sleep(ms: number): Promise<void> {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n }\r\n\r\n private async request<T>(url: string, options: RequestOptions = {}): Promise<T> {\r\n let lastError: any;\r\n\r\n for (let attempt = 0; attempt <= this.MAX_RETRIES; attempt++) {\r\n try {\r\n if (this.debugMode && attempt > 0) {\r\n console.log(`[StackSpotClient] Retry attempt ${attempt}/${this.MAX_RETRIES} for ${url}`);\r\n }\r\n\r\n const headers = await this.getHeaders();\r\n\r\n // Merge custom headers\r\n if (options.headers) {\r\n new Headers(options.headers).forEach((value, key) => headers.set(key, value));\r\n }\r\n\r\n // Add Query Params\r\n let finalUrl = url;\r\n if (options.params) {\r\n const query = new URLSearchParams(options.params).toString();\r\n finalUrl += `?${query}`;\r\n }\r\n\r\n if (this.debugMode) {\r\n console.log(`[StackSpotClient] ${options.method || 'GET'} ${finalUrl}`);\r\n }\r\n\r\n const response = await fetch(finalUrl, {\r\n ...options,\r\n headers,\r\n });\r\n\r\n if (response.status === 401) {\r\n throw new AuthError(\"Session expired or invalid credentials. Please run 'shark login' again.\");\r\n }\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n const error: any = new Error(`API Request failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n error.status = response.status;\r\n throw error;\r\n }\r\n\r\n // Return null for 204 No Content\r\n if (response.status === 204) {\r\n return null as T;\r\n }\r\n\r\n return (await response.json()) as T;\r\n\r\n } catch (error: any) {\r\n lastError = error;\r\n\r\n // Don't retry auth errors\r\n if (error instanceof AuthError) {\r\n throw error;\r\n }\r\n\r\n if (this.shouldRetry(error, attempt)) {\r\n const delay = this.RETRY_DELAYS[attempt] || this.RETRY_DELAYS[this.RETRY_DELAYS.length - 1];\r\n if (this.debugMode) {\r\n console.log(`[StackSpotClient] Retrying in ${delay}ms...`);\r\n }\r\n await this.sleep(delay);\r\n continue;\r\n }\r\n\r\n // No more retries\r\n throw error;\r\n }\r\n }\r\n\r\n throw lastError;\r\n }\r\n\r\n async get<T>(url: string, options?: RequestOptions): Promise<T> {\r\n return this.request<T>(url, { ...options, method: 'GET' });\r\n }\r\n\r\n async post<T>(url: string, body: any, options?: RequestOptions): Promise<T> {\r\n return this.request<T>(url, {\r\n ...options,\r\n method: 'POST',\r\n body: JSON.stringify(body)\r\n });\r\n }\r\n\r\n async put<T>(url: string, body: any, options?: RequestOptions): Promise<T> {\r\n return this.request<T>(url, {\r\n ...options,\r\n method: 'PUT',\r\n body: JSON.stringify(body)\r\n });\r\n }\r\n\r\n async delete<T>(url: string, options?: RequestOptions): Promise<T> {\r\n return this.request<T>(url, { ...options, method: 'DELETE' });\r\n }\r\n}\r\n\r\nexport function createAuthenticatedClient(realm: string): StackSpotClient {\r\n return new StackSpotClient(realm);\r\n}\r\n","import fs from 'node:fs';\r\nimport path from 'node:path';\r\n\r\nexport class FileLogger {\r\n private static logPath = path.resolve(process.cwd(), 'shark-debug.log');\r\n private static enabled = true; // Enabled by default for this debugging session\r\n\r\n static init() {\r\n try {\r\n fs.writeFileSync(this.logPath, `--- Shark CLI Debug Log Started at ${new Date().toISOString()} ---\\n`);\r\n } catch (e) {\r\n console.error('Failed to initialize debug log:', e);\r\n }\r\n }\r\n\r\n static log(category: string, message: string, data?: any) {\r\n if (!this.enabled) return;\r\n\r\n try {\r\n const timestamp = new Date().toISOString();\r\n let logEntry = `[${timestamp}] [${category.toUpperCase()}] ${message}\\n`;\r\n if (data !== undefined) {\r\n if (typeof data === 'object') {\r\n logEntry += JSON.stringify(data, null, 2) + '\\n';\r\n } else {\r\n logEntry += String(data) + '\\n';\r\n }\r\n }\r\n logEntry += '-'.repeat(40) + '\\n';\r\n\r\n fs.appendFileSync(this.logPath, logEntry);\r\n } catch (e) {\r\n // calculated risk: silence logging errors to not break app\r\n }\r\n }\r\n}\r\n","import { FileLogger } from '../debug/file-logger.js';\r\n\r\nexport interface SSECallbacks {\r\n onChunk?: (partialMessage: string) => void;\r\n onComplete?: (fullMessage: string, metadata?: any) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\nexport class SSEClient {\r\n /**\r\n * Streams agent response using Server-Sent Events.\r\n * \r\n * @param url - The SSE endpoint URL\r\n * @param requestPayload - The request payload to POST\r\n * @param headers - Request headers (including Authorization)\r\n * @param callbacks - Event callbacks for chunks, completion, and errors\r\n */\r\n async streamAgentResponse(\r\n url: string,\r\n requestPayload: unknown,\r\n headers: HeadersInit,\r\n callbacks: SSECallbacks = {}\r\n ): Promise<void> {\r\n const { onChunk, onComplete, onError } = callbacks;\r\n\r\n FileLogger.log('SSE', `Starting Request to ${url}`, {\r\n headers,\r\n payload: requestPayload\r\n });\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n ...headers,\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(requestPayload),\r\n });\r\n\r\n FileLogger.log('SSE', `Response Status: ${response.status} ${response.statusText}`);\r\n\r\n const responseHeaders: Record<string, string> = {};\r\n response.headers.forEach((value, key) => { responseHeaders[key] = value; });\r\n FileLogger.log('SSE', 'Response Headers', responseHeaders);\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n FileLogger.log('SSE', 'Response Error Body', errorText);\r\n throw new Error(`SSE request failed: ${response.status} ${response.statusText} - ${errorText}`);\r\n }\r\n\r\n if (!response.body) {\r\n throw new Error('Response body is null');\r\n }\r\n\r\n const reader = response.body.getReader();\r\n const decoder = new TextDecoder();\r\n let buffer = '';\r\n let fullMessage = '';\r\n let metadata: any = {};\r\n\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n\r\n if (done) {\r\n break;\r\n }\r\n\r\n // Decode chunk\r\n buffer += decoder.decode(value, { stream: true });\r\n\r\n // Process complete lines\r\n const lines = buffer.split('\\n');\r\n buffer = lines.pop() || ''; // Keep incomplete line in buffer\r\n\r\n for (const line of lines) {\r\n if (line.startsWith('data:')) {\r\n const data = line.slice(5).trim(); // Remove 'data:' prefix\r\n\r\n if (data === '[DONE]') {\r\n FileLogger.log('SSE', 'Stream Complete [DONE]', { fullMessage, metadata });\r\n // End of stream\r\n if (onComplete) {\r\n onComplete(fullMessage, metadata);\r\n }\r\n return;\r\n }\r\n\r\n try {\r\n const parsed = JSON.parse(data);\r\n const chunk = parsed.message || parsed.content || data;\r\n fullMessage += chunk;\r\n\r\n // Capture latest metadata (e.g. conversation_id)\r\n if (parsed.conversation_id) {\r\n metadata.conversation_id = parsed.conversation_id;\r\n }\r\n\r\n if (onChunk) {\r\n onChunk(chunk);\r\n }\r\n } catch (parseError) {\r\n // Not JSON, treat as plain text\r\n fullMessage += data;\r\n if (onChunk) {\r\n onChunk(data);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n FileLogger.log('SSE', 'Stream Ended Naturally', { fullMessage, metadata });\r\n\r\n // Stream ended without [DONE]\r\n if (onComplete) {\r\n onComplete(fullMessage, metadata);\r\n }\r\n\r\n } catch (error) {\r\n FileLogger.log('SSE', 'Stream Error', error);\r\n if (onError) {\r\n onError(error instanceof Error ? error : new Error(String(error)));\r\n } else {\r\n throw error;\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport const sseClient = new SSEClient();\r\n","import { z } from 'zod';\r\nimport { FileLogger } from '../debug/file-logger';\r\n\r\n// Action Schema\r\nexport const AgentActionSchema = z.object({\r\n type: z.enum(['create_file', 'modify_file', 'delete_file', 'talk_with_user', 'list_files', 'read_file', 'search_file', 'run_command', 'use_mcp_tool']),\r\n path: z.string().nullable().optional(), // Nullable for strict mode combatibility\r\n content: z.string().nullable().optional(),\r\n target_content: z.string().nullable().optional(),\r\n command: z.string().nullable().optional(),\r\n tool_name: z.string().nullable().optional(),\r\n tool_args: z.string().nullable().optional(), // JSON string argument\r\n});\r\n\r\nexport type AgentAction = z.infer<typeof AgentActionSchema>;\r\n\r\n// Command Schema (for future use)\r\nexport const AgentCommandSchema = z.object({\r\n command: z.string(),\r\n description: z.string(),\r\n critical: z.boolean(),\r\n});\r\n\r\n// Full Structured Response Schema\r\nexport const AgentResponseSchema = z.object({\r\n actions: z.array(AgentActionSchema),\r\n commands: z.array(AgentCommandSchema).optional(),\r\n summary: z.string().optional(),\r\n\r\n // Legacy fields handling for smooth transition/fallback\r\n message: z.string().optional(),\r\n conversation_id: z.string().optional(),\r\n});\r\n\r\nexport type AgentResponse = z.infer<typeof AgentResponseSchema>;\r\n\r\n/**\r\n * Parses raw agent response expecting a JSON string that matches our schema.\r\n */\r\nexport function parseAgentResponse(rawResponse: unknown): AgentResponse {\r\n FileLogger.log('PARSER', 'Parsing Agent Response', { rawType: typeof rawResponse });\r\n\r\n let parsedObj: any = {};\r\n let conversation_id: string | undefined;\r\n\r\n // 1. Handle string input (accumulated SSE or raw JSON string)\r\n if (typeof rawResponse === 'string') {\r\n FileLogger.log('PARSER', 'Type String', { length: rawResponse.length });\r\n try {\r\n parsedObj = extractFirstJson(rawResponse);\r\n } catch (e) {\r\n FileLogger.log('PARSER', 'String Parse Failed', { error: (e as Error).message });\r\n // Fallback: treat as simple message if not valid JSON\r\n return {\r\n actions: [{\r\n type: 'talk_with_user',\r\n content: rawResponse,\r\n path: ''\r\n }],\r\n message: rawResponse\r\n };\r\n }\r\n }\r\n // 2. Handle object input (direct API response)\r\n else if (typeof rawResponse === 'object' && rawResponse !== null) {\r\n const anyResp = rawResponse as any;\r\n conversation_id = anyResp.conversation_id;\r\n\r\n FileLogger.log('PARSER', 'Type Object', {\r\n hasContent: !!anyResp.content,\r\n hasMessage: !!anyResp.message,\r\n messageType: typeof anyResp.message\r\n });\r\n\r\n // Sometimes content is nested in 'content' or 'message'\r\n const stringContent = anyResp.content || anyResp.message;\r\n if (stringContent && typeof stringContent === 'string') {\r\n try {\r\n // Try to parse it as JSON actions\r\n const parsedInside = extractFirstJson(stringContent);\r\n // Only use it if it looks like an object (not just a primitive)\r\n if (typeof parsedInside === 'object' && parsedInside !== null) {\r\n parsedObj = parsedInside;\r\n FileLogger.log('PARSER', 'Inner JSON Parsed', { keys: Object.keys(parsedObj) });\r\n } else {\r\n // It was a string literal or number, treat as text\r\n parsedObj = rawResponse;\r\n FileLogger.log('PARSER', 'Inner JSON was primitive');\r\n }\r\n } catch (e) {\r\n // Not JSON, continue with rawResponse\r\n parsedObj = rawResponse;\r\n FileLogger.log('PARSER', 'Inner JSON Parse Error - treating as raw', { error: (e as Error).message });\r\n }\r\n } else {\r\n parsedObj = rawResponse;\r\n }\r\n\r\n // If we didn't successfully parse inner JSON actions, use the raw object\r\n if (!parsedObj.actions) {\r\n parsedObj = rawResponse;\r\n }\r\n }\r\n\r\n // 3. Normalize Actions\r\n // Ensure 'actions' array exists\r\n if (!parsedObj.actions) {\r\n FileLogger.log('PARSER', 'No Actions Found - Constructing Default');\r\n // If it looks like the legacy format or direct message\r\n return {\r\n conversation_id,\r\n actions: [{\r\n type: 'talk_with_user',\r\n content: parsedObj.message || JSON.stringify(parsedObj),\r\n path: ''\r\n }],\r\n message: parsedObj.message\r\n };\r\n }\r\n\r\n // 4. Validate against Schema\r\n // We construct the final object to match our schema structure\r\n const result = {\r\n actions: parsedObj.actions,\r\n commands: parsedObj.commands || [],\r\n summary: parsedObj.summary || '',\r\n conversation_id,\r\n message: parsedObj.summary || 'Agent Action' // Backward compatibility\r\n };\r\n\r\n\r\n FileLogger.log('PARSER', 'Final Result Constructed', { actionCount: result.actions.length });\r\n\r\n try {\r\n return AgentResponseSchema.parse(result);\r\n } catch (e) {\r\n FileLogger.log('PARSER', 'Schema Validation Failed', { error: (e as Error).message });\r\n throw e;\r\n }\r\n}\r\n\r\nfunction extractFirstJson(str: string): any {\r\n try {\r\n return JSON.parse(str);\r\n } catch (e) {\r\n // If simple parse fails, try to find the first balanced object\r\n const firstOpen = str.indexOf('{');\r\n if (firstOpen === -1) throw e;\r\n\r\n let balance = 0;\r\n let inString = false;\r\n let escape = false;\r\n\r\n for (let i = firstOpen; i < str.length; i++) {\r\n const char = str[i];\r\n\r\n if (escape) {\r\n escape = false;\r\n continue;\r\n }\r\n\r\n if (char === '\\\\') {\r\n escape = true;\r\n continue;\r\n }\r\n\r\n if (char === '\"') {\r\n inString = !inString;\r\n continue;\r\n }\r\n\r\n if (!inString) {\r\n if (char === '{') balance++;\r\n else if (char === '}') {\r\n balance--;\r\n if (balance === 0) {\r\n // Found the end of the first object\r\n const potentialJson = str.substring(firstOpen, i + 1);\r\n try {\r\n return JSON.parse(potentialJson);\r\n } catch (innerE) {\r\n // If this chunk failed, maybe our brace counting was off (e.g. comments?), throw original\r\n throw e;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n throw e;\r\n }\r\n}\r\n","import { workflowManager } from './workflow-manager.js';\r\n\r\n/**\r\n * Manages conversation IDs for agent interactions.\r\n * Stores conversation IDs in the workflow state to maintain context across sessions.\r\n */\r\nexport class ConversationManager {\r\n private static instance: ConversationManager;\r\n\r\n private constructor() { }\r\n\r\n public static getInstance(): ConversationManager {\r\n if (!ConversationManager.instance) {\r\n ConversationManager.instance = new ConversationManager();\r\n }\r\n return ConversationManager.instance;\r\n }\r\n\r\n /**\r\n * Saves a conversation ID for a specific agent type.\r\n * \r\n * @param agentType - The type of agent (e.g., 'business_analyst', 'architect')\r\n * @param conversationId - The conversation ID from the agent response\r\n */\r\n async saveConversationId(agentType: string, conversationId: string): Promise<void> {\r\n const state = await workflowManager.load();\r\n if (!state) {\r\n throw new Error('No workflow state found. Please run \"shark init\" first.');\r\n }\r\n\r\n // Initialize conversations object if it doesn't exist\r\n if (!state.conversations) {\r\n state.conversations = {};\r\n }\r\n\r\n state.conversations[agentType] = conversationId;\r\n await workflowManager.save(state);\r\n }\r\n\r\n /**\r\n * Retrieves the conversation ID for a specific agent type.\r\n * \r\n * @param agentType - The type of agent\r\n * @returns The conversation ID, or undefined if none exists\r\n */\r\n async getConversationId(agentType: string): Promise<string | undefined> {\r\n const state = await workflowManager.load();\r\n if (!state || !state.conversations) {\r\n return undefined;\r\n }\r\n\r\n return state.conversations[agentType];\r\n }\r\n\r\n /**\r\n * Clears the conversation ID for a specific agent type.\r\n * \r\n * @param agentType - The type of agent\r\n */\r\n async clearConversationId(agentType: string): Promise<void> {\r\n const state = await workflowManager.load();\r\n if (!state || !state.conversations) {\r\n return;\r\n }\r\n\r\n delete state.conversations[agentType];\r\n await workflowManager.save(state);\r\n }\r\n\r\n /**\r\n * Clears all conversation IDs.\r\n * Useful when transitioning to a new project or resetting state.\r\n */\r\n async clearAllConversations(): Promise<void> {\r\n const state = await workflowManager.load();\r\n if (!state) {\r\n return;\r\n }\r\n\r\n state.conversations = {};\r\n await workflowManager.save(state);\r\n }\r\n}\r\n\r\nexport const conversationManager = ConversationManager.getInstance();\r\n","import { ConfigManager } from '../config-manager.js';\r\n\r\n/**\r\n * Gets the currently active (logged-in) realm from config.\r\n * \r\n * @returns The active realm\r\n * @throws Error if no realm is active (user not logged in)\r\n */\r\nexport async function getActiveRealm(): Promise<string> {\r\n const configManager = ConfigManager.getInstance();\r\n const config = configManager.getConfig();\r\n const realm = config.activeRealm;\r\n\r\n if (!realm) {\r\n throw new Error(\r\n 'No active authentication found.\\n' +\r\n 'Please run \"shark login\" first to authenticate.'\r\n );\r\n }\r\n\r\n return realm;\r\n}\r\n","import { STACKSPOT_AGENT_API_BASE } from '../api/stackspot-client.js';\r\nimport { sseClient } from '../api/sse-client.js';\r\nimport { parseAgentResponse, AgentResponse } from './agent-response-parser.js';\r\nimport { conversationManager } from '../workflow/conversation-manager.js';\r\nimport { tokenStorage } from '../auth/token-storage.js';\r\nimport { getActiveRealm } from '../auth/get-active-realm.js';\r\nimport { tui } from '../../ui/tui.js';\r\nimport { colors } from '../../ui/colors.js';\r\n\r\nconst AGENT_TYPE = 'business_analyst';\r\n\r\n// TODO: Get this from config or environment variable\r\n// You get this ID when you create your custom agent in StackSpot Portal\r\nconst AGENT_ID = process.env.STACKSPOT_BA_AGENT_ID || '01KEJ95G304TNNAKGH5XNEEBVD';\r\n\r\nexport interface BAAgentOptions {\r\n agentId?: string; // Allow overriding agent ID\r\n onChunk?: (chunk: string) => void;\r\n onComplete?: (response: AgentResponse) => void;\r\n}\r\n\r\n/**\r\n * Orchestrates interaction with the Business Analyst agent.\r\n * Integrates all communication components into a complete flow.\r\n * Automatically uses the active realm from config (no need to pass it).\r\n * \r\n * @param prompt - User's project description\r\n * @param options - Configuration options (callbacks, optional agentId override)\r\n * @returns Complete agent response\r\n */\r\nexport async function runBusinessAnalystAgent(\r\n prompt: string,\r\n options: BAAgentOptions = {}\r\n): Promise<AgentResponse> {\r\n const { agentId, onChunk, onComplete } = options;\r\n\r\n // 1. Get active realm from config (auto-detect)\r\n const realm = await getActiveRealm();\r\n\r\n // 1. Get auth token\r\n const token = await tokenStorage.getToken(realm);\r\n if (!token) {\r\n throw new Error(`No authentication token found for realm '${realm}'. Please run 'shark login'.`);\r\n }\r\n\r\n // 2. Load existing conversation ID (if any)\r\n const existingConversationId = await conversationManager.getConversationId(AGENT_TYPE);\r\n\r\n // 3. Build request payload (StackSpot agent format)\r\n const requestPayload = {\r\n user_prompt: prompt,\r\n streaming: true,\r\n stackspot_knowledge: false, // Use agent's configured KS instead\r\n return_ks_in_response: true,\r\n deep_search_ks: false,\r\n conversation_id: existingConversationId,\r\n };\r\n\r\n // 4. Construct agent URL - CORRECT FORMAT\r\n const finalAgentId = agentId || AGENT_ID;\r\n const agentUrl = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${finalAgentId}/chat`;\r\n\r\n // 5. Prepare headers\r\n const headers = {\r\n 'Authorization': `Bearer ${token}`,\r\n 'Content-Type': 'application/json',\r\n };\r\n\r\n // 6. Stream agent response\r\n let fullMessage = '';\r\n let rawResponse: any = {};\r\n\r\n await sseClient.streamAgentResponse(\r\n agentUrl,\r\n requestPayload,\r\n headers,\r\n {\r\n onChunk: (chunk) => {\r\n fullMessage += chunk;\r\n if (onChunk) {\r\n onChunk(chunk);\r\n }\r\n },\r\n onComplete: async (message) => {\r\n // Build complete response object\r\n rawResponse = {\r\n message: message || fullMessage,\r\n conversation_id: existingConversationId, // Will be updated if new one provided\r\n };\r\n },\r\n onError: (error) => {\r\n throw error;\r\n },\r\n }\r\n );\r\n\r\n // 7. Parse response\r\n const parsedResponse = parseAgentResponse(rawResponse);\r\n\r\n // 8. Save new conversation ID (if provided)\r\n if (parsedResponse.conversation_id) {\r\n await conversationManager.saveConversationId(AGENT_TYPE, parsedResponse.conversation_id);\r\n }\r\n\r\n // 9. Call completion callback\r\n if (onComplete) {\r\n onComplete(parsedResponse);\r\n }\r\n\r\n return parsedResponse;\r\n}\r\n\r\n/**\r\n * Interactive Business Analyst session with TUI.\r\n * Prompts user for input and displays streamed response.\r\n * Automatically uses the active realm from config.\r\n */\r\nexport async function interactiveBusinessAnalyst(): Promise<void> {\r\n tui.intro('π― Business Analyst Agent');\r\n\r\n const prompt = await tui.text({\r\n message: 'Describe your project idea',\r\n placeholder: 'E.g., I want to build a task management app for teams...',\r\n validate: (value) => {\r\n if (!value || value.length < 10) return 'Please provide a detailed description (at least 10 characters)';\r\n },\r\n });\r\n\r\n if (tui.isCancel(prompt)) {\r\n tui.outro('Cancelled');\r\n return;\r\n }\r\n\r\n const spinner = tui.spinner();\r\n spinner.start('π¬ Business Analyst is thinking...');\r\n\r\n let responseText = '';\r\n\r\n try {\r\n await runBusinessAnalystAgent(prompt as string, {\r\n onChunk: (chunk) => {\r\n responseText += chunk;\r\n // Update spinner with preview (try to parse JSON if possible, otherwise raw)\r\n try {\r\n // Start of JSON?\r\n if (responseText.trim().startsWith('{')) {\r\n spinner.message(colors.dim('Receiving structured data...'));\r\n } else {\r\n spinner.message(colors.dim('Thinking...'));\r\n }\r\n } catch (e) {\r\n // ignore\r\n }\r\n },\r\n onComplete: async (response) => {\r\n spinner.stop('Response received');\r\n\r\n // Show summary if exists\r\n if (response.summary) {\r\n tui.log.info(colors.italic(response.summary));\r\n }\r\n\r\n // Handle Actions\r\n if (response.actions && response.actions.length > 0) {\r\n for (const action of response.actions) {\r\n\r\n // CASE 1: TALK WITH USER (Conventional Message)\r\n if (action.type === 'talk_with_user') {\r\n tui.log.info(colors.green('π€ BA Agent:'));\r\n console.log(action.content); // Print formatted markdown\r\n\r\n // We don't verify \"talk\", we just show it.\r\n // The flow will wait for next user input naturally at loop start?\r\n // Wait! We need a loop here?\r\n // runBusinessAnalystAgent is a ONE-OFF request.\r\n // The LOOP needs to be in interactiveBusinessAnalyst.\r\n }\r\n\r\n // CASE 2: FILE OPERATIONS (Autonomous Actions)\r\n else {\r\n tui.log.warning(`\\nπ€ Agent wants to ${action.type}: ${colors.bold(action.path || 'unknown')}`);\r\n\r\n // Show content preview\r\n if (action.content) {\r\n console.log(colors.dim('--- Content Preview ---'));\r\n console.log(action.content.substring(0, 300) + (action.content.length > 300 ? '...' : ''));\r\n console.log(colors.dim('-----------------------'));\r\n }\r\n\r\n const confirm = await tui.confirm({\r\n message: `Allow agent to ${action.type} '${action.path}'?`,\r\n active: 'Yes',\r\n inactive: 'No'\r\n });\r\n\r\n if (confirm) {\r\n // TODO: Add actual file system writing logic here\r\n // fs.writeFileSync(action.path!, action.content);\r\n tui.log.success(`β
Action executed: ${action.path} created.`);\r\n } else {\r\n tui.log.error('β Action denied.');\r\n }\r\n }\r\n }\r\n }\r\n if (response.tokens) {\r\n tui.log.info(`Tokens used: ${response.tokens.output || 0}`);\r\n }\r\n },\r\n });\r\n\r\n tui.outro('Session complete');\r\n } catch (error: any) {\r\n spinner.stop('β Error', 1);\r\n tui.log.error(error.message);\r\n throw error;\r\n }\r\n}\r\n","\r\nimport { STACKSPOT_AGENT_API_BASE } from '../api/stackspot-client.js';\r\nimport { sseClient } from '../api/sse-client.js';\r\nimport { parseAgentResponse, AgentResponse } from './agent-response-parser.js';\r\nimport { conversationManager } from '../workflow/conversation-manager.js';\r\nimport { tokenStorage } from '../auth/token-storage.js';\r\nimport { getActiveRealm } from '../auth/get-active-realm.js';\r\nimport { tui } from '../../ui/tui.js';\r\nimport { colors } from '../../ui/colors.js';\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport { FileLogger } from '../debug/file-logger.js';\r\nimport { handleListFiles, handleReadFile, handleSearchFile, startSmartReplace } from './agent-tools.js';\r\n\r\nconst AGENT_TYPE = 'specification_agent';\r\n\r\n// Placeholder ID - User must provide the real one via env or config\r\nconst AGENT_ID = process.env.STACKSPOT_SPEC_AGENT_ID || '01KEPXTX37FTB4N672TZST4SGP';\r\n\r\nexport interface SpecAgentOptions {\r\n agentId?: string;\r\n briefingPath?: string; // Path to the briefing file to read\r\n}\r\n\r\n/**\r\n * Interactive Specification Agent session.\r\n * Reads briefing, consults user, and generates tech-spec.md.\r\n */\r\nexport async function interactiveSpecificationAgent(options: SpecAgentOptions = {}): Promise<void> {\r\n FileLogger.init();\r\n tui.intro('ποΈ Specification Agent');\r\n\r\n // 1. Resolve Briefing File\r\n let briefingContent = '';\r\n let briefingPath = options.briefingPath;\r\n\r\n if (!briefingPath) {\r\n // Try to find a default briefing in current dir\r\n const files = fs.readdirSync(process.cwd());\r\n const defaultBriefing = files.find(f => f.endsWith('_briefing.md'));\r\n\r\n briefingPath = await tui.text({\r\n message: 'Path to Briefing file (Leave empty to skip)',\r\n initialValue: defaultBriefing || '',\r\n placeholder: 'e.g., todo-list_briefing.md',\r\n validate: (val) => {\r\n if (val && !fs.existsSync(val)) return 'File not found';\r\n }\r\n }) as string;\r\n }\r\n\r\n if (tui.isCancel(briefingPath)) return;\r\n\r\n if (briefingPath) {\r\n try {\r\n briefingContent = fs.readFileSync(briefingPath, 'utf-8');\r\n tui.log.info(`Loaded briefing: ${colors.bold(briefingPath)}`);\r\n } catch (e) {\r\n tui.log.error(`Failed to read briefing: ${e}`);\r\n return;\r\n }\r\n } else {\r\n tui.log.info('Skipping briefing file. Starting fresh or exploring existing project.');\r\n }\r\n\r\n // 2. Initial Prompt Construction\r\n const initialPrompt = briefingContent ? `\r\nTenho o seguinte Documento de Briefing de NegΓ³cio. \r\nPor favor, analise-o e inicie o processo de definiΓ§Γ£o da EspecificaΓ§Γ£o TΓ©cnica.\r\n\r\n---\r\n${briefingContent}\r\n---\r\n `.trim() : 'Gostaria de ajuda com uma especificaΓ§Γ£o tΓ©cnica ou explorar este projeto.';\r\n\r\n // 3. Start Conversation Loop\r\n await runSpecLoop(initialPrompt, options.agentId);\r\n}\r\n\r\n/**\r\n * Main Loop for Specification Agent\r\n */\r\nasync function runSpecLoop(initialMessage: string, overrideAgentId?: string) {\r\n let nextPrompt = initialMessage;\r\n let keepGoing = true;\r\n\r\n while (keepGoing) {\r\n const spinner = tui.spinner();\r\n spinner.start('ποΈ Specification Agent is thinking...');\r\n\r\n let responseText = '';\r\n let lastResponse: AgentResponse | null = null;\r\n\r\n try {\r\n // Call Agent\r\n lastResponse = await callSpecAgentApi(nextPrompt, (chunk) => {\r\n responseText += chunk;\r\n try {\r\n if (responseText.trim().startsWith('{')) {\r\n spinner.message(colors.dim('Receiving structured data...'));\r\n } else {\r\n spinner.message(colors.dim('Thinking...'));\r\n }\r\n } catch (e) { }\r\n }, overrideAgentId);\r\n\r\n spinner.stop('Response received');\r\n\r\n // Handle Response Actions\r\n if (lastResponse && lastResponse.actions) {\r\n // Reset next prompt, we will build it based on actions results\r\n let executionResults = \"\";\r\n let waitingForUser = false;\r\n\r\n for (const action of lastResponse.actions) {\r\n\r\n if (action.type === 'talk_with_user') {\r\n tui.log.info(colors.primary('π€ Architect:'));\r\n console.log(action.content);\r\n waitingForUser = true;\r\n }\r\n\r\n else if (action.type === 'list_files') {\r\n tui.log.info(`π List files in: ${colors.bold(action.path || '.')}`);\r\n const result = handleListFiles(action.path || '.');\r\n executionResults += `[Action list_files(${action.path}) Result]:\\n${result}\\n\\n`;\r\n tui.log.info(colors.dim(`Files listed.`));\r\n }\r\n\r\n else if (action.type === 'read_file') {\r\n tui.log.info(`π Read file: ${colors.bold(action.path || '')}`);\r\n const result = handleReadFile(action.path || '');\r\n executionResults += `[Action read_file(${action.path}) Result]:\\n${result}\\n\\n`;\r\n tui.log.info(colors.dim(`File read.`));\r\n }\r\n\r\n else if (action.type === 'search_file') {\r\n tui.log.info(`π Search file: ${colors.bold(action.path || '')}`);\r\n const result = handleSearchFile(action.path || '');\r\n executionResults += `[Action search_file(${action.path}) Result]:\\n${result}\\n\\n`;\r\n tui.log.info(colors.dim(`Files found.`));\r\n }\r\n\r\n else if (['create_file', 'modify_file', 'delete_file'].includes(action.type)) {\r\n tui.log.warning(`\\nπ€ Agent wants to ${action.type}: ${colors.bold(action.path || 'unknown')}`);\r\n\r\n // Preview\r\n if (action.content) {\r\n console.log(colors.dim('--- Content Preview ---'));\r\n console.log(action.content.substring(0, 300) + '...');\r\n console.log(colors.dim('-----------------------'));\r\n }\r\n\r\n const confirm = await tui.confirm({\r\n message: `Approve ${action.type}?`,\r\n active: 'Yes',\r\n inactive: 'No'\r\n });\r\n\r\n if (confirm) {\r\n if (action.path) {\r\n try {\r\n if (action.type === 'create_file') {\r\n fs.writeFileSync(action.path, action.content || '');\r\n tui.log.success(`β
Created: ${action.path}`);\r\n executionResults += `[Action create_file(${action.path})]: Success\\n\\n`;\r\n } else if (action.type === 'modify_file') {\r\n if (action.target_content) {\r\n const success = startSmartReplace(action.path, action.content || '', action.target_content, tui);\r\n executionResults += `[Action modify_file(${action.path})]: ${success ? 'Success' : 'Failed'}\\n\\n`;\r\n } else {\r\n fs.writeFileSync(action.path, action.content || '');\r\n tui.log.success(`β
Overwritten: ${action.path}`);\r\n executionResults += `[Action modify_file(${action.path})]: Success (Overwrite)\\n\\n`;\r\n }\r\n } else if (action.type === 'delete_file') {\r\n fs.unlinkSync(action.path);\r\n tui.log.success(`β
Deleted: ${action.path}`);\r\n executionResults += `[Action delete_file(${action.path})]: Success\\n\\n`;\r\n }\r\n } catch (e: any) {\r\n tui.log.error(`β Failed: ${e.message}`);\r\n executionResults += `[Action ${action.type}(${action.path})]: Error: ${e.message}\\n\\n`;\r\n }\r\n }\r\n } else {\r\n tui.log.error('β Action denied.');\r\n executionResults += `[Action ${action.type}]: User Denied\\n\\n`;\r\n }\r\n }\r\n }\r\n\r\n // Prepare next prompt\r\n if (executionResults) {\r\n // If actions produced output (like file list), send it back to agent automatically\r\n // But if the agent ALSO talked to user, we should give priority to user input??\r\n // Strategy: If agent asked something (talk_with_user), we MUST ask user.\r\n // The tool outputs are appended.\r\n\r\n if (waitingForUser) {\r\n const userReply = await tui.text({\r\n message: 'Your answer',\r\n placeholder: 'Type your answer...'\r\n });\r\n if (tui.isCancel(userReply)) {\r\n keepGoing = false;\r\n return;\r\n }\r\n nextPrompt = `${executionResults}\\n\\nUser Reply: ${userReply}`;\r\n tui.log.info(colors.dim('Auto-replying with tool results...'));\r\n } else {\r\n // Agent just did tools, let's auto-reply with results so it can continue\r\n nextPrompt = executionResults;\r\n FileLogger.log('SYSTEM', 'Auto-replying with Tool Results', { length: executionResults.length });\r\n tui.log.info(colors.dim('Auto-replying with tool results...'));\r\n }\r\n\r\n } else if (waitingForUser) {\r\n // Only talk, no tools\r\n const userReply = await tui.text({\r\n message: 'Your answer',\r\n placeholder: 'Type your answer...'\r\n });\r\n if (tui.isCancel(userReply)) {\r\n keepGoing = false;\r\n return;\r\n }\r\n nextPrompt = userReply as string;\r\n } else {\r\n // No actions? Weird.\r\n tui.log.warning('No actions taken.');\r\n keepGoing = false;\r\n }\r\n\r\n } else {\r\n tui.log.warning('No actions received from agent.');\r\n keepGoing = false;\r\n }\r\n\r\n } catch (error: any) {\r\n spinner.stop('Error');\r\n tui.log.error(error.message);\r\n keepGoing = false;\r\n }\r\n }\r\n}\r\n\r\n// --- Helper Functions in agent-tools.ts ---\r\n\r\n// --- API Wrapper ---\r\n\r\nasync function callSpecAgentApi(prompt: string, onChunk: (chunk: string) => void, agentId?: string): Promise<AgentResponse> {\r\n const realm = await getActiveRealm();\r\n const token = await tokenStorage.getToken(realm);\r\n if (!token) throw new Error('Not logged in');\r\n\r\n const conversationId = await conversationManager.getConversationId(AGENT_TYPE);\r\n\r\n const payload = {\r\n user_prompt: prompt,\r\n streaming: true,\r\n stackspot_knowledge: false,\r\n return_ks_in_response: true,\r\n use_conversation: true,\r\n conversation_id: conversationId\r\n };\r\n\r\n const finalId = agentId || AGENT_ID;\r\n const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${finalId}/chat`;\r\n\r\n let fullMsg = '';\r\n let raw: any = {};\r\n\r\n FileLogger.log('AGENT', 'Calling Agent API', {\r\n agentId: finalId,\r\n conversationId,\r\n prompt: prompt.substring(0, 500) // Log summary of prompt\r\n });\r\n\r\n await sseClient.streamAgentResponse(url, payload, { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, {\r\n onChunk: (c) => { fullMsg += c; onChunk(c); },\r\n onComplete: (msg, metadata) => {\r\n // Prefer conversation_id from metadata (server response), fallback to sent ID\r\n const returnedId = metadata?.conversation_id;\r\n\r\n FileLogger.log('AGENT', 'Response Complete', {\r\n conversationId,\r\n returnedId,\r\n messageLength: msg?.length\r\n });\r\n\r\n raw = {\r\n message: msg || fullMsg,\r\n conversation_id: returnedId || conversationId\r\n };\r\n },\r\n onError: (e) => { throw e; }\r\n });\r\n\r\n const parsed = parseAgentResponse(raw);\r\n if (parsed.conversation_id) {\r\n await conversationManager.saveConversationId(AGENT_TYPE, parsed.conversation_id);\r\n }\r\n\r\n return parsed;\r\n}\r\n","\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport fg from 'fast-glob';\r\nimport { colors } from '../../ui/colors.js';\r\nimport { tui } from '../../ui/tui.js';\r\n\r\n/**\r\n * Shared tools for Agent interaction (File System, etc.)\r\n */\r\n\r\nexport function handleListFiles(dirPath: string): string {\r\n try {\r\n const fullPath = path.resolve(process.cwd(), dirPath);\r\n if (!fs.existsSync(fullPath)) return `Error: Directory ${dirPath} does not exist.`;\r\n\r\n const items = fs.readdirSync(fullPath, { withFileTypes: true });\r\n return items.map(item => {\r\n return `${item.isDirectory() ? '[DIR]' : '[FILE]'} ${item.name}`;\r\n }).join('\\n');\r\n } catch (e: any) {\r\n return `Error listing files: ${e.message}`;\r\n }\r\n}\r\n\r\nexport function handleReadFile(filePath: string): string {\r\n try {\r\n const fullPath = path.resolve(process.cwd(), filePath);\r\n if (!fs.existsSync(fullPath)) return `Error: File ${filePath} does not exist.`;\r\n\r\n // Limit size?\r\n const stats = fs.statSync(fullPath);\r\n if (stats.size > 100 * 1024) return `Error: File too large to read (${stats.size} bytes). Limit is 100KB.`;\r\n\r\n return fs.readFileSync(fullPath, 'utf-8');\r\n } catch (e: any) {\r\n return `Error reading file: ${e.message}`;\r\n }\r\n}\r\n\r\nexport function handleSearchFile(pattern: string): string {\r\n try {\r\n // Limit scope to current directory for safety?\r\n // Patterns are relative to process.cwd()\r\n const entries = fg.sync(pattern, { dot: true });\r\n if (entries.length === 0) return 'No files found matching pattern.';\r\n return entries.slice(0, 50).join('\\n');\r\n } catch (e: any) {\r\n return `Error searching files: ${e.message}`;\r\n }\r\n}\r\n\r\nexport function startSmartReplace(filePath: string, newContent: string, targetContent: string, tui: any): boolean {\r\n if (!fs.existsSync(filePath)) {\r\n tui.log.error(`β File not found for modification: ${filePath}`);\r\n return false;\r\n }\r\n\r\n const currentFileContent = fs.readFileSync(filePath, 'utf-8');\r\n\r\n // 1. Validation: Does target exist?\r\n // Normalize line endings?\r\n if (!currentFileContent.includes(targetContent)) {\r\n tui.log.error(`β Target content not found in ${filePath}. Modification aborted.`);\r\n console.log(colors.dim('--- Target Content Expected ---'));\r\n console.log(targetContent.substring(0, 200) + '...');\r\n return false;\r\n }\r\n\r\n // 2. Validation: Is it unique?\r\n const occurrences = currentFileContent.split(targetContent).length - 1;\r\n if (occurrences > 1) {\r\n tui.log.error(`β Ambiguous target: Found ${occurrences} occurrences in ${filePath}. Modification aborted.`);\r\n return false;\r\n }\r\n\r\n // 3. Apply Replacement\r\n const updatedContent = currentFileContent.replace(targetContent, newContent);\r\n fs.writeFileSync(filePath, updatedContent);\r\n tui.log.success(`β
Smart Replace Applied: ${filePath}`);\r\n return true;\r\n}\r\n\r\nexport async function handleRunCommand(command: string): Promise<string> {\r\n const { spawn } = await import('node:child_process');\r\n try {\r\n tui.log.info(`π» Executing: ${colors.dim(command)}`);\r\n\r\n // Split command into cmd and args (naive split, use specific parser if needed for complex quotes)\r\n // For simplicity in Agent usage, we might act as a shell?\r\n // Let's use shell: true option for ease of piping/env usage.\r\n\r\n return new Promise((resolve) => {\r\n const child = spawn(command, {\r\n shell: true,\r\n stdio: ['ignore', 'pipe', 'pipe'],\r\n cwd: process.cwd()\r\n });\r\n\r\n let stdout = '';\r\n let stderr = '';\r\n\r\n // Timeout safety: 5 minutes\r\n const timer = setTimeout(() => {\r\n child.kill();\r\n resolve(`Error: Command timed out after 5 minutes.\\nOutput so far:\\n${stdout}\\n${stderr}`);\r\n }, 5 * 60 * 1000);\r\n\r\n child.stdout.on('data', (data) => {\r\n const chunk = data.toString();\r\n stdout += chunk;\r\n // Optional: Stream to TUI if verbose?\r\n });\r\n\r\n child.stderr.on('data', (data) => {\r\n stderr += data.toString();\r\n });\r\n\r\n child.on('close', (code) => {\r\n clearTimeout(timer);\r\n if (code === 0) {\r\n resolve(stdout.trim() || 'Command executed successfully (no output).');\r\n } else {\r\n resolve(`Command failed with exit code ${code}.\\nSTDERR:\\n${stderr}\\nSTDOUT:\\n${stdout}`);\r\n }\r\n });\r\n\r\n child.on('error', (err) => {\r\n clearTimeout(timer);\r\n resolve(`Error executing command: ${err.message}`);\r\n });\r\n });\r\n\r\n } catch (e: any) {\r\n return `Error launching command: ${e.message}`;\r\n }\r\n}\r\n","\r\nimport { Command } from 'commander';\r\nimport { interactiveScanAgent } from '../core/agents/scan-agent.js';\r\n\r\nexport const scanCommand = new Command('scan')\r\n .description('Analyze the project and generate context documentation')\r\n .option('-o, --output <path>', 'Output file path (default: _bmad/project-context/project-context.md)')\r\n .option('--depth <level>', 'Scan depth (quick, deep, exhaustive)', 'quick')\r\n .action(async (options) => {\r\n try {\r\n await interactiveScanAgent(options);\r\n } catch (error: any) {\r\n console.error('Error during scan:', error.message);\r\n process.exit(1);\r\n }\r\n });\r\n","\r\nimport { STACKSPOT_AGENT_API_BASE } from '../api/stackspot-client.js';\r\nimport { sseClient } from '../api/sse-client.js';\r\nimport { parseAgentResponse, AgentResponse } from './agent-response-parser.js';\r\nimport { conversationManager } from '../workflow/conversation-manager.js';\r\nimport { tokenStorage } from '../auth/token-storage.js';\r\nimport { getActiveRealm } from '../auth/get-active-realm.js';\r\nimport { tui } from '../../ui/tui.js';\r\nimport { colors } from '../../ui/colors.js';\r\nimport { FileLogger } from '../debug/file-logger.js';\r\nimport { handleListFiles, handleReadFile, handleSearchFile } from './agent-tools.js';\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\n\r\nconst AGENT_TYPE = 'scan_agent';\r\n// We can reuse the Specification Agent ID or a new one. Using env var or default.\r\n// Ideally, we'd have a specific ID for Scan Agent. For now, assume a placeholder or reuse.\r\nconst AGENT_ID = process.env.STACKSPOT_SCAN_AGENT_ID || '01KEQ9AHWB550J2244YBH3QATN'; // User provided Agent ID\r\n\r\n/**\r\n * Scan Agent implementation.\r\n * It autonomously explores the project and generates project-context.md\r\n */\r\nimport { ConfigManager } from '../config-manager.js';\r\n\r\n// ... (existing imports)\r\n\r\n/**\r\n * Scan Agent implementation.\r\n * It autonomously explores the project and generates project-context.md\r\n */\r\nexport async function interactiveScanAgent(options: { output?: string, depth?: string } = {}): Promise<void> {\r\n FileLogger.init();\r\n tui.intro('π΅οΈββοΈ Scan Agent');\r\n\r\n const config = ConfigManager.getInstance().getConfig();\r\n const language = config.language || 'English';\r\n\r\n const projectRoot = process.cwd();\r\n // Use options.output if provided, otherwise default to _sharkrc/project-context.md\r\n // If output option is provided, resolve it.\r\n // If not, use _sharkrc directory (create if needed).\r\n\r\n let outputFile: string;\r\n\r\n if (options.output) {\r\n outputFile = path.resolve(process.cwd(), options.output);\r\n } else {\r\n const outputDir = path.resolve(projectRoot, '_sharkrc');\r\n if (!fs.existsSync(outputDir)) {\r\n // Check if _sharkrc exists as a file (common config file name), if so, error or warn?\r\n // User requested \"pasta _sharkrc\".\r\n const stat = fs.existsSync(outputDir) ? fs.statSync(outputDir) : null;\r\n if (stat && stat.isFile()) {\r\n tui.log.warning(`Warning: '_sharkrc' exists as a file. Using '_bmad/project-context' instead to avoid overwrite.`);\r\n const fallbackDir = path.resolve(projectRoot, '_bmad/project-context');\r\n if (!fs.existsSync(fallbackDir)) fs.mkdirSync(fallbackDir, { recursive: true });\r\n outputFile = path.join(fallbackDir, 'project-context.md');\r\n } else {\r\n fs.mkdirSync(outputDir, { recursive: true });\r\n outputFile = path.join(outputDir, 'project-context.md');\r\n }\r\n } else {\r\n fs.mkdirSync(outputDir, { recursive: true });\r\n outputFile = path.join(outputDir, 'project-context.md');\r\n }\r\n }\r\n\r\n tui.log.info(`Scanning project at: ${colors.bold(projectRoot)}`);\r\n tui.log.info(`Output targeted at: ${colors.bold(outputFile)}`);\r\n tui.log.info(`Language: ${colors.bold(language)}`);\r\n\r\n const configFileRelative = path.relative(projectRoot, outputFile);\r\n\r\n // Construct the \"Super Prompt\"\r\n const superPrompt = `\r\nYou are the **Scan Agent**, an expert software architect and analyst.\r\nYour mission is to explore this project's codebase and generate a comprehensive context file that will be used by other AI agents (specifically a Developer Agent) to understand how to work on this project.\r\n\r\n**Goal**: Create a markdown file at: \\`${configFileRelative}\\`.\r\n\r\n**LANGUAGE INSTRUCTION**:\r\nYou MUST write the content of the \\`project-context.md\\` file in **${language}**.\r\nAlso, strictly interact with tools using the appropriate payload.\r\n\r\n**Instructions**:\r\n1. **Analyze Structure**: Use \\`list_files\\` to understand the root directory and key subdirectories (src, tools, config, etc.).\r\n2. **Identify Tech Stack**: Use \\`read_file\\` or \\`search_file\\` on key manifests (package.json, pom.xml, go.mod, Dockerfile, etc.) to determine languages, frameworks, and versions.\r\n3. **Map Architecture**: Infer the architectural pattern (Monolith? Microservices? Clean Architecture?) based on folder structure and key files.\r\n4. **Document Key Paths**: Identify where source code, tests, and configs live.\r\n\r\n**Output Format** (Markdown):\r\nThe final action MUST be \\`create_file\\` (or \\`modify_file\\`) for the target file with the following structure:\r\n\r\n# Project Context\r\n\r\n## Overview\r\n[Brief description of what this project seems to be]\r\n\r\n## Tech Stack\r\n- **Language**: [e.g. TypeScript]\r\n- **Framework**: [e.g. React, Express, NestJS]\r\n- **Build Tool**: [e.g. Vite, Webpack]\r\n- **Database**: [e.g. PostgreSQL, Prisma] (if detected)\r\n\r\n## Architecture\r\n[Description of the folder structure and architectural patterns detected]\r\n\r\n## Key Locations\r\n- **Source**: [path/to/src]\r\n- **Tests**: [path/to/tests]\r\n- **Config**: [path/to/config]\r\n\r\n## Commands\r\n[List of discovered npm scripts or makefile commands for dev, build, test]\r\n\r\n---\r\n\r\n**Rules**:\r\n- Do NOT guess. If you are unsure, check the file.\r\n- Be concise.\r\n- Focus on FACTS that a Developer Agent needs to know to write code correcty.\r\n- Start by listing the root directory.\r\n`.trim();\r\n\r\n await runScanLoop(superPrompt, outputFile);\r\n}\r\n\r\n// ... (rest of the file)\r\n\r\nasync function runScanLoop(initialPrompt: string, targetPath: string) {\r\n let nextPrompt = initialPrompt;\r\n let keepGoing = true;\r\n let stepCount = 0;\r\n const MAX_STEPS = 15; // Safety limit\r\n\r\n while (keepGoing && stepCount < MAX_STEPS) {\r\n stepCount++;\r\n const spinner = tui.spinner();\r\n spinner.start(`π΅οΈββοΈ Scan Agent analyzing (Step ${stepCount}/${MAX_STEPS})...`);\r\n\r\n let responseText = '';\r\n let lastResponse: AgentResponse | null = null;\r\n\r\n try {\r\n // Call Agent\r\n lastResponse = await callScanAgentApi(nextPrompt, (chunk) => {\r\n responseText += chunk;\r\n // Optional: Update spinner message based on chunk if needed\r\n });\r\n\r\n spinner.stop('Step complete');\r\n\r\n // Handle Response Actions\r\n if (lastResponse && lastResponse.actions) {\r\n let executionResults = \"\";\r\n let fileCreated = false;\r\n\r\n for (const action of lastResponse.actions) {\r\n if (action.type === 'list_files') {\r\n tui.log.info(`π Scanning dir: ${colors.bold(action.path || '.')}`);\r\n const result = handleListFiles(action.path || '.');\r\n executionResults += `[Action list_files(${action.path}) Result]:\\n${result}\\n\\n`;\r\n }\r\n else if (action.type === 'read_file') {\r\n tui.log.info(`π Reading file: ${colors.bold(action.path || '')}`);\r\n const result = handleReadFile(action.path || '');\r\n // Truncate if too long for context window? Agent Tools already limits size.\r\n executionResults += `[Action read_file(${action.path}) Result]:\\n${result}\\n\\n`;\r\n }\r\n else if (action.type === 'search_file') {\r\n tui.log.info(`π Searching: ${colors.bold(action.path || '')}`);\r\n const result = handleSearchFile(action.path || '');\r\n executionResults += `[Action search_file(${action.path}) Result]:\\n${result}\\n\\n`;\r\n }\r\n else if (action.type === 'create_file' || action.type === 'modify_file') {\r\n // Check if this is our target file\r\n // The agent might try to create other files, but we mainly care about the context file.\r\n // We will allow it to create the target file automatically without prompt if it matches.\r\n\r\n // For safety, let's just confirm. Or since this is \"Scan\", maybe we auto-accept?\r\n // Let's auto-accept if it is the target file, confirm otherwise.\r\n const resolvedActionPath = path.resolve(action.path || '');\r\n const resolvedTargetPath = path.resolve(targetPath);\r\n let isTarget = resolvedActionPath === resolvedTargetPath;\r\n\r\n // Fallback: If agent uses wrong directory but correct filename \"project-context.md\", allow it and force correct path.\r\n if (!isTarget && path.basename(action.path || '') === 'project-context.md') {\r\n tui.log.warning(`Agent targeted '${action.path}' but we enforce '${path.relative(process.cwd(), targetPath)}'. Redirecting write.`);\r\n isTarget = true;\r\n // Update action path for logging consistency (optional, but good for clarity)\r\n action.path = targetPath;\r\n }\r\n\r\n if (isTarget) {\r\n // Enforce writing to the correct targetPath regardless of what agent said\r\n const finalPath = targetPath;\r\n if (action.type === 'create_file') {\r\n fs.writeFileSync(finalPath, action.content || '');\r\n tui.log.success(`β
Generated Context: ${finalPath}`);\r\n fileCreated = true;\r\n } else {\r\n // Modify\r\n fs.writeFileSync(finalPath, action.content || ''); // Overwrite for now\r\n tui.log.success(`β
Updated Context: ${finalPath}`);\r\n fileCreated = true;\r\n }\r\n executionResults += `[Action ${action.type}]: Success. Task Completed.\\n`;\r\n } else {\r\n tui.log.warning(`Agent wants to write to unexpected file: ${action.path}`);\r\n // Skip for now to avoid side effects during scan, or ask user?\r\n // Let's just log it.\r\n executionResults += `[Action ${action.type}]: Skipped (Scan Agent only writes context file)\\n`;\r\n }\r\n }\r\n else if (action.type === 'talk_with_user') {\r\n tui.log.info(colors.primary('π€ Scan Agent asks:'));\r\n console.log(action.content);\r\n // We don't really want to chat during auto-scan, but if it asks, we should probably answer or stop.\r\n // For now, let's stop and ask user.\r\n const reply = await tui.text({ message: 'Agent needs input:', placeholder: 'Reply...' });\r\n executionResults += `[User Reply]: ${reply}\\n`;\r\n }\r\n }\r\n\r\n if (fileCreated) {\r\n tui.log.success('β¨ Scan completed successfully!');\r\n keepGoing = false;\r\n } else {\r\n // Feed results back\r\n nextPrompt = executionResults;\r\n FileLogger.log('SCAN', 'Auto-replying with results', { length: executionResults.length });\r\n }\r\n\r\n } else {\r\n // No actions?\r\n if (stepCount > 1) {\r\n tui.log.warning('Scan Agent stopped without actions.');\r\n keepGoing = false;\r\n } else {\r\n // First turn and no actions? problematic.\r\n }\r\n }\r\n\r\n } catch (error: any) {\r\n spinner.stop('Error');\r\n tui.log.error(error.message);\r\n keepGoing = false;\r\n }\r\n }\r\n}\r\n\r\n\r\nasync function callScanAgentApi(prompt: string, onChunk: (chunk: string) => void): Promise<AgentResponse> {\r\n const realm = await getActiveRealm();\r\n const token = await tokenStorage.getToken(realm);\r\n if (!token) throw new Error('Not logged in');\r\n\r\n // Generate a temporary conversation ID for this scan session\r\n // We might not need to persist it long-term, but we need one for the session.\r\n // Or we rely on the one returned.\r\n let conversationId = await conversationManager.getConversationId(AGENT_TYPE);\r\n\r\n // If no conversation exists, that's fine, API will create one.\r\n\r\n const payload = {\r\n user_prompt: prompt,\r\n streaming: true,\r\n stackspot_knowledge: false,\r\n return_ks_in_response: true,\r\n use_conversation: true,\r\n conversation_id: conversationId\r\n };\r\n\r\n const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${AGENT_ID}/chat`;\r\n let fullMsg = '';\r\n let raw: any = {};\r\n\r\n FileLogger.log('SCAN', 'Calling API', { promptLength: prompt.length });\r\n\r\n await sseClient.streamAgentResponse(url, payload, { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, {\r\n onChunk: (c) => { fullMsg += c; onChunk(c); },\r\n onComplete: (msg, metadata) => {\r\n const returnedId = metadata?.conversation_id;\r\n raw = {\r\n message: msg || fullMsg,\r\n conversation_id: returnedId || conversationId\r\n };\r\n },\r\n onError: (e) => { throw e; }\r\n });\r\n\r\n const parsed = parseAgentResponse(raw);\r\n if (parsed.conversation_id) {\r\n await conversationManager.saveConversationId(AGENT_TYPE, parsed.conversation_id);\r\n }\r\n return parsed;\r\n}\r\n","\r\nimport { Command } from 'commander';\r\nimport { interactiveDeveloperAgent } from '../core/agents/developer-agent.js';\r\n\r\nexport const devCommand = new Command('dev')\r\n .description('Starts the Shark Developer Agent (Shark Dev)')\r\n .option('-t, --task <type>', 'Initial task description')\r\n .option('-c, --context <path>', 'Path to custom context file')\r\n .action(async (options) => {\r\n await interactiveDeveloperAgent(options);\r\n });\r\n","\r\nimport { STACKSPOT_AGENT_API_BASE } from '../api/stackspot-client.js';\r\nimport { sseClient } from '../api/sse-client.js';\r\nimport { parseAgentResponse, AgentResponse, AgentAction } from './agent-response-parser.js';\r\nimport { conversationManager } from '../workflow/conversation-manager.js';\r\nimport { tokenStorage } from '../auth/token-storage.js';\r\nimport { getActiveRealm } from '../auth/get-active-realm.js';\r\nimport { tui } from '../../ui/tui.js';\r\nimport { colors } from '../../ui/colors.js';\r\nimport { ConfigManager } from '../config-manager.js';\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport { FileLogger } from '../debug/file-logger.js';\r\nimport {\r\n handleListFiles,\r\n handleReadFile,\r\n handleSearchFile,\r\n startSmartReplace,\r\n handleRunCommand\r\n} from './agent-tools.js';\r\n\r\nconst AGENT_TYPE = 'developer_agent';\r\n// Placeholder ID - User must provide the real one via env\r\nconst AGENT_ID = process.env.STACKSPOT_DEV_AGENT_ID || '01KEQCGJ65YENRA4QBXVN1YFFX'; // Default ID if not set in env\r\n\r\nexport async function interactiveDeveloperAgent(options: { task?: string, context?: string } = {}): Promise<void> {\r\n FileLogger.init();\r\n tui.intro('π¦ Shark Dev Agent');\r\n\r\n if (AGENT_ID === 'PENDING_CONFIGURATION') {\r\n tui.log.error('β STACKSPOT_DEV_AGENT_ID not configured in .env');\r\n return;\r\n }\r\n\r\n // 1. Load Context\r\n const projectRoot = process.cwd();\r\n let contextContent = '';\r\n const defaultContextPath = path.resolve(projectRoot, '_sharkrc', 'project-context.md');\r\n const specificContextPath = options.context ? path.resolve(projectRoot, options.context) : defaultContextPath;\r\n\r\n if (fs.existsSync(specificContextPath)) {\r\n try {\r\n contextContent = fs.readFileSync(specificContextPath, 'utf-8');\r\n tui.log.info(`π Context loaded from: ${colors.dim(path.relative(projectRoot, specificContextPath))}`);\r\n } catch (e) {\r\n tui.log.warning(`Failed to read context file: ${e}`);\r\n }\r\n } else {\r\n tui.log.warning(`β οΈ No context file found. Agent will run without pre-loaded context.`);\r\n }\r\n\r\n // 2. Prepare Initial Prompt\r\n let nextPrompt = options.task || \"I'm ready to help. What's the task?\";\r\n if (contextContent) {\r\n nextPrompt += `\\n\\n--- PROJECT CONTEXT ---\\n${contextContent}\\n-----------------------`;\r\n }\r\n\r\n // 3. Main Loop\r\n let keepGoing = true;\r\n const spinner = tui.spinner();\r\n\r\n while (keepGoing) {\r\n try {\r\n spinner.start('Waiting for Agent...');\r\n\r\n // Call API\r\n let lastResponse: AgentResponse | null = null;\r\n await callDevAgentApi(nextPrompt, (chunk) => {\r\n // Optional: Stream text to TUI if needed\r\n if (!lastResponse) {\r\n // Maybe show thinking dots?\r\n }\r\n }).then(resp => {\r\n lastResponse = resp;\r\n });\r\n\r\n spinner.stop('Response received');\r\n\r\n if (lastResponse && (lastResponse as AgentResponse).actions) {\r\n const response = lastResponse as AgentResponse;\r\n let executionResults = \"\";\r\n let waitingForUser = false;\r\n\r\n for (const action of response.actions) {\r\n\r\n if (action.type === 'talk_with_user') {\r\n tui.log.info(colors.primary('π€ Shark Dev:'));\r\n console.log(action.content);\r\n waitingForUser = true;\r\n }\r\n\r\n else if (action.type === 'list_files') {\r\n tui.log.info(`π Scanning dir: ${colors.dim(action.path || '.')}`);\r\n const result = handleListFiles(action.path || '.');\r\n executionResults += `[Action list_files(${action.path}) Result]:\\n${result}\\n\\n`;\r\n }\r\n\r\n else if (action.type === 'read_file') {\r\n tui.log.info(`π Reading: ${colors.dim(action.path || '')}`);\r\n const result = handleReadFile(action.path || '');\r\n executionResults += `[Action read_file(${action.path}) Result]:\\n${result}\\n\\n`;\r\n }\r\n\r\n else if (action.type === 'search_file') {\r\n tui.log.info(`π Searching: ${colors.dim(action.path || '')}`);\r\n const result = handleSearchFile(action.path || '');\r\n executionResults += `[Action search_file(${action.path}) Result]:\\n${result}\\n\\n`;\r\n }\r\n\r\n else if (action.type === 'run_command') {\r\n const cmd = action.command || '';\r\n tui.log.info(`π» Executing: ${colors.dim(cmd)}`);\r\n // Execute Command\r\n // Warning: Prompt user for non-safe commands? \r\n // For now, let's assume Shark Dev is trusted or ask for everything.\r\n // Let's ask for confirmation for consistency.\r\n const confirm = await tui.confirm({\r\n message: `Execute command: ${cmd}?`,\r\n active: 'Yes',\r\n inactive: 'No'\r\n });\r\n\r\n if (confirm) {\r\n const result = await handleRunCommand(cmd);\r\n executionResults += `[Action run_command(${cmd}) Result]:\\n${result}\\n\\n`;\r\n } else {\r\n executionResults += `[Action run_command]: User blocked execution.\\n\\n`;\r\n }\r\n }\r\n\r\n else if (['create_file', 'modify_file'].includes(action.type)) {\r\n const isCreate = action.type === 'create_file';\r\n const filePath = action.path || '';\r\n tui.log.warning(`\\nπ€ Agent wants to ${isCreate ? 'CREATE' : 'MODIFY'}: ${colors.bold(filePath)}`);\r\n\r\n // Preview content (maybe diff?)\r\n // For brevity, just log start\r\n if (action.content) {\r\n console.log(colors.dim('--- Content ---\\n') + action.content.substring(0, 200) + '...\\n' + colors.dim('---------------'));\r\n }\r\n\r\n const confirm = await tui.confirm({\r\n message: `Approve changes to ${filePath}?`,\r\n active: 'Yes',\r\n inactive: 'No'\r\n });\r\n\r\n if (confirm) {\r\n if (filePath) {\r\n const targetPath = path.resolve(projectRoot, filePath);\r\n const dir = path.dirname(targetPath);\r\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\r\n\r\n if (isCreate) {\r\n fs.writeFileSync(targetPath, action.content || '');\r\n tui.log.success(`β
Created: ${filePath}`);\r\n executionResults += `[Action create_file(${filePath})]: Success\\n\\n`;\r\n } else {\r\n // Modify\r\n if (action.target_content) {\r\n const success = startSmartReplace(filePath, action.content || '', action.target_content, tui);\r\n executionResults += `[Action modify_file(${filePath})]: ${success ? 'Success' : 'Failed'}\\n\\n`;\r\n } else {\r\n // Fallback overwrite if no target_content provided (should be rare given schema)\r\n // But for Dev Agent, schema requires new_content (mapped to content) and target_content.\r\n // If target_content missing, we might fail or overwrite.\r\n // Let's safe fail.\r\n tui.log.error('β Missing target_content for modification.');\r\n executionResults += `[Action modify_file]: Failed. Missing target_content.\\n\\n`;\r\n }\r\n }\r\n }\r\n } else {\r\n tui.log.error('β Denied.');\r\n executionResults += `[Action ${action.type}]: User Denied.\\n\\n`;\r\n }\r\n }\r\n }\r\n\r\n // Prepare next prompt\r\n if (executionResults) {\r\n if (waitingForUser) {\r\n const userReply = await tui.text({ message: 'Your answer:' });\r\n if (tui.isCancel(userReply)) { keepGoing = false; break; }\r\n nextPrompt = `${executionResults}\\n\\nUser Reply: ${userReply}`;\r\n } else {\r\n // Auto-continue\r\n nextPrompt = executionResults;\r\n tui.log.info(colors.dim('Sending tool results to agent...'));\r\n }\r\n } else if (waitingForUser) {\r\n const userReply = await tui.text({ message: 'Your answer:' });\r\n if (tui.isCancel(userReply)) { keepGoing = false; break; }\r\n nextPrompt = userReply as string;\r\n } else {\r\n // Fallback: If no actions but we have a message/summary, assume it's a talk\r\n if (response.message) {\r\n tui.log.info(colors.primary('π€ Shark Dev:'));\r\n console.log(response.message);\r\n const userReply = await tui.text({ message: 'Your answer:' });\r\n if (tui.isCancel(userReply)) {\r\n keepGoing = false;\r\n } else {\r\n nextPrompt = userReply as string;\r\n }\r\n } else {\r\n tui.log.warning('Agent took no actions.');\r\n keepGoing = false;\r\n }\r\n }\r\n\r\n } else {\r\n tui.log.warning('Invalid response from agent.');\r\n keepGoing = false;\r\n }\r\n\r\n } catch (e: any) {\r\n spinner.stop('Error');\r\n tui.log.error(e.message);\r\n keepGoing = false;\r\n }\r\n }\r\n\r\n tui.outro('π Shark Dev Session Ended');\r\n}\r\n\r\nasync function callDevAgentApi(prompt: string, onChunk: (chunk: string) => void): Promise<AgentResponse> {\r\n const realm = await getActiveRealm();\r\n const token = await tokenStorage.getToken(realm);\r\n if (!token) throw new Error('Not logged in. Run shark login.');\r\n\r\n const conversationId = await conversationManager.getConversationId(AGENT_TYPE);\r\n\r\n const payload = {\r\n user_prompt: prompt,\r\n streaming: true,\r\n use_conversation: true,\r\n conversation_id: conversationId,\r\n stackspot_knowledge: false // Dev Agent focuses on project context\r\n };\r\n\r\n const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${AGENT_ID}/chat`;\r\n let fullMsg = '';\r\n let raw: any = {};\r\n\r\n await sseClient.streamAgentResponse(url, payload, { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, {\r\n onChunk: (c) => { fullMsg += c; onChunk(c); },\r\n onComplete: (msg, metadata) => {\r\n const returnedId = metadata?.conversation_id;\r\n raw = {\r\n message: msg || fullMsg,\r\n conversation_id: returnedId || conversationId\r\n };\r\n },\r\n onError: (e) => { throw e; }\r\n });\r\n\r\n const parsed = parseAgentResponse(raw);\r\n if (parsed.conversation_id) {\r\n await conversationManager.saveConversationId(AGENT_TYPE, parsed.conversation_id);\r\n }\r\n return parsed;\r\n}\r\n","import { Command } from 'commander';\r\nimport { runQAAgent } from '../core/agents/qa-agent';\r\n\r\nexport const qaCommand = new Command('qa')\r\n .description('Start the Shark QA Agent to test web applications')\r\n .option('--url <url>', 'Initial URL to test')\r\n .option('--scenario <scenario>', 'Scenario description or test case to execute')\r\n .action(async (options) => {\r\n try {\r\n await runQAAgent({\r\n initialUrl: options.url,\r\n scenario: options.scenario\r\n });\r\n } catch (error: any) {\r\n console.error('Failed to run QA Agent:', error.message);\r\n process.exit(1);\r\n }\r\n });\r\n","import { tui } from '../../ui/tui';\r\nimport { colors } from '../../ui/colors';\r\nimport { getActiveRealm } from '../auth/get-active-realm';\r\nimport { tokenStorage } from '../auth/token-storage';\r\nimport { sseClient } from '../api/sse-client';\r\nimport { parseAgentResponse, AgentAction, AgentResponse } from './agent-response-parser';\r\nimport { conversationManager } from '../workflow/conversation-manager';\r\nimport { handleReadFile, handleListFiles, handleSearchFile, handleRunCommand } from './agent-tools';\r\nimport fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\r\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\r\n\r\nconst AGENT_TYPE = 'qa_agent';\r\n\r\n// Allow override via env var, otherwise use a default (placeholder for now)\r\nconst AGENT_ID = process.env.STACKSPOT_QA_AGENT_ID || '01KEQFJZ3Q3JER11NH22HEZX9X';\r\n\r\ninterface QAAgentOptions {\r\n initialUrl?: string;\r\n scenario?: string;\r\n}\r\n\r\n// MCP Client Wrapper\r\nclass ChromeDevToolsClient {\r\n private client: Client | null = null;\r\n private transport: StdioClientTransport | null = null;\r\n\r\n async connect() {\r\n if (this.client) return;\r\n\r\n try {\r\n this.transport = new StdioClientTransport({\r\n command: 'npx',\r\n args: ['-y', 'chrome-devtools-mcp@latest']\r\n });\r\n\r\n this.client = new Client({\r\n name: \"shark-qa-client\",\r\n version: \"1.0.0\"\r\n }, {\r\n capabilities: {}\r\n });\r\n\r\n await this.client.connect(this.transport);\r\n tui.log.success('π Connected to Chrome DevTools MCP');\r\n } catch (e: any) {\r\n tui.log.error(`Failed to connect to Chrome MCP: ${e.message}`);\r\n throw e;\r\n }\r\n }\r\n\r\n async callTool(name: string, args: any) {\r\n if (!this.client) await this.connect();\r\n try {\r\n const result = await this.client!.callTool({\r\n name,\r\n arguments: args\r\n });\r\n return result;\r\n } catch (e: any) {\r\n return { isError: true, content: [{ type: 'text', text: `MCP Error: ${e.message}` }] };\r\n }\r\n }\r\n\r\n async close() {\r\n if (this.transport) {\r\n await this.transport.close();\r\n }\r\n }\r\n}\r\n\r\nconst mcpClient = new ChromeDevToolsClient();\r\n\r\nexport async function runQAAgent(options: QAAgentOptions) {\r\n if (!AGENT_ID) {\r\n tui.log.error('β STACKSPOT_QA_AGENT_ID not configured.');\r\n tui.log.info('Please run: set STACKSPOT_QA_AGENT_ID=<your-id>');\r\n return;\r\n }\r\n\r\n // Connect to MCP at start\r\n await mcpClient.connect();\r\n\r\n tui.intro('π¦ Shark QA Agent');\r\n tui.log.info('Connecting to Chrome DevTools...');\r\n\r\n const realm = await getActiveRealm();\r\n const token = await tokenStorage.getToken(realm);\r\n\r\n if (!token) {\r\n tui.log.error('Authentication required. Run \"shark login\".');\r\n return;\r\n }\r\n\r\n // 1. Prepare Initial Context\r\n let projectContext = \"\";\r\n try {\r\n const contextPath = path.join(process.cwd(), '_sharkrc', 'project-context.md');\r\n if (fs.existsSync(contextPath)) {\r\n projectContext = fs.readFileSync(contextPath, 'utf-8');\r\n tui.log.info(`π Context loaded from: _sharkrc/project-context.md`);\r\n }\r\n } catch (e) {\r\n // Ignore if no context\r\n }\r\n\r\n let userMessage = `CONTEXTO DO PROJETO:\\n${projectContext}\\n\\n`;\r\n\r\n if (options.initialUrl) {\r\n userMessage += `URL ALVO: ${options.initialUrl}\\n`;\r\n }\r\n if (options.scenario) {\r\n userMessage += `CENΓRIO DE TESTE: ${options.scenario}\\n`;\r\n } else {\r\n userMessage += `Por favor, aguarde instruΓ§Γ΅es do usuΓ‘rio.`;\r\n }\r\n\r\n // 2. Interaction Loop\r\n let keepRunning = true;\r\n\r\n while (keepRunning) {\r\n const spinner = tui.spinner();\r\n spinner.start('π€ Shark QA is thinking...');\r\n\r\n let agentResponseText = \"\";\r\n let agentResponse: AgentResponse | null = null;\r\n\r\n try {\r\n // API Interaction (Manual Call until AgentManager is unified)\r\n const existingConversationId = await conversationManager.getConversationId(AGENT_TYPE);\r\n\r\n await sseClient.streamAgentResponse(\r\n `https://genai-inference-app.stackspot.com/v1/agent/${AGENT_ID}/chat`,\r\n {\r\n user_prompt: userMessage,\r\n streaming: true,\r\n use_conversation: true,\r\n conversation_id: existingConversationId\r\n },\r\n {\r\n 'Authorization': `Bearer ${token}`\r\n },\r\n {\r\n onChunk: (chunk) => {\r\n agentResponseText += chunk;\r\n if (agentResponseText.length > 10 && agentResponseText.trim().startsWith('{')) {\r\n spinner.message('Receiving structured plan...');\r\n }\r\n },\r\n onComplete: (fullText, metadata) => {\r\n try {\r\n if (metadata?.conversation_id) {\r\n conversationManager.saveConversationId(AGENT_TYPE, metadata.conversation_id);\r\n }\r\n agentResponse = parseAgentResponse(fullText || agentResponseText);\r\n } catch (e) {\r\n tui.log.error(`Parse Error: ${(e as Error).message}`);\r\n agentResponse = { actions: [], summary: \"Error parsing response\", message: fullText };\r\n }\r\n }\r\n }\r\n );\r\n\r\n spinner.stop('Response Received');\r\n\r\n } catch (error) {\r\n spinner.stop('Communication Error', 1);\r\n tui.log.error((error as Error).message);\r\n keepRunning = false;\r\n break;\r\n }\r\n\r\n if (!agentResponse) continue;\r\n\r\n // 3. Handle Actions\r\n if (agentResponse.summary) {\r\n tui.log.info(colors.primary(`π Plan: ${agentResponse.summary}`));\r\n }\r\n\r\n if (agentResponse.actions.length === 0) {\r\n // No actions usually means it's waiting for user or finished\r\n const reply = await tui.text({\r\n message: \"π€ Shark QA:\",\r\n placeholder: \"Your reply...\"\r\n });\r\n\r\n if (tui.isCancel(reply)) {\r\n keepRunning = false;\r\n } else {\r\n userMessage = reply as string;\r\n }\r\n continue;\r\n }\r\n\r\n for (const action of agentResponse.actions) {\r\n tui.log.info(colors.dim(`Executing: ${action.type}`));\r\n\r\n let result = \"\";\r\n\r\n try {\r\n switch (action.type) {\r\n case 'talk_with_user':\r\n const reply = await tui.text({\r\n message: `π€ ${action.content}`,\r\n });\r\n if (tui.isCancel(reply)) keepRunning = false;\r\n else result = reply as string;\r\n break;\r\n\r\n case 'use_mcp_tool':\r\n if (action.tool_name) {\r\n tui.log.info(`π§ MCP Tool: ${colors.bold(action.tool_name)}`);\r\n let args = {};\r\n try {\r\n args = typeof action.tool_args === 'string'\r\n ? JSON.parse(action.tool_args)\r\n : (action.tool_args || {});\r\n } catch (e) {\r\n tui.log.warning('Failed to parse tool_args, using empty object');\r\n }\r\n const mcpResult = await mcpClient.callTool(action.tool_name, args);\r\n result = JSON.stringify(mcpResult);\r\n // Brief preview\r\n tui.log.success(`Result: ${result.substring(0, 100)}...`);\r\n }\r\n break;\r\n\r\n case 'create_file':\r\n if (action.path && action.content) {\r\n const fullPath = path.resolve(process.cwd(), action.path);\r\n fs.writeFileSync(fullPath, action.content);\r\n tui.log.success(`File created: ${action.path}`);\r\n result = \"File created successfully.\";\r\n }\r\n break;\r\n\r\n case 'read_file':\r\n result = handleReadFile(action.path || '');\r\n break;\r\n\r\n case 'run_command':\r\n // Safety check?\r\n const confirm = await tui.confirm({ message: `Run command: ${action.command}?` });\r\n if (confirm && action.command) {\r\n result = await handleRunCommand(action.command);\r\n } else {\r\n result = \"Command execution denied by user.\";\r\n }\r\n break;\r\n\r\n default:\r\n result = `Action ${action.type} not fully implemented in local client.`;\r\n }\r\n } catch (e: any) {\r\n result = `Error executing ${action.type}: ${e.message}`;\r\n tui.log.error(result);\r\n }\r\n\r\n // Feed result back to agent\r\n userMessage = `[Action ${action.type} Result]:\\n${result}\\n\\n`;\r\n }\r\n }\r\n\r\n await mcpClient.close();\r\n tui.outro('π¦ Shark QA Session Ended');\r\n}\r\n"],"mappings":"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","names":["Command","fs","path","path","fs","fs","path","z","z","fs","fs","path","path","fs","tui","AGENT_TYPE","AGENT_ID","fs","Command","fs","path","AGENT_TYPE","AGENT_ID","path","fs","Command","Command","fs","path","AGENT_TYPE","AGENT_ID","path","fs","Command","Command","fs","path","AGENT_TYPE","AGENT_ID","Command","Command"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shark-ai",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Shark AI: AI-Native Collaborative Development Tool powered by StackSpot AI and BMAD Method",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -82,4 +82,4 @@
|
|
|
82
82
|
"typescript": "^5.3.2",
|
|
83
83
|
"vitest": "^1.0.0"
|
|
84
84
|
}
|
|
85
|
-
}
|
|
85
|
+
}
|