Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/cli/commands/create/command.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<void> {
const cwd = options.outputDir ?? getWorkingDirectory();
const commandCwd = getWorkingDirectory();
const cwd = options.outputDir ?? commandCwd;
const name = options.name ?? options.projectName;
const projectName = options.projectName ?? name;

Expand Down Expand Up @@ -203,6 +204,7 @@ async function handleCreateHarnessCLI(options: CreateOptions): Promise<void> {
apiKeyArn: options.apiKeyArn,
containerUri: containerOption.containerUri,
dockerfilePath: containerOption.dockerfilePath,
dockerfileBaseDir: commandCwd,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: might be worth a brief comment here noting that dockerfileBaseDir intentionally uses CWD (not outputDir) since the Dockerfile is a source input.

skipMemory: options.harnessMemory === false,
maxIterations: options.maxIterations ? Number(options.maxIterations) : undefined,
maxTokens: options.maxTokens ? Number(options.maxTokens) : undefined,
Expand Down
2 changes: 2 additions & 0 deletions src/cli/commands/create/harness-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface CreateHarnessProjectOptions {
skipMemory?: boolean;
containerUri?: string;
dockerfilePath?: string;
dockerfileBaseDir?: string;
maxIterations?: number;
maxTokens?: number;
timeoutSeconds?: number;
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion src/cli/primitives/HarnessPrimitive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -85,9 +86,10 @@ export class HarnessPrimitive extends BasePrimitive<AddHarnessOptions, Removable
let dockerfile: string | undefined;
if (options.dockerfilePath) {
const projectRoot = dirname(configBaseDir);
const dockerfileBaseDir = options.dockerfileBaseDir ?? projectRoot;
const srcPath = isAbsolute(options.dockerfilePath)
? options.dockerfilePath
: resolve(projectRoot, options.dockerfilePath);
: resolve(dockerfileBaseDir, options.dockerfilePath);
try {
await access(srcPath);
} catch {
Expand Down
50 changes: 50 additions & 0 deletions src/cli/primitives/__tests__/HarnessPrimitive.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { ConfigIO } from '../../../lib';
import { createDefaultProjectSpec } from '../../project';
import { HarnessPrimitive } from '../HarnessPrimitive';
import { randomUUID } from 'node:crypto';
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { afterEach, describe, expect, it } from 'vitest';

describe('HarnessPrimitive', () => {
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');
});
});
1 change: 1 addition & 0 deletions src/cli/tui/screens/create/useCreateFlow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading