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
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,21 @@ AgentCore with minimal configuration.

## Installation

```bash
npm install -g @aws/agentcore
```

> **Public Preview**: If you previously used the
> [Bedrock AgentCore Starter Toolkit](https://github.com/aws/bedrock-agentcore-starter-toolkit), uninstall it before
> using this CLI:
> **Upgrading from the Bedrock AgentCore Starter Toolkit?** The old Python CLI conflicts with this package. If it is
> still installed, `npm install` will fail with an error telling you which package manager has it. Uninstall it first
> using whichever tool you originally used:
>
> ```bash
> pip uninstall bedrock-agentcore-starter-toolkit
> pip uninstall bedrock-agentcore-starter-toolkit # if installed via pip
> pipx uninstall bedrock-agentcore-starter-toolkit # if installed via pipx
> uv tool uninstall bedrock-agentcore-starter-toolkit # if installed via uv
> ```
>
> If you need to bypass the check (for example, in CI), set `AGENTCORE_SKIP_CONFLICT_CHECK=1` before installing.

```bash
npm install -g @aws/agentcore
```

## Quick Start

Expand Down
29 changes: 20 additions & 9 deletions e2e-tests/e2e-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,24 +121,35 @@ export function createE2ESuite(cfg: E2EConfig) {
if (testDir) await rm(testDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 1000 });
}, 600000);

// Container builds go through CodeBuild which is slower and more prone to transient failures.
const isContainerBuild = cfg.build === 'Container';
const deployRetries = isContainerBuild ? 3 : 1;
const deployTimeout = isContainerBuild ? 900000 : 600000;

it.skipIf(!canRun)(
'deploys to AWS successfully',
async () => {
expect(projectPath, 'Project should have been created').toBeTruthy();

const result = await runCLI(['deploy', '--yes', '--json'], projectPath, false);
await retry(
async () => {
const result = await runCLI(['deploy', '--yes', '--json'], projectPath, false);

if (result.exitCode !== 0) {
console.log('Deploy stdout:', result.stdout);
console.log('Deploy stderr:', result.stderr);
}
if (result.exitCode !== 0) {
console.log('Deploy stdout:', result.stdout);
console.log('Deploy stderr:', result.stderr);
}

expect(result.exitCode, `Deploy failed: ${result.stderr}`).toBe(0);
expect(result.exitCode, `Deploy failed (stderr: ${result.stderr}, stdout: ${result.stdout})`).toBe(0);

const json = parseJsonOutput(result.stdout) as { success: boolean };
expect(json.success, 'Deploy should report success').toBe(true);
const json = parseJsonOutput(result.stdout) as { success: boolean };
expect(json.success, 'Deploy should report success').toBe(true);
},
deployRetries,
30000
);
},
600000
deployTimeout
);

it.skipIf(!canRun)(
Expand Down
32 changes: 16 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,13 @@
},
"overridesComments": {
"minimatch": "GHSA-7r86-cg39-jmmj, GHSA-23c5-xmqv-rm74: minimatch 10.0.0-10.2.2 has ReDoS vulnerabilities. Multiple transitive deps (eslint, typescript-eslint, eslint-plugin-import, eslint-plugin-react, prettier-plugin-sort-imports, aws-cdk-lib) pin older versions. Remove this override once upstream packages update their minimatch dependency to >=10.2.3.",
"fast-xml-parser": "GHSA-8gc5-j5rx-235r, GHSA-jp2q-39xq-3w4g: fast-xml-parser <=5.5.6 has entity expansion bypass (CVE-2026-33036, CVE-2026-33349). Transitive via @aws-sdk/xml-builder. Remove once @aws-sdk updates to fast-xml-parser >=5.5.7."
"fast-xml-parser": "GHSA-8gc5-j5rx-235r, GHSA-jp2q-39xq-3w4g: fast-xml-parser <=5.5.6 has entity expansion bypass (CVE-2026-33036, CVE-2026-33349). Transitive via @aws-sdk/xml-builder. Remove once @aws-sdk updates to fast-xml-parser >=5.5.7.",
"@aws-sdk/xml-builder": "@aws-sdk/xml-builder <3.972.14 uses fast-xml-parser without configuring processEntities.maxTotalExpansions, so the 5.5.7 default of 1000 breaks large CloudFormation responses. 3.972.14+ sets maxTotalExpansions: Infinity (safe for trusted AWS API responses). Remove once @aws-sdk/core updates to >=3.973.22."
},
"overrides": {
"minimatch": "10.2.4",
"fast-xml-parser": "5.5.7"
"fast-xml-parser": "5.5.7",
"@aws-sdk/xml-builder": "3.972.14"
},
"engines": {
"node": ">=20"
Expand Down
104 changes: 104 additions & 0 deletions scripts/check-old-cli.lib.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* Testable detection logic for the old Bedrock AgentCore Starter Toolkit.
*
* Each function accepts an `execSyncFn` so callers can inject a mock.
*/

const INSTALLERS = [
{ cmd: 'pip list', label: 'pip', uninstallCmd: 'pip uninstall bedrock-agentcore-starter-toolkit' },
{ cmd: 'pipx list', label: 'pipx', uninstallCmd: 'pipx uninstall bedrock-agentcore-starter-toolkit' },
{ cmd: 'uv tool list', label: 'uv', uninstallCmd: 'uv tool uninstall bedrock-agentcore-starter-toolkit' },
];

/**
* Run a package-manager list command and check whether the old toolkit appears.
* Returns `{ installer, uninstallCmd }` when found, or `null`.
*/
export function probeInstaller(cmd, label, uninstallCmd, execSyncFn) {
try {
const output = execSyncFn(cmd);
if (/^bedrock-agentcore-starter-toolkit\s/m.test(output)) {
return { installer: label, uninstallCmd };
}
} catch {
// Command not found or non-zero exit — ignore.
}
return null;
}

/**
* PATH-based fallback: locate an `agentcore` binary and check whether it's
* the old Python CLI (which doesn't support --version).
* Returns `{ installer, uninstallCmd }` when the old CLI is found, or `null`.
*/
export function probePath(execSyncFn, platform = process.platform) {
const whichCmd = platform === 'win32' ? 'where agentcore' : 'command -v agentcore';
let binaryPath;
try {
binaryPath = execSyncFn(whichCmd).trim();
} catch {
return null; // no agentcore binary on PATH
}
// Skip binaries installed via npm/node — a broken new CLI install would also
// fail --version, and we don't want to block reinstallation.
if (/node_modules|\/npm\/|\/nvm\/|\/fnm\/|\\npm\\/.test(binaryPath)) {
return null;
}
try {
execSyncFn('agentcore --version');
return null; // --version succeeded — this is the new CLI
} catch {
// --version failed — likely the old Python CLI
return {
installer: 'PATH',
uninstallCmd: 'pip uninstall bedrock-agentcore-starter-toolkit',
};
}
}

/**
* Probe pip, pipx, and uv for the old toolkit, then fall back to PATH-based
* detection. Returns an array of matches.
*/
export function detectOldToolkit(execSyncFn) {
const results = [];
for (const { cmd, label, uninstallCmd } of INSTALLERS) {
const match = probeInstaller(cmd, label, uninstallCmd, execSyncFn);
if (match) results.push(match);
}
// If package-manager queries found nothing, fall back to PATH-based check
if (results.length === 0) {
const pathMatch = probePath(execSyncFn);
if (pathMatch) results.push(pathMatch);
}
return results;
}

/**
* Format a user-facing error message listing per-installer uninstall commands.
*/
export function formatErrorMessage(detected) {
const lines = [
'',
'\x1b[31mError: The old Bedrock AgentCore Starter Toolkit is installed and conflicts with @aws/agentcore.\x1b[0m',
'',
'Uninstall it first, then re-run the install:',
'',
];

for (const { installer, uninstallCmd } of detected) {
lines.push(` ${uninstallCmd} # installed via ${installer}`);
}

lines.push(
'',
'Then re-run:',
'',
' npm install -g @aws/agentcore',
'',
'To bypass this check, set AGENTCORE_SKIP_CONFLICT_CHECK=1',
''
);

return lines.join('\n');
}
29 changes: 7 additions & 22 deletions scripts/check-old-cli.mjs
Original file line number Diff line number Diff line change
@@ -1,26 +1,11 @@
import { detectOldToolkit, formatErrorMessage } from './check-old-cli.lib.mjs';
import { execSync } from 'node:child_process';
import { platform } from 'node:os';

try {
// Check if an `agentcore` binary exists on PATH
const whichCmd = platform() === 'win32' ? 'where agentcore' : 'command -v agentcore';
execSync(whichCmd, { stdio: 'ignore' });
if (process.env.AGENTCORE_SKIP_CONFLICT_CHECK === '1') process.exit(0);

// Binary exists — check if it supports --version (the new CLI does, the old Python one does not)
try {
execSync('agentcore --version', { stdio: 'ignore' });
} catch {
// --version failed → likely the old Python CLI
console.warn(
[
'',
'\x1b[33m⚠ WARNING: We detected an older version of the AgentCore CLI.\x1b[0m',
'\x1b[33mFor the best experience, we recommend uninstalling it using:\x1b[0m',
'\x1b[33m pip uninstall bedrock-agentcore-starter-toolkit\x1b[0m',
'',
].join('\n')
);
}
} catch {
// No agentcore binary found or unexpected error — nothing to do
const detected = detectOldToolkit(cmd => execSync(cmd, { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }));

if (detected.length > 0) {
console.error(formatErrorMessage(detected));
process.exit(1);
}
Loading
Loading