@blocksdiy/react-common 1.70.2 → 1.71.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 (75) hide show
  1. package/dist/comments/anchor.d.ts +96 -0
  2. package/dist/comments/anchor.d.ts.map +1 -0
  3. package/dist/comments/anchor.js +346 -0
  4. package/dist/comments/api.d.ts +38 -0
  5. package/dist/comments/api.d.ts.map +1 -0
  6. package/dist/comments/api.js +62 -0
  7. package/dist/comments/comment-agents.d.ts +28 -0
  8. package/dist/comments/comment-agents.d.ts.map +1 -0
  9. package/dist/comments/comment-agents.js +32 -0
  10. package/dist/comments/comment-mode.d.ts +115 -0
  11. package/dist/comments/comment-mode.d.ts.map +1 -0
  12. package/dist/comments/comment-mode.js +176 -0
  13. package/dist/comments/composer.d.ts +133 -0
  14. package/dist/comments/composer.d.ts.map +1 -0
  15. package/dist/comments/composer.js +273 -0
  16. package/dist/comments/index.d.ts +19 -0
  17. package/dist/comments/index.d.ts.map +1 -0
  18. package/dist/comments/index.js +23 -0
  19. package/dist/comments/layout.d.ts +25 -0
  20. package/dist/comments/layout.d.ts.map +1 -0
  21. package/dist/comments/layout.js +83 -0
  22. package/dist/comments/mentions.d.ts +32 -0
  23. package/dist/comments/mentions.d.ts.map +1 -0
  24. package/dist/comments/mentions.js +30 -0
  25. package/dist/comments/menu.d.ts +33 -0
  26. package/dist/comments/menu.d.ts.map +1 -0
  27. package/dist/comments/menu.js +47 -0
  28. package/dist/comments/open-comment.d.ts +28 -0
  29. package/dist/comments/open-comment.d.ts.map +1 -0
  30. package/dist/comments/open-comment.js +9 -0
  31. package/dist/comments/page-pick.d.ts +76 -0
  32. package/dist/comments/page-pick.d.ts.map +1 -0
  33. package/dist/comments/page-pick.js +283 -0
  34. package/dist/comments/pick-message.d.ts +11 -0
  35. package/dist/comments/pick-message.d.ts.map +1 -0
  36. package/dist/comments/pick-message.js +33 -0
  37. package/dist/comments/pin-view.d.ts +107 -0
  38. package/dist/comments/pin-view.d.ts.map +1 -0
  39. package/dist/comments/pin-view.js +248 -0
  40. package/dist/comments/pins.d.ts +126 -0
  41. package/dist/comments/pins.d.ts.map +1 -0
  42. package/dist/comments/pins.js +218 -0
  43. package/dist/comments/text-pick.d.ts +69 -0
  44. package/dist/comments/text-pick.d.ts.map +1 -0
  45. package/dist/comments/text-pick.js +307 -0
  46. package/dist/comments/threads-store.d.ts +119 -0
  47. package/dist/comments/threads-store.d.ts.map +1 -0
  48. package/dist/comments/threads-store.js +286 -0
  49. package/dist/comments/types.d.ts +235 -0
  50. package/dist/comments/types.d.ts.map +1 -0
  51. package/dist/comments/types.js +109 -0
  52. package/dist/comments/use-comment-menu.d.ts +69 -0
  53. package/dist/comments/use-comment-menu.d.ts.map +1 -0
  54. package/dist/comments/use-comment-menu.js +140 -0
  55. package/dist/comments/use-held.d.ts +3 -0
  56. package/dist/comments/use-held.d.ts.map +1 -0
  57. package/dist/comments/use-held.js +16 -0
  58. package/dist/comments/use-thread-scroll.d.ts +23 -0
  59. package/dist/comments/use-thread-scroll.d.ts.map +1 -0
  60. package/dist/comments/use-thread-scroll.js +89 -0
  61. package/dist/hooks/agent-conversation-context.d.ts +12 -1
  62. package/dist/hooks/agent-conversation-context.d.ts.map +1 -1
  63. package/dist/hooks/agent-conversation-context.js +12 -5
  64. package/dist/hooks/agent-thread-live-update.d.ts +5 -2
  65. package/dist/hooks/agent-thread-live-update.d.ts.map +1 -1
  66. package/dist/hooks/agent-thread-live-update.js +14 -0
  67. package/dist/hooks/use-agent-conversation.d.ts +8 -0
  68. package/dist/hooks/use-agent-conversation.d.ts.map +1 -1
  69. package/dist/hooks/use-agent-conversation.js +10 -0
  70. package/dist/hooks/use-agent-threads.d.ts +1 -0
  71. package/dist/hooks/use-agent-threads.d.ts.map +1 -1
  72. package/dist/hooks/use-agent-threads.js +4 -1
  73. package/dist/iframe-communication/types.d.ts +25 -0
  74. package/dist/iframe-communication/types.d.ts.map +1 -1
  75. package/package.json +5 -2
@@ -0,0 +1,69 @@
1
+ import { type FocusEvent, type KeyboardEvent, type MouseEvent } from "react";
2
+ /**
3
+ * A comment menu's open content carries this attribute: the layer asks at a press on the page
4
+ * whether one is open, so that click only closes it.
5
+ */
6
+ export declare const COMMENT_MENU_ATTRIBUTE = "data-blocks-comment-menu";
7
+ export interface UseCommentMenuOptions {
8
+ /** Which edge of the trigger the menu lines up with: its start (a picker) or its end (a ⋯). */
9
+ align: "start" | "end";
10
+ /** The height the menu asks for, to open below its trigger or, without room there, above. */
11
+ height: number;
12
+ }
13
+ /**
14
+ * A menu button of the comments, headless (the registry draws it): the menu is fixed in the window
15
+ * beside its trigger (`menuPosition`), portalled to the comments' layer (`container`) so no
16
+ * panel's overflow clips it and no app menu stack hides it. Opening it (a click, or ↓ on the
17
+ * trigger) moves focus to its checked item, else its first, and ↑ on the trigger to its last
18
+ * (WAI-ARIA's menu button); ↓ ↑ Home End move between items (they
19
+ * take focus by keys only: give them `tabIndex={-1}`); Esc, Tab or Shift+Tab close it with focus
20
+ * back on the trigger, and Esc goes no further (not the thread, not comment mode); focus leaving
21
+ * it, the page scrolling or the window resizing closes it (it stands where its trigger was). A
22
+ * press in it keeps focus where it is, so a browser that doesn't focus buttons on click doesn't
23
+ * blur it shut before the click lands.
24
+ *
25
+ * Spread `rootProps` on an element around the trigger (events from the portalled menu reach it as
26
+ * React bubbles them), `triggerProps` on the button and `menuProps` on the menu's root.
27
+ */
28
+ export declare const useCommentMenu: ({ align, height }: UseCommentMenuOptions) => {
29
+ isOpen: boolean;
30
+ /** Closes it with focus back on its trigger, as a pick does (WAI-ARIA's menu button). */
31
+ close: () => void;
32
+ /** Where to portal the menu while it is open: the comments' layer the trigger is in, else the body. */
33
+ container: Element | null;
34
+ rootProps: {
35
+ ref: import("react").RefObject<HTMLDivElement | null>;
36
+ onBlur: (event: FocusEvent<HTMLElement>) => void;
37
+ onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
38
+ };
39
+ triggerProps: {
40
+ ref: import("react").RefObject<HTMLButtonElement | null>;
41
+ id: string;
42
+ "aria-haspopup": "menu";
43
+ "aria-expanded": boolean;
44
+ "aria-controls": string | undefined;
45
+ "data-state": "open" | "closed";
46
+ onClick: () => void;
47
+ onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
48
+ };
49
+ menuProps: {
50
+ ref: import("react").RefObject<HTMLDivElement | null>;
51
+ id: string;
52
+ role: "menu";
53
+ "aria-labelledby": string;
54
+ "data-blocks-comment-menu": string;
55
+ "data-state": "open";
56
+ "data-side": "top" | "bottom" | undefined;
57
+ style: {
58
+ top?: number | undefined;
59
+ bottom?: number | undefined;
60
+ left?: number | undefined;
61
+ right?: number | undefined;
62
+ maxHeight?: number | undefined;
63
+ };
64
+ onMouseDown: (event: MouseEvent<HTMLElement>) => void;
65
+ onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
66
+ };
67
+ };
68
+ export type CommentMenuState = ReturnType<typeof useCommentMenu>;
69
+ //# sourceMappingURL=use-comment-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-comment-menu.d.ts","sourceRoot":"","sources":["../../src/comments/use-comment-menu.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,UAAU,EAMhB,MAAM,OAAO,CAAC;AAMf;;;GAGG;AACH,eAAO,MAAM,sBAAsB,6BAA6B,CAAC;AAMjE,MAAM,WAAW,qBAAqB;IACpC,+FAA+F;IAC/F,KAAK,EAAE,OAAO,GAAG,KAAK,CAAC;IACvB,6FAA6F;IAC7F,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,cAAc,GAAI,mBAAmB,qBAAqB;;IAsEnE,yFAAyF;;IAEzF,uGAAuG;;;;wBAIrF,UAAU,CAAC,WAAW,CAAC;2BAKpB,aAAa,CAAC,WAAW,CAAC;;;;;;;;;;2BAgB1B,aAAa,CAAC,WAAW,CAAC;;;;;;;;;;;;;;;;;6BAgBxB,UAAU,CAAC,WAAW,CAAC;2BACzB,aAAa,CAAC,WAAW,CAAC;;CAUlD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC"}
@@ -0,0 +1,140 @@
1
+ import { useCallback, useEffect, useId, useRef, useState, } from "react";
2
+ import { toRect } from "./layout.js";
3
+ import { menuKeyTarget, menuPosition } from "./menu.js";
4
+ import { COMMENTS_LAYER_ATTRIBUTE } from "./pins.js";
5
+ /**
6
+ * A comment menu's open content carries this attribute: the layer asks at a press on the page
7
+ * whether one is open, so that click only closes it.
8
+ */
9
+ export const COMMENT_MENU_ATTRIBUTE = "data-blocks-comment-menu";
10
+ const ITEM_SELECTOR = '[role="menuitem"], [role="menuitemradio"], [role="menuitemcheckbox"]';
11
+ const itemsIn = (menu) => Array.from(menu?.querySelectorAll(ITEM_SELECTOR) ?? []);
12
+ /**
13
+ * A menu button of the comments, headless (the registry draws it): the menu is fixed in the window
14
+ * beside its trigger (`menuPosition`), portalled to the comments' layer (`container`) so no
15
+ * panel's overflow clips it and no app menu stack hides it. Opening it (a click, or ↓ on the
16
+ * trigger) moves focus to its checked item, else its first, and ↑ on the trigger to its last
17
+ * (WAI-ARIA's menu button); ↓ ↑ Home End move between items (they
18
+ * take focus by keys only: give them `tabIndex={-1}`); Esc, Tab or Shift+Tab close it with focus
19
+ * back on the trigger, and Esc goes no further (not the thread, not comment mode); focus leaving
20
+ * it, the page scrolling or the window resizing closes it (it stands where its trigger was). A
21
+ * press in it keeps focus where it is, so a browser that doesn't focus buttons on click doesn't
22
+ * blur it shut before the click lands.
23
+ *
24
+ * Spread `rootProps` on an element around the trigger (events from the portalled menu reach it as
25
+ * React bubbles them), `triggerProps` on the button and `menuProps` on the menu's root.
26
+ */
27
+ export const useCommentMenu = ({ align, height }) => {
28
+ // Where it stands and where it is portalled, both read from the trigger as it opens.
29
+ const [opened, setOpened] = useState(null);
30
+ const position = opened?.position ?? null;
31
+ const isOpen = opened !== null;
32
+ const rootRef = useRef(null);
33
+ const triggerRef = useRef(null);
34
+ const menuRef = useRef(null);
35
+ const triggerId = useId();
36
+ const menuId = useId();
37
+ const open = (focus = "checked") => {
38
+ const trigger = triggerRef.current;
39
+ if (!trigger) {
40
+ return;
41
+ }
42
+ setOpened({
43
+ position: menuPosition(toRect(trigger.getBoundingClientRect()), {
44
+ height,
45
+ align,
46
+ isRtl: getComputedStyle(trigger).direction === "rtl",
47
+ viewportWidth: document.documentElement.clientWidth,
48
+ viewportHeight: window.innerHeight,
49
+ }),
50
+ // The comments' layer the trigger is in, else the body.
51
+ container: trigger.closest(`[${COMMENTS_LAYER_ATTRIBUTE}]`) ?? document.body,
52
+ focus,
53
+ });
54
+ };
55
+ const close = useCallback(() => setOpened(null), []);
56
+ const closeToTrigger = () => {
57
+ close();
58
+ triggerRef.current?.focus();
59
+ };
60
+ const focusFrom = opened?.focus;
61
+ useEffect(() => {
62
+ if (!focusFrom) {
63
+ return;
64
+ }
65
+ const all = itemsIn(menuRef.current);
66
+ (focusFrom === "last"
67
+ ? all.at(-1)
68
+ : (all.find((item) => item.getAttribute("aria-checked") === "true") ?? all[0]))?.focus();
69
+ // A scroll inside its own list doesn't move it.
70
+ const onScroll = (event) => {
71
+ if (!menuRef.current?.contains(event.target)) {
72
+ close();
73
+ }
74
+ };
75
+ window.addEventListener("scroll", onScroll, true);
76
+ window.addEventListener("resize", close);
77
+ return () => {
78
+ window.removeEventListener("scroll", onScroll, true);
79
+ window.removeEventListener("resize", close);
80
+ };
81
+ }, [focusFrom, close]);
82
+ const isInside = (node) => !!node && (!!rootRef.current?.contains(node) || !!menuRef.current?.contains(node));
83
+ const { side, ...style } = position ?? {};
84
+ return {
85
+ isOpen,
86
+ /** Closes it with focus back on its trigger, as a pick does (WAI-ARIA's menu button). */
87
+ close: closeToTrigger,
88
+ /** Where to portal the menu while it is open: the comments' layer the trigger is in, else the body. */
89
+ container: opened?.container ?? null,
90
+ rootProps: {
91
+ ref: rootRef,
92
+ onBlur: (event) => {
93
+ if (!isInside(event.relatedTarget)) {
94
+ close();
95
+ }
96
+ },
97
+ onKeyDown: (event) => {
98
+ if (isOpen && (event.key === "Escape" || event.key === "Tab")) {
99
+ event.preventDefault();
100
+ event.stopPropagation();
101
+ closeToTrigger();
102
+ }
103
+ },
104
+ },
105
+ triggerProps: {
106
+ ref: triggerRef,
107
+ id: triggerId,
108
+ "aria-haspopup": "menu",
109
+ "aria-expanded": isOpen,
110
+ "aria-controls": isOpen ? menuId : undefined,
111
+ "data-state": isOpen ? "open" : "closed",
112
+ onClick: () => (isOpen ? close() : open()),
113
+ onKeyDown: (event) => {
114
+ if (!isOpen && (event.key === "ArrowDown" || event.key === "ArrowUp")) {
115
+ event.preventDefault();
116
+ open(event.key === "ArrowUp" ? "last" : "checked");
117
+ }
118
+ },
119
+ },
120
+ menuProps: {
121
+ ref: menuRef,
122
+ id: menuId,
123
+ role: "menu",
124
+ "aria-labelledby": triggerId,
125
+ [COMMENT_MENU_ATTRIBUTE]: "",
126
+ "data-state": "open",
127
+ "data-side": side,
128
+ style,
129
+ onMouseDown: (event) => event.preventDefault(),
130
+ onKeyDown: (event) => {
131
+ const all = itemsIn(menuRef.current);
132
+ const next = menuKeyTarget(event.key, all.indexOf(document.activeElement), all.length);
133
+ if (next !== null) {
134
+ event.preventDefault();
135
+ all[next]?.focus();
136
+ }
137
+ },
138
+ },
139
+ };
140
+ };
@@ -0,0 +1,3 @@
1
+ /** True once `isOn` has held for `ms` under the same `key`; false again the moment it doesn't. */
2
+ export declare const useHeld: (isOn: boolean, ms: number, key: unknown) => boolean;
3
+ //# sourceMappingURL=use-held.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-held.d.ts","sourceRoot":"","sources":["../../src/comments/use-held.ts"],"names":[],"mappings":"AAEA,kGAAkG;AAClG,eAAO,MAAM,OAAO,GAAI,MAAM,OAAO,EAAE,IAAI,MAAM,EAAE,KAAK,OAAO,KAAG,OAajE,CAAC"}
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ /** True once `isOn` has held for `ms` under the same `key`; false again the moment it doesn't. */
3
+ export const useHeld = (isOn, ms, key) => {
4
+ const [heldKey, setHeldKey] = React.useState(null);
5
+ React.useEffect(() => {
6
+ if (!isOn) {
7
+ return;
8
+ }
9
+ const timer = window.setTimeout(() => setHeldKey(key), ms);
10
+ return () => {
11
+ window.clearTimeout(timer);
12
+ setHeldKey(null);
13
+ };
14
+ }, [isOn, ms, key]);
15
+ return isOn && heldKey === key;
16
+ };
@@ -0,0 +1,23 @@
1
+ import * as React from "react";
2
+ /**
3
+ * The comments' scroll area. It opens at the newest; when comments come in or change (a new
4
+ * reply, an agent's progress line, its answer) it scrolls down to them — smoothly, at once under
5
+ * reduced motion — if the reader was at or near the bottom, and leaves them where they are if they
6
+ * scrolled up to read. Sending a comment of one's own always goes down to it. `overflow` says
7
+ * which edges have more to scroll, for the fades.
8
+ */
9
+ export declare function useThreadScroll({ contentKey, newestId, isNewestMine, }: {
10
+ /** Changes whenever what the comments show changes: their ids, bodies and states. */
11
+ contentKey: string;
12
+ newestId: number | undefined;
13
+ isNewestMine: boolean;
14
+ }): {
15
+ scrollRef: React.RefObject<HTMLDivElement | null>;
16
+ contentRef: React.RefObject<HTMLDivElement | null>;
17
+ overflow: {
18
+ top: boolean;
19
+ bottom: boolean;
20
+ };
21
+ onScroll: () => void;
22
+ };
23
+ //# sourceMappingURL=use-thread-scroll.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-thread-scroll.d.ts","sourceRoot":"","sources":["../../src/comments/use-thread-scroll.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAC9B,UAAU,EACV,QAAQ,EACR,YAAY,GACb,EAAE;IACD,qFAAqF;IACrF,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,YAAY,EAAE,OAAO,CAAC;CACvB;;;;;;;;EAiFA"}
@@ -0,0 +1,89 @@
1
+ import * as React from "react";
2
+ /** How near the bottom (px) counts as reading the newest: the thread follows new comments then. */
3
+ const STICK_TO_BOTTOM_PX = 48;
4
+ const prefersReducedMotion = () => typeof window !== "undefined" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
5
+ /**
6
+ * The comments' scroll area. It opens at the newest; when comments come in or change (a new
7
+ * reply, an agent's progress line, its answer) it scrolls down to them — smoothly, at once under
8
+ * reduced motion — if the reader was at or near the bottom, and leaves them where they are if they
9
+ * scrolled up to read. Sending a comment of one's own always goes down to it. `overflow` says
10
+ * which edges have more to scroll, for the fades.
11
+ */
12
+ export function useThreadScroll({ contentKey, newestId, isNewestMine, }) {
13
+ const scrollRef = React.useRef(null);
14
+ const contentRef = React.useRef(null);
15
+ // Whether the reader is at the bottom, kept as they scroll — before the content changes, when
16
+ // the distance would already count the new comment. Only scrolling up lets go of it, so the
17
+ // area's own smooth scroll down never does.
18
+ const isStuckRef = React.useRef(true);
19
+ const lastTopRef = React.useRef(0);
20
+ const lastHeightRef = React.useRef(0);
21
+ const newestIdRef = React.useRef(newestId);
22
+ const hasOpenedRef = React.useRef(false);
23
+ const [overflow, setOverflow] = React.useState({ top: false, bottom: false });
24
+ const measure = React.useCallback(() => {
25
+ const element = scrollRef.current;
26
+ if (!element) {
27
+ return;
28
+ }
29
+ const top = element.scrollTop > 1;
30
+ const bottom = element.scrollHeight - element.scrollTop - element.clientHeight > 1;
31
+ setOverflow((current) => (current.top === top && current.bottom === bottom ? current : { top, bottom }));
32
+ }, []);
33
+ const onScroll = React.useCallback(() => {
34
+ const element = scrollRef.current;
35
+ if (!element) {
36
+ return;
37
+ }
38
+ const distance = element.scrollHeight - element.scrollTop - element.clientHeight;
39
+ if (distance <= STICK_TO_BOTTOM_PX) {
40
+ isStuckRef.current = true;
41
+ }
42
+ else if (element.scrollTop < lastTopRef.current) {
43
+ isStuckRef.current = false;
44
+ }
45
+ lastTopRef.current = element.scrollTop;
46
+ measure();
47
+ }, [measure]);
48
+ React.useLayoutEffect(() => {
49
+ const element = scrollRef.current;
50
+ if (!element || !contentKey) {
51
+ return;
52
+ }
53
+ if (newestId !== newestIdRef.current && isNewestMine) {
54
+ isStuckRef.current = true;
55
+ }
56
+ newestIdRef.current = newestId;
57
+ if (isStuckRef.current) {
58
+ const isOpening = !hasOpenedRef.current;
59
+ element.scrollTo({
60
+ top: element.scrollHeight,
61
+ behavior: isOpening || prefersReducedMotion() ? "auto" : "smooth",
62
+ });
63
+ }
64
+ hasOpenedRef.current = true;
65
+ measure();
66
+ }, [contentKey, newestId, isNewestMine, measure]);
67
+ // The area resizing (the panel, the composer growing a line) keeps a reader at the bottom there,
68
+ // and the fades follow the area and its content.
69
+ React.useEffect(() => {
70
+ const element = scrollRef.current;
71
+ if (!element || typeof ResizeObserver === "undefined") {
72
+ return;
73
+ }
74
+ lastHeightRef.current = element.clientHeight;
75
+ const observer = new ResizeObserver(() => {
76
+ if (element.clientHeight !== lastHeightRef.current && isStuckRef.current) {
77
+ element.scrollTop = element.scrollHeight;
78
+ }
79
+ lastHeightRef.current = element.clientHeight;
80
+ measure();
81
+ });
82
+ observer.observe(element);
83
+ if (contentRef.current) {
84
+ observer.observe(contentRef.current);
85
+ }
86
+ return () => observer.disconnect();
87
+ }, [measure]);
88
+ return { scrollRef, contentRef, overflow, onScroll };
89
+ }
@@ -10,9 +10,20 @@ export interface AgentConversationContextValue {
10
10
  isDraft: boolean;
11
11
  /** The index under `filters`; its `renameThread` also keeps the open conversation's remembered title current. */
12
12
  threads: UseAgentThreadsResult;
13
- /** The open conversation's row: listed, else the last listed, else a stand-in (`isStandIn`). */
13
+ /**
14
+ * The open conversation's row: listed, else the last listed, else a stand-in (`isStandIn`), which
15
+ * shows the conversation's own title and status once they are read (`shownConversationRow`).
16
+ */
14
17
  row: AgentThreadItem;
15
18
  isStandIn: boolean;
19
+ /**
20
+ * The open conversation's own read is done and the server has no row for it that this reader
21
+ * may see (a 404): someone else's comment conversation the reader can't see, or — briefly — a
22
+ * conversation just started whose row hasn't landed. A host tells the two apart (react-common's
23
+ * `parseCommentAgentChatThreadId`) before saying the conversation isn't available. False for a
24
+ * draft and while the read is in flight.
25
+ */
26
+ isConversationMissing: boolean;
16
27
  filters: AgentThreadFilters;
17
28
  setFilters: (filters: AgentThreadFilters) => void;
18
29
  hasActiveFilters: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-conversation-context.d.ts","sourceRoot":"","sources":["../../src/hooks/agent-conversation-context.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAiB,KAAK,SAAS,EAAwB,MAAM,OAAO,CAAC;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAEzB,KAAK,0BAA0B,EAChC,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAmB,KAAK,sBAAsB,EAAE,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE/G,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,sBAAsB,EAAE,QAAQ,GAAG,QAAQ,CAAC,CAAC;AAEnF,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,oBAAoB,CAAC;IACnC,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,iHAAiH;IACjH,OAAO,EAAE,qBAAqB,CAAC;IAC/B,gGAAgG;IAChG,GAAG,EAAE,eAAe,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,UAAU,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,uFAAuF;IACvF,iBAAiB,EAAE,0BAA0B,CAAC,mBAAmB,CAAC,CAAC;CACpE;AAID,MAAM,WAAW,8BAA+B,SAAQ,IAAI,CAC1D,sBAAsB,EACtB,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CACvD;IACC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,oBAAoB,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,IAAI,EAAE,qBAAqB,CAAC;IAC5B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,OAAO,EACP,YAAY,EACZ,OAAO,EACP,IAAI,EACJ,KAAK,EACL,OAAO,EACP,OAAO,EACP,OAAO,EAAE,WAAW,EACpB,MAAM,EACN,QAAQ,GACT,EAAE,8BAA8B,+BAyBhC;AAED,MAAM,MAAM,oCAAoC,GAAG,8BAA8B,CAAC;AAKlF;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAAC,EAC9C,OAAO,EACP,YAAY,EACZ,OAAO,EACP,IAAI,EACJ,KAAK,EACL,OAAO,EACP,OAAO,EACP,QAAQ,GACT,EAAE,oCAAoC,+BAetC;AA2CD,eAAO,MAAM,2BAA2B,QAAO,6BAQ9C,CAAC"}
1
+ {"version":3,"file":"agent-conversation-context.d.ts","sourceRoot":"","sources":["../../src/hooks/agent-conversation-context.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAiB,KAAK,SAAS,EAAwB,MAAM,OAAO,CAAC;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAGzB,KAAK,0BAA0B,EAChC,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAmB,KAAK,sBAAsB,EAAE,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE/G,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,sBAAsB,EAAE,QAAQ,GAAG,QAAQ,CAAC,CAAC;AAMnF,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,oBAAoB,CAAC;IACnC,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,iHAAiH;IACjH,OAAO,EAAE,qBAAqB,CAAC;IAC/B;;;OAGG;IACH,GAAG,EAAE,eAAe,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,qBAAqB,EAAE,OAAO,CAAC;IAC/B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,UAAU,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClD,gBAAgB,EAAE,OAAO,CAAC;IAC1B,uFAAuF;IACvF,iBAAiB,EAAE,0BAA0B,CAAC,mBAAmB,CAAC,CAAC;CACpE;AAID,MAAM,WAAW,8BAA+B,SAAQ,IAAI,CAC1D,sBAAsB,EACtB,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CACvD;IACC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,oBAAoB,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,IAAI,EAAE,qBAAqB,CAAC;IAC5B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,OAAO,EACP,YAAY,EACZ,OAAO,EACP,IAAI,EACJ,KAAK,EACL,OAAO,EACP,OAAO,EACP,OAAO,EAAE,WAAW,EACpB,MAAM,EACN,QAAQ,GACT,EAAE,8BAA8B,+BA+BhC;AAED,MAAM,MAAM,oCAAoC,GAAG,8BAA8B,CAAC;AAKlF;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAAC,EAC9C,OAAO,EACP,YAAY,EACZ,OAAO,EACP,IAAI,EACJ,KAAK,EACL,OAAO,EACP,OAAO,EACP,QAAQ,GACT,EAAE,oCAAoC,+BAgBtC;AAiDD,eAAO,MAAM,2BAA2B,QAAO,6BAQ9C,CAAC"}
@@ -4,9 +4,11 @@ import { jsx as _jsx } from "react/jsx-runtime";
4
4
  // chat (useAgentConversation), for parts to read through useAgentConversationContext. The
5
5
  // agent-layout registry item renders it; a custom UI over the same behaviour can too.
6
6
  import { createContext, useContext, useState } from "react";
7
- import { useAgentConversation, } from "./use-agent-conversation.js";
7
+ import { shownConversationRow, useAgentConversation, } from "./use-agent-conversation.js";
8
8
  import { useAgentThread } from "./use-agent-thread.js";
9
9
  import { useAgentThreads } from "./use-agent-threads.js";
10
+ /** A single-conversation read that finished with no row (a 404): see `isConversationMissing`. */
11
+ const isReadMissing = (read, isDraft) => !isDraft && !read.isLoading && read.error === null && read.threads.length === 0;
10
12
  const AgentConversationContext = createContext(null);
11
13
  /**
12
14
  * The Root over the agent's whole index: the sidebar's list under its filters, and the open
@@ -24,7 +26,11 @@ export function AgentConversationProvider({ agentId, conversation, isDraft, chat
24
26
  headers,
25
27
  baseUrl,
26
28
  });
27
- return (_jsx(AgentConversationRoot, { agentId: agentId, conversation: conversation, isDraft: isDraft, chat: chat, threads: threads, filters: filters, setFilters: setFilters, children: children }));
29
+ // The open conversation read on its own, for when the index doesn't list it (someone else's
30
+ // comment conversation, for a person who neither builds nor manages the app): its header shows
31
+ // its title. Free when the index lists it, and a draft reads nothing.
32
+ const read = useAgentThread({ agentId, conversation, isDraft, token, headers, baseUrl });
33
+ return (_jsx(AgentConversationRoot, { agentId: agentId, conversation: conversation, isDraft: isDraft, chat: chat, threads: threads, filters: filters, setFilters: setFilters, read: read.threads[0], isConversationMissing: isReadMissing(read, isDraft), children: children }));
28
34
  }
29
35
  const NO_FILTERS = {};
30
36
  const noFilters = () => undefined;
@@ -37,9 +43,9 @@ const noFilters = () => undefined;
37
43
  */
38
44
  export function AgentThreadConversationProvider({ agentId, conversation, isDraft, chat, token, headers, baseUrl, children, }) {
39
45
  const threads = useAgentThread({ agentId, conversation, isDraft, token, headers, baseUrl });
40
- return (_jsx(AgentConversationRoot, { agentId: agentId, conversation: conversation, isDraft: isDraft, chat: chat, threads: threads, filters: NO_FILTERS, setFilters: noFilters, children: children }));
46
+ return (_jsx(AgentConversationRoot, { agentId: agentId, conversation: conversation, isDraft: isDraft, chat: chat, threads: threads, filters: NO_FILTERS, setFilters: noFilters, isConversationMissing: isReadMissing(threads, isDraft), children: children }));
41
47
  }
42
- function AgentConversationRoot({ agentId, conversation, isDraft, chat, threads, filters, setFilters, children, }) {
48
+ function AgentConversationRoot({ agentId, conversation, isDraft, chat, threads, filters, setFilters, read, isConversationMissing, children, }) {
43
49
  const { row, isStandIn, renameThread, notifyMessageSent } = useAgentConversation({
44
50
  threads,
45
51
  agentId,
@@ -52,8 +58,9 @@ function AgentConversationRoot({ agentId, conversation, isDraft, chat, threads,
52
58
  conversation,
53
59
  isDraft,
54
60
  threads: { ...threads, renameThread },
55
- row,
61
+ row: shownConversationRow(row, isStandIn, read),
56
62
  isStandIn,
63
+ isConversationMissing,
57
64
  filters,
58
65
  setFilters,
59
66
  hasActiveFilters: Boolean(filters.status ?? filters.source),
@@ -1,6 +1,6 @@
1
1
  declare const THREAD_STATUSES: readonly ["idle", "interrupted", "waiting_on_agent", "busy", "error"];
2
2
  export type AgentThreadStatus = (typeof THREAD_STATUSES)[number];
3
- declare const THREAD_SOURCES: readonly ["direct_chat", "send_message", "feedback", "self_config_resume", "scheduled_reminder", "unknown"];
3
+ declare const THREAD_SOURCES: readonly ["direct_chat", "send_message", "feedback", "self_config_resume", "scheduled_reminder", "comment", "unknown"];
4
4
  export type AgentThreadSource = (typeof THREAD_SOURCES)[number] | "agent_call";
5
5
  export interface AgentThreadItem {
6
6
  agentId: string | null;
@@ -42,7 +42,10 @@ export interface AgentThreadLiveUpdateOptions {
42
42
  * Without `userId` a live update only refreshes rows already listed; it never adds one.
43
43
  */
44
44
  private?: boolean;
45
- /** The signed-in user's id, for `private`. */
45
+ /**
46
+ * The signed-in user's id: for `private`, and to tell whose a comment conversation is — a live
47
+ * update adds one only when this user asked (see `applyAgentThreadUpdate`).
48
+ */
46
49
  userId?: string;
47
50
  sort?: "lastActivity" | "firstSeen";
48
51
  order?: "asc" | "desc";
@@ -1 +1 @@
1
- {"version":3,"file":"agent-thread-live-update.d.ts","sourceRoot":"","sources":["../../src/hooks/agent-thread-live-update.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-thread-live-update.d.ts","sourceRoot":"","sources":["../../src/hooks/agent-thread-live-update.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  // Wire types and pure merge logic for the agent-threads index; dependency-free for tests.
2
+ import { parseCommentAgentChatThreadId } from "../comments/types.js";
2
3
  const THREAD_STATUSES = ["idle", "interrupted", "waiting_on_agent", "busy", "error"];
3
4
  const THREAD_SOURCES = [
4
5
  "direct_chat",
@@ -7,6 +8,8 @@ const THREAD_SOURCES = [
7
8
  "self_config_resume",
8
9
  // A thread a fired reminder or schedule started (wf-actions-py scheduled_reminder_runner.py).
9
10
  "scheduled_reminder",
11
+ // A conversation a comment's @mention started (wf-actions-py agent_comment_mention_runner.py).
12
+ "comment",
10
13
  "unknown",
11
14
  ];
12
15
  /** A thread's identity within its agent: the thread id alone. */
@@ -75,6 +78,10 @@ const sortTime = (item, sort) => {
75
78
  export const matchesAgentThreadFilters = (item, options = {}) => (!options.status || item.status === options.status) &&
76
79
  (!options.source || item.source === options.source) &&
77
80
  (!options.private || options.userId === undefined || item.userId == null || item.userId === options.userId);
81
+ const isOwnOrNotCommentConversation = (item, userId) => {
82
+ const comment = parseCommentAgentChatThreadId(item.chatThreadId);
83
+ return comment === null || (userId !== undefined && String(comment.askerUserId) === userId);
84
+ };
78
85
  export const applyAgentThreadUpdate = (threads, incoming, options = {}) => {
79
86
  const key = agentThreadKey(incoming);
80
87
  const existing = threads.find((thread) => agentThreadKey(thread) === key);
@@ -89,6 +96,12 @@ export const applyAgentThreadUpdate = (threads, incoming, options = {}) => {
89
96
  if (!existing && options.private && (options.userId === undefined || incoming.userId == null)) {
90
97
  return threads;
91
98
  }
99
+ // Every member who may read a comment conversation hears its events, but the server lists
100
+ // someone else's only for the app's builders and managers — and their list already holds it.
101
+ // So a live update adds a comment conversation only when the signed-in user asked.
102
+ if (!existing && !isOwnOrNotCommentConversation(incoming, options.userId)) {
103
+ return threads;
104
+ }
92
105
  const sort = options.sort ?? "lastActivity";
93
106
  const direction = options.order === "asc" ? 1 : -1;
94
107
  const next = existing ? threads.map((thread) => (thread === existing ? incoming : thread)) : [...threads, incoming];
@@ -143,6 +156,7 @@ const GROUP_OF_SOURCE = {
143
156
  direct_chat: "chats",
144
157
  self_config_resume: "chats",
145
158
  scheduled_reminder: "chats",
159
+ comment: "chats",
146
160
  unknown: "chats",
147
161
  send_message: "workflows",
148
162
  feedback: "feedback",
@@ -45,6 +45,14 @@ export declare const useAgentConversationSelection: ({ urlTarget, }: UseAgentCon
45
45
  export declare const RUN_STALE_MS: number;
46
46
  /** A row for a conversation the index lists nothing for (yet): the draft, or a thread whose row has not landed. */
47
47
  export declare const agentThreadStandIn: (agentId: string, conversation: AgentConversationRef, isDraft: boolean) => AgentThreadItem;
48
+ /**
49
+ * The open conversation's row as a surface shows it: `row` as it is, unless it is a stand-in and
50
+ * the conversation's own read (`read`, the server's row for it) is in, whose title and status it
51
+ * then shows. For a conversation the index doesn't list: someone else's comment conversation, which
52
+ * the index leaves out for a person who neither builds nor manages the app. Only what it shows: the
53
+ * row stays a stand-in for the rest (no rename, no turn accounting).
54
+ */
55
+ export declare const shownConversationRow: (row: AgentThreadItem, isStandIn: boolean, read: AgentThreadItem | undefined) => AgentThreadItem;
48
56
  /** When the oldest run mark among `rows` reaches the stale ceiling (epoch ms); null with no mark. */
49
57
  export declare const nextRunStaleAt: (rows: readonly AgentThreadItem[]) => number | null;
50
58
  /** The turns this client has accounted for on one conversation (`key`: agentThreadKey). */
@@ -1 +1 @@
1
- {"version":3,"file":"use-agent-conversation.d.ts","sourceRoot":"","sources":["../../src/hooks/use-agent-conversation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-agent-conversation.d.ts","sourceRoot":"","sources":["../../src/hooks/use-agent-conversation.ts"],"names":[],"mappings":"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"}
@@ -71,6 +71,16 @@ export const agentThreadStandIn = (agentId, conversation, isDraft) => {
71
71
  lastActivityAt: now,
72
72
  };
73
73
  };
74
+ /**
75
+ * The open conversation's row as a surface shows it: `row` as it is, unless it is a stand-in and
76
+ * the conversation's own read (`read`, the server's row for it) is in, whose title and status it
77
+ * then shows. For a conversation the index doesn't list: someone else's comment conversation, which
78
+ * the index leaves out for a person who neither builds nor manages the app. Only what it shows: the
79
+ * row stays a stand-in for the rest (no rename, no turn accounting).
80
+ */
81
+ export const shownConversationRow = (row, isStandIn, read) => isStandIn && read && agentThreadKey(read) === agentThreadKey(row)
82
+ ? { ...row, title: read.title, status: read.status }
83
+ : row;
74
84
  /** When the oldest run mark among `rows` reaches the stale ceiling (epoch ms); null with no mark. */
75
85
  export const nextRunStaleAt = (rows) => {
76
86
  let next = null;
@@ -79,6 +79,7 @@ export interface UseAgentThreadsResult {
79
79
  */
80
80
  export declare const agentInboxChatId: (agentId: string) => string;
81
81
  export declare const agentThreadShortLabel: (thread: Pick<AgentThreadItem, "chatThreadId">) => string;
82
+ /** An untitled comment conversation reads "Comment": its id starts with a word, not a short code. */
82
83
  export declare const agentThreadDisplayTitle: (thread: Pick<AgentThreadItem, "chatThreadId" | "title">) => string;
83
84
  /** Agent-threads index with pagination, realtime upserts, and optimistic send listing. */
84
85
  export declare const useAgentThreads: (options: UseAgentThreadsOptions) => UseAgentThreadsResult;
@@ -1 +1 @@
1
- {"version":3,"file":"use-agent-threads.d.ts","sourceRoot":"","sources":["../../src/hooks/use-agent-threads.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EASvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAA2B,KAAK,gBAAgB,EAA8B,MAAM,sBAAsB,CAAC;AAElH,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,4BAA4B,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAClG,OAAO,EAAE,KAAK,gBAAgB,EAAE,gBAAgB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAClH,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,EAC/B,kBAAkB,EAClB,cAAc,EACd,YAAY,EACZ,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,6BAA6B,EAC7B,KAAK,oCAAoC,EACzC,KAAK,mCAAmC,GACzC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,KAAK,6BAA6B,EAClC,yBAAyB,EACzB,KAAK,8BAA8B,EACnC,+BAA+B,EAC/B,KAAK,oCAAoC,EACzC,KAAK,kBAAkB,EACvB,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC3G,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EACL,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,+BAA+B,EAC/B,0BAA0B,EAC1B,wBAAwB,EACxB,8BAA8B,EAC9B,KAAK,oCAAoC,GAC1C,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EAChC,2BAA2B,EAC3B,KAAK,kCAAkC,EACvC,0BAA0B,EAC1B,KAAK,gCAAgC,GACtC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,uBAAuB,EACvB,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,KAAK,6BAA6B,EAClC,KAAK,uBAAuB,EAC5B,KAAK,8BAA8B,EACnC,gCAAgC,EAChC,KAAK,uCAAuC,EAC5C,KAAK,sCAAsC,GAC5C,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,8BAA8B,EAC9B,oCAAoC,GACrC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,SAAS,EACd,oBAAoB,EACpB,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAC;AAE/B,uFAAuF;AACvF,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,mHAAmH;AACnH,qBAAa,wBAAyB,SAAQ,KAAK;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM;CAIpC;AAED,sGAAsG;AACtG,eAAO,MAAM,qBAAqB,GAAU,CAAC,EAC3C,SAAS,MAAM,GAAG,SAAS,EAC3B,MAAM,gBAAgB,EACtB,MAAM,MAAM,EACZ,OAAO,WAAW,KACjB,OAAO,CAAC,CAAC,CAaX,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,8BAItC,gBAAgB,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,CAShG,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,EAAE,cAAc,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,KAAG,MAGjG,CAAC;AAEP;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAChC,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EAC9D,SAAS,MAAM,EACf,QAAQ,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,EAC7C,OAAO,MAAM,EACb,QAAQ,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,OAAO,CAAC,KACjD,OAAO,CAAC,IAAI,CAiBd,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,cAAc,GAAG,WAAW,CAAC;IACpC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,oBAAoB,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzE,YAAY,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9F,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,MAAM,KAAG,MAAkC,CAAC;AAEtF,eAAO,MAAM,qBAAqB,GAAI,QAAQ,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,KAAG,MACrD,CAAC;AAElC,eAAO,MAAM,uBAAuB,GAAI,QAAQ,IAAI,CAAC,eAAe,EAAE,cAAc,GAAG,OAAO,CAAC,KAAG,MACzC,CAAC;AAuC1D,0FAA0F;AAC1F,eAAO,MAAM,eAAe,GAAI,SAAS,sBAAsB,KAAG,qBA+SjE,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"use-agent-threads.d.ts","sourceRoot":"","sources":["../../src/hooks/use-agent-threads.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { getApiHost } from "@blocksdiy/blocks-client-api/envService";
2
2
  import { websocketsService } from "@blocksdiy/blocks-client-api/websocketService";
3
3
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
+ import { parseCommentAgentChatThreadId } from "../comments/types.js";
4
5
  import { agentThreadKey, applyAgentThreadUpdate, matchesAgentThreadFilters, optimisticThreadAfterSend, overlayOptimisticThreads, reconcileWalkWithLive, removeAgentThread, retireOptimisticThreadsTakenOver, } from "./agent-thread-live-update.js";
5
6
  import { acquireAgentThreadStore } from "./agent-thread-store.js";
6
7
  export * from "./agent-thread-live-update.js";
@@ -84,7 +85,9 @@ export const postAgentThreadRename = async (fetchJson, agentId, thread, title, s
84
85
  */
85
86
  export const agentInboxChatId = (agentId) => `agent-inbox-${agentId}`;
86
87
  export const agentThreadShortLabel = (thread) => thread.chatThreadId.slice(0, 8);
87
- export const agentThreadDisplayTitle = (thread) => thread.title ?? `Chat ${agentThreadShortLabel(thread)}`;
88
+ /** An untitled comment conversation reads "Comment": its id starts with a word, not a short code. */
89
+ export const agentThreadDisplayTitle = (thread) => thread.title ??
90
+ (parseCommentAgentChatThreadId(thread.chatThreadId) ? "Comment" : `Chat ${agentThreadShortLabel(thread)}`);
88
91
  const buildQuery = (filters, cursor) => {
89
92
  const params = new URLSearchParams();
90
93
  if (filters.status) {