@devicai/ui 0.40.2 → 0.41.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 (74) hide show
  1. package/README.md +74 -1
  2. package/dist/cjs/api/client.js +125 -6
  3. package/dist/cjs/api/client.js.map +1 -1
  4. package/dist/cjs/components/AICommandBar/AICommandBar.js +4 -2
  5. package/dist/cjs/components/AICommandBar/AICommandBar.js.map +1 -1
  6. package/dist/cjs/components/AICommandBar/useAICommandBar.js +4 -2
  7. package/dist/cjs/components/AICommandBar/useAICommandBar.js.map +1 -1
  8. package/dist/cjs/components/AIElementWrapper/useAIElementWrapper.js +4 -2
  9. package/dist/cjs/components/AIElementWrapper/useAIElementWrapper.js.map +1 -1
  10. package/dist/cjs/components/AIGenerationButton/useAIGenerationButton.js +4 -2
  11. package/dist/cjs/components/AIGenerationButton/useAIGenerationButton.js.map +1 -1
  12. package/dist/cjs/components/ChatDrawer/ChatDrawer.js +18 -9
  13. package/dist/cjs/components/ChatDrawer/ChatDrawer.js.map +1 -1
  14. package/dist/cjs/components/ChatDrawer/ChatInput.js +9 -3
  15. package/dist/cjs/components/ChatDrawer/ChatInput.js.map +1 -1
  16. package/dist/cjs/components/ChatDrawer/ChatMessages.js +9 -3
  17. package/dist/cjs/components/ChatDrawer/ChatMessages.js.map +1 -1
  18. package/dist/cjs/components/ChatDrawer/ConversationSelector.js +9 -7
  19. package/dist/cjs/components/ChatDrawer/ConversationSelector.js.map +1 -1
  20. package/dist/cjs/components/ChatDrawer/HandoffSubagentWidget.js +10 -3
  21. package/dist/cjs/components/ChatDrawer/HandoffSubagentWidget.js.map +1 -1
  22. package/dist/cjs/components/ChatDrawer/UsageBar.js +8 -2
  23. package/dist/cjs/components/ChatDrawer/UsageBar.js.map +1 -1
  24. package/dist/cjs/components/CoreMemoryModal/CoreMemoryModal.js +7 -3
  25. package/dist/cjs/components/CoreMemoryModal/CoreMemoryModal.js.map +1 -1
  26. package/dist/cjs/components/IntegrationsModal/IntegrationsHint.js +36 -21
  27. package/dist/cjs/components/IntegrationsModal/IntegrationsHint.js.map +1 -1
  28. package/dist/cjs/components/IntegrationsModal/useIntegrations.js +12 -5
  29. package/dist/cjs/components/IntegrationsModal/useIntegrations.js.map +1 -1
  30. package/dist/cjs/components/ThreadStateTag/ThreadStateTag.js +10 -3
  31. package/dist/cjs/components/ThreadStateTag/ThreadStateTag.js.map +1 -1
  32. package/dist/cjs/hooks/useDevicChat.js +4 -2
  33. package/dist/cjs/hooks/useDevicChat.js.map +1 -1
  34. package/dist/cjs/provider/DevicProvider.js +27 -3
  35. package/dist/cjs/provider/DevicProvider.js.map +1 -1
  36. package/dist/esm/api/client.d.ts +63 -3
  37. package/dist/esm/api/client.js +125 -6
  38. package/dist/esm/api/client.js.map +1 -1
  39. package/dist/esm/components/AICommandBar/AICommandBar.js +4 -2
  40. package/dist/esm/components/AICommandBar/AICommandBar.js.map +1 -1
  41. package/dist/esm/components/AICommandBar/useAICommandBar.js +4 -2
  42. package/dist/esm/components/AICommandBar/useAICommandBar.js.map +1 -1
  43. package/dist/esm/components/AIElementWrapper/useAIElementWrapper.js +4 -2
  44. package/dist/esm/components/AIElementWrapper/useAIElementWrapper.js.map +1 -1
  45. package/dist/esm/components/AIGenerationButton/useAIGenerationButton.js +4 -2
  46. package/dist/esm/components/AIGenerationButton/useAIGenerationButton.js.map +1 -1
  47. package/dist/esm/components/ChatDrawer/ChatDrawer.js +18 -9
  48. package/dist/esm/components/ChatDrawer/ChatDrawer.js.map +1 -1
  49. package/dist/esm/components/ChatDrawer/ChatInput.js +9 -3
  50. package/dist/esm/components/ChatDrawer/ChatInput.js.map +1 -1
  51. package/dist/esm/components/ChatDrawer/ChatMessages.js +9 -3
  52. package/dist/esm/components/ChatDrawer/ChatMessages.js.map +1 -1
  53. package/dist/esm/components/ChatDrawer/ConversationSelector.js +9 -7
  54. package/dist/esm/components/ChatDrawer/ConversationSelector.js.map +1 -1
  55. package/dist/esm/components/ChatDrawer/HandoffSubagentWidget.js +10 -3
  56. package/dist/esm/components/ChatDrawer/HandoffSubagentWidget.js.map +1 -1
  57. package/dist/esm/components/ChatDrawer/UsageBar.js +8 -2
  58. package/dist/esm/components/ChatDrawer/UsageBar.js.map +1 -1
  59. package/dist/esm/components/CoreMemoryModal/CoreMemoryModal.js +7 -3
  60. package/dist/esm/components/CoreMemoryModal/CoreMemoryModal.js.map +1 -1
  61. package/dist/esm/components/IntegrationsModal/IntegrationsHint.js +36 -21
  62. package/dist/esm/components/IntegrationsModal/IntegrationsHint.js.map +1 -1
  63. package/dist/esm/components/IntegrationsModal/useIntegrations.js +12 -5
  64. package/dist/esm/components/IntegrationsModal/useIntegrations.js.map +1 -1
  65. package/dist/esm/components/ThreadStateTag/ThreadStateTag.js +10 -3
  66. package/dist/esm/components/ThreadStateTag/ThreadStateTag.js.map +1 -1
  67. package/dist/esm/hooks/useDevicChat.js +4 -2
  68. package/dist/esm/hooks/useDevicChat.js.map +1 -1
  69. package/dist/esm/index.d.ts +1 -1
  70. package/dist/esm/provider/DevicProvider.d.ts +1 -1
  71. package/dist/esm/provider/DevicProvider.js +27 -3
  72. package/dist/esm/provider/DevicProvider.js.map +1 -1
  73. package/dist/esm/provider/types.d.ts +62 -5
  74. package/package.json +1 -1
@@ -14,4 +14,4 @@ import type { DevicProviderProps } from './types';
14
14
  * </DevicProvider>
15
15
  * ```
16
16
  */
17
- export declare function DevicProvider({ apiKey, baseUrl, tenantId, tenantMetadata, subtenantId, subtenantMetadata, tags, debug, children, }: DevicProviderProps): JSX.Element;
17
+ export declare function DevicProvider({ apiKey, getTenantSession, onSessionExpired, baseUrl, tenantId, tenantMetadata, subtenantId, subtenantMetadata, tags, debug, children, }: DevicProviderProps): JSX.Element;
@@ -20,7 +20,7 @@ const DEFAULT_BASE_URL = 'https://api.devic.ai';
20
20
  * </DevicProvider>
21
21
  * ```
22
22
  */
23
- function DevicProvider({ apiKey, baseUrl = DEFAULT_BASE_URL, tenantId, tenantMetadata, subtenantId, subtenantMetadata, tags, debug, children, }) {
23
+ function DevicProvider({ apiKey, getTenantSession, onSessionExpired, baseUrl = DEFAULT_BASE_URL, tenantId, tenantMetadata, subtenantId, subtenantMetadata, tags, debug, children, }) {
24
24
  const [references, setReferences] = useState([]);
25
25
  const drawerRef = useRef(null);
26
26
  const addReference = useCallback((ref) => {
@@ -45,17 +45,38 @@ function DevicProvider({ apiKey, baseUrl = DEFAULT_BASE_URL, tenantId, tenantMet
45
45
  const openDrawer = useCallback(() => {
46
46
  drawerRef.current?.open();
47
47
  }, []);
48
- const client = useMemo(() => new DevicApiClient({ apiKey, baseUrl }), [apiKey, baseUrl]);
48
+ // Both callbacks are read through a ref and handed on as stable wrappers.
49
+ // An inline `getTenantSession={() => …}` is a new function on every render,
50
+ // and passing it straight through would rebuild the client — throwing away
51
+ // the session it holds, so the page fetches a token per render — and rebuild
52
+ // the context, so every component below it would do the same.
53
+ const sessionSourceRef = useRef(getTenantSession);
54
+ sessionSourceRef.current = getTenantSession;
55
+ const expiredRef = useRef(onSessionExpired);
56
+ expiredRef.current = onSessionExpired;
57
+ const usesSessions = !!getTenantSession;
58
+ const tenantSession = useMemo(() => usesSessions
59
+ ? () => sessionSourceRef.current()
60
+ : undefined, [usesSessions]);
61
+ const sessionExpired = useMemo(() => () => expiredRef.current?.(), []);
62
+ const client = useMemo(() => new DevicApiClient({
63
+ apiKey,
64
+ baseUrl,
65
+ getTenantSession: tenantSession,
66
+ onSessionExpired: sessionExpired,
67
+ }), [apiKey, baseUrl, tenantSession, sessionExpired]);
49
68
  const contextValue = useMemo(() => ({
50
69
  client,
51
70
  apiKey,
71
+ getTenantSession: tenantSession,
72
+ onSessionExpired: sessionExpired,
52
73
  baseUrl,
53
74
  tenantId,
54
75
  tenantMetadata,
55
76
  subtenantId,
56
77
  subtenantMetadata,
57
78
  tags,
58
- isConfigured: !!apiKey,
79
+ isConfigured: !!apiKey || usesSessions,
59
80
  debug,
60
81
  references,
61
82
  addReference,
@@ -66,6 +87,9 @@ function DevicProvider({ apiKey, baseUrl = DEFAULT_BASE_URL, tenantId, tenantMet
66
87
  }), [
67
88
  client,
68
89
  apiKey,
90
+ tenantSession,
91
+ sessionExpired,
92
+ usesSessions,
69
93
  baseUrl,
70
94
  tenantId,
71
95
  tenantMetadata,
@@ -1 +1 @@
1
- {"version":3,"file":"DevicProvider.js","sources":["../../../src/provider/DevicProvider.tsx"],"sourcesContent":["import React, { useMemo, useState, useRef, useCallback } from 'react';\nimport { DevicContext } from './DevicContext';\nimport { DevicApiClient } from '../api/client';\nimport { generateId } from '../utils';\nimport type {\n DevicProviderProps,\n DevicContextValue,\n AIReference,\n DrawerRegistration,\n} from './types';\n\nconst DEFAULT_BASE_URL = 'https://api.devic.ai';\n\n/**\n * Provider component for Devic UI configuration\n *\n * @example\n * ```tsx\n * <DevicProvider\n * apiKey=\"devic-xxx\"\n * baseUrl=\"https://api.devic.ai\"\n * tenantId=\"tenant-123\"\n * tenantMetadata={{ userId: '456' }}\n * >\n * <App />\n * </DevicProvider>\n * ```\n */\nexport function DevicProvider({\n apiKey,\n baseUrl = DEFAULT_BASE_URL,\n tenantId,\n tenantMetadata,\n subtenantId,\n subtenantMetadata,\n tags,\n debug,\n children,\n}: DevicProviderProps): JSX.Element {\n const [references, setReferences] = useState<AIReference[]>([]);\n const drawerRef = useRef<DrawerRegistration | null>(null);\n\n const addReference = useCallback((ref: Omit<AIReference, 'id'>): string => {\n const id = generateId();\n setReferences((prev) => [...prev, { ...ref, id }]);\n return id;\n }, []);\n\n const removeReference = useCallback((id: string) => {\n setReferences((prev) => prev.filter((r) => r.id !== id));\n }, []);\n\n const clearReferences = useCallback(() => {\n setReferences([]);\n }, []);\n\n const registerDrawer = useCallback((handle: DrawerRegistration) => {\n drawerRef.current = handle;\n return () => {\n if (drawerRef.current === handle) {\n drawerRef.current = null;\n }\n };\n }, []);\n\n const openDrawer = useCallback(() => {\n drawerRef.current?.open();\n }, []);\n\n const client = useMemo(\n () => new DevicApiClient({ apiKey, baseUrl }),\n [apiKey, baseUrl]\n );\n\n const contextValue = useMemo<DevicContextValue>(\n () => ({\n client,\n apiKey,\n baseUrl,\n tenantId,\n tenantMetadata,\n subtenantId,\n subtenantMetadata,\n tags,\n isConfigured: !!apiKey,\n debug,\n references,\n addReference,\n removeReference,\n clearReferences,\n registerDrawer,\n openDrawer,\n }),\n [\n client,\n apiKey,\n baseUrl,\n tenantId,\n tenantMetadata,\n subtenantId,\n subtenantMetadata,\n tags,\n debug,\n references,\n addReference,\n removeReference,\n clearReferences,\n registerDrawer,\n openDrawer,\n ]\n );\n\n return (\n <DevicContext.Provider value={contextValue}>\n {children}\n </DevicContext.Provider>\n );\n}\n"],"names":["_jsx"],"mappings":";;;;;;AAWA,MAAM,gBAAgB,GAAG,sBAAsB;AAE/C;;;;;;;;;;;;;;AAcG;AACG,SAAU,aAAa,CAAC,EAC5B,MAAM,EACN,OAAO,GAAG,gBAAgB,EAC1B,QAAQ,EACR,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,IAAI,EACJ,KAAK,EACL,QAAQ,GACW,EAAA;IACnB,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,EAAE,CAAC;AAC/D,IAAA,MAAM,SAAS,GAAG,MAAM,CAA4B,IAAI,CAAC;AAEzD,IAAA,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,GAA4B,KAAY;AACxE,QAAA,MAAM,EAAE,GAAG,UAAU,EAAE;AACvB,QAAA,aAAa,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,EAAE,GAAG,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;AAClD,QAAA,OAAO,EAAE;IACX,CAAC,EAAE,EAAE,CAAC;AAEN,IAAA,MAAM,eAAe,GAAG,WAAW,CAAC,CAAC,EAAU,KAAI;QACjD,aAAa,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1D,CAAC,EAAE,EAAE,CAAC;AAEN,IAAA,MAAM,eAAe,GAAG,WAAW,CAAC,MAAK;QACvC,aAAa,CAAC,EAAE,CAAC;IACnB,CAAC,EAAE,EAAE,CAAC;AAEN,IAAA,MAAM,cAAc,GAAG,WAAW,CAAC,CAAC,MAA0B,KAAI;AAChE,QAAA,SAAS,CAAC,OAAO,GAAG,MAAM;AAC1B,QAAA,OAAO,MAAK;AACV,YAAA,IAAI,SAAS,CAAC,OAAO,KAAK,MAAM,EAAE;AAChC,gBAAA,SAAS,CAAC,OAAO,GAAG,IAAI;YAC1B;AACF,QAAA,CAAC;IACH,CAAC,EAAE,EAAE,CAAC;AAEN,IAAA,MAAM,UAAU,GAAG,WAAW,CAAC,MAAK;AAClC,QAAA,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE;IAC3B,CAAC,EAAE,EAAE,CAAC;IAEN,MAAM,MAAM,GAAG,OAAO,CACpB,MAAM,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAC7C,CAAC,MAAM,EAAE,OAAO,CAAC,CAClB;AAED,IAAA,MAAM,YAAY,GAAG,OAAO,CAC1B,OAAO;QACL,MAAM;QACN,MAAM;QACN,OAAO;QACP,QAAQ;QACR,cAAc;QACd,WAAW;QACX,iBAAiB;QACjB,IAAI;QACJ,YAAY,EAAE,CAAC,CAAC,MAAM;QACtB,KAAK;QACL,UAAU;QACV,YAAY;QACZ,eAAe;QACf,eAAe;QACf,cAAc;QACd,UAAU;AACX,KAAA,CAAC,EACF;QACE,MAAM;QACN,MAAM;QACN,OAAO;QACP,QAAQ;QACR,cAAc;QACd,WAAW;QACX,iBAAiB;QACjB,IAAI;QACJ,KAAK;QACL,UAAU;QACV,YAAY;QACZ,eAAe;QACf,eAAe;QACf,cAAc;QACd,UAAU;AACX,KAAA,CACF;AAED,IAAA,QACEA,GAAA,CAAC,YAAY,CAAC,QAAQ,EAAA,EAAC,KAAK,EAAE,YAAY,EAAA,QAAA,EACvC,QAAQ,EAAA,CACa;AAE5B;;;;"}
1
+ {"version":3,"file":"DevicProvider.js","sources":["../../../src/provider/DevicProvider.tsx"],"sourcesContent":["import React, { useMemo, useState, useRef, useCallback } from 'react';\nimport { DevicContext } from './DevicContext';\nimport { DevicApiClient } from '../api/client';\nimport { generateId } from '../utils';\nimport type {\n DevicProviderProps,\n DevicContextValue,\n AIReference,\n DrawerRegistration,\n} from './types';\n\nconst DEFAULT_BASE_URL = 'https://api.devic.ai';\n\n/**\n * Provider component for Devic UI configuration\n *\n * @example\n * ```tsx\n * <DevicProvider\n * apiKey=\"devic-xxx\"\n * baseUrl=\"https://api.devic.ai\"\n * tenantId=\"tenant-123\"\n * tenantMetadata={{ userId: '456' }}\n * >\n * <App />\n * </DevicProvider>\n * ```\n */\nexport function DevicProvider({\n apiKey,\n getTenantSession,\n onSessionExpired,\n baseUrl = DEFAULT_BASE_URL,\n tenantId,\n tenantMetadata,\n subtenantId,\n subtenantMetadata,\n tags,\n debug,\n children,\n}: DevicProviderProps): JSX.Element {\n const [references, setReferences] = useState<AIReference[]>([]);\n const drawerRef = useRef<DrawerRegistration | null>(null);\n\n const addReference = useCallback((ref: Omit<AIReference, 'id'>): string => {\n const id = generateId();\n setReferences((prev) => [...prev, { ...ref, id }]);\n return id;\n }, []);\n\n const removeReference = useCallback((id: string) => {\n setReferences((prev) => prev.filter((r) => r.id !== id));\n }, []);\n\n const clearReferences = useCallback(() => {\n setReferences([]);\n }, []);\n\n const registerDrawer = useCallback((handle: DrawerRegistration) => {\n drawerRef.current = handle;\n return () => {\n if (drawerRef.current === handle) {\n drawerRef.current = null;\n }\n };\n }, []);\n\n const openDrawer = useCallback(() => {\n drawerRef.current?.open();\n }, []);\n\n // Both callbacks are read through a ref and handed on as stable wrappers.\n // An inline `getTenantSession={() => …}` is a new function on every render,\n // and passing it straight through would rebuild the client — throwing away\n // the session it holds, so the page fetches a token per render — and rebuild\n // the context, so every component below it would do the same.\n const sessionSourceRef = useRef(getTenantSession);\n sessionSourceRef.current = getTenantSession;\n const expiredRef = useRef(onSessionExpired);\n expiredRef.current = onSessionExpired;\n const usesSessions = !!getTenantSession;\n\n const tenantSession = useMemo(\n () =>\n usesSessions\n ? () => sessionSourceRef.current!()\n : undefined,\n [usesSessions]\n );\n const sessionExpired = useMemo(() => () => expiredRef.current?.(), []);\n\n const client = useMemo(\n () =>\n new DevicApiClient({\n apiKey,\n baseUrl,\n getTenantSession: tenantSession,\n onSessionExpired: sessionExpired,\n }),\n [apiKey, baseUrl, tenantSession, sessionExpired]\n );\n\n const contextValue = useMemo<DevicContextValue>(\n () => ({\n client,\n apiKey,\n getTenantSession: tenantSession,\n onSessionExpired: sessionExpired,\n baseUrl,\n tenantId,\n tenantMetadata,\n subtenantId,\n subtenantMetadata,\n tags,\n isConfigured: !!apiKey || usesSessions,\n debug,\n references,\n addReference,\n removeReference,\n clearReferences,\n registerDrawer,\n openDrawer,\n }),\n [\n client,\n apiKey,\n tenantSession,\n sessionExpired,\n usesSessions,\n baseUrl,\n tenantId,\n tenantMetadata,\n subtenantId,\n subtenantMetadata,\n tags,\n debug,\n references,\n addReference,\n removeReference,\n clearReferences,\n registerDrawer,\n openDrawer,\n ]\n );\n\n return (\n <DevicContext.Provider value={contextValue}>\n {children}\n </DevicContext.Provider>\n );\n}\n"],"names":["_jsx"],"mappings":"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"}
@@ -42,9 +42,56 @@ export interface SubtenantMetadata {
42
42
  */
43
43
  export interface DevicProviderConfig {
44
44
  /**
45
- * API key for authentication
46
- */
47
- apiKey: string;
45
+ * API key for authentication.
46
+ *
47
+ * Optional when `getTenantSession` is supplied — a page that authenticates with
48
+ * tenant sessions has no reason to carry a key at all.
49
+ */
50
+ apiKey?: string;
51
+ /**
52
+ * Fetches a tenant session from YOUR backend, which is the only place that
53
+ * knows which of your users is logged in.
54
+ *
55
+ * This is what makes the tenant a fact rather than a claim. With an API key
56
+ * alone the tenant is whatever the page declares, and the key sits in the
57
+ * bundle for anyone to read — so anyone can declare any tenant. A session is
58
+ * signed by your server, expires, and cannot reach beyond what an end user is
59
+ * allowed to do.
60
+ *
61
+ * It does not have to reach your backend on every call: if you mint the
62
+ * session inside your own login and put it in a cookie, this is just
63
+ * `async () => readCookie(…)`. Give it a lifetime matching your own session
64
+ * (`ttlSeconds`, up to 12 h) and pair it with `onSessionExpired`.
65
+ *
66
+ * Return the token, or `{ token, expiresAt }` if you know when it dies. It is
67
+ * called again on its own before expiry and after a rejected request, so it
68
+ * must be safe to call repeatedly.
69
+ *
70
+ * @example
71
+ * ```tsx
72
+ * <DevicProvider
73
+ * getTenantSession={async () => {
74
+ * const r = await fetch('/api/devic-session', { credentials: 'include' });
75
+ * return r.json(); // { token, expiresAt }
76
+ * }}
77
+ * >
78
+ * ```
79
+ */
80
+ getTenantSession?: () => Promise<string | {
81
+ token: string;
82
+ expiresAt?: number;
83
+ expiresIn?: number;
84
+ }>;
85
+ /**
86
+ * Called when the session is dead and cannot be replaced — the API rejected
87
+ * it and `getTenantSession` handed back the same expired token.
88
+ *
89
+ * Matters most when the session comes from a cookie with no way to renew it:
90
+ * without this the widget simply stops answering, at the exact moment the
91
+ * user's own login has also expired. Refresh, send them to log in, or say
92
+ * something — but say it.
93
+ */
94
+ onSessionExpired?: () => void;
48
95
  /**
49
96
  * Base URL for the Devic API
50
97
  * @default 'https://api.devic.ai'
@@ -113,9 +160,19 @@ export interface DevicContextValue {
113
160
  */
114
161
  client: DevicApiClient;
115
162
  /**
116
- * Current API key
163
+ * Current API key. Absent when the page authenticates with tenant sessions.
164
+ */
165
+ apiKey?: string;
166
+ /**
167
+ * The session source, when one was configured. Passed down so a component
168
+ * used outside this provider can still authenticate the same way.
169
+ */
170
+ getTenantSession?: DevicProviderConfig['getTenantSession'];
171
+ /**
172
+ * Reported when the session cannot be replaced. Passed down for the same
173
+ * reason as the session source itself.
117
174
  */
118
- apiKey: string;
175
+ onSessionExpired?: DevicProviderConfig['onSessionExpired'];
119
176
  /**
120
177
  * Base URL for the API
121
178
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devicai/ui",
3
- "version": "0.40.2",
3
+ "version": "0.41.0",
4
4
  "type": "module",
5
5
  "description": "React component library for Devic AI assistants",
6
6
  "engines": {