refactor(pty): rename model-facing tools to terminal_* and harden teardown

Rename the six model-facing tools pty_* -> terminal_* and align every
description, guidance section, ACP card title, and rendered result to
terminal terminology. Package and service internals keep their technical
PTY names (PtyService, "unknown PTY session", node-pty).

Harden the local backend teardown:
- a failed close is retryable: drop the memoized rejection so a later
  terminal_close re-runs against the live process table
- service disposal clears the backend, reservation, and owner-cleanup
  registries even when a close fails
- stop readiness polling before teardown so an in-flight send settles as
  session_exit instead of a mis-inferred wait reason
- bound the sanitizer's pending buffer against unterminated escape runs

Update the tool catalog, package READMEs, the bilingual Agent Note, and the
acp/headless pty-tools snapshots to match.
This commit is contained in:
NI0317
2026-07-21 19:29:56 +08:00
parent 85ac747208
commit a7bfade7eb
28 changed files with 568 additions and 401 deletions

View File

@@ -5,7 +5,7 @@ import { renderList, renderRead, renderSend, renderSendRead, renderSpawn } from
describe('tool-pty rendering', () => {
it('renders spawn with and without names or MOTD', () => {
expect(renderSpawn({ sessionId: PtySessionId('pty-1'), type: 'shell', status: { kind: 'running' }, motd: '' }))
.toBe('started PTY session pty-1 [type: shell]\n(no startup output)')
.toBe('started terminal session pty-1 [type: shell]\n(no startup output)')
expect(renderSpawn({ sessionId: PtySessionId('pty-2'), name: 'main', type: 'shell', pid: 2, status: { kind: 'running' }, motd: 'ready' }))
.toContain('pty-2 (main)')
})
@@ -28,7 +28,7 @@ describe('tool-pty rendering', () => {
it('renders history and every list status shape', () => {
expect(renderRead({ text: '', totalLines: 0, lineBegin: 0, lineEnd: 0, truncated: true }))
.toBe('(no retained output)\n[lines: 0-0 of 0]\n[output truncated]')
expect(renderList([])).toBe('(no PTY sessions)')
expect(renderList([])).toBe('(no terminal sessions)')
expect(renderList([
{ sessionId: PtySessionId('pty-1'), type: 'shell', status: { kind: 'running' } },
{ sessionId: PtySessionId('pty-2'), name: 'done', type: 'shell', pid: 9, status: { kind: 'exited', exitCode: 2, signal: null } },