mirror of https://github.com/buster-so/buster.git
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:
parent
3b1354ddff
commit
f2a8388b86
|
@ -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);
|
||||||
|
|
|
@ -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
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue