jd-skills 0.1.1 → 0.1.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/dist/_chunks/libs/@clack/core.mjs +1 -1
- package/dist/_chunks/libs/@clack/prompts.mjs +1 -1
- package/dist/_chunks/libs/@kwsites/file-exists.mjs +1 -1
- package/dist/_chunks/libs/@vercel/detect-agent.mjs +1 -1
- package/dist/_chunks/libs/simple-git.mjs +1 -1
- package/dist/_chunks/rolldown-runtime.mjs +10 -1
- package/dist/cli.mjs +471 -86
- package/package.json +2 -1
- package/dist/_chunks/config.mjs +0 -158
- package/dist/_chunks/config2.mjs +0 -2
- package/dist/_chunks/jd-cookie.mjs +0 -3
- package/dist/_chunks/jd-cookie2.mjs +0 -112
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as __toESM, t as __commonJSMin } from "../../rolldown-runtime.mjs";
|
|
2
2
|
import { stdin, stdout } from "node:process";
|
|
3
3
|
import * as g from "node:readline";
|
|
4
4
|
import O from "node:readline";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as __toESM } from "../../rolldown-runtime.mjs";
|
|
2
2
|
import { a as SD, c as fD, d as require_src, i as RD, l as pD, n as LD, o as _D, r as MD, s as dD, t as ID, u as require_picocolors } from "./core.mjs";
|
|
3
3
|
import { stripVTControlCharacters } from "node:util";
|
|
4
4
|
import y from "node:process";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { r as __require, t as __commonJSMin } from "../../rolldown-runtime.mjs";
|
|
2
2
|
var require_dist = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as __toESM } from "../rolldown-runtime.mjs";
|
|
2
2
|
import { n as require_src, t as require_dist } from "./@kwsites/file-exists.mjs";
|
|
3
3
|
import { t as require_dist$1 } from "./@kwsites/promise-deferred.mjs";
|
|
4
4
|
import { spawn } from "child_process";
|
|
@@ -6,6 +6,15 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
8
|
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
9
|
+
var __exportAll = (all, symbols) => {
|
|
10
|
+
let target = {};
|
|
11
|
+
for (var name in all) __defProp(target, name, {
|
|
12
|
+
get: all[name],
|
|
13
|
+
enumerable: true
|
|
14
|
+
});
|
|
15
|
+
if (symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
16
|
+
return target;
|
|
17
|
+
};
|
|
9
18
|
var __copyProps = (to, from, except, desc) => {
|
|
10
19
|
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
20
|
key = keys[i];
|
|
@@ -21,4 +30,4 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
30
|
enumerable: true
|
|
22
31
|
}) : target, mod));
|
|
23
32
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
24
|
-
export {
|
|
33
|
+
export { __toESM as i, __exportAll as n, __require as r, __commonJSMin as t };
|
package/dist/cli.mjs
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { i as __toESM, n as __exportAll } from "./_chunks/rolldown-runtime.mjs";
|
|
3
3
|
import { l as pD, u as require_picocolors } from "./_chunks/libs/@clack/core.mjs";
|
|
4
4
|
import { a as Y, c as ve, i as Se, l as xe, n as M, o as be, r as Me, s as fe, t as Ie, u as ye } from "./_chunks/libs/@clack/prompts.mjs";
|
|
5
|
-
import { a as JD_INTRANET_DEFAULTS, c as resolveExpectedNpmRegistry, f as resolveSkillApiUrl, i as setBrokerUrl, l as resolveGitlabHosts, n as getConfig, o as isJdIntranetAvailable, p as resolveSkillApiUrlSync, r as resetConfig, s as probeJdIntranet, t as getBrokerUrl } from "./_chunks/config.mjs";
|
|
6
5
|
import "./_chunks/libs/@kwsites/file-exists.mjs";
|
|
7
6
|
import "./_chunks/libs/@kwsites/promise-deferred.mjs";
|
|
8
7
|
import { t as esm_default } from "./_chunks/libs/simple-git.mjs";
|
|
9
8
|
import { t as xdgConfig } from "./_chunks/libs/xdg-basedir.mjs";
|
|
10
9
|
import { t as require_dist } from "./_chunks/libs/@vercel/detect-agent.mjs";
|
|
11
|
-
import { a as getSdkPackageName, c as isBrokerSdkAvailable, i as getJdSourcePromptState, n as getCookieStatus, o as installSdkHint, r as getJdCookie, t as clearJdCookie } from "./_chunks/jd-cookie2.mjs";
|
|
12
10
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "fs";
|
|
13
11
|
import { execFile, execSync, spawn, spawnSync } from "child_process";
|
|
14
12
|
import { basename, dirname, isAbsolute, join, normalize, relative, resolve, sep } from "path";
|
|
@@ -24,6 +22,118 @@ import { createHash } from "crypto";
|
|
|
24
22
|
import { createHash as createHash$1 } from "node:crypto";
|
|
25
23
|
import { gunzipSync, inflateRawSync } from "node:zlib";
|
|
26
24
|
var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
25
|
+
const JD_INTRANET_DEFAULTS = {
|
|
26
|
+
skillApiUrl: "https://mkt-skill-manager.jd.com/api/skill/public/sorted-list",
|
|
27
|
+
brokerUrl: "https://cbroker.jd.com",
|
|
28
|
+
sdkPackage: "@jd/jd-cookie-broker",
|
|
29
|
+
gitlabHosts: ["coding.jd.com"],
|
|
30
|
+
npmRegistry: "http://registry.m.jd.com"
|
|
31
|
+
};
|
|
32
|
+
const PROBE_CACHE_PATH = join(homedir(), ".jd-skills", "intranet-probe.json");
|
|
33
|
+
const PROBE_TTL_MS = 3600 * 1e3;
|
|
34
|
+
const PROBE_NEGATIVE_TTL_MS = 300 * 1e3;
|
|
35
|
+
const PROBE_TIMEOUT_MS = 5e3;
|
|
36
|
+
let memoryProbe = null;
|
|
37
|
+
let inFlightProbe = null;
|
|
38
|
+
function readDiskProbe() {
|
|
39
|
+
try {
|
|
40
|
+
if (!existsSync(PROBE_CACHE_PATH)) return null;
|
|
41
|
+
const parsed = JSON.parse(readFileSync(PROBE_CACHE_PATH, "utf-8"));
|
|
42
|
+
if (typeof parsed.available !== "boolean" || typeof parsed.checkedAt !== "number") return null;
|
|
43
|
+
if (Date.now() - parsed.checkedAt > (parsed.available ? PROBE_TTL_MS : PROBE_NEGATIVE_TTL_MS)) return null;
|
|
44
|
+
return parsed;
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function writeDiskProbe(available) {
|
|
50
|
+
try {
|
|
51
|
+
mkdirSync(dirname(PROBE_CACHE_PATH), { recursive: true });
|
|
52
|
+
writeFileSync(PROBE_CACHE_PATH, JSON.stringify({
|
|
53
|
+
available,
|
|
54
|
+
checkedAt: Date.now()
|
|
55
|
+
}, null, 2), { mode: 384 });
|
|
56
|
+
} catch {}
|
|
57
|
+
}
|
|
58
|
+
function setProbeResult(available) {
|
|
59
|
+
memoryProbe = available;
|
|
60
|
+
writeDiskProbe(available);
|
|
61
|
+
return available;
|
|
62
|
+
}
|
|
63
|
+
function getJdIntranetProbeSync() {
|
|
64
|
+
if (memoryProbe !== null) return memoryProbe;
|
|
65
|
+
const cached = readDiskProbe();
|
|
66
|
+
if (!cached) return null;
|
|
67
|
+
memoryProbe = cached.available;
|
|
68
|
+
return cached.available;
|
|
69
|
+
}
|
|
70
|
+
async function urlReachable(url, method) {
|
|
71
|
+
try {
|
|
72
|
+
return (await fetch(url, {
|
|
73
|
+
method,
|
|
74
|
+
signal: AbortSignal.timeout(PROBE_TIMEOUT_MS)
|
|
75
|
+
})).status < 500;
|
|
76
|
+
} catch {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function probeMarketplaceReachable(apiUrl) {
|
|
81
|
+
if (await urlReachable(apiUrl, "HEAD")) return true;
|
|
82
|
+
if (await urlReachable(apiUrl, "GET")) return true;
|
|
83
|
+
if (await urlReachable(JD_INTRANET_DEFAULTS.brokerUrl, "HEAD")) return true;
|
|
84
|
+
try {
|
|
85
|
+
const origin = new URL(apiUrl).origin;
|
|
86
|
+
if (await urlReachable(origin, "HEAD")) return true;
|
|
87
|
+
} catch {}
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
async function probeJdIntranet(force = false) {
|
|
91
|
+
if (!force && memoryProbe !== null) return memoryProbe;
|
|
92
|
+
if (!force) {
|
|
93
|
+
const cached = readDiskProbe();
|
|
94
|
+
if (cached) {
|
|
95
|
+
memoryProbe = cached.available;
|
|
96
|
+
return cached.available;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (!force && inFlightProbe) return inFlightProbe;
|
|
100
|
+
inFlightProbe = (async () => {
|
|
101
|
+
return setProbeResult(await probeMarketplaceReachable((process.env.JD_SKILL_API_URL ?? "").trim() || JD_INTRANET_DEFAULTS.skillApiUrl));
|
|
102
|
+
})();
|
|
103
|
+
try {
|
|
104
|
+
return await inFlightProbe;
|
|
105
|
+
} finally {
|
|
106
|
+
inFlightProbe = null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function isJdIntranetAvailable() {
|
|
110
|
+
return getJdIntranetProbeSync() === true;
|
|
111
|
+
}
|
|
112
|
+
async function resolveSkillApiUrl() {
|
|
113
|
+
const env = (process.env.JD_SKILL_API_URL ?? "").trim();
|
|
114
|
+
if (env) return env;
|
|
115
|
+
if (await probeJdIntranet()) return JD_INTRANET_DEFAULTS.skillApiUrl;
|
|
116
|
+
return "";
|
|
117
|
+
}
|
|
118
|
+
function resolveSkillApiUrlSync() {
|
|
119
|
+
const env = (process.env.JD_SKILL_API_URL ?? "").trim();
|
|
120
|
+
if (env) return env;
|
|
121
|
+
if (isJdIntranetAvailable()) return JD_INTRANET_DEFAULTS.skillApiUrl;
|
|
122
|
+
return "";
|
|
123
|
+
}
|
|
124
|
+
function resolveBrokerUrlFromIntranet(fileBrokerUrl) {
|
|
125
|
+
const envUrl = (process.env.JD_BROKER_URL ?? "").trim();
|
|
126
|
+
if (envUrl) return envUrl.replace(/\/+$/, "");
|
|
127
|
+
if (fileBrokerUrl) return fileBrokerUrl;
|
|
128
|
+
if (isJdIntranetAvailable()) return JD_INTRANET_DEFAULTS.brokerUrl;
|
|
129
|
+
return "";
|
|
130
|
+
}
|
|
131
|
+
function resolveGitlabHosts() {
|
|
132
|
+
const fromEnv = (process.env.JD_GITLAB_HOSTS ?? "").split(",").map((h) => h.trim().toLowerCase()).filter((h) => h.length > 0).filter((h, i, arr) => arr.indexOf(h) === i);
|
|
133
|
+
if (fromEnv.length > 0) return fromEnv;
|
|
134
|
+
if (isJdIntranetAvailable()) return [...JD_INTRANET_DEFAULTS.gitlabHosts];
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
27
137
|
function getInternalGitlabHosts() {
|
|
28
138
|
return resolveGitlabHosts();
|
|
29
139
|
}
|
|
@@ -3046,7 +3156,7 @@ async function tryBlobInstall(ownerRepo, options = {}) {
|
|
|
3046
3156
|
tree
|
|
3047
3157
|
};
|
|
3048
3158
|
}
|
|
3049
|
-
var version$1 = "0.1.
|
|
3159
|
+
var version$1 = "0.1.3";
|
|
3050
3160
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
3051
3161
|
async function isSourcePrivate(source) {
|
|
3052
3162
|
const ownerRepo = parseOwnerRepo(source);
|
|
@@ -4162,6 +4272,190 @@ function parseAddOptions(args) {
|
|
|
4162
4272
|
options
|
|
4163
4273
|
};
|
|
4164
4274
|
}
|
|
4275
|
+
const CONFIG_PATH = join(join(homedir(), ".jd-skills"), "config.json");
|
|
4276
|
+
function readConfig() {
|
|
4277
|
+
try {
|
|
4278
|
+
if (!existsSync(CONFIG_PATH)) return {};
|
|
4279
|
+
const raw = readFileSync(CONFIG_PATH, "utf-8");
|
|
4280
|
+
const parsed = JSON.parse(raw);
|
|
4281
|
+
if (typeof parsed !== "object" || parsed === null) return {};
|
|
4282
|
+
return parsed;
|
|
4283
|
+
} catch {
|
|
4284
|
+
return {};
|
|
4285
|
+
}
|
|
4286
|
+
}
|
|
4287
|
+
function writeConfig(config) {
|
|
4288
|
+
mkdirSync(dirname(CONFIG_PATH), { recursive: true });
|
|
4289
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 384 });
|
|
4290
|
+
}
|
|
4291
|
+
function getBrokerUrl() {
|
|
4292
|
+
const fileConfig = readConfig();
|
|
4293
|
+
return resolveBrokerUrlFromIntranet(fileConfig.brokerUrl && fileConfig.brokerUrl.trim().length > 0 ? fileConfig.brokerUrl.trim().replace(/\/+$/, "") : "");
|
|
4294
|
+
}
|
|
4295
|
+
function setBrokerUrl(url) {
|
|
4296
|
+
const config = readConfig();
|
|
4297
|
+
if (url && url.trim().length > 0) config.brokerUrl = url.trim().replace(/\/+$/, "");
|
|
4298
|
+
else delete config.brokerUrl;
|
|
4299
|
+
config.version = 1;
|
|
4300
|
+
writeConfig(config);
|
|
4301
|
+
}
|
|
4302
|
+
function resetConfig() {
|
|
4303
|
+
try {
|
|
4304
|
+
if (existsSync(CONFIG_PATH)) writeFileSync(CONFIG_PATH, "{}", { mode: 384 });
|
|
4305
|
+
} catch {}
|
|
4306
|
+
}
|
|
4307
|
+
function getConfig() {
|
|
4308
|
+
return readConfig();
|
|
4309
|
+
}
|
|
4310
|
+
const DEFAULT_BROKER_URL = "https://cbroker.jd.com";
|
|
4311
|
+
function normUrl(url) {
|
|
4312
|
+
return String(url || DEFAULT_BROKER_URL).replace(/\/+$/, "");
|
|
4313
|
+
}
|
|
4314
|
+
async function httpJson(url, init = {}) {
|
|
4315
|
+
const response = await fetch(url, init);
|
|
4316
|
+
const payload = (response.headers.get("content-type") || "").includes("application/json") ? await response.json() : await response.text();
|
|
4317
|
+
if (!response.ok) {
|
|
4318
|
+
const message = typeof payload === "string" ? payload : payload.message || JSON.stringify(payload);
|
|
4319
|
+
throw new Error(`HTTP ${response.status}: ${message}`);
|
|
4320
|
+
}
|
|
4321
|
+
return payload;
|
|
4322
|
+
}
|
|
4323
|
+
async function createSession({ brokerUrl, appId } = {}) {
|
|
4324
|
+
const base = normUrl(brokerUrl);
|
|
4325
|
+
const id = appId || `jd-skills-${Date.now()}`;
|
|
4326
|
+
return httpJson(`${base}/v1/sessions/create?appId=${encodeURIComponent(id)}`);
|
|
4327
|
+
}
|
|
4328
|
+
async function getSession({ brokerUrl, sessionId }) {
|
|
4329
|
+
return httpJson(`${normUrl(brokerUrl)}/v1/sessions/${encodeURIComponent(sessionId)}`);
|
|
4330
|
+
}
|
|
4331
|
+
async function claimCookie({ brokerUrl, sessionId, claimToken }) {
|
|
4332
|
+
return httpJson(`${normUrl(brokerUrl)}/v1/sessions/${encodeURIComponent(sessionId)}/claim?claimToken=${encodeURIComponent(claimToken)}`);
|
|
4333
|
+
}
|
|
4334
|
+
async function waitUntilReady({ brokerUrl, sessionId, timeoutMs = 18e4, intervalMs = 1500 }) {
|
|
4335
|
+
const started = Date.now();
|
|
4336
|
+
while (Date.now() - started < timeoutMs) {
|
|
4337
|
+
const session = await getSession({
|
|
4338
|
+
brokerUrl,
|
|
4339
|
+
sessionId
|
|
4340
|
+
});
|
|
4341
|
+
if (session.status === "READY") {
|
|
4342
|
+
if (!session.claimToken) throw new Error("会话 READY 但缺少 claimToken");
|
|
4343
|
+
return {
|
|
4344
|
+
...session,
|
|
4345
|
+
claimToken: session.claimToken
|
|
4346
|
+
};
|
|
4347
|
+
}
|
|
4348
|
+
if (session.status === "EXPIRED" || session.status === "CLAIMED") throw new Error(`会话不可用,当前状态: ${session.status}`);
|
|
4349
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
4350
|
+
}
|
|
4351
|
+
throw new Error("等待超时,请重新发起登录流程");
|
|
4352
|
+
}
|
|
4353
|
+
async function login(opts = {}) {
|
|
4354
|
+
const { brokerUrl, appId, open: autoOpen = true, timeoutMs, intervalMs, onLoginUrl } = opts;
|
|
4355
|
+
const created = await createSession({
|
|
4356
|
+
brokerUrl,
|
|
4357
|
+
appId
|
|
4358
|
+
});
|
|
4359
|
+
onLoginUrl?.(created.loginUrl);
|
|
4360
|
+
if (autoOpen) {
|
|
4361
|
+
const { default: openBrowser } = await import("open");
|
|
4362
|
+
await openBrowser(created.loginUrl);
|
|
4363
|
+
}
|
|
4364
|
+
const ready = await waitUntilReady({
|
|
4365
|
+
brokerUrl,
|
|
4366
|
+
sessionId: created.sessionId,
|
|
4367
|
+
timeoutMs,
|
|
4368
|
+
intervalMs
|
|
4369
|
+
});
|
|
4370
|
+
return (await claimCookie({
|
|
4371
|
+
brokerUrl,
|
|
4372
|
+
sessionId: created.sessionId,
|
|
4373
|
+
claimToken: ready.claimToken
|
|
4374
|
+
})).cookie;
|
|
4375
|
+
}
|
|
4376
|
+
var jd_cookie_exports = /* @__PURE__ */ __exportAll({
|
|
4377
|
+
clearJdCookie: () => clearJdCookie,
|
|
4378
|
+
getCookieStatus: () => getCookieStatus,
|
|
4379
|
+
getJdCookie: () => getJdCookie,
|
|
4380
|
+
getJdSourcePromptState: () => getJdSourcePromptState,
|
|
4381
|
+
isBrokerReachable: () => isBrokerReachable
|
|
4382
|
+
});
|
|
4383
|
+
const CACHE_PATH = join(join(homedir(), ".jd-skills"), "cookies.json");
|
|
4384
|
+
const COOKIE_TTL_MS = 1440 * 60 * 1e3;
|
|
4385
|
+
function readCache() {
|
|
4386
|
+
try {
|
|
4387
|
+
if (!existsSync(CACHE_PATH)) return null;
|
|
4388
|
+
const raw = readFileSync(CACHE_PATH, "utf-8");
|
|
4389
|
+
const parsed = JSON.parse(raw);
|
|
4390
|
+
if (typeof parsed.cookie !== "string" || typeof parsed.expiresAt !== "number") return null;
|
|
4391
|
+
return parsed;
|
|
4392
|
+
} catch {
|
|
4393
|
+
return null;
|
|
4394
|
+
}
|
|
4395
|
+
}
|
|
4396
|
+
function writeCache(entry) {
|
|
4397
|
+
try {
|
|
4398
|
+
mkdirSync(dirname(CACHE_PATH), { recursive: true });
|
|
4399
|
+
writeFileSync(CACHE_PATH, JSON.stringify(entry, null, 2), { mode: 384 });
|
|
4400
|
+
} catch {}
|
|
4401
|
+
}
|
|
4402
|
+
async function getJdCookie(opts) {
|
|
4403
|
+
if (!opts?.forceRefresh) {
|
|
4404
|
+
const cached = readCache();
|
|
4405
|
+
if (cached && cached.expiresAt > Date.now()) return cached.cookie;
|
|
4406
|
+
}
|
|
4407
|
+
if (!await probeJdIntranet()) return null;
|
|
4408
|
+
const brokerUrl = getBrokerUrl();
|
|
4409
|
+
if (!brokerUrl) return null;
|
|
4410
|
+
try {
|
|
4411
|
+
const cookie = await login({
|
|
4412
|
+
brokerUrl,
|
|
4413
|
+
open: true
|
|
4414
|
+
});
|
|
4415
|
+
if (typeof cookie === "string" && cookie.length > 0) {
|
|
4416
|
+
writeCache({
|
|
4417
|
+
cookie,
|
|
4418
|
+
expiresAt: Date.now() + COOKIE_TTL_MS,
|
|
4419
|
+
cachedAt: Date.now()
|
|
4420
|
+
});
|
|
4421
|
+
return cookie;
|
|
4422
|
+
}
|
|
4423
|
+
return null;
|
|
4424
|
+
} catch {
|
|
4425
|
+
return null;
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
function getCookieStatus() {
|
|
4429
|
+
const cached = readCache();
|
|
4430
|
+
if (!cached) return { loggedIn: false };
|
|
4431
|
+
return {
|
|
4432
|
+
loggedIn: true,
|
|
4433
|
+
expiresAt: cached.expiresAt,
|
|
4434
|
+
remainingMs: cached.expiresAt - Date.now()
|
|
4435
|
+
};
|
|
4436
|
+
}
|
|
4437
|
+
async function isBrokerReachable(brokerUrl) {
|
|
4438
|
+
if (!brokerUrl) return false;
|
|
4439
|
+
try {
|
|
4440
|
+
return (await fetch(brokerUrl, {
|
|
4441
|
+
method: "HEAD",
|
|
4442
|
+
signal: AbortSignal.timeout(3e3)
|
|
4443
|
+
})).status < 500;
|
|
4444
|
+
} catch {
|
|
4445
|
+
return false;
|
|
4446
|
+
}
|
|
4447
|
+
}
|
|
4448
|
+
async function getJdSourcePromptState() {
|
|
4449
|
+
if (!await probeJdIntranet()) return "unreachable";
|
|
4450
|
+
const cookieStatus = getCookieStatus();
|
|
4451
|
+
if (cookieStatus.loggedIn && cookieStatus.remainingMs && cookieStatus.remainingMs > 0) return "logged_in";
|
|
4452
|
+
return await isBrokerReachable(getBrokerUrl()) ? "auth_required" : "unreachable";
|
|
4453
|
+
}
|
|
4454
|
+
function clearJdCookie() {
|
|
4455
|
+
try {
|
|
4456
|
+
if (existsSync(CACHE_PATH)) writeFileSync(CACHE_PATH, "", { mode: 384 });
|
|
4457
|
+
} catch {}
|
|
4458
|
+
}
|
|
4165
4459
|
const REQUEST_TIMEOUT_MS = 5e3;
|
|
4166
4460
|
const DEFAULT_PAGE_SIZE = 24;
|
|
4167
4461
|
async function searchJdSkills(query, opts = {}) {
|
|
@@ -4243,6 +4537,79 @@ function formatInstalls(count) {
|
|
|
4243
4537
|
if (count >= 1e3) return `${(count / 1e3).toFixed(1).replace(/\.0$/, "")}K installs`;
|
|
4244
4538
|
return `${count} install${count === 1 ? "" : "s"}`;
|
|
4245
4539
|
}
|
|
4540
|
+
function isSearchableQuery(q) {
|
|
4541
|
+
const trimmed = q.trim();
|
|
4542
|
+
if (!trimmed) return false;
|
|
4543
|
+
if (/[^\u0000-\u007f]/.test(trimmed)) return trimmed.length >= 1;
|
|
4544
|
+
return trimmed.length >= 2;
|
|
4545
|
+
}
|
|
4546
|
+
function searchMinHint() {
|
|
4547
|
+
return `${DIM$3}Start typing to search (中文 1 字起,英文 2 字母起)${RESET$3}`;
|
|
4548
|
+
}
|
|
4549
|
+
function isPrintableInput(seq) {
|
|
4550
|
+
if (!seq || seq.length === 0) return false;
|
|
4551
|
+
if (seq.length === 1) {
|
|
4552
|
+
const code = seq.charCodeAt(0);
|
|
4553
|
+
if (code < 32 || code === 127) return false;
|
|
4554
|
+
}
|
|
4555
|
+
return true;
|
|
4556
|
+
}
|
|
4557
|
+
let _lastJdSearchKind = null;
|
|
4558
|
+
function getLastJdSearchKind() {
|
|
4559
|
+
return _lastJdSearchKind;
|
|
4560
|
+
}
|
|
4561
|
+
function skillDescriptionKey(skill) {
|
|
4562
|
+
return `${skill.origin}:${skill.source}:${skill.slug}:${skill.name}`;
|
|
4563
|
+
}
|
|
4564
|
+
async function fetchUpstreamDescription(skill) {
|
|
4565
|
+
const parts = skill.source.split("/");
|
|
4566
|
+
if (parts.length < 2) return null;
|
|
4567
|
+
const [owner, repo] = parts;
|
|
4568
|
+
const slug = toSkillSlug(skill.name);
|
|
4569
|
+
if (!slug) return null;
|
|
4570
|
+
try {
|
|
4571
|
+
const url = `${SEARCH_API_BASE}/api/download/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/${encodeURIComponent(slug)}`;
|
|
4572
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(5e3) });
|
|
4573
|
+
if (!res.ok) return null;
|
|
4574
|
+
const skillMd = (await res.json()).files?.find((f) => f.path === "SKILL.md" || f.path.endsWith("/SKILL.md"));
|
|
4575
|
+
if (!skillMd?.contents) return null;
|
|
4576
|
+
const { data: fm } = parseFrontmatter(skillMd.contents);
|
|
4577
|
+
const desc = fm.description;
|
|
4578
|
+
return typeof desc === "string" && desc.trim() ? sanitizeMetadata(desc.trim()) : null;
|
|
4579
|
+
} catch {
|
|
4580
|
+
return null;
|
|
4581
|
+
}
|
|
4582
|
+
}
|
|
4583
|
+
function wrapDescriptionPreview(text, maxLines = 4) {
|
|
4584
|
+
const cols = process.stdout.columns || 80;
|
|
4585
|
+
const width = Math.max(24, cols - 4);
|
|
4586
|
+
const plain = text.replace(/\s+/g, " ").trim();
|
|
4587
|
+
if (!plain) return [];
|
|
4588
|
+
const lines = [];
|
|
4589
|
+
let line = "";
|
|
4590
|
+
let truncated = false;
|
|
4591
|
+
for (const word of plain.split(" ")) {
|
|
4592
|
+
if (!line) {
|
|
4593
|
+
line = word;
|
|
4594
|
+
continue;
|
|
4595
|
+
}
|
|
4596
|
+
if (line.length + 1 + word.length <= width) line += ` ${word}`;
|
|
4597
|
+
else {
|
|
4598
|
+
lines.push(` ${DIM$3}${line}${RESET$3}`);
|
|
4599
|
+
line = word;
|
|
4600
|
+
if (lines.length >= maxLines) {
|
|
4601
|
+
truncated = true;
|
|
4602
|
+
break;
|
|
4603
|
+
}
|
|
4604
|
+
}
|
|
4605
|
+
}
|
|
4606
|
+
if (!truncated && line && lines.length < maxLines) lines.push(` ${DIM$3}${line}${RESET$3}`);
|
|
4607
|
+
else if (truncated && lines.length > 0) {
|
|
4608
|
+
const last = lines[lines.length - 1];
|
|
4609
|
+
lines[lines.length - 1] = last.replace(new RegExp(`${RESET$3}$`), `…${RESET$3}`);
|
|
4610
|
+
}
|
|
4611
|
+
return lines;
|
|
4612
|
+
}
|
|
4246
4613
|
async function searchUpstreamSkills(query) {
|
|
4247
4614
|
try {
|
|
4248
4615
|
const url = `${SEARCH_API_BASE}/api/search?q=${encodeURIComponent(query)}&limit=10`;
|
|
@@ -4276,6 +4643,7 @@ async function searchSkillsAPI(query) {
|
|
|
4276
4643
|
category1Name: s.category1Name,
|
|
4277
4644
|
jdDetail: s
|
|
4278
4645
|
})) : [];
|
|
4646
|
+
_lastJdSearchKind = jdResult?.kind ?? null;
|
|
4279
4647
|
surfaceJdSourceIssue(jdResult);
|
|
4280
4648
|
return [...upstream, ...jdSkills].sort((a, b) => (b.installs || 0) - (a.installs || 0));
|
|
4281
4649
|
}
|
|
@@ -4309,6 +4677,43 @@ async function runSearchPrompt(initialQuery = "") {
|
|
|
4309
4677
|
let loading = false;
|
|
4310
4678
|
let debounceTimer = null;
|
|
4311
4679
|
let lastRenderedLines = 0;
|
|
4680
|
+
let jdNeedsLogin = false;
|
|
4681
|
+
let scrollOffset = 0;
|
|
4682
|
+
const maxVisibleResults = 8;
|
|
4683
|
+
const descriptionCache = /* @__PURE__ */ new Map();
|
|
4684
|
+
let descriptionFetchToken = 0;
|
|
4685
|
+
let descriptionLoading = false;
|
|
4686
|
+
function getSelectedDescription() {
|
|
4687
|
+
const skill = results[selectedIndex];
|
|
4688
|
+
if (!skill) return void 0;
|
|
4689
|
+
if (skill.description?.trim()) return skill.description.trim();
|
|
4690
|
+
if (skill.jdDetail?.description?.trim()) return skill.jdDetail.description.trim();
|
|
4691
|
+
return descriptionCache.get(skillDescriptionKey(skill));
|
|
4692
|
+
}
|
|
4693
|
+
async function prefetchSelectedDescription() {
|
|
4694
|
+
const skill = results[selectedIndex];
|
|
4695
|
+
if (!skill || getSelectedDescription()) return;
|
|
4696
|
+
const key = skillDescriptionKey(skill);
|
|
4697
|
+
if (descriptionCache.has(key)) return;
|
|
4698
|
+
const token = ++descriptionFetchToken;
|
|
4699
|
+
descriptionLoading = true;
|
|
4700
|
+
render();
|
|
4701
|
+
const desc = skill.origin === "upstream" ? await fetchUpstreamDescription(skill) : skill.jdDetail?.description;
|
|
4702
|
+
if (token !== descriptionFetchToken) return;
|
|
4703
|
+
descriptionLoading = false;
|
|
4704
|
+
if (desc?.trim()) {
|
|
4705
|
+
descriptionCache.set(key, desc.trim());
|
|
4706
|
+
render();
|
|
4707
|
+
} else render();
|
|
4708
|
+
}
|
|
4709
|
+
function syncScrollOffset() {
|
|
4710
|
+
if (results.length <= maxVisibleResults) {
|
|
4711
|
+
scrollOffset = 0;
|
|
4712
|
+
return;
|
|
4713
|
+
}
|
|
4714
|
+
if (selectedIndex < scrollOffset) scrollOffset = selectedIndex;
|
|
4715
|
+
else if (selectedIndex >= scrollOffset + maxVisibleResults) scrollOffset = selectedIndex - maxVisibleResults + 1;
|
|
4716
|
+
}
|
|
4312
4717
|
if (process.stdin.isTTY) process.stdin.setRawMode(true);
|
|
4313
4718
|
readline.emitKeypressEvents(process.stdin);
|
|
4314
4719
|
process.stdin.resume();
|
|
@@ -4320,14 +4725,15 @@ async function runSearchPrompt(initialQuery = "") {
|
|
|
4320
4725
|
const cursor = `${BOLD$3}_${RESET$3}`;
|
|
4321
4726
|
lines.push(`${TEXT$2}Search skills:${RESET$3} ${query}${cursor}`);
|
|
4322
4727
|
lines.push("");
|
|
4323
|
-
if (!query || query
|
|
4728
|
+
if (!query || !isSearchableQuery(query)) lines.push(searchMinHint());
|
|
4324
4729
|
else if (results.length === 0 && loading) lines.push(`${DIM$3}Searching...${RESET$3}`);
|
|
4325
4730
|
else if (results.length === 0) lines.push(`${DIM$3}No skills found${RESET$3}`);
|
|
4326
4731
|
else {
|
|
4327
|
-
|
|
4732
|
+
syncScrollOffset();
|
|
4733
|
+
const visible = results.slice(scrollOffset, scrollOffset + maxVisibleResults);
|
|
4328
4734
|
for (let i = 0; i < visible.length; i++) {
|
|
4329
4735
|
const skill = visible[i];
|
|
4330
|
-
const isSelected = i === selectedIndex;
|
|
4736
|
+
const isSelected = scrollOffset + i === selectedIndex;
|
|
4331
4737
|
const arrow = isSelected ? `${BOLD$3}>${RESET$3}` : " ";
|
|
4332
4738
|
const name = isSelected ? `${BOLD$3}${skill.name}${RESET$3}` : `${TEXT$2}${skill.name}${RESET$3}`;
|
|
4333
4739
|
const originBadge = skill.origin === "jd" ? ` ${YELLOW$1}[jd]${RESET$3}` : "";
|
|
@@ -4337,11 +4743,21 @@ async function runSearchPrompt(initialQuery = "") {
|
|
|
4337
4743
|
const loadingIndicator = loading && i === 0 ? ` ${DIM$3}...${RESET$3}` : "";
|
|
4338
4744
|
lines.push(` ${arrow} ${originBadge}${name}${source}${installsBadge}${loadingIndicator}`);
|
|
4339
4745
|
}
|
|
4746
|
+
lines.push("");
|
|
4747
|
+
const preview = getSelectedDescription();
|
|
4748
|
+
if (preview) lines.push(...wrapDescriptionPreview(preview));
|
|
4749
|
+
else if (descriptionLoading) lines.push(` ${DIM$3}Loading description…${RESET$3}`);
|
|
4750
|
+
}
|
|
4751
|
+
if (jdNeedsLogin) {
|
|
4752
|
+
lines.push("");
|
|
4753
|
+
lines.push(`${YELLOW$1}┄${RESET$3} ${YELLOW$1}JD 内网技能需登录.${RESET$3} ${DIM$3}按 ${TEXT$2}L${RESET$3}${DIM$3} 登录,或退出后运行 ${TEXT$2}jd-skills login${RESET$3}`);
|
|
4340
4754
|
}
|
|
4341
4755
|
lines.push("");
|
|
4342
|
-
|
|
4756
|
+
const footerHint = jdNeedsLogin ? `${DIM$3}up/down navigate | enter select | ${TEXT$2}L${DIM$3} login | esc cancel${RESET$3}` : `${DIM$3}up/down navigate | enter select | esc cancel${RESET$3}`;
|
|
4757
|
+
lines.push(footerHint);
|
|
4343
4758
|
for (const line of lines) process.stdout.write(line + "\n");
|
|
4344
4759
|
lastRenderedLines = lines.length;
|
|
4760
|
+
if (results.length > 0 && !getSelectedDescription() && !descriptionLoading) prefetchSelectedDescription();
|
|
4345
4761
|
}
|
|
4346
4762
|
function triggerSearch(q) {
|
|
4347
4763
|
if (debounceTimer) {
|
|
@@ -4349,9 +4765,11 @@ async function runSearchPrompt(initialQuery = "") {
|
|
|
4349
4765
|
debounceTimer = null;
|
|
4350
4766
|
}
|
|
4351
4767
|
loading = false;
|
|
4352
|
-
if (!q
|
|
4768
|
+
if (!isSearchableQuery(q)) {
|
|
4353
4769
|
results = [];
|
|
4354
4770
|
selectedIndex = 0;
|
|
4771
|
+
scrollOffset = 0;
|
|
4772
|
+
jdNeedsLogin = false;
|
|
4355
4773
|
render();
|
|
4356
4774
|
return;
|
|
4357
4775
|
}
|
|
@@ -4362,6 +4780,9 @@ async function runSearchPrompt(initialQuery = "") {
|
|
|
4362
4780
|
try {
|
|
4363
4781
|
results = await searchSkillsAPI(q);
|
|
4364
4782
|
selectedIndex = 0;
|
|
4783
|
+
scrollOffset = 0;
|
|
4784
|
+
if (isJdIntranetAvailable()) jdNeedsLogin = await getJdSourcePromptState() === "auth_required" || getLastJdSearchKind() === "auth_required";
|
|
4785
|
+
else jdNeedsLogin = false;
|
|
4365
4786
|
} catch {
|
|
4366
4787
|
results = [];
|
|
4367
4788
|
} finally {
|
|
@@ -4380,7 +4801,7 @@ async function runSearchPrompt(initialQuery = "") {
|
|
|
4380
4801
|
process.stdout.write(SHOW_CURSOR);
|
|
4381
4802
|
process.stdin.pause();
|
|
4382
4803
|
}
|
|
4383
|
-
function handleKeypress(_ch, key) {
|
|
4804
|
+
async function handleKeypress(_ch, key) {
|
|
4384
4805
|
if (!key) return;
|
|
4385
4806
|
if (key.name === "escape" || key.ctrl && key.name === "c") {
|
|
4386
4807
|
cleanup();
|
|
@@ -4394,27 +4815,34 @@ async function runSearchPrompt(initialQuery = "") {
|
|
|
4394
4815
|
}
|
|
4395
4816
|
if (key.name === "up") {
|
|
4396
4817
|
selectedIndex = Math.max(0, selectedIndex - 1);
|
|
4818
|
+
descriptionFetchToken++;
|
|
4819
|
+
descriptionLoading = false;
|
|
4397
4820
|
render();
|
|
4398
4821
|
return;
|
|
4399
4822
|
}
|
|
4400
4823
|
if (key.name === "down") {
|
|
4401
4824
|
selectedIndex = Math.min(Math.max(0, results.length - 1), selectedIndex + 1);
|
|
4825
|
+
descriptionFetchToken++;
|
|
4826
|
+
descriptionLoading = false;
|
|
4402
4827
|
render();
|
|
4403
4828
|
return;
|
|
4404
4829
|
}
|
|
4405
4830
|
if (key.name === "backspace") {
|
|
4406
4831
|
if (query.length > 0) {
|
|
4407
|
-
query = query.slice(0, -1);
|
|
4832
|
+
query = [...query].slice(0, -1).join("");
|
|
4408
4833
|
triggerSearch(query);
|
|
4409
4834
|
}
|
|
4410
4835
|
return;
|
|
4411
4836
|
}
|
|
4412
|
-
if (key.sequence && !key.ctrl && !key.meta
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4837
|
+
if ((key.name === "l" || key.sequence === "l") && jdNeedsLogin && !key.ctrl && !key.meta) {
|
|
4838
|
+
cleanup();
|
|
4839
|
+
await offerJdLoginPrompt(query);
|
|
4840
|
+
resolve(null);
|
|
4841
|
+
return;
|
|
4842
|
+
}
|
|
4843
|
+
if (key.sequence && !key.ctrl && !key.meta && isPrintableInput(key.sequence)) {
|
|
4844
|
+
query += key.sequence;
|
|
4845
|
+
triggerSearch(query);
|
|
4418
4846
|
}
|
|
4419
4847
|
}
|
|
4420
4848
|
process.stdin.on("keypress", handleKeypress);
|
|
@@ -4438,7 +4866,7 @@ async function offerJdLoginPrompt(query) {
|
|
|
4438
4866
|
if (await getJdSourcePromptState() !== "auth_required") return;
|
|
4439
4867
|
console.log(`${YELLOW$1}┄${RESET$3} ${YELLOW$1}JD marketplace is reachable but you're not logged in.${RESET$3} ${DIM$3}Log in now to also see internal skills?${RESET$3}`);
|
|
4440
4868
|
if (!await promptYesNo(" Log in? [Y/n]: ")) return;
|
|
4441
|
-
const { getJdCookie } = await
|
|
4869
|
+
const { getJdCookie } = await Promise.resolve().then(() => jd_cookie_exports);
|
|
4442
4870
|
if (!!!await getJdCookie({ forceRefresh: true })) {
|
|
4443
4871
|
console.log(`${DIM$3}Login cancelled or failed.${RESET$3} You can retry with: jd-skills login`);
|
|
4444
4872
|
return;
|
|
@@ -4500,6 +4928,7 @@ ${DIM$3} 2) npx jd-skills add <owner/repo@skill>${RESET$3}`;
|
|
|
4500
4928
|
return;
|
|
4501
4929
|
}
|
|
4502
4930
|
await offerJdLoginPrompt();
|
|
4931
|
+
await probeJdIntranet();
|
|
4503
4932
|
const selected = await runSearchPrompt();
|
|
4504
4933
|
track({
|
|
4505
4934
|
event: "find",
|
|
@@ -6195,8 +6624,8 @@ ${BOLD}Project:${RESET}
|
|
|
6195
6624
|
experimental_sync Sync skills from node_modules into agent directories
|
|
6196
6625
|
|
|
6197
6626
|
${BOLD}Auth (intranet marketplaces, opt-in):${RESET}
|
|
6198
|
-
login Open browser to authenticate with
|
|
6199
|
-
|
|
6627
|
+
login Open browser to authenticate with JD marketplace
|
|
6628
|
+
(built-in login; no external SDK install)
|
|
6200
6629
|
login --force Re-authenticate even if a valid cookie is cached
|
|
6201
6630
|
logout Clear the cached auth cookie
|
|
6202
6631
|
whoami Show current login status
|
|
@@ -6365,10 +6794,20 @@ async function runLogin(args = []) {
|
|
|
6365
6794
|
console.log(`Run ${TEXT}jd-skills login --force${RESET} to re-authenticate.`);
|
|
6366
6795
|
return;
|
|
6367
6796
|
}
|
|
6368
|
-
if (!await
|
|
6369
|
-
console.log(`${TEXT}Cannot log in:${RESET}
|
|
6370
|
-
console.log(` ${DIM}${
|
|
6371
|
-
|
|
6797
|
+
if (!await probeJdIntranet()) {
|
|
6798
|
+
console.log(`${TEXT}Cannot log in:${RESET} JD intranet not detected.`);
|
|
6799
|
+
console.log(` ${DIM}Connect to JD VPN/network, then run ${TEXT}jd-skills login${RESET} again.${RESET}`);
|
|
6800
|
+
process.exit(1);
|
|
6801
|
+
}
|
|
6802
|
+
const broker = getBrokerUrl();
|
|
6803
|
+
if (!broker) {
|
|
6804
|
+
console.log(`${TEXT}Cannot log in:${RESET} SSO broker URL not configured.`);
|
|
6805
|
+
console.log(` ${DIM}Run ${TEXT}jd-skills config set-broker <url>${RESET}${DIM} or set JD_BROKER_URL.${RESET}`);
|
|
6806
|
+
process.exit(1);
|
|
6807
|
+
}
|
|
6808
|
+
if (!await isBrokerReachable(broker)) {
|
|
6809
|
+
console.log(`${TEXT}Cannot log in:${RESET} SSO broker unreachable at ${broker}.`);
|
|
6810
|
+
console.log(` ${DIM}Check VPN/network, or run ${TEXT}jd-skills doctor${RESET}${DIM} for diagnostics.${RESET}`);
|
|
6372
6811
|
process.exit(1);
|
|
6373
6812
|
}
|
|
6374
6813
|
console.log(`${TEXT}Logging in to JD marketplace...${RESET}`);
|
|
@@ -6392,16 +6831,14 @@ function runLogout() {
|
|
|
6392
6831
|
}
|
|
6393
6832
|
async function runWhoami() {
|
|
6394
6833
|
const status = getCookieStatus();
|
|
6395
|
-
const sdkOk = await isBrokerSdkAvailable();
|
|
6396
6834
|
const broker = getBrokerUrl();
|
|
6835
|
+
const onIntranet = await probeJdIntranet();
|
|
6397
6836
|
console.log(`${BOLD}JD marketplace status${RESET}`);
|
|
6398
|
-
console.log(`
|
|
6399
|
-
console.log(`
|
|
6837
|
+
console.log(` intranet: ${onIntranet ? `${TEXT}detected${RESET}` : `${DIM}not detected${RESET}`}`);
|
|
6838
|
+
console.log(` broker URL: ${broker ? `${TEXT}${broker}${RESET}` : `${DIM}n/a${RESET}`}`);
|
|
6400
6839
|
console.log();
|
|
6401
|
-
if (!
|
|
6402
|
-
console.log(`${
|
|
6403
|
-
console.log(` ${DIM}${installSdkHint()}${RESET}`);
|
|
6404
|
-
console.log(` (or run: ${TEXT}jd-skills doctor${RESET} for a full diagnostic)`);
|
|
6840
|
+
if (!onIntranet) {
|
|
6841
|
+
console.log(`${DIM}JD marketplace is only available on JD intranet.${RESET}`);
|
|
6405
6842
|
return;
|
|
6406
6843
|
}
|
|
6407
6844
|
if (status.loggedIn) {
|
|
@@ -6422,8 +6859,6 @@ async function runDoctor() {
|
|
|
6422
6859
|
}
|
|
6423
6860
|
const checks = [];
|
|
6424
6861
|
const skillApiUrl = await resolveSkillApiUrl();
|
|
6425
|
-
const sdkPackage = getSdkPackageName();
|
|
6426
|
-
const expectedRegistry = resolveExpectedNpmRegistry();
|
|
6427
6862
|
checks.push({
|
|
6428
6863
|
label: "JD intranet detected",
|
|
6429
6864
|
ok: true,
|
|
@@ -6436,39 +6871,12 @@ async function runDoctor() {
|
|
|
6436
6871
|
fix: skillApiUrl.length > 0 ? void 0 : `Set JD_SKILL_API_URL only if the default marketplace URL is wrong for your environment.`
|
|
6437
6872
|
});
|
|
6438
6873
|
checks.push({
|
|
6439
|
-
label: "
|
|
6440
|
-
ok: sdkPackage.length > 0,
|
|
6441
|
-
detail: sdkPackage || "not resolved (unexpected on intranet)",
|
|
6442
|
-
fix: sdkPackage.length > 0 ? void 0 : `Set JD_BROKER_SDK_PACKAGE only if you use a forked SDK name.`
|
|
6443
|
-
});
|
|
6444
|
-
const npmRegistry = await getNpmRegistry();
|
|
6445
|
-
if (expectedRegistry) {
|
|
6446
|
-
const registryOk = npmRegistry.replace(/\/+$/, "") === expectedRegistry.replace(/\/+$/, "");
|
|
6447
|
-
checks.push({
|
|
6448
|
-
label: "npm registry configured",
|
|
6449
|
-
ok: registryOk,
|
|
6450
|
-
detail: registryOk ? `registry = ${npmRegistry}` : `registry = ${npmRegistry} ${DIM}(expected ${expectedRegistry})${RESET}`,
|
|
6451
|
-
fix: registryOk ? void 0 : `Add this line to ~/.npmrc:\n registry = ${expectedRegistry}\n Or export JD_NPM_REGISTRY=${expectedRegistry} and re-run jd-skills doctor.`
|
|
6452
|
-
});
|
|
6453
|
-
} else checks.push({
|
|
6454
|
-
label: "npm registry (informational)",
|
|
6874
|
+
label: "built-in login client",
|
|
6455
6875
|
ok: true,
|
|
6456
|
-
detail:
|
|
6457
|
-
});
|
|
6458
|
-
const sdkOk = sdkPackage.length > 0 ? await isBrokerSdkAvailable() : false;
|
|
6459
|
-
checks.push({
|
|
6460
|
-
label: sdkPackage ? `${sdkPackage} SDK loadable` : "cookie-broker SDK loadable",
|
|
6461
|
-
ok: sdkOk,
|
|
6462
|
-
detail: sdkOk ? `dynamic import() succeeded` : sdkPackage ? `${sdkPackage} not found in this run's node_modules` : "skipped (SDK package not resolved)",
|
|
6463
|
-
fix: sdkOk ? void 0 : sdkPackage ? `${installSdkHint()}. After fixing ~/.npmrc, re-run npx jd-skills.` : `Unexpected on intranet — contact your platform team.`
|
|
6876
|
+
detail: "cookie broker client bundled with jd-skills (no external SDK install)"
|
|
6464
6877
|
});
|
|
6465
6878
|
const cookieStatus = getCookieStatus();
|
|
6466
|
-
if (
|
|
6467
|
-
label: "cached cookie",
|
|
6468
|
-
ok: false,
|
|
6469
|
-
detail: "skipped (SDK not loadable)"
|
|
6470
|
-
});
|
|
6471
|
-
else if (cookieStatus.loggedIn) {
|
|
6879
|
+
if (cookieStatus.loggedIn) {
|
|
6472
6880
|
const remaining = cookieStatus.remainingMs ?? 0;
|
|
6473
6881
|
checks.push({
|
|
6474
6882
|
label: "cached cookie",
|
|
@@ -6520,29 +6928,6 @@ async function runDoctor() {
|
|
|
6520
6928
|
console.log(`Run ${TEXT}jd-skills doctor${RESET} again after fixing to re-verify.`);
|
|
6521
6929
|
process.exit(1);
|
|
6522
6930
|
}
|
|
6523
|
-
async function getNpmRegistry() {
|
|
6524
|
-
const fs = await import("fs");
|
|
6525
|
-
const path = await import("path");
|
|
6526
|
-
let dir = process.cwd();
|
|
6527
|
-
const root = path.parse(dir).root;
|
|
6528
|
-
while (dir !== root) {
|
|
6529
|
-
const rc = path.join(dir, ".npmrc");
|
|
6530
|
-
if (fs.existsSync(rc)) try {
|
|
6531
|
-
const m = fs.readFileSync(rc, "utf-8").match(/^registry\s*=\s*(.+)$/m);
|
|
6532
|
-
if (m) return m[1].trim();
|
|
6533
|
-
} catch {}
|
|
6534
|
-
dir = path.dirname(dir);
|
|
6535
|
-
}
|
|
6536
|
-
const home = process.env.HOME || process.env.USERPROFILE;
|
|
6537
|
-
if (home) {
|
|
6538
|
-
const userRc = path.join(home, ".npmrc");
|
|
6539
|
-
if (fs.existsSync(userRc)) try {
|
|
6540
|
-
const m = fs.readFileSync(userRc, "utf-8").match(/^registry\s*=\s*(.+)$/m);
|
|
6541
|
-
if (m) return m[1].trim();
|
|
6542
|
-
} catch {}
|
|
6543
|
-
}
|
|
6544
|
-
return "https://registry.npmjs.org/";
|
|
6545
|
-
}
|
|
6546
6931
|
async function isUrlReachable(url) {
|
|
6547
6932
|
try {
|
|
6548
6933
|
return (await fetch(url, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jd-skills",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "CLI for the agent skills ecosystem (JD fork of vercel-labs/skills)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -134,6 +134,7 @@
|
|
|
134
134
|
},
|
|
135
135
|
"packageManager": "pnpm@10.17.1",
|
|
136
136
|
"dependencies": {
|
|
137
|
+
"open": "^11.0.0",
|
|
137
138
|
"yaml": "^2.8.3"
|
|
138
139
|
}
|
|
139
140
|
}
|
package/dist/_chunks/config.mjs
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
-
import { dirname, join } from "path";
|
|
3
|
-
import { homedir } from "os";
|
|
4
|
-
const JD_INTRANET_DEFAULTS = {
|
|
5
|
-
skillApiUrl: "https://mkt-skill-manager.jd.com/api/skill/public/sorted-list",
|
|
6
|
-
brokerUrl: "https://cbroker.jd.com",
|
|
7
|
-
sdkPackage: "@jd/jd-cookie-broker",
|
|
8
|
-
gitlabHosts: ["coding.jd.com"],
|
|
9
|
-
npmRegistry: "http://registry.m.jd.com"
|
|
10
|
-
};
|
|
11
|
-
const PROBE_CACHE_PATH = join(homedir(), ".jd-skills", "intranet-probe.json");
|
|
12
|
-
const PROBE_TTL_MS = 3600 * 1e3;
|
|
13
|
-
const PROBE_TIMEOUT_MS = 3e3;
|
|
14
|
-
let memoryProbe = null;
|
|
15
|
-
let inFlightProbe = null;
|
|
16
|
-
function readDiskProbe() {
|
|
17
|
-
try {
|
|
18
|
-
if (!existsSync(PROBE_CACHE_PATH)) return null;
|
|
19
|
-
const parsed = JSON.parse(readFileSync(PROBE_CACHE_PATH, "utf-8"));
|
|
20
|
-
if (typeof parsed.available !== "boolean" || typeof parsed.checkedAt !== "number") return null;
|
|
21
|
-
if (Date.now() - parsed.checkedAt > PROBE_TTL_MS) return null;
|
|
22
|
-
return parsed;
|
|
23
|
-
} catch {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function writeDiskProbe(available) {
|
|
28
|
-
try {
|
|
29
|
-
mkdirSync(dirname(PROBE_CACHE_PATH), { recursive: true });
|
|
30
|
-
writeFileSync(PROBE_CACHE_PATH, JSON.stringify({
|
|
31
|
-
available,
|
|
32
|
-
checkedAt: Date.now()
|
|
33
|
-
}, null, 2), { mode: 384 });
|
|
34
|
-
} catch {}
|
|
35
|
-
}
|
|
36
|
-
function setProbeResult(available) {
|
|
37
|
-
memoryProbe = available;
|
|
38
|
-
writeDiskProbe(available);
|
|
39
|
-
return available;
|
|
40
|
-
}
|
|
41
|
-
function getJdIntranetProbeSync() {
|
|
42
|
-
if (memoryProbe !== null) return memoryProbe;
|
|
43
|
-
const cached = readDiskProbe();
|
|
44
|
-
if (!cached) return null;
|
|
45
|
-
memoryProbe = cached.available;
|
|
46
|
-
return cached.available;
|
|
47
|
-
}
|
|
48
|
-
async function headReachable(url) {
|
|
49
|
-
try {
|
|
50
|
-
return (await fetch(url, {
|
|
51
|
-
method: "HEAD",
|
|
52
|
-
signal: AbortSignal.timeout(PROBE_TIMEOUT_MS)
|
|
53
|
-
})).status < 500;
|
|
54
|
-
} catch {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
async function probeJdIntranet(force = false) {
|
|
59
|
-
if (!force && memoryProbe !== null) return memoryProbe;
|
|
60
|
-
if (!force) {
|
|
61
|
-
const cached = readDiskProbe();
|
|
62
|
-
if (cached) {
|
|
63
|
-
memoryProbe = cached.available;
|
|
64
|
-
return cached.available;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
if (!force && inFlightProbe) return inFlightProbe;
|
|
68
|
-
inFlightProbe = (async () => {
|
|
69
|
-
return setProbeResult(await headReachable((process.env.JD_SKILL_API_URL ?? "").trim() || JD_INTRANET_DEFAULTS.skillApiUrl));
|
|
70
|
-
})();
|
|
71
|
-
try {
|
|
72
|
-
return await inFlightProbe;
|
|
73
|
-
} finally {
|
|
74
|
-
inFlightProbe = null;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
function isJdIntranetAvailable() {
|
|
78
|
-
return getJdIntranetProbeSync() === true;
|
|
79
|
-
}
|
|
80
|
-
async function resolveSkillApiUrl() {
|
|
81
|
-
const env = (process.env.JD_SKILL_API_URL ?? "").trim();
|
|
82
|
-
if (env) return env;
|
|
83
|
-
if (await probeJdIntranet()) return JD_INTRANET_DEFAULTS.skillApiUrl;
|
|
84
|
-
return "";
|
|
85
|
-
}
|
|
86
|
-
function resolveSkillApiUrlSync() {
|
|
87
|
-
const env = (process.env.JD_SKILL_API_URL ?? "").trim();
|
|
88
|
-
if (env) return env;
|
|
89
|
-
if (isJdIntranetAvailable()) return JD_INTRANET_DEFAULTS.skillApiUrl;
|
|
90
|
-
return "";
|
|
91
|
-
}
|
|
92
|
-
function resolveSdkPackageName() {
|
|
93
|
-
const env = (process.env.JD_BROKER_SDK_PACKAGE ?? "").trim();
|
|
94
|
-
if (env) return env;
|
|
95
|
-
if (isJdIntranetAvailable()) return JD_INTRANET_DEFAULTS.sdkPackage;
|
|
96
|
-
return "";
|
|
97
|
-
}
|
|
98
|
-
async function resolveSdkPackageNameAsync() {
|
|
99
|
-
const env = (process.env.JD_BROKER_SDK_PACKAGE ?? "").trim();
|
|
100
|
-
if (env) return env;
|
|
101
|
-
if (await probeJdIntranet()) return JD_INTRANET_DEFAULTS.sdkPackage;
|
|
102
|
-
return "";
|
|
103
|
-
}
|
|
104
|
-
function resolveBrokerUrlFromIntranet(fileBrokerUrl) {
|
|
105
|
-
const envUrl = (process.env.JD_BROKER_URL ?? "").trim();
|
|
106
|
-
if (envUrl) return envUrl.replace(/\/+$/, "");
|
|
107
|
-
if (fileBrokerUrl) return fileBrokerUrl;
|
|
108
|
-
if (isJdIntranetAvailable()) return JD_INTRANET_DEFAULTS.brokerUrl;
|
|
109
|
-
return "";
|
|
110
|
-
}
|
|
111
|
-
function resolveGitlabHosts() {
|
|
112
|
-
const fromEnv = (process.env.JD_GITLAB_HOSTS ?? "").split(",").map((h) => h.trim().toLowerCase()).filter((h) => h.length > 0).filter((h, i, arr) => arr.indexOf(h) === i);
|
|
113
|
-
if (fromEnv.length > 0) return fromEnv;
|
|
114
|
-
if (isJdIntranetAvailable()) return [...JD_INTRANET_DEFAULTS.gitlabHosts];
|
|
115
|
-
return [];
|
|
116
|
-
}
|
|
117
|
-
function resolveExpectedNpmRegistry() {
|
|
118
|
-
const env = (process.env.JD_NPM_REGISTRY ?? "").trim();
|
|
119
|
-
if (env) return env;
|
|
120
|
-
if (isJdIntranetAvailable()) return JD_INTRANET_DEFAULTS.npmRegistry;
|
|
121
|
-
return "";
|
|
122
|
-
}
|
|
123
|
-
const CONFIG_PATH = join(join(homedir(), ".jd-skills"), "config.json");
|
|
124
|
-
function readConfig() {
|
|
125
|
-
try {
|
|
126
|
-
if (!existsSync(CONFIG_PATH)) return {};
|
|
127
|
-
const raw = readFileSync(CONFIG_PATH, "utf-8");
|
|
128
|
-
const parsed = JSON.parse(raw);
|
|
129
|
-
if (typeof parsed !== "object" || parsed === null) return {};
|
|
130
|
-
return parsed;
|
|
131
|
-
} catch {
|
|
132
|
-
return {};
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
function writeConfig(config) {
|
|
136
|
-
mkdirSync(dirname(CONFIG_PATH), { recursive: true });
|
|
137
|
-
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 384 });
|
|
138
|
-
}
|
|
139
|
-
function getBrokerUrl() {
|
|
140
|
-
const fileConfig = readConfig();
|
|
141
|
-
return resolveBrokerUrlFromIntranet(fileConfig.brokerUrl && fileConfig.brokerUrl.trim().length > 0 ? fileConfig.brokerUrl.trim().replace(/\/+$/, "") : "");
|
|
142
|
-
}
|
|
143
|
-
function setBrokerUrl(url) {
|
|
144
|
-
const config = readConfig();
|
|
145
|
-
if (url && url.trim().length > 0) config.brokerUrl = url.trim().replace(/\/+$/, "");
|
|
146
|
-
else delete config.brokerUrl;
|
|
147
|
-
config.version = 1;
|
|
148
|
-
writeConfig(config);
|
|
149
|
-
}
|
|
150
|
-
function resetConfig() {
|
|
151
|
-
try {
|
|
152
|
-
if (existsSync(CONFIG_PATH)) writeFileSync(CONFIG_PATH, "{}", { mode: 384 });
|
|
153
|
-
} catch {}
|
|
154
|
-
}
|
|
155
|
-
function getConfig() {
|
|
156
|
-
return readConfig();
|
|
157
|
-
}
|
|
158
|
-
export { JD_INTRANET_DEFAULTS as a, resolveExpectedNpmRegistry as c, resolveSdkPackageNameAsync as d, resolveSkillApiUrl as f, setBrokerUrl as i, resolveGitlabHosts as l, getConfig as n, isJdIntranetAvailable as o, resolveSkillApiUrlSync as p, resetConfig as r, probeJdIntranet as s, getBrokerUrl as t, resolveSdkPackageName as u };
|
package/dist/_chunks/config2.mjs
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { d as resolveSdkPackageNameAsync, s as probeJdIntranet, t as getBrokerUrl, u as resolveSdkPackageName } from "./config.mjs";
|
|
2
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
3
|
-
import { dirname, join } from "path";
|
|
4
|
-
import { homedir } from "os";
|
|
5
|
-
const CACHE_PATH = join(join(homedir(), ".jd-skills"), "cookies.json");
|
|
6
|
-
const COOKIE_TTL_MS = 1440 * 60 * 1e3;
|
|
7
|
-
function getSdkPackageName() {
|
|
8
|
-
return resolveSdkPackageName();
|
|
9
|
-
}
|
|
10
|
-
async function getSdkPackageNameResolved() {
|
|
11
|
-
return resolveSdkPackageNameAsync();
|
|
12
|
-
}
|
|
13
|
-
function installSdkHint() {
|
|
14
|
-
return `install ${getSdkPackageName() || "@jd/jd-cookie-broker"} from your npm registry (on JD intranet: add registry = http://registry.m.jd.com to ~/.npmrc)`;
|
|
15
|
-
}
|
|
16
|
-
function readCache() {
|
|
17
|
-
try {
|
|
18
|
-
if (!existsSync(CACHE_PATH)) return null;
|
|
19
|
-
const raw = readFileSync(CACHE_PATH, "utf-8");
|
|
20
|
-
const parsed = JSON.parse(raw);
|
|
21
|
-
if (typeof parsed.cookie !== "string" || typeof parsed.expiresAt !== "number") return null;
|
|
22
|
-
return parsed;
|
|
23
|
-
} catch {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function writeCache(entry) {
|
|
28
|
-
try {
|
|
29
|
-
mkdirSync(dirname(CACHE_PATH), { recursive: true });
|
|
30
|
-
writeFileSync(CACHE_PATH, JSON.stringify(entry, null, 2), { mode: 384 });
|
|
31
|
-
} catch {}
|
|
32
|
-
}
|
|
33
|
-
async function getJdCookie(opts) {
|
|
34
|
-
if (!opts?.forceRefresh) {
|
|
35
|
-
const cached = readCache();
|
|
36
|
-
if (cached && cached.expiresAt > Date.now()) return cached.cookie;
|
|
37
|
-
}
|
|
38
|
-
const sdkPackage = await getSdkPackageNameResolved();
|
|
39
|
-
if (!sdkPackage) return null;
|
|
40
|
-
let loginFn = null;
|
|
41
|
-
try {
|
|
42
|
-
loginFn = (await import(
|
|
43
|
-
/* @vite-ignore */
|
|
44
|
-
`${sdkPackage}/client`
|
|
45
|
-
)).login ?? null;
|
|
46
|
-
} catch {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
if (!loginFn) return null;
|
|
50
|
-
try {
|
|
51
|
-
const cookie = await loginFn({
|
|
52
|
-
brokerUrl: getBrokerUrl(),
|
|
53
|
-
open: true
|
|
54
|
-
});
|
|
55
|
-
if (typeof cookie === "string" && cookie.length > 0) {
|
|
56
|
-
writeCache({
|
|
57
|
-
cookie,
|
|
58
|
-
expiresAt: Date.now() + COOKIE_TTL_MS,
|
|
59
|
-
cachedAt: Date.now()
|
|
60
|
-
});
|
|
61
|
-
return cookie;
|
|
62
|
-
}
|
|
63
|
-
return null;
|
|
64
|
-
} catch {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
function getCookieStatus() {
|
|
69
|
-
const cached = readCache();
|
|
70
|
-
if (!cached) return { loggedIn: false };
|
|
71
|
-
return {
|
|
72
|
-
loggedIn: true,
|
|
73
|
-
expiresAt: cached.expiresAt,
|
|
74
|
-
remainingMs: cached.expiresAt - Date.now()
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
async function isBrokerSdkAvailable() {
|
|
78
|
-
const sdkPackage = await getSdkPackageNameResolved();
|
|
79
|
-
if (!sdkPackage) return false;
|
|
80
|
-
try {
|
|
81
|
-
return typeof (await import(
|
|
82
|
-
/* @vite-ignore */
|
|
83
|
-
`${sdkPackage}/client`
|
|
84
|
-
)).login === "function";
|
|
85
|
-
} catch {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
async function isBrokerReachable(brokerUrl) {
|
|
90
|
-
try {
|
|
91
|
-
return (await fetch(brokerUrl, {
|
|
92
|
-
method: "HEAD",
|
|
93
|
-
signal: AbortSignal.timeout(3e3)
|
|
94
|
-
})).status < 500;
|
|
95
|
-
} catch {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
async function getJdSourcePromptState() {
|
|
100
|
-
if (!await probeJdIntranet()) return "unreachable";
|
|
101
|
-
if (!await isBrokerSdkAvailable()) return "sdk_missing";
|
|
102
|
-
const cookieStatus = getCookieStatus();
|
|
103
|
-
if (cookieStatus.loggedIn && cookieStatus.remainingMs && cookieStatus.remainingMs > 0) return "logged_in";
|
|
104
|
-
const { getBrokerUrl } = await import("./config2.mjs");
|
|
105
|
-
return await isBrokerReachable(getBrokerUrl()) ? "auth_required" : "unreachable";
|
|
106
|
-
}
|
|
107
|
-
function clearJdCookie() {
|
|
108
|
-
try {
|
|
109
|
-
if (existsSync(CACHE_PATH)) writeFileSync(CACHE_PATH, "", { mode: 384 });
|
|
110
|
-
} catch {}
|
|
111
|
-
}
|
|
112
|
-
export { getSdkPackageName as a, isBrokerSdkAvailable as c, getJdSourcePromptState as i, getCookieStatus as n, installSdkHint as o, getJdCookie as r, isBrokerReachable as s, clearJdCookie as t };
|