@dsh-workbench/core 1.1.0 → 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 +726 -397
- package/dist/client/client.body.js +726 -397
- package/dist/client/index.js +587 -258
- package/dist/host/index.js +657 -328
- package/dist/types/app/layouts/approval-detail.d.ts +2 -1
- package/dist/types/app/layouts/market/discover-search.d.ts +8 -0
- 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
|
@@ -556,10 +556,8 @@ function readDeclaration(subject, raw) {
|
|
|
556
556
|
zh: text$2(declaration.title.zh),
|
|
557
557
|
en: text$2(declaration.title.en)
|
|
558
558
|
},
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
order: card.order
|
|
562
|
-
},
|
|
559
|
+
titleKey: unitTitleKey(id),
|
|
560
|
+
card: card === null ? null : { order: card.order },
|
|
563
561
|
tools: declaration.tools.map((tool) => ({
|
|
564
562
|
name: text$2(tool.name),
|
|
565
563
|
writes: tool.writes
|
|
@@ -4579,7 +4577,10 @@ var MARKET_INDEX_README_LINES = [
|
|
|
4579
4577
|
"dsh-wb-module release --index <本仓库地址> --index-policy artifacts-in-repo",
|
|
4580
4578
|
"```",
|
|
4581
4579
|
"",
|
|
4582
|
-
"产物会提交到 `packages
|
|
4580
|
+
"产物会提交到 `packages/<包名>/`(带 scope 时是 `packages/@scope/名字/`),并更新 `market.json`。",
|
|
4581
|
+
"",
|
|
4582
|
+
"一个包名归第一次发布的人(`market.json` 里的 `owner`)。换一个署名发同名会被拒;要换人,先把这一条的 `owner` 改成新的人。",
|
|
4583
|
+
"同一个市场里,一个模块 id(`metadata.unit`)只能被一个条目使用;另一个包名想用同一个 id / 产物目录也会被拒。",
|
|
4583
4584
|
"",
|
|
4584
4585
|
"## 使用这个索引",
|
|
4585
4586
|
"",
|
|
@@ -4685,15 +4686,25 @@ function iconProblem(icon) {
|
|
|
4685
4686
|
if (/^https?:\/\//i.test(icon)) return void 0;
|
|
4686
4687
|
return problem("icon", "icon 只能是 base64 data URL 或 http(s) URL");
|
|
4687
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
|
+
}
|
|
4688
4695
|
function metadataOf(raw) {
|
|
4689
4696
|
const record = asRecord$3(raw);
|
|
4690
4697
|
if (record === void 0) return void 0;
|
|
4698
|
+
const workbench = record["workbench"] === true;
|
|
4699
|
+
const unit = asText$3(record["unit"]);
|
|
4691
4700
|
const category = asText$3(record["category"]);
|
|
4692
4701
|
const labels = asTextArray(record["labels"]);
|
|
4693
4702
|
const keywords = asTextArray(record["keywords"]);
|
|
4694
4703
|
const sortKeysRecord = asRecord$3(record["sortKeys"]);
|
|
4695
4704
|
const sortKeys = sortKeysRecord === void 0 ? void 0 : Object.fromEntries(Object.entries(sortKeysRecord).flatMap(([key, value]) => typeof value === "string" || typeof value === "number" ? [[key, value]] : []));
|
|
4696
4705
|
return {
|
|
4706
|
+
...workbench ? { workbench: true } : {},
|
|
4707
|
+
...unit === "" ? {} : { unit },
|
|
4697
4708
|
...category === "" ? {} : { category },
|
|
4698
4709
|
...labels.length === 0 ? {} : { labels },
|
|
4699
4710
|
...keywords.length === 0 ? {} : { keywords },
|
|
@@ -4715,14 +4726,21 @@ function entryOf$1(raw, at) {
|
|
|
4715
4726
|
const title = asLocalized(record["title"]);
|
|
4716
4727
|
const description = asLocalized(record["description"]);
|
|
4717
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
|
+
}
|
|
4718
4734
|
const homepage = asText$3(record["homepage"]);
|
|
4719
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);
|
|
4720
4737
|
return {
|
|
4721
4738
|
name,
|
|
4722
4739
|
versions,
|
|
4723
4740
|
...title === void 0 ? {} : { title },
|
|
4724
4741
|
...description === void 0 ? {} : { description },
|
|
4725
4742
|
...author === "" ? {} : { author },
|
|
4743
|
+
...owner === "" ? {} : { owner },
|
|
4726
4744
|
...homepage === "" ? {} : { homepage },
|
|
4727
4745
|
...icon === "" ? {} : { icon },
|
|
4728
4746
|
...metadata === void 0 ? {} : { metadata }
|
|
@@ -4909,6 +4927,84 @@ function gitUrlOk(url) {
|
|
|
4909
4927
|
return true;
|
|
4910
4928
|
}
|
|
4911
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
|
|
4912
5008
|
//#region ../shared/dist/host/changelog.js
|
|
4913
5009
|
var CHANGELOG_FILE = "CHANGELOG.md";
|
|
4914
5010
|
var CHANGELOG_KINDS = [
|
|
@@ -5066,6 +5162,25 @@ function appendChangelogEntry(text, options) {
|
|
|
5066
5162
|
out.splice(at, 0, ...bullets);
|
|
5067
5163
|
return `${normalizeWhitespace(out)}\n`;
|
|
5068
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
|
+
}
|
|
5069
5184
|
function normalizeWhitespace(rows) {
|
|
5070
5185
|
const out = [];
|
|
5071
5186
|
for (const row of rows) {
|
|
@@ -5460,12 +5575,14 @@ var MODULES_UPDATE_DEPENDENCY_TOOL = "workbench_modules_update_dependency";
|
|
|
5460
5575
|
var MODULES_UPDATE_PLUGIN_TOOL = "workbench_modules_update_plugin";
|
|
5461
5576
|
var MODULES_UNINSTALL_PLUGIN_TOOL = "workbench_modules_uninstall_plugin";
|
|
5462
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";
|
|
5463
5581
|
var DIY_STATUS_TOOL = "workbench_diy_status";
|
|
5464
5582
|
var DIY_PANEL_TOOL = "workbench_diy_panel";
|
|
5465
5583
|
var DIY_COMPONENTS_TOOL = "workbench_diy_components";
|
|
5466
5584
|
var DIY_RECON_TOOL = "workbench_diy_recon";
|
|
5467
5585
|
var DIY_SPEC_TOOL = "workbench_diy_spec";
|
|
5468
|
-
var DIY_CHANGELOG_TOOL = "workbench_diy_changelog";
|
|
5469
5586
|
var DIY_INSTALL_TOOL = "workbench_diy_install";
|
|
5470
5587
|
var DIY_PUBLISH_TOOL = "workbench_diy_publish";
|
|
5471
5588
|
var DIY_SHOW_TOOL = "workbench_diy_show";
|
|
@@ -5499,6 +5616,7 @@ var DIY_DEBUG_STOP_TOOL = "workbench_diy_debug_stop";
|
|
|
5499
5616
|
var READ_TOOLS = [
|
|
5500
5617
|
PANELS_LIST_TOOL,
|
|
5501
5618
|
MODULES_LIST_TOOL,
|
|
5619
|
+
MARKET_SOURCES_TOOL,
|
|
5502
5620
|
DIY_STATUS_TOOL,
|
|
5503
5621
|
DIY_PANEL_TOOL,
|
|
5504
5622
|
DIY_COMPONENTS_TOOL,
|
|
@@ -5540,7 +5658,8 @@ var WRITE_TOOLS = [
|
|
|
5540
5658
|
MODULES_UPDATE_PLUGIN_TOOL,
|
|
5541
5659
|
MODULES_UNINSTALL_PLUGIN_TOOL,
|
|
5542
5660
|
MODULES_UPDATE_WORKBENCH_TOOL,
|
|
5543
|
-
|
|
5661
|
+
MARKET_ENABLE_TOOL,
|
|
5662
|
+
MARKET_DISABLE_TOOL,
|
|
5544
5663
|
DIY_INSTALL_TOOL,
|
|
5545
5664
|
DIY_PUBLISH_TOOL,
|
|
5546
5665
|
DIY_SHOW_TOOL,
|
|
@@ -5557,7 +5676,6 @@ var DIY_TOOLS = [
|
|
|
5557
5676
|
DIY_COMPONENTS_TOOL,
|
|
5558
5677
|
DIY_RECON_TOOL,
|
|
5559
5678
|
DIY_SPEC_TOOL,
|
|
5560
|
-
DIY_CHANGELOG_TOOL,
|
|
5561
5679
|
DIY_INSTALL_TOOL,
|
|
5562
5680
|
DIY_PUBLISH_TOOL,
|
|
5563
5681
|
DIY_SHOW_TOOL,
|
|
@@ -5601,6 +5719,7 @@ function screenOnlyToolsFor(pageDebug) {
|
|
|
5601
5719
|
}
|
|
5602
5720
|
var panelsUnit = {
|
|
5603
5721
|
id: "panels",
|
|
5722
|
+
titleKey: "panels.title",
|
|
5604
5723
|
card: null,
|
|
5605
5724
|
tools: [...READ_TOOLS.map((name) => ({
|
|
5606
5725
|
name,
|
|
@@ -5833,6 +5952,14 @@ function readDomainsOf(design) {
|
|
|
5833
5952
|
return [...found];
|
|
5834
5953
|
}
|
|
5835
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
|
|
5836
5963
|
//#region src/modules/panels/model/approval.ts
|
|
5837
5964
|
var SPEC_LIMIT = 80;
|
|
5838
5965
|
var TARGET_LIMIT = 20;
|
|
@@ -5939,11 +6066,22 @@ function publishVerdict(call, preview) {
|
|
|
5939
6066
|
if (raw["verify"] === true || raw["target"] === "local") return { kind: "allow" };
|
|
5940
6067
|
const refresh = raw["refresh"] === true;
|
|
5941
6068
|
const unit = textOf$3(raw, "unit");
|
|
5942
|
-
const
|
|
6069
|
+
const askedAuthor = textOf$3(raw, "author");
|
|
6070
|
+
const found = unit === "" ? null : preview?.(unit, askedAuthor === "" ? void 0 : askedAuthor) ?? null;
|
|
5943
6071
|
const asked = textOf$3(raw, "target");
|
|
5944
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
|
+
};
|
|
5945
6079
|
const label = unit === "" ? "工作台模块" : `工作台模块 [${unit}]`;
|
|
5946
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
|
+
};
|
|
5947
6085
|
const copies = {
|
|
5948
6086
|
team: {
|
|
5949
6087
|
zh: `把${label}发到团队源,只发构建产物,不发源码,允许吗?`,
|
|
@@ -5975,7 +6113,7 @@ function publishVerdict(call, preview) {
|
|
|
5975
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);
|
|
5976
6114
|
return askOf(`${DIY_PUBLISH_TOOL} ${targetLabel}${refresh ? "(元数据)" : ""}`, question, question);
|
|
5977
6115
|
}
|
|
5978
|
-
|
|
6116
|
+
function approvalVerdict(call, marketSource) {
|
|
5979
6117
|
if (call.name === "workbench_long_tasks_stop") return stopVerdict(call, void 0);
|
|
5980
6118
|
if (call.name === "workbench_diy_publish") return publishVerdict(call);
|
|
5981
6119
|
if (call.name === "workbench_diy_debug_start" || call.name === "workbench_diy_debug_resume") {
|
|
@@ -6046,9 +6184,41 @@ var panelsApproval = (call) => {
|
|
|
6046
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?`));
|
|
6047
6185
|
}
|
|
6048
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
|
+
}
|
|
6049
6219
|
default: return;
|
|
6050
6220
|
}
|
|
6051
|
-
}
|
|
6221
|
+
}
|
|
6052
6222
|
function recordHeldVerdict(call, recording) {
|
|
6053
6223
|
if (call.name !== "workbench_diy_record_prepare" || recording === void 0) return void 0;
|
|
6054
6224
|
const held = recording();
|
|
@@ -6058,11 +6228,16 @@ function recordHeldVerdict(call, recording) {
|
|
|
6058
6228
|
reason: recordRefusalText(held.sessionId === call.session ? "already-held" : "held-by-other", held)
|
|
6059
6229
|
};
|
|
6060
6230
|
}
|
|
6061
|
-
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
|
+
};
|
|
6062
6237
|
return (call) => {
|
|
6063
6238
|
if (call.name === "workbench_long_tasks_stop") return stopVerdict(call, longTaskRuns);
|
|
6064
6239
|
if (call.name === "workbench_diy_publish") return publishVerdict(call, publishPreview);
|
|
6065
|
-
return recordHeldVerdict(call, recording) ??
|
|
6240
|
+
return recordHeldVerdict(call, recording) ?? approvalVerdict(call, sourceOf);
|
|
6066
6241
|
};
|
|
6067
6242
|
}
|
|
6068
6243
|
//#endregion
|
|
@@ -6128,7 +6303,7 @@ function resolvePanels(manifests, boards, owned = /* @__PURE__ */ new Set()) {
|
|
|
6128
6303
|
const order = hasCard ? rank.get(manifest.id) ?? ordered.length + declared(manifest) : 0;
|
|
6129
6304
|
return {
|
|
6130
6305
|
id: manifest.id,
|
|
6131
|
-
titleKey: manifest.
|
|
6306
|
+
titleKey: manifest.titleKey,
|
|
6132
6307
|
order,
|
|
6133
6308
|
shown: on,
|
|
6134
6309
|
source: overrideOf(boards.workspace, manifest.id) === void 0 ? "default" : "user",
|
|
@@ -6979,7 +7154,7 @@ async function sessionWorkspaceOf(ctx, workspace) {
|
|
|
6979
7154
|
dir = parent;
|
|
6980
7155
|
}
|
|
6981
7156
|
}
|
|
6982
|
-
var OUTPUT$
|
|
7157
|
+
var OUTPUT$3 = {
|
|
6983
7158
|
schema: {
|
|
6984
7159
|
type: "object",
|
|
6985
7160
|
properties: {
|
|
@@ -7124,7 +7299,7 @@ function componentsTool(ctx) {
|
|
|
7124
7299
|
},
|
|
7125
7300
|
additionalProperties: false
|
|
7126
7301
|
},
|
|
7127
|
-
output: OUTPUT$
|
|
7302
|
+
output: OUTPUT$3,
|
|
7128
7303
|
async execute(raw, exec) {
|
|
7129
7304
|
const { root } = await workspaceOf(ctx, exec);
|
|
7130
7305
|
const args = asRecord$1(raw);
|
|
@@ -7222,97 +7397,6 @@ function registerComponentsTool(ctx, tools) {
|
|
|
7222
7397
|
return [tools.register(componentsTool(ctx))];
|
|
7223
7398
|
}
|
|
7224
7399
|
//#endregion
|
|
7225
|
-
//#region src/shared/api/host/diy-changelog.ts
|
|
7226
|
-
function moduleVersionOf(dir) {
|
|
7227
|
-
try {
|
|
7228
|
-
const version = JSON.parse(readFileSync(join(dir, "package.json"), "utf8")).version;
|
|
7229
|
-
return typeof version === "string" ? version.trim() : "";
|
|
7230
|
-
} catch {
|
|
7231
|
-
return "";
|
|
7232
|
-
}
|
|
7233
|
-
}
|
|
7234
|
-
function writeChangelogEntry(dir, input) {
|
|
7235
|
-
const file = join(dir, CHANGELOG_FILE);
|
|
7236
|
-
const text = appendChangelogEntry(existsSync(file) ? readFileSync(file, "utf8") : changelogSkeleton(), {
|
|
7237
|
-
version: input.version,
|
|
7238
|
-
kind: input.kind,
|
|
7239
|
-
note: input.note,
|
|
7240
|
-
date: input.date ?? changelogDate()
|
|
7241
|
-
});
|
|
7242
|
-
writeFileSync(file, text);
|
|
7243
|
-
return {
|
|
7244
|
-
file,
|
|
7245
|
-
section: changelogSectionOf(text, input.version) ?? "",
|
|
7246
|
-
text
|
|
7247
|
-
};
|
|
7248
|
-
}
|
|
7249
|
-
//#endregion
|
|
7250
|
-
//#region src/modules/panels/model/diy-changelog.ts
|
|
7251
|
-
function toolOf(ctx) {
|
|
7252
|
-
return {
|
|
7253
|
-
name: DIY_CHANGELOG_TOOL,
|
|
7254
|
-
description: `发布前把这一版写进 ${CHANGELOG_FILE}(\`## v0.1.0\` + \`### ✨ 新增\` 这种小节):传 note 就记一条,文件不在就先建。没写这一版时发布会被拦下。`,
|
|
7255
|
-
parameters: {
|
|
7256
|
-
type: "object",
|
|
7257
|
-
properties: {
|
|
7258
|
-
unit: {
|
|
7259
|
-
type: "string",
|
|
7260
|
-
description: "模块 id(workbench_diy_status 会给)。"
|
|
7261
|
-
},
|
|
7262
|
-
version: {
|
|
7263
|
-
type: "string",
|
|
7264
|
-
description: "要写的版本;不填用 package.json 里的 version。"
|
|
7265
|
-
},
|
|
7266
|
-
type: {
|
|
7267
|
-
type: "string",
|
|
7268
|
-
enum: [...CHANGELOG_KINDS],
|
|
7269
|
-
description: "分类:added 新增 / changed 改进 / fixed 修复 / removed 移除 / security 安全 / deprecated 弃用。"
|
|
7270
|
-
},
|
|
7271
|
-
note: {
|
|
7272
|
-
type: "string",
|
|
7273
|
-
description: "这一版改了什么;多行时一行一条(必填)。"
|
|
7274
|
-
}
|
|
7275
|
-
},
|
|
7276
|
-
required: ["unit", "note"],
|
|
7277
|
-
additionalProperties: false
|
|
7278
|
-
},
|
|
7279
|
-
output: OUTPUT$2,
|
|
7280
|
-
async execute(raw, exec) {
|
|
7281
|
-
const { root } = await workspaceOf(ctx, exec);
|
|
7282
|
-
const args = asRecord$1(raw);
|
|
7283
|
-
const unit = asText(args["unit"]);
|
|
7284
|
-
const { units } = unitsOf(ctx, root);
|
|
7285
|
-
if (unit === "") throw new Error(`要一个 unit(这个工作区里:${units.map((one) => one.unit).join(", ") || "(空)"})`);
|
|
7286
|
-
const found = units.find((one) => one.unit === unit && one.dir !== "");
|
|
7287
|
-
if (found === void 0) throw new Error(`这个工作区里没有单元 id 为「${unit}」的模块(可用的:${units.map((one) => one.unit).join(", ") || "(空)"})`);
|
|
7288
|
-
if (!insideRoot(root, found.dir)) throw new Error(`这个模块不在这个工作区里(${found.dir})`);
|
|
7289
|
-
const note = asText(args["note"]).trim();
|
|
7290
|
-
if (note === "") throw new Error("要一句 note:这一版改了什么");
|
|
7291
|
-
const version = (asText(args["version"]) || moduleVersionOf(found.dir)).replace(/^v/, "");
|
|
7292
|
-
if (!isValidVersion(version)) throw new Error(`版本要写成 x.y.z(收到「${version}」)—— 也可以不填,用 package.json 里的`);
|
|
7293
|
-
const kind = asText(args["type"]) || "changed";
|
|
7294
|
-
if (!CHANGELOG_KINDS.includes(kind)) throw new Error(`type 只认 ${CHANGELOG_KINDS.join(" / ")}(收到「${kind}」)`);
|
|
7295
|
-
const written = writeChangelogEntry(found.dir, {
|
|
7296
|
-
version,
|
|
7297
|
-
kind,
|
|
7298
|
-
note
|
|
7299
|
-
});
|
|
7300
|
-
return plainJson({
|
|
7301
|
-
ok: true,
|
|
7302
|
-
unit,
|
|
7303
|
-
version,
|
|
7304
|
-
type: kind,
|
|
7305
|
-
path: written.file,
|
|
7306
|
-
section: written.section,
|
|
7307
|
-
text: `${CHANGELOG_FILE} 已记下 ${version}(${kind})。发布时会带进包和市场索引,审批屏会展示它。`
|
|
7308
|
-
});
|
|
7309
|
-
}
|
|
7310
|
-
};
|
|
7311
|
-
}
|
|
7312
|
-
function registerChangelogTool(ctx, tools) {
|
|
7313
|
-
return [tools.register(toolOf(ctx))];
|
|
7314
|
-
}
|
|
7315
|
-
//#endregion
|
|
7316
7400
|
//#region src/shared/api/host/diy-artifacts.ts
|
|
7317
7401
|
function artifactsDirOf(ctx, root) {
|
|
7318
7402
|
const homePath = ctx.get("dshHomePath");
|
|
@@ -7599,7 +7683,7 @@ function registerDebugTools(ctx, tools, store) {
|
|
|
7599
7683
|
required: [],
|
|
7600
7684
|
additionalProperties: false
|
|
7601
7685
|
},
|
|
7602
|
-
output: OUTPUT$
|
|
7686
|
+
output: OUTPUT$3,
|
|
7603
7687
|
async execute(raw, exec) {
|
|
7604
7688
|
const { root, title } = await workspaceOf(ctx, exec);
|
|
7605
7689
|
const { units } = unitsOf(ctx, root);
|
|
@@ -7634,7 +7718,7 @@ function registerDebugTools(ctx, tools, store) {
|
|
|
7634
7718
|
name: DIY_DEBUG_PAUSE_TOOL,
|
|
7635
7719
|
description: "暂停调试(不审批):屏工具停用,不再拿屏当目标。要接着看用 debug_resume。",
|
|
7636
7720
|
parameters: EMPTY,
|
|
7637
|
-
output: OUTPUT$
|
|
7721
|
+
output: OUTPUT$3,
|
|
7638
7722
|
async execute(_raw, exec) {
|
|
7639
7723
|
const { root } = await workspaceOf(ctx, exec);
|
|
7640
7724
|
const held = store.live(Date.now());
|
|
@@ -7652,7 +7736,7 @@ function registerDebugTools(ctx, tools, store) {
|
|
|
7652
7736
|
name: DIY_DEBUG_RESUME_TOOL,
|
|
7653
7737
|
description: "继续调试(要点头一次):请用户回到这一场调试所在的那一屏。",
|
|
7654
7738
|
parameters: EMPTY,
|
|
7655
|
-
output: OUTPUT$
|
|
7739
|
+
output: OUTPUT$3,
|
|
7656
7740
|
async execute(_raw, exec) {
|
|
7657
7741
|
const { root } = await workspaceOf(ctx, exec);
|
|
7658
7742
|
const held = store.live(Date.now());
|
|
@@ -7676,7 +7760,7 @@ function registerDebugTools(ctx, tools, store) {
|
|
|
7676
7760
|
name: DIY_DEBUG_STOP_TOOL,
|
|
7677
7761
|
description: "结束调试(不审批):清掉\"占用用户那一屏\"这件事。收工用它。",
|
|
7678
7762
|
parameters: EMPTY,
|
|
7679
|
-
output: OUTPUT$
|
|
7763
|
+
output: OUTPUT$3,
|
|
7680
7764
|
async execute(_raw, exec) {
|
|
7681
7765
|
const { root } = await workspaceOf(ctx, exec);
|
|
7682
7766
|
const held = store.live(Date.now());
|
|
@@ -7866,7 +7950,7 @@ function registerLogTools(ctx, tools) {
|
|
|
7866
7950
|
name: DIY_LOGS_WATCH_TOOL,
|
|
7867
7951
|
description: "把这一页的控制台听上(每页最多 200 条、单条截 400 字,随页面刷新消失)。",
|
|
7868
7952
|
parameters: schema,
|
|
7869
|
-
output: OUTPUT$
|
|
7953
|
+
output: OUTPUT$3,
|
|
7870
7954
|
async execute(raw, exec) {
|
|
7871
7955
|
const { page, step } = await run(exec, raw, LOGS_ARM_SCRIPT);
|
|
7872
7956
|
const error = actErrorOf(step);
|
|
@@ -7886,7 +7970,7 @@ function registerLogTools(ctx, tools) {
|
|
|
7886
7970
|
name: DIY_LOGS_READ_TOOL,
|
|
7887
7971
|
description: "读刚才听下来的控制台(最近 50 条;没装钩子会说清,不假装是\"没有报错\")。",
|
|
7888
7972
|
parameters: schema,
|
|
7889
|
-
output: OUTPUT$
|
|
7973
|
+
output: OUTPUT$3,
|
|
7890
7974
|
async execute(raw, exec) {
|
|
7891
7975
|
const { page, step } = await run(exec, raw, LOGS_READ_SCRIPT);
|
|
7892
7976
|
const error = actErrorOf(step);
|
|
@@ -7905,7 +7989,7 @@ function registerLogTools(ctx, tools) {
|
|
|
7905
7989
|
name: DIY_LOGS_STOP_TOOL,
|
|
7906
7990
|
description: "控制台收听收工:卸掉钩子、扔掉攒下的记录。",
|
|
7907
7991
|
parameters: schema,
|
|
7908
|
-
output: OUTPUT$
|
|
7992
|
+
output: OUTPUT$3,
|
|
7909
7993
|
async execute(raw, exec) {
|
|
7910
7994
|
const { page, step } = await run(exec, raw, LOGS_STOP_SCRIPT);
|
|
7911
7995
|
const error = actErrorOf(step);
|
|
@@ -8571,7 +8655,7 @@ function registerBrowserTools(ctx, tools) {
|
|
|
8571
8655
|
name: row.tool,
|
|
8572
8656
|
description: row.description,
|
|
8573
8657
|
parameters: parametersOf(row),
|
|
8574
|
-
output: OUTPUT$
|
|
8658
|
+
output: OUTPUT$3,
|
|
8575
8659
|
execute: async (raw, exec) => plainJson(await runBrowserTool(row, ctx, raw, exec))
|
|
8576
8660
|
};
|
|
8577
8661
|
return tools.register(definition);
|
|
@@ -8610,7 +8694,7 @@ function specTool(ctx) {
|
|
|
8610
8694
|
required: ["command"],
|
|
8611
8695
|
additionalProperties: false
|
|
8612
8696
|
},
|
|
8613
|
-
output: OUTPUT$
|
|
8697
|
+
output: OUTPUT$3,
|
|
8614
8698
|
async execute(raw, _exec) {
|
|
8615
8699
|
const args = asRecord$1(raw);
|
|
8616
8700
|
const argv = specArgvOf(asText(args["command"]));
|
|
@@ -8637,6 +8721,176 @@ function registerSpecTool(ctx, tools) {
|
|
|
8637
8721
|
return [tools.register(specTool(ctx))];
|
|
8638
8722
|
}
|
|
8639
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
|
|
8640
8894
|
//#region src/shared/api/host/diy-recon.ts
|
|
8641
8895
|
var SITE_LIMIT = 6;
|
|
8642
8896
|
var COMMAND_LIMIT = 12;
|
|
@@ -9077,7 +9331,7 @@ function renderStatus(root, lines, options = {}) {
|
|
|
9077
9331
|
}
|
|
9078
9332
|
function publishStatusOf(preview) {
|
|
9079
9333
|
if (preview === null) return "";
|
|
9080
|
-
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");
|
|
9081
9335
|
}
|
|
9082
9336
|
function renderList(root, modules, shape = "bare") {
|
|
9083
9337
|
if (modules.length === 0) return [
|
|
@@ -9092,7 +9346,6 @@ function renderList(root, modules, shape = "bare") {
|
|
|
9092
9346
|
}
|
|
9093
9347
|
//#endregion
|
|
9094
9348
|
//#region src/modules/panels/model/diy-tools.ts
|
|
9095
|
-
var PUBLISH_TIMEOUT_MS = 18e5;
|
|
9096
9349
|
function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, inferredAuthorOf = async () => void 0) {
|
|
9097
9350
|
const supply = supplyPortOf(ctx);
|
|
9098
9351
|
const tools = ctx.get("tools");
|
|
@@ -9112,7 +9365,7 @@ function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, in
|
|
|
9112
9365
|
required: [],
|
|
9113
9366
|
additionalProperties: false
|
|
9114
9367
|
},
|
|
9115
|
-
output: OUTPUT$
|
|
9368
|
+
output: OUTPUT$3,
|
|
9116
9369
|
async execute(raw, exec) {
|
|
9117
9370
|
const { root } = await workspaceOf(ctx, exec);
|
|
9118
9371
|
const { units } = unitsOf(ctx, root);
|
|
@@ -9155,7 +9408,7 @@ function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, in
|
|
|
9155
9408
|
} },
|
|
9156
9409
|
additionalProperties: false
|
|
9157
9410
|
},
|
|
9158
|
-
output: OUTPUT$
|
|
9411
|
+
output: OUTPUT$3,
|
|
9159
9412
|
async execute(raw, exec) {
|
|
9160
9413
|
const { root } = await workspaceOf(ctx, exec);
|
|
9161
9414
|
const { installed, units } = unitsOf(ctx, root);
|
|
@@ -9221,7 +9474,7 @@ function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, in
|
|
|
9221
9474
|
required: ["keyword"],
|
|
9222
9475
|
additionalProperties: false
|
|
9223
9476
|
},
|
|
9224
|
-
output: OUTPUT$
|
|
9477
|
+
output: OUTPUT$3,
|
|
9225
9478
|
async execute(raw, _exec) {
|
|
9226
9479
|
const args = asRecord$1(raw);
|
|
9227
9480
|
const keywords = keywordsOf(asText(args["keyword"]), asText(args["url"]));
|
|
@@ -9263,7 +9516,7 @@ function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, in
|
|
|
9263
9516
|
required: ["unit"],
|
|
9264
9517
|
additionalProperties: false
|
|
9265
9518
|
},
|
|
9266
|
-
output: OUTPUT$
|
|
9519
|
+
output: OUTPUT$3,
|
|
9267
9520
|
async execute(raw, exec) {
|
|
9268
9521
|
const { root } = await workspaceOf(ctx, exec);
|
|
9269
9522
|
const { units } = unitsOf(ctx, root);
|
|
@@ -9292,7 +9545,7 @@ function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, in
|
|
|
9292
9545
|
required: ["unit"],
|
|
9293
9546
|
additionalProperties: false
|
|
9294
9547
|
},
|
|
9295
|
-
output: OUTPUT$
|
|
9548
|
+
output: OUTPUT$3,
|
|
9296
9549
|
async execute(raw, exec) {
|
|
9297
9550
|
const { root } = await workspaceOf(ctx, exec);
|
|
9298
9551
|
const found = unitOf(root, raw, "workbench_diy_install");
|
|
@@ -9332,162 +9585,22 @@ function registerDiyTools(ctx, market, panels, debug, previewOf = () => null, in
|
|
|
9332
9585
|
});
|
|
9333
9586
|
}
|
|
9334
9587
|
};
|
|
9335
|
-
const publishTool = {
|
|
9336
|
-
name: DIY_PUBLISH_TOOL,
|
|
9337
|
-
description: "用户说“发布”后才用:把这一格发到 target 指定的出口(不填按环境默认)。",
|
|
9338
|
-
parameters: {
|
|
9339
|
-
type: "object",
|
|
9340
|
-
properties: {
|
|
9341
|
-
unit: {
|
|
9342
|
-
type: "string",
|
|
9343
|
-
description: "模块 id(workbench_diy_status 会给)。"
|
|
9344
|
-
},
|
|
9345
|
-
target: {
|
|
9346
|
-
type: "string",
|
|
9347
|
-
enum: [
|
|
9348
|
-
"team",
|
|
9349
|
-
"public",
|
|
9350
|
-
"tarball",
|
|
9351
|
-
"git",
|
|
9352
|
-
"market",
|
|
9353
|
-
"local"
|
|
9354
|
-
],
|
|
9355
|
-
description: "发到哪:团队源 / 公共 npm / 安装包 / git / 模块市场索引;不填按环境默认(有可写索引走市场,有私源走团队源,否则安装包)。"
|
|
9356
|
-
},
|
|
9357
|
-
version: {
|
|
9358
|
-
type: "string",
|
|
9359
|
-
description: "可选:patch / minor / major / x.y.z;不填首次用当前版本,之后自动 patch。"
|
|
9360
|
-
},
|
|
9361
|
-
verify: {
|
|
9362
|
-
type: "boolean",
|
|
9363
|
-
description: "只核已发布的包(交接验证码后用),不再发;不用审批。"
|
|
9364
|
-
},
|
|
9365
|
-
resume: {
|
|
9366
|
-
type: "boolean",
|
|
9367
|
-
description: "中断后接着发(用记录里的出口与版本)。"
|
|
9368
|
-
},
|
|
9369
|
-
license: {
|
|
9370
|
-
type: "string",
|
|
9371
|
-
description: "公开发布用的许可证(MIT / Apache-2.0 / 仓库已有 LICENSE)。"
|
|
9372
|
-
},
|
|
9373
|
-
author: {
|
|
9374
|
-
type: "string",
|
|
9375
|
-
description: "署谁的名(姓名,或 姓名 <邮箱>);用户点了名才传,不传按模块里写的,没写用推断的署名。"
|
|
9376
|
-
},
|
|
9377
|
-
refresh: {
|
|
9378
|
-
type: "boolean",
|
|
9379
|
-
description: "只刷市集元数据(标题/作者/说明),不升版本、不重发产物。"
|
|
9380
|
-
}
|
|
9381
|
-
},
|
|
9382
|
-
required: ["unit"],
|
|
9383
|
-
additionalProperties: false
|
|
9384
|
-
},
|
|
9385
|
-
output: OUTPUT$2,
|
|
9386
|
-
async execute(raw, exec) {
|
|
9387
|
-
const { root } = await workspaceOf(ctx, exec);
|
|
9388
|
-
const found = unitOf(root, raw, "workbench_diy_publish");
|
|
9389
|
-
const shell = ctx.get("shell");
|
|
9390
|
-
if (shell === void 0) throw new Error("这台机器上没有 shell 服务,发布跑不起来");
|
|
9391
|
-
const bin = toolchainBinOf(root) ?? toolchainBinOf(found.dir);
|
|
9392
|
-
if (bin === null) throw new Error(`这个工作区里没有 dsh-wb-module(${join(root, "node_modules")} 下没有)—— 先 pnpm install`);
|
|
9393
|
-
const target = asText(asRecord$1(raw)["target"]);
|
|
9394
|
-
const version = asText(asRecord$1(raw)["version"]);
|
|
9395
|
-
const license = asText(asRecord$1(raw)["license"]);
|
|
9396
|
-
let author = asText(asRecord$1(raw)["author"]);
|
|
9397
|
-
const verify = asRecord$1(raw)["verify"] === true;
|
|
9398
|
-
const resume = asRecord$1(raw)["resume"] === true;
|
|
9399
|
-
if (!verify && target !== "local" && author === "" && (previewOf(found.unit)?.author ?? "") === "") author = await inferredAuthorOf(found.unit) ?? "";
|
|
9400
|
-
const argv = [
|
|
9401
|
-
bin,
|
|
9402
|
-
"release",
|
|
9403
|
-
"--cwd",
|
|
9404
|
-
found.dir,
|
|
9405
|
-
"--json"
|
|
9406
|
-
];
|
|
9407
|
-
if (verify) argv.push("--verify");
|
|
9408
|
-
else argv.push("--yes");
|
|
9409
|
-
if (resume) argv.push("--resume");
|
|
9410
|
-
if (target !== "") argv.push("--target", target);
|
|
9411
|
-
if (version !== "") argv.push("--version", version);
|
|
9412
|
-
if (license !== "") argv.push("--license", license);
|
|
9413
|
-
if (author !== "") argv.push("--author", author);
|
|
9414
|
-
if (asRecord$1(raw)["refresh"] === true) argv.push("--refresh");
|
|
9415
|
-
const result = await runShell(shell, argv.map((one) => quoteShellArg(one)).join(" "), {
|
|
9416
|
-
workdir: root,
|
|
9417
|
-
timeoutMs: PUBLISH_TIMEOUT_MS
|
|
9418
|
-
});
|
|
9419
|
-
const payload = jsonOf(result.stdout);
|
|
9420
|
-
if (result.exitCode === 3 && payload !== void 0) {
|
|
9421
|
-
const needs = asRecord$1(payload["needsUser"]);
|
|
9422
|
-
const stepText = asText(needs["text"]);
|
|
9423
|
-
const command = asText(needs["command"]);
|
|
9424
|
-
return plainJson({
|
|
9425
|
-
...payload,
|
|
9426
|
-
text: [
|
|
9427
|
-
`还差一步:${stepText}`,
|
|
9428
|
-
...command === "" ? [] : [`命令:${command}`],
|
|
9429
|
-
"做完跟我说「好了」,我接着发。"
|
|
9430
|
-
].join("\n")
|
|
9431
|
-
});
|
|
9432
|
-
}
|
|
9433
|
-
if (result.exitCode === 4 && payload !== void 0) {
|
|
9434
|
-
const resumeInfo = asRecord$1(payload["resume"]);
|
|
9435
|
-
return plainJson({
|
|
9436
|
-
...payload,
|
|
9437
|
-
text: [`发布中断在第 ${asText(resumeInfo["phase"])} 步:${asText(payload["text"])}`, `再调一次 workbench_diy_publish(unit=${found.unit}, resume=true)就能接着发。`].join("\n")
|
|
9438
|
-
});
|
|
9439
|
-
}
|
|
9440
|
-
if (result.exitCode !== 0 || payload === void 0) {
|
|
9441
|
-
const tail = `${result.stderr}\n${result.stdout}`.trim().split("\n").slice(-6).join(" | ");
|
|
9442
|
-
throw new Error(`发布没走通(exit ${String(result.exitCode)})${tail === "" ? "" : `:${tail}`}`);
|
|
9443
|
-
}
|
|
9444
|
-
const name = asText(payload["name"]);
|
|
9445
|
-
const released = asText(payload["version"]);
|
|
9446
|
-
const registry = asText(payload["registry"]);
|
|
9447
|
-
const file = asText(payload["file"]);
|
|
9448
|
-
const install = asText(payload["install"]);
|
|
9449
|
-
const git = asRecord$1(payload["git"]);
|
|
9450
|
-
const targetOfPayload = asText(payload["target"]);
|
|
9451
|
-
const text = verify ? [
|
|
9452
|
-
`已核过 ${name}@${released}`,
|
|
9453
|
-
`安装:${install}`,
|
|
9454
|
-
"没有重新发布。"
|
|
9455
|
-
].join("\n") : payload["refresh"] === true ? [payload["refreshed"] === true ? `已刷新 ${name} 的市集元数据(版本 ${released} 不变)` : `${name} 的市集元数据本来就是这样,没动`, `市场索引:${asText(asRecord$1(payload["market"])["url"])}`].join("\n") : targetOfPayload === "tarball" ? [
|
|
9456
|
-
`安装包在 ${file}`,
|
|
9457
|
-
`本机装:${install}`,
|
|
9458
|
-
"文件可以从对话里带走,发给同事。"
|
|
9459
|
-
].join("\n") : targetOfPayload === "git" ? [
|
|
9460
|
-
`已推到 ${asText(git["url"])}(tag ${asText(git["tag"])})`,
|
|
9461
|
-
`安装:${install}`,
|
|
9462
|
-
"已核过 tag 里的产物。"
|
|
9463
|
-
].join("\n") : targetOfPayload === "market" ? [
|
|
9464
|
-
`已发到市场索引 ${asText(asRecord$1(payload["market"])["url"])}`,
|
|
9465
|
-
`安装:${install}`,
|
|
9466
|
-
"已从索引仓库侧核过产物。"
|
|
9467
|
-
].join("\n") : targetOfPayload === "local" ? "没发,留在本机。" : [
|
|
9468
|
-
`已发布 ${name}@${released} → ${registry}`,
|
|
9469
|
-
`同事安装:${install}`,
|
|
9470
|
-
"包内容已经从源上核过(dist/host.js / client.js / cordis.patch.yml 都在)。"
|
|
9471
|
-
].join("\n");
|
|
9472
|
-
return plainJson({
|
|
9473
|
-
...payload,
|
|
9474
|
-
text
|
|
9475
|
-
});
|
|
9476
|
-
}
|
|
9477
|
-
};
|
|
9478
9588
|
return [
|
|
9479
9589
|
tools.register(statusTool),
|
|
9480
9590
|
tools.register(panelTool),
|
|
9481
9591
|
...registerComponentsTool(ctx, tools),
|
|
9482
9592
|
tools.register(reconTool),
|
|
9483
9593
|
...registerSpecTool(ctx, tools),
|
|
9484
|
-
...registerChangelogTool(ctx, tools),
|
|
9485
9594
|
...registerLogTools(ctx, tools),
|
|
9486
9595
|
...registerBrowserTools(ctx, tools),
|
|
9487
9596
|
...registerDebugTools(ctx, tools, debug),
|
|
9488
9597
|
tools.register(showTool),
|
|
9489
9598
|
tools.register(installTool),
|
|
9490
|
-
tools
|
|
9599
|
+
registerPublishTool(ctx, tools, {
|
|
9600
|
+
resolve: (root, raw) => unitOf(root, raw, "workbench_diy_publish"),
|
|
9601
|
+
previewOf,
|
|
9602
|
+
inferredAuthorOf
|
|
9603
|
+
})
|
|
9491
9604
|
];
|
|
9492
9605
|
}
|
|
9493
9606
|
//#endregion
|
|
@@ -9517,27 +9630,22 @@ function selectedGitSource() {
|
|
|
9517
9630
|
return parsed.source.policy === "artifacts-in-repo" ? parsed.source : void 0;
|
|
9518
9631
|
}
|
|
9519
9632
|
}
|
|
9520
|
-
|
|
9633
|
+
var EMPTY_INDEX = {
|
|
9634
|
+
format: 1,
|
|
9635
|
+
plugins: []
|
|
9636
|
+
};
|
|
9637
|
+
function publishedIndexOf(source) {
|
|
9521
9638
|
const file = join(workbenchRoot(), "market-index", marketSourceKey(source), "worktree", source.path ?? "market.json");
|
|
9522
9639
|
if (!existsSync(file)) return void 0;
|
|
9523
9640
|
try {
|
|
9524
9641
|
const parsed = parseMarketIndexJson(readFileSync(file, "utf8"));
|
|
9525
|
-
|
|
9526
|
-
const entry = parsed.index.plugins.find((one) => one.name === name);
|
|
9527
|
-
if (entry === void 0) return {
|
|
9528
|
-
versions: [],
|
|
9529
|
-
author: ""
|
|
9530
|
-
};
|
|
9531
|
-
return {
|
|
9532
|
-
versions: entry.versions.map((one) => one.version),
|
|
9533
|
-
author: typeof entry.author === "string" ? entry.author.trim() : ""
|
|
9534
|
-
};
|
|
9642
|
+
return parsed.ok ? parsed.index : void 0;
|
|
9535
9643
|
} catch {
|
|
9536
9644
|
return;
|
|
9537
9645
|
}
|
|
9538
9646
|
}
|
|
9539
|
-
function
|
|
9540
|
-
return
|
|
9647
|
+
function publishedEntryOf(index, name) {
|
|
9648
|
+
return index?.plugins.find((one) => one.name === name);
|
|
9541
9649
|
}
|
|
9542
9650
|
function bumped(version, kind) {
|
|
9543
9651
|
const match = SEMVER.exec(version);
|
|
@@ -9562,17 +9670,21 @@ function nextVersionOf(version, published) {
|
|
|
9562
9670
|
if (!exists(candidate)) return candidate;
|
|
9563
9671
|
}
|
|
9564
9672
|
}
|
|
9565
|
-
function marketOf(
|
|
9673
|
+
function marketOf(dir, name, version) {
|
|
9566
9674
|
const source = selectedGitSource();
|
|
9567
9675
|
if (source === void 0) return void 0;
|
|
9568
|
-
const
|
|
9676
|
+
const index = publishedIndexOf(source);
|
|
9677
|
+
const nextVersion = nextVersionOf(version, publishedEntryOf(index, name)?.versions.map((one) => one.version));
|
|
9569
9678
|
return {
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
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 }
|
|
9576
9688
|
};
|
|
9577
9689
|
}
|
|
9578
9690
|
function moduleFactOf(root, unit) {
|
|
@@ -9631,7 +9743,7 @@ async function inferredAuthorOf(root, unit, shell) {
|
|
|
9631
9743
|
if (fact.author !== "") return fact.author;
|
|
9632
9744
|
const source = selectedGitSource();
|
|
9633
9745
|
if (source !== void 0 && fact.name !== "") {
|
|
9634
|
-
const published = publishedEntryOf(source, fact.name)?.author ?? "";
|
|
9746
|
+
const published = publishedEntryOf(publishedIndexOf(source), fact.name)?.author ?? "";
|
|
9635
9747
|
if (published !== "") return published;
|
|
9636
9748
|
}
|
|
9637
9749
|
const sibling = root === null || root === void 0 ? void 0 : siblingAuthorOf(root, unit);
|
|
@@ -9657,17 +9769,24 @@ function publishPreviewOf(root, unit, options = {}) {
|
|
|
9657
9769
|
if (name === "" || version === "") return null;
|
|
9658
9770
|
const publishConfig = record["publishConfig"];
|
|
9659
9771
|
const registry = typeof publishConfig === "object" && publishConfig !== null ? publishConfig["registry"] : void 0;
|
|
9660
|
-
const market = marketOf(found.
|
|
9661
|
-
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);
|
|
9662
9774
|
const askedAuthor = (options.author ?? "").trim();
|
|
9663
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
|
+
});
|
|
9664
9782
|
return {
|
|
9665
9783
|
name,
|
|
9666
9784
|
version,
|
|
9667
9785
|
...author === "" ? {} : { author },
|
|
9668
9786
|
...typeof registry === "string" && registry !== "" ? { registry } : {},
|
|
9669
|
-
...market === void 0 ? {} : { market },
|
|
9670
|
-
|
|
9787
|
+
...market === void 0 ? {} : { market: market.market },
|
|
9788
|
+
...claim === void 0 ? {} : { claim },
|
|
9789
|
+
changelog: changelogOf(found.dir, target, (options.changelog ?? "").trim(), kindOf(options.changelogType))
|
|
9671
9790
|
};
|
|
9672
9791
|
}
|
|
9673
9792
|
function authorOf(manifest) {
|
|
@@ -9685,13 +9804,30 @@ function targetVersionOf(version, asked, market) {
|
|
|
9685
9804
|
if (/^(major|minor|patch)$/.test(asked)) return bumped(version, asked) ?? version;
|
|
9686
9805
|
return asked;
|
|
9687
9806
|
}
|
|
9688
|
-
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) {
|
|
9689
9812
|
let text;
|
|
9690
9813
|
try {
|
|
9691
9814
|
text = readFileSync(join(dir, CHANGELOG_FILE), "utf8");
|
|
9692
9815
|
} catch {
|
|
9693
9816
|
text = void 0;
|
|
9694
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
|
+
}
|
|
9695
9831
|
if (text === void 0 || !changelogHasEntry(text, version)) return {
|
|
9696
9832
|
version,
|
|
9697
9833
|
missing: true
|
|
@@ -11014,7 +11150,7 @@ function registerRecordTools(ctx, store) {
|
|
|
11014
11150
|
required: ["url"],
|
|
11015
11151
|
additionalProperties: false
|
|
11016
11152
|
},
|
|
11017
|
-
output: OUTPUT$
|
|
11153
|
+
output: OUTPUT$3,
|
|
11018
11154
|
async execute(raw, exec) {
|
|
11019
11155
|
const { root } = await workspaceOf(ctx, exec);
|
|
11020
11156
|
const artifactsDir = artifactsDirOf(ctx, root);
|
|
@@ -11114,7 +11250,7 @@ function registerRecordTools(ctx, store) {
|
|
|
11114
11250
|
} },
|
|
11115
11251
|
additionalProperties: false
|
|
11116
11252
|
},
|
|
11117
|
-
output: OUTPUT$
|
|
11253
|
+
output: OUTPUT$3,
|
|
11118
11254
|
async execute(raw, exec) {
|
|
11119
11255
|
const shell = ctx.get("shell");
|
|
11120
11256
|
if (shell === void 0) throw new Error("这台机器上没有 shell 服务,读不了录制");
|
|
@@ -11244,7 +11380,7 @@ function registerRecordTools(ctx, store) {
|
|
|
11244
11380
|
},
|
|
11245
11381
|
additionalProperties: false
|
|
11246
11382
|
},
|
|
11247
|
-
output: OUTPUT$
|
|
11383
|
+
output: OUTPUT$3,
|
|
11248
11384
|
async execute(raw, exec) {
|
|
11249
11385
|
const { root } = await workspaceOf(ctx, exec);
|
|
11250
11386
|
const artifactsDir = artifactsDirOf(ctx, root);
|
|
@@ -11326,7 +11462,7 @@ function registerRecordTools(ctx, store) {
|
|
|
11326
11462
|
properties: {},
|
|
11327
11463
|
additionalProperties: false
|
|
11328
11464
|
},
|
|
11329
|
-
output: OUTPUT$
|
|
11465
|
+
output: OUTPUT$3,
|
|
11330
11466
|
async execute(_raw, exec) {
|
|
11331
11467
|
const shell = ctx.get("shell");
|
|
11332
11468
|
if (shell === void 0) throw new Error("这台机器上没有 shell 服务,收不了工");
|
|
@@ -12236,7 +12372,7 @@ function createMarketService(options) {
|
|
|
12236
12372
|
const manifest = requireEntry(unit);
|
|
12237
12373
|
return {
|
|
12238
12374
|
unit,
|
|
12239
|
-
titleKey: manifest.
|
|
12375
|
+
titleKey: manifest.titleKey,
|
|
12240
12376
|
needs: needsOf(manifest),
|
|
12241
12377
|
capability: await capabilityOf(unit, force)
|
|
12242
12378
|
};
|
|
@@ -12567,6 +12703,7 @@ function normalizedRepo(value) {
|
|
|
12567
12703
|
return value.trim().replace(/^git\+/, "").replace(/\.git$/, "").toLowerCase();
|
|
12568
12704
|
}
|
|
12569
12705
|
function isWorkbenchEntry(entry) {
|
|
12706
|
+
if (entry.metadata?.workbench === true) return true;
|
|
12570
12707
|
const labels = marketEntryLabels(entry);
|
|
12571
12708
|
if (labels.includes("workbench")) return true;
|
|
12572
12709
|
return entry.metadata?.category === "workbench" && labels.length === 0;
|
|
@@ -12824,37 +12961,66 @@ function parseMarketSourcesAction(payload) {
|
|
|
12824
12961
|
id: id.trim()
|
|
12825
12962
|
};
|
|
12826
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
|
+
}
|
|
12827
12972
|
if (action === "init") {
|
|
12828
12973
|
const id = record["id"];
|
|
12829
12974
|
if (typeof id !== "string" || id.trim() === "") throw new Error("init 需要 id");
|
|
12830
12975
|
const ref = typeof record["ref"] === "string" ? record["ref"].trim() : "";
|
|
12831
12976
|
if (ref !== "" && !marketBranchOk(ref)) throw new Error(`分支名不合格:${ref}`);
|
|
12977
|
+
const stampOnly = record["stampOnly"] === true;
|
|
12832
12978
|
return {
|
|
12833
12979
|
action,
|
|
12834
12980
|
id: id.trim(),
|
|
12835
|
-
...ref === "" ? {} : { ref }
|
|
12981
|
+
...ref === "" ? {} : { ref },
|
|
12982
|
+
...stampOnly ? { stampOnly } : {}
|
|
12836
12983
|
};
|
|
12837
12984
|
}
|
|
12838
12985
|
throw new Error(`不认识的索引源动作:${String(action)}`);
|
|
12839
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
|
+
}
|
|
12840
13001
|
function marketSourcesAction(store, init) {
|
|
12841
13002
|
return {
|
|
12842
13003
|
resource: MARKET_SOURCES_RESOURCE,
|
|
12843
13004
|
async handle(payload) {
|
|
12844
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
|
+
}
|
|
12845
13014
|
if (action.action === "init") {
|
|
12846
13015
|
if (init === void 0) throw new Error("这台机器上没有 shell 服务,初始化不了索引仓库");
|
|
12847
13016
|
const result = await init({
|
|
12848
13017
|
id: action.id,
|
|
12849
|
-
...action.ref === void 0 ? {} : { ref: action.ref }
|
|
13018
|
+
...action.ref === void 0 ? {} : { ref: action.ref },
|
|
13019
|
+
...action.stampOnly === true ? { stampOnly: true } : {}
|
|
12850
13020
|
});
|
|
12851
13021
|
return {
|
|
12852
13022
|
ok: true,
|
|
12853
|
-
...
|
|
12854
|
-
action: "save",
|
|
12855
|
-
source: result.source,
|
|
12856
|
-
select: true
|
|
12857
|
-
}),
|
|
13023
|
+
...store.read(),
|
|
12858
13024
|
branch: result.branch,
|
|
12859
13025
|
commit: result.commit,
|
|
12860
13026
|
created: result.created
|
|
@@ -12874,20 +13040,29 @@ function publishPreviewRoutes(workshop, inferredAuthorOf = async () => void 0) {
|
|
|
12874
13040
|
const unit = (param(search, "unit") ?? "").trim();
|
|
12875
13041
|
const version = (param(search, "version") ?? "").trim();
|
|
12876
13042
|
const author = (param(search, "author") ?? "").trim();
|
|
13043
|
+
const changelog = param(search, "changelog") ?? "";
|
|
13044
|
+
const changelogType = (param(search, "changelogType") ?? "").trim();
|
|
12877
13045
|
if (unit === "") return {
|
|
12878
13046
|
ok: true,
|
|
12879
13047
|
preview: null
|
|
12880
13048
|
};
|
|
12881
13049
|
let preview = publishPreviewOf(workshop, unit, {
|
|
12882
13050
|
version,
|
|
12883
|
-
author
|
|
13051
|
+
author,
|
|
13052
|
+
changelog,
|
|
13053
|
+
changelogType
|
|
12884
13054
|
});
|
|
12885
13055
|
if (preview !== null && author === "" && (preview.author === void 0 || preview.author === "")) {
|
|
12886
13056
|
const inferred = await inferredAuthorOf(unit);
|
|
12887
|
-
if (inferred !== void 0 && inferred !== "")
|
|
12888
|
-
|
|
12889
|
-
|
|
12890
|
-
|
|
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
|
+
}
|
|
12891
13066
|
}
|
|
12892
13067
|
return {
|
|
12893
13068
|
ok: true,
|
|
@@ -13514,17 +13689,21 @@ function createMarketSourceInitializer(options) {
|
|
|
13514
13689
|
if (created.exitCode !== 0) throw new Error(`建分支 ${branch} 没过:${tailLines(created.stderr, 4)}`);
|
|
13515
13690
|
}
|
|
13516
13691
|
const indexPath = (source.path ?? "market.json").replace(/^\/+/, "") || "market.json";
|
|
13517
|
-
const written = [];
|
|
13518
13692
|
const indexFile = join(workdir, indexPath);
|
|
13519
|
-
|
|
13520
|
-
|
|
13521
|
-
|
|
13522
|
-
|
|
13523
|
-
|
|
13524
|
-
|
|
13525
|
-
|
|
13526
|
-
|
|
13527
|
-
|
|
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
|
+
}
|
|
13528
13707
|
}
|
|
13529
13708
|
if (written.length > 0) {
|
|
13530
13709
|
const added = await git(["add", ...written], workdir);
|
|
@@ -13551,8 +13730,7 @@ function createMarketSourceInitializer(options) {
|
|
|
13551
13730
|
};
|
|
13552
13731
|
await options.store.apply({
|
|
13553
13732
|
action: "save",
|
|
13554
|
-
source: next
|
|
13555
|
-
select: true
|
|
13733
|
+
source: next
|
|
13556
13734
|
});
|
|
13557
13735
|
forget(source, next);
|
|
13558
13736
|
return {
|
|
@@ -13679,6 +13857,73 @@ async function dispatchMarket(market, request) {
|
|
|
13679
13857
|
};
|
|
13680
13858
|
}
|
|
13681
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
|
|
13682
13927
|
//#region src/modules/panels/model/market-tools.ts
|
|
13683
13928
|
function supplyNamesOf(entry) {
|
|
13684
13929
|
return entry.needs.filter((need) => need.kind === "extension" || need.kind === "lib").map((need) => need.name);
|
|
@@ -13774,7 +14019,7 @@ function usersOf(shared, names) {
|
|
|
13774
14019
|
if (hit === void 0 || hit.usedBy.length === 0) return "";
|
|
13775
14020
|
return `它被 ${hit.usedBy.join("、")} 用着(动的是它们的供给,它们的状态跟着重探了一遍)`;
|
|
13776
14021
|
}
|
|
13777
|
-
function registerMarketTools(ctx, market) {
|
|
14022
|
+
function registerMarketTools(ctx, market, sources) {
|
|
13778
14023
|
const tools = ctx.get("tools");
|
|
13779
14024
|
if (tools === void 0) {
|
|
13780
14025
|
ctx.logger?.info?.("[dsh-workbench] 没有 tools 服务,跳过模块市场工具注册");
|
|
@@ -13973,6 +14218,82 @@ function registerMarketTools(ctx, market) {
|
|
|
13973
14218
|
};
|
|
13974
14219
|
}
|
|
13975
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
|
+
};
|
|
13976
14297
|
return [
|
|
13977
14298
|
tools.register(listTool),
|
|
13978
14299
|
tools.register(installTool),
|
|
@@ -13982,7 +14303,10 @@ function registerMarketTools(ctx, market) {
|
|
|
13982
14303
|
tools.register(updateDependencyTool),
|
|
13983
14304
|
tools.register(updatePluginTool),
|
|
13984
14305
|
tools.register(uninstallPluginTool),
|
|
13985
|
-
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)
|
|
13986
14310
|
];
|
|
13987
14311
|
}
|
|
13988
14312
|
//#endregion
|
|
@@ -14100,6 +14424,7 @@ function listedRunUnits(result) {
|
|
|
14100
14424
|
}
|
|
14101
14425
|
function panelsFactsOf(call, manifests) {
|
|
14102
14426
|
if (call.source === "workbench_panels_list") return [PANELS_FACT];
|
|
14427
|
+
if (call.source === "market-sources") return [PANELS_FACT];
|
|
14103
14428
|
if (call.source === "workbench_long_tasks_list") return listedRunUnits(call.result).map(runsRouteOf);
|
|
14104
14429
|
if (call.source === "workbench_modules_list") return [PANELS_FACT, CAPABILITY_FACT];
|
|
14105
14430
|
if (call.source === "workbench_modules_update_workbench") return [PANELS_FACT, CAPABILITY_FACT];
|
|
@@ -14794,13 +15119,17 @@ var OWNED = [{
|
|
|
14794
15119
|
},
|
|
14795
15120
|
registerTools: () => [
|
|
14796
15121
|
...registerPanelTools(ctx, panels, values),
|
|
14797
|
-
...registerMarketTools(ctx, market
|
|
15122
|
+
...registerMarketTools(ctx, market, {
|
|
15123
|
+
read: () => marketSources.read(),
|
|
15124
|
+
init: marketInit,
|
|
15125
|
+
readOnly: (id) => markSourceReadOnly(marketSources, id)
|
|
15126
|
+
}),
|
|
14798
15127
|
...registerDiyTools(ctx, market, panels, debug, (unit) => publishPreviewOf(workshopPathOf(ctx), unit), (unit) => inferredAuthorOf(workshopPathOf(ctx), unit, shell)),
|
|
14799
15128
|
...registerRecordTools(ctx, record),
|
|
14800
15129
|
...registerLongTaskTools(ctx, longTaskRuns)
|
|
14801
15130
|
],
|
|
14802
15131
|
factsOf: (call) => panelsFactsOf(call, manifests()),
|
|
14803
|
-
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),
|
|
14804
15133
|
gate: {
|
|
14805
15134
|
deniedTools: (context) => {
|
|
14806
15135
|
const boards = panels.boards(context.workspace);
|