fix(stdio): close startup failure gaps

This commit is contained in:
Tianyi Cui
2026-07-16 02:00:56 +08:00
parent a6e406a778
commit d56cc8d424
4 changed files with 30 additions and 14 deletions
@@ -20,17 +20,26 @@ export async function main(boot: SdkBootContext) {
{{/if}}
const ctx = await startSDK(new URL('./cordis.yml', import.meta.url))
{{#if isStdio}}
if (resume === undefined) {
await ctx.agents.create({
sessionId,
meta: { cwd: boot.cwd },
agentOptions: { model },
})
} else {
await ctx.agents.resume({
resumeSessionId: sessionId,
agentOptions: { model },
})
try {
if (resume === undefined) {
await ctx.agents.create({
sessionId,
meta: { cwd: boot.cwd },
agentOptions: { model },
})
} else {
await ctx.agents.resume({
resumeSessionId: sessionId,
agentOptions: { model },
})
}
} catch (error) {
try {
await ctx.fiber.dispose()
} catch (disposeError) {
throw new AggregateError([error, disposeError], 'stdio startup and cleanup failed')
}
throw error
}
{{else}}
{{#if isEmbed}}
@@ -171,6 +171,8 @@ describe('SdkProject and ProjectEditSession', () => {
expect(index).toContain('const sessionId = SessionId(resume ?? `main-session-${randomUUID()}`)')
expect(index).toContain('process.env.DSH_SDK_SESSION_ID = sessionId')
expect(index).toContain('resumeSessionId: sessionId')
expect(index).toContain('await ctx.fiber.dispose()')
expect(index).toContain("new AggregateError([error, disposeError], 'stdio startup and cleanup failed')")
expect(project.packageManifest().scripts).toEqual({
dev: 'dsh-sdk dev index.ts -- --model="deepseek-v4-flash"',
build: 'dsh-sdk build',
+3 -3
View File
@@ -9,7 +9,7 @@ This package owns the terminal channel only. It injects `agents` and `userIntera
| Key | Default | Meaning |
|---|---|---|
| `welcome` | `ready.` | Banner printed before the first prompt |
| `agent` | `main` | Agent id driven by stdin and observed for EOF shutdown |
| `sessionId` | `main` | Exact agent/session identity driven by stdin and observed for EOF shutdown |
The plugin seeds display labels from the live agent registry, then tracks `agent/created` and `agent/disposed` so HMR and externally managed agents render consistently. Disposal closes readline and unregisters every listener/provider through Cordis effects.
@@ -18,7 +18,7 @@ The plugin seeds display labels from the live agent registry, then tracks `agent
name: '@deepseek-ai/dsh-stdio'
config:
welcome: 'agent REPL ready. Give it a coding task.'
agent: main
sessionId: main
```
## Model Experience
@@ -37,6 +37,6 @@ The plugin seeds display labels from the live agent registry, then tracks `agent
## Known Limitations and Deferred Work
- **One configured agent receives stdin** — the session/event renderer can print output from any session, but input lines always drive the configured `agent` id rather than routing by the visible label.
- **One configured session receives stdin** — the session/event renderer can print output from any session, but input lines always drive the configured `sessionId` rather than routing by the visible label.
- **Terminal questions are text-only and sequential** — the provider queues asks, supports option labels plus custom text, and has no richer UI shapes such as file pickers or diff previews.
- **Closed stdin ends the terminal channel** — EOF rejects active or queued questions and exits after submitted work reaches idle; there is no reconnect path for a long-lived process.
+5
View File
@@ -29,6 +29,11 @@
"@deepseek-ai/dsh-user-interaction": "^0.0.1",
"cordis": "^4.0.0-rc.7"
},
"peerDependenciesMeta": {
"@deepseek-ai/dsh-agent-loop": {
"optional": true
}
},
"dependencies": {
"schemastery": "^3.18.0"
},