@algolia/wizard 0.87.0-rc.211.681 → 0.87.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +346 -309
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { render } from "ink";
|
|
5
5
|
|
|
6
6
|
// src/ui/App.tsx
|
|
7
|
-
import { Box as
|
|
7
|
+
import { Box as Box23, Text as Text24, useApp as useApp2, useInput as useInput10, useWindowSize as useWindowSize8 } from "ink";
|
|
8
8
|
import Spinner3 from "ink-spinner";
|
|
9
9
|
|
|
10
10
|
// src/lib/terminalSize.ts
|
|
@@ -98,8 +98,8 @@ function runAlgoliaCli(args, { onOutput, redact } = {}) {
|
|
|
98
98
|
let stdout = "";
|
|
99
99
|
let stderr = "";
|
|
100
100
|
const splitters = {
|
|
101
|
-
stdout: lineSplitter((line) => onOutput?.("stdout", line)),
|
|
102
|
-
stderr: lineSplitter((line) => onOutput?.("stderr", line))
|
|
101
|
+
stdout: lineSplitter((line) => onOutput?.("stdout", mask(line, redact))),
|
|
102
|
+
stderr: lineSplitter((line) => onOutput?.("stderr", mask(line, redact)))
|
|
103
103
|
};
|
|
104
104
|
child.stdout.on("data", (chunk) => {
|
|
105
105
|
const text = String(chunk);
|
|
@@ -287,6 +287,16 @@ var CLI_OUTPUT_LIMIT = 200;
|
|
|
287
287
|
function commandApprovalKey(command, cwd) {
|
|
288
288
|
return `${cwd}\0${command}`;
|
|
289
289
|
}
|
|
290
|
+
function appendOutputLog(logs, outputCount, entry) {
|
|
291
|
+
if (outputCount < CLI_OUTPUT_LIMIT) {
|
|
292
|
+
return { logs: [...logs, entry], _outputLogCount: outputCount + 1 };
|
|
293
|
+
}
|
|
294
|
+
const oldest = logs.findIndex((e) => e.kind === "output");
|
|
295
|
+
return {
|
|
296
|
+
logs: [...logs.filter((_, i) => i !== oldest), entry],
|
|
297
|
+
_outputLogCount: outputCount
|
|
298
|
+
};
|
|
299
|
+
}
|
|
290
300
|
var useWizard = create((set, get) => ({
|
|
291
301
|
phase: "idle",
|
|
292
302
|
homeScreen: "home",
|
|
@@ -304,6 +314,7 @@ var useWizard = create((set, get) => ({
|
|
|
304
314
|
writtenFiles: [],
|
|
305
315
|
approvedCommands: /* @__PURE__ */ new Set(),
|
|
306
316
|
logs: [],
|
|
317
|
+
_outputLogCount: 0,
|
|
307
318
|
error: null,
|
|
308
319
|
inputReq: null,
|
|
309
320
|
_resolve: null,
|
|
@@ -396,11 +407,23 @@ var useWizard = create((set, get) => ({
|
|
|
396
407
|
get()._clearNoticeQueue();
|
|
397
408
|
set({ notices: [] });
|
|
398
409
|
},
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
)
|
|
403
|
-
|
|
410
|
+
// Logged too, so a line cut off on the main screen can be read in the log view.
|
|
411
|
+
pushCliOutput: (stream, text) => {
|
|
412
|
+
const id = nanoid();
|
|
413
|
+
set((s) => ({
|
|
414
|
+
cliOutput: [...s.cliOutput, { id, stream, text }].slice(
|
|
415
|
+
-CLI_OUTPUT_LIMIT
|
|
416
|
+
),
|
|
417
|
+
...appendOutputLog(s.logs, s._outputLogCount, {
|
|
418
|
+
id,
|
|
419
|
+
kind: "output",
|
|
420
|
+
name: text,
|
|
421
|
+
stream,
|
|
422
|
+
status: "success",
|
|
423
|
+
startedAt: Date.now()
|
|
424
|
+
})
|
|
425
|
+
}));
|
|
426
|
+
},
|
|
404
427
|
clearCliOutput: () => set({ cliOutput: [] }),
|
|
405
428
|
setReview: (review2) => set({ review: review2 }),
|
|
406
429
|
setTargetIndex: (index) => set({ targetIndex: index }),
|
|
@@ -474,6 +497,7 @@ var useWizard = create((set, get) => ({
|
|
|
474
497
|
writtenFiles: [],
|
|
475
498
|
approvedCommands: /* @__PURE__ */ new Set(),
|
|
476
499
|
logs: [],
|
|
500
|
+
_outputLogCount: 0,
|
|
477
501
|
error: null,
|
|
478
502
|
inputReq: null,
|
|
479
503
|
_resolve: null,
|
|
@@ -713,6 +737,32 @@ import { useState as useState9 } from "react";
|
|
|
713
737
|
import { Box as Box8, Text as Text8, useInput as useInput3 } from "ink";
|
|
714
738
|
import { useLayoutEffect as useLayoutEffect3, useState as useState6 } from "react";
|
|
715
739
|
|
|
740
|
+
// src/lib/wrapExact.ts
|
|
741
|
+
function wrapExactLine(line, width) {
|
|
742
|
+
if (line.length === 0) return [" "];
|
|
743
|
+
const lines = [];
|
|
744
|
+
let i = 0;
|
|
745
|
+
while (i < line.length) {
|
|
746
|
+
if (line.length - i <= width) {
|
|
747
|
+
lines.push(line.slice(i));
|
|
748
|
+
break;
|
|
749
|
+
}
|
|
750
|
+
let end = i + width;
|
|
751
|
+
if (line.charAt(end) !== " ") {
|
|
752
|
+
const lastSpace = line.lastIndexOf(" ", end - 1);
|
|
753
|
+
if (lastSpace >= i) end = lastSpace + 1;
|
|
754
|
+
}
|
|
755
|
+
if (end <= i) end = i + width;
|
|
756
|
+
lines.push(line.slice(i, end));
|
|
757
|
+
i = end;
|
|
758
|
+
}
|
|
759
|
+
return lines;
|
|
760
|
+
}
|
|
761
|
+
function wrapExact(text, width) {
|
|
762
|
+
if (width <= 0) return [text || " "];
|
|
763
|
+
return text.split(/\r\n|\n|\r/).flatMap((line) => wrapExactLine(line, width));
|
|
764
|
+
}
|
|
765
|
+
|
|
716
766
|
// src/ui/DecisionSelect.tsx
|
|
717
767
|
import { Box as Box5, Text as Text5, useInput } from "ink";
|
|
718
768
|
import { useState as useState3 } from "react";
|
|
@@ -1028,30 +1078,6 @@ function Review() {
|
|
|
1028
1078
|
import { jsx as jsx6, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1029
1079
|
var BLANK2 = { prefix: "", text: " ", color: COLORS.dim };
|
|
1030
1080
|
var COMMAND_PREFIX = "$ ";
|
|
1031
|
-
function wrapExactLine(line, width) {
|
|
1032
|
-
if (line.length === 0) return [" "];
|
|
1033
|
-
const lines = [];
|
|
1034
|
-
let i = 0;
|
|
1035
|
-
while (i < line.length) {
|
|
1036
|
-
if (line.length - i <= width) {
|
|
1037
|
-
lines.push(line.slice(i));
|
|
1038
|
-
break;
|
|
1039
|
-
}
|
|
1040
|
-
let end = i + width;
|
|
1041
|
-
if (line.charAt(end) !== " ") {
|
|
1042
|
-
const lastSpace = line.lastIndexOf(" ", end - 1);
|
|
1043
|
-
if (lastSpace >= i) end = lastSpace + 1;
|
|
1044
|
-
}
|
|
1045
|
-
if (end <= i) end = i + width;
|
|
1046
|
-
lines.push(line.slice(i, end));
|
|
1047
|
-
i = end;
|
|
1048
|
-
}
|
|
1049
|
-
return lines;
|
|
1050
|
-
}
|
|
1051
|
-
function wrapExact(text, width) {
|
|
1052
|
-
if (width <= 0) return [text || " "];
|
|
1053
|
-
return text.split(/\r\n|\n|\r/).flatMap((line) => wrapExactLine(line, width));
|
|
1054
|
-
}
|
|
1055
1081
|
function fieldLines(prefix, value, color, width) {
|
|
1056
1082
|
return wrapText(value, Math.max(width - prefix.length, 1)).map((text, i) => ({
|
|
1057
1083
|
prefix: i === 0 ? prefix : " ".repeat(prefix.length),
|
|
@@ -2332,7 +2358,7 @@ async function ensureApplication(resumeAppId) {
|
|
|
2332
2358
|
// package.json
|
|
2333
2359
|
var package_default = {
|
|
2334
2360
|
name: "@algolia/wizard",
|
|
2335
|
-
version: "0.87.0
|
|
2361
|
+
version: "0.87.0",
|
|
2336
2362
|
description: "Magically implement Algolia functionality in your codebase",
|
|
2337
2363
|
type: "module",
|
|
2338
2364
|
engines: {
|
|
@@ -2805,9 +2831,6 @@ async function runWorkflow(workflow, startWorkflowAppId, options) {
|
|
|
2805
2831
|
}
|
|
2806
2832
|
}
|
|
2807
2833
|
|
|
2808
|
-
// src/actions/selectIndex.ts
|
|
2809
|
-
import { basename } from "node:path";
|
|
2810
|
-
|
|
2811
2834
|
// src/actions/listIndices.ts
|
|
2812
2835
|
import { z as z5 } from "zod";
|
|
2813
2836
|
var indicesListSchema = z5.object({
|
|
@@ -2842,28 +2865,11 @@ function indexNameError(name) {
|
|
|
2842
2865
|
return "Index name cannot end with .txt, .bin, or .idx.";
|
|
2843
2866
|
return void 0;
|
|
2844
2867
|
}
|
|
2845
|
-
function slug(text) {
|
|
2846
|
-
return text.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
2847
|
-
}
|
|
2848
|
-
function suggestIndexName(project, entity, taken) {
|
|
2849
|
-
const base = ([slug(project), slug(entity ?? "")].filter(Boolean).join("_") || "records").slice(0, MAX_INDEX_NAME_LENGTH);
|
|
2850
|
-
let name = base;
|
|
2851
|
-
for (let n = 2; taken.includes(name); n++) {
|
|
2852
|
-
const suffix = `_${n}`;
|
|
2853
|
-
name = base.slice(0, MAX_INDEX_NAME_LENGTH - suffix.length) + suffix;
|
|
2854
|
-
}
|
|
2855
|
-
return name;
|
|
2856
|
-
}
|
|
2857
2868
|
var selectIndexStep = async (ctx) => {
|
|
2858
2869
|
await requireApplication(ctx.appId);
|
|
2859
2870
|
const indices = await listIndices();
|
|
2860
2871
|
const names = indices.map((i) => i.name);
|
|
2861
2872
|
const hasIndices = names.length > 0;
|
|
2862
|
-
const entity = ctx.getStepOutput(
|
|
2863
|
-
"confirm-entities"
|
|
2864
|
-
)?.confirmedEntities?.[0]?.name;
|
|
2865
|
-
const suggested = suggestIndexName(basename(process.cwd()), entity, names);
|
|
2866
|
-
const suggestionHint = `Press Enter to use "${suggested}".`;
|
|
2867
2873
|
let error;
|
|
2868
2874
|
let chosen;
|
|
2869
2875
|
while (chosen === void 0) {
|
|
@@ -2878,8 +2884,7 @@ var selectIndexStep = async (ctx) => {
|
|
|
2878
2884
|
promptType: "textInput",
|
|
2879
2885
|
options: [],
|
|
2880
2886
|
messages: [
|
|
2881
|
-
"This app has no existing indices \u2014 enter a name to create one."
|
|
2882
|
-
suggestionHint
|
|
2887
|
+
"This app has no existing indices \u2014 enter a name to create one."
|
|
2883
2888
|
],
|
|
2884
2889
|
error
|
|
2885
2890
|
});
|
|
@@ -2889,18 +2894,17 @@ var selectIndexStep = async (ctx) => {
|
|
|
2889
2894
|
let candidate;
|
|
2890
2895
|
let isNewName = true;
|
|
2891
2896
|
if (!hasIndices) {
|
|
2892
|
-
candidate = selection.trim()
|
|
2897
|
+
candidate = selection.trim();
|
|
2893
2898
|
} else if (selection === CREATE_NEW_INDEX) {
|
|
2894
2899
|
const name = await ctx.requestUserInput({
|
|
2895
2900
|
prompt: "Name the new index:",
|
|
2896
2901
|
promptType: "textInput",
|
|
2897
|
-
options: []
|
|
2898
|
-
messages: [suggestionHint]
|
|
2902
|
+
options: []
|
|
2899
2903
|
});
|
|
2900
2904
|
if (typeof name !== "string") {
|
|
2901
2905
|
throw new Error("selectIndex received an unexpected non-text result");
|
|
2902
2906
|
}
|
|
2903
|
-
candidate = name.trim()
|
|
2907
|
+
candidate = name.trim();
|
|
2904
2908
|
} else {
|
|
2905
2909
|
candidate = selection;
|
|
2906
2910
|
isNewName = false;
|
|
@@ -3136,14 +3140,14 @@ import z9 from "zod";
|
|
|
3136
3140
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
3137
3141
|
|
|
3138
3142
|
// src/lib/tools/env.ts
|
|
3139
|
-
import { basename
|
|
3143
|
+
import { basename } from "node:path";
|
|
3140
3144
|
function isEnvFile(filePath) {
|
|
3141
|
-
const name =
|
|
3145
|
+
const name = basename(filePath);
|
|
3142
3146
|
return name === ".env" || name.startsWith(".env.");
|
|
3143
3147
|
}
|
|
3144
3148
|
function isSecretEnvFile(filePath) {
|
|
3145
3149
|
if (!isEnvFile(filePath)) return false;
|
|
3146
|
-
const name =
|
|
3150
|
+
const name = basename(filePath);
|
|
3147
3151
|
return !/\.(example|sample|template)$/.test(name);
|
|
3148
3152
|
}
|
|
3149
3153
|
function secretEnvWriteRefusal(filePath) {
|
|
@@ -3778,7 +3782,7 @@ import { execFile as execFile2 } from "node:child_process";
|
|
|
3778
3782
|
import { tool as tool8 } from "ai";
|
|
3779
3783
|
import z15 from "zod";
|
|
3780
3784
|
import { lstat as lstat3, readdir as readdir2, readFile as readFile8, realpath, stat as stat2 } from "node:fs/promises";
|
|
3781
|
-
import { basename as
|
|
3785
|
+
import { basename as basename2, isAbsolute as isAbsolute2, join as join8, relative as relative4, sep as sep2 } from "node:path";
|
|
3782
3786
|
import { performance } from "node:perf_hooks";
|
|
3783
3787
|
import { Worker } from "node:worker_threads";
|
|
3784
3788
|
var MAX_GIT_OUTPUT_BYTES = 32e6;
|
|
@@ -4121,7 +4125,7 @@ async function safeSearchPath(rootPath, file) {
|
|
|
4121
4125
|
}
|
|
4122
4126
|
async function searchableFiles(root, target) {
|
|
4123
4127
|
try {
|
|
4124
|
-
if (SKIP_FILES.has(
|
|
4128
|
+
if (SKIP_FILES.has(basename2(target)) && (await lstat3(target)).isFile()) {
|
|
4125
4129
|
return [target];
|
|
4126
4130
|
}
|
|
4127
4131
|
const gitRoot = await gitRootForTarget(root, target);
|
|
@@ -4300,7 +4304,7 @@ import { tool as tool9 } from "ai";
|
|
|
4300
4304
|
import z16 from "zod";
|
|
4301
4305
|
import { createHash as createHash2 } from "node:crypto";
|
|
4302
4306
|
import { readFile as readFile9, stat as stat3 } from "node:fs/promises";
|
|
4303
|
-
import { basename as
|
|
4307
|
+
import { basename as basename3, relative as relative5, resolve as resolve3 } from "node:path";
|
|
4304
4308
|
|
|
4305
4309
|
// src/lib/tools/utils/prompt.ts
|
|
4306
4310
|
var chain = Promise.resolve();
|
|
@@ -4398,7 +4402,7 @@ function commandDiffersFromReviewedScript(ctx, command, cwd) {
|
|
|
4398
4402
|
if (approval.command === command && approval.cwd === cwd) return false;
|
|
4399
4403
|
if (approval.command === command) return true;
|
|
4400
4404
|
const scriptReferences = [
|
|
4401
|
-
|
|
4405
|
+
basename3(approval.filePath),
|
|
4402
4406
|
relative5(ctx.root, approval.filePath),
|
|
4403
4407
|
".algolia-wizard"
|
|
4404
4408
|
];
|
|
@@ -5119,8 +5123,8 @@ function generateRecordTool(ctx, createModel = defaultCreateModel2) {
|
|
|
5119
5123
|
...record,
|
|
5120
5124
|
objectID: nanoid2()
|
|
5121
5125
|
}));
|
|
5122
|
-
const
|
|
5123
|
-
const relPath = `${DATA_DIR}/${
|
|
5126
|
+
const slug = entityName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
5127
|
+
const relPath = `${DATA_DIR}/${slug}.json`;
|
|
5124
5128
|
const resolved2 = resolveInRoot(ctx, relPath);
|
|
5125
5129
|
if (resolved2.ok === false) return resolved2.error;
|
|
5126
5130
|
const writeError = await safeWriteFile(
|
|
@@ -6073,7 +6077,7 @@ import {
|
|
|
6073
6077
|
// src/lib/git.ts
|
|
6074
6078
|
import { execFile as execFile3 } from "node:child_process";
|
|
6075
6079
|
import { copyFile, mkdir as mkdir4, stat as stat4 } from "node:fs/promises";
|
|
6076
|
-
import { basename as
|
|
6080
|
+
import { basename as basename4, dirname as dirname3, isAbsolute as isAbsolute3, join as join9, resolve as resolve4 } from "node:path";
|
|
6077
6081
|
var MAX_BUFFER = 32 * 1024 * 1024;
|
|
6078
6082
|
function git(args) {
|
|
6079
6083
|
return new Promise((resolve6, reject) => {
|
|
@@ -6110,7 +6114,7 @@ async function copyUploadIntoProject(repoRoot, ingestDir, sourcePath) {
|
|
|
6110
6114
|
} catch {
|
|
6111
6115
|
return { ok: false, reason: `"${sourcePath}" does not exist` };
|
|
6112
6116
|
}
|
|
6113
|
-
const relPath = join9(ingestDir,
|
|
6117
|
+
const relPath = join9(ingestDir, basename4(source));
|
|
6114
6118
|
const dest = join9(repoRoot, relPath);
|
|
6115
6119
|
if (resolve4(source) === resolve4(dest)) {
|
|
6116
6120
|
return { ok: true, relPath };
|
|
@@ -6268,7 +6272,6 @@ var INGEST_RETRY = {
|
|
|
6268
6272
|
retry: "Retry ingestion",
|
|
6269
6273
|
skip: "Continue without records"
|
|
6270
6274
|
};
|
|
6271
|
-
var INGEST_AGENT_RETRY_PROMPT = "Retry to let the wizard write and run the ingestion script again.";
|
|
6272
6275
|
var FILE_UPLOAD_PATH_PROMPT = "Enter the path to your JSON, CSV, or TSV file (relative to the project root, or absolute):";
|
|
6273
6276
|
var JS_LANGUAGES = ["javascript", "typescript", "jsx", "tsx", "node"];
|
|
6274
6277
|
function lower(entries) {
|
|
@@ -6495,29 +6498,9 @@ function cdnSearchInstructions(input) {
|
|
|
6495
6498
|
input.searchKey ? `Set window.${SEARCH_CONFIG_SEARCH_KEY} to "${input.searchKey}".` : `A real search-only key could not be provisioned${input.searchKeyError ? ` (${input.searchKeyError})` : ""} \u2014 set window.${SEARCH_CONFIG_SEARCH_KEY} to the placeholder "${SEARCH_KEY_PLACEHOLDER}" and add a prominent TODO for the developer to fill in a real one.`,
|
|
6496
6499
|
'Load these exact pinned tags in order before the config and search scripts: <script src="https://cdn.jsdelivr.net/npm/algoliasearch@5.59.0/dist/lite/builds/browser.umd.js" integrity="sha256-pduQHl1jn0IaN/BIpSotQm7Y5THdpKcX3Bw6xdRteRw=" crossorigin="anonymous"></script> then <script src="https://cdn.jsdelivr.net/npm/instantsearch.js@4.117.0/dist/instantsearch.production.min.js" integrity="sha256-5zhKxAGeH7ThWfnmdD4pS1gsmafE2b8aWRsq8set/dc=" crossorigin="anonymous"></script>.',
|
|
6497
6500
|
'When using the InstantSearch theme, load this exact tag before the application styles: <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/instantsearch.css@8.22.1/themes/satellite-min.css" integrity="sha256-5/eHPZl63VYJSDVOKrOgGe/5+owUkX3uPAW6+XYeLNc=" crossorigin="anonymous">. Never use an unversioned or differently versioned theme URL, and never omit its integrity attribute.',
|
|
6498
|
-
`In that classic search script, use window['algoliasearch/lite'].liteClient and window.instantsearch. Add window.instantsearch.widgets.autocomplete as the only search widget. Configure it with container '#autocomplete', the content-specific placeholder ${JSON.stringify(placeholder)}, and an indices array containing one object whose indexName is window.${SEARCH_CONFIG_INDEX_NAME}
|
|
6499
|
-
CDN_AUTOCOMPLETE_SHAPE
|
|
6501
|
+
`In that classic search script, use window['algoliasearch/lite'].liteClient and window.instantsearch. Add window.instantsearch.widgets.autocomplete as the only search widget. Configure it with container '#autocomplete', the content-specific placeholder ${JSON.stringify(placeholder)}, and an indices array containing one object whose indexName is window.${SEARCH_CONFIG_INDEX_NAME}; put item and noResults functions in its templates option, implement getURL only for an existing route, and match the item template to the entity schema. Keep insights: true and call search.start(). Do not substitute searchBox or hits, omit indices, use imports or exports, or use type="module".`
|
|
6500
6502
|
];
|
|
6501
6503
|
}
|
|
6502
|
-
var CDN_AUTOCOMPLETE_SHAPE = `Use this shape for the autocomplete call. Replace the item fields and the getURL route with the real record fields and an existing route:
|
|
6503
|
-
\`\`\`js
|
|
6504
|
-
window.instantsearch.widgets.autocomplete({
|
|
6505
|
-
container: '#autocomplete',
|
|
6506
|
-
placeholder: '...',
|
|
6507
|
-
indices: [
|
|
6508
|
-
{
|
|
6509
|
-
indexName: window.${SEARCH_CONFIG_INDEX_NAME},
|
|
6510
|
-
getURL: (item) => '/existing-route/' + item.slug,
|
|
6511
|
-
templates: {
|
|
6512
|
-
item: ({ item, onSelect }, { html, components }) =>
|
|
6513
|
-
html\`<div onClick=\${onSelect}>\${components.Highlight({ hit: item, attribute: 'name' })}</div>\`,
|
|
6514
|
-
noResults: (_, { html }) => html\`<span>No results</span>\`,
|
|
6515
|
-
},
|
|
6516
|
-
},
|
|
6517
|
-
],
|
|
6518
|
-
})
|
|
6519
|
-
\`\`\`
|
|
6520
|
-
The widget reads the item and noResults templates only from each indices entry. Its own top-level templates option accepts only panel. If item is not inside indices[].templates, the widget throws "Template must be 'string' or 'function', was 'undefined' (key: item)" on the first search and shows no results.`;
|
|
6521
6504
|
function validationInstructions(input) {
|
|
6522
6505
|
return [
|
|
6523
6506
|
"Validate the Algolia search implementation by inspecting the project source.",
|
|
@@ -6538,8 +6521,7 @@ function validationInstructions(input) {
|
|
|
6538
6521
|
"Do not modify files. Report each implementation issue as a concrete instruction for the next implementation pass.",
|
|
6539
6522
|
`Detected verification tools: ${JSON.stringify(input.findings.verification ?? [])}. Use only a type checker; ignore any linter or formatter in this list.`,
|
|
6540
6523
|
...!input.frontendHasPackageJson ? [
|
|
6541
|
-
"The frontend has no package.json: never create one or run npm, pnpm, yarn, or bun. Validate the CDN implementation by inspecting its HTML or template and classic scripts for the search container, Algolia \u2192 InstantSearch \u2192 config \u2192 search load order, browser globals, autocomplete widget configuration, search.start(), and exact pinned CDN URLs and integrity attributes for every Algolia script or stylesheet. Source inspection is required even when the project has no automated checks. window.instantsearch.widgets.autocomplete is a real widget in the pinned InstantSearch build; do not report its use as an error, and do not fetch a remote bundle or URL to verify it."
|
|
6542
|
-
"In the autocomplete call, confirm that the item and noResults templates are inside the templates option of the indices entry, not in the top-level templates option of the widget. The top-level templates option accepts only panel, so an item template there throws on the first search and no results show. If item is missing from indices[].templates, set sufficient=false and tell the next pass to move the templates into the indices entry."
|
|
6524
|
+
"The frontend has no package.json: never create one or run npm, pnpm, yarn, or bun. Validate the CDN implementation by inspecting its HTML or template and classic scripts for the search container, Algolia \u2192 InstantSearch \u2192 config \u2192 search load order, browser globals, autocomplete widget configuration, search.start(), and exact pinned CDN URLs and integrity attributes for every Algolia script or stylesheet. Source inspection is required even when the project has no automated checks. window.instantsearch.widgets.autocomplete is a real widget in the pinned InstantSearch build; do not report its use as an error, and do not fetch a remote bundle or URL to verify it."
|
|
6543
6525
|
] : [],
|
|
6544
6526
|
"Always call reportStatus with status=success after validation, even when sufficient=false.",
|
|
6545
6527
|
"Set sufficient=false if the input's computed accessible name is empty or generic, including when aria-labelledby references a missing or empty element; a placeholder does not count as the label.",
|
|
@@ -6679,8 +6661,8 @@ async function firstRecordIn(filePath) {
|
|
|
6679
6661
|
async function ingestedRecordSample(repoRoot, entityName, uploadFilePath) {
|
|
6680
6662
|
const candidates = [];
|
|
6681
6663
|
if (entityName) {
|
|
6682
|
-
const
|
|
6683
|
-
candidates.push(join11(repoRoot, INGEST_DIR, "data", `${
|
|
6664
|
+
const slug = entityName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
6665
|
+
candidates.push(join11(repoRoot, INGEST_DIR, "data", `${slug}.json`));
|
|
6684
6666
|
}
|
|
6685
6667
|
if (uploadFilePath?.toLowerCase().endsWith(".json")) {
|
|
6686
6668
|
candidates.push(join11(repoRoot, uploadFilePath));
|
|
@@ -6699,25 +6681,12 @@ function recordSchema(sample, attributes) {
|
|
|
6699
6681
|
}
|
|
6700
6682
|
return Object.fromEntries(attributes.map((key) => [key, "unknown"]));
|
|
6701
6683
|
}
|
|
6702
|
-
function
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
}) {
|
|
6708
|
-
if (agentFailure !== void 0) {
|
|
6709
|
-
return `the wizard stopped before it finished the ingestion script (${agentFailure || "no reason given"})`;
|
|
6710
|
-
}
|
|
6711
|
-
if (executions.some((e) => !e.approved)) {
|
|
6712
|
-
return "a command it needed was declined";
|
|
6713
|
-
}
|
|
6714
|
-
if (!ingestCommand) {
|
|
6715
|
-
return scriptPath ? `the ingestion script ${scriptPath} was written but not run` : "no ingestion script was written";
|
|
6684
|
+
function ingestFailure(attempt, executions) {
|
|
6685
|
+
if (!attempt) {
|
|
6686
|
+
return {
|
|
6687
|
+
reason: executions.some((e) => !e.approved) ? "a command it needed was declined" : "no successful run was recorded"
|
|
6688
|
+
};
|
|
6716
6689
|
}
|
|
6717
|
-
return "no successful run was recorded";
|
|
6718
|
-
}
|
|
6719
|
-
function ingestFailure(attempt, missingRunReason = "no successful run was recorded") {
|
|
6720
|
-
if (!attempt) return { reason: missingRunReason };
|
|
6721
6690
|
if (!attempt.approved) return { reason: "you declined to run it" };
|
|
6722
6691
|
const detail = errorLine(attempt.output);
|
|
6723
6692
|
if (attempt.timedOut) {
|
|
@@ -6759,9 +6728,6 @@ function briefSummary(summary) {
|
|
|
6759
6728
|
if (!firstLine) return "no summary given";
|
|
6760
6729
|
return firstLine.length > ERROR_SUMMARY_MAX_CHARS ? `${firstLine.slice(0, ERROR_SUMMARY_MAX_CHARS - 1)}\u2026` : firstLine;
|
|
6761
6730
|
}
|
|
6762
|
-
function ingestionRetryInstruction(reason) {
|
|
6763
|
-
return `The previous ingestion attempt ended with no successful run: ${reason}. Look in "${INGEST_DIR}/" for a script from that attempt and finish or fix it instead of starting over. Then call reviewScript and run the script as described above.`;
|
|
6764
|
-
}
|
|
6765
6731
|
function validationRetryInstructions(validation) {
|
|
6766
6732
|
return [
|
|
6767
6733
|
`Implementation insufficient. Address these findings before reporting completion: ${validation.additionalInstructions ?? validation.summary}`
|
|
@@ -7048,70 +7014,16 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
|
|
|
7048
7014
|
}
|
|
7049
7015
|
if (useCases.includes("ingestion")) {
|
|
7050
7016
|
let ingestFailureDetail;
|
|
7017
|
+
const result = await runImplementationUseCase("ingestion");
|
|
7018
|
+
summaries.push(formatSummary("ingestion", result.summary));
|
|
7019
|
+
ingestCommand = result.ingestCommand;
|
|
7051
7020
|
const ingestionContext = ingestionTools;
|
|
7052
7021
|
const executions = ingestionContext.shell.executions;
|
|
7053
|
-
let agentFailure;
|
|
7054
|
-
const runIngestionAgent = async (extraInstructions = []) => {
|
|
7055
|
-
const isRetry = extraInstructions.length > 0;
|
|
7056
|
-
if (isRetry) {
|
|
7057
|
-
resetToolCounts(ingestionContext);
|
|
7058
|
-
ingestionContext.cwd = ingestionContext.root;
|
|
7059
|
-
}
|
|
7060
|
-
try {
|
|
7061
|
-
const result = await runImplementationUseCase(
|
|
7062
|
-
"ingestion",
|
|
7063
|
-
extraInstructions,
|
|
7064
|
-
isRetry
|
|
7065
|
-
);
|
|
7066
|
-
summaries.push(formatSummary("ingestion", result.summary));
|
|
7067
|
-
ingestCommand = result.ingestCommand ?? ingestCommand;
|
|
7068
|
-
agentFailure = void 0;
|
|
7069
|
-
} catch (err) {
|
|
7070
|
-
if (!(err instanceof AgentReportedFailureError)) throw err;
|
|
7071
|
-
agentFailure = err.reason ?? "";
|
|
7072
|
-
summaries.push(
|
|
7073
|
-
formatSummary(
|
|
7074
|
-
"ingestion",
|
|
7075
|
-
`Stopped before the script was finished: ${err.reason ?? "no reason given"}`
|
|
7076
|
-
)
|
|
7077
|
-
);
|
|
7078
|
-
logger.warn(
|
|
7079
|
-
{ reason: err.reason, counts: ingestionContext.counts },
|
|
7080
|
-
"implement: ingestion agent reported fail"
|
|
7081
|
-
);
|
|
7082
|
-
}
|
|
7083
|
-
};
|
|
7084
|
-
const currentNoRunReason = async () => noRunReason({
|
|
7085
|
-
agentFailure,
|
|
7086
|
-
executions,
|
|
7087
|
-
ingestCommand,
|
|
7088
|
-
scriptPath: await findIngestionScript(
|
|
7089
|
-
repoRoot,
|
|
7090
|
-
INGEST_DIR,
|
|
7091
|
-
ingestCommand
|
|
7092
|
-
)
|
|
7093
|
-
});
|
|
7094
|
-
await runIngestionAgent();
|
|
7095
7022
|
let outcome = ingestOutcome(executions, repoRoot, ingestCommand);
|
|
7096
7023
|
let failureAcknowledged = false;
|
|
7097
|
-
while (!outcome.run &&
|
|
7098
|
-
const reason = await currentNoRunReason();
|
|
7099
|
-
const choice = await ctx.requestUserInput({
|
|
7100
|
-
prompt: INGEST_AGENT_RETRY_PROMPT,
|
|
7101
|
-
promptType: "multipleChoice",
|
|
7102
|
-
options: [INGEST_RETRY.retry, INGEST_RETRY.skip],
|
|
7103
|
-
messages: [`\u26A0\uFE0F Records were not indexed \u2014 ${reason}.`]
|
|
7104
|
-
});
|
|
7105
|
-
if (choice !== INGEST_RETRY.retry) {
|
|
7106
|
-
failureAcknowledged = true;
|
|
7107
|
-
break;
|
|
7108
|
-
}
|
|
7109
|
-
await runIngestionAgent([ingestionRetryInstruction(reason)]);
|
|
7110
|
-
outcome = ingestOutcome(executions, repoRoot, ingestCommand);
|
|
7111
|
-
}
|
|
7112
|
-
while (!failureAcknowledged && !outcome.run && outcome.attempt?.approved) {
|
|
7024
|
+
while (!outcome.run && outcome.attempt?.approved) {
|
|
7113
7025
|
const attempt = outcome.attempt;
|
|
7114
|
-
const { reason, detail } = ingestFailure(attempt);
|
|
7026
|
+
const { reason, detail } = ingestFailure(attempt, executions);
|
|
7115
7027
|
const choice = await ctx.requestUserInput({
|
|
7116
7028
|
prompt: INGEST_RETRY_PROMPT,
|
|
7117
7029
|
promptType: "multipleChoice",
|
|
@@ -7187,10 +7099,7 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
|
|
|
7187
7099
|
);
|
|
7188
7100
|
}
|
|
7189
7101
|
} else {
|
|
7190
|
-
const { reason, detail } = ingestFailure(
|
|
7191
|
-
ingestAttempt,
|
|
7192
|
-
await currentNoRunReason()
|
|
7193
|
-
);
|
|
7102
|
+
const { reason, detail } = ingestFailure(ingestAttempt, executions);
|
|
7194
7103
|
ingestOutcomeMessage = `\u26A0\uFE0F Records were not indexed \u2014 ${reason}.${ingestCommand ? " Run the command below when you are ready." : ""}`;
|
|
7195
7104
|
ingestFailureDetail = detail;
|
|
7196
7105
|
summaries.push(
|
|
@@ -7477,25 +7386,14 @@ var defaultWorkflow = {
|
|
|
7477
7386
|
"ingestion"
|
|
7478
7387
|
);
|
|
7479
7388
|
return reviewStep(ctx, {
|
|
7480
|
-
|
|
7389
|
+
// ingestCommand was already shown verbatim as a notice; an
|
|
7390
|
+
// LLM-paraphrased restatement in nextSteps risks being wrong.
|
|
7391
|
+
nextStepsGuidance: ingestion2?.ingestScriptRan ? "The wizard already ran the ingestion script and records are in the index. Do NOT tell the user to run it again; instead point them at the target index to confirm the records. Do not restate the ingestion command \u2014 the wizard already showed it to them." : "Tell the user to run the ingestion script; do not restate the exact command \u2014 the wizard already showed it to them above."
|
|
7481
7392
|
});
|
|
7482
7393
|
}
|
|
7483
7394
|
})
|
|
7484
7395
|
]
|
|
7485
7396
|
};
|
|
7486
|
-
function ingestionGuidance(ingestion2) {
|
|
7487
|
-
if (ingestion2?.ingestScriptRan) {
|
|
7488
|
-
return "The wizard already ran the ingestion script and records are in the index. Do NOT tell the user to run it again; instead point them at the target index to confirm the records. Do not restate the ingestion command \u2014 the wizard already showed it to them.";
|
|
7489
|
-
}
|
|
7490
|
-
const partialCount = ingestion2?.ingestRecordCount ?? 0;
|
|
7491
|
-
if (partialCount > 0) {
|
|
7492
|
-
return `The ingestion script indexed ${partialCount} record(s) and then failed before it finished. Say that plainly. Do not say that ingestion succeeded or that no records were indexed. Tell the user to fix the error shown above and run the ingestion script again. Do not restate the exact command, because the wizard already showed it to them above.`;
|
|
7493
|
-
}
|
|
7494
|
-
if (ingestion2?.ingestCommand) {
|
|
7495
|
-
return "No records were indexed in this run. Say that plainly, and do not say that the wizard created or populated an index. Tell the user to run the ingestion script; do not restate the exact command \u2014 the wizard already showed it to them above.";
|
|
7496
|
-
}
|
|
7497
|
-
return "No ingestion script ran and no records were indexed in this run. Say that plainly. Do not say that the wizard created, selected, or populated an index, and do not tell the user to run an ingestion script, because the wizard has no tested command for one. Tell the user to run the wizard again to create and run the ingestion script.";
|
|
7498
|
-
}
|
|
7499
7397
|
|
|
7500
7398
|
// src/actions/playbookSteps/selectPlaybook.ts
|
|
7501
7399
|
import { z as z33 } from "zod";
|
|
@@ -7628,9 +7526,9 @@ async function getPlaybooks() {
|
|
|
7628
7526
|
);
|
|
7629
7527
|
return data;
|
|
7630
7528
|
}
|
|
7631
|
-
async function createPlaybookExecution(appId,
|
|
7529
|
+
async function createPlaybookExecution(appId, slug, indexName, options) {
|
|
7632
7530
|
const { data } = await dashboardRequest(
|
|
7633
|
-
`/api/1/playbook-integrations/applications/${appId}/playbooks/${
|
|
7531
|
+
`/api/1/playbook-integrations/applications/${appId}/playbooks/${slug}/executions`,
|
|
7634
7532
|
playbookExecutionCreateResponseSchema,
|
|
7635
7533
|
{
|
|
7636
7534
|
method: "POST",
|
|
@@ -7671,9 +7569,9 @@ async function assessPlaybookExecution(uuid) {
|
|
|
7671
7569
|
var selectPlaybookSchema = z33.object({
|
|
7672
7570
|
slug: z33.string()
|
|
7673
7571
|
});
|
|
7674
|
-
function persistSlug(ctx,
|
|
7675
|
-
ctx.setUserInput("playbookSlug",
|
|
7676
|
-
return { slug
|
|
7572
|
+
function persistSlug(ctx, slug) {
|
|
7573
|
+
ctx.setUserInput("playbookSlug", slug);
|
|
7574
|
+
return { slug };
|
|
7677
7575
|
}
|
|
7678
7576
|
async function selectPlaybookStep(ctx, requestedSlug) {
|
|
7679
7577
|
const playbooks = await getPlaybooks();
|
|
@@ -7804,13 +7702,13 @@ async function confirmIndexStep(ctx) {
|
|
|
7804
7702
|
if (!sampleIndex) {
|
|
7805
7703
|
return null;
|
|
7806
7704
|
}
|
|
7807
|
-
const { slug
|
|
7705
|
+
const { slug } = ctx.getStepOutput("select-playbook");
|
|
7808
7706
|
const selection = await ctx.requestUserInput({
|
|
7809
7707
|
prompt: "Ready to create sample index?",
|
|
7810
7708
|
promptType: "multipleChoice",
|
|
7811
7709
|
options: [CONTINUE_OPTION, GO_BACK_OPTION2],
|
|
7812
7710
|
messages: [
|
|
7813
|
-
`A new index called "algolia_playbooks_${
|
|
7711
|
+
`A new index called "algolia_playbooks_${slug}_sample_index" will be created with sample ${slug} data.`
|
|
7814
7712
|
],
|
|
7815
7713
|
helpText: "Going back lets you choose a different index."
|
|
7816
7714
|
});
|
|
@@ -7962,13 +7860,13 @@ var POLL_NOTICES = [
|
|
|
7962
7860
|
{ message: "detecting required fields\u2026" }
|
|
7963
7861
|
];
|
|
7964
7862
|
async function dataAssessmentStep(ctx) {
|
|
7965
|
-
const { slug
|
|
7863
|
+
const { slug } = ctx.getStepOutput("select-playbook");
|
|
7966
7864
|
const { indexName, existingExecution } = indexForAssessment(ctx);
|
|
7967
7865
|
if (existingExecution) return existingExecution;
|
|
7968
7866
|
try {
|
|
7969
7867
|
showNotice(ctx, CREATING_EXECUTION_NOTICE);
|
|
7970
7868
|
const { id: appId } = await requireApplication();
|
|
7971
|
-
const execution = await resolveExecution(ctx, appId,
|
|
7869
|
+
const execution = await resolveExecution(ctx, appId, slug, indexName);
|
|
7972
7870
|
const assessed = await runAssessment(ctx, execution, indexName);
|
|
7973
7871
|
ctx.clearNotices();
|
|
7974
7872
|
await promptReady(ctx, assessed);
|
|
@@ -8073,24 +7971,24 @@ function unexpectedAssessmentStatus(status) {
|
|
|
8073
7971
|
`data-assessment received an unexpected assessment status: ${status}`
|
|
8074
7972
|
);
|
|
8075
7973
|
}
|
|
8076
|
-
async function resolveExecution(ctx, appId,
|
|
8077
|
-
const created = await createWithRecovery(ctx, appId,
|
|
7974
|
+
async function resolveExecution(ctx, appId, slug, indexName) {
|
|
7975
|
+
const created = await createWithRecovery(ctx, appId, slug, indexName);
|
|
8078
7976
|
if (!created.resumed) return created;
|
|
8079
7977
|
const choice = await promptResumeExecution(ctx, indexName);
|
|
8080
7978
|
if (choice === CONTINUE_EXECUTION_OPTION) return created;
|
|
8081
7979
|
if (choice === RESTART_OPTION) {
|
|
8082
|
-
return createWithRecovery(ctx, appId,
|
|
7980
|
+
return createWithRecovery(ctx, appId, slug, indexName, { forceNew: true });
|
|
8083
7981
|
}
|
|
8084
7982
|
if (choice === GO_BACK_OPTION3) {
|
|
8085
7983
|
return ctx.returnToStep("select-index");
|
|
8086
7984
|
}
|
|
8087
7985
|
throw new Error("data-assessment received an unexpected execution choice");
|
|
8088
7986
|
}
|
|
8089
|
-
async function createWithRecovery(ctx, appId,
|
|
7987
|
+
async function createWithRecovery(ctx, appId, slug, indexName, options) {
|
|
8090
7988
|
return retryOnDashboardError(
|
|
8091
7989
|
() => {
|
|
8092
7990
|
showNotice(ctx, CREATING_EXECUTION_NOTICE);
|
|
8093
|
-
return createPlaybookExecution(appId,
|
|
7991
|
+
return createPlaybookExecution(appId, slug, indexName, options);
|
|
8094
7992
|
},
|
|
8095
7993
|
onRequestFailure(ctx, indexName)
|
|
8096
7994
|
);
|
|
@@ -8692,10 +8590,15 @@ var sidebarCommands = [
|
|
|
8692
8590
|
{ keyHint: "tab", description: "toggle logs" },
|
|
8693
8591
|
{ keyHint: "esc", description: "exit wizard" }
|
|
8694
8592
|
];
|
|
8593
|
+
var logsSidebarCommands = [
|
|
8594
|
+
{ keyHint: "tab", description: "toggle logs" },
|
|
8595
|
+
{ keyHint: "esc", description: "back" }
|
|
8596
|
+
];
|
|
8695
8597
|
|
|
8696
8598
|
// src/ui/Sidebar.tsx
|
|
8697
8599
|
import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
8698
|
-
function Sidebar() {
|
|
8600
|
+
function Sidebar({ inLogs = false }) {
|
|
8601
|
+
const commands = inLogs ? logsSidebarCommands : sidebarCommands;
|
|
8699
8602
|
return /* @__PURE__ */ jsxs16(
|
|
8700
8603
|
Box17,
|
|
8701
8604
|
{
|
|
@@ -8712,7 +8615,7 @@ function Sidebar() {
|
|
|
8712
8615
|
] }),
|
|
8713
8616
|
/* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", gap: 1, children: [
|
|
8714
8617
|
/* @__PURE__ */ jsx16(Progress, {}),
|
|
8715
|
-
/* @__PURE__ */ jsx16(Box17, { flexDirection: "column", children:
|
|
8618
|
+
/* @__PURE__ */ jsx16(Box17, { flexDirection: "column", children: commands.map((c) => {
|
|
8716
8619
|
return /* @__PURE__ */ jsxs16(Box17, { flexDirection: "row", gap: 1, children: [
|
|
8717
8620
|
/* @__PURE__ */ jsx16(Text18, { color: COLORS.primary, children: `[${c.keyHint}]` }),
|
|
8718
8621
|
/* @__PURE__ */ jsx16(Text18, { color: COLORS.muted, children: c.description })
|
|
@@ -8750,23 +8653,130 @@ function Ribbon() {
|
|
|
8750
8653
|
}
|
|
8751
8654
|
|
|
8752
8655
|
// src/ui/App.tsx
|
|
8753
|
-
import { useState as
|
|
8656
|
+
import { useState as useState14 } from "react";
|
|
8754
8657
|
|
|
8755
8658
|
// src/ui/Logs.tsx
|
|
8659
|
+
import { Box as Box20, Text as Text21, useInput as useInput9 } from "ink";
|
|
8660
|
+
import { useLayoutEffect as useLayoutEffect6, useState as useState12 } from "react";
|
|
8661
|
+
|
|
8662
|
+
// src/ui/LogDetails.tsx
|
|
8756
8663
|
import { Box as Box19, Text as Text20, useInput as useInput8 } from "ink";
|
|
8757
|
-
import {
|
|
8664
|
+
import { useLayoutEffect as useLayoutEffect5, useMemo, useState as useState11 } from "react";
|
|
8665
|
+
|
|
8666
|
+
// src/ui/logFormat.ts
|
|
8758
8667
|
var KIND_COLOR = {
|
|
8759
8668
|
tool: COLORS.primary,
|
|
8760
|
-
prompt: COLORS.badge
|
|
8669
|
+
prompt: COLORS.badge,
|
|
8670
|
+
output: COLORS.muted
|
|
8671
|
+
};
|
|
8672
|
+
var STREAM_COLOR = {
|
|
8673
|
+
stderr: COLORS.muted,
|
|
8674
|
+
stdout: COLORS.dim
|
|
8761
8675
|
};
|
|
8762
8676
|
var STATUS_COLOR = {
|
|
8763
8677
|
running: COLORS.status.running,
|
|
8764
8678
|
error: COLORS.danger
|
|
8765
8679
|
};
|
|
8766
8680
|
function logNameColor(entry) {
|
|
8767
|
-
|
|
8681
|
+
const base = entry.stream ? STREAM_COLOR[entry.stream] : KIND_COLOR[entry.kind];
|
|
8682
|
+
return STATUS_COLOR[entry.status] ?? base;
|
|
8683
|
+
}
|
|
8684
|
+
function formatTimestamp(ms) {
|
|
8685
|
+
const d = new Date(ms);
|
|
8686
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
8687
|
+
return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
|
8688
|
+
}
|
|
8689
|
+
function durationText(entry) {
|
|
8690
|
+
return entry.kind === "tool" && entry.durationMs !== void 0 ? `${entry.durationMs}ms` : "";
|
|
8691
|
+
}
|
|
8692
|
+
|
|
8693
|
+
// src/ui/LogDetails.tsx
|
|
8694
|
+
import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
8695
|
+
var BLANK4 = { text: " ", color: COLORS.dim };
|
|
8696
|
+
var VALUE_INDENT = " ";
|
|
8697
|
+
var TAB = " ";
|
|
8698
|
+
function wrapLines(text, width, line, indent = "") {
|
|
8699
|
+
return wrapExact(
|
|
8700
|
+
text.replaceAll(" ", TAB),
|
|
8701
|
+
Math.max(width - indent.length, 1)
|
|
8702
|
+
).map((part) => ({ ...line, text: indent + part }));
|
|
8703
|
+
}
|
|
8704
|
+
function formatValue(value) {
|
|
8705
|
+
return typeof value === "string" ? value : JSON.stringify(value, null, 2);
|
|
8706
|
+
}
|
|
8707
|
+
function inputFields(input) {
|
|
8708
|
+
if (input === void 0) return [];
|
|
8709
|
+
if (input !== null && typeof input === "object" && !Array.isArray(input)) {
|
|
8710
|
+
return Object.entries(input).filter(([, value]) => value !== void 0).map(([label, value]) => [label, formatValue(value)]);
|
|
8711
|
+
}
|
|
8712
|
+
return [["input", formatValue(input)]];
|
|
8713
|
+
}
|
|
8714
|
+
function metaText(entry) {
|
|
8715
|
+
const parts = [`[${formatTimestamp(entry.startedAt)}]`];
|
|
8716
|
+
if (entry.kind === "tool") parts.push(entry.status, durationText(entry));
|
|
8717
|
+
return parts.filter(Boolean).join(" ");
|
|
8718
|
+
}
|
|
8719
|
+
function buildDetailLines(entry, width) {
|
|
8720
|
+
const lines = wrapLines(entry.name, width, {
|
|
8721
|
+
color: logNameColor(entry),
|
|
8722
|
+
bold: true
|
|
8723
|
+
});
|
|
8724
|
+
lines.push({ text: metaText(entry), color: COLORS.dim });
|
|
8725
|
+
for (const [label, value] of inputFields(entry.input)) {
|
|
8726
|
+
lines.push(BLANK4, { text: label, color: COLORS.muted });
|
|
8727
|
+
lines.push(
|
|
8728
|
+
...wrapLines(value, width, { color: COLORS.primary }, VALUE_INDENT)
|
|
8729
|
+
);
|
|
8730
|
+
}
|
|
8731
|
+
return lines;
|
|
8732
|
+
}
|
|
8733
|
+
function LogDetails({
|
|
8734
|
+
entry,
|
|
8735
|
+
onClose
|
|
8736
|
+
}) {
|
|
8737
|
+
const [width, setWidth] = useState11(0);
|
|
8738
|
+
const lines = useMemo(
|
|
8739
|
+
() => width > 0 ? buildDetailLines(entry, width) : [],
|
|
8740
|
+
[entry, width]
|
|
8741
|
+
);
|
|
8742
|
+
const scroll = useScrollWindow({ itemCount: lines.length });
|
|
8743
|
+
useLayoutEffect5(() => {
|
|
8744
|
+
if (scroll.measured) setWidth(scroll.width);
|
|
8745
|
+
}, [scroll.measured, scroll.width]);
|
|
8746
|
+
useInput8((input, key) => {
|
|
8747
|
+
if (input === "k" || key.upArrow) scroll.scrollBy(-1);
|
|
8748
|
+
else if (input === "j" || key.downArrow) scroll.scrollBy(1);
|
|
8749
|
+
else if (key.escape) onClose();
|
|
8750
|
+
});
|
|
8751
|
+
const visible = lines.slice(scroll.offset, scroll.offset + scroll.capacity);
|
|
8752
|
+
return /* @__PURE__ */ jsxs18(Box19, { flexDirection: "column", flexGrow: 1, children: [
|
|
8753
|
+
/* @__PURE__ */ jsx18(ScrollView, { scroll, children: visible.map((line, i) => /* @__PURE__ */ jsx18(
|
|
8754
|
+
Text20,
|
|
8755
|
+
{
|
|
8756
|
+
color: line.color,
|
|
8757
|
+
bold: line.bold,
|
|
8758
|
+
wrap: "truncate",
|
|
8759
|
+
children: line.text
|
|
8760
|
+
},
|
|
8761
|
+
`detail-${scroll.offset + i}`
|
|
8762
|
+
)) }),
|
|
8763
|
+
/* @__PURE__ */ jsxs18(Box19, { gap: 2, children: [
|
|
8764
|
+
scroll.maxOffset > 0 && /* @__PURE__ */ jsxs18(Text20, { children: [
|
|
8765
|
+
/* @__PURE__ */ jsx18(Text20, { color: COLORS.primary, children: "[j] [k]" }),
|
|
8766
|
+
/* @__PURE__ */ jsx18(Text20, { color: COLORS.dim, children: " scroll" })
|
|
8767
|
+
] }),
|
|
8768
|
+
/* @__PURE__ */ jsxs18(Text20, { children: [
|
|
8769
|
+
/* @__PURE__ */ jsx18(Text20, { color: COLORS.primary, children: "[esc]" }),
|
|
8770
|
+
/* @__PURE__ */ jsx18(Text20, { color: COLORS.dim, children: " back" })
|
|
8771
|
+
] })
|
|
8772
|
+
] })
|
|
8773
|
+
] });
|
|
8768
8774
|
}
|
|
8775
|
+
|
|
8776
|
+
// src/ui/Logs.tsx
|
|
8777
|
+
import { Fragment, jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
8769
8778
|
var ROW_GAP = 1;
|
|
8779
|
+
var SELECTED_MARKER = "\u276F";
|
|
8770
8780
|
function truncate3(str, maxWidth) {
|
|
8771
8781
|
if (maxWidth <= 0) return "";
|
|
8772
8782
|
return str.length > maxWidth ? `${str.slice(0, maxWidth - 1)}\u2026` : str;
|
|
@@ -8777,53 +8787,84 @@ function rawInputText(input) {
|
|
|
8777
8787
|
if (!str || str === "{}") return "";
|
|
8778
8788
|
return str.replace(/\s+/g, " ").trim();
|
|
8779
8789
|
}
|
|
8780
|
-
function
|
|
8781
|
-
const d = new Date(ms);
|
|
8782
|
-
const pad = (n) => String(n).padStart(2, "0");
|
|
8783
|
-
return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
|
8784
|
-
}
|
|
8785
|
-
function Logs() {
|
|
8790
|
+
function Logs({ onBack }) {
|
|
8786
8791
|
const logs = useWizard((s) => s.logs);
|
|
8787
|
-
const
|
|
8788
|
-
|
|
8789
|
-
|
|
8790
|
-
|
|
8792
|
+
const [openLogId, setOpenLogId] = useState12(null);
|
|
8793
|
+
const [selectedId, setSelectedId] = useState12(null);
|
|
8794
|
+
const found = selectedId === null ? -1 : logs.findIndex((e) => e.id === selectedId);
|
|
8795
|
+
if (selectedId !== null && found < 0) setSelectedId(null);
|
|
8796
|
+
const scroll = useScrollWindow({
|
|
8797
|
+
itemCount: logs.length,
|
|
8798
|
+
followBottom: selectedId === null
|
|
8791
8799
|
});
|
|
8800
|
+
const selectedIndex = found >= 0 ? found : logs.length - 1;
|
|
8801
|
+
const openEntry = logs.find((e) => e.id === openLogId);
|
|
8802
|
+
const { revealIndex } = scroll;
|
|
8803
|
+
useLayoutEffect6(() => {
|
|
8804
|
+
if (selectedIndex >= 0) revealIndex(selectedIndex);
|
|
8805
|
+
}, [selectedIndex, revealIndex]);
|
|
8806
|
+
const moveSelection = (delta) => {
|
|
8807
|
+
if (logs.length === 0) return;
|
|
8808
|
+
const next = Math.min(Math.max(selectedIndex + delta, 0), logs.length - 1);
|
|
8809
|
+
setSelectedId(next === logs.length - 1 ? null : logs[next].id);
|
|
8810
|
+
};
|
|
8811
|
+
useInput9(
|
|
8812
|
+
(input, key) => {
|
|
8813
|
+
if (input === "k" || key.upArrow) moveSelection(-1);
|
|
8814
|
+
else if (input === "j" || key.downArrow) moveSelection(1);
|
|
8815
|
+
else if (key.return && logs[selectedIndex]) {
|
|
8816
|
+
setOpenLogId(logs[selectedIndex].id);
|
|
8817
|
+
} else if (key.escape) onBack();
|
|
8818
|
+
},
|
|
8819
|
+
{ isActive: !openEntry }
|
|
8820
|
+
);
|
|
8792
8821
|
const visible = logs.slice(scroll.offset, scroll.offset + scroll.capacity);
|
|
8793
|
-
return /* @__PURE__ */
|
|
8794
|
-
logs.length === 0 && /* @__PURE__ */
|
|
8795
|
-
/* @__PURE__ */
|
|
8822
|
+
return /* @__PURE__ */ jsx19(Box20, { flexDirection: "column", paddingX: 4, paddingY: 2, flexGrow: 1, children: openEntry ? /* @__PURE__ */ jsx19(LogDetails, { entry: openEntry, onClose: () => setOpenLogId(null) }) : /* @__PURE__ */ jsxs19(Fragment, { children: [
|
|
8823
|
+
logs.length === 0 && /* @__PURE__ */ jsx19(Text21, { color: COLORS.dim, children: "No logs yet." }),
|
|
8824
|
+
/* @__PURE__ */ jsx19(ScrollView, { scroll, children: visible.map((entry, i) => {
|
|
8825
|
+
const selected = scroll.offset + i === selectedIndex;
|
|
8796
8826
|
const timestamp = `[${formatTimestamp(entry.startedAt)}]`;
|
|
8797
|
-
const
|
|
8827
|
+
const duration = durationText(entry);
|
|
8798
8828
|
const rawPreview = rawInputText(entry.input);
|
|
8799
|
-
const partCount =
|
|
8829
|
+
const partCount = 3 + (rawPreview ? 1 : 0) + (duration ? 1 : 0);
|
|
8800
8830
|
const gaps = (partCount - 1) * ROW_GAP;
|
|
8801
|
-
let budget = scroll.width - timestamp.length -
|
|
8831
|
+
let budget = scroll.width - SELECTED_MARKER.length - timestamp.length - duration.length - gaps;
|
|
8802
8832
|
const name = truncate3(entry.name, budget);
|
|
8803
8833
|
budget -= name.length;
|
|
8804
8834
|
const preview = rawPreview ? truncate3(rawPreview, budget) : "";
|
|
8805
|
-
return /* @__PURE__ */
|
|
8806
|
-
/* @__PURE__ */
|
|
8807
|
-
/* @__PURE__ */
|
|
8808
|
-
|
|
8809
|
-
|
|
8835
|
+
return /* @__PURE__ */ jsxs19(Box20, { flexDirection: "row", gap: ROW_GAP, children: [
|
|
8836
|
+
/* @__PURE__ */ jsx19(Text21, { color: COLORS.success, children: selected ? SELECTED_MARKER : " " }),
|
|
8837
|
+
/* @__PURE__ */ jsx19(Text21, { color: COLORS.dim, children: timestamp }),
|
|
8838
|
+
/* @__PURE__ */ jsx19(Text21, { color: logNameColor(entry), wrap: "truncate", children: name }),
|
|
8839
|
+
preview && /* @__PURE__ */ jsx19(Text21, { color: COLORS.dim, wrap: "truncate", children: preview }),
|
|
8840
|
+
duration && /* @__PURE__ */ jsx19(Text21, { color: COLORS.dim, children: duration })
|
|
8810
8841
|
] }, entry.id);
|
|
8811
8842
|
}) }),
|
|
8812
|
-
/* @__PURE__ */
|
|
8813
|
-
/* @__PURE__ */
|
|
8814
|
-
|
|
8843
|
+
/* @__PURE__ */ jsxs19(Box20, { gap: 2, children: [
|
|
8844
|
+
/* @__PURE__ */ jsxs19(Text21, { children: [
|
|
8845
|
+
/* @__PURE__ */ jsx19(Text21, { color: COLORS.primary, children: "[j] [k]" }),
|
|
8846
|
+
/* @__PURE__ */ jsx19(Text21, { color: COLORS.dim, children: " select" })
|
|
8847
|
+
] }),
|
|
8848
|
+
/* @__PURE__ */ jsxs19(Text21, { children: [
|
|
8849
|
+
/* @__PURE__ */ jsx19(Text21, { color: COLORS.primary, children: "[enter]" }),
|
|
8850
|
+
/* @__PURE__ */ jsx19(Text21, { color: COLORS.dim, children: " details" })
|
|
8851
|
+
] }),
|
|
8852
|
+
/* @__PURE__ */ jsxs19(Text21, { children: [
|
|
8853
|
+
/* @__PURE__ */ jsx19(Text21, { color: COLORS.primary, children: "[esc]" }),
|
|
8854
|
+
/* @__PURE__ */ jsx19(Text21, { color: COLORS.dim, children: " back" })
|
|
8855
|
+
] })
|
|
8815
8856
|
] })
|
|
8816
|
-
] });
|
|
8857
|
+
] }) });
|
|
8817
8858
|
}
|
|
8818
8859
|
|
|
8819
8860
|
// src/ui/Tips.tsx
|
|
8820
|
-
import { useEffect as useEffect3, useRef as useRef4, useState as
|
|
8821
|
-
import { Box as
|
|
8861
|
+
import { useEffect as useEffect3, useRef as useRef4, useState as useState13 } from "react";
|
|
8862
|
+
import { Box as Box22, Text as Text23 } from "ink";
|
|
8822
8863
|
import terminalLink from "terminal-link";
|
|
8823
8864
|
|
|
8824
8865
|
// src/ui/Code.tsx
|
|
8825
|
-
import { Box as
|
|
8826
|
-
import { jsx as
|
|
8866
|
+
import { Box as Box21, Text as Text22 } from "ink";
|
|
8867
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
8827
8868
|
var TOKEN_RE = /("(?:\\.|[^"\\])*"|\btrue\b|\bfalse\b|\bnull\b|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|[{}[\]:,])/g;
|
|
8828
8869
|
function highlightJson(json) {
|
|
8829
8870
|
const parts = json.split(TOKEN_RE);
|
|
@@ -8832,22 +8873,22 @@ function highlightJson(json) {
|
|
|
8832
8873
|
if (part[0] === '"') {
|
|
8833
8874
|
const next = parts.slice(i + 1).find((p) => p.trim());
|
|
8834
8875
|
const isKey = next?.trimStart().startsWith(":");
|
|
8835
|
-
return /* @__PURE__ */
|
|
8876
|
+
return /* @__PURE__ */ jsx20(Text22, { color: isKey ? "cyan" : "green", children: part }, i);
|
|
8836
8877
|
}
|
|
8837
8878
|
if (part === "true" || part === "false" || part === "null") {
|
|
8838
|
-
return /* @__PURE__ */
|
|
8879
|
+
return /* @__PURE__ */ jsx20(Text22, { color: "magenta", children: part }, i);
|
|
8839
8880
|
}
|
|
8840
8881
|
if (/^-?\d/.test(part)) {
|
|
8841
|
-
return /* @__PURE__ */
|
|
8882
|
+
return /* @__PURE__ */ jsx20(Text22, { color: "yellow", children: part }, i);
|
|
8842
8883
|
}
|
|
8843
8884
|
if (/^[{}[\]:,]$/.test(part)) {
|
|
8844
|
-
return /* @__PURE__ */
|
|
8885
|
+
return /* @__PURE__ */ jsx20(Text22, { color: COLORS.dim, children: part }, i);
|
|
8845
8886
|
}
|
|
8846
|
-
return /* @__PURE__ */
|
|
8887
|
+
return /* @__PURE__ */ jsx20(Text22, { children: part }, i);
|
|
8847
8888
|
});
|
|
8848
8889
|
}
|
|
8849
8890
|
function Code({ children }) {
|
|
8850
|
-
return /* @__PURE__ */
|
|
8891
|
+
return /* @__PURE__ */ jsx20(Box21, { children: /* @__PURE__ */ jsx20(Text22, { children: highlightJson(children) }) });
|
|
8851
8892
|
}
|
|
8852
8893
|
|
|
8853
8894
|
// src/ui/copy/tips.ts
|
|
@@ -9043,26 +9084,26 @@ var tips = [
|
|
|
9043
9084
|
];
|
|
9044
9085
|
|
|
9045
9086
|
// src/ui/Tips.tsx
|
|
9046
|
-
import { jsx as
|
|
9087
|
+
import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
9047
9088
|
var TICK_MS = 16;
|
|
9048
9089
|
var CHUNK_HOLD_MS = 2e3;
|
|
9049
9090
|
var TIP_DURATION_MS = 25e3;
|
|
9050
9091
|
function TipTitle({ children }) {
|
|
9051
|
-
return /* @__PURE__ */
|
|
9052
|
-
/* @__PURE__ */
|
|
9053
|
-
/* @__PURE__ */
|
|
9092
|
+
return /* @__PURE__ */ jsxs20(Box22, { gap: 1, children: [
|
|
9093
|
+
/* @__PURE__ */ jsx21(Text23, { color: "cyan", children: "\u2726" }),
|
|
9094
|
+
/* @__PURE__ */ jsx21(Text23, { color: "white", bold: true, children })
|
|
9054
9095
|
] });
|
|
9055
9096
|
}
|
|
9056
9097
|
function InlineSegment({ segment }) {
|
|
9057
9098
|
switch (segment.type) {
|
|
9058
9099
|
case "highlight":
|
|
9059
|
-
return /* @__PURE__ */
|
|
9100
|
+
return /* @__PURE__ */ jsx21(Text23, { color: COLORS.success, children: segment.value });
|
|
9060
9101
|
case "link":
|
|
9061
|
-
return /* @__PURE__ */
|
|
9102
|
+
return /* @__PURE__ */ jsx21(Text23, { color: "cyan", underline: true, children: segment.href ? terminalLink(segment.value, segment.href) : segment.value });
|
|
9062
9103
|
case "codeword":
|
|
9063
|
-
return /* @__PURE__ */
|
|
9104
|
+
return /* @__PURE__ */ jsx21(Text23, { color: COLORS.highlight.fg, backgroundColor: COLORS.highlight.bg, children: segment.value });
|
|
9064
9105
|
default:
|
|
9065
|
-
return /* @__PURE__ */
|
|
9106
|
+
return /* @__PURE__ */ jsx21(Text23, { color: COLORS.muted, children: segment.value });
|
|
9066
9107
|
}
|
|
9067
9108
|
}
|
|
9068
9109
|
function TipContent({
|
|
@@ -9096,10 +9137,10 @@ function TipContent({
|
|
|
9096
9137
|
blocks.push({ type: "inline", segments: [segment] });
|
|
9097
9138
|
}
|
|
9098
9139
|
}
|
|
9099
|
-
return /* @__PURE__ */
|
|
9100
|
-
(block, i) => block.type === "code" ? /* @__PURE__ */
|
|
9140
|
+
return /* @__PURE__ */ jsx21(Box22, { flexDirection: "column", marginLeft: 2, gap: 1, children: blocks.map(
|
|
9141
|
+
(block, i) => block.type === "code" ? /* @__PURE__ */ jsx21(Code, { children: block.segment.value }, i) : /* @__PURE__ */ jsx21(Text23, { children: block.segments.map((segment, j) => /* @__PURE__ */ jsxs20(Text23, { children: [
|
|
9101
9142
|
j > 0 && " ",
|
|
9102
|
-
/* @__PURE__ */
|
|
9143
|
+
/* @__PURE__ */ jsx21(InlineSegment, { segment })
|
|
9103
9144
|
] }, j)) }, i)
|
|
9104
9145
|
) });
|
|
9105
9146
|
}
|
|
@@ -9129,7 +9170,7 @@ function Tips({
|
|
|
9129
9170
|
onRevealStateChange,
|
|
9130
9171
|
onComplete
|
|
9131
9172
|
}) {
|
|
9132
|
-
const [position, setPosition] =
|
|
9173
|
+
const [position, setPosition] = useState13(() => {
|
|
9133
9174
|
const now = Date.now();
|
|
9134
9175
|
return {
|
|
9135
9176
|
tipIndex: clock.tipIndex,
|
|
@@ -9189,9 +9230,9 @@ function Tips({
|
|
|
9189
9230
|
if (position.complete) return null;
|
|
9190
9231
|
const titleRevealed = tip.title.slice(0, revealed);
|
|
9191
9232
|
const contentRevealed = Math.max(0, revealed - tip.title.length);
|
|
9192
|
-
return /* @__PURE__ */
|
|
9193
|
-
/* @__PURE__ */
|
|
9194
|
-
/* @__PURE__ */
|
|
9233
|
+
return /* @__PURE__ */ jsxs20(Box22, { flexDirection: "column", marginBottom: 1, gap: 1, children: [
|
|
9234
|
+
/* @__PURE__ */ jsx21(TipTitle, { children: titleRevealed }),
|
|
9235
|
+
/* @__PURE__ */ jsx21(TipContent, { chunks: tip.chunks, revealed: contentRevealed })
|
|
9195
9236
|
] });
|
|
9196
9237
|
}
|
|
9197
9238
|
|
|
@@ -9233,7 +9274,7 @@ function useRepaintOnResize(debounceMs = 100) {
|
|
|
9233
9274
|
}
|
|
9234
9275
|
|
|
9235
9276
|
// src/ui/App.tsx
|
|
9236
|
-
import { jsx as
|
|
9277
|
+
import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
9237
9278
|
function App() {
|
|
9238
9279
|
const {
|
|
9239
9280
|
phase,
|
|
@@ -9252,14 +9293,9 @@ function App() {
|
|
|
9252
9293
|
const { columns, rows } = useWindowSize8();
|
|
9253
9294
|
useRepaintOnResize();
|
|
9254
9295
|
const compactRun = isCompactTerminal(columns, rows);
|
|
9255
|
-
const [showLogs, setShowLogs] =
|
|
9256
|
-
const [
|
|
9257
|
-
|
|
9258
|
-
setSeenInputReq(inputReq);
|
|
9259
|
-
if (inputReq) setShowLogs(false);
|
|
9260
|
-
}
|
|
9261
|
-
const [tipState, setTipState] = useState12("idle");
|
|
9262
|
-
const [tipsComplete, setTipsComplete] = useState12(false);
|
|
9296
|
+
const [showLogs, setShowLogs] = useState14(false);
|
|
9297
|
+
const [tipState, setTipState] = useState14("idle");
|
|
9298
|
+
const [tipsComplete, setTipsComplete] = useState14(false);
|
|
9263
9299
|
const finished = phase === "done" || phase === "error";
|
|
9264
9300
|
const currentStep = steps[currentStepIndex];
|
|
9265
9301
|
const workflowDef = workflow ? getWorkflow(workflow.id) : void 0;
|
|
@@ -9270,15 +9306,15 @@ function App() {
|
|
|
9270
9306
|
const showTips = !compactRun && tipsActive && (phase === "running" && currentStep?.status === "running" && !loadingMessage && !settingUpAppId || holdForTip);
|
|
9271
9307
|
const showNoticesInMain = !tipsActive;
|
|
9272
9308
|
const showNotices = !compactRun && (!isAwaitingUserInput || holdForTip) && !review2;
|
|
9273
|
-
|
|
9309
|
+
useInput10(
|
|
9274
9310
|
(_input, key) => {
|
|
9275
9311
|
if (key.return) {
|
|
9276
9312
|
exit();
|
|
9277
9313
|
}
|
|
9278
9314
|
},
|
|
9279
|
-
{ isActive: finished }
|
|
9315
|
+
{ isActive: finished && !showLogs }
|
|
9280
9316
|
);
|
|
9281
|
-
|
|
9317
|
+
useInput10((_input, key) => {
|
|
9282
9318
|
if (phase === "idle" || phase === "authenticating") return;
|
|
9283
9319
|
if (key.tab) {
|
|
9284
9320
|
setShowLogs(!showLogs);
|
|
@@ -9289,8 +9325,9 @@ function App() {
|
|
|
9289
9325
|
});
|
|
9290
9326
|
}
|
|
9291
9327
|
});
|
|
9292
|
-
const escOwnedElsewhere = phase === "idle" || phase === "authenticating" ||
|
|
9293
|
-
|
|
9328
|
+
const escOwnedElsewhere = phase === "idle" || phase === "authenticating" || // The log view owns esc: it closes the details, then leaves the list.
|
|
9329
|
+
showLogs || phase === "awaitingInput" && !holdForTip && (inputReq?.promptType === "enterToContinue" || inputReq?.promptType === "commandApproval");
|
|
9330
|
+
useInput10((_input, key) => {
|
|
9294
9331
|
if (escOwnedElsewhere) return;
|
|
9295
9332
|
if (key.escape) {
|
|
9296
9333
|
track("AI Wizard Interaction", {
|
|
@@ -9308,8 +9345,8 @@ function App() {
|
|
|
9308
9345
|
/* Clamped to exactly the viewport: a taller frame makes Ink clear and repaint
|
|
9309
9346
|
the whole screen, and the scrolling throws off its cursor arithmetic.
|
|
9310
9347
|
Flicker and leftover rows. */
|
|
9311
|
-
/* @__PURE__ */
|
|
9312
|
-
|
|
9348
|
+
/* @__PURE__ */ jsxs21(
|
|
9349
|
+
Box23,
|
|
9313
9350
|
{
|
|
9314
9351
|
backgroundColor: COLORS.bg.main,
|
|
9315
9352
|
flexDirection: "row",
|
|
@@ -9317,16 +9354,16 @@ function App() {
|
|
|
9317
9354
|
height: rows,
|
|
9318
9355
|
overflow: "hidden",
|
|
9319
9356
|
children: [
|
|
9320
|
-
mainWindowVisible && /* @__PURE__ */
|
|
9321
|
-
|
|
9357
|
+
mainWindowVisible && /* @__PURE__ */ jsxs21(
|
|
9358
|
+
Box23,
|
|
9322
9359
|
{
|
|
9323
9360
|
flexDirection,
|
|
9324
9361
|
width: "100%",
|
|
9325
9362
|
maxHeight: rows,
|
|
9326
9363
|
justifyContent: "space-between",
|
|
9327
9364
|
children: [
|
|
9328
|
-
showLogs ? /* @__PURE__ */
|
|
9329
|
-
|
|
9365
|
+
showLogs ? /* @__PURE__ */ jsx22(Logs, { onBack: () => setShowLogs(false) }) : /* @__PURE__ */ jsxs21(
|
|
9366
|
+
Box23,
|
|
9330
9367
|
{
|
|
9331
9368
|
flexDirection: "column",
|
|
9332
9369
|
paddingX: 4,
|
|
@@ -9335,58 +9372,58 @@ function App() {
|
|
|
9335
9372
|
flexGrow: 1,
|
|
9336
9373
|
gap: 1,
|
|
9337
9374
|
children: [
|
|
9338
|
-
/* @__PURE__ */
|
|
9339
|
-
phase === "preflight" && !user && /* @__PURE__ */
|
|
9340
|
-
/* @__PURE__ */
|
|
9375
|
+
/* @__PURE__ */ jsxs21(Box23, { flexGrow: 2, flexDirection: "column", children: [
|
|
9376
|
+
phase === "preflight" && !user && /* @__PURE__ */ jsx22(Box23, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs21(Text24, { color: COLORS.strong, bold: true, children: [
|
|
9377
|
+
/* @__PURE__ */ jsx22(Spinner3, { type: "dots" }),
|
|
9341
9378
|
" Signing in to Algolia"
|
|
9342
9379
|
] }) }),
|
|
9343
|
-
phase === "preflight" && user && /* @__PURE__ */
|
|
9344
|
-
/* @__PURE__ */
|
|
9380
|
+
phase === "preflight" && user && /* @__PURE__ */ jsx22(Box23, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs21(Text24, { color: COLORS.strong, bold: true, children: [
|
|
9381
|
+
/* @__PURE__ */ jsx22(Spinner3, { type: "dots" }),
|
|
9345
9382
|
" Getting things ready"
|
|
9346
9383
|
] }) }),
|
|
9347
|
-
phase === "authenticating" && /* @__PURE__ */
|
|
9348
|
-
/* @__PURE__ */
|
|
9349
|
-
/* @__PURE__ */
|
|
9384
|
+
phase === "authenticating" && /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", marginBottom: 1, children: [
|
|
9385
|
+
/* @__PURE__ */ jsxs21(Text24, { color: COLORS.strong, bold: true, children: [
|
|
9386
|
+
/* @__PURE__ */ jsx22(Spinner3, { type: "dots" }),
|
|
9350
9387
|
" Signing in to Algolia"
|
|
9351
9388
|
] }),
|
|
9352
|
-
/* @__PURE__ */
|
|
9389
|
+
/* @__PURE__ */ jsx22(Text24, { color: COLORS.muted, children: "A browser window will open \u2014 complete sign-in there." })
|
|
9353
9390
|
] }),
|
|
9354
|
-
settingUpAppId && /* @__PURE__ */
|
|
9355
|
-
/* @__PURE__ */
|
|
9391
|
+
settingUpAppId && /* @__PURE__ */ jsx22(Box23, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs21(Text24, { color: COLORS.strong, bold: true, children: [
|
|
9392
|
+
/* @__PURE__ */ jsx22(Spinner3, { type: "dots" }),
|
|
9356
9393
|
" Setting up Wizard using app",
|
|
9357
9394
|
" ",
|
|
9358
9395
|
settingUpAppId
|
|
9359
9396
|
] }) }),
|
|
9360
|
-
phase === "running" && !settingUpAppId && loadingMessage && /* @__PURE__ */
|
|
9361
|
-
/* @__PURE__ */
|
|
9397
|
+
phase === "running" && !settingUpAppId && loadingMessage && /* @__PURE__ */ jsx22(Box23, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsxs21(Text24, { color: COLORS.strong, bold: true, children: [
|
|
9398
|
+
/* @__PURE__ */ jsx22(Spinner3, { type: "dots" }),
|
|
9362
9399
|
" ",
|
|
9363
9400
|
loadingMessage
|
|
9364
9401
|
] }) }),
|
|
9365
|
-
/* @__PURE__ */
|
|
9366
|
-
showTips && /* @__PURE__ */
|
|
9402
|
+
/* @__PURE__ */ jsx22(CliOutput, {}),
|
|
9403
|
+
showTips && /* @__PURE__ */ jsx22(
|
|
9367
9404
|
Tips,
|
|
9368
9405
|
{
|
|
9369
9406
|
onRevealStateChange: setTipState,
|
|
9370
9407
|
onComplete: () => setTipsComplete(true)
|
|
9371
9408
|
}
|
|
9372
9409
|
),
|
|
9373
|
-
showNoticesInMain && showNotices && /* @__PURE__ */
|
|
9374
|
-
/* @__PURE__ */
|
|
9375
|
-
!showTips && /* @__PURE__ */
|
|
9376
|
-
phase === "error" && error && /* @__PURE__ */
|
|
9410
|
+
showNoticesInMain && showNotices && /* @__PURE__ */ jsx22(Notices, { border: false }),
|
|
9411
|
+
/* @__PURE__ */ jsx22(Review, {}),
|
|
9412
|
+
!showTips && /* @__PURE__ */ jsx22(PromptInput, {}),
|
|
9413
|
+
phase === "error" && error && /* @__PURE__ */ jsx22(Box23, { marginTop: 1, children: /* @__PURE__ */ jsxs21(Text24, { color: COLORS.status.error, children: [
|
|
9377
9414
|
"\u2716 ",
|
|
9378
9415
|
error
|
|
9379
9416
|
] }) })
|
|
9380
9417
|
] }),
|
|
9381
|
-
!showNoticesInMain && showNotices && /* @__PURE__ */
|
|
9418
|
+
!showNoticesInMain && showNotices && /* @__PURE__ */ jsx22(Notices, {})
|
|
9382
9419
|
]
|
|
9383
9420
|
}
|
|
9384
9421
|
),
|
|
9385
|
-
showSidebar ? /* @__PURE__ */
|
|
9422
|
+
showSidebar ? /* @__PURE__ */ jsx22(Sidebar, { inLogs: showLogs }) : /* @__PURE__ */ jsx22(Ribbon, {})
|
|
9386
9423
|
]
|
|
9387
9424
|
}
|
|
9388
9425
|
),
|
|
9389
|
-
phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */
|
|
9426
|
+
phase === "idle" && (homeScreen === "learnMore" ? /* @__PURE__ */ jsx22(LearnMore, {}) : /* @__PURE__ */ jsx22(Welcome, {}))
|
|
9390
9427
|
]
|
|
9391
9428
|
}
|
|
9392
9429
|
)
|
|
@@ -9625,7 +9662,7 @@ async function resetProjectState() {
|
|
|
9625
9662
|
// package.json with { type: 'json' }
|
|
9626
9663
|
var package_default2 = {
|
|
9627
9664
|
name: "@algolia/wizard",
|
|
9628
|
-
version: "0.87.0
|
|
9665
|
+
version: "0.87.0",
|
|
9629
9666
|
description: "Magically implement Algolia functionality in your codebase",
|
|
9630
9667
|
type: "module",
|
|
9631
9668
|
engines: {
|
|
@@ -9731,7 +9768,7 @@ async function checkVersion() {
|
|
|
9731
9768
|
}
|
|
9732
9769
|
|
|
9733
9770
|
// src/main.tsx
|
|
9734
|
-
import { jsx as
|
|
9771
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
9735
9772
|
var FAILURE_EXIT_CODE = 1;
|
|
9736
9773
|
async function exitProcessWithError(store, instance, message) {
|
|
9737
9774
|
store.setError(message);
|
|
@@ -9794,7 +9831,7 @@ ${formatStepList(workflow)}`);
|
|
|
9794
9831
|
async function run(opts) {
|
|
9795
9832
|
const { workflow, skipResumePrompt } = opts;
|
|
9796
9833
|
const store = useWizard.getState();
|
|
9797
|
-
const instance = render(/* @__PURE__ */
|
|
9834
|
+
const instance = render(/* @__PURE__ */ jsx23(App, {}), { incrementalRendering: true });
|
|
9798
9835
|
await store.waitForStart();
|
|
9799
9836
|
store.syncSteps(
|
|
9800
9837
|
workflow.steps.map((s) => ({
|