@things-factory/ai-assistant 10.1.15 → 10.1.16
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 +68 -19
- package/client/components/chat-defaults.ts +24 -0
- package/dist-client/components/assistant-chat.d.ts +15 -0
- package/dist-client/components/assistant-chat.js +64 -18
- package/dist-client/components/assistant-chat.js.map +1 -1
- package/dist-client/components/chat-defaults.d.ts +22 -0
- package/dist-client/components/chat-defaults.js +4 -0
- package/dist-client/components/chat-defaults.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -570,6 +570,44 @@ export class OxAssistantChat extends LitElement {
|
|
|
570
570
|
@state()
|
|
571
571
|
private sentProposals = new Set<string>()
|
|
572
572
|
|
|
573
|
+
/** Proposal keys the host has reported staged. Only the host knows; see `acknowledgeProposalStaged`. */
|
|
574
|
+
@state()
|
|
575
|
+
private stagedProposals = new Set<string>()
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* The host reports that it put this candidate somewhere the person can look at it.
|
|
579
|
+
*
|
|
580
|
+
* Staging happens outside this component — a dock catches `assistant-proposal-preview`, hands
|
|
581
|
+
* the candidate to a viewer, and only that host knows whether it worked, or whether it has a
|
|
582
|
+
* viewer at all. So the card says nothing until the host calls this, and it then says it in the
|
|
583
|
+
* words the host registered (`chatDefaults.stagedNoticeKey`).
|
|
584
|
+
*
|
|
585
|
+
* Safe to call for a candidate the card never showed; the key simply never matches.
|
|
586
|
+
*/
|
|
587
|
+
acknowledgeProposalStaged(proposal: any): void {
|
|
588
|
+
/*
|
|
589
|
+
Silence has two meanings and they are not the same defect. A host that never calls this is
|
|
590
|
+
telling us it does not know, and drawing nothing is right. A host that calls it without
|
|
591
|
+
registering `stagedNoticeKey` meant to say something and left out the words -- staying quiet
|
|
592
|
+
about that reads to whoever wired it as "the badge just doesn't appear here".
|
|
593
|
+
|
|
594
|
+
The screen still shows nothing either way. There is no sentence to show, and inventing one is
|
|
595
|
+
what this whole correction removed.
|
|
596
|
+
*/
|
|
597
|
+
if (!chatDefaults.stagedNoticeKey && !OxAssistantChat.warnedMissingStagedNotice) {
|
|
598
|
+
OxAssistantChat.warnedMissingStagedNotice = true
|
|
599
|
+
console.warn(
|
|
600
|
+
'[assistant-chat] a host reported a proposal staged but registered no `stagedNoticeKey`, ' +
|
|
601
|
+
'so the card can say nothing. Pass one to `registerChatDefaults` from the host.'
|
|
602
|
+
)
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
this.stagedProposals = new Set(this.stagedProposals).add(this.proposalKey(proposal))
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/** Once per page: the miss is a wiring mistake, and repeating it per candidate buries it. */
|
|
609
|
+
private static warnedMissingStagedNotice = false
|
|
610
|
+
|
|
573
611
|
/**
|
|
574
612
|
* 이 대화가 길어져 앞부분이 프롬프트에서 접혔다는 **사실**(서버 보고). 주제 이탈을 판정한 것이
|
|
575
613
|
* 아니다 — 판정하면 오탐이 생기고, 오탐이 생기면 사용자는 안내 자체를 무시한다.
|
|
@@ -3199,13 +3237,12 @@ export class OxAssistantChat extends LitElement {
|
|
|
3199
3237
|
${items.map(p => {
|
|
3200
3238
|
const key = this.proposalKey(p)
|
|
3201
3239
|
const sent = this.sentProposals.has(key)
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
] : [])
|
|
3240
|
+
/*
|
|
3241
|
+
Follow-up chips are the host's words, never this component's. The fallback that used
|
|
3242
|
+
to live here named a 3D modeller's operations in hardcoded Korean, and it reached the
|
|
3243
|
+
plant and twin chats too.
|
|
3244
|
+
*/
|
|
3245
|
+
const rawChoices: any[] = Array.isArray(p.choices) ? p.choices : (chatDefaults.proposalChoices ?? [])
|
|
3209
3246
|
|
|
3210
3247
|
return html`
|
|
3211
3248
|
<div class="proposal ${sent ? 'sent' : ''}">
|
|
@@ -3214,20 +3251,32 @@ export class OxAssistantChat extends LitElement {
|
|
|
3214
3251
|
<span class="plabel">${p.label || p.command}</span>
|
|
3215
3252
|
${p.reason ? html`<span class="preason">${p.reason}</span>` : nothing}
|
|
3216
3253
|
</span>
|
|
3217
|
-
${
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3254
|
+
${/*
|
|
3255
|
+
The run button and the follow-up chips answer different questions — "is there
|
|
3256
|
+
something to apply" and "what else could I ask for" — and they used to share one
|
|
3257
|
+
ternary on `rawChoices.length`. A proposal that carried chips lost its button, so
|
|
3258
|
+
the one action the card exists for became unreachable while the model kept
|
|
3259
|
+
telling people to press it.
|
|
3260
|
+
*/ ''}
|
|
3261
|
+
<button
|
|
3262
|
+
class="run"
|
|
3263
|
+
?disabled=${sent}
|
|
3264
|
+
@click=${() => this.executeProposal(p, key)}>
|
|
3265
|
+
${sent ? i18next.t('ai-assistant.text.proposal-sent', { defaultValue: '실행 요청됨' })
|
|
3266
|
+
: i18next.t('ai-assistant.button.run-proposal', { defaultValue: '실행' })}
|
|
3267
|
+
</button>
|
|
3268
|
+
${/*
|
|
3269
|
+
Drawn only where the host has said it staged this candidate, in the host's own
|
|
3270
|
+
words. Not knowing is not a claim: with no word from the host, nothing is drawn.
|
|
3271
|
+
This badge used to read "there are chips" as "the model is in the 3D viewer" and
|
|
3272
|
+
say so, in a component that plant and twin also use.
|
|
3273
|
+
*/ ''}
|
|
3274
|
+
${this.stagedProposals.has(key) && chatDefaults.stagedNoticeKey ? html`
|
|
3275
|
+
<span class="staged-badge">
|
|
3227
3276
|
<md-icon>check_circle</md-icon>
|
|
3228
|
-
<span
|
|
3277
|
+
<span>${i18next.t(chatDefaults.stagedNoticeKey)}</span>
|
|
3229
3278
|
</span>
|
|
3230
|
-
`}
|
|
3279
|
+
` : nothing}
|
|
3231
3280
|
</div>
|
|
3232
3281
|
${rawChoices.length ? html`
|
|
3233
3282
|
<div class="proposal-choices" role="group" aria-label="대화 선택지">
|
|
@@ -28,6 +28,28 @@ export interface ChatDefaults {
|
|
|
28
28
|
* 그 말을 한다.
|
|
29
29
|
*/
|
|
30
30
|
footerNoticeKey?: string
|
|
31
|
+
/**
|
|
32
|
+
* Follow-up chips offered on a proposal that arrived without its own `choices`.
|
|
33
|
+
*
|
|
34
|
+
* These used to sit in the chat component as a literal array: "다른 콘셉트 재제안", "비율 슬림
|
|
35
|
+
* 조정", "색상 테마 변경", "디테일 보강". Those are a 3D modeller's words, written in Korean with
|
|
36
|
+
* no i18n, inside a component four apps share. A plant screen proposal offered to slim its
|
|
37
|
+
* aspect ratio.
|
|
38
|
+
*
|
|
39
|
+
* Same reason as `footerNoticeKey`: the host that knows what a follow-up means writes it.
|
|
40
|
+
* Leave it unset and a proposal without choices simply gets none, which is correct.
|
|
41
|
+
*/
|
|
42
|
+
proposalChoices?: any[]
|
|
43
|
+
/**
|
|
44
|
+
* The **i18n key** for the line shown once the host reports a proposal staged. Unset means the
|
|
45
|
+
* badge is never drawn.
|
|
46
|
+
*
|
|
47
|
+
* The component cannot know this on its own. It used to read "선택지가 딸려 있다" as "the model is
|
|
48
|
+
* in the 3D viewer" and say so — in a component plant and twin also use, neither of which has a
|
|
49
|
+
* 3D viewer. Staging is something the host does, so the host says whether it happened
|
|
50
|
+
* (`acknowledgeProposalStaged`) and in what words.
|
|
51
|
+
*/
|
|
52
|
+
stagedNoticeKey?: string
|
|
31
53
|
}
|
|
32
54
|
|
|
33
55
|
export const chatDefaults: ChatDefaults = { catalogEntries: [], slashTemplates: [] }
|
|
@@ -37,4 +59,6 @@ export function registerChatDefaults(defaults: Partial<ChatDefaults>): void {
|
|
|
37
59
|
if (defaults.catalogEntries) chatDefaults.catalogEntries = defaults.catalogEntries
|
|
38
60
|
if (defaults.slashTemplates) chatDefaults.slashTemplates = defaults.slashTemplates
|
|
39
61
|
if (defaults.footerNoticeKey) chatDefaults.footerNoticeKey = defaults.footerNoticeKey
|
|
62
|
+
if (defaults.proposalChoices) chatDefaults.proposalChoices = defaults.proposalChoices
|
|
63
|
+
if (defaults.stagedNoticeKey) chatDefaults.stagedNoticeKey = defaults.stagedNoticeKey
|
|
40
64
|
}
|
|
@@ -212,6 +212,21 @@ export declare class OxAssistantChat extends LitElement {
|
|
|
212
212
|
private openToolSteps;
|
|
213
213
|
/** 이미 실행을 요청한 제안 키 — 같은 카드를 두 번 눌러 되돌릴 수 없는 명령이 두 번 나가지 않게. */
|
|
214
214
|
private sentProposals;
|
|
215
|
+
/** Proposal keys the host has reported staged. Only the host knows; see `acknowledgeProposalStaged`. */
|
|
216
|
+
private stagedProposals;
|
|
217
|
+
/**
|
|
218
|
+
* The host reports that it put this candidate somewhere the person can look at it.
|
|
219
|
+
*
|
|
220
|
+
* Staging happens outside this component — a dock catches `assistant-proposal-preview`, hands
|
|
221
|
+
* the candidate to a viewer, and only that host knows whether it worked, or whether it has a
|
|
222
|
+
* viewer at all. So the card says nothing until the host calls this, and it then says it in the
|
|
223
|
+
* words the host registered (`chatDefaults.stagedNoticeKey`).
|
|
224
|
+
*
|
|
225
|
+
* Safe to call for a candidate the card never showed; the key simply never matches.
|
|
226
|
+
*/
|
|
227
|
+
acknowledgeProposalStaged(proposal: any): void;
|
|
228
|
+
/** Once per page: the miss is a wiring mistake, and repeating it per candidate buries it. */
|
|
229
|
+
private static warnedMissingStagedNotice;
|
|
215
230
|
/**
|
|
216
231
|
* 이 대화가 길어져 앞부분이 프롬프트에서 접혔다는 **사실**(서버 보고). 주제 이탈을 판정한 것이
|
|
217
232
|
* 아니다 — 판정하면 오탐이 생기고, 오탐이 생기면 사용자는 안내 자체를 무시한다.
|
|
@@ -223,6 +223,8 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
223
223
|
this.openToolSteps = new Set();
|
|
224
224
|
/** 이미 실행을 요청한 제안 키 — 같은 카드를 두 번 눌러 되돌릴 수 없는 명령이 두 번 나가지 않게. */
|
|
225
225
|
this.sentProposals = new Set();
|
|
226
|
+
/** Proposal keys the host has reported staged. Only the host knows; see `acknowledgeProposalStaged`. */
|
|
227
|
+
this.stagedProposals = new Set();
|
|
226
228
|
/** 안내를 닫았는가 — 한 번 닫으면 이 세션에서는 다시 띄우지 않는다(잔소리 금지). */
|
|
227
229
|
this.foldNoticeDismissed = false;
|
|
228
230
|
this.busy = false;
|
|
@@ -395,6 +397,35 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
395
397
|
this.onAttachFiles(e.dataTransfer.files);
|
|
396
398
|
}
|
|
397
399
|
}
|
|
400
|
+
/**
|
|
401
|
+
* The host reports that it put this candidate somewhere the person can look at it.
|
|
402
|
+
*
|
|
403
|
+
* Staging happens outside this component — a dock catches `assistant-proposal-preview`, hands
|
|
404
|
+
* the candidate to a viewer, and only that host knows whether it worked, or whether it has a
|
|
405
|
+
* viewer at all. So the card says nothing until the host calls this, and it then says it in the
|
|
406
|
+
* words the host registered (`chatDefaults.stagedNoticeKey`).
|
|
407
|
+
*
|
|
408
|
+
* Safe to call for a candidate the card never showed; the key simply never matches.
|
|
409
|
+
*/
|
|
410
|
+
acknowledgeProposalStaged(proposal) {
|
|
411
|
+
/*
|
|
412
|
+
Silence has two meanings and they are not the same defect. A host that never calls this is
|
|
413
|
+
telling us it does not know, and drawing nothing is right. A host that calls it without
|
|
414
|
+
registering `stagedNoticeKey` meant to say something and left out the words -- staying quiet
|
|
415
|
+
about that reads to whoever wired it as "the badge just doesn't appear here".
|
|
416
|
+
|
|
417
|
+
The screen still shows nothing either way. There is no sentence to show, and inventing one is
|
|
418
|
+
what this whole correction removed.
|
|
419
|
+
*/
|
|
420
|
+
if (!chatDefaults.stagedNoticeKey && !OxAssistantChat_1.warnedMissingStagedNotice) {
|
|
421
|
+
OxAssistantChat_1.warnedMissingStagedNotice = true;
|
|
422
|
+
console.warn('[assistant-chat] a host reported a proposal staged but registered no `stagedNoticeKey`, ' +
|
|
423
|
+
'so the card can say nothing. Pass one to `registerChatDefaults` from the host.');
|
|
424
|
+
}
|
|
425
|
+
this.stagedProposals = new Set(this.stagedProposals).add(this.proposalKey(proposal));
|
|
426
|
+
}
|
|
427
|
+
/** Once per page: the miss is a wiring mistake, and repeating it per candidate buries it. */
|
|
428
|
+
static { this.warnedMissingStagedNotice = false; }
|
|
398
429
|
/** 현재 로그인 사용자 email — 그룹챗에서 내 메시지 vs 타인 메시지 구분.
|
|
399
430
|
* email 을 쓰는 이유: /auth/profile 이 항상 내려주는 로그인 식별자이고(비어 있지 않다),
|
|
400
431
|
* 내부 관리키(User.id)를 클라이언트 판정에 의존하지 않기 위함. */
|
|
@@ -2836,13 +2867,12 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
2836
2867
|
${items.map(p => {
|
|
2837
2868
|
const key = this.proposalKey(p);
|
|
2838
2869
|
const sent = this.sentProposals.has(key);
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
] : []);
|
|
2870
|
+
/*
|
|
2871
|
+
Follow-up chips are the host's words, never this component's. The fallback that used
|
|
2872
|
+
to live here named a 3D modeller's operations in hardcoded Korean, and it reached the
|
|
2873
|
+
plant and twin chats too.
|
|
2874
|
+
*/
|
|
2875
|
+
const rawChoices = Array.isArray(p.choices) ? p.choices : (chatDefaults.proposalChoices ?? []);
|
|
2846
2876
|
return html `
|
|
2847
2877
|
<div class="proposal ${sent ? 'sent' : ''}">
|
|
2848
2878
|
<md-icon>${p.icon || (p.source ? 'view_in_ar' : 'bolt')}</md-icon>
|
|
@@ -2850,20 +2880,32 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
2850
2880
|
<span class="plabel">${p.label || p.command}</span>
|
|
2851
2881
|
${p.reason ? html `<span class="preason">${p.reason}</span>` : nothing}
|
|
2852
2882
|
</span>
|
|
2853
|
-
${
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2883
|
+
${ /*
|
|
2884
|
+
The run button and the follow-up chips answer different questions — "is there
|
|
2885
|
+
something to apply" and "what else could I ask for" — and they used to share one
|
|
2886
|
+
ternary on `rawChoices.length`. A proposal that carried chips lost its button, so
|
|
2887
|
+
the one action the card exists for became unreachable while the model kept
|
|
2888
|
+
telling people to press it.
|
|
2889
|
+
*/''}
|
|
2890
|
+
<button
|
|
2891
|
+
class="run"
|
|
2892
|
+
?disabled=${sent}
|
|
2893
|
+
@click=${() => this.executeProposal(p, key)}>
|
|
2894
|
+
${sent ? i18next.t('ai-assistant.text.proposal-sent', { defaultValue: '실행 요청됨' })
|
|
2859
2895
|
: i18next.t('ai-assistant.button.run-proposal', { defaultValue: '실행' })}
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2896
|
+
</button>
|
|
2897
|
+
${ /*
|
|
2898
|
+
Drawn only where the host has said it staged this candidate, in the host's own
|
|
2899
|
+
words. Not knowing is not a claim: with no word from the host, nothing is drawn.
|
|
2900
|
+
This badge used to read "there are chips" as "the model is in the 3D viewer" and
|
|
2901
|
+
say so, in a component that plant and twin also use.
|
|
2902
|
+
*/''}
|
|
2903
|
+
${this.stagedProposals.has(key) && chatDefaults.stagedNoticeKey ? html `
|
|
2904
|
+
<span class="staged-badge">
|
|
2863
2905
|
<md-icon>check_circle</md-icon>
|
|
2864
|
-
<span
|
|
2906
|
+
<span>${i18next.t(chatDefaults.stagedNoticeKey)}</span>
|
|
2865
2907
|
</span>
|
|
2866
|
-
`}
|
|
2908
|
+
` : nothing}
|
|
2867
2909
|
</div>
|
|
2868
2910
|
${rawChoices.length ? html `
|
|
2869
2911
|
<div class="proposal-choices" role="group" aria-label="대화 선택지">
|
|
@@ -3554,6 +3596,10 @@ __decorate([
|
|
|
3554
3596
|
state(),
|
|
3555
3597
|
__metadata("design:type", Object)
|
|
3556
3598
|
], OxAssistantChat.prototype, "sentProposals", void 0);
|
|
3599
|
+
__decorate([
|
|
3600
|
+
state(),
|
|
3601
|
+
__metadata("design:type", Object)
|
|
3602
|
+
], OxAssistantChat.prototype, "stagedProposals", void 0);
|
|
3557
3603
|
__decorate([
|
|
3558
3604
|
state(),
|
|
3559
3605
|
__metadata("design:type", Object)
|