@audashai/cli 1.0.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 (49) hide show
  1. package/README.md +57 -0
  2. package/bin/audashai.js +3 -0
  3. package/dist/commands/add.d.ts +1 -0
  4. package/dist/commands/add.js +73 -0
  5. package/dist/commands/init.d.ts +1 -0
  6. package/dist/commands/init.js +62 -0
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.js +16 -0
  9. package/dist/templates/components/AudashAIChatBot.d.ts +8 -0
  10. package/dist/templates/components/AudashAIChatBot.js +14 -0
  11. package/dist/templates/components/AudashAIInput.d.ts +1 -0
  12. package/dist/templates/components/AudashAIInput.js +114 -0
  13. package/dist/templates/components/AudashAIOutput.d.ts +1 -0
  14. package/dist/templates/components/AudashAIOutput.js +66 -0
  15. package/dist/templates/components/BarChart.d.ts +2 -0
  16. package/dist/templates/components/BarChart.js +41 -0
  17. package/dist/templates/components/ErrorDisplay.d.ts +4 -0
  18. package/dist/templates/components/ErrorDisplay.js +61 -0
  19. package/dist/templates/components/LineChart.d.ts +2 -0
  20. package/dist/templates/components/LineChart.js +41 -0
  21. package/dist/templates/context/AudashAIContext.d.ts +1 -0
  22. package/dist/templates/context/AudashAIContext.js +5 -0
  23. package/dist/templates/context/AudashAIProvider.d.ts +7 -0
  24. package/dist/templates/context/AudashAIProvider.js +50 -0
  25. package/dist/templates/hooks/useAudashAI.d.ts +1 -0
  26. package/dist/templates/hooks/useAudashAI.js +13 -0
  27. package/dist/templates/index.d.ts +9 -0
  28. package/dist/templates/index.js +38 -0
  29. package/dist/templates/types/index.d.ts +39 -0
  30. package/dist/templates/types/index.js +2 -0
  31. package/dist/templates/utils/api.d.ts +3 -0
  32. package/dist/templates/utils/api.js +52 -0
  33. package/dist/utils/config.d.ts +6 -0
  34. package/dist/utils/config.js +15 -0
  35. package/dist/utils/copy-files.d.ts +1 -0
  36. package/dist/utils/copy-files.js +14 -0
  37. package/package.json +42 -0
  38. package/templates/components/AudashAIChatBot.tsx +34 -0
  39. package/templates/components/AudashAIInput.tsx +181 -0
  40. package/templates/components/AudashAIOutput.tsx +90 -0
  41. package/templates/components/BarChart.tsx +113 -0
  42. package/templates/components/ErrorDisplay.tsx +87 -0
  43. package/templates/components/LineChart.tsx +105 -0
  44. package/templates/context/AudashAIContext.tsx +18 -0
  45. package/templates/context/AudashAIProvider.tsx +60 -0
  46. package/templates/hooks/useAudashAI.ts +10 -0
  47. package/templates/index.tsx +12 -0
  48. package/templates/types/index.ts +44 -0
  49. package/templates/utils/api.ts +57 -0
@@ -0,0 +1,113 @@
1
+ import type { ChartProps } from '../types';
2
+ import { Bar } from 'react-chartjs-2';
3
+ import {
4
+ Chart as ChartJS,
5
+ CategoryScale,
6
+ LinearScale,
7
+ PointElement,
8
+ LineElement,
9
+ BarElement,
10
+ Title,
11
+ Tooltip,
12
+ Legend,
13
+ Filler,
14
+ type ChartOptions,
15
+ } from 'chart.js';
16
+
17
+ ChartJS.register(
18
+ CategoryScale,
19
+ LinearScale,
20
+ PointElement,
21
+ LineElement,
22
+ BarElement,
23
+ Title,
24
+ Tooltip,
25
+ Legend,
26
+ Filler
27
+ );
28
+
29
+ export const BarChart: React.FC<ChartProps> = ({ labels, datasets }) => {
30
+ const options: ChartOptions<'bar'> = {
31
+ responsive: true,
32
+ maintainAspectRatio: false,
33
+ plugins: {
34
+ legend: {
35
+ position: 'top',
36
+ align: 'end',
37
+ labels: {
38
+ boxWidth: 10,
39
+ usePointStyle: true,
40
+ pointStyle: 'circle',
41
+ font: { family: "'Inter', sans-serif", size: 11 },
42
+ color: '#64748b',
43
+ },
44
+ },
45
+ title: {
46
+ display: false,
47
+ },
48
+ tooltip: {
49
+ backgroundColor: 'rgba(255, 255, 255, 0.95)',
50
+ titleColor: '#0f172a',
51
+ bodyColor: '#334155',
52
+ borderColor: '#e2e8f0',
53
+ borderWidth: 1,
54
+ padding: 10,
55
+ displayColors: true,
56
+ boxPadding: 4,
57
+ cornerRadius: 8,
58
+ titleFont: { family: "'Inter', sans-serif", weight: 'bold' },
59
+ bodyFont: { family: "'Inter', sans-serif" },
60
+ },
61
+ },
62
+ scales: {
63
+ x: {
64
+ grid: {
65
+ display: false,
66
+ },
67
+ ticks: {
68
+ color: '#94a3b8',
69
+ font: { family: "'Inter', sans-serif", size: 11 },
70
+ },
71
+ },
72
+ y: {
73
+ beginAtZero: true,
74
+ border: { dash: [4, 4] },
75
+ grid: {
76
+ color: '#f1f5f9',
77
+ },
78
+ ticks: {
79
+ padding: 10,
80
+ color: '#94a3b8',
81
+ font: { family: "'Inter', sans-serif", size: 11 },
82
+ },
83
+ },
84
+ },
85
+ layout: {
86
+ padding: 10,
87
+ },
88
+ };
89
+
90
+ const barData = {
91
+ labels: labels,
92
+ datasets: datasets.map((dataset, index) => ({
93
+ label: dataset.label,
94
+ data: dataset.data,
95
+ backgroundColor: index === 0 ? '#6366f1' : '#a5b4fc',
96
+ hoverBackgroundColor: '#4f46e5',
97
+ borderRadius: 4,
98
+ barPercentage: 0.6,
99
+ categoryPercentage: 0.8,
100
+ })),
101
+ };
102
+
103
+ return (
104
+ <div className="w-full h-full relative">
105
+ <h3 className="text-xs font-bold text-slate-500 uppercase tracking-wide mb-2 absolute top-0 left-0">
106
+ Data Visualization
107
+ </h3>
108
+ <div className="pt-6 h-full w-full">
109
+ <Bar options={options} data={barData} />
110
+ </div>
111
+ </div>
112
+ );
113
+ };
@@ -0,0 +1,87 @@
1
+ import type { ErrorInfo } from '../types';
2
+
3
+ export const ErrorDisplay: React.FC<{ errorInfo: ErrorInfo }> = ({ errorInfo }) => {
4
+ const isWarning =
5
+ errorInfo.error_type === 'data_not_found' || errorInfo.error_type === 'data_not_available';
6
+
7
+ return (
8
+ <div
9
+ className={`
10
+ w-full max-w-lg p-5 rounded-xl border flex gap-4
11
+ ${isWarning ? 'bg-amber-50/50 border-amber-200' : 'bg-red-50/50 border-red-200'}
12
+ `}
13
+ >
14
+ <div className="flex-shrink-0 pt-1">
15
+ {isWarning ? (
16
+ <svg
17
+ className="w-6 h-6 text-amber-600"
18
+ fill="none"
19
+ viewBox="0 0 24 24"
20
+ stroke="currentColor"
21
+ >
22
+ <path
23
+ strokeLinecap="round"
24
+ strokeLinejoin="round"
25
+ strokeWidth={2}
26
+ d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
27
+ />
28
+ </svg>
29
+ ) : (
30
+ <svg
31
+ className="w-6 h-6 text-red-600"
32
+ fill="none"
33
+ viewBox="0 0 24 24"
34
+ stroke="currentColor"
35
+ >
36
+ <path
37
+ strokeLinecap="round"
38
+ strokeLinejoin="round"
39
+ strokeWidth={2}
40
+ d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
41
+ />
42
+ </svg>
43
+ )}
44
+ </div>
45
+
46
+ <div className="flex-1 space-y-2">
47
+ <h3 className={`font-semibold text-sm ${isWarning ? 'text-amber-800' : 'text-red-800'}`}>
48
+ {errorInfo.message}
49
+ </h3>
50
+
51
+ {errorInfo.reason && (
52
+ <p className={`text-xs ${isWarning ? 'text-amber-700' : 'text-red-700'}`}>
53
+ {errorInfo.reason}
54
+ </p>
55
+ )}
56
+
57
+ {(errorInfo.suggestion || errorInfo.available_data_summary) && (
58
+ <div
59
+ className={`mt-3 pt-3 border-t ${
60
+ isWarning ? 'border-amber-200/50' : 'border-red-200/50'
61
+ }`}
62
+ >
63
+ {errorInfo.suggestion && (
64
+ <div className="text-xs space-y-1 mb-2">
65
+ <span className="font-semibold opacity-75 uppercase tracking-wider text-[10px]">
66
+ Saran:
67
+ </span>
68
+ <p className="opacity-90">{errorInfo.suggestion}</p>
69
+ </div>
70
+ )}
71
+
72
+ {errorInfo.available_data_summary && (
73
+ <div className="text-xs space-y-1">
74
+ <span className="font-semibold opacity-75 uppercase tracking-wider text-[10px]">
75
+ Data Tersedia:
76
+ </span>
77
+ <p className="opacity-90 font-mono text-[11px] bg-white/50 p-1.5 rounded">
78
+ {errorInfo.available_data_summary}
79
+ </p>
80
+ </div>
81
+ )}
82
+ </div>
83
+ )}
84
+ </div>
85
+ </div>
86
+ );
87
+ };
@@ -0,0 +1,105 @@
1
+ import type { ChartProps } from '../types';
2
+ import { Line } from 'react-chartjs-2';
3
+ import {
4
+ Chart as ChartJS,
5
+ CategoryScale,
6
+ LinearScale,
7
+ PointElement,
8
+ LineElement,
9
+ Title,
10
+ Tooltip,
11
+ Legend,
12
+ Filler,
13
+ type ChartOptions,
14
+ } from 'chart.js';
15
+
16
+ ChartJS.register(
17
+ CategoryScale,
18
+ LinearScale,
19
+ PointElement,
20
+ LineElement,
21
+ Title,
22
+ Tooltip,
23
+ Legend,
24
+ Filler
25
+ );
26
+
27
+ export const LineChart: React.FC<ChartProps> = ({ labels, datasets }) => {
28
+ const options: ChartOptions<'line'> = {
29
+ responsive: true,
30
+ maintainAspectRatio: false,
31
+ interaction: {
32
+ mode: 'index',
33
+ intersect: false,
34
+ },
35
+ plugins: {
36
+ legend: {
37
+ position: 'top',
38
+ align: 'end',
39
+ labels: {
40
+ boxWidth: 10,
41
+ usePointStyle: true,
42
+ pointStyle: 'circle',
43
+ font: { family: "'Inter', sans-serif", size: 11 },
44
+ color: '#64748b',
45
+ },
46
+ },
47
+ title: { display: false },
48
+ tooltip: {
49
+ backgroundColor: 'rgba(255, 255, 255, 0.95)',
50
+ titleColor: '#0f172a',
51
+ bodyColor: '#334155',
52
+ borderColor: '#e2e8f0',
53
+ borderWidth: 1,
54
+ padding: 10,
55
+ cornerRadius: 8,
56
+ },
57
+ },
58
+ scales: {
59
+ x: {
60
+ grid: { display: false },
61
+ ticks: { color: '#94a3b8', font: { size: 11 } },
62
+ },
63
+ y: {
64
+ beginAtZero: true,
65
+ grid: { color: '#f1f5f9' },
66
+ ticks: { padding: 10, color: '#94a3b8', font: { size: 11 } },
67
+ },
68
+ },
69
+ };
70
+
71
+ const lineData = {
72
+ labels: labels,
73
+ datasets: datasets.map((dataset) => ({
74
+ label: dataset.label,
75
+ data: dataset.data,
76
+ borderColor: '#0ea5e9',
77
+ backgroundColor: (context: { chart: { ctx: CanvasRenderingContext2D } }) => {
78
+ const ctx = context.chart.ctx;
79
+ const gradient = ctx.createLinearGradient(0, 0, 0, 300);
80
+ gradient.addColorStop(0, 'rgba(14, 165, 233, 0.2)');
81
+ gradient.addColorStop(1, 'rgba(14, 165, 233, 0)');
82
+ return gradient;
83
+ },
84
+ borderWidth: 2,
85
+ pointBackgroundColor: '#fff',
86
+ pointBorderColor: '#0ea5e9',
87
+ pointBorderWidth: 2,
88
+ pointRadius: 3,
89
+ pointHoverRadius: 5,
90
+ fill: true,
91
+ tension: 0.4,
92
+ })),
93
+ };
94
+
95
+ return (
96
+ <div className="w-full h-full relative">
97
+ <h3 className="text-xs font-bold text-slate-500 uppercase tracking-wide mb-2 absolute top-0 left-0">
98
+ Data Visualization
99
+ </h3>
100
+ <div className="pt-6 h-full w-full">
101
+ <Line options={options} data={lineData} />
102
+ </div>
103
+ </div>
104
+ );
105
+ };
@@ -0,0 +1,18 @@
1
+ import { createContext } from 'react';
2
+ import type { AudashAIConfig, ChartData, ErrorInfo } from '../types';
3
+
4
+ interface AudashAIContextType {
5
+ config: AudashAIConfig;
6
+ chartData: ChartData | null;
7
+ setChartData: (data: ChartData | null) => void;
8
+ descData: string | null;
9
+ setDescData: (data: string | null) => void;
10
+ loading: boolean;
11
+ setLoading: (loading: boolean) => void;
12
+ errorInfo: ErrorInfo | null;
13
+ setErrorInfo: (error: ErrorInfo | null) => void;
14
+ refreshData: () => Promise<void>;
15
+ isRefreshing: boolean;
16
+ }
17
+
18
+ export const AudashAIContext = createContext<AudashAIContextType | undefined>(undefined);
@@ -0,0 +1,60 @@
1
+ import { useState } from 'react';
2
+ import type { AudashAIConfig, ChartData, ErrorInfo } from '../types';
3
+ import { ingestSingleEndpoint } from '../utils/api';
4
+ import { AudashAIContext } from './AudashAIContext';
5
+
6
+ interface AudashAIProviderProps {
7
+ config: AudashAIConfig;
8
+ children: React.ReactNode;
9
+ }
10
+
11
+ export const AudashAIProvider: React.FC<AudashAIProviderProps> = ({ config, children }) => {
12
+ const [chartData, setChartData] = useState<ChartData | null>(null);
13
+ const [descData, setDescData] = useState<string | null>(null);
14
+ const [loading, setLoading] = useState(false);
15
+ const [errorInfo, setErrorInfo] = useState<ErrorInfo | null>(null);
16
+ const [isRefreshing, setIsRefreshing] = useState(false);
17
+
18
+ const refreshData = async () => {
19
+ if (!config.dataApiUrl || !config.endpoints || config.endpoints.length === 0) {
20
+ console.warn('Data API URL or endpoints not configured');
21
+ return;
22
+ }
23
+
24
+ setIsRefreshing(true);
25
+ try {
26
+ const results = await Promise.allSettled(
27
+ config.endpoints.map((endpoint) => ingestSingleEndpoint(endpoint, config))
28
+ );
29
+
30
+ const successful = results.filter((r) => r.status === 'fulfilled').length;
31
+ const failed = results.filter((r) => r.status === 'rejected').length;
32
+
33
+ console.log(`✅ Data refresh completed: ${successful} success, ${failed} failed`);
34
+
35
+ if (failed > 0) {
36
+ console.warn('Some endpoints failed to ingest');
37
+ }
38
+ } catch (error) {
39
+ console.error('Error during data refresh:', error);
40
+ } finally {
41
+ setIsRefreshing(false);
42
+ }
43
+ };
44
+
45
+ const value = {
46
+ config,
47
+ chartData,
48
+ setChartData,
49
+ descData,
50
+ setDescData,
51
+ loading,
52
+ setLoading,
53
+ errorInfo,
54
+ setErrorInfo,
55
+ refreshData,
56
+ isRefreshing,
57
+ };
58
+
59
+ return <AudashAIContext.Provider value={value}>{children}</AudashAIContext.Provider>;
60
+ };
@@ -0,0 +1,10 @@
1
+ import { useContext } from 'react';
2
+ import { AudashAIContext } from '../context/AudashAIContext';
3
+
4
+ export const useAudashAI = () => {
5
+ const context = useContext(AudashAIContext);
6
+ if (context === undefined) {
7
+ throw new Error('useAudashAI must be used within AudashAIProvider');
8
+ }
9
+ return context;
10
+ };
@@ -0,0 +1,12 @@
1
+ // src/index.tsx
2
+ export { default as AudashAIChatbot } from './components/AudashAIChatBot';
3
+ export { AudashAIInput } from './components/AudashAIInput';
4
+ export { AudashAIOutput } from './components/AudashAIOutput';
5
+ export { BarChart } from './components/BarChart';
6
+ export { LineChart } from './components/LineChart';
7
+ export { PieChart } from './components/PieChart';
8
+ export { DoughnutChart } from './components/DoughnutChart';
9
+ export { ErrorDisplay } from './components/ErrorDisplay';
10
+ export { AudashAIContext } from './context/AudashAIContext';
11
+ export { useAudashAI } from './hooks/useAudashAI';
12
+ export * from './types';
@@ -0,0 +1,44 @@
1
+ export interface ChartDataset {
2
+ label: string;
3
+ data: number[];
4
+ }
5
+
6
+ export interface ChartData {
7
+ visualization_type: 'bar' | 'line';
8
+ labels: string[];
9
+ datasets: ChartDataset[];
10
+ }
11
+
12
+ export interface ErrorInfo {
13
+ error_type: string;
14
+ message: string;
15
+ reason?: string;
16
+ suggestion?: string;
17
+ available_data_summary?: string;
18
+ documents_found: number;
19
+ }
20
+
21
+ export interface QueryResponse {
22
+ response_type: 'visualization' | 'description' | 'error';
23
+ chart_config?: ChartData;
24
+ text_response?: string;
25
+ processing_info?: {
26
+ error_type?: string;
27
+ message?: string;
28
+ suggestion?: string;
29
+ available_data_summary?: string;
30
+ documents_found?: number;
31
+ };
32
+ }
33
+
34
+ export interface AudashAIConfig {
35
+ apiKey: string;
36
+ apiUrl: string;
37
+ dataApiUrl?: string;
38
+ endpoints?: string[];
39
+ }
40
+
41
+ export interface ChartProps {
42
+ labels: string[];
43
+ datasets: ChartDataset[];
44
+ }
@@ -0,0 +1,57 @@
1
+ import type { AudashAIConfig } from '../types';
2
+
3
+ export async function fetchDataFromAPI(endpoint: string, baseUrl: string) {
4
+ try {
5
+ const response = await fetch(`${baseUrl}/${endpoint}`, {
6
+ method: 'GET',
7
+ headers: {
8
+ 'Content-Type': 'application/json',
9
+ },
10
+ });
11
+
12
+ if (!response.ok) {
13
+ throw new Error(`Failed to fetch data: ${response.status} ${response.statusText}`);
14
+ }
15
+
16
+ return await response.json();
17
+ } catch (error) {
18
+ console.error('Error fetching data from API:', error);
19
+ throw error;
20
+ }
21
+ }
22
+
23
+ export async function ingestSingleEndpoint(endpoint: string, config: AudashAIConfig) {
24
+ if (!config.dataApiUrl) {
25
+ throw new Error('Data API URL not configured');
26
+ }
27
+
28
+ let data;
29
+ try {
30
+ data = await fetchDataFromAPI(endpoint, config.dataApiUrl);
31
+ } catch (error) {
32
+ console.error(`❌ Failed to fetch data from ${endpoint}:`, error);
33
+ throw new Error(`Failed to fetch data from ${endpoint}`);
34
+ }
35
+
36
+ const response = await fetch(`${config.apiUrl}/ingest`, {
37
+ method: 'POST',
38
+ headers: {
39
+ 'Content-Type': 'application/json',
40
+ },
41
+ body: JSON.stringify({
42
+ data: data.data || data,
43
+ source_name: endpoint,
44
+ api_key: config.apiKey,
45
+ metadata: { description: `${endpoint} data from API` },
46
+ }),
47
+ });
48
+
49
+ if (!response.ok) {
50
+ const errorBody = await response.text();
51
+ throw new Error(
52
+ `HTTP error! Status: ${response.status}, Endpoint: ${endpoint}, Body: ${errorBody}`
53
+ );
54
+ }
55
+
56
+ return await response.json();
57
+ }