ghostykit 0.2.1 → 0.3.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 +8 -4
- package/dist/chunks/{chunk-D6JXJWYM.js → chunk-XZHX2NZT.js} +2 -0
- package/dist/fonts.css +3 -3
- package/dist/react/Bubble.d.ts +4 -2
- package/dist/react/Chips.d.ts +7 -3
- package/dist/react/Composer.d.ts +4 -1
- package/dist/react/Status.d.ts +1 -1
- package/dist/react/Steps.d.ts +11 -6
- package/dist/react/connectingGate.d.ts +17 -0
- package/dist/react/index.js +544 -345
- package/dist/styles.css +652 -534
- package/dist/transport/index.js +1 -1
- package/dist/transport/types.d.ts +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Piloto UI · `ghostykit`
|
|
2
2
|
|
|
3
3
|
**An in-app copilot for React.** Piloto UI is the agent chat from
|
|
4
|
-
[Ghosty Studio](https://www.ghosty.studio), packaged as a library
|
|
4
|
+
[Ghosty Studio](https://www.ghosty.studio) (`/c`), packaged as a library: same components, same
|
|
5
|
+
markup, same look ([side by side](https://raw.githubusercontent.com/blissito/ghostykit/main/docs/screenshots/parity/desktop-done-gs-vs-ghostykit.png)). You drop it into an app you already
|
|
5
6
|
have. It sees what the user has on screen, streams what the agent says and does, and **stops to ask
|
|
6
7
|
before anything risky** (human in the loop).
|
|
7
8
|
|
|
@@ -131,9 +132,11 @@ your own layout.
|
|
|
131
132
|
### Skins and theming
|
|
132
133
|
|
|
133
134
|
`ghostykit/styles.css` is self-contained and scoped under `.piloto`. It works the same with
|
|
134
|
-
**Tailwind 3, Tailwind 4 or no Tailwind
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
**Tailwind 3, Tailwind 4 or no Tailwind**, and it shields its fields from the host's CSS (verified
|
|
136
|
+
in a Tailwind 3 app **with `@tailwindcss/forms`**: Piloto's textarea gets no border or focus ring, and
|
|
137
|
+
the app's own utilities compute identically with and without Piloto's CSS). Sizes don't depend on
|
|
138
|
+
the host's `html` font size either: `1rem` inside Piloto is `--piloto-rem` (18 px in the Ghosty skin,
|
|
139
|
+
like ghosty.studio; 16 px in the others). Every color, radius, border width and shadow is a variable:
|
|
137
140
|
|
|
138
141
|
```css
|
|
139
142
|
.my-app .piloto {
|
|
@@ -142,6 +145,7 @@ variable:
|
|
|
142
145
|
--piloto-radius-card: 6px;
|
|
143
146
|
--piloto-border-width: 3px;
|
|
144
147
|
--piloto-shadow-hero: 6px 6px 0 #0f766e;
|
|
148
|
+
--piloto-rem: 16px;
|
|
145
149
|
--piloto-font: "Your Sans", sans-serif;
|
|
146
150
|
}
|
|
147
151
|
```
|
|
@@ -141,6 +141,8 @@ function createPostStreamTransport(target, options = {}) {
|
|
|
141
141
|
return {
|
|
142
142
|
// Sin steer: con un turno corriendo el servidor contesta 409. El composer no deja mandar.
|
|
143
143
|
steer: false,
|
|
144
|
+
// Cada turno trae su stream: no hay «conectando» que enseñar.
|
|
145
|
+
stream: "per-turn",
|
|
144
146
|
subscribe(l, sub = {}) {
|
|
145
147
|
listener = l;
|
|
146
148
|
isBusy = sub.isBusy ?? (() => false);
|
package/dist/fonts.css
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/* Opcional: las fuentes de las pieles de casa (
|
|
2
|
-
|
|
3
|
-
@import url("https://fonts.googleapis.com/css2?family=Big+Shoulders+Stencil+Display:wght@
|
|
1
|
+
/* Opcional: las fuentes de las pieles de casa — Inter (la de Ghosty) y Big Shoulders Stencil (el
|
|
2
|
+
reloj y el sello del pase de permiso). Sin esto, Piloto cae a las fuentes del sistema. */
|
|
3
|
+
@import url("https://fonts.googleapis.com/css2?family=Big+Shoulders+Stencil+Display:wght@800;900&family=Inter:opsz,wght@14..32,400..800&display=swap");
|
package/dist/react/Bubble.d.ts
CHANGED
|
@@ -16,11 +16,12 @@ export declare function ReplyOptionButtons({ options, onPick }: {
|
|
|
16
16
|
/** Tokens del turno, qué tanto del contexto se llevó y cuánto costó. */
|
|
17
17
|
export declare function UsageStats({ used, size, cost }: Usage): import("react").JSX.Element | null;
|
|
18
18
|
/** El pie de una respuesta terminada: cuánto tardó, copiar y reintentar. */
|
|
19
|
-
export declare function TurnFooter({ text, seconds, onRetry, showCopy }: {
|
|
19
|
+
export declare function TurnFooter({ text, seconds, onRetry, showCopy, showDuration }: {
|
|
20
20
|
text: string;
|
|
21
21
|
seconds?: number;
|
|
22
22
|
onRetry?: () => void;
|
|
23
23
|
showCopy?: boolean;
|
|
24
|
+
showDuration?: boolean;
|
|
24
25
|
}): import("react").JSX.Element;
|
|
25
26
|
/** Las entregas por defecto: una ficha por archivo (las apps pintan las suyas con `renderDeliveries`). */
|
|
26
27
|
export declare function DeliveryChips({ deliveries }: {
|
|
@@ -35,7 +36,8 @@ export interface AgentBubbleProps {
|
|
|
35
36
|
onOption?: (text: string) => void;
|
|
36
37
|
showUsage?: boolean;
|
|
37
38
|
showCopy?: boolean;
|
|
39
|
+
showDuration?: boolean;
|
|
38
40
|
/** Las entregas (y lo que la app quiera bajo la respuesta). Sin esto, fichas simples. */
|
|
39
41
|
renderDeliveries?: (turn: Turn, live: boolean) => ReactNode;
|
|
40
42
|
}
|
|
41
|
-
export declare function AgentBubble({ turn, live, onRetry, onOption, showUsage, showCopy, renderDeliveries }: AgentBubbleProps): import("react").JSX.Element;
|
|
43
|
+
export declare function AgentBubble({ turn, live, onRetry, onOption, showUsage, showCopy, showDuration, renderDeliveries }: AgentBubbleProps): import("react").JSX.Element;
|
package/dist/react/Chips.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import type { Reference } from "../core/types";
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Las referencias del mensaje: chips atómicos con ×. Una con `prompt` (un elemento señalado) se pinta
|
|
4
|
+
* con la mira, como en Ghosty; las demás (tarjetas del tablero), con su etiqueta. Clic = `onActivate`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function ReferenceChips({ references, onRemove, onActivate }: {
|
|
4
7
|
references: Reference[];
|
|
5
8
|
onRemove: (id: string) => void;
|
|
6
9
|
onActivate?: (ref: Reference) => void;
|
|
7
10
|
}): import("react").JSX.Element | null;
|
|
8
11
|
/** Sugerencias para arrancar. Una que termina en «: » se escribe en la caja en vez de mandarse. */
|
|
9
|
-
export declare function Suggestions({ items, onPick, onPrefill }: {
|
|
12
|
+
export declare function Suggestions({ items, onPick, onPrefill, disabled }: {
|
|
10
13
|
items: string[];
|
|
11
14
|
onPick: (text: string) => void;
|
|
12
15
|
onPrefill?: (text: string) => void;
|
|
16
|
+
disabled?: boolean;
|
|
13
17
|
}): import("react").JSX.Element | null;
|
package/dist/react/Composer.d.ts
CHANGED
|
@@ -37,7 +37,10 @@ export interface ComposerProps {
|
|
|
37
37
|
maxFileMb?: number;
|
|
38
38
|
}
|
|
39
39
|
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;
|
|
40
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* El selector de modelo. PORTADO de Ghosty (`ModelPicker.tsx`): dropdown discreto hacia arriba, sin
|
|
42
|
+
* Radix; cierra con clic fuera y con Escape.
|
|
43
|
+
*/
|
|
41
44
|
export declare function ModelPicker({ models, current, onChange }: {
|
|
42
45
|
models: ModelOption[];
|
|
43
46
|
current: string | null;
|
package/dist/react/Status.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import type { ConnectPhase } from "../core/types";
|
|
3
|
-
/** Los tres
|
|
3
|
+
/** Los tres puntitos de «escribiendo» (color y animación en CSS: `gc-typing`). */
|
|
4
4
|
export declare function TypingDots(): import("react").JSX.Element;
|
|
5
5
|
export declare function WaitLabel({ phase, since, elsewhere, onLost, showDuration, }: {
|
|
6
6
|
phase: ConnectPhase;
|
package/dist/react/Steps.d.ts
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
|
-
import { type ReactNode } from "react";
|
|
2
1
|
import type { ToolEntry } from "../core/types";
|
|
3
2
|
import { type PilotIcon } from "./context";
|
|
4
|
-
/** La garra de máquina de peluches: el ícono de «usó una herramienta»
|
|
3
|
+
/** La garra de máquina de peluches: el ícono de «usó una herramienta» (baja, cierra y sube en bucle). */
|
|
5
4
|
export declare function ClawIcon({ className }: {
|
|
6
5
|
className?: string;
|
|
7
6
|
}): import("react").JSX.Element;
|
|
8
|
-
/**
|
|
7
|
+
/** Brazo robot agarrando — «Robot grab» de Delapouite (game-icons.net, CC BY 3.0): los pasos técnicos. */
|
|
8
|
+
export declare function RobotArmIcon({ className }: {
|
|
9
|
+
className?: string;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
11
|
+
/** Máquina arcade (Iconoir «arcade», MIT): las herramientas de un MCP conectado. */
|
|
12
|
+
export declare function ArcadeIcon({ className }: {
|
|
13
|
+
className?: string;
|
|
14
|
+
}): import("react").JSX.Element;
|
|
15
|
+
/** Un ícono por tipo de herramienta (los de Ghosty); lo desconocido cae en la garra. */
|
|
9
16
|
export declare const DEFAULT_TOOL_ICONS: Record<string, PilotIcon>;
|
|
10
17
|
export declare function AgentSteps({ tools, live }: {
|
|
11
18
|
tools: ToolEntry[];
|
|
12
19
|
live: boolean;
|
|
13
20
|
}): import("react").JSX.Element;
|
|
14
|
-
/** El detalle de un paso (lista desplegada): rótulo, detalle y ruta. */
|
|
15
21
|
export declare function ToolRow({ tool }: {
|
|
16
22
|
tool: ToolEntry;
|
|
17
23
|
}): import("react").JSX.Element;
|
|
18
24
|
/** La narración del agente como avance: una palomita por lo que ya dijo que hacía. */
|
|
19
|
-
export declare function Narration({ steps
|
|
25
|
+
export declare function Narration({ steps }: {
|
|
20
26
|
steps: string[];
|
|
21
|
-
children?: ReactNode;
|
|
22
27
|
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Sin conexión por este rato, se enseña. */
|
|
2
|
+
export declare const CONNECTING_DELAY_MS = 1200;
|
|
3
|
+
/** Una vez a la vista, se queda al menos esto. */
|
|
4
|
+
export declare const CONNECTING_MIN_MS = 700;
|
|
5
|
+
export interface ConnectingGate {
|
|
6
|
+
/** Desde cuándo está a la vista (null = oculto). */
|
|
7
|
+
shownAt: number | null;
|
|
8
|
+
/** Desde cuándo falta la conexión (null = conectado). */
|
|
9
|
+
waitingSince: number | null;
|
|
10
|
+
}
|
|
11
|
+
export declare const initialGate: (now: number, connected: boolean) => ConnectingGate;
|
|
12
|
+
/** El estado a `now`, y cuándo volver a mirar (null = no hace falta). */
|
|
13
|
+
export declare function stepGate(g: ConnectingGate, connected: boolean, now: number, delay?: number, min?: number): {
|
|
14
|
+
gate: ConnectingGate;
|
|
15
|
+
visible: boolean;
|
|
16
|
+
recheckAt: number | null;
|
|
17
|
+
};
|