@m6d/cortex-angular 0.1.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.
- package/README.md +117 -0
- package/fesm2022/m6d-cortex-angular.mjs +10191 -0
- package/package.json +48 -0
- package/theme.css +71 -0
- package/types/m6d-cortex-angular.d.ts +412 -0
package/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# @m6d/cortex-angular
|
|
2
|
+
|
|
3
|
+
Angular AI chat UI library. Provides a self-contained chat widget with streaming messages, tool call visualization, composer attachments, syntax highlighting, and i18n support.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { CortexChatWidgetComponent, CortexAngularConfig } from '@m6d/cortex-angular';
|
|
9
|
+
|
|
10
|
+
@Component({
|
|
11
|
+
imports: [CortexChatWidgetComponent],
|
|
12
|
+
template: `<cortex-chat-widget [config]="config" />`,
|
|
13
|
+
})
|
|
14
|
+
export class MyComponent {
|
|
15
|
+
protected readonly config: CortexAngularConfig = {
|
|
16
|
+
locale: 'en',
|
|
17
|
+
transport: {
|
|
18
|
+
baseUrl: '/api/agents/assistant',
|
|
19
|
+
getHeaders: () => ({ Authorization: `Bearer ${token}` }),
|
|
20
|
+
},
|
|
21
|
+
// The WebSocket URL is derived from baseUrl (…/agents/assistant/ws); set
|
|
22
|
+
// `wsUrl` only to override it, and point it at that same agent-scoped path.
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
No root-level providers needed — each widget instance is fully self-contained. You can render multiple widgets with different configs on the same page.
|
|
28
|
+
|
|
29
|
+
### Configuration
|
|
30
|
+
|
|
31
|
+
`CortexAngularConfig` is the shared `CortexConfig` plus two Angular-only slots
|
|
32
|
+
(`toolComponents`, `injector`). `@m6d/cortex-react` takes the same shared shape.
|
|
33
|
+
|
|
34
|
+
| Property | Type | Description |
|
|
35
|
+
| -------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
|
36
|
+
| `locale` | `'en' \| 'ar'` | Active locale (default: `'en'`) |
|
|
37
|
+
| `transport.baseUrl` | `string \| () => string` | Agent API base URL |
|
|
38
|
+
| `transport.getHeaders` | `() => Headers \| Promise<Headers>` | Request headers provider; `Headers` is `Record<string, string>` |
|
|
39
|
+
| `wsUrl` | `string \| false` | WebSocket URL override; `false` disables the socket (optional) |
|
|
40
|
+
| `viewMode` | `'helper' \| 'full'` | Compact panel or full layout with a sidebar (default: `'helper'`) |
|
|
41
|
+
| `theme` | `'light' \| 'dark' \| 'system'` | Color scheme (default: `'light'`) |
|
|
42
|
+
| `agentName` | `string \| { en, ar }` | Header title while no thread is selected (optional) |
|
|
43
|
+
| `showDebugButton` | `boolean` | Show/hide the debug toggle button (default: `false`) |
|
|
44
|
+
| `mediaRenderers` | `Record<string, MediaRenderer>` | Replace or add the media fences the assistant can draw (optional) |
|
|
45
|
+
| `trustSameOriginEmbeds` | `boolean` | Allow embedded tool pages served from this page's own origin (default: `false`) |
|
|
46
|
+
| `hooks.onToolCall` | `(toolCall, context) => unknown` | Answers a static client tool; return `undefined` for tools you do not own (optional) |
|
|
47
|
+
| `hooks.onThreadSelected` | `(thread) => void \| Promise<void>` | Runs when a thread opens (optional) |
|
|
48
|
+
| `hooks.onThreadDeselected` | `(thread) => void \| Promise<void>` | Runs when a thread closes (optional) |
|
|
49
|
+
| `toolComponents` | `Record<string, Type<CortexToolComponentInputs>>` | Custom Angular components for tool rendering (optional) |
|
|
50
|
+
| `injector` | `Injector` | Injector for `toolComponents` (optional) |
|
|
51
|
+
|
|
52
|
+
`transport.getHeaders` can return any request headers needed by the host app. WebSocket auth continues to derive the `token` query param from a bearer `Authorization` header when present.
|
|
53
|
+
|
|
54
|
+
## Client tools
|
|
55
|
+
|
|
56
|
+
Control-Center tools published with type "embedded" render inside the chat
|
|
57
|
+
as an embedded flow (payment, signature, ...): the widget asks the server to
|
|
58
|
+
initiate, shows the returned page in a sandboxed iframe (inline card or
|
|
59
|
+
modal, per tool config), and submits the page's `cortex:client-tool`
|
|
60
|
+
postMessage outcome back to the run as-is — anything that must actually be
|
|
61
|
+
true lives in the integrating backend's own records. No widget configuration
|
|
62
|
+
is needed. One caveat: an embed served from the host page's **own origin** is
|
|
63
|
+
refused by default, because a same-origin iframe cannot be sandboxed — it
|
|
64
|
+
could reach into the host page, and embed URLs come from Control Center tool
|
|
65
|
+
config, whose administrator is not necessarily the site owner. When both are
|
|
66
|
+
the same party and the embeds are the site's own pages, set
|
|
67
|
+
`trustSameOriginEmbeds: true` to render them anyway (with full access, as any
|
|
68
|
+
of the site's own pages has). Other pending tool calls keep the existing `toolComponents` /
|
|
69
|
+
`hooks.onToolCall` behavior. That hook is also how static client tools work:
|
|
70
|
+
declare an executor-less tool in the server config and answer it here by
|
|
71
|
+
returning its output from `hooks.onToolCall` for that tool name. Consumer `hooks.onToolCall` implementations must
|
|
72
|
+
return `undefined` for tool names they do not own — answering an unknown
|
|
73
|
+
pending call would settle an embedded flow before the user completes it.
|
|
74
|
+
|
|
75
|
+
## Media blocks
|
|
76
|
+
|
|
77
|
+
The assistant can answer with more than text. A fenced block tagged `mermaid`,
|
|
78
|
+
`vega-lite` or `map` renders as a diagram, chart or map inside the message,
|
|
79
|
+
with a placeholder while the block is still streaming and an error card (with
|
|
80
|
+
the source) when it cannot be drawn. An image attachment the model references
|
|
81
|
+
as `` on its own line renders inline.
|
|
82
|
+
|
|
83
|
+
The renderers are peer dependencies your bundler must be able to resolve, but
|
|
84
|
+
they load only when a block of their kind first appears: `mermaid` for
|
|
85
|
+
diagrams, `vega`, `vega-lite` and `vega-embed` for charts, and `leaflet` for
|
|
86
|
+
maps (plus its stylesheet, `leaflet/dist/leaflet.css`, in your page). Maps
|
|
87
|
+
draw OpenStreetMap tiles and need no key. A block whose library fails to load
|
|
88
|
+
at runtime shows the error card.
|
|
89
|
+
|
|
90
|
+
Leaflet finds its marker images next to wherever the build put the one the
|
|
91
|
+
stylesheet references, so an Angular build needs the other two copied there as
|
|
92
|
+
well:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
"assets": [
|
|
96
|
+
{ "glob": "marker-*.png", "input": "node_modules/leaflet/dist/images", "output": "media" }
|
|
97
|
+
]
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`mediaRenderers` swaps a renderer or adds a fence tag of your own. A renderer
|
|
101
|
+
draws a closed fence's source into the host element and returns its teardown:
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
mediaRenderers: {
|
|
105
|
+
map: async (host, source, { scheme }) => {
|
|
106
|
+
// draw with Google Maps, Mapbox, MapLibre, ...
|
|
107
|
+
return () => {
|
|
108
|
+
/* dispose */
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Requirements
|
|
115
|
+
|
|
116
|
+
- Angular 21.2 or 22
|
|
117
|
+
- Peer dependencies: `@tanstack/ai`, `@tanstack/ai-angular`, `@tanstack/ai-client`, `marked`, `dompurify`, `highlight.js`, `rxjs`, plus the lazily loaded `mermaid`, `vega`, `vega-lite`, `vega-embed`, `leaflet`
|