@dsh-workbench/core 1.0.0-beta.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -15
- package/bin/dsh-workbench +27 -26
- package/client.js +213 -322
- package/dist/client/client.body.js +213 -322
- package/dist/client/index.js +213 -322
- package/dist/host/index.js +108 -74
- package/dist/types/app/layouts/rightbar/market-shared-rows.d.ts +0 -1
- package/dist/types/app/layouts/workbench-settings/ConfigSyncRows.d.ts +1 -3
- package/dist/types/kernel/contract/config-sync.d.ts +1 -1
- package/dist/types/modules/panels/model/diy-context.d.ts +14 -4
- package/dist/types/modules/panels/model/diy-report.d.ts +2 -0
- package/dist/types/modules/panels/model/diy-tools.d.ts +2 -1
- package/package.json +5 -3
- package/profile/sandbox.patch.yml +7 -5
- package/scripts/clone-profile.mjs +11 -199
- package/scripts/create-workbench.mjs +7 -20
- package/scripts/patch-blocks.mjs +60 -0
- package/scripts/seed-profile.sh +14 -27
- package/scripts/share-data-root.mjs +211 -0
- package/skills/workbench-module-diy/FAMILY.md +4 -6
- package/skills/workbench-module-diy/SKILL.md +4 -5
- package/skills/workbench-module-diy/WIRING.md +4 -13
- package/dist/types/shared/api/host/git.test.d.ts +0 -1
- package/profile/isolation.patch.yml +0 -46
package/dist/host/index.js
CHANGED
|
@@ -964,69 +964,6 @@ function wroteNow(result) {
|
|
|
964
964
|
function unitFactScope(unit) {
|
|
965
965
|
return `${unit}*`;
|
|
966
966
|
}
|
|
967
|
-
//#endregion
|
|
968
|
-
//#region ../shared/dist/host/shell-text.js
|
|
969
|
-
/**
|
|
970
|
-
* 按目标平台把一个值裹成 shell 字面量:POSIX 用单引号,win32 用双引号(cmd 与 PowerShell 都认)。
|
|
971
|
-
* @param value - 任意值;不是字符串的先 `String()`。
|
|
972
|
-
* @param platform - 目标平台,默认当前 `process.platform`。
|
|
973
|
-
* @returns 可安全拼进该平台 shell 命令的一段文本;含空格 / 元字符的值不会被当成语法。
|
|
974
|
-
*/
|
|
975
|
-
function quoteShellArgFor(value, platform = process.platform) {
|
|
976
|
-
const text = String(value);
|
|
977
|
-
if (platform === "win32") return `"${text.replace(/"/g, "\\\"")}"`;
|
|
978
|
-
return `'${text.replace(/'/g, `'\\''`)}'`;
|
|
979
|
-
}
|
|
980
|
-
/**
|
|
981
|
-
* 按当前平台把值裹成 shell 字面量;跨平台代码要固定平台时用 `quoteShellArgFor`。
|
|
982
|
-
* @param value - 任意值;不是字符串的先 `String()`。
|
|
983
|
-
* @returns 可安全拼进当前平台 shell 命令的一段文本。
|
|
984
|
-
*/
|
|
985
|
-
function quoteShellArg(value) {
|
|
986
|
-
return quoteShellArgFor(value, process.platform);
|
|
987
|
-
}
|
|
988
|
-
/**
|
|
989
|
-
* 取一段文本的末尾若干行(如命令输出),顺带去掉首尾空白。
|
|
990
|
-
* @param text - 原文;`null` / `undefined` 当空串。
|
|
991
|
-
* @param lines - 最多留几行,默认 6;0 给全篇、负数从开头砍掉那么多行(都是 `slice` 语义),调用方传正数。
|
|
992
|
-
* @returns 末尾若干行、去首尾空行后的文本;原文行数不够就全给,空输入给空串。
|
|
993
|
-
*/
|
|
994
|
-
function tailLines(text, lines = 6) {
|
|
995
|
-
return String(text ?? "").trim().split("\n").slice(-lines).join("\n");
|
|
996
|
-
}
|
|
997
|
-
//#endregion
|
|
998
|
-
//#region ../shared/dist/host/shell.js
|
|
999
|
-
var DEFAULT_MAX_BYTES$2 = 8388608;
|
|
1000
|
-
async function runShell(shell, command, options = {}) {
|
|
1001
|
-
const { workdir, timeoutMs = GIT_TIMEOUT_MS, signal } = options;
|
|
1002
|
-
const spec = shell.resolve({
|
|
1003
|
-
command,
|
|
1004
|
-
...workdir === void 0 ? {} : { workdir },
|
|
1005
|
-
timeoutMs,
|
|
1006
|
-
onExpiry: "kill",
|
|
1007
|
-
stdoutMaxBytes: DEFAULT_MAX_BYTES$2,
|
|
1008
|
-
...signal === void 0 ? {} : { signal }
|
|
1009
|
-
});
|
|
1010
|
-
const result = await (await shell.execute(spec)).result();
|
|
1011
|
-
return {
|
|
1012
|
-
exitCode: result.exitCode,
|
|
1013
|
-
timedOut: result.timedOut === true,
|
|
1014
|
-
aborted: result.aborted === true,
|
|
1015
|
-
stdout: result.stdout.text,
|
|
1016
|
-
stderr: result.stderr.text,
|
|
1017
|
-
truncated: result.stdout.truncated || result.stderr.truncated
|
|
1018
|
-
};
|
|
1019
|
-
}
|
|
1020
|
-
function backgroundPrefix() {
|
|
1021
|
-
return [quoteShellArg("env"), quoteShellArg("OPENCLI_WINDOW=background")];
|
|
1022
|
-
}
|
|
1023
|
-
function backgroundLine(command, argv) {
|
|
1024
|
-
return [
|
|
1025
|
-
...backgroundPrefix(),
|
|
1026
|
-
quoteShellArg(command),
|
|
1027
|
-
...argv.map(quoteShellArg)
|
|
1028
|
-
].join(" ");
|
|
1029
|
-
}
|
|
1030
967
|
/**
|
|
1031
968
|
* 上报文本字段的截断长度(2000 字符;workspace / reason / message 共用)。
|
|
1032
969
|
*/
|
|
@@ -2385,6 +2322,69 @@ function createWorkspaceStore(options) {
|
|
|
2385
2322
|
};
|
|
2386
2323
|
}
|
|
2387
2324
|
//#endregion
|
|
2325
|
+
//#region ../shared/dist/host/shell-text.js
|
|
2326
|
+
/**
|
|
2327
|
+
* 按目标平台把一个值裹成 shell 字面量:POSIX 用单引号,win32 用双引号(cmd 与 PowerShell 都认)。
|
|
2328
|
+
* @param value - 任意值;不是字符串的先 `String()`。
|
|
2329
|
+
* @param platform - 目标平台,默认当前 `process.platform`。
|
|
2330
|
+
* @returns 可安全拼进该平台 shell 命令的一段文本;含空格 / 元字符的值不会被当成语法。
|
|
2331
|
+
*/
|
|
2332
|
+
function quoteShellArgFor(value, platform = process.platform) {
|
|
2333
|
+
const text = String(value);
|
|
2334
|
+
if (platform === "win32") return `"${text.replace(/"/g, "\\\"")}"`;
|
|
2335
|
+
return `'${text.replace(/'/g, `'\\''`)}'`;
|
|
2336
|
+
}
|
|
2337
|
+
/**
|
|
2338
|
+
* 按当前平台把值裹成 shell 字面量;跨平台代码要固定平台时用 `quoteShellArgFor`。
|
|
2339
|
+
* @param value - 任意值;不是字符串的先 `String()`。
|
|
2340
|
+
* @returns 可安全拼进当前平台 shell 命令的一段文本。
|
|
2341
|
+
*/
|
|
2342
|
+
function quoteShellArg(value) {
|
|
2343
|
+
return quoteShellArgFor(value, process.platform);
|
|
2344
|
+
}
|
|
2345
|
+
/**
|
|
2346
|
+
* 取一段文本的末尾若干行(如命令输出),顺带去掉首尾空白。
|
|
2347
|
+
* @param text - 原文;`null` / `undefined` 当空串。
|
|
2348
|
+
* @param lines - 最多留几行,默认 6;0 给全篇、负数从开头砍掉那么多行(都是 `slice` 语义),调用方传正数。
|
|
2349
|
+
* @returns 末尾若干行、去首尾空行后的文本;原文行数不够就全给,空输入给空串。
|
|
2350
|
+
*/
|
|
2351
|
+
function tailLines(text, lines = 6) {
|
|
2352
|
+
return String(text ?? "").trim().split("\n").slice(-lines).join("\n");
|
|
2353
|
+
}
|
|
2354
|
+
//#endregion
|
|
2355
|
+
//#region ../shared/dist/host/shell.js
|
|
2356
|
+
var DEFAULT_MAX_BYTES$2 = 8388608;
|
|
2357
|
+
async function runShell(shell, command, options = {}) {
|
|
2358
|
+
const { workdir, timeoutMs = GIT_TIMEOUT_MS, signal } = options;
|
|
2359
|
+
const spec = shell.resolve({
|
|
2360
|
+
command,
|
|
2361
|
+
...workdir === void 0 ? {} : { workdir },
|
|
2362
|
+
timeoutMs,
|
|
2363
|
+
onExpiry: "kill",
|
|
2364
|
+
stdoutMaxBytes: DEFAULT_MAX_BYTES$2,
|
|
2365
|
+
...signal === void 0 ? {} : { signal }
|
|
2366
|
+
});
|
|
2367
|
+
const result = await (await shell.execute(spec)).result();
|
|
2368
|
+
return {
|
|
2369
|
+
exitCode: result.exitCode,
|
|
2370
|
+
timedOut: result.timedOut === true,
|
|
2371
|
+
aborted: result.aborted === true,
|
|
2372
|
+
stdout: result.stdout.text,
|
|
2373
|
+
stderr: result.stderr.text,
|
|
2374
|
+
truncated: result.stdout.truncated || result.stderr.truncated
|
|
2375
|
+
};
|
|
2376
|
+
}
|
|
2377
|
+
function backgroundPrefix() {
|
|
2378
|
+
return [quoteShellArg("env"), quoteShellArg("OPENCLI_WINDOW=background")];
|
|
2379
|
+
}
|
|
2380
|
+
function backgroundLine(command, argv) {
|
|
2381
|
+
return [
|
|
2382
|
+
...backgroundPrefix(),
|
|
2383
|
+
quoteShellArg(command),
|
|
2384
|
+
...argv.map(quoteShellArg)
|
|
2385
|
+
].join(" ");
|
|
2386
|
+
}
|
|
2387
|
+
//#endregion
|
|
2388
2388
|
//#region ../shared/dist/host/paths.js
|
|
2389
2389
|
function isolatedRoot() {
|
|
2390
2390
|
return `${workbenchRoot()}/opencli`;
|
|
@@ -5738,10 +5738,11 @@ function stopVerdict(call, runs) {
|
|
|
5738
5738
|
function publishVerdict(call, preview) {
|
|
5739
5739
|
const raw = argsOf$1(call);
|
|
5740
5740
|
if (raw["verify"] === true || raw["target"] === "local") return { kind: "allow" };
|
|
5741
|
+
const refresh = raw["refresh"] === true;
|
|
5741
5742
|
const unit = textOf$3(raw, "unit");
|
|
5742
5743
|
const found = unit === "" ? null : preview?.(unit) ?? null;
|
|
5743
5744
|
const asked = textOf$3(raw, "target");
|
|
5744
|
-
const target = asked === "" ? found?.market === void 0 ? found?.registry === void 0 ? "tarball" : "team" : "market" : asked;
|
|
5745
|
+
const target = refresh ? "market" : asked === "" ? found?.market === void 0 ? found?.registry === void 0 ? "tarball" : "team" : "market" : asked;
|
|
5745
5746
|
const label = unit === "" ? "工作台模块" : `工作台模块 [${unit}]`;
|
|
5746
5747
|
const labelEn = unit === "" ? "the workbench module" : `the workbench module [${unit}]`;
|
|
5747
5748
|
const copies = {
|
|
@@ -5771,7 +5772,9 @@ function publishVerdict(call, preview) {
|
|
|
5771
5772
|
}
|
|
5772
5773
|
};
|
|
5773
5774
|
const copy = copies[target] ?? copies["team"];
|
|
5774
|
-
|
|
5775
|
+
const targetLabel = found === null ? target : target === "market" && found.market !== void 0 ? `${found.name}@${found.version} → market (${found.market.url})` : `${found.name}@${found.version} → ${target}${found.registry === void 0 ? "" : ` (${found.registry})`}`;
|
|
5776
|
+
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);
|
|
5777
|
+
return askOf(`${DIY_PUBLISH_TOOL} ${targetLabel}${refresh ? "(元数据)" : ""}`, question, question);
|
|
5775
5778
|
}
|
|
5776
5779
|
var panelsApproval = (call) => {
|
|
5777
5780
|
if (call.name === "workbench_long_tasks_stop") return stopVerdict(call, void 0);
|
|
@@ -6792,10 +6795,10 @@ var OUTPUT$2 = {
|
|
|
6792
6795
|
},
|
|
6793
6796
|
unit: { type: "string" },
|
|
6794
6797
|
path: { type: "string" },
|
|
6795
|
-
install: {
|
|
6798
|
+
install: { oneOf: [{
|
|
6796
6799
|
type: "object",
|
|
6797
6800
|
additionalProperties: true
|
|
6798
|
-
},
|
|
6801
|
+
}, { type: "string" }] },
|
|
6799
6802
|
alreadyInstalled: { type: "boolean" },
|
|
6800
6803
|
panel: {
|
|
6801
6804
|
type: "object",
|
|
@@ -8873,6 +8876,10 @@ function renderStatus(root, lines, options = {}) {
|
|
|
8873
8876
|
});
|
|
8874
8877
|
return `${notice === void 0 ? `工作区:${root}` : `工作区:${root}\n${notice}`}\n${block.join("\n")}`;
|
|
8875
8878
|
}
|
|
8879
|
+
function publishStatusOf(preview) {
|
|
8880
|
+
if (preview === null) return "";
|
|
8881
|
+
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} 这一版 —— 先 workbench_diy_changelog(unit=…)` : `发布前置:CHANGELOG 里已有 ${preview.changelog.version}`].filter((one) => one !== void 0).join("\n");
|
|
8882
|
+
}
|
|
8876
8883
|
function renderList(root, modules, shape = "bare") {
|
|
8877
8884
|
if (modules.length === 0) return [
|
|
8878
8885
|
`这个工作区里没有模块源码(${root})—— ${shape === "workspace" ? "它声明了 workspace,但里面的包没有一个报 dsh.workbench.unit" : shape === "package" ? "它是一个包(有 package.json),但没声明 dsh.workbench.unit,也没声明 workspace" : "它没有 package.json(空项目 / 一堆散文件都算这一档)"};这条会话也还没装过任何模块。`,
|
|
@@ -8887,7 +8894,7 @@ function renderList(root, modules, shape = "bare") {
|
|
|
8887
8894
|
//#endregion
|
|
8888
8895
|
//#region src/modules/panels/model/diy-tools.ts
|
|
8889
8896
|
var PUBLISH_TIMEOUT_MS = 18e5;
|
|
8890
|
-
function registerDiyTools(ctx, market, panels, debug) {
|
|
8897
|
+
function registerDiyTools(ctx, market, panels, debug, previewOf = () => null) {
|
|
8891
8898
|
const supply = supplyPortOf(ctx);
|
|
8892
8899
|
const tools = ctx.get("tools");
|
|
8893
8900
|
if (tools === void 0) {
|
|
@@ -8928,10 +8935,13 @@ function registerDiyTools(ctx, market, panels, debug) {
|
|
|
8928
8935
|
installed: one.installed
|
|
8929
8936
|
})
|
|
8930
8937
|
}));
|
|
8938
|
+
const preview = wanted === "" ? null : previewOf(wanted);
|
|
8939
|
+
const text = [renderStatus(root, rows), publishStatusOf(preview)].filter((one) => one !== "").join("\n");
|
|
8931
8940
|
return plainJson({
|
|
8932
8941
|
workspace: root,
|
|
8933
8942
|
status: rows,
|
|
8934
|
-
|
|
8943
|
+
...preview === null ? {} : { publish: preview },
|
|
8944
|
+
text
|
|
8935
8945
|
});
|
|
8936
8946
|
}
|
|
8937
8947
|
};
|
|
@@ -9125,7 +9135,7 @@ function registerDiyTools(ctx, market, panels, debug) {
|
|
|
9125
9135
|
};
|
|
9126
9136
|
const publishTool = {
|
|
9127
9137
|
name: DIY_PUBLISH_TOOL,
|
|
9128
|
-
description: "
|
|
9138
|
+
description: "用户说“发布”后才用:把这一格发到 target 指定的出口(不填按环境默认)。",
|
|
9129
9139
|
parameters: {
|
|
9130
9140
|
type: "object",
|
|
9131
9141
|
properties: {
|
|
@@ -9160,6 +9170,10 @@ function registerDiyTools(ctx, market, panels, debug) {
|
|
|
9160
9170
|
license: {
|
|
9161
9171
|
type: "string",
|
|
9162
9172
|
description: "公开发布用的许可证(MIT / Apache-2.0 / 仓库已有 LICENSE)。"
|
|
9173
|
+
},
|
|
9174
|
+
refresh: {
|
|
9175
|
+
type: "boolean",
|
|
9176
|
+
description: "只刷市集元数据(标题/作者/说明),不升版本、不重发产物。"
|
|
9163
9177
|
}
|
|
9164
9178
|
},
|
|
9165
9179
|
required: ["unit"],
|
|
@@ -9191,6 +9205,7 @@ function registerDiyTools(ctx, market, panels, debug) {
|
|
|
9191
9205
|
if (target !== "") argv.push("--target", target);
|
|
9192
9206
|
if (version !== "") argv.push("--version", version);
|
|
9193
9207
|
if (license !== "") argv.push("--license", license);
|
|
9208
|
+
if (asRecord$1(raw)["refresh"] === true) argv.push("--refresh");
|
|
9194
9209
|
const result = await runShell(shell, argv.map((one) => quoteShellArg(one)).join(" "), {
|
|
9195
9210
|
workdir: root,
|
|
9196
9211
|
timeoutMs: PUBLISH_TIMEOUT_MS
|
|
@@ -9231,7 +9246,7 @@ function registerDiyTools(ctx, market, panels, debug) {
|
|
|
9231
9246
|
`已核过 ${name}@${released}`,
|
|
9232
9247
|
`安装:${install}`,
|
|
9233
9248
|
"没有重新发布。"
|
|
9234
|
-
].join("\n") : targetOfPayload === "tarball" ? [
|
|
9249
|
+
].join("\n") : payload["refresh"] === true ? [payload["refreshed"] === true ? `已刷新 ${name} 的市集元数据(版本 ${released} 不变)` : `${name} 的市集元数据本来就是这样,没动`, `市场索引:${asText(asRecord$1(payload["market"])["url"])}`].join("\n") : targetOfPayload === "tarball" ? [
|
|
9235
9250
|
`安装包在 ${file}`,
|
|
9236
9251
|
`本机装:${install}`,
|
|
9237
9252
|
"文件可以从对话里带走,发给同事。"
|
|
@@ -9362,14 +9377,26 @@ function publishPreviewOf(root, unit, options = {}) {
|
|
|
9362
9377
|
const registry = typeof publishConfig === "object" && publishConfig !== null ? publishConfig["registry"] : void 0;
|
|
9363
9378
|
const market = marketOf(found.unit, found.dir, name, version);
|
|
9364
9379
|
const target = targetVersionOf(version, (options.version ?? "").trim(), market);
|
|
9380
|
+
const author = authorOf(record);
|
|
9365
9381
|
return {
|
|
9366
9382
|
name,
|
|
9367
9383
|
version,
|
|
9384
|
+
...author === "" ? {} : { author },
|
|
9368
9385
|
...typeof registry === "string" && registry !== "" ? { registry } : {},
|
|
9369
9386
|
...market === void 0 ? {} : { market },
|
|
9370
9387
|
changelog: changelogOf(found.dir, target)
|
|
9371
9388
|
};
|
|
9372
9389
|
}
|
|
9390
|
+
function authorOf(manifest) {
|
|
9391
|
+
const author = manifest["author"];
|
|
9392
|
+
if (typeof author === "string") return author.trim();
|
|
9393
|
+
if (author === null || typeof author !== "object") return "";
|
|
9394
|
+
const record = author;
|
|
9395
|
+
const name = typeof record["name"] === "string" ? record["name"].trim() : "";
|
|
9396
|
+
if (name === "") return "";
|
|
9397
|
+
const email = typeof record["email"] === "string" ? record["email"].trim() : "";
|
|
9398
|
+
return email === "" ? name : `${name} <${email}>`;
|
|
9399
|
+
}
|
|
9373
9400
|
function targetVersionOf(version, asked, market) {
|
|
9374
9401
|
if (asked === "") return market?.nextVersion ?? version;
|
|
9375
9402
|
if (/^(major|minor|patch)$/.test(asked)) return bumped(version, asked) ?? version;
|
|
@@ -12851,11 +12878,18 @@ function createMarketDocReader(options) {
|
|
|
12851
12878
|
const directory = (git.path ?? "").replace(/^\/+|\/+$/g, "");
|
|
12852
12879
|
const file = directory === "" ? FILES[kind] : `${directory}/${FILES[kind]}`;
|
|
12853
12880
|
const repo = join(options.root, "market-index", marketSourceKey(source), "repo.git");
|
|
12881
|
+
const show = () => runShell(shell, `git -C ${quoteShellArg(repo)} show ${git.commit}:${quoteShellArg(file)}`, { timeoutMs });
|
|
12882
|
+
const hasCommit = async () => {
|
|
12883
|
+
return (await runShell(shell, `git -C ${quoteShellArg(repo)} cat-file -e ${quoteShellArg(`${git.commit}^{commit}`)}`, { timeoutMs })).exitCode === 0;
|
|
12884
|
+
};
|
|
12854
12885
|
try {
|
|
12855
|
-
|
|
12886
|
+
let result = await show();
|
|
12887
|
+
if (result.exitCode !== 0 && !await hasCommit()) {
|
|
12888
|
+
if ((await runShell(shell, `git -C ${quoteShellArg(repo)} fetch --depth 1 origin ${git.commit}`, { timeoutMs })).exitCode === 0) result = await show();
|
|
12889
|
+
}
|
|
12856
12890
|
if (result.exitCode !== 0) {
|
|
12857
12891
|
const text = result.stderr.trim();
|
|
12858
|
-
return
|
|
12892
|
+
return missingText(text) ? fail(kind, target.version, "missing") : fail(kind, target.version, "unavailable", text);
|
|
12859
12893
|
}
|
|
12860
12894
|
return remember(key, {
|
|
12861
12895
|
ok: true,
|
|
@@ -14353,7 +14387,7 @@ var OWNED = [{
|
|
|
14353
14387
|
registerTools: () => [
|
|
14354
14388
|
...registerPanelTools(ctx, panels, values),
|
|
14355
14389
|
...registerMarketTools(ctx, market),
|
|
14356
|
-
...registerDiyTools(ctx, market, panels, debug),
|
|
14390
|
+
...registerDiyTools(ctx, market, panels, debug, (unit) => publishPreviewOf(workshopPathOf(ctx), unit)),
|
|
14357
14391
|
...registerRecordTools(ctx, record),
|
|
14358
14392
|
...registerLongTaskTools(ctx, longTaskRuns)
|
|
14359
14393
|
],
|
|
@@ -14,7 +14,6 @@ export interface SharedRow {
|
|
|
14
14
|
readonly installed?: string;
|
|
15
15
|
readonly latest?: string;
|
|
16
16
|
};
|
|
17
|
-
readonly detail?: string;
|
|
18
17
|
}
|
|
19
18
|
export declare function sharedActions(row: SharedRow): MarketRowAction[];
|
|
20
19
|
export declare function sharedRows(manifests: readonly UnitManifest[], capabilities: CapabilityMap | null): SharedRow[];
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import type { Translate } from '@dsh-workbench/shared';
|
|
2
2
|
import type { ConfigSyncRow } from '../../../kernel/contract/config-sync';
|
|
3
|
-
export declare function SourceRows({ t, rows, picked, profile,
|
|
3
|
+
export declare function SourceRows({ t, rows, picked, profile, onToggle, }: {
|
|
4
4
|
readonly t: Translate;
|
|
5
5
|
readonly rows: readonly ConfigSyncRow[];
|
|
6
6
|
readonly picked: readonly string[];
|
|
7
7
|
readonly profile: string;
|
|
8
|
-
readonly assetOverwrites: readonly string[];
|
|
9
8
|
readonly onToggle: (key: string, next: boolean) => void;
|
|
10
|
-
readonly onToggleAsset: (key: string, next: boolean) => void;
|
|
11
9
|
}): JSX.Element;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { CONFIG_SYNC_ROUTE, CONFIG_SYNC_RESOURCE } from '@dsh-workbench/shared/contract/protocol/config-sync';
|
|
2
|
-
export type { ConfigSyncState,
|
|
2
|
+
export type { ConfigSyncState, ConfigSyncRow, ConfigSyncProfile, ConfigSyncSnapshot, ConfigSyncApplied, ConfigSyncRequest } from '@dsh-workbench/shared/contract/protocol/config-sync';
|
|
@@ -24,8 +24,13 @@ export declare const OUTPUT_SCHEMA: {
|
|
|
24
24
|
type: string;
|
|
25
25
|
};
|
|
26
26
|
install: {
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
oneOf: ({
|
|
28
|
+
type: string;
|
|
29
|
+
additionalProperties: boolean;
|
|
30
|
+
} | {
|
|
31
|
+
type: string;
|
|
32
|
+
additionalProperties?: undefined;
|
|
33
|
+
})[];
|
|
29
34
|
};
|
|
30
35
|
alreadyInstalled: {
|
|
31
36
|
type: string;
|
|
@@ -61,8 +66,13 @@ export declare const OUTPUT: {
|
|
|
61
66
|
type: string;
|
|
62
67
|
};
|
|
63
68
|
install: {
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
oneOf: ({
|
|
70
|
+
type: string;
|
|
71
|
+
additionalProperties: boolean;
|
|
72
|
+
} | {
|
|
73
|
+
type: string;
|
|
74
|
+
additionalProperties?: undefined;
|
|
75
|
+
})[];
|
|
66
76
|
};
|
|
67
77
|
alreadyInstalled: {
|
|
68
78
|
type: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PanelUnitReport } from '@dsh-workbench/shared/host';
|
|
2
|
+
import type { PublishPreview } from '@dsh-workbench/shared/contract/protocol/market-index';
|
|
2
3
|
import { type DiyModule, type SyncState, type Toolchain, type WorkspaceShape } from '../../../shared/api/host/diy-modules';
|
|
3
4
|
export declare const SYNC_STALE_MINUTES = 15;
|
|
4
5
|
export declare const SYNC_STALE_MS: number;
|
|
@@ -70,4 +71,5 @@ export declare function statusOf(options: {
|
|
|
70
71
|
export declare function renderStatus(root: string, lines: readonly ModuleStatus[], options?: {
|
|
71
72
|
readonly shellVersion?: string;
|
|
72
73
|
}): string;
|
|
74
|
+
export declare function publishStatusOf(preview: PublishPreview | null): string;
|
|
73
75
|
export declare function renderList(root: string, modules: readonly DiyModule[], shape?: WorkspaceShape): string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { DshHostContext } from '@dsh-workbench/shared';
|
|
2
2
|
import type { DebugStore } from '@dsh-workbench/shared/host';
|
|
3
|
+
import type { PublishPreview } from '@dsh-workbench/shared/contract/protocol/market-index';
|
|
3
4
|
import type { MarketService } from './market';
|
|
4
5
|
import type { PanelsService } from './service';
|
|
5
6
|
export declare const PUBLISH_TIMEOUT_MS: number;
|
|
6
|
-
export declare function registerDiyTools(ctx: DshHostContext, market: MarketService, panels: PanelsService, debug: DebugStore): Array<() => void>;
|
|
7
|
+
export declare function registerDiyTools(ctx: DshHostContext, market: MarketService, panels: PanelsService, debug: DebugStore, previewOf?: (unit: string) => PublishPreview | null): Array<() => void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-workbench/core",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "个人工作台:Agent 工作台(左栏 + 常驻对话 + 自研右侧数据面板)。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"icon": "./icon.svg",
|
|
@@ -36,6 +36,8 @@
|
|
|
36
36
|
"preset",
|
|
37
37
|
"scripts/create-workbench.mjs",
|
|
38
38
|
"scripts/clone-profile.mjs",
|
|
39
|
+
"scripts/patch-blocks.mjs",
|
|
40
|
+
"scripts/share-data-root.mjs",
|
|
39
41
|
"scripts/seed-profile.sh",
|
|
40
42
|
"scripts/seed-workshop.sh",
|
|
41
43
|
"README.md"
|
|
@@ -98,8 +100,8 @@
|
|
|
98
100
|
"proper-lockfile": "^4.1.2",
|
|
99
101
|
"which": "^7.0.0",
|
|
100
102
|
"write-file-atomic": "^8.0.0",
|
|
101
|
-
"@dsh-workbench/shared": "1.0.0
|
|
102
|
-
"@dsh-workbench/adapters-default": "1.0.0
|
|
103
|
+
"@dsh-workbench/shared": "1.0.0",
|
|
104
|
+
"@dsh-workbench/adapters-default": "1.0.0"
|
|
103
105
|
},
|
|
104
106
|
"license": "MIT",
|
|
105
107
|
"repository": {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 工作台运行时的**可写根**声明。两个入口共用同一行:
|
|
2
|
+
# 1. 启动器每次启动用 `--patch` 叠一层(对新旧 profile 都生效);
|
|
3
|
+
# 2. `scripts/share-data-root.mjs` 把这一行补进 profile 的 cordis.patch.yml,
|
|
4
|
+
# 给不带启动器的 `dsh <profile>` 兜底(只抄这一行,不抄注释)。
|
|
2
5
|
#
|
|
3
6
|
# 为什么必须有它:工作台自己要跑命令(启动体检自动装 opencli、模块市场装/升插件、
|
|
4
7
|
# 查源上有没有新版),而这些命令走 dsh 的**执行缝**,执行缝带**文件沙箱**。
|
|
@@ -9,14 +12,13 @@
|
|
|
9
12
|
# 症状:自动安装死在第一步,界面只能退化成"让用户去终端抄一条命令" ——
|
|
10
13
|
# 终端没有沙箱,抄过去反而能跑,于是这个缺口一直看不出来。
|
|
11
14
|
#
|
|
12
|
-
#
|
|
15
|
+
# 指到运行时根之后,沙箱放行的是**同一棵树**:
|
|
13
16
|
# 隔离运行时的工具链 + npm 缓存(opencli-runtime.ts)、
|
|
14
17
|
# 模块专属文件夹(ADR-0011 的 workspaces/)、模块市场的 plugins-npm。
|
|
15
18
|
# 也就是 ADR-0011 说的"启动器给插件声明的可写根"。
|
|
16
19
|
#
|
|
17
|
-
#
|
|
18
|
-
# profile
|
|
19
|
-
# seed-profile.sh —— 叠加层每次启动都生效,对新旧 profile 一视同仁。
|
|
20
|
+
# 会话 / 项目 / 附件**不在这里**:它们跟 `dsh web` / Desktop 共用 `$DSH_HOME`,
|
|
21
|
+
# 不再由工作台按 profile 隔离(见 ADR-0085)。
|
|
20
22
|
#
|
|
21
23
|
# mode 与 base 出厂值**一致**(只重述,不改变语义):patch 的 config 是**整体替换**、
|
|
22
24
|
# 不深合并,所以两个字段都得写全,否则 workspaceRoot 会被替换掉 mode 丢失。
|