@things-factory/ai-assistant 10.1.79 → 10.1.81
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/client/components/assistant-chat.ts +102 -13
- package/client/components/assistant-dock.ts +160 -18
- package/client/components/assistant-mode.test.ts +16 -2
- package/client/components/assistant-session-manager.ts +52 -25
- package/client/components/assistant-session-toolbar.ts +4 -2
- package/client/components/chat-echo-dedup.ts +4 -0
- package/client/components/proposal-outcome-line.ts +36 -0
- package/client/components/proposal-request.test.ts +52 -0
- package/client/utils/assistant-navigation.test.ts +38 -0
- package/client/utils/assistant-navigation.ts +6 -0
- package/client/utils/assistant-surface.ts +21 -0
- package/dist-client/components/assistant-chat.d.ts +15 -0
- package/dist-client/components/assistant-chat.js +106 -13
- package/dist-client/components/assistant-chat.js.map +1 -1
- package/dist-client/components/assistant-dock.d.ts +13 -0
- package/dist-client/components/assistant-dock.js +175 -20
- package/dist-client/components/assistant-dock.js.map +1 -1
- package/dist-client/components/assistant-mode.test.js +14 -2
- package/dist-client/components/assistant-mode.test.js.map +1 -1
- package/dist-client/components/assistant-session-manager.d.ts +4 -0
- package/dist-client/components/assistant-session-manager.js +68 -26
- package/dist-client/components/assistant-session-manager.js.map +1 -1
- package/dist-client/components/assistant-session-toolbar.d.ts +1 -0
- package/dist-client/components/assistant-session-toolbar.js +8 -2
- package/dist-client/components/assistant-session-toolbar.js.map +1 -1
- package/dist-client/components/chat-echo-dedup.d.ts +2 -0
- package/dist-client/components/chat-echo-dedup.js +2 -0
- package/dist-client/components/chat-echo-dedup.js.map +1 -1
- package/dist-client/components/proposal-outcome-line.d.ts +29 -0
- package/dist-client/components/proposal-outcome-line.js +15 -0
- package/dist-client/components/proposal-outcome-line.js.map +1 -1
- package/dist-client/components/proposal-request.test.d.ts +1 -0
- package/dist-client/components/proposal-request.test.js +45 -0
- package/dist-client/components/proposal-request.test.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/assistant-navigation.d.ts +6 -0
- package/dist-client/utils/assistant-navigation.js +9 -0
- package/dist-client/utils/assistant-navigation.js.map +1 -0
- package/dist-client/utils/assistant-navigation.test.d.ts +1 -0
- package/dist-client/utils/assistant-navigation.test.js +37 -0
- package/dist-client/utils/assistant-navigation.test.js.map +1 -0
- package/dist-client/utils/assistant-surface.d.ts +19 -0
- package/dist-client/utils/assistant-surface.js.map +1 -1
- package/dist-server/service/assistant-chat-resolver.js +1 -0
- package/dist-server/service/assistant-chat-resolver.js.map +1 -1
- package/dist-server/service/chat-message/chat-message.d.ts +10 -0
- package/dist-server/service/chat-message/chat-message.js +29 -0
- package/dist-server/service/chat-message/chat-message.js.map +1 -1
- package/dist-server/service/chat-message/proposal-outcome.d.ts +8 -0
- package/dist-server/service/chat-message/proposal-outcome.js +35 -1
- package/dist-server/service/chat-message/proposal-outcome.js.map +1 -1
- package/dist-server/service/chat-session/session-inbox.d.ts +7 -0
- package/dist-server/service/chat-session/session-inbox.js +7 -0
- package/dist-server/service/chat-session/session-inbox.js.map +1 -1
- package/dist-server/service/chat-session-resolver.d.ts +1 -0
- package/dist-server/service/chat-session-resolver.js +63 -9
- package/dist-server/service/chat-session-resolver.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/server/service/assistant-chat-resolver.ts +1 -0
- package/server/service/chat-message/chat-message.ts +32 -0
- package/server/service/chat-message/proposal-outcome.test.ts +53 -2
- package/server/service/chat-message/proposal-outcome.ts +33 -0
- package/server/service/chat-session/session-inbox.ts +7 -0
- package/server/service/chat-session-resolver.ts +71 -12
- package/test/assistant-dock.test.ts +8 -3
- package/test/assistant-session-toolbar.test.ts +7 -1
- package/test/open-doors.test.ts +2 -1
- package/test/session-discovery.test.ts +42 -0
- package/translations/en.json +26 -1
- package/translations/ja.json +26 -1
- package/translations/ko.json +26 -1
- package/translations/ms.json +26 -1
- package/translations/zh.json +26 -1
|
@@ -35,6 +35,9 @@ export declare class AssistantDock extends AssistantDock_base {
|
|
|
35
35
|
private showingHistory;
|
|
36
36
|
private conversationView;
|
|
37
37
|
private asking?;
|
|
38
|
+
private screenChanged;
|
|
39
|
+
private navigationNotice;
|
|
40
|
+
private openedIdentity;
|
|
38
41
|
private app;
|
|
39
42
|
/** The kind the person picked; kept while the surface stays the same. */
|
|
40
43
|
private chosenKind;
|
|
@@ -47,6 +50,10 @@ export declare class AssistantDock extends AssistantDock_base {
|
|
|
47
50
|
connectedCallback(): void;
|
|
48
51
|
disconnectedCallback(): void;
|
|
49
52
|
private scopeKey;
|
|
53
|
+
private identityKey;
|
|
54
|
+
private get navigationState();
|
|
55
|
+
private mayLeaveConversation;
|
|
56
|
+
private requestSurface;
|
|
50
57
|
/** The screen changed - a different surface or domain is a different conversation. */
|
|
51
58
|
private follow;
|
|
52
59
|
private open;
|
|
@@ -62,8 +69,14 @@ export declare class AssistantDock extends AssistantDock_base {
|
|
|
62
69
|
private report;
|
|
63
70
|
/** Every proposal ends in exactly one reported outcome - a kind nobody handles is `unavailable`. */
|
|
64
71
|
private onProposal;
|
|
72
|
+
/**
|
|
73
|
+
* "Check result" - asks the surface what became of a requested proposal and reports only what it learns.
|
|
74
|
+
* Nothing is run: a lost answer never turns into a second application (ADR-0097 Q-D4 ④).
|
|
75
|
+
*/
|
|
76
|
+
private onProposalCheck;
|
|
65
77
|
private appendNote;
|
|
66
78
|
private onScenePatch;
|
|
79
|
+
private mayApplyOnScreen;
|
|
67
80
|
private onBoardRevert;
|
|
68
81
|
private onSceneAction;
|
|
69
82
|
private stuckLine;
|
|
@@ -21,6 +21,7 @@ import { setOpenSession, subscribeSessionActivity } from '../utils/assistant-act
|
|
|
21
21
|
import { assistantHomeSurface, currentAssistantSurface, isAnchor, subscribeAssistantSurface } from '../utils/assistant-surface.js';
|
|
22
22
|
import { runProposal } from '../utils/assistant-proposals.js';
|
|
23
23
|
import { holdAssistantAsk, subscribeAssistantAsk, takeAssistantAsk } from '../utils/assistant-ask.js';
|
|
24
|
+
import { surfaceTransition } from '../utils/assistant-navigation.js';
|
|
24
25
|
export const ASSISTANT_DOCK_VIEWPART = 'assistant-dock';
|
|
25
26
|
const t = (key, defaultValue, options = {}) => i18next.t(`ai-assistant.dock.${key}`, { defaultValue, ...options });
|
|
26
27
|
const MODES_QUERY = gql `
|
|
@@ -66,6 +67,9 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
66
67
|
this.failure = '';
|
|
67
68
|
this.showingHistory = false;
|
|
68
69
|
this.conversationView = 0;
|
|
70
|
+
this.screenChanged = false;
|
|
71
|
+
this.navigationNotice = '';
|
|
72
|
+
this.openedIdentity = '';
|
|
69
73
|
this.app = new AppController(this);
|
|
70
74
|
/** The kind the person picked; kept while the surface stays the same. */
|
|
71
75
|
this.chosenKind = '';
|
|
@@ -84,17 +88,21 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
84
88
|
this.failure = next.error;
|
|
85
89
|
}, { getItem: key => sessionStorage.getItem(key), setItem: (key, value) => sessionStorage.setItem(key, value) }, { lazy: true });
|
|
86
90
|
this.onStartNewSession = () => void this.newConversation();
|
|
87
|
-
this.onModeChange = (event) => {
|
|
91
|
+
this.onModeChange = async (event) => {
|
|
88
92
|
const kind = event.detail?.kind;
|
|
89
93
|
if (!kind || kind === this.kind)
|
|
90
94
|
return;
|
|
95
|
+
if (!(await this.mayLeaveConversation()))
|
|
96
|
+
return;
|
|
91
97
|
this.chosenKind = kind;
|
|
92
98
|
void this.open();
|
|
93
99
|
};
|
|
94
100
|
/** Every proposal ends in exactly one reported outcome - a kind nobody handles is `unavailable`. */
|
|
95
101
|
this.onProposal = async (event) => {
|
|
96
102
|
const { proposal, sessionId, proposalKey } = event.detail ?? {};
|
|
97
|
-
const outcome =
|
|
103
|
+
const outcome = this.openedFor !== this.scopeKey(currentAssistantSurface()) || this.openedIdentity !== this.identityKey()
|
|
104
|
+
? { verdict: 'unavailable', errorCode: 'conversation-screen-changed', note: t('return-to-subject', 'Return to the conversation subject before applying this proposal.') }
|
|
105
|
+
: await runProposal(proposal, this.proposalContext(sessionId));
|
|
98
106
|
if (outcome.verdict === 'unavailable' && outcome.errorCode === 'unknown-proposal-kind') {
|
|
99
107
|
notify({ level: 'error', message: t('proposal-not-runnable', 'this proposal cannot be run on this screen.') });
|
|
100
108
|
}
|
|
@@ -103,8 +111,36 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
103
111
|
if (outcome.note && sessionId)
|
|
104
112
|
await this.appendNote(sessionId, outcome.note);
|
|
105
113
|
};
|
|
114
|
+
/**
|
|
115
|
+
* "Check result" - asks the surface what became of a requested proposal and reports only what it learns.
|
|
116
|
+
* Nothing is run: a lost answer never turns into a second application (ADR-0097 Q-D4 ④).
|
|
117
|
+
*/
|
|
118
|
+
this.onProposalCheck = async (event) => {
|
|
119
|
+
const { proposal, sessionId, proposalKey } = event.detail ?? {};
|
|
120
|
+
const ask = this.surface?.proposalOutcome;
|
|
121
|
+
if (!ask) {
|
|
122
|
+
notify({ level: 'info', message: t('proposal-result-uncheckable', 'this screen cannot check that result. open the screen where it was applied.') });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
let outcome;
|
|
126
|
+
try {
|
|
127
|
+
outcome = await ask.call(this.surface, proposalKey, proposal);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
outcome = undefined;
|
|
131
|
+
}
|
|
132
|
+
if (!outcome?.verdict) {
|
|
133
|
+
notify({ level: 'info', message: t('proposal-result-unknown', 'the result is still unknown. it was not applied again.') });
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
await this.report(sessionId, proposalKey, outcome);
|
|
137
|
+
if (outcome.note && sessionId)
|
|
138
|
+
await this.appendNote(sessionId, outcome.note);
|
|
139
|
+
};
|
|
106
140
|
/* ── board surfaces: the chat's scene edits land on the open board ───────────────── */
|
|
107
141
|
this.onScenePatch = async (event) => {
|
|
142
|
+
if (!this.mayApplyOnScreen())
|
|
143
|
+
return;
|
|
108
144
|
const board = this.surface?.board;
|
|
109
145
|
if (!board)
|
|
110
146
|
return;
|
|
@@ -112,8 +148,10 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
112
148
|
if (result?.missed)
|
|
113
149
|
notify({ level: 'info', message: t('patch-missed', '{missed} of the changes could not be applied.', { missed: result.missed }) });
|
|
114
150
|
};
|
|
115
|
-
this.onBoardRevert = (event) =>
|
|
116
|
-
|
|
151
|
+
this.onBoardRevert = (event) => { if (this.mayApplyOnScreen())
|
|
152
|
+
void this.surface?.board?.revertPatch?.(event.detail?.patchId); };
|
|
153
|
+
this.onSceneAction = (event) => { if (this.mayApplyOnScreen())
|
|
154
|
+
void this.surface?.board?.applyAction?.(event.detail); };
|
|
117
155
|
}
|
|
118
156
|
static { this.styles = [
|
|
119
157
|
ScrollbarStyles,
|
|
@@ -239,12 +277,42 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
239
277
|
gap: 4px;
|
|
240
278
|
font: inherit;
|
|
241
279
|
}
|
|
280
|
+
|
|
281
|
+
.next-step {
|
|
282
|
+
display: flex;
|
|
283
|
+
align-items: center;
|
|
284
|
+
justify-content: space-between;
|
|
285
|
+
gap: 10px;
|
|
286
|
+
padding: 8px 12px;
|
|
287
|
+
border-bottom: 1px solid var(--md-sys-color-outline-variant);
|
|
288
|
+
background: var(--md-sys-color-surface-container-low);
|
|
289
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
290
|
+
font-size: 12px;
|
|
291
|
+
line-height: 1.4;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.next-step a {
|
|
295
|
+
display: inline-flex;
|
|
296
|
+
align-items: center;
|
|
297
|
+
gap: 3px;
|
|
298
|
+
flex: none;
|
|
299
|
+
color: var(--md-sys-color-primary);
|
|
300
|
+
font-weight: 650;
|
|
301
|
+
text-decoration: none;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.next-step a:hover { text-decoration: underline; }
|
|
305
|
+
.next-step md-icon { --md-icon-size: 16px; }
|
|
306
|
+
ox-assistant-chat[hidden] { display: none; }
|
|
307
|
+
.transition { padding: 10px 12px; font-size: 13px; line-height: 1.5; border-bottom: 1px solid var(--md-sys-color-outline-variant); background: var(--md-sys-color-surface-container-low); }
|
|
308
|
+
.transition button { display: block; margin-top: 6px; font: inherit; }
|
|
242
309
|
`
|
|
243
310
|
]; }
|
|
244
311
|
connectedCallback() {
|
|
245
312
|
super.connectedCallback();
|
|
246
313
|
this.addEventListener('assistant-start-new-session', this.onStartNewSession);
|
|
247
|
-
this.unsubscribers.push(subscribeAssistantSurface(() => this.follow()),
|
|
314
|
+
this.unsubscribers.push(subscribeAssistantSurface(() => this.follow()), store.subscribe(() => { if (this.openedIdentity !== this.identityKey())
|
|
315
|
+
this.follow(); }), subscribeAssistantAsk(() => void this.takeAsk()), subscribeSessionActivity(activity => {
|
|
248
316
|
/* A rename or a new conversation elsewhere on this anchor - the tabs read again. */
|
|
249
317
|
if (activity.kind === 'meta' && isAnchor(this.anchor) && activity.anchorId === this.anchor.anchorId)
|
|
250
318
|
void this.reloadSessions();
|
|
@@ -259,23 +327,73 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
259
327
|
this.controller.clear();
|
|
260
328
|
super.disconnectedCallback();
|
|
261
329
|
}
|
|
262
|
-
scopeKey(surface
|
|
330
|
+
scopeKey(surface) {
|
|
263
331
|
return JSON.stringify([this.app.contextPath, surface?.key ?? '']);
|
|
264
332
|
}
|
|
333
|
+
identityKey() {
|
|
334
|
+
const user = store.getState().auth?.user;
|
|
335
|
+
return JSON.stringify([this.app.contextPath, user?.id || user?.email || '']);
|
|
336
|
+
}
|
|
337
|
+
get navigationState() {
|
|
338
|
+
return this.renderRoot.querySelector('ox-assistant-chat')?.navigationState ?? { busy: false, draft: false };
|
|
339
|
+
}
|
|
340
|
+
async mayLeaveConversation() {
|
|
341
|
+
if (this.navigationState.busy) {
|
|
342
|
+
notify({ level: 'info', message: t('wait-before-switch', 'Wait for the current response before changing conversations.') });
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
if (!this.navigationState.draft)
|
|
346
|
+
return true;
|
|
347
|
+
const identity = this.identityKey();
|
|
348
|
+
const accepted = await OxPrompt.open({
|
|
349
|
+
type: 'warning', title: t('switch-title', 'Change conversation?'),
|
|
350
|
+
text: t('switch-draft', 'Your unsent text and attachments will not move to the other conversation.'),
|
|
351
|
+
confirmButton: { text: t('switch-confirm', 'Discard draft and switch') },
|
|
352
|
+
cancelButton: { text: t('stay', 'Keep writing') }
|
|
353
|
+
});
|
|
354
|
+
return !!accepted && identity === this.identityKey();
|
|
355
|
+
}
|
|
356
|
+
async requestSurface(surface) {
|
|
357
|
+
if (!(await this.mayLeaveConversation()))
|
|
358
|
+
return;
|
|
359
|
+
this.chosenKind = '';
|
|
360
|
+
this.surface = surface;
|
|
361
|
+
this.navigationNotice = surface ? t('now-about', 'Conversation subject: {name}', { name: surface.label() }) : '';
|
|
362
|
+
await this.open();
|
|
363
|
+
}
|
|
265
364
|
/** The screen changed - a different surface or domain is a different conversation. */
|
|
266
365
|
follow(force = false) {
|
|
267
366
|
const next = currentAssistantSurface();
|
|
268
|
-
|
|
269
|
-
|
|
367
|
+
const transition = surfaceTransition({
|
|
368
|
+
identityChanged: this.openedIdentity !== this.identityKey(),
|
|
369
|
+
sameSubject: this.scopeKey(next) === this.openedFor,
|
|
370
|
+
active: isAnchor(this.anchor) && (!!this.sessionId || this.navigationState.draft || this.navigationState.busy)
|
|
371
|
+
});
|
|
372
|
+
if (!force && transition === 'refresh') {
|
|
373
|
+
this.surface = next;
|
|
374
|
+
this.screenChanged = false;
|
|
270
375
|
this.requestUpdate();
|
|
271
376
|
return;
|
|
272
377
|
}
|
|
378
|
+
if (!force && transition === 'offer') {
|
|
379
|
+
this.screenChanged = true;
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (transition === 'reset') {
|
|
383
|
+
this.asking = undefined;
|
|
384
|
+
this.capability = 'unknown';
|
|
385
|
+
if (this.openedIdentity)
|
|
386
|
+
takeAssistantAsk();
|
|
387
|
+
}
|
|
388
|
+
this.navigationNotice = transition === 'follow' && next ? t('now-about', 'Conversation subject: {name}', { name: next.label() }) : '';
|
|
273
389
|
if (next?.key !== this.surface?.key)
|
|
274
390
|
this.chosenKind = '';
|
|
275
391
|
this.surface = next;
|
|
276
392
|
void this.open();
|
|
277
393
|
}
|
|
278
394
|
async open() {
|
|
395
|
+
this.openedIdentity = this.identityKey();
|
|
396
|
+
this.screenChanged = false;
|
|
279
397
|
const ticket = ++this.revision;
|
|
280
398
|
this.conversationView++;
|
|
281
399
|
this.showingHistory = false;
|
|
@@ -283,7 +401,7 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
283
401
|
this.loading = true;
|
|
284
402
|
this.failure = '';
|
|
285
403
|
this.anchor = undefined;
|
|
286
|
-
this.openedFor = this.scopeKey();
|
|
404
|
+
this.openedFor = this.scopeKey(this.surface);
|
|
287
405
|
try {
|
|
288
406
|
if (this.capability !== 'configured') {
|
|
289
407
|
this.capability = await readAiCapability();
|
|
@@ -342,13 +460,17 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
342
460
|
async newConversation() {
|
|
343
461
|
if (this.loading || !isAnchor(this.anchor))
|
|
344
462
|
return;
|
|
463
|
+
if (!(await this.mayLeaveConversation()))
|
|
464
|
+
return;
|
|
345
465
|
this.showingHistory = false;
|
|
346
466
|
const revision = this.controller.state.revision;
|
|
347
467
|
await this.controller.reset();
|
|
348
468
|
if (revision !== this.controller.state.revision)
|
|
349
469
|
this.conversationView++;
|
|
350
470
|
}
|
|
351
|
-
selectSession(id, pickedKind) {
|
|
471
|
+
async selectSession(id, pickedKind) {
|
|
472
|
+
if (id !== this.sessionId && !(await this.mayLeaveConversation()))
|
|
473
|
+
return;
|
|
352
474
|
this.showingHistory = false;
|
|
353
475
|
const follow = followPickedConversation(pickedKind, this.kind);
|
|
354
476
|
if (follow) {
|
|
@@ -365,6 +487,12 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
365
487
|
async takeAsk() {
|
|
366
488
|
if (this.loading || !this.anchor)
|
|
367
489
|
return;
|
|
490
|
+
if (this.screenChanged || this.navigationState.busy || this.navigationState.draft) {
|
|
491
|
+
const waiting = takeAssistantAsk();
|
|
492
|
+
if (waiting)
|
|
493
|
+
notify({ level: 'info', message: t('ask-kept-current', 'The current conversation was kept. Switch to the intended subject before asking again.') });
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
368
496
|
if (!isAnchor(this.anchor)) {
|
|
369
497
|
/*
|
|
370
498
|
A question is not sent later on its own, once some conversation happens to stand - by then the person is looking
|
|
@@ -438,6 +566,8 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
438
566
|
}
|
|
439
567
|
/* ── proposals ───────────────────────────────────────────────────────────────────── */
|
|
440
568
|
proposalContext(sessionId) {
|
|
569
|
+
const identity = this.identityKey();
|
|
570
|
+
const scope = this.openedFor;
|
|
441
571
|
return {
|
|
442
572
|
sessionId,
|
|
443
573
|
surface: this.surface,
|
|
@@ -447,7 +577,7 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
447
577
|
text,
|
|
448
578
|
confirmButton: { text: confirmText ?? t('confirm', 'OK') },
|
|
449
579
|
cancelButton: { text: cancelText ?? t('cancel', 'Cancel') }
|
|
450
|
-
})),
|
|
580
|
+
})) && identity === this.identityKey() && scope === this.scopeKey(currentAssistantSurface()),
|
|
451
581
|
notify: (level, message) => notify({ level, message })
|
|
452
582
|
};
|
|
453
583
|
}
|
|
@@ -483,6 +613,12 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
483
613
|
/* the outcome is already reported; a lost note is not a lost outcome */
|
|
484
614
|
}
|
|
485
615
|
}
|
|
616
|
+
mayApplyOnScreen() {
|
|
617
|
+
if (this.openedFor === this.scopeKey(currentAssistantSurface()) && this.openedIdentity === this.identityKey())
|
|
618
|
+
return true;
|
|
619
|
+
notify({ level: 'info', message: t('return-to-subject', 'Return to the conversation subject before applying this proposal.') });
|
|
620
|
+
return false;
|
|
621
|
+
}
|
|
486
622
|
/* ── drawing ─────────────────────────────────────────────────────────────────────── */
|
|
487
623
|
stuckLine() {
|
|
488
624
|
if (this.capability === 'not-configured')
|
|
@@ -512,16 +648,16 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
512
648
|
<md-icon>home</md-icon>
|
|
513
649
|
</button>`
|
|
514
650
|
: nothing}
|
|
515
|
-
${ready
|
|
651
|
+
${ready && this.showingHistory
|
|
516
652
|
? html `<button
|
|
517
653
|
class="sbtn"
|
|
518
654
|
title=${this.showingHistory ? t('back-to-conversation', 'back to the conversation') : t('conversations', 'conversations')}
|
|
519
655
|
@click=${() => (this.showingHistory = !this.showingHistory)}
|
|
520
656
|
>
|
|
521
|
-
<md-icon>${
|
|
657
|
+
<md-icon>arrow_back</md-icon>${t('back-to-conversation', 'back to the conversation')}
|
|
522
658
|
</button>`
|
|
523
659
|
: nothing}
|
|
524
|
-
<button class="sbtn" title=${t('rebind', 'follow this screen again')} @click=${() => this.
|
|
660
|
+
<button class="sbtn" title=${t('rebind', 'follow this screen again')} @click=${() => this.requestSurface(currentAssistantSurface())}>
|
|
525
661
|
<md-icon>refresh</md-icon>
|
|
526
662
|
</button>
|
|
527
663
|
<button class="sbtn" title=${t('close', 'close')} @click=${() => closeOverlay(this.viewpart)}>
|
|
@@ -532,9 +668,7 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
532
668
|
}
|
|
533
669
|
/** The home button: talk about the application instead of this screen, until the screen changes. */
|
|
534
670
|
useSurface(surface) {
|
|
535
|
-
this.surface
|
|
536
|
-
this.chosenKind = '';
|
|
537
|
-
void this.open();
|
|
671
|
+
void this.requestSurface(surface);
|
|
538
672
|
}
|
|
539
673
|
render() {
|
|
540
674
|
const anchor = this.anchor;
|
|
@@ -546,6 +680,14 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
546
680
|
const mode = ready ? { kind: this.kind, target: anchor.anchorId, hostContext: {} } : undefined;
|
|
547
681
|
return html `
|
|
548
682
|
${this.header()}
|
|
683
|
+
${surface?.nextStep ? html `<div class="next-step" role="status">
|
|
684
|
+
<span>${surface.nextStep.description?.() || ''}</span>
|
|
685
|
+
<a href=${surface.nextStep.href}>${surface.nextStep.label()}<md-icon>arrow_forward</md-icon></a>
|
|
686
|
+
</div>` : nothing}
|
|
687
|
+
${this.screenChanged ? html `<div class="transition" role="status">
|
|
688
|
+
${t('screen-and-conversation', 'Screen: {screen}. Conversation: {conversation}. Your conversation has been kept.', { screen: currentAssistantSurface()?.label() || t('no-subject', 'No subject'), conversation: surface?.label() || '' })}
|
|
689
|
+
<button class="sbtn" @click=${() => this.requestSurface(currentAssistantSurface())}>${t('switch-to-screen', 'Talk about this screen')}</button>
|
|
690
|
+
</div>` : this.navigationNotice ? html `<div class="transition" role="status">${this.navigationNotice}</div>` : nothing}
|
|
549
691
|
${ready && this.showingHistory
|
|
550
692
|
? html `<ox-assistant-session-manager
|
|
551
693
|
.anchorType=${anchor.anchorType}
|
|
@@ -553,6 +695,7 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
553
695
|
.sessionId=${this.sessionId}
|
|
554
696
|
.kind=${this.kind}
|
|
555
697
|
.kindLabels=${this.kindLabels}
|
|
698
|
+
.scopeLabel=${t('conversation-scope', 'Conversations · {name}', { name: surface?.label() || '' })}
|
|
556
699
|
@assistant-session-select=${(event) => this.selectSession(event.detail.sessionId, event.detail.kind)}
|
|
557
700
|
@assistant-session-reset=${() => this.newConversation()}
|
|
558
701
|
@assistant-session-changed=${() => this.reloadSessions()}
|
|
@@ -565,20 +708,23 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
565
708
|
.loading=${this.loading}
|
|
566
709
|
.error=${this.failure}
|
|
567
710
|
historyEnabled
|
|
711
|
+
singleConversation
|
|
568
712
|
@assistant-session-select=${(event) => this.selectSession(event.detail.sessionId)}
|
|
569
713
|
@assistant-session-reset=${() => this.newConversation()}
|
|
570
714
|
@assistant-session-history=${() => (this.showingHistory = true)}
|
|
571
715
|
@assistant-session-retry=${() => this.open()}
|
|
572
716
|
></ox-assistant-session-toolbar>`
|
|
573
717
|
: nothing}
|
|
574
|
-
${ready && !this.
|
|
718
|
+
${ready && !this.loading && !this.failure
|
|
575
719
|
? keyed(this.conversationView, html `<ox-assistant-chat
|
|
720
|
+
?hidden=${this.showingHistory}
|
|
721
|
+
.sendBlocked=${this.screenChanged ? t('return-to-subject', 'Return to the conversation subject before sending or applying changes.') : ''}
|
|
576
722
|
.sessionId=${this.sessionId}
|
|
577
723
|
.prepareSession=${(adopt) => this.controller.prepareSession(adopt)}
|
|
578
724
|
.contextProvider=${() => {
|
|
579
725
|
/* The screen moved on between writing and sending - do not answer about the old one. */
|
|
580
|
-
if (openedFor !== this.scopeKey(currentAssistantSurface()
|
|
581
|
-
throw new Error(t('
|
|
726
|
+
if (openedFor !== this.scopeKey(currentAssistantSurface()) || this.openedIdentity !== this.identityKey())
|
|
727
|
+
throw new Error(t('return-to-subject', 'Return to the conversation subject before applying this proposal.'));
|
|
582
728
|
return { hostContext: surface?.hostContext?.() ?? {} };
|
|
583
729
|
}}
|
|
584
730
|
.mode=${mode}
|
|
@@ -598,6 +744,7 @@ let AssistantDock = class AssistantDock extends localize(i18next)(LitElement) {
|
|
|
598
744
|
.draftRequestId=${this.asking?.requestId}
|
|
599
745
|
@assistant-mode-change=${this.onModeChange}
|
|
600
746
|
@assistant-proposal-execute=${this.onProposal}
|
|
747
|
+
@assistant-proposal-check=${this.onProposalCheck}
|
|
601
748
|
@scene-edit-patch=${this.onScenePatch}
|
|
602
749
|
@board-edit-revert=${this.onBoardRevert}
|
|
603
750
|
@scene-action-execute=${this.onSceneAction}
|
|
@@ -676,6 +823,14 @@ __decorate([
|
|
|
676
823
|
state(),
|
|
677
824
|
__metadata("design:type", Object)
|
|
678
825
|
], AssistantDock.prototype, "asking", void 0);
|
|
826
|
+
__decorate([
|
|
827
|
+
state(),
|
|
828
|
+
__metadata("design:type", Object)
|
|
829
|
+
], AssistantDock.prototype, "screenChanged", void 0);
|
|
830
|
+
__decorate([
|
|
831
|
+
state(),
|
|
832
|
+
__metadata("design:type", Object)
|
|
833
|
+
], AssistantDock.prototype, "navigationNotice", void 0);
|
|
679
834
|
AssistantDock = __decorate([
|
|
680
835
|
customElement('ox-assistant-dock')
|
|
681
836
|
], AssistantDock);
|