Merge remote-tracking branch 'origin/master' into worktree/web-multimodal-image-input

This commit is contained in:
creatixchu
2026-07-24 20:01:36 +08:00
107 changed files with 4589 additions and 502 deletions

View File

@@ -4,7 +4,7 @@
*/
import { randomUUID } from 'node:crypto'
import { stat } from 'node:fs/promises'
import { mkdir, stat } from 'node:fs/promises'
import type { Context } from 'cordis'
import type { Agent, AgentStatus } from '@deepseek-ai/dsh-agent'
import { AttachmentError } from '@deepseek-ai/dsh-attachment-local'
@@ -474,8 +474,18 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
const sessionId = `session-${randomUUID()}` as SessionId
// A session's cwd is its project path. When the creator does not choose
// one, the default project is the host-level default (the host process
// working directory unless boot overrides it).
// working directory unless boot overrides it). Ensure the directory
// exists so Create-workspace and typed paths land on a real folder.
const cwd = request.payload.cwd ?? defaults.cwd
try {
await mkdir(cwd, { recursive: true })
} catch (error: unknown) {
return err(request, {
code: 'internal',
message: `failed to ensure project directory "${cwd}": ${String(error)}`,
details: {},
})
}
const handle = await ctx.agents.create({ sessionId, agentOptions, meta: { cwd } })
return ok(request, { sessionId: handle.agent.id })
},

View File

@@ -286,6 +286,29 @@ describe('sessions.create / list', () => {
expect(first?.running).toBe(false)
expect(first?.parentSessionId).toBeUndefined()
})
it('ensures a missing project directory before minting the session', async () => {
const { api } = await boot()
const root = mkdtempSync(join(tmpdir(), 'dsh-host-create-cwd-'))
const cwd = join(root, 'nested', 'workspace')
expect(existsSync(cwd)).toBe(false)
const { sessionId } = expectOk(await api.sessions.create(request({ cwd })))
expect(existsSync(cwd)).toBe(true)
const { items } = expectOk(await api.sessions.list(request({})))
expect(items.find(item => item.sessionId === sessionId)?.cwd).toBe(cwd)
})
it('fails loud when the project directory cannot be created', async () => {
const { api } = await boot()
const root = mkdtempSync(join(tmpdir(), 'dsh-host-create-cwd-fail-'))
const blocker = join(root, 'file-not-dir')
writeFileSync(blocker, 'x')
const response = await api.sessions.create(request({ cwd: join(blocker, 'child') }))
expect(response.result.ok).toBe(false)
if (response.result.ok) throw new Error('expected mkdir failure')
expect(response.result.error.code).toBe('internal')
expect(response.result.error.message).toMatch(/failed to ensure project directory/)
})
})
describe('sessions.prompt / cancel', () => {