@algolia/wizard 0.98.0-rc.217.731 → 0.99.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 +181 -121
  2. package/package.json +4 -4
package/dist/main.js CHANGED
@@ -1581,35 +1581,41 @@ import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2, rm } f
1581
1581
  import { join as join4 } from "node:path";
1582
1582
  var isStepVisible = (s) => s.visible !== false;
1583
1583
  var stateFile = (workflowId) => join4(stateDir(), `state-${workflowId}.json`);
1584
+ var pendingWrite = Promise.resolve();
1584
1585
  function runAppId(state) {
1585
1586
  const appId = state.algoliaState.appId;
1586
1587
  return typeof appId === "string" && appId ? appId : void 0;
1587
1588
  }
1588
1589
  async function loadWorkflowState(workflowId) {
1590
+ const file = stateFile(workflowId);
1591
+ await pendingWrite;
1589
1592
  try {
1590
- const raw = await readFile2(stateFile(workflowId), "utf8");
1593
+ const raw = await readFile2(file, "utf8");
1591
1594
  return JSON.parse(raw);
1592
1595
  } catch {
1593
1596
  return null;
1594
1597
  }
1595
1598
  }
1599
+ function enqueueWrite(write) {
1600
+ const next = pendingWrite.then(write, write);
1601
+ pendingWrite = next.catch(() => void 0);
1602
+ return next;
1603
+ }
1596
1604
  async function saveWorkflowState(state) {
1597
- await mkdir2(stateDir(), { recursive: true });
1598
- await writeFile2(
1599
- stateFile(state.workflowId),
1600
- JSON.stringify(state, null, 2),
1601
- "utf8"
1602
- );
1605
+ const dir = stateDir();
1606
+ const file = stateFile(state.workflowId);
1607
+ const json = JSON.stringify(state, null, 2);
1608
+ return enqueueWrite(async () => {
1609
+ await mkdir2(dir, { recursive: true });
1610
+ await writeFile2(file, json, "utf8");
1611
+ });
1603
1612
  }
1604
1613
  async function clearWorkflowState(workflowId) {
1605
- await rm(stateFile(workflowId), { force: true });
1614
+ const file = stateFile(workflowId);
1615
+ return enqueueWrite(() => rm(file, { force: true }));
1606
1616
  }
1607
1617
 
1608
1618
  // src/lib/modelProfiles.ts
1609
- var MODEL_CAPABILITIES = {
1610
- "claude-haiku-5-5": { forcedToolUse: true, lowestThinking: "disabled" },
1611
- "claude-sonnet-5-5": { forcedToolUse: false, lowestThinking: "between_tools" }
1612
- };
1613
1619
  var TOKENS_PER_MILLION = 1e6;
1614
1620
  var INITIAL_MODEL_ATTEMPT = 1;
1615
1621
  var NO_TOKENS = 0;
@@ -1621,57 +1627,57 @@ var IMPLEMENTATION_MAX_OUTPUT_TOKENS = 65536;
1621
1627
  var IMPLEMENTATION_MAX_STEPS = 48;
1622
1628
  var VALIDATION_MAX_OUTPUT_TOKENS = 8192;
1623
1629
  var VALIDATION_MAX_STEPS = 24;
1624
- var HAIKU_5_5_PRICES = {
1625
- input: 0.1,
1626
- output: 0.5,
1627
- cacheRead: 0.01,
1628
- cacheWrite: 0.125
1630
+ var HAIKU_4_5_PRICES = {
1631
+ input: 1,
1632
+ output: 5,
1633
+ cacheRead: 0.1,
1634
+ cacheWrite: 1.25
1629
1635
  };
1630
- var SONNET_5_5_PRICES = {
1636
+ var SONNET_5_PRICES = {
1631
1637
  input: 2,
1632
1638
  output: 10,
1633
- cacheRead: 0.1,
1639
+ cacheRead: 0.2,
1634
1640
  cacheWrite: 2.5
1635
1641
  };
1636
1642
  var MODEL_PROFILES = {
1637
1643
  quick: {
1638
- model: "claude-haiku-5-5",
1644
+ model: "claude-haiku-4-5",
1639
1645
  thinking: "disabled",
1640
1646
  maxOutputTokens: QUICK_MAX_OUTPUT_TOKENS,
1641
1647
  maxSteps: QUICK_MAX_STEPS,
1642
- prices: HAIKU_5_5_PRICES
1648
+ prices: HAIKU_4_5_PRICES
1643
1649
  },
1644
1650
  analysis: {
1645
- model: "claude-sonnet-5-5",
1651
+ model: "claude-sonnet-5",
1646
1652
  thinking: "adaptive",
1647
1653
  effort: "low",
1648
1654
  maxOutputTokens: ANALYSIS_MAX_OUTPUT_TOKENS,
1649
1655
  maxSteps: ANALYSIS_MAX_STEPS,
1650
- prices: SONNET_5_5_PRICES
1656
+ prices: SONNET_5_PRICES
1651
1657
  },
1652
1658
  implementation: {
1653
- model: "claude-sonnet-5-5",
1659
+ model: "claude-sonnet-5",
1654
1660
  thinking: "adaptive",
1655
1661
  effort: "medium",
1656
1662
  maxOutputTokens: IMPLEMENTATION_MAX_OUTPUT_TOKENS,
1657
1663
  maxSteps: IMPLEMENTATION_MAX_STEPS,
1658
- prices: SONNET_5_5_PRICES
1664
+ prices: SONNET_5_PRICES
1659
1665
  },
1660
1666
  implementationRetry: {
1661
- model: "claude-sonnet-5-5",
1667
+ model: "claude-sonnet-5",
1662
1668
  thinking: "adaptive",
1663
1669
  effort: "high",
1664
1670
  maxOutputTokens: IMPLEMENTATION_MAX_OUTPUT_TOKENS,
1665
1671
  maxSteps: IMPLEMENTATION_MAX_STEPS,
1666
- prices: SONNET_5_5_PRICES
1672
+ prices: SONNET_5_PRICES
1667
1673
  },
1668
1674
  validation: {
1669
- model: "claude-sonnet-5-5",
1675
+ model: "claude-sonnet-5",
1670
1676
  thinking: "adaptive",
1671
1677
  effort: "low",
1672
1678
  maxOutputTokens: VALIDATION_MAX_OUTPUT_TOKENS,
1673
1679
  maxSteps: VALIDATION_MAX_STEPS,
1674
- prices: SONNET_5_5_PRICES
1680
+ prices: SONNET_5_PRICES
1675
1681
  }
1676
1682
  };
1677
1683
  function getModelProfile(profileName) {
@@ -1684,14 +1690,6 @@ function providerOptionsForProfile(profileName) {
1684
1690
  ...profile.effort !== void 0 && { effort: profile.effort }
1685
1691
  };
1686
1692
  }
1687
- function toolChoiceForProfile(profileName) {
1688
- const { model } = getModelProfile(profileName);
1689
- return MODEL_CAPABILITIES[model].forcedToolUse ? "required" : "auto";
1690
- }
1691
- function lowestThinkingForProfile(profileName) {
1692
- const { model } = getModelProfile(profileName);
1693
- return { type: MODEL_CAPABILITIES[model].lowestThinking };
1694
- }
1695
1693
  function tokenCount(value = NO_TOKENS) {
1696
1694
  return value;
1697
1695
  }
@@ -1713,10 +1711,45 @@ var COUNT_METRIC = 1;
1713
1711
  var GAUGE_METRIC = 3;
1714
1712
  var FIRST_ATTEMPT = 1;
1715
1713
  var NO_TOKENS2 = 0;
1714
+ var NO_COST = 0;
1716
1715
  var AGENT_TELEMETRY_CONTEXT = {
1717
1716
  appId: void 0,
1718
- workflowId: void 0
1717
+ workflowId: void 0,
1718
+ agentRunId: void 0,
1719
+ sessionCostUsd: NO_COST
1719
1720
  };
1721
+ function resetTelemetryContext() {
1722
+ AGENT_TELEMETRY_CONTEXT.appId = void 0;
1723
+ AGENT_TELEMETRY_CONTEXT.workflowId = void 0;
1724
+ AGENT_TELEMETRY_CONTEXT.agentRunId = void 0;
1725
+ AGENT_TELEMETRY_CONTEXT.sessionCostUsd = NO_COST;
1726
+ }
1727
+ function sessionCostUsd(agentRunId) {
1728
+ return agentRunId && agentRunId === AGENT_TELEMETRY_CONTEXT.agentRunId ? AGENT_TELEMETRY_CONTEXT.sessionCostUsd : void 0;
1729
+ }
1730
+ var sessionCostListeners = /* @__PURE__ */ new Set();
1731
+ function onSessionCost(listener) {
1732
+ sessionCostListeners.add(listener);
1733
+ return () => {
1734
+ sessionCostListeners.delete(listener);
1735
+ };
1736
+ }
1737
+ function sessionTags() {
1738
+ const { agentRunId } = AGENT_TELEMETRY_CONTEXT;
1739
+ return agentRunId ? [`agent_run_id:${agentRunId}`] : [];
1740
+ }
1741
+ var UNKNOWN_STACK = "unknown";
1742
+ function sessionSummary(outcome, session) {
1743
+ const completedSteps = session?.completedSteps ?? [];
1744
+ return {
1745
+ outcome,
1746
+ estimated_cost_usd: AGENT_TELEMETRY_CONTEXT.sessionCostUsd,
1747
+ completed_steps: truncate2(completedSteps.join(", ")),
1748
+ completed_step_count: completedSteps.length,
1749
+ language: truncate2(session?.language ?? UNKNOWN_STACK),
1750
+ framework: truncate2(session?.framework ?? UNKNOWN_STACK)
1751
+ };
1752
+ }
1720
1753
  function isTelemetryOptedOut() {
1721
1754
  return process.env.WIZARD_TELEMETRY === "false";
1722
1755
  }
@@ -1849,13 +1882,15 @@ function agentRunMetrics(event, values, tags) {
1849
1882
  function trackAgentRun(event) {
1850
1883
  const profile = getModelProfile(event.profile);
1851
1884
  const values = agentRunValues(event);
1885
+ AGENT_TELEMETRY_CONTEXT.sessionCostUsd += values.estimatedCostUsd;
1852
1886
  const tagsForMetrics = agentMetricTags(
1853
1887
  event,
1854
1888
  AGENT_TELEMETRY_CONTEXT.workflowId
1855
1889
  );
1856
1890
  const tags = [
1857
1891
  ...tagsForMetrics,
1858
- ...AGENT_TELEMETRY_CONTEXT.appId ? [`app_id:${AGENT_TELEMETRY_CONTEXT.appId}`] : []
1892
+ ...AGENT_TELEMETRY_CONTEXT.appId ? [`app_id:${AGENT_TELEMETRY_CONTEXT.appId}`] : [],
1893
+ ...sessionTags()
1859
1894
  ];
1860
1895
  sendTelemetry({
1861
1896
  logs: [
@@ -1876,6 +1911,7 @@ function trackAgentRun(event) {
1876
1911
  finishReason: event.finishReason,
1877
1912
  workflow_id: AGENT_TELEMETRY_CONTEXT.workflowId,
1878
1913
  app_id: AGENT_TELEMETRY_CONTEXT.appId,
1914
+ agent_run_id: AGENT_TELEMETRY_CONTEXT.agentRunId,
1879
1915
  ...values
1880
1916
  },
1881
1917
  tags
@@ -1883,14 +1919,26 @@ function trackAgentRun(event) {
1883
1919
  ],
1884
1920
  metrics: agentRunMetrics(event, values, tagsForMetrics)
1885
1921
  });
1922
+ for (const listener of sessionCostListeners) {
1923
+ try {
1924
+ listener();
1925
+ } catch (err) {
1926
+ logger.warn({ err }, "session cost listener failed");
1927
+ }
1928
+ }
1886
1929
  }
1887
1930
  function logTags(workflowId, actionId, appId) {
1888
1931
  return [
1889
1932
  ...metricTags(workflowId, actionId),
1890
- ...appId ? [`app_id:${appId}`] : []
1933
+ ...appId ? [`app_id:${appId}`] : [],
1934
+ ...sessionTags()
1891
1935
  ];
1892
1936
  }
1893
- function emitTelemetryLog(level, message, attributes, tags) {
1937
+ function emitTelemetryLog(level, message, fields, tags) {
1938
+ const attributes = {
1939
+ ...fields,
1940
+ agent_run_id: AGENT_TELEMETRY_CONTEXT.agentRunId
1941
+ };
1894
1942
  if (level === "info") {
1895
1943
  logger.info(attributes, message);
1896
1944
  } else {
@@ -1901,6 +1949,8 @@ function emitTelemetryLog(level, message, attributes, tags) {
1901
1949
  function trackWorkflowStart(ctx) {
1902
1950
  AGENT_TELEMETRY_CONTEXT.appId = ctx.appId;
1903
1951
  AGENT_TELEMETRY_CONTEXT.workflowId = ctx.workflowId;
1952
+ AGENT_TELEMETRY_CONTEXT.agentRunId = ctx.agentRunId;
1953
+ AGENT_TELEMETRY_CONTEXT.sessionCostUsd = ctx.estimatedCostUsd ?? NO_COST;
1904
1954
  const attributes = {
1905
1955
  event: "wizard.workflow.start",
1906
1956
  workflow_id: ctx.workflowId,
@@ -1919,7 +1969,8 @@ function trackWorkflowAbandoned(ctx) {
1919
1969
  event: "wizard.workflow.abandoned",
1920
1970
  workflow_id: ctx.workflowId,
1921
1971
  app_id: ctx.appId,
1922
- reason: ctx.reason
1972
+ reason: ctx.reason,
1973
+ ...sessionSummary("abandoned", ctx.session)
1923
1974
  };
1924
1975
  emitTelemetryLog(
1925
1976
  "info",
@@ -2049,7 +2100,8 @@ function trackWizardComplete(event) {
2049
2100
  workflow_id: event.workflowId,
2050
2101
  app_id: event.appId,
2051
2102
  total_duration: event.total_duration,
2052
- total_steps: event.total_steps
2103
+ total_steps: event.total_steps,
2104
+ ...sessionSummary("success", event)
2053
2105
  };
2054
2106
  emitTelemetryLog(
2055
2107
  "info",
@@ -2057,8 +2109,7 @@ function trackWizardComplete(event) {
2057
2109
  attributes,
2058
2110
  logTags(event.workflowId, void 0, event.appId)
2059
2111
  );
2060
- AGENT_TELEMETRY_CONTEXT.appId = void 0;
2061
- AGENT_TELEMETRY_CONTEXT.workflowId = void 0;
2112
+ resetTelemetryContext();
2062
2113
  }
2063
2114
  function trackWorkflowError(ctx) {
2064
2115
  const attributes = {
@@ -2067,7 +2118,8 @@ function trackWorkflowError(ctx) {
2067
2118
  action_id: ctx.actionId,
2068
2119
  error: ctx.error,
2069
2120
  app_id: ctx.appId,
2070
- ...errorAttributes(ctx.cause)
2121
+ ...errorAttributes(ctx.cause),
2122
+ ...sessionSummary("failed", ctx.session)
2071
2123
  };
2072
2124
  emitTelemetryLog(
2073
2125
  "error",
@@ -2075,8 +2127,7 @@ function trackWorkflowError(ctx) {
2075
2127
  attributes,
2076
2128
  logTags(ctx.workflowId, ctx.actionId, ctx.appId)
2077
2129
  );
2078
- AGENT_TELEMETRY_CONTEXT.appId = void 0;
2079
- AGENT_TELEMETRY_CONTEXT.workflowId = void 0;
2130
+ resetTelemetryContext();
2080
2131
  }
2081
2132
 
2082
2133
  // src/lib/events.ts
@@ -2396,7 +2447,7 @@ async function ensureApplication(resumeAppId) {
2396
2447
  // package.json
2397
2448
  var package_default = {
2398
2449
  name: "@algolia/wizard",
2399
- version: "0.98.0-rc.217.731",
2450
+ version: "0.99.0",
2400
2451
  description: "Magically implement Algolia functionality in your codebase",
2401
2452
  type: "module",
2402
2453
  engines: {
@@ -2443,11 +2494,11 @@ var package_default = {
2443
2494
  vitest: "^4.1.11"
2444
2495
  },
2445
2496
  dependencies: {
2446
- "@ai-sdk/anthropic": "^3.0.128",
2447
- "@ai-sdk/openai-compatible": "^2.0.81",
2497
+ "@ai-sdk/anthropic": "^3.0.118",
2498
+ "@ai-sdk/openai-compatible": "^2.0.75",
2448
2499
  "@hono/node-server": "^2.0.10",
2449
2500
  "@segment/analytics-node": "^3.1.0",
2450
- ai: "^6.0.302",
2501
+ ai: "^6.0.283",
2451
2502
  "cross-keychain": "^1.1.0",
2452
2503
  dotenv: "^17.4.2",
2453
2504
  hono: "^4.13.8",
@@ -2540,6 +2591,36 @@ function initWorkflowState(workflow, now, appId) {
2540
2591
  function ensureAgentRunId(state) {
2541
2592
  if (!state.agentRunId) state.agentRunId = crypto.randomUUID();
2542
2593
  }
2594
+ async function persistState(state) {
2595
+ state.estimatedCostUsd = sessionCostUsd(state.agentRunId) ?? state.estimatedCostUsd;
2596
+ await saveWorkflowState(state);
2597
+ }
2598
+ function saveCostDuringStep(state) {
2599
+ const snapshot = JSON.parse(JSON.stringify(state));
2600
+ return onSessionCost(() => {
2601
+ const cost = sessionCostUsd(state.agentRunId);
2602
+ if (cost === void 0) return;
2603
+ snapshot.estimatedCostUsd = cost;
2604
+ saveWorkflowState(snapshot).catch((err) => {
2605
+ logger.warn({ err }, "failed to save the session cost");
2606
+ });
2607
+ });
2608
+ }
2609
+ function stepOutput(state, stepId) {
2610
+ const record = state.steps.find((s) => s.id === stepId);
2611
+ return record?.status === "done" ? record.output : void 0;
2612
+ }
2613
+ function stackName(state, confirmStepId, key) {
2614
+ const name = stepOutput(state, confirmStepId)?.[key]?.[0]?.name ?? stepOutput(state, "project-scan")?.[key]?.[0]?.name;
2615
+ return name ? name.toLowerCase() : "unknown";
2616
+ }
2617
+ function sessionReport(state) {
2618
+ return {
2619
+ completedSteps: state.steps.filter((s) => s.status === "done").map((s) => s.id),
2620
+ language: stackName(state, "confirm-language", "languages"),
2621
+ framework: stackName(state, "confirm-framework", "frameworks")
2622
+ };
2623
+ }
2543
2624
  function completeEventProperties(state, totalDurationMs, stepCount) {
2544
2625
  const indexName = state.steps.find((s) => s.id === "select-index")?.output?.selection;
2545
2626
  const framework = state.steps.find((s) => s.id === "confirm-framework")?.output?.frameworks?.[0]?.name;
@@ -2644,7 +2725,7 @@ async function rewindTo(state, targetIndex, fromIndex) {
2644
2725
  const store = useWizard.getState();
2645
2726
  store.setActiveStep(targetIndex);
2646
2727
  store.syncSteps([...state.steps], targetIndex);
2647
- await saveWorkflowState(state);
2728
+ await persistState(state);
2648
2729
  }
2649
2730
  async function runStep(state, index, step) {
2650
2731
  const store = useWizard.getState();
@@ -2665,9 +2746,10 @@ async function runStep(state, index, step) {
2665
2746
  state.updatedAt = nowIso();
2666
2747
  store.setActiveStep(index);
2667
2748
  store.syncSteps([...state.steps], index);
2668
- await saveWorkflowState(state);
2749
+ await persistState(state);
2669
2750
  await markInteraction();
2670
2751
  const ctx = await makeContext(state);
2752
+ const stopSavingCost = saveCostDuringStep(state);
2671
2753
  let output;
2672
2754
  try {
2673
2755
  const raw = await step.run(ctx);
@@ -2675,6 +2757,7 @@ async function runStep(state, index, step) {
2675
2757
  await step.onStepComplete?.(output, ctx);
2676
2758
  } catch (err) {
2677
2759
  if (err instanceof ReturnToStepSignal) {
2760
+ stopSavingCost();
2678
2761
  await rewindTo(state, err.targetIndex, index);
2679
2762
  return err.targetIndex;
2680
2763
  }
@@ -2689,12 +2772,14 @@ async function runStep(state, index, step) {
2689
2772
  });
2690
2773
  }
2691
2774
  throw err;
2775
+ } finally {
2776
+ stopSavingCost();
2692
2777
  }
2693
2778
  record.status = "done";
2694
2779
  record.output = output;
2695
2780
  state.updatedAt = nowIso();
2696
2781
  store.syncSteps([...state.steps], index);
2697
- await saveWorkflowState(state);
2782
+ await persistState(state);
2698
2783
  trackActionEnd({
2699
2784
  workflowId: state.workflowId,
2700
2785
  appId,
@@ -2752,13 +2837,19 @@ async function beginRun(workflow, state) {
2752
2837
  [...state.steps]
2753
2838
  );
2754
2839
  await ensureConsent();
2755
- trackWorkflowStart({ workflowId: workflow.id, appId: runAppId(state) });
2840
+ trackWorkflowStart({
2841
+ workflowId: workflow.id,
2842
+ appId: runAppId(state),
2843
+ agentRunId: state.agentRunId,
2844
+ estimatedCostUsd: state.estimatedCostUsd
2845
+ });
2756
2846
  }
2757
2847
  async function handleRestartWorkflow(workflow, previous, newAppId) {
2758
2848
  trackWorkflowAbandoned({
2759
2849
  workflowId: workflow.id,
2760
2850
  appId: runAppId(previous),
2761
- reason: "application_changed"
2851
+ reason: "application_changed",
2852
+ session: sessionReport(previous)
2762
2853
  });
2763
2854
  await clearWorkflowState(workflow.id);
2764
2855
  const next = initWorkflowState(workflow, nowIso(), newAppId);
@@ -2807,7 +2898,8 @@ async function runWorkflow(workflow, startWorkflowAppId, options) {
2807
2898
  workflowId: workflow.id,
2808
2899
  appId: runAppId(state),
2809
2900
  total_duration: Math.round(totalDurationMs / 1e3),
2810
- total_steps: stepCount
2901
+ total_steps: stepCount,
2902
+ ...sessionReport(state)
2811
2903
  });
2812
2904
  track(
2813
2905
  "AI Wizard Completed",
@@ -2831,12 +2923,12 @@ async function runWorkflow(workflow, startWorkflowAppId, options) {
2831
2923
  if (record.status === "running") {
2832
2924
  record.status = "error";
2833
2925
  record.error = message;
2834
- await saveWorkflowState(failed);
2835
2926
  store.syncSteps([...failed.steps], failed.currentStepIndex);
2836
2927
  }
2837
2928
  failedActionId = record.id;
2838
2929
  failedActionTitle = record.title;
2839
2930
  }
2931
+ await persistState(failed);
2840
2932
  }
2841
2933
  if (failedActionId && failedActionTitle) {
2842
2934
  trackActionError({
@@ -2853,7 +2945,8 @@ async function runWorkflow(workflow, startWorkflowAppId, options) {
2853
2945
  appId: failedAppId,
2854
2946
  error: message,
2855
2947
  actionId: failedActionId,
2856
- cause: err
2948
+ cause: err,
2949
+ session: failed ? sessionReport(failed) : void 0
2857
2950
  });
2858
2951
  const errorType = wizardErrorType(failedActionId, step, message);
2859
2952
  const errorCode2 = errorCodeFrom(err);
@@ -5282,10 +5375,6 @@ var MISSING_REPORT_STATUS_ERROR_MESSAGE = "Agent finished without calling report
5282
5375
  var MISSING_REPORT_USER_MESSAGE = "This step ran into a problem finishing. Run the wizard again to retry it.";
5283
5376
  var REPORT_STATUS_RETRIES = 2;
5284
5377
  var STEP_LIMIT_INSTRUCTION = "When reportStatus is the only tool available, you reached the step limit. This limit is not a failure, so do not report fail because of it: report status=success with the work done so far, and name the remaining work in the summary.";
5285
- var TOOL_EVERY_TURN_INSTRUCTION = "Call at least one tool in every response. Do not reply with text only. The run ends only when you call reportStatus.";
5286
- var ENDED_TURN_NUDGE = "Your last response did not call a tool. Continue the work with tools. When the work is done, call reportStatus.";
5287
- var INITIAL_PROMPT = "Follow system instructions";
5288
- var ENDED_TURN_CONTINUATIONS = 3;
5289
5378
  var RECENT_STEPS_LOGGED = 3;
5290
5379
  var LOGGED_CHARS = 300;
5291
5380
  var ATTEMPT_NUMBER_OFFSET = 1;
@@ -5323,13 +5412,6 @@ var MissingReportError = class extends Error {
5323
5412
  this.incompleteCause = incompleteCause;
5324
5413
  }
5325
5414
  };
5326
- var EndedTurnError = class extends MissingReportError {
5327
- continuation;
5328
- constructor(continuation) {
5329
- super(null);
5330
- this.continuation = continuation;
5331
- }
5332
- };
5333
5415
  function incompleteCauseOf(stepCount, maxSteps, finishReason) {
5334
5416
  if (stepCount >= maxSteps) return "stepLimit";
5335
5417
  if (finishReason === "length") return "truncated";
@@ -5380,23 +5462,10 @@ function exhaustedError(kind, err) {
5380
5462
  }
5381
5463
  async function runAgent(req) {
5382
5464
  let retryReason = null;
5383
- let attempt = INITIAL_ATTEMPT;
5384
- let continuation;
5385
- let continuations = 0;
5386
- for (; ; ) {
5465
+ for (let attempt = INITIAL_ATTEMPT; attempt <= REPORT_STATUS_RETRIES; attempt++) {
5387
5466
  try {
5388
- return await runAgentAttempt(req, attempt, retryReason, continuation);
5467
+ return await runAgentAttempt(req, attempt, retryReason);
5389
5468
  } catch (err) {
5390
- continuation = void 0;
5391
- if (err instanceof EndedTurnError && continuations < ENDED_TURN_CONTINUATIONS) {
5392
- continuations++;
5393
- continuation = err.continuation;
5394
- logger.warn(
5395
- { attempt: attempt + 1, continuations },
5396
- "continuing runAgent after a turn ended without a tool call"
5397
- );
5398
- continue;
5399
- }
5400
5469
  const kind = retryKind(err);
5401
5470
  if (!kind) throw err;
5402
5471
  if (attempt === REPORT_STATUS_RETRIES) throw exhaustedError(kind, err);
@@ -5405,23 +5474,19 @@ async function runAgent(req) {
5405
5474
  { attempt: attempt + 1, err },
5406
5475
  isMissingReportRetry(kind) ? "retrying runAgent after missing reportStatus" : "retrying runAgent after a transient provider error"
5407
5476
  );
5408
- attempt++;
5409
5477
  }
5410
5478
  }
5479
+ throw new Error("unreachable");
5411
5480
  }
5412
- async function runAgentAttempt(req, attempt, retryReason, continuation) {
5481
+ async function runAgentAttempt(req, attempt, retryReason) {
5413
5482
  const start = Date.now();
5414
5483
  const profileName = req.modelProfile ?? "implementation" /* implementation */;
5415
5484
  const profile = getModelProfile(profileName);
5416
5485
  const profileOptions = providerOptionsForProfile(profileName);
5417
- const toolChoice = toolChoiceForProfile(profileName);
5418
5486
  const maxSteps = req.maxSteps ?? profile.maxSteps;
5419
- const stepsUsed = continuation?.stepsUsed ?? 0;
5420
- const stepsLeft = maxSteps - stepsUsed;
5421
5487
  const forceReport = retryReason === "missingReport";
5422
5488
  const incompleteReason = incompleteReasonOf(retryReason);
5423
- const reportThinking = lowestThinkingForProfile(profileName);
5424
- const modelOptions = forceReport ? { thinking: reportThinking, effort: void 0 } : profileOptions;
5489
+ const modelOptions = forceReport ? { thinking: { type: "disabled" } } : profileOptions;
5425
5490
  logger.info(
5426
5491
  {
5427
5492
  startedAt: new Date(start).toISOString(),
@@ -5429,9 +5494,8 @@ async function runAgentAttempt(req, attempt, retryReason, continuation) {
5429
5494
  profile: profileName,
5430
5495
  model: profile.model,
5431
5496
  effort: forceReport ? void 0 : profile.effort,
5432
- thinking: forceReport ? reportThinking.type : profile.thinking,
5433
- retryReason,
5434
- stepsUsed
5497
+ thinking: forceReport ? "disabled" : profile.thinking,
5498
+ retryReason
5435
5499
  },
5436
5500
  "runAgent started"
5437
5501
  );
@@ -5445,7 +5509,7 @@ async function runAgentAttempt(req, attempt, retryReason, continuation) {
5445
5509
  fetch: proxyFetch
5446
5510
  });
5447
5511
  const toolContext = req.toolContext ?? createToolContext();
5448
- if (attempt > INITIAL_ATTEMPT && !continuation) resetToolCounts(toolContext);
5512
+ if (attempt > INITIAL_ATTEMPT) resetToolCounts(toolContext);
5449
5513
  const readTools = ["readFile", "searchFiles", "listFiles"];
5450
5514
  const hasReadTools = !req.tools || req.tools.some((t) => readTools.includes(t));
5451
5515
  const instructions = [
@@ -5454,7 +5518,6 @@ async function runAgentAttempt(req, attempt, retryReason, continuation) {
5454
5518
  "When you need to read or search multiple files, issue those tool calls together in one step rather than one at a time."
5455
5519
  ] : [],
5456
5520
  "Call notifyUser whenever you start a new phase of work or your focus shifts (e.g. moving from reading code to writing files) \u2014 a short, plain-language, high-level update. Do not call it for every tool use.",
5457
- ...toolChoice === "auto" ? [TOOL_EVERY_TURN_INSTRUCTION] : [],
5458
5521
  STEP_LIMIT_INSTRUCTION,
5459
5522
  // Last so a retry does not bust the cached tools+system prefix from
5460
5523
  // the first attempt. Inspect-and-continue, not start over: implement
@@ -5499,14 +5562,14 @@ async function runAgentAttempt(req, attempt, retryReason, continuation) {
5499
5562
  output: req.outputSchema,
5500
5563
  tools: req.tools
5501
5564
  }),
5502
- toolChoice,
5565
+ toolChoice: "required",
5503
5566
  stopWhen: [
5504
5567
  hasToolCall("reportStatus"),
5505
- stepCountIs(stepsLeft)
5568
+ stepCountIs(maxSteps)
5506
5569
  ],
5507
5570
  prepareStep: ({ stepNumber, messages }) => ({
5508
5571
  messages: withCachedHistory(messages),
5509
- ...stepNumber >= stepsLeft - 1 && {
5572
+ ...stepNumber >= maxSteps - 1 && {
5510
5573
  activeTools: ["reportStatus"]
5511
5574
  }
5512
5575
  }),
@@ -5514,11 +5577,9 @@ async function runAgentAttempt(req, attempt, retryReason, continuation) {
5514
5577
  ...{ onError: () => {
5515
5578
  } }
5516
5579
  });
5517
- const prompt = continuation ? [
5518
- ...continuation.messages,
5519
- { role: "user", content: ENDED_TURN_NUDGE }
5520
- ] : [{ role: "user", content: INITIAL_PROMPT }];
5521
- const stream = await agent.stream({ prompt });
5580
+ const stream = await agent.stream({
5581
+ prompt: "Follow system instructions"
5582
+ });
5522
5583
  let chunks = [];
5523
5584
  const chunkLimit = 5;
5524
5585
  let streamError;
@@ -5550,8 +5611,7 @@ async function runAgentAttempt(req, attempt, retryReason, continuation) {
5550
5611
  const usage = await stream.totalUsage;
5551
5612
  const steps = await stream.steps;
5552
5613
  const stepCount = steps.length;
5553
- const totalSteps = stepsUsed + stepCount;
5554
- const hitStepLimit = totalSteps >= maxSteps;
5614
+ const hitStepLimit = stepCount >= maxSteps;
5555
5615
  const lastStep = steps[steps.length - 1];
5556
5616
  const finishReason = lastStep?.finishReason;
5557
5617
  trackAgentRun({
@@ -5599,16 +5659,8 @@ async function runAgentAttempt(req, attempt, retryReason, continuation) {
5599
5659
  },
5600
5660
  "Agent finished without calling reportStatus"
5601
5661
  );
5602
- const endedTurn = toolChoice === "auto" && finishReason === "stop" && !lastStep?.toolCalls?.length && !hitStepLimit;
5603
- if (endedTurn) {
5604
- const { messages } = await stream.response;
5605
- throw new EndedTurnError({
5606
- messages: [...prompt, ...messages],
5607
- stepsUsed: totalSteps
5608
- });
5609
- }
5610
5662
  throw new MissingReportError(
5611
- incompleteCauseOf(totalSteps, maxSteps, finishReason)
5663
+ incompleteCauseOf(stepCount, maxSteps, finishReason)
5612
5664
  );
5613
5665
  }
5614
5666
  const result = report.output;
@@ -7351,6 +7403,14 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES) {
7351
7403
  }
7352
7404
  if (ingestScriptRan) {
7353
7405
  ingestOutcomeMessage = `\u2705 Ingestion succeeded${ingestRecordCount != null ? ` \u2014 ${ingestRecordCount} record(s) indexed.` : "."}`;
7406
+ if (ingestRunAttempts > 1) {
7407
+ summaries.push(
7408
+ formatSummary(
7409
+ "ingestion",
7410
+ `The script ran ${ingestRunAttempts} times. Ingestion succeeded${ingestRecordCount != null ? ` and indexed ${ingestRecordCount} record(s)` : ""}.`
7411
+ )
7412
+ );
7413
+ }
7354
7414
  if (ingestRecordCount != null) {
7355
7415
  const data_model = confirmed2?.[0]?.name ?? "unknown";
7356
7416
  const sample = await ingestedRecordSample(
@@ -9956,7 +10016,7 @@ async function resetProjectState() {
9956
10016
  // package.json with { type: 'json' }
9957
10017
  var package_default2 = {
9958
10018
  name: "@algolia/wizard",
9959
- version: "0.98.0-rc.217.731",
10019
+ version: "0.99.0",
9960
10020
  description: "Magically implement Algolia functionality in your codebase",
9961
10021
  type: "module",
9962
10022
  engines: {
@@ -10003,11 +10063,11 @@ var package_default2 = {
10003
10063
  vitest: "^4.1.11"
10004
10064
  },
10005
10065
  dependencies: {
10006
- "@ai-sdk/anthropic": "^3.0.128",
10007
- "@ai-sdk/openai-compatible": "^2.0.81",
10066
+ "@ai-sdk/anthropic": "^3.0.118",
10067
+ "@ai-sdk/openai-compatible": "^2.0.75",
10008
10068
  "@hono/node-server": "^2.0.10",
10009
10069
  "@segment/analytics-node": "^3.1.0",
10010
- ai: "^6.0.302",
10070
+ ai: "^6.0.283",
10011
10071
  "cross-keychain": "^1.1.0",
10012
10072
  dotenv: "^17.4.2",
10013
10073
  hono: "^4.13.8",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@algolia/wizard",
3
- "version": "0.98.0-rc.217.731",
3
+ "version": "0.99.0",
4
4
  "description": "Magically implement Algolia functionality in your codebase",
5
5
  "type": "module",
6
6
  "engines": {
@@ -47,11 +47,11 @@
47
47
  "vitest": "^4.1.11"
48
48
  },
49
49
  "dependencies": {
50
- "@ai-sdk/anthropic": "^3.0.128",
51
- "@ai-sdk/openai-compatible": "^2.0.81",
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.302",
54
+ "ai": "^6.0.283",
55
55
  "cross-keychain": "^1.1.0",
56
56
  "dotenv": "^17.4.2",
57
57
  "hono": "^4.13.8",