@reforma/components 0.2.1 → 0.2.2
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/Button/Button.module.css +1 -1
- package/dist/List/Menu.d.ts.map +1 -1
- package/dist/List/Menu.js +98 -84
- package/dist/List/Menu.js.map +1 -1
- package/dist/chat/Chip/Chip.js +9 -9
- package/dist/chat/Chip/Chip.module.css.js +8 -8
- package/dist/chat/Chip/helpers/cursorLines.d.ts +1 -0
- package/dist/chat/Chip/helpers/cursorLines.d.ts.map +1 -1
- package/dist/chat/Chip/helpers/cursorLines.js +27 -21
- package/dist/chat/Chip/helpers/cursorLines.js.map +1 -1
- package/dist/chat/Chip/index.d.ts +1 -1
- package/dist/chat/Chip/index.d.ts.map +1 -1
- package/dist/chat/Chip/index.js +9 -8
- package/dist/chat/Message/segments/MessagePhaseSection.module.css +1 -1
- package/dist/chat/Message/streamdown/options.d.ts +2 -0
- package/dist/chat/Message/streamdown/options.d.ts.map +1 -1
- package/dist/chat/Message/streamdown/options.js +13 -12
- package/dist/chat/Message/streamdown/options.js.map +1 -1
- package/dist/chat/Message/turn/MessageUserBubble.d.ts.map +1 -1
- package/dist/chat/Message/turn/MessageUserBubble.js +57 -54
- package/dist/chat/Message/turn/MessageUserBubble.js.map +1 -1
- package/dist/chat/Tool/mountTool.d.ts.map +1 -1
- package/dist/chat/Tool/remove-file/RemoveFileTool.d.ts +1 -1
- package/dist/chat/Tool/remove-file/RemoveFileTool.d.ts.map +1 -1
- package/dist/chat/Tool/remove-file/RemoveFileTool.js +82 -38
- package/dist/chat/Tool/remove-file/RemoveFileTool.js.map +1 -1
- package/dist/chat/Tool/remove-file/RemoveFileTool.module.css +1 -0
- package/dist/chat/Tool/remove-file/RemoveFileTool.module.css.js +8 -0
- package/dist/chat/Tool/remove-file/RemoveFileTool.module.css.js.map +1 -0
- package/dist/chat/index.js +110 -109
- package/dist/index.js +417 -416
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sources":["../../../../src/chat/Message/streamdown/options.ts"],"sourcesContent":["import { cjk } from '@streamdown/cjk';\nimport { defaultRehypePlugins, type StreamdownProps } from 'streamdown';\n\nimport { streamdownComponents } from './components';\n\nconst sanitize = defaultRehypePlugins.sanitize as [unknown, { protocols?: { src?: readonly string[] } }];\n\
|
|
1
|
+
{"version":3,"file":"options.js","sources":["../../../../src/chat/Message/streamdown/options.ts"],"sourcesContent":["import { cjk } from '@streamdown/cjk';\nimport { defaultRehypePlugins, type StreamdownProps } from 'streamdown';\n\nimport { streamdownComponents } from './components';\n\nconst sanitize = defaultRehypePlugins.sanitize as [unknown, { protocols?: { src?: readonly string[] } }];\n\nconst rehypeSanitize = [\n sanitize[0],\n {\n ...sanitize[1],\n protocols: {\n ...sanitize[1].protocols,\n src: [...(sanitize[1].protocols?.src ?? []), 'data'],\n },\n },\n] as NonNullable<StreamdownProps['rehypePlugins']>[number];\n\n/** Sanitize + harden, no rehype-raw. HTML tags stay characters; markdown still renders. */\nexport const USER_MESSAGE_REHYPE_PLUGINS = [\n rehypeSanitize,\n defaultRehypePlugins.harden,\n] as NonNullable<StreamdownProps['rehypePlugins']>;\n\nexport const STREAMDOWN_OPTIONS = {\n plugins: { cjk },\n parseIncompleteMarkdown: true,\n caret: 'block',\n controls: false,\n rehypePlugins: [\n defaultRehypePlugins.raw,\n ...USER_MESSAGE_REHYPE_PLUGINS,\n ] as NonNullable<StreamdownProps['rehypePlugins']>,\n components: streamdownComponents,\n} satisfies StreamdownProps;\n"],"names":["sanitize","defaultRehypePlugins","rehypeSanitize","USER_MESSAGE_REHYPE_PLUGINS","STREAMDOWN_OPTIONS","cjk","streamdownComponents"],"mappings":";;;AAGA,MAAMA,IAAWC,EAAqB,UAChCC,IAAiB,CAACF,EAAS,CAAC,GAAG;AAAA,EACnC,GAAGA,EAAS,CAAC;AAAA,EACb,WAAW;AAAA,IACT,GAAGA,EAAS,CAAC,EAAE;AAAA,IACf,KAAK,CAAC,GAAIA,EAAS,CAAC,EAAE,WAAW,OAAO,CAAA,GAAK,MAAM;AAAA,EAAA;AAEvD,CAAC,GAGYG,IAA8B,CAACD,GAAgBD,EAAqB,MAAM,GAC1EG,IAAqB;AAAA,EAChC,SAAS;AAAA,IACP,KAAAC;AAAA,EAAA;AAAA,EAEF,yBAAyB;AAAA,EACzB,OAAO;AAAA,EACP,UAAU;AAAA,EACV,eAAe,CAACJ,EAAqB,KAAK,GAAGE,CAA2B;AAAA,EACxE,YAAYG;AACd;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageUserBubble.d.ts","sourceRoot":"","sources":["../../../../src/chat/Message/turn/MessageUserBubble.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MessageUserBubble.d.ts","sourceRoot":"","sources":["../../../../src/chat/Message/turn/MessageUserBubble.tsx"],"names":[],"mappings":"AA6BA,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAuPnD,wFAAwF;AACxF,eAAO,MAAM,iBAAiB;;CA4D5B,CAAC"}
|
|
@@ -1,42 +1,43 @@
|
|
|
1
|
-
import { cn as
|
|
2
|
-
import { resolveLayerCite as
|
|
1
|
+
import { cn as g } from "@reforma/lib";
|
|
2
|
+
import { resolveLayerCite as x, attachedLayerRefKey as E, formatLayerCite as v, codeEditorStateKey as M } from "@reforma/types";
|
|
3
3
|
import { observer as N } from "mobx-react-lite";
|
|
4
|
-
import { useState as
|
|
4
|
+
import { useState as L } from "react";
|
|
5
5
|
import { For as $ } from "../../../For/For.js";
|
|
6
6
|
import { Scrollable as w } from "../../../Scrollable/Scrollable.js";
|
|
7
7
|
import { ScrollExpandChevronButton as B } from "../../../Scrollable/ScrollExpandChevronButton.js";
|
|
8
8
|
import { Show as f } from "../../../Show/Show.js";
|
|
9
|
-
import { Badge as
|
|
10
|
-
import { useChat as
|
|
11
|
-
import { Chip as
|
|
12
|
-
import { chipItemFromPath as
|
|
13
|
-
import { fileCite as
|
|
9
|
+
import { Badge as A } from "../../../Tag/Badge.js";
|
|
10
|
+
import { useChat as P } from "../../ChatContext.js";
|
|
11
|
+
import { Chip as U } from "../../Chip/Chip.js";
|
|
12
|
+
import { chipItemFromPath as _ } from "../../Chip/helpers/chipPath.js";
|
|
13
|
+
import { clipLayerChipLabel as k, fileCite as R, fileChipDisplay as I } from "../../Chip/helpers/cursorLines.js";
|
|
14
14
|
import { MessageText as y } from "../streamdown/MessageText.js";
|
|
15
|
+
import { USER_MESSAGE_REHYPE_PLUGINS as C } from "../streamdown/options.js";
|
|
15
16
|
import i from "./Message.module.css.js";
|
|
16
|
-
import { useMessageTurn as
|
|
17
|
-
import { jsx as
|
|
18
|
-
const
|
|
17
|
+
import { useMessageTurn as F } from "./messageTurnContext.js";
|
|
18
|
+
import { jsx as a, jsxs as S } from "react/jsx-runtime";
|
|
19
|
+
const T = 500, b = {
|
|
19
20
|
expand: "Show full message",
|
|
20
21
|
collapse: "Show less"
|
|
21
22
|
};
|
|
22
|
-
function
|
|
23
|
-
const
|
|
23
|
+
function G(s) {
|
|
24
|
+
const l = _(s.path);
|
|
24
25
|
return {
|
|
25
26
|
id: M(s),
|
|
26
|
-
path:
|
|
27
|
+
path: l?.path ?? s.path,
|
|
27
28
|
label: I(s),
|
|
28
|
-
tooltip:
|
|
29
|
-
...
|
|
30
|
-
icon:
|
|
29
|
+
tooltip: l?.tooltip,
|
|
30
|
+
...l?.icon ? {
|
|
31
|
+
icon: l.icon
|
|
31
32
|
} : {},
|
|
32
33
|
...s.cursor ? {
|
|
33
34
|
cursor: s.cursor
|
|
34
35
|
} : {}
|
|
35
36
|
};
|
|
36
37
|
}
|
|
37
|
-
function
|
|
38
|
-
const n =
|
|
39
|
-
const r =
|
|
38
|
+
function j(s, l) {
|
|
39
|
+
const n = l?.attached?.files ?? [], p = l?.attached?.layers ?? [], m = [.../* @__PURE__ */ new Set([...l?.skills ?? [], ...l?.commands ?? []])], e = [...n.map((t) => {
|
|
40
|
+
const r = R(t);
|
|
40
41
|
return {
|
|
41
42
|
cite: r,
|
|
42
43
|
segment: {
|
|
@@ -111,33 +112,35 @@ function T(s, a) {
|
|
|
111
112
|
}
|
|
112
113
|
function d({
|
|
113
114
|
item: s,
|
|
114
|
-
onOpenPath:
|
|
115
|
+
onOpenPath: l
|
|
115
116
|
}) {
|
|
116
|
-
return /* @__PURE__ */
|
|
117
|
+
return /* @__PURE__ */ a(U, {
|
|
117
118
|
className: i.userCite,
|
|
118
119
|
item: s,
|
|
119
|
-
onAction: s.href ? void 0 :
|
|
120
|
+
onAction: s.href ? void 0 : l
|
|
120
121
|
});
|
|
121
122
|
}
|
|
122
|
-
function
|
|
123
|
+
function H({
|
|
123
124
|
text: s,
|
|
124
|
-
metadata:
|
|
125
|
+
metadata: l,
|
|
125
126
|
onOpenPath: n
|
|
126
127
|
}) {
|
|
127
|
-
const p =
|
|
128
|
-
return p.length === 0 ? null : !p.some((e) => e.type !== "text") && p[0]?.type === "text" ? /* @__PURE__ */
|
|
128
|
+
const p = j(s, l);
|
|
129
|
+
return p.length === 0 ? null : !p.some((e) => e.type !== "text") && p[0]?.type === "text" ? /* @__PURE__ */ a(y, {
|
|
129
130
|
className: i.userMessageBody,
|
|
130
131
|
mode: "static",
|
|
132
|
+
rehypePlugins: C,
|
|
131
133
|
children: p[0].value
|
|
132
|
-
}) : /* @__PURE__ */
|
|
133
|
-
className:
|
|
134
|
-
children: /* @__PURE__ */
|
|
134
|
+
}) : /* @__PURE__ */ a("div", {
|
|
135
|
+
className: g(i.userMessageBody, i.userMessageWithCites),
|
|
136
|
+
children: /* @__PURE__ */ a($, {
|
|
135
137
|
each: p,
|
|
136
|
-
children: (e, c) => e.type === "text" ? /* @__PURE__ */
|
|
138
|
+
children: (e, c) => e.type === "text" ? /* @__PURE__ */ a(y, {
|
|
137
139
|
className: i.userMessageFragment,
|
|
138
140
|
mode: "static",
|
|
141
|
+
rehypePlugins: C,
|
|
139
142
|
children: e.value
|
|
140
|
-
}, `t-${c}`) : e.type === "command" ? /* @__PURE__ */
|
|
143
|
+
}, `t-${c}`) : e.type === "command" ? /* @__PURE__ */ a(A, {
|
|
141
144
|
size: "xs",
|
|
142
145
|
color: "success",
|
|
143
146
|
value: e.skill,
|
|
@@ -145,10 +148,10 @@ function j({
|
|
|
145
148
|
"aria-label": e.cite,
|
|
146
149
|
className: i.userCite,
|
|
147
150
|
children: e.cite
|
|
148
|
-
}, `c-${e.cite}-${c}`) : e.type === "file" ? /* @__PURE__ */
|
|
149
|
-
item:
|
|
151
|
+
}, `c-${e.cite}-${c}`) : e.type === "file" ? /* @__PURE__ */ a(d, {
|
|
152
|
+
item: G(e.file),
|
|
150
153
|
onOpenPath: n
|
|
151
|
-
}, `f-${e.cite}-${c}`) : e.type === "link" ? /* @__PURE__ */
|
|
154
|
+
}, `f-${e.cite}-${c}`) : e.type === "link" ? /* @__PURE__ */ a(d, {
|
|
152
155
|
item: {
|
|
153
156
|
id: e.url,
|
|
154
157
|
type: "link",
|
|
@@ -157,11 +160,11 @@ function j({
|
|
|
157
160
|
href: e.url
|
|
158
161
|
},
|
|
159
162
|
onOpenPath: n
|
|
160
|
-
}, `u-${e.cite}-${c}`) : /* @__PURE__ */
|
|
163
|
+
}, `u-${e.cite}-${c}`) : /* @__PURE__ */ a(d, {
|
|
161
164
|
item: {
|
|
162
|
-
id:
|
|
165
|
+
id: E(e.layer),
|
|
163
166
|
type: "element",
|
|
164
|
-
label: e.layer.propName ? `${
|
|
167
|
+
label: k(e.layer.propName ? `${x(e.layer)}.${e.layer.propName}` : e.layer.text || e.layer.label || e.layer.layerId),
|
|
165
168
|
...e.layer.icon ? {
|
|
166
169
|
icon: e.layer.icon
|
|
167
170
|
} : {}
|
|
@@ -171,10 +174,10 @@ function j({
|
|
|
171
174
|
})
|
|
172
175
|
});
|
|
173
176
|
}
|
|
174
|
-
const
|
|
175
|
-
const s =
|
|
176
|
-
onOpenPath:
|
|
177
|
-
} =
|
|
177
|
+
const oe = N(() => {
|
|
178
|
+
const s = F(), {
|
|
179
|
+
onOpenPath: l
|
|
180
|
+
} = P(), [n, p] = L(!1);
|
|
178
181
|
if (s?.role !== "user" || s.message.role !== "user")
|
|
179
182
|
return null;
|
|
180
183
|
const {
|
|
@@ -183,22 +186,22 @@ const se = N(() => {
|
|
|
183
186
|
} = s, c = m.trim().length > 0, u = !!(e.metadata?.attached?.files?.length || e.metadata?.attached?.layers?.length || e.metadata?.skills?.length || e.metadata?.commands?.length);
|
|
184
187
|
if (!c && !u)
|
|
185
188
|
return null;
|
|
186
|
-
const t = /* @__PURE__ */
|
|
189
|
+
const t = /* @__PURE__ */ a(H, {
|
|
187
190
|
text: m,
|
|
188
191
|
metadata: e.metadata,
|
|
189
|
-
onOpenPath:
|
|
190
|
-
}), r = m.length >
|
|
191
|
-
return /* @__PURE__ */
|
|
192
|
-
className:
|
|
193
|
-
children: [/* @__PURE__ */
|
|
192
|
+
onOpenPath: l
|
|
193
|
+
}), r = m.length > T;
|
|
194
|
+
return /* @__PURE__ */ S("div", {
|
|
195
|
+
className: g(i.messageBubble, i.userBubble),
|
|
196
|
+
children: [/* @__PURE__ */ a(f, {
|
|
194
197
|
when: !r,
|
|
195
|
-
children: /* @__PURE__ */
|
|
198
|
+
children: /* @__PURE__ */ a("div", {
|
|
196
199
|
className: i.parts,
|
|
197
200
|
children: t
|
|
198
201
|
})
|
|
199
|
-
}), /* @__PURE__ */
|
|
202
|
+
}), /* @__PURE__ */ S(f, {
|
|
200
203
|
when: r,
|
|
201
|
-
children: [/* @__PURE__ */
|
|
204
|
+
children: [/* @__PURE__ */ a(w, {
|
|
202
205
|
vertical: !0,
|
|
203
206
|
edgeFade: !n,
|
|
204
207
|
className: i.userMessageScroll,
|
|
@@ -206,7 +209,7 @@ const se = N(() => {
|
|
|
206
209
|
contentClass: i.parts,
|
|
207
210
|
"aria-expanded": n,
|
|
208
211
|
children: t
|
|
209
|
-
}), /* @__PURE__ */
|
|
212
|
+
}), /* @__PURE__ */ a(B, {
|
|
210
213
|
expanded: n,
|
|
211
214
|
onPress: () => p((o) => !o),
|
|
212
215
|
labelExpand: b.expand,
|
|
@@ -217,7 +220,7 @@ const se = N(() => {
|
|
|
217
220
|
});
|
|
218
221
|
});
|
|
219
222
|
export {
|
|
220
|
-
|
|
221
|
-
|
|
223
|
+
T as MESSAGE_USER_COLLAPSE_MIN_CHARS,
|
|
224
|
+
oe as MessageUserBubble
|
|
222
225
|
};
|
|
223
226
|
//# sourceMappingURL=MessageUserBubble.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageUserBubble.js","sources":["../../../../src/chat/Message/turn/MessageUserBubble.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@reforma/lib';\nimport {\n attachedLayerRefKey,\n codeEditorStateKey,\n formatLayerCite,\n resolveLayerCite,\n type CodeEditorState,\n type SelectedLayerContext,\n} from '@reforma/types';\nimport { observer } from 'mobx-react-lite';\nimport { useState, type ReactNode } from 'react';\n\nimport { For } from '../../../For';\nimport { Scrollable, ScrollExpandChevronButton } from '../../../Scrollable';\nimport { Show } from '../../../Show';\nimport { Badge } from '../../../Tag/Badge';\nimport { useChat } from '../../ChatContext';\nimport { Chip, type ChipItem } from '../../Chip/Chip';\nimport { chipItemFromPath } from '../../Chip/helpers/chipPath';\nimport { fileChipDisplay, fileCite } from '../../Chip/helpers/cursorLines';\nimport { MessageText } from '../streamdown/MessageText';\nimport styles from './Message.module.css';\nimport { useMessageTurn } from './messageTurnContext';\n\nimport type { ReformaUserMessageMetadata } from '@reforma/types/sandbox';\n\nexport const MESSAGE_USER_COLLAPSE_MIN_CHARS = 500;\n\nconst USER_COLLAPSE_LABELS = {\n expand: 'Show full message',\n collapse: 'Show less',\n} as const;\n\ntype TextSegment = { type: 'text'; value: string };\ntype FileSegment = { type: 'file'; cite: string; file: CodeEditorState };\ntype LayerSegment = {\n type: 'layer';\n cite: string;\n layer: SelectedLayerContext;\n};\ntype CommandSegment = { type: 'command'; cite: string; skill: string };\ntype LinkSegment = { type: 'link'; cite: string; url: string; host: string };\ntype UserMessageSegment = TextSegment | FileSegment | LayerSegment | CommandSegment | LinkSegment;\n\nfunction fileCiteChipItem(file: CodeEditorState): ChipItem {\n const fromPath = chipItemFromPath(file.path);\n\n return {\n id: codeEditorStateKey(file),\n path: fromPath?.path ?? file.path,\n label: fileChipDisplay(file),\n tooltip: fromPath?.tooltip,\n ...(fromPath?.icon ? { icon: fromPath.icon } : {}),\n ...(file.cursor ? { cursor: file.cursor } : {}),\n };\n}\n\n/**\n * Split user prompt into text + chips for cites that appear in the prompt.\n * Forced meta pins (comment / ask-to-apply) stay in metadata for the agent — not rendered here.\n */\nfunction splitUserMessageSegments(\n text: string,\n metadata: ReformaUserMessageMetadata | undefined\n): UserMessageSegment[] {\n const files = metadata?.attached?.files ?? [];\n const layers = metadata?.attached?.layers ?? [];\n const slashNames = [...new Set([\n ...(metadata?.skills ?? []),\n ...(metadata?.commands ?? []),\n ])];\n\n const cites: Array<{ cite: string; segment: Exclude<UserMessageSegment, TextSegment> }> = [\n ...files.map((file) => {\n const cite = fileCite(file);\n\n return { cite, segment: { type: 'file' as const, cite, file } };\n }),\n ...layers.map((layer) => {\n const cite = formatLayerCite(layer);\n\n return { cite, segment: { type: 'layer' as const, cite, layer } };\n }),\n ...slashNames.map((raw) => {\n const name = raw.trim().replace(/^\\//, '');\n const cite = `/${ name }`;\n\n return { cite, segment: { type: 'command' as const, cite, skill: name } };\n }),\n ...[...text.matchAll(/@https?:\\/\\/[^\\s]+/gi)].map((match) => {\n const cite = match[0] ?? '';\n const url = cite.slice(1);\n let host = url;\n\n try {\n host = new URL(url).hostname.replace(/^www\\./, '') || url;\n }\n catch {\n // keep `url` as the chip label\n }\n\n return { cite, segment: { type: 'link' as const, cite, url, host } };\n }),\n ].sort((a, b) => b.cite.length - a.cite.length);\n\n if (cites.length === 0) {\n return text ? [{ type: 'text', value: text }] : [];\n }\n\n const segments: UserMessageSegment[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n let bestIdx = -1;\n let best: (typeof cites)[number] | undefined;\n\n for (const entry of cites) {\n const idx = remaining.indexOf(entry.cite);\n\n if (idx < 0) {\n continue;\n }\n\n if (\n bestIdx < 0\n || idx < bestIdx\n || (idx === bestIdx && entry.cite.length > (best?.cite.length ?? 0))\n ) {\n bestIdx = idx;\n best = entry;\n }\n }\n\n if (bestIdx < 0 || !best) {\n segments.push({ type: 'text', value: remaining });\n break;\n }\n\n if (bestIdx > 0) {\n segments.push({ type: 'text', value: remaining.slice(0, bestIdx) });\n }\n\n segments.push(best.segment);\n remaining = remaining.slice(bestIdx + best.cite.length);\n }\n\n return segments.filter(segment => segment.type !== 'text' || segment.value.length > 0);\n}\n\nfunction UserCiteChip({\n item,\n onOpenPath,\n}: {\n item: ChipItem;\n onOpenPath?: (item: ChipItem) => void;\n}): ReactNode {\n return (\n <Chip\n className={ styles.userCite }\n item={ item }\n onAction={ item.href ? undefined : onOpenPath }\n />\n );\n}\n\nfunction UserMessageBody({\n text,\n metadata,\n onOpenPath,\n}: {\n text: string;\n metadata: ReformaUserMessageMetadata | undefined;\n onOpenPath?: (item: ChipItem) => void;\n}): ReactNode {\n const segments = splitUserMessageSegments(text, metadata);\n\n if (segments.length === 0) {\n return null;\n }\n\n const hasCites = segments.some(segment => segment.type !== 'text');\n\n if (!hasCites && segments[0]?.type === 'text') {\n return (\n <MessageText\n className={ styles.userMessageBody }\n mode=\"static\"\n >\n { segments[0].value }\n </MessageText>\n );\n }\n\n return (\n <div className={ cn(styles.userMessageBody, styles.userMessageWithCites) }>\n <For each={ segments }>\n { (segment, index) => {\n if (segment.type === 'text') {\n return (\n <MessageText\n key={ `t-${ index }` }\n className={ styles.userMessageFragment }\n mode=\"static\"\n >\n { segment.value }\n </MessageText>\n );\n }\n\n if (segment.type === 'command') {\n return (\n <Badge\n key={ `c-${ segment.cite }-${ index }` }\n size=\"xs\"\n color=\"success\"\n value={ segment.skill }\n textValue={ segment.cite }\n aria-label={ segment.cite }\n className={ styles.userCite }\n >\n { segment.cite }\n </Badge>\n );\n }\n\n if (segment.type === 'file') {\n return (\n <UserCiteChip\n key={ `f-${ segment.cite }-${ index }` }\n item={ fileCiteChipItem(segment.file) }\n onOpenPath={ onOpenPath }\n />\n );\n }\n\n if (segment.type === 'link') {\n return (\n <UserCiteChip\n key={ `u-${ segment.cite }-${ index }` }\n item={ {\n id: segment.url,\n type: 'link',\n label: segment.host,\n tooltip: segment.url,\n href: segment.url,\n } }\n onOpenPath={ onOpenPath }\n />\n );\n }\n\n return (\n <UserCiteChip\n key={ `l-${ segment.cite }-${ index }` }\n item={ {\n id: attachedLayerRefKey(segment.layer),\n type: 'element',\n label: segment.layer.propName\n ? `${ resolveLayerCite(segment.layer) }.${ segment.layer.propName }`\n : (segment.layer.text || segment.layer.label || segment.layer.layerId),\n ...(segment.layer.icon ? { icon: segment.layer.icon } : {}),\n } }\n onOpenPath={ onOpenPath }\n />\n );\n } }\n </For>\n </div>\n );\n}\n\n/** User turn text bubble with collapsible long messages. Renders nothing when empty. */\nexport const MessageUserBubble = observer(() => {\n const turn = useMessageTurn();\n const { onOpenPath } = useChat();\n const [expanded, setExpanded] = useState(false);\n\n if (turn?.role !== 'user' || turn.message.role !== 'user') {\n return null;\n }\n\n const { text, message } = turn;\n const hasText = text.trim().length > 0;\n const hasAttached = Boolean(\n message.metadata?.attached?.files?.length\n || message.metadata?.attached?.layers?.length\n || message.metadata?.skills?.length\n || message.metadata?.commands?.length\n );\n\n if (!hasText && !hasAttached) {\n return null;\n }\n\n const body = (\n <UserMessageBody\n text={ text }\n metadata={ message.metadata }\n onOpenPath={ onOpenPath }\n />\n );\n const collapsible = text.length > MESSAGE_USER_COLLAPSE_MIN_CHARS;\n\n return (\n <div className={ cn(styles.messageBubble, styles.userBubble) }>\n <Show when={ !collapsible }>\n <div className={ styles.parts }>\n { body }\n </div>\n </Show>\n\n <Show when={ collapsible }>\n <Scrollable\n vertical\n edgeFade={ !expanded }\n className={ styles.userMessageScroll }\n containerClass={ styles.userMessageScrollPort }\n contentClass={ styles.parts }\n aria-expanded={ expanded }\n >\n { body }\n </Scrollable>\n <ScrollExpandChevronButton\n expanded={ expanded }\n onPress={ () => setExpanded(v => !v) }\n labelExpand={ USER_COLLAPSE_LABELS.expand }\n labelCollapse={ USER_COLLAPSE_LABELS.collapse }\n className={ styles.userMessageExpandToggle }\n />\n </Show>\n </div>\n );\n});\n"],"names":["MESSAGE_USER_COLLAPSE_MIN_CHARS","USER_COLLAPSE_LABELS","fileCiteChipItem","file","fromPath","chipItemFromPath","codeEditorStateKey","fileChipDisplay","splitUserMessageSegments","text","metadata","files","layers","slashNames","cites","cite","fileCite","layer","formatLayerCite","raw","name","match","url","host","a","b","segments","remaining","bestIdx","best","entry","idx","segment","UserCiteChip","item","onOpenPath","Chip","styles","UserMessageBody","MessageText","cn","For","index","Badge","attachedLayerRefKey","resolveLayerCite","MessageUserBubble","observer","turn","useMessageTurn","useChat","expanded","setExpanded","useState","message","hasText","hasAttached","body","collapsible","_jsx","Show","_jsxs","Scrollable","ScrollExpandChevronButton","v"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MessageUserBubble.js","sources":["../../../../src/chat/Message/turn/MessageUserBubble.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@reforma/lib';\nimport {\n attachedLayerRefKey,\n codeEditorStateKey,\n formatLayerCite,\n resolveLayerCite,\n type CodeEditorState,\n type SelectedLayerContext,\n} from '@reforma/types';\nimport { observer } from 'mobx-react-lite';\nimport { useState, type ReactNode } from 'react';\n\nimport { For } from '../../../For';\nimport { Scrollable, ScrollExpandChevronButton } from '../../../Scrollable';\nimport { Show } from '../../../Show';\nimport { Badge } from '../../../Tag/Badge';\nimport { useChat } from '../../ChatContext';\nimport { Chip, type ChipItem } from '../../Chip/Chip';\nimport { chipItemFromPath } from '../../Chip/helpers/chipPath';\nimport { clipLayerChipLabel, fileChipDisplay, fileCite } from '../../Chip/helpers/cursorLines';\nimport { MessageText } from '../streamdown/MessageText';\nimport { USER_MESSAGE_REHYPE_PLUGINS } from '../streamdown/options';\nimport styles from './Message.module.css';\nimport { useMessageTurn } from './messageTurnContext';\n\nimport type { ReformaUserMessageMetadata } from '@reforma/types/sandbox';\n\nexport const MESSAGE_USER_COLLAPSE_MIN_CHARS = 500;\n\nconst USER_COLLAPSE_LABELS = {\n expand: 'Show full message',\n collapse: 'Show less',\n} as const;\n\ntype TextSegment = { type: 'text'; value: string };\ntype FileSegment = { type: 'file'; cite: string; file: CodeEditorState };\ntype LayerSegment = {\n type: 'layer';\n cite: string;\n layer: SelectedLayerContext;\n};\ntype CommandSegment = { type: 'command'; cite: string; skill: string };\ntype LinkSegment = { type: 'link'; cite: string; url: string; host: string };\ntype UserMessageSegment = TextSegment | FileSegment | LayerSegment | CommandSegment | LinkSegment;\n\nfunction fileCiteChipItem(file: CodeEditorState): ChipItem {\n const fromPath = chipItemFromPath(file.path);\n\n return {\n id: codeEditorStateKey(file),\n path: fromPath?.path ?? file.path,\n label: fileChipDisplay(file),\n tooltip: fromPath?.tooltip,\n ...(fromPath?.icon ? { icon: fromPath.icon } : {}),\n ...(file.cursor ? { cursor: file.cursor } : {}),\n };\n}\n\n/**\n * Split user prompt into text + chips for cites that appear in the prompt.\n * Forced meta pins (comment / ask-to-apply) stay in metadata for the agent — not rendered here.\n */\nfunction splitUserMessageSegments(\n text: string,\n metadata: ReformaUserMessageMetadata | undefined\n): UserMessageSegment[] {\n const files = metadata?.attached?.files ?? [];\n const layers = metadata?.attached?.layers ?? [];\n const slashNames = [...new Set([\n ...(metadata?.skills ?? []),\n ...(metadata?.commands ?? []),\n ])];\n\n const cites: Array<{ cite: string; segment: Exclude<UserMessageSegment, TextSegment> }> = [\n ...files.map((file) => {\n const cite = fileCite(file);\n\n return { cite, segment: { type: 'file' as const, cite, file } };\n }),\n ...layers.map((layer) => {\n const cite = formatLayerCite(layer);\n\n return { cite, segment: { type: 'layer' as const, cite, layer } };\n }),\n ...slashNames.map((raw) => {\n const name = raw.trim().replace(/^\\//, '');\n const cite = `/${ name }`;\n\n return { cite, segment: { type: 'command' as const, cite, skill: name } };\n }),\n ...[...text.matchAll(/@https?:\\/\\/[^\\s]+/gi)].map((match) => {\n const cite = match[0] ?? '';\n const url = cite.slice(1);\n let host = url;\n\n try {\n host = new URL(url).hostname.replace(/^www\\./, '') || url;\n }\n catch {\n // keep `url` as the chip label\n }\n\n return { cite, segment: { type: 'link' as const, cite, url, host } };\n }),\n ].sort((a, b) => b.cite.length - a.cite.length);\n\n if (cites.length === 0) {\n return text ? [{ type: 'text', value: text }] : [];\n }\n\n const segments: UserMessageSegment[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n let bestIdx = -1;\n let best: (typeof cites)[number] | undefined;\n\n for (const entry of cites) {\n const idx = remaining.indexOf(entry.cite);\n\n if (idx < 0) {\n continue;\n }\n\n if (\n bestIdx < 0\n || idx < bestIdx\n || (idx === bestIdx && entry.cite.length > (best?.cite.length ?? 0))\n ) {\n bestIdx = idx;\n best = entry;\n }\n }\n\n if (bestIdx < 0 || !best) {\n segments.push({ type: 'text', value: remaining });\n break;\n }\n\n if (bestIdx > 0) {\n segments.push({ type: 'text', value: remaining.slice(0, bestIdx) });\n }\n\n segments.push(best.segment);\n remaining = remaining.slice(bestIdx + best.cite.length);\n }\n\n return segments.filter(segment => segment.type !== 'text' || segment.value.length > 0);\n}\n\nfunction UserCiteChip({\n item,\n onOpenPath,\n}: {\n item: ChipItem;\n onOpenPath?: (item: ChipItem) => void;\n}): ReactNode {\n return (\n <Chip\n className={ styles.userCite }\n item={ item }\n onAction={ item.href ? undefined : onOpenPath }\n />\n );\n}\n\nfunction UserMessageBody({\n text,\n metadata,\n onOpenPath,\n}: {\n text: string;\n metadata: ReformaUserMessageMetadata | undefined;\n onOpenPath?: (item: ChipItem) => void;\n}): ReactNode {\n const segments = splitUserMessageSegments(text, metadata);\n\n if (segments.length === 0) {\n return null;\n }\n\n const hasCites = segments.some(segment => segment.type !== 'text');\n\n if (!hasCites && segments[0]?.type === 'text') {\n return (\n <MessageText\n className={ styles.userMessageBody }\n mode=\"static\"\n rehypePlugins={ USER_MESSAGE_REHYPE_PLUGINS }\n >\n { segments[0].value }\n </MessageText>\n );\n }\n\n return (\n <div className={ cn(styles.userMessageBody, styles.userMessageWithCites) }>\n <For each={ segments }>\n { (segment, index) => {\n if (segment.type === 'text') {\n return (\n <MessageText\n key={ `t-${ index }` }\n className={ styles.userMessageFragment }\n mode=\"static\"\n rehypePlugins={ USER_MESSAGE_REHYPE_PLUGINS }\n >\n { segment.value }\n </MessageText>\n );\n }\n\n if (segment.type === 'command') {\n return (\n <Badge\n key={ `c-${ segment.cite }-${ index }` }\n size=\"xs\"\n color=\"success\"\n value={ segment.skill }\n textValue={ segment.cite }\n aria-label={ segment.cite }\n className={ styles.userCite }\n >\n { segment.cite }\n </Badge>\n );\n }\n\n if (segment.type === 'file') {\n return (\n <UserCiteChip\n key={ `f-${ segment.cite }-${ index }` }\n item={ fileCiteChipItem(segment.file) }\n onOpenPath={ onOpenPath }\n />\n );\n }\n\n if (segment.type === 'link') {\n return (\n <UserCiteChip\n key={ `u-${ segment.cite }-${ index }` }\n item={ {\n id: segment.url,\n type: 'link',\n label: segment.host,\n tooltip: segment.url,\n href: segment.url,\n } }\n onOpenPath={ onOpenPath }\n />\n );\n }\n\n return (\n <UserCiteChip\n key={ `l-${ segment.cite }-${ index }` }\n item={ {\n id: attachedLayerRefKey(segment.layer),\n type: 'element',\n label: clipLayerChipLabel(segment.layer.propName\n ? `${ resolveLayerCite(segment.layer) }.${ segment.layer.propName }`\n : (segment.layer.text || segment.layer.label || segment.layer.layerId)),\n ...(segment.layer.icon ? { icon: segment.layer.icon } : {}),\n } }\n onOpenPath={ onOpenPath }\n />\n );\n } }\n </For>\n </div>\n );\n}\n\n/** User turn text bubble with collapsible long messages. Renders nothing when empty. */\nexport const MessageUserBubble = observer(() => {\n const turn = useMessageTurn();\n const { onOpenPath } = useChat();\n const [expanded, setExpanded] = useState(false);\n\n if (turn?.role !== 'user' || turn.message.role !== 'user') {\n return null;\n }\n\n const { text, message } = turn;\n const hasText = text.trim().length > 0;\n const hasAttached = Boolean(\n message.metadata?.attached?.files?.length\n || message.metadata?.attached?.layers?.length\n || message.metadata?.skills?.length\n || message.metadata?.commands?.length\n );\n\n if (!hasText && !hasAttached) {\n return null;\n }\n\n const body = (\n <UserMessageBody\n text={ text }\n metadata={ message.metadata }\n onOpenPath={ onOpenPath }\n />\n );\n const collapsible = text.length > MESSAGE_USER_COLLAPSE_MIN_CHARS;\n\n return (\n <div className={ cn(styles.messageBubble, styles.userBubble) }>\n <Show when={ !collapsible }>\n <div className={ styles.parts }>\n { body }\n </div>\n </Show>\n\n <Show when={ collapsible }>\n <Scrollable\n vertical\n edgeFade={ !expanded }\n className={ styles.userMessageScroll }\n containerClass={ styles.userMessageScrollPort }\n contentClass={ styles.parts }\n aria-expanded={ expanded }\n >\n { body }\n </Scrollable>\n <ScrollExpandChevronButton\n expanded={ expanded }\n onPress={ () => setExpanded(v => !v) }\n labelExpand={ USER_COLLAPSE_LABELS.expand }\n labelCollapse={ USER_COLLAPSE_LABELS.collapse }\n className={ styles.userMessageExpandToggle }\n />\n </Show>\n </div>\n );\n});\n"],"names":["MESSAGE_USER_COLLAPSE_MIN_CHARS","USER_COLLAPSE_LABELS","fileCiteChipItem","file","fromPath","chipItemFromPath","codeEditorStateKey","fileChipDisplay","splitUserMessageSegments","text","metadata","files","layers","slashNames","cites","cite","fileCite","layer","formatLayerCite","raw","name","match","url","host","a","b","segments","remaining","bestIdx","best","entry","idx","segment","UserCiteChip","item","onOpenPath","Chip","styles","UserMessageBody","MessageText","USER_MESSAGE_REHYPE_PLUGINS","cn","For","index","Badge","attachedLayerRefKey","clipLayerChipLabel","resolveLayerCite","MessageUserBubble","observer","turn","useMessageTurn","useChat","expanded","setExpanded","useState","message","hasText","hasAttached","body","collapsible","_jsx","Show","_jsxs","Scrollable","ScrollExpandChevronButton","v"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mountTool.d.ts","sourceRoot":"","sources":["../../../src/chat/Tool/mountTool.tsx"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG5C,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS;
|
|
1
|
+
{"version":3,"file":"mountTool.d.ts","sourceRoot":"","sources":["../../../src/chat/Tool/mountTool.tsx"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG5C,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS;IAgCjC,QAAQ;IACR,OAAO;EAWd"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ToolRendererProps } from '../types';
|
|
2
|
-
/** RemoveFile:
|
|
2
|
+
/** RemoveFile: one path stays a chip. Several collapse to a count that opens the list. */
|
|
3
3
|
export declare function RemoveFileTool({ part }: ToolRendererProps): import("react").JSX.Element | null;
|
|
4
4
|
//# sourceMappingURL=RemoveFileTool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoveFileTool.d.ts","sourceRoot":"","sources":["../../../../src/chat/Tool/remove-file/RemoveFileTool.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RemoveFileTool.d.ts","sourceRoot":"","sources":["../../../../src/chat/Tool/remove-file/RemoveFileTool.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAuElD,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,EAAE,iBAAiB,sCAqCzD"}
|
|
@@ -1,58 +1,102 @@
|
|
|
1
1
|
import { Trash as s } from "@reforma/icons/14";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
2
|
+
import { plural as u, cn as a } from "@reforma/lib";
|
|
3
|
+
import { isToolUIPart as p, getToolName as f } from "ai";
|
|
4
|
+
import { Box as c } from "../../../Box/Box.js";
|
|
5
|
+
import { For as h } from "../../../For/For.js";
|
|
6
|
+
import { Pressable as d } from "react-aria-components";
|
|
7
|
+
import { Show as v } from "../../../Show/Show.js";
|
|
8
|
+
import { Text as T } from "../../../Text/Text.js";
|
|
9
|
+
import { Chip as g } from "../../Chip/Chip.js";
|
|
10
|
+
import { ChipContent as F } from "../../Chip/ChipContent.js";
|
|
11
|
+
import { chipItemFromPath as R } from "../../Chip/helpers/chipPath.js";
|
|
12
|
+
import b from "../../Chip/Chip.module.css.js";
|
|
13
|
+
import { getToolFailureRowState as x, removeFileLinesRemoved as P } from "../helpers.js";
|
|
14
|
+
import { ToolLineCounts as y } from "../shell/ToolLineCounts.js";
|
|
15
|
+
import { ToolPathListPopover as S } from "../shell/ToolPathListHoverCard.js";
|
|
16
|
+
import { ToolShell as j, ToolShellHeader as C, ToolShellFooter as I } from "../shell/ToolShell.js";
|
|
17
|
+
import { parseRemoveFileInput as w } from "./parseRemoveFileInput.js";
|
|
18
|
+
import L from "./RemoveFileTool.module.css.js";
|
|
19
|
+
import { jsxs as l, jsx as e } from "react/jsx-runtime";
|
|
20
|
+
function A(o) {
|
|
21
|
+
if (o == null || typeof o != "object")
|
|
22
|
+
return [];
|
|
23
|
+
const i = o.results;
|
|
24
|
+
return Array.isArray(i) ? i.flatMap((r) => {
|
|
25
|
+
if (r == null || typeof r != "object")
|
|
26
|
+
return [];
|
|
27
|
+
const t = r.path;
|
|
28
|
+
return typeof t == "string" && t.trim() !== "" ? [t] : [];
|
|
29
|
+
}) : [];
|
|
30
|
+
}
|
|
31
|
+
function N({
|
|
32
|
+
paths: o
|
|
16
33
|
}) {
|
|
17
|
-
|
|
34
|
+
return o.length > 1 ? /* @__PURE__ */ e(S, {
|
|
35
|
+
trigger: /* @__PURE__ */ e(d, {
|
|
36
|
+
children: /* @__PURE__ */ e("button", {
|
|
37
|
+
type: "button",
|
|
38
|
+
className: a(b.chip, L.count),
|
|
39
|
+
"data-chip": !0,
|
|
40
|
+
"data-interactive": !0,
|
|
41
|
+
children: /* @__PURE__ */ e(F, {
|
|
42
|
+
item: {
|
|
43
|
+
label: u(o.length, "file", "files")
|
|
44
|
+
},
|
|
45
|
+
icon: null,
|
|
46
|
+
tooltip: !1
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
}),
|
|
50
|
+
paths: o
|
|
51
|
+
}) : /* @__PURE__ */ e(c, {
|
|
52
|
+
direction: "row",
|
|
53
|
+
gap: "xs",
|
|
54
|
+
wrap: !0,
|
|
55
|
+
children: /* @__PURE__ */ e(h, {
|
|
56
|
+
each: [...o],
|
|
57
|
+
children: (i, r) => {
|
|
58
|
+
const t = R(i);
|
|
59
|
+
return t ? /* @__PURE__ */ e(g, {
|
|
60
|
+
item: t
|
|
61
|
+
}, t.id ?? r) : null;
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function _({
|
|
67
|
+
part: o
|
|
68
|
+
}) {
|
|
69
|
+
if (!p(o) || f(o) !== "RemoveFile")
|
|
18
70
|
return null;
|
|
19
|
-
const i =
|
|
20
|
-
return /* @__PURE__ */ l(
|
|
71
|
+
const i = o.state, r = x(o), t = A(o.output), n = t.length > 0 ? t : w(o.input).filePaths, m = i === "output-available" ? P(o.output) : void 0;
|
|
72
|
+
return /* @__PURE__ */ l(j, {
|
|
21
73
|
"data-slot": "remove-file-tool",
|
|
22
|
-
children: [/* @__PURE__ */ l(
|
|
74
|
+
children: [/* @__PURE__ */ l(C, {
|
|
23
75
|
state: i,
|
|
24
|
-
statusDetail:
|
|
76
|
+
statusDetail: r.tooltip,
|
|
25
77
|
title: "Removed",
|
|
26
78
|
titleInProgress: "Removing",
|
|
27
|
-
icon: /* @__PURE__ */
|
|
79
|
+
icon: /* @__PURE__ */ e(s, {
|
|
28
80
|
"aria-hidden": !0
|
|
29
81
|
}),
|
|
30
|
-
children: [/* @__PURE__ */
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
children: /* @__PURE__ */ o(f, {
|
|
35
|
-
each: m,
|
|
36
|
-
children: (e, a) => /* @__PURE__ */ o(v, {
|
|
37
|
-
item: e
|
|
38
|
-
}, e.id ?? e.path ?? a)
|
|
39
|
-
})
|
|
40
|
-
}), /* @__PURE__ */ o(R, {
|
|
41
|
-
removed: n
|
|
82
|
+
children: [/* @__PURE__ */ e(N, {
|
|
83
|
+
paths: n
|
|
84
|
+
}), /* @__PURE__ */ e(y, {
|
|
85
|
+
removed: m
|
|
42
86
|
})]
|
|
43
|
-
}), /* @__PURE__ */
|
|
44
|
-
when:
|
|
45
|
-
children: /* @__PURE__ */
|
|
46
|
-
children: /* @__PURE__ */
|
|
87
|
+
}), /* @__PURE__ */ e(v, {
|
|
88
|
+
when: r.problemText,
|
|
89
|
+
children: /* @__PURE__ */ e(I, {
|
|
90
|
+
children: /* @__PURE__ */ e(T, {
|
|
47
91
|
color: "danger",
|
|
48
92
|
variant: "xs",
|
|
49
|
-
children:
|
|
93
|
+
children: r.problemText
|
|
50
94
|
})
|
|
51
95
|
})
|
|
52
96
|
})]
|
|
53
97
|
});
|
|
54
98
|
}
|
|
55
99
|
export {
|
|
56
|
-
|
|
100
|
+
_ as RemoveFileTool
|
|
57
101
|
};
|
|
58
102
|
//# sourceMappingURL=RemoveFileTool.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoveFileTool.js","sources":["../../../../src/chat/Tool/remove-file/RemoveFileTool.tsx"],"sourcesContent":["import { Trash } from '@reforma/icons/14';\nimport { getToolName, isToolUIPart } from 'ai';\n\nimport { Box } from '../../../Box';\nimport { For } from '../../../For';\nimport { Show } from '../../../Show';\nimport { Text } from '../../../Text';\nimport { Chip, chipItemFromPath } from '../../Chip';\nimport { getToolFailureRowState, removeFileLinesRemoved } from '../helpers';\nimport { ToolLineCounts, ToolShell, ToolShellFooter, ToolShellHeader } from '../shell';\nimport { parseRemoveFileInput } from './parseRemoveFileInput';\n\nimport type { ToolRendererProps } from '../types';\n\
|
|
1
|
+
{"version":3,"file":"RemoveFileTool.js","sources":["../../../../src/chat/Tool/remove-file/RemoveFileTool.tsx"],"sourcesContent":["import { Trash } from '@reforma/icons/14';\nimport { cn, plural } from '@reforma/lib';\nimport { getToolName, isToolUIPart } from 'ai';\n\nimport { Box } from '../../../Box';\nimport { For } from '../../../For';\nimport { Pressable } from '../../../Pressable';\nimport { Show } from '../../../Show';\nimport { Text } from '../../../Text';\nimport { Chip, ChipContent, chipItemFromPath } from '../../Chip';\nimport chipStyles from '../../Chip/Chip.module.css';\nimport { getToolFailureRowState, removeFileLinesRemoved } from '../helpers';\nimport { ToolLineCounts, ToolPathListPopover, ToolShell, ToolShellFooter, ToolShellHeader } from '../shell';\nimport { parseRemoveFileInput } from './parseRemoveFileInput';\nimport styles from './RemoveFileTool.module.css';\n\nimport type { ToolRendererProps } from '../types';\n\nfunction pathsFromRemoveOutput(output: unknown): string[] {\n if (output == null || typeof output !== 'object') {\n return [];\n }\n\n const results = (output as { results?: unknown }).results;\n\n if (!Array.isArray(results)) {\n return [];\n }\n\n return results.flatMap((row) => {\n if (row == null || typeof row !== 'object') {\n return [];\n }\n\n const path = (row as { path?: unknown }).path;\n\n return typeof path === 'string' && path.trim() !== '' ? [path] : [];\n });\n}\n\nfunction RemoveFilePaths({ paths }: { paths: readonly string[] }) {\n if (paths.length > 1) {\n return (\n <ToolPathListPopover\n trigger={ (\n <Pressable>\n <button\n type=\"button\"\n className={ cn(chipStyles.chip, styles.count) }\n data-chip\n data-interactive\n >\n <ChipContent\n item={{ label: plural(paths.length, 'file', 'files') }}\n icon={ null }\n tooltip={ false }\n />\n </button>\n </Pressable>\n ) }\n paths={ paths }\n />\n );\n }\n\n return (\n <Box direction=\"row\" gap=\"xs\" wrap>\n <For each={ [...paths] }>\n { (path, index) => {\n const item = chipItemFromPath(path);\n\n if (!item) {\n return null;\n }\n\n return (\n <Chip\n key={ item.id ?? index }\n item={ item }\n />\n );\n } }\n </For>\n </Box>\n );\n}\n\n/** RemoveFile: one path stays a chip. Several collapse to a count that opens the list. */\nexport function RemoveFileTool({ part }: ToolRendererProps) {\n if (!isToolUIPart(part) || getToolName(part) !== 'RemoveFile') {\n return null;\n }\n\n const state = part.state;\n const failure = getToolFailureRowState(part);\n const outputPaths = pathsFromRemoveOutput(part.output);\n const paths = outputPaths.length > 0\n ? outputPaths\n : parseRemoveFileInput(part.input).filePaths;\n\n const linesRemoved = state === 'output-available'\n ? removeFileLinesRemoved(part.output)\n : undefined;\n\n return (\n <ToolShell data-slot=\"remove-file-tool\">\n <ToolShellHeader\n state={ state }\n statusDetail={ failure.tooltip }\n title=\"Removed\"\n titleInProgress=\"Removing\"\n icon={ <Trash aria-hidden /> }\n >\n <RemoveFilePaths paths={ paths } />\n\n <ToolLineCounts removed={ linesRemoved } />\n </ToolShellHeader>\n\n <Show when={ failure.problemText }>\n <ToolShellFooter>\n <Text color=\"danger\" variant=\"xs\">{failure.problemText}</Text>\n </ToolShellFooter>\n </Show>\n </ToolShell>\n );\n}\n"],"names":["pathsFromRemoveOutput","output","results","row","path","RemoveFilePaths","paths","ToolPathListPopover","Pressable","cn","chipStyles","styles","ChipContent","plural","Box","For","index","item","chipItemFromPath","Chip","RemoveFileTool","part","isToolUIPart","getToolName","state","failure","getToolFailureRowState","outputPaths","parseRemoveFileInput","linesRemoved","removeFileLinesRemoved","ToolShell","_jsxs","ToolShellHeader","Trash","_jsx","ToolLineCounts","Show","ToolShellFooter","Text"],"mappings":";;;;;;;;;;;;;;;;;;;AAeA,SAASA,EAAsBC,GAAQ;AACrC,MAAIA,KAAU,QAAQ,OAAOA,KAAW;AACtC,WAAO,CAAA;AAET,QAAMC,IAAUD,EAAO;AACvB,SAAK,MAAM,QAAQC,CAAO,IAGnBA,EAAQ,QAAQ,CAAAC,MAAO;AAC5B,QAAIA,KAAO,QAAQ,OAAOA,KAAQ;AAChC,aAAO,CAAA;AAET,UAAMC,IAAOD,EAAI;AACjB,WAAO,OAAOC,KAAS,YAAYA,EAAK,KAAA,MAAW,KAAK,CAACA,CAAI,IAAI,CAAA;AAAA,EACnE,CAAC,IARQ,CAAA;AASX;AACA,SAASC,EAAgB;AAAA,EACvB,OAAAC;AACF,GAAG;AACD,SAAIA,EAAM,SAAS,sBACQC,GAAqB;AAAA,IAC5C,2BAA2BC,GAAW;AAAA,MACpC,4BAA4B,UAAU;AAAA,QACpC,MAAM;AAAA,QACN,WAAWC,EAAGC,EAAW,MAAMC,EAAO,KAAK;AAAA,QAC3C,aAAa;AAAA,QACb,oBAAoB;AAAA,QACpB,4BAA4BC,GAAa;AAAA,UACvC,MAAM;AAAA,YACJ,OAAOC,EAAOP,EAAM,QAAQ,QAAQ,OAAO;AAAA,UAAA;AAAA,UAE7C,MAAM;AAAA,UACN,SAAS;AAAA,QAAA,CACV;AAAA,MAAA,CACF;AAAA,IAAA,CACF;AAAA,IACD,OAAAA;AAAA,EAAA,CACD,sBAEsBQ,GAAK;AAAA,IAC5B,WAAW;AAAA,IACX,KAAK;AAAA,IACL,MAAM;AAAA,IACN,4BAA4BC,GAAK;AAAA,MAC/B,MAAM,CAAC,GAAGT,CAAK;AAAA,MACf,UAAU,CAACF,GAAMY,MAAU;AACzB,cAAMC,IAAOC,EAAiBd,CAAI;AAClC,eAAKa,sBAGoBE,GAAM;AAAA,UAC7B,MAAAF;AAAA,QAAA,GACCA,EAAK,MAAMD,CAAK,IAJV;AAAA,MAKX;AAAA,IAAA,CACD;AAAA,EAAA,CACF;AACH;AAGO,SAASI,EAAe;AAAA,EAC7B,MAAAC;AACF,GAAG;AACD,MAAI,CAACC,EAAaD,CAAI,KAAKE,EAAYF,CAAI,MAAM;AAC/C,WAAO;AAET,QAAMG,IAAQH,EAAK,OACbI,IAAUC,EAAuBL,CAAI,GACrCM,IAAc3B,EAAsBqB,EAAK,MAAM,GAC/Cf,IAAQqB,EAAY,SAAS,IAAIA,IAAcC,EAAqBP,EAAK,KAAK,EAAE,WAChFQ,IAAeL,MAAU,qBAAqBM,EAAuBT,EAAK,MAAM,IAAI;AAC1F,2BAA0BU,GAAW;AAAA,IACnC,aAAa;AAAA,IACb,UAAU,CAAcC,gBAAAA,EAAMC,GAAiB;AAAA,MAC7C,OAAAT;AAAA,MACA,cAAcC,EAAQ;AAAA,MACtB,OAAO;AAAA,MACP,iBAAiB;AAAA,MACjB,wBAAwBS,GAAO;AAAA,QAC7B,eAAe;AAAA,MAAA,CAChB;AAAA,MACD,UAAU,CAAcC,gBAAAA,EAAK9B,GAAiB;AAAA,QAC5C,OAAAC;AAAA,MAAA,CACD,GAAgB6B,gBAAAA,EAAKC,GAAgB;AAAA,QACpC,SAASP;AAAA,MAAA,CACV,CAAC;AAAA,IAAA,CACH,GAAgBM,gBAAAA,EAAKE,GAAM;AAAA,MAC1B,MAAMZ,EAAQ;AAAA,MACd,4BAA4Ba,GAAiB;AAAA,QAC3C,4BAA4BC,GAAM;AAAA,UAChC,OAAO;AAAA,UACP,SAAS;AAAA,UACT,UAAUd,EAAQ;AAAA,QAAA,CACnB;AAAA,MAAA,CACF;AAAA,IAAA,CACF,CAAC;AAAA,EAAA,CACH;AACH;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer components{.RemoveFileTool_count_4OjF0D{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0}.RemoveFileTool_count_4OjF0D:focus-visible{outline:var(--spacing-4) solid var(--color-primary-muted-border);outline-offset:0}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RemoveFileTool.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|