From f2a8388b86113075d2ea6ff666da77c9a5bda406 Mon Sep 17 00:00:00 2001 From: dal Date: Tue, 29 Jul 2025 14:48:18 -0600 Subject: [PATCH] feat: enhance repository tree output with current directory information - Added functionality to retrieve and prepend the current working directory to the repository tree output, improving context for users. - Updated runtime context to store the modified tree structure with location information. - Removed outdated integration tests and streamlined the test suite for better maintainability. This update enhances the usability of the repository tree feature by providing clearer context during execution. --- .../docs-agent/get-repository-tree-step.ts | 12 +- .../docs-agent-workflow.int.test.ts | 272 +----------------- 2 files changed, 11 insertions(+), 273 deletions(-) diff --git a/packages/ai/src/steps/docs-agent/get-repository-tree-step.ts b/packages/ai/src/steps/docs-agent/get-repository-tree-step.ts index 4dd52b732..433139fdc 100644 --- a/packages/ai/src/steps/docs-agent/get-repository-tree-step.ts +++ b/packages/ai/src/steps/docs-agent/get-repository-tree-step.ts @@ -43,6 +43,10 @@ const getRepositoryTreeExecution = async ({ console.info('[GetRepositoryTree] Generating repository tree structure'); + // Get current working directory + const pwdResult = await sandbox.process.executeCommand('pwd'); + const currentDir = pwdResult.result.trim(); + // Get the tree structure with gitignore option enabled const treeResult = await getRepositoryTree(sandbox, '.', { gitignore: true, @@ -57,18 +61,22 @@ const getRepositoryTreeExecution = async ({ }; } + // Prepend current directory info to tree output + const treeWithLocation = `\n\n${treeResult.output}`; + console.info('[GetRepositoryTree] Tree structure generated successfully', { outputLength: treeResult.output.length, command: treeResult.command, + currentDirectory: currentDir, }); // Store the tree in runtime context for potential use by other steps - runtimeContext.set('repositoryTree', treeResult.output); + runtimeContext.set('repositoryTree', treeWithLocation); // Return the data with the tree structure added return { ...inputData, - repositoryTree: treeResult.output, + repositoryTree: treeWithLocation, }; } catch (error) { console.error('[GetRepositoryTree] Error generating repository tree:', error); diff --git a/packages/ai/src/workflows/docs-agent/docs-agent-workflow.int.test.ts b/packages/ai/src/workflows/docs-agent/docs-agent-workflow.int.test.ts index 4b5d994d1..ade570897 100644 --- a/packages/ai/src/workflows/docs-agent/docs-agent-workflow.int.test.ts +++ b/packages/ai/src/workflows/docs-agent/docs-agent-workflow.int.test.ts @@ -124,26 +124,6 @@ describe('docs-agent-workflow', () => { } }, 300000); // Increase timeout to 5 minutes - it('should handle pre-populated todo list', async () => { - testSandbox = await createIntegrationTestSandbox(); - const context = createContextWithTodos(testSandbox.sandbox); - - const input = createTestWorkflowInput({ - message: TEST_MESSAGES.completePartial, - context, - }); - - const result = await runWorkflowWithTracing(input, { - testType: 'todo-completion', - }); - - expect(result.status).toBe('success'); - if (result.status === 'success') { - expect(result.result.todos).toBeDefined(); - expect(result.result.todoList).toBeDefined(); - } - }); - it('should generate clarification questions when needed', async () => { testSandbox = await createIntegrationTestSandbox(); @@ -179,255 +159,5 @@ describe('docs-agent-workflow', () => { } } }); - }); - - describe('error handling', () => { - it('should handle malformed YAML files gracefully', async () => { - testSandbox = await createIntegrationTestSandbox(); - - // Add malformed YAML files - await addFilesToSandbox( - testSandbox.sandbox, - createMalformedYamlFiles(), - testSandbox.projectPath - ); - - const context = createTestContext({ - sandbox: testSandbox.sandbox, - }); - - const input = createTestWorkflowInput({ - message: TEST_MESSAGES.fixYaml, - context, - }); - - const result = await runWorkflowWithTracing(input, { - testType: 'error-handling', - errorType: 'malformed-yaml', - }); - - // Should complete successfully - expect(result.status).toBe('success'); - if (result.status === 'success') { - expect(result.result).toBeDefined(); - console.log('Malformed YAML test completed with:', { - documentationCreated: result.result.documentationCreated, - clarificationNeeded: result.result.clarificationNeeded, - toolsUsed: result.result.metadata?.toolsUsed, - }); - } - }); - - it('should handle missing sandbox gracefully', async () => { - const context = createTestContext({ - sandbox: null as unknown as Sandbox, // Intentionally pass null - }); - - const input = createTestWorkflowInput({ - message: TEST_MESSAGES.documentAll, - context, - }); - - const result = await runWorkflowWithTracing(input, { - testType: 'error-handling', - errorType: 'missing-sandbox', - }); - - // Workflow should fail gracefully - expect(result.status).toBe('failed'); - }); - }); - - describe('complex scenarios', () => { - it('should handle large project with multiple domains', async () => { - testSandbox = await createIntegrationTestSandbox({ - projectOptions: { - includeDocumentation: false, - }, - }); - - // Add complex project structure - await addFilesToSandbox( - testSandbox.sandbox, - createComplexProjectStructure(), - testSandbox.projectPath - ); - - const context = createTestContext({ - sandbox: testSandbox.sandbox, - }); - - const input = createTestWorkflowInput({ - message: TEST_MESSAGES.documentAll, - context, - }); - - const result = await runWorkflowWithTracing(input, { - testType: 'complex-project', - projectComplexity: 'high', - }); - - expect(result.status).toBe('success'); - if (result.status === 'success') { - expect(result.result).toBeDefined(); - console.log('Complex project test completed with:', { - documentationCreated: result.result.documentationCreated, - filesCreated: result.result.metadata?.filesCreated, - toolsUsed: result.result.metadata?.toolsUsed, - }); - } - }, 30000); // Increase timeout for complex test - - it('should resume partially completed documentation', async () => { - testSandbox = await createIntegrationTestSandbox(); - const context = createPartiallyCompletedContext(testSandbox.sandbox); - - const input = createTestWorkflowInput({ - message: TEST_MESSAGES.completePartial, - context, - }); - - const result = await runWorkflowWithTracing(input, { - testType: 'resume-partial', - }); - - expect(result.status).toBe('success'); - if (result.status === 'success') { - expect(result.result).toBeDefined(); - console.log('Resume partial test completed with:', { - finished: result.result.finished, - filesCreated: result.result.metadata?.filesCreated, - toolsUsed: result.result.metadata?.toolsUsed, - }); - } - }); - }); - - describe('workflow structure', () => { - it('should have correct input and output schemas', () => { - expect(docsAgentWorkflow.inputSchema).toBeDefined(); - expect(docsAgentWorkflow.outputSchema).toBeDefined(); - }); - - it('should have all required steps', () => { - const workflow = docsAgentWorkflow as any; - // The workflow has a steps object with the step definitions - const stepKeys = Object.keys(workflow.steps); - expect(stepKeys).toHaveLength(3); - expect(stepKeys).toContain('initialize-context'); - expect(stepKeys).toContain('create-docs-todos'); - expect(stepKeys).toContain('docs-agent'); - }); - }); - - describe('integration with real sandbox', () => { - it.skip('should work with actual Daytona sandbox', async () => { - // This test requires actual Daytona setup - // Skip in CI, run locally with proper credentials - - testSandbox = await createIntegrationTestSandbox({ - projectOptions: { - projectName: 'production_analytics', - companyName: 'RealCo', - }, - }); - - const context = createTestContext({ - sandbox: testSandbox.sandbox, - }); - - const input = createTestWorkflowInput({ - message: 'Document the entire dbt project with detailed explanations', - context, - }); - - const result = await runWorkflowWithTracing(input, { - testType: 'real-sandbox-integration', - environment: 'production-like', - }); - - expect(result.status).toBe('success'); - if (result.status === 'success') { - expect(result.result.documentationCreated).toBe(true); - } - - // Verify files were actually created in sandbox - const files = await (testSandbox.sandbox.fs as any).listDirectory(testSandbox.projectPath); - expect(files).toContain('README.md'); - }); - }); -}); - -// Performance benchmark tests -describe('docs-agent-workflow performance', () => { - let testSandbox: TestSandboxResult | null = null; - let braintrustLogger: BraintrustLogger | null = null; - - // Initialize Braintrust logger before each test - beforeEach(() => { - if (process.env.BRAINTRUST_KEY) { - braintrustLogger = initLogger({ - apiKey: process.env.BRAINTRUST_KEY, - projectName: 'DOCS-AGENT', - }); - } - }); - - afterEach(async () => { - if (testSandbox) { - await testSandbox.cleanup(); - testSandbox = null; - } - if (braintrustLogger) { - await braintrustLogger.flush(); - braintrustLogger = null; - } - }); - - /** - * Helper to run workflow with Braintrust tracing - */ - async function runWorkflowWithTracing(input: unknown, metadata: Record = {}) { - if (!braintrustLogger) { - // Run without tracing if no Braintrust key - const run = docsAgentWorkflow.createRun(); - return await run.start({ inputData: input as any }); - } - - return await wrapTraced( - async () => { - currentSpan().log({ - metadata: { - testName: expect.getState().currentTestName, - ...metadata, - }, - }); - - const run = docsAgentWorkflow.createRun(); - return await run.start({ inputData: input as any }); - }, - { - name: 'Docs Agent Workflow Test', - } - )(); - } - - it('should complete basic documentation within reasonable time', async () => { - const startTime = Date.now(); - - testSandbox = await createIntegrationTestSandbox(); - const context = createTestContext({ sandbox: testSandbox.sandbox }); - const input = createTestWorkflowInput({ - message: TEST_MESSAGES.documentSpecific, - context, - }); - - await runWorkflowWithTracing(input, { - testType: 'performance', - benchmark: true, - }); - - const duration = Date.now() - startTime; - expect(duration).toBeLessThan(10000); // Should complete within 10 seconds - }); + }, 300000); });