@algolia/wizard 0.64.0 → 0.66.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.js +144 -48
  2. package/package.json +6 -6
package/dist/main.js CHANGED
@@ -1760,7 +1760,7 @@ function identify(traits) {
1760
1760
  // package.json
1761
1761
  var package_default = {
1762
1762
  name: "@algolia/wizard",
1763
- version: "0.64.0",
1763
+ version: "0.66.0",
1764
1764
  description: "Magically implement Algolia functionality in your codebase",
1765
1765
  type: "module",
1766
1766
  engines: {
@@ -1804,17 +1804,17 @@ var package_default = {
1804
1804
  "lint-staged": "^17.0.8",
1805
1805
  tsx: "^4.22.3",
1806
1806
  typescript: "^6.0.3",
1807
- vitest: "^4.1.8"
1807
+ vitest: "^4.1.11"
1808
1808
  },
1809
1809
  dependencies: {
1810
- "@ai-sdk/anthropic": "^3.0.81",
1811
- "@ai-sdk/openai-compatible": "^2.0.47",
1810
+ "@ai-sdk/anthropic": "^3.0.118",
1811
+ "@ai-sdk/openai-compatible": "^2.0.75",
1812
1812
  "@hono/node-server": "^2.0.10",
1813
1813
  "@segment/analytics-node": "^3.1.0",
1814
- ai: "^6.0.190",
1814
+ ai: "^6.0.283",
1815
1815
  "cross-keychain": "^1.1.0",
1816
1816
  dotenv: "^17.4.2",
1817
- hono: "^4.12.27",
1817
+ hono: "^4.13.8",
1818
1818
  ink: "^7.0.5",
1819
1819
  "ink-picture": "^2.1.0",
1820
1820
  "ink-spinner": "^5.0.0",
@@ -4567,7 +4567,7 @@ ${formatCompletedSteps(ctx.completedSteps)}`,
4567
4567
 
4568
4568
  // src/actions/implement.ts
4569
4569
  import z28 from "zod";
4570
- import { mkdir as mkdir5, readFile as readFile8 } from "node:fs/promises";
4570
+ import { access, mkdir as mkdir5, readFile as readFile8 } from "node:fs/promises";
4571
4571
  import { join as join10, relative as relative6 } from "node:path";
4572
4572
 
4573
4573
  // src/lib/git.ts
@@ -4732,12 +4732,13 @@ var implementationOutputSchema = z28.object({
4732
4732
  // won't end up gitignored (it's public, meant to be committed).
4733
4733
  searchConfigFile: z28.string().optional()
4734
4734
  });
4735
- var verificationOutputSchema = z28.object({
4735
+ var validationOutputSchema = z28.object({
4736
4736
  summary: z28.string(),
4737
4737
  sufficient: z28.boolean(),
4738
- additionalInstructions: z28.string().optional()
4738
+ additionalInstructions: z28.string().optional(),
4739
+ unrelatedFailure: z28.string().optional()
4739
4740
  });
4740
- var MAX_IMPLEMENT_VERIFICATION_ATTEMPTS = 3;
4741
+ var MAX_IMPLEMENT_VALIDATION_ATTEMPTS = 3;
4741
4742
  var DEFAULT_IMPLEMENT_USE_CASES = ["ingestion", "search"];
4742
4743
  var INGEST_DIR = ".algolia-wizard";
4743
4744
  var INGESTION_SOURCE_PROMPT = "What data do you want to index?";
@@ -4746,6 +4747,9 @@ var INGESTION_SOURCE = {
4746
4747
  fileUpload: "Import a data file (CSV, JSON, TSV)",
4747
4748
  generated: "Generate sample data"
4748
4749
  };
4750
+ var BUILD_CHECK_PROMPT = "Run type-check and lint now? This can take several minutes on a large repository.";
4751
+ var MISSING_DEPENDENCIES_PROMPT = "Dependencies are not installed. Install them and run type-check and lint now?";
4752
+ var UNRELATED_FAILURE_PROMPT = "These checks are still failing and appear unrelated to the changes. Continue the investigation?";
4749
4753
  var FILE_UPLOAD_PATH_PROMPT = "Enter the path to your JSON, CSV, or TSV file (relative to the project root, or absolute):";
4750
4754
  var JS_LANGUAGES = ["javascript", "typescript", "jsx", "tsx", "node"];
4751
4755
  function lower(entries) {
@@ -4870,19 +4874,19 @@ function searchInstructions(input) {
4870
4874
  "The summary should be extremely concise; do not mention manual testing steps."
4871
4875
  ];
4872
4876
  }
4873
- function verificationInstructions(input) {
4877
+ function validationInstructions(input) {
4874
4878
  return [
4875
- "Verify the Algolia implementation changes.",
4876
- `Verification tools found in the codebase: ${JSON.stringify(input.findings.verification ?? [])}.`,
4877
- "Run the project's own checks (lint, type check, tests) via runShell, using the project's commands \u2014 its task runner, manifest scripts, etc. Run every check that applies, not just the first.",
4878
- "If a check fails because packages or modules are missing, install the dependencies via runShell and re-run it rather than changing the code.",
4879
- "For issues caused by the implementation, make minimal fixes with writeFile and re-run the checks.",
4880
- "Do not make speculative fixes when no checks exist, a check cannot run, or failures are unrelated to these changes \u2014 note the limitation in your summary.",
4881
- "Do not add new Algolia functionality here; only validate and make minimal correctness fixes.",
4882
- `Do not modify "${input.ingestDir}/" unless a check reports an actionable issue in its files.`,
4883
- "Always call reportStatus with status=success once verification has run, even when sufficient=false.",
4884
- "Set sufficient=true only when the implementation is complete and checks pass (or fail for a clearly unrelated reason).",
4885
- "Set sufficient=false when the implementation is incomplete or has implementation-caused failures; include concrete additionalInstructions for the next pass."
4879
+ "Validate the Algolia search implementation by inspecting the project source.",
4880
+ "Confirm that the application renders exactly one search bar. Check for an old search bar and duplicate mounts.",
4881
+ `Confirm that the search bar is mounted in ${input.searchLocation ? `"${input.searchLocation}"` : "the best always-rendered shared layout location"}.`,
4882
+ "Confirm that the search component is reachable across the application and fits the surrounding layout.",
4883
+ "Do not run the test suite or any test command.",
4884
+ "Do not modify files. Report each implementation issue as a concrete instruction for the next implementation pass.",
4885
+ `Available type-check and lint tools: ${JSON.stringify(input.findings.verification ?? [])}.`,
4886
+ "Always call reportStatus with status=success after validation, even when sufficient=false.",
4887
+ "Set sufficient=true only when the search bar is unique, correctly placed, and structurally complete.",
4888
+ "Set sufficient=false for an implementation issue. Include concrete additionalInstructions for the next pass.",
4889
+ "If a check fails only in untouched code, set unrelatedFailure to a concise failure description."
4886
4890
  ];
4887
4891
  }
4888
4892
  var IMPLEMENT_CONFIG = {
@@ -4894,9 +4898,9 @@ var IMPLEMENT_CONFIG = {
4894
4898
  title: "Algolia search",
4895
4899
  buildInstructions: searchInstructions
4896
4900
  },
4897
- verification: {
4898
- title: "Algolia verification",
4899
- buildInstructions: verificationInstructions
4901
+ validation: {
4902
+ title: "Algolia validation",
4903
+ buildInstructions: validationInstructions
4900
4904
  }
4901
4905
  };
4902
4906
  var useCaseToolMap = {
@@ -4909,7 +4913,7 @@ var useCaseToolMap = {
4909
4913
  "notifyUser"
4910
4914
  ],
4911
4915
  search: [...FS_READ_TOOLS, "writeFile", "runShell", "notifyUser"],
4912
- verification: [...FS_READ_TOOLS, "writeFile", "runShell", "notifyUser"]
4916
+ validation: [...FS_READ_TOOLS, "runShell", "notifyUser"]
4913
4917
  };
4914
4918
  function toolsForUseCase(useCase, ingestionSource) {
4915
4919
  const tools = useCaseToolMap[useCase];
@@ -4929,7 +4933,7 @@ function buildAgentInstructions(useCase, input, extraInstructions = []) {
4929
4933
  ];
4930
4934
  }
4931
4935
  function formatSummary(useCase, summary) {
4932
- const label = useCase === "ingestion" ? "Ingestion" : useCase === "search" ? "Search" : "Verification";
4936
+ const label = useCase === "ingestion" ? "Ingestion" : useCase === "search" ? "Search" : "Validation";
4933
4937
  return `${label}: ${summary}`;
4934
4938
  }
4935
4939
  function parseIngestRecordCount(output) {
@@ -5021,9 +5025,62 @@ function makeToolContext(root, env = async () => ({})) {
5021
5025
  createShellContext({ env, approve: storeApproval(root) })
5022
5026
  );
5023
5027
  }
5024
- function verificationRetryInstructions(verification) {
5028
+ function validationRetryInstructions(validation) {
5025
5029
  return [
5026
- `Implementation insufficient. Address these findings before reporting completion: ${verification.additionalInstructions ?? verification.summary}`
5030
+ `Implementation insufficient. Address these findings before reporting completion: ${validation.additionalInstructions ?? validation.summary}`
5031
+ ];
5032
+ }
5033
+ async function pathExists(path) {
5034
+ try {
5035
+ await access(path);
5036
+ return true;
5037
+ } catch {
5038
+ return false;
5039
+ }
5040
+ }
5041
+ async function resolveBuildCheckPlan(ctx, repoRoot, input) {
5042
+ if (!input.findings.verification?.length) {
5043
+ return { run: false, installDependencies: false };
5044
+ }
5045
+ const installDependencies = isJsProject(input.language) && !await pathExists(join10(repoRoot, "node_modules"));
5046
+ const accepted = Boolean(
5047
+ await ctx.requestUserInput({
5048
+ prompt: installDependencies ? MISSING_DEPENDENCIES_PROMPT : BUILD_CHECK_PROMPT,
5049
+ promptType: "acceptReject",
5050
+ options: ["Yes", "No"],
5051
+ messages: []
5052
+ })
5053
+ );
5054
+ return {
5055
+ run: accepted,
5056
+ installDependencies: accepted && installDependencies
5057
+ };
5058
+ }
5059
+ function installCheckInstructions(plan, attempt) {
5060
+ if (!plan.installDependencies) {
5061
+ return [];
5062
+ }
5063
+ if (attempt === 1) {
5064
+ return [
5065
+ "Install dependencies once with the project's declared package manager before any check.",
5066
+ "Do not try alternate install commands. If installation fails, stop the checks and report the limitation."
5067
+ ];
5068
+ }
5069
+ return ["Dependencies were already installed. Do not install them again."];
5070
+ }
5071
+ function validationRunInstructions(plan, changedFiles, attempt) {
5072
+ if (!plan.run) {
5073
+ return [
5074
+ "The developer chose to skip build checks. Do not install dependencies or run shell checks."
5075
+ ];
5076
+ }
5077
+ return [
5078
+ "The developer approved the optional build checks.",
5079
+ ...installCheckInstructions(plan, attempt),
5080
+ "Do not use npx, dlx, or another package runner that can download an undeclared tool.",
5081
+ "Run the type check once with the project's existing command, when one is available.",
5082
+ `Lint only these changed files: ${JSON.stringify(changedFiles)}. Do not run a full-project lint. If this list is empty, do not run lint.`,
5083
+ "Do not use an autofix option during validation."
5027
5084
  ];
5028
5085
  }
5029
5086
  async function resolveIngestionSource(ctx, repoRoot) {
@@ -5192,13 +5249,17 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
5192
5249
  toolContext: currentUseCase === "ingestion" ? ingestionTools ?? searchTools : searchTools
5193
5250
  });
5194
5251
  }
5195
- async function runVerificationUseCase() {
5252
+ async function runValidationUseCase(extraInstructions) {
5196
5253
  if (agentRuns > 0) ctx.recordStepExecution();
5197
5254
  agentRuns += 1;
5198
5255
  return runAgent({
5199
- instructions: buildAgentInstructions("verification", input),
5200
- tools: toolsForUseCase("verification"),
5201
- outputSchema: verificationOutputSchema,
5256
+ instructions: buildAgentInstructions(
5257
+ "validation",
5258
+ input,
5259
+ extraInstructions
5260
+ ),
5261
+ tools: toolsForUseCase("validation"),
5262
+ outputSchema: validationOutputSchema,
5202
5263
  toolContext: searchTools
5203
5264
  });
5204
5265
  }
@@ -5307,6 +5368,7 @@ ${detail}` : ""}`
5307
5368
  let searchConfigFile;
5308
5369
  if (useCases.includes("search")) {
5309
5370
  let extraInstructions = [];
5371
+ let buildCheckPlan;
5310
5372
  const confirmedFrameworks = language.frameworks ?? [];
5311
5373
  const detectedFrameworks = scan.frameworks ?? [];
5312
5374
  const framework = confirmedFrameworks[0]?.name ?? "unknown";
@@ -5331,15 +5393,15 @@ ${detail}` : ""}`
5331
5393
  });
5332
5394
  };
5333
5395
  useWizard.getState().clearWrittenFiles();
5334
- for (let attempt = 1; attempt <= MAX_IMPLEMENT_VERIFICATION_ATTEMPTS; attempt++) {
5396
+ for (let attempt = 1; attempt <= MAX_IMPLEMENT_VALIDATION_ATTEMPTS; attempt++) {
5335
5397
  if (attempt > 1) {
5336
5398
  logger.info(
5337
5399
  {
5338
5400
  attempt,
5339
- maxAttempts: MAX_IMPLEMENT_VERIFICATION_ATTEMPTS,
5401
+ maxAttempts: MAX_IMPLEMENT_VALIDATION_ATTEMPTS,
5340
5402
  extraInstructions
5341
5403
  },
5342
- "implement: retrying search implementation after failed verification"
5404
+ "implement: retrying search implementation after failed validation"
5343
5405
  );
5344
5406
  }
5345
5407
  const searchResult = await runImplementationUseCase(
@@ -5350,21 +5412,55 @@ ${detail}` : ""}`
5350
5412
  if (searchResult.searchConfigFile) {
5351
5413
  searchConfigFile = searchResult.searchConfigFile;
5352
5414
  }
5353
- const verification = await runVerificationUseCase();
5354
- summaries.push(formatSummary("verification", verification.summary));
5355
- if (verification.sufficient) {
5415
+ buildCheckPlan ??= await resolveBuildCheckPlan(ctx, repoRoot, input);
5416
+ const searchFilesChanged = [
5417
+ ...new Set(useWizard.getState().writtenFiles)
5418
+ ].map((file) => relative6(repoRoot, file));
5419
+ const validation = await runValidationUseCase(
5420
+ validationRunInstructions(buildCheckPlan, searchFilesChanged, attempt)
5421
+ );
5422
+ summaries.push(formatSummary("validation", validation.summary));
5423
+ const finalAttempt = attempt === MAX_IMPLEMENT_VALIDATION_ATTEMPTS;
5424
+ let investigateUnrelated = false;
5425
+ if (validation.unrelatedFailure && !finalAttempt) {
5426
+ investigateUnrelated = Boolean(
5427
+ await ctx.requestUserInput({
5428
+ prompt: UNRELATED_FAILURE_PROMPT,
5429
+ promptType: "acceptReject",
5430
+ options: ["Yes", "No"],
5431
+ messages: [validation.unrelatedFailure]
5432
+ })
5433
+ );
5434
+ if (!investigateUnrelated) {
5435
+ summaries.push("Validation: Skipped unrelated check failures.");
5436
+ if (validation.sufficient) {
5437
+ ctx.setUserInput("implementation", "success");
5438
+ trackComponentGenerated(true, attempt);
5439
+ break;
5440
+ }
5441
+ }
5442
+ }
5443
+ if (validation.sufficient && (!validation.unrelatedFailure || finalAttempt)) {
5444
+ if (validation.unrelatedFailure) {
5445
+ summaries.push("Validation: Unrelated check failures remain.");
5446
+ }
5356
5447
  ctx.setUserInput("implementation", "success");
5357
5448
  trackComponentGenerated(true, attempt);
5358
5449
  break;
5359
5450
  }
5360
- if (attempt === MAX_IMPLEMENT_VERIFICATION_ATTEMPTS) {
5451
+ if (finalAttempt) {
5361
5452
  ctx.setUserInput("implementation", "fail");
5362
5453
  trackComponentGenerated(false, attempt);
5363
5454
  throw new Error(
5364
- `Implementation verification failed after ${MAX_IMPLEMENT_VERIFICATION_ATTEMPTS} attempts: ${verification.additionalInstructions ?? verification.summary}`
5455
+ `Unable to validate the implementation after ${MAX_IMPLEMENT_VALIDATION_ATTEMPTS} attempts: ${validation.additionalInstructions ?? validation.unrelatedFailure ?? validation.summary}`
5456
+ );
5457
+ }
5458
+ extraInstructions = validation.sufficient ? [] : validationRetryInstructions(validation);
5459
+ if (validation.unrelatedFailure && investigateUnrelated) {
5460
+ extraInstructions.push(
5461
+ `The developer asked you to investigate this check failure: ${validation.unrelatedFailure}`
5365
5462
  );
5366
5463
  }
5367
- extraInstructions = verificationRetryInstructions(verification);
5368
5464
  }
5369
5465
  if (searchConfigFile) {
5370
5466
  const ignoreStatus = await gitIgnoreStatus(
@@ -7074,7 +7170,7 @@ function delay(ms) {
7074
7170
  // package.json with { type: 'json' }
7075
7171
  var package_default2 = {
7076
7172
  name: "@algolia/wizard",
7077
- version: "0.64.0",
7173
+ version: "0.66.0",
7078
7174
  description: "Magically implement Algolia functionality in your codebase",
7079
7175
  type: "module",
7080
7176
  engines: {
@@ -7118,17 +7214,17 @@ var package_default2 = {
7118
7214
  "lint-staged": "^17.0.8",
7119
7215
  tsx: "^4.22.3",
7120
7216
  typescript: "^6.0.3",
7121
- vitest: "^4.1.8"
7217
+ vitest: "^4.1.11"
7122
7218
  },
7123
7219
  dependencies: {
7124
- "@ai-sdk/anthropic": "^3.0.81",
7125
- "@ai-sdk/openai-compatible": "^2.0.47",
7220
+ "@ai-sdk/anthropic": "^3.0.118",
7221
+ "@ai-sdk/openai-compatible": "^2.0.75",
7126
7222
  "@hono/node-server": "^2.0.10",
7127
7223
  "@segment/analytics-node": "^3.1.0",
7128
- ai: "^6.0.190",
7224
+ ai: "^6.0.283",
7129
7225
  "cross-keychain": "^1.1.0",
7130
7226
  dotenv: "^17.4.2",
7131
- hono: "^4.12.27",
7227
+ hono: "^4.13.8",
7132
7228
  ink: "^7.0.5",
7133
7229
  "ink-picture": "^2.1.0",
7134
7230
  "ink-spinner": "^5.0.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@algolia/wizard",
3
- "version": "0.64.0",
3
+ "version": "0.66.0",
4
4
  "description": "Magically implement Algolia functionality in your codebase",
5
5
  "type": "module",
6
6
  "engines": {
@@ -44,17 +44,17 @@
44
44
  "lint-staged": "^17.0.8",
45
45
  "tsx": "^4.22.3",
46
46
  "typescript": "^6.0.3",
47
- "vitest": "^4.1.8"
47
+ "vitest": "^4.1.11"
48
48
  },
49
49
  "dependencies": {
50
- "@ai-sdk/anthropic": "^3.0.81",
51
- "@ai-sdk/openai-compatible": "^2.0.47",
50
+ "@ai-sdk/anthropic": "^3.0.118",
51
+ "@ai-sdk/openai-compatible": "^2.0.75",
52
52
  "@hono/node-server": "^2.0.10",
53
53
  "@segment/analytics-node": "^3.1.0",
54
- "ai": "^6.0.190",
54
+ "ai": "^6.0.283",
55
55
  "cross-keychain": "^1.1.0",
56
56
  "dotenv": "^17.4.2",
57
- "hono": "^4.12.27",
57
+ "hono": "^4.13.8",
58
58
  "ink": "^7.0.5",
59
59
  "ink-picture": "^2.1.0",
60
60
  "ink-spinner": "^5.0.0",