ghostykit 0.8.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -95,6 +95,7 @@ const ref = useRef<PilotoHandle>(null);
95
95
  welcome="How can I help with your crons?"
96
96
  suggestions={["Why did the monitor fail?"]}
97
97
  draft={{ text: "Why did the monitor fail?", key: row.id }} // prefilled + focused, not sent
98
+ background={running.length ? { label: "2 helpers working", since: oldestStart } : null} // work after the run closed
98
99
  threadId={conversationId} // reopen a stored thread
99
100
  context={() => ({ screen: "crons", selected })} // AG-UI `context`, every run
100
101
  onTurnDone={({ text }) => refreshMyData()}
@@ -53,6 +53,15 @@ export interface PilotoProps extends UsePilotOptions {
53
53
  text: string;
54
54
  key?: string | number;
55
55
  } | null;
56
+ /**
57
+ * Trabajo que sigue FUERA del run (ayudantes en segundo plano, una tarea larga): con el run ya
58
+ * cerrado, el hilo enseña `label` y cuenta desde `since` (ms) para que no parezca terminado.
59
+ * Con un run vivo manda su propia espera. `null` = nada pendiente.
60
+ */
61
+ background?: {
62
+ label: string;
63
+ since: number;
64
+ } | null;
56
65
  /** Referencias controladas (si no, Piloto las guarda; agrégalas con `ref.addReference`). */
57
66
  references?: Reference[];
58
67
  onReferencesChange?: (refs: Reference[]) => void;
@@ -1,6 +1,8 @@
1
1
  /** Los tres puntitos de «escribiendo» (color y animación en CSS: `gc-typing`). */
2
2
  export declare function TypingDots(): import("react").JSX.Element;
3
- export declare function WaitLabel({ since, showDuration, step, }: {
3
+ export declare function WaitLabel({ since, showDuration, step, text, }: {
4
+ /** Frase fija que gana a las del turno (p. ej. «2 ayudantes trabajando» con el run ya cerrado). */
5
+ text?: string | null;
4
6
  /** El paso con nombre en curso (`STEP_STARTED`): si `strings.steps` lo nombra, esa es la frase. */
5
7
  step?: string | null;
6
8
  /** Desde que se MANDÓ el mensaje (no desde que se montó la etiqueta). */
@@ -828,7 +828,8 @@ function TypingDots() {
828
828
  function WaitLabel({
829
829
  since,
830
830
  showDuration = true,
831
- step
831
+ step,
832
+ text
832
833
  }) {
833
834
  const { strings: t } = usePiloto();
834
835
  const [mounted] = useState6(() => Date.now());
@@ -840,7 +841,7 @@ function WaitLabel({
840
841
  const seconds = Math.max(0, Math.floor((now - (since || mounted)) / 1e3));
841
842
  const phrases = t.thinkingPhrases;
842
843
  const stepText = step ? t.steps?.[step] : void 0;
843
- const what = stepText ? stepText : phrases?.length ? seconds >= STILL_WORKING_S ? t.stillWorking : phrases[Math.floor(seconds / 4) % phrases.length] : t.howItGoes(seconds);
844
+ const what = text ? text : stepText ? stepText : phrases?.length ? seconds >= STILL_WORKING_S ? t.stillWorking : phrases[Math.floor(seconds / 4) % phrases.length] : t.howItGoes(seconds);
844
845
  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
846
  /* @__PURE__ */ jsx7(AnimatePresence2, { mode: "wait", initial: false, children: /* @__PURE__ */ jsx7(
846
847
  motion2.span,
@@ -957,11 +958,13 @@ function usePilot(transport, opts = {}) {
957
958
  if (!steering && (input.messages.length || input.resume?.length || input.forwardedProps?.continueRun)) liveRun.current = input.runId;
958
959
  optsRef.current.onSend?.(input);
959
960
  let ended = false;
961
+ let gotEvent = false;
960
962
  try {
961
963
  await t.run(
962
964
  input,
963
965
  (e) => {
964
966
  if (c.signal.aborted) return;
967
+ gotEvent = true;
965
968
  optsRef.current.onEvent?.(e);
966
969
  for (const fn of listeners.current) fn(e);
967
970
  if (e.type === "RUN_FINISHED" || e.type === "RUN_ERROR") {
@@ -974,6 +977,11 @@ function usePilot(transport, opts = {}) {
974
977
  );
975
978
  } catch (err) {
976
979
  if (c.signal.aborted) return;
980
+ if (gotEvent && !(err instanceof PilotHttpError)) {
981
+ if (!reopening) return runNow({ messages: [] }, true);
982
+ commit(sendFailed(ref.current, "Se cort\xF3 la conexi\xF3n con el agente."));
983
+ return;
984
+ }
977
985
  const code = err instanceof PilotHttpError ? err.code : void 0;
978
986
  if (code === "run_not_live" && steering && userMsg) {
979
987
  const { text } = fromUserMessage(userMsg.content);
@@ -1658,6 +1666,10 @@ var Piloto = forwardRef(function Piloto2(props, handle) {
1658
1666
  /* @__PURE__ */ jsx8(TypingDots, {}),
1659
1667
  /* @__PURE__ */ jsx8(WaitLabel, { since: state.turnStartedAt, step: state.step, showDuration: features.duration !== false })
1660
1668
  ] })),
1669
+ !busy && props.background && /* @__PURE__ */ jsxs6("div", { "data-background": true, className: "flex flex-col gap-1.5", children: [
1670
+ /* @__PURE__ */ jsx8(TypingDots, {}),
1671
+ /* @__PURE__ */ jsx8(WaitLabel, { text: props.background.label, since: props.background.since, showDuration: features.duration !== false })
1672
+ ] }),
1661
1673
  notice && /* @__PURE__ */ jsx8("p", { className: "text-sm text-text-tertiary", children: notice }),
1662
1674
  error && /* @__PURE__ */ jsx8("p", { className: "text-sm text-text-danger", children: error })
1663
1675
  ] }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ghostykit",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Ghosty Autopilot — the autopilot chat for your React app, on AG-UI: works with LangGraph, Mastra, CrewAI or any AG-UI agent. Streaming text, agent steps, human approval cards (interrupt/resume), attachments and voice.",
5
5
  "type": "module",
6
6
  "main": "./dist/core/index.js",