ghostykit 0.6.4 → 0.7.0
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 +94 -19
- package/dist/chunks/{chunk-LPPND5ME.js → chunk-FWBUIGTC.js} +30 -145
- package/dist/chunks/chunk-UUH37KXA.js +144 -0
- package/dist/chunks/chunk-ZIUOXG7B.js +1757 -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/plugins/index.d.ts +39 -0
- package/dist/plugins/index.js +129 -0
- package/dist/react/Bubble.d.ts +11 -1
- package/dist/react/Composer.d.ts +11 -3
- package/dist/react/Piloto.d.ts +13 -37
- package/dist/react/context.d.ts +4 -1
- package/dist/react/index.d.ts +4 -3
- package/dist/react/index.js +503 -1788
- package/dist/react/plugins.d.ts +212 -0
- package/dist/react/usePilot.d.ts +15 -0
- package/dist/styles.css +572 -548
- package/package.json +5 -1
package/dist/core/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from "./types";
|
|
2
2
|
export { argsDetail, beginSend, beginSteer, createPilotState, dropLastExchange, expiryMs, lastUserTurn, markSubagent, messagesToTurns, prependHistory, queueMessage, reduceAgUiEvent, resolvePermission, sendFailed, stopTurn, subagentsOf, takeQueued, toPermission, } from "./reducer";
|
|
3
3
|
export { applyJsonPatch, type PatchOp } from "./jsonPatch";
|
|
4
|
-
export { isNarration, narrationToMarkdown, splitNarration } from "./narration";
|
|
4
|
+
export { extractBlocks, isNarration, narrationToMarkdown, splitNarration, type TextBlock } from "./narration";
|
|
5
5
|
export { cleanReplyOption, extractReplyOptions, type ReplyOptions } from "./options";
|
|
6
6
|
export { TOOL_VERBS_EN, TOOL_VERBS_ES, groupSteps, isRunning, stepLabel, summarizeTools, toolName, toolNames, type ToolVerb, type ToolVerbs, } from "./steps";
|
|
7
7
|
export { applyReferences, cleanUserText, formatDuration, systemNoteOf } from "./text";
|
package/dist/core/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,15 +20,21 @@ 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
|
|
26
|
+
toPermission
|
|
27
|
+
} from "../chunks/chunk-FWBUIGTC.js";
|
|
28
|
+
import {
|
|
29
|
+
TOOL_VERBS_EN,
|
|
30
|
+
TOOL_VERBS_ES,
|
|
31
|
+
groupSteps,
|
|
32
|
+
isRunning,
|
|
33
|
+
stepLabel,
|
|
34
|
+
summarizeTools,
|
|
32
35
|
toolName,
|
|
33
36
|
toolNames
|
|
34
|
-
} from "../chunks/chunk-
|
|
37
|
+
} from "../chunks/chunk-UUH37KXA.js";
|
|
35
38
|
import {
|
|
36
39
|
applyReferences,
|
|
37
40
|
cleanUserText,
|
|
@@ -51,6 +54,7 @@ export {
|
|
|
51
54
|
createPilotState,
|
|
52
55
|
dropLastExchange,
|
|
53
56
|
expiryMs,
|
|
57
|
+
extractBlocks,
|
|
54
58
|
extractReplyOptions,
|
|
55
59
|
formatDuration,
|
|
56
60
|
groupSteps,
|
package/dist/core/narration.d.ts
CHANGED
|
@@ -9,9 +9,26 @@
|
|
|
9
9
|
*/
|
|
10
10
|
/** Un tramo es «narración» si es corto y de un solo párrafo; si no, es texto normal. */
|
|
11
11
|
export declare function isNarration(chunk: string): boolean;
|
|
12
|
-
export declare function splitNarration(text: string, cuts?: number[]): {
|
|
12
|
+
export declare function splitNarration(text: string, cuts?: number[], closed?: boolean): {
|
|
13
13
|
steps: string[];
|
|
14
14
|
rest: string;
|
|
15
15
|
};
|
|
16
16
|
/** La copia que se guarda: narración como `- ✓ …` y luego la respuesta. */
|
|
17
17
|
export declare function narrationToMarkdown(chunks: string[], answer: string): string;
|
|
18
|
+
/** Un bloque con nombre del texto (```eb-file …```) que una app pinta como tarjeta. */
|
|
19
|
+
export interface TextBlock {
|
|
20
|
+
lang: string;
|
|
21
|
+
body: string;
|
|
22
|
+
/** El bloque ya cerró (en vivo, uno a medio escribir llega sin cerrar). */
|
|
23
|
+
complete: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Saca del texto los bloques ```<lang>``` cuyos nombres se piden (sólo los que abren al inicio de un
|
|
27
|
+
* renglón) y recorre los cortes de la narración para que sigan cayendo donde caían. Uno sin cerrar
|
|
28
|
+
* (todavía se escribe) se saca hasta el final.
|
|
29
|
+
*/
|
|
30
|
+
export declare function extractBlocks(text: string, langs: readonly string[], cuts?: number[]): {
|
|
31
|
+
text: string;
|
|
32
|
+
cuts?: number[];
|
|
33
|
+
blocks: TextBlock[];
|
|
34
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type PilotoPlugin, type PluginCtx } from "../react/plugins";
|
|
2
|
+
export interface ModelPickerOptions {
|
|
3
|
+
/** La llave de `agentState` con `{current, options: [{value, name}]}`. Default: `model`. */
|
|
4
|
+
stateKey?: string;
|
|
5
|
+
/** Cambiar de modelo es API de la app (no un run): aquí la llamas. */
|
|
6
|
+
onChange: (value: string, ctx: PluginCtx) => void | Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* El selector de modelo en la barra del composer, con lo que el agente anuncia en
|
|
10
|
+
* `agentState.model = {current, options}`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function modelPicker({ stateKey, onChange }: ModelPickerOptions): PilotoPlugin;
|
|
13
|
+
/** Una página que el agente arma en vivo (`CUSTOM ghosty.page`). */
|
|
14
|
+
export interface LivePage {
|
|
15
|
+
pageId: string;
|
|
16
|
+
title: string;
|
|
17
|
+
sections: {
|
|
18
|
+
id: string;
|
|
19
|
+
title?: string;
|
|
20
|
+
status: "pending" | "building" | "done" | "failed";
|
|
21
|
+
}[];
|
|
22
|
+
url: string | null;
|
|
23
|
+
error?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface LivePageOptions {
|
|
26
|
+
/** Ancho del panel. Default: 320 px. */
|
|
27
|
+
width?: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* El panel de la página en vivo: escucha `ghosty.page` (plan, secciones, lista, error) y pinta el
|
|
31
|
+
* avance a un lado del chat, con el enlace al terminar.
|
|
32
|
+
*/
|
|
33
|
+
export declare function livePage({ width }?: LivePageOptions): PilotoPlugin;
|
|
34
|
+
export interface DevtoolsOptions {
|
|
35
|
+
/** Además de la lista de plugins, cada evento con quién lo atiende. Default: no. */
|
|
36
|
+
events?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/** Imprime en consola los plugins montados, sus puntos y lo que atienden (y, si quieres, cada evento). */
|
|
39
|
+
export declare function pilotDevtools({ events }?: DevtoolsOptions): PilotoPlugin;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ModelPicker,
|
|
3
|
+
definePlugin,
|
|
4
|
+
pluginPoints,
|
|
5
|
+
pluginRequires
|
|
6
|
+
} from "../chunks/chunk-ZIUOXG7B.js";
|
|
7
|
+
import "../chunks/chunk-UUH37KXA.js";
|
|
8
|
+
import "../chunks/chunk-6U545WJG.js";
|
|
9
|
+
|
|
10
|
+
// src/plugins/index.tsx
|
|
11
|
+
import { useEffect, useState, useSyncExternalStore } from "react";
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
function modelPicker({ stateKey = "model", onChange }) {
|
|
14
|
+
function Picker({ ctx }) {
|
|
15
|
+
const model = ctx.agentState[stateKey];
|
|
16
|
+
const [chosen, setChosen] = useState(null);
|
|
17
|
+
useEffect(() => setChosen(null), [model?.current]);
|
|
18
|
+
if (!model?.options?.length) return null;
|
|
19
|
+
return /* @__PURE__ */ jsx(
|
|
20
|
+
ModelPicker,
|
|
21
|
+
{
|
|
22
|
+
models: model.options,
|
|
23
|
+
current: chosen ?? model.current ?? null,
|
|
24
|
+
onChange: (value) => {
|
|
25
|
+
setChosen(value);
|
|
26
|
+
void onChange(value, ctx);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return definePlugin({ name: "modelPicker", styles: "ghostykit", requires: { state: [stateKey] }, composer: { actionsEnd: Picker } });
|
|
32
|
+
}
|
|
33
|
+
function livePage({ width = 320 } = {}) {
|
|
34
|
+
let page = null;
|
|
35
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
36
|
+
const set = (next) => {
|
|
37
|
+
page = next;
|
|
38
|
+
for (const l of listeners) l();
|
|
39
|
+
};
|
|
40
|
+
const store = {
|
|
41
|
+
subscribe: (l) => {
|
|
42
|
+
listeners.add(l);
|
|
43
|
+
return () => void listeners.delete(l);
|
|
44
|
+
},
|
|
45
|
+
get: () => page
|
|
46
|
+
};
|
|
47
|
+
const status = (id, s) => page && set({ ...page, sections: page.sections.map((x) => x.id === id ? { ...x, status: s } : x) });
|
|
48
|
+
function onPage(e) {
|
|
49
|
+
const v = e.value ?? {};
|
|
50
|
+
switch (v.event) {
|
|
51
|
+
case "page-plan":
|
|
52
|
+
return set({ pageId: v.pageId, title: v.title, url: null, sections: (v.sections ?? []).map((x) => ({ id: x.id, title: x.title, status: "pending" })) });
|
|
53
|
+
case "section-building":
|
|
54
|
+
return status(v.id, "building");
|
|
55
|
+
case "section":
|
|
56
|
+
return status(v.id, v.ok === false ? "failed" : "done");
|
|
57
|
+
case "page-ready":
|
|
58
|
+
return page && set({ ...page, title: v.title ?? page.title, url: v.url ?? null });
|
|
59
|
+
case "page-error":
|
|
60
|
+
return page && set({ ...page, error: v.message });
|
|
61
|
+
case "page-drop":
|
|
62
|
+
return page?.pageId === v.pageId && set(null);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function Panel({ ctx }) {
|
|
66
|
+
const p = useSyncExternalStore(store.subscribe, store.get, store.get);
|
|
67
|
+
if (!p) return null;
|
|
68
|
+
const done = p.sections.filter((x) => x.status === "done").length;
|
|
69
|
+
return /* @__PURE__ */ jsxs("aside", { style: { width }, className: "hidden shrink-0 flex-col gap-3 overflow-y-auto border-l border-border-primary bg-background-secondary p-4 text-sm md:flex", children: [
|
|
70
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
71
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium text-text-primary", children: p.title }),
|
|
72
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-text-tertiary", children: [
|
|
73
|
+
done,
|
|
74
|
+
"/",
|
|
75
|
+
p.sections.length,
|
|
76
|
+
" ",
|
|
77
|
+
ctx.strings.numberLocale.startsWith("en") ? "sections" : "secciones"
|
|
78
|
+
] })
|
|
79
|
+
] }),
|
|
80
|
+
/* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1.5", children: p.sections.map((x) => /* @__PURE__ */ jsxs("li", { "data-status": x.status, className: "flex items-center gap-2", children: [
|
|
81
|
+
/* @__PURE__ */ jsx(
|
|
82
|
+
"span",
|
|
83
|
+
{
|
|
84
|
+
className: `h-2 w-2 shrink-0 rounded-full ${x.status === "done" ? "bg-text-success" : x.status === "failed" ? "bg-text-danger" : x.status === "building" ? "animate-pulse bg-brand-500" : "bg-border-primary"}`
|
|
85
|
+
}
|
|
86
|
+
),
|
|
87
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-text-secondary", children: x.title ?? x.id })
|
|
88
|
+
] }, x.id)) }),
|
|
89
|
+
p.error && /* @__PURE__ */ jsx("p", { className: "text-xs text-text-danger", children: p.error }),
|
|
90
|
+
p.url && /* @__PURE__ */ jsx("a", { href: p.url, target: "_blank", rel: "noopener noreferrer", className: "self-start rounded-full bg-brand-500 px-3 py-1 text-white hover:bg-brand-600", children: ctx.strings.linkOpen })
|
|
91
|
+
] });
|
|
92
|
+
}
|
|
93
|
+
return definePlugin({ name: "livePage", styles: "ghostykit", requires: { events: ["ghosty.page"] }, events: { "ghosty.page": onPage }, sidePanel: Panel });
|
|
94
|
+
}
|
|
95
|
+
function pilotDevtools({ events = false } = {}) {
|
|
96
|
+
function Devtools({ ctx }) {
|
|
97
|
+
const names = ctx.plugins.map((p) => p.name).join(",");
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
console.groupCollapsed(`[ghostykit] ${ctx.plugins.length} plugins`);
|
|
100
|
+
console.table(
|
|
101
|
+
ctx.plugins.map((p) => {
|
|
102
|
+
const req = pluginRequires(p);
|
|
103
|
+
return { plugin: p.name, points: pluginPoints(p).join(" "), events: req.events.join(" "), state: req.state.join(" ") };
|
|
104
|
+
})
|
|
105
|
+
);
|
|
106
|
+
console.groupEnd();
|
|
107
|
+
}, [names]);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
return definePlugin({
|
|
111
|
+
name: "pilotDevtools",
|
|
112
|
+
styles: "ghostykit",
|
|
113
|
+
aboveThread: Devtools,
|
|
114
|
+
...events ? {
|
|
115
|
+
events: {
|
|
116
|
+
"*": (e, ctx) => {
|
|
117
|
+
const key = e.type === "CUSTOM" ? e.name : e.type;
|
|
118
|
+
const who = ctx.plugins.filter((p) => p.name !== "pilotDevtools" && (p.events?.[e.type] || key && (p.events?.[key] || p.message?.custom?.[key]))).map((p) => p.name);
|
|
119
|
+
console.debug(`[ghostykit] ${e.type}${e.type === "CUSTOM" ? ` ${e.name}` : ""}`, who.length ? `\u2192 ${who.join(", ")}` : "", e);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
} : {}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
export {
|
|
126
|
+
livePage,
|
|
127
|
+
modelPicker,
|
|
128
|
+
pilotDevtools
|
|
129
|
+
};
|
package/dist/react/Bubble.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
+
import { type TextBlock } from "../core/narration";
|
|
2
3
|
import { type ReplyOptions } from "../core/options";
|
|
3
4
|
import type { Turn, Usage } from "../core/types";
|
|
4
5
|
export declare function UserBubble({ turn }: {
|
|
@@ -35,5 +36,14 @@ export interface AgentBubbleProps {
|
|
|
35
36
|
showDuration?: boolean;
|
|
36
37
|
/** Lo que la app quiera pintar bajo la respuesta (archivos, tarjetas propias). */
|
|
37
38
|
renderDeliveries?: (turn: Turn, live: boolean) => ReactNode;
|
|
39
|
+
/** Vistas propias de las herramientas, justo bajo los pasos. */
|
|
40
|
+
renderTools?: (turn: Turn, live: boolean) => ReactNode;
|
|
41
|
+
/** Antes del texto de la respuesta, bajo sus pasos. */
|
|
42
|
+
renderBefore?: (turn: Turn, live: boolean) => ReactNode;
|
|
43
|
+
/** Bloques con nombre (```eb-file```) que salen del texto y se pintan como tarjetas bajo la respuesta. */
|
|
44
|
+
blocks?: {
|
|
45
|
+
langs: string[];
|
|
46
|
+
render: (blocks: TextBlock[], turn: Turn, live: boolean) => ReactNode;
|
|
47
|
+
};
|
|
38
48
|
}
|
|
39
|
-
export declare function AgentBubble({ turn, live, onRetry, onOption, showUsage, showCopy, showDuration, renderDeliveries }: AgentBubbleProps): import("react").JSX.Element;
|
|
49
|
+
export declare function AgentBubble({ turn, live, onRetry, onOption, showUsage, showCopy, showDuration, renderDeliveries, renderTools, renderBefore, blocks }: AgentBubbleProps): import("react").JSX.Element;
|
package/dist/react/Composer.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ReactNode } from "react";
|
|
1
|
+
import { type ReactNode, type Ref } from "react";
|
|
2
2
|
import type { Attachment, Reference } from "../core/types";
|
|
3
3
|
/** Un modelo que la app ofrece elegir (AG-UI no lo define: la app lo manda en `forwardedProps`). */
|
|
4
4
|
export interface ModelOption {
|
|
@@ -10,6 +10,10 @@ export interface UploadResult {
|
|
|
10
10
|
url: string;
|
|
11
11
|
id?: string;
|
|
12
12
|
}
|
|
13
|
+
/** Lo que se puede hacer con la caja desde afuera (`ctx.addAttachments`). */
|
|
14
|
+
export interface ComposerHandle {
|
|
15
|
+
addAttachments: (items: (File | Attachment)[]) => void;
|
|
16
|
+
}
|
|
13
17
|
/** El tipo del archivo, deducido del nombre cuando el navegador no lo dice (pasa más de lo que parece). */
|
|
14
18
|
export declare function mimeOf(file: File): string;
|
|
15
19
|
export interface ComposerProps {
|
|
@@ -36,12 +40,16 @@ export interface ComposerProps {
|
|
|
36
40
|
references?: Reference[];
|
|
37
41
|
onRemoveReference?: (id: string) => void;
|
|
38
42
|
onActivateReference?: (ref: Reference) => void;
|
|
39
|
-
/** Botones propios
|
|
43
|
+
/** Botones propios entre la imagen y el clip. */
|
|
40
44
|
extras?: ReactNode;
|
|
45
|
+
/** Botones propios después del clip. */
|
|
46
|
+
extrasEnd?: ReactNode;
|
|
47
|
+
/** Para agregar adjuntos desde afuera. */
|
|
48
|
+
handleRef?: Ref<ComposerHandle>;
|
|
41
49
|
maxFiles?: number;
|
|
42
50
|
maxFileMb?: number;
|
|
43
51
|
}
|
|
44
|
-
export declare function Composer({ onSubmit, onStop, busy, canSteer, placeholder, initialValue, autoFocus, canSeeImages, attachments: withFiles, upload, transcribe, voiceNoteText, models, currentModel, onModelChange, references, onRemoveReference, onActivateReference, extras, maxFiles, maxFileMb, }: ComposerProps): import("react").JSX.Element;
|
|
52
|
+
export declare function Composer({ onSubmit, onStop, busy, canSteer, placeholder, initialValue, autoFocus, canSeeImages, attachments: withFiles, upload, transcribe, voiceNoteText, models, currentModel, onModelChange, references, onRemoveReference, onActivateReference, extras, extrasEnd, handleRef, maxFiles, maxFileMb, }: ComposerProps): import("react").JSX.Element;
|
|
45
53
|
/**
|
|
46
54
|
* El selector de modelo. PORTADO de Ghosty (`ModelPicker.tsx`): dropdown discreto hacia arriba, sin
|
|
47
55
|
* Radix; cierra con clic fuera y con Escape.
|
package/dist/react/Piloto.d.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { type CSSProperties, type ReactNode } from "react";
|
|
2
|
-
import {
|
|
3
|
-
import type { Attachment, Reference, Turn } from "../core/types";
|
|
2
|
+
import type { Reference } from "../core/types";
|
|
4
3
|
import type { PilotTransport } from "../transport";
|
|
5
|
-
import { type
|
|
6
|
-
import { type
|
|
7
|
-
import { type PilotStrings } from "./strings";
|
|
4
|
+
import { type PilotTheme } from "./context";
|
|
5
|
+
import { type PilotoPlugin, type PluginCtx } from "./plugins";
|
|
8
6
|
import { type Pilot, type UsePilotOptions } from "./usePilot";
|
|
9
7
|
export interface PilotoFeatures {
|
|
10
8
|
/** Botones de adjuntar. Default: sí si hay `upload`. */
|
|
@@ -22,45 +20,22 @@ export interface PilotoFeatures {
|
|
|
22
20
|
/** Mandar con el run vivo (steer). Default: lo que diga el agente en `state.caps.steer`. */
|
|
23
21
|
steer?: boolean;
|
|
24
22
|
}
|
|
25
|
-
export interface PilotoSlots {
|
|
26
|
-
/** Lo que la app pinte bajo cada respuesta (archivos, tarjetas propias). */
|
|
27
|
-
renderDeliveries?: (turn: Turn, live: boolean) => ReactNode;
|
|
28
|
-
/** Botones propios en la barra del composer. */
|
|
29
|
-
composerExtras?: ReactNode;
|
|
30
|
-
/** Lo que se ve con el hilo vacío (en lugar del saludo de casa). */
|
|
31
|
-
emptyState?: ReactNode;
|
|
32
|
-
/** Arriba a la derecha, sobre el hilo (compartir, abrir en grande…). */
|
|
33
|
-
headerActions?: ReactNode;
|
|
34
|
-
/** Pegado arriba del composer (un aviso, un banner, `<Subagents pilot={pilot} />`). */
|
|
35
|
-
aboveComposer?: ReactNode | ((pilot: Pilot) => ReactNode);
|
|
36
|
-
/** Un panel junto al chat (subagentes, vista previa), con el estado del agente y el piloto. */
|
|
37
|
-
sidePanel?: (agentState: Record<string, unknown>, pilot: Pilot) => ReactNode;
|
|
38
|
-
}
|
|
39
23
|
export interface PilotoProps extends UsePilotOptions {
|
|
40
24
|
transport: PilotTransport | null;
|
|
41
25
|
/** Si la app ya usa `usePilot` (para leer el estado afuera), pásalo aquí. */
|
|
42
26
|
pilot?: Pilot;
|
|
43
27
|
agentName?: string;
|
|
44
28
|
locale?: "es" | "en";
|
|
45
|
-
strings?: Partial<PilotStrings>;
|
|
46
29
|
theme?: PilotTheme;
|
|
47
30
|
/** La piel: `ghosty` (default), `easybits`, `neutral`, o el nombre de una propia (`[data-skin]`). */
|
|
48
31
|
skin?: string;
|
|
49
32
|
className?: string;
|
|
50
33
|
style?: CSSProperties;
|
|
51
|
-
toolVerbs?: ToolVerbs;
|
|
52
|
-
toolIcons?: Record<string, PilotIcon>;
|
|
53
|
-
/** El texto del usuario como se pinta (quita la fontanería que la app pega al prompt). */
|
|
54
|
-
formatUserText?: (text: string) => string;
|
|
55
|
-
markdown?: MarkdownOptions;
|
|
56
34
|
/** Saludo del hilo vacío. */
|
|
57
35
|
welcome?: ReactNode;
|
|
58
36
|
avatar?: ReactNode;
|
|
59
37
|
placeholder?: string;
|
|
60
38
|
suggestions?: string[];
|
|
61
|
-
upload?: (file: File) => Promise<UploadResult>;
|
|
62
|
-
transcribe?: (audio: Blob) => Promise<string>;
|
|
63
|
-
voiceNoteText?: (transcript: string) => string;
|
|
64
39
|
features?: PilotoFeatures;
|
|
65
40
|
/**
|
|
66
41
|
* Una pregunta lista en la caja (sin mandarla) y el foco en ella: al abrir el piloto desde una
|
|
@@ -75,15 +50,16 @@ export interface PilotoProps extends UsePilotOptions {
|
|
|
75
50
|
onReferencesChange?: (refs: Reference[]) => void;
|
|
76
51
|
/** Clic en un chip de referencia (resaltar la tarjeta en la app). */
|
|
77
52
|
onReferenceClick?: (ref: Reference) => void;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
addReference: (ref: Reference) => void;
|
|
84
|
-
/** Escribe en la caja sin mandar. */
|
|
85
|
-
setDraft: (text: string) => void;
|
|
86
|
-
focus: () => void;
|
|
53
|
+
/**
|
|
54
|
+
* La ÚNICA forma de personalizar: textos, pasos, eventos, entregas, composer y paneles (ver
|
|
55
|
+
* `PilotoPlugin`). Créalos una vez (fuera del render o con `useMemo`).
|
|
56
|
+
*/
|
|
57
|
+
plugins?: readonly PilotoPlugin[];
|
|
87
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Lo que la app puede hacer desde afuera (`<Piloto ref={…} />`): lo MISMO que recibe un plugin en
|
|
61
|
+
* `ctx`. Con `pilot` (estado, `reconnect`, `stop`, `continueRun`…) nadie necesita `usePilot` aparte.
|
|
62
|
+
*/
|
|
63
|
+
export type PilotoHandle = Omit<PluginCtx, "plugins" | "strings" | "agentState">;
|
|
88
64
|
export declare const Piloto: import("react").ForwardRefExoticComponent<PilotoProps & import("react").RefAttributes<PilotoHandle>>;
|
|
89
65
|
export default Piloto;
|
package/dist/react/context.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ComponentType } from "react";
|
|
2
2
|
import { type ToolVerbs } from "../core/steps";
|
|
3
|
+
import type { Turn } from "../core/types";
|
|
3
4
|
import { type PilotStrings } from "./strings";
|
|
4
5
|
/** Un ícono: cualquier componente que acepte `className` (los de lucide-react sirven tal cual). */
|
|
5
6
|
export type PilotIcon = ComponentType<{
|
|
@@ -9,7 +10,7 @@ export type PilotTheme = "light" | "dark" | "auto";
|
|
|
9
10
|
/** Ajustes del markdown de las respuestas. */
|
|
10
11
|
export interface MarkdownOptions {
|
|
11
12
|
/** Reescribe el markdown antes de pintarlo (p. ej. `#12` → `[#12](#folio-12)`). */
|
|
12
|
-
transform?: (md: string) => string;
|
|
13
|
+
transform?: (md: string, turn?: Turn) => string;
|
|
13
14
|
/** Un clic en un enlace. Devuelve `true` si la app lo manejó (no se abre el aviso de salida). */
|
|
14
15
|
onLinkClick?: (href: string, event: MouseEvent) => boolean;
|
|
15
16
|
}
|
|
@@ -26,6 +27,8 @@ export interface PilotoConfig {
|
|
|
26
27
|
}
|
|
27
28
|
export declare const PilotoContext: import("react").Context<PilotoConfig>;
|
|
28
29
|
export declare const usePiloto: () => PilotoConfig;
|
|
30
|
+
/** La respuesta que se está pintando (para `markdown.transform(md, turn)`). */
|
|
31
|
+
export declare const TurnContext: import("react").Context<Turn | undefined>;
|
|
29
32
|
/** Las clases de la raíz: el alcance de los estilos y el tema. Lo usan también los portales. */
|
|
30
33
|
export declare function rootProps(theme: PilotTheme, skin?: string): {
|
|
31
34
|
className: string;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
export { Piloto, Piloto as default, type PilotoFeatures, type PilotoHandle, type PilotoProps
|
|
2
|
-
export {
|
|
1
|
+
export { Piloto, Piloto as default, type PilotoFeatures, type PilotoHandle, type PilotoProps } from "./Piloto";
|
|
2
|
+
export { definePlugin, pluginPoints, pluginRequires, resolvePlugins, type PilotoPlugin, type PluginCtx, type PluginEvent, type PluginView, type ResolvedPlugins, } from "./plugins";
|
|
3
|
+
export { toAgUiContext, usePilot, type Pilot, type SendOptions, type TurnDoneInfo, type TurnEvent, type UsePilotOptions } from "./usePilot";
|
|
3
4
|
export { AgentBubble, CopyUserMessage, ReplyOptionButtons, TurnFooter, UsageStats, UserBubble, type AgentBubbleProps } from "./Bubble";
|
|
4
5
|
export { AgentSteps, ArcadeIcon, ClawIcon, DEFAULT_TOOL_ICONS, Narration, RobotArmIcon, ToolRow } from "./Steps";
|
|
5
6
|
export { LinkSafetyModal, Markdown } from "./Markdown";
|
|
6
7
|
export { InlineMarkdown, renderInline } from "./InlineMarkdown";
|
|
7
8
|
export { useTextAtPace } from "./TextAtPace";
|
|
8
|
-
export { Composer, ModelPicker, mimeOf, type ComposerProps, type ModelOption, type UploadResult } from "./Composer";
|
|
9
|
+
export { Composer, ModelPicker, mimeOf, type ComposerHandle, type ComposerProps, type ModelOption, type UploadResult } from "./Composer";
|
|
9
10
|
export { ConfirmCard, DecisionLines } from "./ConfirmCard";
|
|
10
11
|
export { ReferenceChips, Suggestions } from "./Chips";
|
|
11
12
|
export { TypingDots, WaitLabel } from "./Status";
|