fix(projects): require creation directories and show remote directory links

Require a root folder in the local project creation dialog and IPC while preserving updates to historical projects with blank paths. Show remote symlinks whose targets are directories and resolve their canonical paths when browsing.

Validation: focused UI, contract, IPC and SSH tests passed; typecheck and lint passed. Verified directory links on the shared Linux Host. Full test run timed out after a Magic Notes storage timing failure.

Release note: 新建本地项目必须选择目录;远程项目选择目录时可查看并进入指向目录的符号链接。
This commit is contained in:
mesalogo
2026-10-04 15:00:13 +08:00
parent 629e82545b
commit ee186f9f70
15 changed files with 309 additions and 29 deletions
+14
View File
@@ -159,6 +159,20 @@ describe('isUntouchedBuiltInDefaultProject', () => {
})
describe('project execution space contracts', () => {
it.each(['', ' ', '\t\n'])('rejects blank creation paths but preserves updates: %j', (rootPath) => {
const input = { name: 'Project', description: '', rootPath, defaultWorkMode: 'ask' }
const result = projectCreateSchema.safeParse(input)
expect(result.success).toBe(false)
if (!result.success) expect(result.error.issues[0]?.path).toEqual(['rootPath'])
expect(projectUpdateSchema.parse(input).rootPath).toBe('')
})
it.each(['C:\\Workspace', '/home/user/project'])('accepts and trims a creation directory: %s', (rootPath) => {
expect(projectCreateSchema.parse({
name: 'Project', description: '', rootPath: ` ${rootPath} `, defaultWorkMode: 'ask'
}).rootPath).toBe(rootPath)
})
it('parses strict local and SSH output without normalizing paths', () => {
expect(
projectExecutionSpaceSchema.parse({
+4 -2
View File
@@ -277,7 +277,7 @@ export function normalizeInteractiveWorkMode(
return workMode === 'execute' ? 'execute' : 'ask'
}
export const projectCreateSchema = z
export const projectUpdateSchema = z
.object({
name: z.string().trim().min(1).max(120),
description: z.string().trim().max(2_000),
@@ -288,7 +288,9 @@ export const projectCreateSchema = z
})
.strict()
export const projectUpdateSchema = projectCreateSchema
export const projectCreateSchema = projectUpdateSchema.extend({
rootPath: z.string().trim().min(1).max(4_096)
})
export type ProjectCreateInput = z.infer<typeof projectCreateSchema>