Merge remote-tracking branch 'upstream/master' into ux/automation-tasks-plugin-row

This commit is contained in:
ZiyaZhang committed 2026-09-26 06:10:21 -07:00
commit 9626323fc4
6 files changed
+47 -38

No files matched your search

+2 -2
View File
@@ -21,8 +21,8 @@
en: 0d11af8639977a6d
zh: 86b086b12d2210d3
/deepseek-harness-desktop/develop:
en: 9b9b362a9865e763
zh: c748901168e2db8c
en: 40d2ad4014bf445b
zh: 6a08de06df9ed042
/deepseek-harness-desktop/develop/startup-onboarding:
en: a51346b8d880ddba
zh: 7913214c1c66063c
+1 -1
View File
@@ -134,7 +134,7 @@ pnpm run start:desktop
The Web counterparts are `pnpm run dev:web` and `pnpm run start:web`, documented in the [development guide](../../docs/development.md). Workspace development runs the current CLI and private Desktop Host packages under Electron RunAsNode. Plugin management and recovery use `$DSH_HOME/profiles/desktop`, separate from the disposable workspace runtime. The Host uses runtime module resolution in both development and packaged builds without creating official-package fallback links; developer-installed packages, including links, retain native priority. Use an unpacked application to exercise Electron RunAsNode, bundled pnpm, bundled dsh resources, plugin installation and repair paths.
The [native/renderer keyboard tests](tests/keyboard.spec.ts) compile in [their own Client test project](../../tsconfig.desktop-keyboard-tests.json), reached by the repository Client typecheck. Its Desktop imports are limited to Cordis-free input, persistence, IPC, browser-guest, and overlay modules.
The [native/renderer keyboard tests](tests/keyboard.spec.ts) compile as part of the repository Client typecheck. Their Desktop imports are limited to Cordis-free input, persistence, IPC, browser-guest, and overlay modules.
### Startup onboarding
+1 -1
View File
@@ -136,7 +136,7 @@ pnpm run start:desktop
Web 侧的对应命令是 `pnpm run dev:web` 与 `pnpm run start:web`,见[开发指南](../../docs/development.zh.md)。Workspace 开发使用 Electron RunAsNode 运行当前 CLI 与私有 Desktop Host 包,插件管理和恢复使用 `$DSH_HOME/profiles/desktop`,与一次性工作区运行时分离。Host 在开发与打包构建中都使用 runtime 模块解析,不创建官方包的 fallback 链接;开发者安装的包(包括链接)保留原生优先级。需要验证 Electron RunAsNode、内置 pnpm、内置 dsh 资源、插件安装和修复时,应运行未封装安装器的应用目录。
[原生输入与渲染进程键盘测试](tests/keyboard.spec.ts)在[独立的 Client 测试项目](../../tsconfig.desktop-keyboard-tests.json)中编译,由仓库 Client 类型检查纳入。它只导入不依赖 Cordis 的 Desktop 输入、持久化、IPC、浏览器 guest 和蒙层模块。
[原生输入与渲染进程键盘测试](tests/keyboard.spec.ts)直接纳入仓库 Client 类型检查。它只导入不依赖 Cordis 的 Desktop 输入、持久化、IPC、浏览器 guest 和蒙层模块。
### 启动引导
+35 -9
View File
@@ -7,6 +7,7 @@ import {
mkdtempSync,
lstatSync,
readFileSync,
realpathSync,
renameSync,
rmSync,
symlinkSync,
@@ -158,9 +159,15 @@ function gitDirectory(fixture: Fixture, root: string): string {
return git(fixture, root, ['rev-parse', '--absolute-git-dir'])
}
// The installer resolves the common directory against Git's own top-level path, and the host
// spells that path differently from the fixture directory this file created: Git canonicalizes
// Windows 8.3 short names and the macOS `/var` symlink, while `mkdtempSync` returns the temp
// directory's own spelling. Canonicalizing the fixture-side directory collapses both spellings
// onto the one directory the installer touches, so an injected failure on this path reaches the
// installer's own lock instead of a differently spelled name for it.
function commonDirectory(fixture: Fixture): string {
const output = git(fixture, fixture.main, ['rev-parse', '--git-common-dir'])
return isAbsolute(output) ? output : resolve(fixture.main, output)
return realpathSync.native(isAbsolute(output) ? output : resolve(fixture.main, output))
}
function hooksPath(fixture: Fixture, root: string): string {
@@ -321,14 +328,11 @@ describe('worktree-local Lefthook installer', { timeout: 90_000 }, () => {
expect(existsSync(join(hooksPath(fixture, fixture.main), '.fake-lefthook-running'))).toBe(false)
})
it.each([
{ operation: 'openSync', code: 'EPERM', expires: false },
{ operation: 'readFileSync', code: 'EPERM', expires: false },
{ operation: 'lstatSync', code: 'EPERM', expires: false },
{ operation: 'openSync', code: 'EPERM', expires: true },
{ operation: 'openSync', code: 'EACCES', expires: false },
])('handles $operation $code with expired deadline=$expires', async ({ operation, code, expires }) => {
const fixture = createFixture()
/** Inject one lock-access failure and assert the installer's documented outcome. */
async function expectInjectedLockAccessFailure(
fixture: Fixture,
{ operation, code, expires }: { operation: string; code: string; expires: boolean },
): Promise<void> {
const lockPath = installLockPath(fixture)
const probe = join(fixture.container, 'lock-access-probe')
const preload = join(fixture.container, 'lock-access.cjs')
@@ -369,6 +373,28 @@ syncBuiltinESMExports()
expect(result.stderr).toContain('injected lock access failure')
expect(existsSync(hooksPath(fixture, fixture.main))).toBe(false)
}
}
it.each([
{ operation: 'openSync', code: 'EPERM', expires: false },
{ operation: 'readFileSync', code: 'EPERM', expires: false },
{ operation: 'lstatSync', code: 'EPERM', expires: false },
{ operation: 'openSync', code: 'EPERM', expires: true },
{ operation: 'openSync', code: 'EACCES', expires: false },
])('handles $operation $code with expired deadline=$expires', async ({ operation, code, expires }) => {
await expectInjectedLockAccessFailure(createFixture(), { operation, code, expires })
})
// The alias forces the installer's resolved common directory to differ from the path this spec
// composes on every host — a junction on Windows, a directory symlink elsewhere — instead of
// depending on a runner whose temp directory happens to carry a short name.
it('handles an injected lock failure through an aliased worktree root', async () => {
const fixture = createFixture()
const alias = join(fixture.container, 'main-alias')
symlinkSync(fixture.main, alias, process.platform === 'win32' ? 'junction' : 'dir')
fixture.main = alias
await expectInjectedLockAccessFailure(fixture, { operation: 'openSync', code: 'EPERM', expires: false })
})
it('waits for a concurrent installer to finish publishing its lock record', async () => {
+8 -1
View File
@@ -14,6 +14,13 @@
"types": ["node"]
},
"include": [
// The native/renderer keyboard fixture imports only these Cordis-free Desktop modules.
"apps/desktop/tests/keyboard.spec.ts",
"apps/desktop/src/keyboard.ts",
"apps/desktop/src/keybindings.ts",
"apps/desktop/src/browser-guests.ts",
"apps/desktop/src/ipc.ts",
"apps/desktop/src/update-overlay.ts",
"apps/desktop/tests/**/*.client.spec.tsx",
// Source-subpath test imports can arrive through workspace links whose
// realpath semantics vary by host. Load package CSS declarations directly.
@@ -43,8 +50,8 @@
"packages/client/*/tests/**/*.host.spec.ts"
],
"references": [
{ "path": "./tsconfig.desktop-keyboard-tests.json" },
{ "path": "./apps/desktop/tsconfig.client.json" },
{ "path": "./packages/util/atomic-write" },
{ "path": "./packages/experimental/client-ui-voice-input" },
{ "path": "./packages/client/ui-sidebar-terminal" },
-24
View File
@@ -1,24 +0,0 @@
{
// The native/renderer integration fixture imports only Cordis-free Desktop modules.
"extends": "./tsconfig.base.client.json",
"compilerOptions": {
"rootDir": ".",
"outDir": "lib/desktop-keyboard-test-types",
"emitDeclarationOnly": true,
"types": ["node"]
},
"files": [
"apps/desktop/tests/keyboard.spec.ts",
"apps/desktop/src/keyboard.ts",
"apps/desktop/src/keybindings.ts",
"apps/desktop/src/browser-guests.ts",
"apps/desktop/src/ipc.ts",
"apps/desktop/src/update-overlay.ts"
],
"include": [],
"references": [
{ "path": "./packages/client/shortcuts/tsconfig.client.json" },
{ "path": "./packages/client/ui-sidebar-browser/tsconfig.client.json" },
{ "path": "./packages/util/atomic-write" }
]
}