camox 0.72.0 → 0.74.1

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 (36) hide show
  1. package/dist/features/preview/components/PageInfo.js +121 -98
  2. package/dist/features/preview/components/SelectionEditor.js +1 -1
  3. package/dist/features/routes/pageRuntime.js +15 -4
  4. package/dist/features/runtime/ClaimCard.js +192 -0
  5. package/dist/features/runtime/pageApp.js +4 -3
  6. package/dist/features/runtime/runtime.js +26 -5
  7. package/dist/features/runtime/worker.js +2 -2
  8. package/dist/features/runtime/workerRequest.d.ts +6 -0
  9. package/dist/features/runtime/workerRequest.js +13 -1
  10. package/dist/features/runtime/workerRuntime.d.ts +2 -2
  11. package/dist/features/runtime/workerRuntime.js +2 -2
  12. package/dist/features/studio/components/AgentSidebar.js +7 -7
  13. package/dist/features/studio/components/ChatWidget.js +142 -106
  14. package/dist/features/studio/components/ContentFindings.js +127 -230
  15. package/dist/features/studio/components/DeleteDraftDialog.js +112 -0
  16. package/dist/features/studio/components/DraftBar.js +98 -53
  17. package/dist/features/studio/components/DraftsControl.js +203 -190
  18. package/dist/features/studio/components/ReviewDraftDialog.js +670 -0
  19. package/dist/features/studio/components/{Patrol.js → Specialists.js} +291 -330
  20. package/dist/features/studio/components/Squareling.js +5 -5
  21. package/dist/features/studio/components/ThreadComposer.js +106 -127
  22. package/dist/features/studio/components/ThreadMessages.js +94 -69
  23. package/dist/features/studio/findingSentence.js +14 -12
  24. package/dist/features/studio/fixMessage.js +23 -0
  25. package/dist/features/studio/reportSentence.js +1 -1
  26. package/dist/features/studio/{patrollerBio.js → specialistBio.js} +8 -5
  27. package/dist/features/studio/studioStore.js +29 -15
  28. package/dist/features/studio/workingSentence.js +1 -1
  29. package/dist/lib/api-client.js +5 -1
  30. package/dist/lib/queries.js +5 -5
  31. package/dist/lib/studio-reads.d.ts +1 -1
  32. package/dist/lib/studio-reads.js +5 -5
  33. package/dist/package.js +1 -1
  34. package/dist/studio.css +1 -1
  35. package/package.json +4 -4
  36. package/dist/features/studio/components/ReviewDraftSheet.js +0 -1587
@@ -9,12 +9,12 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
9
  * mark, or at the editor while idle. Its face and motion say what it is doing. The animations
10
10
  * live in `studio.css`.
11
11
  *
12
- * The agent's (the default) is the logo's square with its soft corner, in emerald. Each patroller
12
+ * The agent's (the default) is the logo's square with its soft corner, in emerald. Each specialist
13
13
  * has its own, one family: the Translator is the logo's wide wedge, in violet, glancing across
14
14
  * while it works; the SEO manager is a tall block with the small shape's soft corner, in amber,
15
15
  * scanning down while it works.
16
16
  *
17
- * A patroller off duty where the editor is sleeps, eyes closed, breathing slowly.
17
+ * A specialist off duty where the editor is sleeps, eyes closed, breathing slowly.
18
18
  *
19
19
  * One face flows into the next: its eyes glide to where the next face holds them, opening or
20
20
  * narrowing, and a looping motion settles before the next one starts (`useFaceChange`).
@@ -67,7 +67,7 @@ function Squareling(props) {
67
67
  children: props.variant === void 0 || props.variant === "agent" ? /* @__PURE__ */ jsx(AgentEyes, {
68
68
  eyes: look.eyes,
69
69
  status: props.status
70
- }) : /* @__PURE__ */ jsx(PatrollerEyes, {
70
+ }) : /* @__PURE__ */ jsx(SpecialistEyes, {
71
71
  eyes: look.eyes,
72
72
  working: props.status === "working",
73
73
  asleep: props.status === "asleep"
@@ -306,10 +306,10 @@ function AgentEyes(t0) {
306
306
  return t5;
307
307
  }
308
308
  /**
309
- * A patroller's eyes: open while idle, narrowed on the work while working, closed while asleep,
309
+ * A specialist's eyes: open while idle, narrowed on the work while working, closed while asleep,
310
310
  * when they don't blink.
311
311
  */
312
- function PatrollerEyes({ eyes, working, asleep }) {
312
+ function SpecialistEyes({ eyes, working, asleep }) {
313
313
  return eyes.x.map((x) => /* @__PURE__ */ jsx(Eye, {
314
314
  x,
315
315
  y: eyes.y,
@@ -8,14 +8,13 @@ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupTextarea } fro
8
8
  /**
9
9
  * Where an editor writes to the agent: Enter sends, Shift+Enter adds a line. While a run is
10
10
  * going, sending steers it, and a Stop button sits beside Send. Over the message, what the
11
- * editor has selected, which their messages carry to the agent until they clear it. A message
12
- * filled in from elsewhere in the studio replaces what the editor wrote, for them to send. Given a
11
+ * editor has selected, which their messages carry to the agent until they clear it. Given a
13
12
  * `carry`, the composer of the next thread goes on from this one, as when the studio enters the
14
13
  * draft the editor's request was handed off to: with what they were writing, focused if it was.
15
14
  */
16
15
  function ThreadComposer(t0) {
17
- const $ = c(48);
18
- const { onSend, onStop, selection, onClearSelection, running: t1, disabled: t2, filled, carry } = t0;
16
+ const $ = c(45);
17
+ const { onSend, onStop, selection, onClearSelection, running: t1, disabled: t2, carry } = t0;
19
18
  const running = t1 === void 0 ? false : t1;
20
19
  const disabled = t2 === void 0 ? false : t2;
21
20
  let t3;
@@ -25,11 +24,6 @@ function ThreadComposer(t0) {
25
24
  $[1] = t3;
26
25
  } else t3 = $[1];
27
26
  const [text, setText] = useState(t3);
28
- const [filledId, setFilledId] = useState();
29
- if (filled && filled.id !== filledId) {
30
- setFilledId(filled.id);
31
- setText(filled.text);
32
- }
33
27
  const box = useRef(null);
34
28
  let t4;
35
29
  let t5;
@@ -72,53 +66,38 @@ function ThreadComposer(t0) {
72
66
  }
73
67
  useLayoutEffect(t6, t7);
74
68
  let t8;
75
- let t9;
76
- if ($[9] !== filledId) {
77
- t8 = () => {
78
- if (filledId !== void 0) box.current?.focus();
79
- };
80
- t9 = [filledId];
81
- $[9] = filledId;
69
+ if ($[9] !== text) {
70
+ t8 = text.trim();
71
+ $[9] = text;
82
72
  $[10] = t8;
83
- $[11] = t9;
84
- } else {
85
- t8 = $[10];
86
- t9 = $[11];
87
- }
88
- useEffect(t8, t9);
89
- let t10;
90
- if ($[12] !== text) {
91
- t10 = text.trim();
92
- $[12] = text;
93
- $[13] = t10;
94
- } else t10 = $[13];
95
- const message = t10;
73
+ } else t8 = $[10];
74
+ const message = t8;
96
75
  const canSend = !disabled && message !== "" && onSend !== void 0;
97
- let t11;
98
- if ($[14] !== canSend || $[15] !== message || $[16] !== onSend) {
99
- t11 = () => {
76
+ let t9;
77
+ if ($[11] !== canSend || $[12] !== message || $[13] !== onSend) {
78
+ t9 = () => {
100
79
  if (!canSend) return;
101
80
  onSend(message);
102
81
  setText("");
103
82
  };
104
- $[14] = canSend;
105
- $[15] = message;
106
- $[16] = onSend;
107
- $[17] = t11;
108
- } else t11 = $[17];
109
- const submit = t11;
110
- let t12;
111
- if ($[18] !== submit) {
112
- t12 = (event) => {
83
+ $[11] = canSend;
84
+ $[12] = message;
85
+ $[13] = onSend;
86
+ $[14] = t9;
87
+ } else t9 = $[14];
88
+ const submit = t9;
89
+ let t10;
90
+ if ($[15] !== submit) {
91
+ t10 = (event) => {
113
92
  event.preventDefault();
114
93
  submit();
115
94
  };
116
- $[18] = submit;
117
- $[19] = t12;
118
- } else t12 = $[19];
119
- let t13;
120
- if ($[20] !== onClearSelection || $[21] !== selection) {
121
- t13 = selection && /* @__PURE__ */ jsx(InputGroupAddon, {
95
+ $[15] = submit;
96
+ $[16] = t10;
97
+ } else t10 = $[16];
98
+ let t11;
99
+ if ($[17] !== onClearSelection || $[18] !== selection) {
100
+ t11 = selection && /* @__PURE__ */ jsx(InputGroupAddon, {
122
101
  align: "block-start",
123
102
  className: "border-input border-b",
124
103
  children: /* @__PURE__ */ jsx(SelectionChip, {
@@ -126,45 +105,45 @@ function ThreadComposer(t0) {
126
105
  onClear: onClearSelection
127
106
  })
128
107
  });
129
- $[20] = onClearSelection;
130
- $[21] = selection;
131
- $[22] = t13;
132
- } else t13 = $[22];
133
- let t14;
134
- if ($[23] === Symbol.for("react.memo_cache_sentinel")) {
135
- t14 = (event_0) => setText(event_0.target.value);
136
- $[23] = t14;
137
- } else t14 = $[23];
138
- let t15;
139
- if ($[24] !== submit) {
140
- t15 = (event_1) => {
108
+ $[17] = onClearSelection;
109
+ $[18] = selection;
110
+ $[19] = t11;
111
+ } else t11 = $[19];
112
+ let t12;
113
+ if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
114
+ t12 = (event_0) => setText(event_0.target.value);
115
+ $[20] = t12;
116
+ } else t12 = $[20];
117
+ let t13;
118
+ if ($[21] !== submit) {
119
+ t13 = (event_1) => {
141
120
  if (event_1.key !== "Enter" || event_1.shiftKey || event_1.nativeEvent.isComposing) return;
142
121
  event_1.preventDefault();
143
122
  submit();
144
123
  };
145
- $[24] = submit;
146
- $[25] = t15;
147
- } else t15 = $[25];
148
- let t16;
149
- if ($[26] !== disabled || $[27] !== t15 || $[28] !== text) {
150
- t16 = /* @__PURE__ */ jsx(InputGroupTextarea, {
124
+ $[21] = submit;
125
+ $[22] = t13;
126
+ } else t13 = $[22];
127
+ let t14;
128
+ if ($[23] !== disabled || $[24] !== t13 || $[25] !== text) {
129
+ t14 = /* @__PURE__ */ jsx(InputGroupTextarea, {
151
130
  ref: box,
152
131
  "aria-label": "Message",
153
132
  placeholder: "Message Camox…",
154
133
  value: text,
155
134
  disabled,
156
- onChange: t14,
157
- onKeyDown: t15,
135
+ onChange: t12,
136
+ onKeyDown: t13,
158
137
  className: "max-h-48 min-h-14"
159
138
  });
160
- $[26] = disabled;
161
- $[27] = t15;
162
- $[28] = text;
163
- $[29] = t16;
164
- } else t16 = $[29];
165
- let t17;
166
- if ($[30] !== disabled || $[31] !== onStop || $[32] !== running) {
167
- t17 = running && onStop && /* @__PURE__ */ jsxs(InputGroupButton, {
139
+ $[23] = disabled;
140
+ $[24] = t13;
141
+ $[25] = text;
142
+ $[26] = t14;
143
+ } else t14 = $[26];
144
+ let t15;
145
+ if ($[27] !== disabled || $[28] !== onStop || $[29] !== running) {
146
+ t15 = running && onStop && /* @__PURE__ */ jsxs(InputGroupButton, {
168
147
  type: "button",
169
148
  variant: "outline",
170
149
  size: "icon-sm",
@@ -175,73 +154,73 @@ function ThreadComposer(t0) {
175
154
  children: "Stop"
176
155
  })]
177
156
  });
178
- $[30] = disabled;
179
- $[31] = onStop;
180
- $[32] = running;
181
- $[33] = t17;
182
- } else t17 = $[33];
183
- const t18 = !canSend;
184
- let t19;
185
- let t20;
186
- if ($[34] === Symbol.for("react.memo_cache_sentinel")) {
187
- t19 = /* @__PURE__ */ jsx(ArrowUp, {});
188
- t20 = /* @__PURE__ */ jsx("span", {
157
+ $[27] = disabled;
158
+ $[28] = onStop;
159
+ $[29] = running;
160
+ $[30] = t15;
161
+ } else t15 = $[30];
162
+ const t16 = !canSend;
163
+ let t17;
164
+ let t18;
165
+ if ($[31] === Symbol.for("react.memo_cache_sentinel")) {
166
+ t17 = /* @__PURE__ */ jsx(ArrowUp, {});
167
+ t18 = /* @__PURE__ */ jsx("span", {
189
168
  className: "sr-only",
190
169
  children: "Send"
191
170
  });
192
- $[34] = t19;
193
- $[35] = t20;
171
+ $[31] = t17;
172
+ $[32] = t18;
194
173
  } else {
195
- t19 = $[34];
196
- t20 = $[35];
174
+ t17 = $[31];
175
+ t18 = $[32];
197
176
  }
198
- let t21;
199
- if ($[36] !== t18) {
200
- t21 = /* @__PURE__ */ jsxs(InputGroupButton, {
177
+ let t19;
178
+ if ($[33] !== t16) {
179
+ t19 = /* @__PURE__ */ jsxs(InputGroupButton, {
201
180
  type: "submit",
202
181
  variant: "default",
203
182
  size: "icon-sm",
204
- disabled: t18,
205
- children: [t19, t20]
183
+ disabled: t16,
184
+ children: [t17, t18]
206
185
  });
207
- $[36] = t18;
208
- $[37] = t21;
209
- } else t21 = $[37];
210
- let t22;
211
- if ($[38] !== t17 || $[39] !== t21) {
212
- t22 = /* @__PURE__ */ jsxs(InputGroupAddon, {
186
+ $[33] = t16;
187
+ $[34] = t19;
188
+ } else t19 = $[34];
189
+ let t20;
190
+ if ($[35] !== t15 || $[36] !== t19) {
191
+ t20 = /* @__PURE__ */ jsxs(InputGroupAddon, {
213
192
  align: "block-end",
214
193
  className: "justify-end",
215
- children: [t17, t21]
194
+ children: [t15, t19]
216
195
  });
217
- $[38] = t17;
218
- $[39] = t21;
219
- $[40] = t22;
220
- } else t22 = $[40];
221
- let t23;
222
- if ($[41] !== t13 || $[42] !== t16 || $[43] !== t22) {
223
- t23 = /* @__PURE__ */ jsxs(InputGroup, { children: [
224
- t13,
225
- t16,
226
- t22
196
+ $[35] = t15;
197
+ $[36] = t19;
198
+ $[37] = t20;
199
+ } else t20 = $[37];
200
+ let t21;
201
+ if ($[38] !== t11 || $[39] !== t14 || $[40] !== t20) {
202
+ t21 = /* @__PURE__ */ jsxs(InputGroup, { children: [
203
+ t11,
204
+ t14,
205
+ t20
227
206
  ] });
228
- $[41] = t13;
229
- $[42] = t16;
230
- $[43] = t22;
231
- $[44] = t23;
232
- } else t23 = $[44];
233
- let t24;
234
- if ($[45] !== t12 || $[46] !== t23) {
235
- t24 = /* @__PURE__ */ jsx("form", {
207
+ $[38] = t11;
208
+ $[39] = t14;
209
+ $[40] = t20;
210
+ $[41] = t21;
211
+ } else t21 = $[41];
212
+ let t22;
213
+ if ($[42] !== t10 || $[43] !== t21) {
214
+ t22 = /* @__PURE__ */ jsx("form", {
236
215
  className: "p-2",
237
- onSubmit: t12,
238
- children: t23
216
+ onSubmit: t10,
217
+ children: t21
239
218
  });
240
- $[45] = t12;
241
- $[46] = t23;
242
- $[47] = t24;
243
- } else t24 = $[47];
244
- return t24;
219
+ $[42] = t10;
220
+ $[43] = t21;
221
+ $[44] = t22;
222
+ } else t22 = $[44];
223
+ return t22;
245
224
  }
246
225
  /** A carrier that lasts as long as the component that keeps it. */
247
226
  function useComposerCarrier() {
@@ -298,7 +298,7 @@ const PUSH_OUTCOMES = {
298
298
  notPreviewed: "Built, but the preview can’t show it."
299
299
  };
300
300
  function ThreadMessageRow(t0) {
301
- const $ = c(46);
301
+ const $ = c(50);
302
302
  const { message, onOpenDraft } = t0;
303
303
  if (message.from === "draft") {
304
304
  let t1;
@@ -407,95 +407,117 @@ function ThreadMessageRow(t0) {
407
407
  }
408
408
  if (message.from === "connectedAgent") {
409
409
  const { member, client } = message;
410
+ const sender = `${member.name}’s ${client.verified ? client.name : "agent"}`;
411
+ if (message.answer) {
412
+ const t1 = `${sender} added context`;
413
+ const t2 = client.verified ? void 0 : client.name;
414
+ let t3;
415
+ if ($[26] !== message.text || $[27] !== t1 || $[28] !== t2) {
416
+ t3 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(CollapsedNote, {
417
+ label: t1,
418
+ hideLabel: "Hide the context",
419
+ title: t2,
420
+ text: message.text
421
+ }) }) });
422
+ $[26] = message.text;
423
+ $[27] = t1;
424
+ $[28] = t2;
425
+ $[29] = t3;
426
+ } else t3 = $[29];
427
+ return t3;
428
+ }
410
429
  const t1 = client.verified ? void 0 : client.name;
411
- const t2 = `${member.name}’s ${client.verified ? client.name : "agent"}`;
412
- let t3;
413
- if ($[26] !== t1 || $[27] !== t2) {
414
- t3 = /* @__PURE__ */ jsx(MessageHeader, {
430
+ let t2;
431
+ if ($[30] !== sender || $[31] !== t1) {
432
+ t2 = /* @__PURE__ */ jsx(MessageHeader, {
415
433
  className: "text-muted-foreground text-xs",
416
434
  title: t1,
417
- children: t2
435
+ children: sender
418
436
  });
419
- $[26] = t1;
420
- $[27] = t2;
421
- $[28] = t3;
422
- } else t3 = $[28];
423
- let t4;
424
- if ($[29] !== message.text) {
425
- t4 = /* @__PURE__ */ jsx(Bubble, {
437
+ $[30] = sender;
438
+ $[31] = t1;
439
+ $[32] = t2;
440
+ } else t2 = $[32];
441
+ let t3;
442
+ if ($[33] !== message.text) {
443
+ t3 = /* @__PURE__ */ jsx(Bubble, {
426
444
  variant: "muted",
427
445
  className: "max-w-full",
428
446
  children: /* @__PURE__ */ jsx(BubbleContent, { children: /* @__PURE__ */ jsx(CroppedText, { text: message.text }) })
429
447
  });
430
- $[29] = message.text;
431
- $[30] = t4;
432
- } else t4 = $[30];
433
- let t5;
434
- if ($[31] !== t3 || $[32] !== t4) {
435
- t5 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsxs(MessageContent, { children: [t3, t4] }) });
436
- $[31] = t3;
437
- $[32] = t4;
438
- $[33] = t5;
439
- } else t5 = $[33];
440
- return t5;
448
+ $[33] = message.text;
449
+ $[34] = t3;
450
+ } else t3 = $[34];
451
+ let t4;
452
+ if ($[35] !== t2 || $[36] !== t3) {
453
+ t4 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsxs(MessageContent, { children: [t2, t3] }) });
454
+ $[35] = t2;
455
+ $[36] = t3;
456
+ $[37] = t4;
457
+ } else t4 = $[37];
458
+ return t4;
441
459
  }
442
460
  if (message.from === "brief") {
443
461
  let t1;
444
- if ($[34] !== message.text) {
445
- t1 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(BriefNote, { text: message.text }) }) });
446
- $[34] = message.text;
447
- $[35] = t1;
448
- } else t1 = $[35];
462
+ if ($[38] !== message.text) {
463
+ t1 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(CollapsedNote, {
464
+ label: "Camox briefed the agent",
465
+ hideLabel: "Hide the brief",
466
+ text: message.text
467
+ }) }) });
468
+ $[38] = message.text;
469
+ $[39] = t1;
470
+ } else t1 = $[39];
449
471
  return t1;
450
472
  }
451
473
  if (message.from === "camox") {
452
474
  let t1;
453
- if ($[36] === Symbol.for("react.memo_cache_sentinel")) {
475
+ if ($[40] === Symbol.for("react.memo_cache_sentinel")) {
454
476
  t1 = /* @__PURE__ */ jsx(MessageHeader, {
455
477
  className: "text-muted-foreground text-xs",
456
478
  children: "Camox"
457
479
  });
458
- $[36] = t1;
459
- } else t1 = $[36];
480
+ $[40] = t1;
481
+ } else t1 = $[40];
460
482
  let t2;
461
- if ($[37] !== message.text) {
483
+ if ($[41] !== message.text) {
462
484
  t2 = /* @__PURE__ */ jsx(Message, { children: /* @__PURE__ */ jsxs(MessageContent, { children: [t1, /* @__PURE__ */ jsx(Bubble, {
463
485
  variant: "muted",
464
486
  className: "max-w-full",
465
487
  children: /* @__PURE__ */ jsx(BubbleContent, { children: /* @__PURE__ */ jsx(CroppedText, { text: message.text }) })
466
488
  })] }) });
467
- $[37] = message.text;
468
- $[38] = t2;
469
- } else t2 = $[38];
489
+ $[41] = message.text;
490
+ $[42] = t2;
491
+ } else t2 = $[42];
470
492
  return t2;
471
493
  }
472
494
  let t1;
473
- if ($[39] !== message.sender) {
495
+ if ($[43] !== message.sender) {
474
496
  t1 = /* @__PURE__ */ jsx(MessageAvatar, { children: /* @__PURE__ */ jsx(SenderAvatar, { sender: message.sender }) });
475
- $[39] = message.sender;
476
- $[40] = t1;
477
- } else t1 = $[40];
497
+ $[43] = message.sender;
498
+ $[44] = t1;
499
+ } else t1 = $[44];
478
500
  let t2;
479
- if ($[41] !== message.text) {
501
+ if ($[45] !== message.text) {
480
502
  t2 = /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(Bubble, {
481
503
  align: "end",
482
504
  variant: "muted",
483
505
  className: "max-w-full",
484
506
  children: /* @__PURE__ */ jsx(BubbleContent, { children: /* @__PURE__ */ jsx(CroppedText, { text: message.text }) })
485
507
  }) });
486
- $[41] = message.text;
487
- $[42] = t2;
488
- } else t2 = $[42];
508
+ $[45] = message.text;
509
+ $[46] = t2;
510
+ } else t2 = $[46];
489
511
  let t3;
490
- if ($[43] !== t1 || $[44] !== t2) {
512
+ if ($[47] !== t1 || $[48] !== t2) {
491
513
  t3 = /* @__PURE__ */ jsxs(Message, {
492
514
  align: "end",
493
515
  children: [t1, t2]
494
516
  });
495
- $[43] = t1;
496
- $[44] = t2;
497
- $[45] = t3;
498
- } else t3 = $[45];
517
+ $[47] = t1;
518
+ $[48] = t2;
519
+ $[49] = t3;
520
+ } else t3 = $[49];
499
521
  return t3;
500
522
  }
501
523
  function _temp(subject, index) {
@@ -586,34 +608,37 @@ function CroppedText(t0) {
586
608
  return t9;
587
609
  }
588
610
  /**
589
- * The Brief the agent on Live handed the request off with, under the editor's messages: a quiet
590
- * line, so the request reads on as they sent it, which shows it once clicked.
611
+ * Context the agent was given beside the editors' requests, such as the Brief the agent on Live
612
+ * handed the request off with, or a Connected Agent's answers to its questions: a quiet line,
613
+ * `label`, so the requests read on as they were sent, which shows `text` once clicked.
591
614
  */
592
- function BriefNote(t0) {
593
- const $ = c(10);
594
- const { text } = t0;
615
+ function CollapsedNote(t0) {
616
+ const $ = c(11);
617
+ const { label, hideLabel, title, text } = t0;
595
618
  const [open, setOpen] = React.useState(false);
596
619
  let t1;
597
620
  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
598
621
  t1 = () => setOpen(_temp2);
599
622
  $[0] = t1;
600
623
  } else t1 = $[0];
601
- const t2 = open ? "Hide the brief" : "Camox briefed the agent";
624
+ const t2 = open ? hideLabel : label;
602
625
  let t3;
603
- if ($[1] !== open || $[2] !== t2) {
626
+ if ($[1] !== open || $[2] !== t2 || $[3] !== title) {
604
627
  t3 = /* @__PURE__ */ jsx("button", {
605
628
  type: "button",
606
629
  "aria-expanded": open,
630
+ title,
607
631
  onClick: t1,
608
632
  className: "focus-visible:ring-ring self-start rounded-sm hover:underline focus-visible:ring-2 focus-visible:outline-none",
609
633
  children: t2
610
634
  });
611
635
  $[1] = open;
612
636
  $[2] = t2;
613
- $[3] = t3;
614
- } else t3 = $[3];
637
+ $[3] = title;
638
+ $[4] = t3;
639
+ } else t3 = $[4];
615
640
  let t4;
616
- if ($[4] !== open || $[5] !== text) {
641
+ if ($[5] !== open || $[6] !== text) {
617
642
  t4 = open && /* @__PURE__ */ jsx(Bubble, {
618
643
  variant: "muted",
619
644
  className: "max-w-full",
@@ -622,21 +647,21 @@ function BriefNote(t0) {
622
647
  children: text
623
648
  }) })
624
649
  });
625
- $[4] = open;
626
- $[5] = text;
627
- $[6] = t4;
628
- } else t4 = $[6];
650
+ $[5] = open;
651
+ $[6] = text;
652
+ $[7] = t4;
653
+ } else t4 = $[7];
629
654
  let t5;
630
- if ($[7] !== t3 || $[8] !== t4) {
655
+ if ($[8] !== t3 || $[9] !== t4) {
631
656
  t5 = /* @__PURE__ */ jsxs("div", {
632
- "data-thread-brief": true,
657
+ "data-thread-collapsed": true,
633
658
  className: "text-muted-foreground flex flex-col gap-2 text-xs",
634
659
  children: [t3, t4]
635
660
  });
636
- $[7] = t3;
637
- $[8] = t4;
638
- $[9] = t5;
639
- } else t5 = $[9];
661
+ $[8] = t3;
662
+ $[9] = t4;
663
+ $[10] = t5;
664
+ } else t5 = $[10];
640
665
  return t5;
641
666
  }
642
667
  function _temp2(current) {
@@ -1,14 +1,13 @@
1
- import { localeName } from "./localeOptions.js";
2
- import { findingSentence, findingSentenceInPlace } from "@camox/api-contract/patrol";
1
+ import { fixMessage, whereSentence } from "./fixMessage.js";
2
+ import { findingSentence, findingSentenceInPlace } from "@camox/api-contract/specialists";
3
3
 
4
4
  //#region src/features/studio/findingSentence.ts
5
- /** Quoted as editors read it. */
6
- const quoted = (text) => `“${text}”`;
7
- /** What a dismissal dismissed, briefly: "Links to About". */
5
+ /** What a dismissal dismissed, briefly: "Links to About", or "No meta title". */
8
6
  function dismissedSentence(about) {
9
7
  switch (about.kind) {
10
8
  case "missingPage": return `Links to ${about.page ?? "a missing page"}`;
11
9
  case "brokenLink": return `Links to ${about.url}`;
10
+ case "missingMetaTitle": return "No meta title";
12
11
  }
13
12
  }
14
13
  /** What dismissing a finding says, as its button says it: a broken link's is "This link is fine". */
@@ -22,14 +21,17 @@ function fixLabel(fix) {
22
21
  }
23
22
  }
24
23
  /**
25
- * What "Ask the agent" fills the draft's chat with: who found what, where, and the fix it
26
- * suggests, for the agent to find among the draft's findings and fix.
24
+ * What Fix with agent sends to the chat of what the studio views: who found what, where, and the
25
+ * fix it suggests, for the agent to find among the findings it sees and fix.
27
26
  */
28
- function askAgentMessage(finding, role) {
29
- const where = `(in ${localeName(finding.locale)}, field ${quoted(finding.field)})`;
30
- const fix = finding.fix ? ` Suggested fix: ${fixLabel(finding.fix)}.` : "";
31
- return `${role} finding: ${findingSentence(finding)} ${where}.${fix}`;
27
+ function fixWithAgentMessage(finding, role) {
28
+ return fixMessage({
29
+ from: `${role} finding`,
30
+ what: findingSentence(finding),
31
+ places: [whereSentence(finding)],
32
+ fix: finding.fix ? fixLabel(finding.fix) : void 0
33
+ });
32
34
  }
33
35
 
34
36
  //#endregion
35
- export { askAgentMessage, dismissLabel, dismissedSentence, findingSentence, findingSentenceInPlace, fixLabel };
37
+ export { dismissLabel, dismissedSentence, findingSentence, findingSentenceInPlace, fixLabel, fixWithAgentMessage };
@@ -0,0 +1,23 @@
1
+ import { localeName } from "./localeOptions.js";
2
+
3
+ //#region src/features/studio/fixMessage.ts
4
+ /** Quoted as editors read it. */
5
+ const quoted = (text) => `“${text}”`;
6
+ /** Where something is in content, in a sentence: "Hero on Home, in German, field “image”". */
7
+ function whereSentence({ label, locale, field }) {
8
+ return [
9
+ label,
10
+ locale && `in ${localeName(locale)}`,
11
+ field && `field ${quoted(field)}`
12
+ ].filter(Boolean).join(", ");
13
+ }
14
+ /**
15
+ * The message: "Link checker finding: … (in French, field “body”). Suggested fix: Remove the
16
+ * link." Each of `places` is a `whereSentence`.
17
+ */
18
+ function fixMessage({ from, what, places = [], fix }) {
19
+ return `${from}: ${what}${places.length > 0 ? ` (${places.join("; ")})` : ""}.${fix ? ` Suggested fix: ${fix}.` : ""}`;
20
+ }
21
+
22
+ //#endregion
23
+ export { fixMessage, quoted, whereSentence };