@my-life-buddies/cli 0.25.2 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -5
- package/dist/bin/core.js +596 -188
- package/dist/bin/core.js.map +4 -4
- package/dist/bin/preview.js +65 -5
- package/dist/bin/preview.js.map +2 -2
- package/dist/web/app.js +7 -4
- package/dist/web/index.html +2 -0
- package/dist/web/products.css +19 -0
- package/dist/web/products.js +104 -0
- package/package.json +3 -3
package/dist/bin/preview.js
CHANGED
|
@@ -916,8 +916,26 @@ var PreviewController = class {
|
|
|
916
916
|
throw Object.assign(new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u5C0F\u6302\u4EF6"), { status: 409 });
|
|
917
917
|
return result;
|
|
918
918
|
}
|
|
919
|
+
#productOperationPending = false;
|
|
920
|
+
async simulatorProduct(offerId, input) {
|
|
921
|
+
if (this.#resetting || this.#productOperationPending) throw Object.assign(new Error("\u4F1A\u8BDD\u6B63\u5728\u5904\u7406\u5176\u4ED6\u64CD\u4F5C\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"), { status: 409 });
|
|
922
|
+
const client = this.#requiredSimulator(), revision = this.#conversationRevision;
|
|
923
|
+
if (input && input.conversationRevision !== revision) throw Object.assign(new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u5546\u54C1\u5361"), { status: 409 });
|
|
924
|
+
if (!client.productOffer || input && !client.purchaseProduct) throw Object.assign(new Error("\u8BF7\u66F4\u65B0 CLI \u540E\u91CD\u8FDE\uFF0C\u4EE5\u9884\u89C8\u5546\u54C1\u5361"), { status: 501 });
|
|
925
|
+
const state = await client.state();
|
|
926
|
+
if (!state.messages.some((message2) => message2.product?.offerId === offerId)) throw Object.assign(new Error("\u5546\u54C1\u5361\u5DF2\u4E0D\u5728\u5F53\u524D\u5BF9\u8BDD\u4E2D\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00"), { status: 404 });
|
|
927
|
+
if (this.#resetting || this.#productOperationPending || client !== this.#simulator || revision !== this.#conversationRevision) throw Object.assign(new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362\u6216\u6B63\u5728\u8D2D\u4E70\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"), { status: 409 });
|
|
928
|
+
this.#productOperationPending = true;
|
|
929
|
+
try {
|
|
930
|
+
const result = input ? await client.purchaseProduct(offerId, input) : await client.productOffer(offerId);
|
|
931
|
+
if (this.#resetting || client !== this.#simulator || revision !== this.#conversationRevision) throw Object.assign(new Error("\u4F1A\u8BDD\u5DF2\u5207\u6362\uFF0C\u8BF7\u5237\u65B0\u72B6\u6001"), { status: 409 });
|
|
932
|
+
return result;
|
|
933
|
+
} finally {
|
|
934
|
+
this.#productOperationPending = false;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
919
937
|
async resetSimulator() {
|
|
920
|
-
if (this.#resetting || this.#sendingMessage || this.#simulatorState.activeRun) {
|
|
938
|
+
if (this.#resetting || this.#sendingMessage || this.#productOperationPending || this.#simulatorState.activeRun) {
|
|
921
939
|
throw Object.assign(new Error("\u8BF7\u7B49\u5F85\u5F53\u524D\u56DE\u590D\u6216\u64CD\u4F5C\u5B8C\u6210\u540E\u518D\u6E05\u7A7A"), { status: 409, code: "SIMULATOR_BUSY" });
|
|
922
940
|
}
|
|
923
941
|
const simulator = this.#requiredSimulator();
|
|
@@ -1381,6 +1399,8 @@ var WEB_ASSETS = Object.freeze(/* @__PURE__ */ new Map([
|
|
|
1381
1399
|
contentType: "text/css; charset=utf-8",
|
|
1382
1400
|
body: readFileSync2(new URL("../web/brand.css", import.meta.url))
|
|
1383
1401
|
}],
|
|
1402
|
+
["/assets/products.js", { contentType: "text/javascript; charset=utf-8", body: readFileSync2(new URL("../web/products.js", import.meta.url)) }],
|
|
1403
|
+
["/assets/products.css", { contentType: "text/css; charset=utf-8", body: readFileSync2(new URL("../web/products.css", import.meta.url)) }],
|
|
1384
1404
|
["/assets/widgets.js", { contentType: "text/javascript; charset=utf-8", body: readFileSync2(new URL("../web/widgets.js", import.meta.url)) }],
|
|
1385
1405
|
["/assets/widgets.css", { contentType: "text/css; charset=utf-8", body: readFileSync2(new URL("../web/widgets.css", import.meta.url)) }],
|
|
1386
1406
|
["/assets/app.js", {
|
|
@@ -1629,6 +1649,22 @@ data: ${JSON.stringify(value)}
|
|
|
1629
1649
|
return apiError(response, failure.status, failure.code, failure.message);
|
|
1630
1650
|
}
|
|
1631
1651
|
}
|
|
1652
|
+
const productRoute = /^\/api\/simulator\/products\/([A-Za-z0-9_-]{1,120})(\/mock-purchase)?$/u.exec(url.pathname);
|
|
1653
|
+
if (productRoute) {
|
|
1654
|
+
try {
|
|
1655
|
+
if (request.method === "GET" && !productRoute[2]) return json(response, 200, await options.controller.simulatorProduct(productRoute[1]));
|
|
1656
|
+
if (request.method === "POST" && productRoute[2]) {
|
|
1657
|
+
const body = exactObject(await readJsonBody(request), ["expectedVersion", "idempotencyKey", "conversationRevision"]);
|
|
1658
|
+
if (!body || !Number.isSafeInteger(body.expectedVersion) || Number(body.expectedVersion) < 1 || !Number.isSafeInteger(body.conversationRevision) || !safeIdentifier(body.idempotencyKey, 128))
|
|
1659
|
+
return apiError(response, 400, "INVALID_PURCHASE", "\u8BF7\u91CD\u65B0\u6253\u5F00\u5546\u54C1\u5361\u5E76\u786E\u8BA4\u7248\u672C");
|
|
1660
|
+
return json(response, 200, await options.controller.simulatorProduct(productRoute[1], body));
|
|
1661
|
+
}
|
|
1662
|
+
return apiError(response, 405, "METHOD_NOT_ALLOWED", "\u4E0D\u652F\u6301\u8FD9\u4E2A\u5546\u54C1\u64CD\u4F5C");
|
|
1663
|
+
} catch (cause) {
|
|
1664
|
+
const failure = requestFailure(cause);
|
|
1665
|
+
return apiError(response, failure.status, failure.code, failure.message);
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1632
1668
|
const widgetRoute = /^\/api\/simulator\/widgets(?:\/([^/]+)(?:\/(image|pin|bridge))?)?$/u.exec(url.pathname);
|
|
1633
1669
|
if (widgetRoute) {
|
|
1634
1670
|
try {
|
|
@@ -2233,10 +2269,10 @@ function object2(value) {
|
|
|
2233
2269
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
2234
2270
|
}
|
|
2235
2271
|
function httpError(status, value) {
|
|
2236
|
-
const serverMessage = object2(value)?.error;
|
|
2272
|
+
const serverMessage = object2(object2(value)?.error)?.message ?? object2(value)?.error;
|
|
2237
2273
|
const message2 = typeof serverMessage === "string" && serverMessage.trim() ? serverMessage.slice(0, 512) : status >= 500 ? "MLB Server \u6682\u65F6\u4E0D\u53EF\u7528" : "\u6A21\u62DF\u5668\u8BF7\u6C42\u672A\u80FD\u5B8C\u6210";
|
|
2238
2274
|
return Object.assign(new Error(message2), {
|
|
2239
|
-
code: "MLB_REQUEST_FAILED",
|
|
2275
|
+
code: typeof object2(object2(value)?.error)?.code === "string" ? object2(object2(value)?.error).code : "MLB_REQUEST_FAILED",
|
|
2240
2276
|
status,
|
|
2241
2277
|
publicMessage: message2
|
|
2242
2278
|
});
|
|
@@ -2247,7 +2283,7 @@ function message(value, index) {
|
|
|
2247
2283
|
const role = input.author === "buddy" ? "assistant" : input.author === "user" || input.author === "owner" ? "user" : void 0;
|
|
2248
2284
|
if (!role) return null;
|
|
2249
2285
|
const messageId = safeText(input.id, `messages[${index}].id`, 256);
|
|
2250
|
-
let text2 = input.type
|
|
2286
|
+
let text2 = ["widget", "product"].includes(String(input.type)) && input.text === void 0 ? "" : input.text;
|
|
2251
2287
|
if (typeof text2 !== "string" || Buffer.byteLength(text2, "utf8") > 48 * 1024) {
|
|
2252
2288
|
throw new Error(`messages[${index}].text is invalid`);
|
|
2253
2289
|
}
|
|
@@ -2275,7 +2311,20 @@ ${options.map((option, i) => `${i + 1}. ${option}`).join("\n")}
|
|
|
2275
2311
|
role,
|
|
2276
2312
|
text: text2,
|
|
2277
2313
|
createdAt: new Date(input.timestamp).toISOString(),
|
|
2278
|
-
...input.type === "widget" && object2(input.widget) ? { widget: parseWidget(input.widget) } : {}
|
|
2314
|
+
...input.type === "widget" && object2(input.widget) ? { widget: parseWidget(input.widget) } : {},
|
|
2315
|
+
...input.type === "product" && role === "assistant" ? { product: parseProduct(input.product) } : {}
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2318
|
+
function parseProduct(value) {
|
|
2319
|
+
const product = object2(value);
|
|
2320
|
+
if (!product || !Number.isSafeInteger(product.version) || Number(product.version) < 1) throw new TypeError("\u5546\u54C1\u5361\u7248\u672C\u65E0\u6548");
|
|
2321
|
+
return Object.freeze({
|
|
2322
|
+
offerId: safeText(product.offerId, "offerId", 120),
|
|
2323
|
+
productId: safeText(product.productId, "productId", 120),
|
|
2324
|
+
version: Number(product.version),
|
|
2325
|
+
title: safeText(product.title, "\u5546\u54C1\u540D\u79F0", 512),
|
|
2326
|
+
summary: typeof product.summary === "string" ? product.summary.slice(0, 4096) : "",
|
|
2327
|
+
buttonText: typeof product.buttonText === "string" && product.buttonText.trim() ? product.buttonText.slice(0, 100) : "\u67E5\u770B\u65B9\u6848"
|
|
2279
2328
|
});
|
|
2280
2329
|
}
|
|
2281
2330
|
function widgetId(value) {
|
|
@@ -2395,6 +2444,17 @@ var MlbSimulatorClient = class {
|
|
|
2395
2444
|
}
|
|
2396
2445
|
return Object.freeze({ ...details, avatarPreview });
|
|
2397
2446
|
}
|
|
2447
|
+
async productOffer(offerId) {
|
|
2448
|
+
this.#assertResetComplete();
|
|
2449
|
+
const detail = object2(await this.#request("GET", `/app/product-offers/${encodeURIComponent(safeText(offerId, "offerId", 120))}`, {}));
|
|
2450
|
+
if (detail?.buddyId !== this.#buddyId || detail?.offerId !== offerId || detail.paymentChannel !== "mock" || detail.chargedAmountMinor !== 0)
|
|
2451
|
+
throw httpError(409, { error: "\u4EC5\u652F\u6301\u5F53\u524D DEV \u642D\u5B50\u7684\u96F6\u6263\u8D39\u6A21\u62DF\u8D2D\u4E70" });
|
|
2452
|
+
return detail;
|
|
2453
|
+
}
|
|
2454
|
+
async purchaseProduct(offerId, input) {
|
|
2455
|
+
await this.productOffer(offerId);
|
|
2456
|
+
return this.#request("POST", `/app/product-offers/${encodeURIComponent(offerId)}/mock-purchase`, { body: { expectedVersion: input.expectedVersion, idempotencyKey: safeText(input.idempotencyKey, "\u5E42\u7B49\u952E", 128) } });
|
|
2457
|
+
}
|
|
2398
2458
|
async widgets() {
|
|
2399
2459
|
this.#assertResetComplete();
|
|
2400
2460
|
const id = await this.#ensurePrivate();
|