@fiodos/cli 0.1.31 → 0.1.32

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiodos/cli",
3
- "version": "0.1.31",
3
+ "version": "0.1.32",
4
4
  "description": "Fiodos CLI — analyzes your app's source code and generates the in-app voice-agent manifest, then wires the orb. Powers `npx @fiodos/cli analyze`.",
5
5
  "type": "commonjs",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -102,6 +102,7 @@ const {
102
102
  const { wireReactNativeOrb, reportReactNativeWire, connectRnSession } = require('./wireReactNative');
103
103
  const {
104
104
  isShopifyThemeRoot, fetchStorefrontSnapshot, wireShopifyTheme, reportShopifyWire,
105
+ normalizeStoreDomain,
105
106
  } = require('./shopifyTheme');
106
107
  const { wireFlutterOrb, writeFlutterEnv, reportFlutterWire } = require('./wireFlutter');
107
108
  const { wireHandlers, reportHandlerResult } = require('./wireHandlers');
@@ -404,13 +405,22 @@ async function main() {
404
405
  // so the analysis personalizes routes/bubbles/examples to the REAL catalog
405
406
  // — and so evidence verification has concrete files to point at. Fail-open:
406
407
  // an unreachable store still gets the universal surface file.
408
+ // Hoisted out of the `if` so it also reaches analysisMeta below: persisting
409
+ // the store domain in the published meta (not just using it locally for the
410
+ // snapshot) is what lets the DASHBOARD reconstruct the exact `--platform
411
+ // shopify --store <domain>` re-analysis command from the BACKEND record —
412
+ // no dependency on this browser's localStorage remembering how the project
413
+ // was first set up. Without it, a project analyzed before this field existed
414
+ // (or from a different browser/machine) shows the generic web command,
415
+ // silently missing the flags a Shopify re-analysis needs.
416
+ let shopifyStoreDomain = '';
407
417
  if (platform === 'shopify') {
408
- const storeDomain = arg('--store', process.env.FYODOS_SHOPIFY_STORE || '');
409
- if (!storeDomain) {
418
+ shopifyStoreDomain = normalizeStoreDomain(arg('--store', process.env.FYODOS_SHOPIFY_STORE || ''));
419
+ if (!shopifyStoreDomain) {
410
420
  logUser('Tip: add --store your-store.com so the analysis reads your live catalog (collections & products).');
411
421
  }
412
422
  const snapshot = await withSpinner('Reading your store\u2019s public catalog', () =>
413
- fetchStorefrontSnapshot(storeDomain, { log: logDev }),
423
+ fetchStorefrontSnapshot(shopifyStoreDomain, { log: logDev }),
414
424
  );
415
425
  included.push(...snapshot.files);
416
426
  }
@@ -466,6 +476,13 @@ async function main() {
466
476
  ({ manifest, provenance } = routesOnlyManifest(appMeta, routes));
467
477
  logDev('[no-llm] static-only manifest (routes only, no actions)');
468
478
  logUser('Static analysis complete');
479
+ // Still record platform (+ store, when given) so the dashboard's
480
+ // re-analysis command stays correct even for a free/no-key smoke pass.
481
+ analysisMeta = {
482
+ ...analysisMeta,
483
+ platform,
484
+ ...(platform === 'shopify' && shopifyStoreDomain ? { store: shopifyStoreDomain } : {}),
485
+ };
469
486
  } else {
470
487
  // Hybrid AI-key model. DEFAULT: hosted analysis via the Fiodos backend
471
488
  // proxy (Fiodos's AI key, no key needed by the developer). With
@@ -552,6 +569,7 @@ async function main() {
552
569
  costUSD: Number(costUSD.toFixed(4)),
553
570
  droppedActions,
554
571
  droppedRoutes,
572
+ ...(platform === 'shopify' && shopifyStoreDomain ? { store: shopifyStoreDomain } : {}),
555
573
  };
556
574
  }
557
575
 
@@ -194,11 +194,41 @@ async function fetchStorefrontSnapshot(storeRaw, { log = () => {} } = {}) {
194
194
  return { files, store, collections, products, warnings };
195
195
  }
196
196
 
197
+ /**
198
+ * The Liquid-rendered SCREEN CONTEXT lines shared by the CLI and dashboard
199
+ * snippets. One branch per storefront template the agent can act on, each
200
+ * exposing the visible items WITH their add-to-cart variantIds.
201
+ *
202
+ * Why every branch matters: with product-only context (the original version)
203
+ * the agent was BLIND on collection/search/cart pages — "add it to the cart"
204
+ * said next to a perfectly visible product degenerated into a text search
205
+ * with the user's phrasing, zero results, and an apology. The agent must be
206
+ * able to act on whatever the customer is LOOKING AT, on every page type.
207
+ */
208
+ function shopifyScreenContextLiquidLines() {
209
+ return [
210
+ " {% if template contains 'product' and product %}",
211
+ ' {% capture fyodos_screen_text %}The customer is viewing the product page of: {{ product.title }} (price {{ product.price | money | strip_html }}). Add-to-cart variantId: {{ product.selected_or_first_available_variant.id }}.{% endcapture %}',
212
+ " window.__fyodosScreen = { kind: 'product', text: {{ fyodos_screen_text | json }} };",
213
+ " {% elsif template contains 'collection' and collection %}",
214
+ ' {% capture fyodos_screen_text %}The customer is browsing the collection "{{ collection.title }}". Products visible on screen (title — price — add-to-cart variantId): {% for fyodos_p in collection.products limit: 16 %}{{ fyodos_p.title }} — {{ fyodos_p.price | money | strip_html }} — variantId {{ fyodos_p.selected_or_first_available_variant.id }}; {% endfor %}To add one to the cart, call add_to_cart with its variantId from this list.{% endcapture %}',
215
+ " window.__fyodosScreen = { kind: 'collection', text: {{ fyodos_screen_text | json }} };",
216
+ " {% elsif template contains 'search' and search.performed %}",
217
+ ' {% capture fyodos_screen_text %}The customer is viewing search results for "{{ search.terms }}". Products visible on screen (title — price — add-to-cart variantId): {% for fyodos_r in search.results limit: 12 %}{% if fyodos_r.object_type == \'product\' %}{{ fyodos_r.title }} — {{ fyodos_r.price | money | strip_html }} — variantId {{ fyodos_r.selected_or_first_available_variant.id }}; {% endif %}{% endfor %}To add one to the cart, call add_to_cart with its variantId from this list.{% endcapture %}',
218
+ " window.__fyodosScreen = { kind: 'search', text: {{ fyodos_screen_text | json }} };",
219
+ " {% elsif template contains 'cart' %}",
220
+ ' {% capture fyodos_screen_text %}The customer is viewing their cart: {{ cart.item_count }} item(s), total {{ cart.total_price | money | strip_html }}. Lines (title × quantity — variantId): {% for fyodos_i in cart.items %}{{ fyodos_i.product.title }} × {{ fyodos_i.quantity }} — variantId {{ fyodos_i.variant_id }}; {% endfor %}Use update_cart_item with a variantId from this list to change quantities.{% endcapture %}',
221
+ " window.__fyodosScreen = { kind: 'cart', text: {{ fyodos_screen_text | json }} };",
222
+ ' {% endif %}',
223
+ ];
224
+ }
225
+
197
226
  /**
198
227
  * The theme.liquid block: loads the embed, fetches the published manifest and
199
228
  * mounts the orb with API-wired registries. Mirrors the dashboard's
200
- * buildShopifySnippet, plus a Liquid-rendered PRODUCT screen context so the
201
- * agent knows the visible variant id (what add_to_cart needs by voice).
229
+ * buildShopifySnippet, plus a Liquid-rendered screen context (product,
230
+ * collection, search and cart pages) so the agent knows the visible items and
231
+ * their variant ids (what add_to_cart / update_cart_item need by voice).
202
232
  */
203
233
  function buildShopifySnippet({ apiKey, apiUrl }) {
204
234
  const key = apiKey || '<your-api-key>';
@@ -207,10 +237,7 @@ function buildShopifySnippet({ apiKey, apiUrl }) {
207
237
  ORB_START,
208
238
  `<script src="${FIODOS_EMBED_CDN_URL}" defer></script>`,
209
239
  '<script>',
210
- " {% if template contains 'product' and product %}",
211
- ' {% capture fyodos_screen_text %}The customer is viewing the product page of: {{ product.title }} (price {{ product.price | money | strip_html }}). Add-to-cart variantId: {{ product.selected_or_first_available_variant.id }}.{% endcapture %}',
212
- " window.__fyodosScreen = { kind: 'product', text: {{ fyodos_screen_text | json }} };",
213
- ' {% endif %}',
240
+ ...shopifyScreenContextLiquidLines(),
214
241
  " window.addEventListener('DOMContentLoaded', function () {",
215
242
  ` var FYODOS_API_KEY = '${key}';`,
216
243
  ` var FYODOS_API_URL = '${url}';`,
@@ -330,6 +357,7 @@ module.exports = {
330
357
  isShopifyThemeRoot,
331
358
  readThemeMeta,
332
359
  fetchStorefrontSnapshot,
360
+ shopifyScreenContextLiquidLines,
333
361
  buildShopifySnippet,
334
362
  wireShopifyTheme,
335
363
  reportShopifyWire,