nextclaw 0.9.27 → 0.10.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.
Files changed (45) hide show
  1. package/dist/cli/index.js +70 -11
  2. package/package.json +5 -5
  3. package/ui-dist/assets/ChannelsList-DF2U-LY1.js +1 -0
  4. package/ui-dist/assets/ChatPage-BX39y0U5.js +36 -0
  5. package/ui-dist/assets/DocBrowser-B9ws5JL7.js +1 -0
  6. package/ui-dist/assets/{LogoBadge-Cer0jX6t.js → LogoBadge-DvGAzkZ3.js} +1 -1
  7. package/ui-dist/assets/MarketplacePage-DG5mHWJ8.js +49 -0
  8. package/ui-dist/assets/ModelConfig-BL_HsOsm.js +1 -0
  9. package/ui-dist/assets/ProvidersList-CH5z00YT.js +1 -0
  10. package/ui-dist/assets/RuntimeConfig-BplBgkwo.js +1 -0
  11. package/ui-dist/assets/SearchConfig-BhaI0fUf.js +1 -0
  12. package/ui-dist/assets/{SecretsConfig-BnGVZiv4.js → SecretsConfig-CFoimOh9.js} +2 -2
  13. package/ui-dist/assets/SessionsConfig-BHTAYn9T.js +2 -0
  14. package/ui-dist/assets/index-BLeJkJ0o.css +1 -0
  15. package/ui-dist/assets/index-DK4TS5ev.js +8 -0
  16. package/ui-dist/assets/index-X5J6Mm--.js +1 -0
  17. package/ui-dist/assets/{index-CkqvHQAt.js → index-uMsNsQX6.js} +1 -1
  18. package/ui-dist/assets/{label-DkL14Jvl.js → label-D8ly4a2P.js} +1 -1
  19. package/ui-dist/assets/page-layout-BSYfvwbp.js +1 -0
  20. package/ui-dist/assets/security-config-DlKEYHNN.js +1 -0
  21. package/ui-dist/assets/{session-run-status-tZ4ISNj-.js → session-run-status-TkIuGbVw.js} +1 -1
  22. package/ui-dist/assets/skeleton-CWbsNx2h.js +1 -0
  23. package/ui-dist/assets/{switch-CgbPbIX3.js → switch-Ce_g9lpN.js} +1 -1
  24. package/ui-dist/assets/tabs-custom-Cf5azvT5.js +1 -0
  25. package/ui-dist/assets/useConfirmDialog-A8Ek8Wu7.js +5 -0
  26. package/ui-dist/assets/vendor-B7ozqnFC.js +412 -0
  27. package/ui-dist/index.html +3 -3
  28. package/ui-dist/assets/ChannelsList-DzeVn-JC.js +0 -1
  29. package/ui-dist/assets/ChatPage-BiFhIm1-.js +0 -36
  30. package/ui-dist/assets/DocBrowser-By3lF9yN.js +0 -1
  31. package/ui-dist/assets/MarketplacePage-EZxALdIz.js +0 -49
  32. package/ui-dist/assets/ModelConfig-AchYxLft.js +0 -1
  33. package/ui-dist/assets/ProvidersList-BsD-4kKX.js +0 -1
  34. package/ui-dist/assets/RuntimeConfig-sKOERbFD.js +0 -1
  35. package/ui-dist/assets/SearchConfig-DAfvDwX6.js +0 -1
  36. package/ui-dist/assets/SessionsConfig-CzvrKDRs.js +0 -2
  37. package/ui-dist/assets/card-BAM7vbMg.js +0 -1
  38. package/ui-dist/assets/index-D9rRqOi8.css +0 -1
  39. package/ui-dist/assets/index-DJZ5y7t1.js +0 -8
  40. package/ui-dist/assets/input-BoelTiYL.js +0 -1
  41. package/ui-dist/assets/page-layout-CERNdqzB.js +0 -1
  42. package/ui-dist/assets/popover-uwYz3Chm.js +0 -1
  43. package/ui-dist/assets/tabs-custom-pDyl95el.js +0 -1
  44. package/ui-dist/assets/useConfirmDialog-DyP6Ac75.js +0 -5
  45. package/ui-dist/assets/vendor-BKtTvQYU.js +0 -407
package/dist/cli/index.js CHANGED
@@ -199,20 +199,20 @@ async function installMarketplaceSkill(options) {
199
199
  const dirName = options.dir?.trim() || "skills";
200
200
  const destinationDir = isAbsolute(dirName) ? resolve2(dirName, slug) : resolve2(workdir, dirName, slug);
201
201
  const skillFile = join(destinationDir, "SKILL.md");
202
- if (!options.force && existsSync2(destinationDir)) {
203
- if (existsSync2(skillFile)) {
204
- return {
205
- slug,
206
- destinationDir,
207
- alreadyInstalled: true,
208
- source: "marketplace"
209
- };
210
- }
211
- throw new Error(`Skill directory already exists: ${destinationDir} (use --force)`);
212
- }
213
202
  const apiBase = resolveMarketplaceApiBase(options.apiBaseUrl);
214
203
  const item = await fetchMarketplaceSkillItem(apiBase, slug);
215
204
  if (item.install.kind === "builtin") {
205
+ if (!options.force && existsSync2(destinationDir)) {
206
+ if (existsSync2(skillFile)) {
207
+ return {
208
+ slug,
209
+ destinationDir,
210
+ alreadyInstalled: true,
211
+ source: "builtin"
212
+ };
213
+ }
214
+ throw new Error(`Skill directory already exists: ${destinationDir} (use --force)`);
215
+ }
216
216
  if (existsSync2(destinationDir) && options.force) {
217
217
  rmSync2(destinationDir, { recursive: true, force: true });
218
218
  }
@@ -224,6 +224,22 @@ async function installMarketplaceSkill(options) {
224
224
  };
225
225
  }
226
226
  const filesPayload = await fetchMarketplaceSkillFiles(apiBase, slug);
227
+ if (!options.force && existsSync2(destinationDir)) {
228
+ const existingDirState = inspectMarketplaceSkillDirectory(destinationDir, filesPayload.files);
229
+ if (existingDirState === "installed") {
230
+ return {
231
+ slug,
232
+ destinationDir,
233
+ alreadyInstalled: true,
234
+ source: "marketplace"
235
+ };
236
+ }
237
+ if (existingDirState === "recoverable") {
238
+ rmSync2(destinationDir, { recursive: true, force: true });
239
+ } else {
240
+ throw new Error(`Skill directory already exists: ${destinationDir} (use --force)`);
241
+ }
242
+ }
227
243
  if (existsSync2(destinationDir) && options.force) {
228
244
  rmSync2(destinationDir, { recursive: true, force: true });
229
245
  }
@@ -247,6 +263,49 @@ async function installMarketplaceSkill(options) {
247
263
  source: "marketplace"
248
264
  };
249
265
  }
266
+ function inspectMarketplaceSkillDirectory(destinationDir, files) {
267
+ if (existsSync2(join(destinationDir, "SKILL.md"))) {
268
+ return "installed";
269
+ }
270
+ const discoveredFiles = collectRelativeFiles(destinationDir);
271
+ if (discoveredFiles === null) {
272
+ return "conflict";
273
+ }
274
+ const relevantFiles = discoveredFiles.filter((file) => !isIgnorableMarketplaceResidue(file));
275
+ if (relevantFiles.length === 0) {
276
+ return "recoverable";
277
+ }
278
+ const manifestPaths = new Set(files.map((file) => normalizeMarketplaceRelativePath(file.path)));
279
+ return relevantFiles.every((file) => manifestPaths.has(normalizeMarketplaceRelativePath(file))) ? "recoverable" : "conflict";
280
+ }
281
+ function collectRelativeFiles(rootDir) {
282
+ const output = [];
283
+ const walk = (dir) => {
284
+ const entries = readdirSync(dir, { withFileTypes: true });
285
+ for (const entry of entries) {
286
+ const absolute = join(dir, entry.name);
287
+ if (entry.isDirectory()) {
288
+ if (!walk(absolute)) {
289
+ return false;
290
+ }
291
+ continue;
292
+ }
293
+ if (!entry.isFile()) {
294
+ return false;
295
+ }
296
+ const relativePath = relative(rootDir, absolute);
297
+ output.push(normalizeMarketplaceRelativePath(relativePath));
298
+ }
299
+ return true;
300
+ };
301
+ return walk(rootDir) ? output : null;
302
+ }
303
+ function normalizeMarketplaceRelativePath(path) {
304
+ return path.replace(/\\/g, "/");
305
+ }
306
+ function isIgnorableMarketplaceResidue(path) {
307
+ return path === ".DS_Store";
308
+ }
250
309
  async function publishMarketplaceSkill(options) {
251
310
  const skillDir = resolve2(options.skillDir);
252
311
  if (!existsSync2(skillDir)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextclaw",
3
- "version": "0.9.27",
3
+ "version": "0.10.0",
4
4
  "description": "Lightweight personal AI assistant with CLI, multi-provider routing, and channel integrations.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -38,10 +38,10 @@
38
38
  "dependencies": {
39
39
  "chokidar": "^3.6.0",
40
40
  "commander": "^12.1.0",
41
- "@nextclaw/core": "0.7.7",
42
- "@nextclaw/server": "0.6.13",
43
- "@nextclaw/runtime": "0.1.6",
44
- "@nextclaw/openclaw-compat": "0.2.6"
41
+ "@nextclaw/core": "0.8.0",
42
+ "@nextclaw/runtime": "0.1.7",
43
+ "@nextclaw/server": "0.7.0",
44
+ "@nextclaw/openclaw-compat": "0.2.7"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/node": "^20.17.6",
@@ -0,0 +1 @@
1
+ import{r as v,j as a,a5 as Z,F as ee,e as T,K as ae,ai as te,aS as se,aT as ne,aU as le,z as re,s as oe,a9 as ce,v as ie}from"./vendor-B7ozqnFC.js";import{t as e,c as I,U as me,u as q,a as $,b as H,W as pe,X as de,I as D,S as be,e as ue,f as xe,g as ye,h as ge,B as E}from"./index-DK4TS5ev.js";import{L as he}from"./label-D8ly4a2P.js";import{S as fe}from"./switch-Ce_g9lpN.js";import{L as K,S as J}from"./LogoBadge-DvGAzkZ3.js";import{h as U}from"./config-hints-CApS3K_7.js";import{c as we,b as ve,a as je,C as ke}from"./config-layout-BHnOoweL.js";import{T as Se}from"./tabs-custom-Cf5azvT5.js";import{P as Ce,a as Ne}from"./page-layout-BSYfvwbp.js";function Pe({value:t,onChange:m,className:i,placeholder:r=""}){const[o,u]=v.useState(""),d=x=>{x.key==="Enter"&&o.trim()?(x.preventDefault(),m([...t,o.trim()]),u("")):x.key==="Backspace"&&!o&&t.length>0&&m(t.slice(0,-1))},g=x=>{m(t.filter((j,h)=>h!==x))};return a.jsxs("div",{className:I("flex flex-wrap gap-2 p-2 border rounded-md min-h-[42px]",i),children:[t.map((x,j)=>a.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-1 bg-primary text-primary-foreground rounded text-sm",children:[x,a.jsx("button",{type:"button",onClick:()=>g(j),className:"hover:text-red-300 transition-colors",children:a.jsx(Z,{className:"h-3 w-3"})})]},j)),a.jsx("input",{type:"text",value:o,onChange:x=>u(x.target.value),onKeyDown:d,className:"flex-1 outline-none min-w-[100px] bg-transparent text-sm",placeholder:r||e("enterTag")})]})}function z(t){var r,o;const m=me();return((r=t.tutorialUrls)==null?void 0:r[m])||((o=t.tutorialUrls)==null?void 0:o.default)||t.tutorialUrl}const Ie={telegram:"telegram.svg",slack:"slack.svg",discord:"discord.svg",whatsapp:"whatsapp.svg",qq:"qq.svg",feishu:"feishu.svg",dingtalk:"dingtalk.svg",wecom:"wecom.svg",mochat:"mochat.svg",email:"email.svg"};function Fe(t,m){const i=m.toLowerCase(),r=t[i];return r?`/logos/${r}`:null}function Y(t){return Fe(Ie,t)}const B=[{value:"pairing",label:"pairing"},{value:"allowlist",label:"allowlist"},{value:"open",label:"open"},{value:"disabled",label:"disabled"}],R=[{value:"open",label:"open"},{value:"allowlist",label:"allowlist"},{value:"disabled",label:"disabled"}],Te=[{value:"off",label:"off"},{value:"partial",label:"partial"},{value:"block",label:"block"},{value:"progress",label:"progress"}],De=t=>t.includes("token")||t.includes("secret")||t.includes("password")?a.jsx(ae,{className:"h-3.5 w-3.5 text-gray-500"}):t.includes("url")||t.includes("host")?a.jsx(te,{className:"h-3.5 w-3.5 text-gray-500"}):t.includes("email")||t.includes("mail")?a.jsx(se,{className:"h-3.5 w-3.5 text-gray-500"}):t.includes("id")||t.includes("from")?a.jsx(ne,{className:"h-3.5 w-3.5 text-gray-500"}):t==="enabled"||t==="consentGranted"?a.jsx(le,{className:"h-3.5 w-3.5 text-gray-500"}):a.jsx(re,{className:"h-3.5 w-3.5 text-gray-500"});function G(){return{telegram:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"token",type:"password",label:e("botToken")},{name:"allowFrom",type:"tags",label:e("allowFrom")},{name:"proxy",type:"text",label:e("proxy")},{name:"accountId",type:"text",label:e("accountId")},{name:"dmPolicy",type:"select",label:e("dmPolicy"),options:B},{name:"groupPolicy",type:"select",label:e("groupPolicy"),options:R},{name:"groupAllowFrom",type:"tags",label:e("groupAllowFrom")},{name:"requireMention",type:"boolean",label:e("requireMention")},{name:"mentionPatterns",type:"tags",label:e("mentionPatterns")},{name:"groups",type:"json",label:e("groupRulesJson")}],discord:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"token",type:"password",label:e("botToken")},{name:"allowBots",type:"boolean",label:e("allowBotMessages")},{name:"allowFrom",type:"tags",label:e("allowFrom")},{name:"gatewayUrl",type:"text",label:e("gatewayUrl")},{name:"intents",type:"number",label:e("intents")},{name:"proxy",type:"text",label:e("proxy")},{name:"mediaMaxMb",type:"number",label:e("attachmentMaxSizeMb")},{name:"streaming",type:"select",label:e("streamingMode"),options:Te},{name:"draftChunk",type:"json",label:e("draftChunkingJson")},{name:"textChunkLimit",type:"number",label:e("textChunkLimit")},{name:"accountId",type:"text",label:e("accountId")},{name:"dmPolicy",type:"select",label:e("dmPolicy"),options:B},{name:"groupPolicy",type:"select",label:e("groupPolicy"),options:R},{name:"groupAllowFrom",type:"tags",label:e("groupAllowFrom")},{name:"requireMention",type:"boolean",label:e("requireMention")},{name:"mentionPatterns",type:"tags",label:e("mentionPatterns")},{name:"groups",type:"json",label:e("groupRulesJson")}],whatsapp:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"bridgeUrl",type:"text",label:e("bridgeUrl")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],feishu:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"appId",type:"text",label:e("appId")},{name:"appSecret",type:"password",label:e("appSecret")},{name:"encryptKey",type:"password",label:e("encryptKey")},{name:"verificationToken",type:"password",label:e("verificationToken")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],dingtalk:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"clientId",type:"text",label:e("clientId")},{name:"clientSecret",type:"password",label:e("clientSecret")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],wecom:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"corpId",type:"text",label:e("corpId")},{name:"agentId",type:"text",label:e("agentId")},{name:"secret",type:"password",label:e("secret")},{name:"token",type:"password",label:e("token")},{name:"callbackPort",type:"number",label:e("callbackPort")},{name:"callbackPath",type:"text",label:e("callbackPath")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],slack:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"mode",type:"text",label:e("mode")},{name:"webhookPath",type:"text",label:e("webhookPath")},{name:"allowBots",type:"boolean",label:e("allowBotMessages")},{name:"botToken",type:"password",label:e("botToken")},{name:"appToken",type:"password",label:e("appToken")}],email:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"consentGranted",type:"boolean",label:e("consentGranted")},{name:"imapHost",type:"text",label:e("imapHost")},{name:"imapPort",type:"number",label:e("imapPort")},{name:"imapUsername",type:"text",label:e("imapUsername")},{name:"imapPassword",type:"password",label:e("imapPassword")},{name:"fromAddress",type:"email",label:e("fromAddress")}],mochat:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"baseUrl",type:"text",label:e("baseUrl")},{name:"clawToken",type:"password",label:e("clawToken")},{name:"agentUserId",type:"text",label:e("agentUserId")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],qq:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"appId",type:"text",label:e("appId")},{name:"secret",type:"password",label:e("appSecret")},{name:"markdownSupport",type:"boolean",label:e("markdownSupport")},{name:"allowFrom",type:"tags",label:e("allowFrom")}]}}function A(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function V(t,m){const i={...t};for(const[r,o]of Object.entries(m)){const u=i[r];if(A(u)&&A(o)){i[r]=V(u,o);continue}i[r]=o}return i}function Ae(t,m){const i=t.split("."),r={};let o=r;for(let u=0;u<i.length-1;u+=1){const d=i[u];o[d]={},o=o[d]}return o[i[i.length-1]]=m,r}function Le({channelName:t}){var _,O;const{data:m}=q(),{data:i}=$(),{data:r}=H(),o=pe(),u=de(),[d,g]=v.useState({}),[x,j]=v.useState({}),[h,f]=v.useState(null),k=t?m==null?void 0:m.channels[t]:null,w=t?G()[t]??[]:[],c=r==null?void 0:r.uiHints,p=t?`channels.${t}`:null,S=((_=r==null?void 0:r.actions)==null?void 0:_.filter(s=>s.scope===p))??[],C=t&&(((O=U(`channels.${t}`,c))==null?void 0:O.label)??t),P=i==null?void 0:i.channels.find(s=>s.name===t),F=P?z(P):void 0;v.useEffect(()=>{if(k){g({...k});const s={};(t?G()[t]??[]:[]).filter(l=>l.type==="json").forEach(l=>{const y=k[l.name];s[l.name]=JSON.stringify(y??{},null,2)}),j(s)}else g({}),j({})},[k,t]);const N=(s,n)=>{g(l=>({...l,[s]:n}))},L=s=>{if(s.preventDefault(),!t)return;const n={...d};for(const l of w){if(l.type!=="password")continue;const y=n[l.name];(typeof y!="string"||y.length===0)&&delete n[l.name]}for(const l of w){if(l.type!=="json")continue;const y=x[l.name]??"";try{n[l.name]=y.trim()?JSON.parse(y):{}}catch{T.error(`${e("invalidJson")}: ${l.name}`);return}}o.mutate({channel:t,data:n})},W=s=>{if(!s||!t)return;const n=s.channels;if(!A(n))return;const l=n[t];A(l)&&g(y=>V(y,l))},X=async s=>{if(!(!t||!p)){f(s.id);try{let n={...d};s.saveBeforeRun&&(n={...n,...s.savePatch??{}},g(n),await o.mutateAsync({channel:t,data:n}));const l=await u.mutateAsync({actionId:s.id,data:{scope:p,draftConfig:Ae(p,n)}});W(l.patch),l.ok?T.success(l.message||e("success")):T.error(l.message||e("error"))}catch(n){const l=n instanceof Error?n.message:String(n);T.error(`${e("error")}: ${l}`)}finally{f(null)}}};if(!t||!P||!k)return a.jsx("div",{className:we,children:a.jsxs("div",{children:[a.jsx("h3",{className:"text-base font-semibold text-gray-900",children:e("channelsSelectTitle")}),a.jsx("p",{className:"mt-2 text-sm text-gray-500",children:e("channelsSelectDescription")})]})});const M=!!k.enabled;return a.jsxs("div",{className:ve,children:[a.jsx("div",{className:"border-b border-gray-100 px-6 py-5",children:a.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[a.jsxs("div",{className:"min-w-0",children:[a.jsxs("div",{className:"flex items-center gap-3",children:[a.jsx(K,{name:t,src:Y(t),className:I("h-9 w-9 rounded-lg border",M?"border-primary/30 bg-white":"border-gray-200/70 bg-white"),imgClassName:"h-5 w-5 object-contain",fallback:a.jsx("span",{className:"text-sm font-semibold uppercase text-gray-500",children:t[0]})}),a.jsx("h3",{className:"truncate text-lg font-semibold text-gray-900 capitalize",children:C})]}),a.jsx("p",{className:"mt-2 text-sm text-gray-500",children:e("channelsFormDescription")}),F&&a.jsxs("a",{href:F,className:"mt-2 inline-flex items-center gap-1.5 text-xs text-primary transition-colors hover:text-primary-hover",children:[a.jsx(ee,{className:"h-3.5 w-3.5"}),e("channelsGuideTitle")]})]}),a.jsx(J,{status:M?"active":"inactive",label:M?e("statusActive"):e("statusInactive")})]})}),a.jsxs("form",{onSubmit:L,className:"flex min-h-0 flex-1 flex-col",children:[a.jsx("div",{className:"min-h-0 flex-1 space-y-6 overflow-y-auto overscroll-contain px-6 py-5",children:w.map(s=>{const n=t?U(`channels.${t}.${s.name}`,c):void 0,l=(n==null?void 0:n.label)??s.label,y=n==null?void 0:n.placeholder;return a.jsxs("div",{className:"space-y-2.5",children:[a.jsxs(he,{htmlFor:s.name,className:"flex items-center gap-2 text-sm font-medium text-gray-900",children:[De(s.name),l]}),s.type==="boolean"&&a.jsxs("div",{className:"flex items-center justify-between rounded-xl bg-gray-50 p-3",children:[a.jsx("span",{className:"text-sm text-gray-500",children:d[s.name]?e("enabled"):e("disabled")}),a.jsx(fe,{id:s.name,checked:d[s.name]||!1,onCheckedChange:b=>N(s.name,b),className:"data-[state=checked]:bg-emerald-500"})]}),(s.type==="text"||s.type==="email")&&a.jsx(D,{id:s.name,type:s.type,value:d[s.name]||"",onChange:b=>N(s.name,b.target.value),placeholder:y,className:"rounded-xl"}),s.type==="password"&&a.jsx(D,{id:s.name,type:"password",value:d[s.name]||"",onChange:b=>N(s.name,b.target.value),placeholder:y??e("leaveBlankToKeepUnchanged"),className:"rounded-xl"}),s.type==="number"&&a.jsx(D,{id:s.name,type:"number",value:d[s.name]||0,onChange:b=>N(s.name,parseInt(b.target.value,10)||0),placeholder:y,className:"rounded-xl"}),s.type==="tags"&&a.jsx(Pe,{value:d[s.name]||[],onChange:b=>N(s.name,b)}),s.type==="select"&&a.jsxs(be,{value:d[s.name]||"",onValueChange:b=>N(s.name,b),children:[a.jsx(ue,{className:"rounded-xl",children:a.jsx(xe,{})}),a.jsx(ye,{children:(s.options??[]).map(b=>a.jsx(ge,{value:b.value,children:b.label},b.value))})]}),s.type==="json"&&a.jsx("textarea",{id:s.name,value:x[s.name]??"{}",onChange:b=>j(Q=>({...Q,[s.name]:b.target.value})),className:"min-h-[120px] w-full resize-none rounded-lg border border-gray-200 bg-white px-3 py-2 text-xs font-mono"})]},s.name)})}),a.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 border-t border-gray-100 px-6 py-4",children:[a.jsx("div",{className:"flex flex-wrap items-center gap-2",children:S.filter(s=>s.trigger==="manual").map(s=>a.jsx(E,{type:"button",onClick:()=>X(s),disabled:o.isPending||!!h,variant:"secondary",children:h===s.id?e("connecting"):s.title},s.id))}),a.jsx(E,{type:"submit",disabled:o.isPending||!!h,children:o.isPending?e("saving"):e("save")})]})]})]})}const Me={telegram:"channelDescTelegram",slack:"channelDescSlack",email:"channelDescEmail",webhook:"channelDescWebhook",discord:"channelDescDiscord",feishu:"channelDescFeishu"};function He(){const{data:t}=q(),{data:m}=$(),{data:i}=H(),[r,o]=v.useState("enabled"),[u,d]=v.useState(),[g,x]=v.useState(""),j=i==null?void 0:i.uiHints,h=m==null?void 0:m.channels,f=t==null?void 0:t.channels,k=[{id:"enabled",label:e("channelsTabEnabled"),count:(h??[]).filter(c=>{var p;return(p=f==null?void 0:f[c.name])==null?void 0:p.enabled}).length},{id:"all",label:e("channelsTabAll"),count:(h??[]).length}],w=v.useMemo(()=>{const c=g.trim().toLowerCase();return(h??[]).filter(p=>{var C;const S=((C=f==null?void 0:f[p.name])==null?void 0:C.enabled)||!1;return r==="enabled"?S:!0}).filter(p=>c?(p.displayName||p.name).toLowerCase().includes(c)||p.name.toLowerCase().includes(c):!0)},[r,f,h,g]);return v.useEffect(()=>{if(w.length===0){d(void 0);return}w.some(p=>p.name===u)||d(w[0].name)},[w,u]),!t||!m?a.jsx("div",{className:"p-8 text-gray-400",children:e("channelsLoading")}):a.jsxs(Ce,{className:"xl:flex xl:h-full xl:min-h-0 xl:flex-col xl:pb-0",children:[a.jsx(Ne,{title:e("channelsPageTitle"),description:e("channelsPageDescription")}),a.jsxs("div",{className:I(ke,"xl:min-h-0 xl:flex-1"),children:[a.jsxs("section",{className:je,children:[a.jsx("div",{className:"border-b border-gray-100 px-4 pt-4",children:a.jsx(Se,{tabs:k,activeTab:r,onChange:o,className:"mb-0"})}),a.jsx("div",{className:"border-b border-gray-100 px-4 py-3",children:a.jsxs("div",{className:"relative",children:[a.jsx(oe,{className:"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400"}),a.jsx(D,{value:g,onChange:c=>x(c.target.value),placeholder:e("channelsFilterPlaceholder"),className:"h-10 rounded-xl pl-9"})]})}),a.jsxs("div",{className:"min-h-0 flex-1 space-y-2 overflow-y-auto overscroll-contain p-3",children:[w.map(c=>{const p=t.channels[c.name],S=(p==null?void 0:p.enabled)||!1,C=U(`channels.${c.name}`,j),P=z(c),F=(C==null?void 0:C.help)||e(Me[c.name]||"channelDescriptionDefault"),N=u===c.name;return a.jsx("button",{type:"button",onClick:()=>d(c.name),className:I("w-full rounded-xl border p-2.5 text-left transition-all",N?"border-primary/30 bg-primary-50/40 shadow-sm":"border-gray-200/70 bg-white hover:border-gray-300 hover:bg-gray-50/70"),children:a.jsxs("div",{className:"flex items-start justify-between gap-3",children:[a.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[a.jsx(K,{name:c.name,src:Y(c.name),className:I("h-10 w-10 rounded-lg border",S?"border-primary/30 bg-white":"border-gray-200/70 bg-white"),imgClassName:"h-5 w-5 object-contain",fallback:a.jsx("span",{className:"text-sm font-semibold uppercase text-gray-500",children:c.name[0]})}),a.jsxs("div",{className:"min-w-0",children:[a.jsx("p",{className:"truncate text-sm font-semibold text-gray-900",children:c.displayName||c.name}),a.jsx("p",{className:"line-clamp-1 text-[11px] text-gray-500",children:F})]})]}),a.jsxs("div",{className:"flex items-center gap-2",children:[P&&a.jsx("a",{href:P,onClick:L=>L.stopPropagation(),className:"inline-flex h-7 w-7 items-center justify-center rounded-md text-gray-300 transition-colors hover:bg-gray-100/70 hover:text-gray-500",title:e("channelsGuideTitle"),children:a.jsx(ce,{className:"h-3.5 w-3.5"})}),a.jsx(J,{status:S?"active":"inactive",label:S?e("statusActive"):e("statusInactive"),className:"min-w-[56px] justify-center"})]})]})},c.name)}),w.length===0&&a.jsxs("div",{className:"flex h-full min-h-[220px] flex-col items-center justify-center rounded-xl border border-dashed border-gray-200 bg-gray-50/70 py-10 text-center",children:[a.jsx("div",{className:"mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-white",children:a.jsx(ie,{className:"h-5 w-5 text-gray-300"})}),a.jsx("p",{className:"text-sm font-medium text-gray-700",children:e("channelsNoMatch")})]})]})]}),a.jsx(Le,{channelName:u})]})]})}export{He as ChannelsList};