@algolia/wizard 0.49.0 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.js +461 -294
  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
@@ -641,10 +641,9 @@ function Notices({
641
641
  }
642
642
 
643
643
  // src/ui/PromptInput.tsx
644
- import { Box as Box9, Text as Text9 } from "ink";
644
+ import { Box as Box9, Text as Text10 } from "ink";
645
645
  import Spinner from "ink-spinner";
646
- import TextInput from "ink-text-input";
647
- import { useState as useState6 } from "react";
646
+ import { useState as useState7 } from "react";
648
647
 
649
648
  // src/ui/CommandApproval.tsx
650
649
  import { Box as Box6, Text as Text6 } from "ink";
@@ -783,14 +782,62 @@ function CommandApproval({
783
782
  ] });
784
783
  }
785
784
 
785
+ // src/ui/FreeTextInput.tsx
786
+ import { Text as Text7, useInput as useInput2 } from "ink";
787
+ import { useState as useState4 } from "react";
788
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
789
+ function FreeTextInput({
790
+ value,
791
+ onChange,
792
+ onSubmit
793
+ }) {
794
+ const [cursor, setCursor] = useState4(value.length);
795
+ const at = Math.min(cursor, value.length);
796
+ useInput2((input, key) => {
797
+ if (key.upArrow || key.downArrow || key.tab || key.ctrl && input === "c") {
798
+ return;
799
+ }
800
+ if (key.return) {
801
+ onSubmit(value);
802
+ return;
803
+ }
804
+ if (key.leftArrow) {
805
+ setCursor(Math.max(0, at - 1));
806
+ return;
807
+ }
808
+ if (key.rightArrow) {
809
+ setCursor(Math.min(value.length, at + 1));
810
+ return;
811
+ }
812
+ if (key.backspace || key.delete) {
813
+ if (at === 0) return;
814
+ onChange(value.slice(0, at - 1) + value.slice(at));
815
+ setCursor(at - 1);
816
+ return;
817
+ }
818
+ if (input) {
819
+ onChange(value.slice(0, at) + input + value.slice(at));
820
+ setCursor(at + input.length);
821
+ }
822
+ });
823
+ const before = value.slice(0, at);
824
+ const current = value.slice(at, at + 1) || " ";
825
+ const after = value.slice(at + 1);
826
+ return /* @__PURE__ */ jsxs6(Text7, { color: COLORS.strong, children: [
827
+ before,
828
+ /* @__PURE__ */ jsx6(Text7, { inverse: true, children: current }),
829
+ after
830
+ ] });
831
+ }
832
+
786
833
  // 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";
834
+ import { Box as Box8, Text as Text9, useInput as useInput3, useWindowSize as useWindowSize4 } from "ink";
835
+ import { useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState6 } from "react";
789
836
 
790
837
  // 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";
838
+ import { Box as Box7, Text as Text8, measureElement as measureElement2, useWindowSize as useWindowSize3 } from "ink";
839
+ import { useCallback, useLayoutEffect, useRef as useRef2, useState as useState5 } from "react";
840
+ import { jsxs as jsxs7 } from "react/jsx-runtime";
794
841
  var INDICATOR_ROWS = 2;
795
842
  function fittedWidth(node, columns) {
796
843
  let left = 0;
@@ -806,7 +853,7 @@ function useScrollWindow({
806
853
  }) {
807
854
  const viewportRef = useRef2(null);
808
855
  const { columns } = useWindowSize3();
809
- const [size, setSize] = useState4(
856
+ const [size, setSize] = useState5(
810
857
  null
811
858
  );
812
859
  useLayoutEffect(() => {
@@ -819,7 +866,7 @@ function useScrollWindow({
819
866
  });
820
867
  const capacity = size === null || itemCount * rowHeight <= size.height ? itemCount : Math.max(Math.floor((size.height - INDICATOR_ROWS) / rowHeight), 1);
821
868
  const maxOffset = Math.max(itemCount - capacity, 0);
822
- const [offset, setOffset] = useState4(0);
869
+ const [offset, setOffset] = useState5(0);
823
870
  const prevMaxOffsetRef = useRef2(0);
824
871
  useLayoutEffect(() => {
825
872
  const wasAtBottom = offset >= prevMaxOffsetRef.current;
@@ -861,14 +908,14 @@ function useScrollWindow({
861
908
  };
862
909
  }
863
910
  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: [
911
+ return /* @__PURE__ */ jsxs7(Box7, { ref: scroll.viewportRef, flexDirection: "column", flexGrow: 1, children: [
912
+ scroll.hiddenAbove > 0 && /* @__PURE__ */ jsxs7(Text8, { color: COLORS.dim, children: [
866
913
  "\u2191 ",
867
914
  scroll.hiddenAbove,
868
915
  " more"
869
916
  ] }),
870
917
  children,
871
- scroll.hiddenBelow > 0 && /* @__PURE__ */ jsxs6(Text7, { color: COLORS.dim, children: [
918
+ scroll.hiddenBelow > 0 && /* @__PURE__ */ jsxs7(Text8, { color: COLORS.dim, children: [
872
919
  "\u2193 ",
873
920
  scroll.hiddenBelow,
874
921
  " more"
@@ -877,7 +924,7 @@ function ScrollView({ scroll, children }) {
877
924
  }
878
925
 
879
926
  // src/ui/SelectPrompt.tsx
880
- import { jsx as jsx6, jsxs as jsxs7 } from "react/jsx-runtime";
927
+ import { jsx as jsx7, jsxs as jsxs8 } from "react/jsx-runtime";
881
928
  var CANCEL = "cancel";
882
929
  var ARROW_WIDTH = 4;
883
930
  var COLUMN_GAP = 2;
@@ -909,18 +956,18 @@ function SelectPrompt({
909
956
  const rows = hasCancel ? [...options, "Cancel"] : options;
910
957
  const cancelIndex = hasCancel ? options.length : -1;
911
958
  const isDisabled = (i) => i !== cancelIndex && Boolean(disabled?.[i]);
912
- const [index, setIndex] = useState5(() => {
959
+ const [index, setIndex] = useState6(() => {
913
960
  const start = defaultSelectedIndex > 0 && defaultSelectedIndex < options.length ? defaultSelectedIndex : 0;
914
961
  return isDisabled(start) ? nextSelectableIndex(start, 1, rows.length, isDisabled) : start;
915
962
  });
916
- const [checked, setChecked] = useState5(() => /* @__PURE__ */ new Set());
963
+ const [checked, setChecked] = useState6(() => /* @__PURE__ */ new Set());
917
964
  const hints = [];
918
965
  if (rows.length > 1) hints.push({ key: "[\u2191] [\u2193]", label: "move" });
919
966
  if (multi) hints.push({ key: "[space]", label: "select" });
920
967
  hints.push({ key: "[enter]", label: "confirm" });
921
968
  const containerRef = useRef3(null);
922
969
  const { columns } = useWindowSize4();
923
- const [width, setWidth] = useState5(columns);
970
+ const [width, setWidth] = useState6(columns);
924
971
  useLayoutEffect2(() => {
925
972
  if (!containerRef.current) return;
926
973
  const measured = fittedWidth(containerRef.current, columns);
@@ -950,7 +997,7 @@ function SelectPrompt({
950
997
  revealIndex(index);
951
998
  }, [index, revealIndex]);
952
999
  const visible = rows.slice(scroll.offset, scroll.offset + scroll.capacity);
953
- useInput2((input, key) => {
1000
+ useInput3((input, key) => {
954
1001
  if (rows.length === 0) return;
955
1002
  if (key.upArrow || input === "k") {
956
1003
  setIndex((i) => nextSelectableIndex(i, -1, rows.length, isDisabled));
@@ -975,17 +1022,17 @@ function SelectPrompt({
975
1022
  }
976
1023
  }
977
1024
  });
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 })
1025
+ return /* @__PURE__ */ jsx7(Box8, { ref: containerRef, flexGrow: 1, children: /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, width, children: [
1026
+ /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, flexShrink: 0, children: [
1027
+ error && /* @__PURE__ */ jsx7(Text9, { color: COLORS.danger, children: error }),
1028
+ messages?.map((m, i) => /* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: m }, `msg-${i}`)),
1029
+ table && /* @__PURE__ */ jsx7(Table, { columns: table.columns, rows: table.rows }),
1030
+ /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
1031
+ question && /* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: question }),
1032
+ helpText && /* @__PURE__ */ jsx7(Text9, { color: COLORS.dim, children: helpText })
986
1033
  ] })
987
1034
  ] }),
988
- /* @__PURE__ */ jsx6(ScrollView, { scroll, children: visible.map((option, visibleIndex) => {
1035
+ /* @__PURE__ */ jsx7(ScrollView, { scroll, children: visible.map((option, visibleIndex) => {
989
1036
  const i = scroll.offset + visibleIndex;
990
1037
  const highlighted = i === index;
991
1038
  const isCancel = i === cancelIndex;
@@ -993,7 +1040,7 @@ function SelectPrompt({
993
1040
  const sec = isCancel ? void 0 : secondary?.[i];
994
1041
  const isText = sec?.kind === "text";
995
1042
  const rowDisabled = isDisabled(i);
996
- return /* @__PURE__ */ jsxs7(
1043
+ return /* @__PURE__ */ jsxs8(
997
1044
  SelectRow,
998
1045
  {
999
1046
  highlighted,
@@ -1003,24 +1050,24 @@ function SelectPrompt({
1003
1050
  label: `${bullet}${option}`,
1004
1051
  usePadding: true,
1005
1052
  children: [
1006
- isText && textWidth > 0 && /* @__PURE__ */ jsx6(Box8, { width: textWidth, children: /* @__PURE__ */ jsx6(
1007
- Text8,
1053
+ isText && textWidth > 0 && /* @__PURE__ */ jsx7(Box8, { width: textWidth, children: /* @__PURE__ */ jsx7(
1054
+ Text9,
1008
1055
  {
1009
1056
  wrap: "truncate",
1010
1057
  color: rowDisabled ? COLORS.dim : highlighted ? COLORS.primary : COLORS.muted,
1011
1058
  children: sec.value
1012
1059
  }
1013
1060
  ) }),
1014
- sec?.kind === "badge" && /* @__PURE__ */ jsx6(Box8, { width: badgeWidth, justifyContent: "flex-end", children: /* @__PURE__ */ jsx6(Text8, { color: COLORS.badge, wrap: "truncate", children: sec.value }) })
1061
+ sec?.kind === "badge" && /* @__PURE__ */ jsx7(Box8, { width: badgeWidth, justifyContent: "flex-end", children: /* @__PURE__ */ jsx7(Text9, { color: COLORS.badge, wrap: "truncate", children: sec.value }) })
1015
1062
  ]
1016
1063
  },
1017
1064
  `row-${i}`
1018
1065
  );
1019
1066
  }) }),
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: [
1067
+ /* @__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
1068
  i > 0 ? " " : "",
1022
- /* @__PURE__ */ jsx6(Text8, { color: COLORS.primary, children: key }),
1023
- /* @__PURE__ */ jsxs7(Text8, { color: COLORS.dim, children: [
1069
+ /* @__PURE__ */ jsx7(Text9, { color: COLORS.primary, children: key }),
1070
+ /* @__PURE__ */ jsxs8(Text9, { color: COLORS.dim, children: [
1024
1071
  " ",
1025
1072
  label
1026
1073
  ] })
@@ -1029,17 +1076,17 @@ function SelectPrompt({
1029
1076
  }
1030
1077
 
1031
1078
  // src/ui/PromptInput.tsx
1032
- import { jsx as jsx7, jsxs as jsxs8 } from "react/jsx-runtime";
1079
+ import { jsx as jsx8, jsxs as jsxs9 } from "react/jsx-runtime";
1033
1080
  var ACCEPT_REJECT_OPTIONS = ["Accept", "Reject"];
1034
1081
  function EnterToContinuePrompt({
1035
1082
  question,
1036
1083
  messages,
1037
1084
  onDecide
1038
1085
  }) {
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(
1086
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", gap: 1, children: [
1087
+ messages?.map((m, i) => /* @__PURE__ */ jsx8(Text10, { color: COLORS.muted, children: m }, `msg-${i}`)),
1088
+ question && /* @__PURE__ */ jsx8(Text10, { color: COLORS.primary, children: question }),
1089
+ /* @__PURE__ */ jsx8(
1043
1090
  DecisionSelect,
1044
1091
  {
1045
1092
  actions: [
@@ -1053,17 +1100,17 @@ function EnterToContinuePrompt({
1053
1100
  }
1054
1101
  function PromptInput() {
1055
1102
  const { phase, inputReq, submitInput } = useWizard();
1056
- const [draft, setDraft] = useState6("");
1057
- const [submittedReq, setSubmittedReq] = useState6(null);
1103
+ const [draft, setDraft] = useState7("");
1104
+ const [submittedReq, setSubmittedReq] = useState7(null);
1058
1105
  const promptKey = inputReq && `${inputReq.promptType}:${inputReq.prompt}`;
1059
1106
  const submitting = inputReq != null && submittedReq === inputReq;
1060
1107
  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" }) });
1108
+ return /* @__PURE__ */ jsx8(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text10, { color: "gray", dimColor: true, children: "Press Enter or Esc to exit" }) });
1062
1109
  }
1063
1110
  if (phase !== "awaitingInput" || !inputReq) return null;
1064
1111
  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" }),
1112
+ return /* @__PURE__ */ jsx8(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsxs9(Text10, { color: COLORS.strong, bold: true, children: [
1113
+ /* @__PURE__ */ jsx8(Spinner, { type: "dots" }),
1067
1114
  " Continuing\u2026"
1068
1115
  ] }) });
1069
1116
  }
@@ -1072,7 +1119,7 @@ function PromptInput() {
1072
1119
  submitInput(value);
1073
1120
  };
1074
1121
  if (inputReq.promptType === "multipleChoice") {
1075
- return /* @__PURE__ */ jsx7(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx7(
1122
+ return /* @__PURE__ */ jsx8(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx8(
1076
1123
  SelectPrompt,
1077
1124
  {
1078
1125
  question: inputReq.prompt,
@@ -1091,7 +1138,7 @@ function PromptInput() {
1091
1138
  ) });
1092
1139
  }
1093
1140
  if (inputReq.promptType === "multiSelect") {
1094
- return /* @__PURE__ */ jsx7(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx7(
1141
+ return /* @__PURE__ */ jsx8(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx8(
1095
1142
  SelectPrompt,
1096
1143
  {
1097
1144
  multi: true,
@@ -1107,7 +1154,7 @@ function PromptInput() {
1107
1154
  ) });
1108
1155
  }
1109
1156
  if (inputReq.promptType === "notice") {
1110
- return /* @__PURE__ */ jsx7(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx7(
1157
+ return /* @__PURE__ */ jsx8(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx8(
1111
1158
  SelectPrompt,
1112
1159
  {
1113
1160
  question: inputReq.prompt,
@@ -1119,7 +1166,7 @@ function PromptInput() {
1119
1166
  ) });
1120
1167
  }
1121
1168
  if (inputReq.promptType === "enterToContinue") {
1122
- return /* @__PURE__ */ jsx7(
1169
+ return /* @__PURE__ */ jsx8(
1123
1170
  EnterToContinuePrompt,
1124
1171
  {
1125
1172
  question: inputReq.prompt,
@@ -1129,11 +1176,11 @@ function PromptInput() {
1129
1176
  );
1130
1177
  }
1131
1178
  if (inputReq.promptType === "commandApproval" && inputReq.command) {
1132
- return /* @__PURE__ */ jsx7(CommandApproval, { command: inputReq.command, onDecide: submitInput });
1179
+ return /* @__PURE__ */ jsx8(CommandApproval, { command: inputReq.command, onDecide: submitInput });
1133
1180
  }
1134
1181
  if (inputReq.promptType === "acceptReject") {
1135
1182
  const labels = inputReq.options?.length ? inputReq.options : ACCEPT_REJECT_OPTIONS;
1136
- return /* @__PURE__ */ jsx7(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx7(
1183
+ return /* @__PURE__ */ jsx8(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx8(
1137
1184
  SelectPrompt,
1138
1185
  {
1139
1186
  question: inputReq.prompt,
@@ -1145,16 +1192,16 @@ function PromptInput() {
1145
1192
  promptKey
1146
1193
  ) });
1147
1194
  }
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: [
1195
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
1196
+ inputReq.error && /* @__PURE__ */ jsx8(Text10, { color: COLORS.danger, children: inputReq.error }),
1197
+ inputReq.messages?.map((m, i) => /* @__PURE__ */ jsx8(Text10, { color: COLORS.muted, children: m }, `msg-${i}`)),
1198
+ /* @__PURE__ */ jsxs9(Box9, { children: [
1199
+ /* @__PURE__ */ jsxs9(Text10, { color: COLORS.primary, children: [
1153
1200
  inputReq.prompt,
1154
1201
  " "
1155
1202
  ] }),
1156
- /* @__PURE__ */ jsx7(Text9, { color: COLORS.strong, children: /* @__PURE__ */ jsx7(
1157
- TextInput,
1203
+ /* @__PURE__ */ jsx8(
1204
+ FreeTextInput,
1158
1205
  {
1159
1206
  value: draft,
1160
1207
  onChange: setDraft,
@@ -1163,15 +1210,15 @@ function PromptInput() {
1163
1210
  setDraft("");
1164
1211
  }
1165
1212
  }
1166
- ) })
1213
+ )
1167
1214
  ] })
1168
1215
  ] });
1169
1216
  }
1170
1217
 
1171
1218
  // 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";
1219
+ import { Box as Box10, Text as Text11, useInput as useInput4 } from "ink";
1220
+ import { useLayoutEffect as useLayoutEffect3, useState as useState8 } from "react";
1221
+ import { jsx as jsx9, jsxs as jsxs10 } from "react/jsx-runtime";
1175
1222
  var INGEST_SCRIPT = ".algolia-wizard/ingest.sh";
1176
1223
  function wrapText(text, width) {
1177
1224
  if (width <= 0) return [text];
@@ -1254,14 +1301,14 @@ function buildRows(review2, width) {
1254
1301
  return rows;
1255
1302
  }
1256
1303
  function ReviewPanel({ review: review2 }) {
1257
- const [width, setWidth] = useState7(0);
1304
+ const [width, setWidth] = useState8(0);
1258
1305
  const rows = width > 0 ? buildRows(review2, width) : [];
1259
1306
  const scroll = useScrollWindow({ itemCount: rows.length });
1260
1307
  useLayoutEffect3(() => {
1261
1308
  if (scroll.measured) setWidth(scroll.width);
1262
1309
  }, [scroll.measured, scroll.width]);
1263
1310
  const scrollable = scroll.maxOffset > 0;
1264
- useInput3(
1311
+ useInput4(
1265
1312
  (_input, key) => {
1266
1313
  if (key.upArrow) scroll.scrollBy(-1);
1267
1314
  else if (key.downArrow) scroll.scrollBy(1);
@@ -1269,18 +1316,18 @@ function ReviewPanel({ review: review2 }) {
1269
1316
  { isActive: scrollable }
1270
1317
  );
1271
1318
  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 })
1319
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", flexGrow: 1, children: [
1320
+ /* @__PURE__ */ jsx9(ScrollView, { scroll, children: visible.map((row, i) => /* @__PURE__ */ jsxs10(Text11, { wrap: "truncate", children: [
1321
+ row.prefix && /* @__PURE__ */ jsx9(Text11, { color: row.prefixColor ?? row.color, bold: row.bold, children: row.prefix }),
1322
+ /* @__PURE__ */ jsx9(Text11, { color: row.color, bold: row.bold, children: row.text })
1276
1323
  ] }, `review-row-${i}`)) }),
1277
- scrollable && /* @__PURE__ */ jsx8(Text10, { color: COLORS.dim, children: "\u2191/\u2193 scroll" })
1324
+ scrollable && /* @__PURE__ */ jsx9(Text11, { color: COLORS.dim, children: "\u2191/\u2193 scroll" })
1278
1325
  ] });
1279
1326
  }
1280
1327
  function Review() {
1281
1328
  const review2 = useWizard((s) => s.review);
1282
1329
  if (!review2) return null;
1283
- return /* @__PURE__ */ jsx8(ReviewPanel, { review: review2 });
1330
+ return /* @__PURE__ */ jsx9(ReviewPanel, { review: review2 });
1284
1331
  }
1285
1332
 
1286
1333
  // src/workflows/default.ts
@@ -3604,7 +3651,7 @@ async function runAnalysis(mode, extraInstructions = []) {
3604
3651
  // package.json
3605
3652
  var package_default = {
3606
3653
  name: "@algolia/wizard",
3607
- version: "0.49.0",
3654
+ version: "0.51.0",
3608
3655
  description: "Magically implement Algolia functionality in your codebase",
3609
3656
  type: "module",
3610
3657
  engines: {
@@ -3662,7 +3709,6 @@ var package_default = {
3662
3709
  ink: "^7.0.5",
3663
3710
  "ink-picture": "^2.1.0",
3664
3711
  "ink-spinner": "^5.0.0",
3665
- "ink-text-input": "^6.0.0",
3666
3712
  ioredis: "^5.11.1",
3667
3713
  nanoid: "^5.1.15",
3668
3714
  pino: "^10.3.1",
@@ -4888,9 +4934,168 @@ var defaultWorkflow = {
4888
4934
  ]
4889
4935
  };
4890
4936
 
4937
+ // src/actions/playbookSteps/selectPlaybook.ts
4938
+ import { z as z32 } from "zod";
4939
+
4940
+ // src/lib/dashboardApi/client.ts
4941
+ import "zod";
4942
+ var DASHBOARD_API_BASE_URL = `${PROXY_BASE_URL}/dashboard`;
4943
+ var DashboardApiError = class extends Error {
4944
+ constructor(status, message) {
4945
+ super(message);
4946
+ this.status = status;
4947
+ this.name = "DashboardApiError";
4948
+ }
4949
+ status;
4950
+ };
4951
+ async function dashboardRequest(path, schema, init) {
4952
+ const token = getAuthToken();
4953
+ if (!token) {
4954
+ throw new Error("Not authenticated: no user token available");
4955
+ }
4956
+ const res = await proxyFetch(`${DASHBOARD_API_BASE_URL}${path}`, {
4957
+ ...init,
4958
+ headers: {
4959
+ accept: "application/json",
4960
+ authorization: `Bearer ${token}`,
4961
+ ...init?.headers
4962
+ }
4963
+ });
4964
+ if (!res.ok) {
4965
+ throw new DashboardApiError(
4966
+ res.status,
4967
+ `Dashboard API responded ${res.status} for ${path}`
4968
+ );
4969
+ }
4970
+ const body = await res.json();
4971
+ return { status: res.status, data: schema.parse(body) };
4972
+ }
4973
+
4974
+ // src/lib/dashboardApi/schemas.ts
4975
+ import { z as z31 } from "zod";
4976
+ var playbookSchema = z31.object({
4977
+ slug: z31.string(),
4978
+ category: z31.string().optional(),
4979
+ title: z31.string(),
4980
+ description: z31.string().optional()
4981
+ });
4982
+ var playbooksListSchema = z31.array(playbookSchema);
4983
+
4984
+ // src/lib/dashboardApi/api.ts
4985
+ async function getPlaybooks() {
4986
+ const { data } = await dashboardRequest(
4987
+ "/api/1/playbook-integrations/playbooks",
4988
+ playbooksListSchema
4989
+ );
4990
+ return data;
4991
+ }
4992
+
4993
+ // src/actions/playbookSteps/selectPlaybook.ts
4994
+ var selectPlaybookSchema = z32.object({
4995
+ slug: z32.string()
4996
+ });
4997
+ function persistSlug(ctx, slug) {
4998
+ ctx.setUserInput("playbookSlug", slug);
4999
+ return { slug };
5000
+ }
5001
+ async function selectPlaybookStep(ctx, requestedSlug) {
5002
+ const playbooks = await getPlaybooks();
5003
+ const slugs = playbooks.map((playbook) => playbook.slug);
5004
+ if (slugs.length === 0) {
5005
+ throw new Error("No playbooks are available.");
5006
+ }
5007
+ if (requestedSlug && slugs.includes(requestedSlug)) {
5008
+ return persistSlug(ctx, requestedSlug);
5009
+ }
5010
+ const messages = requestedSlug ? [
5011
+ `"${requestedSlug}" is not a valid playbook. Choose one of the available playbooks:`
5012
+ ] : ["Choose a playbook:"];
5013
+ const selection = await ctx.requestUserInput({
5014
+ prompt: "Which playbook do you want to run?",
5015
+ promptType: "multipleChoice",
5016
+ options: slugs,
5017
+ messages
5018
+ });
5019
+ if (typeof selection !== "string") {
5020
+ throw new Error("selectPlaybook received an unexpected non-text result");
5021
+ }
5022
+ return persistSlug(ctx, selection);
5023
+ }
5024
+
5025
+ // src/lib/cli.ts
5026
+ var USAGE = `Usage: wizard [workflow-id] [options]
5027
+ wizard playbook [playbook-slug] [options]
5028
+
5029
+ Options:
5030
+ --seed <step-id> Start the workflow at the step with this id, with earlier
5031
+ steps pre-filled with test data. Pass with no value to print
5032
+ the step ids. See CONTRIBUTING.md.
5033
+ --no-telemetry Send no telemetry or analytics for this run.
5034
+ --reset-on-run Wipe this project's wizard state (run state, AI consent)
5035
+ before starting, so the run behaves like a first-ever
5036
+ run. Also drops every API key the wizard has
5037
+ stored in your keychain (or, where the platform has none,
5038
+ the encrypted file it falls back to \u2014 see CONTRIBUTING.md),
5039
+ for this project and any other, so later runs create new
5040
+ ones. Your Algolia login is not touched.
5041
+ -h, --help Print this message.`;
5042
+ function parseCliArgs(argv) {
5043
+ const positionals = [];
5044
+ let seed;
5045
+ let telemetry = true;
5046
+ let resetOnRun = false;
5047
+ let help = false;
5048
+ for (let i = 0; i < argv.length; i++) {
5049
+ const arg = argv[i];
5050
+ if (arg === "--seed") {
5051
+ const next = argv[i + 1];
5052
+ if (next !== void 0 && !next.startsWith("-")) {
5053
+ seed = next;
5054
+ i++;
5055
+ } else {
5056
+ seed = null;
5057
+ }
5058
+ } else if (arg.startsWith("--seed=")) {
5059
+ seed = arg.slice("--seed=".length);
5060
+ } else if (arg === "--no-telemetry") {
5061
+ telemetry = false;
5062
+ } else if (arg === "--reset-on-run") {
5063
+ resetOnRun = true;
5064
+ } else if (arg === "--help" || arg === "-h") {
5065
+ help = true;
5066
+ } else if (arg.startsWith("-")) {
5067
+ throw new Error(`Unknown option "${arg}".`);
5068
+ } else {
5069
+ positionals.push(arg);
5070
+ }
5071
+ }
5072
+ return { positionals, seed, telemetry, resetOnRun, help };
5073
+ }
5074
+ function getPlaybookSlugArg(argv = process.argv.slice(2)) {
5075
+ const { positionals } = parseCliArgs(argv);
5076
+ if (positionals[0] !== "playbook") return void 0;
5077
+ return positionals[1];
5078
+ }
5079
+
5080
+ // src/workflows/playbook.ts
5081
+ var playbookWorkflow = {
5082
+ id: "playbook",
5083
+ title: "Playbook Workflow",
5084
+ description: "Select a playbook from the dashboard catalogue and walk through its implementation.",
5085
+ steps: [
5086
+ defineStep({
5087
+ id: "select-playbook",
5088
+ title: "Select playbook",
5089
+ outputSchema: selectPlaybookSchema,
5090
+ run: (ctx) => selectPlaybookStep(ctx, getPlaybookSlugArg())
5091
+ })
5092
+ ]
5093
+ };
5094
+
4891
5095
  // src/workflows/index.ts
4892
5096
  var workflows = {
4893
- [defaultWorkflow.id]: defaultWorkflow
5097
+ [defaultWorkflow.id]: defaultWorkflow,
5098
+ [playbookWorkflow.id]: playbookWorkflow
4894
5099
  };
4895
5100
  function getWorkflow(id) {
4896
5101
  return workflows[id];
@@ -4899,8 +5104,8 @@ function getWorkflow(id) {
4899
5104
  // src/ui/Welcome.tsx
4900
5105
  import { dirname as dirname8, join as join11 } from "node:path";
4901
5106
  import { fileURLToPath as fileURLToPath2 } from "node:url";
4902
- import { useState as useState8 } from "react";
4903
- import { Box as Box11, Spacer, Text as Text11, useInput as useInput4, useWindowSize as useWindowSize5 } from "ink";
5107
+ import { useState as useState9 } from "react";
5108
+ import { Box as Box11, Spacer, Text as Text12, useInput as useInput5, useWindowSize as useWindowSize5 } from "ink";
4904
5109
 
4905
5110
  // src/ui/copy/welcome.ts
4906
5111
  var sidebarItems = [
@@ -4928,7 +5133,7 @@ var sidebarItems = [
4928
5133
 
4929
5134
  // src/ui/Welcome.tsx
4930
5135
  import Image, { TerminalInfoContext, defaultTerminalInfo } from "ink-picture";
4931
- import { jsx as jsx9, jsxs as jsxs10 } from "react/jsx-runtime";
5136
+ import { jsx as jsx10, jsxs as jsxs11 } from "react/jsx-runtime";
4932
5137
  var IMAGE_PATH = join11(dirname8(fileURLToPath2(import.meta.url)), "algolia.png");
4933
5138
  var TERMINAL_INFO = {
4934
5139
  ...defaultTerminalInfo,
@@ -4939,14 +5144,14 @@ function SidebarItem({
4939
5144
  title,
4940
5145
  description
4941
5146
  }) {
4942
- return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", children: [
4943
- /* @__PURE__ */ jsxs10(Box11, { gap: 1, children: [
4944
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.success, children: "\u2192" }),
4945
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.strong, bold: true, children: title })
5147
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
5148
+ /* @__PURE__ */ jsxs11(Box11, { gap: 1, children: [
5149
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.success, children: "\u2192" }),
5150
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.strong, bold: true, children: title })
4946
5151
  ] }),
4947
- /* @__PURE__ */ jsxs10(Box11, { flexDirection: "row", gap: 2, children: [
4948
- /* @__PURE__ */ jsx9(Spacer, {}),
4949
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.muted, children: description })
5152
+ /* @__PURE__ */ jsxs11(Box11, { flexDirection: "row", gap: 2, children: [
5153
+ /* @__PURE__ */ jsx10(Spacer, {}),
5154
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: description })
4950
5155
  ] })
4951
5156
  ] });
4952
5157
  }
@@ -4958,8 +5163,8 @@ function Welcome() {
4958
5163
  { label: "start wizard", run: confirmStart },
4959
5164
  { label: "learn more", run: openLearnMore }
4960
5165
  ];
4961
- const [index, setIndex] = useState8(0);
4962
- useInput4((input, key) => {
5166
+ const [index, setIndex] = useState9(0);
5167
+ useInput5((input, key) => {
4963
5168
  if (key.upArrow || input === "k") {
4964
5169
  setIndex((i) => (i - 1 + actions.length) % actions.length);
4965
5170
  } else if (key.downArrow || input === "j") {
@@ -4982,16 +5187,16 @@ function Welcome() {
4982
5187
  if (rows < 30) {
4983
5188
  layout = scales["small"];
4984
5189
  }
4985
- return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "row", justifyContent: "space-between", width: "100%", children: [
4986
- /* @__PURE__ */ jsx9(
5190
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "row", justifyContent: "space-between", width: "100%", children: [
5191
+ /* @__PURE__ */ jsx10(
4987
5192
  Box11,
4988
5193
  {
4989
5194
  paddingY: layout.main.padding.y,
4990
5195
  paddingX: layout.main.padding.x,
4991
5196
  flexDirection: "column",
4992
5197
  justifyContent: "center",
4993
- children: /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", gap: 2, children: [
4994
- /* @__PURE__ */ jsx9(TerminalInfoContext.Provider, { value: TERMINAL_INFO, children: /* @__PURE__ */ jsx9(
5198
+ children: /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", gap: 2, children: [
5199
+ /* @__PURE__ */ jsx10(TerminalInfoContext.Provider, { value: TERMINAL_INFO, children: /* @__PURE__ */ jsx10(
4995
5200
  Image,
4996
5201
  {
4997
5202
  src: IMAGE_PATH,
@@ -5002,8 +5207,8 @@ function Welcome() {
5002
5207
  protocol: "halfBlock"
5003
5208
  }
5004
5209
  ) }),
5005
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.muted, children: "\u2726 From zero \u2192 working search in ~10 minutes" }),
5006
- /* @__PURE__ */ jsx9(Box11, { flexDirection: "column", children: actions.map((action, i) => /* @__PURE__ */ jsx9(
5210
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "\u2726 From zero \u2192 working search in ~10 minutes" }),
5211
+ /* @__PURE__ */ jsx10(Box11, { flexDirection: "column", children: actions.map((action, i) => /* @__PURE__ */ jsx10(
5007
5212
  SelectRow,
5008
5213
  {
5009
5214
  highlighted: i === index,
@@ -5012,20 +5217,20 @@ function Welcome() {
5012
5217
  },
5013
5218
  action.label
5014
5219
  )) }),
5015
- /* @__PURE__ */ jsxs10(Box11, { gap: 2, children: [
5016
- /* @__PURE__ */ jsxs10(Text11, { children: [
5017
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.primary, children: "[\u2191] [\u2193]" }),
5018
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.dim, children: " move" })
5220
+ /* @__PURE__ */ jsxs11(Box11, { gap: 2, children: [
5221
+ /* @__PURE__ */ jsxs11(Text12, { children: [
5222
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.primary, children: "[\u2191] [\u2193]" }),
5223
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.dim, children: " move" })
5019
5224
  ] }),
5020
- /* @__PURE__ */ jsxs10(Text11, { children: [
5021
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.primary, children: "[enter]" }),
5022
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.dim, children: " confirm" })
5225
+ /* @__PURE__ */ jsxs11(Text12, { children: [
5226
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.primary, children: "[enter]" }),
5227
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.dim, children: " confirm" })
5023
5228
  ] })
5024
5229
  ] })
5025
5230
  ] })
5026
5231
  }
5027
5232
  ),
5028
- /* @__PURE__ */ jsxs10(
5233
+ /* @__PURE__ */ jsxs11(
5029
5234
  Box11,
5030
5235
  {
5031
5236
  backgroundColor: COLORS.bg.sidebar,
@@ -5036,8 +5241,8 @@ function Welcome() {
5036
5241
  flexDirection: "column",
5037
5242
  justifyContent: "center",
5038
5243
  children: [
5039
- /* @__PURE__ */ jsx9(Text11, { color: COLORS.muted, children: "WHAT THIS WIZARD WILL DO" }),
5040
- sidebarItems.map((i, idx) => /* @__PURE__ */ jsx9(SidebarItem, { title: i.title, description: i.description }, idx))
5244
+ /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "WHAT THIS WIZARD WILL DO" }),
5245
+ sidebarItems.map((i, idx) => /* @__PURE__ */ jsx10(SidebarItem, { title: i.title, description: i.description }, idx))
5041
5246
  ]
5042
5247
  }
5043
5248
  )
@@ -5046,7 +5251,7 @@ function Welcome() {
5046
5251
 
5047
5252
  // src/ui/LearnMore.tsx
5048
5253
  import { Fragment } from "react";
5049
- import { Box as Box12, Text as Text12, useInput as useInput5, useWindowSize as useWindowSize6 } from "ink";
5254
+ import { Box as Box12, Text as Text13, useInput as useInput6, useWindowSize as useWindowSize6 } from "ink";
5050
5255
 
5051
5256
  // src/ui/copy/learn-more.ts
5052
5257
  var accessIntro = "Everything runs locally on your machine. Nothing is written or sent without an explicit yes from you.";
@@ -5088,7 +5293,7 @@ var policyLinks = [
5088
5293
  ];
5089
5294
 
5090
5295
  // src/ui/LearnMore.tsx
5091
- import { jsx as jsx10, jsxs as jsxs11 } from "react/jsx-runtime";
5296
+ import { jsx as jsx11, jsxs as jsxs12 } from "react/jsx-runtime";
5092
5297
  var TAG_COLORS = {
5093
5298
  READ: COLORS.success,
5094
5299
  WRITE: COLORS.badge,
@@ -5105,12 +5310,12 @@ function NeverLine({
5105
5310
  }) {
5106
5311
  const used = segments.reduce((n, s) => n + s.text.length, 0);
5107
5312
  const rightPad = Math.max(0, width - 2 - NEVER_BOX_PAD_X - used);
5108
- return /* @__PURE__ */ jsxs11(Text12, { color: COLORS.primary, children: [
5109
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.danger, children: "\u2502" }),
5313
+ return /* @__PURE__ */ jsxs12(Text13, { color: COLORS.primary, children: [
5314
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.danger, children: "\u2502" }),
5110
5315
  " ".repeat(NEVER_BOX_PAD_X),
5111
- segments.map((s, i) => /* @__PURE__ */ jsx10(Text12, { color: s.color, bold: s.bold, children: s.text }, i)),
5316
+ segments.map((s, i) => /* @__PURE__ */ jsx11(Text13, { color: s.color, bold: s.bold, children: s.text }, i)),
5112
5317
  " ".repeat(rightPad),
5113
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.danger, children: "\u2502" })
5318
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.danger, children: "\u2502" })
5114
5319
  ] });
5115
5320
  }
5116
5321
  function LearnMore() {
@@ -5118,11 +5323,11 @@ function LearnMore() {
5118
5323
  const backToHome = useWizard((s) => s.backToHome);
5119
5324
  const { columns } = useWindowSize6();
5120
5325
  const dividerWidth = Math.max(0, columns - PADDING_X * 2);
5121
- useInput5((_input, key) => {
5326
+ useInput6((_input, key) => {
5122
5327
  if (key.escape) backToHome();
5123
5328
  else if (key.return) confirmStart();
5124
5329
  });
5125
- return /* @__PURE__ */ jsxs11(
5330
+ return /* @__PURE__ */ jsxs12(
5126
5331
  Box12,
5127
5332
  {
5128
5333
  flexDirection: "column",
@@ -5131,31 +5336,31 @@ function LearnMore() {
5131
5336
  width: "100%",
5132
5337
  gap: 1,
5133
5338
  children: [
5134
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.strong, bold: true, children: "What algolia wizard accesses" }),
5135
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: accessIntro }),
5136
- /* @__PURE__ */ jsx10(Box12, { flexDirection: "column", children: accessItems.map((item) => /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", marginTop: 1, children: [
5137
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.border, children: "\u2500".repeat(dividerWidth) }),
5138
- /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, marginTop: 1, children: [
5139
- /* @__PURE__ */ jsx10(Box12, { width: TAG_COLUMN_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx10(Text12, { color: TAG_COLORS[item.tag], bold: true, children: `[${item.tag}]` }) }),
5140
- /* @__PURE__ */ jsx10(Box12, { flexDirection: "column", children: /* @__PURE__ */ jsxs11(Text12, { color: COLORS.primary, children: [
5141
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.strong, bold: true, children: item.title }),
5142
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: ` \u2014 ${item.description}` })
5339
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.strong, bold: true, children: "What algolia wizard accesses" }),
5340
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: accessIntro }),
5341
+ /* @__PURE__ */ jsx11(Box12, { flexDirection: "column", children: accessItems.map((item) => /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", marginTop: 1, children: [
5342
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.border, children: "\u2500".repeat(dividerWidth) }),
5343
+ /* @__PURE__ */ jsxs12(Box12, { flexDirection: "row", gap: 1, marginTop: 1, children: [
5344
+ /* @__PURE__ */ jsx11(Box12, { width: TAG_COLUMN_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx11(Text13, { color: TAG_COLORS[item.tag], bold: true, children: `[${item.tag}]` }) }),
5345
+ /* @__PURE__ */ jsx11(Box12, { flexDirection: "column", children: /* @__PURE__ */ jsxs12(Text13, { color: COLORS.primary, children: [
5346
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.strong, bold: true, children: item.title }),
5347
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: ` \u2014 ${item.description}` })
5143
5348
  ] }) })
5144
5349
  ] })
5145
5350
  ] }, item.tag)) }),
5146
- /* @__PURE__ */ jsxs11(Box12, { marginTop: 1, flexDirection: "column", children: [
5147
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.danger, children: `\u256D${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256E` }),
5148
- /* @__PURE__ */ jsx10(NeverLine, { width: dividerWidth }),
5149
- /* @__PURE__ */ jsx10(
5351
+ /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
5352
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.danger, children: `\u256D${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256E` }),
5353
+ /* @__PURE__ */ jsx11(NeverLine, { width: dividerWidth }),
5354
+ /* @__PURE__ */ jsx11(
5150
5355
  NeverLine,
5151
5356
  {
5152
5357
  width: dividerWidth,
5153
5358
  segments: [{ text: "I NEVER", color: COLORS.danger, bold: true }]
5154
5359
  }
5155
5360
  ),
5156
- neverItems.map((item) => /* @__PURE__ */ jsxs11(Fragment, { children: [
5157
- /* @__PURE__ */ jsx10(NeverLine, { width: dividerWidth }),
5158
- /* @__PURE__ */ jsx10(
5361
+ neverItems.map((item) => /* @__PURE__ */ jsxs12(Fragment, { children: [
5362
+ /* @__PURE__ */ jsx11(NeverLine, { width: dividerWidth }),
5363
+ /* @__PURE__ */ jsx11(
5159
5364
  NeverLine,
5160
5365
  {
5161
5366
  width: dividerWidth,
@@ -5167,24 +5372,24 @@ function LearnMore() {
5167
5372
  }
5168
5373
  )
5169
5374
  ] }, item)),
5170
- /* @__PURE__ */ jsx10(NeverLine, { width: dividerWidth }),
5171
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.danger, children: `\u2570${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256F` })
5375
+ /* @__PURE__ */ jsx11(NeverLine, { width: dividerWidth }),
5376
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.danger, children: `\u2570${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256F` })
5172
5377
  ] }),
5173
- /* @__PURE__ */ jsx10(Box12, { marginTop: 1, flexDirection: "column", children: policyLinks.map((link) => /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, children: [
5174
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.strong, bold: true, children: `${link.label}:` }),
5175
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.accent, children: link.url })
5378
+ /* @__PURE__ */ jsx11(Box12, { marginTop: 1, flexDirection: "column", children: policyLinks.map((link) => /* @__PURE__ */ jsxs12(Box12, { flexDirection: "row", gap: 1, children: [
5379
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.strong, bold: true, children: `${link.label}:` }),
5380
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.accent, children: link.url })
5176
5381
  ] }, link.label)) }),
5177
- /* @__PURE__ */ jsxs11(Box12, { marginTop: 1, flexDirection: "row", gap: 3, children: [
5178
- /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, children: [
5179
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "[" }),
5180
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.primary, children: "esc" }),
5181
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "] back" })
5382
+ /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "row", gap: 3, children: [
5383
+ /* @__PURE__ */ jsxs12(Box12, { flexDirection: "row", gap: 1, children: [
5384
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: "[" }),
5385
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.primary, children: "esc" }),
5386
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: "] back" })
5182
5387
  ] }),
5183
- /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, children: [
5184
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "[" }),
5185
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.primary, children: "enter" }),
5186
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "]" }),
5187
- /* @__PURE__ */ jsx10(Text12, { color: COLORS.success, bold: true, children: "start wizard" })
5388
+ /* @__PURE__ */ jsxs12(Box12, { flexDirection: "row", gap: 1, children: [
5389
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: "[" }),
5390
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.primary, children: "enter" }),
5391
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: "]" }),
5392
+ /* @__PURE__ */ jsx11(Text13, { color: COLORS.success, bold: true, children: "start wizard" })
5188
5393
  ] })
5189
5394
  ] })
5190
5395
  ]
@@ -5193,17 +5398,17 @@ function LearnMore() {
5193
5398
  }
5194
5399
 
5195
5400
  // src/ui/Sidebar.tsx
5196
- import { Box as Box15, Text as Text15 } from "ink";
5401
+ import { Box as Box15, Text as Text16 } from "ink";
5197
5402
 
5198
5403
  // src/ui/Steps.tsx
5199
- import { Box as Box13, Text as Text13 } from "ink";
5404
+ import { Box as Box13, Text as Text14 } from "ink";
5200
5405
  import Spinner2 from "ink-spinner";
5201
- import { jsx as jsx11, jsxs as jsxs12 } from "react/jsx-runtime";
5406
+ import { jsx as jsx12, jsxs as jsxs13 } from "react/jsx-runtime";
5202
5407
  function Steps() {
5203
5408
  const { steps } = useWizard();
5204
5409
  const visibleSteps = steps.filter(isStepVisible);
5205
- 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: [
5206
- s.status === "running" ? /* @__PURE__ */ jsx11(Spinner2, { type: "dots" }) : MARKER[s.status],
5410
+ 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: [
5411
+ s.status === "running" ? /* @__PURE__ */ jsx12(Spinner2, { type: "dots" }) : MARKER[s.status],
5207
5412
  " ",
5208
5413
  s.title
5209
5414
  ] }) }, s.id)) });
@@ -5212,27 +5417,27 @@ function CurrentStep() {
5212
5417
  const { steps } = useWizard();
5213
5418
  const currentStep = steps.filter(isStepVisible).find((s) => s.status === "running");
5214
5419
  if (!currentStep) return null;
5215
- return /* @__PURE__ */ jsxs12(Text13, { color: COLORS.status.running, children: [
5216
- /* @__PURE__ */ jsx11(Spinner2, { type: "dots" }),
5420
+ return /* @__PURE__ */ jsxs13(Text14, { color: COLORS.status.running, children: [
5421
+ /* @__PURE__ */ jsx12(Spinner2, { type: "dots" }),
5217
5422
  " ",
5218
5423
  ` ${currentStep.title}`
5219
5424
  ] });
5220
5425
  }
5221
5426
 
5222
5427
  // src/ui/Progress.tsx
5223
- import { Box as Box14, Text as Text14 } from "ink";
5224
- import { jsx as jsx12, jsxs as jsxs13 } from "react/jsx-runtime";
5428
+ import { Box as Box14, Text as Text15 } from "ink";
5429
+ import { jsx as jsx13, jsxs as jsxs14 } from "react/jsx-runtime";
5225
5430
  function Progress() {
5226
5431
  const { steps, currentStepIndex } = useWizard();
5227
5432
  const visibleSteps = steps.filter(isStepVisible);
5228
5433
  if (visibleSteps.length === 0) return null;
5229
5434
  const visibleCountThroughCurrent = steps.slice(0, currentStepIndex + 1).filter(isStepVisible).length;
5230
5435
  const activeStepNumber = Math.max(1, visibleCountThroughCurrent);
5231
- return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "row", gap: 1, children: [
5232
- /* @__PURE__ */ jsx12(Text14, { color: COLORS.muted, children: "STEP" }),
5233
- /* @__PURE__ */ jsx12(Text14, { color: COLORS.strong, bold: true, children: activeStepNumber }),
5234
- /* @__PURE__ */ jsx12(Text14, { color: COLORS.strong, bold: true, children: "/" }),
5235
- /* @__PURE__ */ jsx12(Text14, { color: COLORS.strong, bold: true, children: visibleSteps.length })
5436
+ return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "row", gap: 1, children: [
5437
+ /* @__PURE__ */ jsx13(Text15, { color: COLORS.muted, children: "STEP" }),
5438
+ /* @__PURE__ */ jsx13(Text15, { color: COLORS.strong, bold: true, children: activeStepNumber }),
5439
+ /* @__PURE__ */ jsx13(Text15, { color: COLORS.strong, bold: true, children: "/" }),
5440
+ /* @__PURE__ */ jsx13(Text15, { color: COLORS.strong, bold: true, children: visibleSteps.length })
5236
5441
  ] });
5237
5442
  }
5238
5443
 
@@ -5243,9 +5448,9 @@ var sidebarCommands = [
5243
5448
  ];
5244
5449
 
5245
5450
  // src/ui/Sidebar.tsx
5246
- import { jsx as jsx13, jsxs as jsxs14 } from "react/jsx-runtime";
5451
+ import { jsx as jsx14, jsxs as jsxs15 } from "react/jsx-runtime";
5247
5452
  function Sidebar() {
5248
- return /* @__PURE__ */ jsxs14(
5453
+ return /* @__PURE__ */ jsxs15(
5249
5454
  Box15,
5250
5455
  {
5251
5456
  backgroundColor: "#14171E",
@@ -5255,16 +5460,16 @@ function Sidebar() {
5255
5460
  flexDirection: "column",
5256
5461
  justifyContent: "space-between",
5257
5462
  children: [
5258
- /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", gap: 1, children: [
5259
- /* @__PURE__ */ jsx13(Text15, { color: COLORS.muted, children: "PROGRESS" }),
5260
- /* @__PURE__ */ jsx13(Steps, {})
5463
+ /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", gap: 1, children: [
5464
+ /* @__PURE__ */ jsx14(Text16, { color: COLORS.muted, children: "PROGRESS" }),
5465
+ /* @__PURE__ */ jsx14(Steps, {})
5261
5466
  ] }),
5262
- /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", gap: 1, children: [
5263
- /* @__PURE__ */ jsx13(Progress, {}),
5264
- /* @__PURE__ */ jsx13(Box15, { flexDirection: "column", children: sidebarCommands.map((c) => {
5265
- return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "row", gap: 1, children: [
5266
- /* @__PURE__ */ jsx13(Text15, { color: COLORS.primary, children: `[${c.keyHint}]` }),
5267
- /* @__PURE__ */ jsx13(Text15, { color: COLORS.muted, children: c.description })
5467
+ /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", gap: 1, children: [
5468
+ /* @__PURE__ */ jsx14(Progress, {}),
5469
+ /* @__PURE__ */ jsx14(Box15, { flexDirection: "column", children: sidebarCommands.map((c) => {
5470
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "row", gap: 1, children: [
5471
+ /* @__PURE__ */ jsx14(Text16, { color: COLORS.primary, children: `[${c.keyHint}]` }),
5472
+ /* @__PURE__ */ jsx14(Text16, { color: COLORS.muted, children: c.description })
5268
5473
  ] }, c.keyHint);
5269
5474
  }) })
5270
5475
  ] })
@@ -5274,11 +5479,11 @@ function Sidebar() {
5274
5479
  }
5275
5480
 
5276
5481
  // src/ui/Ribbon.tsx
5277
- import { Box as Box16, Text as Text16 } from "ink";
5278
- import { jsx as jsx14, jsxs as jsxs15 } from "react/jsx-runtime";
5482
+ import { Box as Box16, Text as Text17 } from "ink";
5483
+ import { jsx as jsx15, jsxs as jsxs16 } from "react/jsx-runtime";
5279
5484
  function Ribbon() {
5280
5485
  const firstCommand = sidebarCommands[0];
5281
- return /* @__PURE__ */ jsxs15(
5486
+ return /* @__PURE__ */ jsxs16(
5282
5487
  Box16,
5283
5488
  {
5284
5489
  backgroundColor: "#14171E",
@@ -5287,11 +5492,11 @@ function Ribbon() {
5287
5492
  paddingX: 2,
5288
5493
  paddingY: 1,
5289
5494
  children: [
5290
- /* @__PURE__ */ jsx14(Progress, {}),
5291
- /* @__PURE__ */ jsx14(CurrentStep, {}),
5292
- /* @__PURE__ */ jsxs15(Box16, { flexDirection: "row", gap: 1, children: [
5293
- /* @__PURE__ */ jsx14(Text16, { color: COLORS.primary, children: `[${firstCommand.keyHint}]` }),
5294
- /* @__PURE__ */ jsx14(Text16, { color: COLORS.muted, children: firstCommand.description })
5495
+ /* @__PURE__ */ jsx15(Progress, {}),
5496
+ /* @__PURE__ */ jsx15(CurrentStep, {}),
5497
+ /* @__PURE__ */ jsxs16(Box16, { flexDirection: "row", gap: 1, children: [
5498
+ /* @__PURE__ */ jsx15(Text17, { color: COLORS.primary, children: `[${firstCommand.keyHint}]` }),
5499
+ /* @__PURE__ */ jsx15(Text17, { color: COLORS.muted, children: firstCommand.description })
5295
5500
  ] })
5296
5501
  ]
5297
5502
  }
@@ -5299,11 +5504,11 @@ function Ribbon() {
5299
5504
  }
5300
5505
 
5301
5506
  // src/ui/App.tsx
5302
- import { useState as useState10 } from "react";
5507
+ import { useState as useState11 } from "react";
5303
5508
 
5304
5509
  // src/ui/Logs.tsx
5305
- import { Box as Box17, Text as Text17, useInput as useInput6 } from "ink";
5306
- import { jsx as jsx15, jsxs as jsxs16 } from "react/jsx-runtime";
5510
+ import { Box as Box17, Text as Text18, useInput as useInput7 } from "ink";
5511
+ import { jsx as jsx16, jsxs as jsxs17 } from "react/jsx-runtime";
5307
5512
  var KIND_COLOR = {
5308
5513
  tool: COLORS.primary,
5309
5514
  prompt: COLORS.badge
@@ -5334,14 +5539,14 @@ function formatTimestamp(ms) {
5334
5539
  function Logs() {
5335
5540
  const logs = useWizard((s) => s.logs);
5336
5541
  const scroll = useScrollWindow({ itemCount: logs.length, followBottom: true });
5337
- useInput6((_input, key) => {
5542
+ useInput7((_input, key) => {
5338
5543
  if (key.upArrow) scroll.scrollBy(-1);
5339
5544
  else if (key.downArrow) scroll.scrollBy(1);
5340
5545
  });
5341
5546
  const visible = logs.slice(scroll.offset, scroll.offset + scroll.capacity);
5342
- return /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", paddingX: 4, paddingY: 2, flexGrow: 1, children: [
5343
- logs.length === 0 && /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, children: "No logs yet." }),
5344
- /* @__PURE__ */ jsx15(ScrollView, { scroll, children: visible.map((entry) => {
5547
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", paddingX: 4, paddingY: 2, flexGrow: 1, children: [
5548
+ logs.length === 0 && /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, children: "No logs yet." }),
5549
+ /* @__PURE__ */ jsx16(ScrollView, { scroll, children: visible.map((entry) => {
5345
5550
  const timestamp = `[${formatTimestamp(entry.startedAt)}]`;
5346
5551
  const durationText = entry.kind === "tool" && entry.durationMs !== void 0 ? `${entry.durationMs}ms` : "";
5347
5552
  const rawPreview = rawInputText(entry.input);
@@ -5351,25 +5556,25 @@ function Logs() {
5351
5556
  const name = truncate3(entry.name, budget);
5352
5557
  budget -= name.length;
5353
5558
  const preview = rawPreview ? truncate3(rawPreview, budget) : "";
5354
- return /* @__PURE__ */ jsxs16(Box17, { flexDirection: "row", gap: ROW_GAP, children: [
5355
- /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, children: timestamp }),
5356
- /* @__PURE__ */ jsx15(Text17, { color: logNameColor(entry), wrap: "truncate", children: name }),
5357
- preview && /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, wrap: "truncate", children: preview }),
5358
- durationText && /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, children: durationText })
5559
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "row", gap: ROW_GAP, children: [
5560
+ /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, children: timestamp }),
5561
+ /* @__PURE__ */ jsx16(Text18, { color: logNameColor(entry), wrap: "truncate", children: name }),
5562
+ preview && /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, wrap: "truncate", children: preview }),
5563
+ durationText && /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, children: durationText })
5359
5564
  ] }, entry.id);
5360
5565
  }) }),
5361
- /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, children: "\u2191/\u2193 scroll" })
5566
+ /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, children: "\u2191/\u2193 scroll" })
5362
5567
  ] });
5363
5568
  }
5364
5569
 
5365
5570
  // src/ui/Tips.tsx
5366
- import { useEffect as useEffect3, useRef as useRef4, useState as useState9 } from "react";
5367
- import { Box as Box19, Text as Text19 } from "ink";
5571
+ import { useEffect as useEffect3, useRef as useRef4, useState as useState10 } from "react";
5572
+ import { Box as Box19, Text as Text20 } from "ink";
5368
5573
  import terminalLink from "terminal-link";
5369
5574
 
5370
5575
  // src/ui/Code.tsx
5371
- import { Box as Box18, Text as Text18 } from "ink";
5372
- import { jsx as jsx16 } from "react/jsx-runtime";
5576
+ import { Box as Box18, Text as Text19 } from "ink";
5577
+ import { jsx as jsx17 } from "react/jsx-runtime";
5373
5578
  var TOKEN_RE = /("(?:\\.|[^"\\])*"|\btrue\b|\bfalse\b|\bnull\b|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|[{}[\]:,])/g;
5374
5579
  function highlightJson(json) {
5375
5580
  const parts = json.split(TOKEN_RE);
@@ -5378,22 +5583,22 @@ function highlightJson(json) {
5378
5583
  if (part[0] === '"') {
5379
5584
  const next = parts.slice(i + 1).find((p) => p.trim());
5380
5585
  const isKey = next?.trimStart().startsWith(":");
5381
- return /* @__PURE__ */ jsx16(Text18, { color: isKey ? "cyan" : "green", children: part }, i);
5586
+ return /* @__PURE__ */ jsx17(Text19, { color: isKey ? "cyan" : "green", children: part }, i);
5382
5587
  }
5383
5588
  if (part === "true" || part === "false" || part === "null") {
5384
- return /* @__PURE__ */ jsx16(Text18, { color: "magenta", children: part }, i);
5589
+ return /* @__PURE__ */ jsx17(Text19, { color: "magenta", children: part }, i);
5385
5590
  }
5386
5591
  if (/^-?\d/.test(part)) {
5387
- return /* @__PURE__ */ jsx16(Text18, { color: "yellow", children: part }, i);
5592
+ return /* @__PURE__ */ jsx17(Text19, { color: "yellow", children: part }, i);
5388
5593
  }
5389
5594
  if (/^[{}[\]:,]$/.test(part)) {
5390
- return /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, children: part }, i);
5595
+ return /* @__PURE__ */ jsx17(Text19, { color: COLORS.dim, children: part }, i);
5391
5596
  }
5392
- return /* @__PURE__ */ jsx16(Text18, { children: part }, i);
5597
+ return /* @__PURE__ */ jsx17(Text19, { children: part }, i);
5393
5598
  });
5394
5599
  }
5395
5600
  function Code({ children }) {
5396
- return /* @__PURE__ */ jsx16(Box18, { children: /* @__PURE__ */ jsx16(Text18, { children: highlightJson(children) }) });
5601
+ return /* @__PURE__ */ jsx17(Box18, { children: /* @__PURE__ */ jsx17(Text19, { children: highlightJson(children) }) });
5397
5602
  }
5398
5603
 
5399
5604
  // src/ui/copy/tips.ts
@@ -5607,26 +5812,26 @@ function tipsByIds(ids) {
5607
5812
  }
5608
5813
 
5609
5814
  // src/ui/Tips.tsx
5610
- import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
5815
+ import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
5611
5816
  var TICK_MS = 16;
5612
5817
  var CHUNK_HOLD_MS = 2e3;
5613
5818
  var HOLD_MS = 12e3;
5614
5819
  function TipTitle({ children }) {
5615
- return /* @__PURE__ */ jsxs17(Box19, { gap: 1, children: [
5616
- /* @__PURE__ */ jsx17(Text19, { color: "cyan", children: "\u2726" }),
5617
- /* @__PURE__ */ jsx17(Text19, { color: "white", bold: true, children })
5820
+ return /* @__PURE__ */ jsxs18(Box19, { gap: 1, children: [
5821
+ /* @__PURE__ */ jsx18(Text20, { color: "cyan", children: "\u2726" }),
5822
+ /* @__PURE__ */ jsx18(Text20, { color: "white", bold: true, children })
5618
5823
  ] });
5619
5824
  }
5620
5825
  function InlineSegment({ segment }) {
5621
5826
  switch (segment.type) {
5622
5827
  case "highlight":
5623
- return /* @__PURE__ */ jsx17(Text19, { color: COLORS.success, children: segment.value });
5828
+ return /* @__PURE__ */ jsx18(Text20, { color: COLORS.success, children: segment.value });
5624
5829
  case "link":
5625
- return /* @__PURE__ */ jsx17(Text19, { color: "cyan", underline: true, children: segment.href ? terminalLink(segment.value, segment.href) : segment.value });
5830
+ return /* @__PURE__ */ jsx18(Text20, { color: "cyan", underline: true, children: segment.href ? terminalLink(segment.value, segment.href) : segment.value });
5626
5831
  case "codeword":
5627
- return /* @__PURE__ */ jsx17(Text19, { color: COLORS.highlight.fg, backgroundColor: COLORS.highlight.bg, children: segment.value });
5832
+ return /* @__PURE__ */ jsx18(Text20, { color: COLORS.highlight.fg, backgroundColor: COLORS.highlight.bg, children: segment.value });
5628
5833
  default:
5629
- return /* @__PURE__ */ jsx17(Text19, { color: COLORS.muted, children: segment.value });
5834
+ return /* @__PURE__ */ jsx18(Text20, { color: COLORS.muted, children: segment.value });
5630
5835
  }
5631
5836
  }
5632
5837
  function TipContent({
@@ -5660,10 +5865,10 @@ function TipContent({
5660
5865
  blocks.push({ type: "inline", segments: [segment] });
5661
5866
  }
5662
5867
  }
5663
- return /* @__PURE__ */ jsx17(Box19, { flexDirection: "column", marginLeft: 2, gap: 1, children: blocks.map(
5664
- (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: [
5868
+ return /* @__PURE__ */ jsx18(Box19, { flexDirection: "column", marginLeft: 2, gap: 1, children: blocks.map(
5869
+ (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: [
5665
5870
  j > 0 && " ",
5666
- /* @__PURE__ */ jsx17(InlineSegment, { segment })
5871
+ /* @__PURE__ */ jsx18(InlineSegment, { segment })
5667
5872
  ] }, j)) }, i)
5668
5873
  ) });
5669
5874
  }
@@ -5680,8 +5885,8 @@ function Tips({
5680
5885
  progress.tipIndex = 0;
5681
5886
  progress.revealed = 0;
5682
5887
  }
5683
- const [tipIndex, setTipIndex] = useState9(resuming ? progress.tipIndex : 0);
5684
- const [revealed, setRevealed] = useState9(resuming ? progress.revealed : 0);
5888
+ const [tipIndex, setTipIndex] = useState10(resuming ? progress.tipIndex : 0);
5889
+ const [revealed, setRevealed] = useState10(resuming ? progress.revealed : 0);
5685
5890
  const tip = tips2.length > 0 ? tips2[tipIndex % tips2.length] : void 0;
5686
5891
  const contentLength = tip?.chunks.reduce((sum, c) => sum + c.value.length, 0) ?? 0;
5687
5892
  const totalLength = (tip?.title.length ?? 0) + contentLength;
@@ -5740,14 +5945,14 @@ function Tips({
5740
5945
  if (!tip) return null;
5741
5946
  const titleRevealed = tip.title.slice(0, revealed);
5742
5947
  const contentRevealed = Math.max(0, revealed - tip.title.length);
5743
- return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", marginBottom: 1, gap: 1, children: [
5744
- /* @__PURE__ */ jsx17(TipTitle, { children: titleRevealed }),
5745
- /* @__PURE__ */ jsx17(TipContent, { chunks: tip.chunks, revealed: contentRevealed })
5948
+ return /* @__PURE__ */ jsxs18(Box19, { flexDirection: "column", marginBottom: 1, gap: 1, children: [
5949
+ /* @__PURE__ */ jsx18(TipTitle, { children: titleRevealed }),
5950
+ /* @__PURE__ */ jsx18(TipContent, { chunks: tip.chunks, revealed: contentRevealed })
5746
5951
  ] });
5747
5952
  }
5748
5953
 
5749
5954
  // src/ui/App.tsx
5750
- import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
5955
+ import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
5751
5956
  function App() {
5752
5957
  const {
5753
5958
  phase,
@@ -5763,8 +5968,8 @@ function App() {
5763
5968
  } = useWizard();
5764
5969
  const { exit } = useApp();
5765
5970
  const { columns, rows } = useWindowSize7();
5766
- const [showLogs, setShowLogs] = useState10(false);
5767
- const [tipState, setTipState] = useState10("idle");
5971
+ const [showLogs, setShowLogs] = useState11(false);
5972
+ const [tipState, setTipState] = useState11("idle");
5768
5973
  const finished = phase === "done" || phase === "error";
5769
5974
  const currentStep = steps[currentStepIndex];
5770
5975
  const stepDef = workflow ? getWorkflow(workflow.id)?.steps.find((s) => s.id === currentStep?.id) : void 0;
@@ -5777,7 +5982,7 @@ function App() {
5777
5982
  const showTips = stepHasTips && (phase === "running" && currentStep?.status === "running" || isCommandApprovalPrompt || holdForTip);
5778
5983
  const showNoticesInMain = !stepHasTips;
5779
5984
  const showNotices = (!isAwaitingUserInput || holdForTip) && !review2;
5780
- useInput7(
5985
+ useInput8(
5781
5986
  (_input, key) => {
5782
5987
  if (key.return) {
5783
5988
  exit();
@@ -5785,7 +5990,7 @@ function App() {
5785
5990
  },
5786
5991
  { isActive: finished }
5787
5992
  );
5788
- useInput7((_input, key) => {
5993
+ useInput8((_input, key) => {
5789
5994
  if (phase === "idle" || phase === "authenticating") return;
5790
5995
  if (key.tab) {
5791
5996
  setShowLogs(!showLogs);
@@ -5797,7 +6002,7 @@ function App() {
5797
6002
  }
5798
6003
  });
5799
6004
  const escOwnedElsewhere = phase === "idle" || phase === "authenticating" || phase === "awaitingInput" && !holdForTip && (inputReq?.promptType === "enterToContinue" || inputReq?.promptType === "commandApproval");
5800
- useInput7((_input, key) => {
6005
+ useInput8((_input, key) => {
5801
6006
  if (escOwnedElsewhere) return;
5802
6007
  if (key.escape) {
5803
6008
  track("AI Wizard Interaction", {
@@ -5816,7 +6021,7 @@ function App() {
5816
6021
  /* Clamped to exactly the viewport: a taller frame makes Ink clear and repaint
5817
6022
  the whole screen, and the scrolling throws off its cursor arithmetic —
5818
6023
  flicker and leftover rows. */
5819
- /* @__PURE__ */ jsxs18(
6024
+ /* @__PURE__ */ jsxs19(
5820
6025
  Box20,
5821
6026
  {
5822
6027
  backgroundColor: COLORS.bg.main,
@@ -5825,7 +6030,7 @@ function App() {
5825
6030
  height: scrollsPastViewport ? void 0 : rows,
5826
6031
  overflow: scrollsPastViewport ? "visible" : "hidden",
5827
6032
  children: [
5828
- mainWindowVisible && /* @__PURE__ */ jsxs18(
6033
+ mainWindowVisible && /* @__PURE__ */ jsxs19(
5829
6034
  Box20,
5830
6035
  {
5831
6036
  flexDirection,
@@ -5833,7 +6038,7 @@ function App() {
5833
6038
  maxHeight: rows,
5834
6039
  justifyContent: "space-between",
5835
6040
  children: [
5836
- showLogs ? /* @__PURE__ */ jsx18(Logs, {}) : /* @__PURE__ */ jsxs18(
6041
+ showLogs ? /* @__PURE__ */ jsx19(Logs, {}) : /* @__PURE__ */ jsxs19(
5837
6042
  Box20,
5838
6043
  {
5839
6044
  flexDirection: "column",
@@ -5843,30 +6048,30 @@ function App() {
5843
6048
  flexGrow: 1,
5844
6049
  gap: 1,
5845
6050
  children: [
5846
- /* @__PURE__ */ jsxs18(Box20, { flexGrow: 2, flexDirection: "column", children: [
5847
- phase === "preflight" && !user && /* @__PURE__ */ jsx18(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
5848
- /* @__PURE__ */ jsx18(Spinner3, { type: "dots" }),
6051
+ /* @__PURE__ */ jsxs19(Box20, { flexGrow: 2, flexDirection: "column", children: [
6052
+ phase === "preflight" && !user && /* @__PURE__ */ jsx19(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs19(Text21, { color: COLORS.strong, bold: true, children: [
6053
+ /* @__PURE__ */ jsx19(Spinner3, { type: "dots" }),
5849
6054
  " Signing in to Algolia"
5850
6055
  ] }) }),
5851
- phase === "preflight" && user && /* @__PURE__ */ jsx18(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
5852
- /* @__PURE__ */ jsx18(Spinner3, { type: "dots" }),
6056
+ phase === "preflight" && user && /* @__PURE__ */ jsx19(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs19(Text21, { color: COLORS.strong, bold: true, children: [
6057
+ /* @__PURE__ */ jsx19(Spinner3, { type: "dots" }),
5853
6058
  " Getting things ready"
5854
6059
  ] }) }),
5855
- phase === "authenticating" && /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", marginBottom: 1, children: [
5856
- /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
5857
- /* @__PURE__ */ jsx18(Spinner3, { type: "dots" }),
6060
+ phase === "authenticating" && /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", marginBottom: 1, children: [
6061
+ /* @__PURE__ */ jsxs19(Text21, { color: COLORS.strong, bold: true, children: [
6062
+ /* @__PURE__ */ jsx19(Spinner3, { type: "dots" }),
5858
6063
  " Signing in to Algolia"
5859
6064
  ] }),
5860
- /* @__PURE__ */ jsx18(Text20, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
6065
+ /* @__PURE__ */ jsx19(Text21, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
5861
6066
  ] }),
5862
- settingUpAppId && /* @__PURE__ */ jsx18(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
5863
- /* @__PURE__ */ jsx18(Spinner3, { type: "dots" }),
6067
+ settingUpAppId && /* @__PURE__ */ jsx19(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs19(Text21, { color: COLORS.strong, bold: true, children: [
6068
+ /* @__PURE__ */ jsx19(Spinner3, { type: "dots" }),
5864
6069
  " Setting up Wizard using app",
5865
6070
  " ",
5866
6071
  settingUpAppId
5867
6072
  ] }) }),
5868
- /* @__PURE__ */ jsx18(CliOutput, {}),
5869
- showTips && currentStep && /* @__PURE__ */ jsx18(
6073
+ /* @__PURE__ */ jsx19(CliOutput, {}),
6074
+ showTips && currentStep && /* @__PURE__ */ jsx19(
5870
6075
  Tips,
5871
6076
  {
5872
6077
  stepId: currentStep.id,
@@ -5874,24 +6079,24 @@ function App() {
5874
6079
  onRevealStateChange: setTipState
5875
6080
  }
5876
6081
  ),
5877
- showNoticesInMain && showNotices && /* @__PURE__ */ jsx18(Notices, { showAll: true, border: false }),
5878
- /* @__PURE__ */ jsx18(Review, {}),
5879
- !showTips && /* @__PURE__ */ jsx18(PromptInput, {}),
5880
- phase === "error" && error && /* @__PURE__ */ jsx18(Box20, { marginTop: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.status.error, children: [
6082
+ showNoticesInMain && showNotices && /* @__PURE__ */ jsx19(Notices, { showAll: true, border: false }),
6083
+ /* @__PURE__ */ jsx19(Review, {}),
6084
+ !showTips && /* @__PURE__ */ jsx19(PromptInput, {}),
6085
+ phase === "error" && error && /* @__PURE__ */ jsx19(Box20, { marginTop: 1, children: /* @__PURE__ */ jsxs19(Text21, { color: COLORS.status.error, children: [
5881
6086
  "\u2716 ",
5882
6087
  error
5883
6088
  ] }) })
5884
6089
  ] }),
5885
- !showNoticesInMain && showNotices && /* @__PURE__ */ jsx18(Notices, {}),
5886
- showTips && !holdForTip && /* @__PURE__ */ jsx18(PromptInput, {})
6090
+ !showNoticesInMain && showNotices && /* @__PURE__ */ jsx19(Notices, {}),
6091
+ showTips && !holdForTip && /* @__PURE__ */ jsx19(PromptInput, {})
5887
6092
  ]
5888
6093
  }
5889
6094
  ),
5890
- showSidebar ? /* @__PURE__ */ jsx18(Sidebar, {}) : /* @__PURE__ */ jsx18(Ribbon, {})
6095
+ showSidebar ? /* @__PURE__ */ jsx19(Sidebar, {}) : /* @__PURE__ */ jsx19(Ribbon, {})
5891
6096
  ]
5892
6097
  }
5893
6098
  ),
5894
- phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */ jsx18(LearnMore, {}) : /* @__PURE__ */ jsx18(Welcome, {}))
6099
+ phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */ jsx19(LearnMore, {}) : /* @__PURE__ */ jsx19(Welcome, {}))
5895
6100
  ]
5896
6101
  }
5897
6102
  )
@@ -6071,6 +6276,9 @@ var search = {
6071
6276
  ]
6072
6277
  }
6073
6278
  };
6279
+ var selectPlaybook = {
6280
+ slug: "orders"
6281
+ };
6074
6282
  var review = {
6075
6283
  summaryPoints: [
6076
6284
  "Ingested 25 generated Product records into wizard_seed_products.",
@@ -6089,6 +6297,9 @@ var SEEDS = {
6089
6297
  "confirm-framework": confirmFramework2,
6090
6298
  search,
6091
6299
  review
6300
+ },
6301
+ playbook: {
6302
+ "select-playbook": selectPlaybook
6092
6303
  }
6093
6304
  };
6094
6305
  var SEED_USER_INPUTS = {
@@ -6097,6 +6308,9 @@ var SEED_USER_INPUTS = {
6097
6308
  confirmedEntities: confirmEntities2.confirmedEntities,
6098
6309
  ingestionAnalysis: confirmEntities2.ingestionAnalysis,
6099
6310
  implementation: "success"
6311
+ },
6312
+ playbook: {
6313
+ playbookSlug: selectPlaybook.slug
6100
6314
  }
6101
6315
  };
6102
6316
  function formatStepList(workflow, startIndex) {
@@ -6159,7 +6373,9 @@ async function seedWorkflowState(workflow, value) {
6159
6373
  if (!config.aiConsent) {
6160
6374
  config.aiConsent = true;
6161
6375
  await saveConfig(config);
6162
- messages.push("Seed: set aiConsent in the project config (skips the consent prompt).");
6376
+ messages.push(
6377
+ "Seed: set aiConsent in the project config (skips the consent prompt)."
6378
+ );
6163
6379
  }
6164
6380
  if (startIndex === 0) {
6165
6381
  await clearWorkflowState(workflow.id);
@@ -6185,55 +6401,6 @@ async function seedWorkflowState(workflow, value) {
6185
6401
  return { messages };
6186
6402
  }
6187
6403
 
6188
- // src/lib/cli.ts
6189
- var USAGE = `Usage: wizard [workflow-id] [options]
6190
-
6191
- Options:
6192
- --seed <step-id> Start the workflow at the step with this id, with earlier
6193
- steps pre-filled with test data. Pass with no value to print
6194
- the step ids. See CONTRIBUTING.md.
6195
- --no-telemetry Send no telemetry or analytics for this run.
6196
- --reset-on-run Wipe this project's wizard state (run state, AI consent)
6197
- before starting, so the run behaves like a first-ever
6198
- run. Also drops every API key the wizard has
6199
- stored in your keychain (or, where the platform has none,
6200
- the encrypted file it falls back to \u2014 see CONTRIBUTING.md),
6201
- for this project and any other, so later runs create new
6202
- ones. Your Algolia login is not touched.
6203
- -h, --help Print this message.`;
6204
- function parseCliArgs(argv) {
6205
- const positionals = [];
6206
- let seed;
6207
- let telemetry = true;
6208
- let resetOnRun = false;
6209
- let help = false;
6210
- for (let i = 0; i < argv.length; i++) {
6211
- const arg = argv[i];
6212
- if (arg === "--seed") {
6213
- const next = argv[i + 1];
6214
- if (next !== void 0 && !next.startsWith("-")) {
6215
- seed = next;
6216
- i++;
6217
- } else {
6218
- seed = null;
6219
- }
6220
- } else if (arg.startsWith("--seed=")) {
6221
- seed = arg.slice("--seed=".length);
6222
- } else if (arg === "--no-telemetry") {
6223
- telemetry = false;
6224
- } else if (arg === "--reset-on-run") {
6225
- resetOnRun = true;
6226
- } else if (arg === "--help" || arg === "-h") {
6227
- help = true;
6228
- } else if (arg.startsWith("-")) {
6229
- throw new Error(`Unknown option "${arg}".`);
6230
- } else {
6231
- positionals.push(arg);
6232
- }
6233
- }
6234
- return { positionals, seed, telemetry, resetOnRun, help };
6235
- }
6236
-
6237
6404
  // src/lib/resetState.ts
6238
6405
  import { readdir as readdir3, rm as rm2 } from "node:fs/promises";
6239
6406
  import { join as join13 } from "node:path";
@@ -6296,7 +6463,7 @@ function delay(ms) {
6296
6463
  }
6297
6464
 
6298
6465
  // src/main.tsx
6299
- import { jsx as jsx19 } from "react/jsx-runtime";
6466
+ import { jsx as jsx20 } from "react/jsx-runtime";
6300
6467
  async function startup() {
6301
6468
  setProjectRoot(process.cwd());
6302
6469
  let args;
@@ -6347,7 +6514,7 @@ ${formatStepList(workflow)}`);
6347
6514
  async function run(opts) {
6348
6515
  const { workflow, skipResumePrompt } = opts;
6349
6516
  const store = useWizard.getState();
6350
- const instance = render(/* @__PURE__ */ jsx19(App, {}), { incrementalRendering: true });
6517
+ const instance = render(/* @__PURE__ */ jsx20(App, {}), { incrementalRendering: true });
6351
6518
  await store.waitForStart();
6352
6519
  store.syncSteps(
6353
6520
  workflow.steps.map((s) => ({