@algolia/wizard 0.9.0-rc.84.74 → 0.9.0-rc.85.78
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/README.md +1 -1
- package/dist/main.js +761 -543
- package/package.json +1 -3
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 Box15, Text as Text15, useApp, useInput as useInput6, useWindowSize as useWindowSize8 } from "ink";
|
|
8
8
|
|
|
9
9
|
// src/core/store.ts
|
|
10
10
|
import { create } from "zustand";
|
|
@@ -12,32 +12,86 @@ import { nanoid } from "nanoid";
|
|
|
12
12
|
|
|
13
13
|
// src/lib/algoliaCli.ts
|
|
14
14
|
import { spawn } from "node:child_process";
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return require2.resolve("@algolia/cli/bin/run.js");
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
function npxArgs(args) {
|
|
17
|
+
return ["--yes", "@algolia/cli@latest", ...args];
|
|
19
18
|
}
|
|
20
|
-
|
|
19
|
+
var shell = process.platform === "win32";
|
|
20
|
+
function lineSplitter(emit) {
|
|
21
|
+
let buffer = "";
|
|
22
|
+
return {
|
|
23
|
+
push(chunk) {
|
|
24
|
+
buffer += chunk;
|
|
25
|
+
const lines = buffer.split("\n");
|
|
26
|
+
buffer = lines.pop() ?? "";
|
|
27
|
+
for (const line of lines) emit(line.replace(/\r$/, ""));
|
|
28
|
+
},
|
|
29
|
+
flush() {
|
|
30
|
+
if (buffer) emit(buffer.replace(/\r$/, ""));
|
|
31
|
+
buffer = "";
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
var wizardSink = (stream, line) => {
|
|
36
|
+
if (!line.trim()) return;
|
|
37
|
+
useWizard.getState().pushCliOutput(stream, line);
|
|
38
|
+
};
|
|
39
|
+
var stderrSink = (stream, line) => {
|
|
40
|
+
if (stream === "stdout") return;
|
|
41
|
+
wizardSink(stream, line);
|
|
42
|
+
};
|
|
43
|
+
function runAlgoliaCli(args, { onOutput } = {}) {
|
|
44
|
+
const store = useWizard.getState();
|
|
45
|
+
const logId = store.logStart("tool", `algolia ${args.join(" ")}`);
|
|
21
46
|
return new Promise((resolve4, reject) => {
|
|
22
|
-
const child = spawn(
|
|
47
|
+
const child = spawn("npx", npxArgs(args), { shell });
|
|
23
48
|
let stdout = "";
|
|
24
49
|
let stderr = "";
|
|
25
|
-
|
|
26
|
-
|
|
50
|
+
const splitters = {
|
|
51
|
+
stdout: lineSplitter((line) => onOutput?.("stdout", line)),
|
|
52
|
+
stderr: lineSplitter((line) => onOutput?.("stderr", line))
|
|
53
|
+
};
|
|
54
|
+
child.stdout.on("data", (chunk) => {
|
|
55
|
+
const text = String(chunk);
|
|
56
|
+
stdout += text;
|
|
57
|
+
splitters.stdout.push(text);
|
|
58
|
+
});
|
|
59
|
+
child.stderr.on("data", (chunk) => {
|
|
60
|
+
const text = String(chunk);
|
|
61
|
+
stderr += text;
|
|
62
|
+
splitters.stderr.push(text);
|
|
63
|
+
});
|
|
27
64
|
child.on("error", reject);
|
|
28
65
|
child.on("close", (code) => {
|
|
66
|
+
splitters.stdout.flush();
|
|
67
|
+
splitters.stderr.flush();
|
|
29
68
|
if (code === 0) {
|
|
30
69
|
resolve4(stdout);
|
|
31
70
|
} else {
|
|
32
|
-
const
|
|
71
|
+
const failed = stderr.trim();
|
|
72
|
+
let detail = "";
|
|
73
|
+
if (failed) {
|
|
74
|
+
detail = `: ${failed}`;
|
|
75
|
+
} else if (stdout.trim()) {
|
|
76
|
+
detail = " (no stderr; stdout withheld \u2014 it may contain credentials)";
|
|
77
|
+
}
|
|
33
78
|
reject(
|
|
34
79
|
new Error(
|
|
35
|
-
`Algolia CLI \`${args.join(" ")}\` failed (exit ${code})${detail
|
|
80
|
+
`Algolia CLI \`${args.join(" ")}\` failed (exit ${code})${detail}`
|
|
36
81
|
)
|
|
37
82
|
);
|
|
38
83
|
}
|
|
39
84
|
});
|
|
40
|
-
})
|
|
85
|
+
}).then(
|
|
86
|
+
(out) => {
|
|
87
|
+
useWizard.getState().logEnd(logId, "success");
|
|
88
|
+
return out;
|
|
89
|
+
},
|
|
90
|
+
(err) => {
|
|
91
|
+
useWizard.getState().logEnd(logId, "error");
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
);
|
|
41
95
|
}
|
|
42
96
|
async function getUser() {
|
|
43
97
|
let raw;
|
|
@@ -52,19 +106,23 @@ async function getUser() {
|
|
|
52
106
|
return null;
|
|
53
107
|
}
|
|
54
108
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
child.on("error", reject);
|
|
63
|
-
child.on("close", (code) => {
|
|
64
|
-
if (code === 0) resolve4();
|
|
65
|
-
else reject(new Error(`Algolia authentication failed (exit ${code}).`));
|
|
66
|
-
});
|
|
109
|
+
var loginResultSchema = z.object({
|
|
110
|
+
success: z.boolean(),
|
|
111
|
+
email: z.string().optional()
|
|
112
|
+
});
|
|
113
|
+
async function runAuthLogin() {
|
|
114
|
+
const raw = await runAlgoliaCli(["auth", "login", "--non-interactive"], {
|
|
115
|
+
onOutput: stderrSink
|
|
67
116
|
});
|
|
117
|
+
let parsed;
|
|
118
|
+
try {
|
|
119
|
+
parsed = loginResultSchema.safeParse(JSON.parse(raw));
|
|
120
|
+
} catch {
|
|
121
|
+
parsed = void 0;
|
|
122
|
+
}
|
|
123
|
+
if (parsed?.success && !parsed.data.success) {
|
|
124
|
+
throw new Error("Algolia sign-in did not report success.");
|
|
125
|
+
}
|
|
68
126
|
}
|
|
69
127
|
|
|
70
128
|
// src/lib/auth.ts
|
|
@@ -171,6 +229,7 @@ function describeInputValue(value) {
|
|
|
171
229
|
return Array.isArray(value) ? value.join(", ") : value;
|
|
172
230
|
}
|
|
173
231
|
var NOTICE_INTERVAL_MS = 2e3;
|
|
232
|
+
var CLI_OUTPUT_LIMIT = 200;
|
|
174
233
|
var useWizard = create((set, get) => ({
|
|
175
234
|
phase: "idle",
|
|
176
235
|
homeScreen: "home",
|
|
@@ -182,22 +241,21 @@ var useWizard = create((set, get) => ({
|
|
|
182
241
|
notices: [],
|
|
183
242
|
_noticeQueue: [],
|
|
184
243
|
_noticeTimer: null,
|
|
244
|
+
cliOutput: [],
|
|
245
|
+
targetIndex: null,
|
|
185
246
|
logs: [],
|
|
186
247
|
error: null,
|
|
187
248
|
inputReq: null,
|
|
188
249
|
_resolve: null,
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
|
|
250
|
+
// `endAuth` lands on 'preflight', not 'idle': sign-in happens after the
|
|
251
|
+
// welcome screen, so going back would gate the run a second time.
|
|
252
|
+
beginAuth: () => set({ phase: "authenticating", cliOutput: [] }),
|
|
253
|
+
endAuth: () => set((s) => s.phase === "authenticating" ? { phase: "preflight" } : {}),
|
|
192
254
|
confirmStart: () => set(
|
|
193
255
|
(s) => s.phase === "idle" ? { phase: "preflight", homeScreen: "home" } : {}
|
|
194
256
|
),
|
|
195
|
-
// Welcome sub-view navigation; leaves `phase` untouched so the workflow stays paused.
|
|
196
257
|
openLearnMore: () => set({ homeScreen: "learnMore" }),
|
|
197
258
|
backToHome: () => set({ homeScreen: "home" }),
|
|
198
|
-
// Resolves once the phase leaves 'idle', whether that happens before or
|
|
199
|
-
// after this is called (the welcome screen's enter handler is what
|
|
200
|
-
// drives the transition via `confirmStart`).
|
|
201
259
|
waitForStart: () => new Promise((resolve4) => {
|
|
202
260
|
if (get().phase !== "idle") {
|
|
203
261
|
resolve4();
|
|
@@ -220,15 +278,19 @@ var useWizard = create((set, get) => ({
|
|
|
220
278
|
syncSteps: (steps, currentStepIndex) => set({ steps, currentStepIndex }),
|
|
221
279
|
setActiveStep: (index) => {
|
|
222
280
|
get()._clearNoticeQueue();
|
|
223
|
-
set({
|
|
281
|
+
set({
|
|
282
|
+
phase: "running",
|
|
283
|
+
currentStepIndex: index,
|
|
284
|
+
output: "",
|
|
285
|
+
notices: [],
|
|
286
|
+
cliOutput: []
|
|
287
|
+
});
|
|
224
288
|
},
|
|
225
289
|
setUser: (user) => set({ user }),
|
|
226
290
|
appendToken: (text) => set((s) => ({ output: s.output + text })),
|
|
227
291
|
clearOutput: () => set({ output: "" }),
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
// the timer stays armed through an empty drain so the cooldown always
|
|
231
|
-
// covers the time since the last render, even across bursts.
|
|
292
|
+
// The timer stays armed through an empty drain, so the spacing covers the
|
|
293
|
+
// time since the last render even across bursts.
|
|
232
294
|
pushNotice: (notice) => {
|
|
233
295
|
const { notices, _noticeQueue, _noticeTimer } = get();
|
|
234
296
|
if (_noticeTimer === null) {
|
|
@@ -261,6 +323,13 @@ var useWizard = create((set, get) => ({
|
|
|
261
323
|
get()._clearNoticeQueue();
|
|
262
324
|
set({ notices: [] });
|
|
263
325
|
},
|
|
326
|
+
pushCliOutput: (stream, text) => set((s) => ({
|
|
327
|
+
cliOutput: [...s.cliOutput, { id: nanoid(), stream, text }].slice(
|
|
328
|
+
-CLI_OUTPUT_LIMIT
|
|
329
|
+
)
|
|
330
|
+
})),
|
|
331
|
+
clearCliOutput: () => set({ cliOutput: [] }),
|
|
332
|
+
setTargetIndex: (index) => set({ targetIndex: index }),
|
|
264
333
|
logStart: (kind, name, input) => {
|
|
265
334
|
const id = nanoid();
|
|
266
335
|
set((s) => ({
|
|
@@ -283,17 +352,12 @@ var useWizard = create((set, get) => ({
|
|
|
283
352
|
_resolve: resolve4
|
|
284
353
|
});
|
|
285
354
|
}),
|
|
286
|
-
// Logs what the user picked — not the prompt text that was shown, which
|
|
287
|
-
// may repeat or duplicate on-screen content and isn't the useful signal
|
|
288
|
-
// here.
|
|
289
355
|
submitInput: async (value) => {
|
|
290
|
-
|
|
291
|
-
|
|
356
|
+
await markInteraction();
|
|
357
|
+
get()._resolve?.(value);
|
|
292
358
|
set({ inputReq: null, _resolve: null, phase: "running" });
|
|
293
359
|
const id = get().logStart("prompt", `User input: ${describeInputValue(value)}`);
|
|
294
360
|
get().logEnd(id, "success");
|
|
295
|
-
await markInteraction();
|
|
296
|
-
resolve4(value);
|
|
297
361
|
},
|
|
298
362
|
setDone: () => set({ phase: "done" }),
|
|
299
363
|
setError: (message) => set({ phase: "error", error: message }),
|
|
@@ -307,6 +371,8 @@ var useWizard = create((set, get) => ({
|
|
|
307
371
|
currentStepIndex: 0,
|
|
308
372
|
output: "",
|
|
309
373
|
notices: [],
|
|
374
|
+
cliOutput: [],
|
|
375
|
+
targetIndex: null,
|
|
310
376
|
logs: [],
|
|
311
377
|
error: null,
|
|
312
378
|
inputReq: null,
|
|
@@ -315,16 +381,100 @@ var useWizard = create((set, get) => ({
|
|
|
315
381
|
}
|
|
316
382
|
}));
|
|
317
383
|
|
|
384
|
+
// src/ui/CliOutput.tsx
|
|
385
|
+
import { Box, Text, useWindowSize } from "ink";
|
|
386
|
+
|
|
387
|
+
// src/ui/theme.ts
|
|
388
|
+
var MARKER = {
|
|
389
|
+
pending: "\u25CB",
|
|
390
|
+
running: "\u25D0",
|
|
391
|
+
done: "\u2713",
|
|
392
|
+
error: "\u2716"
|
|
393
|
+
};
|
|
394
|
+
var BRAND = "#003DFF";
|
|
395
|
+
var SECONDARY = "#5468FF";
|
|
396
|
+
var DANGER = "#F86E7E";
|
|
397
|
+
var COLORS = {
|
|
398
|
+
brand: BRAND,
|
|
399
|
+
primary: "#E6EDF3",
|
|
400
|
+
secondary: SECONDARY,
|
|
401
|
+
strong: "#FFFFFF",
|
|
402
|
+
muted: "#8B949E",
|
|
403
|
+
dim: "#484F58",
|
|
404
|
+
highlight: { bg: "#12331C", fg: "#4ADE80" },
|
|
405
|
+
badge: "#E3B341",
|
|
406
|
+
danger: DANGER,
|
|
407
|
+
success: "#4ADE80",
|
|
408
|
+
bg: {
|
|
409
|
+
main: "#0B0E14",
|
|
410
|
+
sidebar: "#14171E"
|
|
411
|
+
},
|
|
412
|
+
border: "#30363D",
|
|
413
|
+
accent: "#76A0FF",
|
|
414
|
+
status: {
|
|
415
|
+
pending: "gray",
|
|
416
|
+
running: "#76A0FF",
|
|
417
|
+
done: "#4ADE80",
|
|
418
|
+
error: DANGER
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
// src/ui/CliOutput.tsx
|
|
423
|
+
import { jsxs } from "react/jsx-runtime";
|
|
424
|
+
var CLI_MARKER = "\u203A";
|
|
425
|
+
var RESERVED_ROWS = 16;
|
|
426
|
+
var MAX_ROWS = 12;
|
|
427
|
+
var PANEL_TEXT_WIDTH = 45;
|
|
428
|
+
var URL_PATTERN = /https?:\/\//;
|
|
429
|
+
function rowCost(text) {
|
|
430
|
+
return URL_PATTERN.test(text) ? Math.max(1, Math.ceil(text.length / PANEL_TEXT_WIDTH)) : 1;
|
|
431
|
+
}
|
|
432
|
+
function CliOutput() {
|
|
433
|
+
const cliOutput = useWizard((s) => s.cliOutput);
|
|
434
|
+
const { rows } = useWindowSize();
|
|
435
|
+
if (!cliOutput.length) return null;
|
|
436
|
+
const rowBudget = Math.min(Math.max(rows - RESERVED_ROWS, 3), MAX_ROWS);
|
|
437
|
+
const visible = [];
|
|
438
|
+
let usedRows = 0;
|
|
439
|
+
for (let i = cliOutput.length - 1; i >= 0; i--) {
|
|
440
|
+
const cost = rowCost(cliOutput[i].text);
|
|
441
|
+
if (usedRows + cost > rowBudget && visible.length > 0) break;
|
|
442
|
+
visible.unshift(cliOutput[i]);
|
|
443
|
+
usedRows += cost;
|
|
444
|
+
}
|
|
445
|
+
const hidden = cliOutput.length - visible.length;
|
|
446
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
447
|
+
hidden > 0 && /* @__PURE__ */ jsxs(Text, { color: COLORS.dim, children: [
|
|
448
|
+
"\u2191 ",
|
|
449
|
+
hidden,
|
|
450
|
+
" earlier line(s)"
|
|
451
|
+
] }),
|
|
452
|
+
visible.map((line) => /* @__PURE__ */ jsxs(
|
|
453
|
+
Text,
|
|
454
|
+
{
|
|
455
|
+
color: line.stream === "stderr" ? COLORS.muted : COLORS.dim,
|
|
456
|
+
wrap: URL_PATTERN.test(line.text) ? "wrap" : "truncate",
|
|
457
|
+
children: [
|
|
458
|
+
CLI_MARKER,
|
|
459
|
+
" ",
|
|
460
|
+
line.text
|
|
461
|
+
]
|
|
462
|
+
},
|
|
463
|
+
line.id
|
|
464
|
+
))
|
|
465
|
+
] });
|
|
466
|
+
}
|
|
467
|
+
|
|
318
468
|
// src/ui/Notices.tsx
|
|
319
|
-
import { Box as
|
|
469
|
+
import { Box as Box3, Text as Text3, useWindowSize as useWindowSize3 } from "ink";
|
|
320
470
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
321
471
|
|
|
322
472
|
// src/ui/Table.tsx
|
|
323
|
-
import { Box, Text, measureElement, useWindowSize } from "ink";
|
|
473
|
+
import { Box as Box2, Text as Text2, measureElement, useWindowSize as useWindowSize2 } from "ink";
|
|
324
474
|
import { useEffect, useRef, useState } from "react";
|
|
325
475
|
import { jsx } from "react/jsx-runtime";
|
|
326
476
|
function Table({ columns, rows }) {
|
|
327
|
-
const { columns: termCols } =
|
|
477
|
+
const { columns: termCols } = useWindowSize2();
|
|
328
478
|
const ref = useRef(null);
|
|
329
479
|
const [width, setWidth] = useState(0);
|
|
330
480
|
useEffect(() => {
|
|
@@ -332,7 +482,7 @@ function Table({ columns, rows }) {
|
|
|
332
482
|
}, [termCols, columns, rows]);
|
|
333
483
|
if (rows.length === 0) return null;
|
|
334
484
|
const lines = formatTable(columns, rows, width || void 0);
|
|
335
|
-
return /* @__PURE__ */ jsx(
|
|
485
|
+
return /* @__PURE__ */ jsx(Box2, { flexDirection: "column", ref, children: lines.map((line, i) => /* @__PURE__ */ jsx(Text2, { wrap: "truncate", children: line }, `tbl-${i}`)) });
|
|
336
486
|
}
|
|
337
487
|
function formatTable(columns, rows, width) {
|
|
338
488
|
const natural = columns.map(
|
|
@@ -372,48 +522,13 @@ function resize(widths, budget) {
|
|
|
372
522
|
}
|
|
373
523
|
var truncate = (s, width) => s.length <= width ? s : width <= 1 ? s.slice(0, width) : `${s.slice(0, width - 1)}\u2026`;
|
|
374
524
|
|
|
375
|
-
// src/ui/theme.ts
|
|
376
|
-
var MARKER = {
|
|
377
|
-
pending: "\u25CB",
|
|
378
|
-
running: "\u25D0",
|
|
379
|
-
done: "\u2713",
|
|
380
|
-
error: "\u2716"
|
|
381
|
-
};
|
|
382
|
-
var BRAND = "#003DFF";
|
|
383
|
-
var SECONDARY = "#5468FF";
|
|
384
|
-
var DANGER = "#F86E7E";
|
|
385
|
-
var COLORS = {
|
|
386
|
-
brand: BRAND,
|
|
387
|
-
primary: "#E6EDF3",
|
|
388
|
-
secondary: SECONDARY,
|
|
389
|
-
strong: "#FFFFFF",
|
|
390
|
-
muted: "#8B949E",
|
|
391
|
-
dim: "#484F58",
|
|
392
|
-
highlight: { bg: "#12331C", fg: "#4ADE80" },
|
|
393
|
-
badge: "#E3B341",
|
|
394
|
-
danger: DANGER,
|
|
395
|
-
success: "#4ADE80",
|
|
396
|
-
bg: {
|
|
397
|
-
main: "#0B0E14",
|
|
398
|
-
sidebar: "#14171E"
|
|
399
|
-
},
|
|
400
|
-
border: "#30363D",
|
|
401
|
-
accent: "#76A0FF",
|
|
402
|
-
status: {
|
|
403
|
-
pending: "gray",
|
|
404
|
-
running: "#76A0FF",
|
|
405
|
-
done: "#4ADE80",
|
|
406
|
-
error: DANGER
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
|
|
410
525
|
// src/ui/Notices.tsx
|
|
411
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
526
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
412
527
|
var AGENT_MARKER = "\u2726";
|
|
413
|
-
var
|
|
414
|
-
var
|
|
528
|
+
var RESERVED_ROWS2 = 14;
|
|
529
|
+
var PANEL_TEXT_WIDTH2 = 45;
|
|
415
530
|
function messageLineCount(text) {
|
|
416
|
-
return Math.max(1, Math.ceil(text.length /
|
|
531
|
+
return Math.max(1, Math.ceil(text.length / PANEL_TEXT_WIDTH2));
|
|
417
532
|
}
|
|
418
533
|
function noticeLineCount(notice) {
|
|
419
534
|
const messageLines = (notice.messages ?? []).reduce((sum, m) => {
|
|
@@ -424,7 +539,7 @@ function noticeLineCount(notice) {
|
|
|
424
539
|
return messageLines + tableLines;
|
|
425
540
|
}
|
|
426
541
|
function fitVisibleNotices(notices, windowRows) {
|
|
427
|
-
const budget = Math.max(windowRows -
|
|
542
|
+
const budget = Math.max(windowRows - RESERVED_ROWS2, 3);
|
|
428
543
|
let used = 0;
|
|
429
544
|
let count = 0;
|
|
430
545
|
for (let i = notices.length - 1; i >= 0; i--) {
|
|
@@ -457,7 +572,7 @@ function parseHex(hex) {
|
|
|
457
572
|
}
|
|
458
573
|
function Notices() {
|
|
459
574
|
const notices = useWizard((s) => s.notices);
|
|
460
|
-
const { rows: windowRows } =
|
|
575
|
+
const { rows: windowRows } = useWindowSize3();
|
|
461
576
|
const visible = fitVisibleNotices(notices, windowRows);
|
|
462
577
|
const [pulseStep, setPulseStep] = useState2(0);
|
|
463
578
|
useEffect2(() => {
|
|
@@ -474,14 +589,14 @@ function Notices() {
|
|
|
474
589
|
}, []);
|
|
475
590
|
if (!visible.length) return null;
|
|
476
591
|
const pulseColor = PULSE_COLORS[pulseStep];
|
|
477
|
-
return /* @__PURE__ */ jsx2(
|
|
592
|
+
return /* @__PURE__ */ jsx2(Box3, { flexDirection: "column", gap: 1, marginBottom: 1, children: visible.map((notice, i) => {
|
|
478
593
|
const isLatest = i === visible.length - 1;
|
|
479
|
-
return /* @__PURE__ */
|
|
594
|
+
return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", children: [
|
|
480
595
|
notice.messages?.map((m, j) => {
|
|
481
596
|
const line = typeof m === "string" ? { text: m } : m;
|
|
482
597
|
const prefix = j === 0 ? `${AGENT_MARKER} ` : " ";
|
|
483
|
-
return /* @__PURE__ */
|
|
484
|
-
|
|
598
|
+
return /* @__PURE__ */ jsxs2(
|
|
599
|
+
Text3,
|
|
485
600
|
{
|
|
486
601
|
color: isLatest && !line.color ? pulseColor : line.color ?? COLORS.dim,
|
|
487
602
|
bold: line.bold,
|
|
@@ -499,41 +614,41 @@ function Notices() {
|
|
|
499
614
|
}
|
|
500
615
|
|
|
501
616
|
// src/ui/PromptInput.tsx
|
|
502
|
-
import { Box as
|
|
617
|
+
import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
|
|
503
618
|
import TextInput from "ink-text-input";
|
|
504
619
|
import { useState as useState5 } from "react";
|
|
505
620
|
|
|
506
621
|
// src/ui/NextAction.tsx
|
|
507
|
-
import { Box as
|
|
508
|
-
import { Fragment, jsx as jsx3, jsxs as
|
|
622
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
623
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
509
624
|
function NextAction({
|
|
510
625
|
action,
|
|
511
626
|
keyHint,
|
|
512
627
|
hierarchy = "primary"
|
|
513
628
|
}) {
|
|
514
|
-
return /* @__PURE__ */
|
|
515
|
-
hierarchy === "primary" && /* @__PURE__ */ jsx3(
|
|
516
|
-
hierarchy === "secondary" && /* @__PURE__ */
|
|
517
|
-
/* @__PURE__ */ jsx3(
|
|
518
|
-
/* @__PURE__ */ jsx3(
|
|
629
|
+
return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "row", gap: 1, children: [
|
|
630
|
+
hierarchy === "primary" && /* @__PURE__ */ jsx3(Text4, { color: COLORS.success, bold: true, children: `> ${action}` }),
|
|
631
|
+
hierarchy === "secondary" && /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
632
|
+
/* @__PURE__ */ jsx3(Text4, { color: COLORS.success, bold: true, children: `>` }),
|
|
633
|
+
/* @__PURE__ */ jsx3(Text4, { color: COLORS.primary, bold: true, children: action })
|
|
519
634
|
] }),
|
|
520
|
-
/* @__PURE__ */
|
|
521
|
-
/* @__PURE__ */ jsx3(
|
|
522
|
-
/* @__PURE__ */ jsx3(
|
|
523
|
-
/* @__PURE__ */ jsx3(
|
|
524
|
-
/* @__PURE__ */ jsx3(
|
|
635
|
+
/* @__PURE__ */ jsxs3(Box4, { children: [
|
|
636
|
+
/* @__PURE__ */ jsx3(Text4, { color: COLORS.muted, children: "press " }),
|
|
637
|
+
/* @__PURE__ */ jsx3(Text4, { color: COLORS.muted, children: `[` }),
|
|
638
|
+
/* @__PURE__ */ jsx3(Text4, { color: COLORS.primary, children: keyHint }),
|
|
639
|
+
/* @__PURE__ */ jsx3(Text4, { color: COLORS.muted, children: `]` })
|
|
525
640
|
] })
|
|
526
641
|
] });
|
|
527
642
|
}
|
|
528
643
|
|
|
529
644
|
// src/ui/SelectPrompt.tsx
|
|
530
|
-
import { Box as
|
|
645
|
+
import { Box as Box6, Text as Text6, useInput, useWindowSize as useWindowSize5 } from "ink";
|
|
531
646
|
import { useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState4 } from "react";
|
|
532
647
|
|
|
533
648
|
// src/ui/ScrollView.tsx
|
|
534
|
-
import { Box as
|
|
649
|
+
import { Box as Box5, Text as Text5, measureElement as measureElement2, useWindowSize as useWindowSize4 } from "ink";
|
|
535
650
|
import { useCallback, useLayoutEffect, useRef as useRef2, useState as useState3 } from "react";
|
|
536
|
-
import { jsxs as
|
|
651
|
+
import { jsxs as jsxs4 } from "react/jsx-runtime";
|
|
537
652
|
var INDICATOR_ROWS = 2;
|
|
538
653
|
function fittedWidth(node, columns) {
|
|
539
654
|
let left = 0;
|
|
@@ -548,7 +663,7 @@ function useScrollWindow({
|
|
|
548
663
|
followBottom = false
|
|
549
664
|
}) {
|
|
550
665
|
const viewportRef = useRef2(null);
|
|
551
|
-
const { columns } =
|
|
666
|
+
const { columns } = useWindowSize4();
|
|
552
667
|
const [size, setSize] = useState3(
|
|
553
668
|
null
|
|
554
669
|
);
|
|
@@ -603,14 +718,14 @@ function useScrollWindow({
|
|
|
603
718
|
};
|
|
604
719
|
}
|
|
605
720
|
function ScrollView({ scroll, children }) {
|
|
606
|
-
return /* @__PURE__ */
|
|
607
|
-
scroll.hiddenAbove > 0 && /* @__PURE__ */
|
|
721
|
+
return /* @__PURE__ */ jsxs4(Box5, { ref: scroll.viewportRef, flexDirection: "column", flexGrow: 1, children: [
|
|
722
|
+
scroll.hiddenAbove > 0 && /* @__PURE__ */ jsxs4(Text5, { color: COLORS.dim, children: [
|
|
608
723
|
"\u2191 ",
|
|
609
724
|
scroll.hiddenAbove,
|
|
610
725
|
" more"
|
|
611
726
|
] }),
|
|
612
727
|
children,
|
|
613
|
-
scroll.hiddenBelow > 0 && /* @__PURE__ */
|
|
728
|
+
scroll.hiddenBelow > 0 && /* @__PURE__ */ jsxs4(Text5, { color: COLORS.dim, children: [
|
|
614
729
|
"\u2193 ",
|
|
615
730
|
scroll.hiddenBelow,
|
|
616
731
|
" more"
|
|
@@ -619,7 +734,7 @@ function ScrollView({ scroll, children }) {
|
|
|
619
734
|
}
|
|
620
735
|
|
|
621
736
|
// src/ui/SelectPrompt.tsx
|
|
622
|
-
import { jsx as jsx4, jsxs as
|
|
737
|
+
import { jsx as jsx4, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
623
738
|
var CANCEL = "cancel";
|
|
624
739
|
var ARROW_WIDTH = 4;
|
|
625
740
|
var COLUMN_GAP = 2;
|
|
@@ -650,7 +765,7 @@ function SelectPrompt({
|
|
|
650
765
|
if (multi) hints.push({ key: "[space]", label: "select" });
|
|
651
766
|
hints.push({ key: "[enter]", label: "confirm" });
|
|
652
767
|
const containerRef = useRef3(null);
|
|
653
|
-
const { columns } =
|
|
768
|
+
const { columns } = useWindowSize5();
|
|
654
769
|
const [width, setWidth] = useState4(columns);
|
|
655
770
|
useLayoutEffect2(() => {
|
|
656
771
|
if (!containerRef.current) return;
|
|
@@ -704,14 +819,14 @@ function SelectPrompt({
|
|
|
704
819
|
}
|
|
705
820
|
}
|
|
706
821
|
});
|
|
707
|
-
return /* @__PURE__ */ jsx4(
|
|
708
|
-
/* @__PURE__ */
|
|
709
|
-
error && /* @__PURE__ */ jsx4(
|
|
710
|
-
messages?.map((m, i) => /* @__PURE__ */ jsx4(
|
|
822
|
+
return /* @__PURE__ */ jsx4(Box6, { ref: containerRef, flexGrow: 1, children: /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", gap: 1, width, children: [
|
|
823
|
+
/* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", gap: 1, flexShrink: 0, children: [
|
|
824
|
+
error && /* @__PURE__ */ jsx4(Text6, { color: COLORS.danger, children: error }),
|
|
825
|
+
messages?.map((m, i) => /* @__PURE__ */ jsx4(Text6, { color: COLORS.muted, children: m }, `msg-${i}`)),
|
|
711
826
|
table && /* @__PURE__ */ jsx4(Table, { columns: table.columns, rows: table.rows }),
|
|
712
|
-
/* @__PURE__ */
|
|
713
|
-
question && /* @__PURE__ */ jsx4(
|
|
714
|
-
helpText && /* @__PURE__ */ jsx4(
|
|
827
|
+
/* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
828
|
+
question && /* @__PURE__ */ jsx4(Text6, { color: COLORS.muted, children: question }),
|
|
829
|
+
helpText && /* @__PURE__ */ jsx4(Text6, { color: COLORS.dim, children: helpText })
|
|
715
830
|
] })
|
|
716
831
|
] }),
|
|
717
832
|
/* @__PURE__ */ jsx4(ScrollView, { scroll, children: visible.map((option, visibleIndex) => {
|
|
@@ -721,39 +836,39 @@ function SelectPrompt({
|
|
|
721
836
|
const bullet = multi && !isCancel ? checked.has(i) ? "\u25CF " : "\u25CB " : "";
|
|
722
837
|
const sec = isCancel ? void 0 : secondary?.[i];
|
|
723
838
|
const labelColor = highlighted ? COLORS.highlight.fg : void 0;
|
|
724
|
-
const label = /* @__PURE__ */
|
|
839
|
+
const label = /* @__PURE__ */ jsxs5(Text6, { color: labelColor, wrap: "truncate", children: [
|
|
725
840
|
highlighted ? "\u276F " : " ",
|
|
726
841
|
bullet,
|
|
727
842
|
option
|
|
728
843
|
] });
|
|
729
844
|
const isText = sec?.kind === "text";
|
|
730
|
-
return /* @__PURE__ */
|
|
731
|
-
|
|
845
|
+
return /* @__PURE__ */ jsxs5(
|
|
846
|
+
Box6,
|
|
732
847
|
{
|
|
733
848
|
width: isText ? "100%" : barWidth,
|
|
734
849
|
paddingX: 1,
|
|
735
850
|
paddingY: 1,
|
|
736
851
|
backgroundColor: highlighted ? COLORS.highlight.bg : void 0,
|
|
737
852
|
children: [
|
|
738
|
-
/* @__PURE__ */ jsx4(
|
|
739
|
-
isText && textWidth > 0 && /* @__PURE__ */ jsx4(
|
|
740
|
-
|
|
853
|
+
/* @__PURE__ */ jsx4(Box6, { width: isText ? labelWidth : barLabelWidth, children: label }),
|
|
854
|
+
isText && textWidth > 0 && /* @__PURE__ */ jsx4(Box6, { width: textWidth, children: /* @__PURE__ */ jsx4(
|
|
855
|
+
Text6,
|
|
741
856
|
{
|
|
742
857
|
wrap: "truncate",
|
|
743
858
|
color: highlighted ? COLORS.primary : COLORS.muted,
|
|
744
859
|
children: sec.value
|
|
745
860
|
}
|
|
746
861
|
) }),
|
|
747
|
-
sec?.kind === "badge" && /* @__PURE__ */ jsx4(
|
|
862
|
+
sec?.kind === "badge" && /* @__PURE__ */ jsx4(Box6, { width: badgeWidth, justifyContent: "flex-end", children: /* @__PURE__ */ jsx4(Text6, { color: COLORS.badge, wrap: "truncate", children: sec.value }) })
|
|
748
863
|
]
|
|
749
864
|
},
|
|
750
865
|
`row-${i}`
|
|
751
866
|
);
|
|
752
867
|
}) }),
|
|
753
|
-
/* @__PURE__ */ jsx4(
|
|
868
|
+
/* @__PURE__ */ jsx4(Box6, { flexShrink: 0, children: /* @__PURE__ */ jsx4(Text6, { children: hints.map(({ key, label }, i) => /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
754
869
|
i > 0 ? " " : "",
|
|
755
|
-
/* @__PURE__ */ jsx4(
|
|
756
|
-
/* @__PURE__ */
|
|
870
|
+
/* @__PURE__ */ jsx4(Text6, { color: COLORS.primary, children: key }),
|
|
871
|
+
/* @__PURE__ */ jsxs5(Text6, { color: COLORS.dim, children: [
|
|
757
872
|
" ",
|
|
758
873
|
label
|
|
759
874
|
] })
|
|
@@ -762,7 +877,7 @@ function SelectPrompt({
|
|
|
762
877
|
}
|
|
763
878
|
|
|
764
879
|
// src/ui/PromptInput.tsx
|
|
765
|
-
import { jsx as jsx5, jsxs as
|
|
880
|
+
import { jsx as jsx5, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
766
881
|
var ACCEPT_REJECT_OPTIONS = ["Accept", "Reject"];
|
|
767
882
|
function EnterToContinuePrompt({
|
|
768
883
|
question,
|
|
@@ -773,10 +888,10 @@ function EnterToContinuePrompt({
|
|
|
773
888
|
if (key.return) onDecide(true);
|
|
774
889
|
else if (key.escape) onDecide(false);
|
|
775
890
|
});
|
|
776
|
-
return /* @__PURE__ */
|
|
777
|
-
messages?.map((m, i) => /* @__PURE__ */ jsx5(
|
|
778
|
-
question && /* @__PURE__ */ jsx5(
|
|
779
|
-
/* @__PURE__ */
|
|
891
|
+
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", gap: 1, children: [
|
|
892
|
+
messages?.map((m, i) => /* @__PURE__ */ jsx5(Text7, { color: COLORS.muted, children: m }, `msg-${i}`)),
|
|
893
|
+
question && /* @__PURE__ */ jsx5(Text7, { color: COLORS.primary, children: question }),
|
|
894
|
+
/* @__PURE__ */ jsxs6(Box7, { gap: 1, flexDirection: "column", children: [
|
|
780
895
|
/* @__PURE__ */ jsx5(NextAction, { action: "continue", keyHint: "enter" }),
|
|
781
896
|
/* @__PURE__ */ jsx5(NextAction, { action: "decline", keyHint: "esc", hierarchy: "secondary" })
|
|
782
897
|
] })
|
|
@@ -786,11 +901,11 @@ function PromptInput() {
|
|
|
786
901
|
const { phase, inputReq, submitInput } = useWizard();
|
|
787
902
|
const [draft, setDraft] = useState5("");
|
|
788
903
|
if (phase === "done" || phase === "error") {
|
|
789
|
-
return /* @__PURE__ */ jsx5(
|
|
904
|
+
return /* @__PURE__ */ jsx5(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text7, { color: "gray", dimColor: true, children: "Press Enter or Esc to exit" }) });
|
|
790
905
|
}
|
|
791
906
|
if (phase !== "awaitingInput" || !inputReq) return null;
|
|
792
907
|
if (inputReq.promptType === "multipleChoice") {
|
|
793
|
-
return /* @__PURE__ */ jsx5(
|
|
908
|
+
return /* @__PURE__ */ jsx5(Box7, { flexGrow: 1, children: /* @__PURE__ */ jsx5(
|
|
794
909
|
SelectPrompt,
|
|
795
910
|
{
|
|
796
911
|
question: inputReq.prompt,
|
|
@@ -807,7 +922,7 @@ function PromptInput() {
|
|
|
807
922
|
) });
|
|
808
923
|
}
|
|
809
924
|
if (inputReq.promptType === "multiSelect") {
|
|
810
|
-
return /* @__PURE__ */ jsx5(
|
|
925
|
+
return /* @__PURE__ */ jsx5(Box7, { flexGrow: 1, children: /* @__PURE__ */ jsx5(
|
|
811
926
|
SelectPrompt,
|
|
812
927
|
{
|
|
813
928
|
multi: true,
|
|
@@ -822,7 +937,7 @@ function PromptInput() {
|
|
|
822
937
|
) });
|
|
823
938
|
}
|
|
824
939
|
if (inputReq.promptType === "notice") {
|
|
825
|
-
return /* @__PURE__ */ jsx5(
|
|
940
|
+
return /* @__PURE__ */ jsx5(Box7, { flexGrow: 1, children: /* @__PURE__ */ jsx5(
|
|
826
941
|
SelectPrompt,
|
|
827
942
|
{
|
|
828
943
|
question: inputReq.prompt,
|
|
@@ -844,7 +959,7 @@ function PromptInput() {
|
|
|
844
959
|
}
|
|
845
960
|
if (inputReq.promptType === "acceptReject") {
|
|
846
961
|
const labels = inputReq.options?.length ? inputReq.options : ACCEPT_REJECT_OPTIONS;
|
|
847
|
-
return /* @__PURE__ */ jsx5(
|
|
962
|
+
return /* @__PURE__ */ jsx5(Box7, { flexGrow: 1, children: /* @__PURE__ */ jsx5(
|
|
848
963
|
SelectPrompt,
|
|
849
964
|
{
|
|
850
965
|
question: inputReq.prompt,
|
|
@@ -855,11 +970,11 @@ function PromptInput() {
|
|
|
855
970
|
}
|
|
856
971
|
) });
|
|
857
972
|
}
|
|
858
|
-
return /* @__PURE__ */
|
|
859
|
-
inputReq.error && /* @__PURE__ */ jsx5(
|
|
860
|
-
inputReq.messages?.map((m, i) => /* @__PURE__ */ jsx5(
|
|
861
|
-
/* @__PURE__ */
|
|
862
|
-
/* @__PURE__ */
|
|
973
|
+
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
|
|
974
|
+
inputReq.error && /* @__PURE__ */ jsx5(Text7, { color: COLORS.danger, children: inputReq.error }),
|
|
975
|
+
inputReq.messages?.map((m, i) => /* @__PURE__ */ jsx5(Text7, { color: COLORS.muted, children: m }, `msg-${i}`)),
|
|
976
|
+
/* @__PURE__ */ jsxs6(Box7, { children: [
|
|
977
|
+
/* @__PURE__ */ jsxs6(Text7, { color: COLORS.primary, children: [
|
|
863
978
|
inputReq.prompt,
|
|
864
979
|
" "
|
|
865
980
|
] }),
|
|
@@ -881,7 +996,7 @@ function PromptInput() {
|
|
|
881
996
|
// src/ui/Welcome.tsx
|
|
882
997
|
import { dirname as dirname2, join as join3 } from "node:path";
|
|
883
998
|
import { fileURLToPath } from "node:url";
|
|
884
|
-
import { Box as
|
|
999
|
+
import { Box as Box8, Spacer, Text as Text8, useInput as useInput3, useWindowSize as useWindowSize6 } from "ink";
|
|
885
1000
|
|
|
886
1001
|
// src/ui/copy/welcome.ts
|
|
887
1002
|
var sidebarItems = [
|
|
@@ -909,27 +1024,27 @@ var sidebarItems = [
|
|
|
909
1024
|
|
|
910
1025
|
// src/ui/Welcome.tsx
|
|
911
1026
|
import Image, { InkPictureProvider } from "ink-picture";
|
|
912
|
-
import { jsx as jsx6, jsxs as
|
|
1027
|
+
import { jsx as jsx6, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
913
1028
|
var IMAGE_PATH = join3(dirname2(fileURLToPath(import.meta.url)), "algolia.png");
|
|
914
1029
|
function SidebarItem({
|
|
915
1030
|
title,
|
|
916
1031
|
description
|
|
917
1032
|
}) {
|
|
918
|
-
return /* @__PURE__ */
|
|
919
|
-
/* @__PURE__ */
|
|
920
|
-
/* @__PURE__ */ jsx6(
|
|
921
|
-
/* @__PURE__ */ jsx6(
|
|
1033
|
+
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", children: [
|
|
1034
|
+
/* @__PURE__ */ jsxs7(Box8, { gap: 1, children: [
|
|
1035
|
+
/* @__PURE__ */ jsx6(Text8, { color: COLORS.success, children: "\u2192" }),
|
|
1036
|
+
/* @__PURE__ */ jsx6(Text8, { color: COLORS.strong, bold: true, children: title })
|
|
922
1037
|
] }),
|
|
923
|
-
/* @__PURE__ */
|
|
1038
|
+
/* @__PURE__ */ jsxs7(Box8, { flexDirection: "row", gap: 2, children: [
|
|
924
1039
|
/* @__PURE__ */ jsx6(Spacer, {}),
|
|
925
|
-
/* @__PURE__ */ jsx6(
|
|
1040
|
+
/* @__PURE__ */ jsx6(Text8, { color: COLORS.muted, children: description })
|
|
926
1041
|
] })
|
|
927
1042
|
] });
|
|
928
1043
|
}
|
|
929
1044
|
function Welcome() {
|
|
930
1045
|
const confirmStart = useWizard((s) => s.confirmStart);
|
|
931
1046
|
const openLearnMore = useWizard((s) => s.openLearnMore);
|
|
932
|
-
const { rows } =
|
|
1047
|
+
const { rows } = useWindowSize6();
|
|
933
1048
|
useInput3((input, key) => {
|
|
934
1049
|
if (key.return) confirmStart();
|
|
935
1050
|
else if (input === "i") openLearnMore();
|
|
@@ -948,15 +1063,15 @@ function Welcome() {
|
|
|
948
1063
|
if (rows < 30) {
|
|
949
1064
|
layout = scales["small"];
|
|
950
1065
|
}
|
|
951
|
-
return /* @__PURE__ */
|
|
1066
|
+
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "row", justifyContent: "space-between", width: "100%", children: [
|
|
952
1067
|
/* @__PURE__ */ jsx6(
|
|
953
|
-
|
|
1068
|
+
Box8,
|
|
954
1069
|
{
|
|
955
1070
|
paddingY: layout.main.padding.y,
|
|
956
1071
|
paddingX: layout.main.padding.x,
|
|
957
1072
|
flexDirection: "column",
|
|
958
1073
|
justifyContent: "center",
|
|
959
|
-
children: /* @__PURE__ */
|
|
1074
|
+
children: /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 2, children: [
|
|
960
1075
|
/* @__PURE__ */ jsx6(InkPictureProvider, { children: /* @__PURE__ */ jsx6(
|
|
961
1076
|
Image,
|
|
962
1077
|
{
|
|
@@ -968,16 +1083,16 @@ function Welcome() {
|
|
|
968
1083
|
protocol: "halfBlock"
|
|
969
1084
|
}
|
|
970
1085
|
) }),
|
|
971
|
-
/* @__PURE__ */ jsx6(
|
|
972
|
-
/* @__PURE__ */
|
|
1086
|
+
/* @__PURE__ */ jsx6(Text8, { color: COLORS.muted, children: "\u2726 From zero \u2192 working search in ~10 minutes" }),
|
|
1087
|
+
/* @__PURE__ */ jsxs7(Box8, { gap: 1, flexDirection: "column", children: [
|
|
973
1088
|
/* @__PURE__ */ jsx6(NextAction, { action: "start wizard", keyHint: "enter" }),
|
|
974
1089
|
/* @__PURE__ */ jsx6(NextAction, { action: "learn more", keyHint: "i", hierarchy: "secondary" })
|
|
975
1090
|
] })
|
|
976
1091
|
] })
|
|
977
1092
|
}
|
|
978
1093
|
),
|
|
979
|
-
/* @__PURE__ */
|
|
980
|
-
|
|
1094
|
+
/* @__PURE__ */ jsxs7(
|
|
1095
|
+
Box8,
|
|
981
1096
|
{
|
|
982
1097
|
backgroundColor: COLORS.bg.sidebar,
|
|
983
1098
|
width: 40,
|
|
@@ -987,7 +1102,7 @@ function Welcome() {
|
|
|
987
1102
|
flexDirection: "column",
|
|
988
1103
|
justifyContent: "center",
|
|
989
1104
|
children: [
|
|
990
|
-
/* @__PURE__ */ jsx6(
|
|
1105
|
+
/* @__PURE__ */ jsx6(Text8, { color: COLORS.muted, children: "WHAT THIS WIZARD WILL DO" }),
|
|
991
1106
|
sidebarItems.map((i, idx) => /* @__PURE__ */ jsx6(SidebarItem, { title: i.title, description: i.description }, idx))
|
|
992
1107
|
]
|
|
993
1108
|
}
|
|
@@ -997,7 +1112,7 @@ function Welcome() {
|
|
|
997
1112
|
|
|
998
1113
|
// src/ui/LearnMore.tsx
|
|
999
1114
|
import { Fragment as Fragment2 } from "react";
|
|
1000
|
-
import { Box as
|
|
1115
|
+
import { Box as Box9, Text as Text9, useInput as useInput4, useWindowSize as useWindowSize7 } from "ink";
|
|
1001
1116
|
|
|
1002
1117
|
// src/ui/copy/learn-more.ts
|
|
1003
1118
|
var accessIntro = "Everything runs locally on your machine. Nothing is written or sent without an explicit yes from you.";
|
|
@@ -1034,7 +1149,7 @@ var policyLinks = [
|
|
|
1034
1149
|
];
|
|
1035
1150
|
|
|
1036
1151
|
// src/ui/LearnMore.tsx
|
|
1037
|
-
import { jsx as jsx7, jsxs as
|
|
1152
|
+
import { jsx as jsx7, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1038
1153
|
var TAG_COLORS = {
|
|
1039
1154
|
READ: COLORS.success,
|
|
1040
1155
|
WRITE: COLORS.badge,
|
|
@@ -1050,25 +1165,25 @@ function NeverLine({
|
|
|
1050
1165
|
}) {
|
|
1051
1166
|
const used = segments.reduce((n, s) => n + s.text.length, 0);
|
|
1052
1167
|
const rightPad = Math.max(0, width - 2 - NEVER_BOX_PAD_X - used);
|
|
1053
|
-
return /* @__PURE__ */
|
|
1054
|
-
/* @__PURE__ */ jsx7(
|
|
1168
|
+
return /* @__PURE__ */ jsxs8(Text9, { children: [
|
|
1169
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.danger, children: "\u2502" }),
|
|
1055
1170
|
" ".repeat(NEVER_BOX_PAD_X),
|
|
1056
|
-
segments.map((s, i) => /* @__PURE__ */ jsx7(
|
|
1171
|
+
segments.map((s, i) => /* @__PURE__ */ jsx7(Text9, { color: s.color, bold: s.bold, children: s.text }, i)),
|
|
1057
1172
|
" ".repeat(rightPad),
|
|
1058
|
-
/* @__PURE__ */ jsx7(
|
|
1173
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.danger, children: "\u2502" })
|
|
1059
1174
|
] });
|
|
1060
1175
|
}
|
|
1061
1176
|
function LearnMore() {
|
|
1062
1177
|
const confirmStart = useWizard((s) => s.confirmStart);
|
|
1063
1178
|
const backToHome = useWizard((s) => s.backToHome);
|
|
1064
|
-
const { columns } =
|
|
1179
|
+
const { columns } = useWindowSize7();
|
|
1065
1180
|
const dividerWidth = Math.max(0, columns - PADDING_X * 2);
|
|
1066
1181
|
useInput4((_input, key) => {
|
|
1067
1182
|
if (key.escape) backToHome();
|
|
1068
1183
|
else if (key.return) confirmStart();
|
|
1069
1184
|
});
|
|
1070
|
-
return /* @__PURE__ */
|
|
1071
|
-
|
|
1185
|
+
return /* @__PURE__ */ jsxs8(
|
|
1186
|
+
Box9,
|
|
1072
1187
|
{
|
|
1073
1188
|
flexDirection: "column",
|
|
1074
1189
|
paddingX: PADDING_X,
|
|
@@ -1076,20 +1191,20 @@ function LearnMore() {
|
|
|
1076
1191
|
width: "100%",
|
|
1077
1192
|
gap: 1,
|
|
1078
1193
|
children: [
|
|
1079
|
-
/* @__PURE__ */ jsx7(
|
|
1080
|
-
/* @__PURE__ */ jsx7(
|
|
1081
|
-
/* @__PURE__ */ jsx7(
|
|
1082
|
-
/* @__PURE__ */ jsx7(
|
|
1083
|
-
/* @__PURE__ */
|
|
1084
|
-
/* @__PURE__ */ jsx7(
|
|
1085
|
-
/* @__PURE__ */ jsx7(
|
|
1086
|
-
/* @__PURE__ */ jsx7(
|
|
1087
|
-
/* @__PURE__ */ jsx7(
|
|
1194
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.strong, bold: true, children: "What algolia wizard accesses" }),
|
|
1195
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: accessIntro }),
|
|
1196
|
+
/* @__PURE__ */ jsx7(Box9, { flexDirection: "column", children: accessItems.map((item) => /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", marginTop: 1, children: [
|
|
1197
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.border, children: "\u2500".repeat(dividerWidth) }),
|
|
1198
|
+
/* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", gap: 1, marginTop: 1, children: [
|
|
1199
|
+
/* @__PURE__ */ jsx7(Box9, { width: TAG_COLUMN_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx7(Text9, { color: TAG_COLORS[item.tag], bold: true, children: `[${item.tag}]` }) }),
|
|
1200
|
+
/* @__PURE__ */ jsx7(Box9, { flexDirection: "column", children: /* @__PURE__ */ jsxs8(Text9, { children: [
|
|
1201
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.strong, bold: true, children: item.title }),
|
|
1202
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: ` \u2014 ${item.description}` })
|
|
1088
1203
|
] }) })
|
|
1089
1204
|
] })
|
|
1090
1205
|
] }, item.tag)) }),
|
|
1091
|
-
/* @__PURE__ */
|
|
1092
|
-
/* @__PURE__ */ jsx7(
|
|
1206
|
+
/* @__PURE__ */ jsxs8(Box9, { marginTop: 1, flexDirection: "column", children: [
|
|
1207
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.danger, children: `\u256D${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256E` }),
|
|
1093
1208
|
/* @__PURE__ */ jsx7(NeverLine, { width: dividerWidth }),
|
|
1094
1209
|
/* @__PURE__ */ jsx7(
|
|
1095
1210
|
NeverLine,
|
|
@@ -1098,7 +1213,7 @@ function LearnMore() {
|
|
|
1098
1213
|
segments: [{ text: "I NEVER", color: COLORS.danger, bold: true }]
|
|
1099
1214
|
}
|
|
1100
1215
|
),
|
|
1101
|
-
neverItems.map((item) => /* @__PURE__ */
|
|
1216
|
+
neverItems.map((item) => /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
1102
1217
|
/* @__PURE__ */ jsx7(NeverLine, { width: dividerWidth }),
|
|
1103
1218
|
/* @__PURE__ */ jsx7(
|
|
1104
1219
|
NeverLine,
|
|
@@ -1113,23 +1228,23 @@ function LearnMore() {
|
|
|
1113
1228
|
)
|
|
1114
1229
|
] }, item)),
|
|
1115
1230
|
/* @__PURE__ */ jsx7(NeverLine, { width: dividerWidth }),
|
|
1116
|
-
/* @__PURE__ */ jsx7(
|
|
1231
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.danger, children: `\u2570${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256F` })
|
|
1117
1232
|
] }),
|
|
1118
|
-
/* @__PURE__ */ jsx7(
|
|
1119
|
-
/* @__PURE__ */ jsx7(
|
|
1120
|
-
/* @__PURE__ */ jsx7(
|
|
1233
|
+
/* @__PURE__ */ jsx7(Box9, { marginTop: 1, flexDirection: "column", children: policyLinks.map((link) => /* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", gap: 1, children: [
|
|
1234
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.strong, bold: true, children: `${link.label}:` }),
|
|
1235
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.accent, children: link.url })
|
|
1121
1236
|
] }, link.label)) }),
|
|
1122
|
-
/* @__PURE__ */
|
|
1123
|
-
/* @__PURE__ */
|
|
1124
|
-
/* @__PURE__ */ jsx7(
|
|
1125
|
-
/* @__PURE__ */ jsx7(
|
|
1126
|
-
/* @__PURE__ */ jsx7(
|
|
1237
|
+
/* @__PURE__ */ jsxs8(Box9, { marginTop: 1, flexDirection: "row", gap: 3, children: [
|
|
1238
|
+
/* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", gap: 1, children: [
|
|
1239
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: "[" }),
|
|
1240
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.primary, children: "esc" }),
|
|
1241
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: "] back" })
|
|
1127
1242
|
] }),
|
|
1128
|
-
/* @__PURE__ */
|
|
1129
|
-
/* @__PURE__ */ jsx7(
|
|
1130
|
-
/* @__PURE__ */ jsx7(
|
|
1131
|
-
/* @__PURE__ */ jsx7(
|
|
1132
|
-
/* @__PURE__ */ jsx7(
|
|
1243
|
+
/* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", gap: 1, children: [
|
|
1244
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: "[" }),
|
|
1245
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.primary, children: "enter" }),
|
|
1246
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: "]" }),
|
|
1247
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.success, bold: true, children: "start wizard" })
|
|
1133
1248
|
] })
|
|
1134
1249
|
] })
|
|
1135
1250
|
]
|
|
@@ -1138,10 +1253,10 @@ function LearnMore() {
|
|
|
1138
1253
|
}
|
|
1139
1254
|
|
|
1140
1255
|
// src/ui/Sidebar.tsx
|
|
1141
|
-
import { Box as
|
|
1256
|
+
import { Box as Box12, Text as Text12 } from "ink";
|
|
1142
1257
|
|
|
1143
1258
|
// src/ui/Steps.tsx
|
|
1144
|
-
import { Box as
|
|
1259
|
+
import { Box as Box10, Text as Text10 } from "ink";
|
|
1145
1260
|
import Spinner from "ink-spinner";
|
|
1146
1261
|
|
|
1147
1262
|
// src/core/persistence.ts
|
|
@@ -1170,11 +1285,11 @@ async function clearWorkflowState(workflowId) {
|
|
|
1170
1285
|
}
|
|
1171
1286
|
|
|
1172
1287
|
// src/ui/Steps.tsx
|
|
1173
|
-
import { jsx as jsx8, jsxs as
|
|
1288
|
+
import { jsx as jsx8, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1174
1289
|
function Steps() {
|
|
1175
1290
|
const { steps } = useWizard();
|
|
1176
1291
|
const visibleSteps = steps.filter(isStepVisible);
|
|
1177
|
-
return /* @__PURE__ */ jsx8(
|
|
1292
|
+
return /* @__PURE__ */ jsx8(Box10, { flexDirection: "column", gap: 1, children: visibleSteps.map((s) => /* @__PURE__ */ jsx8(Box10, { flexDirection: "column", children: /* @__PURE__ */ jsxs9(Text10, { color: COLORS.status[s.status], children: [
|
|
1178
1293
|
s.status === "running" ? /* @__PURE__ */ jsx8(Spinner, { type: "dots" }) : MARKER[s.status],
|
|
1179
1294
|
" ",
|
|
1180
1295
|
s.title
|
|
@@ -1184,7 +1299,7 @@ function CurrentStep() {
|
|
|
1184
1299
|
const { steps } = useWizard();
|
|
1185
1300
|
const currentStep = steps.filter(isStepVisible).find((s) => s.status === "running");
|
|
1186
1301
|
if (!currentStep) return null;
|
|
1187
|
-
return /* @__PURE__ */
|
|
1302
|
+
return /* @__PURE__ */ jsxs9(Text10, { color: COLORS.status.running, children: [
|
|
1188
1303
|
/* @__PURE__ */ jsx8(Spinner, { type: "dots" }),
|
|
1189
1304
|
" ",
|
|
1190
1305
|
` ${currentStep.title}`
|
|
@@ -1192,19 +1307,19 @@ function CurrentStep() {
|
|
|
1192
1307
|
}
|
|
1193
1308
|
|
|
1194
1309
|
// src/ui/Progress.tsx
|
|
1195
|
-
import { Box as
|
|
1196
|
-
import { jsx as jsx9, jsxs as
|
|
1310
|
+
import { Box as Box11, Text as Text11 } from "ink";
|
|
1311
|
+
import { jsx as jsx9, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1197
1312
|
function Progress() {
|
|
1198
1313
|
const { steps, currentStepIndex } = useWizard();
|
|
1199
1314
|
const visibleSteps = steps.filter(isStepVisible);
|
|
1200
1315
|
if (visibleSteps.length === 0) return null;
|
|
1201
1316
|
const visibleCountThroughCurrent = steps.slice(0, currentStepIndex + 1).filter(isStepVisible).length;
|
|
1202
1317
|
const activeStepNumber = Math.max(1, visibleCountThroughCurrent);
|
|
1203
|
-
return /* @__PURE__ */
|
|
1204
|
-
/* @__PURE__ */ jsx9(
|
|
1205
|
-
/* @__PURE__ */ jsx9(
|
|
1206
|
-
/* @__PURE__ */ jsx9(
|
|
1207
|
-
/* @__PURE__ */ jsx9(
|
|
1318
|
+
return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "row", gap: 1, children: [
|
|
1319
|
+
/* @__PURE__ */ jsx9(Text11, { color: COLORS.muted, children: "STEP" }),
|
|
1320
|
+
/* @__PURE__ */ jsx9(Text11, { bold: true, children: activeStepNumber }),
|
|
1321
|
+
/* @__PURE__ */ jsx9(Text11, { bold: true, children: "/" }),
|
|
1322
|
+
/* @__PURE__ */ jsx9(Text11, { bold: true, children: visibleSteps.length })
|
|
1208
1323
|
] });
|
|
1209
1324
|
}
|
|
1210
1325
|
|
|
@@ -1215,10 +1330,10 @@ var sidebarCommands = [
|
|
|
1215
1330
|
];
|
|
1216
1331
|
|
|
1217
1332
|
// src/ui/Sidebar.tsx
|
|
1218
|
-
import { jsx as jsx10, jsxs as
|
|
1333
|
+
import { jsx as jsx10, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1219
1334
|
function Sidebar() {
|
|
1220
|
-
return /* @__PURE__ */
|
|
1221
|
-
|
|
1335
|
+
return /* @__PURE__ */ jsxs11(
|
|
1336
|
+
Box12,
|
|
1222
1337
|
{
|
|
1223
1338
|
backgroundColor: "#14171E",
|
|
1224
1339
|
width: 30,
|
|
@@ -1227,16 +1342,16 @@ function Sidebar() {
|
|
|
1227
1342
|
flexDirection: "column",
|
|
1228
1343
|
justifyContent: "space-between",
|
|
1229
1344
|
children: [
|
|
1230
|
-
/* @__PURE__ */
|
|
1231
|
-
/* @__PURE__ */ jsx10(
|
|
1345
|
+
/* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", gap: 1, children: [
|
|
1346
|
+
/* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "PROGRESS" }),
|
|
1232
1347
|
/* @__PURE__ */ jsx10(Steps, {})
|
|
1233
1348
|
] }),
|
|
1234
|
-
/* @__PURE__ */
|
|
1349
|
+
/* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", gap: 1, children: [
|
|
1235
1350
|
/* @__PURE__ */ jsx10(Progress, {}),
|
|
1236
|
-
/* @__PURE__ */ jsx10(
|
|
1237
|
-
return /* @__PURE__ */
|
|
1238
|
-
/* @__PURE__ */ jsx10(
|
|
1239
|
-
/* @__PURE__ */ jsx10(
|
|
1351
|
+
/* @__PURE__ */ jsx10(Box12, { flexDirection: "column", children: sidebarCommands.map((c) => {
|
|
1352
|
+
return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, children: [
|
|
1353
|
+
/* @__PURE__ */ jsx10(Text12, { color: COLORS.primary, children: `[${c.keyHint}]` }),
|
|
1354
|
+
/* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: c.description })
|
|
1240
1355
|
] });
|
|
1241
1356
|
}) })
|
|
1242
1357
|
] })
|
|
@@ -1246,12 +1361,12 @@ function Sidebar() {
|
|
|
1246
1361
|
}
|
|
1247
1362
|
|
|
1248
1363
|
// src/ui/Ribbon.tsx
|
|
1249
|
-
import { Box as
|
|
1250
|
-
import { jsx as jsx11, jsxs as
|
|
1364
|
+
import { Box as Box13, Text as Text13 } from "ink";
|
|
1365
|
+
import { jsx as jsx11, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1251
1366
|
function Ribbon() {
|
|
1252
1367
|
const firstCommand = sidebarCommands[0];
|
|
1253
|
-
return /* @__PURE__ */
|
|
1254
|
-
|
|
1368
|
+
return /* @__PURE__ */ jsxs12(
|
|
1369
|
+
Box13,
|
|
1255
1370
|
{
|
|
1256
1371
|
backgroundColor: "#14171E",
|
|
1257
1372
|
flexDirection: "row",
|
|
@@ -1261,9 +1376,9 @@ function Ribbon() {
|
|
|
1261
1376
|
children: [
|
|
1262
1377
|
/* @__PURE__ */ jsx11(Progress, {}),
|
|
1263
1378
|
/* @__PURE__ */ jsx11(CurrentStep, {}),
|
|
1264
|
-
/* @__PURE__ */
|
|
1265
|
-
/* @__PURE__ */ jsx11(
|
|
1266
|
-
/* @__PURE__ */ jsx11(
|
|
1379
|
+
/* @__PURE__ */ jsxs12(Box13, { flexDirection: "row", gap: 1, children: [
|
|
1380
|
+
/* @__PURE__ */ jsx11(Text13, { color: COLORS.primary, children: `[${firstCommand.keyHint}]` }),
|
|
1381
|
+
/* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: firstCommand.description })
|
|
1267
1382
|
] })
|
|
1268
1383
|
]
|
|
1269
1384
|
}
|
|
@@ -1274,8 +1389,8 @@ function Ribbon() {
|
|
|
1274
1389
|
import { useState as useState6 } from "react";
|
|
1275
1390
|
|
|
1276
1391
|
// src/ui/Logs.tsx
|
|
1277
|
-
import { Box as
|
|
1278
|
-
import { jsx as jsx12, jsxs as
|
|
1392
|
+
import { Box as Box14, Text as Text14, useInput as useInput5 } from "ink";
|
|
1393
|
+
import { jsx as jsx12, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1279
1394
|
var KIND_COLOR = {
|
|
1280
1395
|
tool: COLORS.primary,
|
|
1281
1396
|
prompt: COLORS.badge
|
|
@@ -1311,8 +1426,8 @@ function Logs() {
|
|
|
1311
1426
|
else if (key.downArrow) scroll.scrollBy(1);
|
|
1312
1427
|
});
|
|
1313
1428
|
const visible = logs.slice(scroll.offset, scroll.offset + scroll.capacity);
|
|
1314
|
-
return /* @__PURE__ */
|
|
1315
|
-
logs.length === 0 && /* @__PURE__ */ jsx12(
|
|
1429
|
+
return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", paddingX: 4, paddingY: 2, flexGrow: 1, children: [
|
|
1430
|
+
logs.length === 0 && /* @__PURE__ */ jsx12(Text14, { color: COLORS.dim, children: "No logs yet." }),
|
|
1316
1431
|
/* @__PURE__ */ jsx12(ScrollView, { scroll, children: visible.map((entry) => {
|
|
1317
1432
|
const timestamp = `[${formatTimestamp(entry.startedAt)}]`;
|
|
1318
1433
|
const durationText = entry.kind === "tool" && entry.durationMs !== void 0 ? `${entry.durationMs}ms` : "";
|
|
@@ -1323,14 +1438,14 @@ function Logs() {
|
|
|
1323
1438
|
const name = truncate2(entry.name, budget);
|
|
1324
1439
|
budget -= name.length;
|
|
1325
1440
|
const preview = rawPreview ? truncate2(rawPreview, budget) : "";
|
|
1326
|
-
return /* @__PURE__ */
|
|
1327
|
-
/* @__PURE__ */ jsx12(
|
|
1328
|
-
/* @__PURE__ */ jsx12(
|
|
1329
|
-
preview && /* @__PURE__ */ jsx12(
|
|
1330
|
-
durationText && /* @__PURE__ */ jsx12(
|
|
1441
|
+
return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "row", gap: ROW_GAP, children: [
|
|
1442
|
+
/* @__PURE__ */ jsx12(Text14, { color: COLORS.dim, children: timestamp }),
|
|
1443
|
+
/* @__PURE__ */ jsx12(Text14, { color: logNameColor(entry), wrap: "truncate", children: name }),
|
|
1444
|
+
preview && /* @__PURE__ */ jsx12(Text14, { color: COLORS.dim, wrap: "truncate", children: preview }),
|
|
1445
|
+
durationText && /* @__PURE__ */ jsx12(Text14, { color: COLORS.dim, children: durationText })
|
|
1331
1446
|
] }, entry.id);
|
|
1332
1447
|
}) }),
|
|
1333
|
-
/* @__PURE__ */ jsx12(
|
|
1448
|
+
/* @__PURE__ */ jsx12(Text14, { color: COLORS.dim, children: "\u2191/\u2193 scroll" })
|
|
1334
1449
|
] });
|
|
1335
1450
|
}
|
|
1336
1451
|
|
|
@@ -1522,11 +1637,11 @@ function track(event, payload) {
|
|
|
1522
1637
|
}
|
|
1523
1638
|
|
|
1524
1639
|
// src/ui/App.tsx
|
|
1525
|
-
import { jsx as jsx13, jsxs as
|
|
1640
|
+
import { jsx as jsx13, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1526
1641
|
function App() {
|
|
1527
1642
|
const { phase, error, homeScreen, currentStepIndex, steps, inputReq } = useWizard();
|
|
1528
1643
|
const { exit } = useApp();
|
|
1529
|
-
const { columns, rows } =
|
|
1644
|
+
const { columns, rows } = useWindowSize8();
|
|
1530
1645
|
const [showLogs, setShowLogs] = useState6(false);
|
|
1531
1646
|
const finished = phase === "done" || phase === "error";
|
|
1532
1647
|
const currentStep = steps[currentStepIndex];
|
|
@@ -1539,7 +1654,7 @@ function App() {
|
|
|
1539
1654
|
{ isActive: finished }
|
|
1540
1655
|
);
|
|
1541
1656
|
useInput6((_input, key) => {
|
|
1542
|
-
if (phase === "idle" || phase === "
|
|
1657
|
+
if (phase === "idle" || phase === "authenticating") return;
|
|
1543
1658
|
if (key.tab) {
|
|
1544
1659
|
setShowLogs(!showLogs);
|
|
1545
1660
|
track("AI Wizard Interaction", {
|
|
@@ -1549,49 +1664,45 @@ function App() {
|
|
|
1549
1664
|
});
|
|
1550
1665
|
}
|
|
1551
1666
|
});
|
|
1552
|
-
const escOwnedElsewhere = phase === "idle" || phase === "awaitingInput" && inputReq?.promptType === "enterToContinue";
|
|
1667
|
+
const escOwnedElsewhere = phase === "idle" || phase === "authenticating" || phase === "awaitingInput" && inputReq?.promptType === "enterToContinue";
|
|
1553
1668
|
useInput6((_input, key) => {
|
|
1554
1669
|
if (escOwnedElsewhere) return;
|
|
1555
1670
|
if (key.escape) {
|
|
1556
1671
|
track("AI Wizard Interaction", {
|
|
1557
1672
|
context: "global",
|
|
1558
1673
|
key: "esc",
|
|
1559
|
-
// No step is active until `startWorkflow` — report the phase instead.
|
|
1560
1674
|
currentStep: currentStep?.id ?? phase
|
|
1561
1675
|
});
|
|
1562
1676
|
exit();
|
|
1563
1677
|
}
|
|
1564
1678
|
});
|
|
1565
|
-
const mainWindowVisible = phase === "running" || phase === "awaitingInput" || phase === "error" || phase === "done";
|
|
1679
|
+
const mainWindowVisible = phase === "authenticating" || phase === "preflight" || phase === "running" || phase === "awaitingInput" || phase === "error" || phase === "done";
|
|
1566
1680
|
const flexDirection = columns > 90 ? "row" : "column";
|
|
1567
1681
|
const showSidebar = flexDirection === "row";
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
against (see SelectPrompt). */
|
|
1593
|
-
/* @__PURE__ */ jsxs13(
|
|
1594
|
-
Box14,
|
|
1682
|
+
const scrollsPastViewport = phase === "idle" && homeScreen === "learnMore";
|
|
1683
|
+
return (
|
|
1684
|
+
/* Clamped to exactly the viewport: a taller frame makes Ink clear and repaint
|
|
1685
|
+
the whole screen, and the scrolling throws off its cursor arithmetic —
|
|
1686
|
+
flicker and leftover rows. */
|
|
1687
|
+
/* @__PURE__ */ jsxs14(
|
|
1688
|
+
Box15,
|
|
1689
|
+
{
|
|
1690
|
+
backgroundColor: COLORS.bg.main,
|
|
1691
|
+
flexDirection: "row",
|
|
1692
|
+
width: columns,
|
|
1693
|
+
height: scrollsPastViewport ? void 0 : rows,
|
|
1694
|
+
overflow: scrollsPastViewport ? "visible" : "hidden",
|
|
1695
|
+
children: [
|
|
1696
|
+
mainWindowVisible && /* @__PURE__ */ jsxs14(
|
|
1697
|
+
Box15,
|
|
1698
|
+
{
|
|
1699
|
+
flexDirection,
|
|
1700
|
+
width: "100%",
|
|
1701
|
+
maxHeight: rows,
|
|
1702
|
+
justifyContent: "space-between",
|
|
1703
|
+
children: [
|
|
1704
|
+
showLogs ? /* @__PURE__ */ jsx13(Logs, {}) : /* @__PURE__ */ jsxs14(
|
|
1705
|
+
Box15,
|
|
1595
1706
|
{
|
|
1596
1707
|
flexDirection: "column",
|
|
1597
1708
|
paddingX: 4,
|
|
@@ -1599,24 +1710,29 @@ function App() {
|
|
|
1599
1710
|
width: showSidebar ? 70 : "100%",
|
|
1600
1711
|
flexGrow: 1,
|
|
1601
1712
|
children: [
|
|
1713
|
+
phase === "authenticating" && /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", marginBottom: 1, children: [
|
|
1714
|
+
/* @__PURE__ */ jsx13(Text15, { color: COLORS.strong, bold: true, children: "Signing in to Algolia" }),
|
|
1715
|
+
/* @__PURE__ */ jsx13(Text15, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
|
|
1716
|
+
] }),
|
|
1717
|
+
/* @__PURE__ */ jsx13(CliOutput, {}),
|
|
1602
1718
|
/* @__PURE__ */ jsx13(Notices, {}),
|
|
1603
1719
|
/* @__PURE__ */ jsx13(PromptInput, {}),
|
|
1604
|
-
phase === "running" && showSidebar && /* @__PURE__ */ jsx13(
|
|
1605
|
-
phase === "error" && error && /* @__PURE__ */ jsx13(
|
|
1720
|
+
phase === "running" && showSidebar && /* @__PURE__ */ jsx13(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx13(CurrentStep, {}) }),
|
|
1721
|
+
phase === "error" && error && /* @__PURE__ */ jsx13(Box15, { marginTop: 1, children: /* @__PURE__ */ jsxs14(Text15, { color: COLORS.status.error, children: [
|
|
1606
1722
|
"\u2716 ",
|
|
1607
1723
|
error
|
|
1608
1724
|
] }) })
|
|
1609
1725
|
]
|
|
1610
1726
|
}
|
|
1611
|
-
)
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1727
|
+
),
|
|
1728
|
+
showSidebar ? /* @__PURE__ */ jsx13(Sidebar, {}) : /* @__PURE__ */ jsx13(Ribbon, {})
|
|
1729
|
+
]
|
|
1730
|
+
}
|
|
1731
|
+
),
|
|
1732
|
+
phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */ jsx13(LearnMore, {}) : /* @__PURE__ */ jsx13(Welcome, {}))
|
|
1733
|
+
]
|
|
1734
|
+
}
|
|
1735
|
+
)
|
|
1620
1736
|
);
|
|
1621
1737
|
}
|
|
1622
1738
|
|
|
@@ -1852,61 +1968,138 @@ async function runWorkflow(workflow, appId) {
|
|
|
1852
1968
|
}
|
|
1853
1969
|
}
|
|
1854
1970
|
|
|
1855
|
-
// src/lib/
|
|
1856
|
-
import {
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1971
|
+
// src/lib/algoliaApp.ts
|
|
1972
|
+
import { z as z4 } from "zod";
|
|
1973
|
+
var applicationSchema = z4.object({
|
|
1974
|
+
id: z4.string().min(1),
|
|
1975
|
+
name: z4.string().default(""),
|
|
1976
|
+
plan: z4.string().optional()
|
|
1977
|
+
});
|
|
1978
|
+
var listSchema = z4.array(
|
|
1979
|
+
z4.object({
|
|
1980
|
+
id: z4.string().min(1),
|
|
1981
|
+
name: z4.string().default(""),
|
|
1982
|
+
plan_label: z4.string().optional()
|
|
1983
|
+
}).transform(({ id, name, plan_label }) => ({ id, name, plan: plan_label }))
|
|
1984
|
+
);
|
|
1985
|
+
async function currentApplication() {
|
|
1986
|
+
let raw;
|
|
1868
1987
|
try {
|
|
1869
|
-
|
|
1988
|
+
raw = await runAlgoliaCli(["application", "current", "-o", "json"]);
|
|
1870
1989
|
} catch {
|
|
1871
|
-
return
|
|
1990
|
+
return null;
|
|
1991
|
+
}
|
|
1992
|
+
const parsed = applicationSchema.safeParse(parseJson(raw));
|
|
1993
|
+
return parsed.success ? parsed.data : null;
|
|
1994
|
+
}
|
|
1995
|
+
async function requireApplication() {
|
|
1996
|
+
const app = await currentApplication();
|
|
1997
|
+
if (!app) {
|
|
1998
|
+
throw new Error(
|
|
1999
|
+
"No Algolia application is selected. Run `npx @algolia/cli@latest application select` and restart the wizard."
|
|
2000
|
+
);
|
|
1872
2001
|
}
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
2002
|
+
return app;
|
|
2003
|
+
}
|
|
2004
|
+
async function listApplications() {
|
|
2005
|
+
const raw = await runAlgoliaCli(["application", "list", "-o", "json"]);
|
|
2006
|
+
const parsed = listSchema.safeParse(parseJson(raw));
|
|
2007
|
+
if (!parsed.success) {
|
|
2008
|
+
throw new Error("Could not read the list of Algolia applications.");
|
|
2009
|
+
}
|
|
2010
|
+
return parsed.data;
|
|
2011
|
+
}
|
|
2012
|
+
async function selectApplication(id) {
|
|
2013
|
+
const raw = await runAlgoliaCli(
|
|
2014
|
+
["application", "select", "--non-interactive", "--app-id", id],
|
|
2015
|
+
{ onOutput: stderrSink }
|
|
2016
|
+
);
|
|
2017
|
+
const parsed = applicationSchema.safeParse(parseJson(raw));
|
|
2018
|
+
if (!parsed.success) {
|
|
2019
|
+
throw new Error(
|
|
2020
|
+
`Selected application ${id}, but the Algolia CLI returned an unreadable result.`
|
|
2021
|
+
);
|
|
2022
|
+
}
|
|
2023
|
+
return parsed.data;
|
|
2024
|
+
}
|
|
2025
|
+
function parseJson(text) {
|
|
1886
2026
|
try {
|
|
1887
|
-
|
|
2027
|
+
return JSON.parse(text);
|
|
1888
2028
|
} catch {
|
|
1889
|
-
|
|
2029
|
+
return void 0;
|
|
1890
2030
|
}
|
|
1891
|
-
|
|
1892
|
-
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
// src/lib/algoliaAppPicker.ts
|
|
2034
|
+
function secondaryFor(app) {
|
|
2035
|
+
return app.plan ? { kind: "badge", value: app.plan } : void 0;
|
|
2036
|
+
}
|
|
2037
|
+
function labelFor(app) {
|
|
2038
|
+
return app.name.trim() ? `${app.name} \u2014 ${app.id}` : app.id;
|
|
2039
|
+
}
|
|
2040
|
+
function selectAndReport(app) {
|
|
2041
|
+
useWizard.getState().pushCliOutput(
|
|
2042
|
+
"stdout",
|
|
2043
|
+
`Selecting ${labelFor(app)} \u2014 provisioning its API key\u2026`
|
|
2044
|
+
);
|
|
2045
|
+
return selectApplication(app.id);
|
|
2046
|
+
}
|
|
2047
|
+
async function promptForApplication() {
|
|
2048
|
+
const store = useWizard.getState();
|
|
2049
|
+
const apps = await listApplications();
|
|
2050
|
+
if (apps.length === 0) {
|
|
1893
2051
|
throw new Error(
|
|
1894
|
-
"
|
|
2052
|
+
"This Algolia account has no applications. Create one in the Algolia dashboard, or with `npx @algolia/cli@latest application create`, then restart the wizard."
|
|
1895
2053
|
);
|
|
1896
2054
|
}
|
|
1897
|
-
|
|
2055
|
+
if (apps.length === 1) {
|
|
2056
|
+
const only = apps[0];
|
|
2057
|
+
logger.info(
|
|
2058
|
+
{ app: only.id },
|
|
2059
|
+
"single application on the account; selecting it"
|
|
2060
|
+
);
|
|
2061
|
+
return selectAndReport(only);
|
|
2062
|
+
}
|
|
2063
|
+
const messages = ["Which Algolia application should the wizard work in?"];
|
|
2064
|
+
for (; ; ) {
|
|
2065
|
+
const choice = await store.requestUserInput({
|
|
2066
|
+
prompt: "Select an application",
|
|
2067
|
+
promptType: "multipleChoice",
|
|
2068
|
+
options: apps.map(labelFor),
|
|
2069
|
+
secondary: apps.map(secondaryFor),
|
|
2070
|
+
messages
|
|
2071
|
+
});
|
|
2072
|
+
const chosen = apps.find((app) => labelFor(app) === choice);
|
|
2073
|
+
if (!chosen) {
|
|
2074
|
+
throw new Error("Application picker received an unexpected selection");
|
|
2075
|
+
}
|
|
2076
|
+
try {
|
|
2077
|
+
return await selectAndReport(chosen);
|
|
2078
|
+
} catch (err) {
|
|
2079
|
+
logger.warn(
|
|
2080
|
+
{ app: chosen.id, err: err.message },
|
|
2081
|
+
"application select failed; re-prompting"
|
|
2082
|
+
);
|
|
2083
|
+
messages.push(
|
|
2084
|
+
`Could not select \u201C${labelFor(chosen)}\u201D. It may have been removed \u2014 pick another.`
|
|
2085
|
+
);
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
async function ensureApplication() {
|
|
2090
|
+
return await currentApplication() ?? await promptForApplication();
|
|
1898
2091
|
}
|
|
1899
2092
|
|
|
1900
2093
|
// src/workflows/default.ts
|
|
1901
|
-
import { z as
|
|
2094
|
+
import { z as z27 } from "zod";
|
|
1902
2095
|
|
|
1903
2096
|
// src/actions/listIndices.ts
|
|
1904
|
-
import { z as
|
|
1905
|
-
var indicesListSchema =
|
|
1906
|
-
items:
|
|
1907
|
-
|
|
1908
|
-
name:
|
|
1909
|
-
entries:
|
|
2097
|
+
import { z as z5 } from "zod";
|
|
2098
|
+
var indicesListSchema = z5.object({
|
|
2099
|
+
items: z5.array(
|
|
2100
|
+
z5.object({
|
|
2101
|
+
name: z5.string(),
|
|
2102
|
+
entries: z5.number().default(0)
|
|
1910
2103
|
})
|
|
1911
2104
|
)
|
|
1912
2105
|
});
|
|
@@ -1977,12 +2170,12 @@ import "zod";
|
|
|
1977
2170
|
|
|
1978
2171
|
// src/lib/tools/listFiles.ts
|
|
1979
2172
|
import { tool } from "ai";
|
|
1980
|
-
import
|
|
2173
|
+
import z6 from "zod";
|
|
1981
2174
|
import { readdir } from "node:fs/promises";
|
|
1982
2175
|
|
|
1983
2176
|
// src/lib/tools/path.ts
|
|
1984
2177
|
import { lstat } from "node:fs/promises";
|
|
1985
|
-
import { resolve as resolve2, relative, isAbsolute, dirname as dirname3, join as
|
|
2178
|
+
import { resolve as resolve2, relative, isAbsolute, dirname as dirname3, join as join6, sep } from "node:path";
|
|
1986
2179
|
function resolveInRoot(ctx, path) {
|
|
1987
2180
|
const target = resolve2(ctx.cwd, path);
|
|
1988
2181
|
const rel = relative(ctx.root, target);
|
|
@@ -1998,7 +2191,7 @@ async function hasSymlinkParent(ctx, target) {
|
|
|
1998
2191
|
let current = ctx.root;
|
|
1999
2192
|
const parts = relative(ctx.root, dirname3(target)).split(sep).filter(Boolean);
|
|
2000
2193
|
for (const part of parts) {
|
|
2001
|
-
current =
|
|
2194
|
+
current = join6(current, part);
|
|
2002
2195
|
try {
|
|
2003
2196
|
if ((await lstat(current)).isSymbolicLink()) return true;
|
|
2004
2197
|
} catch (err) {
|
|
@@ -2013,7 +2206,7 @@ async function hasSymlinkParent(ctx, target) {
|
|
|
2013
2206
|
function listFilesTool(ctx) {
|
|
2014
2207
|
return tool({
|
|
2015
2208
|
description: "List files in the current working directory",
|
|
2016
|
-
inputSchema:
|
|
2209
|
+
inputSchema: z6.object(),
|
|
2017
2210
|
execute: async () => {
|
|
2018
2211
|
logger.info("called listFiles tool");
|
|
2019
2212
|
if (++ctx.counts.list > ctx.limits.list) {
|
|
@@ -2029,13 +2222,13 @@ function listFilesTool(ctx) {
|
|
|
2029
2222
|
|
|
2030
2223
|
// src/lib/tools/changeDirectory.ts
|
|
2031
2224
|
import { tool as tool2 } from "ai";
|
|
2032
|
-
import
|
|
2225
|
+
import z7 from "zod";
|
|
2033
2226
|
import { stat } from "node:fs/promises";
|
|
2034
2227
|
function changeDirectoryTool(ctx) {
|
|
2035
2228
|
return tool2({
|
|
2036
2229
|
description: "Change the current working directory. Subsequent file operations resolve relative to it. Returns the new working directory.",
|
|
2037
|
-
inputSchema:
|
|
2038
|
-
path:
|
|
2230
|
+
inputSchema: z7.object({
|
|
2231
|
+
path: z7.string().describe("Directory to change into")
|
|
2039
2232
|
}),
|
|
2040
2233
|
execute: async ({ path }) => {
|
|
2041
2234
|
logger.info({ path }, "called changeDirectory tool");
|
|
@@ -2057,13 +2250,13 @@ function changeDirectoryTool(ctx) {
|
|
|
2057
2250
|
|
|
2058
2251
|
// src/lib/tools/reportStatus.ts
|
|
2059
2252
|
import { tool as tool3 } from "ai";
|
|
2060
|
-
import
|
|
2253
|
+
import z8 from "zod";
|
|
2061
2254
|
function reportStatusTool(output) {
|
|
2062
2255
|
return tool3({
|
|
2063
2256
|
description: "Report the status of your execution. Return a reason in case of failure.",
|
|
2064
|
-
inputSchema:
|
|
2065
|
-
status:
|
|
2066
|
-
reason:
|
|
2257
|
+
inputSchema: z8.object({
|
|
2258
|
+
status: z8.enum(["success", "fail"]),
|
|
2259
|
+
reason: z8.string().optional(),
|
|
2067
2260
|
output
|
|
2068
2261
|
}),
|
|
2069
2262
|
execute: async ({ status, reason, output: output2 }) => {
|
|
@@ -2075,8 +2268,8 @@ function reportStatusTool(output) {
|
|
|
2075
2268
|
|
|
2076
2269
|
// src/lib/tools/readFile.ts
|
|
2077
2270
|
import { tool as tool4 } from "ai";
|
|
2078
|
-
import
|
|
2079
|
-
import { readFile as
|
|
2271
|
+
import z9 from "zod";
|
|
2272
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
2080
2273
|
|
|
2081
2274
|
// src/lib/tools/env.ts
|
|
2082
2275
|
import { basename } from "node:path";
|
|
@@ -2103,8 +2296,8 @@ function redactEnvValues(content) {
|
|
|
2103
2296
|
function readFileTool(ctx) {
|
|
2104
2297
|
return tool4({
|
|
2105
2298
|
description: "Read the contents of a file at the given path",
|
|
2106
|
-
inputSchema:
|
|
2107
|
-
filePath:
|
|
2299
|
+
inputSchema: z9.object({
|
|
2300
|
+
filePath: z9.string().describe("Path to the file to read")
|
|
2108
2301
|
}),
|
|
2109
2302
|
execute: async ({ filePath }) => {
|
|
2110
2303
|
if (++ctx.counts.read > ctx.limits.read) {
|
|
@@ -2114,7 +2307,7 @@ function readFileTool(ctx) {
|
|
|
2114
2307
|
const resolved = resolveInRoot(ctx, filePath);
|
|
2115
2308
|
if (!resolved.ok) return resolved.error;
|
|
2116
2309
|
try {
|
|
2117
|
-
const content = await
|
|
2310
|
+
const content = await readFile3(resolved.target, "utf8");
|
|
2118
2311
|
return isEnvFile(resolved.target) ? redactEnvValues(content) : content;
|
|
2119
2312
|
} catch (err) {
|
|
2120
2313
|
return `Error reading ${filePath}: ${err.message}`;
|
|
@@ -2125,15 +2318,15 @@ function readFileTool(ctx) {
|
|
|
2125
2318
|
|
|
2126
2319
|
// src/lib/tools/writeFile.ts
|
|
2127
2320
|
import { tool as tool5 } from "ai";
|
|
2128
|
-
import
|
|
2321
|
+
import z10 from "zod";
|
|
2129
2322
|
import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
|
|
2130
2323
|
import { dirname as dirname4 } from "node:path";
|
|
2131
2324
|
function writeFileTool(ctx) {
|
|
2132
2325
|
return tool5({
|
|
2133
2326
|
description: "Write content to a file at the given path, overwriting it. To set Algolia credentials in an env file, use writeCredentials instead of this tool.",
|
|
2134
|
-
inputSchema:
|
|
2135
|
-
filePath:
|
|
2136
|
-
content:
|
|
2327
|
+
inputSchema: z10.object({
|
|
2328
|
+
filePath: z10.string().describe("Path to the file to write"),
|
|
2329
|
+
content: z10.string().describe("Content to write to the file")
|
|
2137
2330
|
}),
|
|
2138
2331
|
execute: async ({ filePath, content }) => {
|
|
2139
2332
|
logger.info({ filePath }, "called writeFile tool");
|
|
@@ -2158,9 +2351,95 @@ function writeFileTool(ctx) {
|
|
|
2158
2351
|
|
|
2159
2352
|
// src/lib/tools/writeAlgoliaCredentials.ts
|
|
2160
2353
|
import { tool as tool6 } from "ai";
|
|
2161
|
-
import
|
|
2162
|
-
import { mkdir as mkdir4, readFile as
|
|
2354
|
+
import z12 from "zod";
|
|
2355
|
+
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
|
|
2163
2356
|
import { dirname as dirname5 } from "node:path";
|
|
2357
|
+
|
|
2358
|
+
// src/lib/algoliaApiKey.ts
|
|
2359
|
+
import { z as z11 } from "zod";
|
|
2360
|
+
var SAFE_ACLS = /* @__PURE__ */ new Set(["search", "browse", "listIndexes"]);
|
|
2361
|
+
var WRITE_ACLS = [
|
|
2362
|
+
"addObject",
|
|
2363
|
+
"deleteObject",
|
|
2364
|
+
"settings",
|
|
2365
|
+
"editSettings",
|
|
2366
|
+
"listIndexes"
|
|
2367
|
+
];
|
|
2368
|
+
var WRITE_ACL_SET = new Set(WRITE_ACLS);
|
|
2369
|
+
var apiKeySchema = z11.object({
|
|
2370
|
+
value: z11.string().min(1),
|
|
2371
|
+
acl: z11.array(z11.string()).default([]),
|
|
2372
|
+
indexes: z11.array(z11.string()).default([])
|
|
2373
|
+
});
|
|
2374
|
+
var apiKeyListSchema = z11.object({
|
|
2375
|
+
items: z11.array(apiKeySchema).optional(),
|
|
2376
|
+
keys: z11.array(apiKeySchema).optional()
|
|
2377
|
+
}).transform((o) => o.items ?? o.keys ?? []);
|
|
2378
|
+
var createdKeySchema = z11.object({
|
|
2379
|
+
key: z11.string().min(1).optional(),
|
|
2380
|
+
value: z11.string().min(1).optional()
|
|
2381
|
+
});
|
|
2382
|
+
function canReuse(key, index) {
|
|
2383
|
+
return key.acl.includes("search") && key.acl.every((acl) => SAFE_ACLS.has(acl)) && (key.indexes.length === 0 || key.indexes.includes("*") || key.indexes.includes(index));
|
|
2384
|
+
}
|
|
2385
|
+
async function createSearchKey(index) {
|
|
2386
|
+
const stdout = await runAlgoliaCli([
|
|
2387
|
+
"apikeys",
|
|
2388
|
+
"create",
|
|
2389
|
+
"--indices",
|
|
2390
|
+
index,
|
|
2391
|
+
"--acl",
|
|
2392
|
+
"search,browse",
|
|
2393
|
+
"--description",
|
|
2394
|
+
`wizard search-only key for ${index}`,
|
|
2395
|
+
"-o",
|
|
2396
|
+
"json"
|
|
2397
|
+
]);
|
|
2398
|
+
const { key, value } = createdKeySchema.parse(JSON.parse(stdout));
|
|
2399
|
+
const created = key ?? value;
|
|
2400
|
+
if (!created) throw new Error("apikeys create returned no key value");
|
|
2401
|
+
return created;
|
|
2402
|
+
}
|
|
2403
|
+
function canReuseForWrites(key, index) {
|
|
2404
|
+
return WRITE_ACLS.every((acl) => key.acl.includes(acl)) && key.acl.every((acl) => WRITE_ACL_SET.has(acl)) && key.indexes.includes(index);
|
|
2405
|
+
}
|
|
2406
|
+
async function resolveWriteKey(index) {
|
|
2407
|
+
const stdout = await runAlgoliaCli(["apikeys", "list", "-o", "json"]);
|
|
2408
|
+
const existing = apiKeyListSchema.parse(JSON.parse(stdout)).find((key2) => canReuseForWrites(key2, index))?.value;
|
|
2409
|
+
if (existing) {
|
|
2410
|
+
logger.info({ index }, "reusing existing write API key");
|
|
2411
|
+
return existing;
|
|
2412
|
+
}
|
|
2413
|
+
logger.info({ index }, "no reusable write key found; creating one");
|
|
2414
|
+
const created = await runAlgoliaCli([
|
|
2415
|
+
"apikeys",
|
|
2416
|
+
"create",
|
|
2417
|
+
"--indices",
|
|
2418
|
+
index,
|
|
2419
|
+
"--acl",
|
|
2420
|
+
WRITE_ACLS.join(","),
|
|
2421
|
+
"--description",
|
|
2422
|
+
`wizard write key for ${index}`,
|
|
2423
|
+
"-o",
|
|
2424
|
+
"json"
|
|
2425
|
+
]);
|
|
2426
|
+
const { key, value } = createdKeySchema.parse(JSON.parse(created));
|
|
2427
|
+
const writeKey = key ?? value;
|
|
2428
|
+
if (!writeKey) throw new Error("apikeys create returned no key value");
|
|
2429
|
+
return writeKey;
|
|
2430
|
+
}
|
|
2431
|
+
async function resolveSearchOnlyKey(index) {
|
|
2432
|
+
const stdout = await runAlgoliaCli(["apikeys", "list", "-o", "json"]);
|
|
2433
|
+
const existing = apiKeyListSchema.parse(JSON.parse(stdout)).find((key) => canReuse(key, index))?.value;
|
|
2434
|
+
if (existing) {
|
|
2435
|
+
logger.info({ index }, "reusing existing search-only API key");
|
|
2436
|
+
return existing;
|
|
2437
|
+
}
|
|
2438
|
+
logger.info({ index }, "no reusable search-only key found; creating one");
|
|
2439
|
+
return createSearchKey(index);
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
// src/lib/tools/writeAlgoliaCredentials.ts
|
|
2164
2443
|
var APP_ID_VAR = "ALGOLIA_APPLICATION_ID";
|
|
2165
2444
|
var API_KEY_VAR = "ALGOLIA_WRITE_API_KEY";
|
|
2166
2445
|
function appendEnv(content, entries) {
|
|
@@ -2174,9 +2453,9 @@ function hasEnv(content, name) {
|
|
|
2174
2453
|
}
|
|
2175
2454
|
function writeCredentialsTool(ctx) {
|
|
2176
2455
|
return tool6({
|
|
2177
|
-
description: `Write the active Algolia credentials (${APP_ID_VAR} and ${API_KEY_VAR}) into the given env file. The credentials
|
|
2178
|
-
inputSchema:
|
|
2179
|
-
filePath:
|
|
2456
|
+
description: `Write the active Algolia credentials (${APP_ID_VAR} and ${API_KEY_VAR}) into the given env file. The credentials come from the selected Algolia application, with a write key scoped to the target index; you only pass the path to the env file (e.g. ".env"). If the file already defines ${APP_ID_VAR} or ${API_KEY_VAR}, the write is skipped and existing values are left untouched.`,
|
|
2457
|
+
inputSchema: z12.object({
|
|
2458
|
+
filePath: z12.string().describe(
|
|
2180
2459
|
'Path to the env file to write credentials into (e.g. ".env")'
|
|
2181
2460
|
)
|
|
2182
2461
|
}),
|
|
@@ -2184,11 +2463,17 @@ function writeCredentialsTool(ctx) {
|
|
|
2184
2463
|
logger.info({ filePath }, "called writeCredentials tool");
|
|
2185
2464
|
const resolved = resolveInRoot(ctx, filePath);
|
|
2186
2465
|
if (resolved.ok === false) return resolved.error;
|
|
2187
|
-
|
|
2466
|
+
const targetIndex = useWizard.getState().targetIndex;
|
|
2467
|
+
if (!targetIndex) {
|
|
2468
|
+
return "Error: no target index is set for this run, so a scoped write key cannot be provisioned.";
|
|
2469
|
+
}
|
|
2470
|
+
let appId;
|
|
2471
|
+
let writeKey;
|
|
2188
2472
|
try {
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2473
|
+
appId = (await requireApplication()).id;
|
|
2474
|
+
writeKey = await resolveWriteKey(targetIndex);
|
|
2475
|
+
} catch (err) {
|
|
2476
|
+
return `Error: could not resolve Algolia credentials (${err.message}). Ask the user to authenticate with the Algolia CLI first.`;
|
|
2192
2477
|
}
|
|
2193
2478
|
try {
|
|
2194
2479
|
if (await hasSymlinkParent(ctx, resolved.target)) {
|
|
@@ -2196,7 +2481,7 @@ function writeCredentialsTool(ctx) {
|
|
|
2196
2481
|
}
|
|
2197
2482
|
let existing = "";
|
|
2198
2483
|
try {
|
|
2199
|
-
existing = await
|
|
2484
|
+
existing = await readFile4(resolved.target, "utf8");
|
|
2200
2485
|
} catch (err) {
|
|
2201
2486
|
if (err.code !== "ENOENT") throw err;
|
|
2202
2487
|
}
|
|
@@ -2207,8 +2492,8 @@ function writeCredentialsTool(ctx) {
|
|
|
2207
2492
|
return `Skipped: ${filePath} already defines ${present.join(" and ")}. Leaving existing credentials untouched.`;
|
|
2208
2493
|
}
|
|
2209
2494
|
const envWithCredentials = appendEnv(existing, [
|
|
2210
|
-
[APP_ID_VAR,
|
|
2211
|
-
[API_KEY_VAR,
|
|
2495
|
+
[APP_ID_VAR, appId],
|
|
2496
|
+
[API_KEY_VAR, writeKey]
|
|
2212
2497
|
]);
|
|
2213
2498
|
await mkdir4(dirname5(resolved.target), { recursive: true });
|
|
2214
2499
|
await writeFile4(resolved.target, envWithCredentials, "utf8");
|
|
@@ -2222,16 +2507,16 @@ function writeCredentialsTool(ctx) {
|
|
|
2222
2507
|
|
|
2223
2508
|
// src/lib/tools/searchFiles.ts
|
|
2224
2509
|
import { tool as tool7 } from "ai";
|
|
2225
|
-
import
|
|
2226
|
-
import { readdir as readdir2, readFile as
|
|
2227
|
-
import { join as
|
|
2510
|
+
import z13 from "zod";
|
|
2511
|
+
import { readdir as readdir2, readFile as readFile5 } from "node:fs/promises";
|
|
2512
|
+
import { join as join7 } from "node:path";
|
|
2228
2513
|
var MAX_QUERY_LENGTH = 1e3;
|
|
2229
2514
|
async function walkFiles(dir) {
|
|
2230
2515
|
const skip = /* @__PURE__ */ new Set(["node_modules", ".git", "dist"]);
|
|
2231
2516
|
const out = [];
|
|
2232
2517
|
for (const e of await readdir2(dir, { withFileTypes: true })) {
|
|
2233
2518
|
if (e.name.startsWith(".") || skip.has(e.name)) continue;
|
|
2234
|
-
const full =
|
|
2519
|
+
const full = join7(dir, e.name);
|
|
2235
2520
|
if (e.isDirectory()) out.push(...await walkFiles(full));
|
|
2236
2521
|
else if (e.isFile()) out.push(full);
|
|
2237
2522
|
}
|
|
@@ -2240,9 +2525,9 @@ async function walkFiles(dir) {
|
|
|
2240
2525
|
function searchFilesTool(ctx) {
|
|
2241
2526
|
return tool7({
|
|
2242
2527
|
description: "Search file contents for a JavaScript regular expression (RegExp syntax, not grep/PCRE). Returns matching lines as file:line:text.",
|
|
2243
|
-
inputSchema:
|
|
2244
|
-
query:
|
|
2245
|
-
path:
|
|
2528
|
+
inputSchema: z13.object({
|
|
2529
|
+
query: z13.string().describe("JavaScript RegExp pattern to search for"),
|
|
2530
|
+
path: z13.string().optional().describe("Directory to search in (default: cwd)")
|
|
2246
2531
|
}),
|
|
2247
2532
|
execute: async ({ query, path = "." }) => {
|
|
2248
2533
|
logger.info({ query, path }, "called searchFiles tool");
|
|
@@ -2264,7 +2549,7 @@ function searchFilesTool(ctx) {
|
|
|
2264
2549
|
for (const file of await walkFiles(resolved.target)) {
|
|
2265
2550
|
let content;
|
|
2266
2551
|
try {
|
|
2267
|
-
content = await
|
|
2552
|
+
content = await readFile5(file, "utf8");
|
|
2268
2553
|
} catch {
|
|
2269
2554
|
continue;
|
|
2270
2555
|
}
|
|
@@ -2286,7 +2571,7 @@ function searchFilesTool(ctx) {
|
|
|
2286
2571
|
|
|
2287
2572
|
// src/lib/tools/verifyImplementation.ts
|
|
2288
2573
|
import { tool as tool8 } from "ai";
|
|
2289
|
-
import
|
|
2574
|
+
import z14 from "zod";
|
|
2290
2575
|
|
|
2291
2576
|
// src/lib/tools/utils/runCommand.ts
|
|
2292
2577
|
import { spawn as spawn2 } from "node:child_process";
|
|
@@ -2308,9 +2593,9 @@ function runCommand(command, args, cwd) {
|
|
|
2308
2593
|
}
|
|
2309
2594
|
|
|
2310
2595
|
// src/lib/tools/utils/packageManager.ts
|
|
2311
|
-
import { readFile as
|
|
2596
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
2312
2597
|
import { existsSync } from "node:fs";
|
|
2313
|
-
import { join as
|
|
2598
|
+
import { join as join8 } from "node:path";
|
|
2314
2599
|
var LOCKFILES = [
|
|
2315
2600
|
["pnpm-lock.yaml", "pnpm"],
|
|
2316
2601
|
["yarn.lock", "yarn"],
|
|
@@ -2319,13 +2604,13 @@ var LOCKFILES = [
|
|
|
2319
2604
|
["package-lock.json", "npm"]
|
|
2320
2605
|
];
|
|
2321
2606
|
async function readPackageJson(cwd = process.cwd()) {
|
|
2322
|
-
return JSON.parse(await
|
|
2607
|
+
return JSON.parse(await readFile6(join8(cwd, "package.json"), "utf8"));
|
|
2323
2608
|
}
|
|
2324
2609
|
function packageManagerFrom(pkg) {
|
|
2325
2610
|
return pkg.packageManager?.split("@")[0] ?? "npm";
|
|
2326
2611
|
}
|
|
2327
2612
|
function packageManagerFromLockfile(cwd) {
|
|
2328
|
-
return LOCKFILES.find(([file]) => existsSync(
|
|
2613
|
+
return LOCKFILES.find(([file]) => existsSync(join8(cwd, file)))?.[1];
|
|
2329
2614
|
}
|
|
2330
2615
|
async function detectPackageManager(cwd) {
|
|
2331
2616
|
try {
|
|
@@ -2366,7 +2651,7 @@ async function runRepoVerificationCheck() {
|
|
|
2366
2651
|
function verifyImplementationTool() {
|
|
2367
2652
|
return tool8({
|
|
2368
2653
|
description: "Run the repo's mechanical verification check for generated implementation changes. Detects lint/typecheck/check from package.json and returns structured pass/fail evidence for the verifier to interpret.",
|
|
2369
|
-
inputSchema:
|
|
2654
|
+
inputSchema: z14.object(),
|
|
2370
2655
|
execute: async () => {
|
|
2371
2656
|
logger.info("called verifyImplementation tool");
|
|
2372
2657
|
return runRepoVerificationCheck();
|
|
@@ -2380,7 +2665,7 @@ import { createAnthropic } from "@ai-sdk/anthropic";
|
|
|
2380
2665
|
import { nanoid as nanoid2 } from "nanoid";
|
|
2381
2666
|
import { mkdir as mkdir5, writeFile as writeFile5 } from "node:fs/promises";
|
|
2382
2667
|
import { dirname as dirname6 } from "node:path";
|
|
2383
|
-
import
|
|
2668
|
+
import z15 from "zod";
|
|
2384
2669
|
var DATA_DIR = ".algolia-wizard/data";
|
|
2385
2670
|
var RECORD_MODEL = "claude-haiku-4-5";
|
|
2386
2671
|
var MAX_RECORDS = 100;
|
|
@@ -2392,17 +2677,17 @@ var anthropic = createAnthropic({
|
|
|
2392
2677
|
function generateRecordTool(ctx) {
|
|
2393
2678
|
return tool9({
|
|
2394
2679
|
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.",
|
|
2395
|
-
inputSchema:
|
|
2396
|
-
entityName:
|
|
2397
|
-
attributes:
|
|
2398
|
-
count:
|
|
2399
|
-
hint:
|
|
2680
|
+
inputSchema: z15.object({
|
|
2681
|
+
entityName: z15.string().describe("Name of the entity to generate records for."),
|
|
2682
|
+
attributes: z15.array(z15.string()).describe("Attribute names each record must contain."),
|
|
2683
|
+
count: z15.number().int().min(1).max(MAX_RECORDS).default(10).describe(`How many records to generate (max ${MAX_RECORDS}).`),
|
|
2684
|
+
hint: z15.string().optional().describe("Optional context to steer realistic values.")
|
|
2400
2685
|
}),
|
|
2401
2686
|
execute: async ({ entityName, attributes, count, hint }) => {
|
|
2402
2687
|
logger.info({ entityName, count }, "called generateRecord tool");
|
|
2403
2688
|
try {
|
|
2404
|
-
const value =
|
|
2405
|
-
const recordSchema =
|
|
2689
|
+
const value = z15.union([z15.string(), z15.number(), z15.boolean(), z15.null()]);
|
|
2690
|
+
const recordSchema = z15.object(
|
|
2406
2691
|
Object.fromEntries(attributes.map((attr) => [attr, value]))
|
|
2407
2692
|
);
|
|
2408
2693
|
const generateBatch = async (batchCount) => {
|
|
@@ -2412,8 +2697,8 @@ function generateRecordTool(ctx) {
|
|
|
2412
2697
|
const { output } = await generateText({
|
|
2413
2698
|
model: anthropic(RECORD_MODEL),
|
|
2414
2699
|
output: Output.object({
|
|
2415
|
-
schema:
|
|
2416
|
-
records:
|
|
2700
|
+
schema: z15.object({
|
|
2701
|
+
records: z15.array(recordSchema).length(batchCount)
|
|
2417
2702
|
})
|
|
2418
2703
|
}),
|
|
2419
2704
|
prompt: [
|
|
@@ -2471,12 +2756,12 @@ function generateRecordTool(ctx) {
|
|
|
2471
2756
|
|
|
2472
2757
|
// src/lib/tools/notifyUser.ts
|
|
2473
2758
|
import { tool as tool10 } from "ai";
|
|
2474
|
-
import
|
|
2759
|
+
import z16 from "zod";
|
|
2475
2760
|
function notifyUserTool() {
|
|
2476
2761
|
return tool10({
|
|
2477
2762
|
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.`,
|
|
2478
|
-
inputSchema:
|
|
2479
|
-
message:
|
|
2763
|
+
inputSchema: z16.object({
|
|
2764
|
+
message: z16.string().describe(
|
|
2480
2765
|
"Short, plain-language description of what you are doing now."
|
|
2481
2766
|
)
|
|
2482
2767
|
}),
|
|
@@ -2656,10 +2941,10 @@ async function runAgent(req) {
|
|
|
2656
2941
|
}
|
|
2657
2942
|
|
|
2658
2943
|
// src/actions/detectLanguage.ts
|
|
2659
|
-
import
|
|
2660
|
-
var detectLanguageSchema =
|
|
2661
|
-
languages:
|
|
2662
|
-
frameworks:
|
|
2944
|
+
import z19 from "zod";
|
|
2945
|
+
var detectLanguageSchema = z19.object({
|
|
2946
|
+
languages: z19.array(z19.object({ name: z19.string(), version: z19.string() })),
|
|
2947
|
+
frameworks: z19.array(z19.object({ name: z19.string(), version: z19.string() }))
|
|
2663
2948
|
});
|
|
2664
2949
|
var detectLanguage = () => runAgent({
|
|
2665
2950
|
instructions: [
|
|
@@ -2677,31 +2962,31 @@ var detectLanguage = () => runAgent({
|
|
|
2677
2962
|
});
|
|
2678
2963
|
|
|
2679
2964
|
// src/actions/analyzeCodebase.ts
|
|
2680
|
-
import
|
|
2965
|
+
import z20 from "zod";
|
|
2681
2966
|
var READONLY_TOOLS = [
|
|
2682
2967
|
"listFiles",
|
|
2683
2968
|
"changeDirectory",
|
|
2684
2969
|
"readFile",
|
|
2685
2970
|
"searchFiles"
|
|
2686
2971
|
];
|
|
2687
|
-
var ingestionAnalysisSchema =
|
|
2688
|
-
ingestionAnalysis:
|
|
2689
|
-
|
|
2690
|
-
name:
|
|
2691
|
-
paths:
|
|
2972
|
+
var ingestionAnalysisSchema = z20.object({
|
|
2973
|
+
ingestionAnalysis: z20.array(
|
|
2974
|
+
z20.object({
|
|
2975
|
+
name: z20.string(),
|
|
2976
|
+
paths: z20.array(z20.string()),
|
|
2692
2977
|
// indexable fields the agent found for this entity
|
|
2693
|
-
attributes:
|
|
2978
|
+
attributes: z20.array(z20.string())
|
|
2694
2979
|
})
|
|
2695
2980
|
)
|
|
2696
2981
|
});
|
|
2697
|
-
var searchImplementationAnalysisSchema =
|
|
2698
|
-
searchImplementationAnalysis:
|
|
2982
|
+
var searchImplementationAnalysisSchema = z20.object({
|
|
2983
|
+
searchImplementationAnalysis: z20.string()
|
|
2699
2984
|
});
|
|
2700
|
-
var verificationSchema =
|
|
2701
|
-
verification:
|
|
2985
|
+
var verificationSchema = z20.object({
|
|
2986
|
+
verification: z20.array(z20.string())
|
|
2702
2987
|
});
|
|
2703
2988
|
var confirmedEntitiesFieldSchema = ingestionAnalysisSchema.shape.ingestionAnalysis.optional();
|
|
2704
|
-
var analyzeCodebaseSchema =
|
|
2989
|
+
var analyzeCodebaseSchema = z20.object({
|
|
2705
2990
|
ingestionAnalysis: ingestionAnalysisSchema.shape.ingestionAnalysis.optional(),
|
|
2706
2991
|
searchImplementationAnalysis: searchImplementationAnalysisSchema.shape.searchImplementationAnalysis.optional(),
|
|
2707
2992
|
verification: verificationSchema.shape.verification.optional(),
|
|
@@ -2763,7 +3048,7 @@ async function runAnalysis(mode, extraInstructions = []) {
|
|
|
2763
3048
|
// package.json
|
|
2764
3049
|
var package_default = {
|
|
2765
3050
|
name: "@algolia/wizard",
|
|
2766
|
-
version: "0.9.0-rc.
|
|
3051
|
+
version: "0.9.0-rc.85.78",
|
|
2767
3052
|
description: "Magically implement Algolia functionality in your codebase",
|
|
2768
3053
|
type: "module",
|
|
2769
3054
|
engines: {
|
|
@@ -2811,7 +3096,6 @@ var package_default = {
|
|
|
2811
3096
|
dependencies: {
|
|
2812
3097
|
"@ai-sdk/anthropic": "^3.0.81",
|
|
2813
3098
|
"@ai-sdk/openai-compatible": "^2.0.47",
|
|
2814
|
-
"@algolia/cli": "^5.11.0",
|
|
2815
3099
|
"@hono/node-server": "^2.0.10",
|
|
2816
3100
|
"@segment/analytics-node": "^3.1.0",
|
|
2817
3101
|
ai: "^6.0.190",
|
|
@@ -2825,7 +3109,6 @@ var package_default = {
|
|
|
2825
3109
|
nanoid: "^5.1.15",
|
|
2826
3110
|
pino: "^10.3.1",
|
|
2827
3111
|
react: "^19.2.7",
|
|
2828
|
-
toml: "^4.1.1",
|
|
2829
3112
|
varlock: "^1.5.1",
|
|
2830
3113
|
zod: "^4.4.3",
|
|
2831
3114
|
zustand: "^5.0.14"
|
|
@@ -2883,8 +3166,8 @@ async function askList(ctx, prompt, { required = false } = {}) {
|
|
|
2883
3166
|
}
|
|
2884
3167
|
|
|
2885
3168
|
// src/actions/confirmLanguage.ts
|
|
2886
|
-
import
|
|
2887
|
-
var confirmLanguageSchema =
|
|
3169
|
+
import z22 from "zod";
|
|
3170
|
+
var confirmLanguageSchema = z22.object({
|
|
2888
3171
|
languages: detectLanguageSchema.shape.languages
|
|
2889
3172
|
});
|
|
2890
3173
|
async function confirmLanguage(ctx) {
|
|
@@ -2905,8 +3188,8 @@ async function confirmLanguage(ctx) {
|
|
|
2905
3188
|
}
|
|
2906
3189
|
|
|
2907
3190
|
// src/actions/confirmFramework.ts
|
|
2908
|
-
import
|
|
2909
|
-
var confirmFrameworkSchema =
|
|
3191
|
+
import z23 from "zod";
|
|
3192
|
+
var confirmFrameworkSchema = z23.object({
|
|
2910
3193
|
frameworks: detectLanguageSchema.shape.frameworks
|
|
2911
3194
|
});
|
|
2912
3195
|
var CURATED_FRAMEWORKS = [
|
|
@@ -3034,8 +3317,8 @@ async function promptUser(ctx, params) {
|
|
|
3034
3317
|
}
|
|
3035
3318
|
|
|
3036
3319
|
// src/actions/confirmEntities.ts
|
|
3037
|
-
import
|
|
3038
|
-
var confirmEntitiesSchema =
|
|
3320
|
+
import z24 from "zod";
|
|
3321
|
+
var confirmEntitiesSchema = z24.object({
|
|
3039
3322
|
// Final detection — the focused re-run may supersede project-scan's.
|
|
3040
3323
|
ingestionAnalysis: ingestionAnalysisSchema.shape.ingestionAnalysis.optional(),
|
|
3041
3324
|
confirmedEntities: confirmedEntitiesFieldSchema
|
|
@@ -3105,15 +3388,15 @@ async function confirmEntities(ctx) {
|
|
|
3105
3388
|
}
|
|
3106
3389
|
|
|
3107
3390
|
// src/actions/review.ts
|
|
3108
|
-
import { z as
|
|
3109
|
-
var reviewSchema =
|
|
3391
|
+
import { z as z25 } from "zod";
|
|
3392
|
+
var reviewSchema = z25.object({
|
|
3110
3393
|
// Broad, high-level takeaways grouped by theme (e.g. ingestion, search UI),
|
|
3111
3394
|
// not one entry per workflow step — a step's raw output can be a long,
|
|
3112
3395
|
// multi-paragraph blob (see implement.ts's summaries.join), and mirroring
|
|
3113
3396
|
// that 1:1 is what made the old per-step summary an unreadable wall of text.
|
|
3114
|
-
summaryPoints:
|
|
3115
|
-
reviewPrompt:
|
|
3116
|
-
nextSteps:
|
|
3397
|
+
summaryPoints: z25.array(z25.string()),
|
|
3398
|
+
reviewPrompt: z25.string(),
|
|
3399
|
+
nextSteps: z25.array(z25.string())
|
|
3117
3400
|
});
|
|
3118
3401
|
function formatCompletedSteps(steps) {
|
|
3119
3402
|
if (!steps.length) return "(no prior steps completed)";
|
|
@@ -3164,16 +3447,16 @@ ${formatCompletedSteps(ctx.completedSteps)}`,
|
|
|
3164
3447
|
};
|
|
3165
3448
|
|
|
3166
3449
|
// src/actions/implement.ts
|
|
3167
|
-
import
|
|
3450
|
+
import z26 from "zod";
|
|
3168
3451
|
|
|
3169
3452
|
// src/lib/worktree.ts
|
|
3170
3453
|
import { execFile, spawn as spawn3 } from "node:child_process";
|
|
3171
|
-
import { copyFile, mkdir as mkdir6, readdir as readdir3, readFile as
|
|
3454
|
+
import { copyFile, mkdir as mkdir6, readdir as readdir3, readFile as readFile7, stat as stat2, writeFile as writeFile6 } from "node:fs/promises";
|
|
3172
3455
|
import {
|
|
3173
3456
|
basename as basename2,
|
|
3174
3457
|
dirname as dirname7,
|
|
3175
3458
|
isAbsolute as isAbsolute2,
|
|
3176
|
-
join as
|
|
3459
|
+
join as join9,
|
|
3177
3460
|
relative as relative2,
|
|
3178
3461
|
resolve as resolve3
|
|
3179
3462
|
} from "node:path";
|
|
@@ -3207,7 +3490,7 @@ async function isWorkingTreeDirty(repoRoot) {
|
|
|
3207
3490
|
return out.trim().length > 0;
|
|
3208
3491
|
}
|
|
3209
3492
|
async function pruneOldWorktrees(repoRoot) {
|
|
3210
|
-
const dir =
|
|
3493
|
+
const dir = join9(stateDir(repoRoot), "worktrees");
|
|
3211
3494
|
const stale = (await readdir3(dir).catch(() => [])).filter((name) => /^wizard-implement-\d+$/.test(name)).sort().reverse().slice(MAX_WIZARD_WORKTREES - 1);
|
|
3212
3495
|
for (const slug of stale) {
|
|
3213
3496
|
const branch = slug.replace("wizard-implement-", WIZARD_BRANCH_PREFIX);
|
|
@@ -3218,7 +3501,7 @@ async function pruneOldWorktrees(repoRoot) {
|
|
|
3218
3501
|
"worktree",
|
|
3219
3502
|
"remove",
|
|
3220
3503
|
"--force",
|
|
3221
|
-
|
|
3504
|
+
join9(dir, slug)
|
|
3222
3505
|
]);
|
|
3223
3506
|
await git(["-C", repoRoot, "branch", "-D", branch]);
|
|
3224
3507
|
} catch (err) {
|
|
@@ -3232,7 +3515,7 @@ async function pruneOldWorktrees(repoRoot) {
|
|
|
3232
3515
|
async function createWorktree(repoRoot) {
|
|
3233
3516
|
const branch = `${WIZARD_BRANCH_PREFIX}${Date.now()}`;
|
|
3234
3517
|
const dirSlug = branch.replace(/\//g, "-");
|
|
3235
|
-
const path =
|
|
3518
|
+
const path = join9(stateDir(repoRoot), "worktrees", dirSlug);
|
|
3236
3519
|
await git(["-C", repoRoot, "worktree", "prune"]);
|
|
3237
3520
|
await pruneOldWorktrees(repoRoot);
|
|
3238
3521
|
await mkdir6(dirname7(path), { recursive: true });
|
|
@@ -3352,8 +3635,8 @@ async function copyUploadIntoWorktree(repoRoot, worktreePath, ingestDir, sourceP
|
|
|
3352
3635
|
} catch {
|
|
3353
3636
|
return { ok: false, reason: `"${sourcePath}" does not exist` };
|
|
3354
3637
|
}
|
|
3355
|
-
const relPath =
|
|
3356
|
-
const dest =
|
|
3638
|
+
const relPath = join9(ingestDir, basename2(source));
|
|
3639
|
+
const dest = join9(worktreePath, relPath);
|
|
3357
3640
|
try {
|
|
3358
3641
|
await mkdir6(dirname7(dest), { recursive: true });
|
|
3359
3642
|
await copyFile(source, dest);
|
|
@@ -3369,10 +3652,10 @@ function hasEnvVar(content, name) {
|
|
|
3369
3652
|
return new RegExp(`^(\\s*(?:export\\s+)?${name})\\s*=`, "m").test(content);
|
|
3370
3653
|
}
|
|
3371
3654
|
async function writeSearchEnvValues(worktreePath, vars) {
|
|
3372
|
-
const target =
|
|
3655
|
+
const target = join9(worktreePath, ".env");
|
|
3373
3656
|
let existing = "";
|
|
3374
3657
|
try {
|
|
3375
|
-
existing = await
|
|
3658
|
+
existing = await readFile7(target, "utf8");
|
|
3376
3659
|
} catch (err) {
|
|
3377
3660
|
if (err.code !== "ENOENT") throw err;
|
|
3378
3661
|
}
|
|
@@ -3440,63 +3723,15 @@ async function confirmDirtyWorkingTree(ctx, repoRoot) {
|
|
|
3440
3723
|
}
|
|
3441
3724
|
}
|
|
3442
3725
|
|
|
3443
|
-
// src/lib/algoliaApiKey.ts
|
|
3444
|
-
import { z as z23 } from "zod";
|
|
3445
|
-
var SAFE_ACLS = /* @__PURE__ */ new Set(["search", "browse", "listIndexes"]);
|
|
3446
|
-
var apiKeySchema = z23.object({
|
|
3447
|
-
value: z23.string().min(1),
|
|
3448
|
-
acl: z23.array(z23.string()).default([]),
|
|
3449
|
-
indexes: z23.array(z23.string()).default([])
|
|
3450
|
-
});
|
|
3451
|
-
var apiKeyListSchema = z23.object({
|
|
3452
|
-
items: z23.array(apiKeySchema).optional(),
|
|
3453
|
-
keys: z23.array(apiKeySchema).optional()
|
|
3454
|
-
}).transform((o) => o.items ?? o.keys ?? []);
|
|
3455
|
-
var createdKeySchema = z23.object({
|
|
3456
|
-
key: z23.string().min(1).optional(),
|
|
3457
|
-
value: z23.string().min(1).optional()
|
|
3458
|
-
});
|
|
3459
|
-
function canReuse(key, index) {
|
|
3460
|
-
return key.acl.includes("search") && key.acl.every((acl) => SAFE_ACLS.has(acl)) && (key.indexes.length === 0 || key.indexes.includes("*") || key.indexes.includes(index));
|
|
3461
|
-
}
|
|
3462
|
-
async function createSearchKey(index) {
|
|
3463
|
-
const stdout = await runAlgoliaCli([
|
|
3464
|
-
"apikeys",
|
|
3465
|
-
"create",
|
|
3466
|
-
"--indices",
|
|
3467
|
-
index,
|
|
3468
|
-
"--acl",
|
|
3469
|
-
"search,browse",
|
|
3470
|
-
"--description",
|
|
3471
|
-
`wizard search-only key for ${index}`,
|
|
3472
|
-
"-o",
|
|
3473
|
-
"json"
|
|
3474
|
-
]);
|
|
3475
|
-
const { key, value } = createdKeySchema.parse(JSON.parse(stdout));
|
|
3476
|
-
const created = key ?? value;
|
|
3477
|
-
if (!created) throw new Error("apikeys create returned no key value");
|
|
3478
|
-
return created;
|
|
3479
|
-
}
|
|
3480
|
-
async function resolveSearchOnlyKey(index) {
|
|
3481
|
-
const stdout = await runAlgoliaCli(["apikeys", "list", "-o", "json"]);
|
|
3482
|
-
const existing = apiKeyListSchema.parse(JSON.parse(stdout)).find((key) => canReuse(key, index))?.value;
|
|
3483
|
-
if (existing) {
|
|
3484
|
-
logger.info({ index }, "reusing existing search-only API key");
|
|
3485
|
-
return existing;
|
|
3486
|
-
}
|
|
3487
|
-
logger.info({ index }, "no reusable search-only key found; creating one");
|
|
3488
|
-
return createSearchKey(index);
|
|
3489
|
-
}
|
|
3490
|
-
|
|
3491
3726
|
// src/lib/algoliaDocs.ts
|
|
3492
3727
|
import { readFileSync, readdirSync, existsSync as existsSync2 } from "node:fs";
|
|
3493
|
-
import { dirname as dirname8, join as
|
|
3728
|
+
import { dirname as dirname8, join as join10 } from "node:path";
|
|
3494
3729
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3495
|
-
var DOCS_SUBPATH =
|
|
3730
|
+
var DOCS_SUBPATH = join10("docs", "algolia-sdk");
|
|
3496
3731
|
function findDocsDir() {
|
|
3497
3732
|
let dir = dirname8(fileURLToPath2(import.meta.url));
|
|
3498
3733
|
for (; ; ) {
|
|
3499
|
-
const candidate =
|
|
3734
|
+
const candidate = join10(dir, DOCS_SUBPATH);
|
|
3500
3735
|
if (existsSync2(candidate)) return candidate;
|
|
3501
3736
|
const parent = dirname8(dir);
|
|
3502
3737
|
if (parent === dir) return void 0;
|
|
@@ -3519,7 +3754,7 @@ function loadAlgoliaDoc(language) {
|
|
|
3519
3754
|
);
|
|
3520
3755
|
return "";
|
|
3521
3756
|
}
|
|
3522
|
-
return readFileSync(
|
|
3757
|
+
return readFileSync(join10(docsDir, files[0]), "utf8").trim();
|
|
3523
3758
|
}
|
|
3524
3759
|
function getNamedDoc(name, language) {
|
|
3525
3760
|
const docsDir = findDocsDir();
|
|
@@ -3527,7 +3762,7 @@ function getNamedDoc(name, language) {
|
|
|
3527
3762
|
logger.warn("docs/algolia-sdk not found");
|
|
3528
3763
|
return "";
|
|
3529
3764
|
}
|
|
3530
|
-
const file =
|
|
3765
|
+
const file = join10(docsDir, `${name}-${language}.md`);
|
|
3531
3766
|
if (!existsSync2(file)) {
|
|
3532
3767
|
logger.warn({ name, language }, "named SDK reference not found");
|
|
3533
3768
|
return "";
|
|
@@ -3554,50 +3789,34 @@ function shellQuote(value) {
|
|
|
3554
3789
|
}
|
|
3555
3790
|
|
|
3556
3791
|
// src/actions/implement.ts
|
|
3557
|
-
var implementSchema =
|
|
3558
|
-
filesChanged:
|
|
3559
|
-
summary:
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
// machine-readable count line; absent when the script didn't run or emitted
|
|
3571
|
-
// no parseable count.
|
|
3572
|
-
ingestRecordCount: z24.number().optional(),
|
|
3573
|
-
// Wall-clock duration of the run-now ingestion execution, in ms.
|
|
3574
|
-
ingestDurationMs: z24.number().optional(),
|
|
3575
|
-
ingestionSource: z24.enum(["local", "fileUpload", "generated"]),
|
|
3576
|
-
// Suggested names/values, built from framework detection. The search agent is
|
|
3577
|
-
// instructed to rename the prefix if it doesn't match the project's build
|
|
3578
|
-
// tool, so the names it actually wrote can differ — treat these as hints, not
|
|
3579
|
-
// ground truth (the agent's summary carries the final names).
|
|
3580
|
-
searchEnvVars: z24.array(
|
|
3581
|
-
z24.object({
|
|
3582
|
-
name: z24.string(),
|
|
3583
|
-
value: z24.string()
|
|
3792
|
+
var implementSchema = z26.object({
|
|
3793
|
+
filesChanged: z26.array(z26.string()),
|
|
3794
|
+
summary: z26.string(),
|
|
3795
|
+
worktreePath: z26.string().optional(),
|
|
3796
|
+
ingestCommand: z26.string().optional(),
|
|
3797
|
+
ingestScriptRan: z26.boolean().optional(),
|
|
3798
|
+
ingestRecordCount: z26.number().optional(),
|
|
3799
|
+
ingestDurationMs: z26.number().optional(),
|
|
3800
|
+
ingestionSource: z26.enum(["local", "fileUpload", "generated"]),
|
|
3801
|
+
searchEnvVars: z26.array(
|
|
3802
|
+
z26.object({
|
|
3803
|
+
name: z26.string(),
|
|
3804
|
+
value: z26.string()
|
|
3584
3805
|
})
|
|
3585
3806
|
).optional()
|
|
3586
3807
|
});
|
|
3587
|
-
var implementationOutputSchema =
|
|
3588
|
-
summary:
|
|
3589
|
-
// Ingestion only:
|
|
3590
|
-
//
|
|
3591
|
-
//
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
runtime: z24.enum(INGEST_RUNTIMES).optional(),
|
|
3595
|
-
entrypoint: z24.string().optional()
|
|
3808
|
+
var implementationOutputSchema = z26.object({
|
|
3809
|
+
summary: z26.string(),
|
|
3810
|
+
// Ingestion only: a structured pair the wizard turns into an argv, never a
|
|
3811
|
+
// free-form command string. `runtime` is allowlisted and `entrypoint` is
|
|
3812
|
+
// validated worktree-relative, so the agent cannot inject extra commands.
|
|
3813
|
+
runtime: z26.enum(INGEST_RUNTIMES).optional(),
|
|
3814
|
+
entrypoint: z26.string().optional()
|
|
3596
3815
|
});
|
|
3597
|
-
var verificationOutputSchema =
|
|
3598
|
-
summary:
|
|
3599
|
-
sufficient:
|
|
3600
|
-
additionalInstructions:
|
|
3816
|
+
var verificationOutputSchema = z26.object({
|
|
3817
|
+
summary: z26.string(),
|
|
3818
|
+
sufficient: z26.boolean(),
|
|
3819
|
+
additionalInstructions: z26.string().optional()
|
|
3601
3820
|
});
|
|
3602
3821
|
var MAX_IMPLEMENT_VERIFICATION_ATTEMPTS = 3;
|
|
3603
3822
|
var DEFAULT_IMPLEMENT_USE_CASES = ["ingestion", "search"];
|
|
@@ -3669,9 +3888,6 @@ function sourceSpecificInstructions(input) {
|
|
|
3669
3888
|
"Add env vars for any local source access (DB URL, API base, file paths) that is not a fixed repo path."
|
|
3670
3889
|
],
|
|
3671
3890
|
fileUpload: [
|
|
3672
|
-
// The wizard already copied the developer's file into the worktree at this
|
|
3673
|
-
// exact path, so the agent must read it directly — never search for or
|
|
3674
|
-
// substitute another file.
|
|
3675
3891
|
`Records come from the developer's file, already copied into the worktree at "${input.uploadFilePath}". Read and parse that exact file.`,
|
|
3676
3892
|
"Parse by extension: JSON = array of objects; CSV/TSV = header row maps to keys.",
|
|
3677
3893
|
"Map parsed columns/fields to the confirmed entity attributes.",
|
|
@@ -3711,12 +3927,9 @@ function searchInstructions(input) {
|
|
|
3711
3927
|
doc,
|
|
3712
3928
|
`Add the search UI at ${input.searchLocation ? `"${input.searchLocation}"` : "the best shared, always-rendered layout location (e.g. a header/nav component)"} so it is reachable across the app \u2014 at least a working SearchBox and Hits against the "${input.targetIndex}" index.`,
|
|
3713
3929
|
"Read the App ID and a search-only API key from public env vars; never hardcode them. A search-only key is safe to expose client-side.",
|
|
3714
|
-
// appId always resolves (loadActiveProfile throws otherwise); only the
|
|
3715
|
-
// search-only key is best-effort and can fall back to a placeholder.
|
|
3716
3930
|
`Values: App ID "${input.appId}", search-only key ${input.searchKey ? `"${input.searchKey}"` : "(placeholder for the developer to fill in)"}.`,
|
|
3717
|
-
//
|
|
3718
|
-
//
|
|
3719
|
-
// right after this step, so a renamed prefix here would leave the code
|
|
3931
|
+
// Not the agent's to rename: the wizard writes these exact names into
|
|
3932
|
+
// ".env" right after this step, so a renamed prefix would leave the code
|
|
3720
3933
|
// reading a var the wizard never wrote.
|
|
3721
3934
|
`Use exactly these public env var names in the code: ${input.searchEnvVars.map(({ name }) => name).join(", ")}.`,
|
|
3722
3935
|
'Add any Algolia/InstantSearch packages you import to package.json "dependencies" with a valid version range; the wizard installs them in the worktree after you finish.',
|
|
@@ -3860,6 +4073,7 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
3860
4073
|
}
|
|
3861
4074
|
}
|
|
3862
4075
|
const targetIndex = selected?.selection;
|
|
4076
|
+
useWizard.getState().setTargetIndex(targetIndex ?? null);
|
|
3863
4077
|
await assertGitRepoWithHead(repoRoot);
|
|
3864
4078
|
if (await isWorkingTreeDirty(repoRoot)) {
|
|
3865
4079
|
await confirmDirtyWorkingTree(ctx, repoRoot);
|
|
@@ -3870,7 +4084,7 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
3870
4084
|
let appId;
|
|
3871
4085
|
let searchKey;
|
|
3872
4086
|
if (useCases.includes("search")) {
|
|
3873
|
-
appId = (await
|
|
4087
|
+
appId = (await requireApplication()).id;
|
|
3874
4088
|
try {
|
|
3875
4089
|
searchKey = await resolveSearchOnlyKey(targetIndex);
|
|
3876
4090
|
} catch (err) {
|
|
@@ -3915,8 +4129,6 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
3915
4129
|
ingestDir: INGEST_DIR,
|
|
3916
4130
|
ingestionSource,
|
|
3917
4131
|
uploadFilePath,
|
|
3918
|
-
// language.frameworks already prefers the confirm-framework step output,
|
|
3919
|
-
// so the user's confirmed stack (not just raw detection) picks the flavor.
|
|
3920
4132
|
uiFramework: detectUiFramework(language)
|
|
3921
4133
|
};
|
|
3922
4134
|
const summaries = [];
|
|
@@ -3981,7 +4193,8 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
3981
4193
|
messages: []
|
|
3982
4194
|
}) === true;
|
|
3983
4195
|
if (runNow) {
|
|
3984
|
-
const
|
|
4196
|
+
const ingestApp = await requireApplication();
|
|
4197
|
+
const writeKey = await resolveWriteKey(targetIndex);
|
|
3985
4198
|
ctx.notify({ messages: [`Writing records to "${targetIndex}"\u2026`] });
|
|
3986
4199
|
const scriptLogId = ctx.logStart("runIngestScript", {
|
|
3987
4200
|
runtime: ingestRuntime,
|
|
@@ -3993,8 +4206,8 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
3993
4206
|
ingestRuntime,
|
|
3994
4207
|
ingestEntrypoint,
|
|
3995
4208
|
{
|
|
3996
|
-
[APP_ID_VAR]:
|
|
3997
|
-
[API_KEY_VAR]:
|
|
4209
|
+
[APP_ID_VAR]: ingestApp.id,
|
|
4210
|
+
[API_KEY_VAR]: writeKey
|
|
3998
4211
|
}
|
|
3999
4212
|
);
|
|
4000
4213
|
ctx.logEnd(scriptLogId, run2.ok ? "success" : "error");
|
|
@@ -4063,8 +4276,6 @@ ${run2.output}` : status;
|
|
|
4063
4276
|
);
|
|
4064
4277
|
}
|
|
4065
4278
|
await ctx.requestUserInput({
|
|
4066
|
-
// No question being asked here, just an acknowledgement — the
|
|
4067
|
-
// continue/decline hints below already say "continue".
|
|
4068
4279
|
prompt: "",
|
|
4069
4280
|
promptType: "enterToContinue",
|
|
4070
4281
|
options: [],
|
|
@@ -4205,8 +4416,8 @@ var defaultWorkflow = {
|
|
|
4205
4416
|
defineStep({
|
|
4206
4417
|
id: "select-index",
|
|
4207
4418
|
title: "Set up index",
|
|
4208
|
-
outputSchema:
|
|
4209
|
-
selection:
|
|
4419
|
+
outputSchema: z27.object({
|
|
4420
|
+
selection: z27.string()
|
|
4210
4421
|
}),
|
|
4211
4422
|
run: (ctx) => selectIndexStep(ctx)
|
|
4212
4423
|
}),
|
|
@@ -4485,7 +4696,7 @@ function parseCliArgs(argv) {
|
|
|
4485
4696
|
|
|
4486
4697
|
// src/lib/resetState.ts
|
|
4487
4698
|
import { readdir as readdir4, rm as rm2 } from "node:fs/promises";
|
|
4488
|
-
import { join as
|
|
4699
|
+
import { join as join11 } from "node:path";
|
|
4489
4700
|
var KEEP = ["wizard.log"];
|
|
4490
4701
|
async function resetProjectState() {
|
|
4491
4702
|
const dir = stateDir();
|
|
@@ -4497,7 +4708,7 @@ async function resetProjectState() {
|
|
|
4497
4708
|
}
|
|
4498
4709
|
const targets = entries.filter((name) => !KEEP.includes(name));
|
|
4499
4710
|
await Promise.all(
|
|
4500
|
-
targets.map((name) => rm2(
|
|
4711
|
+
targets.map((name) => rm2(join11(dir, name), { recursive: true, force: true }))
|
|
4501
4712
|
);
|
|
4502
4713
|
return { dir, removed: targets };
|
|
4503
4714
|
}
|
|
@@ -4552,31 +4763,38 @@ ${formatStepList(workflow)}`);
|
|
|
4552
4763
|
}
|
|
4553
4764
|
async function run(workflow) {
|
|
4554
4765
|
const store = useWizard.getState();
|
|
4555
|
-
|
|
4766
|
+
const instance = render(/* @__PURE__ */ jsx14(App, {}), { incrementalRendering: true });
|
|
4767
|
+
await store.waitForStart();
|
|
4556
4768
|
let user = await getUser();
|
|
4557
4769
|
if (!user) {
|
|
4558
|
-
|
|
4559
|
-
instance.cleanup();
|
|
4770
|
+
store.beginAuth();
|
|
4560
4771
|
try {
|
|
4561
4772
|
await runAuthLogin();
|
|
4562
4773
|
} catch (err) {
|
|
4563
|
-
|
|
4774
|
+
store.setError(err instanceof Error ? err.message : String(err));
|
|
4775
|
+
await instance.waitUntilExit();
|
|
4564
4776
|
process.exit(1);
|
|
4565
4777
|
}
|
|
4566
|
-
|
|
4778
|
+
store.endAuth();
|
|
4567
4779
|
user = await getUser();
|
|
4568
4780
|
if (!user) {
|
|
4569
4781
|
store.setError(
|
|
4570
|
-
"Authentication completed but no Algolia user was returned. Try running `npx @algolia/cli auth login` directly."
|
|
4782
|
+
"Authentication completed but no Algolia user was returned. Try running `npx @algolia/cli@latest auth login` directly."
|
|
4571
4783
|
);
|
|
4572
4784
|
await instance.waitUntilExit();
|
|
4573
4785
|
process.exit(1);
|
|
4574
4786
|
}
|
|
4575
4787
|
}
|
|
4576
4788
|
store.setUser(user);
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4789
|
+
let app;
|
|
4790
|
+
try {
|
|
4791
|
+
app = await ensureApplication();
|
|
4792
|
+
} catch (err) {
|
|
4793
|
+
store.setError(err instanceof Error ? err.message : String(err));
|
|
4794
|
+
await instance.waitUntilExit();
|
|
4795
|
+
process.exit(1);
|
|
4796
|
+
}
|
|
4797
|
+
runWorkflow(workflow, app.id);
|
|
4580
4798
|
}
|
|
4581
4799
|
var started = await startup();
|
|
4582
4800
|
if (typeof started === "number") {
|