@reactionary/feeds 0.10.42 → 0.10.44
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/README.md +75 -1
- package/cli.cjs +56144 -55959
- package/cli.js +33 -0
- package/index.js +1 -0
- package/lib/acp-feed-publisher.js +141 -0
- package/lib/default-registry.js +2 -1
- package/lib/transformers/acp-product-feed.transformer.js +100 -88
- package/package.json +9 -9
- package/src/index.d.ts +1 -0
- package/src/lib/acp-feed-publisher.d.ts +73 -0
- package/src/lib/feed-types.d.ts +5 -0
- package/src/lib/transformers/acp-product-feed.transformer.d.ts +77 -0
package/README.md
CHANGED
|
@@ -13,7 +13,8 @@ The package keeps feed generation separate from protocol adapters. A host can pr
|
|
|
13
13
|
|
|
14
14
|
The default registry includes:
|
|
15
15
|
|
|
16
|
-
- `acp-product-feed` — ACP
|
|
16
|
+
- `acp-product-feed` — ACP Feed API (2026-04-17) `Product` records: `products.jsonl` for file ingestion by default (one product with its variants per line), or with `format: 'json'` the `{ "products": [...] }` body of `PATCH /feeds/{id}/products`. Prices are integer minor units with upper-case currency codes. `toACPFeedMetadata(feedId, feed)` builds the matching `metadata.json`.
|
|
17
|
+
- `acp-feed-metadata` — the ACP feed's `metadata.json` (`id`, `target_country`, `updated_at`) for file ingestion next to `products.jsonl`.
|
|
17
18
|
- `google-merchant-feed` — Google Merchant RSS XML.
|
|
18
19
|
- `sitemap-feed` — sitemap XML of product URLs.
|
|
19
20
|
- `pricerunner-feed` — PriceRunner-style product XML.
|
|
@@ -243,6 +244,7 @@ reactionary-feeds generate \
|
|
|
243
244
|
--feed finnish \
|
|
244
245
|
--testMode \
|
|
245
246
|
--output acp-product-feed=./products.jsonl \
|
|
247
|
+
--output acp-feed-metadata=./metadata.json \
|
|
246
248
|
--output google-merchant-feed=./google-merchant.xml \
|
|
247
249
|
--output sitemap-feed=./sitemap.xml
|
|
248
250
|
```
|
|
@@ -255,3 +257,75 @@ node dist/packages/feeds/cli.js list-feeds --config ./packages/feeds/documentati
|
|
|
255
257
|
```
|
|
256
258
|
|
|
257
259
|
When `@reactionary/feeds` is installed as a package, npm/pnpm/yarn exposes the `reactionary-feeds` command from the package `bin` entry.
|
|
260
|
+
|
|
261
|
+
## Publishing ACP feeds to an agent
|
|
262
|
+
|
|
263
|
+
ACP product feeds (2026-04-17) are **pushed by the merchant to the agent**. The agent (e.g. OpenAI) hosts the Feed API — `POST /feeds`, `GET /feeds/{id}`, `GET`/`PATCH /feeds/{id}/products` — and never calls the merchant for feeds. Your ACP checkout server has no feed endpoints; publishing is a separate job you schedule:
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
your scheduler (cron, Kubernetes CronJob, CI)
|
|
267
|
+
└─ reactionary-feeds publish-acp ── reads the catalogue (Reactionary client)
|
|
268
|
+
└─ PATCH {agent Feed API}/feeds/{id}/products ──▶ agent
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
From the agent's onboarding you receive the Feed API base URL, an API key and (usually) a feed id per catalogue. Put them in the feeds config — the key stays in the environment:
|
|
272
|
+
|
|
273
|
+
```js
|
|
274
|
+
// feeds.config.mjs
|
|
275
|
+
export default {
|
|
276
|
+
acpFeedApi: {
|
|
277
|
+
baseUrl: 'https://feeds.agent.example/api', // from onboarding
|
|
278
|
+
apiKeyEnv: 'ACP_FEED_API_KEY', // default; the key itself is never in config
|
|
279
|
+
},
|
|
280
|
+
feeds: {
|
|
281
|
+
finnish: {
|
|
282
|
+
languageContext: { locale: 'fi-FI', currencyCode: 'EUR' },
|
|
283
|
+
search: { term: '', facets: [], filters: ['market:fi'], paginationOptions: { pageNumber: 1, pageSize: 50 } },
|
|
284
|
+
productUrlBase: 'https://shop.example/{lang}/products/{slug}',
|
|
285
|
+
acp: { feedId: 'feed_8f3K2x' }, // from onboarding
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Publish on a schedule. The command prints `{ "feedId", "products", "batches" }` and exits non-zero on any failure, so the scheduler's alerting sees it:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
ACP_FEED_API_KEY=... reactionary-feeds publish-acp -c ./feeds.config.mjs -f finnish
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
```cron
|
|
298
|
+
# Every 15 minutes
|
|
299
|
+
*/15 * * * * ACP_FEED_API_KEY=... reactionary-feeds publish-acp -c /etc/shop/feeds.config.mjs -f finnish --no-progress
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
```yaml
|
|
303
|
+
apiVersion: batch/v1
|
|
304
|
+
kind: CronJob
|
|
305
|
+
metadata:
|
|
306
|
+
name: acp-feed-finnish
|
|
307
|
+
spec:
|
|
308
|
+
schedule: "*/15 * * * *"
|
|
309
|
+
concurrencyPolicy: Forbid
|
|
310
|
+
jobTemplate:
|
|
311
|
+
spec:
|
|
312
|
+
template:
|
|
313
|
+
spec:
|
|
314
|
+
restartPolicy: Never
|
|
315
|
+
containers:
|
|
316
|
+
- name: publish
|
|
317
|
+
image: registry.example/shop-feeds:latest
|
|
318
|
+
args: ["publish-acp", "-c", "/config/feeds.config.mjs", "-f", "finnish", "--no-progress"]
|
|
319
|
+
env:
|
|
320
|
+
- name: ACP_FEED_API_KEY
|
|
321
|
+
valueFrom: { secretKeyRef: { name: acp-feed-api, key: api-key } }
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Options: `--batch-size <n>` (products per upsert, default 100), `--testMode` (two search pages only) and `--no-progress`.
|
|
325
|
+
|
|
326
|
+
Notes:
|
|
327
|
+
|
|
328
|
+
- If the agent does not hand out feed ids, run `reactionary-feeds create-acp-feed -c ./feeds.config.mjs -f finnish` once; it calls `POST /feeds` with the feed's target country and prints the id to put into `acp.feedId`. Nothing is stored at runtime.
|
|
329
|
+
- `PATCH` upserts by product id and never removes products. Products that should no longer be sold are reported as unavailable when they are still found; to drop products entirely, publish a full replacement.
|
|
330
|
+
- **Full replacement** instead of the API: `reactionary-feeds generate -c ./feeds.config.mjs -f finnish --output acp-product-feed=./products.jsonl --output acp-feed-metadata=./metadata.json`, then upload both files however the agent's onboarding specifies (the ACP spec leaves file transfer to the platform).
|
|
331
|
+
- The same publisher is available in code as `ReactionaryACPFeedPublisher` / `createACPFeedPublisherFromConfig` (also re-exported from `@reactionary/acp`).
|