@nextclaw/ui 0.15.17 → 0.15.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/assets/{app-presenter-provider-C9AcZKKs.js → app-presenter-provider-De7Zwitu.js} +14 -14
  3. package/dist/assets/{appearance-settings-page-CiD9Ey8f.js → appearance-settings-page-BkQaPtQ-.js} +1 -1
  4. package/dist/assets/{chat-page-B0cC3jsB.js → chat-page-AvOuaxuv.js} +1 -1
  5. package/dist/assets/{index-bOqpao-w.js → index-B5AoUrMf.js} +2 -2
  6. package/dist/assets/remote-B6TXClIg.js +1 -0
  7. package/dist/assets/{runtime-config-page-CbSrKeJt.js → runtime-config-page-BLrTVO3n.js} +1 -1
  8. package/dist/index.html +2 -2
  9. package/package.json +6 -6
  10. package/src/features/chat/components/conversation/__tests__/chat-conversation-content.test.tsx +11 -0
  11. package/src/features/chat/components/conversation/chat-conversation-content.tsx +7 -1
  12. package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +50 -4
  13. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +25 -1
  14. package/src/features/chat/features/conversation/components/session-conversation-input.tsx +3 -0
  15. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-input-state.test.tsx +41 -0
  16. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-slash-commands.test.tsx +28 -0
  17. package/src/features/chat/features/conversation/hooks/use-session-conversation-input-query.ts +1 -1
  18. package/src/features/chat/features/conversation/hooks/use-session-conversation-input-state.ts +0 -1
  19. package/src/features/chat/features/conversation/hooks/use-session-conversation-preference-actions.ts +10 -11
  20. package/src/features/chat/features/conversation/hooks/use-session-conversation-slash-commands.ts +5 -2
  21. package/src/features/chat/features/message/components/chat-message-list.container.tsx +12 -9
  22. package/src/features/chat/features/ncp/hooks/__tests__/use-hydrated-ncp-agent.test.tsx +122 -1
  23. package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-agent-runtime-queue.test.tsx +9 -2
  24. package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-agent-runtime.test.tsx +107 -1
  25. package/dist/assets/remote-B0nlynVp.js +0 -1
@@ -200,12 +200,118 @@ describe("useNcpAgentRuntime", () => {
200
200
  assistantMessageId: "assistant-1",
201
201
  runId: "run-1",
202
202
  });
203
- expect(result.current.visibleMessages).toEqual([]);
203
+ expect(result.current.visibleMessages).toEqual([
204
+ expect.objectContaining({
205
+ ...envelope.message,
206
+ sessionId: "session-created",
207
+ }),
208
+ ]);
204
209
  expect(client.stop).not.toHaveBeenCalled();
205
210
 
206
211
  rerender({ sessionId: "session-created" });
207
212
  });
208
213
 
214
+ it("shows an existing-session user message before send returns and deduplicates the server event", async () => {
215
+ const client = new DeferredSendClient();
216
+ const manager = new DefaultNcpAgentConversationStateManager();
217
+ const envelope: NcpAgentSendEnvelope = {
218
+ sessionId: "session-existing",
219
+ message: {
220
+ id: "user-optimistic",
221
+ sessionId: "session-existing",
222
+ role: "user",
223
+ status: "final",
224
+ parts: [{ type: "text", text: "hello now" }],
225
+ timestamp: now,
226
+ },
227
+ };
228
+ let releaseSend = () => {};
229
+ client.send.mockImplementationOnce(
230
+ (pendingEnvelope) =>
231
+ new Promise((resolve) => {
232
+ releaseSend = () =>
233
+ resolve({
234
+ sessionId: "session-existing",
235
+ userMessageId: pendingEnvelope.message.id,
236
+ assistantMessageId: "assistant-1",
237
+ runId: "run-1",
238
+ });
239
+ }),
240
+ );
241
+ const { result } = renderHook(() =>
242
+ useNcpAgentRuntime({
243
+ sessionId: "session-existing",
244
+ client,
245
+ manager: manager as never,
246
+ }),
247
+ );
248
+
249
+ let sendPromise!: ReturnType<typeof result.current.send>;
250
+ act(() => {
251
+ sendPromise = result.current.send(envelope);
252
+ });
253
+
254
+ await waitFor(() => {
255
+ expect(result.current.visibleMessages).toEqual([envelope.message]);
256
+ });
257
+
258
+ await act(async () => {
259
+ await client.emit({
260
+ type: NcpEventType.MessageSent,
261
+ payload: {
262
+ sessionId: "session-existing",
263
+ message: envelope.message as NcpMessage,
264
+ },
265
+ });
266
+ });
267
+ await waitFor(() => {
268
+ expect(result.current.visibleMessages).toHaveLength(1);
269
+ });
270
+
271
+ await act(async () => {
272
+ releaseSend();
273
+ await sendPromise;
274
+ });
275
+ expect(result.current.visibleMessages).toEqual([envelope.message]);
276
+ });
277
+
278
+ it("marks an optimistic user message as failed when send fails", async () => {
279
+ const client = new DeferredSendClient();
280
+ const manager = new DefaultNcpAgentConversationStateManager();
281
+ const envelope: NcpAgentSendEnvelope = {
282
+ sessionId: "session-existing",
283
+ message: {
284
+ id: "user-failed",
285
+ sessionId: "session-existing",
286
+ role: "user",
287
+ status: "final",
288
+ parts: [{ type: "text", text: "please retry" }],
289
+ timestamp: now,
290
+ },
291
+ };
292
+ client.send.mockRejectedValueOnce(new Error("network unavailable"));
293
+ const { result } = renderHook(() =>
294
+ useNcpAgentRuntime({
295
+ sessionId: "session-existing",
296
+ client,
297
+ manager: manager as never,
298
+ }),
299
+ );
300
+
301
+ await act(async () => {
302
+ await expect(result.current.send(envelope)).rejects.toThrow(
303
+ "network unavailable",
304
+ );
305
+ });
306
+
307
+ expect(result.current.visibleMessages).toEqual([
308
+ expect.objectContaining({
309
+ ...envelope.message,
310
+ status: "error",
311
+ }),
312
+ ]);
313
+ });
314
+
209
315
  it("aborts by session id even before a hydrated active run reaches local state", async () => {
210
316
  const client = new DeferredSendClient();
211
317
  const manager = new DefaultNcpAgentConversationStateManager();
@@ -1 +0,0 @@
1
- import{Z as e}from"./app-presenter-provider-C9AcZKKs.js";export{e as RemoteAccessPage};