@things-factory/ai-assistant 10.1.39 → 10.1.40

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.
@@ -15,7 +15,7 @@
15
15
  */
16
16
  import '@material/web/icon/icon.js'
17
17
  import './assistant-session-toolbar.js'
18
- import { assistantAutoAskKey, assistantModelFingerprint, type AssistantRequestContext } from '../utils/assistant-request-context.js'
18
+ import { assistantAutoAskKey, assistantDraftDecision, assistantModelFingerprint, type AssistantRequestContext } from '../utils/assistant-request-context.js'
19
19
 
20
20
  import { LitElement, css, html, nothing } from 'lit'
21
21
  import { customElement, property, state } from 'lit/decorators.js'
@@ -516,6 +516,18 @@ export class OxAssistantChat extends LitElement {
516
516
  @property({ attribute: false })
517
517
  autoAsk?: string
518
518
  @property() autoAskRequestId?: string
519
+
520
+ /**
521
+ * A sentence to place in the input **without sending it** — the pair of `autoAsk`.
522
+ *
523
+ * Some paths hand the person a starting sentence to edit and send themselves (twin's "new twin →
524
+ * AI"). Filled once per `draftRequestId`, with focus on the input; never over text the person is
525
+ * typing; and when `autoAsk` arrives for the same request, `autoAsk` wins
526
+ * (`assistantDraftDecision`).
527
+ */
528
+ @property({ attribute: false })
529
+ draft?: string
530
+ @property() draftRequestId?: string
519
531
  @property({ attribute: false }) contextProvider?: () => AssistantRequestContext
520
532
 
521
533
  /**
@@ -548,6 +560,8 @@ export class OxAssistantChat extends LitElement {
548
560
 
549
561
  /** autoAsk 를 이미 보냈는지 — 재렌더마다 다시 보내지 않기 위한 표식. */
550
562
  private _autoAsked?: string
563
+ /** The draft already placed (or deliberately skipped) — so a re-render does not place it again. */
564
+ private _drafted?: string
551
565
 
552
566
  /** 마지막 send 실패 시 보존 — 다시 시도 버튼 클릭 시 사용 */
553
567
  @state()
@@ -2599,6 +2613,21 @@ export class OxAssistantChat extends LitElement {
2599
2613
  this.send()
2600
2614
  }
2601
2615
 
2616
+ /* A draft fills the input and waits for the person — it is never sent from here. */
2617
+ const draft = assistantDraftDecision({
2618
+ draft: this.draft,
2619
+ draftRequestId: this.draftRequestId,
2620
+ drafted: this._drafted,
2621
+ typed: this.input,
2622
+ autoAsk: this.autoAsk,
2623
+ autoAskRequestId: this.autoAskRequestId
2624
+ })
2625
+ if (draft.consumed) this._drafted = draft.consumed
2626
+ if (draft.fill) {
2627
+ this.input = this.draft!
2628
+ this.updateComplete.then(() => (this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null)?.focus())
2629
+ }
2630
+
2602
2631
  /*
2603
2632
  * The subject changed, so the conversation is over.
2604
2633
  *
@@ -12,6 +12,38 @@ export interface AssistantRequestContext {
12
12
  export function assistantAutoAskKey(text: string, requestId?: string): string {
13
13
  return requestId ? JSON.stringify([requestId, text]) : text
14
14
  }
15
+ /**
16
+ * Whether a draft handed in from outside fills the input now — the pair of `autoAsk` that does not send.
17
+ *
18
+ * A host sometimes wants a sentence placed in the input for the person to edit and send themselves
19
+ * ("new twin → AI" in twin's instance list). Four rules, each a thing a person would notice:
20
+ * · once per request — a re-render must not fill it again after the person cleared or changed it
21
+ * · never over what the person is typing — their text is theirs
22
+ * · when `autoAsk` comes for the same request, it wins — sending is the clearer intent
23
+ * · no draft, nothing to do
24
+ * Returns the key to remember when the draft was consumed (filled, or deliberately skipped), so a
25
+ * skipped draft does not surface later by surprise.
26
+ */
27
+ export function assistantDraftDecision(input: {
28
+ draft?: string
29
+ draftRequestId?: string
30
+ drafted?: string
31
+ typed: string
32
+ autoAsk?: string
33
+ autoAskRequestId?: string
34
+ }): { fill: boolean; consumed?: string } {
35
+ if (!input.draft) return { fill: false }
36
+
37
+ const key = assistantAutoAskKey(input.draft, input.draftRequestId)
38
+ if (key === input.drafted) return { fill: false }
39
+
40
+ const sameRequestAsked = !!input.autoAsk && !!input.draftRequestId && input.autoAskRequestId === input.draftRequestId
41
+ if (sameRequestAsked) return { fill: false, consumed: key }
42
+
43
+ if (input.typed.trim()) return { fill: false, consumed: key }
44
+
45
+ return { fill: true, consumed: key }
46
+ }
15
47
  export function assistantRecentSessions<T extends { id: string }>(sessions: T[], selected: string, limit: number): T[] {
16
48
  const count = Math.max(1, Math.floor(limit) || 5)
17
49
  const recent = sessions.slice(0, count)
@@ -171,6 +171,16 @@ export declare class OxAssistantChat extends LitElement {
171
171
  */
172
172
  autoAsk?: string;
173
173
  autoAskRequestId?: string;
174
+ /**
175
+ * A sentence to place in the input **without sending it** — the pair of `autoAsk`.
176
+ *
177
+ * Some paths hand the person a starting sentence to edit and send themselves (twin's "new twin →
178
+ * AI"). Filled once per `draftRequestId`, with focus on the input; never over text the person is
179
+ * typing; and when `autoAsk` arrives for the same request, `autoAsk` wins
180
+ * (`assistantDraftDecision`).
181
+ */
182
+ draft?: string;
183
+ draftRequestId?: string;
174
184
  contextProvider?: () => AssistantRequestContext;
175
185
  /**
176
186
  * 빈 화면의 제목·부제 — **호스트가 자기 말로 준다.**
@@ -206,6 +216,8 @@ export declare class OxAssistantChat extends LitElement {
206
216
  }>;
207
217
  /** autoAsk 를 이미 보냈는지 — 재렌더마다 다시 보내지 않기 위한 표식. */
208
218
  private _autoAsked?;
219
+ /** The draft already placed (or deliberately skipped) — so a re-render does not place it again. */
220
+ private _drafted?;
209
221
  /** 마지막 send 실패 시 보존 — 다시 시도 버튼 클릭 시 사용 */
210
222
  private lastFailedInput?;
211
223
  /** 되돌려진 patch id 들 — 한 번 revert 한 patch 는 버튼 비활성 */
@@ -17,7 +17,7 @@ import { __decorate, __metadata } from "tslib";
17
17
  */
18
18
  import '@material/web/icon/icon.js';
19
19
  import './assistant-session-toolbar.js';
20
- import { assistantAutoAskKey, assistantModelFingerprint } from '../utils/assistant-request-context.js';
20
+ import { assistantAutoAskKey, assistantDraftDecision, assistantModelFingerprint } from '../utils/assistant-request-context.js';
21
21
  import { LitElement, css, html, nothing } from 'lit';
22
22
  import { customElement, property, state } from 'lit/decorators.js';
23
23
  import { unsafeHTML } from 'lit/directives/unsafe-html.js';
@@ -2272,6 +2272,21 @@ let OxAssistantChat = class OxAssistantChat extends LitElement {
2272
2272
  this.input = this.autoAsk;
2273
2273
  this.send();
2274
2274
  }
2275
+ /* A draft fills the input and waits for the person — it is never sent from here. */
2276
+ const draft = assistantDraftDecision({
2277
+ draft: this.draft,
2278
+ draftRequestId: this.draftRequestId,
2279
+ drafted: this._drafted,
2280
+ typed: this.input,
2281
+ autoAsk: this.autoAsk,
2282
+ autoAskRequestId: this.autoAskRequestId
2283
+ });
2284
+ if (draft.consumed)
2285
+ this._drafted = draft.consumed;
2286
+ if (draft.fill) {
2287
+ this.input = this.draft;
2288
+ this.updateComplete.then(() => this.renderRoot.querySelector('textarea')?.focus());
2289
+ }
2275
2290
  /*
2276
2291
  * The subject changed, so the conversation is over.
2277
2292
  *
@@ -4199,6 +4214,14 @@ __decorate([
4199
4214
  property(),
4200
4215
  __metadata("design:type", String)
4201
4216
  ], OxAssistantChat.prototype, "autoAskRequestId", void 0);
4217
+ __decorate([
4218
+ property({ attribute: false }),
4219
+ __metadata("design:type", String)
4220
+ ], OxAssistantChat.prototype, "draft", void 0);
4221
+ __decorate([
4222
+ property(),
4223
+ __metadata("design:type", String)
4224
+ ], OxAssistantChat.prototype, "draftRequestId", void 0);
4202
4225
  __decorate([
4203
4226
  property({ attribute: false }),
4204
4227
  __metadata("design:type", Function)