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,57 +1,4 @@
1
- import{s as f,f as b,i as _,n as u,a as g,A as c,b as a,t as y,S as x,I as h,r as l}from"./index-CEcM1R_C.js";import"./ic-tabs-B7QtM_v8.js";import"./ic-empty-state-60l2ePhd.js";import"./ic-tag-CPPUnDLF.js";import"./ic-icon-xeGTVhVG.js";import"./ic-connection-dot-CnT1b8xr.js";import"./ic-search-input-CSOxY9g7.js";var P=Object.defineProperty,w=Object.getOwnPropertyDescriptor,m=(e,t,i,s)=>{for(var r=s>1?void 0:s?w(t,i):t,n=e.length-1,p;n>=0;n--)(p=e[n])&&(r=(s?p(t,i,r):p(r))||r);return s&&r&&P(t,i,r),r};let v=class extends g{constructor(){super(...arguments),this.name="",this.type="",this.baseUrl="",this.enabled=!1,this.testResult=null,this.testing=!1}_onTest(){this.dispatchEvent(new CustomEvent("test-connection"))}_onEdit(){this.dispatchEvent(new CustomEvent("edit-provider"))}_onToggle(e){const t=e.target.checked;this.dispatchEvent(new CustomEvent("toggle-provider",{detail:t}))}_renderTestResult(){if(!this.testResult)return c;const e=this.testResult;return a`
2
- <div class="test-result">
3
- <div class="test-result-line">
4
- <ic-icon
5
- name=${e.status==="ok"?"check":"x"}
6
- size="12px"
7
- color=${e.status==="ok"?"var(--ic-success)":"var(--ic-error)"}
8
- ></ic-icon>
9
- <span>${e.status==="ok"?"Connection OK":`Status: ${e.status}`}</span>
10
- </div>
11
- ${e.modelsAvailable!=null?a`<div class="test-result-line">Models available: ${e.modelsAvailable}</div>`:c}
12
- ${e.validatedModels!=null?a`<div class="test-result-line">Validated: ${e.validatedModels}</div>`:c}
13
- </div>
14
- `}render(){return a`
15
- <div class="card">
16
- <div class="header">
17
- <span class="name">${this.name}</span>
18
- <ic-tag variant="info">${this.type}</ic-tag>
19
- </div>
20
- <div class="url-row">${this.baseUrl||"Default"}</div>
21
- <div class="status-row">
22
- <ic-connection-dot
23
- status=${this.enabled?"connected":"disconnected"}
24
- size="6px"
25
- ></ic-connection-dot>
26
- <span>${this.enabled?"Enabled":"Disabled"}</span>
27
- <input
28
- type="checkbox"
29
- .checked=${this.enabled}
30
- @change=${this._onToggle}
31
- aria-label="Toggle ${this.name}"
32
- style="margin-left: auto; accent-color: var(--ic-accent); cursor: pointer;"
33
- />
34
- </div>
35
- ${this._renderTestResult()}
36
- <div class="actions">
37
- <button
38
- class="btn btn-test"
39
- @click=${this._onTest}
40
- ?disabled=${this.testing}
41
- aria-label="Test connection for ${this.name}"
42
- >
43
- ${this.testing?a`<span class="spinner-inline"></span>`:"Test"}
44
- </button>
45
- <button
46
- class="btn btn-edit"
47
- @click=${this._onEdit}
48
- aria-label="Edit ${this.name}"
49
- >
50
- Edit
51
- </button>
52
- </div>
53
- </div>
54
- `}};v.styles=[f,b,_`
1
+ import{c as e,f as t,h as n,l as r,n as i,o as a,r as o,s,t as c,u as l}from"./decorate-BvWYovGE.js";import{a as u,i as d}from"./index-FLPhHz8p.js";import"./ic-tag-CvMVQFRR.js";import"./ic-search-input-B02AGw1i.js";import"./ic-icon-BGNCCPpZ.js";import"./ic-empty-state-CM3Wbj2f.js";import"./ic-tabs-yBjkWKJH.js";import"./ic-connection-dot-BgYiK2N4.js";var f=class extends r{constructor(...e){super(...e),this.name=``,this.type=``,this.baseUrl=``,this.enabled=!1,this.testResult=null,this.testing=!1}static{this.styles=[o,i,n`
55
2
  :host {
56
3
  display: block;
57
4
  }
@@ -173,332 +120,60 @@ import{s as f,f as b,i as _,n as u,a as g,A as c,b as a,t as y,S as x,I as h,r a
173
120
  opacity: 0.7;
174
121
  }
175
122
  }
176
- `];m([u()],v.prototype,"name",2);m([u()],v.prototype,"type",2);m([u()],v.prototype,"baseUrl",2);m([u({type:Boolean})],v.prototype,"enabled",2);m([u({attribute:!1})],v.prototype,"testResult",2);m([u({type:Boolean})],v.prototype,"testing",2);v=m([y("ic-provider-card")],v);var A=Object.defineProperty,k=Object.getOwnPropertyDescriptor,d=(e,t,i,s)=>{for(var r=s>1?void 0:s?k(t,i):t,n=e.length-1,p;n>=0;n--)(p=e[n])&&(r=(s?p(t,i,r):p(r))||r);return s&&r&&A(t,i,r),r};const C=[{id:"providers",label:"Providers"},{id:"models",label:"Catalog"},{id:"aliases",label:"Aliases"},{id:"defaults",label:"Defaults"}];let o=class extends g{constructor(){super(...arguments),this.apiClient=null,this.rpcClient=null,this.eventDispatcher=null,this._sse=null,this._reloadDebounce=null,this._loadState="loading",this._error="",this._activeTab="providers",this._providers={},this._models=[],this._aliases=[],this._defaultProvider="",this._defaultModel="",this._providerTestResults=new Map,this._testingProviders=new Set,this._editingProvider=null,this._editForm={name:"",type:"",baseUrl:"",apiKeyName:""},this._editingAlias=null,this._aliasForm={alias:"",provider:"",modelId:""},this._modelsSearchQuery="",this._modelsProviderFilter="",this._agents=[],this._rpcStatusUnsub=null}connectedCallback(){super.connectedCallback(),this._initSse()}disconnectedCallback(){super.disconnectedCallback(),this._rpcStatusUnsub?.(),this._rpcStatusUnsub=null,this._reloadDebounce!==null&&(clearTimeout(this._reloadDebounce),this._reloadDebounce=null)}updated(e){e.has("eventDispatcher")&&this.eventDispatcher&&!this._sse&&this._initSse(),e.has("rpcClient")&&this.rpcClient&&(this._rpcStatusUnsub?.(),this._rpcStatusUnsub=null,this.rpcClient.status==="connected"?this._loadData():this._rpcStatusUnsub=this.rpcClient.onStatusChange(t=>{t==="connected"&&(this._rpcStatusUnsub?.(),this._rpcStatusUnsub=null,this._loadData())}))}_scheduleReload(e=300){this._reloadDebounce!==null&&clearTimeout(this._reloadDebounce),this._reloadDebounce=setTimeout(()=>{this._reloadDebounce=null,this._loadData()},e)}_initSse(){!this.eventDispatcher||this._sse||(this._sse=new x(this,this.eventDispatcher,{"model:catalog_loaded":()=>{this._scheduleReload()}}))}async _loadData(){if(this.rpcClient){this._loadState="loading",this._error="";try{const e=await this.rpcClient.call("config.read");this._providers=e.config.providers?.entries??{},this._aliases=e.config.models?.aliases??[],this._defaultProvider=e.config.models?.defaultProvider??"",this._defaultModel=e.config.models?.defaultModel??"",this._loadState="loaded",this.rpcClient.call("models.list").then(t=>{t.models&&t.models.length>0?this._models=t.models:t.providers&&t.providers.length>0&&(this._models=t.providers.flatMap(i=>(i.models??[]).map(s=>{const r=typeof s=="object"&&s!==null,n=r?s.modelId:s;return{provider:i.name,modelId:n,displayName:n,contextWindow:r?s.contextWindow:0,maxTokens:r?s.maxTokens:0,input:!0,reasoning:!1,validated:!1}})))}).catch(()=>{}),(async()=>{try{const i=((await this.rpcClient.call("agents.list")).agents??[]).slice(0,20),s=await Promise.allSettled(i.map(r=>this.rpcClient.call("agents.get",{agentId:r})));this._agents=s.filter(r=>r.status==="fulfilled"&&r.value.agentId!=null).map(r=>({id:r.value.agentId,provider:r.value.config.provider??"",model:r.value.config.model??""}))}catch{this._agents=[]}})()}catch(e){this._error=e instanceof Error?e.message:"Failed to load model configuration",this._loadState="error"}}}async _patchConfig(e,t){if(!this.rpcClient)return!1;try{const i=e.indexOf("."),s=i>0?e.slice(0,i):e,r=i>0?e.slice(i+1):void 0;return await this.rpcClient.call("config.patch",{section:s,key:r,value:t}),h.show("Configuration updated","success"),!0}catch(i){const s=i instanceof Error?i.message:"Failed to update configuration";return h.show(s,"error"),!1}}async _testProvider(e){if(!this.rpcClient)return;const t=new Set(this._testingProviders);t.add(e),this._testingProviders=t;try{const i=await this.rpcClient.call("models.test",{provider:e}),s=new Map(this._providerTestResults);s.set(e,i),this._providerTestResults=s,h.show(`Provider "${e}" test: ${i.status}`,i.status==="ok"?"success":"warning")}catch(i){const s=i instanceof Error?i.message:"Test failed",r=new Map(this._providerTestResults);r.set(e,{status:"error"}),this._providerTestResults=r,h.show(`Provider "${e}" test failed: ${s}`,"error")}finally{const i=new Set(this._testingProviders);i.delete(e),this._testingProviders=i}}async _toggleProvider(e,t){await this._patchConfig(`providers.entries.${e}.enabled`,t)&&(this._providers={...this._providers,[e]:{...this._providers[e],enabled:t}})}_startEditProvider(e){const t=this._providers[e];this._editingProvider=e,this._editForm={name:e,type:t?.type??"",baseUrl:t?.baseUrl??"",apiKeyName:t?.apiKeyName??""}}_startAddProvider(){this._editingProvider="",this._editForm={name:"",type:"",baseUrl:"",apiKeyName:""}}_cancelEditProvider(){this._editingProvider=null}async _saveProvider(){const{name:e,type:t,baseUrl:i,apiKeyName:s}=this._editForm;if(!e.trim()||!t.trim())return;const r={type:t.trim(),name:e.trim(),baseUrl:i.trim(),apiKeyName:s.trim(),enabled:this._providers[e]?.enabled??!0,timeoutMs:this._providers[e]?.timeoutMs??12e4,maxRetries:this._providers[e]?.maxRetries??2};await this._patchConfig(`providers.entries.${e.trim()}`,r)&&(this._providers={...this._providers,[e.trim()]:r},this._editingProvider=null)}async _deleteProvider(){if(!this._editingProvider)return;const e=this._editingProvider,t={...this._providers};delete t[e],await this._patchConfig("providers.entries",t)&&(this._providers=t,this._editingProvider=null)}_renderProviderEditor(){if(this._editingProvider===null)return c;const e=this._editingProvider==="";return a`
177
- <div class="editor-form">
178
- <div class="editor-title">${e?"Add Provider":`Edit: ${this._editingProvider}`}</div>
179
- <div class="form-field">
180
- <label class="form-label">Provider Name</label>
181
- <input
182
- class="form-input"
183
- type="text"
184
- .value=${this._editForm.name}
185
- ?disabled=${!e}
186
- @input=${t=>{this._editForm={...this._editForm,name:t.target.value}}}
187
- placeholder="e.g., anthropic"
188
- />
189
- </div>
190
- <div class="form-field">
191
- <label class="form-label">Type</label>
192
- <input
193
- class="form-input"
194
- type="text"
195
- .value=${this._editForm.type}
196
- @input=${t=>{this._editForm={...this._editForm,type:t.target.value}}}
197
- placeholder="anthropic, openai, ollama, etc."
198
- />
199
- </div>
200
- <div class="form-field">
201
- <label class="form-label">Base URL (optional)</label>
202
- <input
203
- class="form-input"
204
- type="text"
205
- .value=${this._editForm.baseUrl}
206
- @input=${t=>{this._editForm={...this._editForm,baseUrl:t.target.value}}}
207
- placeholder="Leave empty for default"
208
- />
209
- </div>
210
- <div class="form-field">
211
- <label class="form-label">API Key Name (SecretManager ref)</label>
212
- <input
213
- class="form-input"
214
- type="text"
215
- .value=${this._editForm.apiKeyName}
216
- @input=${t=>{this._editForm={...this._editForm,apiKeyName:t.target.value}}}
217
- placeholder="e.g., ANTHROPIC_API_KEY"
218
- />
219
- </div>
220
- <div class="form-actions">
221
- <button class="btn btn-primary" @click=${()=>this._saveProvider()}>Save</button>
222
- ${e?c:a`<button class="btn btn-danger" @click=${()=>this._deleteProvider()}>Delete</button>`}
223
- <button class="btn btn-secondary" @click=${()=>this._cancelEditProvider()}>Cancel</button>
123
+ `]}_onTest(){this.dispatchEvent(new CustomEvent(`test-connection`))}_onEdit(){this.dispatchEvent(new CustomEvent(`edit-provider`))}_onToggle(e){let t=e.target.checked;this.dispatchEvent(new CustomEvent(`toggle-provider`,{detail:t}))}_renderTestResult(){if(!this.testResult)return l;let e=this.testResult;return t`
124
+ <div class="test-result">
125
+ <div class="test-result-line">
126
+ <ic-icon
127
+ name=${e.status===`ok`?`check`:`x`}
128
+ size="12px"
129
+ color=${e.status===`ok`?`var(--ic-success)`:`var(--ic-error)`}
130
+ ></ic-icon>
131
+ <span>${e.status===`ok`?`Connection OK`:`Status: ${e.status}`}</span>
224
132
  </div>
133
+ ${e.modelsAvailable==null?l:t`<div class="test-result-line">Models available: ${e.modelsAvailable}</div>`}
134
+ ${e.validatedModels==null?l:t`<div class="test-result-line">Validated: ${e.validatedModels}</div>`}
225
135
  </div>
226
- `}_renderProvidersTab(){const e=Object.entries(this._providers);return e.length===0&&this._editingProvider===null?a`
227
- <ic-empty-state
228
- icon="models"
229
- message="No providers configured"
230
- description="Add a provider to connect to LLM services."
231
- ></ic-empty-state>
232
- <button class="btn-add" @click=${()=>this._startAddProvider()}>Add Provider</button>
233
- `:a`
234
- <div class="provider-grid">
235
- ${e.map(([t,i])=>a`
236
- <ic-provider-card
237
- .name=${t}
238
- .type=${i.type}
239
- .baseUrl=${i.baseUrl}
240
- .enabled=${i.enabled}
241
- .testResult=${this._providerTestResults.get(t)??null}
242
- .testing=${this._testingProviders.has(t)}
243
- @test-connection=${()=>this._testProvider(t)}
244
- @edit-provider=${()=>this._startEditProvider(t)}
245
- @toggle-provider=${s=>this._toggleProvider(t,s.detail)}
246
- ></ic-provider-card>
247
- `)}
248
- </div>
249
- ${this._renderProviderEditor()}
250
- ${this._editingProvider===null?a`<button class="btn-add" @click=${()=>this._startAddProvider()}>Add Provider</button>`:c}
251
- `}_renderProviderFilterSelect(){const e=this._getProviderNames();return a`
252
- <select
253
- class="filter-select"
254
- .value=${this._modelsProviderFilter}
255
- @change=${t=>{this._modelsProviderFilter=t.target.value}}
256
- >
257
- <option value="">All providers</option>
258
- ${e.map(t=>a`<option value=${t} ?selected=${t===this._modelsProviderFilter}>${t}</option>`)}
259
- </select>
260
- `}_renderModelsTab(){if(this._models.length===0)return a`
261
- <ic-empty-state
262
- icon="models"
263
- message="No models discovered"
264
- description="Configure providers and run a scan to discover available models."
265
- ></ic-empty-state>
266
- `;let e=[...this._models];if(this._modelsProviderFilter&&(e=e.filter(i=>i.provider===this._modelsProviderFilter)),this._modelsSearchQuery){const i=this._modelsSearchQuery.toLowerCase();e=e.filter(s=>s.modelId.toLowerCase().includes(i)||s.displayName.toLowerCase().includes(i)||s.provider.toLowerCase().includes(i))}const t=e.sort((i,s)=>{const r=i.provider.localeCompare(s.provider);return r!==0?r:i.modelId.localeCompare(s.modelId)});return a`
267
- <div class="filter-bar">
268
- <ic-search-input
269
- placeholder="Search models..."
270
- .value=${this._modelsSearchQuery}
271
- @search=${i=>{this._modelsSearchQuery=i.detail}}
272
- ></ic-search-input>
273
- ${this._renderProviderFilterSelect()}
274
- <span class="filter-count">${e.length} of ${this._models.length} models</span>
275
- </div>
276
- ${t.length===0?a`<ic-empty-state icon="models" message="No models match your filter" description="Try adjusting your search or provider filter."></ic-empty-state>`:a`
277
- <table class="models-table">
278
- <thead>
279
- <tr>
280
- <th>Model ID</th>
281
- <th>Provider</th>
282
- <th>Context Window</th>
283
- <th>Max Tokens</th>
284
- <th></th>
285
- </tr>
286
- </thead>
287
- <tbody>
288
- ${t.map(i=>a`
289
- <tr>
290
- <td class="mono">${i.modelId}</td>
291
- <td><ic-tag variant="info">${i.provider}</ic-tag></td>
292
- <td>${i.contextWindow.toLocaleString()}</td>
293
- <td>${i.maxTokens.toLocaleString()}</td>
294
- <td>
295
- ${i.validated?a`<ic-icon name="check" size="16px" class="validated-icon" label="Validated"></ic-icon>`:c}
296
- </td>
297
- </tr>
298
- `)}
299
- </tbody>
300
- </table>
301
- `}
302
- `}_startEditAlias(e){const t=this._aliases[e];this._editingAlias=e,this._aliasForm={alias:t.alias,provider:t.provider,modelId:t.modelId}}_startAddAlias(){this._editingAlias=-1,this._aliasForm={alias:"",provider:"",modelId:""}}_cancelEditAlias(){this._editingAlias=null,this._aliasForm={alias:"",provider:"",modelId:""}}async _saveAlias(){const{alias:e,provider:t,modelId:i}=this._aliasForm;if(!e.trim()||!t.trim()||!i.trim())return;const s={alias:e.trim(),provider:t.trim(),modelId:i.trim()};let r;if(this._editingAlias===-1)r=[...this._aliases,s];else if(this._editingAlias!==null)r=this._aliases.map((p,$)=>$===this._editingAlias?s:p);else return;await this._patchConfig("models.aliases",r)&&(this._aliases=r,this._editingAlias=null,this._aliasForm={alias:"",provider:"",modelId:""})}async _deleteAlias(e){const t=this._aliases.filter((s,r)=>r!==e);await this._patchConfig("models.aliases",t)&&(this._aliases=t,h.show("Alias removed","success"))}_renderAliasForm(){return this._editingAlias===null?c:a`
303
- <div class="alias-form">
304
- <div class="form-field">
305
- <label class="form-label">Alias</label>
306
- <input
307
- class="form-input"
308
- type="text"
309
- .value=${this._aliasForm.alias}
310
- @input=${e=>{this._aliasForm={...this._aliasForm,alias:e.target.value}}}
311
- placeholder="e.g., claude"
312
- />
313
- </div>
314
- <div class="form-field">
315
- <label class="form-label">Provider</label>
316
- <input
317
- class="form-input"
318
- type="text"
319
- .value=${this._aliasForm.provider}
320
- @input=${e=>{this._aliasForm={...this._aliasForm,provider:e.target.value}}}
321
- placeholder="e.g., anthropic"
322
- />
136
+ `}render(){return t`
137
+ <div class="card">
138
+ <div class="header">
139
+ <span class="name">${this.name}</span>
140
+ <ic-tag variant="info">${this.type}</ic-tag>
323
141
  </div>
324
- <div class="form-field">
325
- <label class="form-label">Model ID</label>
142
+ <div class="url-row">${this.baseUrl||`Default`}</div>
143
+ <div class="status-row">
144
+ <ic-connection-dot
145
+ status=${this.enabled?`connected`:`disconnected`}
146
+ size="6px"
147
+ ></ic-connection-dot>
148
+ <span>${this.enabled?`Enabled`:`Disabled`}</span>
326
149
  <input
327
- class="form-input"
328
- type="text"
329
- .value=${this._aliasForm.modelId}
330
- @input=${e=>{this._aliasForm={...this._aliasForm,modelId:e.target.value}}}
331
- placeholder="e.g., claude-sonnet-4-5-20250929"
150
+ type="checkbox"
151
+ .checked=${this.enabled}
152
+ @change=${this._onToggle}
153
+ aria-label="Toggle ${this.name}"
154
+ style="margin-left: auto; accent-color: var(--ic-accent); cursor: pointer;"
332
155
  />
333
156
  </div>
334
- <div class="form-actions">
335
- <button class="btn btn-primary" @click=${()=>this._saveAlias()}>
336
- ${this._editingAlias===-1?"Add Alias":"Save"}
337
- </button>
338
- <button class="btn btn-secondary" @click=${()=>this._cancelEditAlias()}>Cancel</button>
339
- </div>
340
- </div>
341
- `}_renderAliasesTab(){return this._aliases.length===0&&this._editingAlias===null?a`
342
- <ic-empty-state
343
- icon="models"
344
- message="No aliases configured"
345
- description="Create aliases to reference models by short names."
346
- ></ic-empty-state>
347
- <button class="btn-add" @click=${()=>this._startAddAlias()}>Add Alias</button>
348
- `:a`
349
- ${this._aliases.length>0?a`
350
- <table class="alias-table">
351
- <thead>
352
- <tr>
353
- <th>Alias</th>
354
- <th>Provider</th>
355
- <th>Model ID</th>
356
- <th>Actions</th>
357
- </tr>
358
- </thead>
359
- <tbody>
360
- ${this._aliases.map((e,t)=>a`
361
- <tr>
362
- <td class="mono">${e.alias}</td>
363
- <td><ic-tag variant="info">${e.provider}</ic-tag></td>
364
- <td class="mono">${e.modelId}</td>
365
- <td>
366
- <div class="alias-actions">
367
- <button
368
- class="btn btn-secondary"
369
- @click=${()=>this._startEditAlias(t)}
370
- aria-label="Edit alias ${e.alias}"
371
- >Edit</button>
372
- <button
373
- class="btn btn-danger"
374
- @click=${()=>this._deleteAlias(t)}
375
- aria-label="Delete alias ${e.alias}"
376
- >Delete</button>
377
- </div>
378
- </td>
379
- </tr>
380
- `)}
381
- </tbody>
382
- </table>
383
- `:c}
384
- ${this._renderAliasForm()}
385
- ${this._editingAlias===null?a`<button class="btn-add" @click=${()=>this._startAddAlias()}>Add Alias</button>`:c}
386
- `}async _patchModelDefaults(e,t){const i=await this._patchConfig("models",{defaultProvider:e,defaultModel:t,aliases:this._aliases});return i&&(this._defaultProvider=e,this._defaultModel=t),i}async _updateDefaultProvider(e){const t=e!==this._defaultProvider?"":this._defaultModel;await this._patchModelDefaults(e,t)}async _updateDefaultModel(e){let t=this._defaultProvider;if(e){const i=this._models.find(s=>s.modelId===e);i&&i.provider!==t&&(t=i.provider)}await this._patchModelDefaults(t,e)}_getProviderNames(){const e=Object.keys(this._providers),t=[...new Set(this._models.map(i=>i.provider))];return[...new Set([...e,...t])].sort()}_renderDefaultProviderOptions(){const e=this._getProviderNames();return a`
387
- <option value="">-- Select provider --</option>
388
- ${e.map(t=>a`<option value=${t} ?selected=${t===this._defaultProvider}>${t}</option>`)}
389
- `}_renderDefaultModelOptions(){const t=[...this._defaultProvider?this._models.filter(i=>i.provider===this._defaultProvider):this._models].sort((i,s)=>i.modelId.localeCompare(s.modelId));return this._defaultProvider?a`
390
- <option value="">-- Select model --</option>
391
- ${t.map(i=>a`<option value=${i.modelId} ?selected=${i.modelId===this._defaultModel}>${i.modelId}</option>`)}
392
- `:a`
393
- <option value="">-- Select model --</option>
394
- ${t.map(i=>a`<option value=${i.modelId} ?selected=${i.modelId===this._defaultModel}>${i.provider}/${i.modelId}</option>`)}
395
- `}async _updateAgentOverride(e,t,i){if(this.rpcClient)try{await this.rpcClient.call("agents.update",{agentId:e,config:{provider:t||void 0,model:i||void 0}}),this._agents=this._agents.map(s=>s.id===e?{...s,provider:t,model:i}:s),h.show("Agent model override updated","success")}catch(s){const r=s instanceof Error?s.message:"Failed to update agent override";h.show(r,"error")}}_renderAgentOverrideProviderOptions(e){const t=this._getProviderNames();return a`
396
- <option value="">-- Inherit default --</option>
397
- ${t.map(i=>a`<option value=${i} ?selected=${i===e.provider}>${i}</option>`)}
398
- `}_renderAgentOverrideModelOptions(e){const i=[...e.provider?this._models.filter(r=>r.provider===e.provider):this._models].sort((r,n)=>r.modelId.localeCompare(n.modelId)),s=!e.model;return e.provider?a`
399
- <option value="" ?selected=${s}>-- Select model --</option>
400
- ${i.map(r=>a`<option value=${r.modelId} ?selected=${r.modelId===e.model}>${r.modelId}</option>`)}
401
- `:a`
402
- <option value="" ?selected=${s}>-- Inherit default --</option>
403
- ${i.map(r=>a`<option value=${r.modelId} ?selected=${r.modelId===e.model}>${r.provider}/${r.modelId}</option>`)}
404
- `}_renderPerAgentOverrides(){return this._agents.length===0?a`
405
- <ic-empty-state
406
- icon="models"
407
- message="No agents configured"
408
- description="Configure agents to set per-agent model overrides."
409
- ></ic-empty-state>
410
- `:a`
411
- <table class="overrides-table">
412
- <thead>
413
- <tr>
414
- <th>Agent</th>
415
- <th>Provider</th>
416
- <th>Model</th>
417
- </tr>
418
- </thead>
419
- <tbody>
420
- ${this._agents.map(e=>a`
421
- <tr>
422
- <td class="mono">${e.id}</td>
423
- <td>
424
- <select
425
- class="override-select"
426
- .value=${e.provider}
427
- @change=${t=>{const i=t.target.value;this._updateAgentOverride(e.id,i,"")}}
428
- >
429
- ${this._renderAgentOverrideProviderOptions(e)}
430
- </select>
431
- </td>
432
- <td>
433
- <select
434
- class="override-select"
435
- .value=${e.model}
436
- @change=${t=>{const i=t.target.value;this._updateAgentOverride(e.id,e.provider,i)}}
437
- >
438
- ${this._renderAgentOverrideModelOptions(e)}
439
- </select>
440
- </td>
441
- </tr>
442
- `)}
443
- </tbody>
444
- </table>
445
- `}_renderDefaultsTab(){return a`
446
- <div class="defaults-section">
447
- <div class="form-field">
448
- <label class="form-label">Default Provider</label>
449
- <select
450
- class="defaults-select"
451
- .value=${this._defaultProvider}
452
- @change=${e=>{this._updateDefaultProvider(e.target.value)}}
157
+ ${this._renderTestResult()}
158
+ <div class="actions">
159
+ <button
160
+ class="btn btn-test"
161
+ @click=${this._onTest}
162
+ ?disabled=${this.testing}
163
+ aria-label="Test connection for ${this.name}"
453
164
  >
454
- ${this._renderDefaultProviderOptions()}
455
- </select>
456
- </div>
457
-
458
- <div class="form-field">
459
- <label class="form-label">Default Model</label>
460
- <select
461
- class="defaults-select"
462
- .value=${this._defaultModel}
463
- @change=${e=>{this._updateDefaultModel(e.target.value)}}
165
+ ${this.testing?t`<span class="spinner-inline"></span>`:`Test`}
166
+ </button>
167
+ <button
168
+ class="btn btn-edit"
169
+ @click=${this._onEdit}
170
+ aria-label="Edit ${this.name}"
464
171
  >
465
- ${this._renderDefaultModelOptions()}
466
- </select>
467
- </div>
468
-
469
- <div class="defaults-summary">
470
- Current default:
471
- <ic-tag variant="accent">${this._defaultProvider||"none"}</ic-tag>
472
- /
473
- <ic-tag variant="info">${this._defaultModel||"none"}</ic-tag>
474
- </div>
475
-
476
- <div class="defaults-resolved">
477
- ${this._defaultProvider&&this._defaultModel?a`<span>Resolved: <code class="mono">${this._defaultProvider}/${this._defaultModel}</code></span>`:a`<span style="color: var(--ic-warning)">Select both a provider and model to set defaults</span>`}
478
- </div>
479
-
480
- <hr class="overrides-divider" />
481
- <div class="overrides-heading">Per-Agent Overrides</div>
482
- ${this._renderPerAgentOverrides()}
483
- </div>
484
- `}_renderTabContent(){switch(this._activeTab){case"providers":return this._renderProvidersTab();case"models":return this._renderModelsTab();case"aliases":return this._renderAliasesTab();case"defaults":return this._renderDefaultsTab();default:return c}}render(){return this._loadState==="loading"?a`<ic-skeleton-view variant="list"></ic-skeleton-view>`:this._loadState==="error"?a`
485
- <div class="error-container">
486
- <span class="error-message">${this._error}</span>
487
- <button class="retry-btn" @click=${()=>this._loadData()}>Retry</button>
172
+ Edit
173
+ </button>
488
174
  </div>
489
- `:a`
490
- <div class="view-header">
491
- <div class="view-title">Models & Providers</div>
492
- </div>
493
- <ic-tabs
494
- .tabs=${C}
495
- .activeTab=${this._activeTab}
496
- @tab-change=${e=>{this._activeTab=e.detail}}
497
- ></ic-tabs>
498
- <div style="margin-top: var(--ic-space-md);">
499
- ${this._renderTabContent()}
500
175
  </div>
501
- `}};o.styles=[f,b,_`
176
+ `}};c([s()],f.prototype,`name`,void 0),c([s()],f.prototype,`type`,void 0),c([s()],f.prototype,`baseUrl`,void 0),c([s({type:Boolean})],f.prototype,`enabled`,void 0),c([s({attribute:!1})],f.prototype,`testResult`,void 0),c([s({type:Boolean})],f.prototype,`testing`,void 0),f=c([e(`ic-provider-card`)],f);var p=[{id:`providers`,label:`Providers`},{id:`models`,label:`Catalog`},{id:`aliases`,label:`Aliases`},{id:`defaults`,label:`Defaults`}],m=class extends r{constructor(...e){super(...e),this.apiClient=null,this.rpcClient=null,this.eventDispatcher=null,this._sse=null,this._reloadDebounce=null,this._loadState=`loading`,this._error=``,this._activeTab=`providers`,this._providers={},this._models=[],this._aliases=[],this._defaultProvider=``,this._defaultModel=``,this._providerTestResults=new Map,this._testingProviders=new Set,this._editingProvider=null,this._editForm={name:``,type:``,baseUrl:``,apiKeyName:``},this._editingAlias=null,this._aliasForm={alias:``,provider:``,modelId:``},this._modelsSearchQuery=``,this._modelsProviderFilter=``,this._agents=[],this._rpcStatusUnsub=null}static{this.styles=[o,i,n`
502
177
  :host {
503
178
  display: block;
504
179
  }
@@ -891,4 +566,329 @@ import{s as f,f as b,i as _,n as u,a as g,A as c,b as a,t as y,S as x,I as h,r a
891
566
  outline: none;
892
567
  border-color: var(--ic-accent);
893
568
  }
894
- `];d([u({attribute:!1})],o.prototype,"apiClient",2);d([u({attribute:!1})],o.prototype,"rpcClient",2);d([u({attribute:!1})],o.prototype,"eventDispatcher",2);d([l()],o.prototype,"_loadState",2);d([l()],o.prototype,"_error",2);d([l()],o.prototype,"_activeTab",2);d([l()],o.prototype,"_providers",2);d([l()],o.prototype,"_models",2);d([l()],o.prototype,"_aliases",2);d([l()],o.prototype,"_defaultProvider",2);d([l()],o.prototype,"_defaultModel",2);d([l()],o.prototype,"_providerTestResults",2);d([l()],o.prototype,"_testingProviders",2);d([l()],o.prototype,"_editingProvider",2);d([l()],o.prototype,"_editForm",2);d([l()],o.prototype,"_editingAlias",2);d([l()],o.prototype,"_aliasForm",2);d([l()],o.prototype,"_modelsSearchQuery",2);d([l()],o.prototype,"_modelsProviderFilter",2);d([l()],o.prototype,"_agents",2);o=d([y("ic-models-view")],o);export{o as IcModelsView};
569
+ `]}connectedCallback(){super.connectedCallback(),this._initSse()}disconnectedCallback(){super.disconnectedCallback(),this._rpcStatusUnsub?.(),this._rpcStatusUnsub=null,this._reloadDebounce!==null&&(clearTimeout(this._reloadDebounce),this._reloadDebounce=null)}updated(e){e.has(`eventDispatcher`)&&this.eventDispatcher&&!this._sse&&this._initSse(),e.has(`rpcClient`)&&this.rpcClient&&(this._rpcStatusUnsub?.(),this._rpcStatusUnsub=null,this.rpcClient.status===`connected`?this._loadData():this._rpcStatusUnsub=this.rpcClient.onStatusChange(e=>{e===`connected`&&(this._rpcStatusUnsub?.(),this._rpcStatusUnsub=null,this._loadData())}))}_scheduleReload(e=300){this._reloadDebounce!==null&&clearTimeout(this._reloadDebounce),this._reloadDebounce=setTimeout(()=>{this._reloadDebounce=null,this._loadData()},e)}_initSse(){!this.eventDispatcher||this._sse||(this._sse=new d(this,this.eventDispatcher,{"model:catalog_loaded":()=>{this._scheduleReload()}}))}async _loadData(){if(this.rpcClient){this._loadState=`loading`,this._error=``;try{let e=await this.rpcClient.call(`config.read`);this._providers=e.config.providers?.entries??{},this._aliases=e.config.models?.aliases??[],this._defaultProvider=e.config.models?.defaultProvider??``,this._defaultModel=e.config.models?.defaultModel??``,this._loadState=`loaded`,this.rpcClient.call(`models.list`).then(e=>{e.models&&e.models.length>0?this._models=e.models:e.providers&&e.providers.length>0&&(this._models=e.providers.flatMap(e=>(e.models??[]).map(t=>{let n=typeof t==`object`&&!!t,r=n?t.modelId:t;return{provider:e.name,modelId:r,displayName:r,contextWindow:n?t.contextWindow:0,maxTokens:n?t.maxTokens:0,input:!0,reasoning:!1,validated:!1}})))}).catch(()=>{}),(async()=>{try{let e=((await this.rpcClient.call(`agents.list`)).agents??[]).slice(0,20),t=await Promise.allSettled(e.map(e=>this.rpcClient.call(`agents.get`,{agentId:e})));this._agents=t.filter(e=>e.status===`fulfilled`&&e.value.agentId!=null).map(e=>({id:e.value.agentId,provider:e.value.config.provider??``,model:e.value.config.model??``}))}catch{this._agents=[]}})()}catch(e){this._error=e instanceof Error?e.message:`Failed to load model configuration`,this._loadState=`error`}}}async _patchConfig(e,t){if(!this.rpcClient)return!1;try{let n=e.indexOf(`.`),r=n>0?e.slice(0,n):e,i=n>0?e.slice(n+1):void 0;return await this.rpcClient.call(`config.patch`,{section:r,key:i,value:t}),u.show(`Configuration updated`,`success`),!0}catch(e){let t=e instanceof Error?e.message:`Failed to update configuration`;return u.show(t,`error`),!1}}async _testProvider(e){if(!this.rpcClient)return;let t=new Set(this._testingProviders);t.add(e),this._testingProviders=t;try{let t=await this.rpcClient.call(`models.test`,{provider:e}),n=new Map(this._providerTestResults);n.set(e,t),this._providerTestResults=n,u.show(`Provider "${e}" test: ${t.status}`,t.status===`ok`?`success`:`warning`)}catch(t){let n=t instanceof Error?t.message:`Test failed`,r=new Map(this._providerTestResults);r.set(e,{status:`error`}),this._providerTestResults=r,u.show(`Provider "${e}" test failed: ${n}`,`error`)}finally{let t=new Set(this._testingProviders);t.delete(e),this._testingProviders=t}}async _toggleProvider(e,t){await this._patchConfig(`providers.entries.${e}.enabled`,t)&&(this._providers={...this._providers,[e]:{...this._providers[e],enabled:t}})}_startEditProvider(e){let t=this._providers[e];this._editingProvider=e,this._editForm={name:e,type:t?.type??``,baseUrl:t?.baseUrl??``,apiKeyName:t?.apiKeyName??``}}_startAddProvider(){this._editingProvider=``,this._editForm={name:``,type:``,baseUrl:``,apiKeyName:``}}_cancelEditProvider(){this._editingProvider=null}async _saveProvider(){let{name:e,type:t,baseUrl:n,apiKeyName:r}=this._editForm;if(!e.trim()||!t.trim())return;let i={type:t.trim(),name:e.trim(),baseUrl:n.trim(),apiKeyName:r.trim(),enabled:this._providers[e]?.enabled??!0,timeoutMs:this._providers[e]?.timeoutMs??12e4,maxRetries:this._providers[e]?.maxRetries??2};await this._patchConfig(`providers.entries.${e.trim()}`,i)&&(this._providers={...this._providers,[e.trim()]:i},this._editingProvider=null)}async _deleteProvider(){if(!this._editingProvider)return;let e=this._editingProvider,t={...this._providers};delete t[e],await this._patchConfig(`providers.entries`,t)&&(this._providers=t,this._editingProvider=null)}_renderProviderEditor(){if(this._editingProvider===null)return l;let e=this._editingProvider===``;return t`
570
+ <div class="editor-form">
571
+ <div class="editor-title">${e?`Add Provider`:`Edit: ${this._editingProvider}`}</div>
572
+ <div class="form-field">
573
+ <label class="form-label">Provider Name</label>
574
+ <input
575
+ class="form-input"
576
+ type="text"
577
+ .value=${this._editForm.name}
578
+ ?disabled=${!e}
579
+ @input=${e=>{this._editForm={...this._editForm,name:e.target.value}}}
580
+ placeholder="e.g., anthropic"
581
+ />
582
+ </div>
583
+ <div class="form-field">
584
+ <label class="form-label">Type</label>
585
+ <input
586
+ class="form-input"
587
+ type="text"
588
+ .value=${this._editForm.type}
589
+ @input=${e=>{this._editForm={...this._editForm,type:e.target.value}}}
590
+ placeholder="anthropic, openai, ollama, etc."
591
+ />
592
+ </div>
593
+ <div class="form-field">
594
+ <label class="form-label">Base URL (optional)</label>
595
+ <input
596
+ class="form-input"
597
+ type="text"
598
+ .value=${this._editForm.baseUrl}
599
+ @input=${e=>{this._editForm={...this._editForm,baseUrl:e.target.value}}}
600
+ placeholder="Leave empty for default"
601
+ />
602
+ </div>
603
+ <div class="form-field">
604
+ <label class="form-label">API Key Name (SecretManager ref)</label>
605
+ <input
606
+ class="form-input"
607
+ type="text"
608
+ .value=${this._editForm.apiKeyName}
609
+ @input=${e=>{this._editForm={...this._editForm,apiKeyName:e.target.value}}}
610
+ placeholder="e.g., ANTHROPIC_API_KEY"
611
+ />
612
+ </div>
613
+ <div class="form-actions">
614
+ <button class="btn btn-primary" @click=${()=>this._saveProvider()}>Save</button>
615
+ ${e?l:t`<button class="btn btn-danger" @click=${()=>this._deleteProvider()}>Delete</button>`}
616
+ <button class="btn btn-secondary" @click=${()=>this._cancelEditProvider()}>Cancel</button>
617
+ </div>
618
+ </div>
619
+ `}_renderProvidersTab(){let e=Object.entries(this._providers);return e.length===0&&this._editingProvider===null?t`
620
+ <ic-empty-state
621
+ icon="models"
622
+ message="No providers configured"
623
+ description="Add a provider to connect to LLM services."
624
+ ></ic-empty-state>
625
+ <button class="btn-add" @click=${()=>this._startAddProvider()}>Add Provider</button>
626
+ `:t`
627
+ <div class="provider-grid">
628
+ ${e.map(([e,n])=>t`
629
+ <ic-provider-card
630
+ .name=${e}
631
+ .type=${n.type}
632
+ .baseUrl=${n.baseUrl}
633
+ .enabled=${n.enabled}
634
+ .testResult=${this._providerTestResults.get(e)??null}
635
+ .testing=${this._testingProviders.has(e)}
636
+ @test-connection=${()=>this._testProvider(e)}
637
+ @edit-provider=${()=>this._startEditProvider(e)}
638
+ @toggle-provider=${t=>this._toggleProvider(e,t.detail)}
639
+ ></ic-provider-card>
640
+ `)}
641
+ </div>
642
+ ${this._renderProviderEditor()}
643
+ ${this._editingProvider===null?t`<button class="btn-add" @click=${()=>this._startAddProvider()}>Add Provider</button>`:l}
644
+ `}_renderProviderFilterSelect(){let e=this._getProviderNames();return t`
645
+ <select
646
+ class="filter-select"
647
+ .value=${this._modelsProviderFilter}
648
+ @change=${e=>{this._modelsProviderFilter=e.target.value}}
649
+ >
650
+ <option value="">All providers</option>
651
+ ${e.map(e=>t`<option value=${e} ?selected=${e===this._modelsProviderFilter}>${e}</option>`)}
652
+ </select>
653
+ `}_renderModelsTab(){if(this._models.length===0)return t`
654
+ <ic-empty-state
655
+ icon="models"
656
+ message="No models discovered"
657
+ description="Configure providers and run a scan to discover available models."
658
+ ></ic-empty-state>
659
+ `;let e=[...this._models];if(this._modelsProviderFilter&&(e=e.filter(e=>e.provider===this._modelsProviderFilter)),this._modelsSearchQuery){let t=this._modelsSearchQuery.toLowerCase();e=e.filter(e=>e.modelId.toLowerCase().includes(t)||e.displayName.toLowerCase().includes(t)||e.provider.toLowerCase().includes(t))}let n=e.sort((e,t)=>{let n=e.provider.localeCompare(t.provider);return n===0?e.modelId.localeCompare(t.modelId):n});return t`
660
+ <div class="filter-bar">
661
+ <ic-search-input
662
+ placeholder="Search models..."
663
+ .value=${this._modelsSearchQuery}
664
+ @search=${e=>{this._modelsSearchQuery=e.detail}}
665
+ ></ic-search-input>
666
+ ${this._renderProviderFilterSelect()}
667
+ <span class="filter-count">${e.length} of ${this._models.length} models</span>
668
+ </div>
669
+ ${n.length===0?t`<ic-empty-state icon="models" message="No models match your filter" description="Try adjusting your search or provider filter."></ic-empty-state>`:t`
670
+ <table class="models-table">
671
+ <thead>
672
+ <tr>
673
+ <th>Model ID</th>
674
+ <th>Provider</th>
675
+ <th>Context Window</th>
676
+ <th>Max Tokens</th>
677
+ <th></th>
678
+ </tr>
679
+ </thead>
680
+ <tbody>
681
+ ${n.map(e=>t`
682
+ <tr>
683
+ <td class="mono">${e.modelId}</td>
684
+ <td><ic-tag variant="info">${e.provider}</ic-tag></td>
685
+ <td>${e.contextWindow.toLocaleString()}</td>
686
+ <td>${e.maxTokens.toLocaleString()}</td>
687
+ <td>
688
+ ${e.validated?t`<ic-icon name="check" size="16px" class="validated-icon" label="Validated"></ic-icon>`:l}
689
+ </td>
690
+ </tr>
691
+ `)}
692
+ </tbody>
693
+ </table>
694
+ `}
695
+ `}_startEditAlias(e){let t=this._aliases[e];this._editingAlias=e,this._aliasForm={alias:t.alias,provider:t.provider,modelId:t.modelId}}_startAddAlias(){this._editingAlias=-1,this._aliasForm={alias:``,provider:``,modelId:``}}_cancelEditAlias(){this._editingAlias=null,this._aliasForm={alias:``,provider:``,modelId:``}}async _saveAlias(){let{alias:e,provider:t,modelId:n}=this._aliasForm;if(!e.trim()||!t.trim()||!n.trim())return;let r={alias:e.trim(),provider:t.trim(),modelId:n.trim()},i;if(this._editingAlias===-1)i=[...this._aliases,r];else if(this._editingAlias!==null)i=this._aliases.map((e,t)=>t===this._editingAlias?r:e);else return;await this._patchConfig(`models.aliases`,i)&&(this._aliases=i,this._editingAlias=null,this._aliasForm={alias:``,provider:``,modelId:``})}async _deleteAlias(e){let t=this._aliases.filter((t,n)=>n!==e);await this._patchConfig(`models.aliases`,t)&&(this._aliases=t,u.show(`Alias removed`,`success`))}_renderAliasForm(){return this._editingAlias===null?l:t`
696
+ <div class="alias-form">
697
+ <div class="form-field">
698
+ <label class="form-label">Alias</label>
699
+ <input
700
+ class="form-input"
701
+ type="text"
702
+ .value=${this._aliasForm.alias}
703
+ @input=${e=>{this._aliasForm={...this._aliasForm,alias:e.target.value}}}
704
+ placeholder="e.g., claude"
705
+ />
706
+ </div>
707
+ <div class="form-field">
708
+ <label class="form-label">Provider</label>
709
+ <input
710
+ class="form-input"
711
+ type="text"
712
+ .value=${this._aliasForm.provider}
713
+ @input=${e=>{this._aliasForm={...this._aliasForm,provider:e.target.value}}}
714
+ placeholder="e.g., anthropic"
715
+ />
716
+ </div>
717
+ <div class="form-field">
718
+ <label class="form-label">Model ID</label>
719
+ <input
720
+ class="form-input"
721
+ type="text"
722
+ .value=${this._aliasForm.modelId}
723
+ @input=${e=>{this._aliasForm={...this._aliasForm,modelId:e.target.value}}}
724
+ placeholder="e.g., claude-sonnet-4-5-20250929"
725
+ />
726
+ </div>
727
+ <div class="form-actions">
728
+ <button class="btn btn-primary" @click=${()=>this._saveAlias()}>
729
+ ${this._editingAlias===-1?`Add Alias`:`Save`}
730
+ </button>
731
+ <button class="btn btn-secondary" @click=${()=>this._cancelEditAlias()}>Cancel</button>
732
+ </div>
733
+ </div>
734
+ `}_renderAliasesTab(){return this._aliases.length===0&&this._editingAlias===null?t`
735
+ <ic-empty-state
736
+ icon="models"
737
+ message="No aliases configured"
738
+ description="Create aliases to reference models by short names."
739
+ ></ic-empty-state>
740
+ <button class="btn-add" @click=${()=>this._startAddAlias()}>Add Alias</button>
741
+ `:t`
742
+ ${this._aliases.length>0?t`
743
+ <table class="alias-table">
744
+ <thead>
745
+ <tr>
746
+ <th>Alias</th>
747
+ <th>Provider</th>
748
+ <th>Model ID</th>
749
+ <th>Actions</th>
750
+ </tr>
751
+ </thead>
752
+ <tbody>
753
+ ${this._aliases.map((e,n)=>t`
754
+ <tr>
755
+ <td class="mono">${e.alias}</td>
756
+ <td><ic-tag variant="info">${e.provider}</ic-tag></td>
757
+ <td class="mono">${e.modelId}</td>
758
+ <td>
759
+ <div class="alias-actions">
760
+ <button
761
+ class="btn btn-secondary"
762
+ @click=${()=>this._startEditAlias(n)}
763
+ aria-label="Edit alias ${e.alias}"
764
+ >Edit</button>
765
+ <button
766
+ class="btn btn-danger"
767
+ @click=${()=>this._deleteAlias(n)}
768
+ aria-label="Delete alias ${e.alias}"
769
+ >Delete</button>
770
+ </div>
771
+ </td>
772
+ </tr>
773
+ `)}
774
+ </tbody>
775
+ </table>
776
+ `:l}
777
+ ${this._renderAliasForm()}
778
+ ${this._editingAlias===null?t`<button class="btn-add" @click=${()=>this._startAddAlias()}>Add Alias</button>`:l}
779
+ `}async _patchModelDefaults(e,t){let n=await this._patchConfig(`models`,{defaultProvider:e,defaultModel:t,aliases:this._aliases});return n&&(this._defaultProvider=e,this._defaultModel=t),n}async _updateDefaultProvider(e){let t=e===this._defaultProvider?this._defaultModel:``;await this._patchModelDefaults(e,t)}async _updateDefaultModel(e){let t=this._defaultProvider;if(e){let n=this._models.find(t=>t.modelId===e);n&&n.provider!==t&&(t=n.provider)}await this._patchModelDefaults(t,e)}_getProviderNames(){let e=Object.keys(this._providers),t=[...new Set(this._models.map(e=>e.provider))];return[...new Set([...e,...t])].sort()}_renderDefaultProviderOptions(){return t`
780
+ <option value="">-- Select provider --</option>
781
+ ${this._getProviderNames().map(e=>t`<option value=${e} ?selected=${e===this._defaultProvider}>${e}</option>`)}
782
+ `}_renderDefaultModelOptions(){let e=[...this._defaultProvider?this._models.filter(e=>e.provider===this._defaultProvider):this._models].sort((e,t)=>e.modelId.localeCompare(t.modelId));return this._defaultProvider?t`
783
+ <option value="">-- Select model --</option>
784
+ ${e.map(e=>t`<option value=${e.modelId} ?selected=${e.modelId===this._defaultModel}>${e.modelId}</option>`)}
785
+ `:t`
786
+ <option value="">-- Select model --</option>
787
+ ${e.map(e=>t`<option value=${e.modelId} ?selected=${e.modelId===this._defaultModel}>${e.provider}/${e.modelId}</option>`)}
788
+ `}async _updateAgentOverride(e,t,n){if(this.rpcClient)try{await this.rpcClient.call(`agents.update`,{agentId:e,config:{provider:t||void 0,model:n||void 0}}),this._agents=this._agents.map(r=>r.id===e?{...r,provider:t,model:n}:r),u.show(`Agent model override updated`,`success`)}catch(e){let t=e instanceof Error?e.message:`Failed to update agent override`;u.show(t,`error`)}}_renderAgentOverrideProviderOptions(e){return t`
789
+ <option value="">-- Inherit default --</option>
790
+ ${this._getProviderNames().map(n=>t`<option value=${n} ?selected=${n===e.provider}>${n}</option>`)}
791
+ `}_renderAgentOverrideModelOptions(e){let n=[...e.provider?this._models.filter(t=>t.provider===e.provider):this._models].sort((e,t)=>e.modelId.localeCompare(t.modelId)),r=!e.model;return e.provider?t`
792
+ <option value="" ?selected=${r}>-- Select model --</option>
793
+ ${n.map(n=>t`<option value=${n.modelId} ?selected=${n.modelId===e.model}>${n.modelId}</option>`)}
794
+ `:t`
795
+ <option value="" ?selected=${r}>-- Inherit default --</option>
796
+ ${n.map(n=>t`<option value=${n.modelId} ?selected=${n.modelId===e.model}>${n.provider}/${n.modelId}</option>`)}
797
+ `}_renderPerAgentOverrides(){return this._agents.length===0?t`
798
+ <ic-empty-state
799
+ icon="models"
800
+ message="No agents configured"
801
+ description="Configure agents to set per-agent model overrides."
802
+ ></ic-empty-state>
803
+ `:t`
804
+ <table class="overrides-table">
805
+ <thead>
806
+ <tr>
807
+ <th>Agent</th>
808
+ <th>Provider</th>
809
+ <th>Model</th>
810
+ </tr>
811
+ </thead>
812
+ <tbody>
813
+ ${this._agents.map(e=>t`
814
+ <tr>
815
+ <td class="mono">${e.id}</td>
816
+ <td>
817
+ <select
818
+ class="override-select"
819
+ .value=${e.provider}
820
+ @change=${t=>{let n=t.target.value;this._updateAgentOverride(e.id,n,``)}}
821
+ >
822
+ ${this._renderAgentOverrideProviderOptions(e)}
823
+ </select>
824
+ </td>
825
+ <td>
826
+ <select
827
+ class="override-select"
828
+ .value=${e.model}
829
+ @change=${t=>{let n=t.target.value;this._updateAgentOverride(e.id,e.provider,n)}}
830
+ >
831
+ ${this._renderAgentOverrideModelOptions(e)}
832
+ </select>
833
+ </td>
834
+ </tr>
835
+ `)}
836
+ </tbody>
837
+ </table>
838
+ `}_renderDefaultsTab(){return t`
839
+ <div class="defaults-section">
840
+ <div class="form-field">
841
+ <label class="form-label">Default Provider</label>
842
+ <select
843
+ class="defaults-select"
844
+ .value=${this._defaultProvider}
845
+ @change=${e=>{this._updateDefaultProvider(e.target.value)}}
846
+ >
847
+ ${this._renderDefaultProviderOptions()}
848
+ </select>
849
+ </div>
850
+
851
+ <div class="form-field">
852
+ <label class="form-label">Default Model</label>
853
+ <select
854
+ class="defaults-select"
855
+ .value=${this._defaultModel}
856
+ @change=${e=>{this._updateDefaultModel(e.target.value)}}
857
+ >
858
+ ${this._renderDefaultModelOptions()}
859
+ </select>
860
+ </div>
861
+
862
+ <div class="defaults-summary">
863
+ Current default:
864
+ <ic-tag variant="accent">${this._defaultProvider||`none`}</ic-tag>
865
+ /
866
+ <ic-tag variant="info">${this._defaultModel||`none`}</ic-tag>
867
+ </div>
868
+
869
+ <div class="defaults-resolved">
870
+ ${this._defaultProvider&&this._defaultModel?t`<span>Resolved: <code class="mono">${this._defaultProvider}/${this._defaultModel}</code></span>`:t`<span style="color: var(--ic-warning)">Select both a provider and model to set defaults</span>`}
871
+ </div>
872
+
873
+ <hr class="overrides-divider" />
874
+ <div class="overrides-heading">Per-Agent Overrides</div>
875
+ ${this._renderPerAgentOverrides()}
876
+ </div>
877
+ `}_renderTabContent(){switch(this._activeTab){case`providers`:return this._renderProvidersTab();case`models`:return this._renderModelsTab();case`aliases`:return this._renderAliasesTab();case`defaults`:return this._renderDefaultsTab();default:return l}}render(){return this._loadState===`loading`?t`<ic-skeleton-view variant="list"></ic-skeleton-view>`:this._loadState===`error`?t`
878
+ <div class="error-container">
879
+ <span class="error-message">${this._error}</span>
880
+ <button class="retry-btn" @click=${()=>this._loadData()}>Retry</button>
881
+ </div>
882
+ `:t`
883
+ <div class="view-header">
884
+ <div class="view-title">Models & Providers</div>
885
+ </div>
886
+ <ic-tabs
887
+ .tabs=${p}
888
+ .activeTab=${this._activeTab}
889
+ @tab-change=${e=>{this._activeTab=e.detail}}
890
+ ></ic-tabs>
891
+ <div style="margin-top: var(--ic-space-md);">
892
+ ${this._renderTabContent()}
893
+ </div>
894
+ `}};c([s({attribute:!1})],m.prototype,`apiClient`,void 0),c([s({attribute:!1})],m.prototype,`rpcClient`,void 0),c([s({attribute:!1})],m.prototype,`eventDispatcher`,void 0),c([a()],m.prototype,`_loadState`,void 0),c([a()],m.prototype,`_error`,void 0),c([a()],m.prototype,`_activeTab`,void 0),c([a()],m.prototype,`_providers`,void 0),c([a()],m.prototype,`_models`,void 0),c([a()],m.prototype,`_aliases`,void 0),c([a()],m.prototype,`_defaultProvider`,void 0),c([a()],m.prototype,`_defaultModel`,void 0),c([a()],m.prototype,`_providerTestResults`,void 0),c([a()],m.prototype,`_testingProviders`,void 0),c([a()],m.prototype,`_editingProvider`,void 0),c([a()],m.prototype,`_editForm`,void 0),c([a()],m.prototype,`_editingAlias`,void 0),c([a()],m.prototype,`_aliasForm`,void 0),c([a()],m.prototype,`_modelsSearchQuery`,void 0),c([a()],m.prototype,`_modelsProviderFilter`,void 0),c([a()],m.prototype,`_agents`,void 0),m=c([e(`ic-models-view`)],m);export{m as IcModelsView};