@dsh-workbench/core 1.1.7 → 1.1.8
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/client.js +19 -2
- package/dist/client/client.body.js +19 -2
- package/dist/client/index.js +19 -2
- package/dist/host/index.js +214 -282
- package/dist/types/modules/panels/model/approval-questions.d.ts +6 -0
- package/package.json +3 -3
- package/skills/workbench-module-diy/FAMILY.md +1 -0
- package/skills/workbench-module-diy/SKILL.md +1 -0
- package/skills/workbench-module-diy/WIRING.md +4 -2
package/client.js
CHANGED
|
@@ -3382,7 +3382,7 @@ window.__ModuleLoader__.load({
|
|
|
3382
3382
|
"panels.discover.missingIndex": "This repository has no {path} yet.",
|
|
3383
3383
|
"panels.discover.initTitle": "Initialize this repository as a module market index?",
|
|
3384
3384
|
"panels.discover.initCta": "Initialize market index",
|
|
3385
|
-
"panels.discover.initWhat": "It will write the index directory market/ and README.md on {branch}, commit once, and push. Modules you publish from this workbench will commit their build files under artifacts/<package-name
|
|
3385
|
+
"panels.discover.initWhat": "It will write the index directory market/ and README.md on {branch}, commit once, and push. Modules you publish from this workbench will commit their build files under artifacts/<package-name>/ and their entry in market/<package-name>.json. The repository stays owned by its owner.",
|
|
3386
3386
|
"panels.discover.initBranch": "Branch",
|
|
3387
3387
|
"panels.discover.initBranchHint": "The index and build files go to this branch; an empty repository gets it created.",
|
|
3388
3388
|
"panels.discover.initBranchBad": "Use only letters, digits, dots, underscores, slashes, or dashes in a branch name.",
|
|
@@ -3713,6 +3713,8 @@ window.__ModuleLoader__.load({
|
|
|
3713
3713
|
"approval.publish.version": "Version",
|
|
3714
3714
|
"approval.publish.author": "Author",
|
|
3715
3715
|
"approval.publish.authorMissing": "unsigned",
|
|
3716
|
+
"approval.publish.labels": "Labels",
|
|
3717
|
+
"approval.publish.labelsMissing": "none yet (1–2 picked on publish)",
|
|
3716
3718
|
"approval.publish.owner": "Owner",
|
|
3717
3719
|
"approval.publish.ownerUnowned": "originally unattributed",
|
|
3718
3720
|
"approval.publish.ownerTaken": "Owned by {owner}",
|
|
@@ -4128,7 +4130,7 @@ window.__ModuleLoader__.load({
|
|
|
4128
4130
|
"panels.discover.missingIndex": "仓库里还没有索引文件 {path}",
|
|
4129
4131
|
"panels.discover.initTitle": "把这个仓库初始化成模块市场索引?",
|
|
4130
4132
|
"panels.discover.initCta": "初始化成市场索引",
|
|
4131
|
-
"panels.discover.initWhat": "会在 {branch} 分支写索引目录 market/ 与 README.md,提交一次并推上去;之后从这个工作台发布的模块会把打包好的文件提交到 artifacts
|
|
4133
|
+
"panels.discover.initWhat": "会在 {branch} 分支写索引目录 market/ 与 README.md,提交一次并推上去;之后从这个工作台发布的模块会把打包好的文件提交到 artifacts/<包名>/,条目写到 market/<包名>.json。仓库的写权限归它的所有者。",
|
|
4132
4134
|
"panels.discover.initBranch": "分支",
|
|
4133
4135
|
"panels.discover.initBranchHint": "索引和打包文件都发到这个分支;空仓库会新建它。",
|
|
4134
4136
|
"panels.discover.initBranchBad": "分支名只能用字母、数字、点、下划线、斜杠或短横线",
|
|
@@ -4459,6 +4461,8 @@ window.__ModuleLoader__.load({
|
|
|
4459
4461
|
"approval.publish.version": "版本",
|
|
4460
4462
|
"approval.publish.author": "作者",
|
|
4461
4463
|
"approval.publish.authorMissing": "未署名",
|
|
4464
|
+
"approval.publish.labels": "标签",
|
|
4465
|
+
"approval.publish.labelsMissing": "还没有(发布到市场时补 1–2 个)",
|
|
4462
4466
|
"approval.publish.owner": "认领人",
|
|
4463
4467
|
"approval.publish.ownerUnowned": "原来没署名",
|
|
4464
4468
|
"approval.publish.ownerTaken": "已有主人:{owner}",
|
|
@@ -13247,6 +13251,11 @@ window.__ModuleLoader__.load({
|
|
|
13247
13251
|
const value = args[key];
|
|
13248
13252
|
return typeof value === "string" ? value.replace(/\s+/g, " ").trim() : "";
|
|
13249
13253
|
}
|
|
13254
|
+
function labelsOf(args) {
|
|
13255
|
+
const value = args["labels"];
|
|
13256
|
+
if (!Array.isArray(value)) return [];
|
|
13257
|
+
return [...new Set(value.flatMap((one) => typeof one === "string" && one.trim() !== "" ? [one.trim()] : []))];
|
|
13258
|
+
}
|
|
13250
13259
|
function recordApprovalRows(args, t) {
|
|
13251
13260
|
const unit = textOf(args, "unit");
|
|
13252
13261
|
const doing = textOf(args, "doing");
|
|
@@ -13318,6 +13327,14 @@ window.__ModuleLoader__.load({
|
|
|
13318
13327
|
value: author !== "" ? author : preview === void 0 ? t("approval.publish.reading") : preview?.author === void 0 || preview.author === "" ? t("approval.publish.authorMissing") : preview.author
|
|
13319
13328
|
}
|
|
13320
13329
|
];
|
|
13330
|
+
if (target === "market" || target === "" && preview?.market !== void 0) {
|
|
13331
|
+
const asked = labelsOf(args);
|
|
13332
|
+
const labels = asked.length > 0 ? asked : preview?.labels ?? [];
|
|
13333
|
+
rows.push({
|
|
13334
|
+
label: t("approval.publish.labels"),
|
|
13335
|
+
value: preview === void 0 && asked.length === 0 ? t("approval.publish.reading") : labels.length === 0 ? t("approval.publish.labelsMissing") : labels.join(" · ")
|
|
13336
|
+
});
|
|
13337
|
+
}
|
|
13321
13338
|
const claim = preview?.claim;
|
|
13322
13339
|
if (claim !== void 0 && claim.state !== "new" && claim.state !== "unknown") {
|
|
13323
13340
|
if (claim.state === "unit-taken") rows.push({
|
|
@@ -3375,7 +3375,7 @@ var en = {
|
|
|
3375
3375
|
"panels.discover.missingIndex": "This repository has no {path} yet.",
|
|
3376
3376
|
"panels.discover.initTitle": "Initialize this repository as a module market index?",
|
|
3377
3377
|
"panels.discover.initCta": "Initialize market index",
|
|
3378
|
-
"panels.discover.initWhat": "It will write the index directory market/ and README.md on {branch}, commit once, and push. Modules you publish from this workbench will commit their build files under artifacts/<package-name
|
|
3378
|
+
"panels.discover.initWhat": "It will write the index directory market/ and README.md on {branch}, commit once, and push. Modules you publish from this workbench will commit their build files under artifacts/<package-name>/ and their entry in market/<package-name>.json. The repository stays owned by its owner.",
|
|
3379
3379
|
"panels.discover.initBranch": "Branch",
|
|
3380
3380
|
"panels.discover.initBranchHint": "The index and build files go to this branch; an empty repository gets it created.",
|
|
3381
3381
|
"panels.discover.initBranchBad": "Use only letters, digits, dots, underscores, slashes, or dashes in a branch name.",
|
|
@@ -3706,6 +3706,8 @@ var en = {
|
|
|
3706
3706
|
"approval.publish.version": "Version",
|
|
3707
3707
|
"approval.publish.author": "Author",
|
|
3708
3708
|
"approval.publish.authorMissing": "unsigned",
|
|
3709
|
+
"approval.publish.labels": "Labels",
|
|
3710
|
+
"approval.publish.labelsMissing": "none yet (1–2 picked on publish)",
|
|
3709
3711
|
"approval.publish.owner": "Owner",
|
|
3710
3712
|
"approval.publish.ownerUnowned": "originally unattributed",
|
|
3711
3713
|
"approval.publish.ownerTaken": "Owned by {owner}",
|
|
@@ -4121,7 +4123,7 @@ var dictionaries = {
|
|
|
4121
4123
|
"panels.discover.missingIndex": "仓库里还没有索引文件 {path}",
|
|
4122
4124
|
"panels.discover.initTitle": "把这个仓库初始化成模块市场索引?",
|
|
4123
4125
|
"panels.discover.initCta": "初始化成市场索引",
|
|
4124
|
-
"panels.discover.initWhat": "会在 {branch} 分支写索引目录 market/ 与 README.md,提交一次并推上去;之后从这个工作台发布的模块会把打包好的文件提交到 artifacts
|
|
4126
|
+
"panels.discover.initWhat": "会在 {branch} 分支写索引目录 market/ 与 README.md,提交一次并推上去;之后从这个工作台发布的模块会把打包好的文件提交到 artifacts/<包名>/,条目写到 market/<包名>.json。仓库的写权限归它的所有者。",
|
|
4125
4127
|
"panels.discover.initBranch": "分支",
|
|
4126
4128
|
"panels.discover.initBranchHint": "索引和打包文件都发到这个分支;空仓库会新建它。",
|
|
4127
4129
|
"panels.discover.initBranchBad": "分支名只能用字母、数字、点、下划线、斜杠或短横线",
|
|
@@ -4452,6 +4454,8 @@ var dictionaries = {
|
|
|
4452
4454
|
"approval.publish.version": "版本",
|
|
4453
4455
|
"approval.publish.author": "作者",
|
|
4454
4456
|
"approval.publish.authorMissing": "未署名",
|
|
4457
|
+
"approval.publish.labels": "标签",
|
|
4458
|
+
"approval.publish.labelsMissing": "还没有(发布到市场时补 1–2 个)",
|
|
4455
4459
|
"approval.publish.owner": "认领人",
|
|
4456
4460
|
"approval.publish.ownerUnowned": "原来没署名",
|
|
4457
4461
|
"approval.publish.ownerTaken": "已有主人:{owner}",
|
|
@@ -13240,6 +13244,11 @@ function textOf(args, key) {
|
|
|
13240
13244
|
const value = args[key];
|
|
13241
13245
|
return typeof value === "string" ? value.replace(/\s+/g, " ").trim() : "";
|
|
13242
13246
|
}
|
|
13247
|
+
function labelsOf(args) {
|
|
13248
|
+
const value = args["labels"];
|
|
13249
|
+
if (!Array.isArray(value)) return [];
|
|
13250
|
+
return [...new Set(value.flatMap((one) => typeof one === "string" && one.trim() !== "" ? [one.trim()] : []))];
|
|
13251
|
+
}
|
|
13243
13252
|
function recordApprovalRows(args, t) {
|
|
13244
13253
|
const unit = textOf(args, "unit");
|
|
13245
13254
|
const doing = textOf(args, "doing");
|
|
@@ -13311,6 +13320,14 @@ function publishRows(args, preview, t) {
|
|
|
13311
13320
|
value: author !== "" ? author : preview === void 0 ? t("approval.publish.reading") : preview?.author === void 0 || preview.author === "" ? t("approval.publish.authorMissing") : preview.author
|
|
13312
13321
|
}
|
|
13313
13322
|
];
|
|
13323
|
+
if (target === "market" || target === "" && preview?.market !== void 0) {
|
|
13324
|
+
const asked = labelsOf(args);
|
|
13325
|
+
const labels = asked.length > 0 ? asked : preview?.labels ?? [];
|
|
13326
|
+
rows.push({
|
|
13327
|
+
label: t("approval.publish.labels"),
|
|
13328
|
+
value: preview === void 0 && asked.length === 0 ? t("approval.publish.reading") : labels.length === 0 ? t("approval.publish.labelsMissing") : labels.join(" · ")
|
|
13329
|
+
});
|
|
13330
|
+
}
|
|
13314
13331
|
const claim = preview?.claim;
|
|
13315
13332
|
if (claim !== void 0 && claim.state !== "new" && claim.state !== "unknown") {
|
|
13316
13333
|
if (claim.state === "unit-taken") rows.push({
|
package/dist/client/index.js
CHANGED
|
@@ -3378,7 +3378,7 @@ var en = {
|
|
|
3378
3378
|
"panels.discover.missingIndex": "This repository has no {path} yet.",
|
|
3379
3379
|
"panels.discover.initTitle": "Initialize this repository as a module market index?",
|
|
3380
3380
|
"panels.discover.initCta": "Initialize market index",
|
|
3381
|
-
"panels.discover.initWhat": "It will write the index directory market/ and README.md on {branch}, commit once, and push. Modules you publish from this workbench will commit their build files under artifacts/<package-name
|
|
3381
|
+
"panels.discover.initWhat": "It will write the index directory market/ and README.md on {branch}, commit once, and push. Modules you publish from this workbench will commit their build files under artifacts/<package-name>/ and their entry in market/<package-name>.json. The repository stays owned by its owner.",
|
|
3382
3382
|
"panels.discover.initBranch": "Branch",
|
|
3383
3383
|
"panels.discover.initBranchHint": "The index and build files go to this branch; an empty repository gets it created.",
|
|
3384
3384
|
"panels.discover.initBranchBad": "Use only letters, digits, dots, underscores, slashes, or dashes in a branch name.",
|
|
@@ -3709,6 +3709,8 @@ var en = {
|
|
|
3709
3709
|
"approval.publish.version": "Version",
|
|
3710
3710
|
"approval.publish.author": "Author",
|
|
3711
3711
|
"approval.publish.authorMissing": "unsigned",
|
|
3712
|
+
"approval.publish.labels": "Labels",
|
|
3713
|
+
"approval.publish.labelsMissing": "none yet (1–2 picked on publish)",
|
|
3712
3714
|
"approval.publish.owner": "Owner",
|
|
3713
3715
|
"approval.publish.ownerUnowned": "originally unattributed",
|
|
3714
3716
|
"approval.publish.ownerTaken": "Owned by {owner}",
|
|
@@ -4124,7 +4126,7 @@ var dictionaries = {
|
|
|
4124
4126
|
"panels.discover.missingIndex": "仓库里还没有索引文件 {path}",
|
|
4125
4127
|
"panels.discover.initTitle": "把这个仓库初始化成模块市场索引?",
|
|
4126
4128
|
"panels.discover.initCta": "初始化成市场索引",
|
|
4127
|
-
"panels.discover.initWhat": "会在 {branch} 分支写索引目录 market/ 与 README.md,提交一次并推上去;之后从这个工作台发布的模块会把打包好的文件提交到 artifacts
|
|
4129
|
+
"panels.discover.initWhat": "会在 {branch} 分支写索引目录 market/ 与 README.md,提交一次并推上去;之后从这个工作台发布的模块会把打包好的文件提交到 artifacts/<包名>/,条目写到 market/<包名>.json。仓库的写权限归它的所有者。",
|
|
4128
4130
|
"panels.discover.initBranch": "分支",
|
|
4129
4131
|
"panels.discover.initBranchHint": "索引和打包文件都发到这个分支;空仓库会新建它。",
|
|
4130
4132
|
"panels.discover.initBranchBad": "分支名只能用字母、数字、点、下划线、斜杠或短横线",
|
|
@@ -4455,6 +4457,8 @@ var dictionaries = {
|
|
|
4455
4457
|
"approval.publish.version": "版本",
|
|
4456
4458
|
"approval.publish.author": "作者",
|
|
4457
4459
|
"approval.publish.authorMissing": "未署名",
|
|
4460
|
+
"approval.publish.labels": "标签",
|
|
4461
|
+
"approval.publish.labelsMissing": "还没有(发布到市场时补 1–2 个)",
|
|
4458
4462
|
"approval.publish.owner": "认领人",
|
|
4459
4463
|
"approval.publish.ownerUnowned": "原来没署名",
|
|
4460
4464
|
"approval.publish.ownerTaken": "已有主人:{owner}",
|
|
@@ -13243,6 +13247,11 @@ function textOf(args, key) {
|
|
|
13243
13247
|
const value = args[key];
|
|
13244
13248
|
return typeof value === "string" ? value.replace(/\s+/g, " ").trim() : "";
|
|
13245
13249
|
}
|
|
13250
|
+
function labelsOf(args) {
|
|
13251
|
+
const value = args["labels"];
|
|
13252
|
+
if (!Array.isArray(value)) return [];
|
|
13253
|
+
return [...new Set(value.flatMap((one) => typeof one === "string" && one.trim() !== "" ? [one.trim()] : []))];
|
|
13254
|
+
}
|
|
13246
13255
|
function recordApprovalRows(args, t) {
|
|
13247
13256
|
const unit = textOf(args, "unit");
|
|
13248
13257
|
const doing = textOf(args, "doing");
|
|
@@ -13314,6 +13323,14 @@ function publishRows(args, preview, t) {
|
|
|
13314
13323
|
value: author !== "" ? author : preview === void 0 ? t("approval.publish.reading") : preview?.author === void 0 || preview.author === "" ? t("approval.publish.authorMissing") : preview.author
|
|
13315
13324
|
}
|
|
13316
13325
|
];
|
|
13326
|
+
if (target === "market" || target === "" && preview?.market !== void 0) {
|
|
13327
|
+
const asked = labelsOf(args);
|
|
13328
|
+
const labels = asked.length > 0 ? asked : preview?.labels ?? [];
|
|
13329
|
+
rows.push({
|
|
13330
|
+
label: t("approval.publish.labels"),
|
|
13331
|
+
value: preview === void 0 && asked.length === 0 ? t("approval.publish.reading") : labels.length === 0 ? t("approval.publish.labelsMissing") : labels.join(" · ")
|
|
13332
|
+
});
|
|
13333
|
+
}
|
|
13317
13334
|
const claim = preview?.claim;
|
|
13318
13335
|
if (claim !== void 0 && claim.state !== "new" && claim.state !== "unknown") {
|
|
13319
13336
|
if (claim.state === "unit-taken") rows.push({
|
package/dist/host/index.js
CHANGED
|
@@ -5007,6 +5007,84 @@ var MARKET_PUBLISH_PREVIEW_ROUTE = "panels/market-publish-preview";
|
|
|
5007
5007
|
var MARKET_SOURCES_RESOURCE = "market-sources";
|
|
5008
5008
|
var MARKET_SOURCES_ROUTE = "panels/market-sources";
|
|
5009
5009
|
//#endregion
|
|
5010
|
+
//#region ../shared/dist/host/market-index-claim.js
|
|
5011
|
+
function foldedName(name) {
|
|
5012
|
+
return name.replace(/\s+/gu, " ").trim().toLowerCase();
|
|
5013
|
+
}
|
|
5014
|
+
function publisherIdentityOf(text) {
|
|
5015
|
+
const raw = (text ?? "").trim();
|
|
5016
|
+
if (raw === "") return void 0;
|
|
5017
|
+
const match = /^(.*?)\s*<([^<>]*)>\s*$/u.exec(raw);
|
|
5018
|
+
const name = (match === null ? raw : match[1]).trim();
|
|
5019
|
+
const email = match === null ? "" : match[2].trim().toLowerCase();
|
|
5020
|
+
if (name === "") return void 0;
|
|
5021
|
+
return email === "" ? { name } : {
|
|
5022
|
+
name,
|
|
5023
|
+
email
|
|
5024
|
+
};
|
|
5025
|
+
}
|
|
5026
|
+
function samePublisher(left, right) {
|
|
5027
|
+
const a = publisherIdentityOf(left);
|
|
5028
|
+
const b = publisherIdentityOf(right);
|
|
5029
|
+
if (a === void 0 || b === void 0) return false;
|
|
5030
|
+
if (a.email !== void 0 && b.email !== void 0) return a.email === b.email;
|
|
5031
|
+
return foldedName(a.name) === foldedName(b.name);
|
|
5032
|
+
}
|
|
5033
|
+
function entryOwnerOf(entry) {
|
|
5034
|
+
const owner = (entry.owner ?? "").trim();
|
|
5035
|
+
if (owner !== "") return owner;
|
|
5036
|
+
const author = (entry.author ?? "").trim();
|
|
5037
|
+
return author === "" ? void 0 : author;
|
|
5038
|
+
}
|
|
5039
|
+
function claimOfEntry(entry, publisher) {
|
|
5040
|
+
if (entry === void 0) return { state: "new" };
|
|
5041
|
+
const owner = entryOwnerOf(entry);
|
|
5042
|
+
if (owner === void 0) return { state: "unowned" };
|
|
5043
|
+
if (publisher === void 0 || publisher.trim() === "") return { state: "unknown" };
|
|
5044
|
+
return samePublisher(owner, publisher) ? {
|
|
5045
|
+
state: "owned",
|
|
5046
|
+
owner
|
|
5047
|
+
} : {
|
|
5048
|
+
state: "conflict",
|
|
5049
|
+
owner
|
|
5050
|
+
};
|
|
5051
|
+
}
|
|
5052
|
+
function marketArtifactRoot(name) {
|
|
5053
|
+
return `${MARKET_ARTIFACTS_DIR}/${name}`;
|
|
5054
|
+
}
|
|
5055
|
+
function entryUnitOf(entry) {
|
|
5056
|
+
const unit = entry.metadata?.unit?.trim();
|
|
5057
|
+
if (unit !== void 0 && unit !== "") return unit;
|
|
5058
|
+
for (const version of entry.versions) {
|
|
5059
|
+
if (version.source.type !== "git") continue;
|
|
5060
|
+
const legacy = /^packages\/([^/]+)$/u.exec(version.source.path ?? "")?.[1];
|
|
5061
|
+
if (legacy !== void 0) return legacy;
|
|
5062
|
+
}
|
|
5063
|
+
}
|
|
5064
|
+
function claimOf(index, input) {
|
|
5065
|
+
const base = claimOfEntry(index.plugins.find((one) => one.name === input.name), input.publisher);
|
|
5066
|
+
if (base.state === "conflict" || base.state === "unknown") return base;
|
|
5067
|
+
const unit = (input.unit ?? "").trim();
|
|
5068
|
+
if (unit !== "") for (const other of index.plugins) {
|
|
5069
|
+
if (other.name === input.name) continue;
|
|
5070
|
+
if (entryUnitOf(other) !== unit) continue;
|
|
5071
|
+
return {
|
|
5072
|
+
state: "unit-taken",
|
|
5073
|
+
entry: other.name
|
|
5074
|
+
};
|
|
5075
|
+
}
|
|
5076
|
+
const path = (input.artifactPath ?? "").trim();
|
|
5077
|
+
if (path !== "") for (const other of index.plugins) {
|
|
5078
|
+
if (other.name === input.name) continue;
|
|
5079
|
+
if (!other.versions.some((one) => one.source.type === "git" && (one.source.path ?? "") === path)) continue;
|
|
5080
|
+
return {
|
|
5081
|
+
state: "path-taken",
|
|
5082
|
+
entry: other.name
|
|
5083
|
+
};
|
|
5084
|
+
}
|
|
5085
|
+
return base;
|
|
5086
|
+
}
|
|
5087
|
+
//#endregion
|
|
5010
5088
|
//#region ../shared/dist/lib/market-index.js
|
|
5011
5089
|
var BRANCH = /^[A-Za-z0-9][A-Za-z0-9._/-]*$/;
|
|
5012
5090
|
function marketBranchOk(value) {
|
|
@@ -5363,115 +5441,49 @@ function parseSourceConfig(raw) {
|
|
|
5363
5441
|
}
|
|
5364
5442
|
};
|
|
5365
5443
|
}
|
|
5366
|
-
function
|
|
5367
|
-
|
|
5368
|
-
if (name === "" || name.length > 214 || !NPM_NAME.test(name)) return problem$1("name", `不是合法 npm 包名:${JSON.stringify(name)}`, at);
|
|
5369
|
-
const icon = asText$4(record["icon"]);
|
|
5370
|
-
if (icon !== "") {
|
|
5371
|
-
const badIcon = iconProblem(icon);
|
|
5372
|
-
if (badIcon !== void 0) return badIcon;
|
|
5373
|
-
}
|
|
5374
|
-
const owner = asText$4(record["owner"]);
|
|
5375
|
-
if (owner !== "") {
|
|
5376
|
-
const badOwner = ownerProblem(owner);
|
|
5377
|
-
if (badOwner !== void 0) return badOwner;
|
|
5378
|
-
}
|
|
5379
|
-
const metadata = metadataOf(record["metadata"]);
|
|
5380
|
-
if (metadata?.unit !== void 0 && !UNIT_ID.test(metadata.unit)) return problem$1("unit", `metadata.unit 只能是小写字母开头的 a-z0-9-(现在是 ${JSON.stringify(metadata.unit)})`, at);
|
|
5381
|
-
const title = asLocalized(record["title"]);
|
|
5382
|
-
const description = asLocalized(record["description"]);
|
|
5383
|
-
const author = asText$4(record["author"]);
|
|
5384
|
-
const homepage = asText$4(record["homepage"]);
|
|
5385
|
-
return {
|
|
5386
|
-
name,
|
|
5387
|
-
...title === void 0 ? {} : { title },
|
|
5388
|
-
...description === void 0 ? {} : { description },
|
|
5389
|
-
...author === "" ? {} : { author },
|
|
5390
|
-
...owner === "" ? {} : { owner },
|
|
5391
|
-
...homepage === "" ? {} : { homepage },
|
|
5392
|
-
...icon === "" ? {} : { icon },
|
|
5393
|
-
...metadata === void 0 ? {} : { metadata }
|
|
5394
|
-
};
|
|
5444
|
+
function indexPathBase(dir) {
|
|
5445
|
+
return dir.replace(/^\/+|\/+$/g, "") || "market";
|
|
5395
5446
|
}
|
|
5396
|
-
function
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
problems: [fields]
|
|
5406
|
-
};
|
|
5407
|
-
const version = asText$4(record["version"]);
|
|
5408
|
-
const timestamp = record["publishTimestamp"];
|
|
5409
|
-
if (timestamp !== void 0 && (!Number.isInteger(timestamp) || timestamp < 0)) return {
|
|
5410
|
-
ok: false,
|
|
5411
|
-
problems: [problem$1("timestamp", "publishTimestamp 必须是 Unix 秒整数", "entry")]
|
|
5412
|
-
};
|
|
5413
|
-
if (version === "") {
|
|
5414
|
-
if (timestamp === void 0) return {
|
|
5415
|
-
ok: false,
|
|
5416
|
-
problems: [problem$1("timestamp", "元数据文件要有 publishTimestamp", "entry")]
|
|
5417
|
-
};
|
|
5418
|
-
const epoch = record["epoch"];
|
|
5419
|
-
if (epoch !== void 0 && (!Number.isInteger(epoch) || epoch < 0)) return {
|
|
5420
|
-
ok: false,
|
|
5421
|
-
problems: [problem$1("timestamp", "epoch 必须是非负整数", "entry")]
|
|
5422
|
-
};
|
|
5447
|
+
function marketEntryPath(dir, name) {
|
|
5448
|
+
if (!NPM_NAME.test(name)) throw new Error(`不是合法包名:${JSON.stringify(name)}`);
|
|
5449
|
+
return `${indexPathBase(dir)}/${name}.json`;
|
|
5450
|
+
}
|
|
5451
|
+
function parseMarketEntryJson(text) {
|
|
5452
|
+
let raw;
|
|
5453
|
+
try {
|
|
5454
|
+
raw = JSON.parse(text);
|
|
5455
|
+
} catch (error) {
|
|
5423
5456
|
return {
|
|
5424
|
-
ok:
|
|
5425
|
-
|
|
5426
|
-
...fields,
|
|
5427
|
-
publishTimestamp: timestamp,
|
|
5428
|
-
...epoch === void 0 ? {} : { epoch }
|
|
5429
|
-
}
|
|
5457
|
+
ok: false,
|
|
5458
|
+
problems: [problem$1("not-json", `JSON 解析失败:${error instanceof Error ? error.message : String(error)}`, "entry")]
|
|
5430
5459
|
};
|
|
5431
5460
|
}
|
|
5432
|
-
|
|
5461
|
+
const parsed = entryOf$1(raw, "entry");
|
|
5462
|
+
if ("kind" in parsed) return {
|
|
5433
5463
|
ok: false,
|
|
5434
|
-
problems: [
|
|
5464
|
+
problems: [parsed]
|
|
5435
5465
|
};
|
|
5436
|
-
const source = sourceOf(record["source"], "entry.source");
|
|
5437
|
-
if ("kind" in source) return {
|
|
5438
|
-
ok: false,
|
|
5439
|
-
problems: [source]
|
|
5440
|
-
};
|
|
5441
|
-
const engines = asRecord$4(record["engines"]);
|
|
5442
|
-
const dsh = engines === void 0 ? "" : asText$4(engines["dsh"]);
|
|
5443
5466
|
return {
|
|
5444
5467
|
ok: true,
|
|
5445
|
-
|
|
5446
|
-
...fields,
|
|
5447
|
-
version,
|
|
5448
|
-
source,
|
|
5449
|
-
...timestamp === void 0 ? {} : { publishTimestamp: timestamp },
|
|
5450
|
-
...dsh === "" ? {} : { engines: { dsh } }
|
|
5451
|
-
}
|
|
5468
|
+
entry: parsed
|
|
5452
5469
|
};
|
|
5453
5470
|
}
|
|
5454
|
-
function indexPathBase(dir) {
|
|
5455
|
-
return dir.replace(/^\/+|\/+$/g, "") || "market";
|
|
5456
|
-
}
|
|
5457
|
-
function marketEntryPath(dir, name, version) {
|
|
5458
|
-
if (!NPM_NAME.test(name)) throw new Error(`不是合法包名:${JSON.stringify(name)}`);
|
|
5459
|
-
if (!isValidVersion(version)) throw new Error(`不是合法版本号:${JSON.stringify(version)}`);
|
|
5460
|
-
return `${indexPathBase(dir)}/${name}/${version}.json`;
|
|
5461
|
-
}
|
|
5462
5471
|
//#endregion
|
|
5463
5472
|
//#region ../shared/dist/host/market-index.js
|
|
5464
5473
|
var MARKET_ENTRIES_README_LINES = [
|
|
5465
5474
|
"# 索引目录",
|
|
5466
5475
|
"",
|
|
5467
|
-
"
|
|
5476
|
+
"一个包一个文件:`market/<包名>.json`,里面是这一个包的元数据与所有版本;",
|
|
5477
|
+
"",
|
|
5478
|
+
"产物在 `artifacts/<包名>/`(只放最新一版,老版本按条目里的 commit 取历史)。",
|
|
5468
5479
|
"",
|
|
5469
|
-
"
|
|
5480
|
+
"发布时只改自己包的文件;包与包之间不共享文件。"
|
|
5470
5481
|
];
|
|
5471
5482
|
var MARKET_INDEX_README_LINES = [
|
|
5472
5483
|
"# 模块市场索引",
|
|
5473
5484
|
"",
|
|
5474
|
-
"这个仓库给 DeepSeek Harness
|
|
5485
|
+
"这个仓库给 DeepSeek Harness 工作台当模块市场索引:一个包一个文件 `market/<包名>.json`,",
|
|
5486
|
+
"产物在 `artifacts/<包名>/`;老仓库的 `market.json` 会在第一次发布时自动拆开。",
|
|
5475
5487
|
"",
|
|
5476
5488
|
"## 发布模块",
|
|
5477
5489
|
"",
|
|
@@ -5481,8 +5493,7 @@ var MARKET_INDEX_README_LINES = [
|
|
|
5481
5493
|
"dsh-wb-module release --index <本仓库地址> --index-policy artifacts-in-repo",
|
|
5482
5494
|
"```",
|
|
5483
5495
|
"",
|
|
5484
|
-
"
|
|
5485
|
-
"发布只新增文件、不改已有文件,两台机器同时发也不会冲突;老条目的 `packages/<包名>/` 路径继续可用。",
|
|
5496
|
+
"发布只会改自己包的那一个文件;包与包之间不会碰同一个文件。",
|
|
5486
5497
|
"",
|
|
5487
5498
|
"一个包名归第一次发布的人(条目文件里的 `owner`)。换一个署名发同名会被拒;要换人,先把这一条的 `owner` 改成新的人。",
|
|
5488
5499
|
"同一个市场里,一个模块 id(`metadata.unit`)只能被一个条目使用;另一个包名想用同一个 id / 产物目录也会被拒。",
|
|
@@ -5499,37 +5510,13 @@ function problem(kind, detail, at) {
|
|
|
5499
5510
|
...at === void 0 ? {} : { at }
|
|
5500
5511
|
};
|
|
5501
5512
|
}
|
|
5502
|
-
function docFieldsFromEntry(entry) {
|
|
5503
|
-
return {
|
|
5504
|
-
name: entry.name,
|
|
5505
|
-
...entry.title === void 0 ? {} : { title: entry.title },
|
|
5506
|
-
...entry.description === void 0 ? {} : { description: entry.description },
|
|
5507
|
-
...entry.author === void 0 ? {} : { author: entry.author },
|
|
5508
|
-
...entry.owner === void 0 ? {} : { owner: entry.owner },
|
|
5509
|
-
...entry.homepage === void 0 ? {} : { homepage: entry.homepage },
|
|
5510
|
-
...entry.icon === void 0 ? {} : { icon: entry.icon },
|
|
5511
|
-
...entry.metadata === void 0 ? {} : { metadata: entry.metadata }
|
|
5512
|
-
};
|
|
5513
|
-
}
|
|
5514
|
-
function marketVersionDocOf(entry, version) {
|
|
5515
|
-
return {
|
|
5516
|
-
...docFieldsFromEntry(entry),
|
|
5517
|
-
...version
|
|
5518
|
-
};
|
|
5519
|
-
}
|
|
5520
5513
|
function assembleMarketIndex(files) {
|
|
5521
5514
|
const problems = [];
|
|
5522
|
-
const
|
|
5515
|
+
const entries = /* @__PURE__ */ new Map();
|
|
5523
5516
|
const ordered = [...files].sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
|
|
5524
5517
|
for (const file of ordered) {
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
raw = JSON.parse(file.text);
|
|
5528
|
-
} catch (error) {
|
|
5529
|
-
problems.push(problem("not-json", `JSON 解析失败:${error instanceof Error ? error.message : String(error)}`, file.path));
|
|
5530
|
-
continue;
|
|
5531
|
-
}
|
|
5532
|
-
const parsed = parseMarketEntryDoc(raw);
|
|
5518
|
+
if (!file.path.endsWith(".json")) continue;
|
|
5519
|
+
const parsed = parseMarketEntryJson(file.text);
|
|
5533
5520
|
if (!parsed.ok) {
|
|
5534
5521
|
for (const one of parsed.problems) problems.push({
|
|
5535
5522
|
...one,
|
|
@@ -5537,71 +5524,47 @@ function assembleMarketIndex(files) {
|
|
|
5537
5524
|
});
|
|
5538
5525
|
continue;
|
|
5539
5526
|
}
|
|
5540
|
-
const
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
fallback: void 0
|
|
5545
|
-
};
|
|
5546
|
-
const at = doc.publishTimestamp ?? 0;
|
|
5547
|
-
if ("version" in doc) {
|
|
5548
|
-
if (group.versions.has(doc.version)) problems.push(problem("duplicate-version", `版本重复:${doc.version}`, file.path));
|
|
5549
|
-
group.versions.set(doc.version, {
|
|
5550
|
-
version: doc.version,
|
|
5551
|
-
source: doc.source,
|
|
5552
|
-
...doc.publishTimestamp === void 0 ? {} : { publishTimestamp: doc.publishTimestamp },
|
|
5553
|
-
...doc.engines === void 0 ? {} : { engines: doc.engines }
|
|
5554
|
-
});
|
|
5555
|
-
if (group.fallback === void 0 || at > group.fallback.at || at === group.fallback.at && file.path > group.fallback.path) group.fallback = {
|
|
5556
|
-
at,
|
|
5557
|
-
path: file.path,
|
|
5558
|
-
doc
|
|
5559
|
-
};
|
|
5560
|
-
} else {
|
|
5561
|
-
const epoch = doc.epoch ?? 0;
|
|
5562
|
-
if (group.meta === void 0 || epoch > group.meta.epoch || epoch === group.meta.epoch && at > group.meta.at || epoch === group.meta.epoch && at === group.meta.at && file.path > group.meta.path) group.meta = {
|
|
5563
|
-
epoch,
|
|
5564
|
-
at,
|
|
5565
|
-
path: file.path,
|
|
5566
|
-
doc
|
|
5567
|
-
};
|
|
5527
|
+
const entry = parsed.entry;
|
|
5528
|
+
if (entries.has(entry.name)) {
|
|
5529
|
+
problems.push(problem("duplicate-name", `插件名重复:${entry.name}`, file.path));
|
|
5530
|
+
continue;
|
|
5568
5531
|
}
|
|
5569
|
-
|
|
5532
|
+
entries.set(entry.name, {
|
|
5533
|
+
...entry,
|
|
5534
|
+
versions: sortMarketVersions(entry.versions)
|
|
5535
|
+
});
|
|
5570
5536
|
}
|
|
5571
5537
|
if (problems.length > 0) return {
|
|
5572
5538
|
ok: false,
|
|
5573
5539
|
problems
|
|
5574
5540
|
};
|
|
5575
|
-
const plugins = [...groups.entries()].map(([name, group]) => {
|
|
5576
|
-
const meta = group.meta?.doc ?? group.fallback?.doc;
|
|
5577
|
-
return {
|
|
5578
|
-
name,
|
|
5579
|
-
versions: sortMarketVersions([...group.versions.values()]),
|
|
5580
|
-
...meta?.title === void 0 ? {} : { title: meta.title },
|
|
5581
|
-
...meta?.description === void 0 ? {} : { description: meta.description },
|
|
5582
|
-
...meta?.author === void 0 ? {} : { author: meta.author },
|
|
5583
|
-
...meta?.owner === void 0 ? {} : { owner: meta.owner },
|
|
5584
|
-
...meta?.homepage === void 0 ? {} : { homepage: meta.homepage },
|
|
5585
|
-
...meta?.icon === void 0 ? {} : { icon: meta.icon },
|
|
5586
|
-
...meta?.metadata === void 0 ? {} : { metadata: meta.metadata }
|
|
5587
|
-
};
|
|
5588
|
-
});
|
|
5589
|
-
plugins.sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0);
|
|
5590
5541
|
return {
|
|
5591
5542
|
ok: true,
|
|
5592
5543
|
index: {
|
|
5593
5544
|
format: 1,
|
|
5594
|
-
plugins
|
|
5545
|
+
plugins: [...entries.values()].sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0)
|
|
5595
5546
|
}
|
|
5596
5547
|
};
|
|
5597
5548
|
}
|
|
5549
|
+
function marketEntryFileOf(entry, dir = MARKET_INDEX_DIR) {
|
|
5550
|
+
return {
|
|
5551
|
+
path: marketEntryPath(dir, entry.name),
|
|
5552
|
+
text: `${JSON.stringify(entry, null, 2)}\n`
|
|
5553
|
+
};
|
|
5554
|
+
}
|
|
5598
5555
|
function marketEntryFilesOf(index, dir = MARKET_INDEX_DIR) {
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
return
|
|
5556
|
+
return index.plugins.map((entry) => marketEntryFileOf(healedUnit(entry), dir));
|
|
5557
|
+
}
|
|
5558
|
+
function healedUnit(entry) {
|
|
5559
|
+
if (entry.metadata?.unit !== void 0) return entry;
|
|
5560
|
+
const unit = entryUnitOf(entry);
|
|
5561
|
+
return unit === void 0 ? entry : {
|
|
5562
|
+
...entry,
|
|
5563
|
+
metadata: {
|
|
5564
|
+
...entry.metadata,
|
|
5565
|
+
unit
|
|
5566
|
+
}
|
|
5567
|
+
};
|
|
5605
5568
|
}
|
|
5606
5569
|
function collectMarketEntryFiles(dir) {
|
|
5607
5570
|
if (!existsSync(dir)) return [];
|
|
@@ -5629,87 +5592,6 @@ function marketEntryFilesOfLegacy(text, dir = MARKET_INDEX_DIR) {
|
|
|
5629
5592
|
return marketEntryFilesOf(parsed.index, dir);
|
|
5630
5593
|
}
|
|
5631
5594
|
//#endregion
|
|
5632
|
-
//#region ../shared/dist/host/market-index-claim.js
|
|
5633
|
-
function foldedName(name) {
|
|
5634
|
-
return name.replace(/\s+/gu, " ").trim().toLowerCase();
|
|
5635
|
-
}
|
|
5636
|
-
function publisherIdentityOf(text) {
|
|
5637
|
-
const raw = (text ?? "").trim();
|
|
5638
|
-
if (raw === "") return void 0;
|
|
5639
|
-
const match = /^(.*?)\s*<([^<>]*)>\s*$/u.exec(raw);
|
|
5640
|
-
const name = (match === null ? raw : match[1]).trim();
|
|
5641
|
-
const email = match === null ? "" : match[2].trim().toLowerCase();
|
|
5642
|
-
if (name === "") return void 0;
|
|
5643
|
-
return email === "" ? { name } : {
|
|
5644
|
-
name,
|
|
5645
|
-
email
|
|
5646
|
-
};
|
|
5647
|
-
}
|
|
5648
|
-
function samePublisher(left, right) {
|
|
5649
|
-
const a = publisherIdentityOf(left);
|
|
5650
|
-
const b = publisherIdentityOf(right);
|
|
5651
|
-
if (a === void 0 || b === void 0) return false;
|
|
5652
|
-
if (a.email !== void 0 && b.email !== void 0) return a.email === b.email;
|
|
5653
|
-
return foldedName(a.name) === foldedName(b.name);
|
|
5654
|
-
}
|
|
5655
|
-
function entryOwnerOf(entry) {
|
|
5656
|
-
const owner = (entry.owner ?? "").trim();
|
|
5657
|
-
if (owner !== "") return owner;
|
|
5658
|
-
const author = (entry.author ?? "").trim();
|
|
5659
|
-
return author === "" ? void 0 : author;
|
|
5660
|
-
}
|
|
5661
|
-
function claimOfEntry(entry, publisher) {
|
|
5662
|
-
if (entry === void 0) return { state: "new" };
|
|
5663
|
-
const owner = entryOwnerOf(entry);
|
|
5664
|
-
if (owner === void 0) return { state: "unowned" };
|
|
5665
|
-
if (publisher === void 0 || publisher.trim() === "") return { state: "unknown" };
|
|
5666
|
-
return samePublisher(owner, publisher) ? {
|
|
5667
|
-
state: "owned",
|
|
5668
|
-
owner
|
|
5669
|
-
} : {
|
|
5670
|
-
state: "conflict",
|
|
5671
|
-
owner
|
|
5672
|
-
};
|
|
5673
|
-
}
|
|
5674
|
-
function marketArtifactRoot(name) {
|
|
5675
|
-
return `${MARKET_ARTIFACTS_DIR}/${name}`;
|
|
5676
|
-
}
|
|
5677
|
-
function marketArtifactPathFor(name, version) {
|
|
5678
|
-
return `${MARKET_ARTIFACTS_DIR}/${name}/${version}`;
|
|
5679
|
-
}
|
|
5680
|
-
function entryUnitOf(entry) {
|
|
5681
|
-
const unit = entry.metadata?.unit?.trim();
|
|
5682
|
-
if (unit !== void 0 && unit !== "") return unit;
|
|
5683
|
-
for (const version of entry.versions) {
|
|
5684
|
-
if (version.source.type !== "git") continue;
|
|
5685
|
-
const legacy = /^packages\/([^/]+)$/u.exec(version.source.path ?? "")?.[1];
|
|
5686
|
-
if (legacy !== void 0) return legacy;
|
|
5687
|
-
}
|
|
5688
|
-
}
|
|
5689
|
-
function claimOf(index, input) {
|
|
5690
|
-
const base = claimOfEntry(index.plugins.find((one) => one.name === input.name), input.publisher);
|
|
5691
|
-
if (base.state === "conflict" || base.state === "unknown") return base;
|
|
5692
|
-
const unit = (input.unit ?? "").trim();
|
|
5693
|
-
if (unit !== "") for (const other of index.plugins) {
|
|
5694
|
-
if (other.name === input.name) continue;
|
|
5695
|
-
if (entryUnitOf(other) !== unit) continue;
|
|
5696
|
-
return {
|
|
5697
|
-
state: "unit-taken",
|
|
5698
|
-
entry: other.name
|
|
5699
|
-
};
|
|
5700
|
-
}
|
|
5701
|
-
const path = (input.artifactPath ?? "").trim();
|
|
5702
|
-
if (path !== "") for (const other of index.plugins) {
|
|
5703
|
-
if (other.name === input.name) continue;
|
|
5704
|
-
if (!other.versions.some((one) => one.source.type === "git" && (one.source.path ?? "") === path)) continue;
|
|
5705
|
-
return {
|
|
5706
|
-
state: "path-taken",
|
|
5707
|
-
entry: other.name
|
|
5708
|
-
};
|
|
5709
|
-
}
|
|
5710
|
-
return base;
|
|
5711
|
-
}
|
|
5712
|
-
//#endregion
|
|
5713
5595
|
//#region ../shared/dist/host/changelog.js
|
|
5714
5596
|
var CHANGELOG_FILE = "CHANGELOG.md";
|
|
5715
5597
|
var CHANGELOG_KINDS = [
|
|
@@ -6823,6 +6705,36 @@ function publishClaimDenyOf(claim, name) {
|
|
|
6823
6705
|
if (claim.state === "conflict") return `市场里 ${name} 已经有主了(${claim.owner})—— 同一个名字不能换人发。换一个带团队 scope 的包名;你就是原来的作者(只是换了机器或署名),用 author 参数带上原来的署名;确实是接手,让索引维护者改 market/<包名>/ 条目文件里的 owner。`;
|
|
6824
6706
|
}
|
|
6825
6707
|
//#endregion
|
|
6708
|
+
//#region src/modules/panels/model/approval-questions.ts
|
|
6709
|
+
function copiesOf(label, labelEn) {
|
|
6710
|
+
return {
|
|
6711
|
+
team: {
|
|
6712
|
+
zh: `把${label}发到团队源,只发构建产物,不发源码,允许吗?`,
|
|
6713
|
+
en: `Publish ${labelEn} to the team registry; only built artifacts, never the source. Allow?`
|
|
6714
|
+
},
|
|
6715
|
+
public: {
|
|
6716
|
+
zh: `把${label}公开发到 npm,任何人都能安装,允许吗?`,
|
|
6717
|
+
en: `Publish ${labelEn} publicly to npm; anyone can install it. Allow?`
|
|
6718
|
+
},
|
|
6719
|
+
tarball: {
|
|
6720
|
+
zh: `给${label}打一个安装包,只写本机不发源码,允许吗?`,
|
|
6721
|
+
en: `Pack ${labelEn} into a local tarball; nothing leaves this machine. Allow?`
|
|
6722
|
+
},
|
|
6723
|
+
git: {
|
|
6724
|
+
zh: `把${label}提交并推到 git,源码也会一起推送,允许吗?`,
|
|
6725
|
+
en: `Commit and push ${labelEn} to git; the source is pushed too. Allow?`
|
|
6726
|
+
},
|
|
6727
|
+
market: {
|
|
6728
|
+
zh: `把${label}发到市场仓库,产物与索引一起提交,允许吗?`,
|
|
6729
|
+
en: `Publish ${labelEn} to the market repository; artifacts and the index are committed together. Allow?`
|
|
6730
|
+
},
|
|
6731
|
+
local: {
|
|
6732
|
+
zh: `把${label}留在本机,不发,允许吗?`,
|
|
6733
|
+
en: `Keep ${labelEn} local and publish nothing. Allow?`
|
|
6734
|
+
}
|
|
6735
|
+
};
|
|
6736
|
+
}
|
|
6737
|
+
//#endregion
|
|
6826
6738
|
//#region src/modules/panels/model/approval.ts
|
|
6827
6739
|
var SPEC_LIMIT = 80;
|
|
6828
6740
|
var TARGET_LIMIT = 20;
|
|
@@ -6908,6 +6820,11 @@ function clipped$1(text) {
|
|
|
6908
6820
|
const chars = [...text];
|
|
6909
6821
|
return chars.length > TARGET_LIMIT ? `${chars.slice(0, TARGET_LIMIT).join("")}…` : text;
|
|
6910
6822
|
}
|
|
6823
|
+
function labelsOfArgs(raw) {
|
|
6824
|
+
const value = raw["labels"];
|
|
6825
|
+
if (!Array.isArray(value)) return [];
|
|
6826
|
+
return [...new Set(value.flatMap((one) => typeof one === "string" && one.trim() !== "" ? [one.trim()] : []))];
|
|
6827
|
+
}
|
|
6911
6828
|
function stopVerdict(call, runs) {
|
|
6912
6829
|
const raw = argsOf$1(call);
|
|
6913
6830
|
const unit = textOf$3(raw, "unit");
|
|
@@ -6945,35 +6862,19 @@ function publishVerdict(call, preview) {
|
|
|
6945
6862
|
kind: "deny",
|
|
6946
6863
|
reason: `这一版还没有更新日志(${found.changelog.version})—— 带上 changelogNote(一行一条)再调,发布时会一起写进 CHANGELOG.md 并随包发`
|
|
6947
6864
|
};
|
|
6948
|
-
const
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
},
|
|
6953
|
-
public: {
|
|
6954
|
-
zh: `把${label}公开发到 npm,任何人都能安装,允许吗?`,
|
|
6955
|
-
en: `Publish ${labelEn} publicly to npm; anyone can install it. Allow?`
|
|
6956
|
-
},
|
|
6957
|
-
tarball: {
|
|
6958
|
-
zh: `给${label}打一个安装包,只写本机不发源码,允许吗?`,
|
|
6959
|
-
en: `Pack ${labelEn} into a local tarball; nothing leaves this machine. Allow?`
|
|
6960
|
-
},
|
|
6961
|
-
git: {
|
|
6962
|
-
zh: `把${label}提交并推到 git,源码也会一起推送,允许吗?`,
|
|
6963
|
-
en: `Commit and push ${labelEn} to git; the source is pushed too. Allow?`
|
|
6964
|
-
},
|
|
6965
|
-
market: {
|
|
6966
|
-
zh: `把${label}发到市场仓库,产物与索引一起提交,允许吗?`,
|
|
6967
|
-
en: `Publish ${labelEn} to the market repository; artifacts and the index are committed together. Allow?`
|
|
6968
|
-
},
|
|
6969
|
-
local: {
|
|
6970
|
-
zh: `把${label}留在本机,不发,允许吗?`,
|
|
6971
|
-
en: `Keep ${labelEn} local and publish nothing. Allow?`
|
|
6972
|
-
}
|
|
6865
|
+
const labels = labelsOfArgs(raw);
|
|
6866
|
+
if (labels.length > 2) return {
|
|
6867
|
+
kind: "deny",
|
|
6868
|
+
reason: `标签最多两个(收到 ${String(labels.length)} 个)—— 挑最能说明这个模块干什么的 1–2 个`
|
|
6973
6869
|
};
|
|
6870
|
+
if (target === "market" && labels.length === 0 && (found?.labels ?? []).length === 0) return {
|
|
6871
|
+
kind: "deny",
|
|
6872
|
+
reason: "这个模块还没有标签 —— 发布到市场时给它 1–2 个短词(labels,说它干什么,比如「发布编排」「构建状态」);已经有标签就不用传"
|
|
6873
|
+
};
|
|
6874
|
+
const copies = copiesOf(label, labelEn);
|
|
6974
6875
|
const copy = copies[target] ?? copies["team"];
|
|
6975
6876
|
const targetLabel = found === null ? target : target === "market" && found.market !== void 0 ? `${found.name}@${found.version} → market (${found.market.url})` : `${found.name}@${found.version} → ${target}${found.registry === void 0 ? "" : ` (${found.registry})`}`;
|
|
6976
|
-
const question = refresh ? pair(`只刷新${label}在市集里的元数据(标题 / 作者 /
|
|
6877
|
+
const question = refresh ? pair(`只刷新${label}在市集里的元数据(标题 / 作者 / 说明 / 标签),不升版本、不重发产物,允许吗?`, `Only refresh ${labelEn}'s market metadata (title, author, description, labels); no version bump, no artifacts. Allow?`) : pair(copy.zh, copy.en);
|
|
6977
6878
|
return askOf(`${DIY_PUBLISH_TOOL} ${targetLabel}${refresh ? "(元数据)" : ""}`, question, question);
|
|
6978
6879
|
}
|
|
6979
6880
|
function approvalVerdict(call, marketSource) {
|
|
@@ -9589,7 +9490,7 @@ var PUBLISH_TIMEOUT_MS = 18e5;
|
|
|
9589
9490
|
function registerPublishTool(ctx, tools, deps) {
|
|
9590
9491
|
const publishTool = {
|
|
9591
9492
|
name: DIY_PUBLISH_TOOL,
|
|
9592
|
-
description: "用户说“发布”后才用:把这一格发到 target 指定的出口(不填按环境默认)。这一版还没有更新日志时把 changelogNote 一起带上 —— 发布时写进 CHANGELOG.md
|
|
9493
|
+
description: "用户说“发布”后才用:把这一格发到 target 指定的出口(不填按环境默认)。这一版还没有更新日志时把 changelogNote 一起带上 —— 发布时写进 CHANGELOG.md,随包发。这个模块还没有市集标签时把 labels 带上(1–2 个短词)。",
|
|
9593
9494
|
parameters: {
|
|
9594
9495
|
type: "object",
|
|
9595
9496
|
properties: {
|
|
@@ -9606,6 +9507,11 @@ function registerPublishTool(ctx, tools, deps) {
|
|
|
9606
9507
|
enum: [...CHANGELOG_KINDS],
|
|
9607
9508
|
description: "分类,不填按 changed。"
|
|
9608
9509
|
},
|
|
9510
|
+
labels: {
|
|
9511
|
+
type: "array",
|
|
9512
|
+
items: { type: "string" },
|
|
9513
|
+
description: "市集条目的标签,1–2 个短词(说它干什么,比如「发布编排」「构建状态」)。模块还没有标签时必填;已有可省,传了会替换掉原来的。"
|
|
9514
|
+
},
|
|
9609
9515
|
target: {
|
|
9610
9516
|
type: "string",
|
|
9611
9517
|
enum: [
|
|
@@ -9644,7 +9550,7 @@ function registerPublishTool(ctx, tools, deps) {
|
|
|
9644
9550
|
},
|
|
9645
9551
|
refresh: {
|
|
9646
9552
|
type: "boolean",
|
|
9647
|
-
description: "
|
|
9553
|
+
description: "只刷市集元数据(标题/作者/说明/标签),不升版本、不重发产物。"
|
|
9648
9554
|
}
|
|
9649
9555
|
},
|
|
9650
9556
|
required: ["unit"],
|
|
@@ -9664,6 +9570,7 @@ function registerPublishTool(ctx, tools, deps) {
|
|
|
9664
9570
|
const license = asText(asRecord$1(raw)["license"]);
|
|
9665
9571
|
const changelogNote = asText(asRecord$1(raw)["changelogNote"]);
|
|
9666
9572
|
const changelogType = asText(asRecord$1(raw)["changelogType"]);
|
|
9573
|
+
const labels = labelsOf(asRecord$1(raw)["labels"]);
|
|
9667
9574
|
let author = asText(asRecord$1(raw)["author"]);
|
|
9668
9575
|
const verify = asRecord$1(raw)["verify"] === true;
|
|
9669
9576
|
const resume = asRecord$1(raw)["resume"] === true;
|
|
@@ -9685,6 +9592,7 @@ function registerPublishTool(ctx, tools, deps) {
|
|
|
9685
9592
|
if (author !== "") argv.push("--author", author);
|
|
9686
9593
|
if (changelogNote !== "") argv.push("--changelog-note", changelogNote);
|
|
9687
9594
|
if (changelogType !== "") argv.push("--changelog-type", changelogType);
|
|
9595
|
+
for (const label of labels) argv.push("--label", label);
|
|
9688
9596
|
if (asRecord$1(raw)["refresh"] === true) argv.push("--refresh");
|
|
9689
9597
|
const result = await runShell(shell, argv.map((one) => quoteShellArg(one)).join(" "), {
|
|
9690
9598
|
workdir: root,
|
|
@@ -9744,15 +9652,23 @@ function registerPublishTool(ctx, tools, deps) {
|
|
|
9744
9652
|
"包内容已经从源上核过(dist/host.js / client.js / cordis.patch.yml 都在)。"
|
|
9745
9653
|
].join("\n");
|
|
9746
9654
|
const changelog = asRecord$1(payload["changelog"]);
|
|
9747
|
-
const
|
|
9655
|
+
const tail = [asText(changelog["action"]) === "written" ? `更新日志:已写进 ${CHANGELOG_FILE} 的 ${asText(changelog["version"])}` : asText(changelog["action"]) === "kept" ? `更新日志:这一版已有(${asText(changelog["version"])}),没动` : "", labels.length === 0 || targetOfPayload !== "market" && payload["refresh"] !== true ? "" : `标签:${labels.join(" · ")}`].filter((one) => one !== "").join("\n");
|
|
9748
9656
|
return plainJson({
|
|
9749
9657
|
...payload,
|
|
9750
|
-
text:
|
|
9658
|
+
text: tail === "" ? text : `${text}\n${tail}`
|
|
9751
9659
|
});
|
|
9752
9660
|
}
|
|
9753
9661
|
};
|
|
9754
9662
|
return tools.register(publishTool);
|
|
9755
9663
|
}
|
|
9664
|
+
function labelsOf(value) {
|
|
9665
|
+
if (!Array.isArray(value) || value.length === 0) return [];
|
|
9666
|
+
const labels = value.flatMap((one) => typeof one === "string" ? [one.trim()] : []);
|
|
9667
|
+
if (labels.length !== value.length || labels.some((one) => one === "" || /[\r\n]/u.test(one))) throw new Error("标签是 1–2 个短词:每个都得是一行非空文字");
|
|
9668
|
+
const unique = [...new Set(labels)];
|
|
9669
|
+
if (unique.length > 2) throw new Error(`标签最多两个(收到 ${String(unique.length)} 个)—— 挑最能说明这个模块干什么的`);
|
|
9670
|
+
return unique;
|
|
9671
|
+
}
|
|
9756
9672
|
//#endregion
|
|
9757
9673
|
//#region src/shared/api/host/diy-recon.ts
|
|
9758
9674
|
var SITE_LIMIT = 6;
|
|
@@ -10194,7 +10110,11 @@ function renderStatus(root, lines, options = {}) {
|
|
|
10194
10110
|
}
|
|
10195
10111
|
function publishStatusOf(preview) {
|
|
10196
10112
|
if (preview === null) return "";
|
|
10197
|
-
return [
|
|
10113
|
+
return [
|
|
10114
|
+
preview.market === void 0 ? preview.registry === void 0 ? "发布出口:安装包(这个环境没配可写市场索引源,模块也没声明 publishConfig.registry)" : `发布出口:团队源 ${preview.registry}(package.json 的 publishConfig.registry)` : `发布出口:市场索引 ${preview.market.url}${preview.market.ref === void 0 ? "" : `(${preview.market.ref})`}—— 不填 target 时默认发这里;这一版会发 ${preview.market.nextVersion ?? preview.version}`,
|
|
10115
|
+
preview.market === void 0 ? void 0 : preview.labels === void 0 || preview.labels.length === 0 ? "标签:还没有 —— 发布到市场时带上 1–2 个(labels)" : `标签:${preview.labels.join(" · ")}`,
|
|
10116
|
+
preview.changelog === void 0 ? void 0 : preview.changelog.missing ? `发布前置:CHANGELOG 还差 ${preview.changelog.version} 这一版 —— 发布时带 changelogNote(会先建文件)` : `发布前置:CHANGELOG 里已有 ${preview.changelog.version}`
|
|
10117
|
+
].filter((one) => one !== void 0).join("\n");
|
|
10198
10118
|
}
|
|
10199
10119
|
function renderList(root, modules, shape = "bare") {
|
|
10200
10120
|
if (modules.length === 0) return [
|
|
@@ -10549,7 +10469,7 @@ function marketOf(dir, name, version) {
|
|
|
10549
10469
|
url: source.url,
|
|
10550
10470
|
...source.ref === void 0 ? {} : { ref: source.ref },
|
|
10551
10471
|
indexPath: source.path ?? "market",
|
|
10552
|
-
artifactPath:
|
|
10472
|
+
artifactPath: marketArtifactRoot(name),
|
|
10553
10473
|
files: ARTIFACTS.filter((one) => existsSync(join(dir, one))),
|
|
10554
10474
|
...nextVersion === void 0 ? {} : { nextVersion }
|
|
10555
10475
|
},
|
|
@@ -10639,6 +10559,9 @@ function publishPreviewOf(root, unit, options = {}) {
|
|
|
10639
10559
|
const publishConfig = record["publishConfig"];
|
|
10640
10560
|
const registry = typeof publishConfig === "object" && publishConfig !== null ? publishConfig["registry"] : void 0;
|
|
10641
10561
|
const market = marketOf(found.dir, name, version);
|
|
10562
|
+
const marketEntry = market === void 0 ? void 0 : publishedEntryOf(market.index, name);
|
|
10563
|
+
const declaredLabels = labelsOfManifest(record);
|
|
10564
|
+
const labels = declaredLabels.length > 0 || marketEntry === void 0 ? declaredLabels : marketEntryLabels(marketEntry);
|
|
10642
10565
|
const target = targetVersionOf(version, (options.version ?? "").trim(), market?.market);
|
|
10643
10566
|
const askedAuthor = (options.author ?? "").trim();
|
|
10644
10567
|
const author = askedAuthor === "" ? authorOf(record) : askedAuthor;
|
|
@@ -10652,12 +10575,21 @@ function publishPreviewOf(root, unit, options = {}) {
|
|
|
10652
10575
|
name,
|
|
10653
10576
|
version,
|
|
10654
10577
|
...author === "" ? {} : { author },
|
|
10578
|
+
...labels.length === 0 ? {} : { labels },
|
|
10655
10579
|
...typeof registry === "string" && registry !== "" ? { registry } : {},
|
|
10656
10580
|
...market === void 0 ? {} : { market: market.market },
|
|
10657
10581
|
...claim === void 0 ? {} : { claim },
|
|
10658
10582
|
changelog: changelogOf(found.dir, target, (options.changelog ?? "").trim(), kindOf(options.changelogType))
|
|
10659
10583
|
};
|
|
10660
10584
|
}
|
|
10585
|
+
function labelsOfManifest(record) {
|
|
10586
|
+
const dsh = record["dsh"];
|
|
10587
|
+
const workbench = dsh !== null && typeof dsh === "object" ? dsh["workbench"] : void 0;
|
|
10588
|
+
const market = workbench !== null && typeof workbench === "object" ? workbench["market"] : void 0;
|
|
10589
|
+
const labels = market !== null && typeof market === "object" ? market["labels"] : void 0;
|
|
10590
|
+
if (!Array.isArray(labels)) return [];
|
|
10591
|
+
return [...new Set(labels.flatMap((one) => typeof one === "string" && one.trim() !== "" ? [one.trim()] : []))];
|
|
10592
|
+
}
|
|
10661
10593
|
function authorOf(manifest) {
|
|
10662
10594
|
const author = manifest["author"];
|
|
10663
10595
|
if (typeof author === "string") return author.trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-workbench/core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "个人工作台:Agent 工作台(左栏 + 常驻对话 + 自研右侧数据面板)。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"icon": "./icon.svg",
|
|
@@ -100,8 +100,8 @@
|
|
|
100
100
|
"proper-lockfile": "^4.1.2",
|
|
101
101
|
"which": "^7.0.0",
|
|
102
102
|
"write-file-atomic": "^8.0.0",
|
|
103
|
-
"@dsh-workbench/shared": "1.1.
|
|
104
|
-
"@dsh-workbench/adapters-default": "1.1.
|
|
103
|
+
"@dsh-workbench/shared": "1.1.8",
|
|
104
|
+
"@dsh-workbench/adapters-default": "1.1.8"
|
|
105
105
|
},
|
|
106
106
|
"license": "MIT",
|
|
107
107
|
"repository": {
|
|
@@ -45,5 +45,6 @@
|
|
|
45
45
|
## 4 发布
|
|
46
46
|
|
|
47
47
|
只在用户明确说「帮我发布」后调。这一版还没有更新日志(`_status` 会说)时,把改了什么写进 `changelogNote`(一行一条,`changelogType` 选分类,缺省 changed):审批屏会展示将写进 `CHANGELOG.md` 的那一段,用户点了头才落盘,文件不在会先建。这一版已有内容就不用传,带了也不追加。
|
|
48
|
+
这个模块还没有市集标签(`_status` 会说)时,自己给它想 1–2 个短词放进 `labels`(说它干什么,比如「发布编排」「构建状态」);已有标签就不用传,传了会替换原来的。
|
|
48
49
|
出口、署名、标题、安装命令由工具与审批屏处理,不用问、不用补;没写作者时审批屏显示推断的署名(市集里上次的 / 同工坊的 / 本机 git 身份),用户觉得不对就拒绝后再说,他点名了才传 `author=…`。
|
|
49
50
|
需要用户接管时返回 `needsUser: { step, text, command? }`:把 `text` 说给用户,等「好了」再跑;不向用户要 token。
|
|
@@ -47,6 +47,7 @@ description: 在工作台里把当前面板调明白,或者给它造一块新
|
|
|
47
47
|
审批项标注「要你真用一次」,不打勾。结论只报:已装、在面板哪一格。
|
|
48
48
|
8. **发布** —— 只在用户说「帮我发布」之后:`workbench_diy_publish`(`unit=…`);这一版还没有更新日志就带上 `changelogNote`(一行一条),
|
|
49
49
|
发布时一起写进 `CHANGELOG.md` 并随包发,审批屏会展示将写入的那一段。
|
|
50
|
+
还没有市集标签就自己给 1–2 个短词放进 `labels`(说它干什么,比如「发布编排」「构建状态」);已有标签就不用传。
|
|
50
51
|
不手改 `package.json`、不补标题/署名、不问出口:工具与审批屏已经处理;他明确点名安装包 / 公开 / git 才传 target。
|
|
51
52
|
他说要换作者才传 `author="姓名 <邮箱>"`,别自己编一个;没写作者时审批屏显示推断的署名,他拒绝后再说。
|
|
52
53
|
市场里一个包名归第一次发布的人:换署名发同名会被拒;真是接手,让维护者先改那一条的 `owner`。
|
|
@@ -74,6 +74,8 @@ DIY 族仅在选了 DIY 模式的会话出现(按模式,不按工作区)
|
|
|
74
74
|
用户真是接手的人,让他先找索引维护者改那一条的 `owner`,别自己改成对方的署名去绕。
|
|
75
75
|
一个模块 id(`dsh.workbench.unit`)在同一个市场里只能有一个条目:换包名、沿用旧 unit 会被拒 ——
|
|
76
76
|
换包名时把 unit 也换掉,别为了保留 id 去改别人的条目。
|
|
77
|
+
这个模块还没有标签时(`workbench_diy_status` 会说),自己给它想 1–2 个短词放进 `labels`(说它干什么,比如「发布编排」「构建状态」),
|
|
78
|
+
别再问用户;已经有标签就不用传,传了会替换掉原来的(仍是最多两个)。发布时会把模块里的标签并进索引(只碰标签)。
|
|
77
79
|
2. 工具回 `needsUser` 时照 `text` 转述,不在对话里要 token / OTP;`otp` 交接后 `verify=true` 只核不发。
|
|
78
|
-
3. 只改市集元数据(标题 / 作者 /
|
|
79
|
-
|
|
80
|
+
3. 只改市集元数据(标题 / 作者 / 说明 / 标签)不升版本:`refresh=true`(换作者时同时传 `author`,仍要过 `owner` 检查)。
|
|
81
|
+
发布新版本不会改这些元数据(工具沿用远端条目当前的值),别指望发一版顺手把标题改掉;标签是例外 —— 发布总会照模块里的标签并一次。
|