@things-factory/ai-assistant 10.1.24 → 10.1.26
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 +90 -18
- package/client/components/assistant-mode.test.ts +97 -0
- package/client/components/assistant-mode.ts +130 -0
- package/client/index.ts +1 -1
- package/dist-client/components/assistant-chat.d.ts +15 -4
- package/dist-client/components/assistant-chat.js +73 -18
- package/dist-client/components/assistant-chat.js.map +1 -1
- package/dist-client/components/assistant-mode.d.ts +97 -0
- package/dist-client/components/assistant-mode.js +36 -0
- package/dist-client/components/assistant-mode.js.map +1 -0
- package/dist-client/components/assistant-mode.test.d.ts +1 -0
- package/dist-client/components/assistant-mode.test.js +85 -0
- package/dist-client/components/assistant-mode.test.js.map +1 -0
- package/dist-client/index.d.ts +1 -1
- package/dist-client/index.js +1 -1
- package/dist-client/index.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/index.d.ts +1 -0
- package/dist-server/index.js +1 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/service/assistant-chat-resolver.js +3 -1
- package/dist-server/service/assistant-chat-resolver.js.map +1 -1
- package/dist-server/service/index.d.ts +1 -0
- package/dist-server/service/index.js +1 -0
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/tool-access.d.ts +4 -0
- package/dist-server/service/tool-access.js +23 -0
- package/dist-server/service/tool-access.js.map +1 -0
- package/dist-server/tool-registry-boot-report.d.ts +3 -0
- package/dist-server/tool-registry-boot-report.js +29 -0
- package/dist-server/tool-registry-boot-report.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/docs/session-controller.md +1 -1
- package/package.json +5 -5
- package/server/index.ts +1 -0
- package/server/service/assistant-chat-resolver.ts +3 -1
- package/server/service/index.ts +1 -0
- package/server/service/tool-access.test.ts +48 -0
- package/server/service/tool-access.ts +27 -0
- package/server/tool-registry-boot-report.test.ts +18 -0
- package/server/tool-registry-boot-report.ts +26 -0
- package/test/assistant-request-context.test.ts +2 -2
- package/test/assistant-session-controller.test.ts +0 -1
- package/test/assistant-session-toolbar.test.ts +2 -2
- package/client/utils/board-edit-patch.ts +0 -374
- package/dist-client/utils/board-edit-patch.d.ts +0 -157
- package/dist-client/utils/board-edit-patch.js +0 -284
- package/dist-client/utils/board-edit-patch.js.map +0 -1
|
@@ -9,8 +9,8 @@ import { __decorate, __metadata } from "tslib";
|
|
|
9
9
|
* - scopes / knownTypes / categories: 도메인 컨텍스트
|
|
10
10
|
*
|
|
11
11
|
* 출력 (이벤트):
|
|
12
|
-
* - `
|
|
13
|
-
* 호스트가 받아서 보드 모델에 적용 (
|
|
12
|
+
* - `scene-edit-patch` { detail: { patch, summary, confidence, patchId } }
|
|
13
|
+
* 호스트가 받아서 보드 모델에 적용 (applyScenePatch from @operato/scene-ops).
|
|
14
14
|
* - `chat-followup` { detail: { question } }
|
|
15
15
|
*
|
|
16
16
|
* 모드 전환은 컨테이너 (워크스페이스) 의 책임. 이 컴포넌트는 자체로 풀 채팅 UX.
|
|
@@ -43,6 +43,7 @@ import { buildMentionCandidates, buildCatalogCandidates, buildSlashCandidates, b
|
|
|
43
43
|
* 뜨지 않는 것이 맞다.
|
|
44
44
|
*/
|
|
45
45
|
import { chatDefaults } from './chat-defaults.js';
|
|
46
|
+
import { isDifferentConversation, resolveConversation } from './assistant-mode.js';
|
|
46
47
|
import { availableTriggers } from './chat-triggers.js';
|
|
47
48
|
function formatFileSize(bytes) {
|
|
48
49
|
if (!bytes || bytes < 1024)
|
|
@@ -259,9 +260,13 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
259
260
|
* textarea 에는 @username 만 보이지만 server 한테는 정확한 userId 전달.
|
|
260
261
|
* send 시 mutation input.userMentions 로 함께 전송. */
|
|
261
262
|
this.pickedUserMentions = new Map();
|
|
262
|
-
|
|
263
|
+
/*
|
|
264
|
+
* The `@` and `/` candidates, built once per mode.
|
|
265
|
+
*
|
|
266
|
+
* These were built at field initialisation, which meant a host could not change what the
|
|
267
|
+
* panel offers without replacing the element. A mode change rebuilds them below.
|
|
268
|
+
*/
|
|
263
269
|
this.cachedCatalogCandidates = buildCatalogCandidates(chatDefaults.catalogEntries);
|
|
264
|
-
/** Default slash template 후보 캐시 — chat panel mount 시 1회 빌드 */
|
|
265
270
|
this.cachedSlashCandidates = buildSlashCandidates(chatDefaults.slashTemplates);
|
|
266
271
|
/** `@` 마지막 query 의 도메인 사용자 후보 캐시 — userProvider 응답 도착 시 갱신.
|
|
267
272
|
* query 별 캐시가 아니라 단순 "최근 결과" — async race 회피. */
|
|
@@ -417,7 +422,7 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
417
422
|
The screen still shows nothing either way. There is no sentence to show, and inventing one is
|
|
418
423
|
what this whole correction removed.
|
|
419
424
|
*/
|
|
420
|
-
if (!
|
|
425
|
+
if (!this.conversation.stagedNoticeKey && !OxAssistantChat_1.warnedMissingStagedNotice) {
|
|
421
426
|
OxAssistantChat_1.warnedMissingStagedNotice = true;
|
|
422
427
|
console.warn('[assistant-chat] a host reported a proposal staged but registered no `stagedNoticeKey`, ' +
|
|
423
428
|
'so the card can say nothing. Pass one to `registerChatDefaults` from the host.');
|
|
@@ -432,6 +437,25 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
432
437
|
get _myEmail() {
|
|
433
438
|
return auth.credential?.email;
|
|
434
439
|
}
|
|
440
|
+
/*
|
|
441
|
+
* ── What this conversation is, resolved ──────────────────────────────────────────────
|
|
442
|
+
*
|
|
443
|
+
* A host that declares a mode gets the mode and nothing else — a field it leaves out is empty,
|
|
444
|
+
* never filled from these properties or the registered defaults. A host that has not declared
|
|
445
|
+
* one keeps the separate properties and the global defaults it had before.
|
|
446
|
+
*/
|
|
447
|
+
get conversation() {
|
|
448
|
+
return resolveConversation(this.mode, {
|
|
449
|
+
systemPrompt: this.systemPrompt,
|
|
450
|
+
toolCategories: this.toolCategories,
|
|
451
|
+
hostContext: this.hostContext,
|
|
452
|
+
chatEndpoint: this.chatEndpoint
|
|
453
|
+
}, chatDefaults);
|
|
454
|
+
}
|
|
455
|
+
rebuildMentionCaches() {
|
|
456
|
+
this.cachedCatalogCandidates = buildCatalogCandidates(this.conversation.catalogEntries);
|
|
457
|
+
this.cachedSlashCandidates = buildSlashCandidates(this.conversation.slashTemplates);
|
|
458
|
+
}
|
|
435
459
|
static { this.styles = [
|
|
436
460
|
// 어플리케이션 표준 스크롤바 (--scrollbar-width / --scrollbar-thumb-color 등 호스트 변수 따름)
|
|
437
461
|
ScrollbarStyles,
|
|
@@ -1938,6 +1962,33 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
1938
1962
|
this.input = this.autoAsk;
|
|
1939
1963
|
this.send();
|
|
1940
1964
|
}
|
|
1965
|
+
/*
|
|
1966
|
+
* The subject changed, so the conversation is over.
|
|
1967
|
+
*
|
|
1968
|
+
* A conversation about station 3 is not a conversation about station 7. Leaving the old one
|
|
1969
|
+
* on screen means the user reads an answer about a screen they are no longer looking at,
|
|
1970
|
+
* and every host that met this wrote its own guard: plant re-checked the context on each
|
|
1971
|
+
* send and threw when it had moved, twin closed its session when the anchor changed. The
|
|
1972
|
+
* mode carries an id, so the component can do it once, here.
|
|
1973
|
+
*
|
|
1974
|
+
* The host still owns `sessionId`; it hears `assistant-mode-changed` and decides whether
|
|
1975
|
+
* this subject gets a stored session of its own.
|
|
1976
|
+
*/
|
|
1977
|
+
if (changed.has('mode') && isDifferentConversation(changed.get('mode'), this.mode)) {
|
|
1978
|
+
this.rebuildMentionCaches();
|
|
1979
|
+
this.lines = [];
|
|
1980
|
+
this.pickedMentions.clear();
|
|
1981
|
+
this.pickedUserMentions.clear();
|
|
1982
|
+
this.cachedUserCandidates = [];
|
|
1983
|
+
this.errorMessage = undefined;
|
|
1984
|
+
this.input = '';
|
|
1985
|
+
this._seenMessageIds.clear();
|
|
1986
|
+
this.dispatchEvent(new CustomEvent('assistant-mode-changed', {
|
|
1987
|
+
detail: { mode: this.mode },
|
|
1988
|
+
bubbles: true,
|
|
1989
|
+
composed: true
|
|
1990
|
+
}));
|
|
1991
|
+
}
|
|
1941
1992
|
if (changed.has('sessionId') && this.adoptingSession) {
|
|
1942
1993
|
this.adoptingSession = false;
|
|
1943
1994
|
this._startPresence();
|
|
@@ -2530,7 +2581,7 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
2530
2581
|
}
|
|
2531
2582
|
}
|
|
2532
2583
|
dispatchActions(actions) {
|
|
2533
|
-
this.dispatchEvent(new CustomEvent('
|
|
2584
|
+
this.dispatchEvent(new CustomEvent('scene-action-execute', {
|
|
2534
2585
|
detail: { actions, sessionId: this.sessionId },
|
|
2535
2586
|
bubbles: true,
|
|
2536
2587
|
composed: true
|
|
@@ -2616,7 +2667,7 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
2616
2667
|
return availableTriggers({
|
|
2617
2668
|
hasMentionableThings: !!(this.boardProvider || this.currentBoard || this.knownTypes?.length),
|
|
2618
2669
|
hasSession: !!this.sessionId,
|
|
2619
|
-
slashTemplateCount:
|
|
2670
|
+
slashTemplateCount: this.conversation.slashTemplates.length
|
|
2620
2671
|
});
|
|
2621
2672
|
}
|
|
2622
2673
|
static { this.EXAMPLE_GROUPS = [
|
|
@@ -2729,8 +2780,8 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
2729
2780
|
<span class="badge">${i18next.t('ai-assistant.label.korean-supported')}</span>
|
|
2730
2781
|
<span class="badge">${i18next.t('ai-assistant.label.multi-command')}</span>
|
|
2731
2782
|
<span class="badge">${i18next.t('ai-assistant.label.review-able')}</span>
|
|
2732
|
-
${
|
|
2733
|
-
? html `<br />${i18next.t(
|
|
2783
|
+
${this.conversation.footerNoticeKey
|
|
2784
|
+
? html `<br />${i18next.t(this.conversation.footerNoticeKey)}`
|
|
2734
2785
|
: ''}
|
|
2735
2786
|
</div>
|
|
2736
2787
|
</div>
|
|
@@ -2872,7 +2923,7 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
2872
2923
|
to live here named a 3D modeller's operations in hardcoded Korean, and it reached the
|
|
2873
2924
|
plant and twin chats too.
|
|
2874
2925
|
*/
|
|
2875
|
-
const rawChoices = Array.isArray(p.choices) ? p.choices :
|
|
2926
|
+
const rawChoices = Array.isArray(p.choices) ? p.choices : this.conversation.proposalChoices;
|
|
2876
2927
|
return html `
|
|
2877
2928
|
<div class="proposal ${sent ? 'sent' : ''}">
|
|
2878
2929
|
<md-icon>${p.icon || (p.source ? 'view_in_ar' : 'bolt')}</md-icon>
|
|
@@ -2900,10 +2951,10 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
2900
2951
|
This badge used to read "there are chips" as "the model is in the 3D viewer" and
|
|
2901
2952
|
say so, in a component that plant and twin also use.
|
|
2902
2953
|
*/''}
|
|
2903
|
-
${this.stagedProposals.has(key) &&
|
|
2954
|
+
${this.stagedProposals.has(key) && this.conversation.stagedNoticeKey ? html `
|
|
2904
2955
|
<span class="staged-badge">
|
|
2905
2956
|
<md-icon>check_circle</md-icon>
|
|
2906
|
-
<span>${i18next.t(
|
|
2957
|
+
<span>${i18next.t(this.conversation.stagedNoticeKey)}</span>
|
|
2907
2958
|
</span>
|
|
2908
2959
|
` : nothing}
|
|
2909
2960
|
</div>
|
|
@@ -3274,7 +3325,7 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
3274
3325
|
let requestBase;
|
|
3275
3326
|
try {
|
|
3276
3327
|
const provided = this.contextProvider?.() || {};
|
|
3277
|
-
requestContext = structuredClone({ systemPrompt: this.systemPrompt, hostContext: this.hostContext, ...provided });
|
|
3328
|
+
requestContext = structuredClone({ systemPrompt: this.conversation.systemPrompt, hostContext: this.conversation.hostContext, ...provided });
|
|
3278
3329
|
liveBoard = structuredClone(this.boardProvider ? this.boardProvider() : this.currentBoard);
|
|
3279
3330
|
requestBase = { version: 1, sessionId: this.sessionId, hostContext: requestContext.hostContext,
|
|
3280
3331
|
modelFingerprint: assistantModelFingerprint(liveBoard) };
|
|
@@ -3348,7 +3399,7 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
3348
3399
|
// 라이브 보드 우선 — 호스트의 캔버스가 사용자 수작업 편집을 들고 있을 수 있음.
|
|
3349
3400
|
// boardProvider 가 있으면 send 시점에 그것을 pull, 없으면 정적 currentBoard.
|
|
3350
3401
|
// mentions 는 위에서 이미 계산해 user line 에 thread — 그대로 mutation 입력으로 재사용.
|
|
3351
|
-
const neutral = this.chatEndpoint === 'assistantChat';
|
|
3402
|
+
const neutral = this.conversation.chatEndpoint === 'assistantChat';
|
|
3352
3403
|
const result = await client.mutate({
|
|
3353
3404
|
mutation: neutral ? ASSISTANT_CHAT_MUTATION : BOARD_AI_CHAT_MUTATION,
|
|
3354
3405
|
variables: {
|
|
@@ -3359,7 +3410,7 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
3359
3410
|
systemPrompt: requestContext.systemPrompt,
|
|
3360
3411
|
truncateAfterMessageId: this._truncateAfterId,
|
|
3361
3412
|
hostContext: requestContext.hostContext,
|
|
3362
|
-
toolCategories: this.toolCategories,
|
|
3413
|
+
toolCategories: this.conversation.toolCategories,
|
|
3363
3414
|
requireGroundingTools: this.requireGroundingTools
|
|
3364
3415
|
})
|
|
3365
3416
|
: buildChatMutationInput({
|
|
@@ -3369,7 +3420,7 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
3369
3420
|
scopes: this.scopes,
|
|
3370
3421
|
truncateAfterMessageId: this._truncateAfterId,
|
|
3371
3422
|
hostContext: requestContext.hostContext,
|
|
3372
|
-
toolCategories: this.toolCategories,
|
|
3423
|
+
toolCategories: this.conversation.toolCategories,
|
|
3373
3424
|
boardTools: this.boardTools,
|
|
3374
3425
|
requireGroundingTools: this.requireGroundingTools,
|
|
3375
3426
|
knownTypes: this.knownTypes,
|
|
@@ -3416,7 +3467,7 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
3416
3467
|
}
|
|
3417
3468
|
// 호스트로 patch 이벤트 전파
|
|
3418
3469
|
if (out.patch) {
|
|
3419
|
-
this.dispatchEvent(new CustomEvent('
|
|
3470
|
+
this.dispatchEvent(new CustomEvent('scene-edit-patch', {
|
|
3420
3471
|
detail: {
|
|
3421
3472
|
patch: out.patch,
|
|
3422
3473
|
requestBase,
|
|
@@ -3431,7 +3482,7 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
|
|
|
3431
3482
|
}
|
|
3432
3483
|
// 호스트로 ephemeral scene 조작 actions 전파 (selection / view / mode)
|
|
3433
3484
|
if (Array.isArray(out.actions) && out.actions.length > 0) {
|
|
3434
|
-
this.dispatchEvent(new CustomEvent('
|
|
3485
|
+
this.dispatchEvent(new CustomEvent('scene-action-execute', {
|
|
3435
3486
|
detail: { actions: out.actions, sessionId: out.sessionId, requestBase },
|
|
3436
3487
|
bubbles: true,
|
|
3437
3488
|
composed: true
|
|
@@ -3504,6 +3555,10 @@ __decorate([
|
|
|
3504
3555
|
property({ type: String, attribute: 'chat-endpoint' }),
|
|
3505
3556
|
__metadata("design:type", String)
|
|
3506
3557
|
], OxAssistantChat.prototype, "chatEndpoint", void 0);
|
|
3558
|
+
__decorate([
|
|
3559
|
+
property({ attribute: false }),
|
|
3560
|
+
__metadata("design:type", Object)
|
|
3561
|
+
], OxAssistantChat.prototype, "mode", void 0);
|
|
3507
3562
|
__decorate([
|
|
3508
3563
|
property({ type: String, attribute: 'system-prompt' }),
|
|
3509
3564
|
__metadata("design:type", String)
|