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.
This commit is contained in:
dal 2025-07-29 14:48:18 -06:00
parent 3b1354ddff
commit f2a8388b86
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
2 changed files with 11 additions and 273 deletions

View File

@ -43,6 +43,10 @@ const getRepositoryTreeExecution = async ({
console.info('[GetRepositoryTree] Generating repository tree structure'); 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 // Get the tree structure with gitignore option enabled
const treeResult = await getRepositoryTree(sandbox, '.', { const treeResult = await getRepositoryTree(sandbox, '.', {
gitignore: true, gitignore: true,
@ -57,18 +61,22 @@ const getRepositoryTreeExecution = async ({
}; };
} }
// Prepend current directory info to tree output
const treeWithLocation = `<YOU ARE HERE: ${currentDir}>\n\n${treeResult.output}`;
console.info('[GetRepositoryTree] Tree structure generated successfully', { console.info('[GetRepositoryTree] Tree structure generated successfully', {
outputLength: treeResult.output.length, outputLength: treeResult.output.length,
command: treeResult.command, command: treeResult.command,
currentDirectory: currentDir,
}); });
// Store the tree in runtime context for potential use by other steps // 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 the data with the tree structure added
return { return {
...inputData, ...inputData,
repositoryTree: treeResult.output, repositoryTree: treeWithLocation,
}; };
} catch (error) { } catch (error) {
console.error('[GetRepositoryTree] Error generating repository tree:', error); console.error('[GetRepositoryTree] Error generating repository tree:', error);

View File

@ -124,26 +124,6 @@ describe('docs-agent-workflow', () => {
} }
}, 300000); // Increase timeout to 5 minutes }, 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 () => { it('should generate clarification questions when needed', async () => {
testSandbox = await createIntegrationTestSandbox(); testSandbox = await createIntegrationTestSandbox();
@ -179,255 +159,5 @@ describe('docs-agent-workflow', () => {
} }
} }
}); });
}); }, 300000);
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<true> | 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<string, unknown> = {}) {
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
});
}); });