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,510 +1,104 @@
1
- import{a as _,I as m,A as n,b as s,s as w,f as x,i as $,n as k,r as p,t as C}from"./index-CEcM1R_C.js";import"./ic-icon-xeGTVhVG.js";var D=Object.defineProperty,z=Object.getOwnPropertyDescriptor,c=(e,a,t,r)=>{for(var i=r>1?void 0:r?z(a,t):a,l=e.length-1,o;l>=0;l--)(o=e[l])&&(i=(r?o(a,t,i):o(i))||i);return r&&i&&D(a,t,i),i};const b=[{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:""}],g=[{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"}]}],S=["trace","debug","info","warn","error"];function h(e,a=0){const t=" ".repeat(a);if(e==null)return`${t}~
2
- `;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?`[]
3
- `:e.map(r=>{if(typeof r=="object"&&r!==null){const i=h(r,a+1),l=i.split(`
4
- `).filter(Boolean);if(l.length>0){const o=" ".repeat(a+1);return`${t}- ${l[0].substring(o.length)}
5
- ${l.slice(1).map(u=>`${t} ${u.substring(o.length)}
6
- `).join("")}`}return`${t}- ${i.trim()}
7
- `}return`${t}- ${h(r,0)}
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
- <div class="form-field">
27
- <label class="form-label">Data Directory</label>
28
- <input
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
- <div class="form-field">
38
- <label class="form-label">Log Level</label>
39
- ${this._renderLogLevelSelect()}
40
- </div>
13
+ .wizard-title {
14
+ font-size: 1.125rem;
15
+ font-weight: 600;
16
+ }
41
17
 
42
- <div class="form-field">
43
- <label class="form-label">Gateway Host</label>
44
- <input
45
- class="form-input"
46
- type="text"
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
- <div class="form-field">
53
- <label class="form-label">Gateway Port</label>
54
- <input
55
- class="form-input"
56
- type="number"
57
- min="1"
58
- max="65535"
59
- .value=${String(e.gatewayPort)}
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
- ${t?this._renderProviderConfig(t):n}
90
- `}_renderProviderConfig(e){const a=this._wizardData,t=this._validationErrors;return s`
91
- <div class="provider-config">
92
- ${e.needsApiKey?s`
93
- <div class="form-field">
94
- <label class="form-label">API Key</label>
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
- ${e.needsBaseUrl?s`
107
- <div class="form-field">
108
- <label class="form-label">Base URL</label>
109
- <input
110
- class="form-input"
111
- type="text"
112
- .value=${a.baseUrl}
113
- placeholder=${e.defaultBaseUrl||"https://api.example.com"}
114
- @input=${r=>{this._wizardData={...this._wizardData,baseUrl:r.target.value}}}
115
- />
116
- ${t.baseUrl?s`<span class="form-error">${t.baseUrl}</span>`:n}
117
- </div>
118
- `:n}
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
- <div class="form-field">
121
- <label class="form-label">Default Model</label>
122
- <input
123
- class="form-input"
124
- type="text"
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
- <div class="test-row">
132
- <button
133
- class="test-btn"
134
- ?disabled=${this._testResult.status==="testing"}
135
- @click=${()=>this._testConnection()}
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
- <div class="form-field">
151
- <label class="form-label">Agent ID</label>
152
- <input
153
- class="form-input"
154
- type="text"
155
- .value=${e.agentId}
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
- <div class="form-field">
163
- <label class="form-label">Agent Name</label>
164
- <input
165
- class="form-input"
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
- <div class="form-field">
174
- <label class="form-label">Model</label>
175
- <input
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
- <div class="form-field">
185
- <label class="form-label">Provider</label>
186
- <input
187
- class="form-input"
188
- type="text"
189
- .value=${e.agentProvider}
190
- readonly
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
- <div class="form-field">
195
- <label class="form-label">Max Steps</label>
196
- <input
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
- <div class="form-field">
207
- <label class="form-label">Budget Per Day (tokens)</label>
208
- <input
209
- class="form-input"
210
- type="number"
211
- min="0"
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":""}">&#9660;</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`&#10003;`: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
- `];c([k({attribute:!1})],d.prototype,"rpcClient",2);c([p()],d.prototype,"_currentStep",2);c([p()],d.prototype,"_wizardData",2);c([p()],d.prototype,"_testResult",2);c([p()],d.prototype,"_expandedChannels",2);c([p()],d.prototype,"_yamlPreview",2);c([p()],d.prototype,"_applying",2);c([p()],d.prototype,"_applyStatus",2);c([p()],d.prototype,"_applyDone",2);c([p()],d.prototype,"_validationErrors",2);d=c([C("ic-setup-wizard")],d);export{d as IcSetupWizard};
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`:``}">&#9660;</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`&#10003;`: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};