@dsh-workbench/shared 0.1.3 → 0.1.4

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.
@@ -8,5 +8,6 @@ export type WriteOutcome<T> = {
8
8
  readonly ok: false;
9
9
  readonly message: string;
10
10
  readonly detail?: string;
11
+ readonly helpUrl?: string;
11
12
  };
12
13
  export declare function writeOutcomeOf<T>(response: ApiResponse<T> | null, networkText: string): WriteOutcome<T>;
@@ -11,7 +11,13 @@ export function writeOutcomeOf(response, networkText) {
11
11
  const own = typeof box.error?.message === 'string' && box.error.message !== '' ? box.error.message : undefined;
12
12
  const fallback = typeof box.text === 'string' && box.text !== '' ? box.text : networkText;
13
13
  const detail = typeof box.error?.detail === 'string' ? box.error.detail : undefined;
14
- return { ok: false, message: own ?? fallback, ...(detail === undefined ? {} : { detail }) };
14
+ const helpUrl = typeof box.error?.helpUrl === 'string' && box.error.helpUrl !== '' ? box.error.helpUrl : undefined;
15
+ return {
16
+ ok: false,
17
+ message: own ?? fallback,
18
+ ...(detail === undefined ? {} : { detail }),
19
+ ...(helpUrl === undefined ? {} : { helpUrl }),
20
+ };
15
21
  }
16
22
  return { ok: true, value: response };
17
23
  }
package/dist/host.d.ts CHANGED
@@ -4,6 +4,8 @@ export * from './api/unit.js';
4
4
  export * from './api/facts.js';
5
5
  export * from './api/long-task.js';
6
6
  export * from './lib/text.js';
7
+ export * from './lib/ui.js';
8
+ export * from './api/blocker-table.js';
7
9
  export * from './host/cli-error.js';
8
10
  export * from './host/data-root.js';
9
11
  export * from './host/facts.js';
package/dist/host.js CHANGED
@@ -4,6 +4,8 @@ export * from './api/unit.js';
4
4
  export * from './api/facts.js';
5
5
  export * from './api/long-task.js';
6
6
  export * from './lib/text.js';
7
+ export * from './lib/ui.js';
8
+ export * from './api/blocker-table.js';
7
9
  export * from './host/cli-error.js';
8
10
  export * from './host/data-root.js';
9
11
  export * from './host/facts.js';
package/dist/i18n/en.js CHANGED
@@ -78,7 +78,8 @@ export const en = {
78
78
  'panels.market.badSource': 'The install method is incomplete — install it yourself',
79
79
  'panels.market.empty': 'No modules available',
80
80
  'panels.market.installedSection': 'Installed',
81
- 'panels.market.moduleUpdate': 'Version {version} is out: it may need a restart after installing.',
81
+ 'panels.market.moduleOutdated': 'update available',
82
+ 'panels.market.moduleRestartHint': 'it may need a restart after installing',
82
83
  'panels.market.restartNeeded': 'The new version is installed — restart once to pick it up.',
83
84
  'panels.market.foot': 'After installing, enable it in the panel page of that project.',
84
85
  'panels.market.recheck': 'Check for updates',
@@ -175,11 +176,10 @@ export const en = {
175
176
  'panels.market.add.doneRestart': 'Installed — restart once to pick it up.',
176
177
  'panels.market.add.cancelled': 'Cancelled.',
177
178
  'panels.market.add.failed': "Didn't work: {reason}",
178
- 'panels.market.add.supplyInstalled': 'The plugins it needs are installed too.',
179
+ 'panels.market.add.removed': 'It has been removed.',
179
180
  'panels.market.add.supplyPending': 'Its plugins install after you restart.',
180
181
  'panels.market.add.supplyFailed': "Its plugins didn't install: {reason}",
181
182
  'panels.market.add.notModule': "This is not a workbench module (no dsh.workbench declaration), so it will not show up on the board.",
182
- 'panels.market.add.removed': 'Removed.',
183
183
  'panels.market.add.removedRestart': 'Removed — restart once to finish.',
184
184
  'panels.market.add.remove': 'Remove it',
185
185
  'panels.market.add.problem.invalidSpec': "That is not a spec we accept: it cannot be empty or start with a dash.",
@@ -80,7 +80,8 @@ export declare const dictionaries: {
80
80
  readonly 'panels.market.badSource': "安装方式没写全,只能自己动手";
81
81
  readonly 'panels.market.empty': "暂无可用模块";
82
82
  readonly 'panels.market.installedSection': "已装";
83
- readonly 'panels.market.moduleUpdate': "有新版 {version}:安装完成后可能需要重启才生效。";
83
+ readonly 'panels.market.moduleOutdated': "有新版";
84
+ readonly 'panels.market.moduleRestartHint': "安装完成后可能需要重启才生效";
84
85
  readonly 'panels.market.restartNeeded': "新版装好了,重启一次才生效。";
85
86
  readonly 'panels.market.foot': "装好后到那个项目的面板页勾选它,模块才会出现。";
86
87
  readonly 'panels.market.recheck': "重新检查更新";
@@ -177,11 +178,10 @@ export declare const dictionaries: {
177
178
  readonly 'panels.market.add.doneRestart': "装好了,重启一次才生效。";
178
179
  readonly 'panels.market.add.cancelled': "已取消。";
179
180
  readonly 'panels.market.add.failed': "没成功:{reason}";
180
- readonly 'panels.market.add.supplyInstalled': "它要的插件也装上了。";
181
+ readonly 'panels.market.add.removed': "已经移除了。";
181
182
  readonly 'panels.market.add.supplyPending': "它要的插件重启后再装。";
182
183
  readonly 'panels.market.add.supplyFailed': "它要的插件没装上:{reason}";
183
184
  readonly 'panels.market.add.notModule': "这不是工作台模块(没有 dsh.workbench 声明),不会出现在面板上。";
184
- readonly 'panels.market.add.removed': "已经移除了。";
185
185
  readonly 'panels.market.add.removedRestart': "卸掉了,重启一次才彻底生效。";
186
186
  readonly 'panels.market.add.remove': "移除它";
187
187
  readonly 'panels.market.add.problem.invalidSpec': "这个写法不认:不能是空的,也不能以横杠开头。";
@@ -287,7 +287,7 @@ export declare const dictionaries: {
287
287
  readonly 'panel.conversation': "对话";
288
288
  readonly 'panels.label': "全局面板";
289
289
  };
290
- en: Record<"time.now" | "time.minutes" | "time.hours" | "time.days" | "blocker.retry" | "blocker.copy" | "blocker.unknown.title" | "blocker.login.go" | "blocker.login.titleGeneric" | "blocker.login.title" | "blocker.login.manual" | "blocker.login.hint" | "blocker.forbidden.open" | "blocker.forbidden.titleGeneric" | "blocker.forbidden.title" | "blocker.forbidden.hint" | "blocker.timeout.hint" | "blocker.exec.hint" | "blocker.fix.install" | "blocker.fix.update" | "blocker.market.open" | "env.unit.missingPlugin" | "env.unit.hint" | "env.unit.missingCommands" | "env.unit.missingCommandsHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "session.new" | "session.new.label" | "session.empty" | "session.noProject" | "session.pinned" | "session.actions" | "status.idle" | "status.running" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "panels.title" | "panels.reset" | "panels.enabled" | "panels.disabled" | "panels.choose" | "panels.failed" | "panels.hintEffect" | "panels.dragHint" | "panels.unknownStep" | "panels.labelWithHint" | "panels.dep.missingPlugin" | "panels.dep.missingCommands" | "panels.dep.unchecked" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.outdated" | "panels.market.hasNew" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.checking" | "panels.market.sectionInstalled" | "panels.market.sectionPending" | "panels.market.sectionShared" | "panels.market.sharedUsedBy" | "panels.market.listSeparator" | "panels.market.sharedMissing" | "panels.market.sharedOutdated" | "panels.market.sharedUnsatisfied" | "panels.market.sharedOk" | "panels.market.versionArrow" | "panels.market.lead" | "panels.market.install" | "panels.market.update" | "panels.market.uninstall" | "panels.market.uninstallLabel" | "panels.market.installing" | "panels.market.updating" | "panels.market.uninstalling" | "panels.market.confirmUninstallTitle" | "panels.market.confirmUninstallDetail" | "panels.market.confirmUninstallAck" | "panels.market.confirmYes" | "panels.market.confirmNo" | "panels.market.failed" | "panels.market.needEnv" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.installedSection" | "panels.market.moduleUpdate" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.recheck" | "panels.market.checkUpdates" | "panels.market.checkedAt" | "panels.market.justNow" | "panels.market.minutesAgo" | "panels.market.hoursAgo" | "panels.market.add.description" | "panels.market.add.specPlaceholder" | "panels.market.add.guideToggle" | "panels.market.add.guideHide" | "panels.market.add.guideIdTitle" | "panels.market.add.guideIdExample" | "panels.market.add.guideIdHint" | "panels.market.add.guideGitTitle" | "panels.market.add.guideGitExample" | "panels.market.add.guideGitHint" | "panels.market.add.guidePathTitle" | "panels.market.add.guidePathExample" | "panels.market.add.guidePathHint" | "panels.market.add.guideExampleLabel" | "panels.market.add.guideFill" | "panels.market.add.guideSafety" | "panels.market.add.registryLegend" | "panels.market.add.registryOfficial" | "panels.market.add.registryMirror" | "panels.market.add.registryWithHost" | "panels.market.add.registryToggle" | "panels.market.add.installVersion" | "panels.market.add.registryDefault" | "panels.market.add.registryCustom" | "panels.market.add.registryCustomPlaceholder" | "panels.market.add.registryCustomHint" | "panels.market.add.registryCustomInvalid" | "panels.market.add.run" | "panels.market.add.edit" | "panels.market.add.changeRegistry" | "panels.market.add.installingTitle" | "panels.market.add.installedTitle" | "panels.market.add.failedTitle" | "panels.market.add.cancelledTitle" | "panels.market.add.failureNetworkHost" | "panels.market.add.problemInvalid" | "panels.market.add.problemInstalled" | "panels.market.add.problemNotFound" | "panels.market.add.problemNotPackage" | "panels.market.add.problemNotBundle" | "panels.market.add.problemNetwork" | "panels.market.add.problemUnknown" | "panels.market.add.failureNetwork" | "panels.market.add.failureNotFound" | "panels.market.add.failureNoMatchingVersion" | "panels.market.add.failureDiskFull" | "panels.market.add.failurePermission" | "panels.market.add.failureBuildBlocked" | "panels.market.add.failureIntegrity" | "panels.market.add.failureTimeout" | "panels.market.add.failurePnpmMissing" | "panels.market.add.failureGeneric" | "panels.market.add.approveTitle" | "panels.market.add.approveCaution" | "panels.market.add.approveRun" | "panels.market.add.restart" | "panels.market.add.tookEffect" | "panels.market.add.details" | "panels.market.add.open" | "panels.market.add.title" | "panels.market.add.intro" | "panels.market.add.specLabel" | "panels.market.add.specHint" | "panels.market.add.exampleTitle" | "panels.market.add.exampleFill" | "panels.market.add.registryLabel" | "panels.market.add.registryProfile" | "panels.market.add.registryPnpm" | "panels.market.add.check" | "panels.market.add.checking" | "panels.market.add.change" | "panels.market.add.previewTitle" | "panels.market.add.fieldName" | "panels.market.add.fieldVersion" | "panels.market.add.fieldDescription" | "panels.market.add.fieldSource" | "panels.market.add.install" | "panels.market.add.installing" | "panels.market.add.cancel" | "panels.market.add.close" | "panels.market.add.retry" | "panels.market.add.changeSource" | "panels.market.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.cancelled" | "panels.market.add.failed" | "panels.market.add.supplyInstalled" | "panels.market.add.supplyPending" | "panels.market.add.supplyFailed" | "panels.market.add.notModule" | "panels.market.add.removed" | "panels.market.add.removedRestart" | "panels.market.add.remove" | "panels.market.add.problem.invalidSpec" | "panels.market.add.problem.alreadyInstalled" | "panels.market.add.problem.notFound" | "panels.market.add.problem.notAPackage" | "panels.market.add.problem.notABundle" | "panels.market.add.problem.network" | "panels.market.add.problem.unknown" | "panels.market.add.reason.invalidSpec" | "panels.market.add.reason.incompatible" | "panels.market.add.reason.notBundle" | "panels.market.add.reason.notRemovable" | "panels.market.add.reason.bundleInUse" | "panels.market.add.reason.stopProfile" | "panels.market.add.reason.staleApproval" | "panels.market.add.reason.operationError" | "panels.market.add.reason.buildBlocked" | "panels.market.add.reason.pnpmMissing" | "panels.market.add.reason.noMatchingVersion" | "panels.market.add.reason.diskFull" | "panels.market.add.reason.permission" | "panels.market.add.reason.integrity" | "panels.market.add.reason.timeout" | "panels.market.add.reason.network" | "panels.market.add.reason.notFound" | "panels.market.add.reason.unknown" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.empty" | "panels.emptyHint" | "env.title" | "env.checking" | "env.installing" | "env.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.daemon" | "env.bridge.extension" | "env.bridge.extensionLink" | "env.bridge.profile" | "env.bridge.stale" | "env.bridge.unknown" | "env.fix.title" | "env.fix.why" | "env.fix.whyPath" | "env.fix.whyShell" | "env.fix.step" | "env.fix.stepPath" | "env.fix.stepShell" | "env.fix.permission" | "env.fix.network" | "env.fix.details" | "env.retry" | "env.copyCommand" | "env.copied" | "env.step.opencli" | "env.step.codingPlugin" | "env.step.bridge" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "coding.notARepo.title" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label", string>;
290
+ en: Record<"time.now" | "time.minutes" | "time.hours" | "time.days" | "blocker.retry" | "blocker.copy" | "blocker.unknown.title" | "blocker.login.go" | "blocker.login.titleGeneric" | "blocker.login.title" | "blocker.login.manual" | "blocker.login.hint" | "blocker.forbidden.open" | "blocker.forbidden.titleGeneric" | "blocker.forbidden.title" | "blocker.forbidden.hint" | "blocker.timeout.hint" | "blocker.exec.hint" | "blocker.fix.install" | "blocker.fix.update" | "blocker.market.open" | "env.unit.missingPlugin" | "env.unit.hint" | "env.unit.missingCommands" | "env.unit.missingCommandsHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "session.new" | "session.new.label" | "session.empty" | "session.noProject" | "session.pinned" | "session.actions" | "status.idle" | "status.running" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "panels.title" | "panels.reset" | "panels.enabled" | "panels.disabled" | "panels.choose" | "panels.failed" | "panels.hintEffect" | "panels.dragHint" | "panels.unknownStep" | "panels.labelWithHint" | "panels.dep.missingPlugin" | "panels.dep.missingCommands" | "panels.dep.unchecked" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.outdated" | "panels.market.hasNew" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.checking" | "panels.market.sectionInstalled" | "panels.market.sectionPending" | "panels.market.sectionShared" | "panels.market.sharedUsedBy" | "panels.market.listSeparator" | "panels.market.sharedMissing" | "panels.market.sharedOutdated" | "panels.market.sharedUnsatisfied" | "panels.market.sharedOk" | "panels.market.versionArrow" | "panels.market.lead" | "panels.market.install" | "panels.market.update" | "panels.market.uninstall" | "panels.market.uninstallLabel" | "panels.market.installing" | "panels.market.updating" | "panels.market.uninstalling" | "panels.market.confirmUninstallTitle" | "panels.market.confirmUninstallDetail" | "panels.market.confirmUninstallAck" | "panels.market.confirmYes" | "panels.market.confirmNo" | "panels.market.failed" | "panels.market.needEnv" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.installedSection" | "panels.market.moduleOutdated" | "panels.market.moduleRestartHint" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.recheck" | "panels.market.checkUpdates" | "panels.market.checkedAt" | "panels.market.justNow" | "panels.market.minutesAgo" | "panels.market.hoursAgo" | "panels.market.add.description" | "panels.market.add.specPlaceholder" | "panels.market.add.guideToggle" | "panels.market.add.guideHide" | "panels.market.add.guideIdTitle" | "panels.market.add.guideIdExample" | "panels.market.add.guideIdHint" | "panels.market.add.guideGitTitle" | "panels.market.add.guideGitExample" | "panels.market.add.guideGitHint" | "panels.market.add.guidePathTitle" | "panels.market.add.guidePathExample" | "panels.market.add.guidePathHint" | "panels.market.add.guideExampleLabel" | "panels.market.add.guideFill" | "panels.market.add.guideSafety" | "panels.market.add.registryLegend" | "panels.market.add.registryOfficial" | "panels.market.add.registryMirror" | "panels.market.add.registryWithHost" | "panels.market.add.registryToggle" | "panels.market.add.installVersion" | "panels.market.add.registryDefault" | "panels.market.add.registryCustom" | "panels.market.add.registryCustomPlaceholder" | "panels.market.add.registryCustomHint" | "panels.market.add.registryCustomInvalid" | "panels.market.add.run" | "panels.market.add.edit" | "panels.market.add.changeRegistry" | "panels.market.add.installingTitle" | "panels.market.add.installedTitle" | "panels.market.add.failedTitle" | "panels.market.add.cancelledTitle" | "panels.market.add.failureNetworkHost" | "panels.market.add.problemInvalid" | "panels.market.add.problemInstalled" | "panels.market.add.problemNotFound" | "panels.market.add.problemNotPackage" | "panels.market.add.problemNotBundle" | "panels.market.add.problemNetwork" | "panels.market.add.problemUnknown" | "panels.market.add.failureNetwork" | "panels.market.add.failureNotFound" | "panels.market.add.failureNoMatchingVersion" | "panels.market.add.failureDiskFull" | "panels.market.add.failurePermission" | "panels.market.add.failureBuildBlocked" | "panels.market.add.failureIntegrity" | "panels.market.add.failureTimeout" | "panels.market.add.failurePnpmMissing" | "panels.market.add.failureGeneric" | "panels.market.add.approveTitle" | "panels.market.add.approveCaution" | "panels.market.add.approveRun" | "panels.market.add.restart" | "panels.market.add.tookEffect" | "panels.market.add.details" | "panels.market.add.open" | "panels.market.add.title" | "panels.market.add.intro" | "panels.market.add.specLabel" | "panels.market.add.specHint" | "panels.market.add.exampleTitle" | "panels.market.add.exampleFill" | "panels.market.add.registryLabel" | "panels.market.add.registryProfile" | "panels.market.add.registryPnpm" | "panels.market.add.check" | "panels.market.add.checking" | "panels.market.add.change" | "panels.market.add.previewTitle" | "panels.market.add.fieldName" | "panels.market.add.fieldVersion" | "panels.market.add.fieldDescription" | "panels.market.add.fieldSource" | "panels.market.add.install" | "panels.market.add.installing" | "panels.market.add.cancel" | "panels.market.add.close" | "panels.market.add.retry" | "panels.market.add.changeSource" | "panels.market.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.cancelled" | "panels.market.add.failed" | "panels.market.add.removed" | "panels.market.add.supplyPending" | "panels.market.add.supplyFailed" | "panels.market.add.notModule" | "panels.market.add.removedRestart" | "panels.market.add.remove" | "panels.market.add.problem.invalidSpec" | "panels.market.add.problem.alreadyInstalled" | "panels.market.add.problem.notFound" | "panels.market.add.problem.notAPackage" | "panels.market.add.problem.notABundle" | "panels.market.add.problem.network" | "panels.market.add.problem.unknown" | "panels.market.add.reason.invalidSpec" | "panels.market.add.reason.incompatible" | "panels.market.add.reason.notBundle" | "panels.market.add.reason.notRemovable" | "panels.market.add.reason.bundleInUse" | "panels.market.add.reason.stopProfile" | "panels.market.add.reason.staleApproval" | "panels.market.add.reason.operationError" | "panels.market.add.reason.buildBlocked" | "panels.market.add.reason.pnpmMissing" | "panels.market.add.reason.noMatchingVersion" | "panels.market.add.reason.diskFull" | "panels.market.add.reason.permission" | "panels.market.add.reason.integrity" | "panels.market.add.reason.timeout" | "panels.market.add.reason.network" | "panels.market.add.reason.notFound" | "panels.market.add.reason.unknown" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.empty" | "panels.emptyHint" | "env.title" | "env.checking" | "env.installing" | "env.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.daemon" | "env.bridge.extension" | "env.bridge.extensionLink" | "env.bridge.profile" | "env.bridge.stale" | "env.bridge.unknown" | "env.fix.title" | "env.fix.why" | "env.fix.whyPath" | "env.fix.whyShell" | "env.fix.step" | "env.fix.stepPath" | "env.fix.stepShell" | "env.fix.permission" | "env.fix.network" | "env.fix.details" | "env.retry" | "env.copyCommand" | "env.copied" | "env.step.opencli" | "env.step.codingPlugin" | "env.step.bridge" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "coding.notARepo.title" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label", string>;
291
291
  };
292
292
  export type { WorkbenchMessages };
293
293
  export interface Dictionaries {
package/dist/i18n/zh.d.ts CHANGED
@@ -78,7 +78,8 @@ export declare const zh: {
78
78
  readonly 'panels.market.badSource': "安装方式没写全,只能自己动手";
79
79
  readonly 'panels.market.empty': "暂无可用模块";
80
80
  readonly 'panels.market.installedSection': "已装";
81
- readonly 'panels.market.moduleUpdate': "有新版 {version}:安装完成后可能需要重启才生效。";
81
+ readonly 'panels.market.moduleOutdated': "有新版";
82
+ readonly 'panels.market.moduleRestartHint': "安装完成后可能需要重启才生效";
82
83
  readonly 'panels.market.restartNeeded': "新版装好了,重启一次才生效。";
83
84
  readonly 'panels.market.foot': "装好后到那个项目的面板页勾选它,模块才会出现。";
84
85
  readonly 'panels.market.recheck': "重新检查更新";
@@ -175,11 +176,10 @@ export declare const zh: {
175
176
  readonly 'panels.market.add.doneRestart': "装好了,重启一次才生效。";
176
177
  readonly 'panels.market.add.cancelled': "已取消。";
177
178
  readonly 'panels.market.add.failed': "没成功:{reason}";
178
- readonly 'panels.market.add.supplyInstalled': "它要的插件也装上了。";
179
+ readonly 'panels.market.add.removed': "已经移除了。";
179
180
  readonly 'panels.market.add.supplyPending': "它要的插件重启后再装。";
180
181
  readonly 'panels.market.add.supplyFailed': "它要的插件没装上:{reason}";
181
182
  readonly 'panels.market.add.notModule': "这不是工作台模块(没有 dsh.workbench 声明),不会出现在面板上。";
182
- readonly 'panels.market.add.removed': "已经移除了。";
183
183
  readonly 'panels.market.add.removedRestart': "卸掉了,重启一次才彻底生效。";
184
184
  readonly 'panels.market.add.remove': "移除它";
185
185
  readonly 'panels.market.add.problem.invalidSpec': "这个写法不认:不能是空的,也不能以横杠开头。";
package/dist/i18n/zh.js CHANGED
@@ -78,7 +78,8 @@ export const zh = {
78
78
  'panels.market.badSource': '安装方式没写全,只能自己动手',
79
79
  'panels.market.empty': '暂无可用模块',
80
80
  'panels.market.installedSection': '已装',
81
- 'panels.market.moduleUpdate': '有新版 {version}:安装完成后可能需要重启才生效。',
81
+ 'panels.market.moduleOutdated': '有新版',
82
+ 'panels.market.moduleRestartHint': '安装完成后可能需要重启才生效',
82
83
  'panels.market.restartNeeded': '新版装好了,重启一次才生效。',
83
84
  'panels.market.foot': '装好后到那个项目的面板页勾选它,模块才会出现。',
84
85
  'panels.market.recheck': '重新检查更新',
@@ -175,11 +176,10 @@ export const zh = {
175
176
  'panels.market.add.doneRestart': '装好了,重启一次才生效。',
176
177
  'panels.market.add.cancelled': '已取消。',
177
178
  'panels.market.add.failed': '没成功:{reason}',
178
- 'panels.market.add.supplyInstalled': '它要的插件也装上了。',
179
+ 'panels.market.add.removed': '已经移除了。',
179
180
  'panels.market.add.supplyPending': '它要的插件重启后再装。',
180
181
  'panels.market.add.supplyFailed': '它要的插件没装上:{reason}',
181
182
  'panels.market.add.notModule': '这不是工作台模块(没有 dsh.workbench 声明),不会出现在面板上。',
182
- 'panels.market.add.removed': '已经移除了。',
183
183
  'panels.market.add.removedRestart': '卸掉了,重启一次才彻底生效。',
184
184
  'panels.market.add.remove': '移除它',
185
185
  'panels.market.add.problem.invalidSpec': '这个写法不认:不能是空的,也不能以横杠开头。',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-workbench/shared",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "工作台与模块共享的纯代码与契约类型:类型、纯逻辑、哑组件、平台解析。宿主侧的东西从 /host 进(不影响浏览器产物)。",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -33,6 +33,26 @@ describe('writeOutcomeOf', () => {
33
33
  expect(outcome).toEqual({ ok: false, message: '生产环境要先审批', detail: 'job 1234' });
34
34
  });
35
35
 
36
+ it('★ 登录态失效那条错误带着 helpUrl → 一路带出去(卡片才能给「去登录 ↗」而不是"还没绑定")', () => {
37
+ const outcome = writeOutcomeOf(
38
+ {
39
+ ok: false,
40
+ error: {
41
+ code: 'cmdb/login-required',
42
+ message: 'CMDB 登录态失效了',
43
+ helpUrl: 'https://cmdb.example.test/login',
44
+ },
45
+ },
46
+ '网络不通',
47
+ );
48
+
49
+ expect(outcome).toEqual({
50
+ ok: false,
51
+ message: 'CMDB 登录态失效了',
52
+ helpUrl: 'https://cmdb.example.test/login',
53
+ });
54
+ });
55
+
36
56
  it('没有 detail 就不给那个字段(别塞一个 undefined 进类型里)', () => {
37
57
  const outcome = writeOutcomeOf({ ok: false, error: { code: 'x', message: '不行' } }, '网络不通');
38
58
 
@@ -9,19 +9,33 @@ export function writeRoute(channel: WriteChannel, resource: string): string {
9
9
 
10
10
  export type WriteOutcome<T> =
11
11
  | { readonly ok: true; readonly value: T }
12
- | { readonly ok: false; readonly message: string; readonly detail?: string };
12
+ | {
13
+ readonly ok: false;
14
+ readonly message: string;
15
+ readonly detail?: string;
16
+ readonly helpUrl?: string;
17
+ };
13
18
 
14
19
  export function writeOutcomeOf<T>(response: ApiResponse<T> | null, networkText: string): WriteOutcome<T> {
15
20
  if (response === null) return { ok: false, message: networkText };
16
21
  if (!response.ok) {
17
22
  const box = response as {
18
- readonly error?: { readonly message?: unknown; readonly detail?: unknown } | undefined;
23
+ readonly error?:
24
+ | { readonly message?: unknown; readonly detail?: unknown; readonly helpUrl?: unknown }
25
+ | undefined;
19
26
  readonly text?: unknown;
20
27
  };
21
28
  const own = typeof box.error?.message === 'string' && box.error.message !== '' ? box.error.message : undefined;
22
29
  const fallback = typeof box.text === 'string' && box.text !== '' ? box.text : networkText;
23
30
  const detail = typeof box.error?.detail === 'string' ? box.error.detail : undefined;
24
- return { ok: false, message: own ?? fallback, ...(detail === undefined ? {} : { detail }) };
31
+ const helpUrl =
32
+ typeof box.error?.helpUrl === 'string' && box.error.helpUrl !== '' ? box.error.helpUrl : undefined;
33
+ return {
34
+ ok: false,
35
+ message: own ?? fallback,
36
+ ...(detail === undefined ? {} : { detail }),
37
+ ...(helpUrl === undefined ? {} : { helpUrl }),
38
+ };
25
39
  }
26
40
  return { ok: true, value: response };
27
41
  }
package/src/host.ts CHANGED
@@ -4,6 +4,8 @@ export * from './api/unit.js';
4
4
  export * from './api/facts.js';
5
5
  export * from './api/long-task.js';
6
6
  export * from './lib/text.js';
7
+ export * from './lib/ui.js';
8
+ export * from './api/blocker-table.js';
7
9
  export * from './host/cli-error.js';
8
10
  export * from './host/data-root.js';
9
11
  export * from './host/facts.js';
package/src/i18n/en.ts CHANGED
@@ -85,7 +85,8 @@ export const en: Record<keyof WorkbenchMessages, string> = {
85
85
  'panels.market.badSource': 'The install method is incomplete — install it yourself',
86
86
  'panels.market.empty': 'No modules available',
87
87
  'panels.market.installedSection': 'Installed',
88
- 'panels.market.moduleUpdate': 'Version {version} is out: it may need a restart after installing.',
88
+ 'panels.market.moduleOutdated': 'update available',
89
+ 'panels.market.moduleRestartHint': 'it may need a restart after installing',
89
90
  'panels.market.restartNeeded': 'The new version is installed — restart once to pick it up.',
90
91
  'panels.market.foot': 'After installing, enable it in the panel page of that project.',
91
92
  'panels.market.recheck': 'Check for updates',
@@ -182,11 +183,10 @@ export const en: Record<keyof WorkbenchMessages, string> = {
182
183
  'panels.market.add.doneRestart': 'Installed — restart once to pick it up.',
183
184
  'panels.market.add.cancelled': 'Cancelled.',
184
185
  'panels.market.add.failed': "Didn't work: {reason}",
185
- 'panels.market.add.supplyInstalled': 'The plugins it needs are installed too.',
186
+ 'panels.market.add.removed': 'It has been removed.',
186
187
  'panels.market.add.supplyPending': 'Its plugins install after you restart.',
187
188
  'panels.market.add.supplyFailed': "Its plugins didn't install: {reason}",
188
189
  'panels.market.add.notModule': "This is not a workbench module (no dsh.workbench declaration), so it will not show up on the board.",
189
- 'panels.market.add.removed': 'Removed.',
190
190
  'panels.market.add.removedRestart': 'Removed — restart once to finish.',
191
191
  'panels.market.add.remove': 'Remove it',
192
192
  'panels.market.add.problem.invalidSpec': "That is not a spec we accept: it cannot be empty or start with a dash.",
package/src/i18n/zh.ts CHANGED
@@ -81,7 +81,8 @@ export const zh = {
81
81
  'panels.market.badSource': '安装方式没写全,只能自己动手',
82
82
  'panels.market.empty': '暂无可用模块',
83
83
  'panels.market.installedSection': '已装',
84
- 'panels.market.moduleUpdate': '有新版 {version}:安装完成后可能需要重启才生效。',
84
+ 'panels.market.moduleOutdated': '有新版',
85
+ 'panels.market.moduleRestartHint': '安装完成后可能需要重启才生效',
85
86
  'panels.market.restartNeeded': '新版装好了,重启一次才生效。',
86
87
  'panels.market.foot': '装好后到那个项目的面板页勾选它,模块才会出现。',
87
88
  'panels.market.recheck': '重新检查更新',
@@ -178,11 +179,10 @@ export const zh = {
178
179
  'panels.market.add.doneRestart': '装好了,重启一次才生效。',
179
180
  'panels.market.add.cancelled': '已取消。',
180
181
  'panels.market.add.failed': '没成功:{reason}',
181
- 'panels.market.add.supplyInstalled': '它要的插件也装上了。',
182
+ 'panels.market.add.removed': '已经移除了。',
182
183
  'panels.market.add.supplyPending': '它要的插件重启后再装。',
183
184
  'panels.market.add.supplyFailed': '它要的插件没装上:{reason}',
184
185
  'panels.market.add.notModule': '这不是工作台模块(没有 dsh.workbench 声明),不会出现在面板上。',
185
- 'panels.market.add.removed': '已经移除了。',
186
186
  'panels.market.add.removedRestart': '卸掉了,重启一次才彻底生效。',
187
187
  'panels.market.add.remove': '移除它',
188
188
  'panels.market.add.problem.invalidSpec': '这个写法不认:不能是空的,也不能以横杠开头。',