diff --git a/README.md b/README.md index 155abc14b..6b7f37f70 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ cd MyAssistant && agentcore project deploy agentcore harness invoke --id --prompt "hello" # Scaffold runtime code instead (pass a template or framework flags). -agentcore project create --name MyAgent --template strands-python +agentcore project create --name MyAgent --template agent-python-strands # Translate an existing Amazon Bedrock Agent version into editable runtime code. # The selected alias identifies the immutable source version; generated code diff --git a/src/assets/templates/python-mcp/Dockerfile.template b/src/assets/templates/a2a-python-strands/Dockerfile.template similarity index 100% rename from src/assets/templates/python-mcp/Dockerfile.template rename to src/assets/templates/a2a-python-strands/Dockerfile.template diff --git a/src/assets/templates/strands-py-a2a/README.md b/src/assets/templates/a2a-python-strands/README.md similarity index 100% rename from src/assets/templates/strands-py-a2a/README.md rename to src/assets/templates/a2a-python-strands/README.md diff --git a/src/assets/templates/hello-world-python-container/dockerignore.template b/src/assets/templates/a2a-python-strands/dockerignore.template similarity index 100% rename from src/assets/templates/hello-world-python-container/dockerignore.template rename to src/assets/templates/a2a-python-strands/dockerignore.template diff --git a/src/assets/templates/python-mcp/gitignore.template b/src/assets/templates/a2a-python-strands/gitignore.template similarity index 100% rename from src/assets/templates/python-mcp/gitignore.template rename to src/assets/templates/a2a-python-strands/gitignore.template diff --git a/src/assets/templates/strands-py-a2a/main.py b/src/assets/templates/a2a-python-strands/main.py similarity index 100% rename from src/assets/templates/strands-py-a2a/main.py rename to src/assets/templates/a2a-python-strands/main.py diff --git a/src/assets/templates/strands-http-python/memory/__init__.py b/src/assets/templates/a2a-python-strands/memory/__init__.py similarity index 100% rename from src/assets/templates/strands-http-python/memory/__init__.py rename to src/assets/templates/a2a-python-strands/memory/__init__.py diff --git a/src/assets/templates/strands-http-python/memory/session.py b/src/assets/templates/a2a-python-strands/memory/session.py similarity index 100% rename from src/assets/templates/strands-http-python/memory/session.py rename to src/assets/templates/a2a-python-strands/memory/session.py diff --git a/src/assets/templates/strands-http-python/mcp_client/__init__.py b/src/assets/templates/a2a-python-strands/model/__init__.py similarity index 100% rename from src/assets/templates/strands-http-python/mcp_client/__init__.py rename to src/assets/templates/a2a-python-strands/model/__init__.py diff --git a/src/assets/templates/strands-py-a2a/model/load.py b/src/assets/templates/a2a-python-strands/model/load.py similarity index 100% rename from src/assets/templates/strands-py-a2a/model/load.py rename to src/assets/templates/a2a-python-strands/model/load.py diff --git a/src/assets/templates/strands-py-a2a/pyproject.toml b/src/assets/templates/a2a-python-strands/pyproject.toml similarity index 100% rename from src/assets/templates/strands-py-a2a/pyproject.toml rename to src/assets/templates/a2a-python-strands/pyproject.toml diff --git a/src/assets/templates/strands-http-python/Dockerfile.template b/src/assets/templates/agent-python-strands/Dockerfile.template similarity index 100% rename from src/assets/templates/strands-http-python/Dockerfile.template rename to src/assets/templates/agent-python-strands/Dockerfile.template diff --git a/src/assets/templates/strands-http-python/README.md b/src/assets/templates/agent-python-strands/README.md similarity index 100% rename from src/assets/templates/strands-http-python/README.md rename to src/assets/templates/agent-python-strands/README.md diff --git a/src/assets/templates/python-mcp/dockerignore.template b/src/assets/templates/agent-python-strands/dockerignore.template similarity index 100% rename from src/assets/templates/python-mcp/dockerignore.template rename to src/assets/templates/agent-python-strands/dockerignore.template diff --git a/src/assets/templates/strands-http-python/gitignore.template b/src/assets/templates/agent-python-strands/gitignore.template similarity index 100% rename from src/assets/templates/strands-http-python/gitignore.template rename to src/assets/templates/agent-python-strands/gitignore.template diff --git a/src/assets/templates/strands-http-python/main.py b/src/assets/templates/agent-python-strands/main.py similarity index 100% rename from src/assets/templates/strands-http-python/main.py rename to src/assets/templates/agent-python-strands/main.py diff --git a/src/assets/templates/strands-http-python/model/__init__.py b/src/assets/templates/agent-python-strands/mcp_client/__init__.py similarity index 100% rename from src/assets/templates/strands-http-python/model/__init__.py rename to src/assets/templates/agent-python-strands/mcp_client/__init__.py diff --git a/src/assets/templates/strands-http-python/mcp_client/client.py b/src/assets/templates/agent-python-strands/mcp_client/client.py similarity index 100% rename from src/assets/templates/strands-http-python/mcp_client/client.py rename to src/assets/templates/agent-python-strands/mcp_client/client.py diff --git a/src/assets/templates/strands-py-a2a/memory/__init__.py b/src/assets/templates/agent-python-strands/memory/__init__.py similarity index 100% rename from src/assets/templates/strands-py-a2a/memory/__init__.py rename to src/assets/templates/agent-python-strands/memory/__init__.py diff --git a/src/assets/templates/strands-py-a2a/memory/session.py b/src/assets/templates/agent-python-strands/memory/session.py similarity index 100% rename from src/assets/templates/strands-py-a2a/memory/session.py rename to src/assets/templates/agent-python-strands/memory/session.py diff --git a/src/assets/templates/strands-py-a2a/model/__init__.py b/src/assets/templates/agent-python-strands/model/__init__.py similarity index 100% rename from src/assets/templates/strands-py-a2a/model/__init__.py rename to src/assets/templates/agent-python-strands/model/__init__.py diff --git a/src/assets/templates/strands-http-python/model/load.py b/src/assets/templates/agent-python-strands/model/load.py similarity index 100% rename from src/assets/templates/strands-http-python/model/load.py rename to src/assets/templates/agent-python-strands/model/load.py diff --git a/src/assets/templates/strands-http-python/model/mantle_compat.py b/src/assets/templates/agent-python-strands/model/mantle_compat.py similarity index 100% rename from src/assets/templates/strands-http-python/model/mantle_compat.py rename to src/assets/templates/agent-python-strands/model/mantle_compat.py diff --git a/src/assets/templates/strands-http-python/pyproject.toml b/src/assets/templates/agent-python-strands/pyproject.toml similarity index 100% rename from src/assets/templates/strands-http-python/pyproject.toml rename to src/assets/templates/agent-python-strands/pyproject.toml diff --git a/src/assets/templates/strands-http-python/skills/fetcher.py b/src/assets/templates/agent-python-strands/skills/fetcher.py similarity index 100% rename from src/assets/templates/strands-http-python/skills/fetcher.py rename to src/assets/templates/agent-python-strands/skills/fetcher.py diff --git a/src/assets/templates/hello-world-python-container/Dockerfile.template b/src/assets/templates/agent-python/Dockerfile.template similarity index 100% rename from src/assets/templates/hello-world-python-container/Dockerfile.template rename to src/assets/templates/agent-python/Dockerfile.template diff --git a/src/assets/templates/agent-python/README.md b/src/assets/templates/agent-python/README.md new file mode 100644 index 000000000..ed945bd99 --- /dev/null +++ b/src/assets/templates/agent-python/README.md @@ -0,0 +1,31 @@ +# agent-python + +A minimal AgentCore Runtime HTTP agent with no agent framework. Its +`@app.entrypoint` returns a fixed `Hello, world!` message for every +invocation — a starting point you own and grow into a real agent. + +## What's here + +- `main.py` — the agent. A `BedrockAgentCoreApp` wraps the entrypoint that + receives each invocation payload and returns the response. +- `pyproject.toml` — Python dependencies, managed with + [uv](https://docs.astral.sh/uv/). `agentcore project create` has already run + `uv sync` for you (unless you passed `--skip-install`), so `.venv/` is ready. + +## Develop + +Run the agent locally from the project root: + +```bash +agentcore project dev +``` + +Environment variables for local development go in `agentcore/.env.local` +(gitignored). + +## Deploy + +```bash +agentcore project deploy +agentcore project invoke runtime --payload '{"prompt":"Hello!"}' +``` diff --git a/src/assets/templates/strands-http-python/dockerignore.template b/src/assets/templates/agent-python/dockerignore.template similarity index 100% rename from src/assets/templates/strands-http-python/dockerignore.template rename to src/assets/templates/agent-python/dockerignore.template diff --git a/src/assets/templates/agent-python/main.py b/src/assets/templates/agent-python/main.py new file mode 100644 index 000000000..4bf4e2213 --- /dev/null +++ b/src/assets/templates/agent-python/main.py @@ -0,0 +1,13 @@ +from bedrock_agentcore.runtime import BedrockAgentCoreApp + +app = BedrockAgentCoreApp() + + +@app.entrypoint +def invoke(payload, context): + """Add agent logic here""" + return {"message": "Hello, world!"} + + +if __name__ == "__main__": + app.run() diff --git a/src/assets/templates/hello-world-python/pyproject.toml b/src/assets/templates/agent-python/pyproject.toml similarity index 73% rename from src/assets/templates/hello-world-python/pyproject.toml rename to src/assets/templates/agent-python/pyproject.toml index c352cc800..684d8f604 100644 --- a/src/assets/templates/hello-world-python/pyproject.toml +++ b/src/assets/templates/agent-python/pyproject.toml @@ -3,16 +3,15 @@ requires = ["hatchling"] build-backend = "hatchling.build" [project] -name = "hello-world" +name = "agent-python" version = "0.1.0" -description = "AgentCore Runtime application using the Strands SDK" +description = "Minimal AgentCore Runtime HTTP agent" readme = "README.md" requires-python = ">=3.10" dependencies = [ "aws-opentelemetry-distro ~= 0.18.0", "bedrock-agentcore ~= 1.9.1", "botocore[crt] ~= 1.43.0", - "strands-agents ~= 1.15.0", ] [tool.hatch.build.targets.wheel] diff --git a/src/assets/templates/strands-http-typescript/Dockerfile.template b/src/assets/templates/agent-typescript-strands/Dockerfile.template similarity index 100% rename from src/assets/templates/strands-http-typescript/Dockerfile.template rename to src/assets/templates/agent-typescript-strands/Dockerfile.template diff --git a/src/assets/templates/strands-http-typescript/README.md b/src/assets/templates/agent-typescript-strands/README.md similarity index 100% rename from src/assets/templates/strands-http-typescript/README.md rename to src/assets/templates/agent-typescript-strands/README.md diff --git a/src/assets/templates/strands-http-typescript/dockerignore.template b/src/assets/templates/agent-typescript-strands/dockerignore.template similarity index 100% rename from src/assets/templates/strands-http-typescript/dockerignore.template rename to src/assets/templates/agent-typescript-strands/dockerignore.template diff --git a/src/assets/templates/strands-http-typescript/gitignore.template b/src/assets/templates/agent-typescript-strands/gitignore.template similarity index 100% rename from src/assets/templates/strands-http-typescript/gitignore.template rename to src/assets/templates/agent-typescript-strands/gitignore.template diff --git a/src/assets/templates/strands-http-typescript/main.ts b/src/assets/templates/agent-typescript-strands/main.ts similarity index 100% rename from src/assets/templates/strands-http-typescript/main.ts rename to src/assets/templates/agent-typescript-strands/main.ts diff --git a/src/assets/templates/strands-http-typescript/mcp_client/client.ts b/src/assets/templates/agent-typescript-strands/mcp_client/client.ts similarity index 100% rename from src/assets/templates/strands-http-typescript/mcp_client/client.ts rename to src/assets/templates/agent-typescript-strands/mcp_client/client.ts diff --git a/src/assets/templates/strands-http-typescript/memory/memory.ts b/src/assets/templates/agent-typescript-strands/memory/memory.ts similarity index 100% rename from src/assets/templates/strands-http-typescript/memory/memory.ts rename to src/assets/templates/agent-typescript-strands/memory/memory.ts diff --git a/src/assets/templates/strands-http-typescript/model/load.ts b/src/assets/templates/agent-typescript-strands/model/load.ts similarity index 100% rename from src/assets/templates/strands-http-typescript/model/load.ts rename to src/assets/templates/agent-typescript-strands/model/load.ts diff --git a/src/assets/templates/strands-http-typescript/package.json b/src/assets/templates/agent-typescript-strands/package.json similarity index 100% rename from src/assets/templates/strands-http-typescript/package.json rename to src/assets/templates/agent-typescript-strands/package.json diff --git a/src/assets/templates/strands-http-typescript/tsconfig.json b/src/assets/templates/agent-typescript-strands/tsconfig.json similarity index 100% rename from src/assets/templates/strands-http-typescript/tsconfig.json rename to src/assets/templates/agent-typescript-strands/tsconfig.json diff --git a/src/assets/templates/hello-world-python-container/README.md b/src/assets/templates/hello-world-python-container/README.md deleted file mode 100644 index 190d41163..000000000 --- a/src/assets/templates/hello-world-python-container/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# hello-world - -An AgentCore Runtime agent built with the [Strands](https://strandsagents.com) -SDK. Scaffolded by `agentcore project create`. - -## Layout - -- `main.py` — the agent: a `BedrockAgentCoreApp` entrypoint that streams - responses from a Strands `Agent`. -- `pyproject.toml` — dependencies, installed with [uv](https://docs.astral.sh/uv/). - -## Develop - -Run the agent locally from the project root: - -```bash -agentcore project dev -``` - -Environment variables for local development go in `agentcore/.env.local` -(gitignored). - -## Deploy - -```bash -agentcore project deploy -``` - -Invoke the deployed Runtime with its native payload: - -```bash -agentcore project invoke runtime --payload '{"prompt":"Hello!"}' -``` diff --git a/src/assets/templates/hello-world-python-container/main.py b/src/assets/templates/hello-world-python-container/main.py deleted file mode 100644 index 182bfd57e..000000000 --- a/src/assets/templates/hello-world-python-container/main.py +++ /dev/null @@ -1,17 +0,0 @@ -from bedrock_agentcore.runtime import BedrockAgentCoreApp -from strands import Agent - -app = BedrockAgentCoreApp() -agent = Agent(system_prompt="You are a helpful assistant.") - - -@app.entrypoint -async def invoke(payload, context): - """Stream the agent's response to the caller's prompt.""" - prompt = payload.get("prompt", "Hello!") - async for event in agent.stream_async(prompt): - yield event - - -if __name__ == "__main__": - app.run() diff --git a/src/assets/templates/hello-world-python-container/pyproject.toml b/src/assets/templates/hello-world-python-container/pyproject.toml deleted file mode 100644 index c352cc800..000000000 --- a/src/assets/templates/hello-world-python-container/pyproject.toml +++ /dev/null @@ -1,19 +0,0 @@ -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[project] -name = "hello-world" -version = "0.1.0" -description = "AgentCore Runtime application using the Strands SDK" -readme = "README.md" -requires-python = ">=3.10" -dependencies = [ - "aws-opentelemetry-distro ~= 0.18.0", - "bedrock-agentcore ~= 1.9.1", - "botocore[crt] ~= 1.43.0", - "strands-agents ~= 1.15.0", -] - -[tool.hatch.build.targets.wheel] -packages = ["."] diff --git a/src/assets/templates/hello-world-python/README.md b/src/assets/templates/hello-world-python/README.md deleted file mode 100644 index d2cadd33d..000000000 --- a/src/assets/templates/hello-world-python/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# hello-world - -A minimal AgentCore Runtime agent built with the -[Strands Agents SDK](https://strandsagents.com) — our recommended framework -for building agents on AWS Bedrock AgentCore. - -## What's here - -- `main.py` — the agent. A `BedrockAgentCoreApp` wraps a Strands `Agent`; - the `@app.entrypoint` function receives each invocation payload and streams - the agent's response back to the caller. -- `pyproject.toml` — Python dependencies, managed with - [uv](https://docs.astral.sh/uv/). `agentcore project create` has already run - `uv sync` for you (unless you passed `--skip-install`), so `.venv/` is ready. - -## Run it locally - -```bash -uv run main.py -``` - -The app listens on http://localhost:8080. Invoke it: - -```bash -curl -X POST http://localhost:8080/invocations \ - -H "Content-Type: application/json" \ - -d '{"prompt": "Hello!"}' -``` - -## Build your agent - -Start in `main.py`: - -- Change the `system_prompt` to shape your agent's behavior. -- Give it tools — Strands ships ready-made ones and makes custom tools a - decorator away: - - ```python - from strands import Agent, tool - - @tool - def word_count(text: str) -> int: - """Count words in text.""" - return len(text.split()) - - agent = Agent(system_prompt="You are a helpful assistant.", tools=[word_count]) - ``` - -- Add dependencies with `uv add `. - -See the [Strands documentation](https://strandsagents.com/latest/documentation/docs/) -for multi-agent patterns, MCP tools, and model configuration. - -## Deploy - -Deploy from the project root with the AgentCore CLI; the CDK app under -`agentcore/cdk` provisions the Runtime that hosts this agent. - -```bash -agentcore project deploy -agentcore project invoke runtime --payload '{"prompt":"Hello!"}' -``` diff --git a/src/assets/templates/hello-world-python/main.py b/src/assets/templates/hello-world-python/main.py deleted file mode 100644 index 182bfd57e..000000000 --- a/src/assets/templates/hello-world-python/main.py +++ /dev/null @@ -1,17 +0,0 @@ -from bedrock_agentcore.runtime import BedrockAgentCoreApp -from strands import Agent - -app = BedrockAgentCoreApp() -agent = Agent(system_prompt="You are a helpful assistant.") - - -@app.entrypoint -async def invoke(payload, context): - """Stream the agent's response to the caller's prompt.""" - prompt = payload.get("prompt", "Hello!") - async for event in agent.stream_async(prompt): - yield event - - -if __name__ == "__main__": - app.run() diff --git a/src/assets/templates/strands-py-a2a/Dockerfile.template b/src/assets/templates/mcp-python-fastmcp/Dockerfile.template similarity index 100% rename from src/assets/templates/strands-py-a2a/Dockerfile.template rename to src/assets/templates/mcp-python-fastmcp/Dockerfile.template diff --git a/src/assets/templates/python-mcp/README.md b/src/assets/templates/mcp-python-fastmcp/README.md similarity index 100% rename from src/assets/templates/python-mcp/README.md rename to src/assets/templates/mcp-python-fastmcp/README.md diff --git a/src/assets/templates/strands-py-a2a/dockerignore.template b/src/assets/templates/mcp-python-fastmcp/dockerignore.template similarity index 100% rename from src/assets/templates/strands-py-a2a/dockerignore.template rename to src/assets/templates/mcp-python-fastmcp/dockerignore.template diff --git a/src/assets/templates/strands-py-a2a/gitignore.template b/src/assets/templates/mcp-python-fastmcp/gitignore.template similarity index 100% rename from src/assets/templates/strands-py-a2a/gitignore.template rename to src/assets/templates/mcp-python-fastmcp/gitignore.template diff --git a/src/assets/templates/python-mcp/main.py b/src/assets/templates/mcp-python-fastmcp/main.py similarity index 100% rename from src/assets/templates/python-mcp/main.py rename to src/assets/templates/mcp-python-fastmcp/main.py diff --git a/src/assets/templates/python-mcp/pyproject.toml b/src/assets/templates/mcp-python-fastmcp/pyproject.toml similarity index 100% rename from src/assets/templates/python-mcp/pyproject.toml rename to src/assets/templates/mcp-python-fastmcp/pyproject.toml diff --git a/src/core/project/__snapshots__/manager.test.ts.snap b/src/core/project/__snapshots__/manager.test.ts.snap index a75e5b8d7..93418d3d4 100644 --- a/src/core/project/__snapshots__/manager.test.ts.snap +++ b/src/core/project/__snapshots__/manager.test.ts.snap @@ -17,9 +17,9 @@ exports[`FsProjectManager.create scaffolds the expected file tree into a fresh d "agentcore/cdk/package.json", "agentcore/cdk/test/cdk.test.ts", "agentcore/cdk/tsconfig.json", - "app/hello_world/README.md", - "app/hello_world/main.py", - "app/hello_world/pyproject.toml", + "app/agent_python/README.md", + "app/agent_python/main.py", + "app/agent_python/pyproject.toml", ] `; @@ -41,23 +41,23 @@ exports[`FsProjectManager.create snapshots the Strands project manifest and runt "agentcore/cdk/package.json", "agentcore/cdk/test/cdk.test.ts", "agentcore/cdk/tsconfig.json", - "app/strands_agent/.gitignore", - "app/strands_agent/README.md", - "app/strands_agent/main.py", - "app/strands_agent/mcp_client/__init__.py", - "app/strands_agent/mcp_client/client.py", - "app/strands_agent/memory/__init__.py", - "app/strands_agent/memory/session.py", - "app/strands_agent/model/__init__.py", - "app/strands_agent/model/load.py", - "app/strands_agent/model/mantle_compat.py", - "app/strands_agent/pyproject.toml", - "app/strands_agent/skills/fetcher.py", + "app/agent_python_strands/.gitignore", + "app/agent_python_strands/README.md", + "app/agent_python_strands/main.py", + "app/agent_python_strands/mcp_client/__init__.py", + "app/agent_python_strands/mcp_client/client.py", + "app/agent_python_strands/memory/__init__.py", + "app/agent_python_strands/memory/session.py", + "app/agent_python_strands/model/__init__.py", + "app/agent_python_strands/model/load.py", + "app/agent_python_strands/model/mantle_compat.py", + "app/agent_python_strands/pyproject.toml", + "app/agent_python_strands/skills/fetcher.py", ], "memories": [ { "eventExpiryDuration": 30, - "name": "strands_agentMemory", + "name": "agent_python_strandsMemory", "strategies": [ { "namespaceTemplates": [ @@ -92,9 +92,9 @@ exports[`FsProjectManager.create snapshots the Strands project manifest and runt "runtimes": [ { "build": "CodeZip", - "codeLocation": "app/strands_agent", + "codeLocation": "app/agent_python_strands", "entrypoint": "main.py", - "name": "strands_agent", + "name": "agent_python_strands", "protocol": "HTTP", "runtimeVersion": "PYTHON_3_14", }, @@ -120,19 +120,19 @@ exports[`FsProjectManager.create snapshots the Strands TypeScript project manife "agentcore/cdk/package.json", "agentcore/cdk/test/cdk.test.ts", "agentcore/cdk/tsconfig.json", - "app/strands_agent/.gitignore", - "app/strands_agent/README.md", - "app/strands_agent/main.ts", - "app/strands_agent/mcp_client/client.ts", - "app/strands_agent/memory/memory.ts", - "app/strands_agent/model/load.ts", - "app/strands_agent/package.json", - "app/strands_agent/tsconfig.json", + "app/agent_typescript_strands/.gitignore", + "app/agent_typescript_strands/README.md", + "app/agent_typescript_strands/main.ts", + "app/agent_typescript_strands/mcp_client/client.ts", + "app/agent_typescript_strands/memory/memory.ts", + "app/agent_typescript_strands/model/load.ts", + "app/agent_typescript_strands/package.json", + "app/agent_typescript_strands/tsconfig.json", ], "memories": [ { "eventExpiryDuration": 30, - "name": "strands_agentMemory", + "name": "agent_typescript_strandsMemory", "strategies": [ { "namespaceTemplates": [ @@ -167,9 +167,9 @@ exports[`FsProjectManager.create snapshots the Strands TypeScript project manife "runtimes": [ { "build": "CodeZip", - "codeLocation": "app/strands_agent", + "codeLocation": "app/agent_typescript_strands", "entrypoint": "main.js", - "name": "strands_agent", + "name": "agent_typescript_strands", "protocol": "HTTP", "runtimeVersion": "NODE_22", }, @@ -195,19 +195,19 @@ exports[`FsProjectManager.create snapshots the Strands A2A project manifest and "agentcore/cdk/package.json", "agentcore/cdk/test/cdk.test.ts", "agentcore/cdk/tsconfig.json", - "app/a2a_agent/.gitignore", - "app/a2a_agent/README.md", - "app/a2a_agent/main.py", - "app/a2a_agent/memory/__init__.py", - "app/a2a_agent/memory/session.py", - "app/a2a_agent/model/__init__.py", - "app/a2a_agent/model/load.py", - "app/a2a_agent/pyproject.toml", + "app/a2a_python_strands/.gitignore", + "app/a2a_python_strands/README.md", + "app/a2a_python_strands/main.py", + "app/a2a_python_strands/memory/__init__.py", + "app/a2a_python_strands/memory/session.py", + "app/a2a_python_strands/model/__init__.py", + "app/a2a_python_strands/model/load.py", + "app/a2a_python_strands/pyproject.toml", ], "memories": [ { "eventExpiryDuration": 30, - "name": "a2a_agentMemory", + "name": "a2a_python_strandsMemory", "strategies": [ { "namespaceTemplates": [ @@ -242,9 +242,9 @@ exports[`FsProjectManager.create snapshots the Strands A2A project manifest and "runtimes": [ { "build": "CodeZip", - "codeLocation": "app/a2a_agent", + "codeLocation": "app/a2a_python_strands", "entrypoint": "main.py", - "name": "a2a_agent", + "name": "a2a_python_strands", "protocol": "A2A", "runtimeVersion": "PYTHON_3_14", }, diff --git a/src/core/project/manager.export.test.ts b/src/core/project/manager.export.test.ts index 1c54253cd..6ba6099f7 100644 --- a/src/core/project/manager.export.test.ts +++ b/src/core/project/manager.export.test.ts @@ -61,7 +61,7 @@ async function projectWithHarness( name: "orders", skipInstall: true, skipGit: true, - scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("hello-world-python"), + scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("agent-python"), }), ); project = await drain( diff --git a/src/core/project/manager.test.ts b/src/core/project/manager.test.ts index a9aa4f9e1..47b11e5fa 100644 --- a/src/core/project/manager.test.ts +++ b/src/core/project/manager.test.ts @@ -25,12 +25,14 @@ import { import { createSilentLogger, TestIdentityClient } from "../../testing"; import type { DeployBackendInput, ProjectBackend } from "./backends/types"; -const HELLO_WORLD_PYTHON = resolveRuntimeTemplateShortcut("hello-world-python"); -const HELLO_WORLD_PYTHON_CONTAINER = resolveRuntimeTemplateShortcut("hello-world-python-container"); -const STRANDS_PYTHON = resolveRuntimeTemplateShortcut("strands-python"); -const STRANDS_TS = resolveRuntimeTemplateShortcut("strands-ts"); -const STRANDS_PY_A2A = resolveRuntimeTemplateShortcut("strands-py-a2a"); -const STRANDS_PY_A2A_CONTAINER = resolveRuntimeTemplateShortcut("strands-py-a2a", { +const AGENT_PYTHON = resolveRuntimeTemplateShortcut("agent-python"); +const AGENT_PYTHON_CONTAINER = resolveRuntimeTemplateShortcut("agent-python", { + build: "Container", +}); +const AGENT_PYTHON_STRANDS = resolveRuntimeTemplateShortcut("agent-python-strands"); +const AGENT_TYPESCRIPT_STRANDS = resolveRuntimeTemplateShortcut("agent-typescript-strands"); +const A2A_PYTHON_STRANDS = resolveRuntimeTemplateShortcut("a2a-python-strands"); +const A2A_PYTHON_STRANDS_CONTAINER = resolveRuntimeTemplateShortcut("a2a-python-strands", { build: "Container", }); @@ -97,7 +99,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); const projectRoot = join(directory, "example"); @@ -108,7 +110,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: STRANDS_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON_STRANDS, }); const projectRoot = join(directory, "example"); @@ -124,7 +126,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: STRANDS_TS, + scaffoldRuntimeInput: AGENT_TYPESCRIPT_STRANDS, }); const projectRoot = join(directory, "example"); @@ -140,7 +142,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: STRANDS_PY_A2A, + scaffoldRuntimeInput: A2A_PYTHON_STRANDS, }); const projectRoot = join(directory, "example"); @@ -156,27 +158,27 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: STRANDS_PY_A2A, + scaffoldRuntimeInput: A2A_PYTHON_STRANDS, }); const spec = await Bun.file(join(directory, "example", "agentcore", "agentcore.json")).json(); expect(spec.runtimes[0]).toMatchObject({ - name: "a2a_agent", + name: "a2a_python_strands", build: "CodeZip", protocol: "A2A", entrypoint: "main.py", }); - expect(spec.memories).toMatchObject([{ name: "a2a_agentMemory" }]); + expect(spec.memories).toMatchObject([{ name: "a2a_python_strandsMemory" }]); }); test("scaffolds the Strands A2A runtime as a container with --build Container", async () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: STRANDS_PY_A2A_CONTAINER, + scaffoldRuntimeInput: A2A_PYTHON_STRANDS_CONTAINER, }); - const appDir = join(directory, "example", "app", "a2a_agent"); + const appDir = join(directory, "example", "app", "a2a_python_strands"); expect(await Bun.file(join(appDir, "Dockerfile")).exists()).toBe(true); expect(await Bun.file(join(appDir, ".dockerignore")).exists()).toBe(true); @@ -192,7 +194,7 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); const configDir = join(directory, "example", "agentcore"); @@ -200,10 +202,10 @@ describe("FsProjectManager.create", () => { expect(spec.name).toBe("example"); expect(spec.runtimes).toEqual([ { - name: "hello_world", + name: "agent_python", build: "CodeZip", entrypoint: "main.py", - codeLocation: "app/hello_world", + codeLocation: "app/agent_python", runtimeVersion: "PYTHON_3_14", }, ]); @@ -214,10 +216,10 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON_CONTAINER, + scaffoldRuntimeInput: AGENT_PYTHON_CONTAINER, }); - const appDir = join(directory, "example", "app", "hello_world"); + const appDir = join(directory, "example", "app", "agent_python"); // dockerignore.template must render to .dockerignore (the fsTree regex fix). expect(await Bun.file(join(appDir, ".dockerignore")).exists()).toBe(true); expect(await Bun.file(join(appDir, "dockerignore.template")).exists()).toBe(false); @@ -231,7 +233,7 @@ describe("FsProjectManager.create", () => { await inTempDirectory(); const input: CreateProjectInput = { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }; await runCreate(manager().manager, input); @@ -263,13 +265,13 @@ describe("FsProjectManager.create", () => { const { manager: subject, commands } = manager(); await runCreate(subject, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); const projectRoot = join(directory, "example"); expect(commands).toEqual([ { command: ["npm", "install"], cwd: join(projectRoot, "agentcore", "cdk") }, - { command: ["uv", "sync"], cwd: join(projectRoot, "app", "hello_world") }, + { command: ["uv", "sync"], cwd: join(projectRoot, "app", "agent_python") }, { command: ["git", "init"], cwd: projectRoot }, ]); }); @@ -279,7 +281,7 @@ describe("FsProjectManager.create", () => { const { manager: subject, commands } = manager(); await runCreate(subject, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, skipInstall: true, }); @@ -289,17 +291,19 @@ describe("FsProjectManager.create", () => { test.each([ [ "Python", - resolveRuntimeTemplateShortcut("strands-python", { build: "Container" }), + resolveRuntimeTemplateShortcut("agent-python-strands", { build: "Container" }), ["uv", "lock"], + "agent_python_strands", ], [ "TypeScript", - resolveRuntimeTemplateShortcut("strands-ts", { build: "Container" }), + resolveRuntimeTemplateShortcut("agent-typescript-strands", { build: "Container" }), ["npm", "install", "--package-lock-only"], + "agent_typescript_strands", ], ])( "skipInstall still generates the container lockfile for %s", - async (_label, scaffoldRuntimeInput, lockCommand) => { + async (_label, scaffoldRuntimeInput, lockCommand, runtimeName) => { const directory = await inTempDirectory(); const { manager: subject, commands } = manager(); await runCreate(subject, { @@ -310,7 +314,7 @@ describe("FsProjectManager.create", () => { }); expect(commands).toEqual([ - { command: lockCommand, cwd: join(directory, "example", "app", "strands_agent") }, + { command: lockCommand, cwd: join(directory, "example", "app", runtimeName) }, ]); }, ); @@ -320,7 +324,7 @@ describe("FsProjectManager.create", () => { const { manager: subject, commands } = manager(); await runCreate(subject, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, skipGit: true, }); @@ -331,7 +335,7 @@ describe("FsProjectManager.create", () => { await inTempDirectory(); const { events, project } = await runCreate(manager().manager, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); expect(events.flatMap((event) => (event.type === "step" ? [event.message] : []))).toEqual([ @@ -357,7 +361,7 @@ describe("FsProjectManager.create", () => { }); await expect( - runCreate(failing, { name: "example", scaffoldRuntimeInput: HELLO_WORLD_PYTHON }), + runCreate(failing, { name: "example", scaffoldRuntimeInput: AGENT_PYTHON }), ).rejects.toThrow("npm exploded"); expect(await Bun.file(join(directory, "example", "agentcore", "agentcore.json")).exists()).toBe( true, @@ -368,14 +372,14 @@ describe("FsProjectManager.create", () => { const directory = await inTempDirectory(); await runCreate(manager().manager, { name: "root", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); process.chdir(join(directory, "root")); await expect( runCreate(manager().manager, { name: "child", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }), ).rejects.toBeInstanceOf(ProjectStateError); }); @@ -391,7 +395,7 @@ describe("FsProjectManager.build", () => { ): Promise { const { project } = await runCreate(subject, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, skipInstall: true, skipGit: true, }); @@ -772,7 +776,7 @@ describe("FsProjectManager.resolve", () => { const subject = manager().manager; await runCreate(subject, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); // Resolve from a nested path to prove the walk-up to the project root. @@ -810,10 +814,10 @@ describe("FsProjectManager.resolve", () => { version: 1, runtimes: [ { - name: "hello_world", + name: "agent_python", build: "CodeZip", entrypoint: "main.py", - codeLocation: "app/hello_world", + codeLocation: "app/agent_python", }, ], }), @@ -843,7 +847,7 @@ describe("FsProjectManager removal", () => { const subject = manager().manager; const { project } = await runCreate(subject, { name: "example", - scaffoldRuntimeInput: HELLO_WORLD_PYTHON, + scaffoldRuntimeInput: AGENT_PYTHON, }); return { subject, project }; } diff --git a/src/core/project/templates/export.ts b/src/core/project/templates/export.ts index fd882b04a..fb0c37d0e 100644 --- a/src/core/project/templates/export.ts +++ b/src/core/project/templates/export.ts @@ -53,7 +53,7 @@ export interface HarnessExportInput { /** The pure mapping result; the project manager executes it against the filesystem. */ export interface HarnessExportPlan { - /** Handlebars context for rendering the strands-http-python template. */ + /** Handlebars context for rendering the export-harness-python template. */ context: Record; /** The runtimes[] entry to append to agentcore.json. */ runtime: ProjectRuntime; diff --git a/src/core/project/templates/runtime.ts b/src/core/project/templates/runtime.ts index b3fc98117..98c733ff8 100644 --- a/src/core/project/templates/runtime.ts +++ b/src/core/project/templates/runtime.ts @@ -90,16 +90,18 @@ const importBedrockAgentResolver = () => async (input: RuntimeResourceConfig) => const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: TemplateRenderer) => ({ [buildResolverKey("none", "Python", "HTTP")]: async (input: RuntimeResourceConfig) => { if (input.scaffoldRuntimeInput.memory !== undefined) - throw new InputValidationError(`memory is not supported with the hello-world template`); + throw new InputValidationError(`memory is not supported with the agent-python template`); + const isContainer = input.scaffoldRuntimeInput.build === "Container"; const tree = await FsTreeNode.fromAssetSource( { assetSource }, + { assetDir: "templates/agent-python" }, { - assetDir: - input.scaffoldRuntimeInput.build === "Container" - ? "templates/hello-world-python-container" - : "templates/hello-world-python", + rootDirName: input.name, + filter: (name) => { + if (name === "Dockerfile" || name === ".dockerignore") return isContainer; + return true; + }, }, - { rootDirName: input.name }, ); return { tree, spec: { runtimes: [buildRuntimeSpec(input)] } }; }, @@ -145,7 +147,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa const isContainer = input.scaffoldRuntimeInput.build === "Container"; const tree = await FsTreeNode.fromAssetSource( { assetSource }, - { assetDir: "templates/strands-http-python" }, + { assetDir: "templates/agent-python-strands" }, { rootDirName: input.name, transformContent: (raw) => templateRenderer.render(raw, context), @@ -166,7 +168,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa }, [buildResolverKey("strands", "TypeScript", "HTTP")]: async (input: RuntimeResourceConfig) => { if (input.protocol !== undefined && input.protocol !== "HTTP") - throw new InputValidationError("the strands-ts template only supports HTTP"); + throw new InputValidationError("the agent-typescript-strands template only supports HTTP"); const memory = input.scaffoldRuntimeInput.memory; // The TypeScript strands SDK's createAgentCoreMemoryStores requires at least one @@ -174,7 +176,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa // https://github.com/aws/bedrock-agentcore-sdk-typescript/blob/v0.3.0/src/memory/integrations/strands/factory.ts#L130-L133 if (memory !== undefined && memory.strategies.length === 0) throw new InputValidationError( - "the strands-ts template does not support short-term-only memory; add long-term strategies or use --memory none", + "the agent-typescript-strands template does not support short-term-only memory; add long-term strategies or use --memory none", ); const context = { @@ -190,7 +192,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa const isContainer = input.scaffoldRuntimeInput.build === "Container"; const tree = await FsTreeNode.fromAssetSource( { assetSource }, - { assetDir: "templates/strands-http-typescript" }, + { assetDir: "templates/agent-typescript-strands" }, { rootDirName: input.name, transformContent: (raw) => templateRenderer.render(raw, context), @@ -241,7 +243,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa const isContainer = input.scaffoldRuntimeInput.build === "Container"; const tree = await FsTreeNode.fromAssetSource( { assetSource }, - { assetDir: "templates/python-mcp" }, + { assetDir: "templates/mcp-python-fastmcp" }, { rootDirName: input.name, transformContent: (raw) => templateRenderer.render(raw, context), @@ -292,7 +294,7 @@ const getTemplateResolvers = (assetSource: AssetSource, templateRenderer: Templa const isContainer = input.scaffoldRuntimeInput.build === "Container"; const tree = await FsTreeNode.fromAssetSource( { assetSource }, - { assetDir: "templates/strands-py-a2a" }, + { assetDir: "templates/a2a-python-strands" }, { rootDirName: input.name, transformContent: (raw) => templateRenderer.render(raw, context), diff --git a/src/handlers/project/add/gateway-target/index.test.ts b/src/handlers/project/add/gateway-target/index.test.ts index 211b5c27d..747b8410c 100644 --- a/src/handlers/project/add/gateway-target/index.test.ts +++ b/src/handlers/project/add/gateway-target/index.test.ts @@ -58,7 +58,7 @@ describe("project add gateway-target", () => { "--name", "runtime", "--runtime", - "hello_world", + "agent_python", "--runtime-endpoint", "DEFAULT", ]); @@ -73,7 +73,7 @@ describe("project add gateway-target", () => { { name: "runtime", targetType: "httpRuntime", - httpRuntime: { runtime: "hello_world", runtimeEndpoint: "DEFAULT" }, + httpRuntime: { runtime: "agent_python", runtimeEndpoint: "DEFAULT" }, }, ]); }); @@ -253,7 +253,7 @@ describe("project add gateway-target", () => { ["no Target mode", ["--gateway", "tools", "--name", "target"], "specify exactly one"], [ "multiple Target modes", - [...endpointFlags(), "--runtime", "hello_world"], + [...endpointFlags(), "--runtime", "agent_python"], "specify exactly one", ], [ diff --git a/src/handlers/project/add/gateway-test-support.ts b/src/handlers/project/add/gateway-test-support.ts index 9a422baff..e60f9976c 100644 --- a/src/handlers/project/add/gateway-test-support.ts +++ b/src/handlers/project/add/gateway-test-support.ts @@ -45,7 +45,7 @@ export function createGatewayProjectTestHarness(directoryPrefix: string) { "--name", name, "--template", - "hello-world-python", + "agent-python", "--skip-install", "--skip-git", ]); diff --git a/src/handlers/project/add/online-eval/index.test.ts b/src/handlers/project/add/online-eval/index.test.ts index 10ca3dd73..aa7154fe2 100644 --- a/src/handlers/project/add/online-eval/index.test.ts +++ b/src/handlers/project/add/online-eval/index.test.ts @@ -47,7 +47,7 @@ async function inProject(name = "TestProject"): Promise { "--name", name, "--template", - "hello-world-python", + "agent-python", "--skip-install", "--skip-git", ]); @@ -64,13 +64,13 @@ describe("project add online-eval", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--evaluator", "Builtin.Correctness", "--sampling-rate", "50", ], - { agent: "hello_world", evaluators: ["Builtin.Correctness"], samplingRate: 50 }, + { agent: "agent_python", evaluators: ["Builtin.Correctness"], samplingRate: 50 }, ], [ "custom log-group source", @@ -92,7 +92,7 @@ describe("project add online-eval", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--endpoint", "PROD", "--evaluator", @@ -100,7 +100,7 @@ describe("project add online-eval", () => { "--sampling-rate", "10", ], - { agent: "hello_world", endpoint: "PROD" }, + { agent: "agent_python", endpoint: "PROD" }, ], [ "service-name filter on a custom source", @@ -140,7 +140,7 @@ describe("project add online-eval", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--evaluator", "Builtin.Correctness", "--sampling-rate", diff --git a/src/handlers/project/add/online-insight/index.test.ts b/src/handlers/project/add/online-insight/index.test.ts index 69f943cc5..89551811f 100644 --- a/src/handlers/project/add/online-insight/index.test.ts +++ b/src/handlers/project/add/online-insight/index.test.ts @@ -47,7 +47,7 @@ async function inProject(name = "TestProject"): Promise { "--name", name, "--template", - "hello-world-python", + "agent-python", "--skip-install", "--skip-git", ]); @@ -62,8 +62,8 @@ describe("project add online-insight", () => { test.each<[string, string[], Record]>([ [ "minimal — agent source", - ["--name", "x", "--agent", "hello_world", "--insight", INSIGHT, "--sampling-rate", "50"], - { agent: "hello_world", insights: [INSIGHT], samplingRate: 50 }, + ["--name", "x", "--agent", "agent_python", "--insight", INSIGHT, "--sampling-rate", "50"], + { agent: "agent_python", insights: [INSIGHT], samplingRate: 50 }, ], [ "custom log-group source", @@ -85,7 +85,7 @@ describe("project add online-insight", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--endpoint", "PROD", "--insight", @@ -93,7 +93,7 @@ describe("project add online-insight", () => { "--sampling-rate", "10", ], - { agent: "hello_world", endpoint: "PROD" }, + { agent: "agent_python", endpoint: "PROD" }, ], [ "clustering frequencies", @@ -101,7 +101,7 @@ describe("project add online-insight", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--insight", INSIGHT, "--sampling-rate", @@ -134,7 +134,7 @@ describe("project add online-insight", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--insight", INSIGHT, "--sampling-rate", @@ -163,7 +163,7 @@ describe("project add online-insight", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--insight", INSIGHT, "--sampling-rate", @@ -190,7 +190,7 @@ describe("project add online-insight", () => { "--name", "x", "--agent", - "hello_world", + "agent_python", "--insight", INSIGHT, "--sampling-rate", diff --git a/src/handlers/project/add/payment-test-support.ts b/src/handlers/project/add/payment-test-support.ts index 66665c647..0e2322802 100644 --- a/src/handlers/project/add/payment-test-support.ts +++ b/src/handlers/project/add/payment-test-support.ts @@ -33,7 +33,7 @@ export function createPaymentProjectTestHarness(directoryPrefix: string) { "--name", name, "--template", - "hello-world-python", + "agent-python", "--skip-install", "--skip-git", ]); diff --git a/src/handlers/project/add/runtime/index.test.ts b/src/handlers/project/add/runtime/index.test.ts index b0bcf0e42..17869ac44 100644 --- a/src/handlers/project/add/runtime/index.test.ts +++ b/src/handlers/project/add/runtime/index.test.ts @@ -78,7 +78,7 @@ function translatedImportPlan( } describe("project add runtime", () => { - const template = ["--template", "hello-world-python"]; + const template = ["--template", "agent-python"]; const allScaffoldingFlags = [ "--build", @@ -125,18 +125,15 @@ describe("project add runtime", () => { build: "Container", dockerfile: "Dockerfile", }, - "container template build override to CodeZip": { - build: "CodeZip", - }, "strands template overrides to Container": { build: "Container", dockerfile: "Dockerfile", }, - "py-mcp template preset": { + "mcp-python-fastmcp template preset": { build: "CodeZip", protocol: "MCP", }, - "py-mcp overrides to Container": { + "mcp-python-fastmcp overrides to Container": { build: "Container", dockerfile: "Dockerfile", protocol: "MCP", @@ -145,11 +142,11 @@ describe("project add runtime", () => { build: "CodeZip", protocol: "MCP", }, - "strands-py-a2a template preset": { + "a2a-python-strands template preset": { build: "CodeZip", protocol: "A2A", }, - "strands-py-a2a overrides to Container": { + "a2a-python-strands overrides to Container": { build: "Container", dockerfile: "Dockerfile", protocol: "A2A", @@ -188,17 +185,16 @@ describe("project add runtime", () => { test.each<[string, string[]]>([ ["template preset", ["--name", "my_agent", ...template]], [ - "container template preset", - ["--name", "my_agent", "--template", "hello-world-python-container"], + "agent-python-strands template preset", + ["--name", "my_agent", "--template", "agent-python-strands"], ], - ["strands-python template preset", ["--name", "my_agent", "--template", "strands-python"]], [ "template overrides to Container", [ "--name", "my_agent", "--template", - "hello-world-python", + "agent-python", "--build", "Container", "--model-provider", @@ -208,22 +204,24 @@ describe("project add runtime", () => { ], ], [ - "container template build override to CodeZip", - ["--name", "my_agent", "--template", "hello-world-python-container", "--build", "CodeZip"], + "strands template overrides to Container", + ["--name", "my_agent", "--template", "agent-python-strands", "--build", "Container"], ], [ - "strands template overrides to Container", - ["--name", "my_agent", "--template", "strands-python", "--build", "Container"], + "mcp-python-fastmcp template preset", + ["--name", "my_mcp", "--template", "mcp-python-fastmcp"], ], - ["py-mcp template preset", ["--name", "my_mcp", "--template", "py-mcp"]], [ - "py-mcp overrides to Container", - ["--name", "my_mcp", "--template", "py-mcp", "--build", "Container"], + "mcp-python-fastmcp overrides to Container", + ["--name", "my_mcp", "--template", "mcp-python-fastmcp", "--build", "Container"], ], - ["strands-py-a2a template preset", ["--name", "my_a2a", "--template", "strands-py-a2a"]], [ - "strands-py-a2a overrides to Container", - ["--name", "my_a2a", "--template", "strands-py-a2a", "--build", "Container"], + "a2a-python-strands template preset", + ["--name", "my_a2a", "--template", "a2a-python-strands"], + ], + [ + "a2a-python-strands overrides to Container", + ["--name", "my_a2a", "--template", "a2a-python-strands", "--build", "Container"], ], [ "custom A2A runtime", @@ -245,12 +243,12 @@ describe("project add runtime", () => { ], ], [ - "strands-python with session, EFS, and S3 mounts", + "agent-python-strands with session, EFS, and S3 mounts", [ "--name", "fs_agent", "--template", - "strands-python", + "agent-python-strands", "--network-mode", "VPC", "--network-config", @@ -260,12 +258,12 @@ describe("project add runtime", () => { ], ], [ - "py-mcp with session, EFS, and S3 mounts", + "mcp-python-fastmcp with session, EFS, and S3 mounts", [ "--name", "fs_mcp", "--template", - "py-mcp", + "mcp-python-fastmcp", "--network-mode", "VPC", "--network-config", @@ -275,12 +273,12 @@ describe("project add runtime", () => { ], ], [ - "strands-py-a2a with session, EFS, and S3 mounts", + "a2a-python-strands with session, EFS, and S3 mounts", [ "--name", "fs_a2a", "--template", - "strands-py-a2a", + "a2a-python-strands", "--network-mode", "VPC", "--network-config", @@ -467,10 +465,7 @@ describe("project add runtime", () => { expect(runtime).toMatchObject({ entrypoint: "main.py", ...expectedSpecByLabel[label] }); expect(await Bun.file(join(projectRoot, "app", name, "main.py")).exists()).toBe(true); const buildFlagIndex = flags.indexOf("--build"); - const isContainer = - buildFlagIndex >= 0 - ? flags[buildFlagIndex + 1] === "Container" - : flags.includes("hello-world-python-container"); + const isContainer = buildFlagIndex >= 0 && flags[buildFlagIndex + 1] === "Container"; expect(runtime.runtimeVersion).toBe(isContainer ? undefined : "PYTHON_3_14"); expect(await Bun.file(join(projectRoot, "app", name, "Dockerfile")).exists()).toBe(isContainer); expect(await Bun.file(join(projectRoot, "app", name, ".dockerignore")).exists()).toBe( @@ -525,15 +520,15 @@ describe("project add runtime", () => { test.each<[string, string[], string[]]>([ [ "template preset defaults to long and short-term memory", - ["--name", "my_a2a", "--template", "strands-py-a2a"], + ["--name", "my_a2a", "--template", "a2a-python-strands"], ["SEMANTIC", "USER_PREFERENCE", "SUMMARIZATION", "EPISODIC"], ], [ "template preset with --memory none", - ["--name", "my_a2a", "--template", "strands-py-a2a", "--memory", "none"], + ["--name", "my_a2a", "--template", "a2a-python-strands", "--memory", "none"], [], ], - ])("strands-py-a2a %s", async (_label, flags, expectedStrategies) => { + ])("a2a-python-strands %s", async (_label, flags, expectedStrategies) => { const projectRoot = await inProject(); await run(["add", "runtime", ...flags]); @@ -556,7 +551,7 @@ describe("project add runtime", () => { test.each<[string, string[], string[]]>([ [ "template preset", - ["--name", "my_agent", "--template", "strands-ts"], + ["--name", "my_agent", "--template", "agent-typescript-strands"], ["SEMANTIC", "USER_PREFERENCE", "SUMMARIZATION", "EPISODIC"], ], [ @@ -579,43 +574,46 @@ describe("project add runtime", () => { ], [ "template overrides to Container", - ["--name", "my_agent", "--template", "strands-ts", "--build", "Container"], + ["--name", "my_agent", "--template", "agent-typescript-strands", "--build", "Container"], ["SEMANTIC", "USER_PREFERENCE", "SUMMARIZATION", "EPISODIC"], ], - ])("strands-ts %s scaffolds a TypeScript agent", async (_label, flags, expectedStrategies) => { - const projectRoot = await inProject(); - await run(["add", "runtime", ...flags]); - - const buildFlagIndex = flags.indexOf("--build"); - const isContainer = buildFlagIndex >= 0 && flags[buildFlagIndex + 1] === "Container"; - - const spec = await Bun.file(join(projectRoot, "agentcore", "agentcore.json")).json(); - const runtime = spec.runtimes.find( - (candidate: { name: string }) => candidate.name === "my_agent", - ); - expect(runtime).toMatchObject({ - entrypoint: "main.js", - ...(isContainer - ? { build: "Container", dockerfile: "Dockerfile" } - : { build: "CodeZip", runtimeVersion: "NODE_22" }), - }); - expect(runtime.runtimeVersion).toBe(isContainer ? undefined : "NODE_22"); - expect(await Bun.file(join(projectRoot, "app", "my_agent", "Dockerfile")).exists()).toBe( - isContainer, - ); - expect(await Bun.file(join(projectRoot, "app", "my_agent", ".dockerignore")).exists()).toBe( - isContainer, - ); - - const memory = (spec.memories ?? []).find( - (candidate: { name: string }) => candidate.name === "my_agentMemory", - ); - const strategies = memory?.strategies.map(({ type }: { type: string }) => type) ?? []; - expect(strategies).toEqual(expectedStrategies); - }); + ])( + "agent-typescript-strands %s scaffolds a TypeScript agent", + async (_label, flags, expectedStrategies) => { + const projectRoot = await inProject(); + await run(["add", "runtime", ...flags]); + + const buildFlagIndex = flags.indexOf("--build"); + const isContainer = buildFlagIndex >= 0 && flags[buildFlagIndex + 1] === "Container"; + + const spec = await Bun.file(join(projectRoot, "agentcore", "agentcore.json")).json(); + const runtime = spec.runtimes.find( + (candidate: { name: string }) => candidate.name === "my_agent", + ); + expect(runtime).toMatchObject({ + entrypoint: "main.js", + ...(isContainer + ? { build: "Container", dockerfile: "Dockerfile" } + : { build: "CodeZip", runtimeVersion: "NODE_22" }), + }); + expect(runtime.runtimeVersion).toBe(isContainer ? undefined : "NODE_22"); + expect(await Bun.file(join(projectRoot, "app", "my_agent", "Dockerfile")).exists()).toBe( + isContainer, + ); + expect(await Bun.file(join(projectRoot, "app", "my_agent", ".dockerignore")).exists()).toBe( + isContainer, + ); + + const memory = (spec.memories ?? []).find( + (candidate: { name: string }) => candidate.name === "my_agentMemory", + ); + const strategies = memory?.strategies.map(({ type }: { type: string }) => type) ?? []; + expect(strategies).toEqual(expectedStrategies); + }, + ); test.each<[string, string[]]>([ - ["missing --name", ["--template", "hello-world-python"]], + ["missing --name", ["--template", "agent-python"]], [ "missing --build without --template", [ @@ -632,8 +630,8 @@ describe("project add runtime", () => { ], ], [ - "--protocol cannot override the strands-python template", - ["--name", "my_agent", "--template", "strands-python", "--protocol", "MCP"], + "--protocol cannot override the agent-python-strands template", + ["--name", "my_agent", "--template", "agent-python-strands", "--protocol", "MCP"], ], [ "TypeScript without a strands template has no resolver", @@ -651,7 +649,7 @@ describe("project add runtime", () => { ], ], [ - "strands-ts rejects short-term-only memory", + "agent-typescript-strands rejects short-term-only memory", [ "--name", "my_agent", @@ -672,12 +670,12 @@ describe("project add runtime", () => { ["--name", "my_agent", ...template, "--network-config", "{bad}"], ], [ - "--protocol cannot override the hello-world-python template", - ["--name", "my_agent", "--template", "hello-world-python", "--protocol", "MCP"], + "--protocol cannot override the agent-python template", + ["--name", "my_agent", "--template", "agent-python", "--protocol", "MCP"], ], [ - "py-mcp does not support memory", - ["--name", "my_agent", "--template", "py-mcp", "--memory", "shortTerm"], + "mcp-python-fastmcp does not support memory", + ["--name", "my_agent", "--template", "mcp-python-fastmcp", "--memory", "shortTerm"], ], [ "--protocol alone requires --framework and --language", @@ -685,7 +683,7 @@ describe("project add runtime", () => { ], [ "--protocol cannot override a template", - ["--name", "my_agent", "--template", "py-mcp", "--protocol", "MCP"], + ["--name", "my_agent", "--template", "mcp-python-fastmcp", "--protocol", "MCP"], ], [ "custom MCP runtime does not support memory", @@ -758,7 +756,7 @@ describe("project add runtime", () => { "--name", "my_agent", "--template", - "hello-world-python", + "agent-python", `--${flagName}`, value, ]), @@ -777,7 +775,7 @@ describe("project add runtime", () => { "--name", "my_agent", "--template", - "hello-world-python", + "agent-python", "--api-key", `file://${apiKeyPath}`, ]), @@ -925,7 +923,7 @@ describe("project add runtime --type import", () => { const core = new TestCoreClient(); core.bedrockAgentImportPlans["A1B2C3D4E5/TSTALIASID"] = translatedImportPlan(); await expect(run([...importArgs, "--framework", "strands"], { core })).resolves.toBeDefined(); - await expect(run([...importArgs, "--template", "hello-world-python"])).rejects.toThrow( + await expect(run([...importArgs, "--template", "agent-python"])).rejects.toThrow( /--template cannot be combined/, ); await expect(run([...importArgs, "--build", "Container"])).rejects.toThrow( diff --git a/src/handlers/project/add/runtime/index.ts b/src/handlers/project/add/runtime/index.ts index f3148e219..4f629e7c5 100644 --- a/src/handlers/project/add/runtime/index.ts +++ b/src/handlers/project/add/runtime/index.ts @@ -226,7 +226,7 @@ export const createAddRuntimeHandler = (config: AddProjectResourceConfig) => ? LANGUAGE_VERSION_DEFAULTS[flags.language ?? "Python"] : undefined, }) - : resolveRuntimeTemplateShortcut("hello-world-python", { runtimeName: flags.name }); + : resolveRuntimeTemplateShortcut("agent-python", { runtimeName: flags.name }); const inputEnvironmentVariables = parseJsonFlag>( "environment-variables", diff --git a/src/handlers/project/create/create.screen.test.tsx b/src/handlers/project/create/create.screen.test.tsx index 10cb73945..c56259bed 100644 --- a/src/handlers/project/create/create.screen.test.tsx +++ b/src/handlers/project/create/create.screen.test.tsx @@ -282,14 +282,14 @@ describe("project create wizard", () => { await waitForText(r.lastFrame, "● scaffolded agent code"); await r.press("return"); - // Template step: the three refactor-supported templates are offered. + // Template step: the supported templates are offered. await waitForText(r.lastFrame, "choose a template"); - expect(r.lastFrame()).toContain("hello-world-python"); - expect(r.lastFrame()).toContain("hello-world-python-container"); - expect(r.lastFrame()).toContain("● strands-python (recommended)"); + expect(r.lastFrame()).toContain("mcp-python-fastmcp"); + expect(r.lastFrame()).toContain("a2a-python-strands"); + expect(r.lastFrame()).toContain("● agent-python-strands (recommended)"); const templateFrame = r.lastFrame() ?? ""; - expect(templateFrame.indexOf("strands-python")).toBeLessThan( - templateFrame.indexOf("hello-world-python"), + expect(templateFrame.indexOf("agent-python-strands")).toBeLessThan( + templateFrame.indexOf("mcp-python-fastmcp"), ); await r.press("return"); @@ -306,18 +306,18 @@ describe("project create wizard", () => { line.includes("this project will be created"), ); expect(reviewLines[reviewHeading + 1] ?? "").toContain("─"); - expect(r.lastFrame()).toContain("strands-python"); + expect(r.lastFrame()).toContain("agent-python-strands"); expect(r.lastFrame()).toContain("long and short-term"); await r.press("return"); await waitForText(r.lastFrame, "project created in ./StrandsApp", 5000); - // Identical to the flag-driven `--template strands-python` input. + // Identical to the flag-driven `--template agent-python-strands` input. expect(inputs).toEqual([ { name: "StrandsApp", skipInstall: false, skipGit: false, - scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("strands-python"), + scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("agent-python-strands"), }, ]); @@ -325,7 +325,7 @@ describe("project create wizard", () => { join(directory, "StrandsApp", "agentcore", "agentcore.json"), ).json(); expect(spec.runtimes.map((runtime: { name: string }) => runtime.name)).toEqual([ - "strands_agent", + "agent_python_strands", ]); expect(spec.memories).toHaveLength(1); r.unmount(); @@ -344,7 +344,7 @@ describe("project create wizard", () => { await r.press("down"); await r.press("return"); await waitForText(r.lastFrame, "choose a template"); - await r.press("return"); // strands-python is preselected + await r.press("return"); // agent-python-strands is preselected await waitForText(r.lastFrame, "choose a memory configuration"); await r.press("down"); // none await waitForText(r.lastFrame, "● none"); @@ -357,7 +357,9 @@ describe("project create wizard", () => { name: "BareStrands", skipInstall: false, skipGit: false, - scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("strands-python", { memory: "none" }), + scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("agent-python-strands", { + memory: "none", + }), }); r.unmount(); }, 10000); @@ -375,8 +377,8 @@ describe("project create wizard", () => { await r.press("down"); await r.press("return"); await waitForText(r.lastFrame, "choose a template"); - await r.press("down"); // hello-world-python - await waitForText(r.lastFrame, "● hello-world-python "); + await r.press("down"); // agent-python + await waitForText(r.lastFrame, "● agent-python "); await r.press("return"); // Straight to review: hello-world does not support memory. @@ -389,7 +391,7 @@ describe("project create wizard", () => { name: "HelloApp", skipInstall: false, skipGit: false, - scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("hello-world-python"), + scaffoldRuntimeInput: resolveRuntimeTemplateShortcut("agent-python"), }); r.unmount(); }, 10000); diff --git a/src/handlers/project/create/screen.tsx b/src/handlers/project/create/screen.tsx index bb31f661f..55048312a 100644 --- a/src/handlers/project/create/screen.tsx +++ b/src/handlers/project/create/screen.tsx @@ -99,7 +99,7 @@ function emptyCreateProjectForm(): CreateProjectFormValues { name: "", kind: "harness", model: emptyProjectModel(), - template: "strands-python", + template: "agent-python-strands", memory: "longAndShortTerm", }; } @@ -123,28 +123,23 @@ const TEMPLATE_OPTIONS: { description: string; }[] = [ { - template: "strands-python", - label: "strands-python (recommended)", + template: "agent-python-strands", + label: "agent-python-strands (recommended)", description: "Strands agent on Bedrock with memory (CodeZip build)", }, { - template: "hello-world-python", - label: "hello-world-python", + template: "agent-python", + label: "agent-python", description: "minimal Python agent on Bedrock, no framework (CodeZip build)", }, { - template: "hello-world-python-container", - label: "hello-world-python-container", - description: "the hello-world agent packaged as a container image", - }, - { - template: "py-mcp", - label: "py-mcp", + template: "mcp-python-fastmcp", + label: "mcp-python-fastmcp", description: "MCP server exposing tools via FastMCP (CodeZip build)", }, { - template: "strands-py-a2a", - label: "strands-py-a2a", + template: "a2a-python-strands", + label: "a2a-python-strands", description: "Strands agent speaking the A2A protocol on Bedrock (CodeZip build)", }, ]; @@ -195,9 +190,9 @@ export function buildCreateInput(values: CreateProjectFormValues): CreateProject skipGit: false, scaffoldRuntimeInput: resolveRuntimeTemplateShortcut( values.template, - // Memory is a strands question; the hello-world templates keep their own + // Memory is a strands question; the non-strands templates keep their own // (memory-less) defaults, exactly like `--template` without `--memory`. - values.template === "strands-python" ? { memory: values.memory } : undefined, + values.template === "agent-python-strands" ? { memory: values.memory } : undefined, ), }; } @@ -219,7 +214,7 @@ function summaryOf(values: CreateProjectFormValues): Record { }; } const withTemplate = { ...base, type: "agent code", template: values.template }; - return values.template === "strands-python" + return values.template === "agent-python-strands" ? { ...withTemplate, memory: MEMORY_OPTIONS.find((option) => option.memory === values.memory)!.label, @@ -263,7 +258,9 @@ export function ProjectCreateScreen({ core }: ScreenProps) { ? [{ key: "model", title: "model" }] : [ { key: "template", title: "template" }, - ...(values.template === "strands-python" ? [{ key: "memory", title: "memory" }] : []), + ...(values.template === "agent-python-strands" + ? [{ key: "memory", title: "memory" }] + : []), ]; return [ { key: "name", title: "name" }, diff --git a/src/handlers/project/export/harness.test.ts b/src/handlers/project/export/harness.test.ts index c3e2f9000..e2dcebe06 100644 --- a/src/handlers/project/export/harness.test.ts +++ b/src/handlers/project/export/harness.test.ts @@ -65,7 +65,7 @@ async function inProjectWithHarness( "--name", "orders", "--template", - "hello-world-python", + "agent-python", "--skip-install", "--skip-git", ]); @@ -155,8 +155,8 @@ describe("project export harness handler", () => { // The scaffolded template runtime already owns its name. await expect( - subject.run(["--name", "exportme", "--target-agent-name", "hello_world"]), - ).rejects.toThrow(/runtime with name 'hello_world' already exists/); + subject.run(["--name", "exportme", "--target-agent-name", "agent_python"]), + ).rejects.toThrow(/runtime with name 'agent_python' already exists/); // A harness name is just as taken. await expect( subject.run(["--name", "exportme", "--target-agent-name", "exportme"]), diff --git a/src/handlers/project/project.test.ts b/src/handlers/project/project.test.ts index 74c185ce1..200f55ce6 100644 --- a/src/handlers/project/project.test.ts +++ b/src/handlers/project/project.test.ts @@ -241,26 +241,19 @@ describe("project create", () => { run(["create", "--name", "MyAgent", "--framework", "strands", "--model-id", "x"]), ).rejects.toThrow(/Cannot mix runtime scaffolding flags \(--framework\)/); await expect( - run(["create", "--name", "MyAgent", "--template", "hello-world-python", "--timeout", "9"]), + run(["create", "--name", "MyAgent", "--template", "agent-python", "--timeout", "9"]), ).rejects.toThrow(/harness-only flags \(--timeout\)/); await expect( - run([ - "create", - "--name", - "MyAgent", - "--template", - "hello-world-python", - "--no-harness-memory", - ]), + run(["create", "--name", "MyAgent", "--template", "agent-python", "--no-harness-memory"]), ).rejects.toThrow(/harness-only flags \(--no-harness-memory\)/); }); test("--defaults is ignored when a runtime path flag routes to scaffolding", async () => { const directory = await inTempDirectory(); - await run(["create", "--name", "MyAgent", "--defaults", "--template", "hello-world-python"]); + await run(["create", "--name", "MyAgent", "--defaults", "--template", "agent-python"]); const spec = await Bun.file(join(directory, "MyAgent", "agentcore", "agentcore.json")).json(); - expect(spec.runtimes[0]).toMatchObject({ name: "hello_world" }); + expect(spec.runtimes[0]).toMatchObject({ name: "agent_python" }); expect(spec.harnesses).toBeUndefined(); }); @@ -368,18 +361,12 @@ describe("project create", () => { test("runs the post-scaffold steps and reports progress on stderr", async () => { const directory = await inTempDirectory(); - const { io, core } = await run([ - "create", - "--name", - "MyAgent", - "--template", - "hello-world-python", - ]); + const { io, core } = await run(["create", "--name", "MyAgent", "--template", "agent-python"]); const projectRoot = join(directory, "MyAgent"); expect(core.projectCommands).toEqual([ { command: ["npm", "install"], cwd: join(projectRoot, "agentcore", "cdk") }, - { command: ["uv", "sync"], cwd: join(projectRoot, "app", "hello_world") }, + { command: ["uv", "sync"], cwd: join(projectRoot, "app", "agent_python") }, { command: ["git", "init"], cwd: projectRoot }, ]); expect(io.stderr()).toContain("Creating project tree"); @@ -402,15 +389,7 @@ describe("project create", () => { ])("rejects --%s as a template override", async (flagName, value) => { await inTempDirectory(); await expect( - run([ - "create", - "--name", - "MyAgent", - "--template", - "hello-world-python", - `--${flagName}`, - value, - ]), + run(["create", "--name", "MyAgent", "--template", "agent-python", `--${flagName}`, value]), ).rejects.toThrow(`--${flagName} cannot override a template`); }); @@ -421,7 +400,7 @@ describe("project create", () => { "--name", "MyProject", "--template", - "strands-python", + "agent-python-strands", "--runtime-name", "custom_agent", "--build", @@ -453,7 +432,7 @@ describe("project create", () => { "--name", "MyProject", "--template", - "strands-python", + "agent-python-strands", "--model-provider", "open_ai", ]), @@ -468,7 +447,7 @@ describe("project create", () => { "--name", "MyProject", "--template", - "strands-python", + "agent-python-strands", "--build", "Container", "--skip-install", @@ -478,13 +457,13 @@ describe("project create", () => { const projectRoot = join(directory, "MyProject"); const spec = await Bun.file(join(projectRoot, "agentcore", "agentcore.json")).json(); expect(spec.runtimes[0]).toMatchObject({ - name: "strands_agent", + name: "agent_python_strands", build: "Container", - codeLocation: "app/strands_agent", + codeLocation: "app/agent_python_strands", dockerfile: "Dockerfile", }); expect(spec.runtimes[0].runtimeVersion).toBeUndefined(); - const runtimeRoot = join(projectRoot, "app", "strands_agent"); + const runtimeRoot = join(projectRoot, "app", "agent_python_strands"); expect(await Bun.file(join(runtimeRoot, "Dockerfile")).exists()).toBe(true); expect(await Bun.file(join(runtimeRoot, ".dockerignore")).exists()).toBe(true); }); @@ -496,12 +475,12 @@ describe("project create", () => { "--name", "MyProject", "--template", - "strands-python", + "agent-python-strands", "--skip-install", "--skip-git", ]); - const runtimeRoot = join(directory, "MyProject", "app", "strands_agent"); + const runtimeRoot = join(directory, "MyProject", "app", "agent_python_strands"); expect(await Bun.file(join(runtimeRoot, "Dockerfile")).exists()).toBe(false); expect(await Bun.file(join(runtimeRoot, ".dockerignore")).exists()).toBe(false); }); @@ -513,7 +492,7 @@ describe("project create", () => { "--name", "MyProject", "--template", - "strands-python", + "agent-python-strands", "--build", "Container", "--skip-install", @@ -522,18 +501,18 @@ describe("project create", () => { expect(core.projectCommands).toContainEqual({ command: ["uv", "lock"], - cwd: join(directory, "MyProject", "app", "strands_agent"), + cwd: join(directory, "MyProject", "app", "agent_python_strands"), }); }); - test("scaffolds an MCP server from the py-mcp template (CodeZip default)", async () => { + test("scaffolds an MCP server from the mcp-python-fastmcp template (CodeZip default)", async () => { const directory = await inTempDirectory(); await run([ "create", "--name", "MyProject", "--template", - "py-mcp", + "mcp-python-fastmcp", "--skip-install", "--skip-git", ]); @@ -541,27 +520,27 @@ describe("project create", () => { const projectRoot = join(directory, "MyProject"); const spec = await Bun.file(join(projectRoot, "agentcore", "agentcore.json")).json(); expect(spec.runtimes[0]).toMatchObject({ - name: "mcp_server", + name: "mcp_python_fastmcp", build: "CodeZip", protocol: "MCP", - codeLocation: "app/mcp_server", + codeLocation: "app/mcp_python_fastmcp", runtimeVersion: "PYTHON_3_14", }); - const runtimeRoot = join(projectRoot, "app", "mcp_server"); + const runtimeRoot = join(projectRoot, "app", "mcp_python_fastmcp"); const mainPy = await Bun.file(join(runtimeRoot, "main.py")).text(); expect(mainPy).toContain("FastMCP"); expect(mainPy).toContain('mcp.run(transport="streamable-http")'); expect(await Bun.file(join(runtimeRoot, "Dockerfile")).exists()).toBe(false); }); - test("scaffolds a Container MCP server from the py-mcp template", async () => { + test("scaffolds a Container MCP server from the mcp-python-fastmcp template", async () => { const directory = await inTempDirectory(); await run([ "create", "--name", "MyProject", "--template", - "py-mcp", + "mcp-python-fastmcp", "--build", "Container", "--skip-install", @@ -571,15 +550,15 @@ describe("project create", () => { const projectRoot = join(directory, "MyProject"); const spec = await Bun.file(join(projectRoot, "agentcore", "agentcore.json")).json(); expect(spec.runtimes[0]).toMatchObject({ - name: "mcp_server", + name: "mcp_python_fastmcp", build: "Container", protocol: "MCP", dockerfile: "Dockerfile", }); expect(spec.runtimes[0].runtimeVersion).toBeUndefined(); - expect(await Bun.file(join(projectRoot, "app", "mcp_server", "Dockerfile")).exists()).toBe( - true, - ); + expect( + await Bun.file(join(projectRoot, "app", "mcp_python_fastmcp", "Dockerfile")).exists(), + ).toBe(true); }); test.each([ @@ -768,7 +747,7 @@ describe("project create", () => { "--name", "MyProject", "--template", - "hello-world-python", + "agent-python", "--api-key", "-", "--skip-install", diff --git a/src/handlers/project/remove/index.test.ts b/src/handlers/project/remove/index.test.ts index 137b88a20..ef54af689 100644 --- a/src/handlers/project/remove/index.test.ts +++ b/src/handlers/project/remove/index.test.ts @@ -56,7 +56,7 @@ async function inProject(name = "TestProject"): Promise { "--name", name, "--template", - "hello-world-python", + "agent-python", "--skip-install", "--skip-git", ]); @@ -87,7 +87,7 @@ describe("project remove", () => { }, { label: "runtime", - commands: [["remove", "runtime", "--name", "hello_world"]], + commands: [["remove", "runtime", "--name", "agent_python"]], specKey: "runtimes", expectedRemaining: [], }, @@ -136,7 +136,7 @@ describe("project remove", () => { "--name", "quality", "--agent", - "hello_world", + "agent_python", "--evaluator", "Builtin.Correctness", "--sampling-rate", @@ -156,7 +156,7 @@ describe("project remove", () => { "--name", "failures", "--agent", - "hello_world", + "agent_python", "--insight", "Builtin.Insight.FailureAnalysis", "--sampling-rate", @@ -533,7 +533,7 @@ describe("project remove all", () => { expect(spec.managedBy).toBe(before.managedBy); // Removal stays spec-level: scaffolded code and the credential's env entry. - expect(existsSync(join(projectRoot, "app", "hello_world"))).toBe(true); + expect(existsSync(join(projectRoot, "app", "agent_python"))).toBe(true); expect(await Bun.file(envPath).text()).not.toContain(envKey); expect(io.stderr()).toContain(`removed '${envKey}' from ${ENV_LOCAL_RELATIVE_PATH}`); expect(io.stdout()).toContain("removed all resources from project"); diff --git a/src/handlers/project/shortcuts.ts b/src/handlers/project/shortcuts.ts index 5a783fd5e..72a6e08da 100644 --- a/src/handlers/project/shortcuts.ts +++ b/src/handlers/project/shortcuts.ts @@ -50,8 +50,8 @@ type RuntimeTemplateShortcut = Omit & { }; export const RUNTIME_TEMPLATE_SHORTCUTS = { - "hello-world-python": { - runtimeName: "hello_world", + "agent-python": { + runtimeName: "agent_python", build: "CodeZip", language: "Python", framework: "none", @@ -59,16 +59,8 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = { memory: "none", runtimeVersion: "PYTHON_3_14", }, - "hello-world-python-container": { - runtimeName: "hello_world", - build: "Container", - language: "Python", - framework: "none", - modelProvider: "Bedrock", - memory: "none", - }, - "strands-python": { - runtimeName: "strands_agent", + "agent-python-strands": { + runtimeName: "agent_python_strands", build: "CodeZip", language: "Python", framework: "strands", @@ -76,8 +68,8 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = { memory: "longAndShortTerm", runtimeVersion: "PYTHON_3_14", }, - "strands-ts": { - runtimeName: "strands_agent", + "agent-typescript-strands": { + runtimeName: "agent_typescript_strands", build: "CodeZip", language: "TypeScript", framework: "strands", @@ -85,8 +77,8 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = { memory: "longAndShortTerm", runtimeVersion: "NODE_22", }, - "py-mcp": { - runtimeName: "mcp_server", + "mcp-python-fastmcp": { + runtimeName: "mcp_python_fastmcp", build: "CodeZip", language: "Python", framework: "none", @@ -95,8 +87,8 @@ export const RUNTIME_TEMPLATE_SHORTCUTS = { memory: "none", runtimeVersion: "PYTHON_3_14", }, - "strands-py-a2a": { - runtimeName: "a2a_agent", + "a2a-python-strands": { + runtimeName: "a2a_python_strands", build: "CodeZip", language: "Python", framework: "strands",