feat: add persistent PTY sessions

This commit is contained in:
NI0317
2026-07-21 16:01:00 +08:00
parent b4750f6333
commit 58cde5103a
71 changed files with 5677 additions and 82 deletions

View File

@@ -77,6 +77,17 @@ export const LINK_MAP: Record<string, string> = {
ConfinedArgv: 'sandbox.md',
SandboxMode: 'sandbox.md',
SandboxPolicy: 'sandbox.md',
PtyBackend: 'pty.md',
PtyReadRequest: 'pty.md',
PtyReadResult: 'pty.md',
PtySendOperation: 'pty.md',
PtySendRequest: 'pty.md',
PtySessionId: 'pty.md',
PtySessionSnapshot: 'pty.md',
PtySignal: 'pty.md',
PtySignalResult: 'pty.md',
PtySpawnRequest: 'pty.md',
PtySpawnResult: 'pty.md',
ScopeKey: 'scope.md',
Scoped: 'scope.md',
EpochHeader: 'session.md',

View File

@@ -59,6 +59,7 @@ const GROUP_ORDER = [
'llm',
'core',
'bash',
'pty',
'sandbox',
'fs',
'skill',
@@ -124,7 +125,7 @@ const SERVICE_ROLES: ServiceRole[] = [
pkg: 'system-prompt',
title: 'System prompt assembly registry',
mode: 'core',
consumers: ['agent-loop', 'tools', 'tool-fs', 'tool-web'],
consumers: ['agent-loop', 'tools', 'tool-fs', 'tool-pty', 'tool-web'],
note: 'Collects prompt sections and model-facing tool schemas for each step.',
},
{
@@ -132,7 +133,7 @@ const SERVICE_ROLES: ServiceRole[] = [
pkg: 'tools',
title: 'Tool registry and guarded execution pipeline',
mode: 'core',
consumers: ['agent-loop', 'tool-ask-user', 'tool-bash', 'tool-cordis', 'tool-fs', 'tool-skill', 'tool-subagent', 'tool-todo', 'tool-web', 'acp'],
consumers: ['agent-loop', 'tool-ask-user', 'tool-bash', 'tool-cordis', 'tool-fs', 'tool-pty', 'tool-skill', 'tool-subagent', 'tool-todo', 'tool-web', 'acp'],
note: 'Registers capabilities, owns Code Mode transport, and routes calls through pre-policy, monotonic guards, around dispatch, post-policy, and final-result observation.',
},
{
@@ -185,13 +186,22 @@ const SERVICE_ROLES: ServiceRole[] = [
mode: 'core',
note: 'Plugins declare effect-scoped DSH_* facts; tool-bash collects one trusted snapshot per execution and the executor rebuilds the namespace.',
},
{
key: 'pty',
pkg: 'pty',
title: 'Persistent PTY session registry',
mode: 'seam',
implementations: ['pty-local'],
consumers: ['tool-pty'],
note: 'The registry owns exact-Agent session identity and cleanup; backends own terminal mechanics, while tool-pty exposes the owner-scoped model surface.',
},
{
key: 'sandbox',
pkg: 'sandbox',
title: 'Process-sandbox seam',
mode: 'seam',
implementations: ['sandbox-local'],
consumers: ['bash-sandbox'],
consumers: ['bash-sandbox', 'pty-local'],
note: 'Consumers hand over the exact argv they are about to spawn; same-world backends wrap it under a per-call policy and report enforcement.',
},
{
@@ -200,7 +210,7 @@ const SERVICE_ROLES: ServiceRole[] = [
title: 'Sandbox policy home',
mode: 'core',
implementations: [],
consumers: ['bash-sandbox', 'fs-sandbox'],
consumers: ['bash-sandbox', 'fs-sandbox', 'pty-local'],
note: 'The one home for the deployment default mode + workspace root; only the sandboxed executor and provider read the service (the tool layers use the pure `sandbox/mode` fold it also exports). Both enforcing families read it so bash and fs cannot confine to different roots.',
},
{
@@ -263,8 +273,8 @@ const SERVICE_ROLES: ServiceRole[] = [
pkg: 'tasks',
title: 'Background task registry',
mode: 'core',
consumers: ['tool-bash', 'tool-subagent', 'tool-tasks'],
note: 'Producers (tool-bash background commands, tool-subagent background delegations) register running work; tool-tasks is the model-facing control surface that reads, lists, and kills it.',
consumers: ['tool-bash', 'tool-pty', 'tool-subagent', 'tool-tasks'],
note: 'Producers (background bash, PTY sends, and subagent delegations) register running work; tool-tasks is the model-facing control surface that reads, lists, and kills it.',
},
{
key: 'web',

View File

@@ -30,6 +30,8 @@ import * as ToolBash from '@deepseek-ai/dsh-tool-bash'
import * as ToolCordis from '@deepseek-ai/dsh-tool-cordis'
import * as ToolFs from '@deepseek-ai/dsh-tool-fs'
import * as ToolFsSearch from '@deepseek-ai/dsh-tool-fs-search'
import PtyService from '@deepseek-ai/dsh-pty'
import * as ToolPty from '@deepseek-ai/dsh-tool-pty'
import * as ToolSkill from '@deepseek-ai/dsh-tool-skill'
import * as ToolTasks from '@deepseek-ai/dsh-tool-tasks'
import * as ToolTodo from '@deepseek-ai/dsh-tool-todo'
@@ -219,6 +221,19 @@ const TOOL_PACKAGES: ToolPackage[] = [
note:
'glob and grep are conditional bash-backed discovery tools: they register only when ctx.bash can find `rg`, then run fixed ripgrep commands through ctx.bash as ordinary foreground calls (never background tasks). Capped results save the complete formatted list through the optional ctx.spillStore backend; returned locators are follow-up-readable/searchable when the backend exposes local paths in co-located deployments.',
},
{
pkg: '@deepseek-ai/dsh-tool-pty',
dir: 'tool-pty',
source: 'packages/pty/tool-pty/src/index.ts',
requires: ['ctx.tools', 'ctx.pty', 'ctx.systemPrompt', 'ctx.tasks at call time for run_in_background'],
writes: ['tool/call', 'tool/result'],
async mount(ctx) {
await ctx.plugin(PtyService)
await ctx.plugin(ToolPty)
},
note:
'The six PTY tools are opt-in and complement one-shot bash/filesystem tools. `pty_send(run_in_background: true)` registers with `ctx.tasks`; TUI, named key sequences, BEL, resize, auto-start, and cross-agent sharing are absent from the schema.',
},
{
pkg: '@deepseek-ai/dsh-tool-skill',
dir: 'tool-skill',

View File

@@ -118,6 +118,12 @@
{ "doc": "docs/core-data-structures/tasks.md", "symbol": "TaskOutcome", "source": "packages/tasks/tasks/src/types.ts" },
{ "doc": "docs/core-data-structures/tasks.md", "symbol": "TaskSnapshot", "source": "packages/tasks/tasks/src/types.ts" },
{ "doc": "docs/core-data-structures/tasks.md", "symbol": "TaskRead", "source": "packages/tasks/tasks/src/types.ts" },
{ "doc": "docs/core-data-structures/pty.md", "symbol": "PtyWaitReason", "source": "packages/pty/pty/src/types.ts" },
{ "doc": "docs/core-data-structures/pty.md", "symbol": "PtySessionStatus", "source": "packages/pty/pty/src/types.ts" },
{ "doc": "docs/core-data-structures/pty.md", "symbol": "PtyBackend", "source": "packages/pty/pty/src/types.ts" },
{ "doc": "docs/core-data-structures/pty.md", "symbol": "PtyBackendSession", "source": "packages/pty/pty/src/types.ts" },
{ "doc": "docs/core-data-structures/pty.md", "symbol": "PtySendOperation", "source": "packages/pty/pty/src/types.ts" },
{ "doc": "docs/core-data-structures/pty.md", "symbol": "PtySendResult", "source": "packages/pty/pty/src/types.ts" },
{ "doc": "docs/core-data-structures/sandbox.md", "symbol": "SandboxMode", "source": "packages/sandbox/sandbox/src/index.ts" },
{ "doc": "docs/core-data-structures/sandbox.md", "symbol": "ConfinedSandboxMode", "source": "packages/sandbox/sandbox/src/index.ts" },