@itpay/cli 2.1.49 → 2.1.53

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/src/main.js CHANGED
@@ -4453,7 +4453,7 @@ var require_browser = __commonJS({
4453
4453
  var QRCode2 = require_qrcode();
4454
4454
  var CanvasRenderer = require_canvas();
4455
4455
  var SvgRenderer = require_svg_tag();
4456
- function renderCanvas(renderFunc, canvas, text, opts, cb) {
4456
+ function renderCanvas(renderFunc, canvas, text2, opts, cb) {
4457
4457
  const args = [].slice.call(arguments, 1);
4458
4458
  const argsNum = args.length;
4459
4459
  const isLastArgCb = typeof args[argsNum - 1] === "function";
@@ -4465,8 +4465,8 @@ var require_browser = __commonJS({
4465
4465
  throw new Error("Too few arguments provided");
4466
4466
  }
4467
4467
  if (argsNum === 2) {
4468
- cb = text;
4469
- text = canvas;
4468
+ cb = text2;
4469
+ text2 = canvas;
4470
4470
  canvas = opts = void 0;
4471
4471
  } else if (argsNum === 3) {
4472
4472
  if (canvas.getContext && typeof cb === "undefined") {
@@ -4474,8 +4474,8 @@ var require_browser = __commonJS({
4474
4474
  opts = void 0;
4475
4475
  } else {
4476
4476
  cb = opts;
4477
- opts = text;
4478
- text = canvas;
4477
+ opts = text2;
4478
+ text2 = canvas;
4479
4479
  canvas = void 0;
4480
4480
  }
4481
4481
  }
@@ -4484,16 +4484,16 @@ var require_browser = __commonJS({
4484
4484
  throw new Error("Too few arguments provided");
4485
4485
  }
4486
4486
  if (argsNum === 1) {
4487
- text = canvas;
4487
+ text2 = canvas;
4488
4488
  canvas = opts = void 0;
4489
4489
  } else if (argsNum === 2 && !canvas.getContext) {
4490
- opts = text;
4491
- text = canvas;
4490
+ opts = text2;
4491
+ text2 = canvas;
4492
4492
  canvas = void 0;
4493
4493
  }
4494
4494
  return new Promise(function(resolve8, reject) {
4495
4495
  try {
4496
- const data = QRCode2.create(text, opts);
4496
+ const data = QRCode2.create(text2, opts);
4497
4497
  resolve8(renderFunc(data, canvas, opts));
4498
4498
  } catch (e) {
4499
4499
  reject(e);
@@ -4501,7 +4501,7 @@ var require_browser = __commonJS({
4501
4501
  });
4502
4502
  }
4503
4503
  try {
4504
- const data = QRCode2.create(text, opts);
4504
+ const data = QRCode2.create(text2, opts);
4505
4505
  cb(null, renderFunc(data, canvas, opts));
4506
4506
  } catch (e) {
4507
4507
  cb(e);
@@ -4526,8 +4526,8 @@ var require_server = __commonJS({
4526
4526
  var Utf8Renderer = require_utf8();
4527
4527
  var TerminalRenderer = require_terminal2();
4528
4528
  var SvgRenderer = require_svg();
4529
- function checkParams(text, opts, cb) {
4530
- if (typeof text === "undefined") {
4529
+ function checkParams(text2, opts, cb) {
4530
+ if (typeof text2 === "undefined") {
4531
4531
  throw new Error("String required as first argument");
4532
4532
  }
4533
4533
  if (typeof cb === "undefined") {
@@ -4578,11 +4578,11 @@ var require_server = __commonJS({
4578
4578
  }
4579
4579
  }
4580
4580
  __name(getStringRendererFromType, "getStringRendererFromType");
4581
- function render(renderFunc, text, params) {
4581
+ function render(renderFunc, text2, params) {
4582
4582
  if (!params.cb) {
4583
4583
  return new Promise(function(resolve8, reject) {
4584
4584
  try {
4585
- const data = QRCode2.create(text, params.opts);
4585
+ const data = QRCode2.create(text2, params.opts);
4586
4586
  return renderFunc(data, params.opts, function(err, data2) {
4587
4587
  return err ? reject(err) : resolve8(data2);
4588
4588
  });
@@ -4592,7 +4592,7 @@ var require_server = __commonJS({
4592
4592
  });
4593
4593
  }
4594
4594
  try {
4595
- const data = QRCode2.create(text, params.opts);
4595
+ const data = QRCode2.create(text2, params.opts);
4596
4596
  return renderFunc(data, params.opts, params.cb);
4597
4597
  } catch (e) {
4598
4598
  params.cb(e);
@@ -4601,43 +4601,43 @@ var require_server = __commonJS({
4601
4601
  __name(render, "render");
4602
4602
  exports.create = QRCode2.create;
4603
4603
  exports.toCanvas = require_browser().toCanvas;
4604
- exports.toString = /* @__PURE__ */ __name(function toString(text, opts, cb) {
4605
- const params = checkParams(text, opts, cb);
4604
+ exports.toString = /* @__PURE__ */ __name(function toString(text2, opts, cb) {
4605
+ const params = checkParams(text2, opts, cb);
4606
4606
  const type = params.opts ? params.opts.type : void 0;
4607
4607
  const renderer = getStringRendererFromType(type);
4608
- return render(renderer.render, text, params);
4608
+ return render(renderer.render, text2, params);
4609
4609
  }, "toString");
4610
- exports.toDataURL = /* @__PURE__ */ __name(function toDataURL(text, opts, cb) {
4611
- const params = checkParams(text, opts, cb);
4610
+ exports.toDataURL = /* @__PURE__ */ __name(function toDataURL(text2, opts, cb) {
4611
+ const params = checkParams(text2, opts, cb);
4612
4612
  const renderer = getRendererFromType(params.opts.type);
4613
- return render(renderer.renderToDataURL, text, params);
4613
+ return render(renderer.renderToDataURL, text2, params);
4614
4614
  }, "toDataURL");
4615
- exports.toBuffer = /* @__PURE__ */ __name(function toBuffer(text, opts, cb) {
4616
- const params = checkParams(text, opts, cb);
4615
+ exports.toBuffer = /* @__PURE__ */ __name(function toBuffer(text2, opts, cb) {
4616
+ const params = checkParams(text2, opts, cb);
4617
4617
  const renderer = getRendererFromType(params.opts.type);
4618
- return render(renderer.renderToBuffer, text, params);
4618
+ return render(renderer.renderToBuffer, text2, params);
4619
4619
  }, "toBuffer");
4620
- exports.toFile = /* @__PURE__ */ __name(function toFile(path3, text, opts, cb) {
4621
- if (typeof path3 !== "string" || !(typeof text === "string" || typeof text === "object")) {
4620
+ exports.toFile = /* @__PURE__ */ __name(function toFile(path3, text2, opts, cb) {
4621
+ if (typeof path3 !== "string" || !(typeof text2 === "string" || typeof text2 === "object")) {
4622
4622
  throw new Error("Invalid argument");
4623
4623
  }
4624
4624
  if (arguments.length < 3 && !canPromise()) {
4625
4625
  throw new Error("Too few arguments provided");
4626
4626
  }
4627
- const params = checkParams(text, opts, cb);
4627
+ const params = checkParams(text2, opts, cb);
4628
4628
  const type = params.opts.type || getTypeFromFilename(path3);
4629
4629
  const renderer = getRendererFromType(type);
4630
4630
  const renderToFile = renderer.renderToFile.bind(null, path3);
4631
- return render(renderToFile, text, params);
4631
+ return render(renderToFile, text2, params);
4632
4632
  }, "toFile");
4633
- exports.toFileStream = /* @__PURE__ */ __name(function toFileStream(stream, text, opts) {
4633
+ exports.toFileStream = /* @__PURE__ */ __name(function toFileStream(stream, text2, opts) {
4634
4634
  if (arguments.length < 2) {
4635
4635
  throw new Error("Too few arguments provided");
4636
4636
  }
4637
- const params = checkParams(text, opts, stream.emit.bind(stream, "error"));
4637
+ const params = checkParams(text2, opts, stream.emit.bind(stream, "error"));
4638
4638
  const renderer = getRendererFromType("png");
4639
4639
  const renderToFileStream = renderer.renderToFileStream.bind(null, stream);
4640
- render(renderToFileStream, text, params);
4640
+ render(renderToFileStream, text2, params);
4641
4641
  }, "toFileStream");
4642
4642
  }
4643
4643
  });
@@ -7581,7 +7581,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
7581
7581
  * @param {(string | Function)} text - string to add, or a function returning a string
7582
7582
  * @return {Command} `this` command for chaining
7583
7583
  */
7584
- addHelpText(position, text) {
7584
+ addHelpText(position, text2) {
7585
7585
  const allowedValues = ["beforeAll", "before", "after", "afterAll"];
7586
7586
  if (!allowedValues.includes(position)) {
7587
7587
  throw new Error(`Unexpected value for position to addHelpText.
@@ -7590,10 +7590,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
7590
7590
  const helpEvent = `${position}Help`;
7591
7591
  this.on(helpEvent, (context) => {
7592
7592
  let helpStr;
7593
- if (typeof text === "function") {
7594
- helpStr = text({ error: context.error, command: context.command });
7593
+ if (typeof text2 === "function") {
7594
+ helpStr = text2({ error: context.error, command: context.command });
7595
7595
  } else {
7596
- helpStr = text;
7596
+ helpStr = text2;
7597
7597
  }
7598
7598
  if (helpStr) {
7599
7599
  context.write(`${helpStr}
@@ -7673,6 +7673,25 @@ var require_commander = __commonJS({
7673
7673
  }
7674
7674
  });
7675
7675
 
7676
+ // src/services/shared/purchase_contract.generated.ts
7677
+ var purchaseContract = {
7678
+ "version": "itpay.purchase-confirmation.v1",
7679
+ "required": [
7680
+ "review_ref",
7681
+ "request_key",
7682
+ "user_approved",
7683
+ "user_answer",
7684
+ "price_policy"
7685
+ ],
7686
+ "request_key_max_utf16_units": 200,
7687
+ "amount_maximum": 9007199254740991,
7688
+ "modes": {
7689
+ "exact": "amount_minor",
7690
+ "capped": "maximum_minor",
7691
+ "confirm_on_official_page": null
7692
+ }
7693
+ };
7694
+
7676
7695
  // src/client/transport.ts
7677
7696
  var HttpTransportError = class extends Error {
7678
7697
  constructor(code, attempts, causeCode, cause) {
@@ -7879,7 +7898,7 @@ var HttpClient = class _HttpClient {
7879
7898
  if (options.bearer) headers.Authorization = `Bearer ${options.bearer}`;
7880
7899
  if (options.idempotencyKey) headers["Idempotency-Key"] = options.idempotencyKey;
7881
7900
  let response;
7882
- let text;
7901
+ let text2;
7883
7902
  try {
7884
7903
  response = await this.fetchImpl(url, {
7885
7904
  method,
@@ -7894,7 +7913,7 @@ var HttpClient = class _HttpClient {
7894
7913
  requestID = headerID;
7895
7914
  diagnostic.request_id = headerID;
7896
7915
  }
7897
- text = await response.text();
7916
+ text2 = await response.text();
7898
7917
  this.localSimulation = response.headers.get("X-ItPay-Environment") === "local_simulation";
7899
7918
  } catch (error2) {
7900
7919
  if (options.signal?.aborted) {
@@ -7912,7 +7931,7 @@ var HttpClient = class _HttpClient {
7912
7931
  throw asTransientTransportError(error2, transportRetries + 1) ?? error2;
7913
7932
  }
7914
7933
  record(response.ok ? void 0 : `HTTP_${response.status}`);
7915
- const parsed = text.length > 0 ? safeParseJson(text) : void 0;
7934
+ const parsed = text2.length > 0 ? safeParseJson(text2) : void 0;
7916
7935
  if (response.ok) return parsed;
7917
7936
  const error = new HttpError(response.status, parsed, `HTTP ${response.status}`);
7918
7937
  if (!authorizationRecovered && error.status === 401 && error.code === "agent_device_session_required" && this.recoverAuthorization) {
@@ -7956,9 +7975,9 @@ function safeRouteTemplate(path3) {
7956
7975
  return path3.split("/").map((segment) => staticSegments.has(segment) ? segment : segment ? "{value}" : "").join("/");
7957
7976
  }
7958
7977
  __name(safeRouteTemplate, "safeRouteTemplate");
7959
- function safeParseJson(text) {
7978
+ function safeParseJson(text2) {
7960
7979
  try {
7961
- return JSON.parse(text);
7980
+ return JSON.parse(text2);
7962
7981
  } catch {
7963
7982
  return void 0;
7964
7983
  }
@@ -8232,10 +8251,10 @@ async function streamSSE(url, onEvent, signal) {
8232
8251
  signal
8233
8252
  });
8234
8253
  if (!response.ok) {
8235
- const text = await response.text();
8254
+ const text2 = await response.text();
8236
8255
  let msg = `SSE stream failed: HTTP ${response.status}`;
8237
8256
  try {
8238
- const parsed = JSON.parse(text);
8257
+ const parsed = JSON.parse(text2);
8239
8258
  msg = parsed.message || parsed.code || msg;
8240
8259
  } catch {
8241
8260
  }
@@ -8373,9 +8392,9 @@ function readRegular(path3) {
8373
8392
  }
8374
8393
  }
8375
8394
  __name(readRegular, "readRegular");
8376
- function writeComplete(path3, text, createOnly) {
8395
+ function writeComplete(path3, text2, createOnly) {
8377
8396
  const temp = `${path3}.${randomUUID2()}.tmp`;
8378
- writeFileSync2(temp, text, { flag: "wx", mode: 384 });
8397
+ writeFileSync2(temp, text2, { flag: "wx", mode: 384 });
8379
8398
  try {
8380
8399
  if (createOnly) {
8381
8400
  try {
@@ -8452,12 +8471,12 @@ var DeviceSessionCache = class {
8452
8471
  }
8453
8472
  read() {
8454
8473
  const before = this.generation(false);
8455
- const text = readRegular(this.cachePath);
8456
- if (text === void 0) return void 0;
8474
+ const text2 = readRegular(this.cachePath);
8475
+ if (text2 === void 0) return void 0;
8457
8476
  if (before === void 0) throw invalid2("DEVICE_CACHE_GENERATION_MISSING");
8458
8477
  let record;
8459
8478
  try {
8460
- record = JSON.parse(text);
8479
+ record = JSON.parse(text2);
8461
8480
  } catch {
8462
8481
  throw invalid2("DEVICE_CACHE_CORRUPT");
8463
8482
  }
@@ -8470,11 +8489,11 @@ var DeviceSessionCache = class {
8470
8489
  }
8471
8490
  registrationHint() {
8472
8491
  this.checkDirectory();
8473
- const text = readRegular(this.cachePath);
8474
- if (text === void 0) return void 0;
8492
+ const text2 = readRegular(this.cachePath);
8493
+ if (text2 === void 0) return void 0;
8475
8494
  let record;
8476
8495
  try {
8477
- record = JSON.parse(text);
8496
+ record = JSON.parse(text2);
8478
8497
  } catch {
8479
8498
  throw invalid2("DEVICE_CACHE_CORRUPT");
8480
8499
  }
@@ -8502,9 +8521,9 @@ function deviceCacheAgentTypes(directory, backend, keyThumbprint) {
8502
8521
  }
8503
8522
  const types = /* @__PURE__ */ new Set();
8504
8523
  for (const file of files.filter((name) => /^[0-9a-f]{64}\.(json|generation)$/.test(name))) {
8505
- const text = readRegular(join(directory, file));
8506
- if (text === void 0) continue;
8507
- const value = JSON.parse(text);
8524
+ const text2 = readRegular(join(directory, file));
8525
+ if (text2 === void 0) continue;
8526
+ const value = JSON.parse(text2);
8508
8527
  if (value?.backend !== backend || value?.keyThumbprint !== keyThumbprint) continue;
8509
8528
  const marker = file.endsWith(".generation");
8510
8529
  if (value.schemaVersion !== (marker ? "itpay.device-generation.v1" : "itpay.device-session.v1")) throw invalid2("DEVICE_CACHE_CORRUPT");
@@ -9042,7 +9061,10 @@ __name(isOperationID, "isOperationID");
9042
9061
  // src/state/config.ts
9043
9062
  var DEFAULT_BASE_URL = "https://app.itpay.ai";
9044
9063
  var DEV_BASE_URL = "https://dev.itpay.ai";
9064
+ var V4_DEV_BASE_URL = "https://v4-dev.itpay.ai";
9045
9065
  var SANDBOX_BASE_URL = "https://sandbox.itpay.ai";
9066
+ var TEST_BASE_URL = "https://app-test.itpay.ai";
9067
+ var OFFICIAL_BACKEND_URLS = [DEFAULT_BASE_URL, SANDBOX_BASE_URL, DEV_BASE_URL, TEST_BASE_URL, V4_DEV_BASE_URL];
9046
9068
  var CART_SESSION_DEFAULT_DIR = ".itpay-v3";
9047
9069
  var CART_SESSION_FILENAME = "cart.json";
9048
9070
  var OPERATION_JOURNAL_FILENAME = "operations.json";
@@ -9059,15 +9081,15 @@ var BackendOverrideError = class extends Error {
9059
9081
  }
9060
9082
  code = "backend_override_forbidden";
9061
9083
  constructor() {
9062
- super(`ITPAY_BACKEND_URL only supports ${DEFAULT_BASE_URL}, ${SANDBOX_BASE_URL}, or ${DEV_BASE_URL}`);
9084
+ super(`ITPAY_BACKEND_URL only supports ${OFFICIAL_BACKEND_URLS.join(", ")}`);
9063
9085
  this.name = "BackendOverrideError";
9064
9086
  }
9065
9087
  };
9066
9088
  function resolveBackendURL(env = process.env) {
9067
9089
  const requested = env.ITPAY_BACKEND_URL?.trim();
9068
- if (!requested || requested === DEFAULT_BASE_URL || requested === `${DEFAULT_BASE_URL}/`) return DEFAULT_BASE_URL;
9069
- if (requested === SANDBOX_BASE_URL || requested === `${SANDBOX_BASE_URL}/`) return SANDBOX_BASE_URL;
9070
- if (requested === DEV_BASE_URL || requested === `${DEV_BASE_URL}/`) return DEV_BASE_URL;
9090
+ if (!requested) return DEFAULT_BASE_URL;
9091
+ const official = OFFICIAL_BACKEND_URLS.find((origin) => requested === origin || requested === `${origin}/`);
9092
+ if (official) return official;
9071
9093
  if (env.ITPAY_CLI_DEV === "1" && /^http:\/\/(localhost|127\.0\.0\.1):\d+\/?$/.test(requested)) return requested.replace(/\/$/, "");
9072
9094
  throw new BackendOverrideError();
9073
9095
  }
@@ -9244,20 +9266,20 @@ function writeCommandEnvelope(value, options = {}) {
9244
9266
  `);
9245
9267
  }
9246
9268
  } else {
9247
- for (const [key, fact] of Object.entries(facts)) {
9248
- for (const line of plainValueLines(fact, key)) out(`${line}
9269
+ for (const [key, fact2] of Object.entries(facts)) {
9270
+ for (const line of plainValueLines(fact2, key)) out(`${line}
9249
9271
  `);
9250
9272
  }
9251
9273
  if ("error" in qualified && qualified.result) {
9252
- for (const [key, fact] of Object.entries(qualified.result)) {
9253
- for (const line of plainValueLines(fact, key)) out(`${line}
9274
+ for (const [key, fact2] of Object.entries(qualified.result)) {
9275
+ for (const line of plainValueLines(fact2, key)) out(`${line}
9254
9276
  `);
9255
9277
  }
9256
9278
  }
9257
9279
  }
9258
9280
  if ("handoff" in qualified && qualified.handoff) {
9259
- for (const [key, fact] of Object.entries(qualified.handoff)) {
9260
- for (const line of plainValueLines(fact, `handoff.${key}`)) out(`${line}
9281
+ for (const [key, fact2] of Object.entries(qualified.handoff)) {
9282
+ for (const line of plainValueLines(fact2, `handoff.${key}`)) out(`${line}
9261
9283
  `);
9262
9284
  }
9263
9285
  }
@@ -9383,8 +9405,8 @@ function purchaseEnvelope(state) {
9383
9405
  const review = state.review;
9384
9406
  return {
9385
9407
  status: state.status,
9386
- result: { service_execution_id: id, completed_stage: state.completed_stage, ...state.auto_wait_remaining_ms !== void 0 ? { auto_wait_remaining_ms: state.auto_wait_remaining_ms } : {}, effects: state.effects, ...review ? { summary: review.summary, price_kind: review.binding.price_kind, review_expires_at: review.binding.expires_at, input_template: fileInputTemplate(`itpay services purchase ${id} --input-json <purchase-confirmation.json> --json`, { ...review.confirmation_template }, ["user_approved", "user_answer", ...review.confirmation_template.price_policy.mode === "" ? ["price_policy"] : []], { executionID: id }) } : {} },
9387
- instruction: review ? `${state.status === "confirmation_changed" ? "\u8D2D\u4E70\u6761\u4EF6\u53D1\u751F\u53D8\u5316\uFF0C\u53EA\u8865\u5145\u5BF9\u53D8\u5316\u7684\u771F\u5B9E\u786E\u8BA4\u3002" : "\u6838\u5BF9\u5F53\u524D\u5BF9\u8C61\u3001\u6570\u91CF\u3001\u91D1\u989D\u4E0E\u6761\u6B3E\u3002"}\u5DF2\u6709\u660E\u786E\u540C\u610F\u4E14\u8986\u76D6\u8FD9\u4E9B\u6761\u4EF6\u65F6\u6CBF\u7528\uFF1B\u5426\u5219\u4EC5\u8865\u7F3A\u5931\u540C\u610F\u3002\u5C06\u5B8C\u6574 file_content \u5199\u5165\u6587\u4EF6\uFF0C\u586B\u5199\u771F\u5B9E\u56DE\u7B54\u548C\u660E\u786E\u4EF7\u683C\u7B56\u7565\u540E\u6267\u884C\u6A21\u677F\u3002\u672C\u6B65\u9AA4\u53EA\u751F\u6210\u5B98\u65B9\u586B\u5199\u4E0E\u4ED8\u6B3E\u9875\u9762\uFF0C\u4E0D\u53D1\u8D77\u652F\u4ED8\u3002\u672A\u77E5\u4EF7\u683C\u4E0D\u5F97\u9ED8\u8BA4\u6539\u6210\u5B98\u65B9\u9875\u786E\u8BA4\u3002` : state.status === "running" && state.auto_wait_remaining_ms === 0 ? "\u81EA\u52A8\u7B49\u5F85\u5DF2\u8FBE\u5230120\u79D2\u4E0A\u9650\uFF0C\u5DF2\u505C\u6B62\u3002\u539F\u786E\u8BA4\u548C\u539F\u8D2D\u4E70\u4FDD\u7559\uFF1B\u62A5\u544A completed_stage\uFF0C\u7528\u6237\u660E\u786E\u8981\u6C42\u6062\u590D\u65F6\u4F7F\u7528 recovery \u4E2D\u7684\u539F\u5355\u547D\u4EE4\uFF0C\u4E0D\u81EA\u52A8\u91CD\u542F\u7B49\u5F85\u3002" : state.status === "running" ? "\u5DF2\u4FDD\u5B58\u539F\u786E\u8BA4\uFF0C\u5F53\u524D\u5B8C\u6210\u9636\u6BB5\u89C1 completed_stage\u3002\u4FDD\u7559\u540C\u4E00\u4EFB\u52A1\u7EE7\u7EED\u6709\u754C\u7B49\u5F85\uFF1B\u4E0D\u8981\u6C42\u7528\u6237\u8BF4\u7EE7\u7EED\u3002\u7D2F\u8BA1120\u79D2\u4ECD\u672A\u5B8C\u6210\u65F6\u505C\u6B62\u81EA\u52A8\u7B49\u5F85\u5E76\u62A5\u544A\u539F\u8FDB\u5EA6\uFF0C\u4E0D\u521B\u5EFA\u66FF\u4EE3\u8D2D\u4E70\u3002" : state.status === "expired" ? "\u539F\u786E\u8BA4\u6216\u62A5\u4EF7\u5DF2\u5230\u671F\uFF0C\u4E0D\u80FD\u6CBF\u7528\u8FC7\u671F\u5165\u53E3\uFF1B\u4FDD\u7559\u539F\u8D2D\u4E70\u5E76\u6838\u5BF9\u5F53\u524D\u72B6\u6001\uFF0C\u4ED8\u6B3E\u672A\u77E5\u4E0D\u91CD\u5EFA\u3002" : "\u5F53\u524D\u8D2D\u4E70\u672A\u80FD\u7EE7\u7EED\uFF1B\u4FDD\u7559\u539F\u6267\u884C\uFF0C\u6309\u5F53\u524D\u539F\u56E0\u5904\u7406\uFF0C\u4E0D\u91CD\u5EFA\u8D2D\u4E70\u6216\u731C\u6D4B\u7ED3\u679C\u3002",
9408
+ result: { service_execution_id: id, completed_stage: state.completed_stage, ...state.auto_wait_remaining_ms !== void 0 ? { auto_wait_remaining_ms: state.auto_wait_remaining_ms } : {}, effects: state.effects, ...review ? { summary: review.summary, allowed_modes: review.allowed_modes, confirmation_schema: review.confirmation_schema, price_kind: review.binding.price_kind, review_expires_at: review.binding.expires_at, input_template: fileInputTemplate(`itpay services purchase ${id} --input-json <purchase-confirmation.json> --json`, { ...review.confirmation_template }, ["user_approved", "user_answer", ...review.confirmation_template.price_policy.mode === "" ? ["price_policy"] : []], { executionID: id }) } : {} },
9409
+ instruction: review ? `${state.status === "confirmation_changed" ? "\u8D2D\u4E70\u6761\u4EF6\u53D1\u751F\u53D8\u5316\uFF0C\u53EA\u8865\u5145\u5BF9\u53D8\u5316\u7684\u771F\u5B9E\u786E\u8BA4\u3002" : "\u6838\u5BF9\u5F53\u524D\u5BF9\u8C61\u3001\u6570\u91CF\u3001\u91D1\u989D\u4E0E\u6761\u6B3E\u3002"}\u5DF2\u6709\u660E\u786E\u540C\u610F\u4E14\u8986\u76D6\u8FD9\u4E9B\u6761\u4EF6\u65F6\u6CBF\u7528\uFF1B\u5426\u5219\u4EC5\u8865\u7F3A\u5931\u540C\u610F\u3002\u5C06\u5B8C\u6574 file_content \u5199\u5165\u6587\u4EF6\uFF0C\u586B\u5199\u771F\u5B9E\u56DE\u7B54\u548C\u660E\u786E\u4EF7\u683C\u7B56\u7565\u540E\u6267\u884C\u6A21\u677F\u3002\u672C\u6B65\u9AA4\u7684\u6548\u679C\u4EE5 effects \u548C\u5F53\u524D\u670D\u52A1\u5408\u540C\u4E3A\u51C6\uFF1B\u4E0D\u53D1\u8D77\u652F\u4ED8\u4E0D\u80FD\u63A8\u65AD\u6CA1\u6709\u8BA2\u5355\u6216\u5E93\u5B58\u6548\u679C\u3002\u5BBF\u4E3B\u539F\u751F\u6279\u51C6\u4E0E\u4E1A\u52A1\u540C\u610F\u5206\u522B\u4FDD\u7559\u3002\u672A\u77E5\u4EF7\u683C\u4E0D\u5F97\u9ED8\u8BA4\u6539\u6210\u5B98\u65B9\u9875\u786E\u8BA4\u3002` : state.status === "running" && state.auto_wait_remaining_ms === 0 ? "\u81EA\u52A8\u7B49\u5F85\u5DF2\u8FBE\u5230120\u79D2\u4E0A\u9650\uFF0C\u5DF2\u505C\u6B62\u3002\u539F\u786E\u8BA4\u548C\u539F\u8D2D\u4E70\u4FDD\u7559\uFF1B\u62A5\u544A completed_stage\uFF0C\u7528\u6237\u660E\u786E\u8981\u6C42\u6062\u590D\u65F6\u4F7F\u7528 recovery \u4E2D\u7684\u539F\u5355\u547D\u4EE4\uFF0C\u4E0D\u81EA\u52A8\u91CD\u542F\u7B49\u5F85\u3002" : state.status === "running" ? "\u5DF2\u4FDD\u5B58\u539F\u786E\u8BA4\uFF0C\u5F53\u524D\u5B8C\u6210\u9636\u6BB5\u89C1 completed_stage\u3002\u4FDD\u7559\u540C\u4E00\u4EFB\u52A1\u7EE7\u7EED\u6709\u754C\u7B49\u5F85\uFF1B\u4E0D\u8981\u6C42\u7528\u6237\u8BF4\u7EE7\u7EED\u3002\u7D2F\u8BA1120\u79D2\u4ECD\u672A\u5B8C\u6210\u65F6\u505C\u6B62\u81EA\u52A8\u7B49\u5F85\u5E76\u62A5\u544A\u539F\u8FDB\u5EA6\uFF0C\u4E0D\u521B\u5EFA\u66FF\u4EE3\u8D2D\u4E70\u3002" : state.status === "expired" ? "\u539F\u786E\u8BA4\u6216\u62A5\u4EF7\u5DF2\u5230\u671F\uFF0C\u4E0D\u80FD\u6CBF\u7528\u8FC7\u671F\u5165\u53E3\uFF1B\u4FDD\u7559\u539F\u8D2D\u4E70\u5E76\u6838\u5BF9\u5F53\u524D\u72B6\u6001\uFF0C\u4ED8\u6B3E\u672A\u77E5\u4E0D\u91CD\u5EFA\u3002" : "\u5F53\u524D\u8D2D\u4E70\u672A\u80FD\u7EE7\u7EED\uFF1B\u4FDD\u7559\u539F\u6267\u884C\uFF0C\u6309\u5F53\u524D\u539F\u56E0\u5904\u7406\uFF0C\u4E0D\u91CD\u5EFA\u8D2D\u4E70\u6216\u731C\u6D4B\u7ED3\u679C\u3002",
9388
9410
  next: state.status === "running" && state.auto_wait_remaining_ms !== 0 ? resume : null,
9389
9411
  recovery: state.status === "running" && state.auto_wait_remaining_ms === 0 ? [{ ...resume, reason: "\u4EC5\u7528\u6237\u660E\u786E\u8981\u6C42\u7EE7\u7EED\u65F6\u6062\u590D\u539F\u8D2D\u4E70\uFF1B\u4E0D\u81EA\u52A8\u91CD\u542F\u7B49\u5F85" }] : state.status === "blocked" || state.status === "expired" ? [{ command: `itpay services next ${id} --json`, reason: "\u8BFB\u53D6\u539F\u6267\u884C\u7684\u5F53\u524D\u4E8B\u5B9E\u4E0E\u5B8C\u6574\u6062\u590D\u52A8\u4F5C\uFF1B\u4E0D\u65B0\u5EFA\u8D2D\u4E70" }] : []
9390
9412
  };
@@ -9436,6 +9458,7 @@ function defaultHostForAgentType(agentType) {
9436
9458
  const normalized = agentType?.trim().toLowerCase() ?? "";
9437
9459
  if (normalized === "codex-desktop") return "codex";
9438
9460
  if (normalized === "claude-code-desktop") return "claude-code";
9461
+ if (normalized === "dot" || normalized === "muse" || normalized === "hermes") return "plain-chat";
9439
9462
  if (normalized === "workbuddy") return "plain-chat";
9440
9463
  if (normalized === "zcode") return "plain-chat";
9441
9464
  if (normalized === "doubao-work") return "plain-chat";
@@ -9515,228 +9538,6 @@ function hostCapabilities(host) {
9515
9538
  }
9516
9539
  __name(hostCapabilities, "hostCapabilities");
9517
9540
 
9518
- // src/render/telegram.ts
9519
- function buttonsFor(plan) {
9520
- if (plan.kind === "payment_qr" && plan.paymentIntentID) {
9521
- return [
9522
- { label: "\u652F\u4ED8\u9047\u5230\u95EE\u9898 / \u5237\u65B0", kind: "callback", intent: "refresh_payment_qr", ref: plan.paymentIntentID },
9523
- { label: "\u6211\u5DF2\u4ED8\u6B3E\uFF0C\u67E5\u8BE2\u72B6\u6001", kind: "callback", intent: "check_payment_status", ref: plan.paymentIntentID }
9524
- ];
9525
- }
9526
- if (plan.kind === "auth_qr" && plan.checkoutID) {
9527
- return [
9528
- { label: "\u6253\u5F00\u6388\u6743\u9875\u9762", kind: "url", url: plan.url },
9529
- { label: "\u67E5\u8BE2\u6388\u6743\u72B6\u6001", kind: "callback", intent: "check_checkout_status", ref: plan.checkoutID }
9530
- ];
9531
- }
9532
- return [
9533
- { label: "\u{1F4F1} \u624B\u673A\u70B9\u8FD9\u513F\u652F\u4ED8", kind: "url", url: plan.url },
9534
- ...plan.checkoutID ? [{ label: "\u{1F4CB} \u5DF2\u6388\u6743\u7ED9\u6211\u8BFB", kind: "callback", intent: "grant_confirmed", ref: plan.checkoutID }] : []
9535
- ];
9536
- }
9537
- __name(buttonsFor, "buttonsFor");
9538
- function nativeButton(button) {
9539
- if (button.kind === "url") {
9540
- return { label: button.label, url: button.url ?? "" };
9541
- }
9542
- const value = button.intent === "check_checkout_status" ? `itp:checkout:${button.ref ?? ""}` : `itp:${button.intent ?? "callback"}:${button.ref ?? ""}`;
9543
- return { label: button.label, value };
9544
- }
9545
- __name(nativeButton, "nativeButton");
9546
- function renderTelegram(plan, options) {
9547
- const out = options.output ?? ((line) => process.stdout.write(line));
9548
- const agentAction = buildOpenClawTelegramAction(plan, options.target);
9549
- const presentation = agentAction.arguments.presentation;
9550
- const media = collectTelegramMedia(plan);
9551
- const text = agentAction.arguments.message;
9552
- const openclawMessage = {
9553
- command: [
9554
- "openclaw",
9555
- "message",
9556
- "send",
9557
- "--channel",
9558
- "telegram",
9559
- "--target",
9560
- options.target,
9561
- "--message",
9562
- text,
9563
- ...media.length > 0 ? ["--media", media[0].url] : [],
9564
- "--presentation",
9565
- JSON.stringify(presentation)
9566
- ],
9567
- // Keep the same Checkout visible if native buttons are unavailable.
9568
- if_unavailable: "If `openclaw message send` is unavailable, send the same QR media and Checkout URL as ordinary Telegram content, report that inline buttons are unavailable, and stop. Do not create another Checkout."
9569
- };
9570
- out(JSON.stringify({ presentation, agent_action: agentAction, openclaw_message: openclawMessage }, null, 2) + "\n");
9571
- }
9572
- __name(renderTelegram, "renderTelegram");
9573
- function buildOpenClawTelegramAction(plan, target2) {
9574
- const buttons = buttonsFor(plan).map(nativeButton);
9575
- const media = collectTelegramMedia(plan);
9576
- const message = plan.kind === "payment_qr" ? `ItPay payment QR \u2014 ${plan.summary}` : plan.kind === "auth_qr" ? `ItPay auth required \u2014 ${plan.summary}` : `ItPay checkout QR \u2014 ${plan.summary}`;
9577
- const presentation = {
9578
- blocks: [{ type: "buttons", buttons }]
9579
- };
9580
- const nativeTarget = target2.trim().replace(/^telegram:/i, "");
9581
- return {
9582
- tool: "message",
9583
- arguments: {
9584
- action: "send",
9585
- channel: "telegram",
9586
- target: nativeTarget,
9587
- message,
9588
- ...media[0]?.url ? { media: media[0].url } : {},
9589
- presentation
9590
- }
9591
- };
9592
- }
9593
- __name(buildOpenClawTelegramAction, "buildOpenClawTelegramAction");
9594
- function collectTelegramMedia(plan) {
9595
- const media = (plan.platform.media ?? []).map((item) => ({
9596
- url: item.url,
9597
- mimeType: item.mimeType ?? "image/png"
9598
- }));
9599
- if (plan.kind === "payment_qr" || media.length === 0) {
9600
- media.unshift({
9601
- url: plan.preferredQRSources.find((src) => src.length > 0) ?? plan.url,
9602
- mimeType: "image/png"
9603
- });
9604
- }
9605
- return media;
9606
- }
9607
- __name(collectTelegramMedia, "collectTelegramMedia");
9608
-
9609
- // src/render/checkout_handoff.ts
9610
- function shouldPrepareLocalCheckoutImage(platform2) {
9611
- return platform2 === "markdown";
9612
- }
9613
- __name(shouldPrepareLocalCheckoutImage, "shouldPrepareLocalCheckoutImage");
9614
- function isWorkBuddyPlainChat(agentType, platform2) {
9615
- return agentType?.trim().toLowerCase() === "workbuddy" && platform2 === "plain_chat";
9616
- }
9617
- __name(isWorkBuddyPlainChat, "isWorkBuddyPlainChat");
9618
- function isZCodePlainChat(agentType, platform2) {
9619
- return agentType?.trim().toLowerCase() === "zcode" && platform2 === "plain_chat";
9620
- }
9621
- __name(isZCodePlainChat, "isZCodePlainChat");
9622
- function isLinkOnlyBrowserAgent(agentType, platform2) {
9623
- return isWorkBuddyPlainChat(agentType, platform2) || isZCodePlainChat(agentType, platform2);
9624
- }
9625
- __name(isLinkOnlyBrowserAgent, "isLinkOnlyBrowserAgent");
9626
- function buildWorkBuddyPresentFilesAction(url) {
9627
- return {
9628
- tool: "present_files",
9629
- arguments: { files: [url] }
9630
- };
9631
- }
9632
- __name(buildWorkBuddyPresentFilesAction, "buildWorkBuddyPresentFilesAction");
9633
- function hasCompleteCheckoutTokens(url) {
9634
- if (!url) {
9635
- return false;
9636
- }
9637
- try {
9638
- const parsed = new URL(url);
9639
- return Boolean(parsed.searchParams.get("display_token") && parsed.searchParams.get("complete_exchange_token"));
9640
- } catch {
9641
- return false;
9642
- }
9643
- }
9644
- __name(hasCompleteCheckoutTokens, "hasCompleteCheckoutTokens");
9645
- function buildCheckoutHandoff(input) {
9646
- const url = input.plan?.localSimulation && input.mobileUrl && hasCompleteCheckoutTokens(input.mobileUrl) ? input.mobileUrl : input.url;
9647
- const handoff = { url, ...input.plan?.localSimulation ? { environment: "local_simulation", query: "live", transactions: "simulated" } : {} };
9648
- const mobileUrl = !input.plan?.localSimulation && hasCompleteCheckoutTokens(input.mobileUrl) ? input.mobileUrl : void 0;
9649
- if (mobileUrl) {
9650
- handoff.mobile_url = mobileUrl;
9651
- }
9652
- const workBuddyAction = isWorkBuddyPlainChat(input.agentType, input.platform);
9653
- if (workBuddyAction) {
9654
- handoff.agent_action = buildWorkBuddyPresentFilesAction(url);
9655
- }
9656
- if (input.platform === "markdown") {
9657
- if (input.localPath) handoff.qr_local_path = input.localPath;
9658
- if (input.markdown) handoff.markdown = input.markdown;
9659
- } else if (input.platform === "plain_chat" && input.qrImageURL && !isLinkOnlyBrowserAgent(input.agentType, input.platform)) {
9660
- handoff.qr_image_url = input.qrImageURL;
9661
- } else if (input.platform === "telegram" && input.qrImageURL) {
9662
- handoff.qr_image_url = input.qrImageURL;
9663
- }
9664
- if (input.agentType?.trim().toLowerCase() === "openclaw" && input.platform === "telegram" && input.plan && input.target) {
9665
- handoff.agent_action = buildOpenClawTelegramAction(input.plan, input.target);
9666
- }
9667
- return {
9668
- handoff,
9669
- instruction: input.plan?.localSimulation ? `\u672C\u5730\u5B9E\u9A8C\uFF1A\u94C1\u8DEF\u4E0E\u5730\u56FE\u67E5\u8BE2\u771F\u5B9E\uFF0C\u6388\u6743\u3001\u901A\u77E5\u548C\u4EA4\u6613\u6A21\u62DF\uFF0C\u4E0D\u4F1A\u6263\u6B3E\u3002\u5728\u672C\u673A\u6253\u5F00 handoff.url \u6A21\u62DF\u4ED8\u6B3E\u5165\u53E3\uFF0C\u91D1\u989D ${input.amount}\uFF1B\u4EC5\u672C\u673A\u684C\u9762\u53EF\u8FBE\u3002${workBuddyAction ? "\u6309 handoff.agent_action \u539F\u6837\u6253\u5F00\u4E00\u6B21\u3002" : "\u5C55\u793A\u539F\u5165\u53E3\u3002"}\u7B49\u5F85\u7528\u6237\u64CD\u4F5C\u540E\u8BFB\u53D6\u540C\u4E00 Checkout\uFF1B\u4E0D\u521B\u5EFA\u66FF\u4EE3\u8BA2\u5355\uFF0C\u7528\u6237\u58F0\u660E\u4E0D\u8BC1\u660E\u6A21\u62DF\u4ED8\u6B3E\u5DF2\u786E\u8BA4\u3002` : `\u5148\u5C55\u793A\u5B98\u65B9\u5165\u53E3\uFF0C\u518D\u505A\u975E\u5FC5\u8981\u8BB0\u5FC6\u6216\u65E5\u5FD7\uFF1B\u4FDD\u7559\u5FC5\u9700\u5B89\u5168\u68C0\u67E5\u548C\u5BBF\u4E3B\u6743\u9650\u3002${checkoutHandoffInstruction(input.agentType, input.platform, input.amount, Boolean(mobileUrl))}`
9670
- };
9671
- }
9672
- __name(buildCheckoutHandoff, "buildCheckoutHandoff");
9673
- function checkoutHandoffInstruction(agentType, platform2, amount, hasMobileLink) {
9674
- if (isWorkBuddyPlainChat(agentType, platform2)) {
9675
- const mobileSentence = hasMobileLink ? "\uFF0C\u7136\u540E\u628A handoff.mobile_url \u4F5C\u4E3A\u53EF\u70B9\u51FB\u94FE\u63A5\u53D1\u7ED9\u7528\u6237\uFF0C\u8BF4\u660E\u201C\u624B\u673A\u7AEF\u70B9\u5F00\u53EF\u76F4\u63A5\u8DF3\u8F6C\u652F\u4ED8\u5B9D\u6216\u5FAE\u4FE1\u652F\u4ED8\uFF1B\u5C0F\u7A0B\u5E8F\u5185\u6253\u4E0D\u5F00\u65F6\u590D\u5236\u5230\u624B\u673A\u6D4F\u89C8\u5668\u6253\u5F00\u5373\u53EF\u201D" : "";
9676
- const failLinks = hasMobileLink ? "\u53D1\u9001 handoff.url \u4E0E handoff.mobile_url" : "\u53D1\u9001\u539F\u59CB handoff.url";
9677
- return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u3002\u82E5\u5F53\u524D\u53EF\u7528 present_files\uFF0C\u6309 handoff.agent_action \u539F\u6837\u6267\u884C\u4E00\u6B21\uFF1B\u4E0D\u53EF\u7528\u5219\u5F53\u8F6E\u76F4\u63A5\u5C55\u793A\u539F\u94FE\u63A5\uFF0C\u5728\u53F3\u4FA7\u6253\u5F00 handoff.url\uFF1B\u5DE5\u5177\u6210\u529F\u6216\u76F4\u63A5\u5C55\u793A\u94FE\u63A5\u540E\u8BF4\u660E\u91D1\u989D ${amount}${mobileSentence}\uFF0C\u7136\u540E\u505C\u6B62\u7B49\u5F85\u3002\u82E5\u5DE5\u5177\u5931\u8D25\uFF0C\u53EA${failLinks}\uFF0C\u62A5\u544A\u672A\u81EA\u52A8\u6253\u5F00\u5E76\u505C\u6B62\u3002\u4E0D\u8981\u7528 present_files \u6253\u5F00\u672C\u5730\u6587\u4EF6\u6216\u4E8C\u7EF4\u7801 PNG\uFF0C\u4E0D\u8981\u4E0B\u8F7D\u6216\u91CD\u5EFA\u4E8C\u7EF4\u7801\uFF0C\u4E0D\u8981\u8C03\u7528 pay\uFF0C\u4E0D\u8981\u521B\u5EFA\u65B0 Checkout\u3001Payment Intent \u6216 Execution\u3002\u53EA\u6709\u7528\u6237\u660E\u786E\u8868\u793A\u5DF2\u4ED8\u6B3E\u6216\u8981\u6C42\u67E5\u8BE2\u72B6\u6001\u65F6\uFF0C\u624D\u6267\u884C next.command\uFF1B\u7528\u6237\u7684\u8BDD\u4E0D\u662F\u4ED8\u6B3E\u6210\u529F\u8BC1\u660E\u3002`;
9678
- }
9679
- if (isZCodePlainChat(agentType, platform2)) {
9680
- const mobileSentence = hasMobileLink ? "\uFF0C\u5E76\u628A handoff.mobile_url \u53D1\u7ED9\u7528\u6237\u5907\u7528\uFF08\u624B\u673A\u7AEF\u70B9\u5F00\u53EF\u76F4\u63A5\u8DF3\u8F6C\u652F\u4ED8\u5B9D\u6216\u5FAE\u4FE1\u652F\u4ED8\uFF09" : "";
9681
- const fallbackLinks = hasMobileLink ? "\u540C\u4E00\u4E2A\u53EF\u70B9\u51FB handoff.url \u4E0E handoff.mobile_url" : "\u540C\u4E00\u4E2A\u53EF\u70B9\u51FB handoff.url";
9682
- return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u3002\u7ACB\u5373\u7528 ZCode \u5185\u7F6E\u6D4F\u89C8\u5668\u6253\u5F00 handoff.url\uFF0C\u8BA9\u7528\u6237\u5B8C\u6210\u4ED8\u6B3E\uFF1B\u786E\u8BA4\u5DF2\u53D1\u8D77\u6253\u5F00\u540E\u8BF4\u660E\u91D1\u989D ${amount}${mobileSentence}\uFF0C\u7136\u540E\u505C\u6B62\u7B49\u5F85\u3002\u5DE5\u5177\u4E0D\u53EF\u7528\u65F6\u76F4\u63A5\u5C55\u793A\u94FE\u63A5\uFF0C\u4E0D\u8981\u4E0B\u8F7D\u3001\u89E3\u6790\u6216\u91CD\u5EFA\u4E8C\u7EF4\u7801\uFF0C\u4E0D\u8981\u521B\u5EFA\u65B0 Checkout\u3001Payment Intent \u6216 Execution\u3002\u53EA\u6709\u5185\u7F6E\u6D4F\u89C8\u5668\u660E\u786E\u4E0D\u53EF\u7528\u65F6\uFF0C\u624D\u5C55\u793A${fallbackLinks}\u3002\u53EA\u6709\u7528\u6237\u660E\u786E\u8868\u793A\u5DF2\u4ED8\u6B3E\u6216\u8981\u6C42\u67E5\u8BE2\u72B6\u6001\u65F6\uFF0C\u624D\u6267\u884C next.command\uFF1B\u7528\u6237\u7684\u8BDD\u4E0D\u662F\u4ED8\u6B3E\u6210\u529F\u8BC1\u660E\u3002`;
9683
- }
9684
- if (agentType?.trim().toLowerCase() === "doubao-work" && platform2 === "plain_chat") {
9685
- const directLink = hasMobileLink ? "handoff.mobile_url" : "handoff.url";
9686
- const directLabel = hasMobileLink ? "\u624B\u673A\u76F4\u63A5\u6253\u5F00\u6536\u94F6\u53F0\uFF08\u53EF\u8DF3\u8F6C\u652F\u4ED8\u5B9D/\u5FAE\u4FE1\uFF09" : "\u624B\u673A\u76F4\u63A5\u6253\u5F00\u6536\u94F6\u53F0";
9687
- return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u3002\u5728\u5F53\u524D\u8C46\u5305\u5DE5\u4F5C\u5BF9\u8BDD\u4E2D\u5C55\u793A\u4E24\u4E2A\u6709\u6807\u7B7E\u7684\u5B98\u65B9\u5165\u53E3\uFF1A\u5C06 ${directLink} \u6807\u4E3A\u201C${directLabel}\u201D\uFF0C\u5C06 handoff.qr_image_url \u6807\u4E3A\u201C\u4E8C\u7EF4\u7801\u56FE\u7247\uFF08\u4FDD\u5B58\u6216\u7528\u53E6\u4E00\u53F0\u8BBE\u5907\u626B\u7801\uFF09\u201D\u3002\u8BF4\u660E\u91D1\u989D ${amount} \u540E\u505C\u6B62\u7B49\u5F85\u3002\u4E0D\u8981\u89E3\u6790\u6216\u5355\u72EC\u8F93\u51FA URL credential\uFF0C\u4E0D\u8981\u4E0B\u8F7D\u6216\u91CD\u5EFA\u4E8C\u7EF4\u7801\uFF0C\u4E0D\u8981\u8C03\u7528 pay\uFF0C\u4E0D\u8981\u521B\u5EFA\u65B0 Checkout\u3001Payment Intent \u6216 Execution\u3002\u53EA\u6709\u7528\u6237\u660E\u786E\u8868\u793A\u5DF2\u4ED8\u6B3E\u6216\u8981\u6C42\u67E5\u8BE2\u72B6\u6001\u65F6\uFF0C\u624D\u6267\u884C next.command\uFF1B\u7528\u6237\u7684\u8BDD\u4E0D\u662F\u4ED8\u6B3E\u6210\u529F\u8BC1\u660E\u3002`;
9688
- }
9689
- if (platform2 === "markdown") {
9690
- const mobileSentence = hasMobileLink ? "\uFF0C\u5E76\u9644 handoff.mobile_url \u4F9B\u624B\u673A\u7AEF\u70B9\u51FB\u76F4\u8FBE\u652F\u4ED8" : "";
9691
- return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u3002\u628A handoff.markdown \u539F\u6837\u53D1\u9001\u5230\u5F53\u524D\u684C\u9762\u5BF9\u8BDD\uFF0C\u786E\u8BA4\u4E8C\u7EF4\u7801\u3001\u4ED8\u6B3E\u94FE\u63A5\u548C\u91D1\u989D ${amount} \u5747\u5DF2\u5B9E\u9645\u5BF9\u7528\u6237\u53EF\u89C1${mobileSentence}\uFF0C\u7136\u540E\u505C\u6B62\u7B49\u5F85\u3002\u4E0D\u8981\u521B\u5EFA\u65B0 Checkout\u3001Payment Intent \u6216 Execution\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8868\u793A\u5DF2\u4ED8\u6B3E\u6216\u8981\u6C42\u67E5\u8BE2\u72B6\u6001\u65F6\uFF0C\u624D\u6267\u884C next.command\uFF1B\u7528\u6237\u7684\u8BDD\u4E0D\u662F\u4ED8\u6B3E\u6210\u529F\u8BC1\u660E\u3002`;
9692
- }
9693
- if (platform2 === "terminal") {
9694
- const mobileSentence = hasMobileLink ? "\uFF0C\u5E76\u5C55\u793A handoff.mobile_url \u4F9B\u624B\u673A\u7AEF\u70B9\u51FB\u76F4\u8FBE\u652F\u4ED8" : "";
9695
- return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u3002\u5728\u7528\u6237\u53EF\u89C1\u7EC8\u7AEF\u5C55\u793A\u5F53\u524D Checkout \u7684\u4E8C\u7EF4\u7801\u3001handoff.url \u548C\u91D1\u989D ${amount}${mobileSentence}\uFF0C\u7136\u540E\u505C\u6B62\u7B49\u5F85\u3002\u4E0D\u8981\u521B\u5EFA\u65B0 Checkout\u3001Payment Intent \u6216 Execution\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8868\u793A\u5DF2\u4ED8\u6B3E\u6216\u8981\u6C42\u67E5\u8BE2\u72B6\u6001\u65F6\uFF0C\u624D\u6267\u884C next.command\uFF1B\u7528\u6237\u7684\u8BDD\u4E0D\u662F\u4ED8\u6B3E\u6210\u529F\u8BC1\u660E\u3002`;
9696
- }
9697
- if (agentType?.trim().toLowerCase() === "openclaw" && platform2 === "telegram") {
9698
- const failLinks = hasMobileLink ? "handoff.qr_image_url\u3001\u91D1\u989D\u3001handoff.url \u4E0E handoff.mobile_url" : "handoff.qr_image_url\u3001\u91D1\u989D\u548C handoff.url";
9699
- return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u6216\u6388\u6743\u72B6\u6001\u3002\u82E5\u5F53\u524D\u5DF2\u6709\u53EF\u7528 OpenClaw \u539F\u751F message tool\uFF0C\u4E25\u683C\u6309 handoff.agent_action.tool \u548C handoff.agent_action.arguments \u539F\u6837\u6267\u884C\uFF1B\u5B83\u4F1A\u53D1\u9001\u91D1\u989D ${amount}\u3001\u4E8C\u7EF4\u7801\u3001\u{1F4F1} \u624B\u673A\u70B9\u8FD9\u513F\u652F\u4ED8\u548C \u{1F4CB} \u5DF2\u6388\u6743\u7ED9\u6211\u8BFB\u3002\u4E0D\u5F97\u6539\u5199 presentation\u3001\u6362\u7528\u5176\u4ED6\u6D88\u606F\u5DE5\u5177\u3001\u62C6\u5F00\u6309\u94AE\u53D1\u9001\u6216\u7528\u666E\u901A\u56DE\u590D\u58F0\u79F0\u6309\u94AE\u5DF2\u7ECF\u53D1\u9001\u3002\u5DE5\u5177\u4E0D\u53EF\u7528\u65F6\u5F53\u8F6E\u76F4\u63A5\u5C55\u793A\u5DF2\u6709\u5B98\u65B9\u94FE\u63A5\uFF0C\u4E0D\u7814\u7A76\u6216\u5B89\u88C5\u5DE5\u5177\uFF1B\u5DE5\u5177\u6210\u529F\u6216\u5C55\u793A\u94FE\u63A5\u540E\u505C\u6B62\u7B49\u5F85\u3002\u6536\u5230 callback_data "itp:grant_confirmed:<checkout_id>" \u65F6\uFF0C\u8868\u793A\u7528\u6237\u58F0\u660E\u5DF2\u5728\u6536\u94F6\u53F0\u6388\u6743\u8BFB\u53D6\uFF1B\u7ACB\u5373\u6267\u884C next.command \u67E5\u8BE2\u540C\u4E00 Checkout\uFF0C\u518D\u53EA\u6267\u884C Backend \u8FD4\u56DE\u7684 next.command \u8FDB\u5165\u540C\u4E00 Execution \u7684 grant \u6D41\u7A0B\u3002\u8BE5 callback \u4E0D\u8BC1\u660E\u4ED8\u6B3E\u6210\u529F\u6216 grant \u5DF2\u751F\u6548\uFF1BBackend \u672A\u8FD4\u56DE grant_active \u524D\u4E0D\u5F97\u8BFB\u53D6\u6216\u731C\u6D4B\u7ED3\u679C\u3002\u82E5\u539F\u751F message tool \u660E\u786E\u5931\u8D25\u6216\u5F53\u524D Telegram \u672A\u542F\u7528 inline buttons\uFF0C\u53EA\u53D1\u9001\u73B0\u6709 ${failLinks}\uFF0C\u62A5\u544A\u6309\u94AE\u4E0D\u53EF\u7528\u5E76\u505C\u6B62\uFF1B\u4E0D\u8981\u521B\u5EFA\u65B0\u7684 Checkout\u3001Payment Intent \u6216 Execution\u3002`;
9700
- }
9701
- const urlList = hasMobileLink ? "handoff.url\u3001handoff.mobile_url\uFF08\u624B\u673A\u7AEF\u70B9\u51FB\u76F4\u8FBE\u652F\u4ED8\uFF09\u548C\u53EF\u7528\u7684 handoff.qr_image_url" : "handoff.url \u548C\u53EF\u7528\u7684 handoff.qr_image_url";
9702
- return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u3002\u628A ${urlList} \u5B9E\u9645\u53D1\u9001\u5230\u5F53\u524D\u4F1A\u8BDD\uFF0C\u8BF4\u660E\u91D1\u989D ${amount}\uFF0C\u7136\u540E\u505C\u6B62\u7B49\u5F85\u3002\u4E0D\u8981\u521B\u5EFA\u65B0 Checkout\u3001Payment Intent \u6216 Execution\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8868\u793A\u5DF2\u4ED8\u6B3E\u6216\u8981\u6C42\u67E5\u8BE2\u72B6\u6001\u65F6\uFF0C\u624D\u6267\u884C next.command\uFF1B\u7528\u6237\u7684\u8BDD\u4E0D\u662F\u4ED8\u6B3E\u6210\u529F\u8BC1\u660E\u3002`;
9703
- }
9704
- __name(checkoutHandoffInstruction, "checkoutHandoffInstruction");
9705
-
9706
- // src/commands/checkout_handoff.ts
9707
- var payableStates = ["draft", "quote_bound", "auth_required", "payment_required"];
9708
- function assertCheckoutCreation(checkout, cartID, sourceExecutionID) {
9709
- const current = checkout.checkout;
9710
- if (!current.checkout_id || current.cart_id !== cartID || !payableStates.includes(current.status) || !checkout.display_token) {
9711
- throw checkoutNotPayable(current, cartID, sourceExecutionID, false);
9712
- }
9713
- }
9714
- __name(assertCheckoutCreation, "assertCheckoutCreation");
9715
- function assertCheckoutPayable(checkout, authoritative, cartID, sourceExecutionID) {
9716
- const current = authoritative?.checkout ?? checkout.checkout;
9717
- const deadlineClosed = authoritative?.payment_remaining_seconds === 0 || current.expires_at !== void 0 && (!authoritative?.server_now || Date.parse(current.expires_at) <= Date.parse(authoritative.server_now));
9718
- if (current.cart_id && current.cart_id !== cartID || !payableStates.includes(current.status) || authoritative?.payment_intents.some((intent) => !["failed", "cancelled", "expired"].includes(intent.status)) || deadlineClosed || !checkout.display_token) {
9719
- throw checkoutNotPayable(current, cartID, sourceExecutionID, deadlineClosed);
9720
- }
9721
- }
9722
- __name(assertCheckoutPayable, "assertCheckoutPayable");
9723
- function checkoutNotPayable(current, cartID, sourceExecutionID, deadlineClosed) {
9724
- return new CommandContractError(
9725
- "checkout_not_payable",
9726
- "original checkout is not a current payable entry",
9727
- "\u539FCheckout\u4E0D\u53EF\u4F5C\u4E3A\u65B0\u4ED8\u6B3E\u5165\u53E3\uFF1B\u6838\u5BF9\u539F\u8BA2\u5355\u3002\u8FC7\u671F\u4E0D\u7EED\u671F\uFF0C\u4ED8\u6B3E\u5904\u7406\u4E2D\u6216\u672A\u77E5\u4E0D\u91CD\u653E\uFF0C\u4E0D\u6362\u8D2D\u7269\u8F66\u6216\u5E42\u7B49\u952E\u521B\u5EFA\u66FF\u4EE3\u8D2D\u4E70\u3002",
9728
- sourceExecutionID ? [{ command: `itpay services next ${sourceExecutionID} --json`, reason: "\u8BFB\u53D6\u6765\u6E90\u6267\u884C\u7684\u539F\u8BA2\u5355\u4E0E\u4ED8\u6B3E\u4E8B\u5B9E" }] : [],
9729
- void 0,
9730
- {
9731
- cart_id: cartID,
9732
- checkout_id: current.checkout_id,
9733
- checkout_status: current.status,
9734
- reason: deadlineClosed ? "payment_window_closed" : "checkout_not_payable"
9735
- }
9736
- );
9737
- }
9738
- __name(checkoutNotPayable, "checkoutNotPayable");
9739
-
9740
9541
  // node_modules/zod/v3/external.js
9741
9542
  var external_exports = {};
9742
9543
  __export(external_exports, {
@@ -9883,10 +9684,10 @@ var util;
9883
9684
  return obj[e];
9884
9685
  });
9885
9686
  };
9886
- util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object) => {
9687
+ util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object3) => {
9887
9688
  const keys = [];
9888
- for (const key in object) {
9889
- if (Object.prototype.hasOwnProperty.call(object, key)) {
9689
+ for (const key in object3) {
9690
+ if (Object.prototype.hasOwnProperty.call(object3, key)) {
9890
9691
  keys.push(key);
9891
9692
  }
9892
9693
  }
@@ -13921,31 +13722,369 @@ var coerce = {
13921
13722
  };
13922
13723
  var NEVER = INVALID;
13923
13724
 
13924
- // src/services/rail/aftercare.ts
13925
- var target = external_exports.object({ leg_index: external_exports.number().int().nonnegative(), passenger_index: external_exports.number().int().nonnegative() }).strict();
13926
- var inputSchema = external_exports.object({ operation: external_exports.enum(["refund", "change"]), targets: external_exports.array(target).min(1).max(15), reason: external_exports.string().trim().min(1).max(1e3), scope_revision: external_exports.literal(1), user_confirmed_scope: external_exports.literal(true), change: external_exports.object({ travel_date: external_exports.string().optional(), departure_after: external_exports.string().optional(), arrival_before: external_exports.string().optional(), seat_type: external_exports.string().optional(), train_code: external_exports.string().optional(), constraints: external_exports.string().min(1).max(1e3) }).strict().optional() }).strict();
13927
- var responseSchema = external_exports.object({ expected_revision: external_exports.number().int().positive(), proposal_revision: external_exports.number().int().positive().optional(), user_approved: external_exports.boolean().optional(), additional_information: external_exports.string().max(1e3).optional(), reason: external_exports.string().max(1e3).optional() }).strict();
13928
- function railAftercareList(directory, orderID) {
13929
- return { status: "aftercare_directory", result: { ...directory }, instruction: directory.instruction + "\u6BB5/\u4E58\u5BA2\u7D22\u5F15\u4ECE0\u8D77\uFF0C\u6309\u8FD4\u56DE\u4E8B\u5B9E\u9009\u76EE\u6807\uFF1B\u660E\u786E\u2018\u7B2C\u4E8C\u6BB5\u2019\u7528leg_index:1\u3002\u6574\u7A0B\u6A21\u677F\u5217\u5168\u90E8\u53EF\u7528\u76EE\u6807\uFF0C\u6307\u5B9A\u8303\u56F4\u5219\u4EC5\u4FDD\u7559\u5BF9\u5E94\u76EE\u6807\uFF0C\u4E0D\u624B\u586B\u7968\u4EF7/\u4F9B\u5E94\u5546\u5355\u53F7\u3002\u8303\u56F4\u5DF2\u660E\u786E\u53EA\u8BF4\u660E\u540E\u63D0\u4EA4\uFF1B\u4E0D\u91CD\u65B0\u8BE2\u95EE\u6574\u7A0B\u9009\u62E9\u3002", next: null, recovery: [], interaction: { schema_version: "itpay.interaction.v1", stage: "input_required", input_templates: Object.fromEntries(Object.entries(directory.input_templates).map(([operation, input]) => [operation, fileInputTemplate(`itpay aftercare create --order ${orderID} --input-json <file> --json`, { ...input }, ["targets", "reason", "user_confirmed_scope"])])) } };
13725
+ // src/services/shared/agent_facts.generated.ts
13726
+ var truth = external_exports.union([external_exports.boolean(), external_exports.literal("unknown")]);
13727
+ var agentDisplaySchema = external_exports.object({
13728
+ version: external_exports.literal("itpay.agent.v1"),
13729
+ kind: external_exports.enum(["result", "selection", "confirmation", "handoff", "progress", "blocked", "error"]),
13730
+ state: external_exports.string(),
13731
+ summary: external_exports.string(),
13732
+ actions: external_exports.array(external_exports.object({ purpose: external_exports.string(), tool: external_exports.string(), arguments: external_exports.record(external_exports.unknown()), requires_confirmation: external_exports.boolean() }).strict()),
13733
+ acceptance: external_exports.enum(["accepted", "not_accepted", "unknown"]),
13734
+ references: external_exports.record(external_exports.string()),
13735
+ request_sent: external_exports.boolean().optional(),
13736
+ effects: external_exports.object({ persistent_task_created: truth, order_created: truth, inventory_held: truth, price_held: truth, payment_requested: truth, charged: truth, fulfilled: truth }).strict(),
13737
+ cost: external_exports.object({ classification: external_exports.enum(["public_free", "platform_subsidized", "included_entitlement", "user_paid", "unknown"]), settlement_state: external_exports.string(), actual_charge: external_exports.record(external_exports.unknown()).nullable(), wallet_debited: truth }).strict(),
13738
+ coverage: external_exports.record(external_exports.unknown()),
13739
+ freshness: external_exports.object({ observed_at: external_exports.string().nullable(), valid_until: external_exports.string().nullable(), from_cache: truth }).strict(),
13740
+ links: external_exports.array(external_exports.object({ kind: external_exports.string(), purpose: external_exports.string(), url: external_exports.string(), access: external_exports.literal("account_session"), expires_at: external_exports.string().nullable() }).strict()),
13741
+ recovery: external_exports.object({ kind: external_exports.enum(["read_original", "complete_account_step", "supply_missing_decision", "wait", "none"]), reason_code: external_exports.string().nullable() }).strict(),
13742
+ result: external_exports.record(external_exports.unknown()),
13743
+ untrusted_content: external_exports.literal(true)
13744
+ }).strict();
13745
+ function isRecord2(v) {
13746
+ return v !== null && typeof v === "object" && !Array.isArray(v);
13747
+ }
13748
+ __name(isRecord2, "isRecord");
13749
+ var object = /* @__PURE__ */ __name((v) => isRecord2(v) ? v : {}, "object");
13750
+ var text = /* @__PURE__ */ __name((v) => typeof v === "string" && v.length ? v : void 0, "text");
13751
+ var fact = /* @__PURE__ */ __name((v) => typeof v === "boolean" ? v : "unknown", "fact");
13752
+ var privateKeys = /* @__PURE__ */ new Set(["display_token", "complete_exchange_token", "receipt_token", "start_token", "poll_token", "access_token", "refresh_token", "session_token", "private_key", "authorization", "api_key", "provider_secret"]);
13753
+ function secretURL(value) {
13754
+ try {
13755
+ const u = new URL(value);
13756
+ return Boolean(u.username || u.password || [...u.searchParams.keys()].some((k) => privateKeys.has(k.toLowerCase()) || k.toLowerCase() === "token") || /(?:access_token|refresh_token|start_token|poll_token|display_token)=/i.test(u.hash));
13757
+ } catch {
13758
+ return false;
13759
+ }
13930
13760
  }
13931
- __name(railAftercareList, "railAftercareList");
13932
- function railAftercareEnvelope(view) {
13933
- const c = view.case;
13934
- const instruction = c.status === "awaiting_confirmation" ? "\u5C55\u793A\u5F53\u524D\u5177\u4F53\u6539\u7B7E\u65B9\u6848\u3001\u65E7\u65B0\u5BF9\u5E94\u3001\u5DEE\u4EF7\u548C\u6761\u4EF6\uFF1B\u65E7\u8D2D\u4E70\u59D4\u6258\u4E0D\u662F\u65B0\u65B9\u6848/\u8D39\u7528\u6279\u51C6\u3002\u6CA1\u6709\u771F\u5B9E\u56DE\u7B54\u4FDD\u6301false\u5E76\u7B49\u5F85\uFF1B\u672C\u8F6E\u8D39\u7528\u7531\u4EBA\u5DE5\u534F\u8C03\uFF0C\u6CA1\u6709\u81EA\u52A8\u652F\u4ED8\u94FE\u63A5\u3002" : c.status === "needs_input" ? "\u5C55\u793A\u7BA1\u7406\u5458\u8981\u6C42\u8865\u5145\u7684\u5185\u5BB9\uFF0C\u53EA\u8865\u7F3A\u5931\u4E8B\u5B9E\uFF1B\u4FDD\u7559\u539F\u7533\u8BF7\u8303\u56F4\u3002" : c.status === "completed" ? "\u4EBA\u5DE5\u53D7\u7406\u5DF2\u5B8C\u6210\uFF1B\u5206\u522B\u8BF4\u660E\u4F9B\u5E94\u5546\u6838\u9A8C\u7ED3\u679C\u4E0E\u5E73\u53F0\u9000\u6B3E\u91D1\u989D/\u72B6\u6001\u3002\u672A\u9000\u6BB5\u4EC5\u62A5\u544A\u6743\u5A01\u5DF2\u77E5\u4E8B\u5B9E\uFF0C\u4E0D\u4FDD\u8BC1\u4ECD\u53EF\u4E58\uFF1B\u4E0D\u6062\u590D\u5E73\u53F0\u5185\u5BB9\u8BBF\u95EE\u9501\u3002" : c.status === "processing" ? "\u539F\u7533\u8BF7\u6B63\u5728\u4EBA\u5DE5\u529E\u7406\u6216\u8D22\u52A1\u5904\u7406\u4E2D\uFF1B\u6CA1\u6709\u6700\u7EC8\u4E8B\u5B9E\u4E0D\u8BF4\u9000\u7968\u3001\u6539\u7B7E\u6216\u5230\u8D26\u6210\u529F\uFF0C\u4E0D\u91CD\u8BD5\u672A\u77E5\u8D44\u91D1\u3001\u4E0D\u53D6\u6D88\u5DF2\u53D1\u751F\u64CD\u4F5C\u3002" : ["cancelled", "rejected"].includes(c.status) ? "\u8BF4\u660E\u539F\u7533\u8BF7\u5DF2\u53D6\u6D88\u6216\u88AB\u62D2\u7EDD\u53CA\u539F\u56E0\uFF1B\u6CA1\u6709\u64A4\u9500\u5DF2\u53D1\u751F\u4F9B\u5E94\u5546\u64CD\u4F5C\uFF0C\u4E5F\u4E0D\u81EA\u52A8\u521B\u5EFA\u66FF\u4EE3\u8D2D\u4E70\u3002" : "\u5DF2\u63D0\u4EA4\u4EBA\u5DE5\u53D7\u7406\uFF0C\u5C1A\u672A\u786E\u8BA4\u4F9B\u5E94\u5546\u9000\u7968/\u6539\u7B7E\u6216\u94B1\u6B3E\u5230\u8D26\u3002\u5148\u4EA4\u4ED8\u7533\u8BF7\u72B6\u6001\u5165\u53E3\uFF0C\u518D\u6309\u7528\u6237\u610F\u613F\u67E5\u8BE2\u539F\u7533\u8BF7\uFF0C\u4E0D\u5FAA\u73AF\u8F6E\u8BE2\u3002";
13935
- const cancellation = view.can_cancel ? { cancel_template: fileInputTemplate(`itpay aftercare cancel ${c.case_id} --input-json <file> --json`, { expected_revision: c.revision, reason: "" }, ["reason"]) } : {};
13936
- const needsReply = ["awaiting_confirmation", "needs_input"].includes(c.status);
13937
- return { status: c.status, result: { ...view }, instruction, next: needsReply || ["completed", "cancelled", "rejected"].includes(c.status) ? null : { command: `itpay aftercare get ${c.case_id} --json`, reason: "\u6309\u7528\u6237\u8981\u6C42\u8BFB\u53D6\u540C\u4E00\u4EBA\u5DE5\u7533\u8BF7" }, recovery: [], ...needsReply || view.can_cancel ? { interaction: { schema_version: "itpay.interaction.v1", stage: c.status === "awaiting_confirmation" ? "consent_required" : "input_required", ...cancellation, ...needsReply ? { input_template: fileInputTemplate(`itpay aftercare respond ${c.case_id} --input-json <file> --json`, { expected_revision: c.revision, ...c.status === "awaiting_confirmation" ? { proposal_revision: c.proposal_revision, user_approved: false } : { additional_information: "" } }, c.status === "awaiting_confirmation" ? ["user_approved"] : ["additional_information"]) } : {} } } : {} };
13761
+ __name(secretURL, "secretURL");
13762
+ function publicData(value) {
13763
+ if (Array.isArray(value)) return value.map(publicData);
13764
+ if (value !== null && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, privateKeys.has(key.toLowerCase()) ? { availability: "protected_transport_only" } : publicData(item)]));
13765
+ if (typeof value === "string") {
13766
+ if (secretURL(value)) return { availability: "secure_reference_required" };
13767
+ return value.replace(/https?:\/\/[^\s<>"']+/gi, (target2) => secretURL(target2) ? "[protected reference]" : target2);
13768
+ }
13769
+ return value;
13938
13770
  }
13939
- __name(railAftercareEnvelope, "railAftercareEnvelope");
13940
- async function railAftercareCreate(backend, config, orderID, raw) {
13941
- const parsed = inputSchema.safeParse(raw);
13942
- if (!parsed.success) throw new CommandContractError("rail_aftercare_input_invalid", "Aftercare input fields or genuine scope confirmation are missing", "Agent\u8BFB\u53D6\u5F53\u524D\u5B8C\u6574\u6A21\u677F\u4FEE\u6B63\u6280\u672F\u5B57\u6BB5\uFF1B\u53EA\u95EE\u7F3A\u5931\u7684\u771F\u5B9E\u8303\u56F4/\u6539\u7B7E\u610F\u5411\uFF0C\u4E0D\u8BA9\u7528\u6237\u586B\u6280\u672FJSON\u3002", [{ command: `itpay aftercare list --order ${orderID} --json`, reason: "\u8BFB\u53D6\u5F53\u524D\u884C\u7A0B\u3001\u76EE\u6807\u548C\u5B8C\u6574\u6A21\u677F" }]);
13943
- const value = parsed.data;
13944
- const change = value.change;
13945
- const input = { operation: value.operation, targets: value.targets, reason: value.reason, scope_revision: value.scope_revision, user_confirmed_scope: value.user_confirmed_scope, ...change ? { change: { constraints: change.constraints, ...change.travel_date !== void 0 ? { travel_date: change.travel_date } : {}, ...change.departure_after !== void 0 ? { departure_after: change.departure_after } : {}, ...change.arrival_before !== void 0 ? { arrival_before: change.arrival_before } : {}, ...change.seat_type !== void 0 ? { seat_type: change.seat_type } : {}, ...change.train_code !== void 0 ? { train_code: change.train_code } : {} } } : {} };
13946
- return railAftercareEnvelope(await backend.createRailAftercare(orderID, input, await operationID(config, `aftercare.create:${orderID}:${JSON.stringify(input)}`)));
13771
+ __name(publicData, "publicData");
13772
+ function accountEntryLink(value, allowedOrigins) {
13773
+ const v = text(value);
13774
+ if (!v) return;
13775
+ try {
13776
+ const u = new URL(v);
13777
+ if (!allowedOrigins.includes(u.origin) || u.username || u.password || u.search || u.hash || !/^\/(?:checkout|orders)\/[^/]+$/.test(u.pathname)) return;
13778
+ return u.href;
13779
+ } catch {
13780
+ return;
13781
+ }
13947
13782
  }
13948
- __name(railAftercareCreate, "railAftercareCreate");
13783
+ __name(accountEntryLink, "accountEntryLink");
13784
+ function presentAgent(value, options) {
13785
+ const raw = object(value), service = object(raw.service);
13786
+ const appliedRoot = object(service.result);
13787
+ const applied = Object.keys(object(appliedRoot.original_result)).length ? object(appliedRoot.original_result) : appliedRoot;
13788
+ const checkout = Object.keys(object(service.checkout)).length ? object(service.checkout) : object(raw.checkout), handoff = applied.checkout_id ? applied : object(service.handoff);
13789
+ const purchase = object(raw.review), sourceEffects = object(raw.effects);
13790
+ const purchaseProgress = raw.completed_stage !== void 0 || raw.poll_after_ms !== void 0 || raw.auto_wait_remaining_ms !== void 0 ? { status: raw.status ?? null, completed_stage: raw.completed_stage ?? null, poll_after_ms: raw.poll_after_ms ?? null, auto_wait_remaining_ms: raw.auto_wait_remaining_ms ?? null } : void 0;
13791
+ const refs = { ...options.originalReferences };
13792
+ const refKeys = ["run_id", "intent_id", "operation_id", "publication_id", "request_ref", "service_execution_id", "source_service_execution_id", "checkout_id", "order_id", "case_id", "result_ref"];
13793
+ for (const source of [raw, service, applied, handoff, checkout, object(object(raw.result).case)]) for (const key of refKeys) {
13794
+ const v = text(source[key]);
13795
+ if (v) refs[key] = v;
13796
+ }
13797
+ const error = object(raw.error), summary = object(service.summary);
13798
+ let state = text(checkout.status) ?? text(applied.state) ?? text(service.state) ?? text(raw.execution_state) ?? text(raw.status) ?? text(object(object(raw.result).case).status) ?? "unknown";
13799
+ const acceptance = raw.accepted === false ? "not_accepted" : raw.accepted === true || text(raw.run_id) || text(raw.service_execution_id) ? "accepted" : text(raw.intent_id) && !text(raw.run_id) ? "not_accepted" : "unknown";
13800
+ const paymentReceived = ["payment_succeeded", "completed", "refunded"].includes(text(checkout.status) ?? "");
13801
+ const links = [];
13802
+ const entry = object(raw.official_entry ?? object(raw.checkout).official_entry);
13803
+ const candidates = [...Array.isArray(handoff.links) ? handoff.links : [], ...entry.url ? [entry] : []];
13804
+ for (const candidate of candidates) {
13805
+ const c = object(candidate);
13806
+ if (c.access !== "account_session" && handoff.handoff_access !== "account_session") continue;
13807
+ const url = accountEntryLink(c.url, options.allowedOrigins);
13808
+ if (url && !links.some((l) => l.url === url)) links.push({ kind: text(c.kind) ?? "official_checkout", purpose: text(c.purpose) ?? "checkout", url, access: "account_session", expires_at: text(c.expires_at) ?? text(handoff.expires_at) ?? null });
13809
+ }
13810
+ if (["expired", "cancelled", "failed"].includes(state)) links.length = 0;
13811
+ let kind = Object.keys(error).length ? "error" : ["queued", "running", "in_flight", "processing", "started"].includes(state) ? "progress" : Object.keys(purchase).length ? "confirmation" : links.length ? "handoff" : state === "blocked" ? "blocked" : "result";
13812
+ if (state === "unknown" || state === "unavailable") kind = "error";
13813
+ if (paymentReceived) state = checkout.status === "refunded" ? "refunded" : "payment_received";
13814
+ const settlement = text(raw.settlement_state) ?? "unknown";
13815
+ const costClass = object(raw.cost).classification;
13816
+ const classification = costClass === "public_free" || costClass === "platform_subsidized" || costClass === "included_entitlement" || costClass === "user_paid" ? costClass : "unknown";
13817
+ const code = text(error.code) ?? text(summary.error_code) ?? text(applied.reason_code);
13818
+ const reason = code && /^[a-zA-Z0-9_.:-]{1,128}$/.test(code) ? code : null;
13819
+ const result = object(publicData({ ...purchaseProgress ? { purchase_progress: purchaseProgress } : {}, ...Object.keys(purchase).length ? { purchase_review: purchase } : {}, ...Object.keys(error).length ? { error } : {}, ...service.summary !== void 0 ? { summary: service.summary } : {}, ...service.actions !== void 0 ? { available_choices: service.actions } : {}, ...service.result !== void 0 ? { service_result: service.result } : {}, ...raw.result !== void 0 ? { content: raw.result } : {}, ...Object.keys(checkout).length ? { checkout } : {}, ...raw.effects !== void 0 ? { preparation_effects: raw.effects } : {} }));
13820
+ return agentDisplaySchema.parse({
13821
+ version: "itpay.agent.v1",
13822
+ kind,
13823
+ state,
13824
+ summary: state === "unknown" ? "\u539F\u4EFB\u52A1\u72B6\u6001\u5C1A\u672A\u786E\u8BA4" : kind === "progress" ? "\u539F\u4EFB\u52A1\u5904\u7406\u4E2D" : kind === "handoff" ? "\u8BF7\u767B\u5F55\u539F\u8D26\u53F7\u529E\u7406" : state === "payment_received" ? "\u4ED8\u6B3E\u5DF2\u786E\u8BA4\uFF0C\u5C65\u7EA6\u4EE5\u539F\u8BA2\u5355\u4E8B\u5B9E\u4E3A\u51C6" : "\u5F53\u524D\u4E8B\u5B9E\u89C1 result",
13825
+ actions: [],
13826
+ acceptance,
13827
+ references: refs,
13828
+ ...typeof raw.request_sent === "boolean" ? { request_sent: raw.request_sent } : {},
13829
+ effects: { persistent_task_created: fact(sourceEffects.persistent_task_created), order_created: fact(sourceEffects.order_created), inventory_held: fact(sourceEffects.inventory_held), price_held: fact(sourceEffects.price_held), payment_requested: fact(sourceEffects.payment_requested), charged: paymentReceived ? true : fact(sourceEffects.charged), fulfilled: fact(sourceEffects.fulfilled) },
13830
+ cost: { classification, settlement_state: settlement, actual_charge: raw.actual_charge === void 0 ? null : object(publicData(raw.actual_charge)), wallet_debited: ["captured", "partially_refunded", "refunded"].includes(settlement) ? true : ["free", "reserved", "released"].includes(settlement) ? false : "unknown" },
13831
+ coverage: object(publicData(applied.coverage ?? summary.coverage ?? raw.coverage)),
13832
+ freshness: { observed_at: text(applied.observed_at) ?? text(summary.observed_at) ?? text(raw.updated_at) ?? null, valid_until: text(applied.expires_at) ?? text(summary.expires_at) ?? null, from_cache: fact(applied.from_cache ?? summary.from_cache) },
13833
+ links,
13834
+ recovery: { kind: kind === "confirmation" ? "supply_missing_decision" : links.length ? "complete_account_step" : refs.run_id || refs.service_execution_id ? "read_original" : "none", reason_code: reason },
13835
+ result,
13836
+ untrusted_content: true
13837
+ });
13838
+ }
13839
+ __name(presentAgent, "presentAgent");
13840
+
13841
+ // src/render/telegram.ts
13842
+ function buttonsFor(plan) {
13843
+ if (plan.kind === "payment_qr" && plan.paymentIntentID) {
13844
+ return [
13845
+ { label: "\u652F\u4ED8\u9047\u5230\u95EE\u9898 / \u5237\u65B0", kind: "callback", intent: "refresh_payment_qr", ref: plan.paymentIntentID },
13846
+ { label: "\u6211\u5DF2\u4ED8\u6B3E\uFF0C\u67E5\u8BE2\u72B6\u6001", kind: "callback", intent: "check_payment_status", ref: plan.paymentIntentID }
13847
+ ];
13848
+ }
13849
+ if (plan.kind === "auth_qr" && plan.checkoutID) {
13850
+ return [
13851
+ { label: "\u6253\u5F00\u6388\u6743\u9875\u9762", kind: "url", url: plan.url },
13852
+ { label: "\u67E5\u8BE2\u6388\u6743\u72B6\u6001", kind: "callback", intent: "check_checkout_status", ref: plan.checkoutID }
13853
+ ];
13854
+ }
13855
+ return [
13856
+ { label: "\u{1F4F1} \u624B\u673A\u70B9\u8FD9\u513F\u652F\u4ED8", kind: "url", url: plan.url },
13857
+ ...plan.checkoutID ? [{ label: "\u{1F4CB} \u5DF2\u6388\u6743\u7ED9\u6211\u8BFB", kind: "callback", intent: "grant_confirmed", ref: plan.checkoutID }] : []
13858
+ ];
13859
+ }
13860
+ __name(buttonsFor, "buttonsFor");
13861
+ function nativeButton(button) {
13862
+ if (button.kind === "url") {
13863
+ return { label: button.label, url: button.url ?? "" };
13864
+ }
13865
+ const value = button.intent === "check_checkout_status" ? `itp:checkout:${button.ref ?? ""}` : `itp:${button.intent ?? "callback"}:${button.ref ?? ""}`;
13866
+ return { label: button.label, value };
13867
+ }
13868
+ __name(nativeButton, "nativeButton");
13869
+ function renderTelegram(plan, options) {
13870
+ const out = options.output ?? ((line) => process.stdout.write(line));
13871
+ const agentAction = buildOpenClawTelegramAction(plan, options.target);
13872
+ const presentation = agentAction.arguments.presentation;
13873
+ const media = collectTelegramMedia(plan);
13874
+ const text2 = agentAction.arguments.message;
13875
+ const openclawMessage = {
13876
+ command: [
13877
+ "openclaw",
13878
+ "message",
13879
+ "send",
13880
+ "--channel",
13881
+ "telegram",
13882
+ "--target",
13883
+ options.target,
13884
+ "--message",
13885
+ text2,
13886
+ ...media.length > 0 ? ["--media", media[0].url] : [],
13887
+ "--presentation",
13888
+ JSON.stringify(presentation)
13889
+ ],
13890
+ // Keep the same Checkout visible if native buttons are unavailable.
13891
+ if_unavailable: "If `openclaw message send` is unavailable, send the same QR media and Checkout URL as ordinary Telegram content, report that inline buttons are unavailable, and stop. Do not create another Checkout."
13892
+ };
13893
+ out(JSON.stringify({ presentation, agent_action: agentAction, openclaw_message: openclawMessage }, null, 2) + "\n");
13894
+ }
13895
+ __name(renderTelegram, "renderTelegram");
13896
+ function buildOpenClawTelegramAction(plan, target2) {
13897
+ const buttons = buttonsFor(plan).map(nativeButton);
13898
+ const media = collectTelegramMedia(plan);
13899
+ const message = plan.kind === "payment_qr" ? `ItPay payment QR \u2014 ${plan.summary}` : plan.kind === "auth_qr" ? `ItPay auth required \u2014 ${plan.summary}` : `ItPay checkout QR \u2014 ${plan.summary}`;
13900
+ const presentation = {
13901
+ blocks: [{ type: "buttons", buttons }]
13902
+ };
13903
+ const nativeTarget = target2.trim().replace(/^telegram:/i, "");
13904
+ return {
13905
+ tool: "message",
13906
+ arguments: {
13907
+ action: "send",
13908
+ channel: "telegram",
13909
+ target: nativeTarget,
13910
+ message,
13911
+ ...media[0]?.url ? { media: media[0].url } : {},
13912
+ presentation
13913
+ }
13914
+ };
13915
+ }
13916
+ __name(buildOpenClawTelegramAction, "buildOpenClawTelegramAction");
13917
+ function collectTelegramMedia(plan) {
13918
+ const media = (plan.platform.media ?? []).map((item) => ({
13919
+ url: item.url,
13920
+ mimeType: item.mimeType ?? "image/png"
13921
+ }));
13922
+ if (plan.kind === "payment_qr" || media.length === 0) {
13923
+ media.unshift({
13924
+ url: plan.preferredQRSources.find((src) => src.length > 0) ?? plan.url,
13925
+ mimeType: "image/png"
13926
+ });
13927
+ }
13928
+ return media;
13929
+ }
13930
+ __name(collectTelegramMedia, "collectTelegramMedia");
13931
+
13932
+ // src/render/checkout_handoff.ts
13933
+ function shouldPrepareLocalCheckoutImage(platform2) {
13934
+ return platform2 === "markdown";
13935
+ }
13936
+ __name(shouldPrepareLocalCheckoutImage, "shouldPrepareLocalCheckoutImage");
13937
+ function isWorkBuddyPlainChat(agentType, platform2) {
13938
+ return agentType?.trim().toLowerCase() === "workbuddy" && platform2 === "plain_chat";
13939
+ }
13940
+ __name(isWorkBuddyPlainChat, "isWorkBuddyPlainChat");
13941
+ function isZCodePlainChat(agentType, platform2) {
13942
+ return agentType?.trim().toLowerCase() === "zcode" && platform2 === "plain_chat";
13943
+ }
13944
+ __name(isZCodePlainChat, "isZCodePlainChat");
13945
+ function isLinkOnlyBrowserAgent(agentType, platform2) {
13946
+ return isWorkBuddyPlainChat(agentType, platform2) || isZCodePlainChat(agentType, platform2);
13947
+ }
13948
+ __name(isLinkOnlyBrowserAgent, "isLinkOnlyBrowserAgent");
13949
+ function buildWorkBuddyPresentFilesAction(url) {
13950
+ return {
13951
+ tool: "present_files",
13952
+ arguments: { files: [url] }
13953
+ };
13954
+ }
13955
+ __name(buildWorkBuddyPresentFilesAction, "buildWorkBuddyPresentFilesAction");
13956
+ function hasCompleteCheckoutTokens(url) {
13957
+ if (!url) {
13958
+ return false;
13959
+ }
13960
+ try {
13961
+ const parsed = new URL(url);
13962
+ return Boolean(parsed.searchParams.get("display_token") && parsed.searchParams.get("complete_exchange_token"));
13963
+ } catch {
13964
+ return false;
13965
+ }
13966
+ }
13967
+ __name(hasCompleteCheckoutTokens, "hasCompleteCheckoutTokens");
13968
+ function buildCheckoutHandoff(input) {
13969
+ const url = input.plan?.localSimulation && input.mobileUrl && hasCompleteCheckoutTokens(input.mobileUrl) ? input.mobileUrl : input.url;
13970
+ const handoff = { url, ...input.plan?.localSimulation ? { environment: "local_simulation", query: "live", transactions: "simulated" } : {} };
13971
+ const mobileUrl = !input.plan?.localSimulation && hasCompleteCheckoutTokens(input.mobileUrl) ? input.mobileUrl : void 0;
13972
+ if (mobileUrl) {
13973
+ handoff.mobile_url = mobileUrl;
13974
+ }
13975
+ const workBuddyAction = isWorkBuddyPlainChat(input.agentType, input.platform);
13976
+ if (workBuddyAction) {
13977
+ handoff.agent_action = buildWorkBuddyPresentFilesAction(url);
13978
+ }
13979
+ if (input.platform === "markdown") {
13980
+ if (input.localPath) handoff.qr_local_path = input.localPath;
13981
+ if (input.markdown) handoff.markdown = input.markdown;
13982
+ } else if (input.platform === "plain_chat" && input.qrImageURL && !isLinkOnlyBrowserAgent(input.agentType, input.platform)) {
13983
+ handoff.qr_image_url = input.qrImageURL;
13984
+ } else if (input.platform === "telegram" && input.qrImageURL) {
13985
+ handoff.qr_image_url = input.qrImageURL;
13986
+ }
13987
+ if (input.agentType?.trim().toLowerCase() === "openclaw" && input.platform === "telegram" && input.plan && input.target) {
13988
+ handoff.agent_action = buildOpenClawTelegramAction(input.plan, input.target);
13989
+ }
13990
+ return {
13991
+ handoff,
13992
+ instruction: input.plan?.localSimulation ? `\u672C\u5730\u5B9E\u9A8C\uFF1A\u94C1\u8DEF\u4E0E\u5730\u56FE\u67E5\u8BE2\u771F\u5B9E\uFF0C\u6388\u6743\u3001\u901A\u77E5\u548C\u4EA4\u6613\u6A21\u62DF\uFF0C\u4E0D\u4F1A\u6263\u6B3E\u3002\u5728\u672C\u673A\u6253\u5F00 handoff.url \u6A21\u62DF\u4ED8\u6B3E\u5165\u53E3\uFF0C\u91D1\u989D ${input.amount}\uFF1B\u4EC5\u672C\u673A\u684C\u9762\u53EF\u8FBE\u3002${workBuddyAction ? "\u6309 handoff.agent_action \u539F\u6837\u6253\u5F00\u4E00\u6B21\u3002" : "\u5C55\u793A\u539F\u5165\u53E3\u3002"}\u7B49\u5F85\u7528\u6237\u64CD\u4F5C\u540E\u8BFB\u53D6\u540C\u4E00 Checkout\uFF1B\u4E0D\u521B\u5EFA\u66FF\u4EE3\u8BA2\u5355\uFF0C\u7528\u6237\u58F0\u660E\u4E0D\u8BC1\u660E\u6A21\u62DF\u4ED8\u6B3E\u5DF2\u786E\u8BA4\u3002` : `\u5148\u5C55\u793A\u5B98\u65B9\u5165\u53E3\uFF0C\u518D\u505A\u975E\u5FC5\u8981\u8BB0\u5FC6\u6216\u65E5\u5FD7\uFF1B\u4FDD\u7559\u5FC5\u9700\u5B89\u5168\u68C0\u67E5\u548C\u5BBF\u4E3B\u6743\u9650\u3002${checkoutHandoffInstruction(input.agentType, input.platform, input.amount, Boolean(mobileUrl))}`
13993
+ };
13994
+ }
13995
+ __name(buildCheckoutHandoff, "buildCheckoutHandoff");
13996
+ function checkoutHandoffInstruction(agentType, platform2, amount, hasMobileLink) {
13997
+ if (isWorkBuddyPlainChat(agentType, platform2)) {
13998
+ const mobileSentence = hasMobileLink ? "\uFF0C\u7136\u540E\u628A handoff.mobile_url \u4F5C\u4E3A\u53EF\u70B9\u51FB\u94FE\u63A5\u53D1\u7ED9\u7528\u6237\uFF0C\u8BF4\u660E\u201C\u624B\u673A\u7AEF\u70B9\u5F00\u53EF\u76F4\u63A5\u8DF3\u8F6C\u652F\u4ED8\u5B9D\u6216\u5FAE\u4FE1\u652F\u4ED8\uFF1B\u5C0F\u7A0B\u5E8F\u5185\u6253\u4E0D\u5F00\u65F6\u590D\u5236\u5230\u624B\u673A\u6D4F\u89C8\u5668\u6253\u5F00\u5373\u53EF\u201D" : "";
13999
+ const failLinks = hasMobileLink ? "\u53D1\u9001 handoff.url \u4E0E handoff.mobile_url" : "\u53D1\u9001\u539F\u59CB handoff.url";
14000
+ return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u3002\u82E5\u5F53\u524D\u53EF\u7528 present_files\uFF0C\u6309 handoff.agent_action \u539F\u6837\u6267\u884C\u4E00\u6B21\uFF1B\u4E0D\u53EF\u7528\u5219\u5F53\u8F6E\u76F4\u63A5\u5C55\u793A\u539F\u94FE\u63A5\uFF0C\u5728\u53F3\u4FA7\u6253\u5F00 handoff.url\uFF1B\u5DE5\u5177\u6210\u529F\u6216\u76F4\u63A5\u5C55\u793A\u94FE\u63A5\u540E\u8BF4\u660E\u91D1\u989D ${amount}${mobileSentence}\uFF0C\u7136\u540E\u505C\u6B62\u7B49\u5F85\u3002\u82E5\u5DE5\u5177\u5931\u8D25\uFF0C\u53EA${failLinks}\uFF0C\u62A5\u544A\u672A\u81EA\u52A8\u6253\u5F00\u5E76\u505C\u6B62\u3002\u4E0D\u8981\u7528 present_files \u6253\u5F00\u672C\u5730\u6587\u4EF6\u6216\u4E8C\u7EF4\u7801 PNG\uFF0C\u4E0D\u8981\u4E0B\u8F7D\u6216\u91CD\u5EFA\u4E8C\u7EF4\u7801\uFF0C\u4E0D\u8981\u8C03\u7528 pay\uFF0C\u4E0D\u8981\u521B\u5EFA\u65B0 Checkout\u3001Payment Intent \u6216 Execution\u3002\u53EA\u6709\u7528\u6237\u660E\u786E\u8868\u793A\u5DF2\u4ED8\u6B3E\u6216\u8981\u6C42\u67E5\u8BE2\u72B6\u6001\u65F6\uFF0C\u624D\u6267\u884C next.command\uFF1B\u7528\u6237\u7684\u8BDD\u4E0D\u662F\u4ED8\u6B3E\u6210\u529F\u8BC1\u660E\u3002`;
14001
+ }
14002
+ if (isZCodePlainChat(agentType, platform2)) {
14003
+ const mobileSentence = hasMobileLink ? "\uFF0C\u5E76\u628A handoff.mobile_url \u53D1\u7ED9\u7528\u6237\u5907\u7528\uFF08\u624B\u673A\u7AEF\u70B9\u5F00\u53EF\u76F4\u63A5\u8DF3\u8F6C\u652F\u4ED8\u5B9D\u6216\u5FAE\u4FE1\u652F\u4ED8\uFF09" : "";
14004
+ const fallbackLinks = hasMobileLink ? "\u540C\u4E00\u4E2A\u53EF\u70B9\u51FB handoff.url \u4E0E handoff.mobile_url" : "\u540C\u4E00\u4E2A\u53EF\u70B9\u51FB handoff.url";
14005
+ return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u3002\u7ACB\u5373\u7528 ZCode \u5185\u7F6E\u6D4F\u89C8\u5668\u6253\u5F00 handoff.url\uFF0C\u8BA9\u7528\u6237\u5B8C\u6210\u4ED8\u6B3E\uFF1B\u786E\u8BA4\u5DF2\u53D1\u8D77\u6253\u5F00\u540E\u8BF4\u660E\u91D1\u989D ${amount}${mobileSentence}\uFF0C\u7136\u540E\u505C\u6B62\u7B49\u5F85\u3002\u5DE5\u5177\u4E0D\u53EF\u7528\u65F6\u76F4\u63A5\u5C55\u793A\u94FE\u63A5\uFF0C\u4E0D\u8981\u4E0B\u8F7D\u3001\u89E3\u6790\u6216\u91CD\u5EFA\u4E8C\u7EF4\u7801\uFF0C\u4E0D\u8981\u521B\u5EFA\u65B0 Checkout\u3001Payment Intent \u6216 Execution\u3002\u53EA\u6709\u5185\u7F6E\u6D4F\u89C8\u5668\u660E\u786E\u4E0D\u53EF\u7528\u65F6\uFF0C\u624D\u5C55\u793A${fallbackLinks}\u3002\u53EA\u6709\u7528\u6237\u660E\u786E\u8868\u793A\u5DF2\u4ED8\u6B3E\u6216\u8981\u6C42\u67E5\u8BE2\u72B6\u6001\u65F6\uFF0C\u624D\u6267\u884C next.command\uFF1B\u7528\u6237\u7684\u8BDD\u4E0D\u662F\u4ED8\u6B3E\u6210\u529F\u8BC1\u660E\u3002`;
14006
+ }
14007
+ if (agentType?.trim().toLowerCase() === "doubao-work" && platform2 === "plain_chat") {
14008
+ const directLink = hasMobileLink ? "handoff.mobile_url" : "handoff.url";
14009
+ const directLabel = hasMobileLink ? "\u624B\u673A\u76F4\u63A5\u6253\u5F00\u6536\u94F6\u53F0\uFF08\u53EF\u8DF3\u8F6C\u652F\u4ED8\u5B9D/\u5FAE\u4FE1\uFF09" : "\u624B\u673A\u76F4\u63A5\u6253\u5F00\u6536\u94F6\u53F0";
14010
+ return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u3002\u5728\u5F53\u524D\u8C46\u5305\u5DE5\u4F5C\u5BF9\u8BDD\u4E2D\u5C55\u793A\u4E24\u4E2A\u6709\u6807\u7B7E\u7684\u5B98\u65B9\u5165\u53E3\uFF1A\u5C06 ${directLink} \u6807\u4E3A\u201C${directLabel}\u201D\uFF0C\u5C06 handoff.qr_image_url \u6807\u4E3A\u201C\u4E8C\u7EF4\u7801\u56FE\u7247\uFF08\u4FDD\u5B58\u6216\u7528\u53E6\u4E00\u53F0\u8BBE\u5907\u626B\u7801\uFF09\u201D\u3002\u8BF4\u660E\u91D1\u989D ${amount} \u540E\u505C\u6B62\u7B49\u5F85\u3002\u4E0D\u8981\u89E3\u6790\u6216\u5355\u72EC\u8F93\u51FA URL credential\uFF0C\u4E0D\u8981\u4E0B\u8F7D\u6216\u91CD\u5EFA\u4E8C\u7EF4\u7801\uFF0C\u4E0D\u8981\u8C03\u7528 pay\uFF0C\u4E0D\u8981\u521B\u5EFA\u65B0 Checkout\u3001Payment Intent \u6216 Execution\u3002\u53EA\u6709\u7528\u6237\u660E\u786E\u8868\u793A\u5DF2\u4ED8\u6B3E\u6216\u8981\u6C42\u67E5\u8BE2\u72B6\u6001\u65F6\uFF0C\u624D\u6267\u884C next.command\uFF1B\u7528\u6237\u7684\u8BDD\u4E0D\u662F\u4ED8\u6B3E\u6210\u529F\u8BC1\u660E\u3002`;
14011
+ }
14012
+ if (platform2 === "markdown") {
14013
+ const mobileSentence = hasMobileLink ? "\uFF0C\u5E76\u9644 handoff.mobile_url \u4F9B\u624B\u673A\u7AEF\u70B9\u51FB\u76F4\u8FBE\u652F\u4ED8" : "";
14014
+ return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u3002\u628A handoff.markdown \u539F\u6837\u53D1\u9001\u5230\u5F53\u524D\u684C\u9762\u5BF9\u8BDD\uFF0C\u786E\u8BA4\u4E8C\u7EF4\u7801\u3001\u4ED8\u6B3E\u94FE\u63A5\u548C\u91D1\u989D ${amount} \u5747\u5DF2\u5B9E\u9645\u5BF9\u7528\u6237\u53EF\u89C1${mobileSentence}\uFF0C\u7136\u540E\u505C\u6B62\u7B49\u5F85\u3002\u4E0D\u8981\u521B\u5EFA\u65B0 Checkout\u3001Payment Intent \u6216 Execution\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8868\u793A\u5DF2\u4ED8\u6B3E\u6216\u8981\u6C42\u67E5\u8BE2\u72B6\u6001\u65F6\uFF0C\u624D\u6267\u884C next.command\uFF1B\u7528\u6237\u7684\u8BDD\u4E0D\u662F\u4ED8\u6B3E\u6210\u529F\u8BC1\u660E\u3002`;
14015
+ }
14016
+ if (platform2 === "terminal") {
14017
+ const mobileSentence = hasMobileLink ? "\uFF0C\u5E76\u5C55\u793A handoff.mobile_url \u4F9B\u624B\u673A\u7AEF\u70B9\u51FB\u76F4\u8FBE\u652F\u4ED8" : "";
14018
+ return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u3002\u5728\u7528\u6237\u53EF\u89C1\u7EC8\u7AEF\u5C55\u793A\u5F53\u524D Checkout \u7684\u4E8C\u7EF4\u7801\u3001handoff.url \u548C\u91D1\u989D ${amount}${mobileSentence}\uFF0C\u7136\u540E\u505C\u6B62\u7B49\u5F85\u3002\u4E0D\u8981\u521B\u5EFA\u65B0 Checkout\u3001Payment Intent \u6216 Execution\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8868\u793A\u5DF2\u4ED8\u6B3E\u6216\u8981\u6C42\u67E5\u8BE2\u72B6\u6001\u65F6\uFF0C\u624D\u6267\u884C next.command\uFF1B\u7528\u6237\u7684\u8BDD\u4E0D\u662F\u4ED8\u6B3E\u6210\u529F\u8BC1\u660E\u3002`;
14019
+ }
14020
+ if (agentType?.trim().toLowerCase() === "openclaw" && platform2 === "telegram") {
14021
+ const failLinks = hasMobileLink ? "handoff.qr_image_url\u3001\u91D1\u989D\u3001handoff.url \u4E0E handoff.mobile_url" : "handoff.qr_image_url\u3001\u91D1\u989D\u548C handoff.url";
14022
+ return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u6216\u6388\u6743\u72B6\u6001\u3002\u82E5\u5F53\u524D\u5DF2\u6709\u53EF\u7528 OpenClaw \u539F\u751F message tool\uFF0C\u4E25\u683C\u6309 handoff.agent_action.tool \u548C handoff.agent_action.arguments \u539F\u6837\u6267\u884C\uFF1B\u5B83\u4F1A\u53D1\u9001\u91D1\u989D ${amount}\u3001\u4E8C\u7EF4\u7801\u3001\u{1F4F1} \u624B\u673A\u70B9\u8FD9\u513F\u652F\u4ED8\u548C \u{1F4CB} \u5DF2\u6388\u6743\u7ED9\u6211\u8BFB\u3002\u4E0D\u5F97\u6539\u5199 presentation\u3001\u6362\u7528\u5176\u4ED6\u6D88\u606F\u5DE5\u5177\u3001\u62C6\u5F00\u6309\u94AE\u53D1\u9001\u6216\u7528\u666E\u901A\u56DE\u590D\u58F0\u79F0\u6309\u94AE\u5DF2\u7ECF\u53D1\u9001\u3002\u5DE5\u5177\u4E0D\u53EF\u7528\u65F6\u5F53\u8F6E\u76F4\u63A5\u5C55\u793A\u5DF2\u6709\u5B98\u65B9\u94FE\u63A5\uFF0C\u4E0D\u7814\u7A76\u6216\u5B89\u88C5\u5DE5\u5177\uFF1B\u5DE5\u5177\u6210\u529F\u6216\u5C55\u793A\u94FE\u63A5\u540E\u505C\u6B62\u7B49\u5F85\u3002\u6536\u5230 callback_data "itp:grant_confirmed:<checkout_id>" \u65F6\uFF0C\u8868\u793A\u7528\u6237\u58F0\u660E\u5DF2\u5728\u6536\u94F6\u53F0\u6388\u6743\u8BFB\u53D6\uFF1B\u7ACB\u5373\u6267\u884C next.command \u67E5\u8BE2\u540C\u4E00 Checkout\uFF0C\u518D\u53EA\u6267\u884C Backend \u8FD4\u56DE\u7684 next.command \u8FDB\u5165\u540C\u4E00 Execution \u7684 grant \u6D41\u7A0B\u3002\u8BE5 callback \u4E0D\u8BC1\u660E\u4ED8\u6B3E\u6210\u529F\u6216 grant \u5DF2\u751F\u6548\uFF1BBackend \u672A\u8FD4\u56DE grant_active \u524D\u4E0D\u5F97\u8BFB\u53D6\u6216\u731C\u6D4B\u7ED3\u679C\u3002\u82E5\u539F\u751F message tool \u660E\u786E\u5931\u8D25\u6216\u5F53\u524D Telegram \u672A\u542F\u7528 inline buttons\uFF0C\u53EA\u53D1\u9001\u73B0\u6709 ${failLinks}\uFF0C\u62A5\u544A\u6309\u94AE\u4E0D\u53EF\u7528\u5E76\u505C\u6B62\uFF1B\u4E0D\u8981\u521B\u5EFA\u65B0\u7684 Checkout\u3001Payment Intent \u6216 Execution\u3002`;
14023
+ }
14024
+ const urlList = hasMobileLink ? "handoff.url\u3001handoff.mobile_url\uFF08\u624B\u673A\u7AEF\u70B9\u51FB\u76F4\u8FBE\u652F\u4ED8\uFF09\u548C\u53EF\u7528\u7684 handoff.qr_image_url" : "handoff.url \u548C\u53EF\u7528\u7684 handoff.qr_image_url";
14025
+ return `Backend \u5C1A\u672A\u786E\u8BA4\u4ED8\u6B3E\u3002\u628A ${urlList} \u5B9E\u9645\u53D1\u9001\u5230\u5F53\u524D\u4F1A\u8BDD\uFF0C\u8BF4\u660E\u91D1\u989D ${amount}\uFF0C\u7136\u540E\u505C\u6B62\u7B49\u5F85\u3002\u4E0D\u8981\u521B\u5EFA\u65B0 Checkout\u3001Payment Intent \u6216 Execution\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8868\u793A\u5DF2\u4ED8\u6B3E\u6216\u8981\u6C42\u67E5\u8BE2\u72B6\u6001\u65F6\uFF0C\u624D\u6267\u884C next.command\uFF1B\u7528\u6237\u7684\u8BDD\u4E0D\u662F\u4ED8\u6B3E\u6210\u529F\u8BC1\u660E\u3002`;
14026
+ }
14027
+ __name(checkoutHandoffInstruction, "checkoutHandoffInstruction");
14028
+
14029
+ // src/commands/checkout_handoff.ts
14030
+ var payableStates = ["draft", "quote_bound", "auth_required", "payment_required"];
14031
+ function assertCheckoutCreation(checkout, cartID, sourceExecutionID) {
14032
+ const current = checkout.checkout;
14033
+ if (!current.checkout_id || current.cart_id !== cartID || !payableStates.includes(current.status) || !checkout.display_token) {
14034
+ throw checkoutNotPayable(current, cartID, sourceExecutionID, false);
14035
+ }
14036
+ }
14037
+ __name(assertCheckoutCreation, "assertCheckoutCreation");
14038
+ function assertCheckoutPayable(checkout, authoritative, cartID, sourceExecutionID) {
14039
+ const current = authoritative?.checkout ?? checkout.checkout;
14040
+ const deadlineClosed = authoritative?.payment_remaining_seconds === 0 || current.expires_at !== void 0 && (!authoritative?.server_now || Date.parse(current.expires_at) <= Date.parse(authoritative.server_now));
14041
+ if (current.cart_id && current.cart_id !== cartID || !payableStates.includes(current.status) || authoritative?.payment_intents.some((intent) => !["failed", "cancelled", "expired"].includes(intent.status)) || deadlineClosed || !checkout.display_token) {
14042
+ throw checkoutNotPayable(current, cartID, sourceExecutionID, deadlineClosed);
14043
+ }
14044
+ }
14045
+ __name(assertCheckoutPayable, "assertCheckoutPayable");
14046
+ function checkoutNotPayable(current, cartID, sourceExecutionID, deadlineClosed) {
14047
+ return new CommandContractError(
14048
+ "checkout_not_payable",
14049
+ "original checkout is not a current payable entry",
14050
+ "\u539FCheckout\u4E0D\u53EF\u4F5C\u4E3A\u65B0\u4ED8\u6B3E\u5165\u53E3\uFF1B\u6838\u5BF9\u539F\u8BA2\u5355\u3002\u8FC7\u671F\u4E0D\u7EED\u671F\uFF0C\u4ED8\u6B3E\u5904\u7406\u4E2D\u6216\u672A\u77E5\u4E0D\u91CD\u653E\uFF0C\u4E0D\u6362\u8D2D\u7269\u8F66\u6216\u5E42\u7B49\u952E\u521B\u5EFA\u66FF\u4EE3\u8D2D\u4E70\u3002",
14051
+ sourceExecutionID ? [{ command: `itpay services next ${sourceExecutionID} --json`, reason: "\u8BFB\u53D6\u6765\u6E90\u6267\u884C\u7684\u539F\u8BA2\u5355\u4E0E\u4ED8\u6B3E\u4E8B\u5B9E" }] : [],
14052
+ void 0,
14053
+ {
14054
+ cart_id: cartID,
14055
+ checkout_id: current.checkout_id,
14056
+ checkout_status: current.status,
14057
+ reason: deadlineClosed ? "payment_window_closed" : "checkout_not_payable"
14058
+ }
14059
+ );
14060
+ }
14061
+ __name(checkoutNotPayable, "checkoutNotPayable");
14062
+
14063
+ // src/services/rail/aftercare.ts
14064
+ var target = external_exports.object({ leg_index: external_exports.number().int().nonnegative(), passenger_index: external_exports.number().int().nonnegative() }).strict();
14065
+ var inputSchema = external_exports.object({ operation: external_exports.enum(["refund", "change"]), targets: external_exports.array(target).min(1).max(15), reason: external_exports.string().trim().min(1).max(1e3), scope_revision: external_exports.literal(1), user_confirmed_scope: external_exports.literal(true), change: external_exports.object({ travel_date: external_exports.string().optional(), departure_after: external_exports.string().optional(), arrival_before: external_exports.string().optional(), seat_type: external_exports.string().optional(), train_code: external_exports.string().optional(), constraints: external_exports.string().min(1).max(1e3) }).strict().optional() }).strict();
14066
+ var responseSchema = external_exports.object({ expected_revision: external_exports.number().int().positive(), proposal_revision: external_exports.number().int().positive().optional(), user_approved: external_exports.boolean().optional(), additional_information: external_exports.string().max(1e3).optional(), reason: external_exports.string().max(1e3).optional() }).strict();
14067
+ function railAftercareList(directory, orderID) {
14068
+ return { status: "aftercare_directory", result: { ...directory }, instruction: directory.instruction + "\u6BB5/\u4E58\u5BA2\u7D22\u5F15\u4ECE0\u8D77\uFF0C\u6309\u8FD4\u56DE\u4E8B\u5B9E\u9009\u76EE\u6807\uFF1B\u660E\u786E\u2018\u7B2C\u4E8C\u6BB5\u2019\u7528leg_index:1\u3002\u6574\u7A0B\u6A21\u677F\u5217\u5168\u90E8\u53EF\u7528\u76EE\u6807\uFF0C\u6307\u5B9A\u8303\u56F4\u5219\u4EC5\u4FDD\u7559\u5BF9\u5E94\u76EE\u6807\uFF0C\u4E0D\u624B\u586B\u7968\u4EF7/\u4F9B\u5E94\u5546\u5355\u53F7\u3002\u8303\u56F4\u5DF2\u660E\u786E\u53EA\u8BF4\u660E\u540E\u63D0\u4EA4\uFF1B\u4E0D\u91CD\u65B0\u8BE2\u95EE\u6574\u7A0B\u9009\u62E9\u3002", next: null, recovery: [], interaction: { schema_version: "itpay.interaction.v1", stage: "input_required", input_templates: Object.fromEntries(Object.entries(directory.input_templates).map(([operation, input]) => [operation, fileInputTemplate(`itpay aftercare create --order ${orderID} --input-json <file> --json`, { ...input }, ["targets", "reason", "user_confirmed_scope"])])) } };
14069
+ }
14070
+ __name(railAftercareList, "railAftercareList");
14071
+ function railAftercareEnvelope(view) {
14072
+ const c = view.case;
14073
+ const instruction = c.status === "awaiting_confirmation" ? "\u5C55\u793A\u5F53\u524D\u5177\u4F53\u6539\u7B7E\u65B9\u6848\u3001\u65E7\u65B0\u5BF9\u5E94\u3001\u5DEE\u4EF7\u548C\u6761\u4EF6\uFF1B\u65E7\u8D2D\u4E70\u59D4\u6258\u4E0D\u662F\u65B0\u65B9\u6848/\u8D39\u7528\u6279\u51C6\u3002\u6CA1\u6709\u771F\u5B9E\u56DE\u7B54\u4FDD\u6301false\u5E76\u7B49\u5F85\uFF1B\u672C\u8F6E\u8D39\u7528\u7531\u4EBA\u5DE5\u534F\u8C03\uFF0C\u6CA1\u6709\u81EA\u52A8\u652F\u4ED8\u94FE\u63A5\u3002" : c.status === "needs_input" ? "\u5C55\u793A\u7BA1\u7406\u5458\u8981\u6C42\u8865\u5145\u7684\u5185\u5BB9\uFF0C\u53EA\u8865\u7F3A\u5931\u4E8B\u5B9E\uFF1B\u4FDD\u7559\u539F\u7533\u8BF7\u8303\u56F4\u3002" : c.status === "completed" ? "\u4EBA\u5DE5\u53D7\u7406\u5DF2\u5B8C\u6210\uFF1B\u5206\u522B\u8BF4\u660E\u4F9B\u5E94\u5546\u6838\u9A8C\u7ED3\u679C\u4E0E\u5E73\u53F0\u9000\u6B3E\u91D1\u989D/\u72B6\u6001\u3002\u672A\u9000\u6BB5\u4EC5\u62A5\u544A\u6743\u5A01\u5DF2\u77E5\u4E8B\u5B9E\uFF0C\u4E0D\u4FDD\u8BC1\u4ECD\u53EF\u4E58\uFF1B\u4E0D\u6062\u590D\u5E73\u53F0\u5185\u5BB9\u8BBF\u95EE\u9501\u3002" : c.status === "processing" ? "\u539F\u7533\u8BF7\u6B63\u5728\u4EBA\u5DE5\u529E\u7406\u6216\u8D22\u52A1\u5904\u7406\u4E2D\uFF1B\u6CA1\u6709\u6700\u7EC8\u4E8B\u5B9E\u4E0D\u8BF4\u9000\u7968\u3001\u6539\u7B7E\u6216\u5230\u8D26\u6210\u529F\uFF0C\u4E0D\u91CD\u8BD5\u672A\u77E5\u8D44\u91D1\u3001\u4E0D\u53D6\u6D88\u5DF2\u53D1\u751F\u64CD\u4F5C\u3002" : ["cancelled", "rejected"].includes(c.status) ? "\u8BF4\u660E\u539F\u7533\u8BF7\u5DF2\u53D6\u6D88\u6216\u88AB\u62D2\u7EDD\u53CA\u539F\u56E0\uFF1B\u6CA1\u6709\u64A4\u9500\u5DF2\u53D1\u751F\u4F9B\u5E94\u5546\u64CD\u4F5C\uFF0C\u4E5F\u4E0D\u81EA\u52A8\u521B\u5EFA\u66FF\u4EE3\u8D2D\u4E70\u3002" : "\u5DF2\u63D0\u4EA4\u4EBA\u5DE5\u53D7\u7406\uFF0C\u5C1A\u672A\u786E\u8BA4\u4F9B\u5E94\u5546\u9000\u7968/\u6539\u7B7E\u6216\u94B1\u6B3E\u5230\u8D26\u3002\u5148\u4EA4\u4ED8\u7533\u8BF7\u72B6\u6001\u5165\u53E3\uFF0C\u518D\u6309\u7528\u6237\u610F\u613F\u67E5\u8BE2\u539F\u7533\u8BF7\uFF0C\u4E0D\u5FAA\u73AF\u8F6E\u8BE2\u3002";
14074
+ const cancellation = view.can_cancel ? { cancel_template: fileInputTemplate(`itpay aftercare cancel ${c.case_id} --input-json <file> --json`, { expected_revision: c.revision, reason: "" }, ["reason"]) } : {};
14075
+ const needsReply = ["awaiting_confirmation", "needs_input"].includes(c.status);
14076
+ return { status: c.status, result: { ...view }, instruction, next: needsReply || ["completed", "cancelled", "rejected"].includes(c.status) ? null : { command: `itpay aftercare get ${c.case_id} --json`, reason: "\u6309\u7528\u6237\u8981\u6C42\u8BFB\u53D6\u540C\u4E00\u4EBA\u5DE5\u7533\u8BF7" }, recovery: [], ...needsReply || view.can_cancel ? { interaction: { schema_version: "itpay.interaction.v1", stage: c.status === "awaiting_confirmation" ? "consent_required" : "input_required", ...cancellation, ...needsReply ? { input_template: fileInputTemplate(`itpay aftercare respond ${c.case_id} --input-json <file> --json`, { expected_revision: c.revision, ...c.status === "awaiting_confirmation" ? { proposal_revision: c.proposal_revision, user_approved: false } : { additional_information: "" } }, c.status === "awaiting_confirmation" ? ["user_approved"] : ["additional_information"]) } : {} } } : {} };
14077
+ }
14078
+ __name(railAftercareEnvelope, "railAftercareEnvelope");
14079
+ async function railAftercareCreate(backend, config, orderID, raw) {
14080
+ const parsed = inputSchema.safeParse(raw);
14081
+ if (!parsed.success) throw new CommandContractError("rail_aftercare_input_invalid", "Aftercare input fields or genuine scope confirmation are missing", "Agent\u8BFB\u53D6\u5F53\u524D\u5B8C\u6574\u6A21\u677F\u4FEE\u6B63\u6280\u672F\u5B57\u6BB5\uFF1B\u53EA\u95EE\u7F3A\u5931\u7684\u771F\u5B9E\u8303\u56F4/\u6539\u7B7E\u610F\u5411\uFF0C\u4E0D\u8BA9\u7528\u6237\u586B\u6280\u672FJSON\u3002", [{ command: `itpay aftercare list --order ${orderID} --json`, reason: "\u8BFB\u53D6\u5F53\u524D\u884C\u7A0B\u3001\u76EE\u6807\u548C\u5B8C\u6574\u6A21\u677F" }]);
14082
+ const value = parsed.data;
14083
+ const change = value.change;
14084
+ const input = { operation: value.operation, targets: value.targets, reason: value.reason, scope_revision: value.scope_revision, user_confirmed_scope: value.user_confirmed_scope, ...change ? { change: { constraints: change.constraints, ...change.travel_date !== void 0 ? { travel_date: change.travel_date } : {}, ...change.departure_after !== void 0 ? { departure_after: change.departure_after } : {}, ...change.arrival_before !== void 0 ? { arrival_before: change.arrival_before } : {}, ...change.seat_type !== void 0 ? { seat_type: change.seat_type } : {}, ...change.train_code !== void 0 ? { train_code: change.train_code } : {} } } : {} };
14085
+ return railAftercareEnvelope(await backend.createRailAftercare(orderID, input, await operationID(config, `aftercare.create:${orderID}:${JSON.stringify(input)}`)));
14086
+ }
14087
+ __name(railAftercareCreate, "railAftercareCreate");
13949
14088
  async function railAftercareRespond(backend, id, raw, cancel = false) {
13950
14089
  const parsed = responseSchema.safeParse(raw);
13951
14090
  if (!parsed.success) throw new CommandContractError("rail_aftercare_input_invalid", "Current revision or response fields are missing", "\u4F7F\u7528\u539F\u7533\u8BF7\u5F53\u524D\u8FD4\u56DE\u6A21\u677F\uFF1B\u5B9E\u8D28\u65B9\u6848\u53D8\u5316\u987B\u91CD\u65B0\u53D6\u5F97\u660E\u786E\u540C\u610F\u3002", [{ command: `itpay aftercare get ${id} --json`, reason: "\u8BFB\u53D6\u540C\u4E00\u7533\u8BF7\u5F53\u524D\u65B9\u6848\u548C\u7248\u672C" }]);
@@ -13962,23 +14101,30 @@ async function railAftercareOrder(backend, order, envelope) {
13962
14101
  __name(railAftercareOrder, "railAftercareOrder");
13963
14102
 
13964
14103
  // src/state/task_journal.ts
13965
- import { existsSync as existsSync3, mkdirSync as mkdirSync5, readFileSync as readFileSync5, renameSync as renameSync2, writeFileSync as writeFileSync4 } from "node:fs";
13966
- import { dirname as dirname3 } from "node:path";
13967
- var PAUSED_STAGES = /* @__PURE__ */ new Set([
13968
- "login_required",
13969
- "rate_limited",
13970
- "quota_paused",
13971
- "auth_pending",
13972
- "awaiting_input"
13973
- ]);
13974
- var TERMINAL_STAGES = /* @__PURE__ */ new Set([
13975
- "completed",
13976
- "delivered",
13977
- "issued",
13978
- "failed",
13979
- "cancelled",
13980
- "refunded"
13981
- ]);
14104
+ import { randomUUID as randomUUID5, createHash as createHash6 } from "node:crypto";
14105
+ import { existsSync as existsSync3, linkSync as linkSync4, lstatSync as lstatSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync5, readdirSync as readdirSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync4 } from "node:fs";
14106
+ import { join as join2 } from "node:path";
14107
+ var PAUSED_STAGES = /* @__PURE__ */ new Set(["login_required", "rate_limited", "quota_paused", "auth_pending", "awaiting_input"]);
14108
+ var TERMINAL_STAGES = /* @__PURE__ */ new Set(["completed", "delivered", "issued", "failed", "cancelled", "refunded"]);
14109
+ var object2 = /* @__PURE__ */ __name((v) => v !== null && typeof v === "object" && !Array.isArray(v), "object");
14110
+ var finite = /* @__PURE__ */ __name((v) => typeof v === "number" && Number.isFinite(v) && v >= 0, "finite");
14111
+ function validTask(v) {
14112
+ return object2(v) && typeof v.service_execution_id === "string" && typeof v.stage === "string" && typeof v.updated_at === "string" && Number.isFinite(Date.parse(v.updated_at)) && (v.service_id === void 0 || typeof v.service_id === "string") && (v.resume_command === void 0 || typeof v.resume_command === "string") && (v.automatic_wait_ms === void 0 || finite(v.automatic_wait_ms));
14113
+ }
14114
+ __name(validTask, "validTask");
14115
+ function validChange(v) {
14116
+ if (!object2(v) || v.schema_version !== "itpay.task_change.v1" || typeof v.event_id !== "string" || typeof v.id !== "string" || typeof v.updated_at !== "string" || !Number.isFinite(Date.parse(v.updated_at)) || typeof v.monotonic !== "string" || !/^\d{1,30}$/.test(v.monotonic)) return false;
14117
+ if (v.kind === "clear") return true;
14118
+ if (v.kind === "wait") return finite(v.milliseconds);
14119
+ if (v.kind === "observe") return typeof v.stage === "string" && (v.resume_command === void 0 || typeof v.resume_command === "string");
14120
+ return v.kind === "record" && object2(v.task) && validTask({ ...v.task, updated_at: v.updated_at }) && v.task.service_execution_id === v.id;
14121
+ }
14122
+ __name(validChange, "validChange");
14123
+ var taskHash = /* @__PURE__ */ __name((id) => createHash6("sha256").update(id).digest("hex"), "taskHash");
14124
+ function invalid3() {
14125
+ throw Object.assign(new Error("ItPay task journal is invalid; original records are unchanged"), { code: "task_journal_invalid" });
14126
+ }
14127
+ __name(invalid3, "invalid");
13982
14128
  var TaskJournal = class {
13983
14129
  constructor(path3) {
13984
14130
  this.path = path3;
@@ -13988,83 +14134,103 @@ var TaskJournal = class {
13988
14134
  __name(this, "TaskJournal");
13989
14135
  }
13990
14136
  record(task) {
13991
- const file = this.readFile();
13992
- file.tasks[task.service_execution_id] = {
13993
- ...task,
13994
- ...file.tasks[task.service_execution_id]?.automatic_wait_ms !== void 0 && task.automatic_wait_ms === void 0 ? { automatic_wait_ms: file.tasks[task.service_execution_id].automatic_wait_ms } : {},
13995
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
13996
- };
13997
- this.writeFile(file);
13998
- }
13999
- clear(serviceExecutionID) {
14000
- const file = this.readFile();
14001
- if (!file.tasks[serviceExecutionID]) return;
14002
- delete file.tasks[serviceExecutionID];
14003
- this.writeFile(file);
14004
- }
14005
- // Observe the latest stage without deleting history; terminal stages stop
14006
- // the task from counting as resumable.
14007
- observe(serviceExecutionID, stage, resumeCommand) {
14008
- const file = this.readFile();
14009
- const existing = file.tasks[serviceExecutionID];
14010
- if (existing && existing.stage === stage && (resumeCommand === void 0 || existing.resume_command === resumeCommand)) return;
14011
- file.tasks[serviceExecutionID] = {
14012
- service_execution_id: serviceExecutionID,
14013
- ...existing?.service_id ? { service_id: existing.service_id } : {},
14014
- stage,
14015
- ...existing?.automatic_wait_ms !== void 0 ? { automatic_wait_ms: existing.automatic_wait_ms } : {},
14016
- ...resumeCommand ?? existing?.resume_command ? { resume_command: resumeCommand ?? existing.resume_command } : {},
14017
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
14018
- };
14019
- this.writeFile(file);
14137
+ this.readFile(task.service_execution_id);
14138
+ this.append({ kind: "record", id: task.service_execution_id, task });
14020
14139
  }
14021
- remainingAutomaticWait(serviceExecutionID) {
14022
- if (existsSync3(this.path)) {
14023
- try {
14024
- const raw = JSON.parse(readFileSync5(this.path, "utf8"));
14025
- if (raw.schema_version !== "itpay.task_journal.v1" || !raw.tasks || typeof raw.tasks !== "object") return 0;
14026
- } catch {
14027
- return 0;
14028
- }
14140
+ clear(id) {
14141
+ if (this.readFile(id).tasks[id]) this.append({ kind: "clear", id });
14142
+ }
14143
+ observe(id, stage, resumeCommand) {
14144
+ const existing = this.readFile(id).tasks[id];
14145
+ if (existing && (TERMINAL_STAGES.has(existing.stage) || existing.stage === stage && (resumeCommand === void 0 || existing.resume_command === resumeCommand))) return;
14146
+ this.append({ kind: "observe", id, stage, ...resumeCommand === void 0 ? {} : { resume_command: resumeCommand } });
14147
+ }
14148
+ remainingAutomaticWait(id) {
14149
+ try {
14150
+ return Math.max(0, 12e4 - (this.readFile(id).spent.get(id) ?? 0));
14151
+ } catch {
14152
+ return 0;
14029
14153
  }
14030
- const spent = this.readFile().tasks[serviceExecutionID]?.automatic_wait_ms ?? 0;
14031
- return typeof spent === "number" && Number.isFinite(spent) && spent >= 0 ? Math.max(0, 12e4 - spent) : 0;
14032
14154
  }
14033
- recordAutomaticWait(serviceExecutionID, milliseconds) {
14034
- if (this.remainingAutomaticWait(serviceExecutionID) === 0) return 0;
14035
- const file = this.readFile();
14036
- const existing = file.tasks[serviceExecutionID];
14037
- const spent = Math.min(12e4, (existing?.automatic_wait_ms ?? 0) + Math.max(0, milliseconds));
14038
- file.tasks[serviceExecutionID] = { ...existing ?? { service_execution_id: serviceExecutionID, stage: "running" }, automatic_wait_ms: spent, updated_at: (/* @__PURE__ */ new Date()).toISOString() };
14039
- this.writeFile(file);
14040
- return 12e4 - spent;
14155
+ recordAutomaticWait(id, milliseconds) {
14156
+ if (!finite(milliseconds) || this.remainingAutomaticWait(id) === 0) return 0;
14157
+ if (milliseconds > 0) this.append({ kind: "wait", id, milliseconds: Math.min(12e4, milliseconds) });
14158
+ return this.remainingAutomaticWait(id);
14041
14159
  }
14042
- // Tasks paused behind login/quota gates, newest first. Terminal or
14043
- // completed tasks never count as "still waiting for login".
14044
14160
  pausedTasks() {
14045
- const file = this.readFile();
14046
- return Object.values(file.tasks).filter((task) => PAUSED_STAGES.has(task.stage) && !TERMINAL_STAGES.has(task.stage)).sort((left, right) => right.updated_at.localeCompare(left.updated_at));
14161
+ return Object.values(this.readFile().tasks).filter((t) => PAUSED_STAGES.has(t.stage) && !TERMINAL_STAGES.has(t.stage)).sort((a, b) => b.updated_at.localeCompare(a.updated_at));
14047
14162
  }
14048
- readFile() {
14049
- if (!existsSync3(this.path)) return { schema_version: "itpay.task_journal.v1", tasks: {} };
14163
+ readFile(onlyID) {
14164
+ const tasks = /* @__PURE__ */ new Map(), spent = /* @__PURE__ */ new Map(), cleared = /* @__PURE__ */ new Set();
14165
+ if (existsSync3(this.path)) {
14166
+ let old;
14167
+ try {
14168
+ old = JSON.parse(readFileSync5(this.path, "utf8"));
14169
+ } catch {
14170
+ return invalid3();
14171
+ }
14172
+ if (!object2(old) || old.schema_version !== "itpay.task_journal.v1" || !object2(old.tasks)) return invalid3();
14173
+ for (const [id, task] of Object.entries(old.tasks)) {
14174
+ if (!validTask(task) || task.service_execution_id !== id) return invalid3();
14175
+ if (onlyID === void 0 || onlyID === id) {
14176
+ tasks.set(id, task);
14177
+ spent.set(id, task.automatic_wait_ms ?? 0);
14178
+ }
14179
+ }
14180
+ }
14181
+ const directory = this.path + ".d";
14182
+ const changes = [];
14183
+ if (existsSync3(directory) && (!lstatSync4(directory).isDirectory() || lstatSync4(directory).isSymbolicLink())) return invalid3();
14184
+ if (existsSync3(directory)) for (const name of readdirSync3(directory).filter((n) => n.endsWith(".json") && (onlyID === void 0 || n.startsWith(taskHash(onlyID) + "-") || !/^\w{64}-[\da-f-]+\.json$/.test(n)))) {
14185
+ const path3 = join2(directory, name);
14186
+ const stat = lstatSync4(path3);
14187
+ if (!stat.isFile() || stat.isSymbolicLink()) return invalid3();
14188
+ let raw;
14189
+ try {
14190
+ raw = JSON.parse(readFileSync5(path3, "utf8"));
14191
+ } catch {
14192
+ return invalid3();
14193
+ }
14194
+ if (!validChange(raw) || name !== taskHash(raw.id) + "-" + raw.event_id + ".json") return invalid3();
14195
+ changes.push(raw);
14196
+ }
14197
+ changes.sort((a, b) => a.updated_at.localeCompare(b.updated_at) || (BigInt(a.monotonic) < BigInt(b.monotonic) ? -1 : BigInt(a.monotonic) > BigInt(b.monotonic) ? 1 : a.event_id.localeCompare(b.event_id)));
14198
+ for (const change of changes) {
14199
+ const id = change.id, existing = tasks.get(id);
14200
+ if (change.kind === "wait") {
14201
+ spent.set(id, Math.min(12e4, (spent.get(id) ?? 0) + change.milliseconds));
14202
+ if (!cleared.has(id)) tasks.set(id, { ...existing ?? { service_execution_id: id, stage: "running" }, updated_at: change.updated_at, automatic_wait_ms: spent.get(id) ?? 0 });
14203
+ } else if (change.kind === "clear") {
14204
+ tasks.delete(id);
14205
+ cleared.add(id);
14206
+ } else if (change.kind === "record") {
14207
+ cleared.delete(id);
14208
+ spent.set(id, Math.max(spent.get(id) ?? 0, change.task.automatic_wait_ms ?? 0));
14209
+ tasks.set(id, { ...change.task, updated_at: change.updated_at, automatic_wait_ms: spent.get(id) ?? 0 });
14210
+ } else if (!cleared.has(id) && (!existing || !TERMINAL_STAGES.has(existing.stage))) {
14211
+ tasks.set(id, { ...existing ?? { service_execution_id: id }, stage: change.stage, ...change.resume_command === void 0 ? {} : { resume_command: change.resume_command }, updated_at: change.updated_at, automatic_wait_ms: spent.get(id) ?? 0 });
14212
+ }
14213
+ }
14214
+ return { tasks: Object.fromEntries([...tasks].sort((a, b) => b[1].updated_at.localeCompare(a[1].updated_at)).slice(0, 50)), spent };
14215
+ }
14216
+ append(change) {
14217
+ const event = { ...change, schema_version: "itpay.task_change.v1", event_id: randomUUID5(), updated_at: (/* @__PURE__ */ new Date()).toISOString(), monotonic: process.hrtime.bigint().toString() };
14218
+ if (!validChange(event)) return invalid3();
14219
+ const directory = this.path + ".d";
14220
+ mkdirSync5(directory, { recursive: true, mode: 448 });
14221
+ if (!lstatSync4(directory).isDirectory() || lstatSync4(directory).isSymbolicLink()) return invalid3();
14222
+ const temp = join2(directory, "." + event.event_id + ".tmp"), target2 = join2(directory, taskHash(event.id) + "-" + event.event_id + ".json");
14050
14223
  try {
14051
- const parsed = JSON.parse(readFileSync5(this.path, "utf8"));
14052
- if (parsed.schema_version !== "itpay.task_journal.v1" || !parsed.tasks || typeof parsed.tasks !== "object") {
14053
- return { schema_version: "itpay.task_journal.v1", tasks: {} };
14224
+ writeFileSync4(temp, JSON.stringify(event), { flag: "wx", mode: 384 });
14225
+ linkSync4(temp, target2);
14226
+ } finally {
14227
+ try {
14228
+ unlinkSync4(temp);
14229
+ } catch (e) {
14230
+ if (!object2(e) || e.code !== "ENOENT") throw e;
14054
14231
  }
14055
- return parsed;
14056
- } catch {
14057
- return { schema_version: "itpay.task_journal.v1", tasks: {} };
14058
14232
  }
14059
14233
  }
14060
- writeFile(file) {
14061
- const entries = Object.entries(file.tasks).sort((left, right) => right[1].updated_at.localeCompare(left[1].updated_at));
14062
- file.tasks = Object.fromEntries(entries.slice(0, 50));
14063
- mkdirSync5(dirname3(this.path), { recursive: true, mode: 448 });
14064
- const tmp = `${this.path}.${process.pid}.tmp`;
14065
- writeFileSync4(tmp, JSON.stringify(file), { mode: 384 });
14066
- renameSync2(tmp, this.path);
14067
- }
14068
14234
  };
14069
14235
 
14070
14236
  // src/render/markdown.ts
@@ -14483,10 +14649,10 @@ function tokenizedCheckoutURL(checkoutURL, displayToken, qrPayload) {
14483
14649
  __name(tokenizedCheckoutURL, "tokenizedCheckoutURL");
14484
14650
  function publicPurchaseTemplate(value) {
14485
14651
  if (value === void 0) return void 0;
14486
- const invalid4 = /* @__PURE__ */ __name(() => new CommandContractError("public_operation_contract_invalid", "incomplete public purchase operation", "\u670D\u52A1\u8FD4\u56DE\u7684\u51C6\u5907\u8D2D\u4E70\u5408\u540C\u4E0D\u5B8C\u6574\uFF1B\u4FDD\u7559\u5F53\u524D\u5FEB\u7167\u4E0E\u5DF2\u6709\u8D2D\u4E70\u5E76\u505C\u6B62\uFF0C\u4E0D\u80FD\u9000\u56DE\u65E7\u5165\u53E3\u62FC\u63A5\u51ED\u636E\u3002", [], void 0, { reason: "purchase_contract_missing" }), "invalid");
14487
- if (typeof value !== "object" || value === null || Array.isArray(value) || !("service_id" in value) || typeof value.service_id !== "string" || !("operation_id" in value) || typeof value.operation_id !== "string" || !("input" in value) || typeof value.input !== "object" || value.input === null || Array.isArray(value.input) || !("continuation" in value)) throw invalid4();
14652
+ const invalid5 = /* @__PURE__ */ __name(() => new CommandContractError("public_operation_contract_invalid", "incomplete public purchase operation", "\u670D\u52A1\u8FD4\u56DE\u7684\u51C6\u5907\u8D2D\u4E70\u5408\u540C\u4E0D\u5B8C\u6574\uFF1B\u4FDD\u7559\u5F53\u524D\u5FEB\u7167\u4E0E\u5DF2\u6709\u8D2D\u4E70\u5E76\u505C\u6B62\uFF0C\u4E0D\u80FD\u9000\u56DE\u65E7\u5165\u53E3\u62FC\u63A5\u51ED\u636E\u3002", [], void 0, { reason: "purchase_contract_missing" }), "invalid");
14653
+ if (typeof value !== "object" || value === null || Array.isArray(value) || !("service_id" in value) || typeof value.service_id !== "string" || !("operation_id" in value) || typeof value.operation_id !== "string" || !("input" in value) || typeof value.input !== "object" || value.input === null || Array.isArray(value.input) || !("continuation" in value)) throw invalid5();
14488
14654
  const ref = value.continuation;
14489
- if (typeof ref !== "object" || ref === null || Array.isArray(ref) || !("service_execution_id" in ref) || typeof ref.service_execution_id !== "string" || !("snapshot_id" in ref) || typeof ref.snapshot_id !== "string") throw invalid4();
14655
+ if (typeof ref !== "object" || ref === null || Array.isArray(ref) || !("service_execution_id" in ref) || typeof ref.service_execution_id !== "string" || !("snapshot_id" in ref) || typeof ref.snapshot_id !== "string") throw invalid5();
14490
14656
  const template = fileInputTemplate(`itpay services run ${shellArgument(value.service_id)} --operation ${shellArgument(value.operation_id)} --input-json <file> --json`, { input: value.input, continuation: { service_execution_id: ref.service_execution_id, snapshot_id: ref.snapshot_id } });
14491
14657
  return { ...template, input_example: template.file_content };
14492
14658
  }
@@ -14559,6 +14725,8 @@ var RAIL_SERVICE_GUIDANCE = {
14559
14725
  { name: "origin_location", description: "\u5DF2\u77E5\u5750\u6807\u5BF9\u8C61\uFF08\u9AD8\u5FB7 GCJ-02\uFF09" },
14560
14726
  { name: "destination_location", description: "\u76EE\u7684\u5730\u5750\u6807\u5BF9\u8C61" },
14561
14727
  { name: "depart_after", description: "\u4E0D\u65E9\u4E8E\u8BE5\u65F6\u95F4\u51FA\u53D1" },
14728
+ { name: "depart_before", description: "\u4E0D\u665A\u4E8E\u8BE5\u65F6\u95F4\u51FA\u53D1\uFF1B\u4FDD\u7559\u7528\u6237\u660E\u786E\u4E0A\u9650" },
14729
+ { name: "arrive_after", description: "\u4E0D\u65E9\u4E8E\u8BE5\u65F6\u95F4\u5230\u8FBE\uFF1B\u4E0E\u6700\u665A\u5230\u8FBE\u4E00\u8D77\u4F5C\u4E3A\u8D44\u683C\u6761\u4EF6\uFF0C\u4E0D\u53EA\u4F5C\u6392\u5E8F" },
14562
14730
  { name: "depart_before", description: "\u4E0D\u665A\u4E8E\u8BE5\u65F6\u95F4\u51FA\u53D1" },
14563
14731
  { name: "arrive_before", description: "\u4E0D\u665A\u4E8E\u8BE5\u65F6\u95F4\u5230\u8FBE" },
14564
14732
  { name: "user_query", description: "\u65C5\u884C\u9700\u6C42\u539F\u8BDD\uFF0C\u6700\u591A4096 UTF-8\u5B57\u8282\uFF1B\u65F6\u95F4\u7B49\u660E\u786E\u6761\u4EF6\u4ECD\u586B\u5199\u5BF9\u5E94\u7ED3\u6784\u5316\u5B57\u6BB5" },
@@ -14864,6 +15032,13 @@ function railWorkflowEnvelope(model) {
14864
15032
  const workflowReason = model.workflow?.failure?.reason_code ?? model.workflow?.error_code;
14865
15033
  const paymentVerified = model.payment_bindings.some((binding) => binding.status === "payment_verified") || model.checkout_bindings.some((binding) => binding.status === "payment_verified");
14866
15034
  const state = model.workflow?.status === "payment" && paymentVerified ? "running" : model.workflow?.status ?? "input_required";
15035
+ if (state === "failed" && workflowReason === "queue_expired") return {
15036
+ status: "queue_expired",
15037
+ result: { accepted: true, service_execution_id: id, reason: workflowReason, query: model.workflow?.query_input },
15038
+ instruction: "\u67E5\u8BE2\u5728\u5BB9\u91CF\u7B49\u5F85\u671F\u9650\u5185\u672A\u80FD\u5B8C\u6210\u6D3E\u53D1\uFF0C\u672C\u6B21\u5DF2\u505C\u6B62\uFF1B\u8FD9\u4E0D\u8868\u793A\u6CA1\u6709\u8F66\u3002\u4FDD\u7559\u539F\u6761\u4EF6\u53CA\u5DF2\u6709\u7ED3\u679C\uFF0C\u4E0D\u6269\u5927\u8303\u56F4\u3001\u4E0D\u91CD\u5EFA\u8D2D\u4E70\u6216\u4ED8\u6B3E\u3002",
15039
+ next: null,
15040
+ recovery: []
15041
+ };
14867
15042
  if (["quota_paused", "failed"].includes(state) && !RAIL_LOCATION_EVIDENCE_REASONS.has(workflowReason ?? "") && (model.workflow?.dependency || /^amap_/.test(workflowReason ?? ""))) {
14868
15043
  const dependency = model.workflow?.dependency;
14869
15044
  const resumable = state === "quota_paused" && dependency?.retryable === true;
@@ -15465,6 +15640,13 @@ function railPlanningEnvelope(model) {
15465
15640
  case "failed":
15466
15641
  case "cancelled":
15467
15642
  case "expired": {
15643
+ if (plan.search?.reason === "queue_expired") return {
15644
+ status: "queue_expired",
15645
+ result,
15646
+ instruction: "\u67E5\u8BE2\u7684\u5BB9\u91CF\u7B49\u5F85\u671F\u9650\u5DF2\u5230\uFF0C\u672C\u6B21\u505C\u6B62\u6D3E\u53D1\uFF1B\u8FD9\u4E0D\u662F\u65E0\u8F66\u7ED3\u8BBA\u3002\u5DF2\u6709\u94C1\u8DEF\u4E8B\u5B9E\u4ECD\u6309\u8FD4\u56DE\u7684\u540C\u5FEB\u7167\u5165\u53E3\u8BFB\u53D6\uFF1B\u4FDD\u7559\u539F\u6761\u4EF6\uFF0C\u4E0D\u56E0\u5BB9\u91CF\u7B49\u5F85\u81EA\u52A8\u6362\u7AD9\u6216\u6269\u5927\u641C\u7D22\u3002",
15647
+ next: null,
15648
+ recovery: []
15649
+ };
15468
15650
  if (expansion === "failed" && !plan.snapshot_id && ["address_required", "administrative_area_unresolved", "station_location_evidence_required", "coordinate_identity_unverified", "coordinate_name_mismatch", "endpoint_adcode_name_conflict", "endpoint_station_name_code_conflict", "endpoint_poi_name_conflict"].includes(plan.search?.reason ?? "")) {
15469
15651
  return {
15470
15652
  status: "awaiting_input",
@@ -15731,11 +15913,11 @@ function writeSavedPage(envelope, options, key, offset, continuation, updateMeta
15731
15913
  const render = /* @__PURE__ */ __name((output) => writeCommandEnvelope(envelope, { ...options, output }), "render");
15732
15914
  if (!options.all) {
15733
15915
  for (; ; ) {
15734
- let text = "";
15916
+ let text2 = "";
15735
15917
  render((value) => {
15736
- text += value;
15918
+ text2 += value;
15737
15919
  });
15738
- if (Buffer.byteLength(text, "utf8") <= bound) break;
15920
+ if (Buffer.byteLength(text2, "utf8") <= bound) break;
15739
15921
  if (rows.length <= 1) {
15740
15922
  throw new CommandContractError(
15741
15923
  "saved_row_too_large",
@@ -16291,7 +16473,7 @@ var railAdapter = {
16291
16473
  invocation: railInvocationProjection,
16292
16474
  shouldWait: railShouldWait,
16293
16475
  pollAfter: railPollAfter,
16294
- preservesTerminalRecovery: /* @__PURE__ */ __name((model) => model.workflow?.human_action?.context?.quote_recovery === true, "preservesTerminalRecovery"),
16476
+ preservesTerminalRecovery: /* @__PURE__ */ __name((model) => model.workflow?.human_action?.context?.quote_recovery === true || model.rail_planning?.search?.reason === "queue_expired", "preservesTerminalRecovery"),
16295
16477
  projectState: /* @__PURE__ */ __name((model) => model.rail_booking ? railBookingEnvelope(model) : model.rail_planning ? railPlanningEnvelope(model) : null, "projectState"),
16296
16478
  workflow: railWorkflowEnvelope,
16297
16479
  savedResult: railSavedResultEnvelope,
@@ -16385,15 +16567,15 @@ var unsupportedAdapter = { ...schemaAdapter, supported: false, workflow: /* @__P
16385
16567
 
16386
16568
  // src/services/registry.ts
16387
16569
  var legacyRailContracts = /* @__PURE__ */ new Map([
16388
- ["itpay-rail-exact", /* @__PURE__ */ new Set(["scv_itpay_rail_exact_v1"])],
16389
- ["itpay-rail-smart", /* @__PURE__ */ new Set(["scv_itpay_rail_smart_v1", "scv_itpay_rail_smart_v2", "scv_itpay_rail_smart_v3", "scv_itpay_rail_smart_v4", "scv_itpay_rail_smart_v5", "scv_itpay_rail_smart_v6"])],
16570
+ ["itpay-rail-exact", /* @__PURE__ */ new Set(["scv_itpay_rail_exact_v1", "scv_itpay_rail_exact_v1_capacity_20261015"])],
16571
+ ["itpay-rail-smart", /* @__PURE__ */ new Set(["scv_itpay_rail_smart_v1", "scv_itpay_rail_smart_v2", "scv_itpay_rail_smart_v3", "scv_itpay_rail_smart_v4", "scv_itpay_rail_smart_v5", "scv_itpay_rail_smart_v6", "scv_itpay_rail_smart_v6_capacity_20261015"])],
16390
16572
  ["itpay-rail-booking", /* @__PURE__ */ new Set(["scv_itpay_rail_booking_v1", "scv_itpay_rail_booking_v2", "scv_itpay_rail_booking_v3", "scv_itpay_rail_booking_v4"])]
16391
16573
  ]);
16392
16574
  function serviceAdapterKey(execution) {
16393
16575
  const binding = execution.public_binding;
16394
16576
  if (binding) {
16395
16577
  if (binding.adapter_key === "schema.v1") return "schema.v1";
16396
- if (binding.adapter_key === "rail.v1" && binding.service_definition_version === "scv_itpay_rail_public_v1") return "rail.v1";
16578
+ if (binding.adapter_key === "rail.v1" && ["scv_itpay_rail_public_v1", "scv_itpay_rail_public_v1_capacity_20261015", "scv_itpay_rail_public_v5"].includes(binding.service_definition_version)) return "rail.v1";
16397
16579
  return "unsupported";
16398
16580
  }
16399
16581
  const versions = legacyRailContracts.get(execution.service_id);
@@ -16426,12 +16608,69 @@ function projectCheckoutPresentation(presentation, model) {
16426
16608
  }
16427
16609
  __name(projectCheckoutPresentation, "projectCheckoutPresentation");
16428
16610
 
16611
+ // src/render/browser.ts
16612
+ import { spawn } from "node:child_process";
16613
+ import { platform } from "node:os";
16614
+ function isPresentableURL(raw, baseURL, env = process.env) {
16615
+ let url;
16616
+ try {
16617
+ url = new URL(raw);
16618
+ } catch {
16619
+ return false;
16620
+ }
16621
+ if (url.username || url.password) return false;
16622
+ if (env.ITPAY_CLI_DEV === "1" && /^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(url.origin)) return true;
16623
+ if (url.protocol !== "https:") return false;
16624
+ const allowedOrigins = new Set(OFFICIAL_BACKEND_URLS);
16625
+ if (baseURL) {
16626
+ try {
16627
+ allowedOrigins.add(new URL(baseURL).origin);
16628
+ } catch {
16629
+ }
16630
+ }
16631
+ return allowedOrigins.has(url.origin);
16632
+ }
16633
+ __name(isPresentableURL, "isPresentableURL");
16634
+ function openInSystemBrowser(raw, baseURL, env = process.env) {
16635
+ if (!isPresentableURL(raw, baseURL, env)) {
16636
+ return Promise.resolve({ status: "failed", reason: "url_rejected" });
16637
+ }
16638
+ const [command, args] = openerArgv(raw);
16639
+ if (!command) {
16640
+ return Promise.resolve({ status: "unavailable", reason: "no system opener on this platform" });
16641
+ }
16642
+ return new Promise((resolvePromise) => {
16643
+ const child = spawn(command, args, { detached: true, stdio: "ignore" });
16644
+ child.once("error", (error) => resolvePromise({ status: "failed", reason: error.message }));
16645
+ child.once("spawn", () => {
16646
+ child.unref();
16647
+ resolvePromise({ status: "dispatch_accepted", argv: [command, ...args] });
16648
+ });
16649
+ });
16650
+ }
16651
+ __name(openInSystemBrowser, "openInSystemBrowser");
16652
+ function openerArgv(url) {
16653
+ switch (platform()) {
16654
+ case "darwin":
16655
+ return ["open", [url]];
16656
+ case "win32":
16657
+ return ["cmd.exe", ["/c", "start", "", url]];
16658
+ case "linux":
16659
+ case "freebsd":
16660
+ case "openbsd":
16661
+ return ["xdg-open", [url]];
16662
+ default:
16663
+ return [void 0, []];
16664
+ }
16665
+ }
16666
+ __name(openerArgv, "openerArgv");
16667
+
16429
16668
  // src/render/qr.ts
16430
16669
  var import_qrcode = __toESM(require_lib(), 1);
16431
16670
  import fs from "node:fs/promises";
16432
16671
  import os from "node:os";
16433
16672
  import path from "node:path";
16434
- import { randomUUID as randomUUID5 } from "node:crypto";
16673
+ import { randomUUID as randomUUID6 } from "node:crypto";
16435
16674
  function terminalQRType(format) {
16436
16675
  return format === "utf8" ? "utf8" : "terminal";
16437
16676
  }
@@ -16446,7 +16685,7 @@ async function renderTerminalQR(url, format) {
16446
16685
  __name(renderTerminalQR, "renderTerminalQR");
16447
16686
  async function writeLocalPNG(url) {
16448
16687
  const dir = await fs.mkdtemp(path.join(process.env.ITPAY_STATE_DIR || os.tmpdir(), "itpay-v3-"));
16449
- const filePath = path.join(dir, `itpay-${randomUUID5()}.png`);
16688
+ const filePath = path.join(dir, `itpay-${randomUUID6()}.png`);
16450
16689
  await import_qrcode.default.toFile(filePath, url, {
16451
16690
  type: "png",
16452
16691
  errorCorrectionLevel: "M",
@@ -16480,15 +16719,15 @@ function renderInlineTerminalImage(filePath, out) {
16480
16719
  __name(renderInlineTerminalImage, "renderInlineTerminalImage");
16481
16720
 
16482
16721
  // src/render/ide.ts
16483
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
16484
- import { join as join2 } from "node:path";
16722
+ import { mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as renameSync2, writeFileSync as writeFileSync5 } from "node:fs";
16723
+ import { join as join3 } from "node:path";
16485
16724
  import { tmpdir } from "node:os";
16486
- import { createHash as createHash6, randomUUID as randomUUID6 } from "node:crypto";
16725
+ import { createHash as createHash7, randomUUID as randomUUID7 } from "node:crypto";
16487
16726
  var IDE_ATTACH_REASON = "\u7ACB\u5373\u5C55\u793A\u5DF2\u6838\u9A8C\u5B98\u65B9\u94FE\u63A5\u548C\u771F\u5B9E\u671F\u9650\uFF1B\u56FE\u7247\u53EA\u662F\u589E\u5F3A\u5448\u73B0\u3002\u5DF2\u6709\u5DE5\u5177\u652F\u6301\u65F6\u5C55\u793A\u56FE\u7247\uFF0C\u5931\u8D25\u6216\u4E0D\u53EF\u7528\u5219\u5F53\u8F6E\u4EA4\u4ED8\u540C\u4E00\u94FE\u63A5\uFF0C\u4E0D\u7814\u7A76\u5DE5\u5177\u3001\u4E0D\u7B49\u5F85\u56FE\u7247\u786E\u8BA4\u3001\u4E0D\u91CD\u5EFA\u9875\u9762\u6216\u5BA3\u79F0\u4ED8\u6B3E\u3002";
16488
16727
  function canonicalDir(env = process.env) {
16489
16728
  const override = env.ITPAY_IDE_IMAGE_DIR_OVERRIDE;
16490
16729
  if (override && override.length > 0) return override;
16491
- return join2(tmpdir(), "itpay-v3-qr");
16730
+ return join3(tmpdir(), "itpay-v3-qr");
16492
16731
  }
16493
16732
  __name(canonicalDir, "canonicalDir");
16494
16733
  function resolveIdeImageDirs(env = process.env) {
@@ -16506,8 +16745,8 @@ function resolveIdeImageDirs(env = process.env) {
16506
16745
  }
16507
16746
  __name(resolveIdeImageDirs, "resolveIdeImageDirs");
16508
16747
  function stableNameFor(kind, id) {
16509
- const safeID = id.replace(/[^a-zA-Z0-9_-]/g, "_") || randomUUID6();
16510
- const hash = createHash6("sha1").update(`${kind}:${id}`).digest("hex").slice(0, 6);
16748
+ const safeID = id.replace(/[^a-zA-Z0-9_-]/g, "_") || randomUUID7();
16749
+ const hash = createHash7("sha1").update(`${kind}:${id}`).digest("hex").slice(0, 6);
16511
16750
  return `itpay-v3-${kind}-${safeID}-${hash}`;
16512
16751
  }
16513
16752
  __name(stableNameFor, "stableNameFor");
@@ -16540,9 +16779,9 @@ async function detectImageFormat(url, fetchFn) {
16540
16779
  }
16541
16780
  __name(detectImageFormat, "detectImageFormat");
16542
16781
  function atomicWrite(filePath, body) {
16543
- const tmp = `${filePath}.tmp-${randomUUID6()}`;
16782
+ const tmp = `${filePath}.tmp-${randomUUID7()}`;
16544
16783
  writeFileSync5(tmp, body);
16545
- renameSync3(tmp, filePath);
16784
+ renameSync2(tmp, filePath);
16546
16785
  }
16547
16786
  __name(atomicWrite, "atomicWrite");
16548
16787
  function mirrorToDirs(fileName, body, dirs) {
@@ -16550,7 +16789,7 @@ function mirrorToDirs(fileName, body, dirs) {
16550
16789
  for (const dir of dirs.slice(1)) {
16551
16790
  try {
16552
16791
  mkdirSync6(dir, { recursive: true });
16553
- const target2 = join2(dir, fileName);
16792
+ const target2 = join3(dir, fileName);
16554
16793
  atomicWrite(target2, body);
16555
16794
  written.push(target2);
16556
16795
  } catch {
@@ -16594,7 +16833,7 @@ async function downloadBrandQRToTmp(url, kind, id, options = {}) {
16594
16833
  if (!url) {
16595
16834
  return { ok: false, reason: "no qr_png_url on plan" };
16596
16835
  }
16597
- const stem = stableNameFor(kind, id ?? randomUUID6());
16836
+ const stem = stableNameFor(kind, id ?? randomUUID7());
16598
16837
  const dirs = resolveIdeImageDirs();
16599
16838
  const canonical = dirs[0];
16600
16839
  if (!canonical) {
@@ -16622,7 +16861,7 @@ async function downloadBrandQRToTmp(url, kind, id, options = {}) {
16622
16861
  if (timer) clearTimeout(timer);
16623
16862
  }
16624
16863
  const fileName = `${stem}${detected.ext}`;
16625
- const filePath = join2(canonical, fileName);
16864
+ const filePath = join3(canonical, fileName);
16626
16865
  atomicWrite(filePath, detected.body);
16627
16866
  const mirrors = mirrorToDirs(fileName, detected.body, dirs);
16628
16867
  return {
@@ -17292,6 +17531,23 @@ async function presentServiceCheckout(backend, config, serviceExecutionID, respo
17292
17531
  assertCheckoutPayable(checkout, authoritative, response.cart.cart_id, serviceExecutionID);
17293
17532
  if (authoritative) response.cart.items = authoritative.items;
17294
17533
  const checkoutID = checkout.checkout.checkout_id;
17534
+ const agentType = options.agentType ?? config.agentType;
17535
+ if (agentType === "dot" || agentType === "muse") {
17536
+ const entry = checkout.official_entry;
17537
+ let url;
17538
+ try {
17539
+ if (entry) url = new URL(entry.url);
17540
+ } catch {
17541
+ }
17542
+ const readOriginal = { command: `itpay --agent-type ${agentType} services get ${serviceExecutionID} --json`, reason: "\u7528\u6237\u5B8C\u6210\u9875\u9762\u64CD\u4F5C\u540E\u8BFB\u53D6\u539F\u4EFB\u52A1\u4E8B\u5B9E" };
17543
+ if (!entry || entry.access !== "account_session" || entry.url !== checkout.checkout_url || !url || !isPresentableURL(entry.url, config.baseURL) || url.protocol !== "https:" || url.username || url.password || url.search || url.hash || url.pathname !== `/checkout/${encodeURIComponent(checkoutID)}`) {
17544
+ throw new CommandContractError("secure_handoff_unavailable", "original purchase has no verified account-session entry", "\u4FDD\u7559\u539F\u8D2D\u4E70\uFF1B\u5F53\u524D\u8D26\u53F7\u5B89\u5168\u5165\u53E3\u4E0D\u53EF\u7528\uFF0C\u4E0D\u5C55\u793A\u6216\u62FC\u63A5 bearer \u94FE\u63A5\uFF0C\u4E0D\u6362\u8EAB\u4EFD\u6216\u91CD\u5EFA\u8D2D\u4E70\u3002", [readOriginal], void 0, { service_execution_id: serviceExecutionID, checkout_id: checkoutID });
17545
+ }
17546
+ const { itinerary: itinerary2 } = authoritative ? projectCheckoutPresentation(authoritative, currentModel) : {};
17547
+ const effects = { page_created: !response.handoff_reissued, page_reused: response.handoff_reissued === true, payment_requested: false, charged: false, human_page_action_required: true };
17548
+ writeCommandEnvelope({ status: "human_checkout_required", result: { service_execution_id: serviceExecutionID, checkout_id: checkoutID, amount: formatMoney(checkout.checkout.amount_minor, checkout.checkout.currency), effects, ...itinerary2 ? { itinerary: itinerary2 } : {}, agent_facts: presentAgent({ service_execution_id: serviceExecutionID, checkout_id: checkoutID, status: "human_checkout_required", checkout: { official_entry: entry }, effects }, { allowedOrigins: OFFICIAL_BACKEND_URLS }) }, handoff: { url: entry.url, purpose: entry.purpose, access: entry.access, ...entry.expires_at ? { expires_at: entry.expires_at } : {} }, instruction: "\u7ACB\u5373\u5C55\u793A\u5B98\u65B9\u94FE\u63A5\u53CA\u91D1\u989D\uFF1B\u7528\u6237\u767B\u5F55\u53D1\u8D77\u8FDE\u63A5\u7684\u8D26\u53F7\u5B8C\u6210\u5F53\u524D\u6B65\u9AA4\u3002\u4E8C\u7EF4\u7801\u4E0D\u662F\u524D\u7F6E\u6761\u4EF6\uFF0C\u6253\u5F00\u94FE\u63A5\u4E0D\u4EE3\u8868\u4ED8\u6B3E\u6216\u51FA\u7968\u3002\u7528\u6237\u8868\u793A\u5B8C\u6210\u540E\u8BFB\u53D6\u539F\u4EFB\u52A1\u4E8B\u5B9E\uFF0C\u4E0D\u91CD\u590D\u786E\u8BA4\u3001\u6362\u5355\u6216\u81EA\u52A8\u4ED8\u6B3E\u3002", next: readOriginal, recovery: [] }, { ...options.jsonOutput !== void 0 ? { jsonOutput: options.jsonOutput } : {}, ...options.output ? { output: options.output } : {} });
17549
+ return;
17550
+ }
17295
17551
  const displayToken = checkout.display_token;
17296
17552
  const locale = normalizeCardLocale(options.locale);
17297
17553
  const checkoutURL = tokenizedCheckoutURL(checkout.checkout_url, displayToken, checkout.qr_payload);
@@ -17435,29 +17691,38 @@ async function runServicesQuote(backend, serviceExecutionID, capabilityID, input
17435
17691
  __name(runServicesQuote, "runServicesQuote");
17436
17692
 
17437
17693
  // src/commands/services/purchase.ts
17438
- function invalid3() {
17439
- throw new CommandContractError("purchase_input_invalid", "purchase confirmation input is incomplete or invalid", "\u672C\u6B21\u672A\u53D1\u9001\u786E\u8BA4\u3002\u76F4\u63A5\u590D\u5236\u5F53\u524D\u5B8C\u6574 file_content\uFF1B\u6280\u672F\u5B57\u6BB5\u7531 Agent \u4FEE\u6B63\uFF0C\u53EA\u6709\u7F3A\u5931\u7684\u771F\u5B9E\u540C\u610F\u6216\u4EF7\u683C\u7EA6\u675F\u624D\u95EE\u7528\u6237\u3002", [], void 0, { request_sent: false });
17694
+ function invalid4(path3 = "input", allowed) {
17695
+ throw new CommandContractError("purchase_input_invalid", "purchase confirmation input is incomplete or invalid", "\u672C\u6B21\u672A\u53D1\u9001\u786E\u8BA4\u3002\u6309\u5F53\u524D confirmation_schema \u548C\u5B8C\u6574 file_content \u4FEE\u6B63\u6280\u672F\u5B57\u6BB5\uFF1B\u53EA\u6709\u7F3A\u5931\u7684\u771F\u5B9E\u540C\u610F\u6216\u4EF7\u683C\u51B3\u5B9A\u624D\u95EE\u7528\u6237\u3002", [], void 0, { request_sent: false, field: path3, ...allowed ? { allowed_values: allowed } : {} });
17440
17696
  }
17441
- __name(invalid3, "invalid");
17697
+ __name(invalid4, "invalid");
17442
17698
  function parsePurchaseConfirmation(raw) {
17443
- if (Object.keys(raw).some((key) => !["review_ref", "request_key", "user_approved", "user_answer", "price_policy"].includes(key))) invalid3();
17699
+ const keys = purchaseContract.required;
17700
+ for (const key of Object.keys(raw)) if (!keys.includes(key)) invalid4(key, keys);
17701
+ if (typeof raw.review_ref !== "string" || !raw.review_ref) invalid4("review_ref");
17702
+ if (typeof raw.request_key !== "string" || !raw.request_key || raw.request_key.length > purchaseContract.request_key_max_utf16_units) invalid4("request_key");
17703
+ if (raw.user_approved !== true) invalid4("user_approved", ["true"]);
17704
+ if (typeof raw.user_answer !== "string" || !raw.user_answer.trim()) invalid4("user_answer");
17444
17705
  const p = raw.price_policy;
17445
- if (typeof raw.review_ref !== "string" || !raw.review_ref || typeof raw.request_key !== "string" || !raw.request_key || raw.request_key.length > 200 || raw.user_approved !== true || typeof raw.user_answer !== "string" || !raw.user_answer.trim() || !p || typeof p !== "object" || Array.isArray(p)) invalid3();
17446
- if (!("mode" in p) || !("currency" in p) || typeof p.currency !== "string" || !p.currency || Object.keys(p).some((key) => !["mode", "currency", "amount_minor", "maximum_minor"].includes(key))) invalid3();
17447
- const safeAmount = /* @__PURE__ */ __name((n) => typeof n === "number" && Number.isSafeInteger(n) && n >= 0, "safeAmount");
17448
- if (p.mode === "exact" && "amount_minor" in p && safeAmount(p.amount_minor) && !("maximum_minor" in p)) return { review_ref: raw.review_ref, request_key: raw.request_key, user_approved: true, user_answer: raw.user_answer, price_policy: { mode: "exact", currency: p.currency, amount_minor: p.amount_minor } };
17449
- if (p.mode === "capped" && "maximum_minor" in p && safeAmount(p.maximum_minor) && !("amount_minor" in p)) return { review_ref: raw.review_ref, request_key: raw.request_key, user_approved: true, user_answer: raw.user_answer, price_policy: { mode: "capped", currency: p.currency, maximum_minor: p.maximum_minor } };
17450
- if (p.mode === "confirm_on_official_page" && !("amount_minor" in p) && !("maximum_minor" in p)) return { review_ref: raw.review_ref, request_key: raw.request_key, user_approved: true, user_answer: raw.user_answer, price_policy: { mode: "confirm_on_official_page", currency: p.currency } };
17451
- return invalid3();
17706
+ if (!p || typeof p !== "object" || Array.isArray(p)) invalid4("price_policy");
17707
+ if (!("mode" in p) || typeof p.mode !== "string" || !Object.hasOwn(purchaseContract.modes, p.mode)) invalid4("price_policy.mode", Object.keys(purchaseContract.modes));
17708
+ if (!("currency" in p) || typeof p.currency !== "string" || !p.currency) invalid4("price_policy.currency");
17709
+ const safeAmount = /* @__PURE__ */ __name((n) => typeof n === "number" && Number.isSafeInteger(n) && n >= 0 && n <= purchaseContract.amount_maximum, "safeAmount");
17710
+ const amountField = p.mode === "exact" ? purchaseContract.modes.exact : p.mode === "capped" ? purchaseContract.modes.capped : null;
17711
+ const allowedFields = ["mode", "currency", ...amountField ? [amountField] : []];
17712
+ for (const key of Object.keys(p)) if (!allowedFields.includes(key)) invalid4(`price_policy.${key}`, allowedFields);
17713
+ if (p.mode === "exact" && "amount_minor" in p && safeAmount(p.amount_minor)) return { review_ref: raw.review_ref, request_key: raw.request_key, user_approved: true, user_answer: raw.user_answer, price_policy: { mode: "exact", currency: p.currency, amount_minor: p.amount_minor } };
17714
+ if (p.mode === "capped" && "maximum_minor" in p && safeAmount(p.maximum_minor)) return { review_ref: raw.review_ref, request_key: raw.request_key, user_approved: true, user_answer: raw.user_answer, price_policy: { mode: "capped", currency: p.currency, maximum_minor: p.maximum_minor } };
17715
+ if (p.mode === "confirm_on_official_page") return { review_ref: raw.review_ref, request_key: raw.request_key, user_approved: true, user_answer: raw.user_answer, price_policy: { mode: "confirm_on_official_page", currency: p.currency } };
17716
+ return invalid4(`price_policy.${amountField}`);
17452
17717
  }
17453
17718
  __name(parsePurchaseConfirmation, "parsePurchaseConfirmation");
17454
17719
  async function runServicesPurchase(backend, config, id, input, options = {}) {
17455
17720
  const confirm = input ? parsePurchaseConfirmation(input) : void 0;
17456
- if (confirm && options.resume) invalid3();
17721
+ if (confirm && options.resume) invalid4();
17457
17722
  const contextError = validateContext(options.host ?? "terminal", options.target);
17458
17723
  if (contextError) throw new CommandContractError(contextError.code, contextError.message, "\u8865\u9F50\u5F53\u524D\u53EF\u4FE1 Host/target\uFF1B\u672C\u6B21\u672A\u53D1\u9001\u786E\u8BA4\u3002", [], void 0, { request_sent: false });
17459
17724
  const seconds = options.timeoutSeconds ?? 60;
17460
- if (!Number.isFinite(seconds) || seconds <= 0 || seconds > 120) invalid3();
17725
+ if (!Number.isFinite(seconds) || seconds <= 0 || seconds > 120) invalid4();
17461
17726
  let deadline = options.deadline ?? Date.now() + seconds * 1e3;
17462
17727
  let failureStage = confirm ? "confirm_purchase" : options.resume ? "resume_purchase" : "read_purchase_review";
17463
17728
  try {
@@ -17526,11 +17791,11 @@ __name(runAftercareRespond, "runAftercareRespond");
17526
17791
  import { rmSync } from "node:fs";
17527
17792
 
17528
17793
  // src/state/auth_storage.ts
17529
- import { createHash as createHash7 } from "node:crypto";
17530
- import { dirname as dirname4, resolve as resolve4 } from "node:path";
17531
- import { existsSync as existsSync4, mkdirSync as mkdirSync7, readFileSync as readFileSync8, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "node:fs";
17794
+ import { createHash as createHash8 } from "node:crypto";
17795
+ import { dirname as dirname3, resolve as resolve4 } from "node:path";
17796
+ import { existsSync as existsSync4, mkdirSync as mkdirSync7, readFileSync as readFileSync8, renameSync as renameSync3, writeFileSync as writeFileSync6 } from "node:fs";
17532
17797
  function authStatePath(baseURL, env, purpose) {
17533
- return resolve4(stateDir(env), `${purpose}-${createHash7("sha256").update(baseURL).digest("hex").slice(0, 16)}.json`);
17798
+ return resolve4(stateDir(env), `${purpose}-${createHash8("sha256").update(baseURL).digest("hex").slice(0, 16)}.json`);
17534
17799
  }
17535
17800
  __name(authStatePath, "authStatePath");
17536
17801
  function readAuthState(baseURL, env, purpose) {
@@ -17543,10 +17808,10 @@ function readAuthState(baseURL, env, purpose) {
17543
17808
  __name(readAuthState, "readAuthState");
17544
17809
  function saveAuthState(state, env, purpose) {
17545
17810
  const path3 = authStatePath(state.baseURL, env, purpose);
17546
- mkdirSync7(dirname4(path3), { recursive: true, mode: 448 });
17811
+ mkdirSync7(dirname3(path3), { recursive: true, mode: 448 });
17547
17812
  const tmp = `${path3}.${process.pid}.tmp`;
17548
17813
  writeFileSync6(tmp, JSON.stringify(state), { mode: 384 });
17549
- renameSync4(tmp, path3);
17814
+ renameSync3(tmp, path3);
17550
17815
  }
17551
17816
  __name(saveAuthState, "saveAuthState");
17552
17817
 
@@ -17879,6 +18144,16 @@ function servicesNextEnvelope(model) {
17879
18144
  if (model.purchase_review) return purchaseEnvelope({ status: "confirmation_required", service_execution_id: execution.service_execution_id, completed_stage: "selected", review: model.purchase_review, effects: { page_created: false, page_reused: false, payment_requested: false, charged: false, human_page_action_required: false } });
17880
18145
  if (model.purchase_preparation) return { status: model.purchase_preparation === "expired" ? "purchase_review_expired" : "purchase_review_unavailable", result: { service_execution_id: execution.service_execution_id, purchase_preparation: model.purchase_preparation }, instruction: "\u5F53\u524D\u8D2D\u4E70\u6750\u6599\u65E0\u6CD5\u7528\u4E8E\u786E\u8BA4\uFF1B\u4FDD\u7559\u540C\u4E00\u6267\u884C\u4E0E\u539F\u4ED8\u6B3E\u4E8B\u5B9E\uFF0C\u53EA\u8BFB\u53D6\u539F\u8D2D\u4E70\u72B6\u6001\uFF0C\u4E0D\u5207\u6362\u4E0B\u5355\u8DEF\u5F84\u6216\u65B0\u5EFA\u8D2D\u4E70\u3002", next: null, recovery: [{ command: `itpay services purchase ${execution.service_execution_id} --json`, reason: "\u8BFB\u53D6\u539F\u8D2D\u4E70\u7684\u5F53\u524D\u6750\u6599\u53CA\u9002\u7528\u6062\u590D\u52A8\u4F5C" }] };
17881
18146
  const businessState = adapter2.projectState(model);
18147
+ const scheduling = model.scheduling;
18148
+ if (scheduling?.accepted === true && scheduling.state === "queued" && scheduling.execution_id === execution.service_execution_id && !model.workflow?.human_action && (!businessState || ["queued", "running", "planning", "pending"].includes(businessState.status))) {
18149
+ return {
18150
+ status: "queued",
18151
+ result: { accepted: true, service_execution_id: execution.service_execution_id, reason: scheduling.reason, retry_after_ms: scheduling.retry_after_ms },
18152
+ instruction: "\u67E5\u8BE2\u5DF2\u63A5\u6536\uFF0C\u6B63\u5728\u7B49\u5F85\u670D\u52A1\u5904\u7406\u3002\u6309\u4E0B\u4E00\u6B65\u7EE7\u7EED\u67E5\u770B\u540C\u4E00\u6761\u67E5\u8BE2\uFF0C\u65E0\u9700\u91CD\u65B0\u63D0\u4EA4\uFF1B\u7B49\u5F85\u4E0D\u4EE3\u8868\u6CA1\u6709\u7ED3\u679C\u3002",
18153
+ next: { command: `itpay services next ${execution.service_execution_id} --timeout 60 --json`, reason: "\u5728\u5269\u4F59\u81EA\u52A8\u7B49\u5F85\u9884\u7B97\u5185\u8BFB\u53D6\u539F\u67E5\u8BE2", poll_after_ms: scheduling.retry_after_ms },
18154
+ recovery: []
18155
+ };
18156
+ }
17882
18157
  if (businessState) return businessState;
17883
18158
  const availableResult = adapter2.savedResult(model);
17884
18159
  if (availableResult && adapter2.shouldWait(model) === false) return availableResult;
@@ -18325,6 +18600,12 @@ function shouldWaitForServiceResult(model) {
18325
18600
  return ["queued", "running", "delivery"].includes(model.workflow?.status ?? "");
18326
18601
  }
18327
18602
  __name(shouldWaitForServiceResult, "shouldWaitForServiceResult");
18603
+ function servicePollDelay(model, requested) {
18604
+ const scheduling = model.scheduling;
18605
+ const retry = scheduling?.accepted === true && scheduling.execution_id === model.execution.service_execution_id && Number.isFinite(scheduling.retry_after_ms) ? scheduling.retry_after_ms : 0;
18606
+ return Math.max(1500, retry, requested ?? serviceAdapter(model.execution).pollAfter(model));
18607
+ }
18608
+ __name(servicePollDelay, "servicePollDelay");
18328
18609
  async function runServicesNext(backend, serviceExecutionID, options = {}) {
18329
18610
  const started = options.startedAt ?? Date.now();
18330
18611
  const env = options.env ?? process.env;
@@ -18336,7 +18617,7 @@ async function runServicesNext(backend, serviceExecutionID, options = {}) {
18336
18617
  while (shouldWaitForServiceResult(response) && Date.now() < until) {
18337
18618
  const pollStarted = Date.now();
18338
18619
  try {
18339
- await sleep(Math.min(Math.max(1500, options.pollIntervalMS ?? serviceAdapter(response.execution).pollAfter(response)), Math.max(0, until - Date.now())));
18620
+ await sleep(Math.min(servicePollDelay(response, options.pollIntervalMS), Math.max(0, until - Date.now())));
18340
18621
  if (Date.now() >= until) break;
18341
18622
  try {
18342
18623
  response = await backend.getServiceExecution(serviceExecutionID, { ...options.sinceSnapshot ? { sinceSnapshot: options.sinceSnapshot } : {}, deadline: until });
@@ -18354,7 +18635,7 @@ async function runServicesNext(backend, serviceExecutionID, options = {}) {
18354
18635
  const remaining = remainingAutomaticWait(serviceExecutionID, env);
18355
18636
  if (shouldWaitForServiceResult(response)) {
18356
18637
  envelope.result = { ...envelope.result, waited_seconds: Math.round(waitedMS / 1e3), auto_wait_remaining_ms: remaining, wait_timed_out: Boolean(options.timeoutSeconds) };
18357
- const resume = { command: `itpay services next ${serviceExecutionID} --timeout 60 --json`, reason: remaining > 0 ? "\u4ECD\u5728\u5904\u7406\uFF0C\u672A\u5931\u8D25\uFF1B\u5728\u5269\u4F59\u9884\u7B97\u5185\u8BFB\u53D6\u540C\u4E00\u4EFB\u52A1" : "\u4EC5\u7528\u6237\u660E\u786E\u8981\u6C42\u7EE7\u7EED\u65F6\u8BFB\u53D6\u539F\u4EFB\u52A1", poll_after_ms: 1500 };
18638
+ const resume = { command: `itpay services next ${serviceExecutionID} --timeout 60 --json`, reason: remaining > 0 ? "\u4ECD\u5728\u5904\u7406\uFF0C\u672A\u5931\u8D25\uFF1B\u5728\u5269\u4F59\u9884\u7B97\u5185\u8BFB\u53D6\u540C\u4E00\u4EFB\u52A1" : "\u4EC5\u7528\u6237\u660E\u786E\u8981\u6C42\u7EE7\u7EED\u65F6\u8BFB\u53D6\u539F\u4EFB\u52A1", poll_after_ms: servicePollDelay(response, options.pollIntervalMS) };
18358
18639
  envelope.next = remaining > 0 ? resume : null;
18359
18640
  if (remaining === 0) {
18360
18641
  envelope.recovery = [resume];
@@ -18429,7 +18710,7 @@ async function runServicesRun(backend, config, serviceID, input, options = {}) {
18429
18710
  while ((["queued", "running", "delivery", "quota_paused"].includes(model.workflow?.status ?? "") || model.workflow?.status === "payment" && paid()) && shouldWaitForServiceResult(model) && Date.now() < until) {
18430
18711
  const pollStarted = Date.now();
18431
18712
  try {
18432
- await sleep(Math.min(Math.max(1500, options.pollIntervalMS ?? 1500), Math.max(0, until - Date.now())));
18713
+ await sleep(Math.min(servicePollDelay(model, options.pollIntervalMS), Math.max(0, until - Date.now())));
18433
18714
  if (Date.now() >= until) break;
18434
18715
  try {
18435
18716
  model = await backend.getServiceExecution(id, { deadline: until });
@@ -18466,6 +18747,17 @@ async function runServicesRun(backend, config, serviceID, input, options = {}) {
18466
18747
  if (!id && cause instanceof HttpError && typeof cause.payload?.service_execution_id === "string") id = cause.payload.service_execution_id;
18467
18748
  if (cause instanceof HttpError) adapter2 = errorServiceAdapter(cause.payload, serviceID) ?? adapter2;
18468
18749
  if (cause instanceof HttpError && cause.code === "public_operation_invalid") throw new CommandContractError(cause.code, cause.message, "\u6309\u8FD4\u56DE\u7684\u56FA\u5B9Aservice_definition\u6838\u5BF9\u58F0\u660E\u64CD\u4F5C\uFF1B\u8D2D\u4E70\u4ECD\u4F7F\u7528\u539F\u7ED3\u679C\u8BE6\u60C5\u7684\u5B8C\u6574continuation\u6A21\u677F\uFF0C\u4E0D\u6539owner/snapshot\u3001\u4E0D\u731Coperation\u3001\u4E0D\u91CD\u5EFA\u539F\u8D2D\u4E70\u3002", cause.payload?.service_definition ? [] : [{ command: "itpay catalog list --json", reason: "\u53EA\u8BFB\u516C\u5F00\u76EE\u5F55\u4E0E\u5B9A\u4E49\uFF1B\u4E0D\u521B\u5EFA\u6267\u884C" }], void 0, { service_id: serviceID, ...cause.payload?.service_definition ? { service_definition: cause.payload.service_definition } : {}, execution_created: id ? true : typeof cause.payload?.execution_created === "boolean" ? cause.payload.execution_created : "unknown", ...typeof cause.payload?.provider_called === "boolean" ? { provider_called: cause.payload.provider_called } : {} });
18750
+ if (cause instanceof HttpError && cause.code === "query_capacity_not_accepted" && cause.payload?.accepted === false) {
18751
+ writeCommandEnvelope({
18752
+ status: "not_accepted",
18753
+ result: { accepted: false, execution_created: Boolean(id), ...id ? { service_execution_id: id } : {}, provider_called: false, reason: cause.payload.reason, retry_after_ms: cause.payload.retry_after_ms },
18754
+ instruction: id ? "\u672C\u6B21\u8F93\u5165\u5C1A\u672A\u63A5\u6536\uFF1B\u4FDD\u7559\u539F\u6267\u884C\u548C\u6761\u4EF6\uFF0C\u6309\u8FD4\u56DE\u7684\u7B49\u5F85\u65F6\u95F4\u91CD\u8BD5\u540C\u4E00\u6267\u884C\uFF0C\u4E0D\u65B0\u5EFA\u67E5\u8BE2\u6216\u6269\u5927\u8303\u56F4\u3002" : "\u672C\u6B21\u67E5\u8BE2\u5C1A\u672A\u63A5\u6536\uFF0C\u6CA1\u6709\u65B0\u6267\u884C\u7F16\u53F7\u3002\u6309\u8FD4\u56DE\u7684\u7B49\u5F85\u65F6\u95F4\u4FDD\u7559\u539F\u6761\u4EF6\u91CD\u8BD5\uFF1B\u4E0D\u8981\u8BFB\u53D6\u4E0D\u5B58\u5728\u7684\u4EFB\u52A1\u3001\u6362\u7AD9\u6216\u6269\u5927\u8303\u56F4\u3002",
18755
+ next: null,
18756
+ recovery: [],
18757
+ ...input !== void 0 ? { interaction: { schema_version: "itpay.interaction.v1", stage: "input_required", input_template: operationInputTemplate({ ...inputContext, executionID: id }, input) } } : {}
18758
+ }, options);
18759
+ return;
18760
+ }
18469
18761
  if (cause instanceof HttpError && cause.code === "capability_input_invalid") {
18470
18762
  const schema = cause.payload?.input_schema;
18471
18763
  const executionID = cause.payload?.service_execution_id ?? id;
@@ -18855,9 +19147,9 @@ var {
18855
19147
  } = import_index.default;
18856
19148
 
18857
19149
  // src/state/cart_session.ts
18858
- import { chmodSync as chmodSync2, existsSync as existsSync5, mkdirSync as mkdirSync8, readFileSync as readFileSync9, renameSync as renameSync5, writeFileSync as writeFileSync7 } from "node:fs";
18859
- import { randomUUID as randomUUID7 } from "node:crypto";
18860
- import { dirname as dirname5 } from "node:path";
19150
+ import { chmodSync as chmodSync2, existsSync as existsSync5, mkdirSync as mkdirSync8, readFileSync as readFileSync9, renameSync as renameSync4, writeFileSync as writeFileSync7 } from "node:fs";
19151
+ import { randomUUID as randomUUID8 } from "node:crypto";
19152
+ import { dirname as dirname4 } from "node:path";
18861
19153
  var CartSession = class _CartSession {
18862
19154
  static {
18863
19155
  __name(this, "CartSession");
@@ -18906,11 +19198,11 @@ var CartSession = class _CartSession {
18906
19198
  };
18907
19199
  const contents = JSON.stringify(toSave, null, 2);
18908
19200
  if (existsSync5(path3) && readFileSync9(path3, "utf-8") === contents) return;
18909
- mkdirSync8(dirname5(path3), { recursive: true, mode: 448 });
18910
- const temporary = `${path3}.${process.pid}.${randomUUID7()}.tmp`;
19201
+ mkdirSync8(dirname4(path3), { recursive: true, mode: 448 });
19202
+ const temporary = `${path3}.${process.pid}.${randomUUID8()}.tmp`;
18911
19203
  writeFileSync7(temporary, contents, { encoding: "utf-8", mode: 384 });
18912
19204
  chmodSync2(temporary, 384);
18913
- renameSync5(temporary, path3);
19205
+ renameSync4(temporary, path3);
18914
19206
  chmodSync2(path3, 384);
18915
19207
  }
18916
19208
  add(item) {
@@ -19034,6 +19326,8 @@ __name(versionParts, "versionParts");
19034
19326
 
19035
19327
  // src/commands/install.ts
19036
19328
  var INSTALL_AGENT_TYPES = [
19329
+ "dot",
19330
+ "muse",
19037
19331
  "codex-desktop",
19038
19332
  "codex-cli",
19039
19333
  "claude-code-desktop",
@@ -19042,10 +19336,14 @@ var INSTALL_AGENT_TYPES = [
19042
19336
  "zcode",
19043
19337
  "doubao-work",
19044
19338
  "kimi-code",
19045
- "openclaw"
19339
+ "openclaw",
19340
+ "hermes"
19046
19341
  ];
19047
19342
  var CODEX_WAIT_GUIDANCE = "Codex \u5BBF\u4E3B\u7B49\u5F85\uFF1A\u4FDD\u7559\u5B8C\u6574\u5DE5\u5177\u8FD4\u56DE\uFF0C\u6309\u5B9E\u9645\u8FD4\u56DE\u7684\u4F1A\u8BDD\u53E5\u67C4\u53CA\u5F53\u524D\u5BBF\u4E3B\u7EED\u8BFB\u5DE5\u5177\u6536\u53D6\u6700\u7EC8\u8F93\u51FA\uFF0C\u4E0D\u8981\u53EA\u53D6 stdout\u3002\u82E5\u4F7F\u7528 functions.exec \u5305\u88C5\uFF0C\u53EF\u7528 text(await tools.exec_command(...))\uFF1B\u5185\u5C42\u6709 session_id \u65F6\u7528 write_stdin\uFF0C\u5916\u5C42\u8FD4\u56DE\u8FD0\u884C cell \u65F6\u624D\u7528 wait\u3002\u6CA1\u6709\u8BE5\u5305\u88C5\u65F6\u6309\u5BBF\u4E3B\u5B9E\u9645\u5DE5\u5177\u64CD\u4F5C\u3002\u5148\u6536\u53D6\u6700\u7EC8\u8F93\u51FA\uFF0C\u518D\u6267\u884C CLI \u4E1A\u52A1 next\uFF1B\u4E0D\u8981\u91CD\u590D\u63D0\u4EA4\u3002";
19048
19343
  var INSTRUCTIONS = {
19344
+ hermes: "\u4FDD\u6301\u771F\u5B9E hermes Agent Type\uFF1B\u6309\u5F53\u524D\u5B9E\u9645\u5BBF\u4E3B\u5448\u73B0\u5B98\u65B9\u94FE\u63A5\uFF0C\u672A\u77E5\u663E\u793A\u80FD\u529B\u5982\u5B9E\u4FDD\u7559\u3002\u6CBF\u540C\u4E00 launcher\u3001Backend \u4E0E ITPAY_STATE_DIR \u6062\u590D\uFF0C\u4E0D\u5207\u6362\u8EAB\u4EFD\u6216\u91CD\u7F6E\u989D\u5EA6\u3002",
19345
+ dot: "\u4F7F\u7528\u771F\u5B9E dot \u7C7B\u578B\uFF1B\u4E91\u7AEF\u6267\u884C\u4F4D\u7F6E\u4E0E\u7528\u6237\u663E\u793A\u7AEF\u5206\u522B\u5224\u65AD\u3002\u5C55\u793A\u5B98\u65B9\u53EF\u70B9\u51FB\u94FE\u63A5\uFF0C\u4E8C\u7EF4\u7801\u53EF\u7528\u65F6\u589E\u5F3A\u5C55\u793A\uFF1B\u6D4F\u89C8\u5668\u6253\u5F00\u4E0D\u7B49\u4E8E\u7528\u6237\u5DF2\u770B\u5230\u3002\u540E\u7EED\u4FDD\u6301\u540C\u4E00 launcher\u3001Backend \u548C ITPAY_STATE_DIR\u3002",
19346
+ muse: "\u4F7F\u7528\u771F\u5B9E muse \u7C7B\u578B\uFF1B\u4FDD\u7559\u5BBF\u4E3B\u539F\u751F\u6279\u51C6\uFF0C\u4E0D\u7528\u804A\u5929\u540C\u610F\u66FF\u4EE3\u3002\u4E91\u7AEF\u53EF\u5199\u76EE\u5F55\u4E0D\u7B49\u4E8E\u8DE8\u4F1A\u8BDD\u6301\u4E45\uFF0C\u663E\u793A\u80FD\u529B\u672A\u77E5\u65F6\u5982\u5B9E\u62A5\u544A\uFF1B\u6CBF\u540C\u4E00 launcher\u3001Backend \u548C ITPAY_STATE_DIR \u6062\u590D\u539F\u4EFB\u52A1\u3002",
19049
19347
  "codex-desktop": "\u5728 Codex Desktop \u4E2D\u59CB\u7EC8\u4F20\u8FD9\u4E2A Agent Type\uFF1B\u4ED8\u6B3E\u65F6\u628A\u8FD4\u56DE\u7684\u4E8C\u7EF4\u7801\u548C\u94FE\u63A5\u5B9E\u9645\u5C55\u793A\u5230\u5F53\u524D\u5BF9\u8BDD\u3002",
19050
19348
  "codex-cli": "\u5728 Codex CLI \u4E2D\u59CB\u7EC8\u4F20\u8FD9\u4E2A Agent Type\uFF1B\u4ED8\u6B3E\u4EA4\u63A5\u53EA\u5E94\u663E\u793A\u5728\u7528\u6237\u53EF\u89C1\u7EC8\u7AEF\u3002",
19051
19349
  "claude-code-desktop": "\u5728 Claude Code Desktop \u4E2D\u59CB\u7EC8\u4F20\u8FD9\u4E2A Agent Type\uFF1B\u4ED8\u6B3E\u65F6\u628A\u8FD4\u56DE\u7684\u4E8C\u7EF4\u7801\u548C\u94FE\u63A5\u5B9E\u9645\u5C55\u793A\u5230\u5F53\u524D\u5BF9\u8BDD\u3002",
@@ -19107,17 +19405,23 @@ function installDefinition(agentType) {
19107
19405
  }
19108
19406
  __name(installDefinition, "installDefinition");
19109
19407
 
19408
+ // src/commands/skill.ts
19409
+ import { createHash as createHash9 } from "node:crypto";
19410
+
19411
+ // src/state/skill_identity.generated.ts
19412
+ var CANONICAL_SKILL_SHA256 = "9e36b56ef726cd1c7db603474fb977fa3cc5b84ef6b005d007e9f322ac534ce7";
19413
+
19110
19414
  // src/commands/skill.ts
19111
19415
  import { existsSync as existsSync7, readFileSync as readFileSync11 } from "node:fs";
19112
19416
  import { resolve as resolve6 } from "node:path";
19113
19417
 
19114
19418
  // src/state/package_resources.ts
19115
19419
  import { existsSync as existsSync6, readFileSync as readFileSync10 } from "node:fs";
19116
- import { basename as basename2, dirname as dirname6, resolve as resolve5 } from "node:path";
19420
+ import { basename as basename2, dirname as dirname5, resolve as resolve5 } from "node:path";
19117
19421
  import { fileURLToPath } from "node:url";
19118
19422
  function packageResourcePath(...segments) {
19119
19423
  const modulePath = fileURLToPath(import.meta.url);
19120
- const root = resolve5(dirname6(modulePath), "..", "..");
19424
+ const root = resolve5(dirname5(modulePath), "..", "..");
19121
19425
  if (!basename2(modulePath).startsWith("package_resources.") && basename2(modulePath) !== "main.js") throw new Error("unsupported CLI resource layout");
19122
19426
  const metadata = resolve5(root, "package.json");
19123
19427
  if (!existsSync6(metadata) || JSON.parse(readFileSync10(metadata, "utf8")).name !== "@itpay/cli") throw new Error("current CLI package resources are unavailable");
@@ -19129,7 +19433,7 @@ __name(packageResourcePath, "packageResourcePath");
19129
19433
  var ITPAY_SKILL = "itpay";
19130
19434
  function runSkillShow(name, options = {}) {
19131
19435
  const normalized = name.trim().toLowerCase();
19132
- if (normalized !== ITPAY_SKILL) {
19436
+ if (normalized !== ITPAY_SKILL && normalized !== "itpay-buyer") {
19133
19437
  throw new CommandContractError(
19134
19438
  "skill_not_found",
19135
19439
  `skill not found: ${name}`,
@@ -19187,8 +19491,12 @@ ${CODEX_WAIT_GUIDANCE}
19187
19491
  }
19188
19492
  __name(runSkillShow, "runSkillShow");
19189
19493
  function packagedSkill() {
19190
- const path3 = findSkillPath(false);
19494
+ let path3 = findSkillPath(false);
19495
+ if (!existsSync7(path3) && process.env.ITPAY_CLI_SKILLS_DIR) path3 = findSkillPath();
19191
19496
  const content = readFileSync11(path3, "utf8");
19497
+ if (createHash9("sha256").update(content).digest("hex") !== CANONICAL_SKILL_SHA256) {
19498
+ throw new CommandContractError("skill_override_mismatch", "Skill does not match this pinned CLI build", "\u4F7F\u7528\u5F53\u524D\u5305\u540C\u6E90\u7684\u5B8C\u6574 Skill\uFF1B\u4FDD\u7559\u539F\u4EFB\u52A1\u548C\u8EAB\u4EFD\uFF0C\u4E0D\u5B89\u88C5\u53E6\u4E00\u5957 CLI\u3002", []);
19499
+ }
19192
19500
  validateSkill(content);
19193
19501
  return { path: path3, content };
19194
19502
  }
@@ -19256,6 +19564,13 @@ async function runSetup(backend, config, skillPath, options = {}) {
19256
19564
  cli_version: CLI_VERSION2,
19257
19565
  backend_url: config.baseURL,
19258
19566
  agent_type: config.agentType,
19567
+ state_directory: stateDir(),
19568
+ state_persistence: "unverified_across_sessions",
19569
+ skill_readable: true,
19570
+ skill_written: "unknown",
19571
+ skill_discoverable: "unknown",
19572
+ execution_position: "unknown",
19573
+ presentation_surface: "unknown",
19259
19574
  device_status: "ready",
19260
19575
  account_status: account.status,
19261
19576
  skill_path: skillPath,
@@ -19704,63 +20019,6 @@ function formatProductMoney(amountMinor, currency) {
19704
20019
  }
19705
20020
  __name(formatProductMoney, "formatProductMoney");
19706
20021
 
19707
- // src/render/browser.ts
19708
- import { spawn } from "node:child_process";
19709
- import { platform } from "node:os";
19710
- function isPresentableURL(raw, baseURL, env = process.env) {
19711
- let url;
19712
- try {
19713
- url = new URL(raw);
19714
- } catch {
19715
- return false;
19716
- }
19717
- if (url.username || url.password) return false;
19718
- if (env.ITPAY_CLI_DEV === "1" && /^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(url.origin)) return true;
19719
- if (url.protocol !== "https:") return false;
19720
- const allowedOrigins = /* @__PURE__ */ new Set(["https://app.itpay.ai", "https://sandbox.itpay.ai", "https://dev.itpay.ai"]);
19721
- if (baseURL) {
19722
- try {
19723
- allowedOrigins.add(new URL(baseURL).origin);
19724
- } catch {
19725
- }
19726
- }
19727
- return allowedOrigins.has(url.origin);
19728
- }
19729
- __name(isPresentableURL, "isPresentableURL");
19730
- function openInSystemBrowser(raw, baseURL, env = process.env) {
19731
- if (!isPresentableURL(raw, baseURL, env)) {
19732
- return Promise.resolve({ status: "failed", reason: "url_rejected" });
19733
- }
19734
- const [command, args] = openerArgv(raw);
19735
- if (!command) {
19736
- return Promise.resolve({ status: "unavailable", reason: "no system opener on this platform" });
19737
- }
19738
- return new Promise((resolvePromise) => {
19739
- const child = spawn(command, args, { detached: true, stdio: "ignore" });
19740
- child.once("error", (error) => resolvePromise({ status: "failed", reason: error.message }));
19741
- child.once("spawn", () => {
19742
- child.unref();
19743
- resolvePromise({ status: "dispatch_accepted", argv: [command, ...args] });
19744
- });
19745
- });
19746
- }
19747
- __name(openInSystemBrowser, "openInSystemBrowser");
19748
- function openerArgv(url) {
19749
- switch (platform()) {
19750
- case "darwin":
19751
- return ["open", [url]];
19752
- case "win32":
19753
- return ["cmd.exe", ["/c", "start", "", url]];
19754
- case "linux":
19755
- case "freebsd":
19756
- case "openbsd":
19757
- return ["xdg-open", [url]];
19758
- default:
19759
- return [void 0, []];
19760
- }
19761
- }
19762
- __name(openerArgv, "openerArgv");
19763
-
19764
20022
  // src/commands/presentation.ts
19765
20023
  var yes = /* @__PURE__ */ __name((value) => value === "yes", "yes");
19766
20024
  function resolvePresentation(input) {
@@ -21344,7 +21602,7 @@ function writeCartNextEnvelope(envelope, options) {
21344
21602
  __name(writeCartNextEnvelope, "writeCartNextEnvelope");
21345
21603
 
21346
21604
  // src/commands/docs.ts
21347
- import { readFileSync as readFileSync12, readdirSync as readdirSync3 } from "node:fs";
21605
+ import { readFileSync as readFileSync12, readdirSync as readdirSync4 } from "node:fs";
21348
21606
  import { resolve as resolve7 } from "node:path";
21349
21607
  function runDocsList(options = {}) {
21350
21608
  const topics = loadDocs().map(({ topic, title, purpose }) => ({ topic, title, purpose }));
@@ -21419,11 +21677,11 @@ function runDocsSearch(query, options = {}) {
21419
21677
  __name(runDocsSearch, "runDocsSearch");
21420
21678
  function loadDocs() {
21421
21679
  const docsDir = findDocsDir();
21422
- const files = readdirSync3(docsDir).filter((file) => file.endsWith(".json")).sort();
21680
+ const files = readdirSync4(docsDir).filter((file) => file.endsWith(".json")).sort();
21423
21681
  const docs = files.map((file) => parseDoc(readFileSync12(resolve7(docsDir, file), "utf8"), file));
21424
21682
  if (process.env.ITPAY_CLI_DOCS_DIR) {
21425
21683
  const canonical = packageResourcePath("docs", "agent", "buyer");
21426
- const expectedFiles = readdirSync3(canonical).filter((file) => file.endsWith(".json")).sort();
21684
+ const expectedFiles = readdirSync4(canonical).filter((file) => file.endsWith(".json")).sort();
21427
21685
  if (JSON.stringify(files) !== JSON.stringify(expectedFiles) || files.some((file, index) => JSON.stringify(docs[index]) !== JSON.stringify(parseDoc(readFileSync12(resolve7(canonical, file), "utf8"), file)))) {
21428
21686
  throw new CommandContractError(
21429
21687
  "docs_override_mismatch",
@@ -21568,11 +21826,11 @@ function parseRequiredContactFields(value) {
21568
21826
  return void 0;
21569
21827
  }
21570
21828
  const values = value.split(",").map((item) => item.trim().toLowerCase()).filter(Boolean);
21571
- const invalid4 = values.filter((item) => item !== "email" && item !== "phone");
21572
- if (invalid4.length > 0) {
21829
+ const invalid5 = values.filter((item) => item !== "email" && item !== "phone");
21830
+ if (invalid5.length > 0) {
21573
21831
  throw new CommandContractError(
21574
21832
  "contact_field_invalid",
21575
- `unsupported required contact fields: ${invalid4.join(", ")}`,
21833
+ `unsupported required contact fields: ${invalid5.join(", ")}`,
21576
21834
  "--require-contact \u53EA\u63A5\u53D7 email\u3001phone \u6216\u4E8C\u8005\u7EC4\u5408\u3002",
21577
21835
  [{ command: "itpay buy --help", reason: "\u67E5\u770B contact \u53C2\u6570" }]
21578
21836
  );
@@ -21582,8 +21840,8 @@ function parseRequiredContactFields(value) {
21582
21840
  }
21583
21841
  __name(parseRequiredContactFields, "parseRequiredContactFields");
21584
21842
  function positiveInteger(value, name) {
21585
- const text = String(value ?? "");
21586
- if (!/^[1-9]\d*$/.test(text)) {
21843
+ const text2 = String(value ?? "");
21844
+ if (!/^[1-9]\d*$/.test(text2)) {
21587
21845
  throw new CommandContractError(
21588
21846
  "buy_parameter_invalid",
21589
21847
  `${name} must be a positive integer`,
@@ -21591,7 +21849,7 @@ function positiveInteger(value, name) {
21591
21849
  [{ command: "itpay buy --help", reason: "\u67E5\u770B\u53C2\u6570\u683C\u5F0F" }]
21592
21850
  );
21593
21851
  }
21594
- return Number(text);
21852
+ return Number(text2);
21595
21853
  }
21596
21854
  __name(positiveInteger, "positiveInteger");
21597
21855
  function resolveCheckoutPresentationArgs(input) {
@@ -21682,14 +21940,14 @@ function reportCLIError(error, contract) {
21682
21940
  } : {}
21683
21941
  }
21684
21942
  } : {},
21685
- instruction: incompatible ? "\u5F53\u524D CLI \u4E0E Backend \u5408\u7EA6\u4E0D\u517C\u5BB9\u6216\u65E0\u6CD5\u6838\u9A8C\u3002minimum_cli_version \u4EC5\u662F\u534F\u8BAE\u95E8\u69DB\uFF0C\u4E0D\u662F\u5DF2\u9A8C\u8BC1\u7684\u63A8\u8350\u5B89\u88C5\u5305\u3002\u505C\u6B62\u672C\u8F6E\uFF0C\u8BF7\u7EF4\u62A4\u65B9\u63D0\u4F9B\u4E0E\u5F53\u524D Backend \u914D\u5957\u7684\u5236\u54C1\uFF1B\u4E0D\u8981\u731C\u7248\u672C\u3001\u964D\u7EA7\u3001\u5207\u6362 Agent Type \u6216\u5220\u9664 Device \u8EAB\u4EFD\u3002" : backendInternal ? "\u544A\u8BC9\u7528\u6237 ItPay \u5F53\u524D\u6682\u65F6\u65E0\u6CD5\u5B8C\u6210\u8FD9\u9879\u670D\u52A1\u5E76\u505C\u6B62\u3002\u4E0D\u8981\u8F6C\u8FF0\u5185\u90E8\u9519\u8BEF\u3001\u91CD\u8BD5\u3001\u4FEE\u6539\u8EAB\u4EFD\u3001\u521B\u5EFA\u66FF\u4EE3\u670D\u52A1\u6216\u8FDB\u5165\u4EFB\u4F55\u4ED8\u8D39\u8DEF\u5F84\u3002" : providerConnectionUnavailable ? "\u544A\u8BC9\u7528\u6237\u672C\u6B21\u67E5\u8BE2\u6CA1\u6709\u53D1\u9001\u5230\u6570\u636E\u6765\u6E90\uFF0C\u514D\u8D39\u989D\u5EA6\u5DF2\u4FDD\u7559\uFF0C\u7136\u540E\u505C\u6B62\u3002\u4E0D\u8981\u8F6C\u8FF0\u6280\u672F\u9519\u8BEF\u3001\u81EA\u52A8\u91CD\u8BD5\u6216\u8FDB\u5165\u4ED8\u8D39\u8DEF\u5F84\uFF1B\u53EA\u6709\u670D\u52A1\u6062\u590D\u4E14\u7528\u6237\u660E\u786E\u8981\u6C42\u91CD\u65B0\u67E5\u8BE2\u540E\u624D\u80FD\u5F00\u59CB\u65B0\u7684\u67E5\u8BE2\u3002" : providerTemporary ? "\u544A\u8BC9\u7528\u6237\u6570\u636E\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u5E76\u6309 result.quota \u8BF4\u660E\u989D\u5EA6\u662F\u5426\u4FDD\u7559\uFF0C\u7136\u540E\u505C\u6B62\u3002\u4E0D\u8981\u8F6C\u8FF0\u6280\u672F\u9519\u8BEF\u3001\u81EA\u52A8\u91CD\u8BD5\u6216\u521B\u5EFA\u65B0\u67E5\u8BE2\uFF1B\u53EA\u6709\u7528\u6237\u4E4B\u540E\u660E\u786E\u63D0\u51FA\u65B0\u8BF7\u6C42\u624D\u53EF\u91CD\u65B0\u5F00\u59CB\u3002" : providerInputRejected ? "\u544A\u8BC9\u7528\u6237\u6570\u636E\u6765\u6E90\u660E\u786E\u8868\u793A\u5F53\u524D\u8F93\u5165\u65E0\u6548\uFF0C\u5E76\u6309 result.quota \u8BF4\u660E\u989D\u5EA6\u72B6\u6001\uFF0C\u7136\u540E\u505C\u6B62\u3002\u4E0D\u8981\u8F6C\u8FF0\u5185\u90E8\u9519\u8BEF\u3001\u81EA\u884C\u4FEE\u6539\u8F93\u5165\u3001\u91CD\u8BD5\u6216\u521B\u5EFA\u65B0\u67E5\u8BE2\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u63D0\u4F9B\u65B0\u8F93\u5165\u540E\u624D\u80FD\u91CD\u65B0\u67E5\u8BE2\u3002" : providerContractMismatch ? "\u544A\u8BC9\u7528\u6237\u5E73\u53F0\u6682\u65F6\u65E0\u6CD5\u6B63\u786E\u89E3\u91CA\u6570\u636E\u6765\u6E90\u7684\u54CD\u5E94\uFF0C\u8FD9\u4E0D\u662F\u7528\u6237\u8F93\u5165\u95EE\u9898\uFF0C\u5E76\u6309 result.quota \u8BF4\u660E\u989D\u5EA6\u72B6\u6001\u3002\u7ACB\u5373\u505C\u6B62\uFF0C\u4E0D\u8981\u4FEE\u6539\u8F93\u5165\u3001\u91CD\u8BD5\u3001\u521B\u5EFA\u65B0\u67E5\u8BE2\u6216\u8FDB\u5165\u4ED8\u8D39\u8DEF\u5F84\u3002" : providerRejected ? "\u544A\u8BC9\u7528\u6237\u6570\u636E\u6765\u6E90\u6CA1\u6709\u63A5\u53D7\u672C\u6B21\u8BF7\u6C42\uFF0C\u4F46\u6CA1\u6709\u8BF4\u660E\u662F\u8F93\u5165\u9519\u8BEF\uFF0C\u5E76\u6309 result.quota \u8BF4\u660E\u989D\u5EA6\u72B6\u6001\uFF0C\u7136\u540E\u505C\u6B62\u3002\u4E0D\u8981\u8F6C\u8FF0\u5185\u90E8\u9519\u8BEF\u3001\u4FEE\u6539\u8F93\u5165\u3001\u91CD\u8BD5\u6216\u521B\u5EFA\u65B0\u67E5\u8BE2\u3002" : capabilityInputInvalid ? "Agent\u6309\u5F53\u524D\u5408\u540C\u6A21\u677F\u4FEE\u6B63\u5B57\u6BB5\u548CJSON\u5C42\u7EA7\uFF0C\u4FDD\u7559\u7528\u6237\u539F\u59CB\u9700\u6C42\uFF0C\u7EE7\u7EED\u540C\u4E00\u6B21\u670D\u52A1\u3002\u4E0D\u8981\u8BA9\u7528\u6237\u4FEE\u6280\u672F\u8F93\u5165\uFF0C\u53EA\u6709\u771F\u5B9E\u4E1A\u52A1\u6B67\u4E49\u624D\u8BE2\u95EE\u3002" : transportError ? contract?.initialization ? "\u672C\u8F6E\u521D\u59CB\u5316\u68C0\u67E5\u672A\u5B8C\u6210\uFF1BCLI \u5DF2\u7ED3\u675F\u6709\u9650\u7684\u7F51\u7EDC\u5C1D\u8BD5\uFF0C\u5C1A\u672A\u786E\u8BA4\u540E\u7AEF\u6216\u8BBE\u5907\u5C31\u7EEA\u3002\u7ED3\u675F\u672C\u8F6E\uFF0C\u7F51\u7EDC\u6062\u590D\u540E\u53EF\u91CD\u65B0\u68C0\u67E5\uFF1B\u4E0D\u8981\u7EE7\u7EED\u767B\u5F55\u6216\u4E1A\u52A1\u64CD\u4F5C\u3002" : transportError.attempts > 1 ? "\u4E34\u65F6\u7F51\u7EDC\u6545\u969C\uFF1BCLI \u5DF2\u4EC5\u5BF9\u53EF\u5B89\u5168\u91CD\u653E\u7684\u64CD\u4F5C\u5B8C\u6210\u6709\u9650\u81EA\u52A8\u91CD\u8BD5\uFF0C\u4F46\u4ECD\u672A\u83B7\u5F97\u5B8C\u6574\u54CD\u5E94\u3002\u6309 recovery \u67E5\u8BE2\u540C\u4E00\u8D44\u6E90\u7684\u6743\u5A01\u72B6\u6001\uFF1B\u4E0D\u8981\u521B\u5EFA\u66FF\u4EE3 Checkout\u3001Execution\u3001Payment \u6216 Refund\u3002" : "\u7F51\u7EDC\u5728\u5B8C\u6574\u54CD\u5E94\u524D\u4E2D\u65AD\uFF1B\u5F53\u524D\u5199\u64CD\u4F5C\u6CA1\u6709\u5B89\u5168\u91CD\u653E\u5408\u540C\uFF0C\u56E0\u6B64 CLI \u672A\u81EA\u52A8\u91CD\u8BD5\u3002\u6309 recovery \u67E5\u8BE2\u6743\u5A01\u72B6\u6001\uFF1B\u4E0D\u8981\u539F\u6837\u91CD\u653E\u6216\u521B\u5EFA\u66FF\u4EE3 Checkout\u3001Execution\u3001Payment \u6216 Refund\u3002" : backendOverrideError ? "\u79FB\u9664 ITPAY_BACKEND_URL \u4F7F\u7528\u6B63\u5F0F\u73AF\u5883\uFF0C\u6216\u6309\u5F53\u524D\u6D4B\u8BD5\u76EE\u6807\u51C6\u786E\u8BBE\u7F6E\u4E3A https://sandbox.itpay.ai \u6216 https://dev.itpay.ai\u3002\u4E0D\u8981\u901A\u8FC7\u5207\u6362\u73AF\u5883\u89C4\u907F\u5F53\u524D\u9519\u8BEF\u3002" : commandError?.instruction ?? authorizationInstruction ?? contract?.instruction ?? "\u68C0\u67E5\u547D\u4EE4\u53C2\u6570\u540E\u91CD\u8BD5\u3002",
21943
+ instruction: incompatible ? "\u5F53\u524D CLI \u4E0E Backend \u5408\u7EA6\u4E0D\u517C\u5BB9\u6216\u65E0\u6CD5\u6838\u9A8C\u3002minimum_cli_version \u4EC5\u662F\u534F\u8BAE\u95E8\u69DB\uFF0C\u4E0D\u662F\u5DF2\u9A8C\u8BC1\u7684\u63A8\u8350\u5B89\u88C5\u5305\u3002\u505C\u6B62\u672C\u8F6E\uFF0C\u8BF7\u7EF4\u62A4\u65B9\u63D0\u4F9B\u4E0E\u5F53\u524D Backend \u914D\u5957\u7684\u5236\u54C1\uFF1B\u4E0D\u8981\u731C\u7248\u672C\u3001\u964D\u7EA7\u3001\u5207\u6362 Agent Type \u6216\u5220\u9664 Device \u8EAB\u4EFD\u3002" : backendInternal ? "\u544A\u8BC9\u7528\u6237 ItPay \u5F53\u524D\u6682\u65F6\u65E0\u6CD5\u5B8C\u6210\u8FD9\u9879\u670D\u52A1\u5E76\u505C\u6B62\u3002\u4E0D\u8981\u8F6C\u8FF0\u5185\u90E8\u9519\u8BEF\u3001\u91CD\u8BD5\u3001\u4FEE\u6539\u8EAB\u4EFD\u3001\u521B\u5EFA\u66FF\u4EE3\u670D\u52A1\u6216\u8FDB\u5165\u4EFB\u4F55\u4ED8\u8D39\u8DEF\u5F84\u3002" : providerConnectionUnavailable ? "\u544A\u8BC9\u7528\u6237\u672C\u6B21\u67E5\u8BE2\u6CA1\u6709\u53D1\u9001\u5230\u6570\u636E\u6765\u6E90\uFF0C\u514D\u8D39\u989D\u5EA6\u5DF2\u4FDD\u7559\uFF0C\u7136\u540E\u505C\u6B62\u3002\u4E0D\u8981\u8F6C\u8FF0\u6280\u672F\u9519\u8BEF\u3001\u81EA\u52A8\u91CD\u8BD5\u6216\u8FDB\u5165\u4ED8\u8D39\u8DEF\u5F84\uFF1B\u53EA\u6709\u670D\u52A1\u6062\u590D\u4E14\u7528\u6237\u660E\u786E\u8981\u6C42\u91CD\u65B0\u67E5\u8BE2\u540E\u624D\u80FD\u5F00\u59CB\u65B0\u7684\u67E5\u8BE2\u3002" : providerTemporary ? "\u544A\u8BC9\u7528\u6237\u6570\u636E\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u5E76\u6309 result.quota \u8BF4\u660E\u989D\u5EA6\u662F\u5426\u4FDD\u7559\uFF0C\u7136\u540E\u505C\u6B62\u3002\u4E0D\u8981\u8F6C\u8FF0\u6280\u672F\u9519\u8BEF\u3001\u81EA\u52A8\u91CD\u8BD5\u6216\u521B\u5EFA\u65B0\u67E5\u8BE2\uFF1B\u53EA\u6709\u7528\u6237\u4E4B\u540E\u660E\u786E\u63D0\u51FA\u65B0\u8BF7\u6C42\u624D\u53EF\u91CD\u65B0\u5F00\u59CB\u3002" : providerInputRejected ? "\u544A\u8BC9\u7528\u6237\u6570\u636E\u6765\u6E90\u660E\u786E\u8868\u793A\u5F53\u524D\u8F93\u5165\u65E0\u6548\uFF0C\u5E76\u6309 result.quota \u8BF4\u660E\u989D\u5EA6\u72B6\u6001\uFF0C\u7136\u540E\u505C\u6B62\u3002\u4E0D\u8981\u8F6C\u8FF0\u5185\u90E8\u9519\u8BEF\u3001\u81EA\u884C\u4FEE\u6539\u8F93\u5165\u3001\u91CD\u8BD5\u6216\u521B\u5EFA\u65B0\u67E5\u8BE2\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u63D0\u4F9B\u65B0\u8F93\u5165\u540E\u624D\u80FD\u91CD\u65B0\u67E5\u8BE2\u3002" : providerContractMismatch ? "\u544A\u8BC9\u7528\u6237\u5E73\u53F0\u6682\u65F6\u65E0\u6CD5\u6B63\u786E\u89E3\u91CA\u6570\u636E\u6765\u6E90\u7684\u54CD\u5E94\uFF0C\u8FD9\u4E0D\u662F\u7528\u6237\u8F93\u5165\u95EE\u9898\uFF0C\u5E76\u6309 result.quota \u8BF4\u660E\u989D\u5EA6\u72B6\u6001\u3002\u7ACB\u5373\u505C\u6B62\uFF0C\u4E0D\u8981\u4FEE\u6539\u8F93\u5165\u3001\u91CD\u8BD5\u3001\u521B\u5EFA\u65B0\u67E5\u8BE2\u6216\u8FDB\u5165\u4ED8\u8D39\u8DEF\u5F84\u3002" : providerRejected ? "\u544A\u8BC9\u7528\u6237\u6570\u636E\u6765\u6E90\u6CA1\u6709\u63A5\u53D7\u672C\u6B21\u8BF7\u6C42\uFF0C\u4F46\u6CA1\u6709\u8BF4\u660E\u662F\u8F93\u5165\u9519\u8BEF\uFF0C\u5E76\u6309 result.quota \u8BF4\u660E\u989D\u5EA6\u72B6\u6001\uFF0C\u7136\u540E\u505C\u6B62\u3002\u4E0D\u8981\u8F6C\u8FF0\u5185\u90E8\u9519\u8BEF\u3001\u4FEE\u6539\u8F93\u5165\u3001\u91CD\u8BD5\u6216\u521B\u5EFA\u65B0\u67E5\u8BE2\u3002" : capabilityInputInvalid ? "Agent\u6309\u5F53\u524D\u5408\u540C\u6A21\u677F\u4FEE\u6B63\u5B57\u6BB5\u548CJSON\u5C42\u7EA7\uFF0C\u4FDD\u7559\u7528\u6237\u539F\u59CB\u9700\u6C42\uFF0C\u7EE7\u7EED\u540C\u4E00\u6B21\u670D\u52A1\u3002\u4E0D\u8981\u8BA9\u7528\u6237\u4FEE\u6280\u672F\u8F93\u5165\uFF0C\u53EA\u6709\u771F\u5B9E\u4E1A\u52A1\u6B67\u4E49\u624D\u8BE2\u95EE\u3002" : transportError ? contract?.initialization ? "\u672C\u8F6E\u521D\u59CB\u5316\u68C0\u67E5\u672A\u5B8C\u6210\uFF1BCLI \u5DF2\u7ED3\u675F\u6709\u9650\u7684\u7F51\u7EDC\u5C1D\u8BD5\uFF0C\u5C1A\u672A\u786E\u8BA4\u540E\u7AEF\u6216\u8BBE\u5907\u5C31\u7EEA\u3002\u7ED3\u675F\u672C\u8F6E\uFF0C\u7F51\u7EDC\u6062\u590D\u540E\u53EF\u91CD\u65B0\u68C0\u67E5\uFF1B\u4E0D\u8981\u7EE7\u7EED\u767B\u5F55\u6216\u4E1A\u52A1\u64CD\u4F5C\u3002" : transportError.attempts > 1 ? "\u4E34\u65F6\u7F51\u7EDC\u6545\u969C\uFF1BCLI \u5DF2\u4EC5\u5BF9\u53EF\u5B89\u5168\u91CD\u653E\u7684\u64CD\u4F5C\u5B8C\u6210\u6709\u9650\u81EA\u52A8\u91CD\u8BD5\uFF0C\u4F46\u4ECD\u672A\u83B7\u5F97\u5B8C\u6574\u54CD\u5E94\u3002\u6309 recovery \u67E5\u8BE2\u540C\u4E00\u8D44\u6E90\u7684\u6743\u5A01\u72B6\u6001\uFF1B\u4E0D\u8981\u521B\u5EFA\u66FF\u4EE3 Checkout\u3001Execution\u3001Payment \u6216 Refund\u3002" : "\u7F51\u7EDC\u5728\u5B8C\u6574\u54CD\u5E94\u524D\u4E2D\u65AD\uFF1B\u5F53\u524D\u5199\u64CD\u4F5C\u6CA1\u6709\u5B89\u5168\u91CD\u653E\u5408\u540C\uFF0C\u56E0\u6B64 CLI \u672A\u81EA\u52A8\u91CD\u8BD5\u3002\u6309 recovery \u67E5\u8BE2\u6743\u5A01\u72B6\u6001\uFF1B\u4E0D\u8981\u539F\u6837\u91CD\u653E\u6216\u521B\u5EFA\u66FF\u4EE3 Checkout\u3001Execution\u3001Payment \u6216 Refund\u3002" : backendOverrideError ? "\u79FB\u9664 ITPAY_BACKEND_URL \u4F7F\u7528\u6B63\u5F0F\u73AF\u5883\uFF0C\u6216\u6309\u5F53\u524D\u6D4B\u8BD5\u76EE\u6807\u51C6\u786E\u8BBE\u7F6E\u4E3A https://sandbox.itpay.ai \u3001https://dev.itpay.ai \u6216 https://v4-dev.itpay.ai\u3002\u4E0D\u8981\u901A\u8FC7\u5207\u6362\u73AF\u5883\u89C4\u907F\u5F53\u524D\u9519\u8BEF\u3002" : commandError?.instruction ?? authorizationInstruction ?? contract?.instruction ?? "\u68C0\u67E5\u547D\u4EE4\u53C2\u6570\u540E\u91CD\u8BD5\u3002",
21686
21944
  next: null,
21687
21945
  ...commandError?.interaction ? { interaction: commandError.interaction } : {},
21688
21946
  recovery: incompatible || transportError && contract?.initialization ? [] : backendInternal || providerConnectionUnavailable || providerTemporary || providerInputRejected || providerContractMismatch || providerRejected || capabilityInputInvalid ? [] : backendOverrideError ? [] : commandError?.recovery ?? (stateError ? stateRecovery : deviceError ? deviceRecovery : identityRecovery ? httpRecovery : contract?.recovery ?? [])
21689
21947
  }, {
21690
21948
  ...contract?.jsonOutput !== void 0 ? { jsonOutput: contract.jsonOutput } : backendOverrideError || stateError ? { jsonOutput: process.argv.includes("--json") } : {},
21691
- output: /* @__PURE__ */ __name((text) => {
21692
- process.stdout.write(text);
21949
+ output: /* @__PURE__ */ __name((text2) => {
21950
+ process.stdout.write(text2);
21693
21951
  }, "output")
21694
21952
  });
21695
21953
  process.exitCode = 1;
@@ -21698,7 +21956,7 @@ function reportCLIError(error, contract) {
21698
21956
  if (error instanceof HttpError) {
21699
21957
  process.stderr.write(`[${error.status}] ${error.code}: ${error.message}
21700
21958
  `);
21701
- printErrorRecovery(error, (text) => process.stderr.write(text));
21959
+ printErrorRecovery(error, (text2) => process.stderr.write(text2));
21702
21960
  process.exitCode = 1;
21703
21961
  return;
21704
21962
  }