@invergent/agent-chat-react 2.6.1 → 2.6.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.
@@ -1,4 +1,4 @@
1
- import { cn } from './chunk-QSC4UIVT.js';
1
+ import { cn } from './chunk-47MF6JUW.js';
2
2
  import { useRef, useState, useMemo, useEffect } from 'react';
3
3
  import { Chart } from 'chart.js/auto';
4
4
  import { useTheme } from 'next-themes';
@@ -149,5 +149,5 @@ function isRecord(value) {
149
149
  }
150
150
 
151
151
  export { ArtifactChart };
152
- //# sourceMappingURL=artifact-chart-X53FKRDZ.js.map
153
- //# sourceMappingURL=artifact-chart-X53FKRDZ.js.map
152
+ //# sourceMappingURL=artifact-chart-62C2XKHA.js.map
153
+ //# sourceMappingURL=artifact-chart-62C2XKHA.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/chat/artifacts/artifact-chart.tsx"],"names":["ChartJS"],"mappings":"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","file":"artifact-chart-X53FKRDZ.js","sourcesContent":["// Copyright (c) 2026, Invergent SA, developed by Flavius Burca\n// SPDX-License-Identifier: AGPL-3.0-only\n//\n// Chart artifact renderer — embeds a Chart.js configuration object.\n// Respects the app's dark/light theme and resizes with the thread column.\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Chart as ChartJS } from \"chart.js/auto\";\nimport type { ChartConfiguration, ChartOptions } from \"chart.js\";\nimport { useTheme } from \"next-themes\";\nimport { cn } from \"../../../lib/utils\";\nimport type { ChartArtifactSpec } from \"../../../types\";\n\nconst DEFAULT_CHART_HEIGHT = 320;\nconst MAX_INLINE_CHART_HEIGHT = 800;\n\nconst LIGHT_THEME = {\n text: \"#444\",\n title: \"#111\",\n grid: \"#e5e7eb\",\n border: \"#d1d5db\",\n};\n\nconst DARK_THEME = {\n text: \"#cbd5e1\",\n title: \"#f1f5f9\",\n grid: \"#374151\",\n border: \"#4b5563\",\n};\n\nexport function ArtifactChart({\n spec,\n fill = false,\n}: {\n spec: ChartArtifactSpec;\n fill?: boolean;\n}) {\n const { resolvedTheme } = useTheme();\n const isDark = resolvedTheme === \"dark\";\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const chartRef = useRef<ChartJS | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const config = useMemo<ChartConfiguration>(() => {\n const base = cloneChartConfig(spec.chart_js ?? {});\n return {\n ...base,\n options: mergeThemeOptions(base.options, base.type, isDark),\n } as ChartConfiguration;\n }, [spec.chart_js, isDark]);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n chartRef.current?.destroy();\n chartRef.current = null;\n setError(null);\n\n try {\n chartRef.current = new ChartJS(canvas, config);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n }\n\n return () => {\n chartRef.current?.destroy();\n chartRef.current = null;\n };\n }, [config]);\n\n return (\n <div className=\"flex flex-col gap-2\">\n <div\n className={cn(\"relative w-full\", fill && \"h-full min-h-80\")}\n style={\n fill\n ? undefined\n : {\n height: DEFAULT_CHART_HEIGHT,\n maxHeight: MAX_INLINE_CHART_HEIGHT,\n }\n }\n >\n <canvas ref={canvasRef} />\n </div>\n {error && (\n <p className=\"text-xs text-destructive\">Chart error: {error}</p>\n )}\n {spec.caption && (\n <p className=\"text-xs text-muted-foreground\">{spec.caption}</p>\n )}\n </div>\n );\n}\n\nfunction cloneChartConfig(\n value: Record<string, unknown>,\n): Record<string, unknown> {\n return JSON.parse(JSON.stringify(value)) as Record<string, unknown>;\n}\n\nfunction mergeThemeOptions(\n options: unknown,\n chartType: unknown,\n isDark: boolean,\n): ChartOptions {\n const theme = isDark ? DARK_THEME : LIGHT_THEME;\n const base = isRecord(options) ? options : {};\n const plugins = isRecord(base.plugins) ? base.plugins : {};\n const legend = isRecord(plugins.legend) ? plugins.legend : {};\n const legendLabels = isRecord(legend.labels) ? legend.labels : {};\n const title = isRecord(plugins.title) ? plugins.title : {};\n const scales = isRecord(base.scales) ? base.scales : {};\n\n return {\n responsive: true,\n maintainAspectRatio: false,\n color: theme.text,\n ...base,\n plugins: {\n ...plugins,\n legend: {\n ...legend,\n labels: {\n color: theme.text,\n ...legendLabels,\n },\n },\n title: {\n color: theme.title,\n ...title,\n },\n },\n scales: mergeScales(scales, chartType, theme),\n } as ChartOptions;\n}\n\nfunction mergeScales(\n scales: Record<string, unknown>,\n chartType: unknown,\n theme: typeof LIGHT_THEME,\n): Record<string, unknown> {\n const names = new Set([...defaultScaleNames(chartType), ...Object.keys(scales)]);\n const merged: Record<string, unknown> = {};\n\n for (const name of names) {\n const scale = isRecord(scales[name]) ? scales[name] : {};\n const ticks = isRecord(scale.ticks) ? scale.ticks : {};\n const grid = isRecord(scale.grid) ? scale.grid : {};\n const title = isRecord(scale.title) ? scale.title : {};\n merged[name] = {\n ...scale,\n ticks: {\n color: theme.text,\n ...ticks,\n },\n grid: {\n color: theme.grid,\n ...grid,\n },\n border: {\n color: theme.border,\n ...(isRecord(scale.border) ? scale.border : {}),\n },\n title: {\n color: theme.title,\n ...title,\n },\n };\n }\n\n return merged;\n}\n\nfunction defaultScaleNames(chartType: unknown): string[] {\n if (chartType === \"bar\" || chartType === \"line\" || chartType === \"scatter\") {\n return [\"x\", \"y\"];\n }\n if (chartType === \"bubble\") {\n return [\"x\", \"y\"];\n }\n if (chartType === \"radar\" || chartType === \"polarArea\") {\n return [\"r\"];\n }\n return [];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
1
+ {"version":3,"sources":["../src/components/chat/artifacts/artifact-chart.tsx"],"names":["ChartJS"],"mappings":"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","file":"artifact-chart-62C2XKHA.js","sourcesContent":["// Copyright (c) 2026, Invergent SA, developed by Flavius Burca\n// SPDX-License-Identifier: AGPL-3.0-only\n//\n// Chart artifact renderer — embeds a Chart.js configuration object.\n// Respects the app's dark/light theme and resizes with the thread column.\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Chart as ChartJS } from \"chart.js/auto\";\nimport type { ChartConfiguration, ChartOptions } from \"chart.js\";\nimport { useTheme } from \"next-themes\";\nimport { cn } from \"../../../lib/utils\";\nimport type { ChartArtifactSpec } from \"../../../types\";\n\nconst DEFAULT_CHART_HEIGHT = 320;\nconst MAX_INLINE_CHART_HEIGHT = 800;\n\nconst LIGHT_THEME = {\n text: \"#444\",\n title: \"#111\",\n grid: \"#e5e7eb\",\n border: \"#d1d5db\",\n};\n\nconst DARK_THEME = {\n text: \"#cbd5e1\",\n title: \"#f1f5f9\",\n grid: \"#374151\",\n border: \"#4b5563\",\n};\n\nexport function ArtifactChart({\n spec,\n fill = false,\n}: {\n spec: ChartArtifactSpec;\n fill?: boolean;\n}) {\n const { resolvedTheme } = useTheme();\n const isDark = resolvedTheme === \"dark\";\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const chartRef = useRef<ChartJS | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const config = useMemo<ChartConfiguration>(() => {\n const base = cloneChartConfig(spec.chart_js ?? {});\n return {\n ...base,\n options: mergeThemeOptions(base.options, base.type, isDark),\n } as ChartConfiguration;\n }, [spec.chart_js, isDark]);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n chartRef.current?.destroy();\n chartRef.current = null;\n setError(null);\n\n try {\n chartRef.current = new ChartJS(canvas, config);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n }\n\n return () => {\n chartRef.current?.destroy();\n chartRef.current = null;\n };\n }, [config]);\n\n return (\n <div className=\"flex flex-col gap-2\">\n <div\n className={cn(\"relative w-full\", fill && \"h-full min-h-80\")}\n style={\n fill\n ? undefined\n : {\n height: DEFAULT_CHART_HEIGHT,\n maxHeight: MAX_INLINE_CHART_HEIGHT,\n }\n }\n >\n <canvas ref={canvasRef} />\n </div>\n {error && (\n <p className=\"text-xs text-destructive\">Chart error: {error}</p>\n )}\n {spec.caption && (\n <p className=\"text-xs text-muted-foreground\">{spec.caption}</p>\n )}\n </div>\n );\n}\n\nfunction cloneChartConfig(\n value: Record<string, unknown>,\n): Record<string, unknown> {\n return JSON.parse(JSON.stringify(value)) as Record<string, unknown>;\n}\n\nfunction mergeThemeOptions(\n options: unknown,\n chartType: unknown,\n isDark: boolean,\n): ChartOptions {\n const theme = isDark ? DARK_THEME : LIGHT_THEME;\n const base = isRecord(options) ? options : {};\n const plugins = isRecord(base.plugins) ? base.plugins : {};\n const legend = isRecord(plugins.legend) ? plugins.legend : {};\n const legendLabels = isRecord(legend.labels) ? legend.labels : {};\n const title = isRecord(plugins.title) ? plugins.title : {};\n const scales = isRecord(base.scales) ? base.scales : {};\n\n return {\n responsive: true,\n maintainAspectRatio: false,\n color: theme.text,\n ...base,\n plugins: {\n ...plugins,\n legend: {\n ...legend,\n labels: {\n color: theme.text,\n ...legendLabels,\n },\n },\n title: {\n color: theme.title,\n ...title,\n },\n },\n scales: mergeScales(scales, chartType, theme),\n } as ChartOptions;\n}\n\nfunction mergeScales(\n scales: Record<string, unknown>,\n chartType: unknown,\n theme: typeof LIGHT_THEME,\n): Record<string, unknown> {\n const names = new Set([...defaultScaleNames(chartType), ...Object.keys(scales)]);\n const merged: Record<string, unknown> = {};\n\n for (const name of names) {\n const scale = isRecord(scales[name]) ? scales[name] : {};\n const ticks = isRecord(scale.ticks) ? scale.ticks : {};\n const grid = isRecord(scale.grid) ? scale.grid : {};\n const title = isRecord(scale.title) ? scale.title : {};\n merged[name] = {\n ...scale,\n ticks: {\n color: theme.text,\n ...ticks,\n },\n grid: {\n color: theme.grid,\n ...grid,\n },\n border: {\n color: theme.border,\n ...(isRecord(scale.border) ? scale.border : {}),\n },\n title: {\n color: theme.title,\n ...title,\n },\n };\n }\n\n return merged;\n}\n\nfunction defaultScaleNames(chartType: unknown): string[] {\n if (chartType === \"bar\" || chartType === \"line\" || chartType === \"scatter\") {\n return [\"x\", \"y\"];\n }\n if (chartType === \"bubble\") {\n return [\"x\", \"y\"];\n }\n if (chartType === \"radar\" || chartType === \"polarArea\") {\n return [\"r\"];\n }\n return [];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import { clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+
4
+ var __defProp = Object.defineProperty;
5
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+
11
+ export { __publicField, cn };
12
+ //# sourceMappingURL=chunk-47MF6JUW.js.map
13
+ //# sourceMappingURL=chunk-47MF6JUW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/utils.ts"],"names":[],"mappings":";;;;;;AAGO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B","file":"chunk-47MF6JUW.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"]}
package/dist/index.cjs CHANGED
@@ -32,6 +32,7 @@ var AnsiImport__default = /*#__PURE__*/_interopDefault(AnsiImport);
32
32
 
33
33
  var __defProp = Object.defineProperty;
34
34
  var __getOwnPropNames = Object.getOwnPropertyNames;
35
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
35
36
  var __esm = (fn, res) => function __init() {
36
37
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
37
38
  };
@@ -39,6 +40,7 @@ var __export = (target, all) => {
39
40
  for (var name in all)
40
41
  __defProp(target, name, { get: all[name], enumerable: true });
41
42
  };
43
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
42
44
  function cn(...inputs) {
43
45
  return tailwindMerge.twMerge(clsx.clsx(inputs));
44
46
  }
@@ -12612,6 +12614,160 @@ function delegateTaskTargets(rawArgs) {
12612
12614
  }
12613
12615
  return out;
12614
12616
  }
12617
+
12618
+ // src/runtime/fetch-sse-stream.ts
12619
+ var STREAM_STALL_THRESHOLD_MS = 45e3;
12620
+ var STREAM_STALL_CHECK_INTERVAL_MS = 5e3;
12621
+ var StreamStallWatchdog = class {
12622
+ constructor(onStall) {
12623
+ __publicField(this, "lastByteAt", Date.now());
12624
+ __publicField(this, "timer", null);
12625
+ __publicField(this, "onStall");
12626
+ __publicField(this, "check", () => {
12627
+ if (Date.now() - this.lastByteAt > STREAM_STALL_THRESHOLD_MS) {
12628
+ this.onStall();
12629
+ }
12630
+ });
12631
+ this.onStall = onStall;
12632
+ }
12633
+ start() {
12634
+ this.lastByteAt = Date.now();
12635
+ this.timer = setInterval(this.check, STREAM_STALL_CHECK_INTERVAL_MS);
12636
+ if (typeof document !== "undefined") {
12637
+ document.addEventListener("visibilitychange", this.check);
12638
+ }
12639
+ if (typeof window !== "undefined") {
12640
+ window.addEventListener("online", this.check);
12641
+ }
12642
+ }
12643
+ touch() {
12644
+ this.lastByteAt = Date.now();
12645
+ }
12646
+ stop() {
12647
+ if (this.timer !== null) {
12648
+ clearInterval(this.timer);
12649
+ this.timer = null;
12650
+ }
12651
+ if (typeof document !== "undefined") {
12652
+ document.removeEventListener("visibilitychange", this.check);
12653
+ }
12654
+ if (typeof window !== "undefined") {
12655
+ window.removeEventListener("online", this.check);
12656
+ }
12657
+ }
12658
+ };
12659
+ var FetchSseEventStream = class {
12660
+ constructor(url, options = {}) {
12661
+ __publicField(this, "abort", new AbortController());
12662
+ __publicField(this, "decoder", new TextDecoder());
12663
+ __publicField(this, "listeners", /* @__PURE__ */ new Map());
12664
+ __publicField(this, "buffer", "");
12665
+ __publicField(this, "eventType", "");
12666
+ __publicField(this, "eventId", "");
12667
+ __publicField(this, "dataLines", []);
12668
+ __publicField(this, "url");
12669
+ __publicField(this, "fetchFn");
12670
+ __publicField(this, "watchdog", new StreamStallWatchdog(() => this.fail()));
12671
+ __publicField(this, "errored", false);
12672
+ __publicField(this, "onerror", null);
12673
+ this.url = url;
12674
+ this.fetchFn = options.fetchFn ?? fetch;
12675
+ queueMicrotask(() => void this.start());
12676
+ }
12677
+ addEventListener(type, listener) {
12678
+ const listeners = this.listeners.get(type) ?? /* @__PURE__ */ new Set();
12679
+ listeners.add(listener);
12680
+ this.listeners.set(type, listeners);
12681
+ }
12682
+ close() {
12683
+ this.watchdog.stop();
12684
+ this.abort.abort();
12685
+ }
12686
+ fail() {
12687
+ if (this.errored) return;
12688
+ this.errored = true;
12689
+ this.watchdog.stop();
12690
+ this.onerror?.();
12691
+ }
12692
+ async start() {
12693
+ try {
12694
+ const response = await this.fetchFn(this.url, {
12695
+ signal: this.abort.signal,
12696
+ headers: { Accept: "text/event-stream" }
12697
+ });
12698
+ if (!response.ok || !response.body) {
12699
+ this.fail();
12700
+ return;
12701
+ }
12702
+ this.watchdog.start();
12703
+ const reader = response.body.getReader();
12704
+ while (!this.abort.signal.aborted) {
12705
+ const { done, value } = await reader.read();
12706
+ if (done) break;
12707
+ this.watchdog.touch();
12708
+ this.feed(this.decoder.decode(value, { stream: true }));
12709
+ }
12710
+ this.feed(this.decoder.decode());
12711
+ this.flushEvent();
12712
+ if (!this.abort.signal.aborted) {
12713
+ this.fail();
12714
+ }
12715
+ } catch (error) {
12716
+ if (!this.abort.signal.aborted) {
12717
+ console.error("SSE stream failed:", error);
12718
+ this.fail();
12719
+ }
12720
+ } finally {
12721
+ this.watchdog.stop();
12722
+ }
12723
+ }
12724
+ feed(chunk) {
12725
+ this.buffer += chunk;
12726
+ for (; ; ) {
12727
+ const newlineIndex = this.buffer.indexOf("\n");
12728
+ if (newlineIndex < 0) return;
12729
+ const line = this.buffer.slice(0, newlineIndex).replace(/\r$/, "");
12730
+ this.buffer = this.buffer.slice(newlineIndex + 1);
12731
+ this.processLine(line);
12732
+ }
12733
+ }
12734
+ processLine(line) {
12735
+ if (line === "") {
12736
+ this.flushEvent();
12737
+ return;
12738
+ }
12739
+ if (line.startsWith(":")) return;
12740
+ const separator = line.indexOf(":");
12741
+ const field = separator >= 0 ? line.slice(0, separator) : line;
12742
+ const rawValue = separator >= 0 ? line.slice(separator + 1) : "";
12743
+ const value = rawValue.startsWith(" ") ? rawValue.slice(1) : rawValue;
12744
+ if (field === "event") {
12745
+ this.eventType = value;
12746
+ } else if (field === "id") {
12747
+ this.eventId = value;
12748
+ } else if (field === "data") {
12749
+ this.dataLines.push(value);
12750
+ }
12751
+ }
12752
+ flushEvent() {
12753
+ if (!this.eventType || this.dataLines.length === 0) {
12754
+ this.dataLines = [];
12755
+ return;
12756
+ }
12757
+ const listeners = this.listeners.get(this.eventType);
12758
+ const event = {
12759
+ data: this.dataLines.join("\n"),
12760
+ lastEventId: this.eventId
12761
+ };
12762
+ if (listeners) {
12763
+ for (const listener of listeners) {
12764
+ listener(event);
12765
+ }
12766
+ }
12767
+ this.eventType = "";
12768
+ this.dataLines = [];
12769
+ }
12770
+ };
12615
12771
  var POLL_INTERVAL_MS = 2e3;
12616
12772
  var POLL_TIMEOUT_MS = 18e4;
12617
12773
  var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
@@ -16001,6 +16157,7 @@ exports.AgentChatAdapterProvider = AgentChatAdapterProvider;
16001
16157
  exports.CitationText = CitationText;
16002
16158
  exports.CodingAgentsPanel = CodingAgentsPanel;
16003
16159
  exports.ComposioConnectCard = ComposioConnectCard;
16160
+ exports.FetchSseEventStream = FetchSseEventStream;
16004
16161
  exports.InboxPanel = InboxPanel;
16005
16162
  exports.IntegrationsBand = IntegrationsBand;
16006
16163
  exports.IntegrationsPage = IntegrationsPage;