@algolia/wizard 0.11.0 → 0.12.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.
- package/dist/main.js +512 -281
- 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
|
|
7
|
+
import { Box as Box16, Text as Text16, useApp, useInput as useInput7, useWindowSize as useWindowSize8 } from "ink";
|
|
8
8
|
|
|
9
9
|
// src/core/store.ts
|
|
10
10
|
import { create } from "zustand";
|
|
@@ -304,7 +304,10 @@ var useWizard = create((set, get) => ({
|
|
|
304
304
|
if (_noticeTimer === null) {
|
|
305
305
|
set({
|
|
306
306
|
notices: [...notices, notice],
|
|
307
|
-
_noticeTimer: setTimeout(
|
|
307
|
+
_noticeTimer: setTimeout(
|
|
308
|
+
() => get()._drainNoticeQueue(),
|
|
309
|
+
NOTICE_INTERVAL_MS
|
|
310
|
+
)
|
|
308
311
|
});
|
|
309
312
|
} else {
|
|
310
313
|
set({ _noticeQueue: [..._noticeQueue, notice] });
|
|
@@ -316,7 +319,10 @@ var useWizard = create((set, get) => ({
|
|
|
316
319
|
set((s) => ({
|
|
317
320
|
notices: [...s.notices, next],
|
|
318
321
|
_noticeQueue: rest,
|
|
319
|
-
_noticeTimer: setTimeout(
|
|
322
|
+
_noticeTimer: setTimeout(
|
|
323
|
+
() => get()._drainNoticeQueue(),
|
|
324
|
+
NOTICE_INTERVAL_MS
|
|
325
|
+
)
|
|
320
326
|
}));
|
|
321
327
|
} else {
|
|
322
328
|
set({ _noticeTimer: null });
|
|
@@ -364,13 +370,17 @@ var useWizard = create((set, get) => ({
|
|
|
364
370
|
await markInteraction();
|
|
365
371
|
get()._resolve?.(value);
|
|
366
372
|
set({ inputReq: null, _resolve: null, phase: "running" });
|
|
367
|
-
const id = get().logStart(
|
|
373
|
+
const id = get().logStart(
|
|
374
|
+
"prompt",
|
|
375
|
+
`User input: ${describeInputValue(value)}`
|
|
376
|
+
);
|
|
368
377
|
get().logEnd(id, "success");
|
|
369
378
|
},
|
|
370
379
|
setDone: () => set({ phase: "done" }),
|
|
371
380
|
setError: (message) => set({ phase: "error", error: message }),
|
|
372
381
|
reset: () => {
|
|
373
382
|
get()._clearNoticeQueue();
|
|
383
|
+
get()._resolve?.(false);
|
|
374
384
|
set({
|
|
375
385
|
phase: "idle",
|
|
376
386
|
homeScreen: "home",
|
|
@@ -622,10 +632,13 @@ function Notices() {
|
|
|
622
632
|
}
|
|
623
633
|
|
|
624
634
|
// src/ui/PromptInput.tsx
|
|
625
|
-
import { Box as
|
|
635
|
+
import { Box as Box8, Text as Text8, useInput as useInput3 } from "ink";
|
|
626
636
|
import TextInput from "ink-text-input";
|
|
627
637
|
import { useState as useState5 } from "react";
|
|
628
638
|
|
|
639
|
+
// src/ui/CommandApproval.tsx
|
|
640
|
+
import { Box as Box5, Text as Text5, useInput } from "ink";
|
|
641
|
+
|
|
629
642
|
// src/ui/NextAction.tsx
|
|
630
643
|
import { Box as Box4, Text as Text4 } from "ink";
|
|
631
644
|
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -649,14 +662,60 @@ function NextAction({
|
|
|
649
662
|
] });
|
|
650
663
|
}
|
|
651
664
|
|
|
665
|
+
// src/ui/CommandApproval.tsx
|
|
666
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
667
|
+
function CommandApproval({
|
|
668
|
+
command,
|
|
669
|
+
onDecide
|
|
670
|
+
}) {
|
|
671
|
+
useInput((_input, key) => {
|
|
672
|
+
if (key.return) onDecide("approve");
|
|
673
|
+
else if (key.escape) onDecide("reject");
|
|
674
|
+
});
|
|
675
|
+
return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", gap: 1, children: [
|
|
676
|
+
/* @__PURE__ */ jsx4(Text5, { color: COLORS.primary, bold: true, children: "Run this command?" }),
|
|
677
|
+
/* @__PURE__ */ jsxs4(
|
|
678
|
+
Box5,
|
|
679
|
+
{
|
|
680
|
+
flexDirection: "column",
|
|
681
|
+
paddingLeft: 2,
|
|
682
|
+
borderStyle: "single",
|
|
683
|
+
borderColor: COLORS.success,
|
|
684
|
+
borderTop: false,
|
|
685
|
+
borderBottom: false,
|
|
686
|
+
borderRight: false,
|
|
687
|
+
gap: 1,
|
|
688
|
+
children: [
|
|
689
|
+
/* @__PURE__ */ jsxs4(Box5, { children: [
|
|
690
|
+
/* @__PURE__ */ jsx4(Text5, { color: COLORS.muted, children: "$ " }),
|
|
691
|
+
/* @__PURE__ */ jsx4(Text5, { color: COLORS.strong, wrap: "wrap", children: command.command })
|
|
692
|
+
] }),
|
|
693
|
+
/* @__PURE__ */ jsxs4(Box5, { gap: 1, children: [
|
|
694
|
+
/* @__PURE__ */ jsx4(Text5, { color: COLORS.muted, children: "in:" }),
|
|
695
|
+
/* @__PURE__ */ jsx4(Text5, { color: COLORS.muted, wrap: "wrap", children: command.cwd })
|
|
696
|
+
] }),
|
|
697
|
+
command.explanation && /* @__PURE__ */ jsxs4(Box5, { gap: 1, children: [
|
|
698
|
+
/* @__PURE__ */ jsx4(Text5, { color: COLORS.muted, children: "why:" }),
|
|
699
|
+
/* @__PURE__ */ jsx4(Text5, { color: COLORS.accent, wrap: "wrap", children: command.explanation })
|
|
700
|
+
] })
|
|
701
|
+
]
|
|
702
|
+
}
|
|
703
|
+
),
|
|
704
|
+
/* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
|
|
705
|
+
/* @__PURE__ */ jsx4(NextAction, { action: "approve", keyHint: "enter" }),
|
|
706
|
+
/* @__PURE__ */ jsx4(NextAction, { action: "reject", keyHint: "esc", hierarchy: "secondary" })
|
|
707
|
+
] })
|
|
708
|
+
] });
|
|
709
|
+
}
|
|
710
|
+
|
|
652
711
|
// src/ui/SelectPrompt.tsx
|
|
653
|
-
import { Box as
|
|
712
|
+
import { Box as Box7, Text as Text7, useInput as useInput2, useWindowSize as useWindowSize5 } from "ink";
|
|
654
713
|
import { useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState4 } from "react";
|
|
655
714
|
|
|
656
715
|
// src/ui/ScrollView.tsx
|
|
657
|
-
import { Box as
|
|
716
|
+
import { Box as Box6, Text as Text6, measureElement as measureElement2, useWindowSize as useWindowSize4 } from "ink";
|
|
658
717
|
import { useCallback, useLayoutEffect, useRef as useRef2, useState as useState3 } from "react";
|
|
659
|
-
import { jsxs as
|
|
718
|
+
import { jsxs as jsxs5 } from "react/jsx-runtime";
|
|
660
719
|
var INDICATOR_ROWS = 2;
|
|
661
720
|
function fittedWidth(node, columns) {
|
|
662
721
|
let left = 0;
|
|
@@ -726,14 +785,14 @@ function useScrollWindow({
|
|
|
726
785
|
};
|
|
727
786
|
}
|
|
728
787
|
function ScrollView({ scroll, children }) {
|
|
729
|
-
return /* @__PURE__ */
|
|
730
|
-
scroll.hiddenAbove > 0 && /* @__PURE__ */
|
|
788
|
+
return /* @__PURE__ */ jsxs5(Box6, { ref: scroll.viewportRef, flexDirection: "column", flexGrow: 1, children: [
|
|
789
|
+
scroll.hiddenAbove > 0 && /* @__PURE__ */ jsxs5(Text6, { color: COLORS.dim, children: [
|
|
731
790
|
"\u2191 ",
|
|
732
791
|
scroll.hiddenAbove,
|
|
733
792
|
" more"
|
|
734
793
|
] }),
|
|
735
794
|
children,
|
|
736
|
-
scroll.hiddenBelow > 0 && /* @__PURE__ */
|
|
795
|
+
scroll.hiddenBelow > 0 && /* @__PURE__ */ jsxs5(Text6, { color: COLORS.dim, children: [
|
|
737
796
|
"\u2193 ",
|
|
738
797
|
scroll.hiddenBelow,
|
|
739
798
|
" more"
|
|
@@ -742,7 +801,7 @@ function ScrollView({ scroll, children }) {
|
|
|
742
801
|
}
|
|
743
802
|
|
|
744
803
|
// src/ui/SelectPrompt.tsx
|
|
745
|
-
import { jsx as
|
|
804
|
+
import { jsx as jsx5, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
746
805
|
var CANCEL = "cancel";
|
|
747
806
|
var ARROW_WIDTH = 4;
|
|
748
807
|
var COLUMN_GAP = 2;
|
|
@@ -804,7 +863,7 @@ function SelectPrompt({
|
|
|
804
863
|
revealIndex(index);
|
|
805
864
|
}, [index, revealIndex]);
|
|
806
865
|
const visible = rows.slice(scroll.offset, scroll.offset + scroll.capacity);
|
|
807
|
-
|
|
866
|
+
useInput2((input, key) => {
|
|
808
867
|
if (rows.length === 0) return;
|
|
809
868
|
if (key.upArrow || input === "k") {
|
|
810
869
|
setIndex((i) => (i - 1 + rows.length) % rows.length);
|
|
@@ -827,56 +886,56 @@ function SelectPrompt({
|
|
|
827
886
|
}
|
|
828
887
|
}
|
|
829
888
|
});
|
|
830
|
-
return /* @__PURE__ */
|
|
831
|
-
/* @__PURE__ */
|
|
832
|
-
error && /* @__PURE__ */
|
|
833
|
-
messages?.map((m, i) => /* @__PURE__ */
|
|
834
|
-
table && /* @__PURE__ */
|
|
835
|
-
/* @__PURE__ */
|
|
836
|
-
question && /* @__PURE__ */
|
|
837
|
-
helpText && /* @__PURE__ */
|
|
889
|
+
return /* @__PURE__ */ jsx5(Box7, { ref: containerRef, flexGrow: 1, children: /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", gap: 1, width, children: [
|
|
890
|
+
/* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", gap: 1, flexShrink: 0, children: [
|
|
891
|
+
error && /* @__PURE__ */ jsx5(Text7, { color: COLORS.danger, children: error }),
|
|
892
|
+
messages?.map((m, i) => /* @__PURE__ */ jsx5(Text7, { color: COLORS.muted, children: m }, `msg-${i}`)),
|
|
893
|
+
table && /* @__PURE__ */ jsx5(Table, { columns: table.columns, rows: table.rows }),
|
|
894
|
+
/* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
|
|
895
|
+
question && /* @__PURE__ */ jsx5(Text7, { color: COLORS.muted, children: question }),
|
|
896
|
+
helpText && /* @__PURE__ */ jsx5(Text7, { color: COLORS.dim, children: helpText })
|
|
838
897
|
] })
|
|
839
898
|
] }),
|
|
840
|
-
/* @__PURE__ */
|
|
899
|
+
/* @__PURE__ */ jsx5(ScrollView, { scroll, children: visible.map((option, visibleIndex) => {
|
|
841
900
|
const i = scroll.offset + visibleIndex;
|
|
842
901
|
const highlighted = i === index;
|
|
843
902
|
const isCancel = i === cancelIndex;
|
|
844
903
|
const bullet = multi && !isCancel ? checked.has(i) ? "\u25CF " : "\u25CB " : "";
|
|
845
904
|
const sec = isCancel ? void 0 : secondary?.[i];
|
|
846
905
|
const labelColor = highlighted ? COLORS.highlight.fg : void 0;
|
|
847
|
-
const label = /* @__PURE__ */
|
|
906
|
+
const label = /* @__PURE__ */ jsxs6(Text7, { color: labelColor, wrap: "truncate", children: [
|
|
848
907
|
highlighted ? "\u276F " : " ",
|
|
849
908
|
bullet,
|
|
850
909
|
option
|
|
851
910
|
] });
|
|
852
911
|
const isText = sec?.kind === "text";
|
|
853
|
-
return /* @__PURE__ */
|
|
854
|
-
|
|
912
|
+
return /* @__PURE__ */ jsxs6(
|
|
913
|
+
Box7,
|
|
855
914
|
{
|
|
856
915
|
width: isText ? "100%" : barWidth,
|
|
857
916
|
paddingX: 1,
|
|
858
917
|
paddingY: 1,
|
|
859
918
|
backgroundColor: highlighted ? COLORS.highlight.bg : void 0,
|
|
860
919
|
children: [
|
|
861
|
-
/* @__PURE__ */
|
|
862
|
-
isText && textWidth > 0 && /* @__PURE__ */
|
|
863
|
-
|
|
920
|
+
/* @__PURE__ */ jsx5(Box7, { width: isText ? labelWidth : barLabelWidth, children: label }),
|
|
921
|
+
isText && textWidth > 0 && /* @__PURE__ */ jsx5(Box7, { width: textWidth, children: /* @__PURE__ */ jsx5(
|
|
922
|
+
Text7,
|
|
864
923
|
{
|
|
865
924
|
wrap: "truncate",
|
|
866
925
|
color: highlighted ? COLORS.primary : COLORS.muted,
|
|
867
926
|
children: sec.value
|
|
868
927
|
}
|
|
869
928
|
) }),
|
|
870
|
-
sec?.kind === "badge" && /* @__PURE__ */
|
|
929
|
+
sec?.kind === "badge" && /* @__PURE__ */ jsx5(Box7, { width: badgeWidth, justifyContent: "flex-end", children: /* @__PURE__ */ jsx5(Text7, { color: COLORS.badge, wrap: "truncate", children: sec.value }) })
|
|
871
930
|
]
|
|
872
931
|
},
|
|
873
932
|
`row-${i}`
|
|
874
933
|
);
|
|
875
934
|
}) }),
|
|
876
|
-
/* @__PURE__ */
|
|
935
|
+
/* @__PURE__ */ jsx5(Box7, { flexShrink: 0, children: /* @__PURE__ */ jsx5(Text7, { children: hints.map(({ key, label }, i) => /* @__PURE__ */ jsxs6(Text7, { children: [
|
|
877
936
|
i > 0 ? " " : "",
|
|
878
|
-
/* @__PURE__ */
|
|
879
|
-
/* @__PURE__ */
|
|
937
|
+
/* @__PURE__ */ jsx5(Text7, { color: COLORS.primary, children: key }),
|
|
938
|
+
/* @__PURE__ */ jsxs6(Text7, { color: COLORS.dim, children: [
|
|
880
939
|
" ",
|
|
881
940
|
label
|
|
882
941
|
] })
|
|
@@ -885,23 +944,23 @@ function SelectPrompt({
|
|
|
885
944
|
}
|
|
886
945
|
|
|
887
946
|
// src/ui/PromptInput.tsx
|
|
888
|
-
import { jsx as
|
|
947
|
+
import { jsx as jsx6, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
889
948
|
var ACCEPT_REJECT_OPTIONS = ["Accept", "Reject"];
|
|
890
949
|
function EnterToContinuePrompt({
|
|
891
950
|
question,
|
|
892
951
|
messages,
|
|
893
952
|
onDecide
|
|
894
953
|
}) {
|
|
895
|
-
|
|
954
|
+
useInput3((_input, key) => {
|
|
896
955
|
if (key.return) onDecide(true);
|
|
897
956
|
else if (key.escape) onDecide(false);
|
|
898
957
|
});
|
|
899
|
-
return /* @__PURE__ */
|
|
900
|
-
messages?.map((m, i) => /* @__PURE__ */
|
|
901
|
-
question && /* @__PURE__ */
|
|
902
|
-
/* @__PURE__ */
|
|
903
|
-
/* @__PURE__ */
|
|
904
|
-
/* @__PURE__ */
|
|
958
|
+
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 1, children: [
|
|
959
|
+
messages?.map((m, i) => /* @__PURE__ */ jsx6(Text8, { color: COLORS.muted, children: m }, `msg-${i}`)),
|
|
960
|
+
question && /* @__PURE__ */ jsx6(Text8, { color: COLORS.primary, children: question }),
|
|
961
|
+
/* @__PURE__ */ jsxs7(Box8, { gap: 1, flexDirection: "column", children: [
|
|
962
|
+
/* @__PURE__ */ jsx6(NextAction, { action: "continue", keyHint: "enter" }),
|
|
963
|
+
/* @__PURE__ */ jsx6(NextAction, { action: "decline", keyHint: "esc", hierarchy: "secondary" })
|
|
905
964
|
] })
|
|
906
965
|
] });
|
|
907
966
|
}
|
|
@@ -909,11 +968,11 @@ function PromptInput() {
|
|
|
909
968
|
const { phase, inputReq, submitInput } = useWizard();
|
|
910
969
|
const [draft, setDraft] = useState5("");
|
|
911
970
|
if (phase === "done" || phase === "error") {
|
|
912
|
-
return /* @__PURE__ */
|
|
971
|
+
return /* @__PURE__ */ jsx6(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text8, { color: "gray", dimColor: true, children: "Press Enter or Esc to exit" }) });
|
|
913
972
|
}
|
|
914
973
|
if (phase !== "awaitingInput" || !inputReq) return null;
|
|
915
974
|
if (inputReq.promptType === "multipleChoice") {
|
|
916
|
-
return /* @__PURE__ */
|
|
975
|
+
return /* @__PURE__ */ jsx6(Box8, { flexGrow: 1, children: /* @__PURE__ */ jsx6(
|
|
917
976
|
SelectPrompt,
|
|
918
977
|
{
|
|
919
978
|
question: inputReq.prompt,
|
|
@@ -930,7 +989,7 @@ function PromptInput() {
|
|
|
930
989
|
) });
|
|
931
990
|
}
|
|
932
991
|
if (inputReq.promptType === "multiSelect") {
|
|
933
|
-
return /* @__PURE__ */
|
|
992
|
+
return /* @__PURE__ */ jsx6(Box8, { flexGrow: 1, children: /* @__PURE__ */ jsx6(
|
|
934
993
|
SelectPrompt,
|
|
935
994
|
{
|
|
936
995
|
multi: true,
|
|
@@ -945,7 +1004,7 @@ function PromptInput() {
|
|
|
945
1004
|
) });
|
|
946
1005
|
}
|
|
947
1006
|
if (inputReq.promptType === "notice") {
|
|
948
|
-
return /* @__PURE__ */
|
|
1007
|
+
return /* @__PURE__ */ jsx6(Box8, { flexGrow: 1, children: /* @__PURE__ */ jsx6(
|
|
949
1008
|
SelectPrompt,
|
|
950
1009
|
{
|
|
951
1010
|
question: inputReq.prompt,
|
|
@@ -956,7 +1015,7 @@ function PromptInput() {
|
|
|
956
1015
|
) });
|
|
957
1016
|
}
|
|
958
1017
|
if (inputReq.promptType === "enterToContinue") {
|
|
959
|
-
return /* @__PURE__ */
|
|
1018
|
+
return /* @__PURE__ */ jsx6(
|
|
960
1019
|
EnterToContinuePrompt,
|
|
961
1020
|
{
|
|
962
1021
|
question: inputReq.prompt,
|
|
@@ -965,9 +1024,12 @@ function PromptInput() {
|
|
|
965
1024
|
}
|
|
966
1025
|
);
|
|
967
1026
|
}
|
|
1027
|
+
if (inputReq.promptType === "commandApproval" && inputReq.command) {
|
|
1028
|
+
return /* @__PURE__ */ jsx6(CommandApproval, { command: inputReq.command, onDecide: submitInput });
|
|
1029
|
+
}
|
|
968
1030
|
if (inputReq.promptType === "acceptReject") {
|
|
969
1031
|
const labels = inputReq.options?.length ? inputReq.options : ACCEPT_REJECT_OPTIONS;
|
|
970
|
-
return /* @__PURE__ */
|
|
1032
|
+
return /* @__PURE__ */ jsx6(Box8, { flexGrow: 1, children: /* @__PURE__ */ jsx6(
|
|
971
1033
|
SelectPrompt,
|
|
972
1034
|
{
|
|
973
1035
|
question: inputReq.prompt,
|
|
@@ -978,15 +1040,15 @@ function PromptInput() {
|
|
|
978
1040
|
}
|
|
979
1041
|
) });
|
|
980
1042
|
}
|
|
981
|
-
return /* @__PURE__ */
|
|
982
|
-
inputReq.error && /* @__PURE__ */
|
|
983
|
-
inputReq.messages?.map((m, i) => /* @__PURE__ */
|
|
984
|
-
/* @__PURE__ */
|
|
985
|
-
/* @__PURE__ */
|
|
1043
|
+
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", children: [
|
|
1044
|
+
inputReq.error && /* @__PURE__ */ jsx6(Text8, { color: COLORS.danger, children: inputReq.error }),
|
|
1045
|
+
inputReq.messages?.map((m, i) => /* @__PURE__ */ jsx6(Text8, { color: COLORS.muted, children: m }, `msg-${i}`)),
|
|
1046
|
+
/* @__PURE__ */ jsxs7(Box8, { children: [
|
|
1047
|
+
/* @__PURE__ */ jsxs7(Text8, { color: COLORS.primary, children: [
|
|
986
1048
|
inputReq.prompt,
|
|
987
1049
|
" "
|
|
988
1050
|
] }),
|
|
989
|
-
/* @__PURE__ */
|
|
1051
|
+
/* @__PURE__ */ jsx6(
|
|
990
1052
|
TextInput,
|
|
991
1053
|
{
|
|
992
1054
|
value: draft,
|
|
@@ -1004,7 +1066,7 @@ function PromptInput() {
|
|
|
1004
1066
|
// src/ui/Welcome.tsx
|
|
1005
1067
|
import { dirname as dirname2, join as join3 } from "node:path";
|
|
1006
1068
|
import { fileURLToPath } from "node:url";
|
|
1007
|
-
import { Box as
|
|
1069
|
+
import { Box as Box9, Spacer, Text as Text9, useInput as useInput4, useWindowSize as useWindowSize6 } from "ink";
|
|
1008
1070
|
|
|
1009
1071
|
// src/ui/copy/welcome.ts
|
|
1010
1072
|
var sidebarItems = [
|
|
@@ -1032,20 +1094,20 @@ var sidebarItems = [
|
|
|
1032
1094
|
|
|
1033
1095
|
// src/ui/Welcome.tsx
|
|
1034
1096
|
import Image, { InkPictureProvider } from "ink-picture";
|
|
1035
|
-
import { jsx as
|
|
1097
|
+
import { jsx as jsx7, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1036
1098
|
var IMAGE_PATH = join3(dirname2(fileURLToPath(import.meta.url)), "algolia.png");
|
|
1037
1099
|
function SidebarItem({
|
|
1038
1100
|
title,
|
|
1039
1101
|
description
|
|
1040
1102
|
}) {
|
|
1041
|
-
return /* @__PURE__ */
|
|
1042
|
-
/* @__PURE__ */
|
|
1043
|
-
/* @__PURE__ */
|
|
1044
|
-
/* @__PURE__ */
|
|
1103
|
+
return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", children: [
|
|
1104
|
+
/* @__PURE__ */ jsxs8(Box9, { gap: 1, children: [
|
|
1105
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.success, children: "\u2192" }),
|
|
1106
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.strong, bold: true, children: title })
|
|
1045
1107
|
] }),
|
|
1046
|
-
/* @__PURE__ */
|
|
1047
|
-
/* @__PURE__ */
|
|
1048
|
-
/* @__PURE__ */
|
|
1108
|
+
/* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", gap: 2, children: [
|
|
1109
|
+
/* @__PURE__ */ jsx7(Spacer, {}),
|
|
1110
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: description })
|
|
1049
1111
|
] })
|
|
1050
1112
|
] });
|
|
1051
1113
|
}
|
|
@@ -1053,7 +1115,7 @@ function Welcome() {
|
|
|
1053
1115
|
const confirmStart = useWizard((s) => s.confirmStart);
|
|
1054
1116
|
const openLearnMore = useWizard((s) => s.openLearnMore);
|
|
1055
1117
|
const { rows } = useWindowSize6();
|
|
1056
|
-
|
|
1118
|
+
useInput4((input, key) => {
|
|
1057
1119
|
if (key.return) confirmStart();
|
|
1058
1120
|
else if (input === "i") openLearnMore();
|
|
1059
1121
|
});
|
|
@@ -1071,16 +1133,16 @@ function Welcome() {
|
|
|
1071
1133
|
if (rows < 30) {
|
|
1072
1134
|
layout = scales["small"];
|
|
1073
1135
|
}
|
|
1074
|
-
return /* @__PURE__ */
|
|
1075
|
-
/* @__PURE__ */
|
|
1076
|
-
|
|
1136
|
+
return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", justifyContent: "space-between", width: "100%", children: [
|
|
1137
|
+
/* @__PURE__ */ jsx7(
|
|
1138
|
+
Box9,
|
|
1077
1139
|
{
|
|
1078
1140
|
paddingY: layout.main.padding.y,
|
|
1079
1141
|
paddingX: layout.main.padding.x,
|
|
1080
1142
|
flexDirection: "column",
|
|
1081
1143
|
justifyContent: "center",
|
|
1082
|
-
children: /* @__PURE__ */
|
|
1083
|
-
/* @__PURE__ */
|
|
1144
|
+
children: /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", gap: 2, children: [
|
|
1145
|
+
/* @__PURE__ */ jsx7(InkPictureProvider, { children: /* @__PURE__ */ jsx7(
|
|
1084
1146
|
Image,
|
|
1085
1147
|
{
|
|
1086
1148
|
src: IMAGE_PATH,
|
|
@@ -1091,16 +1153,16 @@ function Welcome() {
|
|
|
1091
1153
|
protocol: "halfBlock"
|
|
1092
1154
|
}
|
|
1093
1155
|
) }),
|
|
1094
|
-
/* @__PURE__ */
|
|
1095
|
-
/* @__PURE__ */
|
|
1096
|
-
/* @__PURE__ */
|
|
1097
|
-
/* @__PURE__ */
|
|
1156
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: "\u2726 From zero \u2192 working search in ~10 minutes" }),
|
|
1157
|
+
/* @__PURE__ */ jsxs8(Box9, { gap: 1, flexDirection: "column", children: [
|
|
1158
|
+
/* @__PURE__ */ jsx7(NextAction, { action: "start wizard", keyHint: "enter" }),
|
|
1159
|
+
/* @__PURE__ */ jsx7(NextAction, { action: "learn more", keyHint: "i", hierarchy: "secondary" })
|
|
1098
1160
|
] })
|
|
1099
1161
|
] })
|
|
1100
1162
|
}
|
|
1101
1163
|
),
|
|
1102
|
-
/* @__PURE__ */
|
|
1103
|
-
|
|
1164
|
+
/* @__PURE__ */ jsxs8(
|
|
1165
|
+
Box9,
|
|
1104
1166
|
{
|
|
1105
1167
|
backgroundColor: COLORS.bg.sidebar,
|
|
1106
1168
|
width: 40,
|
|
@@ -1110,8 +1172,8 @@ function Welcome() {
|
|
|
1110
1172
|
flexDirection: "column",
|
|
1111
1173
|
justifyContent: "center",
|
|
1112
1174
|
children: [
|
|
1113
|
-
/* @__PURE__ */
|
|
1114
|
-
sidebarItems.map((i, idx) => /* @__PURE__ */
|
|
1175
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: "WHAT THIS WIZARD WILL DO" }),
|
|
1176
|
+
sidebarItems.map((i, idx) => /* @__PURE__ */ jsx7(SidebarItem, { title: i.title, description: i.description }, idx))
|
|
1115
1177
|
]
|
|
1116
1178
|
}
|
|
1117
1179
|
)
|
|
@@ -1120,7 +1182,7 @@ function Welcome() {
|
|
|
1120
1182
|
|
|
1121
1183
|
// src/ui/LearnMore.tsx
|
|
1122
1184
|
import { Fragment as Fragment2 } from "react";
|
|
1123
|
-
import { Box as
|
|
1185
|
+
import { Box as Box10, Text as Text10, useInput as useInput5, useWindowSize as useWindowSize7 } from "ink";
|
|
1124
1186
|
|
|
1125
1187
|
// src/ui/copy/learn-more.ts
|
|
1126
1188
|
var accessIntro = "Everything runs locally on your machine. Nothing is written or sent without an explicit yes from you.";
|
|
@@ -1128,12 +1190,17 @@ var accessItems = [
|
|
|
1128
1190
|
{
|
|
1129
1191
|
tag: "READ",
|
|
1130
1192
|
title: "Project files",
|
|
1131
|
-
description: "reads
|
|
1193
|
+
description: "reads manifests, configs & source to detect your stack. Read-only; nothing is uploaded."
|
|
1132
1194
|
},
|
|
1133
1195
|
{
|
|
1134
1196
|
tag: "WRITE",
|
|
1135
1197
|
title: "Code changes",
|
|
1136
|
-
description: "creates & edits files (search UI, config)
|
|
1198
|
+
description: "creates & edits files (search UI, config) in a throwaway git worktree \u2014 your checkout is never touched."
|
|
1199
|
+
},
|
|
1200
|
+
{
|
|
1201
|
+
tag: "EXEC",
|
|
1202
|
+
title: "Setup commands",
|
|
1203
|
+
description: "runs dependency installs, the ingestion script & your own checks. Every command is shown in full and needs your OK; its output is shown as-is, so a command that prints a secret will display it."
|
|
1137
1204
|
},
|
|
1138
1205
|
{
|
|
1139
1206
|
tag: "NET",
|
|
@@ -1143,13 +1210,13 @@ var accessItems = [
|
|
|
1143
1210
|
{
|
|
1144
1211
|
tag: "KEY",
|
|
1145
1212
|
title: "Credentials",
|
|
1146
|
-
description: "
|
|
1213
|
+
description: "writes your Algolia app id and a search-only key (safe to expose) to .env in the worktree."
|
|
1147
1214
|
}
|
|
1148
1215
|
];
|
|
1149
1216
|
var neverItems = [
|
|
1150
1217
|
"Send your source code to a model or third party",
|
|
1151
1218
|
"Commit or push to git",
|
|
1152
|
-
"
|
|
1219
|
+
"Run a command you haven't approved"
|
|
1153
1220
|
];
|
|
1154
1221
|
var policyLinks = [
|
|
1155
1222
|
{ label: "Terms", url: "https://www.algolia.com/policies/terms" },
|
|
@@ -1157,10 +1224,11 @@ var policyLinks = [
|
|
|
1157
1224
|
];
|
|
1158
1225
|
|
|
1159
1226
|
// src/ui/LearnMore.tsx
|
|
1160
|
-
import { jsx as
|
|
1227
|
+
import { jsx as jsx8, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1161
1228
|
var TAG_COLORS = {
|
|
1162
1229
|
READ: COLORS.success,
|
|
1163
1230
|
WRITE: COLORS.badge,
|
|
1231
|
+
EXEC: COLORS.danger,
|
|
1164
1232
|
NET: COLORS.accent,
|
|
1165
1233
|
KEY: COLORS.muted
|
|
1166
1234
|
};
|
|
@@ -1173,12 +1241,12 @@ function NeverLine({
|
|
|
1173
1241
|
}) {
|
|
1174
1242
|
const used = segments.reduce((n, s) => n + s.text.length, 0);
|
|
1175
1243
|
const rightPad = Math.max(0, width - 2 - NEVER_BOX_PAD_X - used);
|
|
1176
|
-
return /* @__PURE__ */
|
|
1177
|
-
/* @__PURE__ */
|
|
1244
|
+
return /* @__PURE__ */ jsxs9(Text10, { children: [
|
|
1245
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.danger, children: "\u2502" }),
|
|
1178
1246
|
" ".repeat(NEVER_BOX_PAD_X),
|
|
1179
|
-
segments.map((s, i) => /* @__PURE__ */
|
|
1247
|
+
segments.map((s, i) => /* @__PURE__ */ jsx8(Text10, { color: s.color, bold: s.bold, children: s.text }, i)),
|
|
1180
1248
|
" ".repeat(rightPad),
|
|
1181
|
-
/* @__PURE__ */
|
|
1249
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.danger, children: "\u2502" })
|
|
1182
1250
|
] });
|
|
1183
1251
|
}
|
|
1184
1252
|
function LearnMore() {
|
|
@@ -1186,12 +1254,12 @@ function LearnMore() {
|
|
|
1186
1254
|
const backToHome = useWizard((s) => s.backToHome);
|
|
1187
1255
|
const { columns } = useWindowSize7();
|
|
1188
1256
|
const dividerWidth = Math.max(0, columns - PADDING_X * 2);
|
|
1189
|
-
|
|
1257
|
+
useInput5((_input, key) => {
|
|
1190
1258
|
if (key.escape) backToHome();
|
|
1191
1259
|
else if (key.return) confirmStart();
|
|
1192
1260
|
});
|
|
1193
|
-
return /* @__PURE__ */
|
|
1194
|
-
|
|
1261
|
+
return /* @__PURE__ */ jsxs9(
|
|
1262
|
+
Box10,
|
|
1195
1263
|
{
|
|
1196
1264
|
flexDirection: "column",
|
|
1197
1265
|
paddingX: PADDING_X,
|
|
@@ -1199,31 +1267,31 @@ function LearnMore() {
|
|
|
1199
1267
|
width: "100%",
|
|
1200
1268
|
gap: 1,
|
|
1201
1269
|
children: [
|
|
1202
|
-
/* @__PURE__ */
|
|
1203
|
-
/* @__PURE__ */
|
|
1204
|
-
/* @__PURE__ */
|
|
1205
|
-
/* @__PURE__ */
|
|
1206
|
-
/* @__PURE__ */
|
|
1207
|
-
/* @__PURE__ */
|
|
1208
|
-
/* @__PURE__ */
|
|
1209
|
-
/* @__PURE__ */
|
|
1210
|
-
/* @__PURE__ */
|
|
1270
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.strong, bold: true, children: "What algolia wizard accesses" }),
|
|
1271
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.muted, children: accessIntro }),
|
|
1272
|
+
/* @__PURE__ */ jsx8(Box10, { flexDirection: "column", children: accessItems.map((item) => /* @__PURE__ */ jsxs9(Box10, { flexDirection: "column", marginTop: 1, children: [
|
|
1273
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.border, children: "\u2500".repeat(dividerWidth) }),
|
|
1274
|
+
/* @__PURE__ */ jsxs9(Box10, { flexDirection: "row", gap: 1, marginTop: 1, children: [
|
|
1275
|
+
/* @__PURE__ */ jsx8(Box10, { width: TAG_COLUMN_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx8(Text10, { color: TAG_COLORS[item.tag], bold: true, children: `[${item.tag}]` }) }),
|
|
1276
|
+
/* @__PURE__ */ jsx8(Box10, { flexDirection: "column", children: /* @__PURE__ */ jsxs9(Text10, { children: [
|
|
1277
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.strong, bold: true, children: item.title }),
|
|
1278
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.muted, children: ` \u2014 ${item.description}` })
|
|
1211
1279
|
] }) })
|
|
1212
1280
|
] })
|
|
1213
1281
|
] }, item.tag)) }),
|
|
1214
|
-
/* @__PURE__ */
|
|
1215
|
-
/* @__PURE__ */
|
|
1216
|
-
/* @__PURE__ */
|
|
1217
|
-
/* @__PURE__ */
|
|
1282
|
+
/* @__PURE__ */ jsxs9(Box10, { marginTop: 1, flexDirection: "column", children: [
|
|
1283
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.danger, children: `\u256D${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256E` }),
|
|
1284
|
+
/* @__PURE__ */ jsx8(NeverLine, { width: dividerWidth }),
|
|
1285
|
+
/* @__PURE__ */ jsx8(
|
|
1218
1286
|
NeverLine,
|
|
1219
1287
|
{
|
|
1220
1288
|
width: dividerWidth,
|
|
1221
1289
|
segments: [{ text: "I NEVER", color: COLORS.danger, bold: true }]
|
|
1222
1290
|
}
|
|
1223
1291
|
),
|
|
1224
|
-
neverItems.map((item) => /* @__PURE__ */
|
|
1225
|
-
/* @__PURE__ */
|
|
1226
|
-
/* @__PURE__ */
|
|
1292
|
+
neverItems.map((item) => /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
1293
|
+
/* @__PURE__ */ jsx8(NeverLine, { width: dividerWidth }),
|
|
1294
|
+
/* @__PURE__ */ jsx8(
|
|
1227
1295
|
NeverLine,
|
|
1228
1296
|
{
|
|
1229
1297
|
width: dividerWidth,
|
|
@@ -1235,24 +1303,24 @@ function LearnMore() {
|
|
|
1235
1303
|
}
|
|
1236
1304
|
)
|
|
1237
1305
|
] }, item)),
|
|
1238
|
-
/* @__PURE__ */
|
|
1239
|
-
/* @__PURE__ */
|
|
1306
|
+
/* @__PURE__ */ jsx8(NeverLine, { width: dividerWidth }),
|
|
1307
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.danger, children: `\u2570${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256F` })
|
|
1240
1308
|
] }),
|
|
1241
|
-
/* @__PURE__ */
|
|
1242
|
-
/* @__PURE__ */
|
|
1243
|
-
/* @__PURE__ */
|
|
1309
|
+
/* @__PURE__ */ jsx8(Box10, { marginTop: 1, flexDirection: "column", children: policyLinks.map((link) => /* @__PURE__ */ jsxs9(Box10, { flexDirection: "row", gap: 1, children: [
|
|
1310
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.strong, bold: true, children: `${link.label}:` }),
|
|
1311
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.accent, children: link.url })
|
|
1244
1312
|
] }, link.label)) }),
|
|
1245
|
-
/* @__PURE__ */
|
|
1246
|
-
/* @__PURE__ */
|
|
1247
|
-
/* @__PURE__ */
|
|
1248
|
-
/* @__PURE__ */
|
|
1249
|
-
/* @__PURE__ */
|
|
1313
|
+
/* @__PURE__ */ jsxs9(Box10, { marginTop: 1, flexDirection: "row", gap: 3, children: [
|
|
1314
|
+
/* @__PURE__ */ jsxs9(Box10, { flexDirection: "row", gap: 1, children: [
|
|
1315
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.muted, children: "[" }),
|
|
1316
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.primary, children: "esc" }),
|
|
1317
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.muted, children: "] back" })
|
|
1250
1318
|
] }),
|
|
1251
|
-
/* @__PURE__ */
|
|
1252
|
-
/* @__PURE__ */
|
|
1253
|
-
/* @__PURE__ */
|
|
1254
|
-
/* @__PURE__ */
|
|
1255
|
-
/* @__PURE__ */
|
|
1319
|
+
/* @__PURE__ */ jsxs9(Box10, { flexDirection: "row", gap: 1, children: [
|
|
1320
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.muted, children: "[" }),
|
|
1321
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.primary, children: "enter" }),
|
|
1322
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.muted, children: "]" }),
|
|
1323
|
+
/* @__PURE__ */ jsx8(Text10, { color: COLORS.success, bold: true, children: "start wizard" })
|
|
1256
1324
|
] })
|
|
1257
1325
|
] })
|
|
1258
1326
|
]
|
|
@@ -1261,10 +1329,10 @@ function LearnMore() {
|
|
|
1261
1329
|
}
|
|
1262
1330
|
|
|
1263
1331
|
// src/ui/Sidebar.tsx
|
|
1264
|
-
import { Box as
|
|
1332
|
+
import { Box as Box13, Text as Text13 } from "ink";
|
|
1265
1333
|
|
|
1266
1334
|
// src/ui/Steps.tsx
|
|
1267
|
-
import { Box as
|
|
1335
|
+
import { Box as Box11, Text as Text11 } from "ink";
|
|
1268
1336
|
import Spinner from "ink-spinner";
|
|
1269
1337
|
|
|
1270
1338
|
// src/core/persistence.ts
|
|
@@ -1293,12 +1361,12 @@ async function clearWorkflowState(workflowId) {
|
|
|
1293
1361
|
}
|
|
1294
1362
|
|
|
1295
1363
|
// src/ui/Steps.tsx
|
|
1296
|
-
import { jsx as
|
|
1364
|
+
import { jsx as jsx9, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1297
1365
|
function Steps() {
|
|
1298
1366
|
const { steps } = useWizard();
|
|
1299
1367
|
const visibleSteps = steps.filter(isStepVisible);
|
|
1300
|
-
return /* @__PURE__ */
|
|
1301
|
-
s.status === "running" ? /* @__PURE__ */
|
|
1368
|
+
return /* @__PURE__ */ jsx9(Box11, { flexDirection: "column", gap: 1, children: visibleSteps.map((s) => /* @__PURE__ */ jsx9(Box11, { flexDirection: "column", children: /* @__PURE__ */ jsxs10(Text11, { color: COLORS.status[s.status], children: [
|
|
1369
|
+
s.status === "running" ? /* @__PURE__ */ jsx9(Spinner, { type: "dots" }) : MARKER[s.status],
|
|
1302
1370
|
" ",
|
|
1303
1371
|
s.title
|
|
1304
1372
|
] }) }, s.id)) });
|
|
@@ -1307,27 +1375,27 @@ function CurrentStep() {
|
|
|
1307
1375
|
const { steps } = useWizard();
|
|
1308
1376
|
const currentStep = steps.filter(isStepVisible).find((s) => s.status === "running");
|
|
1309
1377
|
if (!currentStep) return null;
|
|
1310
|
-
return /* @__PURE__ */
|
|
1311
|
-
/* @__PURE__ */
|
|
1378
|
+
return /* @__PURE__ */ jsxs10(Text11, { color: COLORS.status.running, children: [
|
|
1379
|
+
/* @__PURE__ */ jsx9(Spinner, { type: "dots" }),
|
|
1312
1380
|
" ",
|
|
1313
1381
|
` ${currentStep.title}`
|
|
1314
1382
|
] });
|
|
1315
1383
|
}
|
|
1316
1384
|
|
|
1317
1385
|
// src/ui/Progress.tsx
|
|
1318
|
-
import { Box as
|
|
1319
|
-
import { jsx as
|
|
1386
|
+
import { Box as Box12, Text as Text12 } from "ink";
|
|
1387
|
+
import { jsx as jsx10, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1320
1388
|
function Progress() {
|
|
1321
1389
|
const { steps, currentStepIndex } = useWizard();
|
|
1322
1390
|
const visibleSteps = steps.filter(isStepVisible);
|
|
1323
1391
|
if (visibleSteps.length === 0) return null;
|
|
1324
1392
|
const visibleCountThroughCurrent = steps.slice(0, currentStepIndex + 1).filter(isStepVisible).length;
|
|
1325
1393
|
const activeStepNumber = Math.max(1, visibleCountThroughCurrent);
|
|
1326
|
-
return /* @__PURE__ */
|
|
1327
|
-
/* @__PURE__ */
|
|
1328
|
-
/* @__PURE__ */
|
|
1329
|
-
/* @__PURE__ */
|
|
1330
|
-
/* @__PURE__ */
|
|
1394
|
+
return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, children: [
|
|
1395
|
+
/* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "STEP" }),
|
|
1396
|
+
/* @__PURE__ */ jsx10(Text12, { bold: true, children: activeStepNumber }),
|
|
1397
|
+
/* @__PURE__ */ jsx10(Text12, { bold: true, children: "/" }),
|
|
1398
|
+
/* @__PURE__ */ jsx10(Text12, { bold: true, children: visibleSteps.length })
|
|
1331
1399
|
] });
|
|
1332
1400
|
}
|
|
1333
1401
|
|
|
@@ -1338,10 +1406,10 @@ var sidebarCommands = [
|
|
|
1338
1406
|
];
|
|
1339
1407
|
|
|
1340
1408
|
// src/ui/Sidebar.tsx
|
|
1341
|
-
import { jsx as
|
|
1409
|
+
import { jsx as jsx11, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1342
1410
|
function Sidebar() {
|
|
1343
|
-
return /* @__PURE__ */
|
|
1344
|
-
|
|
1411
|
+
return /* @__PURE__ */ jsxs12(
|
|
1412
|
+
Box13,
|
|
1345
1413
|
{
|
|
1346
1414
|
backgroundColor: "#14171E",
|
|
1347
1415
|
width: 30,
|
|
@@ -1350,16 +1418,16 @@ function Sidebar() {
|
|
|
1350
1418
|
flexDirection: "column",
|
|
1351
1419
|
justifyContent: "space-between",
|
|
1352
1420
|
children: [
|
|
1353
|
-
/* @__PURE__ */
|
|
1354
|
-
/* @__PURE__ */
|
|
1355
|
-
/* @__PURE__ */
|
|
1421
|
+
/* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", gap: 1, children: [
|
|
1422
|
+
/* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: "PROGRESS" }),
|
|
1423
|
+
/* @__PURE__ */ jsx11(Steps, {})
|
|
1356
1424
|
] }),
|
|
1357
|
-
/* @__PURE__ */
|
|
1358
|
-
/* @__PURE__ */
|
|
1359
|
-
/* @__PURE__ */
|
|
1360
|
-
return /* @__PURE__ */
|
|
1361
|
-
/* @__PURE__ */
|
|
1362
|
-
/* @__PURE__ */
|
|
1425
|
+
/* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", gap: 1, children: [
|
|
1426
|
+
/* @__PURE__ */ jsx11(Progress, {}),
|
|
1427
|
+
/* @__PURE__ */ jsx11(Box13, { flexDirection: "column", children: sidebarCommands.map((c) => {
|
|
1428
|
+
return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "row", gap: 1, children: [
|
|
1429
|
+
/* @__PURE__ */ jsx11(Text13, { color: COLORS.primary, children: `[${c.keyHint}]` }),
|
|
1430
|
+
/* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: c.description })
|
|
1363
1431
|
] });
|
|
1364
1432
|
}) })
|
|
1365
1433
|
] })
|
|
@@ -1369,12 +1437,12 @@ function Sidebar() {
|
|
|
1369
1437
|
}
|
|
1370
1438
|
|
|
1371
1439
|
// src/ui/Ribbon.tsx
|
|
1372
|
-
import { Box as
|
|
1373
|
-
import { jsx as
|
|
1440
|
+
import { Box as Box14, Text as Text14 } from "ink";
|
|
1441
|
+
import { jsx as jsx12, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1374
1442
|
function Ribbon() {
|
|
1375
1443
|
const firstCommand = sidebarCommands[0];
|
|
1376
|
-
return /* @__PURE__ */
|
|
1377
|
-
|
|
1444
|
+
return /* @__PURE__ */ jsxs13(
|
|
1445
|
+
Box14,
|
|
1378
1446
|
{
|
|
1379
1447
|
backgroundColor: "#14171E",
|
|
1380
1448
|
flexDirection: "row",
|
|
@@ -1382,11 +1450,11 @@ function Ribbon() {
|
|
|
1382
1450
|
paddingX: 2,
|
|
1383
1451
|
paddingY: 1,
|
|
1384
1452
|
children: [
|
|
1385
|
-
/* @__PURE__ */
|
|
1386
|
-
/* @__PURE__ */
|
|
1387
|
-
/* @__PURE__ */
|
|
1388
|
-
/* @__PURE__ */
|
|
1389
|
-
/* @__PURE__ */
|
|
1453
|
+
/* @__PURE__ */ jsx12(Progress, {}),
|
|
1454
|
+
/* @__PURE__ */ jsx12(CurrentStep, {}),
|
|
1455
|
+
/* @__PURE__ */ jsxs13(Box14, { flexDirection: "row", gap: 1, children: [
|
|
1456
|
+
/* @__PURE__ */ jsx12(Text14, { color: COLORS.primary, children: `[${firstCommand.keyHint}]` }),
|
|
1457
|
+
/* @__PURE__ */ jsx12(Text14, { color: COLORS.muted, children: firstCommand.description })
|
|
1390
1458
|
] })
|
|
1391
1459
|
]
|
|
1392
1460
|
}
|
|
@@ -1397,8 +1465,8 @@ function Ribbon() {
|
|
|
1397
1465
|
import { useState as useState6 } from "react";
|
|
1398
1466
|
|
|
1399
1467
|
// src/ui/Logs.tsx
|
|
1400
|
-
import { Box as
|
|
1401
|
-
import { jsx as
|
|
1468
|
+
import { Box as Box15, Text as Text15, useInput as useInput6 } from "ink";
|
|
1469
|
+
import { jsx as jsx13, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1402
1470
|
var KIND_COLOR = {
|
|
1403
1471
|
tool: COLORS.primary,
|
|
1404
1472
|
prompt: COLORS.badge
|
|
@@ -1429,14 +1497,14 @@ function formatTimestamp(ms) {
|
|
|
1429
1497
|
function Logs() {
|
|
1430
1498
|
const logs = useWizard((s) => s.logs);
|
|
1431
1499
|
const scroll = useScrollWindow({ itemCount: logs.length, followBottom: true });
|
|
1432
|
-
|
|
1500
|
+
useInput6((_input, key) => {
|
|
1433
1501
|
if (key.upArrow) scroll.scrollBy(-1);
|
|
1434
1502
|
else if (key.downArrow) scroll.scrollBy(1);
|
|
1435
1503
|
});
|
|
1436
1504
|
const visible = logs.slice(scroll.offset, scroll.offset + scroll.capacity);
|
|
1437
|
-
return /* @__PURE__ */
|
|
1438
|
-
logs.length === 0 && /* @__PURE__ */
|
|
1439
|
-
/* @__PURE__ */
|
|
1505
|
+
return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", paddingX: 4, paddingY: 2, flexGrow: 1, children: [
|
|
1506
|
+
logs.length === 0 && /* @__PURE__ */ jsx13(Text15, { color: COLORS.dim, children: "No logs yet." }),
|
|
1507
|
+
/* @__PURE__ */ jsx13(ScrollView, { scroll, children: visible.map((entry) => {
|
|
1440
1508
|
const timestamp = `[${formatTimestamp(entry.startedAt)}]`;
|
|
1441
1509
|
const durationText = entry.kind === "tool" && entry.durationMs !== void 0 ? `${entry.durationMs}ms` : "";
|
|
1442
1510
|
const rawPreview = rawInputText(entry.input);
|
|
@@ -1446,14 +1514,14 @@ function Logs() {
|
|
|
1446
1514
|
const name = truncate2(entry.name, budget);
|
|
1447
1515
|
budget -= name.length;
|
|
1448
1516
|
const preview = rawPreview ? truncate2(rawPreview, budget) : "";
|
|
1449
|
-
return /* @__PURE__ */
|
|
1450
|
-
/* @__PURE__ */
|
|
1451
|
-
/* @__PURE__ */
|
|
1452
|
-
preview && /* @__PURE__ */
|
|
1453
|
-
durationText && /* @__PURE__ */
|
|
1517
|
+
return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "row", gap: ROW_GAP, children: [
|
|
1518
|
+
/* @__PURE__ */ jsx13(Text15, { color: COLORS.dim, children: timestamp }),
|
|
1519
|
+
/* @__PURE__ */ jsx13(Text15, { color: logNameColor(entry), wrap: "truncate", children: name }),
|
|
1520
|
+
preview && /* @__PURE__ */ jsx13(Text15, { color: COLORS.dim, wrap: "truncate", children: preview }),
|
|
1521
|
+
durationText && /* @__PURE__ */ jsx13(Text15, { color: COLORS.dim, children: durationText })
|
|
1454
1522
|
] }, entry.id);
|
|
1455
1523
|
}) }),
|
|
1456
|
-
/* @__PURE__ */
|
|
1524
|
+
/* @__PURE__ */ jsx13(Text15, { color: COLORS.dim, children: "\u2191/\u2193 scroll" })
|
|
1457
1525
|
] });
|
|
1458
1526
|
}
|
|
1459
1527
|
|
|
@@ -1645,7 +1713,7 @@ function track(event, payload) {
|
|
|
1645
1713
|
}
|
|
1646
1714
|
|
|
1647
1715
|
// src/ui/App.tsx
|
|
1648
|
-
import { jsx as
|
|
1716
|
+
import { jsx as jsx14, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1649
1717
|
function App() {
|
|
1650
1718
|
const { phase, error, homeScreen, currentStepIndex, steps, inputReq } = useWizard();
|
|
1651
1719
|
const { exit } = useApp();
|
|
@@ -1653,7 +1721,7 @@ function App() {
|
|
|
1653
1721
|
const [showLogs, setShowLogs] = useState6(false);
|
|
1654
1722
|
const finished = phase === "done" || phase === "error";
|
|
1655
1723
|
const currentStep = steps[currentStepIndex];
|
|
1656
|
-
|
|
1724
|
+
useInput7(
|
|
1657
1725
|
(_input, key) => {
|
|
1658
1726
|
if (key.return) {
|
|
1659
1727
|
exit();
|
|
@@ -1661,7 +1729,7 @@ function App() {
|
|
|
1661
1729
|
},
|
|
1662
1730
|
{ isActive: finished }
|
|
1663
1731
|
);
|
|
1664
|
-
|
|
1732
|
+
useInput7((_input, key) => {
|
|
1665
1733
|
if (phase === "idle" || phase === "authenticating") return;
|
|
1666
1734
|
if (key.tab) {
|
|
1667
1735
|
setShowLogs(!showLogs);
|
|
@@ -1672,8 +1740,8 @@ function App() {
|
|
|
1672
1740
|
});
|
|
1673
1741
|
}
|
|
1674
1742
|
});
|
|
1675
|
-
const escOwnedElsewhere = phase === "idle" || phase === "authenticating" || phase === "awaitingInput" && inputReq?.promptType === "enterToContinue";
|
|
1676
|
-
|
|
1743
|
+
const escOwnedElsewhere = phase === "idle" || phase === "authenticating" || phase === "awaitingInput" && (inputReq?.promptType === "enterToContinue" || inputReq?.promptType === "commandApproval");
|
|
1744
|
+
useInput7((_input, key) => {
|
|
1677
1745
|
if (escOwnedElsewhere) return;
|
|
1678
1746
|
if (key.escape) {
|
|
1679
1747
|
track("AI Wizard Interaction", {
|
|
@@ -1692,8 +1760,8 @@ function App() {
|
|
|
1692
1760
|
/* Clamped to exactly the viewport: a taller frame makes Ink clear and repaint
|
|
1693
1761
|
the whole screen, and the scrolling throws off its cursor arithmetic —
|
|
1694
1762
|
flicker and leftover rows. */
|
|
1695
|
-
/* @__PURE__ */
|
|
1696
|
-
|
|
1763
|
+
/* @__PURE__ */ jsxs15(
|
|
1764
|
+
Box16,
|
|
1697
1765
|
{
|
|
1698
1766
|
backgroundColor: COLORS.bg.main,
|
|
1699
1767
|
flexDirection: "row",
|
|
@@ -1701,16 +1769,16 @@ function App() {
|
|
|
1701
1769
|
height: scrollsPastViewport ? void 0 : rows,
|
|
1702
1770
|
overflow: scrollsPastViewport ? "visible" : "hidden",
|
|
1703
1771
|
children: [
|
|
1704
|
-
mainWindowVisible && /* @__PURE__ */
|
|
1705
|
-
|
|
1772
|
+
mainWindowVisible && /* @__PURE__ */ jsxs15(
|
|
1773
|
+
Box16,
|
|
1706
1774
|
{
|
|
1707
1775
|
flexDirection,
|
|
1708
1776
|
width: "100%",
|
|
1709
1777
|
maxHeight: rows,
|
|
1710
1778
|
justifyContent: "space-between",
|
|
1711
1779
|
children: [
|
|
1712
|
-
showLogs ? /* @__PURE__ */
|
|
1713
|
-
|
|
1780
|
+
showLogs ? /* @__PURE__ */ jsx14(Logs, {}) : /* @__PURE__ */ jsxs15(
|
|
1781
|
+
Box16,
|
|
1714
1782
|
{
|
|
1715
1783
|
flexDirection: "column",
|
|
1716
1784
|
paddingX: 4,
|
|
@@ -1718,26 +1786,26 @@ function App() {
|
|
|
1718
1786
|
width: showSidebar ? 70 : "100%",
|
|
1719
1787
|
flexGrow: 1,
|
|
1720
1788
|
children: [
|
|
1721
|
-
phase === "authenticating" && /* @__PURE__ */
|
|
1722
|
-
/* @__PURE__ */
|
|
1723
|
-
/* @__PURE__ */
|
|
1789
|
+
phase === "authenticating" && /* @__PURE__ */ jsxs15(Box16, { flexDirection: "column", marginBottom: 1, children: [
|
|
1790
|
+
/* @__PURE__ */ jsx14(Text16, { color: COLORS.strong, bold: true, children: "Signing in to Algolia" }),
|
|
1791
|
+
/* @__PURE__ */ jsx14(Text16, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
|
|
1724
1792
|
] }),
|
|
1725
|
-
/* @__PURE__ */
|
|
1726
|
-
/* @__PURE__ */
|
|
1727
|
-
/* @__PURE__ */
|
|
1728
|
-
phase === "running" && showSidebar && /* @__PURE__ */
|
|
1729
|
-
phase === "error" && error && /* @__PURE__ */
|
|
1793
|
+
/* @__PURE__ */ jsx14(CliOutput, {}),
|
|
1794
|
+
/* @__PURE__ */ jsx14(Notices, {}),
|
|
1795
|
+
/* @__PURE__ */ jsx14(PromptInput, {}),
|
|
1796
|
+
phase === "running" && showSidebar && /* @__PURE__ */ jsx14(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx14(CurrentStep, {}) }),
|
|
1797
|
+
phase === "error" && error && /* @__PURE__ */ jsx14(Box16, { marginTop: 1, children: /* @__PURE__ */ jsxs15(Text16, { color: COLORS.status.error, children: [
|
|
1730
1798
|
"\u2716 ",
|
|
1731
1799
|
error
|
|
1732
1800
|
] }) })
|
|
1733
1801
|
]
|
|
1734
1802
|
}
|
|
1735
1803
|
),
|
|
1736
|
-
showSidebar ? /* @__PURE__ */
|
|
1804
|
+
showSidebar ? /* @__PURE__ */ jsx14(Sidebar, {}) : /* @__PURE__ */ jsx14(Ribbon, {})
|
|
1737
1805
|
]
|
|
1738
1806
|
}
|
|
1739
1807
|
),
|
|
1740
|
-
phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */
|
|
1808
|
+
phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */ jsx14(LearnMore, {}) : /* @__PURE__ */ jsx14(Welcome, {}))
|
|
1741
1809
|
]
|
|
1742
1810
|
}
|
|
1743
1811
|
)
|
|
@@ -1817,7 +1885,7 @@ async function ensureConsent() {
|
|
|
1817
1885
|
if (config.aiConsent) return;
|
|
1818
1886
|
const store = useWizard.getState();
|
|
1819
1887
|
const answer = await store.requestUserInput({
|
|
1820
|
-
prompt: "Wizard will make AI-authored changes to this repository.",
|
|
1888
|
+
prompt: "Wizard will make AI-authored changes to this repository, and will propose shell commands to set it up. You approve each command before it runs.",
|
|
1821
1889
|
promptType: "enterToContinue",
|
|
1822
1890
|
options: []
|
|
1823
1891
|
});
|
|
@@ -2173,7 +2241,7 @@ async function ensureApplication() {
|
|
|
2173
2241
|
}
|
|
2174
2242
|
|
|
2175
2243
|
// src/workflows/default.ts
|
|
2176
|
-
import { z as
|
|
2244
|
+
import { z as z29 } from "zod";
|
|
2177
2245
|
|
|
2178
2246
|
// src/actions/listIndices.ts
|
|
2179
2247
|
import { z as z5 } from "zod";
|
|
@@ -2896,13 +2964,187 @@ function verifyImplementationTool() {
|
|
|
2896
2964
|
});
|
|
2897
2965
|
}
|
|
2898
2966
|
|
|
2967
|
+
// src/lib/tools/runShell.ts
|
|
2968
|
+
import { tool as tool9 } from "ai";
|
|
2969
|
+
import z16 from "zod";
|
|
2970
|
+
|
|
2971
|
+
// src/lib/tools/utils/runShell.ts
|
|
2972
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
2973
|
+
|
|
2974
|
+
// src/lib/tools/context.ts
|
|
2975
|
+
var DEFAULT_TOOL_LIMITS = {
|
|
2976
|
+
list: 10,
|
|
2977
|
+
search: 10,
|
|
2978
|
+
read: 20,
|
|
2979
|
+
match: 100,
|
|
2980
|
+
shell: 30
|
|
2981
|
+
};
|
|
2982
|
+
var DEFAULT_SHELL_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
2983
|
+
async function refuseByDefault() {
|
|
2984
|
+
return "reject";
|
|
2985
|
+
}
|
|
2986
|
+
function createShellContext(overrides = {}) {
|
|
2987
|
+
return {
|
|
2988
|
+
env: async () => ({}),
|
|
2989
|
+
timeoutMs: DEFAULT_SHELL_TIMEOUT_MS,
|
|
2990
|
+
executions: [],
|
|
2991
|
+
approve: refuseByDefault,
|
|
2992
|
+
...overrides
|
|
2993
|
+
};
|
|
2994
|
+
}
|
|
2995
|
+
function createToolContext(limits = DEFAULT_TOOL_LIMITS, cwd = process.cwd(), shell2 = createShellContext()) {
|
|
2996
|
+
return {
|
|
2997
|
+
root: cwd,
|
|
2998
|
+
cwd,
|
|
2999
|
+
limits: { ...limits },
|
|
3000
|
+
counts: { list: 0, search: 0, read: 0, shell: 0 },
|
|
3001
|
+
shell: shell2
|
|
3002
|
+
};
|
|
3003
|
+
}
|
|
3004
|
+
|
|
3005
|
+
// src/lib/tools/utils/runShell.ts
|
|
3006
|
+
var SIGKILL_DELAY_MS = 5e3;
|
|
3007
|
+
var HEAD_CHARS = 4e3;
|
|
3008
|
+
var TAIL_CHARS = 8e3;
|
|
3009
|
+
function truncateOutput(output) {
|
|
3010
|
+
if (output.length <= HEAD_CHARS + TAIL_CHARS) return output;
|
|
3011
|
+
const omitted = output.length - HEAD_CHARS - TAIL_CHARS;
|
|
3012
|
+
return [
|
|
3013
|
+
output.slice(0, HEAD_CHARS),
|
|
3014
|
+
`
|
|
3015
|
+
\u2026 [${omitted} characters omitted] \u2026
|
|
3016
|
+
`,
|
|
3017
|
+
output.slice(-TAIL_CHARS)
|
|
3018
|
+
].join("");
|
|
3019
|
+
}
|
|
3020
|
+
function runShell(command, opts) {
|
|
3021
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_SHELL_TIMEOUT_MS;
|
|
3022
|
+
const startedAt = Date.now();
|
|
3023
|
+
return new Promise((resolve4) => {
|
|
3024
|
+
let output = "";
|
|
3025
|
+
let timedOut = false;
|
|
3026
|
+
let settled = false;
|
|
3027
|
+
const child = spawn3(command, {
|
|
3028
|
+
shell: true,
|
|
3029
|
+
cwd: opts.cwd,
|
|
3030
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
3031
|
+
env: { ...process.env, ...opts.env }
|
|
3032
|
+
});
|
|
3033
|
+
const finish = (exitCode) => {
|
|
3034
|
+
if (settled) return;
|
|
3035
|
+
settled = true;
|
|
3036
|
+
clearTimeout(timer);
|
|
3037
|
+
clearTimeout(killTimer);
|
|
3038
|
+
resolve4({
|
|
3039
|
+
exitCode,
|
|
3040
|
+
output: truncateOutput(output.trim()),
|
|
3041
|
+
timedOut,
|
|
3042
|
+
durationMs: Date.now() - startedAt
|
|
3043
|
+
});
|
|
3044
|
+
};
|
|
3045
|
+
let killTimer;
|
|
3046
|
+
const timer = setTimeout(() => {
|
|
3047
|
+
timedOut = true;
|
|
3048
|
+
output += `
|
|
3049
|
+
[timed out after ${timeoutMs}ms]`;
|
|
3050
|
+
child.kill("SIGTERM");
|
|
3051
|
+
killTimer = setTimeout(() => child.kill("SIGKILL"), SIGKILL_DELAY_MS);
|
|
3052
|
+
}, timeoutMs);
|
|
3053
|
+
child.stdout?.on("data", (d) => output += d);
|
|
3054
|
+
child.stderr?.on("data", (d) => output += d);
|
|
3055
|
+
child.on("error", (err) => {
|
|
3056
|
+
output += `Failed to run ${command}: ${err.message}`;
|
|
3057
|
+
finish(1);
|
|
3058
|
+
});
|
|
3059
|
+
child.on("close", (code) => finish(code ?? 1));
|
|
3060
|
+
});
|
|
3061
|
+
}
|
|
3062
|
+
|
|
3063
|
+
// src/lib/tools/runShell.ts
|
|
3064
|
+
var shellChain = Promise.resolve();
|
|
3065
|
+
function serialize(work) {
|
|
3066
|
+
const result = shellChain.then(work);
|
|
3067
|
+
shellChain = result.catch(() => {
|
|
3068
|
+
});
|
|
3069
|
+
return result;
|
|
3070
|
+
}
|
|
3071
|
+
async function approveAndRun(ctx, command, cwd, explanation) {
|
|
3072
|
+
const decision = await ctx.shell.approve({ command, cwd, explanation });
|
|
3073
|
+
if (decision === "reject") {
|
|
3074
|
+
ctx.shell.executions.push({ command, cwd, approved: false });
|
|
3075
|
+
logger.info({ command }, "runShell: user rejected the command");
|
|
3076
|
+
return "The user rejected this command. Do not retry it. Propose a different command, or report the limitation via reportStatus.";
|
|
3077
|
+
}
|
|
3078
|
+
useWizard.getState().pushNotice({ messages: [`Running: ${command}`] });
|
|
3079
|
+
const env = await ctx.shell.env().catch((err) => {
|
|
3080
|
+
logger.warn({ err, command }, "runShell: could not resolve command env");
|
|
3081
|
+
return {};
|
|
3082
|
+
});
|
|
3083
|
+
const run2 = await (ctx.shell.run ?? runShell)(command, {
|
|
3084
|
+
cwd,
|
|
3085
|
+
env,
|
|
3086
|
+
timeoutMs: ctx.shell.timeoutMs
|
|
3087
|
+
});
|
|
3088
|
+
logger.info(
|
|
3089
|
+
{
|
|
3090
|
+
command,
|
|
3091
|
+
exitCode: run2.exitCode,
|
|
3092
|
+
timedOut: run2.timedOut,
|
|
3093
|
+
durationMs: run2.durationMs
|
|
3094
|
+
},
|
|
3095
|
+
"runShell finished"
|
|
3096
|
+
);
|
|
3097
|
+
await markInteraction();
|
|
3098
|
+
ctx.shell.executions.push({
|
|
3099
|
+
command,
|
|
3100
|
+
cwd,
|
|
3101
|
+
approved: true,
|
|
3102
|
+
exitCode: run2.exitCode,
|
|
3103
|
+
output: run2.output,
|
|
3104
|
+
timedOut: run2.timedOut,
|
|
3105
|
+
durationMs: run2.durationMs
|
|
3106
|
+
});
|
|
3107
|
+
return {
|
|
3108
|
+
exitCode: run2.exitCode,
|
|
3109
|
+
timedOut: run2.timedOut,
|
|
3110
|
+
output: run2.output
|
|
3111
|
+
};
|
|
3112
|
+
}
|
|
3113
|
+
function runShellTool(ctx) {
|
|
3114
|
+
return tool9({
|
|
3115
|
+
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. The user sees and approves every command before it runs, so write a clear `explanation`. If the user rejects a command, do not retry it \u2014 propose a different approach.",
|
|
3116
|
+
inputSchema: z16.object({
|
|
3117
|
+
command: z16.string().describe(
|
|
3118
|
+
"The command to run, exactly as it would be typed in a shell. Pipes, && and redirects are allowed."
|
|
3119
|
+
),
|
|
3120
|
+
cwd: z16.string().optional().describe(
|
|
3121
|
+
"Directory to run in, relative to the project root. Defaults to the project root."
|
|
3122
|
+
),
|
|
3123
|
+
explanation: z16.string().describe(
|
|
3124
|
+
"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."
|
|
3125
|
+
)
|
|
3126
|
+
}),
|
|
3127
|
+
execute: async ({ command, cwd, explanation }) => {
|
|
3128
|
+
if (++ctx.counts.shell > ctx.limits.shell) {
|
|
3129
|
+
return `Refused: command limit (${ctx.limits.shell}) reached. Stop running commands and report what you have.`;
|
|
3130
|
+
}
|
|
3131
|
+
const resolved2 = resolveInRoot(ctx, cwd ?? ".");
|
|
3132
|
+
if (!resolved2.ok) return resolved2.error;
|
|
3133
|
+
logger.info({ command, cwd: resolved2.target }, "called runShell tool");
|
|
3134
|
+
return serialize(
|
|
3135
|
+
() => approveAndRun(ctx, command, resolved2.target, explanation)
|
|
3136
|
+
);
|
|
3137
|
+
}
|
|
3138
|
+
});
|
|
3139
|
+
}
|
|
3140
|
+
|
|
2899
3141
|
// src/lib/tools/generateRecord.ts
|
|
2900
|
-
import { tool as
|
|
3142
|
+
import { tool as tool10, generateText, Output, NoObjectGeneratedError } from "ai";
|
|
2901
3143
|
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
2902
3144
|
import { nanoid as nanoid2 } from "nanoid";
|
|
2903
3145
|
import { mkdir as mkdir5, writeFile as writeFile5 } from "node:fs/promises";
|
|
2904
3146
|
import { dirname as dirname6 } from "node:path";
|
|
2905
|
-
import
|
|
3147
|
+
import z17 from "zod";
|
|
2906
3148
|
var DATA_DIR = ".algolia-wizard/data";
|
|
2907
3149
|
var RECORD_MODEL = "claude-haiku-4-5";
|
|
2908
3150
|
var MAX_RECORDS = 100;
|
|
@@ -2912,19 +3154,19 @@ var anthropic = createAnthropic({
|
|
|
2912
3154
|
apiKey: process.env.PROVIDER_API_KEY ?? ""
|
|
2913
3155
|
});
|
|
2914
3156
|
function generateRecordTool(ctx) {
|
|
2915
|
-
return
|
|
3157
|
+
return tool10({
|
|
2916
3158
|
description: "Generate realistic sample records for an entity and write them to a JSON file in the worktree. Provide the entity name and its attributes; this tool asks a model to invent varied, realistic values, each with a unique objectID, and returns the file path to read them from at runtime. Do not invent the record values or objectIDs yourself, and do not inline the returned records into the script \u2014 call this tool and read the file it writes.",
|
|
2917
|
-
inputSchema:
|
|
2918
|
-
entityName:
|
|
2919
|
-
attributes:
|
|
2920
|
-
count:
|
|
2921
|
-
hint:
|
|
3159
|
+
inputSchema: z17.object({
|
|
3160
|
+
entityName: z17.string().describe("Name of the entity to generate records for."),
|
|
3161
|
+
attributes: z17.array(z17.string()).describe("Attribute names each record must contain."),
|
|
3162
|
+
count: z17.number().int().min(1).max(MAX_RECORDS).default(10).describe(`How many records to generate (max ${MAX_RECORDS}).`),
|
|
3163
|
+
hint: z17.string().optional().describe("Optional context to steer realistic values.")
|
|
2922
3164
|
}),
|
|
2923
3165
|
execute: async ({ entityName, attributes, count, hint }) => {
|
|
2924
3166
|
logger.info({ entityName, count }, "called generateRecord tool");
|
|
2925
3167
|
try {
|
|
2926
|
-
const value =
|
|
2927
|
-
const recordSchema =
|
|
3168
|
+
const value = z17.union([z17.string(), z17.number(), z17.boolean(), z17.null()]);
|
|
3169
|
+
const recordSchema = z17.object(
|
|
2928
3170
|
Object.fromEntries(attributes.map((attr) => [attr, value]))
|
|
2929
3171
|
);
|
|
2930
3172
|
const generateBatch = async (batchCount) => {
|
|
@@ -2934,8 +3176,8 @@ function generateRecordTool(ctx) {
|
|
|
2934
3176
|
const { output } = await generateText({
|
|
2935
3177
|
model: anthropic(RECORD_MODEL),
|
|
2936
3178
|
output: Output.object({
|
|
2937
|
-
schema:
|
|
2938
|
-
records:
|
|
3179
|
+
schema: z17.object({
|
|
3180
|
+
records: z17.array(recordSchema).length(batchCount)
|
|
2939
3181
|
})
|
|
2940
3182
|
}),
|
|
2941
3183
|
prompt: [
|
|
@@ -2992,13 +3234,13 @@ function generateRecordTool(ctx) {
|
|
|
2992
3234
|
}
|
|
2993
3235
|
|
|
2994
3236
|
// src/lib/tools/notifyUser.ts
|
|
2995
|
-
import { tool as
|
|
2996
|
-
import
|
|
3237
|
+
import { tool as tool11 } from "ai";
|
|
3238
|
+
import z18 from "zod";
|
|
2997
3239
|
function notifyUserTool() {
|
|
2998
|
-
return
|
|
3240
|
+
return tool11({
|
|
2999
3241
|
description: `Give the user a brief, high-level update on what you are currently doing or about to do next. This is for the big picture (e.g. "Reading through your data models", "Writing the search UI") \u2014 not granular detail like individual tool calls, which are already logged separately. Call it when you start a new phase of work or your focus shifts, just not on every step, enough to keep the user engaged. Don't say things like "starting", just describe what you are doing. Don't mention tool calls themselves, just general direction of the work.`,
|
|
3000
|
-
inputSchema:
|
|
3001
|
-
message:
|
|
3242
|
+
inputSchema: z18.object({
|
|
3243
|
+
message: z18.string().describe(
|
|
3002
3244
|
"Short, plain-language description of what you are doing now."
|
|
3003
3245
|
)
|
|
3004
3246
|
}),
|
|
@@ -3010,22 +3252,6 @@ function notifyUserTool() {
|
|
|
3010
3252
|
});
|
|
3011
3253
|
}
|
|
3012
3254
|
|
|
3013
|
-
// src/lib/tools/context.ts
|
|
3014
|
-
var DEFAULT_TOOL_LIMITS = {
|
|
3015
|
-
list: 10,
|
|
3016
|
-
search: 10,
|
|
3017
|
-
read: 20,
|
|
3018
|
-
match: 100
|
|
3019
|
-
};
|
|
3020
|
-
function createToolContext(limits = DEFAULT_TOOL_LIMITS, cwd = process.cwd()) {
|
|
3021
|
-
return {
|
|
3022
|
-
root: cwd,
|
|
3023
|
-
cwd,
|
|
3024
|
-
limits,
|
|
3025
|
-
counts: { list: 0, search: 0, read: 0 }
|
|
3026
|
-
};
|
|
3027
|
-
}
|
|
3028
|
-
|
|
3029
3255
|
// src/lib/tools/index.ts
|
|
3030
3256
|
function withLogging(name, def) {
|
|
3031
3257
|
const execute = def.execute;
|
|
@@ -3061,6 +3287,7 @@ function createTools(ctx, { output, tools }) {
|
|
|
3061
3287
|
"verifyImplementation",
|
|
3062
3288
|
verifyImplementationTool()
|
|
3063
3289
|
),
|
|
3290
|
+
runShell: withLogging("runShell", runShellTool(ctx)),
|
|
3064
3291
|
generateRecord: withLogging("generateRecord", generateRecordTool(ctx)),
|
|
3065
3292
|
notifyUser: withLogging("notifyUser", notifyUserTool())
|
|
3066
3293
|
};
|
|
@@ -3095,7 +3322,7 @@ async function runAgent(req) {
|
|
|
3095
3322
|
baseURL: PROXY_BASE_URL,
|
|
3096
3323
|
fetch: proxyFetch
|
|
3097
3324
|
});
|
|
3098
|
-
const toolContext = createToolContext();
|
|
3325
|
+
const toolContext = req.toolContext ?? createToolContext();
|
|
3099
3326
|
const readTools = ["readFile", "searchFiles", "listFiles"];
|
|
3100
3327
|
const hasReadTools = !req.tools || req.tools.some((t) => readTools.includes(t));
|
|
3101
3328
|
const instructions = [
|
|
@@ -3160,7 +3387,11 @@ async function runAgent(req) {
|
|
|
3160
3387
|
"runAgent finished"
|
|
3161
3388
|
);
|
|
3162
3389
|
logger.info(
|
|
3163
|
-
{
|
|
3390
|
+
{
|
|
3391
|
+
counts: toolContext.counts,
|
|
3392
|
+
limits: toolContext.limits,
|
|
3393
|
+
commandsRun: toolContext.shell.executions.length
|
|
3394
|
+
},
|
|
3164
3395
|
"tool usage"
|
|
3165
3396
|
);
|
|
3166
3397
|
const toolResults = await stream.toolResults;
|
|
@@ -3178,10 +3409,10 @@ async function runAgent(req) {
|
|
|
3178
3409
|
}
|
|
3179
3410
|
|
|
3180
3411
|
// src/actions/detectLanguage.ts
|
|
3181
|
-
import
|
|
3182
|
-
var detectLanguageSchema =
|
|
3183
|
-
languages:
|
|
3184
|
-
frameworks:
|
|
3412
|
+
import z21 from "zod";
|
|
3413
|
+
var detectLanguageSchema = z21.object({
|
|
3414
|
+
languages: z21.array(z21.object({ name: z21.string(), version: z21.string() })),
|
|
3415
|
+
frameworks: z21.array(z21.object({ name: z21.string(), version: z21.string() }))
|
|
3185
3416
|
});
|
|
3186
3417
|
var detectLanguage = () => runAgent({
|
|
3187
3418
|
instructions: [
|
|
@@ -3199,31 +3430,31 @@ var detectLanguage = () => runAgent({
|
|
|
3199
3430
|
});
|
|
3200
3431
|
|
|
3201
3432
|
// src/actions/analyzeCodebase.ts
|
|
3202
|
-
import
|
|
3433
|
+
import z22 from "zod";
|
|
3203
3434
|
var READONLY_TOOLS = [
|
|
3204
3435
|
"listFiles",
|
|
3205
3436
|
"changeDirectory",
|
|
3206
3437
|
"readFile",
|
|
3207
3438
|
"searchFiles"
|
|
3208
3439
|
];
|
|
3209
|
-
var ingestionAnalysisSchema =
|
|
3210
|
-
ingestionAnalysis:
|
|
3211
|
-
|
|
3212
|
-
name:
|
|
3213
|
-
paths:
|
|
3440
|
+
var ingestionAnalysisSchema = z22.object({
|
|
3441
|
+
ingestionAnalysis: z22.array(
|
|
3442
|
+
z22.object({
|
|
3443
|
+
name: z22.string(),
|
|
3444
|
+
paths: z22.array(z22.string()),
|
|
3214
3445
|
// indexable fields the agent found for this entity
|
|
3215
|
-
attributes:
|
|
3446
|
+
attributes: z22.array(z22.string())
|
|
3216
3447
|
})
|
|
3217
3448
|
)
|
|
3218
3449
|
});
|
|
3219
|
-
var searchImplementationAnalysisSchema =
|
|
3220
|
-
searchImplementationAnalysis:
|
|
3450
|
+
var searchImplementationAnalysisSchema = z22.object({
|
|
3451
|
+
searchImplementationAnalysis: z22.string()
|
|
3221
3452
|
});
|
|
3222
|
-
var verificationSchema =
|
|
3223
|
-
verification:
|
|
3453
|
+
var verificationSchema = z22.object({
|
|
3454
|
+
verification: z22.array(z22.string())
|
|
3224
3455
|
});
|
|
3225
3456
|
var confirmedEntitiesFieldSchema = ingestionAnalysisSchema.shape.ingestionAnalysis.optional();
|
|
3226
|
-
var analyzeCodebaseSchema =
|
|
3457
|
+
var analyzeCodebaseSchema = z22.object({
|
|
3227
3458
|
ingestionAnalysis: ingestionAnalysisSchema.shape.ingestionAnalysis.optional(),
|
|
3228
3459
|
searchImplementationAnalysis: searchImplementationAnalysisSchema.shape.searchImplementationAnalysis.optional(),
|
|
3229
3460
|
verification: verificationSchema.shape.verification.optional(),
|
|
@@ -3285,7 +3516,7 @@ async function runAnalysis(mode, extraInstructions = []) {
|
|
|
3285
3516
|
// package.json
|
|
3286
3517
|
var package_default = {
|
|
3287
3518
|
name: "@algolia/wizard",
|
|
3288
|
-
version: "0.
|
|
3519
|
+
version: "0.12.0",
|
|
3289
3520
|
description: "Magically implement Algolia functionality in your codebase",
|
|
3290
3521
|
type: "module",
|
|
3291
3522
|
engines: {
|
|
@@ -3404,8 +3635,8 @@ async function askList(ctx, prompt, { required = false } = {}) {
|
|
|
3404
3635
|
}
|
|
3405
3636
|
|
|
3406
3637
|
// src/actions/confirmLanguage.ts
|
|
3407
|
-
import
|
|
3408
|
-
var confirmLanguageSchema =
|
|
3638
|
+
import z24 from "zod";
|
|
3639
|
+
var confirmLanguageSchema = z24.object({
|
|
3409
3640
|
languages: detectLanguageSchema.shape.languages
|
|
3410
3641
|
});
|
|
3411
3642
|
async function confirmLanguage(ctx) {
|
|
@@ -3426,8 +3657,8 @@ async function confirmLanguage(ctx) {
|
|
|
3426
3657
|
}
|
|
3427
3658
|
|
|
3428
3659
|
// src/actions/confirmFramework.ts
|
|
3429
|
-
import
|
|
3430
|
-
var confirmFrameworkSchema =
|
|
3660
|
+
import z25 from "zod";
|
|
3661
|
+
var confirmFrameworkSchema = z25.object({
|
|
3431
3662
|
frameworks: detectLanguageSchema.shape.frameworks
|
|
3432
3663
|
});
|
|
3433
3664
|
var CURATED_FRAMEWORKS = [
|
|
@@ -3555,8 +3786,8 @@ async function promptUser(ctx, params) {
|
|
|
3555
3786
|
}
|
|
3556
3787
|
|
|
3557
3788
|
// src/actions/confirmEntities.ts
|
|
3558
|
-
import
|
|
3559
|
-
var confirmEntitiesSchema =
|
|
3789
|
+
import z26 from "zod";
|
|
3790
|
+
var confirmEntitiesSchema = z26.object({
|
|
3560
3791
|
// Final detection — the focused re-run may supersede project-scan's.
|
|
3561
3792
|
ingestionAnalysis: ingestionAnalysisSchema.shape.ingestionAnalysis.optional(),
|
|
3562
3793
|
confirmedEntities: confirmedEntitiesFieldSchema
|
|
@@ -3626,15 +3857,15 @@ async function confirmEntities(ctx) {
|
|
|
3626
3857
|
}
|
|
3627
3858
|
|
|
3628
3859
|
// src/actions/review.ts
|
|
3629
|
-
import { z as
|
|
3630
|
-
var reviewSchema =
|
|
3860
|
+
import { z as z27 } from "zod";
|
|
3861
|
+
var reviewSchema = z27.object({
|
|
3631
3862
|
// Broad, high-level takeaways grouped by theme (e.g. ingestion, search UI),
|
|
3632
3863
|
// not one entry per workflow step — a step's raw output can be a long,
|
|
3633
3864
|
// multi-paragraph blob (see implement.ts's summaries.join), and mirroring
|
|
3634
3865
|
// that 1:1 is what made the old per-step summary an unreadable wall of text.
|
|
3635
|
-
summaryPoints:
|
|
3636
|
-
reviewPrompt:
|
|
3637
|
-
nextSteps:
|
|
3866
|
+
summaryPoints: z27.array(z27.string()),
|
|
3867
|
+
reviewPrompt: z27.string(),
|
|
3868
|
+
nextSteps: z27.array(z27.string())
|
|
3638
3869
|
});
|
|
3639
3870
|
function formatCompletedSteps(steps) {
|
|
3640
3871
|
if (!steps.length) return "(no prior steps completed)";
|
|
@@ -3685,10 +3916,10 @@ ${formatCompletedSteps(ctx.completedSteps)}`,
|
|
|
3685
3916
|
};
|
|
3686
3917
|
|
|
3687
3918
|
// src/actions/implement.ts
|
|
3688
|
-
import
|
|
3919
|
+
import z28 from "zod";
|
|
3689
3920
|
|
|
3690
3921
|
// src/lib/worktree.ts
|
|
3691
|
-
import { execFile, spawn as
|
|
3922
|
+
import { execFile, spawn as spawn4 } from "node:child_process";
|
|
3692
3923
|
import { copyFile, mkdir as mkdir6, readdir as readdir3, readFile as readFile8, stat as stat2, writeFile as writeFile6 } from "node:fs/promises";
|
|
3693
3924
|
import {
|
|
3694
3925
|
basename as basename2,
|
|
@@ -3769,7 +4000,7 @@ async function installWorktreeDeps(worktreePath) {
|
|
|
3769
4000
|
const pm = await detectPackageManager(worktreePath);
|
|
3770
4001
|
return new Promise((resolve4) => {
|
|
3771
4002
|
let output = "";
|
|
3772
|
-
const child =
|
|
4003
|
+
const child = spawn4(pm, ["install"], {
|
|
3773
4004
|
cwd: worktreePath,
|
|
3774
4005
|
stdio: ["ignore", "pipe", "pipe"]
|
|
3775
4006
|
});
|
|
@@ -3838,7 +4069,7 @@ async function runIngestScript(worktreePath, runtime, entrypoint, env = {}) {
|
|
|
3838
4069
|
}
|
|
3839
4070
|
return new Promise((resolveRun) => {
|
|
3840
4071
|
let output = "";
|
|
3841
|
-
const child =
|
|
4072
|
+
const child = spawn4(runtime, [entrypoint], {
|
|
3842
4073
|
cwd: worktreePath,
|
|
3843
4074
|
shell: false,
|
|
3844
4075
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -4044,34 +4275,34 @@ function shellQuote(value) {
|
|
|
4044
4275
|
}
|
|
4045
4276
|
|
|
4046
4277
|
// src/actions/implement.ts
|
|
4047
|
-
var implementSchema =
|
|
4048
|
-
filesChanged:
|
|
4049
|
-
summary:
|
|
4050
|
-
worktreePath:
|
|
4051
|
-
ingestCommand:
|
|
4052
|
-
ingestScriptRan:
|
|
4053
|
-
ingestRecordCount:
|
|
4054
|
-
ingestDurationMs:
|
|
4055
|
-
ingestionSource:
|
|
4056
|
-
searchEnvVars:
|
|
4057
|
-
|
|
4058
|
-
name:
|
|
4059
|
-
value:
|
|
4278
|
+
var implementSchema = z28.object({
|
|
4279
|
+
filesChanged: z28.array(z28.string()),
|
|
4280
|
+
summary: z28.string(),
|
|
4281
|
+
worktreePath: z28.string().optional(),
|
|
4282
|
+
ingestCommand: z28.string().optional(),
|
|
4283
|
+
ingestScriptRan: z28.boolean().optional(),
|
|
4284
|
+
ingestRecordCount: z28.number().optional(),
|
|
4285
|
+
ingestDurationMs: z28.number().optional(),
|
|
4286
|
+
ingestionSource: z28.enum(["local", "fileUpload", "generated"]),
|
|
4287
|
+
searchEnvVars: z28.array(
|
|
4288
|
+
z28.object({
|
|
4289
|
+
name: z28.string(),
|
|
4290
|
+
value: z28.string()
|
|
4060
4291
|
})
|
|
4061
4292
|
).optional()
|
|
4062
4293
|
});
|
|
4063
|
-
var implementationOutputSchema =
|
|
4064
|
-
summary:
|
|
4294
|
+
var implementationOutputSchema = z28.object({
|
|
4295
|
+
summary: z28.string(),
|
|
4065
4296
|
// Ingestion only: a structured pair the wizard turns into an argv, never a
|
|
4066
4297
|
// free-form command string. `runtime` is allowlisted and `entrypoint` is
|
|
4067
4298
|
// validated worktree-relative, so the agent cannot inject extra commands.
|
|
4068
|
-
runtime:
|
|
4069
|
-
entrypoint:
|
|
4299
|
+
runtime: z28.enum(INGEST_RUNTIMES).optional(),
|
|
4300
|
+
entrypoint: z28.string().optional()
|
|
4070
4301
|
});
|
|
4071
|
-
var verificationOutputSchema =
|
|
4072
|
-
summary:
|
|
4073
|
-
sufficient:
|
|
4074
|
-
additionalInstructions:
|
|
4302
|
+
var verificationOutputSchema = z28.object({
|
|
4303
|
+
summary: z28.string(),
|
|
4304
|
+
sufficient: z28.boolean(),
|
|
4305
|
+
additionalInstructions: z28.string().optional()
|
|
4075
4306
|
});
|
|
4076
4307
|
var MAX_IMPLEMENT_VERIFICATION_ATTEMPTS = 3;
|
|
4077
4308
|
var DEFAULT_IMPLEMENT_USE_CASES = ["ingestion", "search"];
|
|
@@ -4749,8 +4980,8 @@ var defaultWorkflow = {
|
|
|
4749
4980
|
defineStep({
|
|
4750
4981
|
id: "select-index",
|
|
4751
4982
|
title: "Set up index",
|
|
4752
|
-
outputSchema:
|
|
4753
|
-
selection:
|
|
4983
|
+
outputSchema: z29.object({
|
|
4984
|
+
selection: z29.string()
|
|
4754
4985
|
}),
|
|
4755
4986
|
run: (ctx) => selectIndexStep(ctx)
|
|
4756
4987
|
}),
|
|
@@ -5054,7 +5285,7 @@ async function resetProjectState() {
|
|
|
5054
5285
|
}
|
|
5055
5286
|
|
|
5056
5287
|
// src/main.tsx
|
|
5057
|
-
import { jsx as
|
|
5288
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
5058
5289
|
async function startup() {
|
|
5059
5290
|
setProjectRoot(process.cwd());
|
|
5060
5291
|
let args;
|
|
@@ -5104,7 +5335,7 @@ ${formatStepList(workflow)}`);
|
|
|
5104
5335
|
}
|
|
5105
5336
|
async function run(workflow) {
|
|
5106
5337
|
const store = useWizard.getState();
|
|
5107
|
-
const instance = render(/* @__PURE__ */
|
|
5338
|
+
const instance = render(/* @__PURE__ */ jsx15(App, {}), { incrementalRendering: true });
|
|
5108
5339
|
await store.waitForStart();
|
|
5109
5340
|
let user = await getUser();
|
|
5110
5341
|
if (!user) {
|