@my-life-buddies/cli 0.17.1 → 0.17.3
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 +18 -3
- package/dist/bin/buddy.js +2 -1
- package/dist/bin/buddy.js.map +2 -2
- package/dist/bin/core.js +295 -290
- package/dist/bin/core.js.map +4 -4
- package/package.json +3 -3
- package/resources/agent-template/package-lock.json +4 -4
- package/resources/agent-template/package.json +1 -1
package/dist/bin/core.js
CHANGED
|
@@ -2681,6 +2681,271 @@ Runtime \u542F\u52A8\u65F6\u8BFB\u53D6\u6839\u76EE\u5F55 \`data-access.json\`\uF
|
|
|
2681
2681
|
|
|
2682
2682
|
\u5B8C\u6210\u914D\u7F6E\u3001\u6CE8\u518C\u3001\u6784\u5EFA\u3001\u542F\u52A8\u53CA\u5173\u952E\u89C4\u5219\u7684\u6280\u672F\u68C0\u67E5\u3002\u9700\u8981\u5B9A\u5236\u7684\u884C\u4E3A\u5FC5\u987B\u68C0\u67E5\u771F\u5B9E\u6267\u884C\u8DEF\u5F84\uFF0C\u4E0D\u80FD\u53EA\u641C\u7D22 Prompt \u4E2D\u662F\u5426\u51FA\u73B0\u67D0\u53E5\u8BDD\u3002\u968F\u540E\u8FDB\u5165\u5DF2\u6709\u7684\u771F\u5B9E\u9884\u89C8\u4EA4\u63A5\uFF0C\u7531\u5F00\u53D1\u8005\u4EB2\u81EA\u4F53\u9A8C\u5E76\u53CD\u9988\uFF1B\u4E0D\u81EA\u52A8\u5C55\u5F00\u591A\u573A\u666F\u8BD5\u804A\u3001\u8C03\u6559\u3001\u63D0\u5BA1\u6216\u53D1\u5E03\u3002`;
|
|
2683
2683
|
|
|
2684
|
+
// packages/cli-core/src/platform-url.ts
|
|
2685
|
+
var DEFAULT_MLB_TEST_URL = "http://hey-dada.life:8788";
|
|
2686
|
+
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
2687
|
+
function normalizePlatformUrl(value) {
|
|
2688
|
+
const url = new URL(value);
|
|
2689
|
+
if (url.username || url.password || url.search || url.hash) {
|
|
2690
|
+
throw new TypeError("\u5E73\u53F0\u5730\u5740\u4E0D\u80FD\u5305\u542B credentials\u3001query \u6216 fragment");
|
|
2691
|
+
}
|
|
2692
|
+
if (url.protocol !== "https:" && !(url.protocol === "http:" && (LOOPBACK_HOSTS.has(url.hostname) || url.origin === DEFAULT_MLB_TEST_URL))) {
|
|
2693
|
+
throw new TypeError(`\u5E73\u53F0\u5730\u5740\u5FC5\u987B\u4F7F\u7528 HTTPS\uFF1BHTTP \u4EC5\u5141\u8BB8\u672C\u673A\u6216\u56FA\u5B9A\u6D4B\u8BD5\u5730\u5740 ${DEFAULT_MLB_TEST_URL}`);
|
|
2694
|
+
}
|
|
2695
|
+
if (!url.pathname.endsWith("/")) url.pathname += "/";
|
|
2696
|
+
return url;
|
|
2697
|
+
}
|
|
2698
|
+
function resolvePlatformUrl(options = {}) {
|
|
2699
|
+
const env = options.env ?? process.env;
|
|
2700
|
+
const configured = options.development ? env.BUDDY_DEV_APP_SERVER_URL ?? env.BUDDY_APP_SERVER_URL : env.BUDDY_APP_SERVER_URL ?? env.BUDDY_DEV_APP_SERVER_URL;
|
|
2701
|
+
return normalizePlatformUrl(options.override ?? configured ?? DEFAULT_MLB_TEST_URL);
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
// packages/cli-core/src/cloud/browser-login.ts
|
|
2705
|
+
import { createHash as createHash4, randomBytes } from "node:crypto";
|
|
2706
|
+
import { spawn } from "node:child_process";
|
|
2707
|
+
import { createServer } from "node:http";
|
|
2708
|
+
|
|
2709
|
+
// packages/cli-core/src/cloud/login-result.ts
|
|
2710
|
+
import { readFileSync } from "node:fs";
|
|
2711
|
+
var brand = new URL("../../resources/brand/", import.meta.url);
|
|
2712
|
+
var tokens = readFileSync(new URL("tokens.css", brand), "utf8");
|
|
2713
|
+
var styles = readFileSync(new URL("login-result.css", brand), "utf8");
|
|
2714
|
+
var logo = readFileSync(new URL("logo.png", brand)).toString("base64");
|
|
2715
|
+
function escapeHtml(value) {
|
|
2716
|
+
return value.replace(/[&<>"']/gu, (character) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[character]);
|
|
2717
|
+
}
|
|
2718
|
+
function renderLoginResult(title, message, webUrl, tone) {
|
|
2719
|
+
const label = { success: "\u5DF2\u6388\u6743", neutral: "\u5DF2\u53D6\u6D88", error: "\u672A\u5B8C\u6210" }[tone];
|
|
2720
|
+
return `<!doctype html>
|
|
2721
|
+
<html lang="zh-CN"><head>
|
|
2722
|
+
<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
2723
|
+
<meta name="color-scheme" content="light dark"><title>${escapeHtml(title)} \xB7 \u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0</title>
|
|
2724
|
+
<style>${tokens}
|
|
2725
|
+
${styles}</style></head>
|
|
2726
|
+
<body><div class="result-shell">
|
|
2727
|
+
<header class="result-brand"><img src="data:image/png;base64,${logo}" alt="" width="44" height="44"><span>\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0</span></header>
|
|
2728
|
+
<main class="result-card" aria-labelledby="result-title">
|
|
2729
|
+
<div class="result-heading"><p class="result-eyebrow">buddy-cli \u767B\u5F55</p><span class="result-status" data-tone="${tone}">${label}</span></div>
|
|
2730
|
+
<h1 id="result-title">${escapeHtml(title)}</h1>
|
|
2731
|
+
<p class="result-message">${escapeHtml(message)}</p>
|
|
2732
|
+
<div class="result-next"><strong>${tone === "success" ? "\u56DE\u5230\u7EC8\u7AEF\uFF0C\u7EE7\u7EED\u521B\u4F5C" : "\u56DE\u5230\u7EC8\u7AEF\uFF0C\u91CD\u65B0\u5F00\u59CB"}</strong>
|
|
2733
|
+
<p>${tone === "success" ? "\u67E5\u770B CLI \u7684\u767B\u5F55\u7ED3\u679C\uFF0C\u7EE7\u7EED\u521B\u5EFA\u3001\u5F00\u53D1\u548C\u9884\u89C8\u4F60\u7684\u642D\u5B50\u3002" : "\u9700\u8981\u7EE7\u7EED\u65F6\uFF0C\u5728\u7EC8\u7AEF\u91CD\u65B0\u8FD0\u884C\u767B\u5F55\u547D\u4EE4\u3002"}</p>
|
|
2734
|
+
${tone === "success" ? "" : "<code>buddy-cli login</code>"}</div>
|
|
2735
|
+
<a class="result-link" href="${escapeHtml(webUrl.href)}">\u8FD4\u56DE\u5F00\u653E\u5E73\u53F0</a>
|
|
2736
|
+
</main><footer>\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0</footer></div></body></html>`;
|
|
2737
|
+
}
|
|
2738
|
+
|
|
2739
|
+
// packages/cli-core/src/cloud/browser-login.ts
|
|
2740
|
+
var DEFAULT_LOGIN_TIMEOUT_MS = 5 * 6e4;
|
|
2741
|
+
var DEFAULT_EXCHANGE_TIMEOUT_MS = 15e3;
|
|
2742
|
+
var DEFAULT_DEVELOPER_WEB_URL = "https://hey-dada.life/developer/";
|
|
2743
|
+
var REQUEST_ID = /^[A-Za-z0-9_-]{43}$/u;
|
|
2744
|
+
var AUTH_CODE = /^[A-Za-z0-9_-]{43}$/u;
|
|
2745
|
+
function positive(value, fallback, name) {
|
|
2746
|
+
const result = value ?? fallback;
|
|
2747
|
+
if (!Number.isSafeInteger(result) || result <= 0) throw new TypeError(`${name} must be a positive safe integer`);
|
|
2748
|
+
return result;
|
|
2749
|
+
}
|
|
2750
|
+
function webBase(value) {
|
|
2751
|
+
const url = new URL(value);
|
|
2752
|
+
const loopback = ["localhost", "127.0.0.1", "[::1]", "::1"].includes(url.hostname);
|
|
2753
|
+
if (url.protocol !== "https:" && !(url.protocol === "http:" && loopback) || url.username || url.password || url.search || url.hash) {
|
|
2754
|
+
throw new CloudLifecycleError("INVALID_REQUEST", "\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u5FC5\u987B\u4F7F\u7528 HTTPS\uFF1B\u672C\u673A\u5F00\u53D1\u53EF\u4EE5\u4F7F\u7528 loopback HTTP");
|
|
2755
|
+
}
|
|
2756
|
+
if (!url.pathname.endsWith("/")) url.pathname += "/";
|
|
2757
|
+
return url;
|
|
2758
|
+
}
|
|
2759
|
+
function browserCommand(url) {
|
|
2760
|
+
if (process.platform === "darwin") return { command: "open", args: [url.href] };
|
|
2761
|
+
throw new CloudLifecycleError("INVALID_REQUEST", "\u642D\u642D CLI V1 \u672C\u5730\u767B\u5F55\u76EE\u524D\u53EA\u652F\u6301 macOS");
|
|
2762
|
+
}
|
|
2763
|
+
async function openExternalUrl(url) {
|
|
2764
|
+
const launch = browserCommand(url);
|
|
2765
|
+
await new Promise((resolve19, reject) => {
|
|
2766
|
+
const child = spawn(launch.command, launch.args, { shell: false, stdio: "ignore", windowsHide: true });
|
|
2767
|
+
child.once("error", reject);
|
|
2768
|
+
child.once("exit", (code2) => code2 === 0 ? resolve19() : reject(new Error(`browser launcher exited with ${code2 ?? "unknown"}`)));
|
|
2769
|
+
});
|
|
2770
|
+
}
|
|
2771
|
+
async function write(res, status, title, message, webUrl, tone = "error") {
|
|
2772
|
+
res.writeHead(status, {
|
|
2773
|
+
"cache-control": "no-store",
|
|
2774
|
+
"connection": "close",
|
|
2775
|
+
"content-security-policy": "default-src 'none'; img-src data:; style-src 'unsafe-inline'; frame-ancestors 'none'; base-uri 'none'",
|
|
2776
|
+
"content-type": "text/html; charset=utf-8",
|
|
2777
|
+
"referrer-policy": "no-referrer",
|
|
2778
|
+
"x-content-type-options": "nosniff"
|
|
2779
|
+
});
|
|
2780
|
+
await new Promise((resolve19, reject) => {
|
|
2781
|
+
res.once("error", reject);
|
|
2782
|
+
res.once("close", resolve19);
|
|
2783
|
+
res.end(renderLoginResult(title, message, webUrl, tone), resolve19);
|
|
2784
|
+
});
|
|
2785
|
+
}
|
|
2786
|
+
async function readJson(response) {
|
|
2787
|
+
const value = await response.json().catch(() => void 0);
|
|
2788
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2789
|
+
throw new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", "\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u6388\u6743\u7ED3\u679C");
|
|
2790
|
+
}
|
|
2791
|
+
return value;
|
|
2792
|
+
}
|
|
2793
|
+
var LoopbackBrowserLoginAdapter = class {
|
|
2794
|
+
#platformUrl;
|
|
2795
|
+
#developerWebUrl;
|
|
2796
|
+
#openBrowser;
|
|
2797
|
+
#onLoginUrl;
|
|
2798
|
+
#timeoutMs;
|
|
2799
|
+
#fetch;
|
|
2800
|
+
constructor(options) {
|
|
2801
|
+
this.#platformUrl = normalizePlatformUrl(options.platformUrl);
|
|
2802
|
+
this.#developerWebUrl = webBase(options.developerWebUrl ?? DEFAULT_DEVELOPER_WEB_URL);
|
|
2803
|
+
this.#openBrowser = options.openBrowser ?? openExternalUrl;
|
|
2804
|
+
this.#onLoginUrl = options.onLoginUrl;
|
|
2805
|
+
this.#timeoutMs = positive(options.timeoutMs, DEFAULT_LOGIN_TIMEOUT_MS, "timeoutMs");
|
|
2806
|
+
this.#fetch = options.fetch ?? globalThis.fetch;
|
|
2807
|
+
if (typeof this.#fetch !== "function") throw new TypeError("A Fetch API implementation is required");
|
|
2808
|
+
}
|
|
2809
|
+
async login(request) {
|
|
2810
|
+
if (request.signal?.aborted) throw request.signal.reason;
|
|
2811
|
+
const callbackSecret = randomBytes(24).toString("hex");
|
|
2812
|
+
const codeVerifier = randomBytes(32).toString("base64url");
|
|
2813
|
+
const codeChallenge = createHash4("sha256").update(codeVerifier).digest("base64url");
|
|
2814
|
+
let requestId = "";
|
|
2815
|
+
let settle;
|
|
2816
|
+
let reject;
|
|
2817
|
+
let settled = false;
|
|
2818
|
+
const result = new Promise((resolve19, rejectResult) => {
|
|
2819
|
+
settle = (value) => {
|
|
2820
|
+
if (!settled) {
|
|
2821
|
+
settled = true;
|
|
2822
|
+
resolve19(value);
|
|
2823
|
+
}
|
|
2824
|
+
};
|
|
2825
|
+
reject = (reason) => {
|
|
2826
|
+
if (!settled) {
|
|
2827
|
+
settled = true;
|
|
2828
|
+
rejectResult(reason);
|
|
2829
|
+
}
|
|
2830
|
+
};
|
|
2831
|
+
});
|
|
2832
|
+
void result.catch(() => void 0);
|
|
2833
|
+
const server = createServer((req, res) => {
|
|
2834
|
+
void this.#receiveCallback(req, res, {
|
|
2835
|
+
callbackSecret,
|
|
2836
|
+
codeVerifier,
|
|
2837
|
+
requestId,
|
|
2838
|
+
state: request.state
|
|
2839
|
+
}).then(settle, reject);
|
|
2840
|
+
});
|
|
2841
|
+
await new Promise((resolve19, rejectListen) => {
|
|
2842
|
+
server.once("error", rejectListen);
|
|
2843
|
+
server.listen(0, "127.0.0.1", () => resolve19());
|
|
2844
|
+
});
|
|
2845
|
+
const address = server.address();
|
|
2846
|
+
if (!address || typeof address === "string") {
|
|
2847
|
+
server.close();
|
|
2848
|
+
throw new CloudLifecycleError("PLATFORM_UNAVAILABLE", "\u65E0\u6CD5\u542F\u52A8\u672C\u673A\u767B\u5F55\u56DE\u8C03");
|
|
2849
|
+
}
|
|
2850
|
+
const redirectUri = `http://127.0.0.1:${address.port}/callback/${callbackSecret}`;
|
|
2851
|
+
const timer = setTimeout(() => reject(new CloudLifecycleError("AUTH_LOGIN_CANCELLED", "\u6D4F\u89C8\u5668\u767B\u5F55\u7B49\u5F85\u8D85\u65F6\uFF0C\u8BF7\u91CD\u8BD5")), this.#timeoutMs);
|
|
2852
|
+
timer.unref?.();
|
|
2853
|
+
const abort = () => reject(request.signal?.reason ?? new CloudLifecycleError("AUTH_LOGIN_CANCELLED", "\u767B\u5F55\u5DF2\u53D6\u6D88"));
|
|
2854
|
+
request.signal?.addEventListener("abort", abort, { once: true });
|
|
2855
|
+
try {
|
|
2856
|
+
const created = await this.#post("api/cli/authorizations", {
|
|
2857
|
+
state: request.state,
|
|
2858
|
+
codeChallenge,
|
|
2859
|
+
redirectUri,
|
|
2860
|
+
platformOrigin: this.#platformUrl.origin
|
|
2861
|
+
}, request.signal);
|
|
2862
|
+
if (typeof created.requestId !== "string" || !REQUEST_ID.test(created.requestId)) {
|
|
2863
|
+
throw new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", "\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u6388\u6743\u7F16\u53F7");
|
|
2864
|
+
}
|
|
2865
|
+
requestId = created.requestId;
|
|
2866
|
+
const loginUrl = new URL(this.#developerWebUrl);
|
|
2867
|
+
loginUrl.hash = `#/cli-authorize?requestId=${encodeURIComponent(requestId)}`;
|
|
2868
|
+
this.#onLoginUrl?.(loginUrl);
|
|
2869
|
+
await this.#openBrowser(loginUrl).catch(() => {
|
|
2870
|
+
throw new CloudLifecycleError("PLATFORM_UNAVAILABLE", "\u65E0\u6CD5\u81EA\u52A8\u6253\u5F00\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\uFF0C\u8BF7\u68C0\u67E5\u7CFB\u7EDF\u9ED8\u8BA4\u6D4F\u89C8\u5668\u540E\u91CD\u8BD5");
|
|
2871
|
+
});
|
|
2872
|
+
return await result;
|
|
2873
|
+
} finally {
|
|
2874
|
+
clearTimeout(timer);
|
|
2875
|
+
request.signal?.removeEventListener("abort", abort);
|
|
2876
|
+
await new Promise((resolve19) => {
|
|
2877
|
+
server.close(() => resolve19());
|
|
2878
|
+
server.closeIdleConnections();
|
|
2879
|
+
server.closeAllConnections();
|
|
2880
|
+
});
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
async #receiveCallback(req, res, expected) {
|
|
2884
|
+
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
2885
|
+
if (req.method !== "GET" || url.pathname !== `/callback/${expected.callbackSecret}`) {
|
|
2886
|
+
await write(res, 404, "\u9875\u9762\u4E0D\u5B58\u5728", "\u8BF7\u56DE\u5230\u7EC8\u7AEF\u91CD\u65B0\u53D1\u8D77\u767B\u5F55\u3002", this.#developerWebUrl);
|
|
2887
|
+
throw new CloudLifecycleError("AUTH_LOGIN_CANCELLED", "\u6D4F\u89C8\u5668\u56DE\u8C03\u65E0\u6548\uFF0C\u8BF7\u91CD\u8BD5");
|
|
2888
|
+
}
|
|
2889
|
+
if (url.searchParams.get("state") !== expected.state) {
|
|
2890
|
+
await write(res, 400, "\u767B\u5F55\u6CA1\u6709\u5B8C\u6210", "\u6388\u6743\u6821\u9A8C\u5931\u8D25\uFF0C\u8BF7\u56DE\u5230\u7EC8\u7AEF\u91CD\u8BD5\u3002", this.#developerWebUrl);
|
|
2891
|
+
throw new CloudLifecycleError("AUTH_STATE_MISMATCH", "\u6D4F\u89C8\u5668\u767B\u5F55\u8FD4\u56DE\u7684 state \u4E0D\u5339\u914D\uFF1B\u51ED\u636E\u672A\u4FDD\u5B58");
|
|
2892
|
+
}
|
|
2893
|
+
if (url.searchParams.get("error") === "access_denied") {
|
|
2894
|
+
await write(res, 200, "\u5DF2\u53D6\u6D88\u6388\u6743", "\u6CA1\u6709\u5411 buddy-cli \u63D0\u4F9B\u8D26\u53F7\u6743\u9650\uFF0C\u53EF\u4EE5\u5173\u95ED\u8FD9\u4E2A\u9875\u9762\u3002", this.#developerWebUrl, "neutral");
|
|
2895
|
+
throw new CloudLifecycleError("AUTH_LOGIN_CANCELLED", "\u7528\u6237\u53D6\u6D88\u4E86 CLI \u6388\u6743");
|
|
2896
|
+
}
|
|
2897
|
+
const code2 = url.searchParams.get("code");
|
|
2898
|
+
if (!code2 || !AUTH_CODE.test(code2) || !expected.requestId) {
|
|
2899
|
+
await write(res, 400, "\u767B\u5F55\u6CA1\u6709\u5B8C\u6210", "\u6388\u6743\u7ED3\u679C\u65E0\u6548\uFF0C\u8BF7\u56DE\u5230\u7EC8\u7AEF\u91CD\u8BD5\u3002", this.#developerWebUrl);
|
|
2900
|
+
throw new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", "\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u8FD4\u56DE\u4E86\u65E0\u6548\u6388\u6743\u7801");
|
|
2901
|
+
}
|
|
2902
|
+
try {
|
|
2903
|
+
const exchanged = await this.#post("api/cli/exchange", {
|
|
2904
|
+
requestId: expected.requestId,
|
|
2905
|
+
code: code2,
|
|
2906
|
+
codeVerifier: expected.codeVerifier
|
|
2907
|
+
});
|
|
2908
|
+
if (exchanged.platformOrigin !== this.#platformUrl.origin || typeof exchanged.token !== "string" || typeof exchanged.userId !== "string" || !Number.isSafeInteger(exchanged.expiresAt)) {
|
|
2909
|
+
throw new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", "\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u8FD4\u56DE\u7684\u8D26\u53F7\u51ED\u636E\u4E0D\u5B8C\u6574");
|
|
2910
|
+
}
|
|
2911
|
+
await write(res, 200, "\u767B\u5F55\u6210\u529F", "buddy-cli \u5DF2\u83B7\u5F97\u6388\u6743\uFF0C\u53EF\u4EE5\u5173\u95ED\u8FD9\u4E2A\u9875\u9762\u5E76\u8FD4\u56DE\u7EC8\u7AEF\u3002", this.#developerWebUrl, "success");
|
|
2912
|
+
return {
|
|
2913
|
+
state: expected.state,
|
|
2914
|
+
token: {
|
|
2915
|
+
accessToken: exchanged.token,
|
|
2916
|
+
subject: exchanged.userId,
|
|
2917
|
+
expiresAt: exchanged.expiresAt
|
|
2918
|
+
}
|
|
2919
|
+
};
|
|
2920
|
+
} catch (error2) {
|
|
2921
|
+
await write(res, 502, "\u767B\u5F55\u6CA1\u6709\u5B8C\u6210", "\u6388\u6743\u4EA4\u6362\u5931\u8D25\uFF0C\u8BF7\u56DE\u5230\u7EC8\u7AEF\u91CD\u8BD5\u3002", this.#developerWebUrl);
|
|
2922
|
+
throw error2;
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
async #post(path, payload, signal) {
|
|
2926
|
+
let response;
|
|
2927
|
+
try {
|
|
2928
|
+
const signals = [AbortSignal.timeout(DEFAULT_EXCHANGE_TIMEOUT_MS), ...signal ? [signal] : []];
|
|
2929
|
+
response = await this.#fetch(new URL(path, this.#developerWebUrl), {
|
|
2930
|
+
method: "POST",
|
|
2931
|
+
headers: { Accept: "application/json", "Content-Type": "application/json" },
|
|
2932
|
+
body: JSON.stringify(payload),
|
|
2933
|
+
redirect: "error",
|
|
2934
|
+
signal: AbortSignal.any(signals)
|
|
2935
|
+
});
|
|
2936
|
+
} catch {
|
|
2937
|
+
if (signal?.aborted) throw signal.reason;
|
|
2938
|
+
throw new CloudLifecycleError("PLATFORM_UNAVAILABLE", "\u65E0\u6CD5\u8FDE\u63A5\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u5B8C\u6210 CLI \u767B\u5F55");
|
|
2939
|
+
}
|
|
2940
|
+
const data = await readJson(response);
|
|
2941
|
+
if (!response.ok) {
|
|
2942
|
+
const message = typeof data.error === "string" ? data.error : "\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u62D2\u7EDD\u4E86\u8FD9\u6B21 CLI \u6388\u6743";
|
|
2943
|
+
throw new CloudLifecycleError(response.status === 400 || response.status === 409 || response.status === 410 ? "AUTH_LOGIN_CANCELLED" : "PLATFORM_UNAVAILABLE", message);
|
|
2944
|
+
}
|
|
2945
|
+
return data;
|
|
2946
|
+
}
|
|
2947
|
+
};
|
|
2948
|
+
|
|
2684
2949
|
// packages/cli-core/src/help.ts
|
|
2685
2950
|
var CLI_HELP = `\u642D\u642D Developer Platform CLI
|
|
2686
2951
|
|
|
@@ -2704,6 +2969,8 @@ var CLI_HELP = `\u642D\u642D Developer Platform CLI
|
|
|
2704
2969
|
--version \u67E5\u770B\u5F53\u524D CLI \u7248\u672C
|
|
2705
2970
|
|
|
2706
2971
|
\u76F4\u63A5\u8FD0\u884C buddy-cli \u53EF\u8BC6\u522B\u5F53\u524D\u5DE5\u7A0B\u6216\u5F15\u5BFC\u521B\u5EFA\u3002
|
|
2972
|
+
\u9ED8\u8BA4\u5E73\u53F0\uFF1A${DEFAULT_MLB_TEST_URL}\uFF1B\u5F00\u53D1\u8005\u540E\u53F0\uFF1A${DEFAULT_DEVELOPER_WEB_URL}\u3002
|
|
2973
|
+
\u5E73\u53F0\u8FC1\u79FB\u540E\u91CD\u65B0 login\uFF1B\u65E7\u5DE5\u7A0B\u7528 dev --refresh-token \u6216 preview --refresh-token \u66F4\u65B0\u5F00\u53D1\u51ED\u636E\u548C .env \u5730\u5740\u3002
|
|
2707
2974
|
\u6B63\u5E38\u547D\u4EE4\u5148\u8054\u7F51\u81EA\u68C0\uFF0C\u65E7\u7248\u81EA\u52A8\u66F4\u65B0\u540E\u7EE7\u7EED\u6267\u884C\uFF1B\u5931\u8D25\u65F6\u505C\u6B62\u3002\u5E2E\u52A9\u548C --version \u79BB\u7EBF\u53EF\u7528\u3002
|
|
2708
2975
|
\u53C2\u6570\u4E0E\u793A\u4F8B: buddy-cli <\u547D\u4EE4> --help\uFF0C\u4F8B\u5982 buddy-cli init --help\u3002
|
|
2709
2976
|
Coding Agent \u5F00\u59CB\u5DE5\u4F5C\u524D\u8BF7\u8BFB\u53D6 buddy-cli guide\u3002`;
|
|
@@ -2740,6 +3007,8 @@ Skill \u7684\u5177\u4F53\u6D41\u7A0B\u8BFB\u53D6 HANDOFF.md \u4E2D\u7684\u6587\u
|
|
|
2740
3007
|
|
|
2741
3008
|
## CLI \u7248\u672C\u4E0E\u6267\u884C\u89C4\u5219
|
|
2742
3009
|
|
|
3010
|
+
\u5E73\u53F0\u5165\u53E3\u4E3A ${DEFAULT_MLB_TEST_URL}\uFF0C\u5F00\u53D1\u8005\u540E\u53F0\u4E3A ${DEFAULT_DEVELOPER_WEB_URL}\u3002\u5DF2\u6709\u5DE5\u7A0B\u4ECE\u65E7\u670D\u52A1\u5668\u8FC1\u79FB\u65F6\uFF0C\u5148\u79FB\u9664\u6216\u66F4\u65B0\u7EC8\u7AEF\u4E2D\u7684 BUDDY_APP_SERVER_URL\u3001BUDDY_DEV_APP_SERVER_URL\u3001BUDDY_DEVELOPER_WEB_URL \u8986\u76D6\uFF0C\u91CD\u65B0 login\uFF0C\u518D\u6267\u884C dev --refresh-token \u6216 preview --refresh-token\uFF1BDEV \u542F\u52A8\u65F6\u66F4\u65B0 .env\uFF0C\u4FDD\u7559 package.json.buddyId \u4E0E\u4E1A\u52A1\u914D\u7F6E\u3002
|
|
3011
|
+
|
|
2743
3012
|
\u4F7F\u7528\u5B98\u65B9 buddy-cli \u5165\u53E3\u3002\u6BCF\u6761\u6B63\u5E38\u547D\u4EE4\uFF08\u5305\u62EC guide\uFF09\u6267\u884C\u524D\u90FD\u4F1A\u67E5\u8BE2\u516C\u5171 npm latest\uFF1B\u7248\u672C\u8FC7\u65E7\u65F6\u81EA\u52A8\u66F4\u65B0\uFF0C\u518D\u7531\u65B0\u7248\u6267\u884C\u540C\u4E00\u547D\u4EE4\u3002\u7B49\u5F85\u5F53\u524D\u547D\u4EE4\u5B8C\u6210\uFF0C\u4E0D\u91CD\u590D\u53D1\u8D77\uFF0C\u4E0D\u53E6\u5F00\u8FDB\u7A0B\u540C\u65F6\u91CD\u8DD1\u3002
|
|
2744
3013
|
\u5168\u5C40\u5B89\u88C5\u66F4\u65B0\u5BF9\u5E94 npm \u73AF\u5883\u7684\u5B89\u88C5\uFF1B\u6E90\u7801\u3001npm link\u3001\u9879\u76EE\u5185\u5B89\u88C5\u548C npx \u901A\u8FC7\u7F13\u5B58\u7684\u65B0\u7248\u7EE7\u7EED\u6267\u884C\uFF0C\u4E0D\u6539\u5199\u6E90\u7801\u6216\u9879\u76EE\u4F9D\u8D56\u3002\u53C2\u6570\u3001\u5DE5\u4F5C\u76EE\u5F55\u3001\u7EC8\u7AEF\u8F93\u5165\u8F93\u51FA\u548C\u9000\u51FA\u72B6\u6001\u4FDD\u7559\u3002\u4E00\u6B21\u8C03\u7528\u6700\u591A\u81EA\u52A8\u5207\u6362\u4E00\u6B21\uFF1B\u5F53\u524D\u7248\u672C\u9AD8\u4E8E latest \u65F6\u4E0D\u964D\u7EA7\uFF0C\u5DF2\u8FD0\u884C\u7684 DEV \u4E0D\u4F1A\u56E0\u53D1\u5E03\u65B0 CLI \u81EA\u52A8\u91CD\u542F\u3002
|
|
2745
3014
|
\u5E2E\u52A9\u3001\u5404\u547D\u4EE4 --help \u548C --version \u79BB\u7EBF\u53EF\u7528\uFF1Bupdate \u662F\u5355\u72EC\u68C0\u67E5\u6216\u66F4\u65B0\u5165\u53E3\u3002\u67E5\u8BE2\u6216\u66F4\u65B0\u5931\u8D25\u65F6\u539F\u4E1A\u52A1\u64CD\u4F5C\u4E0D\u4F1A\u5F00\u59CB\uFF0C\u6839\u636E\u9519\u8BEF\u5904\u7406\u540E\u91CD\u8BD5\uFF0C\u4E0D\u8C03\u7528\u65E7\u7248\u6E90\u7801\u7ED5\u8FC7\u68C0\u67E5\u3002\u65E7 CLI \u9700\u5148\u901A\u8FC7\u5B98\u65B9 npm \u5B89\u88C5\u547D\u4EE4\u5347\u7EA7\u4E00\u6B21\uFF0C\u624D\u80FD\u83B7\u5F97\u6B64\u673A\u5236\u3002
|
|
@@ -2760,37 +3029,17 @@ Coding Agent \u5E94\u76F4\u63A5\u6CBF\u7528\u7528\u6237\u660E\u786E\u63D0\u4F9B\
|
|
|
2760
3029
|
\u975E\u4EA4\u4E92\u8C03\u7528\u987B\u5728\u5F00\u53D1\u8005\u660E\u786E\u786E\u8BA4\u5B9E\u9645\u5934\u50CF\u548C\u8D44\u6599\u540E\u4F20 --avatar <\u5DF2\u786E\u8BA4\u56FE\u7247> --confirm-meta\u3002\u672A\u786E\u8BA4\u4E0D\u5F97\u4F20\u8BE5\u6807\u5FD7\uFF1B\u7F3A\u5C11\u56FE\u7247\u6216\u786E\u8BA4\u65F6\u9000\u51FA\u7801\u4E3A 2\uFF0C\u8349\u7A3F\u4FDD\u7559\uFF0C\u53EF\u4EE5\u5728\u539F\u76EE\u5F55\u7EE7\u7EED\u3002
|
|
2761
3030
|
--mode create \u5B8C\u6210\u8D44\u6599\u548C\u5934\u50CF\u767B\u8BB0\u540E\uFF0C\u52A8\u6001\u83B7\u53D6\u72EC\u7ACB Creator Skill \u5E76\u751F\u6210\u63A5\u7EED\u8BF4\u660E\uFF0C\u9879\u76EE .buddy/creator/ \u4FDD\u5B58\u521B\u4F5C\u8D44\u6599\u4E0E skill-lock.json \u7248\u672C\u8BB0\u5F55\u3002\u4F7F\u7528 --creator-version <\u51C6\u786E\u7248\u672C> \u663E\u5F0F\u5347\u7EA7\uFF0C\u5DF2\u6709\u9879\u76EE\u9ED8\u8BA4\u590D\u7528\u56FA\u5B9A\u7248\u672C\uFF1B\u672C\u5730\u8054\u8C03\u53EF\u8BBE\u7F6E BUDDY_CREATOR_SKILL_PATH \u7EDD\u5BF9\u8DEF\u5F84\u3002
|
|
2762
3031
|
\u7531\u5F53\u524D Coding Agent \u8BFB\u53D6 .buddy/creator/HANDOFF.md \u5E76\u6267\u884C\u5176\u4E2D\u6307\u5411\u7684 Skill\uFF1B\u9700\u8981 Python 3.9+\uFF0C\u4E0D\u542F\u52A8\u65E7\u91C7\u8BBF Web \u6216\u72EC\u7ACB\u6A21\u578B\u3002
|
|
2763
|
-
\u56DB\u518C\u786E\u8BA4\u540E\u7EE7\u7EED\u5C0F\u6302\u4EF6\u6E05\u5355\u3001\u539F\u578B\u548C\u8BBE\u8BA1\u9A8C\u6536\uFF1B\u5168\u90E8\u786E\u8BA4\u5E76\u901A\u8FC7\u4EA4\u4ED8\u6821\u9A8C\u540E\uFF0C\u7531 Coding Agent \u81EA\u52A8\u8854\u63A5\u5F00\u53D1\uFF0C\u9700\u8981\u521D\u59CB\u5316\u65F6\u6267\u884C init --mode direct \u751F\u6210\u5B98\u65B9 Runtime \u5DE5\u7A0B\u3002\u540C\u76EE\u5F55\u6062\u590D\u65F6\u4ECE package.json \u8BFB\u53D6 buddyId\uFF0C\u5E76\u4F7F\u7528\u5E73\u53F0\u6700\u65B0 Meta\u3002
|
|
2764
|
-
Coding Agent \u5E94\u4F20\u5165\u6309\u4E0A\u8FF0\u89C4\u5219\u786E\u5B9A\u7684\u8D44\u6599\uFF0C\u811A\u672C\u4F7F\u7528\u5F00\u53D1\u8005\u63D0\u4F9B\u7684\u53C2\u6570\uFF0C\u907F\u514D\u7B49\u5F85\u7EC8\u7AEF\u8F93\u5165\u3002CLI \u6821\u9A8C\u53C2\u6570\uFF0C\u4E0D\u5224\u65AD\u5BF9\u8BDD\u4E2D\u662F\u5426\u5DF2\u7ECF\u786E\u8BA4\uFF1B\u53C2\u6570\u9F50\u5168\u4E0D\u7B49\u4E8E\u7528\u6237\u786E\u8BA4\u3002
|
|
2765
|
-
Coding Agent \u6839\u636E\u5DF2\u786E\u8BA4\u624B\u518C\u6216\u9700\u6C42\u63A8\u8FDB\u5B9E\u73B0\uFF1B\u53EA\u4E3A\u5173\u952E\u7F3A\u53E3\u8BE2\u95EE\uFF0C\u4E0D\u56FA\u5B9A\u8FFD\u52A0\u7B56\u7565\u786E\u8BA4\u3002
|
|
2766
|
-
\u6240\u6709\u642D\u5B50\u7EDF\u4E00\u4F7F\u7528\u5B98\u65B9 Runtime\uFF1B\u9700\u6C42\u660E\u786E\u65F6\u4F7F\u7528 --mode direct\uFF0C\u9700\u8981\u68B3\u7406\u9700\u6C42\u65F6\u4F7F\u7528 --mode create\u3002
|
|
2767
|
-
|
|
2768
|
-
${IMPLEMENTATION_GUIDE}
|
|
2769
|
-
|
|
2770
|
-
${DEVELOPMENT_HANDOFF}`;
|
|
2771
|
-
|
|
2772
|
-
// packages/cli-core/src/commands/dev.ts
|
|
2773
|
-
import { resolve as resolve14 } from "node:path";
|
|
2774
|
-
|
|
2775
|
-
// packages/cli-core/src/platform-url.ts
|
|
2776
|
-
var DEFAULT_MLB_TEST_URL = "http://47.116.168.81:8788";
|
|
2777
|
-
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
2778
|
-
function normalizePlatformUrl(value) {
|
|
2779
|
-
const url = new URL(value);
|
|
2780
|
-
if (url.username || url.password || url.search || url.hash) {
|
|
2781
|
-
throw new TypeError("\u5E73\u53F0\u5730\u5740\u4E0D\u80FD\u5305\u542B credentials\u3001query \u6216 fragment");
|
|
2782
|
-
}
|
|
2783
|
-
if (url.protocol !== "https:" && !(url.protocol === "http:" && (LOOPBACK_HOSTS.has(url.hostname) || url.origin === DEFAULT_MLB_TEST_URL))) {
|
|
2784
|
-
throw new TypeError(`\u5E73\u53F0\u5730\u5740\u5FC5\u987B\u4F7F\u7528 HTTPS\uFF1BHTTP \u4EC5\u5141\u8BB8\u672C\u673A\u6216\u56FA\u5B9A\u6D4B\u8BD5\u5730\u5740 ${DEFAULT_MLB_TEST_URL}`);
|
|
2785
|
-
}
|
|
2786
|
-
if (!url.pathname.endsWith("/")) url.pathname += "/";
|
|
2787
|
-
return url;
|
|
2788
|
-
}
|
|
2789
|
-
function resolvePlatformUrl(options = {}) {
|
|
2790
|
-
const env = options.env ?? process.env;
|
|
2791
|
-
const configured = options.development ? env.BUDDY_DEV_APP_SERVER_URL ?? env.BUDDY_APP_SERVER_URL : env.BUDDY_APP_SERVER_URL ?? env.BUDDY_DEV_APP_SERVER_URL;
|
|
2792
|
-
return normalizePlatformUrl(options.override ?? configured ?? DEFAULT_MLB_TEST_URL);
|
|
2793
|
-
}
|
|
3032
|
+
\u56DB\u518C\u786E\u8BA4\u540E\u7EE7\u7EED\u5C0F\u6302\u4EF6\u6E05\u5355\u3001\u539F\u578B\u548C\u8BBE\u8BA1\u9A8C\u6536\uFF1B\u5168\u90E8\u786E\u8BA4\u5E76\u901A\u8FC7\u4EA4\u4ED8\u6821\u9A8C\u540E\uFF0C\u7531 Coding Agent \u81EA\u52A8\u8854\u63A5\u5F00\u53D1\uFF0C\u9700\u8981\u521D\u59CB\u5316\u65F6\u6267\u884C init --mode direct \u751F\u6210\u5B98\u65B9 Runtime \u5DE5\u7A0B\u3002\u540C\u76EE\u5F55\u6062\u590D\u65F6\u4ECE package.json \u8BFB\u53D6 buddyId\uFF0C\u5E76\u4F7F\u7528\u5E73\u53F0\u6700\u65B0 Meta\u3002
|
|
3033
|
+
Coding Agent \u5E94\u4F20\u5165\u6309\u4E0A\u8FF0\u89C4\u5219\u786E\u5B9A\u7684\u8D44\u6599\uFF0C\u811A\u672C\u4F7F\u7528\u5F00\u53D1\u8005\u63D0\u4F9B\u7684\u53C2\u6570\uFF0C\u907F\u514D\u7B49\u5F85\u7EC8\u7AEF\u8F93\u5165\u3002CLI \u6821\u9A8C\u53C2\u6570\uFF0C\u4E0D\u5224\u65AD\u5BF9\u8BDD\u4E2D\u662F\u5426\u5DF2\u7ECF\u786E\u8BA4\uFF1B\u53C2\u6570\u9F50\u5168\u4E0D\u7B49\u4E8E\u7528\u6237\u786E\u8BA4\u3002
|
|
3034
|
+
Coding Agent \u6839\u636E\u5DF2\u786E\u8BA4\u624B\u518C\u6216\u9700\u6C42\u63A8\u8FDB\u5B9E\u73B0\uFF1B\u53EA\u4E3A\u5173\u952E\u7F3A\u53E3\u8BE2\u95EE\uFF0C\u4E0D\u56FA\u5B9A\u8FFD\u52A0\u7B56\u7565\u786E\u8BA4\u3002
|
|
3035
|
+
\u6240\u6709\u642D\u5B50\u7EDF\u4E00\u4F7F\u7528\u5B98\u65B9 Runtime\uFF1B\u9700\u6C42\u660E\u786E\u65F6\u4F7F\u7528 --mode direct\uFF0C\u9700\u8981\u68B3\u7406\u9700\u6C42\u65F6\u4F7F\u7528 --mode create\u3002
|
|
3036
|
+
|
|
3037
|
+
${IMPLEMENTATION_GUIDE}
|
|
3038
|
+
|
|
3039
|
+
${DEVELOPMENT_HANDOFF}`;
|
|
3040
|
+
|
|
3041
|
+
// packages/cli-core/src/commands/dev.ts
|
|
3042
|
+
import { resolve as resolve14 } from "node:path";
|
|
2794
3043
|
|
|
2795
3044
|
// packages/cli-core/src/dev/project-env.ts
|
|
2796
3045
|
import { constants } from "node:fs";
|
|
@@ -2864,7 +3113,7 @@ async function projectBuddyToken(projectRoot, gatewayUrl) {
|
|
|
2864
3113
|
try {
|
|
2865
3114
|
gateway = normalizePlatformUrl(values.MLB_GATEWAY_URL);
|
|
2866
3115
|
} catch {
|
|
2867
|
-
throw invalid(".env \u4E2D\u7684 MLB_GATEWAY_URL \u65E0\u6548\u3002");
|
|
3116
|
+
throw invalid(".env \u4E2D\u7684 MLB_GATEWAY_URL \u65E0\u6548\uFF1B\u8BF7\u786E\u8BA4\u5E73\u53F0\u540E\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6\u5F00\u53D1\u4EE4\u724C\u5E76\u66F4\u65B0\u5730\u5740\u3002");
|
|
2868
3117
|
}
|
|
2869
3118
|
if (gateway.href !== gatewayUrl.href) throw invalid(".env \u7684\u5E73\u53F0\u5730\u5740\u4E0E\u672C\u6B21\u542F\u52A8\u4E0D\u540C\uFF1B\u8BF7\u786E\u8BA4\u5E73\u53F0\u540E\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6\u5F00\u53D1\u4EE4\u724C\u3002");
|
|
2870
3119
|
}
|
|
@@ -3210,19 +3459,19 @@ function buildAgentEnvironment(options) {
|
|
|
3210
3459
|
}
|
|
3211
3460
|
|
|
3212
3461
|
// packages/cli-core/src/dev/orchestrator.ts
|
|
3213
|
-
import { createHash as
|
|
3462
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
3214
3463
|
import { readFile as readFile16 } from "node:fs/promises";
|
|
3215
3464
|
import { join as join17, resolve as resolve12 } from "node:path";
|
|
3216
3465
|
|
|
3217
3466
|
// packages/cli-core/src/dev/reload.ts
|
|
3218
3467
|
import { watch } from "node:fs";
|
|
3219
|
-
import { createHash as
|
|
3468
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
3220
3469
|
import { readFile as readFile13, readdir as readdir4 } from "node:fs/promises";
|
|
3221
3470
|
import { join as join15, resolve as resolve9 } from "node:path";
|
|
3222
3471
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
3223
3472
|
|
|
3224
3473
|
// packages/cli-core/src/dev/instance-lock.ts
|
|
3225
|
-
import { createHash as
|
|
3474
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
3226
3475
|
import { homedir as homedir3 } from "node:os";
|
|
3227
3476
|
import { join as join14 } from "node:path";
|
|
3228
3477
|
function alreadyRunningError() {
|
|
@@ -3232,14 +3481,14 @@ function alreadyRunningError() {
|
|
|
3232
3481
|
async function acquireDevInstanceLock(options) {
|
|
3233
3482
|
return acquireProcessLock({
|
|
3234
3483
|
directory: options.directory ?? join14(homedir3(), ".buddy", "dev-locks"),
|
|
3235
|
-
key:
|
|
3484
|
+
key: createHash5("sha256").update(`${new URL(options.gatewayUrl).origin}
|
|
3236
3485
|
${options.devAgentId}`).digest("hex"),
|
|
3237
3486
|
busyError: alreadyRunningError
|
|
3238
3487
|
});
|
|
3239
3488
|
}
|
|
3240
3489
|
|
|
3241
3490
|
// packages/cli-core/src/dev/reload.ts
|
|
3242
|
-
var digest2 = (contents) =>
|
|
3491
|
+
var digest2 = (contents) => createHash6("sha256").update(contents).digest("hex");
|
|
3243
3492
|
async function snapshot(root, prefix = "", result = /* @__PURE__ */ new Map()) {
|
|
3244
3493
|
for (const entry2 of await readdir4(join15(root, prefix), { withFileTypes: true })) {
|
|
3245
3494
|
const path = prefix ? `${prefix}/${entry2.name}` : entry2.name;
|
|
@@ -3573,7 +3822,7 @@ async function requireLatestRuntime(root, options = {}) {
|
|
|
3573
3822
|
}
|
|
3574
3823
|
|
|
3575
3824
|
// packages/cli-core/src/dev/launch.ts
|
|
3576
|
-
import { lstatSync, readFileSync } from "node:fs";
|
|
3825
|
+
import { lstatSync, readFileSync as readFileSync2 } from "node:fs";
|
|
3577
3826
|
import { createRequire as createRequire3 } from "node:module";
|
|
3578
3827
|
import { dirname as dirname4, resolve as resolve11 } from "node:path";
|
|
3579
3828
|
|
|
@@ -3643,10 +3892,10 @@ async function officialAgentLaunchPlan(input) {
|
|
|
3643
3892
|
const packagePath = resolve11(input.projectRoot, BUDDY_PLATFORM_PACKAGE_JSON);
|
|
3644
3893
|
try {
|
|
3645
3894
|
await requireLatestRuntime(input.projectRoot, input.runtimeUpdate);
|
|
3646
|
-
const expected = runtimeDependencyVersion(JSON.parse(
|
|
3895
|
+
const expected = runtimeDependencyVersion(JSON.parse(readFileSync2(packagePath, "utf8")));
|
|
3647
3896
|
if (!expected) throw new Error(`package.json \u7684 dependencies \u5FC5\u987B\u58F0\u660E ${BUDDY_RUNTIME_PACKAGE} \u7684\u51C6\u786E\u7248\u672C`);
|
|
3648
3897
|
const runtimePath = createRequire3(packagePath).resolve(`${BUDDY_RUNTIME_PACKAGE}/package.json`);
|
|
3649
|
-
const installed2 = JSON.parse(
|
|
3898
|
+
const installed2 = JSON.parse(readFileSync2(runtimePath, "utf8")).version;
|
|
3650
3899
|
if (installed2 !== expected) throw new Error(`Runtime \u5DF2\u5B89\u88C5 ${installed2}\uFF0C\u5DE5\u7A0B\u8981\u6C42 ${expected}`);
|
|
3651
3900
|
await validateRuntimeDatasets(input.projectRoot, await readDataAccessRequirements(input.projectRoot));
|
|
3652
3901
|
} catch (cause) {
|
|
@@ -4148,7 +4397,7 @@ async function startBuddyDevProcess(options, hooks) {
|
|
|
4148
4397
|
client: options.registrationClient,
|
|
4149
4398
|
devAgentId,
|
|
4150
4399
|
configSource,
|
|
4151
|
-
configDigest: `sha256:${
|
|
4400
|
+
configDigest: `sha256:${createHash7("sha256").update(configSource).digest("hex")}`,
|
|
4152
4401
|
signal
|
|
4153
4402
|
});
|
|
4154
4403
|
secrets.push(registration.agentToken);
|
|
@@ -4267,10 +4516,10 @@ function createBuddyDevStarter(options = {}) {
|
|
|
4267
4516
|
}
|
|
4268
4517
|
|
|
4269
4518
|
// packages/cli-core/src/dev/token-store.ts
|
|
4270
|
-
import { createHash as
|
|
4519
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
4271
4520
|
|
|
4272
4521
|
// packages/cli-core/src/cloud/credential-store.ts
|
|
4273
|
-
import { spawn } from "node:child_process";
|
|
4522
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
4274
4523
|
var DEFAULT_SERVICE = "com.xiaohongshu.buddy.developer-cli";
|
|
4275
4524
|
var DEFAULT_ACCOUNT = "developer-session";
|
|
4276
4525
|
var MAX_CREDENTIAL_BYTES = 32 * 1024;
|
|
@@ -4313,7 +4562,7 @@ function parse(source) {
|
|
|
4313
4562
|
}
|
|
4314
4563
|
async function runCredentialCommand(input) {
|
|
4315
4564
|
return await new Promise((resolve19, reject) => {
|
|
4316
|
-
const child =
|
|
4565
|
+
const child = spawn2(input.command, [...input.args], {
|
|
4317
4566
|
shell: false,
|
|
4318
4567
|
windowsHide: true,
|
|
4319
4568
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4411,7 +4660,7 @@ var SystemBuddyTokenStore = class {
|
|
|
4411
4660
|
const scope = JSON.stringify([normalizePlatformUrl(options.platformUrl).origin, options.subject, options.buddyId]);
|
|
4412
4661
|
this.#store = new SystemCredentialStore({
|
|
4413
4662
|
service: "com.xiaohongshu.buddy.developer-cli.dev-token",
|
|
4414
|
-
account:
|
|
4663
|
+
account: createHash8("sha256").update(scope).digest("hex"),
|
|
4415
4664
|
platform: options.platform,
|
|
4416
4665
|
commandRunner: options.commandRunner
|
|
4417
4666
|
});
|
|
@@ -5050,251 +5299,6 @@ var HttpDeveloperPlatformClient = class {
|
|
|
5050
5299
|
}
|
|
5051
5300
|
};
|
|
5052
5301
|
|
|
5053
|
-
// packages/cli-core/src/cloud/browser-login.ts
|
|
5054
|
-
import { createHash as createHash8, randomBytes } from "node:crypto";
|
|
5055
|
-
import { spawn as spawn2 } from "node:child_process";
|
|
5056
|
-
import { createServer } from "node:http";
|
|
5057
|
-
|
|
5058
|
-
// packages/cli-core/src/cloud/login-result.ts
|
|
5059
|
-
import { readFileSync as readFileSync2 } from "node:fs";
|
|
5060
|
-
var brand = new URL("../../resources/brand/", import.meta.url);
|
|
5061
|
-
var tokens = readFileSync2(new URL("tokens.css", brand), "utf8");
|
|
5062
|
-
var styles = readFileSync2(new URL("login-result.css", brand), "utf8");
|
|
5063
|
-
var logo = readFileSync2(new URL("logo.png", brand)).toString("base64");
|
|
5064
|
-
function escapeHtml(value) {
|
|
5065
|
-
return value.replace(/[&<>"']/gu, (character) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[character]);
|
|
5066
|
-
}
|
|
5067
|
-
function renderLoginResult(title, message, webUrl, tone) {
|
|
5068
|
-
const label = { success: "\u5DF2\u6388\u6743", neutral: "\u5DF2\u53D6\u6D88", error: "\u672A\u5B8C\u6210" }[tone];
|
|
5069
|
-
return `<!doctype html>
|
|
5070
|
-
<html lang="zh-CN"><head>
|
|
5071
|
-
<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
5072
|
-
<meta name="color-scheme" content="light dark"><title>${escapeHtml(title)} \xB7 \u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0</title>
|
|
5073
|
-
<style>${tokens}
|
|
5074
|
-
${styles}</style></head>
|
|
5075
|
-
<body><div class="result-shell">
|
|
5076
|
-
<header class="result-brand"><img src="data:image/png;base64,${logo}" alt="" width="44" height="44"><span>\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0</span></header>
|
|
5077
|
-
<main class="result-card" aria-labelledby="result-title">
|
|
5078
|
-
<div class="result-heading"><p class="result-eyebrow">buddy-cli \u767B\u5F55</p><span class="result-status" data-tone="${tone}">${label}</span></div>
|
|
5079
|
-
<h1 id="result-title">${escapeHtml(title)}</h1>
|
|
5080
|
-
<p class="result-message">${escapeHtml(message)}</p>
|
|
5081
|
-
<div class="result-next"><strong>${tone === "success" ? "\u56DE\u5230\u7EC8\u7AEF\uFF0C\u7EE7\u7EED\u521B\u4F5C" : "\u56DE\u5230\u7EC8\u7AEF\uFF0C\u91CD\u65B0\u5F00\u59CB"}</strong>
|
|
5082
|
-
<p>${tone === "success" ? "\u67E5\u770B CLI \u7684\u767B\u5F55\u7ED3\u679C\uFF0C\u7EE7\u7EED\u521B\u5EFA\u3001\u5F00\u53D1\u548C\u9884\u89C8\u4F60\u7684\u642D\u5B50\u3002" : "\u9700\u8981\u7EE7\u7EED\u65F6\uFF0C\u5728\u7EC8\u7AEF\u91CD\u65B0\u8FD0\u884C\u767B\u5F55\u547D\u4EE4\u3002"}</p>
|
|
5083
|
-
${tone === "success" ? "" : "<code>buddy-cli login</code>"}</div>
|
|
5084
|
-
<a class="result-link" href="${escapeHtml(webUrl.href)}">\u8FD4\u56DE\u5F00\u653E\u5E73\u53F0</a>
|
|
5085
|
-
</main><footer>\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0</footer></div></body></html>`;
|
|
5086
|
-
}
|
|
5087
|
-
|
|
5088
|
-
// packages/cli-core/src/cloud/browser-login.ts
|
|
5089
|
-
var DEFAULT_LOGIN_TIMEOUT_MS = 5 * 6e4;
|
|
5090
|
-
var DEFAULT_EXCHANGE_TIMEOUT_MS = 15e3;
|
|
5091
|
-
var DEFAULT_DEVELOPER_WEB_URL = "https://47.116.168.81/developer/";
|
|
5092
|
-
var REQUEST_ID = /^[A-Za-z0-9_-]{43}$/u;
|
|
5093
|
-
var AUTH_CODE = /^[A-Za-z0-9_-]{43}$/u;
|
|
5094
|
-
function positive(value, fallback, name) {
|
|
5095
|
-
const result = value ?? fallback;
|
|
5096
|
-
if (!Number.isSafeInteger(result) || result <= 0) throw new TypeError(`${name} must be a positive safe integer`);
|
|
5097
|
-
return result;
|
|
5098
|
-
}
|
|
5099
|
-
function webBase(value) {
|
|
5100
|
-
const url = new URL(value);
|
|
5101
|
-
const loopback = ["localhost", "127.0.0.1", "[::1]", "::1"].includes(url.hostname);
|
|
5102
|
-
if (url.protocol !== "https:" && !(url.protocol === "http:" && loopback) || url.username || url.password || url.search || url.hash) {
|
|
5103
|
-
throw new CloudLifecycleError("INVALID_REQUEST", "\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u5FC5\u987B\u4F7F\u7528 HTTPS\uFF1B\u672C\u673A\u5F00\u53D1\u53EF\u4EE5\u4F7F\u7528 loopback HTTP");
|
|
5104
|
-
}
|
|
5105
|
-
if (!url.pathname.endsWith("/")) url.pathname += "/";
|
|
5106
|
-
return url;
|
|
5107
|
-
}
|
|
5108
|
-
function browserCommand(url) {
|
|
5109
|
-
if (process.platform === "darwin") return { command: "open", args: [url.href] };
|
|
5110
|
-
throw new CloudLifecycleError("INVALID_REQUEST", "\u642D\u642D CLI V1 \u672C\u5730\u767B\u5F55\u76EE\u524D\u53EA\u652F\u6301 macOS");
|
|
5111
|
-
}
|
|
5112
|
-
async function openExternalUrl(url) {
|
|
5113
|
-
const launch = browserCommand(url);
|
|
5114
|
-
await new Promise((resolve19, reject) => {
|
|
5115
|
-
const child = spawn2(launch.command, launch.args, { shell: false, stdio: "ignore", windowsHide: true });
|
|
5116
|
-
child.once("error", reject);
|
|
5117
|
-
child.once("exit", (code2) => code2 === 0 ? resolve19() : reject(new Error(`browser launcher exited with ${code2 ?? "unknown"}`)));
|
|
5118
|
-
});
|
|
5119
|
-
}
|
|
5120
|
-
async function write(res, status, title, message, webUrl, tone = "error") {
|
|
5121
|
-
res.writeHead(status, {
|
|
5122
|
-
"cache-control": "no-store",
|
|
5123
|
-
"connection": "close",
|
|
5124
|
-
"content-security-policy": "default-src 'none'; img-src data:; style-src 'unsafe-inline'; frame-ancestors 'none'; base-uri 'none'",
|
|
5125
|
-
"content-type": "text/html; charset=utf-8",
|
|
5126
|
-
"referrer-policy": "no-referrer",
|
|
5127
|
-
"x-content-type-options": "nosniff"
|
|
5128
|
-
});
|
|
5129
|
-
await new Promise((resolve19, reject) => {
|
|
5130
|
-
res.once("error", reject);
|
|
5131
|
-
res.once("close", resolve19);
|
|
5132
|
-
res.end(renderLoginResult(title, message, webUrl, tone), resolve19);
|
|
5133
|
-
});
|
|
5134
|
-
}
|
|
5135
|
-
async function readJson(response) {
|
|
5136
|
-
const value = await response.json().catch(() => void 0);
|
|
5137
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5138
|
-
throw new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", "\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u6388\u6743\u7ED3\u679C");
|
|
5139
|
-
}
|
|
5140
|
-
return value;
|
|
5141
|
-
}
|
|
5142
|
-
var LoopbackBrowserLoginAdapter = class {
|
|
5143
|
-
#platformUrl;
|
|
5144
|
-
#developerWebUrl;
|
|
5145
|
-
#openBrowser;
|
|
5146
|
-
#onLoginUrl;
|
|
5147
|
-
#timeoutMs;
|
|
5148
|
-
#fetch;
|
|
5149
|
-
constructor(options) {
|
|
5150
|
-
this.#platformUrl = normalizePlatformUrl(options.platformUrl);
|
|
5151
|
-
this.#developerWebUrl = webBase(options.developerWebUrl ?? DEFAULT_DEVELOPER_WEB_URL);
|
|
5152
|
-
this.#openBrowser = options.openBrowser ?? openExternalUrl;
|
|
5153
|
-
this.#onLoginUrl = options.onLoginUrl;
|
|
5154
|
-
this.#timeoutMs = positive(options.timeoutMs, DEFAULT_LOGIN_TIMEOUT_MS, "timeoutMs");
|
|
5155
|
-
this.#fetch = options.fetch ?? globalThis.fetch;
|
|
5156
|
-
if (typeof this.#fetch !== "function") throw new TypeError("A Fetch API implementation is required");
|
|
5157
|
-
}
|
|
5158
|
-
async login(request) {
|
|
5159
|
-
if (request.signal?.aborted) throw request.signal.reason;
|
|
5160
|
-
const callbackSecret = randomBytes(24).toString("hex");
|
|
5161
|
-
const codeVerifier = randomBytes(32).toString("base64url");
|
|
5162
|
-
const codeChallenge = createHash8("sha256").update(codeVerifier).digest("base64url");
|
|
5163
|
-
let requestId = "";
|
|
5164
|
-
let settle;
|
|
5165
|
-
let reject;
|
|
5166
|
-
let settled = false;
|
|
5167
|
-
const result = new Promise((resolve19, rejectResult) => {
|
|
5168
|
-
settle = (value) => {
|
|
5169
|
-
if (!settled) {
|
|
5170
|
-
settled = true;
|
|
5171
|
-
resolve19(value);
|
|
5172
|
-
}
|
|
5173
|
-
};
|
|
5174
|
-
reject = (reason) => {
|
|
5175
|
-
if (!settled) {
|
|
5176
|
-
settled = true;
|
|
5177
|
-
rejectResult(reason);
|
|
5178
|
-
}
|
|
5179
|
-
};
|
|
5180
|
-
});
|
|
5181
|
-
void result.catch(() => void 0);
|
|
5182
|
-
const server = createServer((req, res) => {
|
|
5183
|
-
void this.#receiveCallback(req, res, {
|
|
5184
|
-
callbackSecret,
|
|
5185
|
-
codeVerifier,
|
|
5186
|
-
requestId,
|
|
5187
|
-
state: request.state
|
|
5188
|
-
}).then(settle, reject);
|
|
5189
|
-
});
|
|
5190
|
-
await new Promise((resolve19, rejectListen) => {
|
|
5191
|
-
server.once("error", rejectListen);
|
|
5192
|
-
server.listen(0, "127.0.0.1", () => resolve19());
|
|
5193
|
-
});
|
|
5194
|
-
const address = server.address();
|
|
5195
|
-
if (!address || typeof address === "string") {
|
|
5196
|
-
server.close();
|
|
5197
|
-
throw new CloudLifecycleError("PLATFORM_UNAVAILABLE", "\u65E0\u6CD5\u542F\u52A8\u672C\u673A\u767B\u5F55\u56DE\u8C03");
|
|
5198
|
-
}
|
|
5199
|
-
const redirectUri = `http://127.0.0.1:${address.port}/callback/${callbackSecret}`;
|
|
5200
|
-
const timer = setTimeout(() => reject(new CloudLifecycleError("AUTH_LOGIN_CANCELLED", "\u6D4F\u89C8\u5668\u767B\u5F55\u7B49\u5F85\u8D85\u65F6\uFF0C\u8BF7\u91CD\u8BD5")), this.#timeoutMs);
|
|
5201
|
-
timer.unref?.();
|
|
5202
|
-
const abort = () => reject(request.signal?.reason ?? new CloudLifecycleError("AUTH_LOGIN_CANCELLED", "\u767B\u5F55\u5DF2\u53D6\u6D88"));
|
|
5203
|
-
request.signal?.addEventListener("abort", abort, { once: true });
|
|
5204
|
-
try {
|
|
5205
|
-
const created = await this.#post("api/cli/authorizations", {
|
|
5206
|
-
state: request.state,
|
|
5207
|
-
codeChallenge,
|
|
5208
|
-
redirectUri,
|
|
5209
|
-
platformOrigin: this.#platformUrl.origin
|
|
5210
|
-
}, request.signal);
|
|
5211
|
-
if (typeof created.requestId !== "string" || !REQUEST_ID.test(created.requestId)) {
|
|
5212
|
-
throw new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", "\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u6388\u6743\u7F16\u53F7");
|
|
5213
|
-
}
|
|
5214
|
-
requestId = created.requestId;
|
|
5215
|
-
const loginUrl = new URL(this.#developerWebUrl);
|
|
5216
|
-
loginUrl.hash = `#/cli-authorize?requestId=${encodeURIComponent(requestId)}`;
|
|
5217
|
-
this.#onLoginUrl?.(loginUrl);
|
|
5218
|
-
await this.#openBrowser(loginUrl).catch(() => {
|
|
5219
|
-
throw new CloudLifecycleError("PLATFORM_UNAVAILABLE", "\u65E0\u6CD5\u81EA\u52A8\u6253\u5F00\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\uFF0C\u8BF7\u68C0\u67E5\u7CFB\u7EDF\u9ED8\u8BA4\u6D4F\u89C8\u5668\u540E\u91CD\u8BD5");
|
|
5220
|
-
});
|
|
5221
|
-
return await result;
|
|
5222
|
-
} finally {
|
|
5223
|
-
clearTimeout(timer);
|
|
5224
|
-
request.signal?.removeEventListener("abort", abort);
|
|
5225
|
-
await new Promise((resolve19) => {
|
|
5226
|
-
server.close(() => resolve19());
|
|
5227
|
-
server.closeIdleConnections();
|
|
5228
|
-
server.closeAllConnections();
|
|
5229
|
-
});
|
|
5230
|
-
}
|
|
5231
|
-
}
|
|
5232
|
-
async #receiveCallback(req, res, expected) {
|
|
5233
|
-
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
5234
|
-
if (req.method !== "GET" || url.pathname !== `/callback/${expected.callbackSecret}`) {
|
|
5235
|
-
await write(res, 404, "\u9875\u9762\u4E0D\u5B58\u5728", "\u8BF7\u56DE\u5230\u7EC8\u7AEF\u91CD\u65B0\u53D1\u8D77\u767B\u5F55\u3002", this.#developerWebUrl);
|
|
5236
|
-
throw new CloudLifecycleError("AUTH_LOGIN_CANCELLED", "\u6D4F\u89C8\u5668\u56DE\u8C03\u65E0\u6548\uFF0C\u8BF7\u91CD\u8BD5");
|
|
5237
|
-
}
|
|
5238
|
-
if (url.searchParams.get("state") !== expected.state) {
|
|
5239
|
-
await write(res, 400, "\u767B\u5F55\u6CA1\u6709\u5B8C\u6210", "\u6388\u6743\u6821\u9A8C\u5931\u8D25\uFF0C\u8BF7\u56DE\u5230\u7EC8\u7AEF\u91CD\u8BD5\u3002", this.#developerWebUrl);
|
|
5240
|
-
throw new CloudLifecycleError("AUTH_STATE_MISMATCH", "\u6D4F\u89C8\u5668\u767B\u5F55\u8FD4\u56DE\u7684 state \u4E0D\u5339\u914D\uFF1B\u51ED\u636E\u672A\u4FDD\u5B58");
|
|
5241
|
-
}
|
|
5242
|
-
if (url.searchParams.get("error") === "access_denied") {
|
|
5243
|
-
await write(res, 200, "\u5DF2\u53D6\u6D88\u6388\u6743", "\u6CA1\u6709\u5411 buddy-cli \u63D0\u4F9B\u8D26\u53F7\u6743\u9650\uFF0C\u53EF\u4EE5\u5173\u95ED\u8FD9\u4E2A\u9875\u9762\u3002", this.#developerWebUrl, "neutral");
|
|
5244
|
-
throw new CloudLifecycleError("AUTH_LOGIN_CANCELLED", "\u7528\u6237\u53D6\u6D88\u4E86 CLI \u6388\u6743");
|
|
5245
|
-
}
|
|
5246
|
-
const code2 = url.searchParams.get("code");
|
|
5247
|
-
if (!code2 || !AUTH_CODE.test(code2) || !expected.requestId) {
|
|
5248
|
-
await write(res, 400, "\u767B\u5F55\u6CA1\u6709\u5B8C\u6210", "\u6388\u6743\u7ED3\u679C\u65E0\u6548\uFF0C\u8BF7\u56DE\u5230\u7EC8\u7AEF\u91CD\u8BD5\u3002", this.#developerWebUrl);
|
|
5249
|
-
throw new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", "\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u8FD4\u56DE\u4E86\u65E0\u6548\u6388\u6743\u7801");
|
|
5250
|
-
}
|
|
5251
|
-
try {
|
|
5252
|
-
const exchanged = await this.#post("api/cli/exchange", {
|
|
5253
|
-
requestId: expected.requestId,
|
|
5254
|
-
code: code2,
|
|
5255
|
-
codeVerifier: expected.codeVerifier
|
|
5256
|
-
});
|
|
5257
|
-
if (exchanged.platformOrigin !== this.#platformUrl.origin || typeof exchanged.token !== "string" || typeof exchanged.userId !== "string" || !Number.isSafeInteger(exchanged.expiresAt)) {
|
|
5258
|
-
throw new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", "\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u8FD4\u56DE\u7684\u8D26\u53F7\u51ED\u636E\u4E0D\u5B8C\u6574");
|
|
5259
|
-
}
|
|
5260
|
-
await write(res, 200, "\u767B\u5F55\u6210\u529F", "buddy-cli \u5DF2\u83B7\u5F97\u6388\u6743\uFF0C\u53EF\u4EE5\u5173\u95ED\u8FD9\u4E2A\u9875\u9762\u5E76\u8FD4\u56DE\u7EC8\u7AEF\u3002", this.#developerWebUrl, "success");
|
|
5261
|
-
return {
|
|
5262
|
-
state: expected.state,
|
|
5263
|
-
token: {
|
|
5264
|
-
accessToken: exchanged.token,
|
|
5265
|
-
subject: exchanged.userId,
|
|
5266
|
-
expiresAt: exchanged.expiresAt
|
|
5267
|
-
}
|
|
5268
|
-
};
|
|
5269
|
-
} catch (error2) {
|
|
5270
|
-
await write(res, 502, "\u767B\u5F55\u6CA1\u6709\u5B8C\u6210", "\u6388\u6743\u4EA4\u6362\u5931\u8D25\uFF0C\u8BF7\u56DE\u5230\u7EC8\u7AEF\u91CD\u8BD5\u3002", this.#developerWebUrl);
|
|
5271
|
-
throw error2;
|
|
5272
|
-
}
|
|
5273
|
-
}
|
|
5274
|
-
async #post(path, payload, signal) {
|
|
5275
|
-
let response;
|
|
5276
|
-
try {
|
|
5277
|
-
const signals = [AbortSignal.timeout(DEFAULT_EXCHANGE_TIMEOUT_MS), ...signal ? [signal] : []];
|
|
5278
|
-
response = await this.#fetch(new URL(path, this.#developerWebUrl), {
|
|
5279
|
-
method: "POST",
|
|
5280
|
-
headers: { Accept: "application/json", "Content-Type": "application/json" },
|
|
5281
|
-
body: JSON.stringify(payload),
|
|
5282
|
-
redirect: "error",
|
|
5283
|
-
signal: AbortSignal.any(signals)
|
|
5284
|
-
});
|
|
5285
|
-
} catch {
|
|
5286
|
-
if (signal?.aborted) throw signal.reason;
|
|
5287
|
-
throw new CloudLifecycleError("PLATFORM_UNAVAILABLE", "\u65E0\u6CD5\u8FDE\u63A5\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u5B8C\u6210 CLI \u767B\u5F55");
|
|
5288
|
-
}
|
|
5289
|
-
const data = await readJson(response);
|
|
5290
|
-
if (!response.ok) {
|
|
5291
|
-
const message = typeof data.error === "string" ? data.error : "\u642D\u642D\u521B\u4F5C\u8005\u5E73\u53F0\u62D2\u7EDD\u4E86\u8FD9\u6B21 CLI \u6388\u6743";
|
|
5292
|
-
throw new CloudLifecycleError(response.status === 400 || response.status === 409 || response.status === 410 ? "AUTH_LOGIN_CANCELLED" : "PLATFORM_UNAVAILABLE", message);
|
|
5293
|
-
}
|
|
5294
|
-
return data;
|
|
5295
|
-
}
|
|
5296
|
-
};
|
|
5297
|
-
|
|
5298
5302
|
// packages/cli-core/src/cloud/mock-client.ts
|
|
5299
5303
|
import { createHash as createHash9, randomBytes as randomBytes2 } from "node:crypto";
|
|
5300
5304
|
var MockDeveloperPlatformClient = class {
|
|
@@ -7865,6 +7869,7 @@ export {
|
|
|
7865
7869
|
CloudAuthenticator,
|
|
7866
7870
|
CloudCommandUsageError,
|
|
7867
7871
|
CloudLifecycleError,
|
|
7872
|
+
DEFAULT_DEVELOPER_WEB_URL,
|
|
7868
7873
|
DEFAULT_MLB_TEST_URL,
|
|
7869
7874
|
DEFAULT_PUSH_MANIFEST_LIMITS,
|
|
7870
7875
|
DEFAULT_SKILL_SCAN_LIMITS,
|