comisai 1.0.16 → 1.0.17

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.
Files changed (90) hide show
  1. package/node_modules/@comis/agent/package.json +1 -1
  2. package/node_modules/@comis/channels/package.json +1 -1
  3. package/node_modules/@comis/cli/dist/wizard/non-interactive.js +1 -0
  4. package/node_modules/@comis/cli/dist/wizard/steps/01-detect-existing.js +4 -0
  5. package/node_modules/@comis/cli/dist/wizard/steps/07-gateway.js +9 -0
  6. package/node_modules/@comis/cli/dist/wizard/steps/10-write-config.js +2 -0
  7. package/node_modules/@comis/cli/dist/wizard/steps/12-finish.js +5 -2
  8. package/node_modules/@comis/cli/dist/wizard/types.d.ts +1 -0
  9. package/node_modules/@comis/cli/package.json +1 -1
  10. package/node_modules/@comis/core/dist/config/schema-gateway.d.ts +17 -2
  11. package/node_modules/@comis/core/dist/config/schema-gateway.js +11 -0
  12. package/node_modules/@comis/core/dist/config/schema.d.ts +60 -57
  13. package/node_modules/@comis/core/package.json +1 -1
  14. package/node_modules/@comis/daemon/dist/wiring/setup-gateway.js +34 -6
  15. package/node_modules/@comis/daemon/package.json +1 -1
  16. package/node_modules/@comis/gateway/package.json +1 -1
  17. package/node_modules/@comis/infra/package.json +1 -1
  18. package/node_modules/@comis/memory/package.json +1 -1
  19. package/node_modules/@comis/scheduler/package.json +1 -1
  20. package/node_modules/@comis/shared/package.json +1 -1
  21. package/node_modules/@comis/skills/package.json +1 -1
  22. package/node_modules/@comis/web/dist/android-chrome-192x192.png +0 -0
  23. package/node_modules/@comis/web/dist/android-chrome-512x512.png +0 -0
  24. package/node_modules/@comis/web/dist/apple-touch-icon.png +0 -0
  25. package/node_modules/@comis/web/dist/assets/agent-detail-BG9MGWWj.js +615 -0
  26. package/node_modules/@comis/web/dist/assets/agent-editor-C26Q_xCs.js +2173 -0
  27. package/node_modules/@comis/web/dist/assets/agent-list-LHCJ4rw2.js +504 -0
  28. package/node_modules/@comis/web/dist/assets/approvals-q9VH_IKr.js +54 -0
  29. package/node_modules/@comis/web/dist/assets/billing-view-CtYvBqTE.js +375 -0
  30. package/node_modules/@comis/web/dist/assets/channel-detail-CaInesJM.js +681 -0
  31. package/node_modules/@comis/web/dist/assets/channel-list-B8dj3O9a.js +323 -0
  32. package/node_modules/@comis/web/dist/assets/chat-console-CNmzl0JW.js +943 -0
  33. package/node_modules/@comis/web/dist/assets/config-editor-DX4ITw6y.js +1374 -0
  34. package/node_modules/@comis/web/dist/assets/context-dag-browser-BwiaF5tf.js +393 -0
  35. package/node_modules/@comis/web/dist/assets/context-engine-BZ5Am6hA.js +393 -0
  36. package/node_modules/@comis/web/dist/assets/delivery-view-OfBZof-m.js +392 -0
  37. package/node_modules/@comis/web/dist/assets/diagnostics-view-YFwCxgr2.js +231 -0
  38. package/node_modules/@comis/web/dist/assets/directive-DoeGSK_T.js +1 -0
  39. package/node_modules/@comis/web/dist/assets/extract-variables-BM5qyK-s.js +149 -0
  40. package/node_modules/@comis/web/dist/assets/ic-array-editor-B7m6x7-S.js +118 -0
  41. package/node_modules/@comis/web/dist/assets/ic-breadcrumb-CUMpp3BL.js +75 -0
  42. package/node_modules/@comis/web/dist/assets/ic-budget-segment-bar-BtJ6x5mN.js +64 -0
  43. package/node_modules/@comis/web/dist/assets/ic-chat-message-CFyDJd0z.js +352 -0
  44. package/node_modules/@comis/web/dist/assets/ic-confirm-dialog-CCDbB04e.js +110 -0
  45. package/node_modules/@comis/web/dist/assets/ic-connection-dot-CnT1b8xr.js +54 -0
  46. package/node_modules/@comis/web/dist/assets/ic-data-table-CKUNTxHw.js +277 -0
  47. package/node_modules/@comis/web/dist/assets/ic-delivery-row-GP5Fkygs.js +67 -0
  48. package/node_modules/@comis/web/dist/assets/ic-detail-panel-BF83r-if.js +116 -0
  49. package/node_modules/@comis/web/dist/assets/ic-empty-state-60l2ePhd.js +52 -0
  50. package/node_modules/@comis/web/dist/assets/ic-graph-canvas-C8FuSMe1.js +359 -0
  51. package/node_modules/@comis/web/dist/assets/ic-icon-xeGTVhVG.js +33 -0
  52. package/node_modules/@comis/web/dist/assets/ic-layer-waterfall-COvEYMg5.js +69 -0
  53. package/node_modules/@comis/web/dist/assets/ic-relative-time-3FqpjeAI.js +12 -0
  54. package/node_modules/@comis/web/dist/assets/ic-search-input-CSOxY9g7.js +92 -0
  55. package/node_modules/@comis/web/dist/assets/ic-select-Ce-Raudx.js +127 -0
  56. package/node_modules/@comis/web/dist/assets/ic-tabs-B7QtM_v8.js +95 -0
  57. package/node_modules/@comis/web/dist/assets/ic-tag-CPPUnDLF.js +33 -0
  58. package/node_modules/@comis/web/dist/assets/ic-time-range-picker-CypCT68y.js +93 -0
  59. package/node_modules/@comis/web/dist/assets/ic-tool-call-7MaXSsCW.js +146 -0
  60. package/node_modules/@comis/web/dist/assets/index-CEcM1R_C.js +2830 -0
  61. package/node_modules/@comis/web/dist/assets/index-CIJFuItj.css +1 -0
  62. package/node_modules/@comis/web/dist/assets/mcp-management-BNZPnpDn.js +582 -0
  63. package/node_modules/@comis/web/dist/assets/media-config-BBvTYxOX.js +314 -0
  64. package/node_modules/@comis/web/dist/assets/media-test-BkK3RCRK.js +496 -0
  65. package/node_modules/@comis/web/dist/assets/memory-inspector-1hDGCGat.js +1139 -0
  66. package/node_modules/@comis/web/dist/assets/message-center-CXefwsUu.js +785 -0
  67. package/node_modules/@comis/web/dist/assets/models-C1qcU_j3.js +894 -0
  68. package/node_modules/@comis/web/dist/assets/observability-types-D7jUtSde.js +1 -0
  69. package/node_modules/@comis/web/dist/assets/observe-view-C0VBhX4C.js +814 -0
  70. package/node_modules/@comis/web/dist/assets/pipeline-builder-DcUUIrm0.js +1496 -0
  71. package/node_modules/@comis/web/dist/assets/pipeline-history-DkfOQ6SW.js +317 -0
  72. package/node_modules/@comis/web/dist/assets/pipeline-history-detail-hyHgD0ai.js +287 -0
  73. package/node_modules/@comis/web/dist/assets/pipeline-list-BPW8hV-q.js +518 -0
  74. package/node_modules/@comis/web/dist/assets/pipeline-monitor-Bip16T7e.js +972 -0
  75. package/node_modules/@comis/web/dist/assets/scheduler-BGgwKd06.js +1182 -0
  76. package/node_modules/@comis/web/dist/assets/security-D15st4xx.js +1224 -0
  77. package/node_modules/@comis/web/dist/assets/session-detail-SGEYNJ0M.js +632 -0
  78. package/node_modules/@comis/web/dist/assets/session-key-parser-DPORMVyU.js +1 -0
  79. package/node_modules/@comis/web/dist/assets/session-list-6ybUTxbY.js +231 -0
  80. package/node_modules/@comis/web/dist/assets/setup-wizard-nT0tz9QP.js +853 -0
  81. package/node_modules/@comis/web/dist/assets/skills-D8yVfSUy.js +1051 -0
  82. package/node_modules/@comis/web/dist/assets/subagents-HHXMeHYo.js +193 -0
  83. package/node_modules/@comis/web/dist/assets/workspace-manager-BQlr10iH.js +785 -0
  84. package/node_modules/@comis/web/dist/comis-logo.png +0 -0
  85. package/node_modules/@comis/web/dist/favicon-16x16.png +0 -0
  86. package/node_modules/@comis/web/dist/favicon-32x32.png +0 -0
  87. package/node_modules/@comis/web/dist/favicon.ico +0 -0
  88. package/node_modules/@comis/web/dist/index.html +17 -0
  89. package/node_modules/@comis/web/package.json +29 -0
  90. package/package.json +15 -13
@@ -0,0 +1,943 @@
1
+ import{s as $,f as M,i as C,n as p,a as U,b as c,t as D,A as _,I as m,r as d}from"./index-CEcM1R_C.js";import{p as A,f as R}from"./session-key-parser-DPORMVyU.js";import{s as S,a as B}from"./ic-tool-call-7MaXSsCW.js";import"./ic-chat-message-CFyDJd0z.js";import"./ic-search-input-CSOxY9g7.js";import"./ic-tag-CPPUnDLF.js";import"./ic-relative-time-3FqpjeAI.js";import"./ic-empty-state-60l2ePhd.js";import"./ic-icon-xeGTVhVG.js";import"./ic-budget-segment-bar-BtJ6x5mN.js";import"./directive-DoeGSK_T.js";const N=(e,t,s)=>(s.configurable=!0,s.enumerable=!0,Reflect.decorate&&typeof t!="object"&&Object.defineProperty(e,t,s),s);function z(e,t){return(s,a,i)=>{const n=r=>r.renderRoot?.querySelector(e)??null;return N(s,a,{get(){return n(this)}})}}var j=Object.defineProperty,P=Object.getOwnPropertyDescriptor,w=(e,t,s,a)=>{for(var i=a>1?void 0:a?P(t,s):t,n=e.length-1,r;n>=0;n--)(r=e[n])&&(i=(a?r(t,s,i):r(i))||i);return a&&i&&j(t,s,i),i};let y=class extends U{constructor(){super(...arguments),this.sessions=[],this.selectedKey="",this.filter="",this.open=!1}_renderSessionItem(e){const s=e.key===this.selectedKey?"session-item session-item--active":"session-item",a=A(e.key),i=a?R(a):e.key.length>8?e.key.slice(0,8):e.key,n=a?.channelId??e.channelType;return c`
2
+ <div
3
+ class=${s}
4
+ @click=${()=>this.dispatchEvent(new CustomEvent("session-selected",{detail:{key:e.key},bubbles:!0,composed:!0}))}
5
+ role="button"
6
+ tabindex="0"
7
+ @keydown=${r=>{(r.key==="Enter"||r.key===" ")&&(r.preventDefault(),this.dispatchEvent(new CustomEvent("session-selected",{detail:{key:e.key},bubbles:!0,composed:!0})))}}
8
+ >
9
+ <span class="session-key" title=${e.key}>${i}</span>
10
+ <div class="session-meta">
11
+ <ic-tag variant="accent" size="sm">${n}</ic-tag>
12
+ <span class="msg-count">${e.messageCount}</span>
13
+ <ic-relative-time .timestamp=${e.lastActivity}></ic-relative-time>
14
+ </div>
15
+ </div>
16
+ `}render(){return c`
17
+ <aside class="sidebar">
18
+ <div class="sidebar-header">
19
+ <span class="sidebar-title">Sessions</span>
20
+ <button class="new-btn" @click=${()=>this.dispatchEvent(new CustomEvent("new-session",{bubbles:!0,composed:!0}))}>
21
+ <ic-icon name="plus" size="14px"></ic-icon>
22
+ New
23
+ </button>
24
+ </div>
25
+ <div class="sidebar-search">
26
+ <ic-search-input
27
+ placeholder="Filter sessions..."
28
+ debounce="200"
29
+ @search=${e=>this.dispatchEvent(new CustomEvent("filter-changed",{detail:{value:e.detail},bubbles:!0,composed:!0}))}
30
+ ></ic-search-input>
31
+ </div>
32
+ <div class="session-list">
33
+ ${this.sessions.map(e=>this._renderSessionItem(e))}
34
+ </div>
35
+ </aside>
36
+ `}};y.styles=[$,M,C`
37
+ :host {
38
+ display: block;
39
+ }
40
+
41
+ .sidebar {
42
+ display: flex;
43
+ flex-direction: column;
44
+ height: 100%;
45
+ border-right: 1px solid var(--ic-border);
46
+ background: var(--ic-surface);
47
+ width: 280px;
48
+ overflow: hidden;
49
+ }
50
+
51
+ .sidebar-header {
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: space-between;
55
+ padding: var(--ic-space-sm) var(--ic-space-md);
56
+ border-bottom: 1px solid var(--ic-border);
57
+ }
58
+
59
+ .sidebar-title {
60
+ font-size: var(--ic-text-sm);
61
+ font-weight: 600;
62
+ color: var(--ic-text);
63
+ }
64
+
65
+ .new-btn {
66
+ display: flex;
67
+ align-items: center;
68
+ gap: var(--ic-space-xs);
69
+ padding: 0.375rem 0.75rem;
70
+ background: var(--ic-accent);
71
+ color: white;
72
+ border: none;
73
+ border-radius: var(--ic-radius-md);
74
+ font-size: var(--ic-text-xs);
75
+ font-family: inherit;
76
+ cursor: pointer;
77
+ }
78
+
79
+ .new-btn:hover {
80
+ opacity: 0.9;
81
+ }
82
+
83
+ .sidebar-search {
84
+ padding: var(--ic-space-sm) var(--ic-space-md);
85
+ border-bottom: 1px solid var(--ic-border);
86
+ }
87
+
88
+ .session-list {
89
+ flex: 1;
90
+ overflow-y: auto;
91
+ padding: var(--ic-space-xs) 0;
92
+ }
93
+
94
+ .session-item {
95
+ display: flex;
96
+ flex-direction: column;
97
+ gap: 2px;
98
+ padding: var(--ic-space-sm) var(--ic-space-md);
99
+ cursor: pointer;
100
+ border-bottom: 1px solid color-mix(in srgb, var(--ic-border) 50%, transparent);
101
+ transition: background 0.15s;
102
+ }
103
+
104
+ .session-item:hover {
105
+ background: var(--ic-surface-2);
106
+ }
107
+
108
+ .session-item--active {
109
+ background: color-mix(in srgb, var(--ic-accent) 10%, transparent);
110
+ border-left: 3px solid var(--ic-accent);
111
+ }
112
+
113
+ .session-key {
114
+ font-size: var(--ic-text-sm);
115
+ font-weight: 500;
116
+ color: var(--ic-text);
117
+ overflow: hidden;
118
+ text-overflow: ellipsis;
119
+ white-space: nowrap;
120
+ }
121
+
122
+ .session-meta {
123
+ display: flex;
124
+ align-items: center;
125
+ gap: var(--ic-space-xs);
126
+ font-size: var(--ic-text-xs);
127
+ color: var(--ic-text-dim);
128
+ }
129
+
130
+ .msg-count {
131
+ font-size: var(--ic-text-xs);
132
+ color: var(--ic-text-dim);
133
+ }
134
+ `];w([p({type:Array})],y.prototype,"sessions",2);w([p({type:String})],y.prototype,"selectedKey",2);w([p({type:String})],y.prototype,"filter",2);w([p({type:Boolean})],y.prototype,"open",2);y=w([D("ic-session-sidebar")],y);var F=Object.defineProperty,K=Object.getOwnPropertyDescriptor,v=(e,t,s,a)=>{for(var i=a>1?void 0:a?K(t,s):t,n=e.length-1,r;n>=0;n--)(r=e[n])&&(i=(a?r(t,s,i):r(i))||i);return a&&i&&F(t,s,i),i};let g=class extends U{constructor(){super(...arguments),this.messages=[],this.streaming=!1,this.sending=!1,this.loading=!1,this.hasSession=!1,this.streamingContent="",this.streamingTokens=0,this.authToken="",this.hasNewMessages=!1}_formatTokens(e){return e===0?"":e<1e3?`${e} tokens`:`${(e/1e3).toFixed(1)}k tokens`}_renderMessage(e){if(e.role==="tool"){let t=e.content;try{t=JSON.parse(e.content)}catch{}return c`
135
+ <ic-tool-call .toolName=${"tool"} .output=${t} .status=${"success"}></ic-tool-call>
136
+ `}return c`
137
+ <ic-chat-message
138
+ .role=${e.role}
139
+ .content=${e.content}
140
+ .timestamp=${e.timestamp}
141
+ .messageId=${e.id}
142
+ .mediaToken=${this.authToken}
143
+ @retry=${t=>this.dispatchEvent(new CustomEvent("retry",{detail:t.detail,bubbles:!0,composed:!0}))}
144
+ @delete=${t=>this.dispatchEvent(new CustomEvent("delete",{detail:t.detail,bubbles:!0,composed:!0}))}
145
+ ></ic-chat-message>
146
+ ${e.toolCalls?.map(t=>c`
147
+ <ic-tool-call
148
+ .toolName=${t.name}
149
+ .input=${typeof t.input=="string"?t.input:JSON.stringify(t.input,null,2)}
150
+ .output=${typeof t.output=="string"?t.output:JSON.stringify(t.output,null,2)}
151
+ .status=${t.status==="running"?"running":t.status==="error"?"error":"success"}
152
+ ></ic-tool-call>
153
+ `)}
154
+ `}_renderStreamingIndicator(){return this.streamingContent?c`
155
+ <ic-chat-message
156
+ .role=${"assistant"} .content=${this.streamingContent}
157
+ .timestamp=${Date.now()} .showActions=${!1}
158
+ ></ic-chat-message>
159
+ <div class="streaming-indicator">
160
+ <span class="token-counter">${this._formatTokens(this.streamingTokens)}</span>
161
+ </div>
162
+ `:c`
163
+ <div class="streaming-indicator">
164
+ <div class="typing-dots">
165
+ <span class="typing-dot"></span>
166
+ <span class="typing-dot"></span>
167
+ <span class="typing-dot"></span>
168
+ </div>
169
+ <span class="token-counter">${this._formatTokens(this.streamingTokens)}</span>
170
+ </div>
171
+ `}render(){return this.loading?c`<ic-skeleton-view variant="detail"></ic-skeleton-view>`:this.hasSession?this.messages.length===0&&!this.streaming&&!this.sending?c`
172
+ <div class="message-area">
173
+ <ic-empty-state icon="chat" message="No messages yet" description="Start a conversation."></ic-empty-state>
174
+ </div>
175
+ `:c`
176
+ <div class="message-area">
177
+ ${this.messages.map(e=>this._renderMessage(e))}
178
+ ${this.sending&&!this.streaming?c`<div class="thinking-indicator">
179
+ <div class="typing-dots">
180
+ <span class="typing-dot"></span><span class="typing-dot"></span><span class="typing-dot"></span>
181
+ </div>
182
+ <span class="thinking-label">Thinking...</span>
183
+ </div>`:_}
184
+ ${this.streaming?this._renderStreamingIndicator():_}
185
+ ${this.hasNewMessages?c`<button class="new-messages-btn"
186
+ @click=${()=>this.dispatchEvent(new CustomEvent("scroll-to-bottom",{bubbles:!0,composed:!0}))}
187
+ >New messages</button>`:_}
188
+ </div>
189
+ `:c`
190
+ <div class="message-area">
191
+ <ic-empty-state icon="chat" message="Select a session"
192
+ description="Choose a session from the sidebar or create a new one."
193
+ ></ic-empty-state>
194
+ </div>
195
+ `}};g.styles=[$,C`
196
+ :host {
197
+ display: block;
198
+ flex: 1;
199
+ overflow-y: auto;
200
+ }
201
+
202
+ .message-area {
203
+ flex: 1;
204
+ overflow-y: auto;
205
+ padding: var(--ic-space-md);
206
+ display: flex;
207
+ flex-direction: column;
208
+ gap: var(--ic-space-sm);
209
+ }
210
+
211
+ .thinking-indicator {
212
+ display: flex;
213
+ align-items: center;
214
+ gap: var(--ic-space-sm);
215
+ padding: var(--ic-space-sm);
216
+ color: var(--ic-text-dim);
217
+ font-size: var(--ic-text-sm);
218
+ }
219
+
220
+ .typing-dots {
221
+ display: flex;
222
+ gap: 4px;
223
+ }
224
+
225
+ .typing-dot {
226
+ width: 6px;
227
+ height: 6px;
228
+ background: var(--ic-text-dim);
229
+ border-radius: 50%;
230
+ animation: dot-pulse 1.5s infinite;
231
+ }
232
+
233
+ .typing-dot:nth-child(2) {
234
+ animation-delay: 0.15s;
235
+ }
236
+
237
+ .typing-dot:nth-child(3) {
238
+ animation-delay: 0.3s;
239
+ }
240
+
241
+ @keyframes dot-pulse {
242
+ 0%, 80%, 100% { opacity: 0.3; }
243
+ 40% { opacity: 1; }
244
+ }
245
+
246
+ .thinking-label {
247
+ font-style: italic;
248
+ }
249
+
250
+ .streaming-indicator {
251
+ display: flex;
252
+ align-items: center;
253
+ gap: var(--ic-space-sm);
254
+ padding: var(--ic-space-xs) var(--ic-space-md);
255
+ color: var(--ic-text-dim);
256
+ font-size: var(--ic-text-xs);
257
+ }
258
+
259
+ .token-counter {
260
+ font-family: ui-monospace, monospace;
261
+ }
262
+
263
+ .new-messages-btn {
264
+ position: sticky;
265
+ bottom: var(--ic-space-md);
266
+ align-self: center;
267
+ padding: 0.375rem 1rem;
268
+ background: var(--ic-accent);
269
+ color: white;
270
+ border: none;
271
+ border-radius: var(--ic-radius-md);
272
+ font-size: var(--ic-text-xs);
273
+ cursor: pointer;
274
+ font-family: inherit;
275
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
276
+ }
277
+ `];v([p({type:Array})],g.prototype,"messages",2);v([p({type:Boolean})],g.prototype,"streaming",2);v([p({type:Boolean})],g.prototype,"sending",2);v([p({type:Boolean})],g.prototype,"loading",2);v([p({type:Boolean})],g.prototype,"hasSession",2);v([p({type:String})],g.prototype,"streamingContent",2);v([p({type:Number})],g.prototype,"streamingTokens",2);v([p({type:String})],g.prototype,"authToken",2);v([p({type:Boolean})],g.prototype,"hasNewMessages",2);g=v([D("ic-message-renderer")],g);var V=Object.defineProperty,H=Object.getOwnPropertyDescriptor,l=(e,t,s,a)=>{for(var i=a>1?void 0:a?H(t,s):t,n=e.length-1,r;n>=0;n--)(r=e[n])&&(i=(a?r(t,s,i):r(i))||i);return a&&i&&V(t,s,i),i};const k=[{command:"/new",description:"Start a new session",icon:"plus"},{command:"/reset",description:"Reset current session",icon:"refresh"},{command:"/export",description:"Export session as JSONL",icon:"download"},{command:"/compact",description:"Compact current session context",icon:"compress"},{command:"/switch",description:"Switch to another agent",icon:"agents"},{command:"/help",description:"Show available commands",icon:"chat"}],J=5,Q=10*1024*1024,q=120;let o=class extends U{constructor(){super(...arguments),this.apiClient=null,this.rpcClient=null,this.eventDispatcher=null,this.sessionKey="",this.authToken="",this._sessions=[],this._activeSession="",this._messages=[],this._agents=[],this._selectedAgent="default",this._loading=!0,this._searchQuery="",this._sidebarOpen=!1,this._hasNewMessages=!1,this._inputValue="",this._sending=!1,this._attachments=[],this._recording=!1,this._recordingDuration=0,this._transcribing=!1,this._dragOver=!1,this._showSlashMenu=!1,this._slashFilter="",this._slashSelectedIndex=0,this._streaming=!1,this._streamingTokens=0,this._streamingContent="",this._budgetSegments=[],this._budgetTotal=0,this._userScrolledUp=!1,this._streamBuffer="",this._rafPending=!1,this._eventUnsubs=[],this._rpcStatusUnsub=null,this._dataLoaded=!1,this._mediaRecorder=null,this._audioChunks=[],this._recordingTimer=null}connectedCallback(){super.connectedCallback(),this._setupEventListeners()}disconnectedCallback(){super.disconnectedCallback();for(const e of this._eventUnsubs)e();this._eventUnsubs=[],this._rpcStatusUnsub?.(),this._rpcStatusUnsub=null,this._recordingTimer!==null&&clearInterval(this._recordingTimer),this._mediaRecorder?.state==="recording"&&this._mediaRecorder.stop();for(const e of this._attachments)e.previewUrl&&URL.revokeObjectURL(e.previewUrl)}updated(e){e.has("_messages")&&!this._userScrolledUp&&this._scrollToBottom(),e.has("rpcClient")&&this.rpcClient&&(this._rpcStatusUnsub?.(),this.rpcClient.status==="connected"?this._initialLoad():this._rpcStatusUnsub=this.rpcClient.onStatusChange(t=>{t==="connected"&&!this._dataLoaded&&this._initialLoad()})),e.has("apiClient")&&this.apiClient&&this._agents.length<=1&&this._loadAgents()}_initialLoad(){this._dataLoaded||(this._dataLoaded=!0,this._loadSessions())}_setupEventListeners(){const e=i=>{const n=i.detail;n.sessionKey===this._activeSession&&this._appendMessage(n)};document.addEventListener("message:received",e),this._eventUnsubs.push(()=>document.removeEventListener("message:received",e));const t=i=>{const n=i.detail;n.sessionKey===this._activeSession&&this._appendMessage(n)};document.addEventListener("message:sent",t),this._eventUnsubs.push(()=>document.removeEventListener("message:sent",t));const s=i=>{const n=i.detail,r={key:String(n.sessionKey??""),agentId:String(n.agentId??"unknown"),channelType:String(n.channelType??"web"),messageCount:0,lastActivity:Date.now()};this._sessions=[r,...this._sessions]};document.addEventListener("session:created",s),this._eventUnsubs.push(()=>document.removeEventListener("session:created",s));const a=i=>{const n=i.detail;if(n.sessionKey===this._activeSession&&(this._streaming||(this._streaming=!0,this._streamingTokens=0,this._streamingContent="",this._streamBuffer=""),typeof n.content=="string"&&(this._streamBuffer+=n.content,this._rafPending||(this._rafPending=!0,requestAnimationFrame(()=>{this._streamingContent=this._streamBuffer,this._rafPending=!1}))),typeof n.tokens=="number"&&(this._streamingTokens=n.tokens),n.done===!0)){if(this._streamingContent=this._streamBuffer,this._streamBuffer.trim()){const r={id:crypto.randomUUID(),role:"assistant",content:this._streamBuffer,timestamp:Date.now()};this._messages=[...this._messages,r]}this._streaming=!1,this._streamingTokens=0,this._streamingContent="",this._streamBuffer="",this._rafPending=!1,this._focusInput()}};if(document.addEventListener("message:streaming",a),this._eventUnsubs.push(()=>document.removeEventListener("message:streaming",a)),this.rpcClient){const i=this.rpcClient.onNotification((r,u)=>{if(r!=="notification.message")return;const h=u,f=typeof h?.text=="string"?h.text:"";if(!f)return;console.debug("[chat] notification.message received, length:",f.length);const x={id:crypto.randomUUID(),role:"assistant",content:f,timestamp:typeof h?.timestamp=="number"?h.timestamp:Date.now()};this._messages=[...this._messages,x],this._syncSessionMessageCount(),this._scrollToBottom()});this._eventUnsubs.push(i);const n=this.rpcClient.onNotification((r,u)=>{if(r!=="notification.attachment")return;const h=u,f=typeof h?.url=="string"?h.url:"";if(!f)return;console.debug("[chat] notification.attachment received:",h?.type,h?.fileName);const x=h?.type??"file",b=h?.fileName??"attachment",T=typeof h?.caption=="string"?h.caption:"",L=h?.mimeType??"",I=JSON.stringify({url:f,type:x,mimeType:L,fileName:b}),E=T?`${T}
278
+
279
+ <!-- attachment:${I} -->`:`<!-- attachment:${I} -->`,O={id:crypto.randomUUID(),role:"assistant",content:E,timestamp:typeof h?.timestamp=="number"?h.timestamp:Date.now()};this._messages=[...this._messages,O],this._syncSessionMessageCount(),this._scrollToBottom()});this._eventUnsubs.push(n)}}_appendMessage(e){const t={id:String(e.id??crypto.randomUUID()),role:e.role??"assistant",content:String(e.content??""),timestamp:e.timestamp??Date.now()};this._messages=[...this._messages,t],this._userScrolledUp&&(this._hasNewMessages=!0)}async _loadSessions(){if(!this.rpcClient){this._loading=!1;return}try{const t=(await this.rpcClient.call("session.list",{kind:"dm"}))?.sessions??[];if(this._sessions=t.map(s=>({key:s.sessionKey,agentId:s.agentId,channelType:s.channelId.startsWith("web:")?"web":s.kind,messageCount:s.messageCount??0,lastActivity:s.updatedAt})),this._loading=!1,this.sessionKey){const s=this._sessions.find(a=>a.key===this.sessionKey);s&&(this._activeSession=s.key,this._loadSessionHistory())}}catch{this._sessions=[],this._loading=!1}}async _loadSessionHistory(){if(!(!this.rpcClient||!this._activeSession)){this._loading=!0;try{const t=(await this.rpcClient.call("session.history",{session_key:this._activeSession}))?.messages??[];this._messages=t.map(s=>({id:s.id??crypto.randomUUID(),role:s.role,content:s.role==="assistant"?S(s.content):s.role==="user"?B(s.content):s.content,timestamp:s.timestamp??0,toolCalls:s.toolCalls})).filter(s=>s.content!==""||s.role!=="assistant")}catch{this._messages=[]}finally{this._loading=!1,this._scrollToBottom()}this._loadBudgetData()}}async _loadBudgetData(){if(!this.rpcClient||!this._activeSession){this._budgetSegments=[],this._budgetTotal=0;return}const t=this._sessions.find(s=>s.key===this._activeSession)?.agentId??"default";try{const a=(await this.rpcClient.call("obs.context.pipeline",{agentId:t,limit:1}))?.snapshots??[];if(a.length===0){this._budgetSegments=[],this._budgetTotal=0;return}const i=a[0],n=i.tokensLoaded??0,r=i.tokensEvicted??0,u=i.tokensMasked??0,h=i.budgetUtilization??0,f=h>0?Math.round(n/h):0,x=Math.max(0,f-n),b=[];n>0&&b.push({label:"Loaded",tokens:n,color:"var(--ic-accent)"}),r>0&&b.push({label:"Evicted",tokens:r,color:"var(--ic-warning)"}),u>0&&b.push({label:"Masked",tokens:u,color:"var(--ic-text-dim)"}),x>0&&b.push({label:"Available",tokens:x,color:"var(--ic-surface-2)"}),this._budgetSegments=b,this._budgetTotal=f}catch{this._budgetSegments=[],this._budgetTotal=0}}async _loadAgents(){if(this.apiClient)try{const e=await this.apiClient.getAgents();this._agents=e.length>0?e.map(t=>({id:t.id,name:t.name??t.id,model:t.model})):[{id:"default",name:"Default",model:"unknown"}]}catch{this._agents=[{id:"default",name:"Default",model:"unknown"}]}}_createNewSession(){const e=`web:${this._selectedAgent}:${crypto.randomUUID()}`,t={key:e,agentId:this._selectedAgent,channelType:"web",messageCount:0,lastActivity:Date.now()};this._sessions=[t,...this._sessions],this._activeSession=e,this._messages=[]}_selectSession(e){this._activeSession=e,this._sidebarOpen=!1,this._loadSessionHistory()}_handleScroll(){if(!this._messageArea)return;const{scrollTop:e,scrollHeight:t,clientHeight:s}=this._messageArea,a=t-e-s<50;this._userScrolledUp=!a,a&&(this._hasNewMessages=!1)}_scrollToBottom(){requestAnimationFrame(()=>{this._messageArea&&(this._messageArea.scrollTop=this._messageArea.scrollHeight,this._userScrolledUp=!1,this._hasNewMessages=!1)})}_focusInput(){this.updateComplete.then(()=>{setTimeout(()=>{this._textarea&&!this._textarea.disabled&&this._textarea.focus()},0)})}_handleInput(e){const t=e.target;this._inputValue=t.value,t.style.height="auto",t.style.height=`${Math.min(t.scrollHeight,128)}px`,this._inputValue.startsWith("/")?(this._slashFilter=this._inputValue.slice(1),this._showSlashMenu=!0,this._slashSelectedIndex=0):this._showSlashMenu=!1}_handleKeydown(e){if(this._showSlashMenu){const t=this._getFilteredSlashCommands();if(e.key==="ArrowDown"){e.preventDefault(),this._slashSelectedIndex=(this._slashSelectedIndex+1)%t.length;return}if(e.key==="ArrowUp"){e.preventDefault(),this._slashSelectedIndex=(this._slashSelectedIndex-1+t.length)%t.length;return}if(e.key==="Enter"||e.key==="Tab"){e.preventDefault(),t.length>0&&this._executeSlashCommand(t[this._slashSelectedIndex].command);return}if(e.key==="Escape"){e.preventDefault(),this._showSlashMenu=!1;return}}e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),this._sendMessage())}async _sendMessage(){const e=this._inputValue.trim();if(!(e===""&&this._attachments.length===0||this._sending)&&this.apiClient&&!(!this._activeSession&&(this._createNewSession(),!this._activeSession))){if(this._sending=!0,e){const t={id:crypto.randomUUID(),role:"user",content:e,timestamp:Date.now()};this._messages=[...this._messages,t]}this._inputValue="",this._textarea&&(this._textarea.style.height="auto"),this._scrollToBottom();try{for(const a of this._attachments)a.previewUrl&&URL.revokeObjectURL(a.previewUrl);this._attachments=[];const t=await this.apiClient.chat(e,this._selectedAgent,this._activeSession??void 0),s=t.response?S(t.response):"";if(s){const a={id:crypto.randomUUID(),role:"assistant",content:s,timestamp:Date.now()};this._messages=[...this._messages,a]}}catch(t){const s={id:crypto.randomUUID(),role:"error",content:t instanceof Error?t.message:"Failed to send message",timestamp:Date.now()};this._messages=[...this._messages,s]}finally{this._sending=!1,this._syncSessionMessageCount(),this._scrollToBottom(),this._focusInput()}}}_syncSessionMessageCount(){if(!this._activeSession)return;const e=this._messages.filter(t=>t.role!=="error").length;this._sessions=this._sessions.map(t=>t.key===this._activeSession?{...t,messageCount:e,lastActivity:Date.now()}:t)}async _startRecording(){if(!navigator.mediaDevices){m.show("Microphone access not available","error");return}try{const e=await navigator.mediaDevices.getUserMedia({audio:!0});this._mediaRecorder=new MediaRecorder(e),this._audioChunks=[],this._recording=!0,this._recordingDuration=0,this._recordingTimer=setInterval(()=>{this._recordingDuration++,this._recordingDuration>=q&&(m.show("Maximum recording duration reached","warning"),this._stopRecording())},1e3),this._mediaRecorder.ondataavailable=t=>{t.data.size>0&&this._audioChunks.push(t.data)},this._mediaRecorder.onerror=()=>{m.show("Recording error occurred","error"),this._resetRecordingState()},this._mediaRecorder.onstop=async()=>{const t=new Blob(this._audioChunks,{type:"audio/webm"});this._transcribing=!0;try{const s=await t.arrayBuffer(),a=new Uint8Array(s);let i="";for(let u=0;u<a.length;u++)i+=String.fromCharCode(a[u]);const n=btoa(i),r=await this.rpcClient.call("audio.transcribe",{audio:n,format:"webm"});r?.text&&(this._inputValue+=(this._inputValue?" ":"")+r.text)}catch{m.show("Transcription failed","error")}finally{this._transcribing=!1}e.getTracks().forEach(s=>s.stop())},this._mediaRecorder.start()}catch{m.show("Microphone access denied","error")}}_stopRecording(){this._mediaRecorder&&this._mediaRecorder.state==="recording"&&this._mediaRecorder.stop(),this._resetRecordingState()}_resetRecordingState(){this._recording=!1,this._recordingTimer!==null&&(clearInterval(this._recordingTimer),this._recordingTimer=null)}_handleDragOver(e){e.preventDefault(),this._dragOver=!0}_handleDragLeave(){this._dragOver=!1}_handleDrop(e){e.preventDefault(),this._dragOver=!1;const t=e.dataTransfer?.files;if(t)for(let s=0;s<t.length;s++){const a=t[s];if(this._attachments.length>=J){m.show("Maximum 5 attachments per message","warning");break}if(a.size>Q){m.show(`File too large (max 10MB): ${a.name}`,"error");continue}let i="file",n;a.type.startsWith("image/")?(i="image",n=URL.createObjectURL(a)):a.type.startsWith("audio/")&&(i="audio");const r={id:crypto.randomUUID(),file:a,type:i,previewUrl:n};this._attachments=[...this._attachments,r]}}_removeAttachment(e){const t=this._attachments.find(s=>s.id===e);t?.previewUrl&&URL.revokeObjectURL(t.previewUrl),this._attachments=this._attachments.filter(s=>s.id!==e)}_getFilteredSlashCommands(){if(!this._slashFilter)return[...k];const e=this._slashFilter.toLowerCase();return k.filter(t=>t.command.toLowerCase().includes(e)||t.description.toLowerCase().includes(e))}async _executeSlashCommand(e){switch(this._showSlashMenu=!1,this._inputValue="",e){case"/new":await this._createNewSession();break;case"/reset":if(this._activeSession&&this.rpcClient)try{await this.rpcClient.call("session.reset",{session_key:this._activeSession}),m.show("Session reset","success"),await this._loadSessionHistory()}catch{m.show("Failed to reset session","error")}break;case"/export":if(this._activeSession&&this.rpcClient)try{const t=await this.rpcClient.call("session.export",{session_key:this._activeSession});if(t?.data){const s=new Blob([t.data],{type:"application/jsonl"}),a=URL.createObjectURL(s),i=document.createElement("a");i.href=a,i.download=`session-${this._activeSession.slice(0,8)}.jsonl`,i.click(),URL.revokeObjectURL(a)}}catch{m.show("Failed to export session","error")}break;case"/compact":if(this._activeSession&&this.rpcClient)try{await this.rpcClient.call("session.compact",{session_key:this._activeSession}),m.show("Session compacted","success")}catch{m.show("Failed to compact session","error")}break;case"/switch":{const t=this.shadowRoot?.querySelector(".agent-select");t&&t.focus();break}case"/help":{const t=k.map(a=>`${a.command} - ${a.description}`).join(`
280
+ `),s={id:crypto.randomUUID(),role:"system",content:`Available commands:
281
+ ${t}`,timestamp:Date.now()};this._messages=[...this._messages,s];break}}}async _handleRetry(e){const{messageId:t}=e.detail,s=this._messages.findIndex(i=>i.id===t);if(s<0)return;let a;for(let i=s-1;i>=0;i--)if(this._messages[i].role==="user"){a=this._messages[i];break}if(this._messages=this._messages.filter(i=>i.id!==t),a&&this.apiClient){this._sending=!0,this._scrollToBottom();try{const i=await this.apiClient.chat(a.content,this._selectedAgent,this._activeSession??void 0),n=i.response?S(i.response):"";if(n){const r={id:crypto.randomUUID(),role:"assistant",content:n,timestamp:Date.now()};this._messages=[...this._messages,r]}}catch(i){const n={id:crypto.randomUUID(),role:"error",content:i instanceof Error?i.message:"Retry failed",timestamp:Date.now()};this._messages=[...this._messages,n]}finally{this._sending=!1,this._scrollToBottom(),this._focusInput()}}}_handleDelete(e){const{messageId:t}=e.detail;this._messages=this._messages.filter(s=>s.id!==t)}get _filteredSessions(){if(!this._searchQuery)return this._sessions;const e=this._searchQuery.toLowerCase();return this._sessions.filter(t=>t.key.toLowerCase().includes(e)||(t.label?.toLowerCase().includes(e)??!1))}_formatTokens(e){return e>=1e3?`${(e/1e3).toFixed(1)}K tokens`:`${e} tokens`}_renderSidebar(){return c`
282
+ <ic-session-sidebar
283
+ .sessions=${this._filteredSessions}
284
+ .selectedKey=${this._activeSession}
285
+ .filter=${this._searchQuery}
286
+ ?open=${this._sidebarOpen}
287
+ @session-selected=${e=>this._selectSession(e.detail.key)}
288
+ @filter-changed=${e=>{this._searchQuery=e.detail.value}}
289
+ @new-session=${()=>this._createNewSession()}
290
+ ></ic-session-sidebar>
291
+ `}_renderConversation(){return c`
292
+ <div
293
+ class="conversation"
294
+ @dragover=${this._handleDragOver}
295
+ @dragleave=${this._handleDragLeave}
296
+ @drop=${this._handleDrop}
297
+ >
298
+ ${this._renderConvHeader()}
299
+ ${this._renderMessageArea()}
300
+ ${this._activeSession||this._messages.length>0||!this._loading?this._renderInputBar():_}
301
+ ${this._dragOver?c`<div class="drag-overlay"><ic-icon name="attach" size="24px"></ic-icon> Drop files here</div>`:_}
302
+ </div>
303
+ `}_renderConvHeader(){return c`
304
+ <div class="conv-header">
305
+ <button
306
+ class="mobile-toggle"
307
+ @click=${()=>{this._sidebarOpen=!this._sidebarOpen}}
308
+ aria-label="Toggle sidebar"
309
+ >
310
+ <ic-icon name="menu" size="20px"></ic-icon>
311
+ </button>
312
+ <select
313
+ class="agent-select"
314
+ .value=${this._selectedAgent}
315
+ @change=${e=>{this._selectedAgent=e.target.value}}
316
+ >
317
+ ${this._agents.map(e=>c`<option value=${e.id}>${e.name} (${e.model})</option>`)}
318
+ </select>
319
+ ${this._activeSession?c`
320
+ <div class="session-info">
321
+ <span class="session-info-key">${(()=>{const e=A(this._activeSession);return e?R(e):this._activeSession.slice(0,8)})()}</span>
322
+ <span>${this._messages.length} messages</span>
323
+ </div>
324
+ `:_}
325
+ </div>
326
+ `}_renderMessageArea(){return c`
327
+ <ic-message-renderer
328
+ .messages=${this._messages}
329
+ ?streaming=${this._streaming}
330
+ ?sending=${this._sending}
331
+ ?loading=${this._loading}
332
+ ?hasSession=${!!this._activeSession}
333
+ .streamingContent=${this._streamingContent}
334
+ .streamingTokens=${this._streamingTokens}
335
+ .authToken=${this.authToken??""}
336
+ ?hasNewMessages=${this._hasNewMessages}
337
+ @retry=${this._handleRetry}
338
+ @delete=${this._handleDelete}
339
+ @scroll-to-bottom=${()=>this._scrollToBottom()}
340
+ @scroll=${this._handleScroll}
341
+ ></ic-message-renderer>
342
+ `}_renderInputBar(){const e=this._getFilteredSlashCommands(),t=this._inputValue.trim()===""&&this._attachments.length===0||this._sending;return c`
343
+ <div class="input-bar">
344
+ ${this._showSlashMenu&&e.length>0?c`
345
+ <div class="slash-menu" role="listbox">
346
+ ${e.map((s,a)=>c`
347
+ <div
348
+ class="slash-item ${a===this._slashSelectedIndex?"slash-item--active":""}"
349
+ role="option"
350
+ aria-selected=${a===this._slashSelectedIndex}
351
+ @click=${()=>this._executeSlashCommand(s.command)}
352
+ >
353
+ <ic-icon name=${s.icon} size="16px" color="var(--ic-text-muted)"></ic-icon>
354
+ <span class="slash-cmd">${s.command}</span>
355
+ <span class="slash-desc">${s.description}</span>
356
+ </div>
357
+ `)}
358
+ </div>
359
+ `:_}
360
+ ${this._budgetSegments.length>0?c`
361
+ <div class="budget-bar-area">
362
+ <ic-budget-segment-bar
363
+ .segments=${this._budgetSegments}
364
+ .total=${this._budgetTotal}
365
+ ></ic-budget-segment-bar>
366
+ </div>
367
+ `:_}
368
+ ${this._attachments.length>0?c`
369
+ <div class="attachment-strip">
370
+ ${this._attachments.map(s=>this._renderAttachmentPreview(s))}
371
+ </div>
372
+ `:_}
373
+ <div class="input-row">
374
+ ${this._renderVoiceButton()}
375
+ <textarea
376
+ class="input-textarea"
377
+ placeholder="Type a message... (Enter to send, Shift+Enter for newline)"
378
+ maxlength="10000"
379
+ .value=${this._inputValue}
380
+ ?disabled=${this._sending}
381
+ @input=${this._handleInput}
382
+ @keydown=${this._handleKeydown}
383
+ ></textarea>
384
+ <button
385
+ class="send-btn"
386
+ ?disabled=${t}
387
+ @click=${this._sendMessage}
388
+ aria-label="Send message"
389
+ >
390
+ <ic-icon name="send" size="18px"></ic-icon>
391
+ </button>
392
+ </div>
393
+ </div>
394
+ `}_renderVoiceButton(){if(this._transcribing)return c`
395
+ <button class="voice-btn" disabled aria-label="Transcribing">
396
+ <ic-loading size="sm"></ic-loading>
397
+ </button>
398
+ `;if(this._recording){const e=Math.floor(this._recordingDuration/60),t=this._recordingDuration%60,s=`${e}:${t.toString().padStart(2,"0")}`;return c`
399
+ <div class="recording-indicator">
400
+ <span class="recording-dot"></span>
401
+ <span class="recording-time">${s}</span>
402
+ <button
403
+ class="voice-btn voice-btn--recording"
404
+ @click=${this._stopRecording}
405
+ aria-label="Stop recording"
406
+ >
407
+ <ic-icon name="stop" size="18px"></ic-icon>
408
+ </button>
409
+ </div>
410
+ `}return c`
411
+ <button
412
+ class="voice-btn"
413
+ @click=${this._startRecording}
414
+ aria-label="Start voice recording"
415
+ >
416
+ <ic-icon name="microphone" size="18px"></ic-icon>
417
+ </button>
418
+ `}_renderAttachmentPreview(e){return c`
419
+ <div class="attachment-preview">
420
+ ${e.type==="image"&&e.previewUrl?c`<img src=${e.previewUrl} alt=${e.file.name}>`:e.type==="audio"?c`<ic-icon name="audio-wave" size="16px"></ic-icon>`:c`<ic-icon name="attach" size="16px"></ic-icon>`}
421
+ <span>${e.file.name}</span>
422
+ <button
423
+ class="attachment-remove"
424
+ @click=${()=>this._removeAttachment(e.id)}
425
+ aria-label="Remove attachment"
426
+ >\u2715</button>
427
+ </div>
428
+ `}render(){return c`
429
+ ${this._renderSidebar()}
430
+ ${this._renderConversation()}
431
+ `}};o.styles=[$,M,C`
432
+ :host {
433
+ display: flex;
434
+ height: calc(100vh - 6.5rem);
435
+ max-height: calc(100vh - 6.5rem);
436
+ overflow: hidden;
437
+ }
438
+
439
+ /* --- Sidebar --- */
440
+ .sidebar {
441
+ width: 280px;
442
+ min-width: 280px;
443
+ background: var(--ic-surface);
444
+ border-right: 1px solid var(--ic-border);
445
+ display: flex;
446
+ flex-direction: column;
447
+ height: 100%;
448
+ overflow: hidden;
449
+ }
450
+
451
+ .sidebar-header {
452
+ display: flex;
453
+ align-items: center;
454
+ justify-content: space-between;
455
+ padding: var(--ic-space-md);
456
+ border-bottom: 1px solid var(--ic-border);
457
+ flex-shrink: 0;
458
+ }
459
+
460
+ .sidebar-title {
461
+ font-size: var(--ic-text-base);
462
+ font-weight: 600;
463
+ }
464
+
465
+ .new-btn {
466
+ display: inline-flex;
467
+ align-items: center;
468
+ gap: 4px;
469
+ background: var(--ic-accent);
470
+ color: white;
471
+ border: none;
472
+ border-radius: var(--ic-radius-md);
473
+ padding: var(--ic-space-xs) var(--ic-space-sm);
474
+ font-size: var(--ic-text-xs);
475
+ font-family: inherit;
476
+ cursor: pointer;
477
+ font-weight: 500;
478
+ transition: background var(--ic-transition);
479
+ }
480
+
481
+ .new-btn:hover {
482
+ background: var(--ic-accent-hover);
483
+ }
484
+
485
+ .sidebar-search {
486
+ padding: var(--ic-space-sm) var(--ic-space-md);
487
+ flex-shrink: 0;
488
+ }
489
+
490
+ .session-list {
491
+ flex: 1;
492
+ overflow-y: auto;
493
+ }
494
+
495
+ .session-item {
496
+ display: flex;
497
+ flex-direction: column;
498
+ gap: 4px;
499
+ padding: var(--ic-space-sm) var(--ic-space-md);
500
+ cursor: pointer;
501
+ border-left: 3px solid transparent;
502
+ transition: background var(--ic-transition);
503
+ }
504
+
505
+ .session-item:hover {
506
+ background: var(--ic-surface-2);
507
+ }
508
+
509
+ .session-item--active {
510
+ background: var(--ic-surface-2);
511
+ border-left-color: var(--ic-accent);
512
+ }
513
+
514
+ .session-key {
515
+ font-family: var(--ic-font-mono);
516
+ font-size: var(--ic-text-xs);
517
+ color: var(--ic-text);
518
+ overflow: hidden;
519
+ text-overflow: ellipsis;
520
+ white-space: nowrap;
521
+ }
522
+
523
+ .session-meta {
524
+ display: flex;
525
+ align-items: center;
526
+ gap: var(--ic-space-sm);
527
+ }
528
+
529
+ .msg-count {
530
+ font-size: var(--ic-text-xs);
531
+ color: var(--ic-text-dim);
532
+ background: var(--ic-surface-2);
533
+ padding: 1px 6px;
534
+ border-radius: 9999px;
535
+ }
536
+
537
+ /* --- Conversation Area --- */
538
+ .conversation {
539
+ flex: 1;
540
+ display: flex;
541
+ flex-direction: column;
542
+ min-width: 0;
543
+ height: 100%;
544
+ overflow: hidden;
545
+ }
546
+
547
+ .conv-header {
548
+ display: flex;
549
+ align-items: center;
550
+ gap: var(--ic-space-md);
551
+ padding: var(--ic-space-md);
552
+ border-bottom: 1px solid var(--ic-border);
553
+ flex-shrink: 0;
554
+ }
555
+
556
+ .agent-select {
557
+ background: var(--ic-surface-2);
558
+ border: 1px solid var(--ic-border);
559
+ border-radius: var(--ic-radius-md);
560
+ color: var(--ic-text);
561
+ font-size: var(--ic-text-sm);
562
+ padding: var(--ic-space-xs) var(--ic-space-sm);
563
+ font-family: inherit;
564
+ }
565
+
566
+ .session-info {
567
+ display: flex;
568
+ align-items: center;
569
+ gap: var(--ic-space-sm);
570
+ margin-left: auto;
571
+ font-size: var(--ic-text-xs);
572
+ color: var(--ic-text-dim);
573
+ }
574
+
575
+ .session-info-key {
576
+ font-family: var(--ic-font-mono);
577
+ }
578
+
579
+ .message-area {
580
+ flex: 1;
581
+ overflow-y: auto;
582
+ padding: var(--ic-space-lg) var(--ic-space-xl);
583
+ display: flex;
584
+ flex-direction: column;
585
+ gap: var(--ic-space-sm);
586
+ position: relative;
587
+ max-width: 900px;
588
+ margin: 0 auto;
589
+ width: 100%;
590
+ }
591
+
592
+ .new-messages-btn {
593
+ position: sticky;
594
+ bottom: var(--ic-space-sm);
595
+ align-self: center;
596
+ background: var(--ic-accent);
597
+ color: white;
598
+ border: none;
599
+ border-radius: 9999px;
600
+ padding: var(--ic-space-xs) var(--ic-space-md);
601
+ font-size: var(--ic-text-xs);
602
+ font-family: inherit;
603
+ cursor: pointer;
604
+ box-shadow: var(--ic-shadow-md);
605
+ z-index: 1;
606
+ }
607
+
608
+ .new-messages-btn:hover {
609
+ background: var(--ic-accent-hover);
610
+ }
611
+
612
+ /* --- Input Bar --- */
613
+ .input-bar {
614
+ display: flex;
615
+ flex-direction: column;
616
+ padding: var(--ic-space-md);
617
+ border-top: 1px solid var(--ic-border);
618
+ gap: var(--ic-space-sm);
619
+ flex-shrink: 0;
620
+ position: relative;
621
+ }
622
+
623
+ .attachment-strip {
624
+ display: flex;
625
+ gap: var(--ic-space-sm);
626
+ flex-wrap: wrap;
627
+ }
628
+
629
+ .attachment-preview {
630
+ display: flex;
631
+ align-items: center;
632
+ gap: 4px;
633
+ padding: 4px 8px;
634
+ background: var(--ic-surface-2);
635
+ border-radius: var(--ic-radius-sm);
636
+ font-size: var(--ic-text-xs);
637
+ color: var(--ic-text);
638
+ }
639
+
640
+ .attachment-preview img {
641
+ width: 48px;
642
+ height: 48px;
643
+ object-fit: cover;
644
+ border-radius: var(--ic-radius-sm);
645
+ }
646
+
647
+ .attachment-remove {
648
+ background: none;
649
+ border: none;
650
+ color: var(--ic-text-dim);
651
+ cursor: pointer;
652
+ padding: 2px;
653
+ font-size: var(--ic-text-xs);
654
+ line-height: 1;
655
+ border-radius: var(--ic-radius-sm);
656
+ }
657
+
658
+ .attachment-remove:hover {
659
+ color: var(--ic-error);
660
+ }
661
+
662
+ .input-row {
663
+ display: flex;
664
+ align-items: flex-end;
665
+ gap: var(--ic-space-sm);
666
+ }
667
+
668
+ .input-textarea {
669
+ flex: 1;
670
+ min-height: 2.5rem;
671
+ max-height: 8rem;
672
+ background: var(--ic-surface-2);
673
+ border: 1px solid var(--ic-border);
674
+ border-radius: var(--ic-radius-md);
675
+ color: var(--ic-text);
676
+ font-size: var(--ic-text-sm);
677
+ padding: var(--ic-space-sm) var(--ic-space-md);
678
+ resize: none;
679
+ font-family: inherit;
680
+ line-height: 1.5;
681
+ outline: none;
682
+ transition: border-color var(--ic-transition);
683
+ }
684
+
685
+ .input-textarea:focus {
686
+ border-color: var(--ic-accent);
687
+ }
688
+
689
+ .input-textarea:disabled {
690
+ opacity: 0.5;
691
+ cursor: not-allowed;
692
+ }
693
+
694
+ .voice-btn {
695
+ display: inline-flex;
696
+ align-items: center;
697
+ justify-content: center;
698
+ background: none;
699
+ border: none;
700
+ color: var(--ic-text-muted);
701
+ cursor: pointer;
702
+ padding: var(--ic-space-sm);
703
+ border-radius: 50%;
704
+ transition: color var(--ic-transition), background var(--ic-transition);
705
+ }
706
+
707
+ .voice-btn:hover {
708
+ color: var(--ic-text);
709
+ }
710
+
711
+ .voice-btn--recording {
712
+ background: var(--ic-error);
713
+ color: white;
714
+ }
715
+
716
+ .voice-btn--recording:hover {
717
+ background: var(--ic-error);
718
+ color: white;
719
+ }
720
+
721
+ .voice-btn:disabled {
722
+ opacity: 0.5;
723
+ cursor: not-allowed;
724
+ }
725
+
726
+ .recording-indicator {
727
+ display: flex;
728
+ align-items: center;
729
+ gap: var(--ic-space-xs);
730
+ }
731
+
732
+ .recording-dot {
733
+ width: 8px;
734
+ height: 8px;
735
+ border-radius: 50%;
736
+ background: var(--ic-error);
737
+ animation: pulse 1.5s ease-in-out infinite;
738
+ }
739
+
740
+ @media (prefers-reduced-motion: reduce) {
741
+ .recording-dot {
742
+ animation: none;
743
+ opacity: 0.7;
744
+ }
745
+ }
746
+
747
+ @keyframes pulse {
748
+ 0%, 100% { opacity: 1; }
749
+ 50% { opacity: 0.3; }
750
+ }
751
+
752
+ .recording-time {
753
+ color: var(--ic-error);
754
+ font-family: var(--ic-font-mono);
755
+ font-size: var(--ic-text-xs);
756
+ }
757
+
758
+ .send-btn {
759
+ display: inline-flex;
760
+ align-items: center;
761
+ justify-content: center;
762
+ background: var(--ic-accent);
763
+ color: white;
764
+ border: none;
765
+ border-radius: var(--ic-radius-md);
766
+ padding: var(--ic-space-sm) var(--ic-space-md);
767
+ cursor: pointer;
768
+ transition: opacity var(--ic-transition);
769
+ }
770
+
771
+ .send-btn:disabled {
772
+ opacity: 0.4;
773
+ cursor: not-allowed;
774
+ }
775
+
776
+ .send-btn:hover:not(:disabled) {
777
+ opacity: 0.9;
778
+ }
779
+
780
+ /* --- Drag overlay --- */
781
+ .drag-overlay {
782
+ position: absolute;
783
+ inset: 0;
784
+ border: 2px dashed var(--ic-accent);
785
+ background: color-mix(in srgb, var(--ic-accent) 10%, transparent);
786
+ display: flex;
787
+ align-items: center;
788
+ justify-content: center;
789
+ gap: var(--ic-space-sm);
790
+ z-index: 5;
791
+ font-size: var(--ic-text-sm);
792
+ color: var(--ic-accent);
793
+ pointer-events: none;
794
+ }
795
+
796
+ /* --- Slash command menu --- */
797
+ .slash-menu {
798
+ position: absolute;
799
+ bottom: 100%;
800
+ left: var(--ic-space-md);
801
+ right: var(--ic-space-md);
802
+ background: var(--ic-surface);
803
+ border: 1px solid var(--ic-border);
804
+ border-radius: var(--ic-radius-md);
805
+ box-shadow: var(--ic-shadow-lg);
806
+ max-height: 12rem;
807
+ overflow-y: auto;
808
+ z-index: 100;
809
+ }
810
+
811
+ .slash-item {
812
+ display: flex;
813
+ align-items: center;
814
+ gap: var(--ic-space-sm);
815
+ padding: var(--ic-space-sm) var(--ic-space-md);
816
+ cursor: pointer;
817
+ transition: background var(--ic-transition);
818
+ }
819
+
820
+ .slash-item:hover,
821
+ .slash-item--active {
822
+ background: var(--ic-surface-2);
823
+ }
824
+
825
+ .slash-cmd {
826
+ font-family: var(--ic-font-mono);
827
+ color: var(--ic-text);
828
+ font-size: var(--ic-text-sm);
829
+ }
830
+
831
+ .slash-desc {
832
+ color: var(--ic-text-dim);
833
+ font-size: var(--ic-text-xs);
834
+ }
835
+
836
+ /* --- Budget bar --- */
837
+ .budget-bar-area {
838
+ padding: 0 var(--ic-space-md);
839
+ flex-shrink: 0;
840
+ border-top: 1px solid var(--ic-border);
841
+ }
842
+
843
+ /* --- Streaming indicator --- */
844
+ .streaming-indicator {
845
+ display: flex;
846
+ align-items: center;
847
+ gap: var(--ic-space-sm);
848
+ padding: var(--ic-space-sm) var(--ic-space-md);
849
+ }
850
+
851
+ .typing-dots {
852
+ display: flex;
853
+ gap: 4px;
854
+ }
855
+
856
+ .typing-dot {
857
+ width: 6px;
858
+ height: 6px;
859
+ background: var(--ic-text-muted);
860
+ border-radius: 50%;
861
+ animation: bounce 1.2s infinite;
862
+ }
863
+
864
+ .typing-dot:nth-child(2) {
865
+ animation-delay: 0.15s;
866
+ }
867
+
868
+ .typing-dot:nth-child(3) {
869
+ animation-delay: 0.3s;
870
+ }
871
+
872
+ @keyframes bounce {
873
+ 0%, 60%, 100% { transform: scale(1); }
874
+ 30% { transform: scale(1.4); }
875
+ }
876
+
877
+ @media (prefers-reduced-motion: reduce) {
878
+ .typing-dot {
879
+ animation: none;
880
+ }
881
+ .typing-dot:nth-child(1) { opacity: 0.4; }
882
+ .typing-dot:nth-child(2) { opacity: 0.7; }
883
+ .typing-dot:nth-child(3) { opacity: 1; }
884
+ }
885
+
886
+ .thinking-indicator {
887
+ display: flex;
888
+ align-items: center;
889
+ gap: var(--ic-space-sm);
890
+ padding: var(--ic-space-sm) var(--ic-space-md);
891
+ color: var(--ic-text-muted);
892
+ font-size: 0.85rem;
893
+ }
894
+
895
+ .thinking-label {
896
+ color: var(--ic-text-muted);
897
+ font-size: 0.85rem;
898
+ }
899
+
900
+ .token-counter {
901
+ font-family: var(--ic-font-mono);
902
+ font-size: var(--ic-text-xs);
903
+ color: var(--ic-text-dim);
904
+ }
905
+
906
+ /* Mobile toggle */
907
+ .mobile-toggle {
908
+ display: none;
909
+ background: none;
910
+ border: none;
911
+ color: var(--ic-text);
912
+ cursor: pointer;
913
+ padding: var(--ic-space-xs);
914
+ }
915
+
916
+ /* Loading center */
917
+ .loading-center {
918
+ display: flex;
919
+ justify-content: center;
920
+ padding: var(--ic-space-2xl);
921
+ }
922
+
923
+ /* Responsive: mobile */
924
+ @media (max-width: 767px) {
925
+ .sidebar {
926
+ display: none;
927
+ }
928
+
929
+ .sidebar--open {
930
+ display: flex;
931
+ position: absolute;
932
+ top: 0;
933
+ left: 0;
934
+ z-index: 10;
935
+ height: 100%;
936
+ box-shadow: var(--ic-shadow-lg);
937
+ }
938
+
939
+ .mobile-toggle {
940
+ display: inline-flex;
941
+ }
942
+ }
943
+ `];l([p({attribute:!1})],o.prototype,"apiClient",2);l([p({attribute:!1})],o.prototype,"rpcClient",2);l([p({attribute:!1})],o.prototype,"eventDispatcher",2);l([p()],o.prototype,"sessionKey",2);l([p()],o.prototype,"authToken",2);l([d()],o.prototype,"_sessions",2);l([d()],o.prototype,"_activeSession",2);l([d()],o.prototype,"_messages",2);l([d()],o.prototype,"_agents",2);l([d()],o.prototype,"_selectedAgent",2);l([d()],o.prototype,"_loading",2);l([d()],o.prototype,"_searchQuery",2);l([d()],o.prototype,"_sidebarOpen",2);l([d()],o.prototype,"_hasNewMessages",2);l([d()],o.prototype,"_inputValue",2);l([d()],o.prototype,"_sending",2);l([d()],o.prototype,"_attachments",2);l([d()],o.prototype,"_recording",2);l([d()],o.prototype,"_recordingDuration",2);l([d()],o.prototype,"_transcribing",2);l([d()],o.prototype,"_dragOver",2);l([d()],o.prototype,"_showSlashMenu",2);l([d()],o.prototype,"_slashFilter",2);l([d()],o.prototype,"_slashSelectedIndex",2);l([d()],o.prototype,"_streaming",2);l([d()],o.prototype,"_streamingTokens",2);l([d()],o.prototype,"_streamingContent",2);l([d()],o.prototype,"_budgetSegments",2);l([d()],o.prototype,"_budgetTotal",2);l([z(".message-area")],o.prototype,"_messageArea",2);l([z(".input-textarea")],o.prototype,"_textarea",2);o=l([D("ic-chat-console")],o);export{o as IcChatConsole};