@m6d/cortex-angular 0.12.0 → 0.14.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 +22 -22
- package/fesm2022/m6d-cortex-angular.mjs +138 -88
- package/package.json +1 -1
- package/types/m6d-cortex-angular.d.ts +38 -15
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ No root-level providers are needed. Each widget is self-contained, so one page c
|
|
|
42
42
|
| `viewMode` | `'helper' \| 'full'` | Compact panel or full layout with a sidebar (default: `'helper'`) |
|
|
43
43
|
| `theme` | `'light' \| 'dark' \| 'system'` | Color scheme (default: `'light'`) |
|
|
44
44
|
| `agentName` | `string \| { en, ar }` | Header title while no thread is selected (optional) |
|
|
45
|
-
| `
|
|
45
|
+
| `thread` | `string` | A thread id to open on mount (optional) |
|
|
46
46
|
| `mediaRenderers` | `Record<string, MediaRenderer>` | Replace or add the media fences the assistant can draw (optional) |
|
|
47
47
|
| `trustSameOriginEmbeds` | `boolean` | Allow embedded tool pages served from this page's own origin (default: `false`) |
|
|
48
48
|
| `hooks.onToolCall` | `(toolCall, context) => unknown` | Answers a client tool; return `undefined` for tools you do not own (optional) |
|
|
@@ -51,7 +51,7 @@ No root-level providers are needed. Each widget is self-contained, so one page c
|
|
|
51
51
|
| `toolComponents` | `Record<string, Type<CortexToolComponentInputs>>` | Custom Angular components for tool rendering (optional) |
|
|
52
52
|
| `injector` | `Injector` | Injector for `toolComponents` (optional) |
|
|
53
53
|
|
|
54
|
-
`transport.getHeaders` returns the headers every call carries, usually a bearer `Authorization`. Called straight from another origin, the engine accepts only `Authorization` and the headers the widget sets itself; route anything else through a same-origin proxy. The WebSocket takes its `token` query param from a bearer `Authorization` header when there is one.
|
|
54
|
+
`transport.getHeaders` returns the headers every call carries, usually a bearer `Authorization`. Called straight from another origin, the engine accepts only `Authorization` and the headers the widget sets itself; route anything else through a same-origin proxy. The WebSocket takes its `token` query param from a bearer `Authorization` header when there is one. The debug toggle shows only when Cortex offers this caller the debug view: always to a console operator, and to everyone only where the engine runs with `ENGINE_DEBUG=true`. Anyone else gets only what the widget's normal view draws, and so does a `toolComponents` entry for one of the agent's server tools: the model's line for the user as the call's input, and only whether it failed (or a dataset read's row count) as its output.
|
|
55
55
|
|
|
56
56
|
## Custom parts
|
|
57
57
|
|
|
@@ -119,19 +119,19 @@ for typing your own rows and chips.
|
|
|
119
119
|
|
|
120
120
|
One header serves both screens; `screen` says which is showing.
|
|
121
121
|
|
|
122
|
-
| Field | Type | Description
|
|
123
|
-
| -------------- | --------------------- |
|
|
124
|
-
| `screen` | `'chat' \| 'threads'` | Which screen the header is on
|
|
125
|
-
| `viewMode` | `'helper' \| 'full'` | The configured view mode
|
|
126
|
-
| `title` | `string \| null` | The open thread's title; `null` on a new chat
|
|
127
|
-
| `agentName` | `string \| undefined` | `agentName` in the widget's locale
|
|
128
|
-
| `threadCount` | `number \| undefined` | How many conversations the history lists; undefined while it loads
|
|
129
|
-
| `isWorking` | `boolean` | The agent is answering
|
|
130
|
-
| `debug` | `{ shown, on }` | Whether
|
|
131
|
-
| `newChat` | `() => void` | Starts a new chat
|
|
132
|
-
| `openHistory` | `() => void` | Shows the history: its screen, or the sidebar in full mode
|
|
133
|
-
| `closeHistory` | `() => void` | Returns to the open chat
|
|
134
|
-
| `toggleDebug` | `() => void` | Switches debug mode
|
|
122
|
+
| Field | Type | Description |
|
|
123
|
+
| -------------- | --------------------- | -------------------------------------------------------------------- |
|
|
124
|
+
| `screen` | `'chat' \| 'threads'` | Which screen the header is on |
|
|
125
|
+
| `viewMode` | `'helper' \| 'full'` | The configured view mode |
|
|
126
|
+
| `title` | `string \| null` | The open thread's title; `null` on a new chat |
|
|
127
|
+
| `agentName` | `string \| undefined` | `agentName` in the widget's locale |
|
|
128
|
+
| `threadCount` | `number \| undefined` | How many conversations the history lists; undefined while it loads |
|
|
129
|
+
| `isWorking` | `boolean` | The agent is answering |
|
|
130
|
+
| `debug` | `{ shown, on }` | Whether Cortex offers the debug view, and whether it is on |
|
|
131
|
+
| `newChat` | `() => void` | Starts a new chat; absent until Cortex confirms the caller may write |
|
|
132
|
+
| `openHistory` | `() => void` | Shows the history: its screen, or the sidebar in full mode |
|
|
133
|
+
| `closeHistory` | `() => void` | Returns to the open chat |
|
|
134
|
+
| `toggleDebug` | `() => void` | Switches debug mode |
|
|
135
135
|
|
|
136
136
|
### `landing`
|
|
137
137
|
|
|
@@ -152,13 +152,13 @@ landing for it.
|
|
|
152
152
|
|
|
153
153
|
The history's list. Its header is the `header` slot.
|
|
154
154
|
|
|
155
|
-
| Field | Type | Description
|
|
156
|
-
| ------------------ | --------------------------------- |
|
|
157
|
-
| `threads` | `ThreadSummary[] \| undefined` | Newest first; `undefined` while the first load is out
|
|
158
|
-
| `selectedThreadId` | `string \| undefined` | The open thread's id; `undefined` on a new chat
|
|
159
|
-
| `openThread` | `(thread: ThreadSummary) => void` | Opens a thread
|
|
160
|
-
| `deleteThread` | `(threadId: string) => void` | Deletes a thread
|
|
161
|
-
| `newChat` | `() => void` | Starts a new chat
|
|
155
|
+
| Field | Type | Description |
|
|
156
|
+
| ------------------ | --------------------------------- | -------------------------------------------------------------------- |
|
|
157
|
+
| `threads` | `ThreadSummary[] \| undefined` | Newest first; `undefined` while the first load is out |
|
|
158
|
+
| `selectedThreadId` | `string \| undefined` | The open thread's id; `undefined` on a new chat |
|
|
159
|
+
| `openThread` | `(thread: ThreadSummary) => void` | Opens a thread |
|
|
160
|
+
| `deleteThread` | `(threadId: string) => void` | Deletes a thread; absent until Cortex confirms the caller may write |
|
|
161
|
+
| `newChat` | `() => void` | Starts a new chat; absent until Cortex confirms the caller may write |
|
|
162
162
|
|
|
163
163
|
## Theming
|
|
164
164
|
|
|
@@ -48,6 +48,13 @@ function checkAttachmentPolicy(file) {
|
|
|
48
48
|
return "ok";
|
|
49
49
|
}
|
|
50
50
|
var STATEMENT_TOOLS = ["executeCode", "queryDataset", "describeDataset"];
|
|
51
|
+
var APPROVAL_TITLE_FIELD = "approvalTitle";
|
|
52
|
+
function approvalTitleOf(input) {
|
|
53
|
+
if (!input || typeof input !== "object" || !(APPROVAL_TITLE_FIELD in input))
|
|
54
|
+
return;
|
|
55
|
+
const title = input[APPROVAL_TITLE_FIELD];
|
|
56
|
+
return typeof title === "string" && title.trim() ? title.trim() : undefined;
|
|
57
|
+
}
|
|
51
58
|
function toolCallMetadataOf(part) {
|
|
52
59
|
const metadata = part.metadata;
|
|
53
60
|
return metadata?.cortex ?? undefined;
|
|
@@ -60,6 +67,8 @@ function approvalIdOf(part) {
|
|
|
60
67
|
return part.approval?.id ?? `approval_${part.id}`;
|
|
61
68
|
}
|
|
62
69
|
var TIMEZONE_HEADER = "X-Cortex-Timezone";
|
|
70
|
+
var OPERATOR_HEADER = "X-Cortex-Operator";
|
|
71
|
+
var INSPECT_HEADER = "X-Cortex-Inspect";
|
|
63
72
|
|
|
64
73
|
// src/internal/client/src/chat/api-client.ts
|
|
65
74
|
function resolveTransportHeaders(transport) {
|
|
@@ -322,6 +331,7 @@ var ar_default = {
|
|
|
322
331
|
translate_trigger_fired: "تم التشغيل بواسطة",
|
|
323
332
|
translate_trigger_payload: "الحمولة",
|
|
324
333
|
translate_messages_disabled: "يعمل هذا الوكيل من مشغّلاته فقط.",
|
|
334
|
+
translate_read_only: "أنت تطّلع على هذه المحادثة. لا يمكن إرسال شيء من هنا.",
|
|
325
335
|
translate_access_refused: "لم يقبل هذا الوكيل تسجيل دخولك.",
|
|
326
336
|
translate_agent_unreachable: "تعذّر الوصول إلى هذا الوكيل الآن. نعيد المحاولة...",
|
|
327
337
|
translate_agent_missing: "هذا الوكيل غير متاح.",
|
|
@@ -476,6 +486,7 @@ var en_default = {
|
|
|
476
486
|
translate_trigger_fired: "Triggered by",
|
|
477
487
|
translate_trigger_payload: "Payload",
|
|
478
488
|
translate_messages_disabled: "This agent only runs from its triggers.",
|
|
489
|
+
translate_read_only: "You're viewing this conversation. Nothing can be sent from here.",
|
|
479
490
|
translate_access_refused: "This agent did not accept your sign-in.",
|
|
480
491
|
translate_agent_unreachable: "This agent cannot be reached right now. Trying again...",
|
|
481
492
|
translate_agent_missing: "This agent is not available.",
|
|
@@ -724,15 +735,12 @@ function toolCallAnimation(part) {
|
|
|
724
735
|
rows: state === "complete" ? toolCallRows(part) : undefined
|
|
725
736
|
};
|
|
726
737
|
}
|
|
727
|
-
function approvalPrompt(part, locale) {
|
|
728
|
-
return toolCallMetadataOf(part)?.approval?.[locale] || undefined;
|
|
729
|
-
}
|
|
730
738
|
function approvalCard(part, locale) {
|
|
731
739
|
const approved = part.approval?.approved;
|
|
732
740
|
const { state } = toolCallAnimation(part);
|
|
733
741
|
const decision = approved === undefined ? part.state === "approval-requested" ? "pending" : "cancelled" : !approved ? "declined" : state === "error" ? "failed" : "approved";
|
|
734
742
|
return {
|
|
735
|
-
sentence:
|
|
743
|
+
sentence: approvalTitleOf(part.input) ?? translate(locale, "translate_approval_action", { tool: wordsOf(part.name) }),
|
|
736
744
|
decision,
|
|
737
745
|
decisionKey: DECISION_KEYS[decision]
|
|
738
746
|
};
|
|
@@ -1524,7 +1532,7 @@ function createCortexSocket(options) {
|
|
|
1524
1532
|
resolveTransportHeaders(transport).then((headers) => {
|
|
1525
1533
|
if (closed)
|
|
1526
1534
|
return;
|
|
1527
|
-
ws = new WebSocket(
|
|
1535
|
+
ws = new WebSocket(appendAuthToUrl(wsUrl, headers));
|
|
1528
1536
|
ws.addEventListener("open", () => {
|
|
1529
1537
|
open = true;
|
|
1530
1538
|
const opened = ws;
|
|
@@ -1583,14 +1591,21 @@ function resolveWsUrl(wsUrl, baseUrl) {
|
|
|
1583
1591
|
parsed.pathname = parsed.pathname.replace(/\/$/, "") + "/ws";
|
|
1584
1592
|
return parsed.toString();
|
|
1585
1593
|
}
|
|
1586
|
-
function
|
|
1587
|
-
const
|
|
1588
|
-
|
|
1594
|
+
function appendAuthToUrl(wsUrl, headers) {
|
|
1595
|
+
const header = (name) => Object.entries(headers).find(([key]) => key.toLowerCase() === name.toLowerCase())?.[1];
|
|
1596
|
+
const bearer = header("Authorization");
|
|
1597
|
+
const params = Object.entries({
|
|
1598
|
+
token: bearer?.startsWith("Bearer ") ? bearer.slice(7) : undefined,
|
|
1599
|
+
operator: header(OPERATOR_HEADER),
|
|
1600
|
+
inspect: header(INSPECT_HEADER)
|
|
1601
|
+
}).filter((entry) => Boolean(entry[1]));
|
|
1602
|
+
if (params.length === 0)
|
|
1589
1603
|
return wsUrl;
|
|
1590
1604
|
const parsed = new URL(wsUrl, window.location.origin);
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1605
|
+
for (const [param, value] of params) {
|
|
1606
|
+
if (!parsed.searchParams.has(param))
|
|
1607
|
+
parsed.searchParams.set(param, value);
|
|
1608
|
+
}
|
|
1594
1609
|
return parsed.toString();
|
|
1595
1610
|
}
|
|
1596
1611
|
// src/internal/client/src/chat/ask-until-answered.ts
|
|
@@ -1811,7 +1826,7 @@ function splitTail(text, consumed, runs) {
|
|
|
1811
1826
|
if (end <= 0)
|
|
1812
1827
|
break;
|
|
1813
1828
|
let take = Math.min(end, run.length - consumed);
|
|
1814
|
-
if (take < end && /[\uDC00-\uDFFF]/.test(text
|
|
1829
|
+
if (take < end && /[\uDC00-\uDFFF]/.test(text.charAt(end - take)))
|
|
1815
1830
|
take += 1;
|
|
1816
1831
|
const span = document.createElement("span");
|
|
1817
1832
|
span.className = "cortex-stream-fade";
|
|
@@ -4557,17 +4572,19 @@ var ChatHeaderComponent = class ChatHeaderComponent2 {
|
|
|
4557
4572
|
template: `@let header = context();
|
|
4558
4573
|
|
|
4559
4574
|
<ng-template #newChatButton>
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
<
|
|
4569
|
-
|
|
4570
|
-
|
|
4575
|
+
@if (header.newChat; as newChat) {
|
|
4576
|
+
<button
|
|
4577
|
+
type="button"
|
|
4578
|
+
(click)="newChat()"
|
|
4579
|
+
[attr.aria-label]="'translate_new_chat' | translate"
|
|
4580
|
+
[title]="'translate_new_chat' | translate"
|
|
4581
|
+
class="cortex-widget__header-btn cortex-widget__new-btn"
|
|
4582
|
+
>
|
|
4583
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
4584
|
+
<path d="M8 3v10M3 8h10" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" />
|
|
4585
|
+
</svg>
|
|
4586
|
+
</button>
|
|
4587
|
+
}
|
|
4571
4588
|
</ng-template>
|
|
4572
4589
|
|
|
4573
4590
|
@if (header.screen === 'threads') {
|
|
@@ -4696,17 +4713,19 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
4696
4713
|
template: `@let header = context();
|
|
4697
4714
|
|
|
4698
4715
|
<ng-template #newChatButton>
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
<
|
|
4708
|
-
|
|
4709
|
-
|
|
4716
|
+
@if (header.newChat; as newChat) {
|
|
4717
|
+
<button
|
|
4718
|
+
type="button"
|
|
4719
|
+
(click)="newChat()"
|
|
4720
|
+
[attr.aria-label]="'translate_new_chat' | translate"
|
|
4721
|
+
[title]="'translate_new_chat' | translate"
|
|
4722
|
+
class="cortex-widget__header-btn cortex-widget__new-btn"
|
|
4723
|
+
>
|
|
4724
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
4725
|
+
<path d="M8 3v10M3 8h10" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" />
|
|
4726
|
+
</svg>
|
|
4727
|
+
</button>
|
|
4728
|
+
}
|
|
4710
4729
|
</ng-template>
|
|
4711
4730
|
|
|
4712
4731
|
@if (header.screen === 'threads') {
|
|
@@ -9689,9 +9708,10 @@ var MessageToolCallAnimatedComponent = class MessageToolCallAnimatedComponent2 {
|
|
|
9689
9708
|
} : null;
|
|
9690
9709
|
}, ...ngDevMode ? [{ debugName: "mountedComponent" }] : []);
|
|
9691
9710
|
clientToolFallback = signal(false, ...ngDevMode ? [{ debugName: "clientToolFallback" }] : []);
|
|
9692
|
-
|
|
9711
|
+
answers = computed(() => this.chatService.capabilities()?.messages === true, ...ngDevMode ? [{ debugName: "answers" }] : []);
|
|
9712
|
+
owed = computed(() => this.answers() && this.toolCallPart().state === "input-complete" && !this.chatService.isAgentWorking(), ...ngDevMode ? [{ debugName: "owed" }] : []);
|
|
9693
9713
|
showClientTool = computed(() => !this.clientToolFallback() && this.owed() && toolCallMetadataOf(this.toolCallPart())?.embed !== undefined, ...ngDevMode ? [{ debugName: "showClientTool" }] : []);
|
|
9694
|
-
approvalRequested = computed(() => this.toolCallPart().state === "approval-requested" && !this.chatService.isAgentWorking(), ...ngDevMode ? [{ debugName: "approvalRequested" }] : []);
|
|
9714
|
+
approvalRequested = computed(() => this.answers() && this.toolCallPart().state === "approval-requested" && !this.chatService.isAgentWorking(), ...ngDevMode ? [{ debugName: "approvalRequested" }] : []);
|
|
9695
9715
|
animation = computed(() => toolCallAnimation(this.toolCallPart()), ...ngDevMode ? [{ debugName: "animation" }] : []);
|
|
9696
9716
|
animState = computed(() => this.animation().state, ...ngDevMode ? [{ debugName: "animState" }] : []);
|
|
9697
9717
|
gated = computed(() => this.animation().gated, ...ngDevMode ? [{ debugName: "gated" }] : []);
|
|
@@ -11621,7 +11641,7 @@ var MessageListComponent = class MessageListComponent2 {
|
|
|
11621
11641
|
<cortex-message-aborted-flag [label]="failureLabel(failure)" />
|
|
11622
11642
|
<!-- The reason may name the model provider's answer: shown only where
|
|
11623
11643
|
the debug view is offered. -->
|
|
11624
|
-
@if (
|
|
11644
|
+
@if (chatService.capabilities()?.debug && failure.reason) {
|
|
11625
11645
|
<p class="cortex-aborted-flag__reason">{{ failure.reason }}</p>
|
|
11626
11646
|
}
|
|
11627
11647
|
}
|
|
@@ -11717,7 +11737,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
11717
11737
|
<cortex-message-aborted-flag [label]="failureLabel(failure)" />
|
|
11718
11738
|
<!-- The reason may name the model provider's answer: shown only where
|
|
11719
11739
|
the debug view is offered. -->
|
|
11720
|
-
@if (
|
|
11740
|
+
@if (chatService.capabilities()?.debug && failure.reason) {
|
|
11721
11741
|
<p class="cortex-aborted-flag__reason">{{ failure.reason }}</p>
|
|
11722
11742
|
}
|
|
11723
11743
|
}
|
|
@@ -11944,22 +11964,24 @@ var ThreadListComponent = class ThreadListComponent2 {
|
|
|
11944
11964
|
}
|
|
11945
11965
|
</button>
|
|
11946
11966
|
|
|
11947
|
-
|
|
11948
|
-
|
|
11949
|
-
|
|
11950
|
-
|
|
11951
|
-
|
|
11952
|
-
|
|
11953
|
-
|
|
11954
|
-
|
|
11955
|
-
<
|
|
11956
|
-
|
|
11957
|
-
|
|
11958
|
-
|
|
11959
|
-
|
|
11960
|
-
|
|
11961
|
-
|
|
11962
|
-
|
|
11967
|
+
@if (list.deleteThread; as deleteThread) {
|
|
11968
|
+
<button
|
|
11969
|
+
type="button"
|
|
11970
|
+
[attr.aria-label]="'translate_delete_conversation' | translate"
|
|
11971
|
+
(click)="deleteThread(thread.id)"
|
|
11972
|
+
class="cortex-widget__thread-delete"
|
|
11973
|
+
[class.cortex-widget__thread-delete--active]="isActive"
|
|
11974
|
+
>
|
|
11975
|
+
<svg width="12" height="12" viewBox="0 0 16 16" fill="none">
|
|
11976
|
+
<path
|
|
11977
|
+
d="M4 4l8 8M12 4l-8 8"
|
|
11978
|
+
stroke="currentColor"
|
|
11979
|
+
stroke-width="1.3"
|
|
11980
|
+
stroke-linecap="round"
|
|
11981
|
+
/>
|
|
11982
|
+
</svg>
|
|
11983
|
+
</button>
|
|
11984
|
+
}
|
|
11963
11985
|
|
|
11964
11986
|
<svg
|
|
11965
11987
|
class="cortex-widget__thread-arrow"
|
|
@@ -12005,12 +12027,14 @@ var ThreadListComponent = class ThreadListComponent2 {
|
|
|
12005
12027
|
<p class="cortex-widget__threads-empty-subtitle">
|
|
12006
12028
|
{{ 'translate_start_a_new_conversation' | translate }}
|
|
12007
12029
|
</p>
|
|
12008
|
-
|
|
12009
|
-
|
|
12010
|
-
|
|
12011
|
-
|
|
12012
|
-
|
|
12013
|
-
|
|
12030
|
+
@if (list.newChat; as newChat) {
|
|
12031
|
+
<button
|
|
12032
|
+
(click)="newChat()"
|
|
12033
|
+
class="cortex-widget__new-chat-btn cortex-widget__new-chat-btn--empty-state"
|
|
12034
|
+
>
|
|
12035
|
+
{{ 'translate_new_chat' | translate }}
|
|
12036
|
+
</button>
|
|
12037
|
+
}
|
|
12014
12038
|
</div>
|
|
12015
12039
|
}
|
|
12016
12040
|
`,
|
|
@@ -12100,22 +12124,24 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
12100
12124
|
}
|
|
12101
12125
|
</button>
|
|
12102
12126
|
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
|
|
12106
|
-
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
<
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12127
|
+
@if (list.deleteThread; as deleteThread) {
|
|
12128
|
+
<button
|
|
12129
|
+
type="button"
|
|
12130
|
+
[attr.aria-label]="'translate_delete_conversation' | translate"
|
|
12131
|
+
(click)="deleteThread(thread.id)"
|
|
12132
|
+
class="cortex-widget__thread-delete"
|
|
12133
|
+
[class.cortex-widget__thread-delete--active]="isActive"
|
|
12134
|
+
>
|
|
12135
|
+
<svg width="12" height="12" viewBox="0 0 16 16" fill="none">
|
|
12136
|
+
<path
|
|
12137
|
+
d="M4 4l8 8M12 4l-8 8"
|
|
12138
|
+
stroke="currentColor"
|
|
12139
|
+
stroke-width="1.3"
|
|
12140
|
+
stroke-linecap="round"
|
|
12141
|
+
/>
|
|
12142
|
+
</svg>
|
|
12143
|
+
</button>
|
|
12144
|
+
}
|
|
12119
12145
|
|
|
12120
12146
|
<svg
|
|
12121
12147
|
class="cortex-widget__thread-arrow"
|
|
@@ -12161,12 +12187,14 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
12161
12187
|
<p class="cortex-widget__threads-empty-subtitle">
|
|
12162
12188
|
{{ 'translate_start_a_new_conversation' | translate }}
|
|
12163
12189
|
</p>
|
|
12164
|
-
|
|
12165
|
-
|
|
12166
|
-
|
|
12167
|
-
|
|
12168
|
-
|
|
12169
|
-
|
|
12190
|
+
@if (list.newChat; as newChat) {
|
|
12191
|
+
<button
|
|
12192
|
+
(click)="newChat()"
|
|
12193
|
+
class="cortex-widget__new-chat-btn cortex-widget__new-chat-btn--empty-state"
|
|
12194
|
+
>
|
|
12195
|
+
{{ 'translate_new_chat' | translate }}
|
|
12196
|
+
</button>
|
|
12197
|
+
}
|
|
12170
12198
|
</div>
|
|
12171
12199
|
}
|
|
12172
12200
|
`
|
|
@@ -12238,6 +12266,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
12238
12266
|
var CortexChatWidgetComponent = class CortexChatWidgetComponent2 {
|
|
12239
12267
|
config = input.required(...ngDevMode ? [{ debugName: "config" }] : []);
|
|
12240
12268
|
debugMode = signal(false, ...ngDevMode ? [{ debugName: "debugMode" }] : []);
|
|
12269
|
+
writes = computed(() => this.chatService.capabilities()?.readOnly === false, ...ngDevMode ? [{ debugName: "writes" }] : []);
|
|
12241
12270
|
screen = signal("chat", ...ngDevMode ? [{ debugName: "screen" }] : []);
|
|
12242
12271
|
sidebarOpen = signal(false, ...ngDevMode ? [{ debugName: "sidebarOpen" }] : []);
|
|
12243
12272
|
viewMode = computed(() => this.config().viewMode ?? "helper", ...ngDevMode ? [{ debugName: "viewMode" }] : []);
|
|
@@ -12265,8 +12294,10 @@ var CortexChatWidgetComponent = class CortexChatWidgetComponent2 {
|
|
|
12265
12294
|
threads: this.threadService.threads(),
|
|
12266
12295
|
selectedThreadId: this.chatService.selectedThread()?.id,
|
|
12267
12296
|
openThread: (thread) => this.selectThread(thread),
|
|
12268
|
-
|
|
12269
|
-
|
|
12297
|
+
...this.writes() && {
|
|
12298
|
+
deleteThread: (threadId) => this.chatService.deleteThread(threadId).subscribe(),
|
|
12299
|
+
newChat: () => this.newChat()
|
|
12300
|
+
}
|
|
12270
12301
|
}), ...ngDevMode ? [{ debugName: "threadList" }] : []);
|
|
12271
12302
|
chatService;
|
|
12272
12303
|
queue;
|
|
@@ -12286,6 +12317,15 @@ var CortexChatWidgetComponent = class CortexChatWidgetComponent2 {
|
|
|
12286
12317
|
this.queue.store.clear(selectedThreadId);
|
|
12287
12318
|
selectedThreadId = nextThreadId;
|
|
12288
12319
|
}, { injector: this.injector });
|
|
12320
|
+
let openedConfigThread = false;
|
|
12321
|
+
effect(() => {
|
|
12322
|
+
const id = this.config().thread;
|
|
12323
|
+
const named = id && this.threadService.threads()?.find((thread) => thread.id === id);
|
|
12324
|
+
if (openedConfigThread || !named)
|
|
12325
|
+
return;
|
|
12326
|
+
openedConfigThread = true;
|
|
12327
|
+
untracked(() => this.selectThread(named));
|
|
12328
|
+
}, { injector: this.injector });
|
|
12289
12329
|
this.chatService.events$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((event) => {
|
|
12290
12330
|
if (event === "onError") {
|
|
12291
12331
|
this.queue.store.restoreConsumed(this.chatService.selectedThread()?.id);
|
|
@@ -12308,10 +12348,10 @@ var CortexChatWidgetComponent = class CortexChatWidgetComponent2 {
|
|
|
12308
12348
|
threadCount: this.threadService.threads()?.length,
|
|
12309
12349
|
isWorking: this.chatService.isAgentWorking(),
|
|
12310
12350
|
debug: {
|
|
12311
|
-
shown: Boolean(this.
|
|
12351
|
+
shown: Boolean(this.chatService.capabilities()?.debug),
|
|
12312
12352
|
on: this.debugMode()
|
|
12313
12353
|
},
|
|
12314
|
-
newChat: () => this.newChat(),
|
|
12354
|
+
...this.writes() && { newChat: () => this.newChat() },
|
|
12315
12355
|
openHistory: () => this.openHistory(),
|
|
12316
12356
|
closeHistory: () => this.closeHistory(),
|
|
12317
12357
|
toggleDebug: () => this.toggleDebugMode()
|
|
@@ -12502,7 +12542,12 @@ var CortexChatWidgetComponent = class CortexChatWidgetComponent2 {
|
|
|
12502
12542
|
</p>
|
|
12503
12543
|
} @else if (chatService.capabilities()?.messages === false) {
|
|
12504
12544
|
<p class="cortex-widget__messages-disabled">
|
|
12505
|
-
{{
|
|
12545
|
+
{{
|
|
12546
|
+
(chatService.capabilities()?.readOnly
|
|
12547
|
+
? 'translate_read_only'
|
|
12548
|
+
: 'translate_messages_disabled'
|
|
12549
|
+
) | translate
|
|
12550
|
+
}}
|
|
12506
12551
|
</p>
|
|
12507
12552
|
} @else if (chatService.capabilities() !== undefined) {
|
|
12508
12553
|
<cortex-chat-composer />
|
|
@@ -12703,7 +12748,12 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
12703
12748
|
</p>
|
|
12704
12749
|
} @else if (chatService.capabilities()?.messages === false) {
|
|
12705
12750
|
<p class="cortex-widget__messages-disabled">
|
|
12706
|
-
{{
|
|
12751
|
+
{{
|
|
12752
|
+
(chatService.capabilities()?.readOnly
|
|
12753
|
+
? 'translate_read_only'
|
|
12754
|
+
: 'translate_messages_disabled'
|
|
12755
|
+
) | translate
|
|
12756
|
+
}}
|
|
12707
12757
|
</p>
|
|
12708
12758
|
} @else if (chatService.capabilities() !== undefined) {
|
|
12709
12759
|
<cortex-chat-composer />
|
package/package.json
CHANGED
|
@@ -61,12 +61,23 @@ export type CreateThreadRequest = {
|
|
|
61
61
|
*/
|
|
62
62
|
export type AgentCapabilities = {
|
|
63
63
|
attachments: boolean;
|
|
64
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* False when this caller may not send to the chat: the agent's `message`
|
|
66
|
+
* trigger is off, or the caller only reads (`readOnly`). The widget hides
|
|
67
|
+
* its composer and answers no tool call.
|
|
68
|
+
*/
|
|
65
69
|
messages: boolean;
|
|
70
|
+
/** True when the caller only reads, as an operator inspecting a user's thread does. */
|
|
71
|
+
readOnly: boolean;
|
|
66
72
|
/** Prompt chips on the blank-chat landing per locale; clicking one sends its `prompt` as the first message. */
|
|
67
73
|
suggestions: Suggestions;
|
|
68
74
|
/** Headline of the blank-chat landing per locale; "" falls back to the widget's built-in copy. */
|
|
69
75
|
greeting: Greeting;
|
|
76
|
+
/**
|
|
77
|
+
* Whether this caller gets the debug view: tool inputs and outputs, reasoning,
|
|
78
|
+
* model calls. Cortex sends anyone else only what the widget's normal UI draws.
|
|
79
|
+
*/
|
|
80
|
+
debug: boolean;
|
|
70
81
|
};
|
|
71
82
|
/**
|
|
72
83
|
* One landing-page chip: the widget shows `title` and sends `prompt` as the
|
|
@@ -165,7 +176,11 @@ export type CortexConfig = {
|
|
|
165
176
|
* or a map keyed by locale (`{ en: 'Support', ar: 'الدعم' }`).
|
|
166
177
|
*/
|
|
167
178
|
agentName?: Localized<string>;
|
|
168
|
-
|
|
179
|
+
/**
|
|
180
|
+
* A thread to open when the widget mounts, by id, once the thread list holds
|
|
181
|
+
* it: a deep link into one conversation, such as the console's inspector.
|
|
182
|
+
*/
|
|
183
|
+
thread?: string;
|
|
169
184
|
/**
|
|
170
185
|
* Render embedded tool pages served from this page's own origin with their
|
|
171
186
|
* full identity — which, same-origin, means no effective sandbox at all: such
|
|
@@ -193,12 +208,13 @@ export type CortexHeaderContext = {
|
|
|
193
208
|
/** How many conversations the history lists; undefined while the first load is out. */
|
|
194
209
|
threadCount: number | undefined;
|
|
195
210
|
isWorking: boolean;
|
|
196
|
-
/** Whether
|
|
211
|
+
/** Whether Cortex offers this caller the debug view, and whether it is on. */
|
|
197
212
|
debug: {
|
|
198
213
|
shown: boolean;
|
|
199
214
|
on: boolean;
|
|
200
215
|
};
|
|
201
|
-
|
|
216
|
+
/** Absent until the handshake says the caller may write; an operator inspecting a thread only reads. */
|
|
217
|
+
newChat?: () => void;
|
|
202
218
|
/** Shows the history: the history screen, or in full mode the sidebar where it is hidden. */
|
|
203
219
|
openHistory: () => void;
|
|
204
220
|
/** Returns to the open chat from wherever `openHistory` went. */
|
|
@@ -236,8 +252,9 @@ export type CortexThreadListContext = {
|
|
|
236
252
|
/** The open thread's id; undefined on a new chat. */
|
|
237
253
|
selectedThreadId: string | undefined;
|
|
238
254
|
openThread: (thread: ThreadSummary) => void;
|
|
239
|
-
|
|
240
|
-
|
|
255
|
+
/** Both absent until the handshake says the caller may write; an operator inspecting a thread only reads. */
|
|
256
|
+
deleteThread?: (threadId: string) => void;
|
|
257
|
+
newChat?: () => void;
|
|
241
258
|
};
|
|
242
259
|
/** Each part of the widget a consumer can draw itself, with the context it receives. */
|
|
243
260
|
export type CortexSlotContexts<View> = {
|
|
@@ -442,6 +459,12 @@ declare class CortexChatService {
|
|
|
442
459
|
export declare class CortexChatWidgetComponent implements OnInit {
|
|
443
460
|
readonly config: import("@angular/core").InputSignal<CortexAngularConfig>;
|
|
444
461
|
protected readonly debugMode: import("@angular/core").WritableSignal<boolean>;
|
|
462
|
+
/**
|
|
463
|
+
* Whether this caller may start and delete conversations: only once the
|
|
464
|
+
* handshake says so, like every capability-gated control, and never for a
|
|
465
|
+
* caller that only reads, as an operator inspecting a thread does.
|
|
466
|
+
*/
|
|
467
|
+
private readonly writes;
|
|
445
468
|
protected readonly screen: import("@angular/core").WritableSignal<"chat" | "threads">;
|
|
446
469
|
protected readonly sidebarOpen: import("@angular/core").WritableSignal<boolean>;
|
|
447
470
|
protected readonly viewMode: import("@angular/core").Signal<CortexViewMode>;
|
|
@@ -455,6 +478,10 @@ export declare class CortexChatWidgetComponent implements OnInit {
|
|
|
455
478
|
/** Why the handshake has not answered, worded for the composer's place. */
|
|
456
479
|
protected readonly unansweredNotice: import("@angular/core").Signal<"translate_access_refused" | "translate_agent_unreachable" | "translate_agent_missing" | undefined>;
|
|
457
480
|
protected readonly chatHeader: import("@angular/core").Signal<{
|
|
481
|
+
openHistory: () => void;
|
|
482
|
+
closeHistory: () => void;
|
|
483
|
+
toggleDebug: () => void;
|
|
484
|
+
newChat?: (() => void) | undefined;
|
|
458
485
|
screen: "chat" | "threads";
|
|
459
486
|
viewMode: CortexViewMode;
|
|
460
487
|
title: string | null;
|
|
@@ -465,12 +492,12 @@ export declare class CortexChatWidgetComponent implements OnInit {
|
|
|
465
492
|
shown: boolean;
|
|
466
493
|
on: boolean;
|
|
467
494
|
};
|
|
468
|
-
|
|
495
|
+
}>;
|
|
496
|
+
protected readonly threadsHeader: import("@angular/core").Signal<{
|
|
469
497
|
openHistory: () => void;
|
|
470
498
|
closeHistory: () => void;
|
|
471
499
|
toggleDebug: () => void;
|
|
472
|
-
|
|
473
|
-
protected readonly threadsHeader: import("@angular/core").Signal<{
|
|
500
|
+
newChat?: (() => void) | undefined;
|
|
474
501
|
screen: "chat" | "threads";
|
|
475
502
|
viewMode: CortexViewMode;
|
|
476
503
|
title: string | null;
|
|
@@ -481,10 +508,6 @@ export declare class CortexChatWidgetComponent implements OnInit {
|
|
|
481
508
|
shown: boolean;
|
|
482
509
|
on: boolean;
|
|
483
510
|
};
|
|
484
|
-
newChat: () => void;
|
|
485
|
-
openHistory: () => void;
|
|
486
|
-
closeHistory: () => void;
|
|
487
|
-
toggleDebug: () => void;
|
|
488
511
|
}>;
|
|
489
512
|
protected readonly landing: import("@angular/core").Signal<{
|
|
490
513
|
threads: ThreadSummary[] | undefined;
|
|
@@ -496,11 +519,11 @@ export declare class CortexChatWidgetComponent implements OnInit {
|
|
|
496
519
|
send: (prompt: string) => void;
|
|
497
520
|
}>;
|
|
498
521
|
protected readonly threadList: import("@angular/core").Signal<{
|
|
522
|
+
deleteThread?: ((threadId: string) => import("rxjs").Subscription) | undefined;
|
|
523
|
+
newChat?: (() => void) | undefined;
|
|
499
524
|
threads: ThreadSummary[] | undefined;
|
|
500
525
|
selectedThreadId: string | undefined;
|
|
501
526
|
openThread: (thread: ThreadSummary) => void;
|
|
502
|
-
deleteThread: (threadId: string) => import("rxjs").Subscription;
|
|
503
|
-
newChat: () => void;
|
|
504
527
|
}>;
|
|
505
528
|
protected chatService: CortexChatService;
|
|
506
529
|
protected queue: AttachmentQueueService;
|