comisai 1.0.23 → 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.
- package/node_modules/@comis/agent/dist/executor/pi-executor.js +17 -0
- package/node_modules/@comis/agent/dist/index.d.ts +2 -1
- package/node_modules/@comis/agent/dist/index.js +1 -1
- package/node_modules/@comis/agent/dist/model/auth-storage-adapter.d.ts +21 -0
- package/node_modules/@comis/agent/dist/model/auth-storage-adapter.js +15 -1
- package/node_modules/@comis/agent/dist/model/model-registry-adapter.d.ts +46 -0
- package/node_modules/@comis/agent/dist/model/model-registry-adapter.js +108 -0
- package/node_modules/@comis/agent/package.json +1 -1
- package/node_modules/@comis/channels/package.json +1 -1
- package/node_modules/@comis/cli/package.json +1 -1
- package/node_modules/@comis/core/dist/bootstrap.js +5 -0
- package/node_modules/@comis/core/dist/config/env-layer.d.ts +31 -0
- package/node_modules/@comis/core/dist/config/env-layer.js +41 -0
- package/node_modules/@comis/core/dist/config/layered.d.ts +9 -0
- package/node_modules/@comis/core/dist/config/layered.js +11 -0
- package/node_modules/@comis/core/package.json +1 -1
- package/node_modules/@comis/daemon/dist/daemon.js +3 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-agents.js +15 -3
- package/node_modules/@comis/daemon/package.json +1 -1
- package/node_modules/@comis/gateway/package.json +1 -1
- package/node_modules/@comis/infra/package.json +1 -1
- package/node_modules/@comis/memory/package.json +1 -1
- package/node_modules/@comis/scheduler/package.json +1 -1
- package/node_modules/@comis/shared/package.json +1 -1
- package/node_modules/@comis/skills/package.json +1 -1
- package/node_modules/@comis/web/dist/assets/{agent-detail-BG9MGWWj.js → agent-detail-ru-AhppM.js} +270 -270
- package/node_modules/@comis/web/dist/assets/agent-editor-hjwRuFVp.js +2173 -0
- package/node_modules/@comis/web/dist/assets/{agent-list-LHCJ4rw2.js → agent-list-6Uotjatr.js} +170 -170
- package/node_modules/@comis/web/dist/assets/{approvals-q9VH_IKr.js → approvals-C-K6hN2U.js} +13 -13
- package/node_modules/@comis/web/dist/assets/billing-view-CxysXH0p.js +375 -0
- package/node_modules/@comis/web/dist/assets/{channel-detail-CaInesJM.js → channel-detail-BBCKtmne.js} +265 -265
- package/node_modules/@comis/web/dist/assets/channel-list-FkfeOLBQ.js +323 -0
- package/node_modules/@comis/web/dist/assets/{chat-console-CNmzl0JW.js → chat-console-BumBaIgO.js} +243 -246
- package/node_modules/@comis/web/dist/assets/{config-editor-DX4ITw6y.js → config-editor-C9BSwHGy.js} +477 -477
- package/node_modules/@comis/web/dist/assets/{context-dag-browser-BwiaF5tf.js → context-dag-browser-BHm00mJD.js} +105 -105
- package/node_modules/@comis/web/dist/assets/{context-engine-BZ5Am6hA.js → context-engine-BENY3pWE.js} +136 -136
- package/node_modules/@comis/web/dist/assets/decorate-BvWYovGE.js +38 -0
- package/node_modules/@comis/web/dist/assets/{delivery-view-OfBZof-m.js → delivery-view-BCnkPsAp.js} +134 -134
- package/node_modules/@comis/web/dist/assets/{diagnostics-view-YFwCxgr2.js → diagnostics-view-C_jQFG2H.js} +82 -82
- package/node_modules/@comis/web/dist/assets/directive-BOYXJ-K-.js +1 -0
- package/node_modules/@comis/web/dist/assets/{extract-variables-BM5qyK-s.js → extract-variables-B7-Doo7l.js} +39 -39
- package/node_modules/@comis/web/dist/assets/{ic-array-editor-B7m6x7-S.js → ic-array-editor-BLoEyeLS.js} +29 -29
- package/node_modules/@comis/web/dist/assets/{ic-breadcrumb-CUMpp3BL.js → ic-breadcrumb-DqN6G3gc.js} +16 -16
- package/node_modules/@comis/web/dist/assets/{ic-budget-segment-bar-BtJ6x5mN.js → ic-budget-segment-bar-zLsMzjDO.js} +20 -20
- package/node_modules/@comis/web/dist/assets/ic-chat-message-FdQcZsSQ.js +352 -0
- package/node_modules/@comis/web/dist/assets/{ic-confirm-dialog-CCDbB04e.js → ic-confirm-dialog-DGlPbV1T.js} +26 -26
- package/node_modules/@comis/web/dist/assets/{ic-connection-dot-CnT1b8xr.js → ic-connection-dot-BgYiK2N4.js} +13 -13
- package/node_modules/@comis/web/dist/assets/ic-data-table-CKIvr-ag.js +277 -0
- package/node_modules/@comis/web/dist/assets/ic-delivery-row-B3YwjjuM.js +67 -0
- package/node_modules/@comis/web/dist/assets/{ic-detail-panel-BF83r-if.js → ic-detail-panel-DiCe4hLr.js} +27 -27
- package/node_modules/@comis/web/dist/assets/{ic-empty-state-60l2ePhd.js → ic-empty-state-CM3Wbj2f.js} +19 -19
- package/node_modules/@comis/web/dist/assets/ic-graph-canvas-ByRjij68.js +359 -0
- package/node_modules/@comis/web/dist/assets/ic-icon-BGNCCPpZ.js +33 -0
- package/node_modules/@comis/web/dist/assets/{ic-layer-waterfall-COvEYMg5.js → ic-layer-waterfall-WkaFyu-l.js} +18 -18
- package/node_modules/@comis/web/dist/assets/ic-relative-time-B3UAnTqg.js +12 -0
- package/node_modules/@comis/web/dist/assets/{ic-search-input-CSOxY9g7.js → ic-search-input-B02AGw1i.js} +22 -22
- package/node_modules/@comis/web/dist/assets/{ic-select-Ce-Raudx.js → ic-select-BqfZISjw.js} +29 -29
- package/node_modules/@comis/web/dist/assets/ic-tabs-yBjkWKJH.js +95 -0
- package/node_modules/@comis/web/dist/assets/ic-tag-CvMVQFRR.js +33 -0
- package/node_modules/@comis/web/dist/assets/{ic-time-range-picker-CypCT68y.js → ic-time-range-picker-DXbYeBmY.js} +31 -31
- package/node_modules/@comis/web/dist/assets/{ic-tool-call-7MaXSsCW.js → ic-tool-call-DMPHsLyx.js} +51 -51
- package/node_modules/@comis/web/dist/assets/index-CVEaS9aY.css +2 -0
- package/node_modules/@comis/web/dist/assets/index-FLPhHz8p.js +2792 -0
- package/node_modules/@comis/web/dist/assets/{mcp-management-BNZPnpDn.js → mcp-management-5jyScQis.js} +209 -209
- package/node_modules/@comis/web/dist/assets/{media-config-BBvTYxOX.js → media-config-J9oT9PPs.js} +154 -154
- package/node_modules/@comis/web/dist/assets/{media-test-BkK3RCRK.js → media-test-DGTCtM8-.js} +259 -259
- package/node_modules/@comis/web/dist/assets/{memory-inspector-1hDGCGat.js → memory-inspector-D5Re9ptG.js} +450 -450
- package/node_modules/@comis/web/dist/assets/{message-center-CXefwsUu.js → message-center-cRLK6ZmG.js} +290 -290
- package/node_modules/@comis/web/dist/assets/{models-C1qcU_j3.js → models-D5vu07MR.js} +371 -371
- package/node_modules/@comis/web/dist/assets/observability-types-D0tkwElU.js +1 -0
- package/node_modules/@comis/web/dist/assets/{observe-view-C0VBhX4C.js → observe-view-CalNNEmd.js} +399 -399
- package/node_modules/@comis/web/dist/assets/pipeline-builder-DUYDGwZf.js +1495 -0
- package/node_modules/@comis/web/dist/assets/{pipeline-history-DkfOQ6SW.js → pipeline-history-BAO8brOe.js} +124 -124
- package/node_modules/@comis/web/dist/assets/{pipeline-history-detail-hyHgD0ai.js → pipeline-history-detail-DectIoQt.js} +65 -65
- package/node_modules/@comis/web/dist/assets/{pipeline-list-BPW8hV-q.js → pipeline-list-BHlaBKww.js} +227 -227
- package/node_modules/@comis/web/dist/assets/{pipeline-monitor-Bip16T7e.js → pipeline-monitor-BhtpNEHf.js} +298 -298
- package/node_modules/@comis/web/dist/assets/{scheduler-BGgwKd06.js → scheduler-VafN_8xi.js} +486 -486
- package/node_modules/@comis/web/dist/assets/{security-D15st4xx.js → security-QQXMRTlo.js} +389 -389
- package/node_modules/@comis/web/dist/assets/{session-detail-SGEYNJ0M.js → session-detail-BpZ_8Yih.js} +294 -294
- package/node_modules/@comis/web/dist/assets/session-key-parser-Dkqcj2Ss.js +1 -0
- package/node_modules/@comis/web/dist/assets/session-list-DfCm8Cec.js +231 -0
- package/node_modules/@comis/web/dist/assets/{setup-wizard-nT0tz9QP.js → setup-wizard-C-z477CG.js} +486 -494
- package/node_modules/@comis/web/dist/assets/{skills-D8yVfSUy.js → skills-BCOGPf6s.js} +329 -329
- package/node_modules/@comis/web/dist/assets/{subagents-HHXMeHYo.js → subagents-l-auUraL.js} +74 -74
- package/node_modules/@comis/web/dist/assets/{workspace-manager-BQlr10iH.js → workspace-manager-DlvBixiq.js} +236 -236
- package/node_modules/@comis/web/dist/index.html +3 -2
- package/node_modules/@comis/web/package.json +1 -1
- package/package.json +15 -15
- package/node_modules/@comis/web/dist/assets/agent-editor-C26Q_xCs.js +0 -2173
- package/node_modules/@comis/web/dist/assets/billing-view-CtYvBqTE.js +0 -375
- package/node_modules/@comis/web/dist/assets/channel-list-B8dj3O9a.js +0 -323
- package/node_modules/@comis/web/dist/assets/directive-DoeGSK_T.js +0 -1
- package/node_modules/@comis/web/dist/assets/ic-chat-message-CFyDJd0z.js +0 -352
- package/node_modules/@comis/web/dist/assets/ic-data-table-CKUNTxHw.js +0 -277
- package/node_modules/@comis/web/dist/assets/ic-delivery-row-GP5Fkygs.js +0 -67
- package/node_modules/@comis/web/dist/assets/ic-graph-canvas-C8FuSMe1.js +0 -359
- package/node_modules/@comis/web/dist/assets/ic-icon-xeGTVhVG.js +0 -33
- package/node_modules/@comis/web/dist/assets/ic-relative-time-3FqpjeAI.js +0 -12
- package/node_modules/@comis/web/dist/assets/ic-tabs-B7QtM_v8.js +0 -95
- package/node_modules/@comis/web/dist/assets/ic-tag-CPPUnDLF.js +0 -33
- package/node_modules/@comis/web/dist/assets/index-CEcM1R_C.js +0 -2830
- package/node_modules/@comis/web/dist/assets/index-CIJFuItj.css +0 -1
- package/node_modules/@comis/web/dist/assets/observability-types-D7jUtSde.js +0 -1
- package/node_modules/@comis/web/dist/assets/pipeline-builder-DcUUIrm0.js +0 -1496
- package/node_modules/@comis/web/dist/assets/session-key-parser-DPORMVyU.js +0 -1
- package/node_modules/@comis/web/dist/assets/session-list-6ybUTxbY.js +0 -231
package/node_modules/@comis/web/dist/assets/{setup-wizard-nT0tz9QP.js → setup-wizard-C-z477CG.js}
RENAMED
|
@@ -1,510 +1,104 @@
|
|
|
1
|
-
import{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
`}).join("");if(typeof e=="object"){const r=Object.entries(e).filter(([,i])=>i!=null&&i!=="");return r.length===0?`{}
|
|
9
|
-
`:r.map(([i,l])=>{if(typeof l=="object"&&!Array.isArray(l)){const o=h(l,a+1);return`${t}${i}:
|
|
10
|
-
${o}`}if(Array.isArray(l)){const o=h(l,a+1);return`${t}${i}:
|
|
11
|
-
${o}`}return`${t}${i}: ${h(l,0)}
|
|
12
|
-
`}).join("")}return String(e)}function P(){const e={};for(const a of g)e[a.key]={enabled:!1,credentials:{}};return{tenantId:"default",dataDir:"~/.comis",logLevel:"info",gatewayHost:"127.0.0.1",gatewayPort:4766,providerName:"",providerType:"",apiKey:"",baseUrl:"",defaultModel:"",agentId:"default",agentName:"Comis",agentModel:"",agentProvider:"",maxSteps:50,budgetPerDay:1e8,budgetPerHour:1e7,channels:e}}let d=class extends _{constructor(){super(...arguments),this.rpcClient=null,this._currentStep=0,this._wizardData=P(),this._testResult={status:"idle"},this._expandedChannels=new Set,this._yamlPreview="",this._applying=!1,this._applyStatus="",this._applyDone=!1,this._validationErrors={}}_validateStep(e){const a={};switch(e){case 0:this._wizardData.tenantId.trim()||(a.tenantId="Tenant ID is required");break;case 1:{this._wizardData.providerType||(a.providerType="Please select a provider");const t=f.find(r=>r.key===this._wizardData.providerName);t?.needsApiKey&&!this._wizardData.apiKey.trim()&&(a.apiKey="API key is required for this provider"),t?.needsBaseUrl&&!this._wizardData.baseUrl.trim()&&(a.baseUrl="Base URL is required for this provider");break}case 2:this._wizardData.agentId.trim()||(a.agentId="Agent ID is required");break}return this._validationErrors=a,Object.keys(a).length===0}_goNext(){this._validateStep(this._currentStep)&&(this._currentStep===3&&this._generateYaml(),this._currentStep===1&&(this._wizardData.agentModel||(this._wizardData={...this._wizardData,agentModel:this._wizardData.defaultModel,agentProvider:this._wizardData.providerName})),this._currentStep=Math.min(this._currentStep+1,b.length-1),this._validationErrors={})}_goBack(){this._currentStep=Math.max(this._currentStep-1,0),this._validationErrors={}}_selectProvider(e){this._wizardData={...this._wizardData,providerName:e.key,providerType:e.type,baseUrl:e.defaultBaseUrl,defaultModel:e.defaultModel},this._testResult={status:"idle"},this._validationErrors={}}async _testConnection(){if(this.rpcClient){this._testResult={status:"testing"};try{await this.rpcClient.call("models.test",{provider:this._wizardData.providerType}),this._testResult={status:"success",message:"Connected"}}catch(e){const a=e instanceof Error?e.message:"Connection failed";this._testResult={status:"error",message:a}}}}_toggleChannel(e){const a=this._wizardData.channels[e],t={...this._wizardData.channels,[e]:{...a,enabled:!a.enabled}};if(this._wizardData={...this._wizardData,channels:t},!a.enabled){const r=new Set(this._expandedChannels);r.add(e),this._expandedChannels=r}}_toggleExpand(e){const a=new Set(this._expandedChannels);a.has(e)?a.delete(e):a.add(e),this._expandedChannels=a}_updateChannelCredential(e,a,t){const r=this._wizardData.channels[e],i={...r.credentials,[a]:t},l={...this._wizardData.channels,[e]:{...r,credentials:i}};this._wizardData={...this._wizardData,channels:l}}_generateYaml(){const e=this._wizardData,a={};if(e.tenantId&&e.tenantId!=="default"&&(a.tenantId=e.tenantId),a.logLevel=e.logLevel,a.dataDir=e.dataDir,a.gateway={enabled:!0,host:e.gatewayHost,port:e.gatewayPort},e.providerName){const i={};e.apiKey&&(i.apiKeyName="env:"+e.providerName.toUpperCase()+"_API_KEY"),e.baseUrl&&(i.baseUrl=e.baseUrl),a.providers={[e.providerName]:i},e.defaultModel&&(a.models={defaultProvider:e.providerName,defaultModel:e.defaultModel})}const t={name:e.agentName,model:e.agentModel||e.defaultModel,provider:e.agentProvider||e.providerName,maxSteps:e.maxSteps,budgets:{perExecution:2e6,perHour:e.budgetPerHour,perDay:e.budgetPerDay}};a.agents={[e.agentId]:t};const r={};for(const[i,l]of Object.entries(e.channels)){if(!l.enabled)continue;const o={enabled:!0};for(const[u,v]of Object.entries(l.credentials))v&&(u==="allowedChatIds"?o.allowFrom=v.split(",").map(y=>y.trim()).filter(Boolean):o[u]=v);r[i]=o}Object.keys(r).length>0&&(a.channels=r),this._yamlPreview=h(a)}async _copyYaml(){try{await navigator.clipboard.writeText(this._yamlPreview),m.show("Copied to clipboard","success")}catch{m.show("Failed to copy","error")}}_downloadYaml(){const e=new Blob([this._yamlPreview],{type:"text/yaml"}),a=URL.createObjectURL(e),t=document.createElement("a");t.href=a,t.download="comis-config.yaml",t.click(),URL.revokeObjectURL(a)}async _applyConfig(){if(!this.rpcClient||this._applying)return;this._applying=!0,this._applyDone=!1;const e=this._wizardData,a=[];e.providerName&&e.defaultModel&&a.push({label:"models",section:"models",value:{defaultProvider:e.providerName,defaultModel:e.defaultModel}});const t=[];t.push("agents"),t.push("gateway"),e.providerName&&t.push("providers"),Object.values(e.channels).some(l=>l.enabled)&&t.push("channels");let i=0;for(const l of a){this._applyStatus=`Applying ${l.label}...`;try{await this.rpcClient.call("config.apply",{section:l.section,value:l.value}),i++}catch(o){const u=o instanceof Error?o.message:"Failed to apply configuration";m.show(`${l.label}: ${u}`,"error")}}this._applying=!1,this._applyStatus="",this._applyDone=!0,t.length>0?m.show(`Applied ${i} section(s). ${t.join(", ")} require saving the config file and restarting the daemon. Use Copy or Download to get the full config.`,"info"):m.show("Configuration applied! Restart the daemon to activate.","success")}_goToDashboard(){this.dispatchEvent(new CustomEvent("navigate",{detail:"dashboard",bubbles:!0,composed:!0}))}_renderStep1(){const e=this._wizardData,a=this._validationErrors;return s`
|
|
13
|
-
<div class="form-container">
|
|
14
|
-
<div class="form-field">
|
|
15
|
-
<label class="form-label">Tenant ID</label>
|
|
16
|
-
<input
|
|
17
|
-
class="form-input"
|
|
18
|
-
type="text"
|
|
19
|
-
.value=${e.tenantId}
|
|
20
|
-
@input=${t=>{this._wizardData={...this._wizardData,tenantId:t.target.value}}}
|
|
21
|
-
/>
|
|
22
|
-
<span class="form-hint">Unique identifier for this installation</span>
|
|
23
|
-
${a.tenantId?s`<span class="form-error">${a.tenantId}</span>`:n}
|
|
24
|
-
</div>
|
|
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}from"./index-FLPhHz8p.js";import"./ic-icon-BGNCCPpZ.js";var d=[{label:`Basics`,icon:`settings`},{label:`Provider`,icon:`server`},{label:`Agent`,icon:`agent`},{label:`Channels`,icon:`channel`},{label:`Review`,icon:`check`}],f=[{key:`anthropic`,type:`anthropic`,name:`Anthropic`,description:`Claude models, recommended for agents`,needsApiKey:!0,needsBaseUrl:!1,defaultBaseUrl:``,defaultModel:`claude-sonnet-4-5-20250929`},{key:`openai`,type:`openai`,name:`OpenAI`,description:`GPT-4o, o1, o3 models`,needsApiKey:!0,needsBaseUrl:!1,defaultBaseUrl:``,defaultModel:`gpt-4o`},{key:`google`,type:`google`,name:`Google`,description:`Gemini models`,needsApiKey:!0,needsBaseUrl:!1,defaultBaseUrl:``,defaultModel:`gemini-2.0-flash`},{key:`groq`,type:`groq`,name:`Groq`,description:`Fast inference (Llama, Mixtral)`,needsApiKey:!0,needsBaseUrl:!1,defaultBaseUrl:``,defaultModel:`llama-3.3-70b-versatile`},{key:`mistral`,type:`mistral`,name:`Mistral`,description:`Mistral models`,needsApiKey:!0,needsBaseUrl:!1,defaultBaseUrl:``,defaultModel:`mistral-large-latest`},{key:`deepseek`,type:`deepseek`,name:`DeepSeek`,description:`DeepSeek models`,needsApiKey:!0,needsBaseUrl:!1,defaultBaseUrl:``,defaultModel:`deepseek-chat`},{key:`xai`,type:`xai`,name:`xAI`,description:`Grok models`,needsApiKey:!0,needsBaseUrl:!1,defaultBaseUrl:``,defaultModel:`grok-2`},{key:`together`,type:`together`,name:`Together AI`,description:`Open-source model hosting`,needsApiKey:!0,needsBaseUrl:!1,defaultBaseUrl:``,defaultModel:`meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo`},{key:`cerebras`,type:`cerebras`,name:`Cerebras`,description:`Fast inference`,needsApiKey:!0,needsBaseUrl:!1,defaultBaseUrl:``,defaultModel:`llama-3.3-70b`},{key:`openrouter`,type:`openrouter`,name:`OpenRouter`,description:`Multi-provider routing`,needsApiKey:!0,needsBaseUrl:!1,defaultBaseUrl:``,defaultModel:`anthropic/claude-sonnet-4-5-20250929`},{key:`ollama`,type:`ollama`,name:`Ollama`,description:`Local open-source models, no API key needed`,needsApiKey:!1,needsBaseUrl:!0,defaultBaseUrl:`http://localhost:11434`,defaultModel:`llama3`},{key:`custom`,type:`openai`,name:`Custom`,description:`Any OpenAI-compatible API endpoint`,needsApiKey:!1,needsBaseUrl:!0,defaultBaseUrl:``,defaultModel:``}],p=[{key:`telegram`,label:`Telegram`,fields:[{key:`botToken`,label:`Bot Token`,type:`password`},{key:`allowedChatIds`,label:`Allowed Chat IDs`,type:`text`,placeholder:`Comma-separated IDs`}]},{key:`discord`,label:`Discord`,fields:[{key:`botToken`,label:`Bot Token`,type:`password`},{key:`guildIds`,label:`Guild IDs`,type:`text`,placeholder:`Comma-separated IDs`}]},{key:`slack`,label:`Slack`,fields:[{key:`botToken`,label:`Bot Token`,type:`password`},{key:`appToken`,label:`App Token`,type:`password`},{key:`signingSecret`,label:`Signing Secret`,type:`password`}]},{key:`whatsapp`,label:`WhatsApp`,fields:[{key:`phoneNumberId`,label:`Phone Number ID`,type:`text`},{key:`accessToken`,label:`Access Token`,type:`password`},{key:`verifyToken`,label:`Verify Token`,type:`text`}]},{key:`line`,label:`LINE`,fields:[{key:`channelAccessToken`,label:`Channel Access Token`,type:`password`},{key:`channelSecret`,label:`Channel Secret`,type:`password`}]},{key:`signal`,label:`Signal`,fields:[{key:`phone`,label:`Phone Number`,type:`text`},{key:`signalCliPath`,label:`Signal CLI Path`,type:`text`}]},{key:`irc`,label:`IRC`,fields:[{key:`server`,label:`Server`,type:`text`},{key:`port`,label:`Port`,type:`number`,defaultValue:`6667`},{key:`nick`,label:`Nickname`,type:`text`},{key:`channels`,label:`Channels`,type:`text`,placeholder:`Comma-separated, e.g. #general,#dev`}]},{key:`imessage`,label:`iMessage`,fields:[{key:`applescriptPath`,label:`AppleScript Path`,type:`text`,placeholder:`Requires macOS with Messages app`}]}],m=[`trace`,`debug`,`info`,`warn`,`error`];function h(e,t=0){let n=` `.repeat(t);if(e==null)return`${n}~\n`;if(typeof e==`string`)return e===``||/[:#[\]{},&*!|>'"@`]/.test(e)||/^\s|\s$/.test(e)?`"${e.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`)}"`:e;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(Array.isArray(e))return e.length===0?`[]
|
|
2
|
+
`:e.map(e=>{if(typeof e==`object`&&e){let r=h(e,t+1),i=r.split(`
|
|
3
|
+
`).filter(Boolean);if(i.length>0){let e=` `.repeat(t+1);return`${n}- ${i[0].substring(e.length)}\n${i.slice(1).map(t=>`${n} ${t.substring(e.length)}\n`).join(``)}`}return`${n}- ${r.trim()}\n`}return`${n}- ${h(e,0)}\n`}).join(``);if(typeof e==`object`){let r=Object.entries(e).filter(([,e])=>e!=null&&e!==``);return r.length===0?`{}
|
|
4
|
+
`:r.map(([e,r])=>typeof r==`object`&&!Array.isArray(r)||Array.isArray(r)?`${n}${e}:\n${h(r,t+1)}`:`${n}${e}: ${h(r,0)}\n`).join(``)}return String(e)}function g(){let e={};for(let t of p)e[t.key]={enabled:!1,credentials:{}};return{tenantId:`default`,dataDir:`~/.comis`,logLevel:`info`,gatewayHost:`127.0.0.1`,gatewayPort:4766,providerName:``,providerType:``,apiKey:``,baseUrl:``,defaultModel:``,agentId:`default`,agentName:`Comis`,agentModel:``,agentProvider:``,maxSteps:50,budgetPerDay:1e8,budgetPerHour:1e7,channels:e}}var _=class extends r{constructor(...e){super(...e),this.rpcClient=null,this._currentStep=0,this._wizardData=g(),this._testResult={status:`idle`},this._expandedChannels=new Set,this._yamlPreview=``,this._applying=!1,this._applyStatus=``,this._applyDone=!1,this._validationErrors={}}static{this.styles=[o,i,n`
|
|
5
|
+
:host {
|
|
6
|
+
display: block;
|
|
7
|
+
}
|
|
25
8
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class="form-input"
|
|
30
|
-
type="text"
|
|
31
|
-
.value=${e.dataDir}
|
|
32
|
-
@input=${t=>{this._wizardData={...this._wizardData,dataDir:t.target.value}}}
|
|
33
|
-
/>
|
|
34
|
-
<span class="form-hint">Where Comis stores databases and logs</span>
|
|
35
|
-
</div>
|
|
9
|
+
.wizard-header {
|
|
10
|
+
margin-bottom: var(--ic-space-lg);
|
|
11
|
+
}
|
|
36
12
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
13
|
+
.wizard-title {
|
|
14
|
+
font-size: 1.125rem;
|
|
15
|
+
font-weight: 600;
|
|
16
|
+
}
|
|
41
17
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
.value=${e.gatewayHost}
|
|
48
|
-
@input=${t=>{this._wizardData={...this._wizardData,gatewayHost:t.target.value}}}
|
|
49
|
-
/>
|
|
50
|
-
</div>
|
|
18
|
+
.wizard-subtitle {
|
|
19
|
+
font-size: var(--ic-text-sm);
|
|
20
|
+
color: var(--ic-text-muted);
|
|
21
|
+
margin-top: var(--ic-space-xs);
|
|
22
|
+
}
|
|
51
23
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
@input=${t=>{this._wizardData={...this._wizardData,gatewayPort:Number(t.target.value)||4766}}}
|
|
61
|
-
/>
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
`}_renderLogLevelSelect(){return s`
|
|
65
|
-
<select
|
|
66
|
-
class="form-select"
|
|
67
|
-
@change=${e=>{this._wizardData={...this._wizardData,logLevel:e.target.value}}}
|
|
68
|
-
>
|
|
69
|
-
${S.map(e=>s`<option value=${e} ?selected=${e===this._wizardData.logLevel}>${e}</option>`)}
|
|
70
|
-
</select>
|
|
71
|
-
`}_renderStep2(){const e=this._wizardData,a=this._validationErrors,t=f.find(r=>r.key===e.providerName);return s`
|
|
72
|
-
<div class="provider-grid">
|
|
73
|
-
${f.map(r=>s`
|
|
74
|
-
<div
|
|
75
|
-
class="provider-card ${e.providerName===r.key?"active":""}"
|
|
76
|
-
role="button"
|
|
77
|
-
tabindex="0"
|
|
78
|
-
aria-pressed=${e.providerName===r.key?"true":"false"}
|
|
79
|
-
@click=${()=>this._selectProvider(r)}
|
|
80
|
-
@keydown=${i=>{(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),this._selectProvider(r))}}
|
|
81
|
-
>
|
|
82
|
-
<div class="provider-card-name">${r.name}</div>
|
|
83
|
-
<div class="provider-card-desc">${r.description}</div>
|
|
84
|
-
</div>
|
|
85
|
-
`)}
|
|
86
|
-
</div>
|
|
87
|
-
${a.providerType?s`<span class="form-error">${a.providerType}</span>`:n}
|
|
24
|
+
/* Step progress bar */
|
|
25
|
+
.step-bar {
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: flex-start;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
gap: 0;
|
|
30
|
+
margin-bottom: var(--ic-space-xl, 2rem);
|
|
31
|
+
}
|
|
88
32
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<input
|
|
96
|
-
class="form-input"
|
|
97
|
-
type="password"
|
|
98
|
-
.value=${a.apiKey}
|
|
99
|
-
placeholder="Enter your API key"
|
|
100
|
-
@input=${r=>{this._wizardData={...this._wizardData,apiKey:r.target.value}}}
|
|
101
|
-
/>
|
|
102
|
-
${t.apiKey?s`<span class="form-error">${t.apiKey}</span>`:n}
|
|
103
|
-
</div>
|
|
104
|
-
`:n}
|
|
33
|
+
.step-item {
|
|
34
|
+
display: flex;
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
align-items: center;
|
|
37
|
+
min-width: 80px;
|
|
38
|
+
}
|
|
105
39
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
40
|
+
.step-circle {
|
|
41
|
+
width: 32px;
|
|
42
|
+
height: 32px;
|
|
43
|
+
border-radius: 50%;
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
font-size: var(--ic-text-sm);
|
|
48
|
+
font-weight: 600;
|
|
49
|
+
border: 2px solid var(--ic-border);
|
|
50
|
+
background: var(--ic-surface-2);
|
|
51
|
+
color: var(--ic-text-dim);
|
|
52
|
+
position: relative;
|
|
53
|
+
}
|
|
119
54
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
.value=${a.defaultModel}
|
|
126
|
-
placeholder=${e.defaultModel||"Model ID"}
|
|
127
|
-
@input=${r=>{this._wizardData={...this._wizardData,defaultModel:r.target.value}}}
|
|
128
|
-
/>
|
|
129
|
-
</div>
|
|
55
|
+
.step-circle.completed {
|
|
56
|
+
background: var(--ic-accent);
|
|
57
|
+
border-color: var(--ic-accent);
|
|
58
|
+
color: white;
|
|
59
|
+
}
|
|
130
60
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
>
|
|
137
|
-
${this._testResult.status==="testing"?"Testing...":"Test Connection"}
|
|
138
|
-
</button>
|
|
139
|
-
${this._testResult.status==="success"?s`<span class="test-success">Connected</span>`:n}
|
|
140
|
-
${this._testResult.status==="error"?s`<span class="test-error">${this._testResult.message}</span>`:n}
|
|
141
|
-
${this._testResult.status==="testing"?s`<span class="test-spinner">Connecting...</span>`:n}
|
|
142
|
-
</div>
|
|
143
|
-
</div>
|
|
144
|
-
`}_renderStep3(){const e=this._wizardData,a=this._validationErrors;return s`
|
|
145
|
-
<div class="form-container">
|
|
146
|
-
<div class="info-box">
|
|
147
|
-
The agent will use the provider configured in Step 2. You can add more agents later from the Agents view.
|
|
148
|
-
</div>
|
|
61
|
+
.step-circle.current {
|
|
62
|
+
border-color: var(--ic-accent);
|
|
63
|
+
color: var(--ic-accent);
|
|
64
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--ic-accent) 25%, transparent);
|
|
65
|
+
}
|
|
149
66
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
@input=${t=>{this._wizardData={...this._wizardData,agentId:t.target.value}}}
|
|
157
|
-
/>
|
|
158
|
-
<span class="form-hint">Unique identifier (letters, numbers, hyphens)</span>
|
|
159
|
-
${a.agentId?s`<span class="form-error">${a.agentId}</span>`:n}
|
|
160
|
-
</div>
|
|
67
|
+
.step-label {
|
|
68
|
+
font-size: var(--ic-text-xs);
|
|
69
|
+
margin-top: var(--ic-space-xs);
|
|
70
|
+
color: var(--ic-text-dim);
|
|
71
|
+
text-align: center;
|
|
72
|
+
}
|
|
161
73
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
type="text"
|
|
167
|
-
.value=${e.agentName}
|
|
168
|
-
@input=${t=>{this._wizardData={...this._wizardData,agentName:t.target.value}}}
|
|
169
|
-
/>
|
|
170
|
-
<span class="form-hint">Display name for the agent</span>
|
|
171
|
-
</div>
|
|
74
|
+
.step-label.current {
|
|
75
|
+
color: var(--ic-text);
|
|
76
|
+
font-weight: 500;
|
|
77
|
+
}
|
|
172
78
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
class="form-input"
|
|
177
|
-
type="text"
|
|
178
|
-
.value=${e.agentModel}
|
|
179
|
-
@input=${t=>{this._wizardData={...this._wizardData,agentModel:t.target.value}}}
|
|
180
|
-
/>
|
|
181
|
-
<span class="form-hint">LLM model ID to use</span>
|
|
182
|
-
</div>
|
|
79
|
+
.step-label.completed {
|
|
80
|
+
color: var(--ic-text-muted);
|
|
81
|
+
}
|
|
183
82
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
</div>
|
|
83
|
+
.step-line {
|
|
84
|
+
flex: 1;
|
|
85
|
+
height: 2px;
|
|
86
|
+
background: var(--ic-border);
|
|
87
|
+
margin-top: 16px;
|
|
88
|
+
min-width: 40px;
|
|
89
|
+
max-width: 80px;
|
|
90
|
+
}
|
|
193
91
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
class="form-input"
|
|
198
|
-
type="number"
|
|
199
|
-
min="1"
|
|
200
|
-
max="100"
|
|
201
|
-
.value=${String(e.maxSteps)}
|
|
202
|
-
@input=${t=>{this._wizardData={...this._wizardData,maxSteps:Number(t.target.value)||25}}}
|
|
203
|
-
/>
|
|
204
|
-
</div>
|
|
92
|
+
.step-line.completed {
|
|
93
|
+
background: var(--ic-accent);
|
|
94
|
+
}
|
|
205
95
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
step="0.01"
|
|
213
|
-
.value=${String(e.budgetPerDay)}
|
|
214
|
-
@input=${t=>{this._wizardData={...this._wizardData,budgetPerDay:Number(t.target.value)||0}}}
|
|
215
|
-
/>
|
|
216
|
-
</div>
|
|
217
|
-
|
|
218
|
-
<div class="form-field">
|
|
219
|
-
<label class="form-label">Budget Per Hour (tokens)</label>
|
|
220
|
-
<input
|
|
221
|
-
class="form-input"
|
|
222
|
-
type="number"
|
|
223
|
-
min="0"
|
|
224
|
-
step="0.01"
|
|
225
|
-
.value=${String(e.budgetPerHour)}
|
|
226
|
-
@input=${t=>{this._wizardData={...this._wizardData,budgetPerHour:Number(t.target.value)||0}}}
|
|
227
|
-
/>
|
|
228
|
-
</div>
|
|
229
|
-
</div>
|
|
230
|
-
`}_renderStep4(){return s`
|
|
231
|
-
<div class="info-box">
|
|
232
|
-
Enable the channels you want to connect. You can configure more channels later.
|
|
233
|
-
</div>
|
|
234
|
-
<div class="channel-cards">
|
|
235
|
-
${g.map(e=>this._renderChannelCard(e))}
|
|
236
|
-
</div>
|
|
237
|
-
`}_renderChannelCard(e){const a=this._wizardData.channels[e.key],t=this._expandedChannels.has(e.key);return s`
|
|
238
|
-
<div class="channel-card">
|
|
239
|
-
<div
|
|
240
|
-
class="channel-header"
|
|
241
|
-
@click=${()=>this._toggleExpand(e.key)}
|
|
242
|
-
>
|
|
243
|
-
<ic-platform-icon platform=${e.key} size="20px"></ic-platform-icon>
|
|
244
|
-
<span class="channel-name">${e.label}</span>
|
|
245
|
-
<button
|
|
246
|
-
class="channel-toggle ${a.enabled?"enabled":""}"
|
|
247
|
-
aria-label="${a.enabled?"Disable":"Enable"} ${e.label}"
|
|
248
|
-
@click=${r=>{r.stopPropagation(),this._toggleChannel(e.key)}}
|
|
249
|
-
></button>
|
|
250
|
-
<span class="channel-expand ${t?"open":""}">▼</span>
|
|
251
|
-
</div>
|
|
252
|
-
${t?s`
|
|
253
|
-
<div class="channel-body">
|
|
254
|
-
${this._renderChannelFields(e)}
|
|
255
|
-
</div>
|
|
256
|
-
`:n}
|
|
257
|
-
</div>
|
|
258
|
-
`}_renderChannelFields(e){switch(e.key){case"telegram":return this._renderTelegramFields();case"discord":return this._renderDiscordFields();case"slack":return this._renderSlackFields();case"whatsapp":return this._renderWhatsappFields();case"line":return this._renderLineFields();case"signal":return this._renderSignalFields();case"irc":return this._renderIrcFields();case"imessage":return this._renderImessageFields();default:return n}}_renderTelegramFields(){const e=this._wizardData.channels.telegram.credentials;return s`
|
|
259
|
-
<div class="form-field">
|
|
260
|
-
<label class="form-label">Bot Token</label>
|
|
261
|
-
<input class="form-input" type="password" .value=${e.botToken??""}
|
|
262
|
-
@input=${a=>this._updateChannelCredential("telegram","botToken",a.target.value)} />
|
|
263
|
-
</div>
|
|
264
|
-
<div class="form-field">
|
|
265
|
-
<label class="form-label">Allowed Chat IDs</label>
|
|
266
|
-
<input class="form-input" type="text" placeholder="Comma-separated IDs" .value=${e.allowedChatIds??""}
|
|
267
|
-
@input=${a=>this._updateChannelCredential("telegram","allowedChatIds",a.target.value)} />
|
|
268
|
-
</div>
|
|
269
|
-
`}_renderDiscordFields(){const e=this._wizardData.channels.discord.credentials;return s`
|
|
270
|
-
<div class="form-field">
|
|
271
|
-
<label class="form-label">Bot Token</label>
|
|
272
|
-
<input class="form-input" type="password" .value=${e.botToken??""}
|
|
273
|
-
@input=${a=>this._updateChannelCredential("discord","botToken",a.target.value)} />
|
|
274
|
-
</div>
|
|
275
|
-
<div class="form-field">
|
|
276
|
-
<label class="form-label">Guild IDs</label>
|
|
277
|
-
<input class="form-input" type="text" placeholder="Comma-separated IDs" .value=${e.guildIds??""}
|
|
278
|
-
@input=${a=>this._updateChannelCredential("discord","guildIds",a.target.value)} />
|
|
279
|
-
</div>
|
|
280
|
-
`}_renderSlackFields(){const e=this._wizardData.channels.slack.credentials;return s`
|
|
281
|
-
<div class="form-field">
|
|
282
|
-
<label class="form-label">Bot Token</label>
|
|
283
|
-
<input class="form-input" type="password" .value=${e.botToken??""}
|
|
284
|
-
@input=${a=>this._updateChannelCredential("slack","botToken",a.target.value)} />
|
|
285
|
-
</div>
|
|
286
|
-
<div class="form-field">
|
|
287
|
-
<label class="form-label">App Token</label>
|
|
288
|
-
<input class="form-input" type="password" .value=${e.appToken??""}
|
|
289
|
-
@input=${a=>this._updateChannelCredential("slack","appToken",a.target.value)} />
|
|
290
|
-
</div>
|
|
291
|
-
<div class="form-field">
|
|
292
|
-
<label class="form-label">Signing Secret</label>
|
|
293
|
-
<input class="form-input" type="password" .value=${e.signingSecret??""}
|
|
294
|
-
@input=${a=>this._updateChannelCredential("slack","signingSecret",a.target.value)} />
|
|
295
|
-
</div>
|
|
296
|
-
`}_renderWhatsappFields(){const e=this._wizardData.channels.whatsapp.credentials;return s`
|
|
297
|
-
<div class="form-field">
|
|
298
|
-
<label class="form-label">Phone Number ID</label>
|
|
299
|
-
<input class="form-input" type="text" .value=${e.phoneNumberId??""}
|
|
300
|
-
@input=${a=>this._updateChannelCredential("whatsapp","phoneNumberId",a.target.value)} />
|
|
301
|
-
</div>
|
|
302
|
-
<div class="form-field">
|
|
303
|
-
<label class="form-label">Access Token</label>
|
|
304
|
-
<input class="form-input" type="password" .value=${e.accessToken??""}
|
|
305
|
-
@input=${a=>this._updateChannelCredential("whatsapp","accessToken",a.target.value)} />
|
|
306
|
-
</div>
|
|
307
|
-
<div class="form-field">
|
|
308
|
-
<label class="form-label">Verify Token</label>
|
|
309
|
-
<input class="form-input" type="text" .value=${e.verifyToken??""}
|
|
310
|
-
@input=${a=>this._updateChannelCredential("whatsapp","verifyToken",a.target.value)} />
|
|
311
|
-
</div>
|
|
312
|
-
`}_renderLineFields(){const e=this._wizardData.channels.line.credentials;return s`
|
|
313
|
-
<div class="form-field">
|
|
314
|
-
<label class="form-label">Channel Access Token</label>
|
|
315
|
-
<input class="form-input" type="password" .value=${e.channelAccessToken??""}
|
|
316
|
-
@input=${a=>this._updateChannelCredential("line","channelAccessToken",a.target.value)} />
|
|
317
|
-
</div>
|
|
318
|
-
<div class="form-field">
|
|
319
|
-
<label class="form-label">Channel Secret</label>
|
|
320
|
-
<input class="form-input" type="password" .value=${e.channelSecret??""}
|
|
321
|
-
@input=${a=>this._updateChannelCredential("line","channelSecret",a.target.value)} />
|
|
322
|
-
</div>
|
|
323
|
-
`}_renderSignalFields(){const e=this._wizardData.channels.signal.credentials;return s`
|
|
324
|
-
<div class="form-field">
|
|
325
|
-
<label class="form-label">Phone Number</label>
|
|
326
|
-
<input class="form-input" type="text" .value=${e.phone??""}
|
|
327
|
-
@input=${a=>this._updateChannelCredential("signal","phone",a.target.value)} />
|
|
328
|
-
</div>
|
|
329
|
-
<div class="form-field">
|
|
330
|
-
<label class="form-label">Signal CLI Path</label>
|
|
331
|
-
<input class="form-input" type="text" .value=${e.signalCliPath??""}
|
|
332
|
-
@input=${a=>this._updateChannelCredential("signal","signalCliPath",a.target.value)} />
|
|
333
|
-
</div>
|
|
334
|
-
`}_renderIrcFields(){const e=this._wizardData.channels.irc.credentials;return s`
|
|
335
|
-
<div class="form-field">
|
|
336
|
-
<label class="form-label">Server</label>
|
|
337
|
-
<input class="form-input" type="text" .value=${e.server??""}
|
|
338
|
-
@input=${a=>this._updateChannelCredential("irc","server",a.target.value)} />
|
|
339
|
-
</div>
|
|
340
|
-
<div class="form-field">
|
|
341
|
-
<label class="form-label">Port</label>
|
|
342
|
-
<input class="form-input" type="number" .value=${e.port??"6667"}
|
|
343
|
-
@input=${a=>this._updateChannelCredential("irc","port",a.target.value)} />
|
|
344
|
-
</div>
|
|
345
|
-
<div class="form-field">
|
|
346
|
-
<label class="form-label">Nickname</label>
|
|
347
|
-
<input class="form-input" type="text" .value=${e.nick??""}
|
|
348
|
-
@input=${a=>this._updateChannelCredential("irc","nick",a.target.value)} />
|
|
349
|
-
</div>
|
|
350
|
-
<div class="form-field">
|
|
351
|
-
<label class="form-label">Channels</label>
|
|
352
|
-
<input class="form-input" type="text" placeholder="Comma-separated, e.g. #general,#dev" .value=${e.channels??""}
|
|
353
|
-
@input=${a=>this._updateChannelCredential("irc","channels",a.target.value)} />
|
|
354
|
-
</div>
|
|
355
|
-
`}_renderImessageFields(){const e=this._wizardData.channels.imessage.credentials;return s`
|
|
356
|
-
<div class="form-field">
|
|
357
|
-
<label class="form-label">AppleScript Path</label>
|
|
358
|
-
<input class="form-input" type="text" placeholder="Requires macOS with Messages app" .value=${e.applescriptPath??""}
|
|
359
|
-
@input=${a=>this._updateChannelCredential("imessage","applescriptPath",a.target.value)} />
|
|
360
|
-
</div>
|
|
361
|
-
`}_renderStep5(){return s`
|
|
362
|
-
<div class="yaml-preview">${this._yamlPreview}</div>
|
|
363
|
-
<div class="review-actions">
|
|
364
|
-
<button class="btn btn-secondary" @click=${()=>this._copyYaml()}>Copy</button>
|
|
365
|
-
<button class="btn btn-secondary" @click=${()=>this._downloadYaml()}>Download</button>
|
|
366
|
-
<button class="btn btn-primary" ?disabled=${this._applying} @click=${()=>this._applyConfig()}>
|
|
367
|
-
${this._applying?"Applying...":"Apply"}
|
|
368
|
-
</button>
|
|
369
|
-
</div>
|
|
370
|
-
${this._applyStatus?s`<div class="apply-status">${this._applyStatus}</div>`:n}
|
|
371
|
-
${this._applyDone?s`
|
|
372
|
-
<div class="dashboard-link">
|
|
373
|
-
<a @click=${e=>{e.preventDefault(),this._goToDashboard()}}>Go to Dashboard</a>
|
|
374
|
-
</div>
|
|
375
|
-
`:n}
|
|
376
|
-
`}_renderStepBar(){return s`
|
|
377
|
-
<div class="step-bar" role="navigation" aria-label="Setup wizard progress">
|
|
378
|
-
${b.map((e,a)=>{const t=a<this._currentStep,r=a===this._currentStep,i=t?"completed":r?"current":"",l=t?"completed":r?"current":"";return s`
|
|
379
|
-
${a>0?s`<div class="step-line ${a<=this._currentStep?"completed":""}"></div>`:n}
|
|
380
|
-
<div class="step-item">
|
|
381
|
-
<div class="step-circle ${i}" aria-label="Step ${a+1}: ${e.label}">
|
|
382
|
-
${t?s`✓`:s`${a+1}`}
|
|
383
|
-
</div>
|
|
384
|
-
<span class="step-label ${l}">${e.label}</span>
|
|
385
|
-
</div>
|
|
386
|
-
`})}
|
|
387
|
-
</div>
|
|
388
|
-
`}render(){return s`
|
|
389
|
-
<div class="wizard-header">
|
|
390
|
-
<div class="wizard-title">Setup Wizard</div>
|
|
391
|
-
<div class="wizard-subtitle">Configure your Comis installation step by step</div>
|
|
392
|
-
</div>
|
|
393
|
-
|
|
394
|
-
${this._renderStepBar()}
|
|
395
|
-
|
|
396
|
-
<div class="step-content">
|
|
397
|
-
${this._currentStep===0?this._renderStep1():n}
|
|
398
|
-
${this._currentStep===1?this._renderStep2():n}
|
|
399
|
-
${this._currentStep===2?this._renderStep3():n}
|
|
400
|
-
${this._currentStep===3?this._renderStep4():n}
|
|
401
|
-
${this._currentStep===4?this._renderStep5():n}
|
|
402
|
-
</div>
|
|
403
|
-
|
|
404
|
-
<div class="nav-bar">
|
|
405
|
-
${this._currentStep>0?s`<button class="btn btn-secondary" @click=${()=>this._goBack()}>Back</button>`:s`<div class="nav-spacer"></div>`}
|
|
406
|
-
${this._currentStep<4?s`<button class="btn btn-primary" @click=${()=>this._goNext()}>
|
|
407
|
-
${this._currentStep===3?"Review":"Next"}
|
|
408
|
-
</button>`:s`<div class="nav-spacer"></div>`}
|
|
409
|
-
</div>
|
|
410
|
-
`}};d.styles=[w,x,$`
|
|
411
|
-
:host {
|
|
412
|
-
display: block;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
.wizard-header {
|
|
416
|
-
margin-bottom: var(--ic-space-lg);
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
.wizard-title {
|
|
420
|
-
font-size: 1.125rem;
|
|
421
|
-
font-weight: 600;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
.wizard-subtitle {
|
|
425
|
-
font-size: var(--ic-text-sm);
|
|
426
|
-
color: var(--ic-text-muted);
|
|
427
|
-
margin-top: var(--ic-space-xs);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
/* Step progress bar */
|
|
431
|
-
.step-bar {
|
|
432
|
-
display: flex;
|
|
433
|
-
align-items: flex-start;
|
|
434
|
-
justify-content: center;
|
|
435
|
-
gap: 0;
|
|
436
|
-
margin-bottom: var(--ic-space-xl, 2rem);
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
.step-item {
|
|
440
|
-
display: flex;
|
|
441
|
-
flex-direction: column;
|
|
442
|
-
align-items: center;
|
|
443
|
-
min-width: 80px;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
.step-circle {
|
|
447
|
-
width: 32px;
|
|
448
|
-
height: 32px;
|
|
449
|
-
border-radius: 50%;
|
|
450
|
-
display: flex;
|
|
451
|
-
align-items: center;
|
|
452
|
-
justify-content: center;
|
|
453
|
-
font-size: var(--ic-text-sm);
|
|
454
|
-
font-weight: 600;
|
|
455
|
-
border: 2px solid var(--ic-border);
|
|
456
|
-
background: var(--ic-surface-2);
|
|
457
|
-
color: var(--ic-text-dim);
|
|
458
|
-
position: relative;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
.step-circle.completed {
|
|
462
|
-
background: var(--ic-accent);
|
|
463
|
-
border-color: var(--ic-accent);
|
|
464
|
-
color: white;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
.step-circle.current {
|
|
468
|
-
border-color: var(--ic-accent);
|
|
469
|
-
color: var(--ic-accent);
|
|
470
|
-
box-shadow: 0 0 0 3px color-mix(in srgb, var(--ic-accent) 25%, transparent);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
.step-label {
|
|
474
|
-
font-size: var(--ic-text-xs);
|
|
475
|
-
margin-top: var(--ic-space-xs);
|
|
476
|
-
color: var(--ic-text-dim);
|
|
477
|
-
text-align: center;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
.step-label.current {
|
|
481
|
-
color: var(--ic-text);
|
|
482
|
-
font-weight: 500;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
.step-label.completed {
|
|
486
|
-
color: var(--ic-text-muted);
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
.step-line {
|
|
490
|
-
flex: 1;
|
|
491
|
-
height: 2px;
|
|
492
|
-
background: var(--ic-border);
|
|
493
|
-
margin-top: 16px;
|
|
494
|
-
min-width: 40px;
|
|
495
|
-
max-width: 80px;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
.step-line.completed {
|
|
499
|
-
background: var(--ic-accent);
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
/* Step content area */
|
|
503
|
-
.step-content {
|
|
504
|
-
max-width: 640px;
|
|
505
|
-
margin: 0 auto;
|
|
506
|
-
min-height: 300px;
|
|
507
|
-
}
|
|
96
|
+
/* Step content area */
|
|
97
|
+
.step-content {
|
|
98
|
+
max-width: 640px;
|
|
99
|
+
margin: 0 auto;
|
|
100
|
+
min-height: 300px;
|
|
101
|
+
}
|
|
508
102
|
|
|
509
103
|
/* Form styling */
|
|
510
104
|
.form-container {
|
|
@@ -850,4 +444,402 @@ ${o}`}return`${t}${i}: ${h(l,0)}
|
|
|
850
444
|
.nav-spacer {
|
|
851
445
|
flex: 1;
|
|
852
446
|
}
|
|
853
|
-
`];
|
|
447
|
+
`]}_validateStep(e){let t={};switch(e){case 0:this._wizardData.tenantId.trim()||(t.tenantId=`Tenant ID is required`);break;case 1:{this._wizardData.providerType||(t.providerType=`Please select a provider`);let e=f.find(e=>e.key===this._wizardData.providerName);e?.needsApiKey&&!this._wizardData.apiKey.trim()&&(t.apiKey=`API key is required for this provider`),e?.needsBaseUrl&&!this._wizardData.baseUrl.trim()&&(t.baseUrl=`Base URL is required for this provider`);break}case 2:this._wizardData.agentId.trim()||(t.agentId=`Agent ID is required`);break;case 3:break}return this._validationErrors=t,Object.keys(t).length===0}_goNext(){this._validateStep(this._currentStep)&&(this._currentStep===3&&this._generateYaml(),this._currentStep===1&&(this._wizardData.agentModel||(this._wizardData={...this._wizardData,agentModel:this._wizardData.defaultModel,agentProvider:this._wizardData.providerName})),this._currentStep=Math.min(this._currentStep+1,d.length-1),this._validationErrors={})}_goBack(){this._currentStep=Math.max(this._currentStep-1,0),this._validationErrors={}}_selectProvider(e){this._wizardData={...this._wizardData,providerName:e.key,providerType:e.type,baseUrl:e.defaultBaseUrl,defaultModel:e.defaultModel},this._testResult={status:`idle`},this._validationErrors={}}async _testConnection(){if(this.rpcClient){this._testResult={status:`testing`};try{await this.rpcClient.call(`models.test`,{provider:this._wizardData.providerType}),this._testResult={status:`success`,message:`Connected`}}catch(e){let t=e instanceof Error?e.message:`Connection failed`;this._testResult={status:`error`,message:t}}}}_toggleChannel(e){let t=this._wizardData.channels[e],n={...this._wizardData.channels,[e]:{...t,enabled:!t.enabled}};if(this._wizardData={...this._wizardData,channels:n},!t.enabled){let t=new Set(this._expandedChannels);t.add(e),this._expandedChannels=t}}_toggleExpand(e){let t=new Set(this._expandedChannels);t.has(e)?t.delete(e):t.add(e),this._expandedChannels=t}_updateChannelCredential(e,t,n){let r=this._wizardData.channels[e],i={...r.credentials,[t]:n},a={...this._wizardData.channels,[e]:{...r,credentials:i}};this._wizardData={...this._wizardData,channels:a}}_generateYaml(){let e=this._wizardData,t={};if(e.tenantId&&e.tenantId!==`default`&&(t.tenantId=e.tenantId),t.logLevel=e.logLevel,t.dataDir=e.dataDir,t.gateway={enabled:!0,host:e.gatewayHost,port:e.gatewayPort},e.providerName){let n={};e.apiKey&&(n.apiKeyName=`env:`+e.providerName.toUpperCase()+`_API_KEY`),e.baseUrl&&(n.baseUrl=e.baseUrl),t.providers={[e.providerName]:n},e.defaultModel&&(t.models={defaultProvider:e.providerName,defaultModel:e.defaultModel})}let n={name:e.agentName,model:e.agentModel||e.defaultModel,provider:e.agentProvider||e.providerName,maxSteps:e.maxSteps,budgets:{perExecution:2e6,perHour:e.budgetPerHour,perDay:e.budgetPerDay}};t.agents={[e.agentId]:n};let r={};for(let[t,n]of Object.entries(e.channels)){if(!n.enabled)continue;let e={enabled:!0};for(let[t,r]of Object.entries(n.credentials))r&&(t===`allowedChatIds`?e.allowFrom=r.split(`,`).map(e=>e.trim()).filter(Boolean):e[t]=r);r[t]=e}Object.keys(r).length>0&&(t.channels=r),this._yamlPreview=h(t)}async _copyYaml(){try{await navigator.clipboard.writeText(this._yamlPreview),u.show(`Copied to clipboard`,`success`)}catch{u.show(`Failed to copy`,`error`)}}_downloadYaml(){let e=new Blob([this._yamlPreview],{type:`text/yaml`}),t=URL.createObjectURL(e),n=document.createElement(`a`);n.href=t,n.download=`comis-config.yaml`,n.click(),URL.revokeObjectURL(t)}async _applyConfig(){if(!this.rpcClient||this._applying)return;this._applying=!0,this._applyDone=!1;let e=this._wizardData,t=[];e.providerName&&e.defaultModel&&t.push({label:`models`,section:`models`,value:{defaultProvider:e.providerName,defaultModel:e.defaultModel}});let n=[];n.push(`agents`),n.push(`gateway`),e.providerName&&n.push(`providers`),Object.values(e.channels).some(e=>e.enabled)&&n.push(`channels`);let r=0;for(let e of t){this._applyStatus=`Applying ${e.label}...`;try{await this.rpcClient.call(`config.apply`,{section:e.section,value:e.value}),r++}catch(t){let n=t instanceof Error?t.message:`Failed to apply configuration`;u.show(`${e.label}: ${n}`,`error`)}}this._applying=!1,this._applyStatus=``,this._applyDone=!0,n.length>0?u.show(`Applied ${r} section(s). ${n.join(`, `)} require saving the config file and restarting the daemon. Use Copy or Download to get the full config.`,`info`):u.show(`Configuration applied! Restart the daemon to activate.`,`success`)}_goToDashboard(){this.dispatchEvent(new CustomEvent(`navigate`,{detail:`dashboard`,bubbles:!0,composed:!0}))}_renderStep1(){let e=this._wizardData,n=this._validationErrors;return t`
|
|
448
|
+
<div class="form-container">
|
|
449
|
+
<div class="form-field">
|
|
450
|
+
<label class="form-label">Tenant ID</label>
|
|
451
|
+
<input
|
|
452
|
+
class="form-input"
|
|
453
|
+
type="text"
|
|
454
|
+
.value=${e.tenantId}
|
|
455
|
+
@input=${e=>{this._wizardData={...this._wizardData,tenantId:e.target.value}}}
|
|
456
|
+
/>
|
|
457
|
+
<span class="form-hint">Unique identifier for this installation</span>
|
|
458
|
+
${n.tenantId?t`<span class="form-error">${n.tenantId}</span>`:l}
|
|
459
|
+
</div>
|
|
460
|
+
|
|
461
|
+
<div class="form-field">
|
|
462
|
+
<label class="form-label">Data Directory</label>
|
|
463
|
+
<input
|
|
464
|
+
class="form-input"
|
|
465
|
+
type="text"
|
|
466
|
+
.value=${e.dataDir}
|
|
467
|
+
@input=${e=>{this._wizardData={...this._wizardData,dataDir:e.target.value}}}
|
|
468
|
+
/>
|
|
469
|
+
<span class="form-hint">Where Comis stores databases and logs</span>
|
|
470
|
+
</div>
|
|
471
|
+
|
|
472
|
+
<div class="form-field">
|
|
473
|
+
<label class="form-label">Log Level</label>
|
|
474
|
+
${this._renderLogLevelSelect()}
|
|
475
|
+
</div>
|
|
476
|
+
|
|
477
|
+
<div class="form-field">
|
|
478
|
+
<label class="form-label">Gateway Host</label>
|
|
479
|
+
<input
|
|
480
|
+
class="form-input"
|
|
481
|
+
type="text"
|
|
482
|
+
.value=${e.gatewayHost}
|
|
483
|
+
@input=${e=>{this._wizardData={...this._wizardData,gatewayHost:e.target.value}}}
|
|
484
|
+
/>
|
|
485
|
+
</div>
|
|
486
|
+
|
|
487
|
+
<div class="form-field">
|
|
488
|
+
<label class="form-label">Gateway Port</label>
|
|
489
|
+
<input
|
|
490
|
+
class="form-input"
|
|
491
|
+
type="number"
|
|
492
|
+
min="1"
|
|
493
|
+
max="65535"
|
|
494
|
+
.value=${String(e.gatewayPort)}
|
|
495
|
+
@input=${e=>{this._wizardData={...this._wizardData,gatewayPort:Number(e.target.value)||4766}}}
|
|
496
|
+
/>
|
|
497
|
+
</div>
|
|
498
|
+
</div>
|
|
499
|
+
`}_renderLogLevelSelect(){return t`
|
|
500
|
+
<select
|
|
501
|
+
class="form-select"
|
|
502
|
+
@change=${e=>{this._wizardData={...this._wizardData,logLevel:e.target.value}}}
|
|
503
|
+
>
|
|
504
|
+
${m.map(e=>t`<option value=${e} ?selected=${e===this._wizardData.logLevel}>${e}</option>`)}
|
|
505
|
+
</select>
|
|
506
|
+
`}_renderStep2(){let e=this._wizardData,n=this._validationErrors,r=f.find(t=>t.key===e.providerName);return t`
|
|
507
|
+
<div class="provider-grid">
|
|
508
|
+
${f.map(n=>t`
|
|
509
|
+
<div
|
|
510
|
+
class="provider-card ${e.providerName===n.key?`active`:``}"
|
|
511
|
+
role="button"
|
|
512
|
+
tabindex="0"
|
|
513
|
+
aria-pressed=${e.providerName===n.key?`true`:`false`}
|
|
514
|
+
@click=${()=>this._selectProvider(n)}
|
|
515
|
+
@keydown=${e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),this._selectProvider(n))}}
|
|
516
|
+
>
|
|
517
|
+
<div class="provider-card-name">${n.name}</div>
|
|
518
|
+
<div class="provider-card-desc">${n.description}</div>
|
|
519
|
+
</div>
|
|
520
|
+
`)}
|
|
521
|
+
</div>
|
|
522
|
+
${n.providerType?t`<span class="form-error">${n.providerType}</span>`:l}
|
|
523
|
+
|
|
524
|
+
${r?this._renderProviderConfig(r):l}
|
|
525
|
+
`}_renderProviderConfig(e){let n=this._wizardData,r=this._validationErrors;return t`
|
|
526
|
+
<div class="provider-config">
|
|
527
|
+
${e.needsApiKey?t`
|
|
528
|
+
<div class="form-field">
|
|
529
|
+
<label class="form-label">API Key</label>
|
|
530
|
+
<input
|
|
531
|
+
class="form-input"
|
|
532
|
+
type="password"
|
|
533
|
+
.value=${n.apiKey}
|
|
534
|
+
placeholder="Enter your API key"
|
|
535
|
+
@input=${e=>{this._wizardData={...this._wizardData,apiKey:e.target.value}}}
|
|
536
|
+
/>
|
|
537
|
+
${r.apiKey?t`<span class="form-error">${r.apiKey}</span>`:l}
|
|
538
|
+
</div>
|
|
539
|
+
`:l}
|
|
540
|
+
|
|
541
|
+
${e.needsBaseUrl?t`
|
|
542
|
+
<div class="form-field">
|
|
543
|
+
<label class="form-label">Base URL</label>
|
|
544
|
+
<input
|
|
545
|
+
class="form-input"
|
|
546
|
+
type="text"
|
|
547
|
+
.value=${n.baseUrl}
|
|
548
|
+
placeholder=${e.defaultBaseUrl||`https://api.example.com`}
|
|
549
|
+
@input=${e=>{this._wizardData={...this._wizardData,baseUrl:e.target.value}}}
|
|
550
|
+
/>
|
|
551
|
+
${r.baseUrl?t`<span class="form-error">${r.baseUrl}</span>`:l}
|
|
552
|
+
</div>
|
|
553
|
+
`:l}
|
|
554
|
+
|
|
555
|
+
<div class="form-field">
|
|
556
|
+
<label class="form-label">Default Model</label>
|
|
557
|
+
<input
|
|
558
|
+
class="form-input"
|
|
559
|
+
type="text"
|
|
560
|
+
.value=${n.defaultModel}
|
|
561
|
+
placeholder=${e.defaultModel||`Model ID`}
|
|
562
|
+
@input=${e=>{this._wizardData={...this._wizardData,defaultModel:e.target.value}}}
|
|
563
|
+
/>
|
|
564
|
+
</div>
|
|
565
|
+
|
|
566
|
+
<div class="test-row">
|
|
567
|
+
<button
|
|
568
|
+
class="test-btn"
|
|
569
|
+
?disabled=${this._testResult.status===`testing`}
|
|
570
|
+
@click=${()=>this._testConnection()}
|
|
571
|
+
>
|
|
572
|
+
${this._testResult.status===`testing`?`Testing...`:`Test Connection`}
|
|
573
|
+
</button>
|
|
574
|
+
${this._testResult.status===`success`?t`<span class="test-success">Connected</span>`:l}
|
|
575
|
+
${this._testResult.status===`error`?t`<span class="test-error">${this._testResult.message}</span>`:l}
|
|
576
|
+
${this._testResult.status===`testing`?t`<span class="test-spinner">Connecting...</span>`:l}
|
|
577
|
+
</div>
|
|
578
|
+
</div>
|
|
579
|
+
`}_renderStep3(){let e=this._wizardData,n=this._validationErrors;return t`
|
|
580
|
+
<div class="form-container">
|
|
581
|
+
<div class="info-box">
|
|
582
|
+
The agent will use the provider configured in Step 2. You can add more agents later from the Agents view.
|
|
583
|
+
</div>
|
|
584
|
+
|
|
585
|
+
<div class="form-field">
|
|
586
|
+
<label class="form-label">Agent ID</label>
|
|
587
|
+
<input
|
|
588
|
+
class="form-input"
|
|
589
|
+
type="text"
|
|
590
|
+
.value=${e.agentId}
|
|
591
|
+
@input=${e=>{this._wizardData={...this._wizardData,agentId:e.target.value}}}
|
|
592
|
+
/>
|
|
593
|
+
<span class="form-hint">Unique identifier (letters, numbers, hyphens)</span>
|
|
594
|
+
${n.agentId?t`<span class="form-error">${n.agentId}</span>`:l}
|
|
595
|
+
</div>
|
|
596
|
+
|
|
597
|
+
<div class="form-field">
|
|
598
|
+
<label class="form-label">Agent Name</label>
|
|
599
|
+
<input
|
|
600
|
+
class="form-input"
|
|
601
|
+
type="text"
|
|
602
|
+
.value=${e.agentName}
|
|
603
|
+
@input=${e=>{this._wizardData={...this._wizardData,agentName:e.target.value}}}
|
|
604
|
+
/>
|
|
605
|
+
<span class="form-hint">Display name for the agent</span>
|
|
606
|
+
</div>
|
|
607
|
+
|
|
608
|
+
<div class="form-field">
|
|
609
|
+
<label class="form-label">Model</label>
|
|
610
|
+
<input
|
|
611
|
+
class="form-input"
|
|
612
|
+
type="text"
|
|
613
|
+
.value=${e.agentModel}
|
|
614
|
+
@input=${e=>{this._wizardData={...this._wizardData,agentModel:e.target.value}}}
|
|
615
|
+
/>
|
|
616
|
+
<span class="form-hint">LLM model ID to use</span>
|
|
617
|
+
</div>
|
|
618
|
+
|
|
619
|
+
<div class="form-field">
|
|
620
|
+
<label class="form-label">Provider</label>
|
|
621
|
+
<input
|
|
622
|
+
class="form-input"
|
|
623
|
+
type="text"
|
|
624
|
+
.value=${e.agentProvider}
|
|
625
|
+
readonly
|
|
626
|
+
/>
|
|
627
|
+
</div>
|
|
628
|
+
|
|
629
|
+
<div class="form-field">
|
|
630
|
+
<label class="form-label">Max Steps</label>
|
|
631
|
+
<input
|
|
632
|
+
class="form-input"
|
|
633
|
+
type="number"
|
|
634
|
+
min="1"
|
|
635
|
+
max="100"
|
|
636
|
+
.value=${String(e.maxSteps)}
|
|
637
|
+
@input=${e=>{this._wizardData={...this._wizardData,maxSteps:Number(e.target.value)||25}}}
|
|
638
|
+
/>
|
|
639
|
+
</div>
|
|
640
|
+
|
|
641
|
+
<div class="form-field">
|
|
642
|
+
<label class="form-label">Budget Per Day (tokens)</label>
|
|
643
|
+
<input
|
|
644
|
+
class="form-input"
|
|
645
|
+
type="number"
|
|
646
|
+
min="0"
|
|
647
|
+
step="0.01"
|
|
648
|
+
.value=${String(e.budgetPerDay)}
|
|
649
|
+
@input=${e=>{this._wizardData={...this._wizardData,budgetPerDay:Number(e.target.value)||0}}}
|
|
650
|
+
/>
|
|
651
|
+
</div>
|
|
652
|
+
|
|
653
|
+
<div class="form-field">
|
|
654
|
+
<label class="form-label">Budget Per Hour (tokens)</label>
|
|
655
|
+
<input
|
|
656
|
+
class="form-input"
|
|
657
|
+
type="number"
|
|
658
|
+
min="0"
|
|
659
|
+
step="0.01"
|
|
660
|
+
.value=${String(e.budgetPerHour)}
|
|
661
|
+
@input=${e=>{this._wizardData={...this._wizardData,budgetPerHour:Number(e.target.value)||0}}}
|
|
662
|
+
/>
|
|
663
|
+
</div>
|
|
664
|
+
</div>
|
|
665
|
+
`}_renderStep4(){return t`
|
|
666
|
+
<div class="info-box">
|
|
667
|
+
Enable the channels you want to connect. You can configure more channels later.
|
|
668
|
+
</div>
|
|
669
|
+
<div class="channel-cards">
|
|
670
|
+
${p.map(e=>this._renderChannelCard(e))}
|
|
671
|
+
</div>
|
|
672
|
+
`}_renderChannelCard(e){let n=this._wizardData.channels[e.key],r=this._expandedChannels.has(e.key);return t`
|
|
673
|
+
<div class="channel-card">
|
|
674
|
+
<div
|
|
675
|
+
class="channel-header"
|
|
676
|
+
@click=${()=>this._toggleExpand(e.key)}
|
|
677
|
+
>
|
|
678
|
+
<ic-platform-icon platform=${e.key} size="20px"></ic-platform-icon>
|
|
679
|
+
<span class="channel-name">${e.label}</span>
|
|
680
|
+
<button
|
|
681
|
+
class="channel-toggle ${n.enabled?`enabled`:``}"
|
|
682
|
+
aria-label="${n.enabled?`Disable`:`Enable`} ${e.label}"
|
|
683
|
+
@click=${t=>{t.stopPropagation(),this._toggleChannel(e.key)}}
|
|
684
|
+
></button>
|
|
685
|
+
<span class="channel-expand ${r?`open`:``}">▼</span>
|
|
686
|
+
</div>
|
|
687
|
+
${r?t`
|
|
688
|
+
<div class="channel-body">
|
|
689
|
+
${this._renderChannelFields(e)}
|
|
690
|
+
</div>
|
|
691
|
+
`:l}
|
|
692
|
+
</div>
|
|
693
|
+
`}_renderChannelFields(e){switch(e.key){case`telegram`:return this._renderTelegramFields();case`discord`:return this._renderDiscordFields();case`slack`:return this._renderSlackFields();case`whatsapp`:return this._renderWhatsappFields();case`line`:return this._renderLineFields();case`signal`:return this._renderSignalFields();case`irc`:return this._renderIrcFields();case`imessage`:return this._renderImessageFields();default:return l}}_renderTelegramFields(){let e=this._wizardData.channels.telegram.credentials;return t`
|
|
694
|
+
<div class="form-field">
|
|
695
|
+
<label class="form-label">Bot Token</label>
|
|
696
|
+
<input class="form-input" type="password" .value=${e.botToken??``}
|
|
697
|
+
@input=${e=>this._updateChannelCredential(`telegram`,`botToken`,e.target.value)} />
|
|
698
|
+
</div>
|
|
699
|
+
<div class="form-field">
|
|
700
|
+
<label class="form-label">Allowed Chat IDs</label>
|
|
701
|
+
<input class="form-input" type="text" placeholder="Comma-separated IDs" .value=${e.allowedChatIds??``}
|
|
702
|
+
@input=${e=>this._updateChannelCredential(`telegram`,`allowedChatIds`,e.target.value)} />
|
|
703
|
+
</div>
|
|
704
|
+
`}_renderDiscordFields(){let e=this._wizardData.channels.discord.credentials;return t`
|
|
705
|
+
<div class="form-field">
|
|
706
|
+
<label class="form-label">Bot Token</label>
|
|
707
|
+
<input class="form-input" type="password" .value=${e.botToken??``}
|
|
708
|
+
@input=${e=>this._updateChannelCredential(`discord`,`botToken`,e.target.value)} />
|
|
709
|
+
</div>
|
|
710
|
+
<div class="form-field">
|
|
711
|
+
<label class="form-label">Guild IDs</label>
|
|
712
|
+
<input class="form-input" type="text" placeholder="Comma-separated IDs" .value=${e.guildIds??``}
|
|
713
|
+
@input=${e=>this._updateChannelCredential(`discord`,`guildIds`,e.target.value)} />
|
|
714
|
+
</div>
|
|
715
|
+
`}_renderSlackFields(){let e=this._wizardData.channels.slack.credentials;return t`
|
|
716
|
+
<div class="form-field">
|
|
717
|
+
<label class="form-label">Bot Token</label>
|
|
718
|
+
<input class="form-input" type="password" .value=${e.botToken??``}
|
|
719
|
+
@input=${e=>this._updateChannelCredential(`slack`,`botToken`,e.target.value)} />
|
|
720
|
+
</div>
|
|
721
|
+
<div class="form-field">
|
|
722
|
+
<label class="form-label">App Token</label>
|
|
723
|
+
<input class="form-input" type="password" .value=${e.appToken??``}
|
|
724
|
+
@input=${e=>this._updateChannelCredential(`slack`,`appToken`,e.target.value)} />
|
|
725
|
+
</div>
|
|
726
|
+
<div class="form-field">
|
|
727
|
+
<label class="form-label">Signing Secret</label>
|
|
728
|
+
<input class="form-input" type="password" .value=${e.signingSecret??``}
|
|
729
|
+
@input=${e=>this._updateChannelCredential(`slack`,`signingSecret`,e.target.value)} />
|
|
730
|
+
</div>
|
|
731
|
+
`}_renderWhatsappFields(){let e=this._wizardData.channels.whatsapp.credentials;return t`
|
|
732
|
+
<div class="form-field">
|
|
733
|
+
<label class="form-label">Phone Number ID</label>
|
|
734
|
+
<input class="form-input" type="text" .value=${e.phoneNumberId??``}
|
|
735
|
+
@input=${e=>this._updateChannelCredential(`whatsapp`,`phoneNumberId`,e.target.value)} />
|
|
736
|
+
</div>
|
|
737
|
+
<div class="form-field">
|
|
738
|
+
<label class="form-label">Access Token</label>
|
|
739
|
+
<input class="form-input" type="password" .value=${e.accessToken??``}
|
|
740
|
+
@input=${e=>this._updateChannelCredential(`whatsapp`,`accessToken`,e.target.value)} />
|
|
741
|
+
</div>
|
|
742
|
+
<div class="form-field">
|
|
743
|
+
<label class="form-label">Verify Token</label>
|
|
744
|
+
<input class="form-input" type="text" .value=${e.verifyToken??``}
|
|
745
|
+
@input=${e=>this._updateChannelCredential(`whatsapp`,`verifyToken`,e.target.value)} />
|
|
746
|
+
</div>
|
|
747
|
+
`}_renderLineFields(){let e=this._wizardData.channels.line.credentials;return t`
|
|
748
|
+
<div class="form-field">
|
|
749
|
+
<label class="form-label">Channel Access Token</label>
|
|
750
|
+
<input class="form-input" type="password" .value=${e.channelAccessToken??``}
|
|
751
|
+
@input=${e=>this._updateChannelCredential(`line`,`channelAccessToken`,e.target.value)} />
|
|
752
|
+
</div>
|
|
753
|
+
<div class="form-field">
|
|
754
|
+
<label class="form-label">Channel Secret</label>
|
|
755
|
+
<input class="form-input" type="password" .value=${e.channelSecret??``}
|
|
756
|
+
@input=${e=>this._updateChannelCredential(`line`,`channelSecret`,e.target.value)} />
|
|
757
|
+
</div>
|
|
758
|
+
`}_renderSignalFields(){let e=this._wizardData.channels.signal.credentials;return t`
|
|
759
|
+
<div class="form-field">
|
|
760
|
+
<label class="form-label">Phone Number</label>
|
|
761
|
+
<input class="form-input" type="text" .value=${e.phone??``}
|
|
762
|
+
@input=${e=>this._updateChannelCredential(`signal`,`phone`,e.target.value)} />
|
|
763
|
+
</div>
|
|
764
|
+
<div class="form-field">
|
|
765
|
+
<label class="form-label">Signal CLI Path</label>
|
|
766
|
+
<input class="form-input" type="text" .value=${e.signalCliPath??``}
|
|
767
|
+
@input=${e=>this._updateChannelCredential(`signal`,`signalCliPath`,e.target.value)} />
|
|
768
|
+
</div>
|
|
769
|
+
`}_renderIrcFields(){let e=this._wizardData.channels.irc.credentials;return t`
|
|
770
|
+
<div class="form-field">
|
|
771
|
+
<label class="form-label">Server</label>
|
|
772
|
+
<input class="form-input" type="text" .value=${e.server??``}
|
|
773
|
+
@input=${e=>this._updateChannelCredential(`irc`,`server`,e.target.value)} />
|
|
774
|
+
</div>
|
|
775
|
+
<div class="form-field">
|
|
776
|
+
<label class="form-label">Port</label>
|
|
777
|
+
<input class="form-input" type="number" .value=${e.port??`6667`}
|
|
778
|
+
@input=${e=>this._updateChannelCredential(`irc`,`port`,e.target.value)} />
|
|
779
|
+
</div>
|
|
780
|
+
<div class="form-field">
|
|
781
|
+
<label class="form-label">Nickname</label>
|
|
782
|
+
<input class="form-input" type="text" .value=${e.nick??``}
|
|
783
|
+
@input=${e=>this._updateChannelCredential(`irc`,`nick`,e.target.value)} />
|
|
784
|
+
</div>
|
|
785
|
+
<div class="form-field">
|
|
786
|
+
<label class="form-label">Channels</label>
|
|
787
|
+
<input class="form-input" type="text" placeholder="Comma-separated, e.g. #general,#dev" .value=${e.channels??``}
|
|
788
|
+
@input=${e=>this._updateChannelCredential(`irc`,`channels`,e.target.value)} />
|
|
789
|
+
</div>
|
|
790
|
+
`}_renderImessageFields(){return t`
|
|
791
|
+
<div class="form-field">
|
|
792
|
+
<label class="form-label">AppleScript Path</label>
|
|
793
|
+
<input class="form-input" type="text" placeholder="Requires macOS with Messages app" .value=${this._wizardData.channels.imessage.credentials.applescriptPath??``}
|
|
794
|
+
@input=${e=>this._updateChannelCredential(`imessage`,`applescriptPath`,e.target.value)} />
|
|
795
|
+
</div>
|
|
796
|
+
`}_renderStep5(){return t`
|
|
797
|
+
<div class="yaml-preview">${this._yamlPreview}</div>
|
|
798
|
+
<div class="review-actions">
|
|
799
|
+
<button class="btn btn-secondary" @click=${()=>this._copyYaml()}>Copy</button>
|
|
800
|
+
<button class="btn btn-secondary" @click=${()=>this._downloadYaml()}>Download</button>
|
|
801
|
+
<button class="btn btn-primary" ?disabled=${this._applying} @click=${()=>this._applyConfig()}>
|
|
802
|
+
${this._applying?`Applying...`:`Apply`}
|
|
803
|
+
</button>
|
|
804
|
+
</div>
|
|
805
|
+
${this._applyStatus?t`<div class="apply-status">${this._applyStatus}</div>`:l}
|
|
806
|
+
${this._applyDone?t`
|
|
807
|
+
<div class="dashboard-link">
|
|
808
|
+
<a @click=${e=>{e.preventDefault(),this._goToDashboard()}}>Go to Dashboard</a>
|
|
809
|
+
</div>
|
|
810
|
+
`:l}
|
|
811
|
+
`}_renderStepBar(){return t`
|
|
812
|
+
<div class="step-bar" role="navigation" aria-label="Setup wizard progress">
|
|
813
|
+
${d.map((e,n)=>{let r=n<this._currentStep,i=n===this._currentStep,a=r?`completed`:i?`current`:``,o=r?`completed`:i?`current`:``;return t`
|
|
814
|
+
${n>0?t`<div class="step-line ${n<=this._currentStep?`completed`:``}"></div>`:l}
|
|
815
|
+
<div class="step-item">
|
|
816
|
+
<div class="step-circle ${a}" aria-label="Step ${n+1}: ${e.label}">
|
|
817
|
+
${r?t`✓`:t`${n+1}`}
|
|
818
|
+
</div>
|
|
819
|
+
<span class="step-label ${o}">${e.label}</span>
|
|
820
|
+
</div>
|
|
821
|
+
`})}
|
|
822
|
+
</div>
|
|
823
|
+
`}render(){return t`
|
|
824
|
+
<div class="wizard-header">
|
|
825
|
+
<div class="wizard-title">Setup Wizard</div>
|
|
826
|
+
<div class="wizard-subtitle">Configure your Comis installation step by step</div>
|
|
827
|
+
</div>
|
|
828
|
+
|
|
829
|
+
${this._renderStepBar()}
|
|
830
|
+
|
|
831
|
+
<div class="step-content">
|
|
832
|
+
${this._currentStep===0?this._renderStep1():l}
|
|
833
|
+
${this._currentStep===1?this._renderStep2():l}
|
|
834
|
+
${this._currentStep===2?this._renderStep3():l}
|
|
835
|
+
${this._currentStep===3?this._renderStep4():l}
|
|
836
|
+
${this._currentStep===4?this._renderStep5():l}
|
|
837
|
+
</div>
|
|
838
|
+
|
|
839
|
+
<div class="nav-bar">
|
|
840
|
+
${this._currentStep>0?t`<button class="btn btn-secondary" @click=${()=>this._goBack()}>Back</button>`:t`<div class="nav-spacer"></div>`}
|
|
841
|
+
${this._currentStep<4?t`<button class="btn btn-primary" @click=${()=>this._goNext()}>
|
|
842
|
+
${this._currentStep===3?`Review`:`Next`}
|
|
843
|
+
</button>`:t`<div class="nav-spacer"></div>`}
|
|
844
|
+
</div>
|
|
845
|
+
`}};c([s({attribute:!1})],_.prototype,`rpcClient`,void 0),c([a()],_.prototype,`_currentStep`,void 0),c([a()],_.prototype,`_wizardData`,void 0),c([a()],_.prototype,`_testResult`,void 0),c([a()],_.prototype,`_expandedChannels`,void 0),c([a()],_.prototype,`_yamlPreview`,void 0),c([a()],_.prototype,`_applying`,void 0),c([a()],_.prototype,`_applyStatus`,void 0),c([a()],_.prototype,`_applyDone`,void 0),c([a()],_.prototype,`_validationErrors`,void 0),_=c([e(`ic-setup-wizard`)],_);export{_ as IcSetupWizard};
|