@algolia/wizard 0.50.0 → 0.52.0-rc.136.364

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.
Files changed (2) hide show
  1. package/dist/main.js +507 -325
  2. package/package.json +1 -2
package/dist/main.js CHANGED
@@ -4,7 +4,7 @@
4
4
  import { render } from "ink";
5
5
 
6
6
  // src/ui/App.tsx
7
- import { Box as Box20, Text as Text20, useApp, useInput as useInput7, useWindowSize as useWindowSize7 } from "ink";
7
+ import { Box as Box20, Text as Text21, useApp, useInput as useInput8, useWindowSize as useWindowSize7 } from "ink";
8
8
  import Spinner3 from "ink-spinner";
9
9
 
10
10
  // src/core/store.ts
@@ -239,6 +239,9 @@ function describeInputValue(value) {
239
239
  }
240
240
  var NOTICE_INTERVAL_MS = 2e3;
241
241
  var CLI_OUTPUT_LIMIT = 200;
242
+ function commandApprovalKey(command, cwd) {
243
+ return `${cwd}\0${command}`;
244
+ }
242
245
  var useWizard = create((set, get) => ({
243
246
  phase: "idle",
244
247
  homeScreen: "home",
@@ -356,10 +359,17 @@ var useWizard = create((set, get) => ({
356
359
  setTargetIndex: (index) => set({ targetIndex: index }),
357
360
  recordWrittenFile: (path) => set((s) => ({ writtenFiles: [...s.writtenFiles, path] })),
358
361
  clearWrittenFiles: () => set({ writtenFiles: [] }),
359
- isCommandApproved: (command, cwd) => get().approvedCommands.has(`${cwd}\0${command}`),
362
+ isCommandApproved: (command, cwd) => get().approvedCommands.has(commandApprovalKey(command, cwd)),
360
363
  approveCommand: (command, cwd) => set((s) => ({
361
- approvedCommands: new Set(s.approvedCommands).add(`${cwd}\0${command}`)
364
+ approvedCommands: new Set(s.approvedCommands).add(
365
+ commandApprovalKey(command, cwd)
366
+ )
362
367
  })),
368
+ revokeCommand: (command, cwd) => set((s) => {
369
+ const approvedCommands = new Set(s.approvedCommands);
370
+ approvedCommands.delete(commandApprovalKey(command, cwd));
371
+ return { approvedCommands };
372
+ }),
363
373
  logStart: (kind, name, input) => {
364
374
  const id = nanoid();
365
375
  set((s) => ({
@@ -641,10 +651,9 @@ function Notices({
641
651
  }
642
652
 
643
653
  // src/ui/PromptInput.tsx
644
- import { Box as Box9, Text as Text9 } from "ink";
654
+ import { Box as Box9, Text as Text10 } from "ink";
645
655
  import Spinner from "ink-spinner";
646
- import TextInput from "ink-text-input";
647
- import { useState as useState6 } from "react";
656
+ import { useState as useState7 } from "react";
648
657
 
649
658
  // src/ui/CommandApproval.tsx
650
659
  import { Box as Box6, Text as Text6 } from "ink";
@@ -739,9 +748,11 @@ function DecisionSelect({
739
748
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
740
749
  function CommandApproval({
741
750
  command,
751
+ messages,
742
752
  onDecide
743
753
  }) {
744
754
  return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", gap: 1, children: [
755
+ messages?.map((message, index) => /* @__PURE__ */ jsx5(Text6, { color: COLORS.muted, children: message }, `msg-${index}`)),
745
756
  /* @__PURE__ */ jsx5(Text6, { color: COLORS.primary, bold: true, children: "Run this command?" }),
746
757
  /* @__PURE__ */ jsxs5(
747
758
  Box6,
@@ -783,14 +794,62 @@ function CommandApproval({
783
794
  ] });
784
795
  }
785
796
 
797
+ // src/ui/FreeTextInput.tsx
798
+ import { Text as Text7, useInput as useInput2 } from "ink";
799
+ import { useState as useState4 } from "react";
800
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
801
+ function FreeTextInput({
802
+ value,
803
+ onChange,
804
+ onSubmit
805
+ }) {
806
+ const [cursor, setCursor] = useState4(value.length);
807
+ const at = Math.min(cursor, value.length);
808
+ useInput2((input, key) => {
809
+ if (key.upArrow || key.downArrow || key.tab || key.ctrl && input === "c") {
810
+ return;
811
+ }
812
+ if (key.return) {
813
+ onSubmit(value);
814
+ return;
815
+ }
816
+ if (key.leftArrow) {
817
+ setCursor(Math.max(0, at - 1));
818
+ return;
819
+ }
820
+ if (key.rightArrow) {
821
+ setCursor(Math.min(value.length, at + 1));
822
+ return;
823
+ }
824
+ if (key.backspace || key.delete) {
825
+ if (at === 0) return;
826
+ onChange(value.slice(0, at - 1) + value.slice(at));
827
+ setCursor(at - 1);
828
+ return;
829
+ }
830
+ if (input) {
831
+ onChange(value.slice(0, at) + input + value.slice(at));
832
+ setCursor(at + input.length);
833
+ }
834
+ });
835
+ const before = value.slice(0, at);
836
+ const current = value.slice(at, at + 1) || " ";
837
+ const after = value.slice(at + 1);
838
+ return /* @__PURE__ */ jsxs6(Text7, { color: COLORS.strong, children: [
839
+ before,
840
+ /* @__PURE__ */ jsx6(Text7, { inverse: true, children: current }),
841
+ after
842
+ ] });
843
+ }
844
+
786
845
  // src/ui/SelectPrompt.tsx
787
- import { Box as Box8, Text as Text8, useInput as useInput2, useWindowSize as useWindowSize4 } from "ink";
788
- import { useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState5 } from "react";
846
+ import { Box as Box8, Text as Text9, useInput as useInput3, useWindowSize as useWindowSize4 } from "ink";
847
+ import { useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState6 } from "react";
789
848
 
790
849
  // src/ui/ScrollView.tsx
791
- import { Box as Box7, Text as Text7, measureElement as measureElement2, useWindowSize as useWindowSize3 } from "ink";
792
- import { useCallback, useLayoutEffect, useRef as useRef2, useState as useState4 } from "react";
793
- import { jsxs as jsxs6 } from "react/jsx-runtime";
850
+ import { Box as Box7, Text as Text8, measureElement as measureElement2, useWindowSize as useWindowSize3 } from "ink";
851
+ import { useCallback, useLayoutEffect, useRef as useRef2, useState as useState5 } from "react";
852
+ import { jsxs as jsxs7 } from "react/jsx-runtime";
794
853
  var INDICATOR_ROWS = 2;
795
854
  function fittedWidth(node, columns) {
796
855
  let left = 0;
@@ -806,7 +865,7 @@ function useScrollWindow({
806
865
  }) {
807
866
  const viewportRef = useRef2(null);
808
867
  const { columns } = useWindowSize3();
809
- const [size, setSize] = useState4(
868
+ const [size, setSize] = useState5(
810
869
  null
811
870
  );
812
871
  useLayoutEffect(() => {
@@ -819,7 +878,7 @@ function useScrollWindow({
819
878
  });
820
879
  const capacity = size === null || itemCount * rowHeight <= size.height ? itemCount : Math.max(Math.floor((size.height - INDICATOR_ROWS) / rowHeight), 1);
821
880
  const maxOffset = Math.max(itemCount - capacity, 0);
822
- const [offset, setOffset] = useState4(0);
881
+ const [offset, setOffset] = useState5(0);
823
882
  const prevMaxOffsetRef = useRef2(0);
824
883
  useLayoutEffect(() => {
825
884
  const wasAtBottom = offset >= prevMaxOffsetRef.current;
@@ -861,14 +920,14 @@ function useScrollWindow({
861
920
  };
862
921
  }
863
922
  function ScrollView({ scroll, children }) {
864
- return /* @__PURE__ */ jsxs6(Box7, { ref: scroll.viewportRef, flexDirection: "column", flexGrow: 1, children: [
865
- scroll.hiddenAbove > 0 && /* @__PURE__ */ jsxs6(Text7, { color: COLORS.dim, children: [
923
+ return /* @__PURE__ */ jsxs7(Box7, { ref: scroll.viewportRef, flexDirection: "column", flexGrow: 1, children: [
924
+ scroll.hiddenAbove > 0 && /* @__PURE__ */ jsxs7(Text8, { color: COLORS.dim, children: [
866
925
  "\u2191 ",
867
926
  scroll.hiddenAbove,
868
927
  " more"
869
928
  ] }),
870
929
  children,
871
- scroll.hiddenBelow > 0 && /* @__PURE__ */ jsxs6(Text7, { color: COLORS.dim, children: [
930
+ scroll.hiddenBelow > 0 && /* @__PURE__ */ jsxs7(Text8, { color: COLORS.dim, children: [
872
931
  "\u2193 ",
873
932
  scroll.hiddenBelow,
874
933
  " more"
@@ -877,7 +936,7 @@ function ScrollView({ scroll, children }) {
877
936
  }
878
937
 
879
938
  // src/ui/SelectPrompt.tsx
880
- import { jsx as jsx6, jsxs as jsxs7 } from "react/jsx-runtime";
939
+ import { jsx as jsx7, jsxs as jsxs8 } from "react/jsx-runtime";
881
940
  var CANCEL = "cancel";
882
941
  var ARROW_WIDTH = 4;
883
942
  var COLUMN_GAP = 2;
@@ -909,18 +968,18 @@ function SelectPrompt({
909
968
  const rows = hasCancel ? [...options, "Cancel"] : options;
910
969
  const cancelIndex = hasCancel ? options.length : -1;
911
970
  const isDisabled = (i) => i !== cancelIndex && Boolean(disabled?.[i]);
912
- const [index, setIndex] = useState5(() => {
971
+ const [index, setIndex] = useState6(() => {
913
972
  const start = defaultSelectedIndex > 0 && defaultSelectedIndex < options.length ? defaultSelectedIndex : 0;
914
973
  return isDisabled(start) ? nextSelectableIndex(start, 1, rows.length, isDisabled) : start;
915
974
  });
916
- const [checked, setChecked] = useState5(() => /* @__PURE__ */ new Set());
975
+ const [checked, setChecked] = useState6(() => /* @__PURE__ */ new Set());
917
976
  const hints = [];
918
977
  if (rows.length > 1) hints.push({ key: "[\u2191] [\u2193]", label: "move" });
919
978
  if (multi) hints.push({ key: "[space]", label: "select" });
920
979
  hints.push({ key: "[enter]", label: "confirm" });
921
980
  const containerRef = useRef3(null);
922
981
  const { columns } = useWindowSize4();
923
- const [width, setWidth] = useState5(columns);
982
+ const [width, setWidth] = useState6(columns);
924
983
  useLayoutEffect2(() => {
925
984
  if (!containerRef.current) return;
926
985
  const measured = fittedWidth(containerRef.current, columns);
@@ -950,7 +1009,7 @@ function SelectPrompt({
950
1009
  revealIndex(index);
951
1010
  }, [index, revealIndex]);
952
1011
  const visible = rows.slice(scroll.offset, scroll.offset + scroll.capacity);
953
- useInput2((input, key) => {
1012
+ useInput3((input, key) => {
954
1013
  if (rows.length === 0) return;
955
1014
  if (key.upArrow || input === "k") {
956
1015
  setIndex((i) => nextSelectableIndex(i, -1, rows.length, isDisabled));
@@ -975,17 +1034,17 @@ function SelectPrompt({
975
1034
  }
976
1035
  }
977
1036
  });
978
- return /* @__PURE__ */ jsx6(Box8, { ref: containerRef, flexGrow: 1, children: /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 1, width, children: [
979
- /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 1, flexShrink: 0, children: [
980
- error && /* @__PURE__ */ jsx6(Text8, { color: COLORS.danger, children: error }),
981
- messages?.map((m, i) => /* @__PURE__ */ jsx6(Text8, { color: COLORS.muted, children: m }, `msg-${i}`)),
982
- table && /* @__PURE__ */ jsx6(Table, { columns: table.columns, rows: table.rows }),
983
- /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", children: [
984
- question && /* @__PURE__ */ jsx6(Text8, { color: COLORS.muted, children: question }),
985
- helpText && /* @__PURE__ */ jsx6(Text8, { color: COLORS.dim, children: helpText })
1037
+ return /* @__PURE__ */ jsx7(Box8, { ref: containerRef, flexGrow: 1, children: /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, width, children: [
1038
+ /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, flexShrink: 0, children: [
1039
+ error && /* @__PURE__ */ jsx7(Text9, { color: COLORS.danger, children: error }),
1040
+ messages?.map((m, i) => /* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: m }, `msg-${i}`)),
1041
+ table && /* @__PURE__ */ jsx7(Table, { columns: table.columns, rows: table.rows }),
1042
+ /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
1043
+ question && /* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: question }),
1044
+ helpText && /* @__PURE__ */ jsx7(Text9, { color: COLORS.dim, children: helpText })
986
1045
  ] })
987
1046
  ] }),
988
- /* @__PURE__ */ jsx6(ScrollView, { scroll, children: visible.map((option, visibleIndex) => {
1047
+ /* @__PURE__ */ jsx7(ScrollView, { scroll, children: visible.map((option, visibleIndex) => {
989
1048
  const i = scroll.offset + visibleIndex;
990
1049
  const highlighted = i === index;
991
1050
  const isCancel = i === cancelIndex;
@@ -993,7 +1052,7 @@ function SelectPrompt({
993
1052
  const sec = isCancel ? void 0 : secondary?.[i];
994
1053
  const isText = sec?.kind === "text";
995
1054
  const rowDisabled = isDisabled(i);
996
- return /* @__PURE__ */ jsxs7(
1055
+ return /* @__PURE__ */ jsxs8(
997
1056
  SelectRow,
998
1057
  {
999
1058
  highlighted,
@@ -1003,24 +1062,24 @@ function SelectPrompt({
1003
1062
  label: `${bullet}${option}`,
1004
1063
  usePadding: true,
1005
1064
  children: [
1006
- isText && textWidth > 0 && /* @__PURE__ */ jsx6(Box8, { width: textWidth, children: /* @__PURE__ */ jsx6(
1007
- Text8,
1065
+ isText && textWidth > 0 && /* @__PURE__ */ jsx7(Box8, { width: textWidth, children: /* @__PURE__ */ jsx7(
1066
+ Text9,
1008
1067
  {
1009
1068
  wrap: "truncate",
1010
1069
  color: rowDisabled ? COLORS.dim : highlighted ? COLORS.primary : COLORS.muted,
1011
1070
  children: sec.value
1012
1071
  }
1013
1072
  ) }),
1014
- sec?.kind === "badge" && /* @__PURE__ */ jsx6(Box8, { width: badgeWidth, justifyContent: "flex-end", children: /* @__PURE__ */ jsx6(Text8, { color: COLORS.badge, wrap: "truncate", children: sec.value }) })
1073
+ sec?.kind === "badge" && /* @__PURE__ */ jsx7(Box8, { width: badgeWidth, justifyContent: "flex-end", children: /* @__PURE__ */ jsx7(Text9, { color: COLORS.badge, wrap: "truncate", children: sec.value }) })
1015
1074
  ]
1016
1075
  },
1017
1076
  `row-${i}`
1018
1077
  );
1019
1078
  }) }),
1020
- /* @__PURE__ */ jsx6(Box8, { flexShrink: 0, children: /* @__PURE__ */ jsx6(Text8, { color: COLORS.dim, children: hints.map(({ key, label }, i) => /* @__PURE__ */ jsxs7(Text8, { color: COLORS.dim, children: [
1079
+ /* @__PURE__ */ jsx7(Box8, { flexShrink: 0, children: /* @__PURE__ */ jsx7(Text9, { color: COLORS.dim, children: hints.map(({ key, label }, i) => /* @__PURE__ */ jsxs8(Text9, { color: COLORS.dim, children: [
1021
1080
  i > 0 ? " " : "",
1022
- /* @__PURE__ */ jsx6(Text8, { color: COLORS.primary, children: key }),
1023
- /* @__PURE__ */ jsxs7(Text8, { color: COLORS.dim, children: [
1081
+ /* @__PURE__ */ jsx7(Text9, { color: COLORS.primary, children: key }),
1082
+ /* @__PURE__ */ jsxs8(Text9, { color: COLORS.dim, children: [
1024
1083
  " ",
1025
1084
  label
1026
1085
  ] })
@@ -1029,17 +1088,17 @@ function SelectPrompt({
1029
1088
  }
1030
1089
 
1031
1090
  // src/ui/PromptInput.tsx
1032
- import { jsx as jsx7, jsxs as jsxs8 } from "react/jsx-runtime";
1091
+ import { jsx as jsx8, jsxs as jsxs9 } from "react/jsx-runtime";
1033
1092
  var ACCEPT_REJECT_OPTIONS = ["Accept", "Reject"];
1034
1093
  function EnterToContinuePrompt({
1035
1094
  question,
1036
1095
  messages,
1037
1096
  onDecide
1038
1097
  }) {
1039
- return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", gap: 1, children: [
1040
- messages?.map((m, i) => /* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: m }, `msg-${i}`)),
1041
- question && /* @__PURE__ */ jsx7(Text9, { color: COLORS.primary, children: question }),
1042
- /* @__PURE__ */ jsx7(
1098
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", gap: 1, children: [
1099
+ messages?.map((m, i) => /* @__PURE__ */ jsx8(Text10, { color: COLORS.muted, children: m }, `msg-${i}`)),
1100
+ question && /* @__PURE__ */ jsx8(Text10, { color: COLORS.primary, children: question }),
1101
+ /* @__PURE__ */ jsx8(
1043
1102
  DecisionSelect,
1044
1103
  {
1045
1104
  actions: [
@@ -1053,17 +1112,17 @@ function EnterToContinuePrompt({
1053
1112
  }
1054
1113
  function PromptInput() {
1055
1114
  const { phase, inputReq, submitInput } = useWizard();
1056
- const [draft, setDraft] = useState6("");
1057
- const [submittedReq, setSubmittedReq] = useState6(null);
1115
+ const [draft, setDraft] = useState7("");
1116
+ const [submittedReq, setSubmittedReq] = useState7(null);
1058
1117
  const promptKey = inputReq && `${inputReq.promptType}:${inputReq.prompt}`;
1059
1118
  const submitting = inputReq != null && submittedReq === inputReq;
1060
1119
  if (phase === "done" || phase === "error") {
1061
- return /* @__PURE__ */ jsx7(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text9, { color: "gray", dimColor: true, children: "Press Enter or Esc to exit" }) });
1120
+ return /* @__PURE__ */ jsx8(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text10, { color: "gray", dimColor: true, children: "Press Enter or Esc to exit" }) });
1062
1121
  }
1063
1122
  if (phase !== "awaitingInput" || !inputReq) return null;
1064
1123
  if (submitting) {
1065
- return /* @__PURE__ */ jsx7(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsxs8(Text9, { color: COLORS.strong, bold: true, children: [
1066
- /* @__PURE__ */ jsx7(Spinner, { type: "dots" }),
1124
+ return /* @__PURE__ */ jsx8(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsxs9(Text10, { color: COLORS.strong, bold: true, children: [
1125
+ /* @__PURE__ */ jsx8(Spinner, { type: "dots" }),
1067
1126
  " Continuing\u2026"
1068
1127
  ] }) });
1069
1128
  }
@@ -1072,7 +1131,7 @@ function PromptInput() {
1072
1131
  submitInput(value);
1073
1132
  };
1074
1133
  if (inputReq.promptType === "multipleChoice") {
1075
- return /* @__PURE__ */ jsx7(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx7(
1134
+ return /* @__PURE__ */ jsx8(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx8(
1076
1135
  SelectPrompt,
1077
1136
  {
1078
1137
  question: inputReq.prompt,
@@ -1091,7 +1150,7 @@ function PromptInput() {
1091
1150
  ) });
1092
1151
  }
1093
1152
  if (inputReq.promptType === "multiSelect") {
1094
- return /* @__PURE__ */ jsx7(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx7(
1153
+ return /* @__PURE__ */ jsx8(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx8(
1095
1154
  SelectPrompt,
1096
1155
  {
1097
1156
  multi: true,
@@ -1107,10 +1166,9 @@ function PromptInput() {
1107
1166
  ) });
1108
1167
  }
1109
1168
  if (inputReq.promptType === "notice") {
1110
- return /* @__PURE__ */ jsx7(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx7(
1169
+ return /* @__PURE__ */ jsx8(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx8(
1111
1170
  SelectPrompt,
1112
1171
  {
1113
- question: inputReq.prompt,
1114
1172
  messages: inputReq.messages,
1115
1173
  options: ["Continue"],
1116
1174
  onSelect: handleSubmit
@@ -1119,7 +1177,7 @@ function PromptInput() {
1119
1177
  ) });
1120
1178
  }
1121
1179
  if (inputReq.promptType === "enterToContinue") {
1122
- return /* @__PURE__ */ jsx7(
1180
+ return /* @__PURE__ */ jsx8(
1123
1181
  EnterToContinuePrompt,
1124
1182
  {
1125
1183
  question: inputReq.prompt,
@@ -1129,11 +1187,18 @@ function PromptInput() {
1129
1187
  );
1130
1188
  }
1131
1189
  if (inputReq.promptType === "commandApproval" && inputReq.command) {
1132
- return /* @__PURE__ */ jsx7(CommandApproval, { command: inputReq.command, onDecide: submitInput });
1190
+ return /* @__PURE__ */ jsx8(
1191
+ CommandApproval,
1192
+ {
1193
+ command: inputReq.command,
1194
+ messages: inputReq.messages,
1195
+ onDecide: submitInput
1196
+ }
1197
+ );
1133
1198
  }
1134
1199
  if (inputReq.promptType === "acceptReject") {
1135
1200
  const labels = inputReq.options?.length ? inputReq.options : ACCEPT_REJECT_OPTIONS;
1136
- return /* @__PURE__ */ jsx7(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx7(
1201
+ return /* @__PURE__ */ jsx8(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx8(
1137
1202
  SelectPrompt,
1138
1203
  {
1139
1204
  question: inputReq.prompt,
@@ -1145,16 +1210,16 @@ function PromptInput() {
1145
1210
  promptKey
1146
1211
  ) });
1147
1212
  }
1148
- return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", children: [
1149
- inputReq.error && /* @__PURE__ */ jsx7(Text9, { color: COLORS.danger, children: inputReq.error }),
1150
- inputReq.messages?.map((m, i) => /* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: m }, `msg-${i}`)),
1151
- /* @__PURE__ */ jsxs8(Box9, { children: [
1152
- /* @__PURE__ */ jsxs8(Text9, { color: COLORS.primary, children: [
1213
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
1214
+ inputReq.error && /* @__PURE__ */ jsx8(Text10, { color: COLORS.danger, children: inputReq.error }),
1215
+ inputReq.messages?.map((m, i) => /* @__PURE__ */ jsx8(Text10, { color: COLORS.muted, children: m }, `msg-${i}`)),
1216
+ /* @__PURE__ */ jsxs9(Box9, { children: [
1217
+ /* @__PURE__ */ jsxs9(Text10, { color: COLORS.primary, children: [
1153
1218
  inputReq.prompt,
1154
1219
  " "
1155
1220
  ] }),
1156
- /* @__PURE__ */ jsx7(Text9, { color: COLORS.strong, children: /* @__PURE__ */ jsx7(
1157
- TextInput,
1221
+ /* @__PURE__ */ jsx8(
1222
+ FreeTextInput,
1158
1223
  {
1159
1224
  value: draft,
1160
1225
  onChange: setDraft,
@@ -1163,15 +1228,15 @@ function PromptInput() {
1163
1228
  setDraft("");
1164
1229
  }
1165
1230
  }
1166
- ) })
1231
+ )
1167
1232
  ] })
1168
1233
  ] });
1169
1234
  }
1170
1235
 
1171
1236
  // src/ui/Review.tsx
1172
- import { Box as Box10, Text as Text10, useInput as useInput3 } from "ink";
1173
- import { useLayoutEffect as useLayoutEffect3, useState as useState7 } from "react";
1174
- import { jsx as jsx8, jsxs as jsxs9 } from "react/jsx-runtime";
1237
+ import { Box as Box10, Text as Text11, useInput as useInput4 } from "ink";
1238
+ import { useLayoutEffect as useLayoutEffect3, useState as useState8 } from "react";
1239
+ import { jsx as jsx9, jsxs as jsxs10 } from "react/jsx-runtime";
1175
1240
  var INGEST_SCRIPT = ".algolia-wizard/ingest.sh";
1176
1241
  function wrapText(text, width) {
1177
1242
  if (width <= 0) return [text];
@@ -1254,14 +1319,14 @@ function buildRows(review2, width) {
1254
1319
  return rows;
1255
1320
  }
1256
1321
  function ReviewPanel({ review: review2 }) {
1257
- const [width, setWidth] = useState7(0);
1322
+ const [width, setWidth] = useState8(0);
1258
1323
  const rows = width > 0 ? buildRows(review2, width) : [];
1259
1324
  const scroll = useScrollWindow({ itemCount: rows.length });
1260
1325
  useLayoutEffect3(() => {
1261
1326
  if (scroll.measured) setWidth(scroll.width);
1262
1327
  }, [scroll.measured, scroll.width]);
1263
1328
  const scrollable = scroll.maxOffset > 0;
1264
- useInput3(
1329
+ useInput4(
1265
1330
  (_input, key) => {
1266
1331
  if (key.upArrow) scroll.scrollBy(-1);
1267
1332
  else if (key.downArrow) scroll.scrollBy(1);
@@ -1269,18 +1334,18 @@ function ReviewPanel({ review: review2 }) {
1269
1334
  { isActive: scrollable }
1270
1335
  );
1271
1336
  const visible = rows.slice(scroll.offset, scroll.offset + scroll.capacity);
1272
- return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "column", flexGrow: 1, children: [
1273
- /* @__PURE__ */ jsx8(ScrollView, { scroll, children: visible.map((row, i) => /* @__PURE__ */ jsxs9(Text10, { wrap: "truncate", children: [
1274
- row.prefix && /* @__PURE__ */ jsx8(Text10, { color: row.prefixColor ?? row.color, bold: row.bold, children: row.prefix }),
1275
- /* @__PURE__ */ jsx8(Text10, { color: row.color, bold: row.bold, children: row.text })
1337
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", flexGrow: 1, children: [
1338
+ /* @__PURE__ */ jsx9(ScrollView, { scroll, children: visible.map((row, i) => /* @__PURE__ */ jsxs10(Text11, { wrap: "truncate", children: [
1339
+ row.prefix && /* @__PURE__ */ jsx9(Text11, { color: row.prefixColor ?? row.color, bold: row.bold, children: row.prefix }),
1340
+ /* @__PURE__ */ jsx9(Text11, { color: row.color, bold: row.bold, children: row.text })
1276
1341
  ] }, `review-row-${i}`)) }),
1277
- scrollable && /* @__PURE__ */ jsx8(Text10, { color: COLORS.dim, children: "\u2191/\u2193 scroll" })
1342
+ scrollable && /* @__PURE__ */ jsx9(Text11, { color: COLORS.dim, children: "\u2191/\u2193 scroll" })
1278
1343
  ] });
1279
1344
  }
1280
1345
  function Review() {
1281
1346
  const review2 = useWizard((s) => s.review);
1282
1347
  if (!review2) return null;
1283
- return /* @__PURE__ */ jsx8(ReviewPanel, { review: review2 });
1348
+ return /* @__PURE__ */ jsx9(ReviewPanel, { review: review2 });
1284
1349
  }
1285
1350
 
1286
1351
  // src/workflows/default.ts
@@ -2651,9 +2716,16 @@ function searchFilesTool(ctx) {
2651
2716
  }
2652
2717
 
2653
2718
  // src/lib/tools/runShell.ts
2654
- import { tool as tool8, generateText, Output } from "ai";
2719
+ import { tool as tool9, generateText, Output } from "ai";
2655
2720
  import { createAnthropic } from "@ai-sdk/anthropic";
2721
+ import z16 from "zod";
2722
+ import { relative as relative5 } from "node:path";
2723
+
2724
+ // src/lib/tools/reviewScript.ts
2725
+ import { tool as tool8 } from "ai";
2656
2726
  import z15 from "zod";
2727
+ import { createHash } from "node:crypto";
2728
+ import { readFile as readFile7, stat as stat2 } from "node:fs/promises";
2657
2729
  import { relative as relative4 } from "node:path";
2658
2730
 
2659
2731
  // src/lib/tools/utils/prompt.ts
@@ -2665,6 +2737,116 @@ function serializePrompt(work) {
2665
2737
  return result;
2666
2738
  }
2667
2739
 
2740
+ // src/lib/tools/reviewScript.ts
2741
+ var reviewedCommandApprovals = /* @__PURE__ */ new WeakMap();
2742
+ async function fileDigest(filePath) {
2743
+ const content = await readFile7(filePath);
2744
+ return createHash("sha256").update(content).digest("hex");
2745
+ }
2746
+ function grantReviewedCommandApproval(ctx, approval) {
2747
+ reviewedCommandApprovals.set(ctx, approval);
2748
+ }
2749
+ function getReviewedCommandApproval(ctx, command, cwd) {
2750
+ const approval = reviewedCommandApprovals.get(ctx);
2751
+ if (approval?.command !== command || approval.cwd !== cwd) return void 0;
2752
+ return approval;
2753
+ }
2754
+ function clearReviewedCommandApproval(ctx) {
2755
+ reviewedCommandApprovals.delete(ctx);
2756
+ }
2757
+ function revokeCommandApprovals(ctx, command, cwd) {
2758
+ clearReviewedCommandApproval(ctx);
2759
+ useWizard.getState().revokeCommand(command, cwd);
2760
+ }
2761
+ async function reviewedCommandApprovalIsCurrent(approval) {
2762
+ const currentDigest = await fileDigest(approval.filePath).catch(() => null);
2763
+ return currentDigest === approval.digest;
2764
+ }
2765
+ function reviewScriptTool(ctx) {
2766
+ return tool8({
2767
+ description: "Call this as soon as the ingestion script is finished and before you run it. It summarizes the records that will be written, then asks the user to review the script and approve the exact command that will run it, so a matching runShell call needs no second approval.",
2768
+ inputSchema: z15.object({
2769
+ filePath: z15.string().describe(
2770
+ "Path to the script to review, relative to the project root."
2771
+ ),
2772
+ command: z15.string().min(1).describe("The exact command that runShell will use to run the script."),
2773
+ cwd: z15.string().describe(
2774
+ "The exact working directory that runShell will use, relative to the current tool working directory."
2775
+ ),
2776
+ entityName: z15.string().trim().min(1).max(100).regex(/^[^\r\n]+$/).describe("The exact entity name selected by the user."),
2777
+ usesGeneratedRecords: z15.boolean().describe(
2778
+ "Whether the script reads generated sample records instead of the selected real data source."
2779
+ )
2780
+ }),
2781
+ execute: async ({
2782
+ filePath,
2783
+ command,
2784
+ cwd,
2785
+ entityName,
2786
+ usesGeneratedRecords
2787
+ }) => {
2788
+ logger.info(
2789
+ { filePath, command, cwd, entityName, usesGeneratedRecords },
2790
+ "called reviewScript tool"
2791
+ );
2792
+ const resolved2 = resolveInRoot(ctx, filePath);
2793
+ if (resolved2.ok === false) return resolved2.error;
2794
+ const resolvedCwd = resolveInRoot(ctx, cwd);
2795
+ if (resolvedCwd.ok === false) return resolvedCwd.error;
2796
+ const displayCwd = relative4(ctx.root, resolvedCwd.target) || ".";
2797
+ const displayFilePath = relative4(ctx.root, resolved2.target);
2798
+ const ingestionSummary = usesGeneratedRecords ? `This will push ${entityName} records from generated sample data to Algolia. You can replace the sample dataset with your real data source in ${displayFilePath}.` : `This will push ${entityName} records from your selected source to Algolia.`;
2799
+ return serializePrompt(async () => {
2800
+ revokeCommandApprovals(ctx, command, resolvedCwd.target);
2801
+ const isFile = await stat2(resolved2.target).then(
2802
+ (s) => s.isFile(),
2803
+ () => false
2804
+ );
2805
+ if (!isFile) {
2806
+ return `Refused: ${filePath} is not a file. Write the script first, then review the path you wrote.`;
2807
+ }
2808
+ const reviewedDigest = await fileDigest(resolved2.target).catch(
2809
+ () => null
2810
+ );
2811
+ if (reviewedDigest === null) {
2812
+ return `Refused: ${filePath} could not be read. Write the script first, then review it again.`;
2813
+ }
2814
+ const answer = await useWizard.getState().requestUserInput({
2815
+ prompt: "Run this command?",
2816
+ promptType: "commandApproval",
2817
+ options: [],
2818
+ messages: [
2819
+ `We have created your ingestion script. Please review it at ${displayFilePath} before approving.`
2820
+ ],
2821
+ command: {
2822
+ command,
2823
+ cwd: displayCwd,
2824
+ explanation: ingestionSummary
2825
+ }
2826
+ });
2827
+ if (answer !== "approve") {
2828
+ revokeCommandApprovals(ctx, command, resolvedCwd.target);
2829
+ return "The user declined to run this ingestion script. Do not run it.";
2830
+ }
2831
+ const approvedDigest = await fileDigest(resolved2.target).catch(
2832
+ () => null
2833
+ );
2834
+ if (approvedDigest !== reviewedDigest) {
2835
+ return "The ingestion script changed while it was being reviewed. Call reviewScript again before running it.";
2836
+ }
2837
+ ctx.reviewed.push(resolved2.target);
2838
+ grantReviewedCommandApproval(ctx, {
2839
+ command,
2840
+ cwd: resolvedCwd.target,
2841
+ filePath: resolved2.target,
2842
+ digest: reviewedDigest
2843
+ });
2844
+ return "The user reviewed the script and approved this exact command. Run it now with the same cwd.";
2845
+ });
2846
+ }
2847
+ });
2848
+ }
2849
+
2668
2850
  // src/lib/tools/utils/runShell.ts
2669
2851
  import { spawn as spawn2 } from "node:child_process";
2670
2852
 
@@ -2763,7 +2945,7 @@ function storeApproval(root) {
2763
2945
  return async (req) => {
2764
2946
  const store = useWizard.getState();
2765
2947
  if (store.isCommandApproved(req.command, req.cwd)) return "approve";
2766
- const rel = relative4(root, req.cwd);
2948
+ const rel = relative5(root, req.cwd);
2767
2949
  const answer = await store.requestUserInput({
2768
2950
  prompt: "Run this command?",
2769
2951
  promptType: "commandApproval",
@@ -2778,6 +2960,7 @@ function storeApproval(root) {
2778
2960
  return "approve";
2779
2961
  };
2780
2962
  }
2963
+ var SUCCESS_EXIT_CODE = 0;
2781
2964
  var FILE_IO_COMMANDS = /* @__PURE__ */ new Set([
2782
2965
  "ls",
2783
2966
  "find",
@@ -2916,9 +3099,9 @@ function fastPathSafety(command) {
2916
3099
  return void 0;
2917
3100
  }
2918
3101
  var CLASSIFIER_MODEL = "claude-haiku-4-5";
2919
- var commandSafetySchema = z15.object({
2920
- safe: z15.boolean(),
2921
- reason: z15.string().describe("One short sentence explaining the verdict.")
3102
+ var commandSafetySchema = z16.object({
3103
+ safe: z16.boolean(),
3104
+ reason: z16.string().describe("One short sentence explaining the verdict.")
2922
3105
  });
2923
3106
  function defaultCreateModel() {
2924
3107
  const token = getAuthToken();
@@ -2978,12 +3161,15 @@ async function classifyCommandSafety(createModel, command, cwd, explanation, app
2978
3161
  return false;
2979
3162
  }
2980
3163
  }
2981
- async function runAndRecord(ctx, command, cwd) {
2982
- useWizard.getState().pushNotice({ messages: [`Running: ${command}`] });
2983
- const env = await ctx.shell.env().catch((err) => {
3164
+ async function resolveShellEnv(ctx, command) {
3165
+ return ctx.shell.env().catch((err) => {
2984
3166
  logger.warn({ err, command }, "runShell: could not resolve command env");
2985
3167
  return {};
2986
3168
  });
3169
+ }
3170
+ async function runAndRecord(ctx, command, cwd, resolvedEnv) {
3171
+ useWizard.getState().pushNotice({ messages: [`Running: ${command}`] });
3172
+ const env = resolvedEnv ?? await resolveShellEnv(ctx, command);
2987
3173
  const run2 = await (ctx.shell.run ?? runShell)(command, {
2988
3174
  cwd,
2989
3175
  env,
@@ -3014,6 +3200,19 @@ async function runAndRecord(ctx, command, cwd) {
3014
3200
  output: run2.output
3015
3201
  };
3016
3202
  }
3203
+ async function runReviewedCommand(ctx, command, cwd) {
3204
+ const approval = getReviewedCommandApproval(ctx, command, cwd);
3205
+ if (!approval) return void 0;
3206
+ const env = await resolveShellEnv(ctx, command);
3207
+ if (!await reviewedCommandApprovalIsCurrent(approval)) {
3208
+ return `Refused: ${relative5(ctx.root, approval.filePath)} changed after review. Call reviewScript again before running it.`;
3209
+ }
3210
+ const result = await runAndRecord(ctx, command, cwd, env);
3211
+ if (result.exitCode === SUCCESS_EXIT_CODE && !result.timedOut) {
3212
+ clearReviewedCommandApproval(ctx);
3213
+ }
3214
+ return result;
3215
+ }
3017
3216
  async function approveAndRun(ctx, command, cwd, explanation) {
3018
3217
  const decision = await ctx.shell.approve({ command, cwd, explanation });
3019
3218
  if (decision === "reject") {
@@ -3024,16 +3223,16 @@ async function approveAndRun(ctx, command, cwd, explanation) {
3024
3223
  return runAndRecord(ctx, command, cwd);
3025
3224
  }
3026
3225
  function runShellTool(ctx, createModel = defaultCreateModel) {
3027
- return tool8({
3226
+ return tool9({
3028
3227
  description: "Run a shell command in the project. Use this for anything the project needs done in its own ecosystem: installing dependencies, running a script you wrote, running the project's lint/typecheck/test commands. Do not use this to find or read files \u2014 use listFiles, searchFiles, and readFile instead of shell file-listing, reading, or search commands (ls/find/tree/cat/head/tail/grep/rg and similar). This tool refuses all of those outright: the dedicated tools enforce the project-root boundary and secret redaction that a raw shell read would bypass, and they won't count against this tool's command budget. The user approves any command that could change the project before it runs, so write a clear `explanation`. A command judged read-only (inspection, or running tests/typecheck/lint without an autofix flag, in any language) runs immediately without approval. If the user rejects a command, do not retry it \u2014 propose a different approach.",
3029
- inputSchema: z15.object({
3030
- command: z15.string().describe(
3228
+ inputSchema: z16.object({
3229
+ command: z16.string().describe(
3031
3230
  "The command to run, exactly as it would be typed in a shell. Pipes, && and redirects are allowed."
3032
3231
  ),
3033
- cwd: z15.string().optional().describe(
3232
+ cwd: z16.string().optional().describe(
3034
3233
  "Directory to run in, relative to the project root. Defaults to the project root."
3035
3234
  ),
3036
- explanation: z15.string().describe(
3235
+ explanation: z16.string().describe(
3037
3236
  "One short line telling the user what this command does and why, including any side effect (e.g. writes records to Algolia). This is what they approve against."
3038
3237
  )
3039
3238
  }),
@@ -3042,16 +3241,22 @@ function runShellTool(ctx, createModel = defaultCreateModel) {
3042
3241
  return `Refused: command limit (${ctx.limits.shell}) reached. Stop running commands and report what you have.`;
3043
3242
  }
3044
3243
  const resolved2 = resolveInRoot(ctx, cwd ?? ".");
3045
- if (!resolved2.ok) return resolved2.error;
3244
+ if (resolved2.ok === false) return resolved2.error;
3046
3245
  if (isFileIOCommand(command)) {
3047
3246
  return "Refused: use listFiles or searchFiles to find files, and readFile to read one, instead of a shell file-listing, reading, or search command (ls/find/fd/tree/dir/locate/cat/head/tail/less/more/tac/nl/grep/egrep/fgrep/rg/ack/ag/xxd/hexdump/od/strings).";
3048
3247
  }
3049
3248
  logger.info({ command, cwd: resolved2.target }, "called runShell tool");
3249
+ const reviewed = await serializePrompt(
3250
+ () => runReviewedCommand(ctx, command, resolved2.target)
3251
+ );
3252
+ if (reviewed !== void 0) return reviewed;
3050
3253
  const fast = fastPathSafety(command);
3051
3254
  let isSafe = fast;
3255
+ let usedStoredApproval = false;
3052
3256
  if (isSafe === void 0) {
3053
3257
  const store = useWizard.getState();
3054
- isSafe = store.isCommandApproved(command, resolved2.target);
3258
+ usedStoredApproval = store.isCommandApproved(command, resolved2.target);
3259
+ isSafe = usedStoredApproval;
3055
3260
  if (!isSafe) {
3056
3261
  isSafe = await classifyCommandSafety(
3057
3262
  createModel,
@@ -3062,54 +3267,18 @@ function runShellTool(ctx, createModel = defaultCreateModel) {
3062
3267
  );
3063
3268
  }
3064
3269
  }
3065
- if (isSafe) {
3066
- return serializePrompt(
3067
- () => runAndRecord(ctx, command, resolved2.target)
3068
- );
3069
- }
3070
- return serializePrompt(
3071
- () => approveAndRun(ctx, command, resolved2.target, explanation)
3072
- );
3073
- }
3074
- });
3075
- }
3076
-
3077
- // src/lib/tools/reviewScript.ts
3078
- import { tool as tool9 } from "ai";
3079
- import z16 from "zod";
3080
- import { stat as stat2 } from "node:fs/promises";
3081
- import { relative as relative5 } from "node:path";
3082
- function reviewScriptTool(ctx) {
3083
- return tool9({
3084
- description: "Call this as soon as the ingestion script is finished and before you run it, so the user can review it.It shows the file path and returns once they have confirmed reviewing it.",
3085
- inputSchema: z16.object({
3086
- filePath: z16.string().describe(
3087
- "Path to the script to review, relative to the project root."
3088
- )
3089
- }),
3090
- execute: async ({ filePath }) => {
3091
- logger.info({ filePath }, "called reviewScript tool");
3092
- const resolved2 = resolveInRoot(ctx, filePath);
3093
- if (resolved2.ok === false) return resolved2.error;
3094
- const isFile = await stat2(resolved2.target).then(
3095
- (s) => s.isFile(),
3096
- () => false
3097
- );
3098
- if (!isFile) {
3099
- return `Refused: ${filePath} is not a file. Write the script first, then review the path you wrote.`;
3100
- }
3101
3270
  return serializePrompt(async () => {
3102
- await useWizard.getState().requestUserInput({
3103
- prompt: "",
3104
- promptType: "enterToContinue",
3105
- options: [],
3106
- messages: [
3107
- `Please review ${relative5(ctx.root, resolved2.target)} before it runs:`,
3108
- resolved2.target
3109
- ]
3110
- });
3111
- ctx.reviewed.push(resolved2.target);
3112
- return "The user has reviewed the script. You may run it now.";
3271
+ const lateReview = await runReviewedCommand(
3272
+ ctx,
3273
+ command,
3274
+ resolved2.target
3275
+ );
3276
+ if (lateReview !== void 0) return lateReview;
3277
+ const storedApprovalIsCurrent = !usedStoredApproval || useWizard.getState().isCommandApproved(command, resolved2.target);
3278
+ if (isSafe && storedApprovalIsCurrent) {
3279
+ return runAndRecord(ctx, command, resolved2.target);
3280
+ }
3281
+ return approveAndRun(ctx, command, resolved2.target, explanation);
3113
3282
  });
3114
3283
  }
3115
3284
  });
@@ -3604,7 +3773,7 @@ async function runAnalysis(mode, extraInstructions = []) {
3604
3773
  // package.json
3605
3774
  var package_default = {
3606
3775
  name: "@algolia/wizard",
3607
- version: "0.50.0",
3776
+ version: "0.52.0-rc.136.364",
3608
3777
  description: "Magically implement Algolia functionality in your codebase",
3609
3778
  type: "module",
3610
3779
  engines: {
@@ -3662,7 +3831,6 @@ var package_default = {
3662
3831
  ink: "^7.0.5",
3663
3832
  "ink-picture": "^2.1.0",
3664
3833
  "ink-spinner": "^5.0.0",
3665
- "ink-text-input": "^6.0.0",
3666
3834
  ioredis: "^5.11.1",
3667
3835
  nanoid: "^5.1.15",
3668
3836
  pino: "^10.3.1",
@@ -4307,8 +4475,8 @@ function ingestionInstructions(input) {
4307
4475
  ...algoliaClientDoc(input),
4308
4476
  "Install the Algolia client with the project's own package manager via runShell, declaring it in whatever manifest the project uses (e.g. package.json, requirements.txt, Gemfile, go.mod, composer.json) so the dependency is not just installed ad hoc.",
4309
4477
  `If the script loads its env vars from a file (e.g. via dotenv or an equivalent for its language) rather than the process environment directly, decide that up front and call writeCredentials on that file before you finish the script \u2014 do not wait to discover the need for it by having a writeFile call refused.`,
4310
- "When the script is finished, call reviewScript with its path and wait: running it writes records to a live index, so the developer reads it first. Do not run it before that call returns.",
4311
- 'Then run the script yourself via runShell, and report the command you ran as "ingestCommand" so the developer can re-run it. Its explanation must say that running it writes records to Algolia.',
4478
+ `When the script is finished, decide the exact command and cwd you will use to run it, then call reviewScript with that filePath, command, cwd, the exact selected entityName, and usesGeneratedRecords set to ${input.ingestionSource === "generated"}. Wait for the developer to review it because running it writes records to a live index. Do not run it before that call returns.`,
4479
+ 'Then, without changing directories, run the script yourself via runShell using the exact same command and cwd. Report the command you ran as "ingestCommand" so the developer can re-run it. Its explanation must say that running it writes records to Algolia.',
4312
4480
  "The summary should be extremely concise.",
4313
4481
  ...sourceSpecificInstructions(input)
4314
4482
  ] : []
@@ -4688,19 +4856,33 @@ ${detail}` : ""}`
4688
4856
  product_area: "AI Wizard"
4689
4857
  });
4690
4858
  }
4691
- const commandMessages = ingestCommand ? [`Ingestion command: ${ingestCommand}`] : [];
4692
- await ctx.requestUserInput({
4693
- prompt: "",
4694
- promptType: "enterToContinue",
4695
- options: [],
4696
- // One message per line: Notices.tsx counts a message as one wrapped
4697
- // line, so an embedded newline overflows the panel's height accounting.
4698
- messages: [
4699
- ingestOutcomeMessage,
4700
- ...ingestFailureDetail?.split("\n").filter((l) => l.trim()) ?? [],
4701
- ...commandMessages
4702
- ]
4703
- });
4859
+ if (ingestScriptRan) {
4860
+ await ctx.requestUserInput({
4861
+ prompt: "Continue",
4862
+ promptType: "notice",
4863
+ options: [],
4864
+ messages: [
4865
+ ingestOutcomeMessage,
4866
+ "View your ingested records in the Algolia dashboard:",
4867
+ "https://dashboard.algolia.com/explorer/browse",
4868
+ "When you're ready to continue, we'll move on to search implementation."
4869
+ ]
4870
+ });
4871
+ } else {
4872
+ const commandMessages = ingestCommand ? [`Ingestion command: ${ingestCommand}`] : [];
4873
+ await ctx.requestUserInput({
4874
+ prompt: "",
4875
+ promptType: "enterToContinue",
4876
+ options: [],
4877
+ // One message per line: Notices.tsx counts a message as one wrapped
4878
+ // line, so an embedded newline overflows the panel's height accounting.
4879
+ messages: [
4880
+ ingestOutcomeMessage,
4881
+ ...ingestFailureDetail?.split("\n").filter((l) => l.trim()) ?? [],
4882
+ ...commandMessages
4883
+ ]
4884
+ });
4885
+ }
4704
4886
  }
4705
4887
  let searchConfigFile;
4706
4888
  if (useCases.includes("search")) {
@@ -5058,8 +5240,8 @@ function getWorkflow(id) {
5058
5240
  // src/ui/Welcome.tsx
5059
5241
  import { dirname as dirname8, join as join11 } from "node:path";
5060
5242
  import { fileURLToPath as fileURLToPath2 } from "node:url";
5061
- import { useState as useState8 } from "react";
5062
- import { Box as Box11, Spacer, Text as Text11, useInput as useInput4, useWindowSize as useWindowSize5 } from "ink";
5243
+ import { useState as useState9 } from "react";
5244
+ import { Box as Box11, Spacer, Text as Text12, useInput as useInput5, useWindowSize as useWindowSize5 } from "ink";
5063
5245
 
5064
5246
  // src/ui/copy/welcome.ts
5065
5247
  var sidebarItems = [
@@ -5087,7 +5269,7 @@ var sidebarItems = [
5087
5269
 
5088
5270
  // src/ui/Welcome.tsx
5089
5271
  import Image, { TerminalInfoContext, defaultTerminalInfo } from "ink-picture";
5090
- import { jsx as jsx9, jsxs as jsxs10 } from "react/jsx-runtime";
5272
+ import { jsx as jsx10, jsxs as jsxs11 } from "react/jsx-runtime";
5091
5273
  var IMAGE_PATH = join11(dirname8(fileURLToPath2(import.meta.url)), "algolia.png");
5092
5274
  var TERMINAL_INFO = {
5093
5275
  ...defaultTerminalInfo,
@@ -5098,14 +5280,14 @@ function SidebarItem({
5098
5280
  title,
5099
5281
  description
5100
5282
  }) {
5101
- return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", children: [
5102
- /* @__PURE__ */ jsxs10(Box11, { gap: 1, children: [
5103
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.success, children: "\u2192" }),
5104
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.strong, bold: true, children: title })
5283
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
5284
+ /* @__PURE__ */ jsxs11(Box11, { gap: 1, children: [
5285
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.success, children: "\u2192" }),
5286
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.strong, bold: true, children: title })
5105
5287
  ] }),
5106
- /* @__PURE__ */ jsxs10(Box11, { flexDirection: "row", gap: 2, children: [
5107
- /* @__PURE__ */ jsx9(Spacer, {}),
5108
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.muted, children: description })
5288
+ /* @__PURE__ */ jsxs11(Box11, { flexDirection: "row", gap: 2, children: [
5289
+ /* @__PURE__ */ jsx10(Spacer, {}),
5290
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: description })
5109
5291
  ] })
5110
5292
  ] });
5111
5293
  }
@@ -5117,8 +5299,8 @@ function Welcome() {
5117
5299
  { label: "start wizard", run: confirmStart },
5118
5300
  { label: "learn more", run: openLearnMore }
5119
5301
  ];
5120
- const [index, setIndex] = useState8(0);
5121
- useInput4((input, key) => {
5302
+ const [index, setIndex] = useState9(0);
5303
+ useInput5((input, key) => {
5122
5304
  if (key.upArrow || input === "k") {
5123
5305
  setIndex((i) => (i - 1 + actions.length) % actions.length);
5124
5306
  } else if (key.downArrow || input === "j") {
@@ -5141,16 +5323,16 @@ function Welcome() {
5141
5323
  if (rows < 30) {
5142
5324
  layout = scales["small"];
5143
5325
  }
5144
- return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "row", justifyContent: "space-between", width: "100%", children: [
5145
- /* @__PURE__ */ jsx9(
5326
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "row", justifyContent: "space-between", width: "100%", children: [
5327
+ /* @__PURE__ */ jsx10(
5146
5328
  Box11,
5147
5329
  {
5148
5330
  paddingY: layout.main.padding.y,
5149
5331
  paddingX: layout.main.padding.x,
5150
5332
  flexDirection: "column",
5151
5333
  justifyContent: "center",
5152
- children: /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", gap: 2, children: [
5153
- /* @__PURE__ */ jsx9(TerminalInfoContext.Provider, { value: TERMINAL_INFO, children: /* @__PURE__ */ jsx9(
5334
+ children: /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", gap: 2, children: [
5335
+ /* @__PURE__ */ jsx10(TerminalInfoContext.Provider, { value: TERMINAL_INFO, children: /* @__PURE__ */ jsx10(
5154
5336
  Image,
5155
5337
  {
5156
5338
  src: IMAGE_PATH,
@@ -5161,8 +5343,8 @@ function Welcome() {
5161
5343
  protocol: "halfBlock"
5162
5344
  }
5163
5345
  ) }),
5164
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.muted, children: "\u2726 From zero \u2192 working search in ~10 minutes" }),
5165
- /* @__PURE__ */ jsx9(Box11, { flexDirection: "column", children: actions.map((action, i) => /* @__PURE__ */ jsx9(
5346
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "\u2726 From zero \u2192 working search in ~10 minutes" }),
5347
+ /* @__PURE__ */ jsx10(Box11, { flexDirection: "column", children: actions.map((action, i) => /* @__PURE__ */ jsx10(
5166
5348
  SelectRow,
5167
5349
  {
5168
5350
  highlighted: i === index,
@@ -5171,20 +5353,20 @@ function Welcome() {
5171
5353
  },
5172
5354
  action.label
5173
5355
  )) }),
5174
- /* @__PURE__ */ jsxs10(Box11, { gap: 2, children: [
5175
- /* @__PURE__ */ jsxs10(Text11, { children: [
5176
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.primary, children: "[\u2191] [\u2193]" }),
5177
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.dim, children: " move" })
5356
+ /* @__PURE__ */ jsxs11(Box11, { gap: 2, children: [
5357
+ /* @__PURE__ */ jsxs11(Text12, { children: [
5358
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.primary, children: "[\u2191] [\u2193]" }),
5359
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.dim, children: " move" })
5178
5360
  ] }),
5179
- /* @__PURE__ */ jsxs10(Text11, { children: [
5180
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.primary, children: "[enter]" }),
5181
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.dim, children: " confirm" })
5361
+ /* @__PURE__ */ jsxs11(Text12, { children: [
5362
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.primary, children: "[enter]" }),
5363
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.dim, children: " confirm" })
5182
5364
  ] })
5183
5365
  ] })
5184
5366
  ] })
5185
5367
  }
5186
5368
  ),
5187
- /* @__PURE__ */ jsxs10(
5369
+ /* @__PURE__ */ jsxs11(
5188
5370
  Box11,
5189
5371
  {
5190
5372
  backgroundColor: COLORS.bg.sidebar,
@@ -5195,8 +5377,8 @@ function Welcome() {
5195
5377
  flexDirection: "column",
5196
5378
  justifyContent: "center",
5197
5379
  children: [
5198
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.muted, children: "WHAT THIS WIZARD WILL DO" }),
5199
- sidebarItems.map((i, idx) => /* @__PURE__ */ jsx9(SidebarItem, { title: i.title, description: i.description }, idx))
5380
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "WHAT THIS WIZARD WILL DO" }),
5381
+ sidebarItems.map((i, idx) => /* @__PURE__ */ jsx10(SidebarItem, { title: i.title, description: i.description }, idx))
5200
5382
  ]
5201
5383
  }
5202
5384
  )
@@ -5205,7 +5387,7 @@ function Welcome() {
5205
5387
 
5206
5388
  // src/ui/LearnMore.tsx
5207
5389
  import { Fragment } from "react";
5208
- import { Box as Box12, Text as Text12, useInput as useInput5, useWindowSize as useWindowSize6 } from "ink";
5390
+ import { Box as Box12, Text as Text13, useInput as useInput6, useWindowSize as useWindowSize6 } from "ink";
5209
5391
 
5210
5392
  // src/ui/copy/learn-more.ts
5211
5393
  var accessIntro = "Everything runs locally on your machine. Nothing is written or sent without an explicit yes from you.";
@@ -5247,7 +5429,7 @@ var policyLinks = [
5247
5429
  ];
5248
5430
 
5249
5431
  // src/ui/LearnMore.tsx
5250
- import { jsx as jsx10, jsxs as jsxs11 } from "react/jsx-runtime";
5432
+ import { jsx as jsx11, jsxs as jsxs12 } from "react/jsx-runtime";
5251
5433
  var TAG_COLORS = {
5252
5434
  READ: COLORS.success,
5253
5435
  WRITE: COLORS.badge,
@@ -5264,12 +5446,12 @@ function NeverLine({
5264
5446
  }) {
5265
5447
  const used = segments.reduce((n, s) => n + s.text.length, 0);
5266
5448
  const rightPad = Math.max(0, width - 2 - NEVER_BOX_PAD_X - used);
5267
- return /* @__PURE__ */ jsxs11(Text12, { color: COLORS.primary, children: [
5268
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.danger, children: "\u2502" }),
5449
+ return /* @__PURE__ */ jsxs12(Text13, { color: COLORS.primary, children: [
5450
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.danger, children: "\u2502" }),
5269
5451
  " ".repeat(NEVER_BOX_PAD_X),
5270
- segments.map((s, i) => /* @__PURE__ */ jsx10(Text12, { color: s.color, bold: s.bold, children: s.text }, i)),
5452
+ segments.map((s, i) => /* @__PURE__ */ jsx11(Text13, { color: s.color, bold: s.bold, children: s.text }, i)),
5271
5453
  " ".repeat(rightPad),
5272
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.danger, children: "\u2502" })
5454
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.danger, children: "\u2502" })
5273
5455
  ] });
5274
5456
  }
5275
5457
  function LearnMore() {
@@ -5277,11 +5459,11 @@ function LearnMore() {
5277
5459
  const backToHome = useWizard((s) => s.backToHome);
5278
5460
  const { columns } = useWindowSize6();
5279
5461
  const dividerWidth = Math.max(0, columns - PADDING_X * 2);
5280
- useInput5((_input, key) => {
5462
+ useInput6((_input, key) => {
5281
5463
  if (key.escape) backToHome();
5282
5464
  else if (key.return) confirmStart();
5283
5465
  });
5284
- return /* @__PURE__ */ jsxs11(
5466
+ return /* @__PURE__ */ jsxs12(
5285
5467
  Box12,
5286
5468
  {
5287
5469
  flexDirection: "column",
@@ -5290,31 +5472,31 @@ function LearnMore() {
5290
5472
  width: "100%",
5291
5473
  gap: 1,
5292
5474
  children: [
5293
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.strong, bold: true, children: "What algolia wizard accesses" }),
5294
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: accessIntro }),
5295
- /* @__PURE__ */ jsx10(Box12, { flexDirection: "column", children: accessItems.map((item) => /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", marginTop: 1, children: [
5296
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.border, children: "\u2500".repeat(dividerWidth) }),
5297
- /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, marginTop: 1, children: [
5298
- /* @__PURE__ */ jsx10(Box12, { width: TAG_COLUMN_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx10(Text12, { color: TAG_COLORS[item.tag], bold: true, children: `[${item.tag}]` }) }),
5299
- /* @__PURE__ */ jsx10(Box12, { flexDirection: "column", children: /* @__PURE__ */ jsxs11(Text12, { color: COLORS.primary, children: [
5300
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.strong, bold: true, children: item.title }),
5301
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: ` \u2014 ${item.description}` })
5475
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.strong, bold: true, children: "What algolia wizard accesses" }),
5476
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: accessIntro }),
5477
+ /* @__PURE__ */ jsx11(Box12, { flexDirection: "column", children: accessItems.map((item) => /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", marginTop: 1, children: [
5478
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.border, children: "\u2500".repeat(dividerWidth) }),
5479
+ /* @__PURE__ */ jsxs12(Box12, { flexDirection: "row", gap: 1, marginTop: 1, children: [
5480
+ /* @__PURE__ */ jsx11(Box12, { width: TAG_COLUMN_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text13, { color: TAG_COLORS[item.tag], bold: true, children: `[${item.tag}]` }) }),
5481
+ /* @__PURE__ */ jsx11(Box12, { flexDirection: "column", children: /* @__PURE__ */ jsxs12(Text13, { color: COLORS.primary, children: [
5482
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.strong, bold: true, children: item.title }),
5483
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: ` \u2014 ${item.description}` })
5302
5484
  ] }) })
5303
5485
  ] })
5304
5486
  ] }, item.tag)) }),
5305
- /* @__PURE__ */ jsxs11(Box12, { marginTop: 1, flexDirection: "column", children: [
5306
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.danger, children: `\u256D${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256E` }),
5307
- /* @__PURE__ */ jsx10(NeverLine, { width: dividerWidth }),
5308
- /* @__PURE__ */ jsx10(
5487
+ /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
5488
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.danger, children: `\u256D${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256E` }),
5489
+ /* @__PURE__ */ jsx11(NeverLine, { width: dividerWidth }),
5490
+ /* @__PURE__ */ jsx11(
5309
5491
  NeverLine,
5310
5492
  {
5311
5493
  width: dividerWidth,
5312
5494
  segments: [{ text: "I NEVER", color: COLORS.danger, bold: true }]
5313
5495
  }
5314
5496
  ),
5315
- neverItems.map((item) => /* @__PURE__ */ jsxs11(Fragment, { children: [
5316
- /* @__PURE__ */ jsx10(NeverLine, { width: dividerWidth }),
5317
- /* @__PURE__ */ jsx10(
5497
+ neverItems.map((item) => /* @__PURE__ */ jsxs12(Fragment, { children: [
5498
+ /* @__PURE__ */ jsx11(NeverLine, { width: dividerWidth }),
5499
+ /* @__PURE__ */ jsx11(
5318
5500
  NeverLine,
5319
5501
  {
5320
5502
  width: dividerWidth,
@@ -5326,24 +5508,24 @@ function LearnMore() {
5326
5508
  }
5327
5509
  )
5328
5510
  ] }, item)),
5329
- /* @__PURE__ */ jsx10(NeverLine, { width: dividerWidth }),
5330
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.danger, children: `\u2570${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256F` })
5511
+ /* @__PURE__ */ jsx11(NeverLine, { width: dividerWidth }),
5512
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.danger, children: `\u2570${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256F` })
5331
5513
  ] }),
5332
- /* @__PURE__ */ jsx10(Box12, { marginTop: 1, flexDirection: "column", children: policyLinks.map((link) => /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, children: [
5333
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.strong, bold: true, children: `${link.label}:` }),
5334
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.accent, children: link.url })
5514
+ /* @__PURE__ */ jsx11(Box12, { marginTop: 1, flexDirection: "column", children: policyLinks.map((link) => /* @__PURE__ */ jsxs12(Box12, { flexDirection: "row", gap: 1, children: [
5515
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.strong, bold: true, children: `${link.label}:` }),
5516
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.accent, children: link.url })
5335
5517
  ] }, link.label)) }),
5336
- /* @__PURE__ */ jsxs11(Box12, { marginTop: 1, flexDirection: "row", gap: 3, children: [
5337
- /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, children: [
5338
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "[" }),
5339
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.primary, children: "esc" }),
5340
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "] back" })
5518
+ /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "row", gap: 3, children: [
5519
+ /* @__PURE__ */ jsxs12(Box12, { flexDirection: "row", gap: 1, children: [
5520
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: "[" }),
5521
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.primary, children: "esc" }),
5522
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: "] back" })
5341
5523
  ] }),
5342
- /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, children: [
5343
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "[" }),
5344
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.primary, children: "enter" }),
5345
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "]" }),
5346
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.success, bold: true, children: "start wizard" })
5524
+ /* @__PURE__ */ jsxs12(Box12, { flexDirection: "row", gap: 1, children: [
5525
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: "[" }),
5526
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.primary, children: "enter" }),
5527
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: "]" }),
5528
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.success, bold: true, children: "start wizard" })
5347
5529
  ] })
5348
5530
  ] })
5349
5531
  ]
@@ -5352,17 +5534,17 @@ function LearnMore() {
5352
5534
  }
5353
5535
 
5354
5536
  // src/ui/Sidebar.tsx
5355
- import { Box as Box15, Text as Text15 } from "ink";
5537
+ import { Box as Box15, Text as Text16 } from "ink";
5356
5538
 
5357
5539
  // src/ui/Steps.tsx
5358
- import { Box as Box13, Text as Text13 } from "ink";
5540
+ import { Box as Box13, Text as Text14 } from "ink";
5359
5541
  import Spinner2 from "ink-spinner";
5360
- import { jsx as jsx11, jsxs as jsxs12 } from "react/jsx-runtime";
5542
+ import { jsx as jsx12, jsxs as jsxs13 } from "react/jsx-runtime";
5361
5543
  function Steps() {
5362
5544
  const { steps } = useWizard();
5363
5545
  const visibleSteps = steps.filter(isStepVisible);
5364
- return /* @__PURE__ */ jsx11(Box13, { flexDirection: "column", gap: 1, children: visibleSteps.map((s) => /* @__PURE__ */ jsx11(Box13, { flexDirection: "column", children: /* @__PURE__ */ jsxs12(Text13, { color: COLORS.status[s.status], children: [
5365
- s.status === "running" ? /* @__PURE__ */ jsx11(Spinner2, { type: "dots" }) : MARKER[s.status],
5546
+ return /* @__PURE__ */ jsx12(Box13, { flexDirection: "column", gap: 1, children: visibleSteps.map((s) => /* @__PURE__ */ jsx12(Box13, { flexDirection: "column", children: /* @__PURE__ */ jsxs13(Text14, { color: COLORS.status[s.status], children: [
5547
+ s.status === "running" ? /* @__PURE__ */ jsx12(Spinner2, { type: "dots" }) : MARKER[s.status],
5366
5548
  " ",
5367
5549
  s.title
5368
5550
  ] }) }, s.id)) });
@@ -5371,27 +5553,27 @@ function CurrentStep() {
5371
5553
  const { steps } = useWizard();
5372
5554
  const currentStep = steps.filter(isStepVisible).find((s) => s.status === "running");
5373
5555
  if (!currentStep) return null;
5374
- return /* @__PURE__ */ jsxs12(Text13, { color: COLORS.status.running, children: [
5375
- /* @__PURE__ */ jsx11(Spinner2, { type: "dots" }),
5556
+ return /* @__PURE__ */ jsxs13(Text14, { color: COLORS.status.running, children: [
5557
+ /* @__PURE__ */ jsx12(Spinner2, { type: "dots" }),
5376
5558
  " ",
5377
5559
  ` ${currentStep.title}`
5378
5560
  ] });
5379
5561
  }
5380
5562
 
5381
5563
  // src/ui/Progress.tsx
5382
- import { Box as Box14, Text as Text14 } from "ink";
5383
- import { jsx as jsx12, jsxs as jsxs13 } from "react/jsx-runtime";
5564
+ import { Box as Box14, Text as Text15 } from "ink";
5565
+ import { jsx as jsx13, jsxs as jsxs14 } from "react/jsx-runtime";
5384
5566
  function Progress() {
5385
5567
  const { steps, currentStepIndex } = useWizard();
5386
5568
  const visibleSteps = steps.filter(isStepVisible);
5387
5569
  if (visibleSteps.length === 0) return null;
5388
5570
  const visibleCountThroughCurrent = steps.slice(0, currentStepIndex + 1).filter(isStepVisible).length;
5389
5571
  const activeStepNumber = Math.max(1, visibleCountThroughCurrent);
5390
- return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "row", gap: 1, children: [
5391
- /* @__PURE__ */ jsx12(Text14, { color: COLORS.muted, children: "STEP" }),
5392
- /* @__PURE__ */ jsx12(Text14, { color: COLORS.strong, bold: true, children: activeStepNumber }),
5393
- /* @__PURE__ */ jsx12(Text14, { color: COLORS.strong, bold: true, children: "/" }),
5394
- /* @__PURE__ */ jsx12(Text14, { color: COLORS.strong, bold: true, children: visibleSteps.length })
5572
+ return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "row", gap: 1, children: [
5573
+ /* @__PURE__ */ jsx13(Text15, { color: COLORS.muted, children: "STEP" }),
5574
+ /* @__PURE__ */ jsx13(Text15, { color: COLORS.strong, bold: true, children: activeStepNumber }),
5575
+ /* @__PURE__ */ jsx13(Text15, { color: COLORS.strong, bold: true, children: "/" }),
5576
+ /* @__PURE__ */ jsx13(Text15, { color: COLORS.strong, bold: true, children: visibleSteps.length })
5395
5577
  ] });
5396
5578
  }
5397
5579
 
@@ -5402,9 +5584,9 @@ var sidebarCommands = [
5402
5584
  ];
5403
5585
 
5404
5586
  // src/ui/Sidebar.tsx
5405
- import { jsx as jsx13, jsxs as jsxs14 } from "react/jsx-runtime";
5587
+ import { jsx as jsx14, jsxs as jsxs15 } from "react/jsx-runtime";
5406
5588
  function Sidebar() {
5407
- return /* @__PURE__ */ jsxs14(
5589
+ return /* @__PURE__ */ jsxs15(
5408
5590
  Box15,
5409
5591
  {
5410
5592
  backgroundColor: "#14171E",
@@ -5414,16 +5596,16 @@ function Sidebar() {
5414
5596
  flexDirection: "column",
5415
5597
  justifyContent: "space-between",
5416
5598
  children: [
5417
- /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", gap: 1, children: [
5418
- /* @__PURE__ */ jsx13(Text15, { color: COLORS.muted, children: "PROGRESS" }),
5419
- /* @__PURE__ */ jsx13(Steps, {})
5599
+ /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", gap: 1, children: [
5600
+ /* @__PURE__ */ jsx14(Text16, { color: COLORS.muted, children: "PROGRESS" }),
5601
+ /* @__PURE__ */ jsx14(Steps, {})
5420
5602
  ] }),
5421
- /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", gap: 1, children: [
5422
- /* @__PURE__ */ jsx13(Progress, {}),
5423
- /* @__PURE__ */ jsx13(Box15, { flexDirection: "column", children: sidebarCommands.map((c) => {
5424
- return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "row", gap: 1, children: [
5425
- /* @__PURE__ */ jsx13(Text15, { color: COLORS.primary, children: `[${c.keyHint}]` }),
5426
- /* @__PURE__ */ jsx13(Text15, { color: COLORS.muted, children: c.description })
5603
+ /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", gap: 1, children: [
5604
+ /* @__PURE__ */ jsx14(Progress, {}),
5605
+ /* @__PURE__ */ jsx14(Box15, { flexDirection: "column", children: sidebarCommands.map((c) => {
5606
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "row", gap: 1, children: [
5607
+ /* @__PURE__ */ jsx14(Text16, { color: COLORS.primary, children: `[${c.keyHint}]` }),
5608
+ /* @__PURE__ */ jsx14(Text16, { color: COLORS.muted, children: c.description })
5427
5609
  ] }, c.keyHint);
5428
5610
  }) })
5429
5611
  ] })
@@ -5433,11 +5615,11 @@ function Sidebar() {
5433
5615
  }
5434
5616
 
5435
5617
  // src/ui/Ribbon.tsx
5436
- import { Box as Box16, Text as Text16 } from "ink";
5437
- import { jsx as jsx14, jsxs as jsxs15 } from "react/jsx-runtime";
5618
+ import { Box as Box16, Text as Text17 } from "ink";
5619
+ import { jsx as jsx15, jsxs as jsxs16 } from "react/jsx-runtime";
5438
5620
  function Ribbon() {
5439
5621
  const firstCommand = sidebarCommands[0];
5440
- return /* @__PURE__ */ jsxs15(
5622
+ return /* @__PURE__ */ jsxs16(
5441
5623
  Box16,
5442
5624
  {
5443
5625
  backgroundColor: "#14171E",
@@ -5446,11 +5628,11 @@ function Ribbon() {
5446
5628
  paddingX: 2,
5447
5629
  paddingY: 1,
5448
5630
  children: [
5449
- /* @__PURE__ */ jsx14(Progress, {}),
5450
- /* @__PURE__ */ jsx14(CurrentStep, {}),
5451
- /* @__PURE__ */ jsxs15(Box16, { flexDirection: "row", gap: 1, children: [
5452
- /* @__PURE__ */ jsx14(Text16, { color: COLORS.primary, children: `[${firstCommand.keyHint}]` }),
5453
- /* @__PURE__ */ jsx14(Text16, { color: COLORS.muted, children: firstCommand.description })
5631
+ /* @__PURE__ */ jsx15(Progress, {}),
5632
+ /* @__PURE__ */ jsx15(CurrentStep, {}),
5633
+ /* @__PURE__ */ jsxs16(Box16, { flexDirection: "row", gap: 1, children: [
5634
+ /* @__PURE__ */ jsx15(Text17, { color: COLORS.primary, children: `[${firstCommand.keyHint}]` }),
5635
+ /* @__PURE__ */ jsx15(Text17, { color: COLORS.muted, children: firstCommand.description })
5454
5636
  ] })
5455
5637
  ]
5456
5638
  }
@@ -5458,11 +5640,11 @@ function Ribbon() {
5458
5640
  }
5459
5641
 
5460
5642
  // src/ui/App.tsx
5461
- import { useState as useState10 } from "react";
5643
+ import { useState as useState11 } from "react";
5462
5644
 
5463
5645
  // src/ui/Logs.tsx
5464
- import { Box as Box17, Text as Text17, useInput as useInput6 } from "ink";
5465
- import { jsx as jsx15, jsxs as jsxs16 } from "react/jsx-runtime";
5646
+ import { Box as Box17, Text as Text18, useInput as useInput7 } from "ink";
5647
+ import { jsx as jsx16, jsxs as jsxs17 } from "react/jsx-runtime";
5466
5648
  var KIND_COLOR = {
5467
5649
  tool: COLORS.primary,
5468
5650
  prompt: COLORS.badge
@@ -5493,14 +5675,14 @@ function formatTimestamp(ms) {
5493
5675
  function Logs() {
5494
5676
  const logs = useWizard((s) => s.logs);
5495
5677
  const scroll = useScrollWindow({ itemCount: logs.length, followBottom: true });
5496
- useInput6((_input, key) => {
5678
+ useInput7((_input, key) => {
5497
5679
  if (key.upArrow) scroll.scrollBy(-1);
5498
5680
  else if (key.downArrow) scroll.scrollBy(1);
5499
5681
  });
5500
5682
  const visible = logs.slice(scroll.offset, scroll.offset + scroll.capacity);
5501
- return /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", paddingX: 4, paddingY: 2, flexGrow: 1, children: [
5502
- logs.length === 0 && /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, children: "No logs yet." }),
5503
- /* @__PURE__ */ jsx15(ScrollView, { scroll, children: visible.map((entry) => {
5683
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", paddingX: 4, paddingY: 2, flexGrow: 1, children: [
5684
+ logs.length === 0 && /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, children: "No logs yet." }),
5685
+ /* @__PURE__ */ jsx16(ScrollView, { scroll, children: visible.map((entry) => {
5504
5686
  const timestamp = `[${formatTimestamp(entry.startedAt)}]`;
5505
5687
  const durationText = entry.kind === "tool" && entry.durationMs !== void 0 ? `${entry.durationMs}ms` : "";
5506
5688
  const rawPreview = rawInputText(entry.input);
@@ -5510,25 +5692,25 @@ function Logs() {
5510
5692
  const name = truncate3(entry.name, budget);
5511
5693
  budget -= name.length;
5512
5694
  const preview = rawPreview ? truncate3(rawPreview, budget) : "";
5513
- return /* @__PURE__ */ jsxs16(Box17, { flexDirection: "row", gap: ROW_GAP, children: [
5514
- /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, children: timestamp }),
5515
- /* @__PURE__ */ jsx15(Text17, { color: logNameColor(entry), wrap: "truncate", children: name }),
5516
- preview && /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, wrap: "truncate", children: preview }),
5517
- durationText && /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, children: durationText })
5695
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "row", gap: ROW_GAP, children: [
5696
+ /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, children: timestamp }),
5697
+ /* @__PURE__ */ jsx16(Text18, { color: logNameColor(entry), wrap: "truncate", children: name }),
5698
+ preview && /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, wrap: "truncate", children: preview }),
5699
+ durationText && /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, children: durationText })
5518
5700
  ] }, entry.id);
5519
5701
  }) }),
5520
- /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, children: "\u2191/\u2193 scroll" })
5702
+ /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, children: "\u2191/\u2193 scroll" })
5521
5703
  ] });
5522
5704
  }
5523
5705
 
5524
5706
  // src/ui/Tips.tsx
5525
- import { useEffect as useEffect3, useRef as useRef4, useState as useState9 } from "react";
5526
- import { Box as Box19, Text as Text19 } from "ink";
5707
+ import { useEffect as useEffect3, useRef as useRef4, useState as useState10 } from "react";
5708
+ import { Box as Box19, Text as Text20 } from "ink";
5527
5709
  import terminalLink from "terminal-link";
5528
5710
 
5529
5711
  // src/ui/Code.tsx
5530
- import { Box as Box18, Text as Text18 } from "ink";
5531
- import { jsx as jsx16 } from "react/jsx-runtime";
5712
+ import { Box as Box18, Text as Text19 } from "ink";
5713
+ import { jsx as jsx17 } from "react/jsx-runtime";
5532
5714
  var TOKEN_RE = /("(?:\\.|[^"\\])*"|\btrue\b|\bfalse\b|\bnull\b|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|[{}[\]:,])/g;
5533
5715
  function highlightJson(json) {
5534
5716
  const parts = json.split(TOKEN_RE);
@@ -5537,22 +5719,22 @@ function highlightJson(json) {
5537
5719
  if (part[0] === '"') {
5538
5720
  const next = parts.slice(i + 1).find((p) => p.trim());
5539
5721
  const isKey = next?.trimStart().startsWith(":");
5540
- return /* @__PURE__ */ jsx16(Text18, { color: isKey ? "cyan" : "green", children: part }, i);
5722
+ return /* @__PURE__ */ jsx17(Text19, { color: isKey ? "cyan" : "green", children: part }, i);
5541
5723
  }
5542
5724
  if (part === "true" || part === "false" || part === "null") {
5543
- return /* @__PURE__ */ jsx16(Text18, { color: "magenta", children: part }, i);
5725
+ return /* @__PURE__ */ jsx17(Text19, { color: "magenta", children: part }, i);
5544
5726
  }
5545
5727
  if (/^-?\d/.test(part)) {
5546
- return /* @__PURE__ */ jsx16(Text18, { color: "yellow", children: part }, i);
5728
+ return /* @__PURE__ */ jsx17(Text19, { color: "yellow", children: part }, i);
5547
5729
  }
5548
5730
  if (/^[{}[\]:,]$/.test(part)) {
5549
- return /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, children: part }, i);
5731
+ return /* @__PURE__ */ jsx17(Text19, { color: COLORS.dim, children: part }, i);
5550
5732
  }
5551
- return /* @__PURE__ */ jsx16(Text18, { children: part }, i);
5733
+ return /* @__PURE__ */ jsx17(Text19, { children: part }, i);
5552
5734
  });
5553
5735
  }
5554
5736
  function Code({ children }) {
5555
- return /* @__PURE__ */ jsx16(Box18, { children: /* @__PURE__ */ jsx16(Text18, { children: highlightJson(children) }) });
5737
+ return /* @__PURE__ */ jsx17(Box18, { children: /* @__PURE__ */ jsx17(Text19, { children: highlightJson(children) }) });
5556
5738
  }
5557
5739
 
5558
5740
  // src/ui/copy/tips.ts
@@ -5766,26 +5948,26 @@ function tipsByIds(ids) {
5766
5948
  }
5767
5949
 
5768
5950
  // src/ui/Tips.tsx
5769
- import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
5951
+ import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
5770
5952
  var TICK_MS = 16;
5771
5953
  var CHUNK_HOLD_MS = 2e3;
5772
5954
  var HOLD_MS = 12e3;
5773
5955
  function TipTitle({ children }) {
5774
- return /* @__PURE__ */ jsxs17(Box19, { gap: 1, children: [
5775
- /* @__PURE__ */ jsx17(Text19, { color: "cyan", children: "\u2726" }),
5776
- /* @__PURE__ */ jsx17(Text19, { color: "white", bold: true, children })
5956
+ return /* @__PURE__ */ jsxs18(Box19, { gap: 1, children: [
5957
+ /* @__PURE__ */ jsx18(Text20, { color: "cyan", children: "\u2726" }),
5958
+ /* @__PURE__ */ jsx18(Text20, { color: "white", bold: true, children })
5777
5959
  ] });
5778
5960
  }
5779
5961
  function InlineSegment({ segment }) {
5780
5962
  switch (segment.type) {
5781
5963
  case "highlight":
5782
- return /* @__PURE__ */ jsx17(Text19, { color: COLORS.success, children: segment.value });
5964
+ return /* @__PURE__ */ jsx18(Text20, { color: COLORS.success, children: segment.value });
5783
5965
  case "link":
5784
- return /* @__PURE__ */ jsx17(Text19, { color: "cyan", underline: true, children: segment.href ? terminalLink(segment.value, segment.href) : segment.value });
5966
+ return /* @__PURE__ */ jsx18(Text20, { color: "cyan", underline: true, children: segment.href ? terminalLink(segment.value, segment.href) : segment.value });
5785
5967
  case "codeword":
5786
- return /* @__PURE__ */ jsx17(Text19, { color: COLORS.highlight.fg, backgroundColor: COLORS.highlight.bg, children: segment.value });
5968
+ return /* @__PURE__ */ jsx18(Text20, { color: COLORS.highlight.fg, backgroundColor: COLORS.highlight.bg, children: segment.value });
5787
5969
  default:
5788
- return /* @__PURE__ */ jsx17(Text19, { color: COLORS.muted, children: segment.value });
5970
+ return /* @__PURE__ */ jsx18(Text20, { color: COLORS.muted, children: segment.value });
5789
5971
  }
5790
5972
  }
5791
5973
  function TipContent({
@@ -5819,10 +6001,10 @@ function TipContent({
5819
6001
  blocks.push({ type: "inline", segments: [segment] });
5820
6002
  }
5821
6003
  }
5822
- return /* @__PURE__ */ jsx17(Box19, { flexDirection: "column", marginLeft: 2, gap: 1, children: blocks.map(
5823
- (block, i) => block.type === "code" ? /* @__PURE__ */ jsx17(Code, { children: block.segment.value }, i) : /* @__PURE__ */ jsx17(Text19, { children: block.segments.map((segment, j) => /* @__PURE__ */ jsxs17(Text19, { children: [
6004
+ return /* @__PURE__ */ jsx18(Box19, { flexDirection: "column", marginLeft: 2, gap: 1, children: blocks.map(
6005
+ (block, i) => block.type === "code" ? /* @__PURE__ */ jsx18(Code, { children: block.segment.value }, i) : /* @__PURE__ */ jsx18(Text20, { children: block.segments.map((segment, j) => /* @__PURE__ */ jsxs18(Text20, { children: [
5824
6006
  j > 0 && " ",
5825
- /* @__PURE__ */ jsx17(InlineSegment, { segment })
6007
+ /* @__PURE__ */ jsx18(InlineSegment, { segment })
5826
6008
  ] }, j)) }, i)
5827
6009
  ) });
5828
6010
  }
@@ -5839,8 +6021,8 @@ function Tips({
5839
6021
  progress.tipIndex = 0;
5840
6022
  progress.revealed = 0;
5841
6023
  }
5842
- const [tipIndex, setTipIndex] = useState9(resuming ? progress.tipIndex : 0);
5843
- const [revealed, setRevealed] = useState9(resuming ? progress.revealed : 0);
6024
+ const [tipIndex, setTipIndex] = useState10(resuming ? progress.tipIndex : 0);
6025
+ const [revealed, setRevealed] = useState10(resuming ? progress.revealed : 0);
5844
6026
  const tip = tips2.length > 0 ? tips2[tipIndex % tips2.length] : void 0;
5845
6027
  const contentLength = tip?.chunks.reduce((sum, c) => sum + c.value.length, 0) ?? 0;
5846
6028
  const totalLength = (tip?.title.length ?? 0) + contentLength;
@@ -5899,14 +6081,14 @@ function Tips({
5899
6081
  if (!tip) return null;
5900
6082
  const titleRevealed = tip.title.slice(0, revealed);
5901
6083
  const contentRevealed = Math.max(0, revealed - tip.title.length);
5902
- return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", marginBottom: 1, gap: 1, children: [
5903
- /* @__PURE__ */ jsx17(TipTitle, { children: titleRevealed }),
5904
- /* @__PURE__ */ jsx17(TipContent, { chunks: tip.chunks, revealed: contentRevealed })
6084
+ return /* @__PURE__ */ jsxs18(Box19, { flexDirection: "column", marginBottom: 1, gap: 1, children: [
6085
+ /* @__PURE__ */ jsx18(TipTitle, { children: titleRevealed }),
6086
+ /* @__PURE__ */ jsx18(TipContent, { chunks: tip.chunks, revealed: contentRevealed })
5905
6087
  ] });
5906
6088
  }
5907
6089
 
5908
6090
  // src/ui/App.tsx
5909
- import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
6091
+ import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
5910
6092
  function App() {
5911
6093
  const {
5912
6094
  phase,
@@ -5922,8 +6104,8 @@ function App() {
5922
6104
  } = useWizard();
5923
6105
  const { exit } = useApp();
5924
6106
  const { columns, rows } = useWindowSize7();
5925
- const [showLogs, setShowLogs] = useState10(false);
5926
- const [tipState, setTipState] = useState10("idle");
6107
+ const [showLogs, setShowLogs] = useState11(false);
6108
+ const [tipState, setTipState] = useState11("idle");
5927
6109
  const finished = phase === "done" || phase === "error";
5928
6110
  const currentStep = steps[currentStepIndex];
5929
6111
  const stepDef = workflow ? getWorkflow(workflow.id)?.steps.find((s) => s.id === currentStep?.id) : void 0;
@@ -5936,7 +6118,7 @@ function App() {
5936
6118
  const showTips = stepHasTips && (phase === "running" && currentStep?.status === "running" || isCommandApprovalPrompt || holdForTip);
5937
6119
  const showNoticesInMain = !stepHasTips;
5938
6120
  const showNotices = (!isAwaitingUserInput || holdForTip) && !review2;
5939
- useInput7(
6121
+ useInput8(
5940
6122
  (_input, key) => {
5941
6123
  if (key.return) {
5942
6124
  exit();
@@ -5944,7 +6126,7 @@ function App() {
5944
6126
  },
5945
6127
  { isActive: finished }
5946
6128
  );
5947
- useInput7((_input, key) => {
6129
+ useInput8((_input, key) => {
5948
6130
  if (phase === "idle" || phase === "authenticating") return;
5949
6131
  if (key.tab) {
5950
6132
  setShowLogs(!showLogs);
@@ -5956,7 +6138,7 @@ function App() {
5956
6138
  }
5957
6139
  });
5958
6140
  const escOwnedElsewhere = phase === "idle" || phase === "authenticating" || phase === "awaitingInput" && !holdForTip && (inputReq?.promptType === "enterToContinue" || inputReq?.promptType === "commandApproval");
5959
- useInput7((_input, key) => {
6141
+ useInput8((_input, key) => {
5960
6142
  if (escOwnedElsewhere) return;
5961
6143
  if (key.escape) {
5962
6144
  track("AI Wizard Interaction", {
@@ -5975,7 +6157,7 @@ function App() {
5975
6157
  /* Clamped to exactly the viewport: a taller frame makes Ink clear and repaint
5976
6158
  the whole screen, and the scrolling throws off its cursor arithmetic —
5977
6159
  flicker and leftover rows. */
5978
- /* @__PURE__ */ jsxs18(
6160
+ /* @__PURE__ */ jsxs19(
5979
6161
  Box20,
5980
6162
  {
5981
6163
  backgroundColor: COLORS.bg.main,
@@ -5984,7 +6166,7 @@ function App() {
5984
6166
  height: scrollsPastViewport ? void 0 : rows,
5985
6167
  overflow: scrollsPastViewport ? "visible" : "hidden",
5986
6168
  children: [
5987
- mainWindowVisible && /* @__PURE__ */ jsxs18(
6169
+ mainWindowVisible && /* @__PURE__ */ jsxs19(
5988
6170
  Box20,
5989
6171
  {
5990
6172
  flexDirection,
@@ -5992,7 +6174,7 @@ function App() {
5992
6174
  maxHeight: rows,
5993
6175
  justifyContent: "space-between",
5994
6176
  children: [
5995
- showLogs ? /* @__PURE__ */ jsx18(Logs, {}) : /* @__PURE__ */ jsxs18(
6177
+ showLogs ? /* @__PURE__ */ jsx19(Logs, {}) : /* @__PURE__ */ jsxs19(
5996
6178
  Box20,
5997
6179
  {
5998
6180
  flexDirection: "column",
@@ -6002,30 +6184,30 @@ function App() {
6002
6184
  flexGrow: 1,
6003
6185
  gap: 1,
6004
6186
  children: [
6005
- /* @__PURE__ */ jsxs18(Box20, { flexGrow: 2, flexDirection: "column", children: [
6006
- phase === "preflight" && !user && /* @__PURE__ */ jsx18(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
6007
- /* @__PURE__ */ jsx18(Spinner3, { type: "dots" }),
6187
+ /* @__PURE__ */ jsxs19(Box20, { flexGrow: 2, flexDirection: "column", children: [
6188
+ phase === "preflight" && !user && /* @__PURE__ */ jsx19(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs19(Text21, { color: COLORS.strong, bold: true, children: [
6189
+ /* @__PURE__ */ jsx19(Spinner3, { type: "dots" }),
6008
6190
  " Signing in to Algolia"
6009
6191
  ] }) }),
6010
- phase === "preflight" && user && /* @__PURE__ */ jsx18(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
6011
- /* @__PURE__ */ jsx18(Spinner3, { type: "dots" }),
6192
+ phase === "preflight" && user && /* @__PURE__ */ jsx19(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs19(Text21, { color: COLORS.strong, bold: true, children: [
6193
+ /* @__PURE__ */ jsx19(Spinner3, { type: "dots" }),
6012
6194
  " Getting things ready"
6013
6195
  ] }) }),
6014
- phase === "authenticating" && /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", marginBottom: 1, children: [
6015
- /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
6016
- /* @__PURE__ */ jsx18(Spinner3, { type: "dots" }),
6196
+ phase === "authenticating" && /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", marginBottom: 1, children: [
6197
+ /* @__PURE__ */ jsxs19(Text21, { color: COLORS.strong, bold: true, children: [
6198
+ /* @__PURE__ */ jsx19(Spinner3, { type: "dots" }),
6017
6199
  " Signing in to Algolia"
6018
6200
  ] }),
6019
- /* @__PURE__ */ jsx18(Text20, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
6201
+ /* @__PURE__ */ jsx19(Text21, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
6020
6202
  ] }),
6021
- settingUpAppId && /* @__PURE__ */ jsx18(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
6022
- /* @__PURE__ */ jsx18(Spinner3, { type: "dots" }),
6203
+ settingUpAppId && /* @__PURE__ */ jsx19(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs19(Text21, { color: COLORS.strong, bold: true, children: [
6204
+ /* @__PURE__ */ jsx19(Spinner3, { type: "dots" }),
6023
6205
  " Setting up Wizard using app",
6024
6206
  " ",
6025
6207
  settingUpAppId
6026
6208
  ] }) }),
6027
- /* @__PURE__ */ jsx18(CliOutput, {}),
6028
- showTips && currentStep && /* @__PURE__ */ jsx18(
6209
+ /* @__PURE__ */ jsx19(CliOutput, {}),
6210
+ showTips && currentStep && /* @__PURE__ */ jsx19(
6029
6211
  Tips,
6030
6212
  {
6031
6213
  stepId: currentStep.id,
@@ -6033,24 +6215,24 @@ function App() {
6033
6215
  onRevealStateChange: setTipState
6034
6216
  }
6035
6217
  ),
6036
- showNoticesInMain && showNotices && /* @__PURE__ */ jsx18(Notices, { showAll: true, border: false }),
6037
- /* @__PURE__ */ jsx18(Review, {}),
6038
- !showTips && /* @__PURE__ */ jsx18(PromptInput, {}),
6039
- phase === "error" && error && /* @__PURE__ */ jsx18(Box20, { marginTop: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.status.error, children: [
6218
+ showNoticesInMain && showNotices && /* @__PURE__ */ jsx19(Notices, { showAll: true, border: false }),
6219
+ /* @__PURE__ */ jsx19(Review, {}),
6220
+ !showTips && /* @__PURE__ */ jsx19(PromptInput, {}),
6221
+ phase === "error" && error && /* @__PURE__ */ jsx19(Box20, { marginTop: 1, children: /* @__PURE__ */ jsxs19(Text21, { color: COLORS.status.error, children: [
6040
6222
  "\u2716 ",
6041
6223
  error
6042
6224
  ] }) })
6043
6225
  ] }),
6044
- !showNoticesInMain && showNotices && /* @__PURE__ */ jsx18(Notices, {}),
6045
- showTips && !holdForTip && /* @__PURE__ */ jsx18(PromptInput, {})
6226
+ !showNoticesInMain && showNotices && /* @__PURE__ */ jsx19(Notices, {}),
6227
+ showTips && !holdForTip && /* @__PURE__ */ jsx19(PromptInput, {})
6046
6228
  ]
6047
6229
  }
6048
6230
  ),
6049
- showSidebar ? /* @__PURE__ */ jsx18(Sidebar, {}) : /* @__PURE__ */ jsx18(Ribbon, {})
6231
+ showSidebar ? /* @__PURE__ */ jsx19(Sidebar, {}) : /* @__PURE__ */ jsx19(Ribbon, {})
6050
6232
  ]
6051
6233
  }
6052
6234
  ),
6053
- phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */ jsx18(LearnMore, {}) : /* @__PURE__ */ jsx18(Welcome, {}))
6235
+ phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */ jsx19(LearnMore, {}) : /* @__PURE__ */ jsx19(Welcome, {}))
6054
6236
  ]
6055
6237
  }
6056
6238
  )
@@ -6058,7 +6240,7 @@ function App() {
6058
6240
  }
6059
6241
 
6060
6242
  // src/lib/envAppId.ts
6061
- import { readFile as readFile7 } from "node:fs/promises";
6243
+ import { readFile as readFile8 } from "node:fs/promises";
6062
6244
  import { join as join12 } from "node:path";
6063
6245
  var ENV_FILES = [".env", ".env.local"];
6064
6246
  var APP_ID_LINE = /^[ \t]*(?:export[ \t]+)?([A-Z0-9_]*ALGOLIA_APP(?:LICATION)?_ID)[ \t]*=[ \t]*(.*)$/gm;
@@ -6066,7 +6248,7 @@ async function findEnvApplicationId(root = process.cwd()) {
6066
6248
  for (const file of ENV_FILES) {
6067
6249
  let content;
6068
6250
  try {
6069
- content = await readFile7(join12(root, file), "utf8");
6251
+ content = await readFile8(join12(root, file), "utf8");
6070
6252
  } catch (err) {
6071
6253
  if (err.code !== "ENOENT") {
6072
6254
  logger.warn(
@@ -6417,7 +6599,7 @@ function delay(ms) {
6417
6599
  }
6418
6600
 
6419
6601
  // src/main.tsx
6420
- import { jsx as jsx19 } from "react/jsx-runtime";
6602
+ import { jsx as jsx20 } from "react/jsx-runtime";
6421
6603
  async function startup() {
6422
6604
  setProjectRoot(process.cwd());
6423
6605
  let args;
@@ -6468,7 +6650,7 @@ ${formatStepList(workflow)}`);
6468
6650
  async function run(opts) {
6469
6651
  const { workflow, skipResumePrompt } = opts;
6470
6652
  const store = useWizard.getState();
6471
- const instance = render(/* @__PURE__ */ jsx19(App, {}), { incrementalRendering: true });
6653
+ const instance = render(/* @__PURE__ */ jsx20(App, {}), { incrementalRendering: true });
6472
6654
  await store.waitForStart();
6473
6655
  store.syncSteps(
6474
6656
  workflow.steps.map((s) => ({