ghostykit 0.6.4 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -19
- package/dist/chunks/{chunk-LPPND5ME.js → chunk-7M2B7VKH.js} +31 -146
- package/dist/chunks/{chunk-TMEHQZWL.js → chunk-KG23PQI2.js} +5 -2
- package/dist/chunks/chunk-PNU3LKWG.js +1798 -0
- package/dist/chunks/chunk-UUH37KXA.js +144 -0
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +12 -8
- package/dist/core/narration.d.ts +18 -1
- package/dist/core/types.d.ts +7 -0
- package/dist/plugins/index.d.ts +39 -0
- package/dist/plugins/index.js +129 -0
- package/dist/react/Bubble.d.ts +15 -1
- package/dist/react/Composer.d.ts +15 -3
- package/dist/react/Piloto.d.ts +18 -37
- package/dist/react/context.d.ts +6 -1
- package/dist/react/index.d.ts +4 -3
- package/dist/react/index.js +555 -1792
- package/dist/react/plugins.d.ts +249 -0
- package/dist/react/usePilot.d.ts +15 -0
- package/dist/styles.css +572 -548
- package/dist/transport/index.d.ts +3 -1
- package/dist/transport/index.js +1 -1
- package/package.json +5 -1
package/dist/react/index.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
TOOL_VERBS_EN,
|
|
3
|
-
TOOL_VERBS_ES,
|
|
4
2
|
applyJsonPatch,
|
|
5
3
|
argsDetail,
|
|
6
4
|
beginSend,
|
|
@@ -9,10 +7,9 @@ import {
|
|
|
9
7
|
createPilotState,
|
|
10
8
|
dropLastExchange,
|
|
11
9
|
expiryMs,
|
|
10
|
+
extractBlocks,
|
|
12
11
|
extractReplyOptions,
|
|
13
|
-
groupSteps,
|
|
14
12
|
isNarration,
|
|
15
|
-
isRunning,
|
|
16
13
|
lastUserTurn,
|
|
17
14
|
markSubagent,
|
|
18
15
|
messagesToTurns,
|
|
@@ -23,20 +20,77 @@ import {
|
|
|
23
20
|
resolvePermission,
|
|
24
21
|
sendFailed,
|
|
25
22
|
splitNarration,
|
|
26
|
-
stepLabel,
|
|
27
23
|
stopTurn,
|
|
28
24
|
subagentsOf,
|
|
29
|
-
summarizeTools,
|
|
30
25
|
takeQueued,
|
|
31
|
-
toPermission
|
|
32
|
-
|
|
33
|
-
toolNames
|
|
34
|
-
} from "../chunks/chunk-LPPND5ME.js";
|
|
26
|
+
toPermission
|
|
27
|
+
} from "../chunks/chunk-7M2B7VKH.js";
|
|
35
28
|
import {
|
|
36
29
|
PilotHttpError,
|
|
37
30
|
createAgUiTransport,
|
|
38
31
|
readSse
|
|
39
|
-
} from "../chunks/chunk-
|
|
32
|
+
} from "../chunks/chunk-KG23PQI2.js";
|
|
33
|
+
import {
|
|
34
|
+
Activity,
|
|
35
|
+
AppWindow,
|
|
36
|
+
ArrowDown,
|
|
37
|
+
ArrowUpRight,
|
|
38
|
+
BUILTIN_CUSTOM,
|
|
39
|
+
BookOpen,
|
|
40
|
+
Check,
|
|
41
|
+
ChevronRight,
|
|
42
|
+
CircleCheck,
|
|
43
|
+
CircleSlash,
|
|
44
|
+
CircleX,
|
|
45
|
+
Clock,
|
|
46
|
+
Coins,
|
|
47
|
+
Composer,
|
|
48
|
+
Copy,
|
|
49
|
+
ExternalLink,
|
|
50
|
+
FilePenLine,
|
|
51
|
+
FileSpreadsheet,
|
|
52
|
+
FileText,
|
|
53
|
+
Folder,
|
|
54
|
+
Gauge,
|
|
55
|
+
Globe,
|
|
56
|
+
Image,
|
|
57
|
+
Inbox,
|
|
58
|
+
ListChecks,
|
|
59
|
+
LoaderCircle,
|
|
60
|
+
ModelPicker,
|
|
61
|
+
OctagonX,
|
|
62
|
+
PilotoContext,
|
|
63
|
+
ReferenceChips,
|
|
64
|
+
RotateCcw,
|
|
65
|
+
STRINGS_EN,
|
|
66
|
+
STRINGS_ES,
|
|
67
|
+
Search,
|
|
68
|
+
Send,
|
|
69
|
+
ShieldAlert,
|
|
70
|
+
Suggestions,
|
|
71
|
+
TurnContext,
|
|
72
|
+
UsersRound,
|
|
73
|
+
Wrench,
|
|
74
|
+
X,
|
|
75
|
+
definePlugin,
|
|
76
|
+
isDev,
|
|
77
|
+
mimeOf,
|
|
78
|
+
pluginPoints,
|
|
79
|
+
pluginRequires,
|
|
80
|
+
resolvePlugins,
|
|
81
|
+
rootProps,
|
|
82
|
+
usePiloto
|
|
83
|
+
} from "../chunks/chunk-PNU3LKWG.js";
|
|
84
|
+
import {
|
|
85
|
+
TOOL_VERBS_EN,
|
|
86
|
+
TOOL_VERBS_ES,
|
|
87
|
+
groupSteps,
|
|
88
|
+
isRunning,
|
|
89
|
+
stepLabel,
|
|
90
|
+
summarizeTools,
|
|
91
|
+
toolName,
|
|
92
|
+
toolNames
|
|
93
|
+
} from "../chunks/chunk-UUH37KXA.js";
|
|
40
94
|
import {
|
|
41
95
|
applyReferences,
|
|
42
96
|
cleanUserText,
|
|
@@ -44,790 +98,16 @@ import {
|
|
|
44
98
|
systemNoteOf
|
|
45
99
|
} from "../chunks/chunk-6U545WJG.js";
|
|
46
100
|
|
|
47
|
-
// ../../node_modules/lucide-react/dist/esm/createLucideIcon.mjs
|
|
48
|
-
import { forwardRef as forwardRef2, createElement as createElement3 } from "react";
|
|
49
|
-
|
|
50
|
-
// ../../node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.mjs
|
|
51
|
-
var toKebabCase = (string) => string?.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
52
|
-
|
|
53
|
-
// ../../node_modules/lucide-react/dist/esm/shared/src/utils/toLucideIconData.mjs
|
|
54
|
-
function toLucideIconData(iconName, iconNode, aliases = []) {
|
|
55
|
-
if (iconNode == null) {
|
|
56
|
-
throw new Error("[lucide]: iconNode is required when icon name is used");
|
|
57
|
-
}
|
|
58
|
-
return {
|
|
59
|
-
name: toKebabCase(iconName),
|
|
60
|
-
size: 24,
|
|
61
|
-
node: iconNode,
|
|
62
|
-
...aliases.length > 0 ? { aliases } : {}
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// ../../node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.mjs
|
|
67
|
-
var toCamelCase = (string) => {
|
|
68
|
-
let out = "";
|
|
69
|
-
let upperNext = false;
|
|
70
|
-
for (const ch of string) {
|
|
71
|
-
if (ch === "-" || ch === "_" || ch <= " ") {
|
|
72
|
-
upperNext = out.length > 0;
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
if (out.length === 0) {
|
|
76
|
-
out += ch.toLowerCase();
|
|
77
|
-
} else {
|
|
78
|
-
out += upperNext ? ch.toUpperCase() : ch;
|
|
79
|
-
}
|
|
80
|
-
upperNext = false;
|
|
81
|
-
}
|
|
82
|
-
return out;
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
// ../../node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.mjs
|
|
86
|
-
var toPascalCase = (string) => {
|
|
87
|
-
const camelCase = toCamelCase(string);
|
|
88
|
-
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
// ../../node_modules/lucide-react/dist/esm/Icon.mjs
|
|
92
|
-
import { forwardRef, createElement as createElement2 } from "react";
|
|
93
|
-
|
|
94
|
-
// ../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.mjs
|
|
95
|
-
var mergeClasses = (...classes) => classes.filter((className, index, array) => {
|
|
96
|
-
return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index;
|
|
97
|
-
}).join(" ").trim();
|
|
98
|
-
|
|
99
|
-
// ../../node_modules/lucide-react/dist/esm/shared/src/build/defaultAttributes.mjs
|
|
100
|
-
var defaultAttributes = {
|
|
101
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
102
|
-
width: 24,
|
|
103
|
-
height: 24,
|
|
104
|
-
viewBox: "0 0 24 24",
|
|
105
|
-
fill: "none",
|
|
106
|
-
stroke: "currentColor",
|
|
107
|
-
"stroke-width": 2,
|
|
108
|
-
"stroke-linecap": "round",
|
|
109
|
-
"stroke-linejoin": "round"
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
// ../../node_modules/lucide-react/dist/esm/shared/src/build/buildLucideIconNode.mjs
|
|
113
|
-
function isDefined(value) {
|
|
114
|
-
return value !== null && value !== void 0;
|
|
115
|
-
}
|
|
116
|
-
function buildLucideIconNode(icon, params = {}) {
|
|
117
|
-
const attributeNames = params.attributeNames ?? {};
|
|
118
|
-
const getAttributeName = (attributeName) => attributeNames[attributeName] ?? attributeName;
|
|
119
|
-
const viewBoxWidth = icon.size ?? icon.width ?? defaultAttributes["width"];
|
|
120
|
-
const viewBoxHeight = icon.size ?? icon.height ?? defaultAttributes["height"];
|
|
121
|
-
const aliasClassNames = icon.aliases?.filter((alias) => typeof alias === "string" && alias.trim() !== "").map((alias) => `lucide-${alias}`) ?? [];
|
|
122
|
-
const iconClassNames = [...icon.name ? [`lucide-${icon.name}`] : [], ...aliasClassNames];
|
|
123
|
-
const classNamesFromClassName = params.className?.split(" ").filter(Boolean) ?? [];
|
|
124
|
-
const className = params.includeDefaultClasses === false ? mergeClasses(...classNamesFromClassName) : mergeClasses("lucide", ...iconClassNames, ...classNamesFromClassName);
|
|
125
|
-
const calculatedStrokeWidth = params.absoluteStrokeWidth ? Number(params.strokeWidth ?? defaultAttributes["stroke-width"]) * Number(icon.size ?? icon.width ?? defaultAttributes["width"]) / Number(params.size ?? params.width ?? defaultAttributes["width"]) : params.strokeWidth ?? defaultAttributes["stroke-width"];
|
|
126
|
-
const attributes = {
|
|
127
|
-
...Object.entries(defaultAttributes).reduce((attrs, [attrName, value]) => {
|
|
128
|
-
attrs[getAttributeName(attrName)] = value;
|
|
129
|
-
return attrs;
|
|
130
|
-
}, {}),
|
|
131
|
-
..."color" in params && params.color && {
|
|
132
|
-
[getAttributeName("stroke")]: params.color
|
|
133
|
-
},
|
|
134
|
-
..."size" in params && isDefined(params.size) && {
|
|
135
|
-
[getAttributeName("width")]: params.size,
|
|
136
|
-
[getAttributeName("height")]: params.size
|
|
137
|
-
},
|
|
138
|
-
..."width" in params && isDefined(params.width) && {
|
|
139
|
-
[getAttributeName("width")]: params.width
|
|
140
|
-
},
|
|
141
|
-
..."height" in params && isDefined(params.height) && {
|
|
142
|
-
[getAttributeName("height")]: params.height
|
|
143
|
-
},
|
|
144
|
-
[getAttributeName("stroke-width")]: calculatedStrokeWidth,
|
|
145
|
-
...className && {
|
|
146
|
-
[getAttributeName("class")]: className
|
|
147
|
-
},
|
|
148
|
-
[getAttributeName("viewBox")]: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
|
|
149
|
-
...params.hasA11yProp === false ? {
|
|
150
|
-
[getAttributeName("aria-hidden")]: "true"
|
|
151
|
-
} : {},
|
|
152
|
-
..."attributes" in params && params.attributes
|
|
153
|
-
};
|
|
154
|
-
return [
|
|
155
|
-
"svg",
|
|
156
|
-
attributes,
|
|
157
|
-
icon.node.map((child) => {
|
|
158
|
-
const [name, attrs, children] = child;
|
|
159
|
-
const nextAttrs = params.nonScalingStroke ? { [getAttributeName("vector-effect")]: "non-scaling-stroke", ...attrs } : attrs;
|
|
160
|
-
return children ? [name, nextAttrs, children] : [name, nextAttrs];
|
|
161
|
-
})
|
|
162
|
-
];
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// ../../node_modules/lucide-react/dist/esm/shared/src/build/buildLucideIconForReact.mjs
|
|
166
|
-
function buildLucideIconForReact(icon, params = {}) {
|
|
167
|
-
return buildLucideIconNode(icon, {
|
|
168
|
-
...params,
|
|
169
|
-
attributeNames: {
|
|
170
|
-
...params.attributeNames,
|
|
171
|
-
class: "className",
|
|
172
|
-
"stroke-width": "strokeWidth",
|
|
173
|
-
"stroke-linecap": "strokeLinecap",
|
|
174
|
-
"stroke-linejoin": "strokeLinejoin",
|
|
175
|
-
"vector-effect": "vectorEffect"
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// ../../node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.mjs
|
|
181
|
-
var hasA11yProp = (props) => {
|
|
182
|
-
for (const prop in props) {
|
|
183
|
-
if (prop.startsWith("aria-") || prop === "role" || prop === "title") {
|
|
184
|
-
return true;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return false;
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
// ../../node_modules/lucide-react/dist/esm/context.mjs
|
|
191
|
-
import { createContext, useContext, useMemo, createElement } from "react";
|
|
192
|
-
var LucideContext = createContext({});
|
|
193
|
-
var useLucideContext = () => useContext(LucideContext);
|
|
194
|
-
|
|
195
|
-
// ../../node_modules/lucide-react/dist/esm/Icon.mjs
|
|
196
|
-
var Icon = forwardRef(
|
|
197
|
-
({
|
|
198
|
-
color,
|
|
199
|
-
size,
|
|
200
|
-
width,
|
|
201
|
-
height,
|
|
202
|
-
strokeWidth,
|
|
203
|
-
absoluteStrokeWidth,
|
|
204
|
-
nonScalingStroke,
|
|
205
|
-
className = "",
|
|
206
|
-
children,
|
|
207
|
-
iconNode = [],
|
|
208
|
-
icon = {
|
|
209
|
-
node: iconNode,
|
|
210
|
-
aliases: [],
|
|
211
|
-
size: 24
|
|
212
|
-
},
|
|
213
|
-
...rest
|
|
214
|
-
}, ref) => {
|
|
215
|
-
const {
|
|
216
|
-
size: contextSize = 24,
|
|
217
|
-
strokeWidth: contextStrokeWidth = 2,
|
|
218
|
-
absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,
|
|
219
|
-
nonScalingStroke: contextNonScalingStroke = false,
|
|
220
|
-
color: contextColor = "currentColor",
|
|
221
|
-
className: contextClass = ""
|
|
222
|
-
} = useLucideContext() ?? {};
|
|
223
|
-
const hasAccessibleProp = Boolean(children) || hasA11yProp(rest);
|
|
224
|
-
const [name, svgAttributes, builtIconNode = []] = buildLucideIconForReact(icon, {
|
|
225
|
-
color: color ?? contextColor,
|
|
226
|
-
width: width ?? size ?? contextSize,
|
|
227
|
-
height: height ?? size ?? contextSize,
|
|
228
|
-
strokeWidth: strokeWidth ?? contextStrokeWidth,
|
|
229
|
-
absoluteStrokeWidth: absoluteStrokeWidth ?? contextAbsoluteStrokeWidth,
|
|
230
|
-
nonScalingStroke: nonScalingStroke ?? contextNonScalingStroke,
|
|
231
|
-
className: mergeClasses(contextClass, className),
|
|
232
|
-
hasA11yProp: hasAccessibleProp,
|
|
233
|
-
attributes: rest
|
|
234
|
-
});
|
|
235
|
-
return createElement2(
|
|
236
|
-
name,
|
|
237
|
-
{
|
|
238
|
-
ref,
|
|
239
|
-
...svgAttributes
|
|
240
|
-
},
|
|
241
|
-
[
|
|
242
|
-
...builtIconNode.map(([tag, attrs]) => createElement2(tag, attrs)),
|
|
243
|
-
...Array.isArray(children) ? children : [children]
|
|
244
|
-
]
|
|
245
|
-
);
|
|
246
|
-
}
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
// ../../node_modules/lucide-react/dist/esm/createLucideIcon.mjs
|
|
250
|
-
function createLucideIcon(iconDataOrName, iconNode = [], aliases = []) {
|
|
251
|
-
const iconData = typeof iconDataOrName === "string" ? toLucideIconData(iconDataOrName, iconNode, aliases) : iconDataOrName;
|
|
252
|
-
const Component = forwardRef2(
|
|
253
|
-
({ className, ...props }, ref) => createElement3(Icon, {
|
|
254
|
-
ref,
|
|
255
|
-
icon: iconData,
|
|
256
|
-
className,
|
|
257
|
-
...props
|
|
258
|
-
})
|
|
259
|
-
);
|
|
260
|
-
if (iconData.name) {
|
|
261
|
-
Component.displayName = toPascalCase(iconData.name);
|
|
262
|
-
}
|
|
263
|
-
return Component;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// ../../node_modules/lucide-react/dist/esm/icons/activity.mjs
|
|
267
|
-
var __iconData = {
|
|
268
|
-
name: "activity",
|
|
269
|
-
size: 24,
|
|
270
|
-
node: [
|
|
271
|
-
[
|
|
272
|
-
"path",
|
|
273
|
-
{
|
|
274
|
-
d: "M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",
|
|
275
|
-
key: "169zse"
|
|
276
|
-
}
|
|
277
|
-
]
|
|
278
|
-
]
|
|
279
|
-
};
|
|
280
|
-
__iconData.node;
|
|
281
|
-
var Activity = createLucideIcon(__iconData);
|
|
282
|
-
|
|
283
|
-
// ../../node_modules/lucide-react/dist/esm/icons/app-window.mjs
|
|
284
|
-
var __iconData2 = {
|
|
285
|
-
name: "app-window",
|
|
286
|
-
size: 24,
|
|
287
|
-
node: [
|
|
288
|
-
["rect", { x: "2", y: "4", width: "20", height: "16", rx: "2", key: "izxlao" }],
|
|
289
|
-
["path", { d: "M10 4v4", key: "pp8u80" }],
|
|
290
|
-
["path", { d: "M2 8h20", key: "d11cs7" }],
|
|
291
|
-
["path", { d: "M6 4v4", key: "1svtjw" }]
|
|
292
|
-
]
|
|
293
|
-
};
|
|
294
|
-
__iconData2.node;
|
|
295
|
-
var AppWindow = createLucideIcon(__iconData2);
|
|
296
|
-
|
|
297
|
-
// ../../node_modules/lucide-react/dist/esm/icons/arrow-down.mjs
|
|
298
|
-
var __iconData3 = {
|
|
299
|
-
name: "arrow-down",
|
|
300
|
-
size: 24,
|
|
301
|
-
node: [
|
|
302
|
-
["path", { d: "M12 5v14", key: "s699le" }],
|
|
303
|
-
["path", { d: "m19 12-7 7-7-7", key: "1idqje" }]
|
|
304
|
-
]
|
|
305
|
-
};
|
|
306
|
-
__iconData3.node;
|
|
307
|
-
var ArrowDown = createLucideIcon(__iconData3);
|
|
308
|
-
|
|
309
|
-
// ../../node_modules/lucide-react/dist/esm/icons/arrow-up-right.mjs
|
|
310
|
-
var __iconData4 = {
|
|
311
|
-
name: "arrow-up-right",
|
|
312
|
-
size: 24,
|
|
313
|
-
node: [
|
|
314
|
-
["path", { d: "M7 7h10v10", key: "1tivn9" }],
|
|
315
|
-
["path", { d: "M7 17 17 7", key: "1vkiza" }]
|
|
316
|
-
]
|
|
317
|
-
};
|
|
318
|
-
__iconData4.node;
|
|
319
|
-
var ArrowUpRight = createLucideIcon(__iconData4);
|
|
320
|
-
|
|
321
|
-
// ../../node_modules/lucide-react/dist/esm/icons/arrow-up.mjs
|
|
322
|
-
var __iconData5 = {
|
|
323
|
-
name: "arrow-up",
|
|
324
|
-
size: 24,
|
|
325
|
-
node: [
|
|
326
|
-
["path", { d: "m5 12 7-7 7 7", key: "hav0vg" }],
|
|
327
|
-
["path", { d: "M12 19V5", key: "x0mq9r" }]
|
|
328
|
-
]
|
|
329
|
-
};
|
|
330
|
-
__iconData5.node;
|
|
331
|
-
var ArrowUp = createLucideIcon(__iconData5);
|
|
332
|
-
|
|
333
|
-
// ../../node_modules/lucide-react/dist/esm/icons/book-open.mjs
|
|
334
|
-
var __iconData6 = {
|
|
335
|
-
name: "book-open",
|
|
336
|
-
size: 24,
|
|
337
|
-
node: [
|
|
338
|
-
["path", { d: "M12 5v16", key: "1f6ucr" }],
|
|
339
|
-
[
|
|
340
|
-
"path",
|
|
341
|
-
{
|
|
342
|
-
d: "M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z",
|
|
343
|
-
key: "1fyvmf"
|
|
344
|
-
}
|
|
345
|
-
]
|
|
346
|
-
]
|
|
347
|
-
};
|
|
348
|
-
__iconData6.node;
|
|
349
|
-
var BookOpen = createLucideIcon(__iconData6);
|
|
350
|
-
|
|
351
|
-
// ../../node_modules/lucide-react/dist/esm/icons/check.mjs
|
|
352
|
-
var __iconData7 = {
|
|
353
|
-
name: "check",
|
|
354
|
-
size: 24,
|
|
355
|
-
node: [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]]
|
|
356
|
-
};
|
|
357
|
-
__iconData7.node;
|
|
358
|
-
var Check = createLucideIcon(__iconData7);
|
|
359
|
-
|
|
360
|
-
// ../../node_modules/lucide-react/dist/esm/icons/chevron-down.mjs
|
|
361
|
-
var __iconData8 = {
|
|
362
|
-
name: "chevron-down",
|
|
363
|
-
size: 24,
|
|
364
|
-
node: [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]]
|
|
365
|
-
};
|
|
366
|
-
__iconData8.node;
|
|
367
|
-
var ChevronDown = createLucideIcon(__iconData8);
|
|
368
|
-
|
|
369
|
-
// ../../node_modules/lucide-react/dist/esm/icons/chevron-right.mjs
|
|
370
|
-
var __iconData9 = {
|
|
371
|
-
name: "chevron-right",
|
|
372
|
-
size: 24,
|
|
373
|
-
node: [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]]
|
|
374
|
-
};
|
|
375
|
-
__iconData9.node;
|
|
376
|
-
var ChevronRight = createLucideIcon(__iconData9);
|
|
377
|
-
|
|
378
|
-
// ../../node_modules/lucide-react/dist/esm/icons/circle-check.mjs
|
|
379
|
-
var __iconData10 = {
|
|
380
|
-
name: "circle-check",
|
|
381
|
-
size: 24,
|
|
382
|
-
node: [
|
|
383
|
-
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
384
|
-
["path", { d: "m16 9-5.5 5.5L8 12", key: "xofnsj" }]
|
|
385
|
-
],
|
|
386
|
-
aliases: ["check-circle-2"]
|
|
387
|
-
};
|
|
388
|
-
__iconData10.node;
|
|
389
|
-
var CircleCheck = createLucideIcon(__iconData10);
|
|
390
|
-
|
|
391
|
-
// ../../node_modules/lucide-react/dist/esm/icons/circle-slash.mjs
|
|
392
|
-
var __iconData11 = {
|
|
393
|
-
name: "circle-slash",
|
|
394
|
-
size: 24,
|
|
395
|
-
node: [
|
|
396
|
-
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
397
|
-
["line", { x1: "9", x2: "15", y1: "15", y2: "9", key: "1dfufj" }]
|
|
398
|
-
]
|
|
399
|
-
};
|
|
400
|
-
__iconData11.node;
|
|
401
|
-
var CircleSlash = createLucideIcon(__iconData11);
|
|
402
|
-
|
|
403
|
-
// ../../node_modules/lucide-react/dist/esm/icons/circle-x.mjs
|
|
404
|
-
var __iconData12 = {
|
|
405
|
-
name: "circle-x",
|
|
406
|
-
size: 24,
|
|
407
|
-
node: [
|
|
408
|
-
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
409
|
-
["path", { d: "m15 9-6 6", key: "1uzhvr" }],
|
|
410
|
-
["path", { d: "m9 9 6 6", key: "z0biqf" }]
|
|
411
|
-
],
|
|
412
|
-
aliases: ["x-circle"]
|
|
413
|
-
};
|
|
414
|
-
__iconData12.node;
|
|
415
|
-
var CircleX = createLucideIcon(__iconData12);
|
|
416
|
-
|
|
417
|
-
// ../../node_modules/lucide-react/dist/esm/icons/clock.mjs
|
|
418
|
-
var __iconData13 = {
|
|
419
|
-
name: "clock",
|
|
420
|
-
size: 24,
|
|
421
|
-
node: [
|
|
422
|
-
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
423
|
-
["path", { d: "M12 6v6l4 2", key: "mmk7yg" }]
|
|
424
|
-
]
|
|
425
|
-
};
|
|
426
|
-
__iconData13.node;
|
|
427
|
-
var Clock = createLucideIcon(__iconData13);
|
|
428
|
-
|
|
429
|
-
// ../../node_modules/lucide-react/dist/esm/icons/coins.mjs
|
|
430
|
-
var __iconData14 = {
|
|
431
|
-
name: "coins",
|
|
432
|
-
size: 24,
|
|
433
|
-
node: [
|
|
434
|
-
["path", { d: "M13.744 17.736a6 6 0 1 1-7.48-7.48", key: "bq4yh3" }],
|
|
435
|
-
["path", { d: "M15 6h1v4", key: "11y1tn" }],
|
|
436
|
-
["path", { d: "m6.134 14.768.866-.5 2 3.464", key: "17snzx" }],
|
|
437
|
-
["circle", { cx: "16", cy: "8", r: "6", key: "14bfc9" }]
|
|
438
|
-
]
|
|
439
|
-
};
|
|
440
|
-
__iconData14.node;
|
|
441
|
-
var Coins = createLucideIcon(__iconData14);
|
|
442
|
-
|
|
443
|
-
// ../../node_modules/lucide-react/dist/esm/icons/copy.mjs
|
|
444
|
-
var __iconData15 = {
|
|
445
|
-
name: "copy",
|
|
446
|
-
size: 24,
|
|
447
|
-
node: [
|
|
448
|
-
["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2", key: "17jyea" }],
|
|
449
|
-
["path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2", key: "zix9uf" }]
|
|
450
|
-
]
|
|
451
|
-
};
|
|
452
|
-
__iconData15.node;
|
|
453
|
-
var Copy = createLucideIcon(__iconData15);
|
|
454
|
-
|
|
455
|
-
// ../../node_modules/lucide-react/dist/esm/icons/cpu.mjs
|
|
456
|
-
var __iconData16 = {
|
|
457
|
-
name: "cpu",
|
|
458
|
-
size: 24,
|
|
459
|
-
node: [
|
|
460
|
-
["path", { d: "M12 20v2", key: "1lh1kg" }],
|
|
461
|
-
["path", { d: "M12 2v2", key: "tus03m" }],
|
|
462
|
-
["path", { d: "M17 20v2", key: "1rnc9c" }],
|
|
463
|
-
["path", { d: "M17 2v2", key: "11trls" }],
|
|
464
|
-
["path", { d: "M2 12h2", key: "1t8f8n" }],
|
|
465
|
-
["path", { d: "M2 17h2", key: "7oei6x" }],
|
|
466
|
-
["path", { d: "M2 7h2", key: "asdhe0" }],
|
|
467
|
-
["path", { d: "M20 12h2", key: "1q8mjw" }],
|
|
468
|
-
["path", { d: "M20 17h2", key: "1fpfkl" }],
|
|
469
|
-
["path", { d: "M20 7h2", key: "1o8tra" }],
|
|
470
|
-
["path", { d: "M7 20v2", key: "4gnj0m" }],
|
|
471
|
-
["path", { d: "M7 2v2", key: "1i4yhu" }],
|
|
472
|
-
["rect", { x: "4", y: "4", width: "16", height: "16", rx: "2", key: "1vbyd7" }],
|
|
473
|
-
["rect", { x: "8", y: "8", width: "8", height: "8", rx: "1", key: "z9xiuo" }]
|
|
474
|
-
]
|
|
475
|
-
};
|
|
476
|
-
__iconData16.node;
|
|
477
|
-
var Cpu = createLucideIcon(__iconData16);
|
|
478
|
-
|
|
479
|
-
// ../../node_modules/lucide-react/dist/esm/icons/crosshair.mjs
|
|
480
|
-
var __iconData17 = {
|
|
481
|
-
name: "crosshair",
|
|
482
|
-
size: 24,
|
|
483
|
-
node: [
|
|
484
|
-
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
485
|
-
["line", { x1: "22", x2: "18", y1: "12", y2: "12", key: "l9bcsi" }],
|
|
486
|
-
["line", { x1: "6", x2: "2", y1: "12", y2: "12", key: "13hhkx" }],
|
|
487
|
-
["line", { x1: "12", x2: "12", y1: "6", y2: "2", key: "10w3f3" }],
|
|
488
|
-
["line", { x1: "12", x2: "12", y1: "22", y2: "18", key: "15g9kq" }]
|
|
489
|
-
]
|
|
490
|
-
};
|
|
491
|
-
__iconData17.node;
|
|
492
|
-
var Crosshair = createLucideIcon(__iconData17);
|
|
493
|
-
|
|
494
|
-
// ../../node_modules/lucide-react/dist/esm/icons/external-link.mjs
|
|
495
|
-
var __iconData18 = {
|
|
496
|
-
name: "external-link",
|
|
497
|
-
size: 24,
|
|
498
|
-
node: [
|
|
499
|
-
["path", { d: "M15 3h6v6", key: "1q9fwt" }],
|
|
500
|
-
["path", { d: "M10 14 21 3", key: "gplh6r" }],
|
|
501
|
-
["path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6", key: "a6xqqp" }]
|
|
502
|
-
]
|
|
503
|
-
};
|
|
504
|
-
__iconData18.node;
|
|
505
|
-
var ExternalLink = createLucideIcon(__iconData18);
|
|
506
|
-
|
|
507
|
-
// ../../node_modules/lucide-react/dist/esm/icons/file-pen-line.mjs
|
|
508
|
-
var __iconData19 = {
|
|
509
|
-
name: "file-pen-line",
|
|
510
|
-
size: 24,
|
|
511
|
-
node: [
|
|
512
|
-
[
|
|
513
|
-
"path",
|
|
514
|
-
{
|
|
515
|
-
d: "M14.364 13.634a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506l4.013-4.009a1 1 0 0 0-3.004-3.004z",
|
|
516
|
-
key: "ukzhwg"
|
|
517
|
-
}
|
|
518
|
-
],
|
|
519
|
-
["path", { d: "M14.487 7.858A1 1 0 0 1 14 7V2", key: "1klhew" }],
|
|
520
|
-
[
|
|
521
|
-
"path",
|
|
522
|
-
{
|
|
523
|
-
d: "M20 19.645V20a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l2.516 2.516",
|
|
524
|
-
key: "rxaxab"
|
|
525
|
-
}
|
|
526
|
-
],
|
|
527
|
-
["path", { d: "M8 18h1", key: "13wk12" }]
|
|
528
|
-
],
|
|
529
|
-
aliases: ["file-signature"]
|
|
530
|
-
};
|
|
531
|
-
__iconData19.node;
|
|
532
|
-
var FilePenLine = createLucideIcon(__iconData19);
|
|
533
|
-
|
|
534
|
-
// ../../node_modules/lucide-react/dist/esm/icons/file-spreadsheet.mjs
|
|
535
|
-
var __iconData20 = {
|
|
536
|
-
name: "file-spreadsheet",
|
|
537
|
-
size: 24,
|
|
538
|
-
node: [
|
|
539
|
-
[
|
|
540
|
-
"path",
|
|
541
|
-
{
|
|
542
|
-
d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",
|
|
543
|
-
key: "1oefj6"
|
|
544
|
-
}
|
|
545
|
-
],
|
|
546
|
-
["path", { d: "M14 2v5a1 1 0 0 0 1 1h5", key: "wfsgrz" }],
|
|
547
|
-
["path", { d: "M8 13h2", key: "yr2amv" }],
|
|
548
|
-
["path", { d: "M14 13h2", key: "un5t4a" }],
|
|
549
|
-
["path", { d: "M8 17h2", key: "2yhykz" }],
|
|
550
|
-
["path", { d: "M14 17h2", key: "10kma7" }]
|
|
551
|
-
]
|
|
552
|
-
};
|
|
553
|
-
__iconData20.node;
|
|
554
|
-
var FileSpreadsheet = createLucideIcon(__iconData20);
|
|
555
|
-
|
|
556
|
-
// ../../node_modules/lucide-react/dist/esm/icons/file-text.mjs
|
|
557
|
-
var __iconData21 = {
|
|
558
|
-
name: "file-text",
|
|
559
|
-
size: 24,
|
|
560
|
-
node: [
|
|
561
|
-
[
|
|
562
|
-
"path",
|
|
563
|
-
{
|
|
564
|
-
d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",
|
|
565
|
-
key: "1oefj6"
|
|
566
|
-
}
|
|
567
|
-
],
|
|
568
|
-
["path", { d: "M14 2v5a1 1 0 0 0 1 1h5", key: "wfsgrz" }],
|
|
569
|
-
["path", { d: "M10 9H8", key: "b1mrlr" }],
|
|
570
|
-
["path", { d: "M16 13H8", key: "t4e002" }],
|
|
571
|
-
["path", { d: "M16 17H8", key: "z1uh3a" }]
|
|
572
|
-
]
|
|
573
|
-
};
|
|
574
|
-
__iconData21.node;
|
|
575
|
-
var FileText = createLucideIcon(__iconData21);
|
|
576
|
-
|
|
577
|
-
// ../../node_modules/lucide-react/dist/esm/icons/folder.mjs
|
|
578
|
-
var __iconData22 = {
|
|
579
|
-
name: "folder",
|
|
580
|
-
size: 24,
|
|
581
|
-
node: [
|
|
582
|
-
[
|
|
583
|
-
"path",
|
|
584
|
-
{
|
|
585
|
-
d: "M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",
|
|
586
|
-
key: "1kt360"
|
|
587
|
-
}
|
|
588
|
-
]
|
|
589
|
-
]
|
|
590
|
-
};
|
|
591
|
-
__iconData22.node;
|
|
592
|
-
var Folder = createLucideIcon(__iconData22);
|
|
593
|
-
|
|
594
|
-
// ../../node_modules/lucide-react/dist/esm/icons/gauge.mjs
|
|
595
|
-
var __iconData23 = {
|
|
596
|
-
name: "gauge",
|
|
597
|
-
size: 24,
|
|
598
|
-
node: [
|
|
599
|
-
["path", { d: "m12 14 4-4", key: "9kzdfg" }],
|
|
600
|
-
["path", { d: "M3.34 19a10 10 0 1 1 17.32 0", key: "19p75a" }]
|
|
601
|
-
]
|
|
602
|
-
};
|
|
603
|
-
__iconData23.node;
|
|
604
|
-
var Gauge = createLucideIcon(__iconData23);
|
|
605
|
-
|
|
606
|
-
// ../../node_modules/lucide-react/dist/esm/icons/globe.mjs
|
|
607
|
-
var __iconData24 = {
|
|
608
|
-
name: "globe",
|
|
609
|
-
size: 24,
|
|
610
|
-
node: [
|
|
611
|
-
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
612
|
-
["path", { d: "M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20", key: "13o1zl" }],
|
|
613
|
-
["path", { d: "M2 12h20", key: "9i4pu4" }]
|
|
614
|
-
]
|
|
615
|
-
};
|
|
616
|
-
__iconData24.node;
|
|
617
|
-
var Globe = createLucideIcon(__iconData24);
|
|
618
|
-
|
|
619
|
-
// ../../node_modules/lucide-react/dist/esm/icons/image.mjs
|
|
620
|
-
var __iconData25 = {
|
|
621
|
-
name: "image",
|
|
622
|
-
size: 24,
|
|
623
|
-
node: [
|
|
624
|
-
["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
|
|
625
|
-
["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
|
|
626
|
-
["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
|
|
627
|
-
]
|
|
628
|
-
};
|
|
629
|
-
__iconData25.node;
|
|
630
|
-
var Image = createLucideIcon(__iconData25);
|
|
631
|
-
|
|
632
|
-
// ../../node_modules/lucide-react/dist/esm/icons/inbox.mjs
|
|
633
|
-
var __iconData26 = {
|
|
634
|
-
name: "inbox",
|
|
635
|
-
size: 24,
|
|
636
|
-
node: [
|
|
637
|
-
["polyline", { points: "22 12 16 12 14 15 10 15 8 12 2 12", key: "o97t9d" }],
|
|
638
|
-
[
|
|
639
|
-
"path",
|
|
640
|
-
{
|
|
641
|
-
d: "M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",
|
|
642
|
-
key: "oot6mr"
|
|
643
|
-
}
|
|
644
|
-
]
|
|
645
|
-
]
|
|
646
|
-
};
|
|
647
|
-
__iconData26.node;
|
|
648
|
-
var Inbox = createLucideIcon(__iconData26);
|
|
649
|
-
|
|
650
|
-
// ../../node_modules/lucide-react/dist/esm/icons/list-checks.mjs
|
|
651
|
-
var __iconData27 = {
|
|
652
|
-
name: "list-checks",
|
|
653
|
-
size: 24,
|
|
654
|
-
node: [
|
|
655
|
-
["path", { d: "M13 5h8", key: "a7qcls" }],
|
|
656
|
-
["path", { d: "M13 12h8", key: "h98zly" }],
|
|
657
|
-
["path", { d: "M13 19h8", key: "c3s6r1" }],
|
|
658
|
-
["path", { d: "m3 17 2 2 4-4", key: "1jhpwq" }],
|
|
659
|
-
["path", { d: "m3 7 2 2 4-4", key: "1obspn" }]
|
|
660
|
-
]
|
|
661
|
-
};
|
|
662
|
-
__iconData27.node;
|
|
663
|
-
var ListChecks = createLucideIcon(__iconData27);
|
|
664
|
-
|
|
665
|
-
// ../../node_modules/lucide-react/dist/esm/icons/loader-circle.mjs
|
|
666
|
-
var __iconData28 = {
|
|
667
|
-
name: "loader-circle",
|
|
668
|
-
size: 24,
|
|
669
|
-
node: [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]],
|
|
670
|
-
aliases: ["loader-2"]
|
|
671
|
-
};
|
|
672
|
-
__iconData28.node;
|
|
673
|
-
var LoaderCircle = createLucideIcon(__iconData28);
|
|
674
|
-
|
|
675
|
-
// ../../node_modules/lucide-react/dist/esm/icons/mic.mjs
|
|
676
|
-
var __iconData29 = {
|
|
677
|
-
name: "mic",
|
|
678
|
-
size: 24,
|
|
679
|
-
node: [
|
|
680
|
-
["path", { d: "M12 19v3", key: "npa21l" }],
|
|
681
|
-
["path", { d: "M19 10v2a7 7 0 0 1-14 0v-2", key: "1vc78b" }],
|
|
682
|
-
["rect", { x: "9", y: "2", width: "6", height: "13", rx: "3", key: "s6n7sd" }]
|
|
683
|
-
]
|
|
684
|
-
};
|
|
685
|
-
__iconData29.node;
|
|
686
|
-
var Mic = createLucideIcon(__iconData29);
|
|
687
|
-
|
|
688
|
-
// ../../node_modules/lucide-react/dist/esm/icons/octagon-x.mjs
|
|
689
|
-
var __iconData30 = {
|
|
690
|
-
name: "octagon-x",
|
|
691
|
-
size: 24,
|
|
692
|
-
node: [
|
|
693
|
-
["path", { d: "m15 9-6 6", key: "1uzhvr" }],
|
|
694
|
-
[
|
|
695
|
-
"path",
|
|
696
|
-
{
|
|
697
|
-
d: "M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z",
|
|
698
|
-
key: "2d38gg"
|
|
699
|
-
}
|
|
700
|
-
],
|
|
701
|
-
["path", { d: "m9 9 6 6", key: "z0biqf" }]
|
|
702
|
-
],
|
|
703
|
-
aliases: ["x-octagon"]
|
|
704
|
-
};
|
|
705
|
-
__iconData30.node;
|
|
706
|
-
var OctagonX = createLucideIcon(__iconData30);
|
|
707
|
-
|
|
708
|
-
// ../../node_modules/lucide-react/dist/esm/icons/paperclip.mjs
|
|
709
|
-
var __iconData31 = {
|
|
710
|
-
name: "paperclip",
|
|
711
|
-
size: 24,
|
|
712
|
-
node: [
|
|
713
|
-
[
|
|
714
|
-
"path",
|
|
715
|
-
{
|
|
716
|
-
d: "m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551",
|
|
717
|
-
key: "1miecu"
|
|
718
|
-
}
|
|
719
|
-
]
|
|
720
|
-
]
|
|
721
|
-
};
|
|
722
|
-
__iconData31.node;
|
|
723
|
-
var Paperclip = createLucideIcon(__iconData31);
|
|
724
|
-
|
|
725
|
-
// ../../node_modules/lucide-react/dist/esm/icons/rotate-ccw.mjs
|
|
726
|
-
var __iconData32 = {
|
|
727
|
-
name: "rotate-ccw",
|
|
728
|
-
size: 24,
|
|
729
|
-
node: [
|
|
730
|
-
["path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", key: "1357e3" }],
|
|
731
|
-
["path", { d: "M3 3v5h5", key: "1xhq8a" }]
|
|
732
|
-
]
|
|
733
|
-
};
|
|
734
|
-
__iconData32.node;
|
|
735
|
-
var RotateCcw = createLucideIcon(__iconData32);
|
|
736
|
-
|
|
737
|
-
// ../../node_modules/lucide-react/dist/esm/icons/search.mjs
|
|
738
|
-
var __iconData33 = {
|
|
739
|
-
name: "search",
|
|
740
|
-
size: 24,
|
|
741
|
-
node: [
|
|
742
|
-
["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
|
|
743
|
-
["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
|
|
744
|
-
]
|
|
745
|
-
};
|
|
746
|
-
__iconData33.node;
|
|
747
|
-
var Search = createLucideIcon(__iconData33);
|
|
748
|
-
|
|
749
|
-
// ../../node_modules/lucide-react/dist/esm/icons/send.mjs
|
|
750
|
-
var __iconData34 = {
|
|
751
|
-
name: "send",
|
|
752
|
-
size: 24,
|
|
753
|
-
node: [
|
|
754
|
-
[
|
|
755
|
-
"path",
|
|
756
|
-
{
|
|
757
|
-
d: "M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",
|
|
758
|
-
key: "1ffxy3"
|
|
759
|
-
}
|
|
760
|
-
],
|
|
761
|
-
["path", { d: "m21.854 2.147-10.94 10.939", key: "12cjpa" }]
|
|
762
|
-
]
|
|
763
|
-
};
|
|
764
|
-
__iconData34.node;
|
|
765
|
-
var Send = createLucideIcon(__iconData34);
|
|
766
|
-
|
|
767
|
-
// ../../node_modules/lucide-react/dist/esm/icons/shield-alert.mjs
|
|
768
|
-
var __iconData35 = {
|
|
769
|
-
name: "shield-alert",
|
|
770
|
-
size: 24,
|
|
771
|
-
node: [
|
|
772
|
-
[
|
|
773
|
-
"path",
|
|
774
|
-
{
|
|
775
|
-
d: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",
|
|
776
|
-
key: "oel41y"
|
|
777
|
-
}
|
|
778
|
-
],
|
|
779
|
-
["path", { d: "M12 8v4", key: "1got3b" }],
|
|
780
|
-
["path", { d: "M12 16h.01", key: "1drbdi" }]
|
|
781
|
-
]
|
|
782
|
-
};
|
|
783
|
-
__iconData35.node;
|
|
784
|
-
var ShieldAlert = createLucideIcon(__iconData35);
|
|
785
|
-
|
|
786
|
-
// ../../node_modules/lucide-react/dist/esm/icons/square.mjs
|
|
787
|
-
var __iconData36 = {
|
|
788
|
-
name: "square",
|
|
789
|
-
size: 24,
|
|
790
|
-
node: [["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }]]
|
|
791
|
-
};
|
|
792
|
-
__iconData36.node;
|
|
793
|
-
var Square = createLucideIcon(__iconData36);
|
|
794
|
-
|
|
795
|
-
// ../../node_modules/lucide-react/dist/esm/icons/users-round.mjs
|
|
796
|
-
var __iconData37 = {
|
|
797
|
-
name: "users-round",
|
|
798
|
-
size: 24,
|
|
799
|
-
node: [
|
|
800
|
-
["path", { d: "M18 21a8 8 0 0 0-16 0", key: "3ypg7q" }],
|
|
801
|
-
["circle", { cx: "10", cy: "8", r: "5", key: "o932ke" }],
|
|
802
|
-
["path", { d: "M22 20c0-3.37-2-6.5-4-8a5 5 0 0 0-.45-8.3", key: "10s06x" }]
|
|
803
|
-
],
|
|
804
|
-
aliases: ["users-2"]
|
|
805
|
-
};
|
|
806
|
-
__iconData37.node;
|
|
807
|
-
var UsersRound = createLucideIcon(__iconData37);
|
|
808
|
-
|
|
809
|
-
// ../../node_modules/lucide-react/dist/esm/icons/x.mjs
|
|
810
|
-
var __iconData38 = {
|
|
811
|
-
name: "x",
|
|
812
|
-
size: 24,
|
|
813
|
-
node: [
|
|
814
|
-
["path", { d: "M18 6 6 18", key: "1bl5f8" }],
|
|
815
|
-
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
816
|
-
]
|
|
817
|
-
};
|
|
818
|
-
__iconData38.node;
|
|
819
|
-
var X = createLucideIcon(__iconData38);
|
|
820
|
-
|
|
821
101
|
// src/react/Piloto.tsx
|
|
822
102
|
import {
|
|
823
|
-
forwardRef
|
|
824
|
-
useCallback as
|
|
825
|
-
useEffect as
|
|
103
|
+
forwardRef,
|
|
104
|
+
useCallback as useCallback2,
|
|
105
|
+
useEffect as useEffect5,
|
|
826
106
|
useImperativeHandle,
|
|
827
107
|
useLayoutEffect,
|
|
828
|
-
useMemo as
|
|
829
|
-
useRef as
|
|
830
|
-
useState as
|
|
108
|
+
useMemo as useMemo3,
|
|
109
|
+
useRef as useRef4,
|
|
110
|
+
useState as useState8
|
|
831
111
|
} from "react";
|
|
832
112
|
|
|
833
113
|
// src/react/Bubble.tsx
|
|
@@ -835,184 +115,6 @@ import { useState as useState5 } from "react";
|
|
|
835
115
|
|
|
836
116
|
// src/react/ConfirmCard.tsx
|
|
837
117
|
import { useEffect, useRef, useState } from "react";
|
|
838
|
-
|
|
839
|
-
// src/react/context.tsx
|
|
840
|
-
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
841
|
-
|
|
842
|
-
// src/react/strings.ts
|
|
843
|
-
var STRINGS_ES = {
|
|
844
|
-
numberLocale: "es-MX",
|
|
845
|
-
placeholder: (agent) => `Escr\xEDbele a ${agent}`,
|
|
846
|
-
placeholderDefault: "Escr\xEDbele al agente",
|
|
847
|
-
send: "Enviar",
|
|
848
|
-
stop: "Detener",
|
|
849
|
-
uploading: "Subiendo tu archivo\u2026",
|
|
850
|
-
uploadingN: (n) => `Subiendo tus ${n} archivos\u2026`,
|
|
851
|
-
attachImage: "Adjuntar imagen",
|
|
852
|
-
attachFile: "Adjuntar archivo",
|
|
853
|
-
noImages: "Este agente no ve im\xE1genes",
|
|
854
|
-
removeAttachment: "Quitar adjunto",
|
|
855
|
-
removeReference: "Quitar referencia",
|
|
856
|
-
dropFiles: "Suelta tus archivos",
|
|
857
|
-
dropHint: "Excel, Word, PDF o im\xE1genes",
|
|
858
|
-
tooBig: (name, mb) => `${name} pesa m\xE1s de ${mb} MB`,
|
|
859
|
-
tooMany: (max) => `no caben m\xE1s de ${max} archivos por mensaje`,
|
|
860
|
-
cantSeeImage: (name) => `${name}: este agente no ve im\xE1genes`,
|
|
861
|
-
cantUpload: (name) => `${name}: aqu\xED s\xF3lo se pueden mandar im\xE1genes y texto`,
|
|
862
|
-
uploadFailed: "no se pudo subir el archivo",
|
|
863
|
-
recordVoice: "Grabar nota de voz",
|
|
864
|
-
voiceNote: "Nota de voz",
|
|
865
|
-
cancelVoice: "Cancelar la nota de voz",
|
|
866
|
-
stopAndSendVoice: "Parar y mandar la nota de voz",
|
|
867
|
-
micDenied: "No tengo permiso para usar el micr\xF3fono.",
|
|
868
|
-
voiceEmpty: "no se entendi\xF3 nada en la nota de voz",
|
|
869
|
-
voiceFailed: "no se pudo mandar la nota de voz",
|
|
870
|
-
model: "Modelo",
|
|
871
|
-
thinking: "Pensando\u2026",
|
|
872
|
-
howItGoes: (s) => s < 6 ? "Pensando\u2026" : s < 15 ? "Trabajando\u2026" : s < 60 ? "Estoy en ello\u2026" : s < 120 ? "Esto me lleva un poco\u2026" : s < 300 ? "Llevo un buen rato\u2026" : "Me est\xE1 tomando mucho \u2014 puedes detenerme",
|
|
873
|
-
stillWorking: "Estoy en ello\u2026",
|
|
874
|
-
retry: "Reintentar",
|
|
875
|
-
copy: "Copiar",
|
|
876
|
-
copied: "Copiado",
|
|
877
|
-
copyMessage: "Copiar mensaje",
|
|
878
|
-
worked: (s) => `Trabaj\xF3 ${s} s`,
|
|
879
|
-
stepsExpand: "Ver el detalle de los pasos",
|
|
880
|
-
stepsCollapse: "Plegar los pasos",
|
|
881
|
-
earlierSteps: (n) => n === 1 ? "1 paso antes" : `${n} pasos antes`,
|
|
882
|
-
withProblems: (n) => n === 1 ? "1 con problemas" : `${n} con problemas`,
|
|
883
|
-
running: "Ejecutando",
|
|
884
|
-
done: "Lista",
|
|
885
|
-
failed: "Fall\xF3",
|
|
886
|
-
step: "Paso",
|
|
887
|
-
replyOptions: "Opciones para responder",
|
|
888
|
-
linkTitle: "Vas a salir de aqu\xED",
|
|
889
|
-
linkCopy: "Copiar",
|
|
890
|
-
linkCopied: "Copiado",
|
|
891
|
-
linkOpen: "Abrir",
|
|
892
|
-
close: "Cerrar",
|
|
893
|
-
goToLatest: "Ir al \xFAltimo mensaje",
|
|
894
|
-
steps: { waking: "Despertando al agente\u2026", session: "Preparando la sesi\xF3n\u2026", compacting: "Resumiendo la conversaci\xF3n\u2026" },
|
|
895
|
-
loadOlder: "Cargar mensajes anteriores",
|
|
896
|
-
loadingOlder: "Cargando\u2026",
|
|
897
|
-
continueRun: "Continuar",
|
|
898
|
-
runCut: "La respuesta se cort\xF3 antes de terminar.",
|
|
899
|
-
stalled: "Se ator\xF3, sigo intentando\u2026",
|
|
900
|
-
truncated: "La respuesta qued\xF3 incompleta.",
|
|
901
|
-
attachmentFailed: (name, reason) => reason ? `No pude leer ${name}: ${reason}` : `No pude leer ${name}`,
|
|
902
|
-
queued: "Se manda cuando termine",
|
|
903
|
-
subagentsWorking: (n) => n === 1 ? "1 agente trabajando" : `${n} agentes trabajando`,
|
|
904
|
-
subagentsDone: (n) => n === 1 ? "1 agente termin\xF3" : `${n} agentes terminaron`,
|
|
905
|
-
subagentStop: "Detener",
|
|
906
|
-
subagentStatus: { running: "Trabajando", completed: "Termin\xF3", failed: "Fall\xF3", stopped: "Detenido" },
|
|
907
|
-
confirmTitle: "Necesito tu permiso para",
|
|
908
|
-
approve: "Aprobar",
|
|
909
|
-
reject: "Rechazar",
|
|
910
|
-
expiresIn: (t) => `Vence en ${t}`,
|
|
911
|
-
expiredNow: "Venci\xF3 sin respuesta",
|
|
912
|
-
decisionApproved: "Aprobaste",
|
|
913
|
-
decisionRejected: "Rechazaste",
|
|
914
|
-
decisionExpired: "Venci\xF3",
|
|
915
|
-
decisionCancelled: "Descartaste",
|
|
916
|
-
stampCancelled: "Descartado",
|
|
917
|
-
stampApproved: "Aprobado",
|
|
918
|
-
stampRejected: "Rechazado",
|
|
919
|
-
stampExpired: "Vencido"
|
|
920
|
-
};
|
|
921
|
-
var STRINGS_EN = {
|
|
922
|
-
numberLocale: "en-US",
|
|
923
|
-
placeholder: (agent) => `Message ${agent}`,
|
|
924
|
-
placeholderDefault: "Message the agent",
|
|
925
|
-
send: "Send",
|
|
926
|
-
stop: "Stop",
|
|
927
|
-
uploading: "Uploading your file\u2026",
|
|
928
|
-
uploadingN: (n) => `Uploading your ${n} files\u2026`,
|
|
929
|
-
attachImage: "Attach image",
|
|
930
|
-
attachFile: "Attach file",
|
|
931
|
-
noImages: "This agent can't see images",
|
|
932
|
-
removeAttachment: "Remove attachment",
|
|
933
|
-
removeReference: "Remove reference",
|
|
934
|
-
dropFiles: "Drop your files",
|
|
935
|
-
dropHint: "Excel, Word, PDF or images",
|
|
936
|
-
tooBig: (name, mb) => `${name} is larger than ${mb} MB`,
|
|
937
|
-
tooMany: (max) => `no more than ${max} files per message`,
|
|
938
|
-
cantSeeImage: (name) => `${name}: this agent can't see images`,
|
|
939
|
-
cantUpload: (name) => `${name}: only images and text can be sent here`,
|
|
940
|
-
uploadFailed: "couldn't upload the file",
|
|
941
|
-
recordVoice: "Record voice note",
|
|
942
|
-
voiceNote: "Voice note",
|
|
943
|
-
cancelVoice: "Cancel voice note",
|
|
944
|
-
stopAndSendVoice: "Stop and send voice note",
|
|
945
|
-
micDenied: "I don't have permission to use the microphone.",
|
|
946
|
-
voiceEmpty: "nothing was understood in the voice note",
|
|
947
|
-
voiceFailed: "couldn't send the voice note",
|
|
948
|
-
model: "Model",
|
|
949
|
-
thinking: "Thinking\u2026",
|
|
950
|
-
howItGoes: (s) => s < 6 ? "Thinking\u2026" : s < 15 ? "Working\u2026" : s < 60 ? "On it\u2026" : s < 120 ? "This is taking a bit\u2026" : s < 300 ? "Been at it a while\u2026" : "This is taking long \u2014 you can stop me",
|
|
951
|
-
stillWorking: "On it\u2026",
|
|
952
|
-
retry: "Retry",
|
|
953
|
-
copy: "Copy",
|
|
954
|
-
copied: "Copied",
|
|
955
|
-
copyMessage: "Copy message",
|
|
956
|
-
worked: (s) => `Worked ${s} s`,
|
|
957
|
-
stepsExpand: "See step details",
|
|
958
|
-
stepsCollapse: "Collapse the steps",
|
|
959
|
-
earlierSteps: (n) => n === 1 ? "1 earlier step" : `${n} earlier steps`,
|
|
960
|
-
withProblems: (n) => `${n} with problems`,
|
|
961
|
-
running: "Running",
|
|
962
|
-
done: "Done",
|
|
963
|
-
failed: "Failed",
|
|
964
|
-
step: "Step",
|
|
965
|
-
replyOptions: "Reply options",
|
|
966
|
-
linkTitle: "You're about to leave",
|
|
967
|
-
linkCopy: "Copy",
|
|
968
|
-
linkCopied: "Copied",
|
|
969
|
-
linkOpen: "Open",
|
|
970
|
-
close: "Close",
|
|
971
|
-
goToLatest: "Go to latest message",
|
|
972
|
-
steps: { waking: "Waking the agent\u2026", session: "Starting the session\u2026", compacting: "Compacting the conversation\u2026" },
|
|
973
|
-
loadOlder: "Load earlier messages",
|
|
974
|
-
loadingOlder: "Loading\u2026",
|
|
975
|
-
continueRun: "Continue",
|
|
976
|
-
runCut: "The answer was cut off before it finished.",
|
|
977
|
-
stalled: "Got stuck, still trying\u2026",
|
|
978
|
-
truncated: "The answer is incomplete.",
|
|
979
|
-
attachmentFailed: (name, reason) => reason ? `Couldn't read ${name}: ${reason}` : `Couldn't read ${name}`,
|
|
980
|
-
queued: "Sends when this finishes",
|
|
981
|
-
subagentsWorking: (n) => n === 1 ? "1 agent working" : `${n} agents working`,
|
|
982
|
-
subagentsDone: (n) => n === 1 ? "1 agent finished" : `${n} agents finished`,
|
|
983
|
-
subagentStop: "Stop",
|
|
984
|
-
subagentStatus: { running: "Working", completed: "Done", failed: "Failed", stopped: "Stopped" },
|
|
985
|
-
confirmTitle: "I need your permission to",
|
|
986
|
-
approve: "Approve",
|
|
987
|
-
reject: "Reject",
|
|
988
|
-
expiresIn: (t) => `Expires in ${t}`,
|
|
989
|
-
expiredNow: "Expired without an answer",
|
|
990
|
-
decisionApproved: "You approved",
|
|
991
|
-
decisionRejected: "You rejected",
|
|
992
|
-
decisionExpired: "Expired",
|
|
993
|
-
decisionCancelled: "You dismissed",
|
|
994
|
-
stampCancelled: "Dismissed",
|
|
995
|
-
stampApproved: "Approved",
|
|
996
|
-
stampRejected: "Rejected",
|
|
997
|
-
stampExpired: "Expired"
|
|
998
|
-
};
|
|
999
|
-
|
|
1000
|
-
// src/react/context.tsx
|
|
1001
|
-
var PilotoContext = createContext2({
|
|
1002
|
-
strings: STRINGS_ES,
|
|
1003
|
-
toolVerbs: TOOL_VERBS_ES,
|
|
1004
|
-
toolIcons: {},
|
|
1005
|
-
formatUserText: cleanUserText,
|
|
1006
|
-
theme: "light",
|
|
1007
|
-
skin: "ghosty",
|
|
1008
|
-
markdown: {}
|
|
1009
|
-
});
|
|
1010
|
-
var usePiloto = () => useContext2(PilotoContext);
|
|
1011
|
-
function rootProps(theme, skin = "ghosty") {
|
|
1012
|
-
return { className: "piloto", "data-theme": theme, "data-skin": skin };
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
// src/react/ConfirmCard.tsx
|
|
1016
118
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1017
119
|
var isRejectOption = (o) => /^reject|deny|cancel/i.test(o.kind ?? o.optionId);
|
|
1018
120
|
var mmss = (ms) => {
|
|
@@ -1101,10 +203,10 @@ function DecisionLines({ decisions }) {
|
|
|
1101
203
|
const { strings: t } = usePiloto();
|
|
1102
204
|
if (!decisions.length) return null;
|
|
1103
205
|
return /* @__PURE__ */ jsx("ul", { className: "piloto-decisions", children: decisions.map((d) => {
|
|
1104
|
-
const
|
|
206
|
+
const Icon = d.status === "approved" ? CircleCheck : d.status === "expired" ? Clock : CircleSlash;
|
|
1105
207
|
const label = d.status === "approved" ? t.decisionApproved : d.status === "rejected" ? t.decisionRejected : d.status === "cancelled" ? t.decisionCancelled : t.decisionExpired;
|
|
1106
208
|
return /* @__PURE__ */ jsxs("li", { className: "piloto-decision", "data-status": d.status, children: [
|
|
1107
|
-
/* @__PURE__ */ jsx(
|
|
209
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 shrink-0", "aria-hidden": true }),
|
|
1108
210
|
/* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
|
|
1109
211
|
/* @__PURE__ */ jsxs("strong", { children: [
|
|
1110
212
|
label,
|
|
@@ -1123,11 +225,11 @@ function DecisionLines({ decisions }) {
|
|
|
1123
225
|
}
|
|
1124
226
|
|
|
1125
227
|
// src/react/Markdown.tsx
|
|
1126
|
-
import { useState as useState3 } from "react";
|
|
228
|
+
import { useContext as useContext2, useState as useState3 } from "react";
|
|
1127
229
|
import { Streamdown } from "streamdown";
|
|
1128
230
|
|
|
1129
231
|
// src/react/TextAtPace.tsx
|
|
1130
|
-
import { createContext
|
|
232
|
+
import { createContext, memo, useContext, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
|
|
1131
233
|
import { Block } from "streamdown";
|
|
1132
234
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
1133
235
|
var CHUNK_MS = 400;
|
|
@@ -1195,9 +297,9 @@ function useTextAtPace(text, live, whole = false) {
|
|
|
1195
297
|
if (!animate.current) return { visible: text, animate: false };
|
|
1196
298
|
return { visible: text.slice(0, Math.min(released, text.length)), animate: true };
|
|
1197
299
|
}
|
|
1198
|
-
var ChunksContext =
|
|
300
|
+
var ChunksContext = createContext(null);
|
|
1199
301
|
function useChunkRegistry() {
|
|
1200
|
-
return
|
|
302
|
+
return useMemo(() => /* @__PURE__ */ new Map(), []);
|
|
1201
303
|
}
|
|
1202
304
|
var UNTOUCHED = /* @__PURE__ */ new Set(["pre", "code", "svg", "math", "script", "style"]);
|
|
1203
305
|
var STYLE = `gs-tramo ${CHUNK_MS}ms linear both`;
|
|
@@ -1253,9 +355,9 @@ function chunksPlugin(state) {
|
|
|
1253
355
|
};
|
|
1254
356
|
}
|
|
1255
357
|
var ChunkedBlock = memo(function ChunkedBlock2(props) {
|
|
1256
|
-
const ctx =
|
|
358
|
+
const ctx = useContext(ChunksContext);
|
|
1257
359
|
const key = `${ctx?.part ?? 0}-${props.index}`;
|
|
1258
|
-
const plugins =
|
|
360
|
+
const plugins = useMemo(() => {
|
|
1259
361
|
if (!ctx) return props.rehypePlugins;
|
|
1260
362
|
let state = ctx.registry.get(key);
|
|
1261
363
|
if (!state) {
|
|
@@ -1323,7 +425,8 @@ var linkSafety = { enabled: true, renderModal: (p) => /* @__PURE__ */ jsx3(LinkS
|
|
|
1323
425
|
function Markdown({ children, animate = false, className }) {
|
|
1324
426
|
const { markdown } = usePiloto();
|
|
1325
427
|
const registry = useChunkRegistry();
|
|
1326
|
-
const
|
|
428
|
+
const turn = useContext2(TurnContext);
|
|
429
|
+
const text = markdown.transform ? markdown.transform(children, turn) : children;
|
|
1327
430
|
const onClick = markdown.onLinkClick ? (e) => {
|
|
1328
431
|
const a = e.target.closest("a[href]");
|
|
1329
432
|
if (!a) return;
|
|
@@ -1339,7 +442,7 @@ function Markdown({ children, animate = false, className }) {
|
|
|
1339
442
|
{
|
|
1340
443
|
onClickCapture: onClick,
|
|
1341
444
|
className: `ghosty-md min-w-0 max-w-full break-words ${className ?? "text-text-primary"} [&_pre]:max-w-full [&_pre]:overflow-x-auto [&_table]:block [&_table]:max-w-full [&_table]:overflow-x-auto`,
|
|
1342
|
-
children: animate ? /* @__PURE__ */ jsx3(ChunksContext.Provider, { value: { registry, part: 0 }, children: /* @__PURE__ */ jsx3(Streamdown, { BlockComponent: ChunkedBlock, linkSafety, children: text }) }) : /* @__PURE__ */ jsx3(Streamdown, { linkSafety, children: text })
|
|
445
|
+
children: animate ? /* @__PURE__ */ jsx3(ChunksContext.Provider, { value: { registry, part: 0 }, children: /* @__PURE__ */ jsx3(Streamdown, { BlockComponent: ChunkedBlock, linkSafety, components: markdown.components, children: text }) }) : /* @__PURE__ */ jsx3(Streamdown, { linkSafety, components: markdown.components, children: text })
|
|
1343
446
|
}
|
|
1344
447
|
)
|
|
1345
448
|
);
|
|
@@ -1442,7 +545,7 @@ var DEFAULT_TOOL_ICONS = {
|
|
|
1442
545
|
};
|
|
1443
546
|
function iconFor(t, icons) {
|
|
1444
547
|
for (const name of toolNames(t)) if (icons[name]) return icons[name];
|
|
1445
|
-
return t.kind && (icons[t.kind] ?? DEFAULT_TOOL_ICONS[t.kind]) ||
|
|
548
|
+
return t.kind && (icons[t.kind] ?? DEFAULT_TOOL_ICONS[t.kind]) || icons["*"] || Wrench;
|
|
1446
549
|
}
|
|
1447
550
|
var VISIBLE = 5;
|
|
1448
551
|
function AgentSteps({ tools, live }) {
|
|
@@ -1675,9 +778,19 @@ function TurnFooter({ text, seconds, onRetry, showCopy = true, showDuration = tr
|
|
|
1675
778
|
] })
|
|
1676
779
|
] });
|
|
1677
780
|
}
|
|
1678
|
-
function AgentBubble(
|
|
781
|
+
function AgentBubble(props) {
|
|
782
|
+
const { turn, avatar } = props;
|
|
783
|
+
const body = /* @__PURE__ */ jsx6(AgentBody, { ...props, showUsage: props.showUsage ?? true, showCopy: props.showCopy ?? true, showDuration: props.showDuration ?? true });
|
|
784
|
+
return /* @__PURE__ */ jsx6(TurnContext.Provider, { value: turn, children: avatar ? /* @__PURE__ */ jsxs4("div", { className: "flex items-start gap-3", children: [
|
|
785
|
+
/* @__PURE__ */ jsx6("div", { className: "mt-0.5 shrink-0", children: avatar }),
|
|
786
|
+
body
|
|
787
|
+
] }) : body });
|
|
788
|
+
}
|
|
789
|
+
function AgentBody({ turn, live, onRetry, onOption, showUsage, showCopy, showDuration, renderDeliveries, renderTools, renderBefore, blocks, narration = true }) {
|
|
1679
790
|
const { strings: t } = usePiloto();
|
|
1680
|
-
const
|
|
791
|
+
const extracted = blocks ? extractBlocks(turn.text ?? "", blocks.langs, turn.cuts) : { text: turn.text ?? "", cuts: turn.cuts, blocks: [] };
|
|
792
|
+
const closed = !live && !turn.tools?.some((x) => x.status === "pending");
|
|
793
|
+
const narrated = narration ? splitNarration(extracted.text, extracted.cuts, closed) : { steps: [], rest: extracted.text };
|
|
1681
794
|
const visible = narrated.rest;
|
|
1682
795
|
const options = onOption && !live && visible ? extractReplyOptions(visible) : null;
|
|
1683
796
|
return /* @__PURE__ */ jsxs4("div", { className: "gc-msg-agent min-w-0 max-w-[90%]", children: [
|
|
@@ -1686,6 +799,8 @@ function AgentBubble({ turn, live, onRetry, onOption, showUsage = true, showCopy
|
|
|
1686
799
|
/* @__PURE__ */ jsx6("p", { className: "mt-2 whitespace-pre-wrap border-l-2 border-border-secondary pl-3", children: turn.thought })
|
|
1687
800
|
] }),
|
|
1688
801
|
turn.tools && turn.tools.length > 0 && /* @__PURE__ */ jsx6(AgentSteps, { tools: turn.tools, live }),
|
|
802
|
+
turn.tools && turn.tools.length > 0 && renderTools?.(turn, live),
|
|
803
|
+
renderBefore?.(turn, live),
|
|
1689
804
|
narrated.steps.length > 0 && /* @__PURE__ */ jsx6(Narration, { steps: narrated.steps }),
|
|
1690
805
|
options ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1691
806
|
options.before && /* @__PURE__ */ jsx6(AnswerText, { text: options.before, live }),
|
|
@@ -1694,6 +809,7 @@ function AgentBubble({ turn, live, onRetry, onOption, showUsage = true, showCopy
|
|
|
1694
809
|
// Cada tramo nuevo tras una herramienta monta su propio ritmo (empieza de cero).
|
|
1695
810
|
visible && /* @__PURE__ */ jsx6(AnswerText, { text: visible, live }, `r${narrated.steps.length}`)
|
|
1696
811
|
),
|
|
812
|
+
extracted.blocks.length > 0 && blocks.render(extracted.blocks, turn, live),
|
|
1697
813
|
renderDeliveries?.(turn, live),
|
|
1698
814
|
turn.decisions?.length ? /* @__PURE__ */ jsx6(DecisionLines, { decisions: turn.decisions }) : null,
|
|
1699
815
|
showUsage && turn.usage && /* @__PURE__ */ jsx6(UsageStats, { ...turn.usage }),
|
|
@@ -1701,586 +817,13 @@ function AgentBubble({ turn, live, onRetry, onOption, showUsage = true, showCopy
|
|
|
1701
817
|
] });
|
|
1702
818
|
}
|
|
1703
819
|
|
|
1704
|
-
// src/react/Chips.tsx
|
|
1705
|
-
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1706
|
-
function ReferenceChips({ references, onRemove, onActivate }) {
|
|
1707
|
-
const { strings: t } = usePiloto();
|
|
1708
|
-
if (!references.length) return null;
|
|
1709
|
-
const pointed = references.filter((r) => r.prompt);
|
|
1710
|
-
const plain = references.filter((r) => !r.prompt);
|
|
1711
|
-
return /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1712
|
-
pointed.map((r) => /* @__PURE__ */ jsx7("div", { className: "mb-2 flex", children: /* @__PURE__ */ jsxs5("span", { className: "inline-flex max-w-full items-center gap-1.5 rounded-full border border-brand-500/40 bg-brand-500/10 py-1 pl-2.5 pr-1 text-xs text-text-primary", children: [
|
|
1713
|
-
/* @__PURE__ */ jsx7(Crosshair, { size: 13, className: "shrink-0 text-brand-500" }),
|
|
1714
|
-
/* @__PURE__ */ jsx7("span", { className: "shrink-0 font-semibold", children: r.label }),
|
|
1715
|
-
r.hint && /* @__PURE__ */ jsxs5("span", { className: "truncate text-text-secondary", children: [
|
|
1716
|
-
"\xAB",
|
|
1717
|
-
r.hint,
|
|
1718
|
-
"\xBB"
|
|
1719
|
-
] }),
|
|
1720
|
-
/* @__PURE__ */ jsx7(
|
|
1721
|
-
"button",
|
|
1722
|
-
{
|
|
1723
|
-
type: "button",
|
|
1724
|
-
onClick: () => onRemove(r.id),
|
|
1725
|
-
"aria-label": t.removeReference,
|
|
1726
|
-
className: "grid size-5 shrink-0 cursor-pointer place-items-center rounded-full text-text-tertiary hover:bg-background-secondary hover:text-text-primary",
|
|
1727
|
-
children: /* @__PURE__ */ jsx7(X, { size: 12 })
|
|
1728
|
-
}
|
|
1729
|
-
)
|
|
1730
|
-
] }) }, r.id)),
|
|
1731
|
-
plain.length > 0 && /* @__PURE__ */ jsx7("div", { className: "flex flex-wrap gap-1.5", children: plain.map((r) => /* @__PURE__ */ jsxs5("span", { className: "inline-flex items-center gap-1 rounded-full border border-border-primary bg-background-secondary py-0.5 pl-2 pr-1 text-xs text-text-primary", children: [
|
|
1732
|
-
/* @__PURE__ */ jsx7("button", { type: "button", onClick: () => onActivate?.(r), className: "underline-offset-2 hover:underline", children: r.label }),
|
|
1733
|
-
/* @__PURE__ */ jsx7(
|
|
1734
|
-
"button",
|
|
1735
|
-
{
|
|
1736
|
-
type: "button",
|
|
1737
|
-
onClick: () => onRemove(r.id),
|
|
1738
|
-
"aria-label": t.removeReference,
|
|
1739
|
-
className: "flex h-4 w-4 items-center justify-center rounded-full text-text-tertiary hover:bg-background-tertiary hover:text-text-primary",
|
|
1740
|
-
children: /* @__PURE__ */ jsx7(X, { className: "h-3 w-3" })
|
|
1741
|
-
}
|
|
1742
|
-
)
|
|
1743
|
-
] }, r.id)) })
|
|
1744
|
-
] });
|
|
1745
|
-
}
|
|
1746
|
-
function Suggestions({ items, onPick, onPrefill, disabled }) {
|
|
1747
|
-
if (!items.length) return null;
|
|
1748
|
-
return /* @__PURE__ */ jsx7("div", { className: "mt-4 flex flex-wrap justify-center gap-2", children: items.map((c) => /* @__PURE__ */ jsx7(
|
|
1749
|
-
"button",
|
|
1750
|
-
{
|
|
1751
|
-
type: "button",
|
|
1752
|
-
onClick: () => onPrefill && /:\s*$/.test(c) ? onPrefill(c) : onPick(c),
|
|
1753
|
-
disabled,
|
|
1754
|
-
className: "gc-chip rounded-full bg-irongray/10 px-3.5 py-1.5 text-xs font-medium text-metal transition-colors hover:bg-irongray/20 hover:text-dark disabled:opacity-40",
|
|
1755
|
-
children: c
|
|
1756
|
-
},
|
|
1757
|
-
c
|
|
1758
|
-
)) });
|
|
1759
|
-
}
|
|
1760
|
-
|
|
1761
|
-
// src/react/Composer.tsx
|
|
1762
|
-
import { useCallback, useEffect as useEffect3, useRef as useRef3, useState as useState6 } from "react";
|
|
1763
|
-
import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1764
|
-
var MAX_HEIGHT = 240;
|
|
1765
|
-
var BY_EXTENSION = {
|
|
1766
|
-
png: "image/png",
|
|
1767
|
-
jpg: "image/jpeg",
|
|
1768
|
-
jpeg: "image/jpeg",
|
|
1769
|
-
gif: "image/gif",
|
|
1770
|
-
webp: "image/webp",
|
|
1771
|
-
heic: "image/heic",
|
|
1772
|
-
pdf: "application/pdf",
|
|
1773
|
-
csv: "text/csv",
|
|
1774
|
-
txt: "text/plain",
|
|
1775
|
-
md: "text/markdown",
|
|
1776
|
-
json: "application/json"
|
|
1777
|
-
};
|
|
1778
|
-
function mimeOf(file) {
|
|
1779
|
-
if (file.type) return file.type;
|
|
1780
|
-
const ext = (file.name.match(/\.([A-Za-z0-9]+)$/)?.[1] || "").toLowerCase();
|
|
1781
|
-
return BY_EXTENSION[ext] ?? "application/octet-stream";
|
|
1782
|
-
}
|
|
1783
|
-
var isText = (mime) => mime.startsWith("text/") || mime === "application/json" || mime.endsWith("+json") || mime.endsWith("+xml");
|
|
1784
|
-
function shortSize(bytes) {
|
|
1785
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
1786
|
-
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
1787
|
-
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
1788
|
-
}
|
|
1789
|
-
function readInline(file) {
|
|
1790
|
-
return new Promise((resolve, reject) => {
|
|
1791
|
-
const fr = new FileReader();
|
|
1792
|
-
fr.onload = () => {
|
|
1793
|
-
const result = String(fr.result);
|
|
1794
|
-
const comma = result.indexOf(",");
|
|
1795
|
-
resolve({ name: file.name, mimeType: mimeOf(file), data: comma === -1 ? result : result.slice(comma + 1) });
|
|
1796
|
-
};
|
|
1797
|
-
fr.onerror = () => reject(fr.error);
|
|
1798
|
-
fr.readAsDataURL(file);
|
|
1799
|
-
});
|
|
1800
|
-
}
|
|
1801
|
-
function Composer({
|
|
1802
|
-
onSubmit,
|
|
1803
|
-
onStop,
|
|
1804
|
-
busy = false,
|
|
1805
|
-
canSteer = true,
|
|
1806
|
-
placeholder,
|
|
1807
|
-
initialValue = "",
|
|
1808
|
-
autoFocus = true,
|
|
1809
|
-
canSeeImages = true,
|
|
1810
|
-
attachments: withFiles = false,
|
|
1811
|
-
upload,
|
|
1812
|
-
transcribe,
|
|
1813
|
-
voiceNoteText,
|
|
1814
|
-
models = [],
|
|
1815
|
-
currentModel = null,
|
|
1816
|
-
onModelChange,
|
|
1817
|
-
references = [],
|
|
1818
|
-
onRemoveReference,
|
|
1819
|
-
onActivateReference,
|
|
1820
|
-
extras,
|
|
1821
|
-
maxFiles = 8,
|
|
1822
|
-
maxFileMb = 25
|
|
1823
|
-
}) {
|
|
1824
|
-
const { strings: t } = usePiloto();
|
|
1825
|
-
const [value, setValue] = useState6(initialValue);
|
|
1826
|
-
const [files, setFiles] = useState6([]);
|
|
1827
|
-
const [dragging, setDragging] = useState6(false);
|
|
1828
|
-
const [notice, setNotice] = useState6(null);
|
|
1829
|
-
const [uploading, setUploading] = useState6(false);
|
|
1830
|
-
const ref = useRef3(null);
|
|
1831
|
-
const fileRef = useRef3(null);
|
|
1832
|
-
const nextId = useRef3(0);
|
|
1833
|
-
const urls = useRef3(/* @__PURE__ */ new Set());
|
|
1834
|
-
const releaseUrl = (url) => {
|
|
1835
|
-
urls.current.delete(url);
|
|
1836
|
-
URL.revokeObjectURL(url);
|
|
1837
|
-
};
|
|
1838
|
-
useEffect3(() => {
|
|
1839
|
-
if (!autoFocus) return;
|
|
1840
|
-
const id = requestAnimationFrame(() => {
|
|
1841
|
-
const el = ref.current;
|
|
1842
|
-
if (!el) return;
|
|
1843
|
-
el.focus({ preventScroll: true });
|
|
1844
|
-
el.setSelectionRange(el.value.length, el.value.length);
|
|
1845
|
-
});
|
|
1846
|
-
return () => cancelAnimationFrame(id);
|
|
1847
|
-
}, [autoFocus]);
|
|
1848
|
-
useEffect3(
|
|
1849
|
-
() => () => {
|
|
1850
|
-
for (const url of urls.current) URL.revokeObjectURL(url);
|
|
1851
|
-
urls.current.clear();
|
|
1852
|
-
},
|
|
1853
|
-
[]
|
|
1854
|
-
);
|
|
1855
|
-
useEffect3(() => {
|
|
1856
|
-
const el = ref.current;
|
|
1857
|
-
if (!el) return;
|
|
1858
|
-
if (!value) {
|
|
1859
|
-
el.style.height = "";
|
|
1860
|
-
return;
|
|
1861
|
-
}
|
|
1862
|
-
el.style.height = "0px";
|
|
1863
|
-
el.style.height = `${Math.min(el.scrollHeight, MAX_HEIGHT)}px`;
|
|
1864
|
-
}, [value]);
|
|
1865
|
-
const addFiles = useCallback(
|
|
1866
|
-
(list) => {
|
|
1867
|
-
if (busy) return;
|
|
1868
|
-
const rejected = [];
|
|
1869
|
-
setFiles((prev) => {
|
|
1870
|
-
const next = [...prev];
|
|
1871
|
-
for (const file of Array.from(list)) {
|
|
1872
|
-
const mime = mimeOf(file);
|
|
1873
|
-
if (file.size > maxFileMb * 1024 * 1024) {
|
|
1874
|
-
rejected.push(t.tooBig(file.name, maxFileMb));
|
|
1875
|
-
continue;
|
|
1876
|
-
}
|
|
1877
|
-
if (next.length >= maxFiles) {
|
|
1878
|
-
rejected.push(t.tooMany(maxFiles));
|
|
1879
|
-
break;
|
|
1880
|
-
}
|
|
1881
|
-
if (mime.startsWith("image/") && !canSeeImages) {
|
|
1882
|
-
rejected.push(t.cantSeeImage(file.name));
|
|
1883
|
-
continue;
|
|
1884
|
-
}
|
|
1885
|
-
if (!mime.startsWith("image/") && !isText(mime) && !upload) {
|
|
1886
|
-
rejected.push(t.cantUpload(file.name));
|
|
1887
|
-
continue;
|
|
1888
|
-
}
|
|
1889
|
-
const url = URL.createObjectURL(file);
|
|
1890
|
-
urls.current.add(url);
|
|
1891
|
-
next.push({ id: ++nextId.current, file, url });
|
|
1892
|
-
}
|
|
1893
|
-
return next;
|
|
1894
|
-
});
|
|
1895
|
-
setNotice(rejected.length ? rejected.join(" \xB7 ") : null);
|
|
1896
|
-
ref.current?.focus({ preventScroll: true });
|
|
1897
|
-
},
|
|
1898
|
-
[busy, canSeeImages, upload, maxFiles, maxFileMb, t]
|
|
1899
|
-
);
|
|
1900
|
-
useEffect3(() => {
|
|
1901
|
-
if (!withFiles) return;
|
|
1902
|
-
let inside = 0;
|
|
1903
|
-
const hasFiles = (e) => Array.from(e.dataTransfer?.types ?? []).includes("Files");
|
|
1904
|
-
const enter = (e) => {
|
|
1905
|
-
if (!hasFiles(e)) return;
|
|
1906
|
-
e.preventDefault();
|
|
1907
|
-
inside++;
|
|
1908
|
-
if (!busy) setDragging(true);
|
|
1909
|
-
};
|
|
1910
|
-
const over = (e) => {
|
|
1911
|
-
if (hasFiles(e)) e.preventDefault();
|
|
1912
|
-
};
|
|
1913
|
-
const leave = (e) => {
|
|
1914
|
-
if (!hasFiles(e)) return;
|
|
1915
|
-
inside = Math.max(0, inside - 1);
|
|
1916
|
-
if (inside === 0) setDragging(false);
|
|
1917
|
-
};
|
|
1918
|
-
const drop = (e) => {
|
|
1919
|
-
if (!hasFiles(e)) return;
|
|
1920
|
-
e.preventDefault();
|
|
1921
|
-
inside = 0;
|
|
1922
|
-
setDragging(false);
|
|
1923
|
-
if (e.dataTransfer?.files.length) addFiles(e.dataTransfer.files);
|
|
1924
|
-
};
|
|
1925
|
-
window.addEventListener("dragenter", enter);
|
|
1926
|
-
window.addEventListener("dragover", over);
|
|
1927
|
-
window.addEventListener("dragleave", leave);
|
|
1928
|
-
window.addEventListener("drop", drop);
|
|
1929
|
-
return () => {
|
|
1930
|
-
window.removeEventListener("dragenter", enter);
|
|
1931
|
-
window.removeEventListener("dragover", over);
|
|
1932
|
-
window.removeEventListener("dragleave", leave);
|
|
1933
|
-
window.removeEventListener("drop", drop);
|
|
1934
|
-
};
|
|
1935
|
-
}, [withFiles, busy, addFiles]);
|
|
1936
|
-
const removeFile = (id) => setFiles((prev) => {
|
|
1937
|
-
const out = prev.find((a) => a.id === id);
|
|
1938
|
-
if (out) releaseUrl(out.url);
|
|
1939
|
-
return prev.filter((a) => a.id !== id);
|
|
1940
|
-
});
|
|
1941
|
-
const submit = async () => {
|
|
1942
|
-
const body = value.trim();
|
|
1943
|
-
if (!body && files.length === 0 && references.length === 0) return;
|
|
1944
|
-
if (busy && (files.length > 0 || !canSteer)) return;
|
|
1945
|
-
if (uploading) return;
|
|
1946
|
-
let atts = [];
|
|
1947
|
-
if (files.length) setUploading(true);
|
|
1948
|
-
try {
|
|
1949
|
-
atts = await Promise.all(
|
|
1950
|
-
files.map(async (a) => {
|
|
1951
|
-
const mime = mimeOf(a.file);
|
|
1952
|
-
if (mime.startsWith("image/") || isText(mime)) return readInline(a.file);
|
|
1953
|
-
const up = await upload(a.file);
|
|
1954
|
-
return { name: a.file.name, mimeType: mime, url: up.url };
|
|
1955
|
-
})
|
|
1956
|
-
);
|
|
1957
|
-
} catch (e) {
|
|
1958
|
-
setNotice(e instanceof Error ? e.message : t.uploadFailed);
|
|
1959
|
-
return;
|
|
1960
|
-
} finally {
|
|
1961
|
-
setUploading(false);
|
|
1962
|
-
}
|
|
1963
|
-
onSubmit(body, atts);
|
|
1964
|
-
setValue("");
|
|
1965
|
-
setNotice(null);
|
|
1966
|
-
for (const a of files) releaseUrl(a.url);
|
|
1967
|
-
setFiles([]);
|
|
1968
|
-
};
|
|
1969
|
-
const [recording, setRecording] = useState6(false);
|
|
1970
|
-
const [transcribing, setTranscribing] = useState6(false);
|
|
1971
|
-
const [wave, setWave] = useState6([]);
|
|
1972
|
-
const [seconds, setSeconds] = useState6(0);
|
|
1973
|
-
const recRef = useRef3(null);
|
|
1974
|
-
const pieces = useRef3([]);
|
|
1975
|
-
const cancelRef = useRef3(false);
|
|
1976
|
-
const meter = useRef3(null);
|
|
1977
|
-
const [hasMic, setHasMic] = useState6(false);
|
|
1978
|
-
useEffect3(() => setHasMic(typeof window !== "undefined" && "MediaRecorder" in window && Boolean(navigator.mediaDevices?.getUserMedia)), []);
|
|
1979
|
-
const canRecord = Boolean(transcribe) && hasMic;
|
|
1980
|
-
const toggleRecording = async () => {
|
|
1981
|
-
if (recording) {
|
|
1982
|
-
cancelRef.current = false;
|
|
1983
|
-
recRef.current?.stop();
|
|
1984
|
-
return;
|
|
1985
|
-
}
|
|
1986
|
-
try {
|
|
1987
|
-
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
1988
|
-
const mime = ["audio/webm;codecs=opus", "audio/webm", "audio/mp4"].find((m) => MediaRecorder.isTypeSupported(m)) ?? "";
|
|
1989
|
-
const rec = new MediaRecorder(stream, mime ? { mimeType: mime } : void 0);
|
|
1990
|
-
pieces.current = [];
|
|
1991
|
-
rec.ondataavailable = (e) => {
|
|
1992
|
-
if (e.data.size > 0) pieces.current.push(e.data);
|
|
1993
|
-
};
|
|
1994
|
-
const ctx = new AudioContext();
|
|
1995
|
-
const an = ctx.createAnalyser();
|
|
1996
|
-
an.fftSize = 512;
|
|
1997
|
-
ctx.createMediaStreamSource(stream).connect(an);
|
|
1998
|
-
const buf = new Uint8Array(an.fftSize);
|
|
1999
|
-
let lastTick = 0;
|
|
2000
|
-
const tick = (time) => {
|
|
2001
|
-
if (time - lastTick > 80) {
|
|
2002
|
-
lastTick = time;
|
|
2003
|
-
an.getByteTimeDomainData(buf);
|
|
2004
|
-
let acc = 0;
|
|
2005
|
-
for (let i = 0; i < buf.length; i++) {
|
|
2006
|
-
const v = (buf[i] - 128) / 128;
|
|
2007
|
-
acc += v * v;
|
|
2008
|
-
}
|
|
2009
|
-
setWave((w) => [...w.slice(-59), Math.min(1, Math.sqrt(acc / buf.length) * 4)]);
|
|
2010
|
-
}
|
|
2011
|
-
if (meter.current) meter.current.raf = requestAnimationFrame(tick);
|
|
2012
|
-
};
|
|
2013
|
-
const start = Date.now();
|
|
2014
|
-
meter.current = { ctx, raf: requestAnimationFrame(tick), timer: window.setInterval(() => setSeconds(Math.floor((Date.now() - start) / 1e3)), 250) };
|
|
2015
|
-
rec.onstop = async () => {
|
|
2016
|
-
stream.getTracks().forEach((tr) => tr.stop());
|
|
2017
|
-
if (meter.current) {
|
|
2018
|
-
cancelAnimationFrame(meter.current.raf);
|
|
2019
|
-
clearInterval(meter.current.timer);
|
|
2020
|
-
void meter.current.ctx.close();
|
|
2021
|
-
meter.current = null;
|
|
2022
|
-
}
|
|
2023
|
-
setRecording(false);
|
|
2024
|
-
setWave([]);
|
|
2025
|
-
setSeconds(0);
|
|
2026
|
-
if (cancelRef.current) return;
|
|
2027
|
-
const type = rec.mimeType || mime || "audio/webm";
|
|
2028
|
-
const blob = new Blob(pieces.current, { type });
|
|
2029
|
-
if (blob.size < 1e3) return;
|
|
2030
|
-
setTranscribing(true);
|
|
2031
|
-
try {
|
|
2032
|
-
const ext = type.includes("mp4") ? "m4a" : "webm";
|
|
2033
|
-
const name = `nota-de-voz-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.${ext}`;
|
|
2034
|
-
const [said, up] = await Promise.all([transcribe(blob), upload ? upload(new File([blob], name, { type })) : Promise.resolve(null)]);
|
|
2035
|
-
const text = said.trim();
|
|
2036
|
-
if (!text) throw new Error(t.voiceEmpty);
|
|
2037
|
-
const atts = up ? [{ name, mimeType: type, url: up.url }] : [];
|
|
2038
|
-
onSubmit(voiceNoteText ? voiceNoteText(text) : text, atts);
|
|
2039
|
-
setNotice(null);
|
|
2040
|
-
} catch (e) {
|
|
2041
|
-
setNotice(e instanceof Error ? e.message : t.voiceFailed);
|
|
2042
|
-
} finally {
|
|
2043
|
-
setTranscribing(false);
|
|
2044
|
-
}
|
|
2045
|
-
};
|
|
2046
|
-
recRef.current = rec;
|
|
2047
|
-
rec.start();
|
|
2048
|
-
setRecording(true);
|
|
2049
|
-
} catch {
|
|
2050
|
-
setNotice(t.micDenied);
|
|
2051
|
-
}
|
|
2052
|
-
};
|
|
2053
|
-
const canSend = Boolean(value.trim() || files.length > 0 || references.length > 0);
|
|
2054
|
-
return /* @__PURE__ */ jsx8("div", { className: "gc-input rounded-(--piloto-radius-input) border-(length:--piloto-border-width) border-outlines bg-(--piloto-composer-bg) shadow-(--piloto-shadow-input) transition-colors focus-within:border-brand-300", children: /* @__PURE__ */ jsxs6("div", { className: `flex flex-col gap-2 p-3 transition-shadow ${withFiles && dragging ? "rounded-2xl bg-background-secondary/40 ring-2 ring-inset ring-ring-info" : ""}`, children: [
|
|
2055
|
-
withFiles && dragging && /* @__PURE__ */ jsx8("div", { className: "pointer-events-none fixed inset-0 z-50 flex items-center justify-center bg-background-primary/80 p-6 backdrop-blur-sm", children: /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center gap-2 rounded-3xl border-2 border-dashed border-brand-500 bg-background-primary px-10 py-8 text-center shadow-lg", children: [
|
|
2056
|
-
/* @__PURE__ */ jsx8(Paperclip, { className: "size-7 text-brand-500" }),
|
|
2057
|
-
/* @__PURE__ */ jsx8("p", { className: "text-base font-semibold text-text-primary", children: t.dropFiles }),
|
|
2058
|
-
/* @__PURE__ */ jsx8("p", { className: "text-xs text-text-secondary", children: t.dropHint })
|
|
2059
|
-
] }) }),
|
|
2060
|
-
/* @__PURE__ */ jsx8(
|
|
2061
|
-
"input",
|
|
2062
|
-
{
|
|
2063
|
-
ref: fileRef,
|
|
2064
|
-
type: "file",
|
|
2065
|
-
multiple: true,
|
|
2066
|
-
hidden: true,
|
|
2067
|
-
onChange: (e) => {
|
|
2068
|
-
if (e.target.files) addFiles(e.target.files);
|
|
2069
|
-
e.target.value = "";
|
|
2070
|
-
}
|
|
2071
|
-
}
|
|
2072
|
-
),
|
|
2073
|
-
notice && /* @__PURE__ */ jsx8("p", { className: "text-xs text-text-danger", children: notice }),
|
|
2074
|
-
uploading && /* @__PURE__ */ jsxs6("p", { className: "flex items-center gap-1.5 text-xs text-text-secondary", children: [
|
|
2075
|
-
/* @__PURE__ */ jsx8(LoaderCircle, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
2076
|
-
files.length > 1 ? t.uploadingN(files.length) : t.uploading
|
|
2077
|
-
] }),
|
|
2078
|
-
withFiles && files.length > 0 && /* @__PURE__ */ jsx8("div", { className: "flex flex-wrap gap-2", children: files.map((a) => /* @__PURE__ */ jsxs6("div", { className: "relative h-16 w-16 overflow-hidden rounded-lg border border-border-primary bg-background-secondary", children: [
|
|
2079
|
-
mimeOf(a.file).startsWith("image/") ? /* @__PURE__ */ jsx8("img", { src: a.url, alt: a.file.name, className: "h-full w-full object-cover" }) : (
|
|
2080
|
-
// Un PDF pintado con <img> es un recuadro roto: nombre, extensión y peso.
|
|
2081
|
-
/* @__PURE__ */ jsxs6("span", { className: "flex h-full w-full flex-col items-center justify-center gap-1 px-1 text-center", title: a.file.name, children: [
|
|
2082
|
-
/* @__PURE__ */ jsx8(FileText, { className: "h-4 w-4 shrink-0 text-text-tertiary" }),
|
|
2083
|
-
/* @__PURE__ */ jsx8("span", { className: "w-full truncate text-[9px] font-medium uppercase leading-none text-text-secondary", children: a.file.name.match(/\.([A-Za-z0-9]+)$/)?.[1] ?? "file" }),
|
|
2084
|
-
/* @__PURE__ */ jsx8("span", { className: "w-full truncate text-[9px] leading-none text-text-tertiary", children: shortSize(a.file.size) })
|
|
2085
|
-
] })
|
|
2086
|
-
),
|
|
2087
|
-
/* @__PURE__ */ jsx8(
|
|
2088
|
-
"button",
|
|
2089
|
-
{
|
|
2090
|
-
type: "button",
|
|
2091
|
-
onClick: () => removeFile(a.id),
|
|
2092
|
-
"aria-label": t.removeAttachment,
|
|
2093
|
-
className: "absolute top-0.5 right-0.5 flex h-5 w-5 items-center justify-center rounded-full bg-background-inverse/80 text-text-inverse shadow-sm transition-colors hover:bg-background-inverse",
|
|
2094
|
-
children: /* @__PURE__ */ jsx8(X, { className: "h-3 w-3" })
|
|
2095
|
-
}
|
|
2096
|
-
)
|
|
2097
|
-
] }, a.id)) }),
|
|
2098
|
-
/* @__PURE__ */ jsx8(ReferenceChips, { references, onRemove: (id) => onRemoveReference?.(id), onActivate: onActivateReference }),
|
|
2099
|
-
recording ? (
|
|
2100
|
-
// Grabando: la barra sustituye al campo de texto — punto rojo, reloj, la onda y las dos salidas.
|
|
2101
|
-
/* @__PURE__ */ jsxs6("div", { className: "flex min-h-[24px] items-center gap-3 px-1", children: [
|
|
2102
|
-
/* @__PURE__ */ jsx8(
|
|
2103
|
-
"button",
|
|
2104
|
-
{
|
|
2105
|
-
type: "button",
|
|
2106
|
-
onClick: () => {
|
|
2107
|
-
cancelRef.current = true;
|
|
2108
|
-
recRef.current?.stop();
|
|
2109
|
-
},
|
|
2110
|
-
"aria-label": t.cancelVoice,
|
|
2111
|
-
title: t.cancelVoice,
|
|
2112
|
-
className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-text-secondary hover:bg-background-secondary hover:text-text-primary",
|
|
2113
|
-
children: /* @__PURE__ */ jsx8(X, { className: "h-4 w-4" })
|
|
2114
|
-
}
|
|
2115
|
-
),
|
|
2116
|
-
/* @__PURE__ */ jsx8("span", { className: "h-2 w-2 shrink-0 animate-pulse rounded-full bg-red-500" }),
|
|
2117
|
-
/* @__PURE__ */ jsxs6("span", { className: "w-10 shrink-0 font-mono text-xs tabular-nums text-text-secondary", children: [
|
|
2118
|
-
Math.floor(seconds / 60),
|
|
2119
|
-
":",
|
|
2120
|
-
String(seconds % 60).padStart(2, "0")
|
|
2121
|
-
] }),
|
|
2122
|
-
/* @__PURE__ */ jsx8("div", { className: "flex h-6 min-w-0 flex-1 items-center gap-[2px] overflow-hidden", children: Array.from({ length: 60 }, (_, i) => wave[wave.length - 60 + i] ?? 0).map((v, i) => /* @__PURE__ */ jsx8("span", { className: "w-[3px] shrink-0 rounded-full bg-text-secondary/70", style: { height: `${Math.max(3, Math.round(v * 22))}px` } }, i)) }),
|
|
2123
|
-
/* @__PURE__ */ jsx8(
|
|
2124
|
-
"button",
|
|
2125
|
-
{
|
|
2126
|
-
type: "button",
|
|
2127
|
-
onClick: toggleRecording,
|
|
2128
|
-
"aria-label": t.stopAndSendVoice,
|
|
2129
|
-
title: t.send,
|
|
2130
|
-
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-brand-500 text-white hover:bg-brand-600",
|
|
2131
|
-
children: /* @__PURE__ */ jsx8(ArrowUp, { className: "h-4 w-4" })
|
|
2132
|
-
}
|
|
2133
|
-
)
|
|
2134
|
-
] })
|
|
2135
|
-
) : /* @__PURE__ */ jsx8(
|
|
2136
|
-
"textarea",
|
|
2137
|
-
{
|
|
2138
|
-
ref,
|
|
2139
|
-
rows: 1,
|
|
2140
|
-
value,
|
|
2141
|
-
placeholder,
|
|
2142
|
-
onChange: (e) => setValue(e.target.value),
|
|
2143
|
-
onKeyDown: (e) => {
|
|
2144
|
-
if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
|
|
2145
|
-
e.preventDefault();
|
|
2146
|
-
void submit();
|
|
2147
|
-
} else if (e.key === "Backspace" && !value && references.length) {
|
|
2148
|
-
e.preventDefault();
|
|
2149
|
-
onRemoveReference?.(references[references.length - 1].id);
|
|
2150
|
-
}
|
|
2151
|
-
},
|
|
2152
|
-
className: "max-h-60 min-h-[24px] w-full flex-none resize-none overflow-y-auto bg-transparent px-1 text-sm leading-6 text-text-primary outline-none placeholder:text-text-tertiary"
|
|
2153
|
-
}
|
|
2154
|
-
),
|
|
2155
|
-
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2156
|
-
/* @__PURE__ */ jsxs6("div", { className: "@container flex min-w-0 flex-1 items-center gap-1.5 overflow-hidden", children: [
|
|
2157
|
-
withFiles && /* @__PURE__ */ jsxs6(Fragment5, { children: [
|
|
2158
|
-
/* @__PURE__ */ jsx8(
|
|
2159
|
-
"button",
|
|
2160
|
-
{
|
|
2161
|
-
type: "button",
|
|
2162
|
-
onClick: () => {
|
|
2163
|
-
if (!fileRef.current) return;
|
|
2164
|
-
fileRef.current.accept = "image/*";
|
|
2165
|
-
fileRef.current.click();
|
|
2166
|
-
},
|
|
2167
|
-
disabled: busy || !canSeeImages || files.length >= maxFiles,
|
|
2168
|
-
"aria-label": canSeeImages ? t.attachImage : t.noImages,
|
|
2169
|
-
title: canSeeImages ? t.attachImage : t.noImages,
|
|
2170
|
-
className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-text-secondary transition-colors hover:bg-background-secondary hover:text-text-primary disabled:opacity-30",
|
|
2171
|
-
children: /* @__PURE__ */ jsx8(Image, { className: "h-4 w-4" })
|
|
2172
|
-
}
|
|
2173
|
-
),
|
|
2174
|
-
extras,
|
|
2175
|
-
/* @__PURE__ */ jsx8(
|
|
2176
|
-
"button",
|
|
2177
|
-
{
|
|
2178
|
-
type: "button",
|
|
2179
|
-
onClick: () => {
|
|
2180
|
-
if (!fileRef.current) return;
|
|
2181
|
-
fileRef.current.accept = "";
|
|
2182
|
-
fileRef.current.click();
|
|
2183
|
-
},
|
|
2184
|
-
disabled: busy || files.length >= maxFiles,
|
|
2185
|
-
"aria-label": t.attachFile,
|
|
2186
|
-
title: t.attachFile,
|
|
2187
|
-
className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-text-secondary transition-colors hover:bg-background-secondary hover:text-text-primary disabled:opacity-40",
|
|
2188
|
-
children: /* @__PURE__ */ jsx8(Paperclip, { className: "h-4 w-4" })
|
|
2189
|
-
}
|
|
2190
|
-
)
|
|
2191
|
-
] }),
|
|
2192
|
-
!withFiles && extras,
|
|
2193
|
-
models.length > 0 && onModelChange && /* @__PURE__ */ jsx8(ModelPicker, { models, current: currentModel, onChange: onModelChange })
|
|
2194
|
-
] }),
|
|
2195
|
-
/* @__PURE__ */ jsxs6("div", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
2196
|
-
canRecord && !recording && /* @__PURE__ */ jsx8(
|
|
2197
|
-
"button",
|
|
2198
|
-
{
|
|
2199
|
-
type: "button",
|
|
2200
|
-
onClick: toggleRecording,
|
|
2201
|
-
disabled: busy || transcribing,
|
|
2202
|
-
"aria-label": t.recordVoice,
|
|
2203
|
-
title: t.voiceNote,
|
|
2204
|
-
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-text-secondary transition-colors hover:bg-background-secondary hover:text-text-primary disabled:opacity-40",
|
|
2205
|
-
children: transcribing ? /* @__PURE__ */ jsx8("span", { className: "h-3.5 w-3.5 animate-spin rounded-full border-2 border-current border-t-transparent" }) : /* @__PURE__ */ jsx8(Mic, { className: "h-4 w-4" })
|
|
2206
|
-
}
|
|
2207
|
-
),
|
|
2208
|
-
/* @__PURE__ */ jsx8(
|
|
2209
|
-
"button",
|
|
2210
|
-
{
|
|
2211
|
-
type: "button",
|
|
2212
|
-
onClick: busy ? onStop : () => void submit(),
|
|
2213
|
-
disabled: !busy && !canSend || uploading,
|
|
2214
|
-
"aria-label": busy ? t.stop : uploading ? t.uploading : t.send,
|
|
2215
|
-
className: `gc-send flex h-8 w-8 items-center justify-center rounded-full transition-colors ${busy || canSend || uploading ? "bg-brand-500 text-white hover:bg-brand-600" : "bg-background-disabled text-text-disabled"}`,
|
|
2216
|
-
children: busy ? /* @__PURE__ */ jsx8(Square, { className: "h-3 w-3 fill-current" }) : uploading ? /* @__PURE__ */ jsx8(LoaderCircle, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx8(ArrowUp, { className: "h-4 w-4" })
|
|
2217
|
-
}
|
|
2218
|
-
)
|
|
2219
|
-
] })
|
|
2220
|
-
] })
|
|
2221
|
-
] }) });
|
|
2222
|
-
}
|
|
2223
|
-
function ModelPicker({ models, current, onChange }) {
|
|
2224
|
-
const { strings: t } = usePiloto();
|
|
2225
|
-
const [open, setOpen] = useState6(false);
|
|
2226
|
-
const box = useRef3(null);
|
|
2227
|
-
useEffect3(() => {
|
|
2228
|
-
if (!open) return;
|
|
2229
|
-
const outside = (e) => {
|
|
2230
|
-
if (!box.current?.contains(e.target)) setOpen(false);
|
|
2231
|
-
};
|
|
2232
|
-
const escape = (e) => e.key === "Escape" && setOpen(false);
|
|
2233
|
-
document.addEventListener("mousedown", outside);
|
|
2234
|
-
document.addEventListener("keydown", escape);
|
|
2235
|
-
return () => {
|
|
2236
|
-
document.removeEventListener("mousedown", outside);
|
|
2237
|
-
document.removeEventListener("keydown", escape);
|
|
2238
|
-
};
|
|
2239
|
-
}, [open]);
|
|
2240
|
-
if (models.length === 0) return null;
|
|
2241
|
-
const active = models.find((m) => m.value === current) ?? null;
|
|
2242
|
-
return /* @__PURE__ */ jsxs6("div", { ref: box, className: "relative", children: [
|
|
2243
|
-
/* @__PURE__ */ jsxs6(
|
|
2244
|
-
"button",
|
|
2245
|
-
{
|
|
2246
|
-
type: "button",
|
|
2247
|
-
"aria-expanded": open,
|
|
2248
|
-
onClick: () => setOpen((v) => !v),
|
|
2249
|
-
className: "flex max-w-56 items-center gap-1.5 rounded-full border border-border-primary px-2.5 py-1 text-xs text-text-secondary transition-colors outline-none hover:bg-background-secondary hover:text-text-primary",
|
|
2250
|
-
children: [
|
|
2251
|
-
/* @__PURE__ */ jsx8(Cpu, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
2252
|
-
/* @__PURE__ */ jsx8("span", { className: "truncate", children: active?.name ?? t.model }),
|
|
2253
|
-
/* @__PURE__ */ jsx8(ChevronDown, { className: "h-3.5 w-3.5 shrink-0 opacity-70" })
|
|
2254
|
-
]
|
|
2255
|
-
}
|
|
2256
|
-
),
|
|
2257
|
-
open && // Hacia ARRIBA: el selector vive pegado al borde inferior del input.
|
|
2258
|
-
/* @__PURE__ */ jsx8("div", { className: "absolute bottom-full left-0 z-20 mb-1 max-h-80 min-w-52 overflow-y-auto rounded-xl border border-border-primary bg-background-primary py-1 shadow-lg", children: models.map((m) => /* @__PURE__ */ jsxs6(
|
|
2259
|
-
"button",
|
|
2260
|
-
{
|
|
2261
|
-
type: "button",
|
|
2262
|
-
onClick: () => {
|
|
2263
|
-
onChange(m.value);
|
|
2264
|
-
setOpen(false);
|
|
2265
|
-
},
|
|
2266
|
-
className: "flex w-full items-center justify-between gap-3 px-3 py-1.5 text-left text-xs text-text-secondary transition-colors hover:bg-background-secondary hover:text-text-primary",
|
|
2267
|
-
children: [
|
|
2268
|
-
/* @__PURE__ */ jsx8("span", { className: "truncate", children: m.name }),
|
|
2269
|
-
m.value === current && /* @__PURE__ */ jsx8(Check, { className: "h-3.5 w-3.5 shrink-0 text-text-success" })
|
|
2270
|
-
]
|
|
2271
|
-
},
|
|
2272
|
-
m.value
|
|
2273
|
-
)) })
|
|
2274
|
-
] });
|
|
2275
|
-
}
|
|
2276
|
-
|
|
2277
820
|
// src/react/Status.tsx
|
|
2278
821
|
import { AnimatePresence as AnimatePresence2, motion as motion2 } from "motion/react";
|
|
2279
|
-
import { useEffect as
|
|
2280
|
-
import { jsx as
|
|
822
|
+
import { useEffect as useEffect3, useState as useState6 } from "react";
|
|
823
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2281
824
|
var STILL_WORKING_S = 90;
|
|
2282
825
|
function TypingDots() {
|
|
2283
|
-
return /* @__PURE__ */
|
|
826
|
+
return /* @__PURE__ */ jsx7("div", { className: "gc-typing flex gap-1", children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx7("span", { className: "gc-typing-dot h-2 w-2 animate-bounce rounded-full", style: { "--i": i } }, i)) });
|
|
2284
827
|
}
|
|
2285
828
|
function WaitLabel({
|
|
2286
829
|
since,
|
|
@@ -2288,9 +831,9 @@ function WaitLabel({
|
|
|
2288
831
|
step
|
|
2289
832
|
}) {
|
|
2290
833
|
const { strings: t } = usePiloto();
|
|
2291
|
-
const [mounted] =
|
|
2292
|
-
const [now, setNow] =
|
|
2293
|
-
|
|
834
|
+
const [mounted] = useState6(() => Date.now());
|
|
835
|
+
const [now, setNow] = useState6(() => Date.now());
|
|
836
|
+
useEffect3(() => {
|
|
2294
837
|
const id = setInterval(() => setNow(Date.now()), 1e3);
|
|
2295
838
|
return () => clearInterval(id);
|
|
2296
839
|
}, []);
|
|
@@ -2298,8 +841,8 @@ function WaitLabel({
|
|
|
2298
841
|
const phrases = t.thinkingPhrases;
|
|
2299
842
|
const stepText = step ? t.steps?.[step] : void 0;
|
|
2300
843
|
const what = stepText ? stepText : phrases?.length ? seconds >= STILL_WORKING_S ? t.stillWorking : phrases[Math.floor(seconds / 4) % phrases.length] : t.howItGoes(seconds);
|
|
2301
|
-
return /* @__PURE__ */
|
|
2302
|
-
/* @__PURE__ */
|
|
844
|
+
return /* @__PURE__ */ jsx7("div", { className: "flex flex-col gap-0.5 text-sm text-text-secondary", children: /* @__PURE__ */ jsxs5("p", { className: "flex items-center", children: [
|
|
845
|
+
/* @__PURE__ */ jsx7(AnimatePresence2, { mode: "wait", initial: false, children: /* @__PURE__ */ jsx7(
|
|
2303
846
|
motion2.span,
|
|
2304
847
|
{
|
|
2305
848
|
className: "gc-wait-text",
|
|
@@ -2311,7 +854,7 @@ function WaitLabel({
|
|
|
2311
854
|
},
|
|
2312
855
|
what
|
|
2313
856
|
) }),
|
|
2314
|
-
showDuration && /* @__PURE__ */
|
|
857
|
+
showDuration && /* @__PURE__ */ jsxs5("span", { className: "tabular-nums text-text-tertiary", children: [
|
|
2315
858
|
"\xA0\xB7 ",
|
|
2316
859
|
formatDuration(seconds)
|
|
2317
860
|
] })
|
|
@@ -2319,7 +862,7 @@ function WaitLabel({
|
|
|
2319
862
|
}
|
|
2320
863
|
|
|
2321
864
|
// src/react/usePilot.ts
|
|
2322
|
-
import { useCallback
|
|
865
|
+
import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef3, useState as useState7 } from "react";
|
|
2323
866
|
var MAX_QUEUE_TRIES = 3;
|
|
2324
867
|
var uuid = () => {
|
|
2325
868
|
const c = globalThis.crypto;
|
|
@@ -2353,19 +896,29 @@ function fromUserMessage(content) {
|
|
|
2353
896
|
return { text, attachments };
|
|
2354
897
|
}
|
|
2355
898
|
function usePilot(transport, opts = {}) {
|
|
2356
|
-
const [state, setState] =
|
|
2357
|
-
const ref =
|
|
2358
|
-
const optsRef =
|
|
899
|
+
const [state, setState] = useState7(() => createPilotState(opts.initialTurns ?? []));
|
|
900
|
+
const ref = useRef3(state);
|
|
901
|
+
const optsRef = useRef3(opts);
|
|
2359
902
|
optsRef.current = opts;
|
|
2360
|
-
const transportRef =
|
|
903
|
+
const transportRef = useRef3(transport);
|
|
2361
904
|
transportRef.current = transport;
|
|
2362
|
-
const [threadId] =
|
|
2363
|
-
const ctrl =
|
|
2364
|
-
const liveRun =
|
|
2365
|
-
const answers =
|
|
2366
|
-
const queuedTries =
|
|
2367
|
-
const flushRef =
|
|
905
|
+
const [threadId] = useState7(() => opts.threadId ?? uuid());
|
|
906
|
+
const ctrl = useRef3(null);
|
|
907
|
+
const liveRun = useRef3(null);
|
|
908
|
+
const answers = useRef3(/* @__PURE__ */ new Map());
|
|
909
|
+
const queuedTries = useRef3(/* @__PURE__ */ new Map());
|
|
910
|
+
const flushRef = useRef3(() => {
|
|
2368
911
|
});
|
|
912
|
+
const turnListeners = useRef3(/* @__PURE__ */ new Set());
|
|
913
|
+
const onTurn = useCallback((fn) => {
|
|
914
|
+
turnListeners.current.add(fn);
|
|
915
|
+
return () => void turnListeners.current.delete(fn);
|
|
916
|
+
}, []);
|
|
917
|
+
const listeners = useRef3(/* @__PURE__ */ new Set());
|
|
918
|
+
const subscribe = useCallback((fn) => {
|
|
919
|
+
listeners.current.add(fn);
|
|
920
|
+
return () => void listeners.current.delete(fn);
|
|
921
|
+
}, []);
|
|
2369
922
|
const baseInput = () => {
|
|
2370
923
|
const ctx = optsRef.current.context;
|
|
2371
924
|
return { threadId, runId: uuid(), messages: [], tools: [], context: toAgUiContext(typeof ctx === "function" ? ctx() : ctx), state: {}, forwardedProps: extraProps() };
|
|
@@ -2374,19 +927,24 @@ function usePilot(transport, opts = {}) {
|
|
|
2374
927
|
const f = optsRef.current.forwardedProps;
|
|
2375
928
|
return (typeof f === "function" ? f() : f) ?? {};
|
|
2376
929
|
};
|
|
2377
|
-
const commit =
|
|
930
|
+
const commit = useCallback((next) => {
|
|
2378
931
|
if (next === ref.current) return;
|
|
2379
932
|
ref.current = next;
|
|
2380
933
|
setState(next);
|
|
2381
934
|
const o = optsRef.current;
|
|
2382
935
|
for (const e of next.effects) {
|
|
2383
|
-
if (e.type === "turn-start")
|
|
2384
|
-
|
|
2385
|
-
|
|
936
|
+
if (e.type === "turn-start") {
|
|
937
|
+
o.onTurnStart?.();
|
|
938
|
+
for (const fn of turnListeners.current) fn({ type: "start" });
|
|
939
|
+
} else if (e.type === "turn-done") {
|
|
940
|
+
const info = { text: e.text, runId: e.runId, seconds: e.seconds, error: e.error, interrupted: e.interrupted };
|
|
941
|
+
o.onTurnDone?.(info);
|
|
942
|
+
for (const fn of turnListeners.current) fn({ type: "done", info });
|
|
943
|
+
} else if (e.type === "title") o.onTitle?.(e.title);
|
|
2386
944
|
else if (e.type === "state") o.onState?.(e.state);
|
|
2387
945
|
}
|
|
2388
946
|
}, []);
|
|
2389
|
-
const runNow =
|
|
947
|
+
const runNow = useCallback(
|
|
2390
948
|
async (partial, reopening = false) => {
|
|
2391
949
|
const t = transportRef.current;
|
|
2392
950
|
if (!t) return;
|
|
@@ -2405,6 +963,7 @@ function usePilot(transport, opts = {}) {
|
|
|
2405
963
|
(e) => {
|
|
2406
964
|
if (c.signal.aborted) return;
|
|
2407
965
|
optsRef.current.onEvent?.(e);
|
|
966
|
+
for (const fn of listeners.current) fn(e);
|
|
2408
967
|
if (e.type === "RUN_FINISHED" || e.type === "RUN_ERROR") {
|
|
2409
968
|
ended = true;
|
|
2410
969
|
liveRun.current = null;
|
|
@@ -2452,7 +1011,8 @@ function usePilot(transport, opts = {}) {
|
|
|
2452
1011
|
commit({ ...ref.current, notice: err instanceof Error && err.message ? err.message : null, effects: [] });
|
|
2453
1012
|
return runNow({ messages: [] }, true);
|
|
2454
1013
|
}
|
|
2455
|
-
|
|
1014
|
+
const failed = sendFailed(ref.current, err instanceof Error && err.message ? err.message : "No se pudo hablar con el agente.");
|
|
1015
|
+
commit(err instanceof PilotHttpError ? { ...failed, httpError: { status: err.status, ...err.code ? { code: err.code } : {}, message: err.message, ...err.headers ? { headers: err.headers } : {} } } : failed);
|
|
2456
1016
|
return;
|
|
2457
1017
|
}
|
|
2458
1018
|
if (c.signal.aborted) return;
|
|
@@ -2465,17 +1025,31 @@ function usePilot(transport, opts = {}) {
|
|
|
2465
1025
|
},
|
|
2466
1026
|
[commit, threadId]
|
|
2467
1027
|
);
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
1028
|
+
const sentInitial = useRef3(false);
|
|
1029
|
+
useEffect4(() => {
|
|
1030
|
+
if (!transport) return;
|
|
1031
|
+
let alive = true;
|
|
1032
|
+
const sendInitial = () => {
|
|
1033
|
+
const prompt = optsRef.current.initialPrompt;
|
|
1034
|
+
if (!alive || !prompt || sentInitial.current) return;
|
|
1035
|
+
sentInitial.current = true;
|
|
1036
|
+
void sendRef.current(prompt);
|
|
1037
|
+
};
|
|
1038
|
+
if (opts.threadId) void runNow({ messages: [] }, true).then(sendInitial);
|
|
1039
|
+
else setTimeout(sendInitial, 0);
|
|
1040
|
+
return () => {
|
|
1041
|
+
alive = false;
|
|
1042
|
+
ctrl.current?.abort();
|
|
1043
|
+
};
|
|
2472
1044
|
}, [transport]);
|
|
2473
1045
|
const pendingResume = () => [
|
|
2474
1046
|
...ref.current.permissions.filter((p) => !answers.current.has(p.id)).map((p) => ({ interruptId: p.id, status: "cancelled" })),
|
|
2475
1047
|
...[...answers.current.entries()].map(([interruptId, a]) => ({ interruptId, ...a }))
|
|
2476
1048
|
];
|
|
1049
|
+
const sendRef = useRef3(async () => {
|
|
1050
|
+
});
|
|
2477
1051
|
const steerOn = () => optsRef.current.steer ?? ref.current.agentState.caps?.steer === true;
|
|
2478
|
-
const send =
|
|
1052
|
+
const send = useCallback(
|
|
2479
1053
|
async (text, attachments = [], _extra = {}) => {
|
|
2480
1054
|
if (!transportRef.current) return;
|
|
2481
1055
|
if (ref.current.busy) {
|
|
@@ -2490,7 +1064,8 @@ function usePilot(transport, opts = {}) {
|
|
|
2490
1064
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2491
1065
|
[commit, runNow]
|
|
2492
1066
|
);
|
|
2493
|
-
|
|
1067
|
+
sendRef.current = (text) => send(text);
|
|
1068
|
+
const sendNew = useCallback(
|
|
2494
1069
|
async (text, attachments, tries = 0) => {
|
|
2495
1070
|
const resume = pendingResume();
|
|
2496
1071
|
answers.current.clear();
|
|
@@ -2517,7 +1092,7 @@ function usePilot(transport, opts = {}) {
|
|
|
2517
1092
|
const attachments = queued.flatMap((q) => q.attachments ?? []);
|
|
2518
1093
|
void sendNew(text, attachments, Math.max(...queued.map((q) => q.tries)));
|
|
2519
1094
|
};
|
|
2520
|
-
const stop =
|
|
1095
|
+
const stop = useCallback(() => {
|
|
2521
1096
|
const run = liveRun.current ?? (ref.current.busy ? ref.current.runId : null);
|
|
2522
1097
|
liveRun.current = null;
|
|
2523
1098
|
ctrl.current?.abort();
|
|
@@ -2530,14 +1105,14 @@ function usePilot(transport, opts = {}) {
|
|
|
2530
1105
|
}).catch(() => {
|
|
2531
1106
|
});
|
|
2532
1107
|
}, [commit, threadId]);
|
|
2533
|
-
const retry =
|
|
1108
|
+
const retry = useCallback(() => {
|
|
2534
1109
|
const s = ref.current;
|
|
2535
1110
|
const last = lastUserTurn(s.turns);
|
|
2536
1111
|
if (!last || s.busy) return;
|
|
2537
1112
|
commit(dropLastExchange(s));
|
|
2538
1113
|
void send(last.text, last.attachments ?? []);
|
|
2539
1114
|
}, [commit, send]);
|
|
2540
|
-
const sendAnswersIfComplete =
|
|
1115
|
+
const sendAnswersIfComplete = useCallback(() => {
|
|
2541
1116
|
const open = ref.current.permissions.filter((p) => !answers.current.has(p.id));
|
|
2542
1117
|
if (open.length || !answers.current.size || ref.current.busy) return;
|
|
2543
1118
|
const resume = [...answers.current.entries()].map(([interruptId, a]) => ({ interruptId, ...a }));
|
|
@@ -2545,18 +1120,18 @@ function usePilot(transport, opts = {}) {
|
|
|
2545
1120
|
commit(beginSend(ref.current, "", []));
|
|
2546
1121
|
void runNow({ messages: [], resume });
|
|
2547
1122
|
}, [commit, runNow]);
|
|
2548
|
-
const respondPermission =
|
|
1123
|
+
const respondPermission = useCallback(
|
|
2549
1124
|
(id, approved) => {
|
|
2550
1125
|
answers.current.set(id, { status: "resolved", payload: { approved } });
|
|
2551
1126
|
sendAnswersIfComplete();
|
|
2552
1127
|
},
|
|
2553
1128
|
[sendAnswersIfComplete]
|
|
2554
1129
|
);
|
|
2555
|
-
const recordDecision =
|
|
1130
|
+
const recordDecision = useCallback(
|
|
2556
1131
|
(id, status, asked) => commit(resolvePermission(ref.current, id, status, asked)),
|
|
2557
1132
|
[commit]
|
|
2558
1133
|
);
|
|
2559
|
-
const expirePermission =
|
|
1134
|
+
const expirePermission = useCallback(
|
|
2560
1135
|
(id) => {
|
|
2561
1136
|
if (!ref.current.permissions.some((p) => p.id === id)) return;
|
|
2562
1137
|
answers.current.set(id, { status: "cancelled" });
|
|
@@ -2565,9 +1140,9 @@ function usePilot(transport, opts = {}) {
|
|
|
2565
1140
|
},
|
|
2566
1141
|
[commit, sendAnswersIfComplete]
|
|
2567
1142
|
);
|
|
2568
|
-
const [loadingOlder, setLoadingOlder] =
|
|
2569
|
-
const loadingRef =
|
|
2570
|
-
const loadOlder =
|
|
1143
|
+
const [loadingOlder, setLoadingOlder] = useState7(false);
|
|
1144
|
+
const loadingRef = useRef3(false);
|
|
1145
|
+
const loadOlder = useCallback(async () => {
|
|
2571
1146
|
const fn = optsRef.current.loadOlder;
|
|
2572
1147
|
const h = ref.current.history;
|
|
2573
1148
|
if (!fn || !h?.hasMoreBefore || loadingRef.current) return;
|
|
@@ -2584,7 +1159,7 @@ function usePilot(transport, opts = {}) {
|
|
|
2584
1159
|
setLoadingOlder(false);
|
|
2585
1160
|
}
|
|
2586
1161
|
}, [commit]);
|
|
2587
|
-
const stopSubagent =
|
|
1162
|
+
const stopSubagent = useCallback(
|
|
2588
1163
|
async (taskId) => {
|
|
2589
1164
|
const t = transportRef.current;
|
|
2590
1165
|
if (!t) return;
|
|
@@ -2598,96 +1173,186 @@ function usePilot(transport, opts = {}) {
|
|
|
2598
1173
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2599
1174
|
[commit, runNow]
|
|
2600
1175
|
);
|
|
2601
|
-
const continueRun =
|
|
1176
|
+
const continueRun = useCallback(async () => {
|
|
2602
1177
|
const cut = ref.current.cutRun;
|
|
2603
1178
|
if (!cut || ref.current.busy || !transportRef.current) return;
|
|
2604
1179
|
commit(beginSend(ref.current, "", []));
|
|
2605
1180
|
await runNow({ messages: [], forwardedProps: { continueRun: cut.runId } });
|
|
2606
1181
|
}, [commit, runNow]);
|
|
2607
|
-
const refresh =
|
|
1182
|
+
const refresh = useCallback(() => runNow({ messages: [] }, true), [runNow]);
|
|
2608
1183
|
const canSteer = Boolean(transport) && (opts.steer ?? state.agentState.caps?.steer === true);
|
|
2609
|
-
const subagents =
|
|
2610
|
-
return { state, threadId, send, stop, retry, respondPermission, recordDecision, expirePermission, canSteer, loadOlder, loadingOlder, subagents, stopSubagent, refresh, continueRun };
|
|
1184
|
+
const subagents = useMemo2(() => subagentsOf(state.agentState), [state.agentState]);
|
|
1185
|
+
return { state, threadId, send, stop, retry, respondPermission, recordDecision, expirePermission, canSteer, loadOlder, loadingOlder, subagents, stopSubagent, refresh, reconnect: refresh, continueRun, subscribe, onTurn };
|
|
2611
1186
|
}
|
|
2612
1187
|
|
|
2613
1188
|
// src/react/Piloto.tsx
|
|
2614
|
-
import { Fragment as
|
|
2615
|
-
var useIsoLayoutEffect = typeof window === "undefined" ?
|
|
1189
|
+
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1190
|
+
var useIsoLayoutEffect = typeof window === "undefined" ? useEffect5 : useLayoutEffect;
|
|
2616
1191
|
var ANCHOR_GAP = 24;
|
|
2617
|
-
var Piloto =
|
|
2618
|
-
const { transport, pilot: external, locale = "es", theme = "light", features = {}
|
|
1192
|
+
var Piloto = forwardRef(function Piloto2(props, handle) {
|
|
1193
|
+
const { transport, pilot: external, locale = "es", theme = "light", features = {} } = props;
|
|
2619
1194
|
const own = usePilot(external ? null : transport, features.steer === void 0 ? props : { ...props, steer: features.steer });
|
|
2620
1195
|
const pilot = external ?? own;
|
|
2621
1196
|
const { state } = pilot;
|
|
2622
1197
|
const { turns, busy, error, notice, permissions, olderCount } = state;
|
|
2623
|
-
const
|
|
2624
|
-
|
|
1198
|
+
const plugins = useMemo3(() => resolvePlugins(props.plugins), [props.plugins]);
|
|
1199
|
+
useEffect5(() => {
|
|
1200
|
+
if (isDev()) for (const w of plugins.warnings) warnOnce(w);
|
|
1201
|
+
}, [plugins]);
|
|
1202
|
+
const ctxForComponents = useRef4(null);
|
|
1203
|
+
const boundComponents = useMemo3(() => {
|
|
1204
|
+
const entries = Object.entries(plugins.components);
|
|
1205
|
+
if (!entries.length) return void 0;
|
|
1206
|
+
return Object.fromEntries(
|
|
1207
|
+
entries.map(([tag, { plugin, value: C }]) => [
|
|
1208
|
+
tag,
|
|
1209
|
+
// Como toda vista de plugin: marcada con su nombre y, si es de la app, aislada de las utilidades.
|
|
1210
|
+
(p) => /* @__PURE__ */ jsx8("span", { ...pluginAttrs(plugin, plugins.ghostykitStyled), style: { display: "contents" }, children: /* @__PURE__ */ jsx8(C, { ...p, ctx: ctxForComponents.current }) })
|
|
1211
|
+
])
|
|
1212
|
+
);
|
|
1213
|
+
}, [plugins]);
|
|
1214
|
+
const strings = useMemo3(() => ({ ...locale === "en" ? STRINGS_EN : STRINGS_ES, ...plugins.strings }), [locale, plugins]);
|
|
1215
|
+
const config = useMemo3(
|
|
2625
1216
|
() => ({
|
|
2626
1217
|
strings,
|
|
2627
|
-
toolVerbs: { ...locale === "en" ? TOOL_VERBS_EN : TOOL_VERBS_ES, ...
|
|
2628
|
-
toolIcons:
|
|
2629
|
-
formatUserText:
|
|
1218
|
+
toolVerbs: { ...locale === "en" ? TOOL_VERBS_EN : TOOL_VERBS_ES, ...plugins.verbs },
|
|
1219
|
+
toolIcons: plugins.icons,
|
|
1220
|
+
formatUserText: plugins.formatUserText ? (x) => plugins.formatUserText(cleanUserText(x)) : cleanUserText,
|
|
2630
1221
|
theme,
|
|
2631
1222
|
skin: props.skin ?? "ghosty",
|
|
2632
|
-
markdown:
|
|
1223
|
+
markdown: { ...plugins.markdown, ...boundComponents ? { components: boundComponents } : {} }
|
|
2633
1224
|
}),
|
|
2634
|
-
[strings, locale,
|
|
1225
|
+
[strings, locale, plugins, theme, props.skin, boundComponents]
|
|
2635
1226
|
);
|
|
2636
1227
|
const t = strings;
|
|
2637
|
-
const [ownRefs, setOwnRefs] =
|
|
1228
|
+
const [ownRefs, setOwnRefs] = useState8([]);
|
|
2638
1229
|
const refs = props.references ?? ownRefs;
|
|
2639
|
-
const refsRef =
|
|
1230
|
+
const refsRef = useRef4(refs);
|
|
2640
1231
|
refsRef.current = refs;
|
|
2641
|
-
const setRefs =
|
|
1232
|
+
const setRefs = useCallback2(
|
|
2642
1233
|
(next) => {
|
|
2643
1234
|
if (!props.references) setOwnRefs(next);
|
|
2644
1235
|
props.onReferencesChange?.(next);
|
|
2645
1236
|
},
|
|
2646
1237
|
[props.references, props.onReferencesChange]
|
|
2647
1238
|
);
|
|
2648
|
-
const composerBox =
|
|
1239
|
+
const composerBox = useRef4(null);
|
|
2649
1240
|
const draftText = typeof props.draft === "string" ? props.draft : props.draft?.text;
|
|
2650
1241
|
const draftKey = typeof props.draft === "object" && props.draft ? props.draft.key : void 0;
|
|
2651
|
-
const [draft, setDraftState] =
|
|
2652
|
-
const draftSeen =
|
|
2653
|
-
|
|
1242
|
+
const [draft, setDraftState] = useState8(() => ({ text: draftText ?? "", n: 0 }));
|
|
1243
|
+
const draftSeen = useRef4(`${draftText}\0${draftKey}`);
|
|
1244
|
+
useEffect5(() => {
|
|
2654
1245
|
const id = `${draftText}\0${draftKey}`;
|
|
2655
1246
|
if (draftText == null || id === draftSeen.current) return;
|
|
2656
1247
|
draftSeen.current = id;
|
|
2657
1248
|
setDraftState((d) => ({ text: draftText, n: d.n + 1 }));
|
|
2658
1249
|
}, [draftText, draftKey]);
|
|
2659
1250
|
const returned = state.returnedDraft;
|
|
2660
|
-
|
|
1251
|
+
useEffect5(() => {
|
|
2661
1252
|
if (!returned) return;
|
|
2662
1253
|
const typed = composerBox.current?.querySelector("textarea")?.value ?? "";
|
|
2663
1254
|
const text = [returned.text, typed].filter((x) => x.trim()).join("\n\n");
|
|
2664
1255
|
setDraftState((d) => ({ text, n: d.n + 1 }));
|
|
2665
1256
|
}, [returned?.n]);
|
|
2666
|
-
const send =
|
|
1257
|
+
const send = useCallback2(
|
|
2667
1258
|
(text, attachments = []) => {
|
|
2668
1259
|
const current = refsRef.current;
|
|
2669
|
-
const
|
|
1260
|
+
const before = pluginsRef.current.beforeSend;
|
|
1261
|
+
const full = applyReferences(before && ctxRef.current ? before(text, ctxRef.current) : text, current);
|
|
2670
1262
|
if (current.length) setRefs([]);
|
|
2671
1263
|
void pilot.send(full, attachments, current.length ? { references: current } : {});
|
|
2672
1264
|
},
|
|
2673
1265
|
[pilot, setRefs]
|
|
2674
1266
|
);
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
1267
|
+
const pluginsRef = useRef4(plugins);
|
|
1268
|
+
pluginsRef.current = plugins;
|
|
1269
|
+
const ctxRef = useRef4(null);
|
|
1270
|
+
const composerHandle = useRef4(null);
|
|
1271
|
+
const focus = useCallback2(() => composerBox.current?.querySelector("textarea")?.focus({ preventScroll: true }), []);
|
|
1272
|
+
const addReference = useCallback2(
|
|
1273
|
+
(r) => {
|
|
1274
|
+
const current = refsRef.current;
|
|
1275
|
+
if (!current.some((x) => x.id === r.id)) setRefs([...current, r]);
|
|
1276
|
+
requestAnimationFrame(focus);
|
|
1277
|
+
},
|
|
1278
|
+
[setRefs, focus]
|
|
1279
|
+
);
|
|
1280
|
+
const setDraft = useCallback2((text) => setDraftState((d) => ({ text, n: d.n + 1 })), []);
|
|
1281
|
+
const addAttachments = useCallback2((items) => composerHandle.current?.addAttachments(items), []);
|
|
1282
|
+
const actions = { pilot, send, addReference, addAttachments, setDraft, focus };
|
|
1283
|
+
useImperativeHandle(handle, () => actions, [pilot, send, addReference, addAttachments, setDraft, focus]);
|
|
1284
|
+
const ctx = { ...actions, agentState: state.agentState, strings, plugins: plugins.list };
|
|
1285
|
+
ctxForComponents.current = ctx;
|
|
1286
|
+
const mark = (plugin) => pluginAttrs(plugin, plugins.ghostykitStyled);
|
|
1287
|
+
ctxRef.current = ctx;
|
|
1288
|
+
const unattended = useRef4(/* @__PURE__ */ new Set());
|
|
1289
|
+
useEffect5(
|
|
1290
|
+
() => pilot.subscribe?.((event) => {
|
|
1291
|
+
const e = event;
|
|
1292
|
+
const r = pluginsRef.current;
|
|
1293
|
+
const handlers = [...r.events[e.type] ?? [], ...e.type === "CUSTOM" && e.name ? r.events[e.name] ?? [] : [], ...r.events["*"] ?? []];
|
|
1294
|
+
for (const h of handlers) {
|
|
1295
|
+
try {
|
|
1296
|
+
h.value(e, ctxRef.current);
|
|
1297
|
+
} catch (err) {
|
|
1298
|
+
console.error(`[ghostykit] el plugin \xAB${h.plugin}\xBB fall\xF3 con ${e.type}${e.name ? ` ${e.name}` : ""}`, err);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
if (e.type === "CUSTOM" && e.name && isDev() && !BUILTIN_CUSTOM.has(e.name) && !r.events[e.name] && !r.customRenders[e.name] && !unattended.current.has(e.name)) {
|
|
1302
|
+
const declared = r.list.some((p) => p.requires?.events?.includes(e.name));
|
|
1303
|
+
if (!declared) {
|
|
1304
|
+
unattended.current.add(e.name);
|
|
1305
|
+
warnOnce(`Ning\xFAn plugin atiende CUSTOM \xAB${e.name}\xBB.`);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
}),
|
|
1309
|
+
[pilot.subscribe]
|
|
1310
|
+
);
|
|
1311
|
+
const seenState = useRef4({});
|
|
1312
|
+
useEffect5(() => {
|
|
1313
|
+
const r = pluginsRef.current;
|
|
1314
|
+
for (const [key, handlers] of Object.entries(r.state)) {
|
|
1315
|
+
const value = state.agentState[key];
|
|
1316
|
+
if (value === seenState.current[key]) continue;
|
|
1317
|
+
seenState.current[key] = value;
|
|
1318
|
+
if (value === void 0) continue;
|
|
1319
|
+
for (const h of handlers) {
|
|
1320
|
+
try {
|
|
1321
|
+
h.value(value, ctxRef.current);
|
|
1322
|
+
} catch (err) {
|
|
1323
|
+
console.error(`[ghostykit] el plugin \xAB${h.plugin}\xBB fall\xF3 con state.${key}`, err);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
}, [state.agentState, plugins]);
|
|
1328
|
+
useEffect5(
|
|
1329
|
+
() => pilot.onTurn?.((e) => {
|
|
1330
|
+
const r = pluginsRef.current;
|
|
1331
|
+
const run = (plugin, fn) => {
|
|
1332
|
+
try {
|
|
1333
|
+
fn();
|
|
1334
|
+
} catch (err) {
|
|
1335
|
+
console.error(`[ghostykit] el plugin \xAB${plugin}\xBB fall\xF3 al ${e.type === "start" ? "empezar" : "terminar"} el turno`, err);
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
if (e.type === "start") for (const h of r.turnStart) run(h.plugin, () => h.value(ctxRef.current));
|
|
1339
|
+
else for (const h of r.turnDone) run(h.plugin, () => h.value(e.info, ctxRef.current));
|
|
2686
1340
|
}),
|
|
2687
|
-
[
|
|
1341
|
+
[pilot.onTurn]
|
|
2688
1342
|
);
|
|
2689
|
-
|
|
2690
|
-
|
|
1343
|
+
useEffect5(() => {
|
|
1344
|
+
const err = state.httpError;
|
|
1345
|
+
if (!err) return;
|
|
1346
|
+
for (const h of pluginsRef.current.httpError) {
|
|
1347
|
+
try {
|
|
1348
|
+
h.value(err, ctxRef.current);
|
|
1349
|
+
} catch (e) {
|
|
1350
|
+
console.error(`[ghostykit] el plugin \xAB${h.plugin}\xBB fall\xF3 con onHttpError`, e);
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
}, [state.httpError]);
|
|
1354
|
+
const [held, setHeld] = useState8({});
|
|
1355
|
+
const heldRef = useRef4(held);
|
|
2691
1356
|
heldRef.current = held;
|
|
2692
1357
|
const releaseHeld = (id) => setHeld(({ [id]: _, ...rest }) => rest);
|
|
2693
1358
|
const respond = (id, approved) => {
|
|
@@ -2703,15 +1368,15 @@ var Piloto = forwardRef3(function Piloto2(props, handle) {
|
|
|
2703
1368
|
releaseHeld(id);
|
|
2704
1369
|
};
|
|
2705
1370
|
const cards = [...permissions, ...Object.values(held).filter((h) => !permissions.some((p) => p.id === h.id))];
|
|
2706
|
-
const scroller =
|
|
2707
|
-
const column =
|
|
2708
|
-
const spacer =
|
|
2709
|
-
const following =
|
|
2710
|
-
const touchY =
|
|
2711
|
-
const [atBottom, setAtBottom] =
|
|
1371
|
+
const scroller = useRef4(null);
|
|
1372
|
+
const column = useRef4(null);
|
|
1373
|
+
const spacer = useRef4(null);
|
|
1374
|
+
const following = useRef4(true);
|
|
1375
|
+
const touchY = useRef4(null);
|
|
1376
|
+
const [atBottom, setAtBottom] = useState8(true);
|
|
2712
1377
|
const message = (n) => scroller.current?.querySelector(`[data-turn="${n}"]`) ?? null;
|
|
2713
|
-
const olderSeen =
|
|
2714
|
-
const heightBefore =
|
|
1378
|
+
const olderSeen = useRef4(olderCount);
|
|
1379
|
+
const heightBefore = useRef4(0);
|
|
2715
1380
|
useIsoLayoutEffect(() => {
|
|
2716
1381
|
const el = scroller.current;
|
|
2717
1382
|
if (el && olderCount > olderSeen.current && heightBefore.current) el.scrollTop += el.scrollHeight - heightBefore.current;
|
|
@@ -2722,8 +1387,8 @@ var Piloto = forwardRef3(function Piloto2(props, handle) {
|
|
|
2722
1387
|
heightBefore.current = scroller.current?.scrollHeight ?? 0;
|
|
2723
1388
|
void pilot.loadOlder();
|
|
2724
1389
|
};
|
|
2725
|
-
const placed =
|
|
2726
|
-
|
|
1390
|
+
const placed = useRef4(false);
|
|
1391
|
+
useEffect5(() => {
|
|
2727
1392
|
if (placed.current || turns.length === 0) return;
|
|
2728
1393
|
placed.current = true;
|
|
2729
1394
|
const el = scroller.current;
|
|
@@ -2738,16 +1403,20 @@ var Piloto = forwardRef3(function Piloto2(props, handle) {
|
|
|
2738
1403
|
}
|
|
2739
1404
|
}
|
|
2740
1405
|
const mine = mineIndex >= 0 ? turns[mineIndex] : null;
|
|
2741
|
-
const mineSeen =
|
|
2742
|
-
const [anchor, setAnchor] =
|
|
2743
|
-
|
|
1406
|
+
const mineSeen = useRef4(mine);
|
|
1407
|
+
const [anchor, setAnchor] = useState8(null);
|
|
1408
|
+
useEffect5(() => {
|
|
2744
1409
|
if (mine === mineSeen.current) return;
|
|
2745
1410
|
mineSeen.current = mine;
|
|
1411
|
+
if (!state.turnStartedAt) {
|
|
1412
|
+
following.current = true;
|
|
1413
|
+
return;
|
|
1414
|
+
}
|
|
2746
1415
|
if (mine) setAnchor(mineIndex - olderCount);
|
|
2747
1416
|
following.current = true;
|
|
2748
1417
|
}, [mine, mineIndex]);
|
|
2749
1418
|
const gapAbove = (a) => anchor === -olderCount ? a.offsetTop : ANCHOR_GAP;
|
|
2750
|
-
const measureSpacer =
|
|
1419
|
+
const measureSpacer = useCallback2(() => {
|
|
2751
1420
|
const sc = scroller.current;
|
|
2752
1421
|
const sp = spacer.current;
|
|
2753
1422
|
if (!sc || !sp) return;
|
|
@@ -2765,7 +1434,7 @@ var Piloto = forwardRef3(function Piloto2(props, handle) {
|
|
|
2765
1434
|
const a = anchor != null ? message(anchor) : null;
|
|
2766
1435
|
if (sc && a) sc.scrollTo({ top: a.offsetTop - gapAbove(a), behavior: "smooth" });
|
|
2767
1436
|
}, [anchor, measureSpacer]);
|
|
2768
|
-
|
|
1437
|
+
useEffect5(() => {
|
|
2769
1438
|
const col = column.current;
|
|
2770
1439
|
const sc = scroller.current;
|
|
2771
1440
|
if (!col || !sc || typeof ResizeObserver === "undefined") return;
|
|
@@ -2795,13 +1464,22 @@ var Piloto = forwardRef3(function Piloto2(props, handle) {
|
|
|
2795
1464
|
const toolRunning = busy && last?.role === "assistant" && (last.tools ?? []).some(isRunning);
|
|
2796
1465
|
const empty = turns.length === 0 && !busy;
|
|
2797
1466
|
const placeholder = props.placeholder ?? (props.agentName ? t.placeholder(props.agentName) : t.placeholderDefault);
|
|
2798
|
-
const
|
|
1467
|
+
const { upload, transcribe, voiceNoteText, accept, maxFiles, maxBytes } = plugins.attachments;
|
|
1468
|
+
const showFiles = features.attachments ?? Boolean(upload);
|
|
2799
1469
|
const pointedRefs = refs.filter((r) => r.prompt);
|
|
2800
1470
|
const plainRefs = refs.filter((r) => !r.prompt);
|
|
2801
1471
|
const removeRef = (id) => setRefs(refsRef.current.filter((r) => r.id !== id));
|
|
2802
|
-
const
|
|
2803
|
-
|
|
2804
|
-
|
|
1472
|
+
const replacer = plugins.replacers.find((r) => {
|
|
1473
|
+
try {
|
|
1474
|
+
return r.value.when(ctx);
|
|
1475
|
+
} catch {
|
|
1476
|
+
return false;
|
|
1477
|
+
}
|
|
1478
|
+
});
|
|
1479
|
+
const Replacement = replacer?.value.view;
|
|
1480
|
+
const composer = Replacement ? /* @__PURE__ */ jsx8("div", { ...mark(replacer.plugin), children: /* @__PURE__ */ jsx8(Replacement, { ctx }) }) : /* @__PURE__ */ jsxs6("div", { ref: composerBox, children: [
|
|
1481
|
+
/* @__PURE__ */ jsx8(ReferenceChips, { references: pointedRefs, onRemove: removeRef, onActivate: props.onReferenceClick }),
|
|
1482
|
+
/* @__PURE__ */ jsx8(
|
|
2805
1483
|
Composer,
|
|
2806
1484
|
{
|
|
2807
1485
|
initialValue: draft.text,
|
|
@@ -2811,156 +1489,236 @@ var Piloto = forwardRef3(function Piloto2(props, handle) {
|
|
|
2811
1489
|
canSteer: pilot.canSteer,
|
|
2812
1490
|
placeholder,
|
|
2813
1491
|
attachments: showFiles,
|
|
2814
|
-
upload
|
|
2815
|
-
transcribe
|
|
2816
|
-
voiceNoteText
|
|
1492
|
+
upload,
|
|
1493
|
+
transcribe,
|
|
1494
|
+
voiceNoteText,
|
|
2817
1495
|
references: plainRefs,
|
|
2818
1496
|
onRemoveReference: removeRef,
|
|
2819
1497
|
onActivateReference: props.onReferenceClick,
|
|
2820
|
-
extras:
|
|
1498
|
+
extras: plugins.composerActions.length ? /* @__PURE__ */ jsx8(Views, { items: plugins.composerActions, ctx, styled: plugins.ghostykitStyled, inline: true }) : void 0,
|
|
1499
|
+
extrasEnd: plugins.composerActionsEnd.length ? /* @__PURE__ */ jsx8(Views, { items: plugins.composerActionsEnd, ctx, styled: plugins.ghostykitStyled, inline: true }) : void 0,
|
|
1500
|
+
handleRef: composerHandle,
|
|
1501
|
+
accept,
|
|
1502
|
+
...maxFiles ? { maxFiles } : {},
|
|
1503
|
+
...maxBytes ? { maxFileMb: maxBytes / (1024 * 1024) } : {}
|
|
2821
1504
|
},
|
|
2822
1505
|
draft.n
|
|
2823
1506
|
)
|
|
2824
1507
|
] });
|
|
2825
|
-
const withPanel = (chat) =>
|
|
2826
|
-
/* @__PURE__ */
|
|
2827
|
-
|
|
1508
|
+
const withPanel = (chat) => plugins.sidePanel.length ? /* @__PURE__ */ jsxs6("div", { className: "flex min-h-0 flex-1 flex-row", children: [
|
|
1509
|
+
/* @__PURE__ */ jsx8("div", { className: "relative flex min-h-0 min-w-0 flex-1 flex-col", children: chat }),
|
|
1510
|
+
/* @__PURE__ */ jsx8(Views, { items: plugins.sidePanel, ctx, styled: plugins.ghostykitStyled, className: "flex min-h-0 shrink-0" })
|
|
2828
1511
|
] }) : chat;
|
|
2829
|
-
const aboveComposer =
|
|
2830
|
-
const
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
1512
|
+
const aboveComposer = plugins.composerAbove.length ? /* @__PURE__ */ jsx8(Views, { items: plugins.composerAbove, ctx, styled: plugins.ghostykitStyled }) : null;
|
|
1513
|
+
const belowComposer = plugins.composerBelow.length ? /* @__PURE__ */ jsx8(Views, { items: plugins.composerBelow, ctx, styled: plugins.ghostykitStyled }) : null;
|
|
1514
|
+
const header = plugins.header.length ? /* @__PURE__ */ jsx8(Views, { items: plugins.header, ctx, styled: plugins.ghostykitStyled, inline: true }) : null;
|
|
1515
|
+
const Empty = plugins.empty?.value;
|
|
1516
|
+
const Waiting = plugins.waiting?.value;
|
|
1517
|
+
const renderDeliveries = (turn, live) => {
|
|
1518
|
+
const custom = (turn.custom ?? []).map((entry, i) => {
|
|
1519
|
+
const owner = plugins.customRenders[entry.name];
|
|
1520
|
+
if (!owner) return null;
|
|
1521
|
+
const C = owner.value;
|
|
1522
|
+
return /* @__PURE__ */ jsx8("div", { ...mark(owner.plugin), children: /* @__PURE__ */ jsx8(C, { ctx, entry, turn, live }) }, `c${i}`);
|
|
1523
|
+
});
|
|
1524
|
+
const extras = plugins.messageAssistant.map((o, i) => /* @__PURE__ */ jsx8("div", { ...mark(o.plugin), children: /* @__PURE__ */ jsx8(o.value, { ctx, turn, live }) }, `a${i}`));
|
|
1525
|
+
return custom.some(Boolean) || extras.length ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1526
|
+
custom,
|
|
1527
|
+
extras
|
|
1528
|
+
] }) : null;
|
|
1529
|
+
};
|
|
1530
|
+
const renderTools = (turn, live) => {
|
|
1531
|
+
const views = (turn.tools ?? []).flatMap((tool) => {
|
|
1532
|
+
const owner = plugins.toolRenders[tool.title ?? ""] ?? (tool.kind ? plugins.toolRenders[tool.kind] : void 0);
|
|
1533
|
+
if (!owner) return [];
|
|
1534
|
+
const C = owner.value;
|
|
1535
|
+
return [
|
|
1536
|
+
/* @__PURE__ */ jsx8("div", { ...mark(owner.plugin), children: /* @__PURE__ */ jsx8(C, { ctx, tool, turn, live }) }, tool.id)
|
|
1537
|
+
];
|
|
1538
|
+
});
|
|
1539
|
+
return views.length ? /* @__PURE__ */ jsx8("div", { className: "mb-3 flex flex-col gap-2", children: views }) : null;
|
|
1540
|
+
};
|
|
1541
|
+
const renderBefore = plugins.messageBefore.length ? (turn, live) => /* @__PURE__ */ jsx8(Fragment4, { children: plugins.messageBefore.map((o, i) => /* @__PURE__ */ jsx8("div", { ...mark(o.plugin), children: /* @__PURE__ */ jsx8(o.value, { ctx, turn, live }) }, i)) }) : void 0;
|
|
1542
|
+
const blockLangs = Object.keys(plugins.blockRenders);
|
|
1543
|
+
const blocks = blockLangs.length ? {
|
|
1544
|
+
langs: blockLangs,
|
|
1545
|
+
render: (list, turn, live) => /* @__PURE__ */ jsx8("div", { className: "mt-2 flex flex-col gap-2", children: list.map((block, i) => {
|
|
1546
|
+
const owner = plugins.blockRenders[block.lang];
|
|
1547
|
+
const C = owner.value;
|
|
1548
|
+
return /* @__PURE__ */ jsx8("div", { ...mark(owner.plugin), children: /* @__PURE__ */ jsx8(C, { ctx, block, turn, live }) }, i);
|
|
1549
|
+
}) })
|
|
1550
|
+
} : void 0;
|
|
1551
|
+
const wrapAll = (tree) => plugins.wraps.reduceRight((inner, { value: W }) => /* @__PURE__ */ jsx8(W, { ctx, children: inner }), tree);
|
|
1552
|
+
const permissionCards = cards.map((p) => /* @__PURE__ */ jsx8(ConfirmCard, { request: p, onRespond: respond, onSettled: settle, onExpire: pilot.expirePermission }, p.id));
|
|
1553
|
+
return /* @__PURE__ */ jsx8(PilotoContext.Provider, { value: config, children: wrapAll(
|
|
1554
|
+
/* @__PURE__ */ jsx8(
|
|
2856
1555
|
"div",
|
|
2857
1556
|
{
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
1557
|
+
...rootProps(theme, props.skin),
|
|
1558
|
+
"data-busy": busy || void 0,
|
|
1559
|
+
className: `piloto ${plugins.className} ${props.className ?? ""}`,
|
|
1560
|
+
style: Object.keys(plugins.vars).length ? { ...plugins.vars, ...props.style } : props.style,
|
|
1561
|
+
children: withPanel(empty ? (
|
|
1562
|
+
// Un hilo vacío enseña lo mismo que la portada: la cara, el saludo, la caja y por dónde
|
|
1563
|
+
// empezar. Si no cabe (panel bajo), se desplaza: `safe center` nunca empuja nada fuera.
|
|
1564
|
+
/* @__PURE__ */ jsxs6("div", { className: "gs-scroll flex min-h-0 flex-1 flex-col items-center justify-center overflow-y-auto px-4 pb-[10vh] [justify-content:safe_center]", children: [
|
|
1565
|
+
header && /* @__PURE__ */ jsx8("div", { className: "absolute right-4 top-3 flex gap-2", children: header }),
|
|
1566
|
+
Empty ? /* @__PURE__ */ jsx8("div", { ...mark(plugins.empty.plugin), children: /* @__PURE__ */ jsx8(Empty, { ctx }) }) : /* @__PURE__ */ jsxs6("div", { className: "mb-6 flex flex-col items-center", children: [
|
|
1567
|
+
props.avatar && /* @__PURE__ */ jsx8("div", { className: "mb-3", children: props.avatar }),
|
|
1568
|
+
props.welcome && // Un saludo largo (una explicación del piloto) baja a letra de lectura.
|
|
1569
|
+
/* @__PURE__ */ jsx8(
|
|
1570
|
+
"h1",
|
|
1571
|
+
{
|
|
1572
|
+
className: typeof props.welcome === "string" && props.welcome.length > 60 ? "max-w-xl text-center text-base font-medium leading-6 text-metal" : "text-center text-3xl font-extrabold tracking-tight text-dark",
|
|
1573
|
+
children: props.welcome
|
|
1574
|
+
}
|
|
1575
|
+
)
|
|
1576
|
+
] }),
|
|
1577
|
+
/* @__PURE__ */ jsxs6("div", { className: "w-full max-w-3xl", children: [
|
|
1578
|
+
aboveComposer,
|
|
1579
|
+
composer,
|
|
1580
|
+
belowComposer,
|
|
1581
|
+
props.suggestions && /* @__PURE__ */ jsx8(Suggestions, { items: props.suggestions, onPick: (s) => send(s), onPrefill: (s) => setDraftState((d) => ({ text: s, n: d.n + 1 })) })
|
|
1582
|
+
] })
|
|
1583
|
+
] })
|
|
1584
|
+
) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1585
|
+
header && /* @__PURE__ */ jsx8("div", { className: "flex shrink-0 justify-end gap-2 px-4 pt-3 sm:px-6", children: header }),
|
|
1586
|
+
/* @__PURE__ */ jsxs6(
|
|
1587
|
+
"div",
|
|
1588
|
+
{
|
|
1589
|
+
ref: scroller,
|
|
1590
|
+
onScroll,
|
|
1591
|
+
onWheel: (e) => e.deltaY < 0 && release(),
|
|
1592
|
+
onTouchStart: (e) => {
|
|
1593
|
+
touchY.current = e.touches[0]?.clientY ?? null;
|
|
1594
|
+
},
|
|
1595
|
+
onTouchMove: (e) => {
|
|
1596
|
+
const y = e.touches[0]?.clientY;
|
|
1597
|
+
if (touchY.current != null && y != null && y > touchY.current + 4) release();
|
|
1598
|
+
},
|
|
1599
|
+
onKeyDown: (e) => ["ArrowUp", "PageUp", "Home"].includes(e.key) && release(),
|
|
1600
|
+
className: "gs-scroll relative min-h-0 flex-1 overflow-y-auto overflow-x-hidden",
|
|
1601
|
+
children: [
|
|
1602
|
+
/* @__PURE__ */ jsxs6("div", { ref: column, className: "mx-auto flex w-full max-w-[784px] flex-col gap-6 px-4 py-8 sm:px-6", children: [
|
|
1603
|
+
plugins.aboveThread.length > 0 && /* @__PURE__ */ jsx8(Views, { items: plugins.aboveThread, ctx, styled: plugins.ghostykitStyled }),
|
|
1604
|
+
state.history?.hasMoreBefore && (external || props.loadOlder) && /* @__PURE__ */ jsx8(
|
|
1605
|
+
"button",
|
|
1606
|
+
{
|
|
1607
|
+
type: "button",
|
|
1608
|
+
onClick: loadOlder,
|
|
1609
|
+
disabled: pilot.loadingOlder,
|
|
1610
|
+
className: "self-center rounded-full border border-border-primary px-3 py-1 text-sm text-text-secondary transition hover:text-text-primary disabled:opacity-60",
|
|
1611
|
+
children: pilot.loadingOlder ? t.loadingOlder : t.loadOlder
|
|
1612
|
+
}
|
|
1613
|
+
),
|
|
1614
|
+
turns.map((turn, i) => {
|
|
1615
|
+
const isLast = i === turns.length - 1;
|
|
1616
|
+
const live = busy && isLast;
|
|
1617
|
+
return /* @__PURE__ */ jsxs6("div", { "data-turn": i - olderCount, children: [
|
|
1618
|
+
turn.role === "user" ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1619
|
+
/* @__PURE__ */ jsx8(UserBubble, { turn }),
|
|
1620
|
+
plugins.messageUser.map((o, j) => /* @__PURE__ */ jsx8("div", { ...mark(o.plugin), children: /* @__PURE__ */ jsx8(o.value, { ctx, turn }) }, j))
|
|
1621
|
+
] }) : /* @__PURE__ */ jsx8(
|
|
1622
|
+
AgentBubble,
|
|
1623
|
+
{
|
|
1624
|
+
turn,
|
|
1625
|
+
live,
|
|
1626
|
+
onRetry: isLast && features.retry !== false ? pilot.retry : void 0,
|
|
1627
|
+
onOption: isLast && !busy && features.replyOptions !== false ? (text) => send(text) : void 0,
|
|
1628
|
+
showUsage: features.usage !== false,
|
|
1629
|
+
showCopy: features.copy !== false,
|
|
1630
|
+
showDuration: features.duration !== false,
|
|
1631
|
+
renderDeliveries,
|
|
1632
|
+
renderTools,
|
|
1633
|
+
renderBefore,
|
|
1634
|
+
blocks,
|
|
1635
|
+
narration: features.narration !== false,
|
|
1636
|
+
avatar: plugins.avatar ? /* @__PURE__ */ jsx8("span", { ...mark(plugins.avatar.plugin), children: /* @__PURE__ */ jsx8(plugins.avatar.value, { ctx, turn }) }) : void 0
|
|
1637
|
+
}
|
|
1638
|
+
),
|
|
1639
|
+
turn.role === "assistant" && /* @__PURE__ */ jsx8(TurnNotes, { turn })
|
|
1640
|
+
] }, i - olderCount);
|
|
1641
|
+
}),
|
|
1642
|
+
busy && state.stalled && /* @__PURE__ */ jsx8("p", { className: "text-sm text-text-tertiary", children: state.stalled.message ?? t.stalled }),
|
|
1643
|
+
state.queued.map((q, i) => (
|
|
1644
|
+
// Esperan a que termine el run vivo (el servidor no los dejó entrar): salen solos.
|
|
1645
|
+
/* @__PURE__ */ jsxs6("div", { "data-queued": true, className: "flex flex-col items-end gap-1 opacity-60", children: [
|
|
1646
|
+
/* @__PURE__ */ jsx8(UserBubble, { turn: { role: "user", text: q.text, ...q.attachments ? { attachments: q.attachments } : {} } }),
|
|
1647
|
+
/* @__PURE__ */ jsx8("span", { className: "text-xs text-text-tertiary", children: t.queued })
|
|
1648
|
+
] }, `q${i}`)
|
|
1649
|
+
)),
|
|
1650
|
+
permissionCards,
|
|
1651
|
+
busy && !toolRunning && !cards.length && (Waiting ? /* @__PURE__ */ jsx8("div", { ...mark(plugins.waiting.plugin), children: /* @__PURE__ */ jsx8(Waiting, { ctx, step: state.step, since: state.turnStartedAt }) }) : /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-1.5", children: [
|
|
1652
|
+
/* @__PURE__ */ jsx8(TypingDots, {}),
|
|
1653
|
+
/* @__PURE__ */ jsx8(WaitLabel, { since: state.turnStartedAt, step: state.step, showDuration: features.duration !== false })
|
|
1654
|
+
] })),
|
|
1655
|
+
notice && /* @__PURE__ */ jsx8("p", { className: "text-sm text-text-tertiary", children: notice }),
|
|
1656
|
+
error && /* @__PURE__ */ jsx8("p", { className: "text-sm text-text-danger", children: error })
|
|
1657
|
+
] }),
|
|
1658
|
+
/* @__PURE__ */ jsx8("div", { ref: spacer, "aria-hidden": true })
|
|
1659
|
+
]
|
|
1660
|
+
}
|
|
1661
|
+
),
|
|
1662
|
+
/* @__PURE__ */ jsxs6("div", { className: "relative mx-auto w-full max-w-[784px] px-4 pb-4 sm:px-6 sm:pb-6", children: [
|
|
1663
|
+
!atBottom && /* @__PURE__ */ jsx8(
|
|
2873
1664
|
"button",
|
|
2874
1665
|
{
|
|
2875
1666
|
type: "button",
|
|
2876
|
-
onClick:
|
|
2877
|
-
|
|
2878
|
-
className: "
|
|
2879
|
-
children:
|
|
1667
|
+
onClick: toBottom,
|
|
1668
|
+
"aria-label": t.goToLatest,
|
|
1669
|
+
className: "absolute -top-12 left-1/2 z-10 flex h-9 w-9 -translate-x-1/2 items-center justify-center rounded-full border border-border-primary bg-background-secondary text-text-secondary shadow-lg transition hover:text-text-primary",
|
|
1670
|
+
children: /* @__PURE__ */ jsx8(ArrowDown, { className: "h-4 w-4" })
|
|
2880
1671
|
}
|
|
2881
1672
|
),
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
showCopy: features.copy !== false,
|
|
2895
|
-
showDuration: features.duration !== false,
|
|
2896
|
-
renderDeliveries: slots.renderDeliveries
|
|
2897
|
-
}
|
|
2898
|
-
),
|
|
2899
|
-
turn.role === "assistant" && /* @__PURE__ */ jsx10(TurnNotes, { turn })
|
|
2900
|
-
] }, i - olderCount);
|
|
2901
|
-
}),
|
|
2902
|
-
busy && state.stalled && /* @__PURE__ */ jsx10("p", { className: "text-sm text-text-tertiary", children: state.stalled.message ?? t.stalled }),
|
|
2903
|
-
state.queued.map((q, i) => (
|
|
2904
|
-
// Esperan a que termine el run vivo (el servidor no los dejó entrar): salen solos.
|
|
2905
|
-
/* @__PURE__ */ jsxs8("div", { "data-queued": true, className: "flex flex-col items-end gap-1 opacity-60", children: [
|
|
2906
|
-
/* @__PURE__ */ jsx10(UserBubble, { turn: { role: "user", text: q.text, ...q.attachments ? { attachments: q.attachments } : {} } }),
|
|
2907
|
-
/* @__PURE__ */ jsx10("span", { className: "text-xs text-text-tertiary", children: t.queued })
|
|
2908
|
-
] }, `q${i}`)
|
|
2909
|
-
)),
|
|
2910
|
-
permissionCards,
|
|
2911
|
-
busy && !toolRunning && !cards.length && /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-1.5", children: [
|
|
2912
|
-
/* @__PURE__ */ jsx10(TypingDots, {}),
|
|
2913
|
-
/* @__PURE__ */ jsx10(WaitLabel, { since: state.turnStartedAt, step: state.step, showDuration: features.duration !== false })
|
|
1673
|
+
state.cutRun && !busy && // El servidor cortó la respuesta (deploy, caja caída): la persona decide si sigue.
|
|
1674
|
+
/* @__PURE__ */ jsxs6("div", { "data-cut-run": true, role: "status", className: "mb-2 flex items-center gap-3 rounded-2xl border border-border-primary bg-background-secondary px-3 py-2 text-sm text-text-secondary", children: [
|
|
1675
|
+
/* @__PURE__ */ jsx8("span", { className: "min-w-0 flex-1", children: state.cutRun.reason ?? t.runCut }),
|
|
1676
|
+
/* @__PURE__ */ jsx8(
|
|
1677
|
+
"button",
|
|
1678
|
+
{
|
|
1679
|
+
type: "button",
|
|
1680
|
+
onClick: () => void pilot.continueRun(),
|
|
1681
|
+
className: "shrink-0 rounded-full bg-brand-500 px-3 py-1 text-sm font-medium text-white transition hover:bg-brand-600",
|
|
1682
|
+
children: t.continueRun
|
|
1683
|
+
}
|
|
1684
|
+
)
|
|
2914
1685
|
] }),
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
]
|
|
1686
|
+
aboveComposer,
|
|
1687
|
+
composer,
|
|
1688
|
+
belowComposer
|
|
1689
|
+
] })
|
|
1690
|
+
] }))
|
|
2920
1691
|
}
|
|
2921
|
-
)
|
|
2922
|
-
|
|
2923
|
-
!atBottom && /* @__PURE__ */ jsx10(
|
|
2924
|
-
"button",
|
|
2925
|
-
{
|
|
2926
|
-
type: "button",
|
|
2927
|
-
onClick: toBottom,
|
|
2928
|
-
"aria-label": t.goToLatest,
|
|
2929
|
-
className: "absolute -top-12 left-1/2 z-10 flex h-9 w-9 -translate-x-1/2 items-center justify-center rounded-full border border-border-primary bg-background-secondary text-text-secondary shadow-lg transition hover:text-text-primary",
|
|
2930
|
-
children: /* @__PURE__ */ jsx10(ArrowDown, { className: "h-4 w-4" })
|
|
2931
|
-
}
|
|
2932
|
-
),
|
|
2933
|
-
state.cutRun && !busy && // El servidor cortó la respuesta (deploy, caja caída): la persona decide si sigue.
|
|
2934
|
-
/* @__PURE__ */ jsxs8("div", { "data-cut-run": true, role: "status", className: "mb-2 flex items-center gap-3 rounded-2xl border border-border-primary bg-background-secondary px-3 py-2 text-sm text-text-secondary", children: [
|
|
2935
|
-
/* @__PURE__ */ jsx10("span", { className: "min-w-0 flex-1", children: state.cutRun.reason ?? t.runCut }),
|
|
2936
|
-
/* @__PURE__ */ jsx10(
|
|
2937
|
-
"button",
|
|
2938
|
-
{
|
|
2939
|
-
type: "button",
|
|
2940
|
-
onClick: () => void pilot.continueRun(),
|
|
2941
|
-
className: "shrink-0 rounded-full bg-brand-500 px-3 py-1 text-sm font-medium text-white transition hover:bg-brand-600",
|
|
2942
|
-
children: t.continueRun
|
|
2943
|
-
}
|
|
2944
|
-
)
|
|
2945
|
-
] }),
|
|
2946
|
-
aboveComposer,
|
|
2947
|
-
composer
|
|
2948
|
-
] })
|
|
2949
|
-
] })) }) });
|
|
1692
|
+
)
|
|
1693
|
+
) });
|
|
2950
1694
|
});
|
|
1695
|
+
var warned = /* @__PURE__ */ new Set();
|
|
1696
|
+
function warnOnce(message) {
|
|
1697
|
+
if (warned.has(message)) return;
|
|
1698
|
+
warned.add(message);
|
|
1699
|
+
console.warn(`[ghostykit] ${message}`);
|
|
1700
|
+
}
|
|
1701
|
+
function pluginAttrs(plugin, styled) {
|
|
1702
|
+
return styled.has(plugin) ? { "data-plugin": plugin } : { "data-plugin": plugin, "data-piloto-isolate": "" };
|
|
1703
|
+
}
|
|
1704
|
+
function Views({ items, ctx, inline, className, styled }) {
|
|
1705
|
+
return /* @__PURE__ */ jsx8(Fragment4, { children: items.map(
|
|
1706
|
+
({ plugin, value: C }) => inline ? /* @__PURE__ */ jsx8("span", { ...pluginAttrs(plugin, styled), style: { display: "contents" }, children: /* @__PURE__ */ jsx8(C, { ctx }) }, plugin) : /* @__PURE__ */ jsx8("div", { ...pluginAttrs(plugin, styled), className, children: /* @__PURE__ */ jsx8(C, { ctx }) }, plugin)
|
|
1707
|
+
) });
|
|
1708
|
+
}
|
|
2951
1709
|
function TurnNotes({ turn }) {
|
|
2952
1710
|
const { strings: t } = usePiloto();
|
|
2953
1711
|
const failed = (turn.custom ?? []).filter((c) => c.name === "ghosty.attachments_failed").flatMap((c) => (c.value?.files ?? []).filter((f) => f?.name));
|
|
2954
1712
|
if (!failed.length && !turn.truncated) return null;
|
|
2955
|
-
return /* @__PURE__ */
|
|
2956
|
-
failed.map((f, i) => /* @__PURE__ */
|
|
2957
|
-
turn.truncated && /* @__PURE__ */
|
|
1713
|
+
return /* @__PURE__ */ jsxs6("div", { "data-turn-notes": true, className: "mt-1 flex flex-col gap-0.5 text-xs text-text-tertiary", children: [
|
|
1714
|
+
failed.map((f, i) => /* @__PURE__ */ jsx8("p", { children: t.attachmentFailed(f.name, f.reason) }, i)),
|
|
1715
|
+
turn.truncated && /* @__PURE__ */ jsx8("p", { children: turn.truncated.reason ?? t.truncated })
|
|
2958
1716
|
] });
|
|
2959
1717
|
}
|
|
2960
1718
|
|
|
2961
1719
|
// src/react/Subagents.tsx
|
|
2962
|
-
import { useState as
|
|
2963
|
-
import { jsx as
|
|
1720
|
+
import { useState as useState9 } from "react";
|
|
1721
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2964
1722
|
var DOT = {
|
|
2965
1723
|
running: "bg-brand-500 animate-pulse",
|
|
2966
1724
|
completed: "bg-text-tertiary",
|
|
@@ -2969,33 +1727,33 @@ var DOT = {
|
|
|
2969
1727
|
};
|
|
2970
1728
|
function Subagents({ pilot, defaultOpen = false, showFinished = true, className = "" }) {
|
|
2971
1729
|
const { strings: t } = usePiloto();
|
|
2972
|
-
const [open, setOpen] =
|
|
1730
|
+
const [open, setOpen] = useState9(defaultOpen);
|
|
2973
1731
|
const all = pilot.subagents;
|
|
2974
1732
|
const tasks = showFinished ? all : all.filter((x) => x.status === "running");
|
|
2975
1733
|
if (!tasks.length) return null;
|
|
2976
1734
|
const running = all.filter((x) => x.status === "running").length;
|
|
2977
|
-
return /* @__PURE__ */
|
|
2978
|
-
/* @__PURE__ */
|
|
2979
|
-
/* @__PURE__ */
|
|
2980
|
-
/* @__PURE__ */
|
|
2981
|
-
/* @__PURE__ */
|
|
1735
|
+
return /* @__PURE__ */ jsxs7("div", { "data-subagents": true, className: `mb-2 rounded-2xl border border-border-primary bg-background-secondary text-sm ${className}`, children: [
|
|
1736
|
+
/* @__PURE__ */ jsxs7("button", { type: "button", onClick: () => setOpen((o) => !o), "aria-expanded": open, className: "flex w-full items-center gap-2 px-3 py-2 text-left text-text-secondary", children: [
|
|
1737
|
+
/* @__PURE__ */ jsx9("span", { className: `h-2 w-2 shrink-0 rounded-full ${running ? DOT.running : DOT.completed}` }),
|
|
1738
|
+
/* @__PURE__ */ jsx9("span", { className: "flex-1 truncate", children: running ? t.subagentsWorking(running) : t.subagentsDone(tasks.length) }),
|
|
1739
|
+
/* @__PURE__ */ jsx9("span", { "aria-hidden": true, className: `text-text-tertiary transition-transform ${open ? "rotate-180" : ""}`, children: "\u2304" })
|
|
2982
1740
|
] }),
|
|
2983
|
-
open && /* @__PURE__ */
|
|
1741
|
+
open && /* @__PURE__ */ jsx9("ul", { className: "flex flex-col border-t border-border-primary", children: tasks.map((task) => /* @__PURE__ */ jsx9(SubagentRow, { task, onStop: () => void pilot.stopSubagent(task.id) }, task.id)) })
|
|
2984
1742
|
] });
|
|
2985
1743
|
}
|
|
2986
1744
|
function SubagentRow({ task, onStop }) {
|
|
2987
1745
|
const { strings: t } = usePiloto();
|
|
2988
1746
|
const line = task.status === "running" ? task.lastTool : task.summary ?? task.lastTool;
|
|
2989
|
-
return /* @__PURE__ */
|
|
2990
|
-
/* @__PURE__ */
|
|
2991
|
-
/* @__PURE__ */
|
|
2992
|
-
/* @__PURE__ */
|
|
2993
|
-
/* @__PURE__ */
|
|
1747
|
+
return /* @__PURE__ */ jsxs7("li", { "data-subagent": task.id, "data-status": task.status, className: "flex items-center gap-2 px-3 py-2", children: [
|
|
1748
|
+
/* @__PURE__ */ jsx9("span", { className: `h-2 w-2 shrink-0 rounded-full ${DOT[task.status] ?? DOT.completed}` }),
|
|
1749
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1", children: [
|
|
1750
|
+
/* @__PURE__ */ jsx9("div", { className: "truncate text-text-primary", children: task.title ?? task.id }),
|
|
1751
|
+
/* @__PURE__ */ jsxs7("div", { className: "truncate text-xs text-text-tertiary", children: [
|
|
2994
1752
|
t.subagentStatus[task.status] ?? task.status,
|
|
2995
1753
|
line ? ` \xB7 ${line}` : ""
|
|
2996
1754
|
] })
|
|
2997
1755
|
] }),
|
|
2998
|
-
task.status === "running" && /* @__PURE__ */
|
|
1756
|
+
task.status === "running" && /* @__PURE__ */ jsx9("button", { type: "button", onClick: onStop, className: "shrink-0 rounded-full border border-border-primary px-2.5 py-0.5 text-xs text-text-secondary transition hover:text-text-danger", children: t.subagentStop })
|
|
2999
1757
|
] });
|
|
3000
1758
|
}
|
|
3001
1759
|
export {
|
|
@@ -3041,8 +1799,10 @@ export {
|
|
|
3041
1799
|
createAgUiTransport,
|
|
3042
1800
|
createPilotState,
|
|
3043
1801
|
Piloto as default,
|
|
1802
|
+
definePlugin,
|
|
3044
1803
|
dropLastExchange,
|
|
3045
1804
|
expiryMs,
|
|
1805
|
+
extractBlocks,
|
|
3046
1806
|
extractReplyOptions,
|
|
3047
1807
|
formatDuration,
|
|
3048
1808
|
groupSteps,
|
|
@@ -3053,12 +1813,15 @@ export {
|
|
|
3053
1813
|
messagesToTurns,
|
|
3054
1814
|
mimeOf,
|
|
3055
1815
|
narrationToMarkdown,
|
|
1816
|
+
pluginPoints,
|
|
1817
|
+
pluginRequires,
|
|
3056
1818
|
prependHistory,
|
|
3057
1819
|
queueMessage,
|
|
3058
1820
|
readSse,
|
|
3059
1821
|
reduceAgUiEvent,
|
|
3060
1822
|
renderInline,
|
|
3061
1823
|
resolvePermission,
|
|
1824
|
+
resolvePlugins,
|
|
3062
1825
|
sendFailed,
|
|
3063
1826
|
splitNarration,
|
|
3064
1827
|
stepLabel,
|