comisai 1.0.24 → 1.0.26

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 (192) hide show
  1. package/node_modules/@comis/agent/dist/bootstrap/sections/tool-descriptions.js +130 -10
  2. package/node_modules/@comis/agent/dist/bootstrap/sections/tooling-sections.d.ts +1 -1
  3. package/node_modules/@comis/agent/dist/bootstrap/sections/tooling-sections.js +9 -2
  4. package/node_modules/@comis/agent/dist/bridge/bridge-metrics.d.ts +8 -0
  5. package/node_modules/@comis/agent/dist/bridge/bridge-metrics.js +2 -0
  6. package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.d.ts +29 -0
  7. package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.js +242 -2
  8. package/node_modules/@comis/agent/dist/bridge/thinking-block-hash-invariant.d.ts +210 -0
  9. package/node_modules/@comis/agent/dist/bridge/thinking-block-hash-invariant.js +566 -0
  10. package/node_modules/@comis/agent/dist/context-engine/context-engine.js +8 -6
  11. package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.d.ts +51 -30
  12. package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.js +109 -36
  13. package/node_modules/@comis/agent/dist/executor/executor-context-engine-setup.js +5 -1
  14. package/node_modules/@comis/agent/dist/executor/executor-post-execution.js +22 -20
  15. package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.d.ts +2 -0
  16. package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.js +111 -15
  17. package/node_modules/@comis/agent/dist/executor/executor-response-filter.d.ts +20 -17
  18. package/node_modules/@comis/agent/dist/executor/executor-response-filter.js +132 -52
  19. package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +16 -3
  20. package/node_modules/@comis/agent/dist/executor/model-retry.d.ts +14 -0
  21. package/node_modules/@comis/agent/dist/executor/model-retry.js +72 -1
  22. package/node_modules/@comis/agent/dist/executor/pi-executor.d.ts +3 -0
  23. package/node_modules/@comis/agent/dist/executor/pi-executor.js +68 -9
  24. package/node_modules/@comis/agent/dist/executor/post-batch-continuation.d.ts +82 -0
  25. package/node_modules/@comis/agent/dist/executor/post-batch-continuation.js +200 -0
  26. package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.js +1 -9
  27. package/node_modules/@comis/agent/dist/executor/tool-deferral.d.ts +37 -2
  28. package/node_modules/@comis/agent/dist/executor/tool-deferral.js +45 -3
  29. package/node_modules/@comis/agent/dist/executor/tool-parallelism.js +0 -1
  30. package/node_modules/@comis/agent/dist/executor/types.d.ts +11 -2
  31. package/node_modules/@comis/agent/dist/index.d.ts +3 -1
  32. package/node_modules/@comis/agent/dist/index.js +2 -0
  33. package/node_modules/@comis/agent/dist/model/last-known-model.d.ts +36 -0
  34. package/node_modules/@comis/agent/dist/model/last-known-model.js +49 -0
  35. package/node_modules/@comis/agent/dist/model/model-registry-adapter.d.ts +16 -4
  36. package/node_modules/@comis/agent/dist/model/model-registry-adapter.js +65 -21
  37. package/node_modules/@comis/agent/dist/planner/types.d.ts +0 -2
  38. package/node_modules/@comis/agent/dist/session/comis-session-manager.d.ts +10 -0
  39. package/node_modules/@comis/agent/dist/session/comis-session-manager.js +5 -0
  40. package/node_modules/@comis/agent/dist/spawn/pi-mono-adapters.js +7 -0
  41. package/node_modules/@comis/agent/package.json +1 -1
  42. package/node_modules/@comis/channels/package.json +1 -1
  43. package/node_modules/@comis/cli/dist/client/rpc-client.js +6 -1
  44. package/node_modules/@comis/cli/dist/commands/doctor.js +5 -3
  45. package/node_modules/@comis/cli/dist/commands/health.js +5 -2
  46. package/node_modules/@comis/cli/dist/wizard/json-output.js +7 -3
  47. package/node_modules/@comis/cli/dist/wizard/steps/11-daemon-start.js +130 -0
  48. package/node_modules/@comis/cli/package.json +1 -1
  49. package/node_modules/@comis/core/dist/bootstrap.js +5 -0
  50. package/node_modules/@comis/core/dist/config/env-layer.d.ts +31 -0
  51. package/node_modules/@comis/core/dist/config/env-layer.js +41 -0
  52. package/node_modules/@comis/core/dist/config/immutable-keys.d.ts +2 -2
  53. package/node_modules/@comis/core/dist/config/immutable-keys.js +8 -3
  54. package/node_modules/@comis/core/dist/config/layered.d.ts +9 -0
  55. package/node_modules/@comis/core/dist/config/layered.js +11 -0
  56. package/node_modules/@comis/core/dist/config/managed-sections.d.ts +43 -4
  57. package/node_modules/@comis/core/dist/config/managed-sections.js +100 -6
  58. package/node_modules/@comis/core/dist/config/schema-agent.d.ts +39 -0
  59. package/node_modules/@comis/core/dist/config/schema-agent.js +14 -0
  60. package/node_modules/@comis/core/dist/config/schema.d.ts +4 -0
  61. package/node_modules/@comis/core/dist/config/schema.js +14 -0
  62. package/node_modules/@comis/core/dist/domain/execution-graph.d.ts +1 -1
  63. package/node_modules/@comis/core/dist/event-bus/events-agent.d.ts +17 -2
  64. package/node_modules/@comis/core/dist/exports/config.d.ts +2 -2
  65. package/node_modules/@comis/core/dist/exports/config.js +1 -1
  66. package/node_modules/@comis/core/package.json +1 -1
  67. package/node_modules/@comis/daemon/dist/daemon.d.ts +22 -0
  68. package/node_modules/@comis/daemon/dist/daemon.js +45 -0
  69. package/node_modules/@comis/daemon/dist/rpc/agent-handlers.d.ts +5 -2
  70. package/node_modules/@comis/daemon/dist/rpc/agent-handlers.js +80 -1
  71. package/node_modules/@comis/daemon/dist/rpc/agent-inline-workspace.d.ts +67 -0
  72. package/node_modules/@comis/daemon/dist/rpc/agent-inline-workspace.js +139 -0
  73. package/node_modules/@comis/daemon/dist/rpc/model-handlers.d.ts +3 -0
  74. package/node_modules/@comis/daemon/dist/rpc/model-handlers.js +29 -5
  75. package/node_modules/@comis/daemon/dist/rpc/probe-provider-auth.d.ts +30 -0
  76. package/node_modules/@comis/daemon/dist/rpc/probe-provider-auth.js +59 -0
  77. package/node_modules/@comis/daemon/dist/rpc/provider-handlers.d.ts +37 -0
  78. package/node_modules/@comis/daemon/dist/rpc/provider-handlers.js +330 -0
  79. package/node_modules/@comis/daemon/dist/rpc/rpc-dispatch.js +18 -1
  80. package/node_modules/@comis/daemon/dist/setup-docker-restart-warn.d.ts +4 -0
  81. package/node_modules/@comis/daemon/dist/setup-docker-restart-warn.js +30 -0
  82. package/node_modules/@comis/daemon/dist/wiring/setup-agents.d.ts +3 -1
  83. package/node_modules/@comis/daemon/dist/wiring/setup-agents.js +28 -2
  84. package/node_modules/@comis/daemon/dist/wiring/setup-cross-session.js +1 -0
  85. package/node_modules/@comis/daemon/dist/wiring/setup-tools.js +7 -4
  86. package/node_modules/@comis/daemon/package.json +1 -1
  87. package/node_modules/@comis/gateway/package.json +1 -1
  88. package/node_modules/@comis/infra/dist/index.d.ts +1 -0
  89. package/node_modules/@comis/infra/dist/index.js +2 -0
  90. package/node_modules/@comis/infra/dist/runtime/is-docker.d.ts +1 -0
  91. package/node_modules/@comis/infra/dist/runtime/is-docker.js +25 -0
  92. package/node_modules/@comis/infra/package.json +1 -1
  93. package/node_modules/@comis/memory/package.json +1 -1
  94. package/node_modules/@comis/scheduler/package.json +1 -1
  95. package/node_modules/@comis/shared/package.json +1 -1
  96. package/node_modules/@comis/skills/dist/bridge/tool-metadata-registry.js +1 -3
  97. package/node_modules/@comis/skills/dist/builtin/platform/admin-manage-factory.js +24 -1
  98. package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.d.ts +53 -7
  99. package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.js +218 -24
  100. package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.d.ts +4 -1
  101. package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.js +16 -1
  102. package/node_modules/@comis/skills/dist/builtin/platform/index.d.ts +1 -1
  103. package/node_modules/@comis/skills/dist/builtin/platform/index.js +1 -1
  104. package/node_modules/@comis/skills/dist/builtin/platform/providers-manage-tool.d.ts +56 -0
  105. package/node_modules/@comis/skills/dist/builtin/platform/providers-manage-tool.js +203 -0
  106. package/node_modules/@comis/skills/dist/index.d.ts +1 -1
  107. package/node_modules/@comis/skills/dist/index.js +2 -2
  108. package/node_modules/@comis/skills/dist/policy/tool-policy.js +0 -1
  109. package/node_modules/@comis/skills/package.json +1 -1
  110. package/node_modules/@comis/web/dist/assets/{agent-detail-BG9MGWWj.js → agent-detail-DqL6Artv.js} +270 -270
  111. package/node_modules/@comis/web/dist/assets/agent-editor-CNM_h94Y.js +2173 -0
  112. package/node_modules/@comis/web/dist/assets/{agent-list-LHCJ4rw2.js → agent-list-Dbh-xD_F.js} +170 -170
  113. package/node_modules/@comis/web/dist/assets/{approvals-q9VH_IKr.js → approvals-C-K6hN2U.js} +13 -13
  114. package/node_modules/@comis/web/dist/assets/billing-view-C1DmtyzK.js +375 -0
  115. package/node_modules/@comis/web/dist/assets/{channel-detail-CaInesJM.js → channel-detail-CtCH22N1.js} +265 -265
  116. package/node_modules/@comis/web/dist/assets/channel-list-C7xXn-60.js +323 -0
  117. package/node_modules/@comis/web/dist/assets/{chat-console-CNmzl0JW.js → chat-console-C51pjFwk.js} +243 -246
  118. package/node_modules/@comis/web/dist/assets/{config-editor-DX4ITw6y.js → config-editor-BLArYRB7.js} +477 -477
  119. package/node_modules/@comis/web/dist/assets/{context-dag-browser-BwiaF5tf.js → context-dag-browser-fuyMinNI.js} +105 -105
  120. package/node_modules/@comis/web/dist/assets/{context-engine-BZ5Am6hA.js → context-engine-Bngf2bH0.js} +136 -136
  121. package/node_modules/@comis/web/dist/assets/decorate-BvWYovGE.js +38 -0
  122. package/node_modules/@comis/web/dist/assets/{delivery-view-OfBZof-m.js → delivery-view-C80hucxX.js} +134 -134
  123. package/node_modules/@comis/web/dist/assets/{diagnostics-view-YFwCxgr2.js → diagnostics-view-Cl4VbHZ6.js} +82 -82
  124. package/node_modules/@comis/web/dist/assets/directive-BOYXJ-K-.js +1 -0
  125. package/node_modules/@comis/web/dist/assets/{extract-variables-BM5qyK-s.js → extract-variables-B7-Doo7l.js} +39 -39
  126. package/node_modules/@comis/web/dist/assets/{ic-array-editor-B7m6x7-S.js → ic-array-editor-BLoEyeLS.js} +29 -29
  127. package/node_modules/@comis/web/dist/assets/{ic-breadcrumb-CUMpp3BL.js → ic-breadcrumb-DqN6G3gc.js} +16 -16
  128. package/node_modules/@comis/web/dist/assets/{ic-budget-segment-bar-BtJ6x5mN.js → ic-budget-segment-bar-zLsMzjDO.js} +20 -20
  129. package/node_modules/@comis/web/dist/assets/ic-chat-message-ByFUoMm6.js +352 -0
  130. package/node_modules/@comis/web/dist/assets/{ic-confirm-dialog-CCDbB04e.js → ic-confirm-dialog-DGlPbV1T.js} +26 -26
  131. package/node_modules/@comis/web/dist/assets/{ic-connection-dot-CnT1b8xr.js → ic-connection-dot-C4nDHgY2.js} +13 -13
  132. package/node_modules/@comis/web/dist/assets/ic-data-table-CKIvr-ag.js +277 -0
  133. package/node_modules/@comis/web/dist/assets/ic-delivery-row-B3YwjjuM.js +67 -0
  134. package/node_modules/@comis/web/dist/assets/{ic-detail-panel-BF83r-if.js → ic-detail-panel-DiCe4hLr.js} +27 -27
  135. package/node_modules/@comis/web/dist/assets/{ic-empty-state-60l2ePhd.js → ic-empty-state-CM3Wbj2f.js} +19 -19
  136. package/node_modules/@comis/web/dist/assets/ic-graph-canvas-ByRjij68.js +359 -0
  137. package/node_modules/@comis/web/dist/assets/ic-icon-BGNCCPpZ.js +33 -0
  138. package/node_modules/@comis/web/dist/assets/{ic-layer-waterfall-COvEYMg5.js → ic-layer-waterfall-WkaFyu-l.js} +18 -18
  139. package/node_modules/@comis/web/dist/assets/ic-relative-time-B3UAnTqg.js +12 -0
  140. package/node_modules/@comis/web/dist/assets/{ic-search-input-CSOxY9g7.js → ic-search-input-B02AGw1i.js} +22 -22
  141. package/node_modules/@comis/web/dist/assets/{ic-select-Ce-Raudx.js → ic-select-BqfZISjw.js} +29 -29
  142. package/node_modules/@comis/web/dist/assets/ic-tabs-yBjkWKJH.js +95 -0
  143. package/node_modules/@comis/web/dist/assets/ic-tag-CvMVQFRR.js +33 -0
  144. package/node_modules/@comis/web/dist/assets/{ic-time-range-picker-CypCT68y.js → ic-time-range-picker-DXbYeBmY.js} +31 -31
  145. package/node_modules/@comis/web/dist/assets/{ic-tool-call-7MaXSsCW.js → ic-tool-call-Bh5kq-yY.js} +51 -51
  146. package/node_modules/@comis/web/dist/assets/index-BBkuC-EU.js +2792 -0
  147. package/node_modules/@comis/web/dist/assets/index-CVEaS9aY.css +2 -0
  148. package/node_modules/@comis/web/dist/assets/{mcp-management-BNZPnpDn.js → mcp-management-DB-phOo7.js} +209 -209
  149. package/node_modules/@comis/web/dist/assets/{media-config-BBvTYxOX.js → media-config-CRqZ1ZUH.js} +154 -154
  150. package/node_modules/@comis/web/dist/assets/{media-test-BkK3RCRK.js → media-test-C9vE20Oy.js} +259 -259
  151. package/node_modules/@comis/web/dist/assets/{memory-inspector-1hDGCGat.js → memory-inspector-CeqfnxMZ.js} +450 -450
  152. package/node_modules/@comis/web/dist/assets/{message-center-CXefwsUu.js → message-center-Daup7Mof.js} +290 -290
  153. package/node_modules/@comis/web/dist/assets/{models-C1qcU_j3.js → models-DLYnEU8E.js} +371 -371
  154. package/node_modules/@comis/web/dist/assets/observability-types-D0tkwElU.js +1 -0
  155. package/node_modules/@comis/web/dist/assets/{observe-view-C0VBhX4C.js → observe-view-BTSt_PO5.js} +399 -399
  156. package/node_modules/@comis/web/dist/assets/pipeline-builder-DknfzyLt.js +1495 -0
  157. package/node_modules/@comis/web/dist/assets/{pipeline-history-DkfOQ6SW.js → pipeline-history-JnHZdeU_.js} +124 -124
  158. package/node_modules/@comis/web/dist/assets/{pipeline-history-detail-hyHgD0ai.js → pipeline-history-detail-Dg4knsEb.js} +65 -65
  159. package/node_modules/@comis/web/dist/assets/{pipeline-list-BPW8hV-q.js → pipeline-list-AEnibjsp.js} +227 -227
  160. package/node_modules/@comis/web/dist/assets/{pipeline-monitor-Bip16T7e.js → pipeline-monitor-DG7RbIOO.js} +298 -298
  161. package/node_modules/@comis/web/dist/assets/{scheduler-BGgwKd06.js → scheduler-uL1fYKAT.js} +486 -486
  162. package/node_modules/@comis/web/dist/assets/{security-D15st4xx.js → security-C3DywRLH.js} +389 -389
  163. package/node_modules/@comis/web/dist/assets/{session-detail-SGEYNJ0M.js → session-detail-BtqCNWXV.js} +294 -294
  164. package/node_modules/@comis/web/dist/assets/session-key-parser-Dkqcj2Ss.js +1 -0
  165. package/node_modules/@comis/web/dist/assets/session-list-CJXWa2XT.js +231 -0
  166. package/node_modules/@comis/web/dist/assets/{setup-wizard-nT0tz9QP.js → setup-wizard-ywn7oJvu.js} +486 -494
  167. package/node_modules/@comis/web/dist/assets/{skills-D8yVfSUy.js → skills-DX0KYnWD.js} +329 -329
  168. package/node_modules/@comis/web/dist/assets/{subagents-HHXMeHYo.js → subagents-B8p5YJEB.js} +74 -74
  169. package/node_modules/@comis/web/dist/assets/{workspace-manager-BQlr10iH.js → workspace-manager-CgzNIrw1.js} +236 -236
  170. package/node_modules/@comis/web/dist/index.html +3 -2
  171. package/node_modules/@comis/web/package.json +1 -1
  172. package/package.json +15 -15
  173. package/node_modules/@comis/skills/dist/builtin/platform/agents-list-tool.d.ts +0 -19
  174. package/node_modules/@comis/skills/dist/builtin/platform/agents-list-tool.js +0 -39
  175. package/node_modules/@comis/web/dist/assets/agent-editor-C26Q_xCs.js +0 -2173
  176. package/node_modules/@comis/web/dist/assets/billing-view-CtYvBqTE.js +0 -375
  177. package/node_modules/@comis/web/dist/assets/channel-list-B8dj3O9a.js +0 -323
  178. package/node_modules/@comis/web/dist/assets/directive-DoeGSK_T.js +0 -1
  179. package/node_modules/@comis/web/dist/assets/ic-chat-message-CFyDJd0z.js +0 -352
  180. package/node_modules/@comis/web/dist/assets/ic-data-table-CKUNTxHw.js +0 -277
  181. package/node_modules/@comis/web/dist/assets/ic-delivery-row-GP5Fkygs.js +0 -67
  182. package/node_modules/@comis/web/dist/assets/ic-graph-canvas-C8FuSMe1.js +0 -359
  183. package/node_modules/@comis/web/dist/assets/ic-icon-xeGTVhVG.js +0 -33
  184. package/node_modules/@comis/web/dist/assets/ic-relative-time-3FqpjeAI.js +0 -12
  185. package/node_modules/@comis/web/dist/assets/ic-tabs-B7QtM_v8.js +0 -95
  186. package/node_modules/@comis/web/dist/assets/ic-tag-CPPUnDLF.js +0 -33
  187. package/node_modules/@comis/web/dist/assets/index-CEcM1R_C.js +0 -2830
  188. package/node_modules/@comis/web/dist/assets/index-CIJFuItj.css +0 -1
  189. package/node_modules/@comis/web/dist/assets/observability-types-D7jUtSde.js +0 -1
  190. package/node_modules/@comis/web/dist/assets/pipeline-builder-DcUUIrm0.js +0 -1496
  191. package/node_modules/@comis/web/dist/assets/session-key-parser-DPORMVyU.js +0 -1
  192. package/node_modules/@comis/web/dist/assets/session-list-6ybUTxbY.js +0 -231
@@ -1,31 +1,6 @@
1
- import{s as N,f as P,i as I,n as x,r as p,a as j,b as o,t as M,A as g,I as y}from"./index-CEcM1R_C.js";import"./ic-empty-state-60l2ePhd.js";import"./ic-confirm-dialog-CCDbB04e.js";import"./ic-tag-CPPUnDLF.js";import"./ic-relative-time-3FqpjeAI.js";import"./ic-tabs-B7QtM_v8.js";import"./ic-select-Ce-Raudx.js";import"./ic-array-editor-B7m6x7-S.js";import"./ic-icon-xeGTVhVG.js";var V=Object.defineProperty,J=Object.getOwnPropertyDescriptor,S=(e,t,r,i)=>{for(var a=i>1?void 0:i?J(t,r):t,s=e.length-1,n;s>=0;s--)(n=e[s])&&(a=(i?n(t,r,a):n(a))||a);return i&&a&&V(t,r,a),a};function U(e,t){const r=e.split(`
2
- `),i=t.split(`
3
- `),a=r.length,s=i.length,n=Array.from({length:a+1},()=>new Array(s+1).fill(0));for(let u=1;u<=a;u++)for(let v=1;v<=s;v++)r[u-1]===i[v-1]?n[u][v]=n[u-1][v-1]+1:n[u][v]=Math.max(n[u-1][v],n[u][v-1]);let c=a,l=s;const d=[],m=[];for(;c>0||l>0;)c>0&&l>0&&r[c-1]===i[l-1]?(d.push({text:r[c-1],status:"unchanged"}),m.push({text:i[l-1],status:"unchanged"}),c--,l--):l>0&&(c===0||n[c][l-1]>=n[c-1][l])?(m.push({text:i[l-1],status:"added"}),d.push({text:"",status:"unchanged"}),l--):(d.push({text:r[c-1],status:"removed"}),m.push({text:"",status:"unchanged"}),c--);return d.reverse(),m.reverse(),{oldLines:d,newLines:m}}let _=class extends j{constructor(){super(...arguments),this.oldText="",this.newText="",this.oldLabel="Current",this.newLabel="Pending",this._syncing=!1}_handleScroll(e,t){if(this._syncing)return;this._syncing=!0;const r=e.target,i=this.shadowRoot?.querySelector(`.${t}`);i&&(i.scrollTop=r.scrollTop,i.scrollLeft=r.scrollLeft),requestAnimationFrame(()=>{this._syncing=!1})}_renderLines(e){return e.map(t=>{let r="line";return t.status==="removed"?r+=" line--removed":t.status==="added"?r+=" line--added":t.text===""&&(r+=" line--spacer"),o`<span class=${r}>${t.text||" "}</span>`})}render(){if(this.oldText===this.newText)return o`
4
- <div class="diff-container">
5
- <div class="no-changes">No changes detected</div>
6
- </div>
7
- `;const{oldLines:e,newLines:t}=U(this.oldText,this.newText);return o`
8
- <div class="diff-container">
9
- <div class="diff-panel">
10
- <div class="diff-header">${this.oldLabel}</div>
11
- <div
12
- class="diff-body diff-body--old"
13
- @scroll=${r=>this._handleScroll(r,"diff-body--new")}
14
- >
15
- <pre><code>${this._renderLines(e)}</code></pre>
16
- </div>
17
- </div>
18
- <div class="diff-panel">
19
- <div class="diff-header">${this.newLabel}</div>
20
- <div
21
- class="diff-body diff-body--new"
22
- @scroll=${r=>this._handleScroll(r,"diff-body--old")}
23
- >
24
- <pre><code>${this._renderLines(t)}</code></pre>
25
- </div>
26
- </div>
27
- </div>
28
- `}};_.styles=[N,P,I`
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-BBkuC-EU.js";import"./ic-tag-CvMVQFRR.js";import"./ic-confirm-dialog-DGlPbV1T.js";import"./ic-relative-time-B3UAnTqg.js";import"./ic-array-editor-BLoEyeLS.js";import"./ic-empty-state-CM3Wbj2f.js";import"./ic-tabs-yBjkWKJH.js";import"./ic-select-BqfZISjw.js";function d(e,t){let n=e.split(`
2
+ `),r=t.split(`
3
+ `),i=n.length,a=r.length,o=Array.from({length:i+1},()=>Array(a+1).fill(0));for(let e=1;e<=i;e++)for(let t=1;t<=a;t++)n[e-1]===r[t-1]?o[e][t]=o[e-1][t-1]+1:o[e][t]=Math.max(o[e-1][t],o[e][t-1]);let s=i,c=a,l=[],u=[];for(;s>0||c>0;)s>0&&c>0&&n[s-1]===r[c-1]?(l.push({text:n[s-1],status:`unchanged`}),u.push({text:r[c-1],status:`unchanged`}),s--,c--):c>0&&(s===0||o[s][c-1]>=o[s-1][c])?(u.push({text:r[c-1],status:`added`}),l.push({text:``,status:`unchanged`}),c--):(l.push({text:n[s-1],status:`removed`}),u.push({text:``,status:`unchanged`}),s--);return l.reverse(),u.reverse(),{oldLines:l,newLines:u}}var f=class extends r{constructor(...e){super(...e),this.oldText=``,this.newText=``,this.oldLabel=`Current`,this.newLabel=`Pending`,this._syncing=!1}static{this.styles=[o,i,n`
29
4
  :host {
30
5
  display: block;
31
6
  }
@@ -107,156 +82,32 @@ import{s as N,f as P,i as I,n as x,r as p,a as j,b as o,t as M,A as g,I as y}fro
107
82
  font-size: var(--ic-text-sm);
108
83
  grid-column: 1 / -1;
109
84
  }
110
- `];S([x()],_.prototype,"oldText",2);S([x()],_.prototype,"newText",2);S([x()],_.prototype,"oldLabel",2);S([x()],_.prototype,"newLabel",2);S([p()],_.prototype,"_syncing",2);_=S([M("ic-diff-viewer")],_);var B=Object.defineProperty,K=Object.getOwnPropertyDescriptor,w=(e,t,r,i)=>{for(var a=i>1?void 0:i?K(t,r):t,s=e.length-1,n;s>=0;s--)(n=e[s])&&(a=(i?n(t,r,a):n(a))||a);return i&&a&&B(t,r,a),a};const Z=["rpc","ws","admin","api","*"];function C(e){return e.replace(/([A-Z])/g," $1").replace(/^./,t=>t.toUpperCase()).trim()}function T(e,t){const r=t.split(".");let i=e;for(const a of r){if(i==null||typeof i!="object")return;i=i[a]}return i}function W(e,t,r){const i=t.split(".");if(i.length===1)return{...e,[i[0]]:r};const[a,...s]=i,n=e[a]??{};return{...e,[a]:W(n,s.join("."),r)}}let b=class extends j{constructor(){super(...arguments),this.schema={},this.config={},this.sectionKey="",this._formState={},this._formErrors={},this._expandedFormPaths=new Set}updated(e){e.has("config")&&(this._formState=structuredClone(this.config),this._formErrors={})}_onFormFieldChange(e,t){this._formState=W(this._formState,e,t);const r={...this._formErrors};delete r[e],this._formErrors=r,this.dispatchEvent(new CustomEvent("field-change",{detail:{path:e,value:t,formState:this._formState},bubbles:!0,composed:!0}))}_validateField(e,t,r){const i={...this._formErrors};if(r.type==="string"&&typeof t=="string")if(r.minLength!==void 0&&t.length<r.minLength)i[e]=`Minimum length is ${r.minLength}`;else if(r.maxLength!==void 0&&t.length>r.maxLength)i[e]=`Maximum length is ${r.maxLength}`;else if(r.pattern)try{new RegExp(r.pattern).test(t)||(i[e]=`Must match pattern: ${r.pattern}`)}catch{}else delete i[e];else(r.type==="number"||r.type==="integer")&&typeof t=="number"?r.minimum!==void 0&&t<r.minimum?i[e]=`Minimum value is ${r.minimum}`:r.maximum!==void 0&&t>r.maximum?i[e]=`Maximum value is ${r.maximum}`:delete i[e]:delete i[e];this._formErrors=i}_toggleFormFieldset(e){const t=new Set(this._expandedFormPaths);t.has(e)?t.delete(e):t.add(e),this._expandedFormPaths=t}_onArrayItemFieldChange(e,t,r,i){const s=(T(this._formState,e)??[]).map((n,c)=>c!==t?n:{...n,[r]:i});this._onFormFieldChange(e,s)}_renderStringField(e,t,r,i){const a=i.maxLength!==void 0&&i.maxLength>200||e.includes("prompt")||e.includes("template");return o`
111
- <div class="form-field">
112
- <label class="form-label">${t}</label>
113
- ${i.description?o`<span class="form-description">${i.description}</span>`:g}
114
- ${a?o`<textarea class="form-textarea" .value=${r}
115
- @input=${s=>this._onFormFieldChange(e,s.target.value)}
116
- @blur=${()=>this._validateField(e,r,i)}
117
- ></textarea>`:o`<input class="form-input" type="text" .value=${r}
118
- @input=${s=>this._onFormFieldChange(e,s.target.value)}
119
- @blur=${()=>this._validateField(e,r,i)}
120
- />`}
121
- ${this._formErrors[e]?o`<span class="form-error">${this._formErrors[e]}</span>`:g}
122
- </div>
123
- `}_renderNumberField(e,t,r,i){return o`
124
- <div class="form-field">
125
- <label class="form-label">${t}</label>
126
- ${i.description?o`<span class="form-description">${i.description}</span>`:g}
127
- <input class="form-input" type="number" .value=${String(r)}
128
- min=${i.minimum??g} max=${i.maximum??g}
129
- @input=${a=>{const s=parseFloat(a.target.value);isNaN(s)||this._onFormFieldChange(e,s)}}
130
- @blur=${()=>this._validateField(e,r,i)}
131
- />
132
- ${this._formErrors[e]?o`<span class="form-error">${this._formErrors[e]}</span>`:g}
133
- </div>
134
- `}_renderBooleanField(e,t,r,i){return o`
135
- <div class="form-field">
136
- ${i.description?o`<span class="form-description">${i.description}</span>`:g}
137
- <ic-toggle label=${t} .checked=${r}
138
- @change=${a=>this._onFormFieldChange(e,a.detail)}
139
- ></ic-toggle>
140
- </div>
141
- `}_renderEnumField(e,t,r,i){const a=(i.enum??[]).map(s=>({value:String(s),label:String(s)}));return o`
142
- <div class="form-field">
143
- ${i.description?o`<span class="form-description">${i.description}</span>`:g}
144
- <ic-select label=${t} .value=${String(r??"")} .options=${a}
145
- @change=${s=>this._onFormFieldChange(e,s.detail)}
146
- ></ic-select>
147
- </div>
148
- `}_renderArrayField(e,t,r,i){return i.items?.type==="string"?o`
149
- <div class="form-field">
150
- ${i.description?o`<span class="form-description">${i.description}</span>`:g}
151
- <ic-array-editor label=${t} .items=${(r??[]).map(String)} placeholder="Add item..."
152
- @change=${a=>{this._onFormFieldChange(e,a.detail)}}
153
- ></ic-array-editor>
154
- </div>
155
- `:i.items?.type==="object"&&i.items.properties?this._renderArrayOfObjectsField(e,t,r,i):this._renderJsonFallback(e,t,r,i)}_renderArrayOfObjectsField(e,t,r,i){const a=r??[],s=i.items,n=s.properties??{},c=s.required??[],l=()=>{const d={};for(const[m,u]of Object.entries(n))u.default!==void 0?d[m]=JSON.parse(JSON.stringify(u.default)):u.type==="string"?d[m]="":u.type==="number"||u.type==="integer"?d[m]=0:u.type==="boolean"?d[m]=!1:u.type==="array"?d[m]=[]:u.type==="object"&&(d[m]={});return d};return o`
156
- <div class="form-field">
157
- <label class="form-label">${t}</label>
158
- ${i.description?o`<span class="form-description">${i.description}</span>`:g}
159
- <div class="array-cards">
160
- ${a.map((d,m)=>this._renderArrayObjectCard(e,m,d,n,c))}
85
+ `]}_handleScroll(e,t){if(this._syncing)return;this._syncing=!0;let n=e.target,r=this.shadowRoot?.querySelector(`.${t}`);r&&(r.scrollTop=n.scrollTop,r.scrollLeft=n.scrollLeft),requestAnimationFrame(()=>{this._syncing=!1})}_renderLines(e){return e.map(e=>{let n=`line`;return e.status===`removed`?n+=` line--removed`:e.status===`added`?n+=` line--added`:e.text===``&&(n+=` line--spacer`),t`<span class=${n}>${e.text||` `}</span>`})}render(){if(this.oldText===this.newText)return t`
86
+ <div class="diff-container">
87
+ <div class="no-changes">No changes detected</div>
161
88
  </div>
162
- <button class="array-add-btn"
163
- @click=${()=>{this._onFormFieldChange(e,[...a,l()])}}
164
- >+ Add</button>
165
- </div>
166
- `}_renderArrayObjectCard(e,t,r,i,a){return o`
167
- <div class="array-card">
168
- <div class="array-card-header">
169
- <span class="array-card-index">#${t+1}</span>
170
- <button class="array-card-remove" title="Remove"
171
- @click=${()=>{const s=T(this._formState,e)??[];this._onFormFieldChange(e,s.filter((n,c)=>c!==t))}}
172
- >\u00d7</button>
89
+ `;let{oldLines:e,newLines:n}=d(this.oldText,this.newText);return t`
90
+ <div class="diff-container">
91
+ <div class="diff-panel">
92
+ <div class="diff-header">${this.oldLabel}</div>
93
+ <div
94
+ class="diff-body diff-body--old"
95
+ @scroll=${e=>this._handleScroll(e,`diff-body--new`)}
96
+ >
97
+ <pre><code>${this._renderLines(e)}</code></pre>
98
+ </div>
173
99
  </div>
174
- <div class="array-card-fields">
175
- ${Object.entries(i).map(([s,n])=>{const c=`${C(s)}${a.includes(s)?" *":""}`,l=r[s];if(s==="secret")return o`
176
- <div class="form-field">
177
- <label class="form-label">${c}</label>
178
- <input type="password" class="form-input"
179
- .value=${typeof l=="string"?l:""}
180
- placeholder="env:VAR_NAME or min 32 chars"
181
- @input=${d=>{this._onArrayItemFieldChange(e,t,s,d.target.value)}}
182
- />
183
- </div>
184
- `;if(n.type==="array"&&n.items?.type==="string"){if(s==="scopes"){const d=new Set((l??[]).map(String));return o`
185
- <div class="form-field">
186
- <label class="form-label">${c}</label>
187
- <div class="scope-chips">
188
- ${Z.map(m=>o`
189
- <button class="scope-chip" ?data-active=${d.has(m)}
190
- @click=${()=>{const u=new Set(d);u.has(m)?u.delete(m):u.add(m),this._onArrayItemFieldChange(e,t,s,[...u])}}
191
- >${m}</button>
192
- `)}
193
- </div>
194
- </div>
195
- `}return o`
196
- <div class="form-field">
197
- <ic-array-editor label=${c} .items=${(l??[]).map(String)} placeholder="Add..."
198
- @change=${d=>{this._onArrayItemFieldChange(e,t,s,d.detail)}}
199
- ></ic-array-editor>
200
- </div>
201
- `}return n.type==="string"?o`
202
- <div class="form-field">
203
- <label class="form-label">${c}</label>
204
- <input type="text" class="form-input" .value=${String(l??"")}
205
- @input=${d=>{this._onArrayItemFieldChange(e,t,s,d.target.value)}}
206
- />
207
- </div>
208
- `:n.type==="number"||n.type==="integer"?o`
209
- <div class="form-field">
210
- <label class="form-label">${c}</label>
211
- <input type="number" class="form-input" .value=${String(l??0)}
212
- @input=${d=>{this._onArrayItemFieldChange(e,t,s,Number(d.target.value))}}
213
- />
214
- </div>
215
- `:n.type==="boolean"?o`
216
- <div class="form-field">
217
- <label class="form-label">${c}</label>
218
- <ic-toggle ?checked=${!!l}
219
- @change=${d=>{this._onArrayItemFieldChange(e,t,s,d.detail)}}
220
- ></ic-toggle>
221
- </div>
222
- `:o`
223
- <div class="form-field">
224
- <label class="form-label">${c}</label>
225
- <input type="text" class="form-input" .value=${JSON.stringify(l??"")}
226
- @input=${d=>{try{this._onArrayItemFieldChange(e,t,s,JSON.parse(d.target.value))}catch{}}}
227
- />
228
- </div>
229
- `})}
100
+ <div class="diff-panel">
101
+ <div class="diff-header">${this.newLabel}</div>
102
+ <div
103
+ class="diff-body diff-body--new"
104
+ @scroll=${e=>this._handleScroll(e,`diff-body--old`)}
105
+ >
106
+ <pre><code>${this._renderLines(n)}</code></pre>
107
+ </div>
230
108
  </div>
231
109
  </div>
232
- `}_renderObjectField(e,t,r,i){const a=this._expandedFormPaths.has(e),s=i.properties??{},n=i.required??[];return o`
233
- <fieldset class="form-fieldset">
234
- <legend class="form-fieldset-legend" @click=${()=>this._toggleFormFieldset(e)}>
235
- <span class="arrow" ?data-expanded=${a}>\u25B6</span>
236
- ${t}
237
- </legend>
238
- ${a?o`
239
- <div class="form-fieldset-content">
240
- ${Object.entries(s).map(([c,l])=>this._renderSchemaField(`${e}.${c}`,`${C(c)}${n.includes(c)?" *":""}`,T(r??{},c),l))}
241
- </div>
242
- `:g}
243
- </fieldset>
244
- `}_renderJsonFallback(e,t,r,i){const a=JSON.stringify(r??null,null,2);return o`
245
- <div class="form-field">
246
- <label class="form-label">${t}</label>
247
- ${i.description?o`<span class="form-description">${i.description}</span>`:g}
248
- <textarea class="json-fallback-textarea" .value=${a}
249
- @input=${s=>{const n=s.target.value;try{const c=JSON.parse(n);this._onFormFieldChange(e,c);const l={...this._formErrors};delete l[e],this._formErrors=l}catch{this._formErrors={...this._formErrors,[e]:"Invalid JSON"}}}}
250
- ></textarea>
251
- ${this._formErrors[e]?o`<span class="form-error">${this._formErrors[e]}</span>`:g}
252
- </div>
253
- `}_renderSchemaField(e,t,r,i){if(i.enum&&i.enum.length>0)return this._renderEnumField(e,t,r,i);const a=i.anyOf??i.oneOf;if(a&&a.length>=2){const s=a.filter(n=>n.type!=="null");if(s.length===1)return this._renderSchemaField(e,t,r,s[0]);if(r==null||typeof r=="string"){const n=s.find(c=>c.type==="string");if(n)return this._renderStringField(e,t,String(r??""),n)}}if(i.anyOf||i.oneOf||i.allOf)return this._renderJsonFallback(e,t,r,i);switch(i.type){case"string":return this._renderStringField(e,t,String(r??""),i);case"number":case"integer":return this._renderNumberField(e,t,Number(r??0),i);case"boolean":return this._renderBooleanField(e,t,!!r,i);case"array":return this._renderArrayField(e,t,r??[],i);case"object":return this._renderObjectField(e,t,r??{},i);default:return this._renderJsonFallback(e,t,r,i)}}render(){const e=this.schema;if(e&&!e.properties&&e.additionalProperties&&typeof e.additionalProperties=="object"){const i=e.additionalProperties,a=Object.keys(this._formState);return a.length===0?o`<ic-empty-state icon="config" message="No entries" description="This section has no configured entries."></ic-empty-state>`:o`
254
- ${a.map(s=>{const n=this._formState[s]??{};return this._renderObjectField(s,C(s),n,i)})}
255
- `}if(!e||!e.properties)return o`
256
- ${Object.entries(this._formState).map(([i,a])=>this._renderSchemaField(i,C(i),a,{type:typeof a=="boolean"?"boolean":typeof a=="number"?"number":"string"}))}
257
- `;const t=e.properties,r=e.required??[];return o`
258
- ${Object.entries(t).map(([i,a])=>this._renderSchemaField(i,`${C(i)}${r.includes(i)?" *":""}`,T(this._formState,i),a))}
259
- `}};b.styles=[N,P,I`
110
+ `}};c([s()],f.prototype,`oldText`,void 0),c([s()],f.prototype,`newText`,void 0),c([s()],f.prototype,`oldLabel`,void 0),c([s()],f.prototype,`newLabel`,void 0),c([a()],f.prototype,`_syncing`,void 0),f=c([e(`ic-diff-viewer`)],f);var p=[`rpc`,`ws`,`admin`,`api`,`*`];function m(e){return e.replace(/([A-Z])/g,` $1`).replace(/^./,e=>e.toUpperCase()).trim()}function h(e,t){let n=t.split(`.`),r=e;for(let e of n){if(typeof r!=`object`||!r)return;r=r[e]}return r}function g(e,t,n){let r=t.split(`.`);if(r.length===1)return{...e,[r[0]]:n};let[i,...a]=r,o=e[i]??{};return{...e,[i]:g(o,a.join(`.`),n)}}var _=class extends r{constructor(...e){super(...e),this.schema={},this.config={},this.sectionKey=``,this._formState={},this._formErrors={},this._expandedFormPaths=new Set}static{this.styles=[o,i,n`
260
111
  :host {
261
112
  display: block;
262
113
  }
@@ -460,318 +311,161 @@ import{s as N,f as P,i as I,n as x,r as p,a as j,b as o,t as M,A as g,I as y}fro
460
311
  outline: none;
461
312
  border-color: var(--ic-accent);
462
313
  }
463
- `];w([x({attribute:!1})],b.prototype,"schema",2);w([x({attribute:!1})],b.prototype,"config",2);w([x({type:String})],b.prototype,"sectionKey",2);w([p()],b.prototype,"_formState",2);w([p()],b.prototype,"_formErrors",2);w([p()],b.prototype,"_expandedFormPaths",2);b=w([M("ic-schema-form")],b);function $(e,t=0){const r=" ".repeat(t);if(e==null)return"null";if(typeof e=="boolean")return e?"true":"false";if(typeof e=="number")return String(e);if(typeof e=="string")return e===""||e.includes(":")||e.includes("#")||e.includes(`
464
- `)||e.includes('"')||e.includes("'")||e.startsWith(" ")||e.endsWith(" ")||e==="true"||e==="false"||e==="null"||/^\d+(\.\d+)?$/.test(e)?`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:e;if(Array.isArray(e)){if(e.length===0)return"[]";const i=[];for(const a of e)if(typeof a=="object"&&a!==null&&!Array.isArray(a)){const s=Object.entries(a);if(s.length>0){const[n,c]=s[0];i.push(`${r}- ${n}: ${$(c,0)}`);for(let l=1;l<s.length;l++){const[d,m]=s[l];i.push(`${r} ${d}: ${$(m,t+2)}`)}}else i.push(`${r}- {}`)}else i.push(`${r}- ${$(a,0)}`);return`
465
- `+i.join(`
466
- `)}if(typeof e=="object"){const i=Object.entries(e);if(i.length===0)return"{}";const a=[];for(const[s,n]of i)typeof n=="object"&&n!==null&&!Array.isArray(n)&&Object.keys(n).length>0?(a.push(`${r}${s}:`),a.push($(n,t+1))):Array.isArray(n)&&n.length>0?a.push(`${r}${s}:${$(n,t+1)}`):a.push(`${r}${s}: ${$(n,0)}`);return a.join(`
467
- `)}return String(e)}function L(e){try{const t=e.split(`
468
- `);return{data:A(t,0,0).value,error:null}}catch(t){return{data:null,error:t instanceof Error?t.message:"Parse error"}}}function z(e){const t=e.match(/^( *)/);return t?t[1].length:0}function F(e){const t=e.trim();if(t===""||t==="null"||t==="~")return null;if(t==="true")return!0;if(t==="false")return!1;if(t==="[]")return[];if(t==="{}")return{};if(t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'"))return t.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\");const r=Number(t);return!isNaN(r)&&t!==""?r:t}function A(e,t,r){let i=t;for(;i<e.length&&e[i].trim()==="";)i++;if(i>=e.length)return{value:null,nextLine:i};const a=e[i],s=z(a),n=a.trim();if(n.startsWith("- ")){const c=[];for(;i<e.length;){const l=e[i];if(l.trim()===""){i++;continue}const d=z(l);if(d<s||d!==s||!l.trim().startsWith("- "))break;const m=l.trim().slice(2),u=m.match(/^([^:]+):\s*(.*)/);if(u&&!m.startsWith('"')&&!m.startsWith("'")){const v={};v[u[1].trim()]=F(u[2]),i++;const k=s+2;for(;i<e.length;){const E=e[i];if(E.trim()===""){i++;continue}const G=z(E);if(G<k)break;if(G===k&&!E.trim().startsWith("- ")){const O=E.trim().match(/^([^:]+):\s*(.*)/);if(O){const H=O[1].trim(),D=O[2];if(D===""||D===void 0){const q=A(e,i+1);v[H]=q.value,i=q.nextLine}else v[H]=F(D),i++}else break}else break}c.push(v)}else c.push(F(m)),i++}return{value:c,nextLine:i}}if(n.includes(":")){const c={};for(;i<e.length;){const l=e[i];if(l.trim()===""){i++;continue}const d=z(l);if(d<s||d!==s)break;const m=l.indexOf(":");if(m===-1)break;const u=l.slice(0,m).trim(),v=l.slice(m+1).trim();if(v===""||v===void 0){i++;const k=A(e,i);c[u]=k.value,i=k.nextLine}else c[u]=F(v),i++}return{value:c,nextLine:i}}return{value:F(n),nextLine:i+1}}var Q=Object.defineProperty,X=Object.getOwnPropertyDescriptor,h=(e,t,r,i)=>{for(var a=i>1?void 0:i?X(t,r):t,s=e.length-1,n;s>=0;s--)(n=e[s])&&(a=(i?n(t,r,a):n(a))||a);return i&&a&&Q(t,r,a),a};const ee=[{id:"editor",label:"YAML Editor"},{id:"gateway",label:"Gateway"},{id:"history",label:"History"},{id:"wizard",label:"Setup Wizard"}],R=$;function Y(e,t,r){const i=t.split(".");if(i.length===1)return{...e,[i[0]]:r};const[a,...s]=i,n=e[a]??{};return{...e,[a]:Y(n,s.join("."),r)}}let f=class extends j{constructor(){super(...arguments),this.rpcClient=null,this._activeTab="editor",this._loadState="loading",this._error="",this._sections=[],this._selectedSection="",this._mode="form",this._configData={},this._schemaData={},this._yamlText="",this._yamlErrors=[],this._formState={},this._formErrors={},this._dirty=!1,this._applying=!1,this._expandedPaths=new Set,this._showDiff=!1,this._savedYaml="",this._rollbackSnapshot=null,this._confirmRollback=!1,this._gatewayConfig=null,this._gatewayLoading=!1,this._gatewayError="",this._historyEntries=[],this._historyLoading=!1,this._historyError="",this._selectedSha=null,this._diffText="",this._diffLoading=!1,this._confirmRollbackSha=null,this._gcRunning=!1,this._historyReloadTimer=null,this._yamlDebounceTimer=null,this._rpcStatusUnsub=null,this._dataLoaded=!1,this._configPatchedHandler=null}connectedCallback(){super.connectedCallback(),this._configPatchedHandler=()=>{this._dataLoaded&&!this._dirty&&this._tryLoad(),this._activeTab==="history"&&this._scheduleHistoryReload()},document.addEventListener("config:patched",this._configPatchedHandler)}_scheduleHistoryReload(){this._historyReloadTimer!==null&&clearTimeout(this._historyReloadTimer),this._historyReloadTimer=setTimeout(()=>{this._historyReloadTimer=null,this._loadHistory()},300)}disconnectedCallback(){super.disconnectedCallback(),this._yamlDebounceTimer!==null&&clearTimeout(this._yamlDebounceTimer),this._historyReloadTimer!==null&&clearTimeout(this._historyReloadTimer),this._rpcStatusUnsub?.(),this._rpcStatusUnsub=null,this._configPatchedHandler&&(document.removeEventListener("config:patched",this._configPatchedHandler),this._configPatchedHandler=null)}updated(e){e.has("rpcClient")&&this.rpcClient&&this._tryLoad()}_tryLoad(){this.rpcClient&&(this._rpcStatusUnsub?.(),this.rpcClient.status==="connected"?this._loadData():this._rpcStatusUnsub=this.rpcClient.onStatusChange(e=>{e==="connected"&&!this._dataLoaded&&this._loadData()}))}async _loadData(){if(this.rpcClient){this._loadState="loading",this._error="";try{const e=await this.rpcClient.call("config.read");this._sections=e.sections,this._configData=e.config,this._sections.length>0&&!this._selectedSection&&(this._selectedSection=this._sections[0],this._loadSectionState()),this._loadState="loaded",this._dataLoaded=!0,this.rpcClient.call("config.schema").then(t=>{const r=t.schema;this._schemaData=r.properties??r}).catch(()=>{})}catch(e){this._error=e instanceof Error?e.message:"Failed to load configuration",this._loadState="error"}}}_loadSectionState(){const e=this._configData[this._selectedSection]??{};this._formState=structuredClone(e),this._yamlText=R(e),this._savedYaml=this._yamlText,this._yamlErrors=[],this._formErrors={},this._dirty=!1,this._showDiff=!1,this._expandedPaths=new Set}_onSectionClick(e){e!==this._selectedSection&&(this._selectedSection=e,this._loadSectionState())}_onModeChange(e){if(e!==this._mode){if(this._mode==="form"&&e==="yaml")this._yamlText=R(this._formState);else if(this._mode==="yaml"&&e==="form"&&this._yamlErrors.length===0){const t=L(this._yamlText);!t.error&&t.data&&typeof t.data=="object"&&(this._formState=t.data)}this._mode=e}}_renderFormMode(){const e=this._schemaData[this._selectedSection]??{};return o`
469
- <ic-schema-form
470
- .schema=${e}
471
- .config=${this._formState}
472
- .sectionKey=${this._selectedSection}
473
- @field-change=${t=>{const{path:r,value:i,formState:a}=t.detail;this._formState=a??Y(this._formState,r,i),this._dirty=!0;const s={...this._formErrors};delete s[r],this._formErrors=s}}
474
- ></ic-schema-form>
475
- `}_onYamlInput(e){this._yamlText=e.target.value,this._dirty=!0,this._yamlDebounceTimer!==null&&clearTimeout(this._yamlDebounceTimer),this._yamlDebounceTimer=setTimeout(()=>{this._validateYaml()},500)}_validateYaml(){const e=L(this._yamlText);e.error?this._yamlErrors=[e.error]:this._yamlErrors=[]}_renderYamlMode(){return o`
476
- <div class="yaml-editor">
477
- <textarea
478
- class="yaml-textarea"
479
- .value=${this._yamlText}
480
- @input=${e=>this._onYamlInput(e)}
481
- spellcheck="false"
482
- aria-label="YAML editor"
483
- ></textarea>
484
- ${this._yamlErrors.length>0?o`
485
- <div class="yaml-validation yaml-validation--error">
486
- ${this._yamlErrors.map(e=>o`<div>${e}</div>`)}
487
- </div>
488
- `:o`
489
- <div class="yaml-validation yaml-validation--valid">
490
- Valid configuration
491
- </div>
492
- `}
314
+ `]}updated(e){e.has(`config`)&&(this._formState=structuredClone(this.config),this._formErrors={})}_onFormFieldChange(e,t){this._formState=g(this._formState,e,t);let n={...this._formErrors};delete n[e],this._formErrors=n,this.dispatchEvent(new CustomEvent(`field-change`,{detail:{path:e,value:t,formState:this._formState},bubbles:!0,composed:!0}))}_validateField(e,t,n){let r={...this._formErrors};if(n.type===`string`&&typeof t==`string`)if(n.minLength!==void 0&&t.length<n.minLength)r[e]=`Minimum length is ${n.minLength}`;else if(n.maxLength!==void 0&&t.length>n.maxLength)r[e]=`Maximum length is ${n.maxLength}`;else if(n.pattern)try{new RegExp(n.pattern).test(t)||(r[e]=`Must match pattern: ${n.pattern}`)}catch{}else delete r[e];else (n.type===`number`||n.type===`integer`)&&typeof t==`number`?n.minimum!==void 0&&t<n.minimum?r[e]=`Minimum value is ${n.minimum}`:n.maximum!==void 0&&t>n.maximum?r[e]=`Maximum value is ${n.maximum}`:delete r[e]:delete r[e];this._formErrors=r}_toggleFormFieldset(e){let t=new Set(this._expandedFormPaths);t.has(e)?t.delete(e):t.add(e),this._expandedFormPaths=t}_onArrayItemFieldChange(e,t,n,r){let i=(h(this._formState,e)??[]).map((e,i)=>i===t?{...e,[n]:r}:e);this._onFormFieldChange(e,i)}_renderStringField(e,n,r,i){let a=i.maxLength!==void 0&&i.maxLength>200||e.includes(`prompt`)||e.includes(`template`);return t`
315
+ <div class="form-field">
316
+ <label class="form-label">${n}</label>
317
+ ${i.description?t`<span class="form-description">${i.description}</span>`:l}
318
+ ${a?t`<textarea class="form-textarea" .value=${r}
319
+ @input=${t=>this._onFormFieldChange(e,t.target.value)}
320
+ @blur=${()=>this._validateField(e,r,i)}
321
+ ></textarea>`:t`<input class="form-input" type="text" .value=${r}
322
+ @input=${t=>this._onFormFieldChange(e,t.target.value)}
323
+ @blur=${()=>this._validateField(e,r,i)}
324
+ />`}
325
+ ${this._formErrors[e]?t`<span class="form-error">${this._formErrors[e]}</span>`:l}
493
326
  </div>
494
- `}_toggleSchemaPath(e){const t=new Set(this._expandedPaths);t.has(e)?t.delete(e):t.add(e),this._expandedPaths=t}_renderSchemaTreeNode(e,t,r,i,a){const s=t.type==="object"&&t.properties&&Object.keys(t.properties).length>0,n=this._expandedPaths.has(r),c=[];return a&&c.push("required"),t.minimum!==void 0&&c.push(`min: ${t.minimum}`),t.maximum!==void 0&&c.push(`max: ${t.maximum}`),t.minLength!==void 0&&c.push(`minLen: ${t.minLength}`),t.maxLength!==void 0&&c.push(`maxLen: ${t.maxLength}`),t.enum&&c.push(`enum: [${t.enum.join(", ")}]`),t.pattern&&c.push(`pattern: ${t.pattern}`),t.default!==void 0&&c.push(`default: ${JSON.stringify(t.default)}`),o`
495
- <div style="padding-left: ${i*1.5}rem">
496
- <div class="schema-row">
497
- <span
498
- class="schema-key"
499
- @click=${s?()=>this._toggleSchemaPath(r):g}
500
- >
501
- ${s?o`<span class="arrow" ?data-expanded=${n}>\u25B6</span>`:g}
502
- ${e}${a?o`<span class="required-marker">*</span>`:g}
503
- </span>
504
- <ic-tag variant="info">${t.type??"any"}</ic-tag>
505
- ${t.description?o`<span class="schema-desc">${t.description}</span>`:g}
506
- ${c.length>0?o`<span class="schema-constraints">${c.join(", ")}</span>`:g}
507
- </div>
508
- ${s&&n?o`
509
- <div class="schema-children">
510
- ${Object.entries(t.properties).map(([l,d])=>this._renderSchemaTreeNode(l,d,`${r}.${l}`,i+1,(t.required??[]).includes(l)))}
511
- </div>
512
- `:g}
327
+ `}_renderNumberField(e,n,r,i){return t`
328
+ <div class="form-field">
329
+ <label class="form-label">${n}</label>
330
+ ${i.description?t`<span class="form-description">${i.description}</span>`:l}
331
+ <input class="form-input" type="number" .value=${String(r)}
332
+ min=${i.minimum??l} max=${i.maximum??l}
333
+ @input=${t=>{let n=parseFloat(t.target.value);isNaN(n)||this._onFormFieldChange(e,n)}}
334
+ @blur=${()=>this._validateField(e,r,i)}
335
+ />
336
+ ${this._formErrors[e]?t`<span class="form-error">${this._formErrors[e]}</span>`:l}
513
337
  </div>
514
- `}_renderSchemaMode(){const e=this._schemaData[this._selectedSection];if(e&&!e.properties&&e.additionalProperties&&typeof e.additionalProperties=="object"){const r=e.additionalProperties;if(!r.properties)return o`<ic-empty-state icon="config" message="No schema available" description="Schema definition not found for this section."></ic-empty-state>`;const i=r.required??[];return o`
515
- <div class="schema-tree">
516
- <div class="schema-note" style="padding:8px 0;opacity:0.7;font-style:italic">Record&lt;string, entry&gt; - each entry has:</div>
517
- ${Object.entries(r.properties).map(([a,s])=>this._renderSchemaTreeNode(a,s,a,0,i.includes(a)))}
518
- </div>
519
- `}if(!e?.properties)return o`<ic-empty-state icon="config" message="No schema available" description="Schema definition not found for this section."></ic-empty-state>`;const t=e.required??[];return o`
520
- <div class="schema-tree">
521
- ${Object.entries(e.properties).map(([r,i])=>this._renderSchemaTreeNode(r,i,r,0,t.includes(r)))}
338
+ `}_renderBooleanField(e,n,r,i){return t`
339
+ <div class="form-field">
340
+ ${i.description?t`<span class="form-description">${i.description}</span>`:l}
341
+ <ic-toggle label=${n} .checked=${r}
342
+ @change=${t=>this._onFormFieldChange(e,t.detail)}
343
+ ></ic-toggle>
522
344
  </div>
523
- `}async _onApply(){if(!this.rpcClient||!this._dirty)return;this._applying=!0;let e;if(this._mode==="yaml"){const t=L(this._yamlText);if(t.error){y.show(t.error,"error"),this._applying=!1;return}e=t.data}else e=this._formState;this._rollbackSnapshot=structuredClone(this._configData);try{await this.rpcClient.call("config.apply",{section:this._selectedSection,value:e}),y.show("Configuration applied","success"),this._dirty=!1;const t=await this.rpcClient.call("config.read");this._configData=t.config,this._loadSectionState()}catch(t){const r=t instanceof Error?t.message:"Failed to apply configuration";y.show(r,"error"),this._rollbackSnapshot=null}finally{this._applying=!1}}async _onRollback(){if(!(!this.rpcClient||!this._rollbackSnapshot))try{await this.rpcClient.call("config.apply",{config:this._rollbackSnapshot}),y.show("Configuration rolled back","success");const e=await this.rpcClient.call("config.read");this._configData=e.config,this._rollbackSnapshot=null,this._confirmRollback=!1,this._loadSectionState()}catch(e){const t=e instanceof Error?e.message:"Failed to rollback configuration";y.show(t,"error"),this._confirmRollback=!1}}async _loadGatewayConfig(){if(this.rpcClient){this._gatewayLoading=!0,this._gatewayError="";try{const e=await this.rpcClient.call("config.read",{section:"gateway"});this._gatewayConfig=e??{}}catch(e){this._gatewayError=e instanceof Error?e.message:"Failed to load gateway config"}finally{this._gatewayLoading=!1}}}async _patchGateway(e,t){if(this.rpcClient)try{await this.rpcClient.call("config.patch",{section:"gateway",key:e,value:t}),this._gatewayConfig&&(this._gatewayConfig={...this._gatewayConfig,[e]:t}),y.show("Gateway updated","success")}catch(r){const i=r instanceof Error?r.message:"Failed to update gateway";y.show(i,"error")}}_onTabChange(e){this._activeTab=e.detail,e.detail==="gateway"&&this._gatewayConfig===null&&this._loadGatewayConfig(),e.detail==="history"&&this._historyEntries.length===0&&!this._historyLoading&&this._loadHistory()}async _loadHistory(){if(this.rpcClient){this._historyLoading=!0,this._historyError="";try{const e=await this.rpcClient.call("config.history",{limit:50});e.error?(this._historyEntries=[],this._historyError=e.error):this._historyEntries=e.entries}catch(e){this._historyError=e instanceof Error?e.message:"Failed to load history"}finally{this._historyLoading=!1}}}async _loadDiff(e){if(this.rpcClient){this._diffLoading=!0;try{const t=await this.rpcClient.call("config.diff",{sha:e});this._diffText=t.diff}catch(t){this._diffText="";const r=t instanceof Error?t.message:"Failed to load diff";y.show(r,"error")}finally{this._diffLoading=!1}}}_onSelectVersion(e){if(e===this._selectedSha){this._selectedSha=null,this._diffText="";return}this._selectedSha=e,this._loadDiff(e)}async _onHistoryRollback(){if(!(!this.rpcClient||!this._confirmRollbackSha))try{await this.rpcClient.call("config.rollback",{sha:this._confirmRollbackSha}),y.show("Config rolled back. Daemon restarting...","success"),this._confirmRollbackSha=null}catch(e){const t=e instanceof Error?e.message:"Rollback failed";y.show(t,"error"),this._confirmRollbackSha=null}}async _onGc(){if(!(!this.rpcClient||this._gcRunning)){this._gcRunning=!0;try{const t=(await this.rpcClient.call("config.gc")).squashed;y.show(t!=null?`GC complete: ${t} versions squashed`:"GC complete","success"),this._loadHistory()}catch(e){const t=e instanceof Error?e.message:"GC failed";y.show(t,"error")}finally{this._gcRunning=!1}}}_renderDiffLine(e,t){let r="diff-line--context";return e.startsWith("+")?r="diff-line--add":e.startsWith("-")?r="diff-line--remove":e.startsWith("@@")&&(r="diff-line--hunk"),o`<span class=${r}>${e}\n</span>`}_renderHistoryEntry(e,t){const r=e.sha===this._selectedSha,i=t===0,a=e.metadata.user||e.metadata.agent||"system",s=new Date(e.timestamp).toLocaleString();return o`
524
- <div
525
- class="history-entry ${r?"history-entry--selected":""}"
526
- @click=${()=>this._onSelectVersion(e.sha)}
527
- >
528
- <div class="history-entry-header">
529
- <ic-relative-time
530
- .timestamp=${new Date(e.timestamp).getTime()}
531
- title=${s}
532
- ></ic-relative-time>
533
- <code class="history-sha">${e.sha.slice(0,7)}</code>
534
- </div>
535
- <div class="history-entry-summary" title=${e.metadata.summary}>
536
- ${e.metadata.summary}
537
- </div>
538
- <div class="history-entry-meta">
539
- <ic-tag variant="default">${e.metadata.section}</ic-tag>
540
- <span class="history-author">${a}</span>
541
- ${i?g:o`<button
542
- class="history-rollback-link"
543
- @click=${n=>{n.stopPropagation(),this._confirmRollbackSha=e.sha}}
544
- >Rollback</button>`}
545
- </div>
345
+ `}_renderEnumField(e,n,r,i){let a=(i.enum??[]).map(e=>({value:String(e),label:String(e)}));return t`
346
+ <div class="form-field">
347
+ ${i.description?t`<span class="form-description">${i.description}</span>`:l}
348
+ <ic-select label=${n} .value=${String(r??``)} .options=${a}
349
+ @change=${t=>this._onFormFieldChange(e,t.detail)}
350
+ ></ic-select>
546
351
  </div>
547
- `}_renderHistoryTab(){return this._historyLoading?o`<div class="state-container"><ic-loading size="lg"></ic-loading></div>`:this._historyError?o`
548
- <ic-empty-state
549
- icon="config"
550
- message="Version history unavailable"
551
- description=${this._historyError}
552
- ></ic-empty-state>
553
- `:this._historyEntries.length===0?o`
554
- <ic-empty-state
555
- icon="config"
556
- message="No version history"
557
- description="Config changes will appear here after the first edit."
558
- ></ic-empty-state>
559
- `:o`
560
- <div class="history-layout">
561
- <div class="history-timeline">
562
- ${this._historyEntries.map((e,t)=>this._renderHistoryEntry(e,t))}
352
+ `}_renderArrayField(e,n,r,i){return i.items?.type===`string`?t`
353
+ <div class="form-field">
354
+ ${i.description?t`<span class="form-description">${i.description}</span>`:l}
355
+ <ic-array-editor label=${n} .items=${(r??[]).map(String)} placeholder="Add item..."
356
+ @change=${t=>{this._onFormFieldChange(e,t.detail)}}
357
+ ></ic-array-editor>
563
358
  </div>
564
-
565
- <div class="history-diff-panel">
566
- ${this._diffLoading?o`<div class="state-container"><ic-loading size="lg"></ic-loading></div>`:this._selectedSha&&this._diffText?o`<pre class="diff-unified">${this._diffText.split(`
567
- `).map((e,t)=>this._renderDiffLine(e,t))}</pre>`:this._selectedSha&&!this._diffText?o`<ic-empty-state icon="config" message="No changes" description="No changes between this version and current."></ic-empty-state>`:o`<ic-empty-state icon="config" message="Select a version" description="Select a version to view changes."></ic-empty-state>`}
359
+ `:i.items?.type===`object`&&i.items.properties?this._renderArrayOfObjectsField(e,n,r,i):this._renderJsonFallback(e,n,r,i)}_renderArrayOfObjectsField(e,n,r,i){let a=r??[],o=i.items,s=o.properties??{},c=o.required??[],u=()=>{let e={};for(let[t,n]of Object.entries(s))n.default===void 0?n.type===`string`?e[t]=``:n.type===`number`||n.type===`integer`?e[t]=0:n.type===`boolean`?e[t]=!1:n.type===`array`?e[t]=[]:n.type===`object`&&(e[t]={}):e[t]=JSON.parse(JSON.stringify(n.default));return e};return t`
360
+ <div class="form-field">
361
+ <label class="form-label">${n}</label>
362
+ ${i.description?t`<span class="form-description">${i.description}</span>`:l}
363
+ <div class="array-cards">
364
+ ${a.map((t,n)=>this._renderArrayObjectCard(e,n,t,s,c))}
568
365
  </div>
366
+ <button class="array-add-btn"
367
+ @click=${()=>{this._onFormFieldChange(e,[...a,u()])}}
368
+ >+ Add</button>
569
369
  </div>
570
-
571
- <div class="history-actions">
572
- <button
573
- class="secondary-btn"
574
- ?disabled=${this._gcRunning}
575
- @click=${()=>this._onGc()}
576
- >
577
- ${this._gcRunning?o`<span class="spinner"></span> Running GC...`:"Run GC"}
578
- </button>
579
- </div>
580
- `}_onExport(){const e=R(this._configData),t=new Blob([e],{type:"text/yaml"}),r=URL.createObjectURL(t),i=document.createElement("a");i.href=r,i.download="comis-config.yaml",i.click(),URL.revokeObjectURL(r)}_onImportClick(){this.shadowRoot?.querySelector(".hidden-input")?.click()}_onImportFile(e){const t=e.target,r=t.files?.[0];if(!r)return;const i=new FileReader;i.onload=()=>{const a=i.result,s=L(a);if(s.error){y.show(`Import failed: ${s.error}`,"error");return}s.data&&typeof s.data=="object"&&!Array.isArray(s.data)?(this._configData=s.data,this._loadSectionState(),this._dirty=!0,y.show("Configuration imported","info")):y.show("Import failed: expected a YAML object","error")},i.readAsText(r),t.value=""}_renderModeContent(){switch(this._mode){case"form":return this._renderFormMode();case"yaml":return this._renderYamlMode();case"schema":return this._renderSchemaMode();default:return g}}_renderEditorTab(){return this._loadState==="loading"?o`<ic-skeleton-view variant="editor"></ic-skeleton-view>`:this._loadState==="error"?o`
581
- <div class="error-container">
582
- <span class="error-message">${this._error}</span>
583
- <button class="retry-btn" @click=${()=>this._tryLoad()}>Retry</button>
370
+ `}_renderArrayObjectCard(e,n,r,i,a){return t`
371
+ <div class="array-card">
372
+ <div class="array-card-header">
373
+ <span class="array-card-index">#${n+1}</span>
374
+ <button class="array-card-remove" title="Remove"
375
+ @click=${()=>{let t=h(this._formState,e)??[];this._onFormFieldChange(e,t.filter((e,t)=>t!==n))}}
376
+ >\u00d7</button>
584
377
  </div>
585
- `:o`
586
- <div class="editor-layout">
587
- <nav class="section-sidebar" role="navigation" aria-label="Config sections">
588
- ${this._sections.map(e=>o`
589
- <div
590
- class="section-item"
591
- ?data-selected=${e===this._selectedSection}
592
- @click=${()=>this._onSectionClick(e)}
593
- >
594
- ${e.charAt(0).toUpperCase()+e.slice(1)}
595
- </div>
596
- `)}
597
- </nav>
598
-
599
- <div class="content-area" role="main">
600
- <div class="toolbar">
601
- <div class="mode-tabs">
602
- <button
603
- class="mode-btn"
604
- ?data-active=${this._mode==="form"}
605
- @click=${()=>this._onModeChange("form")}
606
- >Form</button>
607
- <button
608
- class="mode-btn"
609
- ?data-active=${this._mode==="yaml"}
610
- @click=${()=>this._onModeChange("yaml")}
611
- >YAML</button>
612
- <button
613
- class="mode-btn"
614
- ?data-active=${this._mode==="schema"}
615
- @click=${()=>this._onModeChange("schema")}
616
- >Schema</button>
617
- </div>
618
-
619
- <div class="action-buttons">
620
- <button
621
- class="diff-btn"
622
- ?data-active=${this._showDiff}
623
- @click=${()=>{this._showDiff=!this._showDiff}}
624
- >Show Diff</button>
625
- ${this._rollbackSnapshot!==null?o`<button
626
- class="rollback-btn"
627
- @click=${()=>{this._confirmRollback=!0}}
628
- >Rollback</button>`:g}
629
- <button
630
- class="secondary-btn"
631
- @click=${()=>this._onImportClick()}
632
- >Import</button>
633
- <button
634
- class="secondary-btn"
635
- @click=${()=>this._onExport()}
636
- >Export</button>
637
- <button
638
- class="apply-btn"
639
- ?disabled=${!this._dirty||this._applying}
640
- @click=${()=>this._onApply()}
641
- >
642
- ${this._applying?o`<span class="spinner"></span>`:g}
643
- Apply Changes
644
- </button>
645
- </div>
646
- </div>
647
-
648
- ${this._renderModeContent()}
649
-
650
- ${this._showDiff?o`
651
- <div class="diff-preview">
652
- <ic-diff-viewer
653
- .oldText=${this._savedYaml}
654
- .newText=${this._mode==="yaml"?this._yamlText:R(this._formState)}
655
- oldLabel="Current"
656
- newLabel="Pending Changes"
657
- ></ic-diff-viewer>
378
+ <div class="array-card-fields">
379
+ ${Object.entries(i).map(([i,o])=>{let s=`${m(i)}${a.includes(i)?` *`:``}`,c=r[i];if(i===`secret`)return t`
380
+ <div class="form-field">
381
+ <label class="form-label">${s}</label>
382
+ <input type="password" class="form-input"
383
+ .value=${typeof c==`string`?c:``}
384
+ placeholder="env:VAR_NAME or min 32 chars"
385
+ @input=${t=>{this._onArrayItemFieldChange(e,n,i,t.target.value)}}
386
+ />
658
387
  </div>
659
- `:g}
660
- </div>
661
- </div>
662
-
663
- <input
664
- class="hidden-input"
665
- type="file"
666
- accept=".yaml,.yml"
667
- @change=${e=>this._onImportFile(e)}
668
- />
669
-
670
- <ic-confirm-dialog
671
- .open=${this._confirmRollback}
672
- title="Rollback Configuration"
673
- message="Restore previous configuration? This will revert all sections to the state before your last apply."
674
- confirmLabel="Rollback"
675
- @confirm=${()=>this._onRollback()}
676
- @cancel=${()=>{this._confirmRollback=!1}}
677
- ></ic-confirm-dialog>
678
- `}_renderGatewayTab(){if(this._gatewayLoading)return o`<div class="state-container"><ic-loading size="lg"></ic-loading></div>`;if(this._gatewayError)return o`
679
- <div class="error-container">
680
- <span class="error-message">${this._gatewayError}</span>
681
- <button class="retry-btn" @click=${()=>this._loadGatewayConfig()}>Retry</button>
682
- </div>
683
- `;if(!this._gatewayConfig)return o`<ic-empty-state icon="config" message="No gateway configuration" description="Gateway config not available."></ic-empty-state>`;const e=this._gatewayConfig,t=e.cors?.origins??[],r=e.tokens??[];return o`
684
- <div class="gateway-form">
685
- <div class="gateway-field">
686
- <ic-toggle
687
- label="Gateway Enabled"
688
- .checked=${e.enabled??!1}
689
- @change=${i=>this._patchGateway("enabled",i.detail)}
690
- ></ic-toggle>
691
- </div>
692
-
693
- <div class="gateway-field">
694
- <label class="gateway-label">Host</label>
695
- <input
696
- class="gateway-input"
697
- type="text"
698
- .value=${e.host??"0.0.0.0"}
699
- @change=${i=>this._patchGateway("host",i.target.value)}
700
- />
701
- </div>
702
-
703
- <div class="gateway-field">
704
- <label class="gateway-label">Port</label>
705
- <input
706
- class="gateway-input"
707
- type="number"
708
- .value=${String(e.port??3e3)}
709
- @change=${i=>{const a=parseInt(i.target.value,10);isNaN(a)||this._patchGateway("port",a)}}
710
- />
711
- </div>
712
-
713
- <div class="gateway-field">
714
- <ic-array-editor
715
- label="CORS Origins"
716
- .items=${t.map(String)}
717
- placeholder="https://example.com"
718
- @change=${i=>this._patchGateway("cors",{...e.cors,origins:i.detail})}
719
- ></ic-array-editor>
720
- </div>
721
-
722
- <div class="gateway-tokens">
723
- <div class="gateway-tokens-label">API Tokens (${r.length})</div>
724
- ${r.length>0?o`
725
- <div class="gateway-tokens-list">
726
- ${r.map(i=>o`
727
- <div class="gateway-token-entry">
728
- <span class="gateway-token-id">${i.id}</span>
729
- ${i.scopes&&i.scopes.length>0?i.scopes.map(a=>o`<ic-tag variant="info">${a}</ic-tag>`):o`<ic-tag variant="default">no scopes</ic-tag>`}
730
- </div>
731
- `)}
388
+ `;if(o.type===`array`&&o.items?.type===`string`){if(i===`scopes`){let r=new Set((c??[]).map(String));return t`
389
+ <div class="form-field">
390
+ <label class="form-label">${s}</label>
391
+ <div class="scope-chips">
392
+ ${p.map(a=>t`
393
+ <button class="scope-chip" ?data-active=${r.has(a)}
394
+ @click=${()=>{let t=new Set(r);t.has(a)?t.delete(a):t.add(a),this._onArrayItemFieldChange(e,n,i,[...t])}}
395
+ >${a}</button>
396
+ `)}
397
+ </div>
398
+ </div>
399
+ `}return t`
400
+ <div class="form-field">
401
+ <ic-array-editor label=${s} .items=${(c??[]).map(String)} placeholder="Add..."
402
+ @change=${t=>{this._onArrayItemFieldChange(e,n,i,t.detail)}}
403
+ ></ic-array-editor>
732
404
  </div>
733
- `:o`<div style="font-size:var(--ic-text-sm);color:var(--ic-text-dim)">No tokens configured</div>`}
734
- <a class="gateway-tokens-link" href="#security">Manage tokens in Security &rarr;</a>
735
- </div>
736
- </div>
737
- `}_renderWizardTab(){return o`
738
- <div class="wizard-content">
739
- <div class="wizard-description">
740
- The setup wizard guides you through initial Comis configuration
741
- including provider keys, agent creation, channel setup, and
742
- security settings.
743
- </div>
744
- <button
745
- class="wizard-btn"
746
- @click=${()=>{window.location.hash="#setup"}}
747
- >Launch Setup Wizard</button>
748
- </div>
749
- `}render(){return o`
750
- <div class="view-header">
751
- <div class="view-title">Settings</div>
752
- </div>
753
-
754
- <ic-tabs
755
- .tabs=${ee}
756
- .activeTab=${this._activeTab}
757
- @tab-change=${this._onTabChange}
758
- >
759
- <div slot="editor">${this._renderEditorTab()}</div>
760
- <div slot="gateway">${this._renderGatewayTab()}</div>
761
- <div slot="history">${this._renderHistoryTab()}</div>
762
- <div slot="wizard">${this._renderWizardTab()}</div>
763
- </ic-tabs>
764
-
765
- <ic-confirm-dialog
766
- .open=${this._confirmRollbackSha!==null}
767
- title="Rollback Configuration"
768
- message="Restore config to this version? The daemon will restart to apply changes."
769
- variant="danger"
770
- confirmLabel="Rollback"
771
- @confirm=${()=>this._onHistoryRollback()}
772
- @cancel=${()=>{this._confirmRollbackSha=null}}
773
- ></ic-confirm-dialog>
774
- `}};f.styles=[N,P,I`
405
+ `}return o.type===`string`?t`
406
+ <div class="form-field">
407
+ <label class="form-label">${s}</label>
408
+ <input type="text" class="form-input" .value=${String(c??``)}
409
+ @input=${t=>{this._onArrayItemFieldChange(e,n,i,t.target.value)}}
410
+ />
411
+ </div>
412
+ `:o.type===`number`||o.type===`integer`?t`
413
+ <div class="form-field">
414
+ <label class="form-label">${s}</label>
415
+ <input type="number" class="form-input" .value=${String(c??0)}
416
+ @input=${t=>{this._onArrayItemFieldChange(e,n,i,Number(t.target.value))}}
417
+ />
418
+ </div>
419
+ `:o.type===`boolean`?t`
420
+ <div class="form-field">
421
+ <label class="form-label">${s}</label>
422
+ <ic-toggle ?checked=${!!c}
423
+ @change=${t=>{this._onArrayItemFieldChange(e,n,i,t.detail)}}
424
+ ></ic-toggle>
425
+ </div>
426
+ `:t`
427
+ <div class="form-field">
428
+ <label class="form-label">${s}</label>
429
+ <input type="text" class="form-input" .value=${JSON.stringify(c??``)}
430
+ @input=${t=>{try{this._onArrayItemFieldChange(e,n,i,JSON.parse(t.target.value))}catch{}}}
431
+ />
432
+ </div>
433
+ `})}
434
+ </div>
435
+ </div>
436
+ `}_renderObjectField(e,n,r,i){let a=this._expandedFormPaths.has(e),o=i.properties??{},s=i.required??[];return t`
437
+ <fieldset class="form-fieldset">
438
+ <legend class="form-fieldset-legend" @click=${()=>this._toggleFormFieldset(e)}>
439
+ <span class="arrow" ?data-expanded=${a}>\u25B6</span>
440
+ ${n}
441
+ </legend>
442
+ ${a?t`
443
+ <div class="form-fieldset-content">
444
+ ${Object.entries(o).map(([t,n])=>this._renderSchemaField(`${e}.${t}`,`${m(t)}${s.includes(t)?` *`:``}`,h(r??{},t),n))}
445
+ </div>
446
+ `:l}
447
+ </fieldset>
448
+ `}_renderJsonFallback(e,n,r,i){let a=JSON.stringify(r??null,null,2);return t`
449
+ <div class="form-field">
450
+ <label class="form-label">${n}</label>
451
+ ${i.description?t`<span class="form-description">${i.description}</span>`:l}
452
+ <textarea class="json-fallback-textarea" .value=${a}
453
+ @input=${t=>{let n=t.target.value;try{let t=JSON.parse(n);this._onFormFieldChange(e,t);let r={...this._formErrors};delete r[e],this._formErrors=r}catch{this._formErrors={...this._formErrors,[e]:`Invalid JSON`}}}}
454
+ ></textarea>
455
+ ${this._formErrors[e]?t`<span class="form-error">${this._formErrors[e]}</span>`:l}
456
+ </div>
457
+ `}_renderSchemaField(e,t,n,r){if(r.enum&&r.enum.length>0)return this._renderEnumField(e,t,n,r);let i=r.anyOf??r.oneOf;if(i&&i.length>=2){let r=i.filter(e=>e.type!==`null`);if(r.length===1)return this._renderSchemaField(e,t,n,r[0]);if(n==null||typeof n==`string`){let i=r.find(e=>e.type===`string`);if(i)return this._renderStringField(e,t,String(n??``),i)}}if(r.anyOf||r.oneOf||r.allOf)return this._renderJsonFallback(e,t,n,r);switch(r.type){case`string`:return this._renderStringField(e,t,String(n??``),r);case`number`:case`integer`:return this._renderNumberField(e,t,Number(n??0),r);case`boolean`:return this._renderBooleanField(e,t,!!n,r);case`array`:return this._renderArrayField(e,t,n??[],r);case`object`:return this._renderObjectField(e,t,n??{},r);default:return this._renderJsonFallback(e,t,n,r)}}render(){let e=this.schema;if(e&&!e.properties&&e.additionalProperties&&typeof e.additionalProperties==`object`){let n=e.additionalProperties,r=Object.keys(this._formState);return r.length===0?t`<ic-empty-state icon="config" message="No entries" description="This section has no configured entries."></ic-empty-state>`:t`
458
+ ${r.map(e=>{let t=this._formState[e]??{};return this._renderObjectField(e,m(e),t,n)})}
459
+ `}if(!e||!e.properties)return t`
460
+ ${Object.entries(this._formState).map(([e,t])=>this._renderSchemaField(e,m(e),t,{type:typeof t==`boolean`?`boolean`:typeof t==`number`?`number`:`string`}))}
461
+ `;let n=e.properties,r=e.required??[];return t`
462
+ ${Object.entries(n).map(([e,t])=>this._renderSchemaField(e,`${m(e)}${r.includes(e)?` *`:``}`,h(this._formState,e),t))}
463
+ `}};c([s({attribute:!1})],_.prototype,`schema`,void 0),c([s({attribute:!1})],_.prototype,`config`,void 0),c([s({type:String})],_.prototype,`sectionKey`,void 0),c([a()],_.prototype,`_formState`,void 0),c([a()],_.prototype,`_formErrors`,void 0),c([a()],_.prototype,`_expandedFormPaths`,void 0),_=c([e(`ic-schema-form`)],_);function v(e,t=0){let n=` `.repeat(t);if(e==null)return`null`;if(typeof e==`boolean`)return e?`true`:`false`;if(typeof e==`number`)return String(e);if(typeof e==`string`)return e===``||e.includes(`:`)||e.includes(`#`)||e.includes(`
464
+ `)||e.includes(`"`)||e.includes(`'`)||e.startsWith(` `)||e.endsWith(` `)||e===`true`||e===`false`||e===`null`||/^\d+(\.\d+)?$/.test(e)?`"${e.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`)}"`:e;if(Array.isArray(e)){if(e.length===0)return`[]`;let r=[];for(let i of e)if(typeof i==`object`&&i&&!Array.isArray(i)){let e=Object.entries(i);if(e.length>0){let[i,a]=e[0];r.push(`${n}- ${i}: ${v(a,0)}`);for(let i=1;i<e.length;i++){let[a,o]=e[i];r.push(`${n} ${a}: ${v(o,t+2)}`)}}else r.push(`${n}- {}`)}else r.push(`${n}- ${v(i,0)}`);return`
465
+ `+r.join(`
466
+ `)}if(typeof e==`object`){let r=Object.entries(e);if(r.length===0)return`{}`;let i=[];for(let[e,a]of r)typeof a==`object`&&a&&!Array.isArray(a)&&Object.keys(a).length>0?(i.push(`${n}${e}:`),i.push(v(a,t+1))):Array.isArray(a)&&a.length>0?i.push(`${n}${e}:${v(a,t+1)}`):i.push(`${n}${e}: ${v(a,0)}`);return i.join(`
467
+ `)}return String(e)}function y(e){try{return{data:S(e.split(`
468
+ `),0,0).value,error:null}}catch(e){return{data:null,error:e instanceof Error?e.message:`Parse error`}}}function b(e){let t=e.match(/^( *)/);return t?t[1].length:0}function x(e){let t=e.trim();if(t===``||t===`null`||t===`~`)return null;if(t===`true`)return!0;if(t===`false`)return!1;if(t===`[]`)return[];if(t===`{}`)return{};if(t.startsWith(`"`)&&t.endsWith(`"`)||t.startsWith(`'`)&&t.endsWith(`'`))return t.slice(1,-1).replace(/\\"/g,`"`).replace(/\\\\/g,`\\`);let n=Number(t);return!isNaN(n)&&t!==``?n:t}function S(e,t,n){let r=t;for(;r<e.length&&e[r].trim()===``;)r++;if(r>=e.length)return{value:null,nextLine:r};let i=e[r],a=b(i),o=i.trim();if(o.startsWith(`- `)){let t=[];for(;r<e.length;){let n=e[r];if(n.trim()===``){r++;continue}let i=b(n);if(i<a||i!==a||!n.trim().startsWith(`- `))break;let o=n.trim().slice(2),s=o.match(/^([^:]+):\s*(.*)/);if(s&&!o.startsWith(`"`)&&!o.startsWith(`'`)){let n={};n[s[1].trim()]=x(s[2]),r++;let i=a+2;for(;r<e.length;){let t=e[r];if(t.trim()===``){r++;continue}let a=b(t);if(a<i)break;if(a===i&&!t.trim().startsWith(`- `)){let a=t.trim().match(/^([^:]+):\s*(.*)/);if(a){let t=a[1].trim(),o=a[2];if(o===``||o===void 0){let a=S(e,r+1,i+2);n[t]=a.value,r=a.nextLine}else n[t]=x(o),r++}else break}else break}t.push(n)}else t.push(x(o)),r++}return{value:t,nextLine:r}}if(o.includes(`:`)){let t={};for(;r<e.length;){let n=e[r];if(n.trim()===``){r++;continue}let i=b(n);if(i<a||i!==a)break;let o=n.indexOf(`:`);if(o===-1)break;let s=n.slice(0,o).trim(),c=n.slice(o+1).trim();if(c===``||c===void 0){r++;let n=S(e,r,a+2);t[s]=n.value,r=n.nextLine}else t[s]=x(c),r++}return{value:t,nextLine:r}}return{value:x(o),nextLine:r+1}}var C=[{id:`editor`,label:`YAML Editor`},{id:`gateway`,label:`Gateway`},{id:`history`,label:`History`},{id:`wizard`,label:`Setup Wizard`}],w=v;function T(e,t,n){let r=t.split(`.`);if(r.length===1)return{...e,[r[0]]:n};let[i,...a]=r,o=e[i]??{};return{...e,[i]:T(o,a.join(`.`),n)}}var E=class extends r{constructor(...e){super(...e),this.rpcClient=null,this._activeTab=`editor`,this._loadState=`loading`,this._error=``,this._sections=[],this._selectedSection=``,this._mode=`form`,this._configData={},this._schemaData={},this._yamlText=``,this._yamlErrors=[],this._formState={},this._formErrors={},this._dirty=!1,this._applying=!1,this._expandedPaths=new Set,this._showDiff=!1,this._savedYaml=``,this._rollbackSnapshot=null,this._confirmRollback=!1,this._gatewayConfig=null,this._gatewayLoading=!1,this._gatewayError=``,this._historyEntries=[],this._historyLoading=!1,this._historyError=``,this._selectedSha=null,this._diffText=``,this._diffLoading=!1,this._confirmRollbackSha=null,this._gcRunning=!1,this._historyReloadTimer=null,this._yamlDebounceTimer=null,this._rpcStatusUnsub=null,this._dataLoaded=!1,this._configPatchedHandler=null}static{this.styles=[o,i,n`
775
469
  :host {
776
470
  display: block;
777
471
  }
@@ -1371,4 +1065,310 @@ import{s as N,f as P,i as I,n as x,r as p,a as j,b as o,t as M,A as g,I as y}fro
1371
1065
  .history-rollback-link:hover {
1372
1066
  text-decoration: underline;
1373
1067
  }
1374
- `];h([x({attribute:!1})],f.prototype,"rpcClient",2);h([p()],f.prototype,"_activeTab",2);h([p()],f.prototype,"_loadState",2);h([p()],f.prototype,"_error",2);h([p()],f.prototype,"_sections",2);h([p()],f.prototype,"_selectedSection",2);h([p()],f.prototype,"_mode",2);h([p()],f.prototype,"_configData",2);h([p()],f.prototype,"_schemaData",2);h([p()],f.prototype,"_yamlText",2);h([p()],f.prototype,"_yamlErrors",2);h([p()],f.prototype,"_formState",2);h([p()],f.prototype,"_formErrors",2);h([p()],f.prototype,"_dirty",2);h([p()],f.prototype,"_applying",2);h([p()],f.prototype,"_expandedPaths",2);h([p()],f.prototype,"_showDiff",2);h([p()],f.prototype,"_savedYaml",2);h([p()],f.prototype,"_rollbackSnapshot",2);h([p()],f.prototype,"_confirmRollback",2);h([p()],f.prototype,"_gatewayConfig",2);h([p()],f.prototype,"_gatewayLoading",2);h([p()],f.prototype,"_gatewayError",2);h([p()],f.prototype,"_historyEntries",2);h([p()],f.prototype,"_historyLoading",2);h([p()],f.prototype,"_historyError",2);h([p()],f.prototype,"_selectedSha",2);h([p()],f.prototype,"_diffText",2);h([p()],f.prototype,"_diffLoading",2);h([p()],f.prototype,"_confirmRollbackSha",2);h([p()],f.prototype,"_gcRunning",2);f=h([M("ic-config-editor")],f);export{f as IcConfigEditor,L as parseYaml,$ as serializeToYaml};
1068
+ `]}connectedCallback(){super.connectedCallback(),this._configPatchedHandler=()=>{this._dataLoaded&&!this._dirty&&this._tryLoad(),this._activeTab===`history`&&this._scheduleHistoryReload()},document.addEventListener(`config:patched`,this._configPatchedHandler)}_scheduleHistoryReload(){this._historyReloadTimer!==null&&clearTimeout(this._historyReloadTimer),this._historyReloadTimer=setTimeout(()=>{this._historyReloadTimer=null,this._loadHistory()},300)}disconnectedCallback(){super.disconnectedCallback(),this._yamlDebounceTimer!==null&&clearTimeout(this._yamlDebounceTimer),this._historyReloadTimer!==null&&clearTimeout(this._historyReloadTimer),this._rpcStatusUnsub?.(),this._rpcStatusUnsub=null,this._configPatchedHandler&&=(document.removeEventListener(`config:patched`,this._configPatchedHandler),null)}updated(e){e.has(`rpcClient`)&&this.rpcClient&&this._tryLoad()}_tryLoad(){this.rpcClient&&(this._rpcStatusUnsub?.(),this.rpcClient.status===`connected`?this._loadData():this._rpcStatusUnsub=this.rpcClient.onStatusChange(e=>{e===`connected`&&!this._dataLoaded&&this._loadData()}))}async _loadData(){if(this.rpcClient){this._loadState=`loading`,this._error=``;try{let e=await this.rpcClient.call(`config.read`);this._sections=e.sections,this._configData=e.config,this._sections.length>0&&!this._selectedSection&&(this._selectedSection=this._sections[0],this._loadSectionState()),this._loadState=`loaded`,this._dataLoaded=!0,this.rpcClient.call(`config.schema`).then(e=>{let t=e.schema;this._schemaData=t.properties??t}).catch(()=>{})}catch(e){this._error=e instanceof Error?e.message:`Failed to load configuration`,this._loadState=`error`}}}_loadSectionState(){let e=this._configData[this._selectedSection]??{};this._formState=structuredClone(e),this._yamlText=w(e),this._savedYaml=this._yamlText,this._yamlErrors=[],this._formErrors={},this._dirty=!1,this._showDiff=!1,this._expandedPaths=new Set}_onSectionClick(e){e!==this._selectedSection&&(this._selectedSection=e,this._loadSectionState())}_onModeChange(e){if(e!==this._mode){if(this._mode===`form`&&e===`yaml`)this._yamlText=w(this._formState);else if(this._mode===`yaml`&&e===`form`&&this._yamlErrors.length===0){let e=y(this._yamlText);!e.error&&e.data&&typeof e.data==`object`&&(this._formState=e.data)}this._mode=e}}_renderFormMode(){return t`
1069
+ <ic-schema-form
1070
+ .schema=${this._schemaData[this._selectedSection]??{}}
1071
+ .config=${this._formState}
1072
+ .sectionKey=${this._selectedSection}
1073
+ @field-change=${e=>{let{path:t,value:n,formState:r}=e.detail;this._formState=r??T(this._formState,t,n),this._dirty=!0;let i={...this._formErrors};delete i[t],this._formErrors=i}}
1074
+ ></ic-schema-form>
1075
+ `}_onYamlInput(e){this._yamlText=e.target.value,this._dirty=!0,this._yamlDebounceTimer!==null&&clearTimeout(this._yamlDebounceTimer),this._yamlDebounceTimer=setTimeout(()=>{this._validateYaml()},500)}_validateYaml(){let e=y(this._yamlText);e.error?this._yamlErrors=[e.error]:this._yamlErrors=[]}_renderYamlMode(){return t`
1076
+ <div class="yaml-editor">
1077
+ <textarea
1078
+ class="yaml-textarea"
1079
+ .value=${this._yamlText}
1080
+ @input=${e=>this._onYamlInput(e)}
1081
+ spellcheck="false"
1082
+ aria-label="YAML editor"
1083
+ ></textarea>
1084
+ ${this._yamlErrors.length>0?t`
1085
+ <div class="yaml-validation yaml-validation--error">
1086
+ ${this._yamlErrors.map(e=>t`<div>${e}</div>`)}
1087
+ </div>
1088
+ `:t`
1089
+ <div class="yaml-validation yaml-validation--valid">
1090
+ Valid configuration
1091
+ </div>
1092
+ `}
1093
+ </div>
1094
+ `}_toggleSchemaPath(e){let t=new Set(this._expandedPaths);t.has(e)?t.delete(e):t.add(e),this._expandedPaths=t}_renderSchemaTreeNode(e,n,r,i,a){let o=n.type===`object`&&n.properties&&Object.keys(n.properties).length>0,s=this._expandedPaths.has(r),c=[];return a&&c.push(`required`),n.minimum!==void 0&&c.push(`min: ${n.minimum}`),n.maximum!==void 0&&c.push(`max: ${n.maximum}`),n.minLength!==void 0&&c.push(`minLen: ${n.minLength}`),n.maxLength!==void 0&&c.push(`maxLen: ${n.maxLength}`),n.enum&&c.push(`enum: [${n.enum.join(`, `)}]`),n.pattern&&c.push(`pattern: ${n.pattern}`),n.default!==void 0&&c.push(`default: ${JSON.stringify(n.default)}`),t`
1095
+ <div style="padding-left: ${i*1.5}rem">
1096
+ <div class="schema-row">
1097
+ <span
1098
+ class="schema-key"
1099
+ @click=${o?()=>this._toggleSchemaPath(r):l}
1100
+ >
1101
+ ${o?t`<span class="arrow" ?data-expanded=${s}>\u25B6</span>`:l}
1102
+ ${e}${a?t`<span class="required-marker">*</span>`:l}
1103
+ </span>
1104
+ <ic-tag variant="info">${n.type??`any`}</ic-tag>
1105
+ ${n.description?t`<span class="schema-desc">${n.description}</span>`:l}
1106
+ ${c.length>0?t`<span class="schema-constraints">${c.join(`, `)}</span>`:l}
1107
+ </div>
1108
+ ${o&&s?t`
1109
+ <div class="schema-children">
1110
+ ${Object.entries(n.properties).map(([e,t])=>this._renderSchemaTreeNode(e,t,`${r}.${e}`,i+1,(n.required??[]).includes(e)))}
1111
+ </div>
1112
+ `:l}
1113
+ </div>
1114
+ `}_renderSchemaMode(){let e=this._schemaData[this._selectedSection];if(e&&!e.properties&&e.additionalProperties&&typeof e.additionalProperties==`object`){let n=e.additionalProperties;if(!n.properties)return t`<ic-empty-state icon="config" message="No schema available" description="Schema definition not found for this section."></ic-empty-state>`;let r=n.required??[];return t`
1115
+ <div class="schema-tree">
1116
+ <div class="schema-note" style="padding:8px 0;opacity:0.7;font-style:italic">Record&lt;string, entry&gt; - each entry has:</div>
1117
+ ${Object.entries(n.properties).map(([e,t])=>this._renderSchemaTreeNode(e,t,e,0,r.includes(e)))}
1118
+ </div>
1119
+ `}if(!e?.properties)return t`<ic-empty-state icon="config" message="No schema available" description="Schema definition not found for this section."></ic-empty-state>`;let n=e.required??[];return t`
1120
+ <div class="schema-tree">
1121
+ ${Object.entries(e.properties).map(([e,t])=>this._renderSchemaTreeNode(e,t,e,0,n.includes(e)))}
1122
+ </div>
1123
+ `}async _onApply(){if(!this.rpcClient||!this._dirty)return;this._applying=!0;let e;if(this._mode===`yaml`){let t=y(this._yamlText);if(t.error){u.show(t.error,`error`),this._applying=!1;return}e=t.data}else e=this._formState;this._rollbackSnapshot=structuredClone(this._configData);try{await this.rpcClient.call(`config.apply`,{section:this._selectedSection,value:e}),u.show(`Configuration applied`,`success`),this._dirty=!1;let t=await this.rpcClient.call(`config.read`);this._configData=t.config,this._loadSectionState()}catch(e){let t=e instanceof Error?e.message:`Failed to apply configuration`;u.show(t,`error`),this._rollbackSnapshot=null}finally{this._applying=!1}}async _onRollback(){if(!(!this.rpcClient||!this._rollbackSnapshot))try{await this.rpcClient.call(`config.apply`,{config:this._rollbackSnapshot}),u.show(`Configuration rolled back`,`success`);let e=await this.rpcClient.call(`config.read`);this._configData=e.config,this._rollbackSnapshot=null,this._confirmRollback=!1,this._loadSectionState()}catch(e){let t=e instanceof Error?e.message:`Failed to rollback configuration`;u.show(t,`error`),this._confirmRollback=!1}}async _loadGatewayConfig(){if(this.rpcClient){this._gatewayLoading=!0,this._gatewayError=``;try{let e=await this.rpcClient.call(`config.read`,{section:`gateway`});this._gatewayConfig=e??{}}catch(e){this._gatewayError=e instanceof Error?e.message:`Failed to load gateway config`}finally{this._gatewayLoading=!1}}}async _patchGateway(e,t){if(this.rpcClient)try{await this.rpcClient.call(`config.patch`,{section:`gateway`,key:e,value:t}),this._gatewayConfig&&={...this._gatewayConfig,[e]:t},u.show(`Gateway updated`,`success`)}catch(e){let t=e instanceof Error?e.message:`Failed to update gateway`;u.show(t,`error`)}}_onTabChange(e){this._activeTab=e.detail,e.detail===`gateway`&&this._gatewayConfig===null&&this._loadGatewayConfig(),e.detail===`history`&&this._historyEntries.length===0&&!this._historyLoading&&this._loadHistory()}async _loadHistory(){if(this.rpcClient){this._historyLoading=!0,this._historyError=``;try{let e=await this.rpcClient.call(`config.history`,{limit:50});e.error?(this._historyEntries=[],this._historyError=e.error):this._historyEntries=e.entries}catch(e){this._historyError=e instanceof Error?e.message:`Failed to load history`}finally{this._historyLoading=!1}}}async _loadDiff(e){if(this.rpcClient){this._diffLoading=!0;try{let t=await this.rpcClient.call(`config.diff`,{sha:e});this._diffText=t.diff}catch(e){this._diffText=``;let t=e instanceof Error?e.message:`Failed to load diff`;u.show(t,`error`)}finally{this._diffLoading=!1}}}_onSelectVersion(e){if(e===this._selectedSha){this._selectedSha=null,this._diffText=``;return}this._selectedSha=e,this._loadDiff(e)}async _onHistoryRollback(){if(!(!this.rpcClient||!this._confirmRollbackSha))try{await this.rpcClient.call(`config.rollback`,{sha:this._confirmRollbackSha}),u.show(`Config rolled back. Daemon restarting...`,`success`),this._confirmRollbackSha=null}catch(e){let t=e instanceof Error?e.message:`Rollback failed`;u.show(t,`error`),this._confirmRollbackSha=null}}async _onGc(){if(!(!this.rpcClient||this._gcRunning)){this._gcRunning=!0;try{let e=(await this.rpcClient.call(`config.gc`)).squashed;u.show(e==null?`GC complete`:`GC complete: ${e} versions squashed`,`success`),this._loadHistory()}catch(e){let t=e instanceof Error?e.message:`GC failed`;u.show(t,`error`)}finally{this._gcRunning=!1}}}_renderDiffLine(e,n){let r=`diff-line--context`;return e.startsWith(`+`)?r=`diff-line--add`:e.startsWith(`-`)?r=`diff-line--remove`:e.startsWith(`@@`)&&(r=`diff-line--hunk`),t`<span class=${r}>${e}\n</span>`}_renderHistoryEntry(e,n){let r=e.sha===this._selectedSha,i=n===0,a=e.metadata.user||e.metadata.agent||`system`,o=new Date(e.timestamp).toLocaleString();return t`
1124
+ <div
1125
+ class="history-entry ${r?`history-entry--selected`:``}"
1126
+ @click=${()=>this._onSelectVersion(e.sha)}
1127
+ >
1128
+ <div class="history-entry-header">
1129
+ <ic-relative-time
1130
+ .timestamp=${new Date(e.timestamp).getTime()}
1131
+ title=${o}
1132
+ ></ic-relative-time>
1133
+ <code class="history-sha">${e.sha.slice(0,7)}</code>
1134
+ </div>
1135
+ <div class="history-entry-summary" title=${e.metadata.summary}>
1136
+ ${e.metadata.summary}
1137
+ </div>
1138
+ <div class="history-entry-meta">
1139
+ <ic-tag variant="default">${e.metadata.section}</ic-tag>
1140
+ <span class="history-author">${a}</span>
1141
+ ${i?l:t`<button
1142
+ class="history-rollback-link"
1143
+ @click=${t=>{t.stopPropagation(),this._confirmRollbackSha=e.sha}}
1144
+ >Rollback</button>`}
1145
+ </div>
1146
+ </div>
1147
+ `}_renderHistoryTab(){return this._historyLoading?t`<div class="state-container"><ic-loading size="lg"></ic-loading></div>`:this._historyError?t`
1148
+ <ic-empty-state
1149
+ icon="config"
1150
+ message="Version history unavailable"
1151
+ description=${this._historyError}
1152
+ ></ic-empty-state>
1153
+ `:this._historyEntries.length===0?t`
1154
+ <ic-empty-state
1155
+ icon="config"
1156
+ message="No version history"
1157
+ description="Config changes will appear here after the first edit."
1158
+ ></ic-empty-state>
1159
+ `:t`
1160
+ <div class="history-layout">
1161
+ <div class="history-timeline">
1162
+ ${this._historyEntries.map((e,t)=>this._renderHistoryEntry(e,t))}
1163
+ </div>
1164
+
1165
+ <div class="history-diff-panel">
1166
+ ${this._diffLoading?t`<div class="state-container"><ic-loading size="lg"></ic-loading></div>`:this._selectedSha&&this._diffText?t`<pre class="diff-unified">${this._diffText.split(`
1167
+ `).map((e,t)=>this._renderDiffLine(e,t))}</pre>`:this._selectedSha&&!this._diffText?t`<ic-empty-state icon="config" message="No changes" description="No changes between this version and current."></ic-empty-state>`:t`<ic-empty-state icon="config" message="Select a version" description="Select a version to view changes."></ic-empty-state>`}
1168
+ </div>
1169
+ </div>
1170
+
1171
+ <div class="history-actions">
1172
+ <button
1173
+ class="secondary-btn"
1174
+ ?disabled=${this._gcRunning}
1175
+ @click=${()=>this._onGc()}
1176
+ >
1177
+ ${this._gcRunning?t`<span class="spinner"></span> Running GC...`:`Run GC`}
1178
+ </button>
1179
+ </div>
1180
+ `}_onExport(){let e=w(this._configData),t=new Blob([e],{type:`text/yaml`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`comis-config.yaml`,r.click(),URL.revokeObjectURL(n)}_onImportClick(){(this.shadowRoot?.querySelector(`.hidden-input`))?.click()}_onImportFile(e){let t=e.target,n=t.files?.[0];if(!n)return;let r=new FileReader;r.onload=()=>{let e=r.result,t=y(e);if(t.error){u.show(`Import failed: ${t.error}`,`error`);return}t.data&&typeof t.data==`object`&&!Array.isArray(t.data)?(this._configData=t.data,this._loadSectionState(),this._dirty=!0,u.show(`Configuration imported`,`info`)):u.show(`Import failed: expected a YAML object`,`error`)},r.readAsText(n),t.value=``}_renderModeContent(){switch(this._mode){case`form`:return this._renderFormMode();case`yaml`:return this._renderYamlMode();case`schema`:return this._renderSchemaMode();default:return l}}_renderEditorTab(){return this._loadState===`loading`?t`<ic-skeleton-view variant="editor"></ic-skeleton-view>`:this._loadState===`error`?t`
1181
+ <div class="error-container">
1182
+ <span class="error-message">${this._error}</span>
1183
+ <button class="retry-btn" @click=${()=>this._tryLoad()}>Retry</button>
1184
+ </div>
1185
+ `:t`
1186
+ <div class="editor-layout">
1187
+ <nav class="section-sidebar" role="navigation" aria-label="Config sections">
1188
+ ${this._sections.map(e=>t`
1189
+ <div
1190
+ class="section-item"
1191
+ ?data-selected=${e===this._selectedSection}
1192
+ @click=${()=>this._onSectionClick(e)}
1193
+ >
1194
+ ${e.charAt(0).toUpperCase()+e.slice(1)}
1195
+ </div>
1196
+ `)}
1197
+ </nav>
1198
+
1199
+ <div class="content-area" role="main">
1200
+ <div class="toolbar">
1201
+ <div class="mode-tabs">
1202
+ <button
1203
+ class="mode-btn"
1204
+ ?data-active=${this._mode===`form`}
1205
+ @click=${()=>this._onModeChange(`form`)}
1206
+ >Form</button>
1207
+ <button
1208
+ class="mode-btn"
1209
+ ?data-active=${this._mode===`yaml`}
1210
+ @click=${()=>this._onModeChange(`yaml`)}
1211
+ >YAML</button>
1212
+ <button
1213
+ class="mode-btn"
1214
+ ?data-active=${this._mode===`schema`}
1215
+ @click=${()=>this._onModeChange(`schema`)}
1216
+ >Schema</button>
1217
+ </div>
1218
+
1219
+ <div class="action-buttons">
1220
+ <button
1221
+ class="diff-btn"
1222
+ ?data-active=${this._showDiff}
1223
+ @click=${()=>{this._showDiff=!this._showDiff}}
1224
+ >Show Diff</button>
1225
+ ${this._rollbackSnapshot===null?l:t`<button
1226
+ class="rollback-btn"
1227
+ @click=${()=>{this._confirmRollback=!0}}
1228
+ >Rollback</button>`}
1229
+ <button
1230
+ class="secondary-btn"
1231
+ @click=${()=>this._onImportClick()}
1232
+ >Import</button>
1233
+ <button
1234
+ class="secondary-btn"
1235
+ @click=${()=>this._onExport()}
1236
+ >Export</button>
1237
+ <button
1238
+ class="apply-btn"
1239
+ ?disabled=${!this._dirty||this._applying}
1240
+ @click=${()=>this._onApply()}
1241
+ >
1242
+ ${this._applying?t`<span class="spinner"></span>`:l}
1243
+ Apply Changes
1244
+ </button>
1245
+ </div>
1246
+ </div>
1247
+
1248
+ ${this._renderModeContent()}
1249
+
1250
+ ${this._showDiff?t`
1251
+ <div class="diff-preview">
1252
+ <ic-diff-viewer
1253
+ .oldText=${this._savedYaml}
1254
+ .newText=${this._mode===`yaml`?this._yamlText:w(this._formState)}
1255
+ oldLabel="Current"
1256
+ newLabel="Pending Changes"
1257
+ ></ic-diff-viewer>
1258
+ </div>
1259
+ `:l}
1260
+ </div>
1261
+ </div>
1262
+
1263
+ <input
1264
+ class="hidden-input"
1265
+ type="file"
1266
+ accept=".yaml,.yml"
1267
+ @change=${e=>this._onImportFile(e)}
1268
+ />
1269
+
1270
+ <ic-confirm-dialog
1271
+ .open=${this._confirmRollback}
1272
+ title="Rollback Configuration"
1273
+ message="Restore previous configuration? This will revert all sections to the state before your last apply."
1274
+ confirmLabel="Rollback"
1275
+ @confirm=${()=>this._onRollback()}
1276
+ @cancel=${()=>{this._confirmRollback=!1}}
1277
+ ></ic-confirm-dialog>
1278
+ `}_renderGatewayTab(){if(this._gatewayLoading)return t`<div class="state-container"><ic-loading size="lg"></ic-loading></div>`;if(this._gatewayError)return t`
1279
+ <div class="error-container">
1280
+ <span class="error-message">${this._gatewayError}</span>
1281
+ <button class="retry-btn" @click=${()=>this._loadGatewayConfig()}>Retry</button>
1282
+ </div>
1283
+ `;if(!this._gatewayConfig)return t`<ic-empty-state icon="config" message="No gateway configuration" description="Gateway config not available."></ic-empty-state>`;let e=this._gatewayConfig,n=e.cors?.origins??[],r=e.tokens??[];return t`
1284
+ <div class="gateway-form">
1285
+ <div class="gateway-field">
1286
+ <ic-toggle
1287
+ label="Gateway Enabled"
1288
+ .checked=${e.enabled??!1}
1289
+ @change=${e=>this._patchGateway(`enabled`,e.detail)}
1290
+ ></ic-toggle>
1291
+ </div>
1292
+
1293
+ <div class="gateway-field">
1294
+ <label class="gateway-label">Host</label>
1295
+ <input
1296
+ class="gateway-input"
1297
+ type="text"
1298
+ .value=${e.host??`0.0.0.0`}
1299
+ @change=${e=>this._patchGateway(`host`,e.target.value)}
1300
+ />
1301
+ </div>
1302
+
1303
+ <div class="gateway-field">
1304
+ <label class="gateway-label">Port</label>
1305
+ <input
1306
+ class="gateway-input"
1307
+ type="number"
1308
+ .value=${String(e.port??3e3)}
1309
+ @change=${e=>{let t=parseInt(e.target.value,10);isNaN(t)||this._patchGateway(`port`,t)}}
1310
+ />
1311
+ </div>
1312
+
1313
+ <div class="gateway-field">
1314
+ <ic-array-editor
1315
+ label="CORS Origins"
1316
+ .items=${n.map(String)}
1317
+ placeholder="https://example.com"
1318
+ @change=${t=>this._patchGateway(`cors`,{...e.cors,origins:t.detail})}
1319
+ ></ic-array-editor>
1320
+ </div>
1321
+
1322
+ <div class="gateway-tokens">
1323
+ <div class="gateway-tokens-label">API Tokens (${r.length})</div>
1324
+ ${r.length>0?t`
1325
+ <div class="gateway-tokens-list">
1326
+ ${r.map(e=>t`
1327
+ <div class="gateway-token-entry">
1328
+ <span class="gateway-token-id">${e.id}</span>
1329
+ ${e.scopes&&e.scopes.length>0?e.scopes.map(e=>t`<ic-tag variant="info">${e}</ic-tag>`):t`<ic-tag variant="default">no scopes</ic-tag>`}
1330
+ </div>
1331
+ `)}
1332
+ </div>
1333
+ `:t`<div style="font-size:var(--ic-text-sm);color:var(--ic-text-dim)">No tokens configured</div>`}
1334
+ <a class="gateway-tokens-link" href="#security">Manage tokens in Security &rarr;</a>
1335
+ </div>
1336
+ </div>
1337
+ `}_renderWizardTab(){return t`
1338
+ <div class="wizard-content">
1339
+ <div class="wizard-description">
1340
+ The setup wizard guides you through initial Comis configuration
1341
+ including provider keys, agent creation, channel setup, and
1342
+ security settings.
1343
+ </div>
1344
+ <button
1345
+ class="wizard-btn"
1346
+ @click=${()=>{window.location.hash=`#setup`}}
1347
+ >Launch Setup Wizard</button>
1348
+ </div>
1349
+ `}render(){return t`
1350
+ <div class="view-header">
1351
+ <div class="view-title">Settings</div>
1352
+ </div>
1353
+
1354
+ <ic-tabs
1355
+ .tabs=${C}
1356
+ .activeTab=${this._activeTab}
1357
+ @tab-change=${this._onTabChange}
1358
+ >
1359
+ <div slot="editor">${this._renderEditorTab()}</div>
1360
+ <div slot="gateway">${this._renderGatewayTab()}</div>
1361
+ <div slot="history">${this._renderHistoryTab()}</div>
1362
+ <div slot="wizard">${this._renderWizardTab()}</div>
1363
+ </ic-tabs>
1364
+
1365
+ <ic-confirm-dialog
1366
+ .open=${this._confirmRollbackSha!==null}
1367
+ title="Rollback Configuration"
1368
+ message="Restore config to this version? The daemon will restart to apply changes."
1369
+ variant="danger"
1370
+ confirmLabel="Rollback"
1371
+ @confirm=${()=>this._onHistoryRollback()}
1372
+ @cancel=${()=>{this._confirmRollbackSha=null}}
1373
+ ></ic-confirm-dialog>
1374
+ `}};c([s({attribute:!1})],E.prototype,`rpcClient`,void 0),c([a()],E.prototype,`_activeTab`,void 0),c([a()],E.prototype,`_loadState`,void 0),c([a()],E.prototype,`_error`,void 0),c([a()],E.prototype,`_sections`,void 0),c([a()],E.prototype,`_selectedSection`,void 0),c([a()],E.prototype,`_mode`,void 0),c([a()],E.prototype,`_configData`,void 0),c([a()],E.prototype,`_schemaData`,void 0),c([a()],E.prototype,`_yamlText`,void 0),c([a()],E.prototype,`_yamlErrors`,void 0),c([a()],E.prototype,`_formState`,void 0),c([a()],E.prototype,`_formErrors`,void 0),c([a()],E.prototype,`_dirty`,void 0),c([a()],E.prototype,`_applying`,void 0),c([a()],E.prototype,`_expandedPaths`,void 0),c([a()],E.prototype,`_showDiff`,void 0),c([a()],E.prototype,`_savedYaml`,void 0),c([a()],E.prototype,`_rollbackSnapshot`,void 0),c([a()],E.prototype,`_confirmRollback`,void 0),c([a()],E.prototype,`_gatewayConfig`,void 0),c([a()],E.prototype,`_gatewayLoading`,void 0),c([a()],E.prototype,`_gatewayError`,void 0),c([a()],E.prototype,`_historyEntries`,void 0),c([a()],E.prototype,`_historyLoading`,void 0),c([a()],E.prototype,`_historyError`,void 0),c([a()],E.prototype,`_selectedSha`,void 0),c([a()],E.prototype,`_diffText`,void 0),c([a()],E.prototype,`_diffLoading`,void 0),c([a()],E.prototype,`_confirmRollbackSha`,void 0),c([a()],E.prototype,`_gcRunning`,void 0),E=c([e(`ic-config-editor`)],E);export{E as IcConfigEditor,y as parseYaml,v as serializeToYaml};