diff --git a/docs/configuration.md b/docs/configuration.md index 827d884d2..985893652 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -31,7 +31,7 @@ Main project configuration using a **flat resource model**. Agents, memories, an "build": "CodeZip", "entrypoint": "main.py", "codeLocation": "app/MyAgent/", - "runtimeVersion": "PYTHON_3_13", + "runtimeVersion": "PYTHON_3_14", "networkMode": "PUBLIC", "protocol": "HTTP" } @@ -166,7 +166,7 @@ on the next deployment. "build": "CodeZip", "entrypoint": "main.py", "codeLocation": "app/MyAgent/", - "runtimeVersion": "PYTHON_3_13", + "runtimeVersion": "PYTHON_3_14", "networkMode": "PUBLIC", "envVars": [{ "name": "MY_VAR", "value": "my-value" }], "instrumentation": { @@ -201,6 +201,7 @@ on the next deployment. - `PYTHON_3_11` - `PYTHON_3_12` - `PYTHON_3_13` +- `PYTHON_3_14` **Node.js:** diff --git a/docs/container-builds.md b/docs/container-builds.md index a75f5e7a9..61d65bcde 100644 --- a/docs/container-builds.md +++ b/docs/container-builds.md @@ -58,7 +58,7 @@ In `agentcore.json`, set `"build": "Container"`: "build": "Container", "entrypoint": "main.py", "codeLocation": "app/MyAgent/", - "runtimeVersion": "PYTHON_3_13" + "runtimeVersion": "PYTHON_3_14" } ``` diff --git a/src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap b/src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap index d06f89b05..cd95b122d 100644 --- a/src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap +++ b/src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap @@ -4002,7 +4002,7 @@ file maps to a JSON config file and includes validation constraints as comments. - **BuildType**: \`'CodeZip'\` | \`'Container'\` - **NetworkMode**: \`'PUBLIC'\` -- **RuntimeVersion**: \`'PYTHON_3_10'\` | \`'PYTHON_3_11'\` | \`'PYTHON_3_12'\` | \`'PYTHON_3_13'\` +- **RuntimeVersion**: \`'PYTHON_3_10'\` | \`'PYTHON_3_11'\` | \`'PYTHON_3_12'\` | \`'PYTHON_3_13'\` | \`'PYTHON_3_14'\` - **MemoryStrategyType**: \`'SEMANTIC'\` | \`'SUMMARIZATION'\` | \`'USER_PREFERENCE'\` | \`'EPISODIC'\` ### Build Types diff --git a/src/assets/agents/AGENTS.md b/src/assets/agents/AGENTS.md index 7861af7ae..dc50d5349 100644 --- a/src/assets/agents/AGENTS.md +++ b/src/assets/agents/AGENTS.md @@ -62,7 +62,7 @@ file maps to a JSON config file and includes validation constraints as comments. - **BuildType**: `'CodeZip'` | `'Container'` - **NetworkMode**: `'PUBLIC'` -- **RuntimeVersion**: `'PYTHON_3_10'` | `'PYTHON_3_11'` | `'PYTHON_3_12'` | `'PYTHON_3_13'` +- **RuntimeVersion**: `'PYTHON_3_10'` | `'PYTHON_3_11'` | `'PYTHON_3_12'` | `'PYTHON_3_13'` | `'PYTHON_3_14'` - **MemoryStrategyType**: `'SEMANTIC'` | `'SUMMARIZATION'` | `'USER_PREFERENCE'` | `'EPISODIC'` ### Build Types diff --git a/src/cli/commands/import/constants.ts b/src/cli/commands/import/constants.ts index 93c25f902..9de391f55 100644 --- a/src/cli/commands/import/constants.ts +++ b/src/cli/commands/import/constants.ts @@ -51,4 +51,5 @@ export const RUNTIME_TYPE_MAP: Record = { PYTHON_3_11: 'PYTHON_3_11', PYTHON_3_12: 'PYTHON_3_12', PYTHON_3_13: 'PYTHON_3_13', + PYTHON_3_14: 'PYTHON_3_14', }; diff --git a/src/cli/operations/agent/generate/__tests__/schema-mapper.test.ts b/src/cli/operations/agent/generate/__tests__/schema-mapper.test.ts index 76b2de9f2..d30ae23fc 100644 --- a/src/cli/operations/agent/generate/__tests__/schema-mapper.test.ts +++ b/src/cli/operations/agent/generate/__tests__/schema-mapper.test.ts @@ -87,7 +87,7 @@ describe('mapGenerateConfigToAgent', () => { expect(result.name).toBe('TestProject'); expect(result.build).toBe('CodeZip'); expect(result.entrypoint).toBe('main.py'); - expect(result.runtimeVersion).toBe('PYTHON_3_13'); + expect(result.runtimeVersion).toBe('PYTHON_3_14'); expect(result.networkMode).toBe('PUBLIC'); expect(result.protocol).toBe('HTTP'); }); diff --git a/src/cli/primitives/AgentPrimitive.tsx b/src/cli/primitives/AgentPrimitive.tsx index 9d36efaeb..a2218aa2d 100644 --- a/src/cli/primitives/AgentPrimitive.tsx +++ b/src/cli/primitives/AgentPrimitive.tsx @@ -12,7 +12,13 @@ import type { SDKFramework, TargetLanguage, } from '../../schema'; -import { AgentEnvSpecSchema, CREDENTIAL_PROVIDERS, LIFECYCLE_TIMEOUT_MAX, LIFECYCLE_TIMEOUT_MIN } from '../../schema'; +import { + AgentEnvSpecSchema, + CREDENTIAL_PROVIDERS, + DEFAULT_PYTHON_VERSION, + LIFECYCLE_TIMEOUT_MAX, + LIFECYCLE_TIMEOUT_MIN, +} from '../../schema'; import type { AddAgentOptions as CLIAddAgentOptions } from '../commands/add/types'; import { validateAddAgentOptions } from '../commands/add/validate'; import { parseAndNormalizeHeaders } from '../commands/shared/header-utils'; @@ -526,7 +532,7 @@ export class AgentPrimitive extends BasePrimitive { expect(extractPythonVersion('PYTHON_3_13' as PythonRuntime)).toBe('3.13'); }); + it('extracts 3.14 from PYTHON_3_14', () => { + expect(extractPythonVersion('PYTHON_3_14' as PythonRuntime)).toBe('3.14'); + }); + it('throws for unsupported runtime string', () => { expect(() => extractPythonVersion('RUBY_3_0' as PythonRuntime)).toThrow('Unsupported Python runtime'); }); diff --git a/src/lib/packaging/__tests__/uv.test.ts b/src/lib/packaging/__tests__/uv.test.ts index a64cabb6a..143a428f5 100644 --- a/src/lib/packaging/__tests__/uv.test.ts +++ b/src/lib/packaging/__tests__/uv.test.ts @@ -57,6 +57,20 @@ describe('detectUnavailablePlatform', () => { expect(issue!.message).toContain('has no wheels'); }); + it('detects "no wheels with a matching Python ABI tag" message (e.g. cp314)', () => { + const out = 'numpy==2.4.4 has no wheels with a matching Python ABI tag (e.g., `cp314`)'; + const issue = detectUnavailablePlatform(result(out)); + expect(issue).not.toBeNull(); + expect(issue!.message).toContain('cp314'); + }); + + it('detects "has no usable wheels" message', () => { + const out = 'numpy>=1.10.4 has no usable wheels, we can conclude that numpy>=1.10.4 cannot be used.'; + const issue = detectUnavailablePlatform(result(out)); + expect(issue).not.toBeNull(); + expect(issue!.message).toContain('usable wheels'); + }); + it('returns null for successful output', () => { const out = 'Successfully installed package-1.0.0\nAll done!'; expect(detectUnavailablePlatform({ code: 0, stdout: out, stderr: '', signal: null })).toBeNull(); diff --git a/src/lib/packaging/index.ts b/src/lib/packaging/index.ts index e90413962..a281bbdbb 100644 --- a/src/lib/packaging/index.ts +++ b/src/lib/packaging/index.ts @@ -1,4 +1,5 @@ import type { AgentCoreProjectSpec, AgentEnvSpec, RuntimeVersion } from '../../schema'; +import { DEFAULT_PYTHON_VERSION } from '../../schema'; import { ContainerPackager } from './container'; import { PackagingError } from './errors'; import { isNodeRuntime, isPythonRuntime } from './helpers'; @@ -78,7 +79,7 @@ export async function packRuntime(spec: AgentEnvSpec, options?: PackageOptions): * Defaults to Python if no runtimeVersion is specified. */ export function packCodeZipSync(config: CodeBundleConfig | AgentEnvSpec, options?: PackageOptions): ArtifactResult { - const runtimeVersion = config.runtimeVersion ?? 'PYTHON_3_13'; + const runtimeVersion = config.runtimeVersion ?? DEFAULT_PYTHON_VERSION; const packager = getCodeZipPackager(runtimeVersion); return packager.packCodeZip(config as AgentEnvSpec, options); } diff --git a/src/lib/packaging/python.ts b/src/lib/packaging/python.ts index 5bb470eae..eac12567f 100644 --- a/src/lib/packaging/python.ts +++ b/src/lib/packaging/python.ts @@ -1,4 +1,5 @@ import type { AgentEnvSpec, PythonRuntime, RuntimeVersion } from '../../schema'; +import { DEFAULT_PYTHON_VERSION } from '../../schema'; import { UV_INSTALL_HINT, getArtifactZipName } from '../constants'; import { runSubprocessCapture, runSubprocessCaptureSync } from '../utils/subprocess'; import { PackagingError } from './errors'; @@ -155,7 +156,7 @@ export class PythonCodeZipPackager implements RuntimePackager { */ export class PythonCodeZipPackagerSync implements CodeZipPackager { packCodeZip(config: AgentEnvSpec, options: PackageOptions = {}): ArtifactResult { - const runtimeVersion = config.runtimeVersion ?? 'PYTHON_3_13'; + const runtimeVersion = config.runtimeVersion ?? DEFAULT_PYTHON_VERSION; if (!isPythonRuntimeVersion(runtimeVersion)) { throw new PackagingError(`Python packager only supports Python runtimes. Received: ${runtimeVersion}`); diff --git a/src/lib/packaging/uv.ts b/src/lib/packaging/uv.ts index 19e7fa0d8..1b6c0c2f6 100644 --- a/src/lib/packaging/uv.ts +++ b/src/lib/packaging/uv.ts @@ -7,7 +7,8 @@ export interface PlatformIssue { const PLATFORM_HINT_REGEX = /platforms:\s*([^\n]+)/i; const MANYLINUX_TOKEN = /(manylinux[^\s,]+)/gi; -const NO_WHEELS_REGEX = /(has no wheels with a matching platform tag|no compatible (?:wheels|tags) found)/i; +const NO_WHEELS_REGEX = + /(has no wheels with a matching (?:platform|Python ABI) tag|no compatible (?:wheels|tags) found|has no usable wheels)/i; export function detectUnavailablePlatform(result: SubprocessResult): PlatformIssue | null { const combined = `${result.stdout}\n${result.stderr}`; diff --git a/src/schema/__tests__/constants.test.ts b/src/schema/__tests__/constants.test.ts index affa85b58..dc6a491dd 100644 --- a/src/schema/__tests__/constants.test.ts +++ b/src/schema/__tests__/constants.test.ts @@ -60,13 +60,13 @@ describe('ModelProviderSchema', () => { }); describe('PythonRuntimeSchema', () => { - it.each(['PYTHON_3_10', 'PYTHON_3_11', 'PYTHON_3_12', 'PYTHON_3_13'])('accepts "%s"', version => { + it.each(['PYTHON_3_10', 'PYTHON_3_11', 'PYTHON_3_12', 'PYTHON_3_13', 'PYTHON_3_14'])('accepts "%s"', version => { expect(PythonRuntimeSchema.safeParse(version).success).toBe(true); }); it('rejects unsupported versions', () => { expect(PythonRuntimeSchema.safeParse('PYTHON_3_9').success).toBe(false); - expect(PythonRuntimeSchema.safeParse('PYTHON_3_14').success).toBe(false); + expect(PythonRuntimeSchema.safeParse('PYTHON_3_15').success).toBe(false); }); }); diff --git a/src/schema/constants.ts b/src/schema/constants.ts index ea159ec21..fc546276a 100644 --- a/src/schema/constants.ts +++ b/src/schema/constants.ts @@ -137,9 +137,12 @@ export function isReservedProjectName(name: string): boolean { // Infrastructure Constants (shared between agent-env and mcp schemas) // ============================================================================ -export const PythonRuntimeSchema = z.enum(['PYTHON_3_10', 'PYTHON_3_11', 'PYTHON_3_12', 'PYTHON_3_13']); +export const PythonRuntimeSchema = z.enum(['PYTHON_3_10', 'PYTHON_3_11', 'PYTHON_3_12', 'PYTHON_3_13', 'PYTHON_3_14']); export type PythonRuntime = z.infer; +/** Default Python runtime version for new agents and MCP tools */ +export const DEFAULT_PYTHON_VERSION: PythonRuntime = 'PYTHON_3_14'; + export const NodeRuntimeSchema = z.enum(['NODE_18', 'NODE_20', 'NODE_22']); export type NodeRuntime = z.infer; diff --git a/src/schema/llm-compacted/agentcore.ts b/src/schema/llm-compacted/agentcore.ts index 7fcda0245..8989d8842 100644 --- a/src/schema/llm-compacted/agentcore.ts +++ b/src/schema/llm-compacted/agentcore.ts @@ -25,7 +25,7 @@ interface AgentCoreProjectSpec { // ───────────────────────────────────────────────────────────────────────────── type BuildType = 'CodeZip' | 'Container'; -type PythonRuntime = 'PYTHON_3_10' | 'PYTHON_3_11' | 'PYTHON_3_12' | 'PYTHON_3_13'; +type PythonRuntime = 'PYTHON_3_10' | 'PYTHON_3_11' | 'PYTHON_3_12' | 'PYTHON_3_13' | 'PYTHON_3_14'; type NodeRuntime = 'NODE_18' | 'NODE_20' | 'NODE_22'; type RuntimeVersion = PythonRuntime | NodeRuntime; type NetworkMode = 'PUBLIC' | 'VPC'; diff --git a/src/schema/llm-compacted/mcp.ts b/src/schema/llm-compacted/mcp.ts index 16a613883..9e1e8d8a2 100644 --- a/src/schema/llm-compacted/mcp.ts +++ b/src/schema/llm-compacted/mcp.ts @@ -177,6 +177,6 @@ interface IamPolicyDocument { // ───────────────────────────────────────────────────────────────────────────── type GatewayTargetType = 'lambda' | 'mcpServer' | 'openApiSchema' | 'smithyModel' | 'apiGateway' | 'lambdaFunctionArn'; -type PythonRuntime = 'PYTHON_3_10' | 'PYTHON_3_11' | 'PYTHON_3_12' | 'PYTHON_3_13'; +type PythonRuntime = 'PYTHON_3_10' | 'PYTHON_3_11' | 'PYTHON_3_12' | 'PYTHON_3_13' | 'PYTHON_3_14'; type NodeRuntime = 'NODE_18' | 'NODE_20' | 'NODE_22'; type NetworkMode = 'PUBLIC' | 'VPC'; diff --git a/src/schema/schemas/__tests__/agent-env.test.ts b/src/schema/schemas/__tests__/agent-env.test.ts index 477c2489a..6f1a014b0 100644 --- a/src/schema/schemas/__tests__/agent-env.test.ts +++ b/src/schema/schemas/__tests__/agent-env.test.ts @@ -209,7 +209,7 @@ describe('AgentEnvSpecSchema', () => { }); it('accepts agent with all Python runtime versions', () => { - for (const version of ['PYTHON_3_10', 'PYTHON_3_11', 'PYTHON_3_12', 'PYTHON_3_13']) { + for (const version of ['PYTHON_3_10', 'PYTHON_3_11', 'PYTHON_3_12', 'PYTHON_3_13', 'PYTHON_3_14']) { const result = AgentEnvSpecSchema.safeParse({ ...validPythonAgent, runtimeVersion: version }); expect(result.success, `Should accept ${version}`).toBe(true); } diff --git a/src/tui-harness/helpers.ts b/src/tui-harness/helpers.ts index eaaa06b10..5b7a79895 100644 --- a/src/tui-harness/helpers.ts +++ b/src/tui-harness/helpers.ts @@ -5,6 +5,7 @@ * AgentCore CLI recognizes as valid projects, without the overhead of * running the full create wizard or npm/uv installs. */ +import { DEFAULT_PYTHON_VERSION } from '../schema'; import { mkdir, mkdtemp, rm, writeFile } from 'fs/promises'; import { tmpdir } from 'os'; import { join } from 'path'; @@ -103,7 +104,7 @@ export async function createMinimalProjectDir( build: 'CodeZip', entrypoint: 'main.py:handler', codeLocation: 'app/TestAgent', - runtimeVersion: 'PYTHON_3_13', + runtimeVersion: DEFAULT_PYTHON_VERSION, }); // Create the agent code directory so the CLI does not complain.