@algolia/wizard 0.62.0 → 0.63.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 +281 -108
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -1697,23 +1697,137 @@ function trackWorkflowError(ctx) {
1697
1697
 
1698
1698
  // src/lib/events.ts
1699
1699
  import "zod";
1700
- function track(event, payload) {
1700
+ var analyticsAppId = void 0;
1701
+ var analyticsAgentRunId = void 0;
1702
+ function setAnalyticsContext(next) {
1703
+ analyticsAppId = next.appId;
1704
+ analyticsAgentRunId = next.agentRunId;
1705
+ }
1706
+ function wizardErrorType(actionId, step, error) {
1707
+ if (actionId === "project-scan" || step === "project scan") {
1708
+ return "Scan Codebase";
1709
+ }
1710
+ if (actionId === "ingestion" || step === "Push Data" || step === "ingest records") {
1711
+ return "Ingest Records";
1712
+ }
1713
+ if (actionId === "search" || step === "create search ui") {
1714
+ if (error && error.toLowerCase().includes("verification failed")) {
1715
+ return "Wire Component to UI";
1716
+ }
1717
+ return "Generate UI";
1718
+ }
1719
+ return void 0;
1720
+ }
1721
+ function commonEventProperties() {
1722
+ const properties = {};
1723
+ if (analyticsAppId) properties.app_id = analyticsAppId;
1724
+ if (analyticsAgentRunId) properties.agent_run_id = analyticsAgentRunId;
1725
+ return properties;
1726
+ }
1727
+ function postAnalytics(path, body, label) {
1701
1728
  if (isTelemetryOptedOut()) return;
1702
1729
  const token = getAuthToken();
1703
1730
  if (!token) return;
1704
1731
  const userId = useWizard.getState().user?.userId;
1705
1732
  if (!userId) return;
1706
- void proxyFetch(`${PROXY_BASE_URL}/events`, {
1733
+ void proxyFetch(`${PROXY_BASE_URL}${path}`, {
1707
1734
  method: "POST",
1708
1735
  headers: {
1709
1736
  "content-type": "application/json",
1710
1737
  authorization: `Bearer ${token}`
1711
1738
  },
1712
- body: JSON.stringify({ userId, event, properties: payload })
1739
+ body: JSON.stringify(body)
1713
1740
  }).catch((err) => {
1714
- logger.warn({ err, event }, "failed to send analytics event");
1741
+ logger.warn({ err, event: label }, "failed to send analytics event");
1715
1742
  });
1716
1743
  }
1744
+ function track(event, payload) {
1745
+ postAnalytics(
1746
+ "/events",
1747
+ {
1748
+ userId: useWizard.getState().user?.userId,
1749
+ event,
1750
+ properties: { ...payload, ...commonEventProperties() }
1751
+ },
1752
+ event
1753
+ );
1754
+ }
1755
+ function identify(traits) {
1756
+ const userId = useWizard.getState().user?.userId;
1757
+ postAnalytics("/identify", { userId, traits }, "identify");
1758
+ }
1759
+
1760
+ // package.json
1761
+ var package_default = {
1762
+ name: "@algolia/wizard",
1763
+ version: "0.63.0",
1764
+ description: "Magically implement Algolia functionality in your codebase",
1765
+ type: "module",
1766
+ engines: {
1767
+ node: ">=24"
1768
+ },
1769
+ bin: {
1770
+ wizard: "dist/main.js"
1771
+ },
1772
+ files: [
1773
+ "dist",
1774
+ "docs"
1775
+ ],
1776
+ scripts: {
1777
+ "build:proxy": "node scripts/build.mjs proxy",
1778
+ build: "node scripts/build.mjs",
1779
+ "dev:proxy": "touch .env && NODE_OPTIONS=--use-system-ca tsx watch --env-file=.env src/proxy/index.ts",
1780
+ dev: "touch .env && tsx --env-file=.env ./src/main.tsx",
1781
+ "env:load": "pnpm exec -- varlock load",
1782
+ prepare: "husky",
1783
+ prepublishOnly: "pnpm build",
1784
+ reset: "tsx ./scripts/reset-state.ts",
1785
+ "test:fixtures": "touch .env && tsx --env-file=.env ./fixtures/run-fixtures.ts",
1786
+ "test:tools": "tsx ./tool-evals/toolEval.ts",
1787
+ "test:tools:improve": "tsx ./tool-evals/improveFromPlan.ts",
1788
+ test: "vitest",
1789
+ typecheck: "tsc --noEmit -p tsconfig.json"
1790
+ },
1791
+ keywords: [],
1792
+ author: "",
1793
+ license: "ISC",
1794
+ packageManager: "pnpm@11.9.0+sha512.bd682d5d03fe525ef7c9fd6780c6884d1e756ac4c9c9fe00c538782824310dcf90e3ddc4f53835f06dfaebd5085e41855e0bcbb3b60de2ac5bbab89e5036f03b",
1795
+ devDependencies: {
1796
+ "@clack/prompts": "^1.6.0",
1797
+ "@types/ioredis-mock": "^8.2.7",
1798
+ "@types/node": "^25.9.1",
1799
+ "@types/react": "^19.2.16",
1800
+ esbuild: "^0.28.0",
1801
+ husky: "^9.1.7",
1802
+ "ink-testing-library": "^4.0.0",
1803
+ "ioredis-mock": "^8.13.1",
1804
+ "lint-staged": "^17.0.8",
1805
+ tsx: "^4.22.3",
1806
+ typescript: "^6.0.3",
1807
+ vitest: "^4.1.8"
1808
+ },
1809
+ dependencies: {
1810
+ "@ai-sdk/anthropic": "^3.0.81",
1811
+ "@ai-sdk/openai-compatible": "^2.0.47",
1812
+ "@hono/node-server": "^2.0.10",
1813
+ "@segment/analytics-node": "^3.1.0",
1814
+ ai: "^6.0.190",
1815
+ "cross-keychain": "^1.1.0",
1816
+ dotenv: "^17.4.2",
1817
+ hono: "^4.12.27",
1818
+ ink: "^7.0.5",
1819
+ "ink-picture": "^2.1.0",
1820
+ "ink-spinner": "^5.0.0",
1821
+ ioredis: "^5.11.1",
1822
+ nanoid: "^5.1.15",
1823
+ pino: "^10.3.1",
1824
+ react: "^19.2.7",
1825
+ "terminal-link": "^5.0.0",
1826
+ varlock: "^1.5.1",
1827
+ zod: "^4.4.3",
1828
+ zustand: "^5.0.14"
1829
+ }
1830
+ };
1717
1831
 
1718
1832
  // src/core/orchestrator.ts
1719
1833
  function defineStep(step) {
@@ -1766,9 +1880,37 @@ function initWorkflowState(workflow, now, appId) {
1766
1880
  status: "pending"
1767
1881
  })),
1768
1882
  algoliaState: appId ? { appId } : {},
1769
- userInputs: {}
1883
+ userInputs: {},
1884
+ agentRunId: crypto.randomUUID()
1885
+ };
1886
+ }
1887
+ function ensureAgentRunId(state) {
1888
+ if (!state.agentRunId) state.agentRunId = crypto.randomUUID();
1889
+ }
1890
+ function completeEventProperties(state, totalDurationMs, stepCount) {
1891
+ const indexName = state.steps.find((s) => s.id === "select-index")?.output?.selection;
1892
+ const framework = state.steps.find((s) => s.id === "confirm-framework")?.output?.frameworks?.[0]?.name;
1893
+ return {
1894
+ total_duration_ms: totalDurationMs,
1895
+ duration_ms: totalDurationMs,
1896
+ step_count: stepCount,
1897
+ index_name: indexName ?? "unknown",
1898
+ framework: framework ?? "unknown"
1770
1899
  };
1771
1900
  }
1901
+ function errorCodeFrom(err) {
1902
+ let current = err;
1903
+ for (let i = 0; i < 4 && current; i++) {
1904
+ if (current && typeof current === "object" && "statusCode" in current) {
1905
+ const code = current.statusCode;
1906
+ if (typeof code === "number" || typeof code === "string") {
1907
+ return String(code);
1908
+ }
1909
+ }
1910
+ current = current instanceof Error ? current.cause : void 0;
1911
+ }
1912
+ return void 0;
1913
+ }
1772
1914
  async function ensureConsent() {
1773
1915
  const config = await loadConfig();
1774
1916
  if (config.aiConsent) return;
@@ -1881,6 +2023,8 @@ async function runWorkflow(workflow, appId, options) {
1881
2023
  try {
1882
2024
  const state = await resolveWorkflowState(workflow, appId, options);
1883
2025
  ensureExecutedStepCount(state);
2026
+ ensureAgentRunId(state);
2027
+ setAnalyticsContext({ appId, agentRunId: state.agentRunId });
1884
2028
  store.startWorkflow(
1885
2029
  {
1886
2030
  id: workflow.id,
@@ -1891,6 +2035,11 @@ async function runWorkflow(workflow, appId, options) {
1891
2035
  );
1892
2036
  await ensureConsent();
1893
2037
  trackWorkflowStart({ workflowId: workflow.id, appId });
2038
+ track("AI Wizard Started", {
2039
+ version: package_default.version,
2040
+ wizard_version: package_default.version,
2041
+ os: process.platform
2042
+ });
1894
2043
  for (let i = state.currentStepIndex; i < workflow.steps.length; i++) {
1895
2044
  await runStep(state, i, workflow.steps[i], appId);
1896
2045
  }
@@ -1902,10 +2051,11 @@ async function runWorkflow(workflow, appId, options) {
1902
2051
  total_duration: Math.round(totalDurationMs / 1e3),
1903
2052
  total_steps: stepCount
1904
2053
  });
1905
- track("AI Wizard Complete", {
1906
- total_duration_ms: totalDurationMs,
1907
- step_count: stepCount
1908
- });
2054
+ track(
2055
+ "AI Wizard Completed",
2056
+ completeEventProperties(state, totalDurationMs, stepCount)
2057
+ );
2058
+ identify({ is_Wizard_user: true });
1909
2059
  await recordWorkflowRun(workflow.id, nowIso());
1910
2060
  await clearWorkflowState(workflow.id);
1911
2061
  store.setDone();
@@ -1946,10 +2096,15 @@ async function runWorkflow(workflow, appId, options) {
1946
2096
  actionId: failedActionId,
1947
2097
  cause: err
1948
2098
  });
2099
+ const errorType = wizardErrorType(failedActionId, step, message);
2100
+ const errorCode2 = errorCodeFrom(err);
1949
2101
  track("Error", {
1950
2102
  step,
1951
2103
  error: message,
1952
- product_area: "AI Wizard"
2104
+ error_message: message,
2105
+ product_area: "AI Wizard",
2106
+ ...errorType ? { error_type: errorType } : {},
2107
+ ...errorCode2 ? { error_code: errorCode2 } : {}
1953
2108
  });
1954
2109
  store.setError(message);
1955
2110
  }
@@ -3529,7 +3684,7 @@ function generateRecordTool(ctx, createModel = defaultCreateModel2) {
3529
3684
  try {
3530
3685
  const anthropic = createModel();
3531
3686
  const value = z17.union([z17.string(), z17.number(), z17.boolean(), z17.null()]);
3532
- const recordSchema = z17.object(
3687
+ const recordSchema2 = z17.object(
3533
3688
  Object.fromEntries(attributes.map((attr) => [attr, value]))
3534
3689
  );
3535
3690
  const generateBatch = async (batchCount) => {
@@ -3540,7 +3695,7 @@ function generateRecordTool(ctx, createModel = defaultCreateModel2) {
3540
3695
  model: anthropic(RECORD_MODEL),
3541
3696
  output: Output2.object({
3542
3697
  schema: z17.object({
3543
- records: z17.array(recordSchema).length(batchCount)
3698
+ records: z17.array(recordSchema2).length(batchCount)
3544
3699
  })
3545
3700
  }),
3546
3701
  prompt: [
@@ -3975,78 +4130,6 @@ async function runAnalysis(mode, extraInstructions = []) {
3975
4130
  return Object.assign({}, ...results);
3976
4131
  }
3977
4132
 
3978
- // package.json
3979
- var package_default = {
3980
- name: "@algolia/wizard",
3981
- version: "0.62.0",
3982
- description: "Magically implement Algolia functionality in your codebase",
3983
- type: "module",
3984
- engines: {
3985
- node: ">=24"
3986
- },
3987
- bin: {
3988
- wizard: "dist/main.js"
3989
- },
3990
- files: [
3991
- "dist",
3992
- "docs"
3993
- ],
3994
- scripts: {
3995
- "build:proxy": "node scripts/build.mjs proxy",
3996
- build: "node scripts/build.mjs",
3997
- "dev:proxy": "touch .env && NODE_OPTIONS=--use-system-ca tsx watch --env-file=.env src/proxy/index.ts",
3998
- dev: "touch .env && tsx --env-file=.env ./src/main.tsx",
3999
- "env:load": "pnpm exec -- varlock load",
4000
- prepare: "husky",
4001
- prepublishOnly: "pnpm build",
4002
- reset: "tsx ./scripts/reset-state.ts",
4003
- "test:fixtures": "touch .env && tsx --env-file=.env ./fixtures/run-fixtures.ts",
4004
- "test:tools": "tsx ./tool-evals/toolEval.ts",
4005
- "test:tools:improve": "tsx ./tool-evals/improveFromPlan.ts",
4006
- test: "vitest",
4007
- typecheck: "tsc --noEmit -p tsconfig.json"
4008
- },
4009
- keywords: [],
4010
- author: "",
4011
- license: "ISC",
4012
- packageManager: "pnpm@11.9.0+sha512.bd682d5d03fe525ef7c9fd6780c6884d1e756ac4c9c9fe00c538782824310dcf90e3ddc4f53835f06dfaebd5085e41855e0bcbb3b60de2ac5bbab89e5036f03b",
4013
- devDependencies: {
4014
- "@clack/prompts": "^1.6.0",
4015
- "@types/ioredis-mock": "^8.2.7",
4016
- "@types/node": "^25.9.1",
4017
- "@types/react": "^19.2.16",
4018
- esbuild: "^0.28.0",
4019
- husky: "^9.1.7",
4020
- "ink-testing-library": "^4.0.0",
4021
- "ioredis-mock": "^8.13.1",
4022
- "lint-staged": "^17.0.8",
4023
- tsx: "^4.22.3",
4024
- typescript: "^6.0.3",
4025
- vitest: "^4.1.8"
4026
- },
4027
- dependencies: {
4028
- "@ai-sdk/anthropic": "^3.0.81",
4029
- "@ai-sdk/openai-compatible": "^2.0.47",
4030
- "@hono/node-server": "^2.0.10",
4031
- "@segment/analytics-node": "^3.1.0",
4032
- ai: "^6.0.190",
4033
- "cross-keychain": "^1.1.0",
4034
- dotenv: "^17.4.2",
4035
- hono: "^4.12.27",
4036
- ink: "^7.0.5",
4037
- "ink-picture": "^2.1.0",
4038
- "ink-spinner": "^5.0.0",
4039
- ioredis: "^5.11.1",
4040
- nanoid: "^5.1.15",
4041
- pino: "^10.3.1",
4042
- react: "^19.2.7",
4043
- "terminal-link": "^5.0.0",
4044
- varlock: "^1.5.1",
4045
- zod: "^4.4.3",
4046
- zustand: "^5.0.14"
4047
- }
4048
- };
4049
-
4050
4133
  // src/actions/projectScan.ts
4051
4134
  import "zod";
4052
4135
  var projectScanSchema = detectLanguageSchema.extend({
@@ -4055,16 +4138,19 @@ var projectScanSchema = detectLanguageSchema.extend({
4055
4138
  verification: analyzeCodebaseSchema.shape.verification
4056
4139
  });
4057
4140
  async function projectScan(ctx) {
4141
+ const startedAt = Date.now();
4058
4142
  const [detected, analyses] = await Promise.all([
4059
4143
  detectLanguage(),
4060
4144
  runAnalysis()
4061
4145
  ]);
4062
- track("AI Wizard Started", {
4063
- wizard_version: package_default.version,
4064
- os: process.platform
4065
- });
4146
+ const entities = toEntitySummary(analyses.ingestionAnalysis ?? []);
4066
4147
  track("AI Wizard Scan Completed", {
4067
- entities: toEntitySummary(analyses.ingestionAnalysis ?? [])
4148
+ languages: detected.languages,
4149
+ frameworks: detected.frameworks,
4150
+ data_models_found: entities.map((entity) => entity.name),
4151
+ back_end_language_detected: detected.languages[0]?.name ?? null,
4152
+ front_end_framework_detected: detected.frameworks[0]?.name ?? null,
4153
+ duration_ms: Date.now() - startedAt
4068
4154
  });
4069
4155
  for (const [key, value] of Object.entries(analyses)) {
4070
4156
  ctx.setUserInput(key, value);
@@ -4162,7 +4248,7 @@ var isSameFramework = (a, b) => {
4162
4248
  };
4163
4249
  function confirmed(name, version) {
4164
4250
  const frameworks = [{ name, version: version ?? "unknown" }];
4165
- track("AI Wizard Frontend Framework Confirmed", { frameworks });
4251
+ track("AI Wizard Frontend Framework Confirmed", { frameworks, framework: name });
4166
4252
  return { frameworks };
4167
4253
  }
4168
4254
  async function askOtherFramework(ctx) {
@@ -4266,6 +4352,11 @@ var confirmEntitiesSchema = z26.object({
4266
4352
  confirmedEntities: confirmedEntitiesFieldSchema
4267
4353
  });
4268
4354
  var SUGGEST_ENTITY = "Suggest a different entity\u2026";
4355
+ function usedDetectedBackend(detected, confirmed2) {
4356
+ if (!detected?.length || !confirmed2?.length) return false;
4357
+ const detectedNames = new Set(detected.map((entry) => entry.name.toLowerCase()));
4358
+ return confirmed2.every((entry) => detectedNames.has(entry.name.toLowerCase()));
4359
+ }
4269
4360
  async function askEntityName(ctx, opts) {
4270
4361
  const blankHint = opts?.blankHint ?? "cancel";
4271
4362
  const declared = await promptUser(ctx, {
@@ -4372,8 +4463,14 @@ async function confirmEntities(ctx) {
4372
4463
  throw new Error("User cancelled entity selection \u2014 analysis halted.");
4373
4464
  }
4374
4465
  ctx.setUserInput("confirmedEntities", confirmed2);
4375
- track("AI Wizard Entities Confirmed", {
4376
- entities: toEntitySummary(confirmed2)
4466
+ const languages = ctx.getStepOutput(
4467
+ "confirm-language"
4468
+ )?.languages;
4469
+ const summary = toEntitySummary(confirmed2);
4470
+ track("AI Wizard Data Model Confirmed", {
4471
+ data_model: summary[0]?.name ?? "unknown",
4472
+ attribute_count: summary[0]?.attributes.length ?? 0,
4473
+ used_detected_back_end: usedDetectedBackend(scan.languages, languages)
4377
4474
  });
4378
4475
  return { ingestionAnalysis: entities, confirmedEntities: confirmed2 };
4379
4476
  }
@@ -4423,7 +4520,7 @@ ${formatCompletedSteps(ctx.completedSteps)}`,
4423
4520
 
4424
4521
  // src/actions/implement.ts
4425
4522
  import z28 from "zod";
4426
- import { mkdir as mkdir5 } from "node:fs/promises";
4523
+ import { mkdir as mkdir5, readFile as readFile8 } from "node:fs/promises";
4427
4524
  import { join as join10, relative as relative6 } from "node:path";
4428
4525
 
4429
4526
  // src/lib/git.ts
@@ -4812,6 +4909,50 @@ function outputTail(output) {
4812
4909
  if (!trimmed) return void 0;
4813
4910
  return trimmed.length > INGEST_OUTPUT_TAIL_CHARS ? `\u2026${trimmed.slice(-INGEST_OUTPUT_TAIL_CHARS)}` : trimmed;
4814
4911
  }
4912
+ function jsTypeName(value) {
4913
+ if (value === null) return "null";
4914
+ if (Array.isArray(value)) return "array";
4915
+ const type = typeof value;
4916
+ if (type === "string" || type === "number" || type === "boolean" || type === "object") {
4917
+ return type;
4918
+ }
4919
+ return "unknown";
4920
+ }
4921
+ async function firstRecordIn(filePath) {
4922
+ try {
4923
+ const parsed = JSON.parse(await readFile8(filePath, "utf8"));
4924
+ const first = Array.isArray(parsed) ? parsed[0] : parsed;
4925
+ if (first && typeof first === "object" && !Array.isArray(first)) {
4926
+ return first;
4927
+ }
4928
+ } catch {
4929
+ return void 0;
4930
+ }
4931
+ return void 0;
4932
+ }
4933
+ async function ingestedRecordSample(repoRoot, entityName, uploadFilePath) {
4934
+ const candidates = [];
4935
+ if (entityName) {
4936
+ const slug = entityName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
4937
+ candidates.push(join10(repoRoot, INGEST_DIR, "data", `${slug}.json`));
4938
+ }
4939
+ if (uploadFilePath?.toLowerCase().endsWith(".json")) {
4940
+ candidates.push(join10(repoRoot, uploadFilePath));
4941
+ }
4942
+ for (const candidate of candidates) {
4943
+ const sample = await firstRecordIn(candidate);
4944
+ if (sample) return sample;
4945
+ }
4946
+ return void 0;
4947
+ }
4948
+ function recordSchema(sample, attributes) {
4949
+ if (sample) {
4950
+ return Object.fromEntries(
4951
+ Object.entries(sample).map(([key, value]) => [key, jsTypeName(value)])
4952
+ );
4953
+ }
4954
+ return Object.fromEntries(attributes.map((key) => [key, "unknown"]));
4955
+ }
4815
4956
  function ingestFailure(attempt, executions) {
4816
4957
  if (!attempt) {
4817
4958
  return {
@@ -5041,11 +5182,24 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
5041
5182
  if (ingestScriptRan) {
5042
5183
  ingestOutcomeMessage = `\u2705 Ingestion succeeded${ingestRecordCount != null ? ` \u2014 ${ingestRecordCount} record(s) indexed.` : "."}`;
5043
5184
  if (ingestRecordCount != null) {
5185
+ const data_model = confirmed2?.[0]?.name ?? "unknown";
5186
+ const sample = await ingestedRecordSample(
5187
+ repoRoot,
5188
+ confirmed2?.[0]?.name,
5189
+ uploadFilePath
5190
+ );
5044
5191
  track("AI Wizard Ingest Successful", {
5045
- entity_name: confirmed2?.map((e) => e.name).join(", ") || "unknown",
5192
+ data_model,
5046
5193
  record_count: ingestRecordCount,
5047
- duration_ms: ingestDurationMs ?? 0
5194
+ duration_ms: ingestDurationMs ?? 0,
5195
+ index_name: targetIndex,
5196
+ record_schema: recordSchema(sample, confirmed2?.[0]?.attributes ?? [])
5048
5197
  });
5198
+ } else {
5199
+ logger.warn(
5200
+ { ingestCommand },
5201
+ "implement: ingestion ran but printed no record count; skipping Ingest Successful event"
5202
+ );
5049
5203
  }
5050
5204
  } else {
5051
5205
  const { reason, detail } = ingestFailure(ingestAttempt, executions);
@@ -5069,7 +5223,10 @@ ${detail}` : ""}`
5069
5223
  track("Error", {
5070
5224
  step: "Push Data",
5071
5225
  error: `ingestion did not complete: ${reason}`,
5072
- product_area: "AI Wizard"
5226
+ error_message: `ingestion did not complete: ${reason}`,
5227
+ error_type: "Ingest Records",
5228
+ product_area: "AI Wizard",
5229
+ ...ingestAttempt?.exitCode != null ? { error_code: String(ingestAttempt.exitCode) } : {}
5073
5230
  });
5074
5231
  }
5075
5232
  if (ingestScriptRan) {
@@ -5103,6 +5260,29 @@ ${detail}` : ""}`
5103
5260
  let searchConfigFile;
5104
5261
  if (useCases.includes("search")) {
5105
5262
  let extraInstructions = [];
5263
+ const confirmedFrameworks = language.frameworks ?? [];
5264
+ const detectedFrameworks = scan.frameworks ?? [];
5265
+ const framework = confirmedFrameworks[0]?.name ?? "unknown";
5266
+ const used_detected_framework = confirmedFrameworks.some(
5267
+ (confirmedFw) => detectedFrameworks.some(
5268
+ (detectedFw) => isSameFramework(confirmedFw.name, detectedFw.name)
5269
+ )
5270
+ );
5271
+ const searchStartedAt = Date.now();
5272
+ const trackComponentGenerated = (mounted_successfully, attempts) => {
5273
+ const searchFilesChanged = [
5274
+ ...new Set(useWizard.getState().writtenFiles)
5275
+ ].map((file) => relative6(repoRoot, file));
5276
+ track("AI Wizard Frontend Component Generated", {
5277
+ file_paths: searchFilesChanged,
5278
+ framework,
5279
+ duration_ms: Date.now() - searchStartedAt,
5280
+ used_detected_framework,
5281
+ mounted_successfully,
5282
+ location_heuristic: searchLocation ?? "unknown",
5283
+ attempts
5284
+ });
5285
+ };
5106
5286
  useWizard.getState().clearWrittenFiles();
5107
5287
  for (let attempt = 1; attempt <= MAX_IMPLEMENT_VERIFICATION_ATTEMPTS; attempt++) {
5108
5288
  if (attempt > 1) {
@@ -5127,19 +5307,12 @@ ${detail}` : ""}`
5127
5307
  summaries.push(formatSummary("verification", verification.summary));
5128
5308
  if (verification.sufficient) {
5129
5309
  ctx.setUserInput("implementation", "success");
5130
- const searchFilesChanged = [
5131
- ...new Set(useWizard.getState().writtenFiles)
5132
- ].map((file) => relative6(repoRoot, file));
5133
- track("AI Wizard Frontend Component Generated", {
5134
- filePaths: searchFilesChanged
5135
- });
5136
- track("AI Wizard Wired to UI", {
5137
- location_heuristic: searchLocation ?? "unknown"
5138
- });
5310
+ trackComponentGenerated(true, attempt);
5139
5311
  break;
5140
5312
  }
5141
5313
  if (attempt === MAX_IMPLEMENT_VERIFICATION_ATTEMPTS) {
5142
5314
  ctx.setUserInput("implementation", "fail");
5315
+ trackComponentGenerated(false, attempt);
5143
5316
  throw new Error(
5144
5317
  `Implementation verification failed after ${MAX_IMPLEMENT_VERIFICATION_ATTEMPTS} attempts: ${verification.additionalInstructions ?? verification.summary}`
5145
5318
  );
@@ -6459,7 +6632,7 @@ function App() {
6459
6632
  }
6460
6633
 
6461
6634
  // src/lib/envAppId.ts
6462
- import { readFile as readFile8 } from "node:fs/promises";
6635
+ import { readFile as readFile9 } from "node:fs/promises";
6463
6636
  import { join as join12 } from "node:path";
6464
6637
  var ENV_FILES = [".env", ".env.local"];
6465
6638
  var APP_ID_LINE = /^[ \t]*(?:export[ \t]+)?([A-Z0-9_]*ALGOLIA_APP(?:LICATION)?_ID)[ \t]*=[ \t]*(.*)$/gm;
@@ -6467,7 +6640,7 @@ async function findEnvApplicationId(root = process.cwd()) {
6467
6640
  for (const file of ENV_FILES) {
6468
6641
  let content;
6469
6642
  try {
6470
- content = await readFile8(join12(root, file), "utf8");
6643
+ content = await readFile9(join12(root, file), "utf8");
6471
6644
  } catch (err) {
6472
6645
  if (err.code !== "ENOENT") {
6473
6646
  logger.warn(
@@ -6820,7 +6993,7 @@ function delay(ms) {
6820
6993
  // package.json with { type: 'json' }
6821
6994
  var package_default2 = {
6822
6995
  name: "@algolia/wizard",
6823
- version: "0.62.0",
6996
+ version: "0.63.0",
6824
6997
  description: "Magically implement Algolia functionality in your codebase",
6825
6998
  type: "module",
6826
6999
  engines: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@algolia/wizard",
3
- "version": "0.62.0",
3
+ "version": "0.63.0",
4
4
  "description": "Magically implement Algolia functionality in your codebase",
5
5
  "type": "module",
6
6
  "engines": {