Add ask_user_question interaction tool

This commit is contained in:
Yichen Jiang
2026-06-25 22:51:38 +08:00
parent 329371a529
commit 08fc8467bc
31 changed files with 1083 additions and 16 deletions

View File

@@ -1,5 +1,7 @@
# @deepseek-ai/dsh-stdio-agent
Terminal stdio chat app. It composes the agent-core spine with JSONL persistence, the readline stdio UI, the user-interaction seam, and the `ask_user_question` tool so the demo/coding front door can pause for human confirmation.
The **terminal stdio chat app**: a Cordis app plugin that composes the providerless agent spine ([`@deepseek-ai/dsh-agent-core`](../../core/agent-core/README.md)) with the front-door cluster a terminal chat needs, and a `bin` that boots a leaf `cordis.yml`.
It is the readline counterpart to [`@deepseek-ai/dsh-acp-agent`](../acp-agent/README.md): both consume the same spine, but each bakes in the OPPOSITE front-door cluster.
@@ -13,7 +15,9 @@ A terminal chat always wants the same cluster, so the package owns it rather tha
| `@cordisjs/plugin-logger-console` | the console logger — stdout is just the terminal here, so logging to it is correct (the ACP app must NOT have this) |
| `@deepseek-ai/dsh-agent-core` | the spine, pre-creating a `main` agent from this app's `model`/`systemPrompt` |
| `@deepseek-ai/dsh-session-persistence-jsonl` | durable JSONL session log under `persistenceRoot` |
| `@deepseek-ai/dsh-ui-stdio` | the readline UI, bound to the `main` agent |
| `@deepseek-ai/dsh-user-interaction` | the human question/answer seam used by confirmation tools |
| `@deepseek-ai/dsh-tool-ask-user` | the model-facing `ask_user_question` tool |
| `@deepseek-ai/dsh-ui-stdio` | the readline UI, bound to the `main` agent, and the user-interaction provider |
`@cordisjs/plugin-hmr` (the dev/demo edit-reload loop) is deliberately a **leaf** entry, NOT baked in here: it is a Loader-only, subprocess-only dev plugin — its constructor throws without `node --expose-internals` + a live `loader`, and the in-process test tier cannot even import it (so a package whose `apply` statically pulled it in could never carry the per-file coverage gate). Unlike the console logger, a stray `hmr` is not a stdout-purity footgun, so leaving it at the leaf costs no safety. The `demo:echo` / `demo:coding` leaves load it and pass `--expose-internals`.

View File

@@ -37,7 +37,9 @@
"@deepseek-ai/dsh-agent-core": "^0.0.1",
"@deepseek-ai/dsh-session": "^0.0.1",
"@deepseek-ai/dsh-session-persistence-jsonl": "^0.0.1",
"@deepseek-ai/dsh-tool-ask-user": "^0.0.1",
"@deepseek-ai/dsh-ui-stdio": "^0.0.1",
"@deepseek-ai/dsh-user-interaction": "^0.0.1",
"cordis": "^4.0.0-rc.6",
"schemastery": "^3.17.0"
},
@@ -49,7 +51,9 @@
"@deepseek-ai/dsh-agent-core": "workspace:^",
"@deepseek-ai/dsh-session": "workspace:^",
"@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^",
"@deepseek-ai/dsh-tool-ask-user": "workspace:^",
"@deepseek-ai/dsh-ui-stdio": "workspace:^",
"@deepseek-ai/dsh-user-interaction": "workspace:^",
"cordis": "^4.0.0-rc.6",
"schemastery": "^3.17.0"
}

View File

@@ -41,6 +41,8 @@ import { AgentId } from '@deepseek-ai/dsh-agent'
import { SessionId } from '@deepseek-ai/dsh-session'
import * as agentCore from '@deepseek-ai/dsh-agent-core'
import SessionPersistenceJsonl from '@deepseek-ai/dsh-session-persistence-jsonl'
import UserInteractionService from '@deepseek-ai/dsh-user-interaction'
import * as toolAskUser from '@deepseek-ai/dsh-tool-ask-user'
import * as uiStdio from '@deepseek-ai/dsh-ui-stdio'
export const name = 'stdio-agent'
@@ -94,5 +96,7 @@ export function apply(ctx: Context, config: Config): void {
}],
})
ctx.plugin(SessionPersistenceJsonl, { root: config.persistenceRoot ?? './.sessions' })
ctx.plugin(UserInteractionService)
ctx.plugin(toolAskUser)
ctx.plugin(uiStdio, { welcome: config.welcome ?? 'ready.', agent: 'main' })
}

View File

@@ -34,7 +34,8 @@ const stdioBin = join(repoRoot, 'packages/ui/stdio-agent/lib/bin.js')
// to the built `lib/` (package.json `main`), exactly as an installed dep would.
const dshPackages = [
'core/agent-core', 'core/agent', 'core/session', 'core/system-prompt',
'core/tools', 'core/agent-loop', 'llm/llm', 'bash/bash', 'bash/bash-local',
'core/tools', 'core/user-interaction', 'core/tool-ask-user',
'core/agent-loop', 'llm/llm', 'bash/bash', 'bash/bash-local',
'bash/tool-bash', 'support/invariants', 'support/ui-stdio',
'session-persistence/session-persistence',
'session-persistence/session-persistence-jsonl', 'ui/stdio-agent',

View File

@@ -33,6 +33,8 @@ describe('dsh-stdio-agent app', () => {
expect(ctx.get('agents')).toBeDefined()
expect(ctx.get('agentLoop')).toBeDefined()
expect(ctx.get('sessionPersistence')).toBeDefined()
expect(ctx.get('userInteraction')).toBeDefined()
expect(ctx.get('tools')?.get('ask_user_question')).toBeDefined()
// The pre-created `main` agent the UI drives.
expect(ctx.get('agents')?.get(AgentId('main'))).toBeDefined()
await ctx.fiber.dispose()

View File

@@ -29,6 +29,12 @@
{
"path": "../../core/agent-core"
},
{
"path": "../../core/user-interaction"
},
{
"path": "../../core/tool-ask-user"
},
{
"path": "../../session-persistence/session-persistence-jsonl"
},