@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 +780 -522
- package/dist/src/state/config.js +2 -2
- package/docs/agent/buyer/install-and-setup.json +10 -3
- package/docs/agent/buyer/purchase.json +126 -0
- package/docs/agent/buyer/rail-booking.json +1 -1
- package/docs/cli-reference/agent-types.md +7 -1
- package/docs/cli-reference/conventions.md +2 -0
- package/package.json +4 -3
- package/skills/itpay/SKILL.md +8 -2
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,
|
|
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 =
|
|
4469
|
-
|
|
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 =
|
|
4478
|
-
|
|
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
|
-
|
|
4487
|
+
text2 = canvas;
|
|
4488
4488
|
canvas = opts = void 0;
|
|
4489
4489
|
} else if (argsNum === 2 && !canvas.getContext) {
|
|
4490
|
-
opts =
|
|
4491
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
4530
|
-
if (typeof
|
|
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,
|
|
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(
|
|
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(
|
|
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(
|
|
4605
|
-
const params = checkParams(
|
|
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,
|
|
4608
|
+
return render(renderer.render, text2, params);
|
|
4609
4609
|
}, "toString");
|
|
4610
|
-
exports.toDataURL = /* @__PURE__ */ __name(function toDataURL(
|
|
4611
|
-
const params = checkParams(
|
|
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,
|
|
4613
|
+
return render(renderer.renderToDataURL, text2, params);
|
|
4614
4614
|
}, "toDataURL");
|
|
4615
|
-
exports.toBuffer = /* @__PURE__ */ __name(function toBuffer(
|
|
4616
|
-
const params = checkParams(
|
|
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,
|
|
4618
|
+
return render(renderer.renderToBuffer, text2, params);
|
|
4619
4619
|
}, "toBuffer");
|
|
4620
|
-
exports.toFile = /* @__PURE__ */ __name(function toFile(path3,
|
|
4621
|
-
if (typeof path3 !== "string" || !(typeof
|
|
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(
|
|
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,
|
|
4631
|
+
return render(renderToFile, text2, params);
|
|
4632
4632
|
}, "toFile");
|
|
4633
|
-
exports.toFileStream = /* @__PURE__ */ __name(function toFileStream(stream,
|
|
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(
|
|
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,
|
|
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,
|
|
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
|
|
7594
|
-
helpStr =
|
|
7593
|
+
if (typeof text2 === "function") {
|
|
7594
|
+
helpStr = text2({ error: context.error, command: context.command });
|
|
7595
7595
|
} else {
|
|
7596
|
-
helpStr =
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
7978
|
+
function safeParseJson(text2) {
|
|
7960
7979
|
try {
|
|
7961
|
-
return JSON.parse(
|
|
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
|
|
8254
|
+
const text2 = await response.text();
|
|
8236
8255
|
let msg = `SSE stream failed: HTTP ${response.status}`;
|
|
8237
8256
|
try {
|
|
8238
|
-
const parsed = JSON.parse(
|
|
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,
|
|
8395
|
+
function writeComplete(path3, text2, createOnly) {
|
|
8377
8396
|
const temp = `${path3}.${randomUUID2()}.tmp`;
|
|
8378
|
-
writeFileSync2(temp,
|
|
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
|
|
8456
|
-
if (
|
|
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(
|
|
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
|
|
8474
|
-
if (
|
|
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(
|
|
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
|
|
8506
|
-
if (
|
|
8507
|
-
const value = JSON.parse(
|
|
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 ${
|
|
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
|
|
9069
|
-
|
|
9070
|
-
if (
|
|
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,
|
|
9248
|
-
for (const line of plainValueLines(
|
|
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,
|
|
9253
|
-
for (const line of plainValueLines(
|
|
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,
|
|
9260
|
-
for (const line of plainValueLines(
|
|
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\
|
|
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) : (
|
|
9687
|
+
util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object3) => {
|
|
9887
9688
|
const keys = [];
|
|
9888
|
-
for (const key in
|
|
9889
|
-
if (Object.prototype.hasOwnProperty.call(
|
|
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/
|
|
13925
|
-
var
|
|
13926
|
-
var
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
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(
|
|
13932
|
-
function
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
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(
|
|
13940
|
-
|
|
13941
|
-
const
|
|
13942
|
-
if (!
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
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(
|
|
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 {
|
|
13966
|
-
import {
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
13974
|
-
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
"
|
|
13978
|
-
"
|
|
13979
|
-
"
|
|
13980
|
-
"
|
|
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
|
-
|
|
13992
|
-
|
|
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
|
-
|
|
14022
|
-
if (
|
|
14023
|
-
|
|
14024
|
-
|
|
14025
|
-
|
|
14026
|
-
|
|
14027
|
-
|
|
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(
|
|
14034
|
-
if (this.remainingAutomaticWait(
|
|
14035
|
-
|
|
14036
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
14052
|
-
|
|
14053
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
15916
|
+
let text2 = "";
|
|
15735
15917
|
render((value) => {
|
|
15736
|
-
|
|
15918
|
+
text2 += value;
|
|
15737
15919
|
});
|
|
15738
|
-
if (Buffer.byteLength(
|
|
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" &&
|
|
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
|
|
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-${
|
|
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
|
|
16484
|
-
import { join as
|
|
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
|
|
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
|
|
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, "_") ||
|
|
16510
|
-
const hash =
|
|
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-${
|
|
16782
|
+
const tmp = `${filePath}.tmp-${randomUUID7()}`;
|
|
16544
16783
|
writeFileSync5(tmp, body);
|
|
16545
|
-
|
|
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 =
|
|
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 ??
|
|
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 =
|
|
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
|
|
17439
|
-
throw new CommandContractError("purchase_input_invalid", "purchase confirmation input is incomplete or invalid", "\u672C\u6B21\u672A\u53D1\u9001\u786E\u8BA4\u3002\
|
|
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(
|
|
17697
|
+
__name(invalid4, "invalid");
|
|
17442
17698
|
function parsePurchaseConfirmation(raw) {
|
|
17443
|
-
|
|
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 (
|
|
17446
|
-
if (!("mode" in p) ||
|
|
17447
|
-
|
|
17448
|
-
|
|
17449
|
-
|
|
17450
|
-
|
|
17451
|
-
|
|
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)
|
|
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)
|
|
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
|
|
17530
|
-
import { dirname as
|
|
17531
|
-
import { existsSync as existsSync4, mkdirSync as mkdirSync7, readFileSync as readFileSync8, renameSync as
|
|
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}-${
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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:
|
|
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(
|
|
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
|
|
18859
|
-
import { randomUUID as
|
|
18860
|
-
import { dirname as
|
|
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(
|
|
18910
|
-
const temporary = `${path3}.${process.pid}.${
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
21572
|
-
if (
|
|
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: ${
|
|
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
|
|
21586
|
-
if (!/^[1-9]\d*$/.test(
|
|
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(
|
|
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((
|
|
21692
|
-
process.stdout.write(
|
|
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, (
|
|
21959
|
+
printErrorRecovery(error, (text2) => process.stderr.write(text2));
|
|
21702
21960
|
process.exitCode = 1;
|
|
21703
21961
|
return;
|
|
21704
21962
|
}
|