@base44-preview/cli 0.1.15-pr.630.51361fe → 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
@@ -52822,7 +52822,7 @@ function canBreakFn(doc) {
52822
52822
  function canBreak(doc) {
52823
52823
  return findInDoc(doc, canBreakFn, false);
52824
52824
  }
52825
- function indent(contents) {
52825
+ function indent2(contents) {
52826
52826
  assertDoc(contents);
52827
52827
  return { type: DOC_TYPE_INDENT, contents };
52828
52828
  }
@@ -52845,7 +52845,7 @@ function addAlignmentToDoc(doc, size, tabWidth) {
52845
52845
  let aligned = doc;
52846
52846
  if (size > 0) {
52847
52847
  for (let level = 0;level < Math.floor(size / tabWidth); ++level) {
52848
- aligned = indent(aligned);
52848
+ aligned = indent2(aligned);
52849
52849
  }
52850
52850
  aligned = align(size % tabWidth, aligned);
52851
52851
  aligned = align(Number.NEGATIVE_INFINITY, aligned);
@@ -53179,7 +53179,7 @@ function printDocToString(doc, options) {
53179
53179
  propagateBreaks(doc);
53180
53180
  while (commands.length > 0) {
53181
53181
  const {
53182
- indent: indent2,
53182
+ indent: indent22,
53183
53183
  mode,
53184
53184
  doc: doc2
53185
53185
  } = commands.pop();
@@ -53199,7 +53199,7 @@ function printDocToString(doc, options) {
53199
53199
  case DOC_TYPE_ARRAY:
53200
53200
  for (let index = doc2.length - 1;index >= 0; index--) {
53201
53201
  commands.push({
53202
- indent: indent2,
53202
+ indent: indent22,
53203
53203
  mode,
53204
53204
  doc: doc2[index]
53205
53205
  });
@@ -53213,14 +53213,14 @@ function printDocToString(doc, options) {
53213
53213
  break;
53214
53214
  case DOC_TYPE_INDENT:
53215
53215
  commands.push({
53216
- indent: makeIndent(indent2, options),
53216
+ indent: makeIndent(indent22, options),
53217
53217
  mode,
53218
53218
  doc: doc2.contents
53219
53219
  });
53220
53220
  break;
53221
53221
  case DOC_TYPE_ALIGN:
53222
53222
  commands.push({
53223
- indent: makeAlign(indent2, doc2.n, options),
53223
+ indent: makeAlign(indent22, doc2.n, options),
53224
53224
  mode,
53225
53225
  doc: doc2.contents
53226
53226
  });
@@ -53233,7 +53233,7 @@ function printDocToString(doc, options) {
53233
53233
  case MODE_FLAT:
53234
53234
  if (!shouldRemeasure) {
53235
53235
  commands.push({
53236
- indent: indent2,
53236
+ indent: indent22,
53237
53237
  mode: doc2.break ? MODE_BREAK : MODE_FLAT,
53238
53238
  doc: doc2.contents
53239
53239
  });
@@ -53242,7 +53242,7 @@ function printDocToString(doc, options) {
53242
53242
  case MODE_BREAK: {
53243
53243
  shouldRemeasure = false;
53244
53244
  const next = {
53245
- indent: indent2,
53245
+ indent: indent22,
53246
53246
  mode: MODE_FLAT,
53247
53247
  doc: doc2.contents
53248
53248
  };
@@ -53255,7 +53255,7 @@ function printDocToString(doc, options) {
53255
53255
  const mostExpanded = method_at_default(0, doc2.expandedStates, -1);
53256
53256
  if (doc2.break) {
53257
53257
  commands.push({
53258
- indent: indent2,
53258
+ indent: indent22,
53259
53259
  mode: MODE_BREAK,
53260
53260
  doc: mostExpanded
53261
53261
  });
@@ -53264,7 +53264,7 @@ function printDocToString(doc, options) {
53264
53264
  for (let index = 1;index < doc2.expandedStates.length + 1; index++) {
53265
53265
  if (index >= doc2.expandedStates.length) {
53266
53266
  commands.push({
53267
- indent: indent2,
53267
+ indent: indent22,
53268
53268
  mode: MODE_BREAK,
53269
53269
  doc: mostExpanded
53270
53270
  });
@@ -53272,7 +53272,7 @@ function printDocToString(doc, options) {
53272
53272
  } else {
53273
53273
  const state = doc2.expandedStates[index];
53274
53274
  const cmd = {
53275
- indent: indent2,
53275
+ indent: indent22,
53276
53276
  mode: MODE_FLAT,
53277
53277
  doc: state
53278
53278
  };
@@ -53285,7 +53285,7 @@ function printDocToString(doc, options) {
53285
53285
  }
53286
53286
  } else {
53287
53287
  commands.push({
53288
- indent: indent2,
53288
+ indent: indent22,
53289
53289
  mode: MODE_BREAK,
53290
53290
  doc: doc2.contents
53291
53291
  });
@@ -53311,12 +53311,12 @@ function printDocToString(doc, options) {
53311
53311
  const content = parts[offset + 0];
53312
53312
  const whitespace = parts[offset + 1];
53313
53313
  const contentFlatCommand = {
53314
- indent: indent2,
53314
+ indent: indent22,
53315
53315
  mode: MODE_FLAT,
53316
53316
  doc: content
53317
53317
  };
53318
53318
  const contentBreakCommand = {
53319
- indent: indent2,
53319
+ indent: indent22,
53320
53320
  mode: MODE_BREAK,
53321
53321
  doc: content
53322
53322
  };
@@ -53330,12 +53330,12 @@ function printDocToString(doc, options) {
53330
53330
  break;
53331
53331
  }
53332
53332
  const whitespaceFlatCommand = {
53333
- indent: indent2,
53333
+ indent: indent22,
53334
53334
  mode: MODE_FLAT,
53335
53335
  doc: whitespace
53336
53336
  };
53337
53337
  const whitespaceBreakCommand = {
53338
- indent: indent2,
53338
+ indent: indent22,
53339
53339
  mode: MODE_BREAK,
53340
53340
  doc: whitespace
53341
53341
  };
@@ -53349,7 +53349,7 @@ function printDocToString(doc, options) {
53349
53349
  }
53350
53350
  const secondContent = parts[offset + 2];
53351
53351
  const remainingCommand = {
53352
- indent: indent2,
53352
+ indent: indent22,
53353
53353
  mode,
53354
53354
  doc: {
53355
53355
  ...doc2,
@@ -53357,7 +53357,7 @@ function printDocToString(doc, options) {
53357
53357
  }
53358
53358
  };
53359
53359
  const firstAndSecondContentFlatCommand = {
53360
- indent: indent2,
53360
+ indent: indent22,
53361
53361
  mode: MODE_FLAT,
53362
53362
  doc: [content, whitespace, secondContent]
53363
53363
  };
@@ -53376,20 +53376,20 @@ function printDocToString(doc, options) {
53376
53376
  case DOC_TYPE_INDENT_IF_BREAK: {
53377
53377
  const groupMode = doc2.groupId ? groupModeMap[doc2.groupId] : mode;
53378
53378
  if (groupMode === MODE_BREAK) {
53379
- const breakContents = doc2.type === DOC_TYPE_IF_BREAK ? doc2.breakContents : doc2.negate ? doc2.contents : indent(doc2.contents);
53379
+ const breakContents = doc2.type === DOC_TYPE_IF_BREAK ? doc2.breakContents : doc2.negate ? doc2.contents : indent2(doc2.contents);
53380
53380
  if (breakContents) {
53381
53381
  commands.push({
53382
- indent: indent2,
53382
+ indent: indent22,
53383
53383
  mode,
53384
53384
  doc: breakContents
53385
53385
  });
53386
53386
  }
53387
53387
  }
53388
53388
  if (groupMode === MODE_FLAT) {
53389
- const flatContents = doc2.type === DOC_TYPE_IF_BREAK ? doc2.flatContents : doc2.negate ? indent(doc2.contents) : doc2.contents;
53389
+ const flatContents = doc2.type === DOC_TYPE_IF_BREAK ? doc2.flatContents : doc2.negate ? indent2(doc2.contents) : doc2.contents;
53390
53390
  if (flatContents) {
53391
53391
  commands.push({
53392
- indent: indent2,
53392
+ indent: indent22,
53393
53393
  mode,
53394
53394
  doc: flatContents
53395
53395
  });
@@ -53399,7 +53399,7 @@ function printDocToString(doc, options) {
53399
53399
  }
53400
53400
  case DOC_TYPE_LINE_SUFFIX:
53401
53401
  lineSuffix2.push({
53402
- indent: indent2,
53402
+ indent: indent22,
53403
53403
  mode,
53404
53404
  doc: doc2.contents
53405
53405
  });
@@ -53407,7 +53407,7 @@ function printDocToString(doc, options) {
53407
53407
  case DOC_TYPE_LINE_SUFFIX_BOUNDARY:
53408
53408
  if (lineSuffix2.length > 0) {
53409
53409
  commands.push({
53410
- indent: indent2,
53410
+ indent: indent22,
53411
53411
  mode,
53412
53412
  doc: hardlineWithoutBreakParent
53413
53413
  });
@@ -53428,7 +53428,7 @@ function printDocToString(doc, options) {
53428
53428
  case MODE_BREAK:
53429
53429
  if (lineSuffix2.length > 0) {
53430
53430
  commands.push({
53431
- indent: indent2,
53431
+ indent: indent22,
53432
53432
  mode,
53433
53433
  doc: doc2
53434
53434
  }, ...lineSuffix2.reverse());
@@ -53438,23 +53438,23 @@ function printDocToString(doc, options) {
53438
53438
  if (doc2.literal) {
53439
53439
  output += newLine;
53440
53440
  position = 0;
53441
- if (indent2.root) {
53442
- if (indent2.root.value) {
53443
- output += indent2.root.value;
53441
+ if (indent22.root) {
53442
+ if (indent22.root.value) {
53443
+ output += indent22.root.value;
53444
53444
  }
53445
- position = indent2.root.length;
53445
+ position = indent22.root.length;
53446
53446
  }
53447
53447
  } else {
53448
53448
  trim2();
53449
- output += newLine + indent2.value;
53450
- position = indent2.length;
53449
+ output += newLine + indent22.value;
53450
+ position = indent22.length;
53451
53451
  }
53452
53452
  break;
53453
53453
  }
53454
53454
  break;
53455
53455
  case DOC_TYPE_LABEL:
53456
53456
  commands.push({
53457
- indent: indent2,
53457
+ indent: indent22,
53458
53458
  mode,
53459
53459
  doc: doc2.contents
53460
53460
  });
@@ -53616,7 +53616,7 @@ var init_doc = __esm(() => {
53616
53616
  breakParent,
53617
53617
  ifBreak,
53618
53618
  trim: trim2,
53619
- indent,
53619
+ indent: indent2,
53620
53620
  indentIfBreak,
53621
53621
  align,
53622
53622
  addAlignmentToDoc,
@@ -140754,7 +140754,7 @@ import { pathToFileURL as pathToFileURL5 } from "url";
140754
140754
  import path122 from "path";
140755
140755
  import path142 from "path";
140756
140756
  import url22 from "url";
140757
- function diffLines(oldStr, newStr, options8) {
140757
+ function diffLines2(oldStr, newStr, options8) {
140758
140758
  return lineDiff.diff(oldStr, newStr, options8);
140759
140759
  }
140760
140760
  function tokenize4(value, options8) {
@@ -140796,10 +140796,10 @@ function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, ne
140796
140796
  throw new Error("newlineIsToken may not be used with patch-generation functions, only with diffing functions");
140797
140797
  }
140798
140798
  if (!optionsObj.callback) {
140799
- return diffLinesResultToPatch(diffLines(oldStr, newStr, optionsObj));
140799
+ return diffLinesResultToPatch(diffLines2(oldStr, newStr, optionsObj));
140800
140800
  } else {
140801
140801
  const { callback } = optionsObj;
140802
- diffLines(oldStr, newStr, Object.assign(Object.assign({}, optionsObj), { callback: (diff) => {
140802
+ diffLines2(oldStr, newStr, Object.assign(Object.assign({}, optionsObj), { callback: (diff) => {
140803
140803
  const patch = diffLinesResultToPatch(diff);
140804
140804
  callback(patch);
140805
140805
  } }));
@@ -146441,7 +146441,7 @@ var require2, __filename2, __dirname3, __create2, __defProp3, __getOwnPropDesc2,
146441
146441
  }
146442
146442
  }
146443
146443
  }, ast_path_default, is_object_default, skipWhitespace, skipSpaces, skipToLineEnd, skipEverythingButNewLine, isNewlineCharacter = (character) => character === `
146444
- ` || character === "\r" || character === "\u2028" || character === "\u2029", skip_newline_default, has_newline_default, is_non_empty_array_default, get_sorted_child_nodes_default, childNodesCache, returnFalse = () => false, isAllEmptyAndNoLineBreak = (text) => !/[\S\n\u2028\u2029]/u.test(text), is_previous_line_empty_default, breakParent2, hardline2, indent2, join32, line22, lineSuffix2, create_print_pre_check_function_default = () => noop_default2, core_options_evaluate_default, arrayToReversed, toReversed, method_to_reversed_default, import_n_readlines, get_interpreter_default, getFileBasename = (file) => {
146444
+ ` || character === "\r" || character === "\u2028" || character === "\u2029", skip_newline_default, has_newline_default, is_non_empty_array_default, get_sorted_child_nodes_default, childNodesCache, returnFalse = () => false, isAllEmptyAndNoLineBreak = (text) => !/[\S\n\u2028\u2029]/u.test(text), is_previous_line_empty_default, breakParent2, hardline2, indent3, join32, line22, lineSuffix2, create_print_pre_check_function_default = () => noop_default2, core_options_evaluate_default, arrayToReversed, toReversed, method_to_reversed_default, import_n_readlines, get_interpreter_default, getFileBasename = (file) => {
146445
146445
  try {
146446
146446
  return path112.basename(toPath4(file));
146447
146447
  } catch {
@@ -156469,7 +156469,7 @@ ${codeblock}`, options8);
156469
156469
  ({
156470
156470
  breakParent: breakParent2,
156471
156471
  hardline: hardline2,
156472
- indent: indent2,
156472
+ indent: indent3,
156473
156473
  join: join32,
156474
156474
  line: line22,
156475
156475
  lineSuffix: lineSuffix2
@@ -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();
@@ -270015,6 +270019,10 @@ var TOOL_ALIASES = {
270015
270019
  read_repo_file: "read",
270016
270020
  write_repo_file: "write",
270017
270021
  edit_repo_file: "edit",
270022
+ read_file: "read",
270023
+ write_file: "write",
270024
+ find_replace: "edit",
270025
+ delete_file: "delete",
270018
270026
  set_secrets: "secrets",
270019
270027
  generate_development_secrets: "secrets",
270020
270028
  create_pull_request: "pr",
@@ -270028,7 +270036,55 @@ var TOOL_ALIASES = {
270028
270036
  preview_screenshot: "screenshot",
270029
270037
  connect_github_account: "github"
270030
270038
  };
270031
- var QUIET_OK_RESULTS = new Set(["read", "write", "edit", "reload"]);
270039
+ var QUIET_OK_RESULTS = new Set(["read", "write", "edit", "reload", "delete"]);
270040
+ var RESULT_LINE_MAX = 110;
270041
+ var DIFF_LINES_MAX = 12;
270042
+ var ERROR_LINES_MAX = 8;
270043
+ function renderEntry(entry, options = {}) {
270044
+ if (typeof entry === "string")
270045
+ return entry;
270046
+ if ("running" in entry)
270047
+ return runningLine(entry.running, entry.startedAt);
270048
+ return eventLine(entry.event, entry.elapsedMs, options) ?? "";
270049
+ }
270050
+ var RUNNING_DOT = "#E86B3C";
270051
+ var PULSE_MS = 500;
270052
+ function runningLine(event, startedAt, now = Date.now()) {
270053
+ const lit = Math.floor(now / PULSE_MS) % 2 === 0;
270054
+ const dot = lit ? source_default.hex(RUNNING_DOT)("●") : source_default.dim("●");
270055
+ const alias = toolAlias(event.name);
270056
+ const title = source_default.bold(event.label || alias);
270057
+ const inline = !event.label && event.summary ? ` ${source_default.dim(event.summary)}` : "";
270058
+ const seconds = Math.round((now - startedAt) / 1000);
270059
+ const took = seconds >= 3 ? ` ${source_default.dim(`· ${seconds}s`)}` : "";
270060
+ const detail = event.label && event.summary ? `
270061
+ ${source_default.dim(`└ ${alias}: ${event.summary}`)}` : "";
270062
+ return `${dot} ${title}${inline}${took}${detail}`;
270063
+ }
270064
+ function fold2(lines, max, options) {
270065
+ if (options.verbose || lines.length <= max)
270066
+ return lines;
270067
+ const hint = options.foldHint ? ` (${options.foldHint})` : "";
270068
+ return [
270069
+ ...lines.slice(0, max),
270070
+ source_default.dim(`… +${lines.length - max} lines${hint}`)
270071
+ ];
270072
+ }
270073
+ var str = (v) => typeof v === "string" ? v : undefined;
270074
+ function diffLines(args) {
270075
+ const find = str(args.find);
270076
+ const replace = str(args.replace);
270077
+ if (find == null && replace == null)
270078
+ return null;
270079
+ return [
270080
+ ...(find ?? "").split(`
270081
+ `).map((l) => source_default.red(`- ${l}`)),
270082
+ ...(replace ?? "").split(`
270083
+ `).map((l) => source_default.green(`+ ${l}`))
270084
+ ];
270085
+ }
270086
+ var indent = (lines) => lines.map((l) => ` ${l}`).join(`
270087
+ `);
270032
270088
  function toolAlias(name) {
270033
270089
  return TOOL_ALIASES[name] ?? name;
270034
270090
  }
@@ -270093,7 +270149,7 @@ function formatDuration2(ms) {
270093
270149
  return `${seconds}s`;
270094
270150
  return `${Math.floor(seconds / 60)}m ${String(seconds % 60).padStart(2, "0")}s`;
270095
270151
  }
270096
- function eventLine(event, elapsedMs) {
270152
+ function eventLine(event, elapsedMs, options = {}) {
270097
270153
  switch (event.kind) {
270098
270154
  case "thinking":
270099
270155
  return source_default.dim(`✻ ${event.text}`);
@@ -270103,7 +270159,7 @@ function eventLine(event, elapsedMs) {
270103
270159
  return null;
270104
270160
  case "waiting": {
270105
270161
  const what = event.label || toolAlias(event.name);
270106
- 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"})`);
270107
270163
  }
270108
270164
  case "tool_end": {
270109
270165
  const alias = toolAlias(event.name);
@@ -270114,12 +270170,40 @@ function eventLine(event, elapsedMs) {
270114
270170
  const paramsLine = event.label && event.summary ? `
270115
270171
  ${source_default.dim(`${alias}: ${event.summary}`)}` : "";
270116
270172
  const head = `${mark} ${title}${inlineDetail}${took}${paramsLine}`;
270173
+ const args = event.args ?? null;
270174
+ if (event.ok && alias === "edit" && args) {
270175
+ const diff = diffLines(args);
270176
+ if (diff)
270177
+ return `${head}
270178
+ ${indent(fold2(diff, DIFF_LINES_MAX, options))}`;
270179
+ }
270180
+ if (event.ok && alias === "write" && args && str(args.content) != null) {
270181
+ const lines = str(args.content).split(`
270182
+ `);
270183
+ const count = source_default.dim(`+${lines.length} lines`);
270184
+ if (!options.verbose)
270185
+ return `${head} ${count}`;
270186
+ return `${head} ${count}
270187
+ ${indent(lines.map((l) => source_default.dim(l)))}`;
270188
+ }
270117
270189
  if (event.ok && (QUIET_OK_RESULTS.has(alias) || !event.result)) {
270118
270190
  return head;
270119
270191
  }
270120
- const result = event.ok ? source_default.dim(linkifyUrls(event.result)) : source_default.red(linkifyUrls(event.result));
270121
- return `${head}${event.result ? `
270122
- ${result}` : ""}`;
270192
+ const paint = event.ok ? source_default.dim : source_default.red;
270193
+ const lines = event.result.split(`
270194
+ `).map((l) => l.trimEnd()).filter((l, i, all) => l.length > 0 || i > 0 && i < all.length - 1);
270195
+ if (event.ok && !options.verbose) {
270196
+ const first = lines[0] ?? "";
270197
+ const cut = first.length > RESULT_LINE_MAX ? `${first.slice(0, RESULT_LINE_MAX)}…` : first;
270198
+ const more = lines.length - 1;
270199
+ const hint = options.foldHint ? ` (${options.foldHint})` : "";
270200
+ const tail = more > 0 ? source_default.dim(` … +${more} lines${hint}`) : "";
270201
+ return `${head}
270202
+ ${paint(linkifyUrls(cut))}${tail}`;
270203
+ }
270204
+ const shown = fold2(lines.map((l) => paint(linkifyUrls(l))), event.ok ? Number.POSITIVE_INFINITY : ERROR_LINES_MAX, options);
270205
+ return `${head}
270206
+ ${indent(shown)}`;
270123
270207
  }
270124
270208
  }
270125
270209
  }
@@ -270225,7 +270309,10 @@ function createTurnStream(interactive, write = (text) => process.stdout.write(te
270225
270309
  elapsedMs = Date.now() - started;
270226
270310
  running.delete(event.id);
270227
270311
  }
270228
- const line = eventLine(event, elapsedMs);
270312
+ const line = eventLine(event, elapsedMs, {
270313
+ verbose: options.verbose,
270314
+ foldHint: "--verbose shows everything"
270315
+ });
270229
270316
  if (line == null)
270230
270317
  return;
270231
270318
  if (interactive) {
@@ -270260,6 +270347,10 @@ var CreatedAppSchema = object({
270260
270347
  name: string2().nullish(),
270261
270348
  imported_repo_url: string2().nullish()
270262
270349
  });
270350
+ var WixCreatedAppSchema = object({
270351
+ app_id: string2().min(1),
270352
+ client_creation_id: string2().min(1)
270353
+ });
270263
270354
  var AppStateSchema = object({
270264
270355
  id: string2(),
270265
270356
  app_type: string2().nullish(),
@@ -270299,7 +270390,8 @@ var ConversationMessageSchema = object({
270299
270390
  name: string2(),
270300
270391
  arguments_string: string2().nullish(),
270301
270392
  status: string2().nullish(),
270302
- results: unknown().nullish()
270393
+ results: unknown().nullish(),
270394
+ waiting_on: object({ kind: string2().nullish() }).nullish()
270303
270395
  })).nullish()
270304
270396
  });
270305
270397
  var FullConversationSchema = object({
@@ -270316,6 +270408,24 @@ function parseOrThrow(schema, payload, what) {
270316
270408
  function branchScope(branchId) {
270317
270409
  return branchId ? { branch_id: branchId } : {};
270318
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
+ }
270319
270429
  async function createApp(options) {
270320
270430
  let response;
270321
270431
  try {
@@ -270373,6 +270483,25 @@ async function getAppState(appId) {
270373
270483
  }
270374
270484
  return parseOrThrow(AppStateSchema, await response.json(), "app status");
270375
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
+ }
270376
270505
  async function sendTurn(content, branchId) {
270377
270506
  let response;
270378
270507
  try {
@@ -270445,12 +270574,32 @@ function inventAppName(prompt) {
270445
270574
  function repoBasename(repoUrl) {
270446
270575
  return repoUrl.replace(/\/+$/, "").replace(/\.git$/, "").split("/").pop() ?? "app";
270447
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
+ }
270448
270597
  async function createAndLinkApp(options) {
270449
270598
  if (options.name && !APP_NAME_RE.test(options.name)) {
270450
270599
  throw new InvalidInputError("The name becomes a directory — letters, digits, dots, dashes and underscores only.");
270451
270600
  }
270452
270601
  const cwd = process.cwd();
270453
- const fallbackName = () => options.importRepo ? repoBasename(options.importRepo) : inventAppName(options.prompt);
270602
+ const fallbackName = () => options.importRepo ? repoBasename(options.importRepo) : inventAppName(options.prompt ?? options.wixLaunch?.prompt);
270454
270603
  const chosenDir = options.path ? resolve8(cwd, options.path) : await isDirEmpty(cwd) ? cwd : undefined;
270455
270604
  const dirBase = chosenDir ? basename6(chosenDir) : undefined;
270456
270605
  const name = options.name ?? (dirBase && APP_NAME_RE.test(dirBase) ? dirBase : fallbackName());
@@ -270461,7 +270610,15 @@ async function createAndLinkApp(options) {
270461
270610
  if (await appConfigExists(targetDir)) {
270462
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.`);
270463
270612
  }
270464
- 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({
270465
270622
  appName: name,
270466
270623
  repoUrl: options.importRepo,
270467
270624
  sourceMode: options.mode ?? "direct",
@@ -270485,7 +270642,8 @@ async function createAndLinkApp(options) {
270485
270642
  repoUrl: created.imported_repo_url ?? undefined,
270486
270643
  dirName,
270487
270644
  targetDir,
270488
- here
270645
+ here,
270646
+ ...clientCreationId ? { clientCreationId } : {}
270489
270647
  };
270490
270648
  }
270491
270649
  function repoLabel(url) {
@@ -270547,12 +270705,27 @@ function newStreamState() {
270547
270705
  return { perMessage: new Map };
270548
270706
  }
270549
270707
  var TOOL_SETTLED = new Set(["success", "error", "stopped"]);
270708
+ function fullText(value) {
270709
+ if (typeof value === "string")
270710
+ return value.trimEnd();
270711
+ if (value == null)
270712
+ return "";
270713
+ return JSON.stringify(value);
270714
+ }
270715
+ function toolArgs(argumentsString) {
270716
+ try {
270717
+ const parsed = JSON.parse(argumentsString ?? "");
270718
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
270719
+ } catch {
270720
+ return null;
270721
+ }
270722
+ }
270550
270723
  function oneLine(value, max) {
270551
270724
  const text = typeof value === "string" ? value : value == null ? "" : JSON.stringify(value);
270552
270725
  const flat = text.replace(/\s+/g, " ").trim();
270553
270726
  return flat.length > max ? `${flat.slice(0, max)}…` : flat;
270554
270727
  }
270555
- var SALIENT_KEYS = ["command", "path", "file_path", "title"];
270728
+ var SALIENT_KEYS = ["command", "path", "file_path", "title", "find"];
270556
270729
  function salvageKey(raw, keys) {
270557
270730
  for (const key of keys) {
270558
270731
  const match = raw.match(new RegExp(`"${key}"\\s*:\\s*"((?:[^"\\\\]|\\\\.)*)"`));
@@ -270581,6 +270754,10 @@ function toolMeta(name, argumentsString) {
270581
270754
  read_repo_file: pick("path") ?? pick("file_path"),
270582
270755
  write_repo_file: pick("path") ?? pick("file_path"),
270583
270756
  edit_repo_file: pick("path") ?? pick("file_path"),
270757
+ read_file: pick("file_path") ?? pick("path"),
270758
+ write_file: pick("file_path") ?? pick("path"),
270759
+ find_replace: pick("file_path") ?? pick("path"),
270760
+ delete_file: pick("file_path") ?? pick("path"),
270584
270761
  create_pull_request: pick("title"),
270585
270762
  reload_preview: ""
270586
270763
  };
@@ -270631,7 +270808,10 @@ function diffConversation(state, messages) {
270631
270808
  }
270632
270809
  for (const tool of message.tool_calls ?? []) {
270633
270810
  if (!progress.announcedTools.has(tool.id)) {
270634
- progress.announcedTools.set(tool.id, toolMeta(tool.name, tool.arguments_string));
270811
+ progress.announcedTools.set(tool.id, {
270812
+ ...toolMeta(tool.name, tool.arguments_string),
270813
+ args: toolArgs(tool.arguments_string)
270814
+ });
270635
270815
  const meta = progress.announcedTools.get(tool.id);
270636
270816
  events.push({
270637
270817
  kind: "tool_start",
@@ -270662,7 +270842,8 @@ function diffConversation(state, messages) {
270662
270842
  label: labelTense(meta.label, "done"),
270663
270843
  summary: meta.summary,
270664
270844
  ok: status === "success",
270665
- result: oneLine(tool.results, 110)
270845
+ result: fullText(tool.results),
270846
+ args: meta.args
270666
270847
  });
270667
270848
  }
270668
270849
  }
@@ -270736,9 +270917,90 @@ async function streamConversationUntilSettled(onEvent, options = {}) {
270736
270917
  return "timeout";
270737
270918
  }
270738
270919
 
270920
+ // src/cli/commands/builder/send.ts
270921
+ function lastAssistantReply(turn) {
270922
+ const messages = turn.conversation?.messages ?? [];
270923
+ for (let i = messages.length - 1;i >= 0; i--) {
270924
+ const { role, content } = messages[i];
270925
+ if (role === "assistant" && typeof content === "string" && content.trim()) {
270926
+ return content.trim();
270927
+ }
270928
+ }
270929
+ return;
270930
+ }
270931
+ function ndjsonWriter() {
270932
+ return (record) => process.stdout.write(`${JSON.stringify(record)}
270933
+ `);
270934
+ }
270935
+ async function sendAction(ctx, message, options) {
270936
+ if (options.streamJson && ctx.jsonMode) {
270937
+ throw new InvalidInputError("--stream-json and --json are exclusive.");
270938
+ }
270939
+ if (ctx.app)
270940
+ await assertBuilderApp(ctx.app.id);
270941
+ const branchId = await resolveBranchId(ctx);
270942
+ if (options.streamJson) {
270943
+ const write = ndjsonWriter();
270944
+ const turn = await streamConversationDuring(() => sendTurn(message, branchId), ({ kind, ...event }) => write({ type: kind, ...event }), { branchId });
270945
+ write({
270946
+ type: "result",
270947
+ queued: turn.queued === true,
270948
+ status: turn.status?.state ?? "ready",
270949
+ error_source: turn.status?.error_source ?? null,
270950
+ reply: lastAssistantReply(turn) ?? null
270951
+ });
270952
+ return {};
270953
+ }
270954
+ if (ctx.jsonMode) {
270955
+ const turn = await ctx.runTask("Agent working (a turn can take minutes)", () => sendTurn(message, branchId));
270956
+ if (turn.queued)
270957
+ return { stdout: `${JSON.stringify({ queued: true })}
270958
+ ` };
270959
+ return {
270960
+ stdout: `${JSON.stringify({
270961
+ status: turn.status?.state ?? "ready",
270962
+ error_source: turn.status?.error_source ?? null,
270963
+ reply: lastAssistantReply(turn) ?? null
270964
+ })}
270965
+ `
270966
+ };
270967
+ }
270968
+ const stream = createTurnStream(process.stdout.isTTY === true, undefined, {
270969
+ verbose: options.verbose
270970
+ });
270971
+ let turn;
270972
+ try {
270973
+ turn = await streamConversationDuring(() => sendTurn(message, branchId), stream.onEvent, { branchId });
270974
+ } finally {
270975
+ stream.stop();
270976
+ }
270977
+ if (turn.queued) {
270978
+ return {
270979
+ outroMessage: "The agent is busy with an earlier message — yours was queued and runs next."
270980
+ };
270981
+ }
270982
+ if (turn.status?.state === "error") {
270983
+ return {
270984
+ outroMessage: `Turn failed (${turn.status.error_source ?? "unknown"}) — see the editor for details.`
270985
+ };
270986
+ }
270987
+ return { outroMessage: "Turn finished." };
270988
+ }
270989
+ function getSendCommand() {
270990
+ const command = new Base44Command("send", { supportsBranch: true });
270991
+ command.description("Send the agent one message and stream the turn until it finishes").argument("<message>", "What you want the agent to do").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(sendAction);
270992
+ return command;
270993
+ }
270994
+
270739
270995
  // src/cli/commands/builder/new.ts
270740
270996
  var POLL_TIMEOUT_MS = 20 * 60000;
270741
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
+ }
270742
271004
  async function newAction({ log, runTask, jsonMode }, prompt, options) {
270743
271005
  if (options.mode && !MODES.includes(options.mode)) {
270744
271006
  throw new InvalidInputError("--mode must be direct, fork, or copy.");
@@ -270746,9 +271008,20 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
270746
271008
  if ((options.mode || options.repoName || options.fromBranch) && !options.import) {
270747
271009
  throw new InvalidInputError("--mode, --repo-name and --from-branch apply only with --import <repo>.");
270748
271010
  }
270749
- if (!prompt && !options.import) {
270750
- 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.");
270751
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>.');
271020
+ }
271021
+ if (options.streamJson && jsonMode) {
271022
+ throw new InvalidInputError("--stream-json and --json are exclusive.");
271023
+ }
271024
+ const ndjson = options.streamJson ? ndjsonWriter() : null;
270752
271025
  let app;
270753
271026
  try {
270754
271027
  app = await runTask(options.import ? "Importing the repository" : "Creating your app", () => createAndLinkApp({
@@ -270758,16 +271031,30 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
270758
271031
  mode: options.mode,
270759
271032
  repoName: options.repoName,
270760
271033
  fromBranch: options.fromBranch,
270761
- path: options.path
271034
+ path: options.path,
271035
+ wixLaunch
270762
271036
  }));
270763
271037
  } catch (error) {
270764
271038
  for (const line of await githubReauthLines(error) ?? [])
270765
271039
  log.message(line);
270766
271040
  throw error;
270767
271041
  }
270768
- if (!jsonMode) {
271042
+ if (ndjson) {
271043
+ ndjson({
271044
+ type: "created",
271045
+ id: app.id,
271046
+ repo_url: app.repoUrl ?? null,
271047
+ editor_url: app.editorUrl,
271048
+ dir: app.dirName,
271049
+ path: app.targetDir,
271050
+ ...app.clientCreationId ? { client_creation_id: app.clientCreationId } : {}
271051
+ });
271052
+ } else if (!jsonMode) {
270769
271053
  if (app.repoUrl)
270770
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
+ }
270771
271058
  log.message(source_default.dim(`editor ${app.editorUrl}`));
270772
271059
  log.message(source_default.dim(`linked ${app.here ? "./ (this directory)" : `./${app.dirName}`}`));
270773
271060
  }
@@ -270778,10 +271065,16 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
270778
271065
  const branchId = await resolveActiveBranchId().catch(() => {
270779
271066
  return;
270780
271067
  });
270781
- const stream = createTurnStream(process.stdout.isTTY === true && !jsonMode, undefined, { idleLabel: "provisioning the sandbox and starting the build" });
271068
+ const stream = createTurnStream(process.stdout.isTTY === true && !jsonMode && !ndjson, undefined, {
271069
+ idleLabel: "provisioning the sandbox and starting the build",
271070
+ verbose: options.verbose
271071
+ });
270782
271072
  try {
270783
271073
  const settled = await streamConversationUntilSettled((event) => {
270784
- if (!jsonMode)
271074
+ if (ndjson) {
271075
+ const { kind, ...rest } = event;
271076
+ ndjson({ type: kind, ...rest });
271077
+ } else if (!jsonMode)
270785
271078
  stream.onEvent(event);
270786
271079
  }, { branchId, timeoutMs: POLL_TIMEOUT_MS });
270787
271080
  finalState = settled === "timeout" ? "processing" : (await getAppState(app.id)).status?.state ?? "ready";
@@ -270794,6 +271087,15 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
270794
271087
  stream.stop();
270795
271088
  }
270796
271089
  }
271090
+ if (ndjson) {
271091
+ ndjson({
271092
+ type: "result",
271093
+ id: app.id,
271094
+ preview_url: previewUrl ?? null,
271095
+ status: finalState ?? "created"
271096
+ });
271097
+ return {};
271098
+ }
270797
271099
  if (jsonMode) {
270798
271100
  return {
270799
271101
  stdout: `${JSON.stringify({
@@ -270803,7 +271105,8 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
270803
271105
  preview_url: previewUrl ?? null,
270804
271106
  dir: app.dirName,
270805
271107
  path: app.targetDir,
270806
- status: finalState ?? "created"
271108
+ status: finalState ?? "created",
271109
+ ...app.clientCreationId ? { client_creation_id: app.clientCreationId } : {}
270807
271110
  })}
270808
271111
  `
270809
271112
  };
@@ -270828,61 +271131,7 @@ async function newAction({ log, runTask, jsonMode }, prompt, options) {
270828
271131
  }
270829
271132
  function getNewCommand() {
270830
271133
  const command = new Base44Command("new", { requireAppContext: false });
270831
- 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").action(newAction);
270832
- return command;
270833
- }
270834
-
270835
- // src/cli/commands/builder/send.ts
270836
- function lastAssistantReply(turn) {
270837
- const messages = turn.conversation?.messages ?? [];
270838
- for (let i = messages.length - 1;i >= 0; i--) {
270839
- const { role, content } = messages[i];
270840
- if (role === "assistant" && typeof content === "string" && content.trim()) {
270841
- return content.trim();
270842
- }
270843
- }
270844
- return;
270845
- }
270846
- async function sendAction(ctx, message) {
270847
- if (ctx.app)
270848
- await assertBuilderApp(ctx.app.id);
270849
- const branchId = await resolveBranchId(ctx);
270850
- if (ctx.jsonMode) {
270851
- const turn = await ctx.runTask("Agent working (a turn can take minutes)", () => sendTurn(message, branchId));
270852
- if (turn.queued)
270853
- return { stdout: `${JSON.stringify({ queued: true })}
270854
- ` };
270855
- return {
270856
- stdout: `${JSON.stringify({
270857
- status: turn.status?.state ?? "ready",
270858
- error_source: turn.status?.error_source ?? null,
270859
- reply: lastAssistantReply(turn) ?? null
270860
- })}
270861
- `
270862
- };
270863
- }
270864
- const stream = createTurnStream(process.stdout.isTTY === true);
270865
- let turn;
270866
- try {
270867
- turn = await streamConversationDuring(() => sendTurn(message, branchId), stream.onEvent, { branchId });
270868
- } finally {
270869
- stream.stop();
270870
- }
270871
- if (turn.queued) {
270872
- return {
270873
- outroMessage: "The agent is busy with an earlier message — yours was queued and runs next."
270874
- };
270875
- }
270876
- if (turn.status?.state === "error") {
270877
- return {
270878
- outroMessage: `Turn failed (${turn.status.error_source ?? "unknown"}) — see the editor for details.`
270879
- };
270880
- }
270881
- return { outroMessage: "Turn finished." };
270882
- }
270883
- function getSendCommand() {
270884
- const command = new Base44Command("send", { supportsBranch: true });
270885
- command.description("Send the agent one message and stream the turn until it finishes").argument("<message>", "What you want the agent to do").action(sendAction);
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);
270886
271135
  return command;
270887
271136
  }
270888
271137
 
@@ -276077,6 +276326,393 @@ function createPasteFriendlyStdin(real) {
276077
276326
  return proxy;
276078
276327
  }
276079
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
+
276080
276716
  // src/cli/commands/code/session-engine.ts
276081
276717
  var POLL_MS = 1000;
276082
276718
  function createSessionEngine(options) {
@@ -276096,6 +276732,28 @@ function createSessionEngine(options) {
276096
276732
  let awaitingTurn = options.awaitingTurnLabel ?? null;
276097
276733
  const awaitingSince = Date.now();
276098
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
+ };
276099
276757
  const submit = (raw) => {
276100
276758
  const typed = raw.trim();
276101
276759
  if (!typed)
@@ -276136,25 +276794,38 @@ function createSessionEngine(options) {
276136
276794
  return;
276137
276795
  }
276138
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));
276139
276803
  if (!prime) {
276140
276804
  for (const event of events) {
276141
276805
  if (event.kind === "tool_start") {
276806
+ const startedAt = Date.now();
276142
276807
  running.set(event.id, {
276143
276808
  alias: toolAlias(event.name),
276144
276809
  label: event.label,
276145
276810
  summary: event.summary,
276146
- startedAt: Date.now()
276811
+ startedAt
276147
276812
  });
276813
+ options.onLine({ running: event, startedAt });
276148
276814
  continue;
276149
276815
  }
276150
- let elapsedMs;
276151
276816
  if (event.kind === "tool_end") {
276152
276817
  const started = running.get(event.id)?.startedAt;
276153
- if (started != null)
276154
- elapsedMs = Date.now() - started;
276155
276818
  running.delete(event.id);
276819
+ lastEventAt = Date.now();
276820
+ options.onLine({
276821
+ event,
276822
+ elapsedMs: started != null ? Date.now() - started : undefined
276823
+ });
276824
+ continue;
276156
276825
  }
276157
- const line = eventLine(event, elapsedMs);
276826
+ const line = eventLine(event, undefined, {
276827
+ waitingHint: "answer in the card below"
276828
+ });
276158
276829
  if (line != null) {
276159
276830
  lastEventAt = Date.now();
276160
276831
  options.onLine(line);
@@ -276221,6 +276892,7 @@ function createSessionEngine(options) {
276221
276892
  });
276222
276893
  },
276223
276894
  submit,
276895
+ answer,
276224
276896
  status() {
276225
276897
  let phase = "idle";
276226
276898
  if (awaitingTurn != null)
@@ -276243,7 +276915,8 @@ function createSessionEngine(options) {
276243
276915
  turnStartedAt,
276244
276916
  runningTool,
276245
276917
  lastTurnMs,
276246
- lastTurnOk
276918
+ lastTurnOk,
276919
+ pending
276247
276920
  };
276248
276921
  },
276249
276922
  turnRunning() {
@@ -276275,6 +276948,17 @@ function exitAltScreen() {
276275
276948
  altScreenActive = false;
276276
276949
  process.stdout.write("\x1B[?1007l\x1B[?1049l");
276277
276950
  }
276951
+ function withEntry(items, entry) {
276952
+ if (typeof entry !== "string" && "event" in entry) {
276953
+ const i = items.findIndex((e) => typeof e !== "string" && ("running" in e) && e.running.id === entry.event.id);
276954
+ if (i >= 0) {
276955
+ const next = [...items];
276956
+ next[i] = entry;
276957
+ return next;
276958
+ }
276959
+ }
276960
+ return [...items, entry];
276961
+ }
276278
276962
  function statusText(status, musingSeed) {
276279
276963
  const frame = FRAMES2[Math.floor(Date.now() / 120) % FRAMES2.length];
276280
276964
  switch (status.phase) {
@@ -276282,13 +276966,6 @@ function statusText(status, musingSeed) {
276282
276966
  return source_default.dim(`${frame} ${status.awaitingLabel} (${formatDuration2(Date.now() - status.awaitingSince)})`);
276283
276967
  case "running": {
276284
276968
  const turnFor = formatDuration2(Date.now() - (status.turnStartedAt ?? Date.now()));
276285
- const tool = status.runningTool;
276286
- if (tool) {
276287
- const toolFor = Math.round((Date.now() - tool.startedAt) / 1000);
276288
- const others = tool.others > 0 ? ` (+${tool.others})` : "";
276289
- const what = tool.label || `${tool.alias}${tool.summary ? ` ${tool.summary}` : ""}`;
276290
- return source_default.dim(`${frame} ${what}${others} · ${toolFor}s (turn ${turnFor})`);
276291
- }
276292
276969
  const quiet = status.quietForMs > 60000 ? " · a long private step — details render in the editor" : "";
276293
276970
  return `${source_default.magenta("✻")} ${source_default.dim(`${idleMusing(musingSeed)} (${turnFor})${quiet}`)}`;
276294
276971
  }
@@ -276304,18 +276981,19 @@ function statusText(status, musingSeed) {
276304
276981
  function SessionView({ engine, footer, subscribe }) {
276305
276982
  const { exit } = use_app_default();
276306
276983
  const [items, setItems] = import_react23.useState([]);
276984
+ const [verbose, setVerbose] = import_react23.useState(false);
276307
276985
  const [input, setInput] = import_react23.useState("");
276308
276986
  const [scroll, setScroll] = import_react23.useState(0);
276309
276987
  const [, tick] = import_react23.useReducer((x) => x + 1, 0);
276310
276988
  const [musingSeed] = import_react23.useState(() => Math.floor(Math.random() * 97));
276311
276989
  const [currentModel, setCurrentModel] = import_react23.useState(null);
276312
276990
  const [pickerIndex, setPickerIndex] = import_react23.useState(null);
276991
+ const [card, setCard] = import_react23.useState(null);
276992
+ const dismissedRef = import_react23.useRef(new Set);
276313
276993
  const maxScrollRef = import_react23.useRef(0);
276314
276994
  const meIdRef = import_react23.useRef(null);
276315
- const emit = (line) => setItems((h) => [...h, `${line}
276316
- `]);
276317
- import_react23.useEffect(() => subscribe((line) => setItems((h) => [...h, `${line}
276318
- `])), [subscribe]);
276995
+ const emit = (entry) => setItems((h) => withEntry(h, entry));
276996
+ import_react23.useEffect(() => subscribe((entry) => setItems((h) => withEntry(h, entry))), [subscribe]);
276319
276997
  import_react23.useEffect(() => {
276320
276998
  const timer = setInterval(tick, 120);
276321
276999
  return () => clearInterval(timer);
@@ -276357,6 +277035,29 @@ function SessionView({ engine, footer, subscribe }) {
276357
277035
  emit(source_default.red(` /model: ${error instanceof Error ? error.message : String(error)}`));
276358
277036
  }
276359
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]);
276360
277061
  use_input_default((char, key) => {
276361
277062
  if (pickerIndex !== null) {
276362
277063
  if (key.upArrow)
@@ -276372,6 +277073,23 @@ function SessionView({ engine, footer, subscribe }) {
276372
277073
  }
276373
277074
  return;
276374
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
+ }
276375
277093
  if (key.ctrl && char === "c") {
276376
277094
  if (input)
276377
277095
  setInput("");
@@ -276383,6 +277101,10 @@ function SessionView({ engine, footer, subscribe }) {
276383
277101
  exit();
276384
277102
  return;
276385
277103
  }
277104
+ if (key.ctrl && char === "o") {
277105
+ setVerbose((v) => !v);
277106
+ return;
277107
+ }
276386
277108
  if (key.upArrow) {
276387
277109
  setScroll((s) => Math.min(s + 3, maxScrollRef.current));
276388
277110
  return;
@@ -276408,14 +277130,17 @@ function SessionView({ engine, footer, subscribe }) {
276408
277130
  });
276409
277131
  const columns = process.stdout.columns || 80;
276410
277132
  const rows = process.stdout.rows || 24;
276411
- const width = Math.min(columns, 100);
277133
+ const width = columns;
276412
277134
  const innerWidth = Math.max(10, width - 4);
276413
277135
  const inputRows = Math.max(1, Math.ceil((input.length + 3) / innerWidth));
276414
277136
  const pickerOpen = pickerIndex !== null;
276415
- 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);
276416
277140
  const widgetHeight = inputBlockHeight + 3 + (footer.length ? 1 : 0);
276417
277141
  const viewHeight = Math.max(3, rows - widgetHeight - 1);
276418
- const lines = items.flatMap((item) => hardWrapAnsi(item, columns));
277142
+ const lines = items.flatMap((item) => hardWrapAnsi(`${renderEntry(item, { verbose, foldHint: "Ctrl+O to expand" })}
277143
+ `, columns));
276419
277144
  const maxScroll = Math.max(0, lines.length - viewHeight);
276420
277145
  maxScrollRef.current = maxScroll;
276421
277146
  const clamped = Math.min(scroll, maxScroll);
@@ -276462,29 +277187,64 @@ function SessionView({ engine, footer, subscribe }) {
276462
277187
  }, m.name, false, undefined, this);
276463
277188
  })
276464
277189
  ]
276465
- }, 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",
276466
277202
  borderStyle: "round",
276467
- borderColor: "gray",
277203
+ borderColor: card?.typing ? "yellow" : "gray",
276468
277204
  paddingX: 1,
276469
277205
  width,
276470
277206
  children: [
276471
- /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
276472
- color: "cyan",
276473
- children: "❯ "
276474
- }, undefined, false, undefined, this),
276475
- /* @__PURE__ */ jsx_dev_runtime.jsxDEV(build_default, {
276476
- value: input,
276477
- onChange: setInput,
276478
- onSubmit: (value) => {
276479
- const trimmed = value.trim();
276480
- if (trimmed === "/model" || trimmed.startsWith("/model ")) {
276481
- runModelSlash(trimmed.slice("/model".length).trim());
276482
- } else if (trimmed) {
276483
- engine.submit(value);
276484
- }
276485
- setInput("");
276486
- }
276487
- }, 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)
276488
277248
  ]
276489
277249
  }, undefined, true, undefined, this),
276490
277250
  footer.length > 0 && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
@@ -276498,7 +277258,7 @@ function SessionView({ engine, footer, subscribe }) {
276498
277258
  /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
276499
277259
  dimColor: true,
276500
277260
  wrap: "truncate-end",
276501
- children: pickerOpen ? " ↑↓ to move · Enter to select · Esc to cancel" : engine.turnRunning() ? " Esc to stop · type to queue · scroll to read · Ctrl+C to exit" : " Enter to send · /model to switch model · Esc for live · 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"
276502
277262
  }, undefined, false, undefined, this)
276503
277263
  ]
276504
277264
  }, undefined, true, undefined, this);
@@ -276623,6 +277383,7 @@ async function runGenesisSession(options) {
276623
277383
  runningTool: null,
276624
277384
  lastTurnMs: null,
276625
277385
  lastTurnOk: true,
277386
+ pending: [],
276626
277387
  quietForMs: 0
276627
277388
  };
276628
277389
  const genesis = {
@@ -276678,6 +277439,9 @@ async function runGenesisSession(options) {
276678
277439
  }
276679
277440
  return IDLE_STATUS;
276680
277441
  },
277442
+ answer(p, action, input) {
277443
+ inner?.answer(p, action, input);
277444
+ },
276681
277445
  turnRunning() {
276682
277446
  return inner?.turnRunning() ?? creating;
276683
277447
  }
@@ -276710,10 +277474,10 @@ async function runGenesisSession(options) {
276710
277474
 
276711
277475
  // src/cli/commands/code/index.ts
276712
277476
  var BRAND_ORANGE2 = "#E86B3C";
276713
- async function bootstrapApp(prompt, footer, emit, onCreated, importRepo, path) {
277477
+ async function bootstrapApp(prompt, footer, emit, onCreated, importRepo, path, wixLaunch) {
276714
277478
  let app;
276715
277479
  try {
276716
- app = await createAndLinkApp({ prompt, importRepo, path });
277480
+ app = await createAndLinkApp({ prompt, importRepo, path, wixLaunch });
276717
277481
  } catch (error) {
276718
277482
  for (const line of await githubReauthLines(error) ?? [])
276719
277483
  emit(line);
@@ -276760,8 +277524,8 @@ async function codeAction({ log }, options, appId) {
276760
277524
  linked = true;
276761
277525
  } catch {}
276762
277526
  if (linked) {
276763
- if (options.import || options.path) {
276764
- 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.");
276765
277529
  }
276766
277530
  const { id, projectRoot } = getAppContext();
276767
277531
  const state = await assertBuilderApp(id);
@@ -276784,16 +277548,22 @@ async function codeAction({ log }, options, appId) {
276784
277548
  outroMessage: `Session closed. Resume with \`base44 code --app-id ${id}\`.`
276785
277549
  };
276786
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;
276787
277555
  let created;
276788
- 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
+ ];
276789
277559
  await runGenesisSession({
276790
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",
276791
277561
  creatingLabel: options.import ? "importing the repository" : "creating your app",
276792
- 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",
276793
277563
  footer,
276794
277564
  createApp: (prompt, emit) => bootstrapApp(prompt, footer, emit, (app) => {
276795
277565
  created = app;
276796
- }, options.import, options.path)
277566
+ }, options.import, options.path, wixLaunch)
276797
277567
  });
276798
277568
  if (!created) {
276799
277569
  return { outroMessage: "Session closed. No app was created." };
@@ -276805,7 +277575,7 @@ async function codeAction({ log }, options, appId) {
276805
277575
  }
276806
277576
  function getCodeCommand() {
276807
277577
  const command = new Base44Command("code", { requireAppContext: false });
276808
- 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));
276809
277579
  return command;
276810
277580
  }
276811
277581
 
@@ -284188,7 +284958,7 @@ async function runScript(options) {
284188
284958
  }
284189
284959
  }
284190
284960
  // src/cli/commands/exec.ts
284191
- function readStdin2() {
284961
+ function readStdin3() {
284192
284962
  return new Promise((resolve, reject) => {
284193
284963
  let data = "";
284194
284964
  process.stdin.setEncoding("utf-8");
@@ -284232,7 +285002,7 @@ async function execAction({ app, isNonInteractive }, options) {
284232
285002
  if (!isNonInteractive) {
284233
285003
  throw noInputError;
284234
285004
  }
284235
- const code = await readStdin2();
285005
+ const code = await readStdin3();
284236
285006
  if (!code.trim()) {
284237
285007
  throw noInputError;
284238
285008
  }
@@ -288413,6 +289183,13 @@ function getFullCommandName(command) {
288413
289183
  }
288414
289184
  return parts.join(" ");
288415
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
+ }
288416
289193
  function addCommandInfoToErrorReporter(program, errorReporter) {
288417
289194
  program.hook("preAction", (_, actionCommand) => {
288418
289195
  const fullCommandName = getFullCommandName(actionCommand);
@@ -288420,7 +289197,7 @@ function addCommandInfoToErrorReporter(program, errorReporter) {
288420
289197
  command: {
288421
289198
  name: fullCommandName,
288422
289199
  args: actionCommand.args,
288423
- options: actionCommand.opts()
289200
+ options: redactSensitiveOptions(actionCommand.opts())
288424
289201
  }
288425
289202
  });
288426
289203
  });
@@ -288467,4 +289244,4 @@ export {
288467
289244
  runCLI
288468
289245
  };
288469
289246
 
288470
- //# debugId=C14BEE0A94355AC364756E2164756E21
289247
+ //# debugId=D93D1396A8EFA10D64756E2164756E21