@stigmer/react 3.2.1 → 3.2.3

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 (137) hide show
  1. package/activity/entry-status-badge.d.ts +23 -0
  2. package/activity/entry-status-badge.d.ts.map +1 -0
  3. package/activity/entry-status-badge.js +18 -0
  4. package/activity/entry-status-badge.js.map +1 -0
  5. package/activity/format-relative-time.d.ts +16 -0
  6. package/activity/format-relative-time.d.ts.map +1 -0
  7. package/activity/format-relative-time.js +38 -0
  8. package/activity/format-relative-time.js.map +1 -0
  9. package/activity/index.d.ts +2 -0
  10. package/activity/index.d.ts.map +1 -1
  11. package/activity/index.js +2 -0
  12. package/activity/index.js.map +1 -1
  13. package/agent/AgentDetailView.d.ts.map +1 -1
  14. package/agent/AgentDetailView.js +6 -3
  15. package/agent/AgentDetailView.js.map +1 -1
  16. package/execution/index.d.ts +1 -2
  17. package/execution/index.d.ts.map +1 -1
  18. package/execution/index.js +0 -1
  19. package/execution/index.js.map +1 -1
  20. package/execution/useLiveAgentExecution.d.ts +17 -1
  21. package/execution/useLiveAgentExecution.d.ts.map +1 -1
  22. package/execution/useLiveAgentExecution.js +19 -4
  23. package/execution/useLiveAgentExecution.js.map +1 -1
  24. package/index.d.ts +7 -7
  25. package/index.d.ts.map +1 -1
  26. package/index.js +3 -3
  27. package/index.js.map +1 -1
  28. package/internal/useInViewport.d.ts +24 -0
  29. package/internal/useInViewport.d.ts.map +1 -0
  30. package/internal/useInViewport.js +49 -0
  31. package/internal/useInViewport.js.map +1 -0
  32. package/library/VisibilitySelector.d.ts +22 -6
  33. package/library/VisibilitySelector.d.ts.map +1 -1
  34. package/library/VisibilitySelector.js +12 -4
  35. package/library/VisibilitySelector.js.map +1 -1
  36. package/library/index.d.ts +1 -1
  37. package/library/index.d.ts.map +1 -1
  38. package/library/index.js.map +1 -1
  39. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  40. package/mcp-server/McpServerDetailView.js +4 -3
  41. package/mcp-server/McpServerDetailView.js.map +1 -1
  42. package/package.json +4 -4
  43. package/session/SessionViewer.js +8 -1
  44. package/session/SessionViewer.js.map +1 -1
  45. package/session/audience.d.ts +6 -1
  46. package/session/audience.d.ts.map +1 -1
  47. package/skill/SkillDetailView.d.ts.map +1 -1
  48. package/skill/SkillDetailView.js +4 -3
  49. package/skill/SkillDetailView.js.map +1 -1
  50. package/src/access/__tests__/useManageAccess.test.tsx +104 -0
  51. package/src/activity/__tests__/format-relative-time.test.ts +40 -0
  52. package/src/activity/entry-status-badge.ts +39 -0
  53. package/src/activity/format-relative-time.ts +38 -0
  54. package/src/activity/index.ts +7 -0
  55. package/src/agent/AgentDetailView.tsx +9 -3
  56. package/src/execution/__tests__/useLiveAgentExecution.test.tsx +125 -0
  57. package/src/execution/index.ts +4 -7
  58. package/src/execution/useLiveAgentExecution.ts +41 -3
  59. package/src/index.ts +7 -5
  60. package/src/internal/__tests__/useInViewport.test.tsx +115 -0
  61. package/src/internal/useInViewport.ts +63 -0
  62. package/src/library/VisibilitySelector.tsx +50 -9
  63. package/src/library/__tests__/VisibilitySelector.test.tsx +38 -0
  64. package/src/library/index.ts +4 -1
  65. package/src/mcp-server/McpServerDetailView.tsx +7 -3
  66. package/src/session/SessionViewer.tsx +7 -1
  67. package/src/session/__tests__/audienceWiring.test.tsx +31 -1
  68. package/src/session/audience.ts +6 -1
  69. package/src/skill/SkillDetailView.tsx +7 -3
  70. package/src/workflow/WorkflowAgentCallTranscript.tsx +279 -0
  71. package/src/workflow/WorkflowDetailView.tsx +7 -3
  72. package/src/workflow/WorkflowExecutionViewer.tsx +20 -77
  73. package/src/workflow/WorkflowTaskApprovalSummary.tsx +45 -8
  74. package/src/workflow/__tests__/WorkflowAgentCallTranscript.liveregion.test.tsx +124 -0
  75. package/src/workflow/__tests__/{WorkflowAgentExecutionDocument.test.tsx → WorkflowAgentCallTranscript.test.tsx} +146 -121
  76. package/src/workflow/__tests__/WorkflowExecutionViewer.approvals.test.tsx +81 -220
  77. package/src/workflow/__tests__/WorkflowExecutionViewer.reconciliation.test.tsx +17 -16
  78. package/src/workflow/__tests__/WorkflowTaskApprovalSummary.test.tsx +52 -2
  79. package/src/workflow/__tests__/WorkflowTaskThread.test.tsx +168 -185
  80. package/src/workflow/__tests__/agent-call-live-experience.test.ts +4 -4
  81. package/src/workflow/__tests__/task-approval.test.ts +119 -0
  82. package/src/workflow/__tests__/task-presentation.test.ts +35 -1
  83. package/src/workflow/__tests__/useWorkflowExecutionPanel.test.ts +0 -57
  84. package/src/workflow/index.ts +6 -3
  85. package/src/workflow/task-detail/index.ts +3 -0
  86. package/src/workflow/task-detail/task-approval.ts +95 -1
  87. package/src/workflow/thread/WorkflowTaskThread.tsx +96 -252
  88. package/src/workflow/thread/task-presentation.ts +8 -2
  89. package/src/workflow/useWorkflowExecutionPanel.ts +0 -47
  90. package/workflow/WorkflowAgentCallTranscript.d.ts +87 -0
  91. package/workflow/WorkflowAgentCallTranscript.d.ts.map +1 -0
  92. package/workflow/WorkflowAgentCallTranscript.js +98 -0
  93. package/workflow/WorkflowAgentCallTranscript.js.map +1 -0
  94. package/workflow/WorkflowDetailView.d.ts.map +1 -1
  95. package/workflow/WorkflowDetailView.js +4 -3
  96. package/workflow/WorkflowDetailView.js.map +1 -1
  97. package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
  98. package/workflow/WorkflowExecutionViewer.js +23 -52
  99. package/workflow/WorkflowExecutionViewer.js.map +1 -1
  100. package/workflow/WorkflowTaskApprovalSummary.d.ts +1 -1
  101. package/workflow/WorkflowTaskApprovalSummary.d.ts.map +1 -1
  102. package/workflow/WorkflowTaskApprovalSummary.js +18 -1
  103. package/workflow/WorkflowTaskApprovalSummary.js.map +1 -1
  104. package/workflow/index.d.ts +2 -2
  105. package/workflow/index.d.ts.map +1 -1
  106. package/workflow/index.js +2 -2
  107. package/workflow/index.js.map +1 -1
  108. package/workflow/task-detail/index.d.ts +1 -1
  109. package/workflow/task-detail/index.d.ts.map +1 -1
  110. package/workflow/task-detail/index.js +1 -1
  111. package/workflow/task-detail/index.js.map +1 -1
  112. package/workflow/task-detail/task-approval.d.ts +44 -1
  113. package/workflow/task-detail/task-approval.d.ts.map +1 -1
  114. package/workflow/task-detail/task-approval.js +47 -0
  115. package/workflow/task-detail/task-approval.js.map +1 -1
  116. package/workflow/thread/WorkflowTaskThread.d.ts +17 -25
  117. package/workflow/thread/WorkflowTaskThread.d.ts.map +1 -1
  118. package/workflow/thread/WorkflowTaskThread.js +60 -105
  119. package/workflow/thread/WorkflowTaskThread.js.map +1 -1
  120. package/workflow/thread/task-presentation.d.ts.map +1 -1
  121. package/workflow/thread/task-presentation.js +7 -2
  122. package/workflow/thread/task-presentation.js.map +1 -1
  123. package/workflow/useWorkflowExecutionPanel.d.ts +0 -12
  124. package/workflow/useWorkflowExecutionPanel.d.ts.map +1 -1
  125. package/workflow/useWorkflowExecutionPanel.js +0 -12
  126. package/workflow/useWorkflowExecutionPanel.js.map +1 -1
  127. package/execution/agent-execution-document.d.ts +0 -31
  128. package/execution/agent-execution-document.d.ts.map +0 -1
  129. package/execution/agent-execution-document.js +0 -48
  130. package/execution/agent-execution-document.js.map +0 -1
  131. package/src/execution/__tests__/agent-execution-document.test.ts +0 -45
  132. package/src/execution/agent-execution-document.ts +0 -54
  133. package/src/workflow/WorkflowAgentExecutionDocument.tsx +0 -283
  134. package/workflow/WorkflowAgentExecutionDocument.d.ts +0 -79
  135. package/workflow/WorkflowAgentExecutionDocument.d.ts.map +0 -1
  136. package/workflow/WorkflowAgentExecutionDocument.js +0 -87
  137. package/workflow/WorkflowAgentExecutionDocument.js.map +0 -1
@@ -196,11 +196,45 @@ describe("per-kind preview lines", () => {
196
196
  expected: "delivery failed",
197
197
  },
198
198
  {
199
- label: "human_input settled decision",
199
+ label: "human_input settled decision (legacy record, raw reviewer)",
200
200
  kind: WorkflowTaskKind.human_input,
201
201
  overrides: { outputSummary: { outcome: "approve", reviewer: "suresh" } },
202
202
  expected: "approve · by suresh",
203
203
  },
204
+ {
205
+ label: "human_input settled decision prefers the reviewer_actor display name",
206
+ kind: WorkflowTaskKind.human_input,
207
+ overrides: {
208
+ outputSummary: {
209
+ outcome: "approve",
210
+ reviewer: "ida_01abc",
211
+ reviewer_actor: {
212
+ id: "ida_01abc",
213
+ display_name: "Ada Lovelace",
214
+ email: "ada@example.com",
215
+ },
216
+ },
217
+ },
218
+ expected: "approve · by Ada Lovelace",
219
+ },
220
+ {
221
+ label: "human_input settled decision falls back to the actor email",
222
+ kind: WorkflowTaskKind.human_input,
223
+ overrides: {
224
+ outputSummary: {
225
+ outcome: "approve",
226
+ reviewer: "ida_01abc",
227
+ reviewer_actor: { id: "ida_01abc", email: "ada@example.com" },
228
+ },
229
+ },
230
+ expected: "approve · by ada@example.com",
231
+ },
232
+ {
233
+ label: "human_input unattributed decision omits the by segment",
234
+ kind: WorkflowTaskKind.human_input,
235
+ overrides: { outputSummary: { outcome: "approve" } },
236
+ expected: "approve",
237
+ },
204
238
  {
205
239
  label: "wait completed with structured duration",
206
240
  kind: WorkflowTaskKind.wait,
@@ -9,7 +9,6 @@ import {
9
9
  FILE_CHANGE_DOCUMENT_ENTRY_ID,
10
10
  fileChangeTabPath,
11
11
  } from "../../execution/file-change-document";
12
- import { AGENT_EXECUTION_DOCUMENT_ENTRY_ID } from "../../execution/agent-execution-document";
13
12
  import {
14
13
  DIAGNOSIS_DOCUMENT_ENTRY_ID,
15
14
  DIAGNOSIS_DOCUMENT_PATH,
@@ -174,62 +173,6 @@ describe("useWorkflowExecutionPanel", () => {
174
173
  expect(new Set(editors.map((e) => e.entryId)).size).toBe(2);
175
174
  });
176
175
 
177
- it("openAgentExecution opens a preview tab in the transcript family and expands the panel", () => {
178
- const { result } = renderHook(() => useWorkflowExecutionPanel());
179
-
180
- act(() => result.current.openAgentExecution("aex_1", "summarize-report"));
181
-
182
- expect(result.current.isOpen).toBe(true);
183
- const { editors } = result.current.editorsStore.getSnapshot();
184
- expect(editors).toEqual([
185
- {
186
- entryId: AGENT_EXECUTION_DOCUMENT_ENTRY_ID,
187
- path: "aex_1/summarize-report",
188
- preview: true,
189
- },
190
- ]);
191
- });
192
-
193
- it("the transcript preview shares the one slot with artifacts and changes", () => {
194
- const { result } = renderHook(() => useWorkflowExecutionPanel());
195
-
196
- act(() => {
197
- result.current.openAgentExecution("aex_1", "call-agent");
198
- result.current.openArtifact(artifact("art_1", "report.json"));
199
- });
200
-
201
- // Preview-tab semantics: the artifact open replaced the transcript.
202
- const { editors } = result.current.editorsStore.getSnapshot();
203
- expect(editors).toHaveLength(1);
204
- expect(editors[0].entryId).toBe(ARTIFACT_DOCUMENT_ENTRY_ID);
205
- });
206
-
207
- it("pinAgentExecution makes the transcript's tab persistent", () => {
208
- const { result } = renderHook(() => useWorkflowExecutionPanel());
209
-
210
- act(() => {
211
- result.current.openAgentExecution("aex_1", "call-agent");
212
- result.current.pinAgentExecution("aex_1", "call-agent");
213
- });
214
-
215
- const { editors } = result.current.editorsStore.getSnapshot();
216
- expect(editors[0].preview).toBe(false);
217
- });
218
-
219
- it("two AGENT_CALL tasks calling the same agent open distinct transcript tabs", () => {
220
- const { result } = renderHook(() => useWorkflowExecutionPanel());
221
-
222
- act(() => {
223
- result.current.openAgentExecution("aex_1", "first-call");
224
- result.current.pinAgentExecution("aex_1", "first-call");
225
- result.current.openAgentExecution("aex_2", "second-call");
226
- });
227
-
228
- const { editors } = result.current.editorsStore.getSnapshot();
229
- expect(editors).toHaveLength(2);
230
- expect(new Set(editors.map((e) => e.path)).size).toBe(2);
231
- });
232
-
233
176
  it("closing an editor keeps the panel open (the panel is more than tabs)", () => {
234
177
  const { result } = renderHook(() => useWorkflowExecutionPanel());
235
178
  const a = artifact("art_1", "a.json");
@@ -226,10 +226,10 @@ export {
226
226
  type WorkflowArtifactDocumentProps,
227
227
  } from "./WorkflowArtifactDocument.js";
228
228
  export {
229
- WorkflowAgentExecutionDocument,
230
- type WorkflowAgentExecutionDocumentProps,
229
+ WorkflowAgentCallTranscript,
230
+ type WorkflowAgentCallTranscriptProps,
231
231
  type WorkflowAgentExecutionHitl,
232
- } from "./WorkflowAgentExecutionDocument.js";
232
+ } from "./WorkflowAgentCallTranscript.js";
233
233
  export {
234
234
  useWorkflowArtifactDownload,
235
235
  type UseWorkflowArtifactDownloadReturn,
@@ -609,8 +609,11 @@ export {
609
609
  type TaskDetailIO,
610
610
  deriveTaskApprovalRequest,
611
611
  deriveTaskApprovalDecision,
612
+ deriveTaskReviewer,
612
613
  type TaskApprovalRequestView,
613
614
  type TaskDetailApprovalDecision,
615
+ type TaskReviewerActor,
616
+ type TaskReviewerView,
614
617
  StructuredDataViewer,
615
618
  type StructuredDataViewerProps,
616
619
  } from "./task-detail/index.js";
@@ -2,8 +2,11 @@ export { buildIO, type TaskDetailIO } from "./task-detail-io.js";
2
2
  export {
3
3
  deriveTaskApprovalRequest,
4
4
  deriveTaskApprovalDecision,
5
+ deriveTaskReviewer,
5
6
  type TaskApprovalRequestView,
6
7
  type TaskDetailApprovalDecision,
8
+ type TaskReviewerActor,
9
+ type TaskReviewerView,
7
10
  } from "./task-approval.js";
8
11
  export {
9
12
  StructuredDataViewer,
@@ -59,11 +59,49 @@ export interface TaskApprovalRequestView {
59
59
  * is signalled but before the status snapshot reflects the task output —
60
60
  * consumers render a "finalizing" affordance in that state.
61
61
  */
62
+ /**
63
+ * Display identity of the reviewer, snapshotted server-side at decision
64
+ * time (see `reviewer_actor` in the human_input task-output contract).
65
+ * Renderers apply the fallback ladder: displayName → email → raw
66
+ * {@link TaskDetailApprovalDecision.reviewer} id → omit.
67
+ */
68
+ export interface TaskReviewerActor {
69
+ /** Canonical identity (matches the decision's `reviewer`). */
70
+ readonly id: string;
71
+ /** Human-readable name; `""` when unknown. */
72
+ readonly displayName: string;
73
+ /** Email address; `""` when unknown. */
74
+ readonly email: string;
75
+ /** Avatar URL; `""` when unknown. */
76
+ readonly avatar: string;
77
+ }
78
+
79
+ /**
80
+ * How a decided gate's reviewer should be presented — the fallback ladder
81
+ * ({@link TaskReviewerActor} fields first, raw id last) collapsed to a
82
+ * render-ready shape shared by the summary card and the thread caption.
83
+ */
84
+ export interface TaskReviewerView {
85
+ /** Best display label: display name → email → canonical id. Never empty. */
86
+ readonly label: string;
87
+ /** Email for secondary display; `""` when unknown or equal to the label. */
88
+ readonly email: string;
89
+ /** Avatar URL; `""` when unknown. */
90
+ readonly avatar: string;
91
+ /**
92
+ * `true` when the label fell through to the raw identity (legacy records
93
+ * that predate actor enrichment) — renderers de-emphasize it.
94
+ */
95
+ readonly isRawId: boolean;
96
+ }
97
+
62
98
  export interface TaskDetailApprovalDecision {
63
99
  /** Chosen outcome identifier (e.g. "approve", "pause_campaigns"). */
64
100
  readonly outcome: string;
65
- /** Reviewer who made the decision. */
101
+ /** Canonical reviewer identity; `""` when the decision is unattributed. */
66
102
  readonly reviewer: string;
103
+ /** Display snapshot of the reviewer, or `null` for unenriched records. */
104
+ readonly reviewerActor: TaskReviewerActor | null;
67
105
  /** ISO-8601 timestamp the decision was recorded, or `null`. */
68
106
  readonly respondedAt: string | null;
69
107
  /** Free-text comment the reviewer attached, or the empty string. */
@@ -131,6 +169,7 @@ export function deriveTaskApprovalDecision(
131
169
  outcome: outputOutcome,
132
170
  reviewer:
133
171
  readSnapshotString(taskOutput, "reviewer") || (resolution?.resolvedBy ?? ""),
172
+ reviewerActor: deriveReviewerActor(resolution, taskOutput),
134
173
  respondedAt: readSnapshotString(taskOutput, "responded_at") || null,
135
174
  comment:
136
175
  readSnapshotString(taskOutput, "comment") || (resolution?.comment ?? ""),
@@ -140,6 +179,61 @@ export function deriveTaskApprovalDecision(
140
179
  };
141
180
  }
142
181
 
182
+ /**
183
+ * Collapses a decision's attribution into the render-ready reviewer view,
184
+ * or `null` when the decision carries no attribution at all (timeout
185
+ * auto-resolution, OSS single-user edition) — consumers omit the "by …"
186
+ * segment entirely in that case.
187
+ */
188
+ export function deriveTaskReviewer(
189
+ decision: TaskDetailApprovalDecision,
190
+ ): TaskReviewerView | null {
191
+ const actor = decision.reviewerActor;
192
+ const label = actor?.displayName || actor?.email || decision.reviewer;
193
+ if (!label) return null;
194
+
195
+ const email = actor?.email && actor.email !== label ? actor.email : "";
196
+ return {
197
+ label,
198
+ email,
199
+ avatar: actor?.avatar ?? "",
200
+ isRawId: !actor?.displayName && !actor?.email,
201
+ };
202
+ }
203
+
204
+ /**
205
+ * Reviewer actor from the task-output snapshot (snake_case JSON stamped by
206
+ * the control plane), falling back to the `approval_resolved` event's
207
+ * proto actor for the finalizing window — mirroring the same output-first
208
+ * precedence as the scalar decision fields.
209
+ */
210
+ function deriveReviewerActor(
211
+ resolution: ApprovalResolvedPayload | null,
212
+ taskOutput: JsonObject | undefined,
213
+ ): TaskReviewerActor | null {
214
+ const snapshot = readSnapshotObject(taskOutput, "reviewer_actor");
215
+ if (snapshot) {
216
+ return {
217
+ id: readSnapshotString(snapshot, "id"),
218
+ displayName: readSnapshotString(snapshot, "display_name"),
219
+ email: readSnapshotString(snapshot, "email"),
220
+ avatar: readSnapshotString(snapshot, "avatar"),
221
+ };
222
+ }
223
+
224
+ const eventActor = resolution?.resolvedByActor;
225
+ if (eventActor) {
226
+ return {
227
+ id: eventActor.id,
228
+ displayName: eventActor.displayName,
229
+ email: eventActor.email,
230
+ avatar: eventActor.avatar,
231
+ };
232
+ }
233
+
234
+ return null;
235
+ }
236
+
143
237
  /** Reads a string field from a task-output Struct, or `""` when absent. */
144
238
  function readSnapshotString(obj: JsonObject | undefined, key: string): string {
145
239
  const value = obj?.[key];