@tangle-network/agent-app 0.46.3 → 0.46.5
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.
- package/dist/assistant/index.js +6 -3
- package/dist/assistant/index.js.map +1 -1
- package/dist/chat-react/index.d.ts +10 -24
- package/dist/chat-react/index.js +6 -127
- package/dist/chat-react/index.js.map +1 -1
- package/dist/chunk-3HUFJ5LO.js +24 -0
- package/dist/chunk-3HUFJ5LO.js.map +1 -0
- package/dist/chunk-5SSUCLBW.js +1896 -0
- package/dist/chunk-5SSUCLBW.js.map +1 -0
- package/dist/{chunk-RZ6MYWMJ.js → chunk-JAYKCWW4.js} +625 -1551
- package/dist/chunk-JAYKCWW4.js.map +1 -0
- package/dist/chunk-L7MB2LLM.js +15 -0
- package/dist/chunk-L7MB2LLM.js.map +1 -0
- package/dist/mention-editor-WW7UVZMR.js +523 -0
- package/dist/mention-editor-WW7UVZMR.js.map +1 -0
- package/dist/teams/drizzle/invitations-schema.d.ts +1 -1
- package/dist/teams/drizzle/schema.d.ts +1 -1
- package/dist/web-react/chat-composer.d.ts +24 -4
- package/dist/{chat-react → web-react}/composer-mode-controls.d.ts +11 -1
- package/dist/{chat-react → web-react}/entry-composer.d.ts +11 -8
- package/dist/web-react/index.d.ts +3 -0
- package/dist/web-react/index.js +17 -8
- package/dist/web-react/mention-boundaries.d.ts +33 -0
- package/dist/web-react/mention-editor.d.ts +84 -0
- package/dist/web-react/mention-list.d.ts +35 -0
- package/dist/web-react/mention-pill.d.ts +10 -0
- package/dist/web-react/mention-serialize.d.ts +44 -0
- package/dist/web-react/use-file-mentions.d.ts +28 -14
- package/package.json +32 -1
- package/dist/chat-react/types.d.ts +0 -11
- package/dist/chunk-DINGA2MO.js +0 -718
- package/dist/chunk-DINGA2MO.js.map +0 -1
- package/dist/chunk-RZ6MYWMJ.js.map +0 -1
|
@@ -1,27 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@tangle-network/agent-app/chat-react` —
|
|
3
|
-
* `@tangle-network/sandbox-ui`.
|
|
2
|
+
* `@tangle-network/agent-app/chat-react` — a compatibility re-export.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* app-shell ASSEMBLY over it — which controls an entry surface gets, the
|
|
13
|
-
* submit gate. Three products each re-derived that assembly and each dropped a
|
|
14
|
-
* different control, so the same "shared" components produced three different
|
|
15
|
-
* capability sets. One assembly, three products, domain by parameter.
|
|
16
|
-
*
|
|
17
|
-
* PICKER CANON. The agent-identity controls an `EntryComposer` renders are the
|
|
18
|
-
* canonical ones: its `agent` prop is `AgentSessionControlsProps` and the row
|
|
19
|
-
* is `/web-react`'s `AgentSessionControls`, whose model menu IS the canonical
|
|
20
|
-
* `ModelPicker` — see "UI chrome ownership (picker canon)" in AGENTS.md and
|
|
21
|
-
* `docs/ui-picker-canon.md`. The legacy `ComposerAgentControls` adapter over
|
|
22
|
-
* sandbox-ui's strip was REMOVED (it was deprecated-first); products still on
|
|
23
|
-
* it migrate per the props mapping in that doc.
|
|
4
|
+
* This subpath used to isolate the one assembly that rendered sandbox-ui's
|
|
5
|
+
* `AgentComposer`, per the optional-peer rule. `EntryComposer` now renders
|
|
6
|
+
* this package's own `ChatComposer` (tangle-network/agent-dev-container#5934,
|
|
7
|
+
* PR 3), so nothing here touches sandbox-ui any more and the components live
|
|
8
|
+
* in `/web-react` with the rest of the composer surface. The subpath stays as
|
|
9
|
+
* a re-export because subpaths are additive (see "Additive subpaths" in
|
|
10
|
+
* AGENTS.md) — existing imports keep working; new code imports `/web-react`.
|
|
24
11
|
*/
|
|
25
|
-
export { EntryComposer, type EntryComposerProps } from '
|
|
26
|
-
export { ComposerModeControls, type ComposerModeControlsProps, } from '
|
|
27
|
-
export type { ComposerPlanModeSelection } from './types';
|
|
12
|
+
export { EntryComposer, type EntryComposerProps } from '../web-react/entry-composer';
|
|
13
|
+
export { ComposerModeControls, type ComposerModeControlsProps, type ComposerPlanModeSelection, } from '../web-react/composer-mode-controls';
|
package/dist/chat-react/index.js
CHANGED
|
@@ -1,134 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "../chunk-
|
|
2
|
+
ComposerModeControls,
|
|
3
|
+
EntryComposer
|
|
4
|
+
} from "../chunk-5SSUCLBW.js";
|
|
5
|
+
import "../chunk-L7MB2LLM.js";
|
|
5
6
|
import "../chunk-YDOQE47G.js";
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
} from "../chunk-YNMPMW3G.js";
|
|
7
|
+
import "../chunk-EDTWGSQT.js";
|
|
8
|
+
import "../chunk-YNMPMW3G.js";
|
|
9
9
|
import "../chunk-KWXUBMXU.js";
|
|
10
10
|
import "../chunk-TH7L265V.js";
|
|
11
|
-
|
|
12
|
-
// src/chat-react/entry-composer.tsx
|
|
13
|
-
import { useState } from "react";
|
|
14
|
-
import { AgentComposer } from "@tangle-network/sandbox-ui/chat";
|
|
15
|
-
|
|
16
|
-
// src/chat-react/composer-mode-controls.tsx
|
|
17
|
-
import { ListChecks } from "lucide-react";
|
|
18
|
-
import { cn } from "@tangle-network/sandbox-ui/utils";
|
|
19
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
20
|
-
function ComposerModeControls({ planMode }) {
|
|
21
|
-
if (!planMode) return null;
|
|
22
|
-
return /* @__PURE__ */ jsxs(
|
|
23
|
-
"button",
|
|
24
|
-
{
|
|
25
|
-
type: "button",
|
|
26
|
-
"aria-pressed": planMode.enabled,
|
|
27
|
-
disabled: planMode.saving,
|
|
28
|
-
onClick: () => planMode.setEnabled(!planMode.enabled),
|
|
29
|
-
title: "Plan mode: the agent proposes a plan you approve before it executes",
|
|
30
|
-
className: cn(
|
|
31
|
-
// Inset ring: this chip sits in a composer row that clips its overflow,
|
|
32
|
-
// so an outward ring loses three of its four sides. Only the offset is
|
|
33
|
-
// overridden — width and colour stay with the tokens.
|
|
34
|
-
"inline-flex h-7 items-center gap-1 rounded-full border px-2.5 text-xs transition-colors focus-visible:[outline-offset:-2px]",
|
|
35
|
-
planMode.enabled ? "border-primary/50 bg-primary/10 text-primary" : "border-border bg-transparent text-muted-foreground hover:text-foreground",
|
|
36
|
-
planMode.saving && "opacity-60"
|
|
37
|
-
),
|
|
38
|
-
children: [
|
|
39
|
-
/* @__PURE__ */ jsx(ListChecks, { className: "h-3.5 w-3.5" }),
|
|
40
|
-
"Plan"
|
|
41
|
-
]
|
|
42
|
-
}
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// src/chat-react/entry-composer.tsx
|
|
47
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
48
|
-
function EntryComposer({
|
|
49
|
-
heading,
|
|
50
|
-
subheading,
|
|
51
|
-
placeholder,
|
|
52
|
-
initialValue = "",
|
|
53
|
-
sendLabel,
|
|
54
|
-
disabled,
|
|
55
|
-
agent,
|
|
56
|
-
modes,
|
|
57
|
-
planMode,
|
|
58
|
-
uploadUrl,
|
|
59
|
-
accept = ATTACHMENT_ACCEPT,
|
|
60
|
-
onAttachmentError,
|
|
61
|
-
onRejectFiles,
|
|
62
|
-
mentions,
|
|
63
|
-
mentionPopoverClassName,
|
|
64
|
-
footer,
|
|
65
|
-
ready = true,
|
|
66
|
-
onSubmit,
|
|
67
|
-
className,
|
|
68
|
-
composerClassName,
|
|
69
|
-
maxWidth = 820
|
|
70
|
-
}) {
|
|
71
|
-
const [value, setValue] = useState(initialValue);
|
|
72
|
-
const attachments = useComposerAttachments({
|
|
73
|
-
uploadUrl,
|
|
74
|
-
enabled: !!uploadUrl,
|
|
75
|
-
onReject: onAttachmentError,
|
|
76
|
-
onError: onAttachmentError
|
|
77
|
-
});
|
|
78
|
-
function submit(prompt) {
|
|
79
|
-
if (!ready || disabled) return;
|
|
80
|
-
const next = prompt.trim();
|
|
81
|
-
if (attachments.hasPending || attachments.hasError) {
|
|
82
|
-
if (attachments.blockReason) onAttachmentError?.(attachments.blockReason);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
if (!next && attachments.references.length === 0) return;
|
|
86
|
-
onSubmit(next, attachments.references, mentions?.mentions ?? []);
|
|
87
|
-
setValue("");
|
|
88
|
-
attachments.clear();
|
|
89
|
-
mentions?.clearMentions();
|
|
90
|
-
}
|
|
91
|
-
return /* @__PURE__ */ jsx2(
|
|
92
|
-
"div",
|
|
93
|
-
{
|
|
94
|
-
className: className ?? "relative flex flex-1 flex-col items-center justify-center overflow-hidden bg-background px-5",
|
|
95
|
-
children: /* @__PURE__ */ jsxs2("div", { className: "w-full", style: { maxWidth }, children: [
|
|
96
|
-
heading ? /* @__PURE__ */ jsx2("h2", { className: "mb-4 text-center text-[1.75rem] font-medium tracking-tight text-foreground", children: heading }) : null,
|
|
97
|
-
subheading ? /* @__PURE__ */ jsx2("p", { className: "mx-auto mb-9 max-w-md text-center text-sm leading-relaxed text-muted-foreground", children: subheading }) : heading ? /* @__PURE__ */ jsx2("div", { className: "mb-7" }) : null,
|
|
98
|
-
/* @__PURE__ */ jsx2(
|
|
99
|
-
AgentComposer,
|
|
100
|
-
{
|
|
101
|
-
className: composerClassName ?? "vt-composer",
|
|
102
|
-
value,
|
|
103
|
-
onChange: setValue,
|
|
104
|
-
onSubmit: () => submit(value),
|
|
105
|
-
placeholder,
|
|
106
|
-
sendLabel,
|
|
107
|
-
disabled,
|
|
108
|
-
autoFocus: true,
|
|
109
|
-
canSubmitAttachmentsOnly: true,
|
|
110
|
-
accept,
|
|
111
|
-
attachments: attachments.composerFiles,
|
|
112
|
-
onAttach: uploadUrl ? (files) => void attachments.addFiles(files) : void 0,
|
|
113
|
-
onRejectFiles,
|
|
114
|
-
onRemoveFile: attachments.removeAttachment,
|
|
115
|
-
onRetryFile: attachments.retry,
|
|
116
|
-
mention: mentions ? {
|
|
117
|
-
...mentions.mention,
|
|
118
|
-
// Sidebar tone + hairline so the popover reads as app chrome
|
|
119
|
-
// (the same treatment the picker menus get) instead of the
|
|
120
|
-
// brighter overlay tone the component defaults to.
|
|
121
|
-
popoverClassName: mentionPopoverClassName ?? "bg-surface-container-low border-[var(--md3-outline-variant)]"
|
|
122
|
-
} : void 0,
|
|
123
|
-
controls: modes ?? /* @__PURE__ */ jsx2(ComposerModeControls, { planMode }),
|
|
124
|
-
trailing: agent ? /* @__PURE__ */ jsx2(AgentSessionControls, { ...agent }) : void 0
|
|
125
|
-
}
|
|
126
|
-
),
|
|
127
|
-
footer ? /* @__PURE__ */ jsx2("div", { className: "mt-7", children: footer }) : null
|
|
128
|
-
] })
|
|
129
|
-
}
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
11
|
export {
|
|
133
12
|
ComposerModeControls,
|
|
134
13
|
EntryComposer
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/chat-react/entry-composer.tsx","../../src/chat-react/composer-mode-controls.tsx"],"sourcesContent":["import { useState, type ReactNode } from 'react'\nimport { AgentComposer } from '@tangle-network/sandbox-ui/chat'\nimport { ATTACHMENT_ACCEPT, useComposerAttachments } from '../web-react/use-composer-attachments'\nimport type { UseFileMentionsResult } from '../web-react/use-file-mentions'\nimport type { ChatAttachmentInput, FileMention } from '../chat-routes/wire'\nimport {\n AgentSessionControls,\n type AgentSessionControlsProps,\n} from '../web-react/agent-session-controls'\nimport { ComposerModeControls } from './composer-mode-controls'\nimport type { ComposerPlanModeSelection } from './types'\n\nexport interface EntryComposerProps {\n /** The one line above the input. Domain copy — always a product parameter. */\n heading?: ReactNode\n /** Optional supporting line under the heading. */\n subheading?: ReactNode\n placeholder?: string\n initialValue?: string\n sendLabel?: string\n disabled?: boolean\n /**\n * Agent identity (backend/model/effort). Pass it and the control row renders;\n * omit it and the composer ships without one. Omitting is a real choice for a\n * surface with nothing to choose — it should never be an oversight, which is\n * why this is one prop rather than a free-form slot a caller can forget.\n *\n * This is the CANONICAL picker cluster: `AgentSessionControls` from\n * `/web-react` (its model menu IS the canonical `ModelPicker`). The legacy\n * sandbox-ui adapter that used to back this prop was removed; the props\n * mapping for migrating a stored selection lives in\n * `docs/ui-picker-canon.md`.\n */\n agent?: AgentSessionControlsProps\n /**\n * Product-specific behavioral controls docked on the LEFT. A mode is an\n * on/off switch, not a value picker, so it sits apart from agent identity.\n * For the standard plan-approval control, prefer `planMode`.\n */\n modes?: ReactNode\n /**\n * Standard plan-approval mode. Pass only when the selected backend supports\n * it; omitted means the control is not rendered.\n */\n planMode?: ComposerPlanModeSelection\n /**\n * Upload endpoint for staged attachments. Omit and the attach affordance is\n * hidden — a composer with no place to put a file must not offer one.\n */\n uploadUrl?: string\n accept?: string\n onAttachmentError?: (reason: string) => void\n onRejectFiles?: Parameters<typeof AgentComposer>[0]['onRejectFiles']\n /**\n * `@`-file mentions. The hook itself is shared (`useFileMentions`), but the\n * cold-box policy around it — whether pressing `@` is worth starting a\n * sandbox — is a per-surface product call, so the result is injected rather\n * than created here.\n */\n mentions?: UseFileMentionsResult\n mentionPopoverClassName?: string\n /** Rendered under the composer: suggestion pills, an onboarding nudge, a\n * disclaimer. All domain copy. */\n footer?: ReactNode\n /** Block submit until a persisted selection has resolved against the catalog,\n * so the first turn cannot go out under the wrong model. Defaults to true. */\n ready?: boolean\n onSubmit: (\n prompt: string,\n attachments: ChatAttachmentInput[],\n mentions: FileMention[],\n ) => void\n className?: string\n composerClassName?: string\n /** Max width of the centered column. Defaults to the fleet's 820px. */\n maxWidth?: number\n}\n\n/**\n * `EntryComposer` — the centered \"what do you want to work on?\" surface a\n * product shows before a conversation exists (a new thread, an empty session,\n * a workspace overview).\n *\n * It exists because three products each grew their own, and they drifted into\n * three different capability sets rather than three different looks: one lost\n * the attach button, one lost the model and effort pickers entirely, one\n * hand-rolled a `<textarea>` and wired pickers from three separate packages\n * into one row. The composer, the pickers, the attachment queue and the mention\n * index were all ALREADY shared — what was not shared was the assembly, so\n * every product re-derived which controls an entry surface gets, and each\n * re-derivation dropped a different one.\n *\n * Mechanism lives here: layout, the attachment queue, the mention wiring, the\n * submit gate (nothing sends while an upload is pending or failed, or before\n * the model selection has resolved). Domain stays a parameter: `heading`,\n * `placeholder`, `footer` (suggestion pills, disclaimers) and the selections\n * themselves.\n *\n * The docked in-thread composer is NOT this component — it renders\n * `AgentComposer` directly with the same canonical `AgentSessionControls`,\n * because a docked composer has a transcript above it and no hero layout.\n */\nexport function EntryComposer({\n heading,\n subheading,\n placeholder,\n initialValue = '',\n sendLabel,\n disabled,\n agent,\n modes,\n planMode,\n uploadUrl,\n accept = ATTACHMENT_ACCEPT,\n onAttachmentError,\n onRejectFiles,\n mentions,\n mentionPopoverClassName,\n footer,\n ready = true,\n onSubmit,\n className,\n composerClassName,\n maxWidth = 820,\n}: EntryComposerProps) {\n const [value, setValue] = useState(initialValue)\n const attachments = useComposerAttachments({\n uploadUrl,\n enabled: !!uploadUrl,\n onReject: onAttachmentError,\n onError: onAttachmentError,\n })\n\n function submit(prompt: string) {\n if (!ready || disabled) return\n const next = prompt.trim()\n // A pending or failed upload must not send: the turn would reference an\n // attachment the store does not have. Surface why rather than no-op'ing.\n if (attachments.hasPending || attachments.hasError) {\n if (attachments.blockReason) onAttachmentError?.(attachments.blockReason)\n return\n }\n if (!next && attachments.references.length === 0) return\n onSubmit(next, attachments.references, mentions?.mentions ?? [])\n setValue('')\n attachments.clear()\n mentions?.clearMentions()\n }\n\n return (\n <div\n className={\n className ??\n 'relative flex flex-1 flex-col items-center justify-center overflow-hidden bg-background px-5'\n }\n >\n <div className=\"w-full\" style={{ maxWidth }}>\n {heading ? (\n <h2 className=\"mb-4 text-center text-[1.75rem] font-medium tracking-tight text-foreground\">\n {heading}\n </h2>\n ) : null}\n {subheading ? (\n <p className=\"mx-auto mb-9 max-w-md text-center text-sm leading-relaxed text-muted-foreground\">\n {subheading}\n </p>\n ) : (\n heading ? <div className=\"mb-7\" /> : null\n )}\n <AgentComposer\n className={composerClassName ?? 'vt-composer'}\n value={value}\n onChange={setValue}\n onSubmit={() => submit(value)}\n placeholder={placeholder}\n sendLabel={sendLabel}\n disabled={disabled}\n autoFocus\n canSubmitAttachmentsOnly\n accept={accept}\n attachments={attachments.composerFiles}\n onAttach={uploadUrl ? (files) => void attachments.addFiles(files) : undefined}\n onRejectFiles={onRejectFiles}\n onRemoveFile={attachments.removeAttachment}\n onRetryFile={attachments.retry}\n mention={\n mentions\n ? {\n ...mentions.mention,\n // Sidebar tone + hairline so the popover reads as app chrome\n // (the same treatment the picker menus get) instead of the\n // brighter overlay tone the component defaults to.\n popoverClassName:\n mentionPopoverClassName ??\n 'bg-surface-container-low border-[var(--md3-outline-variant)]',\n }\n : undefined\n }\n controls={modes ?? <ComposerModeControls planMode={planMode} />}\n trailing={\n agent ? <AgentSessionControls {...agent} /> : undefined\n }\n />\n {footer ? <div className=\"mt-7\">{footer}</div> : null}\n </div>\n </div>\n )\n}\n","import { ListChecks } from 'lucide-react'\nimport { cn } from '@tangle-network/sandbox-ui/utils'\nimport type { ComposerPlanModeSelection } from './types'\n\nexport interface ComposerModeControlsProps {\n /**\n * Plan-approval mode. Products pass it only when the selected backend can\n * propose a plan and wait for approval; omitted means nothing renders.\n */\n planMode?: ComposerPlanModeSelection\n}\n\n/**\n * The shared plan-mode toggle for the left side of an agent composer.\n * Plan mode is a behavioral switch, not part of the profile/backend/model/\n * thinking identity controls on the right.\n */\nexport function ComposerModeControls({ planMode }: ComposerModeControlsProps) {\n if (!planMode) return null\n\n return (\n <button\n type=\"button\"\n aria-pressed={planMode.enabled}\n disabled={planMode.saving}\n onClick={() => planMode.setEnabled(!planMode.enabled)}\n title=\"Plan mode: the agent proposes a plan you approve before it executes\"\n className={cn(\n // Inset ring: this chip sits in a composer row that clips its overflow,\n // so an outward ring loses three of its four sides. Only the offset is\n // overridden — width and colour stay with the tokens.\n 'inline-flex h-7 items-center gap-1 rounded-full border px-2.5 text-xs transition-colors focus-visible:[outline-offset:-2px]',\n planMode.enabled\n ? 'border-primary/50 bg-primary/10 text-primary'\n : 'border-border bg-transparent text-muted-foreground hover:text-foreground',\n planMode.saving && 'opacity-60',\n )}\n >\n <ListChecks className=\"h-3.5 w-3.5\" />\n Plan\n </button>\n )\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,gBAAgC;AACzC,SAAS,qBAAqB;;;ACD9B,SAAS,kBAAkB;AAC3B,SAAS,UAAU;AAoBf,SAiBE,KAjBF;AAJG,SAAS,qBAAqB,EAAE,SAAS,GAA8B;AAC5E,MAAI,CAAC,SAAU,QAAO;AAEtB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,gBAAc,SAAS;AAAA,MACvB,UAAU,SAAS;AAAA,MACnB,SAAS,MAAM,SAAS,WAAW,CAAC,SAAS,OAAO;AAAA,MACpD,OAAM;AAAA,MACN,WAAW;AAAA;AAAA;AAAA;AAAA,QAIT;AAAA,QACA,SAAS,UACL,iDACA;AAAA,QACJ,SAAS,UAAU;AAAA,MACrB;AAAA,MAEA;AAAA,4BAAC,cAAW,WAAU,eAAc;AAAA,QAAE;AAAA;AAAA;AAAA,EAExC;AAEJ;;;ADkHM,SAEI,OAAAA,MAFJ,QAAAC,aAAA;AAtDC,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AACb,GAAuB;AACrB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,YAAY;AAC/C,QAAM,cAAc,uBAAuB;AAAA,IACzC;AAAA,IACA,SAAS,CAAC,CAAC;AAAA,IACX,UAAU;AAAA,IACV,SAAS;AAAA,EACX,CAAC;AAED,WAAS,OAAO,QAAgB;AAC9B,QAAI,CAAC,SAAS,SAAU;AACxB,UAAM,OAAO,OAAO,KAAK;AAGzB,QAAI,YAAY,cAAc,YAAY,UAAU;AAClD,UAAI,YAAY,YAAa,qBAAoB,YAAY,WAAW;AACxE;AAAA,IACF;AACA,QAAI,CAAC,QAAQ,YAAY,WAAW,WAAW,EAAG;AAClD,aAAS,MAAM,YAAY,YAAY,UAAU,YAAY,CAAC,CAAC;AAC/D,aAAS,EAAE;AACX,gBAAY,MAAM;AAClB,cAAU,cAAc;AAAA,EAC1B;AAEA,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,WACE,aACA;AAAA,MAGF,0BAAAC,MAAC,SAAI,WAAU,UAAS,OAAO,EAAE,SAAS,GACvC;AAAA,kBACC,gBAAAD,KAAC,QAAG,WAAU,8EACX,mBACH,IACE;AAAA,QACH,aACC,gBAAAA,KAAC,OAAE,WAAU,mFACV,sBACH,IAEA,UAAU,gBAAAA,KAAC,SAAI,WAAU,QAAO,IAAK;AAAA,QAEvC,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,qBAAqB;AAAA,YAChC;AAAA,YACA,UAAU;AAAA,YACV,UAAU,MAAM,OAAO,KAAK;AAAA,YAC5B;AAAA,YACA;AAAA,YACA;AAAA,YACA,WAAS;AAAA,YACT,0BAAwB;AAAA,YACxB;AAAA,YACA,aAAa,YAAY;AAAA,YACzB,UAAU,YAAY,CAAC,UAAU,KAAK,YAAY,SAAS,KAAK,IAAI;AAAA,YACpE;AAAA,YACA,cAAc,YAAY;AAAA,YAC1B,aAAa,YAAY;AAAA,YACzB,SACE,WACI;AAAA,cACE,GAAG,SAAS;AAAA;AAAA;AAAA;AAAA,cAIZ,kBACE,2BACA;AAAA,YACJ,IACA;AAAA,YAEN,UAAU,SAAS,gBAAAA,KAAC,wBAAqB,UAAoB;AAAA,YAC7D,UACE,QAAQ,gBAAAA,KAAC,wBAAsB,GAAG,OAAO,IAAK;AAAA;AAAA,QAElD;AAAA,QACC,SAAS,gBAAAA,KAAC,SAAI,WAAU,QAAQ,kBAAO,IAAS;AAAA,SACnD;AAAA;AAAA,EACF;AAEJ;","names":["jsx","jsxs"]}
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/web-react/mention-pill.ts
|
|
2
|
+
var MENTION_PILL_CLASS = "rounded-md bg-primary/10 px-1 py-0.5 font-medium text-primary";
|
|
3
|
+
|
|
4
|
+
// src/web-react/mention-boundaries.ts
|
|
5
|
+
var PATH_CONTINUATION_CHAR = /[\p{L}\p{M}\p{N}._\-/]/u;
|
|
6
|
+
var WORD_CHAR = /[\p{L}\p{M}\p{N}]/u;
|
|
7
|
+
function charBefore(text, index) {
|
|
8
|
+
if (index <= 0) return void 0;
|
|
9
|
+
return Array.from(text.slice(Math.max(0, index - 2), index)).pop();
|
|
10
|
+
}
|
|
11
|
+
function charAt(text, index) {
|
|
12
|
+
if (index >= text.length) return void 0;
|
|
13
|
+
const codePoint = text.codePointAt(index);
|
|
14
|
+
return codePoint === void 0 ? void 0 : String.fromCodePoint(codePoint);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
MENTION_PILL_CLASS,
|
|
19
|
+
PATH_CONTINUATION_CHAR,
|
|
20
|
+
WORD_CHAR,
|
|
21
|
+
charBefore,
|
|
22
|
+
charAt
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=chunk-3HUFJ5LO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/web-react/mention-pill.ts","../src/web-react/mention-boundaries.ts"],"sourcesContent":["/**\n * Visual contract for a rendered mention pill. The TipTap extension in\n * `mention-editor.tsx` styles its inline atom node with this, and any other\n * surface that renders a resolved mention (e.g. a sent-message transcript)\n * uses the same constant so the two stay one visual contract instead of\n * silently drifting apart. Kept in its own module (no TipTap import) so\n * importing it never pulls the lazily-loaded editor chunk into a consumer's\n * bundle.\n */\nexport const MENTION_PILL_CLASS = 'rounded-md bg-primary/10 px-1 py-0.5 font-medium text-primary'\n","/**\n * The one boundary vocabulary for reading `@<path>` mention tokens out of\n * plain text. Two inverse readings share it — the transcript segmenter\n * (`chat-mentions.ts`) and editor-pill restore (`mention-serialize.ts`) — and\n * they must agree, or a token one accepts the other mangles. Kept OUT of the\n * `/web-react` barrel on purpose: these are internals of the grammar, not\n * public API.\n */\n\n/** A character that could plausibly continue the SAME path/filename past a\n * matched token. Without this lookahead a mention of `@a/b.md` would match\n * inside the unrelated `@a/b.md.bak` and split it mid-filename.\n *\n * Unicode-aware because the wire validator (`validateSandboxMentionPath`)\n * deliberately ALLOWS non-ASCII paths — in-box filenames are arbitrary. An\n * ASCII-only class here would accept input the readers then mangle.\n * `\\p{M}` keeps DECOMPOSED filenames whole: without it, a combining accent\n * (`a` + U+0301) reads as a boundary and splits the name after its base\n * letter. */\nexport const PATH_CONTINUATION_CHAR = /[\\p{L}\\p{M}\\p{N}._\\-/]/u\n\n/** A character that, immediately BEFORE an `@`, means the `@` is part of a\n * longer token (an email local part, a handle) rather than a mention start.\n * Unicode-aware for the same reasons, combining marks included. */\nexport const WORD_CHAR = /[\\p{L}\\p{M}\\p{N}]/u\n\n/** The full character (code point) ENDING just before `index`, or undefined\n * at the start. Indexing `text[index - 1]` hands a lone UTF-16 surrogate to\n * the Unicode-aware classes above, which then misread every astral letter —\n * boundary checks must see whole characters. `index` must be a code-point\n * boundary (both callers derive it from `@` positions and id lengths, which\n * are). */\nexport function charBefore(text: string, index: number): string | undefined {\n if (index <= 0) return undefined\n return Array.from(text.slice(Math.max(0, index - 2), index)).pop()\n}\n\n/** The full character (code point) starting at `index`, or undefined past the\n * end — same surrogate rationale and precondition as {@link charBefore}. */\nexport function charAt(text: string, index: number): string | undefined {\n if (index >= text.length) return undefined\n const codePoint = text.codePointAt(index)\n return codePoint === undefined ? undefined : String.fromCodePoint(codePoint)\n}\n"],"mappings":";AASO,IAAM,qBAAqB;;;ACU3B,IAAM,yBAAyB;AAK/B,IAAM,YAAY;AAQlB,SAAS,WAAW,MAAc,OAAmC;AAC1E,MAAI,SAAS,EAAG,QAAO;AACvB,SAAO,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI,GAAG,QAAQ,CAAC,GAAG,KAAK,CAAC,EAAE,IAAI;AACnE;AAIO,SAAS,OAAO,MAAc,OAAmC;AACtE,MAAI,SAAS,KAAK,OAAQ,QAAO;AACjC,QAAM,YAAY,KAAK,YAAY,KAAK;AACxC,SAAO,cAAc,SAAY,SAAY,OAAO,cAAc,SAAS;AAC7E;","names":[]}
|