@base44-preview/cli 0.1.15-pr.630.5b0c119 → 0.1.15-pr.630.5c9bc15

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.
package/dist/cli/index.js CHANGED
@@ -268401,6 +268401,10 @@ async function captureRequestBody(request, options) {
268401
268401
  if (request.body == null) {
268402
268402
  return;
268403
268403
  }
268404
+ if (options.context.__redactBody) {
268405
+ options.context.__requestBody = "[redacted]";
268406
+ return;
268407
+ }
268404
268408
  try {
268405
268409
  const cloned = request.clone();
268406
268410
  const text = await cloned.text();
@@ -270155,7 +270159,7 @@ function eventLine(event, elapsedMs, options = {}) {
270155
270159
  return null;
270156
270160
  case "waiting": {
270157
270161
  const what = event.label || toolAlias(event.name);
270158
- return source_default.yellow(`⏸ ${what} — needs your input (answer in the editor)`);
270162
+ return source_default.yellow(`⏸ ${what} — needs your input (${options.waitingHint ?? "answer in the editor"})`);
270159
270163
  }
270160
270164
  case "tool_end": {
270161
270165
  const alias = toolAlias(event.name);
@@ -270343,6 +270347,10 @@ var CreatedAppSchema = object({
270343
270347
  name: string2().nullish(),
270344
270348
  imported_repo_url: string2().nullish()
270345
270349
  });
270350
+ var WixCreatedAppSchema = object({
270351
+ app_id: string2().min(1),
270352
+ client_creation_id: string2().min(1)
270353
+ });
270346
270354
  var AppStateSchema = object({
270347
270355
  id: string2(),
270348
270356
  app_type: string2().nullish(),
@@ -270382,7 +270390,8 @@ var ConversationMessageSchema = object({
270382
270390
  name: string2(),
270383
270391
  arguments_string: string2().nullish(),
270384
270392
  status: string2().nullish(),
270385
- results: unknown().nullish()
270393
+ results: unknown().nullish(),
270394
+ waiting_on: object({ kind: string2().nullish() }).nullish()
270386
270395
  })).nullish()
270387
270396
  });
270388
270397
  var FullConversationSchema = object({
@@ -270399,6 +270408,24 @@ function parseOrThrow(schema, payload, what) {
270399
270408
  function branchScope(branchId) {
270400
270409
  return branchId ? { branch_id: branchId } : {};
270401
270410
  }
270411
+ async function createWixLaunchedApp(options) {
270412
+ let response;
270413
+ try {
270414
+ response = await base44Client.post("api/wix/create-app", {
270415
+ timeout: false,
270416
+ context: { __redactBody: true },
270417
+ json: {
270418
+ prompt: options.prompt,
270419
+ signed_instance: options.signedInstance,
270420
+ ...options.wixClientId ? { wix_client_id: options.wixClientId } : {}
270421
+ }
270422
+ });
270423
+ } catch (error) {
270424
+ throw await ApiError.fromHttpError(error, "creating app via Wix launch");
270425
+ }
270426
+ const created = parseOrThrow(WixCreatedAppSchema, await response.json(), "app");
270427
+ return { id: created.app_id, client_creation_id: created.client_creation_id };
270428
+ }
270402
270429
  async function createApp(options) {
270403
270430
  let response;
270404
270431
  try {
@@ -270456,6 +270483,25 @@ async function getAppState(appId) {
270456
270483
  }
270457
270484
  return parseOrThrow(AppStateSchema, await response.json(), "app status");
270458
270485
  }
270486
+ async function answerToolCall(options, branchId) {
270487
+ let response;
270488
+ try {
270489
+ response = await getAppClient().post("chat/submit-tool-call-input", {
270490
+ timeout: false,
270491
+ context: { __redactBody: true },
270492
+ searchParams: branchScope(branchId),
270493
+ json: {
270494
+ tool_call_id: options.toolCallId,
270495
+ action: options.action,
270496
+ extra_user_input: options.input ?? {},
270497
+ ...options.messageId ? { message_id: options.messageId } : {}
270498
+ }
270499
+ });
270500
+ } catch (error) {
270501
+ throw await ApiError.fromHttpError(error, "answering the agent");
270502
+ }
270503
+ return parseOrThrow(ChatTurnSchema, await response.json(), "chat turn");
270504
+ }
270459
270505
  async function sendTurn(content, branchId) {
270460
270506
  let response;
270461
270507
  try {
@@ -270528,12 +270574,32 @@ function inventAppName(prompt) {
270528
270574
  function repoBasename(repoUrl) {
270529
270575
  return repoUrl.replace(/\/+$/, "").replace(/\.git$/, "").split("/").pop() ?? "app";
270530
270576
  }
270577
+ function parseWixLaunchUrl(raw) {
270578
+ let url;
270579
+ try {
270580
+ url = new URL(raw.trim());
270581
+ } catch {
270582
+ throw new InvalidInputError("--wix-launch expects the full launch URL.");
270583
+ }
270584
+ const fragment = new URLSearchParams(url.hash.replace(/^#/, ""));
270585
+ const signedInstance = fragment.get("wix-signed-instance")?.trim();
270586
+ if (!signedInstance) {
270587
+ throw new InvalidInputError("The launch URL has no #wix-signed-instance — copy the whole URL the funnel printed.");
270588
+ }
270589
+ const prompt = url.searchParams.get("prompt")?.trim();
270590
+ const wixClientId = fragment.get("wix-client-id")?.trim();
270591
+ return {
270592
+ ...prompt ? { prompt } : {},
270593
+ signedInstance,
270594
+ ...wixClientId ? { wixClientId } : {}
270595
+ };
270596
+ }
270531
270597
  async function createAndLinkApp(options) {
270532
270598
  if (options.name && !APP_NAME_RE.test(options.name)) {
270533
270599
  throw new InvalidInputError("The name becomes a directory — letters, digits, dots, dashes and underscores only.");
270534
270600
  }
270535
270601
  const cwd = process.cwd();
270536
- const fallbackName = () => options.importRepo ? repoBasename(options.importRepo) : inventAppName(options.prompt);
270602
+ const fallbackName = () => options.importRepo ? repoBasename(options.importRepo) : inventAppName(options.prompt ?? options.wixLaunch?.prompt);
270537
270603
  const chosenDir = options.path ? resolve8(cwd, options.path) : await isDirEmpty(cwd) ? cwd : undefined;
270538
270604
  const dirBase = chosenDir ? basename6(chosenDir) : undefined;
270539
270605
  const name = options.name ?? (dirBase && APP_NAME_RE.test(dirBase) ? dirBase : fallbackName());
@@ -270544,7 +270610,15 @@ async function createAndLinkApp(options) {
270544
270610
  if (await appConfigExists(targetDir)) {
270545
270611
  throw new InvalidInputError(here ? "This directory is already linked to a Base44 app. Run `base44 code` here to keep building it, or pass --path for a new one." : `./${dirName} is already linked to a Base44 app. Pick another name or --path.`);
270546
270612
  }
270547
- const created = options.importRepo ? await createImportedApp({
270613
+ let clientCreationId;
270614
+ const created = options.wixLaunch ? await createWixLaunchedApp({
270615
+ prompt: options.prompt ?? options.wixLaunch.prompt ?? "",
270616
+ signedInstance: options.wixLaunch.signedInstance,
270617
+ wixClientId: options.wixLaunch.wixClientId
270618
+ }).then((c) => {
270619
+ clientCreationId = c.client_creation_id;
270620
+ return c;
270621
+ }) : options.importRepo ? await createImportedApp({
270548
270622
  appName: name,
270549
270623
  repoUrl: options.importRepo,
270550
270624
  sourceMode: options.mode ?? "direct",
@@ -270568,7 +270642,8 @@ async function createAndLinkApp(options) {
270568
270642
  repoUrl: created.imported_repo_url ?? undefined,
270569
270643
  dirName,
270570
270644
  targetDir,
270571
- here
270645
+ here,
270646
+ ...clientCreationId ? { clientCreationId } : {}
270572
270647
  };
270573
270648
  }
270574
270649
  function repoLabel(url) {
@@ -270920,6 +270995,12 @@ function getSendCommand() {
270920
270995
  // src/cli/commands/builder/new.ts
270921
270996
  var POLL_TIMEOUT_MS = 20 * 60000;
270922
270997
  var MODES = ["direct", "fork", "copy"];
270998
+ async function readStdin2() {
270999
+ const chunks = [];
271000
+ for await (const chunk of process.stdin)
271001
+ chunks.push(chunk);
271002
+ return Buffer.concat(chunks).toString("utf8");
271003
+ }
270923
271004
  async function newAction({ log, runTask, jsonMode }, prompt, options) {
270924
271005
  if (options.mode && !MODES.includes(options.mode)) {
270925
271006
  throw new InvalidInputError("--mode must be direct, fork, or copy.");
@@ -270927,8 +271008,15 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
270927
271008
  if ((options.mode || options.repoName || options.fromBranch) && !options.import) {
270928
271009
  throw new InvalidInputError("--mode, --repo-name and --from-branch apply only with --import <repo>.");
270929
271010
  }
270930
- if (!prompt && !options.import) {
270931
- throw new InvalidInputError('Describe the app ("<prompt>") or pass --import <repo>.');
271011
+ if (options.wixLaunch && options.import) {
271012
+ throw new InvalidInputError("--wix-launch and --import are exclusive.");
271013
+ }
271014
+ const wixLaunch = options.wixLaunch ? parseWixLaunchUrl(options.wixLaunch === "-" ? await readStdin2() : options.wixLaunch) : undefined;
271015
+ if (wixLaunch && !prompt && !wixLaunch.prompt) {
271016
+ throw new InvalidInputError("The launch URL has no ?prompt= — pass the prompt as the argument.");
271017
+ }
271018
+ if (!prompt && !options.import && !wixLaunch) {
271019
+ throw new InvalidInputError('Describe the app ("<prompt>") or pass --import <repo> / --wix-launch <url>.');
270932
271020
  }
270933
271021
  if (options.streamJson && jsonMode) {
270934
271022
  throw new InvalidInputError("--stream-json and --json are exclusive.");
@@ -270943,7 +271031,8 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
270943
271031
  mode: options.mode,
270944
271032
  repoName: options.repoName,
270945
271033
  fromBranch: options.fromBranch,
270946
- path: options.path
271034
+ path: options.path,
271035
+ wixLaunch
270947
271036
  }));
270948
271037
  } catch (error) {
270949
271038
  for (const line of await githubReauthLines(error) ?? [])
@@ -270957,11 +271046,15 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
270957
271046
  repo_url: app.repoUrl ?? null,
270958
271047
  editor_url: app.editorUrl,
270959
271048
  dir: app.dirName,
270960
- path: app.targetDir
271049
+ path: app.targetDir,
271050
+ ...app.clientCreationId ? { client_creation_id: app.clientCreationId } : {}
270961
271051
  });
270962
271052
  } else if (!jsonMode) {
270963
271053
  if (app.repoUrl)
270964
271054
  log.message(source_default.dim(`repo ${app.repoUrl}`));
271055
+ if (app.clientCreationId) {
271056
+ log.message(source_default.dim("wix launched — connector connected before the first turn"));
271057
+ }
270965
271058
  log.message(source_default.dim(`editor ${app.editorUrl}`));
270966
271059
  log.message(source_default.dim(`linked ${app.here ? "./ (this directory)" : `./${app.dirName}`}`));
270967
271060
  }
@@ -271012,7 +271105,8 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
271012
271105
  preview_url: previewUrl ?? null,
271013
271106
  dir: app.dirName,
271014
271107
  path: app.targetDir,
271015
- status: finalState ?? "created"
271108
+ status: finalState ?? "created",
271109
+ ...app.clientCreationId ? { client_creation_id: app.clientCreationId } : {}
271016
271110
  })}
271017
271111
  `
271018
271112
  };
@@ -271037,7 +271131,7 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
271037
271131
  }
271038
271132
  function getNewCommand() {
271039
271133
  const command = new Base44Command("new", { requireAppContext: false });
271040
- command.description("Create an app and start building: from a prompt (the Base44 template), or over an existing GitHub repo with --import").argument("[prompt]", "What to build; the first agent turn starts immediately").option("--import <repo>", "Build over an existing GitHub repository instead of the template").option("--mode <mode>", "How to import: direct, fork, or copy (default: direct)").option("--name <name>", "Directory and app name (invented when omitted)").option("--path <dir>", "Directory to link (default: the current directory when empty, else ./<name>)").option("--repo-name <name>", "Name for the new GitHub repo when forking/copying").option("--from-branch <name>", "Import a specific branch of the repo").option("--verbose", "Show every tool result in full (no folding)").option("--stream-json", "Emit each stream event as a JSON line as it happens, then a final result line").action(newAction);
271134
+ command.description("Create an app and start building: from a prompt (the Base44 template), or over an existing GitHub repo with --import").argument("[prompt]", "What to build; the first agent turn starts immediately").option("--import <repo>", "Build over an existing GitHub repository instead of the template").option("--mode <mode>", "How to import: direct, fork, or copy (default: direct)").option("--name <name>", "Directory and app name (invented when omitted)").option("--path <dir>", "Directory to link (default: the current directory when empty, else ./<name>)").option("--repo-name <name>", "Name for the new GitHub repo when forking/copying").option("--from-branch <name>", "Import a specific branch of the repo").addOption(new Option2("--wix-launch <url>", `Create through a Wix launch URL (the funnel's ?prompt= and #wix-signed-instance); "-" reads it from stdin. A prompt argument is what the agent runs instead of the URL's`).env("BASE44_WIX_LAUNCH_URL")).option("--verbose", "Show every tool result in full (no folding)").option("--stream-json", "Emit each stream event as a JSON line as it happens, then a final result line").action(newAction);
271041
271135
  return command;
271042
271136
  }
271043
271137
 
@@ -276232,6 +276326,393 @@ function createPasteFriendlyStdin(real) {
276232
276326
  return proxy;
276233
276327
  }
276234
276328
 
276329
+ // src/core/resources/apps/pending.ts
276330
+ var CHOICE_TOOLS = new Set([
276331
+ "ask_clarifying_questions",
276332
+ "ask_plan_questions"
276333
+ ]);
276334
+ var SECRET_TOOLS = new Set(["set_secrets"]);
276335
+ var PERMISSION_TOOLS = new Set(["request_agent_tool_permissions"]);
276336
+ var BROWSER_TOOLS = new Set([
276337
+ "connect_github_account",
276338
+ "request_oauth_authorization",
276339
+ "register_workspace_connector",
276340
+ "configure_psp_credentials",
276341
+ "plaid_connect"
276342
+ ]);
276343
+ var str2 = (v) => typeof v === "string" && v.trim() ? v.trim() : undefined;
276344
+ function parseArgs(raw) {
276345
+ try {
276346
+ const parsed = JSON.parse(raw ?? "");
276347
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
276348
+ } catch {
276349
+ return {};
276350
+ }
276351
+ }
276352
+ function questionsFrom(args) {
276353
+ const raw = Array.isArray(args.questions) ? args.questions : [];
276354
+ return raw.flatMap((q) => {
276355
+ if (!q || typeof q !== "object")
276356
+ return [];
276357
+ const item = q;
276358
+ const question = str2(item.question);
276359
+ if (!question)
276360
+ return [];
276361
+ const options = (Array.isArray(item.options) ? item.options : []).flatMap((o) => {
276362
+ const opt = o;
276363
+ const label = str2(opt?.label);
276364
+ return label ? [{ label, description: str2(opt.description) }] : [];
276365
+ });
276366
+ return [
276367
+ {
276368
+ question,
276369
+ description: str2(item.description),
276370
+ options,
276371
+ multiSelect: item.multi_select === true
276372
+ }
276373
+ ];
276374
+ });
276375
+ }
276376
+ function secretsFrom(args) {
276377
+ const raw = Array.isArray(args.secrets_schema) ? args.secrets_schema : [];
276378
+ return raw.flatMap((s) => {
276379
+ const item = s;
276380
+ const name = str2(item?.secretName) ?? str2(item?.name);
276381
+ return name ? [{ name, description: str2(item.description) }] : [];
276382
+ });
276383
+ }
276384
+ function permissionKey(row) {
276385
+ switch (row.type) {
276386
+ case "entity":
276387
+ return row.entity_name ? `entity:${row.entity_name}` : null;
276388
+ case "backend_function":
276389
+ return row.function_name ? `backend_function:${row.function_name}` : null;
276390
+ case "app_user_connector":
276391
+ return row.connector_id ? `app_user_connector:${row.connector_id}` : null;
276392
+ default:
276393
+ return null;
276394
+ }
276395
+ }
276396
+ function permissionsFrom(args) {
276397
+ const raw = Array.isArray(args.requested_permissions) ? args.requested_permissions : [];
276398
+ return raw.flatMap((r) => {
276399
+ const row = r;
276400
+ const key = permissionKey(row);
276401
+ if (!key)
276402
+ return [];
276403
+ const ops = Array.isArray(row.allowed_operations) ? ` (${row.allowed_operations.join(", ")})` : "";
276404
+ const target = str2(row.entity_name) ?? str2(row.function_name) ?? str2(row.connector_name) ?? key;
276405
+ return [
276406
+ { key, label: `${row.type}: ${target}${ops}`, reason: str2(row.reason) }
276407
+ ];
276408
+ });
276409
+ }
276410
+ function guardFrom(results) {
276411
+ const value = typeof results === "string" ? (() => {
276412
+ try {
276413
+ return JSON.parse(results);
276414
+ } catch {
276415
+ return null;
276416
+ }
276417
+ })() : results;
276418
+ if (!value || typeof value !== "object")
276419
+ return null;
276420
+ const g = value;
276421
+ if (!str2(g.guard))
276422
+ return null;
276423
+ return { title: `${g.guard}: needs your approval`, detail: str2(g.reason) };
276424
+ }
276425
+ function humanize(tool) {
276426
+ return tool.replace(/_/g, " ");
276427
+ }
276428
+ function pendingInputs(messages) {
276429
+ const out = [];
276430
+ for (const message of messages) {
276431
+ for (const call of message.tool_calls ?? []) {
276432
+ if (call.status !== "waiting_for_user_input")
276433
+ continue;
276434
+ const args = parseArgs(call.arguments_string);
276435
+ const base = {
276436
+ toolCallId: call.id,
276437
+ messageId: message.id,
276438
+ tool: call.name
276439
+ };
276440
+ const summary = str2(args.summary);
276441
+ if (CHOICE_TOOLS.has(call.name)) {
276442
+ out.push({
276443
+ ...base,
276444
+ kind: "choice",
276445
+ title: summary ?? "The agent has a few questions",
276446
+ questions: questionsFrom(args)
276447
+ });
276448
+ } else if (SECRET_TOOLS.has(call.name)) {
276449
+ out.push({
276450
+ ...base,
276451
+ kind: "secrets",
276452
+ title: summary ?? "The agent needs secrets",
276453
+ secrets: secretsFrom(args)
276454
+ });
276455
+ } else if (PERMISSION_TOOLS.has(call.name)) {
276456
+ out.push({
276457
+ ...base,
276458
+ kind: "permissions",
276459
+ title: summary ?? "Grant the app's agent these permissions?",
276460
+ detail: str2(args.reason),
276461
+ permissions: permissionsFrom(args)
276462
+ });
276463
+ } else if (BROWSER_TOOLS.has(call.name)) {
276464
+ out.push({
276465
+ ...base,
276466
+ kind: "browser",
276467
+ title: summary ?? humanize(call.name),
276468
+ detail: str2(args.reason)
276469
+ });
276470
+ } else {
276471
+ const guard = guardFrom(call.results);
276472
+ const integration = str2(args.integration_type);
276473
+ out.push({
276474
+ ...base,
276475
+ kind: "approval",
276476
+ title: guard?.title ?? (integration ? `Enable ${integration}?` : summary ?? `${humanize(call.name)}?`),
276477
+ detail: guard?.detail ?? (integration ? summary : undefined)
276478
+ });
276479
+ }
276480
+ }
276481
+ }
276482
+ return out;
276483
+ }
276484
+ function choiceAnswers(questions, selections) {
276485
+ const answers = questions.flatMap((q, index) => {
276486
+ const sel = selections[index];
276487
+ if (!sel || sel.labels.length === 0 && !sel.customText)
276488
+ return [];
276489
+ const answer = { question_index: index };
276490
+ if (q.multiSelect) {
276491
+ if (sel.labels.length)
276492
+ answer.selected_labels = sel.labels;
276493
+ } else if (sel.labels[0]) {
276494
+ answer.selected_label = sel.labels[0];
276495
+ }
276496
+ if (sel.customText)
276497
+ answer.custom_text = sel.customText;
276498
+ return [answer];
276499
+ });
276500
+ return { answers };
276501
+ }
276502
+
276503
+ // src/cli/commands/code/pending-card.ts
276504
+ function openCard(pending) {
276505
+ return {
276506
+ pending,
276507
+ step: 0,
276508
+ cursor: 0,
276509
+ selections: (pending.questions ?? []).map(() => ({ labels: [] })),
276510
+ granted: new Set((pending.permissions ?? []).map((p) => p.key)),
276511
+ typing: pending.kind === "secrets" ? "secret" : null,
276512
+ secretValues: {}
276513
+ };
276514
+ }
276515
+ var done = (action, input = {}) => ({ state: null, submit: { action, input } });
276516
+ var later = { state: null, dismissed: true };
276517
+ function choiceRows(state) {
276518
+ return (state.pending.questions?.[state.step]?.options.length ?? 0) + 1;
276519
+ }
276520
+ function advanceChoice(state) {
276521
+ const questions = state.pending.questions ?? [];
276522
+ if (state.step + 1 < questions.length) {
276523
+ return {
276524
+ state: { ...state, step: state.step + 1, cursor: 0, typing: null }
276525
+ };
276526
+ }
276527
+ return done("approved", choiceAnswers(questions, state.selections));
276528
+ }
276529
+ function choiceKey(state, key) {
276530
+ const question = state.pending.questions?.[state.step];
276531
+ if (!question)
276532
+ return done("approved", { answers: [] });
276533
+ const rows = choiceRows(state);
276534
+ const custom = state.cursor === rows - 1;
276535
+ const sel = state.selections[state.step] ?? { labels: [] };
276536
+ const setSel = (next) => {
276537
+ const selections = [...state.selections];
276538
+ selections[state.step] = next;
276539
+ return { ...state, selections };
276540
+ };
276541
+ switch (key) {
276542
+ case "up":
276543
+ return { state: { ...state, cursor: (state.cursor - 1 + rows) % rows } };
276544
+ case "down":
276545
+ return { state: { ...state, cursor: (state.cursor + 1) % rows } };
276546
+ case "space": {
276547
+ if (custom)
276548
+ return { state: { ...state, typing: "custom" } };
276549
+ const label = question.options[state.cursor].label;
276550
+ const labels = question.multiSelect ? sel.labels.includes(label) ? sel.labels.filter((l) => l !== label) : [...sel.labels, label] : [label];
276551
+ return { state: setSel({ ...sel, labels }) };
276552
+ }
276553
+ case "enter": {
276554
+ if (custom)
276555
+ return { state: { ...state, typing: "custom" } };
276556
+ if (question.multiSelect) {
276557
+ if (sel.labels.length === 0 && !sel.customText)
276558
+ return { state };
276559
+ return advanceChoice(state);
276560
+ }
276561
+ const label = question.options[state.cursor].label;
276562
+ return advanceChoice(setSel({ labels: [label] }));
276563
+ }
276564
+ case "s":
276565
+ return done("approved", { answers: [] });
276566
+ case "escape":
276567
+ return later;
276568
+ default:
276569
+ return { state };
276570
+ }
276571
+ }
276572
+ function permissionsKey(state, key) {
276573
+ const rows = state.pending.permissions ?? [];
276574
+ switch (key) {
276575
+ case "up":
276576
+ return {
276577
+ state: {
276578
+ ...state,
276579
+ cursor: (state.cursor - 1 + rows.length) % rows.length
276580
+ }
276581
+ };
276582
+ case "down":
276583
+ return { state: { ...state, cursor: (state.cursor + 1) % rows.length } };
276584
+ case "space": {
276585
+ const k = rows[state.cursor]?.key;
276586
+ if (!k)
276587
+ return { state };
276588
+ const granted = new Set(state.granted);
276589
+ if (granted.has(k))
276590
+ granted.delete(k);
276591
+ else
276592
+ granted.add(k);
276593
+ return { state: { ...state, granted } };
276594
+ }
276595
+ case "enter":
276596
+ case "y":
276597
+ return done("approved", {
276598
+ approved_permission_keys: rows.map((r) => r.key).filter((k) => state.granted.has(k))
276599
+ });
276600
+ case "n":
276601
+ return done("rejected");
276602
+ case "escape":
276603
+ return later;
276604
+ default:
276605
+ return { state };
276606
+ }
276607
+ }
276608
+ function cardKey(state, key) {
276609
+ if (state.typing) {
276610
+ if (key === "escape") {
276611
+ return state.typing === "secret" ? later : { state: { ...state, typing: null } };
276612
+ }
276613
+ return { state };
276614
+ }
276615
+ switch (state.pending.kind) {
276616
+ case "choice":
276617
+ return choiceKey(state, key);
276618
+ case "permissions":
276619
+ return permissionsKey(state, key);
276620
+ default:
276621
+ if (key === "y" || key === "enter")
276622
+ return done("approved");
276623
+ if (key === "n")
276624
+ return done("rejected");
276625
+ if (key === "escape")
276626
+ return later;
276627
+ return { state };
276628
+ }
276629
+ }
276630
+ function cardText(state, text) {
276631
+ const value = text.trim();
276632
+ if (state.typing === "custom") {
276633
+ if (!value)
276634
+ return { state: { ...state, typing: null } };
276635
+ const selections = [...state.selections];
276636
+ const current = selections[state.step] ?? { labels: [] };
276637
+ selections[state.step] = { ...current, customText: value };
276638
+ return advanceChoice({ ...state, selections, typing: null });
276639
+ }
276640
+ if (state.typing === "secret") {
276641
+ const fields = state.pending.secrets ?? [];
276642
+ const field = fields[state.step];
276643
+ if (!field || !value)
276644
+ return { state };
276645
+ const secretValues = { ...state.secretValues, [field.name]: value };
276646
+ if (state.step + 1 < fields.length) {
276647
+ return { state: { ...state, secretValues, step: state.step + 1 } };
276648
+ }
276649
+ return done("approved", { secrets: secretValues });
276650
+ }
276651
+ return { state };
276652
+ }
276653
+ function cardLines(state) {
276654
+ const p = state.pending;
276655
+ const head = [source_default.bold(`⏸ ${p.title}`)];
276656
+ if (p.detail)
276657
+ head.push(source_default.dim(` ${p.detail}`));
276658
+ switch (p.kind) {
276659
+ case "choice": {
276660
+ const q = p.questions?.[state.step];
276661
+ if (!q)
276662
+ return [...head, source_default.dim(" (no questions) · Enter to continue")];
276663
+ const total = p.questions?.length ?? 1;
276664
+ const sel = state.selections[state.step] ?? { labels: [] };
276665
+ const rows = q.options.map((o, i) => {
276666
+ const on = sel.labels.includes(o.label);
276667
+ const mark = q.multiSelect ? on ? "☑" : "☐" : on ? "●" : "○";
276668
+ const text = `${state.cursor === i ? "▸" : " "} ${mark} ${o.label}${o.description ? source_default.dim(` — ${o.description}`) : ""}`;
276669
+ return state.cursor === i ? source_default.cyan(text) : text;
276670
+ });
276671
+ const customRow = `${state.cursor === q.options.length ? "▸" : " "} ✎ something else${sel.customText ? source_default.dim(` — ${sel.customText}`) : ""}`;
276672
+ rows.push(state.cursor === q.options.length ? source_default.cyan(customRow) : customRow);
276673
+ return [
276674
+ ...head,
276675
+ ` ${source_default.bold(q.question)} ${source_default.dim(`(${state.step + 1}/${total})`)}`,
276676
+ ...q.description ? [source_default.dim(` ${q.description}`)] : [],
276677
+ ...rows.map((r) => ` ${r}`),
276678
+ source_default.dim(q.multiSelect ? " ↑↓ move · space toggle · Enter next · s skip all · Esc later" : " ↑↓ move · Enter choose · s skip all · Esc later")
276679
+ ];
276680
+ }
276681
+ case "permissions": {
276682
+ const rows = (p.permissions ?? []).map((r, i) => {
276683
+ const text = `${state.cursor === i ? "▸" : " "} ${state.granted.has(r.key) ? "☑" : "☐"} ${r.label}${r.reason ? source_default.dim(` — ${r.reason}`) : ""}`;
276684
+ return ` ${state.cursor === i ? source_default.cyan(text) : text}`;
276685
+ });
276686
+ return [
276687
+ ...head,
276688
+ ...rows,
276689
+ source_default.dim(" space toggle · Enter grant ticked · n reject all · Esc later")
276690
+ ];
276691
+ }
276692
+ case "secrets": {
276693
+ const fields = p.secrets ?? [];
276694
+ const rows = fields.map((f, i) => {
276695
+ const filled = f.name in state.secretValues;
276696
+ const mark = filled ? source_default.green("✓") : i === state.step ? "▸" : "○";
276697
+ return ` ${mark} ${f.name}${f.description ? source_default.dim(` — ${f.description}`) : ""}`;
276698
+ });
276699
+ return [
276700
+ ...head,
276701
+ ...rows,
276702
+ source_default.dim(" type the value below (hidden) · Enter next · Esc later")
276703
+ ];
276704
+ }
276705
+ case "browser":
276706
+ return [
276707
+ ...head,
276708
+ source_default.dim(" finish this step in the editor (footer link), then press y"),
276709
+ source_default.dim(" y continue · n reject · Esc later")
276710
+ ];
276711
+ default:
276712
+ return [...head, source_default.dim(" y approve · n reject · Esc later")];
276713
+ }
276714
+ }
276715
+
276235
276716
  // src/cli/commands/code/session-engine.ts
276236
276717
  var POLL_MS = 1000;
276237
276718
  function createSessionEngine(options) {
@@ -276251,6 +276732,28 @@ function createSessionEngine(options) {
276251
276732
  let awaitingTurn = options.awaitingTurnLabel ?? null;
276252
276733
  const awaitingSince = Date.now();
276253
276734
  let lastEventAt = Date.now();
276735
+ let pending = [];
276736
+ const answered = new Set;
276737
+ const answer = (p, action, input = {}) => {
276738
+ answered.add(p.toolCallId);
276739
+ pending = pending.filter((x) => x.toolCallId !== p.toolCallId);
276740
+ const verb = action === "rejected" ? source_default.red("✗ rejected") : Object.keys(input).length ? source_default.green("→ answered") : source_default.green("✓ approved");
276741
+ options.onLine(`${verb} ${source_default.dim("—")} ${p.title}`);
276742
+ pendingSubmitAt = Date.now();
276743
+ sendsInFlight++;
276744
+ answerToolCall({ toolCallId: p.toolCallId, messageId: p.messageId, action, input }, options.branchId).catch((error) => {
276745
+ const status = error instanceof ApiError ? error.statusCode : undefined;
276746
+ const edgeDrop = status === 502 || status === 503 || status === 504 || /timeout|gateway/i.test(error instanceof Error ? error.message : "");
276747
+ if (edgeDrop && (turnStartedAt != null || pendingSubmitAt == null)) {
276748
+ return;
276749
+ }
276750
+ answered.delete(p.toolCallId);
276751
+ pendingSubmitAt = null;
276752
+ options.onLine(source_default.red(`✗ answer failed: ${error instanceof Error ? error.message : String(error)}`));
276753
+ }).finally(() => {
276754
+ sendsInFlight--;
276755
+ });
276756
+ };
276254
276757
  const submit = (raw) => {
276255
276758
  const typed = raw.trim();
276256
276759
  if (!typed)
@@ -276291,6 +276794,12 @@ function createSessionEngine(options) {
276291
276794
  return;
276292
276795
  }
276293
276796
  const events = diffConversation(diffState, messages);
276797
+ const waiting = pendingInputs(messages);
276798
+ for (const id of answered) {
276799
+ if (!waiting.some((w) => w.toolCallId === id))
276800
+ answered.delete(id);
276801
+ }
276802
+ pending = waiting.filter((w) => !answered.has(w.toolCallId));
276294
276803
  if (!prime) {
276295
276804
  for (const event of events) {
276296
276805
  if (event.kind === "tool_start") {
@@ -276314,7 +276823,9 @@ function createSessionEngine(options) {
276314
276823
  });
276315
276824
  continue;
276316
276825
  }
276317
- const line = eventLine(event);
276826
+ const line = eventLine(event, undefined, {
276827
+ waitingHint: "answer in the card below"
276828
+ });
276318
276829
  if (line != null) {
276319
276830
  lastEventAt = Date.now();
276320
276831
  options.onLine(line);
@@ -276381,6 +276892,7 @@ function createSessionEngine(options) {
276381
276892
  });
276382
276893
  },
276383
276894
  submit,
276895
+ answer,
276384
276896
  status() {
276385
276897
  let phase = "idle";
276386
276898
  if (awaitingTurn != null)
@@ -276403,7 +276915,8 @@ function createSessionEngine(options) {
276403
276915
  turnStartedAt,
276404
276916
  runningTool,
276405
276917
  lastTurnMs,
276406
- lastTurnOk
276918
+ lastTurnOk,
276919
+ pending
276407
276920
  };
276408
276921
  },
276409
276922
  turnRunning() {
@@ -276475,6 +276988,8 @@ function SessionView({ engine, footer, subscribe }) {
276475
276988
  const [musingSeed] = import_react23.useState(() => Math.floor(Math.random() * 97));
276476
276989
  const [currentModel, setCurrentModel] = import_react23.useState(null);
276477
276990
  const [pickerIndex, setPickerIndex] = import_react23.useState(null);
276991
+ const [card, setCard] = import_react23.useState(null);
276992
+ const dismissedRef = import_react23.useRef(new Set);
276478
276993
  const maxScrollRef = import_react23.useRef(0);
276479
276994
  const meIdRef = import_react23.useRef(null);
276480
276995
  const emit = (entry) => setItems((h) => withEntry(h, entry));
@@ -276520,6 +277035,29 @@ function SessionView({ engine, footer, subscribe }) {
276520
277035
  emit(source_default.red(` /model: ${error instanceof Error ? error.message : String(error)}`));
276521
277036
  }
276522
277037
  };
277038
+ const applyCard = (outcome) => {
277039
+ if (outcome.submit && card) {
277040
+ engine.answer(card.pending, outcome.submit.action, outcome.submit.input);
277041
+ }
277042
+ if (outcome.dismissed && card) {
277043
+ dismissedRef.current.add(card.pending.toolCallId);
277044
+ }
277045
+ setCard(outcome.state);
277046
+ };
277047
+ const pending = engine.status().pending;
277048
+ import_react23.useEffect(() => {
277049
+ if (card) {
277050
+ if (!pending.some((p) => p.toolCallId === card.pending.toolCallId)) {
277051
+ setCard(null);
277052
+ }
277053
+ return;
277054
+ }
277055
+ if (pickerIndex !== null)
277056
+ return;
277057
+ const next = pending.find((p) => !dismissedRef.current.has(p.toolCallId));
277058
+ if (next)
277059
+ setCard(openCard(next));
277060
+ }, [pending, card, pickerIndex]);
276523
277061
  use_input_default((char, key) => {
276524
277062
  if (pickerIndex !== null) {
276525
277063
  if (key.upArrow)
@@ -276535,6 +277073,23 @@ function SessionView({ engine, footer, subscribe }) {
276535
277073
  }
276536
277074
  return;
276537
277075
  }
277076
+ if (key.tab && !card) {
277077
+ const next = pending.find((p) => dismissedRef.current.has(p.toolCallId));
277078
+ if (next) {
277079
+ dismissedRef.current.delete(next.toolCallId);
277080
+ setCard(openCard(next));
277081
+ }
277082
+ return;
277083
+ }
277084
+ if (card) {
277085
+ const mapped = key.upArrow ? "up" : key.downArrow ? "down" : key.return ? "enter" : key.escape ? "escape" : char === " " ? "space" : char === "y" || char === "n" || char === "s" ? char : null;
277086
+ if (card.typing && mapped !== "escape")
277087
+ return;
277088
+ if (mapped)
277089
+ applyCard(cardKey(card, mapped));
277090
+ if (mapped || !card.typing)
277091
+ return;
277092
+ }
276538
277093
  if (key.ctrl && char === "c") {
276539
277094
  if (input)
276540
277095
  setInput("");
@@ -276579,7 +277134,9 @@ function SessionView({ engine, footer, subscribe }) {
276579
277134
  const innerWidth = Math.max(10, width - 4);
276580
277135
  const inputRows = Math.max(1, Math.ceil((input.length + 3) / innerWidth));
276581
277136
  const pickerOpen = pickerIndex !== null;
276582
- const inputBlockHeight = pickerOpen ? MODELS.length + 3 : inputRows + 2;
277137
+ const cardOpen = card !== null && !card.typing;
277138
+ const cardRows = card ? cardLines(card).length : 0;
277139
+ const inputBlockHeight = pickerOpen ? MODELS.length + 3 : cardOpen ? cardRows + 2 : inputRows + 2 + (card?.typing ? 1 : 0);
276583
277140
  const widgetHeight = inputBlockHeight + 3 + (footer.length ? 1 : 0);
276584
277141
  const viewHeight = Math.max(3, rows - widgetHeight - 1);
276585
277142
  const lines = items.flatMap((item) => hardWrapAnsi(`${renderEntry(item, { verbose, foldHint: "Ctrl+O to expand" })}
@@ -276630,29 +277187,64 @@ function SessionView({ engine, footer, subscribe }) {
276630
277187
  }, m.name, false, undefined, this);
276631
277188
  })
276632
277189
  ]
276633
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
277190
+ }, undefined, true, undefined, this) : cardOpen && card ? /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
277191
+ flexDirection: "column",
277192
+ borderStyle: "round",
277193
+ borderColor: "yellow",
277194
+ paddingX: 1,
277195
+ width,
277196
+ children: cardLines(card).map((line, i) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
277197
+ wrap: "truncate-end",
277198
+ children: line
277199
+ }, i, false, undefined, this))
277200
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
277201
+ flexDirection: "column",
276634
277202
  borderStyle: "round",
276635
- borderColor: "gray",
277203
+ borderColor: card?.typing ? "yellow" : "gray",
276636
277204
  paddingX: 1,
276637
277205
  width,
276638
277206
  children: [
276639
- /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
276640
- color: "cyan",
276641
- children: "❯ "
276642
- }, undefined, false, undefined, this),
276643
- /* @__PURE__ */ jsx_dev_runtime.jsxDEV(build_default, {
276644
- value: input,
276645
- onChange: setInput,
276646
- onSubmit: (value) => {
276647
- const trimmed = value.trim();
276648
- if (trimmed === "/model" || trimmed.startsWith("/model ")) {
276649
- runModelSlash(trimmed.slice("/model".length).trim());
276650
- } else if (trimmed) {
276651
- engine.submit(value);
276652
- }
276653
- setInput("");
276654
- }
276655
- }, undefined, false, undefined, this)
277207
+ card?.typing === "secret" && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
277208
+ wrap: "truncate-end",
277209
+ children: [
277210
+ source_default.bold(card.pending.secrets?.[card.step]?.name ?? "secret"),
277211
+ source_default.dim(" — value is hidden · Enter to save · Esc to cancel")
277212
+ ]
277213
+ }, undefined, true, undefined, this),
277214
+ card?.typing === "custom" && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
277215
+ wrap: "truncate-end",
277216
+ children: [
277217
+ source_default.bold(card.pending.questions?.[card.step]?.question ?? ""),
277218
+ source_default.dim(" — your own answer · Enter to save · Esc to go back")
277219
+ ]
277220
+ }, undefined, true, undefined, this),
277221
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
277222
+ children: [
277223
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
277224
+ color: "cyan",
277225
+ children: "❯ "
277226
+ }, undefined, false, undefined, this),
277227
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(build_default, {
277228
+ value: input,
277229
+ onChange: setInput,
277230
+ mask: card?.typing === "secret" ? "•" : undefined,
277231
+ onSubmit: (value) => {
277232
+ if (card?.typing) {
277233
+ applyCard(cardText(card, value));
277234
+ setInput("");
277235
+ return;
277236
+ }
277237
+ const trimmed = value.trim();
277238
+ if (trimmed === "/model" || trimmed.startsWith("/model ")) {
277239
+ runModelSlash(trimmed.slice("/model".length).trim());
277240
+ } else if (trimmed) {
277241
+ engine.submit(value);
277242
+ }
277243
+ setInput("");
277244
+ }
277245
+ }, undefined, false, undefined, this)
277246
+ ]
277247
+ }, undefined, true, undefined, this)
276656
277248
  ]
276657
277249
  }, undefined, true, undefined, this),
276658
277250
  footer.length > 0 && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
@@ -276666,7 +277258,7 @@ function SessionView({ engine, footer, subscribe }) {
276666
277258
  /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
276667
277259
  dimColor: true,
276668
277260
  wrap: "truncate-end",
276669
- children: pickerOpen ? " ↑↓ to move · Enter to select · Esc to cancel" : engine.turnRunning() ? " Esc to stop · type to queue · scroll to read · Ctrl+O to expand · Ctrl+C to exit" : " Enter to send · /model to switch model · Esc for live · Ctrl+O to expand · Ctrl+C to exit"
277261
+ children: pickerOpen ? " ↑↓ to move · Enter to select · Esc to cancel" : cardOpen ? " the agent is waiting on you · answer above, or Esc for later" : pending.length > 0 && !card ? ` ⏸ ${pending[0].title} — Tab to answer · Ctrl+C to exit` : engine.turnRunning() ? " Esc to stop · type to queue · scroll to read · Ctrl+O to expand · Ctrl+C to exit" : " Enter to send · /model to switch model · Esc for live · Ctrl+O to expand · Ctrl+C to exit"
276670
277262
  }, undefined, false, undefined, this)
276671
277263
  ]
276672
277264
  }, undefined, true, undefined, this);
@@ -276791,6 +277383,7 @@ async function runGenesisSession(options) {
276791
277383
  runningTool: null,
276792
277384
  lastTurnMs: null,
276793
277385
  lastTurnOk: true,
277386
+ pending: [],
276794
277387
  quietForMs: 0
276795
277388
  };
276796
277389
  const genesis = {
@@ -276846,6 +277439,9 @@ async function runGenesisSession(options) {
276846
277439
  }
276847
277440
  return IDLE_STATUS;
276848
277441
  },
277442
+ answer(p, action, input) {
277443
+ inner?.answer(p, action, input);
277444
+ },
276849
277445
  turnRunning() {
276850
277446
  return inner?.turnRunning() ?? creating;
276851
277447
  }
@@ -276878,10 +277474,10 @@ async function runGenesisSession(options) {
276878
277474
 
276879
277475
  // src/cli/commands/code/index.ts
276880
277476
  var BRAND_ORANGE2 = "#E86B3C";
276881
- async function bootstrapApp(prompt, footer, emit, onCreated, importRepo, path) {
277477
+ async function bootstrapApp(prompt, footer, emit, onCreated, importRepo, path, wixLaunch) {
276882
277478
  let app;
276883
277479
  try {
276884
- app = await createAndLinkApp({ prompt, importRepo, path });
277480
+ app = await createAndLinkApp({ prompt, importRepo, path, wixLaunch });
276885
277481
  } catch (error) {
276886
277482
  for (const line of await githubReauthLines(error) ?? [])
276887
277483
  emit(line);
@@ -276928,8 +277524,8 @@ async function codeAction({ log }, options, appId) {
276928
277524
  linked = true;
276929
277525
  } catch {}
276930
277526
  if (linked) {
276931
- if (options.import || options.path) {
276932
- throw new InvalidInputError("--import and --path create a new app; run them outside a linked project, without --app-id.");
277527
+ if (options.import || options.path || options.wixLaunch) {
277528
+ throw new InvalidInputError("--import, --path and --wix-launch create a new app; run them outside a linked project, without --app-id.");
276933
277529
  }
276934
277530
  const { id, projectRoot } = getAppContext();
276935
277531
  const state = await assertBuilderApp(id);
@@ -276952,16 +277548,22 @@ async function codeAction({ log }, options, appId) {
276952
277548
  outroMessage: `Session closed. Resume with \`base44 code --app-id ${id}\`.`
276953
277549
  };
276954
277550
  }
277551
+ if (options.wixLaunch && options.import) {
277552
+ throw new InvalidInputError("--wix-launch and --import are exclusive.");
277553
+ }
277554
+ const wixLaunch = options.wixLaunch ? parseWixLaunchUrl(options.wixLaunch) : undefined;
276955
277555
  let created;
276956
- const footer = [chip(options.import ? repoLabel(options.import) : "web app")];
277556
+ const footer = [
277557
+ chip(options.import ? repoLabel(options.import) : wixLaunch ? "web app · wix" : "web app")
277558
+ ];
276957
277559
  await runGenesisSession({
276958
277560
  idleHint: options.import ? "describe what to build over the repository" : "describe the app you want to build · have one already? base44 code --app-id <id>, or base44 link",
276959
277561
  creatingLabel: options.import ? "importing the repository" : "creating your app",
276960
- modeLabel: options.import ? `Repository — ${repoLabel(options.import)}` : "Web app — Base44 template + builder agent",
277562
+ modeLabel: options.import ? `Repository — ${repoLabel(options.import)}` : wixLaunch ? "Web app — Wix launch (connector connected first)" : "Web app — Base44 template + builder agent",
276961
277563
  footer,
276962
277564
  createApp: (prompt, emit) => bootstrapApp(prompt, footer, emit, (app) => {
276963
277565
  created = app;
276964
- }, options.import, options.path)
277566
+ }, options.import, options.path, wixLaunch)
276965
277567
  });
276966
277568
  if (!created) {
276967
277569
  return { outroMessage: "Session closed. No app was created." };
@@ -276973,7 +277575,7 @@ async function codeAction({ log }, options, appId) {
276973
277575
  }
276974
277576
  function getCodeCommand() {
276975
277577
  const command = new Base44Command("code", { requireAppContext: false });
276976
- command.description("Open Base44 Code, an interactive builder session. In a linked directory (or with --app-id <id>) it opens that app; anywhere else your first prompt creates one (--import <repo> to build over your own repository). Attach a directory to an existing app with base44 link.").option("--import <repo>", "Build over an existing GitHub repository instead of the Base44 template").option("--path <dir>", "Directory to link the new app to (default: the current directory when empty, else ./<name>)").action((ctx, options) => codeAction(ctx, options, command.optsWithGlobals().appId));
277578
+ command.description("Open Base44 Code, an interactive builder session. In a linked directory (or with --app-id <id>) it opens that app; anywhere else your first prompt creates one (--import <repo> to build over your own repository). Attach a directory to an existing app with base44 link.").option("--import <repo>", "Build over an existing GitHub repository instead of the Base44 template").option("--path <dir>", "Directory to link the new app to (default: the current directory when empty, else ./<name>)").option("--wix-launch <url>", "Create the new app through a Wix launch URL (your first prompt is what the agent runs)").action((ctx, options) => codeAction(ctx, options, command.optsWithGlobals().appId));
276977
277579
  return command;
276978
277580
  }
276979
277581
 
@@ -284356,7 +284958,7 @@ async function runScript(options) {
284356
284958
  }
284357
284959
  }
284358
284960
  // src/cli/commands/exec.ts
284359
- function readStdin2() {
284961
+ function readStdin3() {
284360
284962
  return new Promise((resolve, reject) => {
284361
284963
  let data = "";
284362
284964
  process.stdin.setEncoding("utf-8");
@@ -284400,7 +285002,7 @@ async function execAction({ app, isNonInteractive }, options) {
284400
285002
  if (!isNonInteractive) {
284401
285003
  throw noInputError;
284402
285004
  }
284403
- const code = await readStdin2();
285005
+ const code = await readStdin3();
284404
285006
  if (!code.trim()) {
284405
285007
  throw noInputError;
284406
285008
  }
@@ -288581,6 +289183,13 @@ function getFullCommandName(command) {
288581
289183
  }
288582
289184
  return parts.join(" ");
288583
289185
  }
289186
+ var SENSITIVE_OPTION = /secret|token|password|launch|instance|key$/i;
289187
+ function redactSensitiveOptions(options) {
289188
+ return Object.fromEntries(Object.entries(options).map(([k, v]) => [
289189
+ k,
289190
+ SENSITIVE_OPTION.test(k) && v != null && v !== false ? "[redacted]" : v
289191
+ ]));
289192
+ }
288584
289193
  function addCommandInfoToErrorReporter(program, errorReporter) {
288585
289194
  program.hook("preAction", (_, actionCommand) => {
288586
289195
  const fullCommandName = getFullCommandName(actionCommand);
@@ -288588,7 +289197,7 @@ function addCommandInfoToErrorReporter(program, errorReporter) {
288588
289197
  command: {
288589
289198
  name: fullCommandName,
288590
289199
  args: actionCommand.args,
288591
- options: actionCommand.opts()
289200
+ options: redactSensitiveOptions(actionCommand.opts())
288592
289201
  }
288593
289202
  });
288594
289203
  });
@@ -288635,4 +289244,4 @@ export {
288635
289244
  runCLI
288636
289245
  };
288637
289246
 
288638
- //# debugId=DBD6D874F0F8D0A564756E2164756E21
289247
+ //# debugId=D93D1396A8EFA10D64756E2164756E21