@datalayer/agent-runtimes 0.0.7 → 0.0.9
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/README.md +9 -0
- package/lib/components/chat/components/AgentDetails.d.ts +14 -1
- package/lib/components/chat/components/AgentDetails.js +3 -2
- package/lib/components/chat/components/AgentIdentity.d.ts +92 -0
- package/lib/components/chat/components/AgentIdentity.js +318 -0
- package/lib/components/chat/components/Chat.d.ts +20 -1
- package/lib/components/chat/components/Chat.js +16 -3
- package/lib/components/chat/components/ChatFloating.d.ts +6 -1
- package/lib/components/chat/components/ChatFloating.js +12 -6
- package/lib/components/chat/components/base/ChatBase.d.ts +47 -1
- package/lib/components/chat/components/base/ChatBase.js +242 -63
- package/lib/components/chat/components/display/ToolCallDisplay.d.ts +16 -2
- package/lib/components/chat/components/display/ToolCallDisplay.js +148 -6
- package/lib/components/chat/components/display/index.d.ts +1 -1
- package/lib/components/chat/components/display/index.js +1 -1
- package/lib/components/chat/components/elements/ChatInputPrompt.d.ts +12 -1
- package/lib/components/chat/components/elements/ChatInputPrompt.js +8 -3
- package/lib/components/chat/components/index.d.ts +1 -0
- package/lib/components/chat/components/index.js +1 -0
- package/lib/components/chat/components/parts/ToolPart.d.ts +1 -1
- package/lib/components/chat/components/parts/ToolPart.js +142 -6
- package/lib/components/chat/index.d.ts +1 -1
- package/lib/components/chat/index.js +1 -1
- package/lib/components/chat/protocols/A2AAdapter.d.ts +9 -0
- package/lib/components/chat/protocols/A2AAdapter.js +13 -2
- package/lib/components/chat/protocols/ACPAdapter.d.ts +9 -0
- package/lib/components/chat/protocols/ACPAdapter.js +13 -2
- package/lib/components/chat/protocols/AGUIAdapter.d.ts +9 -0
- package/lib/components/chat/protocols/AGUIAdapter.js +19 -1
- package/lib/components/chat/protocols/VercelAIAdapter.d.ts +7 -0
- package/lib/components/chat/protocols/VercelAIAdapter.js +19 -0
- package/lib/components/chat/types/execution.d.ts +78 -0
- package/lib/components/chat/types/execution.js +64 -0
- package/lib/components/chat/types/index.d.ts +1 -0
- package/lib/components/chat/types/index.js +1 -0
- package/lib/components/chat/types/protocol.d.ts +9 -0
- package/lib/components/ui/pagination.d.ts +2 -2
- package/lib/components/ui/pagination.js +4 -4
- package/lib/components/ui/resizable.d.ts +4 -4
- package/lib/components/ui/resizable.js +4 -4
- package/lib/examples/A2UiRestaurantExample.js +2 -2
- package/lib/examples/AgUiAgenticExample.js +2 -2
- package/lib/examples/AgUiBackendToolRenderingExample.js +2 -2
- package/lib/examples/AgUiHaikuGenUIExample.js +2 -2
- package/lib/examples/AgUiHumanInTheLoopExample.js +2 -2
- package/lib/examples/AgUiSharedStateExample.js +2 -2
- package/lib/examples/AgUiToolsBasedGenUIExample.js +2 -2
- package/lib/examples/AgentRuntimeCustomExample.js +2 -2
- package/lib/examples/AgentRuntimeLexical2Example.js +2 -1
- package/lib/examples/AgentRuntimeLexicalExample.js +5 -2
- package/lib/examples/AgentRuntimeLexicalSidebarExample.js +4 -2
- package/lib/examples/AgentRuntimeNotebookExample.js +1 -1
- package/lib/examples/AgentRuntimeStandaloneExample.js +2 -2
- package/lib/examples/AgentSpaceFormExample.d.ts +70 -2
- package/lib/examples/AgentSpaceFormExample.js +177 -43
- package/lib/examples/CopilotKitLexicalExample.js +2 -1
- package/lib/examples/components/AgentConfiguration.d.ts +17 -2
- package/lib/examples/components/AgentConfiguration.js +220 -16
- package/lib/examples/components/LexicalEditor.js +2 -1
- package/lib/examples/components/MockFileBrowser.js +6 -2
- package/lib/examples/components/index.d.ts +0 -1
- package/lib/examples/components/index.js +0 -1
- package/lib/examples/example-selector.js +0 -1
- package/lib/examples/index.d.ts +0 -1
- package/lib/examples/index.js +0 -1
- package/lib/examples/lexical/editorConfig.d.ts +3 -2
- package/lib/examples/lexical/editorConfig.js +7 -1
- package/lib/examples/lexical/initial-content.json +2210 -0
- package/lib/examples/main.js +15 -1
- package/lib/identity/IdentityConnect.d.ts +90 -0
- package/lib/identity/IdentityConnect.js +316 -0
- package/lib/identity/OAuthCallback.d.ts +58 -0
- package/lib/identity/OAuthCallback.js +223 -0
- package/lib/identity/dcr.d.ts +257 -0
- package/lib/identity/dcr.js +282 -0
- package/lib/identity/identityStore.d.ts +72 -0
- package/lib/identity/identityStore.js +529 -0
- package/lib/identity/index.d.ts +46 -0
- package/lib/identity/index.js +17 -0
- package/lib/identity/pkce.d.ts +30 -0
- package/lib/identity/pkce.js +65 -0
- package/lib/identity/types.d.ts +293 -0
- package/lib/identity/types.js +73 -0
- package/lib/identity/useIdentity.d.ts +108 -0
- package/lib/identity/useIdentity.js +323 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/lib/utils.js +1 -1
- package/lib/renderers/a2ui/lib/utils.js +1 -1
- package/lib/test-setup.d.ts +1 -1
- package/lib/test-setup.js +1 -0
- package/lib/tools/adapters/agent-runtimes/AgentRuntimesToolAdapter.js +32 -1
- package/lib/tools/adapters/agent-runtimes/lexicalHooks.d.ts +6 -0
- package/lib/tools/adapters/agent-runtimes/lexicalHooks.js +16 -17
- package/package.json +20 -7
- package/patches/@datalayer+jupyter-lexical+1.0.8.patch +11628 -0
- package/patches/@datalayer+jupyter-react+2.0.2.patch +5338 -0
- package/scripts/apply-patches.sh +32 -0
- package/lib/examples/AgentSpaceHomeExample.d.ts +0 -8
- package/lib/examples/AgentSpaceHomeExample.js +0 -171
- package/lib/examples/components/AgentsDataTable.d.ts +0 -13
- package/lib/examples/components/AgentsDataTable.js +0 -74
- package/lib/examples/components/Rating.d.ts +0 -14
- package/lib/examples/components/Rating.js +0 -12
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* React hook for identity management.
|
|
7
|
+
*
|
|
8
|
+
* Provides a simple interface for OAuth 2.1 identity management.
|
|
9
|
+
*
|
|
10
|
+
* @module identity/useIdentity
|
|
11
|
+
*/
|
|
12
|
+
import { useCallback, useEffect, useMemo } from 'react';
|
|
13
|
+
import { useIdentityStore, useConnectedIdentities, useConnectedProviders, usePendingAuthorization, useIdentityLoading, useIdentityError, configureBuiltinProviders, } from './identityStore';
|
|
14
|
+
/**
|
|
15
|
+
* Hook for managing OAuth identities
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* const {
|
|
20
|
+
* identities,
|
|
21
|
+
* connect,
|
|
22
|
+
* disconnect,
|
|
23
|
+
* isConnected,
|
|
24
|
+
* } = useIdentity({
|
|
25
|
+
* providers: {
|
|
26
|
+
* github: { clientId: 'your-client-id' },
|
|
27
|
+
* },
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Connect to GitHub
|
|
31
|
+
* await connect('github', ['repo', 'read:user']);
|
|
32
|
+
*
|
|
33
|
+
* // Check connection
|
|
34
|
+
* if (isConnected('github')) {
|
|
35
|
+
* const token = await getAccessToken('github');
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function useIdentity(options = {}) {
|
|
40
|
+
const { providers, baseUrl = typeof window !== 'undefined' ? window.location.origin : '', callbackPath = typeof window !== 'undefined'
|
|
41
|
+
? window.location.pathname
|
|
42
|
+
: '/oauth/callback', autoHandleCallback = true, } = options;
|
|
43
|
+
// Store state
|
|
44
|
+
const identities = useConnectedIdentities();
|
|
45
|
+
const connectedProviders = useConnectedProviders();
|
|
46
|
+
const pendingAuthorization = usePendingAuthorization();
|
|
47
|
+
const isLoading = useIdentityLoading();
|
|
48
|
+
const error = useIdentityError();
|
|
49
|
+
// Store actions
|
|
50
|
+
const startAuthorization = useIdentityStore(s => s.startAuthorization);
|
|
51
|
+
const completeAuthorizationAction = useIdentityStore(s => s.completeAuthorization);
|
|
52
|
+
const cancelAuthorizationAction = useIdentityStore(s => s.cancelAuthorization);
|
|
53
|
+
const disconnectAction = useIdentityStore(s => s.disconnect);
|
|
54
|
+
const getIdentityAction = useIdentityStore(s => s.getIdentity);
|
|
55
|
+
const isConnectedAction = useIdentityStore(s => s.isConnected);
|
|
56
|
+
const getTokenAction = useIdentityStore(s => s.getToken);
|
|
57
|
+
const configureProviderAction = useIdentityStore(s => s.configureProvider);
|
|
58
|
+
// Configure providers on mount
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (!providers)
|
|
61
|
+
return;
|
|
62
|
+
const redirectUri = `${baseUrl}${callbackPath}`;
|
|
63
|
+
if (providers.github) {
|
|
64
|
+
configureBuiltinProviders({
|
|
65
|
+
github: {
|
|
66
|
+
clientId: providers.github.clientId,
|
|
67
|
+
redirectUri: providers.github.redirectUri || redirectUri,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (providers.google) {
|
|
72
|
+
configureBuiltinProviders({
|
|
73
|
+
google: {
|
|
74
|
+
clientId: providers.google.clientId,
|
|
75
|
+
redirectUri: providers.google.redirectUri || redirectUri,
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
if (providers.kaggle) {
|
|
80
|
+
configureBuiltinProviders({
|
|
81
|
+
kaggle: {
|
|
82
|
+
clientId: providers.kaggle.clientId,
|
|
83
|
+
redirectUri: providers.kaggle.redirectUri || redirectUri,
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// Configure custom providers
|
|
88
|
+
if (providers.custom) {
|
|
89
|
+
providers.custom.forEach(config => {
|
|
90
|
+
configureProviderAction(config);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}, [providers, baseUrl, callbackPath, configureProviderAction]);
|
|
94
|
+
// Auto-handle OAuth callback from URL
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
if (!autoHandleCallback || typeof window === 'undefined')
|
|
97
|
+
return;
|
|
98
|
+
const params = new URLSearchParams(window.location.search);
|
|
99
|
+
const code = params.get('code');
|
|
100
|
+
const state = params.get('state');
|
|
101
|
+
const error = params.get('error');
|
|
102
|
+
const errorDescription = params.get('error_description');
|
|
103
|
+
if ((code && state) || error) {
|
|
104
|
+
completeAuthorizationAction({
|
|
105
|
+
code: code || '',
|
|
106
|
+
state: state || '',
|
|
107
|
+
error: error || undefined,
|
|
108
|
+
errorDescription: errorDescription || undefined,
|
|
109
|
+
})
|
|
110
|
+
.then(() => {
|
|
111
|
+
// Clean up URL
|
|
112
|
+
const cleanUrl = window.location.pathname;
|
|
113
|
+
window.history.replaceState({}, '', cleanUrl);
|
|
114
|
+
})
|
|
115
|
+
.catch(err => {
|
|
116
|
+
console.error('OAuth callback error:', err);
|
|
117
|
+
// Clean up URL even on error
|
|
118
|
+
const cleanUrl = window.location.pathname;
|
|
119
|
+
window.history.replaceState({}, '', cleanUrl);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}, [autoHandleCallback, completeAuthorizationAction]);
|
|
123
|
+
// Connect via redirect
|
|
124
|
+
const connect = useCallback(async (provider, scopes) => {
|
|
125
|
+
const authUrl = await startAuthorization(provider, scopes);
|
|
126
|
+
// Redirect to authorization URL
|
|
127
|
+
window.location.href = authUrl;
|
|
128
|
+
}, [startAuthorization]);
|
|
129
|
+
// Connect via popup
|
|
130
|
+
const connectWithPopup = useCallback(async (provider, scopes) => {
|
|
131
|
+
// Start authorization first (async), then create promise for popup flow
|
|
132
|
+
const authUrl = await startAuthorization(provider, scopes, {
|
|
133
|
+
onComplete: () => { },
|
|
134
|
+
onError: () => { },
|
|
135
|
+
});
|
|
136
|
+
return new Promise((resolve, reject) => {
|
|
137
|
+
// Update callbacks for the pending authorization
|
|
138
|
+
const store = useIdentityStore.getState();
|
|
139
|
+
if (store.pendingAuthorization) {
|
|
140
|
+
store.pendingAuthorization.onComplete = resolve;
|
|
141
|
+
store.pendingAuthorization.onError = reject;
|
|
142
|
+
}
|
|
143
|
+
// Open popup
|
|
144
|
+
const width = 600;
|
|
145
|
+
const height = 700;
|
|
146
|
+
const left = window.screenX + (window.outerWidth - width) / 2;
|
|
147
|
+
const top = window.screenY + (window.outerHeight - height) / 2;
|
|
148
|
+
const popup = window.open(authUrl, 'oauth_popup', `width=${width},height=${height},left=${left},top=${top},toolbar=no,menubar=no`);
|
|
149
|
+
if (!popup) {
|
|
150
|
+
reject(new Error('Failed to open popup window'));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// Listen for callback via postMessage from OAuthCallback component
|
|
154
|
+
const handleMessage = (event) => {
|
|
155
|
+
if (event.origin !== window.location.origin)
|
|
156
|
+
return;
|
|
157
|
+
// Handle success message from OAuthCallback
|
|
158
|
+
if (event.data?.type === 'oauth-callback-success') {
|
|
159
|
+
window.removeEventListener('message', handleMessage);
|
|
160
|
+
clearInterval(pollTimer);
|
|
161
|
+
popup.close();
|
|
162
|
+
const providerName = event.data.provider;
|
|
163
|
+
const identityFromPopup = event.data.identity;
|
|
164
|
+
console.debug('[Identity] Received oauth-callback-success for provider:', providerName);
|
|
165
|
+
console.debug('[Identity] Identity from popup:', identityFromPopup);
|
|
166
|
+
if (identityFromPopup) {
|
|
167
|
+
// Use the identity directly from the popup message
|
|
168
|
+
// Create a new Map to ensure React detects the change
|
|
169
|
+
const currentIdentities = useIdentityStore.getState().identities;
|
|
170
|
+
const newIdentities = new Map(currentIdentities);
|
|
171
|
+
newIdentities.set(providerName, identityFromPopup);
|
|
172
|
+
// Update the store
|
|
173
|
+
useIdentityStore.setState({
|
|
174
|
+
identities: newIdentities,
|
|
175
|
+
pendingAuthorization: null,
|
|
176
|
+
});
|
|
177
|
+
console.debug('[Identity] Store updated with identity from popup, identities count:', newIdentities.size);
|
|
178
|
+
resolve(identityFromPopup);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// Fallback: read from localStorage if identity not in message
|
|
182
|
+
setTimeout(() => {
|
|
183
|
+
const STORAGE_KEY = 'agent-runtimes-identity';
|
|
184
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
185
|
+
console.debug('[Identity] Fallback: reading from localStorage');
|
|
186
|
+
if (stored) {
|
|
187
|
+
try {
|
|
188
|
+
const data = JSON.parse(stored);
|
|
189
|
+
const identitiesArray = data.state?.identities || [];
|
|
190
|
+
const identitiesMap = new Map(identitiesArray);
|
|
191
|
+
const identity = identitiesMap.get(providerName);
|
|
192
|
+
if (identity) {
|
|
193
|
+
const currentIdentities = useIdentityStore.getState().identities;
|
|
194
|
+
const newIdentities = new Map(currentIdentities);
|
|
195
|
+
newIdentities.set(providerName, identity);
|
|
196
|
+
useIdentityStore.setState({
|
|
197
|
+
identities: newIdentities,
|
|
198
|
+
pendingAuthorization: null,
|
|
199
|
+
});
|
|
200
|
+
resolve(identity);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
catch (e) {
|
|
205
|
+
console.error('[Identity] Failed to parse identity from localStorage:', e);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Final fallback
|
|
209
|
+
useIdentityStore.setState({ pendingAuthorization: null });
|
|
210
|
+
reject(new Error('Identity not found after OAuth success'));
|
|
211
|
+
}, 100);
|
|
212
|
+
}
|
|
213
|
+
// Handle error message from OAuthCallback
|
|
214
|
+
else if (event.data?.type === 'oauth-callback-error') {
|
|
215
|
+
window.removeEventListener('message', handleMessage);
|
|
216
|
+
clearInterval(pollTimer);
|
|
217
|
+
popup.close();
|
|
218
|
+
useIdentityStore.setState({ pendingAuthorization: null });
|
|
219
|
+
reject(new Error(event.data.error || 'OAuth authentication failed'));
|
|
220
|
+
}
|
|
221
|
+
// Legacy: handle 'oauth_callback' message type
|
|
222
|
+
else if (event.data?.type === 'oauth_callback') {
|
|
223
|
+
window.removeEventListener('message', handleMessage);
|
|
224
|
+
clearInterval(pollTimer);
|
|
225
|
+
popup.close();
|
|
226
|
+
completeAuthorizationAction(event.data.payload)
|
|
227
|
+
.then(resolve)
|
|
228
|
+
.catch(reject);
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
window.addEventListener('message', handleMessage);
|
|
232
|
+
// Also poll for popup close (user cancelled)
|
|
233
|
+
const pollTimer = setInterval(() => {
|
|
234
|
+
if (popup.closed) {
|
|
235
|
+
clearInterval(pollTimer);
|
|
236
|
+
window.removeEventListener('message', handleMessage);
|
|
237
|
+
// Don't reject if we already got a message
|
|
238
|
+
if (useIdentityStore.getState().pendingAuthorization) {
|
|
239
|
+
cancelAuthorizationAction();
|
|
240
|
+
reject(new Error('Popup closed by user'));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}, 500);
|
|
244
|
+
});
|
|
245
|
+
}, [
|
|
246
|
+
startAuthorization,
|
|
247
|
+
completeAuthorizationAction,
|
|
248
|
+
cancelAuthorizationAction,
|
|
249
|
+
]);
|
|
250
|
+
// Connect with token (for token-based providers like Kaggle)
|
|
251
|
+
const connectWithTokenAction = useIdentityStore(s => s.connectWithToken);
|
|
252
|
+
const connectWithToken = useCallback(async (provider, token, options) => {
|
|
253
|
+
return connectWithTokenAction(provider, token, options);
|
|
254
|
+
}, [connectWithTokenAction]);
|
|
255
|
+
// Disconnect
|
|
256
|
+
const disconnect = useCallback(async (provider) => {
|
|
257
|
+
await disconnectAction(provider);
|
|
258
|
+
}, [disconnectAction]);
|
|
259
|
+
// Complete authorization
|
|
260
|
+
const completeAuthorization = useCallback(async (callback) => {
|
|
261
|
+
return completeAuthorizationAction(callback);
|
|
262
|
+
}, [completeAuthorizationAction]);
|
|
263
|
+
// Cancel authorization
|
|
264
|
+
const cancelAuthorization = useCallback(() => {
|
|
265
|
+
cancelAuthorizationAction();
|
|
266
|
+
}, [cancelAuthorizationAction]);
|
|
267
|
+
// Check if connected
|
|
268
|
+
const isConnected = useCallback((provider) => {
|
|
269
|
+
return isConnectedAction(provider);
|
|
270
|
+
}, [isConnectedAction]);
|
|
271
|
+
// Get identity
|
|
272
|
+
const getIdentity = useCallback((provider) => {
|
|
273
|
+
return getIdentityAction(provider);
|
|
274
|
+
}, [getIdentityAction]);
|
|
275
|
+
// Get access token
|
|
276
|
+
const getAccessToken = useCallback(async (provider) => {
|
|
277
|
+
const token = await getTokenAction(provider);
|
|
278
|
+
return token?.accessToken ?? null;
|
|
279
|
+
}, [getTokenAction]);
|
|
280
|
+
// Configure provider
|
|
281
|
+
const configureProvider = useCallback((config) => {
|
|
282
|
+
configureProviderAction(config);
|
|
283
|
+
}, [configureProviderAction]);
|
|
284
|
+
// Derived state
|
|
285
|
+
const isAuthorizing = pendingAuthorization !== null;
|
|
286
|
+
return useMemo(() => ({
|
|
287
|
+
// State
|
|
288
|
+
identities,
|
|
289
|
+
connectedProviders,
|
|
290
|
+
isAuthorizing,
|
|
291
|
+
isLoading,
|
|
292
|
+
error,
|
|
293
|
+
pendingAuthorization,
|
|
294
|
+
// Actions
|
|
295
|
+
connect,
|
|
296
|
+
connectWithPopup,
|
|
297
|
+
connectWithToken,
|
|
298
|
+
disconnect,
|
|
299
|
+
completeAuthorization,
|
|
300
|
+
cancelAuthorization,
|
|
301
|
+
isConnected,
|
|
302
|
+
getIdentity,
|
|
303
|
+
getAccessToken,
|
|
304
|
+
configureProvider,
|
|
305
|
+
}), [
|
|
306
|
+
identities,
|
|
307
|
+
connectedProviders,
|
|
308
|
+
isAuthorizing,
|
|
309
|
+
isLoading,
|
|
310
|
+
error,
|
|
311
|
+
pendingAuthorization,
|
|
312
|
+
connect,
|
|
313
|
+
connectWithPopup,
|
|
314
|
+
connectWithToken,
|
|
315
|
+
disconnect,
|
|
316
|
+
completeAuthorization,
|
|
317
|
+
cancelAuthorization,
|
|
318
|
+
isConnected,
|
|
319
|
+
getIdentity,
|
|
320
|
+
getAccessToken,
|
|
321
|
+
configureProvider,
|
|
322
|
+
]);
|
|
323
|
+
}
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
package/lib/lib/utils.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
-
import
|
|
5
|
+
import clsx from "clsx";
|
|
6
6
|
import { twMerge } from "tailwind-merge";
|
|
7
7
|
export function cn(...inputs) {
|
|
8
8
|
return twMerge(clsx(inputs));
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
See the License for the specific language governing permissions and
|
|
18
18
|
limitations under the License.
|
|
19
19
|
*/
|
|
20
|
-
import
|
|
20
|
+
import clsx from "clsx";
|
|
21
21
|
import { twMerge } from "tailwind-merge";
|
|
22
22
|
/**
|
|
23
23
|
* Utility function to merge Tailwind CSS classes.
|
package/lib/test-setup.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import '@testing-library/jest-dom/vitest';
|
package/lib/test-setup.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
// Test setup for unit tests
|
|
6
6
|
// Add any global test configuration here
|
|
7
|
+
import '@testing-library/jest-dom/vitest';
|
|
7
8
|
// Define webpack globals that are expected by some dependencies
|
|
8
9
|
global.__webpack_public_path__ = '';
|
|
9
10
|
// Native FormData and fetch should work in Node.js 20+
|
|
@@ -38,6 +38,34 @@ function isRecentDuplicate(toolName, params) {
|
|
|
38
38
|
executionCache.set(signature, Date.now());
|
|
39
39
|
return false;
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Process parameters to handle JSON strings that should be objects
|
|
43
|
+
* LLMs sometimes generate JSON strings instead of objects for nested parameters
|
|
44
|
+
*/
|
|
45
|
+
function processParameters(params) {
|
|
46
|
+
if (!params || typeof params !== 'object' || Array.isArray(params)) {
|
|
47
|
+
return params;
|
|
48
|
+
}
|
|
49
|
+
const processed = {};
|
|
50
|
+
for (const [key, value] of Object.entries(params)) {
|
|
51
|
+
// If value is a string that looks like JSON, try to parse it
|
|
52
|
+
if (typeof value === 'string' &&
|
|
53
|
+
(value.startsWith('{') || value.startsWith('['))) {
|
|
54
|
+
try {
|
|
55
|
+
processed[key] = JSON.parse(value);
|
|
56
|
+
console.log(`[agent-runtimes] 📝 Parsed JSON string for parameter '${key}'`);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// If parsing fails, keep the original string
|
|
60
|
+
processed[key] = value;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
processed[key] = value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return processed;
|
|
68
|
+
}
|
|
41
69
|
/**
|
|
42
70
|
* Converts unified tool definition to agent-runtimes tool format
|
|
43
71
|
*
|
|
@@ -67,8 +95,11 @@ export function createAgentRuntimesTool(definition, operation, context) {
|
|
|
67
95
|
};
|
|
68
96
|
}
|
|
69
97
|
try {
|
|
98
|
+
// Process parameters to handle JSON strings
|
|
99
|
+
const processedParams = processParameters(params);
|
|
100
|
+
console.log(`[agent-runtimes] Processed params:`, processedParams);
|
|
70
101
|
// Use OperationRunner to execute operation with TOON format
|
|
71
|
-
const result = await runner.execute(operation,
|
|
102
|
+
const result = await runner.execute(operation, processedParams, {
|
|
72
103
|
...context,
|
|
73
104
|
format: 'toon', // Return human/LLM-readable string
|
|
74
105
|
});
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hooks for agent-runtimes lexical tool registration.
|
|
3
|
+
* Provides: useLexicalTools hook for ChatFloating integration.
|
|
4
|
+
*
|
|
5
|
+
* @module tools/adapters/agent-runtimes/lexicalHooks
|
|
6
|
+
*/
|
|
1
7
|
import type { ToolExecutionContext } from '@datalayer/jupyter-react';
|
|
2
8
|
import { type AgentRuntimesTool } from './AgentRuntimesToolAdapter';
|
|
3
9
|
/**
|
|
@@ -2,13 +2,6 @@
|
|
|
2
2
|
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
-
/**
|
|
6
|
-
* React hooks for agent-runtimes lexical tool registration.
|
|
7
|
-
* Provides: useLexicalTools hook for ChatFloating integration.
|
|
8
|
-
*
|
|
9
|
-
* @module tools/adapters/agent-runtimes/lexicalHooks
|
|
10
|
-
*/
|
|
11
|
-
import { useMemo } from 'react';
|
|
12
5
|
import { useLexicalStore, DefaultExecutor as LexicalDefaultExecutor, lexicalToolDefinitions, lexicalToolOperations, } from '@datalayer/jupyter-lexical';
|
|
13
6
|
import { createAllAgentRuntimesTools, } from './AgentRuntimesToolAdapter';
|
|
14
7
|
/**
|
|
@@ -32,19 +25,25 @@ import { createAllAgentRuntimesTools, } from './AgentRuntimesToolAdapter';
|
|
|
32
25
|
* ```
|
|
33
26
|
*/
|
|
34
27
|
export function useLexicalTools(documentId, contextOverrides) {
|
|
35
|
-
|
|
28
|
+
console.log('[useLexicalTools] 🎣 Hook called with documentId:', documentId);
|
|
29
|
+
// Get fresh store state every render - NO MEMOIZATION
|
|
30
|
+
// This ensures we always use the latest patched methods after hot reload
|
|
36
31
|
const lexicalStoreState = useLexicalStore();
|
|
37
|
-
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
//
|
|
42
|
-
|
|
32
|
+
console.log('[useLexicalTools] 📦 Store state obtained:', !!lexicalStoreState);
|
|
33
|
+
// Create new executor every render - NO MEMOIZATION
|
|
34
|
+
console.log('[useLexicalTools] 🔧 Creating new executor for documentId:', documentId);
|
|
35
|
+
const executor = new LexicalDefaultExecutor(documentId, lexicalStoreState);
|
|
36
|
+
// Create new context every render - NO MEMOIZATION
|
|
37
|
+
console.log('[useLexicalTools] 📝 Creating context');
|
|
38
|
+
const context = {
|
|
43
39
|
documentId,
|
|
44
40
|
executor,
|
|
45
41
|
format: 'toon',
|
|
46
42
|
...contextOverrides,
|
|
47
|
-
}
|
|
48
|
-
// Create
|
|
49
|
-
|
|
43
|
+
};
|
|
44
|
+
// Create new tools array every render - NO MEMOIZATION
|
|
45
|
+
console.log('[useLexicalTools] 🛠️ Creating tools array');
|
|
46
|
+
const tools = createAllAgentRuntimesTools(lexicalToolDefinitions, lexicalToolOperations, context);
|
|
47
|
+
console.log('[useLexicalTools] ✅ Created', tools.length, 'tools');
|
|
48
|
+
return tools;
|
|
50
49
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datalayer/agent-runtimes",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
".",
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"create:patches": "bash scripts/create-patches.sh",
|
|
70
70
|
"examples": "run-p server:start examples:vite",
|
|
71
71
|
"examples:fresh": "npm run clean:cache && npm run examples",
|
|
72
|
+
"examples:codemode-mcp": "EXAMPLE=AgentCodemodeMcpExample VITE_APP_TARGET=examples VITE_DATALAYER_RUN_URL=http://localhost:8888 vite",
|
|
72
73
|
"examples:nextjs": "npm run dev --workspace=nextjs-notebook-example",
|
|
73
74
|
"examples:vite": "VITE_APP_TARGET=examples VITE_DATALAYER_RUN_URL=http://localhost:8888 vite",
|
|
74
75
|
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,json,md}\" \"examples/**/*.{js,jsx,ts,tsx,css,json,md,mjs}\"",
|
|
@@ -88,7 +89,7 @@
|
|
|
88
89
|
"preview": "vite preview",
|
|
89
90
|
"rebuild:fresh": "npm run create:patches && npm install && npm run build && npm run clean:cache",
|
|
90
91
|
"server": "python -m agent_runtimes",
|
|
91
|
-
"server:start": "python -m agent_runtimes --port 8765 --reload --debug",
|
|
92
|
+
"server:start": "PYTHONIOENCODING=utf-8 python -m agent_runtimes --port 8765 --reload --debug",
|
|
92
93
|
"showcase:vercel-ai-elements": "VITE_APP_TARGET=showcase-vercel-ai-elements vite",
|
|
93
94
|
"start": "vite",
|
|
94
95
|
"start:acp": "run-p server:start start:acp:vite",
|
|
@@ -122,10 +123,10 @@
|
|
|
122
123
|
"@agentclientprotocol/sdk": "^0.8.0",
|
|
123
124
|
"@ai-sdk/react": "3.0.30",
|
|
124
125
|
"@anthropic-ai/sdk": "^0.52.0",
|
|
125
|
-
"@datalayer/core": "^0.0.
|
|
126
|
+
"@datalayer/core": "^0.0.25",
|
|
126
127
|
"@datalayer/icons-react": "^1.0.6",
|
|
127
|
-
"@datalayer/jupyter-lexical": "^1.0.
|
|
128
|
-
"@datalayer/jupyter-react": "^2.0.
|
|
128
|
+
"@datalayer/jupyter-lexical": "^1.0.9",
|
|
129
|
+
"@datalayer/jupyter-react": "^2.0.3",
|
|
129
130
|
"@datalayer/primer-addons": "^1.0.4",
|
|
130
131
|
"@datalayer/primer-rjsf": "^1.0.1",
|
|
131
132
|
"@jupyter-widgets/base-manager": "^1.0.12",
|
|
@@ -145,7 +146,7 @@
|
|
|
145
146
|
"@lumino/disposable": "^2.1.5",
|
|
146
147
|
"@lumino/polling": "^2.1.5",
|
|
147
148
|
"@lumino/signaling": "^2.1.5",
|
|
148
|
-
"@lumino/widgets": "^2.7.
|
|
149
|
+
"@lumino/widgets": "^2.7.3",
|
|
149
150
|
"@mcp-ui/client": "^5.17.1",
|
|
150
151
|
"@modelcontextprotocol/ext-apps": "^0.2.2",
|
|
151
152
|
"@primer/behaviors": "^1.8.4",
|
|
@@ -159,17 +160,24 @@
|
|
|
159
160
|
"@radix-ui/react-alert-dialog": "^1.1.15",
|
|
160
161
|
"@radix-ui/react-aspect-ratio": "^1.1.8",
|
|
161
162
|
"@radix-ui/react-avatar": "^1.1.11",
|
|
163
|
+
"@radix-ui/react-checkbox": "^1.3.3",
|
|
162
164
|
"@radix-ui/react-collapsible": "^1.1.12",
|
|
165
|
+
"@radix-ui/react-context-menu": "^2.2.16",
|
|
163
166
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
164
167
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
165
168
|
"@radix-ui/react-hover-card": "^1.1.15",
|
|
169
|
+
"@radix-ui/react-icons": "^1.3.2",
|
|
170
|
+
"@radix-ui/react-label": "^2.1.8",
|
|
166
171
|
"@radix-ui/react-menubar": "^1.1.16",
|
|
167
172
|
"@radix-ui/react-navigation-menu": "^1.2.14",
|
|
168
173
|
"@radix-ui/react-progress": "^1.1.8",
|
|
174
|
+
"@radix-ui/react-radio-group": "^1.3.8",
|
|
169
175
|
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
170
176
|
"@radix-ui/react-select": "^2.2.6",
|
|
171
177
|
"@radix-ui/react-separator": "^1.1.8",
|
|
178
|
+
"@radix-ui/react-slider": "^1.3.6",
|
|
172
179
|
"@radix-ui/react-slot": "^1.2.4",
|
|
180
|
+
"@radix-ui/react-switch": "^1.2.6",
|
|
173
181
|
"@radix-ui/react-toast": "^1.2.15",
|
|
174
182
|
"@radix-ui/react-toggle-group": "^1.1.11",
|
|
175
183
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
@@ -183,6 +191,7 @@
|
|
|
183
191
|
"ansi-to-html": "^0.7.2",
|
|
184
192
|
"axios": "^1.7.7",
|
|
185
193
|
"boring-avatars": "^2.0.1",
|
|
194
|
+
"class-variance-authority": "^0.7.1",
|
|
186
195
|
"cmdk": "^1.1.1",
|
|
187
196
|
"date-fns": "^2.29.3",
|
|
188
197
|
"deepmerge": "^4.3.1",
|
|
@@ -199,14 +208,16 @@
|
|
|
199
208
|
"mock-socket": "^9.3.1",
|
|
200
209
|
"motion": "^12.23.26",
|
|
201
210
|
"nanoid": "^5.1.6",
|
|
211
|
+
"next-themes": "^0.4.6",
|
|
202
212
|
"react": "18.3.1",
|
|
203
213
|
"react-confetti": "^6.4.0",
|
|
204
214
|
"react-dom": "18.3.1",
|
|
205
215
|
"react-hook-form": "^7.69.0",
|
|
206
216
|
"react-is": "^19.2.0",
|
|
217
|
+
"react-resizable-panels": "^4.4.1",
|
|
207
218
|
"react-router-dom": "^6.0.0",
|
|
208
219
|
"react-toastify": "^11.0.5",
|
|
209
|
-
"recharts": "^3.
|
|
220
|
+
"recharts": "^3.7.0",
|
|
210
221
|
"shiki": "^3.20.0",
|
|
211
222
|
"sonner": "^2.0.7",
|
|
212
223
|
"streamdown": "^1.6.10",
|
|
@@ -240,6 +251,8 @@
|
|
|
240
251
|
"@storybook/builder-vite": "^9.1.1",
|
|
241
252
|
"@storybook/react-vite": "^9.1.1",
|
|
242
253
|
"@tailwindcss/postcss": "^4.1.16",
|
|
254
|
+
"@testing-library/react": "^16.3.0",
|
|
255
|
+
"@testing-library/jest-dom": "^6.4.8",
|
|
243
256
|
"@types/node": "^20.11.0",
|
|
244
257
|
"@types/react": "18.3.20",
|
|
245
258
|
"@types/react-dom": "18.3.6",
|