(host, context)
| 2845 | } |
| 2846 | |
| 2847 | async function executePersistentHostTurn(host, context) { |
| 2848 | if (!host?.child || host.child.exitCode !== null || !host.child.stdin) { |
| 2849 | const error = new Error('长驻 REPL 当前不可写入。') |
| 2850 | error.fallbackAllowed = true |
| 2851 | throw error |
| 2852 | } |
| 2853 | |
| 2854 | host.activeTurn = { |
| 2855 | ...context, |
| 2856 | basePromptCount: host.promptCount, |
| 2857 | baseTranscriptCount: host.syncedTranscriptCount, |
| 2858 | baseToolIds: new Set(host.syncedToolIds), |
| 2859 | stdout: '', |
| 2860 | stderr: '', |
| 2861 | finalized: false, |
| 2862 | } |
| 2863 | |
| 2864 | host.child.stdin.write(`${context.runnerPrompt}\n`, 'utf8') |
| 2865 | |
| 2866 | try { |
| 2867 | await waitForCondition( |
| 2868 | () => { |
| 2869 | if (host.activeTurn?.finalized) { |
| 2870 | return true |
| 2871 | } |
| 2872 | if (host.exited) { |
| 2873 | return true |
| 2874 | } |
| 2875 | return host.promptCount > host.activeTurn.basePromptCount |
| 2876 | }, |
| 2877 | { |
| 2878 | timeoutMs: 15 * 60 * 1000, |
| 2879 | errorMessage: '长驻 REPL 响应超时。', |
| 2880 | }, |
| 2881 | ) |
| 2882 | |
| 2883 | if (!host.activeTurn?.finalized) { |
| 2884 | await finalizePersistentHostTurn(host, { exitCode: 0 }) |
| 2885 | } |
| 2886 | } catch (error) { |
| 2887 | if (host.activeTurn?.finalized) { |
| 2888 | return |
| 2889 | } |
| 2890 | |
| 2891 | host.shuttingDown = true |
| 2892 | try { |
| 2893 | host.child.kill('SIGTERM') |
| 2894 | } catch { |
| 2895 | // ignore |
| 2896 | } |
| 2897 | |
| 2898 | await finalizePersistentHostTurn(host, { |
| 2899 | exitCode: -1, |
| 2900 | didFail: true, |
| 2901 | rawMessage: error instanceof Error ? error.message : String(error), |
| 2902 | }) |
| 2903 | } |
| 2904 | } |
no test coverage detected