cdk-local 0.69.0 → 0.71.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.
@@ -19182,6 +19182,143 @@ function addInvokeAgentCoreSpecificOptions(cmd) {
19182
19182
  return cmd.addOption(new Option("-e, --event <file>", "JSON event payload file (default: {})")).addOption(new Option("--event-stdin", "Read event JSON from stdin").default(false)).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"LogicalId\":{\"KEY\":\"VALUE\"}})")).addOption(new Option("--session-id <id>", "AgentCore runtime session id header value (default: a random UUID)")).addOption(new Option("--ws", "Stream over the HTTP-protocol agent's bidirectional /ws WebSocket endpoint (on 8080) instead of POST /invocations: send --event as the first frame and print every received frame to stdout until the agent closes. Ignored for an MCP runtime.").default(false)).addOption(new Option("--ws-interactive", "REPL mode for --ws: after the initial --event frame, read additional frames from stdin (one frame per line, trailing newline stripped) and send each as a text frame until stdin EOFs (Ctrl-D) or the agent closes. Only meaningful with --ws.").default(false)).addOption(new Option("--bearer-token <jwt>", "Bearer JWT to present when the runtime declares a customJwtAuthorizer. Verified against the runtime OIDC discovery URL (signature / issuer / expiry / audience) before the container starts, then forwarded to /invocations as Authorization: Bearer <jwt>.")).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("--sigv4", "Sign the /invocations POST with AWS SigV4 (service bedrock-agentcore) using the resolved credentials, matching the cloud default when the runtime declares no customJwtAuthorizer. Opt-in: default unsigned. Mutually exclusive with --bearer-token; ignored on a JWT-protected runtime.").default(false)).addOption(new Option("--platform <platform>", "docker --platform for the agent container (linux/amd64 or linux/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 to bind the agent port to").default("127.0.0.1")).addOption(new Option("--timeout <ms>", "Per-request timeout in milliseconds. Applied to POST /invocations, POST /mcp, and the /ws open-to-close window. Raise this for long-running agent calls that exceed the default.").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 so the agent runs with the deployed role. Three forms: (1) `--assume-role <arn>` assumes the explicit ARN; (2) `--assume-role` (bare) uses the runtime's RoleArn when it is a literal ARN; (3) `--no-assume-role` opts out. Off by default — the developer's shell credentials are forwarded unchanged.")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries. Same-account / same-region pulls do not need this flag.")).addOption(new Option("--from-cfn-stack [cfn-stack-name]", "Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in env vars with the deployed physical IDs / exports. Bare form uses the resolved stack name; pass an explicit value when the CFn stack name differs.")).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region."));
19183
19183
  }
19184
19184
 
19185
+ //#endregion
19186
+ //#region src/local/container-log-streamer.ts
19187
+ /**
19188
+ * Spawn `docker logs -f <containerId>` and pipe its stdout / stderr to
19189
+ * the host's `process.stdout` / `process.stderr`, prefixing every emitted
19190
+ * line with the caller-supplied `prefix`. Returns a stop function that
19191
+ * drains any unterminated tail line and SIGTERMs the streamer process —
19192
+ * idempotent + safe to call from a `finally` or shutdown handler.
19193
+ *
19194
+ * Used by `cdkl run-task` (per-container prefix `[<container-name>]`) and
19195
+ * by `cdkl start-service` / `cdkl start-alb` (per-replica prefix
19196
+ * `[svc=<service> r=<i> c=<container>]`) so application `console.log`
19197
+ * output inside a replica is visible in the foreground terminal without
19198
+ * having to attach `docker logs -f` in a separate shell. The prefix shape
19199
+ * is the caller's concern: this helper only cares about line-buffered
19200
+ * pass-through.
19201
+ *
19202
+ * **Auto re-attach on `docker restart`** (Issue #227 + #214 soft-reload):
19203
+ * the docker daemon terminates `docker logs -f` when the container's
19204
+ * PID 1 exits — so a `docker restart` (the soft-reload primitive) ends
19205
+ * the follow stream even though the container ID is preserved across the
19206
+ * restart. The streamer detects an unsolicited child-exit and re-spawns
19207
+ * `docker logs -f` with `--since 0s` so only NEW output (from the
19208
+ * post-restart PID-1) is forwarded; the v1 prelude is not re-emitted.
19209
+ * `stop()` flips an internal "stopping" flag so the re-attach loop sees
19210
+ * the intentional teardown and does not respawn.
19211
+ *
19212
+ * **Cap-reached warning** (Issue #227 review fix — Code #2): the
19213
+ * re-attach budget is bounded at 50 to defend against a permanently-
19214
+ * broken `docker logs -f` (the container was removed out from under
19215
+ * us). When the cap is hit, the streamer surfaces ONE warning line via
19216
+ * `process.stderr` naming the prefix + the manual recovery so a long-
19217
+ * running `--watch` session does not lose its foreground log surface
19218
+ * silently.
19219
+ *
19220
+ * **Dying-container respawn skip** (Issue #227 review fix — Code #4):
19221
+ * when the child exits unsolicited and the container's `State.Status`
19222
+ * is `exited` / `dead` / `removing`, the streamer does NOT respawn —
19223
+ * the natural-exit path is the service-runner's `cleanupEcsRun(...)`
19224
+ * call (~1s after the wait resolves), and a respawn against a
19225
+ * dying container is just a wasted `docker logs -f` process + a
19226
+ * spurious cap-reached tick. A `docker restart` (the soft-reload
19227
+ * primitive) leaves the container in `restarting` / `running`, so
19228
+ * the soft-reload re-attach path is preserved. Falls open: an
19229
+ * inspect error treats the container as still alive (best-effort —
19230
+ * the cap+stop() invariants stay correct either way).
19231
+ *
19232
+ * The streamer is best-effort. A spawn / pipe error is silently swallowed
19233
+ * (the parent's `docker wait` already surfaces the underlying container
19234
+ * failure with full context); the loud surface stays on the runner's exit
19235
+ * path.
19236
+ */
19237
+ function attachContainerLogStreamer(prefix, containerId) {
19238
+ let stopping = false;
19239
+ let current;
19240
+ let stdoutBuf = "";
19241
+ let stderrBuf = "";
19242
+ const maxReattaches = 50;
19243
+ let reattachCount = 0;
19244
+ let pendingRespawn;
19245
+ const spawnOnce = (sinceArg) => {
19246
+ const args = [
19247
+ "logs",
19248
+ "-f",
19249
+ ...sinceArg !== void 0 ? ["--since", sinceArg] : [],
19250
+ containerId
19251
+ ];
19252
+ const proc = spawn(getDockerCmd(), args, { stdio: [
19253
+ "ignore",
19254
+ "pipe",
19255
+ "pipe"
19256
+ ] });
19257
+ current = proc;
19258
+ proc.stdout?.on("data", (chunk) => {
19259
+ stdoutBuf = writePrefixedLines(prefix, stdoutBuf + chunk.toString("utf-8"), process.stdout);
19260
+ });
19261
+ proc.stderr?.on("data", (chunk) => {
19262
+ stderrBuf = writePrefixedLines(prefix, stderrBuf + chunk.toString("utf-8"), process.stderr);
19263
+ });
19264
+ proc.on("error", () => {});
19265
+ proc.on("exit", () => {
19266
+ if (stopping) return;
19267
+ if (reattachCount >= maxReattaches) {
19268
+ process.stderr.write(`${prefix}cdkl: docker logs -f re-attached ${maxReattaches} times; giving up. Run \`docker logs -f ${containerId}\` manually to keep watching.\n`);
19269
+ return;
19270
+ }
19271
+ reattachCount += 1;
19272
+ execFile(getDockerCmd(), [
19273
+ "inspect",
19274
+ "--format",
19275
+ "{{.State.Status}}",
19276
+ containerId
19277
+ ], (err, stdout) => {
19278
+ if (stopping) return;
19279
+ if (!err) {
19280
+ const status = stdout.trim().toLowerCase();
19281
+ if (status === "exited" || status === "dead" || status === "removing") return;
19282
+ }
19283
+ pendingRespawn = setTimeout(() => {
19284
+ pendingRespawn = void 0;
19285
+ if (stopping) return;
19286
+ spawnOnce("0s");
19287
+ }, 200);
19288
+ });
19289
+ });
19290
+ };
19291
+ spawnOnce(void 0);
19292
+ return () => {
19293
+ stopping = true;
19294
+ if (pendingRespawn !== void 0) {
19295
+ clearTimeout(pendingRespawn);
19296
+ pendingRespawn = void 0;
19297
+ }
19298
+ if (stdoutBuf) {
19299
+ process.stdout.write(prefix + stdoutBuf + "\n");
19300
+ stdoutBuf = "";
19301
+ }
19302
+ if (stderrBuf) {
19303
+ process.stderr.write(prefix + stderrBuf + "\n");
19304
+ stderrBuf = "";
19305
+ }
19306
+ if (current && !current.killed) current.kill("SIGTERM");
19307
+ };
19308
+ }
19309
+ /**
19310
+ * Write every complete line in `buffer` to `out`, prefixed with `prefix`.
19311
+ * Returns the trailing partial line (no `\n` yet) so the caller can
19312
+ * accumulate it with the next `data` chunk. Exported for unit tests; the
19313
+ * production callers should use {@link attachContainerLogStreamer}.
19314
+ */
19315
+ function writePrefixedLines(prefix, buffer, out) {
19316
+ const lines = buffer.split("\n");
19317
+ const remainder = lines.pop() ?? "";
19318
+ for (const line of lines) out.write(prefix + line + "\n");
19319
+ return remainder;
19320
+ }
19321
+
19185
19322
  //#endregion
19186
19323
  //#region src/local/ecs-network.ts
19187
19324
  const execFileAsync$3 = promisify(execFile);
@@ -19770,7 +19907,7 @@ async function runEcsTask(task, options, state) {
19770
19907
  id,
19771
19908
  container
19772
19909
  });
19773
- if (!options.detach) state.logStoppers.push(streamContainerLogs(container.name, id));
19910
+ if (!options.detach) state.logStoppers.push(attachContainerLogStreamer(`[${container.name}] `, id));
19774
19911
  }
19775
19912
  if (options.detach) return {
19776
19913
  exitCode: 0,
@@ -19910,42 +20047,6 @@ function sleep$1(ms) {
19910
20047
  return new Promise((res) => setTimeout(res, ms));
19911
20048
  }
19912
20049
  /**
19913
- * Stream `docker logs -f <id>` with `[<container-name>]` prefixes on
19914
- * every line. Returns a stop function for the caller's `finally`.
19915
- */
19916
- function streamContainerLogs(containerName, containerId) {
19917
- const proc = spawn(getDockerCmd(), [
19918
- "logs",
19919
- "-f",
19920
- containerId
19921
- ], { stdio: [
19922
- "ignore",
19923
- "pipe",
19924
- "pipe"
19925
- ] });
19926
- const prefix = `[${containerName}] `;
19927
- let stdoutBuf = "";
19928
- let stderrBuf = "";
19929
- proc.stdout?.on("data", (chunk) => {
19930
- stdoutBuf = writePrefixed(prefix, stdoutBuf + chunk.toString("utf-8"), process.stdout);
19931
- });
19932
- proc.stderr?.on("data", (chunk) => {
19933
- stderrBuf = writePrefixed(prefix, stderrBuf + chunk.toString("utf-8"), process.stderr);
19934
- });
19935
- proc.on("error", () => {});
19936
- return () => {
19937
- if (stdoutBuf) process.stdout.write(prefix + stdoutBuf + "\n");
19938
- if (stderrBuf) process.stderr.write(prefix + stderrBuf + "\n");
19939
- if (!proc.killed) proc.kill("SIGTERM");
19940
- };
19941
- }
19942
- function writePrefixed(prefix, buffer, out) {
19943
- const lines = buffer.split("\n");
19944
- const remainder = lines.pop() ?? "";
19945
- for (const line of lines) out.write(prefix + line + "\n");
19946
- return remainder;
19947
- }
19948
- /**
19949
20050
  * Resolve every container's `Image` to a tag the runner can pass to
19950
20051
  * `docker run`. The map is keyed by container name; entries are
19951
20052
  * populated in parallel up to the asset-manifest bound (single
@@ -20577,6 +20678,7 @@ function extractServiceProperties(stack, serviceLogicalId, resource, stacks, con
20577
20678
  const desiredCount = parseDesiredCount(props["DesiredCount"], serviceLogicalId);
20578
20679
  const healthCheckGracePeriodSeconds = parseHealthCheckGrace(props["HealthCheckGracePeriodSeconds"], serviceLogicalId);
20579
20680
  const serviceName = parseServiceName(props["ServiceName"], serviceLogicalId);
20681
+ const serviceDisplayName = deriveServiceDisplayName(props["ServiceName"], serviceLogicalId, resource.Metadata);
20580
20682
  if (!options?.suppressLoadBalancerWarning && Array.isArray(props["LoadBalancers"]) && props["LoadBalancers"].length > 0) {
20581
20683
  const { cliName } = getEmbedConfig();
20582
20684
  warnings.push(`ECS Service '${serviceLogicalId}' declares LoadBalancers, but \`${cliName} start-service\` runs the replicas only; no local listener fronts them. Reach the containers via their published ports, or run \`${cliName} start-alb <Stack>/<Alb>\` to boot the same replicas behind a local front-door that round-robins the listener rules.`);
@@ -20587,6 +20689,7 @@ function extractServiceProperties(stack, serviceLogicalId, resource, stacks, con
20587
20689
  serviceLogicalId,
20588
20690
  resource,
20589
20691
  serviceName,
20692
+ serviceDisplayName,
20590
20693
  desiredCount,
20591
20694
  healthCheckGracePeriodSeconds,
20592
20695
  task,
@@ -20741,6 +20844,50 @@ function parseServiceName(raw, serviceLogicalId) {
20741
20844
  return serviceLogicalId;
20742
20845
  }
20743
20846
  /**
20847
+ * Issue #227 review fix — derive a CLEAN display name for the per-replica
20848
+ * `[svc=<name> r=<i> c=<container>] ` log prefix. L2 constructs
20849
+ * (`FargateService`, `ApplicationLoadBalancedFargateService`) do NOT set
20850
+ * `ServiceName` explicitly, so the synthesized template's `ServiceName`
20851
+ * is absent and {@link parseServiceName} falls back to the
20852
+ * hash-suffixed logical id (e.g. `BackendApi5F9D8C32`). That ends up in
20853
+ * the foreground prefix as `[svc=BackendApi5F9D8C32 ...]` — noisy +
20854
+ * not what Issue #227's spec example showed.
20855
+ *
20856
+ * Resolution order (display ONLY — does NOT change `service.serviceName`):
20857
+ * 1. The explicit CFn `ServiceName` property, if the user set one.
20858
+ * 2. The last meaningful segment of the resource's `aws:cdk:path`
20859
+ * Metadata. For a typical L2, this is the construct id the user
20860
+ * wrote in CDK source (e.g. `AppStack/BackendApi/Service` →
20861
+ * `BackendApi`). Trailing CDK-internal segments (`/Service`,
20862
+ * `/Resource`, `/Default`) are stripped so the result matches the
20863
+ * construct id the user typed, not the per-resource CFn segment.
20864
+ * 3. The `serviceLogicalId` as today's fallback when neither is
20865
+ * available (synthetic / hand-rolled CFn).
20866
+ *
20867
+ * Pure helper — keep narrowly scoped to the log-prefix use case so
20868
+ * other call sites that rely on `service.serviceName` for awsvpc /
20869
+ * Cloud Map / discovery semantics keep their existing fallback
20870
+ * behavior.
20871
+ */
20872
+ function deriveServiceDisplayName(rawServiceName, serviceLogicalId, metadata) {
20873
+ if (typeof rawServiceName === "string" && rawServiceName.length > 0) return rawServiceName;
20874
+ const cdkPath = typeof metadata?.["aws:cdk:path"] === "string" ? metadata["aws:cdk:path"] : "";
20875
+ if (cdkPath.length > 0) {
20876
+ const segments = cdkPath.split("/");
20877
+ while (segments.length > 1) {
20878
+ const tail = segments[segments.length - 1];
20879
+ if (tail === "Service" || tail === "Resource" || tail === "Default") {
20880
+ segments.pop();
20881
+ continue;
20882
+ }
20883
+ break;
20884
+ }
20885
+ const tail = segments[segments.length - 1];
20886
+ if (typeof tail === "string" && tail.length > 0) return tail;
20887
+ }
20888
+ return serviceLogicalId;
20889
+ }
20890
+ /**
20744
20891
  * Local copy of the same `pickStack` helper used by the task resolver.
20745
20892
  * Kept in-file rather than exported from `ecs-task-resolver.ts` so future
20746
20893
  * service-specific extensions (e.g. cross-stack service-to-task refs)
@@ -20887,6 +21034,22 @@ var EcsServiceRunnerError = class EcsServiceRunnerError extends Error {
20887
21034
  Object.setPrototypeOf(this, EcsServiceRunnerError.prototype);
20888
21035
  }
20889
21036
  };
21037
+ /**
21038
+ * Phase 4 (#214) — completion-log suffix the soft-reload primitive
21039
+ * emits AFTER `Soft-reloaded replica r<i> (gen <g>): ` to confirm
21040
+ * the docker restart + TCP-ready probe + Cloud Map / front-door
21041
+ * re-publish round trip is done.
21042
+ *
21043
+ * Exported so integ fixtures + unit tests can grep against the
21044
+ * canonical text instead of hand-copying the wording — a future
21045
+ * refactor that rewords this line stays detectable via the symbol
21046
+ * import instead of silently breaking every test's regex.
21047
+ *
21048
+ * Per-repo memory (#218 / test reviewer N4): log-line text is part
21049
+ * of the public contract for `--watch` integ scripts, so it earns a
21050
+ * constant.
21051
+ */
21052
+ const SOFT_RELOAD_COMPLETION_LOG_SUFFIX = "restart + TCP-ready probe complete; Cloud Map + front-door re-published.";
20890
21053
  function createServiceRunState() {
20891
21054
  return {
20892
21055
  replicas: [],
@@ -21139,8 +21302,33 @@ async function bootReplica(service, options, instance) {
21139
21302
  };
21140
21303
  logger.info(`Booting replica ${instance.index} (${perReplicaCluster})`);
21141
21304
  await runEcsTask(service.task, perReplicaTaskOptions, instance.state);
21305
+ if (options.streamLogs !== false) for (const started of instance.state.startedContainers) {
21306
+ const prefix = `[svc=${service.serviceDisplayName} r=${instance.index} c=${started.name}] `;
21307
+ instance.state.logStoppers.push(attachContainerLogStreamer(prefix, started.id));
21308
+ }
21142
21309
  if (options.discovery) await publishReplicaToCloudMap(service, instance, options.discovery, ownerKeyPrefix);
21143
21310
  if (options.frontDoor) await publishReplicaToFrontDoor(service, instance, options.frontDoor, options.taskOptions.containerHost, ownerKeyPrefix);
21311
+ instance.lastDeployedAssetHash = pickEssentialAssetHash(service);
21312
+ }
21313
+ /**
21314
+ * Phase 4 follow-up (#218) — extract the CDK asset hash from a
21315
+ * resolved service's first essential container (with the same
21316
+ * fallback the watcher uses: first essential, else first container).
21317
+ * Returns `undefined` when the image isn't a CDK asset OR carries
21318
+ * no hash. Pure helper so the boot + rolling + soft-reload paths
21319
+ * share one source of truth for "what's running right now".
21320
+ *
21321
+ * Exported for unit tests; not part of the semver-covered public
21322
+ * surface.
21323
+ *
21324
+ * @internal
21325
+ */
21326
+ function pickEssentialAssetHash(service) {
21327
+ const essential = service.task.containers.find((c) => c.essential) ?? service.task.containers[0];
21328
+ if (!essential) return void 0;
21329
+ const image = essential.image;
21330
+ if (image?.kind !== "cdk-asset") return void 0;
21331
+ return image.assetHash;
21144
21332
  }
21145
21333
  /**
21146
21334
  * After the replica's main container is up, discover its docker
@@ -21515,6 +21703,7 @@ async function softReloadReplica(args) {
21515
21703
  }
21516
21704
  unregisterReplicaFromFrontDoor(instance, controllerOptions.frontDoor);
21517
21705
  instance.softReloadInProgress = true;
21706
+ instance.softReloadGeneration = (instance.softReloadGeneration ?? 0) + 1;
21518
21707
  try {
21519
21708
  logger.info(`Soft-reloading replica r${instance.index} (gen ${instance.generation}): docker cp ${sourceDirToCopy} -> ${targets.length} essential container(s); restart.`);
21520
21709
  for (const target of targets) {
@@ -21545,7 +21734,8 @@ async function softReloadReplica(args) {
21545
21734
  const ownerKeyPrefix = `${newService.serviceLogicalId}:r${instance.index}${ownerKeyGenSuffix}`;
21546
21735
  if (controllerOptions.discovery) await publishReplicaToCloudMap(newService, instance, controllerOptions.discovery, ownerKeyPrefix);
21547
21736
  if (controllerOptions.frontDoor) await publishReplicaToFrontDoor(newService, instance, controllerOptions.frontDoor, controllerOptions.taskOptions.containerHost, ownerKeyPrefix);
21548
- logger.info(`Soft-reloaded replica r${instance.index} (gen ${instance.generation}): restart + TCP-ready probe complete; Cloud Map + front-door re-published.`);
21737
+ instance.lastDeployedAssetHash = pickEssentialAssetHash(newService);
21738
+ logger.info(`Soft-reloaded replica r${instance.index} (gen ${instance.generation}): ${SOFT_RELOAD_COMPLETION_LOG_SUFFIX}`);
21549
21739
  } finally {
21550
21740
  instance.softReloadInProgress = false;
21551
21741
  }
@@ -21740,6 +21930,7 @@ async function watchReplica(service, options, instance, runState) {
21740
21930
  await sleep(500);
21741
21931
  continue;
21742
21932
  }
21933
+ const softReloadGenBeforeWait = instance.softReloadGeneration ?? 0;
21743
21934
  let exitCode;
21744
21935
  try {
21745
21936
  exitCode = await waitForExitImpl(essentialId);
@@ -21748,7 +21939,8 @@ async function watchReplica(service, options, instance, runState) {
21748
21939
  exitCode = -1;
21749
21940
  }
21750
21941
  if (instance.shuttingDown || runState.shuttingDown) return;
21751
- if (instance.softReloadInProgress) {
21942
+ const softReloadHappenedMidWait = (instance.softReloadGeneration ?? 0) !== softReloadGenBeforeWait;
21943
+ if (instance.softReloadInProgress || softReloadHappenedMidWait) {
21752
21944
  while (instance.softReloadInProgress && !instance.shuttingDown && !runState.shuttingDown) await sleep(100);
21753
21945
  if (instance.shuttingDown || runState.shuttingDown) return;
21754
21946
  continue;
@@ -22729,9 +22921,51 @@ function escapeRealmQuotes(realm) {
22729
22921
  }
22730
22922
  /** Reply 404 — an ALB listener with no matching rule and no default action. */
22731
22923
  function reply404(req, res, opts) {
22732
- writeError(res, 404, `No listener rule matched '${req.url ?? "/"}' on ${opts.label}, and the listener has no default action forwarding to a local target.`);
22924
+ writeError(res, 404, buildNoRuleMatched404Body(req, opts));
22733
22925
  return Promise.resolve();
22734
22926
  }
22927
+ /**
22928
+ * Build the no-rule-matched 404 body. When the call site supplied a
22929
+ * {@link StartFrontDoorServerOptions.rulesSummary}, the body lists every
22930
+ * ALB condition field that WAS evaluated (method, host, path) plus every
22931
+ * configured rule's priority + conditions + action target — so a user
22932
+ * whose request missed on, say, the Host header can spot the mismatch
22933
+ * without inspecting the synthesized template. Header conditions are
22934
+ * NOT spelled out in the evaluated section (too noisy) but ARE listed
22935
+ * in each rule's condition row when the rule constrains them. Without a
22936
+ * summary the body falls back to the original path-only shape (preserves
22937
+ * the behavior for direct callers that wire the proxy with just a
22938
+ * `selectPool` / `selectTarget`).
22939
+ */
22940
+ function buildNoRuleMatched404Body(req, opts) {
22941
+ const requestPath = req.url ?? "/";
22942
+ const summary = opts.rulesSummary;
22943
+ if (!summary) return `No listener rule matched '${requestPath}' on ${opts.label}, and the listener has no default action forwarding to a local target.`;
22944
+ const rawHost = req.headers.host;
22945
+ const hostValue = Array.isArray(rawHost) ? rawHost[0] : rawHost;
22946
+ const lines = [];
22947
+ lines.push(`No listener rule matched the request on ${opts.label}, and the listener has no default action forwarding to a local target.`);
22948
+ lines.push("");
22949
+ lines.push(" Evaluated:");
22950
+ lines.push(` Method: ${req.method ?? "(unknown)"}`);
22951
+ lines.push(` Host: ${hostValue ?? "(no Host header)"}`);
22952
+ lines.push(` Path: ${requestPath}`);
22953
+ lines.push("");
22954
+ if (summary.length === 0) lines.push(" Listener has 0 rule(s).");
22955
+ else {
22956
+ lines.push(` Listener has ${summary.length} rule(s):`);
22957
+ const ordered = [...summary].sort((a, b) => a.priority - b.priority);
22958
+ for (const rule of ordered) {
22959
+ const conditions = rule.conditions.length === 0 ? "(no condition)" : rule.conditions.map(formatRuleConditionSummary).join(" AND ");
22960
+ lines.push(` [priority=${rule.priority}] ${conditions} -> ${rule.action}`);
22961
+ }
22962
+ }
22963
+ return lines.join("\n");
22964
+ }
22965
+ /** Format one condition row of a {@link FrontDoorRuleSummary} for the 404 body. */
22966
+ function formatRuleConditionSummary(c) {
22967
+ return `${c.field} in [${c.values.join(", ")}]`;
22968
+ }
22735
22969
  function handlePoolRequest(req, res, pool, opts) {
22736
22970
  return new Promise((resolve) => {
22737
22971
  const endpoint = pool.next();
@@ -24239,6 +24473,13 @@ async function reloadAllServices(args) {
24239
24473
  * {@link AssetManifestLoader}) so the caller can fall back to rebuild
24240
24474
  * with a warn line that explains why the classifier couldn't run.
24241
24475
  */
24476
+ /**
24477
+ * @internal — exported for unit tests of the fall-through branches
24478
+ * (the 6 `return undefined` paths + the catch arm on
24479
+ * `resolveEcsServiceTarget` throw). Not part of the semver-covered
24480
+ * public surface; the only legitimate caller is `reloadAllServices`
24481
+ * inside this file.
24482
+ */
24242
24483
  async function loadAssetContextForTarget(args) {
24243
24484
  const { target, controller, stacks, cdkOutDir, assetLoader, logger } = args;
24244
24485
  const candidate = pickCandidateStack(parseEcsTarget(target).stackPattern, stacks);
@@ -24261,8 +24502,12 @@ async function loadAssetContextForTarget(args) {
24261
24502
  if (!newDockerImage.source.directory) return;
24262
24503
  const newAssetSourceDir = path.resolve(cdkOutDir, newDockerImage.source.directory);
24263
24504
  let oldAssetHash;
24264
- const oldEssential = controller.service.task.containers.find((c) => c.essential) ?? controller.service.task.containers[0];
24265
- if (oldEssential?.image.kind === "cdk-asset") oldAssetHash = oldEssential.image.assetHash;
24505
+ const liveReplica = controller.runState.replicas.find((r) => !r.shuttingDown);
24506
+ if (liveReplica?.lastDeployedAssetHash !== void 0) oldAssetHash = liveReplica.lastDeployedAssetHash;
24507
+ else {
24508
+ const oldEssential = controller.service.task.containers.find((c) => c.essential) ?? controller.service.task.containers[0];
24509
+ if (oldEssential?.image.kind === "cdk-asset") oldAssetHash = oldEssential.image.assetHash;
24510
+ }
24266
24511
  return {
24267
24512
  ...oldAssetHash !== void 0 && { oldAssetHash },
24268
24513
  newAssetHash,
@@ -24430,7 +24675,8 @@ async function resolveServiceAndRunnerOpts(boot, stacks, options, discovery, ski
24430
24675
  restartPolicy: options.restartPolicy,
24431
24676
  taskOptions: taskOpts,
24432
24677
  discovery,
24433
- ...frontDoorPools && frontDoorPools.length > 0 ? { frontDoor: { pools: frontDoorPools } } : {}
24678
+ ...frontDoorPools && frontDoorPools.length > 0 ? { frontDoor: { pools: frontDoorPools } } : {},
24679
+ streamLogs: options.logs !== false
24434
24680
  }
24435
24681
  };
24436
24682
  }
@@ -24558,6 +24804,7 @@ async function buildFrontDoor(plan, options, logger) {
24558
24804
  const tls = listener.protocol === "HTTPS" && wantTls ? tlsMaterials : void 0;
24559
24805
  const forwardedProto = listener.protocol === "HTTPS" ? "https" : "http";
24560
24806
  const degradedHttps = listener.protocol === "HTTPS" && !wantTls;
24807
+ const rulesSummary = listener.rules.map(buildRuleSummary);
24561
24808
  const server = await startFrontDoorServer({
24562
24809
  route,
24563
24810
  port: listener.hostPort,
@@ -24565,6 +24812,7 @@ async function buildFrontDoor(plan, options, logger) {
24565
24812
  listenerPort: listener.listenerPort,
24566
24813
  label: `listener port ${listener.listenerPort}`,
24567
24814
  forwardedProto,
24815
+ rulesSummary,
24568
24816
  ...tls ? { tls } : {}
24569
24817
  });
24570
24818
  servers.push(server);
@@ -24629,6 +24877,66 @@ function describeTarget(t) {
24629
24877
  function describeTargetShort(t) {
24630
24878
  return t.kind === "lambda" ? `Lambda ${t.lambda.logicalId}` : t.serviceTarget;
24631
24879
  }
24880
+ /**
24881
+ * Build the per-rule summary the front-door surfaces in its no-rule-matched
24882
+ * 404 body (issue #228). One condition row per constrained ALB field, plus a
24883
+ * pre-formatted action target. Distinct from {@link describeConditions} /
24884
+ * {@link describeAction} (which produce a single-line boot-banner string) —
24885
+ * the 404 body needs the rule decomposed into its constituent fields so the
24886
+ * formatter can render `field in [values]` rows.
24887
+ */
24888
+ function buildRuleSummary(rule) {
24889
+ const conditions = [];
24890
+ if (rule.pathPatterns.length > 0) conditions.push({
24891
+ field: "path-pattern",
24892
+ values: rule.pathPatterns
24893
+ });
24894
+ if (rule.hostPatterns.length > 0) conditions.push({
24895
+ field: "host-header",
24896
+ values: rule.hostPatterns
24897
+ });
24898
+ for (const h of rule.httpHeaderConditions) conditions.push({
24899
+ field: "http-header",
24900
+ values: [`${h.name}: ${h.values.join(", ")}`]
24901
+ });
24902
+ if (rule.httpRequestMethods.length > 0) conditions.push({
24903
+ field: "http-request-method",
24904
+ values: rule.httpRequestMethods
24905
+ });
24906
+ if (rule.queryStringConditions.length > 0) conditions.push({
24907
+ field: "query-string",
24908
+ values: rule.queryStringConditions.map(describeQueryStringCondition)
24909
+ });
24910
+ if (rule.sourceIpCidrs.length > 0) conditions.push({
24911
+ field: "source-ip",
24912
+ values: rule.sourceIpCidrs
24913
+ });
24914
+ return {
24915
+ priority: rule.priority,
24916
+ conditions,
24917
+ action: describeRuleActionForSummary(rule.action)
24918
+ };
24919
+ }
24920
+ /**
24921
+ * Describe a planned action for the no-rule-matched 404 body (issue #228).
24922
+ * Uses the `<ECS: ...>` / `<Lambda: ...>` shape the issue body proposes so a
24923
+ * user can read each rule's target at a glance.
24924
+ */
24925
+ function describeRuleActionForSummary(action) {
24926
+ if (action.kind === "redirect") return `redirect ${action.statusCode}`;
24927
+ if (action.kind === "fixed-response") return `fixed-response ${action.statusCode}`;
24928
+ if (action.targets.length === 1) return `forward to ${describeForwardTargetForSummary(action.targets[0])}`;
24929
+ return `forward weighted [${action.targets.map((t) => `${describeForwardTargetForSummary(t)}@${t.weight}`).join(", ")}]`;
24930
+ }
24931
+ /**
24932
+ * One forward target named the way the 404 body shows it: `<ECS: Service>` or
24933
+ * `<Lambda: LogicalId>` — distinct from the boot-banner format (which also
24934
+ * prints the container / port / round-robin hint) so the 404 body stays
24935
+ * scannable.
24936
+ */
24937
+ function describeForwardTargetForSummary(t) {
24938
+ return t.kind === "lambda" ? `<Lambda: ${t.lambda.logicalId}>` : `<ECS: ${t.serviceTarget}>`;
24939
+ }
24632
24940
  async function resolvePlaceholderAccount(arn, region) {
24633
24941
  if (!arn.includes("${AWS::AccountId}")) return arn;
24634
24942
  const { STSClient, GetCallerIdentityCommand } = await import("@aws-sdk/client-sts");
@@ -24821,7 +25129,7 @@ async function resolveSharedSidecarCredentials(options) {
24821
25129
  * factory.
24822
25130
  */
24823
25131
  function addCommonEcsServiceOptions(cmd) {
24824
- cmd.addOption(new Option("--cluster <name>", "Cluster name surfaced to ECS_CONTAINER_METADATA_URI_V4 and used as the docker network prefix").default(getEmbedConfig().resourceNamePrefix)).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"ContainerName\":{\"KEY\":\"VALUE\"}, \"Parameters\":{}})")).addOption(new Option("--container-host <ip>", "Host IP to bind published container ports to. Must be a numeric IP (Docker rejects hostnames here)").default("127.0.0.1")).addOption(new Option("--assume-task-role [arn]", "Assume the task definition's TaskRoleArn (or the supplied ARN) and forward STS-issued temp credentials via the metadata sidecar so containers run with the deployed task role. Bare flag uses the template's TaskRoleArn; pass an explicit ARN to override.")).addOption(new Option("--no-pull", "Skip docker pull for every container image and the metadata sidecar")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries.")).addOption(new Option("--platform <platform>", "Force docker --platform (linux/amd64 or linux/arm64). Default: inferred from task RuntimePlatform.CpuArchitecture")).addOption(new Option("--max-tasks <n>", `Hard cap on local replica count. Caps the template DesiredCount so local dev machines don't run an unbounded number of containers. Cannot exceed ${83} due to the per-replica link-local /24 subnet allocator's range.`).default(3).argParser(parseMaxTasks)).addOption(new Option("--restart-policy <policy>", "How to react when an essential container exits. 'on-failure' (default) restarts only on non-zero exit; 'always' restarts on every exit; 'none' shuts the replica down and runs the service degraded.").default("on-failure").argParser(parseRestartPolicy)).addOption(new Option("--from-cfn-stack [cfn-stack-name]", `Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in container env vars / secrets / image URIs with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (\`cdk deploy\`). Bare form uses the ${getEmbedConfig().binaryName} stack name; pass an explicit value when the CFn stack name differs. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).`)).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region."));
25132
+ cmd.addOption(new Option("--cluster <name>", "Cluster name surfaced to ECS_CONTAINER_METADATA_URI_V4 and used as the docker network prefix").default(getEmbedConfig().resourceNamePrefix)).addOption(new Option("--env-vars <file>", "JSON env-var overrides (SAM-compatible: {\"ContainerName\":{\"KEY\":\"VALUE\"}, \"Parameters\":{}})")).addOption(new Option("--container-host <ip>", "Host IP to bind published container ports to. Must be a numeric IP (Docker rejects hostnames here)").default("127.0.0.1")).addOption(new Option("--assume-task-role [arn]", "Assume the task definition's TaskRoleArn (or the supplied ARN) and forward STS-issued temp credentials via the metadata sidecar so containers run with the deployed task role. Bare flag uses the template's TaskRoleArn; pass an explicit ARN to override.")).addOption(new Option("--no-pull", "Skip docker pull for every container image and the metadata sidecar")).addOption(new Option("--ecr-role-arn <arn>", "Role ARN to assume before authenticating against ECR for cross-account / centralized registries.")).addOption(new Option("--platform <platform>", "Force docker --platform (linux/amd64 or linux/arm64). Default: inferred from task RuntimePlatform.CpuArchitecture")).addOption(new Option("--max-tasks <n>", `Hard cap on local replica count. Caps the template DesiredCount so local dev machines don't run an unbounded number of containers. Cannot exceed ${83} due to the per-replica link-local /24 subnet allocator's range.`).default(3).argParser(parseMaxTasks)).addOption(new Option("--restart-policy <policy>", "How to react when an essential container exits. 'on-failure' (default) restarts only on non-zero exit; 'always' restarts on every exit; 'none' shuts the replica down and runs the service degraded.").default("on-failure").argParser(parseRestartPolicy)).addOption(new Option("--from-cfn-stack [cfn-stack-name]", `Read a deployed CloudFormation stack via ListStackResources and substitute Ref / Fn::ImportValue in container env vars / secrets / image URIs with the deployed physical IDs / exports. Use for CDK apps deployed via the upstream CDK CLI (\`cdk deploy\`). Bare form uses the ${getEmbedConfig().binaryName} stack name; pass an explicit value when the CFn stack name differs. Fn::GetAtt is warn-and-dropped in v1 (CFn ListStackResources does not return per-attribute values).`)).addOption(new Option("--stack-region <region>", "Region of the state record to read. Used with --from-cfn-stack as the CFn client region.")).addOption(new Option("--no-logs", "Disable foreground streaming of each replica container stdout/stderr. By default every booted replica streams its docker logs to the host terminal with a [svc=<service> r=<replica-index> c=<container>] prefix (parity with `run-task`). Pass --no-logs for multi-replica / multi-service runs whose interleaved log volume is unreadable; `docker logs -f <id>` in a separate terminal stays available."));
24825
25133
  [
24826
25134
  ...commonOptions(),
24827
25135
  ...appOptions(),
@@ -25849,5 +26157,5 @@ function addListSpecificOptions(cmd) {
25849
26157
  }
25850
26158
 
25851
26159
  //#endregion
25852
- export { applyAuthorizerOverlay as $, resolveRuntimeCodeMountPath as $t, createLocalStartApiCommand as A, AGENTCORE_AGUI_PROTOCOL as An, A2A_CONTAINER_PORT as At, groupRoutesByServer as B, tryResolveImageFnJoin as Bn, AGENTCORE_SESSION_ID_HEADER as Bt, classifySourceChange as C, discoverWebSocketApis as Cn, attachAuthorizers as Ct, addInvokeAgentCoreSpecificOptions as D, pickRefLogicalId as Dn, isFunctionUrlOacFronted as Dt, createLocalRunTaskCommand as E, discoverRoutes as En, buildCorsConfigFromCloudFrontChain as Et, attachStageContext as F, pickAgentCoreCandidateStack as Fn, MCP_PROTOCOL_VERSION as Ft, defaultCredentialsLoader as G, buildAgentCoreCodeImage as Gt, startApiServer as H, waitForAgentCorePing as Ht, buildStageMap as I, resolveAgentCoreTarget as In, mcpInvokeOnce as It, evaluateCachedLambdaPolicy as J, toCmdArgv as Jt, buildMethodArn as K, computeCodeImageTag as Kt, availableApiIdentifiers as L, derivePseudoParametersFromRegion as Ln, parseSseForJsonRpc as Lt, resolveApiTargetSubset as M, AGENTCORE_MCP_PROTOCOL as Mn, a2aInvokeOnce as Mt, createAuthorizerCache as N, AGENTCORE_RUNTIME_TYPE as Nn, MCP_CONTAINER_PORT as Nt, createLocalInvokeAgentCoreCommand as O, resolveLambdaArnIntrinsic as On, matchPreflight as Ot, createFileWatcher as P, AgentCoreResolutionError as Pn, MCP_PATH as Pt, translateLambdaResponse as Q, buildContainerImage as Qt, filterRoutesByApiIdentifier as R, formatStateRemedy as Rn, AGENTCORE_SIGV4_SERVICE as Rt, CloudMapRegistry as S, listTargets as Sn, verifyJwtViaDiscovery as St, addRunTaskSpecificOptions as T, parseSelectionExpressionPath as Tn, buildCorsConfigByApiId as Tt, resolveSelectionExpression as U, downloadAndExtractS3Bundle as Ut, readMtlsMaterialsFromDisk as V, LocalInvokeBuildError as Vn, invokeAgentCore as Vt, resolveServiceIntegrationParameters as W, SUPPORTED_CODE_RUNTIMES as Wt, invokeTokenAuthorizer as X, createLocalInvokeCommand as Xt, invokeRequestAuthorizer as Y, addInvokeSpecificOptions as Yt, matchRoute as Z, architectureToPlatform as Zt, parseMaxTasks as _, collectSsmParameterRefs as _n, buildCognitoJwksUrl as _t, albStrategy as a, substituteEnvVarsFromState as an, tryParseStatus as at, runEcsServiceEmulator as b, resolveSingleTarget as bn, verifyCognitoJwt as bt, resolveAlbTarget as c, materializeLayerFromArn as cn, probeHostGatewaySupport as ct, addStartServiceSpecificOptions as d, isCfnFlagPresent as dn, buildMgmtEndpointEnvUrl as dt, resolveRuntimeFileExtension as en, buildHttpApiV2Event as et, createLocalStartServiceCommand as f, rejectExplicitCfnStackWithMultipleStacks as fn, handleConnectionsRequest as ft, buildEcsImageResolutionContext as g, CfnLocalStateProvider as gn, buildMessageEvent as gt, addCommonEcsServiceOptions as h, resolveCfnStackName as hn, buildDisconnectEvent as ht, addAlbSpecificOptions as i, substituteAgainstStateAsync as in, selectIntegrationResponse as it, createWatchPredicates as j, AGENTCORE_HTTP_PROTOCOL as jn, A2A_PATH as jt, addStartApiSpecificOptions as k, AGENTCORE_A2A_PROTOCOL as kn, invokeAgentCoreWs as kt, isApplicationLoadBalancer as l, LocalStateSourceError as ln, bufferToBody as lt, MAX_TASKS_SUBNET_RANGE_CAP as m, resolveCfnRegion as mn, buildConnectEvent as mt, createLocalListCommand as n, EcsTaskResolutionError as nn, evaluateResponseParameters as nt, createLocalStartAlbCommand as o, substituteEnvVarsFromStateAsync as on, VtlEvaluationError as ot, serviceStrategy as p, resolveCfnFallbackRegion as pn, parseConnectionsPath as pt, computeRequestIdentityHash as q, renderCodeDockerfile as qt, formatTargetListing as r, substituteAgainstState as rn, pickResponseTemplate as rt, parseLbPortOverrides as s, resolveEnvVars as sn, HOST_GATEWAY_MIN_VERSION as st, addListSpecificOptions as t, resolveRuntimeImage as tn, buildRestV1Event as tt, resolveAlbFrontDoor as u, createLocalStateProvider as un, ConnectionRegistry as ut, parseRestartPolicy as v, resolveSsmParameters as vn, buildJwksUrlFromIssuer as vt, getContainerNetworkIp as w, discoverWebSocketApisOrThrow as wn, applyCorsResponseHeaders as wt, buildCloudMapIndex as x, countTargets as xn, verifyJwtAuthorizer as xt, resolveSharedSidecarCredentials as y, resolveWatchConfig as yn, createJwksCache as yt, filterRoutesByApiIdentifiers as z, substituteImagePlaceholders as zn, signAgentCoreInvocation as zt };
25853
- //# sourceMappingURL=local-list-l2_7oGHF.js.map
26160
+ export { matchRoute as $, architectureToPlatform as $t, createLocalInvokeAgentCoreCommand as A, resolveLambdaArnIntrinsic as An, matchPreflight as At, filterRoutesByApiIdentifier as B, formatStateRemedy as Bn, AGENTCORE_SIGV4_SERVICE as Bt, classifySourceChange as C, countTargets as Cn, verifyJwtAuthorizer as Ct, createLocalRunTaskCommand as D, parseSelectionExpressionPath as Dn, buildCorsConfigByApiId as Dt, addRunTaskSpecificOptions as E, discoverWebSocketApisOrThrow as En, applyCorsResponseHeaders as Et, createAuthorizerCache as F, AGENTCORE_RUNTIME_TYPE as Fn, MCP_CONTAINER_PORT as Ft, resolveSelectionExpression as G, downloadAndExtractS3Bundle as Gt, groupRoutesByServer as H, tryResolveImageFnJoin as Hn, AGENTCORE_SESSION_ID_HEADER as Ht, createFileWatcher as I, AgentCoreResolutionError as In, MCP_PATH as It, buildMethodArn as J, computeCodeImageTag as Jt, resolveServiceIntegrationParameters as K, SUPPORTED_CODE_RUNTIMES as Kt, attachStageContext as L, pickAgentCoreCandidateStack as Ln, MCP_PROTOCOL_VERSION as Lt, createLocalStartApiCommand as M, AGENTCORE_AGUI_PROTOCOL as Mn, A2A_CONTAINER_PORT as Mt, createWatchPredicates as N, AGENTCORE_HTTP_PROTOCOL as Nn, A2A_PATH as Nt, attachContainerLogStreamer as O, discoverRoutes as On, buildCorsConfigFromCloudFrontChain as Ot, resolveApiTargetSubset as P, AGENTCORE_MCP_PROTOCOL as Pn, a2aInvokeOnce as Pt, invokeTokenAuthorizer as Q, createLocalInvokeCommand as Qt, buildStageMap as R, resolveAgentCoreTarget as Rn, mcpInvokeOnce as Rt, CloudMapRegistry as S, resolveSingleTarget as Sn, verifyCognitoJwt as St, getContainerNetworkIp as T, discoverWebSocketApis as Tn, attachAuthorizers as Tt, readMtlsMaterialsFromDisk as U, LocalInvokeBuildError as Un, invokeAgentCore as Ut, filterRoutesByApiIdentifiers as V, substituteImagePlaceholders as Vn, signAgentCoreInvocation as Vt, startApiServer as W, waitForAgentCorePing as Wt, evaluateCachedLambdaPolicy as X, toCmdArgv as Xt, computeRequestIdentityHash as Y, renderCodeDockerfile as Yt, invokeRequestAuthorizer as Z, addInvokeSpecificOptions as Zt, parseMaxTasks as _, resolveCfnStackName as _n, buildDisconnectEvent as _t, albStrategy as a, substituteAgainstState as an, pickResponseTemplate as at, runEcsServiceEmulator as b, resolveSsmParameters as bn, buildJwksUrlFromIssuer as bt, resolveAlbTarget as c, substituteEnvVarsFromStateAsync as cn, VtlEvaluationError as ct, addStartServiceSpecificOptions as d, LocalStateSourceError as dn, bufferToBody as dt, buildContainerImage as en, translateLambdaResponse as et, createLocalStartServiceCommand as f, createLocalStateProvider as fn, ConnectionRegistry as ft, buildEcsImageResolutionContext as g, resolveCfnRegion as gn, buildConnectEvent as gt, addCommonEcsServiceOptions as h, resolveCfnFallbackRegion as hn, parseConnectionsPath as ht, addAlbSpecificOptions as i, EcsTaskResolutionError as in, evaluateResponseParameters as it, addStartApiSpecificOptions as j, AGENTCORE_A2A_PROTOCOL as jn, invokeAgentCoreWs as jt, addInvokeAgentCoreSpecificOptions as k, pickRefLogicalId as kn, isFunctionUrlOacFronted as kt, isApplicationLoadBalancer as l, resolveEnvVars as ln, HOST_GATEWAY_MIN_VERSION as lt, MAX_TASKS_SUBNET_RANGE_CAP as m, rejectExplicitCfnStackWithMultipleStacks as mn, handleConnectionsRequest as mt, createLocalListCommand as n, resolveRuntimeFileExtension as nn, buildHttpApiV2Event as nt, createLocalStartAlbCommand as o, substituteAgainstStateAsync as on, selectIntegrationResponse as ot, serviceStrategy as p, isCfnFlagPresent as pn, buildMgmtEndpointEnvUrl as pt, defaultCredentialsLoader as q, buildAgentCoreCodeImage as qt, formatTargetListing as r, resolveRuntimeImage as rn, buildRestV1Event as rt, parseLbPortOverrides as s, substituteEnvVarsFromState as sn, tryParseStatus as st, addListSpecificOptions as t, resolveRuntimeCodeMountPath as tn, applyAuthorizerOverlay as tt, resolveAlbFrontDoor as u, materializeLayerFromArn as un, probeHostGatewaySupport as ut, parseRestartPolicy as v, CfnLocalStateProvider as vn, buildMessageEvent as vt, SOFT_RELOAD_COMPLETION_LOG_SUFFIX as w, listTargets as wn, verifyJwtViaDiscovery as wt, buildCloudMapIndex as x, resolveWatchConfig as xn, createJwksCache as xt, resolveSharedSidecarCredentials as y, collectSsmParameterRefs as yn, buildCognitoJwksUrl as yt, availableApiIdentifiers as z, derivePseudoParametersFromRegion as zn, parseSseForJsonRpc as zt };
26161
+ //# sourceMappingURL=local-list-B67vK97a.js.map