cdk-local 0.134.1 → 0.136.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18532,6 +18532,47 @@ async function pingProbe(host, port, timeoutMs) {
18532
18532
  }
18533
18533
  }
18534
18534
  /**
18535
+ * Wait until the container's HTTP server on `host:port` answers a probe `POST`
18536
+ * at `path` with ANY HTTP status, or throw after `timeoutMs`. This is the
18537
+ * readiness gate for the MCP / A2A warm serve (`cdkl start-agentcore`), which —
18538
+ * unlike the HTTP / AGUI protocol — have no `GET /ping`: an HTTP response (even
18539
+ * a 4xx for the probe's empty body) proves the app's HTTP server is bound and
18540
+ * routing the protocol path, so the warm serve can advertise its endpoint
18541
+ * without racing container boot. Only transient connect failures (the
18542
+ * container still coming up) are retried; the probe does NOT interpret the
18543
+ * protocol — the real client drives the MCP handshake / A2A JSON-RPC through
18544
+ * the serve.
18545
+ *
18546
+ * A TCP-only probe would be too early (Docker's port forwarder accepts the
18547
+ * connection before the agent's HTTP server binds); an HTTP response is the
18548
+ * honest "the app is up" signal.
18549
+ */
18550
+ async function waitForAgentCoreHttpReady(host, port, path, timeoutMs = 3e4) {
18551
+ const deadline = Date.now() + timeoutMs;
18552
+ let lastDetail = "";
18553
+ while (Date.now() < deadline) {
18554
+ const controller = new AbortController();
18555
+ const timer = setTimeout(() => controller.abort(), 1e3);
18556
+ try {
18557
+ await (await fetch(`http://${host}:${port}${path}`, {
18558
+ method: "POST",
18559
+ headers: { "content-type": "application/json" },
18560
+ body: "{}",
18561
+ signal: controller.signal
18562
+ })).text().catch(() => void 0);
18563
+ return;
18564
+ } catch (err) {
18565
+ if (!isTransientNetworkError$2(err)) throw err;
18566
+ lastDetail = err instanceof Error ? err.message : String(err);
18567
+ } finally {
18568
+ clearTimeout(timer);
18569
+ }
18570
+ await setTimeout$1(150);
18571
+ }
18572
+ const tail = lastDetail ? `: ${lastDetail}` : "";
18573
+ throw new Error(`AgentCore agent did not become ready on ${host}:${port} within ${timeoutMs}ms${tail}. The container may have exited early or may not serve POST ${path} — check 'docker logs' output.`);
18574
+ }
18575
+ /**
18535
18576
  * `fetch()` failures during container boot manifest as a generic
18536
18577
  * `TypeError: fetch failed` whose `.cause` carries the underlying Node
18537
18578
  * `ECONNRESET` / `ECONNREFUSED` / `UND_ERR_SOCKET`. Treat all of those —
@@ -30916,17 +30957,19 @@ function decodeBrowserFrame(data, isBinary) {
30916
30957
  return (Buffer.isBuffer(data) ? data : Array.isArray(data) ? Buffer.concat(data) : Buffer.from(data)).toString("utf-8");
30917
30958
  }
30918
30959
  /**
30919
- * Start the bridge server. Resolves once it is listening; the returned handle
30920
- * carries the connectable `url` and a `close()` that tears down the server and
30921
- * every live bridged connection.
30960
+ * Attach the AgentCore `/ws` bridge to an EXISTING `http.Server`: registers a
30961
+ * `WebSocketServer` on `config.path` and, for each inbound (header-less)
30962
+ * client, opens a container `/ws` leg with the session-id / Authorization
30963
+ * headers injected (via {@link bridgeAgentCoreWs}), piping frames both ways.
30964
+ *
30965
+ * Shared by {@link startAgentCoreWsBridge} (a standalone `/ws`-only bridge) and
30966
+ * the HTTP serve (`startAgentCoreHttpServer`, issue #454), which serves the
30967
+ * same warm container's `POST /invocations` + `GET /ping` on the SAME port and
30968
+ * delegates the `/ws` upgrade here. The caller owns `httpServer.listen()` and
30969
+ * the host port; this helper only owns the WebSocket layer.
30922
30970
  */
30923
- function startAgentCoreWsBridge(config) {
30924
- const host = config.host ?? "127.0.0.1";
30971
+ function attachAgentCoreWsBridge(httpServer, config) {
30925
30972
  const path = config.path ?? DEFAULT_PATH;
30926
- const httpServer = createServer$1((_req, res) => {
30927
- res.writeHead(426, { "Content-Type": "text/plain" });
30928
- res.end("Upgrade required: connect over WebSocket.\n");
30929
- });
30930
30973
  const wss = new WebSocketServer({
30931
30974
  server: httpServer,
30932
30975
  path
@@ -30968,6 +31011,27 @@ function startAgentCoreWsBridge(config) {
30968
31011
  handle.close();
30969
31012
  });
30970
31013
  });
31014
+ return {
31015
+ path,
31016
+ close: () => new Promise((res) => {
31017
+ for (const closeLeg of liveCloses) closeLeg();
31018
+ liveCloses.clear();
31019
+ wss.close(() => res());
31020
+ })
31021
+ };
31022
+ }
31023
+ /**
31024
+ * Start a standalone `/ws`-only bridge server. Resolves once it is listening;
31025
+ * the returned handle carries the connectable `url` and a `close()` that tears
31026
+ * down the server and every live bridged connection.
31027
+ */
31028
+ function startAgentCoreWsBridge(config) {
31029
+ const host = config.host ?? "127.0.0.1";
31030
+ const httpServer = createServer$1((_req, res) => {
31031
+ res.writeHead(426, { "Content-Type": "text/plain" });
31032
+ res.end("Upgrade required: connect over WebSocket.\n");
31033
+ });
31034
+ const attached = attachAgentCoreWsBridge(httpServer, config);
30971
31035
  return new Promise((resolve, reject) => {
30972
31036
  httpServer.once("error", reject);
30973
31037
  httpServer.listen(config.port ?? 0, host, () => {
@@ -30975,18 +31039,114 @@ function startAgentCoreWsBridge(config) {
30975
31039
  httpServer.on("error", (err) => getLogger().debug(`agentcore-ws bridge server error: ${err.message}`));
30976
31040
  const port = httpServer.address().port;
30977
31041
  resolve({
30978
- url: `ws://${host}:${port}${path}`,
31042
+ url: `ws://${host}:${port}${attached.path}`,
30979
31043
  port,
30980
31044
  close: () => new Promise((res) => {
30981
- for (const closeLeg of liveCloses) closeLeg();
30982
- liveCloses.clear();
30983
- wss.close(() => httpServer.close(() => res()));
31045
+ attached.close().then(() => httpServer.close(() => res()));
30984
31046
  })
30985
31047
  });
30986
31048
  });
30987
31049
  });
30988
31050
  }
30989
31051
 
31052
+ //#endregion
31053
+ //#region src/local/agentcore-http-server.ts
31054
+ /** Default routing table — the HTTP / AGUI contract (POST /invocations + GET /ping). */
31055
+ const DEFAULT_ROUTES = [{
31056
+ method: "POST",
31057
+ path: "/invocations"
31058
+ }, {
31059
+ method: "GET",
31060
+ path: "/ping"
31061
+ }];
31062
+ /**
31063
+ * Proxy one inbound HTTP request to the warm container, injecting the
31064
+ * session-id + Authorization (+ any extra) headers, and stream the response
31065
+ * back. Used for both `GET /ping` and `POST /invocations`; piping the response
31066
+ * preserves an SSE (`text/event-stream`) stream.
31067
+ */
31068
+ function proxyToContainer(clientReq, clientRes, config, upstreamPath) {
31069
+ const headers = { ...clientReq.headers };
31070
+ delete headers["host"];
31071
+ headers[AGENTCORE_SESSION_ID_HEADER] = config.sessionId ?? randomUUID();
31072
+ if (config.authorization) headers["authorization"] = config.authorization;
31073
+ const upstream = request({
31074
+ host: config.containerHost,
31075
+ port: config.containerPort,
31076
+ path: upstreamPath,
31077
+ method: clientReq.method,
31078
+ headers
31079
+ }, (upRes) => {
31080
+ clientRes.writeHead(upRes.statusCode ?? 502, upRes.headers);
31081
+ upRes.on("error", () => clientRes.destroy());
31082
+ upRes.pipe(clientRes);
31083
+ });
31084
+ upstream.on("error", (err) => {
31085
+ getLogger().debug(`agentcore http serve upstream error: ${err.message}`);
31086
+ if (!clientRes.headersSent) clientRes.writeHead(502, { "content-type": "application/json" });
31087
+ clientRes.end(JSON.stringify({ error: `upstream error: ${err.message}` }));
31088
+ });
31089
+ clientReq.on("error", (err) => {
31090
+ getLogger().debug(`agentcore http serve client error: ${err.message}`);
31091
+ upstream.destroy();
31092
+ });
31093
+ clientReq.pipe(upstream);
31094
+ }
31095
+ /**
31096
+ * Start the HTTP serve. Resolves once it is listening; the returned handle
31097
+ * carries the connectable `httpUrl` / `wsUrl` and a `close()` that tears down
31098
+ * the server + the `/ws` bridge + every live bridged connection.
31099
+ */
31100
+ function startAgentCoreHttpServer(config) {
31101
+ const host = config.host ?? "127.0.0.1";
31102
+ const routes = config.routes ?? DEFAULT_ROUTES;
31103
+ const attachWs = config.attachWs ?? true;
31104
+ const notFoundHint = buildNotFoundHint(routes, attachWs);
31105
+ const httpServer = createServer$1((req, res) => {
31106
+ const path = (req.url ?? "/").split("?")[0];
31107
+ const match = routes.find((r) => r.method === req.method && r.path === path);
31108
+ if (match) return proxyToContainer(req, res, config, match.path);
31109
+ res.writeHead(404, { "content-type": "application/json" });
31110
+ res.end(JSON.stringify({
31111
+ error: "not found",
31112
+ hint: notFoundHint
31113
+ }));
31114
+ });
31115
+ const bridge = attachWs ? attachAgentCoreWsBridge(httpServer, {
31116
+ containerHost: config.containerHost,
31117
+ containerPort: config.containerPort,
31118
+ ...config.sessionId && { sessionId: config.sessionId },
31119
+ ...config.authorization && { authorization: config.authorization }
31120
+ }) : void 0;
31121
+ return new Promise((resolve, reject) => {
31122
+ httpServer.once("error", reject);
31123
+ httpServer.listen(config.port ?? 0, host, () => {
31124
+ httpServer.removeListener("error", reject);
31125
+ httpServer.on("error", (err) => getLogger().debug(`agentcore http serve server error: ${err.message}`));
31126
+ const port = httpServer.address().port;
31127
+ resolve({
31128
+ httpUrl: `http://${host}:${port}`,
31129
+ ...bridge && { wsUrl: `ws://${host}:${port}${bridge.path}` },
31130
+ port,
31131
+ close: () => new Promise((res) => {
31132
+ if (bridge) bridge.close().then(() => httpServer.close(() => res()));
31133
+ else httpServer.close(() => res());
31134
+ })
31135
+ });
31136
+ });
31137
+ });
31138
+ }
31139
+ /**
31140
+ * Build the 404 hint from the served routes, appending the `/ws` pointer when
31141
+ * the WebSocket bridge is attached. e.g. HTTP / AGUI ->
31142
+ * `POST /invocations or GET /ping (WebSocket: connect to /ws)`; MCP ->
31143
+ * `POST /mcp`.
31144
+ */
31145
+ function buildNotFoundHint(routes, attachWs) {
31146
+ const base = routes.map((r) => `${r.method} ${r.path}`).join(" or ");
31147
+ return attachWs ? `${base} (WebSocket: connect to /ws)` : base;
31148
+ }
31149
+
30990
31150
  //#endregion
30991
31151
  //#region src/cli/commands/local-start-agentcore.ts
30992
31152
  /**
@@ -30998,38 +31158,73 @@ function parsePort(raw) {
30998
31158
  return n;
30999
31159
  }
31000
31160
  /**
31001
- * Reject MCP / A2A runtimes: the `/ws` WebSocket endpoint this command serves
31002
- * exists only on the HTTP / AGUI protocols. MCP (`POST /mcp`) and A2A
31003
- * (`POST /`) are single-shot request/response contracts with no bidirectional
31004
- * socket. Exported so a unit test can drive the gate without the Docker
31005
- * pipeline.
31161
+ * Map a resolved runtime's protocol to its warm-serve plan. All four protocols
31162
+ * are served (issue #454): HTTP / AGUI on 8080 (`POST /invocations` + `GET
31163
+ * /ping` + the `/ws` bridge), MCP on 8000 (`POST /mcp`), A2A on 9000
31164
+ * (`POST /`). MCP / A2A are pure request/response pass-through with no `/ws`.
31006
31165
  */
31007
- function assertAgentCoreWsServable(resolved) {
31008
- if (resolved.protocol === "MCP" || resolved.protocol === "A2A") throw new CdkLocalError(`${getEmbedConfig().cliName} start-agentcore serves the HTTP / AGUI /ws WebSocket endpoint, but '${resolved.logicalId}' is a ${resolved.protocol} runtime, which has no /ws. Use \`${getEmbedConfig().cliName} invoke-agentcore\` for ${resolved.protocol} runtimes.`, "LOCAL_START_AGENTCORE_PROTOCOL_UNSUPPORTED");
31166
+ function resolveAgentCoreServePlan(protocol) {
31167
+ if (protocol === "MCP") return {
31168
+ containerPort: MCP_CONTAINER_PORT,
31169
+ containerPortLabel: `${MCP_CONTAINER_PORT}${MCP_PATH}`,
31170
+ routes: [{
31171
+ method: "POST",
31172
+ path: MCP_PATH
31173
+ }],
31174
+ attachWs: false,
31175
+ readyPath: MCP_PATH
31176
+ };
31177
+ if (protocol === "A2A") return {
31178
+ containerPort: A2A_CONTAINER_PORT,
31179
+ containerPortLabel: `${A2A_CONTAINER_PORT}${"/"}`,
31180
+ routes: [{
31181
+ method: "POST",
31182
+ path: "/"
31183
+ }],
31184
+ attachWs: false,
31185
+ readyPath: "/"
31186
+ };
31187
+ return {
31188
+ containerPort: void 0,
31189
+ containerPortLabel: "8080",
31190
+ routes: [{
31191
+ method: "POST",
31192
+ path: "/invocations"
31193
+ }, {
31194
+ method: "GET",
31195
+ path: "/ping"
31196
+ }],
31197
+ attachWs: true,
31198
+ readyPath: void 0
31199
+ };
31009
31200
  }
31010
31201
  /**
31011
31202
  * `cdkl start-agentcore <target>` — boot a Bedrock AgentCore Runtime container
31012
- * locally and serve its bidirectional `/ws` WebSocket endpoint behind a
31013
- * long-running host bridge, so a browser (or any WebSocket client) can hold an
31014
- * interactive multi-frame session against it.
31015
- *
31016
- * Why a bridge rather than the published container port directly: the
31017
- * AgentCore `/ws` upgrade requires the session-id (and, under a
31018
- * `customJwtAuthorizer`, `Authorization`) header, which a browser `WebSocket`
31019
- * cannot set. The bridge accepts a header-less client and injects those
31020
- * headers on the container leg. HTTP / AGUI protocols only — MCP / A2A
31021
- * runtimes have no `/ws`.
31203
+ * locally ONCE, keep it warm, and serve its native contract on one host port
31204
+ * until SIGINT / SIGTERM, so a client can hit the agent repeatedly against the
31205
+ * SAME warm container (issue #454).
31206
+ *
31207
+ * All four protocols are served (the proxy is protocol-agnostic; only the
31208
+ * routing + readiness differ per {@link resolveAgentCoreServePlan}):
31209
+ * - HTTP / AGUI (8080): `POST /invocations` + `GET /ping`, plus the
31210
+ * bidirectional `/ws` endpoint behind a host bridge. The `/ws` upgrade
31211
+ * requires the session-id (and, under a `customJwtAuthorizer`,
31212
+ * `Authorization`) header a browser `WebSocket` cannot set, so the bridge
31213
+ * accepts a header-less client and injects those headers on the container
31214
+ * leg.
31215
+ * - MCP (8000): `POST /mcp`. A2A (9000): `POST /`. No `/ws` — pure
31216
+ * request/response pass-through (the client drives the handshake).
31022
31217
  *
31023
31218
  * The container is booted once via the SAME image / env / auth resolution as
31024
31219
  * `cdkl invoke-agentcore`; the process then blocks until SIGINT / SIGTERM,
31025
- * tearing down the bridge and the container.
31220
+ * tearing down the serve and the container.
31026
31221
  */
31027
31222
  async function localStartAgentCoreCommand(target, options, extraStateProviders) {
31028
31223
  const logger = getLogger();
31029
31224
  if (options.verbose) logger.setLevel("debug");
31030
31225
  let containerId;
31031
31226
  let stopLogs;
31032
- let bridge;
31227
+ let server;
31033
31228
  let profileCredsFile;
31034
31229
  let stateProvider;
31035
31230
  let shuttingDown = false;
@@ -31037,10 +31232,10 @@ async function localStartAgentCoreCommand(target, options, extraStateProviders)
31037
31232
  const teardown = async () => {
31038
31233
  if (tornDown) return;
31039
31234
  tornDown = true;
31040
- if (bridge) try {
31041
- await bridge.close();
31235
+ if (server) try {
31236
+ await server.close();
31042
31237
  } catch (err) {
31043
- logger.debug(`bridge close failed: ${err instanceof Error ? err.message : String(err)}`);
31238
+ logger.debug(`server close failed: ${err instanceof Error ? err.message : String(err)}`);
31044
31239
  }
31045
31240
  if (stopLogs) try {
31046
31241
  stopLogs();
@@ -31094,7 +31289,7 @@ async function localStartAgentCoreCommand(target, options, extraStateProviders)
31094
31289
  };
31095
31290
  const resolved = resolveAgentCoreTarget(resolvedTarget, stacks, imageContext);
31096
31291
  logger.info(`Target: ${resolved.stack.stackName}/${resolved.logicalId} (${resolved.protocol})`);
31097
- assertAgentCoreWsServable(resolved);
31292
+ const plan = resolveAgentCoreServePlan(resolved.protocol);
31098
31293
  const authorization = await resolveInboundAuthorization(resolved, options);
31099
31294
  await resolveFromS3BucketIntrinsic(resolved, stateProvider, loadedState, imageContext);
31100
31295
  const image = await resolveAgentCoreImage(resolved, options, loadedState, stateProvider);
@@ -31102,7 +31297,7 @@ async function localStartAgentCoreCommand(target, options, extraStateProviders)
31102
31297
  const containerHostPort = await pickFreePort();
31103
31298
  const containerHost = options.containerHost;
31104
31299
  const containerName = `${getEmbedConfig().resourceNamePrefix}-agentcore-${process.pid}-${Math.random().toString(36).slice(2, 8)}`;
31105
- logger.info(`Starting agent container (image=${image}, port=${containerHostPort} -> 8080)...`);
31300
+ logger.info(`Starting agent container (image=${image}, port=${containerHostPort} -> ${plan.containerPortLabel})...`);
31106
31301
  containerId = await runDetached({
31107
31302
  image,
31108
31303
  mounts: [],
@@ -31112,6 +31307,7 @@ async function localStartAgentCoreCommand(target, options, extraStateProviders)
31112
31307
  host: containerHost,
31113
31308
  platform: options.platform,
31114
31309
  name: containerName,
31310
+ ...plan.containerPort !== void 0 && { containerPort: plan.containerPort },
31115
31311
  ...sensitiveEnvKeys.size > 0 && { sensitiveEnvKeys }
31116
31312
  });
31117
31313
  stopLogs = streamLogs(containerId);
@@ -31125,12 +31321,15 @@ async function localStartAgentCoreCommand(target, options, extraStateProviders)
31125
31321
  process.on("SIGINT", () => void shutdown("SIGINT", 130));
31126
31322
  process.on("SIGTERM", () => void shutdown("SIGTERM", 0));
31127
31323
  try {
31128
- await waitForAgentCorePing(containerHost, containerHostPort, options.timeout);
31129
- bridge = await startAgentCoreWsBridge({
31324
+ if (plan.readyPath === void 0) await waitForAgentCorePing(containerHost, containerHostPort, options.timeout);
31325
+ else await waitForAgentCoreHttpReady(containerHost, containerHostPort, plan.readyPath, options.timeout);
31326
+ server = await startAgentCoreHttpServer({
31130
31327
  containerHost,
31131
31328
  containerPort: containerHostPort,
31132
31329
  host: options.host,
31133
31330
  port: options.port,
31331
+ routes: plan.routes,
31332
+ attachWs: plan.attachWs,
31134
31333
  ...authorization && { authorization },
31135
31334
  ...options.sessionId && { sessionId: options.sessionId }
31136
31335
  });
@@ -31138,20 +31337,30 @@ async function localStartAgentCoreCommand(target, options, extraStateProviders)
31138
31337
  await teardown();
31139
31338
  throw err;
31140
31339
  }
31141
- logger.info(`Server listening on ${bridge.url} (${resolved.logicalId} (AgentCore WebSocket))`);
31340
+ if (server.wsUrl) {
31341
+ logger.info(`Server listening on ${server.wsUrl} (${resolved.logicalId} (AgentCore WebSocket))`);
31342
+ logger.info(`HTTP contract served on ${server.httpUrl} — POST ${server.httpUrl}/invocations, GET ${server.httpUrl}/ping`);
31343
+ } else {
31344
+ const contractPath = plan.routes[0]?.path ?? "/";
31345
+ const contractUrl = `${server.httpUrl}${contractPath}`;
31346
+ logger.info(`Server listening on ${server.httpUrl} (${resolved.logicalId})`);
31347
+ logger.info(`${resolved.protocol} contract served on ${contractUrl} — POST ${contractUrl}`);
31348
+ }
31142
31349
  logger.info("Press ^C to shut down.");
31143
31350
  await new Promise(() => void 0);
31144
31351
  }
31145
31352
  /**
31146
- * `cdkl start-agentcore <target>` — long-running serve for a Bedrock AgentCore
31147
- * Runtime's `/ws` WebSocket endpoint, fronted by a host bridge that injects the
31148
- * session-id / Authorization upgrade headers a browser `WebSocket` cannot set.
31149
- * The serve counterpart of the single-shot `cdkl invoke-agentcore`; the studio
31353
+ * `cdkl start-agentcore <target>` — long-running warm serve for a Bedrock
31354
+ * AgentCore Runtime. Boots the container once and serves its native contract on
31355
+ * one host port: HTTP / AGUI get `POST /invocations` + `GET /ping` plus the
31356
+ * `/ws` bridge (which injects the session-id / Authorization upgrade headers a
31357
+ * browser `WebSocket` cannot set), MCP gets `POST /mcp`, A2A gets `POST /`. The
31358
+ * serve counterpart of the single-shot `cdkl invoke-agentcore`; the studio
31150
31359
  * `agentcore-ws` serve kind spawns this command.
31151
31360
  */
31152
31361
  function createLocalStartAgentCoreCommand(opts = {}) {
31153
31362
  setEmbedConfig(opts.embedConfig);
31154
- const cmd = new Command("start-agentcore").description("Serve a Bedrock AgentCore Runtime's bidirectional /ws WebSocket endpoint locally for an interactive multi-frame session. Boots the AWS::BedrockAgentCore::Runtime container (same image / env / credential resolution as invoke-agentcore), then runs a host WebSocket bridge that injects the AgentCore session-id (and Authorization under a customJwtAuthorizer) on the container upgrade so a header-less client (e.g. a browser) can connect. HTTP / AGUI protocols only (MCP / A2A runtimes have no /ws). Target accepts a CDK display path (MyStack/MyAgent) or stack-qualified logical ID; single-stack apps may omit the prefix. Omit <target> in a TTY to pick from a list. Runs until ^C.").argument("[target]", "CDK display path or stack-qualified logical ID of the AgentCore Runtime to serve (omit to pick interactively in a TTY)").action(withErrorHandling(async (target, options) => {
31363
+ const cmd = new Command("start-agentcore").description("Serve a Bedrock AgentCore Runtime's contract locally against a warm container. Boots the AWS::BedrockAgentCore::Runtime container ONCE (same image / env / credential resolution as invoke-agentcore) and keeps it warm, so a client can hit it repeatedly. HTTP / AGUI runtimes serve POST /invocations + GET /ping plus the bidirectional /ws endpoint behind a host bridge (injects the AgentCore session-id, and Authorization under a customJwtAuthorizer, so a header-less client like a browser can connect); MCP runtimes serve POST /mcp, A2A POST /. Target accepts a CDK display path (MyStack/MyAgent) or stack-qualified logical ID; single-stack apps may omit the prefix. Omit <target> in a TTY to pick from a list. Runs until ^C.").argument("[target]", "CDK display path or stack-qualified logical ID of the AgentCore Runtime to serve (omit to pick interactively in a TTY)").action(withErrorHandling(async (target, options) => {
31155
31364
  await localStartAgentCoreCommand(target, options, opts.extraStateProviders);
31156
31365
  }));
31157
31366
  addStartAgentCoreSpecificOptions(cmd);
@@ -31171,7 +31380,7 @@ function createLocalStartAgentCoreCommand(opts = {}) {
31171
31380
  * `.addOption(...)` blocks. Chainable: returns `cmd`.
31172
31381
  */
31173
31382
  function addStartAgentCoreSpecificOptions(cmd) {
31174
- return cmd.addOption(new Option("--port <n>", "Bridge-server bind port the client (browser) connects to. Default 0 (OS-assigned).").default(0).argParser(parsePort)).addOption(new Option("--host <ip>", "Bridge-server bind host. Default 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--session-id <id>", "Pin one AgentCore runtime session id header value for every connection (default: a fresh random UUID per connection, so each client is its own session).")).addOption(new Option("--bearer-token <jwt>", "Bearer JWT to present when the runtime declares a customJwtAuthorizer. Verified against the runtime's OIDC discovery URL before the container starts, then injected as Authorization: Bearer <jwt> on the container /ws upgrade for every bridged connection.")).addOption(new Option("--no-verify-auth", "Skip inbound JWT verification even when the runtime declares a customJwtAuthorizer (local-dev escape hatch). A --bearer-token, if given, is still forwarded.")).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}, \"Parameters\": {...}})")).addOption(new Option("--platform <platform>", "docker --platform for the agent container (linux/amd64 or linux/arm64). Defaults to linux/arm64 because the cloud AgentCore Runtime requires arm64.").choices(["linux/amd64", "linux/arm64"]).default("linux/arm64")).addOption(new Option("--no-pull", "Skip docker pull (use cached image) — no-op for the local-build path")).addOption(new Option("--no-build", "Skip docker build on the local-asset path (use the previously-built tag). No-op for the ECR / registry pull paths.")).addOption(new Option("--container-host <host>", "Host IP used to bind the agent container port. Must be a numeric IP. Defaults to 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--timeout <ms>", "Maximum time in milliseconds to wait for the container to become ready (the GET /ping readiness deadline). Default 120000.").default(12e4).argParser(parseTimeoutMs)).addOption(new Option("--assume-role [arn]", "Assume the runtime's execution role and forward STS-issued temp credentials to the container. (1) `--assume-role <arn>` assumes the explicit ARN; (2) `--assume-role` (bare) uses the runtime's literal RoleArn; (3) `--no-assume-role` opts out. Off by default.")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack and substitute Ref / Fn::ImportValue in env vars / image URIs with the deployed physical IDs / exports. Bare form uses the resolved stack name.")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region."));
31383
+ return cmd.addOption(new Option("--port <n>", "Serve bind port the client connects to (HTTP contract + /ws on the same port). Default 0 (OS-assigned).").default(0).argParser(parsePort)).addOption(new Option("--host <ip>", "Serve bind host. Default 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--session-id <id>", "Pin one AgentCore runtime session id header value for every forwarded request / /ws connection (default: a fresh random UUID each, so each is its own session).")).addOption(new Option("--bearer-token <jwt>", "Bearer JWT to present when the runtime declares a customJwtAuthorizer. Verified against the runtime's OIDC discovery URL before the container starts, then injected as Authorization: Bearer <jwt> on every forwarded request and the container /ws upgrade.")).addOption(new Option("--no-verify-auth", "Skip inbound JWT verification even when the runtime declares a customJwtAuthorizer (local-dev escape hatch). A --bearer-token, if given, is still forwarded.")).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}, \"Parameters\": {...}})")).addOption(new Option("--platform <platform>", "docker --platform for the agent container (linux/amd64 or linux/arm64). Defaults to linux/arm64 because the cloud AgentCore Runtime requires arm64.").choices(["linux/amd64", "linux/arm64"]).default("linux/arm64")).addOption(new Option("--no-pull", "Skip docker pull (use cached image) — no-op for the local-build path")).addOption(new Option("--no-build", "Skip docker build on the local-asset path (use the previously-built tag). No-op for the ECR / registry pull paths.")).addOption(new Option("--container-host <host>", "Host IP used to bind the agent container port. Must be a numeric IP. Defaults to 127.0.0.1.").default("127.0.0.1")).addOption(new Option("--timeout <ms>", "Maximum time in milliseconds to wait for the container to become ready (the GET /ping readiness deadline). Default 120000.").default(12e4).argParser(parseTimeoutMs)).addOption(new Option("--assume-role [arn]", "Assume the runtime's execution role and forward STS-issued temp credentials to the container. (1) `--assume-role <arn>` assumes the explicit ARN; (2) `--assume-role` (bare) uses the runtime's literal RoleArn; (3) `--no-assume-role` opts out. Off by default.")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack and substitute Ref / Fn::ImportValue in env vars / image URIs with the deployed physical IDs / exports. Bare form uses the resolved stack name.")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region."));
31175
31384
  }
31176
31385
 
31177
31386
  //#endregion
@@ -36723,5 +36932,5 @@ function addStudioSpecificOptions(cmd) {
36723
36932
  }
36724
36933
 
36725
36934
  //#endregion
36726
- export { CLOUDFRONT_DISTRIBUTION_TYPE as $, computeRequestIdentityHash as $n, availableWebSocketApiIdentifiers as $r, getContainerNetworkIp as $t, addStartCloudFrontSpecificOptions as A, resolveApiTargetSubset as An, buildContainerImage as Ar, addImageOverrideOptions as At, classifyS3Error as B, groupRoutesByServer as Bn, createLocalStateProvider as Br, enforceImageOverrideOrphans as Bt, addListSpecificOptions as C, toCmdArgv as Cn, buildMgmtEndpointEnvUrl as Cr, createLocalStartServiceCommand as Ct, createLocalStartAgentCoreCommand as D, addStartApiSpecificOptions as Dn, buildDisconnectEvent as Dr, MAX_TASKS_SUBNET_RANGE_CAP as Dt, addStartAgentCoreSpecificOptions as E, createLocalInvokeCommand as En, buildConnectEvent as Er, createLocalRunTaskCommand as Et, idFromArn as F, materializeLayerFromArn as Fn, substituteAgainstState as Fr, resolveEcsAssumeRoleOption as Ft, serveFromStaticOrigin as G, defaultCredentialsLoader as Gn, resolveCfnStackName as Gr, describePinnedImageUri as Gt, matchBehavior as H, startApiServer as Hn, rejectExplicitCfnStackWithMultipleStacks as Hr, parseImageOverrideFlags as Ht, resolveKvsModulesForDistribution as I, resolveEnvVars$1 as In, substituteAgainstStateAsync as Ir, resolveSharedSidecarCredentials as It, applyEdgeResponseResult as J, createJwksCache as Jn, resolveSsmParameters as Jr, buildCloudMapIndex as Jt, serveLambdaUrlOrigin as K, buildCognitoJwksUrl as Kn, CfnLocalStateProvider as Kr, isLocalCdkAssetImage as Kt, createDeployedKvsDataSource as L, availableApiIdentifiers as Ln, substituteEnvVarsFromState as Lr, runEcsServiceEmulator as Lt, parseKvsFileOverrides as M, createFileWatcher as Mn, resolveRuntimeFileExtension as Mr, ecsClusterOption as Mt, parseOriginOverrides as N, attachStageContext as Nn, resolveRuntimeImage as Nr, parseMaxTasks as Nt, startAgentCoreWsBridge as O, createLocalStartApiCommand as On, buildMessageEvent as Or, addCommonEcsServiceOptions as Ot, resolveCloudFrontTarget as P, buildStageMap as Pn, EcsTaskResolutionError as Pr, parseRestartPolicy as Pt, httpHeadersToEdge as Q, buildMethodArn as Qn, listTargets as Qr, setShadowReadyTimeoutMs as Qt, resolveDeployedKvsArnByName as R, filterRoutesByApiIdentifier as Rn, substituteEnvVarsFromStateAsync as Rr, ImageOverrideError as Rt, StudioEventBus as S, resolveProfileCredentials as Si, renderCodeDockerfile as Sn, ConnectionRegistry as Sr, addStartServiceSpecificOptions as St, formatTargetListing as T, addInvokeSpecificOptions as Tn, parseConnectionsPath as Tr, addRunTaskSpecificOptions as Tt, startCloudFrontServer as U, resolveSelectionExpression as Un, resolveCfnFallbackRegion as Ur, resolveImageOverrides as Ut, createS3OriginReader as V, readMtlsMaterialsFromDisk as Vn, isCfnFlagPresent as Vr, mergeForService as Vt, resolveErrorResponseCandidates as W, resolveServiceIntegrationParameters as Wn, resolveCfnRegion as Wr, runImageOverrideBuilds as Wt, buildEdgeResponseEvent as X, verifyJwtAuthorizer as Xn, resolveSingleTarget as Xr, DEFAULT_SHADOW_READY_TIMEOUT_MS as Xt, buildEdgeRequestEvent as Y, verifyCognitoJwt as Yn, resolveWatchConfig as Yr, CloudMapRegistry as Yt, edgeHeadersToHttp as Z, verifyJwtViaDiscovery as Zn, countTargets as Zr, SOFT_RELOAD_COMPLETION_LOG_SUFFIX as Zt, filterStudioTargetGroups as _, formatStateRemedy as _i, waitForAgentCorePing as _n, tryParseStatus as _r, createLocalStartAlbCommand as _t, createLocalStudioCommand as a, discoverRoutes as ai, A2A_CONTAINER_PORT as an, buildCorsConfigByApiId as ar, pickLambdaEdgeFunctionLogicalId as at, renderStudioHtml as b, LocalInvokeBuildError as bi, buildAgentCoreCodeImage as bn, probeHostGatewaySupport as br, isApplicationLoadBalancer as bt, startStudioProxy as c, AGENTCORE_A2A_PROTOCOL as ci, MCP_CONTAINER_PORT as cn, matchPreflight as cr, compileCloudFrontFunction as ct, createStudioDispatcher as d, AGENTCORE_MCP_PROTOCOL as di, mcpInvokeOnce as dn, applyAuthorizerOverlay as dr, stripCloudFrontImport as dt, discoverWebSocketApis as ei, attachContainerLogStreamer as en, evaluateCachedLambdaPolicy as er, describeS3OriginDomain as et, filterStudioCustomResources as f, AGENTCORE_RUNTIME_TYPE as fi, parseSseForJsonRpc as fn, buildHttpApiV2Event as fr, createCloudFrontModule as ft, annotatePinnedEcsTargets as g, derivePseudoParametersFromRegion as gi, invokeAgentCore as gn, selectIntegrationResponse as gr, albStrategy as gt, annotateEcsTaskPinnedTargets as h, resolveAgentCoreTarget as hi, AGENTCORE_SESSION_ID_HEADER as hn, pickResponseTemplate as hr, addAlbSpecificOptions as ht, coerceStopRequest as i, webSocketApiMatchesIdentifier as ii, invokeAgentCoreWs as in, applyCorsResponseHeaders as ir, pickKvsLogicalIdFromArn as it, createLocalStartCloudFrontCommand as j, createAuthorizerCache as jn, resolveRuntimeCodeMountPath as jr, buildEcsImageResolutionContext$1 as jt, LocalStartCloudFrontError as k, createWatchPredicates as kn, architectureToPlatform as kr, addEcsAssumeRoleOptions as kt, relayServeRequest as l, AGENTCORE_AGUI_PROTOCOL as li, MCP_PATH as ln, matchRoute as lr, runViewerRequest as lt, annotateAlbPinnedBackingServices as m, pickAgentCoreCandidateStack as mi, signAgentCoreInvocation as mn, evaluateResponseParameters as mr, createUnboundCloudFrontModule as mt, coerceRunRequest as n, filterWebSocketApisByIdentifiers as ni, createLocalInvokeAgentCoreCommand as nn, invokeTokenAuthorizer as nr, isCloudFrontDistribution as nt, resolveServeBaseUrl as o, pickRefLogicalId as oi, A2A_PATH as on, buildCorsConfigFromCloudFrontChain as or, pickTargetFunctionLogicalId as ot, isCustomResourceLambdaTarget as p, AgentCoreResolutionError as pi, AGENTCORE_SIGV4_SERVICE as pn, buildRestV1Event as pr, createLocalFileKvsDataSource as pt, applyEdgeRequestResult as q, buildJwksUrlFromIssuer as qn, collectSsmParameterRefs as qr, listPinnedTargets as qt, coerceServeRequest as r, parseSelectionExpressionPath as ri, bridgeAgentCoreWs as rn, attachAuthorizers as rr, pickFunctionUrlLogicalIdFromOrigin as rt, createStudioServeManager as s, resolveLambdaArnIntrinsic as si, a2aInvokeOnce as sn, isFunctionUrlOacFronted as sr, resolveCloudFrontDistribution as st, addStudioSpecificOptions as t, discoverWebSocketApisOrThrow as ti, addInvokeAgentCoreSpecificOptions as tn, invokeRequestAuthorizer as tr, extractKvsAssociations as tt, reinvoke as u, AGENTCORE_HTTP_PROTOCOL as ui, MCP_PROTOCOL_VERSION as un, translateLambdaResponse as ur, runViewerResponse as ut, startStudioServer as v, substituteImagePlaceholders as vi, downloadAndExtractS3Bundle as vn, VtlEvaluationError as vr, parseLbPortOverrides as vt, createLocalListCommand as w, classifySourceChange as wn, handleConnectionsRequest as wr, serviceStrategy as wt, createStudioStore as x, buildStsClientConfig as xi, computeCodeImageTag as xn, bufferToBody as xr, resolveAlbFrontDoor as xt, toStudioTargetGroups as y, tryResolveImageFnJoin as yi, SUPPORTED_CODE_RUNTIMES as yn, HOST_GATEWAY_MIN_VERSION as yr, resolveAlbTarget as yt, resolveDeployedOriginBucket as z, filterRoutesByApiIdentifiers as zn, LocalStateSourceError as zr, buildImageOverrideTag as zt };
36727
- //# sourceMappingURL=local-studio-TaIoevIn.js.map
36935
+ export { edgeHeadersToHttp as $, verifyJwtAuthorizer as $n, resolveSingleTarget as $r, SOFT_RELOAD_COMPLETION_LOG_SUFFIX as $t, startAgentCoreWsBridge as A, addStartApiSpecificOptions as An, buildDisconnectEvent as Ar, addCommonEcsServiceOptions as At, resolveDeployedKvsArnByName as B, availableApiIdentifiers as Bn, substituteEnvVarsFromState as Br, ImageOverrideError as Bt, addListSpecificOptions as C, LocalInvokeBuildError as Ci, buildAgentCoreCodeImage as Cn, probeHostGatewaySupport as Cr, resolveAlbFrontDoor as Ct, createLocalStartAgentCoreCommand as D, classifySourceChange as Dn, handleConnectionsRequest as Dr, addRunTaskSpecificOptions as Dt, addStartAgentCoreSpecificOptions as E, toCmdArgv as En, buildMgmtEndpointEnvUrl as Er, serviceStrategy as Et, parseOriginOverrides as F, createFileWatcher as Fn, resolveRuntimeFileExtension as Fr, parseMaxTasks as Ft, startCloudFrontServer as G, startApiServer as Gn, rejectExplicitCfnStackWithMultipleStacks as Gr, resolveImageOverrides as Gt, classifyS3Error as H, filterRoutesByApiIdentifiers as Hn, LocalStateSourceError as Hr, enforceImageOverrideOrphans as Ht, resolveCloudFrontTarget as I, attachStageContext as In, resolveRuntimeImage as Ir, parseRestartPolicy as It, serveLambdaUrlOrigin as J, defaultCredentialsLoader as Jn, resolveCfnStackName as Jr, isLocalCdkAssetImage as Jt, resolveErrorResponseCandidates as K, resolveSelectionExpression as Kn, resolveCfnFallbackRegion as Kr, runImageOverrideBuilds as Kt, idFromArn as L, buildStageMap as Ln, EcsTaskResolutionError as Lr, resolveEcsAssumeRoleOption as Lt, addStartCloudFrontSpecificOptions as M, createWatchPredicates as Mn, architectureToPlatform as Mr, addImageOverrideOptions as Mt, createLocalStartCloudFrontCommand as N, resolveApiTargetSubset as Nn, buildContainerImage as Nr, buildEcsImageResolutionContext$1 as Nt, startAgentCoreHttpServer as O, addInvokeSpecificOptions as On, parseConnectionsPath as Or, createLocalRunTaskCommand as Ot, parseKvsFileOverrides as P, createAuthorizerCache as Pn, resolveRuntimeCodeMountPath as Pr, ecsClusterOption as Pt, buildEdgeResponseEvent as Q, verifyCognitoJwt as Qn, resolveWatchConfig as Qr, DEFAULT_SHADOW_READY_TIMEOUT_MS as Qt, resolveKvsModulesForDistribution as R, materializeLayerFromArn as Rn, substituteAgainstState as Rr, resolveSharedSidecarCredentials as Rt, StudioEventBus as S, tryResolveImageFnJoin as Si, SUPPORTED_CODE_RUNTIMES as Sn, HOST_GATEWAY_MIN_VERSION as Sr, isApplicationLoadBalancer as St, formatTargetListing as T, resolveProfileCredentials as Ti, renderCodeDockerfile as Tn, ConnectionRegistry as Tr, createLocalStartServiceCommand as Tt, createS3OriginReader as U, groupRoutesByServer as Un, createLocalStateProvider as Ur, mergeForService as Ut, resolveDeployedOriginBucket as V, filterRoutesByApiIdentifier as Vn, substituteEnvVarsFromStateAsync as Vr, buildImageOverrideTag as Vt, matchBehavior as W, readMtlsMaterialsFromDisk as Wn, isCfnFlagPresent as Wr, parseImageOverrideFlags as Wt, applyEdgeResponseResult as X, buildJwksUrlFromIssuer as Xn, collectSsmParameterRefs as Xr, buildCloudMapIndex as Xt, applyEdgeRequestResult as Y, buildCognitoJwksUrl as Yn, CfnLocalStateProvider as Yr, listPinnedTargets as Yt, buildEdgeRequestEvent as Z, createJwksCache as Zn, resolveSsmParameters as Zr, CloudMapRegistry as Zt, filterStudioTargetGroups as _, pickAgentCoreCandidateStack as _i, AGENTCORE_SESSION_ID_HEADER as _n, evaluateResponseParameters as _r, addAlbSpecificOptions as _t, createLocalStudioCommand as a, filterWebSocketApisByIdentifiers as ai, bridgeAgentCoreWs as an, invokeTokenAuthorizer as ar, pickFunctionUrlLogicalIdFromOrigin as at, renderStudioHtml as b, formatStateRemedy as bi, waitForAgentCorePing as bn, tryParseStatus as br, parseLbPortOverrides as bt, startStudioProxy as c, discoverRoutes as ci, A2A_PATH as cn, buildCorsConfigByApiId as cr, pickTargetFunctionLogicalId as ct, createStudioDispatcher as d, AGENTCORE_A2A_PROTOCOL as di, MCP_PATH as dn, matchPreflight as dr, runViewerRequest as dt, countTargets as ei, setShadowReadyTimeoutMs as en, verifyJwtViaDiscovery as er, httpHeadersToEdge as et, filterStudioCustomResources as f, AGENTCORE_AGUI_PROTOCOL as fi, MCP_PROTOCOL_VERSION as fn, matchRoute as fr, runViewerResponse as ft, annotatePinnedEcsTargets as g, AgentCoreResolutionError as gi, signAgentCoreInvocation as gn, buildRestV1Event as gr, createUnboundCloudFrontModule as gt, annotateEcsTaskPinnedTargets as h, AGENTCORE_RUNTIME_TYPE as hi, AGENTCORE_SIGV4_SERVICE as hn, buildHttpApiV2Event as hr, createLocalFileKvsDataSource as ht, coerceStopRequest as i, discoverWebSocketApisOrThrow as ii, createLocalInvokeAgentCoreCommand as in, invokeRequestAuthorizer as ir, isCloudFrontDistribution as it, LocalStartCloudFrontError as j, createLocalStartApiCommand as jn, buildMessageEvent as jr, addEcsAssumeRoleOptions as jt, attachAgentCoreWsBridge as k, createLocalInvokeCommand as kn, buildConnectEvent as kr, MAX_TASKS_SUBNET_RANGE_CAP as kt, relayServeRequest as l, pickRefLogicalId as li, a2aInvokeOnce as ln, buildCorsConfigFromCloudFrontChain as lr, resolveCloudFrontDistribution as lt, annotateAlbPinnedBackingServices as m, AGENTCORE_MCP_PROTOCOL as mi, parseSseForJsonRpc as mn, applyAuthorizerOverlay as mr, createCloudFrontModule as mt, coerceRunRequest as n, availableWebSocketApiIdentifiers as ni, attachContainerLogStreamer as nn, computeRequestIdentityHash as nr, describeS3OriginDomain as nt, resolveServeBaseUrl as o, parseSelectionExpressionPath as oi, invokeAgentCoreWs as on, attachAuthorizers as or, pickKvsLogicalIdFromArn as ot, isCustomResourceLambdaTarget as p, AGENTCORE_HTTP_PROTOCOL as pi, mcpInvokeOnce as pn, translateLambdaResponse as pr, stripCloudFrontImport as pt, serveFromStaticOrigin as q, resolveServiceIntegrationParameters as qn, resolveCfnRegion as qr, describePinnedImageUri as qt, coerceServeRequest as r, discoverWebSocketApis as ri, addInvokeAgentCoreSpecificOptions as rn, evaluateCachedLambdaPolicy as rr, extractKvsAssociations as rt, createStudioServeManager as s, webSocketApiMatchesIdentifier as si, A2A_CONTAINER_PORT as sn, applyCorsResponseHeaders as sr, pickLambdaEdgeFunctionLogicalId as st, addStudioSpecificOptions as t, listTargets as ti, getContainerNetworkIp as tn, buildMethodArn as tr, CLOUDFRONT_DISTRIBUTION_TYPE as tt, reinvoke as u, resolveLambdaArnIntrinsic as ui, MCP_CONTAINER_PORT as un, isFunctionUrlOacFronted as ur, compileCloudFrontFunction as ut, startStudioServer as v, resolveAgentCoreTarget as vi, invokeAgentCore as vn, pickResponseTemplate as vr, albStrategy as vt, createLocalListCommand as w, buildStsClientConfig as wi, computeCodeImageTag as wn, bufferToBody as wr, addStartServiceSpecificOptions as wt, createStudioStore as x, substituteImagePlaceholders as xi, downloadAndExtractS3Bundle as xn, VtlEvaluationError as xr, resolveAlbTarget as xt, toStudioTargetGroups as y, derivePseudoParametersFromRegion as yi, waitForAgentCoreHttpReady as yn, selectIntegrationResponse as yr, createLocalStartAlbCommand as yt, createDeployedKvsDataSource as z, resolveEnvVars$1 as zn, substituteAgainstStateAsync as zr, runEcsServiceEmulator as zt };
36936
+ //# sourceMappingURL=local-studio-BqHODjfP.js.map