codicent-app-sdk 0.4.15 → 0.4.18
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 +410 -375
- package/dist/cjs/components/AiInput.js +1 -1
- package/dist/cjs/components/AudioIcon.js +1 -1
- package/dist/cjs/components/ChatInput.js +1 -1
- package/dist/cjs/components/ChatMessage.js +1 -1
- package/dist/cjs/components/CombinedPlaceholderDialog.js +1 -1
- package/dist/cjs/components/DataMessagePicker.d.ts +33 -0
- package/dist/cjs/components/DataMessagePicker.d.ts.map +1 -0
- package/dist/cjs/components/DataMessagePicker.js +1 -0
- package/dist/cjs/components/Footer.js +1 -1
- package/dist/cjs/components/Header.js +1 -1
- package/dist/cjs/components/HtmlView.js +1 -1
- package/dist/cjs/components/MermaidChart.d.ts.map +1 -1
- package/dist/cjs/components/MermaidChart.js +1 -1
- package/dist/cjs/components/MessageInput.js +1 -1
- package/dist/cjs/components/MessageItem.js +1 -1
- package/dist/cjs/components/Profile.js +1 -1
- package/dist/cjs/components/Prompt.js +1 -1
- package/dist/cjs/components/SnapFooter.js +1 -1
- package/dist/cjs/components/TextHeader.js +1 -1
- package/dist/cjs/components/TypingIndicator.js +1 -1
- package/dist/cjs/components/UploadFile.js +1 -1
- package/dist/cjs/components/UrlProcessor.js +1 -1
- package/dist/cjs/components/VoiceIcon.js +1 -1
- package/dist/cjs/components/index.d.ts +2 -0
- package/dist/cjs/components/index.d.ts.map +1 -1
- package/dist/cjs/config/index.d.ts.map +1 -1
- package/dist/cjs/config/index.js +1 -1
- package/dist/cjs/hooks/useAuthState.js +1 -1
- package/dist/cjs/hooks/useCodicentState.js +1 -1
- package/dist/cjs/hooks/useLocalization.d.ts.map +1 -1
- package/dist/cjs/hooks/useLocalization.js +1 -1
- package/dist/cjs/hooks/useRealtimeVoiceAI.d.ts.map +1 -1
- package/dist/cjs/hooks/useRealtimeVoiceAI.js +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/pages/AppFrame.js +1 -1
- package/dist/cjs/pages/Chat.js +1 -1
- package/dist/cjs/pages/Compose.js +1 -1
- package/dist/cjs/pages/CrmPage.js +1 -1
- package/dist/cjs/pages/CrmPagePersistent.js +1 -1
- package/dist/cjs/pages/FormAccept.js +1 -1
- package/dist/cjs/pages/FormInvite.js +1 -1
- package/dist/cjs/pages/HtmlViewer.js +1 -1
- package/dist/cjs/pages/Login.js +1 -1
- package/dist/cjs/pages/Purchase.js +1 -1
- package/dist/cjs/pages/Sales.js +1 -1
- package/dist/cjs/pages/Search.js +1 -1
- package/dist/cjs/pages/Snap.js +1 -1
- package/dist/cjs/services/codicent.d.ts +1 -0
- package/dist/cjs/services/codicent.d.ts.map +1 -1
- package/dist/esm/components/AiInput.js +1 -1
- package/dist/esm/components/AudioIcon.js +1 -1
- package/dist/esm/components/ChatInput.js +1 -1
- package/dist/esm/components/ChatMessage.js +1 -1
- package/dist/esm/components/CombinedPlaceholderDialog.js +1 -1
- package/dist/esm/components/DataMessagePicker.d.ts +33 -0
- package/dist/esm/components/DataMessagePicker.d.ts.map +1 -0
- package/dist/esm/components/DataMessagePicker.js +1 -0
- package/dist/esm/components/Footer.js +1 -1
- package/dist/esm/components/Header.js +1 -1
- package/dist/esm/components/HtmlView.js +1 -1
- package/dist/esm/components/MermaidChart.d.ts.map +1 -1
- package/dist/esm/components/MermaidChart.js +1 -1
- package/dist/esm/components/MessageInput.js +1 -1
- package/dist/esm/components/MessageItem.js +1 -1
- package/dist/esm/components/Profile.js +1 -1
- package/dist/esm/components/Prompt.js +1 -1
- package/dist/esm/components/SnapFooter.js +1 -1
- package/dist/esm/components/TextHeader.js +1 -1
- package/dist/esm/components/TypingIndicator.js +1 -1
- package/dist/esm/components/UploadFile.js +1 -1
- package/dist/esm/components/UrlProcessor.js +1 -1
- package/dist/esm/components/VoiceIcon.js +1 -1
- package/dist/esm/components/index.d.ts +2 -0
- package/dist/esm/components/index.d.ts.map +1 -1
- package/dist/esm/config/index.d.ts.map +1 -1
- package/dist/esm/config/index.js +1 -1
- package/dist/esm/hooks/useAuthState.js +1 -1
- package/dist/esm/hooks/useCodicentState.js +1 -1
- package/dist/esm/hooks/useLocalization.d.ts.map +1 -1
- package/dist/esm/hooks/useLocalization.js +1 -1
- package/dist/esm/hooks/useRealtimeVoiceAI.d.ts.map +1 -1
- package/dist/esm/hooks/useRealtimeVoiceAI.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/pages/AppFrame.js +1 -1
- package/dist/esm/pages/Chat.js +1 -1
- package/dist/esm/pages/Compose.js +1 -1
- package/dist/esm/pages/CrmPage.js +1 -1
- package/dist/esm/pages/CrmPagePersistent.js +1 -1
- package/dist/esm/pages/FormAccept.js +1 -1
- package/dist/esm/pages/FormInvite.js +1 -1
- package/dist/esm/pages/HtmlViewer.js +1 -1
- package/dist/esm/pages/Login.js +1 -1
- package/dist/esm/pages/Purchase.js +1 -1
- package/dist/esm/pages/Sales.js +1 -1
- package/dist/esm/pages/Search.js +1 -1
- package/dist/esm/pages/Snap.js +1 -1
- package/dist/esm/services/codicent.d.ts +1 -0
- package/dist/esm/services/codicent.d.ts.map +1 -1
- package/dist/index.d.ts +264 -233
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,521 +1,556 @@
|
|
|
1
|
-
#
|
|
1
|
+
# codicent-app-sdk
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-

|
|
5
|
-

|
|
3
|
+
React SDK for building AI-powered, multi-tenant white-label applications on top of the Codicent platform.
|
|
6
4
|
|
|
7
|
-
**
|
|
8
|
-
|
|
9
|
-
Codicent App SDK provides React components, hooks, and utilities to help you quickly build, customize, and deploy modern AI-powered apps. It is designed for rapid prototyping and production use, with built-in support for chat, markdown rendering, file uploads, and more.
|
|
5
|
+
**Current version:** 0.4.16 · **License:** MIT · **Peer deps:** React ≥16.8, Fluent UI v9, react-router-dom v6
|
|
10
6
|
|
|
11
7
|
---
|
|
12
8
|
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
**New in v0.4.0:** Create a complete Codicent app with a single function call!
|
|
16
|
-
|
|
17
|
-
```tsx
|
|
18
|
-
import { createCodicentApp } from 'codicent-app-sdk';
|
|
19
|
-
|
|
20
|
-
const app = createCodicentApp({
|
|
21
|
-
name: "My CRM",
|
|
22
|
-
apiBaseUrl: "https://codicent.com/",
|
|
23
|
-
buttons: [
|
|
24
|
-
{ title: "Customers", url: "./#/list?tag=customer2" },
|
|
25
|
-
{ title: "Quotes", url: "./#/list?tag=offertjson" },
|
|
26
|
-
{ title: "Chat", url: "./#/chat" },
|
|
27
|
-
],
|
|
28
|
-
listDefinitions: {
|
|
29
|
-
customer2: [
|
|
30
|
-
{ key: "name", title: "Name", filterable: true },
|
|
31
|
-
{ key: "email", title: "Email" },
|
|
32
|
-
{ key: "phone", title: "Phone" },
|
|
33
|
-
],
|
|
34
|
-
},
|
|
35
|
-
translations: {
|
|
36
|
-
en: { "Kunder": "Customers", "Offerter": "Quotes" },
|
|
37
|
-
sv: { "Customers": "Kunder", "Quotes": "Offerter" },
|
|
38
|
-
},
|
|
39
|
-
modules: {
|
|
40
|
-
sales: true,
|
|
41
|
-
voice: true,
|
|
42
|
-
search: true,
|
|
43
|
-
},
|
|
44
|
-
chatInstructions: "You are a helpful CRM assistant.",
|
|
45
|
-
});
|
|
9
|
+
## What it provides
|
|
46
10
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
11
|
+
- `CodicentService` — data CRUD, chat, file upload, token management
|
|
12
|
+
- React components — `Page`, `Content`, `Chat`, `ListView`, `Markdown`, `UploadFile`, and ~25 more
|
|
13
|
+
- Pages — `AppFrame`, `Chat`, `Compose`, `Sales`, `Search`, `Snap`, `Login`, `Logout`, and more
|
|
14
|
+
- Hooks — `useCodicentApp`, `useLocalization`, `useChat`, `useRealtimeVoiceAI`, `useAuthState`, and more
|
|
15
|
+
- Global config — `initCodicentApp()` initializer consumed by all SDK components
|
|
16
|
+
- Full TypeScript types
|
|
50
17
|
|
|
51
|
-
|
|
52
|
-
- ✅ Auth0 authentication
|
|
53
|
-
- ✅ Navigation buttons
|
|
54
|
-
- ✅ List views with filtering and sorting
|
|
55
|
-
- ✅ i18n support
|
|
56
|
-
- ✅ AI chat integration
|
|
57
|
-
- ✅ Module-based feature flags
|
|
18
|
+
This SDK is the primary dependency of `codicentapp/` (the modern white-label Vite app) in the monorepo. See `codicentapp/` for a complete real-world usage reference.
|
|
58
19
|
|
|
59
20
|
---
|
|
60
21
|
|
|
61
22
|
## Installation
|
|
62
23
|
|
|
63
|
-
### From
|
|
24
|
+
### From npm
|
|
64
25
|
```bash
|
|
65
|
-
npm install
|
|
66
|
-
# or
|
|
67
|
-
yarn add github:izaxon/codicent-app-sdk
|
|
26
|
+
npm install codicent-app-sdk
|
|
68
27
|
```
|
|
69
28
|
|
|
70
|
-
###
|
|
29
|
+
### Monorepo local dependency (recommended during development)
|
|
30
|
+
In your app's `package.json`:
|
|
31
|
+
```json
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"codicent-app-sdk": "file:../codicent-app-sdk"
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
Then `npm install` in your app.
|
|
37
|
+
|
|
38
|
+
### Peer dependencies
|
|
39
|
+
Install these alongside the SDK:
|
|
71
40
|
```bash
|
|
72
|
-
npm install
|
|
73
|
-
# or
|
|
74
|
-
yarn add codicent-app-sdk
|
|
41
|
+
npm install react react-dom react-router-dom @fluentui/react-components mermaid
|
|
75
42
|
```
|
|
76
43
|
|
|
77
44
|
---
|
|
78
45
|
|
|
79
46
|
## Usage
|
|
80
47
|
|
|
81
|
-
###
|
|
48
|
+
### 1. Initialize the SDK (once, at app startup)
|
|
82
49
|
|
|
83
|
-
|
|
50
|
+
Call `initCodicentApp()` before rendering your React tree. It stores config globally so all SDK components and hooks can read it.
|
|
84
51
|
|
|
85
52
|
```tsx
|
|
86
|
-
|
|
53
|
+
// main.tsx
|
|
54
|
+
import { initCodicentApp } from 'codicent-app-sdk';
|
|
55
|
+
import { translations } from './services/translationService';
|
|
56
|
+
import { getAppConfig } from './appconfig';
|
|
87
57
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
58
|
+
initCodicentApp({
|
|
59
|
+
API_BASE_URL: 'https://codicent.com/',
|
|
60
|
+
APP_NAME: 'my-crm',
|
|
61
|
+
APP_PREFIX: 'mycrm',
|
|
62
|
+
USER_PREFIX: 'users',
|
|
63
|
+
APP_CONFIG: getAppConfig(), // buttons, listDefinitions, chatInstructions
|
|
64
|
+
TRANSLATIONS: translations, // { sv: {...}, en: {...}, ... }
|
|
65
|
+
USE_REALTIME_SESSION_ENDPOINT: true,
|
|
92
66
|
});
|
|
93
|
-
|
|
94
|
-
app.render("#root");
|
|
95
67
|
```
|
|
96
68
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
### Option 2: Manual Initialization (v1 - Still Supported)
|
|
69
|
+
### 2. Wrap with Auth0 and FluentProvider
|
|
100
70
|
|
|
101
|
-
|
|
71
|
+
The SDK components depend on these providers being present in the React tree:
|
|
102
72
|
|
|
103
73
|
```tsx
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
74
|
+
// main.tsx (continued)
|
|
75
|
+
import { Auth0Provider } from '@auth0/auth0-react';
|
|
76
|
+
import { FluentProvider, webLightTheme } from '@fluentui/react-components';
|
|
77
|
+
import { createRoot } from 'react-dom/client';
|
|
78
|
+
|
|
79
|
+
createRoot(document.getElementById('root')!).render(
|
|
80
|
+
<Auth0Provider domain={AUTH0_DOMAIN} clientId={AUTH0_CLIENT_ID} authorizationParams={{ redirect_uri: window.location.origin }}>
|
|
81
|
+
<FluentProvider theme={webLightTheme}>
|
|
82
|
+
<App />
|
|
83
|
+
</FluentProvider>
|
|
84
|
+
</Auth0Provider>
|
|
85
|
+
);
|
|
111
86
|
```
|
|
112
87
|
|
|
88
|
+
### 3. Use `useCodicentApp()` in your root App component
|
|
113
89
|
|
|
114
|
-
|
|
90
|
+
```tsx
|
|
91
|
+
// App.tsx
|
|
92
|
+
import { useCodicentApp } from 'codicent-app-sdk';
|
|
93
|
+
import { useAuth0 } from '@auth0/auth0-react';
|
|
94
|
+
import { HashRouter, Routes, Route } from 'react-router-dom';
|
|
95
|
+
import { Chat } from 'codicent-app-sdk';
|
|
96
|
+
import { ListPage } from './pages/ListPage';
|
|
115
97
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
APP_NAME: string // e.g. 'my-app'
|
|
120
|
-
APP_PREFIX: string // e.g. 'myapp'
|
|
121
|
-
USER_PREFIX: string // e.g. 'users'
|
|
122
|
-
```
|
|
98
|
+
export default function App() {
|
|
99
|
+
const auth0 = useAuth0();
|
|
100
|
+
const state = useCodicentApp({ auth0 });
|
|
123
101
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
DEFAULT_LANGUAGE: string
|
|
129
|
-
SUBSCRIPTION_NEEDED: boolean
|
|
130
|
-
REALTIME_VOICE_MODEL: string // Voice model: "alloy", "shimmer", or "echo" (default: "alloy")
|
|
131
|
-
USE_REALTIME_SESSION_ENDPOINT: boolean // Use secure session endpoint (default: true)
|
|
102
|
+
if (!auth0.isAuthenticated) {
|
|
103
|
+
auth0.loginWithRedirect();
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
132
106
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
107
|
+
return (
|
|
108
|
+
<HashRouter>
|
|
109
|
+
<Routes>
|
|
110
|
+
<Route path="/chat" element={<Chat state={state} title="Chat" />} />
|
|
111
|
+
<Route path="/list" element={<ListPage state={state} />} />
|
|
112
|
+
</Routes>
|
|
113
|
+
</HashRouter>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
137
116
|
```
|
|
138
117
|
|
|
139
|
-
|
|
118
|
+
### 4. Build pages using SDK components
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
// pages/ListPage.tsx
|
|
122
|
+
import { Page, Content, ListView, useLocalization, CodicentAppState, DataMessage } from 'codicent-app-sdk';
|
|
123
|
+
import { useEffect, useState } from 'react';
|
|
124
|
+
import { APP_CONFIG } from '../appconfig';
|
|
125
|
+
import { APP_BUTTONS } from '../constants';
|
|
140
126
|
|
|
141
|
-
|
|
127
|
+
export const ListPage: React.FC<{ state: CodicentAppState }> = ({ state }) => {
|
|
128
|
+
const { service } = state;
|
|
129
|
+
const { t } = useLocalization();
|
|
130
|
+
const [data, setData] = useState<DataMessage[]>([]);
|
|
142
131
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
| `COMPOSE_HIDE_LOCATION` | `"false"` (default) | Shows the GPS toggle button; users opt-in per post |
|
|
147
|
-
| `COMPOSE_AUTO_LOCATION` | `"true"` | GPS is fetched **automatically** when the compose page opens — no button tap required. The toggle button is still shown so users can remove it if desired |
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
service.readDataMessages('customer2').then(setData);
|
|
134
|
+
}, [service]);
|
|
148
135
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
136
|
+
const columns = APP_CONFIG.apps[APP_BUTTONS].listDefinitions['customer2'];
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<Page title={t('Kunder')}>
|
|
140
|
+
<Content>
|
|
141
|
+
<ListView data={data} columns={columns} />
|
|
142
|
+
</Content>
|
|
143
|
+
</Page>
|
|
144
|
+
);
|
|
145
|
+
};
|
|
153
146
|
```
|
|
154
147
|
|
|
155
|
-
|
|
148
|
+
---
|
|
156
149
|
|
|
157
|
-
|
|
150
|
+
## `initCodicentApp()` configuration options
|
|
158
151
|
|
|
159
|
-
|
|
152
|
+
**Required:**
|
|
160
153
|
|
|
161
|
-
|
|
162
|
-
|
|
154
|
+
| Key | Type | Description |
|
|
155
|
+
|-----|------|-------------|
|
|
156
|
+
| `API_BASE_URL` | `string` | Codicent backend URL, e.g. `"https://codicent.com/"` |
|
|
157
|
+
| `APP_NAME` | `string` | Application identifier |
|
|
163
158
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
|
|
159
|
+
**Common optional:**
|
|
160
|
+
|
|
161
|
+
| Key | Type | Description |
|
|
162
|
+
|-----|------|-------------|
|
|
163
|
+
| `APP_PREFIX` | `string` | URL/namespace prefix for this app |
|
|
164
|
+
| `USER_PREFIX` | `string` | User namespace prefix (default: `"users"`) |
|
|
165
|
+
| `APP_CONFIG` | `AppConfig` | Per-app config: buttons, listDefinitions, chatInstructions |
|
|
166
|
+
| `TRANSLATIONS` | `object` | i18n map `{ sv: {...}, en: {...} }`. Swedish strings are used as keys. |
|
|
167
|
+
| `DEFAULT_LANGUAGE` | `string` | Default language code (e.g. `"sv"`, `"en"`) |
|
|
168
|
+
| `USE_REALTIME_SESSION_ENDPOINT` | `boolean` | Use secure backend session token for voice AI (default: `true`) |
|
|
169
|
+
| `REALTIME_VOICE_MODEL` | `string` | Voice model: `"alloy"`, `"shimmer"`, or `"echo"` (default: `"alloy"`) |
|
|
170
|
+
| `SUBSCRIPTION_NEEDED` | `boolean` | Redirect to purchase page if no active subscription |
|
|
171
|
+
| `BUTTON_BORDER_RADIUS` | `string` | CSS border-radius for nav buttons |
|
|
172
|
+
| `BUTTON_BACKGROUND_COLOR` | `string` | Background color for nav buttons |
|
|
173
|
+
|
|
174
|
+
**Compose page GPS options:**
|
|
173
175
|
|
|
174
|
-
|
|
176
|
+
| Key | Value | Behaviour |
|
|
177
|
+
|-----|-------|-----------|
|
|
178
|
+
| `COMPOSE_HIDE_LOCATION` | `"true"` | Hides GPS toggle button entirely |
|
|
179
|
+
| `COMPOSE_HIDE_LOCATION` | `"false"` (default) | Shows GPS toggle; users opt-in per post |
|
|
180
|
+
| `COMPOSE_AUTO_LOCATION` | `"true"` | Captures GPS automatically on page open |
|
|
175
181
|
|
|
176
|
-
|
|
182
|
+
When a location is attached, `#gps(lat,lon)` is appended to message content — queryable via tag search and readable by AI.
|
|
177
183
|
|
|
178
184
|
---
|
|
179
185
|
|
|
180
186
|
## API Reference
|
|
181
187
|
|
|
182
|
-
### `
|
|
188
|
+
### `CodicentService`
|
|
183
189
|
|
|
184
|
-
|
|
190
|
+
The main service class for all data and chat operations. Access it via `state.service` from `useCodicentApp()`.
|
|
185
191
|
|
|
186
|
-
**
|
|
192
|
+
**Data message CRUD:**
|
|
193
|
+
```ts
|
|
194
|
+
createDataMessage(tag: string, data: object, codicent?: string): Promise<string>
|
|
187
195
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
| `modules` | `ModuleFlags` | | Feature module flags (sales, voice, forms, etc.) |
|
|
199
|
-
| `chatInstructions` | `string` | | AI chat system prompt |
|
|
200
|
-
| `voiceInstructions` | `string` | | AI voice system prompt |
|
|
201
|
-
| `auth0` | `Auth0Config` | | Auth0 configuration |
|
|
202
|
-
| `stripe` | `StripeConfig` | | Stripe configuration |
|
|
203
|
-
| `theme` | `ThemeConfig` | | Theme/branding configuration |
|
|
196
|
+
readDataMessages(
|
|
197
|
+
tag: string,
|
|
198
|
+
search?: string,
|
|
199
|
+
codicent?: string,
|
|
200
|
+
start?: number,
|
|
201
|
+
length?: number,
|
|
202
|
+
afterTimestamp?: string,
|
|
203
|
+
beforeTimestamp?: string,
|
|
204
|
+
dataFilters?: Record<string, string>
|
|
205
|
+
): Promise<DataMessage[]>
|
|
204
206
|
|
|
205
|
-
|
|
206
|
-
- `render(container)` - Render app to a DOM element
|
|
207
|
-
- `unmount()` - Unmount the app
|
|
208
|
-
- `getConfig()` - Get current configuration
|
|
207
|
+
readOneDataMessage(id: string): Promise<DataMessage | null>
|
|
209
208
|
|
|
210
|
-
|
|
209
|
+
updateDataMessage(id: string, data: object, codicent?: string): Promise<string>
|
|
211
210
|
|
|
212
|
-
|
|
213
|
-
const app = createCodicentApp({
|
|
214
|
-
name: "Sales CRM",
|
|
215
|
-
apiBaseUrl: "https://codicent.com/",
|
|
216
|
-
buttons: [
|
|
217
|
-
{ title: "Dashboard", url: "./#/" },
|
|
218
|
-
{ title: "Customers", url: "./#/list?tag=customer2" },
|
|
219
|
-
],
|
|
220
|
-
listDefinitions: {
|
|
221
|
-
customer2: [
|
|
222
|
-
{ key: "name", title: "Customer Name", filterable: true },
|
|
223
|
-
{ key: "email", title: "Email" },
|
|
224
|
-
],
|
|
225
|
-
},
|
|
226
|
-
modules: { sales: true, voice: false },
|
|
227
|
-
});
|
|
211
|
+
deleteDataMessage(id: string, codicent?: string): Promise<string>
|
|
228
212
|
|
|
229
|
-
|
|
213
|
+
getSchema(tag: string, codicent?: string): Promise<object | null>
|
|
230
214
|
```
|
|
231
215
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
216
|
+
**Chat and messages:**
|
|
217
|
+
```ts
|
|
218
|
+
sendMessage(message: string, parentId?: string, codicent?: string): Promise<Message>
|
|
219
|
+
chat(message: string, messageId?: string, codicent?: string): Promise<Message>
|
|
220
|
+
getMessages(tags: string[], codicent?: string, length?: number): Promise<Message[]>
|
|
221
|
+
getMessagesFast(tags: string[], search?: string, length?: number, publicCodicent?: string, codicent?: string, start?: number): Promise<Message[]>
|
|
222
|
+
```
|
|
237
223
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
Translations,
|
|
245
|
-
UserInfo,
|
|
246
|
-
DataMessage,
|
|
247
|
-
CodicentAppState,
|
|
248
|
-
// ... and more
|
|
249
|
-
} from 'codicent-app-sdk';
|
|
224
|
+
**Files:**
|
|
225
|
+
```ts
|
|
226
|
+
uploadFile(filename: string, formData: FormData): Promise<string>
|
|
227
|
+
getFileInfo(fileId: string): Promise<FileInfo>
|
|
228
|
+
static getImageUrl(fileId: string, width: number): string
|
|
229
|
+
static getFileUrl(fileId: string, extension?: string): string
|
|
250
230
|
```
|
|
251
231
|
|
|
252
|
-
|
|
232
|
+
**Auth and tokens:**
|
|
233
|
+
```ts
|
|
234
|
+
getToken(): string
|
|
235
|
+
generateApiToken(expires?: Date, forUserNickname?: string): Promise<string>
|
|
236
|
+
```
|
|
253
237
|
|
|
254
238
|
---
|
|
255
239
|
|
|
256
|
-
|
|
240
|
+
### `useCodicentApp(options)`
|
|
257
241
|
|
|
258
|
-
|
|
242
|
+
Core hook that bootstraps app state, authentication, and the `CodicentService` instance.
|
|
259
243
|
|
|
260
|
-
|
|
244
|
+
```ts
|
|
245
|
+
const state = useCodicentApp({
|
|
246
|
+
auth0: useAuth0(), // Required: Auth0 hook result
|
|
247
|
+
toolsConfig?: object, // Optional: custom AI tool handlers
|
|
248
|
+
authOptions?: object, // Optional: override auth behaviour
|
|
249
|
+
});
|
|
250
|
+
```
|
|
261
251
|
|
|
262
|
-
|
|
252
|
+
Returns `CodicentAppState`:
|
|
253
|
+
```ts
|
|
254
|
+
{
|
|
255
|
+
service: CodicentService; // Use for all data/chat operations
|
|
256
|
+
context: StateContext; // Project nickname, user info
|
|
257
|
+
auth: UseAuthState;
|
|
258
|
+
voice?: RealtimeVoice; // Voice AI connection (when active)
|
|
259
|
+
audio: AudioRecorderState;
|
|
260
|
+
stateMachine: AppStateMachine;
|
|
261
|
+
state: string; // Current state machine state
|
|
262
|
+
nickname: string; // Active project nickname
|
|
263
|
+
error: string;
|
|
264
|
+
isBusy: () => boolean;
|
|
265
|
+
html: string; // AI-generated HTML output
|
|
266
|
+
setHtml: (html: string) => void;
|
|
267
|
+
}
|
|
268
|
+
```
|
|
263
269
|
|
|
264
|
-
|
|
270
|
+
### 5. Use `DataMessagePicker` for tagged record lookup
|
|
265
271
|
|
|
266
272
|
```tsx
|
|
267
|
-
import {
|
|
268
|
-
|
|
269
|
-
<
|
|
273
|
+
import { DataMessagePicker } from 'codicent-app-sdk';
|
|
274
|
+
|
|
275
|
+
<DataMessagePicker
|
|
276
|
+
service={state.service}
|
|
277
|
+
tag="customer2"
|
|
278
|
+
placeholder="Search customers"
|
|
279
|
+
primaryKey="Company Name"
|
|
280
|
+
displayKeys={["Company Name", "City"]}
|
|
281
|
+
secondaryKeys={["Customer Number", "City"]}
|
|
282
|
+
searchKeys={["Company Name", "Customer Number", "City"]}
|
|
283
|
+
onSelect={(selection) => {
|
|
284
|
+
console.log('Selected customer', selection.id, selection.data);
|
|
285
|
+
}}
|
|
286
|
+
/>
|
|
270
287
|
```
|
|
271
288
|
|
|
272
|
-
|
|
289
|
+
The picker debounces lookups through `readDataMessages(...)`, shows compact autosuggest results, and returns the raw `DataMessage` plus a normalized selection payload.
|
|
273
290
|
|
|
274
|
-
|
|
291
|
+
---
|
|
275
292
|
|
|
276
|
-
|
|
293
|
+
### `useLocalization()`
|
|
277
294
|
|
|
278
|
-
```
|
|
279
|
-
|
|
295
|
+
```ts
|
|
296
|
+
const { t, tAsync, getLanguageInfo } = useLocalization();
|
|
297
|
+
|
|
298
|
+
t('Kunder') // → "Customers" (in English)
|
|
299
|
+
await tAsync('Kunder') // → API-backed translation with fallback
|
|
300
|
+
getLanguageInfo() // → { code: 'en', name: 'English', ... }
|
|
280
301
|
```
|
|
281
302
|
|
|
282
|
-
|
|
303
|
+
Swedish strings are used as keys. Pass your translation maps via `TRANSLATIONS` in `initCodicentApp()`.
|
|
283
304
|
|
|
284
305
|
---
|
|
285
306
|
|
|
286
|
-
###
|
|
307
|
+
### Components
|
|
287
308
|
|
|
288
|
-
|
|
309
|
+
#### `Page`
|
|
310
|
+
Full-screen layout wrapper with optional header and footer.
|
|
311
|
+
```tsx
|
|
312
|
+
<Page title="Customers" hideFooter={false} audio={state.audio} voice={state.voice}>
|
|
313
|
+
<Content>...</Content>
|
|
314
|
+
</Page>
|
|
315
|
+
```
|
|
289
316
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
317
|
+
#### `Content`
|
|
318
|
+
Flex content container — use inside `Page`.
|
|
319
|
+
```tsx
|
|
320
|
+
<Content>
|
|
321
|
+
<ListView data={data} columns={columns} />
|
|
322
|
+
</Content>
|
|
323
|
+
```
|
|
295
324
|
|
|
296
|
-
|
|
325
|
+
#### `Chat` (page)
|
|
326
|
+
Full chat UI with message history, input, typing indicators, file uploads.
|
|
327
|
+
```tsx
|
|
328
|
+
<Chat
|
|
329
|
+
state={state}
|
|
330
|
+
title="AI Assistant"
|
|
331
|
+
codicent="my-project" // Optional: override which project to chat with
|
|
332
|
+
welcomeMessage="Hi!" // Optional: shown when no messages exist
|
|
333
|
+
hideFooter={false}
|
|
334
|
+
/>
|
|
335
|
+
```
|
|
297
336
|
|
|
337
|
+
#### `ListView`
|
|
338
|
+
Tabular data view with sorting, filtering, and column actions.
|
|
298
339
|
```tsx
|
|
299
|
-
import
|
|
300
|
-
|
|
340
|
+
import { ListView } from 'codicent-app-sdk';
|
|
341
|
+
|
|
342
|
+
<ListView
|
|
343
|
+
data={dataMessages}
|
|
344
|
+
columns={[
|
|
345
|
+
{ key: 'name', title: 'Name', filterable: true },
|
|
346
|
+
{ key: ['offer_number', 'offerNumber'], title: 'Quote #', filterable: true },
|
|
347
|
+
{ key: 'grand_total', title: 'Total', format: formatNumber },
|
|
348
|
+
{ key: 'pdf', title: 'PDF', type: 'file' },
|
|
349
|
+
]}
|
|
350
|
+
onSelect={(item) => navigate(`/chat?id=${item.originalMessageId}`)}
|
|
351
|
+
/>
|
|
352
|
+
```
|
|
301
353
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
354
|
+
Column definition options:
|
|
355
|
+
- `key: string | string[]` — JSON field name; array = fallback chain
|
|
356
|
+
- `format: (value) => string` — display transformer
|
|
357
|
+
- `filterable: true` — per-column text filter
|
|
358
|
+
- `type: "file"` — renders download link
|
|
359
|
+
- `type: "checkbox"` — renders checkbox
|
|
360
|
+
- `action` — icon button with click handler
|
|
308
361
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
362
|
+
#### `AppFrame`
|
|
363
|
+
Embeds an external URL in an iframe within the page layout.
|
|
364
|
+
```tsx
|
|
365
|
+
<AppFrame src="https://example.com/embed" title="External view" showFooter={true} />
|
|
366
|
+
```
|
|
312
367
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
<Markdown content={msg.content} />
|
|
318
|
-
</div>
|
|
319
|
-
))}
|
|
320
|
-
<button onClick={() => sendMessage('Hello world')}>Send</button>
|
|
321
|
-
</div>
|
|
322
|
-
);
|
|
323
|
-
};
|
|
368
|
+
#### `Markdown`
|
|
369
|
+
Renders markdown content including GFM and Mermaid diagrams.
|
|
370
|
+
```tsx
|
|
371
|
+
<Markdown content={message.content} />
|
|
324
372
|
```
|
|
325
373
|
|
|
326
|
-
|
|
374
|
+
#### `UploadFile`
|
|
375
|
+
File upload UI with progress.
|
|
376
|
+
```tsx
|
|
377
|
+
<UploadFile service={state.service} codicent="my-project" />
|
|
378
|
+
```
|
|
327
379
|
|
|
328
|
-
|
|
380
|
+
---
|
|
329
381
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
382
|
+
### Hooks summary
|
|
383
|
+
|
|
384
|
+
| Hook | Purpose |
|
|
385
|
+
|------|---------|
|
|
386
|
+
| `useCodicentApp()` | Core app state, service, auth |
|
|
387
|
+
| `useLocalization()` | i18n translation |
|
|
388
|
+
| `useChat(service)` | Chat message state and send |
|
|
389
|
+
| `useRealtimeVoiceAI(options)` | Real-time voice AI connection |
|
|
390
|
+
| `useAuthState(auth0)` | Auth lifecycle and token |
|
|
391
|
+
| `useTheme()` | App theme/branding |
|
|
392
|
+
| `useToaster()` | Toast notification helpers |
|
|
393
|
+
| `useStateWithLocalStorage()` | Persistent local state |
|
|
394
|
+
| `useAudioRecorder()` | Microphone recording |
|
|
395
|
+
| `useTemplateVariables()` | Template string utilities |
|
|
396
|
+
| `useTools()` | AI tool handler registration |
|
|
397
|
+
| `useEmbeddings()` | Vector embedding operations |
|
|
337
398
|
|
|
338
399
|
---
|
|
339
400
|
|
|
340
|
-
##
|
|
401
|
+
## TypeScript types
|
|
341
402
|
|
|
342
|
-
|
|
403
|
+
```tsx
|
|
404
|
+
import type {
|
|
405
|
+
CodicentAppState,
|
|
406
|
+
ButtonConfig,
|
|
407
|
+
ColumnDefinition,
|
|
408
|
+
ListDefinitions,
|
|
409
|
+
DataMessage,
|
|
410
|
+
Message,
|
|
411
|
+
} from 'codicent-app-sdk';
|
|
412
|
+
```
|
|
343
413
|
|
|
344
|
-
|
|
414
|
+
**`ButtonConfig`** — navigation button with optional RBAC claims:
|
|
415
|
+
```ts
|
|
416
|
+
{
|
|
417
|
+
title: string;
|
|
418
|
+
url: string; // "#/list?tag=customer2", "voice:...", "mailto:...", etc.
|
|
419
|
+
claim?: string; // Show only if user has this claim
|
|
420
|
+
notClaim?: string; // Hide if user has this claim
|
|
421
|
+
subtitle?: string;
|
|
422
|
+
options?: ButtonConfig[];
|
|
423
|
+
}
|
|
424
|
+
```
|
|
345
425
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
426
|
+
**`DataMessage`** — result from `readDataMessages()`:
|
|
427
|
+
```ts
|
|
428
|
+
{
|
|
429
|
+
id: string;
|
|
430
|
+
originalMessageId: string; // Stable ID across updates — use this for references/tags
|
|
431
|
+
content: string; // Raw: "@project #data #tag\n{json}"
|
|
432
|
+
data: Record<string, unknown>; // Parsed JSON payload
|
|
433
|
+
tags: string[];
|
|
434
|
+
createdAt: string;
|
|
435
|
+
}
|
|
436
|
+
```
|
|
349
437
|
|
|
350
|
-
|
|
351
|
-
- The package is built
|
|
352
|
-
- A GitHub Release is created with the built package
|
|
353
|
-
- The package is published to GitHub Packages
|
|
438
|
+
---
|
|
354
439
|
|
|
355
|
-
|
|
440
|
+
## Alternative: `createCodicentApp()` factory
|
|
356
441
|
|
|
357
|
-
|
|
442
|
+
For standalone deployments where you do not control the React entry point, `createCodicentApp()` wraps the full initialization (including Auth0Provider, FluentProvider, HashRouter) and renders to a DOM element:
|
|
358
443
|
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
|
|
444
|
+
```tsx
|
|
445
|
+
import { createCodicentApp } from 'codicent-app-sdk';
|
|
446
|
+
|
|
447
|
+
const app = createCodicentApp({
|
|
448
|
+
name: 'My CRM',
|
|
449
|
+
apiBaseUrl: 'https://codicent.com/',
|
|
450
|
+
auth0: { domain: '...', clientId: '...' },
|
|
451
|
+
buttons: [
|
|
452
|
+
{ title: 'Customers', url: './#/list?tag=customer2' },
|
|
453
|
+
{ title: 'Chat', url: './#/chat' },
|
|
454
|
+
],
|
|
455
|
+
listDefinitions: {
|
|
456
|
+
customer2: [
|
|
457
|
+
{ key: 'name', title: 'Name', filterable: true },
|
|
458
|
+
{ key: 'email', title: 'Email' },
|
|
459
|
+
],
|
|
460
|
+
},
|
|
461
|
+
chatInstructions: 'You are a helpful CRM assistant.',
|
|
462
|
+
modules: { sales: true, voice: true },
|
|
463
|
+
});
|
|
362
464
|
|
|
363
|
-
#
|
|
364
|
-
|
|
465
|
+
app.render('#root');
|
|
466
|
+
// app.unmount();
|
|
467
|
+
// app.getConfig();
|
|
365
468
|
```
|
|
366
469
|
|
|
367
|
-
|
|
470
|
+
The `codicentapp/` reference implementation uses `initCodicentApp()` + manual React tree setup, which gives more control over routing and layout. `createCodicentApp()` is appropriate for simpler or standalone deployments.
|
|
368
471
|
|
|
369
|
-
|
|
472
|
+
---
|
|
370
473
|
|
|
371
|
-
|
|
474
|
+
## Local development workflow
|
|
475
|
+
|
|
476
|
+
### Build the SDK
|
|
372
477
|
|
|
373
478
|
```bash
|
|
374
|
-
|
|
479
|
+
cd codicent-app-sdk
|
|
375
480
|
npm install
|
|
481
|
+
npm run build # Output: dist/cjs/, dist/esm/, dist/index.d.ts
|
|
482
|
+
npm run dev # Watch mode
|
|
483
|
+
```
|
|
376
484
|
|
|
377
|
-
|
|
378
|
-
npm run dev
|
|
485
|
+
### Test in codicentapp (file: reference)
|
|
379
486
|
|
|
380
|
-
|
|
487
|
+
In `codicentapp/package.json`:
|
|
488
|
+
```json
|
|
489
|
+
"codicent-app-sdk": "file:../codicent-app-sdk"
|
|
490
|
+
```
|
|
491
|
+
Then:
|
|
492
|
+
```bash
|
|
493
|
+
cd codicentapp
|
|
494
|
+
npm install
|
|
381
495
|
npm run build
|
|
382
496
|
```
|
|
383
497
|
|
|
384
|
-
|
|
385
|
-
- CommonJS modules in `dist/cjs`
|
|
386
|
-
- ES modules in `dist/esm`
|
|
387
|
-
- TypeScript definitions
|
|
388
|
-
|
|
389
|
-
### Testing Your Changes Locally
|
|
390
|
-
|
|
391
|
-
You can test SDK changes in your project:
|
|
498
|
+
### Test with npm link
|
|
392
499
|
|
|
393
500
|
```bash
|
|
394
|
-
# In
|
|
501
|
+
# In SDK directory
|
|
395
502
|
npm link
|
|
396
503
|
|
|
397
|
-
# In your
|
|
504
|
+
# In your app directory
|
|
398
505
|
npm link codicent-app-sdk
|
|
399
506
|
```
|
|
400
507
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
Documentation is automatically deployed to GitHub Pages as part of the workflow when changes are pushed to the main branch.
|
|
404
|
-
|
|
405
|
-
For manual deployment:
|
|
406
|
-
|
|
508
|
+
To restore npm version:
|
|
407
509
|
```bash
|
|
408
|
-
|
|
409
|
-
npm
|
|
410
|
-
|
|
411
|
-
# To manually deploy documentation
|
|
412
|
-
npm run deploy
|
|
510
|
+
npm uninstall codicent-app-sdk
|
|
511
|
+
npm install codicent-app-sdk
|
|
413
512
|
```
|
|
414
513
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
To publish this package to npm:
|
|
418
|
-
|
|
419
|
-
1. **Login to npm** (if you haven't already):
|
|
420
|
-
```bash
|
|
421
|
-
npm login
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
2. **Build the package**:
|
|
425
|
-
```bash
|
|
426
|
-
npm run build
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
3. **Publish to npm**:
|
|
430
|
-
```bash
|
|
431
|
-
npm publish --access public
|
|
432
|
-
```
|
|
514
|
+
### Build output layout
|
|
433
515
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
For full documentation, visit [our docs site](https://izaxon.github.io/codicent-app-sdk/).
|
|
442
|
-
|
|
443
|
-
### Additional Documentation
|
|
444
|
-
|
|
445
|
-
- **[Voice Upgrade Guide](VOICE_UPGRADE_GUIDE.md)** - Complete guide for implementing and upgrading realtime voice AI features
|
|
446
|
-
- **[State Management Caching Improvements](STATE_MANAGEMENT_CACHING_IMPROVEMENTS.md)** - Comprehensive analysis and strategies for optimizing state management performance through intelligent caching
|
|
447
|
-
- **[Implementation Guide](IMPLEMENTATION_GUIDE.md)** - ✅ **NEW!** How to enable and use the state management caching system (now implemented!)
|
|
448
|
-
|
|
449
|
-
## License
|
|
450
|
-
|
|
451
|
-
MIT © Codicent Inside AB
|
|
516
|
+
```
|
|
517
|
+
dist/
|
|
518
|
+
cjs/ CommonJS modules
|
|
519
|
+
esm/ ES modules
|
|
520
|
+
index.d.ts TypeScript definitions
|
|
521
|
+
```
|
|
452
522
|
|
|
453
|
-
|
|
523
|
+
### Release
|
|
454
524
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
1. **Build your SDK in watch mode (if needed):**
|
|
462
|
-
- If your SDK uses TypeScript or a bundler (like rollup), run it in watch mode so changes are rebuilt automatically.
|
|
463
|
-
```cmd
|
|
464
|
-
npm run build -- --watch
|
|
465
|
-
```
|
|
466
|
-
Or for TypeScript:
|
|
467
|
-
```cmd
|
|
468
|
-
npx tsc --watch
|
|
469
|
-
```
|
|
470
|
-
|
|
471
|
-
2. **Link your SDK globally:**
|
|
472
|
-
In your SDK root folder:
|
|
473
|
-
```cmd
|
|
474
|
-
npm link
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
3. **Link your SDK in your app project:**
|
|
478
|
-
In your app project folder (the one that uses the SDK):
|
|
479
|
-
```cmd
|
|
480
|
-
npm link codicent-app-sdk
|
|
481
|
-
```
|
|
482
|
-
(Replace `codicent-app-sdk` with the actual name in your SDK’s `package.json` if different.)
|
|
483
|
-
|
|
484
|
-
4. **Test changes instantly:**
|
|
485
|
-
Now, when you make changes to your SDK and rebuild, your app will use the updated local version immediately—no need to publish or reinstall from npm.
|
|
486
|
-
|
|
487
|
-
5. **Unlink when done:**
|
|
488
|
-
When you want to go back to using the npm-published version, run in your app project:
|
|
489
|
-
```cmd
|
|
490
|
-
npm uninstall codicent-app-sdk
|
|
491
|
-
npm install codicent-app-sdk
|
|
492
|
-
```
|
|
493
|
-
|
|
494
|
-
### Option 2: Using a Local File Dependency
|
|
495
|
-
|
|
496
|
-
1. In your app’s `package.json`, set the dependency to point to your local SDK folder:
|
|
497
|
-
```json
|
|
498
|
-
"dependencies": {
|
|
499
|
-
"codicent-app-sdk": "file:../codicent-app-sdk"
|
|
500
|
-
}
|
|
501
|
-
```
|
|
502
|
-
2. Run `npm install` in your app project.
|
|
525
|
+
```bash
|
|
526
|
+
npm version patch # or minor / major
|
|
527
|
+
npm run build
|
|
528
|
+
npm publish --access public
|
|
529
|
+
```
|
|
503
530
|
|
|
504
531
|
---
|
|
505
532
|
|
|
506
|
-
##
|
|
533
|
+
## Debugging
|
|
507
534
|
|
|
508
|
-
|
|
535
|
+
The SDK emits `codicent-log` custom events on `window`:
|
|
509
536
|
|
|
510
537
|
```tsx
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
// event.detail contains the log payload
|
|
514
|
-
console.log('Codicent Log:', event.detail);
|
|
538
|
+
window.addEventListener('codicent-log', (event: CustomEvent) => {
|
|
539
|
+
console.log(event.detail); // { level, message, context }
|
|
515
540
|
});
|
|
516
541
|
```
|
|
517
542
|
|
|
518
|
-
|
|
519
|
-
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
## Related
|
|
546
|
+
|
|
547
|
+
- `codicentapp/` — primary consumer; complete reference implementation
|
|
548
|
+
- `codicent-api-client/` — framework-agnostic fetch-based API client (shared with web components)
|
|
549
|
+
- `codicent-components/` — zero-build Web Components library using the same Codicent API
|
|
550
|
+
- [Voice Upgrade Guide](VOICE_UPGRADE_GUIDE.md) — real-time voice AI setup and security
|
|
520
551
|
|
|
521
552
|
---
|
|
553
|
+
|
|
554
|
+
## License
|
|
555
|
+
|
|
556
|
+
MIT © Codicent Inside AB
|