|
24 | 24 | import java.nio.file.Paths; |
25 | 25 | import java.util.ArrayList; |
26 | 26 | import java.util.List; |
| 27 | +import java.util.concurrent.CompletableFuture; |
| 28 | +import java.util.concurrent.TimeUnit; |
27 | 29 |
|
28 | 30 | import org.junit.jupiter.api.Test; |
29 | 31 |
|
@@ -51,6 +53,15 @@ private static KimiAcpConfig config() { |
51 | 53 | return config; |
52 | 54 | } |
53 | 55 |
|
| 56 | + private static KimiAcpConfig config(String... modes) { |
| 57 | + KimiAcpConfig config = config(); |
| 58 | + String[] args = new String[modes.length + 1]; |
| 59 | + args[0] = FAKE_AGENT; |
| 60 | + System.arraycopy(modes, 0, args, 1, modes.length); |
| 61 | + config.setAcpArgs(args); |
| 62 | + return config; |
| 63 | + } |
| 64 | + |
54 | 65 | @Test |
55 | 66 | void shouldConnectAndInitialize() { |
56 | 67 | try (KimiAcpClient client = new KimiAcpClient(config())) { |
@@ -148,4 +159,40 @@ void shouldTimeoutPromptWhenAgentNeverAnswers() throws Exception { |
148 | 159 | assertThrows(KimiException.class, client::connect); |
149 | 160 | client.close(); |
150 | 161 | } |
| 162 | + |
| 163 | + @Test |
| 164 | + void shouldRejectSecondActivePromptOnSameSession() throws Exception { |
| 165 | + KimiAcpConfig config = config("--slow-prompt"); |
| 166 | + config.setReadTimeoutMillis(5_000); |
| 167 | + try (KimiAcpClient client = new KimiAcpClient(config)) { |
| 168 | + client.connect(); |
| 169 | + String sessionId = client.newSession("/tmp"); |
| 170 | + |
| 171 | + CompletableFuture<KimiAcpTurnResult> first = client.promptAsync(sessionId, "first", null); |
| 172 | + |
| 173 | + assertThrows(KimiException.class, |
| 174 | + () -> client.promptAsync(sessionId, "second", null), |
| 175 | + "a second active turn must not overwrite the first session stream"); |
| 176 | + |
| 177 | + assertEquals("end_turn", first.get(5, TimeUnit.SECONDS).getStopReason()); |
| 178 | + } |
| 179 | + } |
| 180 | + |
| 181 | + @Test |
| 182 | + void shouldKeepTransportUsableWhenDeltaCallbackThrows() { |
| 183 | + KimiAcpConfig config = config(); |
| 184 | + config.setReadTimeoutMillis(750); |
| 185 | + try (KimiAcpClient client = new KimiAcpClient(config)) { |
| 186 | + client.connect(); |
| 187 | + String sessionId = client.newSession("/tmp"); |
| 188 | + |
| 189 | + assertThrows(KimiException.class, |
| 190 | + () -> client.prompt(sessionId, "callback failure", delta -> { |
| 191 | + throw new IllegalStateException("listener boom"); |
| 192 | + })); |
| 193 | + |
| 194 | + assertNotNull(client.listSessions(), |
| 195 | + "a user callback failure must not terminate the ACP reader transport"); |
| 196 | + } |
| 197 | + } |
151 | 198 | } |
0 commit comments