@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 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 `![alt](attachment#<id>)` 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`