comisai 1.0.24 → 1.0.25

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 (98) 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/package.json +1 -1
  4. package/node_modules/@comis/core/dist/bootstrap.js +5 -0
  5. package/node_modules/@comis/core/dist/config/env-layer.d.ts +31 -0
  6. package/node_modules/@comis/core/dist/config/env-layer.js +41 -0
  7. package/node_modules/@comis/core/dist/config/layered.d.ts +9 -0
  8. package/node_modules/@comis/core/dist/config/layered.js +11 -0
  9. package/node_modules/@comis/core/package.json +1 -1
  10. package/node_modules/@comis/daemon/dist/daemon.js +3 -0
  11. package/node_modules/@comis/daemon/package.json +1 -1
  12. package/node_modules/@comis/gateway/package.json +1 -1
  13. package/node_modules/@comis/infra/package.json +1 -1
  14. package/node_modules/@comis/memory/package.json +1 -1
  15. package/node_modules/@comis/scheduler/package.json +1 -1
  16. package/node_modules/@comis/shared/package.json +1 -1
  17. package/node_modules/@comis/skills/package.json +1 -1
  18. package/node_modules/@comis/web/dist/assets/{agent-detail-BG9MGWWj.js → agent-detail-ru-AhppM.js} +270 -270
  19. package/node_modules/@comis/web/dist/assets/agent-editor-hjwRuFVp.js +2173 -0
  20. package/node_modules/@comis/web/dist/assets/{agent-list-LHCJ4rw2.js → agent-list-6Uotjatr.js} +170 -170
  21. package/node_modules/@comis/web/dist/assets/{approvals-q9VH_IKr.js → approvals-C-K6hN2U.js} +13 -13
  22. package/node_modules/@comis/web/dist/assets/billing-view-CxysXH0p.js +375 -0
  23. package/node_modules/@comis/web/dist/assets/{channel-detail-CaInesJM.js → channel-detail-BBCKtmne.js} +265 -265
  24. package/node_modules/@comis/web/dist/assets/channel-list-FkfeOLBQ.js +323 -0
  25. package/node_modules/@comis/web/dist/assets/{chat-console-CNmzl0JW.js → chat-console-BumBaIgO.js} +243 -246
  26. package/node_modules/@comis/web/dist/assets/{config-editor-DX4ITw6y.js → config-editor-C9BSwHGy.js} +477 -477
  27. package/node_modules/@comis/web/dist/assets/{context-dag-browser-BwiaF5tf.js → context-dag-browser-BHm00mJD.js} +105 -105
  28. package/node_modules/@comis/web/dist/assets/{context-engine-BZ5Am6hA.js → context-engine-BENY3pWE.js} +136 -136
  29. package/node_modules/@comis/web/dist/assets/decorate-BvWYovGE.js +38 -0
  30. package/node_modules/@comis/web/dist/assets/{delivery-view-OfBZof-m.js → delivery-view-BCnkPsAp.js} +134 -134
  31. package/node_modules/@comis/web/dist/assets/{diagnostics-view-YFwCxgr2.js → diagnostics-view-C_jQFG2H.js} +82 -82
  32. package/node_modules/@comis/web/dist/assets/directive-BOYXJ-K-.js +1 -0
  33. package/node_modules/@comis/web/dist/assets/{extract-variables-BM5qyK-s.js → extract-variables-B7-Doo7l.js} +39 -39
  34. package/node_modules/@comis/web/dist/assets/{ic-array-editor-B7m6x7-S.js → ic-array-editor-BLoEyeLS.js} +29 -29
  35. package/node_modules/@comis/web/dist/assets/{ic-breadcrumb-CUMpp3BL.js → ic-breadcrumb-DqN6G3gc.js} +16 -16
  36. package/node_modules/@comis/web/dist/assets/{ic-budget-segment-bar-BtJ6x5mN.js → ic-budget-segment-bar-zLsMzjDO.js} +20 -20
  37. package/node_modules/@comis/web/dist/assets/ic-chat-message-FdQcZsSQ.js +352 -0
  38. package/node_modules/@comis/web/dist/assets/{ic-confirm-dialog-CCDbB04e.js → ic-confirm-dialog-DGlPbV1T.js} +26 -26
  39. package/node_modules/@comis/web/dist/assets/{ic-connection-dot-CnT1b8xr.js → ic-connection-dot-BgYiK2N4.js} +13 -13
  40. package/node_modules/@comis/web/dist/assets/ic-data-table-CKIvr-ag.js +277 -0
  41. package/node_modules/@comis/web/dist/assets/ic-delivery-row-B3YwjjuM.js +67 -0
  42. package/node_modules/@comis/web/dist/assets/{ic-detail-panel-BF83r-if.js → ic-detail-panel-DiCe4hLr.js} +27 -27
  43. package/node_modules/@comis/web/dist/assets/{ic-empty-state-60l2ePhd.js → ic-empty-state-CM3Wbj2f.js} +19 -19
  44. package/node_modules/@comis/web/dist/assets/ic-graph-canvas-ByRjij68.js +359 -0
  45. package/node_modules/@comis/web/dist/assets/ic-icon-BGNCCPpZ.js +33 -0
  46. package/node_modules/@comis/web/dist/assets/{ic-layer-waterfall-COvEYMg5.js → ic-layer-waterfall-WkaFyu-l.js} +18 -18
  47. package/node_modules/@comis/web/dist/assets/ic-relative-time-B3UAnTqg.js +12 -0
  48. package/node_modules/@comis/web/dist/assets/{ic-search-input-CSOxY9g7.js → ic-search-input-B02AGw1i.js} +22 -22
  49. package/node_modules/@comis/web/dist/assets/{ic-select-Ce-Raudx.js → ic-select-BqfZISjw.js} +29 -29
  50. package/node_modules/@comis/web/dist/assets/ic-tabs-yBjkWKJH.js +95 -0
  51. package/node_modules/@comis/web/dist/assets/ic-tag-CvMVQFRR.js +33 -0
  52. package/node_modules/@comis/web/dist/assets/{ic-time-range-picker-CypCT68y.js → ic-time-range-picker-DXbYeBmY.js} +31 -31
  53. package/node_modules/@comis/web/dist/assets/{ic-tool-call-7MaXSsCW.js → ic-tool-call-DMPHsLyx.js} +51 -51
  54. package/node_modules/@comis/web/dist/assets/index-CVEaS9aY.css +2 -0
  55. package/node_modules/@comis/web/dist/assets/index-FLPhHz8p.js +2792 -0
  56. package/node_modules/@comis/web/dist/assets/{mcp-management-BNZPnpDn.js → mcp-management-5jyScQis.js} +209 -209
  57. package/node_modules/@comis/web/dist/assets/{media-config-BBvTYxOX.js → media-config-J9oT9PPs.js} +154 -154
  58. package/node_modules/@comis/web/dist/assets/{media-test-BkK3RCRK.js → media-test-DGTCtM8-.js} +259 -259
  59. package/node_modules/@comis/web/dist/assets/{memory-inspector-1hDGCGat.js → memory-inspector-D5Re9ptG.js} +450 -450
  60. package/node_modules/@comis/web/dist/assets/{message-center-CXefwsUu.js → message-center-cRLK6ZmG.js} +290 -290
  61. package/node_modules/@comis/web/dist/assets/{models-C1qcU_j3.js → models-D5vu07MR.js} +371 -371
  62. package/node_modules/@comis/web/dist/assets/observability-types-D0tkwElU.js +1 -0
  63. package/node_modules/@comis/web/dist/assets/{observe-view-C0VBhX4C.js → observe-view-CalNNEmd.js} +399 -399
  64. package/node_modules/@comis/web/dist/assets/pipeline-builder-DUYDGwZf.js +1495 -0
  65. package/node_modules/@comis/web/dist/assets/{pipeline-history-DkfOQ6SW.js → pipeline-history-BAO8brOe.js} +124 -124
  66. package/node_modules/@comis/web/dist/assets/{pipeline-history-detail-hyHgD0ai.js → pipeline-history-detail-DectIoQt.js} +65 -65
  67. package/node_modules/@comis/web/dist/assets/{pipeline-list-BPW8hV-q.js → pipeline-list-BHlaBKww.js} +227 -227
  68. package/node_modules/@comis/web/dist/assets/{pipeline-monitor-Bip16T7e.js → pipeline-monitor-BhtpNEHf.js} +298 -298
  69. package/node_modules/@comis/web/dist/assets/{scheduler-BGgwKd06.js → scheduler-VafN_8xi.js} +486 -486
  70. package/node_modules/@comis/web/dist/assets/{security-D15st4xx.js → security-QQXMRTlo.js} +389 -389
  71. package/node_modules/@comis/web/dist/assets/{session-detail-SGEYNJ0M.js → session-detail-BpZ_8Yih.js} +294 -294
  72. package/node_modules/@comis/web/dist/assets/session-key-parser-Dkqcj2Ss.js +1 -0
  73. package/node_modules/@comis/web/dist/assets/session-list-DfCm8Cec.js +231 -0
  74. package/node_modules/@comis/web/dist/assets/{setup-wizard-nT0tz9QP.js → setup-wizard-C-z477CG.js} +486 -494
  75. package/node_modules/@comis/web/dist/assets/{skills-D8yVfSUy.js → skills-BCOGPf6s.js} +329 -329
  76. package/node_modules/@comis/web/dist/assets/{subagents-HHXMeHYo.js → subagents-l-auUraL.js} +74 -74
  77. package/node_modules/@comis/web/dist/assets/{workspace-manager-BQlr10iH.js → workspace-manager-DlvBixiq.js} +236 -236
  78. package/node_modules/@comis/web/dist/index.html +3 -2
  79. package/node_modules/@comis/web/package.json +1 -1
  80. package/package.json +15 -15
  81. package/node_modules/@comis/web/dist/assets/agent-editor-C26Q_xCs.js +0 -2173
  82. package/node_modules/@comis/web/dist/assets/billing-view-CtYvBqTE.js +0 -375
  83. package/node_modules/@comis/web/dist/assets/channel-list-B8dj3O9a.js +0 -323
  84. package/node_modules/@comis/web/dist/assets/directive-DoeGSK_T.js +0 -1
  85. package/node_modules/@comis/web/dist/assets/ic-chat-message-CFyDJd0z.js +0 -352
  86. package/node_modules/@comis/web/dist/assets/ic-data-table-CKUNTxHw.js +0 -277
  87. package/node_modules/@comis/web/dist/assets/ic-delivery-row-GP5Fkygs.js +0 -67
  88. package/node_modules/@comis/web/dist/assets/ic-graph-canvas-C8FuSMe1.js +0 -359
  89. package/node_modules/@comis/web/dist/assets/ic-icon-xeGTVhVG.js +0 -33
  90. package/node_modules/@comis/web/dist/assets/ic-relative-time-3FqpjeAI.js +0 -12
  91. package/node_modules/@comis/web/dist/assets/ic-tabs-B7QtM_v8.js +0 -95
  92. package/node_modules/@comis/web/dist/assets/ic-tag-CPPUnDLF.js +0 -33
  93. package/node_modules/@comis/web/dist/assets/index-CEcM1R_C.js +0 -2830
  94. package/node_modules/@comis/web/dist/assets/index-CIJFuItj.css +0 -1
  95. package/node_modules/@comis/web/dist/assets/observability-types-D7jUtSde.js +0 -1
  96. package/node_modules/@comis/web/dist/assets/pipeline-builder-DcUUIrm0.js +0 -1496
  97. package/node_modules/@comis/web/dist/assets/session-key-parser-DPORMVyU.js +0 -1
  98. package/node_modules/@comis/web/dist/assets/session-list-6ybUTxbY.js +0 -231
@@ -1,39 +1,4 @@
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`
1
+ import{a as e,c as t,f as n,h as r,l as i,n as a,o,r as s,s as c,t as l,u}from"./decorate-BvWYovGE.js";import{a as d}from"./index-FLPhHz8p.js";import"./ic-tag-CvMVQFRR.js";import"./ic-relative-time-B3UAnTqg.js";import"./ic-search-input-B02AGw1i.js";import"./ic-icon-BGNCCPpZ.js";import"./ic-empty-state-CM3Wbj2f.js";import{n as f,r as p}from"./session-key-parser-Dkqcj2Ss.js";import{n as m,r as h}from"./ic-tool-call-DMPHsLyx.js";import"./ic-chat-message-FdQcZsSQ.js";import"./ic-budget-segment-bar-zLsMzjDO.js";var g=class extends i{constructor(...e){super(...e),this.sessions=[],this.selectedKey=``,this.filter=``,this.open=!1}static{this.styles=[s,a,r`
37
2
  :host {
38
3
  display: block;
39
4
  }
@@ -131,68 +96,42 @@ 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}fro
131
96
  font-size: var(--ic-text-xs);
132
97
  color: var(--ic-text-dim);
133
98
  }
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>
99
+ `]}_renderSessionItem(e){let t=e.key===this.selectedKey?`session-item session-item--active`:`session-item`,r=p(e.key),i=r?f(r):e.key.length>8?e.key.slice(0,8):e.key,a=r?.channelId??e.channelType;return n`
100
+ <div
101
+ class=${t}
102
+ @click=${()=>this.dispatchEvent(new CustomEvent(`session-selected`,{detail:{key:e.key},bubbles:!0,composed:!0}))}
103
+ role="button"
104
+ tabindex="0"
105
+ @keydown=${t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),this.dispatchEvent(new CustomEvent(`session-selected`,{detail:{key:e.key},bubbles:!0,composed:!0})))}}
106
+ >
107
+ <span class="session-key" title=${e.key}>${i}</span>
108
+ <div class="session-meta">
109
+ <ic-tag variant="accent" size="sm">${a}</ic-tag>
110
+ <span class="msg-count">${e.messageCount}</span>
111
+ <ic-relative-time .timestamp=${e.lastActivity}></ic-relative-time>
168
112
  </div>
169
- <span class="token-counter">${this._formatTokens(this.streamingTokens)}</span>
170
113
  </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>
114
+ `}render(){return n`
115
+ <aside class="sidebar">
116
+ <div class="sidebar-header">
117
+ <span class="sidebar-title">Sessions</span>
118
+ <button class="new-btn" @click=${()=>this.dispatchEvent(new CustomEvent(`new-session`,{bubbles:!0,composed:!0}))}>
119
+ <ic-icon name="plus" size="14px"></ic-icon>
120
+ New
121
+ </button>
174
122
  </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>
123
+ <div class="sidebar-search">
124
+ <ic-search-input
125
+ placeholder="Filter sessions..."
126
+ debounce="200"
127
+ @search=${e=>this.dispatchEvent(new CustomEvent(`filter-changed`,{detail:{value:e.detail},bubbles:!0,composed:!0}))}
128
+ ></ic-search-input>
194
129
  </div>
195
- `}};g.styles=[$,C`
130
+ <div class="session-list">
131
+ ${this.sessions.map(e=>this._renderSessionItem(e))}
132
+ </div>
133
+ </aside>
134
+ `}};l([c({type:Array})],g.prototype,`sessions`,void 0),l([c({type:String})],g.prototype,`selectedKey`,void 0),l([c({type:String})],g.prototype,`filter`,void 0),l([c({type:Boolean})],g.prototype,`open`,void 0),g=l([t(`ic-session-sidebar`)],g);var _=class extends i{constructor(...e){super(...e),this.messages=[],this.streaming=!1,this.sending=!1,this.loading=!1,this.hasSession=!1,this.streamingContent=``,this.streamingTokens=0,this.authToken=``,this.hasNewMessages=!1}static{this.styles=[s,r`
196
135
  :host {
197
136
  display: block;
198
137
  flex: 1;
@@ -274,161 +213,68 @@ 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}fro
274
213
  font-family: inherit;
275
214
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
276
215
  }
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>
216
+ `]}_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 n`
217
+ <ic-tool-call .toolName=${`tool`} .output=${t} .status=${`success`}></ic-tool-call>
218
+ `}return n`
219
+ <ic-chat-message
220
+ .role=${e.role}
221
+ .content=${e.content}
222
+ .timestamp=${e.timestamp}
223
+ .messageId=${e.id}
224
+ .mediaToken=${this.authToken}
225
+ @retry=${e=>this.dispatchEvent(new CustomEvent(`retry`,{detail:e.detail,bubbles:!0,composed:!0}))}
226
+ @delete=${e=>this.dispatchEvent(new CustomEvent(`delete`,{detail:e.detail,bubbles:!0,composed:!0}))}
227
+ ></ic-chat-message>
228
+ ${e.toolCalls?.map(e=>n`
229
+ <ic-tool-call
230
+ .toolName=${e.name}
231
+ .input=${typeof e.input==`string`?e.input:JSON.stringify(e.input,null,2)}
232
+ .output=${typeof e.output==`string`?e.output:JSON.stringify(e.output,null,2)}
233
+ .status=${e.status===`running`?`running`:e.status===`error`?`error`:`success`}
234
+ ></ic-tool-call>
235
+ `)}
236
+ `}_renderStreamingIndicator(){return this.streamingContent?n`
237
+ <ic-chat-message
238
+ .role=${`assistant`} .content=${this.streamingContent}
239
+ .timestamp=${Date.now()} .showActions=${!1}
240
+ ></ic-chat-message>
241
+ <div class="streaming-indicator">
242
+ <span class="token-counter">${this._formatTokens(this.streamingTokens)}</span>
243
+ </div>
244
+ `:n`
245
+ <div class="streaming-indicator">
246
+ <div class="typing-dots">
247
+ <span class="typing-dot"></span>
248
+ <span class="typing-dot"></span>
249
+ <span class="typing-dot"></span>
392
250
  </div>
251
+ <span class="token-counter">${this._formatTokens(this.streamingTokens)}</span>
393
252
  </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>
253
+ `}render(){return this.loading?n`<ic-skeleton-view variant="detail"></ic-skeleton-view>`:this.hasSession?this.messages.length===0&&!this.streaming&&!this.sending?n`
254
+ <div class="message-area">
255
+ <ic-empty-state icon="chat" message="No messages yet" description="Start a conversation."></ic-empty-state>
409
256
  </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>
257
+ `:n`
258
+ <div class="message-area">
259
+ ${this.messages.map(e=>this._renderMessage(e))}
260
+ ${this.sending&&!this.streaming?n`<div class="thinking-indicator">
261
+ <div class="typing-dots">
262
+ <span class="typing-dot"></span><span class="typing-dot"></span><span class="typing-dot"></span>
263
+ </div>
264
+ <span class="thinking-label">Thinking...</span>
265
+ </div>`:u}
266
+ ${this.streaming?this._renderStreamingIndicator():u}
267
+ ${this.hasNewMessages?n`<button class="new-messages-btn"
268
+ @click=${()=>this.dispatchEvent(new CustomEvent(`scroll-to-bottom`,{bubbles:!0,composed:!0}))}
269
+ >New messages</button>`:u}
427
270
  </div>
428
- `}render(){return c`
429
- ${this._renderSidebar()}
430
- ${this._renderConversation()}
431
- `}};o.styles=[$,M,C`
271
+ `:n`
272
+ <div class="message-area">
273
+ <ic-empty-state icon="chat" message="Select a session"
274
+ description="Choose a session from the sidebar or create a new one."
275
+ ></ic-empty-state>
276
+ </div>
277
+ `}};l([c({type:Array})],_.prototype,`messages`,void 0),l([c({type:Boolean})],_.prototype,`streaming`,void 0),l([c({type:Boolean})],_.prototype,`sending`,void 0),l([c({type:Boolean})],_.prototype,`loading`,void 0),l([c({type:Boolean})],_.prototype,`hasSession`,void 0),l([c({type:String})],_.prototype,`streamingContent`,void 0),l([c({type:Number})],_.prototype,`streamingTokens`,void 0),l([c({type:String})],_.prototype,`authToken`,void 0),l([c({type:Boolean})],_.prototype,`hasNewMessages`,void 0),_=l([t(`ic-message-renderer`)],_);var v=[{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`}],y=5,b=10*1024*1024,x=120,S=class extends i{constructor(...e){super(...e),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}static{this.styles=[s,a,r`
432
278
  :host {
433
279
  display: flex;
434
280
  height: calc(100vh - 6.5rem);
@@ -940,4 +786,155 @@ ${t}`,timestamp:Date.now()};this._messages=[...this._messages,s];break}}}async _
940
786
  display: inline-flex;
941
787
  }
942
788
  }
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};
789
+ `]}connectedCallback(){super.connectedCallback(),this._setupEventListeners()}disconnectedCallback(){super.disconnectedCallback();for(let 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(let 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(e=>{e===`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(){let e=e=>{let t=e.detail;t.sessionKey===this._activeSession&&this._appendMessage(t)};document.addEventListener(`message:received`,e),this._eventUnsubs.push(()=>document.removeEventListener(`message:received`,e));let t=e=>{let t=e.detail;t.sessionKey===this._activeSession&&this._appendMessage(t)};document.addEventListener(`message:sent`,t),this._eventUnsubs.push(()=>document.removeEventListener(`message:sent`,t));let n=e=>{let t=e.detail,n={key:String(t.sessionKey??``),agentId:String(t.agentId??`unknown`),channelType:String(t.channelType??`web`),messageCount:0,lastActivity:Date.now()};this._sessions=[n,...this._sessions]};document.addEventListener(`session:created`,n),this._eventUnsubs.push(()=>document.removeEventListener(`session:created`,n));let r=e=>{let t=e.detail;if(t.sessionKey===this._activeSession&&(this._streaming||(this._streaming=!0,this._streamingTokens=0,this._streamingContent=``,this._streamBuffer=``),typeof t.content==`string`&&(this._streamBuffer+=t.content,this._rafPending||(this._rafPending=!0,requestAnimationFrame(()=>{this._streamingContent=this._streamBuffer,this._rafPending=!1}))),typeof t.tokens==`number`&&(this._streamingTokens=t.tokens),t.done===!0)){if(this._streamingContent=this._streamBuffer,this._streamBuffer.trim()){let e={id:crypto.randomUUID(),role:`assistant`,content:this._streamBuffer,timestamp:Date.now()};this._messages=[...this._messages,e]}this._streaming=!1,this._streamingTokens=0,this._streamingContent=``,this._streamBuffer=``,this._rafPending=!1,this._focusInput()}};if(document.addEventListener(`message:streaming`,r),this._eventUnsubs.push(()=>document.removeEventListener(`message:streaming`,r)),this.rpcClient){let e=this.rpcClient.onNotification((e,t)=>{if(e!==`notification.message`)return;let n=t,r=typeof n?.text==`string`?n.text:``;if(!r)return;console.debug(`[chat] notification.message received, length:`,r.length);let i={id:crypto.randomUUID(),role:`assistant`,content:r,timestamp:typeof n?.timestamp==`number`?n.timestamp:Date.now()};this._messages=[...this._messages,i],this._syncSessionMessageCount(),this._scrollToBottom()});this._eventUnsubs.push(e);let t=this.rpcClient.onNotification((e,t)=>{if(e!==`notification.attachment`)return;let n=t,r=typeof n?.url==`string`?n.url:``;if(!r)return;console.debug(`[chat] notification.attachment received:`,n?.type,n?.fileName);let i=n?.type??`file`,a=n?.fileName??`attachment`,o=typeof n?.caption==`string`?n.caption:``,s=n?.mimeType??``,c=JSON.stringify({url:r,type:i,mimeType:s,fileName:a}),l=o?`${o}\n\n<!-- attachment:${c} -->`:`<!-- attachment:${c} -->`,u={id:crypto.randomUUID(),role:`assistant`,content:l,timestamp:typeof n?.timestamp==`number`?n.timestamp:Date.now()};this._messages=[...this._messages,u],this._syncSessionMessageCount(),this._scrollToBottom()});this._eventUnsubs.push(t)}}_appendMessage(e){let 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{let e=(await this.rpcClient.call(`session.list`,{kind:`dm`}))?.sessions??[];if(this._sessions=e.map(e=>({key:e.sessionKey,agentId:e.agentId,channelType:e.channelId.startsWith(`web:`)?`web`:e.kind,messageCount:e.messageCount??0,lastActivity:e.updatedAt})),this._loading=!1,this.sessionKey){let e=this._sessions.find(e=>e.key===this.sessionKey);e&&(this._activeSession=e.key,this._loadSessionHistory())}}catch{this._sessions=[],this._loading=!1}}async _loadSessionHistory(){if(!(!this.rpcClient||!this._activeSession)){this._loading=!0;try{let e=(await this.rpcClient.call(`session.history`,{session_key:this._activeSession}))?.messages??[];this._messages=e.map(e=>({id:e.id??crypto.randomUUID(),role:e.role,content:e.role===`assistant`?m(e.content):e.role===`user`?h(e.content):e.content,timestamp:e.timestamp??0,toolCalls:e.toolCalls})).filter(e=>e.content!==``||e.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}let e=this._sessions.find(e=>e.key===this._activeSession)?.agentId??`default`;try{let t=(await this.rpcClient.call(`obs.context.pipeline`,{agentId:e,limit:1}))?.snapshots??[];if(t.length===0){this._budgetSegments=[],this._budgetTotal=0;return}let n=t[0],r=n.tokensLoaded??0,i=n.tokensEvicted??0,a=n.tokensMasked??0,o=n.budgetUtilization??0,s=o>0?Math.round(r/o):0,c=Math.max(0,s-r),l=[];r>0&&l.push({label:`Loaded`,tokens:r,color:`var(--ic-accent)`}),i>0&&l.push({label:`Evicted`,tokens:i,color:`var(--ic-warning)`}),a>0&&l.push({label:`Masked`,tokens:a,color:`var(--ic-text-dim)`}),c>0&&l.push({label:`Available`,tokens:c,color:`var(--ic-surface-2)`}),this._budgetSegments=l,this._budgetTotal=s}catch{this._budgetSegments=[],this._budgetTotal=0}}async _loadAgents(){if(this.apiClient)try{let e=await this.apiClient.getAgents();this._agents=e.length>0?e.map(e=>({id:e.id,name:e.name??e.id,model:e.model})):[{id:`default`,name:`Default`,model:`unknown`}]}catch{this._agents=[{id:`default`,name:`Default`,model:`unknown`}]}}_createNewSession(){let 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;let{scrollTop:e,scrollHeight:t,clientHeight:n}=this._messageArea,r=t-e-n<50;this._userScrolledUp=!r,r&&(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){let 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){let 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(){let 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){let 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(let e of this._attachments)e.previewUrl&&URL.revokeObjectURL(e.previewUrl);this._attachments=[];let t=await this.apiClient.chat(e,this._selectedAgent,this._activeSession??void 0),n=t.response?m(t.response):``;if(n){let e={id:crypto.randomUUID(),role:`assistant`,content:n,timestamp:Date.now()};this._messages=[...this._messages,e]}}catch(e){let t={id:crypto.randomUUID(),role:`error`,content:e instanceof Error?e.message:`Failed to send message`,timestamp:Date.now()};this._messages=[...this._messages,t]}finally{this._sending=!1,this._syncSessionMessageCount(),this._scrollToBottom(),this._focusInput()}}}_syncSessionMessageCount(){if(!this._activeSession)return;let e=this._messages.filter(e=>e.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){d.show(`Microphone access not available`,`error`);return}try{let 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>=x&&(d.show(`Maximum recording duration reached`,`warning`),this._stopRecording())},1e3),this._mediaRecorder.ondataavailable=e=>{e.data.size>0&&this._audioChunks.push(e.data)},this._mediaRecorder.onerror=()=>{d.show(`Recording error occurred`,`error`),this._resetRecordingState()},this._mediaRecorder.onstop=async()=>{let t=new Blob(this._audioChunks,{type:`audio/webm`});this._transcribing=!0;try{let e=await t.arrayBuffer(),n=new Uint8Array(e),r=``;for(let e=0;e<n.length;e++)r+=String.fromCharCode(n[e]);let i=btoa(r),a=await this.rpcClient.call(`audio.transcribe`,{audio:i,format:`webm`});a?.text&&(this._inputValue+=(this._inputValue?` `:``)+a.text)}catch{d.show(`Transcription failed`,`error`)}finally{this._transcribing=!1}e.getTracks().forEach(e=>e.stop())},this._mediaRecorder.start()}catch{d.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;let t=e.dataTransfer?.files;if(t)for(let e=0;e<t.length;e++){let n=t[e];if(this._attachments.length>=y){d.show(`Maximum 5 attachments per message`,`warning`);break}if(n.size>b){d.show(`File too large (max 10MB): ${n.name}`,`error`);continue}let r=`file`,i;n.type.startsWith(`image/`)?(r=`image`,i=URL.createObjectURL(n)):n.type.startsWith(`audio/`)&&(r=`audio`);let a={id:crypto.randomUUID(),file:n,type:r,previewUrl:i};this._attachments=[...this._attachments,a]}}_removeAttachment(e){let t=this._attachments.find(t=>t.id===e);t?.previewUrl&&URL.revokeObjectURL(t.previewUrl),this._attachments=this._attachments.filter(t=>t.id!==e)}_getFilteredSlashCommands(){if(!this._slashFilter)return[...v];let e=this._slashFilter.toLowerCase();return v.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}),d.show(`Session reset`,`success`),await this._loadSessionHistory()}catch{d.show(`Failed to reset session`,`error`)}break;case`/export`:if(this._activeSession&&this.rpcClient)try{let e=await this.rpcClient.call(`session.export`,{session_key:this._activeSession});if(e?.data){let t=new Blob([e.data],{type:`application/jsonl`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`session-${this._activeSession.slice(0,8)}.jsonl`,r.click(),URL.revokeObjectURL(n)}}catch{d.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}),d.show(`Session compacted`,`success`)}catch{d.show(`Failed to compact session`,`error`)}break;case`/switch`:{let e=this.shadowRoot?.querySelector(`.agent-select`);e&&e.focus();break}case`/help`:{let e=v.map(e=>`${e.command} - ${e.description}`).join(`
790
+ `),t={id:crypto.randomUUID(),role:`system`,content:`Available commands:\n${e}`,timestamp:Date.now()};this._messages=[...this._messages,t];break}}}async _handleRetry(e){let{messageId:t}=e.detail,n=this._messages.findIndex(e=>e.id===t);if(n<0)return;let r;for(let e=n-1;e>=0;e--)if(this._messages[e].role===`user`){r=this._messages[e];break}if(this._messages=this._messages.filter(e=>e.id!==t),r&&this.apiClient){this._sending=!0,this._scrollToBottom();try{let e=await this.apiClient.chat(r.content,this._selectedAgent,this._activeSession??void 0),t=e.response?m(e.response):``;if(t){let e={id:crypto.randomUUID(),role:`assistant`,content:t,timestamp:Date.now()};this._messages=[...this._messages,e]}}catch(e){let t={id:crypto.randomUUID(),role:`error`,content:e instanceof Error?e.message:`Retry failed`,timestamp:Date.now()};this._messages=[...this._messages,t]}finally{this._sending=!1,this._scrollToBottom(),this._focusInput()}}}_handleDelete(e){let{messageId:t}=e.detail;this._messages=this._messages.filter(e=>e.id!==t)}get _filteredSessions(){if(!this._searchQuery)return this._sessions;let 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 n`
791
+ <ic-session-sidebar
792
+ .sessions=${this._filteredSessions}
793
+ .selectedKey=${this._activeSession}
794
+ .filter=${this._searchQuery}
795
+ ?open=${this._sidebarOpen}
796
+ @session-selected=${e=>this._selectSession(e.detail.key)}
797
+ @filter-changed=${e=>{this._searchQuery=e.detail.value}}
798
+ @new-session=${()=>this._createNewSession()}
799
+ ></ic-session-sidebar>
800
+ `}_renderConversation(){return n`
801
+ <div
802
+ class="conversation"
803
+ @dragover=${this._handleDragOver}
804
+ @dragleave=${this._handleDragLeave}
805
+ @drop=${this._handleDrop}
806
+ >
807
+ ${this._renderConvHeader()}
808
+ ${this._renderMessageArea()}
809
+ ${this._activeSession||this._messages.length>0||!this._loading?this._renderInputBar():u}
810
+ ${this._dragOver?n`<div class="drag-overlay"><ic-icon name="attach" size="24px"></ic-icon> Drop files here</div>`:u}
811
+ </div>
812
+ `}_renderConvHeader(){return n`
813
+ <div class="conv-header">
814
+ <button
815
+ class="mobile-toggle"
816
+ @click=${()=>{this._sidebarOpen=!this._sidebarOpen}}
817
+ aria-label="Toggle sidebar"
818
+ >
819
+ <ic-icon name="menu" size="20px"></ic-icon>
820
+ </button>
821
+ <select
822
+ class="agent-select"
823
+ .value=${this._selectedAgent}
824
+ @change=${e=>{this._selectedAgent=e.target.value}}
825
+ >
826
+ ${this._agents.map(e=>n`<option value=${e.id}>${e.name} (${e.model})</option>`)}
827
+ </select>
828
+ ${this._activeSession?n`
829
+ <div class="session-info">
830
+ <span class="session-info-key">${(()=>{let e=p(this._activeSession);return e?f(e):this._activeSession.slice(0,8)})()}</span>
831
+ <span>${this._messages.length} messages</span>
832
+ </div>
833
+ `:u}
834
+ </div>
835
+ `}_renderMessageArea(){return n`
836
+ <ic-message-renderer
837
+ .messages=${this._messages}
838
+ ?streaming=${this._streaming}
839
+ ?sending=${this._sending}
840
+ ?loading=${this._loading}
841
+ ?hasSession=${!!this._activeSession}
842
+ .streamingContent=${this._streamingContent}
843
+ .streamingTokens=${this._streamingTokens}
844
+ .authToken=${this.authToken??``}
845
+ ?hasNewMessages=${this._hasNewMessages}
846
+ @retry=${this._handleRetry}
847
+ @delete=${this._handleDelete}
848
+ @scroll-to-bottom=${()=>this._scrollToBottom()}
849
+ @scroll=${this._handleScroll}
850
+ ></ic-message-renderer>
851
+ `}_renderInputBar(){let e=this._getFilteredSlashCommands(),t=this._inputValue.trim()===``&&this._attachments.length===0||this._sending;return n`
852
+ <div class="input-bar">
853
+ ${this._showSlashMenu&&e.length>0?n`
854
+ <div class="slash-menu" role="listbox">
855
+ ${e.map((e,t)=>n`
856
+ <div
857
+ class="slash-item ${t===this._slashSelectedIndex?`slash-item--active`:``}"
858
+ role="option"
859
+ aria-selected=${t===this._slashSelectedIndex}
860
+ @click=${()=>this._executeSlashCommand(e.command)}
861
+ >
862
+ <ic-icon name=${e.icon} size="16px" color="var(--ic-text-muted)"></ic-icon>
863
+ <span class="slash-cmd">${e.command}</span>
864
+ <span class="slash-desc">${e.description}</span>
865
+ </div>
866
+ `)}
867
+ </div>
868
+ `:u}
869
+ ${this._budgetSegments.length>0?n`
870
+ <div class="budget-bar-area">
871
+ <ic-budget-segment-bar
872
+ .segments=${this._budgetSegments}
873
+ .total=${this._budgetTotal}
874
+ ></ic-budget-segment-bar>
875
+ </div>
876
+ `:u}
877
+ ${this._attachments.length>0?n`
878
+ <div class="attachment-strip">
879
+ ${this._attachments.map(e=>this._renderAttachmentPreview(e))}
880
+ </div>
881
+ `:u}
882
+ <div class="input-row">
883
+ ${this._renderVoiceButton()}
884
+ <textarea
885
+ class="input-textarea"
886
+ placeholder="Type a message... (Enter to send, Shift+Enter for newline)"
887
+ maxlength="10000"
888
+ .value=${this._inputValue}
889
+ ?disabled=${this._sending}
890
+ @input=${this._handleInput}
891
+ @keydown=${this._handleKeydown}
892
+ ></textarea>
893
+ <button
894
+ class="send-btn"
895
+ ?disabled=${t}
896
+ @click=${this._sendMessage}
897
+ aria-label="Send message"
898
+ >
899
+ <ic-icon name="send" size="18px"></ic-icon>
900
+ </button>
901
+ </div>
902
+ </div>
903
+ `}_renderVoiceButton(){return this._transcribing?n`
904
+ <button class="voice-btn" disabled aria-label="Transcribing">
905
+ <ic-loading size="sm"></ic-loading>
906
+ </button>
907
+ `:this._recording?n`
908
+ <div class="recording-indicator">
909
+ <span class="recording-dot"></span>
910
+ <span class="recording-time">${`${Math.floor(this._recordingDuration/60)}:${(this._recordingDuration%60).toString().padStart(2,`0`)}`}</span>
911
+ <button
912
+ class="voice-btn voice-btn--recording"
913
+ @click=${this._stopRecording}
914
+ aria-label="Stop recording"
915
+ >
916
+ <ic-icon name="stop" size="18px"></ic-icon>
917
+ </button>
918
+ </div>
919
+ `:n`
920
+ <button
921
+ class="voice-btn"
922
+ @click=${this._startRecording}
923
+ aria-label="Start voice recording"
924
+ >
925
+ <ic-icon name="microphone" size="18px"></ic-icon>
926
+ </button>
927
+ `}_renderAttachmentPreview(e){return n`
928
+ <div class="attachment-preview">
929
+ ${e.type===`image`&&e.previewUrl?n`<img src=${e.previewUrl} alt=${e.file.name}>`:e.type===`audio`?n`<ic-icon name="audio-wave" size="16px"></ic-icon>`:n`<ic-icon name="attach" size="16px"></ic-icon>`}
930
+ <span>${e.file.name}</span>
931
+ <button
932
+ class="attachment-remove"
933
+ @click=${()=>this._removeAttachment(e.id)}
934
+ aria-label="Remove attachment"
935
+ >\u2715</button>
936
+ </div>
937
+ `}render(){return n`
938
+ ${this._renderSidebar()}
939
+ ${this._renderConversation()}
940
+ `}};l([c({attribute:!1})],S.prototype,`apiClient`,void 0),l([c({attribute:!1})],S.prototype,`rpcClient`,void 0),l([c({attribute:!1})],S.prototype,`eventDispatcher`,void 0),l([c()],S.prototype,`sessionKey`,void 0),l([c()],S.prototype,`authToken`,void 0),l([o()],S.prototype,`_sessions`,void 0),l([o()],S.prototype,`_activeSession`,void 0),l([o()],S.prototype,`_messages`,void 0),l([o()],S.prototype,`_agents`,void 0),l([o()],S.prototype,`_selectedAgent`,void 0),l([o()],S.prototype,`_loading`,void 0),l([o()],S.prototype,`_searchQuery`,void 0),l([o()],S.prototype,`_sidebarOpen`,void 0),l([o()],S.prototype,`_hasNewMessages`,void 0),l([o()],S.prototype,`_inputValue`,void 0),l([o()],S.prototype,`_sending`,void 0),l([o()],S.prototype,`_attachments`,void 0),l([o()],S.prototype,`_recording`,void 0),l([o()],S.prototype,`_recordingDuration`,void 0),l([o()],S.prototype,`_transcribing`,void 0),l([o()],S.prototype,`_dragOver`,void 0),l([o()],S.prototype,`_showSlashMenu`,void 0),l([o()],S.prototype,`_slashFilter`,void 0),l([o()],S.prototype,`_slashSelectedIndex`,void 0),l([o()],S.prototype,`_streaming`,void 0),l([o()],S.prototype,`_streamingTokens`,void 0),l([o()],S.prototype,`_streamingContent`,void 0),l([o()],S.prototype,`_budgetSegments`,void 0),l([o()],S.prototype,`_budgetTotal`,void 0),l([e(`.message-area`)],S.prototype,`_messageArea`,void 0),l([e(`.input-textarea`)],S.prototype,`_textarea`,void 0),S=l([t(`ic-chat-console`)],S);export{S as IcChatConsole};