@itpay/cli 2.1.50 → 2.1.54
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 +733 -516
- 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/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 +7 -1
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" },
|
|
@@ -15745,11 +15913,11 @@ function writeSavedPage(envelope, options, key, offset, continuation, updateMeta
|
|
|
15745
15913
|
const render = /* @__PURE__ */ __name((output) => writeCommandEnvelope(envelope, { ...options, output }), "render");
|
|
15746
15914
|
if (!options.all) {
|
|
15747
15915
|
for (; ; ) {
|
|
15748
|
-
let
|
|
15916
|
+
let text2 = "";
|
|
15749
15917
|
render((value) => {
|
|
15750
|
-
|
|
15918
|
+
text2 += value;
|
|
15751
15919
|
});
|
|
15752
|
-
if (Buffer.byteLength(
|
|
15920
|
+
if (Buffer.byteLength(text2, "utf8") <= bound) break;
|
|
15753
15921
|
if (rows.length <= 1) {
|
|
15754
15922
|
throw new CommandContractError(
|
|
15755
15923
|
"saved_row_too_large",
|
|
@@ -16407,7 +16575,7 @@ function serviceAdapterKey(execution) {
|
|
|
16407
16575
|
const binding = execution.public_binding;
|
|
16408
16576
|
if (binding) {
|
|
16409
16577
|
if (binding.adapter_key === "schema.v1") return "schema.v1";
|
|
16410
|
-
if (binding.adapter_key === "rail.v1" && ["scv_itpay_rail_public_v1", "scv_itpay_rail_public_v1_capacity_20261015"].includes(binding.service_definition_version)) return "rail.v1";
|
|
16578
|
+
if (binding.adapter_key === "rail.v1" && ["scv_itpay_rail_public_v1", "scv_itpay_rail_public_v1_capacity_20261015", "scv_itpay_rail_public_v5"].includes(binding.service_definition_version)) return "rail.v1";
|
|
16411
16579
|
return "unsupported";
|
|
16412
16580
|
}
|
|
16413
16581
|
const versions = legacyRailContracts.get(execution.service_id);
|
|
@@ -16440,12 +16608,69 @@ function projectCheckoutPresentation(presentation, model) {
|
|
|
16440
16608
|
}
|
|
16441
16609
|
__name(projectCheckoutPresentation, "projectCheckoutPresentation");
|
|
16442
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
|
+
|
|
16443
16668
|
// src/render/qr.ts
|
|
16444
16669
|
var import_qrcode = __toESM(require_lib(), 1);
|
|
16445
16670
|
import fs from "node:fs/promises";
|
|
16446
16671
|
import os from "node:os";
|
|
16447
16672
|
import path from "node:path";
|
|
16448
|
-
import { randomUUID as
|
|
16673
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
16449
16674
|
function terminalQRType(format) {
|
|
16450
16675
|
return format === "utf8" ? "utf8" : "terminal";
|
|
16451
16676
|
}
|
|
@@ -16460,7 +16685,7 @@ async function renderTerminalQR(url, format) {
|
|
|
16460
16685
|
__name(renderTerminalQR, "renderTerminalQR");
|
|
16461
16686
|
async function writeLocalPNG(url) {
|
|
16462
16687
|
const dir = await fs.mkdtemp(path.join(process.env.ITPAY_STATE_DIR || os.tmpdir(), "itpay-v3-"));
|
|
16463
|
-
const filePath = path.join(dir, `itpay-${
|
|
16688
|
+
const filePath = path.join(dir, `itpay-${randomUUID6()}.png`);
|
|
16464
16689
|
await import_qrcode.default.toFile(filePath, url, {
|
|
16465
16690
|
type: "png",
|
|
16466
16691
|
errorCorrectionLevel: "M",
|
|
@@ -16494,15 +16719,15 @@ function renderInlineTerminalImage(filePath, out) {
|
|
|
16494
16719
|
__name(renderInlineTerminalImage, "renderInlineTerminalImage");
|
|
16495
16720
|
|
|
16496
16721
|
// src/render/ide.ts
|
|
16497
|
-
import { mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as
|
|
16498
|
-
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";
|
|
16499
16724
|
import { tmpdir } from "node:os";
|
|
16500
|
-
import { createHash as
|
|
16725
|
+
import { createHash as createHash7, randomUUID as randomUUID7 } from "node:crypto";
|
|
16501
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";
|
|
16502
16727
|
function canonicalDir(env = process.env) {
|
|
16503
16728
|
const override = env.ITPAY_IDE_IMAGE_DIR_OVERRIDE;
|
|
16504
16729
|
if (override && override.length > 0) return override;
|
|
16505
|
-
return
|
|
16730
|
+
return join3(tmpdir(), "itpay-v3-qr");
|
|
16506
16731
|
}
|
|
16507
16732
|
__name(canonicalDir, "canonicalDir");
|
|
16508
16733
|
function resolveIdeImageDirs(env = process.env) {
|
|
@@ -16520,8 +16745,8 @@ function resolveIdeImageDirs(env = process.env) {
|
|
|
16520
16745
|
}
|
|
16521
16746
|
__name(resolveIdeImageDirs, "resolveIdeImageDirs");
|
|
16522
16747
|
function stableNameFor(kind, id) {
|
|
16523
|
-
const safeID = id.replace(/[^a-zA-Z0-9_-]/g, "_") ||
|
|
16524
|
-
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);
|
|
16525
16750
|
return `itpay-v3-${kind}-${safeID}-${hash}`;
|
|
16526
16751
|
}
|
|
16527
16752
|
__name(stableNameFor, "stableNameFor");
|
|
@@ -16554,9 +16779,9 @@ async function detectImageFormat(url, fetchFn) {
|
|
|
16554
16779
|
}
|
|
16555
16780
|
__name(detectImageFormat, "detectImageFormat");
|
|
16556
16781
|
function atomicWrite(filePath, body) {
|
|
16557
|
-
const tmp = `${filePath}.tmp-${
|
|
16782
|
+
const tmp = `${filePath}.tmp-${randomUUID7()}`;
|
|
16558
16783
|
writeFileSync5(tmp, body);
|
|
16559
|
-
|
|
16784
|
+
renameSync2(tmp, filePath);
|
|
16560
16785
|
}
|
|
16561
16786
|
__name(atomicWrite, "atomicWrite");
|
|
16562
16787
|
function mirrorToDirs(fileName, body, dirs) {
|
|
@@ -16564,7 +16789,7 @@ function mirrorToDirs(fileName, body, dirs) {
|
|
|
16564
16789
|
for (const dir of dirs.slice(1)) {
|
|
16565
16790
|
try {
|
|
16566
16791
|
mkdirSync6(dir, { recursive: true });
|
|
16567
|
-
const target2 =
|
|
16792
|
+
const target2 = join3(dir, fileName);
|
|
16568
16793
|
atomicWrite(target2, body);
|
|
16569
16794
|
written.push(target2);
|
|
16570
16795
|
} catch {
|
|
@@ -16608,7 +16833,7 @@ async function downloadBrandQRToTmp(url, kind, id, options = {}) {
|
|
|
16608
16833
|
if (!url) {
|
|
16609
16834
|
return { ok: false, reason: "no qr_png_url on plan" };
|
|
16610
16835
|
}
|
|
16611
|
-
const stem = stableNameFor(kind, id ??
|
|
16836
|
+
const stem = stableNameFor(kind, id ?? randomUUID7());
|
|
16612
16837
|
const dirs = resolveIdeImageDirs();
|
|
16613
16838
|
const canonical = dirs[0];
|
|
16614
16839
|
if (!canonical) {
|
|
@@ -16636,7 +16861,7 @@ async function downloadBrandQRToTmp(url, kind, id, options = {}) {
|
|
|
16636
16861
|
if (timer) clearTimeout(timer);
|
|
16637
16862
|
}
|
|
16638
16863
|
const fileName = `${stem}${detected.ext}`;
|
|
16639
|
-
const filePath =
|
|
16864
|
+
const filePath = join3(canonical, fileName);
|
|
16640
16865
|
atomicWrite(filePath, detected.body);
|
|
16641
16866
|
const mirrors = mirrorToDirs(fileName, detected.body, dirs);
|
|
16642
16867
|
return {
|
|
@@ -17306,6 +17531,23 @@ async function presentServiceCheckout(backend, config, serviceExecutionID, respo
|
|
|
17306
17531
|
assertCheckoutPayable(checkout, authoritative, response.cart.cart_id, serviceExecutionID);
|
|
17307
17532
|
if (authoritative) response.cart.items = authoritative.items;
|
|
17308
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
|
+
}
|
|
17309
17551
|
const displayToken = checkout.display_token;
|
|
17310
17552
|
const locale = normalizeCardLocale(options.locale);
|
|
17311
17553
|
const checkoutURL = tokenizedCheckoutURL(checkout.checkout_url, displayToken, checkout.qr_payload);
|
|
@@ -17449,29 +17691,38 @@ async function runServicesQuote(backend, serviceExecutionID, capabilityID, input
|
|
|
17449
17691
|
__name(runServicesQuote, "runServicesQuote");
|
|
17450
17692
|
|
|
17451
17693
|
// src/commands/services/purchase.ts
|
|
17452
|
-
function
|
|
17453
|
-
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 } : {} });
|
|
17454
17696
|
}
|
|
17455
|
-
__name(
|
|
17697
|
+
__name(invalid4, "invalid");
|
|
17456
17698
|
function parsePurchaseConfirmation(raw) {
|
|
17457
|
-
|
|
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");
|
|
17458
17705
|
const p = raw.price_policy;
|
|
17459
|
-
if (
|
|
17460
|
-
if (!("mode" in p) ||
|
|
17461
|
-
|
|
17462
|
-
|
|
17463
|
-
|
|
17464
|
-
|
|
17465
|
-
|
|
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}`);
|
|
17466
17717
|
}
|
|
17467
17718
|
__name(parsePurchaseConfirmation, "parsePurchaseConfirmation");
|
|
17468
17719
|
async function runServicesPurchase(backend, config, id, input, options = {}) {
|
|
17469
17720
|
const confirm = input ? parsePurchaseConfirmation(input) : void 0;
|
|
17470
|
-
if (confirm && options.resume)
|
|
17721
|
+
if (confirm && options.resume) invalid4();
|
|
17471
17722
|
const contextError = validateContext(options.host ?? "terminal", options.target);
|
|
17472
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 });
|
|
17473
17724
|
const seconds = options.timeoutSeconds ?? 60;
|
|
17474
|
-
if (!Number.isFinite(seconds) || seconds <= 0 || seconds > 120)
|
|
17725
|
+
if (!Number.isFinite(seconds) || seconds <= 0 || seconds > 120) invalid4();
|
|
17475
17726
|
let deadline = options.deadline ?? Date.now() + seconds * 1e3;
|
|
17476
17727
|
let failureStage = confirm ? "confirm_purchase" : options.resume ? "resume_purchase" : "read_purchase_review";
|
|
17477
17728
|
try {
|
|
@@ -17540,11 +17791,11 @@ __name(runAftercareRespond, "runAftercareRespond");
|
|
|
17540
17791
|
import { rmSync } from "node:fs";
|
|
17541
17792
|
|
|
17542
17793
|
// src/state/auth_storage.ts
|
|
17543
|
-
import { createHash as
|
|
17544
|
-
import { dirname as
|
|
17545
|
-
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";
|
|
17546
17797
|
function authStatePath(baseURL, env, purpose) {
|
|
17547
|
-
return resolve4(stateDir(env), `${purpose}-${
|
|
17798
|
+
return resolve4(stateDir(env), `${purpose}-${createHash8("sha256").update(baseURL).digest("hex").slice(0, 16)}.json`);
|
|
17548
17799
|
}
|
|
17549
17800
|
__name(authStatePath, "authStatePath");
|
|
17550
17801
|
function readAuthState(baseURL, env, purpose) {
|
|
@@ -17557,10 +17808,10 @@ function readAuthState(baseURL, env, purpose) {
|
|
|
17557
17808
|
__name(readAuthState, "readAuthState");
|
|
17558
17809
|
function saveAuthState(state, env, purpose) {
|
|
17559
17810
|
const path3 = authStatePath(state.baseURL, env, purpose);
|
|
17560
|
-
mkdirSync7(
|
|
17811
|
+
mkdirSync7(dirname3(path3), { recursive: true, mode: 448 });
|
|
17561
17812
|
const tmp = `${path3}.${process.pid}.tmp`;
|
|
17562
17813
|
writeFileSync6(tmp, JSON.stringify(state), { mode: 384 });
|
|
17563
|
-
|
|
17814
|
+
renameSync3(tmp, path3);
|
|
17564
17815
|
}
|
|
17565
17816
|
__name(saveAuthState, "saveAuthState");
|
|
17566
17817
|
|
|
@@ -18896,9 +19147,9 @@ var {
|
|
|
18896
19147
|
} = import_index.default;
|
|
18897
19148
|
|
|
18898
19149
|
// src/state/cart_session.ts
|
|
18899
|
-
import { chmodSync as chmodSync2, existsSync as existsSync5, mkdirSync as mkdirSync8, readFileSync as readFileSync9, renameSync as
|
|
18900
|
-
import { randomUUID as
|
|
18901
|
-
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";
|
|
18902
19153
|
var CartSession = class _CartSession {
|
|
18903
19154
|
static {
|
|
18904
19155
|
__name(this, "CartSession");
|
|
@@ -18947,11 +19198,11 @@ var CartSession = class _CartSession {
|
|
|
18947
19198
|
};
|
|
18948
19199
|
const contents = JSON.stringify(toSave, null, 2);
|
|
18949
19200
|
if (existsSync5(path3) && readFileSync9(path3, "utf-8") === contents) return;
|
|
18950
|
-
mkdirSync8(
|
|
18951
|
-
const temporary = `${path3}.${process.pid}.${
|
|
19201
|
+
mkdirSync8(dirname4(path3), { recursive: true, mode: 448 });
|
|
19202
|
+
const temporary = `${path3}.${process.pid}.${randomUUID8()}.tmp`;
|
|
18952
19203
|
writeFileSync7(temporary, contents, { encoding: "utf-8", mode: 384 });
|
|
18953
19204
|
chmodSync2(temporary, 384);
|
|
18954
|
-
|
|
19205
|
+
renameSync4(temporary, path3);
|
|
18955
19206
|
chmodSync2(path3, 384);
|
|
18956
19207
|
}
|
|
18957
19208
|
add(item) {
|
|
@@ -19075,6 +19326,8 @@ __name(versionParts, "versionParts");
|
|
|
19075
19326
|
|
|
19076
19327
|
// src/commands/install.ts
|
|
19077
19328
|
var INSTALL_AGENT_TYPES = [
|
|
19329
|
+
"dot",
|
|
19330
|
+
"muse",
|
|
19078
19331
|
"codex-desktop",
|
|
19079
19332
|
"codex-cli",
|
|
19080
19333
|
"claude-code-desktop",
|
|
@@ -19083,10 +19336,14 @@ var INSTALL_AGENT_TYPES = [
|
|
|
19083
19336
|
"zcode",
|
|
19084
19337
|
"doubao-work",
|
|
19085
19338
|
"kimi-code",
|
|
19086
|
-
"openclaw"
|
|
19339
|
+
"openclaw",
|
|
19340
|
+
"hermes"
|
|
19087
19341
|
];
|
|
19088
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";
|
|
19089
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",
|
|
19090
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",
|
|
19091
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",
|
|
19092
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",
|
|
@@ -19148,17 +19405,23 @@ function installDefinition(agentType) {
|
|
|
19148
19405
|
}
|
|
19149
19406
|
__name(installDefinition, "installDefinition");
|
|
19150
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
|
+
|
|
19151
19414
|
// src/commands/skill.ts
|
|
19152
19415
|
import { existsSync as existsSync7, readFileSync as readFileSync11 } from "node:fs";
|
|
19153
19416
|
import { resolve as resolve6 } from "node:path";
|
|
19154
19417
|
|
|
19155
19418
|
// src/state/package_resources.ts
|
|
19156
19419
|
import { existsSync as existsSync6, readFileSync as readFileSync10 } from "node:fs";
|
|
19157
|
-
import { basename as basename2, dirname as
|
|
19420
|
+
import { basename as basename2, dirname as dirname5, resolve as resolve5 } from "node:path";
|
|
19158
19421
|
import { fileURLToPath } from "node:url";
|
|
19159
19422
|
function packageResourcePath(...segments) {
|
|
19160
19423
|
const modulePath = fileURLToPath(import.meta.url);
|
|
19161
|
-
const root = resolve5(
|
|
19424
|
+
const root = resolve5(dirname5(modulePath), "..", "..");
|
|
19162
19425
|
if (!basename2(modulePath).startsWith("package_resources.") && basename2(modulePath) !== "main.js") throw new Error("unsupported CLI resource layout");
|
|
19163
19426
|
const metadata = resolve5(root, "package.json");
|
|
19164
19427
|
if (!existsSync6(metadata) || JSON.parse(readFileSync10(metadata, "utf8")).name !== "@itpay/cli") throw new Error("current CLI package resources are unavailable");
|
|
@@ -19170,7 +19433,7 @@ __name(packageResourcePath, "packageResourcePath");
|
|
|
19170
19433
|
var ITPAY_SKILL = "itpay";
|
|
19171
19434
|
function runSkillShow(name, options = {}) {
|
|
19172
19435
|
const normalized = name.trim().toLowerCase();
|
|
19173
|
-
if (normalized !== ITPAY_SKILL) {
|
|
19436
|
+
if (normalized !== ITPAY_SKILL && normalized !== "itpay-buyer") {
|
|
19174
19437
|
throw new CommandContractError(
|
|
19175
19438
|
"skill_not_found",
|
|
19176
19439
|
`skill not found: ${name}`,
|
|
@@ -19228,8 +19491,12 @@ ${CODEX_WAIT_GUIDANCE}
|
|
|
19228
19491
|
}
|
|
19229
19492
|
__name(runSkillShow, "runSkillShow");
|
|
19230
19493
|
function packagedSkill() {
|
|
19231
|
-
|
|
19494
|
+
let path3 = findSkillPath(false);
|
|
19495
|
+
if (!existsSync7(path3) && process.env.ITPAY_CLI_SKILLS_DIR) path3 = findSkillPath();
|
|
19232
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
|
+
}
|
|
19233
19500
|
validateSkill(content);
|
|
19234
19501
|
return { path: path3, content };
|
|
19235
19502
|
}
|
|
@@ -19297,6 +19564,13 @@ async function runSetup(backend, config, skillPath, options = {}) {
|
|
|
19297
19564
|
cli_version: CLI_VERSION2,
|
|
19298
19565
|
backend_url: config.baseURL,
|
|
19299
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",
|
|
19300
19574
|
device_status: "ready",
|
|
19301
19575
|
account_status: account.status,
|
|
19302
19576
|
skill_path: skillPath,
|
|
@@ -19745,63 +20019,6 @@ function formatProductMoney(amountMinor, currency) {
|
|
|
19745
20019
|
}
|
|
19746
20020
|
__name(formatProductMoney, "formatProductMoney");
|
|
19747
20021
|
|
|
19748
|
-
// src/render/browser.ts
|
|
19749
|
-
import { spawn } from "node:child_process";
|
|
19750
|
-
import { platform } from "node:os";
|
|
19751
|
-
function isPresentableURL(raw, baseURL, env = process.env) {
|
|
19752
|
-
let url;
|
|
19753
|
-
try {
|
|
19754
|
-
url = new URL(raw);
|
|
19755
|
-
} catch {
|
|
19756
|
-
return false;
|
|
19757
|
-
}
|
|
19758
|
-
if (url.username || url.password) return false;
|
|
19759
|
-
if (env.ITPAY_CLI_DEV === "1" && /^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(url.origin)) return true;
|
|
19760
|
-
if (url.protocol !== "https:") return false;
|
|
19761
|
-
const allowedOrigins = /* @__PURE__ */ new Set(["https://app.itpay.ai", "https://sandbox.itpay.ai", "https://dev.itpay.ai"]);
|
|
19762
|
-
if (baseURL) {
|
|
19763
|
-
try {
|
|
19764
|
-
allowedOrigins.add(new URL(baseURL).origin);
|
|
19765
|
-
} catch {
|
|
19766
|
-
}
|
|
19767
|
-
}
|
|
19768
|
-
return allowedOrigins.has(url.origin);
|
|
19769
|
-
}
|
|
19770
|
-
__name(isPresentableURL, "isPresentableURL");
|
|
19771
|
-
function openInSystemBrowser(raw, baseURL, env = process.env) {
|
|
19772
|
-
if (!isPresentableURL(raw, baseURL, env)) {
|
|
19773
|
-
return Promise.resolve({ status: "failed", reason: "url_rejected" });
|
|
19774
|
-
}
|
|
19775
|
-
const [command, args] = openerArgv(raw);
|
|
19776
|
-
if (!command) {
|
|
19777
|
-
return Promise.resolve({ status: "unavailable", reason: "no system opener on this platform" });
|
|
19778
|
-
}
|
|
19779
|
-
return new Promise((resolvePromise) => {
|
|
19780
|
-
const child = spawn(command, args, { detached: true, stdio: "ignore" });
|
|
19781
|
-
child.once("error", (error) => resolvePromise({ status: "failed", reason: error.message }));
|
|
19782
|
-
child.once("spawn", () => {
|
|
19783
|
-
child.unref();
|
|
19784
|
-
resolvePromise({ status: "dispatch_accepted", argv: [command, ...args] });
|
|
19785
|
-
});
|
|
19786
|
-
});
|
|
19787
|
-
}
|
|
19788
|
-
__name(openInSystemBrowser, "openInSystemBrowser");
|
|
19789
|
-
function openerArgv(url) {
|
|
19790
|
-
switch (platform()) {
|
|
19791
|
-
case "darwin":
|
|
19792
|
-
return ["open", [url]];
|
|
19793
|
-
case "win32":
|
|
19794
|
-
return ["cmd.exe", ["/c", "start", "", url]];
|
|
19795
|
-
case "linux":
|
|
19796
|
-
case "freebsd":
|
|
19797
|
-
case "openbsd":
|
|
19798
|
-
return ["xdg-open", [url]];
|
|
19799
|
-
default:
|
|
19800
|
-
return [void 0, []];
|
|
19801
|
-
}
|
|
19802
|
-
}
|
|
19803
|
-
__name(openerArgv, "openerArgv");
|
|
19804
|
-
|
|
19805
20022
|
// src/commands/presentation.ts
|
|
19806
20023
|
var yes = /* @__PURE__ */ __name((value) => value === "yes", "yes");
|
|
19807
20024
|
function resolvePresentation(input) {
|
|
@@ -21385,7 +21602,7 @@ function writeCartNextEnvelope(envelope, options) {
|
|
|
21385
21602
|
__name(writeCartNextEnvelope, "writeCartNextEnvelope");
|
|
21386
21603
|
|
|
21387
21604
|
// src/commands/docs.ts
|
|
21388
|
-
import { readFileSync as readFileSync12, readdirSync as
|
|
21605
|
+
import { readFileSync as readFileSync12, readdirSync as readdirSync4 } from "node:fs";
|
|
21389
21606
|
import { resolve as resolve7 } from "node:path";
|
|
21390
21607
|
function runDocsList(options = {}) {
|
|
21391
21608
|
const topics = loadDocs().map(({ topic, title, purpose }) => ({ topic, title, purpose }));
|
|
@@ -21460,11 +21677,11 @@ function runDocsSearch(query, options = {}) {
|
|
|
21460
21677
|
__name(runDocsSearch, "runDocsSearch");
|
|
21461
21678
|
function loadDocs() {
|
|
21462
21679
|
const docsDir = findDocsDir();
|
|
21463
|
-
const files =
|
|
21680
|
+
const files = readdirSync4(docsDir).filter((file) => file.endsWith(".json")).sort();
|
|
21464
21681
|
const docs = files.map((file) => parseDoc(readFileSync12(resolve7(docsDir, file), "utf8"), file));
|
|
21465
21682
|
if (process.env.ITPAY_CLI_DOCS_DIR) {
|
|
21466
21683
|
const canonical = packageResourcePath("docs", "agent", "buyer");
|
|
21467
|
-
const expectedFiles =
|
|
21684
|
+
const expectedFiles = readdirSync4(canonical).filter((file) => file.endsWith(".json")).sort();
|
|
21468
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)))) {
|
|
21469
21686
|
throw new CommandContractError(
|
|
21470
21687
|
"docs_override_mismatch",
|
|
@@ -21609,11 +21826,11 @@ function parseRequiredContactFields(value) {
|
|
|
21609
21826
|
return void 0;
|
|
21610
21827
|
}
|
|
21611
21828
|
const values = value.split(",").map((item) => item.trim().toLowerCase()).filter(Boolean);
|
|
21612
|
-
const
|
|
21613
|
-
if (
|
|
21829
|
+
const invalid5 = values.filter((item) => item !== "email" && item !== "phone");
|
|
21830
|
+
if (invalid5.length > 0) {
|
|
21614
21831
|
throw new CommandContractError(
|
|
21615
21832
|
"contact_field_invalid",
|
|
21616
|
-
`unsupported required contact fields: ${
|
|
21833
|
+
`unsupported required contact fields: ${invalid5.join(", ")}`,
|
|
21617
21834
|
"--require-contact \u53EA\u63A5\u53D7 email\u3001phone \u6216\u4E8C\u8005\u7EC4\u5408\u3002",
|
|
21618
21835
|
[{ command: "itpay buy --help", reason: "\u67E5\u770B contact \u53C2\u6570" }]
|
|
21619
21836
|
);
|
|
@@ -21623,8 +21840,8 @@ function parseRequiredContactFields(value) {
|
|
|
21623
21840
|
}
|
|
21624
21841
|
__name(parseRequiredContactFields, "parseRequiredContactFields");
|
|
21625
21842
|
function positiveInteger(value, name) {
|
|
21626
|
-
const
|
|
21627
|
-
if (!/^[1-9]\d*$/.test(
|
|
21843
|
+
const text2 = String(value ?? "");
|
|
21844
|
+
if (!/^[1-9]\d*$/.test(text2)) {
|
|
21628
21845
|
throw new CommandContractError(
|
|
21629
21846
|
"buy_parameter_invalid",
|
|
21630
21847
|
`${name} must be a positive integer`,
|
|
@@ -21632,7 +21849,7 @@ function positiveInteger(value, name) {
|
|
|
21632
21849
|
[{ command: "itpay buy --help", reason: "\u67E5\u770B\u53C2\u6570\u683C\u5F0F" }]
|
|
21633
21850
|
);
|
|
21634
21851
|
}
|
|
21635
|
-
return Number(
|
|
21852
|
+
return Number(text2);
|
|
21636
21853
|
}
|
|
21637
21854
|
__name(positiveInteger, "positiveInteger");
|
|
21638
21855
|
function resolveCheckoutPresentationArgs(input) {
|
|
@@ -21723,14 +21940,14 @@ function reportCLIError(error, contract) {
|
|
|
21723
21940
|
} : {}
|
|
21724
21941
|
}
|
|
21725
21942
|
} : {},
|
|
21726
|
-
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",
|
|
21727
21944
|
next: null,
|
|
21728
21945
|
...commandError?.interaction ? { interaction: commandError.interaction } : {},
|
|
21729
21946
|
recovery: incompatible || transportError && contract?.initialization ? [] : backendInternal || providerConnectionUnavailable || providerTemporary || providerInputRejected || providerContractMismatch || providerRejected || capabilityInputInvalid ? [] : backendOverrideError ? [] : commandError?.recovery ?? (stateError ? stateRecovery : deviceError ? deviceRecovery : identityRecovery ? httpRecovery : contract?.recovery ?? [])
|
|
21730
21947
|
}, {
|
|
21731
21948
|
...contract?.jsonOutput !== void 0 ? { jsonOutput: contract.jsonOutput } : backendOverrideError || stateError ? { jsonOutput: process.argv.includes("--json") } : {},
|
|
21732
|
-
output: /* @__PURE__ */ __name((
|
|
21733
|
-
process.stdout.write(
|
|
21949
|
+
output: /* @__PURE__ */ __name((text2) => {
|
|
21950
|
+
process.stdout.write(text2);
|
|
21734
21951
|
}, "output")
|
|
21735
21952
|
});
|
|
21736
21953
|
process.exitCode = 1;
|
|
@@ -21739,7 +21956,7 @@ function reportCLIError(error, contract) {
|
|
|
21739
21956
|
if (error instanceof HttpError) {
|
|
21740
21957
|
process.stderr.write(`[${error.status}] ${error.code}: ${error.message}
|
|
21741
21958
|
`);
|
|
21742
|
-
printErrorRecovery(error, (
|
|
21959
|
+
printErrorRecovery(error, (text2) => process.stderr.write(text2));
|
|
21743
21960
|
process.exitCode = 1;
|
|
21744
21961
|
return;
|
|
21745
21962
|
}
|