@threadplane/chat 0.0.56 → 0.0.57
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 +39 -0
- package/fesm2022/threadplane-chat.mjs +1364 -454
- package/fesm2022/threadplane-chat.mjs.map +1 -1
- package/package.json +2 -2
- package/types/threadplane-chat.d.ts +332 -122
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, input, inject, TemplateRef, Directive, contentChildren, computed, ChangeDetectionStrategy, Component, signal, Injectable, ContentChild, effect, output, DOCUMENT, ViewEncapsulation, ElementRef, ViewContainerRef, DestroyRef, viewChild, model, contentChild, untracked, makeEnvironmentProviders, Injector, runInInjectionContext, SecurityContext } from '@angular/core';
|
|
2
|
+
import { InjectionToken, input, inject, TemplateRef, Directive, contentChildren, computed, ChangeDetectionStrategy, Component, signal, Injectable, ContentChild, effect, output, DOCUMENT, ViewEncapsulation, ElementRef, ViewContainerRef, DestroyRef, isDevMode, viewChild, model, contentChild, untracked, makeEnvironmentProviders, Injector, runInInjectionContext, SecurityContext } from '@angular/core';
|
|
3
3
|
import { NgTemplateOutlet, NgComponentOutlet, KeyValuePipe } from '@angular/common';
|
|
4
4
|
import { createPartialMarkdownParser, materialize } from '@cacheplane/partial-markdown';
|
|
5
5
|
import { views, RenderSpecComponent, toRenderRegistry, signalStateStore, withViews, RenderElementComponent, injectRenderHost } from '@threadplane/render';
|
|
@@ -228,6 +228,21 @@ function isSystemMessage(m) {
|
|
|
228
228
|
return m.role === 'system';
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
+
// SPDX-License-Identifier: MIT
|
|
232
|
+
/** Creates the active delivery state for one response-attempt generation. */
|
|
233
|
+
function streamingDelivery(generation) {
|
|
234
|
+
return { generation, phase: 'streaming' };
|
|
235
|
+
}
|
|
236
|
+
/** Creates a terminal delivery state for an existing response-attempt generation. */
|
|
237
|
+
function completeDelivery(generation, outcome) {
|
|
238
|
+
const delivery = { generation, phase: 'complete', outcome };
|
|
239
|
+
return delivery;
|
|
240
|
+
}
|
|
241
|
+
/** Creates a successful terminal delivery state for an already-complete message. */
|
|
242
|
+
function staticDelivery(messageId) {
|
|
243
|
+
return completeDelivery(messageId, 'success');
|
|
244
|
+
}
|
|
245
|
+
|
|
231
246
|
// SPDX-License-Identifier: MIT
|
|
232
247
|
/**
|
|
233
248
|
* Create a typed agent handle.
|
|
@@ -307,9 +322,24 @@ const LIGHT_TOKENS = `
|
|
|
307
322
|
--a2ui-elevation-5: 0 16px 32px rgba(0, 0, 0, 0.18);
|
|
308
323
|
|
|
309
324
|
/* --tplane-chat-citation-* — inline markers, preview card, sources panel */
|
|
310
|
-
--tplane-chat-citation-accent: #
|
|
325
|
+
--tplane-chat-citation-accent: #1d4ed8;
|
|
311
326
|
--tplane-chat-citation-accent-soft: #eaf1fd;
|
|
312
327
|
--tplane-chat-citation-accent-border: #c9def8;
|
|
328
|
+
--tplane-chat-citation-type-web-fg: var(--tplane-chat-citation-accent);
|
|
329
|
+
--tplane-chat-citation-type-web-bg: var(--tplane-chat-citation-accent-soft);
|
|
330
|
+
--tplane-chat-citation-type-web-border: var(--tplane-chat-citation-accent-border);
|
|
331
|
+
--tplane-chat-citation-type-file-fg: #2f684c;
|
|
332
|
+
--tplane-chat-citation-type-file-bg: #edf7f1;
|
|
333
|
+
--tplane-chat-citation-type-file-border: #c8e4d2;
|
|
334
|
+
--tplane-chat-citation-type-app-fg: #7a4d12;
|
|
335
|
+
--tplane-chat-citation-type-app-bg: #fff5e3;
|
|
336
|
+
--tplane-chat-citation-type-app-border: #f0d69f;
|
|
337
|
+
--tplane-chat-citation-type-memory-fg: #67508f;
|
|
338
|
+
--tplane-chat-citation-type-memory-bg: #f3effb;
|
|
339
|
+
--tplane-chat-citation-type-memory-border: #ddd2f1;
|
|
340
|
+
--tplane-chat-citation-type-generic-fg: #526071;
|
|
341
|
+
--tplane-chat-citation-type-generic-bg: #f4f6f8;
|
|
342
|
+
--tplane-chat-citation-type-generic-border: #dfe5ec;
|
|
313
343
|
--tplane-chat-citation-marker-bg: #f1f2f4;
|
|
314
344
|
--tplane-chat-citation-marker-border: var(--tplane-chat-separator);
|
|
315
345
|
--tplane-chat-citation-marker-fg: #4b5563;
|
|
@@ -358,6 +388,21 @@ const DARK_TOKENS = `
|
|
|
358
388
|
--tplane-chat-citation-accent: #6ea8ff;
|
|
359
389
|
--tplane-chat-citation-accent-soft: rgba(79, 141, 245, 0.16);
|
|
360
390
|
--tplane-chat-citation-accent-border: rgba(79, 141, 245, 0.38);
|
|
391
|
+
--tplane-chat-citation-type-web-fg: var(--tplane-chat-citation-accent);
|
|
392
|
+
--tplane-chat-citation-type-web-bg: var(--tplane-chat-citation-accent-soft);
|
|
393
|
+
--tplane-chat-citation-type-web-border: var(--tplane-chat-citation-accent-border);
|
|
394
|
+
--tplane-chat-citation-type-file-fg: #8bd3a9;
|
|
395
|
+
--tplane-chat-citation-type-file-bg: rgba(47, 104, 76, 0.20);
|
|
396
|
+
--tplane-chat-citation-type-file-border: rgba(139, 211, 169, 0.32);
|
|
397
|
+
--tplane-chat-citation-type-app-fg: #f2c36f;
|
|
398
|
+
--tplane-chat-citation-type-app-bg: rgba(122, 77, 18, 0.22);
|
|
399
|
+
--tplane-chat-citation-type-app-border: rgba(242, 195, 111, 0.34);
|
|
400
|
+
--tplane-chat-citation-type-memory-fg: #c4b5fd;
|
|
401
|
+
--tplane-chat-citation-type-memory-bg: rgba(103, 80, 143, 0.26);
|
|
402
|
+
--tplane-chat-citation-type-memory-border: rgba(196, 181, 253, 0.32);
|
|
403
|
+
--tplane-chat-citation-type-generic-fg: #c9ccd1;
|
|
404
|
+
--tplane-chat-citation-type-generic-bg: rgba(255,255,255,0.08);
|
|
405
|
+
--tplane-chat-citation-type-generic-border: rgba(255,255,255,0.14);
|
|
361
406
|
--tplane-chat-citation-marker-bg: rgba(255, 255, 255, 0.08);
|
|
362
407
|
--tplane-chat-citation-marker-border: var(--tplane-chat-separator);
|
|
363
408
|
--tplane-chat-citation-marker-fg: #c9ccd1;
|
|
@@ -854,6 +899,13 @@ const CHAT_MESSAGE_STYLES = `
|
|
|
854
899
|
.chat-message__control-btn svg { width: 16px; height: 16px; pointer-events: none; }
|
|
855
900
|
`;
|
|
856
901
|
|
|
902
|
+
const KNOWN_TYPE_LABELS = {
|
|
903
|
+
web: 'Web',
|
|
904
|
+
file: 'File',
|
|
905
|
+
app: 'App',
|
|
906
|
+
memory: 'Memory',
|
|
907
|
+
generic: 'Generic',
|
|
908
|
+
};
|
|
857
909
|
/** Hostname of `url` with a leading `www.` removed; null if absent/malformed. */
|
|
858
910
|
function deriveDomain(url) {
|
|
859
911
|
if (!url)
|
|
@@ -867,8 +919,9 @@ function deriveDomain(url) {
|
|
|
867
919
|
}
|
|
868
920
|
/** Explicit `sourceType`, else 'web' inferred from a url, else 'unknown'. */
|
|
869
921
|
function deriveSourceType(c) {
|
|
870
|
-
|
|
871
|
-
|
|
922
|
+
const explicit = c.sourceType?.trim();
|
|
923
|
+
if (explicit)
|
|
924
|
+
return explicit;
|
|
872
925
|
return c.url ? 'web' : 'unknown';
|
|
873
926
|
}
|
|
874
927
|
/** Uppercased first letter of the domain (or title) for the monogram chip. */
|
|
@@ -899,16 +952,158 @@ function monogramColor(c) {
|
|
|
899
952
|
const seed = deriveDomain(c.url) ?? c.title ?? '?';
|
|
900
953
|
return `hsl(${monogramHue(seed)} 60% 45%)`;
|
|
901
954
|
}
|
|
955
|
+
function isKnownType(type) {
|
|
956
|
+
return Object.prototype.hasOwnProperty.call(KNOWN_TYPE_LABELS, type);
|
|
957
|
+
}
|
|
958
|
+
function readableSourceTypeLabel(type) {
|
|
959
|
+
const words = type.replace(/[-_\s]+/g, ' ').trim();
|
|
960
|
+
return words ? words.charAt(0).toUpperCase() + words.slice(1) : null;
|
|
961
|
+
}
|
|
962
|
+
/**
|
|
963
|
+
* Derive normalized source-type metadata for badges, icons, and tone tokens.
|
|
964
|
+
*/
|
|
965
|
+
function citationTypeMeta(c) {
|
|
966
|
+
const type = deriveSourceType(c);
|
|
967
|
+
const canonicalType = type.toLowerCase();
|
|
968
|
+
if (isKnownType(canonicalType)) {
|
|
969
|
+
return {
|
|
970
|
+
type: canonicalType,
|
|
971
|
+
label: KNOWN_TYPE_LABELS[canonicalType],
|
|
972
|
+
icon: canonicalType,
|
|
973
|
+
tone: canonicalType,
|
|
974
|
+
isKnown: true,
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
return {
|
|
978
|
+
type,
|
|
979
|
+
label: type === 'unknown' ? null : readableSourceTypeLabel(type),
|
|
980
|
+
icon: 'generic',
|
|
981
|
+
tone: 'generic',
|
|
982
|
+
isKnown: false,
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* Choose the visual source marker for a citation: provider image, type icon, or monogram.
|
|
987
|
+
*/
|
|
988
|
+
function citationSourceVisual(c) {
|
|
989
|
+
const iconUrl = c.iconUrl?.trim();
|
|
990
|
+
if (iconUrl) {
|
|
991
|
+
return { kind: 'image', iconUrl };
|
|
992
|
+
}
|
|
993
|
+
const meta = citationTypeMeta(c);
|
|
994
|
+
if (meta.icon !== 'web') {
|
|
995
|
+
return {
|
|
996
|
+
kind: 'type-icon',
|
|
997
|
+
icon: meta.icon,
|
|
998
|
+
tone: meta.tone,
|
|
999
|
+
label: meta.label,
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
return {
|
|
1003
|
+
kind: 'monogram',
|
|
1004
|
+
monogram: deriveMonogram(c),
|
|
1005
|
+
color: monogramColor(c),
|
|
1006
|
+
};
|
|
1007
|
+
}
|
|
902
1008
|
/** Human label for the source-type badge; null when type is 'unknown'. */
|
|
903
1009
|
function citationTypeLabel(c) {
|
|
904
|
-
|
|
905
|
-
if (t === 'unknown')
|
|
906
|
-
return null;
|
|
907
|
-
return t === 'web' ? 'Web' : t.charAt(0).toUpperCase() + t.slice(1);
|
|
1010
|
+
return citationTypeMeta(c).label;
|
|
908
1011
|
}
|
|
909
1012
|
|
|
910
1013
|
// libs/chat/src/lib/styles/chat-citations.styles.ts
|
|
911
1014
|
// SPDX-License-Identifier: MIT
|
|
1015
|
+
const CHAT_CITATION_SOURCE_VISUAL_STYLES = `
|
|
1016
|
+
.chat-citation-source-icon {
|
|
1017
|
+
width: 18px;
|
|
1018
|
+
height: 18px;
|
|
1019
|
+
flex: 0 0 auto;
|
|
1020
|
+
box-sizing: border-box;
|
|
1021
|
+
display: inline-flex;
|
|
1022
|
+
align-items: center;
|
|
1023
|
+
justify-content: center;
|
|
1024
|
+
border-radius: 5px;
|
|
1025
|
+
border: 1px solid currentColor;
|
|
1026
|
+
}
|
|
1027
|
+
.chat-citation-source-icon svg {
|
|
1028
|
+
width: 12px;
|
|
1029
|
+
height: 12px;
|
|
1030
|
+
display: block;
|
|
1031
|
+
}
|
|
1032
|
+
.chat-citation-source-icon--sm {
|
|
1033
|
+
width: 14px;
|
|
1034
|
+
height: 14px;
|
|
1035
|
+
border-radius: 4px;
|
|
1036
|
+
}
|
|
1037
|
+
.chat-citation-source-icon--sm svg {
|
|
1038
|
+
width: 9px;
|
|
1039
|
+
height: 9px;
|
|
1040
|
+
}
|
|
1041
|
+
.chat-citation-source-icon--web {
|
|
1042
|
+
color: var(--tplane-chat-citation-type-web-fg);
|
|
1043
|
+
background: var(--tplane-chat-citation-type-web-bg);
|
|
1044
|
+
border-color: var(--tplane-chat-citation-type-web-border);
|
|
1045
|
+
}
|
|
1046
|
+
.chat-citation-source-icon--file {
|
|
1047
|
+
color: var(--tplane-chat-citation-type-file-fg);
|
|
1048
|
+
background: var(--tplane-chat-citation-type-file-bg);
|
|
1049
|
+
border-color: var(--tplane-chat-citation-type-file-border);
|
|
1050
|
+
}
|
|
1051
|
+
.chat-citation-source-icon--app {
|
|
1052
|
+
color: var(--tplane-chat-citation-type-app-fg);
|
|
1053
|
+
background: var(--tplane-chat-citation-type-app-bg);
|
|
1054
|
+
border-color: var(--tplane-chat-citation-type-app-border);
|
|
1055
|
+
}
|
|
1056
|
+
.chat-citation-source-icon--memory {
|
|
1057
|
+
color: var(--tplane-chat-citation-type-memory-fg);
|
|
1058
|
+
background: var(--tplane-chat-citation-type-memory-bg);
|
|
1059
|
+
border-color: var(--tplane-chat-citation-type-memory-border);
|
|
1060
|
+
}
|
|
1061
|
+
.chat-citation-source-icon--generic {
|
|
1062
|
+
color: var(--tplane-chat-citation-type-generic-fg);
|
|
1063
|
+
background: var(--tplane-chat-citation-type-generic-bg);
|
|
1064
|
+
border-color: var(--tplane-chat-citation-type-generic-border);
|
|
1065
|
+
}
|
|
1066
|
+
.chat-citation-type-badge {
|
|
1067
|
+
display: inline-flex;
|
|
1068
|
+
align-items: center;
|
|
1069
|
+
justify-content: center;
|
|
1070
|
+
min-width: 0;
|
|
1071
|
+
max-width: 120px;
|
|
1072
|
+
box-sizing: border-box;
|
|
1073
|
+
padding: 1px 6px;
|
|
1074
|
+
border: 1px solid currentColor;
|
|
1075
|
+
border-radius: 999px;
|
|
1076
|
+
overflow: hidden;
|
|
1077
|
+
text-overflow: ellipsis;
|
|
1078
|
+
white-space: nowrap;
|
|
1079
|
+
line-height: 1.35;
|
|
1080
|
+
}
|
|
1081
|
+
.chat-citation-type-badge--web {
|
|
1082
|
+
color: var(--tplane-chat-citation-type-web-fg);
|
|
1083
|
+
background: var(--tplane-chat-citation-type-web-bg);
|
|
1084
|
+
border-color: var(--tplane-chat-citation-type-web-border);
|
|
1085
|
+
}
|
|
1086
|
+
.chat-citation-type-badge--file {
|
|
1087
|
+
color: var(--tplane-chat-citation-type-file-fg);
|
|
1088
|
+
background: var(--tplane-chat-citation-type-file-bg);
|
|
1089
|
+
border-color: var(--tplane-chat-citation-type-file-border);
|
|
1090
|
+
}
|
|
1091
|
+
.chat-citation-type-badge--app {
|
|
1092
|
+
color: var(--tplane-chat-citation-type-app-fg);
|
|
1093
|
+
background: var(--tplane-chat-citation-type-app-bg);
|
|
1094
|
+
border-color: var(--tplane-chat-citation-type-app-border);
|
|
1095
|
+
}
|
|
1096
|
+
.chat-citation-type-badge--memory {
|
|
1097
|
+
color: var(--tplane-chat-citation-type-memory-fg);
|
|
1098
|
+
background: var(--tplane-chat-citation-type-memory-bg);
|
|
1099
|
+
border-color: var(--tplane-chat-citation-type-memory-border);
|
|
1100
|
+
}
|
|
1101
|
+
.chat-citation-type-badge--generic {
|
|
1102
|
+
color: var(--tplane-chat-citation-type-generic-fg);
|
|
1103
|
+
background: var(--tplane-chat-citation-type-generic-bg);
|
|
1104
|
+
border-color: var(--tplane-chat-citation-type-generic-border);
|
|
1105
|
+
}
|
|
1106
|
+
`;
|
|
912
1107
|
/** Inline pill marker (chat-md-citation-reference). */
|
|
913
1108
|
const CHAT_CITATION_MARKER_STYLES = `
|
|
914
1109
|
:host { display: inline; }
|
|
@@ -960,6 +1155,7 @@ const CHAT_CITATION_MARKER_STYLES = `
|
|
|
960
1155
|
`;
|
|
961
1156
|
/** Provenance preview card (chat-citation-preview), portaled into the overlay pane. */
|
|
962
1157
|
const CHAT_CITATION_PREVIEW_STYLES = `
|
|
1158
|
+
${CHAT_CITATION_SOURCE_VISUAL_STYLES}
|
|
963
1159
|
:host { display: block; }
|
|
964
1160
|
.chat-citation-preview {
|
|
965
1161
|
width: 320px;
|
|
@@ -997,7 +1193,6 @@ const CHAT_CITATION_PREVIEW_STYLES = `
|
|
|
997
1193
|
.chat-citation-preview__type {
|
|
998
1194
|
margin-left: auto;
|
|
999
1195
|
font-size: 11px;
|
|
1000
|
-
color: var(--tplane-chat-text-muted);
|
|
1001
1196
|
flex: 0 0 auto;
|
|
1002
1197
|
}
|
|
1003
1198
|
.chat-citation-preview__title {
|
|
@@ -1026,6 +1221,7 @@ const CHAT_CITATION_PREVIEW_STYLES = `
|
|
|
1026
1221
|
`;
|
|
1027
1222
|
/** Sources panel (chat-citations) + detail card (chat-citations-card). */
|
|
1028
1223
|
const CHAT_CITATIONS_PANEL_STYLES = `
|
|
1224
|
+
${CHAT_CITATION_SOURCE_VISUAL_STYLES}
|
|
1029
1225
|
:host { display: block; }
|
|
1030
1226
|
.chat-citations {
|
|
1031
1227
|
margin-top: var(--tplane-chat-space-5);
|
|
@@ -1062,6 +1258,16 @@ const CHAT_CITATIONS_PANEL_STYLES = `
|
|
|
1062
1258
|
display: flex; align-items: center; justify-content: center;
|
|
1063
1259
|
color: #fff; font-size: 9px; font-weight: 700;
|
|
1064
1260
|
}
|
|
1261
|
+
.chat-citations__source-icon {
|
|
1262
|
+
width: 16px; height: 16px;
|
|
1263
|
+
border-radius: 4px;
|
|
1264
|
+
margin-left: -5px;
|
|
1265
|
+
border-width: 1.5px;
|
|
1266
|
+
}
|
|
1267
|
+
.chat-citations__source-icon:first-child { margin-left: 0; }
|
|
1268
|
+
.chat-citations__source-icon svg {
|
|
1269
|
+
width: 10px; height: 10px;
|
|
1270
|
+
}
|
|
1065
1271
|
.chat-citations__chevron {
|
|
1066
1272
|
margin-left: auto;
|
|
1067
1273
|
color: var(--tplane-chat-text-muted);
|
|
@@ -1112,7 +1318,7 @@ const CHAT_CITATIONS_PANEL_STYLES = `
|
|
|
1112
1318
|
color: #fff; font-size: 8px; font-weight: 700;
|
|
1113
1319
|
}
|
|
1114
1320
|
.chat-citations-card__domain { font-size: 11.5px; color: var(--tplane-chat-text-muted); }
|
|
1115
|
-
.chat-citations-card__type { margin-left: auto; font-size: 10.5px;
|
|
1321
|
+
.chat-citations-card__type { margin-left: auto; font-size: 10.5px; }
|
|
1116
1322
|
.chat-citations-card__title {
|
|
1117
1323
|
font-size: 13.5px; font-weight: 600; line-height: 1.35;
|
|
1118
1324
|
margin: 0 0 2px;
|
|
@@ -1135,11 +1341,31 @@ const CHAT_CITATIONS_PANEL_STYLES = `
|
|
|
1135
1341
|
*/
|
|
1136
1342
|
class ChatCitationsCardComponent {
|
|
1137
1343
|
citation = input.required(...(ngDevMode ? [{ debugName: "citation" }] : []));
|
|
1344
|
+
sourceVisual = computed(() => citationSourceVisual(this.citation()), ...(ngDevMode ? [{ debugName: "sourceVisual" }] : []));
|
|
1345
|
+
typeMeta = computed(() => citationTypeMeta(this.citation()), ...(ngDevMode ? [{ debugName: "typeMeta" }] : []));
|
|
1138
1346
|
domain = computed(() => deriveDomain(this.citation().url), ...(ngDevMode ? [{ debugName: "domain" }] : []));
|
|
1139
1347
|
title = computed(() => this.citation().title ?? this.citation().url ?? null, ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1348
|
+
sourceIconUrl = computed(() => {
|
|
1349
|
+
const visual = this.sourceVisual();
|
|
1350
|
+
return visual.kind === 'image' ? visual.iconUrl : null;
|
|
1351
|
+
}, ...(ngDevMode ? [{ debugName: "sourceIconUrl" }] : []));
|
|
1352
|
+
sourceIcon = computed(() => {
|
|
1353
|
+
const visual = this.sourceVisual();
|
|
1354
|
+
return visual.kind === 'type-icon' ? visual.icon : null;
|
|
1355
|
+
}, ...(ngDevMode ? [{ debugName: "sourceIcon" }] : []));
|
|
1356
|
+
sourceMonogram = computed(() => {
|
|
1357
|
+
const visual = this.sourceVisual();
|
|
1358
|
+
return visual.kind === 'monogram' ? visual.monogram : null;
|
|
1359
|
+
}, ...(ngDevMode ? [{ debugName: "sourceMonogram" }] : []));
|
|
1360
|
+
sourceMonoColor = computed(() => {
|
|
1361
|
+
const visual = this.sourceVisual();
|
|
1362
|
+
return visual.kind === 'monogram' ? visual.color : null;
|
|
1363
|
+
}, ...(ngDevMode ? [{ debugName: "sourceMonoColor" }] : []));
|
|
1364
|
+
typeLabel = computed(() => this.typeMeta().label, ...(ngDevMode ? [{ debugName: "typeLabel" }] : []));
|
|
1365
|
+
typeTone = computed(() => this.typeMeta().tone, ...(ngDevMode ? [{ debugName: "typeTone" }] : []));
|
|
1366
|
+
isTypeTone(tone) {
|
|
1367
|
+
return this.typeTone() === tone;
|
|
1368
|
+
}
|
|
1143
1369
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatCitationsCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1144
1370
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: ChatCitationsCardComponent, isStandalone: true, selector: "chat-citations-card", inputs: { citation: { classPropertyName: "citation", publicName: "citation", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
|
|
1145
1371
|
@if (citation().url; as url) {
|
|
@@ -1157,14 +1383,54 @@ class ChatCitationsCardComponent {
|
|
|
1157
1383
|
<span class="chat-citations-card__index">{{ citation().index }}</span>
|
|
1158
1384
|
<span class="chat-citations-card__body">
|
|
1159
1385
|
<span class="chat-citations-card__top">
|
|
1160
|
-
@if (
|
|
1386
|
+
@if (sourceIconUrl(); as icon) {
|
|
1161
1387
|
<img class="chat-citations-card__fav" [src]="icon" alt="" width="14" height="14" />
|
|
1388
|
+
} @else if (sourceIcon(); as icon) {
|
|
1389
|
+
<span class="chat-citation-source-icon chat-citation-source-icon--sm chat-citations-card__source-icon"
|
|
1390
|
+
aria-hidden="true"
|
|
1391
|
+
[class.chat-citation-source-icon--web]="icon === 'web'"
|
|
1392
|
+
[class.chat-citation-source-icon--file]="icon === 'file'"
|
|
1393
|
+
[class.chat-citation-source-icon--app]="icon === 'app'"
|
|
1394
|
+
[class.chat-citation-source-icon--memory]="icon === 'memory'"
|
|
1395
|
+
[class.chat-citation-source-icon--generic]="icon === 'generic'">
|
|
1396
|
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
1397
|
+
@switch (icon) {
|
|
1398
|
+
@case ('file') {
|
|
1399
|
+
<path d="M7 3.5h6.5L18 8v12.5H7z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" />
|
|
1400
|
+
<path d="M13.5 3.5V8H18M9.5 13h5M9.5 16h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1401
|
+
}
|
|
1402
|
+
@case ('app') {
|
|
1403
|
+
<rect x="4" y="5" width="16" height="14" rx="2.5" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
1404
|
+
<path d="M8 9h.01M11.5 9h.01M15 9h.01M8 12.5h8M8 16h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1405
|
+
}
|
|
1406
|
+
@case ('memory') {
|
|
1407
|
+
<path d="M8 7.5a4 4 0 0 1 8 0v9a4 4 0 0 1-8 0z" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
1408
|
+
<path d="M12 4v16M8 10h8M8 14h8" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1409
|
+
}
|
|
1410
|
+
@case ('web') {
|
|
1411
|
+
<circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
1412
|
+
<path d="M4.5 12h15M12 4a12 12 0 0 1 0 16M12 4a12 12 0 0 0 0 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1413
|
+
}
|
|
1414
|
+
@default {
|
|
1415
|
+
<path d="M6 5.5h12v13H6z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" />
|
|
1416
|
+
<path d="M9 9h6M9 12h6M9 15h3" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
</svg>
|
|
1420
|
+
</span>
|
|
1162
1421
|
} @else {
|
|
1163
1422
|
<span class="chat-citations-card__fav chat-citations-card__fav--mono"
|
|
1164
|
-
[style.background]="
|
|
1423
|
+
[style.background]="sourceMonoColor()">{{ sourceMonogram() }}</span>
|
|
1165
1424
|
}
|
|
1166
1425
|
@if (domain(); as d) { <span class="chat-citations-card__domain">{{ d }}</span> }
|
|
1167
|
-
@if (typeLabel(); as t) {
|
|
1426
|
+
@if (typeLabel(); as t) {
|
|
1427
|
+
<span class="chat-citations-card__type chat-citation-type-badge"
|
|
1428
|
+
[class.chat-citation-type-badge--web]="isTypeTone('web')"
|
|
1429
|
+
[class.chat-citation-type-badge--file]="isTypeTone('file')"
|
|
1430
|
+
[class.chat-citation-type-badge--app]="isTypeTone('app')"
|
|
1431
|
+
[class.chat-citation-type-badge--memory]="isTypeTone('memory')"
|
|
1432
|
+
[class.chat-citation-type-badge--generic]="isTypeTone('generic')">{{ t }}</span>
|
|
1433
|
+
}
|
|
1168
1434
|
</span>
|
|
1169
1435
|
@if (title(); as t) {
|
|
1170
1436
|
<span class="chat-citations-card__title">{{ t }}</span>
|
|
@@ -1174,7 +1440,7 @@ class ChatCitationsCardComponent {
|
|
|
1174
1440
|
}
|
|
1175
1441
|
</span>
|
|
1176
1442
|
</ng-template>
|
|
1177
|
-
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block}.chat-citations{margin-top:var(--tplane-chat-space-5);padding-top:var(--tplane-chat-space-4);border-top:1px solid var(--tplane-chat-separator)}.chat-citations__header{display:flex;align-items:center;gap:9px;width:100%;padding:0 0 11px;background:none;border:0;font:inherit;color:inherit;cursor:pointer;text-align:left}.chat-citations__heading{font-size:13px;font-weight:600}.chat-citations__count{font-size:11px;font-weight:600;color:var(--tplane-chat-text-muted);background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);border-radius:20px;padding:1px 7px}.chat-citations__favstack{display:flex;margin-left:2px}.chat-citations__fav{width:16px;height:16px;border-radius:4px;margin-left:-5px;border:1.5px solid var(--tplane-chat-surface);object-fit:cover}.chat-citations__fav:first-child{margin-left:0}.chat-citations__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:9px;font-weight:700}.chat-citations__chevron{margin-left:auto;color:var(--tplane-chat-text-muted);transition:transform .12s ease}.chat-citations__chevron.is-open{transform:rotate(180deg)}.chat-citations__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.chat-citations__item{margin:0}.chat-citations-card{display:flex;gap:10px;padding:10px 11px;background:var(--tplane-chat-surface);border:1px solid var(--tplane-chat-separator);border-radius:var(--tplane-chat-radius-card);text-decoration:none;color:inherit;cursor:pointer;transition:border-color .12s ease,background .12s ease}.chat-citations-card:hover,.chat-citations-card:focus-visible{border-color:var(--tplane-chat-citation-accent-border);outline:none}.chat-citations-card__index{flex:0 0 auto;width:18px;height:18px;border-radius:5px;background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);color:var(--tplane-chat-text-muted);font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center;margin-top:1px}.chat-citations-card__body{min-width:0;flex:1}.chat-citations-card__top{display:flex;align-items:center;gap:6px;margin-bottom:3px}.chat-citations-card__fav{width:14px;height:14px;border-radius:3px;flex:0 0 auto;object-fit:cover}.chat-citations-card__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:8px;font-weight:700}.chat-citations-card__domain{font-size:11.5px;color:var(--tplane-chat-text-muted)}.chat-citations-card__type{margin-left:auto;font-size:10.5px
|
|
1443
|
+
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ".chat-citation-source-icon{width:18px;height:18px;flex:0 0 auto;box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;border-radius:5px;border:1px solid currentColor}.chat-citation-source-icon svg{width:12px;height:12px;display:block}.chat-citation-source-icon--sm{width:14px;height:14px;border-radius:4px}.chat-citation-source-icon--sm svg{width:9px;height:9px}.chat-citation-source-icon--web{color:var(--tplane-chat-citation-type-web-fg);background:var(--tplane-chat-citation-type-web-bg);border-color:var(--tplane-chat-citation-type-web-border)}.chat-citation-source-icon--file{color:var(--tplane-chat-citation-type-file-fg);background:var(--tplane-chat-citation-type-file-bg);border-color:var(--tplane-chat-citation-type-file-border)}.chat-citation-source-icon--app{color:var(--tplane-chat-citation-type-app-fg);background:var(--tplane-chat-citation-type-app-bg);border-color:var(--tplane-chat-citation-type-app-border)}.chat-citation-source-icon--memory{color:var(--tplane-chat-citation-type-memory-fg);background:var(--tplane-chat-citation-type-memory-bg);border-color:var(--tplane-chat-citation-type-memory-border)}.chat-citation-source-icon--generic{color:var(--tplane-chat-citation-type-generic-fg);background:var(--tplane-chat-citation-type-generic-bg);border-color:var(--tplane-chat-citation-type-generic-border)}.chat-citation-type-badge{display:inline-flex;align-items:center;justify-content:center;min-width:0;max-width:120px;box-sizing:border-box;padding:1px 6px;border:1px solid currentColor;border-radius:999px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.35}.chat-citation-type-badge--web{color:var(--tplane-chat-citation-type-web-fg);background:var(--tplane-chat-citation-type-web-bg);border-color:var(--tplane-chat-citation-type-web-border)}.chat-citation-type-badge--file{color:var(--tplane-chat-citation-type-file-fg);background:var(--tplane-chat-citation-type-file-bg);border-color:var(--tplane-chat-citation-type-file-border)}.chat-citation-type-badge--app{color:var(--tplane-chat-citation-type-app-fg);background:var(--tplane-chat-citation-type-app-bg);border-color:var(--tplane-chat-citation-type-app-border)}.chat-citation-type-badge--memory{color:var(--tplane-chat-citation-type-memory-fg);background:var(--tplane-chat-citation-type-memory-bg);border-color:var(--tplane-chat-citation-type-memory-border)}.chat-citation-type-badge--generic{color:var(--tplane-chat-citation-type-generic-fg);background:var(--tplane-chat-citation-type-generic-bg);border-color:var(--tplane-chat-citation-type-generic-border)}:host{display:block}.chat-citations{margin-top:var(--tplane-chat-space-5);padding-top:var(--tplane-chat-space-4);border-top:1px solid var(--tplane-chat-separator)}.chat-citations__header{display:flex;align-items:center;gap:9px;width:100%;padding:0 0 11px;background:none;border:0;font:inherit;color:inherit;cursor:pointer;text-align:left}.chat-citations__heading{font-size:13px;font-weight:600}.chat-citations__count{font-size:11px;font-weight:600;color:var(--tplane-chat-text-muted);background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);border-radius:20px;padding:1px 7px}.chat-citations__favstack{display:flex;margin-left:2px}.chat-citations__fav{width:16px;height:16px;border-radius:4px;margin-left:-5px;border:1.5px solid var(--tplane-chat-surface);object-fit:cover}.chat-citations__fav:first-child{margin-left:0}.chat-citations__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:9px;font-weight:700}.chat-citations__source-icon{width:16px;height:16px;border-radius:4px;margin-left:-5px;border-width:1.5px}.chat-citations__source-icon:first-child{margin-left:0}.chat-citations__source-icon svg{width:10px;height:10px}.chat-citations__chevron{margin-left:auto;color:var(--tplane-chat-text-muted);transition:transform .12s ease}.chat-citations__chevron.is-open{transform:rotate(180deg)}.chat-citations__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.chat-citations__item{margin:0}.chat-citations-card{display:flex;gap:10px;padding:10px 11px;background:var(--tplane-chat-surface);border:1px solid var(--tplane-chat-separator);border-radius:var(--tplane-chat-radius-card);text-decoration:none;color:inherit;cursor:pointer;transition:border-color .12s ease,background .12s ease}.chat-citations-card:hover,.chat-citations-card:focus-visible{border-color:var(--tplane-chat-citation-accent-border);outline:none}.chat-citations-card__index{flex:0 0 auto;width:18px;height:18px;border-radius:5px;background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);color:var(--tplane-chat-text-muted);font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center;margin-top:1px}.chat-citations-card__body{min-width:0;flex:1}.chat-citations-card__top{display:flex;align-items:center;gap:6px;margin-bottom:3px}.chat-citations-card__fav{width:14px;height:14px;border-radius:3px;flex:0 0 auto;object-fit:cover}.chat-citations-card__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:8px;font-weight:700}.chat-citations-card__domain{font-size:11.5px;color:var(--tplane-chat-text-muted)}.chat-citations-card__type{margin-left:auto;font-size:10.5px}.chat-citations-card__title{font-size:13.5px;font-weight:600;line-height:1.35;margin:0 0 2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chat-citations-card:hover .chat-citations-card__title{color:var(--tplane-chat-citation-accent)}.chat-citations-card__snippet{font-size:12px;color:var(--tplane-chat-text-muted);line-height:1.45;margin:0;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1178
1444
|
}
|
|
1179
1445
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatCitationsCardComponent, decorators: [{
|
|
1180
1446
|
type: Component,
|
|
@@ -1194,14 +1460,54 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
1194
1460
|
<span class="chat-citations-card__index">{{ citation().index }}</span>
|
|
1195
1461
|
<span class="chat-citations-card__body">
|
|
1196
1462
|
<span class="chat-citations-card__top">
|
|
1197
|
-
@if (
|
|
1463
|
+
@if (sourceIconUrl(); as icon) {
|
|
1198
1464
|
<img class="chat-citations-card__fav" [src]="icon" alt="" width="14" height="14" />
|
|
1465
|
+
} @else if (sourceIcon(); as icon) {
|
|
1466
|
+
<span class="chat-citation-source-icon chat-citation-source-icon--sm chat-citations-card__source-icon"
|
|
1467
|
+
aria-hidden="true"
|
|
1468
|
+
[class.chat-citation-source-icon--web]="icon === 'web'"
|
|
1469
|
+
[class.chat-citation-source-icon--file]="icon === 'file'"
|
|
1470
|
+
[class.chat-citation-source-icon--app]="icon === 'app'"
|
|
1471
|
+
[class.chat-citation-source-icon--memory]="icon === 'memory'"
|
|
1472
|
+
[class.chat-citation-source-icon--generic]="icon === 'generic'">
|
|
1473
|
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
1474
|
+
@switch (icon) {
|
|
1475
|
+
@case ('file') {
|
|
1476
|
+
<path d="M7 3.5h6.5L18 8v12.5H7z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" />
|
|
1477
|
+
<path d="M13.5 3.5V8H18M9.5 13h5M9.5 16h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1478
|
+
}
|
|
1479
|
+
@case ('app') {
|
|
1480
|
+
<rect x="4" y="5" width="16" height="14" rx="2.5" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
1481
|
+
<path d="M8 9h.01M11.5 9h.01M15 9h.01M8 12.5h8M8 16h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1482
|
+
}
|
|
1483
|
+
@case ('memory') {
|
|
1484
|
+
<path d="M8 7.5a4 4 0 0 1 8 0v9a4 4 0 0 1-8 0z" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
1485
|
+
<path d="M12 4v16M8 10h8M8 14h8" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1486
|
+
}
|
|
1487
|
+
@case ('web') {
|
|
1488
|
+
<circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
1489
|
+
<path d="M4.5 12h15M12 4a12 12 0 0 1 0 16M12 4a12 12 0 0 0 0 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1490
|
+
}
|
|
1491
|
+
@default {
|
|
1492
|
+
<path d="M6 5.5h12v13H6z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" />
|
|
1493
|
+
<path d="M9 9h6M9 12h6M9 15h3" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
</svg>
|
|
1497
|
+
</span>
|
|
1199
1498
|
} @else {
|
|
1200
1499
|
<span class="chat-citations-card__fav chat-citations-card__fav--mono"
|
|
1201
|
-
[style.background]="
|
|
1500
|
+
[style.background]="sourceMonoColor()">{{ sourceMonogram() }}</span>
|
|
1202
1501
|
}
|
|
1203
1502
|
@if (domain(); as d) { <span class="chat-citations-card__domain">{{ d }}</span> }
|
|
1204
|
-
@if (typeLabel(); as t) {
|
|
1503
|
+
@if (typeLabel(); as t) {
|
|
1504
|
+
<span class="chat-citations-card__type chat-citation-type-badge"
|
|
1505
|
+
[class.chat-citation-type-badge--web]="isTypeTone('web')"
|
|
1506
|
+
[class.chat-citation-type-badge--file]="isTypeTone('file')"
|
|
1507
|
+
[class.chat-citation-type-badge--app]="isTypeTone('app')"
|
|
1508
|
+
[class.chat-citation-type-badge--memory]="isTypeTone('memory')"
|
|
1509
|
+
[class.chat-citation-type-badge--generic]="isTypeTone('generic')">{{ t }}</span>
|
|
1510
|
+
}
|
|
1205
1511
|
</span>
|
|
1206
1512
|
@if (title(); as t) {
|
|
1207
1513
|
<span class="chat-citations-card__title">{{ t }}</span>
|
|
@@ -1211,7 +1517,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
1211
1517
|
}
|
|
1212
1518
|
</span>
|
|
1213
1519
|
</ng-template>
|
|
1214
|
-
`, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block}.chat-citations{margin-top:var(--tplane-chat-space-5);padding-top:var(--tplane-chat-space-4);border-top:1px solid var(--tplane-chat-separator)}.chat-citations__header{display:flex;align-items:center;gap:9px;width:100%;padding:0 0 11px;background:none;border:0;font:inherit;color:inherit;cursor:pointer;text-align:left}.chat-citations__heading{font-size:13px;font-weight:600}.chat-citations__count{font-size:11px;font-weight:600;color:var(--tplane-chat-text-muted);background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);border-radius:20px;padding:1px 7px}.chat-citations__favstack{display:flex;margin-left:2px}.chat-citations__fav{width:16px;height:16px;border-radius:4px;margin-left:-5px;border:1.5px solid var(--tplane-chat-surface);object-fit:cover}.chat-citations__fav:first-child{margin-left:0}.chat-citations__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:9px;font-weight:700}.chat-citations__chevron{margin-left:auto;color:var(--tplane-chat-text-muted);transition:transform .12s ease}.chat-citations__chevron.is-open{transform:rotate(180deg)}.chat-citations__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.chat-citations__item{margin:0}.chat-citations-card{display:flex;gap:10px;padding:10px 11px;background:var(--tplane-chat-surface);border:1px solid var(--tplane-chat-separator);border-radius:var(--tplane-chat-radius-card);text-decoration:none;color:inherit;cursor:pointer;transition:border-color .12s ease,background .12s ease}.chat-citations-card:hover,.chat-citations-card:focus-visible{border-color:var(--tplane-chat-citation-accent-border);outline:none}.chat-citations-card__index{flex:0 0 auto;width:18px;height:18px;border-radius:5px;background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);color:var(--tplane-chat-text-muted);font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center;margin-top:1px}.chat-citations-card__body{min-width:0;flex:1}.chat-citations-card__top{display:flex;align-items:center;gap:6px;margin-bottom:3px}.chat-citations-card__fav{width:14px;height:14px;border-radius:3px;flex:0 0 auto;object-fit:cover}.chat-citations-card__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:8px;font-weight:700}.chat-citations-card__domain{font-size:11.5px;color:var(--tplane-chat-text-muted)}.chat-citations-card__type{margin-left:auto;font-size:10.5px
|
|
1520
|
+
`, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ".chat-citation-source-icon{width:18px;height:18px;flex:0 0 auto;box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;border-radius:5px;border:1px solid currentColor}.chat-citation-source-icon svg{width:12px;height:12px;display:block}.chat-citation-source-icon--sm{width:14px;height:14px;border-radius:4px}.chat-citation-source-icon--sm svg{width:9px;height:9px}.chat-citation-source-icon--web{color:var(--tplane-chat-citation-type-web-fg);background:var(--tplane-chat-citation-type-web-bg);border-color:var(--tplane-chat-citation-type-web-border)}.chat-citation-source-icon--file{color:var(--tplane-chat-citation-type-file-fg);background:var(--tplane-chat-citation-type-file-bg);border-color:var(--tplane-chat-citation-type-file-border)}.chat-citation-source-icon--app{color:var(--tplane-chat-citation-type-app-fg);background:var(--tplane-chat-citation-type-app-bg);border-color:var(--tplane-chat-citation-type-app-border)}.chat-citation-source-icon--memory{color:var(--tplane-chat-citation-type-memory-fg);background:var(--tplane-chat-citation-type-memory-bg);border-color:var(--tplane-chat-citation-type-memory-border)}.chat-citation-source-icon--generic{color:var(--tplane-chat-citation-type-generic-fg);background:var(--tplane-chat-citation-type-generic-bg);border-color:var(--tplane-chat-citation-type-generic-border)}.chat-citation-type-badge{display:inline-flex;align-items:center;justify-content:center;min-width:0;max-width:120px;box-sizing:border-box;padding:1px 6px;border:1px solid currentColor;border-radius:999px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.35}.chat-citation-type-badge--web{color:var(--tplane-chat-citation-type-web-fg);background:var(--tplane-chat-citation-type-web-bg);border-color:var(--tplane-chat-citation-type-web-border)}.chat-citation-type-badge--file{color:var(--tplane-chat-citation-type-file-fg);background:var(--tplane-chat-citation-type-file-bg);border-color:var(--tplane-chat-citation-type-file-border)}.chat-citation-type-badge--app{color:var(--tplane-chat-citation-type-app-fg);background:var(--tplane-chat-citation-type-app-bg);border-color:var(--tplane-chat-citation-type-app-border)}.chat-citation-type-badge--memory{color:var(--tplane-chat-citation-type-memory-fg);background:var(--tplane-chat-citation-type-memory-bg);border-color:var(--tplane-chat-citation-type-memory-border)}.chat-citation-type-badge--generic{color:var(--tplane-chat-citation-type-generic-fg);background:var(--tplane-chat-citation-type-generic-bg);border-color:var(--tplane-chat-citation-type-generic-border)}:host{display:block}.chat-citations{margin-top:var(--tplane-chat-space-5);padding-top:var(--tplane-chat-space-4);border-top:1px solid var(--tplane-chat-separator)}.chat-citations__header{display:flex;align-items:center;gap:9px;width:100%;padding:0 0 11px;background:none;border:0;font:inherit;color:inherit;cursor:pointer;text-align:left}.chat-citations__heading{font-size:13px;font-weight:600}.chat-citations__count{font-size:11px;font-weight:600;color:var(--tplane-chat-text-muted);background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);border-radius:20px;padding:1px 7px}.chat-citations__favstack{display:flex;margin-left:2px}.chat-citations__fav{width:16px;height:16px;border-radius:4px;margin-left:-5px;border:1.5px solid var(--tplane-chat-surface);object-fit:cover}.chat-citations__fav:first-child{margin-left:0}.chat-citations__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:9px;font-weight:700}.chat-citations__source-icon{width:16px;height:16px;border-radius:4px;margin-left:-5px;border-width:1.5px}.chat-citations__source-icon:first-child{margin-left:0}.chat-citations__source-icon svg{width:10px;height:10px}.chat-citations__chevron{margin-left:auto;color:var(--tplane-chat-text-muted);transition:transform .12s ease}.chat-citations__chevron.is-open{transform:rotate(180deg)}.chat-citations__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.chat-citations__item{margin:0}.chat-citations-card{display:flex;gap:10px;padding:10px 11px;background:var(--tplane-chat-surface);border:1px solid var(--tplane-chat-separator);border-radius:var(--tplane-chat-radius-card);text-decoration:none;color:inherit;cursor:pointer;transition:border-color .12s ease,background .12s ease}.chat-citations-card:hover,.chat-citations-card:focus-visible{border-color:var(--tplane-chat-citation-accent-border);outline:none}.chat-citations-card__index{flex:0 0 auto;width:18px;height:18px;border-radius:5px;background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);color:var(--tplane-chat-text-muted);font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center;margin-top:1px}.chat-citations-card__body{min-width:0;flex:1}.chat-citations-card__top{display:flex;align-items:center;gap:6px;margin-bottom:3px}.chat-citations-card__fav{width:14px;height:14px;border-radius:3px;flex:0 0 auto;object-fit:cover}.chat-citations-card__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:8px;font-weight:700}.chat-citations-card__domain{font-size:11.5px;color:var(--tplane-chat-text-muted)}.chat-citations-card__type{margin-left:auto;font-size:10.5px}.chat-citations-card__title{font-size:13.5px;font-weight:600;line-height:1.35;margin:0 0 2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chat-citations-card:hover .chat-citations-card__title{color:var(--tplane-chat-citation-accent)}.chat-citations-card__snippet{font-size:12px;color:var(--tplane-chat-text-muted);line-height:1.45;margin:0;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}\n"] }]
|
|
1215
1521
|
}], propDecorators: { citation: [{ type: i0.Input, args: [{ isSignal: true, alias: "citation", required: true }] }] } });
|
|
1216
1522
|
|
|
1217
1523
|
// libs/chat/src/lib/markdown/citations-resolver.service.ts
|
|
@@ -1308,9 +1614,7 @@ class ChatCitationsComponent {
|
|
|
1308
1614
|
return [...fromMessage, ...fromMarkdown].sort((a, b) => a.index - b.index);
|
|
1309
1615
|
}, ...(ngDevMode ? [{ debugName: "citations" }] : []));
|
|
1310
1616
|
/** First 3 sources, mapped to favicon/monogram chips for the header preview. */
|
|
1311
|
-
favstack = computed(() => this.citations().slice(0, 3).map((c) => ({
|
|
1312
|
-
id: c.id, iconUrl: c.iconUrl, mono: deriveMonogram(c), color: monogramColor(c),
|
|
1313
|
-
})), ...(ngDevMode ? [{ debugName: "favstack" }] : []));
|
|
1617
|
+
favstack = computed(() => this.citations().slice(0, 3).map((c) => ({ id: c.id, ...citationSourceVisual(c) })), ...(ngDevMode ? [{ debugName: "favstack" }] : []));
|
|
1314
1618
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatCitationsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1315
1619
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: ChatCitationsComponent, isStandalone: true, selector: "chat-citations", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "cardTpl", first: true, predicate: ChatCitationCardTemplateDirective, descendants: true }], ngImport: i0, template: `
|
|
1316
1620
|
@if (citations().length > 0) {
|
|
@@ -1326,11 +1630,48 @@ class ChatCitationsComponent {
|
|
|
1326
1630
|
<span class="chat-citations__count">{{ citations().length }}</span>
|
|
1327
1631
|
<span class="chat-citations__favstack" aria-hidden="true">
|
|
1328
1632
|
@for (f of favstack(); track f.id) {
|
|
1329
|
-
@if (f.iconUrl) {
|
|
1633
|
+
@if (f.kind === 'image' && f.iconUrl) {
|
|
1330
1634
|
<img class="chat-citations__fav" [src]="f.iconUrl" alt="" width="16" height="16" />
|
|
1635
|
+
} @else if (f.kind === 'type-icon' && f.icon) {
|
|
1636
|
+
<span class="chat-citation-source-icon chat-citations__source-icon"
|
|
1637
|
+
[class.chat-citation-source-icon--web]="f.tone === 'web'"
|
|
1638
|
+
[class.chat-citation-source-icon--file]="f.tone === 'file'"
|
|
1639
|
+
[class.chat-citation-source-icon--app]="f.tone === 'app'"
|
|
1640
|
+
[class.chat-citation-source-icon--memory]="f.tone === 'memory'"
|
|
1641
|
+
[class.chat-citation-source-icon--generic]="f.tone === 'generic'"
|
|
1642
|
+
[class.chat-citations__source-icon--web]="f.icon === 'web'"
|
|
1643
|
+
[class.chat-citations__source-icon--file]="f.icon === 'file'"
|
|
1644
|
+
[class.chat-citations__source-icon--app]="f.icon === 'app'"
|
|
1645
|
+
[class.chat-citations__source-icon--memory]="f.icon === 'memory'"
|
|
1646
|
+
[class.chat-citations__source-icon--generic]="f.icon === 'generic'">
|
|
1647
|
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
1648
|
+
@switch (f.icon) {
|
|
1649
|
+
@case ('file') {
|
|
1650
|
+
<path d="M7 3.5h6.5L18 8v12.5H7z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" />
|
|
1651
|
+
<path d="M13.5 3.5V8H18M9.5 13h5M9.5 16h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1652
|
+
}
|
|
1653
|
+
@case ('app') {
|
|
1654
|
+
<rect x="4" y="5" width="16" height="14" rx="2.5" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
1655
|
+
<path d="M8 9h.01M11.5 9h.01M15 9h.01M8 12.5h8M8 16h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1656
|
+
}
|
|
1657
|
+
@case ('memory') {
|
|
1658
|
+
<path d="M8 7.5a4 4 0 0 1 8 0v9a4 4 0 0 1-8 0z" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
1659
|
+
<path d="M12 4v16M8 10h8M8 14h8" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1660
|
+
}
|
|
1661
|
+
@case ('web') {
|
|
1662
|
+
<circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
1663
|
+
<path d="M4.5 12h15M12 4a12 12 0 0 1 0 16M12 4a12 12 0 0 0 0 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1664
|
+
}
|
|
1665
|
+
@default {
|
|
1666
|
+
<path d="M6 5.5h12v13H6z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" />
|
|
1667
|
+
<path d="M9 9h6M9 12h6M9 15h3" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
</svg>
|
|
1671
|
+
</span>
|
|
1331
1672
|
} @else {
|
|
1332
1673
|
<span class="chat-citations__fav chat-citations__fav--mono"
|
|
1333
|
-
[style.background]="f.color">{{ f.
|
|
1674
|
+
[style.background]="f.color">{{ f.monogram }}</span>
|
|
1334
1675
|
}
|
|
1335
1676
|
}
|
|
1336
1677
|
</span>
|
|
@@ -1354,7 +1695,7 @@ class ChatCitationsComponent {
|
|
|
1354
1695
|
}
|
|
1355
1696
|
</section>
|
|
1356
1697
|
}
|
|
1357
|
-
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block}.chat-citations{margin-top:var(--tplane-chat-space-5);padding-top:var(--tplane-chat-space-4);border-top:1px solid var(--tplane-chat-separator)}.chat-citations__header{display:flex;align-items:center;gap:9px;width:100%;padding:0 0 11px;background:none;border:0;font:inherit;color:inherit;cursor:pointer;text-align:left}.chat-citations__heading{font-size:13px;font-weight:600}.chat-citations__count{font-size:11px;font-weight:600;color:var(--tplane-chat-text-muted);background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);border-radius:20px;padding:1px 7px}.chat-citations__favstack{display:flex;margin-left:2px}.chat-citations__fav{width:16px;height:16px;border-radius:4px;margin-left:-5px;border:1.5px solid var(--tplane-chat-surface);object-fit:cover}.chat-citations__fav:first-child{margin-left:0}.chat-citations__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:9px;font-weight:700}.chat-citations__chevron{margin-left:auto;color:var(--tplane-chat-text-muted);transition:transform .12s ease}.chat-citations__chevron.is-open{transform:rotate(180deg)}.chat-citations__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.chat-citations__item{margin:0}.chat-citations-card{display:flex;gap:10px;padding:10px 11px;background:var(--tplane-chat-surface);border:1px solid var(--tplane-chat-separator);border-radius:var(--tplane-chat-radius-card);text-decoration:none;color:inherit;cursor:pointer;transition:border-color .12s ease,background .12s ease}.chat-citations-card:hover,.chat-citations-card:focus-visible{border-color:var(--tplane-chat-citation-accent-border);outline:none}.chat-citations-card__index{flex:0 0 auto;width:18px;height:18px;border-radius:5px;background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);color:var(--tplane-chat-text-muted);font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center;margin-top:1px}.chat-citations-card__body{min-width:0;flex:1}.chat-citations-card__top{display:flex;align-items:center;gap:6px;margin-bottom:3px}.chat-citations-card__fav{width:14px;height:14px;border-radius:3px;flex:0 0 auto;object-fit:cover}.chat-citations-card__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:8px;font-weight:700}.chat-citations-card__domain{font-size:11.5px;color:var(--tplane-chat-text-muted)}.chat-citations-card__type{margin-left:auto;font-size:10.5px
|
|
1698
|
+
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ".chat-citation-source-icon{width:18px;height:18px;flex:0 0 auto;box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;border-radius:5px;border:1px solid currentColor}.chat-citation-source-icon svg{width:12px;height:12px;display:block}.chat-citation-source-icon--sm{width:14px;height:14px;border-radius:4px}.chat-citation-source-icon--sm svg{width:9px;height:9px}.chat-citation-source-icon--web{color:var(--tplane-chat-citation-type-web-fg);background:var(--tplane-chat-citation-type-web-bg);border-color:var(--tplane-chat-citation-type-web-border)}.chat-citation-source-icon--file{color:var(--tplane-chat-citation-type-file-fg);background:var(--tplane-chat-citation-type-file-bg);border-color:var(--tplane-chat-citation-type-file-border)}.chat-citation-source-icon--app{color:var(--tplane-chat-citation-type-app-fg);background:var(--tplane-chat-citation-type-app-bg);border-color:var(--tplane-chat-citation-type-app-border)}.chat-citation-source-icon--memory{color:var(--tplane-chat-citation-type-memory-fg);background:var(--tplane-chat-citation-type-memory-bg);border-color:var(--tplane-chat-citation-type-memory-border)}.chat-citation-source-icon--generic{color:var(--tplane-chat-citation-type-generic-fg);background:var(--tplane-chat-citation-type-generic-bg);border-color:var(--tplane-chat-citation-type-generic-border)}.chat-citation-type-badge{display:inline-flex;align-items:center;justify-content:center;min-width:0;max-width:120px;box-sizing:border-box;padding:1px 6px;border:1px solid currentColor;border-radius:999px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.35}.chat-citation-type-badge--web{color:var(--tplane-chat-citation-type-web-fg);background:var(--tplane-chat-citation-type-web-bg);border-color:var(--tplane-chat-citation-type-web-border)}.chat-citation-type-badge--file{color:var(--tplane-chat-citation-type-file-fg);background:var(--tplane-chat-citation-type-file-bg);border-color:var(--tplane-chat-citation-type-file-border)}.chat-citation-type-badge--app{color:var(--tplane-chat-citation-type-app-fg);background:var(--tplane-chat-citation-type-app-bg);border-color:var(--tplane-chat-citation-type-app-border)}.chat-citation-type-badge--memory{color:var(--tplane-chat-citation-type-memory-fg);background:var(--tplane-chat-citation-type-memory-bg);border-color:var(--tplane-chat-citation-type-memory-border)}.chat-citation-type-badge--generic{color:var(--tplane-chat-citation-type-generic-fg);background:var(--tplane-chat-citation-type-generic-bg);border-color:var(--tplane-chat-citation-type-generic-border)}:host{display:block}.chat-citations{margin-top:var(--tplane-chat-space-5);padding-top:var(--tplane-chat-space-4);border-top:1px solid var(--tplane-chat-separator)}.chat-citations__header{display:flex;align-items:center;gap:9px;width:100%;padding:0 0 11px;background:none;border:0;font:inherit;color:inherit;cursor:pointer;text-align:left}.chat-citations__heading{font-size:13px;font-weight:600}.chat-citations__count{font-size:11px;font-weight:600;color:var(--tplane-chat-text-muted);background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);border-radius:20px;padding:1px 7px}.chat-citations__favstack{display:flex;margin-left:2px}.chat-citations__fav{width:16px;height:16px;border-radius:4px;margin-left:-5px;border:1.5px solid var(--tplane-chat-surface);object-fit:cover}.chat-citations__fav:first-child{margin-left:0}.chat-citations__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:9px;font-weight:700}.chat-citations__source-icon{width:16px;height:16px;border-radius:4px;margin-left:-5px;border-width:1.5px}.chat-citations__source-icon:first-child{margin-left:0}.chat-citations__source-icon svg{width:10px;height:10px}.chat-citations__chevron{margin-left:auto;color:var(--tplane-chat-text-muted);transition:transform .12s ease}.chat-citations__chevron.is-open{transform:rotate(180deg)}.chat-citations__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.chat-citations__item{margin:0}.chat-citations-card{display:flex;gap:10px;padding:10px 11px;background:var(--tplane-chat-surface);border:1px solid var(--tplane-chat-separator);border-radius:var(--tplane-chat-radius-card);text-decoration:none;color:inherit;cursor:pointer;transition:border-color .12s ease,background .12s ease}.chat-citations-card:hover,.chat-citations-card:focus-visible{border-color:var(--tplane-chat-citation-accent-border);outline:none}.chat-citations-card__index{flex:0 0 auto;width:18px;height:18px;border-radius:5px;background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);color:var(--tplane-chat-text-muted);font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center;margin-top:1px}.chat-citations-card__body{min-width:0;flex:1}.chat-citations-card__top{display:flex;align-items:center;gap:6px;margin-bottom:3px}.chat-citations-card__fav{width:14px;height:14px;border-radius:3px;flex:0 0 auto;object-fit:cover}.chat-citations-card__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:8px;font-weight:700}.chat-citations-card__domain{font-size:11.5px;color:var(--tplane-chat-text-muted)}.chat-citations-card__type{margin-left:auto;font-size:10.5px}.chat-citations-card__title{font-size:13.5px;font-weight:600;line-height:1.35;margin:0 0 2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chat-citations-card:hover .chat-citations-card__title{color:var(--tplane-chat-citation-accent)}.chat-citations-card__snippet{font-size:12px;color:var(--tplane-chat-text-muted);line-height:1.45;margin:0;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ChatCitationsCardComponent, selector: "chat-citations-card", inputs: ["citation"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1358
1699
|
}
|
|
1359
1700
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatCitationsComponent, decorators: [{
|
|
1360
1701
|
type: Component,
|
|
@@ -1372,11 +1713,48 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
1372
1713
|
<span class="chat-citations__count">{{ citations().length }}</span>
|
|
1373
1714
|
<span class="chat-citations__favstack" aria-hidden="true">
|
|
1374
1715
|
@for (f of favstack(); track f.id) {
|
|
1375
|
-
@if (f.iconUrl) {
|
|
1716
|
+
@if (f.kind === 'image' && f.iconUrl) {
|
|
1376
1717
|
<img class="chat-citations__fav" [src]="f.iconUrl" alt="" width="16" height="16" />
|
|
1718
|
+
} @else if (f.kind === 'type-icon' && f.icon) {
|
|
1719
|
+
<span class="chat-citation-source-icon chat-citations__source-icon"
|
|
1720
|
+
[class.chat-citation-source-icon--web]="f.tone === 'web'"
|
|
1721
|
+
[class.chat-citation-source-icon--file]="f.tone === 'file'"
|
|
1722
|
+
[class.chat-citation-source-icon--app]="f.tone === 'app'"
|
|
1723
|
+
[class.chat-citation-source-icon--memory]="f.tone === 'memory'"
|
|
1724
|
+
[class.chat-citation-source-icon--generic]="f.tone === 'generic'"
|
|
1725
|
+
[class.chat-citations__source-icon--web]="f.icon === 'web'"
|
|
1726
|
+
[class.chat-citations__source-icon--file]="f.icon === 'file'"
|
|
1727
|
+
[class.chat-citations__source-icon--app]="f.icon === 'app'"
|
|
1728
|
+
[class.chat-citations__source-icon--memory]="f.icon === 'memory'"
|
|
1729
|
+
[class.chat-citations__source-icon--generic]="f.icon === 'generic'">
|
|
1730
|
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
1731
|
+
@switch (f.icon) {
|
|
1732
|
+
@case ('file') {
|
|
1733
|
+
<path d="M7 3.5h6.5L18 8v12.5H7z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" />
|
|
1734
|
+
<path d="M13.5 3.5V8H18M9.5 13h5M9.5 16h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1735
|
+
}
|
|
1736
|
+
@case ('app') {
|
|
1737
|
+
<rect x="4" y="5" width="16" height="14" rx="2.5" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
1738
|
+
<path d="M8 9h.01M11.5 9h.01M15 9h.01M8 12.5h8M8 16h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1739
|
+
}
|
|
1740
|
+
@case ('memory') {
|
|
1741
|
+
<path d="M8 7.5a4 4 0 0 1 8 0v9a4 4 0 0 1-8 0z" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
1742
|
+
<path d="M12 4v16M8 10h8M8 14h8" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1743
|
+
}
|
|
1744
|
+
@case ('web') {
|
|
1745
|
+
<circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
1746
|
+
<path d="M4.5 12h15M12 4a12 12 0 0 1 0 16M12 4a12 12 0 0 0 0 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1747
|
+
}
|
|
1748
|
+
@default {
|
|
1749
|
+
<path d="M6 5.5h12v13H6z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" />
|
|
1750
|
+
<path d="M9 9h6M9 12h6M9 15h3" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
</svg>
|
|
1754
|
+
</span>
|
|
1377
1755
|
} @else {
|
|
1378
1756
|
<span class="chat-citations__fav chat-citations__fav--mono"
|
|
1379
|
-
[style.background]="f.color">{{ f.
|
|
1757
|
+
[style.background]="f.color">{{ f.monogram }}</span>
|
|
1380
1758
|
}
|
|
1381
1759
|
}
|
|
1382
1760
|
</span>
|
|
@@ -1400,7 +1778,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
1400
1778
|
}
|
|
1401
1779
|
</section>
|
|
1402
1780
|
}
|
|
1403
|
-
`, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block}.chat-citations{margin-top:var(--tplane-chat-space-5);padding-top:var(--tplane-chat-space-4);border-top:1px solid var(--tplane-chat-separator)}.chat-citations__header{display:flex;align-items:center;gap:9px;width:100%;padding:0 0 11px;background:none;border:0;font:inherit;color:inherit;cursor:pointer;text-align:left}.chat-citations__heading{font-size:13px;font-weight:600}.chat-citations__count{font-size:11px;font-weight:600;color:var(--tplane-chat-text-muted);background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);border-radius:20px;padding:1px 7px}.chat-citations__favstack{display:flex;margin-left:2px}.chat-citations__fav{width:16px;height:16px;border-radius:4px;margin-left:-5px;border:1.5px solid var(--tplane-chat-surface);object-fit:cover}.chat-citations__fav:first-child{margin-left:0}.chat-citations__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:9px;font-weight:700}.chat-citations__chevron{margin-left:auto;color:var(--tplane-chat-text-muted);transition:transform .12s ease}.chat-citations__chevron.is-open{transform:rotate(180deg)}.chat-citations__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.chat-citations__item{margin:0}.chat-citations-card{display:flex;gap:10px;padding:10px 11px;background:var(--tplane-chat-surface);border:1px solid var(--tplane-chat-separator);border-radius:var(--tplane-chat-radius-card);text-decoration:none;color:inherit;cursor:pointer;transition:border-color .12s ease,background .12s ease}.chat-citations-card:hover,.chat-citations-card:focus-visible{border-color:var(--tplane-chat-citation-accent-border);outline:none}.chat-citations-card__index{flex:0 0 auto;width:18px;height:18px;border-radius:5px;background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);color:var(--tplane-chat-text-muted);font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center;margin-top:1px}.chat-citations-card__body{min-width:0;flex:1}.chat-citations-card__top{display:flex;align-items:center;gap:6px;margin-bottom:3px}.chat-citations-card__fav{width:14px;height:14px;border-radius:3px;flex:0 0 auto;object-fit:cover}.chat-citations-card__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:8px;font-weight:700}.chat-citations-card__domain{font-size:11.5px;color:var(--tplane-chat-text-muted)}.chat-citations-card__type{margin-left:auto;font-size:10.5px
|
|
1781
|
+
`, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ".chat-citation-source-icon{width:18px;height:18px;flex:0 0 auto;box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;border-radius:5px;border:1px solid currentColor}.chat-citation-source-icon svg{width:12px;height:12px;display:block}.chat-citation-source-icon--sm{width:14px;height:14px;border-radius:4px}.chat-citation-source-icon--sm svg{width:9px;height:9px}.chat-citation-source-icon--web{color:var(--tplane-chat-citation-type-web-fg);background:var(--tplane-chat-citation-type-web-bg);border-color:var(--tplane-chat-citation-type-web-border)}.chat-citation-source-icon--file{color:var(--tplane-chat-citation-type-file-fg);background:var(--tplane-chat-citation-type-file-bg);border-color:var(--tplane-chat-citation-type-file-border)}.chat-citation-source-icon--app{color:var(--tplane-chat-citation-type-app-fg);background:var(--tplane-chat-citation-type-app-bg);border-color:var(--tplane-chat-citation-type-app-border)}.chat-citation-source-icon--memory{color:var(--tplane-chat-citation-type-memory-fg);background:var(--tplane-chat-citation-type-memory-bg);border-color:var(--tplane-chat-citation-type-memory-border)}.chat-citation-source-icon--generic{color:var(--tplane-chat-citation-type-generic-fg);background:var(--tplane-chat-citation-type-generic-bg);border-color:var(--tplane-chat-citation-type-generic-border)}.chat-citation-type-badge{display:inline-flex;align-items:center;justify-content:center;min-width:0;max-width:120px;box-sizing:border-box;padding:1px 6px;border:1px solid currentColor;border-radius:999px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.35}.chat-citation-type-badge--web{color:var(--tplane-chat-citation-type-web-fg);background:var(--tplane-chat-citation-type-web-bg);border-color:var(--tplane-chat-citation-type-web-border)}.chat-citation-type-badge--file{color:var(--tplane-chat-citation-type-file-fg);background:var(--tplane-chat-citation-type-file-bg);border-color:var(--tplane-chat-citation-type-file-border)}.chat-citation-type-badge--app{color:var(--tplane-chat-citation-type-app-fg);background:var(--tplane-chat-citation-type-app-bg);border-color:var(--tplane-chat-citation-type-app-border)}.chat-citation-type-badge--memory{color:var(--tplane-chat-citation-type-memory-fg);background:var(--tplane-chat-citation-type-memory-bg);border-color:var(--tplane-chat-citation-type-memory-border)}.chat-citation-type-badge--generic{color:var(--tplane-chat-citation-type-generic-fg);background:var(--tplane-chat-citation-type-generic-bg);border-color:var(--tplane-chat-citation-type-generic-border)}:host{display:block}.chat-citations{margin-top:var(--tplane-chat-space-5);padding-top:var(--tplane-chat-space-4);border-top:1px solid var(--tplane-chat-separator)}.chat-citations__header{display:flex;align-items:center;gap:9px;width:100%;padding:0 0 11px;background:none;border:0;font:inherit;color:inherit;cursor:pointer;text-align:left}.chat-citations__heading{font-size:13px;font-weight:600}.chat-citations__count{font-size:11px;font-weight:600;color:var(--tplane-chat-text-muted);background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);border-radius:20px;padding:1px 7px}.chat-citations__favstack{display:flex;margin-left:2px}.chat-citations__fav{width:16px;height:16px;border-radius:4px;margin-left:-5px;border:1.5px solid var(--tplane-chat-surface);object-fit:cover}.chat-citations__fav:first-child{margin-left:0}.chat-citations__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:9px;font-weight:700}.chat-citations__source-icon{width:16px;height:16px;border-radius:4px;margin-left:-5px;border-width:1.5px}.chat-citations__source-icon:first-child{margin-left:0}.chat-citations__source-icon svg{width:10px;height:10px}.chat-citations__chevron{margin-left:auto;color:var(--tplane-chat-text-muted);transition:transform .12s ease}.chat-citations__chevron.is-open{transform:rotate(180deg)}.chat-citations__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.chat-citations__item{margin:0}.chat-citations-card{display:flex;gap:10px;padding:10px 11px;background:var(--tplane-chat-surface);border:1px solid var(--tplane-chat-separator);border-radius:var(--tplane-chat-radius-card);text-decoration:none;color:inherit;cursor:pointer;transition:border-color .12s ease,background .12s ease}.chat-citations-card:hover,.chat-citations-card:focus-visible{border-color:var(--tplane-chat-citation-accent-border);outline:none}.chat-citations-card__index{flex:0 0 auto;width:18px;height:18px;border-radius:5px;background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);color:var(--tplane-chat-text-muted);font-size:11px;font-weight:600;display:flex;align-items:center;justify-content:center;margin-top:1px}.chat-citations-card__body{min-width:0;flex:1}.chat-citations-card__top{display:flex;align-items:center;gap:6px;margin-bottom:3px}.chat-citations-card__fav{width:14px;height:14px;border-radius:3px;flex:0 0 auto;object-fit:cover}.chat-citations-card__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:8px;font-weight:700}.chat-citations-card__domain{font-size:11.5px;color:var(--tplane-chat-text-muted)}.chat-citations-card__type{margin-left:auto;font-size:10.5px}.chat-citations-card__title{font-size:13.5px;font-weight:600;line-height:1.35;margin:0 0 2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chat-citations-card:hover .chat-citations-card__title{color:var(--tplane-chat-citation-accent)}.chat-citations-card__snippet{font-size:12px;color:var(--tplane-chat-text-muted);line-height:1.45;margin:0;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}\n"] }]
|
|
1404
1782
|
}], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], cardTpl: [{
|
|
1405
1783
|
type: ContentChild,
|
|
1406
1784
|
args: [ChatCitationCardTemplateDirective]
|
|
@@ -1994,184 +2372,6 @@ const CHAT_REASONING_STYLES = `
|
|
|
1994
2372
|
.chat-reasoning__body chat-streaming-md { font-size: 0.95em; }
|
|
1995
2373
|
`;
|
|
1996
2374
|
|
|
1997
|
-
// libs/chat/src/lib/styles/chat-markdown.styles.ts
|
|
1998
|
-
// SPDX-License-Identifier: MIT
|
|
1999
|
-
//
|
|
2000
|
-
// Scoped to the `chat-streaming-md` element selector (not `:host`) because
|
|
2001
|
-
// the component renders markdown via innerHTML and uses
|
|
2002
|
-
// `ViewEncapsulation.None` — emulated encapsulation would skip these rules
|
|
2003
|
-
// since innerHTML-injected nodes don't carry `_ngcontent-xxx` attributes.
|
|
2004
|
-
// Keeping selectors prefixed with the element name preserves locality so
|
|
2005
|
-
// these rules don't leak to other markup on the page.
|
|
2006
|
-
//
|
|
2007
|
-
// Covers the CommonMark + GFM surface: headings, paragraphs, links, lists
|
|
2008
|
-
// (bullet/ordered/task), code (inline + fenced), blockquotes, horizontal
|
|
2009
|
-
// rules, tables, images, bold (`strong`), italic (`em`), strikethrough
|
|
2010
|
-
// (`del`/`s`).
|
|
2011
|
-
const CHAT_MARKDOWN_STYLES = `
|
|
2012
|
-
chat-streaming-md { display: block; color: var(--tplane-chat-text); line-height: var(--tplane-chat-line-height); }
|
|
2013
|
-
|
|
2014
|
-
/* Headings */
|
|
2015
|
-
chat-streaming-md h1, chat-streaming-md h2, chat-streaming-md h3, chat-streaming-md h4, chat-streaming-md h5, chat-streaming-md h6 {
|
|
2016
|
-
font-weight: 600;
|
|
2017
|
-
line-height: 1.25;
|
|
2018
|
-
margin: 1.25rem 0 0.75rem;
|
|
2019
|
-
}
|
|
2020
|
-
chat-streaming-md h1:first-child, chat-streaming-md h2:first-child, chat-streaming-md h3:first-child,
|
|
2021
|
-
chat-streaming-md h4:first-child, chat-streaming-md h5:first-child, chat-streaming-md h6:first-child { margin-top: 0; }
|
|
2022
|
-
chat-streaming-md h1 { font-size: 1.5em; font-weight: 700; }
|
|
2023
|
-
chat-streaming-md h2 { font-size: 1.25em; }
|
|
2024
|
-
chat-streaming-md h3 { font-size: 1.1em; }
|
|
2025
|
-
chat-streaming-md h4 { font-size: 1em; }
|
|
2026
|
-
chat-streaming-md h5, chat-streaming-md h6 { font-size: 0.95em; color: var(--tplane-chat-text-muted); }
|
|
2027
|
-
|
|
2028
|
-
/* Paragraphs and inline emphasis */
|
|
2029
|
-
chat-streaming-md p { margin: 0 0 0.75rem; line-height: 1.6; font-size: var(--tplane-chat-font-size); }
|
|
2030
|
-
chat-streaming-md p:last-child { margin-bottom: 0; }
|
|
2031
|
-
chat-streaming-md strong, chat-streaming-md b { font-weight: 700; }
|
|
2032
|
-
chat-streaming-md em, chat-streaming-md i { font-style: italic; }
|
|
2033
|
-
chat-streaming-md del, chat-streaming-md s { text-decoration: line-through; color: var(--tplane-chat-text-muted); }
|
|
2034
|
-
chat-streaming-md mark { background: var(--tplane-chat-surface-alt); padding: 0 2px; border-radius: 2px; }
|
|
2035
|
-
chat-streaming-md sub { font-size: 0.75em; vertical-align: sub; }
|
|
2036
|
-
chat-streaming-md sup { font-size: 0.75em; vertical-align: super; }
|
|
2037
|
-
|
|
2038
|
-
/* Links */
|
|
2039
|
-
chat-streaming-md a { color: var(--tplane-chat-primary); text-decoration: underline; text-underline-offset: 2px; }
|
|
2040
|
-
chat-streaming-md a:hover { text-decoration-thickness: 2px; }
|
|
2041
|
-
|
|
2042
|
-
/* Lists (CommonMark + GFM task lists) */
|
|
2043
|
-
chat-streaming-md ul, chat-streaming-md ol { margin: 0 0 0.75rem; padding-left: 1.5rem; }
|
|
2044
|
-
chat-streaming-md ul { list-style: disc outside; }
|
|
2045
|
-
chat-streaming-md ol { list-style: decimal outside; }
|
|
2046
|
-
chat-streaming-md ul ul { list-style: circle outside; }
|
|
2047
|
-
chat-streaming-md ul ul ul { list-style: square outside; }
|
|
2048
|
-
chat-streaming-md li { margin: 0.2rem 0; }
|
|
2049
|
-
chat-streaming-md li::marker { color: var(--tplane-chat-text-muted); }
|
|
2050
|
-
chat-streaming-md li > p { margin: 0 0 0.25rem; }
|
|
2051
|
-
chat-streaming-md li > ul, chat-streaming-md li > ol { margin: 0.25rem 0 0; }
|
|
2052
|
-
/* GFM task lists: marked emits <li><input type="checkbox" disabled> ... */
|
|
2053
|
-
chat-streaming-md li:has(> input[type="checkbox"]) { list-style: none; margin-left: -1.25rem; }
|
|
2054
|
-
chat-streaming-md li > input[type="checkbox"] { margin-right: 0.5rem; vertical-align: middle; }
|
|
2055
|
-
|
|
2056
|
-
/* Code (inline + fenced) */
|
|
2057
|
-
chat-streaming-md code {
|
|
2058
|
-
background: var(--tplane-chat-surface-alt);
|
|
2059
|
-
color: var(--tplane-chat-text);
|
|
2060
|
-
padding: 1px 5px;
|
|
2061
|
-
border-radius: 4px;
|
|
2062
|
-
font-family: var(--tplane-chat-font-mono);
|
|
2063
|
-
font-size: 0.9em;
|
|
2064
|
-
}
|
|
2065
|
-
chat-streaming-md pre {
|
|
2066
|
-
background: var(--tplane-chat-surface-alt);
|
|
2067
|
-
color: var(--tplane-chat-text);
|
|
2068
|
-
padding: 12px 14px;
|
|
2069
|
-
border-radius: var(--tplane-chat-radius-card);
|
|
2070
|
-
overflow-x: auto;
|
|
2071
|
-
font-family: var(--tplane-chat-font-mono);
|
|
2072
|
-
font-size: var(--tplane-chat-font-size-sm);
|
|
2073
|
-
line-height: 1.5;
|
|
2074
|
-
margin: 0 0 0.75rem;
|
|
2075
|
-
}
|
|
2076
|
-
chat-streaming-md pre code { background: transparent; padding: 0; border-radius: 0; font-size: inherit; }
|
|
2077
|
-
|
|
2078
|
-
/* Blockquote */
|
|
2079
|
-
chat-streaming-md blockquote {
|
|
2080
|
-
border-left: 3px solid var(--tplane-chat-separator);
|
|
2081
|
-
padding: 0.25rem 0 0.25rem 12px;
|
|
2082
|
-
margin: 0 0 0.75rem;
|
|
2083
|
-
color: var(--tplane-chat-text-muted);
|
|
2084
|
-
}
|
|
2085
|
-
chat-streaming-md blockquote > :last-child { margin-bottom: 0; }
|
|
2086
|
-
|
|
2087
|
-
/* Horizontal rule */
|
|
2088
|
-
chat-streaming-md hr {
|
|
2089
|
-
border: none;
|
|
2090
|
-
border-top: 1px solid var(--tplane-chat-separator);
|
|
2091
|
-
margin: 1rem 0;
|
|
2092
|
-
}
|
|
2093
|
-
|
|
2094
|
-
/* Tables (GFM) */
|
|
2095
|
-
chat-streaming-md table {
|
|
2096
|
-
border-collapse: collapse;
|
|
2097
|
-
margin: 0 0 0.75rem;
|
|
2098
|
-
width: 100%;
|
|
2099
|
-
font-size: 0.95em;
|
|
2100
|
-
}
|
|
2101
|
-
chat-streaming-md thead { background: var(--tplane-chat-surface-alt); }
|
|
2102
|
-
chat-streaming-md th, chat-streaming-md td {
|
|
2103
|
-
border: 1px solid var(--tplane-chat-separator);
|
|
2104
|
-
padding: 6px 10px;
|
|
2105
|
-
text-align: left;
|
|
2106
|
-
vertical-align: top;
|
|
2107
|
-
}
|
|
2108
|
-
chat-streaming-md th { font-weight: 600; }
|
|
2109
|
-
/* Component-rendered table: chat-md-table becomes a horizontally-scrollable
|
|
2110
|
-
wrapper for the inner <table>; row/cell elements stay layout-transparent
|
|
2111
|
-
so the browser's table layout takes over. Without this overflow wrapper,
|
|
2112
|
-
wide tables push their parent container past the viewport horizontally. */
|
|
2113
|
-
chat-streaming-md chat-md-table {
|
|
2114
|
-
display: block;
|
|
2115
|
-
overflow-x: auto;
|
|
2116
|
-
max-width: 100%;
|
|
2117
|
-
margin: 0 0 0.75rem;
|
|
2118
|
-
}
|
|
2119
|
-
chat-streaming-md chat-md-table-row { display: contents; }
|
|
2120
|
-
chat-streaming-md chat-md-table-cell { display: contents; }
|
|
2121
|
-
chat-streaming-md chat-md-table > table { margin: 0; }
|
|
2122
|
-
/* Task-list items: checkbox + first paragraph render inline; subsequent
|
|
2123
|
-
blocks (sub-lists, multi-paragraph items) flow normally below. */
|
|
2124
|
-
chat-streaming-md li.chat-md-list-item--task {
|
|
2125
|
-
list-style: none;
|
|
2126
|
-
margin-left: -1.25rem;
|
|
2127
|
-
display: flex;
|
|
2128
|
-
flex-wrap: wrap;
|
|
2129
|
-
align-items: baseline;
|
|
2130
|
-
gap: 0.5rem;
|
|
2131
|
-
}
|
|
2132
|
-
chat-streaming-md li.chat-md-list-item--task > input[type="checkbox"] {
|
|
2133
|
-
margin: 0;
|
|
2134
|
-
flex: 0 0 auto;
|
|
2135
|
-
transform: translateY(2px);
|
|
2136
|
-
}
|
|
2137
|
-
/* The chat-md-children wrapper around list-item content takes remaining width */
|
|
2138
|
-
chat-streaming-md li.chat-md-list-item--task > chat-md-children {
|
|
2139
|
-
flex: 1 1 auto;
|
|
2140
|
-
min-width: 0;
|
|
2141
|
-
}
|
|
2142
|
-
/* Tight task items: only the FIRST paragraph aligns inline with the
|
|
2143
|
-
checkbox (margin collapsed). Subsequent paragraphs/blocks keep their
|
|
2144
|
-
normal vertical spacing so multi-block items render readably. */
|
|
2145
|
-
chat-streaming-md li.chat-md-list-item--task > chat-md-children > chat-md-paragraph:first-child > p {
|
|
2146
|
-
margin: 0;
|
|
2147
|
-
}
|
|
2148
|
-
|
|
2149
|
-
/* Media */
|
|
2150
|
-
chat-streaming-md img { max-width: 100%; height: auto; border-radius: 6px; }
|
|
2151
|
-
/* Broken-image fallback: muted pill showing alt text + icon. Triggered
|
|
2152
|
-
when <img> fires (error). Caught by live browser smoke — prior impl
|
|
2153
|
-
showed only the browser's broken-image icon with no readable alt. */
|
|
2154
|
-
chat-streaming-md .chat-md-image--broken {
|
|
2155
|
-
display: inline-flex;
|
|
2156
|
-
align-items: center;
|
|
2157
|
-
gap: 0.4rem;
|
|
2158
|
-
padding: 0.25rem 0.5rem;
|
|
2159
|
-
background: var(--tplane-chat-surface-alt);
|
|
2160
|
-
border: 1px dashed var(--tplane-chat-separator);
|
|
2161
|
-
border-radius: 6px;
|
|
2162
|
-
font-size: 0.9em;
|
|
2163
|
-
color: var(--tplane-chat-text-muted, currentColor);
|
|
2164
|
-
opacity: 0.85;
|
|
2165
|
-
}
|
|
2166
|
-
chat-streaming-md .chat-md-image__icon { font-size: 1em; line-height: 1; }
|
|
2167
|
-
chat-streaming-md .chat-md-image__alt { font-style: italic; }
|
|
2168
|
-
/* Math (KaTeX). Display math is a centered block that scrolls horizontally
|
|
2169
|
-
on overflow; the raw fallback (KaTeX missing or invalid LaTeX) reads as
|
|
2170
|
-
monospace so the source delimiters look intentional. */
|
|
2171
|
-
chat-streaming-md .chat-md-math--display { display: block; margin: 0.5em 0; overflow-x: auto; }
|
|
2172
|
-
chat-streaming-md .chat-md-math--raw { font-family: var(--tplane-chat-font-mono, ui-monospace, monospace); }
|
|
2173
|
-
`;
|
|
2174
|
-
|
|
2175
2375
|
// libs/chat/src/lib/markdown/markdown-view-registry.ts
|
|
2176
2376
|
// SPDX-License-Identifier: MIT
|
|
2177
2377
|
/**
|
|
@@ -3053,23 +3253,83 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
3053
3253
|
*/
|
|
3054
3254
|
class ChatCitationPreviewComponent {
|
|
3055
3255
|
citation = input.required(...(ngDevMode ? [{ debugName: "citation" }] : []));
|
|
3256
|
+
sourceVisual = computed(() => citationSourceVisual(this.citation()), ...(ngDevMode ? [{ debugName: "sourceVisual" }] : []));
|
|
3257
|
+
typeMeta = computed(() => citationTypeMeta(this.citation()), ...(ngDevMode ? [{ debugName: "typeMeta" }] : []));
|
|
3056
3258
|
domain = computed(() => deriveDomain(this.citation().url), ...(ngDevMode ? [{ debugName: "domain" }] : []));
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3259
|
+
sourceIconUrl = computed(() => {
|
|
3260
|
+
const visual = this.sourceVisual();
|
|
3261
|
+
return visual.kind === 'image' ? visual.iconUrl : null;
|
|
3262
|
+
}, ...(ngDevMode ? [{ debugName: "sourceIconUrl" }] : []));
|
|
3263
|
+
sourceIcon = computed(() => {
|
|
3264
|
+
const visual = this.sourceVisual();
|
|
3265
|
+
return visual.kind === 'type-icon' ? visual.icon : null;
|
|
3266
|
+
}, ...(ngDevMode ? [{ debugName: "sourceIcon" }] : []));
|
|
3267
|
+
sourceMonogram = computed(() => {
|
|
3268
|
+
const visual = this.sourceVisual();
|
|
3269
|
+
return visual.kind === 'monogram' ? visual.monogram : null;
|
|
3270
|
+
}, ...(ngDevMode ? [{ debugName: "sourceMonogram" }] : []));
|
|
3271
|
+
sourceMonoColor = computed(() => {
|
|
3272
|
+
const visual = this.sourceVisual();
|
|
3273
|
+
return visual.kind === 'monogram' ? visual.color : null;
|
|
3274
|
+
}, ...(ngDevMode ? [{ debugName: "sourceMonoColor" }] : []));
|
|
3275
|
+
typeLabel = computed(() => this.typeMeta().label, ...(ngDevMode ? [{ debugName: "typeLabel" }] : []));
|
|
3276
|
+
typeTone = computed(() => this.typeMeta().tone, ...(ngDevMode ? [{ debugName: "typeTone" }] : []));
|
|
3060
3277
|
published = computed(() => formatPublished(this.citation().publishedAt), ...(ngDevMode ? [{ debugName: "published" }] : []));
|
|
3278
|
+
isTypeTone(tone) {
|
|
3279
|
+
return this.typeTone() === tone;
|
|
3280
|
+
}
|
|
3061
3281
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatCitationPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3062
3282
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: ChatCitationPreviewComponent, isStandalone: true, selector: "chat-citation-preview", inputs: { citation: { classPropertyName: "citation", publicName: "citation", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
|
|
3063
3283
|
<div class="chat-citation-preview" role="group" [attr.aria-label]="'Source ' + citation().index">
|
|
3064
3284
|
<div class="chat-citation-preview__head">
|
|
3065
|
-
@if (
|
|
3285
|
+
@if (sourceIconUrl(); as icon) {
|
|
3066
3286
|
<img class="chat-citation-preview__fav" [src]="icon" alt="" width="16" height="16" />
|
|
3287
|
+
} @else if (sourceIcon(); as icon) {
|
|
3288
|
+
<span class="chat-citation-source-icon chat-citation-preview__source-icon"
|
|
3289
|
+
aria-hidden="true"
|
|
3290
|
+
[class.chat-citation-source-icon--web]="icon === 'web'"
|
|
3291
|
+
[class.chat-citation-source-icon--file]="icon === 'file'"
|
|
3292
|
+
[class.chat-citation-source-icon--app]="icon === 'app'"
|
|
3293
|
+
[class.chat-citation-source-icon--memory]="icon === 'memory'"
|
|
3294
|
+
[class.chat-citation-source-icon--generic]="icon === 'generic'">
|
|
3295
|
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
3296
|
+
@switch (icon) {
|
|
3297
|
+
@case ('file') {
|
|
3298
|
+
<path d="M7 3.5h6.5L18 8v12.5H7z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" />
|
|
3299
|
+
<path d="M13.5 3.5V8H18M9.5 13h5M9.5 16h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
3300
|
+
}
|
|
3301
|
+
@case ('app') {
|
|
3302
|
+
<rect x="4" y="5" width="16" height="14" rx="2.5" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
3303
|
+
<path d="M8 9h.01M11.5 9h.01M15 9h.01M8 12.5h8M8 16h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
3304
|
+
}
|
|
3305
|
+
@case ('memory') {
|
|
3306
|
+
<path d="M8 7.5a4 4 0 0 1 8 0v9a4 4 0 0 1-8 0z" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
3307
|
+
<path d="M12 4v16M8 10h8M8 14h8" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
3308
|
+
}
|
|
3309
|
+
@case ('web') {
|
|
3310
|
+
<circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
3311
|
+
<path d="M4.5 12h15M12 4a12 12 0 0 1 0 16M12 4a12 12 0 0 0 0 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
3312
|
+
}
|
|
3313
|
+
@default {
|
|
3314
|
+
<path d="M6 5.5h12v13H6z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" />
|
|
3315
|
+
<path d="M9 9h6M9 12h6M9 15h3" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
</svg>
|
|
3319
|
+
</span>
|
|
3067
3320
|
} @else {
|
|
3068
3321
|
<span class="chat-citation-preview__fav chat-citation-preview__fav--mono"
|
|
3069
|
-
[style.background]="
|
|
3322
|
+
[style.background]="sourceMonoColor()">{{ sourceMonogram() }}</span>
|
|
3070
3323
|
}
|
|
3071
3324
|
@if (domain(); as d) { <span class="chat-citation-preview__domain">{{ d }}</span> }
|
|
3072
|
-
@if (typeLabel(); as t) {
|
|
3325
|
+
@if (typeLabel(); as t) {
|
|
3326
|
+
<span class="chat-citation-preview__type chat-citation-type-badge"
|
|
3327
|
+
[class.chat-citation-type-badge--web]="isTypeTone('web')"
|
|
3328
|
+
[class.chat-citation-type-badge--file]="isTypeTone('file')"
|
|
3329
|
+
[class.chat-citation-type-badge--app]="isTypeTone('app')"
|
|
3330
|
+
[class.chat-citation-type-badge--memory]="isTypeTone('memory')"
|
|
3331
|
+
[class.chat-citation-type-badge--generic]="isTypeTone('generic')">{{ t }}</span>
|
|
3332
|
+
}
|
|
3073
3333
|
</div>
|
|
3074
3334
|
@if (citation().title; as title) {
|
|
3075
3335
|
<p class="chat-citation-preview__title">{{ title }}</p>
|
|
@@ -3089,21 +3349,61 @@ class ChatCitationPreviewComponent {
|
|
|
3089
3349
|
</div>
|
|
3090
3350
|
}
|
|
3091
3351
|
</div>
|
|
3092
|
-
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block}.chat-citation-preview{width:320px;max-width:calc(100vw - 24px);box-sizing:border-box;background:var(--tplane-chat-surface);border:1px solid var(--tplane-chat-separator);border-radius:var(--tplane-chat-radius-card);box-shadow:var(--tplane-chat-shadow-md);padding:12px 13px;text-align:left;color:var(--tplane-chat-text)}.chat-citation-preview__head{display:flex;align-items:center;gap:7px;margin-bottom:7px}.chat-citation-preview__fav{width:16px;height:16px;border-radius:4px;flex:0 0 auto;object-fit:cover}.chat-citation-preview__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:10px;font-weight:700}.chat-citation-preview__domain{font-size:12px;color:var(--tplane-chat-text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chat-citation-preview__type{margin-left:auto;font-size:11px;
|
|
3352
|
+
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ".chat-citation-source-icon{width:18px;height:18px;flex:0 0 auto;box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;border-radius:5px;border:1px solid currentColor}.chat-citation-source-icon svg{width:12px;height:12px;display:block}.chat-citation-source-icon--sm{width:14px;height:14px;border-radius:4px}.chat-citation-source-icon--sm svg{width:9px;height:9px}.chat-citation-source-icon--web{color:var(--tplane-chat-citation-type-web-fg);background:var(--tplane-chat-citation-type-web-bg);border-color:var(--tplane-chat-citation-type-web-border)}.chat-citation-source-icon--file{color:var(--tplane-chat-citation-type-file-fg);background:var(--tplane-chat-citation-type-file-bg);border-color:var(--tplane-chat-citation-type-file-border)}.chat-citation-source-icon--app{color:var(--tplane-chat-citation-type-app-fg);background:var(--tplane-chat-citation-type-app-bg);border-color:var(--tplane-chat-citation-type-app-border)}.chat-citation-source-icon--memory{color:var(--tplane-chat-citation-type-memory-fg);background:var(--tplane-chat-citation-type-memory-bg);border-color:var(--tplane-chat-citation-type-memory-border)}.chat-citation-source-icon--generic{color:var(--tplane-chat-citation-type-generic-fg);background:var(--tplane-chat-citation-type-generic-bg);border-color:var(--tplane-chat-citation-type-generic-border)}.chat-citation-type-badge{display:inline-flex;align-items:center;justify-content:center;min-width:0;max-width:120px;box-sizing:border-box;padding:1px 6px;border:1px solid currentColor;border-radius:999px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.35}.chat-citation-type-badge--web{color:var(--tplane-chat-citation-type-web-fg);background:var(--tplane-chat-citation-type-web-bg);border-color:var(--tplane-chat-citation-type-web-border)}.chat-citation-type-badge--file{color:var(--tplane-chat-citation-type-file-fg);background:var(--tplane-chat-citation-type-file-bg);border-color:var(--tplane-chat-citation-type-file-border)}.chat-citation-type-badge--app{color:var(--tplane-chat-citation-type-app-fg);background:var(--tplane-chat-citation-type-app-bg);border-color:var(--tplane-chat-citation-type-app-border)}.chat-citation-type-badge--memory{color:var(--tplane-chat-citation-type-memory-fg);background:var(--tplane-chat-citation-type-memory-bg);border-color:var(--tplane-chat-citation-type-memory-border)}.chat-citation-type-badge--generic{color:var(--tplane-chat-citation-type-generic-fg);background:var(--tplane-chat-citation-type-generic-bg);border-color:var(--tplane-chat-citation-type-generic-border)}:host{display:block}.chat-citation-preview{width:320px;max-width:calc(100vw - 24px);box-sizing:border-box;background:var(--tplane-chat-surface);border:1px solid var(--tplane-chat-separator);border-radius:var(--tplane-chat-radius-card);box-shadow:var(--tplane-chat-shadow-md);padding:12px 13px;text-align:left;color:var(--tplane-chat-text)}.chat-citation-preview__head{display:flex;align-items:center;gap:7px;margin-bottom:7px}.chat-citation-preview__fav{width:16px;height:16px;border-radius:4px;flex:0 0 auto;object-fit:cover}.chat-citation-preview__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:10px;font-weight:700}.chat-citation-preview__domain{font-size:12px;color:var(--tplane-chat-text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chat-citation-preview__type{margin-left:auto;font-size:11px;flex:0 0 auto}.chat-citation-preview__title{font-size:14px;font-weight:600;line-height:1.35;margin:0 0 5px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.chat-citation-preview__snippet{font-size:12.5px;color:var(--tplane-chat-text-muted);line-height:1.5;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.chat-citation-preview__foot{display:flex;align-items:center;justify-content:space-between;margin-top:10px;padding-top:9px;border-top:1px solid var(--tplane-chat-separator)}.chat-citation-preview__open{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:600;color:var(--tplane-chat-citation-accent);text-decoration:none}.chat-citation-preview__open:hover{text-decoration:underline}.chat-citation-preview__meta{font-size:11px;color:var(--tplane-chat-text-muted)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3093
3353
|
}
|
|
3094
3354
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatCitationPreviewComponent, decorators: [{
|
|
3095
3355
|
type: Component,
|
|
3096
3356
|
args: [{ selector: 'chat-citation-preview', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
3097
3357
|
<div class="chat-citation-preview" role="group" [attr.aria-label]="'Source ' + citation().index">
|
|
3098
3358
|
<div class="chat-citation-preview__head">
|
|
3099
|
-
@if (
|
|
3359
|
+
@if (sourceIconUrl(); as icon) {
|
|
3100
3360
|
<img class="chat-citation-preview__fav" [src]="icon" alt="" width="16" height="16" />
|
|
3361
|
+
} @else if (sourceIcon(); as icon) {
|
|
3362
|
+
<span class="chat-citation-source-icon chat-citation-preview__source-icon"
|
|
3363
|
+
aria-hidden="true"
|
|
3364
|
+
[class.chat-citation-source-icon--web]="icon === 'web'"
|
|
3365
|
+
[class.chat-citation-source-icon--file]="icon === 'file'"
|
|
3366
|
+
[class.chat-citation-source-icon--app]="icon === 'app'"
|
|
3367
|
+
[class.chat-citation-source-icon--memory]="icon === 'memory'"
|
|
3368
|
+
[class.chat-citation-source-icon--generic]="icon === 'generic'">
|
|
3369
|
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
|
3370
|
+
@switch (icon) {
|
|
3371
|
+
@case ('file') {
|
|
3372
|
+
<path d="M7 3.5h6.5L18 8v12.5H7z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" />
|
|
3373
|
+
<path d="M13.5 3.5V8H18M9.5 13h5M9.5 16h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
3374
|
+
}
|
|
3375
|
+
@case ('app') {
|
|
3376
|
+
<rect x="4" y="5" width="16" height="14" rx="2.5" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
3377
|
+
<path d="M8 9h.01M11.5 9h.01M15 9h.01M8 12.5h8M8 16h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
3378
|
+
}
|
|
3379
|
+
@case ('memory') {
|
|
3380
|
+
<path d="M8 7.5a4 4 0 0 1 8 0v9a4 4 0 0 1-8 0z" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
3381
|
+
<path d="M12 4v16M8 10h8M8 14h8" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
3382
|
+
}
|
|
3383
|
+
@case ('web') {
|
|
3384
|
+
<circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.8" />
|
|
3385
|
+
<path d="M4.5 12h15M12 4a12 12 0 0 1 0 16M12 4a12 12 0 0 0 0 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
3386
|
+
}
|
|
3387
|
+
@default {
|
|
3388
|
+
<path d="M6 5.5h12v13H6z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" />
|
|
3389
|
+
<path d="M9 9h6M9 12h6M9 15h3" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
3390
|
+
}
|
|
3391
|
+
}
|
|
3392
|
+
</svg>
|
|
3393
|
+
</span>
|
|
3101
3394
|
} @else {
|
|
3102
3395
|
<span class="chat-citation-preview__fav chat-citation-preview__fav--mono"
|
|
3103
|
-
[style.background]="
|
|
3396
|
+
[style.background]="sourceMonoColor()">{{ sourceMonogram() }}</span>
|
|
3104
3397
|
}
|
|
3105
3398
|
@if (domain(); as d) { <span class="chat-citation-preview__domain">{{ d }}</span> }
|
|
3106
|
-
@if (typeLabel(); as t) {
|
|
3399
|
+
@if (typeLabel(); as t) {
|
|
3400
|
+
<span class="chat-citation-preview__type chat-citation-type-badge"
|
|
3401
|
+
[class.chat-citation-type-badge--web]="isTypeTone('web')"
|
|
3402
|
+
[class.chat-citation-type-badge--file]="isTypeTone('file')"
|
|
3403
|
+
[class.chat-citation-type-badge--app]="isTypeTone('app')"
|
|
3404
|
+
[class.chat-citation-type-badge--memory]="isTypeTone('memory')"
|
|
3405
|
+
[class.chat-citation-type-badge--generic]="isTypeTone('generic')">{{ t }}</span>
|
|
3406
|
+
}
|
|
3107
3407
|
</div>
|
|
3108
3408
|
@if (citation().title; as title) {
|
|
3109
3409
|
<p class="chat-citation-preview__title">{{ title }}</p>
|
|
@@ -3123,7 +3423,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
3123
3423
|
</div>
|
|
3124
3424
|
}
|
|
3125
3425
|
</div>
|
|
3126
|
-
`, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block}.chat-citation-preview{width:320px;max-width:calc(100vw - 24px);box-sizing:border-box;background:var(--tplane-chat-surface);border:1px solid var(--tplane-chat-separator);border-radius:var(--tplane-chat-radius-card);box-shadow:var(--tplane-chat-shadow-md);padding:12px 13px;text-align:left;color:var(--tplane-chat-text)}.chat-citation-preview__head{display:flex;align-items:center;gap:7px;margin-bottom:7px}.chat-citation-preview__fav{width:16px;height:16px;border-radius:4px;flex:0 0 auto;object-fit:cover}.chat-citation-preview__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:10px;font-weight:700}.chat-citation-preview__domain{font-size:12px;color:var(--tplane-chat-text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chat-citation-preview__type{margin-left:auto;font-size:11px;
|
|
3426
|
+
`, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ".chat-citation-source-icon{width:18px;height:18px;flex:0 0 auto;box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;border-radius:5px;border:1px solid currentColor}.chat-citation-source-icon svg{width:12px;height:12px;display:block}.chat-citation-source-icon--sm{width:14px;height:14px;border-radius:4px}.chat-citation-source-icon--sm svg{width:9px;height:9px}.chat-citation-source-icon--web{color:var(--tplane-chat-citation-type-web-fg);background:var(--tplane-chat-citation-type-web-bg);border-color:var(--tplane-chat-citation-type-web-border)}.chat-citation-source-icon--file{color:var(--tplane-chat-citation-type-file-fg);background:var(--tplane-chat-citation-type-file-bg);border-color:var(--tplane-chat-citation-type-file-border)}.chat-citation-source-icon--app{color:var(--tplane-chat-citation-type-app-fg);background:var(--tplane-chat-citation-type-app-bg);border-color:var(--tplane-chat-citation-type-app-border)}.chat-citation-source-icon--memory{color:var(--tplane-chat-citation-type-memory-fg);background:var(--tplane-chat-citation-type-memory-bg);border-color:var(--tplane-chat-citation-type-memory-border)}.chat-citation-source-icon--generic{color:var(--tplane-chat-citation-type-generic-fg);background:var(--tplane-chat-citation-type-generic-bg);border-color:var(--tplane-chat-citation-type-generic-border)}.chat-citation-type-badge{display:inline-flex;align-items:center;justify-content:center;min-width:0;max-width:120px;box-sizing:border-box;padding:1px 6px;border:1px solid currentColor;border-radius:999px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.35}.chat-citation-type-badge--web{color:var(--tplane-chat-citation-type-web-fg);background:var(--tplane-chat-citation-type-web-bg);border-color:var(--tplane-chat-citation-type-web-border)}.chat-citation-type-badge--file{color:var(--tplane-chat-citation-type-file-fg);background:var(--tplane-chat-citation-type-file-bg);border-color:var(--tplane-chat-citation-type-file-border)}.chat-citation-type-badge--app{color:var(--tplane-chat-citation-type-app-fg);background:var(--tplane-chat-citation-type-app-bg);border-color:var(--tplane-chat-citation-type-app-border)}.chat-citation-type-badge--memory{color:var(--tplane-chat-citation-type-memory-fg);background:var(--tplane-chat-citation-type-memory-bg);border-color:var(--tplane-chat-citation-type-memory-border)}.chat-citation-type-badge--generic{color:var(--tplane-chat-citation-type-generic-fg);background:var(--tplane-chat-citation-type-generic-bg);border-color:var(--tplane-chat-citation-type-generic-border)}:host{display:block}.chat-citation-preview{width:320px;max-width:calc(100vw - 24px);box-sizing:border-box;background:var(--tplane-chat-surface);border:1px solid var(--tplane-chat-separator);border-radius:var(--tplane-chat-radius-card);box-shadow:var(--tplane-chat-shadow-md);padding:12px 13px;text-align:left;color:var(--tplane-chat-text)}.chat-citation-preview__head{display:flex;align-items:center;gap:7px;margin-bottom:7px}.chat-citation-preview__fav{width:16px;height:16px;border-radius:4px;flex:0 0 auto;object-fit:cover}.chat-citation-preview__fav--mono{display:flex;align-items:center;justify-content:center;color:#fff;font-size:10px;font-weight:700}.chat-citation-preview__domain{font-size:12px;color:var(--tplane-chat-text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chat-citation-preview__type{margin-left:auto;font-size:11px;flex:0 0 auto}.chat-citation-preview__title{font-size:14px;font-weight:600;line-height:1.35;margin:0 0 5px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.chat-citation-preview__snippet{font-size:12.5px;color:var(--tplane-chat-text-muted);line-height:1.5;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.chat-citation-preview__foot{display:flex;align-items:center;justify-content:space-between;margin-top:10px;padding-top:9px;border-top:1px solid var(--tplane-chat-separator)}.chat-citation-preview__open{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:600;color:var(--tplane-chat-citation-accent);text-decoration:none}.chat-citation-preview__open:hover{text-decoration:underline}.chat-citation-preview__meta{font-size:11px;color:var(--tplane-chat-text-muted)}\n"] }]
|
|
3127
3427
|
}], propDecorators: { citation: [{ type: i0.Input, args: [{ isSignal: true, alias: "citation", required: true }] }] } });
|
|
3128
3428
|
|
|
3129
3429
|
// libs/chat/src/lib/markdown/views/markdown-citation-reference.component.ts
|
|
@@ -3555,163 +3855,328 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
3555
3855
|
}]
|
|
3556
3856
|
}], propDecorators: { node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: true }] }] } });
|
|
3557
3857
|
|
|
3558
|
-
// libs/chat/src/lib/markdown/cacheplane-markdown-views.ts
|
|
3559
|
-
// SPDX-License-Identifier: MIT
|
|
3560
|
-
/**
|
|
3561
|
-
* Default view registry consumed by <chat-streaming-md>. Maps every
|
|
3562
|
-
* MarkdownNode.type emitted by @cacheplane/partial-markdown@0.2 to its
|
|
3563
|
-
* corresponding Angular component.
|
|
3564
|
-
*
|
|
3565
|
-
* Override per-node-type via `withViews(cacheplaneMarkdownViews, { … })`.
|
|
3566
|
-
*/
|
|
3567
|
-
const cacheplaneMarkdownViews = views({
|
|
3568
|
-
'document': MarkdownDocumentComponent,
|
|
3569
|
-
'paragraph': MarkdownParagraphComponent,
|
|
3570
|
-
'heading': MarkdownHeadingComponent,
|
|
3571
|
-
'blockquote': MarkdownBlockquoteComponent,
|
|
3572
|
-
'list': MarkdownListComponent,
|
|
3573
|
-
'list-item': MarkdownListItemComponent,
|
|
3574
|
-
'code-block': MarkdownCodeBlockComponent,
|
|
3575
|
-
'thematic-break': MarkdownThematicBreakComponent,
|
|
3576
|
-
'text': MarkdownTextComponent,
|
|
3577
|
-
'emphasis': MarkdownEmphasisComponent,
|
|
3578
|
-
'strong': MarkdownStrongComponent,
|
|
3579
|
-
'strikethrough': MarkdownStrikethroughComponent,
|
|
3580
|
-
'inline-code': MarkdownInlineCodeComponent,
|
|
3581
|
-
'math-inline': MarkdownMathComponent,
|
|
3582
|
-
'math-display': MarkdownMathComponent,
|
|
3583
|
-
'link': MarkdownLinkComponent,
|
|
3584
|
-
'autolink': MarkdownAutolinkComponent,
|
|
3585
|
-
'image': MarkdownImageComponent,
|
|
3586
|
-
'soft-break': MarkdownSoftBreakComponent,
|
|
3587
|
-
'hard-break': MarkdownHardBreakComponent,
|
|
3588
|
-
'citation-reference': MarkdownCitationReferenceComponent,
|
|
3589
|
-
'table': MarkdownTableComponent,
|
|
3590
|
-
'table-row': MarkdownTableRowComponent,
|
|
3591
|
-
'table-cell': MarkdownTableCellComponent,
|
|
3592
|
-
// Raw HTML (added by partial-markdown 0.4.x) renders as escaped literal text
|
|
3593
|
-
// — XSS-safe, and matches the pre-0.4 behavior where HTML was plain text.
|
|
3594
|
-
'html-block': MarkdownHtmlComponent,
|
|
3595
|
-
'html-inline': MarkdownHtmlComponent,
|
|
3596
|
-
});
|
|
3858
|
+
// libs/chat/src/lib/markdown/cacheplane-markdown-views.ts
|
|
3859
|
+
// SPDX-License-Identifier: MIT
|
|
3860
|
+
/**
|
|
3861
|
+
* Default view registry consumed by <chat-streaming-md>. Maps every
|
|
3862
|
+
* MarkdownNode.type emitted by @cacheplane/partial-markdown@0.2 to its
|
|
3863
|
+
* corresponding Angular component.
|
|
3864
|
+
*
|
|
3865
|
+
* Override per-node-type via `withViews(cacheplaneMarkdownViews, { … })`.
|
|
3866
|
+
*/
|
|
3867
|
+
const cacheplaneMarkdownViews = views({
|
|
3868
|
+
'document': MarkdownDocumentComponent,
|
|
3869
|
+
'paragraph': MarkdownParagraphComponent,
|
|
3870
|
+
'heading': MarkdownHeadingComponent,
|
|
3871
|
+
'blockquote': MarkdownBlockquoteComponent,
|
|
3872
|
+
'list': MarkdownListComponent,
|
|
3873
|
+
'list-item': MarkdownListItemComponent,
|
|
3874
|
+
'code-block': MarkdownCodeBlockComponent,
|
|
3875
|
+
'thematic-break': MarkdownThematicBreakComponent,
|
|
3876
|
+
'text': MarkdownTextComponent,
|
|
3877
|
+
'emphasis': MarkdownEmphasisComponent,
|
|
3878
|
+
'strong': MarkdownStrongComponent,
|
|
3879
|
+
'strikethrough': MarkdownStrikethroughComponent,
|
|
3880
|
+
'inline-code': MarkdownInlineCodeComponent,
|
|
3881
|
+
'math-inline': MarkdownMathComponent,
|
|
3882
|
+
'math-display': MarkdownMathComponent,
|
|
3883
|
+
'link': MarkdownLinkComponent,
|
|
3884
|
+
'autolink': MarkdownAutolinkComponent,
|
|
3885
|
+
'image': MarkdownImageComponent,
|
|
3886
|
+
'soft-break': MarkdownSoftBreakComponent,
|
|
3887
|
+
'hard-break': MarkdownHardBreakComponent,
|
|
3888
|
+
'citation-reference': MarkdownCitationReferenceComponent,
|
|
3889
|
+
'table': MarkdownTableComponent,
|
|
3890
|
+
'table-row': MarkdownTableRowComponent,
|
|
3891
|
+
'table-cell': MarkdownTableCellComponent,
|
|
3892
|
+
// Raw HTML (added by partial-markdown 0.4.x) renders as escaped literal text
|
|
3893
|
+
// — XSS-safe, and matches the pre-0.4 behavior where HTML was plain text.
|
|
3894
|
+
'html-block': MarkdownHtmlComponent,
|
|
3895
|
+
'html-inline': MarkdownHtmlComponent,
|
|
3896
|
+
});
|
|
3897
|
+
|
|
3898
|
+
// libs/chat/src/lib/styles/chat-markdown.styles.ts
|
|
3899
|
+
// SPDX-License-Identifier: MIT
|
|
3900
|
+
//
|
|
3901
|
+
// Scoped to the `chat-streaming-md` element selector (not `:host`) because
|
|
3902
|
+
// the component renders markdown via innerHTML and uses
|
|
3903
|
+
// `ViewEncapsulation.None` — emulated encapsulation would skip these rules
|
|
3904
|
+
// since innerHTML-injected nodes don't carry `_ngcontent-xxx` attributes.
|
|
3905
|
+
// Keeping selectors prefixed with the element name preserves locality so
|
|
3906
|
+
// these rules don't leak to other markup on the page.
|
|
3907
|
+
//
|
|
3908
|
+
// Covers the CommonMark + GFM surface: headings, paragraphs, links, lists
|
|
3909
|
+
// (bullet/ordered/task), code (inline + fenced), blockquotes, horizontal
|
|
3910
|
+
// rules, tables, images, bold (`strong`), italic (`em`), strikethrough
|
|
3911
|
+
// (`del`/`s`).
|
|
3912
|
+
const CHAT_MARKDOWN_STYLES = `
|
|
3913
|
+
chat-streaming-md { display: block; color: var(--tplane-chat-text); line-height: var(--tplane-chat-line-height); }
|
|
3914
|
+
|
|
3915
|
+
/* Headings */
|
|
3916
|
+
chat-streaming-md h1, chat-streaming-md h2, chat-streaming-md h3, chat-streaming-md h4, chat-streaming-md h5, chat-streaming-md h6 {
|
|
3917
|
+
font-weight: 600;
|
|
3918
|
+
line-height: 1.25;
|
|
3919
|
+
margin: 1.25rem 0 0.75rem;
|
|
3920
|
+
}
|
|
3921
|
+
chat-streaming-md h1:first-child, chat-streaming-md h2:first-child, chat-streaming-md h3:first-child,
|
|
3922
|
+
chat-streaming-md h4:first-child, chat-streaming-md h5:first-child, chat-streaming-md h6:first-child { margin-top: 0; }
|
|
3923
|
+
chat-streaming-md h1 { font-size: 1.5em; font-weight: 700; }
|
|
3924
|
+
chat-streaming-md h2 { font-size: 1.25em; }
|
|
3925
|
+
chat-streaming-md h3 { font-size: 1.1em; }
|
|
3926
|
+
chat-streaming-md h4 { font-size: 1em; }
|
|
3927
|
+
chat-streaming-md h5, chat-streaming-md h6 { font-size: 0.95em; color: var(--tplane-chat-text-muted); }
|
|
3928
|
+
|
|
3929
|
+
/* Paragraphs and inline emphasis */
|
|
3930
|
+
chat-streaming-md p { margin: 0 0 0.75rem; line-height: 1.6; font-size: var(--tplane-chat-font-size); }
|
|
3931
|
+
chat-streaming-md p:last-child { margin-bottom: 0; }
|
|
3932
|
+
chat-streaming-md strong, chat-streaming-md b { font-weight: 700; }
|
|
3933
|
+
chat-streaming-md em, chat-streaming-md i { font-style: italic; }
|
|
3934
|
+
chat-streaming-md del, chat-streaming-md s { text-decoration: line-through; color: var(--tplane-chat-text-muted); }
|
|
3935
|
+
chat-streaming-md mark { background: var(--tplane-chat-surface-alt); padding: 0 2px; border-radius: 2px; }
|
|
3936
|
+
chat-streaming-md sub { font-size: 0.75em; vertical-align: sub; }
|
|
3937
|
+
chat-streaming-md sup { font-size: 0.75em; vertical-align: super; }
|
|
3938
|
+
|
|
3939
|
+
/* Links */
|
|
3940
|
+
chat-streaming-md a { color: var(--tplane-chat-primary); text-decoration: underline; text-underline-offset: 2px; }
|
|
3941
|
+
chat-streaming-md a:hover { text-decoration-thickness: 2px; }
|
|
3942
|
+
|
|
3943
|
+
/* Lists (CommonMark + GFM task lists) */
|
|
3944
|
+
chat-streaming-md ul, chat-streaming-md ol { margin: 0 0 0.75rem; padding-left: 1.5rem; }
|
|
3945
|
+
chat-streaming-md ul { list-style: disc outside; }
|
|
3946
|
+
chat-streaming-md ol { list-style: decimal outside; }
|
|
3947
|
+
chat-streaming-md ul ul { list-style: circle outside; }
|
|
3948
|
+
chat-streaming-md ul ul ul { list-style: square outside; }
|
|
3949
|
+
chat-streaming-md li { margin: 0.2rem 0; }
|
|
3950
|
+
chat-streaming-md li::marker { color: var(--tplane-chat-text-muted); }
|
|
3951
|
+
chat-streaming-md li > p { margin: 0 0 0.25rem; }
|
|
3952
|
+
chat-streaming-md li > ul, chat-streaming-md li > ol { margin: 0.25rem 0 0; }
|
|
3953
|
+
/* GFM task lists: marked emits <li><input type="checkbox" disabled> ... */
|
|
3954
|
+
chat-streaming-md li:has(> input[type="checkbox"]) { list-style: none; margin-left: -1.25rem; }
|
|
3955
|
+
chat-streaming-md li > input[type="checkbox"] { margin-right: 0.5rem; vertical-align: middle; }
|
|
3956
|
+
|
|
3957
|
+
/* Code (inline + fenced) */
|
|
3958
|
+
chat-streaming-md code {
|
|
3959
|
+
background: var(--tplane-chat-surface-alt);
|
|
3960
|
+
color: var(--tplane-chat-text);
|
|
3961
|
+
padding: 1px 5px;
|
|
3962
|
+
border-radius: 4px;
|
|
3963
|
+
font-family: var(--tplane-chat-font-mono);
|
|
3964
|
+
font-size: 0.9em;
|
|
3965
|
+
}
|
|
3966
|
+
chat-streaming-md pre {
|
|
3967
|
+
background: var(--tplane-chat-surface-alt);
|
|
3968
|
+
color: var(--tplane-chat-text);
|
|
3969
|
+
padding: 12px 14px;
|
|
3970
|
+
border-radius: var(--tplane-chat-radius-card);
|
|
3971
|
+
overflow-x: auto;
|
|
3972
|
+
font-family: var(--tplane-chat-font-mono);
|
|
3973
|
+
font-size: var(--tplane-chat-font-size-sm);
|
|
3974
|
+
line-height: 1.5;
|
|
3975
|
+
margin: 0 0 0.75rem;
|
|
3976
|
+
}
|
|
3977
|
+
chat-streaming-md pre code { background: transparent; padding: 0; border-radius: 0; font-size: inherit; }
|
|
3978
|
+
|
|
3979
|
+
/* Blockquote */
|
|
3980
|
+
chat-streaming-md blockquote {
|
|
3981
|
+
border-left: 3px solid var(--tplane-chat-separator);
|
|
3982
|
+
padding: 0.25rem 0 0.25rem 12px;
|
|
3983
|
+
margin: 0 0 0.75rem;
|
|
3984
|
+
color: var(--tplane-chat-text-muted);
|
|
3985
|
+
}
|
|
3986
|
+
chat-streaming-md blockquote > :last-child { margin-bottom: 0; }
|
|
3987
|
+
|
|
3988
|
+
/* Horizontal rule */
|
|
3989
|
+
chat-streaming-md hr {
|
|
3990
|
+
border: none;
|
|
3991
|
+
border-top: 1px solid var(--tplane-chat-separator);
|
|
3992
|
+
margin: 1rem 0;
|
|
3993
|
+
}
|
|
3994
|
+
|
|
3995
|
+
/* Tables (GFM) */
|
|
3996
|
+
chat-streaming-md table {
|
|
3997
|
+
border-collapse: collapse;
|
|
3998
|
+
margin: 0 0 0.75rem;
|
|
3999
|
+
width: 100%;
|
|
4000
|
+
font-size: 0.95em;
|
|
4001
|
+
}
|
|
4002
|
+
chat-streaming-md thead { background: var(--tplane-chat-surface-alt); }
|
|
4003
|
+
chat-streaming-md th, chat-streaming-md td {
|
|
4004
|
+
border: 1px solid var(--tplane-chat-separator);
|
|
4005
|
+
padding: 6px 10px;
|
|
4006
|
+
text-align: left;
|
|
4007
|
+
vertical-align: top;
|
|
4008
|
+
}
|
|
4009
|
+
chat-streaming-md th { font-weight: 600; }
|
|
4010
|
+
/* Component-rendered table: chat-md-table becomes a horizontally-scrollable
|
|
4011
|
+
wrapper for the inner <table>; row/cell elements stay layout-transparent
|
|
4012
|
+
so the browser's table layout takes over. Without this overflow wrapper,
|
|
4013
|
+
wide tables push their parent container past the viewport horizontally. */
|
|
4014
|
+
chat-streaming-md chat-md-table {
|
|
4015
|
+
display: block;
|
|
4016
|
+
overflow-x: auto;
|
|
4017
|
+
max-width: 100%;
|
|
4018
|
+
margin: 0 0 0.75rem;
|
|
4019
|
+
}
|
|
4020
|
+
chat-streaming-md chat-md-table-row { display: contents; }
|
|
4021
|
+
chat-streaming-md chat-md-table-cell { display: contents; }
|
|
4022
|
+
chat-streaming-md chat-md-table > table { margin: 0; }
|
|
4023
|
+
/* Task-list items: checkbox + first paragraph render inline; subsequent
|
|
4024
|
+
blocks (sub-lists, multi-paragraph items) flow normally below. */
|
|
4025
|
+
chat-streaming-md li.chat-md-list-item--task {
|
|
4026
|
+
list-style: none;
|
|
4027
|
+
margin-left: -1.25rem;
|
|
4028
|
+
display: flex;
|
|
4029
|
+
flex-wrap: wrap;
|
|
4030
|
+
align-items: baseline;
|
|
4031
|
+
gap: 0.5rem;
|
|
4032
|
+
}
|
|
4033
|
+
chat-streaming-md li.chat-md-list-item--task > input[type="checkbox"] {
|
|
4034
|
+
margin: 0;
|
|
4035
|
+
flex: 0 0 auto;
|
|
4036
|
+
transform: translateY(2px);
|
|
4037
|
+
}
|
|
4038
|
+
/* The chat-md-children wrapper around list-item content takes remaining width */
|
|
4039
|
+
chat-streaming-md li.chat-md-list-item--task > chat-md-children {
|
|
4040
|
+
flex: 1 1 auto;
|
|
4041
|
+
min-width: 0;
|
|
4042
|
+
}
|
|
4043
|
+
/* Tight task items: only the FIRST paragraph aligns inline with the
|
|
4044
|
+
checkbox (margin collapsed). Subsequent paragraphs/blocks keep their
|
|
4045
|
+
normal vertical spacing so multi-block items render readably. */
|
|
4046
|
+
chat-streaming-md li.chat-md-list-item--task > chat-md-children > chat-md-paragraph:first-child > p {
|
|
4047
|
+
margin: 0;
|
|
4048
|
+
}
|
|
4049
|
+
|
|
4050
|
+
/* Media */
|
|
4051
|
+
chat-streaming-md img { max-width: 100%; height: auto; border-radius: 6px; }
|
|
4052
|
+
/* Broken-image fallback: muted pill showing alt text + icon. Triggered
|
|
4053
|
+
when <img> fires (error). Caught by live browser smoke — prior impl
|
|
4054
|
+
showed only the browser's broken-image icon with no readable alt. */
|
|
4055
|
+
chat-streaming-md .chat-md-image--broken {
|
|
4056
|
+
display: inline-flex;
|
|
4057
|
+
align-items: center;
|
|
4058
|
+
gap: 0.4rem;
|
|
4059
|
+
padding: 0.25rem 0.5rem;
|
|
4060
|
+
background: var(--tplane-chat-surface-alt);
|
|
4061
|
+
border: 1px dashed var(--tplane-chat-separator);
|
|
4062
|
+
border-radius: 6px;
|
|
4063
|
+
font-size: 0.9em;
|
|
4064
|
+
color: var(--tplane-chat-text-muted, currentColor);
|
|
4065
|
+
opacity: 0.85;
|
|
4066
|
+
}
|
|
4067
|
+
chat-streaming-md .chat-md-image__icon { font-size: 1em; line-height: 1; }
|
|
4068
|
+
chat-streaming-md .chat-md-image__alt { font-style: italic; }
|
|
4069
|
+
/* Math (KaTeX). Display math is a centered block that scrolls horizontally
|
|
4070
|
+
on overflow; the raw fallback (KaTeX missing or invalid LaTeX) reads as
|
|
4071
|
+
monospace so the source delimiters look intentional. */
|
|
4072
|
+
chat-streaming-md .chat-md-math--display { display: block; margin: 0.5em 0; overflow-x: auto; }
|
|
4073
|
+
chat-streaming-md .chat-md-math--raw { font-family: var(--tplane-chat-font-mono, ui-monospace, monospace); }
|
|
4074
|
+
`;
|
|
3597
4075
|
|
|
3598
4076
|
// libs/chat/src/lib/streaming/streaming-markdown.component.ts
|
|
3599
4077
|
// SPDX-License-Identifier: MIT
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
const
|
|
4078
|
+
/** Creates the atomic document consumed by the streaming Markdown renderer. */
|
|
4079
|
+
function markdownDocument(content, delivery, suffix = '') {
|
|
4080
|
+
return {
|
|
4081
|
+
generation: delivery.generation + suffix,
|
|
4082
|
+
phase: delivery.phase,
|
|
4083
|
+
content,
|
|
4084
|
+
};
|
|
4085
|
+
}
|
|
4086
|
+
const STREAMING_MARKDOWN_CONTRACT_VIOLATION_POLICY = new InjectionToken('STREAMING_MARKDOWN_CONTRACT_VIOLATION_POLICY', {
|
|
4087
|
+
providedIn: 'root',
|
|
4088
|
+
factory: () => (isDevMode() ? 'throw' : 'rebuild'),
|
|
4089
|
+
});
|
|
4090
|
+
/** @internal Test seam for verifying parser lifecycle ordering. */
|
|
4091
|
+
const STREAMING_MARKDOWN_PARSER_FACTORY = new InjectionToken('STREAMING_MARKDOWN_PARSER_FACTORY', {
|
|
4092
|
+
providedIn: 'root',
|
|
4093
|
+
factory: () => createPartialMarkdownParser,
|
|
4094
|
+
});
|
|
4095
|
+
function contractViolation(prior, supplied, reason) {
|
|
4096
|
+
return new Error(`Streaming markdown document contract violation: ${reason}; ` +
|
|
4097
|
+
`generation ${JSON.stringify(supplied.generation)} cannot transition ` +
|
|
4098
|
+
`from ${prior.phase} content of length ${prior.content.length} ` +
|
|
4099
|
+
`to ${supplied.phase} content of length ${supplied.content.length}.`);
|
|
4100
|
+
}
|
|
4101
|
+
function contractViolationReason(prior, supplied) {
|
|
4102
|
+
if (prior.phase === 'complete') {
|
|
4103
|
+
return supplied.phase === 'streaming'
|
|
4104
|
+
? 'complete-to-streaming'
|
|
4105
|
+
: 'post-completion-content-mutation';
|
|
4106
|
+
}
|
|
4107
|
+
if (supplied.content.length < prior.content.length)
|
|
4108
|
+
return 'content-shrink';
|
|
4109
|
+
if (!supplied.content.startsWith(prior.content))
|
|
4110
|
+
return 'content-divergence';
|
|
4111
|
+
return null;
|
|
4112
|
+
}
|
|
3609
4113
|
/**
|
|
3610
|
-
* Renders
|
|
3611
|
-
*
|
|
3612
|
-
*
|
|
3613
|
-
* Reactivity model: the live `parser.root` keeps a stable JS reference
|
|
3614
|
-
* across pushes (partial-markdown's identity guarantee). To make Angular
|
|
3615
|
-
* signals propagate downstream when the underlying tree changes, we surface
|
|
3616
|
-
* a materialized snapshot via `materialize()`. The snapshot shares
|
|
3617
|
-
* structurally — unchanged subtrees keep the SAME reference, and any
|
|
3618
|
-
* descendant change yields a NEW root reference. This lets Angular's
|
|
3619
|
-
* `Object.is` equality check both detect changes (root reference differs)
|
|
3620
|
-
* and short-circuit unchanged subtrees (per-node references stable).
|
|
3621
|
-
*
|
|
3622
|
-
* Override per-node-type renderers via the `[viewRegistry]` input or by
|
|
3623
|
-
* supplying a different `MARKDOWN_VIEW_REGISTRY` provider in the injector
|
|
3624
|
-
* tree.
|
|
4114
|
+
* Renders one explicitly-versioned markdown document through the shared view
|
|
4115
|
+
* registry. A generation owns one parser session; append-only updates preserve
|
|
4116
|
+
* parser and subtree identity, while generation changes replace the session.
|
|
3625
4117
|
*/
|
|
3626
4118
|
class ChatStreamingMdComponent {
|
|
3627
|
-
|
|
3628
|
-
streaming = input(false, ...(ngDevMode ? [{ debugName: "streaming" }] : []));
|
|
4119
|
+
document = input.required(...(ngDevMode ? [{ debugName: "document" }] : []));
|
|
3629
4120
|
viewRegistry = input(undefined, ...(ngDevMode ? [{ debugName: "viewRegistry" }] : []));
|
|
3630
4121
|
resolvedRegistry = computed(() => this.viewRegistry() ?? cacheplaneMarkdownViews, ...(ngDevMode ? [{ debugName: "resolvedRegistry" }] : []));
|
|
3631
|
-
resolver = inject(CitationsResolverService, {
|
|
4122
|
+
resolver = inject(CitationsResolverService, {
|
|
4123
|
+
optional: true,
|
|
4124
|
+
});
|
|
4125
|
+
violationPolicy = inject(STREAMING_MARKDOWN_CONTRACT_VIOLATION_POLICY);
|
|
4126
|
+
createParser = inject(STREAMING_MARKDOWN_PARSER_FACTORY);
|
|
4127
|
+
parser = null;
|
|
4128
|
+
prior = null;
|
|
4129
|
+
materializedRoot = null;
|
|
4130
|
+
root = computed(() => {
|
|
4131
|
+
this.process(this.document());
|
|
4132
|
+
return this.materializedRoot;
|
|
4133
|
+
}, ...(ngDevMode ? [{ debugName: "root" }] : []));
|
|
3632
4134
|
constructor() {
|
|
3633
4135
|
effect(() => {
|
|
3634
|
-
const
|
|
3635
|
-
if (this.resolver
|
|
3636
|
-
this.resolver.markdownDefs.set(
|
|
3637
|
-
}
|
|
3638
|
-
});
|
|
3639
|
-
// Debounced finalization. `finish()` is terminal and DESTRUCTIVE: it reverts
|
|
3640
|
-
// an incomplete trailing construct to its CommonMark fallback — e.g. a table
|
|
3641
|
-
// header before its delimiter row becomes raw "| a | b |" paragraph text. We
|
|
3642
|
-
// must therefore never finalize while tokens are still arriving. The
|
|
3643
|
-
// `streaming` input is not a reliable "still arriving" signal — it can flap
|
|
3644
|
-
// false mid-stream, and at cold start it can read false for an entire live
|
|
3645
|
-
// stream — so we finalize only once streaming is false AND no new content
|
|
3646
|
-
// has arrived for a short, imperceptible window. Any new content or a
|
|
3647
|
-
// streaming=true flap re-arms the timer, so finalize fires exactly once,
|
|
3648
|
-
// after the stream truly stops. Until then the live `parser.root` projection
|
|
3649
|
-
// (0.5.x) renders the in-progress content, including streaming tables.
|
|
3650
|
-
let timer = null;
|
|
3651
|
-
effect((onCleanup) => {
|
|
3652
|
-
const isStreaming = this.streaming();
|
|
3653
|
-
this.content(); // re-arm whenever new content arrives
|
|
3654
|
-
if (timer) {
|
|
3655
|
-
clearTimeout(timer);
|
|
3656
|
-
timer = null;
|
|
4136
|
+
const root = this.root();
|
|
4137
|
+
if (this.resolver) {
|
|
4138
|
+
this.resolver.markdownDefs.set(root?.citations ?? new Map());
|
|
3657
4139
|
}
|
|
3658
|
-
if (isStreaming || this.finished)
|
|
3659
|
-
return;
|
|
3660
|
-
timer = setTimeout(() => {
|
|
3661
|
-
timer = null;
|
|
3662
|
-
if (this.streaming() || this.finished)
|
|
3663
|
-
return;
|
|
3664
|
-
if (!this.prior.endsWith('\n'))
|
|
3665
|
-
this.parser.push('\n');
|
|
3666
|
-
this.parser.finish();
|
|
3667
|
-
this.finished = true;
|
|
3668
|
-
this.finalizeTick.update((v) => v + 1);
|
|
3669
|
-
}, FINALIZE_DEBOUNCE_MS);
|
|
3670
|
-
onCleanup(() => {
|
|
3671
|
-
if (timer) {
|
|
3672
|
-
clearTimeout(timer);
|
|
3673
|
-
timer = null;
|
|
3674
|
-
}
|
|
3675
|
-
});
|
|
3676
4140
|
});
|
|
3677
4141
|
}
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
// Re-parse from scratch when the content diverged from the prior prefix,
|
|
3692
|
-
// OR when the parser was already finalized — finish() is terminal, so
|
|
3693
|
-
// pushing further deltas into a finished parser corrupts its state. A
|
|
3694
|
-
// transient `streaming=false` mid-stream that finalized early thus
|
|
3695
|
-
// recovers here: new content rebuilds an open, projecting parser.
|
|
3696
|
-
if (c.startsWith(this.prior) && !this.finished) {
|
|
3697
|
-
this.parser.push(c.slice(this.prior.length));
|
|
4142
|
+
process(supplied) {
|
|
4143
|
+
const prior = this.prior;
|
|
4144
|
+
if (!prior || supplied.generation !== prior.generation) {
|
|
4145
|
+
this.replaceFrom(supplied);
|
|
4146
|
+
return;
|
|
4147
|
+
}
|
|
4148
|
+
if (supplied.phase === prior.phase && supplied.content === prior.content) {
|
|
4149
|
+
return;
|
|
4150
|
+
}
|
|
4151
|
+
const violationReason = contractViolationReason(prior, supplied);
|
|
4152
|
+
if (violationReason) {
|
|
4153
|
+
if (this.violationPolicy === 'throw') {
|
|
4154
|
+
throw contractViolation(prior, supplied, violationReason);
|
|
3698
4155
|
}
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
4156
|
+
this.replaceFrom(supplied);
|
|
4157
|
+
return;
|
|
4158
|
+
}
|
|
4159
|
+
const parser = this.parser;
|
|
4160
|
+
const delta = supplied.content.slice(prior.content.length);
|
|
4161
|
+
if (delta.length > 0)
|
|
4162
|
+
parser.push(delta);
|
|
4163
|
+
if (supplied.phase === 'complete')
|
|
4164
|
+
parser.finish();
|
|
4165
|
+
this.materializedRoot = materialize(parser.root);
|
|
4166
|
+
this.prior = { ...supplied };
|
|
4167
|
+
}
|
|
4168
|
+
replaceFrom(supplied) {
|
|
4169
|
+
const parser = this.createParser();
|
|
4170
|
+
parser.push(supplied.content);
|
|
4171
|
+
if (supplied.phase === 'complete')
|
|
4172
|
+
parser.finish();
|
|
4173
|
+
const root = materialize(parser.root);
|
|
4174
|
+
this.parser = parser;
|
|
4175
|
+
this.prior = { ...supplied };
|
|
4176
|
+
this.materializedRoot = root;
|
|
4177
|
+
}
|
|
3713
4178
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatStreamingMdComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3714
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: ChatStreamingMdComponent, isStandalone: true, selector: "chat-streaming-md", inputs: {
|
|
4179
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: ChatStreamingMdComponent, isStandalone: true, selector: "chat-streaming-md", inputs: { document: { classPropertyName: "document", publicName: "document", isSignal: true, isRequired: true, transformFunction: null }, viewRegistry: { classPropertyName: "viewRegistry", publicName: "viewRegistry", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
3715
4180
|
{
|
|
3716
4181
|
provide: MARKDOWN_VIEW_REGISTRY,
|
|
3717
4182
|
useFactory: (host) => host.resolvedRegistry(),
|
|
@@ -3736,7 +4201,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
3736
4201
|
deps: [ChatStreamingMdComponent],
|
|
3737
4202
|
},
|
|
3738
4203
|
], styles: ["chat-streaming-md{display:block;color:var(--tplane-chat-text);line-height:var(--tplane-chat-line-height)}chat-streaming-md h1,chat-streaming-md h2,chat-streaming-md h3,chat-streaming-md h4,chat-streaming-md h5,chat-streaming-md h6{font-weight:600;line-height:1.25;margin:1.25rem 0 .75rem}chat-streaming-md h1:first-child,chat-streaming-md h2:first-child,chat-streaming-md h3:first-child,chat-streaming-md h4:first-child,chat-streaming-md h5:first-child,chat-streaming-md h6:first-child{margin-top:0}chat-streaming-md h1{font-size:1.5em;font-weight:700}chat-streaming-md h2{font-size:1.25em}chat-streaming-md h3{font-size:1.1em}chat-streaming-md h4{font-size:1em}chat-streaming-md h5,chat-streaming-md h6{font-size:.95em;color:var(--tplane-chat-text-muted)}chat-streaming-md p{margin:0 0 .75rem;line-height:1.6;font-size:var(--tplane-chat-font-size)}chat-streaming-md p:last-child{margin-bottom:0}chat-streaming-md strong,chat-streaming-md b{font-weight:700}chat-streaming-md em,chat-streaming-md i{font-style:italic}chat-streaming-md del,chat-streaming-md s{text-decoration:line-through;color:var(--tplane-chat-text-muted)}chat-streaming-md mark{background:var(--tplane-chat-surface-alt);padding:0 2px;border-radius:2px}chat-streaming-md sub{font-size:.75em;vertical-align:sub}chat-streaming-md sup{font-size:.75em;vertical-align:super}chat-streaming-md a{color:var(--tplane-chat-primary);text-decoration:underline;text-underline-offset:2px}chat-streaming-md a:hover{text-decoration-thickness:2px}chat-streaming-md ul,chat-streaming-md ol{margin:0 0 .75rem;padding-left:1.5rem}chat-streaming-md ul{list-style:disc outside}chat-streaming-md ol{list-style:decimal outside}chat-streaming-md ul ul{list-style:circle outside}chat-streaming-md ul ul ul{list-style:square outside}chat-streaming-md li{margin:.2rem 0}chat-streaming-md li::marker{color:var(--tplane-chat-text-muted)}chat-streaming-md li>p{margin:0 0 .25rem}chat-streaming-md li>ul,chat-streaming-md li>ol{margin:.25rem 0 0}chat-streaming-md li:has(>input[type=checkbox]){list-style:none;margin-left:-1.25rem}chat-streaming-md li>input[type=checkbox]{margin-right:.5rem;vertical-align:middle}chat-streaming-md code{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text);padding:1px 5px;border-radius:4px;font-family:var(--tplane-chat-font-mono);font-size:.9em}chat-streaming-md pre{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text);padding:12px 14px;border-radius:var(--tplane-chat-radius-card);overflow-x:auto;font-family:var(--tplane-chat-font-mono);font-size:var(--tplane-chat-font-size-sm);line-height:1.5;margin:0 0 .75rem}chat-streaming-md pre code{background:transparent;padding:0;border-radius:0;font-size:inherit}chat-streaming-md blockquote{border-left:3px solid var(--tplane-chat-separator);padding:.25rem 0 .25rem 12px;margin:0 0 .75rem;color:var(--tplane-chat-text-muted)}chat-streaming-md blockquote>:last-child{margin-bottom:0}chat-streaming-md hr{border:none;border-top:1px solid var(--tplane-chat-separator);margin:1rem 0}chat-streaming-md table{border-collapse:collapse;margin:0 0 .75rem;width:100%;font-size:.95em}chat-streaming-md thead{background:var(--tplane-chat-surface-alt)}chat-streaming-md th,chat-streaming-md td{border:1px solid var(--tplane-chat-separator);padding:6px 10px;text-align:left;vertical-align:top}chat-streaming-md th{font-weight:600}chat-streaming-md chat-md-table{display:block;overflow-x:auto;max-width:100%;margin:0 0 .75rem}chat-streaming-md chat-md-table-row{display:contents}chat-streaming-md chat-md-table-cell{display:contents}chat-streaming-md chat-md-table>table{margin:0}chat-streaming-md li.chat-md-list-item--task{list-style:none;margin-left:-1.25rem;display:flex;flex-wrap:wrap;align-items:baseline;gap:.5rem}chat-streaming-md li.chat-md-list-item--task>input[type=checkbox]{margin:0;flex:0 0 auto;transform:translateY(2px)}chat-streaming-md li.chat-md-list-item--task>chat-md-children{flex:1 1 auto;min-width:0}chat-streaming-md li.chat-md-list-item--task>chat-md-children>chat-md-paragraph:first-child>p{margin:0}chat-streaming-md img{max-width:100%;height:auto;border-radius:6px}chat-streaming-md .chat-md-image--broken{display:inline-flex;align-items:center;gap:.4rem;padding:.25rem .5rem;background:var(--tplane-chat-surface-alt);border:1px dashed var(--tplane-chat-separator);border-radius:6px;font-size:.9em;color:var(--tplane-chat-text-muted, currentColor);opacity:.85}chat-streaming-md .chat-md-image__icon{font-size:1em;line-height:1}chat-streaming-md .chat-md-image__alt{font-style:italic}chat-streaming-md .chat-md-math--display{display:block;margin:.5em 0;overflow-x:auto}chat-streaming-md .chat-md-math--raw{font-family:var(--tplane-chat-font-mono, ui-monospace, monospace)}\n"] }]
|
|
3739
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
4204
|
+
}], ctorParameters: () => [], propDecorators: { document: [{ type: i0.Input, args: [{ isSignal: true, alias: "document", required: true }] }], viewRegistry: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewRegistry", required: false }] }] } });
|
|
3740
4205
|
|
|
3741
4206
|
// SPDX-License-Identifier: MIT
|
|
3742
4207
|
/**
|
|
@@ -3778,17 +4243,19 @@ function formatDuration(ms) {
|
|
|
3778
4243
|
* step labels often appear in reasoning output).
|
|
3779
4244
|
*
|
|
3780
4245
|
* Internal state: a tristate "expanded" — null means follow auto state-
|
|
3781
|
-
* driven logic (force-expand
|
|
4246
|
+
* driven logic (force-expand while delivery is streaming, otherwise honor
|
|
3782
4247
|
* defaultExpanded), boolean is a manual user choice that wins for the
|
|
3783
4248
|
* lifetime of the instance.
|
|
3784
4249
|
*/
|
|
3785
4250
|
class ChatReasoningComponent {
|
|
3786
4251
|
content = input('', ...(ngDevMode ? [{ debugName: "content" }] : []));
|
|
3787
|
-
|
|
4252
|
+
delivery = input.required(...(ngDevMode ? [{ debugName: "delivery" }] : []));
|
|
3788
4253
|
durationMs = input(undefined, ...(ngDevMode ? [{ debugName: "durationMs" }] : []));
|
|
3789
4254
|
label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
3790
4255
|
defaultExpanded = input(false, ...(ngDevMode ? [{ debugName: "defaultExpanded" }] : []));
|
|
3791
4256
|
hasContent = computed(() => (this.content() ?? '').length > 0, ...(ngDevMode ? [{ debugName: "hasContent" }] : []));
|
|
4257
|
+
isStreaming = computed(() => this.delivery().phase === 'streaming', ...(ngDevMode ? [{ debugName: "isStreaming" }] : []));
|
|
4258
|
+
document = computed(() => markdownDocument(this.content(), this.delivery(), ':reasoning'), ...(ngDevMode ? [{ debugName: "document" }] : []));
|
|
3792
4259
|
/** null = follow auto logic (streaming → expanded, else defaultExpanded). */
|
|
3793
4260
|
_expandedOverride = signal(null, ...(ngDevMode ? [{ debugName: "_expandedOverride" }] : []));
|
|
3794
4261
|
expanded = computed(() => {
|
|
@@ -3828,7 +4295,7 @@ class ChatReasoningComponent {
|
|
|
3828
4295
|
this._expandedOverride.set(!this.expanded());
|
|
3829
4296
|
}
|
|
3830
4297
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatReasoningComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3831
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: ChatReasoningComponent, isStandalone: true, selector: "chat-reasoning", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null },
|
|
4298
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: ChatReasoningComponent, isStandalone: true, selector: "chat-reasoning", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, delivery: { classPropertyName: "delivery", publicName: "delivery", isSignal: true, isRequired: true, transformFunction: null }, durationMs: { classPropertyName: "durationMs", publicName: "durationMs", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, defaultExpanded: { classPropertyName: "defaultExpanded", publicName: "defaultExpanded", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-has-content": "hasContent()", "attr.data-expanded": "expandedStr()", "attr.data-streaming": "isStreaming()" } }, ngImport: i0, template: `
|
|
3832
4299
|
<button
|
|
3833
4300
|
type="button"
|
|
3834
4301
|
class="chat-reasoning__header"
|
|
@@ -3845,10 +4312,10 @@ class ChatReasoningComponent {
|
|
|
3845
4312
|
</button>
|
|
3846
4313
|
@if (expanded()) {
|
|
3847
4314
|
<div class="chat-reasoning__body">
|
|
3848
|
-
<chat-streaming-md [
|
|
4315
|
+
<chat-streaming-md [document]="document()" />
|
|
3849
4316
|
</div>
|
|
3850
4317
|
}
|
|
3851
|
-
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block;margin:0 0 .5rem}:host([data-has-content=\"false\"]){display:none}.chat-reasoning__header{display:inline-flex;align-items:center;gap:.5rem;padding:4px 10px;background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);border-radius:9999px;color:var(--tplane-chat-text-muted);font-size:var(--tplane-chat-font-size-xs);font-family:inherit;cursor:pointer;line-height:1.2}.chat-reasoning__header:hover{color:var(--tplane-chat-text)}.chat-reasoning__chevron{width:10px;height:10px;transition:transform .12s ease}:host([data-expanded=\"true\"]) .chat-reasoning__chevron{transform:rotate(90deg)}.chat-reasoning__pulse{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--tplane-chat-text-muted);animation:chat-reasoning-pulse 1.2s ease-in-out infinite}@keyframes chat-reasoning-pulse{0%,to{opacity:.3}50%{opacity:1}}.chat-reasoning__body{margin-top:.5rem;padding-left:12px;border-left:2px solid var(--tplane-chat-separator);color:var(--tplane-chat-text-muted)}.chat-reasoning__body chat-streaming-md{font-size:.95em}\n"], dependencies: [{ kind: "component", type: ChatStreamingMdComponent, selector: "chat-streaming-md", inputs: ["
|
|
4318
|
+
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block;margin:0 0 .5rem}:host([data-has-content=\"false\"]){display:none}.chat-reasoning__header{display:inline-flex;align-items:center;gap:.5rem;padding:4px 10px;background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);border-radius:9999px;color:var(--tplane-chat-text-muted);font-size:var(--tplane-chat-font-size-xs);font-family:inherit;cursor:pointer;line-height:1.2}.chat-reasoning__header:hover{color:var(--tplane-chat-text)}.chat-reasoning__chevron{width:10px;height:10px;transition:transform .12s ease}:host([data-expanded=\"true\"]) .chat-reasoning__chevron{transform:rotate(90deg)}.chat-reasoning__pulse{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--tplane-chat-text-muted);animation:chat-reasoning-pulse 1.2s ease-in-out infinite}@keyframes chat-reasoning-pulse{0%,to{opacity:.3}50%{opacity:1}}.chat-reasoning__body{margin-top:.5rem;padding-left:12px;border-left:2px solid var(--tplane-chat-separator);color:var(--tplane-chat-text-muted)}.chat-reasoning__body chat-streaming-md{font-size:.95em}\n"], dependencies: [{ kind: "component", type: ChatStreamingMdComponent, selector: "chat-streaming-md", inputs: ["document", "viewRegistry"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3852
4319
|
}
|
|
3853
4320
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatReasoningComponent, decorators: [{
|
|
3854
4321
|
type: Component,
|
|
@@ -3873,11 +4340,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
3873
4340
|
</button>
|
|
3874
4341
|
@if (expanded()) {
|
|
3875
4342
|
<div class="chat-reasoning__body">
|
|
3876
|
-
<chat-streaming-md [
|
|
4343
|
+
<chat-streaming-md [document]="document()" />
|
|
3877
4344
|
</div>
|
|
3878
4345
|
}
|
|
3879
4346
|
`, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block;margin:0 0 .5rem}:host([data-has-content=\"false\"]){display:none}.chat-reasoning__header{display:inline-flex;align-items:center;gap:.5rem;padding:4px 10px;background:var(--tplane-chat-surface-alt);border:1px solid var(--tplane-chat-separator);border-radius:9999px;color:var(--tplane-chat-text-muted);font-size:var(--tplane-chat-font-size-xs);font-family:inherit;cursor:pointer;line-height:1.2}.chat-reasoning__header:hover{color:var(--tplane-chat-text)}.chat-reasoning__chevron{width:10px;height:10px;transition:transform .12s ease}:host([data-expanded=\"true\"]) .chat-reasoning__chevron{transform:rotate(90deg)}.chat-reasoning__pulse{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--tplane-chat-text-muted);animation:chat-reasoning-pulse 1.2s ease-in-out infinite}@keyframes chat-reasoning-pulse{0%,to{opacity:.3}50%{opacity:1}}.chat-reasoning__body{margin-top:.5rem;padding-left:12px;border-left:2px solid var(--tplane-chat-separator);color:var(--tplane-chat-text-muted)}.chat-reasoning__body chat-streaming-md{font-size:.95em}\n"] }]
|
|
3880
|
-
}], ctorParameters: () => [], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }],
|
|
4347
|
+
}], ctorParameters: () => [], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], delivery: [{ type: i0.Input, args: [{ isSignal: true, alias: "delivery", required: true }] }], durationMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "durationMs", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], defaultExpanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultExpanded", required: false }] }] } });
|
|
3881
4348
|
|
|
3882
4349
|
// libs/chat/src/lib/styles/chat-launcher-button.styles.ts
|
|
3883
4350
|
// SPDX-License-Identifier: MIT
|
|
@@ -5514,6 +5981,34 @@ function statusToTraceState(s) {
|
|
|
5514
5981
|
class ChatSubagentCardComponent {
|
|
5515
5982
|
subagent = input.required(...(ngDevMode ? [{ debugName: "subagent" }] : []));
|
|
5516
5983
|
state = computed(() => statusToTraceState(this.subagent().status()), ...(ngDevMode ? [{ debugName: "state" }] : []));
|
|
5984
|
+
markdownDocuments = new Map();
|
|
5985
|
+
constructor() {
|
|
5986
|
+
effect(() => {
|
|
5987
|
+
let liveIds;
|
|
5988
|
+
try {
|
|
5989
|
+
liveIds = new Set(this.subagent().messages().map((message) => message.id));
|
|
5990
|
+
}
|
|
5991
|
+
catch {
|
|
5992
|
+
return;
|
|
5993
|
+
}
|
|
5994
|
+
for (const id of [...this.markdownDocuments.keys()]) {
|
|
5995
|
+
if (!liveIds.has(id))
|
|
5996
|
+
this.markdownDocuments.delete(id);
|
|
5997
|
+
}
|
|
5998
|
+
});
|
|
5999
|
+
}
|
|
6000
|
+
markdownDocumentFor(content, message) {
|
|
6001
|
+
const prior = this.markdownDocuments.get(message.id);
|
|
6002
|
+
const delivery = message.delivery;
|
|
6003
|
+
if (prior?.generation === delivery.generation &&
|
|
6004
|
+
prior.phase === delivery.phase &&
|
|
6005
|
+
prior.content === content) {
|
|
6006
|
+
return prior;
|
|
6007
|
+
}
|
|
6008
|
+
const document = markdownDocument(content, delivery);
|
|
6009
|
+
this.markdownDocuments.set(message.id, document);
|
|
6010
|
+
return document;
|
|
6011
|
+
}
|
|
5517
6012
|
textOf(m) {
|
|
5518
6013
|
const c = m.content;
|
|
5519
6014
|
return typeof c === 'string' ? c : '';
|
|
@@ -5543,7 +6038,7 @@ class ChatSubagentCardComponent {
|
|
|
5543
6038
|
<div class="sac__reasoning">{{ m.reasoning }}</div>
|
|
5544
6039
|
}
|
|
5545
6040
|
@if (textOf(m); as t) {
|
|
5546
|
-
<chat-streaming-md [
|
|
6041
|
+
<chat-streaming-md [document]="markdownDocumentFor(t, m)" />
|
|
5547
6042
|
}
|
|
5548
6043
|
@for (tc of toolCallsFor(m); track tc.id) {
|
|
5549
6044
|
<chat-tool-call-card [toolCall]="toToolCallInfo(tc)" />
|
|
@@ -5551,7 +6046,7 @@ class ChatSubagentCardComponent {
|
|
|
5551
6046
|
</div>
|
|
5552
6047
|
}
|
|
5553
6048
|
</chat-trace>
|
|
5554
|
-
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block}.sac__name{color:var(--tplane-chat-text);font-weight:500;font-size:var(--tplane-chat-font-size-sm)}.sac__id{font-family:var(--tplane-chat-font-mono);font-size:var(--tplane-chat-font-size-xs);color:var(--tplane-chat-text-muted);margin-left:4px}.sac__pill{padding:1px 8px;border-radius:9999px;font-size:11px;font-weight:500;margin-left:4px}.sac__pill[data-status=pending]{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text-muted)}.sac__pill[data-status=running]{background:var(--tplane-chat-warning-bg);color:var(--tplane-chat-warning-text)}.sac__pill[data-status=complete]{color:var(--tplane-chat-success)}.sac__pill[data-status=error]{background:var(--tplane-chat-error-bg);color:var(--tplane-chat-error-text)}.sac__count{font-size:var(--tplane-chat-font-size-xs);color:var(--tplane-chat-text-muted)}.sac__msg{padding:6px 0}.sac__msg+.sac__msg{border-top:1px solid var(--tplane-chat-separator)}.sac__reasoning{font-size:var(--tplane-chat-font-size-xs);color:var(--tplane-chat-text-muted);font-style:italic;margin-bottom:4px}\n"], dependencies: [{ kind: "component", type: ChatTraceComponent, selector: "chat-trace", inputs: ["state", "defaultExpanded"] }, { kind: "component", type: ChatToolCallCardComponent, selector: "chat-tool-call-card", inputs: ["toolCall", "defaultCollapsed"] }, { kind: "component", type: ChatStreamingMdComponent, selector: "chat-streaming-md", inputs: ["
|
|
6049
|
+
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block}.sac__name{color:var(--tplane-chat-text);font-weight:500;font-size:var(--tplane-chat-font-size-sm)}.sac__id{font-family:var(--tplane-chat-font-mono);font-size:var(--tplane-chat-font-size-xs);color:var(--tplane-chat-text-muted);margin-left:4px}.sac__pill{padding:1px 8px;border-radius:9999px;font-size:11px;font-weight:500;margin-left:4px}.sac__pill[data-status=pending]{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text-muted)}.sac__pill[data-status=running]{background:var(--tplane-chat-warning-bg);color:var(--tplane-chat-warning-text)}.sac__pill[data-status=complete]{color:var(--tplane-chat-success)}.sac__pill[data-status=error]{background:var(--tplane-chat-error-bg);color:var(--tplane-chat-error-text)}.sac__count{font-size:var(--tplane-chat-font-size-xs);color:var(--tplane-chat-text-muted)}.sac__msg{padding:6px 0}.sac__msg+.sac__msg{border-top:1px solid var(--tplane-chat-separator)}.sac__reasoning{font-size:var(--tplane-chat-font-size-xs);color:var(--tplane-chat-text-muted);font-style:italic;margin-bottom:4px}\n"], dependencies: [{ kind: "component", type: ChatTraceComponent, selector: "chat-trace", inputs: ["state", "defaultExpanded"] }, { kind: "component", type: ChatToolCallCardComponent, selector: "chat-tool-call-card", inputs: ["toolCall", "defaultCollapsed"] }, { kind: "component", type: ChatStreamingMdComponent, selector: "chat-streaming-md", inputs: ["document", "viewRegistry"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5555
6050
|
}
|
|
5556
6051
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatSubagentCardComponent, decorators: [{
|
|
5557
6052
|
type: Component,
|
|
@@ -5569,7 +6064,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
5569
6064
|
<div class="sac__reasoning">{{ m.reasoning }}</div>
|
|
5570
6065
|
}
|
|
5571
6066
|
@if (textOf(m); as t) {
|
|
5572
|
-
<chat-streaming-md [
|
|
6067
|
+
<chat-streaming-md [document]="markdownDocumentFor(t, m)" />
|
|
5573
6068
|
}
|
|
5574
6069
|
@for (tc of toolCallsFor(m); track tc.id) {
|
|
5575
6070
|
<chat-tool-call-card [toolCall]="toToolCallInfo(tc)" />
|
|
@@ -5578,7 +6073,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
5578
6073
|
}
|
|
5579
6074
|
</chat-trace>
|
|
5580
6075
|
`, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block}.sac__name{color:var(--tplane-chat-text);font-weight:500;font-size:var(--tplane-chat-font-size-sm)}.sac__id{font-family:var(--tplane-chat-font-mono);font-size:var(--tplane-chat-font-size-xs);color:var(--tplane-chat-text-muted);margin-left:4px}.sac__pill{padding:1px 8px;border-radius:9999px;font-size:11px;font-weight:500;margin-left:4px}.sac__pill[data-status=pending]{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text-muted)}.sac__pill[data-status=running]{background:var(--tplane-chat-warning-bg);color:var(--tplane-chat-warning-text)}.sac__pill[data-status=complete]{color:var(--tplane-chat-success)}.sac__pill[data-status=error]{background:var(--tplane-chat-error-bg);color:var(--tplane-chat-error-text)}.sac__count{font-size:var(--tplane-chat-font-size-xs);color:var(--tplane-chat-text-muted)}.sac__msg{padding:6px 0}.sac__msg+.sac__msg{border-top:1px solid var(--tplane-chat-separator)}.sac__reasoning{font-size:var(--tplane-chat-font-size-xs);color:var(--tplane-chat-text-muted);font-style:italic;margin-bottom:4px}\n"] }]
|
|
5581
|
-
}], propDecorators: { subagent: [{ type: i0.Input, args: [{ isSignal: true, alias: "subagent", required: true }] }] } });
|
|
6076
|
+
}], ctorParameters: () => [], propDecorators: { subagent: [{ type: i0.Input, args: [{ isSignal: true, alias: "subagent", required: true }] }] } });
|
|
5582
6077
|
|
|
5583
6078
|
// libs/chat/src/lib/primitives/chat-tool-calls/chat-tool-call-template.directive.ts
|
|
5584
6079
|
// SPDX-License-Identifier: MIT
|
|
@@ -6064,11 +6559,23 @@ function toToolViewSpec(tc) {
|
|
|
6064
6559
|
elements: {
|
|
6065
6560
|
[tc.name]: {
|
|
6066
6561
|
type: tc.name,
|
|
6067
|
-
props: { ...args, ...result, status: tc.status },
|
|
6562
|
+
props: { ...args, ...result, status: tc.status, clientTool: toClientToolLifecycle(tc) },
|
|
6068
6563
|
},
|
|
6069
6564
|
},
|
|
6070
6565
|
};
|
|
6071
6566
|
}
|
|
6567
|
+
function toClientToolLifecycle(tc) {
|
|
6568
|
+
const hasResult = tc.result !== undefined;
|
|
6569
|
+
return {
|
|
6570
|
+
id: tc.id,
|
|
6571
|
+
name: tc.name,
|
|
6572
|
+
status: tc.status,
|
|
6573
|
+
phase: tc.status === 'error' ? 'error' : tc.status === 'complete' ? 'complete' : 'running',
|
|
6574
|
+
hasResult,
|
|
6575
|
+
...(hasResult ? { result: tc.result } : {}),
|
|
6576
|
+
...(tc.error !== undefined ? { error: tc.error } : {}),
|
|
6577
|
+
};
|
|
6578
|
+
}
|
|
6072
6579
|
function isRecord$2(v) {
|
|
6073
6580
|
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
6074
6581
|
}
|
|
@@ -8114,6 +8621,7 @@ function deriveJsonSchema(toolName, schema) {
|
|
|
8114
8621
|
}
|
|
8115
8622
|
}
|
|
8116
8623
|
|
|
8624
|
+
const defaultSignal = new AbortController().signal;
|
|
8117
8625
|
/** Validate raw model args against a Standard Schema. */
|
|
8118
8626
|
async function validateArgs(schema, args) {
|
|
8119
8627
|
const res = await schema['~standard'].validate(args);
|
|
@@ -8126,12 +8634,12 @@ async function validateArgs(schema, args) {
|
|
|
8126
8634
|
return { ok: true, value: res.value };
|
|
8127
8635
|
}
|
|
8128
8636
|
/** Validate args, run the handler, and normalize the outcome to a ClientToolResult. */
|
|
8129
|
-
async function executeFunctionTool(def, rawArgs) {
|
|
8637
|
+
async function executeFunctionTool(def, rawArgs, context = { signal: defaultSignal }) {
|
|
8130
8638
|
const v = await validateArgs(def.schema, rawArgs);
|
|
8131
8639
|
if (!v.ok)
|
|
8132
8640
|
return { ok: false, error: `invalid arguments: ${v.error}` };
|
|
8133
8641
|
try {
|
|
8134
|
-
const value = await def.handler(v.value);
|
|
8642
|
+
const value = await def.handler(v.value, context);
|
|
8135
8643
|
return { ok: true, value };
|
|
8136
8644
|
}
|
|
8137
8645
|
catch (err) {
|
|
@@ -8139,18 +8647,102 @@ async function executeFunctionTool(def, rawArgs) {
|
|
|
8139
8647
|
}
|
|
8140
8648
|
}
|
|
8141
8649
|
|
|
8650
|
+
/** Return whether this function tool should claim before browser execution. */
|
|
8651
|
+
function shouldClaimBeforeExecute(def) {
|
|
8652
|
+
return def.idempotent !== true;
|
|
8653
|
+
}
|
|
8654
|
+
/** Default fail-closed result for a stale in-progress client-tool execution. */
|
|
8655
|
+
function defaultInterruptedClientToolResult(toolCallId) {
|
|
8656
|
+
return {
|
|
8657
|
+
ok: false,
|
|
8658
|
+
error: `client tool execution interrupted before completion: ${toolCallId}`,
|
|
8659
|
+
};
|
|
8660
|
+
}
|
|
8661
|
+
/** Result recorded when the user stops a run while a client tool is running. */
|
|
8662
|
+
function cancelledClientToolResult(toolCallId) {
|
|
8663
|
+
return {
|
|
8664
|
+
ok: false,
|
|
8665
|
+
error: `client tool execution cancelled before completion: ${toolCallId}`,
|
|
8666
|
+
};
|
|
8667
|
+
}
|
|
8668
|
+
/** Default fail-closed result when the execution guard itself cannot be reached. */
|
|
8669
|
+
function clientToolGuardFailureResult(toolCallId, error) {
|
|
8670
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
8671
|
+
return {
|
|
8672
|
+
ok: false,
|
|
8673
|
+
error: `client tool execution guard failed for ${toolCallId}: ${message}`,
|
|
8674
|
+
};
|
|
8675
|
+
}
|
|
8676
|
+
|
|
8142
8677
|
// SPDX-License-Identifier: MIT
|
|
8678
|
+
/** Agents whose stop() this module has already wrapped. */
|
|
8679
|
+
const patchedAgents = new WeakMap();
|
|
8143
8680
|
/**
|
|
8144
8681
|
* Watches the agent's pending client tool calls and auto-runs FUNCTION tools,
|
|
8145
8682
|
* resolving each with its result. View/ask (component) tools are handled by the
|
|
8146
8683
|
* rendering layer, not here. No-op if the agent lacks the clientTools
|
|
8147
8684
|
* capability. MUST be called in an injection context (sets up an effect).
|
|
8148
8685
|
*/
|
|
8149
|
-
function startClientToolExecutor(agent, registry) {
|
|
8686
|
+
function startClientToolExecutor(agent, registry, options = {}) {
|
|
8150
8687
|
const cap = agent.clientTools;
|
|
8151
8688
|
if (!cap)
|
|
8152
8689
|
return;
|
|
8153
|
-
const
|
|
8690
|
+
const destroyRef = inject(DestroyRef);
|
|
8691
|
+
const inFlight = new Map();
|
|
8692
|
+
const abortAll = () => {
|
|
8693
|
+
for (const controller of inFlight.values()) {
|
|
8694
|
+
controller.abort();
|
|
8695
|
+
}
|
|
8696
|
+
};
|
|
8697
|
+
// The stop button lives in chat-input, which has no coordinator reference, so
|
|
8698
|
+
// wrapping agent.stop is the only interception seam. Wrap at most once per
|
|
8699
|
+
// agent, fan the stop out to EVERY live executor, and restore the original
|
|
8700
|
+
// once the last one is destroyed — agents often outlive the components that
|
|
8701
|
+
// start executors, so an unbounded stack of wrappers would leak.
|
|
8702
|
+
let patch = patchedAgents.get(agent);
|
|
8703
|
+
if (!patch) {
|
|
8704
|
+
const originalStop = agent.stop;
|
|
8705
|
+
const boundStop = originalStop.bind(agent);
|
|
8706
|
+
const aborts = new Set();
|
|
8707
|
+
const wrapper = async () => {
|
|
8708
|
+
for (const abort of aborts)
|
|
8709
|
+
abort();
|
|
8710
|
+
await boundStop();
|
|
8711
|
+
};
|
|
8712
|
+
patch = { aborts, originalStop, wrapper };
|
|
8713
|
+
patchedAgents.set(agent, patch);
|
|
8714
|
+
agent.stop = wrapper;
|
|
8715
|
+
}
|
|
8716
|
+
const registration = patch;
|
|
8717
|
+
registration.aborts.add(abortAll);
|
|
8718
|
+
destroyRef.onDestroy(() => {
|
|
8719
|
+
registration.aborts.delete(abortAll);
|
|
8720
|
+
if (registration.aborts.size === 0 && patchedAgents.get(agent) === registration) {
|
|
8721
|
+
// Only un-patch if OUR wrapper is still installed; something else may
|
|
8722
|
+
// have replaced agent.stop since, and clobbering it would be worse.
|
|
8723
|
+
if (agent.stop === registration.wrapper)
|
|
8724
|
+
agent.stop = registration.originalStop;
|
|
8725
|
+
patchedAgents.delete(agent);
|
|
8726
|
+
}
|
|
8727
|
+
});
|
|
8728
|
+
destroyRef.onDestroy(abortAll);
|
|
8729
|
+
const settleToolCall = options.settleToolCall ?? ((toolCall, result) => cap.resolve(toolCall.id, result));
|
|
8730
|
+
// `resolve()` contractually means "record AND continue" — both adapters
|
|
8731
|
+
// submit a new run from it. A cancelled call must therefore NEVER go through
|
|
8732
|
+
// it, or clicking Stop would immediately start another run and the model
|
|
8733
|
+
// could re-call the very tool it was stopped on. settle() + flush() is the
|
|
8734
|
+
// durable, run-free equivalent. If the capability has no settle(), we leave
|
|
8735
|
+
// the call dangling on purpose: a dangling tool call is repaired on the next
|
|
8736
|
+
// user turn, whereas resurrecting a stopped run is not repairable at all.
|
|
8737
|
+
const settleWithoutContinuing = options.settleWithoutContinuing ??
|
|
8738
|
+
((toolCall, result) => {
|
|
8739
|
+
if (!cap.settle) {
|
|
8740
|
+
console.warn(`Client tool "${toolCall.name}" was cancelled but the agent capability does not implement settle(); the result cannot be recorded without starting a run.`);
|
|
8741
|
+
return;
|
|
8742
|
+
}
|
|
8743
|
+
cap.settle(toolCall.id, result);
|
|
8744
|
+
void Promise.resolve(cap.flush?.()).catch(() => undefined);
|
|
8745
|
+
});
|
|
8154
8746
|
effect(() => {
|
|
8155
8747
|
for (const tc of cap.pending()) {
|
|
8156
8748
|
const def = registry[tc.name];
|
|
@@ -8163,16 +8755,148 @@ function startClientToolExecutor(agent, registry) {
|
|
|
8163
8755
|
// double-dispatch within a render cycle.
|
|
8164
8756
|
if (inFlight.has(tc.id))
|
|
8165
8757
|
continue;
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8758
|
+
if (options.shouldExecuteToolCall && !options.shouldExecuteToolCall(tc))
|
|
8759
|
+
continue;
|
|
8760
|
+
const controller = new AbortController();
|
|
8761
|
+
inFlight.set(tc.id, controller);
|
|
8762
|
+
void runFunctionTool({
|
|
8763
|
+
def,
|
|
8764
|
+
toolCall: tc,
|
|
8765
|
+
rawArgs: tc.args,
|
|
8766
|
+
toolCallId: tc.id,
|
|
8767
|
+
controller,
|
|
8768
|
+
executionGuard: options.executionGuard,
|
|
8769
|
+
settleToolCall,
|
|
8770
|
+
settleWithoutContinuing,
|
|
8771
|
+
}).finally(() => {
|
|
8169
8772
|
inFlight.delete(tc.id);
|
|
8170
8773
|
});
|
|
8171
8774
|
}
|
|
8172
8775
|
});
|
|
8173
8776
|
}
|
|
8777
|
+
/**
|
|
8778
|
+
* Settle the moment the signal fires instead of waiting for the handler.
|
|
8779
|
+
*
|
|
8780
|
+
* Honoring `context.signal` is opt-in, and most handlers ignore it, so awaiting
|
|
8781
|
+
* the handler would leave a stopped call unsettled — dangling on the server
|
|
8782
|
+
* thread and pinned in `inFlight` — until it happens to finish, or forever. The
|
|
8783
|
+
* handler's late real result is then discarded: the id is already settled and
|
|
8784
|
+
* in the adapter's `resolvedIds`, so it can neither double-settle nor
|
|
8785
|
+
* re-dispatch. `executeFunctionTool` normalizes throws, so the losing promise
|
|
8786
|
+
* never rejects.
|
|
8787
|
+
*/
|
|
8788
|
+
async function raceAbort(execution, signal) {
|
|
8789
|
+
if (signal.aborted)
|
|
8790
|
+
return { aborted: true };
|
|
8791
|
+
let onAbort = () => undefined;
|
|
8792
|
+
const aborted = new Promise((resolve) => {
|
|
8793
|
+
onAbort = () => resolve({ aborted: true });
|
|
8794
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
8795
|
+
});
|
|
8796
|
+
try {
|
|
8797
|
+
return await Promise.race([
|
|
8798
|
+
execution.then((result) => ({ aborted: signal.aborted, result })),
|
|
8799
|
+
aborted,
|
|
8800
|
+
]);
|
|
8801
|
+
}
|
|
8802
|
+
finally {
|
|
8803
|
+
signal.removeEventListener('abort', onAbort);
|
|
8804
|
+
}
|
|
8805
|
+
}
|
|
8806
|
+
async function runFunctionTool(input) {
|
|
8807
|
+
const { def, toolCall, rawArgs, toolCallId, controller, executionGuard, settleToolCall, settleWithoutContinuing, } = input;
|
|
8808
|
+
const signal = controller.signal;
|
|
8809
|
+
// An aborted call MUST still settle: leaving it unsettled keeps it out of
|
|
8810
|
+
// `resolvedIds`, so it stays pending and is re-dispatched after the next run
|
|
8811
|
+
// (re-running a side-effecting handler the user explicitly stopped) and
|
|
8812
|
+
// leaves the server thread holding a tool call with no tool result. It must
|
|
8813
|
+
// settle through the NON-continuing channel — see `settleWithoutContinuing`.
|
|
8814
|
+
let settled = false;
|
|
8815
|
+
/** Settle and continue the run. Only for outcomes the user did not cancel. */
|
|
8816
|
+
const settleAndContinue = (result) => {
|
|
8817
|
+
if (settled)
|
|
8818
|
+
return;
|
|
8819
|
+
settled = true;
|
|
8820
|
+
settleToolCall(toolCall, result);
|
|
8821
|
+
};
|
|
8822
|
+
/** Settle without continuing the run. Abort and teardown paths only. */
|
|
8823
|
+
const settleCancelled = (result = cancelledClientToolResult(toolCallId)) => {
|
|
8824
|
+
if (settled)
|
|
8825
|
+
return;
|
|
8826
|
+
settled = true;
|
|
8827
|
+
settleWithoutContinuing(toolCall, result);
|
|
8828
|
+
};
|
|
8829
|
+
if (!executionGuard || !shouldClaimBeforeExecute(def)) {
|
|
8830
|
+
const outcome = await raceAbort(executeFunctionTool(def, rawArgs, { signal }), signal);
|
|
8831
|
+
if (outcome.aborted)
|
|
8832
|
+
settleCancelled();
|
|
8833
|
+
else
|
|
8834
|
+
settleAndContinue(outcome.result);
|
|
8835
|
+
return;
|
|
8836
|
+
}
|
|
8837
|
+
const key = { threadId: executionGuard.threadId, toolCallId };
|
|
8838
|
+
let claim;
|
|
8839
|
+
try {
|
|
8840
|
+
claim = await executionGuard.store.claim(key);
|
|
8841
|
+
}
|
|
8842
|
+
catch (err) {
|
|
8843
|
+
// A claim that rejects after the user stopped must still settle, but must
|
|
8844
|
+
// never continue the run.
|
|
8845
|
+
if (signal.aborted)
|
|
8846
|
+
settleCancelled();
|
|
8847
|
+
else
|
|
8848
|
+
settleAndContinue(clientToolGuardFailureResult(toolCallId, err));
|
|
8849
|
+
return;
|
|
8850
|
+
}
|
|
8851
|
+
if (signal.aborted) {
|
|
8852
|
+
// Aborted while the claim RPC was in flight. If the claim succeeded, the
|
|
8853
|
+
// durable row is now `executing`; record the cancelled result or it stays
|
|
8854
|
+
// that way forever and a later reload fails closed as "interrupted".
|
|
8855
|
+
if (claim === 'claimed') {
|
|
8856
|
+
await recordThenSettle(executionGuard, key, cancelledClientToolResult(toolCallId), toolCallId, settleCancelled);
|
|
8857
|
+
}
|
|
8858
|
+
else {
|
|
8859
|
+
settleCancelled();
|
|
8860
|
+
}
|
|
8861
|
+
return;
|
|
8862
|
+
}
|
|
8863
|
+
if (claim === 'claimed') {
|
|
8864
|
+
const outcome = await raceAbort(executeFunctionTool(def, rawArgs, { signal }), signal);
|
|
8865
|
+
const result = outcome.aborted
|
|
8866
|
+
? cancelledClientToolResult(toolCallId)
|
|
8867
|
+
: outcome.result;
|
|
8868
|
+
await recordThenSettle(executionGuard, key, result, toolCallId, outcome.aborted ? settleCancelled : settleAndContinue);
|
|
8869
|
+
return;
|
|
8870
|
+
}
|
|
8871
|
+
if (claim.status === 'done') {
|
|
8872
|
+
settleAndContinue(claim.result);
|
|
8873
|
+
return;
|
|
8874
|
+
}
|
|
8875
|
+
const result = claim.status === 'failed' && claim.result
|
|
8876
|
+
? claim.result
|
|
8877
|
+
: defaultInterruptedClientToolResult(toolCallId);
|
|
8878
|
+
await recordThenSettle(executionGuard, key, result, toolCallId, settleAndContinue);
|
|
8879
|
+
}
|
|
8880
|
+
/**
|
|
8881
|
+
* Record the final result then settle through `settle`. Deliberately
|
|
8882
|
+
* abort-agnostic: an aborted execution must still write its (cancelled) result,
|
|
8883
|
+
* otherwise the guard store stays at `executing` forever and a later reload
|
|
8884
|
+
* fails closed with a misleading "interrupted" message. The caller picks the
|
|
8885
|
+
* settlement channel, so a cancelled result never continues the run.
|
|
8886
|
+
*/
|
|
8887
|
+
async function recordThenSettle(executionGuard, key, result, toolCallId, settle) {
|
|
8888
|
+
try {
|
|
8889
|
+
await executionGuard.store.record(key, result);
|
|
8890
|
+
}
|
|
8891
|
+
catch (err) {
|
|
8892
|
+
settle(clientToolGuardFailureResult(toolCallId, err));
|
|
8893
|
+
return;
|
|
8894
|
+
}
|
|
8895
|
+
settle(result);
|
|
8896
|
+
}
|
|
8174
8897
|
|
|
8175
8898
|
// SPDX-License-Identifier: MIT
|
|
8899
|
+
const DEFAULT_MAX_CONTINUATION_TURNS = 10;
|
|
8176
8900
|
/** Build the catalog spec list shipped to the model. */
|
|
8177
8901
|
function toClientToolSpecs(registry) {
|
|
8178
8902
|
return Object.entries(registry).map(([name, def]) => ({
|
|
@@ -8194,9 +8918,140 @@ function viewComponents(registry) {
|
|
|
8194
8918
|
}
|
|
8195
8919
|
return out;
|
|
8196
8920
|
}
|
|
8197
|
-
function createClientToolsCoordinator(registry) {
|
|
8921
|
+
function createClientToolsCoordinator(registry, options = {}) {
|
|
8198
8922
|
const viewRegistry = views(viewComponents(registry));
|
|
8199
8923
|
const ackedViews = new Set();
|
|
8924
|
+
let currentGroup;
|
|
8925
|
+
let currentUserTurnKey = '';
|
|
8926
|
+
let continuationTurns = 0;
|
|
8927
|
+
function toolWantsFollowUp(tc) {
|
|
8928
|
+
return registry[tc.name]?.followUp !== false;
|
|
8929
|
+
}
|
|
8930
|
+
function latestUserTurnKey(agent) {
|
|
8931
|
+
const messages = agent.messages();
|
|
8932
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
8933
|
+
const msg = messages[i];
|
|
8934
|
+
if (msg.role === 'user' || msg.role === 'human')
|
|
8935
|
+
return msg.id ?? `index:${i}`;
|
|
8936
|
+
}
|
|
8937
|
+
return 'no-user-turn';
|
|
8938
|
+
}
|
|
8939
|
+
function continuationLimit(calls) {
|
|
8940
|
+
const maxTurns = options.continuationPolicy?.maxTurns ?? DEFAULT_MAX_CONTINUATION_TURNS;
|
|
8941
|
+
if (maxTurns === 0)
|
|
8942
|
+
return undefined;
|
|
8943
|
+
const attemptedTurn = continuationTurns + 1;
|
|
8944
|
+
if (attemptedTurn <= maxTurns) {
|
|
8945
|
+
continuationTurns = attemptedTurn;
|
|
8946
|
+
return undefined;
|
|
8947
|
+
}
|
|
8948
|
+
return {
|
|
8949
|
+
maxTurns,
|
|
8950
|
+
attemptedTurn,
|
|
8951
|
+
toolCallIds: calls.map((tc) => tc.id),
|
|
8952
|
+
toolNames: calls.map((tc) => tc.name),
|
|
8953
|
+
};
|
|
8954
|
+
}
|
|
8955
|
+
function emitContinuationLimit(event) {
|
|
8956
|
+
console.error(`Client tool continuation stopped after ${event.maxTurns} turn(s); pending tool calls: ${event.toolCallIds.join(', ')}`);
|
|
8957
|
+
options.continuationPolicy?.onLimit?.(event);
|
|
8958
|
+
}
|
|
8959
|
+
function createGroup(agent, calls) {
|
|
8960
|
+
const userTurnKey = latestUserTurnKey(agent);
|
|
8961
|
+
if (userTurnKey !== currentUserTurnKey) {
|
|
8962
|
+
currentUserTurnKey = userTurnKey;
|
|
8963
|
+
continuationTurns = 0;
|
|
8964
|
+
}
|
|
8965
|
+
const limit = continuationLimit(calls);
|
|
8966
|
+
if (limit)
|
|
8967
|
+
emitContinuationLimit(limit);
|
|
8968
|
+
return {
|
|
8969
|
+
ids: new Set(calls.map((tc) => tc.id)),
|
|
8970
|
+
hasFollowUp: calls.some(toolWantsFollowUp),
|
|
8971
|
+
settledIds: new Set(),
|
|
8972
|
+
allowed: !limit,
|
|
8973
|
+
};
|
|
8974
|
+
}
|
|
8975
|
+
function groupFor(agent, cap, tc) {
|
|
8976
|
+
if (currentGroup?.ids.has(tc.id))
|
|
8977
|
+
return currentGroup;
|
|
8978
|
+
const pending = cap.pending();
|
|
8979
|
+
const calls = pending.some((pendingCall) => pendingCall.id === tc.id)
|
|
8980
|
+
? pending
|
|
8981
|
+
: [tc];
|
|
8982
|
+
currentGroup = createGroup(agent, calls);
|
|
8983
|
+
return currentGroup;
|
|
8984
|
+
}
|
|
8985
|
+
function shouldHandleClientToolCall(agent, cap, tc) {
|
|
8986
|
+
return groupFor(agent, cap, tc).allowed;
|
|
8987
|
+
}
|
|
8988
|
+
function warnMissingSettle(tc) {
|
|
8989
|
+
console.warn(`Client tool "${tc.name}" requested batched or terminal settlement, but the agent capability does not implement settle(); falling back to resolve().`);
|
|
8990
|
+
}
|
|
8991
|
+
/** No settle() and the run must not continue — the result cannot be recorded. */
|
|
8992
|
+
function warnUnrecordableWithoutSettle(tc) {
|
|
8993
|
+
console.warn(`Client tool "${tc.name}" must not continue the run, but the agent capability does not implement settle(); the result cannot be recorded without starting a run.`);
|
|
8994
|
+
}
|
|
8995
|
+
function flushSettledResults(cap) {
|
|
8996
|
+
if (!cap.flush) {
|
|
8997
|
+
console.warn('Client tool results were settled with no follow-up run, but the agent capability does not implement flush(); results may not reach the server.');
|
|
8998
|
+
return;
|
|
8999
|
+
}
|
|
9000
|
+
void Promise.resolve(cap.flush()).catch((err) => {
|
|
9001
|
+
console.error('Client tool flush failed', err);
|
|
9002
|
+
});
|
|
9003
|
+
}
|
|
9004
|
+
function settleClientToolCall(cap, agent, tc, result, mayContinue = true) {
|
|
9005
|
+
const group = groupFor(agent, cap, tc);
|
|
9006
|
+
if (group.settledIds.has(tc.id))
|
|
9007
|
+
return;
|
|
9008
|
+
group.settledIds.add(tc.id);
|
|
9009
|
+
const groupComplete = Array.from(group.ids).every((id) => group.settledIds.has(id));
|
|
9010
|
+
// Over the continuation limit, or cancelled by the user (stop / teardown):
|
|
9011
|
+
// still record the result so the server never keeps an unanswered tool
|
|
9012
|
+
// call, but never continue the run — `resolve()` submits a new run, which
|
|
9013
|
+
// for a cancelled call would undo the very stop the user asked for.
|
|
9014
|
+
if (!group.allowed || !mayContinue) {
|
|
9015
|
+
if (!cap.settle) {
|
|
9016
|
+
warnUnrecordableWithoutSettle(tc);
|
|
9017
|
+
return;
|
|
9018
|
+
}
|
|
9019
|
+
cap.settle(tc.id, result);
|
|
9020
|
+
// Flush ONCE, when the last call in the group settles. Adapters coalesce
|
|
9021
|
+
// concurrent flushes (returning the in-flight promise), so flushing per
|
|
9022
|
+
// call would strand every batch after the first.
|
|
9023
|
+
if (groupComplete) {
|
|
9024
|
+
flushSettledResults(cap);
|
|
9025
|
+
// A limit-blocked group must stay `currentGroup` so repeated effect
|
|
9026
|
+
// passes over the same never-executed calls keep short-circuiting on
|
|
9027
|
+
// `settledIds`. Cancelled calls leave `pending()` once settled, so
|
|
9028
|
+
// their group can be retired normally.
|
|
9029
|
+
if (group.allowed)
|
|
9030
|
+
currentGroup = undefined;
|
|
9031
|
+
}
|
|
9032
|
+
return;
|
|
9033
|
+
}
|
|
9034
|
+
if (!cap.settle) {
|
|
9035
|
+
if (group.ids.size > 1 || registry[tc.name]?.followUp === false)
|
|
9036
|
+
warnMissingSettle(tc);
|
|
9037
|
+
cap.resolve(tc.id, result);
|
|
9038
|
+
if (groupComplete)
|
|
9039
|
+
currentGroup = undefined;
|
|
9040
|
+
return;
|
|
9041
|
+
}
|
|
9042
|
+
if (groupComplete && group.hasFollowUp) {
|
|
9043
|
+
cap.resolve(tc.id, result);
|
|
9044
|
+
currentGroup = undefined;
|
|
9045
|
+
return;
|
|
9046
|
+
}
|
|
9047
|
+
cap.settle(tc.id, result);
|
|
9048
|
+
if (groupComplete) {
|
|
9049
|
+
// Terminal group: nothing will continue the run, so make the settled
|
|
9050
|
+
// results durable ourselves or the server keeps an unanswered tool call.
|
|
9051
|
+
flushSettledResults(cap);
|
|
9052
|
+
currentGroup = undefined;
|
|
9053
|
+
}
|
|
9054
|
+
}
|
|
8200
9055
|
return {
|
|
8201
9056
|
viewRegistry,
|
|
8202
9057
|
connect(agent) {
|
|
@@ -8204,7 +9059,24 @@ function createClientToolsCoordinator(registry) {
|
|
|
8204
9059
|
if (!cap)
|
|
8205
9060
|
return;
|
|
8206
9061
|
cap.setCatalog(toClientToolSpecs(registry));
|
|
8207
|
-
startClientToolExecutor(agent, registry
|
|
9062
|
+
startClientToolExecutor(agent, registry, {
|
|
9063
|
+
executionGuard: options.executionGuard,
|
|
9064
|
+
shouldExecuteToolCall: (tc) => {
|
|
9065
|
+
if (shouldHandleClientToolCall(agent, cap, tc))
|
|
9066
|
+
return true;
|
|
9067
|
+
// Blocked before executing: record why, so the model sees a reason
|
|
9068
|
+
// instead of an unanswered tool call.
|
|
9069
|
+
settleClientToolCall(cap, agent, tc, {
|
|
9070
|
+
ok: false,
|
|
9071
|
+
error: `client tool continuation limit reached; ${tc.name} was not executed`,
|
|
9072
|
+
});
|
|
9073
|
+
return false;
|
|
9074
|
+
},
|
|
9075
|
+
settleToolCall: (tc, result) => settleClientToolCall(cap, agent, tc, result),
|
|
9076
|
+
// Cancelled calls reuse the same group bookkeeping (so the flush-once-
|
|
9077
|
+
// per-group property holds) but are forced down the settle+flush path.
|
|
9078
|
+
settleWithoutContinuing: (tc, result) => settleClientToolCall(cap, agent, tc, result, false),
|
|
9079
|
+
}); // function tools
|
|
8208
9080
|
// Auto-ack `view` tools: they render but produce no user value.
|
|
8209
9081
|
effect(() => {
|
|
8210
9082
|
for (const tc of cap.pending()) {
|
|
@@ -8214,7 +9086,7 @@ function createClientToolsCoordinator(registry) {
|
|
|
8214
9086
|
if (ackedViews.has(tc.id))
|
|
8215
9087
|
continue;
|
|
8216
9088
|
ackedViews.add(tc.id);
|
|
8217
|
-
cap
|
|
9089
|
+
settleClientToolCall(cap, agent, tc, { ok: true, value: { shown: true } });
|
|
8218
9090
|
}
|
|
8219
9091
|
});
|
|
8220
9092
|
},
|
|
@@ -8229,7 +9101,7 @@ function createClientToolsCoordinator(registry) {
|
|
|
8229
9101
|
const name = event.elementKey;
|
|
8230
9102
|
const pending = cap.pending().find((tc) => tc.name === name && registry[tc.name]?.kind === 'ask');
|
|
8231
9103
|
if (pending)
|
|
8232
|
-
cap
|
|
9104
|
+
settleClientToolCall(cap, agent, pending, { ok: true, value: event.value });
|
|
8233
9105
|
},
|
|
8234
9106
|
};
|
|
8235
9107
|
}
|
|
@@ -9823,6 +10695,8 @@ class ChatComponent {
|
|
|
9823
10695
|
'generate_json_render_spec',
|
|
9824
10696
|
'render_spec',
|
|
9825
10697
|
], ...(ngDevMode ? [{ debugName: "genuiToolNames" }] : []));
|
|
10698
|
+
clientToolExecutionGuard = input(undefined, ...(ngDevMode ? [{ debugName: "clientToolExecutionGuard" }] : []));
|
|
10699
|
+
clientToolContinuationPolicy = input(undefined, ...(ngDevMode ? [{ debugName: "clientToolContinuationPolicy" }] : []));
|
|
9826
10700
|
showWelcome = computed(() => {
|
|
9827
10701
|
if (this.welcomeDisabled())
|
|
9828
10702
|
return false;
|
|
@@ -9833,6 +10707,7 @@ class ChatComponent {
|
|
|
9833
10707
|
}, ...(ngDevMode ? [{ debugName: "showWelcome" }] : []));
|
|
9834
10708
|
threadSelected = output();
|
|
9835
10709
|
renderEvent = output();
|
|
10710
|
+
clientToolContinuationLimit = output();
|
|
9836
10711
|
/** Emitted when the user clicks the regenerate button on an assistant message. */
|
|
9837
10712
|
regenerate = output();
|
|
9838
10713
|
/** Emitted when the user rates an assistant message. */
|
|
@@ -9858,7 +10733,17 @@ class ChatComponent {
|
|
|
9858
10733
|
*/
|
|
9859
10734
|
coordinator = computed(() => {
|
|
9860
10735
|
const reg = this.clientTools();
|
|
9861
|
-
|
|
10736
|
+
const policy = this.clientToolContinuationPolicy();
|
|
10737
|
+
return reg ? createClientToolsCoordinator(reg, {
|
|
10738
|
+
executionGuard: this.clientToolExecutionGuard(),
|
|
10739
|
+
continuationPolicy: {
|
|
10740
|
+
...policy,
|
|
10741
|
+
onLimit: (event) => {
|
|
10742
|
+
policy?.onLimit?.(event);
|
|
10743
|
+
this.clientToolContinuationLimit.emit(event);
|
|
10744
|
+
},
|
|
10745
|
+
},
|
|
10746
|
+
}) : undefined;
|
|
9862
10747
|
}, ...(ngDevMode ? [{ debugName: "coordinator" }] : []));
|
|
9863
10748
|
/**
|
|
9864
10749
|
* The view registry actually used for rendering tool-views and for
|
|
@@ -9911,22 +10796,6 @@ class ChatComponent {
|
|
|
9911
10796
|
const raw = messageContent(message);
|
|
9912
10797
|
return a2uiActionLabel(raw) ?? raw;
|
|
9913
10798
|
}
|
|
9914
|
-
/**
|
|
9915
|
-
* True while a message's reasoning is mid-stream — i.e. it's the latest
|
|
9916
|
-
* message, the agent is loading, the message has reasoning content, and
|
|
9917
|
-
* no response text has arrived yet. Once the response text begins, the
|
|
9918
|
-
* reasoning pill collapses (per its internal logic).
|
|
9919
|
-
*/
|
|
9920
|
-
isReasoningStreaming(message, index) {
|
|
9921
|
-
const agent = this.agent();
|
|
9922
|
-
const isTail = index === agent.messages().length - 1;
|
|
9923
|
-
if (!isTail || !agent.isLoading())
|
|
9924
|
-
return false;
|
|
9925
|
-
if (!message.reasoning || message.reasoning.length === 0)
|
|
9926
|
-
return false;
|
|
9927
|
-
const text = typeof message.content === 'string' ? message.content : '';
|
|
9928
|
-
return text.length === 0;
|
|
9929
|
-
}
|
|
9930
10799
|
/** The nearest preceding assistant message (skipping hidden tool messages), or undefined. */
|
|
9931
10800
|
prevAssistant(msgs, index) {
|
|
9932
10801
|
for (let j = index - 1; j >= 0; j--) {
|
|
@@ -9949,9 +10818,10 @@ class ChatComponent {
|
|
|
9949
10818
|
}
|
|
9950
10819
|
/**
|
|
9951
10820
|
* Aggregate the reasoning RUN starting at `index`: joins each step's
|
|
9952
|
-
* reasoning, sums durations, counts steps, and
|
|
9953
|
-
*
|
|
9954
|
-
*
|
|
10821
|
+
* reasoning, sums durations, counts steps, and returns the last step's
|
|
10822
|
+
* delivery because that step owns the current aggregate snapshot. Also
|
|
10823
|
+
* computes the merged label when N > 1 ("Thought for {total} · {N} steps",
|
|
10824
|
+
* or just "{N} steps" when no step reported timing).
|
|
9955
10825
|
*/
|
|
9956
10826
|
reasoningRun(index) {
|
|
9957
10827
|
const msgs = this.agent().messages();
|
|
@@ -9961,18 +10831,18 @@ class ChatComponent {
|
|
|
9961
10831
|
if (m.role === 'tool')
|
|
9962
10832
|
continue; // skip hidden tool messages
|
|
9963
10833
|
if (m.role === 'assistant' && m.reasoning) {
|
|
9964
|
-
steps.push(
|
|
10834
|
+
steps.push(m);
|
|
9965
10835
|
continue;
|
|
9966
10836
|
}
|
|
9967
10837
|
break; // any other message ends the run
|
|
9968
10838
|
}
|
|
9969
|
-
const content = steps.map((
|
|
10839
|
+
const content = steps.map((step) => step.reasoning ?? '').filter(Boolean).join('\n\n');
|
|
9970
10840
|
const durations = steps
|
|
9971
|
-
.map((
|
|
10841
|
+
.map((step) => step.reasoningDurationMs)
|
|
9972
10842
|
.filter((d) => typeof d === 'number');
|
|
9973
10843
|
const durationMs = durations.length ? durations.reduce((a, b) => a + b, 0) : undefined;
|
|
9974
10844
|
const last = steps[steps.length - 1];
|
|
9975
|
-
const
|
|
10845
|
+
const delivery = last?.delivery ?? msgs[index].delivery;
|
|
9976
10846
|
// Only claim a duration when at least one step reported timing. Otherwise
|
|
9977
10847
|
// "Thought for <1s" would read as "fast" when it really means "unknown", so
|
|
9978
10848
|
// drop the duration phrase and label by step count alone.
|
|
@@ -9981,9 +10851,10 @@ class ChatComponent {
|
|
|
9981
10851
|
? `Thought for ${formatDuration(durationMs)} · ${steps.length} steps`
|
|
9982
10852
|
: `${steps.length} steps`
|
|
9983
10853
|
: undefined;
|
|
9984
|
-
return { content, durationMs,
|
|
10854
|
+
return { content, durationMs, delivery, label };
|
|
9985
10855
|
}
|
|
9986
10856
|
classifiers = new Map();
|
|
10857
|
+
markdownDocuments = new Map();
|
|
9987
10858
|
destroyRef = inject(DestroyRef);
|
|
9988
10859
|
injector = inject(Injector);
|
|
9989
10860
|
// Resolved against the component's own `providers` in normal use. The fallback
|
|
@@ -10007,28 +10878,24 @@ class ChatComponent {
|
|
|
10007
10878
|
programmaticScrollCount = 0;
|
|
10008
10879
|
static PIN_TOLERANCE_PX = 150;
|
|
10009
10880
|
/**
|
|
10010
|
-
* True iff
|
|
10011
|
-
*
|
|
10881
|
+
* True iff the current (last-index) assistant message owns an active
|
|
10882
|
+
* delivery generation. The bubble's own caret already signals loading;
|
|
10012
10883
|
* we suppress the floor typing-indicator in that case so the user
|
|
10013
10884
|
* doesn't see two loading affordances at once.
|
|
10014
10885
|
*
|
|
10015
10886
|
* Matches the same `streaming + current` condition the bubble uses
|
|
10016
|
-
* to enable `.chat-message__caret
|
|
10017
|
-
* `this.agent().isLoading() && i === this.agent().messages().length - 1`
|
|
10018
|
-
* `i === this.agent().messages().length - 1`
|
|
10887
|
+
* to enable `.chat-message__caret`.
|
|
10019
10888
|
*
|
|
10020
10889
|
* Restricted to assistant role because the caret only renders on
|
|
10021
10890
|
* assistant bubbles (`:host([data-role="assistant"][data-current=...
|
|
10022
10891
|
* ][data-streaming=...])`).
|
|
10023
10892
|
*/
|
|
10024
10893
|
currentAssistantStreaming = computed(() => {
|
|
10025
|
-
if (!this.agent().isLoading())
|
|
10026
|
-
return false;
|
|
10027
10894
|
const msgs = this.agent().messages();
|
|
10028
10895
|
if (msgs.length === 0)
|
|
10029
10896
|
return false;
|
|
10030
10897
|
const last = msgs[msgs.length - 1];
|
|
10031
|
-
return last?.role === 'assistant';
|
|
10898
|
+
return last?.role === 'assistant' && last.delivery.phase === 'streaming';
|
|
10032
10899
|
}, ...(ngDevMode ? [{ debugName: "currentAssistantStreaming" }] : []));
|
|
10033
10900
|
constructor() {
|
|
10034
10901
|
// Inject the chat lib's root CSS custom properties (--tplane-chat-bg,
|
|
@@ -10252,10 +11119,14 @@ class ChatComponent {
|
|
|
10252
11119
|
}
|
|
10253
11120
|
for (const key of [...this.classifiers.keys()]) {
|
|
10254
11121
|
if (!liveIds.has(key)) {
|
|
10255
|
-
this.classifiers.get(key)?.dispose();
|
|
11122
|
+
this.classifiers.get(key)?.classifier.dispose();
|
|
10256
11123
|
this.classifiers.delete(key);
|
|
10257
11124
|
}
|
|
10258
11125
|
}
|
|
11126
|
+
for (const key of [...this.markdownDocuments.keys()]) {
|
|
11127
|
+
if (!liveIds.has(key))
|
|
11128
|
+
this.markdownDocuments.delete(key);
|
|
11129
|
+
}
|
|
10259
11130
|
});
|
|
10260
11131
|
}
|
|
10261
11132
|
prevRole(index) {
|
|
@@ -10435,20 +11306,34 @@ class ChatComponent {
|
|
|
10435
11306
|
return false;
|
|
10436
11307
|
}
|
|
10437
11308
|
classifyMessage(content, message) {
|
|
10438
|
-
const
|
|
10439
|
-
let
|
|
10440
|
-
if (!
|
|
10441
|
-
|
|
10442
|
-
|
|
10443
|
-
|
|
10444
|
-
|
|
10445
|
-
|
|
11309
|
+
const generation = message.delivery.generation;
|
|
11310
|
+
let entry = this.classifiers.get(message.id);
|
|
11311
|
+
if (!entry || entry.generation !== generation) {
|
|
11312
|
+
entry?.classifier.dispose();
|
|
11313
|
+
entry = { generation, classifier: createContentClassifier() };
|
|
11314
|
+
this.classifiers.set(message.id, entry);
|
|
11315
|
+
}
|
|
11316
|
+
entry.classifier.update(content);
|
|
11317
|
+
return entry.classifier;
|
|
11318
|
+
}
|
|
11319
|
+
markdownDocumentFor(content, message) {
|
|
11320
|
+
const prior = this.markdownDocuments.get(message.id);
|
|
11321
|
+
const delivery = message.delivery;
|
|
11322
|
+
if (prior?.generation === delivery.generation &&
|
|
11323
|
+
prior.phase === delivery.phase &&
|
|
11324
|
+
prior.content === content) {
|
|
11325
|
+
return prior;
|
|
11326
|
+
}
|
|
11327
|
+
const document = markdownDocument(content, delivery);
|
|
11328
|
+
this.markdownDocuments.set(message.id, document);
|
|
11329
|
+
return document;
|
|
10446
11330
|
}
|
|
10447
11331
|
clearClassifiers() {
|
|
10448
|
-
for (const [,
|
|
10449
|
-
|
|
11332
|
+
for (const [, entry] of this.classifiers) {
|
|
11333
|
+
entry.classifier.dispose();
|
|
10450
11334
|
}
|
|
10451
11335
|
this.classifiers.clear();
|
|
11336
|
+
this.markdownDocuments.clear();
|
|
10452
11337
|
}
|
|
10453
11338
|
onSpecEvent(event, messageIndex) {
|
|
10454
11339
|
this.renderEvent.emit({ messageIndex, event });
|
|
@@ -10492,7 +11377,7 @@ class ChatComponent {
|
|
|
10492
11377
|
this.messageCopy.emit({ messageIndex: idx, content });
|
|
10493
11378
|
}
|
|
10494
11379
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10495
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: ChatComponent, isStandalone: true, selector: "chat", inputs: { agent: { classPropertyName: "agent", publicName: "agent", isSignal: true, isRequired: true, transformFunction: null }, views: { classPropertyName: "views", publicName: "views", isSignal: true, isRequired: false, transformFunction: null }, clientTools: { classPropertyName: "clientTools", publicName: "clientTools", isSignal: true, isRequired: false, transformFunction: null }, store: { classPropertyName: "store", publicName: "store", isSignal: true, isRequired: false, transformFunction: null }, handlers: { classPropertyName: "handlers", publicName: "handlers", isSignal: true, isRequired: false, transformFunction: null }, threads: { classPropertyName: "threads", publicName: "threads", isSignal: true, isRequired: false, transformFunction: null }, activeThreadId: { classPropertyName: "activeThreadId", publicName: "activeThreadId", isSignal: true, isRequired: false, transformFunction: null }, welcomeDisabled: { classPropertyName: "welcomeDisabled", publicName: "welcomeDisabled", isSignal: true, isRequired: false, transformFunction: null }, modelOptions: { classPropertyName: "modelOptions", publicName: "modelOptions", isSignal: true, isRequired: false, transformFunction: null }, showModelPicker: { classPropertyName: "showModelPicker", publicName: "showModelPicker", isSignal: true, isRequired: false, transformFunction: null }, selectedModel: { classPropertyName: "selectedModel", publicName: "selectedModel", isSignal: true, isRequired: false, transformFunction: null }, modelPickerPlaceholder: { classPropertyName: "modelPickerPlaceholder", publicName: "modelPickerPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, genuiToolNames: { classPropertyName: "genuiToolNames", publicName: "genuiToolNames", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedModel: "selectedModelChange", threadSelected: "threadSelected", renderEvent: "renderEvent", regenerate: "regenerate", rate: "rate", messageCopy: "messageCopy" }, providers: [
|
|
11380
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: ChatComponent, isStandalone: true, selector: "chat", inputs: { agent: { classPropertyName: "agent", publicName: "agent", isSignal: true, isRequired: true, transformFunction: null }, views: { classPropertyName: "views", publicName: "views", isSignal: true, isRequired: false, transformFunction: null }, clientTools: { classPropertyName: "clientTools", publicName: "clientTools", isSignal: true, isRequired: false, transformFunction: null }, store: { classPropertyName: "store", publicName: "store", isSignal: true, isRequired: false, transformFunction: null }, handlers: { classPropertyName: "handlers", publicName: "handlers", isSignal: true, isRequired: false, transformFunction: null }, threads: { classPropertyName: "threads", publicName: "threads", isSignal: true, isRequired: false, transformFunction: null }, activeThreadId: { classPropertyName: "activeThreadId", publicName: "activeThreadId", isSignal: true, isRequired: false, transformFunction: null }, welcomeDisabled: { classPropertyName: "welcomeDisabled", publicName: "welcomeDisabled", isSignal: true, isRequired: false, transformFunction: null }, modelOptions: { classPropertyName: "modelOptions", publicName: "modelOptions", isSignal: true, isRequired: false, transformFunction: null }, showModelPicker: { classPropertyName: "showModelPicker", publicName: "showModelPicker", isSignal: true, isRequired: false, transformFunction: null }, selectedModel: { classPropertyName: "selectedModel", publicName: "selectedModel", isSignal: true, isRequired: false, transformFunction: null }, modelPickerPlaceholder: { classPropertyName: "modelPickerPlaceholder", publicName: "modelPickerPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, genuiToolNames: { classPropertyName: "genuiToolNames", publicName: "genuiToolNames", isSignal: true, isRequired: false, transformFunction: null }, clientToolExecutionGuard: { classPropertyName: "clientToolExecutionGuard", publicName: "clientToolExecutionGuard", isSignal: true, isRequired: false, transformFunction: null }, clientToolContinuationPolicy: { classPropertyName: "clientToolContinuationPolicy", publicName: "clientToolContinuationPolicy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedModel: "selectedModelChange", threadSelected: "threadSelected", renderEvent: "renderEvent", clientToolContinuationLimit: "clientToolContinuationLimit", regenerate: "regenerate", rate: "rate", messageCopy: "messageCopy" }, providers: [
|
|
10496
11381
|
{ provide: CHAT_LIFECYCLE, useFactory: createChatLifecycle },
|
|
10497
11382
|
], viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
10498
11383
|
@if (showWelcome()) {
|
|
@@ -10534,12 +11419,11 @@ class ChatComponent {
|
|
|
10534
11419
|
<ng-template chatMessageTemplate="ai" let-message let-i="index">
|
|
10535
11420
|
@let content = messageContent(message);
|
|
10536
11421
|
@let classified = classifyMessage(content, message);
|
|
10537
|
-
@let pending = classified.type() === 'pending';
|
|
10538
11422
|
<chat-message
|
|
10539
11423
|
[role]="'assistant'"
|
|
10540
11424
|
[message]="message"
|
|
10541
11425
|
[prevRole]="prevRole(i)"
|
|
10542
|
-
[streaming]="
|
|
11426
|
+
[streaming]="message.delivery.phase === 'streaming'"
|
|
10543
11427
|
[current]="i === agent().messages().length - 1"
|
|
10544
11428
|
>
|
|
10545
11429
|
<!-- Reasoning is merged across a run of consecutive (tool-
|
|
@@ -10552,7 +11436,7 @@ class ChatComponent {
|
|
|
10552
11436
|
@let run = reasoningRun(i);
|
|
10553
11437
|
<chat-reasoning
|
|
10554
11438
|
[content]="run.content"
|
|
10555
|
-
[
|
|
11439
|
+
[delivery]="run.delivery"
|
|
10556
11440
|
[durationMs]="run.durationMs"
|
|
10557
11441
|
[label]="run.label"
|
|
10558
11442
|
/>
|
|
@@ -10571,7 +11455,7 @@ class ChatComponent {
|
|
|
10571
11455
|
(events)="onClientToolEvent($event)"
|
|
10572
11456
|
/>
|
|
10573
11457
|
@if (classified.markdown(); as md) {
|
|
10574
|
-
<chat-streaming-md [
|
|
11458
|
+
<chat-streaming-md [document]="markdownDocumentFor(md, message)" />
|
|
10575
11459
|
}
|
|
10576
11460
|
@if (classified.spec(); as spec) {
|
|
10577
11461
|
<!-- Pass ONLY the explicit consumer store (may be
|
|
@@ -10664,7 +11548,7 @@ class ChatComponent {
|
|
|
10664
11548
|
</div>
|
|
10665
11549
|
</div>
|
|
10666
11550
|
}
|
|
10667
|
-
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:flex;flex-direction:column;flex:1 1 auto;height:100%;min-height:0;max-height:100%;overflow:hidden;background:var(--tplane-chat-bg)}:host>chat-welcome{display:flex;flex:1 1 auto;width:100%}.chat-shell{display:flex;flex:1;min-height:0;overflow:hidden}.chat-shell__sidebar{width:240px;flex-shrink:0;border-right:1px solid var(--tplane-chat-separator);background:var(--tplane-chat-surface-alt);overflow-y:auto;display:none}@media(min-width:768px){.chat-shell__sidebar{display:block}}.chat-shell__main{flex:1;min-width:0;display:flex;flex-direction:column;min-height:0}.chat-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:60px 20px;color:var(--tplane-chat-text-muted);text-align:center;flex:1;min-height:0}.chat-empty[hidden]{display:none}.chat-empty__title{font-size:1.125rem;font-weight:500;color:var(--tplane-chat-text);margin:0}.chat-empty__sub{margin:0;font-size:var(--tplane-chat-font-size-sm)}.chat-scroll{flex:1;min-height:0;overflow-y:auto;padding-top:var(--tplane-chat-edge-pad)}.chat-scroll::-webkit-scrollbar{width:6px}.chat-scroll::-webkit-scrollbar-thumb{background:var(--tplane-chat-separator);border-radius:10px}[chatFooter]{padding-bottom:var(--tplane-chat-edge-pad)}.chat-footer-wrap{position:relative}\n"], dependencies: [{ kind: "component", type: ChatWindowComponent, selector: "chat-window" }, { kind: "component", type: ChatMessageListComponent, selector: "chat-message-list", inputs: ["agent"] }, { kind: "directive", type: MessageTemplateDirective, selector: "ng-template[chatMessageTemplate]", inputs: ["chatMessageTemplate"] }, { kind: "component", type: ChatMessageComponent, selector: "chat-message", inputs: ["role", "current", "streaming", "prevRole", "message"] }, { kind: "component", type: ChatInputComponent, selector: "chat-input", inputs: ["agent", "submitOnEnter", "placeholder", "showStopButton"], outputs: ["submitted", "stopped"] }, { kind: "component", type: ChatTypingIndicatorComponent, selector: "chat-typing-indicator", inputs: ["agent"] }, { kind: "component", type: ChatErrorComponent, selector: "chat-error", inputs: ["agent"] }, { kind: "component", type: ChatThreadListComponent, selector: "chat-thread-list", inputs: ["threads", "activeThreadId", "showNewThreadButton", "actions", "mode", "projects"], outputs: ["threadSelected", "newThreadRequested"] }, { kind: "component", type: ChatGenerativeUiComponent, selector: "chat-generative-ui", inputs: ["spec", "registry", "store", "handlers", "loading"], outputs: ["events"] }, { kind: "component", type: ChatStreamingMdComponent, selector: "chat-streaming-md", inputs: ["
|
|
11551
|
+
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:flex;flex-direction:column;flex:1 1 auto;height:100%;min-height:0;max-height:100%;overflow:hidden;background:var(--tplane-chat-bg)}:host>chat-welcome{display:flex;flex:1 1 auto;width:100%}.chat-shell{display:flex;flex:1;min-height:0;overflow:hidden}.chat-shell__sidebar{width:240px;flex-shrink:0;border-right:1px solid var(--tplane-chat-separator);background:var(--tplane-chat-surface-alt);overflow-y:auto;display:none}@media(min-width:768px){.chat-shell__sidebar{display:block}}.chat-shell__main{flex:1;min-width:0;display:flex;flex-direction:column;min-height:0}.chat-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:60px 20px;color:var(--tplane-chat-text-muted);text-align:center;flex:1;min-height:0}.chat-empty[hidden]{display:none}.chat-empty__title{font-size:1.125rem;font-weight:500;color:var(--tplane-chat-text);margin:0}.chat-empty__sub{margin:0;font-size:var(--tplane-chat-font-size-sm)}.chat-scroll{flex:1;min-height:0;overflow-y:auto;padding-top:var(--tplane-chat-edge-pad)}.chat-scroll::-webkit-scrollbar{width:6px}.chat-scroll::-webkit-scrollbar-thumb{background:var(--tplane-chat-separator);border-radius:10px}[chatFooter]{padding-bottom:var(--tplane-chat-edge-pad)}.chat-footer-wrap{position:relative}\n"], dependencies: [{ kind: "component", type: ChatWindowComponent, selector: "chat-window" }, { kind: "component", type: ChatMessageListComponent, selector: "chat-message-list", inputs: ["agent"] }, { kind: "directive", type: MessageTemplateDirective, selector: "ng-template[chatMessageTemplate]", inputs: ["chatMessageTemplate"] }, { kind: "component", type: ChatMessageComponent, selector: "chat-message", inputs: ["role", "current", "streaming", "prevRole", "message"] }, { kind: "component", type: ChatInputComponent, selector: "chat-input", inputs: ["agent", "submitOnEnter", "placeholder", "showStopButton"], outputs: ["submitted", "stopped"] }, { kind: "component", type: ChatTypingIndicatorComponent, selector: "chat-typing-indicator", inputs: ["agent"] }, { kind: "component", type: ChatErrorComponent, selector: "chat-error", inputs: ["agent"] }, { kind: "component", type: ChatThreadListComponent, selector: "chat-thread-list", inputs: ["threads", "activeThreadId", "showNewThreadButton", "actions", "mode", "projects"], outputs: ["threadSelected", "newThreadRequested"] }, { kind: "component", type: ChatGenerativeUiComponent, selector: "chat-generative-ui", inputs: ["spec", "registry", "store", "handlers", "loading"], outputs: ["events"] }, { kind: "component", type: ChatStreamingMdComponent, selector: "chat-streaming-md", inputs: ["document", "viewRegistry"] }, { kind: "component", type: ChatToolCallsComponent, selector: "chat-tool-calls", inputs: ["agent", "message", "grouping", "groupSummary", "excludeToolNames"] }, { kind: "component", type: ChatToolViewsComponent, selector: "chat-tool-views", inputs: ["agent", "message", "views", "store", "handlers"], outputs: ["events"] }, { kind: "component", type: A2uiSurfaceComponent, selector: "a2ui-surface", inputs: ["surface", "state", "catalog", "handlers", "surfaceFallback"], outputs: ["events", "action"] }, { kind: "component", type: ChatMessageActionsComponent, selector: "chat-message-actions", inputs: ["content", "disabled"], outputs: ["regenerate", "rate", "contentCopied"] }, { kind: "component", type: ChatWelcomeComponent, selector: "chat-welcome" }, { kind: "component", type: ChatSelectComponent, selector: "chat-select", inputs: ["options", "value", "placeholder", "disabled", "menuLabel", "panelClass"], outputs: ["valueChange"] }, { kind: "component", type: ChatReasoningComponent, selector: "chat-reasoning", inputs: ["content", "delivery", "durationMs", "label", "defaultExpanded"] }, { kind: "component", type: ChatScrollBubbleComponent, selector: "chat-scroll-bubble", inputs: ["mode"], outputs: ["clicked"] }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10668
11552
|
}
|
|
10669
11553
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatComponent, decorators: [{
|
|
10670
11554
|
type: Component,
|
|
@@ -10718,12 +11602,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
10718
11602
|
<ng-template chatMessageTemplate="ai" let-message let-i="index">
|
|
10719
11603
|
@let content = messageContent(message);
|
|
10720
11604
|
@let classified = classifyMessage(content, message);
|
|
10721
|
-
@let pending = classified.type() === 'pending';
|
|
10722
11605
|
<chat-message
|
|
10723
11606
|
[role]="'assistant'"
|
|
10724
11607
|
[message]="message"
|
|
10725
11608
|
[prevRole]="prevRole(i)"
|
|
10726
|
-
[streaming]="
|
|
11609
|
+
[streaming]="message.delivery.phase === 'streaming'"
|
|
10727
11610
|
[current]="i === agent().messages().length - 1"
|
|
10728
11611
|
>
|
|
10729
11612
|
<!-- Reasoning is merged across a run of consecutive (tool-
|
|
@@ -10736,7 +11619,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
10736
11619
|
@let run = reasoningRun(i);
|
|
10737
11620
|
<chat-reasoning
|
|
10738
11621
|
[content]="run.content"
|
|
10739
|
-
[
|
|
11622
|
+
[delivery]="run.delivery"
|
|
10740
11623
|
[durationMs]="run.durationMs"
|
|
10741
11624
|
[label]="run.label"
|
|
10742
11625
|
/>
|
|
@@ -10755,7 +11638,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
10755
11638
|
(events)="onClientToolEvent($event)"
|
|
10756
11639
|
/>
|
|
10757
11640
|
@if (classified.markdown(); as md) {
|
|
10758
|
-
<chat-streaming-md [
|
|
11641
|
+
<chat-streaming-md [document]="markdownDocumentFor(md, message)" />
|
|
10759
11642
|
}
|
|
10760
11643
|
@if (classified.spec(); as spec) {
|
|
10761
11644
|
<!-- Pass ONLY the explicit consumer store (may be
|
|
@@ -10849,7 +11732,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
10849
11732
|
</div>
|
|
10850
11733
|
}
|
|
10851
11734
|
`, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:flex;flex-direction:column;flex:1 1 auto;height:100%;min-height:0;max-height:100%;overflow:hidden;background:var(--tplane-chat-bg)}:host>chat-welcome{display:flex;flex:1 1 auto;width:100%}.chat-shell{display:flex;flex:1;min-height:0;overflow:hidden}.chat-shell__sidebar{width:240px;flex-shrink:0;border-right:1px solid var(--tplane-chat-separator);background:var(--tplane-chat-surface-alt);overflow-y:auto;display:none}@media(min-width:768px){.chat-shell__sidebar{display:block}}.chat-shell__main{flex:1;min-width:0;display:flex;flex-direction:column;min-height:0}.chat-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:60px 20px;color:var(--tplane-chat-text-muted);text-align:center;flex:1;min-height:0}.chat-empty[hidden]{display:none}.chat-empty__title{font-size:1.125rem;font-weight:500;color:var(--tplane-chat-text);margin:0}.chat-empty__sub{margin:0;font-size:var(--tplane-chat-font-size-sm)}.chat-scroll{flex:1;min-height:0;overflow-y:auto;padding-top:var(--tplane-chat-edge-pad)}.chat-scroll::-webkit-scrollbar{width:6px}.chat-scroll::-webkit-scrollbar-thumb{background:var(--tplane-chat-separator);border-radius:10px}[chatFooter]{padding-bottom:var(--tplane-chat-edge-pad)}.chat-footer-wrap{position:relative}\n"] }]
|
|
10852
|
-
}], ctorParameters: () => [], propDecorators: { agent: [{ type: i0.Input, args: [{ isSignal: true, alias: "agent", required: true }] }], views: [{ type: i0.Input, args: [{ isSignal: true, alias: "views", required: false }] }], clientTools: [{ type: i0.Input, args: [{ isSignal: true, alias: "clientTools", required: false }] }], store: [{ type: i0.Input, args: [{ isSignal: true, alias: "store", required: false }] }], handlers: [{ type: i0.Input, args: [{ isSignal: true, alias: "handlers", required: false }] }], threads: [{ type: i0.Input, args: [{ isSignal: true, alias: "threads", required: false }] }], activeThreadId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeThreadId", required: false }] }], welcomeDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "welcomeDisabled", required: false }] }], modelOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "modelOptions", required: false }] }], showModelPicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "showModelPicker", required: false }] }], selectedModel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedModel", required: false }] }, { type: i0.Output, args: ["selectedModelChange"] }], modelPickerPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "modelPickerPlaceholder", required: false }] }], genuiToolNames: [{ type: i0.Input, args: [{ isSignal: true, alias: "genuiToolNames", required: false }] }], threadSelected: [{ type: i0.Output, args: ["threadSelected"] }], renderEvent: [{ type: i0.Output, args: ["renderEvent"] }], regenerate: [{ type: i0.Output, args: ["regenerate"] }], rate: [{ type: i0.Output, args: ["rate"] }], messageCopy: [{ type: i0.Output, args: ["messageCopy"] }], scrollContainer: [{ type: i0.ViewChild, args: ['scrollContainer', { isSignal: true }] }] } });
|
|
11735
|
+
}], ctorParameters: () => [], propDecorators: { agent: [{ type: i0.Input, args: [{ isSignal: true, alias: "agent", required: true }] }], views: [{ type: i0.Input, args: [{ isSignal: true, alias: "views", required: false }] }], clientTools: [{ type: i0.Input, args: [{ isSignal: true, alias: "clientTools", required: false }] }], store: [{ type: i0.Input, args: [{ isSignal: true, alias: "store", required: false }] }], handlers: [{ type: i0.Input, args: [{ isSignal: true, alias: "handlers", required: false }] }], threads: [{ type: i0.Input, args: [{ isSignal: true, alias: "threads", required: false }] }], activeThreadId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeThreadId", required: false }] }], welcomeDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "welcomeDisabled", required: false }] }], modelOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "modelOptions", required: false }] }], showModelPicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "showModelPicker", required: false }] }], selectedModel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedModel", required: false }] }, { type: i0.Output, args: ["selectedModelChange"] }], modelPickerPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "modelPickerPlaceholder", required: false }] }], genuiToolNames: [{ type: i0.Input, args: [{ isSignal: true, alias: "genuiToolNames", required: false }] }], clientToolExecutionGuard: [{ type: i0.Input, args: [{ isSignal: true, alias: "clientToolExecutionGuard", required: false }] }], clientToolContinuationPolicy: [{ type: i0.Input, args: [{ isSignal: true, alias: "clientToolContinuationPolicy", required: false }] }], threadSelected: [{ type: i0.Output, args: ["threadSelected"] }], renderEvent: [{ type: i0.Output, args: ["renderEvent"] }], clientToolContinuationLimit: [{ type: i0.Output, args: ["clientToolContinuationLimit"] }], regenerate: [{ type: i0.Output, args: ["regenerate"] }], rate: [{ type: i0.Output, args: ["rate"] }], messageCopy: [{ type: i0.Output, args: ["messageCopy"] }], scrollContainer: [{ type: i0.ViewChild, args: ['scrollContainer', { isSignal: true }] }] } });
|
|
10853
11736
|
|
|
10854
11737
|
// libs/chat/src/lib/compositions/chat-popup/chat-popup.component.ts
|
|
10855
11738
|
// SPDX-License-Identifier: MIT
|
|
@@ -10936,7 +11819,7 @@ class ChatPopupComponent {
|
|
|
10936
11819
|
<ng-content select="[chatWelcomeSuggestions]" chatWelcomeSuggestions />
|
|
10937
11820
|
</chat>
|
|
10938
11821
|
</div>
|
|
10939
|
-
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{position:fixed;bottom:1rem;right:1rem;z-index:var(--tplane-chat-z-overlay-content, 30)}.chat-popup__launcher{position:relative}.chat-popup__window{position:fixed;bottom:5rem;right:1rem;width:24rem;height:600px;max-height:calc(100vh - 6rem);background:var(--tplane-chat-bg);border:1px solid var(--tplane-chat-separator);border-radius:.75rem;box-shadow:0 5px 40px #00000029;transform-origin:bottom right;transform:scale(.95) translateY(20px);opacity:0;pointer-events:none;transition:transform .2s ease-out,opacity .1s ease-out;overflow:hidden;display:flex;flex-direction:column}.chat-popup__window[data-open=true]{transform:scale(1) translateY(0);opacity:1;pointer-events:auto}@media(max-width:640px){.chat-popup__window{inset:0 auto auto 0;width:100vw;height:100vh;max-height:100vh;border-radius:0}}.chat-popup__close{position:absolute;top:8px;right:8px;width:32px;height:32px;background:transparent;border:0;cursor:pointer;color:var(--tplane-chat-text-muted);border-radius:50%;z-index:1;display:flex;align-items:center;justify-content:center}.chat-popup__close:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}\n"], dependencies: [{ kind: "component", type: ChatComponent, selector: "chat", inputs: ["agent", "views", "clientTools", "store", "handlers", "threads", "activeThreadId", "welcomeDisabled", "modelOptions", "showModelPicker", "selectedModel", "modelPickerPlaceholder", "genuiToolNames"], outputs: ["selectedModelChange", "threadSelected", "renderEvent", "regenerate", "rate", "messageCopy"] }, { kind: "component", type: ChatLauncherButtonComponent, selector: "chat-launcher-button", outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
11822
|
+
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{position:fixed;bottom:1rem;right:1rem;z-index:var(--tplane-chat-z-overlay-content, 30)}.chat-popup__launcher{position:relative}.chat-popup__window{position:fixed;bottom:5rem;right:1rem;width:24rem;height:600px;max-height:calc(100vh - 6rem);background:var(--tplane-chat-bg);border:1px solid var(--tplane-chat-separator);border-radius:.75rem;box-shadow:0 5px 40px #00000029;transform-origin:bottom right;transform:scale(.95) translateY(20px);opacity:0;pointer-events:none;transition:transform .2s ease-out,opacity .1s ease-out;overflow:hidden;display:flex;flex-direction:column}.chat-popup__window[data-open=true]{transform:scale(1) translateY(0);opacity:1;pointer-events:auto}@media(max-width:640px){.chat-popup__window{inset:0 auto auto 0;width:100vw;height:100vh;max-height:100vh;border-radius:0}}.chat-popup__close{position:absolute;top:8px;right:8px;width:32px;height:32px;background:transparent;border:0;cursor:pointer;color:var(--tplane-chat-text-muted);border-radius:50%;z-index:1;display:flex;align-items:center;justify-content:center}.chat-popup__close:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}\n"], dependencies: [{ kind: "component", type: ChatComponent, selector: "chat", inputs: ["agent", "views", "clientTools", "store", "handlers", "threads", "activeThreadId", "welcomeDisabled", "modelOptions", "showModelPicker", "selectedModel", "modelPickerPlaceholder", "genuiToolNames", "clientToolExecutionGuard", "clientToolContinuationPolicy"], outputs: ["selectedModelChange", "threadSelected", "renderEvent", "clientToolContinuationLimit", "regenerate", "rate", "messageCopy"] }, { kind: "component", type: ChatLauncherButtonComponent, selector: "chat-launcher-button", outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10940
11823
|
}
|
|
10941
11824
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatPopupComponent, decorators: [{
|
|
10942
11825
|
type: Component,
|
|
@@ -11059,7 +11942,7 @@ class ChatSidebarComponent {
|
|
|
11059
11942
|
<ng-content select="[chatWelcomeSuggestions]" chatWelcomeSuggestions />
|
|
11060
11943
|
</chat>
|
|
11061
11944
|
</aside>
|
|
11062
|
-
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:flex;height:100%;min-height:0}.chat-sidebar__content{flex:1 1 auto;min-width:0;min-height:0;transition:margin-right .3s ease}:host([data-push=\"true\"][data-open=\"true\"]) .chat-sidebar__content{margin-right:var(--tplane-chat-sidebar-width-drawer, 28rem)}@media(max-width:640px){:host([data-push=\"true\"][data-open=\"true\"]) .chat-sidebar__content{margin-right:0}}.chat-sidebar__panel{position:fixed;top:0;right:0;bottom:var(--tplane-chat-debug-claim-bottom, 0);width:var(--tplane-chat-sidebar-width-drawer, 28rem);background:var(--tplane-chat-bg);border-left:1px solid var(--tplane-chat-separator);box-shadow:-8px 0 32px #00000014;transform:translate(100%);transition:transform .2s ease-out,bottom .2s ease-out;z-index:var(--tplane-chat-z-overlay-content, 30);display:flex;flex-direction:column}.chat-sidebar__panel[data-open=true]{transform:translate(0)}@media(max-width:640px){.chat-sidebar__panel{width:100vw}}.chat-sidebar__panel-header{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 12px;border-bottom:1px solid var(--tplane-chat-separator);min-height:48px}.chat-sidebar__panel-title{min-width:0;flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:var(--tplane-chat-text);font-weight:500;font-size:var(--tplane-chat-font-size-sm)}.chat-sidebar__close{flex:0 0 auto;width:32px;height:32px;background:transparent;border:0;cursor:pointer;color:var(--tplane-chat-text-muted);border-radius:50%;display:flex;align-items:center;justify-content:center}.chat-sidebar__close:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}.chat-sidebar__launcher{position:fixed;bottom:calc(1rem + var(--tplane-chat-debug-claim-bottom, 0));right:1rem;z-index:var(--tplane-chat-z-overlay-content, 30);transition:bottom .2s ease-out}:host([data-open=\"true\"]) .chat-sidebar__launcher{display:none}\n"], dependencies: [{ kind: "component", type: ChatComponent, selector: "chat", inputs: ["agent", "views", "clientTools", "store", "handlers", "threads", "activeThreadId", "welcomeDisabled", "modelOptions", "showModelPicker", "selectedModel", "modelPickerPlaceholder", "genuiToolNames"], outputs: ["selectedModelChange", "threadSelected", "renderEvent", "regenerate", "rate", "messageCopy"] }, { kind: "component", type: ChatLauncherButtonComponent, selector: "chat-launcher-button", outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
11945
|
+
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:flex;height:100%;min-height:0}.chat-sidebar__content{flex:1 1 auto;min-width:0;min-height:0;transition:margin-right .3s ease}:host([data-push=\"true\"][data-open=\"true\"]) .chat-sidebar__content{margin-right:var(--tplane-chat-sidebar-width-drawer, 28rem)}@media(max-width:640px){:host([data-push=\"true\"][data-open=\"true\"]) .chat-sidebar__content{margin-right:0}}.chat-sidebar__panel{position:fixed;top:0;right:0;bottom:var(--tplane-chat-debug-claim-bottom, 0);width:var(--tplane-chat-sidebar-width-drawer, 28rem);background:var(--tplane-chat-bg);border-left:1px solid var(--tplane-chat-separator);box-shadow:-8px 0 32px #00000014;transform:translate(100%);transition:transform .2s ease-out,bottom .2s ease-out;z-index:var(--tplane-chat-z-overlay-content, 30);display:flex;flex-direction:column}.chat-sidebar__panel[data-open=true]{transform:translate(0)}@media(max-width:640px){.chat-sidebar__panel{width:100vw}}.chat-sidebar__panel-header{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 12px;border-bottom:1px solid var(--tplane-chat-separator);min-height:48px}.chat-sidebar__panel-title{min-width:0;flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:var(--tplane-chat-text);font-weight:500;font-size:var(--tplane-chat-font-size-sm)}.chat-sidebar__close{flex:0 0 auto;width:32px;height:32px;background:transparent;border:0;cursor:pointer;color:var(--tplane-chat-text-muted);border-radius:50%;display:flex;align-items:center;justify-content:center}.chat-sidebar__close:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}.chat-sidebar__launcher{position:fixed;bottom:calc(1rem + var(--tplane-chat-debug-claim-bottom, 0));right:1rem;z-index:var(--tplane-chat-z-overlay-content, 30);transition:bottom .2s ease-out}:host([data-open=\"true\"]) .chat-sidebar__launcher{display:none}\n"], dependencies: [{ kind: "component", type: ChatComponent, selector: "chat", inputs: ["agent", "views", "clientTools", "store", "handlers", "threads", "activeThreadId", "welcomeDisabled", "modelOptions", "showModelPicker", "selectedModel", "modelPickerPlaceholder", "genuiToolNames", "clientToolExecutionGuard", "clientToolContinuationPolicy"], outputs: ["selectedModelChange", "threadSelected", "renderEvent", "clientToolContinuationLimit", "regenerate", "rate", "messageCopy"] }, { kind: "component", type: ChatLauncherButtonComponent, selector: "chat-launcher-button", outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
11063
11946
|
}
|
|
11064
11947
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatSidebarComponent, decorators: [{
|
|
11065
11948
|
type: Component,
|
|
@@ -11222,6 +12105,14 @@ const CHAT_SIDENAV_STYLES = `
|
|
|
11222
12105
|
bottom: 0;
|
|
11223
12106
|
width: var(--tplane-chat-sidenav-width-drawer);
|
|
11224
12107
|
z-index: var(--tplane-chat-z-drawer, 1001);
|
|
12108
|
+
/* The host is a fixed, drawer-width, full-height box at z-index 1001 that
|
|
12109
|
+
* stays put whether or not the drawer is open — only the inner .chat-sidenav
|
|
12110
|
+
* PANEL slides off-screen (translateX(-100%)) when closed. Without this, the
|
|
12111
|
+
* transparent closed host still intercepts clicks over the left strip of the
|
|
12112
|
+
* content beneath it (e.g. App-mode forces drawer on desktop, so it covered
|
|
12113
|
+
* the itinerary overlay + welcome suggestions). Make the host inert; the
|
|
12114
|
+
* on-screen panel re-enables pointer events below. */
|
|
12115
|
+
pointer-events: none;
|
|
11225
12116
|
}
|
|
11226
12117
|
:host([data-mode="drawer"][data-open="true"]) {
|
|
11227
12118
|
box-shadow: 8px 0 32px rgba(0, 0, 0, 0.18);
|
|
@@ -11240,9 +12131,14 @@ const CHAT_SIDENAV_STYLES = `
|
|
|
11240
12131
|
height: 100%;
|
|
11241
12132
|
transition: transform 200ms ease;
|
|
11242
12133
|
transform: translateX(-100%);
|
|
12134
|
+
/* Keep the closed/closing panel inert. The host is inert above, and the
|
|
12135
|
+
* panel can still be hit during its transform transition unless pointer
|
|
12136
|
+
* events are restored only for the open state below. */
|
|
12137
|
+
pointer-events: none;
|
|
11243
12138
|
}
|
|
11244
12139
|
:host([data-mode="drawer"][data-open="true"]) .chat-sidenav {
|
|
11245
12140
|
transform: translateX(0);
|
|
12141
|
+
pointer-events: auto;
|
|
11246
12142
|
}
|
|
11247
12143
|
.chat-sidenav__header {
|
|
11248
12144
|
flex-shrink: 0;
|
|
@@ -11990,7 +12886,7 @@ class ChatSidenavComponent {
|
|
|
11990
12886
|
</div>
|
|
11991
12887
|
</nav>
|
|
11992
12888
|
<ng-container #debugHost />
|
|
11993
|
-
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block;height:100%}:host([data-mode=\"expanded\"]),:host([data-mode=\"collapsed\"]){position:fixed;top:0;left:0;bottom:0;z-index:100}:host([data-mode=\"expanded\"]){width:var(--tplane-chat-sidenav-width-expanded)}:host([data-mode=\"collapsed\"]){width:var(--tplane-chat-sidenav-width-collapsed)}:host([data-mode=\"expanded\"]) .chat-sidenav{width:100%}:host([data-mode=\"collapsed\"]) .chat-sidenav{width:100%}:host([data-mode=\"drawer\"]){position:fixed;top:0;left:0;bottom:0;width:var(--tplane-chat-sidenav-width-drawer);z-index:var(--tplane-chat-z-drawer, 1001)}:host([data-mode=\"drawer\"][data-open=\"true\"]){box-shadow:8px 0 32px #0000002e}.chat-sidenav{display:flex;flex-direction:column;height:100%;background:var(--tplane-chat-bg);border-right:1px solid var(--tplane-chat-separator);box-sizing:border-box;overflow:hidden}:host([data-mode=\"drawer\"]) .chat-sidenav{width:100%;height:100%;transition:transform .2s ease;transform:translate(-100%)}:host([data-mode=\"drawer\"][data-open=\"true\"]) .chat-sidenav{transform:translate(0)}.chat-sidenav__header{flex-shrink:0;padding:var(--tplane-chat-space-3)}.chat-sidenav__header:empty{display:none}.chat-sidenav__topbar{flex-shrink:0;display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:4px;padding:var(--tplane-chat-space-2) var(--tplane-chat-space-3);border-bottom:1px solid var(--tplane-chat-separator)}:host([data-mode=\"collapsed\"]) .chat-sidenav__topbar{flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:var(--tplane-chat-space-2) 0}.chat-sidenav__topbar .chat-sidenav__action--close{width:36px;height:36px;padding:0;justify-content:center;flex:0 0 auto}.chat-sidenav__topbar .chat-sidenav__action--close .chat-sidenav__action-label{display:none}.chat-sidenav__action--new{border:0;padding:12px 18px;border-radius:8px;font-size:var(--tplane-chat-font-size-sm);font-weight:600;display:flex;align-items:center;gap:8px;cursor:pointer;width:100%}.chat-sidenav__action--new:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--new{width:32px;height:32px;padding:0;border-radius:10px;justify-content:center}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--new .chat-sidenav__action-label{display:none}.chat-sidenav__actions{flex-shrink:0;display:flex;flex-direction:column;gap:4px;padding:var(--tplane-chat-space-3)}:host([data-mode=\"collapsed\"]) .chat-sidenav__actions{align-items:center;padding:var(--tplane-chat-space-2)}.chat-sidenav__action{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;background:transparent;color:var(--tplane-chat-text);border-radius:8px;cursor:pointer;font-family:inherit;font-size:var(--tplane-chat-font-size-sm);font-weight:400;text-align:left}.chat-sidenav__action:hover{background:var(--tplane-chat-surface-alt)}.chat-sidenav__action:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}:host([data-mode=\"collapsed\"]) .chat-sidenav__action{width:36px;height:36px;padding:0;justify-content:center}:host([data-mode=\"collapsed\"]) .chat-sidenav__action-label{display:none}.chat-sidenav__action.chat-sidenav__action--new{background:var(--tplane-chat-text);color:var(--tplane-chat-bg);border-radius:8px;padding:12px 18px;font-weight:600;font-size:var(--tplane-chat-font-size-sm)}.chat-sidenav__action.chat-sidenav__action--new:hover{background:var(--tplane-chat-text);filter:brightness(.92)}.chat-sidenav__action-icon{width:16px;height:16px;flex-shrink:0}.chat-sidenav__primary,.chat-sidenav__sections{flex-shrink:0}.chat-sidenav__threads{flex:1 1 auto;min-height:0;overflow-y:auto}.chat-sidenav__threads-heading{padding:8px 12px 4px;font-size:11px;color:var(--tplane-chat-text-muted);text-transform:uppercase;letter-spacing:.4px}:host([data-mode=\"collapsed\"]) .chat-sidenav__threads-heading{display:none}.chat-sidenav__footer{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;border-top:1px solid var(--tplane-chat-separator);gap:8px;flex-shrink:0}.chat-sidenav__footer-left{display:flex;align-items:center;gap:4px;min-height:28px}.chat-sidenav__debug{height:28px;min-width:28px;display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:0 9px;border:0;border-radius:8px;background:transparent;color:var(--tplane-chat-text-muted);cursor:pointer;font:inherit;font-size:12px;font-weight:500}.chat-sidenav__debug:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}.chat-sidenav__debug:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}.chat-sidenav__debug-dot{width:8px;height:8px;border-radius:50%;background:#22c55e;box-shadow:0 0 8px color-mix(in srgb,#22c55e 60%,transparent);flex:0 0 auto}.chat-sidenav__debug-dot--streaming{animation:chat-sidenav-debug-pulse 1.2s ease-in-out infinite}@keyframes chat-sidenav-debug-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(.85)}}.chat-sidenav__footer-right{display:flex;align-items:center;gap:4px;margin-left:auto}.chat-sidenav__toggle{width:28px;height:28px;border-radius:8px;border:0;background:transparent;color:var(--tplane-chat-text-muted);cursor:pointer;display:flex;align-items:center;justify-content:center}.chat-sidenav__toggle:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}:host([data-mode=\"collapsed\"]) .chat-sidenav__footer{flex-direction:column;align-items:center;padding:10px 4px}:host([data-mode=\"collapsed\"]) .chat-sidenav__footer-left{display:flex;flex-direction:column;align-items:center;min-height:28px}:host([data-mode=\"collapsed\"]) .chat-sidenav__debug{width:28px;padding:0}:host([data-mode=\"collapsed\"]) .chat-sidenav__debug-label,:host([data-mode=\"collapsed\"]) .chat-sidenav__footer-left>:not(.chat-sidenav__debug){display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__footer-right{flex-direction:column}.chat-sidenav__account{display:none}.chat-sidenav__account:has(>*){display:flex;align-items:center;gap:4px}.chat-sidenav__archived{flex-shrink:0}.chat-sidenav__archived-heading{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;border-radius:8px;background:transparent;color:var(--tplane-chat-text);font:inherit;font-size:var(--tplane-chat-font-size-sm);text-align:left;cursor:pointer}.chat-sidenav__archived-heading:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}.chat-sidenav__archived-heading:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}.chat-sidenav__archived-chevron{width:12px;height:12px;transition:transform .15s ease;flex-shrink:0}.chat-sidenav__archived[data-open=true] .chat-sidenav__archived-chevron{transform:rotate(90deg)}.chat-sidenav__archived-empty{padding:8px 12px;color:var(--tplane-chat-text-muted);font-size:var(--tplane-chat-font-size-sm)}:host([data-mode=\"collapsed\"]) .chat-sidenav__archived{display:none}.chat-sidenav__projects{flex-shrink:0}:host([data-mode=\"collapsed\"]) .chat-sidenav__projects{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__initial{display:inline-flex}:host([data-mode=\"collapsed\"]) .chat-thread-list__item-title{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__item-time{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__kebab{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__grip{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__item-wrap{justify-content:center}:host([data-mode=\"collapsed\"]) .chat-thread-list__item{padding:6px;justify-content:center;align-items:center;flex-direction:row}:host([data-mode=\"collapsed\"]) .chat-thread-list__new{display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--search{width:32px;height:32px;padding:0;border-radius:10px;justify-content:center;background:transparent}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--search .chat-sidenav__action-label{display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__threads,:host([data-mode=\"collapsed\"]) .chat-sidenav__projects,:host([data-mode=\"collapsed\"]) .chat-sidenav__archived,:host([data-mode=\"collapsed\"]) .chat-sidenav__sections,:host([data-mode=\"collapsed\"]) .chat-sidenav__primary{display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__topbar,:host([data-mode=\"collapsed\"]) .chat-sidenav__actions{padding:8px 4px;align-items:center;justify-content:center}\n"], dependencies: [{ kind: "component", type: ChatThreadListComponent, selector: "chat-thread-list", inputs: ["threads", "activeThreadId", "showNewThreadButton", "actions", "mode", "projects"], outputs: ["threadSelected", "newThreadRequested"] }, { kind: "component", type: ChatProjectListComponent, selector: "chat-project-list", inputs: ["projects", "activeProjectId", "showNewProjectButton", "actions"], outputs: ["projectSelected", "newProjectRequested"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
12889
|
+
`, isInline: true, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block;height:100%}:host([data-mode=\"expanded\"]),:host([data-mode=\"collapsed\"]){position:fixed;top:0;left:0;bottom:0;z-index:100}:host([data-mode=\"expanded\"]){width:var(--tplane-chat-sidenav-width-expanded)}:host([data-mode=\"collapsed\"]){width:var(--tplane-chat-sidenav-width-collapsed)}:host([data-mode=\"expanded\"]) .chat-sidenav{width:100%}:host([data-mode=\"collapsed\"]) .chat-sidenav{width:100%}:host([data-mode=\"drawer\"]){position:fixed;top:0;left:0;bottom:0;width:var(--tplane-chat-sidenav-width-drawer);z-index:var(--tplane-chat-z-drawer, 1001);pointer-events:none}:host([data-mode=\"drawer\"][data-open=\"true\"]){box-shadow:8px 0 32px #0000002e}.chat-sidenav{display:flex;flex-direction:column;height:100%;background:var(--tplane-chat-bg);border-right:1px solid var(--tplane-chat-separator);box-sizing:border-box;overflow:hidden}:host([data-mode=\"drawer\"]) .chat-sidenav{width:100%;height:100%;transition:transform .2s ease;transform:translate(-100%);pointer-events:none}:host([data-mode=\"drawer\"][data-open=\"true\"]) .chat-sidenav{transform:translate(0);pointer-events:auto}.chat-sidenav__header{flex-shrink:0;padding:var(--tplane-chat-space-3)}.chat-sidenav__header:empty{display:none}.chat-sidenav__topbar{flex-shrink:0;display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:4px;padding:var(--tplane-chat-space-2) var(--tplane-chat-space-3);border-bottom:1px solid var(--tplane-chat-separator)}:host([data-mode=\"collapsed\"]) .chat-sidenav__topbar{flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:var(--tplane-chat-space-2) 0}.chat-sidenav__topbar .chat-sidenav__action--close{width:36px;height:36px;padding:0;justify-content:center;flex:0 0 auto}.chat-sidenav__topbar .chat-sidenav__action--close .chat-sidenav__action-label{display:none}.chat-sidenav__action--new{border:0;padding:12px 18px;border-radius:8px;font-size:var(--tplane-chat-font-size-sm);font-weight:600;display:flex;align-items:center;gap:8px;cursor:pointer;width:100%}.chat-sidenav__action--new:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--new{width:32px;height:32px;padding:0;border-radius:10px;justify-content:center}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--new .chat-sidenav__action-label{display:none}.chat-sidenav__actions{flex-shrink:0;display:flex;flex-direction:column;gap:4px;padding:var(--tplane-chat-space-3)}:host([data-mode=\"collapsed\"]) .chat-sidenav__actions{align-items:center;padding:var(--tplane-chat-space-2)}.chat-sidenav__action{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;background:transparent;color:var(--tplane-chat-text);border-radius:8px;cursor:pointer;font-family:inherit;font-size:var(--tplane-chat-font-size-sm);font-weight:400;text-align:left}.chat-sidenav__action:hover{background:var(--tplane-chat-surface-alt)}.chat-sidenav__action:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}:host([data-mode=\"collapsed\"]) .chat-sidenav__action{width:36px;height:36px;padding:0;justify-content:center}:host([data-mode=\"collapsed\"]) .chat-sidenav__action-label{display:none}.chat-sidenav__action.chat-sidenav__action--new{background:var(--tplane-chat-text);color:var(--tplane-chat-bg);border-radius:8px;padding:12px 18px;font-weight:600;font-size:var(--tplane-chat-font-size-sm)}.chat-sidenav__action.chat-sidenav__action--new:hover{background:var(--tplane-chat-text);filter:brightness(.92)}.chat-sidenav__action-icon{width:16px;height:16px;flex-shrink:0}.chat-sidenav__primary,.chat-sidenav__sections{flex-shrink:0}.chat-sidenav__threads{flex:1 1 auto;min-height:0;overflow-y:auto}.chat-sidenav__threads-heading{padding:8px 12px 4px;font-size:11px;color:var(--tplane-chat-text-muted);text-transform:uppercase;letter-spacing:.4px}:host([data-mode=\"collapsed\"]) .chat-sidenav__threads-heading{display:none}.chat-sidenav__footer{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;border-top:1px solid var(--tplane-chat-separator);gap:8px;flex-shrink:0}.chat-sidenav__footer-left{display:flex;align-items:center;gap:4px;min-height:28px}.chat-sidenav__debug{height:28px;min-width:28px;display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:0 9px;border:0;border-radius:8px;background:transparent;color:var(--tplane-chat-text-muted);cursor:pointer;font:inherit;font-size:12px;font-weight:500}.chat-sidenav__debug:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}.chat-sidenav__debug:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}.chat-sidenav__debug-dot{width:8px;height:8px;border-radius:50%;background:#22c55e;box-shadow:0 0 8px color-mix(in srgb,#22c55e 60%,transparent);flex:0 0 auto}.chat-sidenav__debug-dot--streaming{animation:chat-sidenav-debug-pulse 1.2s ease-in-out infinite}@keyframes chat-sidenav-debug-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(.85)}}.chat-sidenav__footer-right{display:flex;align-items:center;gap:4px;margin-left:auto}.chat-sidenav__toggle{width:28px;height:28px;border-radius:8px;border:0;background:transparent;color:var(--tplane-chat-text-muted);cursor:pointer;display:flex;align-items:center;justify-content:center}.chat-sidenav__toggle:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}:host([data-mode=\"collapsed\"]) .chat-sidenav__footer{flex-direction:column;align-items:center;padding:10px 4px}:host([data-mode=\"collapsed\"]) .chat-sidenav__footer-left{display:flex;flex-direction:column;align-items:center;min-height:28px}:host([data-mode=\"collapsed\"]) .chat-sidenav__debug{width:28px;padding:0}:host([data-mode=\"collapsed\"]) .chat-sidenav__debug-label,:host([data-mode=\"collapsed\"]) .chat-sidenav__footer-left>:not(.chat-sidenav__debug){display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__footer-right{flex-direction:column}.chat-sidenav__account{display:none}.chat-sidenav__account:has(>*){display:flex;align-items:center;gap:4px}.chat-sidenav__archived{flex-shrink:0}.chat-sidenav__archived-heading{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;border-radius:8px;background:transparent;color:var(--tplane-chat-text);font:inherit;font-size:var(--tplane-chat-font-size-sm);text-align:left;cursor:pointer}.chat-sidenav__archived-heading:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}.chat-sidenav__archived-heading:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}.chat-sidenav__archived-chevron{width:12px;height:12px;transition:transform .15s ease;flex-shrink:0}.chat-sidenav__archived[data-open=true] .chat-sidenav__archived-chevron{transform:rotate(90deg)}.chat-sidenav__archived-empty{padding:8px 12px;color:var(--tplane-chat-text-muted);font-size:var(--tplane-chat-font-size-sm)}:host([data-mode=\"collapsed\"]) .chat-sidenav__archived{display:none}.chat-sidenav__projects{flex-shrink:0}:host([data-mode=\"collapsed\"]) .chat-sidenav__projects{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__initial{display:inline-flex}:host([data-mode=\"collapsed\"]) .chat-thread-list__item-title{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__item-time{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__kebab{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__grip{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__item-wrap{justify-content:center}:host([data-mode=\"collapsed\"]) .chat-thread-list__item{padding:6px;justify-content:center;align-items:center;flex-direction:row}:host([data-mode=\"collapsed\"]) .chat-thread-list__new{display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--search{width:32px;height:32px;padding:0;border-radius:10px;justify-content:center;background:transparent}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--search .chat-sidenav__action-label{display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__threads,:host([data-mode=\"collapsed\"]) .chat-sidenav__projects,:host([data-mode=\"collapsed\"]) .chat-sidenav__archived,:host([data-mode=\"collapsed\"]) .chat-sidenav__sections,:host([data-mode=\"collapsed\"]) .chat-sidenav__primary{display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__topbar,:host([data-mode=\"collapsed\"]) .chat-sidenav__actions{padding:8px 4px;align-items:center;justify-content:center}\n"], dependencies: [{ kind: "component", type: ChatThreadListComponent, selector: "chat-thread-list", inputs: ["threads", "activeThreadId", "showNewThreadButton", "actions", "mode", "projects"], outputs: ["threadSelected", "newThreadRequested"] }, { kind: "component", type: ChatProjectListComponent, selector: "chat-project-list", inputs: ["projects", "activeProjectId", "showNewProjectButton", "actions"], outputs: ["projectSelected", "newProjectRequested"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
11994
12890
|
}
|
|
11995
12891
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ChatSidenavComponent, decorators: [{
|
|
11996
12892
|
type: Component,
|
|
@@ -12234,7 +13130,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImpor
|
|
|
12234
13130
|
</div>
|
|
12235
13131
|
</nav>
|
|
12236
13132
|
<ng-container #debugHost />
|
|
12237
|
-
`, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block;height:100%}:host([data-mode=\"expanded\"]),:host([data-mode=\"collapsed\"]){position:fixed;top:0;left:0;bottom:0;z-index:100}:host([data-mode=\"expanded\"]){width:var(--tplane-chat-sidenav-width-expanded)}:host([data-mode=\"collapsed\"]){width:var(--tplane-chat-sidenav-width-collapsed)}:host([data-mode=\"expanded\"]) .chat-sidenav{width:100%}:host([data-mode=\"collapsed\"]) .chat-sidenav{width:100%}:host([data-mode=\"drawer\"]){position:fixed;top:0;left:0;bottom:0;width:var(--tplane-chat-sidenav-width-drawer);z-index:var(--tplane-chat-z-drawer, 1001)}:host([data-mode=\"drawer\"][data-open=\"true\"]){box-shadow:8px 0 32px #0000002e}.chat-sidenav{display:flex;flex-direction:column;height:100%;background:var(--tplane-chat-bg);border-right:1px solid var(--tplane-chat-separator);box-sizing:border-box;overflow:hidden}:host([data-mode=\"drawer\"]) .chat-sidenav{width:100%;height:100%;transition:transform .2s ease;transform:translate(-100%)}:host([data-mode=\"drawer\"][data-open=\"true\"]) .chat-sidenav{transform:translate(0)}.chat-sidenav__header{flex-shrink:0;padding:var(--tplane-chat-space-3)}.chat-sidenav__header:empty{display:none}.chat-sidenav__topbar{flex-shrink:0;display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:4px;padding:var(--tplane-chat-space-2) var(--tplane-chat-space-3);border-bottom:1px solid var(--tplane-chat-separator)}:host([data-mode=\"collapsed\"]) .chat-sidenav__topbar{flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:var(--tplane-chat-space-2) 0}.chat-sidenav__topbar .chat-sidenav__action--close{width:36px;height:36px;padding:0;justify-content:center;flex:0 0 auto}.chat-sidenav__topbar .chat-sidenav__action--close .chat-sidenav__action-label{display:none}.chat-sidenav__action--new{border:0;padding:12px 18px;border-radius:8px;font-size:var(--tplane-chat-font-size-sm);font-weight:600;display:flex;align-items:center;gap:8px;cursor:pointer;width:100%}.chat-sidenav__action--new:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--new{width:32px;height:32px;padding:0;border-radius:10px;justify-content:center}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--new .chat-sidenav__action-label{display:none}.chat-sidenav__actions{flex-shrink:0;display:flex;flex-direction:column;gap:4px;padding:var(--tplane-chat-space-3)}:host([data-mode=\"collapsed\"]) .chat-sidenav__actions{align-items:center;padding:var(--tplane-chat-space-2)}.chat-sidenav__action{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;background:transparent;color:var(--tplane-chat-text);border-radius:8px;cursor:pointer;font-family:inherit;font-size:var(--tplane-chat-font-size-sm);font-weight:400;text-align:left}.chat-sidenav__action:hover{background:var(--tplane-chat-surface-alt)}.chat-sidenav__action:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}:host([data-mode=\"collapsed\"]) .chat-sidenav__action{width:36px;height:36px;padding:0;justify-content:center}:host([data-mode=\"collapsed\"]) .chat-sidenav__action-label{display:none}.chat-sidenav__action.chat-sidenav__action--new{background:var(--tplane-chat-text);color:var(--tplane-chat-bg);border-radius:8px;padding:12px 18px;font-weight:600;font-size:var(--tplane-chat-font-size-sm)}.chat-sidenav__action.chat-sidenav__action--new:hover{background:var(--tplane-chat-text);filter:brightness(.92)}.chat-sidenav__action-icon{width:16px;height:16px;flex-shrink:0}.chat-sidenav__primary,.chat-sidenav__sections{flex-shrink:0}.chat-sidenav__threads{flex:1 1 auto;min-height:0;overflow-y:auto}.chat-sidenav__threads-heading{padding:8px 12px 4px;font-size:11px;color:var(--tplane-chat-text-muted);text-transform:uppercase;letter-spacing:.4px}:host([data-mode=\"collapsed\"]) .chat-sidenav__threads-heading{display:none}.chat-sidenav__footer{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;border-top:1px solid var(--tplane-chat-separator);gap:8px;flex-shrink:0}.chat-sidenav__footer-left{display:flex;align-items:center;gap:4px;min-height:28px}.chat-sidenav__debug{height:28px;min-width:28px;display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:0 9px;border:0;border-radius:8px;background:transparent;color:var(--tplane-chat-text-muted);cursor:pointer;font:inherit;font-size:12px;font-weight:500}.chat-sidenav__debug:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}.chat-sidenav__debug:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}.chat-sidenav__debug-dot{width:8px;height:8px;border-radius:50%;background:#22c55e;box-shadow:0 0 8px color-mix(in srgb,#22c55e 60%,transparent);flex:0 0 auto}.chat-sidenav__debug-dot--streaming{animation:chat-sidenav-debug-pulse 1.2s ease-in-out infinite}@keyframes chat-sidenav-debug-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(.85)}}.chat-sidenav__footer-right{display:flex;align-items:center;gap:4px;margin-left:auto}.chat-sidenav__toggle{width:28px;height:28px;border-radius:8px;border:0;background:transparent;color:var(--tplane-chat-text-muted);cursor:pointer;display:flex;align-items:center;justify-content:center}.chat-sidenav__toggle:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}:host([data-mode=\"collapsed\"]) .chat-sidenav__footer{flex-direction:column;align-items:center;padding:10px 4px}:host([data-mode=\"collapsed\"]) .chat-sidenav__footer-left{display:flex;flex-direction:column;align-items:center;min-height:28px}:host([data-mode=\"collapsed\"]) .chat-sidenav__debug{width:28px;padding:0}:host([data-mode=\"collapsed\"]) .chat-sidenav__debug-label,:host([data-mode=\"collapsed\"]) .chat-sidenav__footer-left>:not(.chat-sidenav__debug){display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__footer-right{flex-direction:column}.chat-sidenav__account{display:none}.chat-sidenav__account:has(>*){display:flex;align-items:center;gap:4px}.chat-sidenav__archived{flex-shrink:0}.chat-sidenav__archived-heading{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;border-radius:8px;background:transparent;color:var(--tplane-chat-text);font:inherit;font-size:var(--tplane-chat-font-size-sm);text-align:left;cursor:pointer}.chat-sidenav__archived-heading:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}.chat-sidenav__archived-heading:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}.chat-sidenav__archived-chevron{width:12px;height:12px;transition:transform .15s ease;flex-shrink:0}.chat-sidenav__archived[data-open=true] .chat-sidenav__archived-chevron{transform:rotate(90deg)}.chat-sidenav__archived-empty{padding:8px 12px;color:var(--tplane-chat-text-muted);font-size:var(--tplane-chat-font-size-sm)}:host([data-mode=\"collapsed\"]) .chat-sidenav__archived{display:none}.chat-sidenav__projects{flex-shrink:0}:host([data-mode=\"collapsed\"]) .chat-sidenav__projects{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__initial{display:inline-flex}:host([data-mode=\"collapsed\"]) .chat-thread-list__item-title{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__item-time{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__kebab{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__grip{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__item-wrap{justify-content:center}:host([data-mode=\"collapsed\"]) .chat-thread-list__item{padding:6px;justify-content:center;align-items:center;flex-direction:row}:host([data-mode=\"collapsed\"]) .chat-thread-list__new{display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--search{width:32px;height:32px;padding:0;border-radius:10px;justify-content:center;background:transparent}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--search .chat-sidenav__action-label{display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__threads,:host([data-mode=\"collapsed\"]) .chat-sidenav__projects,:host([data-mode=\"collapsed\"]) .chat-sidenav__archived,:host([data-mode=\"collapsed\"]) .chat-sidenav__sections,:host([data-mode=\"collapsed\"]) .chat-sidenav__primary{display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__topbar,:host([data-mode=\"collapsed\"]) .chat-sidenav__actions{padding:8px 4px;align-items:center;justify-content:center}\n"] }]
|
|
13133
|
+
`, styles: [":host{font-family:var(--tplane-chat-font-family);color:var(--tplane-chat-text)}\n", ":host{display:block;height:100%}:host([data-mode=\"expanded\"]),:host([data-mode=\"collapsed\"]){position:fixed;top:0;left:0;bottom:0;z-index:100}:host([data-mode=\"expanded\"]){width:var(--tplane-chat-sidenav-width-expanded)}:host([data-mode=\"collapsed\"]){width:var(--tplane-chat-sidenav-width-collapsed)}:host([data-mode=\"expanded\"]) .chat-sidenav{width:100%}:host([data-mode=\"collapsed\"]) .chat-sidenav{width:100%}:host([data-mode=\"drawer\"]){position:fixed;top:0;left:0;bottom:0;width:var(--tplane-chat-sidenav-width-drawer);z-index:var(--tplane-chat-z-drawer, 1001);pointer-events:none}:host([data-mode=\"drawer\"][data-open=\"true\"]){box-shadow:8px 0 32px #0000002e}.chat-sidenav{display:flex;flex-direction:column;height:100%;background:var(--tplane-chat-bg);border-right:1px solid var(--tplane-chat-separator);box-sizing:border-box;overflow:hidden}:host([data-mode=\"drawer\"]) .chat-sidenav{width:100%;height:100%;transition:transform .2s ease;transform:translate(-100%);pointer-events:none}:host([data-mode=\"drawer\"][data-open=\"true\"]) .chat-sidenav{transform:translate(0);pointer-events:auto}.chat-sidenav__header{flex-shrink:0;padding:var(--tplane-chat-space-3)}.chat-sidenav__header:empty{display:none}.chat-sidenav__topbar{flex-shrink:0;display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:4px;padding:var(--tplane-chat-space-2) var(--tplane-chat-space-3);border-bottom:1px solid var(--tplane-chat-separator)}:host([data-mode=\"collapsed\"]) .chat-sidenav__topbar{flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:var(--tplane-chat-space-2) 0}.chat-sidenav__topbar .chat-sidenav__action--close{width:36px;height:36px;padding:0;justify-content:center;flex:0 0 auto}.chat-sidenav__topbar .chat-sidenav__action--close .chat-sidenav__action-label{display:none}.chat-sidenav__action--new{border:0;padding:12px 18px;border-radius:8px;font-size:var(--tplane-chat-font-size-sm);font-weight:600;display:flex;align-items:center;gap:8px;cursor:pointer;width:100%}.chat-sidenav__action--new:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--new{width:32px;height:32px;padding:0;border-radius:10px;justify-content:center}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--new .chat-sidenav__action-label{display:none}.chat-sidenav__actions{flex-shrink:0;display:flex;flex-direction:column;gap:4px;padding:var(--tplane-chat-space-3)}:host([data-mode=\"collapsed\"]) .chat-sidenav__actions{align-items:center;padding:var(--tplane-chat-space-2)}.chat-sidenav__action{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;background:transparent;color:var(--tplane-chat-text);border-radius:8px;cursor:pointer;font-family:inherit;font-size:var(--tplane-chat-font-size-sm);font-weight:400;text-align:left}.chat-sidenav__action:hover{background:var(--tplane-chat-surface-alt)}.chat-sidenav__action:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}:host([data-mode=\"collapsed\"]) .chat-sidenav__action{width:36px;height:36px;padding:0;justify-content:center}:host([data-mode=\"collapsed\"]) .chat-sidenav__action-label{display:none}.chat-sidenav__action.chat-sidenav__action--new{background:var(--tplane-chat-text);color:var(--tplane-chat-bg);border-radius:8px;padding:12px 18px;font-weight:600;font-size:var(--tplane-chat-font-size-sm)}.chat-sidenav__action.chat-sidenav__action--new:hover{background:var(--tplane-chat-text);filter:brightness(.92)}.chat-sidenav__action-icon{width:16px;height:16px;flex-shrink:0}.chat-sidenav__primary,.chat-sidenav__sections{flex-shrink:0}.chat-sidenav__threads{flex:1 1 auto;min-height:0;overflow-y:auto}.chat-sidenav__threads-heading{padding:8px 12px 4px;font-size:11px;color:var(--tplane-chat-text-muted);text-transform:uppercase;letter-spacing:.4px}:host([data-mode=\"collapsed\"]) .chat-sidenav__threads-heading{display:none}.chat-sidenav__footer{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;border-top:1px solid var(--tplane-chat-separator);gap:8px;flex-shrink:0}.chat-sidenav__footer-left{display:flex;align-items:center;gap:4px;min-height:28px}.chat-sidenav__debug{height:28px;min-width:28px;display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:0 9px;border:0;border-radius:8px;background:transparent;color:var(--tplane-chat-text-muted);cursor:pointer;font:inherit;font-size:12px;font-weight:500}.chat-sidenav__debug:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}.chat-sidenav__debug:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}.chat-sidenav__debug-dot{width:8px;height:8px;border-radius:50%;background:#22c55e;box-shadow:0 0 8px color-mix(in srgb,#22c55e 60%,transparent);flex:0 0 auto}.chat-sidenav__debug-dot--streaming{animation:chat-sidenav-debug-pulse 1.2s ease-in-out infinite}@keyframes chat-sidenav-debug-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(.85)}}.chat-sidenav__footer-right{display:flex;align-items:center;gap:4px;margin-left:auto}.chat-sidenav__toggle{width:28px;height:28px;border-radius:8px;border:0;background:transparent;color:var(--tplane-chat-text-muted);cursor:pointer;display:flex;align-items:center;justify-content:center}.chat-sidenav__toggle:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}:host([data-mode=\"collapsed\"]) .chat-sidenav__footer{flex-direction:column;align-items:center;padding:10px 4px}:host([data-mode=\"collapsed\"]) .chat-sidenav__footer-left{display:flex;flex-direction:column;align-items:center;min-height:28px}:host([data-mode=\"collapsed\"]) .chat-sidenav__debug{width:28px;padding:0}:host([data-mode=\"collapsed\"]) .chat-sidenav__debug-label,:host([data-mode=\"collapsed\"]) .chat-sidenav__footer-left>:not(.chat-sidenav__debug){display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__footer-right{flex-direction:column}.chat-sidenav__account{display:none}.chat-sidenav__account:has(>*){display:flex;align-items:center;gap:4px}.chat-sidenav__archived{flex-shrink:0}.chat-sidenav__archived-heading{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;border-radius:8px;background:transparent;color:var(--tplane-chat-text);font:inherit;font-size:var(--tplane-chat-font-size-sm);text-align:left;cursor:pointer}.chat-sidenav__archived-heading:hover{background:var(--tplane-chat-surface-alt);color:var(--tplane-chat-text)}.chat-sidenav__archived-heading:focus-visible{outline:2px solid var(--tplane-chat-primary);outline-offset:2px}.chat-sidenav__archived-chevron{width:12px;height:12px;transition:transform .15s ease;flex-shrink:0}.chat-sidenav__archived[data-open=true] .chat-sidenav__archived-chevron{transform:rotate(90deg)}.chat-sidenav__archived-empty{padding:8px 12px;color:var(--tplane-chat-text-muted);font-size:var(--tplane-chat-font-size-sm)}:host([data-mode=\"collapsed\"]) .chat-sidenav__archived{display:none}.chat-sidenav__projects{flex-shrink:0}:host([data-mode=\"collapsed\"]) .chat-sidenav__projects{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__initial{display:inline-flex}:host([data-mode=\"collapsed\"]) .chat-thread-list__item-title{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__item-time{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__kebab{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__grip{display:none}:host([data-mode=\"collapsed\"]) .chat-thread-list__item-wrap{justify-content:center}:host([data-mode=\"collapsed\"]) .chat-thread-list__item{padding:6px;justify-content:center;align-items:center;flex-direction:row}:host([data-mode=\"collapsed\"]) .chat-thread-list__new{display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--search{width:32px;height:32px;padding:0;border-radius:10px;justify-content:center;background:transparent}:host([data-mode=\"collapsed\"]) .chat-sidenav__action--search .chat-sidenav__action-label{display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__threads,:host([data-mode=\"collapsed\"]) .chat-sidenav__projects,:host([data-mode=\"collapsed\"]) .chat-sidenav__archived,:host([data-mode=\"collapsed\"]) .chat-sidenav__sections,:host([data-mode=\"collapsed\"]) .chat-sidenav__primary{display:none}:host([data-mode=\"collapsed\"]) .chat-sidenav__topbar,:host([data-mode=\"collapsed\"]) .chat-sidenav__actions{padding:8px 4px;align-items:center;justify-content:center}\n"] }]
|
|
12238
13134
|
}], ctorParameters: () => [], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], threads: [{ type: i0.Input, args: [{ isSignal: true, alias: "threads", required: false }] }], activeThreadId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeThreadId", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], archivedThreads: [{ type: i0.Input, args: [{ isSignal: true, alias: "archivedThreads", required: false }] }], projects: [{ type: i0.Input, args: [{ isSignal: true, alias: "projects", required: false }] }], selectedProjectId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedProjectId", required: false }] }], projectActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectActions", required: false }] }], agent: [{ type: i0.Input, args: [{ isSignal: true, alias: "agent", required: false }] }], debug: [{ type: i0.Input, args: [{ isSignal: true, alias: "debug", required: false }] }], newChat: [{ type: i0.Output, args: ["newChat"] }], threadSelected: [{ type: i0.Output, args: ["threadSelected"] }], searchOpened: [{ type: i0.Output, args: ["searchOpened"] }], openChange: [{ type: i0.Output, args: ["openChange"] }], modeChange: [{ type: i0.Output, args: ["modeChange"] }], projectSelected: [{ type: i0.Output, args: ["projectSelected"] }], newProjectRequested: [{ type: i0.Output, args: ["newProjectRequested"] }], debugHost: [{ type: i0.ViewChild, args: ['debugHost', { ...{
|
|
12239
13135
|
read: ViewContainerRef,
|
|
12240
13136
|
}, isSignal: true }] }] } });
|
|
@@ -13612,8 +14508,11 @@ function a2uiBasicCatalog() {
|
|
|
13612
14508
|
* @param description Natural-language description the model sees.
|
|
13613
14509
|
* @param schema Standard Schema (e.g. a Zod object) for the arguments; the
|
|
13614
14510
|
* handler's argument type is inferred from it.
|
|
13615
|
-
* @param handler Runs in the browser when the model calls the tool
|
|
13616
|
-
* type `R` is carried on the
|
|
14511
|
+
* @param handler Runs in the browser when the model calls the tool. The second
|
|
14512
|
+
* argument carries an `AbortSignal`; its return type `R` is carried on the
|
|
14513
|
+
* resulting {@link FunctionToolDef}.
|
|
14514
|
+
* @param options Execution policy options, including `idempotent: true` to skip
|
|
14515
|
+
* durable pre-execution claims when a guard is configured.
|
|
13617
14516
|
* @returns A {@link FunctionToolDef} for inclusion in {@link tools}.
|
|
13618
14517
|
* @example
|
|
13619
14518
|
* ```ts
|
|
@@ -13621,8 +14520,8 @@ function a2uiBasicCatalog() {
|
|
|
13621
14520
|
* const registry = tools({ move_stop: move });
|
|
13622
14521
|
* ```
|
|
13623
14522
|
*/
|
|
13624
|
-
function action(description, schema, handler) {
|
|
13625
|
-
return { kind: 'function', description, schema, handler };
|
|
14523
|
+
function action(description, schema, handler, options = {}) {
|
|
14524
|
+
return { kind: 'function', description, schema, handler, ...options };
|
|
13626
14525
|
}
|
|
13627
14526
|
/**
|
|
13628
14527
|
* Render-only component tool — the model fills the component's props from the
|
|
@@ -13654,8 +14553,8 @@ function action(description, schema, handler) {
|
|
|
13654
14553
|
* const registry = tools({ day_card: dayCard });
|
|
13655
14554
|
* ```
|
|
13656
14555
|
*/
|
|
13657
|
-
function view(description, schema, component) {
|
|
13658
|
-
return { kind: 'view', description, schema, component: component };
|
|
14556
|
+
function view(description, schema, component, options = {}) {
|
|
14557
|
+
return { kind: 'view', description, schema, component: component, ...options };
|
|
13659
14558
|
}
|
|
13660
14559
|
/**
|
|
13661
14560
|
* Interactive (human-in-the-loop) component tool — the model fills the
|
|
@@ -13689,8 +14588,8 @@ function view(description, schema, component) {
|
|
|
13689
14588
|
* const registry = tools({ pick_option: choice });
|
|
13690
14589
|
* ```
|
|
13691
14590
|
*/
|
|
13692
|
-
function ask(description, schema, component) {
|
|
13693
|
-
return { kind: 'ask', description, schema, component: component };
|
|
14591
|
+
function ask(description, schema, component, options = {}) {
|
|
14592
|
+
return { kind: 'ask', description, schema, component: component, ...options };
|
|
13694
14593
|
}
|
|
13695
14594
|
/**
|
|
13696
14595
|
* Collect named client tools into a frozen, name-keyed registry.
|
|
@@ -13718,6 +14617,15 @@ function tools(map) {
|
|
|
13718
14617
|
return Object.freeze({ ...map });
|
|
13719
14618
|
}
|
|
13720
14619
|
|
|
14620
|
+
/** Select client tool calls that are ready for browser-side resolution. */
|
|
14621
|
+
function selectPendingClientToolCalls(input) {
|
|
14622
|
+
if (input.isLoading)
|
|
14623
|
+
return [];
|
|
14624
|
+
return input.toolCalls.filter((tc) => input.catalogNames.has(tc.name) &&
|
|
14625
|
+
tc.result === undefined &&
|
|
14626
|
+
!input.resolvedIds.has(tc.id));
|
|
14627
|
+
}
|
|
14628
|
+
|
|
13721
14629
|
// SPDX-License-Identifier: MIT
|
|
13722
14630
|
/**
|
|
13723
14631
|
* Build an in-memory {@link Agent} for tests and stories — no transport, no
|
|
@@ -13728,8 +14636,10 @@ function tools(map) {
|
|
|
13728
14636
|
* @returns A {@link MockAgent} satisfying the full `Agent` contract.
|
|
13729
14637
|
* @example
|
|
13730
14638
|
* ```ts
|
|
14639
|
+
* import { staticDelivery } from '@threadplane/chat';
|
|
14640
|
+
*
|
|
13731
14641
|
* const agent = mockAgent({
|
|
13732
|
-
* messages: [{ id: '1', role: 'assistant', content: 'Hi' }],
|
|
14642
|
+
* messages: [{ id: '1', role: 'assistant', content: 'Hi', delivery: staticDelivery('1') }],
|
|
13733
14643
|
* isLoading: true,
|
|
13734
14644
|
* });
|
|
13735
14645
|
* ```
|
|
@@ -13785,5 +14695,5 @@ function mockAgent(opts = {}) {
|
|
|
13785
14695
|
* Generated bundle index. Do not edit.
|
|
13786
14696
|
*/
|
|
13787
14697
|
|
|
13788
|
-
export { A2uiAudioPlayerComponent, A2uiButtonComponent, A2uiCardComponent, A2uiCheckBoxComponent, A2uiColumnComponent, A2uiDateTimeInputComponent, A2uiDividerComponent, A2uiIconComponent, A2uiImageComponent, A2uiListComponent, A2uiModalComponent, A2uiMultipleChoiceComponent, A2uiRowComponent, A2uiSliderComponent, A2uiSurfaceComponent, A2uiTabsComponent, A2uiTextComponent, A2uiTextFieldComponent, A2uiVideoComponent, AGENT_ERROR_MESSAGES, AgentError, CHAT_CONFIG, CHAT_LIFECYCLE, ChatApprovalCardComponent, ChatCitationCardTemplateDirective, ChatCitationPreviewComponent, ChatCitationsCardComponent, ChatCitationsComponent, ChatComponent, ChatConfirmDialogComponent, ChatConnectedOverlayDirective, ChatErrorComponent, ChatGenerativeUiComponent, ChatGenuiSkeletonComponent, ChatHistorySearchPaletteComponent, ChatInputComponent, ChatInterruptComponent, ChatInterruptPanelComponent, ChatLauncherButtonComponent, ChatMessageActionsComponent, ChatMessageComponent, ChatMessageListComponent, ChatOverflowMenuComponent, ChatOverlayOriginDirective, ChatPopupComponent, ChatProjectListComponent, ChatReasoningComponent, ChatScrollBubbleComponent, ChatSelectComponent, ChatSidebarComponent, ChatSidenavComponent, ChatSidenavScrimComponent, ChatStreamingMdComponent, ChatSubagentCardComponent, ChatSubagentsComponent, ChatSuggestionsComponent, ChatThreadListComponent, ChatTimelineComponent, ChatTimelineSliderComponent, ChatToolCallCardComponent, ChatToolCallTemplateDirective, ChatToolCallsComponent, ChatToolViewsComponent, ChatTraceComponent, ChatTypingIndicatorComponent, ChatWelcomeComponent, ChatWelcomeSuggestionComponent, ChatWindowComponent, CitationsResolverService, IS_HEADER_ROW, MARKDOWN_VIEW_REGISTRY, MarkdownAutolinkComponent, MarkdownBlockquoteComponent, MarkdownChildrenComponent, MarkdownCitationReferenceComponent, MarkdownCodeBlockComponent, MarkdownDocumentComponent, MarkdownEmphasisComponent, MarkdownHardBreakComponent, MarkdownHeadingComponent, MarkdownHtmlComponent, MarkdownImageComponent, MarkdownInlineCodeComponent, MarkdownLinkComponent, MarkdownListComponent, MarkdownListItemComponent, MarkdownMathComponent, MarkdownParagraphComponent, MarkdownSoftBreakComponent, MarkdownStrikethroughComponent, MarkdownStrongComponent, MarkdownTableCellComponent, MarkdownTableComponent, MarkdownTableRowComponent, MarkdownTextComponent, MarkdownThematicBreakComponent, MessageTemplateDirective, a2uiBasicCatalog, action, ask, buildA2uiActionMessage, cacheplaneMarkdownViews, citationTypeLabel, createA2uiSurfaceStore, createAgentRef, createContentClassifier, createParseTreeStore, createPartialArgsBridge, deriveDomain, deriveJsonSchema, deriveMonogram, deriveSourceType, emitBinding, executeFunctionTool, extractErrorMessage, formatDuration, formatPublished, getInterrupt, getMessageType, injectThreadRouting, isAbortError, isAssistantMessage, isSystemMessage, isToolMessage, isTyping, isUserMessage, messageContent, mockAgent, monogramColor, monogramHue, normalizeEnvelopeArgs, normalizeViewEntry, provideChat, renderMarkdown, startClientToolExecutor, statusColor, submitMessage, toAgentError, toClientToolSpecs, tools, validateArgs, view };
|
|
14698
|
+
export { A2uiAudioPlayerComponent, A2uiButtonComponent, A2uiCardComponent, A2uiCheckBoxComponent, A2uiColumnComponent, A2uiDateTimeInputComponent, A2uiDividerComponent, A2uiIconComponent, A2uiImageComponent, A2uiListComponent, A2uiModalComponent, A2uiMultipleChoiceComponent, A2uiRowComponent, A2uiSliderComponent, A2uiSurfaceComponent, A2uiTabsComponent, A2uiTextComponent, A2uiTextFieldComponent, A2uiVideoComponent, AGENT_ERROR_MESSAGES, AgentError, CHAT_CONFIG, CHAT_LIFECYCLE, ChatApprovalCardComponent, ChatCitationCardTemplateDirective, ChatCitationPreviewComponent, ChatCitationsCardComponent, ChatCitationsComponent, ChatComponent, ChatConfirmDialogComponent, ChatConnectedOverlayDirective, ChatErrorComponent, ChatGenerativeUiComponent, ChatGenuiSkeletonComponent, ChatHistorySearchPaletteComponent, ChatInputComponent, ChatInterruptComponent, ChatInterruptPanelComponent, ChatLauncherButtonComponent, ChatMessageActionsComponent, ChatMessageComponent, ChatMessageListComponent, ChatOverflowMenuComponent, ChatOverlayOriginDirective, ChatPopupComponent, ChatProjectListComponent, ChatReasoningComponent, ChatScrollBubbleComponent, ChatSelectComponent, ChatSidebarComponent, ChatSidenavComponent, ChatSidenavScrimComponent, ChatStreamingMdComponent, ChatSubagentCardComponent, ChatSubagentsComponent, ChatSuggestionsComponent, ChatThreadListComponent, ChatTimelineComponent, ChatTimelineSliderComponent, ChatToolCallCardComponent, ChatToolCallTemplateDirective, ChatToolCallsComponent, ChatToolViewsComponent, ChatTraceComponent, ChatTypingIndicatorComponent, ChatWelcomeComponent, ChatWelcomeSuggestionComponent, ChatWindowComponent, CitationsResolverService, IS_HEADER_ROW, MARKDOWN_VIEW_REGISTRY, MarkdownAutolinkComponent, MarkdownBlockquoteComponent, MarkdownChildrenComponent, MarkdownCitationReferenceComponent, MarkdownCodeBlockComponent, MarkdownDocumentComponent, MarkdownEmphasisComponent, MarkdownHardBreakComponent, MarkdownHeadingComponent, MarkdownHtmlComponent, MarkdownImageComponent, MarkdownInlineCodeComponent, MarkdownLinkComponent, MarkdownListComponent, MarkdownListItemComponent, MarkdownMathComponent, MarkdownParagraphComponent, MarkdownSoftBreakComponent, MarkdownStrikethroughComponent, MarkdownStrongComponent, MarkdownTableCellComponent, MarkdownTableComponent, MarkdownTableRowComponent, MarkdownTextComponent, MarkdownThematicBreakComponent, MessageTemplateDirective, STREAMING_MARKDOWN_CONTRACT_VIOLATION_POLICY, a2uiBasicCatalog, action, ask, buildA2uiActionMessage, cacheplaneMarkdownViews, cancelledClientToolResult, citationSourceVisual, citationTypeLabel, citationTypeMeta, clientToolGuardFailureResult, completeDelivery, createA2uiSurfaceStore, createAgentRef, createContentClassifier, createParseTreeStore, createPartialArgsBridge, defaultInterruptedClientToolResult, deriveDomain, deriveJsonSchema, deriveMonogram, deriveSourceType, emitBinding, executeFunctionTool, extractErrorMessage, formatDuration, formatPublished, getInterrupt, getMessageType, injectThreadRouting, isAbortError, isAssistantMessage, isSystemMessage, isToolMessage, isTyping, isUserMessage, markdownDocument, messageContent, mockAgent, monogramColor, monogramHue, normalizeEnvelopeArgs, normalizeViewEntry, provideChat, renderMarkdown, selectPendingClientToolCalls, shouldClaimBeforeExecute, startClientToolExecutor, staticDelivery, statusColor, streamingDelivery, submitMessage, toAgentError, toClientToolSpecs, tools, validateArgs, view };
|
|
13789
14699
|
//# sourceMappingURL=threadplane-chat.mjs.map
|