Przeglądaj źródła

test(code-mode): cover terminal output types

Tianyi Cui 2 miesięcy temu
rodzic
commit
25d0ef5c6c
1 zmienionych plików z 84 dodań i 2 usunięć
  1. 84 2
      packages/pty/tool-pty/tests/tools.spec.ts

+ 84 - 2
packages/pty/tool-pty/tests/tools.spec.ts

@@ -5,7 +5,8 @@ import { Session, SessionId } from '@deepseek-ai/dsh-session'
 import AgentRegistry from '@deepseek-ai/dsh-agent'
 import type { Agent } from '@deepseek-ai/dsh-agent'
 import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
-import ToolRegistry from '@deepseek-ai/dsh-tools'
+import ToolRegistry, { renderToolsSdk } from '@deepseek-ai/dsh-tools'
+import type { ToolSdkSchema } from '@deepseek-ai/dsh-tools/src/ts-types.ts'
 import PtyService, { PtySessionId } from '@deepseek-ai/dsh-pty'
 import type { PtyBackend, PtyBackendSession, PtySendOperation, PtySendRequest, PtySessionStatus, PtySignal } from '@deepseek-ai/dsh-pty'
 import TaskService from '@deepseek-ai/dsh-tasks'
@@ -104,6 +105,7 @@ async function setup(tasks: boolean) {
 }
 
 let callNumber = 0
+const TOOL_NAMES = ['terminal_open', 'terminal_send', 'terminal_read', 'terminal_signal', 'terminal_close', 'terminal_list'] as const
 const testToolSignal = new AbortController().signal
 function call(ctx: Context, name: string, args: unknown, agent?: Agent) {
   return ctx.tools.execute({ signal: testToolSignal, callId: CallId(`pty-call-${++callNumber}`), name, arguments: args, ...agent ? { agent } : {} })
@@ -120,7 +122,7 @@ function text(result: { content: { type: string; text?: string }[] }): string {
 describe('tool-pty foreground surface', () => {
   it('registers exactly six schemas and drives the full owner-scoped lifecycle', async () => {
     const { ctx, agent } = await setup(false)
-    expect(['terminal_open', 'terminal_send', 'terminal_read', 'terminal_signal', 'terminal_close', 'terminal_list'].every(name => ctx.tools.get(name) !== undefined)).toBe(true)
+    expect(TOOL_NAMES.every(name => ctx.tools.get(name) !== undefined)).toBe(true)
 
     const spawned = await call(ctx, 'terminal_open', { type: 'stub', name: 'main' }, agent)
     expect(text(spawned)).toContain('started terminal session pty-1 (main)')
@@ -170,6 +172,86 @@ describe('tool-pty foreground surface', () => {
     expect(empty).toMatchObject({ isError: false, value: [] })
   })
 
+  it('projects every terminal DTO into the generated Code Mode output map', async () => {
+    const { ctx } = await setup(false)
+    const schemas = TOOL_NAMES.map((toolName): ToolSdkSchema => {
+      const definition = ctx.tools.get(toolName)
+      if (definition === undefined) throw new Error(`missing terminal tool ${toolName}`)
+      return {
+        name: definition.name,
+        description: definition.description,
+        parameters: definition.parameters,
+        output: definition.output.schema,
+      }
+    })
+    const sdk = renderToolsSdk(schemas)
+    const outputMapStart = sdk.indexOf('interface ToolOutputMap')
+    const outputMapEnd = sdk.indexOf('\n\ntype ToolName', outputMapStart)
+
+    expect(sdk.slice(outputMapStart, outputMapEnd)).toMatchInlineSnapshot(`
+      "interface ToolOutputMap {
+        terminal_close: {
+          sessionId: string;
+          outcome: "closed" | "already-closing";
+        };
+        terminal_list: ({
+          sessionId: string;
+          name?: string;
+          type: string;
+          pid?: number;
+          status: {
+            kind: "running";
+          } | {
+            kind: "exited";
+            exitCode: number | null;
+            signal: string | null;
+          };
+        })[];
+        terminal_open: {
+          sessionId: string;
+          name?: string;
+          type: string;
+          pid?: number;
+          status: {
+            kind: "running";
+          } | {
+            kind: "exited";
+            exitCode: number | null;
+            signal: string | null;
+          };
+          motd: string;
+        };
+        terminal_read: {
+          text: string;
+          totalLines: number;
+          lineBegin: number;
+          lineEnd: number;
+          truncated: boolean;
+        };
+        terminal_send: {
+          kind: "background";
+          taskId: string;
+        } | {
+          kind: "foreground";
+          viewport: string;
+          waitReason: "stdin_read" | "inferred_idle" | "timeout" | "session_exit";
+          sessionStatus: {
+            kind: "running";
+          } | {
+            kind: "exited";
+            exitCode: number | null;
+            signal: string | null;
+          };
+          truncated: boolean;
+        };
+        terminal_signal: {
+          delivered: true;
+          targetPgid: number;
+        };
+      }"
+    `)
+  })
+
   it('fails without an initiating agent and rejects background before writing', async () => {
     const { ctx, agent, stub } = await setup(false)
     expect((await call(ctx, 'terminal_open', { type: 'stub' })).isError).toBe(true)