@tangle-network/agent-app 0.46.3 → 0.46.4

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.
@@ -2,8 +2,10 @@
2
2
  * ChatComposer — the shared message input every agent app used to hand-roll:
3
3
  * an auto-resizing textarea (Enter sends, Shift+Enter inserts a newline), an
4
4
  * opt-in attach + drag-and-drop + clipboard-paste surface with pending-file
5
- * chips, a streaming Stop/Send toggle, a slot for inline controls (model
6
- * picker, reasoning effort), and a Cmd/Ctrl+L focus shortcut.
5
+ * chips, an opt-in `@`-mention mode (`mention`) that swaps the textarea for a
6
+ * lazily loaded rich input with atomic mention pills, a streaming Stop/Send
7
+ * toggle, a slot for inline controls (model picker, reasoning effort), and a
8
+ * Cmd/Ctrl+L focus shortcut.
7
9
  *
8
10
  * Files arrive by three routes — the picker dialog, a drop, and a paste — and
9
11
  * all three funnel through `accept` (`./composer-file-accept`) before they
@@ -35,6 +37,7 @@
35
37
  import { type ReactNode } from 'react';
36
38
  import { type ComposerFileRejection } from './composer-file-accept';
37
39
  import { type DictationAudio } from './use-dictation';
40
+ import type { ComposerMentionProp } from './use-file-mentions';
38
41
  /** Prompt-part descriptor an uploaded file carries (the upload route's
39
42
  * `UploadedChatFile.part`), echoed back in the turn body on send. Mirrors
40
43
  * `/chat-routes`' wire shape structurally — no server import here. */
@@ -259,8 +262,25 @@ export interface ChatComposerProps {
259
262
  * status line. It sits outside the controls slot and never shrinks, so a
260
263
  * wrapping picker set cannot push it away. */
261
264
  trailing?: ReactNode;
265
+ /**
266
+ * Opt-in `@`-mentions. Present ⇒ the textarea is swapped for a lazily
267
+ * loaded TipTap rich input that renders mentions as atomic pills and
268
+ * serializes them to `@<id>` in the value; absent ⇒ exactly the plain
269
+ * textarea, with no TipTap in the bundle. Wire `useFileMentions().mention`
270
+ * straight in. The six `@tiptap/*` packages (core, extension-mention, pm,
271
+ * react, starter-kit, suggestion) are OPTIONAL peers — a consumer installs
272
+ * them to use this prop.
273
+ *
274
+ * The rich input owns its own keyboard surface, so `slashCommands` is
275
+ * disabled while `mention` is set rather than left half-armed with a menu
276
+ * no key can reach; no shipped surface combines the two. Seed and
277
+ * failed-send drafts still apply in mention mode, but caret placement (a
278
+ * textarea affordance) degrades to content-only.
279
+ */
280
+ mention?: ComposerMentionProp;
262
281
  /** `/` commands offered when the draft is exactly a leading slash token.
263
- * Omit (or pass []) and `/` types as ordinary text. */
282
+ * Omit (or pass []) and `/` types as ordinary text. Inert while `mention`
283
+ * is set — see {@link mention}. */
264
284
  slashCommands?: SlashCommand[];
265
285
  /** Dictation is opt-in: pass `onDictate` and the action row gains a mic
266
286
  * button (browsers without `MediaRecorder`/`getUserMedia` render none).
@@ -286,4 +306,4 @@ export interface ChatComposerProps {
286
306
  sendVariant?: 'pill' | 'icon';
287
307
  className?: string;
288
308
  }
289
- export declare function ChatComposer({ onSend, onSendParts, onSendFailed, sendFailureMessage, onCancel, isStreaming, disabled, placeholder, value, onValueChange, initialValue, seed, onSeedApplied, controls, controlsPlacement, onAttach, onAttachFolder, pendingFiles, onRemoveFile, onRetryFile, accept, onRejectFiles, dropTitle, dropDescription, contextItems, canSubmitAttachmentsOnly, attachmentsNotReadyMessage, canSubmitWhileBusy, autoFocus, minRows, maxHeight, trailing, slashCommands, onDictate, onDictateError, focusShortcut, floating, sendLabel, sendVariant, className, }: ChatComposerProps): import("react").JSX.Element;
309
+ export declare function ChatComposer({ onSend, onSendParts, onSendFailed, sendFailureMessage, onCancel, isStreaming, disabled, placeholder, value, onValueChange, initialValue, seed, onSeedApplied, controls, controlsPlacement, onAttach, onAttachFolder, pendingFiles, onRemoveFile, onRetryFile, accept, onRejectFiles, dropTitle, dropDescription, contextItems, canSubmitAttachmentsOnly, attachmentsNotReadyMessage, canSubmitWhileBusy, autoFocus, minRows, maxHeight, trailing, mention, slashCommands, onDictate, onDictateError, focusShortcut, floating, sendLabel, sendVariant, className, }: ChatComposerProps): import("react").JSX.Element;
@@ -41,6 +41,7 @@ export * from './durable-interaction-submit';
41
41
  export * from './use-chat-interactions';
42
42
  export * from './use-file-mentions';
43
43
  export * from './chat-mentions';
44
+ export * from './mention-pill';
44
45
  export * from './chat-attachments';
45
46
  export * from './message-attachments';
46
47
  export * from './use-composer-attachments';
@@ -132,7 +132,7 @@ import {
132
132
  withoutRecordGridCreated,
133
133
  withoutRecordGridRemoved,
134
134
  withoutRecordGridUpdate
135
- } from "../chunk-RZ6MYWMJ.js";
135
+ } from "../chunk-YTEUZXX2.js";
136
136
  import {
137
137
  SessionHistoryPanel,
138
138
  formatSessionTimestamp,
@@ -140,6 +140,9 @@ import {
140
140
  useSessionActions,
141
141
  useSessionHistory
142
142
  } from "../chunk-KKBTPZIE.js";
143
+ import {
144
+ MENTION_PILL_CLASS
145
+ } from "../chunk-RLOHIX5Y.js";
143
146
  import "../chunk-FBVLEGEG.js";
144
147
  import {
145
148
  EvidenceLineageTable,
@@ -288,6 +291,7 @@ export {
288
291
  InteractionBadge,
289
292
  InteractionPlanCard,
290
293
  InteractionQuestionCard,
294
+ MENTION_PILL_CLASS,
291
295
  MessageAttachments,
292
296
  MissionActivityLane,
293
297
  ModelPicker,
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The one boundary vocabulary for reading `@<path>` mention tokens out of
3
+ * plain text. Two inverse readings share it — the transcript segmenter
4
+ * (`chat-mentions.ts`) and editor-pill restore (`mention-serialize.ts`) — and
5
+ * they must agree, or a token one accepts the other mangles. Kept OUT of the
6
+ * `/web-react` barrel on purpose: these are internals of the grammar, not
7
+ * public API.
8
+ */
9
+ /** A character that could plausibly continue the SAME path/filename past a
10
+ * matched token. Without this lookahead a mention of `@a/b.md` would match
11
+ * inside the unrelated `@a/b.md.bak` and split it mid-filename.
12
+ *
13
+ * Unicode-aware because the wire validator (`validateSandboxMentionPath`)
14
+ * deliberately ALLOWS non-ASCII paths — in-box filenames are arbitrary. An
15
+ * ASCII-only class here would accept input the readers then mangle.
16
+ * `\p{M}` keeps DECOMPOSED filenames whole: without it, a combining accent
17
+ * (`a` + U+0301) reads as a boundary and splits the name after its base
18
+ * letter. */
19
+ export declare const PATH_CONTINUATION_CHAR: RegExp;
20
+ /** A character that, immediately BEFORE an `@`, means the `@` is part of a
21
+ * longer token (an email local part, a handle) rather than a mention start.
22
+ * Unicode-aware for the same reasons, combining marks included. */
23
+ export declare const WORD_CHAR: RegExp;
24
+ /** The full character (code point) ENDING just before `index`, or undefined
25
+ * at the start. Indexing `text[index - 1]` hands a lone UTF-16 surrogate to
26
+ * the Unicode-aware classes above, which then misread every astral letter —
27
+ * boundary checks must see whole characters. `index` must be a code-point
28
+ * boundary (both callers derive it from `@` positions and id lengths, which
29
+ * are). */
30
+ export declare function charBefore(text: string, index: number): string | undefined;
31
+ /** The full character (code point) starting at `index`, or undefined past the
32
+ * end — same surrogate rationale and precondition as {@link charBefore}. */
33
+ export declare function charAt(text: string, index: number): string | undefined;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * The mention-capable rich input behind `ChatComposer`'s `mention` prop.
3
+ *
4
+ * The five `@tiptap/*` packages are OPTIONAL peers, and every value access to
5
+ * them goes through `loadTiptapModules()`'s dynamic `import()` — never a
6
+ * static named import. A bundler resolves a missing optional peer to a stub
7
+ * module with a default export only, so a static `import { mergeAttributes }`
8
+ * fails the CONSUMER'S build even when nothing ever renders the mention path
9
+ * (measured against Vite 7's `__vite-optional-peer-dep` stub). The dynamic
10
+ * form builds clean and defers the failure to the first actual editor load,
11
+ * where it throws with the missing packages named — the same doctrine as
12
+ * `sequences-react`'s transcription peer. Type-only imports are erased and
13
+ * stay allowed.
14
+ */
15
+ import type { MentionOptions } from '@tiptap/extension-mention';
16
+ import type * as TiptapCore from '@tiptap/core';
17
+ import type * as TiptapExtensionMention from '@tiptap/extension-mention';
18
+ import type * as TiptapReact from '@tiptap/react';
19
+ import type * as TiptapStarterKit from '@tiptap/starter-kit';
20
+ import type * as TiptapSuggestion from '@tiptap/suggestion';
21
+ import { type ComponentType } from 'react';
22
+ import type { ComposerMentionProp } from './use-file-mentions';
23
+ /** The loaded namespaces of the five optional peers, as one bag. */
24
+ export interface TiptapModules {
25
+ core: typeof TiptapCore;
26
+ extensionMention: typeof TiptapExtensionMention;
27
+ react: typeof TiptapReact;
28
+ starterKit: typeof TiptapStarterKit;
29
+ suggestion: typeof TiptapSuggestion;
30
+ }
31
+ /** Resolve the optional peers, or throw naming every one of them. */
32
+ export declare function loadTiptapModules(): Promise<TiptapModules>;
33
+ export interface MentionEditorProps {
34
+ value: string;
35
+ onChange: (value: string) => void;
36
+ /** Fired when Enter (no Shift, popover closed, not composing) should send. */
37
+ onSubmit: () => void;
38
+ placeholder: string;
39
+ disabled?: boolean;
40
+ autoFocus?: boolean;
41
+ /** Pixel floor for the input box. The composer computes it from `minRows`
42
+ * against its own line metrics, so the two input modes cannot drift. */
43
+ minHeight: number;
44
+ /** Pixel height the input grows to before it scrolls. */
45
+ maxHeight: number;
46
+ mention: ComposerMentionProp;
47
+ /** Registers a focus callback the composer wires to Cmd/Ctrl+L; called with
48
+ * `null` on unmount so the composer never focuses a destroyed editor. */
49
+ registerFocus?: (focus: (() => void) | null) => void;
50
+ /**
51
+ * Clipboard files pulled off a paste. Returns true when consumed so the
52
+ * editor suppresses its default text paste — the same funnel the textarea
53
+ * path routes through to `onAttach`.
54
+ */
55
+ onPasteFiles?: (files: FileList) => boolean;
56
+ }
57
+ /** Only text, hard breaks, and atomic mention pills — no marks, no formatting. */
58
+ export declare function buildComposerStarterKit(tiptap: TiptapModules): TiptapCore.Extension<TiptapStarterKit.StarterKitOptions, any>;
59
+ /**
60
+ * The mention node: an inline atom (`inline: true, selectable: false,
61
+ * atom: true` from `@tiptap/extension-mention`) carrying `{ id, label, kind }`,
62
+ * rendered as a themed pill showing the label with the full id in `title`. Atom
63
+ * means the cursor can't enter it and a single backspace removes the whole
64
+ * thing. The `suggestion` config is supplied by the caller so the popover's
65
+ * fetch/keyboard wiring stays in the component.
66
+ */
67
+ export declare function buildMentionExtension(tiptap: TiptapModules, trigger: string, suggestion: MentionOptions['suggestion']): TiptapCore.Node<MentionOptions<any, TiptapExtensionMention.MentionNodeAttrs>, any>;
68
+ /** `React.lazy` payload: resolve the peers, then build the component. */
69
+ export declare function loadMentionEditor(): Promise<{
70
+ default: ComponentType<MentionEditorProps>;
71
+ }>;
72
+ /**
73
+ * Builds the mention-capable rich input against loaded tiptap modules. Loaded
74
+ * lazily by `ChatComposer` so textarea-only consumers never pull TipTap into
75
+ * their initial bundle. It preserves every textarea behavior — controlled
76
+ * plain-text `value`, Enter to send / Shift+Enter for a newline, placeholder,
77
+ * disabled, autofocus, file-paste routing — and adds `@`-mention pills backed
78
+ * by an async provider.
79
+ *
80
+ * The suggestion list renders through `PopoverSurface` anchored to the input
81
+ * box, like the composer's slash menu: an in-place panel is a panel the host
82
+ * clips away (see the popover canon in AGENTS.md).
83
+ */
84
+ export declare function createMentionEditor(tiptap: TiptapModules): ComponentType<MentionEditorProps>;
@@ -0,0 +1,35 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { MentionItem } from './use-file-mentions';
3
+ /** Imperative surface the editor's suggestion keymap drives. */
4
+ export interface MentionListHandle {
5
+ /** Returns true when the key was consumed — the editor must not also act. */
6
+ onKeyDown: (event: KeyboardEvent) => boolean;
7
+ }
8
+ export interface MentionListProps {
9
+ items: MentionItem[];
10
+ loading: boolean;
11
+ error: boolean;
12
+ /** Shown when the fetch resolved to zero items. Default "No matches". */
13
+ emptyText?: string;
14
+ renderItem?: (item: MentionItem) => ReactNode;
15
+ onSelect: (item: MentionItem) => void;
16
+ /** Root `role="listbox"` element id; option rows derive stable ids from it
17
+ * (`<id>-opt-<index>`) so the editor can point `aria-activedescendant` at
18
+ * the highlighted row. */
19
+ id?: string;
20
+ /** Fired whenever the highlight moves (keys, hover, or a result-set
21
+ * re-home) — what keeps the editor's `aria-activedescendant` current. */
22
+ onActiveChange?: (index: number) => void;
23
+ /** Extra classes merged onto the panel's root element, applied last so
24
+ * they win over the component's own. */
25
+ className?: string;
26
+ }
27
+ /**
28
+ * The mention suggestion list: a flat, keyboard-driven menu with loading,
29
+ * empty, and error states. Selection is owned here so ↑/↓ and Enter/Tab
30
+ * resolve against the highlighted row; every key it handles is reported
31
+ * consumed so the composer's Enter-to-send never fires while open. The panel
32
+ * carries its own surface classes but no positioning — the editor places it
33
+ * through `PopoverSurface`, per the popover canon.
34
+ */
35
+ export declare const MentionList: import("react").ForwardRefExoticComponent<MentionListProps & import("react").RefAttributes<MentionListHandle>>;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Visual contract for a rendered mention pill. The TipTap extension in
3
+ * `mention-editor.tsx` styles its inline atom node with this, and any other
4
+ * surface that renders a resolved mention (e.g. a sent-message transcript)
5
+ * uses the same constant so the two stay one visual contract instead of
6
+ * silently drifting apart. Kept in its own module (no TipTap import) so
7
+ * importing it never pulls the lazily-loaded editor chunk into a consumer's
8
+ * bundle.
9
+ */
10
+ export declare const MENTION_PILL_CLASS = "rounded-md bg-primary/10 px-1 py-0.5 font-medium text-primary";
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Round-trip between the mention editor's document and the composer's plain
3
+ * `value` string. A mention node serializes to `@<id>`; parsing restores a
4
+ * pill only for ids the session already knows (fetched, inserted, or
5
+ * restored), so unknown `@…` runs stay literal text.
6
+ *
7
+ * The document shape is kept structural (no TipTap import) so this round-trip
8
+ * is unit-testable on its own and never pulls the editor chunk into a bundle.
9
+ */
10
+ import type { MentionItem } from './use-file-mentions';
11
+ /**
12
+ * The subset of a TipTap/ProseMirror JSON document the mention editor
13
+ * produces: a `doc` of paragraphs, each holding text, hard breaks, and atomic
14
+ * mention nodes.
15
+ */
16
+ export interface MentionDocNode {
17
+ type: string;
18
+ text?: string;
19
+ attrs?: {
20
+ id?: string | null;
21
+ label?: string | null;
22
+ kind?: string | null;
23
+ };
24
+ content?: MentionDocNode[];
25
+ }
26
+ /**
27
+ * Plain-text serialization of the editor document. Paragraphs join with a
28
+ * newline, hard breaks become a newline, and a mention node becomes `@<id>` —
29
+ * the stable text form the controlled `value` carries.
30
+ */
31
+ export declare function serializeMentionDoc(doc: MentionDocNode): string;
32
+ /** Every mention node in the document, in order, as `MentionItem`s. */
33
+ export declare function collectMentions(doc: MentionDocNode): MentionItem[];
34
+ /**
35
+ * Parse a controlled `value` string back into an editor document. `@<id>`
36
+ * runs that match a currently-known mention restore as atomic mention nodes;
37
+ * every other `@…` stays literal text. Each line becomes a paragraph — a
38
+ * deliberate asymmetry with `serializeMentionDoc`, which also flattens an
39
+ * in-paragraph `hardBreak` to `\n`: the string round-trips byte-identically,
40
+ * but a restored Shift+Enter comes back as a paragraph break. The two render
41
+ * identically under the composer's styling (no paragraph margins), so the
42
+ * plain-text `value` contract stays the source of truth.
43
+ */
44
+ export declare function parseMentionValue(value: string, known: Map<string, MentionItem>): MentionDocNode;
@@ -1,7 +1,7 @@
1
1
  /**
2
- * `useFileMentions` — the glue a host passes straight into `AgentComposer`'s
3
- * `mention` prop (`@tangle-network/sandbox-ui#184`) to wire up `@`-file
4
- * mentions against `createSandboxFileIndexRoute` (`/chat-routes`).
2
+ * `useFileMentions` — the glue a host passes straight into `ChatComposer`'s
3
+ * `mention` prop to wire up `@`-file mentions against
4
+ * `createSandboxFileIndexRoute` (`/chat-routes`).
5
5
  *
6
6
  * Fetches the index once per session from `indexUrl`, refreshes it in the
7
7
  * background whenever the popover opens (a `fetchItems` call) if the cached
@@ -10,31 +10,45 @@
10
10
  * `refresh()` lets a caller force a re-fetch immediately instead of waiting
11
11
  * on `refreshAfterMs` — e.g. right after the agent creates a file mid-session.
12
12
  *
13
- * `MentionItem`/the `mention` prop shape mirror the FROZEN contract from
14
- * sandbox-ui#184 structurally (no import: `/web-react` stays dependency-free
15
- * beyond React, and `@tangle-network/sandbox-ui` is an optional peer).
13
+ * `MentionItem` and `ComposerMentionProp` are the mention contract this
14
+ * package defines and `mention-editor.tsx` renders. The shape stays
15
+ * structurally identical to sandbox-ui#184's `AgentComposerProps['mention']`,
16
+ * so the same value drives sandbox-ui's `AgentComposer` during migration
17
+ * (tangle-network/agent-dev-container#5934) without an import either way.
16
18
  */
17
19
  import type { ReactNode } from 'react';
18
20
  import type { FileMention } from '../chat-routes/wire';
19
- /** Mirrors sandbox-ui#184's `MentionItem` — the atomic pill's payload. For a
20
- * file mention, `id` is the workspace-relative path (the pill's stable
21
- * identity and the `@<id>` serialization sandbox-ui uses to round-trip
22
- * `value`), `label` is the display name, and `detail` carries the full path
23
- * for the popover row's secondary line. */
21
+ /** The atomic pill's payload. For a file mention, `id` is the
22
+ * workspace-relative path (the pill's stable identity and the `@<id>`
23
+ * serialization the editor uses to round-trip `value`), `label` is the
24
+ * display name, and `detail` carries the full path for the popover row's
25
+ * secondary line. */
24
26
  export interface MentionItem {
25
27
  id: string;
26
28
  label: string;
27
29
  detail?: string;
28
30
  kind?: string;
29
31
  }
30
- /** Mirrors sandbox-ui#184's `AgentComposerProps['mention']` shape — plug the
31
- * hook's `mention` return value straight into that prop. */
32
+ /** `ChatComposer`'s `mention` prop shape — plug the hook's `mention` return
33
+ * value straight into it. Structurally identical to sandbox-ui#184's
34
+ * `AgentComposerProps['mention']`, so it also drives `AgentComposer`. */
32
35
  export interface ComposerMentionProp {
36
+ /** The character that opens the popover. Default "@". Read once when the
37
+ * editor mounts — a runtime change does not re-key the editor. */
33
38
  trigger?: string;
39
+ /** Async provider called with the query typed after the trigger. */
34
40
  fetchItems(query: string): Promise<MentionItem[]>;
41
+ /** Fired with the mentions currently in the document whenever they change. */
35
42
  onMentionsChange?(mentions: MentionItem[]): void;
43
+ /** Custom row renderer for a popover item. */
36
44
  renderItem?(item: MentionItem): ReactNode;
45
+ /** Shown when a fetch resolves to zero items. Default "No matches". */
37
46
  emptyText?: string;
47
+ /** Extra classes merged onto the suggestion panel's root element
48
+ * (`role="listbox"`), applied last so they win over the component's own —
49
+ * the supported way to retheme the popover instead of targeting it by its
50
+ * ARIA attributes. */
51
+ popoverClassName?: string;
38
52
  }
39
53
  /**
40
54
  * Ranks `files` against `query` (case-insensitive), capped to `limit`:
@@ -77,7 +91,7 @@ export interface UseFileMentionsOptions {
77
91
  }
78
92
  /** Provide properties and methods to manage and refresh file mentions in a composer interface */
79
93
  export interface UseFileMentionsResult {
80
- /** Spread straight into `AgentComposer`'s `mention` prop. */
94
+ /** Spread straight into `ChatComposer`'s `mention` prop. */
81
95
  mention: ComposerMentionProp;
82
96
  /** The files currently referenced by mentions in the composer's value —
83
97
  * the send-body list (map through `fileMentionsToParts`). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-app",
3
- "version": "0.46.3",
3
+ "version": "0.46.4",
4
4
  "packageManager": "pnpm@11.17.0",
5
5
  "description": "Build agent applications with typed chat, tools, sandboxes, integrations, billing, and evaluation.",
6
6
  "keywords": [
@@ -530,6 +530,13 @@
530
530
  "@tangle-network/ui": "^11.5.0",
531
531
  "@testing-library/dom": "^10.4.1",
532
532
  "@testing-library/react": "^16.3.2",
533
+ "@testing-library/user-event": "^14.6.1",
534
+ "@tiptap/core": "^3.28.0",
535
+ "@tiptap/extension-mention": "^3.28.0",
536
+ "@tiptap/pm": "^3.28.0",
537
+ "@tiptap/react": "^3.28.0",
538
+ "@tiptap/starter-kit": "^3.28.0",
539
+ "@tiptap/suggestion": "^3.28.0",
533
540
  "@types/better-sqlite3": "^7.6.13",
534
541
  "@types/node": "^22.20.1",
535
542
  "@types/react": "^19.0.0",
@@ -579,6 +586,12 @@
579
586
  "@tangle-network/sandbox": ">=0.29.0 <0.30.0",
580
587
  "@tangle-network/sandbox-ui": ">=0.105.0",
581
588
  "@tangle-network/ui": ">=11.5.0",
589
+ "@tiptap/core": ">=3.28.0 <4.0.0",
590
+ "@tiptap/extension-mention": ">=3.28.0 <4.0.0",
591
+ "@tiptap/pm": ">=3.28.0 <4.0.0",
592
+ "@tiptap/react": ">=3.28.0 <4.0.0",
593
+ "@tiptap/starter-kit": ">=3.28.0 <4.0.0",
594
+ "@tiptap/suggestion": ">=3.28.0 <4.0.0",
582
595
  "@xyflow/react": ">=12.0.0",
583
596
  "better-auth": ">=1.6.16",
584
597
  "drizzle-orm": ">=0.36",
@@ -634,6 +647,24 @@
634
647
  "@tangle-network/brand": {
635
648
  "optional": true
636
649
  },
650
+ "@tiptap/core": {
651
+ "optional": true
652
+ },
653
+ "@tiptap/extension-mention": {
654
+ "optional": true
655
+ },
656
+ "@tiptap/pm": {
657
+ "optional": true
658
+ },
659
+ "@tiptap/react": {
660
+ "optional": true
661
+ },
662
+ "@tiptap/starter-kit": {
663
+ "optional": true
664
+ },
665
+ "@tiptap/suggestion": {
666
+ "optional": true
667
+ },
637
668
  "@xyflow/react": {
638
669
  "optional": true
639
670
  },