@algolia/wizard 0.28.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.js +382 -99
  2. package/package.json +2 -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 Box17, Text as Text17, useApp, useInput as useInput7, useWindowSize as useWindowSize8 } from "ink";
7
+ import { Box as Box19, Text as Text19, useApp, useInput as useInput7, useWindowSize as useWindowSize7 } from "ink";
8
8
  import Spinner2 from "ink-spinner";
9
9
 
10
10
  // src/core/store.ts
@@ -489,7 +489,7 @@ function CliOutput() {
489
489
  }
490
490
 
491
491
  // src/ui/Notices.tsx
492
- import { Box as Box3, Text as Text3, useWindowSize as useWindowSize3 } from "ink";
492
+ import { Box as Box3, Text as Text3 } from "ink";
493
493
  import { useEffect as useEffect2, useState as useState2 } from "react";
494
494
 
495
495
  // src/ui/Table.tsx
@@ -548,31 +548,6 @@ var truncate = (s, width) => s.length <= width ? s : width <= 1 ? s.slice(0, wid
548
548
  // src/ui/Notices.tsx
549
549
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
550
550
  var AGENT_MARKER = "\u2726";
551
- var RESERVED_ROWS2 = 14;
552
- var PANEL_TEXT_WIDTH2 = 45;
553
- function messageLineCount(text) {
554
- return Math.max(1, Math.ceil(text.length / PANEL_TEXT_WIDTH2));
555
- }
556
- function noticeLineCount(notice) {
557
- const messageLines = (notice.messages ?? []).reduce((sum, m) => {
558
- const text = typeof m === "string" ? m : m.text;
559
- return sum + messageLineCount(text);
560
- }, 0);
561
- const tableLines = notice.table ? notice.table.rows.length + 4 : 0;
562
- return messageLines + tableLines;
563
- }
564
- function fitVisibleNotices(notices, windowRows) {
565
- const budget = Math.max(windowRows - RESERVED_ROWS2, 3);
566
- let used = 0;
567
- let count = 0;
568
- for (let i = notices.length - 1; i >= 0; i--) {
569
- const height = noticeLineCount(notices[i]) + (count > 0 ? 1 : 0);
570
- if (count > 0 && used + height > budget) break;
571
- used += height;
572
- count++;
573
- }
574
- return notices.slice(notices.length - count);
575
- }
576
551
  var PULSE_STEPS = 12;
577
552
  var PULSE_STEP_MS = 150;
578
553
  var PULSE_COLORS = Array.from(
@@ -593,10 +568,13 @@ function parseHex(hex) {
593
568
  b: parseInt(n.slice(4, 6), 16)
594
569
  };
595
570
  }
596
- function Notices() {
571
+ function Notices({
572
+ showAll = false,
573
+ border = true
574
+ } = {}) {
597
575
  const notices = useWizard((s) => s.notices);
598
- const { rows: windowRows } = useWindowSize3();
599
- const visible = fitVisibleNotices(notices, windowRows);
576
+ const latest = notices[notices.length - 1];
577
+ const visible = showAll ? notices : latest ? [latest] : [];
600
578
  const [pulseStep, setPulseStep] = useState2(0);
601
579
  useEffect2(() => {
602
580
  let direction = 1;
@@ -610,30 +588,41 @@ function Notices() {
610
588
  }, PULSE_STEP_MS);
611
589
  return () => clearInterval(id);
612
590
  }, []);
613
- if (!visible.length) return null;
591
+ if (visible.length === 0) return null;
614
592
  const pulseColor = PULSE_COLORS[pulseStep];
615
- return /* @__PURE__ */ jsx2(Box3, { flexDirection: "column", gap: 1, marginBottom: 1, children: visible.map((notice, i) => {
616
- const isLatest = i === visible.length - 1;
617
- return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", children: [
618
- notice.messages?.map((m, j) => {
619
- const line = typeof m === "string" ? { text: m } : m;
620
- const prefix = j === 0 ? `${AGENT_MARKER} ` : " ";
621
- return /* @__PURE__ */ jsxs2(
622
- Text3,
623
- {
624
- color: isLatest && !line.color ? pulseColor : line.color ?? COLORS.dim,
625
- bold: line.bold,
626
- children: [
627
- prefix,
628
- line.text
629
- ]
630
- },
631
- `notice-${i}-${j}`
632
- );
633
- }),
634
- notice.table && /* @__PURE__ */ jsx2(Table, { columns: notice.table.columns, rows: notice.table.rows })
635
- ] }, `notice-${i}`);
636
- }) });
593
+ return /* @__PURE__ */ jsx2(
594
+ Box3,
595
+ {
596
+ borderColor: border ? COLORS.border : void 0,
597
+ borderStyle: border ? "single" : void 0,
598
+ borderBackgroundColor: COLORS.bg.main,
599
+ borderLeft: false,
600
+ borderRight: false,
601
+ borderBottom: false,
602
+ paddingTop: border ? 1 : 0,
603
+ flexDirection: "column",
604
+ gap: 1,
605
+ children: visible.map((notice, i) => /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", children: [
606
+ notice.messages?.map((m, j) => {
607
+ const line = typeof m === "string" ? { text: m } : m;
608
+ const prefix = j === 0 ? `${AGENT_MARKER} ` : " ";
609
+ return /* @__PURE__ */ jsxs2(
610
+ Text3,
611
+ {
612
+ color: !line.color ? notice === latest ? pulseColor : COLORS.dim : line.color ?? COLORS.dim,
613
+ bold: line.bold,
614
+ children: [
615
+ prefix,
616
+ line.text
617
+ ]
618
+ },
619
+ `notice-line-${j}`
620
+ );
621
+ }),
622
+ notice.table && /* @__PURE__ */ jsx2(Table, { columns: notice.table.columns, rows: notice.table.rows })
623
+ ] }, `notice-${i}`))
624
+ }
625
+ );
637
626
  }
638
627
 
639
628
  // src/ui/PromptInput.tsx
@@ -714,11 +703,11 @@ function CommandApproval({
714
703
  }
715
704
 
716
705
  // src/ui/SelectPrompt.tsx
717
- import { Box as Box8, Text as Text8, useInput as useInput2, useWindowSize as useWindowSize5 } from "ink";
706
+ import { Box as Box8, Text as Text8, useInput as useInput2, useWindowSize as useWindowSize4 } from "ink";
718
707
  import { useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState4 } from "react";
719
708
 
720
709
  // src/ui/ScrollView.tsx
721
- import { Box as Box6, Text as Text6, measureElement as measureElement2, useWindowSize as useWindowSize4 } from "ink";
710
+ import { Box as Box6, Text as Text6, measureElement as measureElement2, useWindowSize as useWindowSize3 } from "ink";
722
711
  import { useCallback, useLayoutEffect, useRef as useRef2, useState as useState3 } from "react";
723
712
  import { jsxs as jsxs5 } from "react/jsx-runtime";
724
713
  var INDICATOR_ROWS = 2;
@@ -735,7 +724,7 @@ function useScrollWindow({
735
724
  followBottom = false
736
725
  }) {
737
726
  const viewportRef = useRef2(null);
738
- const { columns } = useWindowSize4();
727
+ const { columns } = useWindowSize3();
739
728
  const [size, setSize] = useState3(
740
729
  null
741
730
  );
@@ -876,7 +865,7 @@ function SelectPrompt({
876
865
  if (multi) hints.push({ key: "[space]", label: "select" });
877
866
  hints.push({ key: "[enter]", label: "confirm" });
878
867
  const containerRef = useRef3(null);
879
- const { columns } = useWindowSize5();
868
+ const { columns } = useWindowSize4();
880
869
  const [width, setWidth] = useState4(columns);
881
870
  useLayoutEffect2(() => {
882
871
  if (!containerRef.current) return;
@@ -1105,7 +1094,7 @@ function PromptInput() {
1105
1094
  import { dirname as dirname2, join as join3 } from "node:path";
1106
1095
  import { fileURLToPath } from "node:url";
1107
1096
  import { useState as useState6 } from "react";
1108
- import { Box as Box10, Spacer, Text as Text10, useInput as useInput4, useWindowSize as useWindowSize6 } from "ink";
1097
+ import { Box as Box10, Spacer, Text as Text10, useInput as useInput4, useWindowSize as useWindowSize5 } from "ink";
1109
1098
 
1110
1099
  // src/ui/copy/welcome.ts
1111
1100
  var sidebarItems = [
@@ -1158,7 +1147,7 @@ function SidebarItem({
1158
1147
  function Welcome() {
1159
1148
  const confirmStart = useWizard((s) => s.confirmStart);
1160
1149
  const openLearnMore = useWizard((s) => s.openLearnMore);
1161
- const { rows } = useWindowSize6();
1150
+ const { rows } = useWindowSize5();
1162
1151
  const actions = [
1163
1152
  { label: "start wizard", run: confirmStart },
1164
1153
  { label: "learn more", run: openLearnMore }
@@ -1251,7 +1240,7 @@ function Welcome() {
1251
1240
 
1252
1241
  // src/ui/LearnMore.tsx
1253
1242
  import { Fragment as Fragment2 } from "react";
1254
- import { Box as Box11, Text as Text11, useInput as useInput5, useWindowSize as useWindowSize7 } from "ink";
1243
+ import { Box as Box11, Text as Text11, useInput as useInput5, useWindowSize as useWindowSize6 } from "ink";
1255
1244
 
1256
1245
  // src/ui/copy/learn-more.ts
1257
1246
  var accessIntro = "Everything runs locally on your machine. Nothing is written or sent without an explicit yes from you.";
@@ -1321,7 +1310,7 @@ function NeverLine({
1321
1310
  function LearnMore() {
1322
1311
  const confirmStart = useWizard((s) => s.confirmStart);
1323
1312
  const backToHome = useWizard((s) => s.backToHome);
1324
- const { columns } = useWindowSize7();
1313
+ const { columns } = useWindowSize6();
1325
1314
  const dividerWidth = Math.max(0, columns - PADDING_X * 2);
1326
1315
  useInput5((_input, key) => {
1327
1316
  if (key.escape) backToHome();
@@ -1531,7 +1520,7 @@ function Ribbon() {
1531
1520
  }
1532
1521
 
1533
1522
  // src/ui/App.tsx
1534
- import { useState as useState7 } from "react";
1523
+ import { useState as useState8 } from "react";
1535
1524
 
1536
1525
  // src/ui/Logs.tsx
1537
1526
  import { Box as Box16, Text as Text16, useInput as useInput6 } from "ink";
@@ -1781,15 +1770,303 @@ function track(event, payload) {
1781
1770
  });
1782
1771
  }
1783
1772
 
1773
+ // src/ui/Tips.tsx
1774
+ import { useEffect as useEffect3, useState as useState7 } from "react";
1775
+ import { Box as Box18, Text as Text18 } from "ink";
1776
+ import terminalLink from "terminal-link";
1777
+
1778
+ // src/ui/Code.tsx
1779
+ import { Box as Box17, Text as Text17 } from "ink";
1780
+ import { jsx as jsx15 } from "react/jsx-runtime";
1781
+ var TOKEN_RE = /("(?:\\.|[^"\\])*"|\btrue\b|\bfalse\b|\bnull\b|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|[{}[\]:,])/g;
1782
+ function highlightJson(json) {
1783
+ const parts = json.split(TOKEN_RE);
1784
+ return parts.map((part, i) => {
1785
+ if (!part) return null;
1786
+ if (part[0] === '"') {
1787
+ const next = parts.slice(i + 1).find((p) => p.trim());
1788
+ const isKey = next?.trimStart().startsWith(":");
1789
+ return /* @__PURE__ */ jsx15(Text17, { color: isKey ? "cyan" : "green", children: part }, i);
1790
+ }
1791
+ if (part === "true" || part === "false" || part === "null") {
1792
+ return /* @__PURE__ */ jsx15(Text17, { color: "magenta", children: part }, i);
1793
+ }
1794
+ if (/^-?\d/.test(part)) {
1795
+ return /* @__PURE__ */ jsx15(Text17, { color: "yellow", children: part }, i);
1796
+ }
1797
+ if (/^[{}[\]:,]$/.test(part)) {
1798
+ return /* @__PURE__ */ jsx15(Text17, { dimColor: true, children: part }, i);
1799
+ }
1800
+ return /* @__PURE__ */ jsx15(Text17, { children: part }, i);
1801
+ });
1802
+ }
1803
+ function Code({ children }) {
1804
+ return /* @__PURE__ */ jsx15(Box17, { children: /* @__PURE__ */ jsx15(Text17, { children: highlightJson(children) }) });
1805
+ }
1806
+
1807
+ // src/ui/copy/tips.ts
1808
+ var tips = [
1809
+ {
1810
+ title: "An Application is like your library. Indices are the books in it.",
1811
+ chunks: [
1812
+ {
1813
+ type: "text",
1814
+ value: "Applications hold your API keys and Indices."
1815
+ },
1816
+ {
1817
+ type: "text",
1818
+ value: "Each index is a searchable collection of records (think: products, articles, orders, concerts)."
1819
+ }
1820
+ ]
1821
+ },
1822
+ {
1823
+ title: "A Record is a JSON object inside of an index.",
1824
+ chunks: [
1825
+ {
1826
+ type: "text",
1827
+ value: "Every object you index is just a JSON document with a unique objectID."
1828
+ },
1829
+ {
1830
+ type: "text",
1831
+ value: "No fixed schema, no hard requirements."
1832
+ },
1833
+ {
1834
+ type: "text",
1835
+ value: "Everything else is up to you:"
1836
+ },
1837
+ {
1838
+ type: "code",
1839
+ value: JSON.stringify(
1840
+ {
1841
+ objectID: "sku_48213",
1842
+ name: "Trail Running Shoe",
1843
+ brand: "Northline",
1844
+ categories: ["Footwear", "Running", "Mens"],
1845
+ price: 129.99,
1846
+ in_stock: true,
1847
+ rating: 4.6
1848
+ },
1849
+ null,
1850
+ 2
1851
+ )
1852
+ }
1853
+ ]
1854
+ },
1855
+ {
1856
+ title: "Speed isn't a feature, it's our business",
1857
+ chunks: [
1858
+ {
1859
+ type: "text",
1860
+ value: "Algolia's engine processes most search queries in 1 to 50 milliseconds."
1861
+ },
1862
+ {
1863
+ type: "text",
1864
+ value: "This is why our search-as-you-type experience feels instant."
1865
+ }
1866
+ ]
1867
+ },
1868
+ {
1869
+ title: "Searchable attributes are your relevance dial #1",
1870
+ chunks: [
1871
+ {
1872
+ type: "text",
1873
+ value: "Order matters. Attributes listed first in"
1874
+ },
1875
+ { type: "codeword", value: "searchableAttributes" },
1876
+ { type: "text", value: "carry more ranking weight." },
1877
+ {
1878
+ type: "text",
1879
+ value: "This is the single highest-leverage lever new users don't know exists."
1880
+ }
1881
+ ]
1882
+ },
1883
+ {
1884
+ title: "Facets aren't just filters, they help build your UI",
1885
+ chunks: [
1886
+ { type: "codeword", value: "attributesForFaceting" },
1887
+ {
1888
+ type: "text",
1889
+ value: "unlock category sidebars, price sliders, tag clouds without extra backend work."
1890
+ }
1891
+ ]
1892
+ },
1893
+ {
1894
+ title: "Test relevance in the dashboard before you write a line of ranking code",
1895
+ chunks: [
1896
+ {
1897
+ type: "text",
1898
+ value: "Our Search dashboard has a live preview where you can browse results."
1899
+ },
1900
+ {
1901
+ type: "text",
1902
+ value: "Tune your settings and see how it alters your results in"
1903
+ },
1904
+ {
1905
+ type: "link",
1906
+ value: "real-time.",
1907
+ href: "https://dashboard.algolia.com/explorer/browse"
1908
+ }
1909
+ ]
1910
+ },
1911
+ {
1912
+ title: "Search Analytics helps you discover opportunities",
1913
+ chunks: [
1914
+ {
1915
+ type: "text",
1916
+ value: "No click results for a particular query? Low click-through rates for another?"
1917
+ },
1918
+ {
1919
+ type: "text",
1920
+ value: "Our Search Analytics will help you identify synonyms, rules or other relevancy settings to improve your results."
1921
+ }
1922
+ ]
1923
+ },
1924
+ {
1925
+ title: "Let Algolia act as your recommendation engine",
1926
+ chunks: [
1927
+ {
1928
+ type: "text",
1929
+ value: "Beyond search, Algolia Recommend runs models trained on your existing indices and event data to power your recommendation engine."
1930
+ },
1931
+ {
1932
+ type: "text",
1933
+ value: "You can improve engagement with related, popular or visually similar items."
1934
+ }
1935
+ ]
1936
+ }
1937
+ ];
1938
+
1939
+ // src/ui/Tips.tsx
1940
+ import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
1941
+ var TICK_MS = 16;
1942
+ var CHUNK_HOLD_MS = 2e3;
1943
+ var HOLD_MS = 8e3;
1944
+ function TipTitle({ children }) {
1945
+ return /* @__PURE__ */ jsxs16(Box18, { gap: 1, children: [
1946
+ /* @__PURE__ */ jsx16(Text18, { color: "cyan", children: "\u2726" }),
1947
+ /* @__PURE__ */ jsx16(Text18, { color: "white", bold: true, children })
1948
+ ] });
1949
+ }
1950
+ function InlineSegment({ segment }) {
1951
+ switch (segment.type) {
1952
+ case "highlight":
1953
+ return /* @__PURE__ */ jsx16(Text18, { color: COLORS.success, children: segment.value });
1954
+ case "link":
1955
+ return /* @__PURE__ */ jsx16(Text18, { color: "cyan", underline: true, children: segment.href ? terminalLink(segment.value, segment.href) : segment.value });
1956
+ case "codeword":
1957
+ return /* @__PURE__ */ jsx16(Text18, { color: COLORS.highlight.fg, backgroundColor: COLORS.highlight.bg, children: segment.value });
1958
+ default:
1959
+ return /* @__PURE__ */ jsx16(Text18, { color: COLORS.muted, children: segment.value });
1960
+ }
1961
+ }
1962
+ function TipContent({
1963
+ chunks,
1964
+ revealed
1965
+ }) {
1966
+ let remaining = revealed;
1967
+ const slices = chunks.map((chunk) => {
1968
+ const slice = chunk.value.slice(0, Math.max(0, remaining));
1969
+ remaining -= chunk.value.length;
1970
+ return slice;
1971
+ });
1972
+ const blocks = [];
1973
+ for (let i = 0; i < chunks.length; i++) {
1974
+ const chunk = chunks[i];
1975
+ const slice = slices[i];
1976
+ if (!slice) continue;
1977
+ const segment = {
1978
+ type: chunk.type,
1979
+ value: slice,
1980
+ href: chunk.type === "link" ? chunk.href : void 0
1981
+ };
1982
+ if (chunk.type === "code") {
1983
+ blocks.push({ type: "code", segment });
1984
+ continue;
1985
+ }
1986
+ const last = blocks[blocks.length - 1];
1987
+ if (last?.type === "inline") {
1988
+ last.segments.push(segment);
1989
+ } else {
1990
+ blocks.push({ type: "inline", segments: [segment] });
1991
+ }
1992
+ }
1993
+ return /* @__PURE__ */ jsx16(Box18, { flexDirection: "column", marginLeft: 2, gap: 1, children: blocks.map(
1994
+ (block, i) => block.type === "code" ? /* @__PURE__ */ jsx16(Code, { children: block.segment.value }, i) : /* @__PURE__ */ jsx16(Text18, { children: block.segments.map((segment, j) => /* @__PURE__ */ jsxs16(Text18, { children: [
1995
+ j > 0 && " ",
1996
+ /* @__PURE__ */ jsx16(InlineSegment, { segment })
1997
+ ] }, j)) }, i)
1998
+ ) });
1999
+ }
2000
+ function Tips() {
2001
+ const [tipIndex, setTipIndex] = useState7(0);
2002
+ const [revealed, setRevealed] = useState7(0);
2003
+ const tip = tips[tipIndex];
2004
+ const contentLength = tip.chunks.reduce((sum, c) => sum + c.value.length, 0);
2005
+ const totalLength = tip.title.length + contentLength;
2006
+ const segments = [
2007
+ { type: "title", length: tip.title.length },
2008
+ ...tip.chunks.map((c) => ({ type: c.type, length: c.value.length }))
2009
+ ];
2010
+ const noPauseAfterText = [
2011
+ "highlight",
2012
+ "link",
2013
+ "codeword"
2014
+ ];
2015
+ const chunkBoundaries = [];
2016
+ let cumulative = 0;
2017
+ for (let i = 0; i < segments.length - 1; i++) {
2018
+ cumulative += segments[i].length;
2019
+ const skipPause = noPauseAfterText.includes(
2020
+ segments[i + 1].type
2021
+ );
2022
+ if (!skipPause) chunkBoundaries.push(cumulative);
2023
+ }
2024
+ useEffect3(() => {
2025
+ if (revealed < totalLength) {
2026
+ const delay2 = chunkBoundaries.includes(revealed) ? CHUNK_HOLD_MS : TICK_MS;
2027
+ const timer2 = setTimeout(() => setRevealed((r) => r + 1), delay2);
2028
+ return () => clearTimeout(timer2);
2029
+ }
2030
+ const timer = setTimeout(() => {
2031
+ setTipIndex((i) => {
2032
+ if (i < tips.length - 1) return i + 1;
2033
+ return 0;
2034
+ });
2035
+ setRevealed(0);
2036
+ }, HOLD_MS);
2037
+ return () => clearTimeout(timer);
2038
+ }, [revealed, totalLength]);
2039
+ const titleRevealed = tip.title.slice(0, revealed);
2040
+ const contentRevealed = Math.max(0, revealed - tip.title.length);
2041
+ return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", marginBottom: 1, gap: 1, children: [
2042
+ /* @__PURE__ */ jsx16(TipTitle, { children: titleRevealed }),
2043
+ /* @__PURE__ */ jsx16(TipContent, { chunks: tip.chunks, revealed: contentRevealed })
2044
+ ] });
2045
+ }
2046
+
1784
2047
  // src/ui/App.tsx
1785
- import { jsx as jsx15, jsxs as jsxs16 } from "react/jsx-runtime";
2048
+ import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
1786
2049
  function App() {
1787
- const { phase, error, homeScreen, currentStepIndex, steps, inputReq, user } = useWizard();
2050
+ const {
2051
+ phase,
2052
+ error,
2053
+ homeScreen,
2054
+ currentStepIndex,
2055
+ steps,
2056
+ inputReq,
2057
+ user,
2058
+ notices
2059
+ } = useWizard();
1788
2060
  const { exit } = useApp();
1789
- const { columns, rows } = useWindowSize8();
1790
- const [showLogs, setShowLogs] = useState7(false);
2061
+ const { columns, rows } = useWindowSize7();
2062
+ const [showLogs, setShowLogs] = useState8(false);
1791
2063
  const finished = phase === "done" || phase === "error";
1792
2064
  const currentStep = steps[currentStepIndex];
2065
+ const isInitialAnalysisStep = currentStepIndex === 0;
2066
+ const isAwaitingUserInput = phase === "awaitingInput" && !!inputReq;
2067
+ const showTips = phase === "running" && isInitialAnalysisStep && notices.length > 0;
2068
+ const showNoticesInMain = !isInitialAnalysisStep;
2069
+ const showNotices = !isAwaitingUserInput;
1793
2070
  useInput7(
1794
2071
  (_input, key) => {
1795
2072
  if (key.return) {
@@ -1829,8 +2106,8 @@ function App() {
1829
2106
  /* Clamped to exactly the viewport: a taller frame makes Ink clear and repaint
1830
2107
  the whole screen, and the scrolling throws off its cursor arithmetic —
1831
2108
  flicker and leftover rows. */
1832
- /* @__PURE__ */ jsxs16(
1833
- Box17,
2109
+ /* @__PURE__ */ jsxs17(
2110
+ Box19,
1834
2111
  {
1835
2112
  backgroundColor: COLORS.bg.main,
1836
2113
  flexDirection: "row",
@@ -1838,53 +2115,58 @@ function App() {
1838
2115
  height: scrollsPastViewport ? void 0 : rows,
1839
2116
  overflow: scrollsPastViewport ? "visible" : "hidden",
1840
2117
  children: [
1841
- mainWindowVisible && /* @__PURE__ */ jsxs16(
1842
- Box17,
2118
+ mainWindowVisible && /* @__PURE__ */ jsxs17(
2119
+ Box19,
1843
2120
  {
1844
2121
  flexDirection,
1845
2122
  width: "100%",
1846
2123
  maxHeight: rows,
1847
2124
  justifyContent: "space-between",
1848
2125
  children: [
1849
- showLogs ? /* @__PURE__ */ jsx15(Logs, {}) : /* @__PURE__ */ jsxs16(
1850
- Box17,
2126
+ showLogs ? /* @__PURE__ */ jsx17(Logs, {}) : /* @__PURE__ */ jsxs17(
2127
+ Box19,
1851
2128
  {
1852
2129
  flexDirection: "column",
1853
2130
  paddingX: 4,
1854
2131
  paddingY: 2,
1855
2132
  width: showSidebar ? 70 : "100%",
1856
2133
  flexGrow: 1,
2134
+ gap: 1,
1857
2135
  children: [
1858
- phase === "preflight" && !user && /* @__PURE__ */ jsx15(Box17, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs16(Text17, { color: COLORS.strong, bold: true, children: [
1859
- /* @__PURE__ */ jsx15(Spinner2, { type: "dots" }),
1860
- " Signing in to Algolia"
1861
- ] }) }),
1862
- phase === "preflight" && user && /* @__PURE__ */ jsx15(Box17, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs16(Text17, { color: COLORS.strong, bold: true, children: [
1863
- /* @__PURE__ */ jsx15(Spinner2, { type: "dots" }),
1864
- " Getting things ready"
1865
- ] }) }),
1866
- phase === "authenticating" && /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", marginBottom: 1, children: [
1867
- /* @__PURE__ */ jsxs16(Text17, { color: COLORS.strong, bold: true, children: [
1868
- /* @__PURE__ */ jsx15(Spinner2, { type: "dots" }),
2136
+ /* @__PURE__ */ jsxs17(Box19, { flexGrow: 2, flexDirection: "column", children: [
2137
+ phase === "preflight" && !user && /* @__PURE__ */ jsx17(Box19, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs17(Text19, { color: COLORS.strong, bold: true, children: [
2138
+ /* @__PURE__ */ jsx17(Spinner2, { type: "dots" }),
1869
2139
  " Signing in to Algolia"
2140
+ ] }) }),
2141
+ phase === "preflight" && user && /* @__PURE__ */ jsx17(Box19, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs17(Text19, { color: COLORS.strong, bold: true, children: [
2142
+ /* @__PURE__ */ jsx17(Spinner2, { type: "dots" }),
2143
+ " Getting things ready"
2144
+ ] }) }),
2145
+ phase === "authenticating" && /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", marginBottom: 1, children: [
2146
+ /* @__PURE__ */ jsxs17(Text19, { color: COLORS.strong, bold: true, children: [
2147
+ /* @__PURE__ */ jsx17(Spinner2, { type: "dots" }),
2148
+ " Signing in to Algolia"
2149
+ ] }),
2150
+ /* @__PURE__ */ jsx17(Text19, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
1870
2151
  ] }),
1871
- /* @__PURE__ */ jsx15(Text17, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
2152
+ /* @__PURE__ */ jsx17(CliOutput, {}),
2153
+ showTips && /* @__PURE__ */ jsx17(Tips, {}),
2154
+ showNoticesInMain && showNotices && /* @__PURE__ */ jsx17(Notices, { showAll: true, border: false }),
2155
+ /* @__PURE__ */ jsx17(PromptInput, {}),
2156
+ phase === "error" && error && /* @__PURE__ */ jsx17(Box19, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text19, { color: COLORS.status.error, children: [
2157
+ "\u2716 ",
2158
+ error
2159
+ ] }) })
1872
2160
  ] }),
1873
- /* @__PURE__ */ jsx15(CliOutput, {}),
1874
- /* @__PURE__ */ jsx15(Notices, {}),
1875
- /* @__PURE__ */ jsx15(PromptInput, {}),
1876
- phase === "error" && error && /* @__PURE__ */ jsx15(Box17, { marginTop: 1, children: /* @__PURE__ */ jsxs16(Text17, { color: COLORS.status.error, children: [
1877
- "\u2716 ",
1878
- error
1879
- ] }) })
2161
+ !showNoticesInMain && showNotices && /* @__PURE__ */ jsx17(Notices, {})
1880
2162
  ]
1881
2163
  }
1882
2164
  ),
1883
- showSidebar ? /* @__PURE__ */ jsx15(Sidebar, {}) : /* @__PURE__ */ jsx15(Ribbon, {})
2165
+ showSidebar ? /* @__PURE__ */ jsx17(Sidebar, {}) : /* @__PURE__ */ jsx17(Ribbon, {})
1884
2166
  ]
1885
2167
  }
1886
2168
  ),
1887
- phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */ jsx15(LearnMore, {}) : /* @__PURE__ */ jsx15(Welcome, {}))
2169
+ phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */ jsx17(LearnMore, {}) : /* @__PURE__ */ jsx17(Welcome, {}))
1888
2170
  ]
1889
2171
  }
1890
2172
  )
@@ -3445,10 +3727,10 @@ import { tool as tool11 } from "ai";
3445
3727
  import z18 from "zod";
3446
3728
  function notifyUserTool() {
3447
3729
  return tool11({
3448
- 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.`,
3730
+ 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. Only the latest update is shown on screen, in one line, so keep it under 140 characters.`,
3449
3731
  inputSchema: z18.object({
3450
- message: z18.string().describe(
3451
- "Short, plain-language description of what you are doing now."
3732
+ message: z18.string().max(140).describe(
3733
+ "Short, plain-language description of what you are doing now. Under 140 characters \u2014 only the latest update is shown, on one line."
3452
3734
  )
3453
3735
  }),
3454
3736
  execute: async ({ message }) => {
@@ -3764,7 +4046,7 @@ async function runAnalysis(mode, extraInstructions = []) {
3764
4046
  // package.json
3765
4047
  var package_default = {
3766
4048
  name: "@algolia/wizard",
3767
- version: "0.28.0",
4049
+ version: "0.29.0",
3768
4050
  description: "Magically implement Algolia functionality in your codebase",
3769
4051
  type: "module",
3770
4052
  engines: {
@@ -3826,6 +4108,7 @@ var package_default = {
3826
4108
  nanoid: "^5.1.15",
3827
4109
  pino: "^10.3.1",
3828
4110
  react: "^19.2.7",
4111
+ "terminal-link": "^5.0.0",
3829
4112
  varlock: "^1.5.1",
3830
4113
  zod: "^4.4.3",
3831
4114
  zustand: "^5.0.14"
@@ -5377,7 +5660,7 @@ function delay(ms) {
5377
5660
  }
5378
5661
 
5379
5662
  // src/main.tsx
5380
- import { jsx as jsx16 } from "react/jsx-runtime";
5663
+ import { jsx as jsx18 } from "react/jsx-runtime";
5381
5664
  async function startup() {
5382
5665
  setProjectRoot(process.cwd());
5383
5666
  let args;
@@ -5427,7 +5710,7 @@ ${formatStepList(workflow)}`);
5427
5710
  }
5428
5711
  async function run(workflow) {
5429
5712
  const store = useWizard.getState();
5430
- const instance = render(/* @__PURE__ */ jsx16(App, {}), { incrementalRendering: true });
5713
+ const instance = render(/* @__PURE__ */ jsx18(App, {}), { incrementalRendering: true });
5431
5714
  await store.waitForStart();
5432
5715
  store.syncSteps(
5433
5716
  workflow.steps.map((s) => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@algolia/wizard",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "Magically implement Algolia functionality in your codebase",
5
5
  "type": "module",
6
6
  "engines": {
@@ -62,6 +62,7 @@
62
62
  "nanoid": "^5.1.15",
63
63
  "pino": "^10.3.1",
64
64
  "react": "^19.2.7",
65
+ "terminal-link": "^5.0.0",
65
66
  "varlock": "^1.5.1",
66
67
  "zod": "^4.4.3",
67
68
  "zustand": "^5.0.14"