diff --git a/src/cli/commands/create/command.tsx b/src/cli/commands/create/command.tsx index b5a934b50..db8191a5c 100644 --- a/src/cli/commands/create/command.tsx +++ b/src/cli/commands/create/command.tsx @@ -136,7 +136,8 @@ function printCreateHarnessSummary(projectName: string, harnessName: string): vo /** Handle CLI mode for the harness path (preview mode) */ async function handleCreateHarnessCLI(options: CreateOptions): Promise { - const cwd = options.outputDir ?? getWorkingDirectory(); + const commandCwd = getWorkingDirectory(); + const cwd = options.outputDir ?? commandCwd; const name = options.name ?? options.projectName; const projectName = options.projectName ?? name; @@ -203,6 +204,7 @@ async function handleCreateHarnessCLI(options: CreateOptions): Promise { apiKeyArn: options.apiKeyArn, containerUri: containerOption.containerUri, dockerfilePath: containerOption.dockerfilePath, + dockerfileBaseDir: commandCwd, skipMemory: options.harnessMemory === false, maxIterations: options.maxIterations ? Number(options.maxIterations) : undefined, maxTokens: options.maxTokens ? Number(options.maxTokens) : undefined, diff --git a/src/cli/commands/create/harness-action.ts b/src/cli/commands/create/harness-action.ts index 86bdd1161..020203b85 100644 --- a/src/cli/commands/create/harness-action.ts +++ b/src/cli/commands/create/harness-action.ts @@ -16,6 +16,7 @@ export interface CreateHarnessProjectOptions { skipMemory?: boolean; containerUri?: string; dockerfilePath?: string; + dockerfileBaseDir?: string; maxIterations?: number; maxTokens?: number; timeoutSeconds?: number; @@ -62,6 +63,7 @@ export async function createProjectWithHarness(options: CreateHarnessProjectOpti apiKeyArn: options.apiKeyArn, containerUri: options.containerUri, dockerfilePath: options.dockerfilePath, + dockerfileBaseDir: options.dockerfileBaseDir ?? options.cwd, skipMemory: options.skipMemory, maxIterations: options.maxIterations, maxTokens: options.maxTokens, diff --git a/src/cli/primitives/HarnessPrimitive.ts b/src/cli/primitives/HarnessPrimitive.ts index 5164d148e..b3a25080c 100644 --- a/src/cli/primitives/HarnessPrimitive.ts +++ b/src/cli/primitives/HarnessPrimitive.ts @@ -45,6 +45,7 @@ export interface AddHarnessOptions { efsAccessPoints?: { accessPointArn: string; mountPath: string }[]; s3AccessPoints?: { accessPointArn: string; mountPath: string }[]; withInvokeScript?: boolean; + dockerfileBaseDir?: string; selectedTools?: string[]; mcpName?: string; mcpUrl?: string; @@ -85,9 +86,10 @@ export class HarnessPrimitive extends BasePrimitive { + const tempDirs: string[] = []; + + afterEach(async () => { + await Promise.all(tempDirs.map(dir => rm(dir, { recursive: true, force: true }))); + tempDirs.length = 0; + }); + + it('resolves create-flow Dockerfile paths from the command working directory', async () => { + const commandCwd = join(tmpdir(), `harness-dockerfile-${randomUUID()}`); + tempDirs.push(commandCwd); + const projectRoot = join(commandCwd, 'HarnessProject'); + const configBaseDir = join(projectRoot, 'agentcore'); + await mkdir(projectRoot, { recursive: true }); + + const configIO = new ConfigIO({ baseDir: configBaseDir }); + await configIO.initializeBaseDir(); + await configIO.writeAWSDeploymentTargets([]); + await configIO.writeDeployedState({ targets: {} }); + await configIO.writeProjectSpec(createDefaultProjectSpec('HarnessProject')); + + await writeFile(join(commandCwd, 'Dockerfile.custom'), 'FROM public.ecr.aws/docker/library/python:3.12\n'); + + const result = await new HarnessPrimitive().add({ + name: 'MyHarness', + modelProvider: 'bedrock', + modelId: 'global.anthropic.claude-sonnet-4-6', + skipMemory: true, + dockerfilePath: './Dockerfile.custom', + dockerfileBaseDir: commandCwd, + configBaseDir, + }); + + expect(result.success).toBe(true); + const harnessDir = join(projectRoot, 'app', 'MyHarness'); + await expect(readFile(join(harnessDir, 'Dockerfile.custom'), 'utf-8')).resolves.toContain('python:3.12'); + + const harnessSpec = JSON.parse(await readFile(join(harnessDir, 'harness.json'), 'utf-8')); + expect(harnessSpec.dockerfile).toBe('Dockerfile.custom'); + }); +}); diff --git a/src/cli/tui/screens/create/useCreateFlow.ts b/src/cli/tui/screens/create/useCreateFlow.ts index 0beb8aa14..398a96a2d 100644 --- a/src/cli/tui/screens/create/useCreateFlow.ts +++ b/src/cli/tui/screens/create/useCreateFlow.ts @@ -654,6 +654,7 @@ export function useCreateFlow(cwd: string): CreateFlowState { skipMemory: addHarnessConfig.skipMemory, containerUri: addHarnessConfig.containerUri, dockerfilePath: addHarnessConfig.dockerfilePath, + dockerfileBaseDir: cwd, maxIterations: addHarnessConfig.maxIterations, maxTokens: addHarnessConfig.maxTokens, timeoutSeconds: addHarnessConfig.timeoutSeconds,