@dsh-workbench/shared 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/i18n/en.js +13 -1
- package/dist/i18n/index.d.ts +16 -4
- package/dist/i18n/zh.d.ts +15 -3
- package/dist/i18n/zh.js +15 -3
- package/dist/lib/ui.d.ts +8 -0
- package/dist/lib/ui.js +34 -0
- package/package.json +1 -1
- package/src/i18n/en.ts +13 -1
- package/src/i18n/zh.ts +15 -3
- package/src/lib/ui.test.ts +49 -2
- package/src/lib/ui.ts +38 -0
package/dist/i18n/en.js
CHANGED
|
@@ -29,20 +29,32 @@ export const en = {
|
|
|
29
29
|
'session.new.label': 'Start a session in the current project',
|
|
30
30
|
'session.empty': 'No sessions in this project yet.',
|
|
31
31
|
'session.noProject': 'Add a project first.',
|
|
32
|
+
'session.list.label': 'Sessions',
|
|
33
|
+
'session.copy': 'Copy',
|
|
32
34
|
'session.pinned': 'Pinned',
|
|
33
35
|
'session.actions': 'Actions for {name}',
|
|
34
36
|
'status.idle': 'Idle',
|
|
35
37
|
'status.running': 'Running',
|
|
36
38
|
'status.waitingApproval': 'Waiting for approval',
|
|
37
|
-
'status.planReview': '
|
|
39
|
+
'status.planReview': 'Plan awaiting review',
|
|
38
40
|
'status.waitingAnswer': 'Waiting for your answer',
|
|
41
|
+
'status.compact.approval': 'Approval',
|
|
42
|
+
'status.compact.planReview': 'Plan review',
|
|
43
|
+
'status.compact.answer': 'Answer',
|
|
39
44
|
'status.completed': 'Completed',
|
|
40
45
|
'status.subagentsRunning.one': '{n} subagent running',
|
|
41
46
|
'status.subagentsRunning.other': '{n} subagents running',
|
|
47
|
+
'hover.copied': 'Copied',
|
|
42
48
|
'time.now': 'just now',
|
|
43
49
|
'time.minutes': '{n} min ago',
|
|
44
50
|
'time.hours': '{n} h ago',
|
|
45
51
|
'time.days': '{n} d ago',
|
|
52
|
+
'time.ago': '{t} ago',
|
|
53
|
+
'time.short.minutes': '{n}min',
|
|
54
|
+
'time.short.hours': '{n}h',
|
|
55
|
+
'time.short.days': '{n}d',
|
|
56
|
+
'time.short.months': '{n}mo',
|
|
57
|
+
'time.short.years': '{n}y',
|
|
46
58
|
'panels.title': 'Panel modules',
|
|
47
59
|
'panels.groupBoardless': 'No-board modules',
|
|
48
60
|
'panels.groupPlugins': 'opencli plugins',
|
package/dist/i18n/index.d.ts
CHANGED
|
@@ -31,20 +31,32 @@ export declare const dictionaries: {
|
|
|
31
31
|
readonly 'session.new.label': "在当前项目新建会话";
|
|
32
32
|
readonly 'session.empty': "这个项目还没有会话。";
|
|
33
33
|
readonly 'session.noProject': "先添加一个项目。";
|
|
34
|
+
readonly 'session.list.label': "会话";
|
|
35
|
+
readonly 'session.copy': "复制";
|
|
34
36
|
readonly 'session.pinned': "已置顶";
|
|
35
37
|
readonly 'session.actions': "{name} 的操作";
|
|
36
38
|
readonly 'status.idle': "空闲";
|
|
37
|
-
readonly 'status.running': "
|
|
38
|
-
readonly 'status.waitingApproval': "
|
|
39
|
-
readonly 'status.planReview': "
|
|
39
|
+
readonly 'status.running': "进行中";
|
|
40
|
+
readonly 'status.waitingApproval': "等待审批";
|
|
41
|
+
readonly 'status.planReview': "计划待审";
|
|
40
42
|
readonly 'status.waitingAnswer': "等待回答";
|
|
43
|
+
readonly 'status.compact.approval': "待审批";
|
|
44
|
+
readonly 'status.compact.planReview': "计划待审";
|
|
45
|
+
readonly 'status.compact.answer': "待回答";
|
|
41
46
|
readonly 'status.completed': "已完成";
|
|
42
47
|
readonly 'status.subagentsRunning.one': "{n} 个子代理运行中";
|
|
43
48
|
readonly 'status.subagentsRunning.other': "{n} 个子代理运行中";
|
|
49
|
+
readonly 'hover.copied': "已复制";
|
|
44
50
|
readonly 'time.now': "刚刚";
|
|
45
51
|
readonly 'time.minutes': "{n} 分钟前";
|
|
46
52
|
readonly 'time.hours': "{n} 小时前";
|
|
47
53
|
readonly 'time.days': "{n} 天前";
|
|
54
|
+
readonly 'time.ago': "{t}前";
|
|
55
|
+
readonly 'time.short.minutes': "{n}分钟";
|
|
56
|
+
readonly 'time.short.hours': "{n}小时";
|
|
57
|
+
readonly 'time.short.days': "{n}天";
|
|
58
|
+
readonly 'time.short.months': "{n}个月";
|
|
59
|
+
readonly 'time.short.years': "{n}年";
|
|
48
60
|
readonly 'panels.title': "面板模块";
|
|
49
61
|
readonly 'panels.groupBoardless': "无看板模块";
|
|
50
62
|
readonly 'panels.groupPlugins': "opencli 插件";
|
|
@@ -346,7 +358,7 @@ export declare const dictionaries: {
|
|
|
346
358
|
readonly 'panel.conversation': "对话";
|
|
347
359
|
readonly 'panels.label': "全局面板";
|
|
348
360
|
};
|
|
349
|
-
en: Record<"time.now" | "time.minutes" | "time.hours" | "time.days" | "blocker.retry" | "blocker.copy" | "blocker.unknown.title" | "blocker.login.go" | "blocker.login.titleGeneric" | "blocker.login.title" | "blocker.login.manual" | "blocker.login.hint" | "blocker.forbidden.open" | "blocker.forbidden.titleGeneric" | "blocker.forbidden.title" | "blocker.forbidden.hint" | "blocker.timeout.hint" | "blocker.exec.hint" | "blocker.fix.install" | "blocker.fix.update" | "blocker.market.open" | "env.unit.failed" | "env.unit.failedHint" | "env.unit.missingPlugin" | "env.unit.hint" | "env.unit.missingCommands" | "env.unit.missingCommandsHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "project.add.busy" | "project.add.failed" | "project.search.label" | "project.search.placeholder" | "project.search.empty" | "project.group.workspaces" | "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.pinned" | "session.actions" | "status.idle" | "status.running" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "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.dep.failed" | "panels.dep.missingPlugin" | "panels.dep.missingCommands" | "panels.dep.unchecked" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.notActive" | "panels.market.notUsable" | "panels.market.broken" | "panels.market.hasNew" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.checking" | "panels.market.sectionInstalled" | "panels.market.sectionPending" | "panels.market.sectionShared" | "panels.market.sharedUsedBy" | "panels.market.listSeparator" | "panels.market.sharedMissing" | "panels.market.sharedOutdated" | "panels.market.sharedUnsatisfied" | "panels.market.sharedOk" | "panels.market.versionArrow" | "panels.market.lead" | "panels.market.install" | "panels.market.update" | "panels.market.uninstall" | "panels.market.uninstallLabel" | "panels.market.installing" | "panels.market.updating" | "panels.market.uninstalling" | "panels.market.confirmUninstallTitle" | "panels.market.confirmUninstallDetail" | "panels.market.confirmUninstallAck" | "panels.market.confirmYes" | "panels.market.confirmNo" | "panels.market.failed" | "panels.market.needEnv" | "panels.market.needCommands" | "panels.market.localMark" | "panels.market.localHint" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.sectionPlugins" | "panels.market.moduleOutdated" | "panels.market.moduleRefused" | "panels.market.moduleRefusedDetail" | "panels.market.moduleRestartHint" | "panels.market.workbenchName" | "panels.market.workbenchLocal" | "panels.market.pluginKeptInUse" | "panels.market.pluginKeptUnsure" | "panels.market.pluginKeptHeld" | "panels.market.pluginKeptUnnamed" | "panels.market.pluginBroken" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.recheck" | "panels.market.checkUpdates" | "panels.market.checkedAt" | "panels.market.justNow" | "panels.market.minutesAgo" | "panels.market.hoursAgo" | "panels.market.add.description" | "panels.market.add.specPlaceholder" | "panels.market.add.guideToggle" | "panels.market.add.guideHide" | "panels.market.add.guideIdTitle" | "panels.market.add.guideIdExample" | "panels.market.add.guideIdHint" | "panels.market.add.guideGitTitle" | "panels.market.add.guideGitExample" | "panels.market.add.guideGitHint" | "panels.market.add.guidePathTitle" | "panels.market.add.guidePathExample" | "panels.market.add.guidePathHint" | "panels.market.add.guideExampleLabel" | "panels.market.add.guideFill" | "panels.market.add.guideSafety" | "panels.market.add.registryLegend" | "panels.market.add.registryOfficial" | "panels.market.add.registryMirror" | "panels.market.add.registryWithHost" | "panels.market.add.registryToggle" | "panels.market.add.installVersion" | "panels.market.add.registryDefault" | "panels.market.add.registryCustom" | "panels.market.add.registryCustomPlaceholder" | "panels.market.add.registryCustomHint" | "panels.market.add.registryCustomInvalid" | "panels.market.add.run" | "panels.market.add.edit" | "panels.market.add.changeRegistry" | "panels.market.add.installingTitle" | "panels.market.add.installedTitle" | "panels.market.add.failedTitle" | "panels.market.add.cancelledTitle" | "panels.market.add.failureNetworkHost" | "panels.market.add.problemInvalid" | "panels.market.add.problemInstalled" | "panels.market.add.problemNotFound" | "panels.market.add.problemNotPackage" | "panels.market.add.problemNotBundle" | "panels.market.add.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.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.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.cancelled" | "panels.market.add.failed" | "panels.market.add.removed" | "panels.market.add.supplyPending" | "panels.market.add.supplyFailed" | "panels.market.add.notModule" | "panels.market.add.removedRestart" | "panels.market.add.remove" | "panels.market.add.problem.invalidSpec" | "panels.market.add.problem.alreadyInstalled" | "panels.market.add.problem.notFound" | "panels.market.add.problem.notAPackage" | "panels.market.add.problem.notABundle" | "panels.market.add.problem.network" | "panels.market.add.problem.unknown" | "panels.market.add.reason.invalidSpec" | "panels.market.add.reason.incompatible" | "panels.market.add.reason.notBundle" | "panels.market.add.reason.notRemovable" | "panels.market.add.reason.bundleInUse" | "panels.market.add.reason.stopProfile" | "panels.market.add.reason.staleApproval" | "panels.market.add.reason.operationError" | "panels.market.add.reason.buildBlocked" | "panels.market.add.reason.pnpmMissing" | "panels.market.add.reason.noMatchingVersion" | "panels.market.add.reason.diskFull" | "panels.market.add.reason.permission" | "panels.market.add.reason.integrity" | "panels.market.add.reason.timeout" | "panels.market.add.reason.network" | "panels.market.add.reason.notFound" | "panels.market.add.reason.unknown" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.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.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.daemon" | "env.bridge.extension" | "env.bridge.extensionLink" | "env.bridge.profile" | "env.bridge.stale" | "env.bridge.unknown" | "env.fix.title" | "env.fix.why" | "env.fix.whyPath" | "env.fix.whyShell" | "env.fix.step" | "env.fix.stepPath" | "env.fix.stepShell" | "env.fix.permission" | "env.fix.network" | "env.fix.details" | "env.retry" | "env.copyCommand" | "env.copied" | "env.step.opencli" | "env.step.codingPlugin" | "env.step.bridge" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.column.label" | "rightbar.column.workbench" | "rightbar.column.dsh" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "rightbar.openPlatform" | "coding.notARepo.title" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label", string>;
|
|
361
|
+
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.fix.update" | "blocker.market.open" | "env.unit.failed" | "env.unit.failedHint" | "env.unit.missingPlugin" | "env.unit.hint" | "env.unit.missingCommands" | "env.unit.missingCommandsHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "project.add.busy" | "project.add.failed" | "project.search.label" | "project.search.placeholder" | "project.search.empty" | "project.group.workspaces" | "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.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.compact.approval" | "status.compact.planReview" | "status.compact.answer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "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.dep.failed" | "panels.dep.missingPlugin" | "panels.dep.missingCommands" | "panels.dep.unchecked" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.notActive" | "panels.market.notUsable" | "panels.market.broken" | "panels.market.hasNew" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.checking" | "panels.market.sectionInstalled" | "panels.market.sectionPending" | "panels.market.sectionShared" | "panels.market.sharedUsedBy" | "panels.market.listSeparator" | "panels.market.sharedMissing" | "panels.market.sharedOutdated" | "panels.market.sharedUnsatisfied" | "panels.market.sharedOk" | "panels.market.versionArrow" | "panels.market.lead" | "panels.market.install" | "panels.market.update" | "panels.market.uninstall" | "panels.market.uninstallLabel" | "panels.market.installing" | "panels.market.updating" | "panels.market.uninstalling" | "panels.market.confirmUninstallTitle" | "panels.market.confirmUninstallDetail" | "panels.market.confirmUninstallAck" | "panels.market.confirmYes" | "panels.market.confirmNo" | "panels.market.failed" | "panels.market.needEnv" | "panels.market.needCommands" | "panels.market.localMark" | "panels.market.localHint" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.sectionPlugins" | "panels.market.moduleOutdated" | "panels.market.moduleRefused" | "panels.market.moduleRefusedDetail" | "panels.market.moduleRestartHint" | "panels.market.workbenchName" | "panels.market.workbenchLocal" | "panels.market.pluginKeptInUse" | "panels.market.pluginKeptUnsure" | "panels.market.pluginKeptHeld" | "panels.market.pluginKeptUnnamed" | "panels.market.pluginBroken" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.recheck" | "panels.market.checkUpdates" | "panels.market.checkedAt" | "panels.market.justNow" | "panels.market.minutesAgo" | "panels.market.hoursAgo" | "panels.market.add.description" | "panels.market.add.specPlaceholder" | "panels.market.add.guideToggle" | "panels.market.add.guideHide" | "panels.market.add.guideIdTitle" | "panels.market.add.guideIdExample" | "panels.market.add.guideIdHint" | "panels.market.add.guideGitTitle" | "panels.market.add.guideGitExample" | "panels.market.add.guideGitHint" | "panels.market.add.guidePathTitle" | "panels.market.add.guidePathExample" | "panels.market.add.guidePathHint" | "panels.market.add.guideExampleLabel" | "panels.market.add.guideFill" | "panels.market.add.guideSafety" | "panels.market.add.registryLegend" | "panels.market.add.registryOfficial" | "panels.market.add.registryMirror" | "panels.market.add.registryWithHost" | "panels.market.add.registryToggle" | "panels.market.add.installVersion" | "panels.market.add.registryDefault" | "panels.market.add.registryCustom" | "panels.market.add.registryCustomPlaceholder" | "panels.market.add.registryCustomHint" | "panels.market.add.registryCustomInvalid" | "panels.market.add.run" | "panels.market.add.edit" | "panels.market.add.changeRegistry" | "panels.market.add.installingTitle" | "panels.market.add.installedTitle" | "panels.market.add.failedTitle" | "panels.market.add.cancelledTitle" | "panels.market.add.failureNetworkHost" | "panels.market.add.problemInvalid" | "panels.market.add.problemInstalled" | "panels.market.add.problemNotFound" | "panels.market.add.problemNotPackage" | "panels.market.add.problemNotBundle" | "panels.market.add.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.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.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.cancelled" | "panels.market.add.failed" | "panels.market.add.removed" | "panels.market.add.supplyPending" | "panels.market.add.supplyFailed" | "panels.market.add.notModule" | "panels.market.add.removedRestart" | "panels.market.add.remove" | "panels.market.add.problem.invalidSpec" | "panels.market.add.problem.alreadyInstalled" | "panels.market.add.problem.notFound" | "panels.market.add.problem.notAPackage" | "panels.market.add.problem.notABundle" | "panels.market.add.problem.network" | "panels.market.add.problem.unknown" | "panels.market.add.reason.invalidSpec" | "panels.market.add.reason.incompatible" | "panels.market.add.reason.notBundle" | "panels.market.add.reason.notRemovable" | "panels.market.add.reason.bundleInUse" | "panels.market.add.reason.stopProfile" | "panels.market.add.reason.staleApproval" | "panels.market.add.reason.operationError" | "panels.market.add.reason.buildBlocked" | "panels.market.add.reason.pnpmMissing" | "panels.market.add.reason.noMatchingVersion" | "panels.market.add.reason.diskFull" | "panels.market.add.reason.permission" | "panels.market.add.reason.integrity" | "panels.market.add.reason.timeout" | "panels.market.add.reason.network" | "panels.market.add.reason.notFound" | "panels.market.add.reason.unknown" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.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.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.daemon" | "env.bridge.extension" | "env.bridge.extensionLink" | "env.bridge.profile" | "env.bridge.stale" | "env.bridge.unknown" | "env.fix.title" | "env.fix.why" | "env.fix.whyPath" | "env.fix.whyShell" | "env.fix.step" | "env.fix.stepPath" | "env.fix.stepShell" | "env.fix.permission" | "env.fix.network" | "env.fix.details" | "env.retry" | "env.copyCommand" | "env.copied" | "env.step.opencli" | "env.step.codingPlugin" | "env.step.bridge" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.column.label" | "rightbar.column.workbench" | "rightbar.column.dsh" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "rightbar.openPlatform" | "coding.notARepo.title" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label", string>;
|
|
350
362
|
};
|
|
351
363
|
export type { WorkbenchMessages };
|
|
352
364
|
export interface Dictionaries {
|
package/dist/i18n/zh.d.ts
CHANGED
|
@@ -29,20 +29,32 @@ export declare const zh: {
|
|
|
29
29
|
readonly 'session.new.label': "在当前项目新建会话";
|
|
30
30
|
readonly 'session.empty': "这个项目还没有会话。";
|
|
31
31
|
readonly 'session.noProject': "先添加一个项目。";
|
|
32
|
+
readonly 'session.list.label': "会话";
|
|
33
|
+
readonly 'session.copy': "复制";
|
|
32
34
|
readonly 'session.pinned': "已置顶";
|
|
33
35
|
readonly 'session.actions': "{name} 的操作";
|
|
34
36
|
readonly 'status.idle': "空闲";
|
|
35
|
-
readonly 'status.running': "
|
|
36
|
-
readonly 'status.waitingApproval': "
|
|
37
|
-
readonly 'status.planReview': "
|
|
37
|
+
readonly 'status.running': "进行中";
|
|
38
|
+
readonly 'status.waitingApproval': "等待审批";
|
|
39
|
+
readonly 'status.planReview': "计划待审";
|
|
38
40
|
readonly 'status.waitingAnswer': "等待回答";
|
|
41
|
+
readonly 'status.compact.approval': "待审批";
|
|
42
|
+
readonly 'status.compact.planReview': "计划待审";
|
|
43
|
+
readonly 'status.compact.answer': "待回答";
|
|
39
44
|
readonly 'status.completed': "已完成";
|
|
40
45
|
readonly 'status.subagentsRunning.one': "{n} 个子代理运行中";
|
|
41
46
|
readonly 'status.subagentsRunning.other': "{n} 个子代理运行中";
|
|
47
|
+
readonly 'hover.copied': "已复制";
|
|
42
48
|
readonly 'time.now': "刚刚";
|
|
43
49
|
readonly 'time.minutes': "{n} 分钟前";
|
|
44
50
|
readonly 'time.hours': "{n} 小时前";
|
|
45
51
|
readonly 'time.days': "{n} 天前";
|
|
52
|
+
readonly 'time.ago': "{t}前";
|
|
53
|
+
readonly 'time.short.minutes': "{n}分钟";
|
|
54
|
+
readonly 'time.short.hours': "{n}小时";
|
|
55
|
+
readonly 'time.short.days': "{n}天";
|
|
56
|
+
readonly 'time.short.months': "{n}个月";
|
|
57
|
+
readonly 'time.short.years': "{n}年";
|
|
46
58
|
readonly 'panels.title': "面板模块";
|
|
47
59
|
readonly 'panels.groupBoardless': "无看板模块";
|
|
48
60
|
readonly 'panels.groupPlugins': "opencli 插件";
|
package/dist/i18n/zh.js
CHANGED
|
@@ -29,20 +29,32 @@ export const zh = {
|
|
|
29
29
|
'session.new.label': '在当前项目新建会话',
|
|
30
30
|
'session.empty': '这个项目还没有会话。',
|
|
31
31
|
'session.noProject': '先添加一个项目。',
|
|
32
|
+
'session.list.label': '会话',
|
|
33
|
+
'session.copy': '复制',
|
|
32
34
|
'session.pinned': '已置顶',
|
|
33
35
|
'session.actions': '{name} 的操作',
|
|
34
36
|
'status.idle': '空闲',
|
|
35
|
-
'status.running': '
|
|
36
|
-
'status.waitingApproval': '
|
|
37
|
-
'status.planReview': '
|
|
37
|
+
'status.running': '进行中',
|
|
38
|
+
'status.waitingApproval': '等待审批',
|
|
39
|
+
'status.planReview': '计划待审',
|
|
38
40
|
'status.waitingAnswer': '等待回答',
|
|
41
|
+
'status.compact.approval': '待审批',
|
|
42
|
+
'status.compact.planReview': '计划待审',
|
|
43
|
+
'status.compact.answer': '待回答',
|
|
39
44
|
'status.completed': '已完成',
|
|
40
45
|
'status.subagentsRunning.one': '{n} 个子代理运行中',
|
|
41
46
|
'status.subagentsRunning.other': '{n} 个子代理运行中',
|
|
47
|
+
'hover.copied': '已复制',
|
|
42
48
|
'time.now': '刚刚',
|
|
43
49
|
'time.minutes': '{n} 分钟前',
|
|
44
50
|
'time.hours': '{n} 小时前',
|
|
45
51
|
'time.days': '{n} 天前',
|
|
52
|
+
'time.ago': '{t}前',
|
|
53
|
+
'time.short.minutes': '{n}分钟',
|
|
54
|
+
'time.short.hours': '{n}小时',
|
|
55
|
+
'time.short.days': '{n}天',
|
|
56
|
+
'time.short.months': '{n}个月',
|
|
57
|
+
'time.short.years': '{n}年',
|
|
46
58
|
'panels.title': '面板模块',
|
|
47
59
|
'panels.groupBoardless': '无看板模块',
|
|
48
60
|
'panels.groupPlugins': 'opencli 插件',
|
package/dist/lib/ui.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
export declare function cx(...parts: Array<string | false | null | undefined>): string;
|
|
2
2
|
export type TimeTranslate = (key: string, params?: Record<string, unknown>) => string;
|
|
3
|
+
export type RelativeTimeUnit = 'now' | 'minutes' | 'hours' | 'days' | 'months' | 'years';
|
|
4
|
+
export interface RelativeTimeBucket {
|
|
5
|
+
readonly unit: RelativeTimeUnit;
|
|
6
|
+
readonly n: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function relativeTimeBucket(epochMs: number, now?: number): RelativeTimeBucket | null;
|
|
9
|
+
export declare function relativeTimeCompact(epochMs: number, t: TimeTranslate, now?: number): string;
|
|
10
|
+
export declare function relativeTimeAgo(epochMs: number, t: TimeTranslate, now?: number): string;
|
|
3
11
|
export declare function relativeTime(epochMs: number, t: TimeTranslate): string;
|
|
4
12
|
export declare function shortenPath(path: unknown): string;
|
|
5
13
|
export declare function parseLocalTimestamp(text: string | null | undefined): number;
|
package/dist/lib/ui.js
CHANGED
|
@@ -2,6 +2,40 @@ export function cx(...parts) {
|
|
|
2
2
|
return parts.filter(Boolean).join(' ');
|
|
3
3
|
}
|
|
4
4
|
const MINUTE = 60 * 1000;
|
|
5
|
+
const HOUR = 60 * MINUTE;
|
|
6
|
+
const DAY = 24 * HOUR;
|
|
7
|
+
const MONTH = 30 * DAY;
|
|
8
|
+
const YEAR = 365 * DAY;
|
|
9
|
+
export function relativeTimeBucket(epochMs, now = Date.now()) {
|
|
10
|
+
if (!Number.isFinite(epochMs) || !Number.isFinite(now))
|
|
11
|
+
return null;
|
|
12
|
+
const diff = Math.max(0, now - epochMs);
|
|
13
|
+
if (diff < MINUTE)
|
|
14
|
+
return { unit: 'now', n: 0 };
|
|
15
|
+
if (diff < HOUR)
|
|
16
|
+
return { unit: 'minutes', n: Math.floor(diff / MINUTE) };
|
|
17
|
+
if (diff < DAY)
|
|
18
|
+
return { unit: 'hours', n: Math.floor(diff / HOUR) };
|
|
19
|
+
if (diff < MONTH)
|
|
20
|
+
return { unit: 'days', n: Math.floor(diff / DAY) };
|
|
21
|
+
if (diff < YEAR)
|
|
22
|
+
return { unit: 'months', n: Math.floor(diff / MONTH) };
|
|
23
|
+
return { unit: 'years', n: Math.floor(diff / YEAR) };
|
|
24
|
+
}
|
|
25
|
+
function bucketLabel(bucket, t) {
|
|
26
|
+
return bucket.unit === 'now' ? t('time.now') : t(`time.short.${bucket.unit}`, { n: bucket.n });
|
|
27
|
+
}
|
|
28
|
+
export function relativeTimeCompact(epochMs, t, now) {
|
|
29
|
+
const bucket = relativeTimeBucket(epochMs, now);
|
|
30
|
+
return bucket === null ? '' : bucketLabel(bucket, t);
|
|
31
|
+
}
|
|
32
|
+
export function relativeTimeAgo(epochMs, t, now) {
|
|
33
|
+
const bucket = relativeTimeBucket(epochMs, now);
|
|
34
|
+
if (bucket === null)
|
|
35
|
+
return '';
|
|
36
|
+
const label = bucketLabel(bucket, t);
|
|
37
|
+
return bucket.unit === 'now' ? label : t('time.ago', { t: label });
|
|
38
|
+
}
|
|
5
39
|
export function relativeTime(epochMs, t) {
|
|
6
40
|
if (!Number.isFinite(epochMs))
|
|
7
41
|
return '';
|
package/package.json
CHANGED
package/src/i18n/en.ts
CHANGED
|
@@ -32,21 +32,33 @@ export const en: Record<keyof WorkbenchMessages, string> = {
|
|
|
32
32
|
'session.new.label': 'Start a session in the current project',
|
|
33
33
|
'session.empty': 'No sessions in this project yet.',
|
|
34
34
|
'session.noProject': 'Add a project first.',
|
|
35
|
+
'session.list.label': 'Sessions',
|
|
36
|
+
'session.copy': 'Copy',
|
|
35
37
|
'session.pinned': 'Pinned',
|
|
36
38
|
'session.actions': 'Actions for {name}',
|
|
37
39
|
'status.idle': 'Idle',
|
|
38
40
|
'status.running': 'Running',
|
|
39
41
|
'status.waitingApproval': 'Waiting for approval',
|
|
40
|
-
'status.planReview': '
|
|
42
|
+
'status.planReview': 'Plan awaiting review',
|
|
41
43
|
'status.waitingAnswer': 'Waiting for your answer',
|
|
44
|
+
'status.compact.approval': 'Approval',
|
|
45
|
+
'status.compact.planReview': 'Plan review',
|
|
46
|
+
'status.compact.answer': 'Answer',
|
|
42
47
|
'status.completed': 'Completed',
|
|
43
48
|
'status.subagentsRunning.one': '{n} subagent running',
|
|
44
49
|
'status.subagentsRunning.other': '{n} subagents running',
|
|
45
50
|
|
|
51
|
+
'hover.copied': 'Copied',
|
|
46
52
|
'time.now': 'just now',
|
|
47
53
|
'time.minutes': '{n} min ago',
|
|
48
54
|
'time.hours': '{n} h ago',
|
|
49
55
|
'time.days': '{n} d ago',
|
|
56
|
+
'time.ago': '{t} ago',
|
|
57
|
+
'time.short.minutes': '{n}min',
|
|
58
|
+
'time.short.hours': '{n}h',
|
|
59
|
+
'time.short.days': '{n}d',
|
|
60
|
+
'time.short.months': '{n}mo',
|
|
61
|
+
'time.short.years': '{n}y',
|
|
50
62
|
|
|
51
63
|
'panels.title': 'Panel modules',
|
|
52
64
|
'panels.groupBoardless': 'No-board modules',
|
package/src/i18n/zh.ts
CHANGED
|
@@ -30,21 +30,33 @@ export const zh = {
|
|
|
30
30
|
'session.new.label': '在当前项目新建会话',
|
|
31
31
|
'session.empty': '这个项目还没有会话。',
|
|
32
32
|
'session.noProject': '先添加一个项目。',
|
|
33
|
+
'session.list.label': '会话',
|
|
34
|
+
'session.copy': '复制',
|
|
33
35
|
'session.pinned': '已置顶',
|
|
34
36
|
'session.actions': '{name} 的操作',
|
|
35
37
|
'status.idle': '空闲',
|
|
36
|
-
'status.running': '
|
|
37
|
-
'status.waitingApproval': '
|
|
38
|
-
'status.planReview': '
|
|
38
|
+
'status.running': '进行中',
|
|
39
|
+
'status.waitingApproval': '等待审批',
|
|
40
|
+
'status.planReview': '计划待审',
|
|
39
41
|
'status.waitingAnswer': '等待回答',
|
|
42
|
+
'status.compact.approval': '待审批',
|
|
43
|
+
'status.compact.planReview': '计划待审',
|
|
44
|
+
'status.compact.answer': '待回答',
|
|
40
45
|
'status.completed': '已完成',
|
|
41
46
|
'status.subagentsRunning.one': '{n} 个子代理运行中',
|
|
42
47
|
'status.subagentsRunning.other': '{n} 个子代理运行中',
|
|
43
48
|
|
|
49
|
+
'hover.copied': '已复制',
|
|
44
50
|
'time.now': '刚刚',
|
|
45
51
|
'time.minutes': '{n} 分钟前',
|
|
46
52
|
'time.hours': '{n} 小时前',
|
|
47
53
|
'time.days': '{n} 天前',
|
|
54
|
+
'time.ago': '{t}前',
|
|
55
|
+
'time.short.minutes': '{n}分钟',
|
|
56
|
+
'time.short.hours': '{n}小时',
|
|
57
|
+
'time.short.days': '{n}天',
|
|
58
|
+
'time.short.months': '{n}个月',
|
|
59
|
+
'time.short.years': '{n}年',
|
|
48
60
|
|
|
49
61
|
'panels.title': '面板模块',
|
|
50
62
|
'panels.groupBoardless': '无看板模块',
|
package/src/lib/ui.test.ts
CHANGED
|
@@ -3,12 +3,17 @@ import {
|
|
|
3
3
|
cx,
|
|
4
4
|
parseLocalTimestamp,
|
|
5
5
|
relativeTime,
|
|
6
|
+
relativeTimeAgo,
|
|
7
|
+
relativeTimeBucket,
|
|
8
|
+
relativeTimeCompact,
|
|
6
9
|
shortenPath,
|
|
7
10
|
type TimeTranslate,
|
|
8
11
|
} from './ui.js';
|
|
9
12
|
|
|
10
|
-
const t: TimeTranslate = (key, params) =>
|
|
11
|
-
params === undefined
|
|
13
|
+
const t: TimeTranslate = (key, params) => {
|
|
14
|
+
if (params === undefined) return key;
|
|
15
|
+
return `${key}:${String(params.n ?? params.t ?? '')}`;
|
|
16
|
+
};
|
|
12
17
|
|
|
13
18
|
const NOW = Date.parse('2026-09-27T12:00:00.000Z');
|
|
14
19
|
|
|
@@ -59,6 +64,48 @@ describe('relativeTime', () => {
|
|
|
59
64
|
});
|
|
60
65
|
});
|
|
61
66
|
|
|
67
|
+
describe('relativeTimeBucket / relativeTimeCompact / relativeTimeAgo(会话行那一列)', () => {
|
|
68
|
+
const at = (ago: number): number => NOW - ago;
|
|
69
|
+
const MIN = 60_000;
|
|
70
|
+
const HOUR = 3_600_000;
|
|
71
|
+
const DAY = 86_400_000;
|
|
72
|
+
|
|
73
|
+
it('★ 档位与 dsh 的 relative-time 逐条一致:now / minutes / hours / days / months / years', () => {
|
|
74
|
+
expect(relativeTimeBucket(at(30_000), NOW)).toEqual({ unit: 'now', n: 0 });
|
|
75
|
+
expect(relativeTimeBucket(at(3 * MIN), NOW)).toEqual({ unit: 'minutes', n: 3 });
|
|
76
|
+
expect(relativeTimeBucket(at(5 * HOUR), NOW)).toEqual({ unit: 'hours', n: 5 });
|
|
77
|
+
expect(relativeTimeBucket(at(3 * DAY), NOW)).toEqual({ unit: 'days', n: 3 });
|
|
78
|
+
expect(relativeTimeBucket(at(40 * DAY), NOW)).toEqual({ unit: 'months', n: 1 });
|
|
79
|
+
expect(relativeTimeBucket(at(400 * DAY), NOW)).toEqual({ unit: 'years', n: 1 });
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('★ 边界在 30 天与 365 天那一侧(dsh 的分档,不是我们的 7 天)', () => {
|
|
83
|
+
expect(relativeTimeBucket(at(29 * DAY), NOW)?.unit).toBe('days');
|
|
84
|
+
expect(relativeTimeBucket(at(30 * DAY), NOW)?.unit).toBe('months');
|
|
85
|
+
expect(relativeTimeBucket(at(364 * DAY), NOW)?.unit).toBe('months');
|
|
86
|
+
expect(relativeTimeBucket(at(365 * DAY), NOW)?.unit).toBe('years');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('未来时间钳到 now(不当成负档)', () => {
|
|
90
|
+
expect(relativeTimeBucket(NOW + MIN, NOW)).toEqual({ unit: 'now', n: 0 });
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('非法时间戳:桶给 null、两句都给空串', () => {
|
|
94
|
+
expect(relativeTimeBucket(Number.NaN, NOW)).toBeNull();
|
|
95
|
+
expect(relativeTimeBucket(NOW, Number.NaN)).toBeNull();
|
|
96
|
+
expect(relativeTimeCompact(Number.NaN, t, NOW)).toBe('');
|
|
97
|
+
expect(relativeTimeAgo(Number.NaN, t, NOW)).toBe('');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('★ 行里是紧凑写法,悬停卡才补「前」;now 那一档两处都不加', () => {
|
|
101
|
+
expect(relativeTimeCompact(at(3 * MIN), t, NOW)).toBe('time.short.minutes:3');
|
|
102
|
+
expect(relativeTimeCompact(at(40 * DAY), t, NOW)).toBe('time.short.months:1');
|
|
103
|
+
expect(relativeTimeAgo(at(3 * MIN), t, NOW)).toBe('time.ago:time.short.minutes:3');
|
|
104
|
+
expect(relativeTimeCompact(at(30_000), t, NOW)).toBe('time.now');
|
|
105
|
+
expect(relativeTimeAgo(at(30_000), t, NOW)).toBe('time.now');
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
62
109
|
describe('shortenPath', () => {
|
|
63
110
|
it('把用户主目录缩成 ~', () => {
|
|
64
111
|
expect(shortenPath('/Users/you/dev/app')).toBe('~/dev/app');
|
package/src/lib/ui.ts
CHANGED
|
@@ -3,9 +3,47 @@ export function cx(...parts: Array<string | false | null | undefined>): string {
|
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
const MINUTE = 60 * 1000;
|
|
6
|
+
const HOUR = 60 * MINUTE;
|
|
7
|
+
const DAY = 24 * HOUR;
|
|
8
|
+
const MONTH = 30 * DAY;
|
|
9
|
+
const YEAR = 365 * DAY;
|
|
6
10
|
|
|
7
11
|
export type TimeTranslate = (key: string, params?: Record<string, unknown>) => string;
|
|
8
12
|
|
|
13
|
+
export type RelativeTimeUnit = 'now' | 'minutes' | 'hours' | 'days' | 'months' | 'years';
|
|
14
|
+
|
|
15
|
+
export interface RelativeTimeBucket {
|
|
16
|
+
readonly unit: RelativeTimeUnit;
|
|
17
|
+
readonly n: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function relativeTimeBucket(epochMs: number, now: number = Date.now()): RelativeTimeBucket | null {
|
|
21
|
+
if (!Number.isFinite(epochMs) || !Number.isFinite(now)) return null;
|
|
22
|
+
const diff = Math.max(0, now - epochMs);
|
|
23
|
+
if (diff < MINUTE) return { unit: 'now', n: 0 };
|
|
24
|
+
if (diff < HOUR) return { unit: 'minutes', n: Math.floor(diff / MINUTE) };
|
|
25
|
+
if (diff < DAY) return { unit: 'hours', n: Math.floor(diff / HOUR) };
|
|
26
|
+
if (diff < MONTH) return { unit: 'days', n: Math.floor(diff / DAY) };
|
|
27
|
+
if (diff < YEAR) return { unit: 'months', n: Math.floor(diff / MONTH) };
|
|
28
|
+
return { unit: 'years', n: Math.floor(diff / YEAR) };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function bucketLabel(bucket: RelativeTimeBucket, t: TimeTranslate): string {
|
|
32
|
+
return bucket.unit === 'now' ? t('time.now') : t(`time.short.${bucket.unit}`, { n: bucket.n });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function relativeTimeCompact(epochMs: number, t: TimeTranslate, now?: number): string {
|
|
36
|
+
const bucket = relativeTimeBucket(epochMs, now);
|
|
37
|
+
return bucket === null ? '' : bucketLabel(bucket, t);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function relativeTimeAgo(epochMs: number, t: TimeTranslate, now?: number): string {
|
|
41
|
+
const bucket = relativeTimeBucket(epochMs, now);
|
|
42
|
+
if (bucket === null) return '';
|
|
43
|
+
const label = bucketLabel(bucket, t);
|
|
44
|
+
return bucket.unit === 'now' ? label : t('time.ago', { t: label });
|
|
45
|
+
}
|
|
46
|
+
|
|
9
47
|
export function relativeTime(epochMs: number, t: TimeTranslate): string {
|
|
10
48
|
if (!Number.isFinite(epochMs)) return '';
|
|
11
49
|
const diff = Date.now() - epochMs;
|