@agenzo/merchant-cli 0.9.2 → 0.9.4

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/dist/index.js CHANGED
@@ -62,6 +62,7 @@ var CODE_NUM = {
62
62
  BOOKING_RESTRICTED: 4310,
63
63
  PAYORDER_FAILED: 4311,
64
64
  PAYORDER_FAILED_AFTER_PAYMENT: 4312,
65
+ OFFER_UNAVAILABLE: 4401,
65
66
  RATE_LIMITED: 5001,
66
67
  UPSTREAM_ERROR: 5101,
67
68
  INTERNAL_ERROR: 5201,
@@ -249,6 +250,7 @@ var STABLE_MESSAGE = {
249
250
  BOOKING_RESTRICTED: "This room has a booking condition that your request doesn't meet. Please check the room's booking rules and adjust your request.",
250
251
  PAYORDER_FAILED: "The hotel order was created, but payment failed. Retry payment for the existing order.",
251
252
  PAYORDER_FAILED_AFTER_PAYMENT: "Payment was received, but hotel confirmation failed. Contact support for reconciliation.",
253
+ OFFER_UNAVAILABLE: "The selected flight is no longer available. Please search again and pick another flight.",
252
254
  NOT_IMPLEMENTED: "This operation is not implemented yet."
253
255
  };
254
256
  function errorDetailLines(envelope) {
@@ -329,6 +331,8 @@ function isBelow(current, minimum) {
329
331
  return compareVersions(current, minimum) < 0;
330
332
  }
331
333
  var TRACEPARENT_PATTERN = /^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$/;
334
+ var FLOW_ID_BAGGAGE_KEY = "agenzo.flow_id";
335
+ var FLOW_ID_PATTERN = /^flw_[A-Za-z0-9_-]{8,60}$/;
332
336
  var DEFAULT_HTTP_TIMEOUT_MS = 7e4;
333
337
  function httpTimeoutFromEnv(env = process.env) {
334
338
  const raw = env.AGENZO_CLI_HTTP_TIMEOUT_MS;
@@ -338,6 +342,25 @@ function httpTimeoutFromEnv(env = process.env) {
338
342
  return parsed;
339
343
  }
340
344
  var DEADLINE_HEADER = "x-deadline-ms";
345
+ var BAGGAGE_HEADER = "baggage";
346
+ function baggageFromEnv(env = process.env) {
347
+ const raw = env.BAGGAGE;
348
+ if (raw === void 0 || raw.trim() === "") return null;
349
+ for (const member of raw.split(",")) {
350
+ const pair = member.split(";", 1)[0] ?? "";
351
+ const eq = pair.indexOf("=");
352
+ if (eq < 0) continue;
353
+ if (pair.slice(0, eq).trim() !== FLOW_ID_BAGGAGE_KEY) continue;
354
+ let value = pair.slice(eq + 1).trim();
355
+ try {
356
+ value = decodeURIComponent(value);
357
+ } catch {
358
+ return null;
359
+ }
360
+ return FLOW_ID_PATTERN.test(value) ? `${FLOW_ID_BAGGAGE_KEY}=${encodeURIComponent(value)}` : null;
361
+ }
362
+ return null;
363
+ }
341
364
  var DEADLINE_RESERVE_MS = 200;
342
365
  function deadlineFromEnv(env = process.env) {
343
366
  const raw = env.DEADLINE_MS;
@@ -399,6 +422,10 @@ var ApiClient = class {
399
422
  if (traceparent && TRACEPARENT_PATTERN.test(traceparent.trim())) {
400
423
  headers["traceparent"] = traceparent.trim();
401
424
  }
425
+ const baggage = baggageFromEnv();
426
+ if (baggage !== null) {
427
+ headers[BAGGAGE_HEADER] = baggage;
428
+ }
402
429
  if (auth.type === "bearer") {
403
430
  headers["Authorization"] = `Bearer ${auth.token}`;
404
431
  } else if (auth.type === "api-key") {
@@ -2432,13 +2459,21 @@ var flightMoreOffersSchema = flightSchema(
2432
2459
  );
2433
2460
  var flightVerifySchema = flightSchema(
2434
2461
  "verify",
2435
- "Pre-booking price verification. Returns the authoritative product_token and a price_changed flag; pass the returned token to create-order.",
2436
- { "product-token": { type: "string", required: true, description: "Opaque token from search." } },
2462
+ "Pre-booking price verification. Returns the authoritative product_token and a price_changed flag; pass the returned token to create-order. With --previous-total-price set, supplier 1002/1950 no longer dead-ends: the platform re-searches the SAME flight from the token and returns the refreshed fare; if that flight can no longer be found it fails with OFFER_UNAVAILABLE (pick another flight).",
2463
+ {
2464
+ "product-token": { type: "string", required: true, description: "Opaque token from search." },
2465
+ "previous-total-price": { type: "int", required: false, description: "Total price of the selected offer; enables the one-shot re-search refresh on supplier 1002/1950. Omit to keep the legacy behavior (error surfaces as-is)." },
2466
+ "cabin-class": { type: "string", required: false, description: "Cabin class to re-search with when refreshing (economy | premium_economy | business | first). Omitted falls back to economy." },
2467
+ "adult-num": { type: "int", required: false, description: "Adults to re-search with when refreshing (1-9)." },
2468
+ "child-num": { type: "int", required: false, description: "Children to re-search with when refreshing (0-9)." },
2469
+ "infant-num": { type: "int", required: false, description: "Infants to re-search with when refreshing (0-9)." }
2470
+ },
2437
2471
  {
2438
2472
  product_token: { type: "string", description: "Authoritative token to pass to create-order." },
2439
2473
  total_price: { type: "int", description: "Verified total price (integer)." },
2440
2474
  currency: { type: "string", description: "Currency code." },
2441
2475
  price_changed: { type: "bool", description: "True if the price changed since search; re-confirm with the user." },
2476
+ previous_total_price: { type: "int", description: "The selected offer\u2019s price at pick time; present when the request carried previous-total-price. If it differs from total_price the fare was refreshed by a re-search (show the user the old \u2192 new price)." },
2442
2477
  journeys: { type: "array", description: "The COMPLETE itinerary being priced \u2014 every leg, not just the last one relayed. Use it to show the full trip on a confirmation screen." }
2443
2478
  },
2444
2479
  { command: "agenzo-merchant-cli flight-flink verify --product-token pt_...", output_summary: "Returns the authoritative product_token + price_changed." }
@@ -6325,18 +6360,26 @@ function registerMoreOffersCommand(parent, deps) {
6325
6360
 
6326
6361
  // src/flight-flink/verify.ts
6327
6362
  function registerVerifyCommand(parent, deps) {
6328
- const cmd = parent.command("verify").description("Verify the latest price before booking; returns the authoritative product_token").option("--api-key <key>", "API Key for authentication (X-Api-Key)").option("--product-token <token>", "Opaque token from search");
6363
+ const cmd = parent.command("verify").description("Verify the latest price before booking; returns the authoritative product_token").option("--api-key <key>", "API Key for authentication (X-Api-Key)").option("--product-token <token>", "Opaque token from search").option("--previous-total-price <n>", "Total price of the selected offer; enables the one-shot re-search refresh on supplier 1002/1950").option("--cabin-class <c>", "Cabin class to re-search with (economy | premium_economy | business | first)").option("--adult-num <n>", "Adults to re-search with (1-9)").option("--child-num <n>", "Children to re-search with (0-9)").option("--infant-num <n>", "Infants to re-search with (0-9)");
6329
6364
  attachSchemaHelp(cmd, flightVerifySchema);
6330
6365
  cmd.action(async () => {
6331
6366
  const opts = cmd.optsWithGlobals();
6332
6367
  const format = resolveFormat(opts.format);
6333
6368
  const apiKey = await resolveApiKey(opts.apiKey);
6334
6369
  const productToken = need21(opts.productToken, "product-token");
6370
+ const body = { product_token: productToken };
6371
+ if (opts.previousTotalPrice !== void 0) {
6372
+ body.previous_total_price = num10(opts.previousTotalPrice, "previous-total-price");
6373
+ }
6374
+ if (opts.cabinClass !== void 0) body.cabin_class = opts.cabinClass;
6375
+ if (opts.adultNum !== void 0) body.adult_num = num10(opts.adultNum, "adult-num");
6376
+ if (opts.childNum !== void 0) body.child_num = num10(opts.childNum, "child-num");
6377
+ if (opts.infantNum !== void 0) body.infant_num = num10(opts.infantNum, "infant-num");
6335
6378
  const spinner = format === "json" ? null : createSpinner("Verifying price...");
6336
6379
  const result = await deps.apiClient.post(
6337
6380
  "/flight/verify",
6338
6381
  { type: "api-key", key: apiKey },
6339
- { product_token: productToken }
6382
+ body
6340
6383
  );
6341
6384
  spinner?.stop();
6342
6385
  if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
@@ -6346,7 +6389,9 @@ function registerVerifyCommand(parent, deps) {
6346
6389
  (d) => Formatter.keyValue([
6347
6390
  ["Product token", String(d.product_token ?? "-")],
6348
6391
  ["Total price", `${d.total_price ?? "-"} ${d.currency ?? ""}`.trim()],
6349
- ["Price changed", String(d.price_changed)]
6392
+ ["Price changed", String(d.price_changed)],
6393
+ // 刷新路径:平台带回选中时的原价,人读 output 里直接看出 原价 → 新价。
6394
+ ...d.previous_total_price != null ? [["Previous total price", String(d.previous_total_price)]] : []
6350
6395
  ])
6351
6396
  );
6352
6397
  });