@stigmer/react 3.0.8-dev.20260613085218 → 3.0.9-dev.20260615145121

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.
@@ -11,12 +11,16 @@ import {
11
11
  ExecutionConfigSchema,
12
12
  } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/spec_pb";
13
13
  import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/metadata_pb";
14
- import { AgentMessageSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
14
+ import {
15
+ AgentMessageSchema,
16
+ ToolCallSchema,
17
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
15
18
  import { PendingApprovalSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
16
19
  import {
17
20
  ExecutionPhase,
18
21
  InteractionMode,
19
22
  MessageType,
23
+ ToolCallStatus,
20
24
  } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
21
25
  import { MessageThread } from "../MessageThread";
22
26
 
@@ -376,6 +380,86 @@ describe("MessageThread", () => {
376
380
  expect(onEditMessage).toHaveBeenCalledWith("new turn");
377
381
  });
378
382
 
383
+ // Issue #179: while a turn streams, the synthetic "Thinking…" setup
384
+ // placeholder must yield the moment real content (streamed reasoning or a tool
385
+ // call) arrives — otherwise it renders *alongside* the real cards.
386
+ describe("streaming trace replaces the synthetic placeholder (issue #179)", () => {
387
+ function makeStreamingExecution(
388
+ messages: ReturnType<typeof create<typeof AgentMessageSchema>>[],
389
+ ): AgentExecution {
390
+ const exec = create(AgentExecutionSchema);
391
+ const meta = create(ApiResourceMetadataSchema);
392
+ meta.id = "exec-streaming";
393
+ exec.metadata = meta;
394
+ const spec = create(AgentExecutionSpecSchema);
395
+ spec.message = "Do the thing";
396
+ exec.spec = spec;
397
+ const status = create(AgentExecutionStatusSchema);
398
+ status.phase = ExecutionPhase.EXECUTION_IN_PROGRESS;
399
+ status.messages = messages;
400
+ exec.status = status;
401
+ return exec;
402
+ }
403
+
404
+ function humanMessage(text: string) {
405
+ const m = create(AgentMessageSchema);
406
+ m.type = MessageType.MESSAGE_HUMAN;
407
+ m.content = text;
408
+ return m;
409
+ }
410
+
411
+ function thinkingMessage(text: string) {
412
+ const m = create(AgentMessageSchema);
413
+ m.type = MessageType.MESSAGE_THINKING;
414
+ m.content = text;
415
+ m.isStreaming = true;
416
+ return m;
417
+ }
418
+
419
+ it("streamed reasoning (no AI text yet) hides the synthetic 'Thinking…' placeholder", () => {
420
+ const active = makeStreamingExecution([
421
+ humanMessage("Do the thing"),
422
+ thinkingMessage("Let me reason about the request"),
423
+ ]);
424
+
425
+ render(<MessageThread executions={[]} activeStreamExecution={active} />);
426
+
427
+ // The real reasoning card is shown...
428
+ expect(
429
+ screen.getByRole("article", { name: "Model thinking" }),
430
+ ).toBeTruthy();
431
+ // ...and the synthetic placeholder (ellipsis "Thinking…") is gone. Before
432
+ // the fix, hasAiMessages ignored MESSAGE_THINKING and both rendered.
433
+ expect(screen.queryByText("Thinking\u2026")).toBeNull();
434
+ });
435
+
436
+ it("renders thinking + a running tool call mid-turn without the placeholder", () => {
437
+ const aiWithTool = create(AgentMessageSchema);
438
+ aiWithTool.type = MessageType.MESSAGE_AI;
439
+ aiWithTool.content = "";
440
+ aiWithTool.toolCalls = [
441
+ create(ToolCallSchema, {
442
+ id: "tc-1",
443
+ name: "read",
444
+ status: ToolCallStatus.TOOL_CALL_RUNNING,
445
+ }),
446
+ ];
447
+
448
+ const active = makeStreamingExecution([
449
+ humanMessage("Do the thing"),
450
+ thinkingMessage("Planning the edit"),
451
+ aiWithTool,
452
+ ]);
453
+
454
+ render(<MessageThread executions={[]} activeStreamExecution={active} />);
455
+
456
+ expect(
457
+ screen.getByRole("article", { name: "Model thinking" }),
458
+ ).toBeTruthy();
459
+ expect(screen.queryByText("Thinking\u2026")).toBeNull();
460
+ });
461
+ });
462
+
379
463
  it("renders plan-completion card when last execution is completed Plan mode", () => {
380
464
  const exec = makeExecution({
381
465
  id: "exec-plan",