@dsh-workbench/core 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -5
- package/bin/dsh-workbench +7 -1
- package/client.js +678 -382
- package/dist/client/client.body.js +678 -382
- package/dist/client/index.js +545 -249
- package/dist/host/index.js +710 -380
- package/dist/types/app/layouts/approval-detail.d.ts +2 -1
- package/dist/types/app/layouts/market/discover-source-item.d.ts +26 -0
- package/dist/types/app/layouts/market/discover-sources-dialog.d.ts +4 -0
- package/dist/types/app/layouts/market/discover-view.d.ts +2 -0
- package/dist/types/app/layouts/market/use-discover.d.ts +3 -0
- package/dist/types/kernel/contract/market-index.d.ts +1 -1
- package/dist/types/modules/panels/client.d.ts +1 -1
- package/dist/types/modules/panels/model/approval.d.ts +4 -2
- package/dist/types/modules/panels/model/diy-publish.d.ts +10 -0
- package/dist/types/modules/panels/model/diy-tools.d.ts +0 -1
- package/dist/types/modules/panels/model/market-sources-act.d.ts +2 -1
- package/dist/types/modules/panels/model/market-sources-tool.d.ts +3 -0
- package/dist/types/modules/panels/model/market-sources-tool.test.d.ts +1 -0
- package/dist/types/modules/panels/model/market-tools.d.ts +8 -1
- package/dist/types/modules/panels/model/publish-claim.d.ts +2 -0
- package/dist/types/modules/panels/unit.d.ts +7 -5
- package/dist/types/shared/api/host/diy-publish-preview.d.ts +2 -0
- package/dist/types/shared/api/host/market-source-init.d.ts +1 -0
- package/dist/types/shared/api/host/market-sources-store.d.ts +2 -0
- package/dist/types/shared/hooks/market-queries.d.ts +1 -1
- package/package.json +3 -3
- package/skills/workbench-module-diy/FAMILY.md +3 -4
- package/skills/workbench-module-diy/SKILL.md +4 -1
- package/skills/workbench-module-diy/WIRING.md +9 -2
- package/dist/types/modules/panels/model/diy-changelog.d.ts +0 -2
- package/dist/types/shared/api/host/diy-changelog.d.ts +0 -13
package/dist/host/index.js
CHANGED
|
@@ -4577,7 +4577,10 @@ var MARKET_INDEX_README_LINES = [
|
|
|
4577
4577
|
"dsh-wb-module release --index <本仓库地址> --index-policy artifacts-in-repo",
|
|
4578
4578
|
"```",
|
|
4579
4579
|
"",
|
|
4580
|
-
"产物会提交到 `packages
|
|
4580
|
+
"产物会提交到 `packages/<包名>/`(带 scope 时是 `packages/@scope/名字/`),并更新 `market.json`。",
|
|
4581
|
+
"",
|
|
4582
|
+
"一个包名归第一次发布的人(`market.json` 里的 `owner`)。换一个署名发同名会被拒;要换人,先把这一条的 `owner` 改成新的人。",
|
|
4583
|
+
"同一个市场里,一个模块 id(`metadata.unit`)只能被一个条目使用;另一个包名想用同一个 id / 产物目录也会被拒。",
|
|
4581
4584
|
"",
|
|
4582
4585
|
"## 使用这个索引",
|
|
4583
4586
|
"",
|
|
@@ -4683,15 +4686,25 @@ function iconProblem(icon) {
|
|
|
4683
4686
|
if (/^https?:\/\//i.test(icon)) return void 0;
|
|
4684
4687
|
return problem("icon", "icon 只能是 base64 data URL 或 http(s) URL");
|
|
4685
4688
|
}
|
|
4689
|
+
var MAX_OWNER_CHARS = 200;
|
|
4690
|
+
var UNIT_ID = /^[a-z][a-z0-9-]*$/;
|
|
4691
|
+
function ownerProblem(owner) {
|
|
4692
|
+
if (/[\r\n]/u.test(owner)) return problem("owner", "owner 只能是一行署名");
|
|
4693
|
+
if (owner.length > MAX_OWNER_CHARS) return problem("owner", "owner 超过 200 字");
|
|
4694
|
+
}
|
|
4686
4695
|
function metadataOf(raw) {
|
|
4687
4696
|
const record = asRecord$3(raw);
|
|
4688
4697
|
if (record === void 0) return void 0;
|
|
4698
|
+
const workbench = record["workbench"] === true;
|
|
4699
|
+
const unit = asText$3(record["unit"]);
|
|
4689
4700
|
const category = asText$3(record["category"]);
|
|
4690
4701
|
const labels = asTextArray(record["labels"]);
|
|
4691
4702
|
const keywords = asTextArray(record["keywords"]);
|
|
4692
4703
|
const sortKeysRecord = asRecord$3(record["sortKeys"]);
|
|
4693
4704
|
const sortKeys = sortKeysRecord === void 0 ? void 0 : Object.fromEntries(Object.entries(sortKeysRecord).flatMap(([key, value]) => typeof value === "string" || typeof value === "number" ? [[key, value]] : []));
|
|
4694
4705
|
return {
|
|
4706
|
+
...workbench ? { workbench: true } : {},
|
|
4707
|
+
...unit === "" ? {} : { unit },
|
|
4695
4708
|
...category === "" ? {} : { category },
|
|
4696
4709
|
...labels.length === 0 ? {} : { labels },
|
|
4697
4710
|
...keywords.length === 0 ? {} : { keywords },
|
|
@@ -4713,14 +4726,21 @@ function entryOf$1(raw, at) {
|
|
|
4713
4726
|
const title = asLocalized(record["title"]);
|
|
4714
4727
|
const description = asLocalized(record["description"]);
|
|
4715
4728
|
const author = asText$3(record["author"]);
|
|
4729
|
+
const owner = asText$3(record["owner"]);
|
|
4730
|
+
if (owner !== "") {
|
|
4731
|
+
const badOwner = ownerProblem(owner);
|
|
4732
|
+
if (badOwner !== void 0) return badOwner;
|
|
4733
|
+
}
|
|
4716
4734
|
const homepage = asText$3(record["homepage"]);
|
|
4717
4735
|
const metadata = metadataOf(record["metadata"]);
|
|
4736
|
+
if (metadata?.unit !== void 0 && !UNIT_ID.test(metadata.unit)) return problem("unit", `metadata.unit 只能是小写字母开头的 a-z0-9-(现在是 ${JSON.stringify(metadata.unit)})`, at);
|
|
4718
4737
|
return {
|
|
4719
4738
|
name,
|
|
4720
4739
|
versions,
|
|
4721
4740
|
...title === void 0 ? {} : { title },
|
|
4722
4741
|
...description === void 0 ? {} : { description },
|
|
4723
4742
|
...author === "" ? {} : { author },
|
|
4743
|
+
...owner === "" ? {} : { owner },
|
|
4724
4744
|
...homepage === "" ? {} : { homepage },
|
|
4725
4745
|
...icon === "" ? {} : { icon },
|
|
4726
4746
|
...metadata === void 0 ? {} : { metadata }
|
|
@@ -4907,6 +4927,84 @@ function gitUrlOk(url) {
|
|
|
4907
4927
|
return true;
|
|
4908
4928
|
}
|
|
4909
4929
|
//#endregion
|
|
4930
|
+
//#region ../shared/dist/host/market-index-claim.js
|
|
4931
|
+
function foldedName(name) {
|
|
4932
|
+
return name.replace(/\s+/gu, " ").trim().toLowerCase();
|
|
4933
|
+
}
|
|
4934
|
+
function publisherIdentityOf(text) {
|
|
4935
|
+
const raw = (text ?? "").trim();
|
|
4936
|
+
if (raw === "") return void 0;
|
|
4937
|
+
const match = /^(.*?)\s*<([^<>]*)>\s*$/u.exec(raw);
|
|
4938
|
+
const name = (match === null ? raw : match[1]).trim();
|
|
4939
|
+
const email = match === null ? "" : match[2].trim().toLowerCase();
|
|
4940
|
+
if (name === "") return void 0;
|
|
4941
|
+
return email === "" ? { name } : {
|
|
4942
|
+
name,
|
|
4943
|
+
email
|
|
4944
|
+
};
|
|
4945
|
+
}
|
|
4946
|
+
function samePublisher(left, right) {
|
|
4947
|
+
const a = publisherIdentityOf(left);
|
|
4948
|
+
const b = publisherIdentityOf(right);
|
|
4949
|
+
if (a === void 0 || b === void 0) return false;
|
|
4950
|
+
if (a.email !== void 0 && b.email !== void 0) return a.email === b.email;
|
|
4951
|
+
return foldedName(a.name) === foldedName(b.name);
|
|
4952
|
+
}
|
|
4953
|
+
function entryOwnerOf(entry) {
|
|
4954
|
+
const owner = (entry.owner ?? "").trim();
|
|
4955
|
+
if (owner !== "") return owner;
|
|
4956
|
+
const author = (entry.author ?? "").trim();
|
|
4957
|
+
return author === "" ? void 0 : author;
|
|
4958
|
+
}
|
|
4959
|
+
function claimOfEntry(entry, publisher) {
|
|
4960
|
+
if (entry === void 0) return { state: "new" };
|
|
4961
|
+
const owner = entryOwnerOf(entry);
|
|
4962
|
+
if (owner === void 0) return { state: "unowned" };
|
|
4963
|
+
if (publisher === void 0 || publisher.trim() === "") return { state: "unknown" };
|
|
4964
|
+
return samePublisher(owner, publisher) ? {
|
|
4965
|
+
state: "owned",
|
|
4966
|
+
owner
|
|
4967
|
+
} : {
|
|
4968
|
+
state: "conflict",
|
|
4969
|
+
owner
|
|
4970
|
+
};
|
|
4971
|
+
}
|
|
4972
|
+
function marketArtifactPath(name) {
|
|
4973
|
+
return `packages/${name}`;
|
|
4974
|
+
}
|
|
4975
|
+
function entryUnitOf(entry) {
|
|
4976
|
+
const unit = entry.metadata?.unit?.trim();
|
|
4977
|
+
if (unit !== void 0 && unit !== "") return unit;
|
|
4978
|
+
for (const version of entry.versions) {
|
|
4979
|
+
if (version.source.type !== "git") continue;
|
|
4980
|
+
const legacy = /^packages\/([^/]+)$/u.exec(version.source.path ?? "")?.[1];
|
|
4981
|
+
if (legacy !== void 0) return legacy;
|
|
4982
|
+
}
|
|
4983
|
+
}
|
|
4984
|
+
function claimOf(index, input) {
|
|
4985
|
+
const base = claimOfEntry(index.plugins.find((one) => one.name === input.name), input.publisher);
|
|
4986
|
+
if (base.state === "conflict" || base.state === "unknown") return base;
|
|
4987
|
+
const unit = (input.unit ?? "").trim();
|
|
4988
|
+
if (unit !== "") for (const other of index.plugins) {
|
|
4989
|
+
if (other.name === input.name) continue;
|
|
4990
|
+
if (entryUnitOf(other) !== unit) continue;
|
|
4991
|
+
return {
|
|
4992
|
+
state: "unit-taken",
|
|
4993
|
+
entry: other.name
|
|
4994
|
+
};
|
|
4995
|
+
}
|
|
4996
|
+
const path = (input.artifactPath ?? "").trim();
|
|
4997
|
+
if (path !== "") for (const other of index.plugins) {
|
|
4998
|
+
if (other.name === input.name) continue;
|
|
4999
|
+
if (!other.versions.some((one) => one.source.type === "git" && (one.source.path ?? "") === path)) continue;
|
|
5000
|
+
return {
|
|
5001
|
+
state: "path-taken",
|
|
5002
|
+
entry: other.name
|
|
5003
|
+
};
|
|
5004
|
+
}
|
|
5005
|
+
return base;
|
|
5006
|
+
}
|
|
5007
|
+
//#endregion
|
|
4910
5008
|
//#region ../shared/dist/host/changelog.js
|
|
4911
5009
|
var CHANGELOG_FILE = "CHANGELOG.md";
|
|
4912
5010
|
var CHANGELOG_KINDS = [
|
|
@@ -5064,6 +5162,25 @@ function appendChangelogEntry(text, options) {
|
|
|
5064
5162
|
out.splice(at, 0, ...bullets);
|
|
5065
5163
|
return `${normalizeWhitespace(out)}\n`;
|
|
5066
5164
|
}
|
|
5165
|
+
function planChangelog(text, options) {
|
|
5166
|
+
const source = normalizeChangelogText(text);
|
|
5167
|
+
const version = changelogVersion(options.version);
|
|
5168
|
+
const section = changelogSectionOf(source, version);
|
|
5169
|
+
if (section !== void 0 && changelogHasEntry(source, version)) return {
|
|
5170
|
+
action: "kept",
|
|
5171
|
+
version,
|
|
5172
|
+
text: source,
|
|
5173
|
+
section
|
|
5174
|
+
};
|
|
5175
|
+
if (bulletsOf(options.note).length === 0) return void 0;
|
|
5176
|
+
const next = appendChangelogEntry(source, options);
|
|
5177
|
+
return {
|
|
5178
|
+
action: "written",
|
|
5179
|
+
version,
|
|
5180
|
+
text: next,
|
|
5181
|
+
section: changelogSectionOf(next, version) ?? ""
|
|
5182
|
+
};
|
|
5183
|
+
}
|
|
5067
5184
|
function normalizeWhitespace(rows) {
|
|
5068
5185
|
const out = [];
|
|
5069
5186
|
for (const row of rows) {
|
|
@@ -5458,12 +5575,14 @@ var MODULES_UPDATE_DEPENDENCY_TOOL = "workbench_modules_update_dependency";
|
|
|
5458
5575
|
var MODULES_UPDATE_PLUGIN_TOOL = "workbench_modules_update_plugin";
|
|
5459
5576
|
var MODULES_UNINSTALL_PLUGIN_TOOL = "workbench_modules_uninstall_plugin";
|
|
5460
5577
|
var MODULES_UPDATE_WORKBENCH_TOOL = "workbench_modules_update_workbench";
|
|
5578
|
+
var MARKET_SOURCES_TOOL = "workbench_market_sources";
|
|
5579
|
+
var MARKET_ENABLE_TOOL = "workbench_market_enable";
|
|
5580
|
+
var MARKET_DISABLE_TOOL = "workbench_market_disable";
|
|
5461
5581
|
var DIY_STATUS_TOOL = "workbench_diy_status";
|
|
5462
5582
|
var DIY_PANEL_TOOL = "workbench_diy_panel";
|
|
5463
5583
|
var DIY_COMPONENTS_TOOL = "workbench_diy_components";
|
|
5464
5584
|
var DIY_RECON_TOOL = "workbench_diy_recon";
|
|
5465
5585
|
var DIY_SPEC_TOOL = "workbench_diy_spec";
|
|
5466
|
-
var DIY_CHANGELOG_TOOL = "workbench_diy_changelog";
|
|
5467
5586
|
var DIY_INSTALL_TOOL = "workbench_diy_install";
|
|
5468
5587
|
var DIY_PUBLISH_TOOL = "workbench_diy_publish";
|
|
5469
5588
|
var DIY_SHOW_TOOL = "workbench_diy_show";
|
|
@@ -5497,6 +5616,7 @@ var DIY_DEBUG_STOP_TOOL = "workbench_diy_debug_stop";
|
|
|
5497
5616
|
var READ_TOOLS = [
|
|
5498
5617
|
PANELS_LIST_TOOL,
|
|
5499
5618
|
MODULES_LIST_TOOL,
|
|
5619
|
+
MARKET_SOURCES_TOOL,
|
|
5500
5620
|
DIY_STATUS_TOOL,
|
|
5501
5621
|
DIY_PANEL_TOOL,
|
|
5502
5622
|
DIY_COMPONENTS_TOOL,
|
|
@@ -5538,7 +5658,8 @@ var WRITE_TOOLS = [
|
|
|
5538
5658
|
MODULES_UPDATE_PLUGIN_TOOL,
|
|
5539
5659
|
MODULES_UNINSTALL_PLUGIN_TOOL,
|
|
5540
5660
|
MODULES_UPDATE_WORKBENCH_TOOL,
|
|
5541
|
-
|
|
5661
|
+
MARKET_ENABLE_TOOL,
|
|
5662
|
+
MARKET_DISABLE_TOOL,
|
|
5542
5663
|
DIY_INSTALL_TOOL,
|
|
5543
5664
|
DIY_PUBLISH_TOOL,
|
|
5544
5665
|
DIY_SHOW_TOOL,
|
|
@@ -5555,7 +5676,6 @@ var DIY_TOOLS = [
|
|
|
5555
5676
|
DIY_COMPONENTS_TOOL,
|
|
5556
5677
|
DIY_RECON_TOOL,
|
|
5557
5678
|
DIY_SPEC_TOOL,
|
|
5558
|
-
DIY_CHANGELOG_TOOL,
|
|
5559
5679
|
DIY_INSTALL_TOOL,
|
|
5560
5680
|
DIY_PUBLISH_TOOL,
|
|
5561
5681
|
DIY_SHOW_TOOL,
|
|
@@ -5832,6 +5952,14 @@ function readDomainsOf(design) {
|
|
|
5832
5952
|
return [...found];
|
|
5833
5953
|
}
|
|
5834
5954
|
//#endregion
|
|
5955
|
+
//#region src/modules/panels/model/publish-claim.ts
|
|
5956
|
+
function publishClaimDenyOf(claim, name) {
|
|
5957
|
+
if (claim === void 0) return void 0;
|
|
5958
|
+
if (claim.state === "unit-taken") return `市场里 ${claim.entry} 已经用了这个模块 id —— 两个模块不能共用一个,装在一起会撞。给这个模块换一个 unit(dsh.workbench.unit)再发。`;
|
|
5959
|
+
if (claim.state === "path-taken") return `市场仓库里的产物目录已经被 ${claim.entry} 占了 —— 换一个包名再发。`;
|
|
5960
|
+
if (claim.state === "conflict") return `市场里 ${name} 已经有主了(${claim.owner})—— 同一个名字不能换人发。换一个带团队 scope 的包名;你就是原来的作者(只是换了机器或署名),用 author 参数带上原来的署名;确实是接手,让索引维护者改 market.json 里这一条的 owner。`;
|
|
5961
|
+
}
|
|
5962
|
+
//#endregion
|
|
5835
5963
|
//#region src/modules/panels/model/approval.ts
|
|
5836
5964
|
var SPEC_LIMIT = 80;
|
|
5837
5965
|
var TARGET_LIMIT = 20;
|
|
@@ -5938,11 +6066,22 @@ function publishVerdict(call, preview) {
|
|
|
5938
6066
|
if (raw["verify"] === true || raw["target"] === "local") return { kind: "allow" };
|
|
5939
6067
|
const refresh = raw["refresh"] === true;
|
|
5940
6068
|
const unit = textOf$3(raw, "unit");
|
|
5941
|
-
const
|
|
6069
|
+
const askedAuthor = textOf$3(raw, "author");
|
|
6070
|
+
const found = unit === "" ? null : preview?.(unit, askedAuthor === "" ? void 0 : askedAuthor) ?? null;
|
|
5942
6071
|
const asked = textOf$3(raw, "target");
|
|
5943
6072
|
const target = refresh ? "market" : asked === "" ? found?.market === void 0 ? found?.registry === void 0 ? "tarball" : "team" : "market" : asked;
|
|
6073
|
+
const source = textOf$3(raw, "source");
|
|
6074
|
+
const claimReason = publishClaimDenyOf(found?.claim, found?.name ?? unit);
|
|
6075
|
+
if (source === "" && target !== "tarball" && target !== "local" && claimReason !== void 0) return {
|
|
6076
|
+
kind: "deny",
|
|
6077
|
+
reason: claimReason
|
|
6078
|
+
};
|
|
5944
6079
|
const label = unit === "" ? "工作台模块" : `工作台模块 [${unit}]`;
|
|
5945
6080
|
const labelEn = unit === "" ? "the workbench module" : `the workbench module [${unit}]`;
|
|
6081
|
+
if (!refresh && found?.changelog?.missing === true && textOf$3(raw, "changelogNote") === "") return {
|
|
6082
|
+
kind: "deny",
|
|
6083
|
+
reason: `这一版还没有更新日志(${found.changelog.version})—— 带上 changelogNote(一行一条)再调,发布时会一起写进 CHANGELOG.md 并随包发`
|
|
6084
|
+
};
|
|
5946
6085
|
const copies = {
|
|
5947
6086
|
team: {
|
|
5948
6087
|
zh: `把${label}发到团队源,只发构建产物,不发源码,允许吗?`,
|
|
@@ -5974,7 +6113,7 @@ function publishVerdict(call, preview) {
|
|
|
5974
6113
|
const question = refresh ? pair(`只刷新${label}在市集里的元数据(标题 / 作者 / 说明),不升版本、不重发产物,允许吗?`, `Only refresh ${labelEn}'s market metadata (title, author, description); no version bump, no artifacts. Allow?`) : pair(copy.zh, copy.en);
|
|
5975
6114
|
return askOf(`${DIY_PUBLISH_TOOL} ${targetLabel}${refresh ? "(元数据)" : ""}`, question, question);
|
|
5976
6115
|
}
|
|
5977
|
-
|
|
6116
|
+
function approvalVerdict(call, marketSource) {
|
|
5978
6117
|
if (call.name === "workbench_long_tasks_stop") return stopVerdict(call, void 0);
|
|
5979
6118
|
if (call.name === "workbench_diy_publish") return publishVerdict(call);
|
|
5980
6119
|
if (call.name === "workbench_diy_debug_start" || call.name === "workbench_diy_debug_resume") {
|
|
@@ -6045,9 +6184,41 @@ var panelsApproval = (call) => {
|
|
|
6045
6184
|
return askOf(`${MODULES_UNINSTALL_PLUGIN_TOOL} ${plugin ?? ""} uninstalls an opencli plugin on this machine`, pair(`会卸载${target.zh},允许吗?`, `it uninstalls ${target.en}. Allow?`), pair(`agent 想卸载${target.zh},允许吗?`, `The agent wants to uninstall ${target.en}. Allow?`));
|
|
6046
6185
|
}
|
|
6047
6186
|
case MODULES_UPDATE_WORKBENCH_TOOL: return askOf(`${MODULES_UPDATE_WORKBENCH_TOOL} replaces the workbench itself with the new version from the registry`, pair("会把工作台本身更新到源上的新版,允许吗?", "it updates the workbench itself to the new version from the registry. Allow?"), pair("agent 想把工作台本身更新到源上的新版,允许吗?", "The agent wants to update the workbench itself from the registry. Allow?"));
|
|
6187
|
+
case MARKET_ENABLE_TOOL: {
|
|
6188
|
+
const id = text("id");
|
|
6189
|
+
const source = marketSource?.(id);
|
|
6190
|
+
if (marketSource !== void 0 && source === void 0) return {
|
|
6191
|
+
kind: "deny",
|
|
6192
|
+
reason: id === void 0 ? "这台机器上还没有选中的索引源 —— 先在「模块市场 → 发现」里添加并选中一个" : `没有这个索引源:${id}`
|
|
6193
|
+
};
|
|
6194
|
+
if (source !== void 0 && source.policy === "artifacts-in-repo") return { kind: "allow" };
|
|
6195
|
+
if (source !== void 0 && source.kind === "http") return {
|
|
6196
|
+
kind: "deny",
|
|
6197
|
+
reason: "http 索引源只能读,不能当发布目的地"
|
|
6198
|
+
};
|
|
6199
|
+
const where = source === void 0 ? {
|
|
6200
|
+
zh: id === void 0 ? "工作台当前选中的索引源" : `工作台的索引源「${id}」`,
|
|
6201
|
+
en: id === void 0 ? "the selected workbench index source" : `the workbench index source "${id}"`
|
|
6202
|
+
} : {
|
|
6203
|
+
zh: `工作台的索引源「${source.label}」`,
|
|
6204
|
+
en: `the workbench index source "${source.label}"`
|
|
6205
|
+
};
|
|
6206
|
+
return askOf(`${MARKET_ENABLE_TOOL}${source === void 0 ? "" : ` ${source.url}`} marks a market index source as a publish destination on this machine`, pair(`把${where.zh}设为可发布,允许吗?`, `Make ${where.en} a publish destination. Allow?`), pair(`会把${where.zh}设为可发布,只改本机配置,不碰仓库,允许吗?`, `It makes ${where.en} a publish destination on this machine, without touching the repository. Allow?`));
|
|
6207
|
+
}
|
|
6208
|
+
case MARKET_DISABLE_TOOL: {
|
|
6209
|
+
const id = text("id");
|
|
6210
|
+
const source = marketSource?.(id);
|
|
6211
|
+
if (marketSource !== void 0 && source === void 0) return {
|
|
6212
|
+
kind: "deny",
|
|
6213
|
+
reason: id === void 0 ? "这台机器上还没有选中的索引源 —— 先在「模块市场 → 发现」里添加并选中一个" : `没有这个索引源:${id}`
|
|
6214
|
+
};
|
|
6215
|
+
if (source === void 0) return askOf(`${MARKET_DISABLE_TOOL} stops using a market index source as a publish destination on this machine`, pair("把工作台当前选中的索引源改回只读,允许吗?", "Make the selected workbench index source read-only again. Allow?"), pair("会把工作台当前选中的索引源改回只读,只改本机配置,不碰仓库,允许吗?", "It makes the selected workbench index source read-only again on this machine, without touching the repository. Allow?"));
|
|
6216
|
+
if (source.kind !== "git" || source.policy !== "artifacts-in-repo") return { kind: "allow" };
|
|
6217
|
+
return askOf(`${MARKET_DISABLE_TOOL} ${source.url} stops using a market index source as a publish destination on this machine`, pair(`把工作台的索引源「${source.label}」改回只读,允许吗?`, `Make the workbench index source "${source.label}" read-only again. Allow?`), pair(`会把工作台的索引源「${source.label}」改回只读,只改本机配置,不碰仓库,允许吗?`, `It makes the workbench index source "${source.label}" read-only again on this machine, without touching the repository. Allow?`));
|
|
6218
|
+
}
|
|
6048
6219
|
default: return;
|
|
6049
6220
|
}
|
|
6050
|
-
}
|
|
6221
|
+
}
|
|
6051
6222
|
function recordHeldVerdict(call, recording) {
|
|
6052
6223
|
if (call.name !== "workbench_diy_record_prepare" || recording === void 0) return void 0;
|
|
6053
6224
|
const held = recording();
|
|
@@ -6057,11 +6228,16 @@ function recordHeldVerdict(call, recording) {
|
|
|
6057
6228
|
reason: recordRefusalText(held.sessionId === call.session ? "already-held" : "held-by-other", held)
|
|
6058
6229
|
};
|
|
6059
6230
|
}
|
|
6060
|
-
function panelsApprovalFor(longTaskRuns, recording, publishPreview) {
|
|
6231
|
+
function panelsApprovalFor(longTaskRuns, recording, publishPreview, marketSources) {
|
|
6232
|
+
const sourceOf = marketSources === void 0 ? void 0 : (id) => {
|
|
6233
|
+
const payload = marketSources.read();
|
|
6234
|
+
const wanted = id === void 0 || id === "" ? payload.selected : id;
|
|
6235
|
+
return wanted === null ? void 0 : payload.sources.find((one) => one.id === wanted);
|
|
6236
|
+
};
|
|
6061
6237
|
return (call) => {
|
|
6062
6238
|
if (call.name === "workbench_long_tasks_stop") return stopVerdict(call, longTaskRuns);
|
|
6063
6239
|
if (call.name === "workbench_diy_publish") return publishVerdict(call, publishPreview);
|
|
6064
|
-
return recordHeldVerdict(call, recording) ??
|
|
6240
|
+
return recordHeldVerdict(call, recording) ?? approvalVerdict(call, sourceOf);
|
|
6065
6241
|
};
|
|
6066
6242
|
}
|
|
6067
6243
|
//#endregion
|
|
@@ -6978,7 +7154,7 @@ async function sessionWorkspaceOf(ctx, workspace) {
|
|
|
6978
7154
|
dir = parent;
|
|
6979
7155
|
}
|
|
6980
7156
|
}
|
|
6981
|
-
var OUTPUT$
|
|
7157
|
+
var OUTPUT$3 = {
|
|
6982
7158
|
schema: {
|
|
6983
7159
|
type: "object",
|
|
6984
7160
|
properties: {
|
|
@@ -7123,7 +7299,7 @@ function componentsTool(ctx) {
|
|
|
7123
7299
|
},
|
|
7124
7300
|
additionalProperties: false
|
|
7125
7301
|
},
|
|
7126
|
-
output: OUTPUT$
|
|
7302
|
+
output: OUTPUT$3,
|
|
7127
7303
|
async execute(raw, exec) {
|
|
7128
7304
|
const { root } = await workspaceOf(ctx, exec);
|
|
7129
7305
|
const args = asRecord$1(raw);
|
|
@@ -7221,97 +7397,6 @@ function registerComponentsTool(ctx, tools) {
|
|
|
7221
7397
|
return [tools.register(componentsTool(ctx))];
|
|
7222
7398
|
}
|
|
7223
7399
|
//#endregion
|
|
7224
|
-
//#region src/shared/api/host/diy-changelog.ts
|
|
7225
|
-
function moduleVersionOf(dir) {
|
|
7226
|
-
try {
|
|
7227
|
-
const version = JSON.parse(readFileSync(join(dir, "package.json"), "utf8")).version;
|
|
7228
|
-
return typeof version === "string" ? version.trim() : "";
|
|
7229
|
-
} catch {
|
|
7230
|
-
return "";
|
|
7231
|
-
}
|
|
7232
|
-
}
|
|
7233
|
-
function writeChangelogEntry(dir, input) {
|
|
7234
|
-
const file = join(dir, CHANGELOG_FILE);
|
|
7235
|
-
const text = appendChangelogEntry(existsSync(file) ? readFileSync(file, "utf8") : changelogSkeleton(), {
|
|
7236
|
-
version: input.version,
|
|
7237
|
-
kind: input.kind,
|
|
7238
|
-
note: input.note,
|
|
7239
|
-
date: input.date ?? changelogDate()
|
|
7240
|
-
});
|
|
7241
|
-
writeFileSync(file, text);
|
|
7242
|
-
return {
|
|
7243
|
-
file,
|
|
7244
|
-
section: changelogSectionOf(text, input.version) ?? "",
|
|
7245
|
-
text
|
|
7246
|
-
};
|
|
7247
|
-
}
|
|
7248
|
-
//#endregion
|
|
7249
|
-
//#region src/modules/panels/model/diy-changelog.ts
|
|
7250
|
-
function toolOf(ctx) {
|
|
7251
|
-
return {
|
|
7252
|
-
name: DIY_CHANGELOG_TOOL,
|
|
7253
|
-
description: `发布前把这一版写进 ${CHANGELOG_FILE}(\`## v0.1.0\` + \`### ✨ 新增\` 这种小节):传 note 就记一条,文件不在就先建。没写这一版时发布会被拦下。`,
|
|
7254
|
-
parameters: {
|
|
7255
|
-
type: "object",
|
|
7256
|
-
properties: {
|
|
7257
|
-
unit: {
|
|
7258
|
-
type: "string",
|
|
7259
|
-
description: "模块 id(workbench_diy_status 会给)。"
|
|
7260
|
-
},
|
|
7261
|
-
version: {
|
|
7262
|
-
type: "string",
|
|
7263
|
-
description: "要写的版本;不填用 package.json 里的 version。"
|
|
7264
|
-
},
|
|
7265
|
-
type: {
|
|
7266
|
-
type: "string",
|
|
7267
|
-
enum: [...CHANGELOG_KINDS],
|
|
7268
|
-
description: "分类:added 新增 / changed 改进 / fixed 修复 / removed 移除 / security 安全 / deprecated 弃用。"
|
|
7269
|
-
},
|
|
7270
|
-
note: {
|
|
7271
|
-
type: "string",
|
|
7272
|
-
description: "这一版改了什么;多行时一行一条(必填)。"
|
|
7273
|
-
}
|
|
7274
|
-
},
|
|
7275
|
-
required: ["unit", "note"],
|
|
7276
|
-
additionalProperties: false
|
|
7277
|
-
},
|
|
7278
|
-
output: OUTPUT$2,
|
|
7279
|
-
async execute(raw, exec) {
|
|
7280
|
-
const { root } = await workspaceOf(ctx, exec);
|
|
7281
|
-
const args = asRecord$1(raw);
|
|
7282
|
-
const unit = asText(args["unit"]);
|
|
7283
|
-
const { units } = unitsOf(ctx, root);
|
|
7284
|
-
if (unit === "") throw new Error(`要一个 unit(这个工作区里:${units.map((one) => one.unit).join(", ") || "(空)"})`);
|
|
7285
|
-
const found = units.find((one) => one.unit === unit && one.dir !== "");
|
|
7286
|
-
if (found === void 0) throw new Error(`这个工作区里没有单元 id 为「${unit}」的模块(可用的:${units.map((one) => one.unit).join(", ") || "(空)"})`);
|
|
7287
|
-
if (!insideRoot(root, found.dir)) throw new Error(`这个模块不在这个工作区里(${found.dir})`);
|
|
7288
|
-
const note = asText(args["note"]).trim();
|
|
7289
|
-
if (note === "") throw new Error("要一句 note:这一版改了什么");
|
|
7290
|
-
const version = (asText(args["version"]) || moduleVersionOf(found.dir)).replace(/^v/, "");
|
|
7291
|
-
if (!isValidVersion(version)) throw new Error(`版本要写成 x.y.z(收到「${version}」)—— 也可以不填,用 package.json 里的`);
|
|
7292
|
-
const kind = asText(args["type"]) || "changed";
|
|
7293
|
-
if (!CHANGELOG_KINDS.includes(kind)) throw new Error(`type 只认 ${CHANGELOG_KINDS.join(" / ")}(收到「${kind}」)`);
|
|
7294
|
-
const written = writeChangelogEntry(found.dir, {
|
|
7295
|
-
version,
|
|
7296
|
-
kind,
|
|
7297
|
-
note
|
|
7298
|
-
});
|
|
7299
|
-
return plainJson({
|
|
7300
|
-
ok: true,
|
|
7301
|
-
unit,
|
|
7302
|
-
version,
|
|
7303
|
-
type: kind,
|
|
7304
|
-
path: written.file,
|
|
7305
|
-
section: written.section,
|
|
7306
|
-
text: `${CHANGELOG_FILE} 已记下 ${version}(${kind})。发布时会带进包和市场索引,审批屏会展示它。`
|
|
7307
|
-
});
|
|
7308
|
-
}
|
|
7309
|
-
};
|
|
7310
|
-
}
|
|
7311
|
-
function registerChangelogTool(ctx, tools) {
|
|
7312
|
-
return [tools.register(toolOf(ctx))];
|
|
7313
|
-
}
|
|
7314
|
-
//#endregion
|
|
7315
7400
|
//#region src/shared/api/host/diy-artifacts.ts
|
|
7316
7401
|
function artifactsDirOf(ctx, root) {
|
|
7317
7402
|
const homePath = ctx.get("dshHomePath");
|
|
@@ -7598,7 +7683,7 @@ function registerDebugTools(ctx, tools, store) {
|
|
|
7598
7683
|
required: [],
|
|
7599
7684
|
additionalProperties: false
|
|
7600
7685
|
},
|
|
7601
|
-
output: OUTPUT$
|
|
7686
|
+
output: OUTPUT$3,
|
|
7602
7687
|
async execute(raw, exec) {
|
|
7603
7688
|
const { root, title } = await workspaceOf(ctx, exec);
|
|
7604
7689
|
const { units } = unitsOf(ctx, root);
|
|
@@ -7633,7 +7718,7 @@ function registerDebugTools(ctx, tools, store) {
|
|
|
7633
7718
|
name: DIY_DEBUG_PAUSE_TOOL,
|
|
7634
7719
|
description: "暂停调试(不审批):屏工具停用,不再拿屏当目标。要接着看用 debug_resume。",
|
|
7635
7720
|
parameters: EMPTY,
|
|
7636
|
-
output: OUTPUT$
|
|
7721
|
+
output: OUTPUT$3,
|
|
7637
7722
|
async execute(_raw, exec) {
|
|
7638
7723
|
const { root } = await workspaceOf(ctx, exec);
|
|
7639
7724
|
const held = store.live(Date.now());
|
|
@@ -7651,7 +7736,7 @@ function registerDebugTools(ctx, tools, store) {
|
|
|
7651
7736
|
name: DIY_DEBUG_RESUME_TOOL,
|
|
7652
7737
|
description: "继续调试(要点头一次):请用户回到这一场调试所在的那一屏。",
|
|
7653
7738
|
parameters: EMPTY,
|
|
7654
|
-
output: OUTPUT$
|
|
7739
|
+
output: OUTPUT$3,
|
|
7655
7740
|
async execute(_raw, exec) {
|
|
7656
7741
|
const { root } = await workspaceOf(ctx, exec);
|
|
7657
7742
|
const held = store.live(Date.now());
|
|
@@ -7675,7 +7760,7 @@ function registerDebugTools(ctx, tools, store) {
|
|
|
7675
7760
|
name: DIY_DEBUG_STOP_TOOL,
|
|
7676
7761
|
description: "结束调试(不审批):清掉\"占用用户那一屏\"这件事。收工用它。",
|
|
7677
7762
|
parameters: EMPTY,
|
|
7678
|
-
output: OUTPUT$
|
|
7763
|
+
output: OUTPUT$3,
|
|
7679
7764
|
async execute(_raw, exec) {
|
|
7680
7765
|
const { root } = await workspaceOf(ctx, exec);
|
|
7681
7766
|
const held = store.live(Date.now());
|
|
@@ -7865,7 +7950,7 @@ function registerLogTools(ctx, tools) {
|
|
|
7865
7950
|
name: DIY_LOGS_WATCH_TOOL,
|
|
7866
7951
|
description: "把这一页的控制台听上(每页最多 200 条、单条截 400 字,随页面刷新消失)。",
|
|
7867
7952
|
parameters: schema,
|
|
7868
|
-
output: OUTPUT$
|
|
7953
|
+
output: OUTPUT$3,
|
|
7869
7954
|
async execute(raw, exec) {
|
|
7870
7955
|
const { page, step } = await run(exec, raw, LOGS_ARM_SCRIPT);
|
|
7871
7956
|
const error = actErrorOf(step);
|
|
@@ -7885,7 +7970,7 @@ function registerLogTools(ctx, tools) {
|
|
|
7885
7970
|
name: DIY_LOGS_READ_TOOL,
|
|
7886
7971
|
description: "读刚才听下来的控制台(最近 50 条;没装钩子会说清,不假装是\"没有报错\")。",
|
|
7887
7972
|
parameters: schema,
|
|
7888
|
-
output: OUTPUT$
|
|
7973
|
+
output: OUTPUT$3,
|
|
7889
7974
|
async execute(raw, exec) {
|
|
7890
7975
|
const { page, step } = await run(exec, raw, LOGS_READ_SCRIPT);
|
|
7891
7976
|
const error = actErrorOf(step);
|
|
@@ -7904,7 +7989,7 @@ function registerLogTools(ctx, tools) {
|
|
|
7904
7989
|
name: DIY_LOGS_STOP_TOOL,
|
|
7905
7990
|
description: "控制台收听收工:卸掉钩子、扔掉攒下的记录。",
|
|
7906
7991
|
parameters: schema,
|
|
7907
|
-
output: OUTPUT$
|
|
7992
|
+
output: OUTPUT$3,
|
|
7908
7993
|
async execute(raw, exec) {
|
|
7909
7994
|
const { page, step } = await run(exec, raw, LOGS_STOP_SCRIPT);
|
|
7910
7995
|
const error = actErrorOf(step);
|
|
@@ -8570,7 +8655,7 @@ function registerBrowserTools(ctx, tools) {
|
|
|
8570
8655
|
name: row.tool,
|
|
8571
8656
|
description: row.description,
|
|
8572
8657
|
parameters: parametersOf(row),
|
|
8573
|
-
output: OUTPUT$
|
|
8658
|
+
output: OUTPUT$3,
|
|
8574
8659
|
execute: async (raw, exec) => plainJson(await runBrowserTool(row, ctx, raw, exec))
|
|
8575
8660
|
};
|
|
8576
8661
|
return tools.register(definition);
|
|
@@ -8609,7 +8694,7 @@ function specTool(ctx) {
|
|
|
8609
8694
|
required: ["command"],
|
|
8610
8695
|
additionalProperties: false
|
|
8611
8696
|
},
|
|
8612
|
-
output: OUTPUT$
|
|
8697
|
+
output: OUTPUT$3,
|
|
8613
8698
|
async execute(raw, _exec) {
|
|
8614
8699
|
const args = asRecord$1(raw);
|
|
8615
8700
|
const argv = specArgvOf(asText(args["command"]));
|
|
@@ -8636,6 +8721,176 @@ function registerSpecTool(ctx, tools) {
|
|
|
8636
8721
|
return [tools.register(specTool(ctx))];
|
|
8637
8722
|
}
|
|
8638
8723
|
//#endregion
|
|
8724
|
+
//#region src/modules/panels/model/diy-publish.ts
|
|
8725
|
+
var PUBLISH_TIMEOUT_MS = 18e5;
|
|
8726
|
+
function registerPublishTool(ctx, tools, deps) {
|
|
8727
|
+
const publishTool = {
|
|
8728
|
+
name: DIY_PUBLISH_TOOL,
|
|
8729
|
+
description: "用户说“发布”后才用:把这一格发到 target 指定的出口(不填按环境默认)。这一版还没有更新日志时把 changelogNote 一起带上 —— 发布时写进 CHANGELOG.md,随包发。",
|
|
8730
|
+
parameters: {
|
|
8731
|
+
type: "object",
|
|
8732
|
+
properties: {
|
|
8733
|
+
unit: {
|
|
8734
|
+
type: "string",
|
|
8735
|
+
description: "模块 id(workbench_diy_status 会给)。"
|
|
8736
|
+
},
|
|
8737
|
+
changelogNote: {
|
|
8738
|
+
type: "string",
|
|
8739
|
+
description: "这一版改了什么,一行一条;这一版还没有更新日志时必填(文件不在会先建)。"
|
|
8740
|
+
},
|
|
8741
|
+
changelogType: {
|
|
8742
|
+
type: "string",
|
|
8743
|
+
enum: [...CHANGELOG_KINDS],
|
|
8744
|
+
description: "分类,不填按 changed。"
|
|
8745
|
+
},
|
|
8746
|
+
target: {
|
|
8747
|
+
type: "string",
|
|
8748
|
+
enum: [
|
|
8749
|
+
"team",
|
|
8750
|
+
"public",
|
|
8751
|
+
"tarball",
|
|
8752
|
+
"git",
|
|
8753
|
+
"market",
|
|
8754
|
+
"local"
|
|
8755
|
+
],
|
|
8756
|
+
description: "发到哪:团队源 / 公共 npm / 安装包 / git / 模块市场索引;不填按环境默认(有可写索引走市场,有私源走团队源,否则安装包)。"
|
|
8757
|
+
},
|
|
8758
|
+
version: {
|
|
8759
|
+
type: "string",
|
|
8760
|
+
description: "可选:patch / minor / major / x.y.z;不填首次用当前版本,之后自动 patch。"
|
|
8761
|
+
},
|
|
8762
|
+
source: {
|
|
8763
|
+
type: "string",
|
|
8764
|
+
description: "发布到哪个索引源(workbench_market_sources 会给 id);不填用唯一可发布的源。"
|
|
8765
|
+
},
|
|
8766
|
+
verify: {
|
|
8767
|
+
type: "boolean",
|
|
8768
|
+
description: "只核已发布的包(交接验证码后用),不再发;不用审批。"
|
|
8769
|
+
},
|
|
8770
|
+
resume: {
|
|
8771
|
+
type: "boolean",
|
|
8772
|
+
description: "中断后接着发(用记录里的出口与版本)。"
|
|
8773
|
+
},
|
|
8774
|
+
license: {
|
|
8775
|
+
type: "string",
|
|
8776
|
+
description: "公开发布用的许可证(MIT / Apache-2.0 / 仓库已有 LICENSE)。"
|
|
8777
|
+
},
|
|
8778
|
+
author: {
|
|
8779
|
+
type: "string",
|
|
8780
|
+
description: "署谁的名(姓名,或 姓名 <邮箱>);用户点了名才传,不传按模块里写的,没写用推断的署名。"
|
|
8781
|
+
},
|
|
8782
|
+
refresh: {
|
|
8783
|
+
type: "boolean",
|
|
8784
|
+
description: "只刷市集元数据(标题/作者/说明),不升版本、不重发产物。"
|
|
8785
|
+
}
|
|
8786
|
+
},
|
|
8787
|
+
required: ["unit"],
|
|
8788
|
+
additionalProperties: false
|
|
8789
|
+
},
|
|
8790
|
+
output: OUTPUT$3,
|
|
8791
|
+
async execute(raw, exec) {
|
|
8792
|
+
const { root } = await workspaceOf(ctx, exec);
|
|
8793
|
+
const found = deps.resolve(root, raw);
|
|
8794
|
+
const shell = ctx.get("shell");
|
|
8795
|
+
if (shell === void 0) throw new Error("这台机器上没有 shell 服务,发布跑不起来");
|
|
8796
|
+
const bin = toolchainBinOf(root) ?? toolchainBinOf(found.dir);
|
|
8797
|
+
if (bin === null) throw new Error(`这个工作区里没有 dsh-wb-module(${join(root, "node_modules")} 下没有)—— 先 pnpm install`);
|
|
8798
|
+
const target = asText(asRecord$1(raw)["target"]);
|
|
8799
|
+
const source = asText(asRecord$1(raw)["source"]);
|
|
8800
|
+
const version = asText(asRecord$1(raw)["version"]);
|
|
8801
|
+
const license = asText(asRecord$1(raw)["license"]);
|
|
8802
|
+
const changelogNote = asText(asRecord$1(raw)["changelogNote"]);
|
|
8803
|
+
const changelogType = asText(asRecord$1(raw)["changelogType"]);
|
|
8804
|
+
let author = asText(asRecord$1(raw)["author"]);
|
|
8805
|
+
const verify = asRecord$1(raw)["verify"] === true;
|
|
8806
|
+
const resume = asRecord$1(raw)["resume"] === true;
|
|
8807
|
+
if (!verify && target !== "local" && author === "" && (deps.previewOf(found.unit)?.author ?? "") === "") author = await deps.inferredAuthorOf(found.unit) ?? "";
|
|
8808
|
+
const argv = [
|
|
8809
|
+
bin,
|
|
8810
|
+
"release",
|
|
8811
|
+
"--cwd",
|
|
8812
|
+
found.dir,
|
|
8813
|
+
"--json"
|
|
8814
|
+
];
|
|
8815
|
+
if (verify) argv.push("--verify");
|
|
8816
|
+
else argv.push("--yes");
|
|
8817
|
+
if (resume) argv.push("--resume");
|
|
8818
|
+
if (target !== "") argv.push("--target", target);
|
|
8819
|
+
if (source !== "") argv.push("--index-source", source);
|
|
8820
|
+
if (version !== "") argv.push("--version", version);
|
|
8821
|
+
if (license !== "") argv.push("--license", license);
|
|
8822
|
+
if (author !== "") argv.push("--author", author);
|
|
8823
|
+
if (changelogNote !== "") argv.push("--changelog-note", changelogNote);
|
|
8824
|
+
if (changelogType !== "") argv.push("--changelog-type", changelogType);
|
|
8825
|
+
if (asRecord$1(raw)["refresh"] === true) argv.push("--refresh");
|
|
8826
|
+
const result = await runShell(shell, argv.map((one) => quoteShellArg(one)).join(" "), {
|
|
8827
|
+
workdir: root,
|
|
8828
|
+
timeoutMs: PUBLISH_TIMEOUT_MS
|
|
8829
|
+
});
|
|
8830
|
+
const payload = jsonOf(result.stdout);
|
|
8831
|
+
if (result.exitCode === 3 && payload !== void 0) {
|
|
8832
|
+
const needs = asRecord$1(payload["needsUser"]);
|
|
8833
|
+
const stepText = asText(needs["text"]);
|
|
8834
|
+
const command = asText(needs["command"]);
|
|
8835
|
+
return plainJson({
|
|
8836
|
+
...payload,
|
|
8837
|
+
text: [
|
|
8838
|
+
`还差一步:${stepText}`,
|
|
8839
|
+
...command === "" ? [] : [`命令:${command}`],
|
|
8840
|
+
"做完跟我说「好了」,我接着发。"
|
|
8841
|
+
].join("\n")
|
|
8842
|
+
});
|
|
8843
|
+
}
|
|
8844
|
+
if (result.exitCode === 4 && payload !== void 0) {
|
|
8845
|
+
const resumeInfo = asRecord$1(payload["resume"]);
|
|
8846
|
+
return plainJson({
|
|
8847
|
+
...payload,
|
|
8848
|
+
text: [`发布中断在第 ${asText(resumeInfo["phase"])} 步:${asText(payload["text"])}`, `再调一次 workbench_diy_publish(unit=${found.unit}, resume=true)就能接着发。`].join("\n")
|
|
8849
|
+
});
|
|
8850
|
+
}
|
|
8851
|
+
if (result.exitCode !== 0 || payload === void 0) {
|
|
8852
|
+
const tail = `${result.stderr}\n${result.stdout}`.trim().split("\n").slice(-6).join(" | ");
|
|
8853
|
+
throw new Error(`发布没走通(exit ${String(result.exitCode)})${tail === "" ? "" : `:${tail}`}`);
|
|
8854
|
+
}
|
|
8855
|
+
const name = asText(payload["name"]);
|
|
8856
|
+
const released = asText(payload["version"]);
|
|
8857
|
+
const registry = asText(payload["registry"]);
|
|
8858
|
+
const file = asText(payload["file"]);
|
|
8859
|
+
const install = asText(payload["install"]);
|
|
8860
|
+
const git = asRecord$1(payload["git"]);
|
|
8861
|
+
const targetOfPayload = asText(payload["target"]);
|
|
8862
|
+
const text = verify ? [
|
|
8863
|
+
`已核过 ${name}@${released}`,
|
|
8864
|
+
`安装:${install}`,
|
|
8865
|
+
"没有重新发布。"
|
|
8866
|
+
].join("\n") : payload["refresh"] === true ? [payload["refreshed"] === true ? `已刷新 ${name} 的市集元数据(版本 ${released} 不变)` : `${name} 的市集元数据本来就是这样,没动`, `市场索引:${asText(asRecord$1(payload["market"])["url"])}`].join("\n") : targetOfPayload === "tarball" ? [
|
|
8867
|
+
`安装包在 ${file}`,
|
|
8868
|
+
`本机装:${install}`,
|
|
8869
|
+
"文件可以从对话里带走,发给同事。"
|
|
8870
|
+
].join("\n") : targetOfPayload === "git" ? [
|
|
8871
|
+
`已推到 ${asText(git["url"])}(tag ${asText(git["tag"])})`,
|
|
8872
|
+
`安装:${install}`,
|
|
8873
|
+
"已核过 tag 里的产物。"
|
|
8874
|
+
].join("\n") : targetOfPayload === "market" ? [
|
|
8875
|
+
`已发到市场索引 ${asText(asRecord$1(payload["market"])["url"])}`,
|
|
8876
|
+
`安装:${install}`,
|
|
8877
|
+
"已从索引仓库侧核过产物。"
|
|
8878
|
+
].join("\n") : targetOfPayload === "local" ? "没发,留在本机。" : [
|
|
8879
|
+
`已发布 ${name}@${released} → ${registry}`,
|
|
8880
|
+
`同事安装:${install}`,
|
|
8881
|
+
"包内容已经从源上核过(dist/host.js / client.js / cordis.patch.yml 都在)。"
|
|
8882
|
+
].join("\n");
|
|
8883
|
+
const changelog = asRecord$1(payload["changelog"]);
|
|
8884
|
+
const changelogLine = asText(changelog["action"]) === "written" ? `更新日志:已写进 ${CHANGELOG_FILE} 的 ${asText(changelog["version"])}` : asText(changelog["action"]) === "kept" ? `更新日志:这一版已有(${asText(changelog["version"])}),没动` : "";
|
|
8885
|
+
return plainJson({
|
|
8886
|
+
...payload,
|
|
8887
|
+
text: changelogLine === "" ? text : `${text}\n${changelogLine}`
|
|
8888
|
+
});
|
|
8889
|
+
}
|
|
8890
|
+
};
|
|
8891
|
+
return tools.register(publishTool);
|
|
8892
|
+
}
|
|
8893
|
+
//#endregion
|
|
8639
8894
|
//#region src/shared/api/host/diy-recon.ts
|
|
8640
8895
|
var SITE_LIMIT = 6;
|
|
8641
8896
|
var COMMAND_LIMIT = 12;
|
|
@@ -9076,7 +9331,7 @@ function renderStatus(root, lines, options = {}) {
|
|
|
9076
9331
|
}
|
|
9077
9332
|
function publishStatusOf(preview) {
|
|
9078
9333
|
if (preview === null) return "";
|
|
9079
|
-
return [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}`, preview.changelog === void 0 ? void 0 : preview.changelog.missing ? `发布前置:CHANGELOG 还差 ${preview.changelog.version} 这一版 ——
|
|
9334
|
+
return [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}`, preview.changelog === void 0 ? void 0 : preview.changelog.missing ? `发布前置:CHANGELOG 还差 ${preview.changelog.version} 这一版 —— 发布时带 changelogNote(会先建文件)` : `发布前置:CHANGELOG 里已有 ${preview.changelog.version}`].filter((one) => one !== void 0).join("\n");
|
|
9080
9335
|
}
|
|
9081
9336
|
function renderList(root, modules, shape = "bare") {
|
|
9082
9337
|
if (modules.length === 0) return [
|
|
@@ -9091,7 +9346,6 @@ function renderList(root, modules, shape = "bare") {
|
|
|
9091
9346
|
}
|
|
9092
9347
|
//#endregion
|
|
9093
9348
|
//#region src/modules/panels/model/diy-tools.ts
|
|
9094
|
-
var PUBLISH_TIMEOUT_MS = 18e5;
|
|
9095
9349
|
function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, inferredAuthorOf = async () => void 0) {
|
|
9096
9350
|
const supply = supplyPortOf(ctx);
|
|
9097
9351
|
const tools = ctx.get("tools");
|
|
@@ -9111,7 +9365,7 @@ function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, in
|
|
|
9111
9365
|
required: [],
|
|
9112
9366
|
additionalProperties: false
|
|
9113
9367
|
},
|
|
9114
|
-
output: OUTPUT$
|
|
9368
|
+
output: OUTPUT$3,
|
|
9115
9369
|
async execute(raw, exec) {
|
|
9116
9370
|
const { root } = await workspaceOf(ctx, exec);
|
|
9117
9371
|
const { units } = unitsOf(ctx, root);
|
|
@@ -9154,7 +9408,7 @@ function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, in
|
|
|
9154
9408
|
} },
|
|
9155
9409
|
additionalProperties: false
|
|
9156
9410
|
},
|
|
9157
|
-
output: OUTPUT$
|
|
9411
|
+
output: OUTPUT$3,
|
|
9158
9412
|
async execute(raw, exec) {
|
|
9159
9413
|
const { root } = await workspaceOf(ctx, exec);
|
|
9160
9414
|
const { installed, units } = unitsOf(ctx, root);
|
|
@@ -9220,7 +9474,7 @@ function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, in
|
|
|
9220
9474
|
required: ["keyword"],
|
|
9221
9475
|
additionalProperties: false
|
|
9222
9476
|
},
|
|
9223
|
-
output: OUTPUT$
|
|
9477
|
+
output: OUTPUT$3,
|
|
9224
9478
|
async execute(raw, _exec) {
|
|
9225
9479
|
const args = asRecord$1(raw);
|
|
9226
9480
|
const keywords = keywordsOf(asText(args["keyword"]), asText(args["url"]));
|
|
@@ -9256,220 +9510,77 @@ function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, in
|
|
|
9256
9510
|
parameters: {
|
|
9257
9511
|
type: "object",
|
|
9258
9512
|
properties: { unit: {
|
|
9259
|
-
type: "string",
|
|
9260
|
-
description: "模块 id(workbench_diy_status 会给)。"
|
|
9261
|
-
} },
|
|
9262
|
-
required: ["unit"],
|
|
9263
|
-
additionalProperties: false
|
|
9264
|
-
},
|
|
9265
|
-
output: OUTPUT$2,
|
|
9266
|
-
async execute(raw, exec) {
|
|
9267
|
-
const { root } = await workspaceOf(ctx, exec);
|
|
9268
|
-
const { units } = unitsOf(ctx, root);
|
|
9269
|
-
const found = unitAmong(units, raw, "workbench_diy_show");
|
|
9270
|
-
if (!found.installed) throw new Error(`${found.unit} 还没装 —— 只上板的前提是它装过了。先用 workbench_diy_install(第一次)`);
|
|
9271
|
-
const panel = showOrReason(panels, found.unit, root);
|
|
9272
|
-
const text = panel.ok ? `面板上已经打开它了(${root})—— 验收就走这一张卡(你自己走一遍)` : `面板上还没打开:${panel.reason}。这就是它的下一步(workbench_diy_status 会给出同样的判断)`;
|
|
9273
|
-
return plainJson({
|
|
9274
|
-
workspace: root,
|
|
9275
|
-
unit: found.unit,
|
|
9276
|
-
path: found.dir,
|
|
9277
|
-
panel,
|
|
9278
|
-
text
|
|
9279
|
-
});
|
|
9280
|
-
}
|
|
9281
|
-
};
|
|
9282
|
-
const installTool = {
|
|
9283
|
-
name: DIY_INSTALL_TOOL,
|
|
9284
|
-
description: "把这个工作区里造好的模块装上并上到当前工作区的面板。这是持久变更,一个模块只装一次:之后改源码只需 dsh-wb-module build(宿主侧秒级热换)。",
|
|
9285
|
-
parameters: {
|
|
9286
|
-
type: "object",
|
|
9287
|
-
properties: { unit: {
|
|
9288
|
-
type: "string",
|
|
9289
|
-
description: "模块 id(workbench_diy_status 会给)。"
|
|
9290
|
-
} },
|
|
9291
|
-
required: ["unit"],
|
|
9292
|
-
additionalProperties: false
|
|
9293
|
-
},
|
|
9294
|
-
output: OUTPUT$2,
|
|
9295
|
-
async execute(raw, exec) {
|
|
9296
|
-
const { root } = await workspaceOf(ctx, exec);
|
|
9297
|
-
const found = unitOf(root, raw, "workbench_diy_install");
|
|
9298
|
-
if (found.installed) {
|
|
9299
|
-
const panel = showOrReason(panels, found.unit, root);
|
|
9300
|
-
const text = ["它已经装过了(就是这个工作区里这一份)—— **不要再装**:改源码 + dsh-wb-module build(宿主侧与 client.js 都秒级热换 —— dsh-client-hmr 盯着每个 bundle 的 lib/client.js,重建了就换进已打开的页面)。", panel.ok ? `面板上已经打开它了(${root})—— 验收就走这一张卡(你自己走一遍)` : `面板上还没打开:${panel.reason}。调 workbench_diy_show(unit=${found.unit})`].join("\n");
|
|
9301
|
-
return plainJson({
|
|
9302
|
-
workspace: root,
|
|
9303
|
-
unit: found.unit,
|
|
9304
|
-
path: found.dir,
|
|
9305
|
-
alreadyInstalled: true,
|
|
9306
|
-
panel,
|
|
9307
|
-
text
|
|
9308
|
-
});
|
|
9309
|
-
}
|
|
9310
|
-
const outcome = await market.installBundle(found.dir);
|
|
9311
|
-
const verdict = verdictOf(outcome.change);
|
|
9312
|
-
const restartRequired = outcome.change.application === "restart-required";
|
|
9313
|
-
const panel = outcome.change.application === "applied" ? showOrReason(panels, found.unit, root) : {
|
|
9314
|
-
ok: false,
|
|
9315
|
-
reason: `安装结果是 ${outcome.change.application},还没生效`
|
|
9316
|
-
};
|
|
9317
|
-
const panelText = panel.ok ? `面板上已经打开它了(${root})—— 验收就走这一张卡(你自己走一遍)` : outcome.change.application === "applied" ? `面板上还没打开:${panel.reason}。调 workbench_diy_show(unit=${found.unit})试试。` : restartRequired ? `面板上还没打开(${panel.reason}):模块要**重启一次工作台**才注册进面板 —— 把这句话转给用户,重启后再调 workbench_diy_show(unit=${found.unit})。` : `面板上还没打开:${panel.reason}。先把上面那句"没装成"处理掉,再谈上板。`;
|
|
9318
|
-
const text = [
|
|
9319
|
-
`${verdict}:${found.unit}(${found.name})`,
|
|
9320
|
-
panelText,
|
|
9321
|
-
"之后只改源码 + dsh-wb-module build(宿主侧与 client.js 都秒级热换 —— dsh-client-hmr 盯着每个 bundle 的 lib/client.js,重建了就换进已打开的页面):不要再装一遍。"
|
|
9322
|
-
].join("\n");
|
|
9323
|
-
return plainJson({
|
|
9324
|
-
workspace: root,
|
|
9325
|
-
unit: found.unit,
|
|
9326
|
-
path: found.dir,
|
|
9327
|
-
install: outcome.change,
|
|
9328
|
-
module: outcome.module,
|
|
9329
|
-
panel,
|
|
9330
|
-
text
|
|
9331
|
-
});
|
|
9332
|
-
}
|
|
9333
|
-
};
|
|
9334
|
-
const publishTool = {
|
|
9335
|
-
name: DIY_PUBLISH_TOOL,
|
|
9336
|
-
description: "用户说“发布”后才用:把这一格发到 target 指定的出口(不填按环境默认)。",
|
|
9337
|
-
parameters: {
|
|
9338
|
-
type: "object",
|
|
9339
|
-
properties: {
|
|
9340
|
-
unit: {
|
|
9341
|
-
type: "string",
|
|
9342
|
-
description: "模块 id(workbench_diy_status 会给)。"
|
|
9343
|
-
},
|
|
9344
|
-
target: {
|
|
9345
|
-
type: "string",
|
|
9346
|
-
enum: [
|
|
9347
|
-
"team",
|
|
9348
|
-
"public",
|
|
9349
|
-
"tarball",
|
|
9350
|
-
"git",
|
|
9351
|
-
"market",
|
|
9352
|
-
"local"
|
|
9353
|
-
],
|
|
9354
|
-
description: "发到哪:团队源 / 公共 npm / 安装包 / git / 模块市场索引;不填按环境默认(有可写索引走市场,有私源走团队源,否则安装包)。"
|
|
9355
|
-
},
|
|
9356
|
-
version: {
|
|
9357
|
-
type: "string",
|
|
9358
|
-
description: "可选:patch / minor / major / x.y.z;不填首次用当前版本,之后自动 patch。"
|
|
9359
|
-
},
|
|
9360
|
-
verify: {
|
|
9361
|
-
type: "boolean",
|
|
9362
|
-
description: "只核已发布的包(交接验证码后用),不再发;不用审批。"
|
|
9363
|
-
},
|
|
9364
|
-
resume: {
|
|
9365
|
-
type: "boolean",
|
|
9366
|
-
description: "中断后接着发(用记录里的出口与版本)。"
|
|
9367
|
-
},
|
|
9368
|
-
license: {
|
|
9369
|
-
type: "string",
|
|
9370
|
-
description: "公开发布用的许可证(MIT / Apache-2.0 / 仓库已有 LICENSE)。"
|
|
9371
|
-
},
|
|
9372
|
-
author: {
|
|
9373
|
-
type: "string",
|
|
9374
|
-
description: "署谁的名(姓名,或 姓名 <邮箱>);用户点了名才传,不传按模块里写的,没写用推断的署名。"
|
|
9375
|
-
},
|
|
9376
|
-
refresh: {
|
|
9377
|
-
type: "boolean",
|
|
9378
|
-
description: "只刷市集元数据(标题/作者/说明),不升版本、不重发产物。"
|
|
9379
|
-
}
|
|
9380
|
-
},
|
|
9513
|
+
type: "string",
|
|
9514
|
+
description: "模块 id(workbench_diy_status 会给)。"
|
|
9515
|
+
} },
|
|
9381
9516
|
required: ["unit"],
|
|
9382
9517
|
additionalProperties: false
|
|
9383
9518
|
},
|
|
9384
|
-
output: OUTPUT$
|
|
9519
|
+
output: OUTPUT$3,
|
|
9385
9520
|
async execute(raw, exec) {
|
|
9386
9521
|
const { root } = await workspaceOf(ctx, exec);
|
|
9387
|
-
const
|
|
9388
|
-
const
|
|
9389
|
-
if (
|
|
9390
|
-
const
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
if (!verify && target !== "local" && author === "" && (previewOf(found.unit)?.author ?? "") === "") author = await inferredAuthorOf(found.unit) ?? "";
|
|
9399
|
-
const argv = [
|
|
9400
|
-
bin,
|
|
9401
|
-
"release",
|
|
9402
|
-
"--cwd",
|
|
9403
|
-
found.dir,
|
|
9404
|
-
"--json"
|
|
9405
|
-
];
|
|
9406
|
-
if (verify) argv.push("--verify");
|
|
9407
|
-
else argv.push("--yes");
|
|
9408
|
-
if (resume) argv.push("--resume");
|
|
9409
|
-
if (target !== "") argv.push("--target", target);
|
|
9410
|
-
if (version !== "") argv.push("--version", version);
|
|
9411
|
-
if (license !== "") argv.push("--license", license);
|
|
9412
|
-
if (author !== "") argv.push("--author", author);
|
|
9413
|
-
if (asRecord$1(raw)["refresh"] === true) argv.push("--refresh");
|
|
9414
|
-
const result = await runShell(shell, argv.map((one) => quoteShellArg(one)).join(" "), {
|
|
9415
|
-
workdir: root,
|
|
9416
|
-
timeoutMs: PUBLISH_TIMEOUT_MS
|
|
9522
|
+
const { units } = unitsOf(ctx, root);
|
|
9523
|
+
const found = unitAmong(units, raw, "workbench_diy_show");
|
|
9524
|
+
if (!found.installed) throw new Error(`${found.unit} 还没装 —— 只上板的前提是它装过了。先用 workbench_diy_install(第一次)`);
|
|
9525
|
+
const panel = showOrReason(panels, found.unit, root);
|
|
9526
|
+
const text = panel.ok ? `面板上已经打开它了(${root})—— 验收就走这一张卡(你自己走一遍)` : `面板上还没打开:${panel.reason}。这就是它的下一步(workbench_diy_status 会给出同样的判断)`;
|
|
9527
|
+
return plainJson({
|
|
9528
|
+
workspace: root,
|
|
9529
|
+
unit: found.unit,
|
|
9530
|
+
path: found.dir,
|
|
9531
|
+
panel,
|
|
9532
|
+
text
|
|
9417
9533
|
});
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9421
|
-
|
|
9422
|
-
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
|
|
9433
|
-
|
|
9534
|
+
}
|
|
9535
|
+
};
|
|
9536
|
+
const installTool = {
|
|
9537
|
+
name: DIY_INSTALL_TOOL,
|
|
9538
|
+
description: "把这个工作区里造好的模块装上并上到当前工作区的面板。这是持久变更,一个模块只装一次:之后改源码只需 dsh-wb-module build(宿主侧秒级热换)。",
|
|
9539
|
+
parameters: {
|
|
9540
|
+
type: "object",
|
|
9541
|
+
properties: { unit: {
|
|
9542
|
+
type: "string",
|
|
9543
|
+
description: "模块 id(workbench_diy_status 会给)。"
|
|
9544
|
+
} },
|
|
9545
|
+
required: ["unit"],
|
|
9546
|
+
additionalProperties: false
|
|
9547
|
+
},
|
|
9548
|
+
output: OUTPUT$3,
|
|
9549
|
+
async execute(raw, exec) {
|
|
9550
|
+
const { root } = await workspaceOf(ctx, exec);
|
|
9551
|
+
const found = unitOf(root, raw, "workbench_diy_install");
|
|
9552
|
+
if (found.installed) {
|
|
9553
|
+
const panel = showOrReason(panels, found.unit, root);
|
|
9554
|
+
const text = ["它已经装过了(就是这个工作区里这一份)—— **不要再装**:改源码 + dsh-wb-module build(宿主侧与 client.js 都秒级热换 —— dsh-client-hmr 盯着每个 bundle 的 lib/client.js,重建了就换进已打开的页面)。", panel.ok ? `面板上已经打开它了(${root})—— 验收就走这一张卡(你自己走一遍)` : `面板上还没打开:${panel.reason}。调 workbench_diy_show(unit=${found.unit})`].join("\n");
|
|
9434
9555
|
return plainJson({
|
|
9435
|
-
|
|
9436
|
-
|
|
9556
|
+
workspace: root,
|
|
9557
|
+
unit: found.unit,
|
|
9558
|
+
path: found.dir,
|
|
9559
|
+
alreadyInstalled: true,
|
|
9560
|
+
panel,
|
|
9561
|
+
text
|
|
9437
9562
|
});
|
|
9438
9563
|
}
|
|
9439
|
-
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
|
|
9446
|
-
const
|
|
9447
|
-
const
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
`已核过 ${name}@${released}`,
|
|
9452
|
-
`安装:${install}`,
|
|
9453
|
-
"没有重新发布。"
|
|
9454
|
-
].join("\n") : payload["refresh"] === true ? [payload["refreshed"] === true ? `已刷新 ${name} 的市集元数据(版本 ${released} 不变)` : `${name} 的市集元数据本来就是这样,没动`, `市场索引:${asText(asRecord$1(payload["market"])["url"])}`].join("\n") : targetOfPayload === "tarball" ? [
|
|
9455
|
-
`安装包在 ${file}`,
|
|
9456
|
-
`本机装:${install}`,
|
|
9457
|
-
"文件可以从对话里带走,发给同事。"
|
|
9458
|
-
].join("\n") : targetOfPayload === "git" ? [
|
|
9459
|
-
`已推到 ${asText(git["url"])}(tag ${asText(git["tag"])})`,
|
|
9460
|
-
`安装:${install}`,
|
|
9461
|
-
"已核过 tag 里的产物。"
|
|
9462
|
-
].join("\n") : targetOfPayload === "market" ? [
|
|
9463
|
-
`已发到市场索引 ${asText(asRecord$1(payload["market"])["url"])}`,
|
|
9464
|
-
`安装:${install}`,
|
|
9465
|
-
"已从索引仓库侧核过产物。"
|
|
9466
|
-
].join("\n") : targetOfPayload === "local" ? "没发,留在本机。" : [
|
|
9467
|
-
`已发布 ${name}@${released} → ${registry}`,
|
|
9468
|
-
`同事安装:${install}`,
|
|
9469
|
-
"包内容已经从源上核过(dist/host.js / client.js / cordis.patch.yml 都在)。"
|
|
9564
|
+
const outcome = await market.installBundle(found.dir);
|
|
9565
|
+
const verdict = verdictOf(outcome.change);
|
|
9566
|
+
const restartRequired = outcome.change.application === "restart-required";
|
|
9567
|
+
const panel = outcome.change.application === "applied" ? showOrReason(panels, found.unit, root) : {
|
|
9568
|
+
ok: false,
|
|
9569
|
+
reason: `安装结果是 ${outcome.change.application},还没生效`
|
|
9570
|
+
};
|
|
9571
|
+
const panelText = panel.ok ? `面板上已经打开它了(${root})—— 验收就走这一张卡(你自己走一遍)` : outcome.change.application === "applied" ? `面板上还没打开:${panel.reason}。调 workbench_diy_show(unit=${found.unit})试试。` : restartRequired ? `面板上还没打开(${panel.reason}):模块要**重启一次工作台**才注册进面板 —— 把这句话转给用户,重启后再调 workbench_diy_show(unit=${found.unit})。` : `面板上还没打开:${panel.reason}。先把上面那句"没装成"处理掉,再谈上板。`;
|
|
9572
|
+
const text = [
|
|
9573
|
+
`${verdict}:${found.unit}(${found.name})`,
|
|
9574
|
+
panelText,
|
|
9575
|
+
"之后只改源码 + dsh-wb-module build(宿主侧与 client.js 都秒级热换 —— dsh-client-hmr 盯着每个 bundle 的 lib/client.js,重建了就换进已打开的页面):不要再装一遍。"
|
|
9470
9576
|
].join("\n");
|
|
9471
9577
|
return plainJson({
|
|
9472
|
-
|
|
9578
|
+
workspace: root,
|
|
9579
|
+
unit: found.unit,
|
|
9580
|
+
path: found.dir,
|
|
9581
|
+
install: outcome.change,
|
|
9582
|
+
module: outcome.module,
|
|
9583
|
+
panel,
|
|
9473
9584
|
text
|
|
9474
9585
|
});
|
|
9475
9586
|
}
|
|
@@ -9480,13 +9591,16 @@ function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, in
|
|
|
9480
9591
|
...registerComponentsTool(ctx, tools),
|
|
9481
9592
|
tools.register(reconTool),
|
|
9482
9593
|
...registerSpecTool(ctx, tools),
|
|
9483
|
-
...registerChangelogTool(ctx, tools),
|
|
9484
9594
|
...registerLogTools(ctx, tools),
|
|
9485
9595
|
...registerBrowserTools(ctx, tools),
|
|
9486
9596
|
...registerDebugTools(ctx, tools, debug),
|
|
9487
9597
|
tools.register(showTool),
|
|
9488
9598
|
tools.register(installTool),
|
|
9489
|
-
tools
|
|
9599
|
+
registerPublishTool(ctx, tools, {
|
|
9600
|
+
resolve: (root, raw) => unitOf(root, raw, "workbench_diy_publish"),
|
|
9601
|
+
previewOf,
|
|
9602
|
+
inferredAuthorOf
|
|
9603
|
+
})
|
|
9490
9604
|
];
|
|
9491
9605
|
}
|
|
9492
9606
|
//#endregion
|
|
@@ -9516,27 +9630,22 @@ function selectedGitSource() {
|
|
|
9516
9630
|
return parsed.source.policy === "artifacts-in-repo" ? parsed.source : void 0;
|
|
9517
9631
|
}
|
|
9518
9632
|
}
|
|
9519
|
-
|
|
9633
|
+
var EMPTY_INDEX = {
|
|
9634
|
+
format: 1,
|
|
9635
|
+
plugins: []
|
|
9636
|
+
};
|
|
9637
|
+
function publishedIndexOf(source) {
|
|
9520
9638
|
const file = join(workbenchRoot(), "market-index", marketSourceKey(source), "worktree", source.path ?? "market.json");
|
|
9521
9639
|
if (!existsSync(file)) return void 0;
|
|
9522
9640
|
try {
|
|
9523
9641
|
const parsed = parseMarketIndexJson(readFileSync(file, "utf8"));
|
|
9524
|
-
|
|
9525
|
-
const entry = parsed.index.plugins.find((one) => one.name === name);
|
|
9526
|
-
if (entry === void 0) return {
|
|
9527
|
-
versions: [],
|
|
9528
|
-
author: ""
|
|
9529
|
-
};
|
|
9530
|
-
return {
|
|
9531
|
-
versions: entry.versions.map((one) => one.version),
|
|
9532
|
-
author: typeof entry.author === "string" ? entry.author.trim() : ""
|
|
9533
|
-
};
|
|
9642
|
+
return parsed.ok ? parsed.index : void 0;
|
|
9534
9643
|
} catch {
|
|
9535
9644
|
return;
|
|
9536
9645
|
}
|
|
9537
9646
|
}
|
|
9538
|
-
function
|
|
9539
|
-
return
|
|
9647
|
+
function publishedEntryOf(index, name) {
|
|
9648
|
+
return index?.plugins.find((one) => one.name === name);
|
|
9540
9649
|
}
|
|
9541
9650
|
function bumped(version, kind) {
|
|
9542
9651
|
const match = SEMVER.exec(version);
|
|
@@ -9561,17 +9670,21 @@ function nextVersionOf(version, published) {
|
|
|
9561
9670
|
if (!exists(candidate)) return candidate;
|
|
9562
9671
|
}
|
|
9563
9672
|
}
|
|
9564
|
-
function marketOf(
|
|
9673
|
+
function marketOf(dir, name, version) {
|
|
9565
9674
|
const source = selectedGitSource();
|
|
9566
9675
|
if (source === void 0) return void 0;
|
|
9567
|
-
const
|
|
9676
|
+
const index = publishedIndexOf(source);
|
|
9677
|
+
const nextVersion = nextVersionOf(version, publishedEntryOf(index, name)?.versions.map((one) => one.version));
|
|
9568
9678
|
return {
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
9679
|
+
market: {
|
|
9680
|
+
url: source.url,
|
|
9681
|
+
...source.ref === void 0 ? {} : { ref: source.ref },
|
|
9682
|
+
indexPath: source.path ?? "market.json",
|
|
9683
|
+
artifactPath: marketArtifactPath(name),
|
|
9684
|
+
files: ARTIFACTS.filter((one) => existsSync(join(dir, one))),
|
|
9685
|
+
...nextVersion === void 0 ? {} : { nextVersion }
|
|
9686
|
+
},
|
|
9687
|
+
...index === void 0 ? {} : { index }
|
|
9575
9688
|
};
|
|
9576
9689
|
}
|
|
9577
9690
|
function moduleFactOf(root, unit) {
|
|
@@ -9630,7 +9743,7 @@ async function inferredAuthorOf(root, unit, shell) {
|
|
|
9630
9743
|
if (fact.author !== "") return fact.author;
|
|
9631
9744
|
const source = selectedGitSource();
|
|
9632
9745
|
if (source !== void 0 && fact.name !== "") {
|
|
9633
|
-
const published = publishedEntryOf(source, fact.name)?.author ?? "";
|
|
9746
|
+
const published = publishedEntryOf(publishedIndexOf(source), fact.name)?.author ?? "";
|
|
9634
9747
|
if (published !== "") return published;
|
|
9635
9748
|
}
|
|
9636
9749
|
const sibling = root === null || root === void 0 ? void 0 : siblingAuthorOf(root, unit);
|
|
@@ -9656,17 +9769,24 @@ function publishPreviewOf(root, unit, options = {}) {
|
|
|
9656
9769
|
if (name === "" || version === "") return null;
|
|
9657
9770
|
const publishConfig = record["publishConfig"];
|
|
9658
9771
|
const registry = typeof publishConfig === "object" && publishConfig !== null ? publishConfig["registry"] : void 0;
|
|
9659
|
-
const market = marketOf(found.
|
|
9660
|
-
const target = targetVersionOf(version, (options.version ?? "").trim(), market);
|
|
9772
|
+
const market = marketOf(found.dir, name, version);
|
|
9773
|
+
const target = targetVersionOf(version, (options.version ?? "").trim(), market?.market);
|
|
9661
9774
|
const askedAuthor = (options.author ?? "").trim();
|
|
9662
9775
|
const author = askedAuthor === "" ? authorOf(record) : askedAuthor;
|
|
9776
|
+
const claim = market === void 0 ? void 0 : claimOf(market.index ?? EMPTY_INDEX, {
|
|
9777
|
+
name,
|
|
9778
|
+
publisher: author,
|
|
9779
|
+
unit,
|
|
9780
|
+
artifactPath: marketArtifactPath(name)
|
|
9781
|
+
});
|
|
9663
9782
|
return {
|
|
9664
9783
|
name,
|
|
9665
9784
|
version,
|
|
9666
9785
|
...author === "" ? {} : { author },
|
|
9667
9786
|
...typeof registry === "string" && registry !== "" ? { registry } : {},
|
|
9668
|
-
...market === void 0 ? {} : { market },
|
|
9669
|
-
|
|
9787
|
+
...market === void 0 ? {} : { market: market.market },
|
|
9788
|
+
...claim === void 0 ? {} : { claim },
|
|
9789
|
+
changelog: changelogOf(found.dir, target, (options.changelog ?? "").trim(), kindOf(options.changelogType))
|
|
9670
9790
|
};
|
|
9671
9791
|
}
|
|
9672
9792
|
function authorOf(manifest) {
|
|
@@ -9684,13 +9804,30 @@ function targetVersionOf(version, asked, market) {
|
|
|
9684
9804
|
if (/^(major|minor|patch)$/.test(asked)) return bumped(version, asked) ?? version;
|
|
9685
9805
|
return asked;
|
|
9686
9806
|
}
|
|
9687
|
-
function
|
|
9807
|
+
function kindOf(given) {
|
|
9808
|
+
const wanted = (given ?? "").trim();
|
|
9809
|
+
return CHANGELOG_KINDS.includes(wanted) ? wanted : "changed";
|
|
9810
|
+
}
|
|
9811
|
+
function changelogOf(dir, version, note, kind) {
|
|
9688
9812
|
let text;
|
|
9689
9813
|
try {
|
|
9690
9814
|
text = readFileSync(join(dir, CHANGELOG_FILE), "utf8");
|
|
9691
9815
|
} catch {
|
|
9692
9816
|
text = void 0;
|
|
9693
9817
|
}
|
|
9818
|
+
if (note !== "") {
|
|
9819
|
+
const plan = planChangelog(text ?? "", {
|
|
9820
|
+
version,
|
|
9821
|
+
kind,
|
|
9822
|
+
note,
|
|
9823
|
+
date: changelogDate()
|
|
9824
|
+
});
|
|
9825
|
+
if (plan !== void 0) return {
|
|
9826
|
+
version: plan.version,
|
|
9827
|
+
text: plan.section,
|
|
9828
|
+
...plan.action === "written" ? { pending: true } : {}
|
|
9829
|
+
};
|
|
9830
|
+
}
|
|
9694
9831
|
if (text === void 0 || !changelogHasEntry(text, version)) return {
|
|
9695
9832
|
version,
|
|
9696
9833
|
missing: true
|
|
@@ -11013,7 +11150,7 @@ function registerRecordTools(ctx, store) {
|
|
|
11013
11150
|
required: ["url"],
|
|
11014
11151
|
additionalProperties: false
|
|
11015
11152
|
},
|
|
11016
|
-
output: OUTPUT$
|
|
11153
|
+
output: OUTPUT$3,
|
|
11017
11154
|
async execute(raw, exec) {
|
|
11018
11155
|
const { root } = await workspaceOf(ctx, exec);
|
|
11019
11156
|
const artifactsDir = artifactsDirOf(ctx, root);
|
|
@@ -11113,7 +11250,7 @@ function registerRecordTools(ctx, store) {
|
|
|
11113
11250
|
} },
|
|
11114
11251
|
additionalProperties: false
|
|
11115
11252
|
},
|
|
11116
|
-
output: OUTPUT$
|
|
11253
|
+
output: OUTPUT$3,
|
|
11117
11254
|
async execute(raw, exec) {
|
|
11118
11255
|
const shell = ctx.get("shell");
|
|
11119
11256
|
if (shell === void 0) throw new Error("这台机器上没有 shell 服务,读不了录制");
|
|
@@ -11243,7 +11380,7 @@ function registerRecordTools(ctx, store) {
|
|
|
11243
11380
|
},
|
|
11244
11381
|
additionalProperties: false
|
|
11245
11382
|
},
|
|
11246
|
-
output: OUTPUT$
|
|
11383
|
+
output: OUTPUT$3,
|
|
11247
11384
|
async execute(raw, exec) {
|
|
11248
11385
|
const { root } = await workspaceOf(ctx, exec);
|
|
11249
11386
|
const artifactsDir = artifactsDirOf(ctx, root);
|
|
@@ -11325,7 +11462,7 @@ function registerRecordTools(ctx, store) {
|
|
|
11325
11462
|
properties: {},
|
|
11326
11463
|
additionalProperties: false
|
|
11327
11464
|
},
|
|
11328
|
-
output: OUTPUT$
|
|
11465
|
+
output: OUTPUT$3,
|
|
11329
11466
|
async execute(_raw, exec) {
|
|
11330
11467
|
const shell = ctx.get("shell");
|
|
11331
11468
|
if (shell === void 0) throw new Error("这台机器上没有 shell 服务,收不了工");
|
|
@@ -12566,6 +12703,7 @@ function normalizedRepo(value) {
|
|
|
12566
12703
|
return value.trim().replace(/^git\+/, "").replace(/\.git$/, "").toLowerCase();
|
|
12567
12704
|
}
|
|
12568
12705
|
function isWorkbenchEntry(entry) {
|
|
12706
|
+
if (entry.metadata?.workbench === true) return true;
|
|
12569
12707
|
const labels = marketEntryLabels(entry);
|
|
12570
12708
|
if (labels.includes("workbench")) return true;
|
|
12571
12709
|
return entry.metadata?.category === "workbench" && labels.length === 0;
|
|
@@ -12823,37 +12961,66 @@ function parseMarketSourcesAction(payload) {
|
|
|
12823
12961
|
id: id.trim()
|
|
12824
12962
|
};
|
|
12825
12963
|
}
|
|
12964
|
+
if (action === "read-only") {
|
|
12965
|
+
const id = record["id"];
|
|
12966
|
+
if (typeof id !== "string" || id.trim() === "") throw new Error("read-only 需要 id");
|
|
12967
|
+
return {
|
|
12968
|
+
action,
|
|
12969
|
+
id: id.trim()
|
|
12970
|
+
};
|
|
12971
|
+
}
|
|
12826
12972
|
if (action === "init") {
|
|
12827
12973
|
const id = record["id"];
|
|
12828
12974
|
if (typeof id !== "string" || id.trim() === "") throw new Error("init 需要 id");
|
|
12829
12975
|
const ref = typeof record["ref"] === "string" ? record["ref"].trim() : "";
|
|
12830
12976
|
if (ref !== "" && !marketBranchOk(ref)) throw new Error(`分支名不合格:${ref}`);
|
|
12977
|
+
const stampOnly = record["stampOnly"] === true;
|
|
12831
12978
|
return {
|
|
12832
12979
|
action,
|
|
12833
12980
|
id: id.trim(),
|
|
12834
|
-
...ref === "" ? {} : { ref }
|
|
12981
|
+
...ref === "" ? {} : { ref },
|
|
12982
|
+
...stampOnly ? { stampOnly } : {}
|
|
12835
12983
|
};
|
|
12836
12984
|
}
|
|
12837
12985
|
throw new Error(`不认识的索引源动作:${String(action)}`);
|
|
12838
12986
|
}
|
|
12987
|
+
async function markSourceReadOnly(store, id) {
|
|
12988
|
+
const source = store.read().sources.find((one) => one.id === id);
|
|
12989
|
+
if (source === void 0) throw new Error("这个索引源已经不在了 —— 刷新后再试");
|
|
12990
|
+
if (source.kind !== "git") throw new Error("http 索引源本来就是只读");
|
|
12991
|
+
const next = {
|
|
12992
|
+
...source,
|
|
12993
|
+
policy: "catalog-only"
|
|
12994
|
+
};
|
|
12995
|
+
if (source.policy !== "catalog-only") await store.apply({
|
|
12996
|
+
action: "save",
|
|
12997
|
+
source: next
|
|
12998
|
+
});
|
|
12999
|
+
return next;
|
|
13000
|
+
}
|
|
12839
13001
|
function marketSourcesAction(store, init) {
|
|
12840
13002
|
return {
|
|
12841
13003
|
resource: MARKET_SOURCES_RESOURCE,
|
|
12842
13004
|
async handle(payload) {
|
|
12843
13005
|
const action = parseMarketSourcesAction(payload);
|
|
13006
|
+
if (action.action === "read-only") {
|
|
13007
|
+
const source = await markSourceReadOnly(store, action.id);
|
|
13008
|
+
return {
|
|
13009
|
+
ok: true,
|
|
13010
|
+
...store.read(),
|
|
13011
|
+
source
|
|
13012
|
+
};
|
|
13013
|
+
}
|
|
12844
13014
|
if (action.action === "init") {
|
|
12845
13015
|
if (init === void 0) throw new Error("这台机器上没有 shell 服务,初始化不了索引仓库");
|
|
12846
13016
|
const result = await init({
|
|
12847
13017
|
id: action.id,
|
|
12848
|
-
...action.ref === void 0 ? {} : { ref: action.ref }
|
|
13018
|
+
...action.ref === void 0 ? {} : { ref: action.ref },
|
|
13019
|
+
...action.stampOnly === true ? { stampOnly: true } : {}
|
|
12849
13020
|
});
|
|
12850
13021
|
return {
|
|
12851
13022
|
ok: true,
|
|
12852
|
-
...
|
|
12853
|
-
action: "save",
|
|
12854
|
-
source: result.source,
|
|
12855
|
-
select: true
|
|
12856
|
-
}),
|
|
13023
|
+
...store.read(),
|
|
12857
13024
|
branch: result.branch,
|
|
12858
13025
|
commit: result.commit,
|
|
12859
13026
|
created: result.created
|
|
@@ -12873,20 +13040,29 @@ function publishPreviewRoutes(workshop, inferredAuthorOf = async () => void 0) {
|
|
|
12873
13040
|
const unit = (param(search, "unit") ?? "").trim();
|
|
12874
13041
|
const version = (param(search, "version") ?? "").trim();
|
|
12875
13042
|
const author = (param(search, "author") ?? "").trim();
|
|
13043
|
+
const changelog = param(search, "changelog") ?? "";
|
|
13044
|
+
const changelogType = (param(search, "changelogType") ?? "").trim();
|
|
12876
13045
|
if (unit === "") return {
|
|
12877
13046
|
ok: true,
|
|
12878
13047
|
preview: null
|
|
12879
13048
|
};
|
|
12880
13049
|
let preview = publishPreviewOf(workshop, unit, {
|
|
12881
13050
|
version,
|
|
12882
|
-
author
|
|
13051
|
+
author,
|
|
13052
|
+
changelog,
|
|
13053
|
+
changelogType
|
|
12883
13054
|
});
|
|
12884
13055
|
if (preview !== null && author === "" && (preview.author === void 0 || preview.author === "")) {
|
|
12885
13056
|
const inferred = await inferredAuthorOf(unit);
|
|
12886
|
-
if (inferred !== void 0 && inferred !== "")
|
|
12887
|
-
|
|
12888
|
-
|
|
12889
|
-
|
|
13057
|
+
if (inferred !== void 0 && inferred !== "") {
|
|
13058
|
+
const again = publishPreviewOf(workshop, unit, {
|
|
13059
|
+
version,
|
|
13060
|
+
author: inferred,
|
|
13061
|
+
changelog,
|
|
13062
|
+
changelogType
|
|
13063
|
+
});
|
|
13064
|
+
if (again !== null) preview = again;
|
|
13065
|
+
}
|
|
12890
13066
|
}
|
|
12891
13067
|
return {
|
|
12892
13068
|
ok: true,
|
|
@@ -13513,17 +13689,21 @@ function createMarketSourceInitializer(options) {
|
|
|
13513
13689
|
if (created.exitCode !== 0) throw new Error(`建分支 ${branch} 没过:${tailLines(created.stderr, 4)}`);
|
|
13514
13690
|
}
|
|
13515
13691
|
const indexPath = (source.path ?? "market.json").replace(/^\/+/, "") || "market.json";
|
|
13516
|
-
const written = [];
|
|
13517
13692
|
const indexFile = join(workdir, indexPath);
|
|
13518
|
-
|
|
13519
|
-
|
|
13520
|
-
|
|
13521
|
-
|
|
13522
|
-
|
|
13523
|
-
|
|
13524
|
-
|
|
13525
|
-
|
|
13526
|
-
|
|
13693
|
+
const stampOnly = request.stampOnly === true;
|
|
13694
|
+
if (stampOnly && !existsSync(indexFile)) throw new Error(`仓库里还没有 ${indexPath} —— 先选中这个源,按发现页的提示把它初始化成索引`);
|
|
13695
|
+
const written = [];
|
|
13696
|
+
if (!stampOnly) {
|
|
13697
|
+
if (!existsSync(indexFile)) {
|
|
13698
|
+
mkdirSync(dirname(indexFile), { recursive: true });
|
|
13699
|
+
writeFileSync(indexFile, MARKET_INDEX_SEED);
|
|
13700
|
+
written.push(indexPath);
|
|
13701
|
+
}
|
|
13702
|
+
const readmeFile = join(workdir, "README.md");
|
|
13703
|
+
if (!existsSync(readmeFile)) {
|
|
13704
|
+
writeFileSync(readmeFile, MARKET_INDEX_README_LINES.join("\n"));
|
|
13705
|
+
written.push("README.md");
|
|
13706
|
+
}
|
|
13527
13707
|
}
|
|
13528
13708
|
if (written.length > 0) {
|
|
13529
13709
|
const added = await git(["add", ...written], workdir);
|
|
@@ -13550,8 +13730,7 @@ function createMarketSourceInitializer(options) {
|
|
|
13550
13730
|
};
|
|
13551
13731
|
await options.store.apply({
|
|
13552
13732
|
action: "save",
|
|
13553
|
-
source: next
|
|
13554
|
-
select: true
|
|
13733
|
+
source: next
|
|
13555
13734
|
});
|
|
13556
13735
|
forget(source, next);
|
|
13557
13736
|
return {
|
|
@@ -13678,6 +13857,73 @@ async function dispatchMarket(market, request) {
|
|
|
13678
13857
|
};
|
|
13679
13858
|
}
|
|
13680
13859
|
//#endregion
|
|
13860
|
+
//#region src/modules/panels/model/market-sources-tool.ts
|
|
13861
|
+
var OUTPUT$2 = {
|
|
13862
|
+
schema: {
|
|
13863
|
+
type: "object",
|
|
13864
|
+
properties: {
|
|
13865
|
+
text: { type: "string" },
|
|
13866
|
+
sources: {
|
|
13867
|
+
type: "array",
|
|
13868
|
+
items: {
|
|
13869
|
+
type: "object",
|
|
13870
|
+
additionalProperties: true
|
|
13871
|
+
}
|
|
13872
|
+
}
|
|
13873
|
+
},
|
|
13874
|
+
additionalProperties: true
|
|
13875
|
+
},
|
|
13876
|
+
render: (_args, value) => {
|
|
13877
|
+
const payload = value;
|
|
13878
|
+
return [{
|
|
13879
|
+
type: "text",
|
|
13880
|
+
text: typeof payload?.text === "string" ? payload.text : JSON.stringify(value)
|
|
13881
|
+
}];
|
|
13882
|
+
}
|
|
13883
|
+
};
|
|
13884
|
+
function marketSourcesTool(read) {
|
|
13885
|
+
return {
|
|
13886
|
+
name: MARKET_SOURCES_TOOL,
|
|
13887
|
+
description: "看本机的索引源:id、地址、是否可发布、当前用的是哪个。",
|
|
13888
|
+
parameters: {
|
|
13889
|
+
type: "object",
|
|
13890
|
+
properties: {},
|
|
13891
|
+
additionalProperties: false
|
|
13892
|
+
},
|
|
13893
|
+
output: OUTPUT$2,
|
|
13894
|
+
async execute() {
|
|
13895
|
+
if (read === void 0) throw new Error("这台机器上没有索引源服务,看不了");
|
|
13896
|
+
const payload = read();
|
|
13897
|
+
const rows = payload.sources.map((source) => ({
|
|
13898
|
+
id: source.id,
|
|
13899
|
+
label: source.label,
|
|
13900
|
+
kind: source.kind,
|
|
13901
|
+
url: source.url,
|
|
13902
|
+
policy: source.policy ?? "catalog-only",
|
|
13903
|
+
ref: source.ref ?? null,
|
|
13904
|
+
path: source.path ?? null,
|
|
13905
|
+
selected: source.id === payload.selected
|
|
13906
|
+
}));
|
|
13907
|
+
if (rows.length === 0) return {
|
|
13908
|
+
sources: rows,
|
|
13909
|
+
selected: payload.selected,
|
|
13910
|
+
text: "这台机器还没有索引源 —— 在「模块市场 → 发现 → 索引源」里加一个。"
|
|
13911
|
+
};
|
|
13912
|
+
const current = rows.find((one) => one.selected);
|
|
13913
|
+
const head = current === void 0 ? "当前没有选中索引源" : `当前:${current.label}(${current.url})`;
|
|
13914
|
+
const lines = rows.map((one) => {
|
|
13915
|
+
const state = one.policy === "artifacts-in-repo" ? "可发布" : "仅读取模块列表";
|
|
13916
|
+
return `${one.selected ? "●" : "○"} ${one.id} · ${one.label} · ${one.kind} · ${state} · ${one.url}`;
|
|
13917
|
+
});
|
|
13918
|
+
return {
|
|
13919
|
+
sources: rows,
|
|
13920
|
+
selected: payload.selected,
|
|
13921
|
+
text: [head, ...lines].join("\n")
|
|
13922
|
+
};
|
|
13923
|
+
}
|
|
13924
|
+
};
|
|
13925
|
+
}
|
|
13926
|
+
//#endregion
|
|
13681
13927
|
//#region src/modules/panels/model/market-tools.ts
|
|
13682
13928
|
function supplyNamesOf(entry) {
|
|
13683
13929
|
return entry.needs.filter((need) => need.kind === "extension" || need.kind === "lib").map((need) => need.name);
|
|
@@ -13773,7 +14019,7 @@ function usersOf(shared, names) {
|
|
|
13773
14019
|
if (hit === void 0 || hit.usedBy.length === 0) return "";
|
|
13774
14020
|
return `它被 ${hit.usedBy.join("、")} 用着(动的是它们的供给,它们的状态跟着重探了一遍)`;
|
|
13775
14021
|
}
|
|
13776
|
-
function registerMarketTools(ctx, market) {
|
|
14022
|
+
function registerMarketTools(ctx, market, sources) {
|
|
13777
14023
|
const tools = ctx.get("tools");
|
|
13778
14024
|
if (tools === void 0) {
|
|
13779
14025
|
ctx.logger?.info?.("[dsh-workbench] 没有 tools 服务,跳过模块市场工具注册");
|
|
@@ -13972,6 +14218,82 @@ function registerMarketTools(ctx, market) {
|
|
|
13972
14218
|
};
|
|
13973
14219
|
}
|
|
13974
14220
|
};
|
|
14221
|
+
const enableTool = {
|
|
14222
|
+
name: MARKET_ENABLE_TOOL,
|
|
14223
|
+
description: "把索引源设为可发布(只改本机配置,不碰仓库);要用户审批。",
|
|
14224
|
+
parameters: {
|
|
14225
|
+
type: "object",
|
|
14226
|
+
properties: { id: {
|
|
14227
|
+
type: "string",
|
|
14228
|
+
description: "索引源 id;不填=当前选中的那个。"
|
|
14229
|
+
} },
|
|
14230
|
+
additionalProperties: false
|
|
14231
|
+
},
|
|
14232
|
+
output: OUTPUT$1,
|
|
14233
|
+
async execute(raw) {
|
|
14234
|
+
if (sources === void 0) throw new Error("这台机器上没有索引源服务,设不了可发布");
|
|
14235
|
+
const payload = sources.read();
|
|
14236
|
+
const asked = textArg(raw, "id");
|
|
14237
|
+
const id = asked === "" ? payload.selected : asked;
|
|
14238
|
+
const source = id === null ? void 0 : payload.sources.find((one) => one.id === id);
|
|
14239
|
+
if (source === void 0) {
|
|
14240
|
+
const known = payload.sources.map((one) => one.id).join("、") || "(空)";
|
|
14241
|
+
throw new Error(`没有这个索引源${asked === "" ? "" : `:${asked}`}。现有的:${known};先在「模块市场 → 发现 → 索引源」里加一个。`);
|
|
14242
|
+
}
|
|
14243
|
+
if (source.kind !== "git") throw new Error(`索引源 ${source.id} 是 http 地址,只能读,不能当发布目的地`);
|
|
14244
|
+
if (source.policy === "artifacts-in-repo") return {
|
|
14245
|
+
source,
|
|
14246
|
+
changed: false,
|
|
14247
|
+
text: `已经是可发布:${source.label}(${source.url})`
|
|
14248
|
+
};
|
|
14249
|
+
const result = await sources.init({
|
|
14250
|
+
id: source.id,
|
|
14251
|
+
stampOnly: true
|
|
14252
|
+
});
|
|
14253
|
+
return {
|
|
14254
|
+
source: result.source,
|
|
14255
|
+
branch: result.branch,
|
|
14256
|
+
commit: result.commit,
|
|
14257
|
+
changed: true,
|
|
14258
|
+
text: `已把「${source.label}」设为可发布(${source.url},分支 ${result.branch})—— 仓库本身没动。之后发布可以落到它的 ${source.path ?? "market.json"}。`
|
|
14259
|
+
};
|
|
14260
|
+
}
|
|
14261
|
+
};
|
|
14262
|
+
const readOnlyTool = {
|
|
14263
|
+
name: MARKET_DISABLE_TOOL,
|
|
14264
|
+
description: "把索引源改回只读(不再作为发布目的地;只改本机配置)。",
|
|
14265
|
+
parameters: {
|
|
14266
|
+
type: "object",
|
|
14267
|
+
properties: { id: {
|
|
14268
|
+
type: "string",
|
|
14269
|
+
description: "索引源 id;不填=当前选中的那个。"
|
|
14270
|
+
} },
|
|
14271
|
+
additionalProperties: false
|
|
14272
|
+
},
|
|
14273
|
+
output: OUTPUT$1,
|
|
14274
|
+
async execute(raw) {
|
|
14275
|
+
if (sources === void 0) throw new Error("这台机器上没有索引源服务,改不了");
|
|
14276
|
+
const payload = sources.read();
|
|
14277
|
+
const asked = textArg(raw, "id");
|
|
14278
|
+
const id = asked === "" ? payload.selected : asked;
|
|
14279
|
+
const source = id === null ? void 0 : payload.sources.find((one) => one.id === id);
|
|
14280
|
+
if (source === void 0) {
|
|
14281
|
+
const known = payload.sources.map((one) => one.id).join("、") || "(空)";
|
|
14282
|
+
throw new Error(`没有这个索引源${asked === "" ? "" : `:${asked}`}。现有的:${known};先在「模块市场 → 发现 → 索引源」里加一个。`);
|
|
14283
|
+
}
|
|
14284
|
+
if (source.kind !== "git") throw new Error(`索引源 ${source.id} 是 http 地址,本来就是只读`);
|
|
14285
|
+
if (source.policy === "catalog-only") return {
|
|
14286
|
+
source,
|
|
14287
|
+
changed: false,
|
|
14288
|
+
text: `已经是只读:${source.label}(${source.url})`
|
|
14289
|
+
};
|
|
14290
|
+
return {
|
|
14291
|
+
source: await sources.readOnly(source.id),
|
|
14292
|
+
changed: true,
|
|
14293
|
+
text: `已把「${source.label}」设为只读(${source.url})—— 发布不会再落到它。`
|
|
14294
|
+
};
|
|
14295
|
+
}
|
|
14296
|
+
};
|
|
13975
14297
|
return [
|
|
13976
14298
|
tools.register(listTool),
|
|
13977
14299
|
tools.register(installTool),
|
|
@@ -13981,7 +14303,10 @@ function registerMarketTools(ctx, market) {
|
|
|
13981
14303
|
tools.register(updateDependencyTool),
|
|
13982
14304
|
tools.register(updatePluginTool),
|
|
13983
14305
|
tools.register(uninstallPluginTool),
|
|
13984
|
-
tools.register(updateWorkbenchTool)
|
|
14306
|
+
tools.register(updateWorkbenchTool),
|
|
14307
|
+
tools.register(marketSourcesTool(sources === void 0 ? void 0 : () => sources.read())),
|
|
14308
|
+
tools.register(enableTool),
|
|
14309
|
+
tools.register(readOnlyTool)
|
|
13985
14310
|
];
|
|
13986
14311
|
}
|
|
13987
14312
|
//#endregion
|
|
@@ -14099,6 +14424,7 @@ function listedRunUnits(result) {
|
|
|
14099
14424
|
}
|
|
14100
14425
|
function panelsFactsOf(call, manifests) {
|
|
14101
14426
|
if (call.source === "workbench_panels_list") return [PANELS_FACT];
|
|
14427
|
+
if (call.source === "market-sources") return [PANELS_FACT];
|
|
14102
14428
|
if (call.source === "workbench_long_tasks_list") return listedRunUnits(call.result).map(runsRouteOf);
|
|
14103
14429
|
if (call.source === "workbench_modules_list") return [PANELS_FACT, CAPABILITY_FACT];
|
|
14104
14430
|
if (call.source === "workbench_modules_update_workbench") return [PANELS_FACT, CAPABILITY_FACT];
|
|
@@ -14793,13 +15119,17 @@ var OWNED = [{
|
|
|
14793
15119
|
},
|
|
14794
15120
|
registerTools: () => [
|
|
14795
15121
|
...registerPanelTools(ctx, panels, values),
|
|
14796
|
-
...registerMarketTools(ctx, market
|
|
15122
|
+
...registerMarketTools(ctx, market, {
|
|
15123
|
+
read: () => marketSources.read(),
|
|
15124
|
+
init: marketInit,
|
|
15125
|
+
readOnly: (id) => markSourceReadOnly(marketSources, id)
|
|
15126
|
+
}),
|
|
14797
15127
|
...registerDiyTools(ctx, market, panels, debug, (unit) => publishPreviewOf(workshopPathOf(ctx), unit), (unit) => inferredAuthorOf(workshopPathOf(ctx), unit, shell)),
|
|
14798
15128
|
...registerRecordTools(ctx, record),
|
|
14799
15129
|
...registerLongTaskTools(ctx, longTaskRuns)
|
|
14800
15130
|
],
|
|
14801
15131
|
factsOf: (call) => panelsFactsOf(call, manifests()),
|
|
14802
|
-
needsApproval: panelsApprovalFor(longTaskRuns, () => record.live(Date.now()), (unit) => publishPreviewOf(workshopPathOf(ctx), unit)),
|
|
15132
|
+
needsApproval: panelsApprovalFor(longTaskRuns, () => record.live(Date.now()), (unit, author) => publishPreviewOf(workshopPathOf(ctx), unit, author === void 0 ? {} : { author }), marketSources),
|
|
14803
15133
|
gate: {
|
|
14804
15134
|
deniedTools: (context) => {
|
|
14805
15135
|
const boards = panels.boards(context.workspace);
|