@dsh-workbench/shared 1.1.12 → 1.1.14-beta.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.
Files changed (94) hide show
  1. package/README.md +6 -4
  2. package/dist/api/dsh.d.ts +2 -0
  3. package/dist/config/constants.d.ts +2 -0
  4. package/dist/config/constants.js +2 -0
  5. package/dist/contract/command.d.ts +2 -0
  6. package/dist/contract/unit-declaration.js +3 -2
  7. package/dist/host/data-root.js +5 -3
  8. package/dist/host/flow/step.d.ts +11 -0
  9. package/dist/host/flow/step.js +21 -0
  10. package/dist/host/host-kit.d.ts +7 -2
  11. package/dist/host/host-kit.js +4 -1
  12. package/dist/host/install-failure.js +1 -1
  13. package/dist/host/lib-install.d.ts +1 -0
  14. package/dist/host/lib-install.js +4 -3
  15. package/dist/host/paths.js +8 -7
  16. package/dist/host/payload.d.ts +12 -0
  17. package/dist/host/payload.js +16 -0
  18. package/dist/host/preflight.d.ts +4 -2
  19. package/dist/host/shell-text.d.ts +11 -1
  20. package/dist/host/shell-text.js +11 -3
  21. package/dist/host/shell.d.ts +2 -0
  22. package/dist/host/shell.js +41 -11
  23. package/dist/host/tool-approval.d.ts +20 -0
  24. package/dist/host/tool-approval.js +20 -0
  25. package/dist/host/unit-face.d.ts +5 -0
  26. package/dist/host/unit-plugin.d.ts +33 -0
  27. package/dist/host/unit-plugin.js +25 -0
  28. package/dist/host/workspace-store.js +12 -6
  29. package/dist/host.d.ts +3 -0
  30. package/dist/host.js +3 -0
  31. package/dist/i18n/en.js +4 -0
  32. package/dist/i18n/index.d.ts +5 -1
  33. package/dist/i18n/zh.d.ts +4 -0
  34. package/dist/i18n/zh.js +4 -0
  35. package/dist/lib/board-fact.d.ts +2 -1
  36. package/dist/lib/board-fact.js +10 -4
  37. package/dist/lib/ui.d.ts +8 -1
  38. package/dist/lib/ui.js +21 -3
  39. package/dist/lib/unit-plugin.d.ts +28 -0
  40. package/dist/lib/unit-plugin.js +23 -0
  41. package/dist/testing/host-fakes.d.ts +2 -0
  42. package/dist/testing/host-fakes.js +1 -1
  43. package/package.json +2 -2
  44. package/src/api/dsh.ts +2 -0
  45. package/src/components/__tests__/long-task-row.test.ts +1 -1
  46. package/src/config/constants.ts +3 -0
  47. package/src/contract/command.ts +2 -0
  48. package/src/contract/unit-declaration.ts +3 -2
  49. package/src/host/__tests__/data-root.test.ts +47 -0
  50. package/src/host/__tests__/plugin-helpers.test.ts +68 -0
  51. package/src/host/__tests__/runtime-layout.test.ts +5 -4
  52. package/src/host/__tests__/shell-text.test.ts +32 -7
  53. package/src/host/__tests__/shell.test.ts +94 -0
  54. package/src/host/data-root.ts +6 -3
  55. package/src/host/flow/__tests__/step.test.ts +43 -0
  56. package/src/host/flow/step.ts +21 -0
  57. package/src/host/host-kit.ts +11 -3
  58. package/src/host/install-failure.ts +1 -1
  59. package/src/host/lib-install.ts +5 -3
  60. package/src/host/paths.ts +8 -7
  61. package/src/host/payload.ts +17 -0
  62. package/src/host/preflight.ts +4 -2
  63. package/src/host/shell-text.ts +16 -2
  64. package/src/host/shell.ts +52 -12
  65. package/src/host/tool-approval.ts +31 -0
  66. package/src/host/unit-face.ts +5 -0
  67. package/src/host/unit-plugin.ts +49 -0
  68. package/src/host/workspace-store.ts +13 -6
  69. package/src/host.ts +3 -0
  70. package/src/i18n/en.ts +4 -0
  71. package/src/i18n/zh.ts +4 -0
  72. package/src/lib/__tests__/board-fact.test.ts +8 -0
  73. package/src/lib/__tests__/ui.test.ts +26 -0
  74. package/src/lib/board-fact.ts +11 -4
  75. package/src/lib/ui.ts +21 -3
  76. package/src/testing/host-fakes.ts +3 -1
  77. package/dist/components/SelectFieldWheel.d.ts +0 -9
  78. package/dist/components/SelectFieldWheel.js +0 -35
  79. package/dist/host/channel-plugin.d.ts +0 -15
  80. package/dist/host/channel-plugin.js +0 -42
  81. package/dist/host/command-name.d.ts +0 -1
  82. package/dist/host/command-name.js +0 -14
  83. package/dist/host/opencli-runner.d.ts +0 -26
  84. package/dist/host/opencli-runner.js +0 -50
  85. package/dist/host/plugin-source.d.ts +0 -33
  86. package/dist/host/plugin-source.js +0 -91
  87. package/dist/host/runner.d.ts +0 -26
  88. package/dist/host/runner.js +0 -50
  89. package/dist/host/runtime-links.d.ts +0 -7
  90. package/dist/host/runtime-links.js +0 -25
  91. package/dist/lib/version.d.ts +0 -4
  92. package/dist/lib/version.js +0 -21
  93. package/dist/testing/git.d.ts +0 -3
  94. package/dist/testing/git.js +0 -36
package/dist/host.js CHANGED
@@ -47,13 +47,16 @@ export * from './host/flow/expr.js';
47
47
  export * from './host/flow/check.js';
48
48
  export * from './host/flow/run.js';
49
49
  export * from './host/flow/kit.js';
50
+ export * from './host/flow/step.js';
50
51
  export * from './host/host-kit.js';
51
52
  export * from './host/panel-state.js';
53
+ export * from './host/payload.js';
52
54
  export * from './host/plugin-ledger.js';
53
55
  export * from './host/time.js';
54
56
  export * from './host/tokens.js';
55
57
  export * from './host/tool-approval.js';
56
58
  export * from './host/tool-kit.js';
59
+ export * from './host/unit-plugin.js';
57
60
  export * from './host/unit-face.js';
58
61
  export * from './host/lib-runners.js';
59
62
  export * from './host/value-handoff.js';
package/dist/i18n/en.js CHANGED
@@ -589,6 +589,7 @@ export const en = {
589
589
  'env.stepFailed.install': 'install failed',
590
590
  'env.stepFailed.path': 'installed but not found',
591
591
  'env.stepFailed.shell': 'cannot reach the command line',
592
+ 'env.stepFailed.host': 'the command never returned',
592
593
  'env.toolchain.ok': 'Looks good',
593
594
  'env.toolchain.warn': 'Almost ready',
594
595
  'env.runtime.ok': 'Ready',
@@ -601,12 +602,15 @@ export const en = {
601
602
  'env.fix.why': 'The workbench uses its own background tool (installed separately from the one in your terminal), and it is not set up on this machine yet.',
602
603
  'env.fix.whyPath': 'The background tool is installed, but this environment cannot find it \u2014 usually a PATH or shell-session issue.',
603
604
  'env.fix.whyShell': 'The workbench cannot reach the command line on this machine, so it cannot fetch data \u2014 you cannot install this from here; someone needs to fix the background environment.',
605
+ 'env.fix.whyHost': 'The workbench runs a few checks on the command line and collects what they return; this time the command went out and nothing came back. The tools themselves are most likely fine \u2014 reinstalling Node / npm / pnpm will not help.',
604
606
  'env.fix.step': 'Run this in a terminal, then hit Retry:',
605
607
  'env.fix.stepPath': 'Open a new terminal window (or make sure npm\u2019s global bin directory is on PATH), then hit Retry.',
606
608
  'env.fix.stepShell': 'Restart the workbench (or dsh); if it keeps happening, the workbench still cannot reach the command line.',
609
+ 'env.fix.stepHost': 'Quit the workbench completely (including the tray icon), clear the dsh-* leftovers in the system temp folder, then open it again. If it keeps happening, update dsh.',
607
610
  'env.fix.permission': 'Permission denied: rerun with sudo, or point npm\u2019s global directory at your home.',
608
611
  'env.fix.network': 'Network unreachable: check your network or proxy, then retry.',
609
612
  'env.fix.details': 'Details (for troubleshooting)',
613
+ 'env.log': 'Detailed output',
610
614
  'env.retry': 'Retry',
611
615
  'env.wake': 'Open browser',
612
616
  'env.wake.opening': 'Opening the browser…',
@@ -599,6 +599,7 @@ export declare const dictionaries: {
599
599
  readonly 'env.stepFailed.install': "装不上";
600
600
  readonly 'env.stepFailed.path': "装了但还找不到";
601
601
  readonly 'env.stepFailed.shell': "连不上命令行";
602
+ readonly 'env.stepFailed.host': "命令行没有返回";
602
603
  readonly 'env.toolchain.ok': "正常";
603
604
  readonly 'env.toolchain.warn': "还没完全准备好";
604
605
  readonly 'env.runtime.ok': "已就绪";
@@ -611,12 +612,15 @@ export declare const dictionaries: {
611
612
  readonly 'env.fix.why': "工作台用它自己那份后台工具(与你在终端里那套分开装,互不影响),这台机器上还没装好它。";
612
613
  readonly 'env.fix.whyPath': "后台工具装上了,但当前环境还找不到它 —— 通常是 PATH 或终端会话的问题。";
613
614
  readonly 'env.fix.whyShell': "工作台拿不到这台机器的命令行,所以取不了数据 —— 这一步你装不了,需要有人处理后台环境。";
615
+ readonly 'env.fix.whyHost': "工作台要靠命令行跑几条检查,再把结果收回来;这次命令发出去了,结果一直没回来。工具本身多半是好的 —— 重装 Node / npm / pnpm 不会有帮助。";
614
616
  readonly 'env.fix.step': "在终端里运行下面这条命令,装好之后点「重试」:";
615
617
  readonly 'env.fix.stepPath': "新开一个终端窗口(或确认 npm 的全局 bin 目录在 PATH 里),然后点「重试」。";
616
618
  readonly 'env.fix.stepShell': "重启一次工作台(或 dsh);如果反复出现,说明工作台还是拿不到命令行。";
619
+ readonly 'env.fix.stepHost': "完全退出工作台(托盘图标也要退),清掉系统临时目录里 dsh- 开头的残留,再重新打开;反复出现就升级 dsh。";
617
620
  readonly 'env.fix.permission': "权限不够:在命令前加 sudo 重跑,或先把 npm 的全局目录配到你的用户目录。";
618
621
  readonly 'env.fix.network': "网络不通:检查网络或代理设置后重试。";
619
622
  readonly 'env.fix.details': "详细输出(排障用)";
623
+ readonly 'env.log': "详细输出";
620
624
  readonly 'env.retry': "重试";
621
625
  readonly 'env.wake': "打开浏览器";
622
626
  readonly 'env.wake.opening': "正在打开浏览器…";
@@ -823,7 +827,7 @@ export declare const dictionaries: {
823
827
  readonly 'configSync.emptyProviders': "工作台还没有任何模型供应商 —— 去「配置同步」从某个 profile 把模型供应商那几行同步过来,或自己去「模型」里配。";
824
828
  readonly 'configSync.failed': "同步没成功,再试一次。";
825
829
  };
826
- en: Record<"time.now" | "time.ago" | "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.market.open" | "env.unit.failed" | "env.unit.failedHint" | "env.unit.unsupported" | "env.unit.unsupportedHint" | "env.unit.degraded" | "env.unit.degradedHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "profileCreate.nav" | "profileCreate.lead" | "profileCreate.name" | "profileCreate.nameHint" | "profileCreate.source" | "profileCreate.current" | "profileCreate.copy" | "profileCreate.settings" | "profileCreate.create" | "profileCreate.creating" | "profileCreate.created" | "profileCreate.command" | "profileCreate.readFailed" | "profileCreate.retry" | "profileCreate.reading" | "profileCreate.noProfiles" | "profileCreate.failed" | "configSync.nav" | "configSync.lead" | "configSync.source" | "configSync.sourceBroken" | "configSync.sourceRows" | "configSync.sourceDead" | "configSync.refresh" | "configSync.loading" | "configSync.readHint" | "configSync.tag.new" | "configSync.tag.differs" | "configSync.conflictNote" | "configSync.code.lang" | "configSync.code.copy" | "configSync.code.copied" | "configSync.code.wrap" | "configSync.code.unwrap" | "configSync.code.collapse" | "configSync.code.collapseAria" | "configSync.code.expandAria" | "configSync.code.expand" | "configSync.missing" | "configSync.apply" | "configSync.applyNone" | "configSync.applying" | "configSync.applied" | "configSync.appliedUnverified" | "configSync.appliedIds" | "configSync.skippedIds" | "configSync.nothing" | "configSync.unreadable" | "configSync.noSource" | "configSync.emptyProviders" | "configSync.failed" | "env.need.bin.missing" | "env.need.bin.hint" | "env.need.extension.missing" | "env.need.extension.outdated" | "env.need.extension.hint" | "env.need.lib.missing" | "env.need.lib.outdated" | "env.need.lib.unsatisfied" | "env.need.lib.hint" | "env.need.env.missing" | "env.need.env.hint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "project.add.busy" | "project.add.failed" | "project.search.label" | "project.search.placeholder" | "project.search.empty" | "project.group.workspaces" | "project.group.defaultWorkspace" | "project.group.workshop" | "project.rename.row" | "project.rename.current" | "project.rename.title" | "project.rename.description" | "project.rename.field" | "project.rename.placeholder" | "project.rename.hint" | "project.rename.save" | "project.rename.saving" | "project.rename.cancel" | "project.rename.failed" | "session.new" | "session.new.label" | "session.empty" | "session.noProject" | "session.list.label" | "session.copy" | "session.pinned" | "session.actions" | "status.idle" | "status.running" | "status.longTask" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.compact.approval" | "status.compact.planReview" | "status.compact.answer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "project.attention.warning.one" | "project.attention.warning.other" | "project.attention.running.one" | "project.attention.running.other" | "project.attention.longTask.one" | "project.attention.longTask.other" | "project.attention.done.one" | "project.attention.done.other" | "project.attention.state.warning" | "project.attention.state.running" | "project.attention.state.done" | "hover.copied" | "time.short.minutes" | "time.short.hours" | "time.short.days" | "time.short.months" | "time.short.years" | "panels.title" | "panels.groupBoardless" | "panels.groupPlugins" | "runtime.plugin" | "runtime.pluginOf" | "runtime.pluginThing" | "runtime.pluginArea" | "panels.market.defaultHint" | "panels.market.defaultLabel" | "panels.market.defaultLocked" | "panels.followAll" | "panels.followAllConfirmTitle" | "panels.followAllConfirmDetail" | "panels.followAllConfirmAck" | "panels.followAllConfirmYes" | "panels.followAllConfirmNo" | "panels.enabled" | "panels.disabled" | "panels.choose" | "panels.buildModule" | "panels.failed" | "panels.dragHint" | "panels.unknownStep" | "panels.labelWithHint" | "panels.hintJoin" | "panels.dep.failed" | "panels.dep.unchecked" | "panels.dep.missing" | "panels.dep.outdated" | "panels.dep.degraded" | "panels.dep.unsupported" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.notActive" | "panels.market.notUsable" | "panels.market.broken" | "panels.market.hasNew" | "panels.market.hasProblem" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.uncheckedHint" | "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.swapSlow" | "panels.market.removeSlow" | "panels.market.updateNoChange" | "panels.market.updateUnknownVersion" | "panels.market.updateGone" | "panels.market.updateRestored" | "panels.market.updateBehind" | "panels.market.updateStuck.title" | "panels.market.updateStuck.factNoChange" | "panels.market.updateStuck.copiedHint" | "panels.market.selfUpdateFailed" | "panels.market.selfUpdateUnknown" | "panels.market.selfUpdateRolledBack" | "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.noMarketSource" | "panels.market.failed" | "panels.market.failure.permission" | "panels.market.failure.diskFull" | "panels.market.failure.sandbox" | "panels.market.failure.unknown" | "panels.market.failure.factOwner" | "panels.market.failure.factMode" | "panels.market.failure.factSpace" | "panels.market.failure.factStuck" | "panels.market.failure.nowhere" | "panels.market.failure.copyFix" | "panels.market.failure.copied" | "panels.market.failure.copiedHint" | "panels.market.failure.askAgent" | "panels.market.failure.askAgentText" | "panels.market.failure.askAgentHint" | "panels.market.failure.recheck" | "panels.market.failure.showOutput" | "panels.market.failure.hideOutput" | "panels.market.failure.term.commandLine" | "panels.market.failure.term.signal" | "panels.market.failure.term.exitCode" | "panels.market.failure.term.noExitCode" | "panels.market.failure.term.running" | "panels.market.failure.term.failed" | "panels.market.failure.term.done" | "panels.market.failure.term.copy" | "panels.market.failure.term.copied" | "panels.market.failure.term.noOutput" | "panels.market.failure.term.collapse" | "panels.market.failure.term.expandAria" | "panels.market.failure.term.expand" | "panels.market.needEnv" | "panels.market.needCommands" | "panels.market.needBinary" | "panels.market.needLib" | "panels.market.localMark" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.sectionPlugins" | "panels.market.openDetail" | "panels.market.detailBack" | "panels.market.detailSourceTitle" | "panels.market.detailSource" | "panels.market.detailRegistry" | "panels.market.detailSpec" | "panels.market.detailUnit" | "panels.market.detailVersion" | "panels.market.detailLatest" | "panels.market.detailPluginName" | "panels.market.detailInstalledAt" | "panels.market.detailMarket" | "panels.market.detailRepository" | "panels.market.detailCommit" | "panels.market.detailDirectory" | "panels.market.detailUpdateSource" | "panels.market.detailUpdateVersion" | "panels.market.detailLocalDirectory" | "panels.market.detailUnknown" | "panels.market.moduleOutdated" | "panels.market.updateNeedsWorkbench" | "panels.market.updateIncompatible" | "panels.market.moduleRefused" | "panels.market.moduleRestartHint" | "panels.market.pendingRestart" | "panels.market.pendingFollowUp" | "panels.market.migrationHint" | "panels.market.migrateAction" | "panels.market.migrating" | "panels.market.migrateConfirmTitle" | "panels.market.migrateConfirmDetail" | "panels.market.migrateConfirmAck" | "panels.market.migrateConfirmYes" | "panels.market.migrateDone" | "panels.market.dismissFollowUp" | "panels.market.dismissing" | "panels.market.dismissFollowUpTitle" | "panels.market.dismissFollowUpDetail" | "panels.market.dismissFollowUpAck" | "panels.market.dismissFollowUpYes" | "panels.market.dismissed" | "panels.market.workbenchName" | "panels.market.pluginBroken" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.checkUpdates" | "panels.market.checkAll" | "panels.market.checkingNow" | "panels.market.checkFailed" | "panels.market.checkedAt" | "panels.market.latestPartial" | "panels.market.latestNoRegistry" | "panels.market.latestProbeFailed" | "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.problemNotWorkbenchModule" | "panels.market.add.problemNotModuleOrPlugin" | "panels.market.add.failureNotModuleOrPlugin" | "panels.market.add.installedPlugin" | "panels.market.add.pluginPreview" | "panels.market.add.pluginAlias" | "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.failureStopProfile" | "panels.market.add.failureCancelled" | "panels.market.add.failureTimeout" | "panels.market.add.failurePnpmMissing" | "panels.market.add.failureInstalled" | "panels.market.add.failureGeneric" | "panels.market.add.failureCredentials" | "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.classifying" | "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.tabInstalled" | "panels.market.tabs" | "panels.tab.discover" | "panels.discover.loading" | "panels.discover.slowHint" | "panels.discover.lead" | "panels.discover.addSource" | "panels.discover.addingSource" | "panels.discover.addFirstSource" | "panels.discover.removeSource" | "panels.discover.removeTitle" | "panels.discover.removeBody" | "panels.discover.sourceActions" | "panels.discover.sourceStateWritable" | "panels.discover.sourceStateReadOnly" | "panels.discover.sourceEnable" | "panels.discover.sourceDisable" | "panels.discover.sourceWorking" | "panels.discover.sourceEnabled" | "panels.discover.sourceReadOnly" | "panels.discover.refresh" | "panels.discover.search" | "panels.discover.clearSearch" | "panels.discover.all" | "panels.discover.sourceLabel" | "panels.discover.sourceKind" | "panels.discover.sourceKindHttp" | "panels.discover.sourceKindGit" | "panels.discover.sourceUrl" | "panels.discover.sourcePlaceholder" | "panels.discover.sourceRef" | "panels.discover.sourcePath" | "panels.discover.sourceLocal" | "panels.discover.sourceLocalHint" | "panels.discover.save" | "panels.discover.cancel" | "panels.discover.retry" | "panels.discover.noSource" | "panels.discover.noSourceHint" | "panels.discover.sourcesFailed" | "panels.discover.unreadable" | "panels.discover.sandbox" | "panels.discover.sourceAuth" | "panels.discover.invalid" | "panels.discover.emptyRepo" | "panels.discover.missingIndex" | "panels.discover.initTitle" | "panels.discover.initCta" | "panels.discover.initWhat" | "panels.discover.initBranch" | "panels.discover.initBranchHint" | "panels.discover.initBranchBad" | "panels.discover.initOk" | "panels.discover.initBusy" | "panels.discover.initDone" | "panels.discover.stale" | "panels.discover.empty" | "panels.discover.noMatch" | "panels.discover.notInstalled" | "panels.discover.installed" | "panels.discover.installedVersion" | "panels.discover.update" | "panels.discover.badShell" | "panels.discover.badShellDetail" | "panels.discover.unverified" | "panels.discover.installing" | "panels.discover.installingNamed" | "panels.discover.cancelInstall" | "panels.discover.cancelling" | "panels.discover.installCancelled" | "panels.discover.installedDone" | "panels.discover.failed" | "panels.discover.transportTitle" | "panels.discover.transportSsh" | "panels.discover.transportHttps" | "panels.discover.transportOk" | "panels.discover.transportAuth" | "panels.discover.transportUnreachable" | "panels.discover.transportUnknown" | "panels.discover.transportChecking" | "panels.discover.transportTest" | "panels.discover.transportPlaceholder" | "panels.discover.transportNeedsAuth" | "panels.discover.transportChange" | "panels.discover.transportChangeHide" | "panels.discover.transportNone" | "panels.discover.expand" | "panels.discover.collapse" | "panels.discover.versionCount" | "panels.discover.sourceNpm" | "panels.discover.sourceNpmDefault" | "panels.discover.sourceGit" | "panels.discover.installVersion" | "panels.discover.confirmTitle" | "panels.discover.confirmDetail" | "panels.discover.confirmAck" | "panels.discover.confirmOk" | "panels.discover.confirmCancel" | "panels.discover.marketMenu" | "panels.discover.manageSources" | "panels.discover.sourcesTitle" | "panels.discover.sourcesIntro" | "panels.discover.sourcesLabel" | "panels.discover.sourceTrust" | "panels.discover.sourceDuplicate" | "panels.discover.sourceBadUrl" | "panels.discover.close" | "panels.discover.labelsMenu" | "panels.discover.labelsCount" | "panels.discover.tagsAll" | "panels.discover.sort" | "panels.discover.sortWith" | "panels.discover.sortRelevance" | "panels.discover.sortDefault" | "panels.discover.sortPublished" | "panels.discover.categoriesLabel" | "panels.discover.showMore" | "panels.discover.entryMeta" | "panels.discover.entryMetaAuthor" | "panels.discover.openEntry" | "panels.discover.cardInstall" | "panels.discover.cardInstalled" | "panels.discover.cardUpdate" | "panels.discover.cardBlocked" | "panels.discover.installTitle" | "panels.discover.installVersionTitle" | "panels.discover.openInstalled" | "panels.discover.noCompatibleVersion" | "panels.discover.detailBack" | "panels.discover.publishedAt" | "panels.discover.detailMarket" | "panels.discover.detailIncompatible" | "panels.discover.detailUnknown" | "panels.discover.detailSource" | "panels.discover.authorUnknown" | "panels.discover.tabOverview" | "panels.discover.tabReadme" | "panels.discover.tabChangelog" | "panels.discover.docReadme" | "panels.discover.docChangelog" | "panels.discover.docLoading" | "panels.discover.docMissing" | "panels.discover.docUnavailable" | "panels.discover.docUnknownReason" | "panels.discover.detailTabs" | "panels.discover.factPackage" | "panels.discover.factRegistry" | "panels.discover.factRepository" | "panels.discover.factCommit" | "panels.discover.factDirectory" | "panels.discover.factPublished" | "panels.discover.factAuthor" | "panels.discover.factHomepage" | "panels.discover.factCategory" | "panels.discover.factLabels" | "panels.discover.factMarket" | "panels.discover.detailVersions" | "panels.discover.versionsLabel" | "panels.discover.tagRecommended" | "panels.discover.tagPrerelease" | "panels.discover.tagInstalled" | "panels.discover.tagIncompatible" | "panels.discover.tagUnknown" | "panels.discover.selected" | "panels.discover.done" | "panels.discover.installTrust" | "panels.discover.progress" | "panels.market.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.restartWhy" | "panels.market.add.restartWhy.no-hmr" | "panels.market.add.restartWhy.package-moved" | "panels.market.add.restartWhy.host-module" | "panels.market.add.restartWhy.unmanaged-plugin" | "panels.market.add.restartWhy.module-comparison" | "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.update" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.cardBroken" | "panels.cardRetry" | "panels.empty" | "panels.emptyHint" | "env.title" | "env.checking" | "env.installing" | "env.installingToolchain" | "env.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.toolchain.ok" | "env.toolchain.warn" | "env.runtime.ok" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.hold" | "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.wake" | "env.wake.opening" | "env.wake.browserOpen" | "env.wake.noBrowser" | "env.wake.failed" | "env.bridge.continue" | "env.diy.ok" | "env.diy.short" | "env.diy.hold" | "env.diy.why" | "env.diy.rows" | "env.diy.noRow" | "env.diy.step" | "env.diy.continue" | "env.copyCommand" | "env.copied" | "env.step.toolchain" | "env.step.adapter" | "env.step.runtime" | "env.step.bridge" | "env.step.diy" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "adapterSet.not-configured" | "adapterSet.no-profile" | "adapterSet.malformed" | "adapterSet.not-resolvable" | "adapterSet.import-failed" | "adapterSet.bad-export" | "adapterSet.factory-failed" | "adapterSet.incompatible-version" | "adapterSet.missing-member" | "env.unit.hint" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.column.label" | "rightbar.column.workbench" | "rightbar.column.dsh" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "rightbar.openPlatform" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label" | "adapterSet.title" | "adapterSet.lead" | "adapterSet.active" | "adapterSet.defaults" | "adapterSet.failed" | "adapterSet.healthUnreadable" | "workbenchSettings.nav" | "workbenchSettings.lead" | "sidebarEdition.nav" | "sidebarEdition.lead" | "sidebarEdition.official" | "sidebarEdition.officialHint" | "sidebarEdition.custom" | "sidebarEdition.customHint" | "sidebarEdition.saving" | "sidebarEdition.reloadRequired" | "sidebarEdition.reload" | "sidebarEdition.failed" | "debug.workspace" | "debug.status" | "debug.status.trouble" | "debug.stalled" | "debug.act.pause" | "debug.act.resume" | "debug.act.stop" | "debug.act.stop.ask" | "debug.card.here.title" | "debug.card.here.note" | "debug.card.away.note" | "debug.card.paused.note" | "debug.card.hidden.note" | "record.waiting" | "record.waiting.note" | "record.recording" | "record.recording.note" | "record.recording.shots" | "record.finished" | "record.finished.note" | "record.act.cancel" | "record.act.halt" | "approval.record.site" | "approval.record.what" | "approval.record.lands" | "approval.record.noUrl" | "approval.record.oneAction" | "approval.record.noSwitch" | "approval.longTask.what" | "approval.longTask.signal" | "approval.plugin.name" | "approval.plugin.command" | "approval.plugin.note" | "approval.publish.module" | "approval.publish.target" | "approval.publish.version" | "approval.publish.author" | "approval.publish.authorMissing" | "approval.publish.labels" | "approval.publish.labelsMissing" | "approval.publish.owner" | "approval.publish.ownerUnowned" | "approval.publish.ownerTaken" | "approval.publish.unit" | "approval.publish.unitTaken" | "approval.publish.path" | "approval.publish.pathTaken" | "approval.publish.registry" | "approval.publish.repo" | "approval.publish.branch" | "approval.publish.defaultBranch" | "approval.publish.artifacts" | "approval.publish.index" | "approval.publish.commits" | "approval.publish.twoCommits" | "approval.publish.reading" | "approval.publish.changelog" | "approval.publish.changelogPending" | "approval.publish.changelogMissing" | "approval.publish.targetAuto" | "approval.publish.targetTeam" | "approval.publish.targetPublic" | "approval.publish.targetTarball" | "approval.publish.targetGit" | "approval.publish.targetMarket" | "approval.publish.targetLocal" | "approval.market.source" | "approval.market.url" | "approval.market.action" | "approval.market.policy" | "approval.market.enable" | "approval.market.disable" | "approval.market.writable" | "approval.market.readOnly" | "approval.market.reading" | "markdown.copy" | "markdown.copied" | "markdown.footnotes", string>;
830
+ en: Record<"time.now" | "time.ago" | "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.market.open" | "env.unit.failed" | "env.unit.failedHint" | "env.unit.unsupported" | "env.unit.unsupportedHint" | "env.unit.degraded" | "env.unit.degradedHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "profileCreate.nav" | "profileCreate.lead" | "profileCreate.name" | "profileCreate.nameHint" | "profileCreate.source" | "profileCreate.current" | "profileCreate.copy" | "profileCreate.settings" | "profileCreate.create" | "profileCreate.creating" | "profileCreate.created" | "profileCreate.command" | "profileCreate.readFailed" | "profileCreate.retry" | "profileCreate.reading" | "profileCreate.noProfiles" | "profileCreate.failed" | "configSync.nav" | "configSync.lead" | "configSync.source" | "configSync.sourceBroken" | "configSync.sourceRows" | "configSync.sourceDead" | "configSync.refresh" | "configSync.loading" | "configSync.readHint" | "configSync.tag.new" | "configSync.tag.differs" | "configSync.conflictNote" | "configSync.code.lang" | "configSync.code.copy" | "configSync.code.copied" | "configSync.code.wrap" | "configSync.code.unwrap" | "configSync.code.collapse" | "configSync.code.collapseAria" | "configSync.code.expandAria" | "configSync.code.expand" | "configSync.missing" | "configSync.apply" | "configSync.applyNone" | "configSync.applying" | "configSync.applied" | "configSync.appliedUnverified" | "configSync.appliedIds" | "configSync.skippedIds" | "configSync.nothing" | "configSync.unreadable" | "configSync.noSource" | "configSync.emptyProviders" | "configSync.failed" | "env.need.bin.missing" | "env.need.bin.hint" | "env.need.extension.missing" | "env.need.extension.outdated" | "env.need.extension.hint" | "env.need.lib.missing" | "env.need.lib.outdated" | "env.need.lib.unsatisfied" | "env.need.lib.hint" | "env.need.env.missing" | "env.need.env.hint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "project.add.busy" | "project.add.failed" | "project.search.label" | "project.search.placeholder" | "project.search.empty" | "project.group.workspaces" | "project.group.defaultWorkspace" | "project.group.workshop" | "project.rename.row" | "project.rename.current" | "project.rename.title" | "project.rename.description" | "project.rename.field" | "project.rename.placeholder" | "project.rename.hint" | "project.rename.save" | "project.rename.saving" | "project.rename.cancel" | "project.rename.failed" | "session.new" | "session.new.label" | "session.empty" | "session.noProject" | "session.list.label" | "session.copy" | "session.pinned" | "session.actions" | "status.idle" | "status.running" | "status.longTask" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.compact.approval" | "status.compact.planReview" | "status.compact.answer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "project.attention.warning.one" | "project.attention.warning.other" | "project.attention.running.one" | "project.attention.running.other" | "project.attention.longTask.one" | "project.attention.longTask.other" | "project.attention.done.one" | "project.attention.done.other" | "project.attention.state.warning" | "project.attention.state.running" | "project.attention.state.done" | "hover.copied" | "time.short.minutes" | "time.short.hours" | "time.short.days" | "time.short.months" | "time.short.years" | "panels.title" | "panels.groupBoardless" | "panels.groupPlugins" | "runtime.plugin" | "runtime.pluginOf" | "runtime.pluginThing" | "runtime.pluginArea" | "panels.market.defaultHint" | "panels.market.defaultLabel" | "panels.market.defaultLocked" | "panels.followAll" | "panels.followAllConfirmTitle" | "panels.followAllConfirmDetail" | "panels.followAllConfirmAck" | "panels.followAllConfirmYes" | "panels.followAllConfirmNo" | "panels.enabled" | "panels.disabled" | "panels.choose" | "panels.buildModule" | "panels.failed" | "panels.dragHint" | "panels.unknownStep" | "panels.labelWithHint" | "panels.hintJoin" | "panels.dep.failed" | "panels.dep.unchecked" | "panels.dep.missing" | "panels.dep.outdated" | "panels.dep.degraded" | "panels.dep.unsupported" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.notActive" | "panels.market.notUsable" | "panels.market.broken" | "panels.market.hasNew" | "panels.market.hasProblem" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.uncheckedHint" | "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.swapSlow" | "panels.market.removeSlow" | "panels.market.updateNoChange" | "panels.market.updateUnknownVersion" | "panels.market.updateGone" | "panels.market.updateRestored" | "panels.market.updateBehind" | "panels.market.updateStuck.title" | "panels.market.updateStuck.factNoChange" | "panels.market.updateStuck.copiedHint" | "panels.market.selfUpdateFailed" | "panels.market.selfUpdateUnknown" | "panels.market.selfUpdateRolledBack" | "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.noMarketSource" | "panels.market.failed" | "panels.market.failure.permission" | "panels.market.failure.diskFull" | "panels.market.failure.sandbox" | "panels.market.failure.unknown" | "panels.market.failure.factOwner" | "panels.market.failure.factMode" | "panels.market.failure.factSpace" | "panels.market.failure.factStuck" | "panels.market.failure.nowhere" | "panels.market.failure.copyFix" | "panels.market.failure.copied" | "panels.market.failure.copiedHint" | "panels.market.failure.askAgent" | "panels.market.failure.askAgentText" | "panels.market.failure.askAgentHint" | "panels.market.failure.recheck" | "panels.market.failure.showOutput" | "panels.market.failure.hideOutput" | "panels.market.failure.term.commandLine" | "panels.market.failure.term.signal" | "panels.market.failure.term.exitCode" | "panels.market.failure.term.noExitCode" | "panels.market.failure.term.running" | "panels.market.failure.term.failed" | "panels.market.failure.term.done" | "panels.market.failure.term.copy" | "panels.market.failure.term.copied" | "panels.market.failure.term.noOutput" | "panels.market.failure.term.collapse" | "panels.market.failure.term.expandAria" | "panels.market.failure.term.expand" | "panels.market.needEnv" | "panels.market.needCommands" | "panels.market.needBinary" | "panels.market.needLib" | "panels.market.localMark" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.sectionPlugins" | "panels.market.openDetail" | "panels.market.detailBack" | "panels.market.detailSourceTitle" | "panels.market.detailSource" | "panels.market.detailRegistry" | "panels.market.detailSpec" | "panels.market.detailUnit" | "panels.market.detailVersion" | "panels.market.detailLatest" | "panels.market.detailPluginName" | "panels.market.detailInstalledAt" | "panels.market.detailMarket" | "panels.market.detailRepository" | "panels.market.detailCommit" | "panels.market.detailDirectory" | "panels.market.detailUpdateSource" | "panels.market.detailUpdateVersion" | "panels.market.detailLocalDirectory" | "panels.market.detailUnknown" | "panels.market.moduleOutdated" | "panels.market.updateNeedsWorkbench" | "panels.market.updateIncompatible" | "panels.market.moduleRefused" | "panels.market.moduleRestartHint" | "panels.market.pendingRestart" | "panels.market.pendingFollowUp" | "panels.market.migrationHint" | "panels.market.migrateAction" | "panels.market.migrating" | "panels.market.migrateConfirmTitle" | "panels.market.migrateConfirmDetail" | "panels.market.migrateConfirmAck" | "panels.market.migrateConfirmYes" | "panels.market.migrateDone" | "panels.market.dismissFollowUp" | "panels.market.dismissing" | "panels.market.dismissFollowUpTitle" | "panels.market.dismissFollowUpDetail" | "panels.market.dismissFollowUpAck" | "panels.market.dismissFollowUpYes" | "panels.market.dismissed" | "panels.market.workbenchName" | "panels.market.pluginBroken" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.checkUpdates" | "panels.market.checkAll" | "panels.market.checkingNow" | "panels.market.checkFailed" | "panels.market.checkedAt" | "panels.market.latestPartial" | "panels.market.latestNoRegistry" | "panels.market.latestProbeFailed" | "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.problemNotWorkbenchModule" | "panels.market.add.problemNotModuleOrPlugin" | "panels.market.add.failureNotModuleOrPlugin" | "panels.market.add.installedPlugin" | "panels.market.add.pluginPreview" | "panels.market.add.pluginAlias" | "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.failureStopProfile" | "panels.market.add.failureCancelled" | "panels.market.add.failureTimeout" | "panels.market.add.failurePnpmMissing" | "panels.market.add.failureInstalled" | "panels.market.add.failureGeneric" | "panels.market.add.failureCredentials" | "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.classifying" | "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.tabInstalled" | "panels.market.tabs" | "panels.tab.discover" | "panels.discover.loading" | "panels.discover.slowHint" | "panels.discover.lead" | "panels.discover.addSource" | "panels.discover.addingSource" | "panels.discover.addFirstSource" | "panels.discover.removeSource" | "panels.discover.removeTitle" | "panels.discover.removeBody" | "panels.discover.sourceActions" | "panels.discover.sourceStateWritable" | "panels.discover.sourceStateReadOnly" | "panels.discover.sourceEnable" | "panels.discover.sourceDisable" | "panels.discover.sourceWorking" | "panels.discover.sourceEnabled" | "panels.discover.sourceReadOnly" | "panels.discover.refresh" | "panels.discover.search" | "panels.discover.clearSearch" | "panels.discover.all" | "panels.discover.sourceLabel" | "panels.discover.sourceKind" | "panels.discover.sourceKindHttp" | "panels.discover.sourceKindGit" | "panels.discover.sourceUrl" | "panels.discover.sourcePlaceholder" | "panels.discover.sourceRef" | "panels.discover.sourcePath" | "panels.discover.sourceLocal" | "panels.discover.sourceLocalHint" | "panels.discover.save" | "panels.discover.cancel" | "panels.discover.retry" | "panels.discover.noSource" | "panels.discover.noSourceHint" | "panels.discover.sourcesFailed" | "panels.discover.unreadable" | "panels.discover.sandbox" | "panels.discover.sourceAuth" | "panels.discover.invalid" | "panels.discover.emptyRepo" | "panels.discover.missingIndex" | "panels.discover.initTitle" | "panels.discover.initCta" | "panels.discover.initWhat" | "panels.discover.initBranch" | "panels.discover.initBranchHint" | "panels.discover.initBranchBad" | "panels.discover.initOk" | "panels.discover.initBusy" | "panels.discover.initDone" | "panels.discover.stale" | "panels.discover.empty" | "panels.discover.noMatch" | "panels.discover.notInstalled" | "panels.discover.installed" | "panels.discover.installedVersion" | "panels.discover.update" | "panels.discover.badShell" | "panels.discover.badShellDetail" | "panels.discover.unverified" | "panels.discover.installing" | "panels.discover.installingNamed" | "panels.discover.cancelInstall" | "panels.discover.cancelling" | "panels.discover.installCancelled" | "panels.discover.installedDone" | "panels.discover.failed" | "panels.discover.transportTitle" | "panels.discover.transportSsh" | "panels.discover.transportHttps" | "panels.discover.transportOk" | "panels.discover.transportAuth" | "panels.discover.transportUnreachable" | "panels.discover.transportUnknown" | "panels.discover.transportChecking" | "panels.discover.transportTest" | "panels.discover.transportPlaceholder" | "panels.discover.transportNeedsAuth" | "panels.discover.transportChange" | "panels.discover.transportChangeHide" | "panels.discover.transportNone" | "panels.discover.expand" | "panels.discover.collapse" | "panels.discover.versionCount" | "panels.discover.sourceNpm" | "panels.discover.sourceNpmDefault" | "panels.discover.sourceGit" | "panels.discover.installVersion" | "panels.discover.confirmTitle" | "panels.discover.confirmDetail" | "panels.discover.confirmAck" | "panels.discover.confirmOk" | "panels.discover.confirmCancel" | "panels.discover.marketMenu" | "panels.discover.manageSources" | "panels.discover.sourcesTitle" | "panels.discover.sourcesIntro" | "panels.discover.sourcesLabel" | "panels.discover.sourceTrust" | "panels.discover.sourceDuplicate" | "panels.discover.sourceBadUrl" | "panels.discover.close" | "panels.discover.labelsMenu" | "panels.discover.labelsCount" | "panels.discover.tagsAll" | "panels.discover.sort" | "panels.discover.sortWith" | "panels.discover.sortRelevance" | "panels.discover.sortDefault" | "panels.discover.sortPublished" | "panels.discover.categoriesLabel" | "panels.discover.showMore" | "panels.discover.entryMeta" | "panels.discover.entryMetaAuthor" | "panels.discover.openEntry" | "panels.discover.cardInstall" | "panels.discover.cardInstalled" | "panels.discover.cardUpdate" | "panels.discover.cardBlocked" | "panels.discover.installTitle" | "panels.discover.installVersionTitle" | "panels.discover.openInstalled" | "panels.discover.noCompatibleVersion" | "panels.discover.detailBack" | "panels.discover.publishedAt" | "panels.discover.detailMarket" | "panels.discover.detailIncompatible" | "panels.discover.detailUnknown" | "panels.discover.detailSource" | "panels.discover.authorUnknown" | "panels.discover.tabOverview" | "panels.discover.tabReadme" | "panels.discover.tabChangelog" | "panels.discover.docReadme" | "panels.discover.docChangelog" | "panels.discover.docLoading" | "panels.discover.docMissing" | "panels.discover.docUnavailable" | "panels.discover.docUnknownReason" | "panels.discover.detailTabs" | "panels.discover.factPackage" | "panels.discover.factRegistry" | "panels.discover.factRepository" | "panels.discover.factCommit" | "panels.discover.factDirectory" | "panels.discover.factPublished" | "panels.discover.factAuthor" | "panels.discover.factHomepage" | "panels.discover.factCategory" | "panels.discover.factLabels" | "panels.discover.factMarket" | "panels.discover.detailVersions" | "panels.discover.versionsLabel" | "panels.discover.tagRecommended" | "panels.discover.tagPrerelease" | "panels.discover.tagInstalled" | "panels.discover.tagIncompatible" | "panels.discover.tagUnknown" | "panels.discover.selected" | "panels.discover.done" | "panels.discover.installTrust" | "panels.discover.progress" | "panels.market.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.restartWhy" | "panels.market.add.restartWhy.no-hmr" | "panels.market.add.restartWhy.package-moved" | "panels.market.add.restartWhy.host-module" | "panels.market.add.restartWhy.unmanaged-plugin" | "panels.market.add.restartWhy.module-comparison" | "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.update" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.cardBroken" | "panels.cardRetry" | "panels.empty" | "panels.emptyHint" | "env.title" | "env.checking" | "env.installing" | "env.installingToolchain" | "env.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.stepFailed.host" | "env.toolchain.ok" | "env.toolchain.warn" | "env.runtime.ok" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.hold" | "env.bridge.unknown" | "env.fix.title" | "env.fix.why" | "env.fix.whyPath" | "env.fix.whyShell" | "env.fix.whyHost" | "env.fix.step" | "env.fix.stepPath" | "env.fix.stepShell" | "env.fix.stepHost" | "env.fix.permission" | "env.fix.network" | "env.fix.details" | "env.log" | "env.retry" | "env.wake" | "env.wake.opening" | "env.wake.browserOpen" | "env.wake.noBrowser" | "env.wake.failed" | "env.bridge.continue" | "env.diy.ok" | "env.diy.short" | "env.diy.hold" | "env.diy.why" | "env.diy.rows" | "env.diy.noRow" | "env.diy.step" | "env.diy.continue" | "env.copyCommand" | "env.copied" | "env.step.toolchain" | "env.step.adapter" | "env.step.runtime" | "env.step.bridge" | "env.step.diy" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "adapterSet.not-configured" | "adapterSet.no-profile" | "adapterSet.malformed" | "adapterSet.not-resolvable" | "adapterSet.import-failed" | "adapterSet.bad-export" | "adapterSet.factory-failed" | "adapterSet.incompatible-version" | "adapterSet.missing-member" | "env.unit.hint" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.column.label" | "rightbar.column.workbench" | "rightbar.column.dsh" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "rightbar.openPlatform" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label" | "adapterSet.title" | "adapterSet.lead" | "adapterSet.active" | "adapterSet.defaults" | "adapterSet.failed" | "adapterSet.healthUnreadable" | "workbenchSettings.nav" | "workbenchSettings.lead" | "sidebarEdition.nav" | "sidebarEdition.lead" | "sidebarEdition.official" | "sidebarEdition.officialHint" | "sidebarEdition.custom" | "sidebarEdition.customHint" | "sidebarEdition.saving" | "sidebarEdition.reloadRequired" | "sidebarEdition.reload" | "sidebarEdition.failed" | "debug.workspace" | "debug.status" | "debug.status.trouble" | "debug.stalled" | "debug.act.pause" | "debug.act.resume" | "debug.act.stop" | "debug.act.stop.ask" | "debug.card.here.title" | "debug.card.here.note" | "debug.card.away.note" | "debug.card.paused.note" | "debug.card.hidden.note" | "record.waiting" | "record.waiting.note" | "record.recording" | "record.recording.note" | "record.recording.shots" | "record.finished" | "record.finished.note" | "record.act.cancel" | "record.act.halt" | "approval.record.site" | "approval.record.what" | "approval.record.lands" | "approval.record.noUrl" | "approval.record.oneAction" | "approval.record.noSwitch" | "approval.longTask.what" | "approval.longTask.signal" | "approval.plugin.name" | "approval.plugin.command" | "approval.plugin.note" | "approval.publish.module" | "approval.publish.target" | "approval.publish.version" | "approval.publish.author" | "approval.publish.authorMissing" | "approval.publish.labels" | "approval.publish.labelsMissing" | "approval.publish.owner" | "approval.publish.ownerUnowned" | "approval.publish.ownerTaken" | "approval.publish.unit" | "approval.publish.unitTaken" | "approval.publish.path" | "approval.publish.pathTaken" | "approval.publish.registry" | "approval.publish.repo" | "approval.publish.branch" | "approval.publish.defaultBranch" | "approval.publish.artifacts" | "approval.publish.index" | "approval.publish.commits" | "approval.publish.twoCommits" | "approval.publish.reading" | "approval.publish.changelog" | "approval.publish.changelogPending" | "approval.publish.changelogMissing" | "approval.publish.targetAuto" | "approval.publish.targetTeam" | "approval.publish.targetPublic" | "approval.publish.targetTarball" | "approval.publish.targetGit" | "approval.publish.targetMarket" | "approval.publish.targetLocal" | "approval.market.source" | "approval.market.url" | "approval.market.action" | "approval.market.policy" | "approval.market.enable" | "approval.market.disable" | "approval.market.writable" | "approval.market.readOnly" | "approval.market.reading" | "markdown.copy" | "markdown.copied" | "markdown.footnotes", string>;
827
831
  };
828
832
  /** 中文词表的键类型(从 `zh.ts` 转出):`en` 与模块词表都得覆盖同一批键。 */
829
833
  export type { WorkbenchMessages };
package/dist/i18n/zh.d.ts CHANGED
@@ -597,6 +597,7 @@ export declare const zh: {
597
597
  readonly 'env.stepFailed.install': "装不上";
598
598
  readonly 'env.stepFailed.path': "装了但还找不到";
599
599
  readonly 'env.stepFailed.shell': "连不上命令行";
600
+ readonly 'env.stepFailed.host': "命令行没有返回";
600
601
  readonly 'env.toolchain.ok': "正常";
601
602
  readonly 'env.toolchain.warn': "还没完全准备好";
602
603
  readonly 'env.runtime.ok': "已就绪";
@@ -609,12 +610,15 @@ export declare const zh: {
609
610
  readonly 'env.fix.why': "工作台用它自己那份后台工具(与你在终端里那套分开装,互不影响),这台机器上还没装好它。";
610
611
  readonly 'env.fix.whyPath': "后台工具装上了,但当前环境还找不到它 —— 通常是 PATH 或终端会话的问题。";
611
612
  readonly 'env.fix.whyShell': "工作台拿不到这台机器的命令行,所以取不了数据 —— 这一步你装不了,需要有人处理后台环境。";
613
+ readonly 'env.fix.whyHost': "工作台要靠命令行跑几条检查,再把结果收回来;这次命令发出去了,结果一直没回来。工具本身多半是好的 —— 重装 Node / npm / pnpm 不会有帮助。";
612
614
  readonly 'env.fix.step': "在终端里运行下面这条命令,装好之后点「重试」:";
613
615
  readonly 'env.fix.stepPath': "新开一个终端窗口(或确认 npm 的全局 bin 目录在 PATH 里),然后点「重试」。";
614
616
  readonly 'env.fix.stepShell': "重启一次工作台(或 dsh);如果反复出现,说明工作台还是拿不到命令行。";
617
+ readonly 'env.fix.stepHost': "完全退出工作台(托盘图标也要退),清掉系统临时目录里 dsh- 开头的残留,再重新打开;反复出现就升级 dsh。";
615
618
  readonly 'env.fix.permission': "权限不够:在命令前加 sudo 重跑,或先把 npm 的全局目录配到你的用户目录。";
616
619
  readonly 'env.fix.network': "网络不通:检查网络或代理设置后重试。";
617
620
  readonly 'env.fix.details': "详细输出(排障用)";
621
+ readonly 'env.log': "详细输出";
618
622
  readonly 'env.retry': "重试";
619
623
  readonly 'env.wake': "打开浏览器";
620
624
  readonly 'env.wake.opening': "正在打开浏览器…";
package/dist/i18n/zh.js CHANGED
@@ -589,6 +589,7 @@ export const zh = {
589
589
  'env.stepFailed.install': '装不上',
590
590
  'env.stepFailed.path': '装了但还找不到',
591
591
  'env.stepFailed.shell': '连不上命令行',
592
+ 'env.stepFailed.host': '命令行没有返回',
592
593
  'env.toolchain.ok': '正常',
593
594
  'env.toolchain.warn': '还没完全准备好',
594
595
  'env.runtime.ok': '已就绪',
@@ -601,12 +602,15 @@ export const zh = {
601
602
  'env.fix.why': '工作台用它自己那份后台工具(与你在终端里那套分开装,互不影响),这台机器上还没装好它。',
602
603
  'env.fix.whyPath': '后台工具装上了,但当前环境还找不到它 —— 通常是 PATH 或终端会话的问题。',
603
604
  'env.fix.whyShell': '工作台拿不到这台机器的命令行,所以取不了数据 —— 这一步你装不了,需要有人处理后台环境。',
605
+ 'env.fix.whyHost': '工作台要靠命令行跑几条检查,再把结果收回来;这次命令发出去了,结果一直没回来。工具本身多半是好的 —— 重装 Node / npm / pnpm 不会有帮助。',
604
606
  'env.fix.step': '在终端里运行下面这条命令,装好之后点「重试」:',
605
607
  'env.fix.stepPath': '新开一个终端窗口(或确认 npm 的全局 bin 目录在 PATH 里),然后点「重试」。',
606
608
  'env.fix.stepShell': '重启一次工作台(或 dsh);如果反复出现,说明工作台还是拿不到命令行。',
609
+ 'env.fix.stepHost': '完全退出工作台(托盘图标也要退),清掉系统临时目录里 dsh- 开头的残留,再重新打开;反复出现就升级 dsh。',
607
610
  'env.fix.permission': '权限不够:在命令前加 sudo 重跑,或先把 npm 的全局目录配到你的用户目录。',
608
611
  'env.fix.network': '网络不通:检查网络或代理设置后重试。',
609
612
  'env.fix.details': '详细输出(排障用)',
613
+ 'env.log': '详细输出',
610
614
  'env.retry': '重试',
611
615
  'env.wake': '打开浏览器',
612
616
  'env.wake.opening': '正在打开浏览器…',
@@ -21,7 +21,8 @@ export interface BoardProbe {
21
21
  * 判一个路径落不落在这个工作区里(按路径前缀比,不是字符串包含)。
22
22
  * @param root - 工作区根路径。
23
23
  * @param target - 要判的路径。
24
- * @returns 同一个路径或在其下给 `true`;`root` 末尾带不带斜杠都认(`/a` 不匹配 `/ab`)。
24
+ * @returns 同一个路径或在其下给 `true`;分隔符先归一(Windows 的 `\` 与 `/` 都认),
25
+ * 盘符路径按大小写不敏感比;`root` 末尾带不带斜杠都认(`/a` 不匹配 `/ab`)。
25
26
  */
26
27
  export declare function insideWorkshop(root: string, target: string): boolean;
27
28
  /**
@@ -1,14 +1,20 @@
1
+ function normalizePath(value) {
2
+ const forward = value.replace(/\\/g, '/').replace(/\/+$/g, '');
3
+ return /^[A-Za-z]:\//.test(forward) || forward.startsWith('//') ? forward.toLowerCase() : forward;
4
+ }
1
5
  /**
2
6
  * 判一个路径落不落在这个工作区里(按路径前缀比,不是字符串包含)。
3
7
  * @param root - 工作区根路径。
4
8
  * @param target - 要判的路径。
5
- * @returns 同一个路径或在其下给 `true`;`root` 末尾带不带斜杠都认(`/a` 不匹配 `/ab`)。
9
+ * @returns 同一个路径或在其下给 `true`;分隔符先归一(Windows 的 `\` 与 `/` 都认),
10
+ * 盘符路径按大小写不敏感比;`root` 末尾带不带斜杠都认(`/a` 不匹配 `/ab`)。
6
11
  */
7
12
  export function insideWorkshop(root, target) {
8
- if (target === root)
13
+ const base = normalizePath(root);
14
+ const real = normalizePath(target);
15
+ if (real === base)
9
16
  return true;
10
- const base = root.endsWith('/') ? root : `${root}/`;
11
- return target.startsWith(base);
17
+ return real.startsWith(base === '' ? '/' : `${base}/`);
12
18
  }
13
19
  /**
14
20
  * 把探针读数归成左栏那句人话的档位。
package/dist/lib/ui.d.ts CHANGED
@@ -50,11 +50,18 @@ export declare function relativeTimeAgo(epochMs: number, t: TimeTranslate, now?:
50
50
  */
51
51
  export declare function relativeTime(epochMs: number, t: TimeTranslate): string;
52
52
  /**
53
- * 把 `/Users/<用户名>/…` 缩成 `~/…`,免得会话行里全是一样的长前缀。
53
+ * 把用户主目录(macOS `/Users/<用户名>`、Linux `/home/<用户名>`、Windows `C:\Users\<用户名>`)缩成 `~`,
54
+ * 免得会话行里全是一样的长前缀。
54
55
  * @param path - 任意值。
55
56
  * @returns 缩好的路径;不在用户主目录下原样返回,不是字符串给空串。
56
57
  */
57
58
  export declare function shortenPath(path: unknown): string;
59
+ /**
60
+ * 取路径最后一段,`/` 与 `\` 都认(Windows 路径、混合分隔符都行)。
61
+ * @param path - 任意值。
62
+ * @returns 末段;尾部有分隔符先去掉,没有分隔符就整串,不是字符串给空串。
63
+ */
64
+ export declare function pathBase(path: unknown): string;
58
65
  /**
59
66
  * 解析不带时区的本地时间戳(`YYYY-MM-DD HH:mm:ss`,也接受 `T` 分隔),按本机时区换算。
60
67
  * @param text - 原文;`null` / `undefined` 当空串;首尾空白容忍。
package/dist/lib/ui.js CHANGED
@@ -82,16 +82,34 @@ export function relativeTime(epochMs, t) {
82
82
  return t('time.days', { n: Math.floor(diff / (24 * 60 * MINUTE)) });
83
83
  return dayjs(epochMs).format('YYYY/M/D HH:mm:ss');
84
84
  }
85
+ const HOME_PREFIXES = [/^\/Users\/[^/]+/, /^\/home\/[^/]+/, /^[A-Za-z]:\\Users\\[^\\]+/];
85
86
  /**
86
- * 把 `/Users/<用户名>/…` 缩成 `~/…`,免得会话行里全是一样的长前缀。
87
+ * 把用户主目录(macOS `/Users/<用户名>`、Linux `/home/<用户名>`、Windows `C:\Users\<用户名>`)缩成 `~`,
88
+ * 免得会话行里全是一样的长前缀。
87
89
  * @param path - 任意值。
88
90
  * @returns 缩好的路径;不在用户主目录下原样返回,不是字符串给空串。
89
91
  */
90
92
  export function shortenPath(path) {
91
93
  if (typeof path !== 'string')
92
94
  return '';
93
- const hit = path.match(/^\/Users\/[^/]+/);
94
- return hit === null ? path : path.replace(hit[0], '~');
95
+ for (const pattern of HOME_PREFIXES) {
96
+ const hit = path.match(pattern);
97
+ if (hit !== null)
98
+ return path.replace(hit[0], '~');
99
+ }
100
+ return path;
101
+ }
102
+ /**
103
+ * 取路径最后一段,`/` 与 `\` 都认(Windows 路径、混合分隔符都行)。
104
+ * @param path - 任意值。
105
+ * @returns 末段;尾部有分隔符先去掉,没有分隔符就整串,不是字符串给空串。
106
+ */
107
+ export function pathBase(path) {
108
+ if (typeof path !== 'string')
109
+ return '';
110
+ const trimmed = path.replace(/[\\/]+$/, '');
111
+ const at = Math.max(trimmed.lastIndexOf('/'), trimmed.lastIndexOf('\\'));
112
+ return at === -1 ? trimmed : trimmed.slice(at + 1);
95
113
  }
96
114
  const LOCAL_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})$/;
97
115
  /**
@@ -0,0 +1,28 @@
1
+ import type { UnitClientFace } from '../components/board-module.js';
2
+ /**
3
+ * 浏览器面注册需要的那点上下文:`get` / `effect`。
4
+ */
5
+ export interface UnitClientContextLike {
6
+ get<T = unknown>(name: string): T | undefined;
7
+ effect(effect: () => void | (() => void), label?: string): () => void;
8
+ }
9
+ /**
10
+ * 一个浏览器插件导出的两件:`inject` / `apply`。
11
+ */
12
+ export interface UnitClientPlugin {
13
+ readonly inject: readonly string[];
14
+ apply(ctx: UnitClientContextLike): void;
15
+ }
16
+ /**
17
+ * 把「浏览器面注册进外壳」这段在每个模块里都一样的接线收成一份。
18
+ * 把它直接当插件导出用:`export const { inject, apply } = defineUnitClientPlugin({ … })`。
19
+ * @param options.unit 单元 id。
20
+ * @param options.face 这个单元的浏览器面。
21
+ * @param options.label 清理标签里用的名字;默认用 `unit`。
22
+ * @returns `{ inject, apply }`;`apply` 里取 `workbenchUnits`、缺了就 warn 一声。
23
+ */
24
+ export declare function defineUnitClientPlugin(options: {
25
+ readonly unit: string;
26
+ readonly face: UnitClientFace;
27
+ readonly label?: string | undefined;
28
+ }): UnitClientPlugin;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 把「浏览器面注册进外壳」这段在每个模块里都一样的接线收成一份。
3
+ * 把它直接当插件导出用:`export const { inject, apply } = defineUnitClientPlugin({ … })`。
4
+ * @param options.unit 单元 id。
5
+ * @param options.face 这个单元的浏览器面。
6
+ * @param options.label 清理标签里用的名字;默认用 `unit`。
7
+ * @returns `{ inject, apply }`;`apply` 里取 `workbenchUnits`、缺了就 warn 一声。
8
+ */
9
+ export function defineUnitClientPlugin(options) {
10
+ const { unit, face } = options;
11
+ const label = options.label ?? unit;
12
+ return {
13
+ inject: ['workbenchUnits'],
14
+ apply(ctx) {
15
+ const units = ctx.get('workbenchUnits');
16
+ if (units === undefined) {
17
+ console.warn(`[${unit}] 外壳没有提供 workbenchUnits 服务:这张卡片装不进来`);
18
+ return;
19
+ }
20
+ ctx.effect(() => units.registerUnit(face), `${label}: 注册 ${unit}`);
21
+ },
22
+ };
23
+ }
@@ -5,6 +5,7 @@ export interface ShellCall {
5
5
  timeoutMs?: number;
6
6
  onExpiry?: string;
7
7
  stdoutMaxBytes?: number;
8
+ env?: Readonly<Record<string, string>>;
8
9
  }
9
10
  export interface ShellReply {
10
11
  stdout?: string;
@@ -12,6 +13,7 @@ export interface ShellReply {
12
13
  exitCode?: number | null;
13
14
  timedOut?: boolean;
14
15
  aborted?: boolean;
16
+ truncated?: boolean;
15
17
  failWith?: Error;
16
18
  }
17
19
  export declare function createFakeShell(replies?: ShellReply[] | ((call: ShellCall, index: number) => ShellReply)): {
@@ -25,7 +25,7 @@ export function createFakeShell(replies = []) {
25
25
  exitCode: reply.exitCode ?? 0,
26
26
  timedOut: reply.timedOut ?? false,
27
27
  aborted: reply.aborted ?? false,
28
- stdout: { text: reply.stdout ?? '', truncated: false },
28
+ stdout: { text: reply.stdout ?? '', truncated: reply.truncated === true },
29
29
  stderr: { text: reply.stderr ?? '', truncated: false },
30
30
  };
31
31
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-workbench/shared",
3
- "version": "1.1.12",
3
+ "version": "1.1.14-beta.0",
4
4
  "description": "工作台与模块共享的纯代码与契约类型:类型、纯逻辑、哑组件、平台解析。宿主侧的东西从 /host 进(不影响浏览器产物)。",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -33,7 +33,7 @@
33
33
  "react": "*"
34
34
  },
35
35
  "devDependencies": {
36
- "@arch-guard/core": "^0.11.2",
36
+ "@arch-guard/core": "^0.11.3",
37
37
  "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-rc.2",
38
38
  "@types/node": "^24.19.0",
39
39
  "@types/react": "^19.0.0",
package/src/api/dsh.ts CHANGED
@@ -149,6 +149,7 @@ export interface DshShellExecution {
149
149
 
150
150
  /**
151
151
  * dsh 的 shell 服务:先 resolve 出执行规格,再把它原样喂给 execute。
152
+ * `env` 是**叠加**在宿主环境上的变量覆盖(不是替换),所以设一个变量不必自己拼 shell 语法。
152
153
  */
153
154
  export interface DshShell {
154
155
  resolve(request: {
@@ -158,6 +159,7 @@ export interface DshShell {
158
159
  onExpiry?: 'kill' | 'none';
159
160
  stdoutMaxBytes?: number;
160
161
  signal?: AbortSignal;
162
+ env?: Readonly<Record<string, string>>;
161
163
  }): unknown;
162
164
  execute(spec: unknown): Promise<DshShellExecution>;
163
165
  }
@@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs';
2
2
  import { describe, expect, it } from 'vitest';
3
3
 
4
4
  const HERE = new URL('../', import.meta.url);
5
- const read = (name: string): string => readFileSync(new URL(name, HERE), 'utf8');
5
+ const read = (name: string): string => readFileSync(new URL(name, HERE), 'utf8').replaceAll('\r\n', '\n');
6
6
 
7
7
  const ROW = read('LongTaskRow.tsx');
8
8
  const CSS = read('LongTaskRow.css');
@@ -73,6 +73,9 @@ export const PREFLIGHT_FRESH_MS = 30_000;
73
73
  /** 装 / 卸模块包的超时(毫秒):pnpm 与取包内容都按它算。 */
74
74
  export const INSTALL_TIMEOUT_MS = 300_000;
75
75
 
76
+ /** 启动体检里查版本号那一条的超时(毫秒):只印个版本号,留够 opencli 每次调用约 5 秒的开销;`doctor` 要起浏览器会话,另按 `OPENCLI_TIMEOUT_MS`。 */
77
+ export const PREFLIGHT_VERSION_TIMEOUT_MS = 30_000;
78
+
76
79
  /** 查 registry 版本那一次请求的超时(毫秒)。 */
77
80
  export const VERSION_CHECK_TIMEOUT_MS = 10_000;
78
81
 
@@ -7,6 +7,7 @@ export interface CommandRequest {
7
7
  readonly argv: readonly string[];
8
8
  readonly timeoutMs?: number | undefined;
9
9
  readonly cwd?: string | undefined;
10
+ readonly env?: Readonly<Record<string, string>> | undefined;
10
11
  readonly files?: readonly CommandFile[] | undefined;
11
12
  readonly appendFileArgs?: string | undefined;
12
13
  }
@@ -16,6 +17,7 @@ export interface CommandResult {
16
17
  readonly stderr: string;
17
18
  readonly exitCode: number;
18
19
  readonly timedOut: boolean;
20
+ readonly truncated: boolean;
19
21
  readonly filePaths: readonly string[];
20
22
  readonly error?: string | undefined;
21
23
  }
@@ -120,7 +120,8 @@ export function declarationProblemsOf(subject: string, raw: unknown): readonly s
120
120
  if (version === undefined) {
121
121
  return [
122
122
  `${subject}: dsh.workbench 没有 apiVersion —— 协议从 v${WORKBENCH_API_VERSION} 起,` +
123
- `写 \`"apiVersion": ${WORKBENCH_API_VERSION}\`。缺它 = 外壳不认这个模块`,
123
+ `写 \`"apiVersion": ${WORKBENCH_API_VERSION}\`。缺它 = 外壳不认这个模块` +
124
+ '(`dsh-wb-module migrate` 能自动补这一项)',
124
125
  ];
125
126
  }
126
127
  if (!Number.isInteger(version) || !SUPPORTED_API_VERSIONS.includes(version as number)) {
@@ -128,7 +129,7 @@ export function declarationProblemsOf(subject: string, raw: unknown): readonly s
128
129
  version === 2
129
130
  ? ' —— v3 把卡片标题挪成了顶层 `title`(`{ "zh": "…", "en": "…" }` 字面量):' +
130
131
  '把 `card.titleKey` 删掉、在顶层写 title,再把 apiVersion 改成 3'
131
- : '';
132
+ : ' —— 先跑 `dsh-wb-module migrate` 把版本号改到 3,再按 check 的提示改源码';
132
133
  return [
133
134
  `${subject}: dsh.workbench.apiVersion 是 ${JSON.stringify(version)},这里只认 ` +
134
135
  `${SUPPORTED_API_VERSIONS.join(' / ')}(要整数)${hint}`,
@@ -0,0 +1,47 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { afterEach, describe, expect, it, vi } from 'vitest';
4
+ import { dshHome, workbenchRoot, workspacesRoot } from '../data-root.js';
5
+
6
+ afterEach(() => {
7
+ vi.unstubAllEnvs();
8
+ });
9
+
10
+ describe('dshHome', () => {
11
+ it('★ DSH_HOME 优先', () => {
12
+ vi.stubEnv('DSH_HOME', '/tmp/explicit-home');
13
+
14
+ expect(dshHome()).toBe('/tmp/explicit-home');
15
+ });
16
+
17
+ it('★ 没配 DSH_HOME 时交给系统的用户主目录,不自己拼 HOME', () => {
18
+ vi.stubEnv('DSH_HOME', '');
19
+ vi.stubEnv('HOME', '');
20
+
21
+ expect(dshHome()).toBe(join(homedir(), '.dsh'));
22
+ expect(dshHome()).not.toBe('/.dsh');
23
+ });
24
+
25
+ it('★ 无论 HOME 怎么写,数据根都跟着系统的用户主目录走', () => {
26
+ vi.stubEnv('DSH_HOME', '');
27
+ vi.stubEnv('HOME', '/tmp/posix-only-home');
28
+
29
+ expect(dshHome()).toBe(join(homedir(), '.dsh'));
30
+ });
31
+
32
+ it('★ workbenchRoot 与 workspacesRoot 都挂在数据根下面', () => {
33
+ vi.stubEnv('DSH_HOME', '/tmp/root');
34
+ vi.stubEnv('DSH_WORKBENCH_HOME', '');
35
+
36
+ expect(workbenchRoot()).toBe(join('/tmp/root', 'workbench'));
37
+ expect(workspacesRoot()).toBe(join('/tmp/root', 'workbench', 'workspaces'));
38
+ });
39
+
40
+ it('DSH_WORKBENCH_HOME 能单独指定运行时根', () => {
41
+ vi.stubEnv('DSH_HOME', '/tmp/root');
42
+ vi.stubEnv('DSH_WORKBENCH_HOME', '/tmp/runtime');
43
+
44
+ expect(workbenchRoot()).toBe('/tmp/runtime');
45
+ expect(workspacesRoot()).toBe(join('/tmp/runtime', 'workspaces'));
46
+ });
47
+ });