# Alokai Changelog (/alokai-changelog) # Alokai Changelog [#alokai-changelog] ## 2.4.0 [#240] **Release date:** 2026-08-12 ### Minor Changes [#minor-changes] * **ADDED** (`@alokai/connect-admin`) The feature editor — the middleware-served tool where you edit the configuration of your features at runtime, without a redeploy — now ships as its own package, moved out of `@alokai/compass`. Compass drops its feature-editor endpoints, the `defineFeatureEditor` API, the `featureEditors` config field, and the `sdk.compass.getFeatureEditorData` SDK method, with no re-exports left behind; you install, version, and turn the editor on independently. What you register are **features** — one per area of your app you want to administer — each grouping editable form views and browsable list-panel views, served at `/connect-admin`. The editor ships with versioning, auto-save, a three-way configuration merge, `{{ }}` template variables, per-feature documentation guides, and a bundled playground feature to explore before wiring a real one. See the Connect Admin documentation for installation, authoring view schemas, and reading the authored values through the SDK. The feature editor previously shipped only in Compass `-next` releases, so nothing changes for existing projects; if you used it on a `-next` release, see the migration guide below. * **ADDED** Major version upgrades now prompt for confirmation before running automated dependency installation, and print the migration guide URL on completion. * **ADDED** AI code review for pull requests. A CI-run review posts findings on your PRs — incremental by default (each run covers only the commits pushed since the last review, and a push with nothing new to review posts nothing; `--full` forces a whole-PR pass) and tuned for fewer, more trustworthy findings: every finding quotes the code it is about, a finding is only dropped by citing the code that contradicts it, findings the author already replied to are never raised again, pre-existing defects near the change are reported as context instead of blocking comments, and every review states what it did not cover. The review model is configured through the `AI_REVIEW_MODEL` environment variable, and the default configuration works out of the box in CI. To review changes before opening a pull request, use the `alokai-review` skill from `@alokai/ai-toolkit` in your coding agent session — it applies the same review criteria (correctness, consistency, security and performance, maintainability) without needing an API key; `yarn alokai ai review` remains the engine behind the CI review. * **ADDED** The `autofix` skill: applies accepted code review findings - a single review comment, a whole PR's feedback, or findings handed over in conversation - making the smallest correct edit per finding. When a fix depends on a judgement call, it puts the question to the developer instead of guessing or silently skipping. ### Patch Changes [#patch-changes] * **FIXED** Icon-only buttons now expose accessible names via translated `aria-label`s, fixing the failing `agent-accessibility-tree` audit in the Lighthouse "Agentic Browsing" category (covers the CMS mini-cart button with item count, the rotating-images pagination dots, and the Compass add-use-case button). * **FIXED** Storefront `build`, `dev`, and test scripts now work on Windows. Several `yarn` scripts (Next.js `multistore:dev`, middleware `build`, Playwright `test:integration` / `test:integration:dev`, and `changesets:publish:local`) previously set environment variables inline (e.g. `NODE_OPTIONS=... command`), which Windows `cmd`/PowerShell cannot parse. These scripts now use `cross-env` to set environment variables in a cross-platform way, and shell-only constructs (`if [ -d ... ]`, inline `node -e` one-liners) were replaced with small Node scripts so they run the same on Windows, macOS, and Linux. If your project overrides any of these scripts, see the migration guide below. * **ADDED** Per-integration circuit breaker preset selection via the `CB__PRESET` environment variable (e.g. `CB_SAPCC_PRESET=TOLERANT`). The integration name is uppercased with `-` replaced by `_`. Resolution priority: `CB__PRESET` → `CB_PRESET` → `circuitBreaker.preset` from the integration config → `BALANCED`. An invalid value logs a warning (naming the exact variable) and falls back to `BALANCED`; the `EXTREME_DEBUG` preset remains blocked in production. * **FIXED** Generated projects' GitHub Actions workflows now pin third-party actions (`actions/checkout`, `actions/setup-node`, `actions/cache`) to an immutable commit SHA instead of a mutable version tag, closing a supply-chain risk where a compromised tag could inject code into your CI/CD pipeline. * **CHANGED** The generated AGENTS.md now points to the `theming` and `perf-review` skills for theming and performance-review guidance instead of duplicating their instructions inline, keeping the always-loaded AGENTS.md leaner. * **FIXED** The CLI now includes the specific package name in the error shown when a package fails to install from the registry (e.g. during `yarn alokai store deploy`), instead of only a generic "Authorization required" message. * **FIXED** `yarn alokai store lint` (runs ESLint for one or more stores) no longer reports a store as failed when it has no override files to lint (e.g. a template store, or a store that fully inherits an app). * **FIXED** `yarn install` no longer fails on fresh clones at the `alokai-cli plugins install @alokai/cli-plugin-compass` postinstall step. The CLI now resolves plugins from the Alokai registry (`https://npm.alokai.cloud`) directly, so a user-level `@alokai:registry` mapping in `~/.npmrc` is no longer required — only the registry auth token. A user-level scope mapping or the `ALOKAI_CLI_NPM_REGISTRY` environment variable still takes precedence. * **FIXED** The request mocker no longer loads its `nock` and `@mswjs/interceptors` dependencies unless `defineMocker` is actually used, so importing the middleware integration kit no longer pulls these dev-only packages into your application at startup. * **FIXED** Deployed Next.js storefronts no longer crash on the first request with `Failed to load external module -: Cannot find module` when a server-external dependency (e.g. `pino`) is hoisted outside the app directory. `yarn alokai store deploy` now ships the complete Next.js standalone output — including the traced `node_modules` produced by the build — instead of reinstalling a minimal dependency set, so the shipped dependencies exactly match what the build traced and packaging no longer depends on the npm registry. * **ADDED** `yarn alokai store deploy` (deploys stores to the Alokai Console) now fails at packaging time with an actionable error when the assembled deployment package contains dangling symlinks, instead of surfacing the problem as a runtime crash in production. * **FIXED** `yarn alokai ai sync` (syncs skills and AGENTS.md from `@alokai/ai-toolkit` into the project's AI agent directories) now repairs AI skill links that git checked out as plain text stubs instead of symlinks (a common outcome on Windows), so skills load again without any manual cleanup. * **FIXED** Fixed project generation and store composition failing on native Windows: the generated project's `package.json` no longer relies on the Unix-only `mkdir -p`, and composed store output no longer includes `node_modules/.bin` shims that pointed at broken paths. * **FIXED** Store composition no longer crashes on Windows with `RangeError: path should be a path.relative()'d string`. The ignore-path filter now normalises Windows paths (backslashes and drive letters) to POSIX before matching, so absolute `C:\...` paths no longer reach the `ignore` matcher and `.gitignore`-style ignore rules apply correctly. * **FIXED** Alokai projects now work on native Windows (PowerShell), without WSL: cloning, installing, generating a project, and running the Next.js storefront are all supported. WSL2 remains the recommended setup. Known limitations: the Nuxt storefront does not yet start on native Windows, and Windows CI coverage is a biweekly scheduled E2E run rather than a check on every PR. See the [Windows support docs](https://docs.alokai.com/general/starting-new-project#windows-support) for setup and troubleshooting guidance. * **ADDED** (Compass) A/B experiment system. Mount `ExperimentsProvider` with an experiment registry and each visitor is assigned a variant per experiment by weighted random on page load, persisted in a per-experiment cookie so it stays sticky across reloads. `useExperiments()` exposes the resolved variants, serialized payloads for stamping analytics events, and a dev/QA override; a per-experiment `onAssignment` callback wires new assignments to any analytics provider. Experiments roll client-side only (rolling during SSR would be incompatible with CDN caching), and each split can be overridden from env via `NEXT_PUBLIC_COMPASS_AB__`. A demo experiment is mounted on the guided-selling page. * **CHANGED** (Compass) Installing the module now defaults to no-credentials-manager mode. `.env.example` is seeded with an active `ALOKAI_COMPASS_API_URL` (the Alokai LLM gateway) and `ALOKAI_COMPASS_NO_CREDENTIALS_MANAGER=true`, plus a commented-out, empty `ALOKAI_COMPASS_API_KEY=` for you to fill in. Previously it seeded an active dummy API key and a commented-out URL, which defaulted to the hosted credentials manager. * **FIXED** (Compass) Clearing the AI assistant session now also clears the page-context tracking entries in local storage (`ai-assistant-last-sent-product-id`, `assistant-last-title`, `assistant-last-search`). Previously the stale `ai-assistant-last-sent-product-id` entry survived a session restart, so the assistant never re-sent the product-visit context and lost track of the currently viewed product. The product and category context components now read the tracking entries fresh on each render pass, so the context message is re-sent immediately after a restart without leaving the page. * **FIXED** (Compass) AI Shopping Assistant reliability after the gateway model update: * Adding products from an uploaded file (e.g. CSV) no longer dead-ends with "no products found" — the `searchProducts` tool now steers the model to query by SKU, and a 0-results response tells it how to recover instead of giving up. * Price questions on a product page are answered in the product's actual currency; the assistant no longer assumes or converts the currency symbol. * Guided selling facet updates reject values outside the catalog facet domain and feed the valid options back to the model for a retry, instead of silently patching the UI with a value no select option matches. * Guided selling UI updates apply reliably during streaming: assistant messages are processed by id, so a state patch arriving in the same render as a stream consolidation is no longer skipped. * **FIXED** (Compass) Importing a trace dump in the dev tools no longer fails with HTTP 413 when the trace exceeds the middleware's default 100kb JSON body limit. The module's install script now raises the limit to 2mb for the `devToolsImport` endpoint. * **FIXED** (Compass) The dev tools page (`/compass/devTools`) now works when the middleware is served behind a path prefix, e.g. proxied under `/api` on deployed environments. The page previously requested its stylesheet, script, and trace data from the domain root (`/compass/...`), which returned 404 behind a proxy; all of these are now requested relative to the page URL. * **FIXED** (Compass) Clicking the search submit (magnifying glass) button no longer clears the live query. React 19 auto-resets a `
` after the action runs, which fired the form's `onReset` and wiped the query that a results-slot module (e.g. Coveo instant results) reads — so the slot reverted to its default/popular state for the whole submit → navigation window. The query is now cleared only on the explicit Cancel (reset) button; the post-submit auto-reset is ignored. * **ADDED** (Compass) Chat product results show a "Powered by …" source badge. The `searchProducts` tool reads an engine display name from the result's `$custom.source` (set by whichever search engine backs the unified method) and passes it to the generative `products-list`, which renders it verbatim and shows no badge when absent. The UI stays agnostic of which search engines exist — a backing engine sets its own `$custom.source` with no change to Compass. * **FIXED** (Compass) Cart, order summary, and cart-confirmation widgets no longer render broken product images when the commerce backend returns absolute media URLs. Image source resolution now passes absolute URLs through untouched and only prefixes `mediaHost` for relative paths. * **FIXED** (Compass) The "Open in Store" topbar button no longer crashes with `TypeError: redirectLinkFactories.addCartLineItems is not a function` after add/remove/update/clear cart tool calls. The redirect-link factory map now registers all cart-mutation tool names (`addCartLineItems`, `removeCartLineItems`, `updateCartLineItems`, `clearCart`), all redirecting to `/cart`. * **FIXED** (Compass) Search-result product names in the ChatGPT app now render matched terms in bold instead of showing literal `` markup. The widget escapes every other HTML tag the search backend might emit, so only the `` highlight is rendered as styled output. ### Migration guide [#migration-guide] #### Moving the feature editor to `@alokai/connect-admin` [#moving-the-feature-editor-to-alokaiconnect-admin] The feature editor only ever shipped in Compass `-next` releases, so there is nothing to migrate from a stable version. If you are on a `-next` release and using it, install `@alokai/connect-admin` (see the entry above) and follow the Connect Admin documentation for registering the integration and reading values from the SDK. Three things to be aware of beyond the package move: * **The authoring API is renamed.** What Compass called an *editor* holding *features* is now a **feature** holding **views**: `defineFeatureEditor` becomes `defineFeature`, registered through the integration's `configuration.features` instead of the `featureEditors` middleware config field. * **Env vars.** `COMPASS_FEATURE_EDITOR` becomes `CONNECT_ADMIN_FEATURE_EDITOR`, `ALOKAI_COMPASS_MOCK_REDIS` becomes `CONNECT_ADMIN_MOCK_REDIS`, and the Redis key prefix can now be set with `CONNECT_ADMIN_REDIS_PREFIX`. * **Saved versions do not migrate.** Version history lives in Redis under a new key prefix (`connect-admin:` instead of `compass:`). After the upgrade each feature starts again from the defaults in your code, and anything authored through the old UI is no longer read. Export what you want to keep first (header menu → Download), then upload it again on the new version. #### Windows-compatible package scripts [#windows-compatible-package-scripts] If your project overrides any of the storefront `build`, `dev`, or test scripts in `package.json`, update them to use `cross-env` for inline environment variables, for example: ```json // Before "multistore:dev": "NODE_TLS_REJECT_UNAUTHORIZED=0 NEXT_PUBLIC_ALOKAI_MULTISTORE_ENABLED=true yarn dev" // After "multistore:dev": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 NEXT_PUBLIC_ALOKAI_MULTISTORE_ENABLED=true yarn dev" ``` Add `cross-env` as a dev dependency if it is not already present. ## 2.3.6 [#236] **Release date:** 2026-07-13 ### Patch Changes [#patch-changes-1] * **CHANGED** The logger now skips empty/whitespace-only string messages (`logger.info("")`, `logger.error(" ")`) instead of emitting a meaningless `{"message":""}` entry. Applies to every consumer (middleware, storefront, SDK). Log an actual message or pass data as the log argument/metadata to record something. * **CHANGED** The GCP structured logger now serializes an error's full `cause` chain for ANY error that has one - previously only `AppError` subclasses did. So an SSR `SDKError: fetch failed` whose real reason is a nested `SocketError`/`ECONNRESET` is now logged with that reason (under `cause`) instead of just the top-level message. The serialization is unchanged (circular-safe via `serializeErrorForLog`, then secret-redacted and depth/size-bounded via `sanitizeLogMetadata`); this only widens which errors it applies to. Affects every consumer that logs a plain `Error` with a `cause` (middleware and storefront). * **ADDED** `createStorefrontLogger(options?)` and `withStorefrontScope(logger, scope)` to `@alokai/connect/logger`. `createStorefrontLogger` builds the standard GCP-structured logger tagged `alokai.context: "storefront"` (previously duplicated in `@vue-storefront/next` and `@vue-storefront/nuxt`, now shared). `withStorefrontScope` wraps such a logger so every entry carries per-log detail under `alokai.scope` - and only `scope`, so callers cannot override the protected `alokai.context`. The underlying metadata injector stays internal: exposing it would hand consumers an unguarded way to overwrite the reserved `alokai` namespace. * **ADDED** `installConsoleBridge(logger, options?)` to `@alokai/connect/logger`: an opt-in helper that routes the runtime's raw `console.error`/`console.warn` output through the Alokai logger, so framework SSR errors and third-party console output are emitted as single structured (GCP JSON in production) entries instead of multi-line dumps that log collectors cannot parse. Renders nested Errors with their stack, strips ANSI color codes, keeps non-error arguments as `details` metadata, drops empty/whitespace-only output (blank spacing lines) on every patched console method, guards against reporter recursion, passes already-structured logger lines straight through, and falls back to the native console on failure. Kept free of Node built-ins so the logger stays browser-safe. Options: `metadata` (merged into every entry); returns a handle with `uninstall()`. * **ADDED** `@vue-storefront/next/instrumentation` export with a ready-to-use `register` hook. Wire it up from your app's root `instrumentation.ts` (`export { register } from "@vue-storefront/next/instrumentation";`) to re-emit Next.js' raw, multi-line `console.error`/`warn` dumps - which log collectors (GCP, Datadog, Elasticsearch) cannot parse - as single structured GCP JSON entries matching the middleware log format. `register` installs a console→logger bridge that normalizes every server `console.error`/`warn` (rendering Errors with their stack) and drops empty spacing lines. Active only in production Node runtime; local dev output is unchanged. * **ADDED** The storefront logger now emits a one-time warning in a production Node server when `instrumentation.ts` did not wire the Alokai `register` hook, so a missing setup is surfaced instead of silently skipping SSR log normalization. * **ADDED** A Nitro server plugin that routes Nitro's raw server console output - including unhandled SSR errors - through the Alokai logger, so the multi-line text Nitro prints by default (which log collectors like GCP, Datadog, Elasticsearch cannot parse) is re-emitted as single structured GCP JSON entries matching the middleware log format. Installs a console→logger bridge that normalizes every server `console.error`/`warn` (rendering Errors with their stack) and drops empty spacing lines. Registered automatically by the module; active only in production builds, so local dev output is unchanged. * **CHANGED** The default logger option `includeStackTrace` is now `true` (was `false`), aligning Nuxt with the middleware and Next.js defaults so 5xx/unexpected errors carry a stack trace out of the box. Set `alokai.logger.includeStackTrace: false` in `nuxt.config` to opt out. Traces are still never attached to 4xx client errors. * **ADDED** `store build` now guarantees each composed Next.js app wires the Alokai instrumentation - automatically, without failing the build. It parses the composed `instrumentation.ts` (AST, not string matching) and, when the file does not already export `register`, appends `export { register } from "@vue-storefront/next/instrumentation";` as the last statement (so any side-effect imports still run first) with a "do not remove" comment; when there is no instrumentation file, it creates one. This runs on the composed `.out` output only - your project's source is left untouched - so removing the wiring from source cannot silently disable SSR/RSC log normalization. A file whose `register` references `@vue-storefront/next/instrumentation` (our re-export, an `export *`, or a wrapper that imports it) is left exactly as-is, so custom instrumentation is never clobbered and the step is idempotent. A file that exports a custom `register` with NO reference to our module cannot be wired (our hook can't run without being imported), so it overrides Alokai's - the build **fails** with a fix hint. Whether a `register` that does reference our module actually calls it can't be proven statically without false positives, so that residual case is enforced at runtime instead (`@vue-storefront/next` throws on server start if the hook never ran). * **FIXED** The generated Deployment workflow now reads `CONSOLE_API_URL` from the `CONSOLE_API_URL` repository variable (`vars.CONSOLE_API_URL`), so you can configure the Console API URL as a non-secret variable. ## 2.3.5 [#235] **Release date:** 2026-07-09 ### Patch Changes [#patch-changes-2] * **FIXED** Next.js standalone Docker images no longer crash with `Cannot find module 'react-dom/server.browser'` on npm/pnpm projects. `react-dom` is now kept as an explicit production dependency of the deployed app so it survives the production install step. ## 2.3.4 [#234] **Release date:** 2026-07-07 ### Patch Changes [#patch-changes-3] * **FIXED** Middleware error responses (404/405 and endpoint errors) are now sent as `text/plain` with `X-Content-Type-Options: nosniff` instead of `text/html`, so request values reflected in an error body can no longer be rendered as HTML in the browser (reflected HTML injection). > **Note:** The response body and status codes are unchanged - only the `Content-Type` header changes (`text/html` → `text/plain`) and `X-Content-Type-Options: nosniff` is added. This is non-breaking for clients that read the response body or status. The only case to check is code that branches on the literal `text/html` content-type of these error responses. ## 2.3.3 [#233] **Release date:** 2026-07-06 ### Patch Changes [#patch-changes-4] * **FIXED** Generated projects no longer bundle unused platform integration packages (`@vsf-enterprise/algolia-api`, `@vsf-enterprise/magento-types`) in `storefront-middleware`'s dependencies. ## 2.3.2 [#232] **Release date:** 2026-07-02 ### Patch Changes [#patch-changes-5] * **FIXED** `store deploy` no longer ignores the `projectName`, `framework`, and `cloudRegion` values from `alokai.config.json` when the `CLI_PROJECT_NAME`, `CLI_FRAMEWORK`, or `CLI_CLOUD_REGION` environment variable is set to an empty string - which happens in the generated GitHub Actions workflow when the corresponding repository variable is not defined. An empty environment variable is now treated as unset. ## 2.3.1 [#231] **Release date:** 2026-07-02 ### Patch Changes [#patch-changes-6] * **FIXED** Circuit-breaker-blocked requests no longer crash the middleware error handler and no longer leak the upstream `Authorization` header into logs. * Requests rejected by an open circuit breaker previously threw `TypeError: Cannot read properties of undefined (reading 'errorBoundary')` while handling the error, masking the original failure. The blocked request now returns its proper error response. * Serialized error causes written to logs now redact secret-named fields (e.g. the raw request `_header` and `Authorization`/`Cookie` headers on axios-style errors), matching the redaction already applied to log metadata. ## 2.3.0 [#230] **Release date:** 2026-07-01 ### Minor Changes [#minor-changes-1] * **ADDED** New `@alokai/ai-toolkit` package that makes coding agents (Claude Code, Cursor, Codex, Gemini CLI, GitHub Copilot) meaningfully more effective in an Alokai codebase. It gives your agent framework-aware context so generated code follows Alokai conventions, agent-driven review workflows to run before opening a PR (for example, catching common performance regressions in a Next.js diff), and Alokai reference docs it can consult on demand. Customer projects pick it up via a new `alokai ai sync` command in `@alokai/cli`, which keeps the toolkit and your project's `AGENTS.md` in sync as the package evolves. The generated Next.js storefront also follows the [Next.js AI agents guidance](https://nextjs.org/docs/app/guides/ai-agents), so agents pick up framework-level context alongside the Alokai skills. See the migration guide below for adopting it in an existing project. * **ADDED** `integration generate` in `@alokai/cli` now accepts an `--answers` flag taking a JSON object of the template's prompt answers (keyed by prompt name), so the command can run non-interactively. Interactive prompts are skipped and the integration is generated directly from the supplied answers. Enables scripting and automated testing of integration generation. * **ADDED** `integration generate` in `@alokai/cli` now accepts a `--skip-version-check` flag that lets generation proceed even when the project's Alokai ecosystem version is not in the compatibility matrix (the version-mismatch warning is still printed instead of aborting). * **ADDED** New Alokai Image Optimizer for both Next.js (`@vue-storefront/next`) and Nuxt (`@vue-storefront/nuxt`) storefronts. It rewrites image URLs matching a configured media host to a `/img-proxy/{key}/...?width=&quality=&format=auto` route so the optimizer CDN can transform them, and the server route proxies the bytes back from the origin. On Nuxt, set `alokai.imageOptimizer.hosts` in your Nuxt config to register an `@nuxt/image` provider plus a `/img-proxy/:host/**:path` server route (mirroring the Next.js `createImageOptimizer` API); the `default` and `sapcc` URL variants and per-host `cacheControl` are supported, and the media host for each key is overridable per deployment via `NUXT_PUBLIC_{KEY}_MEDIA_HOST` (leaving it empty passes image URLs through untouched). Toggle the optimizer at runtime with `NEXT_PUBLIC_IMAGE_OPTIMIZER_ENABLED=true` (Next.js) or `NUXT_PUBLIC_IMAGE_OPTIMIZER_ENABLED=true` (Nuxt); when unset or set to any other value, image URLs are passed through unchanged and the optimizer route returns 404. ```ts // nuxt.config.ts - @vue-storefront/nuxt must precede @nuxt/image in `modules` export default defineNuxtConfig({ alokai: { imageOptimizer: { hosts: { commerce: {}, // reads NUXT_PUBLIC_COMMERCE_MEDIA_HOST, `default` variant }, }, }, }); ``` * **ADDED** Multi-instance bootstrap for Config Switcher in `@alokai/connect`. Each configured store now gets its own isolated `init()` and `extendApp()` at startup with correctly merged configuration, so services initialized during startup (such as authentication token services) are correctly configured per store. * **ADDED** Opt-in retry of transient failures for integration API methods in `@alokai/connect`. When enabled, calls that fail with a transient transport error (`502`/`503`/`504`/`408`/`429` and normalized network failures such as `ETIMEDOUT`/`ECONNRESET`) are automatically retried before failing. Off by default; enable per integration via the new `retry` config: ```typescript // middleware.config.ts export const config = { integrations: { commerce: { location: "@vsf-enterprise/sapcc-api/server", configuration: {/* ... */}, retry: true, // default policy: 2 retries, randomized exponential backoff // or a custom policy: // retry: { retries: 3, retryCondition, retryDelay }, }, }, }; ``` * **ADDED** `createStorefrontEvents` factory, exported from `@vue-storefront/next/client` - a typed, client-side pub/sub for storefront domain events. Declare your app's event map once and use the bound `emitStorefrontEvent` / `subscribeStorefrontEvent` / `useStorefrontEvent` / `StorefrontEventEmitter` helpers, so modules (analytics, personalization, search) can emit and subscribe without the core knowing who listens. `useStorefrontEvent` reads the handler through a ref so inline handlers do not re-subscribe every render; `StorefrontEventEmitter` emits once per mount (Strict-Mode-safe) for server-rendered pages. * **ADDED** `getCurrentPath` helper, exported from `@vue-storefront/next/server` - returns the current request path (pathname + search) inside an App-Router Server Component, reading the headers set by `createAlokaiMiddleware`. It lives in a dedicated `server` entry because it imports `next/headers`, which is unavailable in the client / Pages Router bundles that also import the package. * **ADDED** (SAPCC only) Added support for SAP Customer Data Cloud. * **ADDED** (Compass only) `retryFailedToolCalls` action config option that routes failed tool calls back to the LLM for retry, even when `shouldReactToToolsResponses` is disabled. * **ADDED** (Compass only) `outputSchema` in structured-output actions now accepts a dynamic schema definition `{ schema, cache? }`, mirroring the `schema` + `cache` shape already used by tools. The schema is resolved per invocation with access to the request `context` and the workflow payload, and - when a `cache.key` is provided - goes through the same Redis-backed caching pipeline as dynamic tool schemas. Static `z.ZodType` schemas keep working unchanged. ```ts // Before - static schema only const action: StructuredOutputActionConfig = { allowStreaming: false, model: "medium", outputSchema: REVIEW_SCHEMA, type: "llm", }; // Now - dynamic resolver with optional caching const action: StructuredOutputActionConfig = { allowStreaming: false, model: "medium", outputSchema: { schema: async (context, { workflowPayload }) => { const tier = await resolveUserTier(context); return tier === "premium" ? PREMIUM_REVIEW_SCHEMA : BASIC_REVIEW_SCHEMA; }, cache: { key: async (context) => `review-schema:${context.store.id}`, }, }, type: "llm", }; ``` * **ADDED** (Compass only) New `ALOKAI_COMPASS_NO_CREDENTIALS_MANAGER` environment variable that disables the Alokai-hosted credentials manager. When set, Compass reads `ALOKAI_COMPASS_API_KEY` and `ALOKAI_COMPASS_API_URL` directly from the environment, allowing Compass to be pointed to the Alokai AI service. When the flag is set without `ALOKAI_COMPASS_API_URL`, the server fails fast at startup with a clear error. Installing the Compass module via `storefront-cli add-module compass` now also seeds `.env.example` with a commented `ALOKAI_COMPASS_API_URL=https://llm-gateway.alokai.dev` line as a discoverable default. * **CHANGED** (Compass only) Tool return values now expose an `instructions` property that yields a system message for the LLM on how to interpret the tool-call result. * **REMOVED** (Compass only) Removed the custom `previewProducts` tool. * **ADDED** (SmartEdit only) Header and footer are now consistently rendered on all CMS-managed pages. The `connectCmsPage` helper wraps each page with the default layout (navbar, main content area, and footer), ensuring consistent appearance whether a page has CMS content or falls back to the storefront default. See the migration guide below for the required layout changes in existing SAP storefronts. ### Patch Changes [#patch-changes-7] * **FIXED** Integrations generated by `@alokai/cli` from the `openapi` and `graphql` templates now build against the current Alokai version. Previously a freshly generated `openapi` or `graphql` integration failed to compile and needed manual fixes before it could be used. The `openapi` template's `fetch` HTTP-client option now also builds out of the box, with no manual setup required. * **CHANGED** Improved integration boilerplate templates in `@alokai/cli`. The **graphql** template now reads the integration's `baseUrl` from the `_BASE_URL` environment variable instead of a hardcoded placeholder URL, so you configure the endpoint through your environment. The **sdk-proxy** template now ships a working example endpoint (`getSample`, returning sample data) out of the box instead of a non-functional placeholder, giving you a runnable starting point to adapt to your own SDK. * **FIXED** `@alokai/cli` version check no longer crashes when the Alokai version API is temporarily unavailable - a warning is shown and the check is skipped gracefully. * **FIXED** Bump `actions/setup-node`, `actions/checkout`, `actions/download-artifact` to v5 to avoid Node 20 deprecation warnings. * **FIXED** `integrationConfigSchema` in `@alokai/connect` accepts any object instead of only `{}`. The previous schema rejected the config the config-switcher injects, breaking middleware bootstrap. * **FIXED** GCP structured logging in `@alokai/connect` now surfaces the full error `cause` chain and `AppError` subclass details. The per-request error log serializes the underlying `cause` - previously it took the cause from `AppError.toJSON()`, which flattens it to `name`/`message`, hiding the real reason of a transport failure (the network error carried as `cause` - `ECONNRESET`, `ETIMEDOUT`, the upstream status/response body). Logs also now include the `data` and `cause` fields from `AppError` subclasses (e.g. `ValidationError`, `HttpError`), so normalizer failures and other diagnostics surface without the logger needing to know about specific subclasses. Secret redaction, circular-reference safety, and size bounds are preserved. `AppError.toJSON()`, which the error handler returns to API clients, is intentionally left untouched, so nothing extra is exposed to clients. * **FIXED** Correctly infer type for custom fields of `SfOrderListItem` in `@alokai/connect`. * **FIXED** `cart-page-providers.tsx` is now correctly installed to `cart/components/` instead of `my-account/my-orders/[id]/components/`. * **FIXED** `env('NEXT_PUBLIC_*')` from `@vue-storefront/next` now returns the correct value on the client during the first render and inside initial `useEffect` calls. Previously, runtime env vars were `undefined` until shortly after hydration, which could break integrations that read them eagerly - for example, the SAP CDC module's `getCdcConfig()` returned no API key on first render and failed to load the Gigya SDK. * **FIXED** `AlokaiInstrumentation` now reliably captures the initial page view and any navigation that happens during page load. Previously, the history-trace script started running after hydration, so the very first page view and any router navigation triggered before that point were not reported. * **FIXED** Multiple bugs in the re-order module. `wantedQuantities` on the product card is now correctly keyed by SKU instead of cart line item ID. Items not found in the updated cart after the add-line-items API call are now reported as errors instead of successes. `use-re-order-products` guards against undefined `lineItems` crashing on `.forEach` and surfaces unhandled `mutateAsync` rejections as error notifications. The local-storage hook now correctly resets state to `initialValue` when the item is removed (`newValue === null`) or storage is cleared (`changedKey === null`), fixing a stale closure that prevented clearing from taking effect. * **ADDED** Ability to add a suffix to hardcoded store IDs from the `generate-gtm` action. Generated workflows were also updated to use `environment: ${{ matrix.store_id }}` so that different store IDs can have different GitHub environments (and env vars/secrets) associated with them. * **CHANGED** Updated `@storefront-ui/react` to 4.0.1, `@storefront-ui/vue` to 3.1.2, and `@storefront-ui/nuxt` to 3.3.1. * **CHANGED** Aligned axios to `^1.15.2`. * **CHANGED** Bumped pinned dependency versions (defu, glob, h3, lodash-es, minimatch, path-to-regexp, rollup, diff, uuid) to patched releases within the same major to address known security vulnerabilities. No public API or runtime behavior change. * **CHANGED** Node engines tightened to `^20.10.0 || >=22.14.0` to match the runtime support range for JSON ESM imports with `with { type: "json" }`. * **FIXED** (SAPCC only) Improved facet value matching to handle prefixed values (e.g. `color-black`, `size-10`) and prefer `superZoom` image format for gallery and primary images. The facet normalizer now resolves prefixed facet values by trying an exact match first and then a suffix match; the product images normalizer prefers the `superZoom` format over `zoom` for highest quality; and the `getOptions` helper falls back to `variantOptions` when `baseOptions` is empty. * **ADDED** (Compass only) New `appendToCompactHistory` SDK utility in `@alokai/compass` for appending entries to the compact history in localStorage. * **FIXED** (Compass only) Chat history no longer disappears on page reload when the assistant is using compact history. The `useWorkflow` hook now passes the prior conversation to the SDK as `messageHistory`, ensuring the full chat is persisted to localStorage across turns. * **FIXED** (Compass only) Context messages in compact history are now stringified before being persisted, ensuring the assistant can recall prior search context (e.g. "green beanie") across conversation turns. * **FIXED** (Compass only) `CompassProvider` no longer overrides the root translation provider. Previously, wrapping the app with `CompassProvider` blocked access to all translation namespaces except `AddToCartButton` and `Compass`, causing missing translation errors for components like `NavCartButton` and `AuthButton`. * **FIXED** (Compass only) Cart page loading spinner no longer gets stuck. Previously, the Compass assistant's `useFrontendActions` hook subscribed to cart query state, causing a render loop that prevented `isLoading` from resolving to `false`. * **FIXED** (Compass only) Lazy-load pako compression library to avoid bundling it on the client when compression is not used. * **FIXED** (Compass only) Bumped `@frsource/autoresize-textarea` to `^2.0.196` in the Compass module's Next.js dependencies. Versions `2.0.192`-`2.0.195` stopped shipping the `dist/index.d.ts` declaration file, causing `tsc --noEmit` to fail with TS7016 when generating the SAPCC store with the Compass module added. The upstream author republished the declarations in `2.0.196`. * **CHANGED** (Compass only) `ProductMessage` now embeds only `{ name, sku }` in the product-visit context messages sent to the assistant, instead of the full `SfProduct` object. This significantly reduces the prompt size (and token cost) on every product page view without losing enough identity for the assistant to follow up or tool-call for more detail. * **CHANGED** (Compass only) Adjusted model naming to the new convention. Each action config now carries a `model` (the dated codename forwarded to the proxy in no-credentials mode) and a `legacyModel` (the concrete model resolved in credentials-manager mode). The default Compass module config sets both for every workflow action so it behaves correctly in both modes. * **CHANGED** (Compass only) The `model` option on `defineAction` is now typed as `string` (was the literal union `"heavy" | "light" | "medium"`), so the IDE no longer suggests a hardcoded set of names that drifts away from what the gateway actually exposes. The TSDoc on the field links to the new [Available Models](https://docs.alokai.com/unified/modules/sap/compass/available-models) docs page where the live, curated catalog is browsable. * **FIXED** (Contentstack only) `LivePreview` typed its `onLiveEdit` callback parameter as required, which failed to type-check against the published contentstack SDK signature (`() => void`) and left the parameter as an implicit `any`. Marking `livePreviewUrl` optional (`livePreviewUrl?: string`) makes the handler assignable to both signatures. * **FIXED** (Coveo only) The Coveo proxy forwards only whitelisted headers (the auth token plus JSON content headers) and rewrites the host, instead of spreading every incoming header. Forwarding the incoming request's `content-length` / `transfer-encoding` described the original body - not the re-serialized payload axios sends upstream - which hung the request and eventually OOM-ed the middleware. * **FIXED** (SmartEdit only) Restored full heading hierarchy (h1-h6), responsive typography, and list styles in the SmartEdit paragraph component. ### Migration guide [#migration-guide-1] #### Adopting `@alokai/ai-toolkit` in an existing project [#adopting-alokaiai-toolkit-in-an-existing-project] New projects generated by the Alokai CLI already include everything below. For projects generated before this release: 1. Run `alokai ai sync`. When prompted: * confirm the install - the CLI will add `@alokai/ai-toolkit` to `devDependencies` at the version pinned for your ecosystem release; * confirm the postinstall wiring - the CLI will add (or append) `alokai ai sync` to `scripts.postinstall` so symlinks and the managed `AGENTS.md` block are refreshed on every install. For non-interactive runs (e.g. CI), pass `--yes`: ```sh yarn alokai ai sync --yes ``` 2. (Optional) Pin the agent targets explicitly in your root `alokai.config.json`. Without this, the CLI auto-detects installed agents from the project. The forced `agents` list ensures symlinks land in standard paths even on machines (or CI runners) where the agent home directory is not yet present: ```json { "$schema": "node_modules/@alokai/cli/lib/static/alokaiConfigSchema.json", "aiToolkit": { "agents": [ "claude-code", "codex", "cursor", "gemini-cli", "github-copilot" ] }, "stores": {} } ``` After step 1, your agents (Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot) will see the Alokai skills and the managed AGENTS.md guidance on next startup. #### Header and footer on CMS pages (`connectCmsPage`) — SAP storefront [#header-and-footer-on-cms-pages-connectcmspage--sap-storefront] **1. Wrap storefront pages with `connectCmsPage`** Each page that should be enrichable with CMS content must be wrapped with `connectCmsPage`. The helper accepts the page component and an options object with a `getCmsPagePath` function that returns the CMS page path for the given page props. Apply the following changes to each page where you want to display CMS content: **Example — page without shared sub-layout (`app/[locale]/(default)/cart/page.tsx`)** ```tsx import { connectCmsPage } from "@/components/cms/wrappers"; export default connectCmsPage( function CartPage() { // ... existing page content }, { getCmsPagePath: () => "/cart" }, ); ``` **Example — page using `MyAccountBaseLayout` (`app/[locale]/(default)/my-account/(navigation-sidepanel)/my-orders/page.tsx`)** My-account pages share a navigation sidepanel. Wrap the existing page content in the new `MyAccountBaseLayout` component *inside* the `connectCmsPage` call: ```tsx import MyAccountBaseLayout from "@/app/[locale]/(default)/my-account/(navigation-sidepanel)/components/my-account-base-layout"; import { connectCmsPage } from "@/components/cms/wrappers"; export default connectCmsPage( function MyOrdersPage() { return ( {/* ... existing page content */} ); }, { getCmsPagePath: () => "/my-account/orders" }, ); ``` Apply the same pattern to all other my-account sub-pages with the appropriate `getCmsPagePath` value: * `my-account/(navigation-sidepanel)/page.tsx` → `/my-account` * `my-account/(navigation-sidepanel)/personal-data/page.tsx` → `/my-account/personal-data` * `my-account/(navigation-sidepanel)/returns/page.tsx` → `/my-account/returns` * `my-account/(navigation-sidepanel)/shipping-details/page.tsx` → `/my-account/shipping-details` * `my-account/my-orders/[id]/page.tsx` → dynamic: `` `/my-account/orders/${id}` `` **2. Extract `MyAccountBaseLayout` component** Create a new `app/[locale]/(default)/my-account/(navigation-sidepanel)/components/my-account-base-layout.tsx` file that consolidates the shared my-account navigation sidepanel layout (heading, navigation sidebar, and children slot). This component is used inside each my-account page wrapped with `connectCmsPage` above. **3. (SAP storefront) Update `app/[locale]/(default)/layout.tsx`** The `(default)/layout.tsx` must be replaced with the version provided by the `cms-smartedit` module (installed automatically when running `yarn sf-modules install cms-smartedit`). The key structural change is that **Navbar and Footer are removed from the root layout** and are instead rendered per-page by `connectCmsPage`. This prevents double-rendering since `connectCmsPage` now always wraps pages with `BaseDefaultLayoutWithNavbarAndFooter`. The new layout exports three components: * `DefaultLayout` (default export) — thin wrapper that delegates to `BaseDefaultLayout` * `BaseDefaultLayout` — renders shared UI: BottomNav, ScrollToTop, UserSettingsModal * `BaseDefaultLayoutWithNavbarAndFooter` — renders Navbar + children + Footer; used internally by `connectCmsPage` ```tsx // Before export async function BaseDefaultLayout({ children }) { return ( <> {children}