@nanisoft/prism-ui 0.16.0 → 1.0.0

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 (173) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/blocks/activity-feed-01/activity-feed-01.d.ts +120 -190
  3. package/dist/blocks/activity-feed-01/activity-feed-01.d.ts.map +1 -1
  4. package/dist/blocks/activity-feed-01/activity-feed-01.js +107 -97
  5. package/dist/blocks/activity-feed-01/index.d.ts +1 -1
  6. package/dist/blocks/activity-feed-01/index.d.ts.map +1 -1
  7. package/dist/blocks/auth-form-01/auth-form.d.ts +86 -53
  8. package/dist/blocks/auth-form-01/auth-form.d.ts.map +1 -1
  9. package/dist/blocks/auth-form-01/auth-form.js +95 -31
  10. package/dist/blocks/auth-form-01/index.d.ts +1 -1
  11. package/dist/blocks/auth-form-01/index.d.ts.map +1 -1
  12. package/dist/blocks/calendar-01/calendar.d.ts +28 -0
  13. package/dist/blocks/calendar-01/calendar.d.ts.map +1 -1
  14. package/dist/blocks/calendar-01/calendar.js +15 -1
  15. package/dist/blocks/card-index-01/card-index.d.ts +225 -0
  16. package/dist/blocks/card-index-01/card-index.d.ts.map +1 -0
  17. package/dist/blocks/card-index-01/card-index.js +154 -0
  18. package/dist/blocks/card-index-01/index.d.ts +3 -0
  19. package/dist/blocks/card-index-01/index.d.ts.map +1 -0
  20. package/dist/blocks/card-index-01/index.js +1 -0
  21. package/dist/blocks/chart-card-01/chart-card-01.d.ts +23 -21
  22. package/dist/blocks/chart-card-01/chart-card-01.d.ts.map +1 -1
  23. package/dist/blocks/chart-card-01/chart-card-01.js +46 -1
  24. package/dist/blocks/chart-card-01/index.d.ts +1 -1
  25. package/dist/blocks/chart-card-01/index.d.ts.map +1 -1
  26. package/dist/blocks/chart-group-01/chart-group-01.d.ts +3 -3
  27. package/dist/blocks/chart-group-01/chart-group-01.d.ts.map +1 -1
  28. package/dist/blocks/contact-01/contact.d.ts +30 -82
  29. package/dist/blocks/contact-01/contact.d.ts.map +1 -1
  30. package/dist/blocks/contact-01/contact.js +59 -30
  31. package/dist/blocks/contact-01/index.d.ts +1 -1
  32. package/dist/blocks/contact-01/index.d.ts.map +1 -1
  33. package/dist/blocks/dashboard-01/dashboard-01.d.ts +26 -71
  34. package/dist/blocks/dashboard-01/dashboard-01.d.ts.map +1 -1
  35. package/dist/blocks/dashboard-01/dashboard-01.js +34 -23
  36. package/dist/blocks/dashboard-01/index.d.ts +1 -1
  37. package/dist/blocks/dashboard-01/index.d.ts.map +1 -1
  38. package/dist/blocks/data-table-01/data-table.d.ts +276 -59
  39. package/dist/blocks/data-table-01/data-table.d.ts.map +1 -1
  40. package/dist/blocks/data-table-01/data-table.js +217 -35
  41. package/dist/blocks/data-table-01/index.d.ts +1 -1
  42. package/dist/blocks/data-table-01/index.d.ts.map +1 -1
  43. package/dist/blocks/directory-01/directory-01.d.ts +23 -2
  44. package/dist/blocks/directory-01/directory-01.d.ts.map +1 -1
  45. package/dist/blocks/directory-01/directory-01.js +3 -3
  46. package/dist/blocks/empty-state-01/empty-state.d.ts +60 -21
  47. package/dist/blocks/empty-state-01/empty-state.d.ts.map +1 -1
  48. package/dist/blocks/empty-state-01/empty-state.js +52 -17
  49. package/dist/blocks/index-detail-01/index-detail.d.ts +85 -0
  50. package/dist/blocks/index-detail-01/index-detail.d.ts.map +1 -0
  51. package/dist/blocks/index-detail-01/index-detail.js +58 -0
  52. package/dist/blocks/index-detail-01/index.d.ts +3 -0
  53. package/dist/blocks/index-detail-01/index.d.ts.map +1 -0
  54. package/dist/blocks/index-detail-01/index.js +1 -0
  55. package/dist/blocks/index.d.ts +20 -8
  56. package/dist/blocks/index.d.ts.map +1 -1
  57. package/dist/blocks/index.js +7 -0
  58. package/dist/blocks/issue-detail-01/issue-detail.d.ts +18 -0
  59. package/dist/blocks/issue-detail-01/issue-detail.d.ts.map +1 -1
  60. package/dist/blocks/issue-detail-01/issue-detail.js +18 -0
  61. package/dist/blocks/nothing-chosen-01/index.d.ts +3 -0
  62. package/dist/blocks/nothing-chosen-01/index.d.ts.map +1 -0
  63. package/dist/blocks/nothing-chosen-01/index.js +1 -0
  64. package/dist/blocks/nothing-chosen-01/nothing-chosen.d.ts +119 -0
  65. package/dist/blocks/nothing-chosen-01/nothing-chosen.d.ts.map +1 -0
  66. package/dist/blocks/nothing-chosen-01/nothing-chosen.js +79 -0
  67. package/dist/blocks/project-dashboard-01/index.d.ts +1 -1
  68. package/dist/blocks/project-dashboard-01/index.d.ts.map +1 -1
  69. package/dist/blocks/project-dashboard-01/project-dashboard.d.ts +21 -27
  70. package/dist/blocks/project-dashboard-01/project-dashboard.d.ts.map +1 -1
  71. package/dist/blocks/project-dashboard-01/project-dashboard.js +45 -5
  72. package/dist/blocks/provisioning-01/index.d.ts +1 -1
  73. package/dist/blocks/provisioning-01/index.d.ts.map +1 -1
  74. package/dist/blocks/provisioning-01/provisioning.d.ts +9 -97
  75. package/dist/blocks/provisioning-01/provisioning.d.ts.map +1 -1
  76. package/dist/blocks/provisioning-01/provisioning.js +26 -13
  77. package/dist/blocks/record-detail-01/index.d.ts +3 -0
  78. package/dist/blocks/record-detail-01/index.d.ts.map +1 -0
  79. package/dist/blocks/record-detail-01/index.js +1 -0
  80. package/dist/blocks/record-detail-01/record-detail.d.ts +239 -0
  81. package/dist/blocks/record-detail-01/record-detail.d.ts.map +1 -0
  82. package/dist/blocks/record-detail-01/record-detail.js +150 -0
  83. package/dist/blocks/record-form-01/index.d.ts +3 -0
  84. package/dist/blocks/record-form-01/index.d.ts.map +1 -0
  85. package/dist/blocks/record-form-01/index.js +1 -0
  86. package/dist/blocks/record-form-01/record-form.d.ts +148 -0
  87. package/dist/blocks/record-form-01/record-form.d.ts.map +1 -0
  88. package/dist/blocks/record-form-01/record-form.js +107 -0
  89. package/dist/blocks/record-grid-01/index.d.ts +3 -0
  90. package/dist/blocks/record-grid-01/index.d.ts.map +1 -0
  91. package/dist/blocks/record-grid-01/index.js +1 -0
  92. package/dist/blocks/record-grid-01/record-grid.d.ts +145 -0
  93. package/dist/blocks/record-grid-01/record-grid.d.ts.map +1 -0
  94. package/dist/blocks/record-grid-01/record-grid.js +114 -0
  95. package/dist/blocks/record-wizard-01/index.d.ts +3 -0
  96. package/dist/blocks/record-wizard-01/index.d.ts.map +1 -0
  97. package/dist/blocks/record-wizard-01/index.js +1 -0
  98. package/dist/blocks/record-wizard-01/record-wizard.d.ts +152 -0
  99. package/dist/blocks/record-wizard-01/record-wizard.d.ts.map +1 -0
  100. package/dist/blocks/record-wizard-01/record-wizard.js +144 -0
  101. package/dist/blocks/settings-members-01/settings-members.d.ts +2 -1
  102. package/dist/blocks/settings-members-01/settings-members.d.ts.map +1 -1
  103. package/dist/blocks/settings-panel-01/index.d.ts +1 -1
  104. package/dist/blocks/settings-panel-01/index.d.ts.map +1 -1
  105. package/dist/blocks/settings-panel-01/settings-panel.d.ts +165 -67
  106. package/dist/blocks/settings-panel-01/settings-panel.d.ts.map +1 -1
  107. package/dist/blocks/settings-panel-01/settings-panel.js +92 -33
  108. package/dist/blocks/signup-01/index.d.ts +1 -1
  109. package/dist/blocks/signup-01/index.d.ts.map +1 -1
  110. package/dist/blocks/signup-01/signup-01.d.ts +10 -84
  111. package/dist/blocks/signup-01/signup-01.d.ts.map +1 -1
  112. package/dist/blocks/signup-01/signup-01.js +41 -23
  113. package/dist/blocks/stats-01/index.d.ts +5 -5
  114. package/dist/blocks/stats-01/index.d.ts.map +1 -1
  115. package/dist/blocks/stats-01/index.js +4 -4
  116. package/dist/blocks/stats-01/stats.d.ts +49 -14
  117. package/dist/blocks/stats-01/stats.d.ts.map +1 -1
  118. package/dist/blocks/stats-01/stats.js +65 -15
  119. package/dist/blocks/trend-01/index.d.ts +1 -1
  120. package/dist/blocks/trend-01/index.d.ts.map +1 -1
  121. package/dist/blocks/trend-01/trend.d.ts +26 -73
  122. package/dist/blocks/trend-01/trend.d.ts.map +1 -1
  123. package/dist/blocks/trend-01/trend.js +47 -30
  124. package/dist/catalog.d.ts.map +1 -1
  125. package/dist/catalog.js +93 -3
  126. package/dist/components/ui/metric.d.ts +4 -2
  127. package/dist/components/ui/metric.d.ts.map +1 -1
  128. package/dist/index.d.ts +10 -0
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +6 -0
  131. package/dist/lib/field-render.d.ts +107 -0
  132. package/dist/lib/field-render.d.ts.map +1 -0
  133. package/dist/lib/field-render.js +251 -0
  134. package/dist/lib/spec.d.ts +609 -0
  135. package/dist/lib/spec.d.ts.map +1 -0
  136. package/dist/lib/spec.js +1 -0
  137. package/dist/live/index.d.ts +2 -0
  138. package/dist/live/index.d.ts.map +1 -1
  139. package/dist/live/index.js +6 -0
  140. package/dist/live/message-thread-01/index.d.ts +3 -0
  141. package/dist/live/message-thread-01/index.d.ts.map +1 -0
  142. package/dist/live/message-thread-01/index.js +1 -0
  143. package/dist/live/message-thread-01/message-thread.d.ts +282 -0
  144. package/dist/live/message-thread-01/message-thread.d.ts.map +1 -0
  145. package/dist/live/message-thread-01/message-thread.js +221 -0
  146. package/dist/live/run-stream-01/run-stream.d.ts +2 -1
  147. package/dist/live/run-stream-01/run-stream.d.ts.map +1 -1
  148. package/dist/live/run-stream-01/run-stream.js +1 -7
  149. package/dist/live/status.d.ts +27 -0
  150. package/dist/live/status.d.ts.map +1 -0
  151. package/dist/live/status.js +15 -0
  152. package/dist/live/tool-call-row.d.ts +26 -0
  153. package/dist/live/tool-call-row.d.ts.map +1 -0
  154. package/dist/live/tool-call-row.js +60 -0
  155. package/dist/live/tool-ledger-01/tool-ledger.d.ts.map +1 -1
  156. package/dist/live/tool-ledger-01/tool-ledger.js +2 -42
  157. package/dist/pages/contact-page/index.d.ts +7 -7
  158. package/dist/pages/contact-page/index.d.ts.map +1 -1
  159. package/dist/pages/contact-page/index.js +17 -5
  160. package/dist/pages/docs-shell/docs-shell.d.ts +42 -30
  161. package/dist/pages/docs-shell/docs-shell.d.ts.map +1 -1
  162. package/dist/pages/docs-shell/docs-shell.js +70 -48
  163. package/dist/pages/document-page/document-page.d.ts +146 -0
  164. package/dist/pages/document-page/document-page.d.ts.map +1 -0
  165. package/dist/pages/document-page/document-page.js +80 -0
  166. package/dist/pages/document-page/index.d.ts +3 -0
  167. package/dist/pages/document-page/index.d.ts.map +1 -0
  168. package/dist/pages/document-page/index.js +1 -0
  169. package/dist/pages/index.d.ts +2 -0
  170. package/dist/pages/index.d.ts.map +1 -1
  171. package/dist/pages/index.js +6 -0
  172. package/dist/styles.css +59 -3
  173. package/package.json +7 -2
@@ -0,0 +1,282 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type RunStatus } from '../status.js';
3
+ import type { ToolCall } from '../tool-ledger-01/tool-ledger.js';
4
+ /**
5
+ * Who a message is from, as a closed set.
6
+ *
7
+ * The four are the ones a conversation actually has, and they are closed for the
8
+ * reason `RunEventRole` is: a sender is a slot for a mark and an ink, and a
9
+ * free-text sender would be a string with no rendering behind it. The **words**
10
+ * are still the caller's, in `senderLabel`. Prism owns which sender looks like
11
+ * what, and ships none of the labels.
12
+ */
13
+ export type MessageSender = 'user' | 'assistant' | 'system' | 'tool';
14
+ /** A run of text, in the consumer's words. */
15
+ export type MessageTextPart = {
16
+ kind: 'text';
17
+ /** What the sender said. */
18
+ text: string;
19
+ };
20
+ /**
21
+ * A reasoning block: the model's own working, shown collapsed.
22
+ *
23
+ * `label` is required because a disclosure whose summary has no words is announced
24
+ * as a disclosure and nothing else, and the word on it is the consumer's.
25
+ */
26
+ export type MessageReasoningPart = {
27
+ kind: 'reasoning';
28
+ /** The words on the disclosure's summary. */
29
+ label: string;
30
+ /** The reasoning itself. */
31
+ text: string;
32
+ };
33
+ /**
34
+ * A tool call inside a message, drawn through the ledger's own row.
35
+ *
36
+ * The call is a `ToolCall`, which is the shape `ToolLedger01` already receives, so
37
+ * a tool call is drawn the same way in a message as in the ledger and there is no
38
+ * second tool-call shape.
39
+ */
40
+ export type MessageToolPart = {
41
+ kind: 'tool';
42
+ /** The call, in the vocabulary `ToolLedger01` already publishes. */
43
+ call: ToolCall;
44
+ };
45
+ /** A citation: a labelled destination for a claim in the message. */
46
+ export type MessageCitationPart = {
47
+ kind: 'citation';
48
+ /** The words on the link, required because a link with no name announces as a link. */
49
+ label: string;
50
+ /** Where it goes. */
51
+ href: string;
52
+ /** Anything the label cannot hold: a page, a line, a quote. */
53
+ detail?: string;
54
+ };
55
+ /**
56
+ * An attachment in the thread.
57
+ *
58
+ * `preview` is the consumer's own node, because the media an attachment shows is
59
+ * drawn by Items this package already ships rather than by this surface. It is
60
+ * placed above the name and never inside the link, so a preview that holds a
61
+ * control cannot nest one inside the anchor.
62
+ */
63
+ export type MessageAttachmentPart = {
64
+ kind: 'attachment';
65
+ /** The name a reader recognises it by. */
66
+ name: string;
67
+ /** Where the attachment lives, absent for one that is only named. */
68
+ href?: string;
69
+ /** The consumer's own rendering of the attachment's contents. */
70
+ preview?: ReactNode;
71
+ };
72
+ /**
73
+ * One part of a message, as the surface receives it.
74
+ *
75
+ * The five are the ones every surveyed stream converges on, and the set is closed
76
+ * because a part is a slot for a rendering rather than a free-text kind. Several
77
+ * tool calls fit in one message without a second key, which is the reason the
78
+ * content shape is a message with ordered parts rather than a flat event list.
79
+ */
80
+ export type MessagePart = MessageTextPart | MessageReasoningPart | MessageToolPart | MessageCitationPart | MessageAttachmentPart;
81
+ /**
82
+ * One message, as the surface receives it.
83
+ *
84
+ * A message has a stable identity, a sender, an optional metadata node and an
85
+ * ordered list of parts. The `id` is stable across deliveries, so a transport that
86
+ * reports the same message again as more parts arrive updates one message rather
87
+ * than appending a second. `at` is the consumer's own epoch milliseconds and the
88
+ * only value the surface orders by.
89
+ */
90
+ export type ChatMessage = {
91
+ /** Stable across deliveries, so a re-reported message updates in place. */
92
+ id: string;
93
+ /** Who sent it. See `MessageSender`. */
94
+ sender: MessageSender;
95
+ /** The sender's own name for the reader, absent for a surface that draws only the mark. */
96
+ senderLabel?: string;
97
+ /** Epoch milliseconds, used for order. */
98
+ at: number;
99
+ /**
100
+ * The caller's own per-message metadata, drawn in the message's header.
101
+ *
102
+ * A message carries one node of the caller's choosing beside the sender and the
103
+ * time: the model a provider stated for the turn, a token count it reported, and
104
+ * the cost or the latency the caller derived. It is a node rather than a set of
105
+ * Prism fields because the last two are the consumer's own derivation, which the
106
+ * conversation decision in `DESIGN.md` rules: no provider read publishes a cost
107
+ * or a latency, so the surface draws only what the caller hands it and states no
108
+ * model, no count and no figure for itself. The parts are content a reader reads
109
+ * as the message; this is metadata about the message and sits above its parts.
110
+ *
111
+ * It is the same `meta` shape `ItemEntry` takes, read at the message.
112
+ */
113
+ meta?: ReactNode;
114
+ /** The message's parts, in the order they are drawn and never re-sorted. */
115
+ parts: readonly MessagePart[];
116
+ };
117
+ /**
118
+ * How the surface receives messages.
119
+ *
120
+ * The consumer owns the socket, the transport and the persistence, so this is a
121
+ * function it supplies rather than a connection Prism opens. It is called once on
122
+ * mount and must return an unsubscribe, which is what makes a WebSocket, an
123
+ * `EventSource`, a polling timer or a test's own array all the same shape to the
124
+ * surface. Nothing here knows which one it got.
125
+ */
126
+ export type MessageSubscribe = (emit: (message: ChatMessage) => void) => () => void;
127
+ export type MessageThread01Props = {
128
+ /**
129
+ * Called once to begin receiving, and again whenever `resubscribeKey` changes.
130
+ * Must return an unsubscribe; the surface calls it on unmount and before
131
+ * re-subscribing, so a consumer that returns nothing leaks its connection.
132
+ */
133
+ subscribe: MessageSubscribe;
134
+ /**
135
+ * The messages already known when this thread is opened, so a surface opened
136
+ * mid-thread is not blank. Oldest first.
137
+ *
138
+ * Read when the thread is opened, and again whenever `resubscribeKey` changes. It
139
+ * is **not** read on every render: a prop that looked like the current message
140
+ * list and quietly seeded only once would be a trap, and a prop that re-seeded on
141
+ * every render would discard the stream. This seeds, and the stream takes over.
142
+ *
143
+ * It is also the whole of the resumption seam: the durable buffer that outlives
144
+ * a mount is the consumer's, and a surface opened after a reconnect is seeded
145
+ * from the consumer's own record rather than from anything Prism kept.
146
+ */
147
+ initial?: readonly ChatMessage[];
148
+ /**
149
+ * Which thread this surface is showing, and the reset lever.
150
+ *
151
+ * Changing it **clears the thread and reseeds it from `initial`**, as well as
152
+ * tearing the subscription down and opening a new one. A thread is identified by
153
+ * whatever the consumer already uses to identify it, so a second thread in the
154
+ * same surface is a new subscription rather than two consumers of one, and it is
155
+ * a new thread rather than the old messages with the new ones appended.
156
+ */
157
+ resubscribeKey?: string | number;
158
+ /** Where the thread has got to. The tiers are the `live` Kind's own. */
159
+ status?: RunStatus;
160
+ /** The word beside the status. Required when a status is passed. */
161
+ statusLabel?: string;
162
+ /** Optional label above the surface's heading. See the No-Default-Eyebrow Rule. */
163
+ eyebrow?: string;
164
+ /** The surface's heading. Omit it for one composed under its own. */
165
+ title?: string;
166
+ /** One or two sentences under the heading. */
167
+ description?: string;
168
+ /** What the surface says when it holds no messages yet. */
169
+ emptyLabel?: string;
170
+ /**
171
+ * The accessible name of the scrolling region.
172
+ *
173
+ * Required, because `ScrollArea` requires it and the reason is the right one: a
174
+ * scroll region with no name is announced as a group of focusable nothing, and a
175
+ * keyboard reader who tabs into it cannot tell what is in it or what is past the
176
+ * edge. The name is the consumer's word, as every other word here is.
177
+ */
178
+ messagesLabel: string;
179
+ /** Announced to assistive technology as messages arrive. */
180
+ liveLabel?: string;
181
+ /** How many messages to keep. Older messages fall off the top. @defaultValue 200 */
182
+ limit?: number;
183
+ /**
184
+ * Whether the surface opens paused.
185
+ *
186
+ * Read when the thread opens, and the control below owns it from the first press
187
+ * after that. It pauses the **surface** and never the run: the subscription stays
188
+ * open, because the connection is the consumer's and they may be sharing it with
189
+ * a `RunStream01` beside it.
190
+ */
191
+ paused?: boolean;
192
+ /** Layout only. Changing a Prism-owned visual property from here is prohibited. */
193
+ className?: string;
194
+ } & ({
195
+ pauseControl?: false;
196
+ pauseLabel?: never;
197
+ resumeLabel?: never;
198
+ } | {
199
+ pauseControl: true;
200
+ pauseLabel: string;
201
+ resumeLabel: string;
202
+ });
203
+ /**
204
+ * The message thread of a conversation, receiving messages as they arrive.
205
+ *
206
+ * **This is the `live` Kind's second family, and it is the second client surface in
207
+ * the package beside `RunStream01`.** A conversation's content changes over time
208
+ * without a navigation event, which is the definition of the Kind, and a chat that
209
+ * cannot stream is not a chat. So this surface owns a subscription and the bounded
210
+ * window behind it, exactly as the run log does.
211
+ *
212
+ * **Prism owns the surface, the consumer owns the transport.** `subscribe` is a
213
+ * function the consumer supplies and a function it tears down. There is no socket
214
+ * in this file, no endpoint, no retry policy, no persistence and no provider to
215
+ * mount, so a WebSocket, an `EventSource`, a polling timer and a test's own array
216
+ * are all the same shape to this surface. A consumer that already has a connection
217
+ * passes it in, and one that does not has not acquired a client runtime by
218
+ * importing this.
219
+ *
220
+ * **The content is a message list with ordered parts, and neither an event list nor
221
+ * a turn list is taken.** A message is an artifact a reader reads and addresses,
222
+ * where an occurrence is not, so the run's flat `RunEvent` stays the run log's own
223
+ * vocabulary. A turn is a derived grouping of a request and its answers, the
224
+ * transport does not preserve it as a unit, and the order of a stream after a
225
+ * reconnect is unsettled, so a surface that grouped by turn would impose a
226
+ * structure the consumer's data may not have. The message and part vocabulary lives
227
+ * here, beside `RunEvent` and `ToolCall`, and is deliberately not a member of the
228
+ * shared specification module.
229
+ *
230
+ * **Per-message metadata is the caller's own node.** The model a provider stated
231
+ * for a turn, a token count it reported, and the cost and the latency a consumer
232
+ * derived are metadata about a message rather than content a reader reads as it, so
233
+ * a message carries an optional `meta` the surface draws in its header beside the
234
+ * sender and the time. It is a node, and deliberately not a set of Prism fields:
235
+ * cost and latency are the consumer's own derivation, because no provider read
236
+ * publishes either, so the surface draws what it was handed and states no figure
237
+ * for itself. This is the `ItemEntry.meta` shape read at the message.
238
+ *
239
+ * **The four things the Kind already names are reused rather than answered twice.**
240
+ * A tool-call part is drawn through `ToolLedger01`'s own row, so there is no second
241
+ * tool-call shape. The status tiers are the ones `RunStatus` already publishes. The
242
+ * run controls are `PromptComposer`'s send, stop, retry and attach, which the
243
+ * consumer composes beside this surface rather than this surface drawing a second
244
+ * set of them. The one surface it does not reuse is `RunStream01`, because a run's
245
+ * log is a sequence of occurrences and a conversation is a sequence of messages.
246
+ *
247
+ * **The surface draws no control it cannot act on.** The only control in it is the
248
+ * pause control, which pauses this surface and never the run, and which a consumer
249
+ * opts into with `pauseControl`. Send, stop, retry and attach are not here: they are
250
+ * `PromptComposer`'s, and a settled thread composed outside the live module reaches
251
+ * a decision through a `CtaLink` with its required `href` or a slot the consumer
252
+ * fills.
253
+ *
254
+ * **Prism holds a bounded in-memory window and promises no resumption.** The
255
+ * durable buffer that outlives a mount is the consumer's, because Prism ships no
256
+ * permanent client runtime and cannot assume a server framework. The seam is
257
+ * `initial` and `resubscribeKey`: a surface opened mid-thread is seeded from the
258
+ * consumer's own record, a reconnect is a new key over a fresh seed, and the
259
+ * surface promises no resumption so it cannot fail to keep one.
260
+ *
261
+ * **Messages are kept sorted by `at`, not by arrival.** A transport decides when a
262
+ * message is delivered, and a reconnect can deliver an older message after a newer
263
+ * one. Ties break on `id`, so the order is total and the same thread renders the
264
+ * same way every time. The same `id` is also the same message, so a transport that
265
+ * reports it again as more parts arrive updates one message rather than adding a
266
+ * second.
267
+ *
268
+ * **New messages are announced once, politely, and the thread itself is not a live
269
+ * region.** Announcing a growing list would make a screen reader read the whole
270
+ * thread again on every arrival, which is the failure a live region on a list
271
+ * guarantees. `LiveRegion` carries the newest message's first readable part alone,
272
+ * and the thread is an ordinary scrollable list a reader moves through at their own
273
+ * pace.
274
+ *
275
+ * `limit` bounds what is held, because a long conversation produces thousands of
276
+ * messages and a surface that grows without bound eventually stops repainting.
277
+ * Older messages fall off the top, which is the direction a reader wants: the
278
+ * thread's beginning is the part they can scroll back to in the consumer's store.
279
+ */
280
+ export declare function MessageThread01({ subscribe, initial, resubscribeKey, status, statusLabel, eyebrow, title, description, emptyLabel, messagesLabel, liveLabel, limit, paused, pauseControl, pauseLabel, resumeLabel, className, }: MessageThread01Props): import("react").JSX.Element;
281
+ export default MessageThread01;
282
+ //# sourceMappingURL=message-thread.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-thread.d.ts","sourceRoot":"","sources":["../../../src/live/message-thread-01/message-thread.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,221 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { Button } from '../../components/ui/button.js';
5
+ import { LiveRegion } from '../../components/ui/live-region.js';
6
+ import { ScrollArea } from '../../components/ui/scroll-area.js';
7
+ import { headingSizeClass } from '../../components/ui/section.js';
8
+ import { cn } from '../../lib/utils.js';
9
+ import { STATUS_INK } from '../status.js';
10
+ import { ToolCallRow } from '../tool-call-row.js';
11
+ /** The ink each sender is stated in. */
12
+ const SENDER_INK = {
13
+ user: 'text-foreground',
14
+ assistant: 'text-foreground',
15
+ system: 'text-muted-foreground',
16
+ tool: 'text-muted-foreground',
17
+ };
18
+ /** The mark each sender draws, so the four are told apart without relying on colour. */
19
+ const SENDER_MARK = {
20
+ user: 'u',
21
+ assistant: 'a',
22
+ system: 's',
23
+ tool: 't',
24
+ };
25
+ /** The clock a message reads, in UTC, because the surface holds no locale to format in. */
26
+ const clockOf = (at) => new Date(at).toISOString().slice(11, 19);
27
+ /** The one source of truth for order, so a late message with an earlier `at` sorts there. */
28
+ const byTimeThenId = (a, b) => a.at - b.at || a.id.localeCompare(b.id);
29
+ /** The seed a thread opens with, already sorted and trimmed to the window. */
30
+ function seedOf(messages, limit) {
31
+ const sorted = [...messages].sort(byTimeThenId);
32
+ return sorted.length > limit ? sorted.slice(sorted.length - limit) : sorted;
33
+ }
34
+ /** One message merged into the thread, and the window applied. */
35
+ function merge(messages, message, limit) {
36
+ const at = messages.findIndex((current) => current.id === message.id);
37
+ const next = at === -1
38
+ ? [...messages, message]
39
+ : messages.map((current, index) => (index === at ? message : current));
40
+ next.sort(byTimeThenId);
41
+ return next.length > limit ? next.slice(next.length - limit) : next;
42
+ }
43
+ /**
44
+ * The one line the live region announces for an arriving message.
45
+ *
46
+ * The region carries a single short string rather than the message, because a live
47
+ * region around a growing list makes a screen reader read the whole thread again
48
+ * on every arrival. The string is the message's own first readable part, in the
49
+ * consumer's words: the first text, reasoning, tool name, citation or attachment
50
+ * name it carries.
51
+ */
52
+ function announcementOf(message) {
53
+ for (const part of message.parts) {
54
+ if (part.kind === 'text' || part.kind === 'reasoning')
55
+ return part.text;
56
+ if (part.kind === 'tool')
57
+ return part.call.name;
58
+ if (part.kind === 'citation')
59
+ return part.label;
60
+ if (part.kind === 'attachment')
61
+ return part.name;
62
+ }
63
+ return undefined;
64
+ }
65
+ /**
66
+ * The message thread of a conversation, receiving messages as they arrive.
67
+ *
68
+ * **This is the `live` Kind's second family, and it is the second client surface in
69
+ * the package beside `RunStream01`.** A conversation's content changes over time
70
+ * without a navigation event, which is the definition of the Kind, and a chat that
71
+ * cannot stream is not a chat. So this surface owns a subscription and the bounded
72
+ * window behind it, exactly as the run log does.
73
+ *
74
+ * **Prism owns the surface, the consumer owns the transport.** `subscribe` is a
75
+ * function the consumer supplies and a function it tears down. There is no socket
76
+ * in this file, no endpoint, no retry policy, no persistence and no provider to
77
+ * mount, so a WebSocket, an `EventSource`, a polling timer and a test's own array
78
+ * are all the same shape to this surface. A consumer that already has a connection
79
+ * passes it in, and one that does not has not acquired a client runtime by
80
+ * importing this.
81
+ *
82
+ * **The content is a message list with ordered parts, and neither an event list nor
83
+ * a turn list is taken.** A message is an artifact a reader reads and addresses,
84
+ * where an occurrence is not, so the run's flat `RunEvent` stays the run log's own
85
+ * vocabulary. A turn is a derived grouping of a request and its answers, the
86
+ * transport does not preserve it as a unit, and the order of a stream after a
87
+ * reconnect is unsettled, so a surface that grouped by turn would impose a
88
+ * structure the consumer's data may not have. The message and part vocabulary lives
89
+ * here, beside `RunEvent` and `ToolCall`, and is deliberately not a member of the
90
+ * shared specification module.
91
+ *
92
+ * **Per-message metadata is the caller's own node.** The model a provider stated
93
+ * for a turn, a token count it reported, and the cost and the latency a consumer
94
+ * derived are metadata about a message rather than content a reader reads as it, so
95
+ * a message carries an optional `meta` the surface draws in its header beside the
96
+ * sender and the time. It is a node, and deliberately not a set of Prism fields:
97
+ * cost and latency are the consumer's own derivation, because no provider read
98
+ * publishes either, so the surface draws what it was handed and states no figure
99
+ * for itself. This is the `ItemEntry.meta` shape read at the message.
100
+ *
101
+ * **The four things the Kind already names are reused rather than answered twice.**
102
+ * A tool-call part is drawn through `ToolLedger01`'s own row, so there is no second
103
+ * tool-call shape. The status tiers are the ones `RunStatus` already publishes. The
104
+ * run controls are `PromptComposer`'s send, stop, retry and attach, which the
105
+ * consumer composes beside this surface rather than this surface drawing a second
106
+ * set of them. The one surface it does not reuse is `RunStream01`, because a run's
107
+ * log is a sequence of occurrences and a conversation is a sequence of messages.
108
+ *
109
+ * **The surface draws no control it cannot act on.** The only control in it is the
110
+ * pause control, which pauses this surface and never the run, and which a consumer
111
+ * opts into with `pauseControl`. Send, stop, retry and attach are not here: they are
112
+ * `PromptComposer`'s, and a settled thread composed outside the live module reaches
113
+ * a decision through a `CtaLink` with its required `href` or a slot the consumer
114
+ * fills.
115
+ *
116
+ * **Prism holds a bounded in-memory window and promises no resumption.** The
117
+ * durable buffer that outlives a mount is the consumer's, because Prism ships no
118
+ * permanent client runtime and cannot assume a server framework. The seam is
119
+ * `initial` and `resubscribeKey`: a surface opened mid-thread is seeded from the
120
+ * consumer's own record, a reconnect is a new key over a fresh seed, and the
121
+ * surface promises no resumption so it cannot fail to keep one.
122
+ *
123
+ * **Messages are kept sorted by `at`, not by arrival.** A transport decides when a
124
+ * message is delivered, and a reconnect can deliver an older message after a newer
125
+ * one. Ties break on `id`, so the order is total and the same thread renders the
126
+ * same way every time. The same `id` is also the same message, so a transport that
127
+ * reports it again as more parts arrive updates one message rather than adding a
128
+ * second.
129
+ *
130
+ * **New messages are announced once, politely, and the thread itself is not a live
131
+ * region.** Announcing a growing list would make a screen reader read the whole
132
+ * thread again on every arrival, which is the failure a live region on a list
133
+ * guarantees. `LiveRegion` carries the newest message's first readable part alone,
134
+ * and the thread is an ordinary scrollable list a reader moves through at their own
135
+ * pace.
136
+ *
137
+ * `limit` bounds what is held, because a long conversation produces thousands of
138
+ * messages and a surface that grows without bound eventually stops repainting.
139
+ * Older messages fall off the top, which is the direction a reader wants: the
140
+ * thread's beginning is the part they can scroll back to in the consumer's store.
141
+ */
142
+ export function MessageThread01({ subscribe, initial, resubscribeKey, status, statusLabel, eyebrow, title, description, emptyLabel, messagesLabel, liveLabel, limit = 200, paused, pauseControl, pauseLabel, resumeLabel, className, }) {
143
+ /**
144
+ * The thread, held against the key that produced it.
145
+ *
146
+ * Adjusting state during render when the key changes is React's documented
147
+ * pattern for "a prop changed, start over", and it is the right one here: the
148
+ * alternative is an effect, and an effect that clears the thread runs *after* a
149
+ * render, so the surface would paint one frame holding the previous thread's
150
+ * messages under the new thread's heading.
151
+ */
152
+ const [newest, setNewest] = useState(undefined);
153
+ const [thread, setThread] = useState(() => ({
154
+ key: resubscribeKey,
155
+ messages: seedOf(initial ?? [], limit),
156
+ }));
157
+ if (thread.key !== resubscribeKey) {
158
+ setThread({ key: resubscribeKey, messages: seedOf(initial ?? [], limit) });
159
+ // The announcement is cleared with the thread it announced, so a thread switch
160
+ // does not leave the previous thread's last message in the live region saying so.
161
+ setNewest(undefined);
162
+ }
163
+ const messages = thread.messages;
164
+ /**
165
+ * Whether this surface is holding still, kept in a ref as well as in state.
166
+ *
167
+ * The ref is what the arrival path reads, and it is why the subscription effect
168
+ * does not list the pause among its dependencies: an effect that depended on the
169
+ * pause would tear the consumer's connection down and open a new one every time a
170
+ * reader pressed the control. The button writes both, so the value the effect
171
+ * reads is the value the reader set.
172
+ */
173
+ const [held, setHeldState] = useState(paused === true);
174
+ const heldRef = useRef(held);
175
+ const setHeld = (next) => {
176
+ heldRef.current = next;
177
+ setHeldState(next);
178
+ };
179
+ // A ref rather than state, so the effect does not re-subscribe because a message
180
+ // arrived. An effect that depended on the value it writes re-runs itself, and the
181
+ // surface would open a new subscription per message.
182
+ const emit = useRef(() => { });
183
+ useEffect(() => {
184
+ emit.current = (message) => {
185
+ // Read through the ref, so a paused surface decides without re-subscribing.
186
+ if (heldRef.current)
187
+ return;
188
+ setThread((current) => ({
189
+ ...current,
190
+ messages: merge(current.messages, message, limit),
191
+ }));
192
+ setNewest(announcementOf(message));
193
+ };
194
+ const stop = subscribe(emit.current);
195
+ return () => {
196
+ // Calling an unsubscribe the consumer did not return would throw during
197
+ // unmount, so a missing one is stepped over and the leak is the consumer's to
198
+ // fix rather than a crash in someone else's teardown.
199
+ if (typeof stop === 'function')
200
+ stop();
201
+ };
202
+ }, [subscribe, resubscribeKey, limit]);
203
+ return (_jsxs("section", { "data-slot": "message-thread", className: cn('border-border flex flex-col gap-4 rounded-lg border p-4', className), children: [LiveRegion({ politeness: 'polite', label: liveLabel, children: newest }), title !== undefined || eyebrow !== undefined || description !== undefined ? (_jsxs("header", { className: "flex flex-col gap-1", children: [eyebrow ? (_jsx("span", { className: "text-muted-foreground text-xs font-medium tracking-wide uppercase", children: eyebrow })) : null, title ? (_jsx("h2", { className: cn('font-semibold tracking-tight text-balance', headingSizeClass('h2')), children: title })) : null, description ? (_jsx("p", { className: "text-muted-foreground text-pretty text-sm", children: description })) : null] })) : null, status !== undefined ? (_jsx("p", { "data-slot": "thread-status", className: cn('font-mono text-xs', STATUS_INK[status]), children: statusLabel })) : null, pauseControl === true ? (_jsx("div", { "data-slot": "thread-bar", className: "flex flex-wrap items-center gap-3", children: _jsx(Button, { "data-slot": "thread-pause", type: "button", variant: "outline", size: "sm", "aria-pressed": held, className: "ml-auto", onClick: () => setHeld(!heldRef.current), children: held ? resumeLabel : pauseLabel }) })) : null, messages.length === 0 ? (_jsx("p", { "data-slot": "message-thread-empty", className: "text-muted-foreground text-sm", children: emptyLabel })) : (_jsx(ScrollArea, { label: messagesLabel, className: "max-h-96", children: _jsx("ol", { "data-slot": "thread-messages", className: "flex flex-col gap-4", children: messages.map((message) => (_jsxs("li", { "data-slot": "thread-message", "data-sender": message.sender, className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-baseline gap-x-2", children: [_jsx("span", { "aria-hidden": "true", className: cn('font-mono text-xs', SENDER_INK[message.sender]), children: SENDER_MARK[message.sender] }), message.senderLabel ? (_jsx("span", { className: "text-foreground text-xs font-medium", children: message.senderLabel })) : null, _jsx("time", { dateTime: new Date(message.at).toISOString(), className: "text-muted-foreground font-mono text-xs tabular-nums", children: clockOf(message.at) }), message.meta === undefined ? null : (_jsx("span", { "data-slot": "thread-message-meta", className: "text-muted-foreground text-xs", children: message.meta }))] }), _jsx("ol", { "data-slot": "message-parts", className: "flex flex-col gap-2", children: message.parts.map((part, index) => (_jsx("li", { "data-slot": "message-part", "data-kind": part.kind, className: "text-sm", children: renderPart(part) }, `${message.id}-${index}`))) })] }, message.id))) }) }))] }));
204
+ }
205
+ /** One part, drawn by its kind. */
206
+ function renderPart(part) {
207
+ if (part.kind === 'text') {
208
+ return _jsx("p", { className: "text-foreground text-pretty text-sm", children: part.text });
209
+ }
210
+ if (part.kind === 'reasoning') {
211
+ return (_jsxs("details", { "data-slot": "message-reasoning", className: "text-muted-foreground text-sm", children: [_jsx("summary", { className: "cursor-pointer text-xs font-medium", children: part.label }), _jsx("p", { className: "text-muted-foreground text-pretty text-sm", children: part.text })] }));
212
+ }
213
+ if (part.kind === 'tool') {
214
+ return (_jsx("div", { className: "border-border flex flex-col gap-1 rounded-md border p-2", children: _jsx(ToolCallRow, { call: part.call, openedAt: part.call.at }) }));
215
+ }
216
+ if (part.kind === 'citation') {
217
+ return (_jsxs("span", { className: "flex flex-col gap-0.5", children: [_jsx("a", { "data-slot": "message-citation", href: part.href, className: "text-foreground self-start rounded-sm text-sm underline-offset-4 hover:underline", children: part.label }), part.detail ? (_jsx("span", { className: "text-muted-foreground text-pretty text-xs", children: part.detail })) : null] }));
218
+ }
219
+ return (_jsxs("span", { "data-slot": "message-attachment", className: "border-border flex flex-col gap-1 rounded-md border p-2", children: [part.preview ? _jsx("span", { className: "block", children: part.preview }) : null, part.href ? (_jsx("a", { "data-slot": "message-attachment-link", href: part.href, className: "text-foreground self-start rounded-sm text-sm underline-offset-4 hover:underline", children: part.name })) : (_jsx("span", { className: "text-foreground text-sm", children: part.name }))] }));
220
+ }
221
+ export default MessageThread01;
@@ -1,3 +1,4 @@
1
+ import { type RunStatus } from '../status.js';
1
2
  /**
2
3
  * Who produced an event, as a closed set.
3
4
  *
@@ -21,7 +22,7 @@ export type RunEvent = {
21
22
  detail?: string;
22
23
  };
23
24
  /** Where a run has got to. The tiers are Prism's; the words beside them are the caller's. */
24
- export type RunStatus = 'queued' | 'running' | 'waiting' | 'done' | 'failed';
25
+ export type { RunStatus };
25
26
  /**
26
27
  * How the surface receives events.
27
28
  *
@@ -1 +1 @@
1
- {"version":3,"file":"run-stream.d.ts","sourceRoot":"","sources":["../../../src/live/run-stream-01/run-stream.tsx"],"names":[],"mappings":"AASA;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEhE,6CAA6C;AAC7C,MAAM,MAAM,QAAQ,GAAG;IACrB,2FAA2F;IAC3F,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,YAAY,CAAA;IAClB,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAA;IACV,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAA;IACf,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,6FAA6F;AAC7F,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAA;AAE5E;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;AAE1E,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;OAIG;IACH,SAAS,EAAE,YAAY,CAAA;IACvB;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAChC;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAA;IAC7B,gCAAgC;IAChC,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;;;OAOG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AA8BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,cAAc,EACd,OAAO,EACP,MAAM,EACN,WAAW,EACX,OAAO,EACP,KAAK,EACL,WAAW,EACX,UAAU,EACV,WAAW,EACX,SAAS,EACT,KAAW,EACX,SAAS,GACV,EAAE,gBAAgB,+BA0IlB;AAED,eAAe,WAAW,CAAA"}
1
+ {"version":3,"file":"run-stream.d.ts","sourceRoot":"","sources":["../../../src/live/run-stream-01/run-stream.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,WAAW,CAAA;AAEtD;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEhE,6CAA6C;AAC7C,MAAM,MAAM,QAAQ,GAAG;IACrB,2FAA2F;IAC3F,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,YAAY,CAAA;IAClB,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAA;IACV,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAA;IACf,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,6FAA6F;AAC7F,YAAY,EAAE,SAAS,EAAE,CAAA;AAEzB;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;AAE1E,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;OAIG;IACH,SAAS,EAAE,YAAY,CAAA;IACvB;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAChC;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAA;IAC7B,gCAAgC;IAChC,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;;;OAOG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAsBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,cAAc,EACd,OAAO,EACP,MAAM,EACN,WAAW,EACX,OAAO,EACP,KAAK,EACL,WAAW,EACX,UAAU,EACV,WAAW,EACX,SAAS,EACT,KAAW,EACX,SAAS,GACV,EAAE,gBAAgB,+BA0IlB;AAED,eAAe,WAAW,CAAA"}
@@ -5,6 +5,7 @@ import { LiveRegion } from '../../components/ui/live-region.js';
5
5
  import { ScrollArea } from '../../components/ui/scroll-area.js';
6
6
  import { headingSizeClass } from '../../components/ui/section.js';
7
7
  import { cn } from '../../lib/utils.js';
8
+ import { STATUS_INK } from '../status.js';
8
9
  /** The ink each role is stated in, and the tick beside it. */
9
10
  const ROLE_INK = {
10
11
  agent: 'text-foreground',
@@ -19,13 +20,6 @@ const ROLE_MARK = {
19
20
  system: '·',
20
21
  error: '×',
21
22
  };
22
- const STATUS_INK = {
23
- queued: 'text-muted-foreground',
24
- running: 'text-foreground',
25
- waiting: 'text-warning',
26
- done: 'text-success',
27
- failed: 'text-destructive',
28
- };
29
23
  /** The one source of truth for order, so a late event with an earlier `at` sorts there. */
30
24
  const byTimeThenId = (a, b) => a.at - b.at || a.id.localeCompare(b.id);
31
25
  /**
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Where a live surface has got to, as the Kind's one closed set of tiers.
3
+ *
4
+ * A run and a conversation are two families of the same Kind, and a reader
5
+ * watching either one asks the same question: is this queued, running, waiting,
6
+ * done or failed. The tiers are therefore declared once, here, and every live
7
+ * surface draws its state from them rather than minting a vocabulary of its own.
8
+ * A second status word invented for a conversation would be a second answer to a
9
+ * question this set already answers, and two answers that agree today are a
10
+ * catalogue drifting a second list.
11
+ *
12
+ * The **words** beside a tier are still the consumer's: Prism owns which tier
13
+ * looks like what, and ships none of the labels. The ink below is the whole of
14
+ * what the Kind states about a tier, and it is stated once so the run log and the
15
+ * message thread cannot disagree about what a failure looks like.
16
+ */
17
+ export type RunStatus = 'queued' | 'running' | 'waiting' | 'done' | 'failed';
18
+ /**
19
+ * The ink each tier is stated in.
20
+ *
21
+ * The five roles are the ones an agent surface actually reports, and the ink is
22
+ * the one Prism-owned visual fact about a tier. `waiting` and `failed` are the
23
+ * two that carry a colour a reader acts on, which is why they are the two that
24
+ * are not the foreground or the muted ink.
25
+ */
26
+ export declare const STATUS_INK: Record<RunStatus, string>;
27
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/live/status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAA;AAE5E;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAMhD,CAAA"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The ink each tier is stated in.
3
+ *
4
+ * The five roles are the ones an agent surface actually reports, and the ink is
5
+ * the one Prism-owned visual fact about a tier. `waiting` and `failed` are the
6
+ * two that carry a colour a reader acts on, which is why they are the two that
7
+ * are not the foreground or the muted ink.
8
+ */
9
+ export const STATUS_INK = {
10
+ queued: 'text-muted-foreground',
11
+ running: 'text-foreground',
12
+ waiting: 'text-warning',
13
+ done: 'text-success',
14
+ failed: 'text-destructive',
15
+ };
@@ -0,0 +1,26 @@
1
+ import type { ToolCall } from './tool-ledger-01/tool-ledger.js';
2
+ /** The clock a row reads, in UTC, because the surface holds no locale to format in. */
3
+ export declare const clockOf: (at: number) => string;
4
+ /**
5
+ * One tool call, drawn as the ledger draws it.
6
+ *
7
+ * **This is the tool-call row the `live` Kind owns, and it is shared rather than
8
+ * copied.** `ToolLedger01` draws one row per call in its ledger, and a
9
+ * conversation's tool-call part draws the same row inside a message, so the two
10
+ * surfaces cannot drift into two shapes for one call. `ToolLedger01` renders this
11
+ * inside its own `<li>`; the message thread renders it inside a part. The
12
+ * Component owns no `<li>`, so it can sit in either list without nesting one.
13
+ *
14
+ * **The duration is the difference between two sightings of the same call, and
15
+ * only when there are two.** `openedAt` is the moment the surface first saw the
16
+ * call's `id`; a call seen once has no second timestamp and draws no duration,
17
+ * because a zero is a claim that a call took no time. The sentence is the
18
+ * consumer's, on `call.durationLabel`, and the arithmetic is one subtraction of
19
+ * the consumer's own `at` values. There is no clock in this file.
20
+ */
21
+ export declare function ToolCallRow({ call, openedAt }: {
22
+ call: ToolCall;
23
+ openedAt: number;
24
+ }): import("react").JSX.Element;
25
+ export default ToolCallRow;
26
+ //# sourceMappingURL=tool-call-row.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-call-row.d.ts","sourceRoot":"","sources":["../../src/live/tool-call-row.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,8BAA8B,CAAA;AAgC3E,uFAAuF;AACvF,eAAO,MAAM,OAAO,GAAI,IAAI,MAAM,KAAG,MAAkD,CAAA;AAEvF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,+BAqFnF;AAED,eAAe,WAAW,CAAA"}