fix(typescript): TypeScript agent template and streaming fixes#981
Open
jesseturner21 wants to merge 36 commits intomainfrom
Open
fix(typescript): TypeScript agent template and streaming fixes#981jesseturner21 wants to merge 36 commits intomainfrom
jesseturner21 wants to merge 36 commits intomainfrom
Conversation
Unblocks TypeScript as a language option in the generate path and teaches the spec builder to emit NODE_22 / main.ts defaults when language=TypeScript. Templates, node setup helper, dev-server Python-only guard removal, tests, and docs still to come — see docs/TYPESCRIPT_SUPPORT_HANDOFF.md for the full remaining scope and plan link. - schema: add DEFAULT_NODE_VERSION, DEFAULT_ENTRYPOINT_BY_LANGUAGE, DEFAULT_RUNTIME_BY_LANGUAGE constants - tui: remove disabled=true from TypeScript LANGUAGE_OPTIONS entry - tui: filter SDK list to Strands-only when language=TypeScript - validate: drop the --language TypeScript reject; add Strands-only gate for TS - schema-mapper: branch entrypoint/runtime on config.language Confidence: medium Scope-risk: narrow Not-tested: end-to-end create/deploy — templates not yet authored
Living checklist alongside the handoff doc. Tracks phases 0-8, captures verification-sweep results, and reserves a commit log so the next person can reconstruct state from this file + git log. Confidence: high Scope-risk: narrow
Confidence: high Scope-risk: narrow
Drop the Python-only guard in isDevSupported. CodeZipDevServer already branches on entrypoint extension and selects `npx tsx watch` for non-Python agents, so the guard was the only thing rejecting TS entrypoints. Constraint: Dev-server spawn path must stay unchanged for Python agents Rejected: Add an explicit TypeScript allow-list branch | redundant — extension check already distinguishes, extra branch adds drift risk Confidence: high Scope-risk: narrow Not-tested: TS-specific unit test for spawn config (deferred to Phase 6)
Add src/assets/typescript/http/strands/ with gitignore, package.json,
tsconfig.json, main.ts, README.md, mcp_client/client.ts, model/load.ts,
and capabilities/memory/session.ts — mirroring the Python Strands
templates surface-for-surface, keyed off the same Handlebars variables.
Update asset snapshot baseline (8 new TS files + file-listing diff).
Align three stale tests with the Phase 1/2 validator + dev-server
changes: accept TS+Strands in validateAddAgentOptions; treat Node
entrypoints as dev-supported in getDevSupportedAgents / getDevConfig.
Extend .prettierignore to skip src/assets TS/JSON template files —
these are Handlebars templates with {{...}} expressions that do not
parse as TypeScript. ESLint already ignores src/assets via eslint.config.
Constraint: SDK surface for @strands-agents/sdk + bedrock-agentcore TS is still RC; templates are written against the surface described in the handoff
Rejected: Run prettier over the Handlebars TS templates | they do not parse as TS — same reason Python templates with {{...}} aren't formatted as Python
Confidence: medium
Scope-risk: narrow
Directive: Verify SDK event-type names, model-class names, and memory import path against the actual tarballs before shipping — see Known gotchas in docs/TYPESCRIPT_SUPPORT_PROGRESS.md
Not-tested: Rendered templates have not been compiled or run against real SDKs (Phase 6 integ + Phase 8 E2E)
src/assets/container/typescript/Dockerfile uses node:22-slim with a cached deps layer (npm ci --omit=dev, fallback to npm install when no lockfile) and runs `npx tsx main.ts`. Exposes 8080/8000/9000 to match the Python Dockerfile contract. Non-root bedrock_agentcore user mirrors Python. Update asset file-listing snapshot for the two new files. Constraint: Dev and container runtimes should share one entrypoint shape so main.ts stays the single source of truth Rejected: Add a tsc build step + `node dist/main.js` CMD | adds a build surface and diverges dev vs container semantics; defer until image size or cold start becomes a problem Confidence: medium Scope-risk: narrow Not-tested: Container build + AgentCore deploy against a live runtime (Phase 6 E2E)
Add src/cli/operations/node/setup.ts with setupNodeProject({projectDir})
that runs `npm install` and returns a structured result, mirroring the
Python setup helper. Export via a new node/ operations barrel.
Wire into useCreateFlow so a TypeScript create-path scaffold runs
`npm install` in app/<name>/ after the agent is added. Add a matching
entry to getCreateSteps so the progress UI reflects the step.
Unit tests mirror python/setup.test.ts (8 specs).
checkCreateDependencies requires no change — npm is already checked
unconditionally (needed for CDK synth) and uv is already gated to
Python. Node version is likewise checked unconditionally.
Constraint: Fresh scaffolds don't ship a lockfile
Rejected: Use `npm ci` | fails without package-lock.json; switching to `npm ci` after the first install is a later optimization
Rejected: Mark npm_not_found as a hard error | keep parity with Python (uv failure is a warn, not error) so create still succeeds and the user can install deps manually
Confidence: high
Scope-risk: narrow
Not-tested: End-to-end scaffold run against a real npm registry (Phase 8)
…ix spawn entrypoint rewrite Adds a TypeScript HTTP spec to codezip-dev-server.test.ts asserting the spawn is `npx tsx watch <entry>` with LOCAL_DEV env plumbed through. Adds a TypeScript block to the create integ suite that scaffolds a Strands/Bedrock TS agent and asserts the core generated files (main.ts, package.json, tsconfig.json, model/load.ts, mcp_client/client.ts). Fixes a latent bug in CodeZipDevServer where the non-Python spawn path was applying a Python-style module-path rewrite (`.replace(/\./g, '/') + '.ts'`), which turned `main.ts` into `main/ts.ts`. The entrypoint is now passed literally to tsx. Constraint: TS create integ must stay offline-safe — skips npm install via runCLI's skipInstall flag. Rejected: Shelling out to real `npm install` in the integ test | too slow + flaky on CI without a registry mirror. Confidence: high Scope-risk: narrow Directive: The non-Python dev-server spawn path passes the entrypoint literally — do not re-introduce Python module-path rewriting here. Not-tested: Real `npm install` end-to-end for TS scaffolds (covered manually in Phase 8).
Mirrors the create-flow pattern from lifecycle-config.test.ts. Drives `agentcore create --language TypeScript --framework Strands` through the advanced-no path, confirms, and asserts the generated agentcore.json has runtimeVersion "NODE_22" and entrypoint "main.ts". Runs with AGENTCORE_SKIP_INSTALL=1 so the scaffold stays fast and offline-safe. Constraint: Walkthrough must not require a network-reachable npm registry. Rejected: Exercising advanced-settings branch too | already covered by lifecycle-config.test.ts for Python; TS path reuses the same wizard. Confidence: medium Scope-risk: narrow Not-tested: Real npm install end-to-end (covered manually in Phase 8).
…trands gate The create command's validator still hard-rejected --language TypeScript with "TypeScript is not yet supported", which shadowed all the Phase 1–5 plumbing for TS agents. The add-agent validator already performs the Strands-only gate, but the create path was missed. Replaces the hard reject with the same Strands-only gate used by the add command: TypeScript is accepted, but non-Strands frameworks produce a clear "Framework X is not yet available for TypeScript" error. The generic "Invalid language" message now also lists TypeScript alongside Python. Updates the corresponding unit test (previously asserted the old error message) to cover both the TS+Strands happy path and the TS+non-Strands rejection. Constraint: Create and add validators must agree on which TS frameworks are permitted. Rejected: Leave the add validator as the only gate | create path is reachable directly from the CLI and must reject non-Strands TS itself. Confidence: high Scope-risk: narrow Directive: Keep create/validate.ts and add/validate.ts TS gates in lockstep — both must restrict TypeScript to Strands until other TS templates land.
Adds TypeScript coverage to the user-facing docs: - frameworks.md: new "Supported languages" table + Strands-only note, TS example in the Strands section. - local-development.md: new "TypeScript Agents" subsection covering the npm + tsx watch dev loop and AGENTCORE_SKIP_INSTALL. - commands.md: --language row now lists TypeScript (Strands-only) with a cross-link, plus a TS create example. - container-builds.md: new "TypeScript Dockerfile" subsection matching the generated template (node:22-slim, non-root, tsx entrypoint, agentcore.json example). - README.md: Strands row annotated "Python + TypeScript". Also logs Phase 7 completion and Phase 8 partial results in the progress tracker — unit + integ suites green, manual agentcore dev/deploy runs and the gated E2E container deploy test are still outstanding. Confidence: high Scope-risk: narrow Not-tested: Manual agentcore create -> dev -> deploy walkthrough deferred until credentials are refreshed.
Adds docs/TYPESCRIPT_SUPPORT_TEST_PLAN.md — a hands-on verification checklist for TypeScript Strands support that a tester can work through top-to-bottom. Structure: - Metadata block (tester, date, CLI version, Node/npm/platform) - 9 sections: prerequisites, automated suites, validator checks, scaffold, local dev, non-Strands rejection, CodeZip deploy + invoke, optional container build + deploy, docs smoke, Python regression - Each step has explicit commands, expected outcomes, and a [ ] / [x] / [!] / [~] status box - Known limitations and failure-capture guidance at the bottom Intended as a companion to docs/TYPESCRIPT_SUPPORT_PROGRESS.md — the progress tracker records what was built; this plan records what was actually tested end-to-end. Confidence: high Scope-risk: narrow Not-tested: The plan itself — it needs a first human pass to shake out any missing steps.
Extends docs/TYPESCRIPT_SUPPORT_TEST_PLAN.md with two kinds of pointers: - A top-level "Code map" table listing every concern (validator, templates, dev-server, packaging, TUI, etc.) alongside the primary source file and its test file. One-stop reference for a fixer. - Inline "Fix pointers if Section N fails" blocks after sections 2, 3, 4, 5, 6, and 7. Each explicitly names the file to edit and the corresponding test file, so a tester who hits a red box can jump straight to the right place without re-deriving the architecture. Rationale: the progress tracker lists what was built commit-by-commit, but the tester who follows the plan needs to know where to look when a step fails. Surfacing the files inline saves them from grepping the repo mid-bug. Confidence: high Scope-risk: narrow Not-tested: Link rot — these paths are accurate as of the latest commit but may drift if future refactors move files.
Two bugs blocked `agentcore dev` for scaffolded TypeScript agents:
1. `npm install` failed with ERESOLVE. bedrock-agentcore@0.2.2 declares
`@strands-agents/sdk >=0.1.0` as a peerOptional, and npm excludes
pre-releases (1.0.0-rc.4) from plain ranges. Added an `overrides`
block pinning bedrock-agentcore's peer to the root SDK version. Also
added the OpenTelemetry / AWS SDK / express / zod peers that Strands
SDK expects at runtime as direct deps so they resolve deterministically.
2. `app.run()` threw because `new BedrockAgentCoreApp()` with no args is
rejected by the 0.2.2 constructor. Rewrote the template to pass
`{ invocationHandler: { process } }` to the constructor instead of
assigning to `app.invocationHandler` post-construction.
Verified end-to-end: fresh `agentcore create --language TypeScript` →
`agentcore dev` binds :8080, Fastify serves `/invocations`, agent
streams a 200 response in ~2.7s, and `tsx watch` hot-reloads on edits.
Constraint: bedrock-agentcore@0.2.2 peerOptional excludes pre-release SDKs
Rejected: bump Strands SDK past 1.0.0-rc.4 | no stable release available yet
Confidence: high
Scope-risk: narrow
Not-tested: Container build path and MCP gateway variant of this template
… projects Non-interactive `agentcore create --language TypeScript` scaffolded files but never ran `npm install`, so the resulting project could not boot `agentcore dev` without a manual install step. Python had the equivalent `setupPythonProject` call; TypeScript had no matching branch. Added a `setupNodeProject` invocation that runs when language=TypeScript and `--skip-install` is not set. npm failures (ERESOLVE, missing npm, etc.) are surfaced as warnings on the result rather than aborting the whole create — the scaffold is still useful and the user can retry. Also added a TypeScript branch to `getDryRunInfo` so `--dry-run` lists the TS files that would be created (main.ts, package.json, tsconfig.json, model/load.ts, mcp_client/client.ts) instead of an empty `app/` entry. Constraint: Must match Python's behavior so non-interactive flow is symmetric Confidence: high Scope-risk: narrow
… TUI The interactive TS create flow previously collapsed every npm install failure into "Failed to set up Node environment. Run npm install manually to see the error." That hid ERESOLVE and other diagnostic output behind a manual re-run, which was especially painful during the rc.4/peer-dep work since the user had no signal why install failed. Now the warn message includes the first meaningful line of npm stderr (stripped of the `npm error`/`npm warn` prefix, capped at 160 chars), differentiates `npm_not_found` from install failures, and logs every non-empty line of npm output as a sub-step so the full trace is visible in the TUI without re-running. Confidence: high Scope-risk: narrow
…bash Filled-in copy of docs/TYPESCRIPT_SUPPORT_TEST_PLAN.md with run data, outputs, and checkbox state for each scenario exercised during the TypeScript support bug bash. Captures what works today, what required the template and create-flow fixes landing in this batch, and the residual gaps (container build path, MCP gateway variant) that need follow-up. Confidence: high Scope-risk: narrow
`agentcore dev` with build=Container failed during image build with `useradd: UID 1000 is not unique`. The node:22-slim base image already ships a `node` user at UID 1000, so creating `bedrock_agentcore` at the same UID collided. Delete the preexisting node user before creating bedrock_agentcore so UID 1000 is free. Verified with a fresh TS Container scaffold: image builds in ~12s, container boots, `/ping` returns Healthy, and `/invocations` routes to the agent. Constraint: Must keep bedrock_agentcore at UID 1000 to match Python image Rejected: Pick a different UID | diverges from Python container contract Confidence: high Scope-risk: narrow Directive: node:22-slim base reserves UID 1000 for `node` — leave the `userdel -r node` in place if this image is ever rebased onto a different tag, verify no other user at UID 1000 first
…t re-install The TS Container Dockerfile runs `npm ci --omit=dev`, which drops tsx because it was a devDependency. The container then fell back to `npx tsx main.ts` at runtime, which re-downloaded tsx from the registry on every boot (~4–6s added latency, plus a hard dep on network access at container start). Moved tsx to dependencies. Preinstalled in the image, no network call at boot, container ready ~5s instead of 10+. Local `tsx watch` dev behavior is unchanged since runtime-present deps are still resolvable by the `dev` script. Snapshot updated to reflect the new dep layout. Confidence: high Scope-risk: narrow
… clear error `agentcore create --protocol MCP --language TypeScript` previously got past validation and crashed in the renderer with an ENOENT pointing at a non-existent template directory (`src/assets/typescript/mcp/standalone/base`). The MCP TS template has not been authored yet. Added an explicit guard in both `create` and `add agent` validators that returns "MCP protocol is not yet supported for TypeScript. Use --protocol HTTP or --language Python." before we try to render the missing template. Same message for both commands so users hitting it from either path see the same guidance. Follow-up: when the MCP TS template lands, delete these two guards. Confidence: high Scope-risk: narrow Directive: Remove these guards in lockstep with the MCP TS template — leaving one in place will continue rejecting a valid combo.
The language picker in the interactive `agentcore create` wizard had TypeScript marked `disabled: true` with a "(coming soon)" label, so users could not pick it from the TUI even though non-interactive `agentcore create --language TypeScript` worked end-to-end. Removed the disabled flag and "(coming soon)" label now that the TS HTTP/Strands template runs through create, dev (CodeZip), and dev (Container) verified end-to-end. Also dropped the now-dead `'disabled' in o` branch in GenerateWizardUI since no LANGUAGE_OPTIONS entry carries the field anymore. Confidence: high Scope-risk: narrow
…TS templates land `agentcore create` exposed MCP and A2A in the TUI protocol picker for any language. Both trigger a renderer ENOENT for TypeScript because the templates (`typescript/mcp/...`, `typescript/a2a/...`) do not exist yet. - TUI: protocol step now disables MCP and A2A when language=TypeScript, so the picker reflects what is actually supported. - Validators: replaced the MCP-only TypeScript guard (landed in 38e9973) with a general `protocol !== 'HTTP' && language === 'TypeScript'` check, so A2A is now rejected with the same friendly message instead of crashing in the renderer. Follow-up: when MCP and/or A2A TS templates land, drop the disabled flag in GenerateWizardUI and the validator guards in both create and add — all three must move in lockstep. Confidence: high Scope-risk: narrow Directive: The validator and TUI guards are paired with a missing template. Do not remove one without confirming the corresponding template directory exists under `src/assets/typescript/`.
…, browser + no-browser) Unblock TypeScript agents in `agentcore dev` across all four combinations: CodeZip/Container x browser/no-browser. The underlying dev server already handled TypeScript in the CodeZip spawn path (npx tsx watch) and the Container path is language-agnostic - only the user-facing guards and messages still claimed Python-only. Also wires a node-deps install step parallel to ensurePythonVenv so a freshly cloned TS project works on first invocation. - command.tsx: drop "requires Python agents" message - DevScreen.tsx: drop "requires Python agent" message - codezip-dev-server.ts: add ensureNodeDeps (detects pnpm/yarn/npm via lockfile) - codezip-dev-server.test.ts: cover install-on-missing and skip-on-present Constraint: Container path must remain language-agnostic - no Dockerfile assumptions Rejected: Split CodeZip into Python/Node subclasses | spawn branch is 8 lines, not worth the abstraction Confidence: high Scope-risk: narrow Not-tested: End-to-end matrix against live AWS; pre-existing dev.test.ts failures unrelated to this change
The useDevServer hook only checked for Python/uvicorn startup strings
("Application startup complete", "Uvicorn running") to transition from
"starting" to "running". TS agents log "Server listening" instead,
causing the TUI to stay stuck on "Starting..." forever.
Add "Server listening" to the readiness detection pattern.
Confidence: high
Scope-risk: narrow
The Strands TypeScript SDK (@strands-agents/sdk 1.0.0-rc.4) emits modelStreamUpdateEvent with nested modelContentBlockDeltaEvent, not contentBlockDelta. The template filter matched nothing, so the async generator yielded zero chunks and agentcore dev showed empty response.
The SigV4 invoke paths sent Accept: application/json, causing 406 Not Acceptable from container agents whose bedrock-agentcore runtime only produces SSE streams. The bearer-token, MCP, A2A, and AGUI paths already included text/event-stream — this aligns the two remaining HTTP invoke functions. Constraint: bedrock-agentcore Node.js runtime returns 406 when Accept header lacks text/event-stream and handler is an async generator Rejected: Change only the streaming path | non-streaming path also needs it for containers that always stream Confidence: high Scope-risk: narrow
…mplates TypeScript Strands SDK does not yet support the memory session manager, so the generate wizard now skips the memory step for TypeScript agents and the template removes the memory-related Handlebars blocks. Also filters protocol options to only show HTTP for TypeScript (instead of showing disabled options) for a cleaner UX.
Contributor
Package TarballHow to installnpm install https://github.com/aws/agentcore-cli/releases/download/pr-981-tarball/aws-agentcore-0.9.1.tgz |
Add VercelAI as a new framework option alongside Strands, LangChain, GoogleADK, and OpenAIAgents. Supports all 4 model providers (Bedrock, Anthropic, OpenAI, Gemini) with HTTP protocol, both CodeZip and Container deploy modes. Includes template assets (main.ts, model/load.ts with per-provider Handlebars conditionals, package.json, tsconfig.json), VercelAIRenderer, renderer factory wiring, TUI wizard option, and validation gate updates. Confidence: high Scope-risk: narrow
…ials The Vercel AI template had outdated dependency versions (ai@^4.3.0) incompatible with bedrock-agentcore@0.2.2 which requires ai@>=6.0.0. The Bedrock model ID was invalid, and the provider lacked credential chain support needed for deployed AgentCore Runtime environments. Constraint: @ai-sdk/amazon-bedrock does not use AWS SDK default credential chain Rejected: Explicit env var credentials | not available in AgentCore Runtime container Confidence: high Scope-risk: narrow
When both AWS_ACCESS_KEY_ID and AWS_PROFILE are set, the SDK credential chain inside the container prefers AWS_PROFILE. But the mounted ~/.aws files have 600 permissions owned by the host user, so the container's bedrock_agentcore user cannot read them — falling back to EC2 instance metadata which uses the wrong account. Now omits AWS_PROFILE from the container env when explicit credentials are available, so the credential chain finds env var creds first. Constraint: Container user uid differs from host user uid Rejected: chmod the mounted credentials | security risk, read-only mount Confidence: high Scope-risk: moderate
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.
Description
Fixes several issues with TypeScript agent support in the CLI:
text/event-streamin the Accept header, breaking SSE streaming for HTTP agents.session.tscapability file from TypeScript templates.Related Issue
Closes #
Documentation PR
N/A
Type of Change
Testing
How have you tested the change?
npm run test:unitandnpm run test:integnpm run typechecknpm run lintsrc/assets/, I rannpm run test:update-snapshotsand committed the updated snapshotsChecklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
terms of your choice.