@dsh-workbench/shared 1.1.5 → 1.1.7

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 (38) hide show
  1. package/dist/contract/needs.d.ts +3 -0
  2. package/dist/contract/needs.js +17 -0
  3. package/dist/contract/protocol/market-index.d.ts +3 -1
  4. package/dist/contract/protocol/market-index.js +2 -0
  5. package/dist/host/lib-runners.d.ts +20 -0
  6. package/dist/host/lib-runners.js +46 -0
  7. package/dist/host/market-index-claim.d.ts +2 -0
  8. package/dist/host/market-index-claim.js +7 -0
  9. package/dist/host/market-index-doc.d.ts +56 -0
  10. package/dist/host/market-index-doc.js +1 -0
  11. package/dist/host/market-index-parse.d.ts +23 -0
  12. package/dist/host/market-index-parse.js +485 -0
  13. package/dist/host/market-index.d.ts +13 -21
  14. package/dist/host/market-index.js +120 -368
  15. package/dist/host/opencli-runner.d.ts +25 -0
  16. package/dist/host/opencli-runner.js +50 -0
  17. package/dist/host.d.ts +2 -0
  18. package/dist/host.js +2 -0
  19. package/dist/i18n/en.js +10 -4
  20. package/dist/i18n/index.d.ts +11 -5
  21. package/dist/i18n/zh.d.ts +10 -4
  22. package/dist/i18n/zh.js +10 -4
  23. package/package.json +1 -1
  24. package/src/contract/__tests__/needs.test.ts +8 -0
  25. package/src/contract/needs.ts +15 -0
  26. package/src/contract/protocol/market-index.ts +4 -0
  27. package/src/host/__tests__/lib-runners.test.ts +82 -0
  28. package/src/host/__tests__/market-index.test.ts +114 -0
  29. package/src/host/__tests__/opencli-runner.test.ts +120 -0
  30. package/src/host/lib-runners.ts +70 -0
  31. package/src/host/market-index-claim.ts +9 -0
  32. package/src/host/market-index-doc.ts +62 -0
  33. package/src/host/market-index-parse.ts +482 -0
  34. package/src/host/market-index.ts +162 -357
  35. package/src/host/opencli-runner.ts +76 -0
  36. package/src/host.ts +2 -0
  37. package/src/i18n/en.ts +10 -4
  38. package/src/i18n/zh.ts +10 -4
package/dist/i18n/en.js CHANGED
@@ -129,11 +129,14 @@ export const en = {
129
129
  'panels.market.update': 'Update',
130
130
  'panels.market.swapSlow': 'Not swapped yet — maybe a slow or failed download. Press Update again; if it stays like this, restart dsh.',
131
131
  'panels.market.removeSlow': 'Not removed yet — maybe a slow network or an uninstall that did not finish. Check again in a moment; if it stays like this, restart dsh.',
132
- 'panels.market.updateNoChange': 'Update failed: still {from}. The newest on the registry is {latest} — press Update again.',
132
+ 'panels.market.updateNoChange': 'Update did not swap in: still {from}; the registry has {latest}.',
133
133
  'panels.market.updateUnknownVersion': '(unknown)',
134
134
  'panels.market.updateGone': 'Update failed: the module is gone after the update.',
135
135
  'panels.market.updateRestored': 'Update failed: the new version could not be found after the update, so {version} was put back.',
136
- 'panels.market.updateBehind': 'Installed {installed}, but the newest on the registry is {latest} — not the latest; you can update once more.',
136
+ 'panels.market.updateBehind': 'Installed {installed}, but the registry has {latest}.',
137
+ 'panels.market.updateStuck.title': 'Update did not swap in',
138
+ 'panels.market.updateStuck.factNoChange': 'Still {from} on disk; the registry has {latest}.',
139
+ 'panels.market.updateStuck.copiedHint': 'Paste it into a terminal, then restart the workbench once.',
137
140
  'panels.market.selfUpdateFailed': 'Workbench update failed: {reason}',
138
141
  'panels.market.selfUpdateUnknown': 'the outside process left no reason (see ~/.dsh/workbench/self-update.log)',
139
142
  'panels.market.selfUpdateRolledBack': 'Workbench update failed; rolled back to {version}.',
@@ -219,6 +222,7 @@ export const en = {
219
222
  'panels.market.restartNeeded': 'The new version is installed — restart once to pick it up.',
220
223
  'panels.market.foot': 'After installing, enable it in the panel page of that project.',
221
224
  'panels.market.checkUpdates': 'Check for updates',
225
+ 'panels.market.checkAll': 'Check all updates',
222
226
  'panels.market.checkingNow': 'Checking…',
223
227
  'panels.market.checkFailed': 'The last check failed. Check your connection and retry.',
224
228
  'panels.market.checkedAt': 'Last checked: {time}',
@@ -283,6 +287,8 @@ export const en = {
283
287
  'panels.market.add.failurePermission': 'No write permission, cannot install',
284
288
  'panels.market.add.failureBuildBlocked': 'A dependency wants to run install scripts; you have to allow it first',
285
289
  'panels.market.add.failureIntegrity': 'The downloaded package failed its integrity check',
290
+ 'panels.market.add.failureStopProfile': 'The old copy is still in use (the workbench has this module loaded), so this dsh version will not overwrite it in place.',
291
+ 'panels.market.add.failureCancelled': 'This run was cancelled and nothing changed.',
286
292
  'panels.market.add.failureTimeout': 'The install timed out',
287
293
  'panels.market.add.failurePnpmMissing': 'pnpm was not found, cannot install',
288
294
  'panels.market.add.failureInstalled': 'It is already installed in this workbench. The same package cannot be installed over itself: uninstall it first, then install again. The uninstall did not succeed this time.',
@@ -366,7 +372,7 @@ export const en = {
366
372
  'panels.discover.missingIndex': 'This repository has no {path} yet.',
367
373
  'panels.discover.initTitle': 'Initialize this repository as a module market index?',
368
374
  'panels.discover.initCta': 'Initialize market index',
369
- 'panels.discover.initWhat': 'It will write market.json and README.md on {branch}, commit once, and push. Modules you publish from this workbench will commit their build files under packages/<package-name>/. The repository stays owned by its owner.',
375
+ 'panels.discover.initWhat': 'It will write the index directory market/ and README.md on {branch}, commit once, and push. Modules you publish from this workbench will commit their build files under artifacts/<package-name>/<version>/ and their entry under market/<package-name>/<version>.json. The repository stays owned by its owner.',
370
376
  'panels.discover.initBranch': 'Branch',
371
377
  'panels.discover.initBranchHint': 'The index and build files go to this branch; an empty repository gets it created.',
372
378
  'panels.discover.initBranchBad': 'Use only letters, digits, dots, underscores, slashes, or dashes in a branch name.',
@@ -711,7 +717,7 @@ export const en = {
711
717
  'approval.publish.artifacts': 'Build files',
712
718
  'approval.publish.index': 'Index',
713
719
  'approval.publish.commits': 'Commits',
714
- 'approval.publish.twoCommits': 'build files + market.json in 2 commits, one push',
720
+ 'approval.publish.twoCommits': 'build files + entry file in 2 commits, one push',
715
721
  'approval.publish.reading': 'Reading…',
716
722
  'approval.publish.changelog': 'Changelog for {version}',
717
723
  'approval.publish.changelogPending': 'This release writes the {version} changelog entry',
@@ -139,11 +139,14 @@ export declare const dictionaries: {
139
139
  readonly 'panels.market.update': "更新";
140
140
  readonly 'panels.market.swapSlow': "还没换上:可能网慢或没装上。再点一次「更新」;一直这样就把 dsh 重启一遍。";
141
141
  readonly 'panels.market.removeSlow': "还没卸掉:可能网慢或卸载没走完。等一下再看;一直这样就把 dsh 重启一遍。";
142
- readonly 'panels.market.updateNoChange': "更新失败:还是 {from};源上最新是 {latest},可以再点一次「更新」。";
142
+ readonly 'panels.market.updateNoChange': "更新没换上:还是 {from};源上最新是 {latest}。";
143
143
  readonly 'panels.market.updateUnknownVersion': "(问不到)";
144
144
  readonly 'panels.market.updateGone': "更新失败:更新后找不到这个模块。";
145
145
  readonly 'panels.market.updateRestored': "更新失败:更新后找不到新版本,已把 {version} 装回去。";
146
- readonly 'panels.market.updateBehind': "装上了 {installed},但源上最新是 {latest} —— 没更到最新,可以再点一次。";
146
+ readonly 'panels.market.updateBehind': "装上了 {installed},但源上最新是 {latest}。";
147
+ readonly 'panels.market.updateStuck.title': "更新没换上";
148
+ readonly 'panels.market.updateStuck.factNoChange': "盘上还是 {from};源上最新是 {latest}。";
149
+ readonly 'panels.market.updateStuck.copiedHint': "粘到终端跑一次,跑完重启一次工作台。";
147
150
  readonly 'panels.market.selfUpdateFailed': "工作台更新失败:{reason}";
148
151
  readonly 'panels.market.selfUpdateUnknown': "外部进程没留下原因(看 ~/.dsh/workbench/self-update.log)";
149
152
  readonly 'panels.market.selfUpdateRolledBack': "工作台更新失败,已回滚到 {version}。";
@@ -229,6 +232,7 @@ export declare const dictionaries: {
229
232
  readonly 'panels.market.restartNeeded': "新版装好了,重启一次才生效。";
230
233
  readonly 'panels.market.foot': "装好后到那个项目的面板页勾选它,模块才会出现。";
231
234
  readonly 'panels.market.checkUpdates': "检查更新";
235
+ readonly 'panels.market.checkAll': "检查全部更新";
232
236
  readonly 'panels.market.checkingNow': "正在检查…";
233
237
  readonly 'panels.market.checkFailed': "最近一次没查到,检查网络后重试";
234
238
  readonly 'panels.market.checkedAt': "最近检查:{time}";
@@ -293,6 +297,8 @@ export declare const dictionaries: {
293
297
  readonly 'panels.market.add.failurePermission': "没有写入权限,无法安装";
294
298
  readonly 'panels.market.add.failureBuildBlocked': "有依赖的安装脚本需要你允许后才能继续";
295
299
  readonly 'panels.market.add.failureIntegrity': "下载的安装包校验失败";
300
+ readonly 'panels.market.add.failureStopProfile': "旧版还在用着(工作台正加载这个模块),这一版 dsh 不肯就地覆盖。";
301
+ readonly 'panels.market.add.failureCancelled': "这次操作被取消了,什么都没动。";
296
302
  readonly 'panels.market.add.failureTimeout': "安装超时";
297
303
  readonly 'panels.market.add.failurePnpmMissing': "没有找到 pnpm,无法安装";
298
304
  readonly 'panels.market.add.failureInstalled': "它已经装在这份工作台里了。同一个包不能就地覆盖,得先卸载再装;这次卸载也没成功。";
@@ -376,7 +382,7 @@ export declare const dictionaries: {
376
382
  readonly 'panels.discover.missingIndex': "仓库里还没有索引文件 {path}";
377
383
  readonly 'panels.discover.initTitle': "把这个仓库初始化成模块市场索引?";
378
384
  readonly 'panels.discover.initCta': "初始化成市场索引";
379
- readonly 'panels.discover.initWhat': "会在 {branch} 分支写 market.json 与 README.md,提交一次并推上去;之后从这个工作台发布的模块会把打包好的文件提交到按包名分的 packages/<包名>/。仓库的写权限归它的所有者。";
385
+ readonly 'panels.discover.initWhat': "会在 {branch} 分支写索引目录 market/ 与 README.md,提交一次并推上去;之后从这个工作台发布的模块会把打包好的文件提交到 artifacts/<包名>/<版本>/,条目写到 market/<包名>/<版本>.json。仓库的写权限归它的所有者。";
380
386
  readonly 'panels.discover.initBranch': "分支";
381
387
  readonly 'panels.discover.initBranchHint': "索引和打包文件都发到这个分支;空仓库会新建它。";
382
388
  readonly 'panels.discover.initBranchBad': "分支名只能用字母、数字、点、下划线、斜杠或短横线";
@@ -721,7 +727,7 @@ export declare const dictionaries: {
721
727
  readonly 'approval.publish.artifacts': "打包文件";
722
728
  readonly 'approval.publish.index': "索引";
723
729
  readonly 'approval.publish.commits': "提交";
724
- readonly 'approval.publish.twoCommits': "打包文件 + market.json 两次提交,一次推送";
730
+ readonly 'approval.publish.twoCommits': "打包文件 + 条目文件两次提交,一次推送";
725
731
  readonly 'approval.publish.reading': "读取中…";
726
732
  readonly 'approval.publish.changelog': "{version} 的更新日志";
727
733
  readonly 'approval.publish.changelogPending': "{version} 这一版会写进更新日志,随包发布";
@@ -797,7 +803,7 @@ export declare const dictionaries: {
797
803
  readonly 'configSync.emptyProviders': "工作台还没有任何模型供应商 —— 去「配置同步」从某个 profile 把模型供应商那几行同步过来,或自己去「模型」里配。";
798
804
  readonly 'configSync.failed': "同步没成功,再试一次。";
799
805
  };
800
- 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" | "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.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.askAgent" | "panels.market.askAgentCopied" | "panels.market.askAgentText" | "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.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.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.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.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.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.toolchain.ok" | "env.toolchain.warn" | "env.opencli.ok" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.hold" | "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.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.opencli" | "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.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>;
806
+ 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" | "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.askAgent" | "panels.market.askAgentCopied" | "panels.market.askAgentText" | "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.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.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.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.toolchain.ok" | "env.toolchain.warn" | "env.opencli.ok" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.hold" | "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.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.opencli" | "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.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>;
801
807
  };
802
808
  /** 中文词表的键类型(从 `zh.ts` 转出):`en` 与模块词表都得覆盖同一批键。 */
803
809
  export type { WorkbenchMessages };
package/dist/i18n/zh.d.ts CHANGED
@@ -137,11 +137,14 @@ export declare const zh: {
137
137
  readonly 'panels.market.update': "更新";
138
138
  readonly 'panels.market.swapSlow': "还没换上:可能网慢或没装上。再点一次「更新」;一直这样就把 dsh 重启一遍。";
139
139
  readonly 'panels.market.removeSlow': "还没卸掉:可能网慢或卸载没走完。等一下再看;一直这样就把 dsh 重启一遍。";
140
- readonly 'panels.market.updateNoChange': "更新失败:还是 {from};源上最新是 {latest},可以再点一次「更新」。";
140
+ readonly 'panels.market.updateNoChange': "更新没换上:还是 {from};源上最新是 {latest}。";
141
141
  readonly 'panels.market.updateUnknownVersion': "(问不到)";
142
142
  readonly 'panels.market.updateGone': "更新失败:更新后找不到这个模块。";
143
143
  readonly 'panels.market.updateRestored': "更新失败:更新后找不到新版本,已把 {version} 装回去。";
144
- readonly 'panels.market.updateBehind': "装上了 {installed},但源上最新是 {latest} —— 没更到最新,可以再点一次。";
144
+ readonly 'panels.market.updateBehind': "装上了 {installed},但源上最新是 {latest}。";
145
+ readonly 'panels.market.updateStuck.title': "更新没换上";
146
+ readonly 'panels.market.updateStuck.factNoChange': "盘上还是 {from};源上最新是 {latest}。";
147
+ readonly 'panels.market.updateStuck.copiedHint': "粘到终端跑一次,跑完重启一次工作台。";
145
148
  readonly 'panels.market.selfUpdateFailed': "工作台更新失败:{reason}";
146
149
  readonly 'panels.market.selfUpdateUnknown': "外部进程没留下原因(看 ~/.dsh/workbench/self-update.log)";
147
150
  readonly 'panels.market.selfUpdateRolledBack': "工作台更新失败,已回滚到 {version}。";
@@ -227,6 +230,7 @@ export declare const zh: {
227
230
  readonly 'panels.market.restartNeeded': "新版装好了,重启一次才生效。";
228
231
  readonly 'panels.market.foot': "装好后到那个项目的面板页勾选它,模块才会出现。";
229
232
  readonly 'panels.market.checkUpdates': "检查更新";
233
+ readonly 'panels.market.checkAll': "检查全部更新";
230
234
  readonly 'panels.market.checkingNow': "正在检查…";
231
235
  readonly 'panels.market.checkFailed': "最近一次没查到,检查网络后重试";
232
236
  readonly 'panels.market.checkedAt': "最近检查:{time}";
@@ -291,6 +295,8 @@ export declare const zh: {
291
295
  readonly 'panels.market.add.failurePermission': "没有写入权限,无法安装";
292
296
  readonly 'panels.market.add.failureBuildBlocked': "有依赖的安装脚本需要你允许后才能继续";
293
297
  readonly 'panels.market.add.failureIntegrity': "下载的安装包校验失败";
298
+ readonly 'panels.market.add.failureStopProfile': "旧版还在用着(工作台正加载这个模块),这一版 dsh 不肯就地覆盖。";
299
+ readonly 'panels.market.add.failureCancelled': "这次操作被取消了,什么都没动。";
294
300
  readonly 'panels.market.add.failureTimeout': "安装超时";
295
301
  readonly 'panels.market.add.failurePnpmMissing': "没有找到 pnpm,无法安装";
296
302
  readonly 'panels.market.add.failureInstalled': "它已经装在这份工作台里了。同一个包不能就地覆盖,得先卸载再装;这次卸载也没成功。";
@@ -374,7 +380,7 @@ export declare const zh: {
374
380
  readonly 'panels.discover.missingIndex': "仓库里还没有索引文件 {path}";
375
381
  readonly 'panels.discover.initTitle': "把这个仓库初始化成模块市场索引?";
376
382
  readonly 'panels.discover.initCta': "初始化成市场索引";
377
- readonly 'panels.discover.initWhat': "会在 {branch} 分支写 market.json 与 README.md,提交一次并推上去;之后从这个工作台发布的模块会把打包好的文件提交到按包名分的 packages/<包名>/。仓库的写权限归它的所有者。";
383
+ readonly 'panels.discover.initWhat': "会在 {branch} 分支写索引目录 market/ 与 README.md,提交一次并推上去;之后从这个工作台发布的模块会把打包好的文件提交到 artifacts/<包名>/<版本>/,条目写到 market/<包名>/<版本>.json。仓库的写权限归它的所有者。";
378
384
  readonly 'panels.discover.initBranch': "分支";
379
385
  readonly 'panels.discover.initBranchHint': "索引和打包文件都发到这个分支;空仓库会新建它。";
380
386
  readonly 'panels.discover.initBranchBad': "分支名只能用字母、数字、点、下划线、斜杠或短横线";
@@ -719,7 +725,7 @@ export declare const zh: {
719
725
  readonly 'approval.publish.artifacts': "打包文件";
720
726
  readonly 'approval.publish.index': "索引";
721
727
  readonly 'approval.publish.commits': "提交";
722
- readonly 'approval.publish.twoCommits': "打包文件 + market.json 两次提交,一次推送";
728
+ readonly 'approval.publish.twoCommits': "打包文件 + 条目文件两次提交,一次推送";
723
729
  readonly 'approval.publish.reading': "读取中…";
724
730
  readonly 'approval.publish.changelog': "{version} 的更新日志";
725
731
  readonly 'approval.publish.changelogPending': "{version} 这一版会写进更新日志,随包发布";
package/dist/i18n/zh.js CHANGED
@@ -129,11 +129,14 @@ export const zh = {
129
129
  'panels.market.update': '更新',
130
130
  'panels.market.swapSlow': '还没换上:可能网慢或没装上。再点一次「更新」;一直这样就把 dsh 重启一遍。',
131
131
  'panels.market.removeSlow': '还没卸掉:可能网慢或卸载没走完。等一下再看;一直这样就把 dsh 重启一遍。',
132
- 'panels.market.updateNoChange': '更新失败:还是 {from};源上最新是 {latest},可以再点一次「更新」。',
132
+ 'panels.market.updateNoChange': '更新没换上:还是 {from};源上最新是 {latest}。',
133
133
  'panels.market.updateUnknownVersion': '(问不到)',
134
134
  'panels.market.updateGone': '更新失败:更新后找不到这个模块。',
135
135
  'panels.market.updateRestored': '更新失败:更新后找不到新版本,已把 {version} 装回去。',
136
- 'panels.market.updateBehind': '装上了 {installed},但源上最新是 {latest} —— 没更到最新,可以再点一次。',
136
+ 'panels.market.updateBehind': '装上了 {installed},但源上最新是 {latest}。',
137
+ 'panels.market.updateStuck.title': '更新没换上',
138
+ 'panels.market.updateStuck.factNoChange': '盘上还是 {from};源上最新是 {latest}。',
139
+ 'panels.market.updateStuck.copiedHint': '粘到终端跑一次,跑完重启一次工作台。',
137
140
  'panels.market.selfUpdateFailed': '工作台更新失败:{reason}',
138
141
  'panels.market.selfUpdateUnknown': '外部进程没留下原因(看 ~/.dsh/workbench/self-update.log)',
139
142
  'panels.market.selfUpdateRolledBack': '工作台更新失败,已回滚到 {version}。',
@@ -219,6 +222,7 @@ export const zh = {
219
222
  'panels.market.restartNeeded': '新版装好了,重启一次才生效。',
220
223
  'panels.market.foot': '装好后到那个项目的面板页勾选它,模块才会出现。',
221
224
  'panels.market.checkUpdates': '检查更新',
225
+ 'panels.market.checkAll': '检查全部更新',
222
226
  'panels.market.checkingNow': '正在检查…',
223
227
  'panels.market.checkFailed': '最近一次没查到,检查网络后重试',
224
228
  'panels.market.checkedAt': '最近检查:{time}',
@@ -283,6 +287,8 @@ export const zh = {
283
287
  'panels.market.add.failurePermission': '没有写入权限,无法安装',
284
288
  'panels.market.add.failureBuildBlocked': '有依赖的安装脚本需要你允许后才能继续',
285
289
  'panels.market.add.failureIntegrity': '下载的安装包校验失败',
290
+ 'panels.market.add.failureStopProfile': '旧版还在用着(工作台正加载这个模块),这一版 dsh 不肯就地覆盖。',
291
+ 'panels.market.add.failureCancelled': '这次操作被取消了,什么都没动。',
286
292
  'panels.market.add.failureTimeout': '安装超时',
287
293
  'panels.market.add.failurePnpmMissing': '没有找到 pnpm,无法安装',
288
294
  'panels.market.add.failureInstalled': '它已经装在这份工作台里了。同一个包不能就地覆盖,得先卸载再装;这次卸载也没成功。',
@@ -366,7 +372,7 @@ export const zh = {
366
372
  'panels.discover.missingIndex': '仓库里还没有索引文件 {path}',
367
373
  'panels.discover.initTitle': '把这个仓库初始化成模块市场索引?',
368
374
  'panels.discover.initCta': '初始化成市场索引',
369
- 'panels.discover.initWhat': '会在 {branch} 分支写 market.json 与 README.md,提交一次并推上去;之后从这个工作台发布的模块会把打包好的文件提交到按包名分的 packages/<包名>/。仓库的写权限归它的所有者。',
375
+ 'panels.discover.initWhat': '会在 {branch} 分支写索引目录 market/ 与 README.md,提交一次并推上去;之后从这个工作台发布的模块会把打包好的文件提交到 artifacts/<包名>/<版本>/,条目写到 market/<包名>/<版本>.json。仓库的写权限归它的所有者。',
370
376
  'panels.discover.initBranch': '分支',
371
377
  'panels.discover.initBranchHint': '索引和打包文件都发到这个分支;空仓库会新建它。',
372
378
  'panels.discover.initBranchBad': '分支名只能用字母、数字、点、下划线、斜杠或短横线',
@@ -711,7 +717,7 @@ export const zh = {
711
717
  'approval.publish.artifacts': '打包文件',
712
718
  'approval.publish.index': '索引',
713
719
  'approval.publish.commits': '提交',
714
- 'approval.publish.twoCommits': '打包文件 + market.json 两次提交,一次推送',
720
+ 'approval.publish.twoCommits': '打包文件 + 条目文件两次提交,一次推送',
715
721
  'approval.publish.reading': '读取中…',
716
722
  'approval.publish.changelog': '{version} 的更新日志',
717
723
  'approval.publish.changelogPending': '{version} 这一版会写进更新日志,随包发布',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-workbench/shared",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "description": "工作台与模块共享的纯代码与契约类型:类型、纯逻辑、哑组件、平台解析。宿主侧的东西从 /host 进(不影响浏览器产物)。",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -114,6 +114,14 @@ describe('needs 校验矩阵', () => {
114
114
  expect(errorsOf({ ...base, id: '' }).join(' ')).toContain('id 是空串');
115
115
  });
116
116
 
117
+ it('lib 声明 runs(会自己起运行时的命令)→ 过;写歪了判红并点名', () => {
118
+ expect(errorsOf({ ...base, runs: ['opencli'] })).toEqual([]);
119
+ expect(errorsOf({ ...base, runs: 'opencli' }).join(' ')).toContain('.runs 要是数组');
120
+ expect(errorsOf({ ...base, runs: [] }).join(' ')).toContain('空数组');
121
+ expect(errorsOf({ ...base, runs: [''] }).join(' ')).toContain('空字符串');
122
+ expect(errorsOf({ ...base, runs: ['opencli', 'opencli'] }).join(' ')).toContain('重复');
123
+ });
124
+
117
125
  it('★ need 内未知字段只是警告;x- 前缀直接忽略(不为可选字段升协议版本)', () => {
118
126
  const read = needProblemsOf('demo', { ...base, future: 1, 'x-vendor': true }, 0);
119
127
  expect(read.errors).toEqual([]);
@@ -82,12 +82,15 @@ export interface ExtensionNeed extends NeedCommon {
82
82
 
83
83
  /**
84
84
  * 要在隔离运行时里有一个共用依赖包。
85
+ * `runs` 写它自己会起哪些运行时的命令(如 `["opencli"]`)—— 写了外壳就把那份执行器注入进去
86
+ * (库侧约定 `setOpencliRunner`);不写就按它自己在 PATH 上找。
85
87
  */
86
88
  export interface LibNeed extends NeedCommon {
87
89
  readonly kind: 'lib';
88
90
  readonly name: string;
89
91
  readonly version?: string;
90
92
  readonly sources?: readonly SupplySource[];
93
+ readonly runs?: readonly string[] | undefined;
91
94
  }
92
95
 
93
96
  /**
@@ -128,6 +131,7 @@ export const NEED_KEYS: readonly string[] = [
128
131
  'secret',
129
132
  'install',
130
133
  'docs',
134
+ 'runs',
131
135
  ];
132
136
 
133
137
  /**
@@ -267,6 +271,16 @@ export function binInstallProblemsOf(raw: unknown, at: string): readonly string[
267
271
  return errors;
268
272
  }
269
273
 
274
+ function libRunsProblemsOf(raw: unknown, at: string): readonly string[] {
275
+ if (raw === undefined) return [];
276
+ if (!Array.isArray(raw)) return [`${at}.runs 要是数组`];
277
+ if (raw.length === 0) return [`${at}.runs 是空数组 —— 不自己跑命令就整条删掉`];
278
+ const names = raw.map((one) => text(one));
279
+ if (names.some((one) => one === '')) return [`${at}.runs 里有空字符串`];
280
+ if (new Set(names).size !== names.length) return [`${at}.runs 里有重复的运行时`];
281
+ return [];
282
+ }
283
+
270
284
  function perKindProblemsOf(
271
285
  kind: NeedKind,
272
286
  raw: Readonly<Record<string, unknown>>,
@@ -278,6 +292,7 @@ function perKindProblemsOf(
278
292
  }
279
293
  if (kind === 'bin') errors.push(...binInstallProblemsOf(raw['install'], at));
280
294
  if (raw['docs'] !== undefined && text(raw['docs']) === '') errors.push(`${at}.docs 是空串`);
295
+ if (kind === 'lib') errors.push(...libRunsProblemsOf(raw['runs'], at));
281
296
  if (kind === 'extension') {
282
297
  if (text(raw['runtime']) === '') errors.push(`${at}.runtime 没写 —— 扩展属于哪个运行时(如 opencli)`);
283
298
  if (text(raw['name']) === '') errors.push(`${at}.name 没写`);
@@ -1,4 +1,6 @@
1
1
  export const MARKET_INDEX_FORMAT = 1;
2
+ export const MARKET_INDEX_DIR = 'market';
3
+ export const MARKET_ARTIFACTS_DIR = 'artifacts';
2
4
  export const MARKET_INDEX_PATH = 'market.json';
3
5
  export const MARKET_DISCOVER_ROUTE = 'panels/market-discover';
4
6
  export const MARKET_DOC_ROUTE = 'panels/market-doc';
@@ -127,11 +129,13 @@ export type MarketIndexProblemKind =
127
129
  | 'format'
128
130
  | 'plugins'
129
131
  | 'plugin'
132
+ | 'entry'
130
133
  | 'name'
131
134
  | 'duplicate-name'
132
135
  | 'versions'
133
136
  | 'version'
134
137
  | 'version-order'
138
+ | 'duplicate-version'
135
139
  | 'source'
136
140
  | 'git-commit'
137
141
  | 'timestamp'
@@ -0,0 +1,82 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import type { LibNeed } from '../../contract/needs.js';
3
+ import type { LibReader } from '../../contract/lib.js';
4
+ import type { OpencliRunner } from '../opencli-runner.js';
5
+ import { withLibRunners } from '../lib-runners.js';
6
+
7
+ const runner: OpencliRunner = async () => ({ stdout: '[]' });
8
+
9
+ function needOf(runs?: readonly string[]): LibNeed {
10
+ return {
11
+ kind: 'lib',
12
+ name: 'opencli-workflow',
13
+ purpose: '发布编排',
14
+ ...(runs === undefined ? {} : { runs }),
15
+ };
16
+ }
17
+
18
+ function libsOf(module: unknown): LibReader {
19
+ return {
20
+ async load<T = unknown>(): Promise<T> {
21
+ return module as T;
22
+ },
23
+ };
24
+ }
25
+
26
+ function logger(): { readonly warn: ReturnType<typeof vi.fn<(message: string) => void>> } {
27
+ return { warn: vi.fn<(message: string) => void>() };
28
+ }
29
+
30
+ describe('withLibRunners', () => {
31
+ it('没声明 runs → 原样返回,不注入、不记 warn', async () => {
32
+ const module = { setOpencliRunner: vi.fn() };
33
+ const warn = logger();
34
+ const libs = withLibRunners(libsOf(module), { opencli: runner }, warn);
35
+
36
+ await expect(libs.load(needOf(), 'src/utils.js')).resolves.toBe(module);
37
+ expect(module.setOpencliRunner).not.toHaveBeenCalled();
38
+ expect(warn.warn).not.toHaveBeenCalled();
39
+ });
40
+
41
+ it('声明了 opencli 且库有 setOpencliRunner → 把执行器交进去', async () => {
42
+ const module = { setOpencliRunner: vi.fn() };
43
+ const warn = logger();
44
+ const libs = withLibRunners(libsOf(module), { opencli: runner }, warn);
45
+
46
+ await expect(libs.load(needOf(['opencli']), 'src/utils.js')).resolves.toBe(module);
47
+ expect(module.setOpencliRunner).toHaveBeenCalledWith(runner);
48
+ expect(warn.warn).not.toHaveBeenCalled();
49
+ });
50
+
51
+ it('库版本旧、没有 setter → 不注入,只 warn 一次', async () => {
52
+ const module = {};
53
+ const warn = logger();
54
+ const libs = withLibRunners(libsOf(module), { opencli: runner }, warn);
55
+
56
+ await libs.load(needOf(['opencli']), 'src/utils.js');
57
+ await libs.load(needOf(['opencli']), 'src/utils.js');
58
+
59
+ expect(warn.warn).toHaveBeenCalledTimes(1);
60
+ expect(String(warn.warn.mock.calls[0]?.[0])).toContain('没有 setOpencliRunner');
61
+ });
62
+
63
+ it('声明了外壳没有的运行时 → 不注入,只 warn 一次', async () => {
64
+ const module = { setGitRunner: vi.fn() };
65
+ const warn = logger();
66
+ const libs = withLibRunners(libsOf(module), { opencli: runner }, warn);
67
+
68
+ await libs.load(needOf(['git']), 'src/utils.js');
69
+
70
+ expect(module.setGitRunner).not.toHaveBeenCalled();
71
+ expect(warn.warn).toHaveBeenCalledTimes(1);
72
+ expect(String(warn.warn.mock.calls[0]?.[0])).toContain('没有这个执行器');
73
+ });
74
+
75
+ it('模块导出不是对象(函数 / 原始值)也不炸', async () => {
76
+ const warn = logger();
77
+ const libs = withLibRunners(libsOf(() => undefined), { opencli: runner }, warn);
78
+
79
+ await expect(libs.load(needOf(['opencli']), 'src/utils.js')).resolves.toBeTypeOf('function');
80
+ expect(warn.warn).toHaveBeenCalledTimes(1);
81
+ });
82
+ });