@algolia/wizard 0.66.0 → 0.67.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 +319 -27
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -1490,7 +1490,106 @@ async function clearWorkflowState(workflowId) {
1490
1490
  await rm(stateFile(workflowId), { force: true });
1491
1491
  }
1492
1492
 
1493
+ // src/lib/modelProfiles.ts
1494
+ var TOKENS_PER_MILLION = 1e6;
1495
+ var INITIAL_MODEL_ATTEMPT = 1;
1496
+ var NO_TOKENS = 0;
1497
+ var QUICK_MAX_OUTPUT_TOKENS = 8192;
1498
+ var QUICK_MAX_STEPS = 16;
1499
+ var ANALYSIS_MAX_OUTPUT_TOKENS = 8192;
1500
+ var ANALYSIS_MAX_STEPS = 24;
1501
+ var IMPLEMENTATION_MAX_OUTPUT_TOKENS = 65536;
1502
+ var IMPLEMENTATION_MAX_STEPS = 48;
1503
+ var VALIDATION_MAX_OUTPUT_TOKENS = 8192;
1504
+ var VALIDATION_MAX_STEPS = 24;
1505
+ var HAIKU_4_5_PRICES = {
1506
+ input: 1,
1507
+ output: 5,
1508
+ cacheRead: 0.1,
1509
+ cacheWrite: 1.25
1510
+ };
1511
+ var SONNET_5_PRICES = {
1512
+ input: 2,
1513
+ output: 10,
1514
+ cacheRead: 0.2,
1515
+ cacheWrite: 2.5
1516
+ };
1517
+ var MODEL_PROFILES = {
1518
+ quick: {
1519
+ model: "claude-haiku-4-5",
1520
+ thinking: "disabled",
1521
+ maxOutputTokens: QUICK_MAX_OUTPUT_TOKENS,
1522
+ maxSteps: QUICK_MAX_STEPS,
1523
+ prices: HAIKU_4_5_PRICES
1524
+ },
1525
+ analysis: {
1526
+ model: "claude-sonnet-5",
1527
+ thinking: "adaptive",
1528
+ effort: "low",
1529
+ maxOutputTokens: ANALYSIS_MAX_OUTPUT_TOKENS,
1530
+ maxSteps: ANALYSIS_MAX_STEPS,
1531
+ prices: SONNET_5_PRICES
1532
+ },
1533
+ implementation: {
1534
+ model: "claude-sonnet-5",
1535
+ thinking: "adaptive",
1536
+ effort: "medium",
1537
+ maxOutputTokens: IMPLEMENTATION_MAX_OUTPUT_TOKENS,
1538
+ maxSteps: IMPLEMENTATION_MAX_STEPS,
1539
+ prices: SONNET_5_PRICES
1540
+ },
1541
+ implementationRetry: {
1542
+ model: "claude-sonnet-5",
1543
+ thinking: "adaptive",
1544
+ effort: "high",
1545
+ maxOutputTokens: IMPLEMENTATION_MAX_OUTPUT_TOKENS,
1546
+ maxSteps: IMPLEMENTATION_MAX_STEPS,
1547
+ prices: SONNET_5_PRICES
1548
+ },
1549
+ validation: {
1550
+ model: "claude-sonnet-5",
1551
+ thinking: "adaptive",
1552
+ effort: "low",
1553
+ maxOutputTokens: VALIDATION_MAX_OUTPUT_TOKENS,
1554
+ maxSteps: VALIDATION_MAX_STEPS,
1555
+ prices: SONNET_5_PRICES
1556
+ }
1557
+ };
1558
+ function getModelProfile(profileName) {
1559
+ return MODEL_PROFILES[profileName];
1560
+ }
1561
+ function providerOptionsForProfile(profileName) {
1562
+ const profile = getModelProfile(profileName);
1563
+ return {
1564
+ thinking: { type: profile.thinking },
1565
+ ...profile.effort !== void 0 && { effort: profile.effort }
1566
+ };
1567
+ }
1568
+ function tokenCount(value = NO_TOKENS) {
1569
+ return value;
1570
+ }
1571
+ function estimateModelCost(profileName, usage) {
1572
+ const { prices } = getModelProfile(profileName);
1573
+ const inputDetails = Object.assign({}, usage.inputTokenDetails);
1574
+ const cacheRead = tokenCount(inputDetails.cacheReadTokens);
1575
+ const cacheWrite = tokenCount(inputDetails.cacheWriteTokens);
1576
+ const input = Math.max(
1577
+ NO_TOKENS,
1578
+ tokenCount(usage.inputTokens) - cacheRead - cacheWrite
1579
+ );
1580
+ const output = tokenCount(usage.outputTokens);
1581
+ return (input * prices.input + cacheRead * prices.cacheRead + cacheWrite * prices.cacheWrite + output * prices.output) / TOKENS_PER_MILLION;
1582
+ }
1583
+
1493
1584
  // src/lib/telemetry.ts
1585
+ var COUNT_METRIC = 1;
1586
+ var GAUGE_METRIC = 3;
1587
+ var FIRST_ATTEMPT = 1;
1588
+ var NO_TOKENS2 = 0;
1589
+ var AGENT_TELEMETRY_CONTEXT = {
1590
+ appId: void 0,
1591
+ workflowId: void 0
1592
+ };
1494
1593
  function isTelemetryOptedOut() {
1495
1594
  return process.env.WIZARD_TELEMETRY === "false";
1496
1595
  }
@@ -1537,6 +1636,110 @@ function sendMetric(name, value, type, tags = []) {
1537
1636
  function metricTags(workflowId, actionId) {
1538
1637
  return actionId ? [`workflow:${workflowId}`, `action:${actionId}`] : [`workflow:${workflowId}`];
1539
1638
  }
1639
+ function agentMetricTags(event, workflowId) {
1640
+ const profile = getModelProfile(event.profile);
1641
+ return [
1642
+ ...workflowId ? [`workflow:${workflowId}`] : [],
1643
+ `operation:${event.operation}`,
1644
+ `profile:${event.profile}`,
1645
+ `model:${profile.model}`,
1646
+ `effort:${profile.effort ?? "none"}`,
1647
+ `thinking:${profile.thinking}`
1648
+ ];
1649
+ }
1650
+ function agentRunValues(event) {
1651
+ const usage = Object.assign({}, event.usage);
1652
+ const inputTokenDetails = Object.assign({}, usage.inputTokenDetails);
1653
+ return {
1654
+ inputTokens: usage.inputTokens ?? NO_TOKENS2,
1655
+ outputTokens: usage.outputTokens ?? NO_TOKENS2,
1656
+ cacheReadTokens: inputTokenDetails.cacheReadTokens ?? NO_TOKENS2,
1657
+ cacheWriteTokens: inputTokenDetails.cacheWriteTokens ?? NO_TOKENS2,
1658
+ estimatedCostUsd: estimateModelCost(event.profile, usage)
1659
+ };
1660
+ }
1661
+ function agentRunMetrics(event, values, tags) {
1662
+ const runTags = [...tags];
1663
+ return [
1664
+ {
1665
+ name: "wizard.agent.duration_ms",
1666
+ value: event.durationMs,
1667
+ type: GAUGE_METRIC,
1668
+ tags: runTags
1669
+ },
1670
+ {
1671
+ name: "wizard.agent.input_tokens",
1672
+ value: values.inputTokens,
1673
+ type: COUNT_METRIC,
1674
+ tags: runTags
1675
+ },
1676
+ {
1677
+ name: "wizard.agent.output_tokens",
1678
+ value: values.outputTokens,
1679
+ type: COUNT_METRIC,
1680
+ tags: runTags
1681
+ },
1682
+ {
1683
+ name: "wizard.agent.cache_read_tokens",
1684
+ value: values.cacheReadTokens,
1685
+ type: COUNT_METRIC,
1686
+ tags: runTags
1687
+ },
1688
+ {
1689
+ name: "wizard.agent.cache_write_tokens",
1690
+ value: values.cacheWriteTokens,
1691
+ type: COUNT_METRIC,
1692
+ tags: runTags
1693
+ },
1694
+ {
1695
+ name: "wizard.agent.estimated_cost_usd",
1696
+ value: values.estimatedCostUsd,
1697
+ type: COUNT_METRIC,
1698
+ tags: runTags
1699
+ },
1700
+ {
1701
+ name: "wizard.agent.retry",
1702
+ value: Number(event.attempt > FIRST_ATTEMPT),
1703
+ type: COUNT_METRIC,
1704
+ tags: runTags
1705
+ }
1706
+ ];
1707
+ }
1708
+ function trackAgentRun(event) {
1709
+ const profile = getModelProfile(event.profile);
1710
+ const values = agentRunValues(event);
1711
+ const tagsForMetrics = agentMetricTags(
1712
+ event,
1713
+ AGENT_TELEMETRY_CONTEXT.workflowId
1714
+ );
1715
+ const tags = [
1716
+ ...tagsForMetrics,
1717
+ ...AGENT_TELEMETRY_CONTEXT.appId ? [`app_id:${AGENT_TELEMETRY_CONTEXT.appId}`] : []
1718
+ ];
1719
+ sendTelemetry({
1720
+ logs: [
1721
+ {
1722
+ status: "info",
1723
+ message: "wizard agent completed",
1724
+ attributes: {
1725
+ event: "wizard.agent.complete",
1726
+ operation: event.operation,
1727
+ profile: event.profile,
1728
+ model: profile.model,
1729
+ effort: profile.effort ?? "none",
1730
+ thinking: profile.thinking,
1731
+ attempt: event.attempt,
1732
+ durationMs: event.durationMs,
1733
+ workflow_id: AGENT_TELEMETRY_CONTEXT.workflowId,
1734
+ app_id: AGENT_TELEMETRY_CONTEXT.appId,
1735
+ ...values
1736
+ },
1737
+ tags
1738
+ }
1739
+ ],
1740
+ metrics: agentRunMetrics(event, values, tagsForMetrics)
1741
+ });
1742
+ }
1540
1743
  function logTags(workflowId, actionId, appId) {
1541
1744
  return [
1542
1745
  ...metricTags(workflowId, actionId),
@@ -1552,6 +1755,8 @@ function emitTelemetryLog(level, message, attributes, tags) {
1552
1755
  sendLog(level, message, attributes, tags);
1553
1756
  }
1554
1757
  function trackWorkflowStart(ctx) {
1758
+ AGENT_TELEMETRY_CONTEXT.appId = ctx.appId;
1759
+ AGENT_TELEMETRY_CONTEXT.workflowId = ctx.workflowId;
1555
1760
  const attributes = {
1556
1761
  event: "wizard.workflow.start",
1557
1762
  workflow_id: ctx.workflowId,
@@ -1677,6 +1882,8 @@ function trackWizardComplete(event) {
1677
1882
  attributes,
1678
1883
  logTags(event.workflowId, void 0, event.appId)
1679
1884
  );
1885
+ AGENT_TELEMETRY_CONTEXT.appId = void 0;
1886
+ AGENT_TELEMETRY_CONTEXT.workflowId = void 0;
1680
1887
  }
1681
1888
  function trackWorkflowError(ctx) {
1682
1889
  const attributes = {
@@ -1693,6 +1900,8 @@ function trackWorkflowError(ctx) {
1693
1900
  attributes,
1694
1901
  logTags(ctx.workflowId, ctx.actionId, ctx.appId)
1695
1902
  );
1903
+ AGENT_TELEMETRY_CONTEXT.appId = void 0;
1904
+ AGENT_TELEMETRY_CONTEXT.workflowId = void 0;
1696
1905
  }
1697
1906
 
1698
1907
  // src/lib/events.ts
@@ -1760,7 +1969,7 @@ function identify(traits) {
1760
1969
  // package.json
1761
1970
  var package_default = {
1762
1971
  name: "@algolia/wizard",
1763
- version: "0.66.0",
1972
+ version: "0.67.0",
1764
1973
  description: "Magically implement Algolia functionality in your codebase",
1765
1974
  type: "module",
1766
1975
  engines: {
@@ -2306,7 +2515,8 @@ import {
2306
2515
  hasToolCall,
2307
2516
  Output as Output3,
2308
2517
  APICallError,
2309
- NoOutputGeneratedError
2518
+ NoOutputGeneratedError,
2519
+ stepCountIs
2310
2520
  } from "ai";
2311
2521
  import { createAnthropic as createAnthropic3 } from "@ai-sdk/anthropic";
2312
2522
  import "zod";
@@ -3297,6 +3507,7 @@ function runShell(command, opts) {
3297
3507
  }
3298
3508
 
3299
3509
  // src/lib/tools/runShell.ts
3510
+ var CLASSIFIER_MAX_OUTPUT_TOKENS = 512;
3300
3511
  function storeApproval(root) {
3301
3512
  return async (req) => {
3302
3513
  const store = useWizard.getState();
@@ -3510,7 +3721,6 @@ function fastPathSafety(command) {
3510
3721
  if (results.every((r) => r === true)) return true;
3511
3722
  return void 0;
3512
3723
  }
3513
- var CLASSIFIER_MODEL = "claude-haiku-4-5";
3514
3724
  var commandSafetySchema = z16.object({
3515
3725
  safe: z16.boolean(),
3516
3726
  reason: z16.string().describe("One short sentence explaining the verdict.")
@@ -3535,9 +3745,21 @@ function approvedCommandHistory(approvedCommands) {
3535
3745
  async function classifyCommandSafety(createModel, command, cwd, explanation, approvedHistory) {
3536
3746
  try {
3537
3747
  const anthropic = createModel();
3538
- const { output } = await generateText({
3539
- model: anthropic(CLASSIFIER_MODEL),
3748
+ const profile = getModelProfile("quick" /* quick */);
3749
+ const modelOptions = providerOptionsForProfile("quick" /* quick */);
3750
+ const startedAt = Date.now();
3751
+ const { output, usage } = await generateText({
3752
+ model: anthropic(profile.model),
3753
+ maxOutputTokens: CLASSIFIER_MAX_OUTPUT_TOKENS,
3540
3754
  temperature: 0,
3755
+ providerOptions: {
3756
+ anthropic: {
3757
+ thinking: modelOptions.thinking,
3758
+ ...modelOptions.effort !== void 0 && {
3759
+ effort: modelOptions.effort
3760
+ }
3761
+ }
3762
+ },
3541
3763
  output: Output.object({ schema: commandSafetySchema }),
3542
3764
  prompt: [
3543
3765
  "A coding agent wants to run this shell command in a user's project without asking for approval first. The command may be in any programming language or ecosystem.",
@@ -3558,6 +3780,13 @@ async function classifyCommandSafety(createModel, command, cwd, explanation, app
3558
3780
  `Stated purpose: ${explanation}`
3559
3781
  ].join("\n")
3560
3782
  });
3783
+ trackAgentRun({
3784
+ operation: "shell-safety-classifier",
3785
+ profile: "quick" /* quick */,
3786
+ attempt: INITIAL_MODEL_ATTEMPT,
3787
+ durationMs: Date.now() - startedAt,
3788
+ usage
3789
+ });
3561
3790
  if (!output.safe) {
3562
3791
  logger.info(
3563
3792
  { command, reason: output.reason },
@@ -3702,7 +3931,6 @@ import { createAnthropic as createAnthropic2 } from "@ai-sdk/anthropic";
3702
3931
  import { nanoid as nanoid2 } from "nanoid";
3703
3932
  import z17 from "zod";
3704
3933
  var DATA_DIR = ".algolia-wizard/data";
3705
- var RECORD_MODEL = "claude-haiku-4-5";
3706
3934
  var MAX_RECORDS = 100;
3707
3935
  var BATCH_SIZE = 10;
3708
3936
  var MAX_BATCH_ATTEMPTS = 3;
@@ -3737,9 +3965,21 @@ function generateRecordTool(ctx, createModel = defaultCreateModel2) {
3737
3965
  const generateBatch = async (batchCount) => {
3738
3966
  let lastError;
3739
3967
  for (let attempt = 1; attempt <= MAX_BATCH_ATTEMPTS; attempt++) {
3968
+ const profile = getModelProfile("quick" /* quick */);
3969
+ const modelOptions = providerOptionsForProfile("quick" /* quick */);
3970
+ const startedAt = Date.now();
3740
3971
  try {
3741
- const { output } = await generateText2({
3742
- model: anthropic(RECORD_MODEL),
3972
+ const { output, usage } = await generateText2({
3973
+ model: anthropic(profile.model),
3974
+ maxOutputTokens: profile.maxOutputTokens,
3975
+ providerOptions: {
3976
+ anthropic: {
3977
+ thinking: modelOptions.thinking,
3978
+ ...modelOptions.effort !== void 0 && {
3979
+ effort: modelOptions.effort
3980
+ }
3981
+ }
3982
+ },
3743
3983
  output: Output2.object({
3744
3984
  schema: z17.object({
3745
3985
  records: z17.array(recordSchema2).length(batchCount)
@@ -3751,9 +3991,23 @@ function generateRecordTool(ctx, createModel = defaultCreateModel2) {
3751
3991
  `Variety seed: ${nanoid2()}. Use it to diversify values.`
3752
3992
  ].filter(Boolean).join("\n")
3753
3993
  });
3994
+ trackAgentRun({
3995
+ operation: "sample-record-generation",
3996
+ profile: "quick" /* quick */,
3997
+ attempt,
3998
+ durationMs: Date.now() - startedAt,
3999
+ usage
4000
+ });
3754
4001
  return output.records;
3755
4002
  } catch (err) {
3756
4003
  if (!NoObjectGeneratedError.isInstance(err)) throw err;
4004
+ trackAgentRun({
4005
+ operation: "sample-record-generation",
4006
+ profile: "quick" /* quick */,
4007
+ attempt,
4008
+ durationMs: Date.now() - startedAt,
4009
+ usage: err.usage
4010
+ });
3757
4011
  lastError = err;
3758
4012
  logger.warn(
3759
4013
  { entityName, batchCount, attempt, err },
@@ -3867,14 +4121,10 @@ var FS_READ_TOOLS = [
3867
4121
  ];
3868
4122
 
3869
4123
  // src/lib/agent.ts
3870
- var MODEL_BY_SIZE = {
3871
- small: "claude-haiku-4-5",
3872
- medium: "claude-sonnet-4-6",
3873
- large: "claude-opus-4-8"
3874
- };
3875
4124
  var MISSING_REPORT_STATUS_ERROR_MESSAGE = "Agent finished without calling reportStatus";
3876
4125
  var MISSING_REPORT_USER_MESSAGE = "This step ran into a problem finishing. Run the wizard again to retry it.";
3877
4126
  var REPORT_STATUS_RETRIES = 2;
4127
+ var ATTEMPT_NUMBER_OFFSET = 1;
3878
4128
  var PROVIDER_ERROR_USER_MESSAGE = "The AI service had trouble responding. Run the wizard again to retry this step.";
3879
4129
  function retryKind(err) {
3880
4130
  if (err instanceof Error && err.message === MISSING_REPORT_STATUS_ERROR_MESSAGE) {
@@ -3907,7 +4157,20 @@ async function runAgent(req) {
3907
4157
  }
3908
4158
  async function runAgentAttempt(req, attempt) {
3909
4159
  const start = Date.now();
3910
- logger.info({ startedAt: new Date(start).toISOString() }, "runAgent started");
4160
+ const profileName = req.modelProfile ?? "implementation" /* implementation */;
4161
+ const profile = getModelProfile(profileName);
4162
+ const modelOptions = providerOptionsForProfile(profileName);
4163
+ logger.info(
4164
+ {
4165
+ startedAt: new Date(start).toISOString(),
4166
+ operation: req.operation,
4167
+ profile: profileName,
4168
+ model: profile.model,
4169
+ effort: profile.effort,
4170
+ thinking: profile.thinking
4171
+ },
4172
+ "runAgent started"
4173
+ );
3911
4174
  const token = getAuthToken();
3912
4175
  if (!token) {
3913
4176
  throw new Error("Not authenticated: no user token available");
@@ -3934,7 +4197,16 @@ async function runAgentAttempt(req, attempt) {
3934
4197
  ] : []
3935
4198
  ];
3936
4199
  const agent = new ToolLoopAgent({
3937
- model: anthropic(MODEL_BY_SIZE[req.modelSize ?? "medium"]),
4200
+ model: anthropic(profile.model),
4201
+ maxOutputTokens: profile.maxOutputTokens,
4202
+ providerOptions: {
4203
+ anthropic: {
4204
+ thinking: modelOptions.thinking,
4205
+ ...modelOptions.effort !== void 0 && {
4206
+ effort: modelOptions.effort
4207
+ }
4208
+ }
4209
+ },
3938
4210
  // Cache tools + system on the last system block. Tools render before
3939
4211
  // system, so one breakpoint here caches both, reused on every loop turn
3940
4212
  // after the first.
@@ -3955,7 +4227,10 @@ async function runAgentAttempt(req, attempt) {
3955
4227
  tools: req.tools
3956
4228
  }),
3957
4229
  toolChoice: "required",
3958
- stopWhen: [hasToolCall("reportStatus")]
4230
+ stopWhen: [
4231
+ hasToolCall("reportStatus"),
4232
+ stepCountIs(profile.maxSteps)
4233
+ ]
3959
4234
  });
3960
4235
  const stream = await agent.stream({
3961
4236
  prompt: "Follow system instructions"
@@ -3986,13 +4261,20 @@ async function runAgentAttempt(req, attempt) {
3986
4261
  }
3987
4262
  const end = Date.now();
3988
4263
  const usage = await stream.totalUsage;
4264
+ trackAgentRun({
4265
+ operation: req.operation,
4266
+ profile: profileName,
4267
+ attempt: attempt + ATTEMPT_NUMBER_OFFSET,
4268
+ durationMs: end - start,
4269
+ usage
4270
+ });
3989
4271
  logger.info(
3990
4272
  {
3991
4273
  finishedAt: new Date(end).toISOString(),
3992
4274
  durationMs: end - start,
3993
- // cachedInputTokens > 0 confirms prompt caching engaged. If it stays 0
3994
- // across turns, the tools+system prefix is under the model's min
3995
- // cacheable size (2048 tokens for sonnet-4-6) and caching is a no-op.
4275
+ operation: req.operation,
4276
+ profile: profileName,
4277
+ model: profile.model,
3996
4278
  usage
3997
4279
  },
3998
4280
  "runAgent finished"
@@ -4073,6 +4355,7 @@ function prioritizeFrontendFrameworks(result) {
4073
4355
  }
4074
4356
  var detectLanguage = async () => {
4075
4357
  const result = await runAgent({
4358
+ operation: "language-detection",
4076
4359
  instructions: [
4077
4360
  "Analyze the codebase and determine the programming languages and frameworks used",
4078
4361
  "If a superset language is found, exclude the subset language (e.g. TypeScript over JavaScript).",
@@ -4088,7 +4371,7 @@ var detectLanguage = async () => {
4088
4371
  ],
4089
4372
  tools: ["listFiles", "changeDirectory", "readFile", "searchFiles"],
4090
4373
  outputSchema: detectLanguageSchema,
4091
- modelSize: "small"
4374
+ modelProfile: "quick" /* quick */
4092
4375
  });
4093
4376
  return prioritizeFrontendFrameworks(result);
4094
4377
  };
@@ -4164,9 +4447,11 @@ var MODE_CONFIG = {
4164
4447
  function runMode(mode, extraInstructions = []) {
4165
4448
  const { instructions, outputSchema } = MODE_CONFIG[mode];
4166
4449
  return runAgent({
4450
+ operation: `code-analysis-${mode}`,
4167
4451
  instructions: [...instructions, ...extraInstructions],
4168
4452
  tools: READONLY_TOOLS,
4169
- outputSchema
4453
+ outputSchema,
4454
+ modelProfile: "analysis" /* analysis */
4170
4455
  });
4171
4456
  }
4172
4457
  async function runAnalysis(mode, extraInstructions = []) {
@@ -4544,6 +4829,7 @@ ${JSON.stringify(s.output, null, 2)}`
4544
4829
  }
4545
4830
  var reviewStep = async (ctx, options) => {
4546
4831
  const result = await runAgent({
4832
+ operation: "workflow-review",
4547
4833
  instructions: [
4548
4834
  "Summarize what was accomplished in the workflow, leaving out verbose details.",
4549
4835
  "Base your summary only on the step outputs provided \u2014 do not read the repository.",
@@ -4558,7 +4844,7 @@ ${formatCompletedSteps(ctx.completedSteps)}`,
4558
4844
  ],
4559
4845
  tools: [],
4560
4846
  outputSchema: reviewSchema,
4561
- modelSize: "small"
4847
+ modelProfile: "quick" /* quick */
4562
4848
  });
4563
4849
  ctx.clearNotices();
4564
4850
  useWizard.getState().setReview(result);
@@ -4739,6 +5025,7 @@ var validationOutputSchema = z28.object({
4739
5025
  unrelatedFailure: z28.string().optional()
4740
5026
  });
4741
5027
  var MAX_IMPLEMENT_VALIDATION_ATTEMPTS = 3;
5028
+ var FIRST_IMPLEMENTATION_ATTEMPT = 1;
4742
5029
  var DEFAULT_IMPLEMENT_USE_CASES = ["ingestion", "search"];
4743
5030
  var INGEST_DIR = ".algolia-wizard";
4744
5031
  var INGESTION_SOURCE_PROMPT = "What data do you want to index?";
@@ -5235,10 +5522,11 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
5235
5522
  [INDEX_NAME_VAR]: targetIndex
5236
5523
  })) : void 0;
5237
5524
  const searchTools = makeToolContext(repoRoot);
5238
- async function runImplementationUseCase(currentUseCase, extraInstructions = []) {
5525
+ async function runImplementationUseCase(currentUseCase, extraInstructions = [], isRetry = false) {
5239
5526
  if (agentRuns > 0) ctx.recordStepExecution();
5240
5527
  agentRuns += 1;
5241
5528
  return runAgent({
5529
+ operation: `${currentUseCase}-implementation`,
5242
5530
  instructions: buildAgentInstructions(
5243
5531
  currentUseCase,
5244
5532
  input,
@@ -5246,6 +5534,7 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
5246
5534
  ),
5247
5535
  tools: toolsForUseCase(currentUseCase, input.ingestionSource),
5248
5536
  outputSchema: implementationOutputSchema,
5537
+ modelProfile: isRetry ? "implementationRetry" /* implementationRetry */ : "implementation" /* implementation */,
5249
5538
  toolContext: currentUseCase === "ingestion" ? ingestionTools ?? searchTools : searchTools
5250
5539
  });
5251
5540
  }
@@ -5253,6 +5542,7 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
5253
5542
  if (agentRuns > 0) ctx.recordStepExecution();
5254
5543
  agentRuns += 1;
5255
5544
  return runAgent({
5545
+ operation: "search-validation",
5256
5546
  instructions: buildAgentInstructions(
5257
5547
  "validation",
5258
5548
  input,
@@ -5260,6 +5550,7 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
5260
5550
  ),
5261
5551
  tools: toolsForUseCase("validation"),
5262
5552
  outputSchema: validationOutputSchema,
5553
+ modelProfile: "validation" /* validation */,
5263
5554
  toolContext: searchTools
5264
5555
  });
5265
5556
  }
@@ -5393,8 +5684,8 @@ ${detail}` : ""}`
5393
5684
  });
5394
5685
  };
5395
5686
  useWizard.getState().clearWrittenFiles();
5396
- for (let attempt = 1; attempt <= MAX_IMPLEMENT_VALIDATION_ATTEMPTS; attempt++) {
5397
- if (attempt > 1) {
5687
+ for (let attempt = FIRST_IMPLEMENTATION_ATTEMPT; attempt <= MAX_IMPLEMENT_VALIDATION_ATTEMPTS; attempt++) {
5688
+ if (attempt > FIRST_IMPLEMENTATION_ATTEMPT) {
5398
5689
  logger.info(
5399
5690
  {
5400
5691
  attempt,
@@ -5406,7 +5697,8 @@ ${detail}` : ""}`
5406
5697
  }
5407
5698
  const searchResult = await runImplementationUseCase(
5408
5699
  "search",
5409
- extraInstructions
5700
+ extraInstructions,
5701
+ attempt > FIRST_IMPLEMENTATION_ATTEMPT
5410
5702
  );
5411
5703
  summaries.push(formatSummary("search", searchResult.summary));
5412
5704
  if (searchResult.searchConfigFile) {
@@ -7170,7 +7462,7 @@ function delay(ms) {
7170
7462
  // package.json with { type: 'json' }
7171
7463
  var package_default2 = {
7172
7464
  name: "@algolia/wizard",
7173
- version: "0.66.0",
7465
+ version: "0.67.0",
7174
7466
  description: "Magically implement Algolia functionality in your codebase",
7175
7467
  type: "module",
7176
7468
  engines: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@algolia/wizard",
3
- "version": "0.66.0",
3
+ "version": "0.67.0",
4
4
  "description": "Magically implement Algolia functionality in your codebase",
5
5
  "type": "module",
6
6
  "engines": {