cdk-local 0.167.1 → 0.168.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.
@@ -2502,6 +2502,32 @@ async function resolveProfileRegion(profile) {
2502
2502
  return resolveSdkDefaultRegion(profile);
2503
2503
  }
2504
2504
 
2505
+ // src/utils/shutdown-signal.ts
2506
+ function signalExitCode(signal) {
2507
+ return signal === "SIGINT" ? 130 : 143;
2508
+ }
2509
+ function createShutdownSignalHandler(options) {
2510
+ const exit = options.exit ?? ((code) => process.exit(code));
2511
+ const writeStderr = options.writeStderr ?? ((text) => void process.stderr.write(text));
2512
+ let count = 0;
2513
+ const handler = (signal, exitCode) => {
2514
+ const code = exitCode ?? signalExitCode(signal === "SIGINT" ? "SIGINT" : "SIGTERM");
2515
+ count += 1;
2516
+ if (count === 1) {
2517
+ options.info(options.stoppingMessage(signal));
2518
+ options.cleanup().then(() => exit(code));
2519
+ return;
2520
+ }
2521
+ if (count === 2) {
2522
+ options.warn(`Received ${signal} again; still shutting down — waiting for the cleanup to remove the containers and networks. Send it once more to force-exit (that skips the cleanup).`);
2523
+ return;
2524
+ }
2525
+ writeStderr(`Force-exit on repeated ${signal}; container cleanup skipped. ${options.forceExitHint}\n`);
2526
+ exit(code);
2527
+ };
2528
+ return handler;
2529
+ }
2530
+
2505
2531
  // src/utils/error-handler.ts
2506
2532
  var CdkLocalError = class CdkLocalError extends Error {
2507
2533
  code;
@@ -5334,17 +5360,38 @@ function resolveWatchConfig() {
5334
5360
  }
5335
5361
 
5336
5362
  // src/local/ssm-parameter-resolver.ts
5337
- const SSM_STRING_TYPE = "AWS::SSM::Parameter::Value<String>";
5338
- const SSM_LIST_TYPE = "AWS::SSM::Parameter::Value<List<String>>";
5363
+ const AWS_SPECIFIC_PARAMETER_TYPES = /* @__PURE__ */ new Set([
5364
+ "AWS::EC2::AvailabilityZone::Name",
5365
+ "AWS::EC2::Image::Id",
5366
+ "AWS::EC2::Instance::Id",
5367
+ "AWS::EC2::KeyPair::KeyName",
5368
+ "AWS::EC2::SecurityGroup::GroupName",
5369
+ "AWS::EC2::SecurityGroup::Id",
5370
+ "AWS::EC2::Subnet::Id",
5371
+ "AWS::EC2::Volume::Id",
5372
+ "AWS::EC2::VPC::Id",
5373
+ "AWS::Route53::HostedZone::Id"
5374
+ ]);
5375
+ const SSM_VALUE_PREFIX = "AWS::SSM::Parameter::Value<";
5376
+ function classifySsmParameterType(type) {
5377
+ if (typeof type !== "string" || !type.startsWith(SSM_VALUE_PREFIX) || !type.endsWith(">")) return;
5378
+ const inner = type.slice(27, -1);
5379
+ if (inner === "String" || AWS_SPECIFIC_PARAMETER_TYPES.has(inner)) return "scalar";
5380
+ if (inner === "CommaDelimitedList") return "list";
5381
+ if (inner.startsWith("List<") && inner.endsWith(">")) {
5382
+ const member = inner.slice(5, -1);
5383
+ if (member === "String" || AWS_SPECIFIC_PARAMETER_TYPES.has(member)) return "list";
5384
+ }
5385
+ }
5339
5386
  function collectSsmParameterRefs(template) {
5340
5387
  const params = template?.Parameters;
5341
5388
  if (!params) return [];
5342
5389
  const out = [];
5343
5390
  for (const [logicalId, entry] of Object.entries(params)) {
5344
5391
  if (!entry || typeof entry !== "object") continue;
5345
- const type = entry.Type;
5346
- const isList = type === SSM_LIST_TYPE;
5347
- if (type !== SSM_STRING_TYPE && !isList) continue;
5392
+ const kind = classifySsmParameterType(entry.Type);
5393
+ if (kind === void 0) continue;
5394
+ const isList = kind === "list";
5348
5395
  const ssmName = entry.Default;
5349
5396
  if (typeof ssmName !== "string" || ssmName.length === 0) continue;
5350
5397
  out.push({
@@ -5394,7 +5441,7 @@ async function resolveSsmParameters(client, refs, label) {
5394
5441
  if (!requesters) continue;
5395
5442
  const isSecure = p.Type === "SecureString";
5396
5443
  for (const ref of requesters) {
5397
- out.values[ref.logicalId] = p.Value;
5444
+ out.values[ref.logicalId] = ref.isList ? p.Value.split(",") : p.Value;
5398
5445
  if (isSecure) out.secureStringLogicalIds.push(ref.logicalId);
5399
5446
  }
5400
5447
  }
@@ -6039,6 +6086,10 @@ function resolveRef(arg, context) {
6039
6086
  };
6040
6087
  const parameterValue = context.parameters?.[arg];
6041
6088
  if (parameterValue !== void 0) {
6089
+ if (Array.isArray(parameterValue)) return {
6090
+ kind: "unresolved",
6091
+ reason: `Ref ${displayIdent(arg)}: the parameter is a list, which is not a valid string value (use Fn::Select to pick one element or Fn::Join to join it)`
6092
+ };
6042
6093
  if (context.sensitiveParameters?.has(arg)) context.onSensitiveParameterConsumed?.(arg);
6043
6094
  return {
6044
6095
  kind: "literal",
@@ -6193,15 +6244,31 @@ function resolveSub(arg, context) {
6193
6244
  };
6194
6245
  }
6195
6246
  function resolveJoin(arg, context) {
6196
- if (!Array.isArray(arg) || arg.length !== 2 || !Array.isArray(arg[1])) return {
6247
+ if (!Array.isArray(arg) || arg.length !== 2) return {
6197
6248
  kind: "unresolved",
6198
6249
  reason: `Fn::Join expects [delimiter, [elements]], got ${Array.isArray(arg) ? `array of length ${arg.length}` : typeof arg}`
6199
6250
  };
6200
- const [delimiterRaw, elements] = arg;
6251
+ const [delimiterRaw, elementsArg] = arg;
6201
6252
  if (typeof delimiterRaw !== "string") return {
6202
6253
  kind: "unresolved",
6203
6254
  reason: `Fn::Join delimiter must be a string, got ${typeof delimiterRaw}`
6204
6255
  };
6256
+ if (!Array.isArray(elementsArg)) {
6257
+ const list = resolveAny(elementsArg, context);
6258
+ if (list.kind === "unresolved") return {
6259
+ kind: "unresolved",
6260
+ reason: `Fn::Join list: ${list.reason}`
6261
+ };
6262
+ if (!Array.isArray(list.value)) return {
6263
+ kind: "unresolved",
6264
+ reason: `Fn::Join list must resolve to an array, got ${typeof list.value}`
6265
+ };
6266
+ return {
6267
+ kind: "literal",
6268
+ value: list.value.join(delimiterRaw)
6269
+ };
6270
+ }
6271
+ const elements = elementsArg;
6205
6272
  const parts = [];
6206
6273
  for (let i = 0; i < elements.length; i += 1) {
6207
6274
  const sub = substituteAgainstState(elements[i], context);
@@ -6294,6 +6361,19 @@ function resolveAny(value, context) {
6294
6361
  };
6295
6362
  }
6296
6363
  if (value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 1 && Object.prototype.hasOwnProperty.call(value, "Fn::Split")) return resolveSplitAsArray(value["Fn::Split"], context);
6364
+ if (value !== null && typeof value === "object" && Object.keys(value).length === 1 && Object.prototype.hasOwnProperty.call(value, "Ref")) {
6365
+ const target = value["Ref"];
6366
+ if (typeof target === "string" && !context.resources[target]) {
6367
+ const parameterValue = context.parameters?.[target];
6368
+ if (Array.isArray(parameterValue)) {
6369
+ if (context.sensitiveParameters?.has(target)) context.onSensitiveParameterConsumed?.(target);
6370
+ return {
6371
+ kind: "literal",
6372
+ value: [...parameterValue]
6373
+ };
6374
+ }
6375
+ }
6376
+ }
6297
6377
  return substituteAgainstState(value, context);
6298
6378
  }
6299
6379
  async function substituteAgainstStateAsync(value, contextOrResources) {
@@ -7247,10 +7327,43 @@ function getAttReads(node, out = []) {
7247
7327
  }
7248
7328
  return out;
7249
7329
  }
7330
+ function computedAttributeRead(node) {
7331
+ if (node === null || typeof node !== "object") return void 0;
7332
+ if (Array.isArray(node)) {
7333
+ for (const item of node) {
7334
+ const r = computedAttributeRead(item);
7335
+ if (r !== void 0) return r;
7336
+ }
7337
+ return;
7338
+ }
7339
+ for (const [key, value] of Object.entries(node)) {
7340
+ if (key === "Fn::GetAtt" && isCrossStackIntrinsic(value)) return "a Fn::GetAtt whose logical ID or attribute name is a cross-stack reference, which CloudFormation does not accept";
7341
+ if (key === "Fn::Sub") {
7342
+ if (isCrossStackIntrinsic(Array.isArray(value) ? value[0] : value)) return "a Fn::Sub whose template is a cross-stack reference, which CloudFormation does not accept";
7343
+ }
7344
+ const r = computedAttributeRead(value);
7345
+ if (r !== void 0) return r;
7346
+ }
7347
+ }
7348
+ function withMaskWatch(context, masked) {
7349
+ const inner = context.crossStackResolver;
7350
+ if (!inner) return context;
7351
+ const watch = (v) => {
7352
+ if (v === STATE_SECRET_MASK) masked.hit = true;
7353
+ return v;
7354
+ };
7355
+ return {
7356
+ ...context,
7357
+ crossStackResolver: {
7358
+ resolveImport: async (exportName) => watch(await inner.resolveImport(exportName)),
7359
+ resolveGetStackOutput: async (stack, region, output) => watch(await inner.resolveGetStackOutput(stack, region, output))
7360
+ }
7361
+ };
7362
+ }
7250
7363
  const CROSS_STACK_ARGV_REASON = "a cross-stack reference (Fn::ImportValue / Fn::GetStackOutput): it resolves only from a state source with the producer stack deployed";
7251
7364
  function argvValue(sub, consumedSensitive) {
7252
- if (sub.kind !== "literal") return { reason: sub.reason };
7253
7365
  if (consumedSensitive) return { reason: "resolved from a SecureString parameter, which would put the secret on the docker run argv; move the value into an Environment variable or a Secrets entry" };
7366
+ if (sub.kind !== "literal") return { reason: sub.reason };
7254
7367
  const value = sub.value;
7255
7368
  if (typeof value === "number" || typeof value === "boolean") return { value: String(value) };
7256
7369
  if (value === STATE_SECRET_MASK) return { reason: "resolved to the secret mask (***), not the deployed value" };
@@ -7663,16 +7776,17 @@ async function applyCrossStackResolverToTask(task, context, containerState) {
7663
7776
  remaining.push(u);
7664
7777
  continue;
7665
7778
  }
7666
- const secret = secretAttributeRead(rawElement, argvContext.resources);
7667
- if (secret !== void 0) {
7779
+ const refusal = secretAttributeRead(rawElement, argvContext.resources) ?? computedAttributeRead(rawElement);
7780
+ if (refusal !== void 0) {
7668
7781
  remaining.push({
7669
7782
  ...u,
7670
- reason: secret
7783
+ reason: refusal
7671
7784
  });
7672
7785
  continue;
7673
7786
  }
7674
- const { result: sub, consumedSensitive } = await resolveWithSensitivityAsync(rawElement, argvContext);
7675
- const arg = argvValue(sub, consumedSensitive);
7787
+ const masked = { hit: false };
7788
+ const { result: sub, consumedSensitive } = await resolveWithSensitivityAsync(rawElement, withMaskWatch(argvContext, masked));
7789
+ const arg = masked.hit ? { reason: `resolved a cross-stack value recorded as the secret mask (${STATE_SECRET_MASK}), not the deployed value` } : argvValue(sub, consumedSensitive);
7676
7790
  if ("value" in arg) {
7677
7791
  target[u.index] = arg.value;
7678
7792
  continue;
@@ -8411,32 +8525,6 @@ function isMalformedEnvKey(key) {
8411
8525
  return !WELL_FORMED_ENV_KEY.test(key);
8412
8526
  }
8413
8527
 
8414
- // src/utils/shutdown-signal.ts
8415
- function signalExitCode(signal) {
8416
- return signal === "SIGINT" ? 130 : 143;
8417
- }
8418
- function createShutdownSignalHandler(options) {
8419
- const exit = options.exit ?? ((code) => process.exit(code));
8420
- const writeStderr = options.writeStderr ?? ((text) => void process.stderr.write(text));
8421
- let count = 0;
8422
- const handler = (signal, exitCode) => {
8423
- const code = exitCode ?? signalExitCode(signal === "SIGINT" ? "SIGINT" : "SIGTERM");
8424
- count += 1;
8425
- if (count === 1) {
8426
- options.info(options.stoppingMessage(signal));
8427
- options.cleanup().then(() => exit(code));
8428
- return;
8429
- }
8430
- if (count === 2) {
8431
- options.warn(`Received ${signal} again; still shutting down — waiting for the cleanup to remove the containers and networks. Send it once more to force-exit (that skips the cleanup).`);
8432
- return;
8433
- }
8434
- writeStderr(`Force-exit on repeated ${signal}; container cleanup skipped. ${options.forceExitHint}\n`);
8435
- exit(code);
8436
- };
8437
- return handler;
8438
- }
8439
-
8440
8528
  // src/assets/asset-source-path.ts
8441
8529
  function resolveAssetSourcePath(opts) {
8442
8530
  const { manifestDir, value, assetOutdir, field, subject, action, wrapError } = opts;
@@ -9670,6 +9758,46 @@ function execEnvForSecrets(passthrough) {
9670
9758
  return { env };
9671
9759
  }
9672
9760
 
9761
+ // src/local/container-start-guard.ts
9762
+ const NAME_CONFLICT = /is already (?:in use|used) by|Conflict\. The container name/;
9763
+ function createContainerStartGuard(options) {
9764
+ const remove = options.remove ?? removeContainer;
9765
+ let stopping = false;
9766
+ const inFlight = /* @__PURE__ */ new Set();
9767
+ const cancelled = () => new CdkLocalError("Shutting down: the container is not used.", options.cancelledCode);
9768
+ const stopAll = async () => {
9769
+ stopping = true;
9770
+ return (await Promise.all([...inFlight])).filter((id) => id !== void 0);
9771
+ };
9772
+ return {
9773
+ async run(start, name) {
9774
+ if (stopping) throw cancelled();
9775
+ const started = start();
9776
+ const outcome = started.then((id) => id, async (err) => {
9777
+ const message = err instanceof Error ? err.message : String(err);
9778
+ if (name !== void 0 && !NAME_CONFLICT.test(message)) try {
9779
+ await remove(name);
9780
+ } catch {}
9781
+ });
9782
+ inFlight.add(outcome);
9783
+ try {
9784
+ const id = await started;
9785
+ if (stopping) throw cancelled();
9786
+ return id;
9787
+ } catch (err) {
9788
+ await outcome;
9789
+ throw err;
9790
+ } finally {
9791
+ inFlight.delete(outcome);
9792
+ }
9793
+ },
9794
+ async stop() {
9795
+ return (await stopAll())[0];
9796
+ },
9797
+ stopAll
9798
+ };
9799
+ }
9800
+
9673
9801
  // src/local/debug-timeout.ts
9674
9802
  const DEBUG_FUNCTION_TIMEOUT_SEC = 36e3;
9675
9803
  function applyDebuggerEnv(dockerEnv, debugPort) {
@@ -10404,13 +10532,17 @@ async function localInvokeCommand(target, options, extraStateProviders) {
10404
10532
  let containerId;
10405
10533
  let stopLogs;
10406
10534
  let sigintHandler;
10535
+ let sigtermHandler;
10407
10536
  let profileCredsFile;
10537
+ const startGuard = createContainerStartGuard({ cancelledCode: "LOCAL_INVOKE_CANCELLED" });
10408
10538
  const cleanup = singleFlight(async () => {
10539
+ const pendingContainer = startGuard.stop();
10409
10540
  if (stopLogs) try {
10410
10541
  stopLogs();
10411
10542
  } catch (err) {
10412
10543
  getLogger().debug(`streamLogs stop failed: ${err instanceof Error ? err.message : String(err)}`);
10413
10544
  }
10545
+ containerId ??= await pendingContainer;
10414
10546
  if (containerId) try {
10415
10547
  await removeContainer(containerId);
10416
10548
  } catch (err) {
@@ -10456,6 +10588,17 @@ async function localInvokeCommand(target, options, extraStateProviders) {
10456
10588
  }, (err) => {
10457
10589
  getLogger().debug(`cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
10458
10590
  });
10591
+ const onSignal = createShutdownSignalHandler({
10592
+ cleanup,
10593
+ stoppingMessage: (signal) => `Received ${signal}, removing the Lambda container...`,
10594
+ forceExitHint: `Run 'docker ps -a --filter name=${getEmbedConfig().resourceNamePrefix}-' to find what is left.`,
10595
+ info: (m) => logger.info(m),
10596
+ warn: (m) => logger.warn(m)
10597
+ });
10598
+ sigintHandler = () => onSignal("SIGINT");
10599
+ sigtermHandler = () => onSignal("SIGTERM");
10600
+ process.on("SIGINT", sigintHandler);
10601
+ process.on("SIGTERM", sigtermHandler);
10459
10602
  try {
10460
10603
  await activateWorkloadAwsWiring({
10461
10604
  ...options,
@@ -10523,29 +10666,26 @@ async function localInvokeCommand(target, options, extraStateProviders) {
10523
10666
  readOnly: true
10524
10667
  }] : imagePlan.extraMounts;
10525
10668
  const hostGatewayExtraHosts = await resolveHostGatewayExtraHosts();
10526
- containerId = await runDetached({
10527
- image: imagePlan.image,
10528
- mounts: imagePlan.mounts,
10669
+ const containerName = `${getEmbedConfig().resourceNamePrefix}-invoke-${process.pid}-${Math.random().toString(36).slice(2, 8)}`;
10670
+ const runPlan = imagePlan;
10671
+ containerId = await startGuard.run(() => runDetached({
10672
+ name: containerName,
10673
+ image: runPlan.image,
10674
+ mounts: runPlan.mounts,
10529
10675
  extraMounts: extraMountsWithProfile,
10530
10676
  env: dockerEnv,
10531
10677
  ...containerEnv.sensitiveEnvKeys.length > 0 && { sensitiveEnvKeys: new Set(containerEnv.sensitiveEnvKeys) },
10532
10678
  ...hostGatewayExtraHosts.length > 0 && { extraHosts: hostGatewayExtraHosts },
10533
- cmd: imagePlan.cmd,
10679
+ cmd: runPlan.cmd,
10534
10680
  hostPort,
10535
10681
  host: containerHost,
10536
10682
  ...debugPort !== void 0 && { debugPort },
10537
- ...imagePlan.platform !== void 0 && { platform: imagePlan.platform },
10538
- ...imagePlan.entryPoint !== void 0 && { entryPoint: imagePlan.entryPoint },
10539
- ...imagePlan.workingDir !== void 0 && { workingDir: imagePlan.workingDir },
10540
- ...imagePlan.tmpfs !== void 0 && { tmpfs: imagePlan.tmpfs }
10541
- });
10683
+ ...runPlan.platform !== void 0 && { platform: runPlan.platform },
10684
+ ...runPlan.entryPoint !== void 0 && { entryPoint: runPlan.entryPoint },
10685
+ ...runPlan.workingDir !== void 0 && { workingDir: runPlan.workingDir },
10686
+ ...runPlan.tmpfs !== void 0 && { tmpfs: runPlan.tmpfs }
10687
+ }), containerName);
10542
10688
  stopLogs = streamLogs(containerId);
10543
- sigintHandler = () => {
10544
- cleanup().then(() => {
10545
- process.exit(130);
10546
- });
10547
- };
10548
- process.on("SIGINT", sigintHandler);
10549
10689
  await waitForRieReady(containerHost, hostPort, 5e3);
10550
10690
  const invokeTimeoutMs = rieInvokeTimeoutMs(lambda.timeoutSec, debugPort !== void 0);
10551
10691
  const result = await invokeRie(containerHost, hostPort, event, invokeTimeoutMs);
@@ -10553,8 +10693,9 @@ async function localInvokeCommand(target, options, extraStateProviders) {
10553
10693
  process.stdout.write(`${result.raw}\n`);
10554
10694
  if (options.responseFile) writeFileSync(options.responseFile, result.raw);
10555
10695
  } finally {
10556
- if (sigintHandler) process.off("SIGINT", sigintHandler);
10557
10696
  await cleanup();
10697
+ if (sigintHandler) process.off("SIGINT", sigintHandler);
10698
+ if (sigtermHandler) process.off("SIGTERM", sigtermHandler);
10558
10699
  }
10559
10700
  }
10560
10701
  async function resolveImagePlan(lambda, options) {
@@ -13058,6 +13199,8 @@ function createContainerPool(specs, options) {
13058
13199
  const entries = /* @__PURE__ */ new Map();
13059
13200
  let disposed = false;
13060
13201
  const inFlightStarts = /* @__PURE__ */ new Set();
13202
+ const startGuard = createContainerStartGuard({ cancelledCode: "CONTAINER_POOL_DISPOSED" });
13203
+ const startedNotReady = /* @__PURE__ */ new Set();
13061
13204
  for (const logicalId of specs.keys()) entries.set(logicalId, emptyEntry(logicalId));
13062
13205
  function emptyEntry(logicalId) {
13063
13206
  return {
@@ -13088,7 +13231,7 @@ function createContainerPool(specs, options) {
13088
13231
  }] : optMount;
13089
13232
  const containerCodePath = resolveRuntimeCodeMountPath(spec.lambda.runtime);
13090
13233
  const image = resolveRuntimeImage(spec.lambda.runtime);
13091
- containerId = await runDetached({
13234
+ containerId = await startGuard.run(() => runDetached({
13092
13235
  image,
13093
13236
  platform: architectureToPlatform(spec.lambda.architecture),
13094
13237
  mounts: [{
@@ -13106,8 +13249,8 @@ function createContainerPool(specs, options) {
13106
13249
  ...spec.debugPort !== void 0 && { debugPort: spec.debugPort },
13107
13250
  ...spec.tmpfs !== void 0 && { tmpfs: spec.tmpfs },
13108
13251
  ...spec.extraHosts !== void 0 && { extraHosts: spec.extraHosts }
13109
- });
13110
- } else containerId = await runDetached({
13252
+ }), name);
13253
+ } else containerId = await startGuard.run(() => runDetached({
13111
13254
  image: spec.image,
13112
13255
  mounts: [],
13113
13256
  extraMounts: [...spec.rieMount ? [spec.rieMount] : [], ...spec.profileCredentialsFile ? [{
@@ -13127,14 +13270,17 @@ function createContainerPool(specs, options) {
13127
13270
  ...spec.debugPort !== void 0 && { debugPort: spec.debugPort },
13128
13271
  ...spec.tmpfs !== void 0 && { tmpfs: spec.tmpfs },
13129
13272
  ...spec.extraHosts !== void 0 && { extraHosts: spec.extraHosts }
13130
- });
13273
+ }), name);
13131
13274
  const stopLogStream = streamingEnabled ? streamLogs(containerId) : () => void 0;
13275
+ startedNotReady.add(containerId);
13132
13276
  try {
13133
13277
  await waitForRieReady(spec.containerHost, hostPort, 3e4);
13134
13278
  } catch (err) {
13135
13279
  stopLogStream();
13136
13280
  await removeContainer(containerId).catch(() => void 0);
13137
13281
  throw err;
13282
+ } finally {
13283
+ startedNotReady.delete(containerId);
13138
13284
  }
13139
13285
  return {
13140
13286
  logicalId: spec.lambda.logicalId,
@@ -13191,6 +13337,7 @@ function createContainerPool(specs, options) {
13191
13337
  }
13192
13338
  return {
13193
13339
  async acquire(logicalId) {
13340
+ if (disposed) throw new Error(`Container pool disposed; not starting ${displayIdent(logicalId)}.`);
13194
13341
  const entry = entries.get(logicalId);
13195
13342
  if (!entry) throw new Error(`containerPool.acquire: no spec registered for Lambda ${displayIdent(logicalId)}. This is a bug — every reachable route's Lambda should be registered at server boot.`);
13196
13343
  if (entry.warm.length > 0) {
@@ -13257,6 +13404,7 @@ function createContainerPool(specs, options) {
13257
13404
  return;
13258
13405
  }
13259
13406
  disposed = true;
13407
+ const pendingRuns = startGuard.stopAll();
13260
13408
  logger.debug("Disposing container pool");
13261
13409
  for (const entry of entries.values()) {
13262
13410
  if (entry.idleTimer) {
@@ -13318,10 +13466,14 @@ function createContainerPool(specs, options) {
13318
13466
  let timedOut = 0;
13319
13467
  for (const r of results) if (r.kind === "ok") allHandles.push(r.handle);
13320
13468
  else if (r.kind === "timeout") timedOut++;
13321
- if (timedOut > 0) logger.warn(`Container pool disposed with ${timedOut} in-flight start(s) still pending after ${drainTimeoutMs}ms; relying on docker --rm + the verify.sh sweep to clean up.`);
13469
+ if (timedOut > 0) logger.debug(`${timedOut} in-flight start(s) still pending after ${drainTimeoutMs}ms; removing them by id once their docker run returns.`);
13322
13470
  inFlightStarts.clear();
13323
13471
  }
13324
- await Promise.allSettled(allHandles.map((h) => tearDown(h)));
13472
+ const interruptedIds = [...await pendingRuns, ...startedNotReady];
13473
+ startedNotReady.clear();
13474
+ await Promise.allSettled([...allHandles.map((h) => tearDown(h)), ...interruptedIds.map((id) => removeContainer(id).catch((err) => {
13475
+ logger.warn(`Failed to remove container ${id}: ${err instanceof Error ? err.message : String(err)}. Continuing cleanup.`);
13476
+ }))]);
13325
13477
  entries.clear();
13326
13478
  }
13327
13479
  };
@@ -16255,6 +16407,21 @@ function formatServerListeningBanner(scheme, host, port, pathSuffix, label) {
16255
16407
  return `Server listening on ${scheme}://${formatAuthority(host, port)}${pathSuffix} (${label})\n`;
16256
16408
  }
16257
16409
  async function localStartApiCommand(targets, options, extraStateProviders) {
16410
+ let boot;
16411
+ try {
16412
+ await serveStartApi(targets, options, extraStateProviders, (b) => {
16413
+ boot = b;
16414
+ });
16415
+ } catch (err) {
16416
+ if (boot) {
16417
+ await boot.teardown().catch(() => void 0);
16418
+ if (boot.signalled()) await new Promise(() => void 0);
16419
+ boot.detachSignals();
16420
+ }
16421
+ throw err;
16422
+ }
16423
+ }
16424
+ async function serveStartApi(targets, options, extraStateProviders, registerBoot) {
16258
16425
  const logger = getLogger();
16259
16426
  if (options.verbose) logger.setLevel("debug");
16260
16427
  let apiFilters = [...targets];
@@ -16291,6 +16458,106 @@ async function localStartApiCommand(targets, options, extraStateProviders) {
16291
16458
  const inlineTmpDirs = /* @__PURE__ */ new Set();
16292
16459
  const layerTmpDirs = /* @__PURE__ */ new Set();
16293
16460
  let profileCredsFile;
16461
+ const servers = [];
16462
+ const wsServers = [];
16463
+ const bootPools = [];
16464
+ let watcher;
16465
+ let reloadQueue;
16466
+ let shuttingDown = false;
16467
+ let signalled = false;
16468
+ const runCleanup = singleFlight(async () => {
16469
+ shuttingDown = true;
16470
+ await stopWatchReloads({
16471
+ watcher,
16472
+ queue: reloadQueue,
16473
+ onWatcherCloseError: (err) => logger.warn(`watcher.close() failed: ${err instanceof Error ? err.message : String(err)}`)
16474
+ });
16475
+ await Promise.allSettled(wsServers.map(async (ws) => {
16476
+ try {
16477
+ await ws.attached.close();
16478
+ } catch (err) {
16479
+ logger.warn(`WebSocket close() failed for ${ws.api.apiLogicalId}: ${err instanceof Error ? err.message : String(err)}`);
16480
+ }
16481
+ }));
16482
+ await Promise.allSettled(servers.map(async ({ server, group }) => {
16483
+ try {
16484
+ await server.close();
16485
+ } catch (err) {
16486
+ logger.warn(`server.close() failed for ${group.displayName}: ${err instanceof Error ? err.message : String(err)}`);
16487
+ }
16488
+ }));
16489
+ await Promise.allSettled(wsServers.map(async (ws) => {
16490
+ try {
16491
+ await ws.server.close();
16492
+ } catch (err) {
16493
+ logger.warn(`WebSocket server.close() failed for ${ws.api.apiLogicalId}: ${err instanceof Error ? err.message : String(err)}`);
16494
+ }
16495
+ }));
16496
+ await Promise.allSettled(servers.map(async ({ server, group }) => {
16497
+ try {
16498
+ await server.getServerState().pool.dispose();
16499
+ } catch (err) {
16500
+ logger.warn(`pool.dispose() failed for ${group.displayName}: ${err instanceof Error ? err.message : String(err)}`);
16501
+ }
16502
+ }));
16503
+ await Promise.allSettled(wsServers.map(async (ws) => {
16504
+ try {
16505
+ await ws.server.getServerState().pool.dispose();
16506
+ } catch (err) {
16507
+ logger.warn(`WebSocket pool.dispose() failed for ${ws.api.apiLogicalId}: ${err instanceof Error ? err.message : String(err)}`);
16508
+ }
16509
+ }));
16510
+ await Promise.allSettled(bootPools.map(async (pool) => {
16511
+ try {
16512
+ await pool.dispose();
16513
+ } catch (err) {
16514
+ logger.warn(`pool.dispose() failed: ${err instanceof Error ? err.message : String(err)}`);
16515
+ }
16516
+ }));
16517
+ for (const dir of inlineTmpDirs) try {
16518
+ rmSync(dir, {
16519
+ recursive: true,
16520
+ force: true
16521
+ });
16522
+ } catch (err) {
16523
+ logger.warn(`Failed to remove inline-code tmpdir ${dir}: ${err instanceof Error ? err.message : String(err)}`);
16524
+ }
16525
+ for (const dir of layerTmpDirs) try {
16526
+ rmSync(dir, {
16527
+ recursive: true,
16528
+ force: true
16529
+ });
16530
+ } catch (err) {
16531
+ logger.warn(`Failed to remove merged-layers tmpdir ${dir}: ${err instanceof Error ? err.message : String(err)}`);
16532
+ }
16533
+ if (profileCredsFile) try {
16534
+ await profileCredsFile.dispose();
16535
+ } catch (err) {
16536
+ logger.warn(`Failed to remove profile credentials tmpdir ${profileCredsFile.hostPath}: ${err instanceof Error ? err.message : String(err)}`);
16537
+ }
16538
+ });
16539
+ const shutdown = createShutdownSignalHandler({
16540
+ cleanup: async () => {
16541
+ signalled = true;
16542
+ await runCleanup();
16543
+ },
16544
+ stoppingMessage: (signal) => `Received ${signal}, shutting down...`,
16545
+ forceExitHint: `Orphan containers may remain — run 'docker ps --filter name=${getEmbedConfig().resourceNamePrefix}-' and 'docker rm -f' to clean up.`,
16546
+ info: (m) => logger.info(m),
16547
+ warn: (m) => logger.warn(m)
16548
+ });
16549
+ const onSigint = () => shutdown("SIGINT");
16550
+ const onSigterm = () => shutdown("SIGTERM");
16551
+ process.on("SIGINT", onSigint);
16552
+ process.on("SIGTERM", onSigterm);
16553
+ registerBoot({
16554
+ teardown: runCleanup,
16555
+ detachSignals: () => {
16556
+ process.off("SIGINT", onSigint);
16557
+ process.off("SIGTERM", onSigterm);
16558
+ },
16559
+ signalled: () => signalled
16560
+ });
16294
16561
  const authorizerCache = createAuthorizerCache();
16295
16562
  const jwksCache = createJwksCache();
16296
16563
  const jwksWarnedAt = /* @__PURE__ */ new Map();
@@ -16412,6 +16679,7 @@ async function localStartApiCommand(targets, options, extraStateProviders) {
16412
16679
  };
16413
16680
  };
16414
16681
  const buildPool = (specs) => {
16682
+ if (shuttingDown) throw new CdkLocalError("Shutting down: no container pool is built.", "LOCAL_START_API_CANCELLED");
16415
16683
  const pool = createContainerPool(specs, {
16416
16684
  perLambdaConcurrency,
16417
16685
  skipPull: options.pull === false
@@ -16437,11 +16705,11 @@ async function localStartApiCommand(targets, options, extraStateProviders) {
16437
16705
  const mtlsConfig = resolveMtlsConfig(options);
16438
16706
  if (mtlsConfig) logger.info("mTLS enabled: client certificates required (chain check against --mtls-truststore at TLS handshake).");
16439
16707
  const initialGroups = groupRoutesByServer(initialMaterial.routes);
16440
- const servers = [];
16441
16708
  let nextPort = basePort;
16442
16709
  for (const group of initialGroups) {
16443
16710
  const groupSpecs = filterSpecsForGroup(group, initialMaterial.specs);
16444
16711
  const groupPool = buildPool(groupSpecs);
16712
+ bootPools.push(groupPool);
16445
16713
  const groupState = {
16446
16714
  routes: group.routes,
16447
16715
  pool: groupPool,
@@ -16450,6 +16718,7 @@ async function localStartApiCommand(targets, options, extraStateProviders) {
16450
16718
  if (options.warm) {
16451
16719
  logger.info(`Pre-warming ${groupSpecs.size} container(s) for ${group.displayName}...`);
16452
16720
  const handles = await Promise.allSettled([...groupSpecs.keys()].map((id) => groupPool.acquire(id)));
16721
+ if (shuttingDown) throw new CdkLocalError("Shutting down: the boot is not continued.", "LOCAL_START_API_CANCELLED");
16453
16722
  for (const result of handles) if (result.status === "fulfilled") groupPool.release(result.value);
16454
16723
  else logger.warn(`Pre-warm failed for one Lambda in ${group.displayName} (cold start cost will apply on first request): ${result.reason instanceof Error ? result.reason.message : String(result.reason)}`);
16455
16724
  }
@@ -16474,7 +16743,6 @@ async function localStartApiCommand(targets, options, extraStateProviders) {
16474
16743
  });
16475
16744
  if (basePort !== 0) nextPort += 1;
16476
16745
  }
16477
- const wsServers = [];
16478
16746
  const initialWsApis = initialMaterial.webSocketApis ?? [];
16479
16747
  warnUnsupportedWebSocketApis(initialWsApis, logger);
16480
16748
  if (initialWsApis.filter((api) => !api.unsupported).length > 0) {
@@ -16495,6 +16763,7 @@ async function localStartApiCommand(targets, options, extraStateProviders) {
16495
16763
  continue;
16496
16764
  }
16497
16765
  const wsPool = buildPool(wsSpecs);
16766
+ bootPools.push(wsPool);
16498
16767
  const wsState = {
16499
16768
  routes: [],
16500
16769
  pool: wsPool,
@@ -16562,8 +16831,6 @@ async function localStartApiCommand(targets, options, extraStateProviders) {
16562
16831
  process.stdout.write(formatServerListeningBanner(scheme, ws.server.host, ws.server.port, ws.apiPath, `${ws.api.apiLogicalId} (WebSocket API)`));
16563
16832
  }
16564
16833
  process.stdout.write("^C to stop and clean up containers.\n");
16565
- let watcher;
16566
- let reloadQueue;
16567
16834
  if (options.watch) {
16568
16835
  const watchRoot = process.cwd();
16569
16836
  const { ignored, shouldTrigger, excludePatterns } = createWatchPredicates({
@@ -16593,82 +16860,6 @@ async function localStartApiCommand(targets, options, extraStateProviders) {
16593
16860
  });
16594
16861
  logger.info(`Watching ${watchRoot} for source changes (excluding ${excludePatterns.join(", ")}).`);
16595
16862
  }
16596
- const runCleanup = singleFlight(async () => {
16597
- await stopWatchReloads({
16598
- watcher,
16599
- queue: reloadQueue,
16600
- onWatcherCloseError: (err) => logger.warn(`watcher.close() failed: ${err instanceof Error ? err.message : String(err)}`)
16601
- });
16602
- await Promise.allSettled(wsServers.map(async (ws) => {
16603
- try {
16604
- await ws.attached.close();
16605
- } catch (err) {
16606
- logger.warn(`WebSocket close() failed for ${ws.api.apiLogicalId}: ${err instanceof Error ? err.message : String(err)}`);
16607
- }
16608
- }));
16609
- await Promise.allSettled(servers.map(async ({ server, group }) => {
16610
- try {
16611
- await server.close();
16612
- } catch (err) {
16613
- logger.warn(`server.close() failed for ${group.displayName}: ${err instanceof Error ? err.message : String(err)}`);
16614
- }
16615
- }));
16616
- await Promise.allSettled(wsServers.map(async (ws) => {
16617
- try {
16618
- await ws.server.close();
16619
- } catch (err) {
16620
- logger.warn(`WebSocket server.close() failed for ${ws.api.apiLogicalId}: ${err instanceof Error ? err.message : String(err)}`);
16621
- }
16622
- }));
16623
- await Promise.allSettled(servers.map(async ({ server, group }) => {
16624
- try {
16625
- await server.getServerState().pool.dispose();
16626
- } catch (err) {
16627
- logger.warn(`pool.dispose() failed for ${group.displayName}: ${err instanceof Error ? err.message : String(err)}`);
16628
- }
16629
- }));
16630
- await Promise.allSettled(wsServers.map(async (ws) => {
16631
- try {
16632
- await ws.server.getServerState().pool.dispose();
16633
- } catch (err) {
16634
- logger.warn(`WebSocket pool.dispose() failed for ${ws.api.apiLogicalId}: ${err instanceof Error ? err.message : String(err)}`);
16635
- }
16636
- }));
16637
- for (const dir of inlineTmpDirs) try {
16638
- rmSync(dir, {
16639
- recursive: true,
16640
- force: true
16641
- });
16642
- } catch (err) {
16643
- logger.warn(`Failed to remove inline-code tmpdir ${dir}: ${err instanceof Error ? err.message : String(err)}`);
16644
- }
16645
- for (const dir of layerTmpDirs) try {
16646
- rmSync(dir, {
16647
- recursive: true,
16648
- force: true
16649
- });
16650
- } catch (err) {
16651
- logger.warn(`Failed to remove merged-layers tmpdir ${dir}: ${err instanceof Error ? err.message : String(err)}`);
16652
- }
16653
- if (profileCredsFile) try {
16654
- await profileCredsFile.dispose();
16655
- } catch (err) {
16656
- logger.warn(`Failed to remove profile credentials tmpdir ${profileCredsFile.hostPath}: ${err instanceof Error ? err.message : String(err)}`);
16657
- }
16658
- });
16659
- const shutdown = createShutdownSignalHandler({
16660
- cleanup: runCleanup,
16661
- stoppingMessage: (signal) => `Received ${signal}, shutting down...`,
16662
- forceExitHint: `Orphan containers may remain — run 'docker ps --filter name=${getEmbedConfig().resourceNamePrefix}-' and 'docker rm -f' to clean up.`,
16663
- info: (m) => logger.info(m),
16664
- warn: (m) => logger.warn(m)
16665
- });
16666
- process.on("SIGINT", () => {
16667
- shutdown("SIGINT");
16668
- });
16669
- process.on("SIGTERM", () => {
16670
- shutdown("SIGTERM");
16671
- });
16672
16863
  process.on("uncaughtException", (err) => {
16673
16864
  logger.error(`Uncaught exception: ${err instanceof Error ? err.stack ?? err.message : String(err)}`);
16674
16865
  shutdown("uncaughtException", 1);
@@ -18381,7 +18572,9 @@ async function localInvokeAgentCoreCommand(target, options, extraStateProviders)
18381
18572
  let profileCredsFile;
18382
18573
  let stateProvider;
18383
18574
  let stopWatch;
18575
+ const startGuard = createContainerStartGuard({ cancelledCode: "LOCAL_INVOKE_AGENTCORE_CANCELLED" });
18384
18576
  const cleanup = singleFlight(async () => {
18577
+ const pendingContainer = startGuard.stop();
18385
18578
  if (stopWatch) await stopWatch();
18386
18579
  if (stateProvider) try {
18387
18580
  stateProvider.dispose();
@@ -18393,6 +18586,7 @@ async function localInvokeAgentCoreCommand(target, options, extraStateProviders)
18393
18586
  } catch (err) {
18394
18587
  getLogger().debug(`streamLogs stop failed: ${err instanceof Error ? err.message : String(err)}`);
18395
18588
  }
18589
+ containerId ??= await pendingContainer;
18396
18590
  if (containerId) try {
18397
18591
  await removeContainer(containerId);
18398
18592
  } catch (err) {
@@ -18406,6 +18600,17 @@ async function localInvokeAgentCoreCommand(target, options, extraStateProviders)
18406
18600
  }, (err) => {
18407
18601
  getLogger().debug(`cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
18408
18602
  });
18603
+ const onSignal = createShutdownSignalHandler({
18604
+ cleanup,
18605
+ stoppingMessage: (signal) => `Received ${signal}, removing the agent container...`,
18606
+ forceExitHint: `Run 'docker ps -a --filter name=${getEmbedConfig().resourceNamePrefix}-' to find what is left.`,
18607
+ info: (m) => logger.info(m),
18608
+ warn: (m) => logger.warn(m)
18609
+ });
18610
+ sigintHandler = () => onSignal("SIGINT");
18611
+ sigtermHandler = () => onSignal("SIGTERM");
18612
+ process.on("SIGINT", sigintHandler);
18613
+ process.on("SIGTERM", sigtermHandler);
18409
18614
  try {
18410
18615
  await activateWorkloadAwsWiring({
18411
18616
  ...options,
@@ -18485,7 +18690,7 @@ async function localInvokeAgentCoreCommand(target, options, extraStateProviders)
18485
18690
  const containerPort = isMcp ? MCP_CONTAINER_PORT : isA2a ? A2A_CONTAINER_PORT : void 0;
18486
18691
  const containerPortLabel = isMcp ? `${MCP_CONTAINER_PORT}${MCP_PATH}` : isA2a ? `${A2A_CONTAINER_PORT}${"/"}` : "8080";
18487
18692
  logger.info(`Starting agent container (image=${image}, port=${hostPort} -> ${containerPortLabel})...`);
18488
- containerId = await runDetached({
18693
+ containerId = await startGuard.run(() => runDetached({
18489
18694
  image,
18490
18695
  mounts: [],
18491
18696
  env: dockerEnv,
@@ -18496,19 +18701,8 @@ async function localInvokeAgentCoreCommand(target, options, extraStateProviders)
18496
18701
  name: containerName,
18497
18702
  ...containerPort !== void 0 && { containerPort },
18498
18703
  ...sensitiveEnvKeys.size > 0 && { sensitiveEnvKeys }
18499
- });
18704
+ }), containerName);
18500
18705
  stopLogs = streamLogs(containerId);
18501
- const onSignal = createShutdownSignalHandler({
18502
- cleanup,
18503
- stoppingMessage: (signal) => `Received ${signal}, removing the agent container...`,
18504
- forceExitHint: `Run 'docker ps -a --filter name=${getEmbedConfig().resourceNamePrefix}-' to find what is left.`,
18505
- info: (m) => logger.info(m),
18506
- warn: (m) => logger.warn(m)
18507
- });
18508
- sigintHandler = () => onSignal("SIGINT");
18509
- sigtermHandler = () => onSignal("SIGTERM");
18510
- process.on("SIGINT", sigintHandler);
18511
- process.on("SIGTERM", sigtermHandler);
18512
18706
  if (isMcp && mcpRequest) {
18513
18707
  logger.info(`MCP request: ${mcpRequest.method}`);
18514
18708
  const mcp = await mcpInvokeOnce(containerHost, hostPort, mcpRequest, { requestTimeoutMs: options.timeout });
@@ -23430,8 +23624,32 @@ function createFrontDoorLambdaRunner(lambda, opts) {
23430
23624
  let stopLogStream;
23431
23625
  let starting;
23432
23626
  let stopped = false;
23627
+ const startGuard = createContainerStartGuard({ cancelledCode: "FRONT_DOOR_LAMBDA_STOPPED" });
23628
+ function removePlanTmpDirs(p) {
23629
+ if (p?.inlineTmpDir) try {
23630
+ rmSync(p.inlineTmpDir, {
23631
+ recursive: true,
23632
+ force: true
23633
+ });
23634
+ } catch (err) {
23635
+ logger.debug(`Failed to remove inline-code tmpdir ${p.inlineTmpDir}: ${err instanceof Error ? err.message : String(err)}`);
23636
+ }
23637
+ if (p?.assetTmpDir) try {
23638
+ rmSync(p.assetTmpDir, {
23639
+ recursive: true,
23640
+ force: true
23641
+ });
23642
+ } catch (err) {
23643
+ logger.debug(`Failed to remove zip-asset tmpdir ${p.assetTmpDir}: ${err instanceof Error ? err.message : String(err)}`);
23644
+ }
23645
+ }
23433
23646
  async function doStart() {
23434
- plan = lambda.kind === "zip" ? await resolveZipImagePlan(lambda, opts) : await resolveContainerImagePlan(lambda, opts);
23647
+ const resolved = lambda.kind === "zip" ? await resolveZipImagePlan(lambda, opts) : await resolveContainerImagePlan(lambda, opts);
23648
+ if (stopped) {
23649
+ removePlanTmpDirs(resolved);
23650
+ throw new Error("FrontDoorLambdaRunner stopped while starting");
23651
+ }
23652
+ plan = resolved;
23435
23653
  const port = await pickFreePort();
23436
23654
  hostPort = port;
23437
23655
  const name = `${getEmbedConfig().resourceNamePrefix}-alblambda-${lambda.logicalId}-${process.pid}-${Math.floor(Math.random() * 1e6)}`;
@@ -23444,20 +23662,20 @@ function createFrontDoorLambdaRunner(lambda, opts) {
23444
23662
  AWS_LAMBDA_LOG_STREAM_NAME: "local",
23445
23663
  ...forwardAwsEnv()
23446
23664
  };
23447
- logger.info(`Starting Lambda target container for ${lambda.logicalId} (image=${plan.image}, port=${port})...`);
23448
- const id = await runDetached({
23449
- image: plan.image,
23450
- mounts: plan.mounts,
23665
+ logger.info(`Starting Lambda target container for ${lambda.logicalId} (image=${resolved.image}, port=${port})...`);
23666
+ const id = await startGuard.run(() => runDetached({
23667
+ image: resolved.image,
23668
+ mounts: resolved.mounts,
23451
23669
  env,
23452
23670
  ...opts.sensitiveEnvKeys && opts.sensitiveEnvKeys.size > 0 && { sensitiveEnvKeys: opts.sensitiveEnvKeys },
23453
- cmd: plan.cmd,
23671
+ cmd: resolved.cmd,
23454
23672
  hostPort: port,
23455
23673
  host: opts.containerHost,
23456
23674
  name,
23457
- ...plan.platform !== void 0 && { platform: plan.platform },
23458
- ...plan.entryPoint !== void 0 && { entryPoint: plan.entryPoint },
23459
- ...plan.workingDir !== void 0 && { workingDir: plan.workingDir }
23460
- });
23675
+ ...resolved.platform !== void 0 && { platform: resolved.platform },
23676
+ ...resolved.entryPoint !== void 0 && { entryPoint: resolved.entryPoint },
23677
+ ...resolved.workingDir !== void 0 && { workingDir: resolved.workingDir }
23678
+ }), name);
23461
23679
  containerId = id;
23462
23680
  stopLogStream = opts.streamLogs === false ? void 0 : streamLogs(id);
23463
23681
  try {
@@ -23486,11 +23704,14 @@ function createFrontDoorLambdaRunner(lambda, opts) {
23486
23704
  async stop() {
23487
23705
  if (stopped) return;
23488
23706
  stopped = true;
23707
+ const pendingContainer = startGuard.stop();
23489
23708
  try {
23490
23709
  stopLogStream?.();
23491
23710
  } catch (err) {
23492
23711
  logger.debug(`stopLogStream(${displayIdent(lambda.logicalId)}) failed: ${err instanceof Error ? err.message : String(err)}`);
23493
23712
  }
23713
+ const pendingId = await pendingContainer;
23714
+ containerId ??= pendingId;
23494
23715
  if (containerId) {
23495
23716
  try {
23496
23717
  await removeContainer(containerId);
@@ -23499,22 +23720,7 @@ function createFrontDoorLambdaRunner(lambda, opts) {
23499
23720
  }
23500
23721
  containerId = void 0;
23501
23722
  }
23502
- if (plan?.inlineTmpDir) try {
23503
- rmSync(plan.inlineTmpDir, {
23504
- recursive: true,
23505
- force: true
23506
- });
23507
- } catch (err) {
23508
- logger.debug(`Failed to remove inline-code tmpdir ${plan.inlineTmpDir}: ${err instanceof Error ? err.message : String(err)}`);
23509
- }
23510
- if (plan?.assetTmpDir) try {
23511
- rmSync(plan.assetTmpDir, {
23512
- recursive: true,
23513
- force: true
23514
- });
23515
- } catch (err) {
23516
- logger.debug(`Failed to remove zip-asset tmpdir ${plan.assetTmpDir}: ${err instanceof Error ? err.message : String(err)}`);
23517
- }
23723
+ removePlanTmpDirs(plan);
23518
23724
  }
23519
23725
  };
23520
23726
  }
@@ -24141,7 +24347,14 @@ async function runEcsServiceEmulator(targets, options, strategy, extraStateProvi
24141
24347
  let frontDoorLambdaRunners = [];
24142
24348
  let watcher;
24143
24349
  let reloadQueue;
24350
+ let sharedNetworkPending;
24351
+ let signalled = false;
24352
+ let stopping = false;
24353
+ const throwIfStopping = () => {
24354
+ if (stopping) throw new LocalStartServiceError("Shutting down: the boot is not continued.");
24355
+ };
24144
24356
  const cleanup = singleFlight(async () => {
24357
+ stopping = true;
24145
24358
  await stopWatchReloads({
24146
24359
  watcher,
24147
24360
  queue: reloadQueue,
@@ -24159,6 +24372,9 @@ async function runEcsServiceEmulator(targets, options, strategy, extraStateProvi
24159
24372
  frontDoorServers = [];
24160
24373
  await Promise.allSettled(frontDoorLambdaRunners.map((r) => r.stop().catch((err) => getLogger().warn(`front-door Lambda target teardown failed: ${err instanceof Error ? err.message : String(err)}`))));
24161
24374
  frontDoorLambdaRunners = [];
24375
+ const pendingNetwork = await sharedNetworkPending;
24376
+ sharedNetwork ??= pendingNetwork;
24377
+ sharedNetworkPending = void 0;
24162
24378
  if (profileCredsFile) {
24163
24379
  try {
24164
24380
  await profileCredsFile.dispose();
@@ -24177,6 +24393,20 @@ async function runEcsServiceEmulator(targets, options, strategy, extraStateProvi
24177
24393
  }
24178
24394
  }, (err) => getLogger().warn(`service cleanup failed: ${err instanceof Error ? err.message : String(err)}`));
24179
24395
  try {
24396
+ const onSignal = createShutdownSignalHandler({
24397
+ cleanup: async () => {
24398
+ signalled = true;
24399
+ await cleanup();
24400
+ },
24401
+ stoppingMessage: () => "Stopping service(s)...",
24402
+ forceExitHint: `Run 'docker ps -a --filter name=${getEmbedConfig().resourceNamePrefix}-' and 'docker network ls --filter name=${getEmbedConfig().resourceNamePrefix}-' to find what is left.`,
24403
+ info: (m) => logger.info(m),
24404
+ warn: (m) => logger.warn(m)
24405
+ });
24406
+ sigintHandler = () => onSignal("SIGINT");
24407
+ sigtermHandler = () => onSignal("SIGTERM");
24408
+ process.on("SIGINT", sigintHandler);
24409
+ process.on("SIGTERM", sigtermHandler);
24180
24410
  await activateWorkloadAwsWiring(options);
24181
24411
  warnIfEmulateRoleViaUnused(options.emulateRoleVia, {
24182
24412
  roleFlag: "--assume-role",
@@ -24227,16 +24457,20 @@ async function runEcsServiceEmulator(targets, options, strategy, extraStateProvi
24227
24457
  const taskRoleMode = isTaskRoleInEffect(options);
24228
24458
  const sidecarCredentials = taskRoleMode ? void 0 : await resolveSharedSidecarCredentials(options);
24229
24459
  try {
24230
- sharedNetwork = await createSharedSvcNetwork({
24460
+ const creating = createSharedSvcNetwork({
24231
24461
  prefix: options.cluster,
24232
24462
  skipPull,
24233
24463
  cluster: options.cluster,
24234
24464
  ...taskRoleMode && { taskRole: true },
24235
24465
  ...sidecarCredentials !== void 0 && { credentials: sidecarCredentials }
24236
24466
  });
24467
+ sharedNetworkPending = creating.catch(() => void 0);
24468
+ sharedNetwork = await creating;
24469
+ sharedNetworkPending = void 0;
24237
24470
  } catch (err) {
24238
24471
  throw new LocalStartServiceError(`Failed to create shared service network: ${err instanceof Error ? err.message : String(err)}`);
24239
24472
  }
24473
+ throwIfStopping();
24240
24474
  if (options.profile && sidecarCredentials) profileCredsFile = await writeProfileCredentialsFile(options.profile, sidecarCredentials);
24241
24475
  const discovery = {
24242
24476
  registry,
@@ -24244,22 +24478,13 @@ async function runEcsServiceEmulator(targets, options, strategy, extraStateProvi
24244
24478
  sharedNetwork
24245
24479
  };
24246
24480
  if (frontDoor && frontDoor.listeners.length > 0) {
24247
- const built = await buildFrontDoor(frontDoor, options, logger, extraStateProviders);
24481
+ const built = await buildFrontDoor(frontDoor, options, logger, extraStateProviders, (r) => {
24482
+ frontDoorLambdaRunners.push(r);
24483
+ if (stopping) r.stop().catch(() => void 0);
24484
+ });
24248
24485
  frontDoorServers = built.servers;
24249
24486
  frontDoorByService = built.frontDoorByService;
24250
- frontDoorLambdaRunners = built.lambdaRunners;
24251
24487
  }
24252
- const onSignal = createShutdownSignalHandler({
24253
- cleanup,
24254
- stoppingMessage: () => "Stopping service(s)...",
24255
- forceExitHint: `Run 'docker ps -a --filter name=${getEmbedConfig().resourceNamePrefix}-' and 'docker network ls --filter name=${getEmbedConfig().resourceNamePrefix}-' to find what is left.`,
24256
- info: (m) => logger.info(m),
24257
- warn: (m) => logger.warn(m)
24258
- });
24259
- sigintHandler = () => onSignal("SIGINT");
24260
- sigtermHandler = () => onSignal("SIGTERM");
24261
- process.on("SIGINT", sigintHandler);
24262
- process.on("SIGTERM", sigtermHandler);
24263
24488
  const { tags: imageOverrideTags, overrides: imageOverrideMap } = await resolveAndBuildImageOverrides({
24264
24489
  perTarget: perTarget.map((pt) => pt.boot.target),
24265
24490
  stacks,
@@ -24267,7 +24492,10 @@ async function runEcsServiceEmulator(targets, options, strategy, extraStateProvi
24267
24492
  extraStateProviders,
24268
24493
  logger
24269
24494
  });
24270
- for (const pt of perTarget) pt.controller = await bootOneTarget(pt.boot, pt.runState, stacks, options, discovery, skipPull, extraStateProviders, profileCredsFile, frontDoorByService.get(pt.boot.target), strategy.suppressLoadBalancerWarning === true, imageOverrideTags.get(pt.boot.target));
24495
+ for (const pt of perTarget) {
24496
+ throwIfStopping();
24497
+ pt.controller = await bootOneTarget(pt.boot, pt.runState, stacks, options, discovery, skipPull, extraStateProviders, profileCredsFile, frontDoorByService.get(pt.boot.target), strategy.suppressLoadBalancerWarning === true, imageOverrideTags.get(pt.boot.target));
24498
+ }
24271
24499
  if (perTarget.length > 0) {
24272
24500
  const summary = perTarget.map((pt) => `${pt.controller.service.serviceName} (${pt.controller.activeReplicaCount()} replica(s))`).join(", ");
24273
24501
  logger.info(`Service(s) running: ${summary}.`);
@@ -24331,6 +24559,7 @@ async function runEcsServiceEmulator(targets, options, strategy, extraStateProvi
24331
24559
  await new Promise(() => {});
24332
24560
  } finally {
24333
24561
  await cleanup();
24562
+ if (signalled) await new Promise(() => void 0);
24334
24563
  if (sigintHandler) process.off("SIGINT", sigintHandler);
24335
24564
  if (sigtermHandler) process.off("SIGTERM", sigtermHandler);
24336
24565
  }
@@ -24692,7 +24921,7 @@ async function resolveAlbLambdaTargetEnv(plan, options, extraStateProviders) {
24692
24921
  for (const [logicalId, lambda] of lambdas) out.set(logicalId, await resolveLambdaContainerEnv(lambda, envOptions, profileCredentials, extraStateProviders));
24693
24922
  return out;
24694
24923
  }
24695
- async function buildFrontDoor(plan, options, logger, extraStateProviders) {
24924
+ async function buildFrontDoor(plan, options, logger, extraStateProviders, onLambdaRunner) {
24696
24925
  const containerHost = options.containerHost;
24697
24926
  const servers = [];
24698
24927
  const poolRegistry = /* @__PURE__ */ new Map();
@@ -24713,6 +24942,7 @@ async function buildFrontDoor(plan, options, logger, extraStateProviders) {
24713
24942
  ...containerEnv !== void 0 && containerEnv.sensitiveEnvKeys.length > 0 && { sensitiveEnvKeys: new Set(containerEnv.sensitiveEnvKeys) }
24714
24943
  });
24715
24944
  lambdaRegistry.set(t.lambda.logicalId, runner);
24945
+ onLambdaRunner?.(runner);
24716
24946
  }
24717
24947
  const boundRunner = runner;
24718
24948
  return {
@@ -29344,6 +29574,7 @@ async function bootLambdaUrlOrigins(distribution, stacks, opts) {
29344
29574
  containerEnv: containerEnv.env,
29345
29575
  ...containerEnv.sensitiveEnvKeys.length > 0 && { sensitiveEnvKeys: new Set(containerEnv.sensitiveEnvKeys) }
29346
29576
  });
29577
+ opts.runnerSink?.push(runner);
29347
29578
  logger.info(`Booting Lambda Function URL origin container for ${functionLogicalId} (the backing Lambda runs locally via RIE)...`);
29348
29579
  await runner.start();
29349
29580
  } catch (err) {
@@ -29366,6 +29597,14 @@ async function drainWebFunctionServes(serves) {
29366
29597
  await Promise.all(batch.map((s) => s.teardown().catch(() => void 0)));
29367
29598
  }
29368
29599
  }
29600
+ async function drainLambdaRunners(runners) {
29601
+ let done = 0;
29602
+ while (done < runners.length) {
29603
+ const batch = runners.slice(done);
29604
+ done = runners.length;
29605
+ await Promise.all(batch.map((r) => r.stop().catch(() => void 0)));
29606
+ }
29607
+ }
29369
29608
  const WEB_FUNCTION_ORIGIN_READY_TIMEOUT_MS = 6e4;
29370
29609
  async function bootWebFunctionOrigins(distribution, stacks, opts) {
29371
29610
  const logger = getLogger();
@@ -29434,6 +29673,7 @@ async function bootLambdaEdgeFunctions(distribution, stacks, opts) {
29434
29673
  containerEnv: containerEnv.env,
29435
29674
  ...containerEnv.sensitiveEnvKeys.length > 0 && { sensitiveEnvKeys: new Set(containerEnv.sensitiveEnvKeys) }
29436
29675
  });
29676
+ opts.runnerSink?.push(runner);
29437
29677
  logger.info(`Booting Lambda@Edge container for ${functionLogicalId} (the function runs locally via RIE)...`);
29438
29678
  await runner.start();
29439
29679
  runners.push(runner);
@@ -29610,12 +29850,13 @@ async function localStartCloudFrontCommand(target, options, extraStateProviders,
29610
29850
  await attachKvsModules(initial.distribution, initial.stacks, options, profileCredentials, logger, extraStateProviders);
29611
29851
  const bootOpts = buildLambdaBootOptions(options, profileCredentials, extraStateProviders);
29612
29852
  const webFunctionServes = [];
29853
+ const bootRunners = [];
29613
29854
  let bootAborted = false;
29614
29855
  const onBootSignal = (signal) => {
29615
29856
  if (bootAborted) return;
29616
29857
  bootAborted = true;
29617
- logger.info(`Received ${signal} during start-up; removing the web function containers...`);
29618
- drainWebFunctionServes(webFunctionServes).then(() => process.exit(signalExitCode(signal)));
29858
+ logger.info(`Received ${signal} during start-up; removing the web function containers and the Lambda containers started so far...`);
29859
+ Promise.all([drainWebFunctionServes(webFunctionServes), drainLambdaRunners(bootRunners)]).then(() => process.exit(signalExitCode(signal)));
29619
29860
  };
29620
29861
  const bootSigint = () => onBootSignal("SIGINT");
29621
29862
  const bootSigterm = () => onBootSignal("SIGTERM");
@@ -29623,14 +29864,18 @@ async function localStartCloudFrontCommand(target, options, extraStateProviders,
29623
29864
  process.off("SIGINT", bootSigint);
29624
29865
  process.off("SIGTERM", bootSigterm);
29625
29866
  };
29626
- if ([...initial.distribution.origins.values()].some((o) => o.kind === "web-function")) {
29627
- process.on("SIGINT", bootSigint);
29628
- process.on("SIGTERM", bootSigterm);
29629
- }
29630
- const { invokers: lambdaInvokers, runners: lambdaRunners } = await bootLambdaUrlOrigins(initial.distribution, initial.stacks, bootOpts);
29631
- const { invokers: edgeInvokers, runners: edgeRunners } = await bootLambdaEdgeFunctions(initial.distribution, initial.stacks, bootOpts);
29867
+ process.on("SIGINT", bootSigint);
29868
+ process.on("SIGTERM", bootSigterm);
29632
29869
  let server;
29633
29870
  try {
29871
+ const { invokers: lambdaInvokers } = await bootLambdaUrlOrigins(initial.distribution, initial.stacks, {
29872
+ ...bootOpts,
29873
+ runnerSink: bootRunners
29874
+ });
29875
+ const { invokers: edgeInvokers } = await bootLambdaEdgeFunctions(initial.distribution, initial.stacks, {
29876
+ ...bootOpts,
29877
+ runnerSink: bootRunners
29878
+ });
29634
29879
  const webFunctions = await bootWebFunctionOrigins(initial.distribution, initial.stacks, {
29635
29880
  ...bootOpts,
29636
29881
  sink: webFunctionServes
@@ -29651,7 +29896,7 @@ async function localStartCloudFrontCommand(target, options, extraStateProviders,
29651
29896
  ...webFunctions.targets.size > 0 && { webFunctionOrigins: webFunctions.targets }
29652
29897
  });
29653
29898
  } catch (err) {
29654
- await Promise.all([...[...lambdaRunners, ...edgeRunners].map((r) => r.stop().catch(() => void 0)), ...webFunctionServes.map((s) => s.teardown().catch(() => void 0))]);
29899
+ await Promise.all([...bootRunners.map((r) => r.stop().catch(() => void 0)), ...webFunctionServes.map((s) => s.teardown().catch(() => void 0))]);
29655
29900
  if (bootAborted) return await new Promise(() => void 0);
29656
29901
  disarmBootSignals();
29657
29902
  throw err;
@@ -29703,7 +29948,7 @@ async function localStartCloudFrontCommand(target, options, extraStateProviders,
29703
29948
  try {
29704
29949
  await server.close();
29705
29950
  } catch {}
29706
- await Promise.all([...[...lambdaRunners, ...edgeRunners].map((r) => r.stop().catch((err) => {
29951
+ await Promise.all([...bootRunners.map((r) => r.stop().catch((err) => {
29707
29952
  logger.debug(`Lambda runner stop failed: ${err instanceof Error ? err.message : String(err)}`);
29708
29953
  })), ...webFunctionServes.map((s) => s.teardown().catch((err) => {
29709
29954
  logger.debug(`Web function server teardown failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -30077,6 +30322,21 @@ function resolveAgentCoreServePlan(protocol) {
30077
30322
  };
30078
30323
  }
30079
30324
  async function localStartAgentCoreCommand(target, options, extraStateProviders, hostSynthesizer) {
30325
+ let boot;
30326
+ try {
30327
+ await serveAgentCore(target, options, extraStateProviders, hostSynthesizer, (b) => {
30328
+ boot = b;
30329
+ });
30330
+ } catch (err) {
30331
+ if (boot) {
30332
+ await boot.teardown().catch(() => void 0);
30333
+ if (boot.signalled()) await new Promise(() => void 0);
30334
+ boot.detachSignals();
30335
+ }
30336
+ throw err;
30337
+ }
30338
+ }
30339
+ async function serveAgentCore(target, options, extraStateProviders, hostSynthesizer, registerBoot) {
30080
30340
  const logger = getLogger();
30081
30341
  if (options.verbose) logger.setLevel("debug");
30082
30342
  let containerId;
@@ -30088,9 +30348,12 @@ async function localStartAgentCoreCommand(target, options, extraStateProviders,
30088
30348
  let reloadQueue;
30089
30349
  let shuttingDown = false;
30090
30350
  let tornDown = false;
30091
- const teardown = async () => {
30092
- if (tornDown) return;
30351
+ const startGuard = createContainerStartGuard({ cancelledCode: "LOCAL_START_AGENTCORE_CANCELLED" });
30352
+ let teardownPromise;
30353
+ const teardown = () => teardownPromise ??= doTeardown();
30354
+ const doTeardown = async () => {
30093
30355
  tornDown = true;
30356
+ const pendingContainer = startGuard.stop();
30094
30357
  await stopWatchReloads({
30095
30358
  watcher,
30096
30359
  queue: reloadQueue,
@@ -30106,6 +30369,7 @@ async function localStartAgentCoreCommand(target, options, extraStateProviders,
30106
30369
  } catch (err) {
30107
30370
  logger.debug(`streamLogs stop failed: ${err instanceof Error ? err.message : String(err)}`);
30108
30371
  }
30372
+ containerId ??= await pendingContainer;
30109
30373
  if (containerId) try {
30110
30374
  await removeContainer(containerId);
30111
30375
  } catch (err) {
@@ -30118,6 +30382,28 @@ async function localStartAgentCoreCommand(target, options, extraStateProviders,
30118
30382
  await profileCredsFile.dispose();
30119
30383
  } catch {}
30120
30384
  };
30385
+ const shutdown = createShutdownSignalHandler({
30386
+ cleanup: async () => {
30387
+ shuttingDown = true;
30388
+ await teardown().catch(() => void 0);
30389
+ },
30390
+ stoppingMessage: (signal) => `Received ${signal}, shutting down...`,
30391
+ forceExitHint: `Run 'docker ps -a --filter name=${getEmbedConfig().resourceNamePrefix}-' to find what is left.`,
30392
+ info: (m) => logger.info(m),
30393
+ warn: (m) => logger.warn(m)
30394
+ });
30395
+ const onSigint = () => shutdown("SIGINT");
30396
+ const onSigterm = () => shutdown("SIGTERM");
30397
+ process.on("SIGINT", onSigint);
30398
+ process.on("SIGTERM", onSigterm);
30399
+ registerBoot({
30400
+ teardown,
30401
+ detachSignals: () => {
30402
+ process.off("SIGINT", onSigint);
30403
+ process.off("SIGTERM", onSigterm);
30404
+ },
30405
+ signalled: () => shuttingDown
30406
+ });
30121
30407
  await activateWorkloadAwsWiring(options);
30122
30408
  warnIfEmulateRoleViaUnused(options.emulateRoleVia, {
30123
30409
  roleFlag: "--assume-role",
@@ -30171,31 +30457,20 @@ async function localStartAgentCoreCommand(target, options, extraStateProviders,
30171
30457
  const containerHost = options.containerHost;
30172
30458
  const containerName = `${getEmbedConfig().resourceNamePrefix}-agentcore-${process.pid}-${Math.random().toString(36).slice(2, 8)}`;
30173
30459
  logger.info(`Starting agent container (image=${image}, port=${containerHostPort} -> ${plan.containerPortLabel})...`);
30174
- containerId = await runDetached({
30460
+ const bootPort = containerHostPort;
30461
+ containerId = await startGuard.run(() => runDetached({
30175
30462
  image,
30176
30463
  mounts: [],
30177
30464
  env: dockerEnv,
30178
30465
  cmd: [],
30179
- hostPort: containerHostPort,
30466
+ hostPort: bootPort,
30180
30467
  host: containerHost,
30181
30468
  platform: options.platform,
30182
30469
  name: containerName,
30183
30470
  ...plan.containerPort !== void 0 && { containerPort: plan.containerPort },
30184
30471
  ...sensitiveEnvKeys.size > 0 && { sensitiveEnvKeys }
30185
- });
30472
+ }), containerName);
30186
30473
  stopLogs = streamLogs(containerId);
30187
- const shutdown = createShutdownSignalHandler({
30188
- cleanup: async () => {
30189
- shuttingDown = true;
30190
- await teardown().catch(() => void 0);
30191
- },
30192
- stoppingMessage: (signal) => `Received ${signal}, shutting down...`,
30193
- forceExitHint: `Run 'docker ps -a --filter name=${getEmbedConfig().resourceNamePrefix}-' to find what is left.`,
30194
- info: (m) => logger.info(m),
30195
- warn: (m) => logger.warn(m)
30196
- });
30197
- process.on("SIGINT", () => shutdown("SIGINT"));
30198
- process.on("SIGTERM", () => shutdown("SIGTERM"));
30199
30474
  try {
30200
30475
  if (plan.readyPath === void 0) await waitForAgentCorePing(containerHost, containerHostPort, options.timeout);
30201
30476
  else await waitForAgentCoreHttpReady(containerHost, containerHostPort, plan.readyPath, options.timeout);
@@ -37022,4 +37297,4 @@ function addStudioSpecificOptions(cmd) {
37022
37297
  }
37023
37298
 
37024
37299
  export { postHook as $, AGENTCORE_A2A_PROTOCOL as $a, probeHostGatewaySupport as $i, addImageOverrideOptions as $n, loopbackForwarderPlan as $o, resolveApiTargetSubset as $r, classifyS3Error as $t, microvmFidelityWarnings as A, createLocalStateProvider as Aa, translateLambdaResponse as Ai, stripCloudFrontImport as An, readEnvCallerCredentials as Ao, A2A_CONTAINER_PORT as Ar, readContainerLogTail as At, MICROVM_WS_BASE_PROTOCOL as B, resolveWatchConfig as Ba, ConnectionRegistry as Bi, createLocalStartAlbCommand as Bn, HOST_DEFAULT_CREDENTIALS_MISS_TTL_MS as Bo, AGENTCORE_SESSION_ID_HEADER as Br, parseWebFunctionBuildConfig as Bt, addListSpecificOptions as C, substituteAgainstState as Ca, attachAuthorizers as Ci, WEB_FUNCTION_REVISION_TYPE as Cn, resolveDynamicReferencesInEnv as Co, setShadowReadyTimeoutMs as Cr, parseKvsFileOverrides as Ct, buildMicrovmLambdaView as D, materializeLayerFromArn as Da, isFunctionUrlOacFronted as Di, compileCloudFrontFunction as Dn, SECOND_ASSUME_MESSAGE as Do, createLocalInvokeAgentCoreCommand as Dr, WEB_FUNCTION_CONTAINER_PORT as Dt, addStartMicrovmSpecificOptions as E, substituteEnvVarsFromStateAsync as Ea, buildCorsConfigFromCloudFrontChain as Ei, resolveWebFunctionTarget as En, awsEndpointOptions as Eo, addInvokeAgentCoreSpecificOptions as Er, RecentOutput as Et, microvmImageTag as F, resolveCfnRegion as Fa, pickResponseTemplate as Fi, findFileAssetForObjectKey as Fn, AUTH_OFF_PLACEHOLDER_CREDENTIALS as Fo, MCP_PROTOCOL_VERSION as Fr, buildNodeEntryFileStart as Ft, startMicrovmFrontDoor as G, discoverWebSocketApis as Ga, buildDisconnectEvent as Gi, addStartServiceSpecificOptions as Gn, collectHostEndpointOverrides as Go, SUPPORTED_CODE_RUNTIMES as Gr, readWebFunctionServiceConfig as Gt, PROXY_PORT_HEADER as H, countTargets as Ha, handleConnectionsRequest as Hi, resolveAlbTarget as Hn, applyWorkloadAwsWiringToEnv as Ho, waitForAgentCoreHttpReady as Hr, WEB_FUNCTION_HTTP_ENDPOINT_ENV as Ht, planMicrovmPorts as I, resolveCfnStackName as Ia, selectIntegrationResponse as Ii, isBucketDeploymentResource as In, CA_TRUST_ENV_KEYS as Io, mcpInvokeOnce as Ir, defaultWebFunctionPlatform as It, MICROVM_HOOK_PATH_PREFIX as J, parseSelectionExpressionPath as Ja, createFileWatcher as Ji, addRunTaskSpecificOptions as Jn, getActiveWorkloadAwsWiring as Jo, renderCodeDockerfile as Jr, idFromArn as Jt, stripMicrovmProxyHeaders as K, discoverWebSocketApisOrThrow as Ka, buildMessageEvent as Ki, createLocalStartServiceCommand as Kn, displayEndpointValue as Ko, buildAgentCoreCodeImage as Kr, webFunctionAssumeRole as Kt, readExposedPorts as L, CfnLocalStateProvider as La, tryParseStatus as Li, resolveBucketDeploymentObjectKey as Ln, DEFAULT_AWS_EMULATOR_URL as Lo, parseSseForJsonRpc as Lr, resolveWebFunctionRuntime as Lt, DEFAULT_TERMINATE_HOOK_TIMEOUT_MS as M, isCfnFlagPresent as Ma, buildHttpApiV2Event as Mi, createLocalFileKvsDataSource as Mn, resetWorkloadIdentity as Mo, a2aInvokeOnce as Mr, waitForWebFunctionReady as Mt, LocalMicrovm as N, rejectExplicitCfnStackWithMultipleStacks as Na, buildRestV1Event as Ni, createUnboundCloudFrontModule as Nn, workloadClientConfig as No, MCP_CONTAINER_PORT as Nr, watchContainerExit as Nt, createLocalStartMicrovmCommand as O, LocalStateSourceError as Oa, matchPreflight as Oi, runViewerRequest as On, assumedRoleRecorded as Oo, bridgeAgentCoreWs as Or, containerFailure as Ot, buildMicrovmImage as P, resolveCfnFallbackRegion as Pa, evaluateResponseParameters as Pi, bucketDeploymentSourceObjectKeys as Pn, workloadStsClientConfig as Po, MCP_PATH as Pr, WEB_FUNCTION_RUNTIMES as Pt, pollBuildHook as Q, resolveLambdaArnIntrinsic as Qa, HOST_GATEWAY_MIN_VERSION as Qi, addEcsAssumeRoleOptions as Qn, logMixedModeForWorkload as Qo, createWatchPredicates as Qr, resolveDeployedOriginBucket as Qt, setContainerPaused as R, collectSsmParameterRefs as Ra, VtlEvaluationError as Ri, addAlbSpecificOptions as Rn, EMULATOR_SCRUBBED_ENV_KEYS as Ro, AGENTCORE_SIGV4_SERVICE as Rr, supportedWebFunctionRuntimes as Rt, StudioEventBus as S, containsCrossStackIntrinsic as Sa, invokeTokenAuthorizer as Si, WEB_FUNCTION_ENDPOINT_TYPE as Sn, parseDynamicReference as So, SOFT_RELOAD_COMPLETION_LOG_SUFFIX as Sr, normalizeKvsFileKeys as St, formatTargetListing as T, substituteEnvVarsFromState as Ta, buildCorsConfigByApiId as Ti, WebFunctionResolutionError as Tn, addAwsEndpointOptions as To, attachContainerLogStreamer as Tr, resolveCloudFrontTarget as Tt, rewriteUpgradeResponseHead as U, listTargets as Ua, parseConnectionsPath as Ui, isApplicationLoadBalancer as Un, awsEmulatorEnvName as Uo, waitForAgentCorePing as Ur, buildWebFunctionLambdaView as Ut, MicrovmStateError as V, resolveSingleTarget as Va, buildMgmtEndpointEnvUrl as Vi, parseLbPortOverrides as Vn, activateWorkloadAwsWiring as Vo, invokeAgentCore as Vr, resolveWebFunctionArtifact as Vt, selectTargetPort as W, availableWebSocketApiIdentifiers as Wa, buildConnectEvent as Wi, resolveAlbFrontDoor as Wn, awsEmulatorSqsHostBlocks as Wo, downloadAndExtractS3Bundle as Wr, finalizeWebFunctionEnv as Wt, callRuntimeHook as X, discoverRoutes as Xa, createLocalInvokeCommand as Xi, MAX_TASKS_SUBNET_RANGE_CAP as Xn, getContainerJavaTruststorePath as Xo, addStartApiSpecificOptions as Xr, createDeployedKvsDataSource as Xt, MicrovmHookError as Y, webSocketApiMatchesIdentifier as Ya, addInvokeSpecificOptions as Yi, createLocalRunTaskCommand as Yn, getContainerCaBundlePath as Yo, toCmdArgv as Yr, resolveKvsModulesForDistribution as Yt, generateMicrovmId as Z, pickRefLogicalId as Za, HOST_DOCKER_INTERNAL_GATEWAY as Zi, addCommonEcsServiceOptions as Zn, javaTruststoreToolOptions as Zo, createLocalStartApiCommand as Zr, resolveDeployedKvsArnByName as Zt, filterStudioTargetGroups as _, resolveRuntimeFileExtension as _a, verifyJwtViaDiscovery as _i, pickKvsLogicalIdFromArn as _n, containsDynamicReference as _o, isLocalCdkAssetImage as _r, sqsEmulatorOriginOf as _s, attachAgentCoreWsBridge as _t, createLocalStudioCommand as a, buildLoopbackForwarderDockerArgs as aa, filterRoutesByApiIdentifiers as ai, serveLambdaUrlOrigin as an, pickAgentCoreCandidateStack as ao, resolveSharedSidecarCredentials as ar, resolveAwsEmulatorOption as as, disposeMicrovmCodeArtifact as at, renderStudioHtml as b, assertEcsTaskCommandsResolved as ba, evaluateCachedLambdaPolicy as bi, pickWebFunctionEndpointLogicalIdFromOrigin as bn, keysNotFromTemplate as bo, CloudMapRegistry as br, buildStsClientConfig as bs, addStartCloudFrontSpecificOptions as bt, startStudioProxy as c, ensureForwarderImage as ca, startApiServer as ci, buildEdgeRequestEvent as cn, formatStateRemedy as co, buildImageOverrideTag as cr, setActiveWorkloadAwsWiring as cs, resolveMicrovmImageTarget as ct, createStudioDispatcher as d, buildContainerImage as da, defaultCredentialsLoader as di, httpHeadersToEdge as dn, LocalInvokeBuildError as do, mergeForService as dr, MIXED_MODE_RESIGN_BODY_CAP_BYTES as ds, createLocalStartWebFunctionCommand as dt, resolveHostGatewayExtraHosts as ea, createAuthorizerCache as ei, createS3OriginReader as en, AGENTCORE_AGUI_PROTOCOL as eo, buildEcsImageResolutionContext$1 as er, mergeJavaToolOptions as es, runHookBody as et, filterStudioCustomResources as f, dockerRegistryEnv as fa, buildCognitoJwksUrl as fi, CLOUDFRONT_DISTRIBUTION_TYPE as fn, ambientDefaultRegion as fo, parseImageOverrideFlags as fr, REAL_SQS_QUEUE_URL as fs, addStartAgentCoreSpecificOptions as ft, annotatePinnedEcsTargets as g, resolveRuntimeCodeMountPath as ga, verifyJwtAuthorizer as gi, pickFunctionUrlLogicalIdFromOrigin as gn, DynamicReferenceResolver as go, imageOverrideKeyAliases as gr, rewriteSqsQueueUrlsInEnv as gs, startAgentCoreHttpServer as gt, annotateEcsTaskPinnedTargets as h, stripEcrCredentials as ha, verifyCognitoJwt as hi, isCloudFrontDistribution as hn, DynamicReferenceResolutionError as ho, describePinnedImageUri as hr, repointLocalSqsQueueUrlsInEnv as hs, selectServeInboundAuth as ht, coerceStopRequest as i, awaitLoopbackForwarderStatus as ia, filterRoutesByApiIdentifier as ii, serveFromStaticOrigin as in, AgentCoreResolutionError as io, resolveEcsAssumeRoleOption as ir, readProfileEndpointSettings as is, MicrovmResolutionError as it, readRunHookPayload as j, groupWorkloadsRoutedApart as ja, applyAuthorizerOverlay as ji, createCloudFrontModule as jn, recordAssumedRole as jo, A2A_PATH as jr, startWebFunctionContainer as jt, finalizeMicrovmEnv as k, UNNAMED_WORKLOAD as ka, matchRoute as ki, runViewerResponse as kn, deployAccountStsClientConfig as ko, invokeAgentCoreWs as kr, planWebFunctionContainer as kt, relayServeRequest as l, startLoopbackForwarder as la, resolveSelectionExpression as li, buildEdgeResponseEvent as ln, substituteImagePlaceholders as lo, canonicalizeImageOverrideKeys as lr, takeAwsEmulatorStateSourceHint as ls, s3KeyOfUri as lt, annotateAlbPinnedBackingServices as m, noImplicitEcrPullArgs as ma, createJwksCache as mi, extractKvsAssociations as mn, setAmbientDefaultRegion as mo, runImageOverrideBuilds as mr, realSqsHostnames as ms, buildAgentCoreServeAuthCheck as mt, coerceRunRequest as n, withWorkloadAwsWiring as na, buildStageMap as ni, startCloudFrontServer as nn, AGENTCORE_MCP_PROTOCOL as no, parseMaxTasks as nr, probeAwsEmulatorHealth as ns, MICROVM_DEFAULT_INGRESS_PORT as nt, resolveServeBaseUrl as o, buildNamespaceOwnerForwarderDockerArgs as oa, groupRoutesByServer as oi, applyEdgeRequestResult as on, resolveAgentCoreTarget as oo, runEcsServiceEmulator as or, resolveHostDefaultCredentials as os, readMicrovmImageConfig as ot, isCustomResourceLambdaTarget as p, isEcrRegistryConfigKey as pa, buildJwksUrlFromIssuer as pi, describeS3OriginDomain as pn, namedEnvAwsRegion as po, resolveImageOverrides as pr, isRealAwsHost as ps, createLocalStartAgentCoreCommand as pt, MAX_RUN_HOOK_PAYLOAD_BYTES as q, filterWebSocketApisByIdentifiers as qa, classifySourceChange as qi, serviceStrategy as qn, effectiveLoopbackPorts as qo, computeCodeImageTag as qr, webFunctionFidelityWarnings as qt, coerceServeRequest as r, LOOPBACK_FORWARDER_IMAGE as ra, availableApiIdentifiers as ri, resolveErrorResponseCandidates as rn, AGENTCORE_RUNTIME_TYPE as ro, parseRestartPolicy as rr, readEmulatorRunFiles as rs, MICROVM_IMAGE_TYPE as rt, createStudioServeManager as s, describeForwarderFailure as sa, readMtlsMaterialsFromDisk as si, applyEdgeResponseResult as sn, derivePseudoParametersFromRegion as so, ImageOverrideError as sr, resolveWorkloadAwsWiring as ss, resolveMicrovmCodeArtifact as st, addStudioSpecificOptions as t, attachLoopbackForwarder as ta, attachStageContext as ti, matchBehavior as tn, AGENTCORE_HTTP_PROTOCOL as to, ecsClusterOption as tr, parseAwsEndpoint as ts, waitForAppAnswer as tt, reinvoke as u, architectureToPlatform as ua, resolveServiceIntegrationParameters as ui, edgeHeadersToHttp as un, tryResolveImageFnJoin as uo, enforceImageOverrideOrphans as ur, writeCaBundleFile as us, addStartWebFunctionSpecificOptions as ut, startStudioServer as v, resolveRuntimeImage as va, buildMethodArn as vi, pickLambdaEdgeFunctionLogicalId as vn, deployedFillMayBeSecret as vo, listPinnedTargets as vr, buildJavaTrustStore as vs, startAgentCoreWsBridge as vt, createLocalListCommand as w, substituteAgainstStateAsync as wa, applyCorsResponseHeaders as wi, WEB_FUNCTION_TYPE as wn, withoutKeys as wo, getContainerNetworkIp as wr, parseOriginOverrides as wt, createStudioStore as x, assertEcsTaskImagesResolvable as xa, invokeRequestAuthorizer as xi, resolveCloudFrontDistribution as xn, keysOverriddenBy as xo, DEFAULT_SHADOW_READY_TIMEOUT_MS as xr, resolveProfileCredentials as xs, createLocalStartCloudFrontCommand as xt, toStudioTargetGroups as y, EcsTaskResolutionError as ya, computeRequestIdentityHash as yi, pickTargetFunctionLogicalId as yn, firstUsableRegion as yo, buildCloudMapIndex as yr, createMixedModeTlsMaterials as ys, LocalStartCloudFrontError as yt, MICROVM_CONTROL_PATH as z, resolveSsmParameters as za, bufferToBody as zi, albStrategy as zn, HOST_CA_TRUST_ENV_KEYS as zo, signAgentCoreInvocation as zr, disposeWebFunctionArtifact as zt };
37025
- //# sourceMappingURL=local-studio-CrP4kia1.js.map
37300
+ //# sourceMappingURL=local-studio-CAxQV9HT.js.map