@vertesia/ui 0.79.1 → 0.80.0-dev-20251118
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 +6 -1
- package/src/core/components/SelectBox.tsx +1 -1
- package/src/core/components/TagsInput.tsx +388 -0
- package/src/core/components/index.ts +2 -1
- package/src/core/components/shadcn/popover.tsx +2 -2
- package/src/core/hooks/CompositeState.tsx +156 -6
- package/src/env/index.ts +4 -3
- package/src/features/agent/PayloadBuilder.tsx +92 -65
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +1 -1
- package/src/features/agent/chat/ModernAgentOutput/Header.tsx +2 -2
- package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +3 -3
- package/src/features/store/collections/EditCollectionView.tsx +31 -10
- package/src/features/store/collections/SharedPropsEditor.tsx +61 -0
- package/src/features/store/collections/SyncMemberHeadsToggle.tsx +48 -0
- package/src/features/store/collections/index.ts +3 -1
- package/src/features/store/objects/DocumentSearchResults.tsx +11 -2
- package/src/features/store/objects/components/useDownloadObject.ts +7 -2
- package/src/features/user/UserInfo.tsx +2 -0
- package/src/session/UserSession.ts +1 -0
- package/src/session/UserSessionProvider.tsx +10 -2
- package/src/session/auth/composable.ts +71 -70
- package/src/shell/apps/AppProjectSelector.tsx +2 -2
- package/src/widgets/form/Form.tsx +1 -1
- package/src/widgets/form/ManagedObject.ts +4 -0
|
@@ -32,95 +32,96 @@ export async function fetchComposableToken(getIdToken: () => Promise<string | nu
|
|
|
32
32
|
throw new Error('No id token found');
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
// Use STS endpoint - either configured or default to sts.vertesia.io
|
|
36
|
+
const stsEndpoint = Env.endpoints.sts;
|
|
37
|
+
console.log('Using STS for token generation:', stsEndpoint);
|
|
38
|
+
Env.logger.info('Using STS for token generation', {
|
|
37
39
|
vertesia: {
|
|
38
40
|
account_id: accountId,
|
|
39
41
|
project_id: projectId,
|
|
42
|
+
sts_url: stsEndpoint,
|
|
40
43
|
},
|
|
41
44
|
});
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
console.log(`Getting composable token for account ${accountId} and project ${projectId}`);
|
|
49
|
-
Env.logger.info('Getting composable token', {
|
|
50
|
-
vertesia: {
|
|
46
|
+
try {
|
|
47
|
+
// Call STS to generate a user token
|
|
48
|
+
const stsUrl = new URL(stsEndpoint + '/token/issue');
|
|
49
|
+
const requestBody = {
|
|
50
|
+
type: 'user',
|
|
51
51
|
account_id: accountId,
|
|
52
52
|
project_id: projectId,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
}).catch(err => {
|
|
63
|
-
localStorage.removeItem(LastSelectedAccountId_KEY);
|
|
64
|
-
localStorage.removeItem(LastSelectedProjectId_KEY);
|
|
65
|
-
console.error('Failed to get composable token', err);
|
|
66
|
-
Env.logger.error('Failed to get composable token', {
|
|
67
|
-
vertesia: {
|
|
68
|
-
account_id: accountId,
|
|
69
|
-
project_id: projectId,
|
|
70
|
-
error: err,
|
|
53
|
+
expires_at: ttl ? Math.floor(Date.now() / 1000) + ttl : undefined,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const stsRes = await fetch(stsUrl, {
|
|
57
|
+
method: 'POST',
|
|
58
|
+
headers: {
|
|
59
|
+
'Content-Type': 'application/json',
|
|
60
|
+
'Authorization': `Bearer ${idToken}` // Firebase token for authentication
|
|
71
61
|
},
|
|
62
|
+
body: JSON.stringify(requestBody)
|
|
72
63
|
});
|
|
73
|
-
throw new Error('Failed to get composable token');
|
|
74
|
-
});
|
|
75
64
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
Env.logger.error('User not found', {
|
|
91
|
-
vertesia: {
|
|
92
|
-
account_id: accountId,
|
|
93
|
-
project_id: projectId,
|
|
94
|
-
email: idTokenDecoded.email
|
|
65
|
+
if (idToken && stsRes?.status === 412) {
|
|
66
|
+
console.log("412: auth succeeded but user doesn't exist - signup required", stsRes?.status);
|
|
67
|
+
Env.logger.error("412: auth succeeded but user doesn't exist - signup required", {
|
|
68
|
+
vertesia: {
|
|
69
|
+
account_id: accountId,
|
|
70
|
+
project_id: projectId,
|
|
71
|
+
status: stsRes?.status
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
const idTokenDecoded = jwtDecode(idToken) as any;
|
|
75
|
+
if (!idTokenDecoded?.email) {
|
|
76
|
+
Env.logger.error('No email found in id token');
|
|
77
|
+
throw new Error('No email found in id token');
|
|
95
78
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
79
|
+
Env.logger.error('User not found', {
|
|
80
|
+
vertesia: {
|
|
81
|
+
account_id: accountId,
|
|
82
|
+
project_id: projectId,
|
|
83
|
+
email: idTokenDecoded.email
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
throw new UserNotFoundError('User not found', idTokenDecoded.email);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!stsRes.ok) {
|
|
90
|
+
const errorText = await stsRes.text();
|
|
91
|
+
console.error('STS token generation failed:', stsRes.status, errorText);
|
|
92
|
+
Env.logger.error('STS token generation failed', {
|
|
93
|
+
vertesia: {
|
|
94
|
+
status: stsRes.status,
|
|
95
|
+
error: errorText,
|
|
96
|
+
account_id: accountId,
|
|
97
|
+
project_id: projectId,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
throw new Error(`Failed to get token from STS: ${stsRes.status}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const { token } = await stsRes.json();
|
|
104
|
+
console.log('Successfully got token from STS');
|
|
105
|
+
Env.logger.info('Successfully got token from STS');
|
|
106
|
+
return token;
|
|
99
107
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
108
|
+
} catch (error) {
|
|
109
|
+
if (error instanceof UserNotFoundError) {
|
|
110
|
+
throw error; // Re-throw UserNotFoundError
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
localStorage.removeItem(LastSelectedAccountId_KEY);
|
|
114
|
+
localStorage.removeItem(LastSelectedProjectId_KEY);
|
|
115
|
+
console.error('Failed to get composable token from STS', error);
|
|
116
|
+
Env.logger.error('Failed to get composable token from STS', {
|
|
103
117
|
vertesia: {
|
|
104
118
|
account_id: accountId,
|
|
105
119
|
project_id: projectId,
|
|
106
|
-
|
|
120
|
+
error: error,
|
|
107
121
|
},
|
|
108
122
|
});
|
|
109
123
|
throw new Error('Failed to get composable token');
|
|
110
124
|
}
|
|
111
|
-
|
|
112
|
-
const { token } = await res.json().catch(err => {
|
|
113
|
-
Env.logger.error('Failed to parse composable token', {
|
|
114
|
-
vertesia: {
|
|
115
|
-
account_id: accountId,
|
|
116
|
-
project_id: projectId,
|
|
117
|
-
error: err,
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
console.error('Failed to parse composable token', err);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
return token;
|
|
124
125
|
}
|
|
125
126
|
|
|
126
127
|
/**
|
|
@@ -187,4 +188,4 @@ export class UserNotFoundError extends Error {
|
|
|
187
188
|
this.name = 'UserNotFoundError';
|
|
188
189
|
this.email = email;
|
|
189
190
|
}
|
|
190
|
-
}
|
|
191
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ProjectRef, RequireAtLeastOne } from "@vertesia/common";
|
|
2
|
-
import {
|
|
2
|
+
import { VSelectBox, useFetch } from "@vertesia/ui/core";
|
|
3
3
|
import { LastSelectedAccountId_KEY, LastSelectedProjectId_KEY, useUserSession } from "@vertesia/ui/session";
|
|
4
4
|
import { useState } from "react";
|
|
5
5
|
|
|
@@ -47,7 +47,7 @@ function SelectProject({ initialValue, projects, onChange, placeholder = "Select
|
|
|
47
47
|
}
|
|
48
48
|
let actualValue = !value && initialValue ? projects.find(p => p.id === initialValue) : value;
|
|
49
49
|
return (
|
|
50
|
-
<
|
|
50
|
+
<VSelectBox
|
|
51
51
|
by="id"
|
|
52
52
|
value={actualValue}
|
|
53
53
|
options={projects}
|
|
@@ -97,7 +97,7 @@ export function ScalarField({ object, editor, inline = false }: ScalarFieldProps
|
|
|
97
97
|
return (
|
|
98
98
|
<FormItem label={object.title} required={object.schema.isRequired} description={object.schema.description}
|
|
99
99
|
className={clsx('flex', inline ? 'flex-row items-center' : 'flex-col')}>
|
|
100
|
-
{!object.isListItem && <Component object={object} type={inputType} onChange={handleOnChange} />}
|
|
100
|
+
{!object.isListItem && <Component object={object} type={inputType} onChange={handleOnChange} disabled={disabled} />}
|
|
101
101
|
</FormItem>
|
|
102
102
|
)
|
|
103
103
|
}
|
|
@@ -10,6 +10,10 @@ function getInputType(_name: string, schema: PropertySchema) {
|
|
|
10
10
|
if (schema.editor) {
|
|
11
11
|
return schema.editor;
|
|
12
12
|
}
|
|
13
|
+
// Check format as fallback (e.g., "document", "media", "date", etc.)
|
|
14
|
+
if (schema.schema.format) {
|
|
15
|
+
return schema.schema.format;
|
|
16
|
+
}
|
|
13
17
|
switch (schema.type) {
|
|
14
18
|
case 'number':
|
|
15
19
|
case 'integer':
|