@algolia/wizard 0.46.0-rc.136.345 → 0.46.0-rc.146.324

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 +419 -553
  2. package/package.json +1 -1
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 Box19, Text as Text19, useApp, useInput as useInput7, useWindowSize as useWindowSize8 } from "ink";
8
8
  import Spinner2 from "ink-spinner";
9
9
 
10
10
  // src/core/store.ts
@@ -239,9 +239,6 @@ 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
- }
245
242
  var useWizard = create((set, get) => ({
246
243
  phase: "idle",
247
244
  homeScreen: "home",
@@ -355,17 +352,10 @@ var useWizard = create((set, get) => ({
355
352
  setTargetIndex: (index) => set({ targetIndex: index }),
356
353
  recordWrittenFile: (path) => set((s) => ({ writtenFiles: [...s.writtenFiles, path] })),
357
354
  clearWrittenFiles: () => set({ writtenFiles: [] }),
358
- isCommandApproved: (command, cwd) => get().approvedCommands.has(commandApprovalKey(command, cwd)),
355
+ isCommandApproved: (command, cwd) => get().approvedCommands.has(`${cwd}\0${command}`),
359
356
  approveCommand: (command, cwd) => set((s) => ({
360
- approvedCommands: new Set(s.approvedCommands).add(
361
- commandApprovalKey(command, cwd)
362
- )
357
+ approvedCommands: new Set(s.approvedCommands).add(`${cwd}\0${command}`)
363
358
  })),
364
- revokeCommand: (command, cwd) => set((s) => {
365
- const approvedCommands = new Set(s.approvedCommands);
366
- approvedCommands.delete(commandApprovalKey(command, cwd));
367
- return { approvedCommands };
368
- }),
369
359
  logStart: (kind, name, input) => {
370
360
  const id = nanoid();
371
361
  set((s) => ({
@@ -509,23 +499,112 @@ function CliOutput() {
509
499
  }
510
500
 
511
501
  // src/ui/Notices.tsx
512
- import { Box as Box3, Text as Text3 } from "ink";
513
- import { useEffect as useEffect2, useState as useState2 } from "react";
502
+ import { Box as Box4, Text as Text4, useWindowSize as useWindowSize4 } from "ink";
503
+ import { useEffect as useEffect2, useState as useState3 } from "react";
514
504
 
515
- // src/ui/Table.tsx
505
+ // src/ui/ScrollView.tsx
516
506
  import { Box as Box2, Text as Text2, measureElement, useWindowSize as useWindowSize2 } from "ink";
517
- import { useEffect, useRef, useState } from "react";
507
+ import { useCallback, useLayoutEffect, useRef, useState } from "react";
508
+ import { jsxs as jsxs2 } from "react/jsx-runtime";
509
+ var INDICATOR_ROWS = 2;
510
+ function fittedWidth(node, columns) {
511
+ let left = 0;
512
+ for (let n = node; n; n = n.parentNode) {
513
+ left += n.yogaNode?.getComputedLeft() ?? 0;
514
+ }
515
+ return Math.max(Math.min(measureElement(node).width, columns - left), 0);
516
+ }
517
+ function useScrollWindow({
518
+ itemCount,
519
+ rowHeight = 1,
520
+ followBottom = false
521
+ }) {
522
+ const viewportRef = useRef(null);
523
+ const { columns } = useWindowSize2();
524
+ const [size, setSize] = useState(
525
+ null
526
+ );
527
+ useLayoutEffect(() => {
528
+ if (!viewportRef.current) return;
529
+ const width = fittedWidth(viewportRef.current, columns);
530
+ const { height } = measureElement(viewportRef.current);
531
+ setSize(
532
+ (prev) => prev?.width === width && prev.height === height ? prev : { width, height }
533
+ );
534
+ });
535
+ const capacity = size === null || itemCount * rowHeight <= size.height ? itemCount : Math.max(Math.floor((size.height - INDICATOR_ROWS) / rowHeight), 1);
536
+ const maxOffset = Math.max(itemCount - capacity, 0);
537
+ const [offset, setOffset] = useState(0);
538
+ const prevMaxOffsetRef = useRef(0);
539
+ useLayoutEffect(() => {
540
+ const wasAtBottom = offset >= prevMaxOffsetRef.current;
541
+ prevMaxOffsetRef.current = maxOffset;
542
+ setOffset(
543
+ (o) => followBottom && wasAtBottom ? maxOffset : Math.min(o, maxOffset)
544
+ );
545
+ }, [maxOffset, followBottom]);
546
+ const scrollBy = useCallback(
547
+ (delta) => {
548
+ setOffset((o) => Math.min(Math.max(o + delta, 0), maxOffset));
549
+ },
550
+ [maxOffset]
551
+ );
552
+ const revealIndex = useCallback(
553
+ (index) => {
554
+ setOffset((o) => {
555
+ if (index < o) return index;
556
+ if (index >= o + capacity) {
557
+ return Math.min(index - capacity + 1, maxOffset);
558
+ }
559
+ return o;
560
+ });
561
+ },
562
+ [capacity, maxOffset]
563
+ );
564
+ const visibleCount = Math.min(capacity, Math.max(itemCount - offset, 0));
565
+ return {
566
+ viewportRef,
567
+ measured: size !== null,
568
+ width: size?.width ?? columns,
569
+ offset,
570
+ capacity,
571
+ maxOffset,
572
+ hiddenAbove: Math.min(offset, itemCount),
573
+ hiddenBelow: Math.max(itemCount - offset - visibleCount, 0),
574
+ scrollBy,
575
+ revealIndex
576
+ };
577
+ }
578
+ function ScrollView({ scroll, children }) {
579
+ return /* @__PURE__ */ jsxs2(Box2, { ref: scroll.viewportRef, flexDirection: "column", flexGrow: 1, children: [
580
+ scroll.hiddenAbove > 0 && /* @__PURE__ */ jsxs2(Text2, { color: COLORS.dim, children: [
581
+ "\u2191 ",
582
+ scroll.hiddenAbove,
583
+ " more"
584
+ ] }),
585
+ children,
586
+ scroll.hiddenBelow > 0 && /* @__PURE__ */ jsxs2(Text2, { color: COLORS.dim, children: [
587
+ "\u2193 ",
588
+ scroll.hiddenBelow,
589
+ " more"
590
+ ] })
591
+ ] });
592
+ }
593
+
594
+ // src/ui/Table.tsx
595
+ import { Box as Box3, Text as Text3, measureElement as measureElement2, useWindowSize as useWindowSize3 } from "ink";
596
+ import { useEffect, useRef as useRef2, useState as useState2 } from "react";
518
597
  import { jsx } from "react/jsx-runtime";
519
598
  function Table({ columns, rows }) {
520
- const { columns: termCols } = useWindowSize2();
521
- const ref = useRef(null);
522
- const [width, setWidth] = useState(0);
599
+ const { columns: termCols } = useWindowSize3();
600
+ const ref = useRef2(null);
601
+ const [width, setWidth] = useState2(0);
523
602
  useEffect(() => {
524
- if (ref.current) setWidth(measureElement(ref.current).width);
603
+ if (ref.current) setWidth(measureElement2(ref.current).width);
525
604
  }, [termCols, columns, rows]);
526
605
  if (rows.length === 0) return null;
527
606
  const lines = formatTable(columns, rows, width || void 0);
528
- return /* @__PURE__ */ jsx(Box2, { flexDirection: "column", ref, children: lines.map((line, i) => /* @__PURE__ */ jsx(Text2, { color: COLORS.primary, wrap: "truncate", children: line }, `tbl-${i}`)) });
607
+ return /* @__PURE__ */ jsx(Box3, { flexDirection: "column", ref, children: lines.map((line, i) => /* @__PURE__ */ jsx(Text3, { color: COLORS.primary, wrap: "truncate", children: line }, `tbl-${i}`)) });
529
608
  }
530
609
  function formatTable(columns, rows, width) {
531
610
  const natural = columns.map(
@@ -566,7 +645,7 @@ function resize(widths, budget) {
566
645
  var truncate = (s, width) => s.length <= width ? s : width <= 1 ? s.slice(0, width) : `${s.slice(0, width - 1)}\u2026`;
567
646
 
568
647
  // src/ui/Notices.tsx
569
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
648
+ import { jsx as jsx2 } from "react/jsx-runtime";
570
649
  var AGENT_MARKER = "\u2726";
571
650
  var PULSE_STEPS = 12;
572
651
  var PULSE_STEP_MS = 150;
@@ -588,14 +667,48 @@ function parseHex(hex) {
588
667
  b: parseInt(n.slice(4, 6), 16)
589
668
  };
590
669
  }
670
+ function flattenRows(notices, width) {
671
+ const rows = [];
672
+ notices.forEach((notice, noticeIndex) => {
673
+ if (noticeIndex > 0 && notice.table) {
674
+ rows.push({ noticeIndex, text: " ", plain: true });
675
+ }
676
+ notice.messages?.forEach((m, j) => {
677
+ const line = typeof m === "string" ? { text: m } : m;
678
+ rows.push({
679
+ noticeIndex,
680
+ text: `${j === 0 ? `${AGENT_MARKER} ` : " "}${line.text}`,
681
+ color: line.color,
682
+ bold: line.bold
683
+ });
684
+ });
685
+ if (notice.table) {
686
+ for (const text of formatTable(
687
+ notice.table.columns,
688
+ notice.table.rows,
689
+ width
690
+ )) {
691
+ rows.push({ noticeIndex, text, plain: true });
692
+ }
693
+ }
694
+ });
695
+ return rows;
696
+ }
591
697
  function Notices({
592
698
  showAll = false,
593
699
  border = true
594
700
  } = {}) {
595
701
  const notices = useWizard((s) => s.notices);
596
- const latest = notices[notices.length - 1];
597
- const visible = showAll ? notices : latest ? [latest] : [];
598
- const [pulseStep, setPulseStep] = useState2(0);
702
+ const { columns } = useWindowSize4();
703
+ const latestIndex = notices.length - 1;
704
+ const visible = showAll ? notices : latestIndex >= 0 ? [notices[latestIndex]] : [];
705
+ const latestRowIndex = showAll ? latestIndex : 0;
706
+ const measuredRows = flattenRows(visible, columns);
707
+ const scroll = useScrollWindow({
708
+ itemCount: measuredRows.length,
709
+ followBottom: true
710
+ });
711
+ const [pulseStep, setPulseStep] = useState3(0);
599
712
  useEffect2(() => {
600
713
  let direction = 1;
601
714
  const id = setInterval(() => {
@@ -610,8 +723,10 @@ function Notices({
610
723
  }, []);
611
724
  if (visible.length === 0) return null;
612
725
  const pulseColor = PULSE_COLORS[pulseStep];
726
+ const rows = scroll.width === columns ? measuredRows : flattenRows(visible, scroll.width);
727
+ const windowed = rows.slice(scroll.offset, scroll.offset + scroll.capacity);
613
728
  return /* @__PURE__ */ jsx2(
614
- Box3,
729
+ Box4,
615
730
  {
616
731
  borderColor: border ? COLORS.border : void 0,
617
732
  borderStyle: border ? "single" : void 0,
@@ -621,26 +736,18 @@ function Notices({
621
736
  borderBottom: false,
622
737
  paddingTop: border ? 1 : 0,
623
738
  flexDirection: "column",
624
- gap: 1,
625
- children: visible.map((notice, i) => /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", children: [
626
- notice.messages?.map((m, j) => {
627
- const line = typeof m === "string" ? { text: m } : m;
628
- const prefix = j === 0 ? `${AGENT_MARKER} ` : " ";
629
- return /* @__PURE__ */ jsxs2(
630
- Text3,
631
- {
632
- color: !line.color ? notice === latest ? pulseColor : COLORS.dim : line.color ?? COLORS.dim,
633
- bold: line.bold,
634
- children: [
635
- prefix,
636
- line.text
637
- ]
638
- },
639
- `notice-line-${j}`
640
- );
641
- }),
642
- notice.table && /* @__PURE__ */ jsx2(Table, { columns: notice.table.columns, rows: notice.table.rows })
643
- ] }, `notice-${i}`))
739
+ flexGrow: 1,
740
+ minHeight: 0,
741
+ children: /* @__PURE__ */ jsx2(ScrollView, { scroll, children: windowed.map((row, i) => /* @__PURE__ */ jsx2(
742
+ Text4,
743
+ {
744
+ color: row.plain ? COLORS.primary : row.color ?? (row.noticeIndex === latestRowIndex ? pulseColor : COLORS.dim),
745
+ bold: row.bold,
746
+ wrap: "truncate",
747
+ children: row.text
748
+ },
749
+ `notice-row-${scroll.offset + i}`
750
+ )) })
644
751
  }
645
752
  );
646
753
  }
@@ -651,14 +758,14 @@ import TextInput from "ink-text-input";
651
758
  import { useState as useState6 } from "react";
652
759
 
653
760
  // src/ui/CommandApproval.tsx
654
- import { Box as Box6, Text as Text6 } from "ink";
761
+ import { Box as Box7, Text as Text7 } from "ink";
655
762
 
656
763
  // src/ui/DecisionSelect.tsx
657
- import { Box as Box5, Text as Text5, useInput } from "ink";
658
- import { useState as useState3 } from "react";
764
+ import { Box as Box6, Text as Text6, useInput } from "ink";
765
+ import { useState as useState4 } from "react";
659
766
 
660
767
  // src/ui/SelectRow.tsx
661
- import { Box as Box4, Text as Text4 } from "ink";
768
+ import { Box as Box5, Text as Text5 } from "ink";
662
769
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
663
770
  function SelectRow({
664
771
  highlighted,
@@ -671,15 +778,15 @@ function SelectRow({
671
778
  }) {
672
779
  const labelColor = highlighted ? highlightBackground ? COLORS.highlight.fg : COLORS.success : COLORS.primary;
673
780
  return /* @__PURE__ */ jsxs3(
674
- Box4,
781
+ Box5,
675
782
  {
676
783
  width,
677
784
  paddingX: usePadding ? 1 : 0,
678
785
  paddingY: usePadding ? 1 : 0,
679
786
  backgroundColor: highlighted && highlightBackground ? COLORS.highlight.bg : void 0,
680
787
  children: [
681
- /* @__PURE__ */ jsx3(Box4, { width: labelWidth, children: /* @__PURE__ */ jsxs3(
682
- Text4,
788
+ /* @__PURE__ */ jsx3(Box5, { width: labelWidth, children: /* @__PURE__ */ jsxs3(
789
+ Text5,
683
790
  {
684
791
  color: labelColor,
685
792
  bold: highlighted && !highlightBackground,
@@ -702,7 +809,7 @@ function DecisionSelect({
702
809
  actions,
703
810
  onDecide
704
811
  }) {
705
- const [index, setIndex] = useState3(0);
812
+ const [index, setIndex] = useState4(0);
706
813
  useInput((input, key) => {
707
814
  if (key.upArrow || input === "k") {
708
815
  setIndex((i) => (i - 1 + actions.length) % actions.length);
@@ -714,8 +821,8 @@ function DecisionSelect({
714
821
  onDecide(actions[1].value);
715
822
  }
716
823
  });
717
- return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", gap: 1, children: [
718
- /* @__PURE__ */ jsx4(Box5, { flexDirection: "column", children: actions.map((action, i) => /* @__PURE__ */ jsx4(
824
+ return /* @__PURE__ */ jsxs4(Box6, { flexDirection: "column", gap: 1, children: [
825
+ /* @__PURE__ */ jsx4(Box6, { flexDirection: "column", children: actions.map((action, i) => /* @__PURE__ */ jsx4(
719
826
  SelectRow,
720
827
  {
721
828
  highlighted: i === index,
@@ -724,14 +831,14 @@ function DecisionSelect({
724
831
  },
725
832
  action.label
726
833
  )) }),
727
- /* @__PURE__ */ jsxs4(Box5, { gap: 2, children: [
728
- /* @__PURE__ */ jsxs4(Text5, { children: [
729
- /* @__PURE__ */ jsx4(Text5, { color: COLORS.primary, children: "[\u2191] [\u2193]" }),
730
- /* @__PURE__ */ jsx4(Text5, { color: COLORS.dim, children: " move" })
834
+ /* @__PURE__ */ jsxs4(Box6, { gap: 2, children: [
835
+ /* @__PURE__ */ jsxs4(Text6, { children: [
836
+ /* @__PURE__ */ jsx4(Text6, { color: COLORS.primary, children: "[\u2191] [\u2193]" }),
837
+ /* @__PURE__ */ jsx4(Text6, { color: COLORS.dim, children: " move" })
731
838
  ] }),
732
- /* @__PURE__ */ jsxs4(Text5, { children: [
733
- /* @__PURE__ */ jsx4(Text5, { color: COLORS.primary, children: "[enter]" }),
734
- /* @__PURE__ */ jsx4(Text5, { color: COLORS.dim, children: " confirm" })
839
+ /* @__PURE__ */ jsxs4(Text6, { children: [
840
+ /* @__PURE__ */ jsx4(Text6, { color: COLORS.primary, children: "[enter]" }),
841
+ /* @__PURE__ */ jsx4(Text6, { color: COLORS.dim, children: " confirm" })
735
842
  ] })
736
843
  ] })
737
844
  ] });
@@ -741,14 +848,12 @@ function DecisionSelect({
741
848
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
742
849
  function CommandApproval({
743
850
  command,
744
- messages,
745
851
  onDecide
746
852
  }) {
747
- return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", gap: 1, children: [
748
- messages?.map((message, index) => /* @__PURE__ */ jsx5(Text6, { color: COLORS.muted, children: message }, `msg-${index}`)),
749
- /* @__PURE__ */ jsx5(Text6, { color: COLORS.primary, bold: true, children: "Run this command?" }),
853
+ return /* @__PURE__ */ jsxs5(Box7, { flexDirection: "column", gap: 1, children: [
854
+ /* @__PURE__ */ jsx5(Text7, { color: COLORS.primary, bold: true, children: "Run this command?" }),
750
855
  /* @__PURE__ */ jsxs5(
751
- Box6,
856
+ Box7,
752
857
  {
753
858
  flexDirection: "column",
754
859
  paddingLeft: 2,
@@ -759,17 +864,17 @@ function CommandApproval({
759
864
  borderRight: false,
760
865
  gap: 1,
761
866
  children: [
762
- /* @__PURE__ */ jsxs5(Box6, { children: [
763
- /* @__PURE__ */ jsx5(Text6, { color: COLORS.muted, children: "$ " }),
764
- /* @__PURE__ */ jsx5(Text6, { color: COLORS.strong, wrap: "wrap", children: command.command })
867
+ /* @__PURE__ */ jsxs5(Box7, { children: [
868
+ /* @__PURE__ */ jsx5(Text7, { color: COLORS.muted, children: "$ " }),
869
+ /* @__PURE__ */ jsx5(Text7, { color: COLORS.strong, wrap: "wrap", children: command.command })
765
870
  ] }),
766
- /* @__PURE__ */ jsxs5(Box6, { gap: 1, children: [
767
- /* @__PURE__ */ jsx5(Text6, { color: COLORS.muted, children: "in:" }),
768
- /* @__PURE__ */ jsx5(Text6, { color: COLORS.muted, wrap: "wrap", children: command.cwd })
871
+ /* @__PURE__ */ jsxs5(Box7, { gap: 1, children: [
872
+ /* @__PURE__ */ jsx5(Text7, { color: COLORS.muted, children: "in:" }),
873
+ /* @__PURE__ */ jsx5(Text7, { color: COLORS.muted, wrap: "wrap", children: command.cwd })
769
874
  ] }),
770
- command.explanation && /* @__PURE__ */ jsxs5(Box6, { gap: 1, children: [
771
- /* @__PURE__ */ jsx5(Text6, { color: COLORS.muted, children: "why:" }),
772
- /* @__PURE__ */ jsx5(Text6, { color: COLORS.accent, wrap: "wrap", children: command.explanation })
875
+ command.explanation && /* @__PURE__ */ jsxs5(Box7, { gap: 1, children: [
876
+ /* @__PURE__ */ jsx5(Text7, { color: COLORS.muted, children: "why:" }),
877
+ /* @__PURE__ */ jsx5(Text7, { color: COLORS.accent, wrap: "wrap", children: command.explanation })
773
878
  ] })
774
879
  ]
775
880
  }
@@ -788,100 +893,9 @@ function CommandApproval({
788
893
  }
789
894
 
790
895
  // src/ui/SelectPrompt.tsx
791
- import { Box as Box8, Text as Text8, useInput as useInput2, useWindowSize as useWindowSize4 } from "ink";
896
+ import { Box as Box8, Text as Text8, useInput as useInput2, useWindowSize as useWindowSize5 } from "ink";
792
897
  import { useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState5 } from "react";
793
-
794
- // src/ui/ScrollView.tsx
795
- import { Box as Box7, Text as Text7, measureElement as measureElement2, useWindowSize as useWindowSize3 } from "ink";
796
- import { useCallback, useLayoutEffect, useRef as useRef2, useState as useState4 } from "react";
797
- import { jsxs as jsxs6 } from "react/jsx-runtime";
798
- var INDICATOR_ROWS = 2;
799
- function fittedWidth(node, columns) {
800
- let left = 0;
801
- for (let n = node; n; n = n.parentNode) {
802
- left += n.yogaNode?.getComputedLeft() ?? 0;
803
- }
804
- return Math.max(Math.min(measureElement2(node).width, columns - left), 0);
805
- }
806
- function useScrollWindow({
807
- itemCount,
808
- rowHeight = 1,
809
- followBottom = false
810
- }) {
811
- const viewportRef = useRef2(null);
812
- const { columns } = useWindowSize3();
813
- const [size, setSize] = useState4(
814
- null
815
- );
816
- useLayoutEffect(() => {
817
- if (!viewportRef.current) return;
818
- const width = fittedWidth(viewportRef.current, columns);
819
- const { height } = measureElement2(viewportRef.current);
820
- setSize(
821
- (prev) => prev?.width === width && prev.height === height ? prev : { width, height }
822
- );
823
- });
824
- const capacity = size === null || itemCount * rowHeight <= size.height ? itemCount : Math.max(Math.floor((size.height - INDICATOR_ROWS) / rowHeight), 1);
825
- const maxOffset = Math.max(itemCount - capacity, 0);
826
- const [offset, setOffset] = useState4(0);
827
- const prevMaxOffsetRef = useRef2(0);
828
- useLayoutEffect(() => {
829
- const wasAtBottom = offset >= prevMaxOffsetRef.current;
830
- prevMaxOffsetRef.current = maxOffset;
831
- setOffset(
832
- (o) => followBottom && wasAtBottom ? maxOffset : Math.min(o, maxOffset)
833
- );
834
- }, [maxOffset, followBottom]);
835
- const scrollBy = useCallback(
836
- (delta) => {
837
- setOffset((o) => Math.min(Math.max(o + delta, 0), maxOffset));
838
- },
839
- [maxOffset]
840
- );
841
- const revealIndex = useCallback(
842
- (index) => {
843
- setOffset((o) => {
844
- if (index < o) return index;
845
- if (index >= o + capacity) {
846
- return Math.min(index - capacity + 1, maxOffset);
847
- }
848
- return o;
849
- });
850
- },
851
- [capacity, maxOffset]
852
- );
853
- const visibleCount = Math.min(capacity, Math.max(itemCount - offset, 0));
854
- return {
855
- viewportRef,
856
- measured: size !== null,
857
- width: size?.width ?? columns,
858
- offset,
859
- capacity,
860
- maxOffset,
861
- hiddenAbove: Math.min(offset, itemCount),
862
- hiddenBelow: Math.max(itemCount - offset - visibleCount, 0),
863
- scrollBy,
864
- revealIndex
865
- };
866
- }
867
- function ScrollView({ scroll, children }) {
868
- return /* @__PURE__ */ jsxs6(Box7, { ref: scroll.viewportRef, flexDirection: "column", flexGrow: 1, children: [
869
- scroll.hiddenAbove > 0 && /* @__PURE__ */ jsxs6(Text7, { color: COLORS.dim, children: [
870
- "\u2191 ",
871
- scroll.hiddenAbove,
872
- " more"
873
- ] }),
874
- children,
875
- scroll.hiddenBelow > 0 && /* @__PURE__ */ jsxs6(Text7, { color: COLORS.dim, children: [
876
- "\u2193 ",
877
- scroll.hiddenBelow,
878
- " more"
879
- ] })
880
- ] });
881
- }
882
-
883
- // src/ui/SelectPrompt.tsx
884
- import { jsx as jsx6, jsxs as jsxs7 } from "react/jsx-runtime";
898
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
885
899
  var CANCEL = "cancel";
886
900
  var ARROW_WIDTH = 4;
887
901
  var COLUMN_GAP = 2;
@@ -912,7 +926,7 @@ function SelectPrompt({
912
926
  if (multi) hints.push({ key: "[space]", label: "select" });
913
927
  hints.push({ key: "[enter]", label: "confirm" });
914
928
  const containerRef = useRef3(null);
915
- const { columns } = useWindowSize4();
929
+ const { columns } = useWindowSize5();
916
930
  const [width, setWidth] = useState5(columns);
917
931
  useLayoutEffect2(() => {
918
932
  if (!containerRef.current) return;
@@ -966,12 +980,12 @@ function SelectPrompt({
966
980
  }
967
981
  }
968
982
  });
969
- return /* @__PURE__ */ jsx6(Box8, { ref: containerRef, flexGrow: 1, children: /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 1, width, children: [
970
- /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 1, flexShrink: 0, children: [
983
+ return /* @__PURE__ */ jsx6(Box8, { ref: containerRef, flexGrow: 1, children: /* @__PURE__ */ jsxs6(Box8, { flexDirection: "column", gap: 1, width, children: [
984
+ /* @__PURE__ */ jsxs6(Box8, { flexDirection: "column", gap: 1, flexShrink: 0, children: [
971
985
  error && /* @__PURE__ */ jsx6(Text8, { color: COLORS.danger, children: error }),
972
986
  messages?.map((m, i) => /* @__PURE__ */ jsx6(Text8, { color: COLORS.muted, children: m }, `msg-${i}`)),
973
987
  table && /* @__PURE__ */ jsx6(Table, { columns: table.columns, rows: table.rows }),
974
- /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", children: [
988
+ /* @__PURE__ */ jsxs6(Box8, { flexDirection: "column", children: [
975
989
  question && /* @__PURE__ */ jsx6(Text8, { color: COLORS.muted, children: question }),
976
990
  helpText && /* @__PURE__ */ jsx6(Text8, { color: COLORS.dim, children: helpText })
977
991
  ] })
@@ -983,7 +997,7 @@ function SelectPrompt({
983
997
  const bullet = multi && !isCancel ? checked.has(i) ? "\u25CF " : "\u25CB " : "";
984
998
  const sec = isCancel ? void 0 : secondary?.[i];
985
999
  const isText = sec?.kind === "text";
986
- return /* @__PURE__ */ jsxs7(
1000
+ return /* @__PURE__ */ jsxs6(
987
1001
  SelectRow,
988
1002
  {
989
1003
  highlighted,
@@ -1006,10 +1020,10 @@ function SelectPrompt({
1006
1020
  `row-${i}`
1007
1021
  );
1008
1022
  }) }),
1009
- /* @__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: [
1023
+ /* @__PURE__ */ jsx6(Box8, { flexShrink: 0, children: /* @__PURE__ */ jsx6(Text8, { color: COLORS.dim, children: hints.map(({ key, label }, i) => /* @__PURE__ */ jsxs6(Text8, { color: COLORS.dim, children: [
1010
1024
  i > 0 ? " " : "",
1011
1025
  /* @__PURE__ */ jsx6(Text8, { color: COLORS.primary, children: key }),
1012
- /* @__PURE__ */ jsxs7(Text8, { color: COLORS.dim, children: [
1026
+ /* @__PURE__ */ jsxs6(Text8, { color: COLORS.dim, children: [
1013
1027
  " ",
1014
1028
  label
1015
1029
  ] })
@@ -1018,14 +1032,14 @@ function SelectPrompt({
1018
1032
  }
1019
1033
 
1020
1034
  // src/ui/PromptInput.tsx
1021
- import { jsx as jsx7, jsxs as jsxs8 } from "react/jsx-runtime";
1035
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1022
1036
  var ACCEPT_REJECT_OPTIONS = ["Accept", "Reject"];
1023
1037
  function EnterToContinuePrompt({
1024
1038
  question,
1025
1039
  messages,
1026
1040
  onDecide
1027
1041
  }) {
1028
- return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", gap: 1, children: [
1042
+ return /* @__PURE__ */ jsxs7(Box9, { flexDirection: "column", gap: 1, children: [
1029
1043
  messages?.map((m, i) => /* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: m }, `msg-${i}`)),
1030
1044
  question && /* @__PURE__ */ jsx7(Text9, { color: COLORS.primary, children: question }),
1031
1045
  /* @__PURE__ */ jsx7(
@@ -1086,6 +1100,7 @@ function PromptInput() {
1086
1100
  return /* @__PURE__ */ jsx7(Box9, { flexGrow: 1, children: /* @__PURE__ */ jsx7(
1087
1101
  SelectPrompt,
1088
1102
  {
1103
+ question: inputReq.prompt,
1089
1104
  messages: inputReq.messages,
1090
1105
  options: ["Continue"],
1091
1106
  onSelect: submitInput
@@ -1104,14 +1119,7 @@ function PromptInput() {
1104
1119
  );
1105
1120
  }
1106
1121
  if (inputReq.promptType === "commandApproval" && inputReq.command) {
1107
- return /* @__PURE__ */ jsx7(
1108
- CommandApproval,
1109
- {
1110
- command: inputReq.command,
1111
- messages: inputReq.messages,
1112
- onDecide: submitInput
1113
- }
1114
- );
1122
+ return /* @__PURE__ */ jsx7(CommandApproval, { command: inputReq.command, onDecide: submitInput });
1115
1123
  }
1116
1124
  if (inputReq.promptType === "acceptReject") {
1117
1125
  const labels = inputReq.options?.length ? inputReq.options : ACCEPT_REJECT_OPTIONS;
@@ -1127,11 +1135,11 @@ function PromptInput() {
1127
1135
  promptKey
1128
1136
  ) });
1129
1137
  }
1130
- return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", children: [
1138
+ return /* @__PURE__ */ jsxs7(Box9, { flexDirection: "column", children: [
1131
1139
  inputReq.error && /* @__PURE__ */ jsx7(Text9, { color: COLORS.danger, children: inputReq.error }),
1132
1140
  inputReq.messages?.map((m, i) => /* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: m }, `msg-${i}`)),
1133
- /* @__PURE__ */ jsxs8(Box9, { children: [
1134
- /* @__PURE__ */ jsxs8(Text9, { color: COLORS.primary, children: [
1141
+ /* @__PURE__ */ jsxs7(Box9, { children: [
1142
+ /* @__PURE__ */ jsxs7(Text9, { color: COLORS.primary, children: [
1135
1143
  inputReq.prompt,
1136
1144
  " "
1137
1145
  ] }),
@@ -1153,7 +1161,7 @@ function PromptInput() {
1153
1161
  // src/ui/Review.tsx
1154
1162
  import { Box as Box10, Text as Text10, useInput as useInput3 } from "ink";
1155
1163
  import { useLayoutEffect as useLayoutEffect3, useState as useState7 } from "react";
1156
- import { jsx as jsx8, jsxs as jsxs9 } from "react/jsx-runtime";
1164
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1157
1165
  var INGEST_SCRIPT = ".algolia-wizard/ingest.sh";
1158
1166
  function wrapText(text, width) {
1159
1167
  if (width <= 0) return [text];
@@ -1251,8 +1259,8 @@ function ReviewPanel({ review: review2 }) {
1251
1259
  { isActive: scrollable }
1252
1260
  );
1253
1261
  const visible = rows.slice(scroll.offset, scroll.offset + scroll.capacity);
1254
- return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "column", flexGrow: 1, children: [
1255
- /* @__PURE__ */ jsx8(ScrollView, { scroll, children: visible.map((row, i) => /* @__PURE__ */ jsxs9(Text10, { wrap: "truncate", children: [
1262
+ return /* @__PURE__ */ jsxs8(Box10, { flexDirection: "column", flexGrow: 1, children: [
1263
+ /* @__PURE__ */ jsx8(ScrollView, { scroll, children: visible.map((row, i) => /* @__PURE__ */ jsxs8(Text10, { wrap: "truncate", children: [
1256
1264
  row.prefix && /* @__PURE__ */ jsx8(Text10, { color: row.prefixColor ?? row.color, bold: row.bold, children: row.prefix }),
1257
1265
  /* @__PURE__ */ jsx8(Text10, { color: row.color, bold: row.bold, children: row.text })
1258
1266
  ] }, `review-row-${i}`)) }),
@@ -2574,16 +2582,9 @@ function searchFilesTool(ctx) {
2574
2582
  }
2575
2583
 
2576
2584
  // src/lib/tools/runShell.ts
2577
- import { tool as tool9, generateText, Output } from "ai";
2585
+ import { tool as tool8, generateText, Output } from "ai";
2578
2586
  import { createAnthropic } from "@ai-sdk/anthropic";
2579
- import z16 from "zod";
2580
- import { relative as relative5 } from "node:path";
2581
-
2582
- // src/lib/tools/reviewScript.ts
2583
- import { tool as tool8 } from "ai";
2584
2587
  import z15 from "zod";
2585
- import { createHash } from "node:crypto";
2586
- import { readFile as readFile7, stat as stat2 } from "node:fs/promises";
2587
2588
  import { relative as relative4 } from "node:path";
2588
2589
 
2589
2590
  // src/lib/tools/utils/prompt.ts
@@ -2595,116 +2596,6 @@ function serializePrompt(work) {
2595
2596
  return result;
2596
2597
  }
2597
2598
 
2598
- // src/lib/tools/reviewScript.ts
2599
- var reviewedCommandApprovals = /* @__PURE__ */ new WeakMap();
2600
- async function fileDigest(filePath) {
2601
- const content = await readFile7(filePath);
2602
- return createHash("sha256").update(content).digest("hex");
2603
- }
2604
- function grantReviewedCommandApproval(ctx, approval) {
2605
- reviewedCommandApprovals.set(ctx, approval);
2606
- }
2607
- function getReviewedCommandApproval(ctx, command, cwd) {
2608
- const approval = reviewedCommandApprovals.get(ctx);
2609
- if (approval?.command !== command || approval.cwd !== cwd) return void 0;
2610
- return approval;
2611
- }
2612
- function clearReviewedCommandApproval(ctx) {
2613
- reviewedCommandApprovals.delete(ctx);
2614
- }
2615
- function revokeCommandApprovals(ctx, command, cwd) {
2616
- clearReviewedCommandApproval(ctx);
2617
- useWizard.getState().revokeCommand(command, cwd);
2618
- }
2619
- async function reviewedCommandApprovalIsCurrent(approval) {
2620
- const currentDigest = await fileDigest(approval.filePath).catch(() => null);
2621
- return currentDigest === approval.digest;
2622
- }
2623
- function reviewScriptTool(ctx) {
2624
- return tool8({
2625
- 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.",
2626
- inputSchema: z15.object({
2627
- filePath: z15.string().describe(
2628
- "Path to the script to review, relative to the project root."
2629
- ),
2630
- command: z15.string().min(1).describe("The exact command that runShell will use to run the script."),
2631
- cwd: z15.string().describe(
2632
- "The exact working directory that runShell will use, relative to the current tool working directory."
2633
- ),
2634
- entityName: z15.string().trim().min(1).max(100).regex(/^[^\r\n]+$/).describe("The exact entity name selected by the user."),
2635
- usesGeneratedRecords: z15.boolean().describe(
2636
- "Whether the script reads generated sample records instead of the selected real data source."
2637
- )
2638
- }),
2639
- execute: async ({
2640
- filePath,
2641
- command,
2642
- cwd,
2643
- entityName,
2644
- usesGeneratedRecords
2645
- }) => {
2646
- logger.info(
2647
- { filePath, command, cwd, entityName, usesGeneratedRecords },
2648
- "called reviewScript tool"
2649
- );
2650
- const resolved2 = resolveInRoot(ctx, filePath);
2651
- if (resolved2.ok === false) return resolved2.error;
2652
- const resolvedCwd = resolveInRoot(ctx, cwd);
2653
- if (resolvedCwd.ok === false) return resolvedCwd.error;
2654
- const displayCwd = relative4(ctx.root, resolvedCwd.target) || ".";
2655
- const displayFilePath = relative4(ctx.root, resolved2.target);
2656
- 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.`;
2657
- return serializePrompt(async () => {
2658
- revokeCommandApprovals(ctx, command, resolvedCwd.target);
2659
- const isFile = await stat2(resolved2.target).then(
2660
- (s) => s.isFile(),
2661
- () => false
2662
- );
2663
- if (!isFile) {
2664
- return `Refused: ${filePath} is not a file. Write the script first, then review the path you wrote.`;
2665
- }
2666
- const reviewedDigest = await fileDigest(resolved2.target).catch(
2667
- () => null
2668
- );
2669
- if (reviewedDigest === null) {
2670
- return `Refused: ${filePath} could not be read. Write the script first, then review it again.`;
2671
- }
2672
- const answer = await useWizard.getState().requestUserInput({
2673
- prompt: "Run this command?",
2674
- promptType: "commandApproval",
2675
- options: [],
2676
- messages: [
2677
- `We have created your ingestion script. Please review it at ${displayFilePath} before approving.`
2678
- ],
2679
- command: {
2680
- command,
2681
- cwd: displayCwd,
2682
- explanation: ingestionSummary
2683
- }
2684
- });
2685
- if (answer !== "approve") {
2686
- revokeCommandApprovals(ctx, command, resolvedCwd.target);
2687
- return "The user declined to run this ingestion script. Do not run it.";
2688
- }
2689
- const approvedDigest = await fileDigest(resolved2.target).catch(
2690
- () => null
2691
- );
2692
- if (approvedDigest !== reviewedDigest) {
2693
- return "The ingestion script changed while it was being reviewed. Call reviewScript again before running it.";
2694
- }
2695
- ctx.reviewed.push(resolved2.target);
2696
- grantReviewedCommandApproval(ctx, {
2697
- command,
2698
- cwd: resolvedCwd.target,
2699
- filePath: resolved2.target,
2700
- digest: reviewedDigest
2701
- });
2702
- return "The user reviewed the script and approved this exact command. Run it now with the same cwd.";
2703
- });
2704
- }
2705
- });
2706
- }
2707
-
2708
2599
  // src/lib/tools/utils/runShell.ts
2709
2600
  import { spawn as spawn2 } from "node:child_process";
2710
2601
 
@@ -2803,7 +2694,7 @@ function storeApproval(root) {
2803
2694
  return async (req) => {
2804
2695
  const store = useWizard.getState();
2805
2696
  if (store.isCommandApproved(req.command, req.cwd)) return "approve";
2806
- const rel = relative5(root, req.cwd);
2697
+ const rel = relative4(root, req.cwd);
2807
2698
  const answer = await store.requestUserInput({
2808
2699
  prompt: "Run this command?",
2809
2700
  promptType: "commandApproval",
@@ -2956,9 +2847,9 @@ function fastPathSafety(command) {
2956
2847
  return void 0;
2957
2848
  }
2958
2849
  var CLASSIFIER_MODEL = "claude-haiku-4-5";
2959
- var commandSafetySchema = z16.object({
2960
- safe: z16.boolean(),
2961
- reason: z16.string().describe("One short sentence explaining the verdict.")
2850
+ var commandSafetySchema = z15.object({
2851
+ safe: z15.boolean(),
2852
+ reason: z15.string().describe("One short sentence explaining the verdict.")
2962
2853
  });
2963
2854
  function defaultCreateModel() {
2964
2855
  const token = getAuthToken();
@@ -3018,15 +2909,12 @@ async function classifyCommandSafety(createModel, command, cwd, explanation, app
3018
2909
  return false;
3019
2910
  }
3020
2911
  }
3021
- async function resolveShellEnv(ctx, command) {
3022
- return ctx.shell.env().catch((err) => {
2912
+ async function runAndRecord(ctx, command, cwd) {
2913
+ useWizard.getState().pushNotice({ messages: [`Running: ${command}`] });
2914
+ const env = await ctx.shell.env().catch((err) => {
3023
2915
  logger.warn({ err, command }, "runShell: could not resolve command env");
3024
2916
  return {};
3025
2917
  });
3026
- }
3027
- async function runAndRecord(ctx, command, cwd, resolvedEnv) {
3028
- useWizard.getState().pushNotice({ messages: [`Running: ${command}`] });
3029
- const env = resolvedEnv ?? await resolveShellEnv(ctx, command);
3030
2918
  const run2 = await (ctx.shell.run ?? runShell)(command, {
3031
2919
  cwd,
3032
2920
  env,
@@ -3057,16 +2945,6 @@ async function runAndRecord(ctx, command, cwd, resolvedEnv) {
3057
2945
  output: run2.output
3058
2946
  };
3059
2947
  }
3060
- async function runReviewedCommand(ctx, command, cwd) {
3061
- const approval = getReviewedCommandApproval(ctx, command, cwd);
3062
- if (!approval) return void 0;
3063
- const env = await resolveShellEnv(ctx, command);
3064
- if (!await reviewedCommandApprovalIsCurrent(approval)) {
3065
- return `Refused: ${relative5(ctx.root, approval.filePath)} changed after review. Call reviewScript again before running it.`;
3066
- }
3067
- clearReviewedCommandApproval(ctx);
3068
- return runAndRecord(ctx, command, cwd, env);
3069
- }
3070
2948
  async function approveAndRun(ctx, command, cwd, explanation) {
3071
2949
  const decision = await ctx.shell.approve({ command, cwd, explanation });
3072
2950
  if (decision === "reject") {
@@ -3077,16 +2955,16 @@ async function approveAndRun(ctx, command, cwd, explanation) {
3077
2955
  return runAndRecord(ctx, command, cwd);
3078
2956
  }
3079
2957
  function runShellTool(ctx, createModel = defaultCreateModel) {
3080
- return tool9({
2958
+ return tool8({
3081
2959
  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.",
3082
- inputSchema: z16.object({
3083
- command: z16.string().describe(
2960
+ inputSchema: z15.object({
2961
+ command: z15.string().describe(
3084
2962
  "The command to run, exactly as it would be typed in a shell. Pipes, && and redirects are allowed."
3085
2963
  ),
3086
- cwd: z16.string().optional().describe(
2964
+ cwd: z15.string().optional().describe(
3087
2965
  "Directory to run in, relative to the project root. Defaults to the project root."
3088
2966
  ),
3089
- explanation: z16.string().describe(
2967
+ explanation: z15.string().describe(
3090
2968
  "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."
3091
2969
  )
3092
2970
  }),
@@ -3095,22 +2973,16 @@ function runShellTool(ctx, createModel = defaultCreateModel) {
3095
2973
  return `Refused: command limit (${ctx.limits.shell}) reached. Stop running commands and report what you have.`;
3096
2974
  }
3097
2975
  const resolved2 = resolveInRoot(ctx, cwd ?? ".");
3098
- if (resolved2.ok === false) return resolved2.error;
2976
+ if (!resolved2.ok) return resolved2.error;
3099
2977
  if (isFileIOCommand(command)) {
3100
2978
  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).";
3101
2979
  }
3102
2980
  logger.info({ command, cwd: resolved2.target }, "called runShell tool");
3103
- const reviewed = await serializePrompt(
3104
- () => runReviewedCommand(ctx, command, resolved2.target)
3105
- );
3106
- if (reviewed !== void 0) return reviewed;
3107
2981
  const fast = fastPathSafety(command);
3108
2982
  let isSafe = fast;
3109
- let usedStoredApproval = false;
3110
2983
  if (isSafe === void 0) {
3111
2984
  const store = useWizard.getState();
3112
- usedStoredApproval = store.isCommandApproved(command, resolved2.target);
3113
- isSafe = usedStoredApproval;
2985
+ isSafe = store.isCommandApproved(command, resolved2.target);
3114
2986
  if (!isSafe) {
3115
2987
  isSafe = await classifyCommandSafety(
3116
2988
  createModel,
@@ -3121,18 +2993,54 @@ function runShellTool(ctx, createModel = defaultCreateModel) {
3121
2993
  );
3122
2994
  }
3123
2995
  }
3124
- return serializePrompt(async () => {
3125
- const lateReview = await runReviewedCommand(
3126
- ctx,
3127
- command,
3128
- resolved2.target
2996
+ if (isSafe) {
2997
+ return serializePrompt(
2998
+ () => runAndRecord(ctx, command, resolved2.target)
3129
2999
  );
3130
- if (lateReview !== void 0) return lateReview;
3131
- const storedApprovalIsCurrent = !usedStoredApproval || useWizard.getState().isCommandApproved(command, resolved2.target);
3132
- if (isSafe && storedApprovalIsCurrent) {
3133
- return runAndRecord(ctx, command, resolved2.target);
3134
- }
3135
- return approveAndRun(ctx, command, resolved2.target, explanation);
3000
+ }
3001
+ return serializePrompt(
3002
+ () => approveAndRun(ctx, command, resolved2.target, explanation)
3003
+ );
3004
+ }
3005
+ });
3006
+ }
3007
+
3008
+ // src/lib/tools/reviewScript.ts
3009
+ import { tool as tool9 } from "ai";
3010
+ import z16 from "zod";
3011
+ import { stat as stat2 } from "node:fs/promises";
3012
+ import { relative as relative5 } from "node:path";
3013
+ function reviewScriptTool(ctx) {
3014
+ return tool9({
3015
+ 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.",
3016
+ inputSchema: z16.object({
3017
+ filePath: z16.string().describe(
3018
+ "Path to the script to review, relative to the project root."
3019
+ )
3020
+ }),
3021
+ execute: async ({ filePath }) => {
3022
+ logger.info({ filePath }, "called reviewScript tool");
3023
+ const resolved2 = resolveInRoot(ctx, filePath);
3024
+ if (resolved2.ok === false) return resolved2.error;
3025
+ const isFile = await stat2(resolved2.target).then(
3026
+ (s) => s.isFile(),
3027
+ () => false
3028
+ );
3029
+ if (!isFile) {
3030
+ return `Refused: ${filePath} is not a file. Write the script first, then review the path you wrote.`;
3031
+ }
3032
+ return serializePrompt(async () => {
3033
+ await useWizard.getState().requestUserInput({
3034
+ prompt: "",
3035
+ promptType: "enterToContinue",
3036
+ options: [],
3037
+ messages: [
3038
+ `Please review ${relative5(ctx.root, resolved2.target)} before it runs:`,
3039
+ resolved2.target
3040
+ ]
3041
+ });
3042
+ ctx.reviewed.push(resolved2.target);
3043
+ return "The user has reviewed the script. You may run it now.";
3136
3044
  });
3137
3045
  }
3138
3046
  });
@@ -3627,7 +3535,7 @@ async function runAnalysis(mode, extraInstructions = []) {
3627
3535
  // package.json
3628
3536
  var package_default = {
3629
3537
  name: "@algolia/wizard",
3630
- version: "0.46.0-rc.136.345",
3538
+ version: "0.46.0-rc.146.324",
3631
3539
  description: "Magically implement Algolia functionality in your codebase",
3632
3540
  type: "module",
3633
3541
  engines: {
@@ -4330,8 +4238,8 @@ function ingestionInstructions(input) {
4330
4238
  ...algoliaClientDoc(input),
4331
4239
  "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.",
4332
4240
  `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.`,
4333
- `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.`,
4334
- '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.',
4241
+ "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.",
4242
+ '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.',
4335
4243
  "The summary should be extremely concise.",
4336
4244
  ...sourceSpecificInstructions(input)
4337
4245
  ] : []
@@ -4703,33 +4611,19 @@ ${detail}` : ""}`
4703
4611
  product_area: "AI Wizard"
4704
4612
  });
4705
4613
  }
4706
- if (ingestScriptRan) {
4707
- await ctx.requestUserInput({
4708
- prompt: "Continue",
4709
- promptType: "notice",
4710
- options: [],
4711
- messages: [
4712
- ingestOutcomeMessage,
4713
- "View your ingested records in the Algolia dashboard:",
4714
- "https://dashboard.algolia.com/explorer/browse",
4715
- "When you're ready to continue, we'll move on to search implementation."
4716
- ]
4717
- });
4718
- } else {
4719
- const commandMessages = ingestCommand ? [`Ingestion command: ${ingestCommand}`] : [];
4720
- await ctx.requestUserInput({
4721
- prompt: "",
4722
- promptType: "enterToContinue",
4723
- options: [],
4724
- // One message per line: Notices.tsx counts a message as one wrapped
4725
- // line, so an embedded newline overflows the panel's height accounting.
4726
- messages: [
4727
- ingestOutcomeMessage,
4728
- ...ingestFailureDetail?.split("\n").filter((l) => l.trim()) ?? [],
4729
- ...commandMessages
4730
- ]
4731
- });
4732
- }
4614
+ const commandMessages = ingestCommand ? [`Ingestion command: ${ingestCommand}`] : [];
4615
+ await ctx.requestUserInput({
4616
+ prompt: "",
4617
+ promptType: "enterToContinue",
4618
+ options: [],
4619
+ // One message per line: Notices.tsx counts a message as one wrapped
4620
+ // line, so an embedded newline overflows the panel's height accounting.
4621
+ messages: [
4622
+ ingestOutcomeMessage,
4623
+ ...ingestFailureDetail?.split("\n").filter((l) => l.trim()) ?? [],
4624
+ ...commandMessages
4625
+ ]
4626
+ });
4733
4627
  }
4734
4628
  let searchConfigFile;
4735
4629
  if (useCases.includes("search")) {
@@ -4929,7 +4823,7 @@ function getWorkflow(id) {
4929
4823
  import { dirname as dirname8, join as join11 } from "node:path";
4930
4824
  import { fileURLToPath as fileURLToPath2 } from "node:url";
4931
4825
  import { useState as useState8 } from "react";
4932
- import { Box as Box11, Spacer, Text as Text11, useInput as useInput4, useWindowSize as useWindowSize5 } from "ink";
4826
+ import { Box as Box11, Spacer, Text as Text11, useInput as useInput4, useWindowSize as useWindowSize6 } from "ink";
4933
4827
 
4934
4828
  // src/ui/copy/welcome.ts
4935
4829
  var sidebarItems = [
@@ -4957,7 +4851,7 @@ var sidebarItems = [
4957
4851
 
4958
4852
  // src/ui/Welcome.tsx
4959
4853
  import Image, { TerminalInfoContext, defaultTerminalInfo } from "ink-picture";
4960
- import { jsx as jsx9, jsxs as jsxs10 } from "react/jsx-runtime";
4854
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
4961
4855
  var IMAGE_PATH = join11(dirname8(fileURLToPath2(import.meta.url)), "algolia.png");
4962
4856
  var TERMINAL_INFO = {
4963
4857
  ...defaultTerminalInfo,
@@ -4968,12 +4862,12 @@ function SidebarItem({
4968
4862
  title,
4969
4863
  description
4970
4864
  }) {
4971
- return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", children: [
4972
- /* @__PURE__ */ jsxs10(Box11, { gap: 1, children: [
4865
+ return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
4866
+ /* @__PURE__ */ jsxs9(Box11, { gap: 1, children: [
4973
4867
  /* @__PURE__ */ jsx9(Text11, { color: COLORS.success, children: "\u2192" }),
4974
4868
  /* @__PURE__ */ jsx9(Text11, { color: COLORS.strong, bold: true, children: title })
4975
4869
  ] }),
4976
- /* @__PURE__ */ jsxs10(Box11, { flexDirection: "row", gap: 2, children: [
4870
+ /* @__PURE__ */ jsxs9(Box11, { flexDirection: "row", gap: 2, children: [
4977
4871
  /* @__PURE__ */ jsx9(Spacer, {}),
4978
4872
  /* @__PURE__ */ jsx9(Text11, { color: COLORS.muted, children: description })
4979
4873
  ] })
@@ -4982,7 +4876,7 @@ function SidebarItem({
4982
4876
  function Welcome() {
4983
4877
  const confirmStart = useWizard((s) => s.confirmStart);
4984
4878
  const openLearnMore = useWizard((s) => s.openLearnMore);
4985
- const { rows } = useWindowSize5();
4879
+ const { rows } = useWindowSize6();
4986
4880
  const actions = [
4987
4881
  { label: "start wizard", run: confirmStart },
4988
4882
  { label: "learn more", run: openLearnMore }
@@ -5011,7 +4905,7 @@ function Welcome() {
5011
4905
  if (rows < 30) {
5012
4906
  layout = scales["small"];
5013
4907
  }
5014
- return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "row", justifyContent: "space-between", width: "100%", children: [
4908
+ return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "row", justifyContent: "space-between", width: "100%", children: [
5015
4909
  /* @__PURE__ */ jsx9(
5016
4910
  Box11,
5017
4911
  {
@@ -5019,7 +4913,7 @@ function Welcome() {
5019
4913
  paddingX: layout.main.padding.x,
5020
4914
  flexDirection: "column",
5021
4915
  justifyContent: "center",
5022
- children: /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", gap: 2, children: [
4916
+ children: /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", gap: 2, children: [
5023
4917
  /* @__PURE__ */ jsx9(TerminalInfoContext.Provider, { value: TERMINAL_INFO, children: /* @__PURE__ */ jsx9(
5024
4918
  Image,
5025
4919
  {
@@ -5041,12 +4935,12 @@ function Welcome() {
5041
4935
  },
5042
4936
  action.label
5043
4937
  )) }),
5044
- /* @__PURE__ */ jsxs10(Box11, { gap: 2, children: [
5045
- /* @__PURE__ */ jsxs10(Text11, { children: [
4938
+ /* @__PURE__ */ jsxs9(Box11, { gap: 2, children: [
4939
+ /* @__PURE__ */ jsxs9(Text11, { children: [
5046
4940
  /* @__PURE__ */ jsx9(Text11, { color: COLORS.primary, children: "[\u2191] [\u2193]" }),
5047
4941
  /* @__PURE__ */ jsx9(Text11, { color: COLORS.dim, children: " move" })
5048
4942
  ] }),
5049
- /* @__PURE__ */ jsxs10(Text11, { children: [
4943
+ /* @__PURE__ */ jsxs9(Text11, { children: [
5050
4944
  /* @__PURE__ */ jsx9(Text11, { color: COLORS.primary, children: "[enter]" }),
5051
4945
  /* @__PURE__ */ jsx9(Text11, { color: COLORS.dim, children: " confirm" })
5052
4946
  ] })
@@ -5054,7 +4948,7 @@ function Welcome() {
5054
4948
  ] })
5055
4949
  }
5056
4950
  ),
5057
- /* @__PURE__ */ jsxs10(
4951
+ /* @__PURE__ */ jsxs9(
5058
4952
  Box11,
5059
4953
  {
5060
4954
  backgroundColor: COLORS.bg.sidebar,
@@ -5075,7 +4969,7 @@ function Welcome() {
5075
4969
 
5076
4970
  // src/ui/LearnMore.tsx
5077
4971
  import { Fragment } from "react";
5078
- import { Box as Box12, Text as Text12, useInput as useInput5, useWindowSize as useWindowSize6 } from "ink";
4972
+ import { Box as Box12, Text as Text12, useInput as useInput5, useWindowSize as useWindowSize7 } from "ink";
5079
4973
 
5080
4974
  // src/ui/copy/learn-more.ts
5081
4975
  var accessIntro = "Everything runs locally on your machine. Nothing is written or sent without an explicit yes from you.";
@@ -5117,7 +5011,7 @@ var policyLinks = [
5117
5011
  ];
5118
5012
 
5119
5013
  // src/ui/LearnMore.tsx
5120
- import { jsx as jsx10, jsxs as jsxs11 } from "react/jsx-runtime";
5014
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
5121
5015
  var TAG_COLORS = {
5122
5016
  READ: COLORS.success,
5123
5017
  WRITE: COLORS.badge,
@@ -5134,7 +5028,7 @@ function NeverLine({
5134
5028
  }) {
5135
5029
  const used = segments.reduce((n, s) => n + s.text.length, 0);
5136
5030
  const rightPad = Math.max(0, width - 2 - NEVER_BOX_PAD_X - used);
5137
- return /* @__PURE__ */ jsxs11(Text12, { color: COLORS.primary, children: [
5031
+ return /* @__PURE__ */ jsxs10(Text12, { color: COLORS.primary, children: [
5138
5032
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.danger, children: "\u2502" }),
5139
5033
  " ".repeat(NEVER_BOX_PAD_X),
5140
5034
  segments.map((s, i) => /* @__PURE__ */ jsx10(Text12, { color: s.color, bold: s.bold, children: s.text }, i)),
@@ -5145,13 +5039,13 @@ function NeverLine({
5145
5039
  function LearnMore() {
5146
5040
  const confirmStart = useWizard((s) => s.confirmStart);
5147
5041
  const backToHome = useWizard((s) => s.backToHome);
5148
- const { columns } = useWindowSize6();
5042
+ const { columns } = useWindowSize7();
5149
5043
  const dividerWidth = Math.max(0, columns - PADDING_X * 2);
5150
5044
  useInput5((_input, key) => {
5151
5045
  if (key.escape) backToHome();
5152
5046
  else if (key.return) confirmStart();
5153
5047
  });
5154
- return /* @__PURE__ */ jsxs11(
5048
+ return /* @__PURE__ */ jsxs10(
5155
5049
  Box12,
5156
5050
  {
5157
5051
  flexDirection: "column",
@@ -5162,17 +5056,17 @@ function LearnMore() {
5162
5056
  children: [
5163
5057
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.strong, bold: true, children: "What algolia wizard accesses" }),
5164
5058
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: accessIntro }),
5165
- /* @__PURE__ */ jsx10(Box12, { flexDirection: "column", children: accessItems.map((item) => /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", marginTop: 1, children: [
5059
+ /* @__PURE__ */ jsx10(Box12, { flexDirection: "column", children: accessItems.map((item) => /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", marginTop: 1, children: [
5166
5060
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.border, children: "\u2500".repeat(dividerWidth) }),
5167
- /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, marginTop: 1, children: [
5061
+ /* @__PURE__ */ jsxs10(Box12, { flexDirection: "row", gap: 1, marginTop: 1, children: [
5168
5062
  /* @__PURE__ */ jsx10(Box12, { width: TAG_COLUMN_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx10(Text12, { color: TAG_COLORS[item.tag], bold: true, children: `[${item.tag}]` }) }),
5169
- /* @__PURE__ */ jsx10(Box12, { flexDirection: "column", children: /* @__PURE__ */ jsxs11(Text12, { color: COLORS.primary, children: [
5063
+ /* @__PURE__ */ jsx10(Box12, { flexDirection: "column", children: /* @__PURE__ */ jsxs10(Text12, { color: COLORS.primary, children: [
5170
5064
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.strong, bold: true, children: item.title }),
5171
5065
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: ` \u2014 ${item.description}` })
5172
5066
  ] }) })
5173
5067
  ] })
5174
5068
  ] }, item.tag)) }),
5175
- /* @__PURE__ */ jsxs11(Box12, { marginTop: 1, flexDirection: "column", children: [
5069
+ /* @__PURE__ */ jsxs10(Box12, { marginTop: 1, flexDirection: "column", children: [
5176
5070
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.danger, children: `\u256D${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256E` }),
5177
5071
  /* @__PURE__ */ jsx10(NeverLine, { width: dividerWidth }),
5178
5072
  /* @__PURE__ */ jsx10(
@@ -5182,7 +5076,7 @@ function LearnMore() {
5182
5076
  segments: [{ text: "I NEVER", color: COLORS.danger, bold: true }]
5183
5077
  }
5184
5078
  ),
5185
- neverItems.map((item) => /* @__PURE__ */ jsxs11(Fragment, { children: [
5079
+ neverItems.map((item) => /* @__PURE__ */ jsxs10(Fragment, { children: [
5186
5080
  /* @__PURE__ */ jsx10(NeverLine, { width: dividerWidth }),
5187
5081
  /* @__PURE__ */ jsx10(
5188
5082
  NeverLine,
@@ -5199,17 +5093,17 @@ function LearnMore() {
5199
5093
  /* @__PURE__ */ jsx10(NeverLine, { width: dividerWidth }),
5200
5094
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.danger, children: `\u2570${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256F` })
5201
5095
  ] }),
5202
- /* @__PURE__ */ jsx10(Box12, { marginTop: 1, flexDirection: "column", children: policyLinks.map((link) => /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, children: [
5096
+ /* @__PURE__ */ jsx10(Box12, { marginTop: 1, flexDirection: "column", children: policyLinks.map((link) => /* @__PURE__ */ jsxs10(Box12, { flexDirection: "row", gap: 1, children: [
5203
5097
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.strong, bold: true, children: `${link.label}:` }),
5204
5098
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.accent, children: link.url })
5205
5099
  ] }, link.label)) }),
5206
- /* @__PURE__ */ jsxs11(Box12, { marginTop: 1, flexDirection: "row", gap: 3, children: [
5207
- /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, children: [
5100
+ /* @__PURE__ */ jsxs10(Box12, { marginTop: 1, flexDirection: "row", gap: 3, children: [
5101
+ /* @__PURE__ */ jsxs10(Box12, { flexDirection: "row", gap: 1, children: [
5208
5102
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "[" }),
5209
5103
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.primary, children: "esc" }),
5210
5104
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "] back" })
5211
5105
  ] }),
5212
- /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, children: [
5106
+ /* @__PURE__ */ jsxs10(Box12, { flexDirection: "row", gap: 1, children: [
5213
5107
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "[" }),
5214
5108
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.primary, children: "enter" }),
5215
5109
  /* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "]" }),
@@ -5227,11 +5121,11 @@ import { Box as Box15, Text as Text15 } from "ink";
5227
5121
  // src/ui/Steps.tsx
5228
5122
  import { Box as Box13, Text as Text13 } from "ink";
5229
5123
  import Spinner from "ink-spinner";
5230
- import { jsx as jsx11, jsxs as jsxs12 } from "react/jsx-runtime";
5124
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
5231
5125
  function Steps() {
5232
5126
  const { steps } = useWizard();
5233
5127
  const visibleSteps = steps.filter(isStepVisible);
5234
- 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: [
5128
+ return /* @__PURE__ */ jsx11(Box13, { flexDirection: "column", gap: 1, children: visibleSteps.map((s) => /* @__PURE__ */ jsx11(Box13, { flexDirection: "column", children: /* @__PURE__ */ jsxs11(Text13, { color: COLORS.status[s.status], children: [
5235
5129
  s.status === "running" ? /* @__PURE__ */ jsx11(Spinner, { type: "dots" }) : MARKER[s.status],
5236
5130
  " ",
5237
5131
  s.title
@@ -5241,7 +5135,7 @@ function CurrentStep() {
5241
5135
  const { steps } = useWizard();
5242
5136
  const currentStep = steps.filter(isStepVisible).find((s) => s.status === "running");
5243
5137
  if (!currentStep) return null;
5244
- return /* @__PURE__ */ jsxs12(Text13, { color: COLORS.status.running, children: [
5138
+ return /* @__PURE__ */ jsxs11(Text13, { color: COLORS.status.running, children: [
5245
5139
  /* @__PURE__ */ jsx11(Spinner, { type: "dots" }),
5246
5140
  " ",
5247
5141
  ` ${currentStep.title}`
@@ -5250,14 +5144,14 @@ function CurrentStep() {
5250
5144
 
5251
5145
  // src/ui/Progress.tsx
5252
5146
  import { Box as Box14, Text as Text14 } from "ink";
5253
- import { jsx as jsx12, jsxs as jsxs13 } from "react/jsx-runtime";
5147
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
5254
5148
  function Progress() {
5255
5149
  const { steps, currentStepIndex } = useWizard();
5256
5150
  const visibleSteps = steps.filter(isStepVisible);
5257
5151
  if (visibleSteps.length === 0) return null;
5258
5152
  const visibleCountThroughCurrent = steps.slice(0, currentStepIndex + 1).filter(isStepVisible).length;
5259
5153
  const activeStepNumber = Math.max(1, visibleCountThroughCurrent);
5260
- return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "row", gap: 1, children: [
5154
+ return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "row", gap: 1, children: [
5261
5155
  /* @__PURE__ */ jsx12(Text14, { color: COLORS.muted, children: "STEP" }),
5262
5156
  /* @__PURE__ */ jsx12(Text14, { color: COLORS.strong, bold: true, children: activeStepNumber }),
5263
5157
  /* @__PURE__ */ jsx12(Text14, { color: COLORS.strong, bold: true, children: "/" }),
@@ -5272,9 +5166,9 @@ var sidebarCommands = [
5272
5166
  ];
5273
5167
 
5274
5168
  // src/ui/Sidebar.tsx
5275
- import { jsx as jsx13, jsxs as jsxs14 } from "react/jsx-runtime";
5169
+ import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
5276
5170
  function Sidebar() {
5277
- return /* @__PURE__ */ jsxs14(
5171
+ return /* @__PURE__ */ jsxs13(
5278
5172
  Box15,
5279
5173
  {
5280
5174
  backgroundColor: "#14171E",
@@ -5284,14 +5178,14 @@ function Sidebar() {
5284
5178
  flexDirection: "column",
5285
5179
  justifyContent: "space-between",
5286
5180
  children: [
5287
- /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", gap: 1, children: [
5181
+ /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", gap: 1, children: [
5288
5182
  /* @__PURE__ */ jsx13(Text15, { color: COLORS.muted, children: "PROGRESS" }),
5289
5183
  /* @__PURE__ */ jsx13(Steps, {})
5290
5184
  ] }),
5291
- /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", gap: 1, children: [
5185
+ /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", gap: 1, children: [
5292
5186
  /* @__PURE__ */ jsx13(Progress, {}),
5293
5187
  /* @__PURE__ */ jsx13(Box15, { flexDirection: "column", children: sidebarCommands.map((c) => {
5294
- return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "row", gap: 1, children: [
5188
+ return /* @__PURE__ */ jsxs13(Box15, { flexDirection: "row", gap: 1, children: [
5295
5189
  /* @__PURE__ */ jsx13(Text15, { color: COLORS.primary, children: `[${c.keyHint}]` }),
5296
5190
  /* @__PURE__ */ jsx13(Text15, { color: COLORS.muted, children: c.description })
5297
5191
  ] }, c.keyHint);
@@ -5304,10 +5198,10 @@ function Sidebar() {
5304
5198
 
5305
5199
  // src/ui/Ribbon.tsx
5306
5200
  import { Box as Box16, Text as Text16 } from "ink";
5307
- import { jsx as jsx14, jsxs as jsxs15 } from "react/jsx-runtime";
5201
+ import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
5308
5202
  function Ribbon() {
5309
5203
  const firstCommand = sidebarCommands[0];
5310
- return /* @__PURE__ */ jsxs15(
5204
+ return /* @__PURE__ */ jsxs14(
5311
5205
  Box16,
5312
5206
  {
5313
5207
  backgroundColor: "#14171E",
@@ -5318,7 +5212,7 @@ function Ribbon() {
5318
5212
  children: [
5319
5213
  /* @__PURE__ */ jsx14(Progress, {}),
5320
5214
  /* @__PURE__ */ jsx14(CurrentStep, {}),
5321
- /* @__PURE__ */ jsxs15(Box16, { flexDirection: "row", gap: 1, children: [
5215
+ /* @__PURE__ */ jsxs14(Box16, { flexDirection: "row", gap: 1, children: [
5322
5216
  /* @__PURE__ */ jsx14(Text16, { color: COLORS.primary, children: `[${firstCommand.keyHint}]` }),
5323
5217
  /* @__PURE__ */ jsx14(Text16, { color: COLORS.muted, children: firstCommand.description })
5324
5218
  ] })
@@ -5332,7 +5226,7 @@ import { useState as useState10 } from "react";
5332
5226
 
5333
5227
  // src/ui/Logs.tsx
5334
5228
  import { Box as Box17, Text as Text17, useInput as useInput6 } from "ink";
5335
- import { jsx as jsx15, jsxs as jsxs16 } from "react/jsx-runtime";
5229
+ import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
5336
5230
  var KIND_COLOR = {
5337
5231
  tool: COLORS.primary,
5338
5232
  prompt: COLORS.badge
@@ -5368,7 +5262,7 @@ function Logs() {
5368
5262
  else if (key.downArrow) scroll.scrollBy(1);
5369
5263
  });
5370
5264
  const visible = logs.slice(scroll.offset, scroll.offset + scroll.capacity);
5371
- return /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", paddingX: 4, paddingY: 2, flexGrow: 1, children: [
5265
+ return /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", paddingX: 4, paddingY: 2, flexGrow: 1, children: [
5372
5266
  logs.length === 0 && /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, children: "No logs yet." }),
5373
5267
  /* @__PURE__ */ jsx15(ScrollView, { scroll, children: visible.map((entry) => {
5374
5268
  const timestamp = `[${formatTimestamp(entry.startedAt)}]`;
@@ -5380,7 +5274,7 @@ function Logs() {
5380
5274
  const name = truncate3(entry.name, budget);
5381
5275
  budget -= name.length;
5382
5276
  const preview = rawPreview ? truncate3(rawPreview, budget) : "";
5383
- return /* @__PURE__ */ jsxs16(Box17, { flexDirection: "row", gap: ROW_GAP, children: [
5277
+ return /* @__PURE__ */ jsxs15(Box17, { flexDirection: "row", gap: ROW_GAP, children: [
5384
5278
  /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, children: timestamp }),
5385
5279
  /* @__PURE__ */ jsx15(Text17, { color: logNameColor(entry), wrap: "truncate", children: name }),
5386
5280
  preview && /* @__PURE__ */ jsx15(Text17, { color: COLORS.dim, wrap: "truncate", children: preview }),
@@ -5393,37 +5287,8 @@ function Logs() {
5393
5287
 
5394
5288
  // src/ui/Tips.tsx
5395
5289
  import { useEffect as useEffect3, useRef as useRef4, useState as useState9 } from "react";
5396
- import { Box as Box19, Text as Text19 } from "ink";
5397
- import terminalLink from "terminal-link";
5398
-
5399
- // src/ui/Code.tsx
5400
5290
  import { Box as Box18, Text as Text18 } from "ink";
5401
- import { jsx as jsx16 } from "react/jsx-runtime";
5402
- var TOKEN_RE = /("(?:\\.|[^"\\])*"|\btrue\b|\bfalse\b|\bnull\b|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|[{}[\]:,])/g;
5403
- function highlightJson(json) {
5404
- const parts = json.split(TOKEN_RE);
5405
- return parts.map((part, i) => {
5406
- if (!part) return null;
5407
- if (part[0] === '"') {
5408
- const next = parts.slice(i + 1).find((p) => p.trim());
5409
- const isKey = next?.trimStart().startsWith(":");
5410
- return /* @__PURE__ */ jsx16(Text18, { color: isKey ? "cyan" : "green", children: part }, i);
5411
- }
5412
- if (part === "true" || part === "false" || part === "null") {
5413
- return /* @__PURE__ */ jsx16(Text18, { color: "magenta", children: part }, i);
5414
- }
5415
- if (/^-?\d/.test(part)) {
5416
- return /* @__PURE__ */ jsx16(Text18, { color: "yellow", children: part }, i);
5417
- }
5418
- if (/^[{}[\]:,]$/.test(part)) {
5419
- return /* @__PURE__ */ jsx16(Text18, { color: COLORS.dim, children: part }, i);
5420
- }
5421
- return /* @__PURE__ */ jsx16(Text18, { children: part }, i);
5422
- });
5423
- }
5424
- function Code({ children }) {
5425
- return /* @__PURE__ */ jsx16(Box18, { children: /* @__PURE__ */ jsx16(Text18, { children: highlightJson(children) }) });
5426
- }
5291
+ import terminalLink from "terminal-link";
5427
5292
 
5428
5293
  // src/ui/copy/tips.ts
5429
5294
  var tips = [
@@ -5455,23 +5320,7 @@ var tips = [
5455
5320
  },
5456
5321
  {
5457
5322
  type: "text",
5458
- value: "Everything else is up to you:"
5459
- },
5460
- {
5461
- type: "code",
5462
- value: JSON.stringify(
5463
- {
5464
- objectID: "sku_48213",
5465
- name: "Trail Running Shoe",
5466
- brand: "Northline",
5467
- categories: ["Footwear", "Running", "Mens"],
5468
- price: 129.99,
5469
- in_stock: true,
5470
- rating: 4.6
5471
- },
5472
- null,
5473
- 2
5474
- )
5323
+ value: "Fields, nesting and types are up to you \u2014 index the shape your app already uses."
5475
5324
  }
5476
5325
  ]
5477
5326
  },
@@ -5636,26 +5485,26 @@ function tipsByIds(ids) {
5636
5485
  }
5637
5486
 
5638
5487
  // src/ui/Tips.tsx
5639
- import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
5488
+ import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
5640
5489
  var TICK_MS = 16;
5641
5490
  var CHUNK_HOLD_MS = 2e3;
5642
5491
  var HOLD_MS = 12e3;
5643
5492
  function TipTitle({ children }) {
5644
- return /* @__PURE__ */ jsxs17(Box19, { gap: 1, children: [
5645
- /* @__PURE__ */ jsx17(Text19, { color: "cyan", children: "\u2726" }),
5646
- /* @__PURE__ */ jsx17(Text19, { color: "white", bold: true, children })
5493
+ return /* @__PURE__ */ jsxs16(Text18, { children: [
5494
+ /* @__PURE__ */ jsx16(Text18, { color: "cyan", children: "\u2726 " }),
5495
+ /* @__PURE__ */ jsx16(Text18, { color: "white", bold: true, children })
5647
5496
  ] });
5648
5497
  }
5649
5498
  function InlineSegment({ segment }) {
5650
5499
  switch (segment.type) {
5651
5500
  case "highlight":
5652
- return /* @__PURE__ */ jsx17(Text19, { color: COLORS.success, children: segment.value });
5501
+ return /* @__PURE__ */ jsx16(Text18, { color: COLORS.success, children: segment.value });
5653
5502
  case "link":
5654
- return /* @__PURE__ */ jsx17(Text19, { color: "cyan", underline: true, children: segment.href ? terminalLink(segment.value, segment.href) : segment.value });
5503
+ return /* @__PURE__ */ jsx16(Text18, { color: "cyan", underline: true, children: segment.href ? terminalLink(segment.value, segment.href) : segment.value });
5655
5504
  case "codeword":
5656
- return /* @__PURE__ */ jsx17(Text19, { color: COLORS.highlight.fg, backgroundColor: COLORS.highlight.bg, children: segment.value });
5505
+ return /* @__PURE__ */ jsx16(Text18, { color: COLORS.highlight.fg, backgroundColor: COLORS.highlight.bg, children: segment.value });
5657
5506
  default:
5658
- return /* @__PURE__ */ jsx17(Text19, { color: COLORS.muted, children: segment.value });
5507
+ return /* @__PURE__ */ jsx16(Text18, { color: COLORS.muted, children: segment.value });
5659
5508
  }
5660
5509
  }
5661
5510
  function TipContent({
@@ -5663,38 +5512,42 @@ function TipContent({
5663
5512
  revealed
5664
5513
  }) {
5665
5514
  let remaining = revealed;
5666
- const slices = chunks.map((chunk) => {
5515
+ const segments = [];
5516
+ for (const chunk of chunks) {
5667
5517
  const slice = chunk.value.slice(0, Math.max(0, remaining));
5668
5518
  remaining -= chunk.value.length;
5669
- return slice;
5670
- });
5671
- const blocks = [];
5672
- for (let i = 0; i < chunks.length; i++) {
5673
- const chunk = chunks[i];
5674
- const slice = slices[i];
5675
5519
  if (!slice) continue;
5676
- const segment = {
5520
+ const last = segments[segments.length - 1];
5521
+ if (chunk.type === "text" && last?.type === "text") {
5522
+ last.value = `${last.value} ${slice}`;
5523
+ continue;
5524
+ }
5525
+ segments.push({
5677
5526
  type: chunk.type,
5678
5527
  value: slice,
5679
5528
  href: chunk.type === "link" ? chunk.href : void 0
5680
- };
5681
- if (chunk.type === "code") {
5682
- blocks.push({ type: "code", segment });
5683
- continue;
5684
- }
5685
- const last = blocks[blocks.length - 1];
5686
- if (last?.type === "inline") {
5687
- last.segments.push(segment);
5688
- } else {
5689
- blocks.push({ type: "inline", segments: [segment] });
5690
- }
5529
+ });
5691
5530
  }
5692
- return /* @__PURE__ */ jsx17(Box19, { flexDirection: "column", marginLeft: 2, gap: 1, children: blocks.map(
5693
- (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: [
5694
- j > 0 && " ",
5695
- /* @__PURE__ */ jsx17(InlineSegment, { segment })
5696
- ] }, j)) }, i)
5697
- ) });
5531
+ return /* @__PURE__ */ jsx16(Box18, { marginLeft: 2, children: /* @__PURE__ */ jsx16(Text18, { children: segments.map((segment, i) => /* @__PURE__ */ jsxs16(Text18, { children: [
5532
+ i > 0 && " ",
5533
+ /* @__PURE__ */ jsx16(InlineSegment, { segment })
5534
+ ] }, i)) }) });
5535
+ }
5536
+ var TIP_PANEL_ROWS = 11;
5537
+ function TipCard({
5538
+ tip,
5539
+ revealed
5540
+ }) {
5541
+ return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", gap: 1, children: [
5542
+ /* @__PURE__ */ jsx16(TipTitle, { children: tip.title.slice(0, revealed) }),
5543
+ /* @__PURE__ */ jsx16(
5544
+ TipContent,
5545
+ {
5546
+ chunks: tip.chunks,
5547
+ revealed: Math.max(0, revealed - tip.title.length)
5548
+ }
5549
+ )
5550
+ ] });
5698
5551
  }
5699
5552
  var progress = { stepId: null, tipIndex: 0, revealed: 0 };
5700
5553
  function Tips({
@@ -5767,16 +5620,11 @@ function Tips({
5767
5620
  return () => clearTimeout(timer);
5768
5621
  }, [revealed, totalLength, tips2.length]);
5769
5622
  if (!tip) return null;
5770
- const titleRevealed = tip.title.slice(0, revealed);
5771
- const contentRevealed = Math.max(0, revealed - tip.title.length);
5772
- return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", marginBottom: 1, gap: 1, children: [
5773
- /* @__PURE__ */ jsx17(TipTitle, { children: titleRevealed }),
5774
- /* @__PURE__ */ jsx17(TipContent, { chunks: tip.chunks, revealed: contentRevealed })
5775
- ] });
5623
+ return /* @__PURE__ */ jsx16(TipCard, { tip, revealed });
5776
5624
  }
5777
5625
 
5778
5626
  // src/ui/App.tsx
5779
- import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
5627
+ import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
5780
5628
  function App() {
5781
5629
  const {
5782
5630
  phase,
@@ -5790,7 +5638,7 @@ function App() {
5790
5638
  review: review2
5791
5639
  } = useWizard();
5792
5640
  const { exit } = useApp();
5793
- const { columns, rows } = useWindowSize7();
5641
+ const { columns, rows } = useWindowSize8();
5794
5642
  const [showLogs, setShowLogs] = useState10(false);
5795
5643
  const [tipState, setTipState] = useState10("idle");
5796
5644
  const finished = phase === "done" || phase === "error";
@@ -5803,7 +5651,6 @@ function App() {
5803
5651
  const promptPending = isAwaitingUserInput && !isCommandApprovalPrompt;
5804
5652
  const holdForTip = stepHasTips && promptPending && tipState === "revealing";
5805
5653
  const showTips = stepHasTips && (phase === "running" || isCommandApprovalPrompt || holdForTip);
5806
- const showNoticesInMain = !stepHasTips;
5807
5654
  const showNotices = (!isAwaitingUserInput || holdForTip) && !review2;
5808
5655
  useInput7(
5809
5656
  (_input, key) => {
@@ -5838,14 +5685,15 @@ function App() {
5838
5685
  });
5839
5686
  const mainWindowVisible = phase === "authenticating" || phase === "preflight" || phase === "running" || phase === "awaitingInput" || phase === "error" || phase === "done";
5840
5687
  const flexDirection = columns > 90 ? "row" : "column";
5688
+ const tipPanelRows = Math.min(TIP_PANEL_ROWS, Math.max(8, rows - 16));
5841
5689
  const showSidebar = flexDirection === "row";
5842
5690
  const scrollsPastViewport = phase === "idle" && homeScreen === "learnMore";
5843
5691
  return (
5844
5692
  /* Clamped to exactly the viewport: a taller frame makes Ink clear and repaint
5845
5693
  the whole screen, and the scrolling throws off its cursor arithmetic —
5846
5694
  flicker and leftover rows. */
5847
- /* @__PURE__ */ jsxs18(
5848
- Box20,
5695
+ /* @__PURE__ */ jsxs17(
5696
+ Box19,
5849
5697
  {
5850
5698
  backgroundColor: COLORS.bg.main,
5851
5699
  flexDirection: "row",
@@ -5853,16 +5701,16 @@ function App() {
5853
5701
  height: scrollsPastViewport ? void 0 : rows,
5854
5702
  overflow: scrollsPastViewport ? "visible" : "hidden",
5855
5703
  children: [
5856
- mainWindowVisible && /* @__PURE__ */ jsxs18(
5857
- Box20,
5704
+ mainWindowVisible && /* @__PURE__ */ jsxs17(
5705
+ Box19,
5858
5706
  {
5859
5707
  flexDirection,
5860
5708
  width: "100%",
5861
5709
  maxHeight: rows,
5862
5710
  justifyContent: "space-between",
5863
5711
  children: [
5864
- showLogs ? /* @__PURE__ */ jsx18(Logs, {}) : /* @__PURE__ */ jsxs18(
5865
- Box20,
5712
+ showLogs ? /* @__PURE__ */ jsx17(Logs, {}) : /* @__PURE__ */ jsxs17(
5713
+ Box19,
5866
5714
  {
5867
5715
  flexDirection: "column",
5868
5716
  paddingX: 4,
@@ -5871,49 +5719,67 @@ function App() {
5871
5719
  flexGrow: 1,
5872
5720
  gap: 1,
5873
5721
  children: [
5874
- /* @__PURE__ */ jsxs18(Box20, { flexGrow: 2, flexDirection: "column", children: [
5875
- phase === "preflight" && !user && /* @__PURE__ */ jsx18(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
5876
- /* @__PURE__ */ jsx18(Spinner2, { type: "dots" }),
5722
+ /* @__PURE__ */ jsxs17(Box19, { flexGrow: 2, flexDirection: "column", children: [
5723
+ phase === "preflight" && !user && /* @__PURE__ */ jsx17(Box19, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs17(Text19, { color: COLORS.strong, bold: true, children: [
5724
+ /* @__PURE__ */ jsx17(Spinner2, { type: "dots" }),
5877
5725
  " Signing in to Algolia"
5878
5726
  ] }) }),
5879
- phase === "preflight" && user && /* @__PURE__ */ jsx18(Box20, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
5880
- /* @__PURE__ */ jsx18(Spinner2, { type: "dots" }),
5727
+ phase === "preflight" && user && /* @__PURE__ */ jsx17(Box19, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs17(Text19, { color: COLORS.strong, bold: true, children: [
5728
+ /* @__PURE__ */ jsx17(Spinner2, { type: "dots" }),
5881
5729
  " Getting things ready"
5882
5730
  ] }) }),
5883
- phase === "authenticating" && /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", marginBottom: 1, children: [
5884
- /* @__PURE__ */ jsxs18(Text20, { color: COLORS.strong, bold: true, children: [
5885
- /* @__PURE__ */ jsx18(Spinner2, { type: "dots" }),
5731
+ phase === "authenticating" && /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", marginBottom: 1, children: [
5732
+ /* @__PURE__ */ jsxs17(Text19, { color: COLORS.strong, bold: true, children: [
5733
+ /* @__PURE__ */ jsx17(Spinner2, { type: "dots" }),
5886
5734
  " Signing in to Algolia"
5887
5735
  ] }),
5888
- /* @__PURE__ */ jsx18(Text20, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
5736
+ /* @__PURE__ */ jsx17(Text19, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
5889
5737
  ] }),
5890
- /* @__PURE__ */ jsx18(CliOutput, {}),
5891
- showTips && currentStep && /* @__PURE__ */ jsx18(
5892
- Tips,
5893
- {
5894
- stepId: currentStep.id,
5895
- ids: tipIds,
5896
- onRevealStateChange: setTipState
5897
- }
5898
- ),
5899
- showNoticesInMain && showNotices && /* @__PURE__ */ jsx18(Notices, { showAll: true, border: false }),
5900
- /* @__PURE__ */ jsx18(Review, {}),
5901
- !showTips && /* @__PURE__ */ jsx18(PromptInput, {}),
5902
- phase === "error" && error && /* @__PURE__ */ jsx18(Box20, { marginTop: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: COLORS.status.error, children: [
5738
+ /* @__PURE__ */ jsx17(CliOutput, {}),
5739
+ showNotices && /* @__PURE__ */ jsx17(Notices, { showAll: true, border: false }),
5740
+ /* @__PURE__ */ jsx17(Review, {}),
5741
+ !showTips && /* @__PURE__ */ jsx17(PromptInput, {}),
5742
+ phase === "error" && error && /* @__PURE__ */ jsx17(Box19, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text19, { color: COLORS.status.error, children: [
5903
5743
  "\u2716 ",
5904
5744
  error
5905
5745
  ] }) })
5906
5746
  ] }),
5907
- !showNoticesInMain && showNotices && /* @__PURE__ */ jsx18(Notices, {}),
5908
- showTips && !holdForTip && /* @__PURE__ */ jsx18(PromptInput, {})
5747
+ showTips && currentStep && /* Fixed height: a panel that grew as the tip streamed would
5748
+ re-measure the notice feed above it on every character and
5749
+ walk its scroll window. */
5750
+ /* @__PURE__ */ jsx17(
5751
+ Box19,
5752
+ {
5753
+ borderColor: COLORS.border,
5754
+ borderStyle: "single",
5755
+ borderBackgroundColor: COLORS.bg.main,
5756
+ borderLeft: false,
5757
+ borderRight: false,
5758
+ borderBottom: false,
5759
+ paddingTop: 1,
5760
+ height: tipPanelRows,
5761
+ flexShrink: 0,
5762
+ overflow: "hidden",
5763
+ flexDirection: "column",
5764
+ children: /* @__PURE__ */ jsx17(
5765
+ Tips,
5766
+ {
5767
+ stepId: currentStep.id,
5768
+ ids: tipIds,
5769
+ onRevealStateChange: setTipState
5770
+ }
5771
+ )
5772
+ }
5773
+ ),
5774
+ showTips && !holdForTip && /* @__PURE__ */ jsx17(PromptInput, {})
5909
5775
  ]
5910
5776
  }
5911
5777
  ),
5912
- showSidebar ? /* @__PURE__ */ jsx18(Sidebar, {}) : /* @__PURE__ */ jsx18(Ribbon, {})
5778
+ showSidebar ? /* @__PURE__ */ jsx17(Sidebar, {}) : /* @__PURE__ */ jsx17(Ribbon, {})
5913
5779
  ]
5914
5780
  }
5915
5781
  ),
5916
- phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */ jsx18(LearnMore, {}) : /* @__PURE__ */ jsx18(Welcome, {}))
5782
+ phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */ jsx17(LearnMore, {}) : /* @__PURE__ */ jsx17(Welcome, {}))
5917
5783
  ]
5918
5784
  }
5919
5785
  )
@@ -5921,7 +5787,7 @@ function App() {
5921
5787
  }
5922
5788
 
5923
5789
  // src/lib/envAppId.ts
5924
- import { readFile as readFile8 } from "node:fs/promises";
5790
+ import { readFile as readFile7 } from "node:fs/promises";
5925
5791
  import { join as join12 } from "node:path";
5926
5792
  var ENV_FILES = [".env", ".env.local"];
5927
5793
  var APP_ID_LINE = /^[ \t]*(?:export[ \t]+)?([A-Z0-9_]*ALGOLIA_APP(?:LICATION)?_ID)[ \t]*=[ \t]*(.*)$/gm;
@@ -5929,7 +5795,7 @@ async function findEnvApplicationId(root = process.cwd()) {
5929
5795
  for (const file of ENV_FILES) {
5930
5796
  let content;
5931
5797
  try {
5932
- content = await readFile8(join12(root, file), "utf8");
5798
+ content = await readFile7(join12(root, file), "utf8");
5933
5799
  } catch (err) {
5934
5800
  if (err.code !== "ENOENT") {
5935
5801
  logger.warn(
@@ -6332,7 +6198,7 @@ function delay(ms) {
6332
6198
  }
6333
6199
 
6334
6200
  // src/main.tsx
6335
- import { jsx as jsx19 } from "react/jsx-runtime";
6201
+ import { jsx as jsx18 } from "react/jsx-runtime";
6336
6202
  async function startup() {
6337
6203
  setProjectRoot(process.cwd());
6338
6204
  let args;
@@ -6382,7 +6248,7 @@ ${formatStepList(workflow)}`);
6382
6248
  }
6383
6249
  async function run(workflow) {
6384
6250
  const store = useWizard.getState();
6385
- const instance = render(/* @__PURE__ */ jsx19(App, {}), { incrementalRendering: true });
6251
+ const instance = render(/* @__PURE__ */ jsx18(App, {}), { incrementalRendering: true });
6386
6252
  await store.waitForStart();
6387
6253
  store.syncSteps(
6388
6254
  workflow.steps.map((s) => ({