@dsh-workbench/core 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.js +372 -248
- package/dist/client/client.body.js +372 -248
- package/dist/client/index.js +372 -248
- package/dist/host/index.js +154 -6
- package/dist/types/app/client.d.ts +6 -6
- package/dist/types/app/layouts/env-gate/__tests__/gate-deadline.test.d.ts +1 -0
- package/dist/types/app/layouts/env-gate/gate-deadline.d.ts +4 -0
- package/dist/types/app/layouts/rightbar/MarketStates.d.ts +7 -0
- package/dist/types/app/layouts/rightbar/MarketView.d.ts +2 -1
- package/dist/types/app/layouts/rightbar/SharedSection.d.ts +11 -0
- package/dist/types/app/layouts/rightbar/__tests__/market-change.test.d.ts +1 -0
- package/dist/types/app/layouts/rightbar/__tests__/market-live.test.d.ts +1 -0
- package/dist/types/app/layouts/rightbar/__tests__/market-settle.test.d.ts +1 -0
- package/dist/types/app/layouts/rightbar/market-change.d.ts +4 -0
- package/dist/types/app/layouts/rightbar/market-rows.d.ts +3 -1
- package/dist/types/app/layouts/rightbar/market-settle.d.ts +2 -0
- package/dist/types/app/layouts/rightbar/market-view-text.d.ts +10 -0
- package/dist/types/modules/panels/__tests__/market-registries.test.d.ts +1 -0
- package/dist/types/modules/panels/model/market.d.ts +2 -0
- package/dist/types/shared/api/host/__tests__/profile-registries.test.d.ts +1 -0
- package/dist/types/shared/api/host/profile-registries.d.ts +21 -0
- package/docs/OPERATIONS.md +2 -0
- package/package.json +2 -2
package/dist/host/index.js
CHANGED
|
@@ -1380,7 +1380,7 @@ function readBundleManager(ctx) {
|
|
|
1380
1380
|
}
|
|
1381
1381
|
//#endregion
|
|
1382
1382
|
//#region src/shared/api/host/installed-module.ts
|
|
1383
|
-
var PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/;
|
|
1383
|
+
var PACKAGE_NAME$1 = /^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/;
|
|
1384
1384
|
function asRecord$1(value) {
|
|
1385
1385
|
return typeof value === "object" && value !== null ? value : void 0;
|
|
1386
1386
|
}
|
|
@@ -1388,7 +1388,7 @@ function asText$1(value) {
|
|
|
1388
1388
|
return typeof value === "string" ? value : "";
|
|
1389
1389
|
}
|
|
1390
1390
|
function isPackageName(value) {
|
|
1391
|
-
return value.length <= 214 && PACKAGE_NAME.test(value);
|
|
1391
|
+
return value.length <= 214 && PACKAGE_NAME$1.test(value);
|
|
1392
1392
|
}
|
|
1393
1393
|
function profileDirOf(ctx) {
|
|
1394
1394
|
const profile = ctx.get("profileContext");
|
|
@@ -1477,6 +1477,118 @@ function readInstalledModule(profileDir, pkg) {
|
|
|
1477
1477
|
};
|
|
1478
1478
|
}
|
|
1479
1479
|
//#endregion
|
|
1480
|
+
//#region src/shared/api/host/profile-registries.ts
|
|
1481
|
+
var REGISTRY_MARKER = "# dsh-workbench 写的:这一行的包只在这个源上(dsh 卸载没有源参数,pnpm 得问得到)";
|
|
1482
|
+
function scopeOf(pkg) {
|
|
1483
|
+
const slash = pkg.indexOf("/");
|
|
1484
|
+
return pkg.startsWith("@") && slash > 1 ? pkg.slice(0, slash) : null;
|
|
1485
|
+
}
|
|
1486
|
+
function normalizeRegistry(url) {
|
|
1487
|
+
const trimmed = url.trim();
|
|
1488
|
+
return trimmed.endsWith("/") ? trimmed : `${trimmed}/`;
|
|
1489
|
+
}
|
|
1490
|
+
function sameRegistry(a, b) {
|
|
1491
|
+
if (a === null || a === void 0 || b === null || b === void 0) return false;
|
|
1492
|
+
if (a.trim() === "" || b.trim() === "") return false;
|
|
1493
|
+
return normalizeRegistry(a) === normalizeRegistry(b);
|
|
1494
|
+
}
|
|
1495
|
+
function registryRootOf(name, tarball) {
|
|
1496
|
+
const at = tarball.indexOf(`/${name}/-/`);
|
|
1497
|
+
if (at > 0) return normalizeRegistry(tarball.slice(0, at));
|
|
1498
|
+
try {
|
|
1499
|
+
return normalizeRegistry(new URL(tarball).origin);
|
|
1500
|
+
} catch {
|
|
1501
|
+
return null;
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
var PACKAGE_KEY = /^ {2}'?(\S+)'?:\s*$/;
|
|
1505
|
+
var PACKAGE_NAME = /^(?:@[^/\s]+\/)?[^/\s@]+$/;
|
|
1506
|
+
var TARBALL = /tarball:\s*(\S+?)\}?\s*$/;
|
|
1507
|
+
function sourcesFromLockfile(text) {
|
|
1508
|
+
const found = /* @__PURE__ */ new Map();
|
|
1509
|
+
let name = null;
|
|
1510
|
+
for (const line of text.split("\n")) {
|
|
1511
|
+
const key = PACKAGE_KEY.exec(line);
|
|
1512
|
+
if (key !== null) {
|
|
1513
|
+
const raw = key[1] ?? "";
|
|
1514
|
+
const at = raw.lastIndexOf("@");
|
|
1515
|
+
const candidate = at > 0 ? raw.slice(0, at) : "";
|
|
1516
|
+
name = PACKAGE_NAME.test(candidate) ? candidate : null;
|
|
1517
|
+
continue;
|
|
1518
|
+
}
|
|
1519
|
+
if (name === null) continue;
|
|
1520
|
+
const tarball = TARBALL.exec(line);
|
|
1521
|
+
if (tarball === null) continue;
|
|
1522
|
+
const scope = scopeOf(name);
|
|
1523
|
+
const root = registryRootOf(name, tarball[1] ?? "");
|
|
1524
|
+
name = null;
|
|
1525
|
+
if (scope === null || root === null) continue;
|
|
1526
|
+
const seen = found.get(scope);
|
|
1527
|
+
if (seen === void 0) found.set(scope, root);
|
|
1528
|
+
else if (!sameRegistry(seen, root)) found.set(scope, null);
|
|
1529
|
+
}
|
|
1530
|
+
return [...found.entries()].filter((entry) => entry[1] !== null).map(([scope, registry]) => ({
|
|
1531
|
+
scope,
|
|
1532
|
+
registry
|
|
1533
|
+
}));
|
|
1534
|
+
}
|
|
1535
|
+
function mergeRegistryConfig(text, entries) {
|
|
1536
|
+
const lines = text.split("\n");
|
|
1537
|
+
const present = (key) => lines.some((line) => line.trim().startsWith(`${key}=`));
|
|
1538
|
+
const appended = [];
|
|
1539
|
+
const added = [];
|
|
1540
|
+
for (const entry of entries) {
|
|
1541
|
+
const key = `${entry.scope}:registry`;
|
|
1542
|
+
if (entry.registry.trim() === "" || present(key)) continue;
|
|
1543
|
+
lines.push(`${key}=${normalizeRegistry(entry.registry)}`);
|
|
1544
|
+
appended.push(`${key}=${normalizeRegistry(entry.registry)}`);
|
|
1545
|
+
added.push(key);
|
|
1546
|
+
}
|
|
1547
|
+
if (appended.length === 0) return {
|
|
1548
|
+
text,
|
|
1549
|
+
added: []
|
|
1550
|
+
};
|
|
1551
|
+
const base = text === "" ? "" : text.endsWith("\n") ? text : `${text}\n`;
|
|
1552
|
+
return {
|
|
1553
|
+
text: `${base}${base.includes("# dsh-workbench 写的:这一行的包只在这个源上(dsh 卸载没有源参数,pnpm 得问得到)") ? "" : `${REGISTRY_MARKER}\n`}${appended.join("\n")}\n`,
|
|
1554
|
+
added
|
|
1555
|
+
};
|
|
1556
|
+
}
|
|
1557
|
+
function registryFailure(change) {
|
|
1558
|
+
if (change.application !== "failed") return false;
|
|
1559
|
+
if (change.packageResult?.kind === "not-found") return true;
|
|
1560
|
+
const output = change.packageResult?.output ?? change.errorDetail ?? "";
|
|
1561
|
+
return /ERR_PNPM_[A-Z_]*FETCH/.test(output);
|
|
1562
|
+
}
|
|
1563
|
+
function createRegistryNotebook(dir) {
|
|
1564
|
+
return {
|
|
1565
|
+
sources() {
|
|
1566
|
+
if (dir === null) return [];
|
|
1567
|
+
try {
|
|
1568
|
+
return sourcesFromLockfile(fs.readFileSync(path.join(dir, "pnpm-lock.yaml"), "utf8"));
|
|
1569
|
+
} catch {
|
|
1570
|
+
return [];
|
|
1571
|
+
}
|
|
1572
|
+
},
|
|
1573
|
+
remember(entries) {
|
|
1574
|
+
if (dir === null || entries.length === 0) return [];
|
|
1575
|
+
const file = path.join(dir, ".npmrc");
|
|
1576
|
+
let before;
|
|
1577
|
+
try {
|
|
1578
|
+
before = fs.readFileSync(file, "utf8");
|
|
1579
|
+
} catch {
|
|
1580
|
+
before = "";
|
|
1581
|
+
}
|
|
1582
|
+
const merged = mergeRegistryConfig(before, entries);
|
|
1583
|
+
if (merged.added.length === 0) return [];
|
|
1584
|
+
const temp = `${file}.dsh-workbench.tmp`;
|
|
1585
|
+
fs.writeFileSync(temp, merged.text, { mode: 384 });
|
|
1586
|
+
fs.renameSync(temp, file);
|
|
1587
|
+
return merged.added;
|
|
1588
|
+
}
|
|
1589
|
+
};
|
|
1590
|
+
}
|
|
1591
|
+
//#endregion
|
|
1480
1592
|
//#region src/shared/api/host/release.ts
|
|
1481
1593
|
function parseLedgerVersion(stdout, name) {
|
|
1482
1594
|
const parsed = parseJsonLoose(stdout);
|
|
@@ -1703,7 +1815,7 @@ function bundleNameOf(change, spec) {
|
|
|
1703
1815
|
return at > 0 ? spec.slice(0, at) : spec;
|
|
1704
1816
|
}
|
|
1705
1817
|
function createMarketService(options) {
|
|
1706
|
-
const { manifests, manifestsNow, probe, shell, logger, onInstalled, onUninstalled, isReleased, bundles, installed, modules } = options;
|
|
1818
|
+
const { manifests, manifestsNow, probe, shell, logger, onInstalled, onUninstalled, isReleased, bundles, installed, modules, registries } = options;
|
|
1707
1819
|
const command = options.command ?? "opencli";
|
|
1708
1820
|
const catalog = () => (manifestsNow?.() ?? manifests).filter((manifest) => (manifest.env?.plugins ?? []).length > 0 || (manifest.env?.libs ?? []).length > 0);
|
|
1709
1821
|
function requireEntry(unit) {
|
|
@@ -1850,6 +1962,38 @@ function createMarketService(options) {
|
|
|
1850
1962
|
};
|
|
1851
1963
|
}
|
|
1852
1964
|
}
|
|
1965
|
+
async function rememberInstalledSource(manager, pkg, registry) {
|
|
1966
|
+
if (registries === void 0 || registry === void 0) return;
|
|
1967
|
+
const scope = scopeOf(pkg);
|
|
1968
|
+
if (scope === null) return;
|
|
1969
|
+
const known = await manager.registries().catch(() => null);
|
|
1970
|
+
if (known !== null && sameRegistry(known.resolved, registry)) return;
|
|
1971
|
+
try {
|
|
1972
|
+
const added = registries.remember([{
|
|
1973
|
+
scope,
|
|
1974
|
+
registry
|
|
1975
|
+
}]);
|
|
1976
|
+
if (added.length > 0) logger?.info?.(`[dsh-workbench] 把 ${added.join("、")} 记进 profile 的 .npmrc(卸载只认 pnpm 的配置)`);
|
|
1977
|
+
} catch (error) {
|
|
1978
|
+
logger?.warn?.(`[dsh-workbench] 记这个 scope 的源失败:${String(error)}`);
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
async function retryAfterRegistryFix(manager, pkg, change) {
|
|
1982
|
+
if (registries === void 0 || !registryFailure(change)) return change;
|
|
1983
|
+
const known = await manager.registries().catch(() => null);
|
|
1984
|
+
const missing = registries.sources().filter((entry) => !sameRegistry(entry.registry, known?.resolved ?? null));
|
|
1985
|
+
if (missing.length === 0) return change;
|
|
1986
|
+
let added;
|
|
1987
|
+
try {
|
|
1988
|
+
added = registries.remember(missing);
|
|
1989
|
+
} catch (error) {
|
|
1990
|
+
logger?.warn?.(`[dsh-workbench] 卸 ${pkg} 撞上源,但补配置失败:${String(error)}`);
|
|
1991
|
+
return change;
|
|
1992
|
+
}
|
|
1993
|
+
if (added.length === 0) return change;
|
|
1994
|
+
logger?.warn?.(`[dsh-workbench] 卸 ${pkg} 撞上源:补 ${added.join("、")} 后重试一次`);
|
|
1995
|
+
return await manager.remove(pkg).catch(() => null) ?? change;
|
|
1996
|
+
}
|
|
1853
1997
|
const service = {
|
|
1854
1998
|
async list() {
|
|
1855
1999
|
return snapshot();
|
|
@@ -1955,7 +2099,8 @@ function createMarketService(options) {
|
|
|
1955
2099
|
};
|
|
1956
2100
|
},
|
|
1957
2101
|
async installBundle(spec, options) {
|
|
1958
|
-
const
|
|
2102
|
+
const manager = requireBundles();
|
|
2103
|
+
const change = await manager.install({
|
|
1959
2104
|
spec,
|
|
1960
2105
|
...options?.registry === void 0 ? {} : { registry: options.registry },
|
|
1961
2106
|
...options?.requestId === void 0 ? {} : { requestId: options.requestId },
|
|
@@ -1967,6 +2112,7 @@ function createMarketService(options) {
|
|
|
1967
2112
|
kind: "unknown",
|
|
1968
2113
|
pkg
|
|
1969
2114
|
};
|
|
2115
|
+
await rememberInstalledSource(manager, pkg, options?.registry);
|
|
1970
2116
|
return {
|
|
1971
2117
|
change,
|
|
1972
2118
|
module,
|
|
@@ -1982,8 +2128,9 @@ function createMarketService(options) {
|
|
|
1982
2128
|
const unit = module.kind === "module" ? module.unit : void 0;
|
|
1983
2129
|
const manifest = unit === void 0 ? void 0 : catalog().find((item) => item.id === unit);
|
|
1984
2130
|
const before = unit === void 0 ? void 0 : await capabilityOf(unit, true);
|
|
1985
|
-
const
|
|
1986
|
-
if (
|
|
2131
|
+
const first = await manager.remove(pkg);
|
|
2132
|
+
if (first === null) throw new Error("插件管理器回的卸载结果看不懂。");
|
|
2133
|
+
const change = await retryAfterRegistryFix(manager, pkg, first);
|
|
1987
2134
|
if (change.application !== "applied" || unit === void 0) return {
|
|
1988
2135
|
change,
|
|
1989
2136
|
keptFor: []
|
|
@@ -2682,6 +2829,7 @@ var HOST_UNITS = [{
|
|
|
2682
2829
|
bundles: readBundleManager(ctx),
|
|
2683
2830
|
installed: (pkg) => readInstalledModule(profileDir, pkg),
|
|
2684
2831
|
modules: () => profileModules(profileDir),
|
|
2832
|
+
registries: createRegistryNotebook(profileDir),
|
|
2685
2833
|
onUninstalled: (unit) => {
|
|
2686
2834
|
panels.release(unit);
|
|
2687
2835
|
},
|
|
@@ -251,7 +251,7 @@ export declare const kit: {
|
|
|
251
251
|
readonly "panels.market.empty": "\u6682\u65E0\u53EF\u7528\u6A21\u5757";
|
|
252
252
|
readonly "panels.market.installedSection": "\u5DF2\u88C5";
|
|
253
253
|
readonly "panels.market.moduleOutdated": "\u6709\u65B0\u7248";
|
|
254
|
-
readonly "panels.market.moduleRestartHint": "\
|
|
254
|
+
readonly "panels.market.moduleRestartHint": "\u88C5\u597D\u4E86\u4F46\u8FD8\u6CA1\u751F\u6548 \u2014\u2014 \u91CD\u542F\u4E00\u6B21 dsh \u5C31\u4F1A\u51FA\u6765";
|
|
255
255
|
readonly "panels.market.restartNeeded": "\u65B0\u7248\u88C5\u597D\u4E86\uFF0C\u91CD\u542F\u4E00\u6B21\u624D\u751F\u6548\u3002";
|
|
256
256
|
readonly "panels.market.foot": "\u88C5\u597D\u540E\u5230\u90A3\u4E2A\u9879\u76EE\u7684\u9762\u677F\u9875\u52FE\u9009\u5B83\uFF0C\u6A21\u5757\u624D\u4F1A\u51FA\u73B0\u3002";
|
|
257
257
|
readonly "panels.market.recheck": "\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0";
|
|
@@ -544,7 +544,7 @@ export declare const kit: {
|
|
|
544
544
|
readonly "panels.market.empty": "\u6682\u65E0\u53EF\u7528\u6A21\u5757";
|
|
545
545
|
readonly "panels.market.installedSection": "\u5DF2\u88C5";
|
|
546
546
|
readonly "panels.market.moduleOutdated": "\u6709\u65B0\u7248";
|
|
547
|
-
readonly "panels.market.moduleRestartHint": "\
|
|
547
|
+
readonly "panels.market.moduleRestartHint": "\u88C5\u597D\u4E86\u4F46\u8FD8\u6CA1\u751F\u6548 \u2014\u2014 \u91CD\u542F\u4E00\u6B21 dsh \u5C31\u4F1A\u51FA\u6765";
|
|
548
548
|
readonly "panels.market.restartNeeded": "\u65B0\u7248\u88C5\u597D\u4E86\uFF0C\u91CD\u542F\u4E00\u6B21\u624D\u751F\u6548\u3002";
|
|
549
549
|
readonly "panels.market.foot": "\u88C5\u597D\u540E\u5230\u90A3\u4E2A\u9879\u76EE\u7684\u9762\u677F\u9875\u52FE\u9009\u5B83\uFF0C\u6A21\u5757\u624D\u4F1A\u51FA\u73B0\u3002";
|
|
550
550
|
readonly "panels.market.recheck": "\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0";
|
|
@@ -976,7 +976,7 @@ export declare const kit: {
|
|
|
976
976
|
readonly "panels.market.empty": "\u6682\u65E0\u53EF\u7528\u6A21\u5757";
|
|
977
977
|
readonly "panels.market.installedSection": "\u5DF2\u88C5";
|
|
978
978
|
readonly "panels.market.moduleOutdated": "\u6709\u65B0\u7248";
|
|
979
|
-
readonly "panels.market.moduleRestartHint": "\
|
|
979
|
+
readonly "panels.market.moduleRestartHint": "\u88C5\u597D\u4E86\u4F46\u8FD8\u6CA1\u751F\u6548 \u2014\u2014 \u91CD\u542F\u4E00\u6B21 dsh \u5C31\u4F1A\u51FA\u6765";
|
|
980
980
|
readonly "panels.market.restartNeeded": "\u65B0\u7248\u88C5\u597D\u4E86\uFF0C\u91CD\u542F\u4E00\u6B21\u624D\u751F\u6548\u3002";
|
|
981
981
|
readonly "panels.market.foot": "\u88C5\u597D\u540E\u5230\u90A3\u4E2A\u9879\u76EE\u7684\u9762\u677F\u9875\u52FE\u9009\u5B83\uFF0C\u6A21\u5757\u624D\u4F1A\u51FA\u73B0\u3002";
|
|
982
982
|
readonly "panels.market.recheck": "\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0";
|
|
@@ -1269,7 +1269,7 @@ export declare const kit: {
|
|
|
1269
1269
|
readonly "panels.market.empty": "\u6682\u65E0\u53EF\u7528\u6A21\u5757";
|
|
1270
1270
|
readonly "panels.market.installedSection": "\u5DF2\u88C5";
|
|
1271
1271
|
readonly "panels.market.moduleOutdated": "\u6709\u65B0\u7248";
|
|
1272
|
-
readonly "panels.market.moduleRestartHint": "\
|
|
1272
|
+
readonly "panels.market.moduleRestartHint": "\u88C5\u597D\u4E86\u4F46\u8FD8\u6CA1\u751F\u6548 \u2014\u2014 \u91CD\u542F\u4E00\u6B21 dsh \u5C31\u4F1A\u51FA\u6765";
|
|
1273
1273
|
readonly "panels.market.restartNeeded": "\u65B0\u7248\u88C5\u597D\u4E86\uFF0C\u91CD\u542F\u4E00\u6B21\u624D\u751F\u6548\u3002";
|
|
1274
1274
|
readonly "panels.market.foot": "\u88C5\u597D\u540E\u5230\u90A3\u4E2A\u9879\u76EE\u7684\u9762\u677F\u9875\u52FE\u9009\u5B83\uFF0C\u6A21\u5757\u624D\u4F1A\u51FA\u73B0\u3002";
|
|
1275
1275
|
readonly "panels.market.recheck": "\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0";
|
|
@@ -1696,7 +1696,7 @@ export declare const kit: {
|
|
|
1696
1696
|
readonly "panels.market.empty": "\u6682\u65E0\u53EF\u7528\u6A21\u5757";
|
|
1697
1697
|
readonly "panels.market.installedSection": "\u5DF2\u88C5";
|
|
1698
1698
|
readonly "panels.market.moduleOutdated": "\u6709\u65B0\u7248";
|
|
1699
|
-
readonly "panels.market.moduleRestartHint": "\
|
|
1699
|
+
readonly "panels.market.moduleRestartHint": "\u88C5\u597D\u4E86\u4F46\u8FD8\u6CA1\u751F\u6548 \u2014\u2014 \u91CD\u542F\u4E00\u6B21 dsh \u5C31\u4F1A\u51FA\u6765";
|
|
1700
1700
|
readonly "panels.market.restartNeeded": "\u65B0\u7248\u88C5\u597D\u4E86\uFF0C\u91CD\u542F\u4E00\u6B21\u624D\u751F\u6548\u3002";
|
|
1701
1701
|
readonly "panels.market.foot": "\u88C5\u597D\u540E\u5230\u90A3\u4E2A\u9879\u76EE\u7684\u9762\u677F\u9875\u52FE\u9009\u5B83\uFF0C\u6A21\u5757\u624D\u4F1A\u51FA\u73B0\u3002";
|
|
1702
1702
|
readonly "panels.market.recheck": "\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0";
|
|
@@ -1989,7 +1989,7 @@ export declare const kit: {
|
|
|
1989
1989
|
readonly "panels.market.empty": "\u6682\u65E0\u53EF\u7528\u6A21\u5757";
|
|
1990
1990
|
readonly "panels.market.installedSection": "\u5DF2\u88C5";
|
|
1991
1991
|
readonly "panels.market.moduleOutdated": "\u6709\u65B0\u7248";
|
|
1992
|
-
readonly "panels.market.moduleRestartHint": "\
|
|
1992
|
+
readonly "panels.market.moduleRestartHint": "\u88C5\u597D\u4E86\u4F46\u8FD8\u6CA1\u751F\u6548 \u2014\u2014 \u91CD\u542F\u4E00\u6B21 dsh \u5C31\u4F1A\u51FA\u6765";
|
|
1993
1993
|
readonly "panels.market.restartNeeded": "\u65B0\u7248\u88C5\u597D\u4E86\uFF0C\u91CD\u542F\u4E00\u6B21\u624D\u751F\u6548\u3002";
|
|
1994
1994
|
readonly "panels.market.foot": "\u88C5\u597D\u540E\u5230\u90A3\u4E2A\u9879\u76EE\u7684\u9762\u677F\u9875\u52FE\u9009\u5B83\uFF0C\u6A21\u5757\u624D\u4F1A\u51FA\u73B0\u3002";
|
|
1995
1995
|
readonly "panels.market.recheck": "\u91CD\u65B0\u68C0\u67E5\u66F4\u65B0";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -14,6 +14,7 @@ export interface MarketViewProps {
|
|
|
14
14
|
readonly updates?: ModuleUpdateMap | undefined;
|
|
15
15
|
readonly installed?: readonly InstalledWorkbenchModule[] | undefined;
|
|
16
16
|
readonly installedRead?: boolean | undefined;
|
|
17
|
+
readonly settling?: ReadonlySet<string> | undefined;
|
|
17
18
|
readonly mock?: MarketMock | undefined;
|
|
18
19
|
}
|
|
19
|
-
export declare function MarketView({ t, manifests, capabilities, freshness, onChanged, updates, installed, installedRead, mock, }: MarketViewProps): JSX.Element;
|
|
20
|
+
export declare function MarketView({ t, manifests, capabilities, freshness, onChanged, updates, installed, installedRead, settling, mock, }: MarketViewProps): JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Translate } from '@dsh-workbench/shared';
|
|
2
|
+
import { type SharedRow } from './market-rows';
|
|
3
|
+
import { type Pending } from './market-view-text';
|
|
4
|
+
import type { MarketRowAction } from './market-rows';
|
|
5
|
+
export declare function SharedSection({ t, rows, pending, failureOf, act, }: {
|
|
6
|
+
readonly t: Translate;
|
|
7
|
+
readonly rows: readonly SharedRow[];
|
|
8
|
+
readonly pending: Pending | null;
|
|
9
|
+
readonly failureOf: (id: string) => string | null;
|
|
10
|
+
readonly act: (id: string, action: MarketRowAction) => Promise<void>;
|
|
11
|
+
}): JSX.Element | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Translate } from '@dsh-workbench/shared';
|
|
2
|
+
import type { BundleChange } from '../../../shared/api/bundle-install';
|
|
3
|
+
export declare function changeOf(value: unknown): BundleChange | undefined;
|
|
4
|
+
export declare function changeFailure(change: BundleChange | undefined, t: Translate): string | undefined;
|
|
@@ -36,8 +36,10 @@ export interface InstalledWorkbenchModule {
|
|
|
36
36
|
readonly installed: string;
|
|
37
37
|
readonly latest?: string | undefined;
|
|
38
38
|
}
|
|
39
|
-
export declare function
|
|
39
|
+
export declare function mergeTitles(known: ReadonlyMap<string, string>, manifests: readonly UnitManifest[]): ReadonlyMap<string, string>;
|
|
40
|
+
export declare function installedRows(modules: readonly InstalledWorkbenchModule[], manifests: readonly UnitManifest[], listed: ReadonlySet<string>, known?: ReadonlyMap<string, string> | undefined): MarketRow[];
|
|
40
41
|
export declare function marketActions(row: MarketRow): MarketRowAction[];
|
|
42
|
+
export declare function liveManifests(manifests: readonly UnitManifest[], capabilities: CapabilityMap | null, installed: ReadonlySet<string> | null): readonly UnitManifest[];
|
|
41
43
|
export declare function marketHasUpdates(rows: readonly MarketRow[], shared?: readonly SharedRow[]): boolean;
|
|
42
44
|
export interface MarketSection {
|
|
43
45
|
readonly id: 'installed' | 'not-installed';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MarketRowAction } from './market-rows';
|
|
2
|
+
export declare const PROGRESS_KEY: Readonly<Record<MarketRowAction, string>>;
|
|
3
|
+
export declare const ACTION_LABEL_KEY: Readonly<Record<MarketRowAction, string>>;
|
|
4
|
+
export interface Pending {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly action: MarketRowAction;
|
|
7
|
+
readonly titleKey?: string | undefined;
|
|
8
|
+
readonly pkg?: string | undefined;
|
|
9
|
+
readonly version?: string | undefined;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -3,6 +3,7 @@ import type { PluginSource, UnitManifest } from '@dsh-workbench/shared';
|
|
|
3
3
|
import type { BundleCancellation, BundleChange } from '../../../shared/api/bundle-install';
|
|
4
4
|
import type { BundleManager } from '../../../shared/api/host/bundle-manager';
|
|
5
5
|
import type { InstalledModule, ProfileModule } from '../../../shared/api/host/installed-module';
|
|
6
|
+
import { type RegistryNotebook } from '../../../shared/api/host/profile-registries';
|
|
6
7
|
import type { UnitCapability } from '../../../shared/api/host/probe-units';
|
|
7
8
|
import type { ProvisionAction } from '@dsh-workbench/shared/host';
|
|
8
9
|
import type { UnitMountDeps } from '@dsh-workbench/shared/host';
|
|
@@ -81,6 +82,7 @@ export declare function createMarketService(options: {
|
|
|
81
82
|
bundles?: BundleManager | undefined;
|
|
82
83
|
installed?: ((pkg: string) => InstalledModule) | undefined;
|
|
83
84
|
modules?: (() => readonly ProfileModule[]) | undefined;
|
|
85
|
+
registries?: RegistryNotebook | undefined;
|
|
84
86
|
logger?: {
|
|
85
87
|
info?(message: string): void;
|
|
86
88
|
warn?(message: string): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BundleChange } from '../bundle-install.js';
|
|
2
|
+
export interface RegistryEntry {
|
|
3
|
+
readonly scope: string;
|
|
4
|
+
readonly registry: string;
|
|
5
|
+
}
|
|
6
|
+
export interface RegistryNotebook {
|
|
7
|
+
sources(): readonly RegistryEntry[];
|
|
8
|
+
remember(entries: readonly RegistryEntry[]): readonly string[];
|
|
9
|
+
}
|
|
10
|
+
export declare const REGISTRY_MARKER = "# dsh-workbench \u5199\u7684\uFF1A\u8FD9\u4E00\u884C\u7684\u5305\u53EA\u5728\u8FD9\u4E2A\u6E90\u4E0A\uFF08dsh \u5378\u8F7D\u6CA1\u6709\u6E90\u53C2\u6570\uFF0Cpnpm \u5F97\u95EE\u5F97\u5230\uFF09";
|
|
11
|
+
export declare function scopeOf(pkg: string): string | null;
|
|
12
|
+
export declare function normalizeRegistry(url: string): string;
|
|
13
|
+
export declare function sameRegistry(a: string | null | undefined, b: string | null | undefined): boolean;
|
|
14
|
+
export declare function sourcesFromLockfile(text: string): readonly RegistryEntry[];
|
|
15
|
+
export interface RegistryConfigMerge {
|
|
16
|
+
readonly text: string;
|
|
17
|
+
readonly added: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function mergeRegistryConfig(text: string, entries: readonly RegistryEntry[]): RegistryConfigMerge;
|
|
20
|
+
export declare function registryFailure(change: BundleChange): boolean;
|
|
21
|
+
export declare function createRegistryNotebook(dir: string | null): RegistryNotebook;
|
package/docs/OPERATIONS.md
CHANGED
|
@@ -103,6 +103,7 @@ WORKBENCH_PORT=3091 pnpm run dev # 换端口(监听与实例同一个端口
|
|
|
103
103
|
| API 凭据 | ❌ **有意共享** | `~/.dsh/.credentials.yaml`,两边同一把 key |
|
|
104
104
|
| opencli 运行时(CLI + 插件) | ✅ | `~/.dsh/workbench/opencli/`(`HOME` 指到 `…/home`,见 [ADR-0014](../../../docs/adr/0014-opencli-cost-has-one-owner.md) §2.2) |
|
|
105
105
|
| opencli **daemon** | ❌ **整机一个,隔离不了** | 端口 **19825 被扩展写死**(`background.js` 里 `DAEMON_PORT = 19825`;CLI 侧 `OPENCLI_DAEMON_PORT` 设非默认值直接报错)。所以本机的全局 opencli 与工作台的隔离运行时**抢同一个 daemon**:两边版本不一致时,谁的命令后跑谁就把 daemon 重启成自己那版 |
|
|
106
|
+
| profile 的 pnpm 源(私有 scope) | ⚠️ **由工作台写进去** | `<profile>/.npmrc` 里的 `@scope:registry=…`,前面带一行 `# dsh-workbench 写的…` 标记。**为什么在工作台这一侧写**:dsh 的卸载没有源参数(`runPnpm(['remove', name])`),pnpm 只能从 profile 的 `.npmrc` 链知道源;不写它,装私有源的模块能成、卸不了。规则与边界见 [ADR-0030](../../../docs/adr/0030-private-registries-live-in-the-profile-pnpm-config.md):只加不改、只写 scope 行、不碰 `~/.npmrc`。**删了会怎样**:下次从这个源装会再写回来;已经装着的那种,点卸载时撞 404 会自愈补回再重试一次 |
|
|
106
107
|
|
|
107
108
|
## 排障
|
|
108
109
|
|
|
@@ -113,6 +114,7 @@ WORKBENCH_PORT=3091 pnpm run dev # 换端口(监听与实例同一个端口
|
|
|
113
114
|
| 面板显示"这个项目不是 Coding 仓库" | 该工作区的 git `origin` 不指向 `e.coding.net`(或没有 origin) |
|
|
114
115
|
| 打开面板/按刷新要等 5–8 秒 | 正常:opencli 每次调用有**固定约 5 秒**开销(起浏览器会话;接口本身只要 ~260ms)。**没有缓存**——数据一律实时,列表 = 缺陷 + 状态目录两次调用(限并发 2,实测约 7 秒) |
|
|
115
116
|
| 改了源码没变化 | 忘了 `pnpm run build`,或没重启进程(宿主缓存已加载的包) |
|
|
117
|
+
| 市场页点「卸载」报 `没成功:… ERR_PNPM_FETCH_404 GET https://registry.npmjs.org/@你的私有 scope/…` 之类 | 这个 profile 里的私有包不在 pnpm 默认源上,而 dsh 的卸载**不带源**。工作台会自己补上 `<profile>/.npmrc` 的 `@scope:registry=` 再重试一次([ADR-0030](../../../docs/adr/0030-private-registries-live-in-the-profile-pnpm-config.md));**还失败**说明那个包没有 scope(一行 scope 行表达不了),这时才需要人/agent 上手:`dsh plugin --profile <p> remove '<包名>' --config.registry=<那个源>`(`pnpm remove` 不认 `--registry=`),或者给 profile 自己配一行默认 `registry=` |
|
|
116
118
|
| 体检那屏「检测浏览器通道 · 没连上」,可面板照样能用 | 本机全局 opencli 与隔离运行时版本不一致 ⇒ daemon 被顶成对方那版(`Stale daemon detected: daemon vX != CLI vY`)。下一条浏览器命令会自动把它重启回来,体检也会复检后改回「已连接」([ADR-0024](../../../docs/adr/0024-warm-the-sites-before-the-panel.md) §3.2.1)。**要彻底不抖**:让两边同版本 —— 把 `OPENCLI_PIN`(`src/shared/config/constants.ts`)对齐到 `opencli --version`,再 `npm i --prefix ~/.dsh/workbench/opencli/toolchain @jackwener/opencli@<那个版本> --cache ~/.dsh/workbench/opencli/npm-cache` |
|
|
117
119
|
| Settings 页报 `overridden by a home patch` | 想在 Settings 里改的行被 `$DSH_HOME/cordis.patch.yml` 或 `--patch` 覆盖了 |
|
|
118
120
|
| **别人机器上** `npx @dsh-workbench/core setup` 报 `scripts/seed-profile.sh: Permission denied`(或体检永远说"隔离运行时没装好") | 发出去的包里**随包脚本丢了 x 位**:`pnpm publish` 只给 `package.json#bin` 点名那条文件 755,其余一律 644(`npm pack` 会保留,而 `git` 里的 x 位不进 tarball —— 所以**本机永远复现不出来**)。0.1.6 的已知缺陷:应急 `chmod +x <包目录>/{scripts/seed-profile.sh,bin/opencli-isolated}`,正规解是升到 0.1.7(启动器与 `selfcheck` 已改成不吃 x 位) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-workbench/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "个人工作台:Agent 工作台外壳(左栏 + 常驻对话 + 自研右侧数据面板)。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"icon": "./icon.svg",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"access": "public"
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
|
-
"@dsh-workbench/shared": "0.1.
|
|
81
|
+
"@dsh-workbench/shared": "0.1.9"
|
|
82
82
|
},
|
|
83
83
|
"scripts": {
|
|
84
84
|
"build": "node scripts/build.mjs && node scripts/build-types.mjs",
|