@xopcai/xopcbot 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -52
- package/README.zh-CN.md +56 -49
- package/dist/agent/__tests__/media-processing.test.d.ts +6 -0
- package/dist/agent/__tests__/media-processing.test.js +385 -0
- package/dist/agent/__tests__/media-processing.test.js.map +1 -0
- package/dist/agent/fallback/__tests__/index.test.js +16 -5
- package/dist/agent/fallback/__tests__/index.test.js.map +1 -1
- package/dist/agent/fallback/candidates.d.ts +2 -4
- package/dist/agent/fallback/candidates.js +19 -26
- package/dist/agent/fallback/candidates.js.map +1 -1
- package/dist/agent/helpers.d.ts +1 -0
- package/dist/agent/helpers.js.map +1 -1
- package/dist/agent/index.d.ts +6 -1
- package/dist/agent/index.js +10 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/models/compat.d.ts +35 -0
- package/dist/agent/models/compat.js +110 -0
- package/dist/agent/models/compat.js.map +1 -0
- package/dist/agent/models/fallback.d.ts +38 -0
- package/dist/agent/models/fallback.js +133 -0
- package/dist/agent/models/fallback.js.map +1 -0
- package/dist/agent/models/index.d.ts +10 -0
- package/dist/agent/models/index.js +11 -0
- package/dist/agent/models/index.js.map +1 -0
- package/dist/agent/{model-manager.d.ts → models/manager.d.ts} +2 -8
- package/dist/agent/{model-manager.js → models/manager.js} +38 -24
- package/dist/agent/models/manager.js.map +1 -0
- package/dist/agent/models/scan.d.ts +46 -0
- package/dist/agent/models/scan.js +177 -0
- package/dist/agent/models/scan.js.map +1 -0
- package/dist/agent/models/selection.d.ts +44 -0
- package/dist/agent/models/selection.js +141 -0
- package/dist/agent/models/selection.js.map +1 -0
- package/dist/agent/prompt/index.js +1 -1
- package/dist/agent/prompt/index.js.map +1 -1
- package/dist/agent/service.js +34 -16
- package/dist/agent/service.js.map +1 -1
- package/dist/agent/skills/__tests__/test-framework.test.js +15 -7
- package/dist/agent/skills/__tests__/test-framework.test.js.map +1 -1
- package/dist/agent/skills/config.d.ts +1 -1
- package/dist/agent/skills/config.js +2 -2
- package/dist/agent/skills/config.js.map +1 -1
- package/dist/agent/skills/index.js +15 -28
- package/dist/agent/skills/index.js.map +1 -1
- package/dist/agent/skills/installer.d.ts +1 -1
- package/dist/agent/skills/installer.js +1 -1
- package/dist/agent/skills/scanner.d.ts +1 -1
- package/dist/agent/skills/scanner.js +1 -1
- package/dist/agent/skills/test-framework.js +24 -23
- package/dist/agent/skills/test-framework.js.map +1 -1
- package/dist/agent/skills/types.d.ts +3 -3
- package/dist/agent/skills/types.js +1 -1
- package/dist/agent/skills/watcher.d.ts +1 -1
- package/dist/agent/skills/watcher.js +1 -1
- package/dist/agent/system-prompt.d.ts +67 -0
- package/dist/agent/system-prompt.js +351 -0
- package/dist/agent/system-prompt.js.map +1 -0
- package/dist/agent/tools/__tests__/send-media.test.d.ts +6 -0
- package/dist/agent/tools/__tests__/send-media.test.js +251 -0
- package/dist/agent/tools/__tests__/send-media.test.js.map +1 -0
- package/dist/agent/types.agent-defaults.d.ts +48 -0
- package/dist/agent/types.agent-defaults.js +5 -0
- package/dist/agent/types.agent-defaults.js.map +1 -0
- package/dist/agent/types.d.ts +14 -6
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -1
- package/dist/agent/workspace.d.ts +94 -0
- package/dist/agent/workspace.js +625 -0
- package/dist/agent/workspace.js.map +1 -0
- package/dist/auth/index.js +1 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/oauth/index.d.ts +1 -0
- package/dist/auth/oauth/index.js +1 -0
- package/dist/auth/oauth/index.js.map +1 -1
- package/dist/auth/oauth/kimi.d.ts +2 -1
- package/dist/auth/oauth/kimi.js +51 -48
- package/dist/auth/oauth/kimi.js.map +1 -1
- package/dist/auth/oauth/minimax-cn.d.ts +12 -0
- package/dist/auth/oauth/minimax-cn.js +111 -0
- package/dist/auth/oauth/minimax-cn.js.map +1 -0
- package/dist/auth/oauth/qwen.d.ts +5 -0
- package/dist/auth/oauth/qwen.js +54 -84
- package/dist/auth/oauth/qwen.js.map +1 -1
- package/dist/auth/profiles/index.d.ts +0 -2
- package/dist/auth/profiles/index.js +0 -2
- package/dist/auth/profiles/index.js.map +1 -1
- package/dist/auth/storage.js +7 -1
- package/dist/auth/storage.js.map +1 -1
- package/dist/channels/__tests__/media-integration.test.d.ts +6 -0
- package/dist/channels/__tests__/media-integration.test.js +398 -0
- package/dist/channels/__tests__/media-integration.test.js.map +1 -0
- package/dist/channels/__tests__/media.test.d.ts +6 -0
- package/dist/channels/__tests__/media.test.js +251 -0
- package/dist/channels/__tests__/media.test.js.map +1 -0
- package/dist/channels/access-control.d.ts +1 -1
- package/dist/channels/access-control.js +1 -1
- package/dist/channels/draft-stream.d.ts +1 -1
- package/dist/channels/draft-stream.js +1 -1
- package/dist/channels/format.d.ts +1 -1
- package/dist/channels/format.js +1 -1
- package/dist/channels/telegram/command-handler.js +15 -48
- package/dist/channels/telegram/command-handler.js.map +1 -1
- package/dist/channels/telegram/plugin.js +3 -2
- package/dist/channels/telegram/plugin.js.map +1 -1
- package/dist/channels/telegram/webhook.d.ts +1 -1
- package/dist/channels/telegram/webhook.js +1 -1
- package/dist/channels/types.d.ts +1 -1
- package/dist/channels/types.js +1 -1
- package/dist/channels/update-offset-store.d.ts +1 -1
- package/dist/channels/update-offset-store.js +1 -1
- package/dist/cli/commands/auth.js +8 -23
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/gateway.js +9 -1
- package/dist/cli/commands/gateway.js.map +1 -1
- package/dist/cli/commands/models.js +35 -29
- package/dist/cli/commands/models.js.map +1 -1
- package/dist/cli/commands/onboard.js +166 -115
- package/dist/cli/commands/onboard.js.map +1 -1
- package/dist/cli/commands/setup.js +123 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/skills.js +6 -6
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/templates.d.ts +2 -0
- package/dist/cli/templates.js +1 -1
- package/dist/cli/templates.js.map +1 -1
- package/dist/config/defaults.d.ts +19 -0
- package/dist/config/defaults.js +168 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.js +4 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/integration.d.ts +12 -0
- package/dist/config/integration.js +14 -0
- package/dist/config/integration.js.map +1 -0
- package/dist/config/models-json.d.ts +454 -0
- package/dist/config/models-json.js +323 -0
- package/dist/config/models-json.js.map +1 -0
- package/dist/config/paths.d.ts +2 -0
- package/dist/config/paths.js +4 -0
- package/dist/config/paths.js.map +1 -1
- package/dist/config/reload.d.ts +1 -1
- package/dist/config/reload.js +3 -3
- package/dist/config/reload.js.map +1 -1
- package/dist/config/resolve-config-value.d.ts +36 -0
- package/dist/config/resolve-config-value.js +218 -0
- package/dist/config/resolve-config-value.js.map +1 -0
- package/dist/config/rules.js +3 -2
- package/dist/config/rules.js.map +1 -1
- package/dist/config/schema.d.ts +17 -884
- package/dist/config/schema.js +36 -312
- package/dist/config/schema.js.map +1 -1
- package/dist/config/types.models.d.ts +54 -0
- package/dist/config/types.models.js +2 -0
- package/dist/config/types.models.js.map +1 -0
- package/dist/cron/validation.d.ts +4 -4
- package/dist/gateway/hono/app.js +232 -78
- package/dist/gateway/hono/app.js.map +1 -1
- package/dist/gateway/hono/oauth-async.d.ts +14 -0
- package/dist/gateway/hono/oauth-async.js +285 -0
- package/dist/gateway/hono/oauth-async.js.map +1 -0
- package/dist/gateway/hono/oauth.d.ts +9 -0
- package/dist/gateway/hono/oauth.js +157 -0
- package/dist/gateway/hono/oauth.js.map +1 -0
- package/dist/gateway/hono/sse.js +5 -2
- package/dist/gateway/hono/sse.js.map +1 -1
- package/dist/gateway/process-manager.js +12 -10
- package/dist/gateway/process-manager.js.map +1 -1
- package/dist/gateway/service.d.ts +6 -2
- package/dist/gateway/service.js +20 -6
- package/dist/gateway/service.js.map +1 -1
- package/dist/gateway/static/root/assets/flow-BqIEBwW6.js +2 -0
- package/dist/gateway/static/root/assets/flow-BqIEBwW6.js.map +1 -0
- package/dist/gateway/static/root/assets/main-Br2tw-87.js +5168 -0
- package/dist/gateway/static/root/assets/main-Br2tw-87.js.map +1 -0
- package/dist/gateway/static/root/assets/main-DwlbPf8Z.css +1 -0
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/plugins/index.d.ts +0 -2
- package/dist/plugins/index.js +0 -2
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/types.d.ts +0 -2
- package/dist/plugins/types.js +0 -2
- package/dist/plugins/types.js.map +1 -1
- package/dist/providers/index.d.ts +50 -22
- package/dist/providers/index.js +276 -50
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/model-registry.d.ts +84 -0
- package/dist/providers/model-registry.js +385 -0
- package/dist/providers/model-registry.js.map +1 -0
- package/dist/types/providers.d.ts +2 -63
- package/dist/types/providers.js +1 -1
- package/dist/utils/__tests__/frontmatter.test.d.ts +4 -0
- package/dist/utils/__tests__/frontmatter.test.js +150 -0
- package/dist/utils/__tests__/frontmatter.test.js.map +1 -0
- package/dist/utils/diagnostic-events.d.ts +230 -0
- package/dist/utils/diagnostic-events.js +189 -0
- package/dist/utils/diagnostic-events.js.map +1 -0
- package/dist/utils/frontmatter.d.ts +0 -1
- package/dist/utils/frontmatter.js +15 -79
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/log-stream.d.ts +95 -0
- package/dist/utils/log-stream.js +229 -0
- package/dist/utils/log-stream.js.map +1 -0
- package/dist/utils/logger.d.ts +5 -0
- package/dist/utils/logger.js +25 -0
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/redact.d.ts +73 -0
- package/dist/utils/redact.js +245 -0
- package/dist/utils/redact.js.map +1 -0
- package/package.json +6 -4
- package/skills/find-skills/SKILL.md +0 -9
- package/dist/__tests__/core.test.js +0 -72
- package/dist/__tests__/core.test.js.map +0 -1
- package/dist/agent/model-manager.js.map +0 -1
- package/dist/cli/commands/configure.d.ts +0 -1
- package/dist/cli/commands/configure.js +0 -173
- package/dist/cli/commands/configure.js.map +0 -1
- package/dist/cli/commands/gateway-daemon.d.ts +0 -1
- package/dist/cli/commands/gateway-daemon.js +0 -141
- package/dist/cli/commands/gateway-daemon.js.map +0 -1
- package/dist/config/__tests__/diff.test.d.ts +0 -1
- package/dist/config/__tests__/diff.test.js +0 -192
- package/dist/config/__tests__/diff.test.js.map +0 -1
- package/dist/config/__tests__/loader.test.d.ts +0 -1
- package/dist/config/__tests__/loader.test.js +0 -356
- package/dist/config/__tests__/loader.test.js.map +0 -1
- package/dist/config/__tests__/paths.test.d.ts +0 -1
- package/dist/config/__tests__/paths.test.js +0 -192
- package/dist/config/__tests__/paths.test.js.map +0 -1
- package/dist/config/__tests__/reload.test.d.ts +0 -1
- package/dist/config/__tests__/reload.test.js +0 -374
- package/dist/config/__tests__/reload.test.js.map +0 -1
- package/dist/config/__tests__/rules.test.d.ts +0 -1
- package/dist/config/__tests__/rules.test.js +0 -204
- package/dist/config/__tests__/rules.test.js.map +0 -1
- package/dist/config/__tests__/schema.test.d.ts +0 -1
- package/dist/config/__tests__/schema.test.js +0 -672
- package/dist/config/__tests__/schema.test.js.map +0 -1
- package/dist/daemon/background-start.d.ts +0 -33
- package/dist/daemon/background-start.js +0 -89
- package/dist/daemon/background-start.js.map +0 -1
- package/dist/daemon/gateway-manager.d.ts +0 -87
- package/dist/daemon/gateway-manager.js +0 -324
- package/dist/daemon/gateway-manager.js.map +0 -1
- package/dist/daemon/index.d.ts +0 -5
- package/dist/daemon/index.js +0 -6
- package/dist/daemon/index.js.map +0 -1
- package/dist/gateway/static/root/assets/main-DevbZW9K.js +0 -2227
- package/dist/gateway/static/root/assets/main-DevbZW9K.js.map +0 -1
- package/dist/gateway/static/root/assets/main-DxZg1Nmz.css +0 -1
- package/dist/providers/__tests__/registry.test.d.ts +0 -1
- package/dist/providers/__tests__/registry.test.js +0 -110
- package/dist/providers/__tests__/registry.test.js.map +0 -1
- package/dist/providers/api-strategies.d.ts +0 -15
- package/dist/providers/api-strategies.js +0 -96
- package/dist/providers/api-strategies.js.map +0 -1
- package/dist/providers/auto-discovery.d.ts +0 -84
- package/dist/providers/auto-discovery.js +0 -236
- package/dist/providers/auto-discovery.js.map +0 -1
- package/dist/providers/config.d.ts +0 -25
- package/dist/providers/config.js +0 -42
- package/dist/providers/config.js.map +0 -1
- package/dist/providers/model-catalog.d.ts +0 -205
- package/dist/providers/model-catalog.js +0 -1071
- package/dist/providers/model-catalog.js.map +0 -1
- package/dist/providers/models-dev-data.d.ts +0 -11
- package/dist/providers/models-dev-data.js +0 -1035
- package/dist/providers/models-dev-data.js.map +0 -1
- package/dist/providers/models-dev.d.ts +0 -30
- package/dist/providers/models-dev.js +0 -42
- package/dist/providers/models-dev.js.map +0 -1
- package/dist/providers/pi-ai.d.ts +0 -62
- package/dist/providers/pi-ai.js +0 -221
- package/dist/providers/pi-ai.js.map +0 -1
- package/dist/providers/provider-catalog.d.ts +0 -173
- package/dist/providers/provider-catalog.js +0 -834
- package/dist/providers/provider-catalog.js.map +0 -1
- package/dist/providers/registry.d.ts +0 -155
- package/dist/providers/registry.js +0 -524
- package/dist/providers/registry.js.map +0 -1
- package/dist/providers/types.d.ts +0 -95
- package/dist/providers/types.js +0 -7
- package/dist/providers/types.js.map +0 -1
- package/dist/session/chat-manager.d.ts +0 -49
- package/dist/session/chat-manager.js +0 -167
- package/dist/session/chat-manager.js.map +0 -1
- package/dist/session/chat-types.d.ts +0 -53
- package/dist/session/chat-types.js +0 -63
- package/dist/session/chat-types.js.map +0 -1
- /package/dist/{__tests__/core.test.d.ts → cli/commands/setup.d.ts} +0 -0
|
@@ -1,2227 +0,0 @@
|
|
|
1
|
-
(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))i(n);new MutationObserver(n=>{for(const a of n)if(a.type==="childList")for(const l of a.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&i(l)}).observe(document,{childList:!0,subtree:!0});function s(n){const a={};return n.integrity&&(a.integrity=n.integrity),n.referrerPolicy&&(a.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?a.credentials="include":n.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function i(n){if(n.ep)return;n.ep=!0;const a=s(n);fetch(n.href,a)}})();const $e=globalThis,Be=$e.ShadowRoot&&($e.ShadyCSS===void 0||$e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,rt=Symbol(),qe=new WeakMap;let $t=class{constructor(t,s,i){if(this._$cssResult$=!0,i!==rt)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=s}get styleSheet(){let t=this.o;const s=this.t;if(Be&&t===void 0){const i=s!==void 0&&s.length===1;i&&(t=qe.get(s)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&qe.set(s,t))}return t}toString(){return this.cssText}};const kt=e=>new $t(typeof e=="string"?e:e+"",void 0,rt),xt=(e,t)=>{if(Be)e.adoptedStyleSheets=t.map(s=>s instanceof CSSStyleSheet?s:s.styleSheet);else for(const s of t){const i=document.createElement("style"),n=$e.litNonce;n!==void 0&&i.setAttribute("nonce",n),i.textContent=s.cssText,e.appendChild(i)}},Je=Be?e=>e:e=>e instanceof CSSStyleSheet?(t=>{let s="";for(const i of t.cssRules)s+=i.cssText;return kt(s)})(e):e;const{is:St,defineProperty:At,getOwnPropertyDescriptor:Ct,getOwnPropertyNames:Tt,getOwnPropertySymbols:Mt,getPrototypeOf:Et}=Object,Te=globalThis,Ge=Te.trustedTypes,Pt=Ge?Ge.emptyScript:"",Ft=Te.reactiveElementPolyfillSupport,ue=(e,t)=>e,ke={toAttribute(e,t){switch(t){case Boolean:e=e?Pt:null;break;case Object:case Array:e=e==null?e:JSON.stringify(e)}return e},fromAttribute(e,t){let s=e;switch(t){case Boolean:s=e!==null;break;case Number:s=e===null?null:Number(e);break;case Object:case Array:try{s=JSON.parse(e)}catch{s=null}}return s}},Ke=(e,t)=>!St(e,t),We={attribute:!0,type:String,converter:ke,reflect:!1,useDefault:!1,hasChanged:Ke};Symbol.metadata??=Symbol("metadata"),Te.litPropertyMetadata??=new WeakMap;let se=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,s=We){if(s.state&&(s.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((s=Object.create(s)).wrapped=!0),this.elementProperties.set(t,s),!s.noAccessor){const i=Symbol(),n=this.getPropertyDescriptor(t,i,s);n!==void 0&&At(this.prototype,t,n)}}static getPropertyDescriptor(t,s,i){const{get:n,set:a}=Ct(this.prototype,t)??{get(){return this[s]},set(l){this[s]=l}};return{get:n,set(l){const h=n?.call(this);a?.call(this,l),this.requestUpdate(t,h,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??We}static _$Ei(){if(this.hasOwnProperty(ue("elementProperties")))return;const t=Et(this);t.finalize(),t.l!==void 0&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(ue("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(ue("properties"))){const s=this.properties,i=[...Tt(s),...Mt(s)];for(const n of i)this.createProperty(n,s[n])}const t=this[Symbol.metadata];if(t!==null){const s=litPropertyMetadata.get(t);if(s!==void 0)for(const[i,n]of s)this.elementProperties.set(i,n)}this._$Eh=new Map;for(const[s,i]of this.elementProperties){const n=this._$Eu(s,i);n!==void 0&&this._$Eh.set(n,s)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const s=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const n of i)s.unshift(Je(n))}else t!==void 0&&s.push(Je(t));return s}static _$Eu(t,s){const i=s.attribute;return i===!1?void 0:typeof i=="string"?i:typeof t=="string"?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),this.renderRoot!==void 0&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,s=this.constructor.elementProperties;for(const i of s.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return xt(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,s,i){this._$AK(t,i)}_$ET(t,s){const i=this.constructor.elementProperties.get(t),n=this.constructor._$Eu(t,i);if(n!==void 0&&i.reflect===!0){const a=(i.converter?.toAttribute!==void 0?i.converter:ke).toAttribute(s,i.type);this._$Em=t,a==null?this.removeAttribute(n):this.setAttribute(n,a),this._$Em=null}}_$AK(t,s){const i=this.constructor,n=i._$Eh.get(t);if(n!==void 0&&this._$Em!==n){const a=i.getPropertyOptions(n),l=typeof a.converter=="function"?{fromAttribute:a.converter}:a.converter?.fromAttribute!==void 0?a.converter:ke;this._$Em=n;const h=l.fromAttribute(s,a.type);this[n]=h??this._$Ej?.get(n)??h,this._$Em=null}}requestUpdate(t,s,i,n=!1,a){if(t!==void 0){const l=this.constructor;if(n===!1&&(a=this[t]),i??=l.getPropertyOptions(t),!((i.hasChanged??Ke)(a,s)||i.useDefault&&i.reflect&&a===this._$Ej?.get(t)&&!this.hasAttribute(l._$Eu(t,i))))return;this.C(t,s,i)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(t,s,{useDefault:i,reflect:n,wrapped:a},l){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,l??s??this[t]),a!==!0||l!==void 0)||(this._$AL.has(t)||(this.hasUpdated||i||(s=void 0),this._$AL.set(t,s)),n===!0&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(s){Promise.reject(s)}const t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[n,a]of this._$Ep)this[n]=a;this._$Ep=void 0}const i=this.constructor.elementProperties;if(i.size>0)for(const[n,a]of i){const{wrapped:l}=a,h=this[n];l!==!0||this._$AL.has(n)||h===void 0||this.C(n,void 0,a,h)}}let t=!1;const s=this._$AL;try{t=this.shouldUpdate(s),t?(this.willUpdate(s),this._$EO?.forEach(i=>i.hostUpdate?.()),this.update(s)):this._$EM()}catch(i){throw t=!1,this._$EM(),i}t&&this._$AE(s)}willUpdate(t){}_$AE(t){this._$EO?.forEach(s=>s.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(s=>this._$ET(s,this[s])),this._$EM()}updated(t){}firstUpdated(t){}};se.elementStyles=[],se.shadowRootOptions={mode:"open"},se[ue("elementProperties")]=new Map,se[ue("finalized")]=new Map,Ft?.({ReactiveElement:se}),(Te.reactiveElementVersions??=[]).push("2.1.2");const je=globalThis,Ve=e=>e,xe=je.trustedTypes,Qe=xe?xe.createPolicy("lit-html",{createHTML:e=>e}):void 0,lt="$lit$",B=`lit$${Math.random().toFixed(9).slice(2)}$`,ct="?"+B,Lt=`<${ct}>`,G=document,_e=()=>G.createComment(""),me=e=>e===null||typeof e!="object"&&typeof e!="function",Ue=Array.isArray,Dt=e=>Ue(e)||typeof e?.[Symbol.iterator]=="function",Fe=`[
|
|
2
|
-
\f\r]`,ce=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Xe=/-->/g,Ye=/>/g,N=RegExp(`>|${Fe}(?:([^\\s"'>=/]+)(${Fe}*=${Fe}*(?:[^
|
|
3
|
-
\f\r"'\`<>=]|("|')|))|$)`,"g"),Ze=/'/g,et=/"/g,ht=/^(?:script|style|textarea|title)$/i,It=e=>(t,...s)=>({_$litType$:e,strings:t,values:s}),o=It(1),W=Symbol.for("lit-noChange"),_=Symbol.for("lit-nothing"),tt=new WeakMap,q=G.createTreeWalker(G,129);function dt(e,t){if(!Ue(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return Qe!==void 0?Qe.createHTML(t):t}const Ot=(e,t)=>{const s=e.length-1,i=[];let n,a=t===2?"<svg>":t===3?"<math>":"",l=ce;for(let h=0;h<s;h++){const p=e[h];let g,S,f=-1,F=0;for(;F<p.length&&(l.lastIndex=F,S=l.exec(p),S!==null);)F=l.lastIndex,l===ce?S[1]==="!--"?l=Xe:S[1]!==void 0?l=Ye:S[2]!==void 0?(ht.test(S[2])&&(n=RegExp("</"+S[2],"g")),l=N):S[3]!==void 0&&(l=N):l===N?S[0]===">"?(l=n??ce,f=-1):S[1]===void 0?f=-2:(f=l.lastIndex-S[2].length,g=S[1],l=S[3]===void 0?N:S[3]==='"'?et:Ze):l===et||l===Ze?l=N:l===Xe||l===Ye?l=ce:(l=N,n=void 0);const I=l===N&&e[h+1].startsWith("/>")?" ":"";a+=l===ce?p+Lt:f>=0?(i.push(g),p.slice(0,f)+lt+p.slice(f)+B+I):p+B+(f===-2?h:I)}return[dt(e,a+(e[s]||"<?>")+(t===2?"</svg>":t===3?"</math>":"")),i]};class ve{constructor({strings:t,_$litType$:s},i){let n;this.parts=[];let a=0,l=0;const h=t.length-1,p=this.parts,[g,S]=Ot(t,s);if(this.el=ve.createElement(g,i),q.currentNode=this.el.content,s===2||s===3){const f=this.el.content.firstChild;f.replaceWith(...f.childNodes)}for(;(n=q.nextNode())!==null&&p.length<h;){if(n.nodeType===1){if(n.hasAttributes())for(const f of n.getAttributeNames())if(f.endsWith(lt)){const F=S[l++],I=n.getAttribute(f).split(B),we=/([.?@])?(.*)/.exec(F);p.push({type:1,index:a,name:we[2],strings:I,ctor:we[1]==="."?Bt:we[1]==="?"?Kt:we[1]==="@"?jt:Me}),n.removeAttribute(f)}else f.startsWith(B)&&(p.push({type:6,index:a}),n.removeAttribute(f));if(ht.test(n.tagName)){const f=n.textContent.split(B),F=f.length-1;if(F>0){n.textContent=xe?xe.emptyScript:"";for(let I=0;I<F;I++)n.append(f[I],_e()),q.nextNode(),p.push({type:2,index:++a});n.append(f[F],_e())}}}else if(n.nodeType===8)if(n.data===ct)p.push({type:2,index:a});else{let f=-1;for(;(f=n.data.indexOf(B,f+1))!==-1;)p.push({type:7,index:a}),f+=B.length-1}a++}}static createElement(t,s){const i=G.createElement("template");return i.innerHTML=t,i}}function ne(e,t,s=e,i){if(t===W)return t;let n=i!==void 0?s._$Co?.[i]:s._$Cl;const a=me(t)?void 0:t._$litDirective$;return n?.constructor!==a&&(n?._$AO?.(!1),a===void 0?n=void 0:(n=new a(e),n._$AT(e,s,i)),i!==void 0?(s._$Co??=[])[i]=n:s._$Cl=n),n!==void 0&&(t=ne(e,n._$AS(e,t.values),n,i)),t}class Rt{constructor(t,s){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=s}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:s},parts:i}=this._$AD,n=(t?.creationScope??G).importNode(s,!0);q.currentNode=n;let a=q.nextNode(),l=0,h=0,p=i[0];for(;p!==void 0;){if(l===p.index){let g;p.type===2?g=new ye(a,a.nextSibling,this,t):p.type===1?g=new p.ctor(a,p.name,p.strings,this,t):p.type===6&&(g=new Ut(a,this,t)),this._$AV.push(g),p=i[++h]}l!==p?.index&&(a=q.nextNode(),l++)}return q.currentNode=G,n}p(t){let s=0;for(const i of this._$AV)i!==void 0&&(i.strings!==void 0?(i._$AI(t,i,s),s+=i.strings.length-2):i._$AI(t[s])),s++}}class ye{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,s,i,n){this.type=2,this._$AH=_,this._$AN=void 0,this._$AA=t,this._$AB=s,this._$AM=i,this.options=n,this._$Cv=n?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode;const s=this._$AM;return s!==void 0&&t?.nodeType===11&&(t=s.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,s=this){t=ne(this,t,s),me(t)?t===_||t==null||t===""?(this._$AH!==_&&this._$AR(),this._$AH=_):t!==this._$AH&&t!==W&&this._(t):t._$litType$!==void 0?this.$(t):t.nodeType!==void 0?this.T(t):Dt(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==_&&me(this._$AH)?this._$AA.nextSibling.data=t:this.T(G.createTextNode(t)),this._$AH=t}$(t){const{values:s,_$litType$:i}=t,n=typeof i=="number"?this._$AC(t):(i.el===void 0&&(i.el=ve.createElement(dt(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===n)this._$AH.p(s);else{const a=new Rt(n,this),l=a.u(this.options);a.p(s),this.T(l),this._$AH=a}}_$AC(t){let s=tt.get(t.strings);return s===void 0&&tt.set(t.strings,s=new ve(t)),s}k(t){Ue(this._$AH)||(this._$AH=[],this._$AR());const s=this._$AH;let i,n=0;for(const a of t)n===s.length?s.push(i=new ye(this.O(_e()),this.O(_e()),this,this.options)):i=s[n],i._$AI(a),n++;n<s.length&&(this._$AR(i&&i._$AB.nextSibling,n),s.length=n)}_$AR(t=this._$AA.nextSibling,s){for(this._$AP?.(!1,!0,s);t!==this._$AB;){const i=Ve(t).nextSibling;Ve(t).remove(),t=i}}setConnected(t){this._$AM===void 0&&(this._$Cv=t,this._$AP?.(t))}}class Me{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,s,i,n,a){this.type=1,this._$AH=_,this._$AN=void 0,this.element=t,this.name=s,this._$AM=n,this.options=a,i.length>2||i[0]!==""||i[1]!==""?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=_}_$AI(t,s=this,i,n){const a=this.strings;let l=!1;if(a===void 0)t=ne(this,t,s,0),l=!me(t)||t!==this._$AH&&t!==W,l&&(this._$AH=t);else{const h=t;let p,g;for(t=a[0],p=0;p<a.length-1;p++)g=ne(this,h[i+p],s,p),g===W&&(g=this._$AH[p]),l||=!me(g)||g!==this._$AH[p],g===_?t=_:t!==_&&(t+=(g??"")+a[p+1]),this._$AH[p]=g}l&&!n&&this.j(t)}j(t){t===_?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"")}}class Bt extends Me{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===_?void 0:t}}class Kt extends Me{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==_)}}class jt extends Me{constructor(t,s,i,n,a){super(t,s,i,n,a),this.type=5}_$AI(t,s=this){if((t=ne(this,t,s,0)??_)===W)return;const i=this._$AH,n=t===_&&i!==_||t.capture!==i.capture||t.once!==i.once||t.passive!==i.passive,a=t!==_&&(i===_||n);n&&this.element.removeEventListener(this.name,this,i),a&&this.element.addEventListener(this.name,this,t),this._$AH=t}handleEvent(t){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}}class Ut{constructor(t,s,i){this.element=t,this.type=6,this._$AN=void 0,this._$AM=s,this.options=i}get _$AU(){return this._$AM._$AU}_$AI(t){ne(this,t)}}const Ht=je.litHtmlPolyfillSupport;Ht?.(ve,ye),(je.litHtmlVersions??=[]).push("3.3.2");const Nt=(e,t,s)=>{const i=s?.renderBefore??t;let n=i._$litPart$;if(n===void 0){const a=s?.renderBefore??null;i._$litPart$=n=new ye(t.insertBefore(_e(),a),a,void 0,s??{})}return n._$AI(e),n};const He=globalThis;let y=class extends se{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const s=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=Nt(s,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return W}};y._$litElement$=!0,y.finalized=!0,He.litElementHydrateSupport?.({LitElement:y});const zt=He.litElementPolyfillSupport;zt?.({LitElement:y});(He.litElementVersions??=[]).push("4.2.2");const k=e=>(t,s)=>{s!==void 0?s.addInitializer(()=>{customElements.define(e,t)}):customElements.define(e,t)};const qt={attribute:!0,type:String,converter:ke,reflect:!1,hasChanged:Ke},Jt=(e=qt,t,s)=>{const{kind:i,metadata:n}=s;let a=globalThis.litPropertyMetadata.get(n);if(a===void 0&&globalThis.litPropertyMetadata.set(n,a=new Map),i==="setter"&&((e=Object.create(e)).wrapped=!0),a.set(s.name,e),i==="accessor"){const{name:l}=s;return{set(h){const p=t.get.call(this);t.set.call(this,h),this.requestUpdate(l,p,e,!0,h)},init(h){return h!==void 0&&this.C(l,void 0,e,h),h}}}if(i==="setter"){const{name:l}=s;return function(h){const p=this[l];t.call(this,h),this.requestUpdate(l,p,e,!0,h)}}throw Error("Unsupported decorator location: "+i)};function u(e){return(t,s)=>typeof s=="object"?Jt(e,t,s):((i,n,a)=>{const l=n.hasOwnProperty(a);return n.constructor.createProperty(a,i),l?Object.getOwnPropertyDescriptor(n,a):void 0})(e,t,s)}function c(e){return u({...e,state:!0,attribute:!1})}const Gt=(e,t,s)=>(s.configurable=!0,s.enumerable=!0,Reflect.decorate&&typeof t!="object"&&Object.defineProperty(e,t,s),s);function oe(e,t){return(s,i,n)=>{const a=l=>l.renderRoot?.querySelector(e)??null;return Gt(s,i,{get(){return a(this)}})}}const Wt=e=>e.strings===void 0;const pt={CHILD:2},ut=e=>(...t)=>({_$litDirective$:e,values:t});class gt{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,s,i){this._$Ct=t,this._$AM=s,this._$Ci=i}_$AS(t,s){return this.update(t,s)}update(t,s){return this.render(...s)}}const ge=(e,t)=>{const s=e._$AN;if(s===void 0)return!1;for(const i of s)i._$AO?.(t,!1),ge(i,t);return!0},Se=e=>{let t,s;do{if((t=e._$AM)===void 0)break;s=t._$AN,s.delete(e),e=t}while(s?.size===0)},_t=e=>{for(let t;t=e._$AM;e=t){let s=t._$AN;if(s===void 0)t._$AN=s=new Set;else if(s.has(e))break;s.add(e),Xt(t)}};function Vt(e){this._$AN!==void 0?(Se(this),this._$AM=e,_t(this)):this._$AM=e}function Qt(e,t=!1,s=0){const i=this._$AH,n=this._$AN;if(n!==void 0&&n.size!==0)if(t)if(Array.isArray(i))for(let a=s;a<i.length;a++)ge(i[a],!1),Se(i[a]);else i!=null&&(ge(i,!1),Se(i));else ge(this,e)}const Xt=e=>{e.type==pt.CHILD&&(e._$AP??=Qt,e._$AQ??=Vt)};class Yt extends gt{constructor(){super(...arguments),this._$AN=void 0}_$AT(t,s,i){super._$AT(t,s,i),_t(this),this.isConnected=t._$AU}_$AO(t,s=!0){t!==this.isConnected&&(this.isConnected=t,t?this.reconnected?.():this.disconnected?.()),s&&(ge(this,t),Se(this))}setValue(t){if(Wt(this._$Ct))this._$Ct._$AI(t,this);else{const s=[...this._$Ct._$AH];s[this._$Ci]=t,this._$Ct._$AI(s,this,0)}}disconnected(){}reconnected(){}}const st=()=>new Zt;class Zt{}const Le=new WeakMap,it=ut(class extends Yt{render(e){return _}update(e,[t]){const s=t!==this.G;return s&&this.G!==void 0&&this.rt(void 0),(s||this.lt!==this.ct)&&(this.G=t,this.ht=e.options?.host,this.rt(this.ct=e.element)),_}rt(e){if(this.isConnected||(e=void 0),typeof this.G=="function"){const t=this.ht??globalThis;let s=Le.get(t);s===void 0&&(s=new WeakMap,Le.set(t,s)),s.get(this.G)!==void 0&&this.G.call(this.ht,void 0),s.set(this.G,e),e!==void 0&&this.G.call(this.ht,e)}else this.G.value=e}get lt(){return typeof this.G=="function"?Le.get(this.ht??globalThis)?.get(this.G):this.G?.value}disconnected(){this.lt===this.ct&&this.rt(void 0)}reconnected(){this.rt(this.ct)}});class De extends gt{constructor(t){if(super(t),this.it=_,t.type!==pt.CHILD)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(t){if(t===_||t==null)return this._t=void 0,this.it=t;if(t===W)return t;if(typeof t!="string")throw Error(this.constructor.directiveName+"() called with a non-string value");if(t===this.it)return this._t;this.it=t;const s=[t];return s.raw=s,this._t={_$litType$:this.constructor.resultType,strings:s,values:[]}}}De.directiveName="unsafeHTML",De.resultType=1;const he=ut(De);const Ee={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"};const es=["svg",Ee,[["path",{d:"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"}]]];const ts=["svg",Ee,[["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"}],["path",{d:"m21.854 2.147-10.94 10.939"}]]];const ss=["svg",Ee,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]]];const is=["svg",Ee,[["path",{d:"M18 6 6 18"}],["path",{d:"m6 6 12 12"}]]],ns={title:"XOPCBOT Gateway",brand:"XOPCBOT"},os={chat:"Chat",sessions:"Sessions",cron:"Cron Jobs",logs:"Logs",settings:"Settings",management:"Management"},as={title:"XopcBot",newSession:"New Chat",welcomeTitle:"Welcome to xopcbot",welcomeDescription:"Send a message to get started",emptyState:"No messages yet",emptyStateDescription:"Start a conversation by typing a message below",you:"You",assistant:"Assistant",tool:"Tool",thinking:"thinking...",typeMessage:"Type a message...",attachFile:"Attach file",sendMessage:"Send message",abort:"Abort",retry:"Retry",reasoning:"Reasoning",thinkingLevelNone:"None",thinkingLevel1:"Level 1",thinkingLevel2:"Level 2",thinkingLevel3:"Level 3",thinkingLevel4:"Level 4",connecting:"Connecting...",disconnected:"Disconnected",connectionError:"Connection error",reconnecting:"Reconnecting...",online:"Online",offline:"Offline"},rs={title:"Settings",save:"Save",cancel:"Cancel",close:"Close",loading:"Loading settings...",unsaved:"{{count}} unsaved",saveChanges:"Save Changes",saving:"Saving...",noSection:"No section selected",enableFeature:"Enable this feature",required:"{{field}} is required",invalidFormat:"Invalid format",unsavedChanges:"Unsaved changes",sections:{agent:"Agent",providers:"Providers",channels:"Channels",gateway:"Gateway"},descriptions:{agent:"Configure your agent settings",providers:"Configure your provider API keys",channels:"Configure messaging channels",gateway:"Configure gateway settings"},fields:{model:"Model",workspace:"Workspace",maxTokens:"Max Tokens",temperature:"Temperature",maxToolIterations:"Max Tool Iterations",openaiApiKey:"OpenAI API Key",anthropicApiKey:"Anthropic API Key",googleApiKey:"Google API Key",qwenApiKey:"Qwen API Key",kimiApiKey:"Kimi API Key",minimaxApiKey:"MiniMax API Key",deepseekApiKey:"DeepSeek API Key",grokApiKey:"Grok API Key",openrouterApiKey:"OpenRouter API Key",telegramEnabled:"Telegram",telegramToken:"Telegram Token",telegramApiRoot:"API Root (Optional)",telegramAllowFrom:"Allow From (Optional)",telegramDebug:"Debug Mode",whatsappEnabled:"WhatsApp",whatsappBridgeUrl:"Bridge URL",whatsappAllowFrom:"Allow From (Optional)",heartbeatEnabled:"Heartbeat",heartbeatIntervalMs:"Heartbeat Interval (ms)",gatewayToken:"Gateway Token"},descriptionsFields:{model:"Default AI model to use",workspace:"Working directory for agent files",maxTokens:"Maximum tokens in response",temperature:"Randomness in responses (0-2)",maxToolIterations:"Maximum tool calls per message",openaiApiKey:"API key for OpenAI models",anthropicApiKey:"API key for Claude models",googleApiKey:"API key for Gemini models",qwenApiKey:"API key for Qwen models",kimiApiKey:"API key for Kimi models",minimaxApiKey:"API key for MiniMax models",deepseekApiKey:"API key for DeepSeek models",grokApiKey:"API key for Grok models",openrouterApiKey:"API key for OpenRouter models",telegramEnabled:"Enable Telegram bot",telegramToken:"Bot API token from @BotFather",telegramApiRoot:"Custom Telegram API root URL",telegramAllowFrom:"Allowed user IDs, comma separated",telegramDebug:"Enable debug logging for Telegram",whatsappEnabled:"Enable WhatsApp bridge",whatsappBridgeUrl:"WhatsApp bridge WebSocket URL",whatsappAllowFrom:"Allowed phone numbers, comma separated",heartbeatEnabled:"Enable heartbeat monitoring",heartbeatIntervalMs:"Heartbeat check interval in milliseconds",gatewayToken:"Authentication token for gateway API access"},placeholders:{workspace:"~/.xopcbot/workspace",openaiApiKey:"sk-...",anthropicApiKey:"sk-ant-...",googleApiKey:"AIzaSy...",qwenApiKey:"sk-...",kimiApiKey:"sk-kimi-...",minimaxApiKey:"sk-cp-...",deepseekApiKey:"sk-...",openrouterApiKey:"sk-or-...",telegramToken:"1234567890:ABCdefGHIjklMNOpqrsTUVwxyz",telegramApiRoot:"https://api.telegram.org",telegramAllowFrom:"123456789, 987654321",whatsappBridgeUrl:"ws://localhost:3001",whatsappAllowFrom:"+1234567890, +0987654321",gatewayToken:"Enter your gateway authentication token"},connection:{title:"Connection",gatewayUrl:"Gateway URL",gatewayUrlDesc:"WebSocket URL for the gateway server",authToken:"Auth Token",authTokenDesc:"Optional authentication token"},appearance:{title:"Appearance",theme:"Theme",themeDesc:"Choose your preferred color scheme",themeSystem:"System",themeLight:"Light",themeDark:"Dark"},chat:{title:"Chat",enableAttachments:"Enable Attachments",enableAttachmentsDesc:"Allow file attachments in chat",showModelSelector:"Show Model Selector",showModelSelectorDesc:"Display model selection dropdown",showThinkingSelector:"Show Thinking Selector",showThinkingSelectorDesc:"Display thinking level selection"}},ls={noSession:"No session available",noAgent:"No agent set",noModel:"No model set",requestTimeout:"Request timeout",sendFailed:"Failed to send message",invalidFileType:"Invalid file type",fileTooLarge:"File too large (max {{size}})",readFileFailed:"Failed to read file"},cs={dropHere:"Drop files here",dragDrop:"Drag and drop files here",image:"Image",document:"Document",pdf:"PDF",word:"Word",excel:"Excel",powerpoint:"PowerPoint",text:"Text",code:"Code",archive:"Archive",unknown:"Unknown"},hs={settings:"Open settings"},ds={title:"Configuration",save:"Save Configuration",noResult:"No result",artifacts:"Artifacts",showArtifacts:"Show artifacts"},ps={title:"Logs",refresh:"Refresh",clear:"Clear",totalLogs:"Total Logs",pause:"Pause",autoRefresh:"Auto Refresh",level:"Level",search:"Search",searchPlaceholder:"Search logs...",time:"Time",message:"Message",module:"Module",noLogs:"No logs found",noLogsDescription:"Try adjusting your filters or check back later.",details:"Log Details"},us={title:"Sessions",newSession:"New Session",searchPlaceholder:"Search sessions...",totalSessions:"Total Sessions",activeSessions:"Active Sessions",pinnedSessions:"Pinned Sessions",archivedSessions:"Archived Sessions",noSessions:"No sessions",delete:"Delete",archive:"Archive",pin:"Pin",unpin:"Unpin",confirmDelete:"Are you sure you want to delete this session?"},gs={title:"Cron Jobs",addJob:"Add Cron Job",editJob:"Edit Job",name:"Name (optional)",namePlaceholder:"My scheduled task",schedule:"Schedule (cron expression) *",scheduleHint:"e.g., */5 * * * * (every 5 minutes), 0 9 * * * (daily at 9am)",message:"Message *",messagePlaceholder:"What should the assistant do?",create:"Create Job",runNow:"Run Now",delete:"Delete",edit:"Edit",enable:"Enable",disable:"Disable",enabled:"Enabled",disabled:"Disabled",running:"Running",lastRun:"Last Run",nextRun:"Next Run",status:"Status",history:"History",actions:"Actions",noJobs:"No cron jobs",confirmDelete:"Are you sure you want to delete this cron job?",confirmRun:"Run this cron job now?",success:"Success",failed:"Failed",scheduleLabel:"Schedule",messageLabel:"Message",confirm:"Confirm",cancel:"Cancel",total:"Total",schedulePresets:{custom:"-- Custom (enter below) --",everyMinute:"Every minute",every5Minutes:"Every 5 minutes (default)",every10Minutes:"Every 10 minutes",every15Minutes:"Every 15 minutes",every30Minutes:"Every 30 minutes",everyHour:"Every hour",every2Hours:"Every 2 hours",every4Hours:"Every 4 hours",every6Hours:"Every 6 hours",every12Hours:"Every 12 hours",everyDayMidnight:"Every day at midnight",everyDay9AM:"Every day at 9:00 AM",everyDay9PM:"Every day at 9:00 PM"},scheduleHintPreset:"Select a preset or enter custom cron expression",mode:"Mode",modeDirect:"Send message directly to the channel without AI processing",modeAgent:"Use AI agent to process the message, then send the response",modeDirectOption:"Direct (send message directly)",modeAgentOption:"AI Agent (process with AI then send)",model:"Model",noConfiguredModels:"No configured models",save:"Save",failedToLoadJobs:"Failed to load jobs",scheduleRequired:"Schedule and message are required",chatIdRequired:"Chat ID is required",failedToJob:"Failed to {{mode}} job",failedToToggleJob:"Failed to toggle job",actionFailed:"Action failed",enterManuallyOrSelect:"Enter manually or select from recent chats",noRecentChats:"No recent chats found. Enter chat ID manually (e.g., 123456789 for Telegram)",timeLabels:{lessThanMinute:"Less than a minute",minutes:"{{count}} min",hours:"{{count}} hours",overdue:"Overdue"},lastActiveLabels:{justNow:"just now",minutesAgo:"{{count}}m ago",hoursAgo:"{{count}}h ago",daysAgo:"{{count}}d ago"}},_s={save:"Save",cancel:"Cancel",confirm:"Confirm",close:"Close",loading:"Loading...",error:"Error",success:"Success",noData:"No data"},ms={app:ns,nav:os,chat:as,settings:rs,errors:ls,fileUpload:cs,shortcuts:hs,config:ds,logs:ps,sessions:us,cron:gs,common:_s},vs={title:"XOPCBOT 网关",brand:"XOPCBOT"},fs={chat:"对话",sessions:"会话",cron:"定时任务",logs:"日志",settings:"设置",management:"管理"},ys={title:"XopcBot",newSession:"新建对话",welcomeTitle:"欢迎使用 xopcbot",welcomeDescription:"发送消息开始对话",emptyState:"暂无消息",emptyStateDescription:"在下方输入消息开始对话",you:"你",assistant:"助手",tool:"工具",thinking:"思考中...",typeMessage:"输入消息...",attachFile:"附加文件",sendMessage:"发送消息",abort:"中止",retry:"重试",reasoning:"推理",thinkingLevelNone:"无",thinkingLevel1:"级别 1",thinkingLevel2:"级别 2",thinkingLevel3:"级别 3",thinkingLevel4:"级别 4",connecting:"连接中...",disconnected:"已断开",connectionError:"连接错误",reconnecting:"重新连接中...",online:"在线",offline:"离线"},ws={title:"设置",save:"保存",cancel:"取消",close:"关闭",loading:"加载设置中...",unsaved:"{{count}} 个未保存",saveChanges:"保存更改",saving:"保存中...",noSection:"未选择部分",enableFeature:"启用此功能",required:"{{field}} 为必填项",invalidFormat:"格式无效",unsavedChanges:"未保存的更改",sections:{agent:"代理",providers:"提供商",channels:"渠道",gateway:"网关"},descriptions:{agent:"配置代理设置",providers:"配置提供商 API 密钥",channels:"配置消息渠道",gateway:"配置网关设置"},fields:{model:"模型",workspace:"工作区",maxTokens:"最大 Token 数",temperature:"温度",maxToolIterations:"最大工具调用次数",openaiApiKey:"OpenAI API 密钥",anthropicApiKey:"Anthropic API 密钥",googleApiKey:"Google API 密钥",qwenApiKey:"Qwen API 密钥",kimiApiKey:"Kimi API 密钥",minimaxApiKey:"MiniMax API 密钥",deepseekApiKey:"DeepSeek API 密钥",grokApiKey:"Grok API 密钥",openrouterApiKey:"OpenRouter API 密钥",telegramEnabled:"Telegram",telegramToken:"Telegram 令牌",telegramApiRoot:"API 根地址(可选)",telegramAllowFrom:"允许来源(可选)",telegramDebug:"调试模式",whatsappEnabled:"WhatsApp",whatsappBridgeUrl:"桥接地址",whatsappAllowFrom:"允许来源(可选)",heartbeatEnabled:"心跳",heartbeatIntervalMs:"心跳间隔(毫秒)",gatewayToken:"网关令牌"},descriptionsFields:{model:"默认使用的 AI 模型",workspace:"代理文件的工作目录",maxTokens:"响应中的最大 token 数",temperature:"响应随机性(0-2)",maxToolIterations:"每条消息的最大工具调用次数",openaiApiKey:"OpenAI 模型的 API 密钥",anthropicApiKey:"Claude 模型的 API 密钥",googleApiKey:"Gemini 模型的 API 密钥",qwenApiKey:"Qwen 模型的 API 密钥",kimiApiKey:"Kimi 模型的 API 密钥",minimaxApiKey:"MiniMax 模型的 API 密钥",deepseekApiKey:"DeepSeek 模型的 API 密钥",grokApiKey:"Grok 模型的 API 密钥",openrouterApiKey:"OpenRouter 模型的 API 密钥",telegramEnabled:"启用 Telegram 机器人",telegramToken:"@BotFather 获取的机器人 API 令牌",telegramApiRoot:"自定义 Telegram API 根地址",telegramAllowFrom:"允许的用户 ID,逗号分隔",telegramDebug:"启用 Telegram 调试日志",whatsappEnabled:"启用 WhatsApp 桥接",whatsappBridgeUrl:"WhatsApp 桥接 WebSocket 地址",whatsappAllowFrom:"允许的电话号码,逗号分隔",heartbeatEnabled:"启用心跳监控",heartbeatIntervalMs:"心跳检查间隔(毫秒)",gatewayToken:"网关 API 访问认证令牌"},placeholders:{workspace:"~/.xopcbot/workspace",openaiApiKey:"sk-...",anthropicApiKey:"sk-ant-...",googleApiKey:"AIzaSy...",qwenApiKey:"sk-...",kimiApiKey:"sk-kimi-...",minimaxApiKey:"sk-cp-...",deepseekApiKey:"sk-...",openrouterApiKey:"sk-or-...",telegramToken:"1234567890:ABCdefGHIjklMNOpqrsTUVwxyz",telegramApiRoot:"https://api.telegram.org",telegramAllowFrom:"123456789, 987654321",whatsappBridgeUrl:"ws://localhost:3001",whatsappAllowFrom:"+1234567890, +0987654321",gatewayToken:"输入网关认证令牌"},connection:{title:"连接",gatewayUrl:"网关地址",gatewayUrlDesc:"网关服务器的 WebSocket 地址",authToken:"认证令牌",authTokenDesc:"可选的认证令牌"},appearance:{title:"外观",theme:"主题",themeDesc:"选择你喜欢的配色方案",themeSystem:"跟随系统",themeLight:"浅色",themeDark:"深色"},chat:{title:"对话",enableAttachments:"启用附件",enableAttachmentsDesc:"允许在对话中附加文件",showModelSelector:"显示模型选择器",showModelSelectorDesc:"显示模型选择下拉框",showThinkingSelector:"显示思考选择器",showThinkingSelectorDesc:"显示思考级别选择"}},bs={noSession:"无可用会话",noAgent:"未设置代理",noModel:"未设置模型",requestTimeout:"请求超时",sendFailed:"发送消息失败",invalidFileType:"无效的文件类型",fileTooLarge:"文件过大(最大 {{size}})",readFileFailed:"读取文件失败"},$s={dropHere:"拖放文件到此处",dragDrop:"拖放文件到此处",image:"图片",document:"文档",pdf:"PDF",word:"Word",excel:"Excel",powerpoint:"PowerPoint",text:"文本",code:"代码",archive:"压缩包",unknown:"未知"},ks={settings:"打开设置"},xs={title:"配置",save:"保存配置",noResult:"无结果",artifacts:"产物",showArtifacts:"显示产物"},Ss={title:"日志",refresh:"刷新",clear:"清空",totalLogs:"总日志数",pause:"暂停",autoRefresh:"自动刷新",level:"级别",search:"搜索",searchPlaceholder:"搜索日志...",time:"时间",message:"消息",module:"模块",noLogs:"暂无日志",noLogsDescription:"尝试调整筛选条件或稍后再查看。",details:"日志详情"},As={title:"会话",newSession:"新建会话",searchPlaceholder:"搜索会话...",totalSessions:"总会话数",activeSessions:"活跃会话",pinnedSessions:"固定会话",archivedSessions:"归档会话",noSessions:"暂无会话",delete:"删除",archive:"归档",pin:"固定",unpin:"取消固定",confirmDelete:"确定要删除此会话吗?"},Cs={title:"定时任务",addJob:"添加定时任务",editJob:"编辑任务",name:"名称(可选)",namePlaceholder:"我的定时任务",schedule:"计划表达式 *",scheduleHint:"例如:*/5 * * * *(每5分钟),0 9 * * *(每天9点)",message:"消息 *",messagePlaceholder:"助手应该做什么?",create:"创建任务",runNow:"立即执行",delete:"删除",edit:"编辑",enable:"启用",disable:"禁用",enabled:"已启用",disabled:"已禁用",running:"运行中",lastRun:"上次执行",nextRun:"下次执行",status:"状态",history:"历史记录",actions:"操作",noJobs:"暂无定时任务",confirmDelete:"确定要删除此定时任务吗?",confirmRun:"立即执行此定时任务?",success:"成功",failed:"失败",scheduleLabel:"计划",messageLabel:"消息",confirm:"确认",cancel:"取消",total:"总计",schedulePresets:{custom:"-- 自定义(在下方输入) --",everyMinute:"每分钟",every5Minutes:"每 5 分钟(默认)",every10Minutes:"每 10 分钟",every15Minutes:"每 15 分钟",every30Minutes:"每 30 分钟",everyHour:"每小时",every2Hours:"每 2 小时",every4Hours:"每 4 小时",every6Hours:"每 6 小时",every12Hours:"每 12 小时",everyDayMidnight:"每天午夜",everyDay9AM:"每天早上 9 点",everyDay9PM:"每天晚上 9 点"},scheduleHintPreset:"选择预设或输入自定义 cron 表达式",mode:"模式",modeDirect:"直接发送消息到渠道,不经过 AI 处理",modeAgent:"使用 AI 代理处理消息,然后发送回复",modeDirectOption:"直接发送(直接发送到渠道)",modeAgentOption:"AI 代理(经过 AI 处理后发送)",model:"模型",noConfiguredModels:"未配置模型",save:"保存",failedToLoadJobs:"加载任务失败",scheduleRequired:"计划表达式和消息为必填项",chatIdRequired:"Chat ID 为必填项",failedToJob:"{{mode}} 任务失败",failedToToggleJob:"切换任务状态失败",actionFailed:"操作失败",enterManuallyOrSelect:"手动输入或从最近聊天中选择",noRecentChats:"未找到最近聊天。请手动输入 chat ID(例如:Telegram 为 123456789)",timeLabels:{lessThanMinute:"不到 1 分钟",minutes:"{{count}} 分钟",hours:"{{count}} 小时",overdue:"已过期"},lastActiveLabels:{justNow:"刚刚",minutesAgo:"{{count}} 分钟前",hoursAgo:"{{count}} 小时前",daysAgo:"{{count}} 天前"}},Ts={save:"保存",cancel:"取消",confirm:"确认",close:"关闭",loading:"加载中...",error:"错误",success:"成功",noData:"暂无数据"},Ms={app:vs,nav:fs,chat:ys,settings:ws,errors:bs,fileUpload:$s,shortcuts:ks,config:xs,logs:Ss,sessions:As,cron:Cs,common:Ts},mt={en:ms,zh:Ms},K=new Map;K.set("en",mt.en);K.set("zh",mt.zh);let J="en";function r(e,t){const s=K.get(J);if(!s)return e;const i=e.split(".");let n=s;for(const a of i)if(n&&typeof n=="object"&&a in n)n=n[a];else{const l=K.get("en");if(l&&J!=="en"){let h=l;for(const p of i)if(h&&typeof h=="object"&&p in h)h=h[p];else return e;n=h}else return e}return typeof n!="string"?e:t?n.replace(/\{\{(\w+)\}\}/g,(a,l)=>{const h=t[l];return h!==void 0?String(h):`{{${l}}}`}):n}async function Es(e){if(K.has(e)){J=e;return}try{const t=await fetch(`/src/i18n/${e}.json`);if(!t.ok)throw new Error(`Failed to load ${e} translations`);const s=await t.json();K.set(e,s),J=e,window.dispatchEvent(new CustomEvent("languagechange",{detail:{language:e}}))}catch(t){console.error(`Failed to load ${e} translations:`,t),e!=="en"&&K.has("en")&&(J="en")}}function nt(e){K.has(e)?(J=e,window.dispatchEvent(new CustomEvent("languagechange",{detail:{language:e}}))):Es(e)}function Ps(e="en"){J=e}const Fs={"Type a message...":"chat.typeMessage","Attach file":"chat.attachFile","Send message":"chat.sendMessage",Abort:"chat.abort","No session available":"errors.noSession","No agent set":"errors.noAgent",Configuration:"config.title",Cancel:"settings.cancel",Save:"settings.save","No result":"config.noResult",Artifacts:"config.artifacts","Show artifacts":"config.showArtifacts"};function ie(e){const t=Fs[e];return r(t||e)}var Ls=Object.defineProperty,Ds=Object.getOwnPropertyDescriptor,M=(e,t,s,i)=>{for(var n=i>1?void 0:i?Ds(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Ls(t,s,n),n};function de(e,t=""){if(!e||!Array.isArray(e))return"";const[s,i,n]=e,a=Object.entries(i||{}).map(([p,g])=>`${p}="${g}"`).join(" "),l=Array.isArray(n)?n.map(p=>{if(Array.isArray(p)){const[g,S]=p,f=Object.entries(S||{}).map(([F,I])=>`${F}="${I}"`).join(" ");return`<${g} ${f} />`}return""}).join(""):"";return`<svg ${t?`${a} class="${t}"`:a}>${l}</svg>`}let T=class extends y{constructor(){super(...arguments),this.value="",this.attachments=[],this.isStreaming=!1,this.showAttachmentButton=!0,this.showModelSelector=!0,this._isComposing=!1,this._isDragging=!1,this._processingFiles=!1,this._isSending=!1,this.textareaRef=st(),this.fileInputRef=st(),this.maxFileSize=20*1024*1024,this.acceptedTypes="image/*,application/pdf,.docx,.pptx,.xlsx,.xls,.txt,.md,.json,.xml,.html,.css,.js,.ts,.jsx,.tsx,.yml,.yaml,.zip",this._handleDocumentDragOver=e=>{e.dataTransfer?.types.includes("Files")&&(e.preventDefault(),this._isDragging=!0)},this._handleDocumentDragLeave=e=>{e.relatedTarget===null&&(this._isDragging=!1)},this._handleDocumentDrop=async e=>{e.preventDefault(),this._isDragging=!1;const t=e.dataTransfer?.files;t&&t.length>0&&await this._processFiles(Array.from(t))},this._handleInput=e=>{const t=e.target;this.value=t.value,this._adjustTextareaHeight()},this._handleKeydown=e=>{e.key==="Enter"&&!e.shiftKey&&!this._isComposing&&(e.preventDefault(),this._send())},this._handlePaste=async e=>{const t=e.clipboardData?.items;if(!t)return;const s=[];for(const i of Array.from(t))if(i.type.startsWith("image/")){const n=i.getAsFile();n&&s.push(n)}s.length>0&&(e.preventDefault(),await this._processFiles(s))},this._handleFileInputChange=async e=>{const t=e.target,s=t.files;s&&(await this._processFiles(Array.from(s)),t.value="")}}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),document.addEventListener("dragover",this._handleDocumentDragOver),document.addEventListener("drop",this._handleDocumentDrop),document.addEventListener("dragleave",this._handleDocumentDragLeave),document.addEventListener("click",this._handleOutsideClick)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("dragover",this._handleDocumentDragOver),document.removeEventListener("drop",this._handleDocumentDrop),document.removeEventListener("dragleave",this._handleDocumentDragLeave),document.removeEventListener("click",this._handleOutsideClick)}render(){return o`
|
|
4
|
-
<div class="editor-container">
|
|
5
|
-
${this.attachments.length>0?this._renderAttachments():""}
|
|
6
|
-
|
|
7
|
-
<div class="input-row ${this._isDragging?"dragging":""}">
|
|
8
|
-
${this.showAttachmentButton?this._renderAttachmentButton():""}
|
|
9
|
-
|
|
10
|
-
<textarea
|
|
11
|
-
${it(this.textareaRef)}
|
|
12
|
-
class="text-input"
|
|
13
|
-
placeholder=${ie("Type a message...")}
|
|
14
|
-
.value=${this.value}
|
|
15
|
-
@input=${this._handleInput}
|
|
16
|
-
@keydown=${this._handleKeydown}
|
|
17
|
-
@compositionstart=${()=>this._isComposing=!0}
|
|
18
|
-
@compositionend=${()=>this._isComposing=!1}
|
|
19
|
-
@paste=${this._handlePaste}
|
|
20
|
-
rows="1"
|
|
21
|
-
></textarea>
|
|
22
|
-
|
|
23
|
-
<div class="input-actions">
|
|
24
|
-
${this._renderSendButton()}
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
|
|
28
|
-
${this._isDragging?this._renderDropOverlay():""}
|
|
29
|
-
</div>
|
|
30
|
-
`}_renderAttachments(){return o`
|
|
31
|
-
<div class="attachments-row">
|
|
32
|
-
${this.attachments.map((e,t)=>o`
|
|
33
|
-
<div class="attachment-chip">
|
|
34
|
-
<div class="attachment-preview">
|
|
35
|
-
${e.mimeType.startsWith("image/")?o`
|
|
36
|
-
<img src="${e.content}" alt="${e.name}" />
|
|
37
|
-
`:o`
|
|
38
|
-
${he(de(FileText,"w-4 h-4"))}
|
|
39
|
-
`}
|
|
40
|
-
</div>
|
|
41
|
-
<span class="attachment-name">${e.name}</span>
|
|
42
|
-
<button type="button" class="attachment-remove" @click=${()=>this._removeAttachment(t)}>
|
|
43
|
-
${he(de(is,"w-3 h-3"))}
|
|
44
|
-
</button>
|
|
45
|
-
</div>
|
|
46
|
-
`)}
|
|
47
|
-
</div>
|
|
48
|
-
`}_renderAttachmentButton(){return o`
|
|
49
|
-
<button type="button" class="attach-btn" @click=${()=>this._triggerFileSelect("all")} title=${ie("Attach file")}>
|
|
50
|
-
${he(de(es,"w-4 h-4"))}
|
|
51
|
-
</button>
|
|
52
|
-
|
|
53
|
-
<input
|
|
54
|
-
${it(this.fileInputRef)}
|
|
55
|
-
type="file"
|
|
56
|
-
multiple
|
|
57
|
-
accept=${this.acceptedTypes}
|
|
58
|
-
class="hidden"
|
|
59
|
-
@change=${this._handleFileInputChange}
|
|
60
|
-
/>
|
|
61
|
-
`}_renderSendButton(){const e=this.value.trim()||this.attachments.length>0;return this.isStreaming?o`
|
|
62
|
-
<button type="button" class="stop-btn" @click=${()=>this.onAbort?.()} title=${ie("Abort")}>
|
|
63
|
-
${he(de(ss,"w-4 h-4"))}
|
|
64
|
-
</button>
|
|
65
|
-
`:o`
|
|
66
|
-
<button
|
|
67
|
-
type="button"
|
|
68
|
-
class="send-btn ${e?"active":""}"
|
|
69
|
-
?disabled=${!e}
|
|
70
|
-
@click=${this._send}
|
|
71
|
-
title=${ie("Send message")}
|
|
72
|
-
>
|
|
73
|
-
${he(de(ts,"w-4 h-4"))}
|
|
74
|
-
</button>
|
|
75
|
-
`}_renderDropOverlay(){return o`
|
|
76
|
-
<div class="drop-overlay">
|
|
77
|
-
<span>Drop files here to attach</span>
|
|
78
|
-
</div>
|
|
79
|
-
`}_triggerFileSelect(e){let t=this.fileInputRef.value;if(t||(t=this.querySelector('input[type="file"]')),!t){console.warn("File input not found");return}e==="image"?t.accept="image/*":e==="document"?t.accept=".pdf,.docx,.pptx,.xlsx,.xls,.txt,.md,.json,.xml,.html,.css,.js,.ts,.jsx,.tsx,.yml,.yaml,.zip":t.accept=this.acceptedTypes,t.click()}_adjustTextareaHeight(){const e=this.textareaRef.value;e&&(e.style.height="auto",e.style.height=Math.min(e.scrollHeight,200)+"px")}_send(){if(this._isSending||this.isStreaming||!this.value.trim()&&this.attachments.length===0)return;this._isSending=!0;const e=[...this.attachments];this.onSend?.(this.value,e),this.value="",this.attachments=[],requestAnimationFrame(()=>{this._adjustTextareaHeight(),setTimeout(()=>{this._isSending=!1},500)})}async _processFiles(e){this._processingFiles=!0;try{for(const t of e){if(t.size>this.maxFileSize){console.warn(`File ${t.name} exceeds max size of ${this.maxFileSize} bytes`);continue}const s=await this._loadAttachment(t);this.attachments=[...this.attachments,s]}}finally{this._processingFiles=!1}}async _loadAttachment(e){const t=await this._readFileAsBase64(e),s=e.type.startsWith("image/");return{id:crypto.randomUUID(),name:e.name,type:s?"image":"document",mimeType:e.type,size:e.size,content:t}}_readFileAsBase64(e){return new Promise((t,s)=>{const i=new FileReader;i.onload=()=>t(i.result),i.onerror=()=>s(i.error),i.readAsDataURL(e)})}_removeAttachment(e){this.attachments=this.attachments.filter((t,s)=>s!==e)}_formatFileSize(e){const t=["B","KB","MB","GB"];let s=0,i=e;for(;i>=1024&&s<t.length-1;)i/=1024,s++;return`${i.toFixed(1)} ${t[s]}`}};M([oe("textarea")],T.prototype,"textarea",2);M([u({type:String})],T.prototype,"value",2);M([u({type:Array})],T.prototype,"attachments",2);M([u({type:Boolean})],T.prototype,"isStreaming",2);M([u({type:Boolean})],T.prototype,"showAttachmentButton",2);M([u({type:Boolean})],T.prototype,"showModelSelector",2);M([u({attribute:!1})],T.prototype,"currentModel",2);M([u({attribute:!1})],T.prototype,"onSend",2);M([u({attribute:!1})],T.prototype,"onAbort",2);M([u({attribute:!1})],T.prototype,"onModelSelect",2);M([c()],T.prototype,"_isComposing",2);M([c()],T.prototype,"_isDragging",2);M([c()],T.prototype,"_processingFiles",2);M([c()],T.prototype,"_isSending",2);T=M([k("message-editor")],T);function d(e){return Ie[e]||Ie.helpCircle}const Ie={messageSquare:o`
|
|
80
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
81
|
-
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
|
|
82
|
-
</svg>
|
|
83
|
-
`,settings:o`
|
|
84
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
85
|
-
<circle cx="12" cy="12" r="3"></circle>
|
|
86
|
-
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
|
|
87
|
-
</svg>
|
|
88
|
-
`,menu:o`
|
|
89
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
90
|
-
<line x1="3" y1="12" x2="21" y2="12"></line>
|
|
91
|
-
<line x1="3" y1="6" x2="21" y2="6"></line>
|
|
92
|
-
<line x1="3" y1="18" x2="21" y2="18"></line>
|
|
93
|
-
</svg>
|
|
94
|
-
`,chevronDown:o`
|
|
95
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
96
|
-
<polyline points="6 9 12 15 18 9"></polyline>
|
|
97
|
-
</svg>
|
|
98
|
-
`,sun:o`
|
|
99
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
100
|
-
<circle cx="12" cy="12" r="5"></circle>
|
|
101
|
-
<line x1="12" y1="1" x2="12" y2="3"></line>
|
|
102
|
-
<line x1="12" y1="21" x2="12" y2="23"></line>
|
|
103
|
-
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
|
104
|
-
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
|
105
|
-
<line x1="1" y1="12" x2="3" y2="12"></line>
|
|
106
|
-
<line x1="21" y1="12" x2="23" y2="12"></line>
|
|
107
|
-
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
|
108
|
-
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
|
109
|
-
</svg>
|
|
110
|
-
`,moon:o`
|
|
111
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
112
|
-
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
|
113
|
-
</svg>
|
|
114
|
-
`,monitor:o`
|
|
115
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
116
|
-
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
|
|
117
|
-
<line x1="8" y1="21" x2="16" y2="21"></line>
|
|
118
|
-
<line x1="12" y1="17" x2="12" y2="21"></line>
|
|
119
|
-
</svg>
|
|
120
|
-
`,send:o`
|
|
121
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
122
|
-
<line x1="22" y1="2" x2="11" y2="13"></line>
|
|
123
|
-
<polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
|
|
124
|
-
</svg>
|
|
125
|
-
`,paperclip:o`
|
|
126
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
127
|
-
<path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path>
|
|
128
|
-
</svg>
|
|
129
|
-
`,x:o`
|
|
130
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
131
|
-
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
132
|
-
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
133
|
-
</svg>
|
|
134
|
-
`,fileText:o`
|
|
135
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
136
|
-
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
|
137
|
-
<polyline points="14 2 14 8 20 8"></polyline>
|
|
138
|
-
<line x1="16" y1="13" x2="8" y2="13"></line>
|
|
139
|
-
<line x1="16" y1="17" x2="8" y2="17"></line>
|
|
140
|
-
<polyline points="10 9 9 9 8 9"></polyline>
|
|
141
|
-
</svg>
|
|
142
|
-
`,image:o`
|
|
143
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
144
|
-
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
145
|
-
<circle cx="8.5" cy="8.5" r="1.5"></circle>
|
|
146
|
-
<polyline points="21 15 16 10 5 21"></polyline>
|
|
147
|
-
</svg>
|
|
148
|
-
`,file:o`
|
|
149
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
150
|
-
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
|
151
|
-
<polyline points="14 2 14 8 20 8"></polyline>
|
|
152
|
-
</svg>
|
|
153
|
-
`,plug:o`
|
|
154
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
155
|
-
<path d="M12 22v-5"></path>
|
|
156
|
-
<path d="M15 8V2"></path>
|
|
157
|
-
<path d="M9 8V2"></path>
|
|
158
|
-
<path d="M15 8a3 3 0 0 1 3 3v5a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3v-5a3 3 0 0 1 3-3h6z"></path>
|
|
159
|
-
</svg>
|
|
160
|
-
`,palette:o`
|
|
161
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
162
|
-
<circle cx="13.5" cy="6.5" r=".5"></circle>
|
|
163
|
-
<circle cx="17.5" cy="10.5" r=".5"></circle>
|
|
164
|
-
<circle cx="8.5" cy="7.5" r=".5"></circle>
|
|
165
|
-
<circle cx="6.5" cy="12.5" r=".5"></circle>
|
|
166
|
-
<path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.01 17.461 2 12 2z"></path>
|
|
167
|
-
</svg>
|
|
168
|
-
`,alertCircle:o`
|
|
169
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
170
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
171
|
-
<line x1="12" y1="8" x2="12" y2="12"></line>
|
|
172
|
-
<line x1="12" y1="16" x2="12.01" y2="16"></line>
|
|
173
|
-
</svg>
|
|
174
|
-
`,check:o`
|
|
175
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
176
|
-
<polyline points="20 6 9 17 4 12"></polyline>
|
|
177
|
-
</svg>
|
|
178
|
-
`,chevronRight:o`
|
|
179
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
180
|
-
<polyline points="9 18 15 12 9 6"></polyline>
|
|
181
|
-
</svg>
|
|
182
|
-
`,arrowLeft:o`
|
|
183
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
184
|
-
<line x1="19" y1="12" x2="5" y2="12"></line>
|
|
185
|
-
<polyline points="12 19 5 12 12 5"></polyline>
|
|
186
|
-
</svg>
|
|
187
|
-
`,bot:o`
|
|
188
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
189
|
-
<rect x="3" y="11" width="18" height="10" rx="2"></rect>
|
|
190
|
-
<circle cx="12" cy="5" r="2"></circle>
|
|
191
|
-
<path d="M12 7v4"></path>
|
|
192
|
-
<line x1="8" y1="16" x2="8" y2="16.01"></line>
|
|
193
|
-
<line x1="16" y1="16" x2="16" y2="16.01"></line>
|
|
194
|
-
</svg>
|
|
195
|
-
`,helpCircle:o`
|
|
196
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
197
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
198
|
-
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path>
|
|
199
|
-
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
|
200
|
-
</svg>
|
|
201
|
-
`,rotateCcw:o`
|
|
202
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
203
|
-
<polyline points="1 4 1 10 7 10"></polyline>
|
|
204
|
-
<path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path>
|
|
205
|
-
</svg>
|
|
206
|
-
`,square:o`
|
|
207
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
208
|
-
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
209
|
-
</svg>
|
|
210
|
-
`,moreHorizontal:o`
|
|
211
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
212
|
-
<circle cx="12" cy="12" r="1"></circle>
|
|
213
|
-
<circle cx="19" cy="12" r="1"></circle>
|
|
214
|
-
<circle cx="5" cy="12" r="1"></circle>
|
|
215
|
-
</svg>
|
|
216
|
-
`,copy:o`
|
|
217
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
218
|
-
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
|
219
|
-
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
|
220
|
-
</svg>
|
|
221
|
-
`,download:o`
|
|
222
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
223
|
-
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
|
224
|
-
<polyline points="7 10 12 15 17 10"></polyline>
|
|
225
|
-
<line x1="12" y1="15" x2="12" y2="3"></line>
|
|
226
|
-
</svg>
|
|
227
|
-
`,folderOpen:o`
|
|
228
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
229
|
-
<path d="M6 17h12a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3.5"></path>
|
|
230
|
-
<path d="M2 17V5a2 2 0 0 1 2-2h4l2 2h6a2 2 0 0 1 2 2v1"></path>
|
|
231
|
-
</svg>
|
|
232
|
-
`,phone:o`
|
|
233
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
234
|
-
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
|
|
235
|
-
</svg>
|
|
236
|
-
`,globe:o`
|
|
237
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
238
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
239
|
-
<line x1="2" y1="12" x2="22" y2="12"></line>
|
|
240
|
-
<path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>
|
|
241
|
-
</svg>
|
|
242
|
-
`,terminal:o`
|
|
243
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
244
|
-
<polyline points="4 17 10 11 4 5"></polyline>
|
|
245
|
-
<line x1="12" y1="19" x2="20" y2="19"></line>
|
|
246
|
-
</svg>
|
|
247
|
-
`,zap:o`
|
|
248
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
249
|
-
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon>
|
|
250
|
-
</svg>
|
|
251
|
-
`,pin:o`
|
|
252
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
253
|
-
<line x1="12" y1="17" x2="12" y2="22"></line>
|
|
254
|
-
<path d="M5 17h14v-3a2 2 0 0 0-2-2h-3.5"></path>
|
|
255
|
-
<path d="M5 12V7a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v5"></path>
|
|
256
|
-
<circle cx="12" cy="7" r="1"></circle>
|
|
257
|
-
</svg>
|
|
258
|
-
`,pinOff:o`
|
|
259
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
260
|
-
<line x1="2" y1="2" x2="22" y2="22"></line>
|
|
261
|
-
<line x1="12" y1="17" x2="12" y2="22"></line>
|
|
262
|
-
<path d="M5 17h14v-3a2 2 0 0 0-2-2h-3.5"></path>
|
|
263
|
-
<path d="M5 12V7a2 2 0 0 1 2-2h1"></path>
|
|
264
|
-
</svg>
|
|
265
|
-
`,archive:o`
|
|
266
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
267
|
-
<polyline points="21 8 21 21 3 21 3 8"></polyline>
|
|
268
|
-
<rect x="1" y="3" width="22" height="5"></rect>
|
|
269
|
-
<line x1="10" y1="12" x2="14" y2="12"></line>
|
|
270
|
-
</svg>
|
|
271
|
-
`,archiveRestore:o`
|
|
272
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
273
|
-
<polyline points="21 8 21 21 3 21 3 8"></polyline>
|
|
274
|
-
<rect x="1" y="3" width="22" height="5"></rect>
|
|
275
|
-
<polyline points="10 12 14 12 14 8"></polyline>
|
|
276
|
-
</svg>
|
|
277
|
-
`,trash:o`
|
|
278
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
279
|
-
<polyline points="3 6 5 6 21 6"></polyline>
|
|
280
|
-
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
|
|
281
|
-
</svg>
|
|
282
|
-
`,grid:o`
|
|
283
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
284
|
-
<rect x="3" y="3" width="7" height="7"></rect>
|
|
285
|
-
<rect x="14" y="3" width="7" height="7"></rect>
|
|
286
|
-
<rect x="14" y="14" width="7" height="7"></rect>
|
|
287
|
-
<rect x="3" y="14" width="7" height="7"></rect>
|
|
288
|
-
</svg>
|
|
289
|
-
`,list:o`
|
|
290
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
291
|
-
<line x1="8" y1="6" x2="21" y2="6"></line>
|
|
292
|
-
<line x1="8" y1="12" x2="21" y2="12"></line>
|
|
293
|
-
<line x1="8" y1="18" x2="21" y2="18"></line>
|
|
294
|
-
<line x1="3" y1="6" x2="3.01" y2="6"></line>
|
|
295
|
-
<line x1="3" y1="12" x2="3.01" y2="12"></line>
|
|
296
|
-
<line x1="3" y1="18" x2="3.01" y2="18"></line>
|
|
297
|
-
</svg>
|
|
298
|
-
`,layers:o`
|
|
299
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
300
|
-
<polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
|
|
301
|
-
<polyline points="2 17 12 22 22 17"></polyline>
|
|
302
|
-
<polyline points="2 12 12 17 22 12"></polyline>
|
|
303
|
-
</svg>
|
|
304
|
-
`,circle:o`
|
|
305
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
306
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
307
|
-
</svg>
|
|
308
|
-
`,search:o`
|
|
309
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
310
|
-
<circle cx="11" cy="11" r="8"></circle>
|
|
311
|
-
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
|
312
|
-
</svg>
|
|
313
|
-
`,chevronUp:o`
|
|
314
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
315
|
-
<polyline points="18 15 12 9 6 15"></polyline>
|
|
316
|
-
</svg>
|
|
317
|
-
`,alertTriangle:o`
|
|
318
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
319
|
-
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>
|
|
320
|
-
<line x1="12" y1="9" x2="12" y2="13"></line>
|
|
321
|
-
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
|
322
|
-
</svg>
|
|
323
|
-
`,info:o`
|
|
324
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
325
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
326
|
-
<line x1="12" y1="16" x2="12" y2="12"></line>
|
|
327
|
-
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
|
328
|
-
</svg>
|
|
329
|
-
`,folder:o`
|
|
330
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
331
|
-
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
|
|
332
|
-
</svg>
|
|
333
|
-
`,clock:o`
|
|
334
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
335
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
336
|
-
<polyline points="12 6 12 12 16 14"></polyline>
|
|
337
|
-
</svg>
|
|
338
|
-
`,plus:o`
|
|
339
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
340
|
-
<line x1="12" y1="5" x2="12" y2="19"></line>
|
|
341
|
-
<line x1="5" y1="12" x2="19" y2="12"></line>
|
|
342
|
-
</svg>
|
|
343
|
-
`,refresh:o`
|
|
344
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
345
|
-
<polyline points="23 4 23 10 17 10"></polyline>
|
|
346
|
-
<polyline points="1 20 1 14 7 14"></polyline>
|
|
347
|
-
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>
|
|
348
|
-
</svg>
|
|
349
|
-
`,play:o`
|
|
350
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
351
|
-
<polygon points="5 3 19 12 5 21 5 3"></polygon>
|
|
352
|
-
</svg>
|
|
353
|
-
`,edit:o`
|
|
354
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
355
|
-
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
|
|
356
|
-
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
|
|
357
|
-
</svg>
|
|
358
|
-
`,pause:o`
|
|
359
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
360
|
-
<rect x="6" y="4" width="4" height="16"></rect>
|
|
361
|
-
<rect x="14" y="4" width="4" height="16"></rect>
|
|
362
|
-
</svg>
|
|
363
|
-
`,refreshCw:o`
|
|
364
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
365
|
-
<polyline points="23 4 23 10 17 10"></polyline>
|
|
366
|
-
<polyline points="1 20 1 14 7 14"></polyline>
|
|
367
|
-
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>
|
|
368
|
-
</svg>
|
|
369
|
-
`,checkCircle:o`
|
|
370
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
371
|
-
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
|
372
|
-
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
|
373
|
-
</svg>
|
|
374
|
-
`,xCircle:o`
|
|
375
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
376
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
377
|
-
<line x1="15" y1="9" x2="9" y2="15"></line>
|
|
378
|
-
<line x1="9" y1="9" x2="15" y2="15"></line>
|
|
379
|
-
</svg>
|
|
380
|
-
`,loader:o`
|
|
381
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
382
|
-
<line x1="12" y1="2" x2="12" y2="6"></line>
|
|
383
|
-
<line x1="12" y1="18" x2="12" y2="22"></line>
|
|
384
|
-
<line x1="4.93" y1="4.93" x2="7.76" y2="7.76"></line>
|
|
385
|
-
<line x1="16.24" y1="16.24" x2="19.07" y2="19.07"></line>
|
|
386
|
-
<line x1="2" y1="12" x2="6" y2="12"></line>
|
|
387
|
-
<line x1="18" y1="12" x2="22" y2="12"></line>
|
|
388
|
-
<line x1="4.93" y1="19.07" x2="7.76" y2="16.24"></line>
|
|
389
|
-
<line x1="16.24" y1="7.76" x2="19.07" y2="4.93"></line>
|
|
390
|
-
</svg>
|
|
391
|
-
`,slash:o`
|
|
392
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
393
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
394
|
-
<line x1="4.93" y1="4.93" x2="19.07" y2="19.07"></line>
|
|
395
|
-
</svg>
|
|
396
|
-
`};function Is(e){return e.includes("pdf")?o`
|
|
397
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ef4444" stroke-width="2">
|
|
398
|
-
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
399
|
-
<polyline points="14,2 14,8 20,8"/>
|
|
400
|
-
</svg>
|
|
401
|
-
`:e.includes("word")||e.includes("document")?o`
|
|
402
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2563eb" stroke-width="2">
|
|
403
|
-
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
404
|
-
<polyline points="14,2 14,8 20,8"/>
|
|
405
|
-
</svg>
|
|
406
|
-
`:e.includes("sheet")||e.includes("excel")?o`
|
|
407
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#16a34a" stroke-width="2">
|
|
408
|
-
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
409
|
-
<polyline points="14,2 14,8 20,8"/>
|
|
410
|
-
</svg>
|
|
411
|
-
`:e.includes("presentation")||e.includes("powerpoint")?o`
|
|
412
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2">
|
|
413
|
-
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
414
|
-
<polyline points="14,2 14,8 20,8"/>
|
|
415
|
-
</svg>
|
|
416
|
-
`:Ie.file}var Os=Object.defineProperty,Rs=Object.getOwnPropertyDescriptor,vt=(e,t,s,i)=>{for(var n=i>1?void 0:i?Rs(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Os(t,s,n),n};let Oe=class extends y{constructor(){super(...arguments),this.attachments=[]}createRenderRoot(){return this}render(){if(!this.attachments?.length)return null;const e=this.attachments.filter(s=>s.type==="image"||s.mimeType?.startsWith("image/")),t=this.attachments.filter(s=>s.type!=="image"&&!s.mimeType?.startsWith("image/"));return o`
|
|
417
|
-
<div class="flex flex-col gap-2 mt-2">
|
|
418
|
-
${e.length>0?this._renderImageGallery(e):""}
|
|
419
|
-
${t.length>0?this._renderDocumentList(t):""}
|
|
420
|
-
</div>
|
|
421
|
-
`}_renderImageGallery(e){const t=e.length;let s="single";return t===2?s="double":t===3?s="triple":t>=4&&(s="quad"),o`
|
|
422
|
-
<div class="image-gallery ${s}">
|
|
423
|
-
${e.map(i=>o`
|
|
424
|
-
<img
|
|
425
|
-
src="${i.data||i.content}"
|
|
426
|
-
alt="${i.name||r("fileUpload.image")}"
|
|
427
|
-
@click=${()=>this._handleImageClick(i)}
|
|
428
|
-
/>
|
|
429
|
-
`)}
|
|
430
|
-
</div>
|
|
431
|
-
`}_renderDocumentList(e){return o`
|
|
432
|
-
<div class="flex flex-col gap-2">
|
|
433
|
-
${e.map(t=>this._renderDocumentPreview(t))}
|
|
434
|
-
</div>
|
|
435
|
-
`}_renderDocumentPreview(e){const t=e.name||r("fileUpload.document"),s=e.size?this._formatFileSize(e.size):"";return o`
|
|
436
|
-
<div class="document-preview" @click=${()=>this._handleDocumentClick(e)}>
|
|
437
|
-
<div class="icon">${Is(e.mimeType||"")}</div>
|
|
438
|
-
<div class="info">
|
|
439
|
-
<div class="name">${t}</div>
|
|
440
|
-
<div class="meta">${s||e.mimeType||r("fileUpload.unknown")}</div>
|
|
441
|
-
</div>
|
|
442
|
-
</div>
|
|
443
|
-
`}_formatFileSize(e){const t=["B","KB","MB","GB"];let s=0,i=e;for(;i>=1024&&s<t.length-1;)i/=1024,s++;return`${i.toFixed(1)} ${t[s]}`}_handleImageClick(e){this.dispatchEvent(new CustomEvent("image-click",{detail:e,bubbles:!0,composed:!0}))}_handleDocumentClick(e){this.dispatchEvent(new CustomEvent("document-click",{detail:e,bubbles:!0,composed:!0}))}};vt([u({attribute:!1})],Oe.prototype,"attachments",2);Oe=vt([k("attachment-renderer")],Oe);var Bs=Object.defineProperty,Ks=Object.getOwnPropertyDescriptor,ft=(e,t,s,i)=>{for(var n=i>1?void 0:i?Ks(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Bs(t,s,n),n};let Re=class extends y{createRenderRoot(){return this}render(){if(!this.usage)return null;const e=[];return this.usage.totalTokens!==void 0?e.push(`${this.usage.totalTokens} tokens`):this.usage.inputTokens!==void 0&&this.usage.outputTokens!==void 0&&e.push(`${this.usage.inputTokens+this.usage.outputTokens} tokens`),this.usage.cost!==void 0&&this.usage.cost>0&&e.push(`$${this.usage.cost.toFixed(4)}`),e.length===0?null:o`
|
|
444
|
-
<span class="usage-badge">
|
|
445
|
-
${e.join(" · ")}
|
|
446
|
-
</span>
|
|
447
|
-
`}};ft([u({attribute:!1})],Re.prototype,"usage",2);Re=ft([k("usage-badge")],Re);var js=Object.defineProperty,Us=Object.getOwnPropertyDescriptor,Ne=(e,t,s,i)=>{for(var n=i>1?void 0:i?Us(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&js(t,s,n),n};let Ae=class extends y{constructor(){super(...arguments),this.isStreaming=!1}createRenderRoot(){return this}render(){const e=this.message.role==="user"||this.message.role==="user-with-attachments",t=this.message.role==="assistant";this.message.role==="tool"||this.message.role;const s=r(e?"chat.you":t?"chat.assistant":"chat.tool"),i=s.charAt(0);return o`
|
|
448
|
-
<div class="message-item ${e?"flex-row-reverse":""}">
|
|
449
|
-
<div class="avatar ${e?"user":t?"assistant":"tool"}">
|
|
450
|
-
${i}
|
|
451
|
-
</div>
|
|
452
|
-
|
|
453
|
-
<div class="flex flex-col gap-1 max-w-[85%]">
|
|
454
|
-
<div class="flex items-center gap-2 text-xs text-muted">
|
|
455
|
-
<span class="font-medium">${s}</span>
|
|
456
|
-
<span>·</span>
|
|
457
|
-
<span>${this._formatTime(this.message.timestamp)}</span>
|
|
458
|
-
${this.isStreaming?o`<span class="text-primary animate-pulse">${r("chat.thinking")}</span>`:""}
|
|
459
|
-
</div>
|
|
460
|
-
|
|
461
|
-
<div class="message-bubble ${e?"bg-primary-light":"bg-secondary"}">
|
|
462
|
-
${this._renderContent(this.message.content)}
|
|
463
|
-
${this.message.attachments?.length?o`
|
|
464
|
-
<attachment-renderer .attachments=${this.message.attachments}></attachment-renderer>
|
|
465
|
-
`:""}
|
|
466
|
-
</div>
|
|
467
|
-
|
|
468
|
-
${t&&this.message.usage?o`
|
|
469
|
-
<usage-badge .usage=${this.message.usage}></usage-badge>
|
|
470
|
-
`:""}
|
|
471
|
-
</div>
|
|
472
|
-
</div>
|
|
473
|
-
`}_renderContent(e){return!e||e.length===0?this.isStreaming?o`<span class="streaming-cursor"></span>`:null:o`
|
|
474
|
-
<div class="markdown-content">
|
|
475
|
-
${e.map(t=>this._renderContentBlock(t))}
|
|
476
|
-
${this.isStreaming?o`<span class="streaming-cursor"></span>`:""}
|
|
477
|
-
</div>
|
|
478
|
-
`}_renderContentBlock(e){switch(e.type){case"text":if(e.text)return o`<p class="whitespace-pre-wrap">${e.text}</p>`;break;case"image":if(e.source?.data)return o`<img src="${e.source.data}" class="rounded-lg max-w-full" />`;break;case"tool_use":case"tool_result":return this._renderToolCall(e);default:if(e.text)return o`<p class="whitespace-pre-wrap">${e.text}</p>`}return null}_renderToolCall(e){const t=e.is_error||e.error,s=e.name||e.function?.name||"Tool",i=e.input||e.function?.arguments;return o`
|
|
479
|
-
<div class="tool-call ${t?"tool-call--error":""}">
|
|
480
|
-
<div class="tool-call-header">
|
|
481
|
-
<span>🔧 ${s}</span>
|
|
482
|
-
${t?o`<span class="text-red-500 text-xs">Error</span>`:""}
|
|
483
|
-
</div>
|
|
484
|
-
${i?o`
|
|
485
|
-
<pre class="tool-call-content">${JSON.stringify(i,null,2)}</pre>
|
|
486
|
-
`:""}
|
|
487
|
-
${e.content?o`
|
|
488
|
-
<div class="tool-call-result">${JSON.stringify(e.content)}</div>
|
|
489
|
-
`:""}
|
|
490
|
-
</div>
|
|
491
|
-
`}_formatTime(e){return e?new Date(e).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}):""}};Ne([u({attribute:!1})],Ae.prototype,"message",2);Ne([u({type:Boolean})],Ae.prototype,"isStreaming",2);Ae=Ne([k("message-bubble")],Ae);var Hs=Object.defineProperty,Ns=Object.getOwnPropertyDescriptor,Pe=(e,t,s,i)=>{for(var n=i>1?void 0:i?Ns(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Hs(t,s,n),n};let fe=class extends y{constructor(){super(...arguments),this.messages=[],this.isStreaming=!1,this.useVirtualScroll=!1}createRenderRoot(){return this}render(){return!this.messages||this.messages.length===0?this._renderEmptyState():o`
|
|
492
|
-
<div class="flex flex-col gap-4 pb-4">
|
|
493
|
-
${this.messages.map((e,t)=>o`
|
|
494
|
-
<message-bubble
|
|
495
|
-
.message=${e}
|
|
496
|
-
.isStreaming=${this.isStreaming&&t===this.messages.length-1}
|
|
497
|
-
></message-bubble>
|
|
498
|
-
`)}
|
|
499
|
-
</div>
|
|
500
|
-
`}_renderEmptyState(){return o`
|
|
501
|
-
<div class="empty-state">
|
|
502
|
-
<div class="icon">💬</div>
|
|
503
|
-
<div class="title">${r("chat.emptyState")}</div>
|
|
504
|
-
<div class="description">${r("chat.emptyStateDescription")}</div>
|
|
505
|
-
</div>
|
|
506
|
-
`}scrollToBottom(){const e=this.closest(".overflow-y-auto");e&&(e.scrollTop=e.scrollHeight)}isNearBottom(e=100){const t=this.closest(".overflow-y-auto");if(!t)return!0;const{scrollTop:s,scrollHeight:i,clientHeight:n}=t;return i-s-n<e}};Pe([u({attribute:!1})],fe.prototype,"messages",2);Pe([u({type:Boolean})],fe.prototype,"isStreaming",2);Pe([u({type:Boolean})],fe.prototype,"useVirtualScroll",2);fe=Pe([k("message-list")],fe);var zs=Object.defineProperty,qs=Object.getOwnPropertyDescriptor,ae=(e,t,s,i)=>{for(var n=i>1?void 0:i?qs(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&zs(t,s,n),n};let V=class extends y{constructor(){super(...arguments),this.tools=new Map,this.pendingToolCalls=new Set,this.isStreaming=!1,this._currentMessage=null,this._isComplete=!1}createRenderRoot(){return this}setMessage(e,t){this._currentMessage=e,this._isComplete=t}render(){return this._currentMessage?o`
|
|
507
|
-
<div class="flex gap-3 message-item">
|
|
508
|
-
<div class="avatar assistant">
|
|
509
|
-
AI
|
|
510
|
-
</div>
|
|
511
|
-
|
|
512
|
-
<div class="flex flex-col gap-1 max-w-[85%]">
|
|
513
|
-
<div class="flex items-center gap-2 text-xs text-muted">
|
|
514
|
-
<span class="font-medium">Assistant</span>
|
|
515
|
-
<span>·</span>
|
|
516
|
-
<span class="text-accent animate-pulse">thinking...</span>
|
|
517
|
-
</div>
|
|
518
|
-
|
|
519
|
-
<div class="rounded-xl p-3 bg-secondary">
|
|
520
|
-
${this.renderStreamingContent()}
|
|
521
|
-
</div>
|
|
522
|
-
</div>
|
|
523
|
-
</div>
|
|
524
|
-
`:null}renderStreamingContent(){const e=this._currentMessage?.content||[];return o`
|
|
525
|
-
<div class="markdown-content">
|
|
526
|
-
${e.map(t=>t.type==="text"?o`<p class="whitespace-pre-wrap">${this._escapeHtml(t.text||"")}<span class="streaming-cursor"></span></p>`:t.type==="tool_use"?this.renderToolUse(t):"")}
|
|
527
|
-
${this.isStreaming&&(!e.length||e[e.length-1]?.type!=="text")?o`<span class="streaming-cursor"></span>`:""}
|
|
528
|
-
</div>
|
|
529
|
-
`}renderToolUse(e){const t=e.name||e.function?.name,s=e.input||e.function?.arguments||{},i=typeof s=="string"?s:JSON.stringify(s,null,2);return o`
|
|
530
|
-
<div class="tool-call">
|
|
531
|
-
<div class="name">
|
|
532
|
-
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
533
|
-
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/>
|
|
534
|
-
</svg>
|
|
535
|
-
<span>${t}</span>
|
|
536
|
-
</div>
|
|
537
|
-
<pre class="input">${i}</pre>
|
|
538
|
-
</div>
|
|
539
|
-
`}_escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}};ae([u({attribute:!1})],V.prototype,"tools",2);ae([u({attribute:!1})],V.prototype,"pendingToolCalls",2);ae([u({type:Boolean})],V.prototype,"isStreaming",2);ae([c()],V.prototype,"_currentMessage",2);ae([c()],V.prototype,"_isComplete",2);V=ae([k("streaming-message-container")],V);var Js=Object.defineProperty,Gs=Object.getOwnPropertyDescriptor,x=(e,t,s,i)=>{for(var n=i>1?void 0:i?Gs(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Js(t,s,n),n};function Ws(){return window.location.origin}function te(e){return`${Ws()}${e}`}function pe(e){const t={"Content-Type":"application/json"};return e&&(t.Authorization=`Bearer ${e}`),t}let w=class extends y{constructor(){super(...arguments),this.enableAttachments=!0,this.enableModelSelector=!0,this._connectionState="disconnected",this._error=null,this._messages=[],this._isStreaming=!1,this._streamingContent="",this._streamingMessage=null,this._reconnectCount=0,this._isAtBottom=!0,this._currentSessionKey=null,this._sessions=[],this._hasMoreMessages=!0,this._isLoadingMore=!1,this._shouldReconnect=!0,this._isSending=!1,this._lastLoadedSessionKey=null,this._handleScroll=()=>{if(!this._chatMessages)return;const{scrollTop:e,scrollHeight:t,clientHeight:s}=this._chatMessages,i=t-e-s<50;i!==this._isAtBottom&&(this._isAtBottom=i),e<100&&!this._isAtBottom&&this._hasMoreMessages&&!this._isLoadingMore&&this._loadMoreMessages()},this._handleSend=(e,t)=>{const s=t?.map(i=>({type:i.type||"file",mimeType:i.mimeType,data:i.content,name:i.name,size:i.size}));this.sendMessage(e,s)}}get _maxReconnectAttempts(){return this.config?.maxReconnectAttempts??10}get _autoReconnect(){return this.config?.autoReconnect??!0}createRenderRoot(){return this}async connectedCallback(){super.connectedCallback(),this.classList.add("chat-container"),await Ps("en")}firstUpdated(){this._chatMessages&&this._chatMessages.addEventListener("scroll",this._handleScroll),this._handleRouteChange()}updated(e){super.updated(e),e.has("config")&&this.config&&this._connectionState==="disconnected"&&this.connect(),e.has("route")&&this.route&&this._handleRouteChange()}async _handleRouteChange(){const e=this.route;if(!e)return;let t=null;switch(e.type){case"recent":this._lastLoadedSessionKey=null,await this._loadSessions();return;case"session":t=e.sessionKey;break;case"new":await this._createNewSession();return}t&&t!==this._lastLoadedSessionKey&&(await this._loadSession(t,0),this._lastLoadedSessionKey=t)}async _loadSession(e,t=0){if(this.config)try{const s=te(`/api/sessions/${encodeURIComponent(e)}?offset=${t}&limit=50`),i=pe(this.config.token),n=await fetch(s,{headers:i});if(!n.ok)throw new Error(`HTTP ${n.status}`);const l=(await n.json()).session;this._currentSessionKey=e;const h=l.messages||[],p=h.filter(g=>g.role==="user"||g.role==="assistant").map(g=>({role:g.role,content:typeof g.content=="string"?[{type:"text",text:g.content}]:g.content||[],attachments:g.attachments,timestamp:g.timestamp?new Date(g.timestamp).getTime():Date.now()}));t>0?this._messages=[...p,...this._messages]:this._messages=p,this._hasMoreMessages=h.length>=50,t===0&&this._scrollToBottom(!1),this.requestUpdate()}catch(s){console.error("[GatewayChat] Failed to load session:",s)}}async _loadMoreMessages(){if(!this._currentSessionKey||this._isLoadingMore||!this._hasMoreMessages)return;this._isLoadingMore=!0;const e=this._messages.length;try{await this._loadSession(this._currentSessionKey,e)}finally{this._isLoadingMore=!1}}disconnectedCallback(){super.disconnectedCallback(),this._shouldReconnect=!1,this.disconnect(),this._chatMessages&&this._chatMessages.removeEventListener("scroll",this._handleScroll)}_scrollToBottom(e=!0){this.updateComplete.then(()=>{this._chatMessages&&this._chatMessages.scrollTo({top:this._chatMessages.scrollHeight,behavior:e?"smooth":"auto"})})}connect(){if(!(!this.config||this._connectionState==="connecting")){this._connectionState="connecting",this._error=null,this.requestUpdate();try{const e=te("/api/events"),t=new URL(e);this.config.token&&t.searchParams.set("token",this.config.token),this._eventSource=new EventSource(t.toString()),this._eventSource.onopen=()=>{this._connectionState="connected",this._error=null,this._reconnectCount=0,this.requestUpdate(),this._lastLoadedSessionKey||this._loadSessions()},this._eventSource.addEventListener("connected",()=>{this._connectionState="connected",this._error=null,this.requestUpdate()}),this._eventSource.addEventListener("config.reload",s=>{try{const i=JSON.parse(s.data);this.dispatchEvent(new CustomEvent("config-reload",{detail:i}))}catch{}}),this._eventSource.addEventListener("channels.status",s=>{try{const i=JSON.parse(s.data);this.dispatchEvent(new CustomEvent("channels-status",{detail:i}))}catch{}}),this._eventSource.addEventListener("message.sent",s=>{try{const i=JSON.parse(s.data);this.dispatchEvent(new CustomEvent("message-sent",{detail:i}))}catch{}}),this._eventSource.onerror=()=>{this._eventSource?.readyState===EventSource.CLOSED?(this._connectionState="disconnected",this._handlePermanentDisconnect()):this._connectionState="reconnecting",this.requestUpdate()}}catch(e){console.error("[GatewayChat] Failed to create EventSource:",e),this._connectionState="error",this._error=r("errors.connectionError"),this.requestUpdate()}}}_handlePermanentDisconnect(){this._isStreaming&&(this._isStreaming=!1,this._isSending=!1,this._streamingContent="",this._streamingMessage=null),this._shouldReconnect&&this._autoReconnect&&(this._reconnectCount++,this._reconnectCount>this._maxReconnectAttempts&&(this._error=r("errors.connectionError"),this._connectionState="error"))}disconnect(){this._shouldReconnect=!1,this._eventSource?.close(),this._eventSource=void 0,this._agentAbort?.abort(),this._agentAbort=void 0,this._connectionState="disconnected"}reconnect(){this._shouldReconnect=!0,this._reconnectCount=0,this.disconnect(),setTimeout(()=>this.connect(),100)}async _loadSessions(){if(this.config)try{const e=te("/api/sessions?limit=20"),t=pe(this.config.token),s=await fetch(e,{headers:t});if(!s.ok)throw new Error(`HTTP ${s.status}`);const a=((await s.json()).items||[]).filter(h=>h.key.startsWith("gateway:")).sort((h,p)=>new Date(p.updatedAt).getTime()-new Date(h.updatedAt).getTime());this._sessions=a;const l=a.filter(h=>h.messageCount>0);if(l.length>0){const h=l[0].key;await this._loadSession(h,0),this._lastLoadedSessionKey=h,this._updateUrlWithSession(h)}else if(a.length>0){const h=a[0];this._currentSessionKey=h.key,this._messages=[],this._lastLoadedSessionKey=h.key,this._updateUrlWithSession(h.key)}else await this._createNewSession()}catch(e){console.error("[GatewayChat] Failed to load sessions:",e)}}_updateUrlWithSession(e){const t=`#/chat/${encodeURIComponent(e)}`;location.hash!==t&&history.replaceState(null,"",t)}async _createNewSession(){if(!this.config)return;const e=this._sessions.find(t=>t.messageCount===0);if(e){this._currentSessionKey=e.key,this._messages=[],this._lastLoadedSessionKey=e.key,this._updateUrlWithSession(e.key);return}try{const t=te("/api/sessions"),s={...pe(this.config.token),"Content-Type":"application/json"},i=await fetch(t,{method:"POST",headers:s,body:JSON.stringify({channel:"gateway"})});if(!i.ok)throw new Error(`HTTP ${i.status}`);const a=(await i.json()).session;this._currentSessionKey=a.key,this._messages=[],this._sessions=[{key:a.key,name:a.name,updatedAt:a.updatedAt},...this._sessions],this._currentSessionKey=a.key,this._lastLoadedSessionKey=a.key,this._updateUrlWithSession(a.key),this._scrollToBottom(),this.requestUpdate()}catch(t){console.error("[GatewayChat] Failed to create new session:",t)}}async sendMessage(e,t){if(!(this._isSending||this._isStreaming)&&!(!e.trim()&&!t?.length)&&this.config){this._isSending=!0,this._messages=[...this._messages,{role:"user",content:e?[{type:"text",text:e}]:[],attachments:t,timestamp:Date.now()}],this._scrollToBottom(),this.requestUpdate();try{this._agentAbort=new AbortController;const s=te("/api/agent"),i={...pe(this.config.token),Accept:"text/event-stream"},n=this._currentSessionKey?this._currentSessionKey.replace("gateway:",""):"default",a=await fetch(s,{method:"POST",headers:i,body:JSON.stringify({message:e,channel:"gateway",chatId:n,attachments:t}),signal:this._agentAbort.signal});if(!a.ok){const h=await a.json().catch(()=>({}));throw new Error(h.error?.message||`HTTP ${a.status}`)}if((a.headers.get("Content-Type")||"").includes("text/event-stream")&&a.body)await this._consumeSSEStream(a.body);else{const h=await a.json();h.ok&&h.payload?.content&&(this._updateStreamingMessage(h.payload.content),this._finalizeMessage())}}catch(s){if(s.name==="AbortError")return;this._error=s instanceof Error?s.message:r("errors.sendFailed"),this._isStreaming=!1,this._isSending=!1,this._streamingMessage=null,this.requestUpdate()}finally{this._agentAbort=void 0,this._isSending=!1}}}async _consumeSSEStream(e){const t=e.pipeThrough(new TextDecoderStream).getReader();let s="",i="",n="";try{for(;;){const{done:a,value:l}=await t.read();if(a)break;for(s+=l;s.includes(`
|
|
540
|
-
`);){const h=s.indexOf(`
|
|
541
|
-
`),p=s.slice(0,h);s=s.slice(h+1),p.startsWith("event:")?i=p.slice(6).trim():p.startsWith("data:")?n+=(n?`
|
|
542
|
-
`:"")+p.slice(5).trim():p===""&&n&&(this._handleSSEEvent(i||"message",n),i="",n="")}}if(s.trim()||n){if(s.trim()){const a=s.split(`
|
|
543
|
-
`);for(const l of a)l.startsWith("event:")?i=l.slice(6).trim():l.startsWith("data:")?n+=(n?`
|
|
544
|
-
`:"")+l.slice(5).trim():l===""&&n&&(this._handleSSEEvent(i||"message",n),i="",n="")}n&&this._handleSSEEvent(i||"message",n)}}finally{t.releaseLock()}}_handleSSEEvent(e,t){try{const s=JSON.parse(t);switch(e){case"status":this._isStreaming=!0,this.requestUpdate();break;case"token":s.content&&this._updateStreamingMessage(s.content);break;case"error":this._error=s.content||s.error?.message||r("errors.sendFailed"),this._isStreaming=!1,this._isSending=!1,this._streamingMessage=null,this.requestUpdate();break;case"result":this._finalizeMessage();break;default:s.content&&this._updateStreamingMessage(s.content);break}}catch{}}_updateStreamingMessage(e){if(this._streamingMessage){const t=this._streamingMessage.content.find(s=>s.type==="text");t?t.text=(t.text||"")+e:this._streamingMessage.content.push({type:"text",text:e})}else this._streamingMessage={role:"assistant",content:[{type:"text",text:e}],timestamp:Date.now()};this._isStreaming=!0,this._streamingContent=e,this.requestUpdate(),this._isAtBottom&&this._scrollToBottom()}_finalizeMessage(){this._streamingMessage&&(this._messages=[...this._messages,this._streamingMessage],this._streamingMessage=null),this._isStreaming=!1,this._streamingContent="",this._isSending=!1,this._isAtBottom&&this._scrollToBottom(),this.requestUpdate()}async request(e,t,s){if(!this.config)throw new Error("Not configured");const i=te(t),n=await fetch(i,{method:e,headers:pe(this.config.token),body:s?JSON.stringify(s):void 0});if(!n.ok){const a=await n.json().catch(()=>({error:{message:`HTTP ${n.status}`}}));throw new Error(a.error?.message||`HTTP ${n.status}`)}return n.json()}abort(){this._agentAbort?.abort(),this._agentAbort=void 0,this._isStreaming=!1,this._isSending=!1,this._streamingContent="",this._streamingMessage=null,this.requestUpdate()}get connectionState(){return this._connectionState}get messages(){return this._messages}clearMessages(){this._messages=[],this.requestUpdate()}render(){return o`
|
|
545
|
-
${this._renderStatus()}
|
|
546
|
-
${this._renderHeader()}
|
|
547
|
-
|
|
548
|
-
<div class="chat-messages">
|
|
549
|
-
<div class="chat-messages-inner">
|
|
550
|
-
${this._renderMessages()}
|
|
551
|
-
</div>
|
|
552
|
-
</div>
|
|
553
|
-
|
|
554
|
-
<!-- Scroll to bottom button - placed outside overflow container -->
|
|
555
|
-
${this._isAtBottom?"":o`
|
|
556
|
-
<button
|
|
557
|
-
class="scroll-to-bottom-btn"
|
|
558
|
-
style="position: fixed; bottom: 100px; right: 24px; width: 48px; height: 48px; border-radius: 50%; background: #3b82f6; color: white; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 100;"
|
|
559
|
-
@click=${this._scrollToBottom}
|
|
560
|
-
title="Scroll to bottom"
|
|
561
|
-
>
|
|
562
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
|
|
563
|
-
</button>
|
|
564
|
-
`}
|
|
565
|
-
|
|
566
|
-
<div class="chat-input-container">
|
|
567
|
-
<div class="chat-input-inner">
|
|
568
|
-
${this._renderInput()}
|
|
569
|
-
</div>
|
|
570
|
-
</div>
|
|
571
|
-
`}_renderHeader(){return o`
|
|
572
|
-
<div class="chat-header">
|
|
573
|
-
<div class="chat-header-title">
|
|
574
|
-
<span class="font-semibold">${r("chat.title")||"XopcBot"}</span>
|
|
575
|
-
${this._currentSessionKey?o`
|
|
576
|
-
<span class="text-xs text-muted ml-2">${this._sessions.find(e=>e.key===this._currentSessionKey)?.name||this._currentSessionKey}</span>
|
|
577
|
-
`:""}
|
|
578
|
-
</div>
|
|
579
|
-
<button class="new-session-btn" @click=${()=>this._createNewSession()}>
|
|
580
|
-
${this._renderIcon("plus")}
|
|
581
|
-
<span>${r("chat.newSession")||"New Chat"}</span>
|
|
582
|
-
</button>
|
|
583
|
-
</div>
|
|
584
|
-
`}_renderStatus(){return this._connectionState==="error"&&this._error?o`
|
|
585
|
-
<div class="status-bar error">
|
|
586
|
-
${this._renderIcon("alertCircle")}
|
|
587
|
-
<span>${this._error}</span>
|
|
588
|
-
<button class="underline ml-auto" @click=${()=>this.reconnect()}>${r("chat.retry")}</button>
|
|
589
|
-
</div>
|
|
590
|
-
`:this._connectionState==="reconnecting"?o`
|
|
591
|
-
<div class="status-bar warning">
|
|
592
|
-
<div class="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
|
|
593
|
-
<span>${r("chat.reconnecting")}</span>
|
|
594
|
-
</div>
|
|
595
|
-
`:this._connectionState==="connecting"?o`
|
|
596
|
-
<div class="status-bar warning">
|
|
597
|
-
<div class="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
|
|
598
|
-
<span>${r("chat.connecting")}</span>
|
|
599
|
-
</div>
|
|
600
|
-
`:null}_renderIcon(e){return{alertCircle:o`
|
|
601
|
-
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
602
|
-
<circle cx="12" cy="12" r="10"/>
|
|
603
|
-
<line x1="12" y1="8" x2="12" y2="12"/>
|
|
604
|
-
<line x1="12" y1="16" x2="12.01" y2="16"/>
|
|
605
|
-
</svg>
|
|
606
|
-
`,chevronDown:o`
|
|
607
|
-
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
608
|
-
<polyline points="6 9 12 15 18 9"/>
|
|
609
|
-
</svg>
|
|
610
|
-
`,plus:o`
|
|
611
|
-
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
612
|
-
<line x1="12" y1="5" x2="12" y2="19"/>
|
|
613
|
-
<line x1="5" y1="12" x2="19" y2="12"/>
|
|
614
|
-
</svg>
|
|
615
|
-
`}[e]||""}_renderScrollToBottomButton(){return o`
|
|
616
|
-
<button
|
|
617
|
-
class="scroll-to-bottom-btn"
|
|
618
|
-
style="background: red !important; width: 60px; height: 60px; font-size: 24px;"
|
|
619
|
-
@click=${this._scrollToBottom}
|
|
620
|
-
title="Scroll to bottom"
|
|
621
|
-
>
|
|
622
|
-
👇
|
|
623
|
-
</button>
|
|
624
|
-
`}_renderMessages(){return!this._messages.length&&!this._isStreaming?o`
|
|
625
|
-
<div class="empty-state" style="padding-top: 30vh;">
|
|
626
|
-
<div class="icon">🤖</div>
|
|
627
|
-
<div class="title">${r("chat.welcomeTitle")}</div>
|
|
628
|
-
<div class="description">${r("chat.welcomeDescription")}</div>
|
|
629
|
-
</div>
|
|
630
|
-
`:o`
|
|
631
|
-
<div class="flex flex-col gap-4">
|
|
632
|
-
${this._messages.map(e=>this._renderMessage(e))}
|
|
633
|
-
${this._isStreaming&&this._streamingMessage?this._renderStreamingMessage():""}
|
|
634
|
-
</div>
|
|
635
|
-
`}_renderMessage(e){const t=e.role==="user";return!e.content?.some(i=>i.text)&&!e.attachments?.length?null:o`
|
|
636
|
-
<div class="message-item ${t?"flex-row-reverse":""}">
|
|
637
|
-
<div class="avatar ${t?"user":"assistant"}">
|
|
638
|
-
${t?r("chat.you").charAt(0):"X"}
|
|
639
|
-
</div>
|
|
640
|
-
|
|
641
|
-
<div class="flex flex-col gap-1 max-w-[calc(100%-3rem)]">
|
|
642
|
-
<div class="flex items-center gap-2 text-xs text-muted ${t?"flex-row-reverse":""}">
|
|
643
|
-
<span class="font-medium">${r(t?"chat.you":"chat.assistant")}</span>
|
|
644
|
-
<span>·</span>
|
|
645
|
-
<span>${this._formatTime(e.timestamp)}</span>
|
|
646
|
-
</div>
|
|
647
|
-
|
|
648
|
-
<div class="message-bubble ${t?"user":"assistant"}">
|
|
649
|
-
${this._renderMessageContent(e.content)}
|
|
650
|
-
${e.attachments?.length?this._renderAttachments(e.attachments):""}
|
|
651
|
-
</div>
|
|
652
|
-
</div>
|
|
653
|
-
</div>
|
|
654
|
-
`}_renderStreamingMessage(){const e=this._streamingMessage?.content||[];return o`
|
|
655
|
-
<div class="message-item">
|
|
656
|
-
<div class="avatar assistant">X</div>
|
|
657
|
-
<div class="flex flex-col gap-1 max-w-[calc(100%-3rem)]">
|
|
658
|
-
<div class="flex items-center gap-2 text-xs text-muted">
|
|
659
|
-
<span class="font-medium">${r("chat.assistant")}</span>
|
|
660
|
-
<span>·</span>
|
|
661
|
-
<span class="text-primary animate-pulse">${r("chat.thinking")}</span>
|
|
662
|
-
</div>
|
|
663
|
-
<div class="message-bubble assistant">
|
|
664
|
-
<div class="markdown-content">
|
|
665
|
-
${e.map(t=>t.type==="text"&&t.text?o`<p class="whitespace-pre-wrap">${t.text}<span class="streaming-cursor"></span></p>`:"")}
|
|
666
|
-
${e.length?"":o`<span class="streaming-cursor"></span>`}
|
|
667
|
-
</div>
|
|
668
|
-
</div>
|
|
669
|
-
</div>
|
|
670
|
-
</div>
|
|
671
|
-
`}_renderMessageContent(e){return!e||e.length===0?null:o`
|
|
672
|
-
<div class="markdown-content">
|
|
673
|
-
${e.map(t=>t.type==="text"&&t.text?o`<p class="whitespace-pre-wrap">${t.text}</p>`:"")}
|
|
674
|
-
</div>
|
|
675
|
-
`}_renderAttachments(e){const t=e.filter(i=>i.type==="image"||i.mimeType?.startsWith("image/")),s=e.filter(i=>i.type!=="image"&&!i.mimeType?.startsWith("image/"));return o`
|
|
676
|
-
<div class="flex flex-col gap-2 mt-2">
|
|
677
|
-
${t.length>0?this._renderImageGallery(t):""}
|
|
678
|
-
${s.length>0?this._renderDocumentList(s):""}
|
|
679
|
-
</div>
|
|
680
|
-
`}_renderImageGallery(e){const t=e.length;let s="single";return t===2?s="double":t===3?s="triple":t>=4&&(s="quad"),o`
|
|
681
|
-
<div class="image-gallery ${s}">
|
|
682
|
-
${e.map(i=>o`<img src="${i.data}" alt="${i.name||"Image"}" />`)}
|
|
683
|
-
</div>
|
|
684
|
-
`}_renderDocumentList(e){return o`
|
|
685
|
-
<div class="flex flex-col gap-2">
|
|
686
|
-
${e.map(t=>this._renderDocumentPreview(t))}
|
|
687
|
-
</div>
|
|
688
|
-
`}_renderDocumentPreview(e){const t=e.name||"Document",s=e.size?this._formatFileSize(e.size):"";return o`
|
|
689
|
-
<div class="document-preview">
|
|
690
|
-
<div class="icon">${this._getDocumentIcon(e.mimeType||"")}</div>
|
|
691
|
-
<div class="info">
|
|
692
|
-
<div class="name">${t}</div>
|
|
693
|
-
<div class="meta">${s||e.mimeType||"File"}</div>
|
|
694
|
-
</div>
|
|
695
|
-
</div>
|
|
696
|
-
`}_getDocumentIcon(e){const t=e.includes("pdf")?"#ef4444":e.includes("word")||e.includes("document")?"#2563eb":e.includes("sheet")||e.includes("excel")?"#16a34a":"currentColor";return o`
|
|
697
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="${t}" stroke-width="2">
|
|
698
|
-
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
699
|
-
<polyline points="14,2 14,8 20,8"/>
|
|
700
|
-
</svg>
|
|
701
|
-
`}_renderInput(){return o`
|
|
702
|
-
<message-editor
|
|
703
|
-
.isStreaming=${this._isStreaming}
|
|
704
|
-
.showAttachmentButton=${this.enableAttachments}
|
|
705
|
-
.showModelSelector=${this.enableModelSelector}
|
|
706
|
-
.onSend=${(e,t)=>this._handleSend(e,t)}
|
|
707
|
-
.onAbort=${()=>this.abort()}
|
|
708
|
-
></message-editor>
|
|
709
|
-
`}_formatTime(e){return new Date(e).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}_formatFileSize(e){const t=["B","KB","MB","GB"];let s=0,i=e;for(;i>=1024&&s<t.length-1;)i/=1024,s++;return`${i.toFixed(1)} ${t[s]}`}};x([u({attribute:!1})],w.prototype,"config",2);x([u({attribute:!1})],w.prototype,"route",2);x([u({type:Boolean})],w.prototype,"enableAttachments",2);x([u({type:Boolean})],w.prototype,"enableModelSelector",2);x([oe("message-editor")],w.prototype,"_messageEditor",2);x([oe(".chat-messages")],w.prototype,"_chatMessages",2);x([c()],w.prototype,"_connectionState",2);x([c()],w.prototype,"_error",2);x([c()],w.prototype,"_messages",2);x([c()],w.prototype,"_isStreaming",2);x([c()],w.prototype,"_streamingContent",2);x([c()],w.prototype,"_streamingMessage",2);x([c()],w.prototype,"_reconnectCount",2);x([c()],w.prototype,"_isAtBottom",2);x([c()],w.prototype,"_currentSessionKey",2);x([c()],w.prototype,"_sessions",2);x([c()],w.prototype,"_hasMoreMessages",2);x([c()],w.prototype,"_isLoadingMore",2);w=x([k("xopcbot-gateway-chat")],w);var Vs=Object.defineProperty,Qs=Object.getOwnPropertyDescriptor,ze=(e,t,s,i)=>{for(var n=i>1?void 0:i?Qs(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Vs(t,s,n),n};let Ce=class extends y{constructor(){super(...arguments),this.selected=!1}createRenderRoot(){return this}_emit(e){this.dispatchEvent(new CustomEvent("session-action",{detail:{action:e,key:this.session.key},bubbles:!0,composed:!0}))}_formatDate(e){const t=new Date(e),i=Math.floor((new Date().getTime()-t.getTime())/(1e3*60*60*24));return i===0?t.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}):i===1?"Yesterday":i<7?t.toLocaleDateString([],{weekday:"short"}):t.toLocaleDateString([],{month:"short",day:"numeric"})}_getChannelIcon(e){return{telegram:"send",whatsapp:"phone",gateway:"globe",cli:"terminal"}[e]||"messageSquare"}_getStatusBadge(){switch(this.session.status){case"archived":return"bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400";case"pinned":return"bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400";default:return"bg-green-100 text-green-600 dark:bg-green-900/30 dark:text-green-400"}}render(){const e=this.session.name||this.session.key,t=this.session.status==="archived",s=this.session.status==="pinned";return o`
|
|
710
|
-
<div
|
|
711
|
-
class="session-card ${this.selected?"session-card--selected":""} ${t?"session-card--archived":""}"
|
|
712
|
-
@click=${()=>this._emit("click")}
|
|
713
|
-
>
|
|
714
|
-
<div class="session-card__header">
|
|
715
|
-
<div class="session-card__channel">
|
|
716
|
-
<span class="channel-icon">${d(this._getChannelIcon(this.session.sourceChannel))}</span>
|
|
717
|
-
<span class="channel-name">${this.session.sourceChannel}</span>
|
|
718
|
-
</div>
|
|
719
|
-
<div class="session-card__meta">
|
|
720
|
-
${s?o`<span class="pin-badge" title="Pinned">${d("pin")}</span>`:""}
|
|
721
|
-
<span class="date">${this._formatDate(this.session.updatedAt)}</span>
|
|
722
|
-
</div>
|
|
723
|
-
</div>
|
|
724
|
-
|
|
725
|
-
<div class="session-card__title">
|
|
726
|
-
${e}
|
|
727
|
-
</div>
|
|
728
|
-
|
|
729
|
-
<div class="session-card__stats">
|
|
730
|
-
<span class="stat">
|
|
731
|
-
${d("messageSquare")}
|
|
732
|
-
${this.session.messageCount}
|
|
733
|
-
</span>
|
|
734
|
-
<span class="stat">
|
|
735
|
-
${d("zap")}
|
|
736
|
-
${this._formatTokens(this.session.estimatedTokens)}
|
|
737
|
-
</span>
|
|
738
|
-
</div>
|
|
739
|
-
|
|
740
|
-
${this.session.tags.length>0?o`
|
|
741
|
-
<div class="session-card__tags">
|
|
742
|
-
${this.session.tags.slice(0,3).map(i=>o`
|
|
743
|
-
<span class="tag">${i}</span>
|
|
744
|
-
`)}
|
|
745
|
-
${this.session.tags.length>3?o`
|
|
746
|
-
<span class="tag tag--more">+${this.session.tags.length-3}</span>
|
|
747
|
-
`:""}
|
|
748
|
-
</div>
|
|
749
|
-
`:""}
|
|
750
|
-
|
|
751
|
-
<div class="session-card__actions" @click=${i=>i.stopPropagation()}>
|
|
752
|
-
${t?o`
|
|
753
|
-
<button
|
|
754
|
-
class="btn-icon btn-icon--success"
|
|
755
|
-
title="Unarchive"
|
|
756
|
-
@click=${()=>this._emit("unarchive")}
|
|
757
|
-
>${d("archiveRestore")}</button>
|
|
758
|
-
`:o`
|
|
759
|
-
<button
|
|
760
|
-
class="btn-icon"
|
|
761
|
-
title="Archive"
|
|
762
|
-
@click=${()=>this._emit("archive")}
|
|
763
|
-
>${d("archive")}</button>
|
|
764
|
-
`}
|
|
765
|
-
|
|
766
|
-
${s?o`
|
|
767
|
-
<button
|
|
768
|
-
class="btn-icon btn-icon--primary"
|
|
769
|
-
title="Unpin"
|
|
770
|
-
@click=${()=>this._emit("unpin")}
|
|
771
|
-
>${d("pinOff")}</button>
|
|
772
|
-
`:o`
|
|
773
|
-
<button
|
|
774
|
-
class="btn-icon"
|
|
775
|
-
title="Pin"
|
|
776
|
-
@click=${()=>this._emit("pin")}
|
|
777
|
-
>${d("pin")}</button>
|
|
778
|
-
`}
|
|
779
|
-
|
|
780
|
-
<button
|
|
781
|
-
class="btn-icon"
|
|
782
|
-
title="Export"
|
|
783
|
-
@click=${()=>this._emit("export")}
|
|
784
|
-
>${d("download")}</button>
|
|
785
|
-
|
|
786
|
-
<button
|
|
787
|
-
class="btn-icon btn-icon--danger"
|
|
788
|
-
title="Delete"
|
|
789
|
-
@click=${()=>this._emit("delete")}
|
|
790
|
-
>${d("trash")}</button>
|
|
791
|
-
</div>
|
|
792
|
-
</div>
|
|
793
|
-
`}_formatTokens(e){return e>=1e3?(e/1e3).toFixed(1)+"k":e.toString()}};ze([u({attribute:!1})],Ce.prototype,"session",2);ze([u({type:Boolean})],Ce.prototype,"selected",2);Ce=ze([k("session-card")],Ce);var Xs=Object.defineProperty,Ys=Object.getOwnPropertyDescriptor,re=(e,t,s,i)=>{for(var n=i>1?void 0:i?Ys(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Xs(t,s,n),n};let Q=class extends y{constructor(){super(...arguments),this.sessions=[],this.loading=!1,this.hasMore=!1,this.selectedKey=null,this._viewMode="grid"}createRenderRoot(){return this}_emit(e,t){this.dispatchEvent(new CustomEvent("list-action",{detail:{action:e,key:t},bubbles:!0,composed:!0}))}_handleCardAction(e){const{action:t,key:s}=e.detail;t==="click"?this._emit("select",s):this._emit(t,s)}_loadMore(){this.dispatchEvent(new CustomEvent("load-more",{bubbles:!0,composed:!0}))}render(){return this.loading&&this.sessions.length===0?this._renderLoading():this.sessions.length===0?this._renderEmpty():o`
|
|
794
|
-
<div class="session-list">
|
|
795
|
-
${this._renderToolbar()}
|
|
796
|
-
|
|
797
|
-
<div class="session-list__content session-list__content--${this._viewMode}">
|
|
798
|
-
${this.sessions.map(e=>o`
|
|
799
|
-
<session-card
|
|
800
|
-
.session=${e}
|
|
801
|
-
.selected=${e.key===this.selectedKey}
|
|
802
|
-
@session-action=${this._handleCardAction}
|
|
803
|
-
></session-card>
|
|
804
|
-
`)}
|
|
805
|
-
</div>
|
|
806
|
-
|
|
807
|
-
${this.hasMore?o`
|
|
808
|
-
<div class="session-list__load-more">
|
|
809
|
-
<button class="btn btn--secondary" @click=${this._loadMore}>
|
|
810
|
-
${d("chevronDown")}
|
|
811
|
-
Load More
|
|
812
|
-
</button>
|
|
813
|
-
</div>
|
|
814
|
-
`:""}
|
|
815
|
-
|
|
816
|
-
${this.loading?o`
|
|
817
|
-
<div class="session-list__loading-overlay">
|
|
818
|
-
<div class="spinner"></div>
|
|
819
|
-
</div>
|
|
820
|
-
`:""}
|
|
821
|
-
</div>
|
|
822
|
-
`}_renderToolbar(){return o`
|
|
823
|
-
<div class="session-list__toolbar">
|
|
824
|
-
<div class="session-list__count">
|
|
825
|
-
${this.sessions.length} sessions
|
|
826
|
-
</div>
|
|
827
|
-
|
|
828
|
-
<div class="session-list__view-toggle">
|
|
829
|
-
<button
|
|
830
|
-
class="btn-icon ${this._viewMode==="grid"?"btn-icon--active":""}"
|
|
831
|
-
title="Grid view"
|
|
832
|
-
@click=${()=>this._viewMode="grid"}
|
|
833
|
-
>${d("grid")}</button>
|
|
834
|
-
<button
|
|
835
|
-
class="btn-icon ${this._viewMode==="list"?"btn-icon--active":""}"
|
|
836
|
-
title="List view"
|
|
837
|
-
@click=${()=>this._viewMode="list"}
|
|
838
|
-
>${d("list")}</button>
|
|
839
|
-
</div>
|
|
840
|
-
</div>
|
|
841
|
-
`}_renderLoading(){return o`
|
|
842
|
-
<div class="session-list session-list--loading">
|
|
843
|
-
<div class="session-list__skeleton">
|
|
844
|
-
${Array.from({length:6}).map(()=>o`
|
|
845
|
-
<div class="skeleton-card">
|
|
846
|
-
<div class="skeleton skeleton--header"></div>
|
|
847
|
-
<div class="skeleton skeleton--title"></div>
|
|
848
|
-
<div class="skeleton skeleton--stats"></div>
|
|
849
|
-
</div>
|
|
850
|
-
`)}
|
|
851
|
-
</div>
|
|
852
|
-
</div>
|
|
853
|
-
`}_renderEmpty(){return o`
|
|
854
|
-
<div class="session-list session-list--empty">
|
|
855
|
-
<div class="empty-state">
|
|
856
|
-
<div class="empty-state__icon">${d("folderOpen")}</div>
|
|
857
|
-
<div class="empty-state__title">No sessions found</div>
|
|
858
|
-
<div class="empty-state__description">
|
|
859
|
-
Start a conversation to create your first session.
|
|
860
|
-
</div>
|
|
861
|
-
</div>
|
|
862
|
-
</div>
|
|
863
|
-
`}};re([u({attribute:!1})],Q.prototype,"sessions",2);re([u({type:Boolean})],Q.prototype,"loading",2);re([u({type:Boolean})],Q.prototype,"hasMore",2);re([u({type:String})],Q.prototype,"selectedKey",2);re([c()],Q.prototype,"_viewMode",2);Q=re([k("session-list")],Q);var Zs=Object.defineProperty,ei=Object.getOwnPropertyDescriptor,Y=(e,t,s,i)=>{for(var n=i>1?void 0:i?ei(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Zs(t,s,n),n};let j=class extends y{constructor(){super(...arguments),this.session=null,this.open=!1,this.loading=!1,this._searchQuery="",this._searchResults=[],this._currentResultIndex=-1}createRenderRoot(){return this}_emit(e){this.dispatchEvent(new CustomEvent("detail-action",{detail:{action:e},bubbles:!0,composed:!0}))}_handleClose(){this._emit("close")}_handleBackdropClick(e){e.target===e.currentTarget&&this._handleClose()}_handleSearch(e){const t=e.target;this._searchQuery=t.value,this._performSearch()}_performSearch(){if(!this.session||!this._searchQuery.trim()){this._searchResults=[],this._currentResultIndex=-1;return}const e=this._searchQuery.toLowerCase(),t=[];this.session.messages.forEach((s,i)=>{s.content.toLowerCase().includes(e)&&t.push(i)}),this._searchResults=t,this._currentResultIndex=t.length>0?0:-1}_navigateSearch(e){if(this._searchResults.length===0)return;e==="next"?this._currentResultIndex=(this._currentResultIndex+1)%this._searchResults.length:this._currentResultIndex=(this._currentResultIndex-1+this._searchResults.length)%this._searchResults.length;const t=this._searchResults[this._currentResultIndex],s=this.querySelector(`[data-message-index="${t}"]`);s&&s.scrollIntoView({behavior:"smooth",block:"center"})}_highlightText(e){if(!this._searchQuery.trim())return e;const t=this._searchQuery;return e.split(new RegExp(`(${t})`,"gi")).map((i,n)=>i.toLowerCase()===t.toLowerCase()?o`<mark class="search-highlight">${i}</mark>`:i)}_formatDate(e){return new Date(e).toLocaleString()}render(){return this.open?o`
|
|
864
|
-
<div class="drawer-backdrop" @click=${this._handleBackdropClick}>
|
|
865
|
-
<div class="drawer drawer--${this.open?"open":"closed"}">
|
|
866
|
-
${this._renderHeader()}
|
|
867
|
-
${this._renderSearch()}
|
|
868
|
-
${this._renderContent()}
|
|
869
|
-
${this._renderActions()}
|
|
870
|
-
</div>
|
|
871
|
-
</div>
|
|
872
|
-
`:""}_renderHeader(){if(!this.session)return"";const e=this.session.status==="archived",t=this.session.status==="pinned";return o`
|
|
873
|
-
<div class="drawer-header">
|
|
874
|
-
<div class="drawer-header__info">
|
|
875
|
-
<div class="drawer-header__title">
|
|
876
|
-
${this.session.name||this.session.key}
|
|
877
|
-
${t?o`<span class="pin-badge">${d("pin")}</span>`:""}
|
|
878
|
-
${e?o`<span class="archive-badge">Archived</span>`:""}
|
|
879
|
-
</div>
|
|
880
|
-
<div class="drawer-header__meta">
|
|
881
|
-
<span>${this.session.sourceChannel}</span>
|
|
882
|
-
<span>•</span>
|
|
883
|
-
<span>${this.session.messageCount} messages</span>
|
|
884
|
-
<span>•</span>
|
|
885
|
-
<span>${this._formatDate(this.session.updatedAt)}</span>
|
|
886
|
-
</div>
|
|
887
|
-
</div>
|
|
888
|
-
<button class="btn-icon" @click=${this._handleClose} title="Close">
|
|
889
|
-
${d("x")}
|
|
890
|
-
</button>
|
|
891
|
-
</div>
|
|
892
|
-
`}_renderSearch(){return this.session?o`
|
|
893
|
-
<div class="drawer-search">
|
|
894
|
-
<div class="search-input-wrapper">
|
|
895
|
-
${d("search")}
|
|
896
|
-
<input
|
|
897
|
-
type="text"
|
|
898
|
-
placeholder="Search in session..."
|
|
899
|
-
.value=${this._searchQuery}
|
|
900
|
-
@input=${this._handleSearch}
|
|
901
|
-
/>
|
|
902
|
-
${this._searchQuery?o`
|
|
903
|
-
<button class="btn-icon btn-icon--sm" @click=${()=>{this._searchQuery="",this._performSearch()}}>
|
|
904
|
-
${d("x")}
|
|
905
|
-
</button>
|
|
906
|
-
`:""}
|
|
907
|
-
</div>
|
|
908
|
-
|
|
909
|
-
${this._searchResults.length>0?o`
|
|
910
|
-
<div class="search-nav">
|
|
911
|
-
<span class="search-count">${this._currentResultIndex+1} / ${this._searchResults.length}</span>
|
|
912
|
-
<button class="btn-icon btn-icon--sm" @click=${()=>this._navigateSearch("prev")} title="Previous">
|
|
913
|
-
${d("chevronUp")}
|
|
914
|
-
</button>
|
|
915
|
-
<button class="btn-icon btn-icon--sm" @click=${()=>this._navigateSearch("next")} title="Next">
|
|
916
|
-
${d("chevronDown")}
|
|
917
|
-
</button>
|
|
918
|
-
</div>
|
|
919
|
-
`:""}
|
|
920
|
-
</div>
|
|
921
|
-
`:""}_renderContent(){return this.loading?o`
|
|
922
|
-
<div class="drawer-content drawer-content--loading">
|
|
923
|
-
<div class="spinner"></div>
|
|
924
|
-
<span>Loading...</span>
|
|
925
|
-
</div>
|
|
926
|
-
`:this.session?o`
|
|
927
|
-
<div class="drawer-content">
|
|
928
|
-
${this.session.messages.map((e,t)=>{const s=this._searchResults.includes(t),i=this._searchResults[this._currentResultIndex]===t;return o`
|
|
929
|
-
<div
|
|
930
|
-
class="message ${e.role} ${s?"message--highlight":""} ${i?"message--current":""}"
|
|
931
|
-
data-message-index="${t}"
|
|
932
|
-
>
|
|
933
|
-
<div class="message__header">
|
|
934
|
-
<span class="message__role">${e.role}</span>
|
|
935
|
-
${e.timestamp?o`<span class="message__time">${this._formatDate(e.timestamp)}</span>`:""}
|
|
936
|
-
</div>
|
|
937
|
-
<div class="message__content">${this._highlightText(e.content)}</div>
|
|
938
|
-
</div>
|
|
939
|
-
`})}
|
|
940
|
-
</div>
|
|
941
|
-
`:o`
|
|
942
|
-
<div class="drawer-content drawer-content--empty">
|
|
943
|
-
<span>No session selected</span>
|
|
944
|
-
</div>
|
|
945
|
-
`}_renderActions(){if(!this.session)return"";const e=this.session.status==="archived",t=this.session.status==="pinned";return o`
|
|
946
|
-
<div class="drawer-actions">
|
|
947
|
-
${e?o`
|
|
948
|
-
<button class="btn btn--secondary" @click=${()=>this._emit("unarchive")}>
|
|
949
|
-
${d("archiveRestore")} Unarchive
|
|
950
|
-
</button>
|
|
951
|
-
`:o`
|
|
952
|
-
<button class="btn btn--secondary" @click=${()=>this._emit("archive")}>
|
|
953
|
-
${d("archive")} Archive
|
|
954
|
-
</button>
|
|
955
|
-
`}
|
|
956
|
-
|
|
957
|
-
${t?o`
|
|
958
|
-
<button class="btn btn--secondary" @click=${()=>this._emit("unpin")}>
|
|
959
|
-
${d("pinOff")} Unpin
|
|
960
|
-
</button>
|
|
961
|
-
`:o`
|
|
962
|
-
<button class="btn btn--secondary" @click=${()=>this._emit("pin")}>
|
|
963
|
-
${d("pin")} Pin
|
|
964
|
-
</button>
|
|
965
|
-
`}
|
|
966
|
-
|
|
967
|
-
<button class="btn btn--secondary" @click=${()=>this._emit("export")}>
|
|
968
|
-
${d("download")} Export
|
|
969
|
-
</button>
|
|
970
|
-
|
|
971
|
-
<button class="btn btn--danger" @click=${()=>this._emit("delete")}>
|
|
972
|
-
${d("trash")} Delete
|
|
973
|
-
</button>
|
|
974
|
-
</div>
|
|
975
|
-
`}};Y([u({attribute:!1})],j.prototype,"session",2);Y([u({type:Boolean})],j.prototype,"open",2);Y([u({type:Boolean})],j.prototype,"loading",2);Y([c()],j.prototype,"_searchQuery",2);Y([c()],j.prototype,"_searchResults",2);Y([c()],j.prototype,"_currentResultIndex",2);j=Y([k("session-detail-drawer")],j);var ti=Object.defineProperty,si=Object.getOwnPropertyDescriptor,Z=(e,t,s,i)=>{for(var n=i>1?void 0:i?si(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&ti(t,s,n),n};let U=class extends y{constructor(){super(...arguments),this.open=!1,this.title="Confirm",this.message="Are you sure?",this.confirmText="Confirm",this.cancelText="Cancel",this.type="warning"}createRenderRoot(){return this}_emit(e){this.dispatchEvent(new CustomEvent("confirm",{detail:{confirmed:e},bubbles:!0,composed:!0})),this.open=!1}_handleBackdropClick(e){e.target===e.currentTarget&&this._emit(!1)}_getIcon(){switch(this.type){case"danger":return"trash";case"warning":return"alertTriangle";case"info":return"info";default:return"helpCircle"}}_getIconColor(){switch(this.type){case"danger":return"text-red-500";case"warning":return"text-amber-500";case"info":return"text-blue-500";default:return"text-gray-500"}}render(){return this.open?o`
|
|
976
|
-
<div class="modal-backdrop" @click=${this._handleBackdropClick}>
|
|
977
|
-
<div class="modal modal--${this.type}">
|
|
978
|
-
<div class="modal__icon ${this._getIconColor()}">
|
|
979
|
-
${d(this._getIcon())}
|
|
980
|
-
</div>
|
|
981
|
-
|
|
982
|
-
<div class="modal__content">
|
|
983
|
-
<h3 class="modal__title">${this.title}</h3>
|
|
984
|
-
<p class="modal__message">${this.message}</p>
|
|
985
|
-
</div>
|
|
986
|
-
|
|
987
|
-
<div class="modal__actions">
|
|
988
|
-
<button class="btn btn--secondary" @click=${()=>this._emit(!1)}>
|
|
989
|
-
${this.cancelText}
|
|
990
|
-
</button>
|
|
991
|
-
<button class="btn btn--${this.type==="danger"?"danger":"primary"}" @click=${()=>this._emit(!0)}>
|
|
992
|
-
${this.confirmText}
|
|
993
|
-
</button>
|
|
994
|
-
</div>
|
|
995
|
-
</div>
|
|
996
|
-
</div>
|
|
997
|
-
`:""}};Z([u({type:Boolean})],U.prototype,"open",2);Z([u({type:String})],U.prototype,"title",2);Z([u({type:String})],U.prototype,"message",2);Z([u({type:String})],U.prototype,"confirmText",2);Z([u({type:String})],U.prototype,"cancelText",2);Z([u({type:String})],U.prototype,"type",2);U=Z([k("confirm-dialog")],U);class ii{constructor(t,s){this.baseUrl=t.replace(/\/$/,""),this.token=s}async request(t,s,i){const n={"Content-Type":"application/json"};this.token&&(n.Authorization=`Bearer ${this.token}`);const a=await fetch(`${this.baseUrl}${s}`,{method:t,headers:n,body:i?JSON.stringify(i):void 0});if(!a.ok){const l=await a.json().catch(()=>({error:"Request failed"}));throw new Error(l.error||`HTTP ${a.status}`)}return a.json()}async listSessions(t){const s=new URLSearchParams;t?.status&&s.set("status",t.status),t?.search&&s.set("search",t.search),t?.limit&&s.set("limit",String(t.limit)),t?.offset&&s.set("offset",String(t.offset));const i=s.toString(),n=`/api/sessions${i?`?${i}`:""}`;return await this.request("GET",n)}async getSession(t){try{return(await this.request("GET",`/api/sessions/${t}`)).session||null}catch(s){if(s instanceof Error&&s.message.includes("404"))return null;throw s}}async deleteSession(t){return await this.request("DELETE",`/api/sessions/${t}`)}async archiveSession(t){return await this.request("POST",`/api/sessions/${t}/archive`)}async unarchiveSession(t){return await this.request("POST",`/api/sessions/${t}/unarchive`)}async pinSession(t){return await this.request("POST",`/api/sessions/${t}/pin`)}async unpinSession(t){return await this.request("POST",`/api/sessions/${t}/unpin`)}async renameSession(t,s){return await this.request("POST",`/api/sessions/${t}/rename`,{name:s})}async exportSession(t,s="json"){return(await this.request("GET",`/api/sessions/${t}/export?format=${s}`)).content}async getStats(){return await this.request("GET","/api/sessions/stats")}}var ni=Object.defineProperty,oi=Object.getOwnPropertyDescriptor,A=(e,t,s,i)=>{for(var n=i>1?void 0:i?oi(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&ni(t,s,n),n};let b=class extends y{constructor(){super(...arguments),this._sessions=[],this._loading=!1,this._hasMore=!1,this._stats=null,this._searchQuery="",this._statusFilter="all",this._offset=0,this._error=null,this._detailOpen=!1,this._detailSession=null,this._detailLoading=!1,this._confirmOpen=!1,this._confirmTitle="",this._confirmMessage="",this._confirmKey=null,this._confirmAction=null,this._limit=20,this._initialized=!1,this._debouncedSearch=this._debounce(()=>{this._loadSessions(!0)},300)}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this._tryInitialize()}willUpdate(e){super.willUpdate(e),e.has("config")&&this._tryInitialize()}_tryInitialize(){if(this._initialized)return;const e=window.location.origin;this._api=new ii(e,this.config?.token),this._initialized=!0,this._loadSessions(),this._loadStats()}disconnectedCallback(){super.disconnectedCallback()}async _loadSessions(e=!1){if(!this._loading){this._loading=!0,this._error=null,e&&(this._offset=0,this._sessions=[]);try{const t={limit:this._limit,offset:this._offset,sortBy:"updatedAt",sortOrder:"desc",...this._statusFilter!=="all"&&{status:this._statusFilter},...this._searchQuery&&{search:this._searchQuery}},s=await this._api.listSessions(t);e?this._sessions=s.items:this._sessions=[...this._sessions,...s.items],this._hasMore=s.hasMore,this._offset=s.offset+s.items.length}catch(t){this._error=t instanceof Error?t.message:"Failed to load sessions",console.error("[SessionManager] Load error:",t)}finally{this._loading=!1}}}async _loadStats(){try{this._stats=await this._api.getStats()}catch(e){console.error("[SessionManager] Stats error:",e)}}async _openDetail(e){this._detailOpen=!0,this._detailLoading=!0;try{const t=await this._api.getSession(e);this._detailSession=t}catch(t){console.error("[SessionManager] Load detail error:",t),this._detailOpen=!1}finally{this._detailLoading=!1}}_closeDetail(){this._detailOpen=!1,this._detailSession=null}_handleDetailAction(e){const{action:t}=e.detail,s=this._detailSession?.key;if(s)switch(t){case"close":this._closeDetail();break;case"delete":this._showConfirm(s);break;case"archive":this._archiveSession(s);break;case"unarchive":this._unarchiveSession(s);break;case"pin":this._pinSession(s);break;case"unpin":this._unpinSession(s);break;case"export":this._exportSession(s);break}}_showConfirm(e){this._confirmKey=e,this._confirmAction="delete",this._confirmTitle="Delete Session",this._confirmMessage=`Are you sure you want to delete session "${e}"?
|
|
998
|
-
|
|
999
|
-
This action cannot be undone.`,this._confirmOpen=!0}_handleConfirm(e){if(!e.detail.confirmed||!this._confirmKey){this._confirmOpen=!1,this._confirmKey=null;return}this._deleteSession(this._confirmKey),this._confirmOpen=!1,this._confirmKey=null}async _deleteSession(e){try{await this._api.deleteSession(e),this._sessions=this._sessions.filter(t=>t.key!==e),this._detailSession?.key===e&&this._closeDetail(),await this._loadStats()}catch(t){alert("Failed to delete session: "+(t instanceof Error?t.message:String(t)))}}async _archiveSession(e){try{await this._api.archiveSession(e),this._updateSessionStatus(e,"archived"),this._detailSession?.key===e&&(this._detailSession={...this._detailSession,status:"archived"}),await this._loadStats()}catch(t){console.error("[SessionManager] Archive error:",t)}}async _unarchiveSession(e){try{await this._api.unarchiveSession(e),this._updateSessionStatus(e,"active"),this._detailSession?.key===e&&(this._detailSession={...this._detailSession,status:"active"}),await this._loadStats()}catch(t){console.error("[SessionManager] Unarchive error:",t)}}async _pinSession(e){try{await this._api.pinSession(e),this._updateSessionStatus(e,"pinned"),this._detailSession?.key===e&&(this._detailSession={...this._detailSession,status:"pinned"}),await this._loadStats()}catch(t){console.error("[SessionManager] Pin error:",t)}}async _unpinSession(e){try{await this._api.unpinSession(e),this._updateSessionStatus(e,"active"),this._detailSession?.key===e&&(this._detailSession={...this._detailSession,status:"active"}),await this._loadStats()}catch(t){console.error("[SessionManager] Unpin error:",t)}}async _exportSession(e){try{const t=await this._api.exportSession(e,"json"),s=new Blob([t],{type:"application/json"}),i=URL.createObjectURL(s),n=document.createElement("a");n.href=i,n.download=`session-${e.replace(/[^a-z0-9]/gi,"_")}.json`,document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(i)}catch(t){alert("Failed to export session: "+(t instanceof Error?t.message:String(t)))}}_updateSessionStatus(e,t){this._sessions=this._sessions.map(s=>s.key===e?{...s,status:t}:s)}_handleListAction(e){const{action:t,key:s}=e.detail;switch(t){case"select":this._openDetail(s);break;case"delete":this._showConfirm(s);break;case"archive":this._archiveSession(s);break;case"unarchive":this._unarchiveSession(s);break;case"pin":this._pinSession(s);break;case"unpin":this._unpinSession(s);break;case"export":this._exportSession(s);break}}_handleSearch(e){const t=e.target;this._searchQuery=t.value,this._debouncedSearch()}_debounce(e,t){let s;return()=>{clearTimeout(s),s=setTimeout(e,t)}}_handleStatusFilter(e){this._statusFilter=e,this._loadSessions(!0)}_handleLoadMore(){this._loadSessions()}render(){return o`
|
|
1000
|
-
<div class="session-manager">
|
|
1001
|
-
${this._renderHeader()}
|
|
1002
|
-
${this._renderFilters()}
|
|
1003
|
-
${this._renderStats()}
|
|
1004
|
-
${this._error?o`<div class="error-banner">${this._error}</div>`:""}
|
|
1005
|
-
|
|
1006
|
-
<session-list
|
|
1007
|
-
.sessions=${this._sessions}
|
|
1008
|
-
.loading=${this._loading}
|
|
1009
|
-
.hasMore=${this._hasMore}
|
|
1010
|
-
@list-action=${this._handleListAction}
|
|
1011
|
-
@load-more=${this._handleLoadMore}
|
|
1012
|
-
></session-list>
|
|
1013
|
-
</div>
|
|
1014
|
-
|
|
1015
|
-
<session-detail-drawer
|
|
1016
|
-
.session=${this._detailSession}
|
|
1017
|
-
.open=${this._detailOpen}
|
|
1018
|
-
.loading=${this._detailLoading}
|
|
1019
|
-
@detail-action=${this._handleDetailAction}
|
|
1020
|
-
></session-detail-drawer>
|
|
1021
|
-
|
|
1022
|
-
<confirm-dialog
|
|
1023
|
-
.open=${this._confirmOpen}
|
|
1024
|
-
.title=${this._confirmTitle}
|
|
1025
|
-
.message=${this._confirmMessage}
|
|
1026
|
-
.confirmText="Delete"
|
|
1027
|
-
.cancelText="Cancel"
|
|
1028
|
-
.type="danger"
|
|
1029
|
-
@confirm=${this._handleConfirm}
|
|
1030
|
-
></confirm-dialog>
|
|
1031
|
-
`}_renderHeader(){return o`
|
|
1032
|
-
<div class="session-manager__header">
|
|
1033
|
-
<h1 class="page-title">${d("folderOpen")} ${r("sessions.title")}</h1>
|
|
1034
|
-
<div class="search-box">
|
|
1035
|
-
${d("search")}
|
|
1036
|
-
<input
|
|
1037
|
-
type="text"
|
|
1038
|
-
placeholder="${r("sessions.searchPlaceholder")}"
|
|
1039
|
-
.value=${this._searchQuery}
|
|
1040
|
-
@input=${this._handleSearch}
|
|
1041
|
-
/>
|
|
1042
|
-
</div>
|
|
1043
|
-
</div>
|
|
1044
|
-
`}_renderFilters(){return o`
|
|
1045
|
-
<div class="session-manager__filters">
|
|
1046
|
-
${[{key:"all",label:"All",icon:"layers"},{key:"active",label:"Active",icon:"circle"},{key:"pinned",label:"Pinned",icon:"pin"},{key:"archived",label:"Archived",icon:"archive"}].map(t=>o`
|
|
1047
|
-
<button
|
|
1048
|
-
class="filter-btn ${this._statusFilter===t.key?"filter-btn--active":""}"
|
|
1049
|
-
@click=${()=>this._handleStatusFilter(t.key)}
|
|
1050
|
-
>
|
|
1051
|
-
${d(t.icon)}
|
|
1052
|
-
${t.label}
|
|
1053
|
-
</button>
|
|
1054
|
-
`)}
|
|
1055
|
-
</div>
|
|
1056
|
-
`}_renderStats(){return this._stats?o`
|
|
1057
|
-
<div class="session-manager__stats">
|
|
1058
|
-
<div class="stat-card">
|
|
1059
|
-
<div class="stat-value">${this._stats.totalSessions}</div>
|
|
1060
|
-
<div class="stat-label">${r("sessions.totalSessions")}</div>
|
|
1061
|
-
</div>
|
|
1062
|
-
<div class="stat-card">
|
|
1063
|
-
<div class="stat-value">${this._stats.activeSessions}</div>
|
|
1064
|
-
<div class="stat-label">${r("sessions.activeSessions")}</div>
|
|
1065
|
-
</div>
|
|
1066
|
-
<div class="stat-card">
|
|
1067
|
-
<div class="stat-value">${this._stats.pinnedSessions}</div>
|
|
1068
|
-
<div class="stat-label">${r("sessions.pinnedSessions")}</div>
|
|
1069
|
-
</div>
|
|
1070
|
-
<div class="stat-card">
|
|
1071
|
-
<div class="stat-value">${this._stats.archivedSessions}</div>
|
|
1072
|
-
<div class="stat-label">${r("sessions.archivedSessions")}</div>
|
|
1073
|
-
</div>
|
|
1074
|
-
</div>
|
|
1075
|
-
`:""}};A([u({attribute:!1})],b.prototype,"config",2);A([c()],b.prototype,"_sessions",2);A([c()],b.prototype,"_loading",2);A([c()],b.prototype,"_hasMore",2);A([c()],b.prototype,"_stats",2);A([c()],b.prototype,"_searchQuery",2);A([c()],b.prototype,"_statusFilter",2);A([c()],b.prototype,"_offset",2);A([c()],b.prototype,"_error",2);A([c()],b.prototype,"_detailOpen",2);A([c()],b.prototype,"_detailSession",2);A([c()],b.prototype,"_detailLoading",2);A([c()],b.prototype,"_confirmOpen",2);A([c()],b.prototype,"_confirmTitle",2);A([c()],b.prototype,"_confirmMessage",2);A([c()],b.prototype,"_confirmKey",2);A([c()],b.prototype,"_confirmAction",2);b=A([k("session-manager")],b);class ai{constructor(t,s){this.baseUrl=t.replace(/\/$/,""),this.token=s}async request(t,s,i){const n={"Content-Type":"application/json"};this.token&&(n.Authorization=`Bearer ${this.token}`);const a=await fetch(`${this.baseUrl}${s}`,{method:t,headers:n,body:i?JSON.stringify(i):void 0});if(!a.ok){const l=await a.json().catch(()=>({error:"Request failed"}));throw new Error(l.error||`HTTP ${a.status}`)}return a.json()}async listJobs(){return(await this.request("GET","/api/cron")).jobs||[]}async getJob(t){try{return(await this.request("GET",`/api/cron/${t}`)).job||null}catch(s){if(s instanceof Error&&s.message.includes("404"))return null;throw s}}async addJob(t,s,i){return await this.request("POST","/api/cron",{schedule:t,message:s,...i})}async updateJob(t,s){return(await this.request("PATCH",`/api/cron/${t}`,s)).updated}async removeJob(t){return(await this.request("DELETE",`/api/cron/${t}`)).removed}async toggleJob(t,s){return(await this.request("POST",`/api/cron/${t}/toggle`,{enabled:s})).toggled}async runJob(t){await this.request("POST",`/api/cron/${t}/run`)}async getHistory(t,s=10){return(await this.request("GET",`/api/cron/${t}/history?limit=${s}`)).history||[]}async getMetrics(){return await this.request("GET","/api/cron/metrics")}async getChannels(){return(await this.request("GET","/api/channels/status")).payload?.channels||[]}async getModels(){return(await this.request("GET","/api/models")).payload?.models||[]}async getConfig(){return{model:((await this.request("GET","/api/config")).config||{}).agents?.defaults?.model||""}}async getSessionChatIds(t){const s=t?`?channel=${encodeURIComponent(t)}`:"";return(await this.request("GET",`/api/sessions/chat-ids${s}`)).payload?.chatIds||[]}disconnect(){}}var ri=Object.defineProperty,li=Object.getOwnPropertyDescriptor,v=(e,t,s,i)=>{for(var n=i>1?void 0:i?li(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&ri(t,s,n),n};let m=class extends y{constructor(){super(...arguments),this._jobs=[],this._metrics=null,this._channels=[],this._availableModels=[],this._defaultModel="",this._sessionChatIds=[],this._loading=!1,this._error=null,this._formOpen=!1,this._formMode="add",this._formJobId=null,this._formName="",this._formSchedule="*/5 * * * *",this._formChannel="telegram",this._formChatId="",this._formMessage="",this._formSessionTarget="main",this._formModel="",this._formSubmitting=!1,this._detailOpen=!1,this._detailJob=null,this._detailHistory=[],this._detailLoading=!1,this._confirmOpen=!1,this._confirmTitle="",this._confirmMessage="",this._confirmJobId=null,this._confirmAction=null,this._initialized=!1}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this._tryInitialize()}willUpdate(e){super.willUpdate(e),e.has("config")&&this._tryInitialize()}_tryInitialize(){if(this._initialized)return;const e=window.location.origin;this._api=new ai(e,this.config?.token),this._initialized=!0,this._loadJobs(),this._loadMetrics(),this._loadChannels(),this._loadModels(),this._loadSessionChatIds()}disconnectedCallback(){super.disconnectedCallback(),this._api?.disconnect()}async _loadJobs(){if(!this._loading){this._loading=!0,this._error=null;try{this._jobs=await this._api.listJobs()}catch(e){this._error=e instanceof Error&&e.message||r("cron.failedToLoadJobs"),console.error("[CronManager] Load error:",e)}finally{this._loading=!1}}}async _loadMetrics(){try{this._metrics=await this._api.getMetrics()}catch(e){console.error("[CronManager] Metrics error:",e)}}async _loadChannels(){try{this._channels=await this._api.getChannels()}catch(e){console.error("[CronManager] Channels error:",e)}}async _loadModels(){try{this._availableModels=await this._api.getModels();const e=await this._api.getConfig();this._defaultModel=e.model||"",this._formModel=this._defaultModel,console.log("[CronManager] Loaded models:",this._availableModels.length,"default:",this._defaultModel)}catch(e){console.error("[CronManager] Models error:",e)}}async _loadSessionChatIds(){try{const e=await this._api.getSessionChatIds(this._formChannel);this._sessionChatIds=e,console.log("[CronManager] Loaded session chatIds for channel",this._formChannel,":",e.length,e)}catch(e){console.error("[CronManager] Session chatIds error:",e),this._sessionChatIds=[]}}_openForm(e){if(this._formOpen=!0,this._formMode=e?"edit":"add",this._formJobId=e?.id||null,e||this._loadSessionChatIds(),e)if(this._formName=e.name||"",this._formSchedule=e.schedule,this._formMessage=e.message,this._formSessionTarget=e.sessionTarget||"main",this._formModel=e.model||"",e.delivery)this._formChannel=e.delivery.channel||"telegram",this._formChatId=e.delivery.to||"";else{const t=e.message.split(":"),s=["telegram","whatsapp","cli","gateway"];t.length>=3&&s.includes(t[0])?(this._formChannel=t[0],this._formChatId=t[1],this._formMessage=t.slice(2).join(":")):(this._formChannel="telegram",this._formChatId="")}else this._formName="",this._formSchedule="*/5 * * * *",this._formChannel="telegram",this._formChatId="",this._formMessage="",this._formSessionTarget="main",this._formModel=this._defaultModel||(this._availableModels.length>0?this._availableModels[0].id:"")}_closeForm(){this._formOpen=!1,this._formMode="add",this._formJobId=null,this._formName="",this._formSchedule="*/5 * * * *",this._formChannel="telegram",this._formChatId="",this._formMessage="",this._formSessionTarget="main",this._formModel=""}async _submitForm(){if(!this._formSchedule||!this._formMessage){this._error=r("cron.scheduleRequired");return}if(!this._formChatId){this._error=r("cron.chatIdRequired");return}this._formSubmitting=!0,this._error=null;try{const e=this._formMessage,t={mode:"direct",channel:this._formChannel,to:this._formChatId},s=this._formSessionTarget==="isolated"?{kind:"agentTurn",message:e,model:this._formModel}:{kind:"systemEvent",text:e},i={name:this._formName||void 0,schedule:this._formSchedule,message:e,sessionTarget:this._formSessionTarget,model:this._formSessionTarget==="isolated"?this._formModel:void 0,delivery:t};this._formMode==="edit"&&this._formJobId?await this._api.updateJob(this._formJobId,i):await this._api.addJob(this._formSchedule,e,i),this._closeForm(),await this._loadJobs(),await this._loadMetrics()}catch(e){this._error=e instanceof Error?e.message||r("cron.failedToJob",{mode:this._formMode}):r("cron.failedToJob",{mode:this._formMode})}finally{this._formSubmitting=!1}}async _openDetail(e){this._detailOpen=!0,this._detailJob=e,this._detailLoading=!0;try{const t=await this._api.getJob(e.id);t&&(this._detailJob=t,this._detailHistory=await this._api.getHistory(e.id,20))}catch(t){console.error("[CronManager] Load detail error:",t)}finally{this._detailLoading=!1}}_closeDetail(){this._detailOpen=!1,this._detailJob=null,this._detailHistory=[]}async _toggleJob(e,t){try{await this._api.toggleJob(e.id,t),await this._loadJobs(),await this._loadMetrics()}catch(s){this._error=s instanceof Error&&s.message||r("cron.failedToToggleJob")}}_showRunConfirm(e){this._confirmOpen=!0,this._confirmTitle=r("cron.runNow"),this._confirmMessage=r("cron.confirmRun"),this._confirmJobId=e.id,this._confirmAction="run"}_showDeleteConfirm(e){this._confirmOpen=!0,this._confirmTitle=r("cron.delete"),this._confirmMessage=r("cron.confirmDelete"),this._confirmJobId=e.id,this._confirmAction="delete"}_closeConfirm(){this._confirmOpen=!1,this._confirmTitle="",this._confirmMessage="",this._confirmJobId=null,this._confirmAction=null}_handleConfirm(e){e.detail.confirmed?this._executeConfirmAction():this._closeConfirm()}async _executeConfirmAction(){if(!this._confirmJobId||!this._confirmAction)return;const e=this._confirmJobId,t=this._confirmAction;this._closeConfirm();try{t==="run"?(await this._api.runJob(e),await this._loadJobs(),await this._loadMetrics()):t==="delete"&&(await this._api.removeJob(e),await this._loadJobs(),await this._loadMetrics())}catch(s){this._error=s instanceof Error&&s.message||r("cron.actionFailed")}}render(){return o`
|
|
1076
|
-
<div class="cron-manager">
|
|
1077
|
-
${this._error?o`<div class="error-banner">${this._error}</div>`:""}
|
|
1078
|
-
|
|
1079
|
-
<!-- Header -->
|
|
1080
|
-
<div class="cron-manager__header">
|
|
1081
|
-
<h1 class="page-title">${d("clock")} ${r("cron.title")}</h1>
|
|
1082
|
-
<div class="cron-manager__actions">
|
|
1083
|
-
<button class="btn btn-secondary" @click=${this._loadJobs} ?disabled=${this._loading}>
|
|
1084
|
-
${d("refresh")} ${r("logs.refresh")}
|
|
1085
|
-
</button>
|
|
1086
|
-
<button class="btn btn-primary" @click=${()=>this._openForm()}>
|
|
1087
|
-
${d("plus")} ${r("cron.addJob")}
|
|
1088
|
-
</button>
|
|
1089
|
-
</div>
|
|
1090
|
-
</div>
|
|
1091
|
-
|
|
1092
|
-
<!-- Stats -->
|
|
1093
|
-
${this._metrics?o`
|
|
1094
|
-
<div class="cron-manager__stats">
|
|
1095
|
-
<div class="stat-card" style="text-align: center;">
|
|
1096
|
-
<div class="stat-value">${this._metrics.totalJobs}</div>
|
|
1097
|
-
<div class="stat-label">${r("sessions.totalSessions")}</div>
|
|
1098
|
-
</div>
|
|
1099
|
-
<div class="stat-card" style="text-align: center;">
|
|
1100
|
-
<div class="stat-value">${this._metrics.enabledJobs}</div>
|
|
1101
|
-
<div class="stat-label">${r("cron.enabled")}</div>
|
|
1102
|
-
</div>
|
|
1103
|
-
<div class="stat-card" style="text-align: center;">
|
|
1104
|
-
<div class="stat-value">${this._metrics.runningJobs}</div>
|
|
1105
|
-
<div class="stat-label">${r("cron.running")}</div>
|
|
1106
|
-
</div>
|
|
1107
|
-
<div class="stat-card" style="text-align: center;">
|
|
1108
|
-
<div class="stat-value" style="font-size: 0.875rem;">
|
|
1109
|
-
${this._metrics.nextScheduledJob?this._formatNextRun(this._metrics.nextScheduledJob.runAt):"N/A"}
|
|
1110
|
-
</div>
|
|
1111
|
-
<div class="stat-label">${r("cron.nextRun")}</div>
|
|
1112
|
-
</div>
|
|
1113
|
-
</div>
|
|
1114
|
-
`:_}
|
|
1115
|
-
|
|
1116
|
-
<!-- Job List -->
|
|
1117
|
-
<div class="session-list">
|
|
1118
|
-
${this._loading&&this._jobs.length===0?o`
|
|
1119
|
-
<div class="session-list__loading-overlay">
|
|
1120
|
-
<div class="spinner"></div>
|
|
1121
|
-
</div>
|
|
1122
|
-
`:this._jobs.length===0?o`
|
|
1123
|
-
<div class="session-list session-list--empty">
|
|
1124
|
-
<div class="empty-state">
|
|
1125
|
-
<div class="empty-state__icon">${d("clock")}</div>
|
|
1126
|
-
<div class="empty-state__title">No cron jobs yet</div>
|
|
1127
|
-
<button class="btn btn-primary" @click=${this._openForm}>Create your first job</button>
|
|
1128
|
-
</div>
|
|
1129
|
-
</div>
|
|
1130
|
-
`:o`
|
|
1131
|
-
<div class="session-list__toolbar">
|
|
1132
|
-
<div class="session-list__count">${this._jobs.length} job${this._jobs.length!==1?"s":""}</div>
|
|
1133
|
-
</div>
|
|
1134
|
-
<div class="session-list__content">
|
|
1135
|
-
<table class="data-table">
|
|
1136
|
-
<thead>
|
|
1137
|
-
<tr>
|
|
1138
|
-
<th>${r("cron.name")}</th>
|
|
1139
|
-
<th>${r("cron.scheduleLabel")}</th>
|
|
1140
|
-
<th>${r("cron.nextRun")}</th>
|
|
1141
|
-
<th>${r("cron.status")}</th>
|
|
1142
|
-
<th>${r("cron.actions")}</th>
|
|
1143
|
-
</tr>
|
|
1144
|
-
</thead>
|
|
1145
|
-
<tbody>
|
|
1146
|
-
${this._jobs.map(e=>o`
|
|
1147
|
-
<tr>
|
|
1148
|
-
<td style="vertical-align: middle; text-align: center;">
|
|
1149
|
-
<button class="btn btn-link" @click=${()=>this._openDetail(e)}>
|
|
1150
|
-
${e.name||e.id}
|
|
1151
|
-
</button>
|
|
1152
|
-
</td>
|
|
1153
|
-
<td style="vertical-align: middle; text-align: center;"><code>${e.schedule}</code></td>
|
|
1154
|
-
<td style="vertical-align: middle; text-align: center;">${e.next_run?this._formatNextRun(e.next_run):"-"}</td>
|
|
1155
|
-
<td style="vertical-align: middle; text-align: center;">
|
|
1156
|
-
<label class="toggle">
|
|
1157
|
-
<input
|
|
1158
|
-
type="checkbox"
|
|
1159
|
-
?checked=${e.enabled}
|
|
1160
|
-
@change=${t=>this._toggleJob(e,t.target.checked)}
|
|
1161
|
-
/>
|
|
1162
|
-
<span class="toggle__slider"></span>
|
|
1163
|
-
</label>
|
|
1164
|
-
</td>
|
|
1165
|
-
<td style="vertical-align: middle; text-align: center;">
|
|
1166
|
-
<div class="action-buttons">
|
|
1167
|
-
<button class="btn btn-icon btn-secondary" title="Edit" @click=${()=>this._openForm(e)}>
|
|
1168
|
-
${d("edit")}
|
|
1169
|
-
</button>
|
|
1170
|
-
<button class="btn btn-icon btn-secondary" title="${r("cron.runNow")}" @click=${()=>this._showRunConfirm(e)}>
|
|
1171
|
-
${d("play")}
|
|
1172
|
-
</button>
|
|
1173
|
-
<button class="btn btn-icon btn-danger" title="${r("cron.delete")}" @click=${()=>this._showDeleteConfirm(e)}>
|
|
1174
|
-
${d("trash")}
|
|
1175
|
-
</button>
|
|
1176
|
-
</div>
|
|
1177
|
-
</td>
|
|
1178
|
-
</tr>
|
|
1179
|
-
`)}
|
|
1180
|
-
</tbody>
|
|
1181
|
-
</table>
|
|
1182
|
-
</div>
|
|
1183
|
-
`}
|
|
1184
|
-
</div>
|
|
1185
|
-
</div>
|
|
1186
|
-
|
|
1187
|
-
<!-- Add/Edit Job Form Modal -->
|
|
1188
|
-
${this._formOpen?o`
|
|
1189
|
-
<div class="modal-backdrop" @click=${this._closeForm}>
|
|
1190
|
-
<div class="modal modal--form" @click=${e=>e.stopPropagation()}>
|
|
1191
|
-
<div class="modal__header">
|
|
1192
|
-
<h2 class="modal__title">${this._formMode==="edit"?r("cron.editJob"):r("cron.addJob")}</h2>
|
|
1193
|
-
<button class="btn-icon" @click=${this._closeForm}>${d("x")}</button>
|
|
1194
|
-
</div>
|
|
1195
|
-
<div class="modal__content">
|
|
1196
|
-
<div class="form-field">
|
|
1197
|
-
<label class="form-field__label">${r("cron.name")}</label>
|
|
1198
|
-
<input
|
|
1199
|
-
type="text"
|
|
1200
|
-
class="form-field__input"
|
|
1201
|
-
.value=${this._formName??""}
|
|
1202
|
-
@input=${e=>this._formName=e.target.value}
|
|
1203
|
-
placeholder="${r("cron.namePlaceholder")??"My scheduled task"}"
|
|
1204
|
-
/>
|
|
1205
|
-
</div>
|
|
1206
|
-
<div class="form-field">
|
|
1207
|
-
<label class="form-field__label">${r("cron.schedule")}</label>
|
|
1208
|
-
<div style="display: flex; gap: 0.5rem; align-items: center;">
|
|
1209
|
-
<input
|
|
1210
|
-
type="text"
|
|
1211
|
-
class="form-field__input"
|
|
1212
|
-
style="flex: 2; min-width: 0;"
|
|
1213
|
-
.value=${this._formSchedule??"*/5 * * * *"}
|
|
1214
|
-
@input=${e=>this._formSchedule=e.target.value}
|
|
1215
|
-
placeholder="*/5 * * * *"
|
|
1216
|
-
/>
|
|
1217
|
-
<select
|
|
1218
|
-
class="form-field__select"
|
|
1219
|
-
style="flex: 1; min-width: 0;"
|
|
1220
|
-
.value=${this._formSchedule??"*/5 * * * *"}
|
|
1221
|
-
@change=${e=>{const t=e.target.value;t&&(this._formSchedule=t)}}
|
|
1222
|
-
>
|
|
1223
|
-
<option value="">${r("cron.schedulePresets.custom")}</option>
|
|
1224
|
-
<option value="*/1 * * * *">${r("cron.schedulePresets.everyMinute")}</option>
|
|
1225
|
-
<option value="*/5 * * * *">${r("cron.schedulePresets.every5Minutes")}</option>
|
|
1226
|
-
<option value="*/10 * * * *">${r("cron.schedulePresets.every10Minutes")}</option>
|
|
1227
|
-
<option value="*/15 * * * *">${r("cron.schedulePresets.every15Minutes")}</option>
|
|
1228
|
-
<option value="*/30 * * * *">${r("cron.schedulePresets.every30Minutes")}</option>
|
|
1229
|
-
<option value="0 * * * *">${r("cron.schedulePresets.everyHour")}</option>
|
|
1230
|
-
<option value="0 */2 * * *">${r("cron.schedulePresets.every2Hours")}</option>
|
|
1231
|
-
<option value="0 */4 * * *">${r("cron.schedulePresets.every4Hours")}</option>
|
|
1232
|
-
<option value="0 */6 * * *">${r("cron.schedulePresets.every6Hours")}</option>
|
|
1233
|
-
<option value="0 */12 * * *">${r("cron.schedulePresets.every12Hours")}</option>
|
|
1234
|
-
<option value="0 0 * * *">${r("cron.schedulePresets.everyDayMidnight")}</option>
|
|
1235
|
-
<option value="0 9 * * *">${r("cron.schedulePresets.everyDay9AM")}</option>
|
|
1236
|
-
<option value="0 21 * * *">${r("cron.schedulePresets.everyDay9PM")}</option>
|
|
1237
|
-
</select>
|
|
1238
|
-
</div>
|
|
1239
|
-
<p class="form-field__hint">
|
|
1240
|
-
${r("cron.scheduleHintPreset")}
|
|
1241
|
-
</p>
|
|
1242
|
-
</div>
|
|
1243
|
-
<div class="form-field">
|
|
1244
|
-
<label class="form-field__label">${r("cron.mode")}</label>
|
|
1245
|
-
<select
|
|
1246
|
-
class="form-field__select"
|
|
1247
|
-
.value=${this._formSessionTarget??"main"}
|
|
1248
|
-
@change=${e=>this._formSessionTarget=e.target.value}
|
|
1249
|
-
>
|
|
1250
|
-
<option value="main">${r("cron.modeDirectOption")||"Direct (send message directly)"}</option>
|
|
1251
|
-
<option value="isolated">${r("cron.modeAgentOption")||"AI Agent (process with AI then send)"}</option>
|
|
1252
|
-
</select>
|
|
1253
|
-
<p class="form-field__hint">
|
|
1254
|
-
${this._formSessionTarget==="main"?r("cron.modeDirect"):r("cron.modeAgent")}
|
|
1255
|
-
</p>
|
|
1256
|
-
</div>
|
|
1257
|
-
${this._formSessionTarget==="isolated"?o`
|
|
1258
|
-
<div class="form-field">
|
|
1259
|
-
<label class="form-field__label">${r("cron.model")}</label>
|
|
1260
|
-
<select
|
|
1261
|
-
class="form-field__select"
|
|
1262
|
-
.value=${this._formModel??""}
|
|
1263
|
-
@change=${e=>this._formModel=e.target.value}
|
|
1264
|
-
>
|
|
1265
|
-
${this._availableModels.length>0?this._availableModels.map(e=>o`
|
|
1266
|
-
<option value=${e.id}>${e.name} (${e.provider})</option>
|
|
1267
|
-
`):o`
|
|
1268
|
-
<option value="">${r("cron.noConfiguredModels")}</option>
|
|
1269
|
-
`}
|
|
1270
|
-
</select>
|
|
1271
|
-
</div>
|
|
1272
|
-
`:_}
|
|
1273
|
-
<div class="form-field">
|
|
1274
|
-
<label class="form-field__label">Channel</label>
|
|
1275
|
-
<select
|
|
1276
|
-
class="form-field__select"
|
|
1277
|
-
.value=${this._formChannel??"telegram"}
|
|
1278
|
-
@change=${e=>{this._formChannel=e.target.value,this._loadSessionChatIds(),this._formChatId=""}}
|
|
1279
|
-
>
|
|
1280
|
-
${this._channels.map(e=>o`
|
|
1281
|
-
<option value=${e.name} ?disabled=${!e.enabled}>
|
|
1282
|
-
${e.name} ${e.enabled?"":"(disabled)"}
|
|
1283
|
-
</option>
|
|
1284
|
-
`)}
|
|
1285
|
-
</select>
|
|
1286
|
-
</div>
|
|
1287
|
-
<div class="form-field">
|
|
1288
|
-
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem;">
|
|
1289
|
-
<label class="form-field__label" style="margin: 0;">Chat ID *</label>
|
|
1290
|
-
<button
|
|
1291
|
-
type="button"
|
|
1292
|
-
class="btn btn-secondary btn-sm"
|
|
1293
|
-
@click=${()=>this._loadSessionChatIds()}
|
|
1294
|
-
title="Refresh chat list"
|
|
1295
|
-
style="padding: 0.25rem 0.5rem; font-size: 0.75rem;"
|
|
1296
|
-
>
|
|
1297
|
-
${d("refresh")} Refresh
|
|
1298
|
-
</button>
|
|
1299
|
-
</div>
|
|
1300
|
-
<div style="display: flex; gap: 0.5rem; align-items: center;">
|
|
1301
|
-
<input
|
|
1302
|
-
type="text"
|
|
1303
|
-
class="form-field__input"
|
|
1304
|
-
style="flex: 2; min-width: 0;"
|
|
1305
|
-
.value=${this._formChatId??""}
|
|
1306
|
-
@input=${e=>this._formChatId=e.target.value}
|
|
1307
|
-
placeholder="e.g., 123456789"
|
|
1308
|
-
/>
|
|
1309
|
-
<select
|
|
1310
|
-
class="form-field__select"
|
|
1311
|
-
style="flex: 1; min-width: 0;"
|
|
1312
|
-
.value=${this._formChatId??""}
|
|
1313
|
-
@change=${e=>{const t=e.target.value;t&&(this._formChatId=t)}}
|
|
1314
|
-
>
|
|
1315
|
-
<option value="">-- Select --</option>
|
|
1316
|
-
${this._sessionChatIds.length>0?this._sessionChatIds.map(e=>o`
|
|
1317
|
-
<option value=${e.chatId}>
|
|
1318
|
-
${e.channel}: ${e.chatId} (${this._formatLastActive(e.lastActive)})
|
|
1319
|
-
</option>
|
|
1320
|
-
`):o`
|
|
1321
|
-
<option value="" disabled>No recent chats</option>
|
|
1322
|
-
`}
|
|
1323
|
-
</select>
|
|
1324
|
-
</div>
|
|
1325
|
-
<p class="form-field__hint">
|
|
1326
|
-
${this._sessionChatIds.length>0?r("cron.enterManuallyOrSelect"):r("cron.noRecentChats")}
|
|
1327
|
-
</p>
|
|
1328
|
-
</div>
|
|
1329
|
-
<div class="form-field">
|
|
1330
|
-
<label class="form-field__label">${r("cron.message")}</label>
|
|
1331
|
-
<textarea
|
|
1332
|
-
class="form-field__textarea"
|
|
1333
|
-
.value=${this._formMessage??""}
|
|
1334
|
-
@input=${e=>this._formMessage=e.target.value}
|
|
1335
|
-
placeholder="${r("cron.messagePlaceholder")??"What should the assistant do?"}"
|
|
1336
|
-
rows="4"
|
|
1337
|
-
></textarea>
|
|
1338
|
-
</div>
|
|
1339
|
-
</div>
|
|
1340
|
-
<div class="modal__actions">
|
|
1341
|
-
<button class="btn btn-secondary" @click=${this._closeForm}>${r("common.cancel")}</button>
|
|
1342
|
-
<button
|
|
1343
|
-
class="btn btn-primary"
|
|
1344
|
-
@click=${this._submitForm}
|
|
1345
|
-
?disabled=${this._formSubmitting||!this._formSchedule||!this._formChatId||!this._formMessage}
|
|
1346
|
-
>
|
|
1347
|
-
${this._formSubmitting?r("common.loading"):this._formMode==="edit"?r("cron.save"):r("cron.create")}
|
|
1348
|
-
</button>
|
|
1349
|
-
</div>
|
|
1350
|
-
</div>
|
|
1351
|
-
</div>
|
|
1352
|
-
`:_}
|
|
1353
|
-
|
|
1354
|
-
<!-- Detail Drawer -->
|
|
1355
|
-
${this._detailOpen?o`
|
|
1356
|
-
<div class="drawer-backdrop" @click=${this._closeDetail}>
|
|
1357
|
-
<div class="drawer drawer--open" @click=${e=>e.stopPropagation()}>
|
|
1358
|
-
<div class="drawer-header">
|
|
1359
|
-
<div class="drawer-header__info">
|
|
1360
|
-
<div class="drawer-header__title">${this._detailJob?.name||this._detailJob?.id}</div>
|
|
1361
|
-
</div>
|
|
1362
|
-
<button class="btn-icon" @click=${this._closeDetail}>${d("x")}</button>
|
|
1363
|
-
</div>
|
|
1364
|
-
<div class="drawer-content ${this._detailLoading?"drawer-content--loading":""}">
|
|
1365
|
-
${this._detailLoading?o`
|
|
1366
|
-
<div class="spinner"></div>
|
|
1367
|
-
`:o`
|
|
1368
|
-
<div class="session-detail">
|
|
1369
|
-
<div class="session-detail__row">
|
|
1370
|
-
<span class="session-detail__label">${r("cron.scheduleLabel")}</span>
|
|
1371
|
-
<code>${this._detailJob?.schedule}</code>
|
|
1372
|
-
</div>
|
|
1373
|
-
<div class="session-detail__row">
|
|
1374
|
-
<span class="session-detail__label">${r("cron.messageLabel")}</span>
|
|
1375
|
-
<span>${this._detailJob?.message}</span>
|
|
1376
|
-
</div>
|
|
1377
|
-
<div class="session-detail__row">
|
|
1378
|
-
<span class="session-detail__label">${r("cron.status")}</span>
|
|
1379
|
-
<span>${this._detailJob?.enabled?r("cron.enabled"):r("cron.disabled")}</span>
|
|
1380
|
-
</div>
|
|
1381
|
-
<div class="session-detail__row">
|
|
1382
|
-
<span class="session-detail__label">${r("cron.nextRun")}</span>
|
|
1383
|
-
<span>${this._detailJob?.next_run?this._formatNextRun(this._detailJob.next_run):"N/A"}</span>
|
|
1384
|
-
</div>
|
|
1385
|
-
</div>
|
|
1386
|
-
`}
|
|
1387
|
-
</div>
|
|
1388
|
-
</div>
|
|
1389
|
-
</div>
|
|
1390
|
-
`:_}
|
|
1391
|
-
|
|
1392
|
-
<!-- Confirm Dialog -->
|
|
1393
|
-
<confirm-dialog
|
|
1394
|
-
.open=${this._confirmOpen}
|
|
1395
|
-
.title=${this._confirmTitle}
|
|
1396
|
-
.message=${this._confirmMessage}
|
|
1397
|
-
.confirmText=${this._confirmAction==="delete"?r("cron.delete"):r("cron.runNow")}
|
|
1398
|
-
.cancelText=${r("common.cancel")}
|
|
1399
|
-
.type=${this._confirmAction==="delete"?"danger":"warning"}
|
|
1400
|
-
@confirm=${this._handleConfirm}
|
|
1401
|
-
></confirm-dialog>
|
|
1402
|
-
`}_formatNextRun(e){const t=typeof e=="string"?new Date(e):e,s=new Date,i=t.getTime()-s.getTime();if(i<0)return r("cron.timeLabels.overdue");if(i<6e4)return r("cron.timeLabels.lessThanMinute");if(i<36e5){const n=Math.floor(i/6e4);return r("cron.timeLabels.minutes",{count:n})}if(i<864e5){const n=Math.floor(i/36e5);return r("cron.timeLabels.hours",{count:n})}return t.toLocaleString()}_formatLastActive(e){const t=new Date(e),i=new Date().getTime()-t.getTime();if(i<0||i<6e4)return r("cron.lastActiveLabels.justNow");if(i<36e5){const n=Math.floor(i/6e4);return r("cron.lastActiveLabels.minutesAgo",{count:n})}if(i<864e5){const n=Math.floor(i/36e5);return r("cron.lastActiveLabels.hoursAgo",{count:n})}if(i<6048e5){const n=Math.floor(i/864e5);return r("cron.lastActiveLabels.daysAgo",{count:n})}return t.toLocaleDateString()}_formatTime(e){return new Date(e).toLocaleString()}};v([u({attribute:!1})],m.prototype,"config",2);v([c()],m.prototype,"_jobs",2);v([c()],m.prototype,"_metrics",2);v([c()],m.prototype,"_channels",2);v([c()],m.prototype,"_availableModels",2);v([c()],m.prototype,"_defaultModel",2);v([c()],m.prototype,"_sessionChatIds",2);v([c()],m.prototype,"_loading",2);v([c()],m.prototype,"_error",2);v([c()],m.prototype,"_formOpen",2);v([c()],m.prototype,"_formMode",2);v([c()],m.prototype,"_formJobId",2);v([c()],m.prototype,"_formName",2);v([c()],m.prototype,"_formSchedule",2);v([c()],m.prototype,"_formChannel",2);v([c()],m.prototype,"_formChatId",2);v([c()],m.prototype,"_formMessage",2);v([c()],m.prototype,"_formSessionTarget",2);v([c()],m.prototype,"_formModel",2);v([c()],m.prototype,"_formSubmitting",2);v([c()],m.prototype,"_detailOpen",2);v([c()],m.prototype,"_detailJob",2);v([c()],m.prototype,"_detailHistory",2);v([c()],m.prototype,"_detailLoading",2);v([c()],m.prototype,"_confirmOpen",2);v([c()],m.prototype,"_confirmTitle",2);v([c()],m.prototype,"_confirmMessage",2);v([c()],m.prototype,"_confirmJobId",2);v([c()],m.prototype,"_confirmAction",2);m=v([k("cron-manager")],m);const ci=["trace","debug","info","warn","error","fatal"],be={trace:"#9ca3af",debug:"#6b7280",info:"#3b82f6",warn:"#f59e0b",error:"#ef4444",fatal:"#dc2626"};class hi{constructor(t,s){this.baseUrl=t.replace(/\/$/,""),this.token=s}async request(t,s,i){const n={"Content-Type":"application/json"};this.token&&(n.Authorization=`Bearer ${this.token}`);const a=await fetch(`${this.baseUrl}${s}`,{method:t,headers:n,body:i?JSON.stringify(i):void 0});if(!a.ok){const l=await a.json().catch(()=>({error:"Request failed"}));throw new Error(l.error||`HTTP ${a.status}`)}return a.json()}async queryLogs(t){const s=new URLSearchParams;t?.level?.length&&s.set("level",t.level.join(",")),t?.from&&s.set("from",t.from),t?.to&&s.set("to",t.to),t?.q&&s.set("q",t.q),t?.module&&s.set("module",t.module),t?.limit&&s.set("limit",String(t.limit)),t?.offset&&s.set("offset",String(t.offset));const i=s.toString(),n=`/api/logs${i?`?${i}`:""}`;return await this.request("GET",n)}async getLogFiles(){return(await this.request("GET","/api/logs/files")).files||[]}async getLogStats(){return await this.request("GET","/api/logs/stats")}async getLogLevels(){return(await this.request("GET","/api/logs/levels")).levels||[]}async getLogModules(){return(await this.request("GET","/api/logs/modules")).modules||[]}async getLogDir(){return(await this.request("GET","/api/logs/dir")).dir}}var di=Object.defineProperty,pi=Object.getOwnPropertyDescriptor,C=(e,t,s,i)=>{for(var n=i>1?void 0:i?pi(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&di(t,s,n),n};let $=class extends y{constructor(){super(...arguments),this._logs=[],this._loading=!1,this._hasMore=!1,this._files=[],this._modules=[],this._showFilesPanel=!1,this._selectedLevels=new Set,this._searchQuery="",this._selectedModule="",this._dateFrom="",this._dateTo="",this._offset=0,this._error=null,this._selectedLog=null,this._autoRefresh=!1,this._limit=50,this._initialized=!1,this._debouncedSearch=this._debounce(()=>{this._loadLogs(!0)},300)}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this._tryInitialize()}willUpdate(e){super.willUpdate(e),e.has("config")&&this._tryInitialize()}disconnectedCallback(){super.disconnectedCallback(),this._stopAutoRefresh()}firstUpdated(){this._tryInitialize()}_tryInitialize(){if(this._initialized)return;const e=window.location.origin;this._api=new hi(e,this.config?.token),this._initialized=!0,this._loadLogs(),this._loadFiles(),this._loadModules()}async _loadLogs(e=!1){if(!this._loading){this._loading=!0,this._error=null,e&&(this._offset=0,this._logs=[]);try{const t={level:this._selectedLevels.size>0?Array.from(this._selectedLevels):void 0,from:this._dateFrom||void 0,to:this._dateTo||void 0,q:this._searchQuery||void 0,module:this._selectedModule||void 0,limit:this._limit,offset:this._offset},s=await this._api.queryLogs(t);e?this._logs=s.logs:this._logs=[...this._logs,...s.logs],console.log("[LogManager] Total logs in state:",this._logs.length),this._hasMore=s.logs.length===this._limit,this._offset=this._offset+s.logs.length}catch(t){this._error=t instanceof Error?t.message:"Failed to load logs",console.error("[LogManager] Load error:",t)}finally{this._loading=!1}}}async _loadFiles(){try{this._files=await this._api.getLogFiles()}catch(e){console.error("[LogManager] Files error:",e)}}async _loadModules(){try{this._modules=await this._api.getLogModules()}catch(e){console.error("[LogManager] Modules error:",e)}}_toggleLevel(e){this._selectedLevels.has(e)?this._selectedLevels.delete(e):this._selectedLevels.add(e),this._selectedLevels=new Set(this._selectedLevels),this._loadLogs(!0)}_handleSearch(e){const t=e.target;this._searchQuery=t.value,this._debouncedSearch()}_debounce(e,t){let s;return()=>{clearTimeout(s),s=setTimeout(e,t)}}_handleModuleChange(e){const t=e.target;this._selectedModule=t.value,this._loadLogs(!0)}_handleDateFromChange(e){const t=e.target;this._dateFrom=t.value,this._loadLogs(!0)}_handleDateToChange(e){const t=e.target;this._dateTo=t.value,this._loadLogs(!0)}_clearFilters(){this._selectedLevels.clear(),this._selectedLevels=new Set,this._searchQuery="",this._selectedModule="",this._dateFrom="",this._dateTo="",this._loadLogs(!0)}_selectLog(e){this._selectedLog=e}_closeDetail(){this._selectedLog=null}_toggleAutoRefresh(){this._autoRefresh=!this._autoRefresh,this._autoRefresh?this._startAutoRefresh():this._stopAutoRefresh()}_startAutoRefresh(){this._refreshInterval=window.setInterval(()=>{this._loadLogs(!0)},5e3)}_stopAutoRefresh(){this._refreshInterval&&(clearInterval(this._refreshInterval),this._refreshInterval=void 0)}_handleLoadMore(){this._loadLogs()}_formatTimestamp(e){try{return new Date(e).toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch{return e}}_formatFileSize(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}render(){return o`
|
|
1403
|
-
<div class="log-manager">
|
|
1404
|
-
${this._renderHeader()}
|
|
1405
|
-
<div class="log-manager__main">
|
|
1406
|
-
${this._renderFilters()}
|
|
1407
|
-
${this._renderLogTable()}
|
|
1408
|
-
${this._renderFilesPanel()}
|
|
1409
|
-
</div>
|
|
1410
|
-
${this._error?o`<div class="error-banner">${this._error}</div>`:""}
|
|
1411
|
-
</div>
|
|
1412
|
-
|
|
1413
|
-
${this._selectedLog?this._renderDetailDrawer():""}
|
|
1414
|
-
`}_renderHeader(){return o`
|
|
1415
|
-
<div class="log-manager__header">
|
|
1416
|
-
<div class="log-manager__title">
|
|
1417
|
-
<span class="title-icon">${d("fileText")}</span>
|
|
1418
|
-
<div class="title-text">
|
|
1419
|
-
<h1>${r("logs.title")}</h1>
|
|
1420
|
-
<span class="title-subtitle">System logs and diagnostics</span>
|
|
1421
|
-
</div>
|
|
1422
|
-
</div>
|
|
1423
|
-
<div class="log-manager__actions">
|
|
1424
|
-
<button
|
|
1425
|
-
class="btn-icon"
|
|
1426
|
-
@click=${this._toggleFilesPanel}
|
|
1427
|
-
title="Toggle log files"
|
|
1428
|
-
>
|
|
1429
|
-
${d("folder")}
|
|
1430
|
-
${this._files.length>0?o`<span class="badge">${this._files.length}</span>`:""}
|
|
1431
|
-
</button>
|
|
1432
|
-
<button
|
|
1433
|
-
class="btn-icon ${this._autoRefresh?"btn-icon--active":""}"
|
|
1434
|
-
@click=${this._toggleAutoRefresh}
|
|
1435
|
-
title=${this._autoRefresh?r("logs.pause"):r("logs.autoRefresh")}
|
|
1436
|
-
>
|
|
1437
|
-
${d(this._autoRefresh?"pause":"play")}
|
|
1438
|
-
</button>
|
|
1439
|
-
<button
|
|
1440
|
-
class="btn-icon"
|
|
1441
|
-
@click=${()=>this._loadLogs(!0)}
|
|
1442
|
-
title=${r("logs.refresh")}
|
|
1443
|
-
>
|
|
1444
|
-
${d("refreshCw")}
|
|
1445
|
-
</button>
|
|
1446
|
-
</div>
|
|
1447
|
-
</div>
|
|
1448
|
-
`}_renderFilters(){return o`
|
|
1449
|
-
<div class="log-manager__filters">
|
|
1450
|
-
<div class="log-manager__filters-row">
|
|
1451
|
-
<div class="filter-group">
|
|
1452
|
-
<label class="filter-label">${r("logs.level")}</label>
|
|
1453
|
-
<div class="level-filters">
|
|
1454
|
-
${ci.map(e=>o`
|
|
1455
|
-
<button
|
|
1456
|
-
class="level-badge ${this._selectedLevels.has(e)?"level-badge--active":""}"
|
|
1457
|
-
style="--level-color: ${be[e]}"
|
|
1458
|
-
@click=${()=>this._toggleLevel(e)}
|
|
1459
|
-
>
|
|
1460
|
-
${e}
|
|
1461
|
-
</button>
|
|
1462
|
-
`)}
|
|
1463
|
-
</div>
|
|
1464
|
-
</div>
|
|
1465
|
-
|
|
1466
|
-
<div class="filter-group">
|
|
1467
|
-
<label class="filter-label">${r("logs.search")}</label>
|
|
1468
|
-
<div class="search-box">
|
|
1469
|
-
${d("search")}
|
|
1470
|
-
<input
|
|
1471
|
-
type="text"
|
|
1472
|
-
placeholder="${r("logs.searchPlaceholder")}"
|
|
1473
|
-
.value=${this._searchQuery}
|
|
1474
|
-
@input=${this._handleSearch}
|
|
1475
|
-
/>
|
|
1476
|
-
</div>
|
|
1477
|
-
</div>
|
|
1478
|
-
</div>
|
|
1479
|
-
|
|
1480
|
-
<div class="filter-row">
|
|
1481
|
-
<div class="filter-group">
|
|
1482
|
-
<label class="filter-label">Module</label>
|
|
1483
|
-
<select @change=${this._handleModuleChange}>
|
|
1484
|
-
<option value="">All modules</option>
|
|
1485
|
-
${this._modules.map(e=>o`<option value="${e}">${e}</option>`)}
|
|
1486
|
-
</select>
|
|
1487
|
-
</div>
|
|
1488
|
-
|
|
1489
|
-
<div class="filter-group">
|
|
1490
|
-
<label class="filter-label">From</label>
|
|
1491
|
-
<input
|
|
1492
|
-
type="datetime-local"
|
|
1493
|
-
.value=${this._dateFrom}
|
|
1494
|
-
@input=${this._handleDateFromChange}
|
|
1495
|
-
/>
|
|
1496
|
-
</div>
|
|
1497
|
-
|
|
1498
|
-
<div class="filter-group">
|
|
1499
|
-
<label class="filter-label">To</label>
|
|
1500
|
-
<input
|
|
1501
|
-
type="datetime-local"
|
|
1502
|
-
.value=${this._dateTo}
|
|
1503
|
-
@input=${this._handleDateToChange}
|
|
1504
|
-
/>
|
|
1505
|
-
</div>
|
|
1506
|
-
|
|
1507
|
-
<button class="btn btn-ghost" @click=${this._clearFilters}>
|
|
1508
|
-
${d("x")}
|
|
1509
|
-
Clear
|
|
1510
|
-
</button>
|
|
1511
|
-
</div>
|
|
1512
|
-
</div>
|
|
1513
|
-
`}_renderLogTable(){return this._loading&&this._logs.length===0?this._renderLoading():this._logs.length===0?o`
|
|
1514
|
-
<div class="log-manager__empty">
|
|
1515
|
-
<div class="empty-state">
|
|
1516
|
-
<div class="empty-state__icon">${d("fileText")}</div>
|
|
1517
|
-
<div class="empty-state__title">${r("logs.noLogs")}</div>
|
|
1518
|
-
<div class="empty-state__description">
|
|
1519
|
-
${r("logs.noLogsDescription")}
|
|
1520
|
-
</div>
|
|
1521
|
-
</div>
|
|
1522
|
-
</div>
|
|
1523
|
-
`:o`
|
|
1524
|
-
<div class="log-table-container">
|
|
1525
|
-
<table class="log-table">
|
|
1526
|
-
<thead>
|
|
1527
|
-
<tr>
|
|
1528
|
-
<th>${r("logs.time")}</th>
|
|
1529
|
-
<th>${r("logs.level")}</th>
|
|
1530
|
-
<th>${r("logs.module")}</th>
|
|
1531
|
-
<th>${r("logs.message")}</th>
|
|
1532
|
-
</tr>
|
|
1533
|
-
</thead>
|
|
1534
|
-
<tbody>
|
|
1535
|
-
${this._logs.length===0?o`
|
|
1536
|
-
<tr>
|
|
1537
|
-
<td colspan="4" style="padding: 2rem; text-align: center; color: var(--text-muted);">
|
|
1538
|
-
No logs to display
|
|
1539
|
-
</td>
|
|
1540
|
-
</tr>
|
|
1541
|
-
`:this._logs.map(e=>o`
|
|
1542
|
-
<tr class="log-row log-row--${e.level||"info"}" @click=${()=>this._selectLog(e)}>
|
|
1543
|
-
<td class="log-cell log-cell--time">${this._formatTimestamp(e.timestamp)}</td>
|
|
1544
|
-
<td class="log-cell log-cell--level">
|
|
1545
|
-
<span
|
|
1546
|
-
class="level-badge level-badge--small"
|
|
1547
|
-
style="--level-color: ${be[e.level]||be.info}"
|
|
1548
|
-
>
|
|
1549
|
-
${e.level||"info"}
|
|
1550
|
-
</span>
|
|
1551
|
-
</td>
|
|
1552
|
-
<td class="log-cell log-cell--module">${e.module||e.prefix||e.service||"-"}</td>
|
|
1553
|
-
<td class="log-cell log-cell--message">${e.message||JSON.stringify(e)}</td>
|
|
1554
|
-
</tr>
|
|
1555
|
-
`)}
|
|
1556
|
-
</tbody>
|
|
1557
|
-
</table>
|
|
1558
|
-
|
|
1559
|
-
${this._hasMore?o`
|
|
1560
|
-
<div class="log-table__load-more">
|
|
1561
|
-
<button class="btn btn-secondary" @click=${this._handleLoadMore} ?disabled=${this._loading}>
|
|
1562
|
-
${this._loading?o`<span class="spinner"></span>`:d("chevronDown")}
|
|
1563
|
-
Load More
|
|
1564
|
-
</button>
|
|
1565
|
-
</div>
|
|
1566
|
-
`:""}
|
|
1567
|
-
</div>
|
|
1568
|
-
`}_toggleFilesPanel(){this._showFilesPanel=!this._showFilesPanel}_renderFilesPanel(){return o`
|
|
1569
|
-
${this._showFilesPanel?o`
|
|
1570
|
-
<div class="drawer-overlay" @click=${this._toggleFilesPanel}></div>
|
|
1571
|
-
`:""}
|
|
1572
|
-
<div class="files-panel ${this._showFilesPanel?"files-panel--open":""}">
|
|
1573
|
-
<div class="files-panel__header">
|
|
1574
|
-
<span class="files-panel__title">
|
|
1575
|
-
${d("folder")}
|
|
1576
|
-
Log Files
|
|
1577
|
-
</span>
|
|
1578
|
-
<button class="btn btn-icon" @click=${this._toggleFilesPanel}>
|
|
1579
|
-
${d("x")}
|
|
1580
|
-
</button>
|
|
1581
|
-
</div>
|
|
1582
|
-
<div class="files-panel__content">
|
|
1583
|
-
${this._files.length===0?o`
|
|
1584
|
-
<div class="files-panel__empty">No log files found</div>
|
|
1585
|
-
`:o`
|
|
1586
|
-
<div class="file-list">
|
|
1587
|
-
${this._files.map(e=>o`
|
|
1588
|
-
<div class="file-item">
|
|
1589
|
-
<span class="file-name">${d("file")}${e.name}</span>
|
|
1590
|
-
<span class="file-meta">
|
|
1591
|
-
<span class="file-size">${this._formatFileSize(e.size)}</span>
|
|
1592
|
-
<span class="file-time">${this._formatTimestamp(e.modified)}</span>
|
|
1593
|
-
</span>
|
|
1594
|
-
</div>
|
|
1595
|
-
`)}
|
|
1596
|
-
</div>
|
|
1597
|
-
`}
|
|
1598
|
-
</div>
|
|
1599
|
-
</div>
|
|
1600
|
-
`}_renderDetailDrawer(){if(!this._selectedLog)return"";const e=this._selectedLog;return o`
|
|
1601
|
-
<div class="drawer-overlay" @click=${this._closeDetail}></div>
|
|
1602
|
-
<div class="drawer drawer--right">
|
|
1603
|
-
<div class="drawer-header">
|
|
1604
|
-
<h3 class="drawer-header__title">${r("logs.details")}</h3>
|
|
1605
|
-
<button class="btn btn-icon" @click=${this._closeDetail}>${d("x")}</button>
|
|
1606
|
-
</div>
|
|
1607
|
-
<div class="drawer__content">
|
|
1608
|
-
<div class="log-detail">
|
|
1609
|
-
<div class="log-detail__field">
|
|
1610
|
-
<label>${r("logs.time")}</label>
|
|
1611
|
-
<code>${e.timestamp}</code>
|
|
1612
|
-
</div>
|
|
1613
|
-
<div class="log-detail__field">
|
|
1614
|
-
<label>${r("logs.level")}</label>
|
|
1615
|
-
<span
|
|
1616
|
-
class="level-badge"
|
|
1617
|
-
style="--level-color: ${be[e.level]}"
|
|
1618
|
-
>
|
|
1619
|
-
${e.level}
|
|
1620
|
-
</span>
|
|
1621
|
-
</div>
|
|
1622
|
-
<div class="log-detail__field">
|
|
1623
|
-
<label>${r("logs.module")}</label>
|
|
1624
|
-
<code>${e.module}</code>
|
|
1625
|
-
</div>
|
|
1626
|
-
<div class="log-detail__field">
|
|
1627
|
-
<label>${r("logs.message")}</label>
|
|
1628
|
-
<pre class="log-detail__message">${e.message}</pre>
|
|
1629
|
-
</div>
|
|
1630
|
-
${e.meta?o`
|
|
1631
|
-
<div class="log-detail__field">
|
|
1632
|
-
<label>Metadata</label>
|
|
1633
|
-
<pre class="log-detail__meta">${JSON.stringify(e.meta,null,2)}</pre>
|
|
1634
|
-
</div>
|
|
1635
|
-
`:""}
|
|
1636
|
-
</div>
|
|
1637
|
-
</div>
|
|
1638
|
-
</div>
|
|
1639
|
-
`}_renderLoading(){return o`
|
|
1640
|
-
<div class="log-manager__loading">
|
|
1641
|
-
<div class="skeleton-table">
|
|
1642
|
-
${Array.from({length:10}).map(()=>o`
|
|
1643
|
-
<div class="skeleton-row">
|
|
1644
|
-
<div class="skeleton skeleton--time"></div>
|
|
1645
|
-
<div class="skeleton skeleton--level"></div>
|
|
1646
|
-
<div class="skeleton skeleton--module"></div>
|
|
1647
|
-
<div class="skeleton skeleton--message"></div>
|
|
1648
|
-
</div>
|
|
1649
|
-
`)}
|
|
1650
|
-
</div>
|
|
1651
|
-
</div>
|
|
1652
|
-
`}};C([u({attribute:!1})],$.prototype,"config",2);C([c()],$.prototype,"_logs",2);C([c()],$.prototype,"_loading",2);C([c()],$.prototype,"_hasMore",2);C([c()],$.prototype,"_files",2);C([c()],$.prototype,"_modules",2);C([c()],$.prototype,"_showFilesPanel",2);C([c()],$.prototype,"_selectedLevels",2);C([c()],$.prototype,"_searchQuery",2);C([c()],$.prototype,"_selectedModule",2);C([c()],$.prototype,"_dateFrom",2);C([c()],$.prototype,"_dateTo",2);C([c()],$.prototype,"_offset",2);C([c()],$.prototype,"_error",2);C([c()],$.prototype,"_selectedLog",2);C([c()],$.prototype,"_autoRefresh",2);C([c()],$.prototype,"_refreshInterval",2);$=C([k("log-manager")],$);var ui=Object.defineProperty,gi=Object.getOwnPropertyDescriptor,P=(e,t,s,i)=>{for(var n=i>1?void 0:i?gi(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&ui(t,s,n),n};let E=class extends y{constructor(){super(...arguments),this._activeSection="agent",this._loading=!1,this._saving=!1,this._refreshingToken=!1,this._serverToken=null,this._showToken=!1,this._dirtyFields=new Set,this._errors=new Map,this._saveSuccess=!1,this._models=[],this._values={model:"anthropic/claude-sonnet-4-5",maxTokens:8192,temperature:.7,maxToolIterations:20,telegramEnabled:!1,telegramToken:"",telegramApiRoot:"",telegramDebug:!1,telegramAllowFrom:"",whatsappEnabled:!1,whatsappBridgeUrl:"ws://localhost:3001",whatsappAllowFrom:"",gatewayToken:"",heartbeatEnabled:!0,heartbeatIntervalMs:6e4,openaiApiKey:"",anthropicApiKey:"",googleApiKey:"",qwenApiKey:"",kimiApiKey:"",minimaxApiKey:"",deepseekApiKey:"",grokApiKey:"",openrouterApiKey:"",workspace:"",theme:"system"},this._initialized=!1}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this._tryInitialize()}willUpdate(e){super.willUpdate(e),e.has("config")&&this._tryInitialize()}_tryInitialize(){this._initialized||(this._initialized=!0,this._loadSettings())}get _sections(){const e=this._models.map(t=>({value:t.id,label:`${t.provider}/${t.name}`}));return[{id:"agent",title:r("settings.sections.agent"),icon:"bot",fields:[{key:"model",label:r("settings.fields.model"),type:"select",description:r("settings.descriptionsFields.model"),options:e},{key:"workspace",label:r("settings.fields.workspace"),type:"text",description:r("settings.descriptionsFields.workspace"),placeholder:r("settings.placeholders.workspace")},{key:"maxTokens",label:r("settings.fields.maxTokens"),type:"number",description:r("settings.descriptionsFields.maxTokens"),validation:{min:256,max:128e3}},{key:"temperature",label:r("settings.fields.temperature"),type:"number",description:r("settings.descriptionsFields.temperature"),validation:{min:0,max:2}},{key:"maxToolIterations",label:r("settings.fields.maxToolIterations"),type:"number",description:r("settings.descriptionsFields.maxToolIterations"),validation:{min:1,max:100}}]},{id:"providers",title:r("settings.sections.providers"),icon:"cloud",fields:[{key:"openaiApiKey",label:r("settings.fields.openaiApiKey"),type:"password",description:r("settings.descriptionsFields.openaiApiKey"),placeholder:r("settings.placeholders.openaiApiKey")},{key:"anthropicApiKey",label:r("settings.fields.anthropicApiKey"),type:"password",description:r("settings.descriptionsFields.anthropicApiKey"),placeholder:r("settings.placeholders.anthropicApiKey")},{key:"googleApiKey",label:r("settings.fields.googleApiKey"),type:"password",description:r("settings.descriptionsFields.googleApiKey"),placeholder:r("settings.placeholders.googleApiKey")},{key:"qwenApiKey",label:r("settings.fields.qwenApiKey"),type:"password",description:r("settings.descriptionsFields.qwenApiKey"),placeholder:r("settings.placeholders.qwenApiKey")},{key:"kimiApiKey",label:r("settings.fields.kimiApiKey"),type:"password",description:r("settings.descriptionsFields.kimiApiKey"),placeholder:r("settings.placeholders.kimiApiKey")},{key:"minimaxApiKey",label:r("settings.fields.minimaxApiKey"),type:"password",description:r("settings.descriptionsFields.minimaxApiKey"),placeholder:r("settings.placeholders.minimaxApiKey")},{key:"deepseekApiKey",label:r("settings.fields.deepseekApiKey"),type:"password",description:r("settings.descriptionsFields.deepseekApiKey"),placeholder:r("settings.placeholders.deepseekApiKey")},{key:"openrouterApiKey",label:r("settings.fields.openrouterApiKey"),type:"password",description:r("settings.descriptionsFields.openrouterApiKey"),placeholder:r("settings.placeholders.openrouterApiKey")}]},{id:"channels",title:r("settings.sections.channels"),icon:"plug",fields:[{key:"telegramEnabled",label:r("settings.fields.telegramEnabled"),type:"boolean",description:r("settings.descriptionsFields.telegramEnabled")},...this._values.telegramEnabled?[{key:"telegramToken",label:r("settings.fields.telegramToken"),type:"password",description:r("settings.descriptionsFields.telegramToken"),placeholder:r("settings.placeholders.telegramToken")},{key:"telegramApiRoot",label:r("settings.fields.telegramApiRoot"),type:"text",description:r("settings.descriptionsFields.telegramApiRoot"),placeholder:r("settings.placeholders.telegramApiRoot")},{key:"telegramAllowFrom",label:r("settings.fields.telegramAllowFrom"),type:"text",description:r("settings.descriptionsFields.telegramAllowFrom"),placeholder:r("settings.placeholders.telegramAllowFrom")},{key:"telegramDebug",label:r("settings.fields.telegramDebug"),type:"boolean",description:r("settings.descriptionsFields.telegramDebug")}]:[],{key:"whatsappEnabled",label:r("settings.fields.whatsappEnabled"),type:"boolean",description:r("settings.descriptionsFields.whatsappEnabled")},...this._values.whatsappEnabled?[{key:"whatsappBridgeUrl",label:r("settings.fields.whatsappBridgeUrl"),type:"text",description:r("settings.descriptionsFields.whatsappBridgeUrl"),placeholder:r("settings.placeholders.whatsappBridgeUrl")},{key:"whatsappAllowFrom",label:r("settings.fields.whatsappAllowFrom"),type:"text",description:r("settings.descriptionsFields.whatsappAllowFrom"),placeholder:r("settings.placeholders.whatsappAllowFrom")}]:[]]},{id:"gateway",title:r("settings.sections.gateway"),icon:"globe",fields:[{key:"gatewayToken",label:r("settings.fields.gatewayToken"),type:"password",description:r("settings.descriptionsFields.gatewayToken"),placeholder:r("settings.placeholders.gatewayToken")},{key:"heartbeatEnabled",label:r("settings.fields.heartbeatEnabled"),type:"boolean",description:r("settings.descriptionsFields.heartbeatEnabled")},{key:"heartbeatIntervalMs",label:r("settings.fields.heartbeatIntervalMs"),type:"number",description:r("settings.descriptionsFields.heartbeatIntervalMs"),validation:{min:1e3,max:6e5}}]}]}async _loadSettings(){this._loading=!0;const e=window.location.origin,t=this.config?.token;try{await this._loadModels();const s=this._loadUiSettings();this._values.gatewayToken=s.token||"",await this._loadServerToken();const i=await fetch(`${e}/api/config`,{headers:t?{Authorization:`Bearer ${t}`}:{}});if(i.ok){const a=(await i.json()).payload?.config;if(a){let l=a.agents?.defaults?.model;l&&typeof l=="object"&&(l=l.primary||""),this._values={...this._values,model:l||"anthropic/claude-sonnet-4-5",workspace:a.agents?.defaults?.workspace||"",maxTokens:a.agents?.defaults?.maxTokens||8192,temperature:a.agents?.defaults?.temperature??.7,maxToolIterations:a.agents?.defaults?.maxToolIterations||20,openaiApiKey:a.providers?.openai?.apiKey||"",anthropicApiKey:a.providers?.anthropic?.apiKey||"",googleApiKey:a.providers?.google?.apiKey||"",qwenApiKey:a.providers?.qwen?.apiKey||"",kimiApiKey:a.providers?.kimi?.apiKey||"",minimaxApiKey:a.providers?.minimax?.apiKey||"",deepseekApiKey:a.providers?.deepseek?.apiKey||"",openrouterApiKey:a.providers?.openrouter?.apiKey||"",telegramEnabled:a.channels?.telegram?.enabled||!1,telegramToken:a.channels?.telegram?.token||"",telegramApiRoot:a.channels?.telegram?.apiRoot||"",telegramDebug:a.channels?.telegram?.debug||!1,telegramAllowFrom:(a.channels?.telegram?.allowFrom||[]).join(", "),whatsappEnabled:a.channels?.whatsapp?.enabled||!1,whatsappBridgeUrl:a.channels?.whatsapp?.bridgeUrl||"ws://localhost:3001",whatsappAllowFrom:(a.channels?.whatsapp?.allowFrom||[]).join(", "),heartbeatEnabled:a.gateway?.heartbeat?.enabled??!0,heartbeatIntervalMs:a.gateway?.heartbeat?.intervalMs||6e4}}}}catch(s){console.error("Failed to load settings:",s)}finally{this._loading=!1}}_loadUiSettings(){try{return{token:localStorage.getItem("xopcbot.token")||""}}catch{return{token:""}}}_saveUiSettings(e){try{localStorage.setItem("xopcbot.token",e)}catch(t){console.error("Failed to save UI settings:",t)}}async _loadServerToken(){try{const e=window.location.origin,t=this.config?.token,s=await fetch(`${e}/api/auth/token`,{headers:t?{Authorization:`Bearer ${t}`}:{}});if(s.ok){const i=await s.json();i.ok&&i.payload?.token&&(this._serverToken=i.payload.token)}}catch(e){console.error("Failed to load server token:",e)}}async _refreshServerToken(){this._refreshingToken=!0;try{const e=window.location.origin,t=this.config?.token,s=await fetch(`${e}/api/auth/token/refresh`,{method:"POST",headers:t?{Authorization:`Bearer ${t}`}:{}});if(s.ok){const i=await s.json();i.ok&&i.payload?.token&&(this._serverToken=i.payload.token,this._values.gatewayToken=i.payload.token,this._saveUiSettings(i.payload.token),this.requestUpdate(),alert("Token refreshed successfully! Please copy the new token and update any other clients."))}else{const i=await s.json();throw new Error(i.error||"Failed to refresh token")}}catch(e){console.error("Failed to refresh token:",e),alert(e instanceof Error?e.message:"Failed to refresh token")}finally{this._refreshingToken=!1,this.requestUpdate()}}async _loadModels(){try{const e=window.location.origin,t=this.config?.token,s=await fetch(`${e}/api/models`,{headers:t?{Authorization:`Bearer ${t}`}:{}});if(s.ok){const i=await s.json();i.payload?.models&&(this._models=i.payload.models)}}catch(e){console.error("Failed to load models:",e)}}async _saveSettings(){if(this._errors.size>0)return;this._saving=!0,this._saveSuccess=!1;const e=window.location.origin,t=this.config?.token,s={};(this._dirtyFields.has("model")||this._dirtyFields.has("maxTokens")||this._dirtyFields.has("temperature")||this._dirtyFields.has("maxToolIterations")||this._dirtyFields.has("workspace"))&&(s.agents={defaults:{}},this._dirtyFields.has("model")&&(s.agents.defaults.model=this._values.model),this._dirtyFields.has("workspace")&&(s.agents.defaults.workspace=this._values.workspace),this._dirtyFields.has("maxTokens")&&(s.agents.defaults.maxTokens=Number(this._values.maxTokens)),this._dirtyFields.has("temperature")&&(s.agents.defaults.temperature=Number(this._values.temperature)),this._dirtyFields.has("maxToolIterations")&&(s.agents.defaults.maxToolIterations=Number(this._values.maxToolIterations))),["openaiApiKey","anthropicApiKey","googleApiKey","qwenApiKey","kimiApiKey","minimaxApiKey","deepseekApiKey","openrouterApiKey"].filter(a=>this._dirtyFields.has(a)).length>0&&(s.providers={},this._dirtyFields.has("openaiApiKey")&&(s.providers.openai={apiKey:this._values.openaiApiKey}),this._dirtyFields.has("anthropicApiKey")&&(s.providers.anthropic={apiKey:this._values.anthropicApiKey}),this._dirtyFields.has("googleApiKey")&&(s.providers.google={apiKey:this._values.googleApiKey}),this._dirtyFields.has("qwenApiKey")&&(s.providers.qwen={apiKey:this._values.qwenApiKey}),this._dirtyFields.has("kimiApiKey")&&(s.providers.kimi={apiKey:this._values.kimiApiKey}),this._dirtyFields.has("minimaxApiKey")&&(s.providers.minimax={apiKey:this._values.minimaxApiKey}),this._dirtyFields.has("deepseekApiKey")&&(s.providers.deepseek={apiKey:this._values.deepseekApiKey}),this._dirtyFields.has("openrouterApiKey")&&(s.providers.openrouter={apiKey:this._values.openrouterApiKey})),(this._dirtyFields.has("telegramEnabled")||this._dirtyFields.has("whatsappEnabled")||this._dirtyFields.has("telegramToken")||this._dirtyFields.has("telegramApiRoot")||this._dirtyFields.has("telegramDebug")||this._dirtyFields.has("telegramAllowFrom")||this._dirtyFields.has("whatsappBridgeUrl")||this._dirtyFields.has("whatsappAllowFrom"))&&(s.channels={},(this._dirtyFields.has("telegramEnabled")||this._dirtyFields.has("telegramToken")||this._dirtyFields.has("telegramApiRoot")||this._dirtyFields.has("telegramDebug")||this._dirtyFields.has("telegramAllowFrom"))&&(s.channels={...s.channels,telegram:{}},this._dirtyFields.has("telegramEnabled")&&(s.channels.telegram.enabled=!!this._values.telegramEnabled),this._dirtyFields.has("telegramToken")&&(s.channels.telegram.token=this._values.telegramToken),this._dirtyFields.has("telegramApiRoot")&&(s.channels.telegram.apiRoot=this._values.telegramApiRoot||void 0),this._dirtyFields.has("telegramDebug")&&(s.channels.telegram.debug=!!this._values.telegramDebug),this._dirtyFields.has("telegramAllowFrom")&&(s.channels.telegram.allowFrom=this._values.telegramAllowFrom?this._values.telegramAllowFrom.split(",").map(a=>a.trim()).filter(a=>a):[])),(this._dirtyFields.has("whatsappEnabled")||this._dirtyFields.has("whatsappBridgeUrl")||this._dirtyFields.has("whatsappAllowFrom"))&&(s.channels={...s.channels,whatsapp:{}},this._dirtyFields.has("whatsappEnabled")&&(s.channels.whatsapp.enabled=!!this._values.whatsappEnabled),this._dirtyFields.has("whatsappBridgeUrl")&&(s.channels.whatsapp.bridgeUrl=this._values.whatsappBridgeUrl),this._dirtyFields.has("whatsappAllowFrom")&&(s.channels.whatsapp.allowFrom=this._values.whatsappAllowFrom?this._values.whatsappAllowFrom.split(",").map(a=>a.trim()).filter(a=>a):[]))),(this._dirtyFields.has("heartbeatEnabled")||this._dirtyFields.has("heartbeatIntervalMs"))&&(s.gateway={heartbeat:{}},this._dirtyFields.has("heartbeatEnabled")&&(s.gateway.heartbeat.enabled=!!this._values.heartbeatEnabled),this._dirtyFields.has("heartbeatIntervalMs")&&(s.gateway.heartbeat.intervalMs=Number(this._values.heartbeatIntervalMs)));try{const a=await fetch(`${e}/api/config`,{method:"PATCH",headers:{"Content-Type":"application/json",...t?{Authorization:`Bearer ${t}`}:{}},body:JSON.stringify(s)});if(!a.ok){const l=await a.json();throw new Error(l.error||"Failed to save settings")}this._dirtyFields.clear(),this._dirtyFields.has("gatewayToken")&&this._saveUiSettings(this._values.gatewayToken||""),this._saveSuccess=!0,setTimeout(()=>{this._saveSuccess=!1},3e3)}catch(a){console.error("Failed to save settings:",a),alert(a instanceof Error?a.message:"Failed to save settings")}finally{this._saving=!1}}_handleInput(e,t){this._values={...this._values,[e]:t},this._dirtyFields.add(e),this.requestUpdate()}render(){return o`
|
|
1653
|
-
<div class="settings-page">
|
|
1654
|
-
<div class="settings-sidebar">
|
|
1655
|
-
<div class="sidebar-header">
|
|
1656
|
-
<h3>${r("settings.title")}</h3>
|
|
1657
|
-
</div>
|
|
1658
|
-
<nav class="sidebar-nav">
|
|
1659
|
-
${this._sections.map(e=>o`
|
|
1660
|
-
<button
|
|
1661
|
-
class="nav-item ${this._activeSection===e.id?"active":""}"
|
|
1662
|
-
@click=${()=>this._activeSection=e.id}
|
|
1663
|
-
>
|
|
1664
|
-
${d(e.icon)}
|
|
1665
|
-
<span>${e.title}</span>
|
|
1666
|
-
</button>
|
|
1667
|
-
`)}
|
|
1668
|
-
</nav>
|
|
1669
|
-
</div>
|
|
1670
|
-
|
|
1671
|
-
<div class="settings-main">
|
|
1672
|
-
${this._loading?o`
|
|
1673
|
-
<div class="loading-state">
|
|
1674
|
-
<div class="spinner"></div>
|
|
1675
|
-
<p>${r("settings.loading")}</p>
|
|
1676
|
-
</div>
|
|
1677
|
-
`:this._renderSection()}
|
|
1678
|
-
</div>
|
|
1679
|
-
|
|
1680
|
-
<!-- Save button floating -->
|
|
1681
|
-
${this._dirtyFields.size>0?o`
|
|
1682
|
-
<div class="floating-save">
|
|
1683
|
-
<span class="dirty-count">${r("settings.unsaved",{count:this._dirtyFields.size})}</span>
|
|
1684
|
-
<button
|
|
1685
|
-
class="btn btn-primary"
|
|
1686
|
-
?disabled=${this._saving||this._errors.size>0}
|
|
1687
|
-
@click=${this._saveSettings}
|
|
1688
|
-
>
|
|
1689
|
-
${this._saving?o`
|
|
1690
|
-
<span class="spinner-sm"></span>
|
|
1691
|
-
${r("settings.saving")}
|
|
1692
|
-
`:o`
|
|
1693
|
-
<span>${d("save")}</span>
|
|
1694
|
-
${r("settings.saveChanges")}
|
|
1695
|
-
`}
|
|
1696
|
-
</button>
|
|
1697
|
-
</div>
|
|
1698
|
-
`:""}
|
|
1699
|
-
</div>
|
|
1700
|
-
`}_renderSection(){const e=this._sections.find(s=>s.id===this._activeSection);if(!e)return o`<div>${r("settings.noSection")}</div>`;const t=`settings.descriptions.${e.id}`;return o`
|
|
1701
|
-
<div class="section-content">
|
|
1702
|
-
<div class="section-header">
|
|
1703
|
-
<h2>${e.title}</h2>
|
|
1704
|
-
<p class="section-desc">${r(t)}</p>
|
|
1705
|
-
</div>
|
|
1706
|
-
|
|
1707
|
-
${e.id==="gateway"?this._renderGatewaySection():""}
|
|
1708
|
-
|
|
1709
|
-
<div class="fields-grid">
|
|
1710
|
-
${e.fields.map(s=>this._renderField(s))}
|
|
1711
|
-
</div>
|
|
1712
|
-
</div>
|
|
1713
|
-
`}_renderGatewaySection(){const e=this._serverToken?`${this._serverToken.slice(0,8)}...${this._serverToken.slice(-8)}`:"Not available";return o`
|
|
1714
|
-
<div class="gateway-token-section" style="margin-bottom: 24px; padding: 16px; background: var(--muted); border-radius: 8px;">
|
|
1715
|
-
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px;">
|
|
1716
|
-
<h4 style="margin: 0; font-size: 14px; font-weight: 600;">Server Authentication Token</h4>
|
|
1717
|
-
<button
|
|
1718
|
-
class="btn btn-sm btn-secondary"
|
|
1719
|
-
?disabled=${this._refreshingToken}
|
|
1720
|
-
@click=${this._refreshServerToken}
|
|
1721
|
-
style="display: flex; align-items: center; gap: 6px;"
|
|
1722
|
-
>
|
|
1723
|
-
${this._refreshingToken?o`
|
|
1724
|
-
<span class="spinner-sm"></span>
|
|
1725
|
-
Refreshing...
|
|
1726
|
-
`:o`
|
|
1727
|
-
${d("refreshCw")}
|
|
1728
|
-
Refresh Token
|
|
1729
|
-
`}
|
|
1730
|
-
</button>
|
|
1731
|
-
</div>
|
|
1732
|
-
|
|
1733
|
-
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 8px;">
|
|
1734
|
-
<code style="flex: 1; padding: 8px 12px; background: var(--background); border-radius: 4px; font-family: monospace; font-size: 13px; word-break: break-all;">
|
|
1735
|
-
${this._showToken?this._serverToken||"Not available":e}
|
|
1736
|
-
</code>
|
|
1737
|
-
<button
|
|
1738
|
-
class="btn btn-icon"
|
|
1739
|
-
@click=${()=>this._showToken=!this._showToken}
|
|
1740
|
-
title=${this._showToken?"Hide token":"Show token"}
|
|
1741
|
-
>
|
|
1742
|
-
${this._showToken?d("eyeOff"):d("eye")}
|
|
1743
|
-
</button>
|
|
1744
|
-
<button
|
|
1745
|
-
class="btn btn-icon"
|
|
1746
|
-
?disabled=${!this._serverToken}
|
|
1747
|
-
@click=${()=>{this._serverToken&&(navigator.clipboard.writeText(this._serverToken),alert("Token copied to clipboard!"))}}
|
|
1748
|
-
title="Copy token"
|
|
1749
|
-
>
|
|
1750
|
-
${d("copy")}
|
|
1751
|
-
</button>
|
|
1752
|
-
</div>
|
|
1753
|
-
|
|
1754
|
-
<p style="margin: 0; font-size: 12px; color: var(--muted-foreground);">
|
|
1755
|
-
This is the current server token. Click "Refresh Token" to generate a new one.
|
|
1756
|
-
After refreshing, copy the new token and update your client configuration.
|
|
1757
|
-
</p>
|
|
1758
|
-
</div>
|
|
1759
|
-
`}_renderField(e){const t=this._values[e.key],s=this._errors.get(e.key);return o`
|
|
1760
|
-
<div class="field-group ${s?"has-error":""}">
|
|
1761
|
-
<div class="field-header">
|
|
1762
|
-
<label class="field-label">${e.label}</label>
|
|
1763
|
-
${e.validation?.required?o`<span class="required-mark">*</span>`:""}
|
|
1764
|
-
</div>
|
|
1765
|
-
|
|
1766
|
-
${e.description?o`<p class="field-desc">${e.description}</p>`:""}
|
|
1767
|
-
|
|
1768
|
-
${e.type==="boolean"?this._renderBooleanField(e,t):""}
|
|
1769
|
-
${e.type==="select"?this._renderSelectField(e,t):""}
|
|
1770
|
-
${["text","password","number"].includes(e.type)?this._renderInputField(e,t):""}
|
|
1771
|
-
|
|
1772
|
-
${s?o`
|
|
1773
|
-
<div class="field-error">
|
|
1774
|
-
<span>${s}</span>
|
|
1775
|
-
</div>
|
|
1776
|
-
`:""}
|
|
1777
|
-
</div>
|
|
1778
|
-
`}_renderInputField(e,t){return o`
|
|
1779
|
-
<input
|
|
1780
|
-
type=${e.type==="number"?"number":"text"}
|
|
1781
|
-
class="text-input"
|
|
1782
|
-
.value=${String(t??"")}
|
|
1783
|
-
placeholder=${e.placeholder||""}
|
|
1784
|
-
minlength=${e.validation?.min}
|
|
1785
|
-
maxlength=${e.validation?.max}
|
|
1786
|
-
min=${e.validation?.min}
|
|
1787
|
-
max=${e.validation?.max}
|
|
1788
|
-
@input=${s=>this._handleInput(e.key,s.target.value)}
|
|
1789
|
-
/>
|
|
1790
|
-
`}_renderSelectField(e,t){return o`
|
|
1791
|
-
<select
|
|
1792
|
-
class="select-input"
|
|
1793
|
-
.value=${String(t??"")}
|
|
1794
|
-
@change=${s=>this._handleInput(e.key,s.target.value)}
|
|
1795
|
-
>
|
|
1796
|
-
${e.options?.map(s=>o`
|
|
1797
|
-
<option value=${s.value} ?selected=${t===s.value}>${s.label}</option>
|
|
1798
|
-
`)}
|
|
1799
|
-
</select>
|
|
1800
|
-
`}_renderBooleanField(e,t){return o`
|
|
1801
|
-
<label class="toggle-label">
|
|
1802
|
-
<input
|
|
1803
|
-
type="checkbox"
|
|
1804
|
-
class="toggle-input"
|
|
1805
|
-
.checked=${!!t}
|
|
1806
|
-
@change=${s=>this._handleInput(e.key,s.target.checked)}
|
|
1807
|
-
/>
|
|
1808
|
-
<span class="toggle-switch"></span>
|
|
1809
|
-
<span class="toggle-text">${e.description||r("settings.enableFeature")}</span>
|
|
1810
|
-
</label>
|
|
1811
|
-
`}};P([u({attribute:!1})],E.prototype,"config",2);P([c()],E.prototype,"_activeSection",2);P([c()],E.prototype,"_loading",2);P([c()],E.prototype,"_saving",2);P([c()],E.prototype,"_refreshingToken",2);P([c()],E.prototype,"_serverToken",2);P([c()],E.prototype,"_showToken",2);P([c()],E.prototype,"_dirtyFields",2);P([c()],E.prototype,"_errors",2);P([c()],E.prototype,"_saveSuccess",2);P([c()],E.prototype,"_models",2);P([c()],E.prototype,"_values",2);E=P([k("settings-page")],E);var _i=Object.defineProperty,mi=Object.getOwnPropertyDescriptor,le=(e,t,s,i)=>{for(var n=i>1?void 0:i?mi(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&_i(t,s,n),n};let X=class extends y{constructor(){super(...arguments),this._token="",this._showToken=!1,this._loading=!1,this._error=""}createRenderRoot(){return this}_handleSave(){if(!this._token.trim()){this._error="Please enter a token";return}this.config?.onSave(this._token.trim())}_handleKeydown(e){e.key==="Enter"&&this._handleSave()}render(){return o`
|
|
1812
|
-
<div class="token-dialog-overlay" @click=${this._handleOverlayClick}>
|
|
1813
|
-
<div class="token-dialog" @click=${e=>e.stopPropagation()}>
|
|
1814
|
-
<div class="token-dialog-header">
|
|
1815
|
-
<h3>🔐 Authentication Required</h3>
|
|
1816
|
-
<p>Please enter your gateway authentication token to continue.</p>
|
|
1817
|
-
</div>
|
|
1818
|
-
|
|
1819
|
-
<div class="token-dialog-body">
|
|
1820
|
-
<div class="field-group">
|
|
1821
|
-
<label class="field-label">Gateway URL</label>
|
|
1822
|
-
<input
|
|
1823
|
-
type="text"
|
|
1824
|
-
class="text-input"
|
|
1825
|
-
.value=${this.config?.serverUrl||""}
|
|
1826
|
-
disabled
|
|
1827
|
-
/>
|
|
1828
|
-
</div>
|
|
1829
|
-
|
|
1830
|
-
<div class="field-group">
|
|
1831
|
-
<label class="field-label">Token</label>
|
|
1832
|
-
<div class="token-input-wrapper">
|
|
1833
|
-
<input
|
|
1834
|
-
type=${this._showToken?"text":"password"}
|
|
1835
|
-
class="text-input"
|
|
1836
|
-
.value=${this._token}
|
|
1837
|
-
placeholder="Enter your gateway token (e.g., ea4c67bf...)"
|
|
1838
|
-
@input=${e=>{this._token=e.target.value,this._error=""}}
|
|
1839
|
-
@keydown=${this._handleKeydown}
|
|
1840
|
-
/>
|
|
1841
|
-
<button
|
|
1842
|
-
class="btn btn-icon toggle-visibility"
|
|
1843
|
-
@click=${()=>this._showToken=!this._showToken}
|
|
1844
|
-
title=${this._showToken?"Hide token":"Show token"}
|
|
1845
|
-
>
|
|
1846
|
-
${this._showToken?d("eyeOff"):d("eye")}
|
|
1847
|
-
</button>
|
|
1848
|
-
</div>
|
|
1849
|
-
${this._error?o`<span class="field-error">${this._error}</span>`:""}
|
|
1850
|
-
</div>
|
|
1851
|
-
|
|
1852
|
-
<div class="token-hint">
|
|
1853
|
-
<p>💡 <strong>How to get your token:</strong></p>
|
|
1854
|
-
<ol>
|
|
1855
|
-
<li>Run <code>xopcbot gateway token</code> in your terminal</li>
|
|
1856
|
-
<li>Or run <code>xopcbot gateway token --generate</code> to create a new one</li>
|
|
1857
|
-
<li>Copy the token and paste it here</li>
|
|
1858
|
-
</ol>
|
|
1859
|
-
</div>
|
|
1860
|
-
</div>
|
|
1861
|
-
|
|
1862
|
-
<div class="token-dialog-footer">
|
|
1863
|
-
<button
|
|
1864
|
-
class="btn btn-primary"
|
|
1865
|
-
?disabled=${this._loading}
|
|
1866
|
-
@click=${this._handleSave}
|
|
1867
|
-
>
|
|
1868
|
-
${this._loading?o`
|
|
1869
|
-
<span class="spinner-sm"></span>
|
|
1870
|
-
Connecting...
|
|
1871
|
-
`:o`
|
|
1872
|
-
${d("check")}
|
|
1873
|
-
Connect
|
|
1874
|
-
`}
|
|
1875
|
-
</button>
|
|
1876
|
-
</div>
|
|
1877
|
-
</div>
|
|
1878
|
-
</div>
|
|
1879
|
-
`}_handleOverlayClick(e){this.config?.onCancel&&this.config.onCancel()}};le([u({attribute:!1})],X.prototype,"config",2);le([c()],X.prototype,"_token",2);le([c()],X.prototype,"_showToken",2);le([c()],X.prototype,"_loading",2);le([c()],X.prototype,"_error",2);X=le([k("token-dialog")],X);function vi(){return[{label:r("nav.chat"),tabs:["chat"]},{label:r("nav.management"),tabs:["sessions","cron","logs"]},{label:r("nav.settings"),tabs:["settings"]}]}function fi(e){return r(`nav.${e}`)}const yi={chat:"messageSquare",sessions:"folderOpen",cron:"clock",logs:"fileText",settings:"settings"};function wi(e){const t=e.replace(/^#\/?chat\/?/,"");if(!t||t==="/")return{type:"recent"};const s=t.replace(/^\/?/,"");return s==="new"?{type:"new"}:s&&s.length>0?{type:"session",sessionKey:decodeURIComponent(s)}:{type:"recent"}}function ot(e){switch(e.type){case"recent":return"#/chat";case"new":return"#/chat/new";case"session":return`#/chat/${encodeURIComponent(e.sessionKey)}`}}function bi(e,t,s){const i=yi[e],n=fi(e);return o`
|
|
1880
|
-
<button
|
|
1881
|
-
class="nav-item ${t?"nav-item--active":""}"
|
|
1882
|
-
@click=${s}
|
|
1883
|
-
role="tab"
|
|
1884
|
-
aria-selected=${t}
|
|
1885
|
-
>
|
|
1886
|
-
<span class="nav-item__icon">${d(i)}</span>
|
|
1887
|
-
<span class="nav-item__text">${n}</span>
|
|
1888
|
-
</button>
|
|
1889
|
-
`}const yt="xopcbot.token",wt="xopcbot.theme",bt="xopcbot.language";function z(){try{return localStorage.getItem(yt)||""}catch{return""}}function at(e){try{localStorage.setItem(yt,e)}catch(t){console.error("Failed to save token:",t)}}function $i(){try{const e=localStorage.getItem(wt);return e==="light"||e==="dark"||e==="system"?e:"system"}catch{return"system"}}function ki(e){try{localStorage.setItem(wt,e)}catch(t){console.error("Failed to save theme:",t)}}function xi(){try{const e=localStorage.getItem(bt);return e==="en"||e==="zh"?e:"en"}catch{return"en"}}function Si(e){try{localStorage.setItem(bt,e)}catch(t){console.error("Failed to save language:",t)}}var Ai=Object.defineProperty,Ci=Object.getOwnPropertyDescriptor,O=(e,t,s,i)=>{for(var n=i>1?void 0:i?Ci(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Ai(t,s,n),n};let L=class extends y{constructor(){super(),this._gatewayConfig={url:window.location.origin,token:z()||void 0},this._activeTab="chat",this._navCollapsed=!1,this._navMobileOpen=!1,this._theme="system",this._language="en",this._chatRoute={type:"recent"},this._showTokenDialog=!1}get gatewayConfig(){return this._gatewayConfig}set gatewayConfig(e){this._gatewayConfig=e||{url:window.location.origin}}_initializeToken(){const t=new URLSearchParams(window.location.search).get("token");if(t){at(t);const i=window.location.pathname+window.location.hash;window.history.replaceState({},"",i)}const s=z();this._gatewayConfig={url:window.location.origin,token:s||void 0},this._showTokenDialog=!s}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this._initializeToken(),this._loadTheme(),this._loadLanguage(),this._loadRouteFromHash(),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",()=>{this._theme==="system"&&this._applyTheme()}),window.addEventListener("languagechange",()=>{this.requestUpdate()}),window.addEventListener("hashchange",()=>{this._loadRouteFromHash()})}_loadRouteFromHash(){const e=location.hash.slice(1);if(e.startsWith("chat")){const i=wi(e);i&&(this._activeTab!=="chat"&&(this._activeTab="chat"),JSON.stringify(this._chatRoute)!==JSON.stringify(i)&&(this._chatRoute=i));return}const t=e;["sessions","cron","logs","settings"].includes(t)&&this._activeTab!==t&&(this._activeTab=t)}_switchTab(e){this._activeTab=e;let t;e==="chat"?t=ot(this._chatRoute):t=`#${e}`,location.hash!==t&&history.pushState(null,"",t),this._navMobileOpen=!1}_updateChatRoute(e){this._chatRoute=e;const t=ot(e);history.pushState(null,"",t)}_loadTheme(){this._theme=$i(),this._applyTheme()}_loadLanguage(){this._language=xi(),nt(this._language)}_applyTheme(){const e=document.documentElement;e.classList.remove("light","dark");let t=!1;this._theme==="dark"?t=!0:this._theme==="system"&&(t=window.matchMedia("(prefers-color-scheme: dark)").matches),t?e.classList.add("dark"):e.classList.add("light"),window.dispatchEvent(new CustomEvent("themechange",{detail:{theme:t?"dark":"light"}}))}_setTheme(e){this._theme=e,ki(e),this._applyTheme()}_setLanguage(e){this._language=e,nt(e),Si(e),this.requestUpdate()}_renderThemeToggle(){return o`
|
|
1890
|
-
<div class="pill-toggle">
|
|
1891
|
-
<button
|
|
1892
|
-
class="pill-btn ${this._theme==="light"?"active":""}"
|
|
1893
|
-
@click=${()=>this._setTheme("light")}
|
|
1894
|
-
title="Light"
|
|
1895
|
-
>
|
|
1896
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
1897
|
-
<circle cx="12" cy="12" r="5"></circle>
|
|
1898
|
-
<line x1="12" y1="1" x2="12" y2="3"></line>
|
|
1899
|
-
<line x1="12" y1="21" x2="12" y2="23"></line>
|
|
1900
|
-
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
|
1901
|
-
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
|
1902
|
-
<line x1="1" y1="12" x2="3" y2="12"></line>
|
|
1903
|
-
<line x1="21" y1="12" x2="23" y2="12"></line>
|
|
1904
|
-
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
|
1905
|
-
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
|
1906
|
-
</svg>
|
|
1907
|
-
</button>
|
|
1908
|
-
<button
|
|
1909
|
-
class="pill-btn ${this._theme==="dark"?"active":""}"
|
|
1910
|
-
@click=${()=>this._setTheme("dark")}
|
|
1911
|
-
title="Dark"
|
|
1912
|
-
>
|
|
1913
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
1914
|
-
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
|
1915
|
-
</svg>
|
|
1916
|
-
</button>
|
|
1917
|
-
<button
|
|
1918
|
-
class="pill-btn ${this._theme==="system"?"active":""}"
|
|
1919
|
-
@click=${()=>this._setTheme("system")}
|
|
1920
|
-
title="System"
|
|
1921
|
-
>
|
|
1922
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
1923
|
-
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
|
|
1924
|
-
<line x1="8" y1="21" x2="16" y2="21"></line>
|
|
1925
|
-
<line x1="12" y1="17" x2="12" y2="21"></line>
|
|
1926
|
-
</svg>
|
|
1927
|
-
</button>
|
|
1928
|
-
</div>
|
|
1929
|
-
`}_renderLanguageToggle(){return o`
|
|
1930
|
-
<div class="pill-toggle">
|
|
1931
|
-
<button
|
|
1932
|
-
class="pill-btn ${this._language==="en"?"active":""}"
|
|
1933
|
-
@click=${()=>this._setLanguage("en")}
|
|
1934
|
-
title="English"
|
|
1935
|
-
>
|
|
1936
|
-
EN
|
|
1937
|
-
</button>
|
|
1938
|
-
<button
|
|
1939
|
-
class="pill-btn ${this._language==="zh"?"active":""}"
|
|
1940
|
-
@click=${()=>this._setLanguage("zh")}
|
|
1941
|
-
title="中文"
|
|
1942
|
-
>
|
|
1943
|
-
中
|
|
1944
|
-
</button>
|
|
1945
|
-
</div>
|
|
1946
|
-
`}_toggleNav(){window.innerWidth<768?this._navMobileOpen=!this._navMobileOpen:this._navCollapsed=!this._navCollapsed}_closeNavMobile(){this._navMobileOpen=!1}_handleTokenSave(e){at(e),this._gatewayConfig={url:window.location.origin,token:e},this._showTokenDialog=!1,this.requestUpdate()}render(){return this._showTokenDialog?o`
|
|
1947
|
-
<token-dialog
|
|
1948
|
-
.config=${{serverUrl:window.location.origin,onSave:e=>this._handleTokenSave(e)}}
|
|
1949
|
-
></token-dialog>
|
|
1950
|
-
`:o`
|
|
1951
|
-
<div class="shell ${this._activeTab==="chat"?"shell--chat":""} ${this._navCollapsed?"shell--nav-collapsed":""}">
|
|
1952
|
-
<!-- Topbar -->
|
|
1953
|
-
<header class="topbar">
|
|
1954
|
-
<div class="topbar-left">
|
|
1955
|
-
<button
|
|
1956
|
-
class="nav-collapse-toggle"
|
|
1957
|
-
@click=${this._toggleNav}
|
|
1958
|
-
title="${this._navCollapsed?"Expand sidebar":"Collapse sidebar"}"
|
|
1959
|
-
aria-label="${this._navCollapsed?"Expand sidebar":"Collapse sidebar"}"
|
|
1960
|
-
>
|
|
1961
|
-
<span class="nav-collapse-toggle__icon">${d("menu")}</span>
|
|
1962
|
-
</button>
|
|
1963
|
-
|
|
1964
|
-
<div class="brand">
|
|
1965
|
-
<div class="brand-logo">
|
|
1966
|
-
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1967
|
-
<rect width="24" height="24" rx="6" fill="url(#logo-gradient)"/>
|
|
1968
|
-
<path d="M8 12L11 15L16 9" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
1969
|
-
<defs>
|
|
1970
|
-
<linearGradient id="logo-gradient" x1="0" y1="0" x2="24" y2="24" gradientUnits="userSpaceOnUse">
|
|
1971
|
-
<stop stop-color="#3b82f6"/>
|
|
1972
|
-
<stop offset="1" stop-color="#8b5cf6"/>
|
|
1973
|
-
</linearGradient>
|
|
1974
|
-
</defs>
|
|
1975
|
-
</svg>
|
|
1976
|
-
</div>
|
|
1977
|
-
<div class="brand-text">
|
|
1978
|
-
<div class="brand-title">XOPCBOT</div>
|
|
1979
|
-
<div class="brand-sub">Gateway</div>
|
|
1980
|
-
</div>
|
|
1981
|
-
</div>
|
|
1982
|
-
</div>
|
|
1983
|
-
|
|
1984
|
-
<div class="topbar-status">
|
|
1985
|
-
${this._renderLanguageToggle()}
|
|
1986
|
-
${this._renderThemeToggle()}
|
|
1987
|
-
</div>
|
|
1988
|
-
</header>
|
|
1989
|
-
|
|
1990
|
-
<!-- Mobile Overlay Backdrop -->
|
|
1991
|
-
${this._navMobileOpen?o`
|
|
1992
|
-
<div class="nav-overlay" @click=${this._closeNavMobile}></div>
|
|
1993
|
-
`:_}
|
|
1994
|
-
|
|
1995
|
-
<div class="shell-main">
|
|
1996
|
-
<!-- Sidebar Navigation -->
|
|
1997
|
-
<aside class="nav ${this._navCollapsed?"nav--collapsed":""} ${this._navMobileOpen?"nav--mobile-open":""}">
|
|
1998
|
-
${vi().map(e=>(e.tabs.some(t=>t===this._activeTab),o`
|
|
1999
|
-
<div class="nav-group">
|
|
2000
|
-
<div class="nav-label nav-label--static">
|
|
2001
|
-
<span class="nav-label__text">${e.label}</span>
|
|
2002
|
-
</div>
|
|
2003
|
-
<div class="nav-group__items">
|
|
2004
|
-
${e.tabs.map(t=>bi(t,this._activeTab===t,()=>{this._switchTab(t)}))}
|
|
2005
|
-
</div>
|
|
2006
|
-
</div>
|
|
2007
|
-
`))}
|
|
2008
|
-
</aside>
|
|
2009
|
-
|
|
2010
|
-
<!-- Main Content -->
|
|
2011
|
-
<main class="content ${this._activeTab==="chat"?"content--chat":""}">
|
|
2012
|
-
${this._activeTab==="chat"?this._renderChat():_}
|
|
2013
|
-
${this._activeTab==="sessions"?this._renderSessions():_}
|
|
2014
|
-
${this._activeTab==="cron"?this._renderCron():_}
|
|
2015
|
-
${this._activeTab==="logs"?this._renderLogs():_}
|
|
2016
|
-
${this._activeTab==="settings"?this._renderSettings():_}
|
|
2017
|
-
</main>
|
|
2018
|
-
</div>
|
|
2019
|
-
</div>
|
|
2020
|
-
`}_renderChat(){const e=z();return o`
|
|
2021
|
-
<xopcbot-gateway-chat
|
|
2022
|
-
.config=${{url:window.location.origin,token:e||void 0}}
|
|
2023
|
-
.route=${this._chatRoute}
|
|
2024
|
-
.enableAttachments=${!0}
|
|
2025
|
-
.enableModelSelector=${!0}
|
|
2026
|
-
.enableThinkingSelector=${!0}
|
|
2027
|
-
@route-change=${t=>this._updateChatRoute(t.detail)}
|
|
2028
|
-
></xopcbot-gateway-chat>
|
|
2029
|
-
`}_renderSessions(){const e=z()||this._gatewayConfig?.token;return o`
|
|
2030
|
-
<session-manager
|
|
2031
|
-
.config=${{token:e}}
|
|
2032
|
-
></session-manager>
|
|
2033
|
-
`}_renderCron(){const e=z()||this._gatewayConfig?.token;return o`
|
|
2034
|
-
<cron-manager
|
|
2035
|
-
.config=${{token:e}}
|
|
2036
|
-
></cron-manager>
|
|
2037
|
-
`}_renderLogs(){const e=z()||this._gatewayConfig?.token;return o`
|
|
2038
|
-
<log-manager
|
|
2039
|
-
.config=${{token:e}}
|
|
2040
|
-
></log-manager>
|
|
2041
|
-
`}_renderSettings(){const e=z()||this._gatewayConfig?.token;return o`
|
|
2042
|
-
<settings-page
|
|
2043
|
-
.config=${{token:e}}
|
|
2044
|
-
></settings-page>
|
|
2045
|
-
`}showChat(){this._activeTab="chat"}get chatElement(){return this._chatElement}};O([c()],L.prototype,"_gatewayConfig",2);O([c()],L.prototype,"_activeTab",2);O([c()],L.prototype,"_navCollapsed",2);O([c()],L.prototype,"_navMobileOpen",2);O([c()],L.prototype,"_theme",2);O([c()],L.prototype,"_language",2);O([c()],L.prototype,"_chatRoute",2);O([c()],L.prototype,"_showTokenDialog",2);O([oe("xopcbot-gateway-chat")],L.prototype,"_chatElement",2);L=O([k("xopcbot-app")],L);var Ti=Object.defineProperty,Mi=Object.getOwnPropertyDescriptor,R=(e,t,s,i)=>{for(var n=i>1?void 0:i?Mi(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Ti(t,s,n),n};let D=class extends y{constructor(){super(...arguments),this.sections=[],this.values={},this.loading=!1,this._activeSection="",this._dirtyFields=new Set,this._showPasswords=new Set,this._errors=new Map}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this._updateActiveSection()}willUpdate(e){e.has("sections")&&this._updateActiveSection()}_updateActiveSection(){this.sections.length>0&&!this._activeSection&&(this._activeSection=this.sections[0].id)}_getIcon(e){return{user:o`<User class="w-5 h-5" />`,bot:o`<Bot class="w-5 h-5" />`,plug:o`<Plug class="w-5 h-5" />`,globe:o`<Globe class="w-5 h-5" />`,search:o`<Search class="w-5 h-5" />`,clock:o`<Clock class="w-5 h-5" />`,puzzle:o`<Puzzle class="w-5 h-5" />`,settings:o`<Settings class="w-5 h-5" />`}[e]||o`<Settings class="w-5 h-5" />`}render(){return o`
|
|
2046
|
-
<div class="settings-overlay" @click=${e=>e.target===e.currentTarget&&this.onClose?.()}>
|
|
2047
|
-
<div class="settings-dialog">
|
|
2048
|
-
${this.renderHeader()}
|
|
2049
|
-
<div class="settings-content">
|
|
2050
|
-
${this.renderSidebar()}
|
|
2051
|
-
${this.renderMain()}
|
|
2052
|
-
</div>
|
|
2053
|
-
${this.renderFooter()}
|
|
2054
|
-
</div>
|
|
2055
|
-
</div>
|
|
2056
|
-
`}renderHeader(){return o`
|
|
2057
|
-
<div class="settings-header">
|
|
2058
|
-
<div class="settings-title">
|
|
2059
|
-
<Settings class="w-5 h-5" />
|
|
2060
|
-
<span>Settings</span>
|
|
2061
|
-
</div>
|
|
2062
|
-
<button class="close-btn" @click=${()=>this.onClose?.()}>
|
|
2063
|
-
<X class="w-5 h-5" />
|
|
2064
|
-
</button>
|
|
2065
|
-
</div>
|
|
2066
|
-
`}renderSidebar(){return o`
|
|
2067
|
-
<nav class="settings-sidebar">
|
|
2068
|
-
${this.sections.map(e=>o`
|
|
2069
|
-
<button
|
|
2070
|
-
class="sidebar-item ${this._activeSection===e.id?"active":""}"
|
|
2071
|
-
@click=${()=>this._activeSection=e.id}
|
|
2072
|
-
>
|
|
2073
|
-
${this._getIcon(e.icon)}
|
|
2074
|
-
<span>${e.title}</span>
|
|
2075
|
-
<ChevronRight class="w-4 h-4 chevron" />
|
|
2076
|
-
</button>
|
|
2077
|
-
`)}
|
|
2078
|
-
</nav>
|
|
2079
|
-
`}renderMain(){const e=this.sections.find(s=>s.id===this._activeSection);if(!e)return o`<div class="settings-main">${r("settings.noSection")}</div>`;const t=`settings.descriptions.${e.id}`;return o`
|
|
2080
|
-
<div class="settings-main">
|
|
2081
|
-
<div class="section-header">
|
|
2082
|
-
<h2>${e.title}</h2>
|
|
2083
|
-
<p class="section-description">${r(t)}</p>
|
|
2084
|
-
</div>
|
|
2085
|
-
|
|
2086
|
-
<div class="fields-grid">
|
|
2087
|
-
${e.fields.map(s=>this.renderField(s,e.id))}
|
|
2088
|
-
</div>
|
|
2089
|
-
</div>
|
|
2090
|
-
`}renderField(e,t){const s=`${t}.${e.key}`,i=this._getValue(e.key),n=this._dirtyFields.has(s),a=this._errors.get(s),l=this._showPasswords.has(s);return o`
|
|
2091
|
-
<div class="field-group ${a?"has-error":""}">
|
|
2092
|
-
<div class="field-header">
|
|
2093
|
-
<label class="field-label">${e.label}</label>
|
|
2094
|
-
${e.validation?.required?o`<span class="required-mark">*</span>`:""}
|
|
2095
|
-
</div>
|
|
2096
|
-
|
|
2097
|
-
${e.description?o`<p class="field-description">${e.description}</p>`:""}
|
|
2098
|
-
|
|
2099
|
-
${e.type==="boolean"?this.renderBooleanField(e,i,s):""}
|
|
2100
|
-
|
|
2101
|
-
${e.type==="select"?this.renderSelectField(e,i,s):""}
|
|
2102
|
-
|
|
2103
|
-
${e.type==="textarea"?this.renderTextareaField(e,i,s):""}
|
|
2104
|
-
|
|
2105
|
-
${["text","password","number"].includes(e.type)?this.renderInputField(e,i,s,l):""}
|
|
2106
|
-
|
|
2107
|
-
${a?o`
|
|
2108
|
-
<div class="field-error">
|
|
2109
|
-
<AlertCircle class="w-4 h-4" />
|
|
2110
|
-
<span>${a}</span>
|
|
2111
|
-
</div>
|
|
2112
|
-
`:""}
|
|
2113
|
-
|
|
2114
|
-
${n&&!a?o`
|
|
2115
|
-
<div class="field-dirty">${r("settings.unsavedChanges")}</div>
|
|
2116
|
-
`:""}
|
|
2117
|
-
</div>
|
|
2118
|
-
`}renderInputField(e,t,s,i){const n=e.type==="password"?i?"text":"password":e.type;return o`
|
|
2119
|
-
<div class="input-wrapper">
|
|
2120
|
-
<input
|
|
2121
|
-
type=${n}
|
|
2122
|
-
class="text-input ${e.type==="password"?"has-toggle":""}"
|
|
2123
|
-
.value=${String(t??"")}
|
|
2124
|
-
placeholder=${e.placeholder||""}
|
|
2125
|
-
minlength=${e.validation?.min}
|
|
2126
|
-
maxlength=${e.validation?.max}
|
|
2127
|
-
pattern=${e.validation?.pattern||""}
|
|
2128
|
-
@input=${a=>this._handleInput(e,s,a.target.value)}
|
|
2129
|
-
/>
|
|
2130
|
-
${e.type==="password"?o`
|
|
2131
|
-
<button
|
|
2132
|
-
type="button"
|
|
2133
|
-
class="password-toggle"
|
|
2134
|
-
@click=${()=>this._togglePassword(s)}
|
|
2135
|
-
>
|
|
2136
|
-
${i?o`<EyeOff class="w-4 h-4" />`:o`<Eye class="w-4 h-4" />`}
|
|
2137
|
-
</button>
|
|
2138
|
-
`:""}
|
|
2139
|
-
</div>
|
|
2140
|
-
`}renderTextareaField(e,t,s){return o`
|
|
2141
|
-
<textarea
|
|
2142
|
-
class="textarea-input"
|
|
2143
|
-
.value=${String(t??"")}
|
|
2144
|
-
placeholder=${e.placeholder||""}
|
|
2145
|
-
rows="4"
|
|
2146
|
-
@input=${i=>this._handleInput(e,s,i.target.value)}
|
|
2147
|
-
></textarea>
|
|
2148
|
-
`}renderSelectField(e,t,s){return o`
|
|
2149
|
-
<select
|
|
2150
|
-
class="select-input"
|
|
2151
|
-
.value=${String(t??"")}
|
|
2152
|
-
@change=${i=>this._handleInput(e,s,i.target.value)}
|
|
2153
|
-
>
|
|
2154
|
-
${e.options?.map(i=>o`
|
|
2155
|
-
<option value=${i.value} ?selected=${t===i.value}>${i.label}</option>
|
|
2156
|
-
`)}
|
|
2157
|
-
</select>
|
|
2158
|
-
`}renderBooleanField(e,t,s){return o`
|
|
2159
|
-
<label class="toggle-label">
|
|
2160
|
-
<input
|
|
2161
|
-
type="checkbox"
|
|
2162
|
-
class="toggle-input"
|
|
2163
|
-
.checked=${!!t}
|
|
2164
|
-
@change=${i=>this._handleInput(e,s,i.target.checked)}
|
|
2165
|
-
/>
|
|
2166
|
-
<span class="toggle-switch"></span>
|
|
2167
|
-
<span class="toggle-text">${e.description||r("settings.enableFeature")}</span>
|
|
2168
|
-
</label>
|
|
2169
|
-
`}renderFooter(){const e=this._dirtyFields.size>0;return o`
|
|
2170
|
-
<div class="settings-footer">
|
|
2171
|
-
<button class="btn btn-ghost" @click=${()=>this.onClose?.()}>
|
|
2172
|
-
${r("settings.cancel")}
|
|
2173
|
-
</button>
|
|
2174
|
-
<button
|
|
2175
|
-
class="btn btn-primary"
|
|
2176
|
-
?disabled=${this.loading||!e}
|
|
2177
|
-
@click=${()=>this._save()}
|
|
2178
|
-
>
|
|
2179
|
-
${this.loading?o`
|
|
2180
|
-
<Loader2 class="w-4 h-4 animate-spin" />
|
|
2181
|
-
${r("settings.saving")}
|
|
2182
|
-
`:o`
|
|
2183
|
-
<Save class="w-4 h-4" />
|
|
2184
|
-
${r("settings.saveChanges")}
|
|
2185
|
-
`}
|
|
2186
|
-
</button>
|
|
2187
|
-
</div>
|
|
2188
|
-
`}_getValue(e){return this.values[e]}_handleInput(e,t,s){e.validation?.required&&!s?this._errors.set(t,r("settings.required",{field:e.label})):e.validation?.pattern&&s?new RegExp(e.validation.pattern).test(s)?this._errors.delete(t):this._errors.set(t,r("settings.invalidFormat")):this._errors.delete(t),this._dirtyFields.add(t),this.requestUpdate()}_togglePassword(e){this._showPasswords.has(e)?this._showPasswords.delete(e):this._showPasswords.add(e),this.requestUpdate()}_save(){this._errors.size>0||this.onSave&&this.onSave(this.values)}};R([u({attribute:!1})],D.prototype,"sections",2);R([u({attribute:!1})],D.prototype,"values",2);R([u({type:Boolean})],D.prototype,"loading",2);R([u({attribute:!1})],D.prototype,"onSave",2);R([u({attribute:!1})],D.prototype,"onClose",2);R([c()],D.prototype,"_activeSection",2);R([c()],D.prototype,"_dirtyFields",2);R([c()],D.prototype,"_showPasswords",2);R([c()],D.prototype,"_errors",2);D=R([k("xopcbot-settings")],D);var Ei=Object.defineProperty,Pi=Object.getOwnPropertyDescriptor,ee=(e,t,s,i)=>{for(var n=i>1?void 0:i?Pi(t,s):t,a=e.length-1,l;a>=0;a--)(l=e[a])&&(n=(i?l(t,s,n):l(n))||n);return i&&n&&Ei(t,s,n),n};let H=class extends y{constructor(){super(...arguments),this.enableAttachments=!0,this.enableModelSelector=!0,this.enableThinkingSelector=!0,this._autoScroll=!0,this._lastScrollTop=0,this._handleScroll=()=>{if(!this._scrollContainer)return;const e=this._scrollContainer.scrollTop,t=this._scrollContainer.scrollHeight,s=this._scrollContainer.clientHeight,i=t-e-s;if(s<this._lastClientHeight){this._lastClientHeight=s;return}e!==0&&e<this._lastScrollTop&&i>50?this._autoScroll=!1:i<10&&(this._autoScroll=!0),this._lastScrollTop=e,this._lastClientHeight=s}}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.style.display="flex",this.style.flexDirection="column",this.style.height="100%",this.style.minHeight="0",this.setupSessionSubscription()}disconnectedCallback(){super.disconnectedCallback(),this._resizeObserver?.disconnect(),this._scrollContainer?.removeEventListener("scroll",this._handleScroll),this._unsubscribeSession?.()}setupSessionSubscription(){this._unsubscribeSession&&this._unsubscribeSession(),this.agent&&(this._unsubscribeSession=this.agent.subscribe(async e=>{switch(e.type){case"message_start":case"message_end":case"turn_start":case"turn_end":case"agent_start":this.requestUpdate();break;case"agent_end":this._streamingContainer&&(this._streamingContainer.isStreaming=!1,this._streamingContainer.setMessage(null,!0)),this.requestUpdate();break;case"message_update":this._streamingContainer&&(this._streamingContainer.isStreaming=this.agent?.state.isStreaming||!1,this._streamingContainer.setMessage(e.message,!this._streamingContainer.isStreaming)),this.requestUpdate();break}}))}setInput(e,t){this._messageEditor&&(this._messageEditor.value=e,this._messageEditor.attachments=t||[])}setAutoScroll(e){this._autoScroll=e}async sendMessage(e,t){if(!(!e.trim()&&t?.length===0||this.agent?.state.isStreaming)){if(!this.agent)throw new Error("No agent set");if(!this.agent.state.model)throw new Error("No model set");this._messageEditor.value="",this._messageEditor.attachments=[],this._autoScroll=!0,t&&t.length>0?await this.agent.prompt({role:"user-with-attachments",content:e,attachments:t,timestamp:Date.now()}):await this.agent.prompt(e)}}renderMessages(){if(!this.agent)return o`<div class="p-4 text-center text-muted-foreground">${ie("No session available")}</div>`;const e=this.agent.state;return o`
|
|
2189
|
-
<div class="flex flex-col gap-3">
|
|
2190
|
-
<message-list
|
|
2191
|
-
.messages=${this.agent.state.messages}
|
|
2192
|
-
.tools=${e.tools}
|
|
2193
|
-
.pendingToolCalls=${this.agent?this.agent.state.pendingToolCalls:new Set}
|
|
2194
|
-
.isStreaming=${e.isStreaming}
|
|
2195
|
-
></message-list>
|
|
2196
|
-
|
|
2197
|
-
<streaming-message-container
|
|
2198
|
-
class="${e.isStreaming?"":"hidden"}"
|
|
2199
|
-
.tools=${e.tools}
|
|
2200
|
-
.isStreaming=${e.isStreaming}
|
|
2201
|
-
.pendingToolCalls=${e.pendingToolCalls}
|
|
2202
|
-
.isStreaming=${e.isStreaming}
|
|
2203
|
-
></streaming-message-container>
|
|
2204
|
-
</div>
|
|
2205
|
-
`}render(){if(!this.agent)return o`<div class="p-4 text-center text-muted-foreground">${ie("No agent set")}</div>`;const e=this.agent.state;return o`
|
|
2206
|
-
<div class="flex flex-col h-full bg-background text-foreground">
|
|
2207
|
-
<div class="flex-1 overflow-y-auto">
|
|
2208
|
-
<div class="max-w-3xl mx-auto p-4 pb-0">${this.renderMessages()}</div>
|
|
2209
|
-
</div>
|
|
2210
|
-
|
|
2211
|
-
<div class="shrink-0">
|
|
2212
|
-
<div class="max-w-3xl mx-auto px-2">
|
|
2213
|
-
<message-editor
|
|
2214
|
-
.isStreaming=${e.isStreaming}
|
|
2215
|
-
.currentModel=${e.model}
|
|
2216
|
-
.thinkingLevel=${e.thinkingLevel}
|
|
2217
|
-
.showAttachmentButton=${this.enableAttachments}
|
|
2218
|
-
.showModelSelector=${this.enableModelSelector}
|
|
2219
|
-
.showThinkingSelector=${this.enableThinkingSelector}
|
|
2220
|
-
.onSend=${(t,s)=>this.sendMessage(t,s)}
|
|
2221
|
-
.onAbort=${()=>this.agent?.abort()}
|
|
2222
|
-
></message-editor>
|
|
2223
|
-
</div>
|
|
2224
|
-
</div>
|
|
2225
|
-
</div>
|
|
2226
|
-
`}};ee([u({attribute:!1})],H.prototype,"agent",2);ee([u({type:Boolean})],H.prototype,"enableAttachments",2);ee([u({type:Boolean})],H.prototype,"enableModelSelector",2);ee([u({type:Boolean})],H.prototype,"enableThinkingSelector",2);ee([oe("message-editor")],H.prototype,"_messageEditor",2);ee([oe("streaming-message-container")],H.prototype,"_streamingContainer",2);H=ee([k("xopcbot-chat")],H);
|
|
2227
|
-
//# sourceMappingURL=main-DevbZW9K.js.map
|