feat: close the eight essential CLI feature gaps - #2146
Merged
Conversation
`project deploy` now synthesizes the `default` target when aws-targets.json is missing, empty, or lacks a `default` entry: the account comes from STS GetCallerIdentity and the region from the CLI's already-resolved effective region, validated against AgentCoreRegionSchema before anything is written. Existing entries are preserved byte-for-byte, the synthesized entry is reported on stderr, and the deploy proceeds in the same invocation. Named targets still require explicit configuration, and unsupported regions or unresolvable credentials fail with actionable errors before the file is touched. Also restores the vended CDK app (bin/cdk.ts, lib/cdk-stack.ts, test/cdk.test.ts, package.json) to its last publishable state: it referenced an AgentCorePayments L3 that no released @aws/agentcore-cdk exports, so every fresh scaffold failed `cdk synth` at tsc before reaching AWS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
…eck gate Leftover e2e scaffolds under out/ (and stale dist/ build output) were being swept up by bun test and tsc, failing the gate on files that are not part of the source tree. Scope both to the repo source, and fix the two react(set-state-in-effect) findings oxlint 1.80 raises in usePagedList and DataTable by deriving/adjusting state during render instead of in effects. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
Bare `project create --name X` (and --defaults) now creates a harness project — a managed agent configured by spec — matching the original CLI's default quick start. The harness-only flags (--model-id, --api-key-arn, --api-base, --additional-params, --no-harness-memory, --max-iterations, --max-tokens, --timeout, --truncation-strategy, --container) flow into the harness spec, which is validated up front against the same schema `project add harness` uses and scaffolded through the same addResource path, so the two entry points cannot drift. Runtime scaffolding is selected by --template or the runtime flags exactly as before; mixing the two flag families is a validation error, mirroring the original's dispatch. Tests that relied on the previous hello-world default now scaffold it explicitly via --template. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
`project create --type import --agent-id <id> --agent-alias-id <id>` (and the same on `project add runtime`) wraps an existing Amazon Bedrock Agent as an AgentCore runtime: the agent and alias are described through @aws-sdk/client-bedrock-agent to validate they exist (with the global --region naming the agent's region, validated against the supported list), and a proxy runtime is scaffolded from a new bedrock-agent-proxy-python template that forwards prompts via InvokeAgent and streams the reply. The vended bedrock-agent-policy.json grants the execution role bedrock:InvokeAgent on the alias through the runtime's additionalPolicies, so the project deploys and invokes like any other. The original CLI translated the Bedrock Agent's definition into native framework code; this ships the proxy shape instead — the agent stays the brain, the runtime is the AgentCore front door. bun.lock: adds the @aws-sdk/client-bedrock-agent entry; the surrounding churn is bun regenerating the lock format on install. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
project remove now accepts credential, config-bundle, online-eval, online-insight, and memory; removing a credential also deletes the .env.local keys it reserved (EnvLocalFile gains removeKeys with snapshot/rollback). Removing a resource that does not exist now throws ResourceNotFoundError instead of warn-and-rewrite. New `project remove all` empties every resource collection in agentcore.json (spec-level; app/ code and aws-targets.json are kept) behind a y/N prompt with --yes for non-interactive use. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
Bare `agentcore --version` (and -V) prints the package version embedded at build time and exits 0, in dev, bundled, and compiled forms. Handled as a pre-parse intercept on the root router rather than a Commander version option: a root-level --version option would shadow subcommands that declare their own `--version <value>` flag (harness version get, runtime version get, dataset --version, …). Root-only, matching the original CLI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
`agentcore project export harness` converts a harness into an editable Python Strands runtime agent: it renders the strands-http-python template under app/<target-agent-name>/ with a context mapped from the harness spec (model incl. Bedrock Mantle/OpenAI/Gemini/LiteLLM, system prompt, remote MCP + inline-function tools, path/s3/git skills, in-project memory, truncation, and execution limits via a vendored hooks/execution_limits.py), registers the runtime in agentcore.json (the harness entry stays), installs its deps with uv sync, and writes an EXPORT_NOTES.md in the agent directory listing precise manual follow-ups for everything that cannot be mapped mechanically (gateway/browser/code-interpreter tools, external/managed memory, aws skills, custom Dockerfiles, ...). The harness comes from `--name` (in-project files) or `--arn` (fetched from the service via GetHarness, using the region embedded in the ARN); exactly one is required, and the project is resolved and validated by withProject before any service fetch. `--target-agent-name` defaults to <harnessName>Agent, `--build` overrides the CodeZip default (containerUri / dockerfile harnesses auto-select Container), and `--json` emits a machine-readable summary on stdout while progress and notes stay on stderr. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
Move the runtime log-group derivation, the Insights query-value sanitizer, and the paginating CloudWatch Logs Insights query runner out of the private scope of src/core/eval.tsx into src/core/observability.ts so the upcoming runtime logs/traces commands can share them. The runner's row-ceiling error becomes an injectable policy (InsightsRowLimit); eval passes its existing message, so behavior is unchanged. Also adds parseTimeString, porting the old CLI's time-parser semantics (now / relative 5m-1h-2d / epoch ms / ISO 8601) with a typed InputValidationError on invalid input. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
Adds `agentcore runtime logs`: by default it live-tails the runtime's CloudWatch log group via StartLiveTail (reconnecting transparently over the ~3h session cap; Ctrl+C exits 130), and with --since/--until it switches to a bounded FilterLogEvents search, paginated to completion oldest-to-newest. --level/--query compose into a server-side filter pattern (ported from the old CLI's filter-pattern.ts), --limit caps search results, and --json emits JSON Lines. A missing log group maps to "has the runtime been invoked yet?" guidance. Addressing follows `runtime invoke --id`; without --id inside a project the deployed runtime is resolved live from the target stack's CloudFormation outputs (default target, one runtime auto-selects, several list candidates), through a new ObservabilityClient wired into CoreClient and the Core contract. The runtime router's TUI dispatch is limited to its existing children so a bare `runtime logs` streams instead of opening the TUI. The gitignore's blanket `logs` entry is scoped to the repo root so the handler directory is trackable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
Adds `agentcore runtime traces list` and `agentcore runtime traces get <traceId>`. list aggregates the runtime's telemetry with a Logs Insights `stats ... by traceId` query (newest first, default 12h window, --limit default 20) and renders a traceId/timestamp/sessionId table, or a single JSON document with --json; an empty result prints a stderr notice that traces take 2-3 minutes to appear. get validates the trace-id format, downloads every log record of the trace (@message JSON-parsed when possible), writes them to --output or agentcore/.cli/traces/ <runtime>-<traceId>.json inside a project (./<traceId>.json outside), and prints the written path on stdout. Both leaves share `runtime logs`' addressing: --id anywhere, or automatic resolution of the project's deployed runtime from its stack outputs. The queries run through the shared Insights runner extracted in the earlier observability refactor. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
A bare `agentcore project create` in a terminal now opens an interactive wizard: name (validated live against ProjectNameSchema, schema messages inline) → project type → harness model id or agent template (with the strands memory choice; hello-world skips it) → confirmation summary → live ProjectManager progress → success screen with next steps. The wizard builds the same CreateProjectInput as the flag-driven handler — resolveScaffoldHarnessInput (now exported) for the harness path, resolveRuntimeTemplateShortcut for templates — and iterates core.projectManager.create in the cwd, npm install and git init included. A create() failure renders and tears the TUI down via useApp().exit(error), so the process exits nonzero. Dispatch: only a bare, flagless invocation on a TTY opens the wizard (withTuiOnEmptyFlagsAndArgs, TTY-gated at registration). Any user-supplied flag, --json, or a non-TTY session stays headless. To make the middleware reachable, --name is optional at the Commander layer and enforced inside handle with the same "required option '--name <name>' not specified" wording — so `project create --defaults` and bare non-TTY invocations fail exactly as before. The other six project subcommands keep their not-implemented stubs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
Ink delivers rapidly typed keystrokes and every terminal paste as one
multi-character useInput event whose key.return is false even when the
chunk ends in "\r" — so TextInput appended the control byte into the
value as an invisible character. In the create wizard's name step that
left a visually valid name failing ProjectNameSchema with a message the
user couldn't act on ("must ... contain only alphanumeric characters")
and enter refusing to advance. Found by driving the wizard end-to-end
in a real pty during the final live smoke.
A single-line input must never store control bytes: strip C0 controls
and DEL from appended text (the official ink-text-input strips \r/\n
for the same reason). A stripped chunk's newline is deliberately not a
submit — matching readline and browser single-line paste semantics.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
Contributor
|
Claude Security Review: no high-confidence findings. (run) |
bun 1.4.0 — which CI installs via the unpinned setup-bun@v2 — records nested package.json overrides in the lockfile and refuses frozen installs when they are missing, so every CI job fails with "lockfile had changes, but lockfile is frozen" (the base refactor branch's own CI run on 2026-08-31 fails the same way; runs from 2026-08-28 under the previous bun were green). The bun that last saved this lockfile predated nested-override recording and silently dropped the @aws-cdk/toolkit-lib yaml pin from #2122. Regenerated with bun 1.4.0. The only changes are lockfileVersion 1 -> 3 and the recorded override block — zero resolution changes ("Checked 766 installs across 703 packages (no changes)"). The full CI gate passes under bun 1.4.0: frozen install, 2513 tests, tsc, oxlint, prettier. Note: lockfileVersion 3 requires bun >= 1.4.0 for lockfile-honoring installs; older bun prints "Ignoring lockfile" (it cannot represent the nested override either way, so there is no lockfile both versions accept). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## refactor #2146 +/- ##
============================================
- Coverage 97.29% 97.14% -0.15%
============================================
Files 479 494 +15
Lines 29673 32550 +2877
============================================
+ Hits 28871 31622 +2751
- Misses 802 928 +126 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The resolveTraceOutputPath tests hardcoded POSIX strings, so on Windows — where resolve() produces drive-letter backslash paths — all three failed. Build the expected values with the same join/resolve primitives the resolver uses: the tests pin down which branch wins (--output > project > cwd), not the platform separator. First surfaced by CI's Windows unit-test job, which this branch is the first to reach past the install step. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P
Contributor
|
Claude Security Review: no high-confidence findings. (run) |
Contributor
|
Claude Security Review: no high-confidence findings. (run) |
jariy17
approved these changes
Aug 31, 2026
This was referenced Aug 31, 2026
aidandaly24
added a commit
to aidandaly24/agentcore-cli
that referenced
this pull request
Sep 2, 2026
Export rendered `templates/strands-http-python`, the same template `project create` scaffolds from, so every export fix landed in a file whose primary consumer is the regular Strands runtime. That coupling is why this PR was touching provider loading, MCP client construction and memory retrieval in a shared template to fix bugs only export could reach. Export now renders `templates/export-harness-python`, and `strands-http-python` is restored to its pre-aws#2146 state: the hooks/execution_limits.py that aws#2146 added is gone, and the Bedrock model line it extended with temperature/top_p is back to its original form. `project create` output is byte-identical to refactor, verified by rendering a scaffold on both commits and diffing. The export template also drops what export can never produce: the container Dockerfile and .dockerignore (export is always CodeZip) and the Anthropic provider block (export emits Bedrock, OpenAI, Gemini or LiteLLM).
Hweinstock
pushed a commit
that referenced
this pull request
Sep 2, 2026
* feat(core): add cached EC2 client support * fix(export): preserve harness configuration fidelity * fix(export): validate service ARNs and restore VPC IDs * fix(templates): align generated provider dependencies * fix(templates): enforce harness limits per invocation * refactor(export): remove EC2 VPC lookup * fix(schemas): restore the lite_llm-only additionalParams guard The pinned @aws/agentcore-cdk rejects additionalParams on every provider but lite_llm, and re-parses harness.json at synth. Dropping the CLI refinement moved that failure from `project add harness` to `project build`, where it surfaces as a raw zod dump — reachable via `project create --additional-params`, whose provider defaults to bedrock. Restore the refinement, and drop the field with an export note on the --arn path instead of hard-failing, since a harness authored outside this CLI can carry it. * fix(export): require --vpc-id for container exports in VPC mode Export layers the generated agent into the harness's image by writing a `FROM <containerUri>` Dockerfile, which turns a no-build harness into a CodeBuild build. CodeBuild's CreateProject needs an explicit vpcId and cannot infer one from subnets, so the exported project failed at `project build` with a raw zod dump from CDK synth. Neither source of a harness carries a vpcId — the service's VpcConfig has no such field, and a local containerUri harness is never built so its schema rightly does not demand one. Export is what creates the requirement, so add --vpc-id and fail before writing anything when it is needed and absent. No AWS lookup is involved: getHarness remains the only request on the --arn path. * refactor: drop formatting residue from the reverted EC2 client Commit 8570ab2 added an `ec2:` stub key and a fake client, which pushed one object past prettier's width and shifted a blank line. b3fbb3d removed the EC2 code but left the reflowed formatting, so the PR still showed two core test files as changed with no bug behind them. Both files now match the base byte for byte. * fix(export): align --vpc-id with repo conventions Three follow-ups from auditing the new commits against surrounding code: - reuse NetworkConfigSchema.shape.vpcId for the flag instead of restating its regex, matching how every other validated flag reuses a projectSchemas schema (BuildTypeSchema, ProtocolModeSchema, NetworkModeSchema); the inline regex was the only one in src/handlers - the remedy said `--vpc-id vpc-xxxxxxxx`, which VPC_ID_PATTERN rejects because x is not a hex digit, so copy-pasting it produced a second error; use the <placeholder> form the other free-form remedies use - document the flag in README, which enumerates this command's flags in prose - cover both new mapper branches in export.test.ts, which owns mapHarnessToExportPlan branch coverage and already tests the sibling throw * test(export): trim a redundant assertion and close two coverage gaps Mutation-tested every test this PR adds by breaking the behaviour each one claims to cover and re-running it. Three results worth acting on: - the lite_llm half of "notes additionalParams..." asserted what the pre-existing "maps openai and litellm model configs" already asserts with the same fixture value; both fail on the same mutation, so it was pure duplication - "requires --vpc-id..." claimed in its comment to fail before writing anything but only asserted rejection, so relocating the throw after the write would have kept it green; now snapshots agentcore.json and checks the agent dir is absent - the ARN test never pinned the 12-digit account group; loosening \d{12} to \d+ passed. It now fails, verified by applying that mutation. Everything else detected its mutation and stays as is. * fix(export): note unsupported system prompt blocks * refactor(export): keep additional params LiteLLM-only * refactor(templates): remove unreachable provider params * fix(schemas): require vpcId for container builds in VPC mode ProjectRuntimeSchema already mirrors the CDK's CodeBuild security-group cap but not its vpcId requirement, so any writer of agentcore.json could emit a Container/VPC runtime that fails at synth. Adds the missing clause beside its sibling, using the CDK's `build === "Container"` predicate. The security-group cap test only asserted failure, which the new clause would satisfy on its own; it now pins the issue path so it still isolates the cap. * refactor(export): always export a CodeZip runtime The exported agent is a self-contained Strands application: its dependencies come from its own pyproject.toml and it defines its own entrypoint, so nothing in it comes from the source harness's image. Deriving a Container build from containerUri/dockerfile therefore bought a CodeBuild project, an ECR pull grant, and a VPC id the Runtime API cannot supply, for a base layer the agent never used. Export now always emits CodeZip and reports a source image or Dockerfile as an export note. Removes --vpc-id and --build from `project export harness`, along with resolveBuildType, resolveDockerfilePlan and buildDockerfileStub. Path-based skills are now rejected rather than noted: they name directories on the harness image's filesystem, which the exported agent does not have, so the files were simply absent at invocation. Republishing them from s3 or git is the supported path. Container-based export can return additively if a real need for it appears. ProjectRuntimeSchema's vpcId rule is kept — it guards `project add runtime` and hand-edited specs, which can still declare a Container build. * fix(templates): keep the Bedrock model block well formed The optional provider params were rendered with inline conditionals whose leading indentation survived when every param was absent, so a plain `project create` scaffold — which sets none of them — emitted a stray closing paren at twelve spaces. Uses the standalone-conditional form the rest of the template already relies on. * refactor(export): give harness export its own template Export rendered `templates/strands-http-python`, the same template `project create` scaffolds from, so every export fix landed in a file whose primary consumer is the regular Strands runtime. That coupling is why this PR was touching provider loading, MCP client construction and memory retrieval in a shared template to fix bugs only export could reach. Export now renders `templates/export-harness-python`, and `strands-http-python` is restored to its pre-#2146 state: the hooks/execution_limits.py that #2146 added is gone, and the Bedrock model line it extended with temperature/top_p is back to its original form. `project create` output is byte-identical to refactor, verified by rendering a scaffold on both commits and diffing. The export template also drops what export can never produce: the container Dockerfile and .dockerignore (export is always CodeZip) and the Anthropic provider block (export emits Bedrock, OpenAI, Gemini or LiteLLM). * refactor(export): drop template branches export cannot reach The export template started as a copy of strands-http-python, so it carried branches for capabilities the export mapper hardcodes off: gateway, browser and code-interpreter tools (all reported as manual follow-ups rather than generated), payment and config-bundle (no harness concept), and path skills (now rejected outright). Removes those blocks and the render-context keys that fed them. Verified by generating exports for four harness shapes — default Bedrock, execution limits with sliding-window truncation, LiteLLM, and remote MCP with colliding header names plus s3/git skills — before and after: byte-identical output, so only unreachable branches were removed. The generated agent still resolves strands-agents 1.54 via uv sync and imports.
aidandaly24
added a commit
that referenced
this pull request
Sep 3, 2026
… construct The generated CDK app has been carrying its own Payment orchestration since #2146 restored a pre-Quick-Create adapter to unblock scaffolding while AgentCorePayments was unpublished. That construct now ships in @aws/agentcore-cdk 0.1.0-alpha.51, so the vendored loops are obsolete. Quick Create is broken on refactor today: bin/cdk.ts requires every connector to resolve a credentialName to a deployed ARN, and a Quick Create connector deliberately has neither, so it throws before synthesis. The restored adapter also concatenates underscore-stripped manager and connector names into construct IDs, so foo_bar/foobar and A/BC versus AB/C collide, and the tests covering both behaviors were deleted alongside it. bin/cdk.ts now passes the raw spec and the target's deployed credentials straight through, and cdk-stack.ts hands them to AgentCorePayments, which owns connector variant mapping, credential resolution, runtime wiring and outputs inside the upgradeable package. Payment orchestration leaves the frozen scaffold, so future Payment changes reach existing projects through a dependency bump rather than a regenerated app. The generated-CDK tests for manual and Quick Create synthesis and for collision-safe identities are restored.
This was referenced Sep 3, 2026
Closed
Closed
aidandaly24
added a commit
that referenced
this pull request
Sep 4, 2026
… construct (#2186) * fix(project): deploy payments through the published AgentCorePayments construct The generated CDK app has been carrying its own Payment orchestration since #2146 restored a pre-Quick-Create adapter to unblock scaffolding while AgentCorePayments was unpublished. That construct now ships in @aws/agentcore-cdk 0.1.0-alpha.51, so the vendored loops are obsolete. Quick Create is broken on refactor today: bin/cdk.ts requires every connector to resolve a credentialName to a deployed ARN, and a Quick Create connector deliberately has neither, so it throws before synthesis. The restored adapter also concatenates underscore-stripped manager and connector names into construct IDs, so foo_bar/foobar and A/BC versus AB/C collide, and the tests covering both behaviors were deleted alongside it. bin/cdk.ts now passes the raw spec and the target's deployed credentials straight through, and cdk-stack.ts hands them to AgentCorePayments, which owns connector variant mapping, credential resolution, runtime wiring and outputs inside the upgradeable package. Payment orchestration leaves the frozen scaffold, so future Payment changes reach existing projects through a dependency bump rather than a regenerated app. The generated-CDK tests for manual and Quick Create synthesis and for collision-safe identities are restored. * feat(project): report Quick Create connectors awaiting authorization A Quick Create connector is deployed but unusable until someone follows its authorization link, and deploy said nothing about it. The link had to be dug out of the stack's CloudFormation outputs to be found at all, and it expires about ten minutes after the connector is created, so by the time anyone thought to look the window was usually gone. The project reported a successful deploy either way. Deploy now names each Quick Create connector the spec declares, with its live status and, while one exists, the link and how long it lasts. An expired connector says how to get a new link, which is to recreate it: neither UpdatePaymentConnector nor redeploying an unchanged connector mints another one. The status and the link are read from the Payments service rather than the outputs of the same name. Those outputs are Fn::GetAtt values resolved when the connector was created, so they keep serving a dead link and a stale PENDING_AUTHENTICATION long after the service has moved on to AUTHENTICATION_EXPIRED. Managers are found by their CloudFormation resource type in the project's own stack. Manager names are account-scoped, so matching the spec against the account would confuse two projects that both declare `payments`, and reading the L3's output keys would tie the CLI to names the L3 owns. Connectors then come from the manager, so connector names cannot collide across managers. Reads run after the stack is up and never fail the deploy: a status that cannot be retrieved is reported as such. A project without Quick Create connectors makes no calls at all. * fix(project): take the manager id out of the ARN CloudFormation reports The authorization report asked the Payments service about a manager using the physical resource id CloudFormation gives for it, which is the manager's ARN. `paymentManagerId` accepts only the bare identifier and rejects an ARN against its own pattern, so every deploy of a project with a Quick Create connector reported that the connector's status could not be retrieved instead of handing over its authorization link. Only reachable against CloudFormation, so the unit tests could not see it: they fake the service boundary, and the boundary was the defect. * test(project): drop the assertion on the Quick Create authorization output The generated app does not read this output, and neither does the CLI: the authorization URL is read from the Payments service because it expires. The L3 is removing the output for that reason, since an output holding an attribute that disappears fails every later stack update. Asserting it here only pins a value nothing consumes to whichever L3 version is pinned, so the pin bump can stand alone. * test(project): drop the connector identity test the L3 already owns The generated app hands the whole spec to AgentCorePayments, which derives every connector's construct identity. Feeding it colliding names asserted that derivation, not anything this package decides, and the L3 covers the same foo_bar/foobar case in its own suite. Seventy lines of fixture for one resource count, over code owned elsewhere. The manual and Quick Create synthesis test stays: it is the only check that the generated app passes the spec and the target's deployed credentials to the construct at all, which is exactly what regressed when the vendored Payment loops were restored. * refactor(project): simplify payment authorization URL reporting * fix(project): continue after payment connector lookup failures
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the eight essential feature gaps between the original CLI and the refactor, one commit per gap, each verified live against AWS account 501930284170 (us-east-1) where the gap has a deployable surface.
Gaps closed
1. Harness-first project creation —
feat(create): harness-first project creationBare
project create --name X(and--defaults) now creates a harness project, matching the original's default quick start. Harness-only flags (--model-id,--api-key-arn,--api-base,--additional-params,--no-harness-memory,--max-iterations,--max-tokens,--timeout,--truncation-strategy,--container) flow into the harness spec; the create-time harness scaffolds through the sameaddResourcepath asproject add harness; mixing harness and runtime-scaffolding flags is a validation error mirroring the original's dispatch.Live e2e:
project create --name GapE2eHarness0830 --model-id us.amazon.nova-lite-v1:0→ zero-configproject deploy→ stackAgentCore-GapE2eHarness0830-defaultCREATE_COMPLETE (us-east-1) →harness invokereturned a real Nova Lite response. Stack destroyed after (DELETE_COMPLETE).2. Bedrock Agent import —
feat(create): import a Bedrock Agent as a runtimeproject create --type import --agent-id --agent-alias-id(andproject add runtime --type import) describes the agent/alias via@aws-sdk/client-bedrock-agent(new dependency), validates the region against the supported list, and scaffolds a proxy runtime from the newbedrock-agent-proxy-pythontemplate (InvokeAgent + streamed reply; vendedbedrock-agent-policy.jsongrantsbedrock:InvokeAgentviaadditionalPolicies). Deliberate shape difference: the original translated the agent definition to framework code; this ships the proxy form per the parity spec.Live e2e: created throwaway Bedrock Agent
6AHPCYGV7S(Nova Lite) + aliasJJUMUT2PCQ+ service role; imported; deployedAgentCore-GapE2eImport0830-defaultCREATE_COMPLETE;runtime invoke→data: "The capital of France is Paris."; then destroyed the stack and deleted the agent, alias, and role.3. Export harness → Strands runtime —
feat(project): export a harness to a Strands runtime agentNew
project export harness(--namefor an in-project harness,--arnfor any service harness — region-aware from the ARN;--target-agent-name,--build CodeZip|Container,--json). Renders editable Strands code underapp/<target>/through the stock strands template's export context (model config for all four harness providers, system prompt, remote-MCP tools with credential env wiring, inline functions, skills, in-project memory, truncation, execution limits via a vendoredhooks/execution_limits.py), registers the runtime inagentcore.json(the harness entry is kept, mirroring the original), writesEXPORT_NOTES.mdfor anything unmappable, refuses overwrites, and validates the project before any service fetch (the 0.28.1 fix). 73 new unit tests.Live e2e:
GapE2eExport0830— deploy #1 CREATE_COMPLETE with harnessGapE2eExport0830_exportme-ZFg6mVuUYnREADY → export →project build→ deploy #2 UPDATE_COMPLETE →runtime invokeon the exported runtime streamed a live Nova Lite reply ("Exported agent reporting for duty."); the--arnpath was exercised against the deployed harness and built. Stack destroyed (DELETE_COMPLETE).4. Complete
project remove+remove all—feat(remove): cover all addable resources and add remove allThe remove enum now covers every addable type (adds credential, config-bundle, online-eval, online-insight, memory) with
.env.localcleanup for credentials; removing a nonexistent resource raisesResourceNotFoundErrorinstead of warn-and-rewrite;project remove allresets every spec collection behind a y/N confirmation with--yes.Live e2e:
GapE2eRemove0830— added all five newly-removable types, removed them (spec +.env.localverified), deployed CREATE_COMPLETE,remove all --yes, thendeploy --yesteardown path → DELETE_COMPLETE.5.
runtime logs—feat(runtime): logs streaming and search(+refactor(core): extract shared observability helpers)The precursor commit extracts the runtime log-group derivation and the multi-log-group, fully-paginated Logs Insights runner out of
core/evalintosrc/core/observability.ts(zero behavior change; eval re-pointed) and adds the time-string parser (now,30s/5m/1h/2d, epoch ms, ISO 8601).runtime logsthen ships follow mode by default (StartLiveTail with auto-reconnect over the 3-hour session cap; Ctrl-C exits 130 cleanly) and search mode on--since/--until(FilterLogEvents, paginated, oldest→newest), with--level,--query(composed into a CloudWatch filter pattern),--limit, and--jsonJSON-Lines.--idworks anywhere; inside a project the runtime id resolves live from the target stack's outputs via DescribeStacks (single runtime auto-selects; several → error listing candidates), with the deployment target's region taking precedence.Live e2e:
GapE2eObs0830deployed CREATE_COMPLETE; 4 invokes; search returned real events;--level/--query/--limit/--jsonverified; follow mode captured a mid-stream invocation marker and exited 130 on SIGINT; auto-resolve without--id(even with a wrong ambient--region) found the events. Stack destroyed after.6.
runtime traces—feat(runtime): traces list and getruntime traces list(--id/project auto-resolve,--limitdefault 20,--sincedefault 12h,--until,--json) aggregates recent traceIds with timestamps and session ids via the shared Insights runner (filtering empty-traceId infra records before aggregation — fixes an off-by-one the original had).runtime traces get <traceId>validates the id format and downloads every record to--outputoragentcore/.cli/traces/<runtime>-<traceId>.json. No hardcoded console URLs (deep link deliberately skipped).Live e2e: all four invocations' traces listed with matching session ids ~3 minutes after invoking;
traces getwrote 10 records to the default project path; invalid/missing trace ids and missing log group produce guided errors.7.
--version—feat(cli): add --versionBare
agentcore --version/-Vprints the build-time version (verified underbun runand in the bundleddist/index.js). Implemented as a root-only pre-parse intercept so leaf--version <value>flags (harness version get, etc.) are not shadowed.8.
project createTUI wizard —feat(tui): project create wizardBare
agentcore project createin a terminal now opens a wizard instead of exiting withNotImplementedError: name (validated live againstProjectNameSchema, schema messages shown inline) → project type (harness — the default, per gap 1 — or scaffolded agent) → harness model id or agent template with the strands memory choice (hello-world skips the memory question) → confirmation summary → liveProjectManagerprogress → success screen withcd/deploy next steps. No forked creation logic: the wizard builds the sameCreateProjectInputas the flag-driven handler (resolveScaffoldHarnessInput, now exported, for the harness path;resolveRuntimeTemplateShortcutfor templates) and iteratescore.projectManager.createin the cwd, npm install and git init included; acreate()failure renders and exits nonzero viauseApp().exit(error). Dispatch is conservative: only a bare, flagless invocation on a TTY opens the wizard (withTuiOnEmptyFlagsAndArgs, TTY-gated at registration) — any user-supplied flag,--json, or a non-TTY session behaves exactly as before, enforced by making--nameoptional at the Commander layer and re-validated in the handler with the identical error wording. The other six project subcommands keep their not-implemented stubs. 16 ink-testing-library tests cover the flows, validation, esc navigation, error teardown, and all four dispatch cases.Live check: wizard driven end-to-end in a real pty — name typed, harness type and default model accepted, review confirmed, creation ran (npm install + git init), success screen, exit 0 — producing a project spec-identical to the flag path's. Doing so surfaced a pre-existing UI-kit bug: Ink hands coalesced keystrokes (and every terminal paste) to
useInputas one chunk whosekey.returnis false, soTextInputstored a trailing\ras an invisible character that failed name validation with a message the user couldn't act on. Fixed infix(ui): strip control bytes from coalesced text-input chunks(C0/DEL stripped from appended text, matchingink-text-input's\r/\nhandling; stripped newlines deliberately don't submit), with a paste regression test.Verification
bun test(2513 pass, 0 fail, 184 files),bun run typecheck,bun run lint:check.project create --name GapE2eSmoke0831(bare → harness project) → zero-configproject deploy(target auto-provisioned: account 501930284170, us-east-1) → stackAgentCore-GapE2eSmoke0831-defaultCREATE_COMPLETE (verified via DescribeStacks) with harness READY →harness invokereturned the requested reply verbatim ("smoke test ok") →runtime logs --id harness_GapE2eSmoke0831_GapE2eSmoke0831-H1UyMN5OLm --since 15mreturned real CloudWatch events from the runtime log group; bareruntime logswithout--idin this harness-only project fails with the intended actionable error ("stack exports no runtime ids … pass --id" — harness stacks export an AgentRuntimeArn but no RuntimeId output, and the auto-resolver's contract is runtime outputs). Stack destroyed after (confirmed gone via DescribeStacks).bun.lock,node_moduleswas deleted and rebuilt solely from the committed lockfile under bun 1.4.0 (CI's toolchain) — the nested override resolves (@aws-cdk/toolkit-libgetsyaml@1.10.3), all 2513 tests pass on the fresh tree, and the live loop was re-run end-to-end: bareproject create --name GapE2eLock0831→ zero-configproject deploy→AgentCore-GapE2eLock0831-defaultCREATE_COMPLETE with harness READY →harness invokereturned the requested reply verbatim ("lockfile e2e ok") →runtime logs --since 10mreturned real events. Also exercised on the fresh tree:project create --template strands-python→project buildsynthesized the template (runtime + memory) cleanly, andadd runtime --type importloaded@aws-sdk/client-bedrock-agentand made a live signedGetAgentcall (the account role currently lacksbedrock:GetAgent, so it surfaced the service's AccessDenied cleanly and left the spec untouched — the SDK/dependency path the lockfile governs is proven). Stack destroyed after.CDKToolkitbootstrap stacks remain in us-east-1, us-west-2, eu-west-1 (pre-existing).Also included: a leading
chorecommit that scopesbun test/tscto the source tree (generatedout/scaffolds and staledist/output were failing the gate) and fixes tworeact(set-state-in-effect)findings newer oxlint raises.Stacked on #2145 (
feat(deploy): auto-provision the default deployment target from STS): its commit is the base of this branch because every live e2e here rides the zero-config deploy. The diff reduces to just this work once #2145 merges.CI fixes:
fix(deps): record the nested toolkit-lib yaml override in bun.lock, and a follow-upfix(test)making the trace output-path tests platform-agnostic (the Windows unit-test job — which this branch is the first to reach past the install step — exposed hardcoded POSIX path expectations). On the lockfile: CI installs the latest bun (unpinnedsetup-bun@v2); bun 1.4.0 records nestedpackage.jsonoverrides in the lockfile and fails--frozen-lockfilewhen they're absent — which also breaks the baserefactorbranch's own CI as of 2026-08-31 (green on 2026-08-28 under the previous bun). The regenerated lockfile changes onlylockfileVersion1→3 plus the recorded@aws-cdk/toolkit-libyaml override from #2122, with zero resolution changes; the full gate passes under bun 1.4.0. Heads-up for local dev: lockfileVersion 3 needs bun ≥ 1.4.0 (older bun ignores the lockfile — it can't represent the nested override in either format, so no lockfile satisfies both versions).🤖 Generated with Claude Code
https://claude.ai/code/session_01XfADH54TZn2SSGUUixft8P