@things-factory/ai-assistant 10.1.122 → 10.1.125

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.
@@ -2931,33 +2931,6 @@ export class OxAssistantChat extends LitElement {
2931
2931
  updated(changed: Map<string, any>) {
2932
2932
  if (changed.has('input') || changed.has('composerWide') || changed.has('previewAttachmentId') || changed.has('attachments')) this.fitComposer()
2933
2933
 
2934
- /*
2935
- * 밖에서 넣어 준 질문을 자동 전송한다(오류 토스트의 "AI에게 묻기" 등).
2936
- *
2937
- * sessionId 가 붙기 전에 보내면 대화에 남지 않으므로 세션이 준비될 때까지 기다린다.
2938
- * 같은 문장을 두 번 보내지 않도록 보낸 값을 기억한다 — 재렌더마다 updated 가 다시 돌기 때문이다.
2939
- */
2940
- if (this.autoAsk && assistantAutoAskKey(this.autoAsk, this.autoAskRequestId) !== this._autoAsked && (this.sessionId || this.prepareSession) && !this.busy) {
2941
- this._autoAsked = assistantAutoAskKey(this.autoAsk, this.autoAskRequestId)
2942
- this.input = this.autoAsk
2943
- this.send()
2944
- }
2945
-
2946
- /* A draft fills the input and waits for the person — it is never sent from here. */
2947
- const draft = assistantDraftDecision({
2948
- draft: this.draft,
2949
- draftRequestId: this.draftRequestId,
2950
- drafted: this._drafted,
2951
- typed: this.input,
2952
- autoAsk: this.autoAsk,
2953
- autoAskRequestId: this.autoAskRequestId
2954
- })
2955
- if (draft.consumed) this._drafted = draft.consumed
2956
- if (draft.fill) {
2957
- this.input = this.draft!
2958
- this.updateComplete.then(() => (this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null)?.focus())
2959
- }
2960
-
2961
2934
  /*
2962
2935
  * The subject changed, so the conversation is over.
2963
2936
  *
@@ -3019,6 +2992,29 @@ export class OxAssistantChat extends LitElement {
3019
2992
  this._stopMessageSubscription()
3020
2993
  }
3021
2994
  }
2995
+ /* Send carried questions only after subject, mode and session cleanup has completed. */
2996
+ if (this.autoAsk && assistantAutoAskKey(this.autoAsk, this.autoAskRequestId) !== this._autoAsked && (this.sessionId || this.prepareSession) && !this.busy) {
2997
+ this._autoAsked = assistantAutoAskKey(this.autoAsk, this.autoAskRequestId)
2998
+ this.input = this.autoAsk
2999
+ void this.send()
3000
+ }
3001
+
3002
+ /* A draft fills the input and waits for the person — it is never sent from here. */
3003
+ const draft = assistantDraftDecision({
3004
+ draft: this.draft,
3005
+ draftRequestId: this.draftRequestId,
3006
+ drafted: this._drafted,
3007
+ typed: this.input,
3008
+ autoAsk: this.autoAsk,
3009
+ autoAskRequestId: this.autoAskRequestId
3010
+ })
3011
+ if (draft.consumed) this._drafted = draft.consumed
3012
+ if (draft.fill) {
3013
+ this.input = this.draft!
3014
+ this.updateComplete.then(() => (this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null)?.focus())
3015
+ }
3016
+
3017
+
3022
3018
  // 자동 스크롤
3023
3019
  const ms = this.renderRoot.querySelector('.messages') as HTMLElement | null
3024
3020
  if (ms) ms.scrollTop = ms.scrollHeight
@@ -36,3 +36,25 @@ describe('navigation wiring', () => {
36
36
  expect(dock).toContain("errorCode: 'conversation-screen-changed'")
37
37
  })
38
38
  })
39
+
40
+
41
+ describe('a carried draft survives opening a new conversation', () => {
42
+ test('automatic review starts after cleanup and is sent once per request', () => {
43
+ const source = readFileSync(join(__dirname, '../components/assistant-chat.ts'), 'utf8')
44
+ const update = source.slice(source.indexOf(' updated(changed:'), source.indexOf(' disconnectedCallback()', source.indexOf(' updated(changed:')))
45
+ const placement = update.indexOf('if (this.autoAsk &&')
46
+ expect(placement).toBeGreaterThan(update.indexOf("if (changed.has('sessionId')"))
47
+ expect(update.slice(placement)).not.toContain("this.input = ''")
48
+ expect(update.slice(placement)).toContain('!== this._autoAsked')
49
+ expect(update.slice(placement)).toContain('void this.send()')
50
+ })
51
+ test('draft placement follows subject, mode and session cleanup', () => {
52
+ const source = readFileSync(join(__dirname, '../components/assistant-chat.ts'), 'utf8')
53
+ const update = source.slice(source.indexOf(' updated(changed:'), source.indexOf(' disconnectedCallback()', source.indexOf(' updated(changed:')))
54
+ const placement = update.indexOf('const draft = assistantDraftDecision(')
55
+ expect(placement).toBeGreaterThan(update.indexOf("if (changed.has('subject'))"))
56
+ expect(placement).toBeGreaterThan(update.indexOf("if (changed.has('mode')"))
57
+ expect(placement).toBeGreaterThan(update.indexOf("if (changed.has('sessionId')"))
58
+ expect(update.slice(placement)).not.toContain("this.input = ''")
59
+ })
60
+ })
@@ -2578,32 +2578,6 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
2578
2578
  updated(changed) {
2579
2579
  if (changed.has('input') || changed.has('composerWide') || changed.has('previewAttachmentId') || changed.has('attachments'))
2580
2580
  this.fitComposer();
2581
- /*
2582
- * 밖에서 넣어 준 질문을 자동 전송한다(오류 토스트의 "AI에게 묻기" 등).
2583
- *
2584
- * sessionId 가 붙기 전에 보내면 대화에 남지 않으므로 세션이 준비될 때까지 기다린다.
2585
- * 같은 문장을 두 번 보내지 않도록 보낸 값을 기억한다 — 재렌더마다 updated 가 다시 돌기 때문이다.
2586
- */
2587
- if (this.autoAsk && assistantAutoAskKey(this.autoAsk, this.autoAskRequestId) !== this._autoAsked && (this.sessionId || this.prepareSession) && !this.busy) {
2588
- this._autoAsked = assistantAutoAskKey(this.autoAsk, this.autoAskRequestId);
2589
- this.input = this.autoAsk;
2590
- this.send();
2591
- }
2592
- /* A draft fills the input and waits for the person — it is never sent from here. */
2593
- const draft = assistantDraftDecision({
2594
- draft: this.draft,
2595
- draftRequestId: this.draftRequestId,
2596
- drafted: this._drafted,
2597
- typed: this.input,
2598
- autoAsk: this.autoAsk,
2599
- autoAskRequestId: this.autoAskRequestId
2600
- });
2601
- if (draft.consumed)
2602
- this._drafted = draft.consumed;
2603
- if (draft.fill) {
2604
- this.input = this.draft;
2605
- this.updateComplete.then(() => this.renderRoot.querySelector('textarea')?.focus());
2606
- }
2607
2581
  /*
2608
2582
  * The subject changed, so the conversation is over.
2609
2583
  *
@@ -2664,6 +2638,27 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
2664
2638
  this._stopMessageSubscription();
2665
2639
  }
2666
2640
  }
2641
+ /* Send carried questions only after subject, mode and session cleanup has completed. */
2642
+ if (this.autoAsk && assistantAutoAskKey(this.autoAsk, this.autoAskRequestId) !== this._autoAsked && (this.sessionId || this.prepareSession) && !this.busy) {
2643
+ this._autoAsked = assistantAutoAskKey(this.autoAsk, this.autoAskRequestId);
2644
+ this.input = this.autoAsk;
2645
+ void this.send();
2646
+ }
2647
+ /* A draft fills the input and waits for the person — it is never sent from here. */
2648
+ const draft = assistantDraftDecision({
2649
+ draft: this.draft,
2650
+ draftRequestId: this.draftRequestId,
2651
+ drafted: this._drafted,
2652
+ typed: this.input,
2653
+ autoAsk: this.autoAsk,
2654
+ autoAskRequestId: this.autoAskRequestId
2655
+ });
2656
+ if (draft.consumed)
2657
+ this._drafted = draft.consumed;
2658
+ if (draft.fill) {
2659
+ this.input = this.draft;
2660
+ this.updateComplete.then(() => this.renderRoot.querySelector('textarea')?.focus());
2661
+ }
2667
2662
  // 자동 스크롤
2668
2663
  const ms = this.renderRoot.querySelector('.messages');
2669
2664
  if (ms)