@chaaskit/client 0.1.1 → 0.1.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/LICENSE +21 -0
- package/dist/lib/index.js +970 -80
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/routes/AdminPromoCodesRoute.js +19 -0
- package/dist/lib/routes/AdminPromoCodesRoute.js.map +1 -0
- package/dist/lib/routes/AdminWaitlistRoute.js +19 -0
- package/dist/lib/routes/AdminWaitlistRoute.js.map +1 -0
- package/dist/lib/routes.js +47 -37
- package/dist/lib/routes.js.map +1 -1
- package/dist/lib/ssr-utils.js +36 -16
- package/dist/lib/ssr-utils.js.map +1 -1
- package/dist/lib/styles.css +37 -0
- package/dist/lib/useExtensions-B5nX_8XD.js.map +1 -1
- package/package.json +20 -12
- package/src/components/MessageItem.tsx +35 -4
- package/src/components/MessageList.tsx +51 -5
- package/src/components/OAuthAppsSection.tsx +1 -1
- package/src/components/Sidebar.tsx +1 -3
- package/src/components/ToolCallDisplay.tsx +102 -11
- package/src/components/tool-renderers/DocumentListRenderer.tsx +44 -0
- package/src/components/tool-renderers/DocumentReadRenderer.tsx +33 -0
- package/src/components/tool-renderers/DocumentSaveRenderer.tsx +32 -0
- package/src/components/tool-renderers/DocumentSearchRenderer.tsx +33 -0
- package/src/components/tool-renderers/index.ts +36 -0
- package/src/components/tool-renderers/utils.ts +7 -0
- package/src/contexts/AuthContext.tsx +16 -6
- package/src/contexts/ConfigContext.tsx +22 -28
- package/src/extensions/registry.ts +2 -1
- package/src/hooks/__tests__/basePath.test.ts +42 -0
- package/src/index.tsx +5 -2
- package/src/pages/AdminDashboardPage.tsx +15 -1
- package/src/pages/AdminPromoCodesPage.tsx +378 -0
- package/src/pages/AdminTeamPage.tsx +29 -1
- package/src/pages/AdminTeamsPage.tsx +15 -1
- package/src/pages/AdminUsersPage.tsx +15 -1
- package/src/pages/AdminWaitlistPage.tsx +156 -0
- package/src/pages/RegisterPage.tsx +91 -9
- package/src/routes/AdminPromoCodesRoute.tsx +24 -0
- package/src/routes/AdminWaitlistRoute.tsx +24 -0
- package/src/routes/index.ts +2 -0
- package/src/ssr-utils.tsx +32 -12
- package/src/stores/chatStore.ts +5 -0
- package/dist/favicon.svg +0 -11
- package/dist/index.html +0 -17
- package/dist/logo.svg +0 -12
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { Link } from 'react-router';
|
|
3
|
+
import { LayoutDashboard, Users, Building2, X, Mail, Tag } from 'lucide-react';
|
|
4
|
+
import { useConfig } from '../contexts/ConfigContext';
|
|
5
|
+
import { useAppPath } from '../hooks/useAppPath';
|
|
6
|
+
import { api } from '../utils/api';
|
|
7
|
+
import type { AdminWaitlistEntry, AdminWaitlistResponse } from '@chaaskit/shared';
|
|
8
|
+
|
|
9
|
+
export default function AdminWaitlistPage() {
|
|
10
|
+
const config = useConfig();
|
|
11
|
+
const appPath = useAppPath();
|
|
12
|
+
const [entries, setEntries] = useState<AdminWaitlistEntry[]>([]);
|
|
13
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
14
|
+
const [error, setError] = useState('');
|
|
15
|
+
const [success, setSuccess] = useState('');
|
|
16
|
+
|
|
17
|
+
async function loadWaitlist() {
|
|
18
|
+
setIsLoading(true);
|
|
19
|
+
setError('');
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const response = await api.get<AdminWaitlistResponse>('/api/admin/waitlist');
|
|
23
|
+
setEntries(response.entries);
|
|
24
|
+
} catch (err) {
|
|
25
|
+
setError(err instanceof Error ? err.message : 'Failed to load waitlist');
|
|
26
|
+
} finally {
|
|
27
|
+
setIsLoading(false);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
loadWaitlist();
|
|
33
|
+
}, []);
|
|
34
|
+
|
|
35
|
+
async function handleInvite(entryId: string, email: string) {
|
|
36
|
+
setError('');
|
|
37
|
+
setSuccess('');
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
await api.post(`/api/admin/waitlist/${entryId}/invite`, {});
|
|
41
|
+
setSuccess(`Invite sent to ${email}`);
|
|
42
|
+
loadWaitlist();
|
|
43
|
+
} catch (err) {
|
|
44
|
+
setError(err instanceof Error ? err.message : 'Failed to send invite');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div className="min-h-screen bg-background p-4 sm:p-8">
|
|
50
|
+
<div className="mx-auto max-w-6xl">
|
|
51
|
+
<div className="flex items-center justify-between mb-4">
|
|
52
|
+
<h1 className="text-xl sm:text-2xl font-bold text-text-primary">Admin</h1>
|
|
53
|
+
<Link
|
|
54
|
+
to={appPath('/')}
|
|
55
|
+
className="flex items-center justify-center rounded-lg p-2 text-text-muted hover:text-text-primary hover:bg-background-secondary"
|
|
56
|
+
aria-label="Close"
|
|
57
|
+
>
|
|
58
|
+
<X size={20} />
|
|
59
|
+
</Link>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div className="flex items-center gap-2 mb-6 sm:mb-8">
|
|
63
|
+
<Link
|
|
64
|
+
to={appPath('/admin')}
|
|
65
|
+
className="flex items-center gap-1.5 rounded-full bg-background-secondary px-4 py-2 text-sm font-medium text-text-secondary hover:bg-background-secondary/80"
|
|
66
|
+
>
|
|
67
|
+
<LayoutDashboard size={16} />
|
|
68
|
+
Overview
|
|
69
|
+
</Link>
|
|
70
|
+
<Link
|
|
71
|
+
to={appPath('/admin/users')}
|
|
72
|
+
className="flex items-center gap-1.5 rounded-full bg-background-secondary px-4 py-2 text-sm font-medium text-text-secondary hover:bg-background-secondary/80"
|
|
73
|
+
>
|
|
74
|
+
<Users size={16} />
|
|
75
|
+
Users
|
|
76
|
+
</Link>
|
|
77
|
+
{config.teams?.enabled && (
|
|
78
|
+
<Link
|
|
79
|
+
to={appPath('/admin/teams')}
|
|
80
|
+
className="flex items-center gap-1.5 rounded-full bg-background-secondary px-4 py-2 text-sm font-medium text-text-secondary hover:bg-background-secondary/80"
|
|
81
|
+
>
|
|
82
|
+
<Building2 size={16} />
|
|
83
|
+
Teams
|
|
84
|
+
</Link>
|
|
85
|
+
)}
|
|
86
|
+
<Link
|
|
87
|
+
to={appPath('/admin/promo-codes')}
|
|
88
|
+
className="flex items-center gap-1.5 rounded-full bg-background-secondary px-4 py-2 text-sm font-medium text-text-secondary hover:bg-background-secondary/80"
|
|
89
|
+
>
|
|
90
|
+
<Tag size={16} />
|
|
91
|
+
Promo Codes
|
|
92
|
+
</Link>
|
|
93
|
+
<span className="flex items-center gap-1.5 rounded-full bg-primary px-4 py-2 text-sm font-medium text-white">
|
|
94
|
+
<Mail size={16} />
|
|
95
|
+
Waitlist
|
|
96
|
+
</span>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
{error && (
|
|
100
|
+
<div className="mb-6 rounded-lg bg-error/10 p-4 text-sm text-error">
|
|
101
|
+
{error}
|
|
102
|
+
</div>
|
|
103
|
+
)}
|
|
104
|
+
|
|
105
|
+
{success && (
|
|
106
|
+
<div className="mb-6 rounded-lg bg-success/10 p-4 text-sm text-success">
|
|
107
|
+
{success}
|
|
108
|
+
</div>
|
|
109
|
+
)}
|
|
110
|
+
|
|
111
|
+
<div className="rounded-lg bg-background-secondary overflow-hidden">
|
|
112
|
+
<div className="hidden md:block px-4 py-3 bg-background">
|
|
113
|
+
<div className="grid grid-cols-12 gap-4 text-sm font-medium text-text-muted">
|
|
114
|
+
<div className="col-span-4">Email</div>
|
|
115
|
+
<div className="col-span-2">Name</div>
|
|
116
|
+
<div className="col-span-2">Status</div>
|
|
117
|
+
<div className="col-span-2">Joined</div>
|
|
118
|
+
<div className="col-span-2">Action</div>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div className="divide-y divide-background">
|
|
123
|
+
{isLoading ? (
|
|
124
|
+
<div className="px-4 py-8 text-center text-text-muted">Loading...</div>
|
|
125
|
+
) : entries.length === 0 ? (
|
|
126
|
+
<div className="px-4 py-8 text-center text-text-muted">No waitlist entries</div>
|
|
127
|
+
) : (
|
|
128
|
+
entries.map((entry) => (
|
|
129
|
+
<div key={entry.id} className="px-4 py-3 hover:bg-background/50">
|
|
130
|
+
<div className="grid grid-cols-1 md:grid-cols-12 gap-2 md:gap-4 text-sm">
|
|
131
|
+
<div className="md:col-span-4 text-text-primary">{entry.email}</div>
|
|
132
|
+
<div className="md:col-span-2 text-text-secondary">{entry.name || '-'}</div>
|
|
133
|
+
<div className="md:col-span-2 capitalize text-text-secondary">{entry.status.replace('_', ' ')}</div>
|
|
134
|
+
<div className="md:col-span-2 text-text-muted">
|
|
135
|
+
{new Date(entry.createdAt).toLocaleDateString()}
|
|
136
|
+
</div>
|
|
137
|
+
<div className="md:col-span-2">
|
|
138
|
+
<button
|
|
139
|
+
type="button"
|
|
140
|
+
onClick={() => handleInvite(entry.id, entry.email)}
|
|
141
|
+
disabled={entry.status === 'invited'}
|
|
142
|
+
className="rounded-lg bg-primary px-3 py-1.5 text-xs font-medium text-white hover:bg-primary-hover disabled:opacity-50"
|
|
143
|
+
>
|
|
144
|
+
{entry.status === 'invited' ? 'Invited' : 'Invite'}
|
|
145
|
+
</button>
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
))
|
|
150
|
+
)}
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
|
-
import { Link, useNavigate } from 'react-router';
|
|
2
|
+
import { Link, useNavigate, useSearchParams } from 'react-router';
|
|
3
3
|
import { useAuth } from '../contexts/AuthContext';
|
|
4
4
|
import { useConfig } from '../contexts/ConfigContext';
|
|
5
5
|
import { useTheme } from '../contexts/ThemeContext';
|
|
6
6
|
import { useAppPath } from '../hooks/useAppPath';
|
|
7
|
+
import { api } from '../utils/api';
|
|
7
8
|
|
|
8
9
|
export default function RegisterPage() {
|
|
9
10
|
const navigate = useNavigate();
|
|
@@ -11,12 +12,22 @@ export default function RegisterPage() {
|
|
|
11
12
|
const { register } = useAuth();
|
|
12
13
|
const config = useConfig();
|
|
13
14
|
const { theme } = useTheme();
|
|
15
|
+
const [searchParams] = useSearchParams();
|
|
16
|
+
|
|
17
|
+
const inviteToken = searchParams.get('invite') || undefined;
|
|
18
|
+
const referralCode = searchParams.get('ref') || undefined;
|
|
19
|
+
const gating = config.auth.gating;
|
|
20
|
+
const signupsRestricted = gating?.mode && gating.mode !== 'open' && !inviteToken;
|
|
21
|
+
const waitlistEnabled = gating?.waitlistEnabled ?? false;
|
|
22
|
+
const showWaitlist = !!signupsRestricted && waitlistEnabled;
|
|
23
|
+
const showRestrictedMessage = !!signupsRestricted && !waitlistEnabled;
|
|
14
24
|
|
|
15
25
|
const [name, setName] = useState('');
|
|
16
26
|
const [email, setEmail] = useState('');
|
|
17
27
|
const [password, setPassword] = useState('');
|
|
18
28
|
const [error, setError] = useState('');
|
|
19
29
|
const [isLoading, setIsLoading] = useState(false);
|
|
30
|
+
const [waitlistStatus, setWaitlistStatus] = useState<'idle' | 'submitted'>('idle');
|
|
20
31
|
|
|
21
32
|
async function handleSubmit(e: React.FormEvent) {
|
|
22
33
|
e.preventDefault();
|
|
@@ -30,7 +41,10 @@ export default function RegisterPage() {
|
|
|
30
41
|
setIsLoading(true);
|
|
31
42
|
|
|
32
43
|
try {
|
|
33
|
-
const { requiresVerification } = await register(email, password, name || undefined
|
|
44
|
+
const { requiresVerification } = await register(email, password, name || undefined, {
|
|
45
|
+
inviteToken,
|
|
46
|
+
referralCode,
|
|
47
|
+
});
|
|
34
48
|
if (requiresVerification) {
|
|
35
49
|
navigate('/verify-email');
|
|
36
50
|
} else {
|
|
@@ -43,6 +57,18 @@ export default function RegisterPage() {
|
|
|
43
57
|
}
|
|
44
58
|
}
|
|
45
59
|
|
|
60
|
+
async function handleWaitlistSubmit(e: React.FormEvent) {
|
|
61
|
+
e.preventDefault();
|
|
62
|
+
setError('');
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
await api.post('/api/auth/waitlist', { email, name: name || undefined });
|
|
66
|
+
setWaitlistStatus('submitted');
|
|
67
|
+
} catch (err) {
|
|
68
|
+
setError(err instanceof Error ? err.message : 'Failed to join waitlist');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
46
72
|
return (
|
|
47
73
|
<div className="flex min-h-screen items-center justify-center bg-background p-4">
|
|
48
74
|
<div className="w-full max-w-md">
|
|
@@ -66,7 +92,60 @@ export default function RegisterPage() {
|
|
|
66
92
|
</div>
|
|
67
93
|
)}
|
|
68
94
|
|
|
69
|
-
|
|
95
|
+
{showRestrictedMessage ? (
|
|
96
|
+
<div className="rounded-lg border border-border bg-background-secondary p-4 text-sm text-text-secondary">
|
|
97
|
+
Signups are currently closed. Please check back later.
|
|
98
|
+
</div>
|
|
99
|
+
) : showWaitlist ? (
|
|
100
|
+
<div className="rounded-lg border border-border bg-background-secondary p-4">
|
|
101
|
+
<p className="text-sm text-text-secondary">
|
|
102
|
+
Signups are currently restricted. Join the waitlist to get an invite.
|
|
103
|
+
</p>
|
|
104
|
+
|
|
105
|
+
{waitlistStatus === 'submitted' ? (
|
|
106
|
+
<div className="mt-4 rounded-lg bg-success/10 p-3 text-sm text-success">
|
|
107
|
+
Thanks! You’re on the waitlist.
|
|
108
|
+
</div>
|
|
109
|
+
) : (
|
|
110
|
+
<form onSubmit={handleWaitlistSubmit} className="mt-4 space-y-3">
|
|
111
|
+
<div>
|
|
112
|
+
<label htmlFor="waitlist-name" className="block text-sm font-medium text-text-primary">
|
|
113
|
+
Name (optional)
|
|
114
|
+
</label>
|
|
115
|
+
<input
|
|
116
|
+
type="text"
|
|
117
|
+
id="waitlist-name"
|
|
118
|
+
value={name}
|
|
119
|
+
onChange={(e) => setName(e.target.value)}
|
|
120
|
+
className="mt-1 w-full rounded-lg border border-input-border bg-input-background px-4 py-2 text-text-primary focus:border-primary focus:outline-none"
|
|
121
|
+
/>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<div>
|
|
125
|
+
<label htmlFor="waitlist-email" className="block text-sm font-medium text-text-primary">
|
|
126
|
+
Email
|
|
127
|
+
</label>
|
|
128
|
+
<input
|
|
129
|
+
type="email"
|
|
130
|
+
id="waitlist-email"
|
|
131
|
+
value={email}
|
|
132
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
133
|
+
required
|
|
134
|
+
className="mt-1 w-full rounded-lg border border-input-border bg-input-background px-4 py-2 text-text-primary focus:border-primary focus:outline-none"
|
|
135
|
+
/>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<button
|
|
139
|
+
type="submit"
|
|
140
|
+
className="w-full rounded-lg bg-primary px-4 py-2 font-medium text-white hover:bg-primary-hover"
|
|
141
|
+
>
|
|
142
|
+
Join waitlist
|
|
143
|
+
</button>
|
|
144
|
+
</form>
|
|
145
|
+
)}
|
|
146
|
+
</div>
|
|
147
|
+
) : (
|
|
148
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
70
149
|
<div>
|
|
71
150
|
<label
|
|
72
151
|
htmlFor="name"
|
|
@@ -129,13 +208,16 @@ export default function RegisterPage() {
|
|
|
129
208
|
{isLoading ? 'Creating account...' : 'Create account'}
|
|
130
209
|
</button>
|
|
131
210
|
</form>
|
|
211
|
+
)}
|
|
132
212
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
213
|
+
{!signupsRestricted && (
|
|
214
|
+
<p className="mt-6 text-center text-sm text-text-secondary">
|
|
215
|
+
Already have an account?{' '}
|
|
216
|
+
<Link to="/login" className="text-primary hover:underline">
|
|
217
|
+
Sign in
|
|
218
|
+
</Link>
|
|
219
|
+
</p>
|
|
220
|
+
)}
|
|
139
221
|
|
|
140
222
|
<p className="mt-4 text-center text-xs text-text-muted">
|
|
141
223
|
By creating an account, you agree to our{' '}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Promo Codes Route - Promo code management
|
|
3
|
+
*/
|
|
4
|
+
import { ChatProviders } from '../index';
|
|
5
|
+
import AdminPromoCodesPage from '../pages/AdminPromoCodesPage';
|
|
6
|
+
import { SimpleLoadingSkeleton } from '../components/LoadingSkeletons';
|
|
7
|
+
|
|
8
|
+
export function meta() {
|
|
9
|
+
return [{ title: 'Admin - Promo Codes' }];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function links() {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default function AdminPromoCodesRoute() {
|
|
17
|
+
return (
|
|
18
|
+
<ChatProviders>
|
|
19
|
+
<AdminPromoCodesPage />
|
|
20
|
+
</ChatProviders>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { SimpleLoadingSkeleton as LoadingSkeleton };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Waitlist Route - Waitlist management
|
|
3
|
+
*/
|
|
4
|
+
import { ChatProviders } from '../index';
|
|
5
|
+
import AdminWaitlistPage from '../pages/AdminWaitlistPage';
|
|
6
|
+
import { SimpleLoadingSkeleton } from '../components/LoadingSkeletons';
|
|
7
|
+
|
|
8
|
+
export function meta() {
|
|
9
|
+
return [{ title: 'Admin - Waitlist' }];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function links() {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default function AdminWaitlistRoute() {
|
|
17
|
+
return (
|
|
18
|
+
<ChatProviders>
|
|
19
|
+
<AdminWaitlistPage />
|
|
20
|
+
</ChatProviders>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { SimpleLoadingSkeleton as LoadingSkeleton };
|
package/src/routes/index.ts
CHANGED
|
@@ -45,6 +45,8 @@ export { default as AdminDashboardRoute, meta as adminDashboardMeta, links as ad
|
|
|
45
45
|
export { default as AdminUsersRoute, meta as adminUsersMeta, links as adminUsersLinks, LoadingSkeleton as AdminUsersLoadingSkeleton } from './AdminUsersRoute';
|
|
46
46
|
export { default as AdminTeamsRoute, meta as adminTeamsMeta, links as adminTeamsLinks, LoadingSkeleton as AdminTeamsLoadingSkeleton } from './AdminTeamsRoute';
|
|
47
47
|
export { default as AdminTeamRoute, meta as adminTeamMeta, links as adminTeamLinks, LoadingSkeleton as AdminTeamLoadingSkeleton } from './AdminTeamRoute';
|
|
48
|
+
export { default as AdminWaitlistRoute, meta as adminWaitlistMeta, links as adminWaitlistLinks, LoadingSkeleton as AdminWaitlistLoadingSkeleton } from './AdminWaitlistRoute';
|
|
49
|
+
export { default as AdminPromoCodesRoute, meta as adminPromoCodesMeta, links as adminPromoCodesLinks, LoadingSkeleton as AdminPromoCodesLoadingSkeleton } from './AdminPromoCodesRoute';
|
|
48
50
|
|
|
49
51
|
// Auth-related routes
|
|
50
52
|
export { default as VerifyEmailRoute, meta as verifyEmailMeta, links as verifyEmailLinks, LoadingSkeleton as VerifyEmailLoadingSkeleton } from './VerifyEmailRoute';
|
package/src/ssr-utils.tsx
CHANGED
|
@@ -68,29 +68,49 @@ export function ConfigScript({ config }: ConfigScriptProps) {
|
|
|
68
68
|
auth: {
|
|
69
69
|
methods: config.auth?.methods,
|
|
70
70
|
allowUnauthenticated: config.auth?.allowUnauthenticated,
|
|
71
|
+
magicLink: config.auth?.magicLink,
|
|
72
|
+
emailVerification: config.auth?.emailVerification,
|
|
73
|
+
gating: config.auth?.gating,
|
|
71
74
|
},
|
|
72
75
|
payments: {
|
|
73
76
|
enabled: config.payments?.enabled,
|
|
74
|
-
|
|
75
|
-
id: plan.id,
|
|
76
|
-
name: plan.name,
|
|
77
|
-
type: plan.type,
|
|
78
|
-
})),
|
|
77
|
+
provider: config.payments?.provider,
|
|
79
78
|
},
|
|
80
79
|
legal: config.legal,
|
|
81
80
|
sharing: config.sharing,
|
|
82
81
|
teams: config.teams,
|
|
83
82
|
projects: config.projects,
|
|
84
|
-
documents: {
|
|
85
|
-
enabled: config.documents
|
|
86
|
-
|
|
83
|
+
documents: config.documents ? {
|
|
84
|
+
enabled: config.documents.enabled,
|
|
85
|
+
maxFileSizeMB: config.documents.maxFileSizeMB,
|
|
86
|
+
hybridThreshold: config.documents.hybridThreshold,
|
|
87
|
+
acceptedTypes: config.documents.acceptedTypes,
|
|
88
|
+
} : undefined,
|
|
87
89
|
api: {
|
|
88
90
|
enabled: config.api?.enabled,
|
|
89
91
|
},
|
|
90
|
-
promptTemplates: {
|
|
91
|
-
enabled: config.promptTemplates
|
|
92
|
-
allowUserTemplates: config.promptTemplates
|
|
93
|
-
},
|
|
92
|
+
promptTemplates: config.promptTemplates ? {
|
|
93
|
+
enabled: config.promptTemplates.enabled,
|
|
94
|
+
allowUserTemplates: config.promptTemplates.allowUserTemplates,
|
|
95
|
+
} : undefined,
|
|
96
|
+
scheduledPrompts: config.scheduledPrompts ? {
|
|
97
|
+
enabled: config.scheduledPrompts.enabled,
|
|
98
|
+
featureName: config.scheduledPrompts.featureName,
|
|
99
|
+
allowUserPrompts: config.scheduledPrompts.allowUserPrompts,
|
|
100
|
+
allowTeamPrompts: config.scheduledPrompts.allowTeamPrompts,
|
|
101
|
+
defaultTimezone: config.scheduledPrompts.defaultTimezone,
|
|
102
|
+
defaultMaxUserPrompts: config.scheduledPrompts.defaultMaxUserPrompts,
|
|
103
|
+
defaultMaxTeamPrompts: config.scheduledPrompts.defaultMaxTeamPrompts,
|
|
104
|
+
} : undefined,
|
|
105
|
+
credits: config.credits ? {
|
|
106
|
+
enabled: config.credits.enabled,
|
|
107
|
+
expiryEnabled: config.credits.expiryEnabled,
|
|
108
|
+
promoEnabled: config.credits.promoEnabled,
|
|
109
|
+
} : undefined,
|
|
110
|
+
metering: config.metering ? {
|
|
111
|
+
enabled: config.metering.enabled,
|
|
112
|
+
recordPromptCompletion: config.metering.recordPromptCompletion,
|
|
113
|
+
} : undefined,
|
|
94
114
|
};
|
|
95
115
|
|
|
96
116
|
return (
|
package/src/stores/chatStore.ts
CHANGED
|
@@ -19,6 +19,7 @@ interface CompletedToolCall extends PendingToolCall {
|
|
|
19
19
|
result: MCPContent[];
|
|
20
20
|
isError?: boolean;
|
|
21
21
|
uiResource?: UIResource;
|
|
22
|
+
structuredContent?: Record<string, unknown>;
|
|
22
23
|
autoApproveReason?: AutoApproveReason;
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -324,6 +325,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|
|
324
325
|
input?: Record<string, unknown>;
|
|
325
326
|
isError?: boolean;
|
|
326
327
|
uiResource?: UIResource;
|
|
328
|
+
structuredContent?: Record<string, unknown>;
|
|
327
329
|
// Tool confirmation fields
|
|
328
330
|
confirmationId?: string;
|
|
329
331
|
toolName?: string;
|
|
@@ -397,6 +399,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|
|
397
399
|
result: (data.content as unknown as MCPContent[]) || [],
|
|
398
400
|
isError: data.isError,
|
|
399
401
|
uiResource: data.uiResource,
|
|
402
|
+
structuredContent: (data.structuredContent as Record<string, unknown> | undefined),
|
|
400
403
|
}
|
|
401
404
|
: {
|
|
402
405
|
// Fallback: create from tool_result event data (server now includes name/serverId/input)
|
|
@@ -407,6 +410,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|
|
407
410
|
result: (data.content as unknown as MCPContent[]) || [],
|
|
408
411
|
isError: data.isError,
|
|
409
412
|
uiResource: data.uiResource,
|
|
413
|
+
structuredContent: (data.structuredContent as Record<string, unknown> | undefined),
|
|
410
414
|
};
|
|
411
415
|
|
|
412
416
|
return {
|
|
@@ -492,6 +496,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|
|
492
496
|
content: tc.result,
|
|
493
497
|
isError: tc.isError,
|
|
494
498
|
uiResource: tc.uiResource,
|
|
499
|
+
structuredContent: tc.structuredContent,
|
|
495
500
|
}))
|
|
496
501
|
: undefined,
|
|
497
502
|
createdAt: new Date(),
|
package/dist/favicon.svg
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
|
|
2
|
-
<defs>
|
|
3
|
-
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
-
<stop offset="0%" style="stop-color:#6366f1"/>
|
|
5
|
-
<stop offset="100%" style="stop-color:#8b5cf6"/>
|
|
6
|
-
</linearGradient>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect width="32" height="32" rx="6" fill="url(#grad)"/>
|
|
9
|
-
<path d="M10 12 L16 9 L22 12 L22 18 L16 21 L10 18 Z" fill="none" stroke="white" stroke-width="1.5" stroke-linejoin="round"/>
|
|
10
|
-
<circle cx="16" cy="15" r="2.5" fill="white"/>
|
|
11
|
-
</svg>
|
package/dist/index.html
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>AI Chat</title>
|
|
8
|
-
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
9
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
10
|
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
11
|
-
<script type="module" crossorigin src="/assets/index-BYcLoar2.js"></script>
|
|
12
|
-
<link rel="stylesheet" crossorigin href="/assets/index-Ob8N4Y68.css">
|
|
13
|
-
</head>
|
|
14
|
-
<body>
|
|
15
|
-
<div id="root"></div>
|
|
16
|
-
</body>
|
|
17
|
-
</html>
|
package/dist/logo.svg
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
|
|
2
|
-
<defs>
|
|
3
|
-
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
-
<stop offset="0%" style="stop-color:#6366f1"/>
|
|
5
|
-
<stop offset="100%" style="stop-color:#8b5cf6"/>
|
|
6
|
-
</linearGradient>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect width="100" height="100" rx="20" fill="url(#gradient)"/>
|
|
9
|
-
<path d="M30 35 L50 25 L70 35 L70 55 L50 65 L30 55 Z" fill="none" stroke="white" stroke-width="3" stroke-linejoin="round"/>
|
|
10
|
-
<circle cx="50" cy="45" r="8" fill="white"/>
|
|
11
|
-
<path d="M35 70 Q50 78 65 70" fill="none" stroke="white" stroke-width="3" stroke-linecap="round"/>
|
|
12
|
-
</svg>
|