浏览代码

fix(shell): preserve prompt-like PowerShell output

_Kerman 1 月之前
父节点
当前提交
2f759a6b65

+ 1 - 1
packages/shell/tool-pwsh-persistent/package.json

@@ -1,7 +1,7 @@
 {
   "name": "@deepseek-ai/dsh-tool-pwsh-persistent",
   "description": "Model-facing owner-scoped persistent PowerShell tool backed by the Harness PTY service",
-  "version": "0.1.0-rc.6",
+  "version": "0.1.0-rc.7",
   "publishConfig": {
     "access": "public"
   },

+ 1 - 1
packages/shell/tool-pwsh-persistent/src/index.ts

@@ -124,7 +124,7 @@ function commandOutput(
   // scrolled out and extraction fell back to the echoed copy.
   captured = captured.replaceAll(wrapper, '')
   return {
-    text: stripPrompt(captured.replace(/^\r?\n/, '')),
+    text: captured.replace(/^\r?\n/, '').replace(/\r?\n$/, ''),
     incomplete: startMarker < 0,
     exitCode: Number(status),
   }

+ 13 - 1
packages/shell/tool-pwsh-persistent/tests/tools.spec.ts

@@ -100,6 +100,7 @@ type StubMode =
   | 'paged-scrollback'
   | 'with-echo'
   | 'exit-after-send'
+  | 'prompt-collision'
 
 const START_PATTERN = /__DSH_PERSISTENT_PWSH_START_[^_]+(?:-[^_]+)*__/
 const END_PATTERN = /__DSH_PERSISTENT_PWSH_END_[^:]+:/
@@ -215,7 +216,9 @@ class StubTerminalSession implements TerminalBackendSession {
     }
     const commandOutput = this.mode === 'large'
       ? 'x'.repeat(100)
-      : this.mode === 'nonzero' ? '' : 'hello from stub'
+      : this.mode === 'nonzero' ? ''
+        : this.mode === 'prompt-collision' ? this.motd
+          : 'hello from stub'
     const exitCode = this.mode === 'nonzero' ? 7 : 0
     const output = `${start ?? ''}\n${commandOutput}\n${end ?? ''}${exitCode}\n${this.motd}`
     this.scrollback += output
@@ -362,6 +365,15 @@ describe('tool-pwsh-persistent', () => {
     expect(result).not.toContain('Invoke-Expression')
   })
 
+  it('preserves command output that equals the private shell prompt', async () => {
+    const { ctx, owner, stub } = await setup({ backendType: 'stub' })
+    await call(ctx, owner, 'warm up')
+    const session = stub.sessions[0]!
+
+    session.mode = 'prompt-collision'
+    expect(text(await call(ctx, owner, 'complete prompt collision'))).toBe(session.motd)
+  })
+
   it('reports the exit path when the shell exits between send settlement and the next poll', async () => {
     const { ctx, owner, stub } = await setup({ backendType: 'stub' })
     await call(ctx, owner, 'warm up')