@dsh-workbench/shared 1.1.12 → 1.1.13
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/config/constants.d.ts +2 -0
- package/dist/config/constants.js +2 -0
- package/dist/host/preflight.d.ts +2 -2
- package/dist/host/shell.d.ts +1 -0
- package/dist/host/shell.js +39 -10
- package/dist/i18n/en.js +3 -0
- package/dist/i18n/index.d.ts +4 -1
- package/dist/i18n/zh.d.ts +3 -0
- package/dist/i18n/zh.js +3 -0
- package/package.json +1 -1
- package/src/config/constants.ts +3 -0
- package/src/host/__tests__/shell.test.ts +70 -0
- package/src/host/preflight.ts +2 -2
- package/src/host/shell.ts +44 -10
- package/src/i18n/en.ts +3 -0
- package/src/i18n/zh.ts +3 -0
|
@@ -50,6 +50,8 @@ export declare const WARM_TIMEOUT_MS = 20000;
|
|
|
50
50
|
export declare const PREFLIGHT_FRESH_MS = 30000;
|
|
51
51
|
/** 装 / 卸模块包的超时(毫秒):pnpm 与取包内容都按它算。 */
|
|
52
52
|
export declare const INSTALL_TIMEOUT_MS = 300000;
|
|
53
|
+
/** 启动体检里查版本号那一条的超时(毫秒):只印个版本号,留够 opencli 每次调用约 5 秒的开销;`doctor` 要起浏览器会话,另按 `OPENCLI_TIMEOUT_MS`。 */
|
|
54
|
+
export declare const PREFLIGHT_VERSION_TIMEOUT_MS = 30000;
|
|
53
55
|
/** 查 registry 版本那一次请求的超时(毫秒)。 */
|
|
54
56
|
export declare const VERSION_CHECK_TIMEOUT_MS = 10000;
|
|
55
57
|
/** 版本查询结果的缓存有效期(毫秒):期内不发第二次请求。 */
|
package/dist/config/constants.js
CHANGED
|
@@ -50,6 +50,8 @@ export const WARM_TIMEOUT_MS = 20_000;
|
|
|
50
50
|
export const PREFLIGHT_FRESH_MS = 30_000;
|
|
51
51
|
/** 装 / 卸模块包的超时(毫秒):pnpm 与取包内容都按它算。 */
|
|
52
52
|
export const INSTALL_TIMEOUT_MS = 300_000;
|
|
53
|
+
/** 启动体检里查版本号那一条的超时(毫秒):只印个版本号,留够 opencli 每次调用约 5 秒的开销;`doctor` 要起浏览器会话,另按 `OPENCLI_TIMEOUT_MS`。 */
|
|
54
|
+
export const PREFLIGHT_VERSION_TIMEOUT_MS = 30_000;
|
|
53
55
|
/** 查 registry 版本那一次请求的超时(毫秒)。 */
|
|
54
56
|
export const VERSION_CHECK_TIMEOUT_MS = 10_000;
|
|
55
57
|
/** 版本查询结果的缓存有效期(毫秒):期内不发第二次请求。 */
|
package/dist/host/preflight.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type PreflightStepId = 'toolchain' | 'cli' | 'bridge' | 'runtime' | 'diy' | 'warm';
|
|
2
2
|
export type PreflightStepStatus = 'pending' | 'running' | 'ok' | 'warn' | 'failed';
|
|
3
|
-
export type PreflightFailure = 'permission' | 'network' | 'missing' | 'unknown';
|
|
4
|
-
export type PreflightGuidance = 'install' | 'path' | 'shell';
|
|
3
|
+
export type PreflightFailure = 'permission' | 'network' | 'missing' | 'host' | 'unknown';
|
|
4
|
+
export type PreflightGuidance = 'install' | 'path' | 'shell' | 'host';
|
|
5
5
|
export type PreflightBridgeIssue = string;
|
|
6
6
|
export interface PreflightStep {
|
|
7
7
|
readonly id: PreflightStepId;
|
package/dist/host/shell.d.ts
CHANGED
package/dist/host/shell.js
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
import { GIT_TIMEOUT_MS } from '../config/constants.js';
|
|
2
2
|
const DEFAULT_MAX_BYTES = 8 * 1024 * 1024;
|
|
3
|
+
const GUARD_SLACK_MS = 1_000;
|
|
4
|
+
function stalledResult() {
|
|
5
|
+
return {
|
|
6
|
+
exitCode: null,
|
|
7
|
+
timedOut: true,
|
|
8
|
+
aborted: false,
|
|
9
|
+
stdout: '',
|
|
10
|
+
stderr: '',
|
|
11
|
+
truncated: false,
|
|
12
|
+
stalled: true,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
async function settleWithin(work, limitMs) {
|
|
16
|
+
let timer;
|
|
17
|
+
const guard = new Promise((resolve) => {
|
|
18
|
+
timer = setTimeout(() => resolve(null), limitMs);
|
|
19
|
+
});
|
|
20
|
+
try {
|
|
21
|
+
return await Promise.race([work, guard]);
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
if (timer !== undefined)
|
|
25
|
+
clearTimeout(timer);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
3
28
|
export async function runShell(shell, command, options = {}) {
|
|
4
29
|
const { workdir, timeoutMs = GIT_TIMEOUT_MS, signal } = options;
|
|
5
30
|
const spec = shell.resolve({
|
|
@@ -10,14 +35,18 @@ export async function runShell(shell, command, options = {}) {
|
|
|
10
35
|
stdoutMaxBytes: DEFAULT_MAX_BYTES,
|
|
11
36
|
...(signal === undefined ? {} : { signal }),
|
|
12
37
|
});
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
38
|
+
const settled = await settleWithin((async () => {
|
|
39
|
+
const execution = await shell.execute(spec);
|
|
40
|
+
const result = await execution.result();
|
|
41
|
+
return {
|
|
42
|
+
exitCode: result.exitCode,
|
|
43
|
+
timedOut: result.timedOut === true,
|
|
44
|
+
aborted: result.aborted === true,
|
|
45
|
+
stdout: result.stdout.text,
|
|
46
|
+
stderr: result.stderr.text,
|
|
47
|
+
truncated: result.stdout.truncated || result.stderr.truncated,
|
|
48
|
+
stalled: false,
|
|
49
|
+
};
|
|
50
|
+
})(), timeoutMs + GUARD_SLACK_MS);
|
|
51
|
+
return settled ?? stalledResult();
|
|
23
52
|
}
|
package/dist/i18n/en.js
CHANGED
|
@@ -589,6 +589,7 @@ export const en = {
|
|
|
589
589
|
'env.stepFailed.install': 'install failed',
|
|
590
590
|
'env.stepFailed.path': 'installed but not found',
|
|
591
591
|
'env.stepFailed.shell': 'cannot reach the command line',
|
|
592
|
+
'env.stepFailed.host': 'the command never returned',
|
|
592
593
|
'env.toolchain.ok': 'Looks good',
|
|
593
594
|
'env.toolchain.warn': 'Almost ready',
|
|
594
595
|
'env.runtime.ok': 'Ready',
|
|
@@ -601,9 +602,11 @@ export const en = {
|
|
|
601
602
|
'env.fix.why': 'The workbench uses its own background tool (installed separately from the one in your terminal), and it is not set up on this machine yet.',
|
|
602
603
|
'env.fix.whyPath': 'The background tool is installed, but this environment cannot find it \u2014 usually a PATH or shell-session issue.',
|
|
603
604
|
'env.fix.whyShell': 'The workbench cannot reach the command line on this machine, so it cannot fetch data \u2014 you cannot install this from here; someone needs to fix the background environment.',
|
|
605
|
+
'env.fix.whyHost': 'The workbench runs a few checks on the command line and collects what they return; this time the command went out and nothing came back. The tools themselves are most likely fine \u2014 reinstalling Node / npm / pnpm will not help.',
|
|
604
606
|
'env.fix.step': 'Run this in a terminal, then hit Retry:',
|
|
605
607
|
'env.fix.stepPath': 'Open a new terminal window (or make sure npm\u2019s global bin directory is on PATH), then hit Retry.',
|
|
606
608
|
'env.fix.stepShell': 'Restart the workbench (or dsh); if it keeps happening, the workbench still cannot reach the command line.',
|
|
609
|
+
'env.fix.stepHost': 'Quit the workbench completely (including the tray icon), clear the dsh-* leftovers in the system temp folder, then open it again. If it keeps happening, update dsh.',
|
|
607
610
|
'env.fix.permission': 'Permission denied: rerun with sudo, or point npm\u2019s global directory at your home.',
|
|
608
611
|
'env.fix.network': 'Network unreachable: check your network or proxy, then retry.',
|
|
609
612
|
'env.fix.details': 'Details (for troubleshooting)',
|
package/dist/i18n/index.d.ts
CHANGED
|
@@ -599,6 +599,7 @@ export declare const dictionaries: {
|
|
|
599
599
|
readonly 'env.stepFailed.install': "装不上";
|
|
600
600
|
readonly 'env.stepFailed.path': "装了但还找不到";
|
|
601
601
|
readonly 'env.stepFailed.shell': "连不上命令行";
|
|
602
|
+
readonly 'env.stepFailed.host': "命令行没有返回";
|
|
602
603
|
readonly 'env.toolchain.ok': "正常";
|
|
603
604
|
readonly 'env.toolchain.warn': "还没完全准备好";
|
|
604
605
|
readonly 'env.runtime.ok': "已就绪";
|
|
@@ -611,9 +612,11 @@ export declare const dictionaries: {
|
|
|
611
612
|
readonly 'env.fix.why': "工作台用它自己那份后台工具(与你在终端里那套分开装,互不影响),这台机器上还没装好它。";
|
|
612
613
|
readonly 'env.fix.whyPath': "后台工具装上了,但当前环境还找不到它 —— 通常是 PATH 或终端会话的问题。";
|
|
613
614
|
readonly 'env.fix.whyShell': "工作台拿不到这台机器的命令行,所以取不了数据 —— 这一步你装不了,需要有人处理后台环境。";
|
|
615
|
+
readonly 'env.fix.whyHost': "工作台要靠命令行跑几条检查,再把结果收回来;这次命令发出去了,结果一直没回来。工具本身多半是好的 —— 重装 Node / npm / pnpm 不会有帮助。";
|
|
614
616
|
readonly 'env.fix.step': "在终端里运行下面这条命令,装好之后点「重试」:";
|
|
615
617
|
readonly 'env.fix.stepPath': "新开一个终端窗口(或确认 npm 的全局 bin 目录在 PATH 里),然后点「重试」。";
|
|
616
618
|
readonly 'env.fix.stepShell': "重启一次工作台(或 dsh);如果反复出现,说明工作台还是拿不到命令行。";
|
|
619
|
+
readonly 'env.fix.stepHost': "完全退出工作台(托盘图标也要退),清掉系统临时目录里 dsh- 开头的残留,再重新打开;反复出现就升级 dsh。";
|
|
617
620
|
readonly 'env.fix.permission': "权限不够:在命令前加 sudo 重跑,或先把 npm 的全局目录配到你的用户目录。";
|
|
618
621
|
readonly 'env.fix.network': "网络不通:检查网络或代理设置后重试。";
|
|
619
622
|
readonly 'env.fix.details': "详细输出(排障用)";
|
|
@@ -823,7 +826,7 @@ export declare const dictionaries: {
|
|
|
823
826
|
readonly 'configSync.emptyProviders': "工作台还没有任何模型供应商 —— 去「配置同步」从某个 profile 把模型供应商那几行同步过来,或自己去「模型」里配。";
|
|
824
827
|
readonly 'configSync.failed': "同步没成功,再试一次。";
|
|
825
828
|
};
|
|
826
|
-
en: Record<"time.now" | "time.ago" | "time.minutes" | "time.hours" | "time.days" | "blocker.retry" | "blocker.copy" | "blocker.unknown.title" | "blocker.login.go" | "blocker.login.titleGeneric" | "blocker.login.title" | "blocker.login.manual" | "blocker.login.hint" | "blocker.forbidden.open" | "blocker.forbidden.titleGeneric" | "blocker.forbidden.title" | "blocker.forbidden.hint" | "blocker.timeout.hint" | "blocker.exec.hint" | "blocker.fix.install" | "blocker.market.open" | "env.unit.failed" | "env.unit.failedHint" | "env.unit.unsupported" | "env.unit.unsupportedHint" | "env.unit.degraded" | "env.unit.degradedHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "profileCreate.nav" | "profileCreate.lead" | "profileCreate.name" | "profileCreate.nameHint" | "profileCreate.source" | "profileCreate.current" | "profileCreate.copy" | "profileCreate.settings" | "profileCreate.create" | "profileCreate.creating" | "profileCreate.created" | "profileCreate.command" | "profileCreate.readFailed" | "profileCreate.retry" | "profileCreate.reading" | "profileCreate.noProfiles" | "profileCreate.failed" | "configSync.nav" | "configSync.lead" | "configSync.source" | "configSync.sourceBroken" | "configSync.sourceRows" | "configSync.sourceDead" | "configSync.refresh" | "configSync.loading" | "configSync.readHint" | "configSync.tag.new" | "configSync.tag.differs" | "configSync.conflictNote" | "configSync.code.lang" | "configSync.code.copy" | "configSync.code.copied" | "configSync.code.wrap" | "configSync.code.unwrap" | "configSync.code.collapse" | "configSync.code.collapseAria" | "configSync.code.expandAria" | "configSync.code.expand" | "configSync.missing" | "configSync.apply" | "configSync.applyNone" | "configSync.applying" | "configSync.applied" | "configSync.appliedUnverified" | "configSync.appliedIds" | "configSync.skippedIds" | "configSync.nothing" | "configSync.unreadable" | "configSync.noSource" | "configSync.emptyProviders" | "configSync.failed" | "env.need.bin.missing" | "env.need.bin.hint" | "env.need.extension.missing" | "env.need.extension.outdated" | "env.need.extension.hint" | "env.need.lib.missing" | "env.need.lib.outdated" | "env.need.lib.unsatisfied" | "env.need.lib.hint" | "env.need.env.missing" | "env.need.env.hint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "project.add.busy" | "project.add.failed" | "project.search.label" | "project.search.placeholder" | "project.search.empty" | "project.group.workspaces" | "project.group.defaultWorkspace" | "project.group.workshop" | "project.rename.row" | "project.rename.current" | "project.rename.title" | "project.rename.description" | "project.rename.field" | "project.rename.placeholder" | "project.rename.hint" | "project.rename.save" | "project.rename.saving" | "project.rename.cancel" | "project.rename.failed" | "session.new" | "session.new.label" | "session.empty" | "session.noProject" | "session.list.label" | "session.copy" | "session.pinned" | "session.actions" | "status.idle" | "status.running" | "status.longTask" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.compact.approval" | "status.compact.planReview" | "status.compact.answer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "project.attention.warning.one" | "project.attention.warning.other" | "project.attention.running.one" | "project.attention.running.other" | "project.attention.longTask.one" | "project.attention.longTask.other" | "project.attention.done.one" | "project.attention.done.other" | "project.attention.state.warning" | "project.attention.state.running" | "project.attention.state.done" | "hover.copied" | "time.short.minutes" | "time.short.hours" | "time.short.days" | "time.short.months" | "time.short.years" | "panels.title" | "panels.groupBoardless" | "panels.groupPlugins" | "runtime.plugin" | "runtime.pluginOf" | "runtime.pluginThing" | "runtime.pluginArea" | "panels.market.defaultHint" | "panels.market.defaultLabel" | "panels.market.defaultLocked" | "panels.followAll" | "panels.followAllConfirmTitle" | "panels.followAllConfirmDetail" | "panels.followAllConfirmAck" | "panels.followAllConfirmYes" | "panels.followAllConfirmNo" | "panels.enabled" | "panels.disabled" | "panels.choose" | "panels.buildModule" | "panels.failed" | "panels.dragHint" | "panels.unknownStep" | "panels.labelWithHint" | "panels.hintJoin" | "panels.dep.failed" | "panels.dep.unchecked" | "panels.dep.missing" | "panels.dep.outdated" | "panels.dep.degraded" | "panels.dep.unsupported" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.notActive" | "panels.market.notUsable" | "panels.market.broken" | "panels.market.hasNew" | "panels.market.hasProblem" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.uncheckedHint" | "panels.market.checking" | "panels.market.sectionInstalled" | "panels.market.sectionPending" | "panels.market.sectionShared" | "panels.market.sharedUsedBy" | "panels.market.listSeparator" | "panels.market.sharedMissing" | "panels.market.sharedOutdated" | "panels.market.sharedUnsatisfied" | "panels.market.sharedOk" | "panels.market.versionArrow" | "panels.market.lead" | "panels.market.install" | "panels.market.update" | "panels.market.swapSlow" | "panels.market.removeSlow" | "panels.market.updateNoChange" | "panels.market.updateUnknownVersion" | "panels.market.updateGone" | "panels.market.updateRestored" | "panels.market.updateBehind" | "panels.market.updateStuck.title" | "panels.market.updateStuck.factNoChange" | "panels.market.updateStuck.copiedHint" | "panels.market.selfUpdateFailed" | "panels.market.selfUpdateUnknown" | "panels.market.selfUpdateRolledBack" | "panels.market.uninstall" | "panels.market.uninstallLabel" | "panels.market.installing" | "panels.market.updating" | "panels.market.uninstalling" | "panels.market.confirmUninstallTitle" | "panels.market.confirmUninstallDetail" | "panels.market.confirmUninstallAck" | "panels.market.confirmYes" | "panels.market.confirmNo" | "panels.market.noMarketSource" | "panels.market.failed" | "panels.market.failure.permission" | "panels.market.failure.diskFull" | "panels.market.failure.sandbox" | "panels.market.failure.unknown" | "panels.market.failure.factOwner" | "panels.market.failure.factMode" | "panels.market.failure.factSpace" | "panels.market.failure.factStuck" | "panels.market.failure.nowhere" | "panels.market.failure.copyFix" | "panels.market.failure.copied" | "panels.market.failure.copiedHint" | "panels.market.failure.askAgent" | "panels.market.failure.askAgentText" | "panels.market.failure.askAgentHint" | "panels.market.failure.recheck" | "panels.market.failure.showOutput" | "panels.market.failure.hideOutput" | "panels.market.failure.term.commandLine" | "panels.market.failure.term.signal" | "panels.market.failure.term.exitCode" | "panels.market.failure.term.noExitCode" | "panels.market.failure.term.running" | "panels.market.failure.term.failed" | "panels.market.failure.term.done" | "panels.market.failure.term.copy" | "panels.market.failure.term.copied" | "panels.market.failure.term.noOutput" | "panels.market.failure.term.collapse" | "panels.market.failure.term.expandAria" | "panels.market.failure.term.expand" | "panels.market.needEnv" | "panels.market.needCommands" | "panels.market.needBinary" | "panels.market.needLib" | "panels.market.localMark" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.sectionPlugins" | "panels.market.openDetail" | "panels.market.detailBack" | "panels.market.detailSourceTitle" | "panels.market.detailSource" | "panels.market.detailRegistry" | "panels.market.detailSpec" | "panels.market.detailUnit" | "panels.market.detailVersion" | "panels.market.detailLatest" | "panels.market.detailPluginName" | "panels.market.detailInstalledAt" | "panels.market.detailMarket" | "panels.market.detailRepository" | "panels.market.detailCommit" | "panels.market.detailDirectory" | "panels.market.detailUpdateSource" | "panels.market.detailUpdateVersion" | "panels.market.detailLocalDirectory" | "panels.market.detailUnknown" | "panels.market.moduleOutdated" | "panels.market.updateNeedsWorkbench" | "panels.market.updateIncompatible" | "panels.market.moduleRefused" | "panels.market.moduleRestartHint" | "panels.market.pendingRestart" | "panels.market.pendingFollowUp" | "panels.market.migrationHint" | "panels.market.migrateAction" | "panels.market.migrating" | "panels.market.migrateConfirmTitle" | "panels.market.migrateConfirmDetail" | "panels.market.migrateConfirmAck" | "panels.market.migrateConfirmYes" | "panels.market.migrateDone" | "panels.market.dismissFollowUp" | "panels.market.dismissing" | "panels.market.dismissFollowUpTitle" | "panels.market.dismissFollowUpDetail" | "panels.market.dismissFollowUpAck" | "panels.market.dismissFollowUpYes" | "panels.market.dismissed" | "panels.market.workbenchName" | "panels.market.pluginBroken" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.checkUpdates" | "panels.market.checkAll" | "panels.market.checkingNow" | "panels.market.checkFailed" | "panels.market.checkedAt" | "panels.market.latestPartial" | "panels.market.latestNoRegistry" | "panels.market.latestProbeFailed" | "panels.market.justNow" | "panels.market.minutesAgo" | "panels.market.hoursAgo" | "panels.market.add.description" | "panels.market.add.specPlaceholder" | "panels.market.add.guideToggle" | "panels.market.add.guideHide" | "panels.market.add.guideIdTitle" | "panels.market.add.guideIdExample" | "panels.market.add.guideIdHint" | "panels.market.add.guideGitTitle" | "panels.market.add.guideGitExample" | "panels.market.add.guideGitHint" | "panels.market.add.guidePathTitle" | "panels.market.add.guidePathExample" | "panels.market.add.guidePathHint" | "panels.market.add.guideExampleLabel" | "panels.market.add.guideFill" | "panels.market.add.guideSafety" | "panels.market.add.registryLegend" | "panels.market.add.registryOfficial" | "panels.market.add.registryMirror" | "panels.market.add.registryWithHost" | "panels.market.add.registryToggle" | "panels.market.add.installVersion" | "panels.market.add.registryDefault" | "panels.market.add.registryCustom" | "panels.market.add.registryCustomPlaceholder" | "panels.market.add.registryCustomHint" | "panels.market.add.registryCustomInvalid" | "panels.market.add.run" | "panels.market.add.edit" | "panels.market.add.changeRegistry" | "panels.market.add.installingTitle" | "panels.market.add.installedTitle" | "panels.market.add.failedTitle" | "panels.market.add.cancelledTitle" | "panels.market.add.failureNetworkHost" | "panels.market.add.problemInvalid" | "panels.market.add.problemInstalled" | "panels.market.add.problemNotFound" | "panels.market.add.problemNotPackage" | "panels.market.add.problemNotBundle" | "panels.market.add.problemNotWorkbenchModule" | "panels.market.add.problemNotModuleOrPlugin" | "panels.market.add.failureNotModuleOrPlugin" | "panels.market.add.installedPlugin" | "panels.market.add.pluginPreview" | "panels.market.add.pluginAlias" | "panels.market.add.problemNetwork" | "panels.market.add.problemUnknown" | "panels.market.add.failureNetwork" | "panels.market.add.failureNotFound" | "panels.market.add.failureNoMatchingVersion" | "panels.market.add.failureDiskFull" | "panels.market.add.failurePermission" | "panels.market.add.failureBuildBlocked" | "panels.market.add.failureIntegrity" | "panels.market.add.failureStopProfile" | "panels.market.add.failureCancelled" | "panels.market.add.failureTimeout" | "panels.market.add.failurePnpmMissing" | "panels.market.add.failureInstalled" | "panels.market.add.failureGeneric" | "panels.market.add.failureCredentials" | "panels.market.add.approveTitle" | "panels.market.add.approveCaution" | "panels.market.add.approveRun" | "panels.market.add.restart" | "panels.market.add.tookEffect" | "panels.market.add.details" | "panels.market.add.open" | "panels.market.add.title" | "panels.market.add.intro" | "panels.market.add.specLabel" | "panels.market.add.specHint" | "panels.market.add.exampleTitle" | "panels.market.add.exampleFill" | "panels.market.add.registryLabel" | "panels.market.add.registryProfile" | "panels.market.add.registryPnpm" | "panels.market.add.check" | "panels.market.add.checking" | "panels.market.add.classifying" | "panels.market.add.change" | "panels.market.add.previewTitle" | "panels.market.add.fieldName" | "panels.market.add.fieldVersion" | "panels.market.add.fieldDescription" | "panels.market.add.fieldSource" | "panels.market.add.install" | "panels.market.add.installing" | "panels.market.add.cancel" | "panels.market.add.close" | "panels.market.add.retry" | "panels.market.add.changeSource" | "panels.market.tabInstalled" | "panels.market.tabs" | "panels.tab.discover" | "panels.discover.loading" | "panels.discover.slowHint" | "panels.discover.lead" | "panels.discover.addSource" | "panels.discover.addingSource" | "panels.discover.addFirstSource" | "panels.discover.removeSource" | "panels.discover.removeTitle" | "panels.discover.removeBody" | "panels.discover.sourceActions" | "panels.discover.sourceStateWritable" | "panels.discover.sourceStateReadOnly" | "panels.discover.sourceEnable" | "panels.discover.sourceDisable" | "panels.discover.sourceWorking" | "panels.discover.sourceEnabled" | "panels.discover.sourceReadOnly" | "panels.discover.refresh" | "panels.discover.search" | "panels.discover.clearSearch" | "panels.discover.all" | "panels.discover.sourceLabel" | "panels.discover.sourceKind" | "panels.discover.sourceKindHttp" | "panels.discover.sourceKindGit" | "panels.discover.sourceUrl" | "panels.discover.sourcePlaceholder" | "panels.discover.sourceRef" | "panels.discover.sourcePath" | "panels.discover.sourceLocal" | "panels.discover.sourceLocalHint" | "panels.discover.save" | "panels.discover.cancel" | "panels.discover.retry" | "panels.discover.noSource" | "panels.discover.noSourceHint" | "panels.discover.sourcesFailed" | "panels.discover.unreadable" | "panels.discover.sandbox" | "panels.discover.sourceAuth" | "panels.discover.invalid" | "panels.discover.emptyRepo" | "panels.discover.missingIndex" | "panels.discover.initTitle" | "panels.discover.initCta" | "panels.discover.initWhat" | "panels.discover.initBranch" | "panels.discover.initBranchHint" | "panels.discover.initBranchBad" | "panels.discover.initOk" | "panels.discover.initBusy" | "panels.discover.initDone" | "panels.discover.stale" | "panels.discover.empty" | "panels.discover.noMatch" | "panels.discover.notInstalled" | "panels.discover.installed" | "panels.discover.installedVersion" | "panels.discover.update" | "panels.discover.badShell" | "panels.discover.badShellDetail" | "panels.discover.unverified" | "panels.discover.installing" | "panels.discover.installingNamed" | "panels.discover.cancelInstall" | "panels.discover.cancelling" | "panels.discover.installCancelled" | "panels.discover.installedDone" | "panels.discover.failed" | "panels.discover.transportTitle" | "panels.discover.transportSsh" | "panels.discover.transportHttps" | "panels.discover.transportOk" | "panels.discover.transportAuth" | "panels.discover.transportUnreachable" | "panels.discover.transportUnknown" | "panels.discover.transportChecking" | "panels.discover.transportTest" | "panels.discover.transportPlaceholder" | "panels.discover.transportNeedsAuth" | "panels.discover.transportChange" | "panels.discover.transportChangeHide" | "panels.discover.transportNone" | "panels.discover.expand" | "panels.discover.collapse" | "panels.discover.versionCount" | "panels.discover.sourceNpm" | "panels.discover.sourceNpmDefault" | "panels.discover.sourceGit" | "panels.discover.installVersion" | "panels.discover.confirmTitle" | "panels.discover.confirmDetail" | "panels.discover.confirmAck" | "panels.discover.confirmOk" | "panels.discover.confirmCancel" | "panels.discover.marketMenu" | "panels.discover.manageSources" | "panels.discover.sourcesTitle" | "panels.discover.sourcesIntro" | "panels.discover.sourcesLabel" | "panels.discover.sourceTrust" | "panels.discover.sourceDuplicate" | "panels.discover.sourceBadUrl" | "panels.discover.close" | "panels.discover.labelsMenu" | "panels.discover.labelsCount" | "panels.discover.tagsAll" | "panels.discover.sort" | "panels.discover.sortWith" | "panels.discover.sortRelevance" | "panels.discover.sortDefault" | "panels.discover.sortPublished" | "panels.discover.categoriesLabel" | "panels.discover.showMore" | "panels.discover.entryMeta" | "panels.discover.entryMetaAuthor" | "panels.discover.openEntry" | "panels.discover.cardInstall" | "panels.discover.cardInstalled" | "panels.discover.cardUpdate" | "panels.discover.cardBlocked" | "panels.discover.installTitle" | "panels.discover.installVersionTitle" | "panels.discover.openInstalled" | "panels.discover.noCompatibleVersion" | "panels.discover.detailBack" | "panels.discover.publishedAt" | "panels.discover.detailMarket" | "panels.discover.detailIncompatible" | "panels.discover.detailUnknown" | "panels.discover.detailSource" | "panels.discover.authorUnknown" | "panels.discover.tabOverview" | "panels.discover.tabReadme" | "panels.discover.tabChangelog" | "panels.discover.docReadme" | "panels.discover.docChangelog" | "panels.discover.docLoading" | "panels.discover.docMissing" | "panels.discover.docUnavailable" | "panels.discover.docUnknownReason" | "panels.discover.detailTabs" | "panels.discover.factPackage" | "panels.discover.factRegistry" | "panels.discover.factRepository" | "panels.discover.factCommit" | "panels.discover.factDirectory" | "panels.discover.factPublished" | "panels.discover.factAuthor" | "panels.discover.factHomepage" | "panels.discover.factCategory" | "panels.discover.factLabels" | "panels.discover.factMarket" | "panels.discover.detailVersions" | "panels.discover.versionsLabel" | "panels.discover.tagRecommended" | "panels.discover.tagPrerelease" | "panels.discover.tagInstalled" | "panels.discover.tagIncompatible" | "panels.discover.tagUnknown" | "panels.discover.selected" | "panels.discover.done" | "panels.discover.installTrust" | "panels.discover.progress" | "panels.market.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.restartWhy" | "panels.market.add.restartWhy.no-hmr" | "panels.market.add.restartWhy.package-moved" | "panels.market.add.restartWhy.host-module" | "panels.market.add.restartWhy.unmanaged-plugin" | "panels.market.add.restartWhy.module-comparison" | "panels.market.add.cancelled" | "panels.market.add.failed" | "panels.market.add.removed" | "panels.market.add.supplyPending" | "panels.market.add.supplyFailed" | "panels.market.add.notModule" | "panels.market.add.removedRestart" | "panels.market.add.remove" | "panels.market.add.problem.invalidSpec" | "panels.market.add.problem.alreadyInstalled" | "panels.market.add.problem.notFound" | "panels.market.add.problem.notAPackage" | "panels.market.add.problem.notABundle" | "panels.market.add.problem.network" | "panels.market.add.problem.unknown" | "panels.market.add.reason.invalidSpec" | "panels.market.add.reason.incompatible" | "panels.market.add.reason.notBundle" | "panels.market.add.reason.notRemovable" | "panels.market.add.reason.bundleInUse" | "panels.market.add.reason.stopProfile" | "panels.market.add.reason.staleApproval" | "panels.market.add.reason.operationError" | "panels.market.add.reason.buildBlocked" | "panels.market.add.reason.pnpmMissing" | "panels.market.add.reason.noMatchingVersion" | "panels.market.add.reason.diskFull" | "panels.market.add.reason.permission" | "panels.market.add.reason.integrity" | "panels.market.add.reason.timeout" | "panels.market.add.reason.network" | "panels.market.add.reason.notFound" | "panels.market.add.reason.unknown" | "blocker.fix.update" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.cardBroken" | "panels.cardRetry" | "panels.empty" | "panels.emptyHint" | "env.title" | "env.checking" | "env.installing" | "env.installingToolchain" | "env.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.toolchain.ok" | "env.toolchain.warn" | "env.runtime.ok" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.hold" | "env.bridge.unknown" | "env.fix.title" | "env.fix.why" | "env.fix.whyPath" | "env.fix.whyShell" | "env.fix.step" | "env.fix.stepPath" | "env.fix.stepShell" | "env.fix.permission" | "env.fix.network" | "env.fix.details" | "env.retry" | "env.wake" | "env.wake.opening" | "env.wake.browserOpen" | "env.wake.noBrowser" | "env.wake.failed" | "env.bridge.continue" | "env.diy.ok" | "env.diy.short" | "env.diy.hold" | "env.diy.why" | "env.diy.rows" | "env.diy.noRow" | "env.diy.step" | "env.diy.continue" | "env.copyCommand" | "env.copied" | "env.step.toolchain" | "env.step.adapter" | "env.step.runtime" | "env.step.bridge" | "env.step.diy" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "adapterSet.not-configured" | "adapterSet.no-profile" | "adapterSet.malformed" | "adapterSet.not-resolvable" | "adapterSet.import-failed" | "adapterSet.bad-export" | "adapterSet.factory-failed" | "adapterSet.incompatible-version" | "adapterSet.missing-member" | "env.unit.hint" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.column.label" | "rightbar.column.workbench" | "rightbar.column.dsh" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "rightbar.openPlatform" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label" | "adapterSet.title" | "adapterSet.lead" | "adapterSet.active" | "adapterSet.defaults" | "adapterSet.failed" | "adapterSet.healthUnreadable" | "workbenchSettings.nav" | "workbenchSettings.lead" | "sidebarEdition.nav" | "sidebarEdition.lead" | "sidebarEdition.official" | "sidebarEdition.officialHint" | "sidebarEdition.custom" | "sidebarEdition.customHint" | "sidebarEdition.saving" | "sidebarEdition.reloadRequired" | "sidebarEdition.reload" | "sidebarEdition.failed" | "debug.workspace" | "debug.status" | "debug.status.trouble" | "debug.stalled" | "debug.act.pause" | "debug.act.resume" | "debug.act.stop" | "debug.act.stop.ask" | "debug.card.here.title" | "debug.card.here.note" | "debug.card.away.note" | "debug.card.paused.note" | "debug.card.hidden.note" | "record.waiting" | "record.waiting.note" | "record.recording" | "record.recording.note" | "record.recording.shots" | "record.finished" | "record.finished.note" | "record.act.cancel" | "record.act.halt" | "approval.record.site" | "approval.record.what" | "approval.record.lands" | "approval.record.noUrl" | "approval.record.oneAction" | "approval.record.noSwitch" | "approval.longTask.what" | "approval.longTask.signal" | "approval.plugin.name" | "approval.plugin.command" | "approval.plugin.note" | "approval.publish.module" | "approval.publish.target" | "approval.publish.version" | "approval.publish.author" | "approval.publish.authorMissing" | "approval.publish.labels" | "approval.publish.labelsMissing" | "approval.publish.owner" | "approval.publish.ownerUnowned" | "approval.publish.ownerTaken" | "approval.publish.unit" | "approval.publish.unitTaken" | "approval.publish.path" | "approval.publish.pathTaken" | "approval.publish.registry" | "approval.publish.repo" | "approval.publish.branch" | "approval.publish.defaultBranch" | "approval.publish.artifacts" | "approval.publish.index" | "approval.publish.commits" | "approval.publish.twoCommits" | "approval.publish.reading" | "approval.publish.changelog" | "approval.publish.changelogPending" | "approval.publish.changelogMissing" | "approval.publish.targetAuto" | "approval.publish.targetTeam" | "approval.publish.targetPublic" | "approval.publish.targetTarball" | "approval.publish.targetGit" | "approval.publish.targetMarket" | "approval.publish.targetLocal" | "approval.market.source" | "approval.market.url" | "approval.market.action" | "approval.market.policy" | "approval.market.enable" | "approval.market.disable" | "approval.market.writable" | "approval.market.readOnly" | "approval.market.reading" | "markdown.copy" | "markdown.copied" | "markdown.footnotes", string>;
|
|
829
|
+
en: Record<"time.now" | "time.ago" | "time.minutes" | "time.hours" | "time.days" | "blocker.retry" | "blocker.copy" | "blocker.unknown.title" | "blocker.login.go" | "blocker.login.titleGeneric" | "blocker.login.title" | "blocker.login.manual" | "blocker.login.hint" | "blocker.forbidden.open" | "blocker.forbidden.titleGeneric" | "blocker.forbidden.title" | "blocker.forbidden.hint" | "blocker.timeout.hint" | "blocker.exec.hint" | "blocker.fix.install" | "blocker.market.open" | "env.unit.failed" | "env.unit.failedHint" | "env.unit.unsupported" | "env.unit.unsupportedHint" | "env.unit.degraded" | "env.unit.degradedHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "profileCreate.nav" | "profileCreate.lead" | "profileCreate.name" | "profileCreate.nameHint" | "profileCreate.source" | "profileCreate.current" | "profileCreate.copy" | "profileCreate.settings" | "profileCreate.create" | "profileCreate.creating" | "profileCreate.created" | "profileCreate.command" | "profileCreate.readFailed" | "profileCreate.retry" | "profileCreate.reading" | "profileCreate.noProfiles" | "profileCreate.failed" | "configSync.nav" | "configSync.lead" | "configSync.source" | "configSync.sourceBroken" | "configSync.sourceRows" | "configSync.sourceDead" | "configSync.refresh" | "configSync.loading" | "configSync.readHint" | "configSync.tag.new" | "configSync.tag.differs" | "configSync.conflictNote" | "configSync.code.lang" | "configSync.code.copy" | "configSync.code.copied" | "configSync.code.wrap" | "configSync.code.unwrap" | "configSync.code.collapse" | "configSync.code.collapseAria" | "configSync.code.expandAria" | "configSync.code.expand" | "configSync.missing" | "configSync.apply" | "configSync.applyNone" | "configSync.applying" | "configSync.applied" | "configSync.appliedUnverified" | "configSync.appliedIds" | "configSync.skippedIds" | "configSync.nothing" | "configSync.unreadable" | "configSync.noSource" | "configSync.emptyProviders" | "configSync.failed" | "env.need.bin.missing" | "env.need.bin.hint" | "env.need.extension.missing" | "env.need.extension.outdated" | "env.need.extension.hint" | "env.need.lib.missing" | "env.need.lib.outdated" | "env.need.lib.unsatisfied" | "env.need.lib.hint" | "env.need.env.missing" | "env.need.env.hint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "project.add.busy" | "project.add.failed" | "project.search.label" | "project.search.placeholder" | "project.search.empty" | "project.group.workspaces" | "project.group.defaultWorkspace" | "project.group.workshop" | "project.rename.row" | "project.rename.current" | "project.rename.title" | "project.rename.description" | "project.rename.field" | "project.rename.placeholder" | "project.rename.hint" | "project.rename.save" | "project.rename.saving" | "project.rename.cancel" | "project.rename.failed" | "session.new" | "session.new.label" | "session.empty" | "session.noProject" | "session.list.label" | "session.copy" | "session.pinned" | "session.actions" | "status.idle" | "status.running" | "status.longTask" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.compact.approval" | "status.compact.planReview" | "status.compact.answer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "project.attention.warning.one" | "project.attention.warning.other" | "project.attention.running.one" | "project.attention.running.other" | "project.attention.longTask.one" | "project.attention.longTask.other" | "project.attention.done.one" | "project.attention.done.other" | "project.attention.state.warning" | "project.attention.state.running" | "project.attention.state.done" | "hover.copied" | "time.short.minutes" | "time.short.hours" | "time.short.days" | "time.short.months" | "time.short.years" | "panels.title" | "panels.groupBoardless" | "panels.groupPlugins" | "runtime.plugin" | "runtime.pluginOf" | "runtime.pluginThing" | "runtime.pluginArea" | "panels.market.defaultHint" | "panels.market.defaultLabel" | "panels.market.defaultLocked" | "panels.followAll" | "panels.followAllConfirmTitle" | "panels.followAllConfirmDetail" | "panels.followAllConfirmAck" | "panels.followAllConfirmYes" | "panels.followAllConfirmNo" | "panels.enabled" | "panels.disabled" | "panels.choose" | "panels.buildModule" | "panels.failed" | "panels.dragHint" | "panels.unknownStep" | "panels.labelWithHint" | "panels.hintJoin" | "panels.dep.failed" | "panels.dep.unchecked" | "panels.dep.missing" | "panels.dep.outdated" | "panels.dep.degraded" | "panels.dep.unsupported" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.notActive" | "panels.market.notUsable" | "panels.market.broken" | "panels.market.hasNew" | "panels.market.hasProblem" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.uncheckedHint" | "panels.market.checking" | "panels.market.sectionInstalled" | "panels.market.sectionPending" | "panels.market.sectionShared" | "panels.market.sharedUsedBy" | "panels.market.listSeparator" | "panels.market.sharedMissing" | "panels.market.sharedOutdated" | "panels.market.sharedUnsatisfied" | "panels.market.sharedOk" | "panels.market.versionArrow" | "panels.market.lead" | "panels.market.install" | "panels.market.update" | "panels.market.swapSlow" | "panels.market.removeSlow" | "panels.market.updateNoChange" | "panels.market.updateUnknownVersion" | "panels.market.updateGone" | "panels.market.updateRestored" | "panels.market.updateBehind" | "panels.market.updateStuck.title" | "panels.market.updateStuck.factNoChange" | "panels.market.updateStuck.copiedHint" | "panels.market.selfUpdateFailed" | "panels.market.selfUpdateUnknown" | "panels.market.selfUpdateRolledBack" | "panels.market.uninstall" | "panels.market.uninstallLabel" | "panels.market.installing" | "panels.market.updating" | "panels.market.uninstalling" | "panels.market.confirmUninstallTitle" | "panels.market.confirmUninstallDetail" | "panels.market.confirmUninstallAck" | "panels.market.confirmYes" | "panels.market.confirmNo" | "panels.market.noMarketSource" | "panels.market.failed" | "panels.market.failure.permission" | "panels.market.failure.diskFull" | "panels.market.failure.sandbox" | "panels.market.failure.unknown" | "panels.market.failure.factOwner" | "panels.market.failure.factMode" | "panels.market.failure.factSpace" | "panels.market.failure.factStuck" | "panels.market.failure.nowhere" | "panels.market.failure.copyFix" | "panels.market.failure.copied" | "panels.market.failure.copiedHint" | "panels.market.failure.askAgent" | "panels.market.failure.askAgentText" | "panels.market.failure.askAgentHint" | "panels.market.failure.recheck" | "panels.market.failure.showOutput" | "panels.market.failure.hideOutput" | "panels.market.failure.term.commandLine" | "panels.market.failure.term.signal" | "panels.market.failure.term.exitCode" | "panels.market.failure.term.noExitCode" | "panels.market.failure.term.running" | "panels.market.failure.term.failed" | "panels.market.failure.term.done" | "panels.market.failure.term.copy" | "panels.market.failure.term.copied" | "panels.market.failure.term.noOutput" | "panels.market.failure.term.collapse" | "panels.market.failure.term.expandAria" | "panels.market.failure.term.expand" | "panels.market.needEnv" | "panels.market.needCommands" | "panels.market.needBinary" | "panels.market.needLib" | "panels.market.localMark" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.sectionPlugins" | "panels.market.openDetail" | "panels.market.detailBack" | "panels.market.detailSourceTitle" | "panels.market.detailSource" | "panels.market.detailRegistry" | "panels.market.detailSpec" | "panels.market.detailUnit" | "panels.market.detailVersion" | "panels.market.detailLatest" | "panels.market.detailPluginName" | "panels.market.detailInstalledAt" | "panels.market.detailMarket" | "panels.market.detailRepository" | "panels.market.detailCommit" | "panels.market.detailDirectory" | "panels.market.detailUpdateSource" | "panels.market.detailUpdateVersion" | "panels.market.detailLocalDirectory" | "panels.market.detailUnknown" | "panels.market.moduleOutdated" | "panels.market.updateNeedsWorkbench" | "panels.market.updateIncompatible" | "panels.market.moduleRefused" | "panels.market.moduleRestartHint" | "panels.market.pendingRestart" | "panels.market.pendingFollowUp" | "panels.market.migrationHint" | "panels.market.migrateAction" | "panels.market.migrating" | "panels.market.migrateConfirmTitle" | "panels.market.migrateConfirmDetail" | "panels.market.migrateConfirmAck" | "panels.market.migrateConfirmYes" | "panels.market.migrateDone" | "panels.market.dismissFollowUp" | "panels.market.dismissing" | "panels.market.dismissFollowUpTitle" | "panels.market.dismissFollowUpDetail" | "panels.market.dismissFollowUpAck" | "panels.market.dismissFollowUpYes" | "panels.market.dismissed" | "panels.market.workbenchName" | "panels.market.pluginBroken" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.checkUpdates" | "panels.market.checkAll" | "panels.market.checkingNow" | "panels.market.checkFailed" | "panels.market.checkedAt" | "panels.market.latestPartial" | "panels.market.latestNoRegistry" | "panels.market.latestProbeFailed" | "panels.market.justNow" | "panels.market.minutesAgo" | "panels.market.hoursAgo" | "panels.market.add.description" | "panels.market.add.specPlaceholder" | "panels.market.add.guideToggle" | "panels.market.add.guideHide" | "panels.market.add.guideIdTitle" | "panels.market.add.guideIdExample" | "panels.market.add.guideIdHint" | "panels.market.add.guideGitTitle" | "panels.market.add.guideGitExample" | "panels.market.add.guideGitHint" | "panels.market.add.guidePathTitle" | "panels.market.add.guidePathExample" | "panels.market.add.guidePathHint" | "panels.market.add.guideExampleLabel" | "panels.market.add.guideFill" | "panels.market.add.guideSafety" | "panels.market.add.registryLegend" | "panels.market.add.registryOfficial" | "panels.market.add.registryMirror" | "panels.market.add.registryWithHost" | "panels.market.add.registryToggle" | "panels.market.add.installVersion" | "panels.market.add.registryDefault" | "panels.market.add.registryCustom" | "panels.market.add.registryCustomPlaceholder" | "panels.market.add.registryCustomHint" | "panels.market.add.registryCustomInvalid" | "panels.market.add.run" | "panels.market.add.edit" | "panels.market.add.changeRegistry" | "panels.market.add.installingTitle" | "panels.market.add.installedTitle" | "panels.market.add.failedTitle" | "panels.market.add.cancelledTitle" | "panels.market.add.failureNetworkHost" | "panels.market.add.problemInvalid" | "panels.market.add.problemInstalled" | "panels.market.add.problemNotFound" | "panels.market.add.problemNotPackage" | "panels.market.add.problemNotBundle" | "panels.market.add.problemNotWorkbenchModule" | "panels.market.add.problemNotModuleOrPlugin" | "panels.market.add.failureNotModuleOrPlugin" | "panels.market.add.installedPlugin" | "panels.market.add.pluginPreview" | "panels.market.add.pluginAlias" | "panels.market.add.problemNetwork" | "panels.market.add.problemUnknown" | "panels.market.add.failureNetwork" | "panels.market.add.failureNotFound" | "panels.market.add.failureNoMatchingVersion" | "panels.market.add.failureDiskFull" | "panels.market.add.failurePermission" | "panels.market.add.failureBuildBlocked" | "panels.market.add.failureIntegrity" | "panels.market.add.failureStopProfile" | "panels.market.add.failureCancelled" | "panels.market.add.failureTimeout" | "panels.market.add.failurePnpmMissing" | "panels.market.add.failureInstalled" | "panels.market.add.failureGeneric" | "panels.market.add.failureCredentials" | "panels.market.add.approveTitle" | "panels.market.add.approveCaution" | "panels.market.add.approveRun" | "panels.market.add.restart" | "panels.market.add.tookEffect" | "panels.market.add.details" | "panels.market.add.open" | "panels.market.add.title" | "panels.market.add.intro" | "panels.market.add.specLabel" | "panels.market.add.specHint" | "panels.market.add.exampleTitle" | "panels.market.add.exampleFill" | "panels.market.add.registryLabel" | "panels.market.add.registryProfile" | "panels.market.add.registryPnpm" | "panels.market.add.check" | "panels.market.add.checking" | "panels.market.add.classifying" | "panels.market.add.change" | "panels.market.add.previewTitle" | "panels.market.add.fieldName" | "panels.market.add.fieldVersion" | "panels.market.add.fieldDescription" | "panels.market.add.fieldSource" | "panels.market.add.install" | "panels.market.add.installing" | "panels.market.add.cancel" | "panels.market.add.close" | "panels.market.add.retry" | "panels.market.add.changeSource" | "panels.market.tabInstalled" | "panels.market.tabs" | "panels.tab.discover" | "panels.discover.loading" | "panels.discover.slowHint" | "panels.discover.lead" | "panels.discover.addSource" | "panels.discover.addingSource" | "panels.discover.addFirstSource" | "panels.discover.removeSource" | "panels.discover.removeTitle" | "panels.discover.removeBody" | "panels.discover.sourceActions" | "panels.discover.sourceStateWritable" | "panels.discover.sourceStateReadOnly" | "panels.discover.sourceEnable" | "panels.discover.sourceDisable" | "panels.discover.sourceWorking" | "panels.discover.sourceEnabled" | "panels.discover.sourceReadOnly" | "panels.discover.refresh" | "panels.discover.search" | "panels.discover.clearSearch" | "panels.discover.all" | "panels.discover.sourceLabel" | "panels.discover.sourceKind" | "panels.discover.sourceKindHttp" | "panels.discover.sourceKindGit" | "panels.discover.sourceUrl" | "panels.discover.sourcePlaceholder" | "panels.discover.sourceRef" | "panels.discover.sourcePath" | "panels.discover.sourceLocal" | "panels.discover.sourceLocalHint" | "panels.discover.save" | "panels.discover.cancel" | "panels.discover.retry" | "panels.discover.noSource" | "panels.discover.noSourceHint" | "panels.discover.sourcesFailed" | "panels.discover.unreadable" | "panels.discover.sandbox" | "panels.discover.sourceAuth" | "panels.discover.invalid" | "panels.discover.emptyRepo" | "panels.discover.missingIndex" | "panels.discover.initTitle" | "panels.discover.initCta" | "panels.discover.initWhat" | "panels.discover.initBranch" | "panels.discover.initBranchHint" | "panels.discover.initBranchBad" | "panels.discover.initOk" | "panels.discover.initBusy" | "panels.discover.initDone" | "panels.discover.stale" | "panels.discover.empty" | "panels.discover.noMatch" | "panels.discover.notInstalled" | "panels.discover.installed" | "panels.discover.installedVersion" | "panels.discover.update" | "panels.discover.badShell" | "panels.discover.badShellDetail" | "panels.discover.unverified" | "panels.discover.installing" | "panels.discover.installingNamed" | "panels.discover.cancelInstall" | "panels.discover.cancelling" | "panels.discover.installCancelled" | "panels.discover.installedDone" | "panels.discover.failed" | "panels.discover.transportTitle" | "panels.discover.transportSsh" | "panels.discover.transportHttps" | "panels.discover.transportOk" | "panels.discover.transportAuth" | "panels.discover.transportUnreachable" | "panels.discover.transportUnknown" | "panels.discover.transportChecking" | "panels.discover.transportTest" | "panels.discover.transportPlaceholder" | "panels.discover.transportNeedsAuth" | "panels.discover.transportChange" | "panels.discover.transportChangeHide" | "panels.discover.transportNone" | "panels.discover.expand" | "panels.discover.collapse" | "panels.discover.versionCount" | "panels.discover.sourceNpm" | "panels.discover.sourceNpmDefault" | "panels.discover.sourceGit" | "panels.discover.installVersion" | "panels.discover.confirmTitle" | "panels.discover.confirmDetail" | "panels.discover.confirmAck" | "panels.discover.confirmOk" | "panels.discover.confirmCancel" | "panels.discover.marketMenu" | "panels.discover.manageSources" | "panels.discover.sourcesTitle" | "panels.discover.sourcesIntro" | "panels.discover.sourcesLabel" | "panels.discover.sourceTrust" | "panels.discover.sourceDuplicate" | "panels.discover.sourceBadUrl" | "panels.discover.close" | "panels.discover.labelsMenu" | "panels.discover.labelsCount" | "panels.discover.tagsAll" | "panels.discover.sort" | "panels.discover.sortWith" | "panels.discover.sortRelevance" | "panels.discover.sortDefault" | "panels.discover.sortPublished" | "panels.discover.categoriesLabel" | "panels.discover.showMore" | "panels.discover.entryMeta" | "panels.discover.entryMetaAuthor" | "panels.discover.openEntry" | "panels.discover.cardInstall" | "panels.discover.cardInstalled" | "panels.discover.cardUpdate" | "panels.discover.cardBlocked" | "panels.discover.installTitle" | "panels.discover.installVersionTitle" | "panels.discover.openInstalled" | "panels.discover.noCompatibleVersion" | "panels.discover.detailBack" | "panels.discover.publishedAt" | "panels.discover.detailMarket" | "panels.discover.detailIncompatible" | "panels.discover.detailUnknown" | "panels.discover.detailSource" | "panels.discover.authorUnknown" | "panels.discover.tabOverview" | "panels.discover.tabReadme" | "panels.discover.tabChangelog" | "panels.discover.docReadme" | "panels.discover.docChangelog" | "panels.discover.docLoading" | "panels.discover.docMissing" | "panels.discover.docUnavailable" | "panels.discover.docUnknownReason" | "panels.discover.detailTabs" | "panels.discover.factPackage" | "panels.discover.factRegistry" | "panels.discover.factRepository" | "panels.discover.factCommit" | "panels.discover.factDirectory" | "panels.discover.factPublished" | "panels.discover.factAuthor" | "panels.discover.factHomepage" | "panels.discover.factCategory" | "panels.discover.factLabels" | "panels.discover.factMarket" | "panels.discover.detailVersions" | "panels.discover.versionsLabel" | "panels.discover.tagRecommended" | "panels.discover.tagPrerelease" | "panels.discover.tagInstalled" | "panels.discover.tagIncompatible" | "panels.discover.tagUnknown" | "panels.discover.selected" | "panels.discover.done" | "panels.discover.installTrust" | "panels.discover.progress" | "panels.market.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.restartWhy" | "panels.market.add.restartWhy.no-hmr" | "panels.market.add.restartWhy.package-moved" | "panels.market.add.restartWhy.host-module" | "panels.market.add.restartWhy.unmanaged-plugin" | "panels.market.add.restartWhy.module-comparison" | "panels.market.add.cancelled" | "panels.market.add.failed" | "panels.market.add.removed" | "panels.market.add.supplyPending" | "panels.market.add.supplyFailed" | "panels.market.add.notModule" | "panels.market.add.removedRestart" | "panels.market.add.remove" | "panels.market.add.problem.invalidSpec" | "panels.market.add.problem.alreadyInstalled" | "panels.market.add.problem.notFound" | "panels.market.add.problem.notAPackage" | "panels.market.add.problem.notABundle" | "panels.market.add.problem.network" | "panels.market.add.problem.unknown" | "panels.market.add.reason.invalidSpec" | "panels.market.add.reason.incompatible" | "panels.market.add.reason.notBundle" | "panels.market.add.reason.notRemovable" | "panels.market.add.reason.bundleInUse" | "panels.market.add.reason.stopProfile" | "panels.market.add.reason.staleApproval" | "panels.market.add.reason.operationError" | "panels.market.add.reason.buildBlocked" | "panels.market.add.reason.pnpmMissing" | "panels.market.add.reason.noMatchingVersion" | "panels.market.add.reason.diskFull" | "panels.market.add.reason.permission" | "panels.market.add.reason.integrity" | "panels.market.add.reason.timeout" | "panels.market.add.reason.network" | "panels.market.add.reason.notFound" | "panels.market.add.reason.unknown" | "blocker.fix.update" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.cardBroken" | "panels.cardRetry" | "panels.empty" | "panels.emptyHint" | "env.title" | "env.checking" | "env.installing" | "env.installingToolchain" | "env.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.stepFailed.host" | "env.toolchain.ok" | "env.toolchain.warn" | "env.runtime.ok" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.hold" | "env.bridge.unknown" | "env.fix.title" | "env.fix.why" | "env.fix.whyPath" | "env.fix.whyShell" | "env.fix.whyHost" | "env.fix.step" | "env.fix.stepPath" | "env.fix.stepShell" | "env.fix.stepHost" | "env.fix.permission" | "env.fix.network" | "env.fix.details" | "env.retry" | "env.wake" | "env.wake.opening" | "env.wake.browserOpen" | "env.wake.noBrowser" | "env.wake.failed" | "env.bridge.continue" | "env.diy.ok" | "env.diy.short" | "env.diy.hold" | "env.diy.why" | "env.diy.rows" | "env.diy.noRow" | "env.diy.step" | "env.diy.continue" | "env.copyCommand" | "env.copied" | "env.step.toolchain" | "env.step.adapter" | "env.step.runtime" | "env.step.bridge" | "env.step.diy" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "adapterSet.not-configured" | "adapterSet.no-profile" | "adapterSet.malformed" | "adapterSet.not-resolvable" | "adapterSet.import-failed" | "adapterSet.bad-export" | "adapterSet.factory-failed" | "adapterSet.incompatible-version" | "adapterSet.missing-member" | "env.unit.hint" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.column.label" | "rightbar.column.workbench" | "rightbar.column.dsh" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "rightbar.openPlatform" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label" | "adapterSet.title" | "adapterSet.lead" | "adapterSet.active" | "adapterSet.defaults" | "adapterSet.failed" | "adapterSet.healthUnreadable" | "workbenchSettings.nav" | "workbenchSettings.lead" | "sidebarEdition.nav" | "sidebarEdition.lead" | "sidebarEdition.official" | "sidebarEdition.officialHint" | "sidebarEdition.custom" | "sidebarEdition.customHint" | "sidebarEdition.saving" | "sidebarEdition.reloadRequired" | "sidebarEdition.reload" | "sidebarEdition.failed" | "debug.workspace" | "debug.status" | "debug.status.trouble" | "debug.stalled" | "debug.act.pause" | "debug.act.resume" | "debug.act.stop" | "debug.act.stop.ask" | "debug.card.here.title" | "debug.card.here.note" | "debug.card.away.note" | "debug.card.paused.note" | "debug.card.hidden.note" | "record.waiting" | "record.waiting.note" | "record.recording" | "record.recording.note" | "record.recording.shots" | "record.finished" | "record.finished.note" | "record.act.cancel" | "record.act.halt" | "approval.record.site" | "approval.record.what" | "approval.record.lands" | "approval.record.noUrl" | "approval.record.oneAction" | "approval.record.noSwitch" | "approval.longTask.what" | "approval.longTask.signal" | "approval.plugin.name" | "approval.plugin.command" | "approval.plugin.note" | "approval.publish.module" | "approval.publish.target" | "approval.publish.version" | "approval.publish.author" | "approval.publish.authorMissing" | "approval.publish.labels" | "approval.publish.labelsMissing" | "approval.publish.owner" | "approval.publish.ownerUnowned" | "approval.publish.ownerTaken" | "approval.publish.unit" | "approval.publish.unitTaken" | "approval.publish.path" | "approval.publish.pathTaken" | "approval.publish.registry" | "approval.publish.repo" | "approval.publish.branch" | "approval.publish.defaultBranch" | "approval.publish.artifacts" | "approval.publish.index" | "approval.publish.commits" | "approval.publish.twoCommits" | "approval.publish.reading" | "approval.publish.changelog" | "approval.publish.changelogPending" | "approval.publish.changelogMissing" | "approval.publish.targetAuto" | "approval.publish.targetTeam" | "approval.publish.targetPublic" | "approval.publish.targetTarball" | "approval.publish.targetGit" | "approval.publish.targetMarket" | "approval.publish.targetLocal" | "approval.market.source" | "approval.market.url" | "approval.market.action" | "approval.market.policy" | "approval.market.enable" | "approval.market.disable" | "approval.market.writable" | "approval.market.readOnly" | "approval.market.reading" | "markdown.copy" | "markdown.copied" | "markdown.footnotes", string>;
|
|
827
830
|
};
|
|
828
831
|
/** 中文词表的键类型(从 `zh.ts` 转出):`en` 与模块词表都得覆盖同一批键。 */
|
|
829
832
|
export type { WorkbenchMessages };
|
package/dist/i18n/zh.d.ts
CHANGED
|
@@ -597,6 +597,7 @@ export declare const zh: {
|
|
|
597
597
|
readonly 'env.stepFailed.install': "装不上";
|
|
598
598
|
readonly 'env.stepFailed.path': "装了但还找不到";
|
|
599
599
|
readonly 'env.stepFailed.shell': "连不上命令行";
|
|
600
|
+
readonly 'env.stepFailed.host': "命令行没有返回";
|
|
600
601
|
readonly 'env.toolchain.ok': "正常";
|
|
601
602
|
readonly 'env.toolchain.warn': "还没完全准备好";
|
|
602
603
|
readonly 'env.runtime.ok': "已就绪";
|
|
@@ -609,9 +610,11 @@ export declare const zh: {
|
|
|
609
610
|
readonly 'env.fix.why': "工作台用它自己那份后台工具(与你在终端里那套分开装,互不影响),这台机器上还没装好它。";
|
|
610
611
|
readonly 'env.fix.whyPath': "后台工具装上了,但当前环境还找不到它 —— 通常是 PATH 或终端会话的问题。";
|
|
611
612
|
readonly 'env.fix.whyShell': "工作台拿不到这台机器的命令行,所以取不了数据 —— 这一步你装不了,需要有人处理后台环境。";
|
|
613
|
+
readonly 'env.fix.whyHost': "工作台要靠命令行跑几条检查,再把结果收回来;这次命令发出去了,结果一直没回来。工具本身多半是好的 —— 重装 Node / npm / pnpm 不会有帮助。";
|
|
612
614
|
readonly 'env.fix.step': "在终端里运行下面这条命令,装好之后点「重试」:";
|
|
613
615
|
readonly 'env.fix.stepPath': "新开一个终端窗口(或确认 npm 的全局 bin 目录在 PATH 里),然后点「重试」。";
|
|
614
616
|
readonly 'env.fix.stepShell': "重启一次工作台(或 dsh);如果反复出现,说明工作台还是拿不到命令行。";
|
|
617
|
+
readonly 'env.fix.stepHost': "完全退出工作台(托盘图标也要退),清掉系统临时目录里 dsh- 开头的残留,再重新打开;反复出现就升级 dsh。";
|
|
615
618
|
readonly 'env.fix.permission': "权限不够:在命令前加 sudo 重跑,或先把 npm 的全局目录配到你的用户目录。";
|
|
616
619
|
readonly 'env.fix.network': "网络不通:检查网络或代理设置后重试。";
|
|
617
620
|
readonly 'env.fix.details': "详细输出(排障用)";
|
package/dist/i18n/zh.js
CHANGED
|
@@ -589,6 +589,7 @@ export const zh = {
|
|
|
589
589
|
'env.stepFailed.install': '装不上',
|
|
590
590
|
'env.stepFailed.path': '装了但还找不到',
|
|
591
591
|
'env.stepFailed.shell': '连不上命令行',
|
|
592
|
+
'env.stepFailed.host': '命令行没有返回',
|
|
592
593
|
'env.toolchain.ok': '正常',
|
|
593
594
|
'env.toolchain.warn': '还没完全准备好',
|
|
594
595
|
'env.runtime.ok': '已就绪',
|
|
@@ -601,9 +602,11 @@ export const zh = {
|
|
|
601
602
|
'env.fix.why': '工作台用它自己那份后台工具(与你在终端里那套分开装,互不影响),这台机器上还没装好它。',
|
|
602
603
|
'env.fix.whyPath': '后台工具装上了,但当前环境还找不到它 —— 通常是 PATH 或终端会话的问题。',
|
|
603
604
|
'env.fix.whyShell': '工作台拿不到这台机器的命令行,所以取不了数据 —— 这一步你装不了,需要有人处理后台环境。',
|
|
605
|
+
'env.fix.whyHost': '工作台要靠命令行跑几条检查,再把结果收回来;这次命令发出去了,结果一直没回来。工具本身多半是好的 —— 重装 Node / npm / pnpm 不会有帮助。',
|
|
604
606
|
'env.fix.step': '在终端里运行下面这条命令,装好之后点「重试」:',
|
|
605
607
|
'env.fix.stepPath': '新开一个终端窗口(或确认 npm 的全局 bin 目录在 PATH 里),然后点「重试」。',
|
|
606
608
|
'env.fix.stepShell': '重启一次工作台(或 dsh);如果反复出现,说明工作台还是拿不到命令行。',
|
|
609
|
+
'env.fix.stepHost': '完全退出工作台(托盘图标也要退),清掉系统临时目录里 dsh- 开头的残留,再重新打开;反复出现就升级 dsh。',
|
|
607
610
|
'env.fix.permission': '权限不够:在命令前加 sudo 重跑,或先把 npm 的全局目录配到你的用户目录。',
|
|
608
611
|
'env.fix.network': '网络不通:检查网络或代理设置后重试。',
|
|
609
612
|
'env.fix.details': '详细输出(排障用)',
|
package/package.json
CHANGED
package/src/config/constants.ts
CHANGED
|
@@ -73,6 +73,9 @@ export const PREFLIGHT_FRESH_MS = 30_000;
|
|
|
73
73
|
/** 装 / 卸模块包的超时(毫秒):pnpm 与取包内容都按它算。 */
|
|
74
74
|
export const INSTALL_TIMEOUT_MS = 300_000;
|
|
75
75
|
|
|
76
|
+
/** 启动体检里查版本号那一条的超时(毫秒):只印个版本号,留够 opencli 每次调用约 5 秒的开销;`doctor` 要起浏览器会话,另按 `OPENCLI_TIMEOUT_MS`。 */
|
|
77
|
+
export const PREFLIGHT_VERSION_TIMEOUT_MS = 30_000;
|
|
78
|
+
|
|
76
79
|
/** 查 registry 版本那一次请求的超时(毫秒)。 */
|
|
77
80
|
export const VERSION_CHECK_TIMEOUT_MS = 10_000;
|
|
78
81
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import type { DshShell, DshShellExecution } from '../../api/dsh.js';
|
|
3
|
+
import { runShell } from '../shell.js';
|
|
4
|
+
|
|
5
|
+
function hangingShell(): DshShell {
|
|
6
|
+
return {
|
|
7
|
+
resolve: (request) => request,
|
|
8
|
+
execute: () => new Promise<DshShellExecution>(() => {}),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function replyingShell(exitCode: number, timedOut = false): DshShell {
|
|
13
|
+
return {
|
|
14
|
+
resolve: (request) => request,
|
|
15
|
+
execute: async () => ({
|
|
16
|
+
result: async () => ({
|
|
17
|
+
exitCode,
|
|
18
|
+
timedOut,
|
|
19
|
+
aborted: false,
|
|
20
|
+
stdout: { text: 'v24.21.0\n', truncated: false },
|
|
21
|
+
stderr: { text: '', truncated: false },
|
|
22
|
+
}),
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe('runShell', () => {
|
|
28
|
+
it('★ 宿主一直不交结果 → 到点自己收尾,不把调用方挂住', async () => {
|
|
29
|
+
vi.useFakeTimers();
|
|
30
|
+
try {
|
|
31
|
+
const pending = runShell(hangingShell(), 'node --version', { timeoutMs: 10_000 });
|
|
32
|
+
await vi.advanceTimersByTimeAsync(11_000);
|
|
33
|
+
const result = await pending;
|
|
34
|
+
|
|
35
|
+
expect(result.stalled).toBe(true);
|
|
36
|
+
expect(result.timedOut).toBe(true);
|
|
37
|
+
expect(result.exitCode).toBeNull();
|
|
38
|
+
expect(result.stdout).toBe('');
|
|
39
|
+
} finally {
|
|
40
|
+
vi.useRealTimers();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('★ 宿主准时交结果 → stalled=false,退出码与输出原样', async () => {
|
|
45
|
+
const result = await runShell(replyingShell(0), 'node --version');
|
|
46
|
+
|
|
47
|
+
expect(result.stalled).toBe(false);
|
|
48
|
+
expect(result.timedOut).toBe(false);
|
|
49
|
+
expect(result.exitCode).toBe(0);
|
|
50
|
+
expect(result.stdout).toBe('v24.21.0\n');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('★ 宿主自己报超时 → timedOut=true,但不算 stalled', async () => {
|
|
54
|
+
const result = await runShell(replyingShell(0, true), 'node --version');
|
|
55
|
+
|
|
56
|
+
expect(result.timedOut).toBe(true);
|
|
57
|
+
expect(result.stalled).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('★ 宿主自己抛错 → 照旧抛出去,不吞成 stalled', async () => {
|
|
61
|
+
const shell: DshShell = {
|
|
62
|
+
resolve: (request) => request,
|
|
63
|
+
execute: async () => {
|
|
64
|
+
throw new Error('spawn /bin/sh ENOENT');
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
await expect(runShell(shell, 'node --version')).rejects.toThrow('ENOENT');
|
|
69
|
+
});
|
|
70
|
+
});
|
package/src/host/preflight.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type PreflightStepId = 'toolchain' | 'cli' | 'bridge' | 'runtime' | 'diy' | 'warm';
|
|
2
2
|
export type PreflightStepStatus = 'pending' | 'running' | 'ok' | 'warn' | 'failed';
|
|
3
|
-
export type PreflightFailure = 'permission' | 'network' | 'missing' | 'unknown';
|
|
4
|
-
export type PreflightGuidance = 'install' | 'path' | 'shell';
|
|
3
|
+
export type PreflightFailure = 'permission' | 'network' | 'missing' | 'host' | 'unknown';
|
|
4
|
+
export type PreflightGuidance = 'install' | 'path' | 'shell' | 'host';
|
|
5
5
|
export type PreflightBridgeIssue = string;
|
|
6
6
|
|
|
7
7
|
export interface PreflightStep {
|
package/src/host/shell.ts
CHANGED
|
@@ -8,10 +8,37 @@ export interface ShellResult {
|
|
|
8
8
|
readonly stdout: string;
|
|
9
9
|
readonly stderr: string;
|
|
10
10
|
readonly truncated: boolean;
|
|
11
|
+
readonly stalled: boolean;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
const DEFAULT_MAX_BYTES = 8 * 1024 * 1024;
|
|
14
15
|
|
|
16
|
+
const GUARD_SLACK_MS = 1_000;
|
|
17
|
+
|
|
18
|
+
function stalledResult(): ShellResult {
|
|
19
|
+
return {
|
|
20
|
+
exitCode: null,
|
|
21
|
+
timedOut: true,
|
|
22
|
+
aborted: false,
|
|
23
|
+
stdout: '',
|
|
24
|
+
stderr: '',
|
|
25
|
+
truncated: false,
|
|
26
|
+
stalled: true,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function settleWithin<T>(work: Promise<T>, limitMs: number): Promise<T | null> {
|
|
31
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
32
|
+
const guard = new Promise<null>((resolve) => {
|
|
33
|
+
timer = setTimeout(() => resolve(null), limitMs);
|
|
34
|
+
});
|
|
35
|
+
try {
|
|
36
|
+
return await Promise.race([work, guard]);
|
|
37
|
+
} finally {
|
|
38
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
15
42
|
export async function runShell(
|
|
16
43
|
shell: DshShell,
|
|
17
44
|
command: string,
|
|
@@ -28,15 +55,22 @@ export async function runShell(
|
|
|
28
55
|
...(signal === undefined ? {} : { signal }),
|
|
29
56
|
});
|
|
30
57
|
|
|
31
|
-
const
|
|
32
|
-
|
|
58
|
+
const settled = await settleWithin(
|
|
59
|
+
(async (): Promise<ShellResult> => {
|
|
60
|
+
const execution = await shell.execute(spec);
|
|
61
|
+
const result = await execution.result();
|
|
62
|
+
return {
|
|
63
|
+
exitCode: result.exitCode,
|
|
64
|
+
timedOut: result.timedOut === true,
|
|
65
|
+
aborted: result.aborted === true,
|
|
66
|
+
stdout: result.stdout.text,
|
|
67
|
+
stderr: result.stderr.text,
|
|
68
|
+
truncated: result.stdout.truncated || result.stderr.truncated,
|
|
69
|
+
stalled: false,
|
|
70
|
+
};
|
|
71
|
+
})(),
|
|
72
|
+
timeoutMs + GUARD_SLACK_MS,
|
|
73
|
+
);
|
|
33
74
|
|
|
34
|
-
return
|
|
35
|
-
exitCode: result.exitCode,
|
|
36
|
-
timedOut: result.timedOut === true,
|
|
37
|
-
aborted: result.aborted === true,
|
|
38
|
-
stdout: result.stdout.text,
|
|
39
|
-
stderr: result.stderr.text,
|
|
40
|
-
truncated: result.stdout.truncated || result.stderr.truncated,
|
|
41
|
-
};
|
|
75
|
+
return settled ?? stalledResult();
|
|
42
76
|
}
|
package/src/i18n/en.ts
CHANGED
|
@@ -600,6 +600,7 @@ export const en: Record<keyof WorkbenchMessages, string> = {
|
|
|
600
600
|
'env.stepFailed.install': 'install failed',
|
|
601
601
|
'env.stepFailed.path': 'installed but not found',
|
|
602
602
|
'env.stepFailed.shell': 'cannot reach the command line',
|
|
603
|
+
'env.stepFailed.host': 'the command never returned',
|
|
603
604
|
'env.toolchain.ok': 'Looks good',
|
|
604
605
|
'env.toolchain.warn': 'Almost ready',
|
|
605
606
|
'env.runtime.ok': 'Ready',
|
|
@@ -612,9 +613,11 @@ export const en: Record<keyof WorkbenchMessages, string> = {
|
|
|
612
613
|
'env.fix.why': 'The workbench uses its own background tool (installed separately from the one in your terminal), and it is not set up on this machine yet.',
|
|
613
614
|
'env.fix.whyPath': 'The background tool is installed, but this environment cannot find it \u2014 usually a PATH or shell-session issue.',
|
|
614
615
|
'env.fix.whyShell': 'The workbench cannot reach the command line on this machine, so it cannot fetch data \u2014 you cannot install this from here; someone needs to fix the background environment.',
|
|
616
|
+
'env.fix.whyHost': 'The workbench runs a few checks on the command line and collects what they return; this time the command went out and nothing came back. The tools themselves are most likely fine \u2014 reinstalling Node / npm / pnpm will not help.',
|
|
615
617
|
'env.fix.step': 'Run this in a terminal, then hit Retry:',
|
|
616
618
|
'env.fix.stepPath': 'Open a new terminal window (or make sure npm\u2019s global bin directory is on PATH), then hit Retry.',
|
|
617
619
|
'env.fix.stepShell': 'Restart the workbench (or dsh); if it keeps happening, the workbench still cannot reach the command line.',
|
|
620
|
+
'env.fix.stepHost': 'Quit the workbench completely (including the tray icon), clear the dsh-* leftovers in the system temp folder, then open it again. If it keeps happening, update dsh.',
|
|
618
621
|
'env.fix.permission': 'Permission denied: rerun with sudo, or point npm\u2019s global directory at your home.',
|
|
619
622
|
'env.fix.network': 'Network unreachable: check your network or proxy, then retry.',
|
|
620
623
|
'env.fix.details': 'Details (for troubleshooting)',
|
package/src/i18n/zh.ts
CHANGED
|
@@ -596,6 +596,7 @@ export const zh = {
|
|
|
596
596
|
'env.stepFailed.install': '装不上',
|
|
597
597
|
'env.stepFailed.path': '装了但还找不到',
|
|
598
598
|
'env.stepFailed.shell': '连不上命令行',
|
|
599
|
+
'env.stepFailed.host': '命令行没有返回',
|
|
599
600
|
'env.toolchain.ok': '正常',
|
|
600
601
|
'env.toolchain.warn': '还没完全准备好',
|
|
601
602
|
'env.runtime.ok': '已就绪',
|
|
@@ -608,9 +609,11 @@ export const zh = {
|
|
|
608
609
|
'env.fix.why': '工作台用它自己那份后台工具(与你在终端里那套分开装,互不影响),这台机器上还没装好它。',
|
|
609
610
|
'env.fix.whyPath': '后台工具装上了,但当前环境还找不到它 —— 通常是 PATH 或终端会话的问题。',
|
|
610
611
|
'env.fix.whyShell': '工作台拿不到这台机器的命令行,所以取不了数据 —— 这一步你装不了,需要有人处理后台环境。',
|
|
612
|
+
'env.fix.whyHost': '工作台要靠命令行跑几条检查,再把结果收回来;这次命令发出去了,结果一直没回来。工具本身多半是好的 —— 重装 Node / npm / pnpm 不会有帮助。',
|
|
611
613
|
'env.fix.step': '在终端里运行下面这条命令,装好之后点「重试」:',
|
|
612
614
|
'env.fix.stepPath': '新开一个终端窗口(或确认 npm 的全局 bin 目录在 PATH 里),然后点「重试」。',
|
|
613
615
|
'env.fix.stepShell': '重启一次工作台(或 dsh);如果反复出现,说明工作台还是拿不到命令行。',
|
|
616
|
+
'env.fix.stepHost': '完全退出工作台(托盘图标也要退),清掉系统临时目录里 dsh- 开头的残留,再重新打开;反复出现就升级 dsh。',
|
|
614
617
|
'env.fix.permission': '权限不够:在命令前加 sudo 重跑,或先把 npm 的全局目录配到你的用户目录。',
|
|
615
618
|
'env.fix.network': '网络不通:检查网络或代理设置后重试。',
|
|
616
619
|
'env.fix.details': '详细输出(排障用)',
|