@campfire-interactive/ai-chat 0.2.2 → 0.3.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.
Files changed (2) hide show
  1. package/dist/host/index.js +50 -3
  2. package/package.json +1 -1
@@ -61,6 +61,25 @@ function applyEvent(ex, event) {
61
61
  return { ...ex, status: "error", error: event.message };
62
62
  }
63
63
  }
64
+ function restoreCards(cards) {
65
+ return cards.map((card) => ({
66
+ ...card,
67
+ exchanges: card.exchanges.map((ex) => ({
68
+ ...ex,
69
+ ...ex.status === "streaming" ? { status: "error", error: "The page reloaded before this answer finished." } : {},
70
+ parts: ex.parts.map(
71
+ (p) => p.kind === "write" && p.item.state === "confirming" ? {
72
+ ...p,
73
+ item: {
74
+ ...p.item,
75
+ state: "failed",
76
+ error: "The page reloaded while this was being made. Check the changes list before asking again."
77
+ }
78
+ } : p
79
+ )
80
+ }))
81
+ }));
82
+ }
64
83
  function discardPending(cards) {
65
84
  let changed = false;
66
85
  const next = cards.map((card) => {
@@ -212,6 +231,17 @@ function writeSession(key, value) {
212
231
  } catch {
213
232
  }
214
233
  }
234
+ function readThread(key) {
235
+ const raw = readSession(key);
236
+ if (!raw) return null;
237
+ try {
238
+ const parsed = JSON.parse(raw);
239
+ if (typeof parsed?.sessionId !== "string" || !Array.isArray(parsed.cards)) return null;
240
+ return { sessionId: parsed.sessionId, cards: restoreCards(parsed.cards), summaries: parsed.summaries ?? {} };
241
+ } catch {
242
+ return null;
243
+ }
244
+ }
215
245
  function AiChatProvider(props) {
216
246
  return /* @__PURE__ */ jsx(ChatProvider, { ...props, enabled: Boolean(props.hubUrl || props.client) });
217
247
  }
@@ -270,8 +300,10 @@ function ChatProvider({
270
300
  const [expanded, setExpandedState] = useState(() => readStored(expandedKey) === "1");
271
301
  useEffect(() => writeStored(expandedKey, expanded ? "1" : "0"), [expandedKey, expanded]);
272
302
  const setExpanded = useCallback((next) => setExpandedState(next), []);
273
- const [sessionId, setSessionId] = useState(newId);
274
- const [cards, setCards] = useState([]);
303
+ const threadKey = `cfi.ai-chat.${app}.thread`;
304
+ const [restored] = useState(() => readThread(threadKey));
305
+ const [sessionId, setSessionId] = useState(() => restored?.sessionId ?? newId());
306
+ const [cards, setCards] = useState(() => restored?.cards ?? []);
275
307
  const [busy, setBusy] = useState(false);
276
308
  const [draft, setDraft] = useState("");
277
309
  const files = useRef(/* @__PURE__ */ new Map());
@@ -279,7 +311,22 @@ function ChatProvider({
279
311
  const [staged, setStaged] = useState([]);
280
312
  const [attached, setAttached] = useState([]);
281
313
  const [changes, setChanges] = useState({ items: [], loading: false, loaded: false });
282
- const [summaries, setSummaries] = useState({});
314
+ const [summaries, setSummaries] = useState(() => restored?.summaries ?? {});
315
+ const saveThread = useCallback(
316
+ (thread) => writeSession(threadKey, thread.cards.length ? JSON.stringify(thread) : null),
317
+ [threadKey]
318
+ );
319
+ const threadRef = useRef({ sessionId, cards, summaries });
320
+ threadRef.current = { sessionId, cards, summaries };
321
+ useEffect(() => {
322
+ if (!busy) saveThread(threadRef.current);
323
+ }, [busy, sessionId, cards, summaries, saveThread]);
324
+ useEffect(() => {
325
+ if (typeof window === "undefined") return void 0;
326
+ const onHide = () => saveThread(threadRef.current);
327
+ window.addEventListener("pagehide", onHide);
328
+ return () => window.removeEventListener("pagehide", onHide);
329
+ }, [saveThread]);
283
330
  const cardsRef = useRef(cards);
284
331
  cardsRef.current = cards;
285
332
  const pageRef = useRef(pageContext);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@campfire-interactive/ai-chat",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "The platform AI chat panel for Campfire Suite apps: a docked, page-aware assistant opened from the header, answering from every app the user is granted, with typed answer blocks and confirm-to-write cards.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",