cdk-local 0.85.0 → 0.87.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.
@@ -14705,7 +14705,7 @@ function availableApiIdentifiers(routes) {
14705
14705
  * @param overrides Parsed `--env-vars` file contents, or
14706
14706
  * `undefined` when the flag was not passed.
14707
14707
  */
14708
- function resolveEnvVars(logicalId, displayPath, templateEnv, overrides) {
14708
+ function resolveEnvVars$1(logicalId, displayPath, templateEnv, overrides) {
14709
14709
  const resolved = {};
14710
14710
  const unresolved = [];
14711
14711
  if (templateEnv) for (const [key, value] of Object.entries(templateEnv)) if (isLiteralEnvValue(value)) resolved[key] = String(value);
@@ -16196,7 +16196,7 @@ async function buildContainerSpec(args) {
16196
16196
  for (const { key, reason } of unresolved) getLogger().warn(`Lambda ${logicalId}: state source could not substitute env var ${key} (${reason}). Override it via --env-vars or it will be dropped.`);
16197
16197
  }
16198
16198
  const lambdaCdkPath = readCdkPathOrUndefined(lambda.resource);
16199
- const envResult = resolveEnvVars(logicalId, lambdaCdkPath, templateEnv, overrides);
16199
+ const envResult = resolveEnvVars$1(logicalId, lambdaCdkPath, templateEnv, overrides);
16200
16200
  for (const key of envResult.unresolved) {
16201
16201
  if (stateAudit && stateAudit.unresolved.some((u) => u.key === key)) continue;
16202
16202
  const overrideKeyExample = lambdaCdkPath?.replace(/\/Resource$/, "") ?? logicalId;
@@ -17209,7 +17209,7 @@ async function localInvokeCommand(target, options, extraStateProviders) {
17209
17209
  }
17210
17210
  const overrides = readEnvOverridesFile$3(options.envVars);
17211
17211
  const lambdaCdkPath = readCdkPathOrUndefined(lambda.resource);
17212
- const envResult = resolveEnvVars(lambda.logicalId, lambdaCdkPath, templateEnv, overrides);
17212
+ const envResult = resolveEnvVars$1(lambda.logicalId, lambdaCdkPath, templateEnv, overrides);
17213
17213
  for (const key of envResult.unresolved) {
17214
17214
  if (stateAudit && stateAudit.unresolved.some((u) => u.key === key)) continue;
17215
17215
  const overrideKeyExample = lambdaCdkPath?.replace(/\/Resource$/, "") ?? lambda.logicalId;
@@ -19187,7 +19187,7 @@ async function buildContainerEnv(resolved, options, profileCredentials, profileC
19187
19187
  }
19188
19188
  const overrides = readEnvOverridesFile$2(options.envVars);
19189
19189
  const cdkPath = readCdkPathOrUndefined(resolved.resource);
19190
- const envResult = resolveEnvVars(resolved.logicalId, cdkPath, templateEnv, overrides);
19190
+ const envResult = resolveEnvVars$1(resolved.logicalId, cdkPath, templateEnv, overrides);
19191
19191
  for (const key of envResult.unresolved) {
19192
19192
  const overrideKeyExample = cdkPath?.replace(/\/Resource$/, "") ?? resolved.logicalId;
19193
19193
  logger.warn(`Environment variable ${key} contains a CloudFormation intrinsic and was dropped. Override it with --env-vars (e.g. {"${overrideKeyExample}":{"${key}":"<literal>"}}), or pass a state-source flag (e.g. --from-cfn-stack) to recover deployed values.`);
@@ -27971,6 +27971,174 @@ function createStudioStore(bus, options = {}) {
27971
27971
  };
27972
27972
  }
27973
27973
 
27974
+ //#endregion
27975
+ //#region src/local/studio-option-specs.ts
27976
+ /**
27977
+ * The per-kind option table. Kinds absent here (or with an empty list) have
27978
+ * no per-run options — the UI shows just the primary control (the event
27979
+ * composer for `lambda`, a bare Start for a serve).
27980
+ */
27981
+ const OPTION_SPECS = {
27982
+ lambda: [{
27983
+ flag: "--env-vars",
27984
+ kind: "env-kv",
27985
+ label: "Env vars",
27986
+ sep: "=",
27987
+ leftPlaceholder: "KEY",
27988
+ rightPlaceholder: "value",
27989
+ help: "Overlay container env vars — add KEY=VALUE rows or paste a JSON object."
27990
+ }],
27991
+ alb: [
27992
+ {
27993
+ flag: "--tls",
27994
+ kind: "boolean",
27995
+ label: "TLS (terminate HTTPS locally)"
27996
+ },
27997
+ {
27998
+ flag: "--tls-cert",
27999
+ kind: "scalar",
28000
+ label: "TLS cert",
28001
+ placeholder: "./cert.pem",
28002
+ showWhen: "--tls"
28003
+ },
28004
+ {
28005
+ flag: "--tls-key",
28006
+ kind: "scalar",
28007
+ label: "TLS key",
28008
+ placeholder: "./key.pem",
28009
+ showWhen: "--tls"
28010
+ },
28011
+ {
28012
+ flag: "--lb-port",
28013
+ kind: "repeat-pair",
28014
+ label: "Listener port remap",
28015
+ sep: "=",
28016
+ leftPlaceholder: "listenerPort",
28017
+ rightPlaceholder: "hostPort"
28018
+ },
28019
+ {
28020
+ flag: "--bearer-token",
28021
+ kind: "scalar",
28022
+ label: "Bearer token",
28023
+ placeholder: "eyJ...",
28024
+ help: "Default JWT injected for authenticate-cognito / authenticate-oidc actions."
28025
+ },
28026
+ {
28027
+ flag: "--no-verify-auth",
28028
+ kind: "boolean",
28029
+ label: "Disable auth guard"
28030
+ }
28031
+ ],
28032
+ ecs: [{
28033
+ flag: "--max-tasks",
28034
+ kind: "scalar",
28035
+ label: "Max replicas",
28036
+ placeholder: "1",
28037
+ inputType: "number"
28038
+ }, {
28039
+ flag: "--host-port",
28040
+ kind: "repeat-pair",
28041
+ label: "Container port publish",
28042
+ sep: "=",
28043
+ leftPlaceholder: "containerPort",
28044
+ rightPlaceholder: "hostPort"
28045
+ }]
28046
+ };
28047
+ /** True when `value` is a non-empty trimmed string. */
28048
+ function nonEmptyStr(value) {
28049
+ return typeof value === "string" && value.trim() !== "";
28050
+ }
28051
+ /**
28052
+ * Build the per-run argv fragment for a target `kind` from the UI-posted
28053
+ * option `values`, validating each value against {@link OPTION_SPECS}.
28054
+ *
28055
+ * Throws on an unknown flag (a value keyed to an option the kind does not
28056
+ * declare) or a type mismatch (e.g. a string where a boolean is expected) so
28057
+ * a malformed UI / curl body fails loudly rather than spawning a child with
28058
+ * a bogus arg. A `scalar` with `showWhen` is dropped unless its gate boolean
28059
+ * is on. Empty / blank values are omitted.
28060
+ */
28061
+ function buildPerRunArgs(kind, values) {
28062
+ if (values === void 0) return [];
28063
+ const specs = OPTION_SPECS[kind] ?? [];
28064
+ const byFlag = new Map(specs.map((s) => [s.flag, s]));
28065
+ for (const flag of Object.keys(values)) if (!byFlag.has(flag)) throw new Error(`Unknown option '${flag}' for target kind '${kind}'.`);
28066
+ const args = [];
28067
+ for (const spec of specs) {
28068
+ const value = values[spec.flag];
28069
+ if (value === void 0) continue;
28070
+ if (spec.kind === "boolean") {
28071
+ if (typeof value !== "boolean") throw new Error(`Option '${spec.flag}' must be a boolean.`);
28072
+ if (value) args.push(spec.flag);
28073
+ continue;
28074
+ }
28075
+ if (spec.kind === "scalar") {
28076
+ if (value !== "" && typeof value !== "string") throw new Error(`Option '${spec.flag}' must be a string.`);
28077
+ if (spec.showWhen && values[spec.showWhen] !== true) continue;
28078
+ if (nonEmptyStr(value)) args.push(spec.flag, value.trim());
28079
+ continue;
28080
+ }
28081
+ if (spec.kind === "env-kv") {
28082
+ if (!Array.isArray(value) && typeof value !== "string") throw new Error(`Option '${spec.flag}' must be KEY/VALUE rows or a JSON string.`);
28083
+ continue;
28084
+ }
28085
+ if (!Array.isArray(value)) throw new Error(`Option '${spec.flag}' must be an array of { left, right } rows.`);
28086
+ for (const row of value) {
28087
+ if (typeof row !== "object" || row === null) throw new Error(`Option '${spec.flag}' rows must be objects.`);
28088
+ const { left, right } = row;
28089
+ if (!nonEmptyStr(left) && !nonEmptyStr(right)) continue;
28090
+ if (!nonEmptyStr(left) || !nonEmptyStr(right)) throw new Error(`Option '${spec.flag}' rows need both sides (got '${left}${spec.sep}${right}').`);
28091
+ args.push(spec.flag, `${left.trim()}${spec.sep}${right.trim()}`);
28092
+ }
28093
+ }
28094
+ return args;
28095
+ }
28096
+ /**
28097
+ * Materialize the `env-kv` option for a target `kind` into the SAM-shape
28098
+ * object `--env-vars` expects (one level of nesting). The caller writes the
28099
+ * returned object to a temp JSON file and passes `--env-vars <file>` to the
28100
+ * child. Returns `undefined` when there is no env-kv option / no values.
28101
+ *
28102
+ * Two input forms (both produced by the UI's KV / JSON toggle):
28103
+ * - **KV rows** (`PairValue[]`) -> a flat `{KEY: value}` map wrapped as
28104
+ * `{ Parameters: {...} }` (the SAM global scope — applies to the target).
28105
+ * - **JSON string** -> parsed; a full SAM-shape object (a `Parameters` key or
28106
+ * any nested-object value) is used as-is, while a flat `{KEY: "value"}`
28107
+ * object is wrapped in `{ Parameters: {...} }`.
28108
+ *
28109
+ * Throws on malformed JSON / a non-object so a bad value fails as a clean
28110
+ * boundary error rather than writing garbage to the temp file.
28111
+ */
28112
+ function resolveEnvVars(kind, values) {
28113
+ if (values === void 0) return void 0;
28114
+ const spec = (OPTION_SPECS[kind] ?? []).find((s) => s.kind === "env-kv");
28115
+ if (!spec) return void 0;
28116
+ const value = values[spec.flag];
28117
+ if (value === void 0) return void 0;
28118
+ if (Array.isArray(value)) {
28119
+ const flat = {};
28120
+ for (const row of value) {
28121
+ const { left, right } = row ?? {};
28122
+ if (nonEmptyStr(left)) flat[left.trim()] = typeof right === "string" ? right : "";
28123
+ }
28124
+ return Object.keys(flat).length > 0 ? { Parameters: flat } : void 0;
28125
+ }
28126
+ if (typeof value === "string") {
28127
+ const text = value.trim();
28128
+ if (text === "") return void 0;
28129
+ let parsed;
28130
+ try {
28131
+ parsed = JSON.parse(text);
28132
+ } catch {
28133
+ throw new Error("Env vars JSON is not valid JSON.");
28134
+ }
28135
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new Error("Env vars JSON must be a JSON object.");
28136
+ const obj = parsed;
28137
+ return "Parameters" in obj || Object.values(obj).some((v) => typeof v === "object" && v !== null) ? obj : { Parameters: obj };
28138
+ }
28139
+ throw new Error(`Option '${spec.flag}' must be KEY/VALUE rows or a JSON object string.`);
28140
+ }
28141
+
27974
28142
  //#endregion
27975
28143
  //#region src/local/studio-ui.ts
27976
28144
  /**
@@ -28001,6 +28169,7 @@ const STUDIO_CSS = `
28001
28169
  body {
28002
28170
  margin: 0; font: 13px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
28003
28171
  color: #e6e6e6; background: #1a1a1a; height: 100vh; overflow: hidden;
28172
+ display: flex; flex-direction: column;
28004
28173
  }
28005
28174
  header {
28006
28175
  padding: 8px 14px; background: #111; border-bottom: 1px solid #333;
@@ -28008,9 +28177,30 @@ const STUDIO_CSS = `
28008
28177
  }
28009
28178
  header .brand { font-weight: 700; color: #fff; }
28010
28179
  header .meta { color: #888; font-size: 12px; }
28180
+ #session-bar {
28181
+ display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
28182
+ padding: 5px 14px; background: #141414; border-bottom: 1px solid #2a2a2a;
28183
+ font-size: 12px;
28184
+ }
28185
+ #session-bar .sess-title { color: #888; text-transform: uppercase; font-size: 11px; }
28186
+ #session-bar .sess-bind { color: #bbb; display: inline-flex; align-items: center; gap: 4px; }
28187
+ #session-bar input[type=text] {
28188
+ background: #111; color: #ddd; border: 1px solid #333; border-radius: 3px;
28189
+ padding: 3px 6px; font: 12px ui-monospace, Menlo, monospace; min-width: 180px;
28190
+ }
28191
+ #session-bar input:focus { outline: none; border-color: #4ec97a; }
28192
+ #session-bar button {
28193
+ background: #2a3a2c; color: #7bd88f; border: 1px solid #2f4030; border-radius: 3px;
28194
+ cursor: pointer; padding: 3px 12px; font: 12px ui-monospace, monospace;
28195
+ }
28196
+ #session-bar button:hover { background: #314b34; }
28197
+ #session-bar #sess-msg { color: #7bd88f; min-width: 40px; }
28198
+ #session-bar .sess-synth { color: #777; margin-left: auto; }
28011
28199
  main {
28012
28200
  display: grid; grid-template-columns: 280px 5px 1fr 5px 320px;
28013
- height: calc(100vh - 38px);
28201
+ /* Body is a flex column (header + session-bar + main); main fills the
28202
+ rest so the height is computed — no magic constant, wrap-safe. */
28203
+ flex: 1; min-height: 0;
28014
28204
  }
28015
28205
  .pane { overflow: auto; }
28016
28206
  .splitter { background: #2a2a2a; cursor: col-resize; }
@@ -28093,6 +28283,35 @@ const STUDIO_CSS = `
28093
28283
  #conn { font-size: 11px; }
28094
28284
  #conn.up { color: #7bd88f; }
28095
28285
  #conn.down { color: #e0707a; }
28286
+ .options .opt-row { display: flex; align-items: center; gap: 8px; margin: 6px 0; }
28287
+ .options .opt-row.opt-col { display: flex; flex-direction: column; align-items: stretch; gap: 4px; }
28288
+ .opt-label { color: #aaa; font-size: 12px; min-width: 120px; }
28289
+ .opt-bool { color: #ddd; font-size: 12px; display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
28290
+ .options input[type=text], .options input[type=number] {
28291
+ flex: 1; background: #111; color: #ddd; border: 1px solid #333; border-radius: 3px;
28292
+ padding: 4px 6px; font: 12px ui-monospace, Menlo, monospace; min-width: 0;
28293
+ }
28294
+ .options input:focus, .envkv-ta:focus { outline: none; border-color: #4ec97a; }
28295
+ .pair-wrap { display: flex; flex-direction: column; gap: 4px; flex: 1; }
28296
+ .pair-row { display: flex; align-items: center; gap: 6px; }
28297
+ .pair-in { width: 1px; flex: 1; background: #111; color: #ddd; border: 1px solid #333;
28298
+ border-radius: 3px; padding: 4px 6px; font: 12px ui-monospace, Menlo, monospace; min-width: 0; }
28299
+ .pair-sep { color: #888; }
28300
+ .pair-x { background: #2a2a2a; color: #bbb; border: none; border-radius: 3px; cursor: pointer;
28301
+ padding: 2px 7px; font: 12px ui-monospace, monospace; }
28302
+ .pair-x:hover { background: #3a2a2a; color: #e0707a; }
28303
+ .pair-add { align-self: flex-start; background: #1d1d1d; color: #7bd88f; border: 1px solid #2f4030;
28304
+ border-radius: 3px; cursor: pointer; padding: 3px 9px; font: 12px ui-monospace, monospace; }
28305
+ .pair-add:hover { background: #243024; }
28306
+ .envkv-modes { display: flex; gap: 0; }
28307
+ .envkv-mode { background: #1a1a1a; color: #999; border: 1px solid #333; cursor: pointer;
28308
+ padding: 3px 12px; font: 11px ui-monospace, monospace; }
28309
+ .envkv-mode:first-child { border-radius: 3px 0 0 3px; }
28310
+ .envkv-mode:last-child { border-radius: 0 3px 3px 0; border-left: none; }
28311
+ .envkv-mode.active { background: #2a3a2c; color: #7bd88f; }
28312
+ .envkv-ta { width: 100%; box-sizing: border-box; min-height: 70px; resize: vertical;
28313
+ background: #111; color: #ddd; border: 1px solid #333; border-radius: 3px; padding: 6px 8px;
28314
+ font: 12px ui-monospace, Menlo, monospace; }
28096
28315
  `;
28097
28316
  const STUDIO_SCRIPT = `
28098
28317
  const KIND_LABEL = { lambda: 'Lambda', api: 'API', alb: 'ALB', ecs: 'ECS', agentcore: 'AgentCore' };
@@ -28115,6 +28334,142 @@ const STUDIO_SCRIPT = `
28115
28334
  return e;
28116
28335
  }
28117
28336
 
28337
+ // Per-target run options (issue #301 slice 2). The descriptor table is
28338
+ // serialized into the page by the server; we render a control per option
28339
+ // and return { node, collect } so the caller places the section and reads
28340
+ // the values when the user clicks Invoke / Start.
28341
+ const OPTION_SPECS = window.__OPTION_SPECS__ || {};
28342
+
28343
+ function buildOptions(kind) {
28344
+ const specs = OPTION_SPECS[kind] || [];
28345
+ if (!specs.length) return { node: null, collect: function () { return undefined; } };
28346
+ const sec = el('div', 'section options');
28347
+ sec.appendChild(el('h3', null, 'Options'));
28348
+ const getters = [];
28349
+ const bools = {};
28350
+
28351
+ // Shared add-row pair list (used by repeat-pair AND the env-kv KV pane).
28352
+ function pairList(spec) {
28353
+ const list = el('div', 'pair-rows');
28354
+ const pairs = [];
28355
+ const addRow = function () {
28356
+ const r = el('div', 'pair-row');
28357
+ const lv = el('input');
28358
+ lv.placeholder = spec.leftPlaceholder;
28359
+ lv.className = 'pair-in';
28360
+ const rv = el('input');
28361
+ rv.placeholder = spec.rightPlaceholder;
28362
+ rv.className = 'pair-in';
28363
+ const pair = { l: lv, r: rv };
28364
+ const x = el('button', 'pair-x', 'x');
28365
+ x.type = 'button';
28366
+ x.onclick = function () {
28367
+ list.removeChild(r);
28368
+ const i = pairs.indexOf(pair);
28369
+ if (i >= 0) pairs.splice(i, 1);
28370
+ };
28371
+ r.appendChild(lv);
28372
+ r.appendChild(el('span', 'pair-sep', spec.sep));
28373
+ r.appendChild(rv);
28374
+ r.appendChild(x);
28375
+ list.appendChild(r);
28376
+ pairs.push(pair);
28377
+ };
28378
+ const add = el('button', 'pair-add', '+ add');
28379
+ add.type = 'button';
28380
+ add.onclick = addRow;
28381
+ const wrap = el('div', 'pair-wrap');
28382
+ wrap.appendChild(list);
28383
+ wrap.appendChild(add);
28384
+ return {
28385
+ node: wrap,
28386
+ rows: function () {
28387
+ return pairs.map(function (p) { return { left: p.l.value, right: p.r.value }; });
28388
+ },
28389
+ };
28390
+ }
28391
+
28392
+ specs.forEach(function (spec) {
28393
+ const row = el('div', 'opt-row');
28394
+ if (spec.kind === 'boolean') {
28395
+ const cb = el('input');
28396
+ cb.type = 'checkbox';
28397
+ const lab = el('label', 'opt-bool');
28398
+ lab.appendChild(cb);
28399
+ lab.appendChild(document.createTextNode(' ' + spec.label));
28400
+ row.appendChild(lab);
28401
+ bools[spec.flag] = cb;
28402
+ getters.push(function () { return [spec.flag, cb.checked]; });
28403
+ } else if (spec.kind === 'scalar') {
28404
+ row.appendChild(el('span', 'opt-label', spec.label));
28405
+ const inp = el('input');
28406
+ inp.type = spec.inputType === 'number' ? 'number' : 'text';
28407
+ if (spec.placeholder) inp.placeholder = spec.placeholder;
28408
+ row.appendChild(inp);
28409
+ if (spec.showWhen) {
28410
+ const gate = bools[spec.showWhen];
28411
+ const sync = function () { row.style.display = gate && gate.checked ? 'flex' : 'none'; };
28412
+ if (gate) gate.addEventListener('change', sync);
28413
+ sync();
28414
+ }
28415
+ getters.push(function () { return [spec.flag, inp.value]; });
28416
+ } else if (spec.kind === 'env-kv') {
28417
+ // Two input modes — KV add-rows or a raw JSON object; the server
28418
+ // materializes either into a SAM-shape temp file for --env-vars.
28419
+ row.className = 'opt-row opt-col';
28420
+ row.appendChild(el('span', 'opt-label', spec.label));
28421
+ const modes = el('div', 'envkv-modes');
28422
+ const kvBtn = el('button', 'envkv-mode active', 'KV');
28423
+ kvBtn.type = 'button';
28424
+ const jsonBtn = el('button', 'envkv-mode', 'JSON');
28425
+ jsonBtn.type = 'button';
28426
+ modes.appendChild(kvBtn);
28427
+ modes.appendChild(jsonBtn);
28428
+ row.appendChild(modes);
28429
+ const pl = pairList(spec);
28430
+ row.appendChild(pl.node);
28431
+ const ta = el('textarea', 'envkv-ta');
28432
+ ta.placeholder = '{ "KEY": "value" }';
28433
+ ta.spellcheck = false;
28434
+ ta.style.display = 'none';
28435
+ row.appendChild(ta);
28436
+ let mode = 'kv';
28437
+ kvBtn.onclick = function () {
28438
+ mode = 'kv';
28439
+ kvBtn.className = 'envkv-mode active';
28440
+ jsonBtn.className = 'envkv-mode';
28441
+ pl.node.style.display = '';
28442
+ ta.style.display = 'none';
28443
+ };
28444
+ jsonBtn.onclick = function () {
28445
+ mode = 'json';
28446
+ jsonBtn.className = 'envkv-mode active';
28447
+ kvBtn.className = 'envkv-mode';
28448
+ ta.style.display = '';
28449
+ pl.node.style.display = 'none';
28450
+ };
28451
+ getters.push(function () {
28452
+ return mode === 'json' ? [spec.flag, ta.value] : [spec.flag, pl.rows()];
28453
+ });
28454
+ } else {
28455
+ // repeat-pair: an add-row list of left<sep>right inputs.
28456
+ row.appendChild(el('span', 'opt-label', spec.label));
28457
+ const pl = pairList(spec);
28458
+ row.appendChild(pl.node);
28459
+ getters.push(function () { return [spec.flag, pl.rows()]; });
28460
+ }
28461
+ sec.appendChild(row);
28462
+ });
28463
+ return {
28464
+ node: sec,
28465
+ collect: function () {
28466
+ const out = {};
28467
+ getters.forEach(function (g) { const kv = g(); out[kv[0]] = kv[1]; });
28468
+ return out;
28469
+ },
28470
+ };
28471
+ }
28472
+
28118
28473
  async function loadTargets() {
28119
28474
  const pane = document.getElementById('targets');
28120
28475
  try {
@@ -28231,7 +28586,7 @@ const STUDIO_SCRIPT = `
28231
28586
  }
28232
28587
  }
28233
28588
 
28234
- async function startServe(id) {
28589
+ async function startServe(id, options) {
28235
28590
  // The serve kind (api / alb / ecs) drives which headless command the
28236
28591
  // server spawns; it is recorded on the row when the target list loads.
28237
28592
  const meta = serveMeta.get(id);
@@ -28239,10 +28594,12 @@ const STUDIO_SCRIPT = `
28239
28594
  serveState.set(id, { status: 'starting', endpoints: [] });
28240
28595
  updateServeRow(id);
28241
28596
  try {
28597
+ const body = { targetId: id, kind };
28598
+ if (options) body.options = options;
28242
28599
  const res = await fetch('/api/run', {
28243
28600
  method: 'POST',
28244
28601
  headers: { 'content-type': 'application/json' },
28245
- body: JSON.stringify({ targetId: id, kind }),
28602
+ body: JSON.stringify(body),
28246
28603
  });
28247
28604
  const data = await res.json();
28248
28605
  if (!res.ok) {
@@ -28279,12 +28636,17 @@ const STUDIO_SCRIPT = `
28279
28636
  const running = st.status === 'running';
28280
28637
  const starting = st.status === 'starting';
28281
28638
 
28639
+ const meta = serveMeta.get(id);
28640
+ const kind = meta ? meta.kind : 'api';
28641
+
28282
28642
  const head = el('div', 'composer');
28283
28643
  head.appendChild(el('div', 'target-name', 'Serve ' + id));
28284
28644
  const btn = running || starting
28285
28645
  ? el('button', null, 'Stop')
28286
28646
  : el('button', null, starting ? 'Starting…' : 'Start');
28287
- btn.onclick = () => { if (running || starting) stopServe(id); else startServe(id); };
28647
+ // Per-run options are only set before a start; collected on the Start click.
28648
+ let collectOpts = function () { return undefined; };
28649
+ btn.onclick = () => { if (running || starting) stopServe(id); else startServe(id, collectOpts()); };
28288
28650
  head.appendChild(btn);
28289
28651
  if (errMsg) {
28290
28652
  const m = el('div', 'err', errMsg);
@@ -28292,7 +28654,12 @@ const STUDIO_SCRIPT = `
28292
28654
  }
28293
28655
  ws.appendChild(head);
28294
28656
 
28295
- const meta = serveMeta.get(id);
28657
+ if (!running && !starting) {
28658
+ const opt = buildOptions(kind);
28659
+ if (opt.node) ws.appendChild(opt.node);
28660
+ collectOpts = opt.collect;
28661
+ }
28662
+
28296
28663
  const isEcs = meta && meta.kind === 'ecs';
28297
28664
  const epSec = el('div', 'section');
28298
28665
  epSec.appendChild(el('h3', null, 'Endpoints'));
@@ -28340,6 +28707,9 @@ const STUDIO_SCRIPT = `
28340
28707
  ta.value = eventText;
28341
28708
  ta.spellcheck = false;
28342
28709
  composer.appendChild(ta);
28710
+ // Per-run options (e.g. env vars) below the event, above Invoke.
28711
+ const opt = buildOptions(kind);
28712
+ if (opt.node) composer.appendChild(opt.node);
28343
28713
  composer.appendChild(document.createElement('br'));
28344
28714
  const btn = el('button', null, 'Invoke');
28345
28715
  const msg = el('div', 'err');
@@ -28351,7 +28721,7 @@ const STUDIO_SCRIPT = `
28351
28721
  ws.appendChild(composer);
28352
28722
  ws.appendChild(result);
28353
28723
 
28354
- active = { id, kind, ta, btn, msg, result };
28724
+ active = { id, kind, ta, btn, msg, result, collectOpts: opt.collect };
28355
28725
  btn.onclick = () => runInvoke();
28356
28726
  shownInvId = null;
28357
28727
  shownDetailId = null;
@@ -28373,10 +28743,13 @@ const STUDIO_SCRIPT = `
28373
28743
  btn.textContent = 'Invoking...';
28374
28744
  result.innerHTML = '';
28375
28745
  try {
28746
+ const body = { targetId: id, kind, event };
28747
+ const options = active.collectOpts ? active.collectOpts() : undefined;
28748
+ if (options) body.options = options;
28376
28749
  const res = await fetch('/api/run', {
28377
28750
  method: 'POST',
28378
28751
  headers: { 'content-type': 'application/json' },
28379
- body: JSON.stringify({ targetId: id, kind, event }),
28752
+ body: JSON.stringify(body),
28380
28753
  });
28381
28754
  const data = await res.json();
28382
28755
  if (data.invocationId) {
@@ -28648,11 +29021,78 @@ const STUDIO_SCRIPT = `
28648
29021
  wire('split-right', (dx, l0, r0) => { right = clamp(r0 - dx); });
28649
29022
  }
28650
29023
 
29024
+ // Session config (issue #301 slice 3): synth-time context is read-only;
29025
+ // the run-time bindings (from-cfn-stack / assume-role) are editable and
29026
+ // apply to subsequent invokes / serves.
29027
+ async function loadConfig() {
29028
+ try {
29029
+ const res = await fetch('/api/config');
29030
+ const c = await res.json();
29031
+ const cfn = document.getElementById('sess-cfn');
29032
+ const cfnName = document.getElementById('sess-cfn-name');
29033
+ const role = document.getElementById('sess-role');
29034
+ const on = c.fromCfnStack !== undefined && c.fromCfnStack !== false;
29035
+ cfn.checked = on;
29036
+ cfnName.value = typeof c.fromCfnStack === 'string' ? c.fromCfnStack : '';
29037
+ cfnName.style.display = on ? '' : 'none';
29038
+ role.value = c.assumeRole || '';
29039
+ const s = c.synth || {};
29040
+ const parts = [];
29041
+ if (s.profile) parts.push('profile=' + s.profile);
29042
+ if (s.region) parts.push('region=' + s.region);
29043
+ if (s.app) parts.push('app=' + s.app);
29044
+ document.getElementById('sess-synth').textContent = parts.length ? '(' + parts.join(' \\u00b7 ') + ')' : '';
29045
+ } catch (err) {
29046
+ /* best-effort; the session bar is non-critical */
29047
+ }
29048
+ }
29049
+
29050
+ async function saveConfig() {
29051
+ const cfn = document.getElementById('sess-cfn');
29052
+ const cfnName = document.getElementById('sess-cfn-name');
29053
+ const role = document.getElementById('sess-role');
29054
+ const msg = document.getElementById('sess-msg');
29055
+ const body = {
29056
+ fromCfnStack: cfn.checked ? cfnName.value.trim() || true : null,
29057
+ assumeRole: role.value.trim() || null,
29058
+ };
29059
+ msg.textContent = 'Saving...';
29060
+ try {
29061
+ const res = await fetch('/api/config', {
29062
+ method: 'PATCH',
29063
+ headers: { 'content-type': 'application/json' },
29064
+ body: JSON.stringify(body),
29065
+ });
29066
+ if (!res.ok) {
29067
+ const e = await res.json().catch(function () { return {}; });
29068
+ msg.textContent = 'Error: ' + (e.error || ('HTTP ' + res.status));
29069
+ return;
29070
+ }
29071
+ msg.textContent = 'Saved';
29072
+ setTimeout(function () { msg.textContent = ''; }, 1500);
29073
+ await loadConfig();
29074
+ } catch (err) {
29075
+ msg.textContent = 'Failed: ' + err;
29076
+ }
29077
+ }
29078
+
29079
+ function wireSession() {
29080
+ const cfn = document.getElementById('sess-cfn');
29081
+ const cfnName = document.getElementById('sess-cfn-name');
29082
+ cfn.addEventListener('change', function () {
29083
+ cfnName.style.display = cfn.checked ? '' : 'none';
29084
+ if (cfn.checked) cfnName.focus();
29085
+ });
29086
+ document.getElementById('sess-save').onclick = saveConfig;
29087
+ }
29088
+
28651
29089
  loadTargets().then(loadRunning);
28652
29090
  loadHistory();
29091
+ loadConfig();
28653
29092
  connect();
28654
29093
  initSplitters();
28655
29094
  wireLogSearch();
29095
+ wireSession();
28656
29096
  `;
28657
29097
  /**
28658
29098
  * Render the full studio HTML document. `appLabel` is shown in the
@@ -28676,6 +29116,16 @@ function renderStudioHtml(appLabel, cliName) {
28676
29116
  <span class="meta">${safeApp}</span>
28677
29117
  <span id="conn" class="down">● connecting</span>
28678
29118
  </header>
29119
+ <div id="session-bar">
29120
+ <span class="sess-title">Session</span>
29121
+ <label class="sess-bind"><input type="checkbox" id="sess-cfn" /> from-cfn-stack</label>
29122
+ <input id="sess-cfn-name" type="text" placeholder="stack name (blank = auto)" style="display:none" />
29123
+ <label class="sess-bind" for="sess-role">assume-role</label>
29124
+ <input id="sess-role" type="text" placeholder="arn:aws:iam::…:role/…" />
29125
+ <button id="sess-save" type="button">Save</button>
29126
+ <span id="sess-msg"></span>
29127
+ <span id="sess-synth" class="sess-synth"></span>
29128
+ </div>
28679
29129
  <main>
28680
29130
  <section class="pane" id="targets"><h2>Targets</h2></section>
28681
29131
  <div class="splitter" id="split-left"></div>
@@ -28688,6 +29138,7 @@ function renderStudioHtml(appLabel, cliName) {
28688
29138
  <div id="log-results"></div>
28689
29139
  </section>
28690
29140
  </main>
29141
+ <script>window.__OPTION_SPECS__ = ${JSON.stringify(OPTION_SPECS).replace(/</g, "\\u003c")};<\/script>
28691
29142
  <script>${STUDIO_SCRIPT}<\/script>
28692
29143
  </body>
28693
29144
  </html>`;
@@ -28812,6 +29263,16 @@ function handleRequest(req, res, bus, html, targetsJson, options) {
28812
29263
  res.end(JSON.stringify({ logs }));
28813
29264
  return;
28814
29265
  }
29266
+ if (req.method === "GET" && path === "/api/config") {
29267
+ const config = options.getConfig ? options.getConfig() : {};
29268
+ res.writeHead(200, { "content-type": "application/json; charset=utf-8" });
29269
+ res.end(JSON.stringify(config));
29270
+ return;
29271
+ }
29272
+ if (req.method === "PATCH" && path === "/api/config") {
29273
+ handleDispatch(req, res, options.patchConfig);
29274
+ return;
29275
+ }
28815
29276
  if (req.method === "GET" && path === "/api/events") {
28816
29277
  serveSse(req, res, bus);
28817
29278
  return;
@@ -29048,8 +29509,15 @@ function createStudioDispatcher(config) {
29048
29509
  req.targetId,
29049
29510
  "--event",
29050
29511
  eventFile,
29051
- ...buildSharedChildArgs(config)
29512
+ ...buildSharedChildArgs(config),
29513
+ ...buildPerRunArgs("lambda", req.options)
29052
29514
  ];
29515
+ const envVars = resolveEnvVars("lambda", req.options);
29516
+ if (envVars) {
29517
+ const envFile = join(dir, "env-vars.json");
29518
+ writeFileSync(envFile, JSON.stringify(envVars));
29519
+ args.push("--env-vars", envFile);
29520
+ }
29053
29521
  const { code, stdout, stderr } = await runChild(spawnFn, nodeBin, [config.cliEntry, ...args], config.cwd ?? process.cwd(), invocationId, req.targetId, config.bus, clock);
29054
29522
  const durationMs = clock() - startedAt;
29055
29523
  const ok = code === 0;
@@ -29485,12 +29953,13 @@ function createStudioServeManager(config) {
29485
29953
  if (message !== void 0) ev.message = message;
29486
29954
  config.bus.emit("serve", ev);
29487
29955
  }
29488
- function buildArgs(targetId, spec) {
29956
+ function buildArgs(req, spec) {
29489
29957
  return [
29490
29958
  spec.command,
29491
- targetId,
29959
+ req.targetId,
29492
29960
  ...spec.portArgs,
29493
- ...buildSharedChildArgs(config)
29961
+ ...buildSharedChildArgs(config),
29962
+ ...buildPerRunArgs(req.kind, req.options)
29494
29963
  ];
29495
29964
  }
29496
29965
  async function start(req) {
@@ -29501,7 +29970,7 @@ function createStudioServeManager(config) {
29501
29970
  const startedAt = clock();
29502
29971
  let child;
29503
29972
  try {
29504
- child = spawnFn(nodeBin, [config.cliEntry, ...buildArgs(req.targetId, spec)], { cwd });
29973
+ child = spawnFn(nodeBin, [config.cliEntry, ...buildArgs(req, spec)], { cwd });
29505
29974
  } catch (err) {
29506
29975
  throw err instanceof Error ? err : new Error(String(err));
29507
29976
  }
@@ -29711,13 +30180,21 @@ const STUDIO_TARGET_KINDS = [
29711
30180
  */
29712
30181
  function coerceRunRequest(body) {
29713
30182
  if (typeof body !== "object" || body === null) throw new Error("Request body must be a JSON object.");
29714
- const { targetId, kind, event } = body;
30183
+ const { targetId, kind, event, options } = body;
29715
30184
  if (typeof targetId !== "string" || targetId.trim() === "") throw new Error("Request body must include a non-empty \"targetId\" string.");
29716
30185
  if (typeof kind !== "string" || !STUDIO_TARGET_KINDS.includes(kind)) throw new Error(`Request body "kind" must be one of: ${STUDIO_TARGET_KINDS.join(", ")}.`);
30186
+ let runOptions;
30187
+ if (options !== void 0) {
30188
+ if (typeof options !== "object" || options === null || Array.isArray(options)) throw new Error("Request body \"options\" must be a JSON object keyed by option flag.");
30189
+ runOptions = options;
30190
+ buildPerRunArgs(kind, runOptions);
30191
+ resolveEnvVars(kind, runOptions);
30192
+ }
29717
30193
  return {
29718
30194
  targetId,
29719
30195
  kind,
29720
- event
30196
+ event,
30197
+ ...runOptions !== void 0 ? { options: runOptions } : {}
29721
30198
  };
29722
30199
  }
29723
30200
  /**
@@ -29731,6 +30208,32 @@ function coerceStopRequest(body) {
29731
30208
  if (typeof targetId !== "string" || targetId.trim() === "") throw new Error("Request body must include a non-empty \"targetId\" string.");
29732
30209
  return { targetId };
29733
30210
  }
30211
+ /**
30212
+ * Validate a `PATCH /api/config` body and apply the editable run-time
30213
+ * bindings (`fromCfnStack` / `assumeRole`) onto `target` in place. Only the
30214
+ * keys PRESENT in the body are touched (a partial update); `null` / `false` /
30215
+ * `''` clears a binding. Throws on a malformed body / value so a bad patch
30216
+ * fails loudly rather than silently mis-binding subsequent runs — the studio
30217
+ * server surfaces a thrown handler error as a 500 (same as every other
30218
+ * `/api/*` dispatch). The read-only synth context (profile / region / app) is
30219
+ * never patchable.
30220
+ */
30221
+ function applyConfigPatch(body, target) {
30222
+ if (typeof body !== "object" || body === null || Array.isArray(body)) throw new Error("Request body must be a JSON object.");
30223
+ const b = body;
30224
+ if ("fromCfnStack" in b) {
30225
+ const v = b["fromCfnStack"];
30226
+ if (v === null || v === false || v === "") delete target.fromCfnStack;
30227
+ else if (v === true || typeof v === "string") target.fromCfnStack = v;
30228
+ else throw new Error("\"fromCfnStack\" must be a string, boolean, or null.");
30229
+ }
30230
+ if ("assumeRole" in b) {
30231
+ const v = b["assumeRole"];
30232
+ if (v === null || v === "") delete target.assumeRole;
30233
+ else if (typeof v === "string") target.assumeRole = v;
30234
+ else throw new Error("\"assumeRole\" must be a string or null.");
30235
+ }
30236
+ }
29734
30237
  const DEFAULT_STUDIO_PORT = 9999;
29735
30238
  /**
29736
30239
  * Parse + validate the `--studio-port` value. Accepts `0` (OS-assigned)
@@ -29780,6 +30283,15 @@ async function localStudioCommand(options) {
29780
30283
  };
29781
30284
  const dispatcher = createStudioDispatcher(childConfig);
29782
30285
  const serveManager = createStudioServeManager(childConfig);
30286
+ const sessionConfigSnapshot = () => ({
30287
+ synth: {
30288
+ profile: childConfig.profile,
30289
+ region: childConfig.region,
30290
+ app: childConfig.app
30291
+ },
30292
+ fromCfnStack: childConfig.fromCfnStack,
30293
+ assumeRole: childConfig.assumeRole
30294
+ });
29783
30295
  const store = createStudioStore(bus);
29784
30296
  const server = await startStudioServer({
29785
30297
  port,
@@ -29799,7 +30311,12 @@ async function localStudioCommand(options) {
29799
30311
  await serveManager.stop(req);
29800
30312
  return { stopped: req.targetId };
29801
30313
  },
29802
- getRunning: () => ({ running: serveManager.list() })
30314
+ getRunning: () => ({ running: serveManager.list() }),
30315
+ getConfig: () => sessionConfigSnapshot(),
30316
+ patchConfig: (body) => {
30317
+ applyConfigPatch(body, childConfig);
30318
+ return Promise.resolve(sessionConfigSnapshot());
30319
+ }
29803
30320
  });
29804
30321
  const cliName = getEmbedConfig().cliName;
29805
30322
  logger.info(`${cliName} studio is running at ${server.url}`);
@@ -29872,5 +30389,5 @@ function addStudioSpecificOptions(cmd) {
29872
30389
  }
29873
30390
 
29874
30391
  //#endregion
29875
- export { setShadowReadyTimeoutMs as $, discoverWebSocketApis as $n, computeRequestIdentityHash as $t, addEcsAssumeRoleOptions as A, buildContainerImage as An, resolveApiTargetSubset as At, buildImageOverrideTag as B, createLocalStateProvider as Bn, groupRoutesByServer as Bt, addStartServiceSpecificOptions as C, buildMgmtEndpointEnvUrl as Cn, toCmdArgv as Ct, createLocalRunTaskCommand as D, buildDisconnectEvent as Dn, addStartApiSpecificOptions as Dt, addRunTaskSpecificOptions as E, buildConnectEvent as En, createLocalInvokeCommand as Et, parseRestartPolicy as F, substituteAgainstState as Fn, materializeLayerFromArn as Ft, runImageOverrideBuilds as G, resolveCfnStackName as Gn, defaultCredentialsLoader as Gt, mergeForService as H, rejectExplicitCfnStackWithMultipleStacks as Hn, startApiServer as Ht, resolveEcsAssumeRoleOption as I, substituteAgainstStateAsync as In, resolveEnvVars as It, listPinnedTargets as J, resolveSsmParameters as Jn, createJwksCache as Jt, describePinnedImageUri as K, CfnLocalStateProvider as Kn, buildCognitoJwksUrl as Kt, resolveSharedSidecarCredentials as L, substituteEnvVarsFromState as Ln, availableApiIdentifiers as Lt, buildEcsImageResolutionContext$1 as M, resolveRuntimeFileExtension as Mn, createFileWatcher as Mt, ecsClusterOption as N, resolveRuntimeImage as Nn, attachStageContext as Nt, MAX_TASKS_SUBNET_RANGE_CAP as O, buildMessageEvent as On, createLocalStartApiCommand as Ot, parseMaxTasks as P, EcsTaskResolutionError as Pn, buildStageMap as Pt, SOFT_RELOAD_COMPLETION_LOG_SUFFIX as Q, listTargets as Qn, buildMethodArn as Qt, runEcsServiceEmulator as R, substituteEnvVarsFromStateAsync as Rn, filterRoutesByApiIdentifier as Rt, resolveAlbFrontDoor as S, ConnectionRegistry as Sn, renderCodeDockerfile as St, serviceStrategy as T, parseConnectionsPath as Tn, addInvokeSpecificOptions as Tt, parseImageOverrideFlags as U, resolveCfnFallbackRegion as Un, resolveSelectionExpression as Ut, enforceImageOverrideOrphans as V, isCfnFlagPresent as Vn, readMtlsMaterialsFromDisk as Vt, resolveImageOverrides as W, resolveCfnRegion as Wn, resolveServiceIntegrationParameters as Wt, CloudMapRegistry as X, resolveSingleTarget as Xn, verifyJwtAuthorizer as Xt, buildCloudMapIndex as Y, resolveWatchConfig as Yn, verifyCognitoJwt as Yt, DEFAULT_SHADOW_READY_TIMEOUT_MS as Z, countTargets as Zn, verifyJwtViaDiscovery as Zt, albStrategy as _, tryParseStatus as _n, LocalInvokeBuildError as _r, waitForAgentCorePing as _t, createStudioServeManager as a, buildCorsConfigByApiId as an, AGENTCORE_A2A_PROTOCOL as ar, A2A_CONTAINER_PORT as at, resolveAlbTarget as b, probeHostGatewaySupport as bn, buildAgentCoreCodeImage as bt, startStudioServer as c, matchPreflight as cn, AGENTCORE_MCP_PROTOCOL as cr, MCP_CONTAINER_PORT as ct, createStudioStore as d, applyAuthorizerOverlay as dn, pickAgentCoreCandidateStack as dr, mcpInvokeOnce as dt, evaluateCachedLambdaPolicy as en, discoverWebSocketApisOrThrow as er, getContainerNetworkIp as et, StudioEventBus as f, buildHttpApiV2Event as fn, resolveAgentCoreTarget as fr, parseSseForJsonRpc as ft, addAlbSpecificOptions as g, selectIntegrationResponse as gn, tryResolveImageFnJoin as gr, invokeAgentCore as gt, formatTargetListing as h, pickResponseTemplate as hn, substituteImagePlaceholders as hr, AGENTCORE_SESSION_ID_HEADER as ht, createLocalStudioCommand as i, applyCorsResponseHeaders as in, resolveLambdaArnIntrinsic as ir, invokeAgentCoreWs as it, addImageOverrideOptions as j, resolveRuntimeCodeMountPath as jn, createAuthorizerCache as jt, addCommonEcsServiceOptions as k, architectureToPlatform as kn, createWatchPredicates as kt, toStudioTargetGroups as l, matchRoute as ln, AGENTCORE_RUNTIME_TYPE as lr, MCP_PATH as lt, createLocalListCommand as m, evaluateResponseParameters as mn, formatStateRemedy as mr, signAgentCoreInvocation as mt, coerceRunRequest as n, invokeTokenAuthorizer as nn, discoverRoutes as nr, addInvokeAgentCoreSpecificOptions as nt, startStudioProxy as o, buildCorsConfigFromCloudFrontChain as on, AGENTCORE_AGUI_PROTOCOL as or, A2A_PATH as ot, addListSpecificOptions as p, buildRestV1Event as pn, derivePseudoParametersFromRegion as pr, AGENTCORE_SIGV4_SERVICE as pt, isLocalCdkAssetImage as q, collectSsmParameterRefs as qn, buildJwksUrlFromIssuer as qt, coerceStopRequest as r, attachAuthorizers as rn, pickRefLogicalId as rr, createLocalInvokeAgentCoreCommand as rt, createStudioDispatcher as s, isFunctionUrlOacFronted as sn, AGENTCORE_HTTP_PROTOCOL as sr, a2aInvokeOnce as st, addStudioSpecificOptions as t, invokeRequestAuthorizer as tn, parseSelectionExpressionPath as tr, attachContainerLogStreamer as tt, renderStudioHtml as u, translateLambdaResponse as un, AgentCoreResolutionError as ur, MCP_PROTOCOL_VERSION as ut, createLocalStartAlbCommand as v, VtlEvaluationError as vn, buildStsClientConfig as vr, downloadAndExtractS3Bundle as vt, createLocalStartServiceCommand as w, handleConnectionsRequest as wn, classifySourceChange as wt, isApplicationLoadBalancer as x, bufferToBody as xn, computeCodeImageTag as xt, parseLbPortOverrides as y, HOST_GATEWAY_MIN_VERSION as yn, resolveProfileCredentials as yr, SUPPORTED_CODE_RUNTIMES as yt, ImageOverrideError as z, LocalStateSourceError as zn, filterRoutesByApiIdentifiers as zt };
29876
- //# sourceMappingURL=local-studio-DaJ3D7co.js.map
30392
+ export { setShadowReadyTimeoutMs as $, discoverWebSocketApis as $n, computeRequestIdentityHash as $t, addEcsAssumeRoleOptions as A, buildContainerImage as An, resolveApiTargetSubset as At, buildImageOverrideTag as B, createLocalStateProvider as Bn, groupRoutesByServer as Bt, addStartServiceSpecificOptions as C, buildMgmtEndpointEnvUrl as Cn, toCmdArgv as Ct, createLocalRunTaskCommand as D, buildDisconnectEvent as Dn, addStartApiSpecificOptions as Dt, addRunTaskSpecificOptions as E, buildConnectEvent as En, createLocalInvokeCommand as Et, parseRestartPolicy as F, substituteAgainstState as Fn, materializeLayerFromArn as Ft, runImageOverrideBuilds as G, resolveCfnStackName as Gn, defaultCredentialsLoader as Gt, mergeForService as H, rejectExplicitCfnStackWithMultipleStacks as Hn, startApiServer as Ht, resolveEcsAssumeRoleOption as I, substituteAgainstStateAsync as In, resolveEnvVars$1 as It, listPinnedTargets as J, resolveSsmParameters as Jn, createJwksCache as Jt, describePinnedImageUri as K, CfnLocalStateProvider as Kn, buildCognitoJwksUrl as Kt, resolveSharedSidecarCredentials as L, substituteEnvVarsFromState as Ln, availableApiIdentifiers as Lt, buildEcsImageResolutionContext$1 as M, resolveRuntimeFileExtension as Mn, createFileWatcher as Mt, ecsClusterOption as N, resolveRuntimeImage as Nn, attachStageContext as Nt, MAX_TASKS_SUBNET_RANGE_CAP as O, buildMessageEvent as On, createLocalStartApiCommand as Ot, parseMaxTasks as P, EcsTaskResolutionError as Pn, buildStageMap as Pt, SOFT_RELOAD_COMPLETION_LOG_SUFFIX as Q, listTargets as Qn, buildMethodArn as Qt, runEcsServiceEmulator as R, substituteEnvVarsFromStateAsync as Rn, filterRoutesByApiIdentifier as Rt, resolveAlbFrontDoor as S, ConnectionRegistry as Sn, renderCodeDockerfile as St, serviceStrategy as T, parseConnectionsPath as Tn, addInvokeSpecificOptions as Tt, parseImageOverrideFlags as U, resolveCfnFallbackRegion as Un, resolveSelectionExpression as Ut, enforceImageOverrideOrphans as V, isCfnFlagPresent as Vn, readMtlsMaterialsFromDisk as Vt, resolveImageOverrides as W, resolveCfnRegion as Wn, resolveServiceIntegrationParameters as Wt, CloudMapRegistry as X, resolveSingleTarget as Xn, verifyJwtAuthorizer as Xt, buildCloudMapIndex as Y, resolveWatchConfig as Yn, verifyCognitoJwt as Yt, DEFAULT_SHADOW_READY_TIMEOUT_MS as Z, countTargets as Zn, verifyJwtViaDiscovery as Zt, albStrategy as _, tryParseStatus as _n, LocalInvokeBuildError as _r, waitForAgentCorePing as _t, createStudioServeManager as a, buildCorsConfigByApiId as an, AGENTCORE_A2A_PROTOCOL as ar, A2A_CONTAINER_PORT as at, resolveAlbTarget as b, probeHostGatewaySupport as bn, buildAgentCoreCodeImage as bt, startStudioServer as c, matchPreflight as cn, AGENTCORE_MCP_PROTOCOL as cr, MCP_CONTAINER_PORT as ct, createStudioStore as d, applyAuthorizerOverlay as dn, pickAgentCoreCandidateStack as dr, mcpInvokeOnce as dt, evaluateCachedLambdaPolicy as en, discoverWebSocketApisOrThrow as er, getContainerNetworkIp as et, StudioEventBus as f, buildHttpApiV2Event as fn, resolveAgentCoreTarget as fr, parseSseForJsonRpc as ft, addAlbSpecificOptions as g, selectIntegrationResponse as gn, tryResolveImageFnJoin as gr, invokeAgentCore as gt, formatTargetListing as h, pickResponseTemplate as hn, substituteImagePlaceholders as hr, AGENTCORE_SESSION_ID_HEADER as ht, createLocalStudioCommand as i, applyCorsResponseHeaders as in, resolveLambdaArnIntrinsic as ir, invokeAgentCoreWs as it, addImageOverrideOptions as j, resolveRuntimeCodeMountPath as jn, createAuthorizerCache as jt, addCommonEcsServiceOptions as k, architectureToPlatform as kn, createWatchPredicates as kt, toStudioTargetGroups as l, matchRoute as ln, AGENTCORE_RUNTIME_TYPE as lr, MCP_PATH as lt, createLocalListCommand as m, evaluateResponseParameters as mn, formatStateRemedy as mr, signAgentCoreInvocation as mt, coerceRunRequest as n, invokeTokenAuthorizer as nn, discoverRoutes as nr, addInvokeAgentCoreSpecificOptions as nt, startStudioProxy as o, buildCorsConfigFromCloudFrontChain as on, AGENTCORE_AGUI_PROTOCOL as or, A2A_PATH as ot, addListSpecificOptions as p, buildRestV1Event as pn, derivePseudoParametersFromRegion as pr, AGENTCORE_SIGV4_SERVICE as pt, isLocalCdkAssetImage as q, collectSsmParameterRefs as qn, buildJwksUrlFromIssuer as qt, coerceStopRequest as r, attachAuthorizers as rn, pickRefLogicalId as rr, createLocalInvokeAgentCoreCommand as rt, createStudioDispatcher as s, isFunctionUrlOacFronted as sn, AGENTCORE_HTTP_PROTOCOL as sr, a2aInvokeOnce as st, addStudioSpecificOptions as t, invokeRequestAuthorizer as tn, parseSelectionExpressionPath as tr, attachContainerLogStreamer as tt, renderStudioHtml as u, translateLambdaResponse as un, AgentCoreResolutionError as ur, MCP_PROTOCOL_VERSION as ut, createLocalStartAlbCommand as v, VtlEvaluationError as vn, buildStsClientConfig as vr, downloadAndExtractS3Bundle as vt, createLocalStartServiceCommand as w, handleConnectionsRequest as wn, classifySourceChange as wt, isApplicationLoadBalancer as x, bufferToBody as xn, computeCodeImageTag as xt, parseLbPortOverrides as y, HOST_GATEWAY_MIN_VERSION as yn, resolveProfileCredentials as yr, SUPPORTED_CODE_RUNTIMES as yt, ImageOverrideError as z, LocalStateSourceError as zn, filterRoutesByApiIdentifiers as zt };
30393
+ //# sourceMappingURL=local-studio-Cnpre8fu.js.map