@trismegisto/spine 3.3.7 → 3.3.8
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/fesm2022/{trismegisto-spine-layout-ai-agent-chat.component-LlxtxNA5.mjs → trismegisto-spine-layout-ai-agent-chat.component-Brh0_LS9.mjs} +4 -4
- package/fesm2022/trismegisto-spine-layout-ai-agent-chat.component-Brh0_LS9.mjs.map +1 -0
- package/fesm2022/{trismegisto-spine-layout-suggestions-page.component-BEGFNlvw.mjs → trismegisto-spine-layout-suggestions-page.component-Cj4KgMj3.mjs} +2 -2
- package/fesm2022/{trismegisto-spine-layout-suggestions-page.component-BEGFNlvw.mjs.map → trismegisto-spine-layout-suggestions-page.component-Cj4KgMj3.mjs.map} +1 -1
- package/fesm2022/{trismegisto-spine-layout-trismegisto-spine-layout-D3vetDC_.mjs → trismegisto-spine-layout-trismegisto-spine-layout-UM7CC7Sj.mjs} +145 -32
- package/fesm2022/trismegisto-spine-layout-trismegisto-spine-layout-UM7CC7Sj.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-layout.mjs +1 -1
- package/package.json +6 -6
- package/fesm2022/trismegisto-spine-layout-ai-agent-chat.component-LlxtxNA5.mjs.map +0 -1
- package/fesm2022/trismegisto-spine-layout-trismegisto-spine-layout-D3vetDC_.mjs.map +0 -1
|
@@ -1928,7 +1928,10 @@ const RATE_MUTATION = `mutation ($input: RateAgentMessageInput!) {
|
|
|
1928
1928
|
const CONVERSATION_QUERY = `query ($conversationId: ID!) {
|
|
1929
1929
|
agentConversation(conversationId: $conversationId) { status data { role text steps { tool title ok detail } } }
|
|
1930
1930
|
}`;
|
|
1931
|
-
const AGENT_QUERY = `query { agent { status data { suggestions } } }`;
|
|
1931
|
+
const AGENT_QUERY = `query { agent { status data { title suggestions greeting { title text } } } }`;
|
|
1932
|
+
const REFRESH_MUTATION = `mutation ($conversationId: ID!) {
|
|
1933
|
+
refreshAgentCredential(conversationId: $conversationId) { status message }
|
|
1934
|
+
}`;
|
|
1932
1935
|
/**
|
|
1933
1936
|
* Assina os eventos de uma conversa e devolve a função que encerra a assinatura. Usa o WebSocket do navegador, com o
|
|
1934
1937
|
* protocolo do graphql-ws: o shell também atende apps sem GraphQL, que não têm o pacote `graphql-ws` instalado.
|
|
@@ -1996,15 +1999,41 @@ async function rateAgentMessage(url, token, variables, messageIndex, rating, cor
|
|
|
1996
1999
|
const body = await response.json();
|
|
1997
2000
|
return body?.data?.rateAgentMessage ?? { status: response.status >= 400 ? response.status : 500, message: '' };
|
|
1998
2001
|
}
|
|
1999
|
-
/**
|
|
2000
|
-
|
|
2002
|
+
/** Gateway fora do ar ou com erro: vale tentar de novo. Nunca chega à tela. */
|
|
2003
|
+
class GatewayUnavailable extends Error {
|
|
2004
|
+
}
|
|
2005
|
+
/**
|
|
2006
|
+
* O agente desta pessoa, com as perguntas prontas dele. `null` quando o gateway responde que ela não tem agente: o app não
|
|
2007
|
+
* tem um, ou a pessoa está fora dos grupos dele, ou o token não é aceito. Falha de rede ou do gateway sobe como exceção,
|
|
2008
|
+
* para quem chama tentar de novo.
|
|
2009
|
+
*/
|
|
2010
|
+
async function fetchAgent(url, token) {
|
|
2001
2011
|
const response = await fetch(url, {
|
|
2002
2012
|
method: 'POST',
|
|
2003
2013
|
headers: { 'content-type': 'application/json', [TOKEN_HEADER]: token },
|
|
2004
2014
|
body: JSON.stringify({ query: AGENT_QUERY }),
|
|
2005
2015
|
});
|
|
2016
|
+
if (response.status >= 500)
|
|
2017
|
+
throw new GatewayUnavailable();
|
|
2006
2018
|
const body = await response.json();
|
|
2007
|
-
|
|
2019
|
+
const refused = (body?.errors ?? []).some((error) => [401, 403, 'UNAUTHENTICATED', 'FORBIDDEN'].includes(error?.extensions?.code));
|
|
2020
|
+
const envelope = body?.data?.agent;
|
|
2021
|
+
if (refused || !envelope || (envelope.status ?? 200) >= 400 || !envelope.data) {
|
|
2022
|
+
if (!refused && !envelope && body?.errors?.length)
|
|
2023
|
+
throw new GatewayUnavailable();
|
|
2024
|
+
return null;
|
|
2025
|
+
}
|
|
2026
|
+
return { title: envelope.data.title, suggestions: envelope.data.suggestions ?? [], greeting: envelope.data.greeting };
|
|
2027
|
+
}
|
|
2028
|
+
/** Leva o token renovado à resposta em andamento. Falha aqui não muda nada na tela: a resposta conclui com o que tiver. */
|
|
2029
|
+
async function refreshAgentCredential(url, token, variables) {
|
|
2030
|
+
const response = await fetch(url, {
|
|
2031
|
+
method: 'POST',
|
|
2032
|
+
headers: { 'content-type': 'application/json', [TOKEN_HEADER]: token },
|
|
2033
|
+
body: JSON.stringify({ query: REFRESH_MUTATION, variables }),
|
|
2034
|
+
});
|
|
2035
|
+
const body = await response.json();
|
|
2036
|
+
return body?.data?.refreshAgentCredential?.status ?? response.status;
|
|
2008
2037
|
}
|
|
2009
2038
|
/** As perguntas e respostas de uma conversa que já existe; vazia se ela expirou. */
|
|
2010
2039
|
async function fetchAgentConversation(url, token, variables) {
|
|
@@ -2020,6 +2049,12 @@ async function fetchAgentConversation(url, token, variables) {
|
|
|
2020
2049
|
// Teto para o agente dar sinal de vida; acima do limite de uma execução no backend.
|
|
2021
2050
|
const SILENCE_LIMIT_MS = 200_000;
|
|
2022
2051
|
const STORAGE_PREFIX = 'spine-ai-agent:conversation:';
|
|
2052
|
+
// Sem token ainda ou com o gateway fora: novas tentativas em 2, 4 e 6 s, e então desiste até a próxima tela.
|
|
2053
|
+
const AVAILABILITY_RETRIES = 3;
|
|
2054
|
+
const AVAILABILITY_RETRY_MS = 2_000;
|
|
2055
|
+
// De quanto em quanto tempo confere se o login trocou o token durante uma resposta. O agente começa a procurar o novo um
|
|
2056
|
+
// minuto antes do antigo vencer, então há folga de sobra.
|
|
2057
|
+
const CREDENTIAL_CHECK_MS = 10_000;
|
|
2023
2058
|
const PLACEMENT_KEY = 'spine-ai-agent:placement';
|
|
2024
2059
|
// O gateway fecha a conexão quando o token vence, e a rede também cai: a resposta continua no backend. Reconecta com o token atual.
|
|
2025
2060
|
const RECONNECT_ATTEMPTS = 5;
|
|
@@ -2065,7 +2100,13 @@ class SpineAiAgentService {
|
|
|
2065
2100
|
this.auth = inject(AuthorizationService);
|
|
2066
2101
|
this.text = inject(SPINE_MESSAGES).aiAgentChat;
|
|
2067
2102
|
this.enabled = !!this.config;
|
|
2068
|
-
|
|
2103
|
+
/**
|
|
2104
|
+
* O gateway confirmou que esta pessoa tem um agente: só então o balão e o ícone do cabeçalho aparecem. App sem agente, pessoa
|
|
2105
|
+
* fora dos grupos dele ou gateway fora do ar: nada aparece, em vez de um chat que só falha.
|
|
2106
|
+
*/
|
|
2107
|
+
this.available = signal(false, ...(ngDevMode ? [{ debugName: "available" }] : /* istanbul ignore next */ []));
|
|
2108
|
+
/** Nome e saudação: os da definição do agente, que o gateway devolve; sem eles, os do app; sem estes, os padrões. */
|
|
2109
|
+
this.title = signal(this.config?.title || this.text.title, ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
2069
2110
|
this.theme = inject(ThemeService);
|
|
2070
2111
|
this.avatarSources = resolveSpineImage(this.config?.avatar, SPINE_DEFAULT_AGENT_AVATAR);
|
|
2071
2112
|
this.thinkingSources = resolveSpineImage(this.config?.avatarThinking, null);
|
|
@@ -2076,8 +2117,8 @@ class SpineAiAgentService {
|
|
|
2076
2117
|
this.avatar = computed(() => this.pickImage(this.avatarSources), ...(ngDevMode ? [{ debugName: "avatar" }] : /* istanbul ignore next */ []));
|
|
2077
2118
|
/** A figura do agente, para o tema atual. */
|
|
2078
2119
|
this.image = computed(() => this.pickImage(this.imageSources), ...(ngDevMode ? [{ debugName: "image" }] : /* istanbul ignore next */ []));
|
|
2079
|
-
this.greetingTitle = this.config?.greeting?.title || this.text.greetingTitle;
|
|
2080
|
-
this.greetingText = this.config?.greeting?.text || this.text.greetingText;
|
|
2120
|
+
this.greetingTitle = signal(this.config?.greeting?.title || this.text.greetingTitle, ...(ngDevMode ? [{ debugName: "greetingTitle" }] : /* istanbul ignore next */ []));
|
|
2121
|
+
this.greetingText = signal(this.config?.greeting?.text || this.text.greetingText, ...(ngDevMode ? [{ debugName: "greetingText" }] : /* istanbul ignore next */ []));
|
|
2081
2122
|
this.entries = signal([], ...(ngDevMode ? [{ debugName: "entries" }] : /* istanbul ignore next */ []));
|
|
2082
2123
|
this.running = signal(false, ...(ngDevMode ? [{ debugName: "running" }] : /* istanbul ignore next */ []));
|
|
2083
2124
|
/** Perguntas prontas que o agente oferece, mostradas na conversa vazia. */
|
|
@@ -2107,6 +2148,10 @@ class SpineAiAgentService {
|
|
|
2107
2148
|
/** Mensagens que o backend já tinha guardado antes desta pergunta, para reconhecer a resposta nova. */
|
|
2108
2149
|
this.savedBefore = 0;
|
|
2109
2150
|
this.suggestionsLoaded = false;
|
|
2151
|
+
this.availabilityTries = 0;
|
|
2152
|
+
/** O token que a resposta em andamento tem; quando o login troca o da pessoa, o novo é mandado a ela. */
|
|
2153
|
+
this.credentialSent = null;
|
|
2154
|
+
this.credentialTimer = null;
|
|
2110
2155
|
}
|
|
2111
2156
|
/** Como no logo do header: no escuro vale `dark`, e se ele falhar volta para `light`. */
|
|
2112
2157
|
pickImage(sources) {
|
|
@@ -2143,13 +2188,45 @@ class SpineAiAgentService {
|
|
|
2143
2188
|
this.restored = true;
|
|
2144
2189
|
this.send(question);
|
|
2145
2190
|
}
|
|
2191
|
+
/**
|
|
2192
|
+
* Pergunta ao gateway se esta pessoa tem um agente, e já traz as sugestões. A resposta "não tem" é definitiva nesta tela;
|
|
2193
|
+
* sem token ainda, ou com o gateway fora, tenta de novo algumas vezes, cada vez mais devagar.
|
|
2194
|
+
*/
|
|
2195
|
+
checkAvailability() {
|
|
2196
|
+
if (!this.config || this.available())
|
|
2197
|
+
return;
|
|
2198
|
+
const token = this.auth.getToken();
|
|
2199
|
+
if (!token) {
|
|
2200
|
+
this.retryAvailability();
|
|
2201
|
+
return;
|
|
2202
|
+
}
|
|
2203
|
+
fetchAgent(this.config.http, token).then((agent) => {
|
|
2204
|
+
if (!agent)
|
|
2205
|
+
return;
|
|
2206
|
+
if (agent.title)
|
|
2207
|
+
this.title.set(agent.title);
|
|
2208
|
+
if (agent.greeting?.title)
|
|
2209
|
+
this.greetingTitle.set(agent.greeting.title);
|
|
2210
|
+
if (agent.greeting?.text)
|
|
2211
|
+
this.greetingText.set(agent.greeting.text);
|
|
2212
|
+
this.suggestions.set(agent.suggestions);
|
|
2213
|
+
this.suggestionsLoaded = true;
|
|
2214
|
+
this.available.set(true);
|
|
2215
|
+
}, () => this.retryAvailability());
|
|
2216
|
+
}
|
|
2217
|
+
retryAvailability() {
|
|
2218
|
+
if (this.availabilityTries >= AVAILABILITY_RETRIES)
|
|
2219
|
+
return;
|
|
2220
|
+
this.availabilityTries += 1;
|
|
2221
|
+
setTimeout(() => this.checkAvailability(), AVAILABILITY_RETRY_MS * this.availabilityTries);
|
|
2222
|
+
}
|
|
2146
2223
|
/** Busca as sugestões uma vez. Sem elas o chat funciona igual, então a falha não aparece para a pessoa. */
|
|
2147
2224
|
loadSuggestions() {
|
|
2148
2225
|
const token = this.auth.getToken();
|
|
2149
2226
|
if (!this.config || !token || this.suggestionsLoaded)
|
|
2150
2227
|
return;
|
|
2151
2228
|
this.suggestionsLoaded = true;
|
|
2152
|
-
|
|
2229
|
+
fetchAgent(this.config.http, token).then((agent) => this.suggestions.set(agent?.suggestions ?? []), () => { this.suggestionsLoaded = false; });
|
|
2153
2230
|
}
|
|
2154
2231
|
/** Traz de volta a conversa guardada, uma vez. Se falhar, ou se ela expirou, o chat só começa vazio. */
|
|
2155
2232
|
restoreConversation() {
|
|
@@ -2209,10 +2286,10 @@ class SpineAiAgentService {
|
|
|
2209
2286
|
const now = new Date();
|
|
2210
2287
|
const person = this.auth.profile?.name;
|
|
2211
2288
|
const pdf = buildTranscriptPdf({
|
|
2212
|
-
title: this.title,
|
|
2289
|
+
title: this.title(),
|
|
2213
2290
|
subtitle: [this.spine?.appName, person, now.toLocaleString()].filter(Boolean).join(' · '),
|
|
2214
2291
|
personLabel: person || this.text.you,
|
|
2215
|
-
agentLabel: this.title,
|
|
2292
|
+
agentLabel: this.title(),
|
|
2216
2293
|
queriesLabel: this.text.transcriptQueries,
|
|
2217
2294
|
failedLabel: this.text.transcriptStepFailed,
|
|
2218
2295
|
pageLabel: this.text.transcriptPage,
|
|
@@ -2226,7 +2303,7 @@ class SpineAiAgentService {
|
|
|
2226
2303
|
const url = URL.createObjectURL(new Blob([pdf.slice().buffer], { type: 'application/pdf' }));
|
|
2227
2304
|
const link = document.createElement('a');
|
|
2228
2305
|
link.href = url;
|
|
2229
|
-
link.download = transcriptFileName(this.title, this.text.transcriptFile, now);
|
|
2306
|
+
link.download = transcriptFileName(this.title(), this.text.transcriptFile, now);
|
|
2230
2307
|
link.click();
|
|
2231
2308
|
// O navegador só lê o endereço depois do clique: revogar na hora cancelaria o download em alguns deles.
|
|
2232
2309
|
setTimeout(() => URL.revokeObjectURL(url), 10_000);
|
|
@@ -2289,6 +2366,7 @@ class SpineAiAgentService {
|
|
|
2289
2366
|
return;
|
|
2290
2367
|
}
|
|
2291
2368
|
this.messageSent = true;
|
|
2369
|
+
this.watchCredential(http, variables, token);
|
|
2292
2370
|
sendAgentMessage(http, token, variables, question).then(({ status, message }) => { if (status >= 400)
|
|
2293
2371
|
this.fail(answerId, message || this.text.sendError); }, () => this.fail(answerId, this.text.sendError));
|
|
2294
2372
|
}
|
|
@@ -2382,7 +2460,27 @@ class SpineAiAgentService {
|
|
|
2382
2460
|
}));
|
|
2383
2461
|
this.finish();
|
|
2384
2462
|
}
|
|
2463
|
+
/**
|
|
2464
|
+
* O login renova o token da pessoa a cada poucos minutos, mas a resposta começou com o do envio e pode levar mais tempo que
|
|
2465
|
+
* ele. Enquanto ela está em andamento, cada token novo vai para o agente, que troca antes da próxima consulta.
|
|
2466
|
+
*/
|
|
2467
|
+
watchCredential(http, variables, token) {
|
|
2468
|
+
this.credentialSent = token;
|
|
2469
|
+
if (this.credentialTimer)
|
|
2470
|
+
clearInterval(this.credentialTimer);
|
|
2471
|
+
this.credentialTimer = setInterval(() => {
|
|
2472
|
+
const current = this.auth.getToken();
|
|
2473
|
+
if (!current || current === this.credentialSent)
|
|
2474
|
+
return;
|
|
2475
|
+
this.credentialSent = current;
|
|
2476
|
+
refreshAgentCredential(http, current, variables).catch(() => undefined);
|
|
2477
|
+
}, CREDENTIAL_CHECK_MS);
|
|
2478
|
+
}
|
|
2385
2479
|
finish() {
|
|
2480
|
+
if (this.credentialTimer)
|
|
2481
|
+
clearInterval(this.credentialTimer);
|
|
2482
|
+
this.credentialTimer = null;
|
|
2483
|
+
this.credentialSent = null;
|
|
2386
2484
|
if (this.silence)
|
|
2387
2485
|
clearTimeout(this.silence);
|
|
2388
2486
|
if (this.reconnectTimer)
|
|
@@ -2428,12 +2526,12 @@ class SpineAiAgentDockButtonComponent {
|
|
|
2428
2526
|
}
|
|
2429
2527
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SpineAiAgentDockButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2430
2528
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: SpineAiAgentDockButtonComponent, isStandalone: true, selector: "spine-ai-agent-dock-button", ngImport: i0, template: `
|
|
2431
|
-
@if (agent.
|
|
2529
|
+
@if (agent.available() && agent.docked()) {
|
|
2432
2530
|
<hm-icon-button
|
|
2433
2531
|
[class]="dockClass"
|
|
2434
2532
|
emphasis="subtle"
|
|
2435
2533
|
icon="chat-bubble"
|
|
2436
|
-
[label]="agent.panelOpen() ? text.close : agent.title"
|
|
2534
|
+
[label]="agent.panelOpen() ? text.close : agent.title()"
|
|
2437
2535
|
(clicked)="agent.togglePanel()"
|
|
2438
2536
|
/>
|
|
2439
2537
|
}
|
|
@@ -2446,12 +2544,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
2446
2544
|
imports: [IconButtonComponent],
|
|
2447
2545
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2448
2546
|
template: `
|
|
2449
|
-
@if (agent.
|
|
2547
|
+
@if (agent.available() && agent.docked()) {
|
|
2450
2548
|
<hm-icon-button
|
|
2451
2549
|
[class]="dockClass"
|
|
2452
2550
|
emphasis="subtle"
|
|
2453
2551
|
icon="chat-bubble"
|
|
2454
|
-
[label]="agent.panelOpen() ? text.close : agent.title"
|
|
2552
|
+
[label]="agent.panelOpen() ? text.close : agent.title()"
|
|
2455
2553
|
(clicked)="agent.togglePanel()"
|
|
2456
2554
|
/>
|
|
2457
2555
|
}
|
|
@@ -7600,7 +7698,7 @@ function registerPage() {
|
|
|
7600
7698
|
route_redirect: SPINE_SUGGESTIONS_PAGE_PATH,
|
|
7601
7699
|
description: text.description,
|
|
7602
7700
|
},
|
|
7603
|
-
load: () => import('./trismegisto-spine-layout-suggestions-page.component-
|
|
7701
|
+
load: () => import('./trismegisto-spine-layout-suggestions-page.component-Cj4KgMj3.mjs').then((m) => m.SpineSuggestionsPageComponent),
|
|
7604
7702
|
});
|
|
7605
7703
|
});
|
|
7606
7704
|
}
|
|
@@ -8752,6 +8850,9 @@ class SpineAiAgentLauncherComponent {
|
|
|
8752
8850
|
this.expanded = signal(readPanelState().expanded === true, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
8753
8851
|
this.chat = signal(null, ...(ngDevMode ? [{ debugName: "chat" }] : /* istanbul ignore next */ []));
|
|
8754
8852
|
this.dragging = signal(false, ...(ngDevMode ? [{ debugName: "dragging" }] : /* istanbul ignore next */ []));
|
|
8853
|
+
this.started = false;
|
|
8854
|
+
// Lido na criação: o efeito que guarda o estado roda antes do balão aparecer e gravaria "fechado" por cima.
|
|
8855
|
+
this.initialPanel = readPanelState();
|
|
8755
8856
|
/** Com o balão na metade de cima da tela, o painel abre para baixo, onde há espaço. */
|
|
8756
8857
|
this.below = computed(() => !this.agent.docked() && (this.agent.position()?.bottom ?? 0) > window.innerHeight / 2, ...(ngDevMode ? [{ debugName: "below" }] : /* istanbul ignore next */ []));
|
|
8757
8858
|
/** O balão é um círculo: o rosto cabe nele, e uma imagem de corpo inteiro cortaria onde não deve. */
|
|
@@ -8786,12 +8887,24 @@ class SpineAiAgentLauncherComponent {
|
|
|
8786
8887
|
if (this.agent.panelOpen())
|
|
8787
8888
|
untracked(() => void this.prepare());
|
|
8788
8889
|
});
|
|
8890
|
+
// O balão só existe depois que o gateway confirma o agente: aí o painel volta como estava e o convite aparece.
|
|
8891
|
+
effect(() => {
|
|
8892
|
+
if (this.agent.available())
|
|
8893
|
+
untracked(() => this.start());
|
|
8894
|
+
});
|
|
8789
8895
|
}
|
|
8790
8896
|
ngOnInit() {
|
|
8897
|
+
if (this.agent.enabled)
|
|
8898
|
+
this.agent.checkAvailability();
|
|
8899
|
+
}
|
|
8900
|
+
start() {
|
|
8901
|
+
if (this.started)
|
|
8902
|
+
return;
|
|
8903
|
+
this.started = true;
|
|
8791
8904
|
// Sem roubar o foco: a pessoa acabou de recarregar a tela, não pediu o chat agora.
|
|
8792
|
-
if (this.
|
|
8905
|
+
if (this.initialPanel.open === true)
|
|
8793
8906
|
this.agent.panelOpen.set(true);
|
|
8794
|
-
if (this.
|
|
8907
|
+
if (this.greetingVisible()) {
|
|
8795
8908
|
this.agent.loadSuggestions();
|
|
8796
8909
|
this.greetingTimer = setTimeout(() => this.closeGreeting(), GREETING_MS);
|
|
8797
8910
|
}
|
|
@@ -8804,7 +8917,7 @@ class SpineAiAgentLauncherComponent {
|
|
|
8804
8917
|
const focus = this.agent.focusOnOpen;
|
|
8805
8918
|
this.agent.focusOnOpen = false;
|
|
8806
8919
|
if (!this.chat()) {
|
|
8807
|
-
const { SpineAiAgentChatComponent } = await import('./trismegisto-spine-layout-ai-agent-chat.component-
|
|
8920
|
+
const { SpineAiAgentChatComponent } = await import('./trismegisto-spine-layout-ai-agent-chat.component-Brh0_LS9.mjs');
|
|
8808
8921
|
this.chat.set(SpineAiAgentChatComponent);
|
|
8809
8922
|
}
|
|
8810
8923
|
this.agent.loadSuggestions();
|
|
@@ -8891,7 +9004,7 @@ class SpineAiAgentLauncherComponent {
|
|
|
8891
9004
|
}
|
|
8892
9005
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.24", ngImport: i0, type: SpineAiAgentLauncherComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8893
9006
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.24", type: SpineAiAgentLauncherComponent, isStandalone: true, selector: "spine-ai-agent-launcher", host: { properties: { "class.spine-agent--docked": "agent.docked()", "class.spine-agent--below": "below()", "style.--spine-agent-end": "agent.position() ? agent.position()!.end + 'px' : null", "style.--spine-agent-bottom": "agent.position() ? agent.position()!.bottom + 'px' : null" } }, ngImport: i0, template: `
|
|
8894
|
-
@if (agent.
|
|
9007
|
+
@if (agent.available()) {
|
|
8895
9008
|
@if (chat(); as component) {
|
|
8896
9009
|
<section
|
|
8897
9010
|
class="spine-agent-panel"
|
|
@@ -8908,7 +9021,7 @@ class SpineAiAgentLauncherComponent {
|
|
|
8908
9021
|
@if (agent.avatarNow(); as avatar) {
|
|
8909
9022
|
<img class="spine-agent-panel__avatar" [src]="avatar" alt="" (error)="agent.imageFailed(avatar)" />
|
|
8910
9023
|
}
|
|
8911
|
-
<h2 class="spine-agent-panel__title" [attr.id]="titleId">{{ agent.title }}</h2>
|
|
9024
|
+
<h2 class="spine-agent-panel__title" [attr.id]="titleId">{{ agent.title() }}</h2>
|
|
8912
9025
|
<hm-icon-button
|
|
8913
9026
|
emphasis="subtle"
|
|
8914
9027
|
size="small"
|
|
@@ -8950,7 +9063,7 @@ class SpineAiAgentLauncherComponent {
|
|
|
8950
9063
|
[class.spine-agent-greeting--after]="greetingAfter()"
|
|
8951
9064
|
[class.spine-agent-greeting--below]="below()"
|
|
8952
9065
|
[class.spine-agent-greeting--figure]="agent.image()"
|
|
8953
|
-
[attr.aria-label]="agent.title"
|
|
9066
|
+
[attr.aria-label]="agent.title()"
|
|
8954
9067
|
(pointerdown)="$event.stopPropagation()"
|
|
8955
9068
|
(mouseenter)="keepGreeting()"
|
|
8956
9069
|
(focusin)="keepGreeting()"
|
|
@@ -8960,10 +9073,10 @@ class SpineAiAgentLauncherComponent {
|
|
|
8960
9073
|
}
|
|
8961
9074
|
<div class="spine-agent-greeting__content">
|
|
8962
9075
|
<div class="spine-agent-greeting__head">
|
|
8963
|
-
<p class="spine-agent-greeting__title">{{ agent.greetingTitle }}</p>
|
|
9076
|
+
<p class="spine-agent-greeting__title">{{ agent.greetingTitle() }}</p>
|
|
8964
9077
|
<hm-icon-button emphasis="subtle" size="small" icon="times" [label]="text.greetingClose" (clicked)="closeGreeting()" />
|
|
8965
9078
|
</div>
|
|
8966
|
-
<p class="spine-agent-greeting__text">{{ agent.greetingText }}</p>
|
|
9079
|
+
<p class="spine-agent-greeting__text">{{ agent.greetingText() }}</p>
|
|
8967
9080
|
@if (greetingSuggestions().length) {
|
|
8968
9081
|
<hm-prompt-suggestions [suggestions]="greetingSuggestions()" (chosen)="askFromGreeting($event)" />
|
|
8969
9082
|
}
|
|
@@ -8972,7 +9085,7 @@ class SpineAiAgentLauncherComponent {
|
|
|
8972
9085
|
}
|
|
8973
9086
|
<hm-fab
|
|
8974
9087
|
[fixed]="false"
|
|
8975
|
-
[label]="agent.panelOpen() ? text.close : agent.title"
|
|
9088
|
+
[label]="agent.panelOpen() ? text.close : agent.title()"
|
|
8976
9089
|
[icon]="agent.panelOpen() ? 'times' : fabImage() ? '' : 'chat-bubble'"
|
|
8977
9090
|
[expanded]="agent.panelOpen()"
|
|
8978
9091
|
[controls]="panelId"
|
|
@@ -9006,7 +9119,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
9006
9119
|
'[style.--spine-agent-end]': "agent.position() ? agent.position()!.end + 'px' : null",
|
|
9007
9120
|
'[style.--spine-agent-bottom]': "agent.position() ? agent.position()!.bottom + 'px' : null",
|
|
9008
9121
|
}, template: `
|
|
9009
|
-
@if (agent.
|
|
9122
|
+
@if (agent.available()) {
|
|
9010
9123
|
@if (chat(); as component) {
|
|
9011
9124
|
<section
|
|
9012
9125
|
class="spine-agent-panel"
|
|
@@ -9023,7 +9136,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
9023
9136
|
@if (agent.avatarNow(); as avatar) {
|
|
9024
9137
|
<img class="spine-agent-panel__avatar" [src]="avatar" alt="" (error)="agent.imageFailed(avatar)" />
|
|
9025
9138
|
}
|
|
9026
|
-
<h2 class="spine-agent-panel__title" [attr.id]="titleId">{{ agent.title }}</h2>
|
|
9139
|
+
<h2 class="spine-agent-panel__title" [attr.id]="titleId">{{ agent.title() }}</h2>
|
|
9027
9140
|
<hm-icon-button
|
|
9028
9141
|
emphasis="subtle"
|
|
9029
9142
|
size="small"
|
|
@@ -9065,7 +9178,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
9065
9178
|
[class.spine-agent-greeting--after]="greetingAfter()"
|
|
9066
9179
|
[class.spine-agent-greeting--below]="below()"
|
|
9067
9180
|
[class.spine-agent-greeting--figure]="agent.image()"
|
|
9068
|
-
[attr.aria-label]="agent.title"
|
|
9181
|
+
[attr.aria-label]="agent.title()"
|
|
9069
9182
|
(pointerdown)="$event.stopPropagation()"
|
|
9070
9183
|
(mouseenter)="keepGreeting()"
|
|
9071
9184
|
(focusin)="keepGreeting()"
|
|
@@ -9075,10 +9188,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
9075
9188
|
}
|
|
9076
9189
|
<div class="spine-agent-greeting__content">
|
|
9077
9190
|
<div class="spine-agent-greeting__head">
|
|
9078
|
-
<p class="spine-agent-greeting__title">{{ agent.greetingTitle }}</p>
|
|
9191
|
+
<p class="spine-agent-greeting__title">{{ agent.greetingTitle() }}</p>
|
|
9079
9192
|
<hm-icon-button emphasis="subtle" size="small" icon="times" [label]="text.greetingClose" (clicked)="closeGreeting()" />
|
|
9080
9193
|
</div>
|
|
9081
|
-
<p class="spine-agent-greeting__text">{{ agent.greetingText }}</p>
|
|
9194
|
+
<p class="spine-agent-greeting__text">{{ agent.greetingText() }}</p>
|
|
9082
9195
|
@if (greetingSuggestions().length) {
|
|
9083
9196
|
<hm-prompt-suggestions [suggestions]="greetingSuggestions()" (chosen)="askFromGreeting($event)" />
|
|
9084
9197
|
}
|
|
@@ -9087,7 +9200,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
9087
9200
|
}
|
|
9088
9201
|
<hm-fab
|
|
9089
9202
|
[fixed]="false"
|
|
9090
|
-
[label]="agent.panelOpen() ? text.close : agent.title"
|
|
9203
|
+
[label]="agent.panelOpen() ? text.close : agent.title()"
|
|
9091
9204
|
[icon]="agent.panelOpen() ? 'times' : fabImage() ? '' : 'chat-bubble'"
|
|
9092
9205
|
[expanded]="agent.panelOpen()"
|
|
9093
9206
|
[controls]="panelId"
|
|
@@ -9779,4 +9892,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.24", ngImpo
|
|
|
9779
9892
|
*/
|
|
9780
9893
|
|
|
9781
9894
|
export { SpineAppTokensService as $, AppLauncherComponent as A, SPINE_INBOX_POLL_MS as B, SPINE_INBOX_SOURCES as C, SPINE_MARKDOWN_PURIFY_CONFIG as D, SPINE_PREFERENCES_SAVE_DELAY_MS as E, SPINE_RATING_COMMENT_MAX as F, SPINE_RATING_SCORE_MAX as G, HeaderComponent as H, SPINE_SETTINGS_ALIASES as I, SPINE_SETTINGS_KEYS as J, SPINE_SETTINGS_SECTIONS as K, LayoutComponent as L, McpConnectComponent as M, NEW_SCREEN_VALUE as N, SPINE_SUGGESTIONS_PAGE_ID as O, SPINE_SUGGESTION_LIMITS as P, SPINE_SUGGESTION_PUBLIC_SORTS as Q, SPINE_SUGGESTION_PUBLIC_STATUSES as R, SpineSuggestionsService as S, SPINE_SUGGESTION_STATUS_ICONS as T, SPINE_WORKSPACE_LIMITS as U, SettingsPanelComponent as V, ShortcutService as W, ShortcutsCheatsheetComponent as X, SidebarComponent as Y, SpineAccountPreferencesService as Z, SpineAccountSecurityService as _, SpineInboxService as a, SpineBrandComponent as a0, SpineConnectionBannerComponent as a1, SpineDocsComponent as a2, SpineDocsService as a3, SpineIdleService as a4, SpineIdleWarningComponent as a5, SpineInboxButtonComponent as a6, SpineInitialSetupComponent as a7, SpineInitialSetupService as a8, SpineLogoutService as a9, spineParamsOf as aA, spinePathOf as aB, spineScoreBand as aC, spineStarFills as aD, spineSuggestionsEnabled as aE, spineTagColor as aF, stable as aG, SpineMyGroupsService as aa, SpineNewsComponent as ab, SpineNewsService as ac, SpineNoticesService as ad, SpinePageActionsDirective as ae, SpinePageActionsSlot as af, SpineRatingStarsComponent as ag, SpineRatingsService as ah, SpineSettingsService as ai, SpineStartPageService as aj, SpineUnsavedChangesService as ak, SpineWorkspaceNavService as al, accountErrorCode as am, argosAccountApi as an, buildMcpConfig as ao, effectiveIdleMinutes as ap, idleLimits as aq, isInternalPath as ar, provideSettingsSection as as, provideSpineInboxSource as at, provideSpineSuggestionsPage as au, ratingTargetKey as av, registerSpineUnsavedChanges as aw, resolveSettingsSection as ax, sanitizeSpineMarkdownHtml as ay, spineNormalizeUrl as az, SpineSuggestionChatComponent as b, SPINE_SUGGESTION_STATUS_COLORS as c, SPINE_SUGGESTION_KIND_COLORS as d, SPINE_SUGGESTION_KIND_ICONS as e, SPINE_SUGGESTION_WAITING_COLORS as f, SPINE_SUGGESTION_VISIBLE_SORTS as g, SPINE_SUGGESTION_REASONS as h, SPINE_SUGGESTION_STATUSES as i, SPINE_SUGGESTION_KINDS as j, SPINE_SUGGESTION_WAITING as k, SPINE_TAB as l, SPINE_SUGGESTION_PAGE_PARAM as m, SPINE_SUGGESTION_TAB_PARAM as n, SPINE_SUGGESTION_TAB_CONVERSATION as o, screenName as p, screenModule as q, SPINE_SUGGESTIONS_PAGE_PATH as r, suggestionScreens as s, SpineSuggestionsDialogComponent as t, SpineTagRowComponent as u, SpineAiAgentService as v, SpineMarkdownComponent as w, SPINE_BRAND as x, SPINE_GLOBAL_PREFERENCE_KEYS as y, SPINE_IDLE_WARNING_SECONDS as z };
|
|
9782
|
-
//# sourceMappingURL=trismegisto-spine-layout-trismegisto-spine-layout-
|
|
9895
|
+
//# sourceMappingURL=trismegisto-spine-layout-trismegisto-spine-layout-UM7CC7Sj.mjs.map
|