@m6d/cortex-angular 1.7.0 → 1.8.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.
|
@@ -51,6 +51,9 @@ function createCortexApiClient(getTransport) {
|
|
|
51
51
|
return text ? JSON.parse(text) : undefined;
|
|
52
52
|
}
|
|
53
53
|
return {
|
|
54
|
+
getCapabilities() {
|
|
55
|
+
return send("/capabilities");
|
|
56
|
+
},
|
|
54
57
|
listThreads() {
|
|
55
58
|
return send("/threads");
|
|
56
59
|
},
|
|
@@ -1199,6 +1202,9 @@ var CORTEX_CLIENT_CONFIG = new InjectionToken("CORTEX_CLIENT_CONFIG");
|
|
|
1199
1202
|
class CortexApiClient {
|
|
1200
1203
|
config = inject(CORTEX_CLIENT_CONFIG);
|
|
1201
1204
|
client = createCortexApiClient(() => this.config().transport);
|
|
1205
|
+
getCapabilities() {
|
|
1206
|
+
return this.client.getCapabilities();
|
|
1207
|
+
}
|
|
1202
1208
|
listThreads() {
|
|
1203
1209
|
return this.client.listThreads();
|
|
1204
1210
|
}
|
|
@@ -1347,6 +1353,8 @@ class CortexChatService {
|
|
|
1347
1353
|
return unansweredToolCalls(chat.messages()).length > 0;
|
|
1348
1354
|
}, ...ngDevMode ? [{ debugName: "hasPendingToolCalls" }] : []);
|
|
1349
1355
|
messageMetadata = signal(new Map, ...ngDevMode ? [{ debugName: "messageMetadata" }] : []);
|
|
1356
|
+
attachmentsEnabled = computed(() => this.config().attachments !== false && this.serverAcceptsAttachments(), ...ngDevMode ? [{ debugName: "attachmentsEnabled" }] : []);
|
|
1357
|
+
serverAcceptsAttachments = signal(true, ...ngDevMode ? [{ debugName: "serverAcceptsAttachments" }] : []);
|
|
1350
1358
|
events = new Subject;
|
|
1351
1359
|
selectedThreadSnapshot = signal(undefined, ...ngDevMode ? [{ debugName: "selectedThreadSnapshot" }] : []);
|
|
1352
1360
|
config = inject(CORTEX_CLIENT_CONFIG);
|
|
@@ -1369,6 +1377,7 @@ class CortexChatService {
|
|
|
1369
1377
|
this.threadService.start();
|
|
1370
1378
|
this.subscribeToWsEvents();
|
|
1371
1379
|
this.subscribeToWsConnections();
|
|
1380
|
+
this.api.getCapabilities().then((capabilities) => this.serverAcceptsAttachments.set(capabilities.attachments)).catch(() => {});
|
|
1372
1381
|
}
|
|
1373
1382
|
get events$() {
|
|
1374
1383
|
return this.events.asObservable();
|
|
@@ -1807,6 +1816,7 @@ class ChatComposerComponent {
|
|
|
1807
1816
|
translateService = inject(TranslateService);
|
|
1808
1817
|
text = model("", ...ngDevMode ? [{ debugName: "text" }] : []);
|
|
1809
1818
|
dragging = signal(false, ...ngDevMode ? [{ debugName: "dragging" }] : []);
|
|
1819
|
+
attachmentsEnabled = this.chatService.attachmentsEnabled;
|
|
1810
1820
|
acceptedTypes = ATTACHMENT_MIME_TYPES.join(",");
|
|
1811
1821
|
canSend = computed(() => !this.queue.busy() && (Boolean(this.text().trim()) || this.queue.hasReady()), ...ngDevMode ? [{ debugName: "canSend" }] : []);
|
|
1812
1822
|
messageInput = viewChild("messageInput", ...ngDevMode ? [{ debugName: "messageInput" }] : []);
|
|
@@ -1821,7 +1831,8 @@ class ChatComposerComponent {
|
|
|
1821
1831
|
}
|
|
1822
1832
|
onDragOver(event) {
|
|
1823
1833
|
event.preventDefault();
|
|
1824
|
-
this.
|
|
1834
|
+
if (this.attachmentsEnabled())
|
|
1835
|
+
this.dragging.set(true);
|
|
1825
1836
|
}
|
|
1826
1837
|
onDragLeave(event) {
|
|
1827
1838
|
const area = event.currentTarget;
|
|
@@ -1832,11 +1843,12 @@ class ChatComposerComponent {
|
|
|
1832
1843
|
onDrop(event) {
|
|
1833
1844
|
event.preventDefault();
|
|
1834
1845
|
this.dragging.set(false);
|
|
1835
|
-
this.
|
|
1846
|
+
if (this.attachmentsEnabled())
|
|
1847
|
+
this.queue.accept([...event.dataTransfer?.files ?? []]);
|
|
1836
1848
|
}
|
|
1837
1849
|
onPaste(event) {
|
|
1838
1850
|
const files = event.clipboardData?.files;
|
|
1839
|
-
if (!files?.length)
|
|
1851
|
+
if (!this.attachmentsEnabled() || !files?.length)
|
|
1840
1852
|
return;
|
|
1841
1853
|
event.preventDefault();
|
|
1842
1854
|
this.queue.accept([...files]);
|
|
@@ -1902,31 +1914,33 @@ class ChatComposerComponent {
|
|
|
1902
1914
|
</button>
|
|
1903
1915
|
} @else {
|
|
1904
1916
|
<div class="cortex-widget__input-actions">
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
<
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1917
|
+
@if (attachmentsEnabled()) {
|
|
1918
|
+
<!-- Attach button -->
|
|
1919
|
+
<button
|
|
1920
|
+
type="button"
|
|
1921
|
+
(click)="fileInput.click()"
|
|
1922
|
+
class="cortex-widget__attach-btn"
|
|
1923
|
+
[attr.aria-label]="'translate_attach_files' | translate"
|
|
1924
|
+
>
|
|
1925
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
1926
|
+
<path
|
|
1927
|
+
d="M10.5 5.5 6.2 9.8a1.4 1.4 0 0 0 2 2l4.6-4.6a2.8 2.8 0 0 0-4-4L4.2 7.8a4.2 4.2 0 0 0 6 6l4-4"
|
|
1928
|
+
stroke="currentColor"
|
|
1929
|
+
stroke-width="1.3"
|
|
1930
|
+
stroke-linecap="round"
|
|
1931
|
+
stroke-linejoin="round"
|
|
1932
|
+
/>
|
|
1933
|
+
</svg>
|
|
1934
|
+
</button>
|
|
1935
|
+
<input
|
|
1936
|
+
#fileInput
|
|
1937
|
+
type="file"
|
|
1938
|
+
multiple
|
|
1939
|
+
[accept]="acceptedTypes"
|
|
1940
|
+
(change)="onFilesPicked($event)"
|
|
1941
|
+
class="cortex-widget__file-input"
|
|
1942
|
+
/>
|
|
1943
|
+
}
|
|
1930
1944
|
|
|
1931
1945
|
<!-- Send button -->
|
|
1932
1946
|
<button
|
|
@@ -2003,31 +2017,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
|
|
|
2003
2017
|
</button>
|
|
2004
2018
|
} @else {
|
|
2005
2019
|
<div class="cortex-widget__input-actions">
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
<
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2020
|
+
@if (attachmentsEnabled()) {
|
|
2021
|
+
<!-- Attach button -->
|
|
2022
|
+
<button
|
|
2023
|
+
type="button"
|
|
2024
|
+
(click)="fileInput.click()"
|
|
2025
|
+
class="cortex-widget__attach-btn"
|
|
2026
|
+
[attr.aria-label]="'translate_attach_files' | translate"
|
|
2027
|
+
>
|
|
2028
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
2029
|
+
<path
|
|
2030
|
+
d="M10.5 5.5 6.2 9.8a1.4 1.4 0 0 0 2 2l4.6-4.6a2.8 2.8 0 0 0-4-4L4.2 7.8a4.2 4.2 0 0 0 6 6l4-4"
|
|
2031
|
+
stroke="currentColor"
|
|
2032
|
+
stroke-width="1.3"
|
|
2033
|
+
stroke-linecap="round"
|
|
2034
|
+
stroke-linejoin="round"
|
|
2035
|
+
/>
|
|
2036
|
+
</svg>
|
|
2037
|
+
</button>
|
|
2038
|
+
<input
|
|
2039
|
+
#fileInput
|
|
2040
|
+
type="file"
|
|
2041
|
+
multiple
|
|
2042
|
+
[accept]="acceptedTypes"
|
|
2043
|
+
(change)="onFilesPicked($event)"
|
|
2044
|
+
class="cortex-widget__file-input"
|
|
2045
|
+
/>
|
|
2046
|
+
}
|
|
2031
2047
|
|
|
2032
2048
|
<!-- Send button -->
|
|
2033
2049
|
<button
|
package/package.json
CHANGED
|
@@ -124,6 +124,12 @@ export type CortexConfig = {
|
|
|
124
124
|
/** Prompt chips on the blank-chat landing; clicking one sends it as the first message. */
|
|
125
125
|
suggestions?: Localized<string[]>;
|
|
126
126
|
showDebugButton?: boolean;
|
|
127
|
+
/**
|
|
128
|
+
* Embedder override for the file-upload controls (attach button, drop,
|
|
129
|
+
* paste). The widget already hides them when the server's capability
|
|
130
|
+
* handshake says the agent refuses uploads; `false` hides them regardless.
|
|
131
|
+
*/
|
|
132
|
+
attachments?: boolean;
|
|
127
133
|
/**
|
|
128
134
|
* Render embedded tool pages served from this page's own origin with their
|
|
129
135
|
* full identity — which, same-origin, means no effective sandbox at all: such
|
|
@@ -214,6 +220,13 @@ declare class CortexChatService {
|
|
|
214
220
|
* the stream, and are merged back in by message id at render time.
|
|
215
221
|
*/
|
|
216
222
|
readonly messageMetadata: _angular_core.WritableSignal<ReadonlyMap<string, MessageMetadata>>;
|
|
223
|
+
/**
|
|
224
|
+
* Server capability AND the embedder's `config.attachments` override.
|
|
225
|
+
* Optimistically true until the handshake answers; most agents accept files
|
|
226
|
+
* and a briefly hidden button would flicker for them.
|
|
227
|
+
*/
|
|
228
|
+
readonly attachmentsEnabled: _angular_core.Signal<boolean>;
|
|
229
|
+
private readonly serverAcceptsAttachments;
|
|
217
230
|
private readonly events;
|
|
218
231
|
private readonly selectedThreadSnapshot;
|
|
219
232
|
private readonly config;
|