@algolia/wizard 0.8.0 → 0.9.0-rc.53.57
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 +796 -552
- 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,26 @@ 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
|
+
// Sign-in happens after the welcome screen's enter, so `endAuth` lands on
|
|
251
|
+
// 'preflight': returning to 'idle' would put the welcome screen back up and
|
|
252
|
+
// ask the user to confirm the run a second time.
|
|
253
|
+
beginAuth: () => set({ phase: "authenticating", cliOutput: [] }),
|
|
254
|
+
endAuth: () => set((s) => s.phase === "authenticating" ? { phase: "preflight" } : {}),
|
|
255
|
+
// Only meaningful from 'idle' — once the workflow is running there's nothing
|
|
256
|
+
// left to confirm. `homeScreen` resets so preflight shows Welcome rather than
|
|
257
|
+
// the Learn more sub-view.
|
|
192
258
|
confirmStart: () => set(
|
|
193
259
|
(s) => s.phase === "idle" ? { phase: "preflight", homeScreen: "home" } : {}
|
|
194
260
|
),
|
|
195
|
-
// Welcome sub-view navigation; leaves `phase` untouched so the workflow stays paused.
|
|
196
261
|
openLearnMore: () => set({ homeScreen: "learnMore" }),
|
|
197
262
|
backToHome: () => set({ homeScreen: "home" }),
|
|
198
|
-
// Resolves
|
|
199
|
-
// after this is called (the welcome screen's enter handler is what
|
|
200
|
-
// drives the transition via `confirmStart`).
|
|
263
|
+
// Resolves whether the phase left 'idle' before or after this is called.
|
|
201
264
|
waitForStart: () => new Promise((resolve4) => {
|
|
202
265
|
if (get().phase !== "idle") {
|
|
203
266
|
resolve4();
|
|
@@ -220,15 +283,20 @@ var useWizard = create((set, get) => ({
|
|
|
220
283
|
syncSteps: (steps, currentStepIndex) => set({ steps, currentStepIndex }),
|
|
221
284
|
setActiveStep: (index) => {
|
|
222
285
|
get()._clearNoticeQueue();
|
|
223
|
-
set({
|
|
286
|
+
set({
|
|
287
|
+
phase: "running",
|
|
288
|
+
currentStepIndex: index,
|
|
289
|
+
output: "",
|
|
290
|
+
notices: [],
|
|
291
|
+
cliOutput: []
|
|
292
|
+
});
|
|
224
293
|
},
|
|
225
294
|
setUser: (user) => set({ user }),
|
|
226
295
|
appendToken: (text) => set((s) => ({ output: s.output + text })),
|
|
227
296
|
clearOutput: () => set({ output: "" }),
|
|
228
|
-
// Renders the first notice of a burst immediately, then
|
|
229
|
-
//
|
|
230
|
-
// the
|
|
231
|
-
// covers the time since the last render, even across bursts.
|
|
297
|
+
// Renders the first notice of a burst immediately, then drains later arrivals
|
|
298
|
+
// one per `NOTICE_INTERVAL_MS`. The timer stays armed through an empty drain
|
|
299
|
+
// so the cooldown covers the time since the last render, across bursts.
|
|
232
300
|
pushNotice: (notice) => {
|
|
233
301
|
const { notices, _noticeQueue, _noticeTimer } = get();
|
|
234
302
|
if (_noticeTimer === null) {
|
|
@@ -261,6 +329,15 @@ var useWizard = create((set, get) => ({
|
|
|
261
329
|
get()._clearNoticeQueue();
|
|
262
330
|
set({ notices: [] });
|
|
263
331
|
},
|
|
332
|
+
// Unthrottled, unlike `pushNotice`: holding these back would land output
|
|
333
|
+
// after the command it belongs to has already exited.
|
|
334
|
+
pushCliOutput: (stream, text) => set((s) => ({
|
|
335
|
+
cliOutput: [...s.cliOutput, { id: nanoid(), stream, text }].slice(
|
|
336
|
+
-CLI_OUTPUT_LIMIT
|
|
337
|
+
)
|
|
338
|
+
})),
|
|
339
|
+
clearCliOutput: () => set({ cliOutput: [] }),
|
|
340
|
+
setTargetIndex: (index) => set({ targetIndex: index }),
|
|
264
341
|
logStart: (kind, name, input) => {
|
|
265
342
|
const id = nanoid();
|
|
266
343
|
set((s) => ({
|
|
@@ -283,9 +360,8 @@ var useWizard = create((set, get) => ({
|
|
|
283
360
|
_resolve: resolve4
|
|
284
361
|
});
|
|
285
362
|
}),
|
|
286
|
-
// Logs what the user picked
|
|
287
|
-
//
|
|
288
|
-
// here.
|
|
363
|
+
// Logs what the user picked, not the prompt text — that just duplicates
|
|
364
|
+
// on-screen content.
|
|
289
365
|
submitInput: async (value) => {
|
|
290
366
|
await markInteraction();
|
|
291
367
|
get()._resolve?.(value);
|
|
@@ -305,6 +381,8 @@ var useWizard = create((set, get) => ({
|
|
|
305
381
|
currentStepIndex: 0,
|
|
306
382
|
output: "",
|
|
307
383
|
notices: [],
|
|
384
|
+
cliOutput: [],
|
|
385
|
+
targetIndex: null,
|
|
308
386
|
logs: [],
|
|
309
387
|
error: null,
|
|
310
388
|
inputReq: null,
|
|
@@ -313,16 +391,100 @@ var useWizard = create((set, get) => ({
|
|
|
313
391
|
}
|
|
314
392
|
}));
|
|
315
393
|
|
|
394
|
+
// src/ui/CliOutput.tsx
|
|
395
|
+
import { Box, Text, useWindowSize } from "ink";
|
|
396
|
+
|
|
397
|
+
// src/ui/theme.ts
|
|
398
|
+
var MARKER = {
|
|
399
|
+
pending: "\u25CB",
|
|
400
|
+
running: "\u25D0",
|
|
401
|
+
done: "\u2713",
|
|
402
|
+
error: "\u2716"
|
|
403
|
+
};
|
|
404
|
+
var BRAND = "#003DFF";
|
|
405
|
+
var SECONDARY = "#5468FF";
|
|
406
|
+
var DANGER = "#F86E7E";
|
|
407
|
+
var COLORS = {
|
|
408
|
+
brand: BRAND,
|
|
409
|
+
primary: "#E6EDF3",
|
|
410
|
+
secondary: SECONDARY,
|
|
411
|
+
strong: "#FFFFFF",
|
|
412
|
+
muted: "#8B949E",
|
|
413
|
+
dim: "#484F58",
|
|
414
|
+
highlight: { bg: "#12331C", fg: "#4ADE80" },
|
|
415
|
+
badge: "#E3B341",
|
|
416
|
+
danger: DANGER,
|
|
417
|
+
success: "#4ADE80",
|
|
418
|
+
bg: {
|
|
419
|
+
main: "#0B0E14",
|
|
420
|
+
sidebar: "#14171E"
|
|
421
|
+
},
|
|
422
|
+
border: "#30363D",
|
|
423
|
+
accent: "#76A0FF",
|
|
424
|
+
status: {
|
|
425
|
+
pending: "gray",
|
|
426
|
+
running: "#76A0FF",
|
|
427
|
+
done: "#4ADE80",
|
|
428
|
+
error: DANGER
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
// src/ui/CliOutput.tsx
|
|
433
|
+
import { jsxs } from "react/jsx-runtime";
|
|
434
|
+
var CLI_MARKER = "\u203A";
|
|
435
|
+
var RESERVED_ROWS = 16;
|
|
436
|
+
var MAX_ROWS = 12;
|
|
437
|
+
var PANEL_TEXT_WIDTH = 45;
|
|
438
|
+
var URL_PATTERN = /https?:\/\//;
|
|
439
|
+
function rowCost(text) {
|
|
440
|
+
return URL_PATTERN.test(text) ? Math.max(1, Math.ceil(text.length / PANEL_TEXT_WIDTH)) : 1;
|
|
441
|
+
}
|
|
442
|
+
function CliOutput() {
|
|
443
|
+
const cliOutput = useWizard((s) => s.cliOutput);
|
|
444
|
+
const { rows } = useWindowSize();
|
|
445
|
+
if (!cliOutput.length) return null;
|
|
446
|
+
const rowBudget = Math.min(Math.max(rows - RESERVED_ROWS, 3), MAX_ROWS);
|
|
447
|
+
const visible = [];
|
|
448
|
+
let usedRows = 0;
|
|
449
|
+
for (let i = cliOutput.length - 1; i >= 0; i--) {
|
|
450
|
+
const cost = rowCost(cliOutput[i].text);
|
|
451
|
+
if (usedRows + cost > rowBudget && visible.length > 0) break;
|
|
452
|
+
visible.unshift(cliOutput[i]);
|
|
453
|
+
usedRows += cost;
|
|
454
|
+
}
|
|
455
|
+
const hidden = cliOutput.length - visible.length;
|
|
456
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
457
|
+
hidden > 0 && /* @__PURE__ */ jsxs(Text, { color: COLORS.dim, children: [
|
|
458
|
+
"\u2191 ",
|
|
459
|
+
hidden,
|
|
460
|
+
" earlier line(s)"
|
|
461
|
+
] }),
|
|
462
|
+
visible.map((line) => /* @__PURE__ */ jsxs(
|
|
463
|
+
Text,
|
|
464
|
+
{
|
|
465
|
+
color: line.stream === "stderr" ? COLORS.muted : COLORS.dim,
|
|
466
|
+
wrap: URL_PATTERN.test(line.text) ? "wrap" : "truncate",
|
|
467
|
+
children: [
|
|
468
|
+
CLI_MARKER,
|
|
469
|
+
" ",
|
|
470
|
+
line.text
|
|
471
|
+
]
|
|
472
|
+
},
|
|
473
|
+
line.id
|
|
474
|
+
))
|
|
475
|
+
] });
|
|
476
|
+
}
|
|
477
|
+
|
|
316
478
|
// src/ui/Notices.tsx
|
|
317
|
-
import { Box as
|
|
479
|
+
import { Box as Box3, Text as Text3, useWindowSize as useWindowSize3 } from "ink";
|
|
318
480
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
319
481
|
|
|
320
482
|
// src/ui/Table.tsx
|
|
321
|
-
import { Box, Text, measureElement, useWindowSize } from "ink";
|
|
483
|
+
import { Box as Box2, Text as Text2, measureElement, useWindowSize as useWindowSize2 } from "ink";
|
|
322
484
|
import { useEffect, useRef, useState } from "react";
|
|
323
485
|
import { jsx } from "react/jsx-runtime";
|
|
324
486
|
function Table({ columns, rows }) {
|
|
325
|
-
const { columns: termCols } =
|
|
487
|
+
const { columns: termCols } = useWindowSize2();
|
|
326
488
|
const ref = useRef(null);
|
|
327
489
|
const [width, setWidth] = useState(0);
|
|
328
490
|
useEffect(() => {
|
|
@@ -330,7 +492,7 @@ function Table({ columns, rows }) {
|
|
|
330
492
|
}, [termCols, columns, rows]);
|
|
331
493
|
if (rows.length === 0) return null;
|
|
332
494
|
const lines = formatTable(columns, rows, width || void 0);
|
|
333
|
-
return /* @__PURE__ */ jsx(
|
|
495
|
+
return /* @__PURE__ */ jsx(Box2, { flexDirection: "column", ref, children: lines.map((line, i) => /* @__PURE__ */ jsx(Text2, { wrap: "truncate", children: line }, `tbl-${i}`)) });
|
|
334
496
|
}
|
|
335
497
|
function formatTable(columns, rows, width) {
|
|
336
498
|
const natural = columns.map(
|
|
@@ -370,48 +532,13 @@ function resize(widths, budget) {
|
|
|
370
532
|
}
|
|
371
533
|
var truncate = (s, width) => s.length <= width ? s : width <= 1 ? s.slice(0, width) : `${s.slice(0, width - 1)}\u2026`;
|
|
372
534
|
|
|
373
|
-
// src/ui/theme.ts
|
|
374
|
-
var MARKER = {
|
|
375
|
-
pending: "\u25CB",
|
|
376
|
-
running: "\u25D0",
|
|
377
|
-
done: "\u2713",
|
|
378
|
-
error: "\u2716"
|
|
379
|
-
};
|
|
380
|
-
var BRAND = "#003DFF";
|
|
381
|
-
var SECONDARY = "#5468FF";
|
|
382
|
-
var DANGER = "#F86E7E";
|
|
383
|
-
var COLORS = {
|
|
384
|
-
brand: BRAND,
|
|
385
|
-
primary: "#E6EDF3",
|
|
386
|
-
secondary: SECONDARY,
|
|
387
|
-
strong: "#FFFFFF",
|
|
388
|
-
muted: "#8B949E",
|
|
389
|
-
dim: "#484F58",
|
|
390
|
-
highlight: { bg: "#12331C", fg: "#4ADE80" },
|
|
391
|
-
badge: "#E3B341",
|
|
392
|
-
danger: DANGER,
|
|
393
|
-
success: "#4ADE80",
|
|
394
|
-
bg: {
|
|
395
|
-
main: "#0B0E14",
|
|
396
|
-
sidebar: "#14171E"
|
|
397
|
-
},
|
|
398
|
-
border: "#30363D",
|
|
399
|
-
accent: "#76A0FF",
|
|
400
|
-
status: {
|
|
401
|
-
pending: "gray",
|
|
402
|
-
running: "#76A0FF",
|
|
403
|
-
done: "#4ADE80",
|
|
404
|
-
error: DANGER
|
|
405
|
-
}
|
|
406
|
-
};
|
|
407
|
-
|
|
408
535
|
// src/ui/Notices.tsx
|
|
409
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
536
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
410
537
|
var AGENT_MARKER = "\u2726";
|
|
411
|
-
var
|
|
412
|
-
var
|
|
538
|
+
var RESERVED_ROWS2 = 14;
|
|
539
|
+
var PANEL_TEXT_WIDTH2 = 45;
|
|
413
540
|
function messageLineCount(text) {
|
|
414
|
-
return Math.max(1, Math.ceil(text.length /
|
|
541
|
+
return Math.max(1, Math.ceil(text.length / PANEL_TEXT_WIDTH2));
|
|
415
542
|
}
|
|
416
543
|
function noticeLineCount(notice) {
|
|
417
544
|
const messageLines = (notice.messages ?? []).reduce((sum, m) => {
|
|
@@ -422,7 +549,7 @@ function noticeLineCount(notice) {
|
|
|
422
549
|
return messageLines + tableLines;
|
|
423
550
|
}
|
|
424
551
|
function fitVisibleNotices(notices, windowRows) {
|
|
425
|
-
const budget = Math.max(windowRows -
|
|
552
|
+
const budget = Math.max(windowRows - RESERVED_ROWS2, 3);
|
|
426
553
|
let used = 0;
|
|
427
554
|
let count = 0;
|
|
428
555
|
for (let i = notices.length - 1; i >= 0; i--) {
|
|
@@ -455,7 +582,7 @@ function parseHex(hex) {
|
|
|
455
582
|
}
|
|
456
583
|
function Notices() {
|
|
457
584
|
const notices = useWizard((s) => s.notices);
|
|
458
|
-
const { rows: windowRows } =
|
|
585
|
+
const { rows: windowRows } = useWindowSize3();
|
|
459
586
|
const visible = fitVisibleNotices(notices, windowRows);
|
|
460
587
|
const [pulseStep, setPulseStep] = useState2(0);
|
|
461
588
|
useEffect2(() => {
|
|
@@ -472,14 +599,14 @@ function Notices() {
|
|
|
472
599
|
}, []);
|
|
473
600
|
if (!visible.length) return null;
|
|
474
601
|
const pulseColor = PULSE_COLORS[pulseStep];
|
|
475
|
-
return /* @__PURE__ */ jsx2(
|
|
602
|
+
return /* @__PURE__ */ jsx2(Box3, { flexDirection: "column", gap: 1, marginBottom: 1, children: visible.map((notice, i) => {
|
|
476
603
|
const isLatest = i === visible.length - 1;
|
|
477
|
-
return /* @__PURE__ */
|
|
604
|
+
return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", children: [
|
|
478
605
|
notice.messages?.map((m, j) => {
|
|
479
606
|
const line = typeof m === "string" ? { text: m } : m;
|
|
480
607
|
const prefix = j === 0 ? `${AGENT_MARKER} ` : " ";
|
|
481
|
-
return /* @__PURE__ */
|
|
482
|
-
|
|
608
|
+
return /* @__PURE__ */ jsxs2(
|
|
609
|
+
Text3,
|
|
483
610
|
{
|
|
484
611
|
color: isLatest && !line.color ? pulseColor : line.color ?? COLORS.dim,
|
|
485
612
|
bold: line.bold,
|
|
@@ -497,41 +624,41 @@ function Notices() {
|
|
|
497
624
|
}
|
|
498
625
|
|
|
499
626
|
// src/ui/PromptInput.tsx
|
|
500
|
-
import { Box as
|
|
627
|
+
import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
|
|
501
628
|
import TextInput from "ink-text-input";
|
|
502
629
|
import { useState as useState5 } from "react";
|
|
503
630
|
|
|
504
631
|
// src/ui/NextAction.tsx
|
|
505
|
-
import { Box as
|
|
506
|
-
import { Fragment, jsx as jsx3, jsxs as
|
|
632
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
633
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
507
634
|
function NextAction({
|
|
508
635
|
action,
|
|
509
636
|
keyHint,
|
|
510
637
|
hierarchy = "primary"
|
|
511
638
|
}) {
|
|
512
|
-
return /* @__PURE__ */
|
|
513
|
-
hierarchy === "primary" && /* @__PURE__ */ jsx3(
|
|
514
|
-
hierarchy === "secondary" && /* @__PURE__ */
|
|
515
|
-
/* @__PURE__ */ jsx3(
|
|
516
|
-
/* @__PURE__ */ jsx3(
|
|
639
|
+
return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "row", gap: 1, children: [
|
|
640
|
+
hierarchy === "primary" && /* @__PURE__ */ jsx3(Text4, { color: COLORS.success, bold: true, children: `> ${action}` }),
|
|
641
|
+
hierarchy === "secondary" && /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
642
|
+
/* @__PURE__ */ jsx3(Text4, { color: COLORS.success, bold: true, children: `>` }),
|
|
643
|
+
/* @__PURE__ */ jsx3(Text4, { color: COLORS.primary, bold: true, children: action })
|
|
517
644
|
] }),
|
|
518
|
-
/* @__PURE__ */
|
|
519
|
-
/* @__PURE__ */ jsx3(
|
|
520
|
-
/* @__PURE__ */ jsx3(
|
|
521
|
-
/* @__PURE__ */ jsx3(
|
|
522
|
-
/* @__PURE__ */ jsx3(
|
|
645
|
+
/* @__PURE__ */ jsxs3(Box4, { children: [
|
|
646
|
+
/* @__PURE__ */ jsx3(Text4, { color: COLORS.muted, children: "press " }),
|
|
647
|
+
/* @__PURE__ */ jsx3(Text4, { color: COLORS.muted, children: `[` }),
|
|
648
|
+
/* @__PURE__ */ jsx3(Text4, { color: COLORS.primary, children: keyHint }),
|
|
649
|
+
/* @__PURE__ */ jsx3(Text4, { color: COLORS.muted, children: `]` })
|
|
523
650
|
] })
|
|
524
651
|
] });
|
|
525
652
|
}
|
|
526
653
|
|
|
527
654
|
// src/ui/SelectPrompt.tsx
|
|
528
|
-
import { Box as
|
|
655
|
+
import { Box as Box6, Text as Text6, useInput, useWindowSize as useWindowSize5 } from "ink";
|
|
529
656
|
import { useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState4 } from "react";
|
|
530
657
|
|
|
531
658
|
// src/ui/ScrollView.tsx
|
|
532
|
-
import { Box as
|
|
659
|
+
import { Box as Box5, Text as Text5, measureElement as measureElement2, useWindowSize as useWindowSize4 } from "ink";
|
|
533
660
|
import { useCallback, useLayoutEffect, useRef as useRef2, useState as useState3 } from "react";
|
|
534
|
-
import { jsxs as
|
|
661
|
+
import { jsxs as jsxs4 } from "react/jsx-runtime";
|
|
535
662
|
var INDICATOR_ROWS = 2;
|
|
536
663
|
function fittedWidth(node, columns) {
|
|
537
664
|
let left = 0;
|
|
@@ -546,7 +673,7 @@ function useScrollWindow({
|
|
|
546
673
|
followBottom = false
|
|
547
674
|
}) {
|
|
548
675
|
const viewportRef = useRef2(null);
|
|
549
|
-
const { columns } =
|
|
676
|
+
const { columns } = useWindowSize4();
|
|
550
677
|
const [size, setSize] = useState3(
|
|
551
678
|
null
|
|
552
679
|
);
|
|
@@ -601,14 +728,14 @@ function useScrollWindow({
|
|
|
601
728
|
};
|
|
602
729
|
}
|
|
603
730
|
function ScrollView({ scroll, children }) {
|
|
604
|
-
return /* @__PURE__ */
|
|
605
|
-
scroll.hiddenAbove > 0 && /* @__PURE__ */
|
|
731
|
+
return /* @__PURE__ */ jsxs4(Box5, { ref: scroll.viewportRef, flexDirection: "column", flexGrow: 1, children: [
|
|
732
|
+
scroll.hiddenAbove > 0 && /* @__PURE__ */ jsxs4(Text5, { color: COLORS.dim, children: [
|
|
606
733
|
"\u2191 ",
|
|
607
734
|
scroll.hiddenAbove,
|
|
608
735
|
" more"
|
|
609
736
|
] }),
|
|
610
737
|
children,
|
|
611
|
-
scroll.hiddenBelow > 0 && /* @__PURE__ */
|
|
738
|
+
scroll.hiddenBelow > 0 && /* @__PURE__ */ jsxs4(Text5, { color: COLORS.dim, children: [
|
|
612
739
|
"\u2193 ",
|
|
613
740
|
scroll.hiddenBelow,
|
|
614
741
|
" more"
|
|
@@ -617,7 +744,7 @@ function ScrollView({ scroll, children }) {
|
|
|
617
744
|
}
|
|
618
745
|
|
|
619
746
|
// src/ui/SelectPrompt.tsx
|
|
620
|
-
import { jsx as jsx4, jsxs as
|
|
747
|
+
import { jsx as jsx4, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
621
748
|
var CANCEL = "cancel";
|
|
622
749
|
var ARROW_WIDTH = 4;
|
|
623
750
|
var COLUMN_GAP = 2;
|
|
@@ -648,7 +775,7 @@ function SelectPrompt({
|
|
|
648
775
|
if (multi) hints.push({ key: "[space]", label: "select" });
|
|
649
776
|
hints.push({ key: "[enter]", label: "confirm" });
|
|
650
777
|
const containerRef = useRef3(null);
|
|
651
|
-
const { columns } =
|
|
778
|
+
const { columns } = useWindowSize5();
|
|
652
779
|
const [width, setWidth] = useState4(columns);
|
|
653
780
|
useLayoutEffect2(() => {
|
|
654
781
|
if (!containerRef.current) return;
|
|
@@ -702,14 +829,14 @@ function SelectPrompt({
|
|
|
702
829
|
}
|
|
703
830
|
}
|
|
704
831
|
});
|
|
705
|
-
return /* @__PURE__ */ jsx4(
|
|
706
|
-
/* @__PURE__ */
|
|
707
|
-
error && /* @__PURE__ */ jsx4(
|
|
708
|
-
messages?.map((m, i) => /* @__PURE__ */ jsx4(
|
|
832
|
+
return /* @__PURE__ */ jsx4(Box6, { ref: containerRef, flexGrow: 1, children: /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", gap: 1, width, children: [
|
|
833
|
+
/* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", gap: 1, flexShrink: 0, children: [
|
|
834
|
+
error && /* @__PURE__ */ jsx4(Text6, { color: COLORS.danger, children: error }),
|
|
835
|
+
messages?.map((m, i) => /* @__PURE__ */ jsx4(Text6, { color: COLORS.muted, children: m }, `msg-${i}`)),
|
|
709
836
|
table && /* @__PURE__ */ jsx4(Table, { columns: table.columns, rows: table.rows }),
|
|
710
|
-
/* @__PURE__ */
|
|
711
|
-
question && /* @__PURE__ */ jsx4(
|
|
712
|
-
helpText && /* @__PURE__ */ jsx4(
|
|
837
|
+
/* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
838
|
+
question && /* @__PURE__ */ jsx4(Text6, { color: COLORS.muted, children: question }),
|
|
839
|
+
helpText && /* @__PURE__ */ jsx4(Text6, { color: COLORS.dim, children: helpText })
|
|
713
840
|
] })
|
|
714
841
|
] }),
|
|
715
842
|
/* @__PURE__ */ jsx4(ScrollView, { scroll, children: visible.map((option, visibleIndex) => {
|
|
@@ -719,39 +846,39 @@ function SelectPrompt({
|
|
|
719
846
|
const bullet = multi && !isCancel ? checked.has(i) ? "\u25CF " : "\u25CB " : "";
|
|
720
847
|
const sec = isCancel ? void 0 : secondary?.[i];
|
|
721
848
|
const labelColor = highlighted ? COLORS.highlight.fg : void 0;
|
|
722
|
-
const label = /* @__PURE__ */
|
|
849
|
+
const label = /* @__PURE__ */ jsxs5(Text6, { color: labelColor, wrap: "truncate", children: [
|
|
723
850
|
highlighted ? "\u276F " : " ",
|
|
724
851
|
bullet,
|
|
725
852
|
option
|
|
726
853
|
] });
|
|
727
854
|
const isText = sec?.kind === "text";
|
|
728
|
-
return /* @__PURE__ */
|
|
729
|
-
|
|
855
|
+
return /* @__PURE__ */ jsxs5(
|
|
856
|
+
Box6,
|
|
730
857
|
{
|
|
731
858
|
width: isText ? "100%" : barWidth,
|
|
732
859
|
paddingX: 1,
|
|
733
860
|
paddingY: 1,
|
|
734
861
|
backgroundColor: highlighted ? COLORS.highlight.bg : void 0,
|
|
735
862
|
children: [
|
|
736
|
-
/* @__PURE__ */ jsx4(
|
|
737
|
-
isText && textWidth > 0 && /* @__PURE__ */ jsx4(
|
|
738
|
-
|
|
863
|
+
/* @__PURE__ */ jsx4(Box6, { width: isText ? labelWidth : barLabelWidth, children: label }),
|
|
864
|
+
isText && textWidth > 0 && /* @__PURE__ */ jsx4(Box6, { width: textWidth, children: /* @__PURE__ */ jsx4(
|
|
865
|
+
Text6,
|
|
739
866
|
{
|
|
740
867
|
wrap: "truncate",
|
|
741
868
|
color: highlighted ? COLORS.primary : COLORS.muted,
|
|
742
869
|
children: sec.value
|
|
743
870
|
}
|
|
744
871
|
) }),
|
|
745
|
-
sec?.kind === "badge" && /* @__PURE__ */ jsx4(
|
|
872
|
+
sec?.kind === "badge" && /* @__PURE__ */ jsx4(Box6, { width: badgeWidth, justifyContent: "flex-end", children: /* @__PURE__ */ jsx4(Text6, { color: COLORS.badge, wrap: "truncate", children: sec.value }) })
|
|
746
873
|
]
|
|
747
874
|
},
|
|
748
875
|
`row-${i}`
|
|
749
876
|
);
|
|
750
877
|
}) }),
|
|
751
|
-
/* @__PURE__ */ jsx4(
|
|
878
|
+
/* @__PURE__ */ jsx4(Box6, { flexShrink: 0, children: /* @__PURE__ */ jsx4(Text6, { children: hints.map(({ key, label }, i) => /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
752
879
|
i > 0 ? " " : "",
|
|
753
|
-
/* @__PURE__ */ jsx4(
|
|
754
|
-
/* @__PURE__ */
|
|
880
|
+
/* @__PURE__ */ jsx4(Text6, { color: COLORS.primary, children: key }),
|
|
881
|
+
/* @__PURE__ */ jsxs5(Text6, { color: COLORS.dim, children: [
|
|
755
882
|
" ",
|
|
756
883
|
label
|
|
757
884
|
] })
|
|
@@ -760,7 +887,7 @@ function SelectPrompt({
|
|
|
760
887
|
}
|
|
761
888
|
|
|
762
889
|
// src/ui/PromptInput.tsx
|
|
763
|
-
import { jsx as jsx5, jsxs as
|
|
890
|
+
import { jsx as jsx5, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
764
891
|
var ACCEPT_REJECT_OPTIONS = ["Accept", "Reject"];
|
|
765
892
|
function EnterToContinuePrompt({
|
|
766
893
|
question,
|
|
@@ -771,10 +898,10 @@ function EnterToContinuePrompt({
|
|
|
771
898
|
if (key.return) onDecide(true);
|
|
772
899
|
else if (key.escape) onDecide(false);
|
|
773
900
|
});
|
|
774
|
-
return /* @__PURE__ */
|
|
775
|
-
messages?.map((m, i) => /* @__PURE__ */ jsx5(
|
|
776
|
-
question && /* @__PURE__ */ jsx5(
|
|
777
|
-
/* @__PURE__ */
|
|
901
|
+
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", gap: 1, children: [
|
|
902
|
+
messages?.map((m, i) => /* @__PURE__ */ jsx5(Text7, { color: COLORS.muted, children: m }, `msg-${i}`)),
|
|
903
|
+
question && /* @__PURE__ */ jsx5(Text7, { color: COLORS.primary, children: question }),
|
|
904
|
+
/* @__PURE__ */ jsxs6(Box7, { gap: 1, flexDirection: "column", children: [
|
|
778
905
|
/* @__PURE__ */ jsx5(NextAction, { action: "continue", keyHint: "enter" }),
|
|
779
906
|
/* @__PURE__ */ jsx5(NextAction, { action: "decline", keyHint: "esc", hierarchy: "secondary" })
|
|
780
907
|
] })
|
|
@@ -784,11 +911,11 @@ function PromptInput() {
|
|
|
784
911
|
const { phase, inputReq, submitInput } = useWizard();
|
|
785
912
|
const [draft, setDraft] = useState5("");
|
|
786
913
|
if (phase === "done" || phase === "error") {
|
|
787
|
-
return /* @__PURE__ */ jsx5(
|
|
914
|
+
return /* @__PURE__ */ jsx5(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text7, { color: "gray", dimColor: true, children: "Press Enter or Esc to exit" }) });
|
|
788
915
|
}
|
|
789
916
|
if (phase !== "awaitingInput" || !inputReq) return null;
|
|
790
917
|
if (inputReq.promptType === "multipleChoice") {
|
|
791
|
-
return /* @__PURE__ */ jsx5(
|
|
918
|
+
return /* @__PURE__ */ jsx5(Box7, { flexGrow: 1, children: /* @__PURE__ */ jsx5(
|
|
792
919
|
SelectPrompt,
|
|
793
920
|
{
|
|
794
921
|
question: inputReq.prompt,
|
|
@@ -805,7 +932,7 @@ function PromptInput() {
|
|
|
805
932
|
) });
|
|
806
933
|
}
|
|
807
934
|
if (inputReq.promptType === "multiSelect") {
|
|
808
|
-
return /* @__PURE__ */ jsx5(
|
|
935
|
+
return /* @__PURE__ */ jsx5(Box7, { flexGrow: 1, children: /* @__PURE__ */ jsx5(
|
|
809
936
|
SelectPrompt,
|
|
810
937
|
{
|
|
811
938
|
multi: true,
|
|
@@ -820,7 +947,7 @@ function PromptInput() {
|
|
|
820
947
|
) });
|
|
821
948
|
}
|
|
822
949
|
if (inputReq.promptType === "notice") {
|
|
823
|
-
return /* @__PURE__ */ jsx5(
|
|
950
|
+
return /* @__PURE__ */ jsx5(Box7, { flexGrow: 1, children: /* @__PURE__ */ jsx5(
|
|
824
951
|
SelectPrompt,
|
|
825
952
|
{
|
|
826
953
|
question: inputReq.prompt,
|
|
@@ -842,7 +969,7 @@ function PromptInput() {
|
|
|
842
969
|
}
|
|
843
970
|
if (inputReq.promptType === "acceptReject") {
|
|
844
971
|
const labels = inputReq.options?.length ? inputReq.options : ACCEPT_REJECT_OPTIONS;
|
|
845
|
-
return /* @__PURE__ */ jsx5(
|
|
972
|
+
return /* @__PURE__ */ jsx5(Box7, { flexGrow: 1, children: /* @__PURE__ */ jsx5(
|
|
846
973
|
SelectPrompt,
|
|
847
974
|
{
|
|
848
975
|
question: inputReq.prompt,
|
|
@@ -853,11 +980,11 @@ function PromptInput() {
|
|
|
853
980
|
}
|
|
854
981
|
) });
|
|
855
982
|
}
|
|
856
|
-
return /* @__PURE__ */
|
|
857
|
-
inputReq.error && /* @__PURE__ */ jsx5(
|
|
858
|
-
inputReq.messages?.map((m, i) => /* @__PURE__ */ jsx5(
|
|
859
|
-
/* @__PURE__ */
|
|
860
|
-
/* @__PURE__ */
|
|
983
|
+
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
|
|
984
|
+
inputReq.error && /* @__PURE__ */ jsx5(Text7, { color: COLORS.danger, children: inputReq.error }),
|
|
985
|
+
inputReq.messages?.map((m, i) => /* @__PURE__ */ jsx5(Text7, { color: COLORS.muted, children: m }, `msg-${i}`)),
|
|
986
|
+
/* @__PURE__ */ jsxs6(Box7, { children: [
|
|
987
|
+
/* @__PURE__ */ jsxs6(Text7, { color: COLORS.primary, children: [
|
|
861
988
|
inputReq.prompt,
|
|
862
989
|
" "
|
|
863
990
|
] }),
|
|
@@ -879,7 +1006,7 @@ function PromptInput() {
|
|
|
879
1006
|
// src/ui/Welcome.tsx
|
|
880
1007
|
import { dirname as dirname2, join as join3 } from "node:path";
|
|
881
1008
|
import { fileURLToPath } from "node:url";
|
|
882
|
-
import { Box as
|
|
1009
|
+
import { Box as Box8, Spacer, Text as Text8, useInput as useInput3, useWindowSize as useWindowSize6 } from "ink";
|
|
883
1010
|
|
|
884
1011
|
// src/ui/copy/welcome.ts
|
|
885
1012
|
var sidebarItems = [
|
|
@@ -907,27 +1034,27 @@ var sidebarItems = [
|
|
|
907
1034
|
|
|
908
1035
|
// src/ui/Welcome.tsx
|
|
909
1036
|
import Image, { InkPictureProvider } from "ink-picture";
|
|
910
|
-
import { jsx as jsx6, jsxs as
|
|
1037
|
+
import { jsx as jsx6, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
911
1038
|
var IMAGE_PATH = join3(dirname2(fileURLToPath(import.meta.url)), "algolia.png");
|
|
912
1039
|
function SidebarItem({
|
|
913
1040
|
title,
|
|
914
1041
|
description
|
|
915
1042
|
}) {
|
|
916
|
-
return /* @__PURE__ */
|
|
917
|
-
/* @__PURE__ */
|
|
918
|
-
/* @__PURE__ */ jsx6(
|
|
919
|
-
/* @__PURE__ */ jsx6(
|
|
1043
|
+
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", children: [
|
|
1044
|
+
/* @__PURE__ */ jsxs7(Box8, { gap: 1, children: [
|
|
1045
|
+
/* @__PURE__ */ jsx6(Text8, { color: COLORS.success, children: "\u2192" }),
|
|
1046
|
+
/* @__PURE__ */ jsx6(Text8, { color: COLORS.strong, bold: true, children: title })
|
|
920
1047
|
] }),
|
|
921
|
-
/* @__PURE__ */
|
|
1048
|
+
/* @__PURE__ */ jsxs7(Box8, { flexDirection: "row", gap: 2, children: [
|
|
922
1049
|
/* @__PURE__ */ jsx6(Spacer, {}),
|
|
923
|
-
/* @__PURE__ */ jsx6(
|
|
1050
|
+
/* @__PURE__ */ jsx6(Text8, { color: COLORS.muted, children: description })
|
|
924
1051
|
] })
|
|
925
1052
|
] });
|
|
926
1053
|
}
|
|
927
1054
|
function Welcome() {
|
|
928
1055
|
const confirmStart = useWizard((s) => s.confirmStart);
|
|
929
1056
|
const openLearnMore = useWizard((s) => s.openLearnMore);
|
|
930
|
-
const { rows } =
|
|
1057
|
+
const { rows } = useWindowSize6();
|
|
931
1058
|
useInput3((input, key) => {
|
|
932
1059
|
if (key.return) confirmStart();
|
|
933
1060
|
else if (input === "i") openLearnMore();
|
|
@@ -946,15 +1073,15 @@ function Welcome() {
|
|
|
946
1073
|
if (rows < 30) {
|
|
947
1074
|
layout = scales["small"];
|
|
948
1075
|
}
|
|
949
|
-
return /* @__PURE__ */
|
|
1076
|
+
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "row", justifyContent: "space-between", width: "100%", children: [
|
|
950
1077
|
/* @__PURE__ */ jsx6(
|
|
951
|
-
|
|
1078
|
+
Box8,
|
|
952
1079
|
{
|
|
953
1080
|
paddingY: layout.main.padding.y,
|
|
954
1081
|
paddingX: layout.main.padding.x,
|
|
955
1082
|
flexDirection: "column",
|
|
956
1083
|
justifyContent: "center",
|
|
957
|
-
children: /* @__PURE__ */
|
|
1084
|
+
children: /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 2, children: [
|
|
958
1085
|
/* @__PURE__ */ jsx6(InkPictureProvider, { children: /* @__PURE__ */ jsx6(
|
|
959
1086
|
Image,
|
|
960
1087
|
{
|
|
@@ -966,16 +1093,16 @@ function Welcome() {
|
|
|
966
1093
|
protocol: "halfBlock"
|
|
967
1094
|
}
|
|
968
1095
|
) }),
|
|
969
|
-
/* @__PURE__ */ jsx6(
|
|
970
|
-
/* @__PURE__ */
|
|
1096
|
+
/* @__PURE__ */ jsx6(Text8, { color: COLORS.muted, children: "\u2726 From zero \u2192 working search in ~10 minutes" }),
|
|
1097
|
+
/* @__PURE__ */ jsxs7(Box8, { gap: 1, flexDirection: "column", children: [
|
|
971
1098
|
/* @__PURE__ */ jsx6(NextAction, { action: "start wizard", keyHint: "enter" }),
|
|
972
1099
|
/* @__PURE__ */ jsx6(NextAction, { action: "learn more", keyHint: "i", hierarchy: "secondary" })
|
|
973
1100
|
] })
|
|
974
1101
|
] })
|
|
975
1102
|
}
|
|
976
1103
|
),
|
|
977
|
-
/* @__PURE__ */
|
|
978
|
-
|
|
1104
|
+
/* @__PURE__ */ jsxs7(
|
|
1105
|
+
Box8,
|
|
979
1106
|
{
|
|
980
1107
|
backgroundColor: COLORS.bg.sidebar,
|
|
981
1108
|
width: 40,
|
|
@@ -985,7 +1112,7 @@ function Welcome() {
|
|
|
985
1112
|
flexDirection: "column",
|
|
986
1113
|
justifyContent: "center",
|
|
987
1114
|
children: [
|
|
988
|
-
/* @__PURE__ */ jsx6(
|
|
1115
|
+
/* @__PURE__ */ jsx6(Text8, { color: COLORS.muted, children: "WHAT THIS WIZARD WILL DO" }),
|
|
989
1116
|
sidebarItems.map((i, idx) => /* @__PURE__ */ jsx6(SidebarItem, { title: i.title, description: i.description }, idx))
|
|
990
1117
|
]
|
|
991
1118
|
}
|
|
@@ -995,7 +1122,7 @@ function Welcome() {
|
|
|
995
1122
|
|
|
996
1123
|
// src/ui/LearnMore.tsx
|
|
997
1124
|
import { Fragment as Fragment2 } from "react";
|
|
998
|
-
import { Box as
|
|
1125
|
+
import { Box as Box9, Text as Text9, useInput as useInput4, useWindowSize as useWindowSize7 } from "ink";
|
|
999
1126
|
|
|
1000
1127
|
// src/ui/copy/learn-more.ts
|
|
1001
1128
|
var accessIntro = "Everything runs locally on your machine. Nothing is written or sent without an explicit yes from you.";
|
|
@@ -1032,7 +1159,7 @@ var policyLinks = [
|
|
|
1032
1159
|
];
|
|
1033
1160
|
|
|
1034
1161
|
// src/ui/LearnMore.tsx
|
|
1035
|
-
import { jsx as jsx7, jsxs as
|
|
1162
|
+
import { jsx as jsx7, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1036
1163
|
var TAG_COLORS = {
|
|
1037
1164
|
READ: COLORS.success,
|
|
1038
1165
|
WRITE: COLORS.badge,
|
|
@@ -1048,25 +1175,25 @@ function NeverLine({
|
|
|
1048
1175
|
}) {
|
|
1049
1176
|
const used = segments.reduce((n, s) => n + s.text.length, 0);
|
|
1050
1177
|
const rightPad = Math.max(0, width - 2 - NEVER_BOX_PAD_X - used);
|
|
1051
|
-
return /* @__PURE__ */
|
|
1052
|
-
/* @__PURE__ */ jsx7(
|
|
1178
|
+
return /* @__PURE__ */ jsxs8(Text9, { children: [
|
|
1179
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.danger, children: "\u2502" }),
|
|
1053
1180
|
" ".repeat(NEVER_BOX_PAD_X),
|
|
1054
|
-
segments.map((s, i) => /* @__PURE__ */ jsx7(
|
|
1181
|
+
segments.map((s, i) => /* @__PURE__ */ jsx7(Text9, { color: s.color, bold: s.bold, children: s.text }, i)),
|
|
1055
1182
|
" ".repeat(rightPad),
|
|
1056
|
-
/* @__PURE__ */ jsx7(
|
|
1183
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.danger, children: "\u2502" })
|
|
1057
1184
|
] });
|
|
1058
1185
|
}
|
|
1059
1186
|
function LearnMore() {
|
|
1060
1187
|
const confirmStart = useWizard((s) => s.confirmStart);
|
|
1061
1188
|
const backToHome = useWizard((s) => s.backToHome);
|
|
1062
|
-
const { columns } =
|
|
1189
|
+
const { columns } = useWindowSize7();
|
|
1063
1190
|
const dividerWidth = Math.max(0, columns - PADDING_X * 2);
|
|
1064
1191
|
useInput4((_input, key) => {
|
|
1065
1192
|
if (key.escape) backToHome();
|
|
1066
1193
|
else if (key.return) confirmStart();
|
|
1067
1194
|
});
|
|
1068
|
-
return /* @__PURE__ */
|
|
1069
|
-
|
|
1195
|
+
return /* @__PURE__ */ jsxs8(
|
|
1196
|
+
Box9,
|
|
1070
1197
|
{
|
|
1071
1198
|
flexDirection: "column",
|
|
1072
1199
|
paddingX: PADDING_X,
|
|
@@ -1074,20 +1201,20 @@ function LearnMore() {
|
|
|
1074
1201
|
width: "100%",
|
|
1075
1202
|
gap: 1,
|
|
1076
1203
|
children: [
|
|
1077
|
-
/* @__PURE__ */ jsx7(
|
|
1078
|
-
/* @__PURE__ */ jsx7(
|
|
1079
|
-
/* @__PURE__ */ jsx7(
|
|
1080
|
-
/* @__PURE__ */ jsx7(
|
|
1081
|
-
/* @__PURE__ */
|
|
1082
|
-
/* @__PURE__ */ jsx7(
|
|
1083
|
-
/* @__PURE__ */ jsx7(
|
|
1084
|
-
/* @__PURE__ */ jsx7(
|
|
1085
|
-
/* @__PURE__ */ jsx7(
|
|
1204
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.strong, bold: true, children: "What algolia wizard accesses" }),
|
|
1205
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: accessIntro }),
|
|
1206
|
+
/* @__PURE__ */ jsx7(Box9, { flexDirection: "column", children: accessItems.map((item) => /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", marginTop: 1, children: [
|
|
1207
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.border, children: "\u2500".repeat(dividerWidth) }),
|
|
1208
|
+
/* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", gap: 1, marginTop: 1, children: [
|
|
1209
|
+
/* @__PURE__ */ jsx7(Box9, { width: TAG_COLUMN_WIDTH, flexShrink: 0, children: /* @__PURE__ */ jsx7(Text9, { color: TAG_COLORS[item.tag], bold: true, children: `[${item.tag}]` }) }),
|
|
1210
|
+
/* @__PURE__ */ jsx7(Box9, { flexDirection: "column", children: /* @__PURE__ */ jsxs8(Text9, { children: [
|
|
1211
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.strong, bold: true, children: item.title }),
|
|
1212
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: ` \u2014 ${item.description}` })
|
|
1086
1213
|
] }) })
|
|
1087
1214
|
] })
|
|
1088
1215
|
] }, item.tag)) }),
|
|
1089
|
-
/* @__PURE__ */
|
|
1090
|
-
/* @__PURE__ */ jsx7(
|
|
1216
|
+
/* @__PURE__ */ jsxs8(Box9, { marginTop: 1, flexDirection: "column", children: [
|
|
1217
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.danger, children: `\u256D${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256E` }),
|
|
1091
1218
|
/* @__PURE__ */ jsx7(NeverLine, { width: dividerWidth }),
|
|
1092
1219
|
/* @__PURE__ */ jsx7(
|
|
1093
1220
|
NeverLine,
|
|
@@ -1096,7 +1223,7 @@ function LearnMore() {
|
|
|
1096
1223
|
segments: [{ text: "I NEVER", color: COLORS.danger, bold: true }]
|
|
1097
1224
|
}
|
|
1098
1225
|
),
|
|
1099
|
-
neverItems.map((item) => /* @__PURE__ */
|
|
1226
|
+
neverItems.map((item) => /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
1100
1227
|
/* @__PURE__ */ jsx7(NeverLine, { width: dividerWidth }),
|
|
1101
1228
|
/* @__PURE__ */ jsx7(
|
|
1102
1229
|
NeverLine,
|
|
@@ -1111,23 +1238,23 @@ function LearnMore() {
|
|
|
1111
1238
|
)
|
|
1112
1239
|
] }, item)),
|
|
1113
1240
|
/* @__PURE__ */ jsx7(NeverLine, { width: dividerWidth }),
|
|
1114
|
-
/* @__PURE__ */ jsx7(
|
|
1241
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.danger, children: `\u2570${"\u2500".repeat(Math.max(0, dividerWidth - 2))}\u256F` })
|
|
1115
1242
|
] }),
|
|
1116
|
-
/* @__PURE__ */ jsx7(
|
|
1117
|
-
/* @__PURE__ */ jsx7(
|
|
1118
|
-
/* @__PURE__ */ jsx7(
|
|
1243
|
+
/* @__PURE__ */ jsx7(Box9, { marginTop: 1, flexDirection: "column", children: policyLinks.map((link) => /* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", gap: 1, children: [
|
|
1244
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.strong, bold: true, children: `${link.label}:` }),
|
|
1245
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.accent, children: link.url })
|
|
1119
1246
|
] }, link.label)) }),
|
|
1120
|
-
/* @__PURE__ */
|
|
1121
|
-
/* @__PURE__ */
|
|
1122
|
-
/* @__PURE__ */ jsx7(
|
|
1123
|
-
/* @__PURE__ */ jsx7(
|
|
1124
|
-
/* @__PURE__ */ jsx7(
|
|
1247
|
+
/* @__PURE__ */ jsxs8(Box9, { marginTop: 1, flexDirection: "row", gap: 3, children: [
|
|
1248
|
+
/* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", gap: 1, children: [
|
|
1249
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: "[" }),
|
|
1250
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.primary, children: "esc" }),
|
|
1251
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: "] back" })
|
|
1125
1252
|
] }),
|
|
1126
|
-
/* @__PURE__ */
|
|
1127
|
-
/* @__PURE__ */ jsx7(
|
|
1128
|
-
/* @__PURE__ */ jsx7(
|
|
1129
|
-
/* @__PURE__ */ jsx7(
|
|
1130
|
-
/* @__PURE__ */ jsx7(
|
|
1253
|
+
/* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", gap: 1, children: [
|
|
1254
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: "[" }),
|
|
1255
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.primary, children: "enter" }),
|
|
1256
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.muted, children: "]" }),
|
|
1257
|
+
/* @__PURE__ */ jsx7(Text9, { color: COLORS.success, bold: true, children: "start wizard" })
|
|
1131
1258
|
] })
|
|
1132
1259
|
] })
|
|
1133
1260
|
]
|
|
@@ -1136,10 +1263,10 @@ function LearnMore() {
|
|
|
1136
1263
|
}
|
|
1137
1264
|
|
|
1138
1265
|
// src/ui/Sidebar.tsx
|
|
1139
|
-
import { Box as
|
|
1266
|
+
import { Box as Box12, Text as Text12 } from "ink";
|
|
1140
1267
|
|
|
1141
1268
|
// src/ui/Steps.tsx
|
|
1142
|
-
import { Box as
|
|
1269
|
+
import { Box as Box10, Text as Text10 } from "ink";
|
|
1143
1270
|
import Spinner from "ink-spinner";
|
|
1144
1271
|
|
|
1145
1272
|
// src/core/persistence.ts
|
|
@@ -1168,11 +1295,11 @@ async function clearWorkflowState(workflowId) {
|
|
|
1168
1295
|
}
|
|
1169
1296
|
|
|
1170
1297
|
// src/ui/Steps.tsx
|
|
1171
|
-
import { jsx as jsx8, jsxs as
|
|
1298
|
+
import { jsx as jsx8, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1172
1299
|
function Steps() {
|
|
1173
1300
|
const { steps } = useWizard();
|
|
1174
1301
|
const visibleSteps = steps.filter(isStepVisible);
|
|
1175
|
-
return /* @__PURE__ */ jsx8(
|
|
1302
|
+
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: [
|
|
1176
1303
|
s.status === "running" ? /* @__PURE__ */ jsx8(Spinner, { type: "dots" }) : MARKER[s.status],
|
|
1177
1304
|
" ",
|
|
1178
1305
|
s.title
|
|
@@ -1182,7 +1309,7 @@ function CurrentStep() {
|
|
|
1182
1309
|
const { steps } = useWizard();
|
|
1183
1310
|
const currentStep = steps.filter(isStepVisible).find((s) => s.status === "running");
|
|
1184
1311
|
if (!currentStep) return null;
|
|
1185
|
-
return /* @__PURE__ */
|
|
1312
|
+
return /* @__PURE__ */ jsxs9(Text10, { color: COLORS.status.running, children: [
|
|
1186
1313
|
/* @__PURE__ */ jsx8(Spinner, { type: "dots" }),
|
|
1187
1314
|
" ",
|
|
1188
1315
|
` ${currentStep.title}`
|
|
@@ -1190,19 +1317,19 @@ function CurrentStep() {
|
|
|
1190
1317
|
}
|
|
1191
1318
|
|
|
1192
1319
|
// src/ui/Progress.tsx
|
|
1193
|
-
import { Box as
|
|
1194
|
-
import { jsx as jsx9, jsxs as
|
|
1320
|
+
import { Box as Box11, Text as Text11 } from "ink";
|
|
1321
|
+
import { jsx as jsx9, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1195
1322
|
function Progress() {
|
|
1196
1323
|
const { steps, currentStepIndex } = useWizard();
|
|
1197
1324
|
const visibleSteps = steps.filter(isStepVisible);
|
|
1198
1325
|
if (visibleSteps.length === 0) return null;
|
|
1199
1326
|
const visibleCountThroughCurrent = steps.slice(0, currentStepIndex + 1).filter(isStepVisible).length;
|
|
1200
1327
|
const activeStepNumber = Math.max(1, visibleCountThroughCurrent);
|
|
1201
|
-
return /* @__PURE__ */
|
|
1202
|
-
/* @__PURE__ */ jsx9(
|
|
1203
|
-
/* @__PURE__ */ jsx9(
|
|
1204
|
-
/* @__PURE__ */ jsx9(
|
|
1205
|
-
/* @__PURE__ */ jsx9(
|
|
1328
|
+
return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "row", gap: 1, children: [
|
|
1329
|
+
/* @__PURE__ */ jsx9(Text11, { color: COLORS.muted, children: "STEP" }),
|
|
1330
|
+
/* @__PURE__ */ jsx9(Text11, { bold: true, children: activeStepNumber }),
|
|
1331
|
+
/* @__PURE__ */ jsx9(Text11, { bold: true, children: "/" }),
|
|
1332
|
+
/* @__PURE__ */ jsx9(Text11, { bold: true, children: visibleSteps.length })
|
|
1206
1333
|
] });
|
|
1207
1334
|
}
|
|
1208
1335
|
|
|
@@ -1213,10 +1340,10 @@ var sidebarCommands = [
|
|
|
1213
1340
|
];
|
|
1214
1341
|
|
|
1215
1342
|
// src/ui/Sidebar.tsx
|
|
1216
|
-
import { jsx as jsx10, jsxs as
|
|
1343
|
+
import { jsx as jsx10, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1217
1344
|
function Sidebar() {
|
|
1218
|
-
return /* @__PURE__ */
|
|
1219
|
-
|
|
1345
|
+
return /* @__PURE__ */ jsxs11(
|
|
1346
|
+
Box12,
|
|
1220
1347
|
{
|
|
1221
1348
|
backgroundColor: "#14171E",
|
|
1222
1349
|
width: 30,
|
|
@@ -1225,16 +1352,16 @@ function Sidebar() {
|
|
|
1225
1352
|
flexDirection: "column",
|
|
1226
1353
|
justifyContent: "space-between",
|
|
1227
1354
|
children: [
|
|
1228
|
-
/* @__PURE__ */
|
|
1229
|
-
/* @__PURE__ */ jsx10(
|
|
1355
|
+
/* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", gap: 1, children: [
|
|
1356
|
+
/* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: "PROGRESS" }),
|
|
1230
1357
|
/* @__PURE__ */ jsx10(Steps, {})
|
|
1231
1358
|
] }),
|
|
1232
|
-
/* @__PURE__ */
|
|
1359
|
+
/* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", gap: 1, children: [
|
|
1233
1360
|
/* @__PURE__ */ jsx10(Progress, {}),
|
|
1234
|
-
/* @__PURE__ */ jsx10(
|
|
1235
|
-
return /* @__PURE__ */
|
|
1236
|
-
/* @__PURE__ */ jsx10(
|
|
1237
|
-
/* @__PURE__ */ jsx10(
|
|
1361
|
+
/* @__PURE__ */ jsx10(Box12, { flexDirection: "column", children: sidebarCommands.map((c) => {
|
|
1362
|
+
return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "row", gap: 1, children: [
|
|
1363
|
+
/* @__PURE__ */ jsx10(Text12, { color: COLORS.primary, children: `[${c.keyHint}]` }),
|
|
1364
|
+
/* @__PURE__ */ jsx10(Text12, { color: COLORS.muted, children: c.description })
|
|
1238
1365
|
] });
|
|
1239
1366
|
}) })
|
|
1240
1367
|
] })
|
|
@@ -1244,12 +1371,12 @@ function Sidebar() {
|
|
|
1244
1371
|
}
|
|
1245
1372
|
|
|
1246
1373
|
// src/ui/Ribbon.tsx
|
|
1247
|
-
import { Box as
|
|
1248
|
-
import { jsx as jsx11, jsxs as
|
|
1374
|
+
import { Box as Box13, Text as Text13 } from "ink";
|
|
1375
|
+
import { jsx as jsx11, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1249
1376
|
function Ribbon() {
|
|
1250
1377
|
const firstCommand = sidebarCommands[0];
|
|
1251
|
-
return /* @__PURE__ */
|
|
1252
|
-
|
|
1378
|
+
return /* @__PURE__ */ jsxs12(
|
|
1379
|
+
Box13,
|
|
1253
1380
|
{
|
|
1254
1381
|
backgroundColor: "#14171E",
|
|
1255
1382
|
flexDirection: "row",
|
|
@@ -1259,9 +1386,9 @@ function Ribbon() {
|
|
|
1259
1386
|
children: [
|
|
1260
1387
|
/* @__PURE__ */ jsx11(Progress, {}),
|
|
1261
1388
|
/* @__PURE__ */ jsx11(CurrentStep, {}),
|
|
1262
|
-
/* @__PURE__ */
|
|
1263
|
-
/* @__PURE__ */ jsx11(
|
|
1264
|
-
/* @__PURE__ */ jsx11(
|
|
1389
|
+
/* @__PURE__ */ jsxs12(Box13, { flexDirection: "row", gap: 1, children: [
|
|
1390
|
+
/* @__PURE__ */ jsx11(Text13, { color: COLORS.primary, children: `[${firstCommand.keyHint}]` }),
|
|
1391
|
+
/* @__PURE__ */ jsx11(Text13, { color: COLORS.muted, children: firstCommand.description })
|
|
1265
1392
|
] })
|
|
1266
1393
|
]
|
|
1267
1394
|
}
|
|
@@ -1272,8 +1399,8 @@ function Ribbon() {
|
|
|
1272
1399
|
import { useState as useState6 } from "react";
|
|
1273
1400
|
|
|
1274
1401
|
// src/ui/Logs.tsx
|
|
1275
|
-
import { Box as
|
|
1276
|
-
import { jsx as jsx12, jsxs as
|
|
1402
|
+
import { Box as Box14, Text as Text14, useInput as useInput5 } from "ink";
|
|
1403
|
+
import { jsx as jsx12, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1277
1404
|
var KIND_COLOR = {
|
|
1278
1405
|
tool: COLORS.primary,
|
|
1279
1406
|
prompt: COLORS.badge
|
|
@@ -1309,8 +1436,8 @@ function Logs() {
|
|
|
1309
1436
|
else if (key.downArrow) scroll.scrollBy(1);
|
|
1310
1437
|
});
|
|
1311
1438
|
const visible = logs.slice(scroll.offset, scroll.offset + scroll.capacity);
|
|
1312
|
-
return /* @__PURE__ */
|
|
1313
|
-
logs.length === 0 && /* @__PURE__ */ jsx12(
|
|
1439
|
+
return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", paddingX: 4, paddingY: 2, flexGrow: 1, children: [
|
|
1440
|
+
logs.length === 0 && /* @__PURE__ */ jsx12(Text14, { color: COLORS.dim, children: "No logs yet." }),
|
|
1314
1441
|
/* @__PURE__ */ jsx12(ScrollView, { scroll, children: visible.map((entry) => {
|
|
1315
1442
|
const timestamp = `[${formatTimestamp(entry.startedAt)}]`;
|
|
1316
1443
|
const durationText = entry.kind === "tool" && entry.durationMs !== void 0 ? `${entry.durationMs}ms` : "";
|
|
@@ -1321,14 +1448,14 @@ function Logs() {
|
|
|
1321
1448
|
const name = truncate2(entry.name, budget);
|
|
1322
1449
|
budget -= name.length;
|
|
1323
1450
|
const preview = rawPreview ? truncate2(rawPreview, budget) : "";
|
|
1324
|
-
return /* @__PURE__ */
|
|
1325
|
-
/* @__PURE__ */ jsx12(
|
|
1326
|
-
/* @__PURE__ */ jsx12(
|
|
1327
|
-
preview && /* @__PURE__ */ jsx12(
|
|
1328
|
-
durationText && /* @__PURE__ */ jsx12(
|
|
1451
|
+
return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "row", gap: ROW_GAP, children: [
|
|
1452
|
+
/* @__PURE__ */ jsx12(Text14, { color: COLORS.dim, children: timestamp }),
|
|
1453
|
+
/* @__PURE__ */ jsx12(Text14, { color: logNameColor(entry), wrap: "truncate", children: name }),
|
|
1454
|
+
preview && /* @__PURE__ */ jsx12(Text14, { color: COLORS.dim, wrap: "truncate", children: preview }),
|
|
1455
|
+
durationText && /* @__PURE__ */ jsx12(Text14, { color: COLORS.dim, children: durationText })
|
|
1329
1456
|
] }, entry.id);
|
|
1330
1457
|
}) }),
|
|
1331
|
-
/* @__PURE__ */ jsx12(
|
|
1458
|
+
/* @__PURE__ */ jsx12(Text14, { color: COLORS.dim, children: "\u2191/\u2193 scroll" })
|
|
1332
1459
|
] });
|
|
1333
1460
|
}
|
|
1334
1461
|
|
|
@@ -1520,11 +1647,11 @@ function track(event, payload) {
|
|
|
1520
1647
|
}
|
|
1521
1648
|
|
|
1522
1649
|
// src/ui/App.tsx
|
|
1523
|
-
import { jsx as jsx13, jsxs as
|
|
1650
|
+
import { jsx as jsx13, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1524
1651
|
function App() {
|
|
1525
1652
|
const { phase, error, homeScreen, currentStepIndex, steps, inputReq } = useWizard();
|
|
1526
1653
|
const { exit } = useApp();
|
|
1527
|
-
const { columns, rows } =
|
|
1654
|
+
const { columns, rows } = useWindowSize8();
|
|
1528
1655
|
const [showLogs, setShowLogs] = useState6(false);
|
|
1529
1656
|
const finished = phase === "done" || phase === "error";
|
|
1530
1657
|
const currentStep = steps[currentStepIndex];
|
|
@@ -1537,7 +1664,7 @@ function App() {
|
|
|
1537
1664
|
{ isActive: finished }
|
|
1538
1665
|
);
|
|
1539
1666
|
useInput6((_input, key) => {
|
|
1540
|
-
if (phase === "idle" || phase === "
|
|
1667
|
+
if (phase === "idle" || phase === "authenticating") return;
|
|
1541
1668
|
if (key.tab) {
|
|
1542
1669
|
setShowLogs(!showLogs);
|
|
1543
1670
|
track("AI Wizard Interaction", {
|
|
@@ -1547,7 +1674,7 @@ function App() {
|
|
|
1547
1674
|
});
|
|
1548
1675
|
}
|
|
1549
1676
|
});
|
|
1550
|
-
const escOwnedElsewhere = phase === "idle" || phase === "awaitingInput" && inputReq?.promptType === "enterToContinue";
|
|
1677
|
+
const escOwnedElsewhere = phase === "idle" || phase === "authenticating" || phase === "awaitingInput" && inputReq?.promptType === "enterToContinue";
|
|
1551
1678
|
useInput6((_input, key) => {
|
|
1552
1679
|
if (escOwnedElsewhere) return;
|
|
1553
1680
|
if (key.escape) {
|
|
@@ -1560,61 +1687,71 @@ function App() {
|
|
|
1560
1687
|
exit();
|
|
1561
1688
|
}
|
|
1562
1689
|
});
|
|
1563
|
-
const mainWindowVisible = phase === "running" || phase === "awaitingInput" || phase === "error" || phase === "done";
|
|
1690
|
+
const mainWindowVisible = phase === "authenticating" || phase === "preflight" || phase === "running" || phase === "awaitingInput" || phase === "error" || phase === "done";
|
|
1564
1691
|
const flexDirection = columns > 90 ? "row" : "column";
|
|
1565
1692
|
const showSidebar = flexDirection === "row";
|
|
1566
|
-
|
|
1567
|
-
|
|
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
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
"
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1693
|
+
const scrollsPastViewport = phase === "idle" && homeScreen === "learnMore";
|
|
1694
|
+
return (
|
|
1695
|
+
/* Clamped to exactly the viewport: a taller frame makes Ink clear and repaint
|
|
1696
|
+
the whole screen, and the scrolling throws off its cursor arithmetic —
|
|
1697
|
+
flicker and leftover rows. */
|
|
1698
|
+
/* @__PURE__ */ jsxs14(
|
|
1699
|
+
Box15,
|
|
1700
|
+
{
|
|
1701
|
+
backgroundColor: COLORS.bg.main,
|
|
1702
|
+
flexDirection: "row",
|
|
1703
|
+
width: columns,
|
|
1704
|
+
height: scrollsPastViewport ? void 0 : rows,
|
|
1705
|
+
overflow: scrollsPastViewport ? "visible" : "hidden",
|
|
1706
|
+
children: [
|
|
1707
|
+
mainWindowVisible && // Without a cap the scrolling lists in here grow to their content
|
|
1708
|
+
// instead of windowing (see `useScrollWindow`).
|
|
1709
|
+
/* @__PURE__ */ jsxs14(
|
|
1710
|
+
Box15,
|
|
1711
|
+
{
|
|
1712
|
+
flexDirection,
|
|
1713
|
+
width: "100%",
|
|
1714
|
+
maxHeight: rows,
|
|
1715
|
+
justifyContent: "space-between",
|
|
1716
|
+
children: [
|
|
1717
|
+
showLogs ? /* @__PURE__ */ jsx13(Logs, {}) : (
|
|
1718
|
+
/* Fill the space the sidebar/ribbon leaves — width beside the
|
|
1719
|
+
sidebar, height above the ribbon. The height matters even
|
|
1720
|
+
stacked: it is what the prompt's scrolling list measures itself
|
|
1721
|
+
against (see SelectPrompt). */
|
|
1722
|
+
/* @__PURE__ */ jsxs14(
|
|
1723
|
+
Box15,
|
|
1724
|
+
{
|
|
1725
|
+
flexDirection: "column",
|
|
1726
|
+
paddingX: 4,
|
|
1727
|
+
paddingY: 2,
|
|
1728
|
+
width: showSidebar ? 70 : "100%",
|
|
1729
|
+
flexGrow: 1,
|
|
1730
|
+
children: [
|
|
1731
|
+
phase === "authenticating" && /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", marginBottom: 1, children: [
|
|
1732
|
+
/* @__PURE__ */ jsx13(Text15, { color: COLORS.strong, bold: true, children: "Signing in to Algolia" }),
|
|
1733
|
+
/* @__PURE__ */ jsx13(Text15, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
|
|
1734
|
+
] }),
|
|
1735
|
+
/* @__PURE__ */ jsx13(CliOutput, {}),
|
|
1736
|
+
/* @__PURE__ */ jsx13(Notices, {}),
|
|
1737
|
+
/* @__PURE__ */ jsx13(PromptInput, {}),
|
|
1738
|
+
phase === "running" && showSidebar && /* @__PURE__ */ jsx13(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx13(CurrentStep, {}) }),
|
|
1739
|
+
phase === "error" && error && /* @__PURE__ */ jsx13(Box15, { marginTop: 1, children: /* @__PURE__ */ jsxs14(Text15, { color: COLORS.status.error, children: [
|
|
1740
|
+
"\u2716 ",
|
|
1741
|
+
error
|
|
1742
|
+
] }) })
|
|
1743
|
+
]
|
|
1744
|
+
}
|
|
1745
|
+
)
|
|
1746
|
+
),
|
|
1747
|
+
showSidebar ? /* @__PURE__ */ jsx13(Sidebar, {}) : /* @__PURE__ */ jsx13(Ribbon, {})
|
|
1748
|
+
]
|
|
1749
|
+
}
|
|
1750
|
+
),
|
|
1751
|
+
phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */ jsx13(LearnMore, {}) : /* @__PURE__ */ jsx13(Welcome, {}))
|
|
1752
|
+
]
|
|
1753
|
+
}
|
|
1754
|
+
)
|
|
1618
1755
|
);
|
|
1619
1756
|
}
|
|
1620
1757
|
|
|
@@ -1850,61 +1987,138 @@ async function runWorkflow(workflow, appId) {
|
|
|
1850
1987
|
}
|
|
1851
1988
|
}
|
|
1852
1989
|
|
|
1853
|
-
// src/lib/
|
|
1854
|
-
import {
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1990
|
+
// src/lib/algoliaApp.ts
|
|
1991
|
+
import { z as z4 } from "zod";
|
|
1992
|
+
var applicationSchema = z4.object({
|
|
1993
|
+
id: z4.string().min(1),
|
|
1994
|
+
name: z4.string().default(""),
|
|
1995
|
+
plan: z4.string().optional()
|
|
1996
|
+
});
|
|
1997
|
+
var listSchema = z4.array(
|
|
1998
|
+
z4.object({
|
|
1999
|
+
id: z4.string().min(1),
|
|
2000
|
+
name: z4.string().default(""),
|
|
2001
|
+
plan_label: z4.string().optional()
|
|
2002
|
+
}).transform(({ id, name, plan_label }) => ({ id, name, plan: plan_label }))
|
|
2003
|
+
);
|
|
2004
|
+
async function currentApplication() {
|
|
2005
|
+
let raw;
|
|
1866
2006
|
try {
|
|
1867
|
-
|
|
2007
|
+
raw = await runAlgoliaCli(["application", "current", "-o", "json"]);
|
|
1868
2008
|
} catch {
|
|
1869
|
-
return
|
|
2009
|
+
return null;
|
|
1870
2010
|
}
|
|
1871
|
-
const
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
2011
|
+
const parsed = applicationSchema.safeParse(parseJson(raw));
|
|
2012
|
+
return parsed.success ? parsed.data : null;
|
|
2013
|
+
}
|
|
2014
|
+
async function requireApplication() {
|
|
2015
|
+
const app = await currentApplication();
|
|
2016
|
+
if (!app) {
|
|
2017
|
+
throw new Error(
|
|
2018
|
+
"No Algolia application is selected. Run `npx @algolia/cli@latest application select` and restart the wizard."
|
|
2019
|
+
);
|
|
2020
|
+
}
|
|
2021
|
+
return app;
|
|
2022
|
+
}
|
|
2023
|
+
async function listApplications() {
|
|
2024
|
+
const raw = await runAlgoliaCli(["application", "list", "-o", "json"]);
|
|
2025
|
+
const parsed = listSchema.safeParse(parseJson(raw));
|
|
2026
|
+
if (!parsed.success) {
|
|
2027
|
+
throw new Error("Could not read the list of Algolia applications.");
|
|
2028
|
+
}
|
|
2029
|
+
return parsed.data;
|
|
2030
|
+
}
|
|
2031
|
+
async function selectApplication(id) {
|
|
2032
|
+
const raw = await runAlgoliaCli(
|
|
2033
|
+
["application", "select", "--non-interactive", "--app-id", id],
|
|
2034
|
+
{ onOutput: stderrSink }
|
|
2035
|
+
);
|
|
2036
|
+
const parsed = applicationSchema.safeParse(parseJson(raw));
|
|
2037
|
+
if (!parsed.success) {
|
|
2038
|
+
throw new Error(
|
|
2039
|
+
`Selected application ${id}, but the Algolia CLI returned an unreadable result.`
|
|
2040
|
+
);
|
|
2041
|
+
}
|
|
2042
|
+
return parsed.data;
|
|
2043
|
+
}
|
|
2044
|
+
function parseJson(text) {
|
|
1884
2045
|
try {
|
|
1885
|
-
|
|
2046
|
+
return JSON.parse(text);
|
|
1886
2047
|
} catch {
|
|
1887
|
-
|
|
2048
|
+
return void 0;
|
|
1888
2049
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
// src/lib/algoliaAppPicker.ts
|
|
2053
|
+
function secondaryFor(app) {
|
|
2054
|
+
return app.plan ? { kind: "badge", value: app.plan } : void 0;
|
|
2055
|
+
}
|
|
2056
|
+
function labelFor(app) {
|
|
2057
|
+
return app.name.trim() ? `${app.name} \u2014 ${app.id}` : app.id;
|
|
2058
|
+
}
|
|
2059
|
+
function selectAndReport(app) {
|
|
2060
|
+
useWizard.getState().pushCliOutput(
|
|
2061
|
+
"stdout",
|
|
2062
|
+
`Selecting ${labelFor(app)} \u2014 provisioning its API key\u2026`
|
|
2063
|
+
);
|
|
2064
|
+
return selectApplication(app.id);
|
|
2065
|
+
}
|
|
2066
|
+
async function promptForApplication() {
|
|
2067
|
+
const store = useWizard.getState();
|
|
2068
|
+
const apps = await listApplications();
|
|
2069
|
+
if (apps.length === 0) {
|
|
1891
2070
|
throw new Error(
|
|
1892
|
-
"
|
|
2071
|
+
"This Algolia account has no applications. Create one in the Algolia dashboard, or with `npx @algolia/cli@latest application create`, then restart the wizard."
|
|
2072
|
+
);
|
|
2073
|
+
}
|
|
2074
|
+
if (apps.length === 1) {
|
|
2075
|
+
const only = apps[0];
|
|
2076
|
+
logger.info(
|
|
2077
|
+
{ app: only.id },
|
|
2078
|
+
"single application on the account; selecting it"
|
|
1893
2079
|
);
|
|
2080
|
+
return selectAndReport(only);
|
|
1894
2081
|
}
|
|
1895
|
-
|
|
2082
|
+
const messages = ["Which Algolia application should the wizard work in?"];
|
|
2083
|
+
for (; ; ) {
|
|
2084
|
+
const choice = await store.requestUserInput({
|
|
2085
|
+
prompt: "Select an application",
|
|
2086
|
+
promptType: "multipleChoice",
|
|
2087
|
+
options: apps.map(labelFor),
|
|
2088
|
+
secondary: apps.map(secondaryFor),
|
|
2089
|
+
messages
|
|
2090
|
+
});
|
|
2091
|
+
const chosen = apps.find((app) => labelFor(app) === choice);
|
|
2092
|
+
if (!chosen) {
|
|
2093
|
+
throw new Error("Application picker received an unexpected selection");
|
|
2094
|
+
}
|
|
2095
|
+
try {
|
|
2096
|
+
return await selectAndReport(chosen);
|
|
2097
|
+
} catch (err) {
|
|
2098
|
+
logger.warn(
|
|
2099
|
+
{ app: chosen.id, err: err.message },
|
|
2100
|
+
"application select failed; re-prompting"
|
|
2101
|
+
);
|
|
2102
|
+
messages.push(
|
|
2103
|
+
`Could not select \u201C${labelFor(chosen)}\u201D. It may have been removed \u2014 pick another.`
|
|
2104
|
+
);
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
async function ensureApplication() {
|
|
2109
|
+
return await currentApplication() ?? await promptForApplication();
|
|
1896
2110
|
}
|
|
1897
2111
|
|
|
1898
2112
|
// src/workflows/default.ts
|
|
1899
|
-
import { z as
|
|
2113
|
+
import { z as z27 } from "zod";
|
|
1900
2114
|
|
|
1901
2115
|
// src/actions/listIndices.ts
|
|
1902
|
-
import { z as
|
|
1903
|
-
var indicesListSchema =
|
|
1904
|
-
items:
|
|
1905
|
-
|
|
1906
|
-
name:
|
|
1907
|
-
entries:
|
|
2116
|
+
import { z as z5 } from "zod";
|
|
2117
|
+
var indicesListSchema = z5.object({
|
|
2118
|
+
items: z5.array(
|
|
2119
|
+
z5.object({
|
|
2120
|
+
name: z5.string(),
|
|
2121
|
+
entries: z5.number().default(0)
|
|
1908
2122
|
})
|
|
1909
2123
|
)
|
|
1910
2124
|
});
|
|
@@ -1975,12 +2189,12 @@ import "zod";
|
|
|
1975
2189
|
|
|
1976
2190
|
// src/lib/tools/listFiles.ts
|
|
1977
2191
|
import { tool } from "ai";
|
|
1978
|
-
import
|
|
2192
|
+
import z6 from "zod";
|
|
1979
2193
|
import { readdir } from "node:fs/promises";
|
|
1980
2194
|
|
|
1981
2195
|
// src/lib/tools/path.ts
|
|
1982
2196
|
import { lstat } from "node:fs/promises";
|
|
1983
|
-
import { resolve as resolve2, relative, isAbsolute, dirname as dirname3, join as
|
|
2197
|
+
import { resolve as resolve2, relative, isAbsolute, dirname as dirname3, join as join6, sep } from "node:path";
|
|
1984
2198
|
function resolveInRoot(ctx, path) {
|
|
1985
2199
|
const target = resolve2(ctx.cwd, path);
|
|
1986
2200
|
const rel = relative(ctx.root, target);
|
|
@@ -1996,7 +2210,7 @@ async function hasSymlinkParent(ctx, target) {
|
|
|
1996
2210
|
let current = ctx.root;
|
|
1997
2211
|
const parts = relative(ctx.root, dirname3(target)).split(sep).filter(Boolean);
|
|
1998
2212
|
for (const part of parts) {
|
|
1999
|
-
current =
|
|
2213
|
+
current = join6(current, part);
|
|
2000
2214
|
try {
|
|
2001
2215
|
if ((await lstat(current)).isSymbolicLink()) return true;
|
|
2002
2216
|
} catch (err) {
|
|
@@ -2011,7 +2225,7 @@ async function hasSymlinkParent(ctx, target) {
|
|
|
2011
2225
|
function listFilesTool(ctx) {
|
|
2012
2226
|
return tool({
|
|
2013
2227
|
description: "List files in the current working directory",
|
|
2014
|
-
inputSchema:
|
|
2228
|
+
inputSchema: z6.object(),
|
|
2015
2229
|
execute: async () => {
|
|
2016
2230
|
logger.info("called listFiles tool");
|
|
2017
2231
|
if (++ctx.counts.list > ctx.limits.list) {
|
|
@@ -2027,13 +2241,13 @@ function listFilesTool(ctx) {
|
|
|
2027
2241
|
|
|
2028
2242
|
// src/lib/tools/changeDirectory.ts
|
|
2029
2243
|
import { tool as tool2 } from "ai";
|
|
2030
|
-
import
|
|
2244
|
+
import z7 from "zod";
|
|
2031
2245
|
import { stat } from "node:fs/promises";
|
|
2032
2246
|
function changeDirectoryTool(ctx) {
|
|
2033
2247
|
return tool2({
|
|
2034
2248
|
description: "Change the current working directory. Subsequent file operations resolve relative to it. Returns the new working directory.",
|
|
2035
|
-
inputSchema:
|
|
2036
|
-
path:
|
|
2249
|
+
inputSchema: z7.object({
|
|
2250
|
+
path: z7.string().describe("Directory to change into")
|
|
2037
2251
|
}),
|
|
2038
2252
|
execute: async ({ path }) => {
|
|
2039
2253
|
logger.info({ path }, "called changeDirectory tool");
|
|
@@ -2055,13 +2269,13 @@ function changeDirectoryTool(ctx) {
|
|
|
2055
2269
|
|
|
2056
2270
|
// src/lib/tools/reportStatus.ts
|
|
2057
2271
|
import { tool as tool3 } from "ai";
|
|
2058
|
-
import
|
|
2272
|
+
import z8 from "zod";
|
|
2059
2273
|
function reportStatusTool(output) {
|
|
2060
2274
|
return tool3({
|
|
2061
2275
|
description: "Report the status of your execution. Return a reason in case of failure.",
|
|
2062
|
-
inputSchema:
|
|
2063
|
-
status:
|
|
2064
|
-
reason:
|
|
2276
|
+
inputSchema: z8.object({
|
|
2277
|
+
status: z8.enum(["success", "fail"]),
|
|
2278
|
+
reason: z8.string().optional(),
|
|
2065
2279
|
output
|
|
2066
2280
|
}),
|
|
2067
2281
|
execute: async ({ status, reason, output: output2 }) => {
|
|
@@ -2073,8 +2287,8 @@ function reportStatusTool(output) {
|
|
|
2073
2287
|
|
|
2074
2288
|
// src/lib/tools/readFile.ts
|
|
2075
2289
|
import { tool as tool4 } from "ai";
|
|
2076
|
-
import
|
|
2077
|
-
import { readFile as
|
|
2290
|
+
import z9 from "zod";
|
|
2291
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
2078
2292
|
|
|
2079
2293
|
// src/lib/tools/env.ts
|
|
2080
2294
|
import { basename } from "node:path";
|
|
@@ -2101,8 +2315,8 @@ function redactEnvValues(content) {
|
|
|
2101
2315
|
function readFileTool(ctx) {
|
|
2102
2316
|
return tool4({
|
|
2103
2317
|
description: "Read the contents of a file at the given path",
|
|
2104
|
-
inputSchema:
|
|
2105
|
-
filePath:
|
|
2318
|
+
inputSchema: z9.object({
|
|
2319
|
+
filePath: z9.string().describe("Path to the file to read")
|
|
2106
2320
|
}),
|
|
2107
2321
|
execute: async ({ filePath }) => {
|
|
2108
2322
|
if (++ctx.counts.read > ctx.limits.read) {
|
|
@@ -2112,7 +2326,7 @@ function readFileTool(ctx) {
|
|
|
2112
2326
|
const resolved = resolveInRoot(ctx, filePath);
|
|
2113
2327
|
if (!resolved.ok) return resolved.error;
|
|
2114
2328
|
try {
|
|
2115
|
-
const content = await
|
|
2329
|
+
const content = await readFile3(resolved.target, "utf8");
|
|
2116
2330
|
return isEnvFile(resolved.target) ? redactEnvValues(content) : content;
|
|
2117
2331
|
} catch (err) {
|
|
2118
2332
|
return `Error reading ${filePath}: ${err.message}`;
|
|
@@ -2123,15 +2337,15 @@ function readFileTool(ctx) {
|
|
|
2123
2337
|
|
|
2124
2338
|
// src/lib/tools/writeFile.ts
|
|
2125
2339
|
import { tool as tool5 } from "ai";
|
|
2126
|
-
import
|
|
2340
|
+
import z10 from "zod";
|
|
2127
2341
|
import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
|
|
2128
2342
|
import { dirname as dirname4 } from "node:path";
|
|
2129
2343
|
function writeFileTool(ctx) {
|
|
2130
2344
|
return tool5({
|
|
2131
2345
|
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.",
|
|
2132
|
-
inputSchema:
|
|
2133
|
-
filePath:
|
|
2134
|
-
content:
|
|
2346
|
+
inputSchema: z10.object({
|
|
2347
|
+
filePath: z10.string().describe("Path to the file to write"),
|
|
2348
|
+
content: z10.string().describe("Content to write to the file")
|
|
2135
2349
|
}),
|
|
2136
2350
|
execute: async ({ filePath, content }) => {
|
|
2137
2351
|
logger.info({ filePath }, "called writeFile tool");
|
|
@@ -2156,9 +2370,95 @@ function writeFileTool(ctx) {
|
|
|
2156
2370
|
|
|
2157
2371
|
// src/lib/tools/writeAlgoliaCredentials.ts
|
|
2158
2372
|
import { tool as tool6 } from "ai";
|
|
2159
|
-
import
|
|
2160
|
-
import { mkdir as mkdir4, readFile as
|
|
2373
|
+
import z12 from "zod";
|
|
2374
|
+
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
|
|
2161
2375
|
import { dirname as dirname5 } from "node:path";
|
|
2376
|
+
|
|
2377
|
+
// src/lib/algoliaApiKey.ts
|
|
2378
|
+
import { z as z11 } from "zod";
|
|
2379
|
+
var SAFE_ACLS = /* @__PURE__ */ new Set(["search", "browse", "listIndexes"]);
|
|
2380
|
+
var WRITE_ACLS = [
|
|
2381
|
+
"addObject",
|
|
2382
|
+
"deleteObject",
|
|
2383
|
+
"settings",
|
|
2384
|
+
"editSettings",
|
|
2385
|
+
"listIndexes"
|
|
2386
|
+
];
|
|
2387
|
+
var WRITE_ACL_SET = new Set(WRITE_ACLS);
|
|
2388
|
+
var apiKeySchema = z11.object({
|
|
2389
|
+
value: z11.string().min(1),
|
|
2390
|
+
acl: z11.array(z11.string()).default([]),
|
|
2391
|
+
indexes: z11.array(z11.string()).default([])
|
|
2392
|
+
});
|
|
2393
|
+
var apiKeyListSchema = z11.object({
|
|
2394
|
+
items: z11.array(apiKeySchema).optional(),
|
|
2395
|
+
keys: z11.array(apiKeySchema).optional()
|
|
2396
|
+
}).transform((o) => o.items ?? o.keys ?? []);
|
|
2397
|
+
var createdKeySchema = z11.object({
|
|
2398
|
+
key: z11.string().min(1).optional(),
|
|
2399
|
+
value: z11.string().min(1).optional()
|
|
2400
|
+
});
|
|
2401
|
+
function canReuse(key, index) {
|
|
2402
|
+
return key.acl.includes("search") && key.acl.every((acl) => SAFE_ACLS.has(acl)) && (key.indexes.length === 0 || key.indexes.includes("*") || key.indexes.includes(index));
|
|
2403
|
+
}
|
|
2404
|
+
async function createSearchKey(index) {
|
|
2405
|
+
const stdout = await runAlgoliaCli([
|
|
2406
|
+
"apikeys",
|
|
2407
|
+
"create",
|
|
2408
|
+
"--indices",
|
|
2409
|
+
index,
|
|
2410
|
+
"--acl",
|
|
2411
|
+
"search,browse",
|
|
2412
|
+
"--description",
|
|
2413
|
+
`wizard search-only key for ${index}`,
|
|
2414
|
+
"-o",
|
|
2415
|
+
"json"
|
|
2416
|
+
]);
|
|
2417
|
+
const { key, value } = createdKeySchema.parse(JSON.parse(stdout));
|
|
2418
|
+
const created = key ?? value;
|
|
2419
|
+
if (!created) throw new Error("apikeys create returned no key value");
|
|
2420
|
+
return created;
|
|
2421
|
+
}
|
|
2422
|
+
function canReuseForWrites(key, index) {
|
|
2423
|
+
return WRITE_ACLS.every((acl) => key.acl.includes(acl)) && key.acl.every((acl) => WRITE_ACL_SET.has(acl)) && key.indexes.includes(index);
|
|
2424
|
+
}
|
|
2425
|
+
async function resolveWriteKey(index) {
|
|
2426
|
+
const stdout = await runAlgoliaCli(["apikeys", "list", "-o", "json"]);
|
|
2427
|
+
const existing = apiKeyListSchema.parse(JSON.parse(stdout)).find((key2) => canReuseForWrites(key2, index))?.value;
|
|
2428
|
+
if (existing) {
|
|
2429
|
+
logger.info({ index }, "reusing existing write API key");
|
|
2430
|
+
return existing;
|
|
2431
|
+
}
|
|
2432
|
+
logger.info({ index }, "no reusable write key found; creating one");
|
|
2433
|
+
const created = await runAlgoliaCli([
|
|
2434
|
+
"apikeys",
|
|
2435
|
+
"create",
|
|
2436
|
+
"--indices",
|
|
2437
|
+
index,
|
|
2438
|
+
"--acl",
|
|
2439
|
+
WRITE_ACLS.join(","),
|
|
2440
|
+
"--description",
|
|
2441
|
+
`wizard write key for ${index}`,
|
|
2442
|
+
"-o",
|
|
2443
|
+
"json"
|
|
2444
|
+
]);
|
|
2445
|
+
const { key, value } = createdKeySchema.parse(JSON.parse(created));
|
|
2446
|
+
const writeKey = key ?? value;
|
|
2447
|
+
if (!writeKey) throw new Error("apikeys create returned no key value");
|
|
2448
|
+
return writeKey;
|
|
2449
|
+
}
|
|
2450
|
+
async function resolveSearchOnlyKey(index) {
|
|
2451
|
+
const stdout = await runAlgoliaCli(["apikeys", "list", "-o", "json"]);
|
|
2452
|
+
const existing = apiKeyListSchema.parse(JSON.parse(stdout)).find((key) => canReuse(key, index))?.value;
|
|
2453
|
+
if (existing) {
|
|
2454
|
+
logger.info({ index }, "reusing existing search-only API key");
|
|
2455
|
+
return existing;
|
|
2456
|
+
}
|
|
2457
|
+
logger.info({ index }, "no reusable search-only key found; creating one");
|
|
2458
|
+
return createSearchKey(index);
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
// src/lib/tools/writeAlgoliaCredentials.ts
|
|
2162
2462
|
var APP_ID_VAR = "ALGOLIA_APPLICATION_ID";
|
|
2163
2463
|
var API_KEY_VAR = "ALGOLIA_WRITE_API_KEY";
|
|
2164
2464
|
function appendEnv(content, entries) {
|
|
@@ -2172,9 +2472,9 @@ function hasEnv(content, name) {
|
|
|
2172
2472
|
}
|
|
2173
2473
|
function writeCredentialsTool(ctx) {
|
|
2174
2474
|
return tool6({
|
|
2175
|
-
description: `Write the active Algolia credentials (${APP_ID_VAR} and ${API_KEY_VAR}) into the given env file. The credentials
|
|
2176
|
-
inputSchema:
|
|
2177
|
-
filePath:
|
|
2475
|
+
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.`,
|
|
2476
|
+
inputSchema: z12.object({
|
|
2477
|
+
filePath: z12.string().describe(
|
|
2178
2478
|
'Path to the env file to write credentials into (e.g. ".env")'
|
|
2179
2479
|
)
|
|
2180
2480
|
}),
|
|
@@ -2182,11 +2482,17 @@ function writeCredentialsTool(ctx) {
|
|
|
2182
2482
|
logger.info({ filePath }, "called writeCredentials tool");
|
|
2183
2483
|
const resolved = resolveInRoot(ctx, filePath);
|
|
2184
2484
|
if (resolved.ok === false) return resolved.error;
|
|
2185
|
-
|
|
2485
|
+
const targetIndex = useWizard.getState().targetIndex;
|
|
2486
|
+
if (!targetIndex) {
|
|
2487
|
+
return "Error: no target index is set for this run, so a scoped write key cannot be provisioned.";
|
|
2488
|
+
}
|
|
2489
|
+
let appId;
|
|
2490
|
+
let writeKey;
|
|
2186
2491
|
try {
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2492
|
+
appId = (await requireApplication()).id;
|
|
2493
|
+
writeKey = await resolveWriteKey(targetIndex);
|
|
2494
|
+
} catch (err) {
|
|
2495
|
+
return `Error: could not resolve Algolia credentials (${err.message}). Ask the user to authenticate with the Algolia CLI first.`;
|
|
2190
2496
|
}
|
|
2191
2497
|
try {
|
|
2192
2498
|
if (await hasSymlinkParent(ctx, resolved.target)) {
|
|
@@ -2194,7 +2500,7 @@ function writeCredentialsTool(ctx) {
|
|
|
2194
2500
|
}
|
|
2195
2501
|
let existing = "";
|
|
2196
2502
|
try {
|
|
2197
|
-
existing = await
|
|
2503
|
+
existing = await readFile4(resolved.target, "utf8");
|
|
2198
2504
|
} catch (err) {
|
|
2199
2505
|
if (err.code !== "ENOENT") throw err;
|
|
2200
2506
|
}
|
|
@@ -2205,8 +2511,8 @@ function writeCredentialsTool(ctx) {
|
|
|
2205
2511
|
return `Skipped: ${filePath} already defines ${present.join(" and ")}. Leaving existing credentials untouched.`;
|
|
2206
2512
|
}
|
|
2207
2513
|
const envWithCredentials = appendEnv(existing, [
|
|
2208
|
-
[APP_ID_VAR,
|
|
2209
|
-
[API_KEY_VAR,
|
|
2514
|
+
[APP_ID_VAR, appId],
|
|
2515
|
+
[API_KEY_VAR, writeKey]
|
|
2210
2516
|
]);
|
|
2211
2517
|
await mkdir4(dirname5(resolved.target), { recursive: true });
|
|
2212
2518
|
await writeFile4(resolved.target, envWithCredentials, "utf8");
|
|
@@ -2220,16 +2526,16 @@ function writeCredentialsTool(ctx) {
|
|
|
2220
2526
|
|
|
2221
2527
|
// src/lib/tools/searchFiles.ts
|
|
2222
2528
|
import { tool as tool7 } from "ai";
|
|
2223
|
-
import
|
|
2224
|
-
import { readdir as readdir2, readFile as
|
|
2225
|
-
import { join as
|
|
2529
|
+
import z13 from "zod";
|
|
2530
|
+
import { readdir as readdir2, readFile as readFile5 } from "node:fs/promises";
|
|
2531
|
+
import { join as join7 } from "node:path";
|
|
2226
2532
|
var MAX_QUERY_LENGTH = 1e3;
|
|
2227
2533
|
async function walkFiles(dir) {
|
|
2228
2534
|
const skip = /* @__PURE__ */ new Set(["node_modules", ".git", "dist"]);
|
|
2229
2535
|
const out = [];
|
|
2230
2536
|
for (const e of await readdir2(dir, { withFileTypes: true })) {
|
|
2231
2537
|
if (e.name.startsWith(".") || skip.has(e.name)) continue;
|
|
2232
|
-
const full =
|
|
2538
|
+
const full = join7(dir, e.name);
|
|
2233
2539
|
if (e.isDirectory()) out.push(...await walkFiles(full));
|
|
2234
2540
|
else if (e.isFile()) out.push(full);
|
|
2235
2541
|
}
|
|
@@ -2238,9 +2544,9 @@ async function walkFiles(dir) {
|
|
|
2238
2544
|
function searchFilesTool(ctx) {
|
|
2239
2545
|
return tool7({
|
|
2240
2546
|
description: "Search file contents for a JavaScript regular expression (RegExp syntax, not grep/PCRE). Returns matching lines as file:line:text.",
|
|
2241
|
-
inputSchema:
|
|
2242
|
-
query:
|
|
2243
|
-
path:
|
|
2547
|
+
inputSchema: z13.object({
|
|
2548
|
+
query: z13.string().describe("JavaScript RegExp pattern to search for"),
|
|
2549
|
+
path: z13.string().optional().describe("Directory to search in (default: cwd)")
|
|
2244
2550
|
}),
|
|
2245
2551
|
execute: async ({ query, path = "." }) => {
|
|
2246
2552
|
logger.info({ query, path }, "called searchFiles tool");
|
|
@@ -2262,7 +2568,7 @@ function searchFilesTool(ctx) {
|
|
|
2262
2568
|
for (const file of await walkFiles(resolved.target)) {
|
|
2263
2569
|
let content;
|
|
2264
2570
|
try {
|
|
2265
|
-
content = await
|
|
2571
|
+
content = await readFile5(file, "utf8");
|
|
2266
2572
|
} catch {
|
|
2267
2573
|
continue;
|
|
2268
2574
|
}
|
|
@@ -2284,7 +2590,7 @@ function searchFilesTool(ctx) {
|
|
|
2284
2590
|
|
|
2285
2591
|
// src/lib/tools/verifyImplementation.ts
|
|
2286
2592
|
import { tool as tool8 } from "ai";
|
|
2287
|
-
import
|
|
2593
|
+
import z14 from "zod";
|
|
2288
2594
|
|
|
2289
2595
|
// src/lib/tools/utils/runCommand.ts
|
|
2290
2596
|
import { spawn as spawn2 } from "node:child_process";
|
|
@@ -2306,9 +2612,9 @@ function runCommand(command, args, cwd) {
|
|
|
2306
2612
|
}
|
|
2307
2613
|
|
|
2308
2614
|
// src/lib/tools/utils/packageManager.ts
|
|
2309
|
-
import { readFile as
|
|
2615
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
2310
2616
|
import { existsSync } from "node:fs";
|
|
2311
|
-
import { join as
|
|
2617
|
+
import { join as join8 } from "node:path";
|
|
2312
2618
|
var LOCKFILES = [
|
|
2313
2619
|
["pnpm-lock.yaml", "pnpm"],
|
|
2314
2620
|
["yarn.lock", "yarn"],
|
|
@@ -2317,13 +2623,13 @@ var LOCKFILES = [
|
|
|
2317
2623
|
["package-lock.json", "npm"]
|
|
2318
2624
|
];
|
|
2319
2625
|
async function readPackageJson(cwd = process.cwd()) {
|
|
2320
|
-
return JSON.parse(await
|
|
2626
|
+
return JSON.parse(await readFile6(join8(cwd, "package.json"), "utf8"));
|
|
2321
2627
|
}
|
|
2322
2628
|
function packageManagerFrom(pkg) {
|
|
2323
2629
|
return pkg.packageManager?.split("@")[0] ?? "npm";
|
|
2324
2630
|
}
|
|
2325
2631
|
function packageManagerFromLockfile(cwd) {
|
|
2326
|
-
return LOCKFILES.find(([file]) => existsSync(
|
|
2632
|
+
return LOCKFILES.find(([file]) => existsSync(join8(cwd, file)))?.[1];
|
|
2327
2633
|
}
|
|
2328
2634
|
async function detectPackageManager(cwd) {
|
|
2329
2635
|
try {
|
|
@@ -2364,7 +2670,7 @@ async function runRepoVerificationCheck() {
|
|
|
2364
2670
|
function verifyImplementationTool() {
|
|
2365
2671
|
return tool8({
|
|
2366
2672
|
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.",
|
|
2367
|
-
inputSchema:
|
|
2673
|
+
inputSchema: z14.object(),
|
|
2368
2674
|
execute: async () => {
|
|
2369
2675
|
logger.info("called verifyImplementation tool");
|
|
2370
2676
|
return runRepoVerificationCheck();
|
|
@@ -2378,7 +2684,7 @@ import { createAnthropic } from "@ai-sdk/anthropic";
|
|
|
2378
2684
|
import { nanoid as nanoid2 } from "nanoid";
|
|
2379
2685
|
import { mkdir as mkdir5, writeFile as writeFile5 } from "node:fs/promises";
|
|
2380
2686
|
import { dirname as dirname6 } from "node:path";
|
|
2381
|
-
import
|
|
2687
|
+
import z15 from "zod";
|
|
2382
2688
|
var DATA_DIR = ".algolia-wizard/data";
|
|
2383
2689
|
var RECORD_MODEL = "claude-haiku-4-5";
|
|
2384
2690
|
var MAX_RECORDS = 100;
|
|
@@ -2390,17 +2696,17 @@ var anthropic = createAnthropic({
|
|
|
2390
2696
|
function generateRecordTool(ctx) {
|
|
2391
2697
|
return tool9({
|
|
2392
2698
|
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.",
|
|
2393
|
-
inputSchema:
|
|
2394
|
-
entityName:
|
|
2395
|
-
attributes:
|
|
2396
|
-
count:
|
|
2397
|
-
hint:
|
|
2699
|
+
inputSchema: z15.object({
|
|
2700
|
+
entityName: z15.string().describe("Name of the entity to generate records for."),
|
|
2701
|
+
attributes: z15.array(z15.string()).describe("Attribute names each record must contain."),
|
|
2702
|
+
count: z15.number().int().min(1).max(MAX_RECORDS).default(10).describe(`How many records to generate (max ${MAX_RECORDS}).`),
|
|
2703
|
+
hint: z15.string().optional().describe("Optional context to steer realistic values.")
|
|
2398
2704
|
}),
|
|
2399
2705
|
execute: async ({ entityName, attributes, count, hint }) => {
|
|
2400
2706
|
logger.info({ entityName, count }, "called generateRecord tool");
|
|
2401
2707
|
try {
|
|
2402
|
-
const value =
|
|
2403
|
-
const recordSchema =
|
|
2708
|
+
const value = z15.union([z15.string(), z15.number(), z15.boolean(), z15.null()]);
|
|
2709
|
+
const recordSchema = z15.object(
|
|
2404
2710
|
Object.fromEntries(attributes.map((attr) => [attr, value]))
|
|
2405
2711
|
);
|
|
2406
2712
|
const generateBatch = async (batchCount) => {
|
|
@@ -2410,8 +2716,8 @@ function generateRecordTool(ctx) {
|
|
|
2410
2716
|
const { output } = await generateText({
|
|
2411
2717
|
model: anthropic(RECORD_MODEL),
|
|
2412
2718
|
output: Output.object({
|
|
2413
|
-
schema:
|
|
2414
|
-
records:
|
|
2719
|
+
schema: z15.object({
|
|
2720
|
+
records: z15.array(recordSchema).length(batchCount)
|
|
2415
2721
|
})
|
|
2416
2722
|
}),
|
|
2417
2723
|
prompt: [
|
|
@@ -2469,12 +2775,12 @@ function generateRecordTool(ctx) {
|
|
|
2469
2775
|
|
|
2470
2776
|
// src/lib/tools/notifyUser.ts
|
|
2471
2777
|
import { tool as tool10 } from "ai";
|
|
2472
|
-
import
|
|
2778
|
+
import z16 from "zod";
|
|
2473
2779
|
function notifyUserTool() {
|
|
2474
2780
|
return tool10({
|
|
2475
2781
|
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.`,
|
|
2476
|
-
inputSchema:
|
|
2477
|
-
message:
|
|
2782
|
+
inputSchema: z16.object({
|
|
2783
|
+
message: z16.string().describe(
|
|
2478
2784
|
"Short, plain-language description of what you are doing now."
|
|
2479
2785
|
)
|
|
2480
2786
|
}),
|
|
@@ -2654,10 +2960,10 @@ async function runAgent(req) {
|
|
|
2654
2960
|
}
|
|
2655
2961
|
|
|
2656
2962
|
// src/actions/detectLanguage.ts
|
|
2657
|
-
import
|
|
2658
|
-
var detectLanguageSchema =
|
|
2659
|
-
languages:
|
|
2660
|
-
frameworks:
|
|
2963
|
+
import z19 from "zod";
|
|
2964
|
+
var detectLanguageSchema = z19.object({
|
|
2965
|
+
languages: z19.array(z19.object({ name: z19.string(), version: z19.string() })),
|
|
2966
|
+
frameworks: z19.array(z19.object({ name: z19.string(), version: z19.string() }))
|
|
2661
2967
|
});
|
|
2662
2968
|
var detectLanguage = () => runAgent({
|
|
2663
2969
|
instructions: [
|
|
@@ -2675,31 +2981,31 @@ var detectLanguage = () => runAgent({
|
|
|
2675
2981
|
});
|
|
2676
2982
|
|
|
2677
2983
|
// src/actions/analyzeCodebase.ts
|
|
2678
|
-
import
|
|
2984
|
+
import z20 from "zod";
|
|
2679
2985
|
var READONLY_TOOLS = [
|
|
2680
2986
|
"listFiles",
|
|
2681
2987
|
"changeDirectory",
|
|
2682
2988
|
"readFile",
|
|
2683
2989
|
"searchFiles"
|
|
2684
2990
|
];
|
|
2685
|
-
var ingestionAnalysisSchema =
|
|
2686
|
-
ingestionAnalysis:
|
|
2687
|
-
|
|
2688
|
-
name:
|
|
2689
|
-
paths:
|
|
2991
|
+
var ingestionAnalysisSchema = z20.object({
|
|
2992
|
+
ingestionAnalysis: z20.array(
|
|
2993
|
+
z20.object({
|
|
2994
|
+
name: z20.string(),
|
|
2995
|
+
paths: z20.array(z20.string()),
|
|
2690
2996
|
// indexable fields the agent found for this entity
|
|
2691
|
-
attributes:
|
|
2997
|
+
attributes: z20.array(z20.string())
|
|
2692
2998
|
})
|
|
2693
2999
|
)
|
|
2694
3000
|
});
|
|
2695
|
-
var searchImplementationAnalysisSchema =
|
|
2696
|
-
searchImplementationAnalysis:
|
|
3001
|
+
var searchImplementationAnalysisSchema = z20.object({
|
|
3002
|
+
searchImplementationAnalysis: z20.string()
|
|
2697
3003
|
});
|
|
2698
|
-
var verificationSchema =
|
|
2699
|
-
verification:
|
|
3004
|
+
var verificationSchema = z20.object({
|
|
3005
|
+
verification: z20.array(z20.string())
|
|
2700
3006
|
});
|
|
2701
3007
|
var confirmedEntitiesFieldSchema = ingestionAnalysisSchema.shape.ingestionAnalysis.optional();
|
|
2702
|
-
var analyzeCodebaseSchema =
|
|
3008
|
+
var analyzeCodebaseSchema = z20.object({
|
|
2703
3009
|
ingestionAnalysis: ingestionAnalysisSchema.shape.ingestionAnalysis.optional(),
|
|
2704
3010
|
searchImplementationAnalysis: searchImplementationAnalysisSchema.shape.searchImplementationAnalysis.optional(),
|
|
2705
3011
|
verification: verificationSchema.shape.verification.optional(),
|
|
@@ -2761,7 +3067,7 @@ async function runAnalysis(mode, extraInstructions = []) {
|
|
|
2761
3067
|
// package.json
|
|
2762
3068
|
var package_default = {
|
|
2763
3069
|
name: "@algolia/wizard",
|
|
2764
|
-
version: "0.
|
|
3070
|
+
version: "0.9.0-rc.53.57",
|
|
2765
3071
|
description: "Magically implement Algolia functionality in your codebase",
|
|
2766
3072
|
type: "module",
|
|
2767
3073
|
engines: {
|
|
@@ -2809,7 +3115,6 @@ var package_default = {
|
|
|
2809
3115
|
dependencies: {
|
|
2810
3116
|
"@ai-sdk/anthropic": "^3.0.81",
|
|
2811
3117
|
"@ai-sdk/openai-compatible": "^2.0.47",
|
|
2812
|
-
"@algolia/cli": "^5.11.0",
|
|
2813
3118
|
"@hono/node-server": "^2.0.10",
|
|
2814
3119
|
"@mishieck/ink-titled-box": "^0.4.2",
|
|
2815
3120
|
"@segment/analytics-node": "^3.1.0",
|
|
@@ -2824,7 +3129,6 @@ var package_default = {
|
|
|
2824
3129
|
nanoid: "^5.1.15",
|
|
2825
3130
|
pino: "^10.3.1",
|
|
2826
3131
|
react: "^19.2.7",
|
|
2827
|
-
toml: "^4.1.1",
|
|
2828
3132
|
varlock: "^1.5.1",
|
|
2829
3133
|
zod: "^4.4.3",
|
|
2830
3134
|
zustand: "^5.0.14"
|
|
@@ -2882,8 +3186,8 @@ async function askList(ctx, prompt, { required = false } = {}) {
|
|
|
2882
3186
|
}
|
|
2883
3187
|
|
|
2884
3188
|
// src/actions/confirmLanguage.ts
|
|
2885
|
-
import
|
|
2886
|
-
var confirmLanguageSchema =
|
|
3189
|
+
import z22 from "zod";
|
|
3190
|
+
var confirmLanguageSchema = z22.object({
|
|
2887
3191
|
languages: detectLanguageSchema.shape.languages
|
|
2888
3192
|
});
|
|
2889
3193
|
async function confirmLanguage(ctx) {
|
|
@@ -2904,8 +3208,8 @@ async function confirmLanguage(ctx) {
|
|
|
2904
3208
|
}
|
|
2905
3209
|
|
|
2906
3210
|
// src/actions/confirmFramework.ts
|
|
2907
|
-
import
|
|
2908
|
-
var confirmFrameworkSchema =
|
|
3211
|
+
import z23 from "zod";
|
|
3212
|
+
var confirmFrameworkSchema = z23.object({
|
|
2909
3213
|
frameworks: detectLanguageSchema.shape.frameworks
|
|
2910
3214
|
});
|
|
2911
3215
|
var CURATED_FRAMEWORKS = [
|
|
@@ -3033,8 +3337,8 @@ async function promptUser(ctx, params) {
|
|
|
3033
3337
|
}
|
|
3034
3338
|
|
|
3035
3339
|
// src/actions/confirmEntities.ts
|
|
3036
|
-
import
|
|
3037
|
-
var confirmEntitiesSchema =
|
|
3340
|
+
import z24 from "zod";
|
|
3341
|
+
var confirmEntitiesSchema = z24.object({
|
|
3038
3342
|
// Final detection — the focused re-run may supersede project-scan's.
|
|
3039
3343
|
ingestionAnalysis: ingestionAnalysisSchema.shape.ingestionAnalysis.optional(),
|
|
3040
3344
|
confirmedEntities: confirmedEntitiesFieldSchema
|
|
@@ -3104,15 +3408,15 @@ async function confirmEntities(ctx) {
|
|
|
3104
3408
|
}
|
|
3105
3409
|
|
|
3106
3410
|
// src/actions/review.ts
|
|
3107
|
-
import { z as
|
|
3108
|
-
var reviewSchema =
|
|
3411
|
+
import { z as z25 } from "zod";
|
|
3412
|
+
var reviewSchema = z25.object({
|
|
3109
3413
|
// Broad, high-level takeaways grouped by theme (e.g. ingestion, search UI),
|
|
3110
3414
|
// not one entry per workflow step — a step's raw output can be a long,
|
|
3111
3415
|
// multi-paragraph blob (see implement.ts's summaries.join), and mirroring
|
|
3112
3416
|
// that 1:1 is what made the old per-step summary an unreadable wall of text.
|
|
3113
|
-
summaryPoints:
|
|
3114
|
-
reviewPrompt:
|
|
3115
|
-
nextSteps:
|
|
3417
|
+
summaryPoints: z25.array(z25.string()),
|
|
3418
|
+
reviewPrompt: z25.string(),
|
|
3419
|
+
nextSteps: z25.array(z25.string())
|
|
3116
3420
|
});
|
|
3117
3421
|
function formatCompletedSteps(steps) {
|
|
3118
3422
|
if (!steps.length) return "(no prior steps completed)";
|
|
@@ -3163,16 +3467,16 @@ ${formatCompletedSteps(ctx.completedSteps)}`,
|
|
|
3163
3467
|
};
|
|
3164
3468
|
|
|
3165
3469
|
// src/actions/implement.ts
|
|
3166
|
-
import
|
|
3470
|
+
import z26 from "zod";
|
|
3167
3471
|
|
|
3168
3472
|
// src/lib/worktree.ts
|
|
3169
3473
|
import { execFile, spawn as spawn3 } from "node:child_process";
|
|
3170
|
-
import { copyFile, mkdir as mkdir6, readdir as readdir3, readFile as
|
|
3474
|
+
import { copyFile, mkdir as mkdir6, readdir as readdir3, readFile as readFile7, stat as stat2, writeFile as writeFile6 } from "node:fs/promises";
|
|
3171
3475
|
import {
|
|
3172
3476
|
basename as basename2,
|
|
3173
3477
|
dirname as dirname7,
|
|
3174
3478
|
isAbsolute as isAbsolute2,
|
|
3175
|
-
join as
|
|
3479
|
+
join as join9,
|
|
3176
3480
|
relative as relative2,
|
|
3177
3481
|
resolve as resolve3
|
|
3178
3482
|
} from "node:path";
|
|
@@ -3206,7 +3510,7 @@ async function isWorkingTreeDirty(repoRoot) {
|
|
|
3206
3510
|
return out.trim().length > 0;
|
|
3207
3511
|
}
|
|
3208
3512
|
async function pruneOldWorktrees(repoRoot) {
|
|
3209
|
-
const dir =
|
|
3513
|
+
const dir = join9(stateDir(repoRoot), "worktrees");
|
|
3210
3514
|
const stale = (await readdir3(dir).catch(() => [])).filter((name) => /^wizard-implement-\d+$/.test(name)).sort().reverse().slice(MAX_WIZARD_WORKTREES - 1);
|
|
3211
3515
|
for (const slug of stale) {
|
|
3212
3516
|
const branch = slug.replace("wizard-implement-", WIZARD_BRANCH_PREFIX);
|
|
@@ -3217,7 +3521,7 @@ async function pruneOldWorktrees(repoRoot) {
|
|
|
3217
3521
|
"worktree",
|
|
3218
3522
|
"remove",
|
|
3219
3523
|
"--force",
|
|
3220
|
-
|
|
3524
|
+
join9(dir, slug)
|
|
3221
3525
|
]);
|
|
3222
3526
|
await git(["-C", repoRoot, "branch", "-D", branch]);
|
|
3223
3527
|
} catch (err) {
|
|
@@ -3231,7 +3535,7 @@ async function pruneOldWorktrees(repoRoot) {
|
|
|
3231
3535
|
async function createWorktree(repoRoot) {
|
|
3232
3536
|
const branch = `${WIZARD_BRANCH_PREFIX}${Date.now()}`;
|
|
3233
3537
|
const dirSlug = branch.replace(/\//g, "-");
|
|
3234
|
-
const path =
|
|
3538
|
+
const path = join9(stateDir(repoRoot), "worktrees", dirSlug);
|
|
3235
3539
|
await git(["-C", repoRoot, "worktree", "prune"]);
|
|
3236
3540
|
await pruneOldWorktrees(repoRoot);
|
|
3237
3541
|
await mkdir6(dirname7(path), { recursive: true });
|
|
@@ -3351,8 +3655,8 @@ async function copyUploadIntoWorktree(repoRoot, worktreePath, ingestDir, sourceP
|
|
|
3351
3655
|
} catch {
|
|
3352
3656
|
return { ok: false, reason: `"${sourcePath}" does not exist` };
|
|
3353
3657
|
}
|
|
3354
|
-
const relPath =
|
|
3355
|
-
const dest =
|
|
3658
|
+
const relPath = join9(ingestDir, basename2(source));
|
|
3659
|
+
const dest = join9(worktreePath, relPath);
|
|
3356
3660
|
try {
|
|
3357
3661
|
await mkdir6(dirname7(dest), { recursive: true });
|
|
3358
3662
|
await copyFile(source, dest);
|
|
@@ -3368,10 +3672,10 @@ function hasEnvVar(content, name) {
|
|
|
3368
3672
|
return new RegExp(`^(\\s*(?:export\\s+)?${name})\\s*=`, "m").test(content);
|
|
3369
3673
|
}
|
|
3370
3674
|
async function writeSearchEnvValues(worktreePath, vars) {
|
|
3371
|
-
const target =
|
|
3675
|
+
const target = join9(worktreePath, ".env");
|
|
3372
3676
|
let existing = "";
|
|
3373
3677
|
try {
|
|
3374
|
-
existing = await
|
|
3678
|
+
existing = await readFile7(target, "utf8");
|
|
3375
3679
|
} catch (err) {
|
|
3376
3680
|
if (err.code !== "ENOENT") throw err;
|
|
3377
3681
|
}
|
|
@@ -3439,63 +3743,15 @@ async function confirmDirtyWorkingTree(ctx, repoRoot) {
|
|
|
3439
3743
|
}
|
|
3440
3744
|
}
|
|
3441
3745
|
|
|
3442
|
-
// src/lib/algoliaApiKey.ts
|
|
3443
|
-
import { z as z23 } from "zod";
|
|
3444
|
-
var SAFE_ACLS = /* @__PURE__ */ new Set(["search", "browse", "listIndexes"]);
|
|
3445
|
-
var apiKeySchema = z23.object({
|
|
3446
|
-
value: z23.string().min(1),
|
|
3447
|
-
acl: z23.array(z23.string()).default([]),
|
|
3448
|
-
indexes: z23.array(z23.string()).default([])
|
|
3449
|
-
});
|
|
3450
|
-
var apiKeyListSchema = z23.object({
|
|
3451
|
-
items: z23.array(apiKeySchema).optional(),
|
|
3452
|
-
keys: z23.array(apiKeySchema).optional()
|
|
3453
|
-
}).transform((o) => o.items ?? o.keys ?? []);
|
|
3454
|
-
var createdKeySchema = z23.object({
|
|
3455
|
-
key: z23.string().min(1).optional(),
|
|
3456
|
-
value: z23.string().min(1).optional()
|
|
3457
|
-
});
|
|
3458
|
-
function canReuse(key, index) {
|
|
3459
|
-
return key.acl.includes("search") && key.acl.every((acl) => SAFE_ACLS.has(acl)) && (key.indexes.length === 0 || key.indexes.includes("*") || key.indexes.includes(index));
|
|
3460
|
-
}
|
|
3461
|
-
async function createSearchKey(index) {
|
|
3462
|
-
const stdout = await runAlgoliaCli([
|
|
3463
|
-
"apikeys",
|
|
3464
|
-
"create",
|
|
3465
|
-
"--indices",
|
|
3466
|
-
index,
|
|
3467
|
-
"--acl",
|
|
3468
|
-
"search,browse",
|
|
3469
|
-
"--description",
|
|
3470
|
-
`wizard search-only key for ${index}`,
|
|
3471
|
-
"-o",
|
|
3472
|
-
"json"
|
|
3473
|
-
]);
|
|
3474
|
-
const { key, value } = createdKeySchema.parse(JSON.parse(stdout));
|
|
3475
|
-
const created = key ?? value;
|
|
3476
|
-
if (!created) throw new Error("apikeys create returned no key value");
|
|
3477
|
-
return created;
|
|
3478
|
-
}
|
|
3479
|
-
async function resolveSearchOnlyKey(index) {
|
|
3480
|
-
const stdout = await runAlgoliaCli(["apikeys", "list", "-o", "json"]);
|
|
3481
|
-
const existing = apiKeyListSchema.parse(JSON.parse(stdout)).find((key) => canReuse(key, index))?.value;
|
|
3482
|
-
if (existing) {
|
|
3483
|
-
logger.info({ index }, "reusing existing search-only API key");
|
|
3484
|
-
return existing;
|
|
3485
|
-
}
|
|
3486
|
-
logger.info({ index }, "no reusable search-only key found; creating one");
|
|
3487
|
-
return createSearchKey(index);
|
|
3488
|
-
}
|
|
3489
|
-
|
|
3490
3746
|
// src/lib/algoliaDocs.ts
|
|
3491
3747
|
import { readFileSync, readdirSync, existsSync as existsSync2 } from "node:fs";
|
|
3492
|
-
import { dirname as dirname8, join as
|
|
3748
|
+
import { dirname as dirname8, join as join10 } from "node:path";
|
|
3493
3749
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3494
|
-
var DOCS_SUBPATH =
|
|
3750
|
+
var DOCS_SUBPATH = join10("docs", "algolia-sdk");
|
|
3495
3751
|
function findDocsDir() {
|
|
3496
3752
|
let dir = dirname8(fileURLToPath2(import.meta.url));
|
|
3497
3753
|
for (; ; ) {
|
|
3498
|
-
const candidate =
|
|
3754
|
+
const candidate = join10(dir, DOCS_SUBPATH);
|
|
3499
3755
|
if (existsSync2(candidate)) return candidate;
|
|
3500
3756
|
const parent = dirname8(dir);
|
|
3501
3757
|
if (parent === dir) return void 0;
|
|
@@ -3518,7 +3774,7 @@ function loadAlgoliaDoc(language) {
|
|
|
3518
3774
|
);
|
|
3519
3775
|
return "";
|
|
3520
3776
|
}
|
|
3521
|
-
return readFileSync(
|
|
3777
|
+
return readFileSync(join10(docsDir, files[0]), "utf8").trim();
|
|
3522
3778
|
}
|
|
3523
3779
|
function getNamedDoc(name, language) {
|
|
3524
3780
|
const docsDir = findDocsDir();
|
|
@@ -3526,7 +3782,7 @@ function getNamedDoc(name, language) {
|
|
|
3526
3782
|
logger.warn("docs/algolia-sdk not found");
|
|
3527
3783
|
return "";
|
|
3528
3784
|
}
|
|
3529
|
-
const file =
|
|
3785
|
+
const file = join10(docsDir, `${name}-${language}.md`);
|
|
3530
3786
|
if (!existsSync2(file)) {
|
|
3531
3787
|
logger.warn({ name, language }, "named SDK reference not found");
|
|
3532
3788
|
return "";
|
|
@@ -3553,50 +3809,36 @@ function shellQuote(value) {
|
|
|
3553
3809
|
}
|
|
3554
3810
|
|
|
3555
3811
|
// src/actions/implement.ts
|
|
3556
|
-
var implementSchema =
|
|
3557
|
-
filesChanged:
|
|
3558
|
-
summary:
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
//
|
|
3566
|
-
//
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
ingestRecordCount: z24.number().optional(),
|
|
3572
|
-
// Wall-clock duration of the run-now ingestion execution, in ms.
|
|
3573
|
-
ingestDurationMs: z24.number().optional(),
|
|
3574
|
-
ingestionSource: z24.enum(["local", "fileUpload", "generated"]),
|
|
3575
|
-
// Suggested names/values, built from framework detection. The search agent is
|
|
3576
|
-
// instructed to rename the prefix if it doesn't match the project's build
|
|
3577
|
-
// tool, so the names it actually wrote can differ — treat these as hints, not
|
|
3578
|
-
// ground truth (the agent's summary carries the final names).
|
|
3579
|
-
searchEnvVars: z24.array(
|
|
3580
|
-
z24.object({
|
|
3581
|
-
name: z24.string(),
|
|
3582
|
-
value: z24.string()
|
|
3812
|
+
var implementSchema = z26.object({
|
|
3813
|
+
filesChanged: z26.array(z26.string()),
|
|
3814
|
+
summary: z26.string(),
|
|
3815
|
+
worktreePath: z26.string().optional(),
|
|
3816
|
+
ingestCommand: z26.string().optional(),
|
|
3817
|
+
ingestScriptRan: z26.boolean().optional(),
|
|
3818
|
+
ingestRecordCount: z26.number().optional(),
|
|
3819
|
+
ingestDurationMs: z26.number().optional(),
|
|
3820
|
+
ingestionSource: z26.enum(["local", "fileUpload", "generated"]),
|
|
3821
|
+
// Hints, not ground truth: the search agent may rename the prefix to match
|
|
3822
|
+
// the project's build tool, and its summary carries the final names.
|
|
3823
|
+
searchEnvVars: z26.array(
|
|
3824
|
+
z26.object({
|
|
3825
|
+
name: z26.string(),
|
|
3826
|
+
value: z26.string()
|
|
3583
3827
|
})
|
|
3584
3828
|
).optional()
|
|
3585
3829
|
});
|
|
3586
|
-
var implementationOutputSchema =
|
|
3587
|
-
summary:
|
|
3588
|
-
// Ingestion only:
|
|
3589
|
-
//
|
|
3590
|
-
//
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
runtime: z24.enum(INGEST_RUNTIMES).optional(),
|
|
3594
|
-
entrypoint: z24.string().optional()
|
|
3830
|
+
var implementationOutputSchema = z26.object({
|
|
3831
|
+
summary: z26.string(),
|
|
3832
|
+
// Ingestion only: a structured pair the wizard turns into an argv, never a
|
|
3833
|
+
// free-form command string. `runtime` is allowlisted and `entrypoint` is
|
|
3834
|
+
// validated worktree-relative, so the agent cannot inject extra commands.
|
|
3835
|
+
runtime: z26.enum(INGEST_RUNTIMES).optional(),
|
|
3836
|
+
entrypoint: z26.string().optional()
|
|
3595
3837
|
});
|
|
3596
|
-
var verificationOutputSchema =
|
|
3597
|
-
summary:
|
|
3598
|
-
sufficient:
|
|
3599
|
-
additionalInstructions:
|
|
3838
|
+
var verificationOutputSchema = z26.object({
|
|
3839
|
+
summary: z26.string(),
|
|
3840
|
+
sufficient: z26.boolean(),
|
|
3841
|
+
additionalInstructions: z26.string().optional()
|
|
3600
3842
|
});
|
|
3601
3843
|
var MAX_IMPLEMENT_VERIFICATION_ATTEMPTS = 3;
|
|
3602
3844
|
var DEFAULT_IMPLEMENT_USE_CASES = ["ingestion", "search"];
|
|
@@ -3668,9 +3910,6 @@ function sourceSpecificInstructions(input) {
|
|
|
3668
3910
|
"Add env vars for any local source access (DB URL, API base, file paths) that is not a fixed repo path."
|
|
3669
3911
|
],
|
|
3670
3912
|
fileUpload: [
|
|
3671
|
-
// The wizard already copied the developer's file into the worktree at this
|
|
3672
|
-
// exact path, so the agent must read it directly — never search for or
|
|
3673
|
-
// substitute another file.
|
|
3674
3913
|
`Records come from the developer's file, already copied into the worktree at "${input.uploadFilePath}". Read and parse that exact file.`,
|
|
3675
3914
|
"Parse by extension: JSON = array of objects; CSV/TSV = header row maps to keys.",
|
|
3676
3915
|
"Map parsed columns/fields to the confirmed entity attributes.",
|
|
@@ -3710,12 +3949,11 @@ function searchInstructions(input) {
|
|
|
3710
3949
|
doc,
|
|
3711
3950
|
`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.`,
|
|
3712
3951
|
"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.",
|
|
3713
|
-
// appId always resolves (
|
|
3714
|
-
//
|
|
3952
|
+
// appId always resolves (requireApplication throws otherwise); only the key
|
|
3953
|
+
// can fall back to a placeholder.
|
|
3715
3954
|
`Values: App ID "${input.appId}", search-only key ${input.searchKey ? `"${input.searchKey}"` : "(placeholder for the developer to fill in)"}.`,
|
|
3716
|
-
//
|
|
3717
|
-
//
|
|
3718
|
-
// right after this step, so a renamed prefix here would leave the code
|
|
3955
|
+
// Not the agent's to rename: the wizard writes these exact names into
|
|
3956
|
+
// ".env" right after this step, so a renamed prefix would leave the code
|
|
3719
3957
|
// reading a var the wizard never wrote.
|
|
3720
3958
|
`Use exactly these public env var names in the code: ${input.searchEnvVars.map(({ name }) => name).join(", ")}.`,
|
|
3721
3959
|
'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.',
|
|
@@ -3859,6 +4097,7 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
3859
4097
|
}
|
|
3860
4098
|
}
|
|
3861
4099
|
const targetIndex = selected?.selection;
|
|
4100
|
+
useWizard.getState().setTargetIndex(targetIndex ?? null);
|
|
3862
4101
|
await assertGitRepoWithHead(repoRoot);
|
|
3863
4102
|
if (await isWorkingTreeDirty(repoRoot)) {
|
|
3864
4103
|
await confirmDirtyWorkingTree(ctx, repoRoot);
|
|
@@ -3869,7 +4108,7 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
3869
4108
|
let appId;
|
|
3870
4109
|
let searchKey;
|
|
3871
4110
|
if (useCases.includes("search")) {
|
|
3872
|
-
appId = (await
|
|
4111
|
+
appId = (await requireApplication()).id;
|
|
3873
4112
|
try {
|
|
3874
4113
|
searchKey = await resolveSearchOnlyKey(targetIndex);
|
|
3875
4114
|
} catch (err) {
|
|
@@ -3914,8 +4153,6 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
3914
4153
|
ingestDir: INGEST_DIR,
|
|
3915
4154
|
ingestionSource,
|
|
3916
4155
|
uploadFilePath,
|
|
3917
|
-
// language.frameworks already prefers the confirm-framework step output,
|
|
3918
|
-
// so the user's confirmed stack (not just raw detection) picks the flavor.
|
|
3919
4156
|
uiFramework: detectUiFramework(language)
|
|
3920
4157
|
};
|
|
3921
4158
|
const summaries = [];
|
|
@@ -3980,7 +4217,8 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
3980
4217
|
messages: []
|
|
3981
4218
|
}) === true;
|
|
3982
4219
|
if (runNow) {
|
|
3983
|
-
const
|
|
4220
|
+
const ingestApp = await requireApplication();
|
|
4221
|
+
const writeKey = await resolveWriteKey(targetIndex);
|
|
3984
4222
|
ctx.notify({ messages: [`Writing records to "${targetIndex}"\u2026`] });
|
|
3985
4223
|
const scriptLogId = ctx.logStart("runIngestScript", {
|
|
3986
4224
|
runtime: ingestRuntime,
|
|
@@ -3992,8 +4230,8 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
3992
4230
|
ingestRuntime,
|
|
3993
4231
|
ingestEntrypoint,
|
|
3994
4232
|
{
|
|
3995
|
-
[APP_ID_VAR]:
|
|
3996
|
-
[API_KEY_VAR]:
|
|
4233
|
+
[APP_ID_VAR]: ingestApp.id,
|
|
4234
|
+
[API_KEY_VAR]: writeKey
|
|
3997
4235
|
}
|
|
3998
4236
|
);
|
|
3999
4237
|
ctx.logEnd(scriptLogId, run2.ok ? "success" : "error");
|
|
@@ -4062,8 +4300,7 @@ ${run2.output}` : status;
|
|
|
4062
4300
|
);
|
|
4063
4301
|
}
|
|
4064
4302
|
await ctx.requestUserInput({
|
|
4065
|
-
//
|
|
4066
|
-
// continue/decline hints below already say "continue".
|
|
4303
|
+
// Nothing to ask — the continue/decline hints carry the whole prompt.
|
|
4067
4304
|
prompt: "",
|
|
4068
4305
|
promptType: "enterToContinue",
|
|
4069
4306
|
options: [],
|
|
@@ -4204,8 +4441,8 @@ var defaultWorkflow = {
|
|
|
4204
4441
|
defineStep({
|
|
4205
4442
|
id: "select-index",
|
|
4206
4443
|
title: "Set up index",
|
|
4207
|
-
outputSchema:
|
|
4208
|
-
selection:
|
|
4444
|
+
outputSchema: z27.object({
|
|
4445
|
+
selection: z27.string()
|
|
4209
4446
|
}),
|
|
4210
4447
|
run: (ctx) => selectIndexStep(ctx)
|
|
4211
4448
|
}),
|
|
@@ -4484,7 +4721,7 @@ function parseCliArgs(argv) {
|
|
|
4484
4721
|
|
|
4485
4722
|
// src/lib/resetState.ts
|
|
4486
4723
|
import { readdir as readdir4, rm as rm2 } from "node:fs/promises";
|
|
4487
|
-
import { join as
|
|
4724
|
+
import { join as join11 } from "node:path";
|
|
4488
4725
|
var KEEP = ["wizard.log"];
|
|
4489
4726
|
async function resetProjectState() {
|
|
4490
4727
|
const dir = stateDir();
|
|
@@ -4496,7 +4733,7 @@ async function resetProjectState() {
|
|
|
4496
4733
|
}
|
|
4497
4734
|
const targets = entries.filter((name) => !KEEP.includes(name));
|
|
4498
4735
|
await Promise.all(
|
|
4499
|
-
targets.map((name) => rm2(
|
|
4736
|
+
targets.map((name) => rm2(join11(dir, name), { recursive: true, force: true }))
|
|
4500
4737
|
);
|
|
4501
4738
|
return { dir, removed: targets };
|
|
4502
4739
|
}
|
|
@@ -4551,31 +4788,38 @@ ${formatStepList(workflow)}`);
|
|
|
4551
4788
|
}
|
|
4552
4789
|
async function run(workflow) {
|
|
4553
4790
|
const store = useWizard.getState();
|
|
4554
|
-
|
|
4791
|
+
const instance = render(/* @__PURE__ */ jsx14(App, {}), { incrementalRendering: true });
|
|
4792
|
+
await store.waitForStart();
|
|
4555
4793
|
let user = await getUser();
|
|
4556
4794
|
if (!user) {
|
|
4557
|
-
|
|
4558
|
-
instance.cleanup();
|
|
4795
|
+
store.beginAuth();
|
|
4559
4796
|
try {
|
|
4560
4797
|
await runAuthLogin();
|
|
4561
4798
|
} catch (err) {
|
|
4562
|
-
|
|
4799
|
+
store.setError(err instanceof Error ? err.message : String(err));
|
|
4800
|
+
await instance.waitUntilExit();
|
|
4563
4801
|
process.exit(1);
|
|
4564
4802
|
}
|
|
4565
|
-
|
|
4803
|
+
store.endAuth();
|
|
4566
4804
|
user = await getUser();
|
|
4567
4805
|
if (!user) {
|
|
4568
4806
|
store.setError(
|
|
4569
|
-
"Authentication completed but no Algolia user was returned. Try running `npx @algolia/cli auth login` directly."
|
|
4807
|
+
"Authentication completed but no Algolia user was returned. Try running `npx @algolia/cli@latest auth login` directly."
|
|
4570
4808
|
);
|
|
4571
4809
|
await instance.waitUntilExit();
|
|
4572
4810
|
process.exit(1);
|
|
4573
4811
|
}
|
|
4574
4812
|
}
|
|
4575
4813
|
store.setUser(user);
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4814
|
+
let app;
|
|
4815
|
+
try {
|
|
4816
|
+
app = await ensureApplication();
|
|
4817
|
+
} catch (err) {
|
|
4818
|
+
store.setError(err instanceof Error ? err.message : String(err));
|
|
4819
|
+
await instance.waitUntilExit();
|
|
4820
|
+
process.exit(1);
|
|
4821
|
+
}
|
|
4822
|
+
runWorkflow(workflow, app.id);
|
|
4579
4823
|
}
|
|
4580
4824
|
var started = await startup();
|
|
4581
4825
|
if (typeof started === "number") {
|