@arcote.tech/arc-chat 0.7.18 → 0.7.19

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@arcote.tech/arc-chat",
3
3
  "type": "module",
4
- "version": "0.7.18",
4
+ "version": "0.7.19",
5
5
  "private": false,
6
6
  "description": "Chat module with AI integration for Arc framework",
7
7
  "main": "./src/index.ts",
@@ -10,12 +10,12 @@
10
10
  "type-check": "tsc --noEmit"
11
11
  },
12
12
  "peerDependencies": {
13
- "@arcote.tech/arc": "^0.7.18",
14
- "@arcote.tech/arc-ai": "^0.7.18",
15
- "@arcote.tech/arc-ai-voice": "^0.7.18",
16
- "@arcote.tech/arc-auth": "^0.7.18",
17
- "@arcote.tech/arc-ds": "^0.7.18",
18
- "@arcote.tech/platform": "^0.7.18",
13
+ "@arcote.tech/arc": "^0.7.19",
14
+ "@arcote.tech/arc-ai": "^0.7.19",
15
+ "@arcote.tech/arc-ai-voice": "^0.7.19",
16
+ "@arcote.tech/arc-auth": "^0.7.19",
17
+ "@arcote.tech/arc-ds": "^0.7.19",
18
+ "@arcote.tech/platform": "^0.7.19",
19
19
  "lucide-react": ">=0.400.0",
20
20
  "react": ">=18.0.0",
21
21
  "typescript": "^5.0.0"
@@ -340,6 +340,47 @@ export function createChatComponent(
340
340
  return () => clearTimeout(timer);
341
341
  }, [isStreaming, activeGeneratingMessageId, scopeId]);
342
342
 
343
+ // ─── Backstop: merge interactive-tool answers regardless of isStreaming ──
344
+ // Answering an interactive tool (askQuestions) creates a `tool_result` row
345
+ // AND starts a new assistant turn — so `isStreaming` flips back to true and
346
+ // the global rebuild guard freezes the whole timeline. Without this, the
347
+ // answered question stays in input-view ("Odpowiedz na pytania" + the
348
+ // questions) instead of the answer-view, until that next turn ends — and on
349
+ // prod its SSE `done` is often lost (the turn finalizes after the DB
350
+ // projection that nulls `activeGeneratingMessageId` aborts the stream), so
351
+ // it never catches up. This flips any `calling` tool block to answer-view
352
+ // the moment its `tool_result` lands in the DB, bypassing the guard.
353
+ useEffect(() => {
354
+ if (!historyData) return;
355
+ const resultMap = new Map<string, { content: string; isError?: boolean }>();
356
+ for (const msg of historyData) {
357
+ if (msg.role === "tool_result" && msg.toolCallId) {
358
+ resultMap.set(msg.toolCallId, {
359
+ content: msg.content,
360
+ isError: msg.isError,
361
+ });
362
+ }
363
+ }
364
+ if (resultMap.size === 0) return;
365
+ setTimeline((prev) => {
366
+ let changed = false;
367
+ const next = prev.map((t) => {
368
+ if (t.type !== "tool" || !t.calling) return t;
369
+ const r = resultMap.get(t.toolCallId);
370
+ if (!r) return t;
371
+ changed = true;
372
+ return {
373
+ ...t,
374
+ calling: false,
375
+ status: (r.isError ? "error" : "complete") as ToolStatus,
376
+ result: tryParseJson(r.content),
377
+ error: r.isError ? r.content : undefined,
378
+ };
379
+ });
380
+ return changed ? next : prev;
381
+ });
382
+ }, [historySig]);
383
+
343
384
  // ─── SSE event processing ───────────────────────────────────
344
385
  const processEventRef = useRef<((event: ChatStreamEvent) => void) | null>(null);
345
386
  const processEvent = useCallback(